Watt-32 tcp/ip  2.2 dev-rel.10
pc_cbrk.c
Go to the documentation of this file.
1 
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <setjmp.h>
8 #include <signal.h>
9 
10 #include "copyrigh.h"
11 #include "wattcp.h"
12 #include "sock_ini.h"
13 #include "wdpmi.h"
14 #include "x32vm.h"
15 #include "misc.h"
16 #include "printk.h"
17 #include "bsddbug.h"
18 #include "language.h"
19 #include "strings.h"
20 
21 #if defined(__DJGPP__)
22 #include <sys/exceptn.h>
23 #endif
24 
25 #if defined(__HIGHC__)
26  extern UINT _mwstack_limit[2]; /* stack-check limits */
27  pragma Alias (_mwstack_limit, "_mwstack_limit");
28  #undef SIGBREAK /* SIGBREAK == SIGQUIT */
29 
30 #elif defined(__DMC__) /* ditto */
31  #undef SIGBREAK
32 #endif
33 
34 #if defined(TEST_PROG) && !defined(__CYGWIN__)
35  #include <conio.h>
36  #undef outsnl
37  #define outsnl(str) cputs (str)
38 #endif
39 
44 #include "nochkstk.h"
45 
47 volatile int _watt_cbroke = 0;
49 static int cbreak_mode;
50 static jmp_buf sig_jmp;
51 
73 void MS_CDECL sig_handler_watt (int sig)
74 {
75 #if defined(TEST_PROG)
76  BEEP();
77 
78  #if defined(__CYGWIN__) && 0
79  _watt_cbroke++;
80  longjmp (sig_jmp, sig);
81  #endif
82 #endif
83 
84  if (_watt_handle_cbreak) /* inside _arp_resolve(), lookup_domain() etc. */
85  {
86  _watt_cbroke++;
87  if (cbreak_mode & 0x10)
88  outsnl (_LANG("\nInterrupting"));
89  }
90  else if (cbreak_mode & 1)
91  {
92  outsnl (_LANG("\nBreaks ignored"));
93  }
94  else
95  {
96 #if defined(WIN32)
97  _watt_cbroke++;
98 #else
99 #if defined(__HIGHC__)
100  static UINT new_stk [1024];
101  _mwstack_limit[1] = (UINT)&new_stk; /* set new Bottom-Of-Stack */
102 #elif defined(__DJGPP__)
103  signal (sig, SIG_IGN); /* ignore until we quit */
104 #endif
105  _watt_cbroke++;
106  longjmp (sig_jmp, sig); /* jump back to where setjmp() was called */
107 #endif /* WIN32 */
108  }
109 
110  signal (sig, sig_handler_watt); /* rearm our handler */
111 
112 #if !defined(WIN32)
113  /* !! Seems the BREAK state of NTVDM gets reenabled when pressing ^C.
114  * So disable the state again (not reentrant)
115  */
116  if (sig == SIGINT && (cbreak_mode & 1))
117  set_cbreak (0);
118 #endif
119 }
120 
129 int set_cbreak (int want_brk)
130 {
131 #if defined(WIN32)
132  ARGSUSED (want_brk);
133  return (0);
134 #else
135  IREGS reg;
136  WORD brk;
137 
138 #if 0
139  /*
140  * After much testing (ref .\tests\pc_cbrk.exe), I found the following
141  * to be most reliable for both DOS and Windows-NT. Using any combination
142  * of `cbreak_mode' and pressing ^C seems to work in Win-NT, but ^Break still
143  * have problems...
144  */
145  __djgpp_set_ctrl_c (want_brk & 1);
146 
147  /* don't count ^Breaks; the 0x1B vector isn't always restored
148  * at program exit
149  */
150  _go32_want_ctrl_break (want_brk & 1);
151 #endif
152 
153  reg.r_ax = 0x3300; /* get normal BREAK state */
154  GEN_INTERRUPT (0x21, &reg);
155  brk = loBYTE (reg.r_dx);
156 
157 #if 0
158  if (want_brk & 0x0100)
159  {
160  reg.r_ax = 0x3302;
161  GEN_INTERRUPT (0x21, &reg);
162  brk |= loBYTE(reg.r_dx) << 8;
163  }
164 #endif
165 
166  if (want_brk == 0)
167  {
168  reg.r_ax = 0x3301; /* set normal BREAK state off */
169  reg.r_dx = 0;
170  GEN_INTERRUPT (0x21, &reg);
171  reg.r_ax = 0x3302; /* set extended BREAK state off */
172  reg.r_dx = 0;
173  GEN_INTERRUPT (0x21, &reg);
174  }
175  else /* set normal/extended BREAK state on */
176  {
177  reg.r_ax = (want_brk >= 0x0100) ? 0x3302 : 0x3301;
178  reg.r_dx = 1;
179  GEN_INTERRUPT (0x21, &reg);
180  }
181  return (brk);
182 #endif /* WIN32 */
183 }
184 
185 #if defined(WIN32) && 0
186 /*
187  * Ref. http://msdn.microsoft.com/en-us/library/ms683242(v=vs.85).aspx
188  */
189 static BOOL WINAPI console_handler (DWORD event)
190 {
191  if (event == CTRL_C_EVENT || event == CTRL_BREAK_EVENT)
192  {
193  sig_handler_watt (SIGINT);
194  return (TRUE);
195  }
196  return (FALSE);
197 }
198 #endif /* WIN32 */
199 
200 
207 int W32_CALL tcp_cbreak (int mode)
208 {
209  volatile int rc = 0;
210 
211  signal (SIGINT, sig_handler_watt);
212 
213 #if defined(SIGBREAK)
214  signal (SIGBREAK, sig_handler_watt);
215 #endif
216 
217 #if defined(__CYGWIN__) && 0
218  {
219  static sigset_t old_mask, new_mask;
220 
221  sigemptyset (&new_mask);
222  sigaddset (&new_mask, SIGINT);
223  sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
224  }
225 #endif
226 
227 #if defined(__DJGPP__)
228  if (win32_dos_box)
229  rc = set_cbreak (0); /* ignore DOS BREAK checking */
230  else
231 #endif
232  rc = set_cbreak (!(mode & 1));
233 
234  cbreak_mode = mode;
235 
236  {
237  int sig;
238 
239  /* Some vendors calls signal-handlers with a very limited stack.
240  * We longjmp() out of it to restore to a safe stack.
241  */
242  sig = setjmp (sig_jmp);
243  if (sig)
244  sock_sig_exit ("\nTerminating.", sig);
245  }
246  return (rc);
247 }
248 
249 /*
250  * Return TRUE if ^C/^Break should be disabled
251  */
252 BOOL tcp_cbreak_off (void)
253 {
254  return (cbreak_mode & 1);
255 }
256 
257 #if defined(TEST_PROG)
258 
259 void usage (char *argv0)
260 {
261  printf ("Usage: %s normal | nobrk | graceful\n", argv0);
262  exit (-1);
263 }
264 
265 int old_brk = -1;
266 
267 int main (int argc, char **argv)
268 {
269  int mode = 0, show_brk = 1;
270 
271  if (argc != 2)
272  usage (argv[0]);
273 
274  if (!stricmp(argv[1],"normal"))
275  {
276  mode = 0x10;
278  }
279  else if (!stricmp(argv[1],"nobrk"))
280  {
281  mode = 0x01;
283  puts ("Press <^BREAK> three times to exit");
284  }
285  else if (!stricmp(argv[1],"graceful"))
286  {
287  mode = 0x00;
289  puts ("Press <^C> or <^BREAK> three times to exit");
290  }
291  else
292  usage (argv[0]);
293 
294  if (show_brk)
295  mode |= 0x10;
296 
297  old_brk = tcp_cbreak (mode);
298  _watt_cbroke = 0;
299 
300  while (_watt_cbroke < 3)
301  {
302  usleep (200000);
303 
304 #ifdef __MSDOS__
305  /* PEEKB on djgpp changes the FS register. This is just to
306  * test if SIGINT handler restores FS/GS registers.
307  */
308  (void) PEEKB (0, 0);
309 #endif
310 
311 #ifdef __CYGWIN__
312  // os_yield(); /* Hard to raise SIGINT on Cygwin w/o this. */
313 #endif
314 
315  kbhit();
316  putchar ('.');
317  fflush (stdout);
318  }
319  printf ("`_watt_cbroke' set %d times\n", _watt_cbroke);
320  set_cbreak (old_brk);
321  return (1);
322 }
323 #endif /* TEST_PROG */
void MS_CDECL sig_handler_watt(int sig)
SIGINT/SIGBREAK handler function.
Definition: pc_cbrk.c:73
Core definitions.
WORD _watt_handle_cbreak
Turn off stack-checking here because stack may be out of bounds.
Definition: pc_cbrk.c:46
void W32_CALL sock_sig_exit(const char *msg, int sig)
Exit handler for unhandled signals.
Definition: sock_ini.c:1057
int W32_CALL tcp_cbreak(int mode)
Sets our break mode.
Definition: pc_cbrk.c:207
int set_cbreak(int want_brk)
Sets normal and extended BREAK mode.
Definition: pc_cbrk.c:129
volatile int _watt_cbroke
Definition: pc_cbrk.c:47
BOOL win32_dos_box
Definition: misc.c:59
Definition: misc.h:511
int main(int argc, char **argv)
Definition: echo.c:223