first batch of license fixes (boring)
[oweals/gnunet.git] / src / util / signal.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2001, 2002, 2006 GNUnet e.V.
4
5      GNUnet is free software: you can redistribute it and/or modify it
6      under the terms of the GNU General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      Affero General Public License for more details.
14 */
15
16 /**
17  * @file util/signal.c
18  * @brief code for installing and uninstalling signal handlers
19  * @author Christian Grothoff
20  */
21
22 #include "platform.h"
23 #include "gnunet_util_lib.h"
24
25 #define LOG(kind,...) GNUNET_log_from (kind, "util-signal", __VA_ARGS__)
26
27
28 struct GNUNET_SIGNAL_Context
29 {
30
31   struct GNUNET_SIGNAL_Context *next;
32
33   struct GNUNET_SIGNAL_Context *prev;
34
35   int sig;
36
37   GNUNET_SIGNAL_Handler method;
38
39 #ifndef MINGW
40   struct sigaction oldsig;
41 #endif
42 };
43
44 static struct GNUNET_SIGNAL_Context *sc_head;
45
46 static struct GNUNET_SIGNAL_Context *sc_tail;
47
48
49 #ifdef WINDOWS
50 GNUNET_SIGNAL_Handler w32_sigchld_handler = NULL;
51 #endif
52
53 struct GNUNET_SIGNAL_Context *
54 GNUNET_SIGNAL_handler_install (int signum, GNUNET_SIGNAL_Handler handler)
55 {
56   struct GNUNET_SIGNAL_Context *ret;
57
58 #ifndef MINGW
59   struct sigaction sig;
60 #endif
61
62   ret = GNUNET_new (struct GNUNET_SIGNAL_Context);
63   ret->sig = signum;
64   ret->method = handler;
65 #ifndef MINGW
66   memset (&sig, 0, sizeof (sig));
67   sig.sa_handler = (void *) handler;
68   sigemptyset (&sig.sa_mask);
69 #ifdef SA_INTERRUPT
70   sig.sa_flags = SA_INTERRUPT;  /* SunOS */
71 #else
72   sig.sa_flags = SA_RESTART;
73 #endif
74   sigaction (signum, &sig, &ret->oldsig);
75 #else
76   if (signum == GNUNET_SIGCHLD)
77     w32_sigchld_handler = handler;
78   else
79   {
80     __p_sig_fn_t sigret = signal (signum, (__p_sig_fn_t) handler);
81
82     if (sigret == SIG_ERR)
83     {
84       LOG (GNUNET_ERROR_TYPE_WARNING, _("signal (%d, %p) returned %d.\n"),
85            signum, handler, sigret);
86     }
87   }
88 #endif
89   GNUNET_CONTAINER_DLL_insert_tail (sc_head, sc_tail, ret);
90   return ret;
91 }
92
93 void
94 GNUNET_SIGNAL_handler_uninstall (struct GNUNET_SIGNAL_Context *ctx)
95 {
96 #ifndef MINGW
97   struct sigaction sig;
98
99   sigemptyset (&sig.sa_mask);
100   sigaction (ctx->sig, &ctx->oldsig, &sig);
101 #endif
102   GNUNET_CONTAINER_DLL_remove (sc_head, sc_tail, ctx);
103   GNUNET_free (ctx);
104 }
105
106
107 /**
108  * Raise the given signal by calling the installed signal handlers.  This will
109  * not use the @em raise() system call but only calls the handlers registered
110  * through GNUNET_SIGNAL_handler_install().
111  *
112  * @param sig the signal to raise
113  */
114 void
115 GNUNET_SIGNAL_raise (const int sig)
116 {
117   struct GNUNET_SIGNAL_Context *ctx;
118
119   for (ctx = sc_head; NULL != ctx; ctx = ctx->next)
120   {
121     if (sig != ctx->sig)
122       continue;
123     if (NULL == ctx->method)
124       continue;
125     ctx->method ();
126   }
127 }