home *** CD-ROM | disk | FTP | other *** search
/ kermit.columbia.edu / kermit.columbia.edu.tar / kermit.columbia.edu / wkermit / lcktio.c < prev    next >
C/C++ Source or Header  |  1985-11-10  |  15KB  |  587 lines

  1.  
  2. /*  L C K T I O    module   */
  3.  
  4. char *ckxv = "tty I/O, 4LC (001), 01 Jul 85";
  5.  
  6. /* C-Kermit interrupt, terminal control & i/o functions for PC-DOS systems */
  7.  
  8. /* F. da Cruz, Columbia University Center for Computing Activities */
  9. /* Modified for use with PC-DOS by: Jan A. van der Eijk, NUS Corp., July 1985 */
  10.  
  11. /*
  12.  Copyright (C) 1985, Trustees of Columbia University in the City of New York.
  13.  Permission is granted to any individual or institution to use, copy, or
  14.  redistribute this software so long as it is not sold for profit, provided this
  15.  copyright notice is retained.
  16. */
  17. char *ckxsys = " PC-DOS > 2.0";
  18.  
  19. /*
  20.  Variables available to outside world:
  21.  
  22.    dftty  -- Pointer to default tty name string, like "/dev/tty".
  23.    dfloc  -- 0 if dftty is console, 1 if external line.
  24.    dfprty -- Default parity
  25.    dfflow -- Default flow control
  26.    ckxech -- Flag for who echoes console typein:
  27.      1 - The program (system echo is turned off)
  28.      0 - The system (or front end, or terminal).
  29.    functions that want to do their own echoing should check this flag
  30.    before doing so.
  31.  
  32.  Functions for assigned communication line (either external or console tty):
  33.  
  34.    ttopen(ttname,local,mdmtyp) -- Open the named tty for exclusive access.
  35.    ttclos()           -- Close & reset the tty, releasing any access lock.
  36.    ttpkt(speed,flow)       -- Put the tty in packet mode and set the speed.
  37.    ttvt(speed,flow)       -- Put the tty in virtual terminal mode.
  38.                 or in DIALING or CONNECTED modem control state.
  39.    ttinl(dest,max,timo,eol)-- Timed read line from the tty.
  40.  
  41.    ttinc(timo)           -- Timed read character from tty.
  42.    ttchk()           -- See how many characters in tty input buffer.
  43.    ttol(string,length)       -- Write a string to the tty.
  44.    ttoc(c)           -- Write a character to the tty.
  45.    ttflui()           -- Flush tty input buffer.
  46.  
  47. */
  48.  
  49. /*
  50. Functions for console terminal:
  51.  
  52.    conoc(c)  -- Unbuffered output, one character to console.
  53.    conol(s)  -- Unbuffered output, null-terminated string to the console.
  54.    conola(s) -- Unbuffered output, array of strings to the console.
  55.    conxo(n,s) -- Unbuffered output, n characters to the console.
  56.    conchk()  -- Check if characters available at console (bsd 4.2).
  57.         Check if escape char (^\) typed at console (System III/V).
  58.    coninc(timo)  -- Timed get a character from the console.
  59.  
  60. Time functions
  61.  
  62.    msleep(m) -- Millisecond sleep
  63.    ztime(&s) -- Return pointer to date/time string
  64. */
  65.  
  66. /* Includes */
  67.  
  68. #include "stdios.h"                      /* Unix Standard i/o */
  69. #include <fcntl.h>
  70. #include "lckdeb.h"                     /* Formats for debug() */
  71. #include "asic.h"                       /* Greenleaf header */
  72. #include "timedate.h"                   /* Greenleaf header */
  73. #define XONCODE 0
  74. #define XOFFCODE 1
  75. #define NULCODE 2
  76.  
  77. struct TIMEDATE *sgettime();
  78.  
  79.  
  80. long int strtim;
  81.  
  82. /* Declarations */
  83.  
  84. /* dftty is the device name of the default device for file transfer */
  85. /* dfloc is 0 if dftty is the user's console terminal, 1 if an external line */
  86.  
  87.     char *dftty = "COM1";
  88.     int dfloc = 1;
  89.     int dfprty = 0;            /* Parity (0 = none) */
  90.     int dfflow = 1;            /* Xon/Xoff flow control */
  91.  
  92. int ckxech = 0; /* 0 if system normally echoes console characters, else 1 */
  93.  
  94. /* Declarations of variables global within this module */
  95.  
  96. static int xlocal = 0,            /* Flag for tty local or remote */
  97.     ttyfd = -1;             /* TTY file descriptor */
  98. static char escchr;            /* Escape or attn character */
  99.  
  100. static int conesc = 0;            /* set to 1 if esc char (^\) typed */
  101.  
  102.  
  103. char rbuf[4000],tbuf[4000];           /* receive and transmit buffer pointer */
  104. int tlen,rlen;                   /* length of Xmit & Recv buffers */
  105.  
  106.  
  107.  
  108. /*  C O N O C  --  Output a character to the console terminal  */
  109.  
  110. conoc(c) char c; {
  111.        write(1,&c,1);
  112. }
  113.  
  114. /*  C O N X O  --  Write x characters to the console terminal  */
  115.  
  116. conxo(x,s) char *s; int x; {
  117.      write(1,s,x);
  118. }
  119.  
  120. /*  C O N O L  --  Write a line to the console terminal  */
  121.  
  122. conol(s) char *s; {
  123.     int len;
  124.     len = strlen(s);
  125.     write(1,s,len);
  126. }
  127.  
  128. /*  C O N O L A  --  Write an array of lines to the console terminal */
  129.  
  130. conola(s) char *s[]; {
  131.     int i;
  132.     for (i=0 ; *s[i] ; i++) conol(s[i]);
  133. }
  134.  
  135. /*  C O N O L L  --  Output a string followed by CRLF  */
  136.  
  137. conoll(s) char *s; {
  138.     conol(s);
  139.     write(1,"\r\n",2);
  140. }
  141.  
  142. /*  C O N C H K  -- Check to see if user did hit keyboard  */
  143. /*            Return 1 if keyboard has been hit */
  144.  
  145. conchk() {
  146.  
  147.      if (asikbhit()) return(1);    /* Greenleaf function to test keyboard hit */
  148.      return(0);
  149. }
  150.  
  151. /*  C O N I N C  --  Get a character from the console  */
  152.  
  153. /*   argument;    timo = number of seconds to wait for keyboard input */
  154. /*   return -1 if no keyboard input                    */
  155.  
  156. coninc(timo) int timo; {
  157.     int n, time;
  158.  
  159.       time = 0;
  160.       while ( !conchk() ) {
  161.        if ( time++ > (timo*18 )) return(-1);
  162.        timer(1);               /* wait for 1 clock tick */
  163.     }                   /* Greenleaf function timer() */
  164.  
  165.       n = getch();               /* Read a character. */
  166.       if (n > 0 ) return(n);    /* Return the char if read */
  167. }
  168.  
  169.  
  170.  
  171. /*  T T O P E N  --  Open a tty for exclusive access.  */
  172.  
  173. /*  Returns 0 on success, -1 on failure.  */
  174.  
  175. ttopen(ttname,lcl,modem) char *ttname; int lcl, modem; {
  176.     int status;
  177.     if (ttyfd > -1) return(0);        /* If already open, ignore this call */
  178.     xlocal = lcl;            /* Make available to other functions */
  179.     ttyfd = -1;
  180.     if (strcmp(ttname,"COM1") == 0) ttyfd = 0;        /* Check for valid name */
  181.     else if (strcmp(ttname,"COM2") == 0) ttyfd = 1;
  182.     else return(-1);
  183.  
  184.     rlen = 4000;           /* Allocate space for interrupt driven */
  185.     tlen = 4000;           /* RS 232 I/O */
  186.  
  187.     status=asisetup(ttyfd,ASINOUT,BINARYNONE,rbuf,(rlen-2),tbuf,(tlen-2));
  188.     if (status < 0)
  189.        {
  190.      ttyfd = -1;
  191.      return(-1);    /* Setup buffers, return -1 if error */
  192.        }
  193.  
  194.     asdtr(ttyfd,1); asrts(ttyfd,1);   /* Greenleaf specific function to */
  195.     status=asistart(ttyfd,ASINOUT);   /* Setup interrupt handlers */
  196.     if (status < 0)
  197.        {
  198.          ttyfd = -1;
  199.          return(-1);       /* return -1 if any error */
  200.     }
  201.     status= asixrst(ttyfd);
  202.     if (status < 0) return(-1);
  203.     status=asiclear(ttyfd,ASIN);
  204.     if (status < 0) return(-1);
  205.  
  206.     return(0);
  207. }
  208. /*  T T C L O S  --  Close the TTY */
  209.  
  210. ttclos() {
  211.  
  212.     if (ttyfd < 0) return;        /* Wasn't open. */
  213.  
  214.     asiquit(ttyfd);            /* Reset modes, turn off interrupts. */
  215.                     /* Using Greenleaf function */
  216.  
  217.     ttyfd = -1;             /* Mark it as closed. */
  218. }
  219.  
  220. /*  T T O L  --  Similar to "ttinl", but for writing.  */
  221. /*         returns number of characters writen to Com port */
  222.  
  223. ttol(s,n) int n; char *s; {
  224.     int x;
  225.  
  226.     if (ttyfd < 0) return(-1);               /* Not open, return -1. */
  227.  
  228.     ttflow();      /* check for XON */
  229.     if ((x = asiputb(ttyfd,s,n)) >= 0 ) x = n; /* All characters writen ?? */
  230.  
  231.     debug(F111,"ttol",s,n);
  232.     if (x < 0) debug(F101,"ttol failed","",x);
  233.     return(x);
  234. }
  235.  
  236.  
  237. /*  T T O C  --  Output a character to the communication line  */
  238. /*         Returns -1 if an error occured */
  239.  
  240. ttoc(c) char c; {
  241.  
  242.     if (ttyfd < 0) return(-1);        /* Not open. */
  243.     ttflow();
  244.     return(asiputc(ttyfd,c));
  245.  
  246. }
  247. /*  T T I N C --  Read a character from the communication line    */
  248. /*          return the character if possible otherwise -1 */
  249.  
  250. /*  Argument     timo, timout  in seconds */
  251.  
  252. ttinc(timo) int timo; {
  253.     extern long int strtim;
  254.     long int totsec();
  255.  
  256.     int n,time;
  257.  
  258.     n = -1;
  259.     time = 0;
  260.     if (ttyfd < 0) return(-1);        /* Not open. */
  261.     if (timo <= 0) {            /* Untimed. */
  262.     while (carrier()) {
  263.         if( (n = ttin())>= 0) break ; /* Wait for a character. */
  264.     }
  265.     }  else {
  266.       if ((n = ttin()) < 0)  {
  267.          strtim = totsec();
  268.          while(carrier())  {
  269.         if( (n = ttin()) >= 0) break ; /* Wait for a character. */
  270.         else if (toolong(timo))  return(-1); /* Timeout return -1 */
  271.           }
  272.       }
  273.     }
  274.    return(n);
  275. }
  276.  
  277. /*  T T I N L  --  Read a record (up to break character) from comm line.  */
  278. /*
  279.   If no break character encountered within "max", return "max" characters,
  280.   with disposition of any remaining characters undefined.  Otherwise, return
  281.   the characters that were read, including the break character, in "dest" and
  282.   the number of characters read as the value of function, or 0 upon end of
  283.   file, or -1 if an error occurred.  Times out & returns error if not completed
  284.   within "timo" sconds.
  285. */
  286.  
  287. ttinl(dest,maxnum,timo,eol)
  288.  int maxnum,timo,eol;
  289.  char *dest;
  290.  {
  291.     extern long int strtim;
  292.     long int totsec();
  293.  
  294.     int i, y, c;
  295.     int time;
  296.     time = 0;
  297.  
  298.     if (ttyfd < 0) return(-1);        /* Not open. */
  299.     if (timo <= 0) {            /* Untimed. */
  300.        for ( i = c = 0; (i < maxnum) && (c != eol) ; i++)  {
  301.         c = ttin();
  302.         if ( c > -1 ) dest[i] = c;            /* Try to read. */
  303.         else dest[i] = 0;
  304.        }
  305.        return(i);
  306.     } else {
  307.        strtim = totsec();            /* Intialize timer */
  308.        for ( i = c = 0; (i < maxnum) && (c !=eol) ; i++) {
  309.          while ( (c = ttin()) < 0 )  {    /* Try to read */
  310.                         /* Timed out yet */
  311.          if(toolong(timo) || !carrier()) return(i);
  312.          }
  313.          dest[i] = c;           /* Store the character */
  314.        }
  315.     }
  316.     return(i);                   /* Return the count. */
  317. }
  318.  
  319. /* TTPKT -- Condition communication line for packect mode */
  320. /*
  321.        arguments -  speed, communications baud rate
  322.             flow,  flow control used
  323. */
  324.  
  325. ttpkt (speed,flow) int speed, flow; {
  326.  
  327.       int ispeed,iflow;
  328.  
  329.       ispeed =speed;
  330.       iflow = flow;
  331.       return(ttvt(ispeed,iflow));
  332. }
  333.  
  334.  
  335. /* TTVT -- Condition communication line for use as virtual terminal */
  336. /*       Returns -1 if Error */
  337. /*
  338.     Arguments :
  339.              speed -- requested communication baud rate
  340.              flow  -- requested flow control
  341. */
  342.  
  343.  
  344. ttvt (speed,flow) int speed, flow; {
  345.  
  346.        extern int parity;
  347.  
  348.       int s, status,ipar,dbits;
  349.  
  350.  
  351.       s = ttsspd(speed);               /* Check the requested speed */
  352.       if (s < 0 ) return(-1);
  353.       ipar=0;
  354.       dbits = 8;
  355.       if (parity ) dbits = 7;            /* Set up required parity */
  356.       if (parity =='o') ipar =1;
  357.       else if (parity =='e') ipar =2;
  358.       else if (parity =='m') ipar =3;
  359.       else if (parity =='s') ipar =4;
  360.       status = asiinit(ttyfd,s,ipar,1,dbits);  /* Condition comm port using */
  361.                            /* Greenleaf functions         */
  362.       if ( status < 0 ) return(-1);
  363.       if ( flow)
  364.      {
  365.        asirchk(ttyfd,XOFFCODE,XOFF,2);
  366.        asirchk(ttyfd,XONCODE,XON,2);
  367.      }
  368.        else
  369.      {
  370.        asirchk(ttyfd,XOFFCODE,XOFF,0);
  371.        asirchk(ttyfd,XONCODE,XON,0);
  372.       }
  373.       asirchk(ttyfd,NULCODE,0x00,2);
  374.       asiignore(ttyfd,1,ON);
  375.       asiignore(ttyfd,2,ON);
  376.       return(0);
  377. }
  378. /* T T S S P D -- check for valid baud rates */
  379. /*          return the baud rate if valid otherwise -1 */
  380.  
  381. ttsspd(speed) {
  382.     int s;
  383.     if (speed <0) return(-1);
  384.     switch (speed) {
  385.     case 0: s = 0 ; break;
  386.     case 300: s = 300 ; break;
  387.     case 1200: s = 1200 ; break;
  388.     case 2400: s = 2400 ; break;
  389.     case 4800: s = 4800 ; break;
  390.     case 9600: s = 9600 ; break;
  391.     default:
  392.       fprintf(stderr,"Unsupported line speed - %d\n",speed);
  393.       fprintf(stderr,"Current speed not changed\n");
  394.       s = - 1;
  395.       break;
  396.        }
  397. return(s);
  398. }
  399.  
  400.  
  401.  
  402. /* TTFLUI  --- Flush tty input buffer */
  403.  
  404. ttflui() {
  405.  
  406.  
  407.     if ( ttyfd < 0) return(-1);
  408.     if ( !ttsome()) return(0);
  409.     while (1)
  410.        {
  411.      while(ttsome()) asigetc(ttyfd);    /* Greenleaf function */
  412.      if (ttinc(1) < 0) break;        /* Wait one sec */
  413.        }
  414.     return(0);
  415. }
  416.  
  417. /* TTFLUO  ---- Flush tty ouput buffer */
  418.  
  419. ttfluo() {
  420.  
  421.     if ( ttyfd > -1 )  asiclear(ttyfd,ASOUT);      /* Greenleaf function */
  422. }
  423.  
  424. /* T T I N -- read one character for tty input buffer */
  425. /*          return the character if available otherwise -1 */
  426.  
  427. ttin() {
  428.        char ch;
  429.        int n;
  430.        if ( ttyfd <0 ) return(-1);
  431.        if (!ttsome()) return(-1);              /* Anything there */
  432.        n = asigetc(ttyfd);                  /* Greenleaf function */
  433.        if ( n > 0 )  n &= 0377;
  434.        return(n);
  435. }
  436.  
  437. /*  T T C H K    check if character available in receive buffer */
  438.  
  439. ttchk() {
  440.  
  441.      int n;
  442.  
  443.      if ( ttyfd < 0 ) return(0);
  444.      if ( !ttsome() ) return(0);
  445.      return (TRUE);
  446. }
  447.  
  448.  
  449.  
  450. /*    T T S O M E
  451.  *
  452.  *    Routine to return TRUE if receive buffer has character in it
  453.  *
  454.  *    Returns: Serial port receive character register status
  455.  */
  456.  
  457. int ttsome()
  458. {
  459.       int status;
  460.  
  461.     ttflow();        /* Check for XOFF if enabled */
  462.                         /* if receiver is not empty */
  463.     if ((asi_parms[ttyfd].flags&2)==0) return(TRUE);   /* Greenleaf */
  464.     return(FALSE);
  465.  
  466. }
  467. int ttflow()
  468.    {
  469.       if ( isrchk(ttyfd,XOFFCODE)) {         /* check for XOFF */
  470.       asihold(ttyfd);             /* Hold interrupts */
  471.       asiresume(ttyfd,ASIN);         /* Resume receiving */
  472.       if ( !isrchk(ttyfd,XONCODE)) {
  473.           strtim = totsec();         /* Intialize timer */
  474.           while ( TRUE) {
  475.          if ( isrchk(ttyfd,XONCODE)) {       /* wait for XON */
  476.              break;               /* go for it again */
  477.          }
  478.          if ( !carrier() || toolong(5)) break;    /* don't wait toolong */
  479.           }
  480.       }
  481.       asihold(ttyfd);             /* stop interrupts */
  482.       asiresume(ttyfd,ASINOUT);         /* resume them */
  483.       if ( isrchk(ttyfd,XOFFCODE))    {
  484.         asirchk(ttyfd,XOFFCODE,XOFF,4);        /* Clear XOFF flag */
  485.          }
  486.       if ( isrchk(ttyfd,XONCODE)) {
  487.         asirchk(ttyfd,XONCODE,XON,4);           /* Clear XON flag */
  488.          }
  489. /*      printf("xon/xoff detected \n");    */
  490.      }
  491. }
  492.  
  493.  
  494.  
  495. /*  C A R R I E R
  496.  *
  497.  *  check for existance of modem carrier signal
  498.  *
  499.  *  carrier()
  500.  *
  501.  *  Returns: 1 if carrier present; else returns 0
  502.  */
  503.  
  504. int carrier()
  505. {
  506.     extern int cdetect;
  507.  
  508.     int status;
  509.  
  510.     if ( !cdetect) return(TRUE);           /* Carrier not required */
  511.     status = asistat(ttyfd);          /* Greenleaf function        */
  512.     if (status & 0x0080) return(TRUE);    /* check rec line sig detect  */
  513.     return(FALSE);                  /* return FALSE if no carrier */
  514.  
  515. }
  516.  
  517.  
  518.  
  519. /*  S L E E P    wait for m seconds */
  520.  
  521. sleep(m) int m; {
  522.  
  523.        extern long int strtim, totsec();
  524.  
  525.        strtim = totsec();
  526.        while (1) {
  527.           if ( toolong(m) ) break;
  528.        }
  529. }
  530.  
  531. /*  T I C K S -- Returns total number of clock ticks since midnight */
  532.  
  533.  
  534. long int ticks()
  535.  
  536. {
  537.  
  538.      struct REGS regs;
  539.  
  540.      union { int s[2]; long ll;} secs ;
  541.  
  542.     regs.ax = 0;
  543.     secs.ll = 0L;
  544.     int86(0x1A,®s,®s);
  545.     secs.s[0] = regs.dx;            /* High count */
  546.     secs.s[1] = regs.cx;            /* Low count  */
  547.     return(secs.ll);
  548.   }
  549.  
  550. /* T O T S E C    -- Time since midnight in seconds */
  551.  
  552.  
  553. long int totsec() {
  554.  
  555.       long int ticks(), secnds;
  556.  
  557.         secnds = (10l * ticks() ) / 182;
  558.         return(secnds);
  559. }
  560.  
  561. /* T O O L O N G --  Timeout for user input with tout in seconds */
  562.  
  563. toolong(tout)  int tout; {
  564.  
  565.     extern long int strtim, totsec();
  566.     long int nowtim;
  567.  
  568.     nowtim = totsec();
  569.     if (nowtim < strtim)  nowtim += 86400L;
  570.     if ( (nowtim - strtim) < tout) return(0);
  571.     else  return(1);
  572.  
  573. }
  574.  
  575. /*  Z T I M E  --  Return date/time string  */
  576.  
  577. ztime(s) char **s; {
  578.  
  579.  
  580.     struct TIMEDATE *ptd;
  581.  
  582.     ptd = sgettime(6);        /* get the time from system  */
  583.     *s= ptd->dateline;        /* Using Greenleaf function  */
  584. }
  585.  
  586.  
  587.