home *** CD-ROM | disk | FTP | other *** search
/ Zodiac Super OZ / MEDIADEPOT.ISO / FILES / 16 / FREEDOS.ZIP / FD_A4PRE.ZIP / SOURCE / FD10.ZIP / ctrl_c.c < prev    next >
C/C++ Source or Header  |  1995-05-15  |  10KB  |  399 lines

  1. /*
  2.  * *      ctrl_c.c *
  3.  * 
  4.  *      Author:  John Galvin *      Date:    25-Jul-1988 *      Purpose: trap
  5.  * Ctrl-C and Ctrl-Break without printing anything. *
  6.  * 
  7.  *      Note: *          Use of these routines will prevent Ctrl-C and
  8.  * Ctrl-Break *          from terminating your program.  They will also
  9.  * prevent *          Ctrl-P, Ctrl-S, and Ctrl-Z from being interpreted by *
  10.  * MS-DOS as they normally are.  Your program will be able *          to read
  11.  * *all* of these characters, so if you don't want *          them in your
  12.  * input stream, you will have to do something *          about them
  13.  * yourself.  This code was written to work in *          all standard memory
  14.  * models of the Microsoft C compiler *          version 5.1.  Do not use
  15.  * getch() or getche() with these *          routines.  See the #ifdef'd
  16.  * section of code below for an *          example of how to use these
  17.  * functions. *
  18.  * 
  19.  *      Copyright (c) 1988 by John W. Galvin.  All Rights Reserved. *
  20.  * 
  21.  *      Permission is hereby granted by the author for anyone to use this *
  22.  * code in their own programs provided the following conditions are met: *
  23.  * This copyright notice is left intact.  Any changes to this text/code *
  24.  * must be commented and credited to the correct author somewhere *      in
  25.  * this file. *
  26.  * 
  27.  *      $Log:   ctrl_c.c $ *      Revision 1.1  88/07/25  22:04:46  galvin *
  28.  * Initial revision *
  29.  * 
  30.  *
  31.  */
  32.  
  33. #ifndef _lint
  34. static char    *rcsid = "$Id: ctrl_c.c 1.1 88/07/25 22:04:46 galvin Exp $";
  35. #endif
  36.  
  37. #include <stdio.h>
  38. #include <file.h>
  39. #include <freedos.h>
  40. #include <portable.h>
  41. #include "ctrl_c.h"
  42.  
  43.  
  44. #define BREAKINTR       27
  45. #define DOS             33
  46. #define CTRLCCHK        0x33
  47. #define GETVECT         53
  48. #define SETVECT         37
  49. #define IOCTL           0x44
  50. #define DEVFLAG         0x80
  51. #define RAWFLAG         0x20
  52. #define cflag           0x0001
  53.  
  54. void            do_intcpt(void);
  55. static void     do_break(int op);
  56.  
  57. /*
  58.  * *      Name: *
  59.  * 
  60.  *          get_ctrl_c_chk() - return status of MS-DOS Ctrl-C checking. *
  61.  * 
  62.  *      Synopsis: *
  63.  * 
  64.  *          int     get_ctrl_c_chk() *
  65.  * 
  66.  *      Description: *
  67.  * 
  68.  *          This function determines the current level of Ctrl-C *
  69.  * checking being performed by MS-DOS.  The effect of this *
  70.  * function is roughly analagous to issuing a "BREAK" command *          at
  71.  * the MS-DOS command prompt. *
  72.  * 
  73.  *      Return Values: *
  74.  * 
  75.  *          This function returns FALSE if MS-DOS is only checking for *
  76.  * Ctrl-C in the 0x01 - 0x0C group of int 0x21 functions, or *          if an
  77.  * error occurred.  A return of TRUE indicates that MS-DOS *          is
  78.  * checking for Ctrl-C before each DOS service is performed. *
  79.  * 
  80.  *      Bugs: *
  81.  * 
  82.  *
  83.  * 
  84.  */
  85. int 
  86. get_ctrl_c_chk(void)
  87. {
  88.     USEREGS
  89.  
  90.     _AX = CTRLCCHK << 8 | GET;
  91.     if (geninterrupt(DOS) & cflag)
  92.     return FALSE;
  93.     else
  94.     return _DL;
  95. }
  96.  
  97.  
  98. /*
  99.  * *      Name: *
  100.  * 
  101.  *          set_ctrl_c_chk() - set the level of MS-DOS Ctrl-C checking. *
  102.  * 
  103.  *      Synopsis: *
  104.  * 
  105.  *          int     set_ctrl_c_chk(value) *          int     value; *
  106.  * 
  107.  *      Description: *
  108.  * 
  109.  *          This function sets the level of Ctrl-C checking that MS-DOS *
  110.  * will perform.  Value should be one of the two manifest *
  111.  * constants CHKON or CHKOFF.  Calling set_ctrl_c_chk() with a *
  112.  * value of CHKON is equivalent to issuing a "BREAK ON" command *          at
  113.  * the MS-DOS command line.  Calling set_ctrl_c_chk() with a *          value
  114.  * of CHKOFF is equivalent to issuing a "BREAK OFF" command *          at the
  115.  * MS-DOS command line. *
  116.  * 
  117.  *      Return Values: *
  118.  * 
  119.  *          This function returns FALSE if an error occurred, TRUE otherwise. *
  120.  * 
  121.  *      Bugs: *
  122.  * 
  123.  *
  124.  * 
  125.  */
  126. int 
  127. set_ctrl_c_chk(int value)
  128. {
  129.     USEREGS
  130.  
  131.     _AX = CTRLCCHK << 8 | SET;
  132.     _DX = _DH << 8 | value;
  133.     return !(geninterrupt(DOS) & cflag);
  134. }
  135.  
  136.  
  137. /*
  138.  * *      Name: *
  139.  * 
  140.  *          ioctl() - MS-DOS i/o control for devices interface. *
  141.  * 
  142.  *      Synopsis: *
  143.  * 
  144.  *          unsigned int    ioctl(handle, op, value) *          int
  145.  * handle; *          int             op; *          unsigned int    value; *
  146.  * 
  147.  *      Description: *
  148.  * 
  149.  *          This routine provides a limited interface to the MS-DOS *
  150.  * ioctl functions.  It primarily intended to get/set the *          device
  151.  * attribute bits for a file handle.  Handle should *          an open file
  152.  * handle (hopefully for a device).  Op should *          be one of SET or
  153.  * GET.  If op is SET, the device attribute *          bits for handle will
  154.  * be set to those specified in value. *
  155.  * 
  156.  *      Return Values: *
  157.  * 
  158.  *          This function returns FALSE if an error occurred.  Otherwise *
  159.  * The new device attribute word will be returned.  The attribute *
  160.  * word may possibly be equal to FALSE. *
  161.  * 
  162.  *      Bugs: *
  163.  * 
  164.  *
  165.  * 
  166.  */
  167. word 
  168. ioctl(int handle, int op, word value)
  169. {
  170.     USEREGS
  171.  
  172.     _AX = IOCTL << 8 | op;
  173.     _BX = handle;
  174.     _DX = value & 0x00FF;
  175.     if (geninterrupt(DOS) & cflag)
  176.     return FALSE;
  177.     else
  178.     return _DX;
  179. }
  180.  
  181.  
  182. /*
  183.  * *      Name: *
  184.  * 
  185.  *          rawio() - set/reset a device to/from raw i/o mode. *
  186.  * 
  187.  *      Synopsis: *
  188.  * 
  189.  *          int     rawio(handle, raw) *          int     handle; *
  190.  * int     raw; *
  191.  * 
  192.  *      Description: *
  193.  * 
  194.  *          Rawio() uses ioctl() to set/reset a device to/from raw i/o *
  195.  * mode.  When a device is in raw mode, and Ctrl-C checking is *
  196.  * turned off, Ctrl-C, Ctrl-S, Ctrl-P, and Ctrl-Z may be read *          as
  197.  * data without having MS-DOS interpret them.  Handle must *          refer
  198.  * to an open file/device.  If raw is TRUE, the device *          will be set
  199.  * to raw mode.  Otherwise, the device will be reset *          from raw
  200.  * mode. *
  201.  * 
  202.  *      Return Values: *
  203.  * 
  204.  *          This function returns a non-zero value if the device was *
  205.  * in raw mode, 0 otherwise. *
  206.  * 
  207.  *      Bugs: *
  208.  * 
  209.  *          No checks are made for errors from ioctl().
  210.  */
  211. int 
  212. rawio(int handle, int raw)
  213. {
  214.     word            flags;
  215.  
  216.     flags = ioctl(handle, GET, 0);
  217.     if (flags & DEVFLAG) {
  218.     if (raw)
  219.         ioctl(handle, SET, flags | RAWFLAG);
  220.     else
  221.         ioctl(handle, SET, flags & ~RAWFLAG);
  222.     }
  223.     return (flags & RAWFLAG);
  224. }
  225.  
  226.  
  227. /*
  228.  * *      Name: *
  229.  * 
  230.  *          do_intcpt() - Ctrl-Break Interrupt (0x1B) routine. *
  231.  * 
  232.  *      Synopsis: *
  233.  * 
  234.  *          void interrupt cdecl far    do_intcpt() *
  235.  * 
  236.  *      Description: *
  237.  * 
  238.  *          This routine is the dummy interrupt routine which is used *
  239.  * to intercept the IBM PC Break interrupt. *
  240.  * 
  241.  *      Return Values: *
  242.  * 
  243.  *          None. *
  244.  * 
  245.  *      Bugs: *
  246.  * 
  247.  *
  248.  * 
  249.  */
  250. void 
  251. do_intcpt(void)
  252. {
  253.     asm
  254.     {
  255.     POP             BP
  256.                     IRET
  257.     }
  258. }
  259.  
  260.  
  261. /*
  262.  * *      Name: *
  263.  * 
  264.  *          do_break() - intercept/release the IBM PC Break Interrupt. *
  265.  * 
  266.  *      Synopsis: *
  267.  * 
  268.  *          static void do_break(op) *          int         op; *
  269.  * 
  270.  *      Description: *
  271.  * 
  272.  *          If passed the manifest constant INTERCEPT, this routine *
  273.  * will use do_intcpt() to intercept the IBM PC Ctrl-Break *
  274.  * interrupt.  If this routine is not used while trapping *          Ctrl-C
  275.  * and Ctrl-Break, a ^C may turn up *after* the porgram *          exits.
  276.  * When passed the manifest constant RELEASE, do_break() *          will
  277.  * de-install its interrupt handler. *
  278.  * 
  279.  *      Return Values: *
  280.  * 
  281.  *          None. *
  282.  * 
  283.  *      Bugs: *
  284.  * 
  285.  *          No error checks are performed on the returns of int86x().
  286.  */
  287.  
  288. word            oldseg;
  289. word            oldofs;
  290.  
  291. static void 
  292. do_break(int op)
  293. {
  294.     word            ds;
  295.  
  296.     if (op == INTERCEPT) {
  297.     asm
  298.     {
  299.         MOV             AH, GETVECT
  300.                         MOV AL, BREAKINTR
  301.                         INT DOS
  302.                         MOV _oldseg, ES
  303.                         MOV _oldofs, BX
  304.                         MOV DX, OFFSET _do_intcpt
  305.                         MOV asmName(ds, -2), CS
  306.     }
  307.     } else {
  308.     asm
  309.     {
  310.         MOV             DX, _oldofs
  311.                         MOV AX, _oldseg
  312.                         MOV asmName(ds, -2), AX
  313.     }
  314.     }
  315.                     asm
  316.     {
  317.     PUSH            DS
  318.                     MOV DS, asmName(ds, -2)
  319.     MOV             AH, SETVECT
  320.                     MOV AL, BREAKINTR
  321.                     INT DOS
  322.                     POP DS
  323.     }
  324. }
  325.  
  326.  
  327. /*
  328.  * *      Name: *
  329.  * 
  330.  *          ctrl_c() - nullify Ctrl-C and Ctrl-Break. *
  331.  * 
  332.  *      Synopsis: *
  333.  * 
  334.  *          int     ctrl_c(op) *          int     op; *
  335.  * 
  336.  *      Description: *
  337.  * 
  338.  *          If passed the manifest constant INTERCEPT, ctrl_c() will *
  339.  * prevent MS-DOS from interpreting Ctrl-C, Ctrl-Break, Ctrl-P, *
  340.  * Ctrl-S, and Ctrl-Z as it normally does.  I.E. a Ctrl-C or *
  341.  * Ctrl-Break will not cause a ^C to be output and will not *          abort
  342.  * the program.  Do not use getch(), or getche() while *          this
  343.  * routine is in effect, they do not properly support *          this mode.
  344.  * If passed the manifest constant RELEASE, ctrl_c() *          will return
  345.  * the Ctrl character interpretation that existed *          before
  346.  * ctrl_c(INTERCEPT) was called. *
  347.  * 
  348.  *      Return Values: *
  349.  * 
  350.  *          Ctrl_c() always returns TRUE. *
  351.  * 
  352.  *      Bugs: *
  353.  * 
  354.  *          No error checking is done.
  355.  */
  356.  
  357. int 
  358. ctrl_c(int op)
  359. {
  360.     static word     outflg;
  361.     static word     inflg;
  362.     static word     ctrlcchk;
  363.  
  364.     if (op == INTERCEPT) {
  365.     do_break(INTERCEPT);
  366.     inflg = rawio(fileno(stdin), TRUE);
  367.     outflg = rawio(fileno(stdout), TRUE);
  368.     if ((ctrlcchk = get_ctrl_c_chk()) == CHKON)
  369.         set_ctrl_c_chk(CHKOFF);
  370.     } else {
  371.     set_ctrl_c_chk(ctrlcchk);
  372.     rawio(fileno(stdout), outflg);
  373.     rawio(fileno(stdin), inflg);
  374.     do_break(RELEASE);
  375.     }
  376.  
  377.     return (TRUE);
  378. }
  379.  
  380.  
  381. #ifdef CTRL_CDEBUG
  382.  
  383. #include <video.h>
  384.  
  385. int 
  386. main()
  387. {
  388.     int             achar;
  389.  
  390.     ctrl_c(INTERCEPT);
  391.     vopen();
  392.     while ((achar = kbget() & 0xFF) != ' ')
  393.     vputc(achar);
  394.     ctrl_c(RELEASE);
  395.     exit(0);
  396. }
  397.  
  398. #endif
  399.