[comp.sys.ibm.pc.programmer] Avoiding ^C

bruce@archive.rtp.dg.com (Bruce Kahn) (06/28/90)

In article <10688@spool.cs.wisc.edu>, so@brownie.cs.wisc.edu (Bryan So) writes:
|> I have tried to trap the Ctrl-Break and Ctrl-C interrupts by
|> "signal", "ctrlbrk" in Turbo C and installing my own 0x23 handler.
|> But there seems to be no way to prevent "^C" from printing out to
|> the screen.  Can somebody explain a way to do it?  Thanks.
|> 
|> Bryan

  The only way that Ive found to prevent the annoying ^C from being displayed
is to NOT use the standard printf calls.  I found that I had to issue direct
BIOS write calls and bypass DOS.  The reason being (I was told a long long
time ago) that DOS allows you to insert your own INT23 handler but it stil
sets a 'break' flag internally and when it does any screen I/O it checks the
flag; if it is set it inserts a ^C into the buffer and clears the flag.
  If you need more specifics I can dig out my code and tell you what exactly I
did (it may have been I issued INT21, AH=10H calls myself)...

					Bruce (bruce@archive.rtp.dg.com)

horstman@sjsumcs.sjsu.edu (Cay Horstmann) (07/01/90)

In article <577@dg.dg.com> bruce@archive.rtp.dg.com (Bruce Kahn) writes:
>In article <10688@spool.cs.wisc.edu>, so@brownie.cs.wisc.edu (Bryan So) writes:
>|> I have tried to trap the Ctrl-Break and Ctrl-C interrupts by
>|> "signal", "ctrlbrk" in Turbo C and installing my own 0x23 handler.
>|> But there seems to be no way to prevent "^C" from printing out to
>|> the screen.  Can somebody explain a way to do it?  Thanks.
>|> 
>|> Bryan
>
>  The only way that Ive found to prevent the annoying ^C from being displayed
>is to NOT use the standard printf calls.  I found that I had to issue direct
>BIOS write calls and bypass DOS.  The reason being (I was told a long long
>time ago) that DOS allows you to insert your own INT23 handler but it stil
>sets a 'break' flag internally and when it does any screen I/O it checks the
>flag; if it is set it inserts a ^C into the buffer and clears the flag.
>  If you need more specifics I can dig out my code and tell you what exactly I
>did (it may have been I issued INT21, AH=10H calls myself)...
>
>					Bruce (bruce@archive.rtp.dg.com)

I don't think this is true. Software which I wrote and which runs in
graphics mode (with no calls to printf whatsoever) but homegrown
put-the-pixels-to-the-screen routines for all I/O still shows the
(expletive deleted) ^C, even though I (of course) remap the Ctrl-Brk|C
handlers. 

I'd love to know what to do about this. 

Cay

dougs@videovax.tv.tek.com (Doug Stevens) (07/03/90)

Here is a partial solution from Ge van Geldorp (thanks to Pat McCarthy
and Clayton E. Cramer for summarizing this problem before):

> It turns out that the ^C echoed by DOS is written to stdout. Thus, if
> you don't need stdout, you can redirect it to nul from within your
> program (using dup2()), thereby sending the ^C to the bit-bucket.
> Hope this helps.
> 
> Ge van Geldorp
> ge@dutlru2.tudelft.nl
> ...!uunet!hp4nl!dutlru2.tudelft.nl!ge

bmarsh@cod.NOSC.MIL (William C. Marsh) (07/03/90)

In article <1990Jun30.203726.7480@sjsumcs.sjsu.edu> horstman@sjsumcs.SJSU.EDU (Cay Horstmann) writes:
>In article <577@dg.dg.com> bruce@archive.rtp.dg.com (Bruce Kahn) writes:
>I don't think this is true. Software which I wrote and which runs in
>graphics mode (with no calls to printf whatsoever) but homegrown
>put-the-pixels-to-the-screen routines for all I/O still shows the
>(expletive deleted) ^C, even though I (of course) remap the Ctrl-Brk|C
>handlers. 
>
>I'd love to know what to do about this. 

OK, I'll try to explain the method I used to get around the ^C in graphics
programs (and others).  First, you must realize when DOS will put the ^C
characters onto the screen.  This is with any old style console DOS call
(Read Keyboard, write string, read buffered input, etc), or any read/write
to the console device.  If BREAK = ON, then DOS checks for most DOS calls.
(This is where you may be getting hit...)

To get around this problem, you should turn off BREAK within your program
(But *please* restore it when you exit!).  If BREAK is off, you only have
a few places where ^C can creap in.

When I am writing a program where I don't want ^C, I also read directly from
the keyboard BIOS.  Sorry about ignoring an input pipe, but you can't have
your cake and eat it, too...

One last piece of advice, when you read from the BIOS, look out for scan code
0x0000.  That's control-break.  What I do is this:  If a control-break code
is read, my routines call the DOS function to flush the input buffer.  DOS
does set a ^C flag when control-break is entered (The int 1B interrupt), and
this call will clear that flag.

Hope this Helps!

Bill
-- 
Bill Marsh, Naval Ocean Systems Center, San Diego, CA
{arpa,mil}net: bmarsh@cod.nosc.mil
uucp: {ihnp4,akgua,decvax,dcdwest,ucbvax}!sdcsvax!nosc!bmarsh
"If everything seems to be coming your way, you're probably in the wrong lane."

einari@rhi.hi.is (Einar Indridason) (07/04/90)

In article <1985@cod.NOSC.MIL> bmarsh@cod.nosc.mil.UUCP (William C. Marsh) writes:
>To get around this problem, you should turn off BREAK within your program
>(But *please* restore it when you exit!).  If BREAK is off, you only have

Don't restore.  Save the previous status and put that status back.
(If you restore, you might turn break ON for someone that doesn't keep break
on as a default, thereby taking him by surprize)

--
I just learned a new curse: "You #$@! son of SCROLLBAR!"

Internet:       einari@rhi.hi.is   | 'Just give me my command line and throw
UUCP: ..!mcsun!isgate!rhi!einari   | the GUIs in the dust-bin!!!!!!!!!'

mason@tc.fluke.COM (Nick Mason) (07/06/90)

In article <1990Jun30.203726.7480@sjsumcs.sjsu.edu> horstman@sjsumcs.SJSU.EDU (Cay Horstmann) writes:
>In article <577@dg.dg.com> bruce@archive.rtp.dg.com (Bruce Kahn) writes:
>>In article <10688@spool.cs.wisc.edu>, so@brownie.cs.wisc.edu (Bryan So) writes:
>I don't think this is true. Software which I wrote and which runs in
>graphics mode (with no calls to printf whatsoever) but homegrown
>put-the-pixels-to-the-screen routines for all I/O still shows the
>(expletive deleted) ^C, even though I (of course) remap the Ctrl-Brk|C
>handlers. 
>
>I'd love to know what to do about this. 
>
OK, OK, here's the BIG secret to get rid of ^C on the screen.

Keyboard processing uses lots of interrupts on a PC. Hardware int 9,
software 16, 1B and 23 to name a few.

When ctrl-C is pressed, two interrupts are affected, 0x1B and 0x23.

0x23 has been previously discussed , and is the MS-DOS interrupt
associated with ^C.  The interrupt not discussed, is 0x1B the BIOS
interrupt associated with ^C.  It is this interrupt that puts the
*&$^@!ing '^' and 'C' in the keyboard buffer.  

To totally turn off ^C I do something similar to the following:

/*
** junker routine
*/
void interrupt junker()
{
	return;
}

then in the code:

main()
{
_dos_setvect(0x23, junker);  /* map out DOS ctrl-C and ctrl-break */

_dos_setvect(0x1B, junker); /* map out BIOS ctrl-C and ctrl-break */


/*
** code goes here,  ctrl-C and ctrl-break don't work
*/


}

Nick

stever@Octopus.COM (Steve Resnick ) (07/07/90)

In article <1990Jul5.171205.2036@tc.fluke.COM> mason@tc.fluke.COM (Nick Mason) writes:
[Stuff Deleted]
>OK, OK, here's the BIG secret to get rid of ^C on the screen.
>
>Keyboard processing uses lots of interrupts on a PC. Hardware int 9,
>software 16, 1B and 23 to name a few.
>
>When ctrl-C is pressed, two interrupts are affected, 0x1B and 0x23.
>
>0x23 has been previously discussed , and is the MS-DOS interrupt
>associated with ^C.  The interrupt not discussed, is 0x1B the BIOS
>interrupt associated with ^C.  It is this interrupt that puts the
>*&$^@!ing '^' and 'C' in the keyboard buffer.  
>
>To totally turn off ^C I do something similar to the following:
>

This isn't entirely true...

The BIOS responds to ^[Break], DOS reponds to ^C. If you press ^[Break]
int 1BH is executed by the int 09H handler. This gets picked up by DOS
and you get the stupid ^C character. If you intercept the 1BH handler, 
you will avoid getting the ^C when you press ^[Break]. If you press ctrl-C
you will still get the silly ^C display. The only sure-fire meathod I have
been able to come up with is: Use the BIOS for all of your keyboard I/O.
I have noticed that even funcitons like kbhit() will cause you to get the
^C on the screen, so you will need to once again bug int 16H for the input
status.


If you HAVE to use stdio, there might be some diddling of the I/O streams
to set "raw" mode. I have never tried this so I cannot recomend this.

Hope this is usefull.....
Steve

-- 
--------------------------------------------------------------------------------
Steve Resnick -<stever@octopus.COM apple!octopus!stever sun!vsi1!octopus!stever>
408/241-1533 Process Scientific, Inc.
"0x2B|~0x2B THAT is the question!"

huang@stiatl.UUCP (Jim Huang) (07/09/90)

In article <1990Jul6.220720.15747@Octopus.COM> stever@octopus.UUCP (Steve Resnick ) writes:
>
>If you HAVE to use stdio, there might be some diddling of the I/O streams

>to set "raw" mode. I have never tried this so I cannot recomend this.
>
>

  I have try this in my program. It work fine, but you had to remember to
  reset it to "cooked" mode before your program terminated.

  Following are from "Advanced MS-DOS" by Ray Duncan, Micrsoft Press

  To avoid losing control upon entry of a Ctrl-C.

  1, Performing all keyboard input and status check throug function 06h
     and 07h, and turning on the raw mode for the console driver.

  2, Performing all display output through MS-DOS function 06h or by
     direct write to the ROM BIOS or to the video controller's refresh 
     buffer.

  3, Setting the other character devices(AUX, PRN) into raw mode.

  4, Disabling Ctrl-C checking with function 33h, for MS-DOS operations
     other than character I/O.

   
						   Jim Huang

paulb@techbook.com (Paul Buder) (07/11/90)

>In article <10688@spool.cs.wisc.edu>, so@brownie.cs.wisc.edu (Bryan So) writes:
> I have tried to trap the Ctrl-Break and Ctrl-C interrupts by
> "signal", "ctrlbrk" in Turbo C and installing my own 0x23 handler.
> But there seems to be no way to prevent "^C" from printing out to
> the screen.  Can somebody explain a way to do it?  Thanks.
> 
> Bryan

 Since this Control C question has been going on for some time now and no
 one has given anything that sounds like a workable answer I offer this 
 solution.  It traps Control-C and Control-Break at Int 9 so that they 
 never get to DOS or to the BIOS.  This was compiled with Microsoft C.

#include <stdio.h>
#include <dos.h>

/*This gives the status of the control and alt keys, among others */
unsigned char far *kstatus;       
interrupt far scancode(void);     /*func decl for the interrupt routine */
void (interrupt far *oldvect)();  /*the old int 9 vector */
main()
    {
    int c;
    oldvect=_dos_getvect(9);     /*get old INT 9 vector */
    _dos_setvect(9, scancode);   /*install the new one */
    (int)kstatus=0x417;          /*the location of the keyboard status byte */

    /* and some test lines to try pressing control-c or break. */

    for(c=0; c<500; c++)
        printf("\nThis is line number %d", c);

    _dos_setvect(9, oldvect);    /*deactivate */
    }

/*The interrupt routine to check for Control-C */

interrupt far scancode(void)
    {
    unsigned char kb;

    kb=inp(0x60);/*port 0 of 8255, where character's scan codes are received */
    /*0x2e==the letter 'c', 0x46==break, */
    /*kstatus==4 means the control key is pressed. */

    if( (kb==0x2e || kb==0x46) && ((*kstatus) & 4)==4)
        {
    /*port 1 of 8255. Bit 7=0 means enabled kb, bit7=1 means kb acknowledge */
        outp(0x61, inp(0x61) | 0x80); /*raise bit 7 (send acknowledge) */
        outp(0x61, inp(0x61) & 0x7f); /*zero bit 7  (enable keyboard) */
        _enable();                    /*allow 8088 to send more interrupts */
        outp(0x20, 0x20);             /*allow 8259 to send more interrupts */
        }
    else
        _chain_intr(oldvect);/*call regular int 9 to do normal char processing*/
    }