home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1996 June
/
Simtel-MSDOS-Jun1996-CD2.iso
/
disc2
/
c
/
ctrl_c.c
< prev
next >
Wrap
Internet Message Format
|
1988-09-04
|
14KB
Date: Tue, 26 Jul 88 21:04:04 CDT
From: galvin%circle.UUCP@cs.wisc.edu (John Galvin)
Subject: Re: Control-c Trapping Under Msc: The Day After
After I saw your message, I decided to do a bit more
thorough of a job. The result is included below. It is made up
of two files: ctrl_c.c and ctrl_c.h. I have tested these
routines some, and they appear to handle Ctrl-C and Ctrl-Break
with no problem. This code was written for MS C v5.1. Some
rewriting *will* be necessary to get it to work under previous
versions of the compiler. In particular, the do_break() and
do_intcpt() routines would have to be coded in assembler.
Fortunately, the do_break() and do_intcpt() are merely C
versions of the stuff in intercep.asm. So if you had to, you
could remove those routines from ctrl_c.c and replace
do_break(INTERCEPT) with intercept() and do_break(RELEASE) with
release(). If you have 5.1 things should work fine. Have a
nice day :-) !
--John
------------------------ ctrl_c.h: cut here ---------------------------------
/*
** ctrl_c.h
**
** Author: John Galvin
** Date: 25-Jul-1988
** Purpose: trap Ctrl-C and Ctrl-Break without printing anything.
**
** Note:
** Use of these routines will prevent Ctrl-C and Ctrl-Break
** from terminating your program. They will also prevent
** Ctrl-P, Ctrl-S, and Ctrl-Z from being interpreted by
** MS-DOS as they normally are. Your program will be able
** to read *all* of these characters, so if you don't want
** them in your input stream, you will have to do something
** about them yourself. This code was written to work in
** all standard memory models of the Microsoft C compiler
** version 5.1. Do not use getch() or getche() with these
** routines.
**
** $Id: ctrl_c.h 1.1 88/07/25 22:04:48 galvin Exp $
**
** Copyright (c) 1988 by John W. Galvin. All Rights Reserved.
**
** Permission is hereby granted by the author for anyone to use this
** code in their own programs provided the following conditions are met:
** This copyright notice is left intact. Any changes to this text/code
** must be commented and credited to the correct author somewhere
** in this file.
**
** $Log: ctrl_c.h $
** Revision 1.1 88/07/25 22:04:48 galvin
** Initial revision
**
**
*/
#ifndef TRUE
# define TRUE 1
#endif
#ifndef FALSE
# define FALSE 0
#endif
#define INTERCEPT 0
#define RELEASE 1
#define GET 0x00
#define SET 0x01
#define CHKON 0x01
#define CHKOFF 0x00
#ifdef LINT_ARGS
int ctrl_c(int);
int get_ctrl_c_chk(void);
int set_ctrl_c_chk(int);
int rawio(int, int);
unsigned int ioctl(int, int, unsigned int);
#else
extern int ctrl_c(), get_ctrl_c_chk(), set_ctrl_c_chk(),
rawio();
extern unsigned int ioctl();
#endif
------------------------ ctrl_c.c: cut here ---------------------------------
/*
** ctrl_c.c
**
** Author: John Galvin
** Date: 25-Jul-1988
** Purpose: trap Ctrl-C and Ctrl-Break without printing anything.
**
** Note:
** Use of these routines will prevent Ctrl-C and Ctrl-Break
** from terminating your program. They will also prevent
** Ctrl-P, Ctrl-S, and Ctrl-Z from being interpreted by
** MS-DOS as they normally are. Your program will be able
** to read *all* of these characters, so if you don't want
** them in your input stream, you will have to do something
** about them yourself. This code was written to work in
** all standard memory models of the Microsoft C compiler
** version 5.1. Do not use getch() or getche() with these
** routines. See the #ifdef'd section of code below for an
** example of how to use these functions.
**
** Copyright (c) 1988 by John W. Galvin. All Rights Reserved.
**
** Permission is hereby granted by the author for anyone to use this
** code in their own programs provided the following conditions are met:
** This copyright notice is left intact. Any changes to this text/code
** must be commented and credited to the correct author somewhere
** in this file.
**
** $Log: ctrl_c.c $
** Revision 1.1 88/07/25 22:04:46 galvin
** Initial revision
**
**
*/
#ifndef _lint
static char *rcsid = "$Id: ctrl_c.c 1.1 88/07/25 22:04:46 galvin Exp $";
#endif
#include <stdio.h>
#include <dos.h>
#include "ctrl_c.h"
#define BREAKINTR 0x1B
#define DOS 0x21
#define CTRLCCHK 0x33
#define GETVECT 0x35
#define SETVECT 0x25
#define IOCTL 0x44
#define DEVFLAG 0x80
#define RAWFLAG 0x20
/*
** Name:
**
** get_ctrl_c_chk() - return status of MS-DOS Ctrl-C checking.
**
** Synopsis:
**
** int get_ctrl_c_chk()
**
** Description:
**
** This function determines the current level of Ctrl-C
** checking being performed by MS-DOS. The effect of this
** function is roughly analagous to issuing a "BREAK" command
** at the MS-DOS command prompt.
**
** Return Values:
**
** This function returns FALSE if MS-DOS is only checking for
** Ctrl-C in the 0x01 - 0x0C group of int 0x21 functions, or
** if an error occurred. A return of TRUE indicates that MS-DOS
** is checking for Ctrl-C before each DOS service is performed.
**
** Bugs:
**
**
*/
int get_ctrl_c_chk()
{
union REGS regs;
regs.h.ah = CTRLCCHK;
regs.h.al = GET;
int86(DOS, ®s, ®s);
if (regs.x.cflag)
return(FALSE);
return(regs.h.dl);
}
/*
** Name:
**
** set_ctrl_c_chk() - set the level of MS-DOS Ctrl-C checking.
**
** Synopsis:
**
** int set_ctrl_c_chk(value)
** int value;
**
** Description:
**
** This function sets the level of Ctrl-C checking that MS-DOS
** will perform. Value should be one of the two manifest
** constants CHKON or CHKOFF. Calling set_ctrl_c_chk() with a
** value of CHKON is equivalent to issuing a "BREAK ON" command
** at the MS-DOS command line. Calling set_ctrl_c_chk() with a
** value of CHKOFF is equivalent to issuing a "BREAK OFF" command
** at the MS-DOS command line.
**
** Return Values:
**
** This function returns FALSE if an error occurred, TRUE otherwise.
**
** Bugs:
**
**
*/
int set_ctrl_c_chk(value)
int value;
{
union REGS regs;
regs.h.ah = CTRLCCHK;
regs.h.al = SET;
regs.h.dl = value;
int86(DOS, ®s, ®s);
return(!regs.x.cflag);
}
/*
** Name:
**
** ioctl() - MS-DOS i/o control for devices interface.
**
** Synopsis:
**
** unsigned int ioctl(handle, op, value)
** int handle;
** int op;
** unsigned int value;
**
** Description:
**
** This routine provides a limited interface to the MS-DOS
** ioctl functions. It primarily intended to get/set the
** device attribute bits for a file handle. Handle should
** an open file handle (hopefully for a device). Op should
** be one of SET or GET. If op is SET, the device attribute
** bits for handle will be set to those specified in value.
**
** Return Values:
**
** This function returns FALSE if an error occurred. Otherwise
** The new device attribute word will be returned. The attribute
** word may possibly be equal to FALSE.
**
** Bugs:
**
**
*/
unsigned int ioctl(handle, op, value)
int handle;
int op;
unsigned int value;
{
union REGS regs;
regs.h.ah = IOCTL;
regs.h.al = op;
regs.x.bx = handle;
regs.x.dx = value & 0xFF;
int86(DOS, ®s, ®s);
if (regs.x.cflag)
return(FALSE);
return(regs.x.dx);
}
/*
** Name:
**
** rawio() - set/reset a device to/from raw i/o mode.
**
** Synopsis:
**
** int rawio(handle, raw)
** int handle;
** int raw;
**
** Description:
**
** Rawio() uses ioctl() to set/reset a device to/from raw i/o
** mode. When a device is in raw mode, and Ctrl-C checking is
** turned off, Ctrl-C, Ctrl-S, Ctrl-P, and Ctrl-Z may be read
** as data without having MS-DOS interpret them. Handle must
** refer to an open file/device. If raw is TRUE, the device
** will be set to raw mode. Otherwise, the device will be reset
** from raw mode.
**
** Return Values:
**
** This function returns a non-zero value if the device was
** in raw mode, 0 otherwise.
**
** Bugs:
**
** No checks are made for errors from ioctl().
*/
int rawio(handle, raw)
int handle;
int raw;
{
unsigned int flags;
flags = ioctl(handle, GET, 0);
if (flags & DEVFLAG) {
if (raw)
ioctl(handle, SET, flags | RAWFLAG);
else
ioctl(handle, SET, flags & ~RAWFLAG);
}
return(flags & RAWFLAG);
}
/*
** Name:
**
** do_intcpt() - Ctrl-Break Interrupt (0x1B) routine.
**
** Synopsis:
**
** void interrupt cdecl far do_intcpt()
**
** Description:
**
** This routine is the dummy interrupt routine which is used
** to intercept the IBM PC Break interrupt.
**
** Return Values:
**
** None.
**
** Bugs:
**
**
*/
static void interrupt cdecl far do_intcpt()
{
return;
}
/*
** Name:
**
** do_break() - intercept/release the IBM PC Break Interrupt.
**
** Synopsis:
**
** static void do_break(op)
** int op;
**
** Description:
**
** If passed the manifest constant INTERCEPT, this routine
** will use do_intcpt() to intercept the IBM PC Ctrl-Break
** interrupt. If this routine is not used while trapping
** Ctrl-C and Ctrl-Break, a ^C may turn up *after* the porgram
** exits. When passed the manifest constant RELEASE, do_break()
** will de-install its interrupt handler.
**
** Return Values:
**
** None.
**
** Bugs:
**
** No error checks are performed on the returns of int86x().
*/
static void do_break(op)
int op;
{
union REGS regs;
struct SREGS segs;
static unsigned int oldseg;
static unsigned int oldofs;
if (op == INTERCEPT) {
segread(&segs);
regs.h.ah = GETVECT;
regs.h.al = BREAKINTR;
int86x(DOS, ®s, ®s, &segs);
oldseg = segs.es;
oldofs = regs.x.bx;
segread(&segs);
regs.x.dx = (unsigned int) do_intcpt;
segs.ds = ((unsigned long) do_intcpt) >> 16;
}
else {
segread(&segs);
regs.x.dx = oldofs;
segs.ds = oldseg;
}
regs.h.ah = SETVECT;
regs.h.al = BREAKINTR;
int86x(DOS, ®s, ®s, &segs);
}
/*
** Name:
**
** ctrl_c() - nullify Ctrl-C and Ctrl-Break.
**
** Synopsis:
**
** int ctrl_c(op)
** int op;
**
** Description:
**
** If passed the manifest constant INTERCEPT, ctrl_c() will
** prevent MS-DOS from interpreting Ctrl-C, Ctrl-Break, Ctrl-P,
** Ctrl-S, and Ctrl-Z as it normally does. I.E. a Ctrl-C or
** Ctrl-Break will not cause a ^C to be output and will not
** abort the program. Do not use getch(), or getche() while
** this routine is in effect, they do not properly support
** this mode. If passed the manifest constant RELEASE, ctrl_c()
** will return the Ctrl character interpretation that existed
** before ctrl_c(INTERCEPT) was called.
**
** Return Values:
**
** Ctrl_c() always returns TRUE.
**
** Bugs:
**
** No error checking is done.
*/
int ctrl_c(op)
int op;
{
static unsigned int outflg;
static unsigned int inflg;
static unsigned int ctrlcchk;
if (op == INTERCEPT) {
do_break(INTERCEPT);
inflg = rawio(fileno(stdin), TRUE);
outflg = rawio(fileno(stdout), TRUE);
if ((ctrlcchk = get_ctrl_c_chk()) == CHKON)
set_ctrl_c_chk(CHKOFF);
}
else {
set_ctrl_c_chk(ctrlcchk);
rawio(fileno(stdout), outflg);
rawio(fileno(stdin), inflg);
do_break(RELEASE);
}
return(TRUE);
}
#ifdef CTRL_CDEBUG
#include <bios.h>
int main()
{
int achar;
ctrl_c(INTERCEPT);
while ((achar = _bios_keybrd(_KEYBRD_READ) & 0xFF) != ' ')
putch(achar);
ctrl_c(RELEASE);
return(0);
}
#endif
----------------------------- the end ---------------------------------------
--
John Galvin ARPA: galvin@circle.UUCP
1810 Fordem Ave. #6 UUCP: ...!uwvax!geowhiz!circle!galvin
Madison, Wi 53704 FidoNet: Sysop of 1:121/0, and 1:121/1. (608) 249-0275