Date: Sun, 18 Jan 1998 16:28:24 +0200 (IST) From: Eli Zaretskii To: DJ Delorie cc: djgpp-workers AT delorie DOT com Subject: Re: Request for comments: SIGQUIT in DJGPP v2.02 In-Reply-To: <199801111908.OAA25285@delorie.com> Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Precedence: bulk On Sun, 11 Jan 1998, DJ Delorie wrote: > The default handler for SIGQUIT should be SIG_IGN instead of unix's > standard core dump. Even setting SIGQUIT to SIG_DFL should set it to > SIG_IGN. When SIGQUIT is ignored, that key should be treated as any > other key. Attached below please find the patches which introduce SIGQUIT support along these lines, including some simple changes to header files and the docs. These changes also add the ability to change the INTR and QUIT keys from the application code. *** src/libc/go32/exceptn.S~0 Sun Dec 10 20:36:18 1995 --- src/libc/go32/exceptn.S Sun Dec 7 14:04:04 1997 *************** *** 257,262 **** --- 257,270 ---- ___djgpp_dos_sel: .word 0 .global ___djgpp_hwint_flags ___djgpp_hwint_flags: .word 0 + .global ___djgpp_sigint_key + ___djgpp_sigint_key: .word 0 /* scan code and kb status */ + .global ___djgpp_sigint_mask + ___djgpp_sigint_mask: .word 0 /* kb status mask */ + .global ___djgpp_sigquit_key + ___djgpp_sigquit_key: .word 0 + .global ___djgpp_sigquit_mask + ___djgpp_sigquit_mask: .word 0 .global ___djgpp_old_kbd ___djgpp_old_kbd: .long 0,0 .global ___djgpp_old_timer *************** *** 287,315 **** .global ___djgpp_kbd_hdlr ___djgpp_kbd_hdlr: pushl %eax pushl %ds .byte 0x2e /* CS: */ testb $1, ___djgpp_hwint_flags /* Disable? */ jne Lkbd_chain - /* Check CTRL state */ movw %cs:___djgpp_dos_sel, %ds /* Conventional mem selector */ /* movw $0x7021,0xb0f00 */ /* Test code - write to mono */ ! testb $4,0x417 /* Test KB flags: CTRL down? */ ! je Lkbd_chain ! testb $8,0x417 /* Test KB flags: ALT down? */ ! jne Lkbd_chain /* Don't capture ALT-CTRL-C */ ! /* Check port for scan code */ ! inb $0x60,%al ! cmpb $0x2e,%al jne Lkbd_chain /* Clear interrupt, (later: remove byte from controller?) movb $0x20,%al outb %al,$0x020 */ 98: ! movb $0x79,%al call ___djgpp_hw_exception Lkbd_chain: popl %ds popl %eax ljmp %cs:___djgpp_old_kbd --- 295,335 ---- .global ___djgpp_kbd_hdlr ___djgpp_kbd_hdlr: pushl %eax + pushl %ebx pushl %ds .byte 0x2e /* CS: */ testb $1, ___djgpp_hwint_flags /* Disable? */ jne Lkbd_chain movw %cs:___djgpp_dos_sel, %ds /* Conventional mem selector */ /* movw $0x7021,0xb0f00 */ /* Test code - write to mono */ ! /* Check Keyboard status bits */ ! movb 0x417,%ah /* Get KB status byte */ ! testb $1,%ah ! je 6f ! orb $2,%ah /* If RShift is set, set LShift as well */ ! 6: ! inb $0x60,%al /* Read the scan code */ ! movb %ah,%bh /* Save KB status */ ! andb %cs:___djgpp_sigint_mask, %ah /* Mask off irrelevant bits */ ! cmpw %cs:___djgpp_sigint_key, %ax /* Test for SIGINT */ ! jne 7f ! movb $0x79,%bh /* SIGINT */ ! jmp 98f ! 7: ! movb %bh,%ah /* Restore KB status */ ! andb %cs:___djgpp_sigquit_mask, %ah /* Mask off irrelevant bits */ ! cmpw %cs:___djgpp_sigquit_key, %ax /* Test for SIGQUIT*/ jne Lkbd_chain + movb $0x7a,%bh /* SIGQUIT */ /* Clear interrupt, (later: remove byte from controller?) movb $0x20,%al outb %al,$0x020 */ 98: ! movb %bh,%al call ___djgpp_hw_exception Lkbd_chain: popl %ds + popl %ebx popl %eax ljmp %cs:___djgpp_old_kbd *** src/libc/go32/dpmiexcp.c~5 Fri Jan 2 04:51:04 1998 --- src/libc/go32/dpmiexcp.c Sun Jan 18 14:41:38 1998 *************** *** 5,10 **** --- 5,11 ---- #include #include #include + #include #include #include #include *************** *** 82,87 **** --- 83,90 ---- return SIGTIMR; else if(excep == 0x79 || excep == 0x1b) return SIGINT; + else if(excep == 0x7a) + return SIGQUIT; else return SIGILL; } *************** *** 178,185 **** else if (signum == 0x1b) en = "Control-Break Pressed"; else if (signum == 0x79) ! en = "Control-C Pressed"; ! else if (en == 0) { if (fake_exception) err("Raised"); --- 181,190 ---- else if (signum == 0x1b) en = "Control-Break Pressed"; else if (signum == 0x79) ! en = "INTR key Pressed"; ! else if (signum == 0x7a) ! en = "QUIT key Pressed"; ! if (en == 0) { if (fake_exception) err("Raised"); *************** *** 218,223 **** --- 223,232 ---- err(", error="); itox(errorcode, 4); } } + if (except_to_sig(signum) == SIGFPE) + { + err(", x87 status="); itox(_status87(), 4); + } err("\r\neax="); itox(__djgpp_exception_state->__eax, 8); err(" ebx="); itox(__djgpp_exception_state->__ebx, 8); err(" ecx="); itox(__djgpp_exception_state->__ecx, 8); *************** *** 262,321 **** static const char signames[] = "ABRTFPE ILL SEGVTERMALRMHUP INT KILLPIPEQUITUSR1USR2NOFPTRAP"; int raise(int sig) { SignalHandler temp; - jmp_buf fake_exception; if(sig <= 0) return -1; if(sig > SIGMAX) return -1; temp = signal_list[sig - 1]; ! if(temp == (SignalHandler)SIG_IGN) return 0; /* Ignore it */ if(temp == (SignalHandler)SIG_DFL) ! { ! traceback_exit: ! if (sig >= SIGABRT && sig <= SIGTRAP) ! { ! if (!__djgpp_exception_state_ptr) ! { ! /* This is a software signal, like SIGABRT or SIGKILL. ! Fill the exception structure, so we get the traceback. */ ! __djgpp_exception_state_ptr = &fake_exception; ! if (setjmp(__djgpp_exception_state)) ! { ! err("Bad longjmp to __djgpp_exception_state--aborting\r\n"); ! do_faulting_finish_message(0); /* does not return */ ! } ! else ! /* Fake the exception number. 7Ah is the last one hardwired ! inside exceptn.S, for SIGQUIT. */ ! __djgpp_exception_state->__signum = 0x7a + 1 + sig - SIGABRT; ! } ! ! err("Exiting due to signal SIG"); ! _write(STDERR_FILENO, signames+(sig-SIGABRT)*4, 4); ! } ! else ! { ! err("Exiting due to signal 0x"); ! itox(sig, 4); ! } ! err("\r\n"); ! if(__djgpp_exception_state_ptr) ! /* This exits, does not return. */ ! do_faulting_finish_message(__djgpp_exception_state == fake_exception); ! _exit(-1); ! } ! if((unsigned)temp < 4096 || temp > (SignalHandler)&end) { err("Bad signal handler, "); ! goto traceback_exit; } ! temp(sig); return 0; } --- 271,335 ---- static const char signames[] = "ABRTFPE ILL SEGVTERMALRMHUP INT KILLPIPEQUITUSR1USR2NOFPTRAP"; + void __djgpp_traceback_exit(int sig) + { + jmp_buf fake_exception; + + if (sig >= SIGABRT && sig <= SIGTRAP) + { + if (!__djgpp_exception_state_ptr) + { + /* This is a software signal, like SIGABRT or SIGKILL. + Fill the exception structure, so we get the traceback. */ + __djgpp_exception_state_ptr = &fake_exception; + if (setjmp(__djgpp_exception_state)) + { + err("Bad longjmp to __djgpp_exception_state--aborting\r\n"); + do_faulting_finish_message(0); /* does not return */ + } + else + /* Fake the exception number. 7Ah is the last one hardwired + inside exceptn.S, for SIGQUIT. */ + __djgpp_exception_state->__signum = 0x7a + 1 + sig - SIGABRT; + } + + err("Exiting due to signal SIG"); + _write(STDERR_FILENO, signames+(sig-SIGABRT)*4, 4); + } + else + { + err("Exiting due to signal 0x"); + itox(sig, 4); + } + err("\r\n"); + if(__djgpp_exception_state_ptr) + /* This exits, does not return. */ + do_faulting_finish_message(__djgpp_exception_state == fake_exception); + _exit(-1); + } + int raise(int sig) { SignalHandler temp; if(sig <= 0) return -1; if(sig > SIGMAX) return -1; temp = signal_list[sig - 1]; ! if(temp == (SignalHandler)SIG_IGN ! || (sig == SIGQUIT && temp == (SignalHandler)SIG_DFL)) return 0; /* Ignore it */ if(temp == (SignalHandler)SIG_DFL) ! __djgpp_traceback_exit(sig); /* this does not return */ ! else if((unsigned)temp < 4096 || temp > (SignalHandler)&end) { err("Bad signal handler, "); ! __djgpp_traceback_exit(sig); /* does not return */ } ! else ! temp(sig); return 0; } *************** *** 377,382 **** --- 391,460 ---- } } + #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) { *************** *** 384,389 **** --- 462,470 ---- __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; *************** *** 449,451 **** --- 530,563 ---- __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 (0x0522); /* Ctrl-RShift-G */ + signal (SIGQUIT, __djgpp_traceback_exit); + + while (1) + { + char buf[30]; + + count++; + if (count % 100000 == 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 Fri Jan 2 04:53:52 1998 --- src/libc/go32/dpmiexcp.txh Sat Jan 17 18:05:06 1998 *************** *** 33,77 **** 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 codes are specified in @code{} (see below). Every signal is given a mnemonic which you should use for portable programs. ! ! 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 by calling ! @code{_exit} (@pxref{_exit}). As an exception, the default handler ! for the signal @code{SIGINT} doesn't print the traceback, and calls ! @code{exit} instead of @code{_exit}, when the INTR key (@kbd{Ctrl-C}) ! is pressed, so that programs could be shut down safely in this manner. @code{SIGINT} raised by @kbd{Ctrl- AT key{BREAK}} does generate the traceback. ! The function @code{signal} allows you to change the default behavior ! for a specific signal. It registers @var{func} as a signal handler ! for signal number @var{sig}. After you register your function as the handler for a particular signal, it will be called when that signal occurs. The 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{}: --- 33,84 ---- 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 codes are specified in @code{} (see below). Every signal is given a mnemonic which you should use for portable programs. ! ! By default, signal @code{SIGQUIT} is discarded. This is so programs ! ported from other DOS environments, where @code{SIGQUIT} is generally ! not supported, continue to work as they originally did. If you want ! @code{SIGQUIT} to abort with a traceback, install ! @code{__djgpp_traceback_exit} as its handler ! (@pxref{__djgpp_traceback_exit}). ! ! The default handling for the rest of 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 by calling @code{_exit} ! (@pxref{_exit}). As an exception, the default handler for the signal ! @code{SIGINT} doesn't print the traceback, and calls @code{exit} instead ! of @code{_exit}, when the INTR key (@kbd{Ctrl-C} by default) is pressed, ! so that programs could be shut down safely in this manner. @code{SIGINT} raised by @kbd{Ctrl- AT key{BREAK}} does generate the traceback. ! The function @code{signal} allows you to change the default behavior for ! a specific signal. It registers @var{func} as a signal handler for ! signal number @var{sig}. After you register your function as the handler for a particular signal, it will be called when that signal occurs. The 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{}: *************** *** 88,94 **** The Floating Point Error signal. Generated in case of divide by zero exception (Int 00h), overflow exception (Int 04h), and any x87 co-processor exception, either generated by the CPU (Int 10h), or by the ! co-processor itself (Int 75h). @item SIGILL --- 95,103 ---- The Floating Point Error signal. Generated in case of divide by zero exception (Int 00h), overflow exception (Int 04h), and any x87 co-processor exception, either generated by the CPU (Int 10h), or by the ! co-processor itself (Int 75h). The co-processor status word is printed ! by the default handler for this signal. @xref{_status87}, for the ! definition of the individual bits of the status word. @item SIGILL *************** *** 97,104 **** @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 --- 106,114 ---- @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 *************** *** 106,127 **** 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 in response to any of the following exceptions: Bound range exceeded in BOUND instruction (Int 05h), Double Exception or an exception in the exception handler (Int 08h), Segment Boundary violation by co-processor ! (Int 09h), Segment Not Present (Int 0Bh), Stack Fault (Int 0Ch), General ! Protection Violation (Int 0Dh), or Page Fault (Int 0Eh). Note that Int ! 09h is only generated on 80386 processor; i486 and later CPUs cause Int ! 0Dh when the co-processor accesses memory out of bounds. @item SIGTERM --- 116,144 ---- 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 the INTR 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 in response to any of the following exceptions: Bound range exceeded in BOUND instruction (Int 05h), Double Exception or an exception in the exception handler (Int 08h), Segment Boundary violation by co-processor ! (Int 09h), Invalid TSS (Int 0Ah), Segment Not Present (Int 0Bh), Stack ! Fault (Int 0Ch), General Protection Violation (Int 0Dh), or Page Fault ! (Int 0Eh). Note that Int 09h is only generated on 80386 processor; i486 ! and later CPUs cause Int 0Dh when the co-processor accesses memory out ! of bounds. The Double Exception, Invalid TSS, Segment Not Present, ! Stack Fault, GPF, and Page Fault exceptions will cause an error code to ! be printed, if it is non-zero. @item SIGTERM *************** *** 151,157 **** @item SIGQUIT ! The Quit signal. Currently unused. @item SIGUSR1 --- 168,186 ---- @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}. By default, @code{SIGQUIT} is ! discarded, even if its handler is @code{SIG_DFL}, so that DOS programs ! which don't expect it do not break. You can change the effect of ! @code{SIGQUIT} to abort with traceback by installing ! @code{__djgpp_traceback_exit} as its handler. ! @xref{__djgpp_traceback_exit}. ! ! DJGPP hooks the keyboard hardware interrupt (Int 09h) to be able to ! generate @code{SIGQUIT} in response to the QUIT key; you should be ! aware of this when you install a handler for the keyboard interrupt. @item SIGUSR1 *************** *** 225,246 **** @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. --- 254,279 ---- @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. *************** *** 253,260 **** @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 --- 286,293 ---- @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 *************** *** 300,302 **** --- 333,525 ---- __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 + + @c ------------------------------------------------------------------------- + + @node __djgpp_traceback_exit, signal + @subheading Syntax + + @example + + #include + + void __djgpp_traceback_exit(int signo); + + @end example + + + @subheading Description + + This function is a signal handler which will print a traceback and abort + the program. It is called by default by the DJGPP signal-handling code + when any signal except @code{SIGQUIT} is raised (@code{SIGQUIT} is by + default discarded). + + You can use this function to get the Unix behavior of aborting the + program on @code{SIGQUIT} (see the example below). + + When this function is called directly, pass the signal number as its + @var{signo} argument. + + @subheading Example + + @example + signal(SIGQUIT, __djgpp_traceback_exit); + @end example + *** include/sys/exceptn.h~0 Mon Dec 29 21:41:28 1997 --- include/sys/exceptn.h Sat Jan 17 16:56:34 1998 *************** *** 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__ */ *** include/signal.h~0 Sat Apr 27 00:14:42 1996 --- include/signal.h Sun Jan 18 14:57:20 1998 *************** *** 78,83 **** --- 78,85 ---- #define SIGPROF 304 #define SIGMAX 320 + void __djgpp_traceback_exit(int _sig); + #endif /* !_POSIX_SOURCE */ #endif /* !__STRICT_ANSI__ */ #endif /* !__dj_ENFORCE_ANSI_FREESTANDING */