xref: /openbsd-src/gnu/lib/libreadline/signals.c (revision 9704b281e65e1189747652d0ba55eee892cff5f7)
11acd27e7Smillert /* signals.c -- signal handling support for readline. */
21acd27e7Smillert 
31acd27e7Smillert /* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
41acd27e7Smillert 
51acd27e7Smillert    This file is part of the GNU Readline Library, a library for
61acd27e7Smillert    reading lines of text with interactive input and history editing.
71acd27e7Smillert 
81acd27e7Smillert    The GNU Readline Library is free software; you can redistribute it
91acd27e7Smillert    and/or modify it under the terms of the GNU General Public License
101acd27e7Smillert    as published by the Free Software Foundation; either version 2, or
111acd27e7Smillert    (at your option) any later version.
121acd27e7Smillert 
131acd27e7Smillert    The GNU Readline Library is distributed in the hope that it will be
141acd27e7Smillert    useful, but WITHOUT ANY WARRANTY; without even the implied warranty
151acd27e7Smillert    of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
161acd27e7Smillert    GNU General Public License for more details.
171acd27e7Smillert 
181acd27e7Smillert    The GNU General Public License is often shipped with GNU software, and
191acd27e7Smillert    is generally kept in a file called COPYING or LICENSE.  If you do not
201acd27e7Smillert    have a copy of the license, write to the Free Software Foundation,
211acd27e7Smillert    59 Temple Place, Suite 330, Boston, MA 02111 USA. */
221acd27e7Smillert #define READLINE_LIBRARY
231acd27e7Smillert 
241acd27e7Smillert #if defined (HAVE_CONFIG_H)
251acd27e7Smillert #  include <config.h>
261acd27e7Smillert #endif
271acd27e7Smillert 
281acd27e7Smillert #include <stdio.h>		/* Just for NULL.  Yuck. */
291acd27e7Smillert #include <sys/types.h>
301acd27e7Smillert #include <signal.h>
311acd27e7Smillert 
321acd27e7Smillert #if defined (HAVE_UNISTD_H)
331acd27e7Smillert #  include <unistd.h>
341acd27e7Smillert #endif /* HAVE_UNISTD_H */
351acd27e7Smillert 
361acd27e7Smillert /* System-specific feature definitions and include files. */
371acd27e7Smillert #include "rldefs.h"
381acd27e7Smillert 
391acd27e7Smillert #if defined (GWINSZ_IN_SYS_IOCTL)
401acd27e7Smillert #  include <sys/ioctl.h>
411acd27e7Smillert #endif /* GWINSZ_IN_SYS_IOCTL */
421acd27e7Smillert 
431acd27e7Smillert #if defined (HANDLE_SIGNALS)
441acd27e7Smillert /* Some standard library routines. */
451acd27e7Smillert #include "readline.h"
461acd27e7Smillert #include "history.h"
471acd27e7Smillert 
481acd27e7Smillert #include "rlprivate.h"
491acd27e7Smillert 
501acd27e7Smillert #if !defined (RETSIGTYPE)
511acd27e7Smillert #  if defined (VOID_SIGHANDLER)
521acd27e7Smillert #    define RETSIGTYPE void
531acd27e7Smillert #  else
541acd27e7Smillert #    define RETSIGTYPE int
551acd27e7Smillert #  endif /* !VOID_SIGHANDLER */
561acd27e7Smillert #endif /* !RETSIGTYPE */
571acd27e7Smillert 
581acd27e7Smillert #if defined (VOID_SIGHANDLER)
591acd27e7Smillert #  define SIGHANDLER_RETURN return
601acd27e7Smillert #else
611acd27e7Smillert #  define SIGHANDLER_RETURN return (0)
621acd27e7Smillert #endif
631acd27e7Smillert 
64*15b117eaSkettenis /* This typedef is equivalent to the one for Function; it allows us
651acd27e7Smillert    to say SigHandler *foo = signal (SIGKILL, SIG_IGN); */
661acd27e7Smillert typedef RETSIGTYPE SigHandler ();
671acd27e7Smillert 
681acd27e7Smillert #if defined (HAVE_POSIX_SIGNALS)
691acd27e7Smillert typedef struct sigaction sighandler_cxt;
701acd27e7Smillert #  define rl_sigaction(s, nh, oh)	sigaction(s, nh, oh)
711acd27e7Smillert #else
721acd27e7Smillert typedef struct { SigHandler *sa_handler; int sa_mask, sa_flags; } sighandler_cxt;
731acd27e7Smillert #  define sigemptyset(m)
741acd27e7Smillert #endif /* !HAVE_POSIX_SIGNALS */
751acd27e7Smillert 
76*15b117eaSkettenis static SigHandler *rl_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *));
77*15b117eaSkettenis static void rl_maybe_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *));
781acd27e7Smillert 
791acd27e7Smillert /* Exported variables for use by applications. */
801acd27e7Smillert 
811acd27e7Smillert /* If non-zero, readline will install its own signal handlers for
821acd27e7Smillert    SIGINT, SIGTERM, SIGQUIT, SIGALRM, SIGTSTP, SIGTTIN, and SIGTTOU. */
831acd27e7Smillert int rl_catch_signals = 1;
841acd27e7Smillert 
851acd27e7Smillert /* If non-zero, readline will install a signal handler for SIGWINCH. */
861acd27e7Smillert #ifdef SIGWINCH
871acd27e7Smillert int rl_catch_sigwinch = 1;
881acd27e7Smillert #endif
891acd27e7Smillert 
901acd27e7Smillert static int signals_set_flag;
911acd27e7Smillert static int sigwinch_set_flag;
921acd27e7Smillert 
931acd27e7Smillert /* **************************************************************** */
941acd27e7Smillert /*								    */
951acd27e7Smillert /*			   Signal Handling                          */
961acd27e7Smillert /*								    */
971acd27e7Smillert /* **************************************************************** */
981acd27e7Smillert 
991acd27e7Smillert static sighandler_cxt old_int, old_term, old_alrm, old_quit;
1001acd27e7Smillert #if defined (SIGTSTP)
1011acd27e7Smillert static sighandler_cxt old_tstp, old_ttou, old_ttin;
1021acd27e7Smillert #endif
1031acd27e7Smillert #if defined (SIGWINCH)
1041acd27e7Smillert static sighandler_cxt old_winch;
1051acd27e7Smillert #endif
1061acd27e7Smillert 
1071acd27e7Smillert /* Readline signal handler functions. */
1081acd27e7Smillert 
1091acd27e7Smillert static RETSIGTYPE
rl_signal_handler(sig)1101acd27e7Smillert rl_signal_handler (sig)
1111acd27e7Smillert      int sig;
1121acd27e7Smillert {
1131acd27e7Smillert #if defined (HAVE_POSIX_SIGNALS)
1141acd27e7Smillert   sigset_t set;
1151acd27e7Smillert #else /* !HAVE_POSIX_SIGNALS */
1161acd27e7Smillert #  if defined (HAVE_BSD_SIGNALS)
1171acd27e7Smillert   long omask;
1181acd27e7Smillert #  else /* !HAVE_BSD_SIGNALS */
1191acd27e7Smillert   sighandler_cxt dummy_cxt;	/* needed for rl_set_sighandler call */
1201acd27e7Smillert #  endif /* !HAVE_BSD_SIGNALS */
1211acd27e7Smillert #endif /* !HAVE_POSIX_SIGNALS */
1221acd27e7Smillert 
123*15b117eaSkettenis   RL_SETSTATE(RL_STATE_SIGHANDLER);
124*15b117eaSkettenis 
1251acd27e7Smillert #if !defined (HAVE_BSD_SIGNALS) && !defined (HAVE_POSIX_SIGNALS)
1261acd27e7Smillert   /* Since the signal will not be blocked while we are in the signal
1271acd27e7Smillert      handler, ignore it until rl_clear_signals resets the catcher. */
1281acd27e7Smillert   if (sig == SIGINT || sig == SIGALRM)
1291acd27e7Smillert     rl_set_sighandler (sig, SIG_IGN, &dummy_cxt);
1301acd27e7Smillert #endif /* !HAVE_BSD_SIGNALS && !HAVE_POSIX_SIGNALS */
1311acd27e7Smillert 
1321acd27e7Smillert   switch (sig)
1331acd27e7Smillert     {
1341acd27e7Smillert     case SIGINT:
1351acd27e7Smillert       rl_free_line_state ();
1361acd27e7Smillert       /* FALLTHROUGH */
1371acd27e7Smillert 
1381acd27e7Smillert #if defined (SIGTSTP)
1391acd27e7Smillert     case SIGTSTP:
1401acd27e7Smillert     case SIGTTOU:
1411acd27e7Smillert     case SIGTTIN:
1421acd27e7Smillert #endif /* SIGTSTP */
1431acd27e7Smillert     case SIGALRM:
1441acd27e7Smillert     case SIGTERM:
1451acd27e7Smillert     case SIGQUIT:
1461acd27e7Smillert       rl_cleanup_after_signal ();
1471acd27e7Smillert 
1481acd27e7Smillert #if defined (HAVE_POSIX_SIGNALS)
1491acd27e7Smillert       sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set);
1501acd27e7Smillert       sigdelset (&set, sig);
1511acd27e7Smillert #else /* !HAVE_POSIX_SIGNALS */
1521acd27e7Smillert #  if defined (HAVE_BSD_SIGNALS)
1531acd27e7Smillert       omask = sigblock (0);
1541acd27e7Smillert #  endif /* HAVE_BSD_SIGNALS */
1551acd27e7Smillert #endif /* !HAVE_POSIX_SIGNALS */
1561acd27e7Smillert 
1571acd27e7Smillert #if defined (__EMX__)
1581acd27e7Smillert       signal (sig, SIG_ACK);
1591acd27e7Smillert #endif
1601acd27e7Smillert 
1611acd27e7Smillert       kill (getpid (), sig);
1621acd27e7Smillert 
1631acd27e7Smillert       /* Let the signal that we just sent through.  */
1641acd27e7Smillert #if defined (HAVE_POSIX_SIGNALS)
1651acd27e7Smillert       sigprocmask (SIG_SETMASK, &set, (sigset_t *)NULL);
1661acd27e7Smillert #else /* !HAVE_POSIX_SIGNALS */
1671acd27e7Smillert #  if defined (HAVE_BSD_SIGNALS)
1681acd27e7Smillert       sigsetmask (omask & ~(sigmask (sig)));
1691acd27e7Smillert #  endif /* HAVE_BSD_SIGNALS */
1701acd27e7Smillert #endif /* !HAVE_POSIX_SIGNALS */
1711acd27e7Smillert 
1721acd27e7Smillert       rl_reset_after_signal ();
1731acd27e7Smillert     }
1741acd27e7Smillert 
175*15b117eaSkettenis   RL_UNSETSTATE(RL_STATE_SIGHANDLER);
1761acd27e7Smillert   SIGHANDLER_RETURN;
1771acd27e7Smillert }
1781acd27e7Smillert 
1791acd27e7Smillert #if defined (SIGWINCH)
1801acd27e7Smillert static RETSIGTYPE
rl_sigwinch_handler(sig)1811acd27e7Smillert rl_sigwinch_handler (sig)
1821acd27e7Smillert      int sig;
1831acd27e7Smillert {
1841acd27e7Smillert   SigHandler *oh;
1851acd27e7Smillert 
1861acd27e7Smillert #if defined (MUST_REINSTALL_SIGHANDLERS)
1871acd27e7Smillert   sighandler_cxt dummy_winch;
1881acd27e7Smillert 
1891acd27e7Smillert   /* We don't want to change old_winch -- it holds the state of SIGWINCH
1901acd27e7Smillert      disposition set by the calling application.  We need this state
1911acd27e7Smillert      because we call the application's SIGWINCH handler after updating
1921acd27e7Smillert      our own idea of the screen size. */
1931acd27e7Smillert   rl_set_sighandler (SIGWINCH, rl_sigwinch_handler, &dummy_winch);
1941acd27e7Smillert #endif
1951acd27e7Smillert 
196*15b117eaSkettenis   RL_SETSTATE(RL_STATE_SIGHANDLER);
1971acd27e7Smillert   rl_resize_terminal ();
1981acd27e7Smillert 
1991acd27e7Smillert   /* If another sigwinch handler has been installed, call it. */
2001acd27e7Smillert   oh = (SigHandler *)old_winch.sa_handler;
2011acd27e7Smillert   if (oh &&  oh != (SigHandler *)SIG_IGN && oh != (SigHandler *)SIG_DFL)
2021acd27e7Smillert     (*oh) (sig);
2031acd27e7Smillert 
204*15b117eaSkettenis   RL_UNSETSTATE(RL_STATE_SIGHANDLER);
2051acd27e7Smillert   SIGHANDLER_RETURN;
2061acd27e7Smillert }
2071acd27e7Smillert #endif  /* SIGWINCH */
2081acd27e7Smillert 
2091acd27e7Smillert /* Functions to manage signal handling. */
2101acd27e7Smillert 
2111acd27e7Smillert #if !defined (HAVE_POSIX_SIGNALS)
2121acd27e7Smillert static int
rl_sigaction(sig,nh,oh)2131acd27e7Smillert rl_sigaction (sig, nh, oh)
2141acd27e7Smillert      int sig;
2151acd27e7Smillert      sighandler_cxt *nh, *oh;
2161acd27e7Smillert {
2171acd27e7Smillert   oh->sa_handler = signal (sig, nh->sa_handler);
2181acd27e7Smillert   return 0;
2191acd27e7Smillert }
2201acd27e7Smillert #endif /* !HAVE_POSIX_SIGNALS */
2211acd27e7Smillert 
2221acd27e7Smillert /* Set up a readline-specific signal handler, saving the old signal
2231acd27e7Smillert    information in OHANDLER.  Return the old signal handler, like
2241acd27e7Smillert    signal(). */
2251acd27e7Smillert static SigHandler *
rl_set_sighandler(sig,handler,ohandler)2261acd27e7Smillert rl_set_sighandler (sig, handler, ohandler)
2271acd27e7Smillert      int sig;
2281acd27e7Smillert      SigHandler *handler;
2291acd27e7Smillert      sighandler_cxt *ohandler;
2301acd27e7Smillert {
2311acd27e7Smillert   sighandler_cxt old_handler;
2321acd27e7Smillert #if defined (HAVE_POSIX_SIGNALS)
2331acd27e7Smillert   struct sigaction act;
2341acd27e7Smillert 
2351acd27e7Smillert   act.sa_handler = handler;
236*15b117eaSkettenis   act.sa_flags = 0;	/* XXX - should we set SA_RESTART for SIGWINCH? */
2371acd27e7Smillert   sigemptyset (&act.sa_mask);
2381acd27e7Smillert   sigemptyset (&ohandler->sa_mask);
2391acd27e7Smillert   sigaction (sig, &act, &old_handler);
2401acd27e7Smillert #else
2411acd27e7Smillert   old_handler.sa_handler = (SigHandler *)signal (sig, handler);
2421acd27e7Smillert #endif /* !HAVE_POSIX_SIGNALS */
2431acd27e7Smillert 
2441acd27e7Smillert   /* XXX -- assume we have memcpy */
2451acd27e7Smillert   /* If rl_set_signals is called twice in a row, don't set the old handler to
2461acd27e7Smillert      rl_signal_handler, because that would cause infinite recursion. */
2471acd27e7Smillert   if (handler != rl_signal_handler || old_handler.sa_handler != rl_signal_handler)
2481acd27e7Smillert     memcpy (ohandler, &old_handler, sizeof (sighandler_cxt));
2491acd27e7Smillert 
2501acd27e7Smillert   return (ohandler->sa_handler);
2511acd27e7Smillert }
2521acd27e7Smillert 
2531acd27e7Smillert static void
rl_maybe_set_sighandler(sig,handler,ohandler)2541acd27e7Smillert rl_maybe_set_sighandler (sig, handler, ohandler)
2551acd27e7Smillert      int sig;
2561acd27e7Smillert      SigHandler *handler;
2571acd27e7Smillert      sighandler_cxt *ohandler;
2581acd27e7Smillert {
2591acd27e7Smillert   sighandler_cxt dummy;
2601acd27e7Smillert   SigHandler *oh;
2611acd27e7Smillert 
2621acd27e7Smillert   sigemptyset (&dummy.sa_mask);
2631acd27e7Smillert   oh = rl_set_sighandler (sig, handler, ohandler);
2641acd27e7Smillert   if (oh == (SigHandler *)SIG_IGN)
2651acd27e7Smillert     rl_sigaction (sig, ohandler, &dummy);
2661acd27e7Smillert }
2671acd27e7Smillert 
2681acd27e7Smillert int
rl_set_signals()2691acd27e7Smillert rl_set_signals ()
2701acd27e7Smillert {
2711acd27e7Smillert   sighandler_cxt dummy;
2721acd27e7Smillert   SigHandler *oh;
2731acd27e7Smillert 
2741acd27e7Smillert   if (rl_catch_signals && signals_set_flag == 0)
2751acd27e7Smillert     {
2761acd27e7Smillert       rl_maybe_set_sighandler (SIGINT, rl_signal_handler, &old_int);
2771acd27e7Smillert       rl_maybe_set_sighandler (SIGTERM, rl_signal_handler, &old_term);
2781acd27e7Smillert       rl_maybe_set_sighandler (SIGQUIT, rl_signal_handler, &old_quit);
2791acd27e7Smillert 
2801acd27e7Smillert       oh = rl_set_sighandler (SIGALRM, rl_signal_handler, &old_alrm);
2811acd27e7Smillert       if (oh == (SigHandler *)SIG_IGN)
2821acd27e7Smillert 	rl_sigaction (SIGALRM, &old_alrm, &dummy);
2831acd27e7Smillert #if defined (HAVE_POSIX_SIGNALS) && defined (SA_RESTART)
2841acd27e7Smillert       /* If the application using readline has already installed a signal
2851acd27e7Smillert 	 handler with SA_RESTART, SIGALRM will cause reads to be restarted
2861acd27e7Smillert 	 automatically, so readline should just get out of the way.  Since
2871acd27e7Smillert 	 we tested for SIG_IGN above, we can just test for SIG_DFL here. */
2881acd27e7Smillert       if (oh != (SigHandler *)SIG_DFL && (old_alrm.sa_flags & SA_RESTART))
2891acd27e7Smillert 	rl_sigaction (SIGALRM, &old_alrm, &dummy);
2901acd27e7Smillert #endif /* HAVE_POSIX_SIGNALS */
2911acd27e7Smillert 
2921acd27e7Smillert #if defined (SIGTSTP)
2931acd27e7Smillert       rl_maybe_set_sighandler (SIGTSTP, rl_signal_handler, &old_tstp);
2941acd27e7Smillert #endif /* SIGTSTP */
2951acd27e7Smillert 
2961acd27e7Smillert #if defined (SIGTTOU)
2971acd27e7Smillert       rl_maybe_set_sighandler (SIGTTOU, rl_signal_handler, &old_ttou);
2981acd27e7Smillert #endif /* SIGTTOU */
2991acd27e7Smillert 
3001acd27e7Smillert #if defined (SIGTTIN)
3011acd27e7Smillert       rl_maybe_set_sighandler (SIGTTIN, rl_signal_handler, &old_ttin);
3021acd27e7Smillert #endif /* SIGTTIN */
3031acd27e7Smillert 
3041acd27e7Smillert       signals_set_flag = 1;
3051acd27e7Smillert     }
3061acd27e7Smillert 
3071acd27e7Smillert #if defined (SIGWINCH)
3081acd27e7Smillert   if (rl_catch_sigwinch && sigwinch_set_flag == 0)
3091acd27e7Smillert     {
3101acd27e7Smillert       rl_maybe_set_sighandler (SIGWINCH, rl_sigwinch_handler, &old_winch);
3111acd27e7Smillert       sigwinch_set_flag = 1;
3121acd27e7Smillert     }
3131acd27e7Smillert #endif /* SIGWINCH */
3141acd27e7Smillert 
3151acd27e7Smillert   return 0;
3161acd27e7Smillert }
3171acd27e7Smillert 
3181acd27e7Smillert int
rl_clear_signals()3191acd27e7Smillert rl_clear_signals ()
3201acd27e7Smillert {
3211acd27e7Smillert   sighandler_cxt dummy;
3221acd27e7Smillert 
3231acd27e7Smillert   if (rl_catch_signals && signals_set_flag == 1)
3241acd27e7Smillert     {
3251acd27e7Smillert       sigemptyset (&dummy.sa_mask);
3261acd27e7Smillert 
3271acd27e7Smillert       rl_sigaction (SIGINT, &old_int, &dummy);
3281acd27e7Smillert       rl_sigaction (SIGTERM, &old_term, &dummy);
3291acd27e7Smillert       rl_sigaction (SIGQUIT, &old_quit, &dummy);
3301acd27e7Smillert       rl_sigaction (SIGALRM, &old_alrm, &dummy);
3311acd27e7Smillert 
3321acd27e7Smillert #if defined (SIGTSTP)
3331acd27e7Smillert       rl_sigaction (SIGTSTP, &old_tstp, &dummy);
3341acd27e7Smillert #endif /* SIGTSTP */
3351acd27e7Smillert 
3361acd27e7Smillert #if defined (SIGTTOU)
3371acd27e7Smillert       rl_sigaction (SIGTTOU, &old_ttou, &dummy);
3381acd27e7Smillert #endif /* SIGTTOU */
3391acd27e7Smillert 
3401acd27e7Smillert #if defined (SIGTTIN)
3411acd27e7Smillert       rl_sigaction (SIGTTIN, &old_ttin, &dummy);
3421acd27e7Smillert #endif /* SIGTTIN */
3431acd27e7Smillert 
3441acd27e7Smillert       signals_set_flag = 0;
3451acd27e7Smillert     }
3461acd27e7Smillert 
3471acd27e7Smillert #if defined (SIGWINCH)
3481acd27e7Smillert   if (rl_catch_sigwinch && sigwinch_set_flag == 1)
3491acd27e7Smillert     {
3501acd27e7Smillert       sigemptyset (&dummy.sa_mask);
3511acd27e7Smillert       rl_sigaction (SIGWINCH, &old_winch, &dummy);
3521acd27e7Smillert       sigwinch_set_flag = 0;
3531acd27e7Smillert     }
3541acd27e7Smillert #endif
3551acd27e7Smillert 
3561acd27e7Smillert   return 0;
3571acd27e7Smillert }
3581acd27e7Smillert 
3591acd27e7Smillert /* Clean up the terminal and readline state after catching a signal, before
3601acd27e7Smillert    resending it to the calling application. */
3611acd27e7Smillert void
rl_cleanup_after_signal()3621acd27e7Smillert rl_cleanup_after_signal ()
3631acd27e7Smillert {
3641acd27e7Smillert   _rl_clean_up_for_exit ();
3651acd27e7Smillert   (*rl_deprep_term_function) ();
3661acd27e7Smillert   rl_clear_signals ();
367*15b117eaSkettenis   rl_clear_pending_input ();
3681acd27e7Smillert }
3691acd27e7Smillert 
3701acd27e7Smillert /* Reset the terminal and readline state after a signal handler returns. */
3711acd27e7Smillert void
rl_reset_after_signal()3721acd27e7Smillert rl_reset_after_signal ()
3731acd27e7Smillert {
3741acd27e7Smillert   (*rl_prep_term_function) (_rl_meta_flag);
3751acd27e7Smillert   rl_set_signals ();
3761acd27e7Smillert }
3771acd27e7Smillert 
3781acd27e7Smillert /* Free up the readline variable line state for the current line (undo list,
3791acd27e7Smillert    any partial history entry, any keyboard macros in progress, and any
3801acd27e7Smillert    numeric arguments in process) after catching a signal, before calling
3811acd27e7Smillert    rl_cleanup_after_signal(). */
3821acd27e7Smillert void
rl_free_line_state()3831acd27e7Smillert rl_free_line_state ()
3841acd27e7Smillert {
3851acd27e7Smillert   register HIST_ENTRY *entry;
3861acd27e7Smillert 
387*15b117eaSkettenis   rl_free_undo_list ();
3881acd27e7Smillert 
3891acd27e7Smillert   entry = current_history ();
3901acd27e7Smillert   if (entry)
3911acd27e7Smillert     entry->data = (char *)NULL;
3921acd27e7Smillert 
3931acd27e7Smillert   _rl_kill_kbd_macro ();
3941acd27e7Smillert   rl_clear_message ();
3951acd27e7Smillert   _rl_init_argument ();
3961acd27e7Smillert }
3971acd27e7Smillert 
3981acd27e7Smillert #endif  /* HANDLE_SIGNALS */
399