signals.c revision 136644
121308Sache/* signals.c -- signal handling support for readline. */
221308Sache
321308Sache/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
421308Sache
521308Sache   This file is part of the GNU Readline Library, a library for
621308Sache   reading lines of text with interactive input and history editing.
721308Sache
821308Sache   The GNU Readline Library is free software; you can redistribute it
921308Sache   and/or modify it under the terms of the GNU General Public License
1058310Sache   as published by the Free Software Foundation; either version 2, or
1121308Sache   (at your option) any later version.
1221308Sache
1321308Sache   The GNU Readline Library is distributed in the hope that it will be
1421308Sache   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
1521308Sache   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1621308Sache   GNU General Public License for more details.
1721308Sache
1821308Sache   The GNU General Public License is often shipped with GNU software, and
1921308Sache   is generally kept in a file called COPYING or LICENSE.  If you do not
2021308Sache   have a copy of the license, write to the Free Software Foundation,
2158310Sache   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
2221308Sache#define READLINE_LIBRARY
2321308Sache
2421308Sache#if defined (HAVE_CONFIG_H)
2521308Sache#  include <config.h>
2621308Sache#endif
2721308Sache
2821308Sache#include <stdio.h>		/* Just for NULL.  Yuck. */
2921308Sache#include <sys/types.h>
3021308Sache#include <signal.h>
3121308Sache
3221308Sache#if defined (HAVE_UNISTD_H)
3321308Sache#  include <unistd.h>
3421308Sache#endif /* HAVE_UNISTD_H */
3521308Sache
3621308Sache/* System-specific feature definitions and include files. */
3721308Sache#include "rldefs.h"
3821308Sache
3921308Sache#if defined (GWINSZ_IN_SYS_IOCTL)
4021308Sache#  include <sys/ioctl.h>
4121308Sache#endif /* GWINSZ_IN_SYS_IOCTL */
4221308Sache
4321308Sache#if defined (HANDLE_SIGNALS)
4421308Sache/* Some standard library routines. */
4521308Sache#include "readline.h"
4621308Sache#include "history.h"
4721308Sache
4858310Sache#include "rlprivate.h"
4958310Sache
5021308Sache#if !defined (RETSIGTYPE)
5121308Sache#  if defined (VOID_SIGHANDLER)
5221308Sache#    define RETSIGTYPE void
5321308Sache#  else
5421308Sache#    define RETSIGTYPE int
5521308Sache#  endif /* !VOID_SIGHANDLER */
5621308Sache#endif /* !RETSIGTYPE */
5721308Sache
5821308Sache#if defined (VOID_SIGHANDLER)
5921308Sache#  define SIGHANDLER_RETURN return
6021308Sache#else
6121308Sache#  define SIGHANDLER_RETURN return (0)
6221308Sache#endif
6321308Sache
6475406Sache/* This typedef is equivalent to the one for Function; it allows us
6521308Sache   to say SigHandler *foo = signal (SIGKILL, SIG_IGN); */
6621308Sachetypedef RETSIGTYPE SigHandler ();
6721308Sache
6858310Sache#if defined (HAVE_POSIX_SIGNALS)
6958310Sachetypedef struct sigaction sighandler_cxt;
7058310Sache#  define rl_sigaction(s, nh, oh)	sigaction(s, nh, oh)
7158310Sache#else
7258310Sachetypedef struct { SigHandler *sa_handler; int sa_mask, sa_flags; } sighandler_cxt;
7358310Sache#  define sigemptyset(m)
7458310Sache#endif /* !HAVE_POSIX_SIGNALS */
7547558Sache
76136644Sache#ifndef SA_RESTART
77136644Sache#  define SA_RESTART 0
78136644Sache#endif
79136644Sache
80119610Sachestatic SigHandler *rl_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *));
81119610Sachestatic void rl_maybe_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *));
8247558Sache
8347558Sache/* Exported variables for use by applications. */
8447558Sache
8547558Sache/* If non-zero, readline will install its own signal handlers for
8647558Sache   SIGINT, SIGTERM, SIGQUIT, SIGALRM, SIGTSTP, SIGTTIN, and SIGTTOU. */
8747558Sacheint rl_catch_signals = 1;
8847558Sache
8947558Sache/* If non-zero, readline will install a signal handler for SIGWINCH. */
9047558Sache#ifdef SIGWINCH
9147558Sacheint rl_catch_sigwinch = 1;
92136644Sache#else
93136644Sacheint rl_catch_sigwinch = 0;	/* for the readline state struct in readline.c */
9447558Sache#endif
9547558Sache
9647558Sachestatic int signals_set_flag;
9747558Sachestatic int sigwinch_set_flag;
9847558Sache
9921308Sache/* **************************************************************** */
10021308Sache/*					        		    */
10121308Sache/*			   Signal Handling                          */
10221308Sache/*								    */
10321308Sache/* **************************************************************** */
10421308Sache
10547558Sachestatic sighandler_cxt old_int, old_term, old_alrm, old_quit;
10647558Sache#if defined (SIGTSTP)
10726497Sachestatic sighandler_cxt old_tstp, old_ttou, old_ttin;
10826497Sache#endif
10921308Sache#if defined (SIGWINCH)
11021308Sachestatic sighandler_cxt old_winch;
11121308Sache#endif
11221308Sache
11321308Sache/* Readline signal handler functions. */
11421308Sache
11521308Sachestatic RETSIGTYPE
11621308Sacherl_signal_handler (sig)
11721308Sache     int sig;
11821308Sache{
11921308Sache#if defined (HAVE_POSIX_SIGNALS)
12021308Sache  sigset_t set;
12121308Sache#else /* !HAVE_POSIX_SIGNALS */
12221308Sache#  if defined (HAVE_BSD_SIGNALS)
12321308Sache  long omask;
12426497Sache#  else /* !HAVE_BSD_SIGNALS */
12526497Sache  sighandler_cxt dummy_cxt;	/* needed for rl_set_sighandler call */
12626497Sache#  endif /* !HAVE_BSD_SIGNALS */
12721308Sache#endif /* !HAVE_POSIX_SIGNALS */
12821308Sache
12975406Sache  RL_SETSTATE(RL_STATE_SIGHANDLER);
13075406Sache
13121308Sache#if !defined (HAVE_BSD_SIGNALS) && !defined (HAVE_POSIX_SIGNALS)
13221308Sache  /* Since the signal will not be blocked while we are in the signal
13321308Sache     handler, ignore it until rl_clear_signals resets the catcher. */
13421308Sache  if (sig == SIGINT || sig == SIGALRM)
13526497Sache    rl_set_sighandler (sig, SIG_IGN, &dummy_cxt);
13621308Sache#endif /* !HAVE_BSD_SIGNALS && !HAVE_POSIX_SIGNALS */
13721308Sache
13821308Sache  switch (sig)
13921308Sache    {
14021308Sache    case SIGINT:
14147558Sache      rl_free_line_state ();
14247558Sache      /* FALLTHROUGH */
14321308Sache
14421308Sache#if defined (SIGTSTP)
14521308Sache    case SIGTSTP:
14621308Sache    case SIGTTOU:
14721308Sache    case SIGTTIN:
14821308Sache#endif /* SIGTSTP */
14921308Sache    case SIGALRM:
15021308Sache    case SIGTERM:
15147558Sache    case SIGQUIT:
15247558Sache      rl_cleanup_after_signal ();
15321308Sache
15421308Sache#if defined (HAVE_POSIX_SIGNALS)
15521308Sache      sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set);
15621308Sache      sigdelset (&set, sig);
15721308Sache#else /* !HAVE_POSIX_SIGNALS */
15821308Sache#  if defined (HAVE_BSD_SIGNALS)
15921308Sache      omask = sigblock (0);
16021308Sache#  endif /* HAVE_BSD_SIGNALS */
16121308Sache#endif /* !HAVE_POSIX_SIGNALS */
16221308Sache
16358310Sache#if defined (__EMX__)
16458310Sache      signal (sig, SIG_ACK);
16558310Sache#endif
16658310Sache
16721308Sache      kill (getpid (), sig);
16821308Sache
16921308Sache      /* Let the signal that we just sent through.  */
17021308Sache#if defined (HAVE_POSIX_SIGNALS)
17121308Sache      sigprocmask (SIG_SETMASK, &set, (sigset_t *)NULL);
17221308Sache#else /* !HAVE_POSIX_SIGNALS */
17321308Sache#  if defined (HAVE_BSD_SIGNALS)
17421308Sache      sigsetmask (omask & ~(sigmask (sig)));
17521308Sache#  endif /* HAVE_BSD_SIGNALS */
17621308Sache#endif /* !HAVE_POSIX_SIGNALS */
17721308Sache
17847558Sache      rl_reset_after_signal ();
17921308Sache    }
18021308Sache
18175406Sache  RL_UNSETSTATE(RL_STATE_SIGHANDLER);
18221308Sache  SIGHANDLER_RETURN;
18321308Sache}
18421308Sache
18521308Sache#if defined (SIGWINCH)
18621308Sachestatic RETSIGTYPE
18747558Sacherl_sigwinch_handler (sig)
18821308Sache     int sig;
18921308Sache{
19021308Sache  SigHandler *oh;
19121308Sache
19226497Sache#if defined (MUST_REINSTALL_SIGHANDLERS)
19326497Sache  sighandler_cxt dummy_winch;
19426497Sache
19526497Sache  /* We don't want to change old_winch -- it holds the state of SIGWINCH
19626497Sache     disposition set by the calling application.  We need this state
19726497Sache     because we call the application's SIGWINCH handler after updating
19826497Sache     our own idea of the screen size. */
19947558Sache  rl_set_sighandler (SIGWINCH, rl_sigwinch_handler, &dummy_winch);
20026497Sache#endif
20126497Sache
20275406Sache  RL_SETSTATE(RL_STATE_SIGHANDLER);
20347558Sache  rl_resize_terminal ();
20421308Sache
20521308Sache  /* If another sigwinch handler has been installed, call it. */
20621308Sache  oh = (SigHandler *)old_winch.sa_handler;
20721308Sache  if (oh &&  oh != (SigHandler *)SIG_IGN && oh != (SigHandler *)SIG_DFL)
20821308Sache    (*oh) (sig);
20921308Sache
21075406Sache  RL_UNSETSTATE(RL_STATE_SIGHANDLER);
21121308Sache  SIGHANDLER_RETURN;
21221308Sache}
21321308Sache#endif  /* SIGWINCH */
21421308Sache
21521308Sache/* Functions to manage signal handling. */
21621308Sache
21721308Sache#if !defined (HAVE_POSIX_SIGNALS)
21821308Sachestatic int
21921308Sacherl_sigaction (sig, nh, oh)
22021308Sache     int sig;
22121308Sache     sighandler_cxt *nh, *oh;
22221308Sache{
22321308Sache  oh->sa_handler = signal (sig, nh->sa_handler);
22421308Sache  return 0;
22521308Sache}
22621308Sache#endif /* !HAVE_POSIX_SIGNALS */
22721308Sache
22821308Sache/* Set up a readline-specific signal handler, saving the old signal
22921308Sache   information in OHANDLER.  Return the old signal handler, like
23021308Sache   signal(). */
23121308Sachestatic SigHandler *
23221308Sacherl_set_sighandler (sig, handler, ohandler)
23321308Sache     int sig;
23421308Sache     SigHandler *handler;
23521308Sache     sighandler_cxt *ohandler;
23621308Sache{
23758310Sache  sighandler_cxt old_handler;
23821308Sache#if defined (HAVE_POSIX_SIGNALS)
23921308Sache  struct sigaction act;
24021308Sache
24121308Sache  act.sa_handler = handler;
242136644Sache  act.sa_flags = (sig == SIGWINCH) ? SA_RESTART : 0;
24321308Sache  sigemptyset (&act.sa_mask);
24421308Sache  sigemptyset (&ohandler->sa_mask);
24558310Sache  sigaction (sig, &act, &old_handler);
24621308Sache#else
24758310Sache  old_handler.sa_handler = (SigHandler *)signal (sig, handler);
24821308Sache#endif /* !HAVE_POSIX_SIGNALS */
24958310Sache
25058310Sache  /* XXX -- assume we have memcpy */
25158310Sache  /* If rl_set_signals is called twice in a row, don't set the old handler to
25258310Sache     rl_signal_handler, because that would cause infinite recursion. */
25358310Sache  if (handler != rl_signal_handler || old_handler.sa_handler != rl_signal_handler)
25458310Sache    memcpy (ohandler, &old_handler, sizeof (sighandler_cxt));
25558310Sache
25621308Sache  return (ohandler->sa_handler);
25721308Sache}
25821308Sache
25947558Sachestatic void
26047558Sacherl_maybe_set_sighandler (sig, handler, ohandler)
26147558Sache     int sig;
26247558Sache     SigHandler *handler;
26347558Sache     sighandler_cxt *ohandler;
26447558Sache{
26547558Sache  sighandler_cxt dummy;
26647558Sache  SigHandler *oh;
26747558Sache
26847558Sache  sigemptyset (&dummy.sa_mask);
26947558Sache  oh = rl_set_sighandler (sig, handler, ohandler);
27047558Sache  if (oh == (SigHandler *)SIG_IGN)
27147558Sache    rl_sigaction (sig, ohandler, &dummy);
27247558Sache}
27347558Sache
27421308Sacheint
27521308Sacherl_set_signals ()
27621308Sache{
27721308Sache  sighandler_cxt dummy;
27821308Sache  SigHandler *oh;
27921308Sache
28047558Sache  if (rl_catch_signals && signals_set_flag == 0)
28147558Sache    {
28247558Sache      rl_maybe_set_sighandler (SIGINT, rl_signal_handler, &old_int);
28347558Sache      rl_maybe_set_sighandler (SIGTERM, rl_signal_handler, &old_term);
28447558Sache      rl_maybe_set_sighandler (SIGQUIT, rl_signal_handler, &old_quit);
28521308Sache
28647558Sache      oh = rl_set_sighandler (SIGALRM, rl_signal_handler, &old_alrm);
28747558Sache      if (oh == (SigHandler *)SIG_IGN)
28847558Sache	rl_sigaction (SIGALRM, &old_alrm, &dummy);
28921308Sache#if defined (HAVE_POSIX_SIGNALS) && defined (SA_RESTART)
29047558Sache      /* If the application using readline has already installed a signal
29147558Sache	 handler with SA_RESTART, SIGALRM will cause reads to be restarted
29247558Sache	 automatically, so readline should just get out of the way.  Since
29347558Sache	 we tested for SIG_IGN above, we can just test for SIG_DFL here. */
29447558Sache      if (oh != (SigHandler *)SIG_DFL && (old_alrm.sa_flags & SA_RESTART))
29547558Sache	rl_sigaction (SIGALRM, &old_alrm, &dummy);
29621308Sache#endif /* HAVE_POSIX_SIGNALS */
29721308Sache
29821308Sache#if defined (SIGTSTP)
29947558Sache      rl_maybe_set_sighandler (SIGTSTP, rl_signal_handler, &old_tstp);
30021308Sache#endif /* SIGTSTP */
30121308Sache
30221308Sache#if defined (SIGTTOU)
30347558Sache      rl_maybe_set_sighandler (SIGTTOU, rl_signal_handler, &old_ttou);
30421308Sache#endif /* SIGTTOU */
30521308Sache
30647558Sache#if defined (SIGTTIN)
30747558Sache      rl_maybe_set_sighandler (SIGTTIN, rl_signal_handler, &old_ttin);
30847558Sache#endif /* SIGTTIN */
30926497Sache
31047558Sache      signals_set_flag = 1;
31147558Sache    }
31221308Sache
31321308Sache#if defined (SIGWINCH)
31447558Sache  if (rl_catch_sigwinch && sigwinch_set_flag == 0)
31547558Sache    {
31647558Sache      rl_maybe_set_sighandler (SIGWINCH, rl_sigwinch_handler, &old_winch);
31747558Sache      sigwinch_set_flag = 1;
31847558Sache    }
31921308Sache#endif /* SIGWINCH */
32021308Sache
32121308Sache  return 0;
32221308Sache}
32321308Sache
32421308Sacheint
32521308Sacherl_clear_signals ()
32621308Sache{
32721308Sache  sighandler_cxt dummy;
32821308Sache
32947558Sache  if (rl_catch_signals && signals_set_flag == 1)
33047558Sache    {
33147558Sache      sigemptyset (&dummy.sa_mask);
33221308Sache
33347558Sache      rl_sigaction (SIGINT, &old_int, &dummy);
33447558Sache      rl_sigaction (SIGTERM, &old_term, &dummy);
33547558Sache      rl_sigaction (SIGQUIT, &old_quit, &dummy);
33647558Sache      rl_sigaction (SIGALRM, &old_alrm, &dummy);
33721308Sache
33821308Sache#if defined (SIGTSTP)
33947558Sache      rl_sigaction (SIGTSTP, &old_tstp, &dummy);
34047558Sache#endif /* SIGTSTP */
34121308Sache
34221308Sache#if defined (SIGTTOU)
34347558Sache      rl_sigaction (SIGTTOU, &old_ttou, &dummy);
34421308Sache#endif /* SIGTTOU */
34521308Sache
34647558Sache#if defined (SIGTTIN)
34747558Sache      rl_sigaction (SIGTTIN, &old_ttin, &dummy);
34847558Sache#endif /* SIGTTIN */
34926497Sache
35047558Sache      signals_set_flag = 0;
35147558Sache    }
35221308Sache
35321308Sache#if defined (SIGWINCH)
35447558Sache  if (rl_catch_sigwinch && sigwinch_set_flag == 1)
35547558Sache    {
35647558Sache      sigemptyset (&dummy.sa_mask);
35747558Sache      rl_sigaction (SIGWINCH, &old_winch, &dummy);
35847558Sache      sigwinch_set_flag = 0;
35947558Sache    }
36021308Sache#endif
36121308Sache
36221308Sache  return 0;
36321308Sache}
36447558Sache
36547558Sache/* Clean up the terminal and readline state after catching a signal, before
36647558Sache   resending it to the calling application. */
36747558Sachevoid
36847558Sacherl_cleanup_after_signal ()
36947558Sache{
37047558Sache  _rl_clean_up_for_exit ();
37147558Sache  (*rl_deprep_term_function) ();
37247558Sache  rl_clear_signals ();
37375406Sache  rl_clear_pending_input ();
37447558Sache}
37547558Sache
37647558Sache/* Reset the terminal and readline state after a signal handler returns. */
37747558Sachevoid
37847558Sacherl_reset_after_signal ()
37947558Sache{
38047558Sache  (*rl_prep_term_function) (_rl_meta_flag);
38147558Sache  rl_set_signals ();
38247558Sache}
38347558Sache
38447558Sache/* Free up the readline variable line state for the current line (undo list,
38547558Sache   any partial history entry, any keyboard macros in progress, and any
38647558Sache   numeric arguments in process) after catching a signal, before calling
38747558Sache   rl_cleanup_after_signal(). */
38847558Sachevoid
38947558Sacherl_free_line_state ()
39047558Sache{
39147558Sache  register HIST_ENTRY *entry;
39247558Sache
39375406Sache  rl_free_undo_list ();
39447558Sache
39547558Sache  entry = current_history ();
39647558Sache  if (entry)
39747558Sache    entry->data = (char *)NULL;
39847558Sache
39947558Sache  _rl_kill_kbd_macro ();
40047558Sache  rl_clear_message ();
40147558Sache  _rl_init_argument ();
40247558Sache}
40347558Sache
40421308Sache#endif  /* HANDLE_SIGNALS */
405