Date: Mon, 8 Dec 1997 16:58:42 +0200 (IST) From: Eli Zaretskii To: djgpp-workers AT delorie DOT com cc: DJ Delorie , Charles Sandmann Subject: Enhanced signal support (2/2) Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Precedence: bulk (Sorry about the empty message with the same subject.) This is the second part of the changes for SIGQUIT and user-definable INTR and QUIT keys. *** include/sys/exceptn.h~0 Tue Dec 5 03:39:44 1995 --- include/sys/exceptn.h Sat Dec 6 16:56:34 1997 *************** *** 31,42 **** extern unsigned short __djgpp_app_DS; /* Data selector invalidated by HW ints */ extern unsigned short __djgpp_ds_alias; /* Data selector always valid */ extern unsigned short __djgpp_dos_sel; /* Linear mem selector copy in locked mem */ ! extern unsigned short __djgpp_hwint_flags; /* 1 = Disable Ctrl-C; 2 = Count Ctrl-Break (don't kill) */ extern unsigned __djgpp_cbrk_count; /* Count of CTRL-BREAK hits */ extern int __djgpp_exception_inprog; /* Nested exception count */ void __djgpp_exception_toggle(void); int __djgpp_set_ctrl_c(int enable); /* On by default */ #endif /* !_POSIX_SOURCE */ #endif /* !__STRICT_ANSI__ */ --- 31,54 ---- extern unsigned short __djgpp_app_DS; /* Data selector invalidated by HW ints */ extern unsigned short __djgpp_ds_alias; /* Data selector always valid */ extern unsigned short __djgpp_dos_sel; /* Linear mem selector copy in locked mem */ ! /* Hardware Interrupt Flags: ! ! 1 = Disable INTR and QUIT keys (Ctrl-C and Ctrl-\); ! 2 = Count Ctrl-Break (don't kill); ! 4 = IRET from our timer interrupt handler, don't chain */ ! extern unsigned short __djgpp_hwint_flags; extern unsigned __djgpp_cbrk_count; /* Count of CTRL-BREAK hits */ extern int __djgpp_exception_inprog; /* Nested exception count */ + extern unsigned short __djgpp_sigint_key; /* key that raises SIGINT */ + extern unsigned short __djgpp_sigquit_key; /* key that raises SIGQUIT */ + extern unsigned short __djgpp_sigint_mask; /* kb mask for SIGINT key */ + extern unsigned short __djgpp_sigquit_mask;/* kb mask for SIGQUIT key */ + void __djgpp_exception_toggle(void); int __djgpp_set_ctrl_c(int enable); /* On by default */ + int __djgpp_set_sigint_key(int new_key); /* Set key which raises SIGINT */ + int __djgpp_set_sigquit_key(int new_key); /* Set key which raises SIGQUIT */ #endif /* !_POSIX_SOURCE */ #endif /* !__STRICT_ANSI__ */ *** src/libc/go32/dpmiexcp.c~0 Sun Oct 6 00:33:20 1996 --- src/libc/go32/dpmiexcp.c Sun Dec 7 12:37:44 1997 *************** except_to_sig(int excep) *** 82,87 **** --- 82,89 ---- return SIGTIMR; else if(excep == 0x79 || excep == 0x1b) return SIGINT; + else if(excep == 0x7a) + return SIGQUIT; else return SIGILL; } *************** do_faulting_finish_message(void) *** 178,184 **** if (signum == 0x1b) en = "Control-Break Pressed"; if (signum == 0x79) ! en = "Control-C Pressed"; if (en == 0) { err("Exception "); --- 180,188 ---- if (signum == 0x1b) en = "Control-Break Pressed"; if (signum == 0x79) ! en = "INTR key Pressed"; ! if (signum == 0x7a) ! en = "QUIT key Pressed"; if (en == 0) { err("Exception "); *************** __djgpp_exception_toggle(void) *** 345,350 **** --- 349,418 ---- } } + #define RSHIFT 1 + #define LSHIFT 2 + #define CTRL 4 + #define ALT 8 + #define SHIFT (RSHIFT | LSHIFT) + + #define DEFAULT_SIGINT 0x042e /* Ctrl-C: scan code 2Eh, kb status 04h */ + #define DEFAULT_SIGQUIT 0x042b /* Ctrl-\: scan code 2Bh, kb status 04h */ + + /* Make it so the key NEW_KEY will generate the signal SIG. + NEW_KEY must include the keyboard status byte in bits 8-15 and the + scan code in bits 0-7. */ + static int + set_signal_key(int sig, int new_key) + { + int old_key; + unsigned short *mask; + unsigned short *key; + unsigned short kb_status; + + if (sig == SIGINT) + { + mask = &__djgpp_sigint_mask; + key = &__djgpp_sigint_key; + } + else if (sig == SIGQUIT) + { + mask = &__djgpp_sigquit_mask; + key = &__djgpp_sigquit_key; + } + else + return -1; + + old_key = *key; + + *key = new_key & 0xffff; + kb_status = *key >> 8; + + *mask = 0x000f; /* Alt, Ctrl and Shift bits only */ + /* Mask off the RShift bit unless they explicitly asked for it. + Our keyboard handler pretends that LShift is pressed when they + press RShift. */ + if ((kb_status & RSHIFT) == 0) + *mask &= ~RSHIFT; + /* Mask off the LShift bit if any of the Ctrl or Alt are set, + since Shift doesn't matter when Ctrl and/or Alt are pressed. */ + if (kb_status & (CTRL | ALT)) + *mask &= ~LSHIFT; + + return old_key; + } + + int + __djgpp_set_sigint_key(int new_key) + { + return set_signal_key(SIGINT, new_key); + } + + int + __djgpp_set_sigquit_key(int new_key) + { + return set_signal_key(SIGQUIT, new_key); + } + void __djgpp_exception_setup(void) { *************** __djgpp_exception_setup(void) *** 352,357 **** --- 420,428 ---- __dpmi_meminfo lockmem; int i; + __djgpp_set_sigint_key(DEFAULT_SIGINT); + __djgpp_set_sigquit_key(DEFAULT_SIGQUIT); + for (i = 0; i < SIGMAX; i++) signal_list[i] = (SignalHandler)SIG_DFL; *************** _exit(int status) *** 417,419 **** --- 488,520 ---- __djgpp_exception_toggle (); __exit (status); } + + #ifdef TEST + + #include + + int + main(void) + { + volatile int count = 0; /* don't let gcc optimize it away */ + + __djgpp_set_sigint_key (0x0422); /* Ctrl-G */ + + while (1) + { + char buf[30]; + + count++; + if (count % 10000 == 0) + { + sprintf (buf, "counted to %d\r\n", count); + _write(STDERR_FILENO, buf, strlen (buf)); + } + if (count >= 1000000000L) + count = 0; + } + + return 0; + } + + #endif *** src/libc/go32/dpmiexcp.t~0 Thu Sep 12 02:12:48 1996 --- src/libc/go32/dpmiexcp.txh Sun Dec 7 13:49:46 1997 *************** void (*signal(int sig, void (*func)(int) *** 33,39 **** Signals are generated in response to some exceptional behavior of the program, such as division by 0. A signal can also report some asynchronous event outside the program, such as someone pressing a ! Ctrl-Break key combination. Signals are numbered 0..255 for software interrupts and 256..287 for exceptions (exception number plus 256); other implementation-specific --- 33,39 ---- Signals are generated in response to some exceptional behavior of the program, such as division by 0. A signal can also report some asynchronous event outside the program, such as someone pressing a ! @kbd{Ctrl- AT key{BREAK}} key combination. Signals are numbered 0..255 for software interrupts and 256..287 for exceptions (exception number plus 256); other implementation-specific *************** given a mnemonic which you should use fo *** 42,48 **** The default handling for all the signals is to print a traceback (a stack dump which describes the sequence of function calls leading to the ! generation of the signal) and abort the program. This function allows you to change the default behavior for a specific signal. It registers @var{func} as a signal handler for signal number --- 42,50 ---- The default handling for all the signals is to print a traceback (a stack dump which describes the sequence of function calls leading to the ! generation of the signal) and abort the program. (As an exception, the ! default handler for the signal @code{SIGINT} doesn't print the ! traceback when @kbd{Ctrl-C} is pressed.) This function allows you to change the default behavior for a specific signal. It registers @var{func} as a signal handler for signal number *************** particular signal, it will be called whe *** 51,71 **** execution of the program will be suspended until the handler returns or calls @code{longjmp} (@pxref{longjmp}). ! You may pass SIG_DFL as the value of @var{func} to reset the signal ! handling for the signal @var{sig} to default (also @xref{__djgpp_exception_toggle}, for a quick way to restore all the ! signals' handling to default), SIG_ERR to force an error when that ! signal happens, or SIG_IGN to ignore that signal. Signal handlers that ! you write are regular C functions, and may call any function that the ! ANSI/POSIX specs say are valid for signal handlers. For maximum ! portability, a handler for hardware interrupts and processor exceptions ! should only make calls to @code{signal}, assign values to data objects ! of type @code{volatile sig_atomic_t} (defined as @code{int} on ! @code{}) and return. Handlers for hardware interrupts need also be locked in memory (so that the operation of virtual memory ! mechanism won't swap them out), @xref{__dpmi_lock_linear_region, ! locking memory regions}. Handlers for software interrupts can also ! terminate by calling @code{abort}, @code{exit} or @code{longjmp}. The following signals are defined on @code{}: --- 53,73 ---- execution of the program will be suspended until the handler returns or calls @code{longjmp} (@pxref{longjmp}). ! You may pass @code{SIG_DFL} as the value of @var{func} to reset the ! signal handling for the signal @var{sig} to default (also @xref{__djgpp_exception_toggle}, for a quick way to restore all the ! signals' handling to default), @code{SIG_ERR} to force an error when ! that signal happens, or @code{SIG_IGN} to ignore that signal. Signal ! handlers that you write are regular C functions, and may call any ! function that the ANSI/POSIX specs say are valid for signal handlers. ! For maximum portability, a handler for hardware interrupts and processor ! exceptions should only make calls to @code{signal}, assign values to ! data objects of type @code{volatile sig_atomic_t} (defined as @code{int} ! on @code{}) and return. Handlers for hardware interrupts need also be locked in memory (so that the operation of virtual memory ! mechanism won't swap them out), @xref{__dpmi_lock_linear_region, locking ! memory regions}. Handlers for software interrupts can also terminate by ! calling @code{abort}, @code{exit} or @code{longjmp}. The following signals are defined on @code{}: *************** unknown/invalid exceptions. *** 90,97 **** @item SIGINT ! The Interrupt signal. Generated when a @kbd{Ctrl-C} or @kbd{Ctrl-Break} ! (Int 1Bh) key is hit. Note that when you open the console in binary mode, or switch it to binary mode by a call to @code{setmode} (@pxref{setmode}), generation of @code{SIGINT} as result of @kbd{Ctrl-C} key is disabled. This is so for programs (such as Emacs) which want to --- 92,100 ---- @item SIGINT ! The Interrupt signal. Generated when an INTR key (@kbd{Ctrl-C} by ! default) or @kbd{Ctrl- AT key{BREAK}} (Int 1Bh) key is hit. ! Note that when you open the console in binary mode, or switch it to binary mode by a call to @code{setmode} (@pxref{setmode}), generation of @code{SIGINT} as result of @kbd{Ctrl-C} key is disabled. This is so for programs (such as Emacs) which want to *************** be able to read the @samp{^C} character *** 99,110 **** library function @code{__djgpp_set_ctrl_c} to restore @code{SIGINT} generation when @kbd{Ctrl-C} is hit, if you need this. @xref{__djgpp_set_ctrl_c}, for details on how this should be done. ! @kbd{Ctrl-Break} always generates @code{SIGINT}. DJGPP hooks the keyboard hardware interrupt (Int 09h) to be able to generate @code{SIGINT} in response to @kbd{Ctrl-C} key; you should be aware of this when you install a handler for the keyboard interrupt. @item SIGSEGV The invalid storage access (Segmentation Violation) signal. Generated --- 102,117 ---- library function @code{__djgpp_set_ctrl_c} to restore @code{SIGINT} generation when @kbd{Ctrl-C} is hit, if you need this. @xref{__djgpp_set_ctrl_c}, for details on how this should be done. ! @kbd{Ctrl- AT key{BREAK}} always generates @code{SIGINT}. DJGPP hooks the keyboard hardware interrupt (Int 09h) to be able to generate @code{SIGINT} in response to @kbd{Ctrl-C} key; you should be aware of this when you install a handler for the keyboard interrupt. + Note that the key which generates @code{SIGINT} can be changed with a + call to @code{__djgpp_set_sigint_key} function. + @xref{__djgpp_set_sigint_key}. + @item SIGSEGV The invalid storage access (Segmentation Violation) signal. Generated *************** The Broken Pipe signal. Currently unuse *** 144,150 **** @item SIGQUIT ! The Quit signal. Currently unused. @item SIGUSR1 --- 151,160 ---- @item SIGQUIT ! The Quit signal. Generated when the QUIT key (@kbd{Ctrl-\} by default) ! is hit. The key that raises the signal can be changed with a call to ! @code{__djgpp_set_sigquit_key} function. ! @xref{__djgpp_set_sigquit_key}. @item SIGUSR1 *************** int __djgpp_set_ctrl_c(int enable); *** 218,239 **** @subheading Description ! This function sets and resets the bit which controls whether ! @code{SIGINT} (@pxref{signal, SIGINT}) will be raised when you press ! @kbd{Ctrl-C}. By default @kbd{Ctrl-C} generates an interrupt signal which, if uncaught by a signal handler, will abort your program. However, when you call the @code{setmode} library function to switch the console reads to binary mode, or open the console in binary mode for ! reading, this generation of interrupt signal is turned off, because some ! programs want to get the @samp{^C} characters as any other character and ! handle them by themselves. @code{__djgpp_set_ctrl_c} lets you explicitly determine the effect of ! @kbd{Ctrl-C}. When called with non-zero value of @var{enable}, it ! arranges for @kbd{Ctrl-C} to generate an interrupt; if you call it with ! a zero in @var{enable}, @kbd{Ctrl-C} are treated as normal characters. ! Note that the effect of @kbd{Ctrl-Break} key is unaffected by this function; use the @code{_go32_want_ctrl_break} library function to control it. --- 228,253 ---- @subheading Description ! This function sets and resets the bit which controls whether signals ! @code{SIGINT} and @code{SIGQUIT} (@pxref{signal}) will be raised when ! you press the INTR or QUIT keys. By default these generate signals which, if uncaught by a signal handler, will abort your program. However, when you call the @code{setmode} library function to switch the console reads to binary mode, or open the console in binary mode for ! reading, this generation of signals is turned off, because some ! programs want to get the @samp{^C} and @samp{^\} characters as any other ! character and handle them by themselves. @code{__djgpp_set_ctrl_c} lets you explicitly determine the effect of ! INTR and QUIT keys. When called with non-zero value of ! @var{enable}, it arranges for @code{SIGINT} and @code{SIGQUIT} signals ! to be generated when the appropriate key is pressed; if you call it with ! a zero in @var{enable}, these keys are treated as normal characters. ! ! For getting similar effects via the POSIX @code{termios} functions, see ! @ref{tcsetattr}. ! Note that the effect of @kbd{Ctrl- AT key{BREAK}} key is unaffected by this function; use the @code{_go32_want_ctrl_break} library function to control it. *************** returns. *** 246,253 **** @subheading Return Value ! The previous state of the @kbd{Ctrl-C} effect: 0 if the generation of ! @code{SIGINT} by @kbd{Ctrl-C} was disabled, 1 if it was enabled. @subheading Example --- 260,267 ---- @subheading Return Value ! The previous state of @code{SIGINT} and @code{SIGQUIT} generation: 0 if ! it was disabled, 1 if it was enabled. @subheading Example *************** also passed to the parent). *** 291,295 **** --- 305,465 ---- __djgpp_exception_toggle(); system("myprog"); __djgpp_exception_toggle(); + + @end example + + @c ------------------------------------------------------------------------- + + @node __djgpp_set_sigint_key, signal + @subheading Syntax + + @example + + #include + + void __djgpp_set_sigint_key(int new_key); + + @end example + + + @subheading Description + + This function changes the INTR key that generates the signal + @code{SIGINT}. By default, @kbd{Ctrl-C} is set as the INTR key. To + replace it with another key, put the @emph{scan code} of the new INTR + key into the bits 0-7 and the required keyboard status byte into bits + 8-15 of @var{new_key}, and call this function. Here's how the keyboard + status bits are defined: + + @example + + Bit + 76543210 Meaning + + .......X Right Shift key + ......X. Left Shift key + .....X.. Ctrl key + ....X... Alt key + ...X.... Scroll Lock key + ..X..... Num Lock key + .X...... Caps Lock key + X....... Insert + + @end example + + @noindent + A 1 in any of the above bits means that the corresponding key should be + pressed; a zero means it should be released. Currently, all but the + lower 4 bits are always ignored by the DJGPP keyboard handler when + you set the INTR key using this function. + + For example, the default @kbd{Ctrl-C} key should be passed as + @code{0x042e}, since the scan code of the @key{C} key is 2Eh, and when + the @key{Ctrl} key is pressed, the keyboard status byte is 04h. + + To disable @code{SIGINT} generation, pass zero as the argument (since no + key has a zero scan code). + + This function will set things up so that the left @key{Shift} key + doesn't affect Ctrl- and Alt-modified keys; the right @key{Shift} key + won't affect them either, unless its bit is explicitly set in + @var{new_key}. This means that @kbd{Ctrl-C} and @kbd{Ctrl-c} will both + trigger @code{SIGINT} if @code{0x042e} is passed to this function. + + The DJGPP built-in keyboard handler pretends that when the right + @key{Shift} key is pressed, so is the left @key{Shift} key (but not vice + versa). + + For getting similar effects via the POSIX @code{termios} functions, see + @ref{tcsetattr}. + + @subheading Return Value + + The previous INTR key (scan code in bits 0-7, keyboad status in bits + 8-15). + + @subheading Example + + @example + + __djgpp_set_sigint_key(0x0422); /* make Ctrl-g generate SIGINT's */ + + @end example + + @c ------------------------------------------------------------------------- + + @node __djgpp_set_sigquit_key, signal + @subheading Syntax + + @example + + #include + + void __djgpp_set_sigquit_key(int new_key); + + @end example + + + @subheading Description + + This function changes the QUIT key that generates the signal + @code{SIGQUIT}. By default, @kbd{Ctrl-\} is set as the QUIT key. To + replace it with another key, put the @emph{scan code} of the new QUIT + key into the bits 0-7 and the required keyboard status byte into bits + 8-15 of @var{new_key}, and call this function. Here's how the keyboard + status bits are defined: + + @example + + Bit + 76543210 Meaning + + .......X Right Shift key + ......X. Left Shift key + .....X.. Ctrl key + ....X... Alt key + ...X.... Scroll Lock key + ..X..... Num Lock key + .X...... Caps Lock key + X....... Insert + + @end example + + @noindent + A 1 in any of the above bits means that the corresponding key should be + pressed; a zero means it should be released. Currently, all but the + lower 4 bits are always ignored by the DJGPP keyboard handler when + you set the QUIT key with this function. + + For example, the default @kbd{Ctrl-\} key should be passed as + @code{0x042b}, since the scan code of @code{\} is 2Bh and when the + @key{Ctrl} key is pressed, the keyboard status byte is 04h. + + To disable @code{SIGQUIT} generation, pass zero as the argument (since + no key has a zero scan code). + + This function will set things up so that the left @key{Shift} key + doesn't affect Ctrl- and Alt-modified keys; the right @key{Shift} key + won't affect them either, unless its bit is explicitly set in + @var{new_key}. This means that @kbd{Ctrl-\} and @kbd{Ctrl-|} will both + trigger @code{SIGQUIT} if @code{0x042b} is passed to this function. + + The DJGPP built-in keyboard handler pretends that when the right + @key{Shift} key is pressed, so is the left @key{Shift} key (but not vice + versa). + + For getting similar effects via the POSIX @code{termios} functions, see + @ref{tcsetattr}. + + @subheading Return Value + + The previous QUIT key (scan code in bits 0-7, keyboad status in bits + 8-15). + + @subheading Example + + @example + + __djgpp_set_sigint_key(0); /* disable SIGQUIT's */ @end example