home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mitsch75.zip / scheme-7_5_17-src.zip / scheme-7.5.17 / src / microcode / uxsig.c < prev    next >
C/C++ Source or Header  |  2001-07-15  |  36KB  |  1,332 lines

  1. /* -*-C-*-
  2.  
  3. $Id: uxsig.c,v 1.36 2001/07/16 02:44:01 cph Exp $
  4.  
  5. Copyright (c) 1990-2001 Massachusetts Institute of Technology
  6.  
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or (at
  10. your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful, but
  13. WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15. General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  20. USA.
  21. */
  22.  
  23. #include "config.h"
  24. #include "ux.h"
  25. #include "ossig.h"
  26. #include "osctty.h"
  27. #include "ostty.h"
  28. #include "ostop.h"
  29. #include "uxtrap.h"
  30. #include "uxsig.h"
  31. #include "uxutil.h"
  32. #include "critsec.h"
  33.  
  34. extern cc_t EXFUN (OS_ctty_quit_char, (void));
  35. extern cc_t EXFUN (OS_ctty_int_char, (void));
  36. extern cc_t EXFUN (OS_ctty_tstp_char, (void));
  37. extern cc_t EXFUN (OS_ctty_disabled_char, (void));
  38. extern void EXFUN (tty_set_next_interrupt_char, (cc_t c));
  39.  
  40. /* Signal Manipulation */
  41.  
  42. #ifdef HAVE_POSIX_SIGNALS
  43.  
  44. static Tsignal_handler
  45. DEFUN (current_handler, (signo), int signo)
  46. {
  47.   struct sigaction act;
  48.   UX_sigaction (signo, 0, (&act));
  49.   return (act . sa_handler);
  50. }
  51.  
  52. #ifndef SA_SIGINFO
  53. #define SA_SIGINFO 0
  54. #endif
  55.  
  56. void
  57. DEFUN (INSTALL_HANDLER, (signo, handler),
  58.        int signo AND
  59.        Tsignal_handler handler)
  60. {
  61.   struct sigaction act;
  62.   (act . sa_handler) = handler;
  63.   UX_sigemptyset (& (act . sa_mask));
  64.   UX_sigaddset ((& (act . sa_mask)), signo);
  65.   (act . sa_flags) = SA_SIGINFO;
  66.   UX_sigaction (signo, (&act), 0);
  67. }
  68.  
  69. #else /* not HAVE_POSIX_SIGNALS */
  70. #ifdef HAVE_SIGHOLD
  71.  
  72. static Tsignal_handler
  73. DEFUN (current_handler, (signo), int signo)
  74. {
  75.   Tsignal_handler result = (UX_sigset (signo, SIG_HOLD));
  76.   if (result != SIG_HOLD)
  77.     UX_signal (signo, result);
  78.   return (result);
  79. }
  80.  
  81. #else /* not HAVE_SIGHOLD */
  82.  
  83. static Tsignal_handler
  84. DEFUN (current_handler, (signo), int signo)
  85. {
  86.   Tsignal_handler result = (UX_signal (signo, SIG_IGN));
  87.   if (result != SIG_IGN)
  88.     UX_signal (signo, result);
  89.   return (result);
  90. }
  91.  
  92. #endif /* HAVE_SIGHOLD */
  93. #endif /* HAVE_POSIX_SIGNALS */
  94.  
  95. #ifdef NEED_HANDLER_TRANSACTION
  96.  
  97. void
  98. DEFUN (ta_abort_handler, (ap), PTR ap)
  99. {
  100.   ABORT_HANDLER ((((struct handler_record *) ap) -> signo),
  101.          (((struct handler_record *) ap) -> handler));
  102. }
  103.  
  104. #endif /* NEED_HANDLER_TRANSACTION */
  105.  
  106. #ifdef HAVE_POSIX_SIGNALS
  107.  
  108. static void
  109. DEFUN (restore_signal_mask, (environment), PTR environment)
  110. {
  111.   UX_sigprocmask (SIG_SETMASK, ((sigset_t *) environment), 0);
  112. }
  113.  
  114. static void
  115. DEFUN (save_signal_mask, (environment), PTR environment)
  116. {
  117.   UX_sigprocmask (SIG_SETMASK, 0, ((sigset_t *) environment));
  118. }
  119.  
  120. void
  121. DEFUN_VOID (preserve_signal_mask)
  122. {
  123.   dstack_alloc_and_protect
  124.     ((sizeof (sigset_t)), save_signal_mask, restore_signal_mask);
  125. }
  126.  
  127. static sigset_t blocked_signals;
  128.  
  129. void
  130. DEFUN_VOID (block_signals)
  131. {
  132.   sigset_t all_signals;
  133.   UX_sigfillset (&all_signals);
  134.   UX_sigprocmask (SIG_BLOCK, (&all_signals), (&blocked_signals));
  135. }
  136.  
  137. void
  138. DEFUN_VOID (unblock_signals)
  139. {
  140.   UX_sigprocmask (SIG_SETMASK, (&blocked_signals), 0);
  141. }
  142.  
  143. #else /* not HAVE_POSIX_SIGNALS */
  144.  
  145. void
  146. DEFUN_VOID (preserve_signal_mask)
  147. {
  148. }
  149.  
  150. void
  151. DEFUN_VOID (block_signals)
  152. {
  153. }
  154.  
  155. void
  156. DEFUN_VOID (unblock_signals)
  157. {
  158. }
  159.  
  160. #endif /* not HAVE_POSIX_SIGNALS */
  161.  
  162. void
  163. DEFUN (deactivate_handler, (signo), int signo)
  164. {
  165.   INSTALL_HANDLER (signo, SIG_IGN);
  166. }
  167.  
  168. void
  169. DEFUN (activate_handler, (signo, handler),
  170.        int signo AND
  171.        Tsignal_handler handler)
  172. {
  173.   INSTALL_HANDLER (signo, handler);
  174. }
  175.  
  176. /* Signal Debugging */
  177.  
  178. #ifdef DEBUG_SIGNAL_DELIVERY
  179.  
  180. int signal_history [256];
  181. int * signal_history_pointer;
  182.  
  183. static void
  184. DEFUN_VOID (initialize_signal_debugging)
  185. {
  186.   int * scan = (&signal_history[0]);
  187.   int * end = (scan + (sizeof (signal_history)));
  188.   signal_history_pointer = scan;
  189.   while (scan < end)
  190.     (*scan++) = 0;
  191. }
  192.  
  193. static void
  194. DEFUN (record_signal_delivery, (signo), int signo)
  195. {
  196.   block_signals ();
  197.   (*signal_history_pointer++) = signo;
  198.   if (signal_history_pointer >= (& (signal_history [sizeof (signal_history)])))
  199.     signal_history_pointer = (&signal_history[0]);
  200.   unblock_signals ();
  201. }
  202.  
  203. #else /* not DEBUG_SIGNAL_DELIVERY */
  204.  
  205. #define initialize_signal_debugging()
  206.  
  207. #endif /* not DEBUG_SIGNAL_DELIVERY */
  208.  
  209. /* Signal Descriptors */
  210.  
  211. enum dfl_action { dfl_terminate, dfl_ignore, dfl_stop };
  212.  
  213. struct signal_descriptor
  214. {
  215.   int signo;
  216.   CONST char * name;
  217.   enum dfl_action action;
  218.   int flags;
  219. };
  220.  
  221. /* `flags' bits */
  222. #define NOIGNORE 1
  223. #define NOBLOCK 2
  224. #define NOCATCH 4
  225. #define CORE_DUMP 8
  226.  
  227. static struct signal_descriptor * signal_descriptors;
  228. static unsigned int signal_descriptors_length;
  229. static unsigned int signal_descriptors_limit;
  230.  
  231. static void
  232. DEFUN (defsignal, (signo, name, action, flags),
  233.        int signo AND
  234.        CONST char * name AND
  235.        enum dfl_action action AND
  236.        int flags)
  237. {
  238.   if (signo == 0)
  239.     return;
  240.   if (signal_descriptors_length == signal_descriptors_limit)
  241.     {
  242.       signal_descriptors_limit += 8;
  243.       signal_descriptors =
  244.     (UX_realloc (signal_descriptors,
  245.              (signal_descriptors_limit *
  246.               (sizeof (struct signal_descriptor)))));
  247.       if (signal_descriptors == 0)
  248.     {
  249.       fprintf (stderr, "\nUnable to grow signal definitions table.\n");
  250.       fflush (stderr);
  251.       termination_init_error ();
  252.     }
  253.     }
  254.   {
  255.     struct signal_descriptor * sd =
  256.       (signal_descriptors + (signal_descriptors_length++));
  257.     (sd -> signo) = signo;
  258.     (sd -> name) = name;
  259.     (sd -> action) = action;
  260.     (sd -> flags) = flags;
  261.   }
  262. }
  263.  
  264. static struct signal_descriptor *
  265. DEFUN (find_signal_descriptor, (signo), int signo)
  266. {
  267.   struct signal_descriptor * scan = signal_descriptors;
  268.   struct signal_descriptor * end = (scan + signal_descriptors_length);
  269.   for (; (scan < end); scan += 1)
  270.     if ((scan -> signo) == signo)
  271.       return (scan);
  272.   return (0);
  273. }
  274.  
  275. CONST char *
  276. DEFUN (find_signal_name, (signo), int signo)
  277. {
  278.   static char buffer [32];
  279.   struct signal_descriptor * descriptor = (find_signal_descriptor (signo));
  280.   if (descriptor != 0)
  281.     return (descriptor -> name);
  282.   sprintf (buffer, "unknown signal %d", signo);
  283.   return ((CONST char *) buffer);
  284. }
  285.  
  286. #if (SIGABRT == SIGIOT)
  287. #  undef SIGABRT
  288. #  define SIGABRT 0
  289. #endif
  290.  
  291. static void
  292. DEFUN_VOID (initialize_signal_descriptors)
  293. {
  294.   signal_descriptors_length = 0;
  295.   signal_descriptors_limit = 32;
  296.   signal_descriptors =
  297.     (UX_malloc (signal_descriptors_limit *
  298.         (sizeof (struct signal_descriptor))));
  299.   if (signal_descriptors == 0)
  300.     {
  301.       fprintf (stderr, "\nUnable to allocate signal definitions table.\n");
  302.       fflush (stderr);
  303.       termination_init_error ();
  304.     }
  305.   defsignal (SIGHUP, "SIGHUP",        dfl_terminate,    0);
  306.   defsignal (SIGINT, "SIGINT",        dfl_terminate,    0);
  307.   defsignal (SIGQUIT, "SIGQUIT",    dfl_terminate,    CORE_DUMP);
  308.   defsignal (SIGILL, "SIGILL",        dfl_terminate,    CORE_DUMP);
  309.   defsignal (SIGTRAP, "SIGTRAP",    dfl_terminate,    CORE_DUMP);
  310.   defsignal (SIGIOT, "SIGIOT",        dfl_terminate,    CORE_DUMP);
  311.   defsignal (SIGEMT, "SIGEMT",        dfl_terminate,    CORE_DUMP);
  312.   defsignal (SIGFPE, "SIGFPE",        dfl_terminate,    CORE_DUMP);
  313.   defsignal (SIGKILL, "SIGKILL",    dfl_terminate,    (NOIGNORE | NOBLOCK | NOCATCH));
  314.   defsignal (SIGBUS, "SIGBUS",        dfl_terminate,    CORE_DUMP);
  315.   defsignal (SIGSEGV, "SIGSEGV",    dfl_terminate,    CORE_DUMP);
  316.   defsignal (SIGSYS, "SIGSYS",        dfl_terminate,    CORE_DUMP);
  317.   defsignal (SIGPIPE, "SIGPIPE",    dfl_terminate,    0);
  318.   defsignal (SIGALRM, "SIGALRM",    dfl_terminate,    0);
  319.   defsignal (SIGTERM, "SIGTERM",    dfl_terminate,    0);
  320.   defsignal (SIGUSR1, "SIGUSR1",    dfl_terminate,    0);
  321.   defsignal (SIGUSR2, "SIGUSR2",    dfl_terminate,    0);
  322.   defsignal (SIGABRT, "SIGABRT",    dfl_terminate,    CORE_DUMP);
  323.   defsignal (SIGIO, "SIGIO",        dfl_ignore,    0);
  324.   defsignal (SIGURG, "SIGURG",        dfl_ignore,    0);
  325.   defsignal (SIGVTALRM, "SIGVTALRM",    dfl_terminate,    0);
  326.   defsignal (SIGPROF, "SIGPROF",    dfl_terminate,    0);
  327.   defsignal (SIGSTOP, "SIGSTOP",    dfl_stop,    (NOIGNORE | NOBLOCK | NOCATCH));
  328.   defsignal (SIGTSTP, "SIGTSTP",    dfl_stop,    0);
  329.   defsignal (SIGCONT, "SIGCONT",    dfl_ignore,    (NOIGNORE | NOBLOCK));
  330.   defsignal (SIGCHLD, "SIGCHLD",    dfl_ignore,    0);
  331.   defsignal (SIGTTIN, "SIGTTIN",    dfl_stop,    0);
  332.   defsignal (SIGTTOU, "SIGTTOU",    dfl_stop,    0);
  333.   defsignal (SIGLOST, "SIGLOST",    dfl_terminate,    0);
  334.   defsignal (SIGXCPU, "SIGXCPU",    dfl_terminate,    0);
  335.   defsignal (SIGXFSZ, "SIGXFSZ",    dfl_terminate,    0);
  336.   defsignal (SIGPWR, "SIGPWR",        dfl_ignore,    0);
  337.   defsignal (SIGWINDOW, "SIGWINDOW",    dfl_ignore,    0);
  338.   defsignal (SIGWINCH, "SIGWINCH",    dfl_ignore,    0);
  339. }
  340.  
  341. #define CONTROL_B_INTERRUPT_CHAR 'B'
  342. #define CONTROL_G_INTERRUPT_CHAR 'G'
  343. #define CONTROL_U_INTERRUPT_CHAR 'U'
  344. #define CONTROL_X_INTERRUPT_CHAR 'X'
  345.  
  346. static void
  347. DEFUN (echo_keyboard_interrupt, (c, dc), cc_t c AND cc_t dc)
  348. {
  349.   if (c == (OS_ctty_disabled_char ()))
  350.     c = dc;
  351.   c &= 0177;
  352.   if (c == ALERT_CHAR)
  353.     putc (c, stdout);
  354.   else if (c < '\040')
  355.     {
  356.       putc ('^', stdout);
  357.       putc ((c + '@'), stdout);
  358.     }
  359.   else if (c == '\177')
  360.     fputs ("^?", stdout);
  361.   else
  362.     putc (c, stdout);
  363.   fflush (stdout);
  364. }
  365.  
  366. static
  367. DEFUN_STD_HANDLER (sighnd_control_g,
  368. {
  369.   echo_keyboard_interrupt ((OS_ctty_int_char ()), ALERT_CHAR);
  370.   tty_set_next_interrupt_char (CONTROL_G_INTERRUPT_CHAR);
  371. })
  372.  
  373. static
  374. DEFUN_STD_HANDLER (sighnd_control_u,
  375. {
  376.   tty_set_next_interrupt_char (CONTROL_U_INTERRUPT_CHAR);
  377. })
  378.  
  379. static
  380. DEFUN_STD_HANDLER (sighnd_control_x,
  381. {
  382.   tty_set_next_interrupt_char (CONTROL_X_INTERRUPT_CHAR);
  383. })
  384.  
  385. static
  386. DEFUN_STD_HANDLER (sighnd_control_b,
  387. {
  388.   tty_set_next_interrupt_char (CONTROL_B_INTERRUPT_CHAR);
  389. })
  390.  
  391. static void EXFUN
  392.   (interactive_interrupt_handler, (struct FULL_SIGCONTEXT * scp));
  393.  
  394. static
  395. DEFUN_STD_HANDLER (sighnd_interactive,
  396.   (interactive_interrupt_handler (scp)))
  397.  
  398. void
  399. DEFUN (stop_signal_default, (signo), int signo)
  400. {
  401. #ifdef HAVE_POSIX_SIGNALS
  402.   if ((isatty (STDIN_FILENO))
  403.       && (isatty (STDOUT_FILENO))
  404.       && (! option_emacs_subprocess))
  405.   {
  406.     /* No need to handle systems without POSIX signals;
  407.        all job-control systems have them. */
  408.     sigset_t signo_mask;
  409.     sigset_t old_mask;
  410.     Tsignal_handler handler;
  411.  
  412.     /* Give the terminal back to the invoking process. */
  413.     OS_save_internal_state ();
  414.     OS_restore_external_state ();
  415.  
  416.     /* Temporarily unbind this handler. */
  417.     handler = (current_handler (signo));
  418.     INSTALL_HANDLER (signo, SIG_DFL);
  419.  
  420.     /* Perform the default action for this signal. */
  421.     UX_sigemptyset (&signo_mask);
  422.     UX_sigaddset ((&signo_mask), signo);
  423.     UX_sigprocmask (SIG_UNBLOCK, (&signo_mask), (&old_mask));
  424.     UX_kill ((UX_getpid ()), signo);
  425.     UX_sigprocmask (SIG_SETMASK, (&old_mask), 0);
  426.  
  427.     /* Rebind this handler. */
  428.     INSTALL_HANDLER (signo, handler);
  429.  
  430.     /* Get the terminal back to its original state. */
  431.     OS_save_external_state ();
  432.     OS_restore_internal_state ();
  433.   }
  434. #endif /* HAVE_POSIX_SIGNALS */
  435. }
  436.  
  437. void EXFUN ((*stop_signal_hook), (int signo));
  438.  
  439. #ifdef HAVE_POSIX_SIGNALS
  440. #  define IF_POSIX_SIGNALS(code) do code while (0)
  441. #else
  442. #  define IF_POSIX_SIGNALS(code) do {} while (0)
  443. #endif
  444.  
  445. static
  446. DEFUN_STD_HANDLER (sighnd_stop,
  447.   IF_POSIX_SIGNALS (
  448. {
  449.   sigset_t old_mask;
  450.   sigset_t jc_mask;
  451.  
  452.   if (! (UX_SC_JOB_CONTROL ()))
  453.     return;
  454.   /* Initialize the signal masks. */
  455.   UX_sigemptyset (&jc_mask);
  456.   UX_sigaddset ((&jc_mask), SIGTTOU);
  457.   UX_sigaddset ((&jc_mask), SIGTTIN);
  458.   UX_sigaddset ((&jc_mask), SIGTSTP);
  459.   UX_sigaddset ((&jc_mask), SIGSTOP);
  460.   UX_sigaddset ((&jc_mask), SIGCHLD);
  461.  
  462.   /* Block the job-control signals. */
  463.   UX_sigprocmask (SIG_BLOCK, (&jc_mask), (&old_mask));
  464.  
  465.   if (stop_signal_hook == 0)
  466.     stop_signal_default (signo);
  467.   else
  468.     (*stop_signal_hook) (signo);
  469.  
  470.   /* Restore the signal mask to its original state. */
  471.   UX_sigprocmask (SIG_SETMASK, (&old_mask), 0);
  472. }))
  473.  
  474. void
  475. DEFUN_VOID (OS_restartable_exit)
  476. {
  477.   stop_signal_default (SIGTSTP);
  478. }
  479.  
  480. /* The following conditionalization would more naturally be expressed
  481.    by conditionalizing the code inside the handler, but the Sun
  482.    compiler won't accept this conditionalization.  */
  483.  
  484. #ifdef HAVE_SETITIMER
  485.  
  486. static
  487. DEFUN_STD_HANDLER (sighnd_timer,
  488. {
  489.   request_timer_interrupt ();
  490. })
  491.  
  492. #else /* not HAVE_SETITIMER */
  493.  
  494. static
  495. DEFUN_STD_HANDLER (sighnd_timer,
  496. {
  497.   extern void EXFUN (reschedule_alarm, (void));
  498.   reschedule_alarm ();
  499.   request_timer_interrupt ();
  500. })
  501.  
  502. #endif /* not HAVE_SETITIMER */
  503.  
  504. static
  505. DEFUN_STD_HANDLER (sighnd_save_then_terminate,
  506.   (request_suspend_interrupt ()))
  507.  
  508. static
  509. DEFUN_STD_HANDLER (sighnd_terminate,
  510.   (termination_signal
  511.    ((! (option_emacs_subprocess && (signo == SIGHUP)))
  512.     ? (find_signal_name (signo))
  513.     : 0)))
  514.  
  515. static
  516. DEFUN_STD_HANDLER (sighnd_fpe,
  517. {
  518.   if (executing_scheme_primitive_p ())
  519.     error_floating_point_exception ();
  520.   trap_handler ("floating-point exception", signo, info, scp);
  521. })
  522.  
  523. static
  524. DEFUN_STD_HANDLER (sighnd_hardware_trap,
  525.   (trap_handler ("hardware fault", signo, info, scp)))
  526.  
  527. static
  528. DEFUN_STD_HANDLER (sighnd_software_trap,
  529.   (trap_handler ("system software fault", signo, info, scp)))
  530.  
  531. #ifdef HAVE_NICE
  532.  
  533. #ifndef NICE_DELTA
  534. #define NICE_DELTA 5
  535. #endif
  536.  
  537. static
  538. DEFUN_STD_HANDLER (sighnd_renice,
  539. {
  540.   fprintf (stderr, "\n;;; Renicing! New nice value = %d\n",
  541.        ((nice (NICE_DELTA)) + 20));
  542.   fflush (stderr);
  543. })
  544.  
  545. #endif /* HAVE_NICE */
  546.  
  547. /* When a child process terminates, it becomes a zombie until its
  548.    parent process calls one of the wait() routines to obtain the
  549.    child's termination status.  The SIGCHLD handler must always call
  550.    wait() or waitpid() to permit the child process's resources to be
  551.    freed. */
  552.  
  553. /* On systems with waitpid() (i.e. those that support WNOHANG) we must
  554.    loop until there are no more processes, because some of those
  555.    systems may deliver only one SIGCHLD when more than one child
  556.    terminates.  Systems without waitpid() (e.g. System V) typically
  557.    provide queuing of SIGCHLD such that one SIGCHLD is delivered for
  558.    every child that terminates.  Systems that provide neither
  559.    waitpid() nor queuing are so losing that we can't win, in which
  560.    case we just hope that child terminations don't happen too close to
  561.    one another to cause problems. */
  562.  
  563. void EXFUN ((*subprocess_death_hook), (pid_t pid, int * status));
  564.  
  565. #ifdef HAVE_WAITPID
  566. #define WAITPID(status) (UX_waitpid ((-1), (status), (WNOHANG | WUNTRACED)))
  567. #define BREAK
  568. #else
  569. #define WAITPID(status) (UX_wait (status))
  570. #define BREAK break
  571. #endif
  572.  
  573. static
  574. DEFUN_STD_HANDLER (sighnd_dead_subprocess,
  575. {
  576.   while (1)
  577.     {
  578.       int status;
  579.       pid_t pid = (WAITPID (&status));
  580.       if (pid <= 0)
  581.     break;
  582.       if (subprocess_death_hook != 0)
  583.     (*subprocess_death_hook) (pid, (&status));
  584.       BREAK;
  585.     }
  586. })
  587.  
  588. /* Signal Bindings */
  589.  
  590. static void
  591. DEFUN (bind_handler, (signo, handler),
  592.        int signo AND
  593.        Tsignal_handler handler)
  594. {
  595.   Tsignal_handler
  596.     old_handler = ((signo == 0) ? SIG_DFL : (current_handler (signo)));
  597.  
  598.   if ((signo != 0) 
  599.       && ((old_handler == SIG_DFL)
  600.       || ((old_handler == SIG_IGN) && (signo == SIGCHLD)))
  601.       && ((handler != ((Tsignal_handler) sighnd_stop))
  602.       || (UX_SC_JOB_CONTROL ())))
  603.     INSTALL_HANDLER (signo, handler);
  604. }
  605.  
  606. static void
  607. DEFUN_VOID (unblock_all_signals)
  608. {
  609.   /* Force the signal mask to be empty. */
  610. #ifdef HAVE_POSIX_SIGNALS
  611.   {
  612.     sigset_t empty_mask;
  613.     UX_sigemptyset (&empty_mask);
  614.     UX_sigprocmask (SIG_SETMASK, (&empty_mask), 0);
  615.   }
  616. #else
  617. #ifdef HAVE_SIGHOLD
  618.   /* We could do something more here, but it is hard to enumerate all
  619.      the possible signals.  Instead, just release SIGCHLD, which we
  620.      know was held before the child was spawned. */
  621.   UX_sigrelse (SIGCHLD);
  622. #endif
  623. #endif
  624. }
  625.  
  626. void
  627. DEFUN_VOID (UX_initialize_signals)
  628. {
  629.   stop_signal_hook = 0;
  630.   subprocess_death_hook = 0;
  631.   initialize_signal_descriptors ();
  632.   initialize_signal_debugging ();
  633.   bind_handler (SIGINT,        sighnd_control_g);
  634.   bind_handler (SIGFPE,        sighnd_fpe);
  635.   bind_handler (SIGALRM,    sighnd_timer);
  636.   bind_handler (SIGVTALRM,    sighnd_timer);
  637.   bind_handler (SIGUSR1,    sighnd_save_then_terminate);
  638. #ifdef HAVE_NICE
  639.   bind_handler (SIGUSR2,    sighnd_renice);
  640. #endif
  641.   bind_handler (SIGCHLD,    sighnd_dead_subprocess);
  642.   /* If this signal is ignored, then the system call that would have
  643.      caused it will return EPIPE instead.  This is much easier for us
  644.      to handle. */
  645.   bind_handler (SIGPIPE,    SIG_IGN);
  646.   if ((isatty (STDIN_FILENO)) || option_emacs_subprocess)
  647.     {
  648.       if (getenv ("USE_SCHEMATIK_STYLE_INTERRUPTS"))
  649.         bind_handler (SIGHUP,   sighnd_control_b);
  650.       else if (!option_emacs_subprocess)
  651.     bind_handler (SIGHUP,    sighnd_save_then_terminate);
  652.       if (getenv ("USE_SCHEMATIK_STYLE_INTERRUPTS"))
  653.         bind_handler (SIGQUIT,  sighnd_control_u);
  654.       else
  655.         bind_handler (SIGQUIT,    sighnd_interactive);
  656.       bind_handler (SIGPWR,    sighnd_save_then_terminate);
  657.       bind_handler (SIGTSTP,    sighnd_stop);
  658.       bind_handler (SIGILL,    sighnd_hardware_trap);
  659.       bind_handler (SIGTRAP,    sighnd_hardware_trap);
  660.       bind_handler (SIGBUS,    sighnd_hardware_trap);
  661.       bind_handler (SIGSEGV,    sighnd_hardware_trap);
  662.       if (getenv ("USE_SCHEMATIK_STYLE_INTERRUPTS"))
  663.         bind_handler (SIGIOT,   sighnd_control_x);
  664.       else
  665.         bind_handler (SIGIOT,    sighnd_software_trap);
  666.       bind_handler (SIGEMT,    sighnd_software_trap);
  667.       bind_handler (SIGSYS,    sighnd_software_trap);
  668.       bind_handler (SIGABRT,    sighnd_software_trap);
  669.       bind_handler (SIGPROF,    sighnd_software_trap);
  670.     }
  671.   {
  672.     struct signal_descriptor * scan = signal_descriptors;
  673.     struct signal_descriptor * end = (scan + signal_descriptors_length);
  674.     while (scan < end)
  675.       {
  676.     if (((scan -> flags) & NOCATCH) == 0)
  677.       switch (scan -> action)
  678.         {
  679.         case dfl_terminate:
  680.           bind_handler ((scan -> signo), sighnd_terminate);
  681.           break;
  682.         case dfl_stop:
  683.           bind_handler ((scan -> signo), sighnd_stop);
  684.           break;
  685.         case dfl_ignore:
  686.           break;
  687.         }
  688.     scan += 1;
  689.       }
  690.   }
  691.   unblock_all_signals ();
  692. }
  693.  
  694. /* Initialize the signals in a child subprocess.  */
  695.  
  696. void
  697. DEFUN_VOID (UX_initialize_child_signals)
  698. {
  699.   unblock_all_signals ();
  700.   /* SIGPIPE was ignored above; we must set it back to the default
  701.      because some programs depend on this.  */
  702.   INSTALL_HANDLER (SIGPIPE, SIG_DFL);
  703. }
  704.  
  705. /* Interactive Interrupt Handler */
  706.  
  707. /* Under Unix, the interrupt char is NOT requested when the interrupt is
  708.    taken.
  709.  */
  710. cc_t
  711. DEFUN (OS_tty_map_interrupt_char, (int_char), cc_t int_char)
  712. {
  713.   return int_char;
  714. }
  715.  
  716. static void EXFUN (print_interactive_help, (void));
  717. static void EXFUN (print_interrupt_chars, (void));
  718. static void EXFUN (examine_memory, (void));
  719. static void EXFUN (reset_query, (struct FULL_SIGCONTEXT * scp));
  720. static void EXFUN (interactive_back_trace, (void));
  721.  
  722. #define INTERACTIVE_NEWLINE()                        \
  723. {                                    \
  724.   if (!option_emacs_subprocess)                        \
  725.     {                                    \
  726.       putc ('\n', stdout);                        \
  727.       fflush (stdout);                            \
  728.     }                                    \
  729. }
  730.  
  731. static void
  732. DEFUN (interactive_interrupt_handler, (scp), struct FULL_SIGCONTEXT * scp)
  733. {
  734.   if (!option_emacs_subprocess)
  735.     {
  736.       fputs ((OS_tty_command_beep ()), stdout);
  737.       putc ('\n', stdout);
  738.       fflush (stdout);
  739.     }
  740.   while (1)
  741.     {
  742.       if (!option_emacs_subprocess)
  743.     {
  744.       fprintf (stdout, "Interrupt option (? for help): ");
  745.       fflush (stdout);
  746.     }
  747.       switch (userio_read_char_raw ())
  748.     {
  749.     case '\002':        /* C-B */
  750.     case 'B':
  751.     case 'b':
  752.       tty_set_next_interrupt_char (CONTROL_B_INTERRUPT_CHAR);
  753.       return;
  754.     case '\003':        /* C-C */
  755.     case '\007':        /* C-G */
  756.     case 'G':
  757.     case 'g':
  758.       tty_set_next_interrupt_char (CONTROL_G_INTERRUPT_CHAR);
  759.       return;
  760.     case '\025':        /* C-U */
  761.     case 'U':
  762.     case 'u':
  763.       tty_set_next_interrupt_char (CONTROL_U_INTERRUPT_CHAR);
  764.       return;
  765.     case '\030':        /* C-X */
  766.     case 'X':
  767.     case 'x':
  768.       tty_set_next_interrupt_char (CONTROL_X_INTERRUPT_CHAR);
  769.       return;
  770.     case 'E':
  771.     case 'e':
  772.       INTERACTIVE_NEWLINE ();
  773.       examine_memory ();
  774.       return;
  775.     case 'D':
  776.     case 'd':
  777.       INTERACTIVE_NEWLINE ();
  778.       debug_edit_flags ();
  779.       return;
  780.     case 'T':
  781.     case 't':
  782.       INTERACTIVE_NEWLINE ();
  783.       interactive_back_trace ();
  784.       return;
  785.     case 'Z':
  786.     case 'z':
  787.       INTERACTIVE_NEWLINE ();
  788.       OS_restartable_exit ();
  789.       return;
  790.     case 'Q':
  791.     case 'q':
  792.       INTERACTIVE_NEWLINE ();
  793.       termination_normal (0);
  794.       return;
  795.     case '\f':
  796.       if (!option_emacs_subprocess)
  797.         {
  798.           fputs ((OS_tty_command_clear ()), stdout);
  799.           fflush (stdout);
  800.         }
  801.       return;
  802.     case 'R':
  803.     case 'r':
  804.       reset_query (scp);
  805.       return;
  806.     case 'H':
  807.     case 'h':
  808.       if (!option_emacs_subprocess)
  809.         print_interrupt_chars ();
  810.       break;
  811.     case 'I':
  812.     case 'i':
  813.       if (!option_emacs_subprocess)
  814.         {
  815.           fputs ("Ignored.  Resuming Scheme.\n", stdout);
  816.           fflush (stdout);
  817.         }
  818.       return;
  819.     case '\0':        /* C-@ */
  820.       if (errno != 0)
  821.       {
  822.         /* IO problems, assume everything scrod. */
  823.         fprintf (stderr, "Problems reading keyboard input -- Exitting.\n");
  824.         termination_eof ();
  825.       }
  826.     default:
  827.       if (!option_emacs_subprocess)
  828.         print_interactive_help ();
  829.       break;
  830.     }
  831.     }
  832. }
  833.  
  834. static enum interrupt_handler
  835. DEFUN (encode_interrupt_handler, (handler), Tsignal_handler handler)
  836. {
  837.   return
  838.     ((handler == ((Tsignal_handler) sighnd_control_g))
  839.      ? interrupt_handler_control_g
  840.      : (handler == ((Tsignal_handler) sighnd_interactive))
  841.      ? interrupt_handler_interactive
  842.      : (handler == ((Tsignal_handler) sighnd_stop))
  843.      ? interrupt_handler_stop
  844.      : (handler == ((Tsignal_handler) sighnd_terminate))
  845.      ? interrupt_handler_terminate
  846.      : (handler == ((Tsignal_handler) SIG_IGN))
  847.      ? interrupt_handler_ignore
  848.      : (handler == ((Tsignal_handler) SIG_DFL))
  849.      ? interrupt_handler_default
  850.      : interrupt_handler_unknown);
  851. }
  852.  
  853. static Tsignal_handler
  854. DEFUN (decode_interrupt_handler, (encoding), enum interrupt_handler encoding)
  855. {
  856.   return
  857.     ((encoding == interrupt_handler_control_g)
  858.      ? ((Tsignal_handler) sighnd_control_g)
  859.      : (encoding == interrupt_handler_interactive)
  860.      ? ((Tsignal_handler) sighnd_interactive)
  861.      : (encoding == interrupt_handler_stop)
  862.      ? ((Tsignal_handler) sighnd_stop)
  863.      : (encoding == interrupt_handler_terminate)
  864.      ? ((Tsignal_handler) sighnd_terminate)
  865.      : (encoding == interrupt_handler_ignore)
  866.      ? ((Tsignal_handler) SIG_IGN)
  867.      : (encoding == interrupt_handler_default)
  868.      ? ((Tsignal_handler) SIG_DFL)
  869.      : ((Tsignal_handler) 0));
  870. }
  871.  
  872. enum interrupt_handler
  873. DEFUN_VOID (OS_signal_quit_handler)
  874. {
  875.   return (encode_interrupt_handler (current_handler (SIGQUIT)));
  876. }
  877.  
  878. enum interrupt_handler
  879. DEFUN_VOID (OS_signal_int_handler)
  880. {
  881.   return (encode_interrupt_handler (current_handler (SIGINT)));
  882. }
  883.  
  884. enum interrupt_handler
  885. DEFUN_VOID (OS_signal_tstp_handler)
  886. {
  887.   return
  888.     ((UX_SC_JOB_CONTROL ())
  889.      ? (encode_interrupt_handler (current_handler (SIGTSTP)))
  890.      : interrupt_handler_ignore);
  891. }
  892.  
  893. void
  894. DEFUN (OS_signal_set_interrupt_handlers,
  895.        (quit_handler, int_handler, tstp_handler),
  896.        enum interrupt_handler quit_handler AND
  897.        enum interrupt_handler int_handler AND
  898.        enum interrupt_handler tstp_handler)
  899. {
  900.   {
  901.     Tsignal_handler handler = (decode_interrupt_handler (quit_handler));
  902.     if (handler != 0)
  903.       INSTALL_HANDLER (SIGQUIT, handler);
  904.   }
  905.   {
  906.     Tsignal_handler handler = (decode_interrupt_handler (int_handler));
  907.     if (handler != 0)
  908.       INSTALL_HANDLER (SIGINT, handler);
  909.   }
  910.   if (UX_SC_JOB_CONTROL ())
  911.     {
  912.       Tsignal_handler handler = (decode_interrupt_handler (tstp_handler));
  913.       if (handler != 0)
  914.     INSTALL_HANDLER (SIGTSTP, handler);
  915.     }
  916. }
  917.  
  918. static void
  919. DEFUN (describe_sighnd, (signo, c), int signo AND unsigned char c)
  920. {
  921.   switch (encode_interrupt_handler (current_handler (signo)))
  922.     {
  923.     case interrupt_handler_control_g:
  924.       fputs ("When typed, scheme will get the ^G character interrupt.\n",
  925.          stdout);
  926.       fputs ("The default action is to abort the running program,\n", stdout);
  927.       fputs ("and to resume the top level read-eval-print loop.\n", stdout);
  928.       break;
  929.     case interrupt_handler_interactive:
  930.       fputs ("When typed, various interrupt options are offered.\n", stdout);
  931.       fprintf (stdout, "Type %s followed by `?' for a list of options.\n",
  932.            (char_description (c, 0)));
  933.       break;
  934.     case interrupt_handler_terminate:
  935.     describe_terminate:
  936.       fputs ("When typed, scheme will terminate.\n", stdout);
  937.       break;
  938.     case interrupt_handler_stop:
  939.     describe_stop:
  940.       fputs ("When typed, scheme will suspend execution.\n", stdout);
  941.       break;
  942.     case interrupt_handler_ignore:
  943.     describe_ignore:
  944.       fputs ("When typed, this character will be ignored.\n", stdout);
  945.       break;
  946.     case interrupt_handler_default:
  947.       {
  948.     struct signal_descriptor * descriptor =
  949.       (find_signal_descriptor (signo));
  950.     if (descriptor != 0)
  951.       switch (descriptor -> action)
  952.         {
  953.         case dfl_ignore: goto describe_ignore;
  954.         case dfl_stop: goto describe_stop;
  955.         case dfl_terminate: goto describe_terminate;
  956.         }
  957.       }
  958.     default:
  959.       fputs ("When typed, this character will have an unknown effect.\n",
  960.          stdout);
  961.       break;
  962.     }
  963. }
  964.  
  965. static void
  966. DEFUN_VOID (print_interrupt_chars)
  967. {
  968.   {
  969.     unsigned char quit_char = (OS_ctty_quit_char ());
  970.     fprintf (stdout, "\n\nThe quit character is %s.\n",
  971.          (char_description (quit_char, 1)));
  972.     describe_sighnd (SIGQUIT, quit_char);
  973.   }
  974.   {
  975.     unsigned char int_char = (OS_ctty_int_char ());
  976.     fprintf (stdout, "\nThe interrupt character is %s.\n",
  977.          (char_description (int_char, 1)));
  978.     describe_sighnd (SIGINT, int_char);
  979.   }
  980.   if (UX_SC_JOB_CONTROL ())
  981.     {
  982.       unsigned char tstp_char = (OS_ctty_tstp_char ());
  983.       fprintf (stdout, "\nThe terminal stop character is %s.\n",
  984.            (char_description (tstp_char, 1)));
  985.       describe_sighnd (SIGTSTP, tstp_char);
  986.     }
  987.   putc ('\n', stdout);
  988.   fflush (stdout);
  989. }
  990.  
  991. static void
  992. DEFUN_VOID (print_interactive_help)
  993. {
  994.   fputs ("\n\n", stdout);
  995.   fputs ("^B: Enter a breakpoint loop.\n", stdout);
  996.   fputs ("^C: Goto to top level read-eval-print (REP) loop.\n", stdout);
  997.   fputs ("^L: Clear the screen.\n", stdout);
  998.   fputs ("^U: Up to previous (lower numbered) REP loop.\n", stdout);
  999.   fputs ("^X: Abort to current REP loop.\n", stdout);
  1000.   fputs ("D: Debugging: change interpreter flags.\n", stdout);
  1001.   fputs ("E: Examine memory location.\n", stdout);
  1002.   fputs ("H: Print simple information on interrupts.\n", stdout);
  1003.   fputs ("I: Ignore interrupt request.\n", stdout);
  1004.   fputs ("Q: Quit instantly, killing Scheme.\n", stdout);
  1005.   fputs ("R: Hard reset, possibly killing Scheme in the process.\n", stdout);
  1006.   fputs ("T: Stack trace.\n", stdout);
  1007.   if (UX_SC_JOB_CONTROL ())
  1008.     fputs ("Z: Quit instantly, suspending Scheme.\n", stdout);
  1009.   fputs ("\n", stdout);
  1010. }
  1011.  
  1012. static void
  1013. DEFUN (invoke_soft_reset, (name), char * name)
  1014. {
  1015.   soft_reset ();
  1016.   /*NOTREACHED*/
  1017. }
  1018.  
  1019. static void
  1020. DEFUN (reset_query, (scp), struct FULL_SIGCONTEXT * scp)
  1021. {
  1022.   putc ('\n', stdout);
  1023.   fflush (stdout);
  1024.   if (WITHIN_CRITICAL_SECTION_P ())
  1025.     {
  1026.       static CONST char * reset_choices [] =
  1027.     {
  1028.       "D = delay reset until the end of the critical section",
  1029.       "N = attempt reset now",
  1030.       "P = punt reset",
  1031.       0
  1032.       };
  1033.       fprintf (stdout,
  1034.            "Scheme is executing within critical section \"%s\".\n",
  1035.            (CRITICAL_SECTION_NAME ()));
  1036.       fputs ("Resetting now is likely to kill Scheme.\n", stdout);
  1037.       fflush (stdout);
  1038.       switch (userio_choose_option
  1039.           ("Choose one of the following actions:",
  1040.            "Action -> ",
  1041.            reset_choices))
  1042.     {
  1043.     case '\0':
  1044.       /* IO problems, assume everything scrod. */
  1045.       fprintf (stderr, "Problems reading keyboard input -- exitting.\n");
  1046.       termination_eof ();
  1047.     case 'D':
  1048.       SET_CRITICAL_SECTION_HOOK (invoke_soft_reset);
  1049.       return;
  1050.     case 'N':
  1051.       CLEAR_CRITICAL_SECTION_HOOK ();
  1052.       EXIT_CRITICAL_SECTION ({});
  1053.       hard_reset (scp);
  1054.     case 'P':
  1055.     default:
  1056.       return;
  1057.     }
  1058.     }
  1059.   if (userio_confirm ("Do you really want to reset? [Y or N] "))
  1060.     hard_reset (scp);
  1061. }
  1062.  
  1063. #define USERIO_READ_LINE_OK        0
  1064. #define USERIO_READ_LINE_TOO_LONG    1
  1065. #define USERIO_READ_LINE_INPUT_FAILED    2
  1066.  
  1067. static int
  1068. DEFUN (userio_read_line, (line, size), char * line AND int size)
  1069. {
  1070.   int result = USERIO_READ_LINE_TOO_LONG;
  1071.   transaction_begin ();
  1072.   userio_buffered_input ();    /* transaction_record_action here */
  1073.   {
  1074.     char * scan = line;
  1075.     char * end = (line + size);
  1076.     while (scan < end)
  1077.     {
  1078.       char c = (userio_read_char ());
  1079.       if ((c == '\0') && (errno != 0))
  1080.       {
  1081.     /* IO problems, assume everything scrod. */
  1082.     result = USERIO_READ_LINE_INPUT_FAILED;
  1083.     break;
  1084.       }
  1085.       if (c == '\n')
  1086.     c = '\0';
  1087.       (*scan) = c;
  1088.       if (c == '\0')
  1089.       {
  1090.     result = USERIO_READ_LINE_OK;
  1091.     break;
  1092.       }
  1093.       scan += 1;
  1094.     }
  1095.   }
  1096.   transaction_commit ();
  1097.   return (result);
  1098. }
  1099.  
  1100. static void
  1101. DEFUN_VOID (examine_memory)
  1102. {
  1103.   char input_string [256];
  1104.   fputs ("Enter location to examine (0x prefix for hex): ", stdout);
  1105.   fflush (stdout);
  1106.   if ((userio_read_line (&input_string[0], (sizeof (input_string))))
  1107.       == USERIO_READ_LINE_INPUT_FAILED)
  1108.   {
  1109.     fprintf (stderr, "Problems reading keyboard input -- exiting.\n");
  1110.     termination_eof ();
  1111.   }
  1112.   {
  1113.     long input;
  1114.     if (((((input_string[0]) == '0') && ((input_string[1]) == 'x'))
  1115.      ? (sscanf ((&input_string[2]), "%lx", (&input)))
  1116.      : (sscanf (input_string, "%ld", (&input))))
  1117.     == 1)
  1118.       debug_examine_memory (input, "contents");
  1119.   }
  1120.   putc ('\n', stdout);
  1121.   fflush (stdout);
  1122. }
  1123.  
  1124. void
  1125. DEFUN (eta_fclose, (stream), PTR stream)
  1126. {
  1127.   (void) (fclose ((FILE *) stream));
  1128.   return;
  1129. }
  1130.  
  1131. static void
  1132. DEFUN_VOID (interactive_back_trace)
  1133. {
  1134.   char input_string [256];
  1135.   fputs ("Enter the stack trace filename (default: terminal): ", stdout);
  1136.   fflush (stdout);
  1137.   if ((userio_read_line (&input_string[0], (sizeof (input_string))))
  1138.       == USERIO_READ_LINE_INPUT_FAILED)
  1139.   {
  1140.     fprintf (stderr, "Problems reading keyboard input -- exiting.\n");
  1141.     termination_eof ();
  1142.   }
  1143.   INTERACTIVE_NEWLINE ();
  1144.   if ((strlen (&input_string[0])) == 0)
  1145.     debug_back_trace (console_output);
  1146.   else
  1147.   {
  1148.     transaction_begin ();
  1149.     {
  1150.       FILE * to_dump = (fopen (&input_string[0], "w"));
  1151.       if (to_dump == ((FILE *) NULL))
  1152.       {
  1153.     outf_error ("Error opening \"%s\".\n", (&input_string[0]));
  1154.     transaction_abort ();
  1155.     return;
  1156.       }
  1157.       transaction_record_action (tat_always,
  1158.                  eta_fclose,
  1159.                  ((PTR) to_dump));
  1160.       outf_console ("Writing the stack trace to file \"%s\" -- ",
  1161.                     &input_string[0]);
  1162.       outf_flush_console ();
  1163.       debug_back_trace ((outf_channel) to_dump);
  1164.       outf_console ("Done.\n");
  1165.       outf_flush_console ();
  1166.     }
  1167.     transaction_commit ();
  1168.   }
  1169.   return;
  1170. }
  1171.  
  1172. #ifdef sun3
  1173.  
  1174. /* This code assumes that it is called very soon, before
  1175.    any registers except fp have been clobbered.
  1176.  
  1177.    It also assumes that it is called directly by the
  1178.    handler, so that the original fp can be found
  1179.    by indirecting through fp twice.
  1180.  
  1181.    The trampoline routine saves d0, d1, a0, and a1
  1182.    before invoking the handler.
  1183.  
  1184.    The magic constant of 276 was found by poking with adb. */
  1185.  
  1186. static void
  1187. DEFUN (sun3_save_regs, (regs), int * regs)
  1188. {
  1189.   asm ("\n\
  1190.     movel    a6@(8),a0\n\
  1191.     movel    a6@,a1\n\
  1192. \n\
  1193.     movel    a1@(276),a0@\n\
  1194.     movel    a1@(280),a0@(4)\n\
  1195.     movel    d2,a0@(8)\n\
  1196.     movel    d3,a0@(12)\n\
  1197.     movel    d4,a0@(16)\n\
  1198.     movel    d5,a0@(20)\n\
  1199.     movel    d6,a0@(24)\n\
  1200.     movel    d7,a0@(28)\n\
  1201. \n\
  1202.     movel    a1@(284),a0@(32)\n\
  1203.     movel    a1@(288),a0@(36)\n\
  1204.     movel    a2,a0@(40)\n\
  1205.     movel    a3,a0@(44)\n\
  1206.     movel    a4,a0@(48)\n\
  1207.     movel    a5,a0@(52)\n\
  1208.     movel    a1@,a0@(56)\n\
  1209.     ");
  1210. }
  1211.  
  1212. #endif /* sun3 */
  1213.  
  1214. #ifdef vax
  1215.  
  1216. static int
  1217. DEFUN_VOID (vax_get_r0)
  1218. {
  1219.   /* This is a kludge. It relies on r0 being the return value register. */
  1220.   asm ("ret");
  1221. }
  1222.  
  1223. static int *
  1224. DEFUN (vax_save_start, (regs, r0), int * regs AND int r0)
  1225. {
  1226.   asm ("movl    fp,-(sp)");
  1227.   asm ("movl    4(ap),fp");
  1228.   asm ("movl    8(ap),(fp)");
  1229.   asm ("movl    r1,4(fp)");
  1230.   asm ("movl    r2,8(fp)");
  1231.   asm ("movl    r3,12(fp)");
  1232.   asm ("movl    r4,16(fp)");
  1233.   asm ("movl    r5,20(fp)");
  1234.   asm ("movl    r6,24(fp)");
  1235.   asm ("movl    r7,28(fp)");
  1236.   asm ("movl    r8,32(fp)");
  1237.   asm ("movl    r9,36(fp)");
  1238.   asm ("movl    r10,40(fp)");
  1239.   asm ("movl    r11,44(fp)");
  1240.   asm ("movl    (sp)+,fp");
  1241.   asm ("movl    12(fp),r0");
  1242.   asm ("ret");
  1243. }
  1244.  
  1245. static void
  1246. DEFUN (vax_save_finish, (fp, pscp, scp),
  1247.        int * fp AND
  1248.        struct sigcontext * pscp AND
  1249.        struct full_sigcontext * scp)
  1250. {
  1251.   (scp -> fs_original) = pscp;
  1252. #ifndef _ULTRIX
  1253.   /* For now, ap and fp undefined. */
  1254.   ((scp -> fs_regs) [12]) = (pscp -> sc_ap);
  1255.   ((scp -> fs_regs) [13]) = (pscp -> sc_fp);
  1256. #endif
  1257.   ((scp -> fs_regs) [14]) = (pscp -> sc_sp);
  1258.   ((scp -> fs_regs) [15]) = (pscp -> sc_pc);
  1259.   {
  1260.     int reg_number = 0;
  1261.     unsigned long reg_mask = (((fp[1]) >> 16) & 0x0fff);
  1262.     int stack_index = 5;
  1263.     while (reg_mask != 0)
  1264.       {
  1265.     if ((reg_mask & 1) != 0)
  1266.       ((scp -> fs_regs) [reg_number]) = (fp[stack_index++]);
  1267.     reg_number += 1;
  1268.     reg_mask = ((reg_mask >> 1) & 0x0fff);
  1269.       }
  1270.   }
  1271. }
  1272.  
  1273. #endif /* vax */
  1274.  
  1275. #if defined(sonyrisc) && defined(HAVE_GRANTPT)
  1276. /* Sony NEWS-OS 5.0.2 has a nasty bug because `sigaction' maintains a
  1277.    table which contains the signal handlers, and passes
  1278.    `sigaction_handler' to the kernel in place of any handler's
  1279.    address.  Unfortunately, `signal' doesn't know about this table, so
  1280.    it returns `sigaction_handler' as its value, which can subsequently
  1281.    get passed back to `sigaction' and stored in the table.  Once
  1282.    stored in the table, this causes an infinite recursion, which kills
  1283.    the process (with SIGSEGV) when the stack exceeds the allowable
  1284.    amount of virtual memory.
  1285.  
  1286.    This problem would not be an issue, because Scheme deliberately
  1287.    doesn't mix the use of `sigaction' with `signal', except that the
  1288.    last release of 5.0.2 (baseline 31.1) calls `signal' from
  1289.    `grantpt'.  So, the following patch overrides the built-in version
  1290.    of `signal' with one that coexists safely with `sigaction'.
  1291.  
  1292.    This is not a "correct" implementation of `signal' -- it is one
  1293.    that reinstalls the handlers using the same options that we do in
  1294.    this file.  */
  1295.  
  1296. Tsignal_handler
  1297. DEFUN (signal, (signo, handler),
  1298.        int signo AND
  1299.        Tsignal_handler handler)
  1300. {
  1301.   struct sigaction act;
  1302.   struct sigaction oact;
  1303.  
  1304.   (act . sa_handler) = handler;
  1305.   UX_sigemptyset (& (act . sa_mask));
  1306.   (act . sa_flags) = (SA_RESETHAND | SA_NODEFER);
  1307.   if (handler == SIG_IGN)
  1308.     (act . sa_flags) |= SA_NOCLDWAIT;
  1309.   if ((UX_sigaction (signo, (&act), (&oact))) < 0)
  1310.     return (SIG_ERR);
  1311.   else
  1312.     return (oact . sa_handler);
  1313. }
  1314.  
  1315. /* It is best to reinstall the SIGCHLD handler after `grantpt' is
  1316.    called because that guarantees that the flags are correct.  */
  1317.  
  1318. void
  1319. DEFUN_VOID (sony_block_sigchld)
  1320. {
  1321.   sighold (SIGCHLD);
  1322. }
  1323.  
  1324. void
  1325. DEFUN_VOID (sony_unblock_sigchld)
  1326. {
  1327.   INSTALL_HANDLER (SIGCHLD, sighnd_dead_subprocess);
  1328.   sigrelse (SIGCHLD);
  1329. }
  1330.  
  1331. #endif /* sonyrisc and HAVE_GRANTPT */
  1332.