home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / old / ckermit4f / ckotio.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  21KB  |  813 lines

  1. char *ckxv = "OS/2 console i/o, 7 Feb 89";
  2.  
  3. /* C K O T I O  --  Kermit console i/o support for OS/2 systems */
  4.  
  5. /* Also contains code to emulate the Unix 'alarm' function under OS/2 */
  6.  
  7. /*
  8.  Author: Chris Adie (C.Adie@uk.ac.edinburgh)
  9.  Copyright (C) 1988 Edinburgh University Computing Service
  10.  Permission is granted to any individual or institution to use, copy, or
  11.  redistribute this software so long as it is not sold for profit, provided this
  12.  copyright notice is retained.
  13. */
  14.  
  15. #define    INCL_BASE    /* This is needed to pull in the stuff from os2.h */
  16.  
  17. /* Includes */
  18.  
  19. #include "ckcker.h"            /* Kermit definitions */
  20. #include "ckcdeb.h"            /* Typedefs, debug formats, etc */
  21. #include <ctype.h>            /* Character types */
  22. #include <stdio.h>            /* Standard i/o */
  23. #include <io.h>                /* File io function declarations */
  24. #include <process.h>            /* Process-control function declarations */
  25. #include <string.h>            /* String manipulation declarations */
  26. #include <stdlib.h>            /* Standard library declarations */
  27. #include <sys\types.h>
  28. #include <sys\stat.h>
  29. #include <time.h>            /* Time functions */
  30. #include <direct.h>            /* Directory function declarations */
  31. #include <os2.h>            /* This pulls in a whole load of stuff */
  32.  
  33. /*============================================================================*/
  34.  
  35. /*
  36.  * Everything between the lines of = signs can go once Microsoft update their
  37.  * header files to correspond with their QuickHelp documentation.
  38.  */
  39.  
  40. typedef struct _DCBINFO {
  41.     USHORT usWriteTimeout;
  42.     USHORT usReadTimeout;
  43.     BYTE   bFlags1;
  44.     BYTE   bFlags2;
  45.     BYTE   bFlags3;
  46.     BYTE   bErrorReplacementChar;
  47.     BYTE   bBreakReplacementChar;
  48.     BYTE   bXONChar;
  49.     BYTE   bXOFFChar;
  50. } DCBINFO;
  51.  
  52. #define    ASYNC_GETDCBINFO    0x0073
  53. #define    ASYNC_SETDCBINFO    0x0053
  54. #define    ASYNC_GETLINECTRL    0x0062
  55. #define    ASYNC_SETLINECTRL    0x0042
  56. #define    ASYNC_GETBAUDRATE    0x0061
  57. #define    ASYNC_SETMODEMCTRL    0x0046
  58. #define    ASYNC_SETBAUDRATE    0x0041
  59. #define    ASYNC_GETINQUECOUNT    0x0068
  60. #define    ASYNC_TRANSMITIMM    0x0044
  61. #define    ASYNC_SETBREAKON    0x004B
  62. #define    ASYNC_SETBREAKOFF    0x0045
  63.  
  64. /*============================================================================*/
  65.  
  66. char *ckxsys = " OS/2";
  67.  
  68.  
  69. /*
  70.  Variables available to outside world:
  71.  
  72.    dftty  -- Pointer to default tty name string, like "/dev/tty".
  73.    dfloc  -- 0 if dftty is console, 1 if external line.
  74.    dfprty -- Default parity
  75.    dfflow -- Default flow control
  76.    ckxech -- Flag for who echoes console typein:
  77.      1 - The program (system echo is turned off)
  78.      0 - The system (or front end, or terminal).
  79.    functions that want to do their own echoing should check this flag
  80.    before doing so.
  81.  
  82.  Functions for assigned communication line (either external or console tty):
  83.  
  84.    sysinit()               -- System dependent program initialization
  85.    syscleanup()            -- System dependent program shutdown
  86.    ttopen(ttname,local,mdmtyp) -- Open the named tty for exclusive access.
  87.    ttclos()                -- Close & reset the tty, releasing any access lock.
  88.    ttpkt(speed,flow,parity)-- Put the tty in packet mode
  89.                 or in DIALING or CONNECT modem control state.
  90.    ttvt(speed,flow)        -- Put the tty in virtual terminal mode.
  91.    ttinl(dest,max,timo)    -- Timed read line from the tty.
  92.    ttinc(timo)             -- Timed read character from tty.
  93.    ttchk()                 -- See how many characters in tty input buffer.
  94.    ttxin(n,buf)            -- Read n characters from tty (untimed).
  95.    ttol(string,length)     -- Write a string to the tty.
  96.    ttoc(c)                 -- Write a character to the tty.
  97.    ttflui()                -- Flush tty input buffer.
  98.    ttspeed()               -- Speed of tty line.
  99.    
  100. Functions for console terminal:
  101.  
  102.    conraw()  -- Set console into Raw mode
  103.    concooked() -- Set console into Cooked mode
  104.    conoc(c)  -- Unbuffered output, one character to console.
  105.    conol(s)  -- Unbuffered output, null-terminated string to the console.
  106.    conola(s) -- Unbuffered output, array of strings to the console.
  107.    conxo(n,s) -- Unbuffered output, n characters to the console.
  108.    conchk()  -- Check if characters available at console (bsd 4.2).
  109.         Check if escape char (^\) typed at console (System III/V).
  110.    coninc(timo)  -- Timed get a character from the console.
  111.  Following routines are dummies:
  112.    congm()   -- Get console terminal mode.
  113.    concb()   -- Put console into single char mode with no echo.
  114.    conres()  -- Restore console to congm mode.
  115.    conint()  -- Enable console terminal interrupts.
  116.    connoi()  -- No console interrupts.
  117.  
  118. Time functions
  119.  
  120.    sleep(t)  -- Like UNIX sleep
  121.    msleep(m) -- Millisecond sleep
  122.    ztime(&s) -- Return pointer to date/time string
  123.    rtimer() --  Reset timer
  124.    gtimer()  -- Get elapsed time since last call to rtimer()
  125. */
  126.  
  127.  
  128. /* Defines */
  129.  
  130. #define DEVNAMLEN    14
  131.  
  132. /* Declarations */
  133.  
  134. /* dftty is the device name of the default device for file transfer */
  135. /* dfloc is 0 if dftty is the user's console terminal, 1 if an external line */
  136.  
  137. extern int parity;
  138. CHAR dopar();
  139.  
  140.     char *dftty = "COM1";
  141.     int dfloc = 1;
  142.  
  143.     int dfprty = 0;            /* Default parity (0 = none) */
  144.     int ttprty = 0;            /* Parity in use. */
  145.     int ttmdm = 0;            /* Modem in use. */
  146.     int dfflow = 1;            /* Xon/Xoff flow control */
  147.     int backgrd = 0;            /* Assume in foreground (no '&' ) */
  148.  
  149. int ckxech = 1; /* 0 if system normally echoes console characters, else 1 */
  150.  
  151. /* Declarations of variables global within this module */
  152.  
  153. static struct rdchbuf_rec {        /* Buffer for serial characters */
  154.     unsigned char buffer[256];
  155.     USHORT length, index;
  156. } rdchbuf;
  157.  
  158. static long tcount;            /* Elapsed time counter */
  159.  
  160. static HFILE ttyfd = -1;        /* TTY file descriptor */
  161.  
  162. DCBINFO ttydcb;
  163.  
  164. static char xtnded = 0;            /* Is there a pending extended keystroke */
  165. static char xtndedcode;            /* Pending extended keystroke */
  166.  
  167.  
  168. /*  S Y S I N I T  --  System-dependent program initialization.  */
  169.  
  170. sysinit() {
  171.     conraw();            /* Keyboard to raw mode */
  172.     return(0);
  173. }
  174.  
  175.  
  176. /*  S Y S C L E A N U P  --  System-dependent program cleanup.  */
  177.  
  178. syscleanup() {
  179.     concooked();    /* Keyboard to cooked mode */
  180.     return(0);
  181. }
  182.  
  183.  
  184. /*  T T O P E N  --  Open a tty for exclusive access.  */
  185.  
  186. /*  Returns 0 on success, -1 on failure.  */
  187. /*
  188.   If called with lcl < 0, sets value of lcl as follows:
  189.   0: the terminal named by ttname is the job's controlling terminal.
  190.   1: the terminal named by ttname is not the job's controlling terminal.
  191.   But watch out: if a line is already open, or if requested line can't
  192.   be opened, then lcl remains (and is returned as) -1.
  193. */
  194. ttopen(ttname,lcl,modem) char *ttname; int *lcl, modem; {
  195.  
  196.     char *x; extern char* ttyname();
  197.     char cname[DEVNAMLEN+4];
  198.     USHORT action;
  199.  
  200.     if (ttyfd != -1) return(0);        /* If already open, ignore this call */
  201.     if (*lcl == 0) return(-1);        /* Won't open in local mode */
  202.     
  203.     ttmdm = modem;            /* Make this available to other fns */
  204.     if (DosOpen(ttname,&ttyfd,&action,0L,0,1,0x0012,0L)) {
  205.     ttyfd = -1;
  206.     perror(ttname);            /* Can't open it */
  207.     return(-1);
  208.     }
  209.  
  210.     rdchbuf.length = rdchbuf.index = 0;
  211.     debug(F111,"ttopen ok",ttname,*lcl);
  212.  
  213. /* Caller wants us to figure out if line is controlling tty */
  214.     if (*lcl == -1) {
  215.     *lcl = 1;            /* Can never transfer with console */
  216.     }
  217.  
  218.     /* Read DCB */
  219.     if (DosDevIOCtl(&ttydcb,NULL,ASYNC_GETDCBINFO,1,ttyfd)) { /* Not a serial port */
  220.         ttyfd = -1;
  221.         return(-1);
  222.     }
  223.     ttydcb.bFlags3 &= 0xF9;
  224.     ttydcb.bFlags3 |= 0x04;    /* Read "some" data from line mode */
  225.     DosDevIOCtl(NULL,&ttydcb,ASYNC_SETDCBINFO,1,ttyfd);
  226.     ttprty = dfprty;        /* Make parity the default parity */
  227.     if (ttsettings(ttprty,0)) return(-1);
  228.     return(ttflui());
  229. }
  230.  
  231. /*  T T S E T T I N G S  --  Set the device driver parity and stop bits */
  232.  
  233. ttsettings(par,stop) int par, stop; {
  234.     char data[4];
  235.  
  236.     if (DosDevIOCtl(data,NULL,ASYNC_GETLINECTRL,1,ttyfd)) return(-1); /* Get line */
  237.     switch (par) {
  238.         case 'e':
  239.         data[0] = 7;    /* Data bits */
  240.         data[1] = 2;
  241.         break;
  242.     case 'o':
  243.         data[0] = 7;    /* Data bits */
  244.         data[1] = 1;
  245.         break;
  246.     case 'm':
  247.         data[0] = 7;    /* Data bits */
  248.         data[1] = 3;
  249.         break;
  250.     case 's':
  251.         data[0] = 7;    /* Data bits */
  252.         data[1] = 4;
  253.         break;
  254.     default :
  255.         data[0] = 8;    /* Data bits */
  256.         data[1] = 0;    /* No parity */
  257.     }
  258.     switch (stop) {
  259.         case 2:
  260.             data[2] = 2;    /* Two stop bits */
  261.             break;
  262.         case 1:
  263.             data[2] = 0;    /* One stop bit */
  264.             break;
  265.         default: ;        /* No change */
  266.     }
  267.     if (DosDevIOCtl(NULL,data,ASYNC_SETLINECTRL,1,ttyfd)) return(-1); /* Set line */
  268.     return(0);
  269. }
  270.  
  271. /*  T T I S C O M  --  Is the given handle an open COM port? */
  272.  
  273. ttiscom(HFILE f) {
  274.     ttclos();
  275.     ttyfd = f;
  276.     /* Read DCB */
  277.     if (DosDevIOCtl(&ttydcb,NULL,ASYNC_GETDCBINFO,1,ttyfd)) { /* Not a serial port */
  278.         ttyfd = -1;
  279.         return( 0 /* bad */ );
  280.     }
  281.     return( 1 /* good */ );
  282. }
  283.  
  284. /*  T T C L O S  --  Close the TTY.  */
  285.  
  286. ttclos() {
  287.     if (ttyfd == -1) return(0);        /* Wasn't open. */
  288.     DosClose(ttyfd);
  289.     ttyfd = -1;
  290.     return(0);
  291. }
  292.  
  293. /*  T T S P E E D  --  return speed of tt line, or of default line */
  294.  
  295. ttspeed() {
  296.     char df;
  297.     int sp=-1;
  298.     
  299.     df = (ttyfd == -1);
  300.     if (df) if (ttopen(dftty,&sp,0)) return(-1);
  301.     if (DosDevIOCtl(&sp,NULL,ASYNC_GETBAUDRATE,1,ttyfd)) sp=-1;
  302.     return(sp);
  303. }
  304.  
  305.  
  306. /*  T T H A N G -- Hangup phone line */
  307.  
  308. tthang() {
  309.     char parms[2];
  310.     USHORT data;
  311.     
  312.     if (ttyfd == -1) return(0);        /* Not open, so must be hung up */
  313.     parms[0] = 0x00;
  314.     parms[1] = 0xFE;            /* Drop DTR */
  315.     return(DosDevIOCtl(&data,parms,ASYNC_SETMODEMCTRL,1,ttyfd));
  316. }
  317.  
  318.  
  319. /*  T T R E S  --  Restore terminal to "normal" mode.  */
  320.  
  321. ttres() {                /* Restore the tty to normal. */
  322.     if (ttyfd == -1) return(-1);    /* Not open */
  323.     return(0);
  324. }
  325.  
  326. #define DIALING 4        /* for ttpkt parameter */
  327. #define CONNECT 5
  328.  
  329. /*  T T P K T  --  Condition the communication line for packets. */
  330. /*        or for modem dialing */
  331.  
  332. /*  If called with speed > -1, also set the speed.  */
  333. /*  Returns 0 on success, -1 on failure.  */
  334.  
  335. ttpkt(speed,flow,parity) int speed, flow, parity; {
  336.     int s;
  337.     USHORT x;
  338.  
  339.     if (ttyfd < 0) return(-1);        /* Not open. */
  340.  
  341.     if (speed > -1) {
  342.     if ((x = ttsspd(speed))<0) return(-1);        /* Check the speed */
  343.     if (DosDevIOCtl(NULL,&x,ASYNC_SETBAUDRATE,1,ttyfd)) return(-1); /* Set the speed */
  344.     }
  345.  
  346.     ttprty = parity;
  347.     if (ttsettings(ttprty,0)) return(-1);
  348.     debug(F101,"ttpkt setting ttprty","",ttprty);
  349.  
  350.     if (flow == DIALING) {        /* Ignore DCD */
  351.     debug(F100,"ttpkt DIALING","",0);
  352.     /* Driver default is to do so */
  353.     } else
  354.     if (flow == CONNECT) {        /* Pay attention to DCD */
  355.     debug(F100,"ttpkt CONNECT","",0);
  356.     /* We're warned against doing so, for some reason, so no action */
  357.     } else
  358.     return(os2setflow(flow));
  359. }
  360.  
  361.  
  362. /*  T T V T -- Condition communication line for use as virtual terminal  */
  363.  
  364. ttvt(speed,flow) int speed, flow; {
  365.     USHORT x;
  366.  
  367.     if (ttyfd < 0) return(-1);        /* Not open. */
  368.  
  369.     if (speed > -1) {
  370.     if ((x = ttsspd(speed))<0) return(-1);        /* Check the speed */
  371.     if (DosDevIOCtl(NULL,&x,ASYNC_SETBAUDRATE,1,ttyfd)) return(-1); /* Set the speed */
  372.     }
  373.     ttprty = parity;
  374.     if (ttsettings(ttprty,0)) return(-1);
  375.  
  376.     return(os2setflow(flow));
  377. }
  378.  
  379.  
  380. /*  O S 2 S E T F L O W -- set flow state of tty */
  381.  
  382. /*  If flow = 0 turn receive flow XON/XOFF control off, otherwise turn it on.
  383.     If successful, return 0, otherwise return -1.  */
  384.  
  385. os2setflow(flow) int flow; {
  386.  
  387.         ttydcb.bFlags2 &= 0xFD;            /* Set RX flow off */
  388.         if (flow != 0) ttydcb.bFlags2 |= 0x02;    /* Set RX flow on */
  389.         if (DosDevIOCtl(NULL,&ttydcb,ASYNC_SETDCBINFO,1,ttyfd)) return(-1); /* Set DCB */
  390.     return(0);
  391. }
  392.  
  393.  
  394. /*  T T S S P D  --  Return the speed if OK, otherwise -1 */
  395.  
  396. ttsspd(speed) int speed; {
  397.     int s, spdok;
  398.  
  399.     if (speed < 0) return(-1);
  400.     spdok = 1;            /* Assume arg ok */
  401.     switch (speed) {
  402.         case 110:
  403.         case 150:
  404.         case 300:
  405.         case 600:
  406.         case 1200:
  407.         case 2400:
  408.         case 4800:
  409.         case 9600:
  410.         case 19200: break;
  411.         default:
  412.             spdok = 0;
  413.         fprintf(stderr,"Unsupported line speed - %d\n",speed);
  414.         fprintf(stderr,"Current speed not changed\n");
  415.         break;
  416.     }
  417.     if (spdok) return(speed); else return(-1);
  418.  }
  419.  
  420.  
  421. /*  T T F L U I  --  Flush tty input buffer */
  422.  
  423. ttflui() {
  424.     char parm=0;
  425.     long int data;
  426.     int i;
  427.  
  428.     rdchbuf.index = rdchbuf.length = 0;        /* Flush internal buffer */
  429.     DosDevIOCtl(&data,&parm,0x0001,11,ttyfd);    /* Flush driver buffer */
  430.     return(0);
  431. }
  432.  
  433.  
  434. /*  T T C H K  --  Tell how many characters are waiting in tty input buffer  */
  435.  
  436. ttchk() {
  437.     USHORT data[2];
  438.     if(DosDevIOCtl(data,NULL,ASYNC_GETINQUECOUNT,1,ttyfd)) return(0);
  439.     else return((rdchbuf.length-rdchbuf.index)+data[0]);
  440. }
  441.  
  442.  
  443. /*  T T X I N  --  Get n characters from tty input buffer  */
  444.  
  445. /*  Returns number of characters actually gotten, or -1 on failure  */
  446.  
  447. /*  Intended for use only when it is known that n characters are actually */
  448. /*  available in the input buffer.  */
  449.  
  450. ttxin(n,buf) int n; char *buf; {
  451.     int i, j;
  452.     
  453.     if (ttyfd < 0) return(-1);        /* Not open. */
  454.     i = 0;
  455.     while (i < n) {
  456.         if ((j = ttinc(0)) < 0) break;
  457.         buf[i++] = j;
  458.     }
  459.     return(i);
  460. }
  461.  
  462. /*  T T O L  --  Similar to "ttinl", but for writing.  */
  463.  
  464. ttol(s,n) int n; char *s; {
  465.     USHORT i;
  466.     CHAR pkt[1100];            /* So big that we needn't check */
  467.     
  468.     if (ttyfd < 0) return(-1);        /* Not open. */
  469.     if (!parity) {
  470.     if (DosWrite(ttyfd,s,n,&i)) return(-1);
  471.     else return(i);
  472.     } else {
  473.     for (i=0;i<n;i++) pkt[i]=dopar(s[i]);
  474.     if (DosWrite(ttyfd,pkt,n,&i)) return(-1);
  475.     else return(i);
  476.     }
  477. }
  478.  
  479.  
  480. /*  T T O C  --  Output a character to the communication line  */
  481.  
  482. ttoc(c) char c; {
  483.     USHORT i;
  484.     CHAR ch = dopar(c);
  485.     
  486.     if (ttyfd < 0) return(-1);        /* Not open. */
  487.     if(DosWrite(ttyfd,&ch,1,&i)) return(-1);
  488.     else return(i);
  489. }
  490.  
  491.  
  492. /*  T T O C I  --  Output a character to the communication line immediately */
  493.  
  494. ttoci(c) char c; {
  495.     USHORT i;
  496.     CHAR ch = dopar(c);
  497.     
  498.     if (ttyfd < 0) return(-1);        /* Not open. */
  499.     if(DosDevIOCtl(NULL,&ch,ASYNC_TRANSMITIMM,1,ttyfd)) return(-1);
  500.     else return(1);
  501. }
  502.  
  503.  
  504. /*  T T I N L  --  Read a record (up to break character) from comm line.  */
  505. /*
  506.   If no break character encountered within "max", return "max" characters,
  507.   with disposition of any remaining characters undefined.  Otherwise, return
  508.   the characters that were read, including the break character, in "dest" and
  509.   the number of characters read as the value of the function, or 0 upon end of
  510.   file, or -1 if an error occurred.  Times out & returns error if not completed
  511.   within "timo" seconds.
  512. */
  513. ttinl(dest,max,timo,eol) int max,timo; CHAR *dest, eol; {
  514.     int x = 0, c, i, m;
  515.  
  516.     if (ttyfd < 0) return(-1);        /* Not open. */
  517.     *dest = '\0';            /* Clear destination buffer */
  518.     i = 0;                /* Next char to process */
  519.     while (1) {
  520.     if ((c = ttinc(100*timo)) == -1) {
  521.         x = -1;
  522.         break;
  523.     }
  524.         dest[i] = c;            /* Got one. */
  525.     if (dest[i] == eol) {
  526.         dest[++i] = '\0';
  527.         return(i);
  528.     }
  529.     if (i++ > max) {
  530.         debug(F101,"ttinl buffer overflow","",i);
  531.         x = -1;
  532.         break;
  533.     }
  534.     }
  535.     debug(F100,"ttinl timout","",0);    /* Get here on timeout. */
  536.     debug(F111," with",dest,i);
  537.     return(x);                /* and return error code. */
  538. }
  539.  
  540.  
  541. /*  T T I N C --  Read a character from the communication line  */
  542.  
  543. /* Note that the parameter is the time to wait in *centiseconds*, not secs. */
  544.  
  545. ttinc(timo) int timo; {
  546.     int m, i;
  547.     char ch = 0;
  548.  
  549.     m = (ttprty) ? 0177 : 0377;        /* Parity stripping mask. */
  550.     if (ttyfd < 0) return(-1);        /* Not open. */
  551.     if (timo <= 0) {            /* Untimed. */
  552.     do i = rdch(); while (i < 0);    /* Wait for a character. */
  553.     return(i & m);
  554.     } else {
  555.         if (timo != ttydcb.usReadTimeout) { /* Set timeout value */
  556.             ttydcb.usReadTimeout = timo;
  557.             if (DosDevIOCtl(NULL,&ttydcb,ASYNC_SETDCBINFO,1,ttyfd)) return(-1);
  558.         }
  559.         i = rdch();
  560.     if (i < 0) return(-1);
  561.     else return(i & m);
  562.     }
  563. }
  564.  
  565. /*  RDCH -- Read characters from the serial port, maintaining an internal
  566.             buffer of characters for the sake of efficiency. */
  567. static rdch() {
  568.  
  569.     if (rdchbuf.index == rdchbuf.length) {
  570.         rdchbuf.index = 0;
  571.         if (DosRead(ttyfd,rdchbuf.buffer,
  572.                 sizeof(rdchbuf.buffer),&rdchbuf.length)) {
  573.             rdchbuf.length = 0;
  574.                   return(-1);
  575.                }
  576.            }
  577.     return( (rdchbuf.index < rdchbuf.length) ? rdchbuf.buffer[rdchbuf.index++]
  578.                          : -1 );
  579. }    
  580.  
  581.  
  582. /*  T T S N D B  --  Send a BREAK signal  */
  583.  
  584. ttsndb() {
  585.     USHORT i;
  586.     
  587.     DosDevIOCtl(&i,NULL,ASYNC_SETBREAKON,1,ttyfd);    /* Break on */
  588.     DosSleep(1000L);                    /* ZZZzzz */
  589.     DosDevIOCtl(&i,NULL,ASYNC_SETBREAKOFF,1,ttyfd);    /* Break off */
  590. }
  591.  
  592. /*  S L E E P  --  Emulate the Unix sleep function  */
  593.  
  594. sleep(t) unsigned t; {
  595.     ULONG lm = t*1000L;
  596.  
  597.     DosSleep(lm);
  598. }
  599.  
  600.  
  601. /*  M S L E E P  --  Millisecond version of sleep().  */
  602.  
  603. /* Intended only for small intervals.  For big ones, just use sleep(). */
  604.  
  605. msleep(m) int m; {
  606.     ULONG lm = m;
  607.     
  608.     DosSleep(lm);
  609. }
  610.  
  611.  
  612. /*  R T I M E R --  Reset elapsed time counter  */
  613.  
  614. rtimer() {
  615.     tcount = time( (long *) 0 );
  616. }
  617.  
  618.  
  619. /*  G T I M E R --  Get current value of elapsed time counter in seconds  */
  620.  
  621. gtimer() {
  622.     int x;
  623.     x = (int) (time( (long *) 0 ) - tcount);
  624.     rtimer();
  625.     return( (x < 0) ? 0 : x );
  626. }
  627.  
  628.  
  629. /*  Z T I M E  --  Return date/time string  */
  630.  
  631. ztime(s) char **s; {
  632.     long clock_storage;
  633.  
  634.     clock_storage = time( (long *) 0 );
  635.     *s = ctime( &clock_storage );
  636. }
  637.  
  638. /*  C O N O C  --  Output a character to the console terminal  */
  639.  
  640. conoc(c) char c; {
  641.     write(1,&c,1);
  642. }
  643.  
  644.  
  645. /*  C O N X O  --  Write x characters to the console terminal  */
  646.  
  647. conxo(x,s) char *s; int x; {
  648.     write(1,s,x);
  649. }
  650.  
  651.  
  652. /*  C O N O L  --  Write a line to the console terminal  */
  653.  
  654. conol(s) char *s; {
  655.     int len;
  656.     len = strlen(s);
  657.     write(1,s,len);
  658. }
  659.  
  660.  
  661. /*  C O N O L A  --  Write an array of lines to the console terminal */
  662.  
  663. conola(s) char *s[]; {
  664.     int i;
  665.     for (i=0 ; *s[i] ; i++) conol(s[i]);
  666. }
  667.  
  668.  
  669. /*  C O N O L L  --  Output a string followed by CRLF  */
  670.  
  671. conoll(s) char *s; {
  672.     conol(s);
  673.     write(1,"\r\n",2);
  674. }
  675.  
  676.  
  677. /*  C O N C H K  --  Return how many characters available at console  */
  678.  
  679. conchk() {
  680.     KBDKEYINFO k;
  681.  
  682.     KbdPeek(&k,0);
  683.     return( (k.fbStatus & 0x40) ? 1 : 0 );
  684. }
  685.  
  686.  
  687. /*  C O N I N C  --  Get a character from the console  */
  688.  
  689. coninc(timo) int timo; {
  690.     /* We should return -1 if no character received within timo secs,
  691.        but that's difficult to do and not needed anyway for OS/2.  */
  692.     KBDKEYINFO k;
  693.  
  694.     if (xtnded) {            /* Is there a pending extended code */
  695.         xtnded = 0;
  696.         return(xtndedcode);
  697.     }
  698.     KbdCharIn(&k,0,0);            /* No, so read the keyboard */
  699.     if (k.chChar == 0) {
  700.         xtnded = 1;
  701.         xtndedcode = k.chScan;
  702.     }
  703.     return( k.chChar );
  704. }
  705.  
  706.  
  707. conraw() {
  708.     KBDINFO k;
  709.     
  710.     k.cb = 10;
  711.     k.fsMask = 0x06;    /* Set raw mode */
  712.     k.chTurnAround = 0;
  713.     k.fsInterim = 0;
  714.     k.fsState = 0;
  715.     return(KbdSetStatus(&k,0));
  716. }
  717.  
  718. concooked() {
  719.     KBDINFO k;
  720.     
  721.     k.cb = 10;
  722.     k.fsMask = 0x09;    /* Set cooked mode */
  723.     k.chTurnAround = 0;
  724.     k.fsInterim = 0;
  725.     k.fsState = 0;
  726.     return(KbdSetStatus(&k,0));
  727. }
  728.  
  729. /*  C O N G M  -- Get console terminal mode. */
  730.  
  731. congm() {}
  732.  
  733.  
  734. /*  C O N C B  -- Put console into single char mode with no echo. */
  735.  
  736. concb(esc) char esc; {}
  737.  
  738.  
  739. /*  C O N R E S -- Restore console to congm mode. */
  740.  
  741. conres() {}
  742.  
  743.  
  744. /*  C O N I N T -- Enable console terminal interrupts. */
  745.  
  746. conint(f) int (*f)(); {}
  747.  
  748.  
  749. /*  C O N N O I -- No console interrupts. */
  750.  
  751. connoi() {}
  752.  
  753. /*****************************************************************************/
  754.  
  755. /* The following code tries to implement the Unix 'alarm' function under OS/2. */
  756.  
  757. #include <signal.h>
  758. #include <malloc.h>
  759.  
  760. #define THRDSTKSIZ    2048
  761. static    char *alarmstack;
  762. static    ULONG alarmtime;
  763. static     ULONG tsem = 0, hold = 0;
  764. static    int pid;
  765. static    int initialised = 0;
  766.  
  767. #pragma check_stack-
  768. VOID FAR alarmthread(void) {
  769.     while(1) {
  770.     DosSemSetWait(&hold,-1L);    /* Wait until we're told to go */
  771.     if ( DosSemSetWait(&tsem,alarmtime*1000L) == ERROR_SEM_TIMEOUT ) {
  772.         DosFlagProcess(pid,1,0,0);
  773.     }
  774.     }
  775. }
  776. #pragma check_stack+
  777.  
  778. alarminit() {
  779.     USHORT threadid;
  780.     pid = getpid();
  781.     if ( (alarmstack=malloc(THRDSTKSIZ)) == NULL) {
  782.         printf("Not enough space for alarm thread stack\n");
  783.         exit(1);
  784.     }
  785.     alarmstack+=THRDSTKSIZ;
  786.     if (DosCreateThread(alarmthread,&threadid,alarmstack)) {
  787.         printf("Can't create alarm thread\n");
  788.         exit(1);
  789.     }
  790.     while (!hold) DosSleep(300L);    /* Wait for thread to start */
  791.     initialised = 1;
  792. }
  793.  
  794. /*  A L A R M  --  Issue a signal after a specified time */
  795.  
  796. /* Call with t=0 to cancel an alarm.  t>0 is the time in seconds after which
  797.    a signal will be generated.  The signal will be a User Flag A signal, which
  798.    thread 1 must acknowledge with a call to alarmack().  The time t can be
  799.    up to 64k seconds.
  800.    */
  801. alarm(t) unsigned t; {
  802.     if (!initialised) alarminit();
  803.     alarmtime = t;            /* In seconds */
  804.     DosSemClear(&tsem);        /* stopping an existing alarm */
  805.     if (t>0) DosSemClear(&hold);    /* starting a new one */
  806. }
  807.  
  808. /*  A L A R M A C K  --  Acknowledge alarm call received */
  809.  
  810. alarmack() {
  811.     signal(SIGUSR1,SIG_ACK);
  812. }
  813.