home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / pdksh-4.9-src.tgz / tar.out / contrib / pdksh / sh / sigact.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  9KB  |  429 lines

  1. /* NAME:
  2.  *      sigact.c - fake sigaction(2)
  3.  *
  4.  * SYNOPSIS:
  5.  *      #include "sigact.h"
  6.  * 
  7.  *      int sigaction(int sig, struct sigaction *act, 
  8.  *                      struct sigaction *oact);
  9.  *      int sigaddset(sigset_t *mask, int sig);
  10.  *      int sigdelset(sigset_t *mask, int sig);
  11.  *      int sigemptyset(sigset_t *mask);
  12.  *      int sigfillset(sigset_t *mask);
  13.  *      int sigismember(sigset_t *mask, int sig);
  14.  *      int sigpending(sigset_t *set);
  15.  *      int sigprocmask(int how, sigset_t *set, sigset_t *oset);
  16.  *      int sigsuspend(sigset_t *mask);
  17.  *      
  18.  *      SIG_HDLR (*Signal(int sig, SIG_HDLR (*disp)(int)))(int);
  19.  *
  20.  * DESCRIPTION:
  21.  *      This is a fake sigaction implementation.  It uses 
  22.  *      sigsetmask(2) et al or sigset(2) and friends if 
  23.  *      available, otherwise it just uses signal(2).  If it 
  24.  *      thinks sigaction(2) really exists it compiles to "almost" 
  25.  *      nothing. 
  26.  *      
  27.  *      In any case it provides a Signal() function that is 
  28.  *      implemented in terms of sigaction().
  29.  *      If not using signal(2) as part of the underlying 
  30.  *      implementation (USE_SIGNAL or USE_SIGMASK), and 
  31.  *      NO_SIGNAL is not defined, it also provides a signal() 
  32.  *      function that calls Signal(). 
  33.  *
  34.  *      The need for all this mucking about is the problems 
  35.  *      caused by mixing various signal handling mechanisms in 
  36.  *      the one process.  This module allows for a consistent 
  37.  *      POSIX compliant interface to whatever is actually 
  38.  *      available. 
  39.  *      
  40.  *      sigaction() allows the caller to examine and/or set the 
  41.  *      action to be associated with a given signal. "act" and 
  42.  *      "oact" are pointers to 'sigaction structs':
  43.  *.nf
  44.  * 
  45.  *      struct sigaction 
  46.  *      {
  47.  *             SIG_HDLR  (*sa_handler)();
  48.  *             sigset_t  sa_mask;
  49.  *             int       sa_flags;
  50.  *      };
  51.  *.fi
  52.  * 
  53.  *      SIG_HDLR is normally 'void' in the POSIX implementation 
  54.  *      and for most current systems.  On some older UNIX 
  55.  *      systems, signal handlers do not return 'void', so  
  56.  *      this implementation keeps 'sa_handler' inline with the 
  57.  *      hosts normal signal handling conventions.
  58.  *      'sa_mask' controls which signals will be blocked while 
  59.  *      the selected signal handler is active.  It is not used 
  60.  *      in this implementation.
  61.  *      'sa_flags' controls various semantics such as whether 
  62.  *      system calls should be automagically restarted 
  63.  *      (SA_RESTART) etc.  It is not used in this 
  64.  *      implementation. 
  65.  *      Either "act" or "oact" may be NULL in which case the 
  66.  *      appropriate operation is skipped.
  67.  *      
  68.  *      sigaddset() adds "sig" to the sigset_t pointed to by "mask".
  69.  *      
  70.  *      sigdelset() removes "sig" from the sigset_t pointed to 
  71.  *      by "mask". 
  72.  *      
  73.  *      sigemptyset() makes the sigset_t pointed to by "mask" empty.
  74.  *      
  75.  *      sigfillset() makes the sigset_t pointed to by "mask" 
  76.  *      full ie. match all signals.
  77.  *      
  78.  *      sigismember() returns true if "sig" is found in "*mask".
  79.  *      
  80.  *      sigpending() is supposed to return "set" loaded with the 
  81.  *      set of signals that are blocked and pending for the 
  82.  *      calling process.  It does nothing in this impementation.
  83.  *      
  84.  *      sigprocmask() is used to examine and/or change the 
  85.  *      signal mask for the calling process.  Either "set" or 
  86.  *      "oset" may be NULL in which case the appropriate 
  87.  *      operation is skipped.  "how" may be one of SIG_BLOCK, 
  88.  *      SIG_UNBLOCK or SIG_SETMASK.  If this package is built 
  89.  *      with USE_SIGNAL, then this routine achieves nothing.
  90.  *      
  91.  *      sigsuspend() sets the signal mask to "*mask" and waits 
  92.  *      for a signal to be delivered after which the previous 
  93.  *      mask is restored.
  94.  *      
  95.  *      
  96.  * RETURN VALUE:
  97.  *      0==success, -1==failure
  98.  *
  99.  * BUGS:
  100.  *      Since we fake most of this, don't expect fancy usage to 
  101.  *      work.
  102.  *
  103.  * AUTHOR:
  104.  *      Simon J. Gerraty <sjg@zen.void.oz.au>
  105.  */     
  106. /* COPYRIGHT:
  107.  *      @(#)Copyright (c) 1992 Simon J. Gerraty
  108.  *
  109.  *      This is free software.  It comes with NO WARRANTY.
  110.  *      Permission to use, modify and distribute this source code
  111.  *      is granted subject to the following conditions.
  112.  *      1/ that that the above copyright notice and this notice 
  113.  *      are preserved in all copies and that due credit be given 
  114.  *      to the author.  
  115.  *      2/ that any changes to this code are clearly commented 
  116.  *      as such so that the author does get blamed for bugs 
  117.  *      other than his own.
  118.  *      
  119.  *      Please send copies of changes and bug-fixes to:
  120.  *      sjg@zen.void.oz.au
  121.  *
  122.  */
  123. #ifndef lint
  124. static char  *RCSid = "$Id: sigact.c,v 1.10 93/05/08 16:00:06 sjg Exp $";
  125. #endif
  126.  
  127. #include <signal.h>
  128.  
  129. #ifndef __P
  130. # if defined(__STDC__) || defined(__cplusplus)
  131. #   define    __P(p)    p
  132. # else
  133. #   define    __P(p)    p
  134. # endif
  135. #endif
  136.  
  137.  
  138. /*
  139.  * some systems have a faulty sigaction() implementation!
  140.  * Allow us to bypass it.
  141.  * Or they may have installed sigact.h as signal.h which is why 
  142.  * we have SA_NOCLDSTOP defined.
  143.  */
  144. #if !defined(SA_NOCLDSTOP) || defined(_SIGACT_H) || defined(USE_SIGNAL) || defined(USE_SIGSET) || defined(USE_SIGMASK)
  145.  
  146. /*
  147.  * if we haven't been told,
  148.  * try and guess what we should implement with.
  149.  */
  150. #if !defined(USE_SIGSET) && !defined(USE_SIGMASK) && !defined(USE_SIGNAL)
  151. # if defined(sigmask) || defined(BSD) || defined(_BSD) && !defined(BSD41)
  152. #   define USE_SIGMASK
  153. # else
  154. #   ifndef NO_SIGSET
  155. #     define USE_SIGSET
  156. #   else
  157. #     define USE_SIGNAL
  158. #   endif
  159. # endif
  160. #endif
  161. /*
  162.  * if we still don't know, we're in trouble
  163.  */
  164. #if !defined(USE_SIGSET) && !defined(USE_SIGMASK) && !defined(USE_SIGNAL)
  165. error must know what to implement with
  166. #endif
  167.  
  168. #include "sigact.h"
  169.  
  170. /*
  171.  * in case signal() has been mapped to our Signal().
  172.  */
  173. #undef signal
  174.  
  175.  
  176. int
  177. sigaction(sig, act, oact)
  178.   int sig;
  179.   struct sigaction *act, *oact;
  180. {
  181.   SIG_HDLR (*oldh)();
  182.  
  183.   if (act)
  184.   {
  185. #ifdef USE_SIGSET
  186.     oldh = sigset(sig, act->sa_handler);
  187. #else
  188.     oldh = signal(sig, act->sa_handler);
  189. #endif
  190.   }
  191.   else
  192.   {
  193.     if (oact)
  194.     {      
  195. #ifdef USE_SIGSET
  196.       oldh = sigset(sig, SIG_IGN);
  197. #else
  198.       oldh = signal(sig, SIG_IGN);
  199. #endif
  200.       if (oldh != SIG_IGN && oldh !=  SIG_ERR)
  201.       {
  202. #ifdef USE_SIGSET
  203.     (void) sigset(sig, oldh);
  204. #else
  205.     (void) signal(sig, oldh);
  206. #endif
  207.       }
  208.     }
  209.   }
  210.   if (oact)
  211.   {
  212.     oact->sa_handler = oldh;
  213.   }
  214.   return 0;                /* hey we're faking it */
  215. }
  216.  
  217.  
  218. int
  219. sigaddset(mask, sig)
  220.   sigset_t *mask;
  221.   int sig;
  222. {
  223.   *mask |= sigmask(sig);
  224.   return 0;
  225. }
  226.  
  227.  
  228. int
  229. sigdelset(mask, sig)
  230.   sigset_t *mask;
  231.   int sig;
  232. {
  233.   *mask &= ~(sigmask(sig));
  234.   return 0;
  235. }
  236.  
  237.  
  238. int
  239. sigemptyset(mask)
  240.   sigset_t *mask;
  241. {
  242.   *mask = 0;
  243.   return 0;
  244. }
  245.  
  246.  
  247. int
  248. sigfillset(mask)
  249.   sigset_t *mask;
  250. {
  251.   *mask = ~0;
  252.   return 0;
  253. }
  254.  
  255.  
  256. int
  257. sigismember(mask, sig)
  258.   sigset_t *mask;
  259.   int sig;
  260. {
  261.   return ((*mask) & sigmask(sig));
  262. }
  263.  
  264.  
  265. int
  266. sigpending(set)
  267.   sigset_t *set;
  268. {
  269.   return 0;                /* faking it! */
  270. }
  271.  
  272.  
  273. int
  274. sigprocmask(how, set, oset)
  275.   int how;
  276.   sigset_t *set, *oset;
  277. {
  278. #ifdef USE_SIGSET
  279.   register int i;
  280. #endif
  281.   static sigset_t sm;
  282.   static int once = 0;
  283.  
  284.   if (!once)
  285.   {
  286.     /*
  287.      * initally we clear sm,
  288.      * there after, it represents the last
  289.      * thing we did.
  290.      */
  291.     once++;
  292. #ifdef USE_SIGMASK
  293.     sm = sigblock(0);
  294. #else
  295.     sm = 0;
  296. #endif
  297.   }
  298.   
  299.   if (oset)
  300.     *oset = sm;
  301.   if (set)
  302.   {
  303.     switch (how)
  304.     {
  305.     case SIG_BLOCK:
  306.       sm |= *set;
  307.       break;
  308.     case SIG_UNBLOCK:
  309.       sm &= ~(*set);
  310.       break;
  311.     case SIG_SETMASK:
  312.       sm = *set;
  313.       break;
  314.     }
  315. #ifdef USE_SIGMASK
  316.     (void) sigsetmask(sm);
  317. #else
  318. # ifdef USE_SIGSET
  319.     for (i = 1; i < NSIG; i++)
  320.     {
  321.       if (how == SIG_UNBLOCK)
  322.       {
  323.     if (*set & sigmask(i))
  324.       sigrelse(i);
  325.       }
  326.       else
  327.     if (sm & sigmask(i))
  328.     {
  329.       sighold(i);
  330.     }
  331.     }
  332. # endif
  333. #endif
  334.   }
  335.   return 0;
  336. }
  337.  
  338.  
  339. int
  340. sigsuspend(mask)
  341.   sigset_t *mask;
  342. {
  343. #ifdef USE_SIGMASK
  344.   sigpause(mask);
  345. #else
  346.   register int i;
  347.  
  348. # ifdef USE_SIGSET
  349.  
  350.   for (i = 1; i < NSIG; i++)
  351.   {
  352.     if (*mask & sigmask(i))
  353.     {
  354.       /* not the same sigpause() as above! */
  355.       sigpause(i);            
  356.       break;
  357.     }
  358.   }
  359. # else /* signal(2) only */
  360.   SIG_HDLR (*oldh)();
  361.  
  362.   /*
  363.    * make sure that signals in mask will not
  364.    * be ignored.
  365.    */
  366.   for (i = 1; i < NSIG; i++)
  367.   {
  368.     if (*mask & sigmask(i))
  369.     {
  370.       if ((oldh = signal(i, SIG_DFL)) !=  SIG_ERR &&
  371.       oldh != SIG_IGN &&
  372.       oldh != SIG_DFL)
  373.     (void) signal(i, oldh);        /* restore handler */
  374.     }
  375.   }
  376.   pause();                /* wait for a signal */
  377. # endif
  378. #endif
  379.   return 0;
  380. }
  381.  
  382. #endif /* ! SA_NOCLDSTOP */
  383.  
  384. #if !defined(SIG_HDLR)
  385. # define SIG_HDLR void
  386. #endif
  387. #if !defined(SIG_ERR)
  388. # define SIG_ERR    (SIG_HDLR (*)())-1
  389. #endif
  390.  
  391. /*
  392.  * an implementation of signal() using sigaction().
  393.  */
  394.  
  395. SIG_HDLR (*Signal(sig, handler)) __P((int))
  396.   int sig;
  397.   SIG_HDLR (*handler) __P((int));
  398. {
  399.   struct sigaction act, oact;
  400.  
  401.   act.sa_handler = handler;
  402.   sigemptyset(&act.sa_mask);
  403.   act.sa_flags = 0;
  404.   if (sigaction(sig, &act, &oact) < 0)
  405.     return (SIG_ERR);
  406.   return (oact.sa_handler);
  407. }
  408.  
  409. #if !defined(USE_SIGNAL) && !defined(USE_SIGMASK) && !defined(NO_SIGNAL)
  410. /*
  411.  * ensure we avoid signal mayhem
  412.  */
  413.  
  414. SIG_HDLR (*signal(sig, handler)) __P((int))
  415.   int sig;
  416.   SIG_HDLR (*handler) __P((int));
  417. {
  418.   return (Signal(sig, handler));
  419. }
  420. #endif
  421.  
  422. /* This lot (for GNU-Emacs) goes at the end of the file. */
  423. /* 
  424.  * Local Variables:
  425.  * version-control:t
  426.  * comment-column:40
  427.  * End:
  428.  */
  429.