Watt-32 tcp/ip  2.2 dev-rel.10
signal.c
Go to the documentation of this file.
1 
5 /* BSD sockets functionality for Watt-32 TCP/IP
6  *
7  * Copyright (c) 1997-2007 Gisle Vanem <gvanem@yahoo.no>
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  * must display the following acknowledgement:
19  * This product includes software developed by Gisle Vanem
20  * Bergen, Norway.
21  *
22  * THIS SOFTWARE IS PROVIDED BY ME (Gisle Vanem) AND CONTRIBUTORS ``AS IS''
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED. IN NO EVENT SHALL I OR CONTRIBUTORS BE LIABLE FOR ANY
26  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Version
34  *
35  * 0.5 : Dec 18, 1997 : G. Vanem - created
36  */
37 
38 #include "socket.h"
39 
40 #if defined(USE_BSD_API)
41 
42 #include "nochkstk.h"
43 
44 #if defined(__HIGHC__) /* Metaware's HighC have SIGBREAK == SIGQUIT */
45  #undef SIGBREAK
46 #elif defined(__DMC__) /* Digital Mars have SIGBREAK == SIGINT */
47  #undef SIGBREAK
48 #endif
49 
50 /*
51  * I'm not sure what the benefit of using sigprocmask() on djgpp is.
52  * So leave it alone for the moment.
53  */
54 #if defined(__DJGPP__)
55  #define USE_SIGMASK 0
56 #else
57  #define USE_SIGMASK 0
58 #endif
59 
60 struct signal_table {
61  void (MS_CDECL *old)(int);
62  int sig_num;
63  const char *sig_name;
64  BOOL caught; /* we caught this signal */
65  BOOL exit; /* exit if app doesn't have a signal-handler */
66  };
67 
68 static struct signal_table sig_tab[] = {
69  { NULL, SIGINT, "SIGINT", FALSE, TRUE },
70 #if defined(SIGBREAK)
71  { NULL, SIGBREAK, "SIGBREAK",FALSE, TRUE }, /* Watcom */
72 #endif
73 #if defined(SIGQUIT)
74  { NULL, SIGQUIT, "SIGQUIT", FALSE, TRUE }, /* should we trap this? */
75 #endif
76 #if defined(SIGPIPE)
77  { NULL, SIGPIPE, "SIGPIPE", FALSE, FALSE }, /* djgpp */
78 #endif
79 #if defined(SIGALRM) && 0 /* Should we hook this? */
80  { NULL, SIGALRM, "SIGALRM", FALSE, FALSE }, /* djgpp */
81 #endif
82  };
83 
84 static int signal_depth = 0; /* Our running signal "depth" */
85 
86 /*
87  * We block all signals from being raised while running our
88  * loops (connect etc.). Postpone all original signal-handlers until
89  * we're done.
90  */
91 #if (USE_SIGMASK == 0)
92 /*
93  * Our signal catcher. Set 'caught' flag.
94  */
95 static void MS_CDECL sig_catch (int sig)
96 {
97  int i;
98 
99  for (i = 0; i < DIM(sig_tab); i++)
100  if (sig == sig_tab[i].sig_num)
101  {
102  sig_tab[i].caught = TRUE;
103  break;
104  }
105  signal (sig, SIG_IGN); /* ignore until we restore it */
106 }
107 #endif
108 
109 /*
110  * Signal handling for most loops where we can be interrupted
111  * by user pressing ^C/^Break (generating SIGINT/SIGBREAK).
112  */
113 int _sock_sig_setup (void)
114 {
115 #if (USE_SIGMASK)
116  static sigset_t old_mask, new_mask;
117 #endif
118  int i;
119 
120  if (signal_depth > 0 ||
121  ++signal_depth > 1)
122  return (0);
123 
124  _sock_start_timer();
125 
126 #if (USE_SIGMASK)
127  sigemptyset (&new_mask);
128 #endif
129 
130  for (i = 0; i < DIM(sig_tab); i++)
131  {
132  struct signal_table *sig = sig_tab + i;
133 
134  sig->caught = FALSE;
135 
136 #if (USE_SIGMASK)
137  sigaddset (&new_mask, sig->sig_num);
138  sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
139 #else
140  sig->old = signal (sig->sig_num, sig_catch);
141 #endif
142  }
143  return (0);
144 }
145 
146 /*
147  * Return number of blocked signal that are pending/caught.
148  */
149 int _sock_sig_pending (void)
150 {
151  int i, num = 0;
152 
153 #if (USE_SIGMASK)
154  sigset_t pending;
155 
156  sigpending (&pending);
157  for (i = 0; i < DIM(sig_tab); i++)
158  if (sigismember(&pending, sig_tab[i].sig_num))
159  num++;
160 #else
161  for (i = 0; i < DIM(sig_tab); i++)
162  if (sig_tab[i].caught)
163  num++;
164 #endif
165  return (num);
166 }
167 
168 /*
169  * Unhook signal-handlers and raise() signals we caught.
170  */
171 int _sock_sig_restore (void)
172 {
173  int i;
174 
175  if (signal_depth == 0 ||
176  --signal_depth > 0)
177  return (0);
178 
179  _sock_stop_timer();
180 
181  for (i = 0; i < DIM(sig_tab); i++)
182  {
183  struct signal_table *sig = sig_tab + i;
184 
185 #if (USE_SIGMASK)
186  sigset_t pending, new_set;
187 
188  if (sigpending(&pending) == 0 &&
189  sigismember(&pending,sig->sig_num))
190  {
191  /* The signal became pending while we blocked it.
192  * I.e. ^C was pressed, so act on it.
193  */
194  sigemptyset (&new_set);
195  sigaddset (&new_set, sig->sig_num);
196 
197  SOCK_DEBUGF ((", raising %s", sig->sig_name));
198  SOCK_ENTER_SCOPE();
199  sigprocmask (SIG_UNBLOCK, &new_set, NULL);
200  SOCK_LEAVE_SCOPE();
201  }
202 #else
203  signal (sig->sig_num, sig->old);
204  if (!sig->caught)
205  continue;
206 
207  sig->caught = FALSE;
208  if (sig->exit &&
209  (sig->old == SIG_DFL ||
210  sig->old == SIG_IGN ||
211  sig->old == sig_handler_watt))
212  {
213  char buf[30];
214 
215  strcpy (buf, "\nTerminating on ");
216  strcat (buf, sig->sig_name);
217  sock_sig_exit (buf, sig->sig_num);
218  /* no return */
219  }
220  SOCK_DEBUGF ((", raising %s", sig->sig_name));
221  SOCK_ENTER_SCOPE();
222  raise (sig->sig_num);
223  SOCK_LEAVE_SCOPE();
224  return (-1);
225 #endif
226  }
227  return (0);
228 }
229 
230 /*
231  * Raise SIGPIPE/SIGURG if signal defined (not needed yet).
232  * Return -1 with errno = EPIPE.
233  */
234 int _sock_sig_epipe (const Socket *sock)
235 {
236 #if defined(SIGPIPE)
237  if (!sock->msg_nosig)
238  raise (SIGPIPE);
239 #endif
240  SOCK_ERRNO (EPIPE);
241  ARGSUSED (sock);
242  return (-1);
243 }
244 #endif /* USE_BSD_API */
Definition: socket.h:137
void W32_CALL sock_sig_exit(const char *msg, int sig)
Exit handler for unhandled signals.
Definition: sock_ini.c:1057
void MS_CDECL sig_handler_watt(int sig)
SIGINT/SIGBREAK handler function.
Definition: pc_cbrk.c:73