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