home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 3 Comm / 03-Comm.zip / CKPM5X_S.ZIP / CKOTIO.C < prev    next >
C/C++ Source or Header  |  1990-05-27  |  29KB  |  1,024 lines

  1. char *ckxv = "OS/2 console i/o, 13-Apr-90";
  2. char *ckxsys = "\nA PM 1.2 version\nWith some Tektronix support\n27-May-90\n";
  3.  
  4. /* C K O T I O  --  Kermit console i/o support for OS/2 systems */
  5.  
  6. /* Also contains code to emulate the Unix 'alarm' function under OS/2 */
  7.  
  8. /*
  9.  Author: Chris Adie (C.Adie@uk.ac.edinburgh)
  10.  Copyright (C) 1988 Edinburgh University Computing Service
  11.  Permission is granted to any individual or institution to use, copy, or
  12.  redistribute this software so long as it is not sold for profit, provided this
  13.  copyright notice is retained.
  14. */
  15.  
  16. /*
  17. Modifications and additions for Presentation Manager by C.P.Armstrong
  18. Copyright (C) 1990 C.P.Armstrong.
  19. */
  20.  
  21. /*
  22. ttinc() modified wrt timeouts.  The "untimed" timeout setting assumed rdch()
  23. returned immediately if no char waiting.  Not so. The DosRead waits forever
  24. and is impervious to the alarm signals for some reason.  So ttins() for 
  25. "untimed"
  26. reads sets a timeout of 0.1s then goes ahead and repeatedly checks the rdch()
  27. return value for a character.
  28.  
  29. Note that timo means centiseconds plus 0.01 according to MS Prog.Ref. Vol3 p336
  30. */
  31.  
  32.  
  33. #define INCL_BASE   /* This is needed to pull in the stuff from os2.h */
  34. #define INCL_AVIO   /* THis is needed to pull in even more!           */
  35. #define INCL_WININPUT
  36. #include <os2.h>            /* This pulls in lots of stuff */
  37.  
  38. /* Includes */
  39.  
  40. #include <ctype.h>          /* Character types */
  41. #include <stdio.h>          /* Standard i/o */
  42. #include <io.h>             /* File io function declarations */
  43. #include <process.h>            /* Process-control function decl's */
  44. #include <string.h>         /* String manipulation declarations */
  45. #include <stdlib.h>         /* Standard library declarations */
  46. #include <sys\types.h>
  47. #include <sys\stat.h>
  48. #include <time.h>           /* Time functions */
  49. #include <direct.h>         /* Directory function declarations */
  50. #include <signal.h>
  51. #include "ckcker.h"         /* Kermit definitions */
  52. #include "ckofns.h"
  53. #include "ckcdeb.h"         /* Typedefs, debug formats, etc */
  54.  
  55.  
  56.  
  57. /*
  58.  Variables available to outside world:
  59.  
  60.    dftty  -- Pointer to default tty name string, like "/dev/tty".
  61.    dfloc  -- 0 if dftty is console, 1 if external line.
  62.    dfprty -- Default parity
  63.    dfflow -- Default flow control
  64.    ckxech -- Flag for who echoes console typein:
  65.      1 - The program (system echo is turned off)
  66.      0 - The system (or front end, or terminal).
  67.    functions that want to do their own echoing should check this flag
  68.    before doing so.
  69.  
  70.  Functions for assigned communication line (either external or console tty):
  71.  
  72.    sysinit()               -- System dependent program initialization
  73.    syscleanup()            -- System dependent program shutdown
  74.    ttopen(ttname,local,mdmtyp) -- Open the named tty for exclusive access.
  75.    ttclos()                -- Close & reset the tty, releasing any access lock.
  76.    ttpkt(speed,flow,parity)-- Put the tty in packet mode
  77.                 or in DIALING or CONNECT modem control state.
  78.    ttvt(speed,flow)        -- Put the tty in virtual terminal mode.
  79.    ttinl(dest,max,timo)    -- Timed read line from the tty.
  80.    ttinc(timo)             -- Timed read character from tty.
  81.    ttchk()                 -- See how many characters in tty input buffer.
  82.    ttxin(n,buf)            -- Read n characters from tty (untimed).
  83.    ttol(string,length)     -- Write a string to the tty.
  84.    ttoc(c)                 -- Write a character to the tty.
  85.    ttflui()                -- Flush tty input buffer.
  86.    ttspeed()               -- Speed of tty line.
  87.    
  88. Functions for console terminal:
  89.  
  90.    conraw()  -- Set console into Raw mode
  91.    concooked() -- Set console into Cooked mode
  92.    conoc(c)  -- Unbuffered output, one character to console.
  93.    conol(s)  -- Unbuffered output, null-terminated string to the console.
  94.    conola(s) -- Unbuffered output, array of strings to the console.
  95.    conxo(n,s) -- Unbuffered output, n characters to the console.
  96.    conchk()  -- Check if characters available at console (bsd 4.2).
  97.         Check if escape char (^\) typed at console (System III/V).
  98.    coninc(timo)  -- Timed get a character from the console.
  99.  Following routines are dummies:
  100.    congm()   -- Get console terminal mode.
  101.    concb()   -- Put console into single char mode with no echo.
  102.    conres()  -- Restore console to congm mode.
  103.    conint()  -- Enable console terminal interrupts.
  104.    connoi()  -- No console interrupts.
  105.  
  106. Time functions
  107.  
  108.    sleep(t)  -- Like UNIX sleep
  109.    msleep(m) -- Millisecond sleep
  110.    ztime(&s) -- Return pointer to date/time string
  111.    rtimer() --  Reset timer
  112.    gtimer()  -- Get elapsed time since last call to rtimer()
  113. */
  114.  
  115.  
  116. /* Defines */
  117.  
  118. #define DEVNAMLEN   14
  119.  
  120. /* Declarations */
  121.  
  122. /* dftty is the device name of the default device for file transfer */
  123. /* dfloc is 0 if dftty is the user's console terminal, 1 if an external line */
  124.  
  125. extern int parity;
  126. CHAR dopar();
  127.  
  128.     char *dftty = "COM1";
  129.     int dfloc = 1;
  130.  
  131.     int far dfprty = 0;     /* Default parity (0 = none) */
  132.     int far ttprty = 0;     /* Parity in use. */
  133.     int far ttmdm = 0;      /* Modem in use. */
  134.     int far dfflow = 1;     /* Xon/Xoff flow control */
  135.     int far odsr=1;         /* Flow control with DSR (output) ON default */
  136.     int far idsr=1;         /* Flow control with DSR (input)  ON default */
  137.     int far octs=1;         /* Flow control with CTS (output) ON default */
  138.  
  139.     int backgrd = 0;            /* Assume in foreground (no '&' ) */
  140.  
  141. int ckxech = 1; /* 0 if system normally echoes console characters, else 1 */
  142.  
  143. /* Declarations of variables global within this module */
  144.  
  145. static struct rdchbuf_rec {     /* Buffer for serial characters */
  146.     unsigned char buffer[256];
  147.     USHORT length, index;
  148. } rdchbuf;
  149.  
  150. static long tcount;         /* Elapsed time counter */
  151.  
  152. static HFILE ttyfd = -1;        /* TTY file descriptor */
  153.  
  154. DCBINFO ttydcb;
  155.  
  156. static char xtnded = 0;         /* Pending extended keystroke? */
  157. static char xtndedcode;         /* Pending extended keystroke. */
  158.  
  159.  
  160. /*  S Y S I N I T  --  System-dependent program initialization.  */
  161.  
  162. sysinit() {
  163.     conraw();                     /* Keyboard to raw mode */
  164.     PM_init("C-Kermit for OS/2"); /* Initialise the Presentation */
  165.                                   /* Manager thread */
  166.     return(0);
  167. }
  168.  
  169.  
  170. /*  S Y S C L E A N U P  --  System-dependent program cleanup.  */
  171.  
  172. syscleanup() {
  173.     concooked();    /* Keyboard to cooked mode */
  174.  
  175.     /* Kermit has been causing "System internal errors at 00A8:56E2" which */
  176.     /* crash OS/2 and are extremely annoying.  These happen mid program    */
  177.     /* sometimes, especially doing a directory but mainly on program       */
  178.     /* shutdown.  So shutdown the PM thread specifically.                  */
  179.     killpm();
  180.  
  181.     return(0);
  182. }
  183.  
  184.  
  185. /*  T T O P E N  --  Open a tty for exclusive access.  */
  186.  
  187. /*  Returns 0 on success, -1 on failure.  */
  188. /*
  189.   If called with lcl < 0, sets value of lcl as follows:
  190.   0: the terminal named by ttname is the job's controlling terminal.
  191.   1: the terminal named by ttname is not the job's controlling terminal.
  192.   But watch out: if a line is already open, or if requested line can't
  193.   be opened, then lcl remains (and is returned as) -1.
  194. */
  195. ttopen(ttname,lcl,modem) char *ttname; int *lcl, modem; {
  196.  
  197.     char *x; extern char* ttyname();
  198.     char cname[DEVNAMLEN+4];
  199.     USHORT action;
  200.     BYTE dummy;
  201.  
  202.     if (ttyfd != -1) return(0);     /* If already open, ignore this call */
  203.     if (*lcl == 0) return(-1);      /* Won't open in local mode */
  204.     
  205.     ttmdm = modem;          /* Make this available to other fns */
  206.     if (DosOpen(ttname,&ttyfd,&action,0L,0,1,
  207.             OPEN_ACCESS_READWRITE | 
  208.             OPEN_SHARE_DENYREADWRITE | 
  209.             OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_WRITE_THROUGH,
  210.             0L)) 
  211.         {
  212.         ttyfd = -1;
  213.         return(-1);
  214.         }
  215.  
  216.     rdchbuf.length = rdchbuf.index = 0;
  217.     debug(F111,"ttopen ok",ttname,*lcl);
  218.  
  219. /* Caller wants us to figure out if line is controlling tty */
  220.     if (*lcl == -1) {
  221.     *lcl = 1;           /* Can never transfer with console */
  222.     }
  223.  
  224.     /* Read DCB */
  225.     if (DosDevIOCtl(&ttydcb,NULL,ASYNC_GETDCBINFO,1,ttyfd)) {
  226.         ttyfd = -1;         /* Not a serial port */
  227.         return(-1);
  228.     }
  229.  
  230.     ttydcb.fbTimeout &= 0xF9;
  231.     ttydcb.fbTimeout |= 0x04;   /* Read "some" data from line mode */
  232.  
  233. //    /* Read "some" data from line mode */
  234. //    ttydcb.fbTimeout |= MODE_READ_TIMEOUT;   
  235.     
  236. //    ttydcb.fbTimeout ^= MODE_NO_WRITE_TIMEOUT;  /* Disable infinite writes */
  237. //    ttydcb.fbTimeout |= MODE_NO_WRITE_TIMEOUT;  /* write waits             */
  238.  
  239. //    ttydcb.usWriteTimeout = 999;             /* 10 seconds */
  240.  
  241.     if(DosDevIOCtl(NULL,&ttydcb,ASYNC_SETDCBINFO,1,ttyfd)!=0)
  242.         {
  243.         printf("ttopen - Failed to set line parameters\n");
  244.         return(-1);
  245.         }
  246.     ttprty = dfprty;        /* Make parity the default parity */
  247.     if (ttsettings(ttprty,0)) return(-1);
  248.     return(ttflui());
  249. }
  250.  
  251. /*  T T S E T T I N G S  --  Set the device driver parity and stop bits */
  252.  
  253. ttsettings(par,stop) int par, stop; {
  254.     char data[4];
  255.  
  256.  
  257.     /* Get line */
  258.     if (DosDevIOCtl(data,NULL,ASYNC_GETLINECTRL,1,ttyfd)) return(-1);
  259.     switch (par) {
  260.         case 'e':
  261.         data[0] = 7;    /* Data bits */
  262.         data[1] = 2;
  263.         break;
  264.     case 'o':
  265.         data[0] = 7;    /* Data bits */
  266.         data[1] = 1;
  267.         break;
  268.     case 'm':
  269.         data[0] = 7;    /* Data bits */
  270.         data[1] = 3;
  271.         break;
  272.     case 's':
  273.         data[0] = 7;    /* Data bits */
  274.         data[1] = 4;
  275.         break;
  276.     default :
  277.         data[0] = 8;    /* Data bits */
  278.         data[1] = 0;    /* No parity */
  279.     }
  280.     switch (stop) {
  281.         case 2:
  282.             data[2] = 2;    /* Two stop bits */
  283.             break;
  284.         case 1:
  285.             data[2] = 0;    /* One stop bit */
  286.             break;
  287.         default: ;      /* No change */
  288.     }
  289.     /* Set line */
  290.     if (DosDevIOCtl(NULL,data,ASYNC_SETLINECTRL,1,ttyfd)) return(-1);
  291.     return(0);
  292. }
  293.  
  294. /*  T T I S C O M  --  Is the given handle an open COM port? */
  295.  
  296. ttiscom(HFILE f) {
  297.     ttclos();
  298.     ttyfd = f;
  299.     /* Read DCB */
  300.     if (DosDevIOCtl(&ttydcb,NULL,ASYNC_GETDCBINFO,1,ttyfd)) {
  301.         ttyfd = -1;         /* Not a serial port */
  302.         return( 0 /* bad */ );
  303.     }
  304.     return( 1 /* good */ );
  305. }
  306.  
  307. /*  T T C L O S  --  Close the TTY.  */
  308.  
  309. ttclos() {
  310.     if (ttyfd == -1) return(0);     /* Wasn't open. */
  311.     DosClose(ttyfd);
  312.     ttyfd = -1;
  313.     return(0);
  314. }
  315.  
  316. /*  T T S P E E D  --  return speed of tt line, or of default line */
  317.  
  318. ttspeed() {
  319.     char df;
  320.     int sp=-1;
  321.     
  322.     df = (ttyfd == -1);
  323.     if (df) if (ttopen(dftty,&sp,0)) return(-1);
  324.     if (DosDevIOCtl(&sp,NULL,ASYNC_GETBAUDRATE,1,ttyfd)) sp=-1;
  325.     return(sp);
  326. }
  327.  
  328. int ttgspd()
  329.     {
  330.     return(ttspeed());
  331.     }
  332.  
  333. /*  T T H A N G -- Hangup phone line */
  334.  
  335. tthang() {
  336.     char parms[2];
  337.     USHORT data;
  338.     
  339.     if (ttyfd == -1) return(0);     /* Not open, so must be hung up */
  340.     parms[0] = 0x00;
  341.     parms[1] = 0xFE;            /* Drop DTR */
  342.     return(DosDevIOCtl(&data,parms,ASYNC_SETMODEMCTRL,1,ttyfd));
  343. }
  344.  
  345.  
  346. /*  T T R E S  --  Restore terminal to "normal" mode.  */
  347.  
  348. ttres() {               /* Restore the tty to normal. */
  349.     if (ttyfd == -1) return(-1);    /* Not open */
  350.     return(0);
  351. }
  352.  
  353. #define DIALING 4       /* for ttpkt parameter */
  354. #define CONNECT 5
  355.  
  356. /*  T T P K T  --  Condition the communication line for packets. */
  357. /*      or for modem dialing */
  358.  
  359. /*  If called with speed > -1, also set the speed.  */
  360. /*  Returns 0 on success, -1 on failure.  */
  361.  
  362. ttpkt(speed,flow,parity) int speed, flow, parity; {
  363.     int s;
  364.     USHORT x;
  365.  
  366.     if (ttyfd < 0) return(-1);      /* Not open. */
  367.  
  368.     if (speed > -1) {
  369.     if ((x = ttsspd(speed))<0) return(-1);      /* Check the speed */
  370.     /* Set the speed */
  371.     if (DosDevIOCtl(NULL,&x,ASYNC_SETBAUDRATE,1,ttyfd)) return(-1);
  372.     }
  373.  
  374.     ttprty = parity;
  375.     if (ttsettings(ttprty,0)) return(-1);
  376.     debug(F101,"ttpkt setting ttprty","",ttprty);
  377.  
  378.     if (flow == DIALING) {      /* Ignore DCD */
  379.     debug(F100,"ttpkt DIALING","",0);
  380.     /* Driver default is to do so */
  381.     } else
  382.     if (flow == CONNECT) {      /* Pay attention to DCD */
  383.     debug(F100,"ttpkt CONNECT","",0);
  384.     /* We're warned against doing so, for some reason, so no action */
  385.     } else
  386.     return(os2setflow(flow));
  387. }
  388.  
  389.  
  390. /*  T T V T -- Condition communication line for use as virtual terminal  */
  391.  
  392. ttvt(speed,flow) int speed, flow; {
  393.     USHORT x;
  394.  
  395.     if (ttyfd < 0) return(-1);      /* Not open. */
  396.  
  397.     if (speed > -1) {
  398.     if ((x = ttsspd(speed))<0) return(-1);      /* Check the speed */
  399.     /* Set the speed */
  400.     if (DosDevIOCtl(NULL,&x,ASYNC_SETBAUDRATE,1,ttyfd)) return(-1);
  401.     }
  402.     ttprty = parity;
  403.     if (ttsettings(ttprty,0)) return(-1);
  404.  
  405.     return(os2setflow(flow));
  406. }
  407.  
  408.  
  409. /*  O S 2 S E T F L O W -- set flow state of tty */
  410.  
  411. /*  If flow = 0 turn receive flow XON/XOFF control off, otherwise turn it on.
  412.     If successful, return 0, otherwise return -1.  */
  413.  
  414. os2setflow(flow) 
  415.     int flow; 
  416.     {
  417.     extern HFILE ttyfd;
  418.     extern DCBINFO ttydcb;
  419.     extern int odsr;    /* Hardware handshaking controls */
  420.     extern int idsr;
  421.     extern int octs;
  422.  
  423.     /* Get the current settings */
  424.     if (DosDevIOCtl(&ttydcb,NULL,ASYNC_GETDCBINFO,1,ttyfd)) 
  425.         return(-1);
  426.     
  427.     ttydcb.fbFlowReplace &= 0xFD;           /* Set RX flow off */
  428.     if (flow != 0)                          
  429.         ttydcb.fbFlowReplace |= 0x02;       /* Set RX flow on */
  430.         
  431.     /* Set the DSR/CSR handshaking. Set the bits first */
  432.     ttydcb.fbCtlHndShake |= 
  433.         (MODE_DSR_HANDSHAKE | MODE_DSR_SENSITIVITY | MODE_CTS_HANDSHAKE);
  434.  
  435.     /* now clear them if necessary */
  436.     ttydcb.fbCtlHndShake ^= ( (odsr!=0) ? 0 : MODE_DSR_HANDSHAKE);
  437.     ttydcb.fbCtlHndShake ^= ( (idsr!=0) ? 0 : MODE_DSR_SENSITIVITY);
  438.     ttydcb.fbCtlHndShake ^= ( (octs!=0) ? 0 : MODE_CTS_HANDSHAKE);
  439.  
  440.     /* Set DCB */
  441.     if (DosDevIOCtl(NULL,&ttydcb,ASYNC_SETDCBINFO,1,ttyfd)) return(-1);
  442.  
  443.     return(0);
  444. }
  445.  
  446.  
  447. /*  T T S S P D  --  Return the speed if OK, otherwise -1 */
  448.  
  449. ttsspd(speed) int speed; {
  450.     int s, spdok;
  451.  
  452.     if (speed < 0) return(-1);
  453.     spdok = 1;          /* Assume arg ok */
  454.     switch (speed) {
  455.         case 110:
  456.         case 150:
  457.         case 300:
  458.         case 600:
  459.         case 1200:
  460.         case 2400:
  461.         case 4800:
  462.         case 9600:
  463.         case 19200: break;
  464.         default:
  465.             spdok = 0;
  466.         fprintf(stderr,"Unsupported line speed - %d\n",speed);
  467.         fprintf(stderr,"Current speed not changed\n");
  468.         break;
  469.     }
  470.     if (spdok) return(speed); else return(-1);
  471.  }
  472.  
  473.  
  474. /*  T T F L U I  --  Flush tty input buffer */
  475.  
  476. ttflui() {
  477.     char parm=0;
  478.     long int data;
  479.     int i;
  480.  
  481.     rdchbuf.index = rdchbuf.length = 0;     /* Flush internal buffer */
  482.     DosDevIOCtl(&data,&parm,0x0001,11,ttyfd);   /* Flush driver buffer */
  483.     return(0);
  484. }
  485.  
  486.  
  487. /*  T T C H K  --  Tell how many characters are waiting in tty input buffer  */
  488.  
  489. ttchk() {
  490.     USHORT data[2];
  491.     if(DosDevIOCtl(data,NULL,ASYNC_GETINQUECOUNT,1,ttyfd)) return(0);
  492.     else return((rdchbuf.length-rdchbuf.index)+data[0]);
  493. }
  494.  
  495.  
  496. /*  T T X I N  --  Get n characters from tty input buffer  */
  497.  
  498. /*  Returns number of characters actually gotten, or -1 on failure  */
  499.  
  500. /*  Intended for use only when it is known that n characters are actually */
  501. /*  available in the input buffer.  */
  502.  
  503. ttxin(n,buf) int n; char *buf; {
  504.     int i, j;
  505.     
  506.     if (ttyfd < 0) return(-1);      /* Not open. */
  507.     i = 0;
  508.     while (i < n) {
  509.         if ((j = ttinc(0)) < 0) break;
  510.         buf[i++] = j;
  511.     }
  512.     return(i);
  513. }
  514.  
  515. /*  T T O L  --  Similar to "ttinl", but for writing.  */
  516.  
  517. ttol(s,n) int n; char *s; {
  518.     USHORT i;
  519.     CHAR pkt[1100];         /* So big that we needn't check */
  520.     
  521.     if (ttyfd < 0) return(-1);      /* Not open. */
  522.  
  523.     if (!parity) 
  524.         {
  525.         if(DosWrite(ttyfd,s,n,&i)) 
  526.             return(-1);
  527.         else 
  528.             return(i);
  529.         } 
  530.     else 
  531.         {
  532.         for (i=0;i<n;i++) 
  533.             pkt[i]=dopar(s[i]);
  534.         if (DosWrite(ttyfd,pkt,n,&i)) 
  535.             return(-1);
  536.         else 
  537.             return(i);
  538.         }
  539. }
  540.  
  541.  
  542. /*  T T O C  --  Output a character to the communication line  */
  543.  
  544. ttoc(c) char c; {
  545.     USHORT i;
  546.     CHAR ch = dopar(c);
  547.     
  548.     if (ttyfd < 0) return(-1);      /* Not open. */
  549.     if(DosWrite(ttyfd,&ch,1,&i)) 
  550.         {
  551.         bleep();
  552.         return(-1);
  553.         }
  554.     else 
  555.         return(i);
  556. }
  557.  
  558.  
  559. /*  T T O C I  --  Output a character to the communication line immediately */
  560.  
  561. ttoci(c) char c; {
  562.     USHORT i;
  563.     CHAR ch = dopar(c);
  564.     
  565.     if (ttyfd < 0) return(-1);      /* Not open. */
  566.     if(DosDevIOCtl(NULL,&ch,ASYNC_TRANSMITIMM,1,ttyfd)) return(-1);
  567.     else return(1);
  568. }
  569.  
  570.  
  571. /*  T T I N L  --  Read a record (up to break character) from comm line.  */
  572. /*
  573.   If no break character encountered within "max", return "max" characters,
  574.   with disposition of any remaining characters undefined.  Otherwise, return
  575.   the characters that were read, including the break character, in "dest" and
  576.   the number of characters read as the value of the function, or 0 upon end of
  577.   file, or -1 if an error occurred.  Times out & returns error if not completed
  578.   within "timo" seconds.
  579. */
  580. ttinl(dest,max,timo,eol) int max,timo; CHAR *dest, eol; {
  581.     int x = 0, c, i, m;
  582.  
  583.     if (ttyfd < 0) return(-1);      /* Not open. */
  584.     *dest = '\0';           /* Clear destination buffer */
  585.     i = 0;              /* Next char to process */
  586.     while (1) {
  587.     if ((c = ttinc(timo)) == -1) {
  588.         x = -1;
  589.         break;
  590.     }
  591.         dest[i] = c;            /* Got one. */
  592.     if (dest[i] == eol) {
  593.         dest[++i] = '\0';
  594.         return(i);
  595.     }
  596.     if (i++ > max) {
  597.         debug(F101,"ttinl buffer overflow","",i);
  598. //        debug(F101,"ttinl buffer overflow","",j);
  599.         x = -1;
  600.         break;
  601.     }
  602.     }
  603.     debug(F100,"ttinl timout","",0);    /* Get here on timeout. */
  604.     debug(F111," with",dest,i);
  605.     return(x);              /* and return error code. */
  606. }
  607.  
  608.  
  609. /*  T T I N C --  Read a character from the communication line  */
  610.  
  611. /* Note that the parameter is the time to wait in *centiseconds*, not secs. */
  612. /* The time should be in secs for consitency with the other modules in      */
  613. /* kermit.  To retain the option of using times of less than 1s a negative  */ 
  614. /* parameter is interpreted as meaning multiples of 0.01s                  */
  615. ttinc(timo) int timo; {
  616.     int m, i;
  617.     char ch = 0;
  618.  
  619.     m = (ttprty) ? 0177 : 0377;     /* Parity stripping mask. */
  620.     if (ttyfd < 0) return(-1);      /* Not open. */
  621.     if (timo == 0) 
  622.         {                               /* Untimed. */
  623.         ttydcb.usReadTimeout = 9;       /* Test every  0.1s per call */
  624.         if (DosDevIOCtl(NULL,&ttydcb,ASYNC_SETDCBINFO,1,ttyfd)) return(-1);
  625.         do i = rdch(); while (i < 0);   /* Wait for a character. */
  626.         return(i & m);
  627.         } 
  628.     else if(timo<0)
  629.         {
  630.         timo= (timo*(-1))-1;            /* Convert time from cseconds */
  631.         }                               /* OS/2 units */
  632.     else 
  633.         {
  634.         timo = (timo*100)-1;        /* Convert timo from seconds */
  635.         }                           /* to OS/2 units */
  636.  
  637.     if (timo != ttydcb.usReadTimeout+1) 
  638.         { /* Set timeout value */
  639.         ttydcb.usReadTimeout = timo;
  640.         if (DosDevIOCtl(NULL,&ttydcb,ASYNC_SETDCBINFO,1,ttyfd)) return(-1);
  641.         }
  642.  
  643.     i = rdch();
  644.     if (i < 0) 
  645.         return(-1);
  646.     else 
  647.         return(i & m);
  648.     }
  649.  
  650. /*  RDCH -- Read characters from the serial port, maintaining an internal
  651.             buffer of characters for the sake of efficiency. */
  652. static rdch() {
  653.  
  654.     if (rdchbuf.index == rdchbuf.length) {
  655.         rdchbuf.index = 0;
  656.         if (DosRead(ttyfd,rdchbuf.buffer,
  657.                 sizeof(rdchbuf.buffer),&rdchbuf.length)) {
  658.             rdchbuf.length = 0;
  659.                 return(-1);
  660.             }
  661.         }
  662.     return( (rdchbuf.index < rdchbuf.length) ? rdchbuf.buffer[rdchbuf.index++]
  663.                          : -1 );
  664. }    
  665.  
  666.  
  667. /*  T T S N D B  --  Send a BREAK signal  */
  668.  
  669. ttsndb() {
  670.     USHORT i;
  671.     
  672.     DosDevIOCtl(&i,NULL,ASYNC_SETBREAKON,1,ttyfd);  /* Break on */
  673.     DosSleep(1000L);                    /* ZZZzzz */
  674.     DosDevIOCtl(&i,NULL,ASYNC_SETBREAKOFF,1,ttyfd); /* Break off */
  675. }
  676.  
  677. /*  S L E E P  --  Emulate the Unix sleep function  */
  678.  
  679. sleep(t) unsigned t; {
  680.     ULONG lm = t*1000L;
  681.  
  682.     DosSleep(lm);
  683. }
  684.  
  685.  
  686. /*  M S L E E P  --  Millisecond version of sleep().  */
  687.  
  688. /* Intended only for small intervals.  For big ones, just use sleep(). */
  689.  
  690. msleep(m) int m; {
  691.     ULONG lm = m;
  692.     
  693.     DosSleep(lm);
  694. }
  695.  
  696.  
  697. /*  R T I M E R --  Reset elapsed time counter  */
  698.  
  699. rtimer() {
  700.     tcount = time( (long *) 0 );
  701. }
  702.  
  703.  
  704. /*  G T I M E R --  Get current value of elapsed time counter in seconds  */
  705.  
  706. gtimer() {
  707.     int x;
  708.     x = (int) (time( (long *) 0 ) - tcount);
  709.     rtimer();
  710.     return( (x < 0) ? 0 : x );
  711. }
  712.  
  713.  
  714. /*  Z T I M E  --  Return date/time string  */
  715.  
  716. ztime(s) char **s; {
  717.     long clock_storage;
  718.  
  719.     clock_storage = time( (long *) 0 );
  720.     *s = ctime( &clock_storage );
  721. }
  722.  
  723. /*  C O N O C  --  Output a character to the console terminal  */
  724.  
  725. conoc(c) char c; {
  726. //    write(1,&c,1);
  727.     AVIOwrttyc(&c,1);
  728. }
  729.  
  730.  
  731. /*  C O N X O  --  Write x characters to the console terminal  */
  732.  
  733. conxo(x,s) char *s; int x; {
  734. //    write(1,s,x);
  735.       AVIOwrttyc(s,x);
  736. }
  737.  
  738.  
  739. /*  C O N O L  --  Write a NULL termintated line to the console terminal  */
  740.  
  741. conol(s) char *s; {
  742.     int len;
  743.     len = strlen(s);
  744. //    write(1,s,len);
  745.     AVIOwrttyc(s,len);
  746. }
  747.  
  748.  
  749. /*  C O N O L A  --  Write an array of lines to the console terminal */
  750.  
  751. conola(s) char *s[]; {
  752.     int i;
  753.     for (i=0 ; *s[i] ; i++) conol(s[i]);
  754. }
  755.  
  756.  
  757. /*  C O N O L L  --  Output a string followed by CRLF  */
  758.  
  759. conoll(s) char *s; {
  760.     conol(s);
  761. //    write(1,"\r\n",2);
  762.     conol("\r\n");    
  763. }
  764.  
  765.  
  766. /*  C O N C H K  --  Return how many characters available at console  */
  767.  
  768. conchk() {
  769.     extern next_put_pos;
  770.     extern next_get_pos;
  771.     int waiting;
  772.  
  773.     DosEnterCritSec();
  774.     if(next_put_pos< next_get_pos)
  775.         {
  776.         waiting = 128-next_get_pos+next_put_pos;
  777.         }
  778.     else
  779.         {
  780.         waiting = next_put_pos - next_get_pos;
  781.         }
  782.     
  783.     DosExitCritSec();
  784.     return(waiting);
  785.  
  786. }
  787.  
  788.  
  789. /*  C O N I N C  --  Get a character from the console  */
  790.  
  791. coninc(timo) int timo; {
  792.     /* returns -1 if no character received within timo secs */
  793.     int c;
  794.  
  795.     if(timo>0)
  796.         {
  797.         c = buff_tgetch((LONG)(timo*1000));   /* Return after waiting */
  798.         if(c==-1)                             /* timo seconds */
  799.             return(c);
  800.         }
  801.     else
  802.         c = buff_getch();              /* Indefinite wait */
  803.  
  804.  
  805.     if((c&0xFF)==0)
  806.         {
  807.         c = c>>8;                      /* Command line needs backspace to be */
  808.         if(c==VK_BACKSPACE)            /* to be 8, VMS needs backspace to be */
  809.             c=8;                       /* 127, Unix needs to have both!      */
  810.         }
  811.     else
  812.         c &= 0xFF;
  813.  
  814.     return(c&0xFF);
  815. }
  816.  
  817.  
  818. conraw() {
  819.     KBDINFO k;
  820.     
  821.     k.cb = 10;
  822.     k.fsMask = 0x06;    /* Set raw mode */
  823.     k.chTurnAround = 0;
  824.     k.fsInterim = 0;
  825.     k.fsState = 0;
  826.     return(0);  /* Need to find out how this is done */
  827. //    return(KbdSetStatus(&k,0));
  828. }
  829.  
  830. concooked() {
  831.     KBDINFO k;
  832.     
  833.     k.cb = 10;
  834.     k.fsMask = 0x09;    /* Set cooked mode */
  835.     k.chTurnAround = 0;
  836.     k.fsInterim = 0;
  837.     k.fsState = 0;
  838.     return(0);      /* Need to find out if this is possible under PM */
  839. //    return(KbdSetStatus(&k,0));
  840. }
  841.  
  842. /*  C O N G M  -- Get console terminal mode. */
  843.  
  844. congm() {}
  845.  
  846.  
  847. /*  C O N C B  -- Put console into single char mode with no echo. */
  848.  
  849. concb(esc) char esc; {}
  850.  
  851.  
  852. /*  C O N R E S -- Restore console to congm mode. */
  853.  
  854. conres() {}
  855.  
  856.  
  857. /*  C O N I N T -- Enable console terminal interrupts. */
  858.  
  859. conint(f) int (*f)(); {}
  860.  
  861.  
  862. /*  C O N N O I -- No console interrupts. */
  863.  
  864. connoi() {}
  865.  
  866. /*****************************************************************************/
  867.  
  868. /*
  869.   The following code tries to implement the Unix 'alarm' function under OS/2.
  870. */
  871.  
  872. #include <signal.h>
  873. #include <malloc.h>
  874.  
  875. #define THRDSTKSIZ  2048
  876. static  char *alarmstack;
  877. static  ULONG alarmtime;
  878. static  ULONG tsem = 0, hold = 0;
  879. static  int pid;
  880. static  int initialised = 0;
  881.  
  882. VOID FAR alarmthread(void) 
  883.     {
  884.     while(1) 
  885.         {
  886.         DosSemSetWait(&hold,-1L);   /* Wait until we're told to go */
  887.         if ( DosSemSetWait(&tsem,alarmtime*1000L) == ERROR_SEM_TIMEOUT ) 
  888.             {
  889. //            raise(SIGUSR1);
  890. //            if(DosFlagProcess(pid,1,0,0))
  891.               if(DosFlagProcess(pid,FLGP_PID,PFLG_A,0))
  892.                 printf("Failed to raise timeout signal!\n");
  893.             }
  894.         }
  895.     }
  896.  
  897. alarminit() {
  898.     USHORT threadid;
  899.     pid = getpid();
  900.     if ( (alarmstack=malloc(THRDSTKSIZ)) == NULL) {
  901.         printf("Not enough space for alarm thread stack\n");
  902.         doexit(BAD_EXIT);
  903.     }
  904.  
  905.     if((threadid=_beginthread(alarmthread,alarmstack,THRDSTKSIZ,NULL))==-1)
  906.         {
  907.         printf("Can't create alarm thread\n");
  908.         doexit(BAD_EXIT);
  909.         }
  910.     while (!hold) DosSleep(300L);   /* Wait for thread to start */
  911.     initialised = 1;
  912. }
  913.  
  914. /*  A L A R M  --  Issue a signal after a specified time */
  915.  
  916. /* Call with t=0 to cancel an alarm.  t>0 is the time in seconds after which
  917.    a signal will be generated.  The signal will be a User Flag A signal, which
  918.    thread 1 must acknowledge with a call to alarmack().  The time t can be
  919.    up to 64k seconds.
  920.    */
  921. void alarm(t) unsigned t; {
  922.     if (!initialised) alarminit();
  923.     alarmtime = t;          /* In seconds */
  924.     DosSemClear(&tsem);     /* stopping an existing alarm */
  925.     if (t>0) DosSemClear(&hold);    /* starting a new one */
  926. }
  927.  
  928. /*  A L A R M A C K  --  Acknowledge alarm call received */
  929.  
  930. alarmack() {
  931.     signal(SIGUSR1,SIG_ACK);
  932. }
  933.  
  934. zstime(char * f, struct zattr *yy)
  935.     {
  936.     return(0);
  937.     }
  938.     
  939. int os2_set_hand(y)
  940.     int y;
  941.     {     
  942.     extern int com_odsr;
  943.     extern int com_idsr;
  944.     extern int com_octs;
  945.     
  946.     switch(y)
  947.         {
  948.         case ODSR:
  949.             return( seton(&odsr) );
  950.         case IDSR:
  951.             return( seton(&idsr) );
  952.         case OCTS:
  953.             return( seton(&octs) );
  954.         default:
  955.             return(-2);
  956.         }
  957.     }
  958.     
  959. int ttsetspeed(int speed)
  960.     {
  961.     extern HFILE ttyfd;
  962.     USHORT x;
  963.  
  964.     /* Check it's a valid speed */
  965.     if ((x = ttsspd(speed))<0) 
  966.         return(-1);
  967.  
  968.     /* Set it */
  969.     if (DosDevIOCtl(NULL,&x,ASYNC_SETBAUDRATE,1,ttyfd)) 
  970.         return(-1);
  971.  
  972.     return(0);
  973.     }
  974.  
  975. int ttnewport(s)
  976. char * s;       /* The name of the new port to open */
  977.     {
  978.     extern char ttname[];
  979.     extern char * dftty;        /* Default line name */
  980.     extern int dfloc;           /* ? */
  981.     extern int mdmtyp;          /* Modem type */
  982.     extern int tvtflg;          /* ? */
  983.     extern int success;    
  984.     extern int local;
  985.     extern int network;
  986.     extern int speed;
  987.     extern int parity;
  988.     extern int stop;
  989.     extern int flow;
  990.  
  991.     int x;
  992.     int y;
  993.  
  994.     x = strcmp(s,dftty) ? -1 : dfloc; /* Maybe let ttopen figure it out */
  995.     y = mdmtyp;
  996.  
  997.     ttclos();               /* close old line, if any was open */
  998.     tvtflg = 0;
  999.     if (ttopen(s,&x,y) < 0 ) 
  1000.         {                   /* Can we open the new line? */
  1001.         local = dfloc;      /* Go back to normal */
  1002.         network = 0;
  1003.         return(success = 0);/* and return failure */
  1004.         }
  1005.  
  1006.     if (x > -1) 
  1007.         local = x;          /* Opened ok, set local/remote. */
  1008.  
  1009.     network = (y < 0);          /* Remember connection type. */
  1010.     strcpy(ttname,s);           /* Copy name into real place. */
  1011.  
  1012.     /* Set the parity */
  1013.     ttsettings(parity,0);
  1014.     
  1015.     /* Set the speed */
  1016.     ttsetspeed(speed);
  1017.  
  1018.     /* Set the flow*/
  1019.     os2setflow(flow);
  1020.  
  1021.     debug(F111,"set line ",ttname,local);
  1022.     return(success = 1);
  1023.     }
  1024.