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