Back to index

tetex-bin  3.0
signals.c
Go to the documentation of this file.
00001 /* signals.c -- install and maintain signal handlers.
00002    $Id: signals.c,v 1.7 2004/04/11 17:56:46 karl Exp $
00003 
00004    Copyright (C) 1993, 1994, 1995, 1998, 2002, 2003, 2004 Free Software
00005    Foundation, Inc.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2, or (at your option)
00010    any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program; if not, write to the Free Software
00019    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00020 
00021    Originally written by Brian Fox (bfox@ai.mit.edu). */
00022 
00023 #include "info.h"
00024 #include "signals.h"
00025 
00026 void initialize_info_signal_handler (void);
00027 
00028 /* **************************************************************** */
00029 /*                                                                  */
00030 /*              Pretending That We Have POSIX Signals               */
00031 /*                                                                  */
00032 /* **************************************************************** */
00033 
00034 #if !defined (HAVE_SIGPROCMASK) && defined (HAVE_SIGSETMASK)
00035 /* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */
00036 static void
00037 sigprocmask (int operation, int *newset, int *oldset)
00038 {
00039   switch (operation)
00040     {
00041     case SIG_UNBLOCK:
00042       sigsetmask (sigblock (0) & ~(*newset));
00043       break;
00044 
00045     case SIG_BLOCK:
00046       *oldset = sigblock (*newset);
00047       break;
00048 
00049     case SIG_SETMASK:
00050       sigsetmask (*newset);
00051       break;
00052 
00053     default:
00054       abort ();
00055     }
00056 }
00057 #endif /* !HAVE_SIGPROCMASK && HAVE_SIGSETMASK */
00058 
00059 /* **************************************************************** */
00060 /*                                                                  */
00061 /*                  Signal Handling for Info                        */
00062 /*                                                                  */
00063 /* **************************************************************** */
00064 
00065 #if defined (HAVE_SIGACTION) || defined (HAVE_SIGPROCMASK) ||\
00066   defined (HAVE_SIGSETMASK)
00067 static void
00068 mask_termsig (sigset_t *set)
00069 {
00070 # if defined (SIGTSTP)
00071   sigaddset (set, SIGTSTP);
00072   sigaddset (set, SIGTTOU);
00073   sigaddset (set, SIGTTIN);
00074 # endif
00075 # if defined (SIGWINCH)
00076   sigaddset (set, SIGWINCH);
00077 # endif
00078 #if defined (SIGQUIT)
00079   sigaddset (set, SIGQUIT);
00080 #endif
00081 #if defined (SIGINT)
00082   sigaddset (set, SIGINT);
00083 #endif
00084 # if defined (SIGUSR1)
00085   sigaddset (set, SIGUSR1);
00086 # endif
00087 }
00088 #endif /* HAVE_SIGACTION || HAVE_SIGPROCMASK || HAVE_SIGSETMASK */
00089 
00090 static RETSIGTYPE info_signal_proc (int sig);
00091 #if defined (HAVE_SIGACTION)
00092 typedef struct sigaction signal_info;
00093 signal_info info_signal_handler;
00094 
00095 static void
00096 set_termsig (int sig, signal_info *old)
00097 {
00098   sigaction (sig, &info_signal_handler, old);
00099 }
00100 
00101 static void
00102 restore_termsig (int sig, const signal_info *saved)
00103 {
00104   sigaction (sig, saved, NULL);
00105 }
00106 #else /* !HAVE_SIGACTION */
00107 typedef RETSIGTYPE (*signal_info) ();
00108 #define set_termsig(sig, old) (void)(*(old) = signal (sig, info_signal_proc))
00109 #define restore_termsig(sig, saved) (void)signal (sig, *(saved))
00110 #define info_signal_handler info_signal_proc
00111 static int term_conf_busy = 0;
00112 #endif /* !HAVE_SIGACTION */
00113 
00114 static signal_info old_TSTP, old_TTOU, old_TTIN;
00115 static signal_info old_WINCH, old_INT, old_USR1;
00116 static signal_info old_QUIT;
00117 
00118 void
00119 initialize_info_signal_handler (void)
00120 {
00121 #ifdef SA_NOCLDSTOP
00122   /* (Based on info from Paul Eggert found in coreutils.)  Don't use
00123      HAVE_SIGACTION to decide whether to use the sa_handler, sa_flags,
00124      sa_mask members, as some systems (Solaris 7+) don't define them.  Use
00125      SA_NOCLDSTOP instead; it's been part of POSIX.1 since day 1 (in 1988).  */
00126   info_signal_handler.sa_handler = info_signal_proc;
00127   info_signal_handler.sa_flags = 0;
00128   mask_termsig (&info_signal_handler.sa_mask);
00129 #endif /* SA_NOCLDSTOP */
00130 
00131 #if defined (SIGTSTP)
00132   set_termsig (SIGTSTP, &old_TSTP);
00133   set_termsig (SIGTTOU, &old_TTOU);
00134   set_termsig (SIGTTIN, &old_TTIN);
00135 #endif /* SIGTSTP */
00136 
00137 #if defined (SIGWINCH)
00138   set_termsig (SIGWINCH, &old_WINCH);
00139 #endif
00140 
00141 #if defined (SIGQUIT)
00142   set_termsig (SIGQUIT, &old_QUIT);
00143 #endif
00144 
00145 #if defined (SIGINT)
00146   set_termsig (SIGINT, &old_INT);
00147 #endif
00148 
00149 #if defined (SIGUSR1)
00150   /* Used by DJGPP to simulate SIGTSTP on Ctrl-Z.  */
00151   set_termsig (SIGUSR1, &old_USR1);
00152 #endif
00153 }
00154 
00155 static void
00156 redisplay_after_signal (void)
00157 {
00158   terminal_clear_screen ();
00159   display_clear_display (the_display);
00160   window_mark_chain (windows, W_UpdateWindow);
00161   display_update_display (windows);
00162   display_cursor_at_point (active_window);
00163   fflush (stdout);
00164 }
00165 
00166 static void
00167 reset_info_window_sizes (void)
00168 {
00169   terminal_goto_xy (0, 0);
00170   fflush (stdout);
00171   terminal_unprep_terminal ();
00172   terminal_get_screen_size ();
00173   terminal_prep_terminal ();
00174   display_initialize_display (screenwidth, screenheight);
00175   window_new_screen_size (screenwidth, screenheight);
00176   redisplay_after_signal ();
00177 }
00178 
00179 static RETSIGTYPE
00180 info_signal_proc (int sig)
00181 {
00182   signal_info *old_signal_handler = NULL;
00183 
00184 #if !defined (HAVE_SIGACTION)
00185   /* best effort: first increment this counter and later block signals */
00186   if (term_conf_busy)
00187     return;
00188   term_conf_busy++;
00189 #if defined (HAVE_SIGPROCMASK) || defined (HAVE_SIGSETMASK)
00190     {
00191       sigset_t nvar, ovar;
00192       sigemptyset (&nvar);
00193       mask_termsig (&nvar);
00194       sigprocmask (SIG_BLOCK, &nvar, &ovar);
00195     }
00196 #endif /* HAVE_SIGPROCMASK || HAVE_SIGSETMASK */
00197 #endif /* !HAVE_SIGACTION */
00198   switch (sig)
00199     {
00200 #if defined (SIGTSTP)
00201     case SIGTSTP:
00202     case SIGTTOU:
00203     case SIGTTIN:
00204 #endif
00205 #if defined (SIGQUIT)
00206     case SIGQUIT:
00207 #endif
00208 #if defined (SIGINT)
00209     case SIGINT:
00210 #endif
00211       {
00212 #if defined (SIGTSTP)
00213         if (sig == SIGTSTP)
00214           old_signal_handler = &old_TSTP;
00215         if (sig == SIGTTOU)
00216           old_signal_handler = &old_TTOU;
00217         if (sig == SIGTTIN)
00218           old_signal_handler = &old_TTIN;
00219 #endif /* SIGTSTP */
00220 #if defined (SIGQUIT)
00221         if (sig == SIGQUIT)
00222           old_signal_handler = &old_QUIT;
00223 #endif /* SIGQUIT */
00224 #if defined (SIGINT)
00225         if (sig == SIGINT)
00226           old_signal_handler = &old_INT;
00227 #endif /* SIGINT */
00228 
00229         /* For stop signals, restore the terminal IO, leave the cursor
00230            at the bottom of the window, and stop us. */
00231         terminal_goto_xy (0, screenheight - 1);
00232         terminal_clear_to_eol ();
00233         fflush (stdout);
00234         terminal_unprep_terminal ();
00235        restore_termsig (sig, old_signal_handler);
00236        UNBLOCK_SIGNAL (sig);
00237        kill (getpid (), sig);
00238 
00239         /* The program is returning now.  Restore our signal handler,
00240            turn on terminal handling, redraw the screen, and place the
00241            cursor where it belongs. */
00242         terminal_prep_terminal ();
00243        set_termsig (sig, old_signal_handler);
00244        /* window size might be changed while sleeping */
00245        reset_info_window_sizes ();
00246       }
00247       break;
00248 
00249 #if defined (SIGWINCH) || defined (SIGUSR1)
00250 #ifdef SIGWINCH
00251     case SIGWINCH:
00252 #endif
00253 #ifdef SIGUSR1
00254     case SIGUSR1:
00255 #endif
00256       {
00257        /* Turn off terminal IO, tell our parent that the window has changed,
00258           then reinitialize the terminal and rebuild our windows. */
00259 #ifdef SIGWINCH
00260        if (sig == SIGWINCH)
00261          old_signal_handler = &old_WINCH;
00262 #endif
00263 #ifdef SIGUSR1
00264        if (sig == SIGUSR1)
00265          old_signal_handler = &old_USR1;
00266 #endif
00267        terminal_goto_xy (0, 0);
00268        fflush (stdout);
00269        terminal_unprep_terminal (); /* needless? */
00270        restore_termsig (sig, old_signal_handler);
00271        UNBLOCK_SIGNAL (sig);
00272        kill (getpid (), sig);
00273 
00274        /* After our old signal handler returns... */
00275        set_termsig (sig, old_signal_handler); /* needless? */
00276        terminal_prep_terminal ();
00277        reset_info_window_sizes ();
00278       }
00279       break;
00280 #endif /* SIGWINCH || SIGUSR1 */
00281     }
00282 #if !defined (HAVE_SIGACTION)
00283   /* at this time it is safer to perform unblock after decrement */
00284   term_conf_busy--;
00285 #if defined (HAVE_SIGPROCMASK) || defined (HAVE_SIGSETMASK)
00286     {
00287       sigset_t nvar, ovar;
00288       sigemptyset (&nvar);
00289       mask_termsig (&nvar);
00290       sigprocmask (SIG_UNBLOCK, &nvar, &ovar);
00291     }
00292 #endif /* HAVE_SIGPROCMASK || HAVE_SIGSETMASK */
00293 #endif /* !HAVE_SIGACTION */
00294 }
00295 /* vim: set sw=2 cino={1s>2sn-s^-se-s: */