diff --git a/src/kernel/emulation/linux/CMakeLists.txt b/src/kernel/emulation/linux/CMakeLists.txt index 8bbb10148..53db0dec7 100644 --- a/src/kernel/emulation/linux/CMakeLists.txt +++ b/src/kernel/emulation/linux/CMakeLists.txt @@ -57,6 +57,11 @@ set(emulation_sources unistd/getgid.c unistd/getppid.c unistd/rename.c + unistd/getpgrp.c + unistd/getdtablesize.c + unistd/setpgid.c + unistd/setgroups.c + unistd/getgroups.c select/select.c select/poll.c process/vfork.c @@ -70,6 +75,7 @@ set(emulation_sources signal/sigaction.c signal/sigreturn.c signal/sigprocmask.c + signal/sig_restorer.S misc/ioctl.c misc/thread_selfid.c misc/sysctl.c @@ -115,7 +121,7 @@ set(emulation_sources time/utimes.c time/futimes.c ioctl/ioctl.c - # ioctl/termios.c + ioctl/termios.c ext/uname.c ext/epoll_create.c ext/epoll_create1.c diff --git a/src/kernel/emulation/linux/ioctl/ioctl.c b/src/kernel/emulation/linux/ioctl/ioctl.c index 73058e099..60cc8579f 100644 --- a/src/kernel/emulation/linux/ioctl/ioctl.c +++ b/src/kernel/emulation/linux/ioctl/ioctl.c @@ -33,7 +33,7 @@ static bool get_fd_path(int fd, char* buf, size_t len) char proc[32]; int ret; - sprintf(proc, "/proc/self/%d", fd); + sprintf(proc, "/proc/self/fd/%d", fd); ret = sys_readlink(proc, buf, len-1); if (ret <= 0) @@ -50,6 +50,13 @@ static int handle_filio(int fd, int cmd, void* arg, int* retval) case BSD_FIODTYPE: { char orig_path[256]; + int* iarg = (int*) arg; + + if (iarg == NULL) + { + *retval = -EFAULT; + return IOCTL_HANDLED; + } if (!get_fd_path(fd, orig_path, sizeof(orig_path))) { @@ -57,19 +64,20 @@ static int handle_filio(int fd, int cmd, void* arg, int* retval) return IOCTL_HANDLED; } + *retval = 0; if (strncmp(orig_path, "/dev/pts", 8) == 0 || strncmp(orig_path, "/dev/tty", 8) == 0) { - *retval = D_TTY; + *iarg = D_TTY; } else if (strncmp(orig_path, "/dev/st", 7) == 0 || strncmp(orig_path, "/dev/nst", 8) == 0) { - *retval = D_TAPE; + *iarg = D_TAPE; } else { - *retval = D_DISK; + *iarg = D_DISK; } return IOCTL_HANDLED; } diff --git a/src/kernel/emulation/linux/ioctl/ioctl.h b/src/kernel/emulation/linux/ioctl/ioctl.h index 420eaeba3..bf7748727 100644 --- a/src/kernel/emulation/linux/ioctl/ioctl.h +++ b/src/kernel/emulation/linux/ioctl/ioctl.h @@ -39,6 +39,36 @@ enum { #define BSD_FIOGETOWN BSD_IOR('f', 123, int) #define BSD_FIODTYPE BSD_IOR('f', 122, int) +#define LINUX_IOC_NONE 0U +#define LINUX_IOC_WRITE 1U +#define LINUX_IOC_READ 2U +#define LINUX_IOC_NRBITS 8 +#define LINUX_IOC_TYPEBITS 8 +#define LINUX_IOC_SIZEBITS 14 +#define LINUX_IOC_DIRBITS 2 + +#define LINUX_IOC_NRSHIFT 0 +#define LINUX_IOC_TYPESHIFT (LINUX_IOC_NRSHIFT+LINUX_IOC_NRBITS) +#define LINUX_IOC_SIZESHIFT (LINUX_IOC_TYPESHIFT+LINUX_IOC_TYPEBITS) +#define LINUX_IOC_DIRSHIFT (LINUX_IOC_SIZESHIFT+LINUX_IOC_SIZEBITS) + +#define LINUX_IOC(dir,type,nr,size) \ + (((dir) << LINUX_IOC_DIRSHIFT) | \ + ((type) << LINUX_IOC_TYPESHIFT) | \ + ((nr) << LINUX_IOC_NRSHIFT) | \ + ((size) << LINUX_IOC_SIZESHIFT)) + +#define LINUX_IOC_TYPECHECK(t) (sizeof(t)) + +/* used to create numbers */ +#define LINUX_IO(type,nr) LINUX_IOC(LINUX_IOC_NONE,(type),(nr),0) +#define LINUX_IOR(type,nr,size) LINUX_IOC(LINUX_IOC_READ,(type),(nr),(LINUX_IOC_TYPECHECK(size))) +#define LINUX_IOW(type,nr,size) LINUX_IOC(LINUX_IOC_WRITE,(type),(nr),(LINUX_IOC_TYPECHECK(size))) +#define LINUX_IOWR(type,nr,size) LINUX_IOC(LINUX_IOC_READ|LINUX_IOC_WRITE,(type),(nr),(LINUX_IOC_TYPECHECK(size))) +#define LINUX_IOR_BAD(type,nr,size) _IOC(LINUX_IOC_READ,(type),(nr),sizeof(size)) +#define LINUX_IOW_BAD(type,nr,size) _IOC(LINUX_IOC_WRITE,(type),(nr),sizeof(size)) +#define LINUX_IOWR_BAD(type,nr,size) _IOC(LINUX_IOC_READ|LINUX_IOC_WRITE,(type),(nr),sizeof(size)) + #endif diff --git a/src/kernel/emulation/linux/ioctl/termios.c b/src/kernel/emulation/linux/ioctl/termios.c index de1e11257..ccd219085 100644 --- a/src/kernel/emulation/linux/ioctl/termios.c +++ b/src/kernel/emulation/linux/ioctl/termios.c @@ -8,12 +8,22 @@ // http://osxr.org/glibc/source/sysdeps/unix/sysv/linux/speed.c?v=glibc-2.13 extern void *memset(void *s, int c, size_t n); +extern long sys_write(int fd, const void* buf, size_t n); + static void cc_linux_to_bsd(const unsigned char* l, unsigned char* b); static void cc_bsd_to_linux(const unsigned char* b, unsigned char* l); static void iflag_linux_to_bsd(unsigned int l, unsigned long* b); static void iflag_bsd_to_linux(unsigned long b, unsigned int* l); +static void oflag_linux_to_bsd(unsigned int l, unsigned long* b); +static void oflag_bsd_to_linux(unsigned long b, unsigned int* l); +static void cflag_linux_to_bsd(unsigned int l, unsigned long* b); +static void cflag_bsd_to_linux(unsigned long b, unsigned int* l); +static void lflag_linux_to_bsd(unsigned int l, unsigned long* b); +static void lflag_bsd_to_linux(unsigned long b, unsigned int* l); +static void speed_linux_to_bsd(unsigned int l, unsigned long* b); +static void speed_bsd_to_linux(unsigned long b, unsigned int* l); -int handle_termios(int fd, int cmd, void* arg, int* retval) +int handle_termios(int fd, unsigned int cmd, void* arg, int* retval) { switch (cmd) { @@ -24,10 +34,15 @@ int handle_termios(int fd, int cmd, void* arg, int* retval) *retval = __real_ioctl(fd, LINUX_TCGETS, &in); - // TODO: translate termios + // translate termios fields memset(out, 0, sizeof(*out)); cc_linux_to_bsd(in.c_cc, out->c_cc); iflag_linux_to_bsd(in.c_iflag, &out->c_iflag); + oflag_linux_to_bsd(in.c_oflag, &out->c_oflag); + cflag_linux_to_bsd(in.c_cflag, &out->c_cflag); + lflag_linux_to_bsd(in.c_lflag, &out->c_lflag); + speed_linux_to_bsd(in.c_ispeed, &out->c_ispeed); + speed_linux_to_bsd(in.c_ospeed, &out->c_ospeed); return IOCTL_HANDLED; } @@ -46,10 +61,15 @@ int handle_termios(int fd, int cmd, void* arg, int* retval) else op = LINUX_TCSETSF; - // TODO: translate termios + // translate termios fields memset(&out, 0, sizeof(out)); cc_bsd_to_linux(in->c_cc, out.c_cc); iflag_bsd_to_linux(in->c_iflag, &out.c_iflag); + oflag_bsd_to_linux(in->c_oflag, &out.c_oflag); + cflag_bsd_to_linux(in->c_cflag, &out.c_cflag); + lflag_bsd_to_linux(in->c_lflag, &out.c_lflag); + speed_bsd_to_linux(in->c_ispeed, &out.c_ispeed); + speed_bsd_to_linux(in->c_ospeed, &out.c_ospeed); *retval = __real_ioctl(fd, op, &out); @@ -65,49 +85,107 @@ int handle_termios(int fd, int cmd, void* arg, int* retval) *retval = __real_ioctl(fd, LINUX_TIOCSWINSZ, arg); return IOCTL_HANDLED; } + case BSD_TIOCSTOP: + { + *retval = __real_ioctl(fd, LINUX_TIOCSTOP, NULL); + return IOCTL_HANDLED; + } + case BSD_TIOCSTART: + { + *retval = __real_ioctl(fd, LINUX_TIOCSTART, NULL); + return IOCTL_HANDLED; + } + case BSD_TIOCIXON: + case BSD_TIOCIXOFF: + { + struct linux_termios tos; + unsigned char c; + + *retval = __real_ioctl(fd, LINUX_TCGETS, &tos); + if (*retval < 0) + return IOCTL_HANDLED; + + c = tos.c_cc[cmd == BSD_TIOCIXON ? LINUX_VSTART : LINUX_VSTOP]; + if (c != LINUX_POSIX_VDISABLE) + *retval = sys_write(fd, &c, 1); + else + *retval = 0; + + return IOCTL_HANDLED; + } + case BSD_TIOCSBRK: + case BSD_TIOCCBRK: + { + *retval = __real_ioctl(fd, + cmd == BSD_TIOCSBRK ? LINUX_TIOCSBRK : LINUX_TIOCCBRK, + NULL); + return IOCTL_HANDLED; + } + case BSD_TIOCGPGRP: + case BSD_TIOCSPGRP: + { + *retval = __real_ioctl(fd, + cmd == BSD_TIOCGPGRP ? LINUX_TIOCGPGRP : LINUX_TIOCSPGRP, + arg); + return IOCTL_HANDLED; + } default: return IOCTL_PASS; } } +inline static unsigned char c_l2b(unsigned char c) +{ + if (c == LINUX_POSIX_VDISABLE) + return BSD_POSIX_VDISABLE; + return c; +} + +inline static unsigned char c_b2l(unsigned char c) +{ + if (c == BSD_POSIX_VDISABLE) + return LINUX_POSIX_VDISABLE; + return c; +} + static void cc_linux_to_bsd(const unsigned char* l, unsigned char* b) { - b[BSD_VEOF] = l[LINUX_VEOF]; - b[BSD_VEOL] = l[LINUX_VEOL]; - b[BSD_VEOL2] = l[LINUX_VEOL2]; - b[BSD_VERASE] = l[LINUX_VERASE]; - b[BSD_VWERASE] = l[LINUX_VWERASE]; - b[BSD_VKILL] = l[LINUX_VKILL]; - b[BSD_VREPRINT] = l[LINUX_VREPRINT]; - b[BSD_VINTR] = l[LINUX_VINTR]; - b[BSD_VQUIT] = l[LINUX_VQUIT]; - b[BSD_VSUSP] = l[LINUX_VSUSP]; - b[BSD_VSTART] = l[LINUX_VSTART]; - b[BSD_VSTOP] = l[LINUX_VSTOP]; - b[BSD_VLNEXT] = l[LINUX_VLNEXT]; - b[BSD_VDISCARD] = l[LINUX_VDISCARD]; - b[BSD_VMIN] = l[LINUX_VMIN]; - b[BSD_VTIME] = l[LINUX_VTIME]; + b[BSD_VEOF] = c_l2b(l[LINUX_VEOF]); + b[BSD_VEOL] = c_l2b(l[LINUX_VEOL]); + b[BSD_VEOL2] = c_l2b(l[LINUX_VEOL2]); + b[BSD_VERASE] = c_l2b(l[LINUX_VERASE]); + b[BSD_VWERASE] = c_l2b(l[LINUX_VWERASE]); + b[BSD_VKILL] = c_l2b(l[LINUX_VKILL]); + b[BSD_VREPRINT] = c_l2b(l[LINUX_VREPRINT]); + b[BSD_VINTR] = c_l2b(l[LINUX_VINTR]); + b[BSD_VQUIT] = c_l2b(l[LINUX_VQUIT]); + b[BSD_VSUSP] = c_l2b(l[LINUX_VSUSP]); + b[BSD_VSTART] = c_l2b(l[LINUX_VSTART]); + b[BSD_VSTOP] = c_l2b(l[LINUX_VSTOP]); + b[BSD_VLNEXT] = c_l2b(l[LINUX_VLNEXT]); + b[BSD_VDISCARD] = c_l2b(l[LINUX_VDISCARD]); + b[BSD_VMIN] = c_l2b(l[LINUX_VMIN]); + b[BSD_VTIME] = c_l2b(l[LINUX_VTIME]); } static void cc_bsd_to_linux(const unsigned char* b, unsigned char* l) { - l[LINUX_VEOF] = b[BSD_VEOF]; - l[LINUX_VEOL] = b[BSD_VEOL]; - l[LINUX_VEOL2] = b[BSD_VEOL2]; - l[LINUX_VERASE] = b[BSD_VERASE]; - l[LINUX_VWERASE] = b[BSD_VWERASE]; - l[LINUX_VKILL] = b[BSD_VKILL]; - l[LINUX_VREPRINT] = b[BSD_VREPRINT]; - l[LINUX_VINTR] = b[BSD_VINTR]; - l[LINUX_VQUIT] = b[BSD_VQUIT]; - l[LINUX_VSUSP] = b[BSD_VSUSP]; - l[LINUX_VSTART] = b[BSD_VSTART]; - l[LINUX_VSTOP] = b[BSD_VSTOP]; - l[LINUX_VLNEXT] = b[BSD_VLNEXT]; - l[LINUX_VDISCARD] = b[BSD_VDISCARD]; - l[LINUX_VMIN] = b[BSD_VMIN]; - l[LINUX_VTIME] = b[BSD_VTIME]; + l[LINUX_VEOF] = c_b2l(b[BSD_VEOF]); + l[LINUX_VEOL] = c_b2l(b[BSD_VEOL]); + l[LINUX_VEOL2] = c_b2l(b[BSD_VEOL2]); + l[LINUX_VERASE] = c_b2l(b[BSD_VERASE]); + l[LINUX_VWERASE] = c_b2l(b[BSD_VWERASE]); + l[LINUX_VKILL] = c_b2l(b[BSD_VKILL]); + l[LINUX_VREPRINT] = c_b2l(b[BSD_VREPRINT]); + l[LINUX_VINTR] = c_b2l(b[BSD_VINTR]); + l[LINUX_VQUIT] = c_b2l(b[BSD_VQUIT]); + l[LINUX_VSUSP] = c_b2l(b[BSD_VSUSP]); + l[LINUX_VSTART] = c_b2l(b[BSD_VSTART]); + l[LINUX_VSTOP] = c_b2l(b[BSD_VSTOP]); + l[LINUX_VLNEXT] = c_b2l(b[BSD_VLNEXT]); + l[LINUX_VDISCARD] = c_b2l(b[BSD_VDISCARD]); + l[LINUX_VMIN] = c_b2l(b[BSD_VMIN]); + l[LINUX_VTIME] = c_b2l(b[BSD_VTIME]); } static void iflag_linux_to_bsd(unsigned int l, unsigned long* b) @@ -174,3 +252,249 @@ static void iflag_bsd_to_linux(unsigned long b, unsigned int* l) *l |= LINUX_IUTF8; } +static void oflag_linux_to_bsd(unsigned int l, unsigned long* b) +{ + if (l & LINUX_OPOST) + *b |= BSD_OPOST; + if (l & LINUX_ONLCR) + *b |= BSD_ONLCR; + if (l & LINUX_XTABS) + *b |= BSD_OXTABS; + //if (l & LINUX_ONOEOT) + // *b |= BSD_ONOEOT; +} + +static void oflag_bsd_to_linux(unsigned long b, unsigned int* l) +{ + if (b & BSD_OPOST) + *l |= LINUX_OPOST; + if (b & BSD_ONLCR) + *l |= LINUX_ONLCR; + if (b & BSD_OXTABS) + *l |= LINUX_XTABS; + //if (b & BSD_ONOEOT) + // *l |= LINUX_ONOEOT; +} + +static void cflag_linux_to_bsd(unsigned int l, unsigned long* b) +{ + if (l & LINUX_CSIZE) + *b |= BSD_CSIZE; + if (l & LINUX_CS6) + *b |= BSD_CS6; + if (l & LINUX_CS7) + *b |= BSD_CS7; + if (l & LINUX_CS8) + *b |= BSD_CS8; + if (l & LINUX_CSTOPB) + *b |= BSD_CSTOPB; + if (l & LINUX_CREAD) + *b |= BSD_CREAD; + if (l & LINUX_PARENB) + *b |= BSD_PARENB; + if (l & LINUX_PARODD) + *b |= BSD_PARODD; + if (l & LINUX_HUPCL) + *b |= BSD_HUPCL; + if (l & LINUX_CLOCAL) + *b |= BSD_CLOCAL; +} + +static void cflag_bsd_to_linux(unsigned long b, unsigned int* l) +{ + if (b & BSD_CSIZE) + *l |= LINUX_CSIZE; + if (b & BSD_CS6) + *l |= LINUX_CS6; + if (b & BSD_CS7) + *l |= LINUX_CS7; + if (b & BSD_CS8) + *l |= LINUX_CS8; + if (b & BSD_CSTOPB) + *l |= LINUX_CSTOPB; + if (b & BSD_CREAD) + *l |= LINUX_CREAD; + if (b & BSD_PARENB) + *l |= LINUX_PARENB; + if (b & BSD_PARODD) + *l |= LINUX_PARODD; + if (b & BSD_HUPCL) + *l |= LINUX_HUPCL; + if (b & BSD_CLOCAL) + *l |= LINUX_CLOCAL; +} + +static void lflag_linux_to_bsd(unsigned int l, unsigned long* b) +{ + if (l & LINUX_ISIG) + *b |= BSD_ISIG; + if (l & LINUX_ICANON) + *b |= BSD_ICANON; + if (l & LINUX_ECHO) + *b |= BSD_ECHO; + if (l & LINUX_ECHOE) + *b |= BSD_ECHOE; + if (l & LINUX_ECHOKE) + *b |= BSD_ECHOKE; + if (l & LINUX_ECHOK) + *b |= BSD_ECHOK; + if (l & LINUX_ECHONL) + *b |= BSD_ECHONL; + if (l & LINUX_NOFLSH) + *b |= BSD_NOFLSH; + if (l & LINUX_TOSTOP) + *b |= BSD_TOSTOP; + if (l & LINUX_ECHOCTL) + *b |= BSD_ECHOCTL; + if (l & LINUX_ECHOPRT) + *b |= BSD_ECHOPRT; + if (l & LINUX_FLUSHO) + *b |= BSD_FLUSHO; + if (l & LINUX_PENDIN) + *b |= BSD_PENDIN; + if (l & LINUX_IEXTEN) + *b |= BSD_IEXTEN; + if (l & LINUX_EXTPROC) + *b |= BSD_EXTPROC; +} + +static void lflag_bsd_to_linux(unsigned long b, unsigned int* l) +{ + if (b & BSD_ISIG) + *l |= LINUX_ISIG; + if (b & BSD_ICANON) + *l |= LINUX_ICANON; + if (b & BSD_ECHO) + *l |= LINUX_ECHO; + if (b & BSD_ECHOE) + *l |= LINUX_ECHOE; + if (b & BSD_ECHOKE) + *l |= LINUX_ECHOKE; + if (b & BSD_ECHOK) + *l |= LINUX_ECHOK; + if (b & BSD_ECHONL) + *l |= LINUX_ECHONL; + if (b & BSD_NOFLSH) + *l |= LINUX_NOFLSH; + if (b & BSD_TOSTOP) + *l |= LINUX_TOSTOP; + if (b & BSD_ECHOCTL) + *l |= LINUX_ECHOCTL; + if (b & BSD_ECHOPRT) + *l |= LINUX_ECHOPRT; + if (b & BSD_FLUSHO) + *l |= LINUX_FLUSHO; + if (b & BSD_PENDIN) + *l |= LINUX_PENDIN; + if (b & BSD_IEXTEN) + *l |= LINUX_IEXTEN; + if (b & BSD_EXTPROC) + *l |= LINUX_EXTPROC; +} + +static void speed_linux_to_bsd(unsigned int l, unsigned long* b) +{ + unsigned long bspeed; + + switch (l) + { + case LINUX_B0: + bspeed = BSD_B0; break; + case LINUX_B50: + bspeed = BSD_B50; break; + case LINUX_B75: + bspeed = BSD_B75; break; + case LINUX_B110: + bspeed = BSD_B110; break; + case LINUX_B134: + bspeed = BSD_B134; break; + case LINUX_B150: + bspeed = BSD_B150; break; + case LINUX_B200: + bspeed = BSD_B200; break; + case LINUX_B300: + bspeed = BSD_B300; break; + case LINUX_B600: + bspeed = BSD_B600; break; + case LINUX_B1200: + bspeed = BSD_B1200; break; + case LINUX_B1800: + bspeed = BSD_B1800; break; + case LINUX_B2400: + bspeed = BSD_B2400; break; + case LINUX_B4800: + bspeed = BSD_B4800; break; + case LINUX_B9600: + bspeed = BSD_B9600; break; + case LINUX_B19200: + bspeed = BSD_B19200; break; + case LINUX_B38400: + bspeed = BSD_B38400; break; + case LINUX_B57600: + bspeed = BSD_B57600; break; + case LINUX_B115200: + bspeed = BSD_B115200; break; + case LINUX_B230400: + bspeed = BSD_B230400; break; + default: + bspeed = 0; + } + + *b = bspeed; +} + +static void speed_bsd_to_linux(unsigned long b, unsigned int* l) +{ + unsigned int lspeed; + + switch (b) + { + case BSD_B0: + lspeed = LINUX_B0; break; + case BSD_B50: + lspeed = LINUX_B50; break; + case BSD_B75: + lspeed = LINUX_B75; break; + case BSD_B110: + lspeed = LINUX_B110; break; + case BSD_B134: + lspeed = LINUX_B134; break; + case BSD_B150: + lspeed = LINUX_B150; break; + case BSD_B200: + lspeed = LINUX_B200; break; + case BSD_B300: + lspeed = LINUX_B300; break; + case BSD_B600: + lspeed = LINUX_B600; break; + case BSD_B1200: + lspeed = LINUX_B1200; break; + case BSD_B1800: + lspeed = LINUX_B1800; break; + case BSD_B2400: + lspeed = LINUX_B2400; break; + case BSD_B4800: + case BSD_B7200: + lspeed = LINUX_B4800; break; + case BSD_B28800: + case BSD_B14400: + case BSD_B9600: + lspeed = LINUX_B9600; break; + case BSD_B19200: + lspeed = LINUX_B19200; break; + case BSD_B38400: + lspeed = LINUX_B38400; break; + case BSD_B76800: + case BSD_B57600: + lspeed = LINUX_B57600; break; + case BSD_B115200: + lspeed = LINUX_B115200; break; + case BSD_B230400: + lspeed = LINUX_B230400; break; + default: + lspeed = 0; + } + + *l = lspeed; +} + diff --git a/src/kernel/emulation/linux/ioctl/termios.h b/src/kernel/emulation/linux/ioctl/termios.h index 530a792d4..94a0c618d 100644 --- a/src/kernel/emulation/linux/ioctl/termios.h +++ b/src/kernel/emulation/linux/ioctl/termios.h @@ -2,7 +2,7 @@ #define EMU_TERMIOS_H #include "ioctl.h" -int handle_termios(int fd, int cmd, void* arg, int* retval); +int handle_termios(int fd, unsigned int cmd, void* arg, int* retval); struct bsd_winsize { @@ -25,6 +25,7 @@ struct linux_termios unsigned int c_oflag; unsigned int c_cflag; unsigned int c_lflag; + unsigned char c_line; unsigned char c_cc[32]; unsigned int c_ispeed; unsigned int c_ospeed; @@ -176,6 +177,73 @@ enum { #define BSD_PENDIN 0x20000000 #define BSD_NOFLSH 0x80000000 +#define BSD_B0 0 +#define BSD_B50 50 +#define BSD_B75 75 +#define BSD_B110 110 +#define BSD_B134 134 +#define BSD_B150 150 +#define BSD_B200 200 +#define BSD_B300 300 +#define BSD_B600 600 +#define BSD_B1200 1200 +#define BSD_B1800 1800 +#define BSD_B2400 2400 +#define BSD_B4800 4800 +#define BSD_B9600 9600 +#define BSD_B19200 19200 +#define BSD_B38400 38400 +#define BSD_B7200 7200 +#define BSD_B14400 14400 +#define BSD_B28800 28800 +#define BSD_B57600 57600 +#define BSD_B76800 76800 +#define BSD_B115200 115200 +#define BSD_B230400 230400 + +#define LINUX_TCGETS 0x5401 +#define LINUX_TCSETS 0x5402 +#define LINUX_TCSETSW 0x5403 +#define LINUX_TCSETSF 0x5404 +#define LINUX_TCGETA 0x5405 +#define LINUX_TCSETA 0x5406 +#define LINUX_TCSETAW 0x5407 +#define LINUX_TCSETAF 0x5408 +#define LINUX_TCSBRK 0x5409 +#define LINUX_TCXONC 0x540A +#define LINUX_TCFLSH 0x540B +#define LINUX_TIOCEXCL 0x540C +#define LINUX_TIOCNXCL 0x540D +#define LINUX_TIOCSCTTY 0x540E +#define LINUX_TIOCGPGRP 0x540F +#define LINUX_TIOCSPGRP 0x5410 +#define LINUX_TIOCOUTQ 0x5411 +#define LINUX_TIOCSTI 0x5412 +#define LINUX_TIOCGWINSZ 0x5413 +#define LINUX_TIOCSWINSZ 0x5414 +#define LINUX_TIOCMGET 0x5415 +#define LINUX_TIOCMBIS 0x5416 +#define LINUX_TIOCMBIC 0x5417 +#define LINUX_TIOCMSET 0x5418 +#define LINUX_TIOCGSOFTCAR 0x5419 +#define LINUX_TIOCSSOFTCAR 0x541A +#define LINUX_FIONREAD 0x541B +#define LINUX_TIOCINQ LINUX_FIONREAD +#define LINUX_TIOCLINUX 0x541C +#define LINUX_TIOCCONS 0x541D +#define LINUX_TIOCGSERIAL 0x541E +#define LINUX_TIOCSSERIAL 0x541F +#define LINUX_TIOCPKT 0x5420 +#define LINUX_FIONBIO 0x5421 +#define LINUX_TIOCNOTTY 0x5422 +#define LINUX_TIOCSETD 0x5423 +#define LINUX_TIOCGETD 0x5424 +#define LINUX_TIOCSBRK 0x5425 +#define LINUX_TIOCCBRK 0x5426 + +#define LINUX_TIOCSTOP LINUX_IO('t', 111) +#define LINUX_TIOCSTART LINUX_IO('t', 110) + /* c_cc characters */ #define LINUX_VINTR 0 #define LINUX_VQUIT 1 @@ -260,6 +328,32 @@ enum { #define LINUX_IEXTEN 0100000 #define LINUX_EXTPROC 0200000 +/* Linux speed */ +#define LINUX_CBAUD 0010017 +#define LINUX_B0 0000000 +#define LINUX_B50 0000001 +#define LINUX_B75 0000002 +#define LINUX_B110 0000003 +#define LINUX_B134 0000004 +#define LINUX_B150 0000005 +#define LINUX_B200 0000006 +#define LINUX_B300 0000007 +#define LINUX_B600 0000010 +#define LINUX_B1200 0000011 +#define LINUX_B1800 0000012 +#define LINUX_B2400 0000013 +#define LINUX_B4800 0000014 +#define LINUX_B9600 0000015 +#define LINUX_B19200 0000016 +#define LINUX_B38400 0000017 + +#define LINUX_CBAUDEX 0010000 +#define LINUX_B57600 0010001 +#define LINUX_B115200 0010002 +#define LINUX_B230400 0010003 + +#define LINUX_POSIX_VDISABLE ((unsigned char)'\0') +#define BSD_POSIX_VDISABLE ((unsigned char)'\377') #endif diff --git a/src/kernel/emulation/linux/signal/duct_signals.c b/src/kernel/emulation/linux/signal/duct_signals.c index 5c12281e9..4adf611f8 100644 --- a/src/kernel/emulation/linux/signal/duct_signals.c +++ b/src/kernel/emulation/linux/signal/duct_signals.c @@ -147,7 +147,11 @@ void sigset_linux_to_bsd(const linux_sigset_t* linux, sigset_t* bsd) for (i = 0; i < 64; i++) { if (*linux & (1ull << i)) - *bsd |= signum_linux_to_bsd(i+1); + { + int num = signum_linux_to_bsd(i+1); + if (num) + *bsd |= 1 << (num-1); + } } } @@ -159,7 +163,11 @@ void sigset_bsd_to_linux(const sigset_t* bsd, linux_sigset_t* linux) for (i = 0; i < 64; i++) { if (*bsd & (1ull << i)) - *linux |= signum_bsd_to_linux(i+1); + { + int num = signum_bsd_to_linux(i+1); + if (num) + *linux |= 1 << (num-1); + } } } diff --git a/src/kernel/emulation/linux/signal/sig_restorer.S b/src/kernel/emulation/linux/signal/sig_restorer.S new file mode 100644 index 000000000..cdeb124be --- /dev/null +++ b/src/kernel/emulation/linux/signal/sig_restorer.S @@ -0,0 +1,16 @@ +.text +.globl sig_restorer +.hidden sig_restorer + +#ifdef __x86_64__ +sig_restorer: + movl $15, %eax + syscall + +#elif defined(__i386__) + +sig_restorer: + movl $173, %eax + int $0x80 +#endif + diff --git a/src/kernel/emulation/linux/signal/sigaction.c b/src/kernel/emulation/linux/signal/sigaction.c index eccf10792..4f1b897f0 100644 --- a/src/kernel/emulation/linux/signal/sigaction.c +++ b/src/kernel/emulation/linux/signal/sigaction.c @@ -1,6 +1,7 @@ #include "sigaction.h" #include "../base.h" #include "../errno.h" +#include "../simple.h" #include #include #include "../../../../../platform-include/sys/errno.h" @@ -8,7 +9,7 @@ static void handler_linux_to_bsd(int linux_signum, struct linux_siginfo* info, void* ctxt); static int sigflags_bsd_to_linux(int flags); static int sigflags_linux_to_bsd(int flags); -static void sig_restorer(void); +extern void sig_restorer(void); extern void* memcpy(void* dest, const void* src, unsigned long len); @@ -28,7 +29,14 @@ long sys_sigaction(int signum, const struct bsd___sigaction* nsa, struct bsd_sig if (nsa != NULL) { sa_tramp = nsa->sa_tramp; - sa.sa_sigaction = &handler_linux_to_bsd; + if (nsa->sa_sigaction != SIG_DFL && nsa->sa_sigaction != SIG_IGN + && nsa->sa_sigaction != SIG_ERR) + { + sa.sa_sigaction = &handler_linux_to_bsd; + } + else + sa.sa_sigaction = (linux_sig_handler*) nsa->sa_sigaction; + sigset_bsd_to_linux(&nsa->sa_mask, &sa.sa_mask); sa.sa_flags = sigflags_bsd_to_linux(nsa->sa_flags) | LINUX_SA_RESTORER; sa.sa_restorer = sig_restorer; @@ -41,7 +49,10 @@ long sys_sigaction(int signum, const struct bsd___sigaction* nsa, struct bsd_sig return errno_linux_to_bsd(ret); if (nsa != NULL) + { + // __simple_printf("Saving handler for signal %d: %d\n", linux_signum, nsa->sa_sigaction); sig_handlers[linux_signum] = nsa->sa_sigaction; + } if (osa != NULL) { @@ -62,15 +73,12 @@ static void handler_linux_to_bsd(int linux_signum, struct linux_siginfo* info, v memcpy(&binfo, info, sizeof(binfo)); binfo.si_signo = signum_linux_to_bsd(binfo.si_signo); + + // __simple_printf("Handling signal %d\n", linux_signum); sig_handlers[linux_signum](bsd_signum, &binfo, ctxt); -} - -static void sig_restorer(void) -{ - LINUX_SYSCALL(__NR_rt_sigreturn); - //__asm__("movl $137, %eax\n" - // "syscall"); + + // __simple_printf("Signal handled\n"); } static int sigflags_bsd_to_linux(int flags) diff --git a/src/kernel/emulation/linux/signal/sigaction.h b/src/kernel/emulation/linux/signal/sigaction.h index 5d197dfe0..ad670992e 100644 --- a/src/kernel/emulation/linux/signal/sigaction.h +++ b/src/kernel/emulation/linux/signal/sigaction.h @@ -52,6 +52,12 @@ struct linux_siginfo }; typedef void (bsd_sig_handler)(int, struct bsd_siginfo*, void*); +typedef void (linux_sig_handler)(int, struct linux_siginfo*, void*); + +#define SIG_DFL (bsd_sig_handler*)0 +#define SIG_IGN (bsd_sig_handler*)1 +#define SIG_ERR ((bsd_sig_handler*)-1l) + struct bsd_sigaction { bsd_sig_handler* sa_sigaction; @@ -69,7 +75,7 @@ struct bsd___sigaction struct linux_sigaction { - void (*sa_sigaction)(int, struct linux_siginfo*, void*); + linux_sig_handler* sa_sigaction; int sa_flags; void (*sa_restorer)(void); linux_sigset_t sa_mask; diff --git a/src/kernel/emulation/linux/signal/sigprocmask.c b/src/kernel/emulation/linux/signal/sigprocmask.c index 818a264bb..e8f021058 100644 --- a/src/kernel/emulation/linux/signal/sigprocmask.c +++ b/src/kernel/emulation/linux/signal/sigprocmask.c @@ -18,7 +18,7 @@ long sys_sigprocmask(int how, const sigset_t* set, sigset_t* oldset) sigset_bsd_to_linux(set, &in); ret = LINUX_SYSCALL(__NR_rt_sigprocmask, linux_how, - (set != NULL) ? &in : NULL, &out); + (set != NULL) ? &in : NULL, &out, sizeof(linux_sigset_t)); if (ret < 0) ret = errno_linux_to_bsd(ret); else if (oldset != NULL) diff --git a/src/kernel/emulation/linux/syscalls.c b/src/kernel/emulation/linux/syscalls.c index f7a837de9..9ade70792 100644 --- a/src/kernel/emulation/linux/syscalls.c +++ b/src/kernel/emulation/linux/syscalls.c @@ -43,6 +43,11 @@ #include "unistd/getgid.h" #include "unistd/getppid.h" #include "unistd/rename.h" +#include "unistd/getpgrp.h" +#include "unistd/getdtablesize.h" +#include "unistd/setpgid.h" +#include "unistd/getgroups.h" +#include "unistd/setgroups.h" #include "signal/kill.h" #include "signal/sigaltstack.h" #include "signal/sigaction.h" @@ -152,6 +157,11 @@ void* __bsd_syscall_table[512] = { [74] = sys_mprotect, [75] = sys_madvise, [78] = sys_mincore, + [79] = sys_getgroups, + [80] = sys_setgroups, + [81] = sys_getpgrp, + [82] = sys_setpgid, + [89] = sys_getdtablesize, [90] = sys_dup2, [92] = sys_fcntl, [93] = sys_select, diff --git a/src/kernel/emulation/linux/unistd/getdtablesize.c b/src/kernel/emulation/linux/unistd/getdtablesize.c new file mode 100644 index 000000000..900858aea --- /dev/null +++ b/src/kernel/emulation/linux/unistd/getdtablesize.c @@ -0,0 +1,21 @@ +#include "getdtablesize.h" +#include "../misc/getrlimit.h" +#include "../base.h" +#include "../errno.h" +#include +#include + +#define min(a,b) ((a) < (b)) ? (a) : (b) + +long sys_getdtablesize(void) +{ + int ret; + struct rlimit lim; + + ret = sys_getrlimit(BSD_RLIMIT_NOFILE, &lim); + if (ret < 0) + return ret; + + return min(lim.rlim_max, INT_MAX); +} + diff --git a/src/kernel/emulation/linux/unistd/getdtablesize.h b/src/kernel/emulation/linux/unistd/getdtablesize.h new file mode 100644 index 000000000..d96a0c982 --- /dev/null +++ b/src/kernel/emulation/linux/unistd/getdtablesize.h @@ -0,0 +1,7 @@ +#ifndef LINUX_GETDTABLESIZE_H +#define LINUX_GETDTABLESIZE_H + +long sys_getdtablesize(void); + +#endif + diff --git a/src/kernel/emulation/linux/unistd/getgroups.c b/src/kernel/emulation/linux/unistd/getgroups.c new file mode 100644 index 000000000..574923c2a --- /dev/null +++ b/src/kernel/emulation/linux/unistd/getgroups.c @@ -0,0 +1,16 @@ +#include "getgroups.h" +#include "../base.h" +#include "../errno.h" +#include + +long sys_getgroups(unsigned int size, int* gidset) +{ + int ret; + + ret = LINUX_SYSCALL(__NR_getgroups, size, gidset); + if (ret < 0) + ret = errno_linux_to_bsd(ret); + + return ret; +} + diff --git a/src/kernel/emulation/linux/unistd/getgroups.h b/src/kernel/emulation/linux/unistd/getgroups.h new file mode 100644 index 000000000..4a704f2dd --- /dev/null +++ b/src/kernel/emulation/linux/unistd/getgroups.h @@ -0,0 +1,7 @@ +#ifndef LINUX_GETGROUPS_H +#define LINUX_GETGROUPS_H + +long sys_getgroups(unsigned int size, int* gidset); + +#endif + diff --git a/src/kernel/emulation/linux/unistd/getpgrp.c b/src/kernel/emulation/linux/unistd/getpgrp.c new file mode 100644 index 000000000..3580b0f36 --- /dev/null +++ b/src/kernel/emulation/linux/unistd/getpgrp.c @@ -0,0 +1,16 @@ +#include "getpgrp.h" +#include "../base.h" +#include "../errno.h" +#include + +long sys_getpgrp(void) +{ + int ret; + + ret = LINUX_SYSCALL0(__NR_getpgrp); + if (ret < 0) + ret = errno_linux_to_bsd(ret); + + return ret; +} + diff --git a/src/kernel/emulation/linux/unistd/getpgrp.h b/src/kernel/emulation/linux/unistd/getpgrp.h new file mode 100644 index 000000000..387466ed6 --- /dev/null +++ b/src/kernel/emulation/linux/unistd/getpgrp.h @@ -0,0 +1,7 @@ +#ifndef LINUX_GETPGRP_H +#define LINUX_GETPGRP_H + +long sys_getpgrp(void); + +#endif + diff --git a/src/kernel/emulation/linux/unistd/setgroups.c b/src/kernel/emulation/linux/unistd/setgroups.c new file mode 100644 index 000000000..4cac07d98 --- /dev/null +++ b/src/kernel/emulation/linux/unistd/setgroups.c @@ -0,0 +1,16 @@ +#include "setgroups.h" +#include "../base.h" +#include "../errno.h" +#include + +long sys_setgroups(unsigned int size, int* gidset) +{ + int ret; + + ret = LINUX_SYSCALL(__NR_setgroups, size, gidset); + if (ret < 0) + ret = errno_linux_to_bsd(ret); + + return ret; +} + diff --git a/src/kernel/emulation/linux/unistd/setgroups.h b/src/kernel/emulation/linux/unistd/setgroups.h new file mode 100644 index 000000000..d88232d73 --- /dev/null +++ b/src/kernel/emulation/linux/unistd/setgroups.h @@ -0,0 +1,7 @@ +#ifndef LINUX_SETGROUPS_H +#define LINUX_SETGROUPS_H + +long sys_setgroups(unsigned int size, int* gidset); + +#endif + diff --git a/src/kernel/emulation/linux/unistd/setpgid.c b/src/kernel/emulation/linux/unistd/setpgid.c new file mode 100644 index 000000000..86c07feb4 --- /dev/null +++ b/src/kernel/emulation/linux/unistd/setpgid.c @@ -0,0 +1,16 @@ +#include "setpgid.h" +#include "../base.h" +#include "../errno.h" +#include + +long sys_setpgid(int pid, int pgid) +{ + int ret; + + ret = LINUX_SYSCALL(__NR_setpgid, pid, pgid); + if (ret < 0) + ret = errno_linux_to_bsd(ret); + + return ret; +} + diff --git a/src/kernel/emulation/linux/unistd/setpgid.h b/src/kernel/emulation/linux/unistd/setpgid.h new file mode 100644 index 000000000..67ff108dc --- /dev/null +++ b/src/kernel/emulation/linux/unistd/setpgid.h @@ -0,0 +1,7 @@ +#ifndef LINUX_SETPGID_H +#define LINUX_SETPGID_H + +long sys_setpgid(int pid, int pgid); + +#endif + diff --git a/src/kernel/libsyscall/sys/__vfork.S b/src/kernel/libsyscall/sys/__vfork.S index a95d6ed4d..8dcc2d18e 100644 --- a/src/kernel/libsyscall/sys/__vfork.S +++ b/src/kernel/libsyscall/sys/__vfork.S @@ -111,7 +111,7 @@ LEAF(___vfork, 0) lock cmpxchgl %ecx, (%rdx) jne 0b - popq %rdi // return address in %rdi + //popq %rdi // return address in %rdi #ifndef DARLING movq $ SYSCALL_CONSTRUCT_UNIX(SYS_vfork), %rax // code for vfork -> rax UNIX_SYSCALL_TRAP // do the system call @@ -122,7 +122,7 @@ LEAF(___vfork, 0) cmpq $0, %rax jnb L1 #endif - pushq %rdi // put return address back on stack for cerror + //pushq %rdi // put return address back on stack for cerror movq __current_pid@GOTPCREL(%rip), %rcx lock addq $1, (%rcx) @@ -138,13 +138,15 @@ L1: jnz L2 #endif xorq %rax, %rax // zero rax - jmp *%rdi + //jmp *%rdi + ret L2: movq __current_pid@GOTPCREL(%rip), %rdx lock addq $1, (%rdx) - jmp *%rdi + //jmp *%rdi + ret #else #error Unsupported architecture diff --git a/src/libc/CMakeLists.txt b/src/libc/CMakeLists.txt index 73a5e2ecb..1a0d4d273 100644 --- a/src/libc/CMakeLists.txt +++ b/src/libc/CMakeLists.txt @@ -84,12 +84,14 @@ add_library(system_c SHARED $ $ $ + $ $ $ $ $ $ $ + $ $ $ $ diff --git a/src/libc/gen/CMakeLists.txt b/src/libc/gen/CMakeLists.txt index c32fc69a1..6ac6ad497 100644 --- a/src/libc/gen/CMakeLists.txt +++ b/src/libc/gen/CMakeLists.txt @@ -162,8 +162,9 @@ SET_SOURCE_FILES_PROPERTIES(FreeBSD/termios.c PROPERTIES COMPILE_FLAGS "${CMAKE_ SET_SOURCE_FILES_PROPERTIES(FreeBSD/wait.c PROPERTIES COMPILE_FLAGS "${CMAKE_C_FLAGS} -DLIBC_ALIAS_WAIT") SET_SOURCE_FILES_PROPERTIES(FreeBSD/waitpid.c PROPERTIES COMPILE_FLAGS "${CMAKE_C_FLAGS} -DLIBC_ALIAS_WAITPID") -#set(gen_sources ${gen_sources} -# NetBSD/utmpx.c) +set(gen_sources ${gen_sources} + #NetBSD/utmpx.c +) add_library(libc-gen OBJECT ${gen_sources}) @@ -174,3 +175,11 @@ set(gen-cancelable_sources FreeBSD/lockf.c nanosleep.c FreeBSD/pause.c FreeBSD/p add_library(libc-gen_cancelable OBJECT ${gen-cancelable_sources}) SET_TARGET_PROPERTIES(libc-gen_cancelable PROPERTIES COMPILE_DEFINITIONS "BUILDING_VARIANT;VARIANT_CANCELABLE") + +# *** +# No-INODE64 variants +# *** +set(gen-noinode64_sources FreeBSD/seekdir.c FreeBSD/readdir.c FreeBSD/scandir.c FreeBSD/rewinddir.c FreeBSD/telldir.c fts.c FreeBSD/getmntinfo.c FreeBSD/glob.c FreeBSD/opendir.c nftw.c) +add_library(libc-gen_noinode64 OBJECT ${gen-noinode64_sources}) +SET_TARGET_PROPERTIES(libc-gen_noinode64 PROPERTIES COMPILE_FLAGS "-U__DARWIN_UNIX03 -U__DARWIN_64_BIT_INO_T -DVARIANT_INODE32 -DBUILDING_VARIANT -D_DARWIN_NO_64_BIT_INODE") + diff --git a/src/libc/pthreads/CMakeLists.txt b/src/libc/pthreads/CMakeLists.txt index 4b6fd8ae2..94cbde357 100644 --- a/src/libc/pthreads/CMakeLists.txt +++ b/src/libc/pthreads/CMakeLists.txt @@ -25,4 +25,5 @@ set(pthreads-cancelable_sources add_library(libc-pthreads_cancelable OBJECT ${pthreads-cancelable_sources}) SET_TARGET_PROPERTIES(libc-pthreads_cancelable PROPERTIES COMPILE_DEFINITIONS "BUILDING_VARIANT;VARIANT_CANCELABLE") +SET_TARGET_PROPERTIES(libc-pthreads_cancelable PROPERTIES COMPILE_FLAGS "-U__DARWIN_NON_CANCELABLE") diff --git a/src/libc/sys/CMakeLists.txt b/src/libc/sys/CMakeLists.txt index 6af92ccef..07baf6f54 100644 --- a/src/libc/sys/CMakeLists.txt +++ b/src/libc/sys/CMakeLists.txt @@ -39,3 +39,11 @@ SET_SOURCE_FILES_PROPERTIES(shmctl.c PROPERTIES COMPILE_FLAGS "${CMAKE_C_FLAGS} SET_SOURCE_FILES_PROPERTIES(sigtramp.c PROPERTIES COMPILE_FLAGS "${CMAKE_C_FLAGS} -D_XOPEN_SOURCE") add_library(libc-sys OBJECT ${sys_sources}) + +# *** +# No-INODE64 variants +# *** +set(sys-noinode64_sources statx_np.c) +add_library(libc-sys_noinode64 OBJECT ${sys-noinode64_sources}) +SET_TARGET_PROPERTIES(libc-sys_noinode64 PROPERTIES COMPILE_FLAGS "-U__DARWIN_UNIX03 -U__DARWIN_64_BIT_INO_T -DVARIANT_INODE32 -DBUILDING_VARIANT -D_DARWIN_NO_64_BIT_INODE") + diff --git a/src/libc/x86_64/sys/setjmp.S b/src/libc/x86_64/sys/setjmp.S index c78c1f35a..03b35e1da 100644 --- a/src/libc/x86_64/sys/setjmp.S +++ b/src/libc/x86_64/sys/setjmp.S @@ -53,6 +53,7 @@ # define __sigunaltstack _sigunaltstack # define _sigprocmask sigprocmask # define _sigsetjmp sigsetjmp +# define _siglongjmp siglongjmp #else # define x__setjmp __setjmp # define x__longjmp __longjmp