diff --git a/scsh/linux/fix_stdio.c b/scsh/linux/fix_stdio.c new file mode 100644 index 0000000..eefcf78 --- /dev/null +++ b/scsh/linux/fix_stdio.c @@ -0,0 +1,79 @@ +#include + +/* The current stdio lib that Linux uses has a problem that screws up +** scsh's interrupt system: when a stdio function such as getc() or fputs() +** blocks in an i/o system call, and that system call is interrupted, the +** stdio function realises this and loops, retrying the the i/o operation. +** What we need is for the stdio function to return an error, with +** errno=EINTR -- i.e., we need for the stdio function to give control back +** to the caller, telling it that the i/o call was interrupted. +** +** The EINTR error return is in fact mandated by Posix. The next release +** of the GNU libc will provide this functionality. The current release +** doesn't. So we use the workaround in this file. Calling +** remove_bone_from_head_of_linux_libc() +** will smash the call tables of the i/o library so that non-retrying +** functions get called to do the i/o system calls. +** +** Why does scsh need non-retry? Because in scsh, Unix signals are *not* +** handled by the actual Unix signal handler. The signal handler is just +** a piece of C code that sets a bit, notifying the S48 vm that it needs +** to service a signal. When the vm gets to a vm instruction boundary, +** it suspends execution of the program and services the interrupt by +** invoking a *Scheme* function. In this way, we can interrupt on VM +** instruction boundaries with VM interrupt handlers. +** +** If a C function retries when interrupted, we never return to Scheme, +** and so the vm never has a chance to service the interrupt. This is bad. +** +** This code was contributed by Roland McGrath. +*/ + +#ifdef __GLIBC__ + +/* GNU libc 2.0 needs no fixing. */ +void remove_bone_from_head_of_linux_libc () {} + +#else + +#include + +extern _IO_ssize_t _IO_file_read (_IO_FILE *, void *, _IO_ssize_t); +_IO_ssize_t +my_linux_file_read (_IO_FILE *fp, void *buf, _IO_ssize_t size) +{ + return read (fp->_fileno, buf, size); +} + +extern _IO_ssize_t _IO_file_write (_IO_FILE *, const void *, _IO_ssize_t); +_IO_ssize_t +my_linux_file_write (_IO_FILE *fp, const void *buf, _IO_ssize_t size) +{ + return write (fp->_fileno, buf, size); +} + +static void +debone (_IO_ssize_t (**jumptable) ()) +{ + _IO_ssize_t (**p) (); + int r, w; + r = w = 0; + for (p = jumptable; !r || !w; ++p) + { + if (*p == &_IO_file_read) + ++r, *p = &my_linux_file_read; + else if (*p == &_IO_file_write) + ++w, *p = &my_linux_file_write; + } +} + +void +remove_bone_from_head_of_linux_libc () +{ + extern _IO_ssize_t (*_IO_file_jumps[]) (); /* used for normal fds */ + extern _IO_ssize_t (*_IO_proc_jumps[]) (); /* used by popen */ + + debone (_IO_file_jumps); + debone (_IO_proc_jumps); +} +#endif diff --git a/scsh/linux/signals1.c b/scsh/linux/signals1.c new file mode 100644 index 0000000..ee71a34 --- /dev/null +++ b/scsh/linux/signals1.c @@ -0,0 +1,52 @@ +/* This is bogus -- currently unchanged from the bsd file. */ +/* Need to turn off synchronous error signals (SIGPIPE, SIGSYS). */ + +#include "../scsh_aux.h" + +/* Make sure our exports match up w/the implementation: */ +#include "../signals1.h" + +/* This table converts Unix signal numbers to S48/scsh interrupt numbers. +** If the signal doesn't have an interrupt number, the entry is -1. +** (Only asynchronous signals have interrupt numbers.) +** +** Note that we bake into this table the integer values of the signals -- +** i.e., we assume that SIGHUP=1, SIGALRM=15, etc. So this definition is +** very system-dependent. +*/ +const int sig2int[] = { + -1, /* 0 is not a signal */ + scshint_hup, /* SIGHUP */ + scshint_keyboard, /* SIGINT */ + scshint_quit, /* SIGQUIT */ + -1, /* SIGILL */ + -1, /* SIGTRAP */ + -1, /* SIGABRT & SIGIOT */ + -1, /* SIGBUS */ + -1, /* SIGFPE */ + -1, /* SIGKILL */ + scshint_usr1, /* SIGUSR1 */ + -1, /* SIGSEGV */ + scshint_usr2, /* SIGUSR2 */ + -1, /* SIGPIPE */ + scshint_alarm, /* SIGALRM */ + scshint_term, /* SIGTERM */ + -1, /* SIGTKFLT (x86 coprocessor stack fault) */ + scshint_chld, /* SIGCHLD */ + scshint_cont, /* SIGCONT */ + -1, /* SIGSTOP */ + scshint_tstp, /* SIGTSTP */ + -1, /* scshint_ttyin, /* SIGTTIN */ + -1, /* scshint_ttou, /* SIGTTOU */ + scshint_urg, /* SIGURG */ + scshint_xcpu, /* SIGXCPU */ + scshint_xfsz, /* SIGXFSZ */ + scshint_vtalrm, /* SIGVTALRM */ + scshint_prof, /* SIGPROF */ + scshint_winch, /* SIGWINCH */ + scshint_io, /* SIGIO aka SIGPOLL*/ + scshint_pwr, /* SIGPWR */ + -1 /* SIGPWR */ + }; + +const int max_sig = 31; /* SIGUNUSED */