LCOV - code coverage report
Current view: top level - common - signal.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 36 70 51.4 %
Date: 2016-09-12 13:01:59 Functions: 5 8 62.5 %

          Line data    Source code
       1             : /* signal.c - signal handling
       2             :  * Copyright (C) 1998, 1999, 2000, 2001, 2002,
       3             :  *               2005 Free Software Foundation, Inc.
       4             :  *
       5             :  * This file is part of GnuPG.
       6             :  *
       7             :  * This file is free software; you can redistribute it and/or modify
       8             :  * it under the terms of either
       9             :  *
      10             :  *   - the GNU Lesser General Public License as published by the Free
      11             :  *     Software Foundation; either version 3 of the License, or (at
      12             :  *     your option) any later version.
      13             :  *
      14             :  * or
      15             :  *
      16             :  *   - the GNU General Public License as published by the Free
      17             :  *     Software Foundation; either version 2 of the License, or (at
      18             :  *     your option) any later version.
      19             :  *
      20             :  * or both in parallel, as here.
      21             :  *
      22             :  * This file is distributed in the hope that it will be useful,
      23             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      24             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      25             :  * GNU General Public License for more details.
      26             :  *
      27             :  * You should have received a copy of the GNU General Public License
      28             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      29             :  */
      30             : 
      31             : #include <config.h>
      32             : #include <stdio.h>
      33             : #include <stdlib.h>
      34             : #ifdef HAVE_SIGNAL_H
      35             : # include <signal.h>
      36             : #endif
      37             : #include <unistd.h>
      38             : #include <string.h>
      39             : #include <errno.h>
      40             : #include <assert.h>
      41             : 
      42             : #include "util.h"
      43             : 
      44             : 
      45             : #ifndef HAVE_DOSISH_SYSTEM
      46             : static volatile int caught_fatal_sig;
      47             : static volatile int caught_sigusr1;
      48             : #endif
      49             : static void (*cleanup_fnc)(void);
      50             : 
      51             : 
      52             : #ifndef HAVE_DOSISH_SYSTEM
      53             : static void
      54       12817 : init_one_signal (int sig, RETSIGTYPE (*handler)(int), int check_ign )
      55             : {
      56             : # ifdef HAVE_SIGACTION
      57             :   struct sigaction oact, nact;
      58             : 
      59       12817 :   if (check_ign)
      60             :     {
      61             :       /* we don't want to change an IGN handler */
      62        9155 :       sigaction (sig, NULL, &oact );
      63        9155 :       if (oact.sa_handler == SIG_IGN )
      64       12817 :         return;
      65             :     }
      66             : 
      67       12817 :   nact.sa_handler = handler;
      68       12817 :   sigemptyset (&nact.sa_mask);
      69       12817 :   nact.sa_flags = 0;
      70       12817 :   sigaction ( sig, &nact, NULL);
      71             : # else
      72             :   RETSIGTYPE (*ohandler)(int);
      73             : 
      74             :   ohandler = signal (sig, handler);
      75             :   if (check_ign && ohandler == SIG_IGN)
      76             :     {
      77             :       /* Change it back if it was already set to IGN */
      78             :       signal (sig, SIG_IGN);
      79             :     }
      80             : # endif
      81             : }
      82             : #endif /*!HAVE_DOSISH_SYSTEM*/
      83             : 
      84             : #ifndef HAVE_DOSISH_SYSTEM
      85             : static const char *
      86           0 : get_signal_name( int signum )
      87             : {
      88             :   /* Note that we can't use strsignal(), because it is not
      89             :      reentrant. */
      90             : #if HAVE_DECL_SYS_SIGLIST && defined(NSIG)
      91           0 :   return (signum >= 0 && signum < NSIG) ? sys_siglist[signum] : "?";
      92             : #else
      93             :   return NULL;
      94             : #endif
      95             : }
      96             : #endif /*!HAVE_DOSISH_SYSTEM*/
      97             : 
      98             : #ifndef HAVE_DOSISH_SYSTEM
      99             : static RETSIGTYPE
     100           0 : got_fatal_signal (int sig)
     101             : {
     102             :   const char *s;
     103             : 
     104           0 :   if (caught_fatal_sig)
     105           0 :     raise (sig);
     106           0 :   caught_fatal_sig = 1;
     107             : 
     108           0 :   if (cleanup_fnc)
     109           0 :     cleanup_fnc ();
     110             :   /* Better don't translate these messages. */
     111           0 :   (void)write (2, "\n", 1 );
     112           0 :   s = log_get_prefix (NULL);
     113           0 :   if (s)
     114           0 :     (void)write(2, s, strlen (s));
     115           0 :   (void)write (2, ": signal ", 9 );
     116           0 :   s = get_signal_name(sig);
     117           0 :   if (s)
     118           0 :     (void) write (2, s, strlen(s) );
     119             :   else
     120             :     {
     121             :       /* We are in a signal handler so we can't use any kind of printf
     122             :          even not sprintf.  So we use a straightforward algorithm.  We
     123             :          got a report that on one particular system, raising a signal
     124             :          while in this handler, the parameter SIG get sclobbered and
     125             :          things are messed up because we modify its value.  Although
     126             :          this is a bug in that system, we will protect against it.  */
     127           0 :       if (sig < 0 || sig >= 100000)
     128           0 :         (void)write (2, "?", 1);
     129             :       else
     130             :         {
     131           0 :           int i, value, any=0;
     132             : 
     133           0 :           for (value=sig,i=10000; i; i /= 10)
     134             :             {
     135           0 :               if (value >= i || ((any || i==1) && !(value/i)))
     136             :                 {
     137           0 :                   (void)write (2, "0123456789"+(value/i), 1);
     138           0 :                   if ((value/i))
     139           0 :                     any = 1;
     140           0 :                   value %= i;
     141             :                 }
     142             :             }
     143             :         }
     144             :     }
     145           0 :   (void)write (2, " caught ... exiting\n", 20);
     146             : 
     147             :   /* Reset action to default action and raise signal again */
     148           0 :   init_one_signal (sig, SIG_DFL, 0);
     149             :   /* Fixme: remove_lockfiles ();*/
     150             : #ifdef __riscos__
     151             :   close_fds ();
     152             : #endif /* __riscos__ */
     153           0 :   raise( sig );
     154           0 : }
     155             : #endif /*!HAVE_DOSISH_SYSTEM*/
     156             : 
     157             : #ifndef HAVE_DOSISH_SYSTEM
     158             : static RETSIGTYPE
     159           0 : got_usr_signal (int sig)
     160             : {
     161             :   (void)sig;
     162           0 :   caught_sigusr1 = 1;
     163           0 : }
     164             : #endif /*!HAVE_DOSISH_SYSTEM*/
     165             : 
     166             : void
     167        1831 : gnupg_init_signals (int mode, void (*fast_cleanup)(void))
     168             : {
     169        1831 :   assert (!mode);
     170             : 
     171        1831 :   cleanup_fnc = fast_cleanup;
     172             : #ifndef HAVE_DOSISH_SYSTEM
     173        1831 :   init_one_signal (SIGINT, got_fatal_signal, 1 );
     174        1831 :   init_one_signal (SIGHUP, got_fatal_signal, 1 );
     175        1831 :   init_one_signal (SIGTERM, got_fatal_signal, 1 );
     176        1831 :   init_one_signal (SIGQUIT, got_fatal_signal, 1 );
     177        1831 :   init_one_signal (SIGSEGV, got_fatal_signal, 1 );
     178        1831 :   init_one_signal (SIGUSR1, got_usr_signal, 0 );
     179        1831 :   init_one_signal (SIGPIPE, SIG_IGN, 0 );
     180             : #endif
     181        1831 : }
     182             : 
     183             : 
     184             : static void
     185         142 : do_block (int block)
     186             : {
     187             : #ifdef HAVE_DOSISH_SYSTEM
     188             :   (void)block;
     189             : #else /*!HAVE_DOSISH_SYSTEM*/
     190             :   static int is_blocked;
     191             : #ifdef HAVE_SIGPROCMASK
     192             :   static sigset_t oldmask;
     193             : 
     194         142 :   if (block)
     195             :     {
     196             :       sigset_t newmask;
     197             : 
     198          71 :       if (is_blocked)
     199           0 :         log_bug ("signals are already blocked\n");
     200          71 :       sigfillset( &newmask );
     201          71 :       sigprocmask( SIG_BLOCK, &newmask, &oldmask );
     202          71 :       is_blocked = 1;
     203             :     }
     204             :   else
     205             :     {
     206          71 :       if (!is_blocked)
     207           0 :         log_bug("signals are not blocked\n");
     208          71 :       sigprocmask (SIG_SETMASK, &oldmask, NULL);
     209          71 :       is_blocked = 0;
     210             :     }
     211             : #else /*!HAVE_SIGPROCMASK*/
     212             :   static void (*disposition[MAXSIG])();
     213             :   int sig;
     214             : 
     215             :   if (block)
     216             :     {
     217             :       if (is_blocked)
     218             :         log_bug("signals are already blocked\n");
     219             :       for (sig=1; sig < MAXSIG; sig++)
     220             :         {
     221             :           disposition[sig] = sigset (sig, SIG_HOLD);
     222             :         }
     223             :       is_blocked = 1;
     224             :     }
     225             :   else
     226             :     {
     227             :       if (!is_blocked)
     228             :         log_bug ("signals are not blocked\n");
     229             :       for (sig=1; sig < MAXSIG; sig++) {
     230             :         sigset (sig, disposition[sig]);
     231             :       }
     232             :       is_blocked = 0;
     233             :     }
     234             : #endif /*!HAVE_SIGPROCMASK*/
     235             : #endif /*!HAVE_DOSISH_SYSTEM*/
     236         142 : }
     237             : 
     238             : 
     239             : void
     240          71 : gnupg_block_all_signals ()
     241             : {
     242          71 :   do_block(1);
     243          71 : }
     244             : 
     245             : void
     246          71 : gnupg_unblock_all_signals ()
     247             : {
     248          71 :   do_block(0);
     249          71 : }

Generated by: LCOV version 1.11