home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / ckc197.zip / ckdtio.c < prev    next >
C/C++ Source or Header  |  2000-01-02  |  100KB  |  2,879 lines

  1. char *ckxv = "Data General tty I/O, 7.0.105, 9 Dec 1998";
  2.  
  3. /*  C K D T I O  */
  4.  
  5. /* C-Kermit interrupt, terminal control & i/o functions for DG AOS/VS */
  6.  
  7. /*
  8.   Author: Frank da Cruz <fdc@columbia.edu>
  9.   Columbia University Academic Information Systems, New York City.
  10.  
  11.   Copyright (C) 1985, 2000,
  12.     Trustees of Columbia University in the City of New York.
  13.     All rights reserved.  See the C-Kermit COPYING.TXT file or the 
  14.     copyright text in the ckcmai.c module for disclaimer and permissions.
  15.  
  16.   This module originally adapted to AOS/VS by:
  17.   Phil Julian, SAS Institute, Inc., Box 8000, Cary, NC 27512-8000, circa 1985.
  18.   Adapted to C-Kermit 5A by Eugenia Harris of Data General, 1992.
  19.   Upgraded to C-Kermit 6.0 by Frank da Cruz, 1996, and 7.0 (1998).
  20. */
  21. #define MAXINBUF 2048                  /* See ckdcon.c for same definition. */
  22. #nolist
  23. #include <memory.h>
  24. #include <string.h>
  25. #include <dglib.h>
  26. #include <bit.h>
  27. #include <sysid.h>
  28. #include <sys_calls.h>
  29. #include <packets/normal_io.h>
  30. #include <multitask.h>                                  
  31. #include <paru.h>
  32. #include <stdio.h>
  33. #include <packets:common.h>
  34. #include <packets:characteristics.h>
  35. #list
  36. #define CONINT_TSK 20                   /* Task id of interrupt-checker */
  37. #define CONINT_PRI 0                    /* Same as calling task */ 
  38. #define CONINT_STACK 02000
  39. int con_reads_mt = 0;                   /* Flag if task is active */
  40. int conint_ch;                          /* MT character read */
  41. int conint_avl;                         /* Flag that char available */
  42. int termtype;
  43. /* Delimiter table -- defaults to CR only */
  44. short idel_tbl[7] = {0x4,0,0,0,0,0,0};
  45. #include <stdio.h>                      /* Unix Standard i/o */
  46.  
  47. #ifndef DEVNAMLEN
  48. #define DEVNAMLEN (L_ctermid + 6)
  49. #endif 
  50.  
  51. #ifdef  NETCONN
  52. #undef DEVNAMLEN
  53. #define DEVNAMLEN 50                    /* longer field for host:service */
  54. #endif  /* NETCONN */
  55.  
  56. #include <sys/dir.h>                    /* Directory */
  57. #include <ctype.h>                      /* Character types */
  58.  
  59. /* Maximum length for the name of a tty device */
  60. #ifndef DEVNAMLEN
  61. #define DEVNAMLEN 25
  62. #endif
  63.  
  64. #include <stdio.h>                      /* Unix Standard i/o */
  65. #include <signal.h>                     /* Interrupts */
  66. #include <setjmp.h>                     /* Longjumps */
  67. #include "ckcdeb.h"                     /* Typedefs, formats for debug() */
  68. #include "ckcnet.h"
  69. #include <sys/stat.h>
  70.  
  71. char *ckxsys = " Data General AOS/VS";
  72.  
  73. /* Features... */
  74.  
  75. #define MYREAD
  76.  
  77. /*
  78.  Variables available to outside world:
  79.  
  80.    dftty  -- Pointer to default tty name string, like "/dev/tty".
  81.    dfloc  -- 0 if dftty is console, 1 if external line.
  82.    dfprty -- Default parity
  83.    dfflow -- Default flow control
  84.    ckxech -- Flag for who echoes console typein:
  85.      1 - The program (system echo is turned off)
  86.      0 - The system (or front end, or terminal).
  87.    functions that want to do their own echoing should check this flag
  88.    before doing so.
  89.  
  90.    flfnam -- Name of lock file, including its path, e.g.,
  91.                 "/usr/spool/uucp/LCK..cul0" or "/etc/locks/tty77"
  92.    haslock -- Flag set if this kermit established a uucp lock.
  93.    inbufc -- number of tty line rawmode unread characters 
  94.                 (system III/V unixes)
  95.    backgrd -- Flag indicating program executing in background ( & on 
  96.                 end of shell command). Used to ignore INT and QUIT signals.
  97.  
  98. /* Declarations of variables global within this module */
  99.  
  100. /* Declarations of variables global within this module */
  101.  
  102. #ifdef TTLEBUF                /* See ckcnet.h */
  103. int ttpush = -1;
  104. #define LEBUFSIZ 4096
  105. static CHAR le_buf[LEBUFSIZ];
  106. static int le_start = 0, le_end = 0, le_data = 0;
  107. #endif /* TTLEBUF */
  108.  
  109. static time_t tcount;                   /* Elapsed time counter */
  110. SIGTYP (*saval)() = NULL;               /* For saving alarm handler */
  111.  
  112. /* The following lists of functions are somewhat out of date.  For a
  113.    better listing, see ckutio.c
  114.  
  115. Functions for assigned communication line (either external or console tty):
  116.  
  117.    sysinit()               -- System dependent program initialization
  118.    ttopen(ttname,local,mdmtyp) -- Open the named tty for exclusive access.
  119.    ttclos()                -- Close & reset the tty, releasing any access lock.
  120.    ttpkt(speed,flow,parity)-- Put the tty in packet mode and set the speed.
  121.    ttvt(speed,flow)        -- Put the tty in virtual terminal mode.
  122.                               or in DIALING or CONNECTED modem control state.
  123.    ttinl(dest,max,timo,eol,start) -- Timed read line from the tty.
  124.    ttinc(timo)             -- Timed read character from tty.
  125.    myread()                -- System 3 raw mode bulk buffer read, gives
  126.                            -- subsequent chars one at a time and simulates
  127.                            -- FIONREAD!
  128.    ttchk()                 -- See how many characters in tty input buffer.
  129.    ttxin(n,buf)            -- Read n characters from tty (untimed).
  130.    ttol(string,length)     -- Write a string to the tty.
  131.    ttoc(c)                 -- Write a character to the tty.
  132.    ttflui()                -- Flush tty input buffer.
  133.    ttfluo()                -- Flush tty output buffer.  (not used)
  134.    ttgmdm()                -- Returns status of modem signals (not used)
  135.    ttgspd()                -- Returns speed of tty line
  136.    ttsspd(cps)             -- Set line speed on tty line
  137.    ttimoff()               -- Turns off all pending timer interrupts
  138.    ttscarr(carrier)        -- Copies argument to global variable
  139.    ttwmdm(mdmsig,timo)     -- Wait for specified signal (not used)
  140.    ttlock(ttname)          -- Lock against uucp collisions (not used)
  141.    ttunlck()               -- Unlock "       "     "       (not used)
  142.    look4lk(ttname)         -- Check if a lock file exists  (not used)
  143.  
  144. Functions for console terminal:
  145.  
  146.    congm()   -- Get console terminal modes.
  147.    concb(esc) -- Put the console in single-character wakeup mode with no echo.
  148.    conbin(esc) -- Put the console in binary (raw) mode.
  149.    conres()  -- Restore the console to mode obtained by congm().
  150.    conoc(c)  -- Unbuffered output, one character to console.
  151.    conol(s)  -- Unbuffered output, null-terminated string to the console.
  152.    conola(s) -- Unbuffered output, array of strings to the console.
  153.    conxo(n,s) -- Unbuffered output, n characters to the console.
  154.    conchk()  -- Check if characters available at console (bsd 4.2).
  155.  
  156.                 Check if escape char (^\) typed at console (System III/V).
  157.    coninc(timo)  -- Timed get a character from the console.
  158.    conint()  -- Enable terminal interrupts on the console if not background.
  159.    connoi()  -- Disable terminal interrupts on the console if not background.
  160.    congks(timo) -- Get keyboard scan code (not used)
  161.  
  162. Time functions:
  163.  
  164.    msleep(m) -- Millisecond sleep
  165.    ztime(&s) -- Return pointer to date/time string
  166.    rtimer() --  Reset timer
  167.    gtimer()  -- Get elapsed time since last call to rtimer()
  168. */
  169.  
  170. #ifdef UXIII
  171. #ifdef datageneral
  172. /* Console and terminal characteristics vectors */
  173. short *charcurr;
  174. short charconin[$CLMAX];    /* Console input; channel 0 */
  175. short charconout[$CLMAX];   /* Console output; channel 1 */
  176. short chartty[$CLMAX];      /* generic tty channel */
  177. short charttyin[$CLMAX];    /* tty input; channel ttyfd */
  178. short charttyout[$CLMAX];   /* tty output; channel ttyfdout */
  179. short ch_ttold[$CLMAX];
  180. short ch_ttraw[$CLMAX];
  181. short ch_ttvt[$CLMAX]; 
  182. short ch_ccold[$CLMAX];
  183. short ch_ccraw[$CLMAX];
  184. short ch_ccbrk[$CLMAX]; 
  185. #undef ECHO
  186. #include <sys/termio.h>
  187. /* Add synonyms for Unix type ioctl */
  188. #define TCSETAF TCSETA
  189. #define TCSETAW TCSETA
  190. #else
  191. #include <termio.h>
  192. #include <sys/ioctl.h>
  193. #endif datageneral
  194.  
  195. #include <fcntl.h>                      /* directory reading for locking */
  196. #include <errno.h>                      /* error numbers for system returns */
  197. #endif /* UXIII */
  198.  
  199. /* Declarations */
  200.  
  201. long time();                            /* All Unixes should have this... */
  202. extern int errno;                       /* System call error return */
  203. extern int ttnproto;
  204. extern int ttnet;
  205. extern int xfrcan, xfrchr, xfrnum;    /* Transfer cancellation */
  206.  
  207. /* dftty is the device name of the default device for file transfer */
  208. /* dfloc is 0 if dftty is the user's console terminal, 1 if an external line */
  209.  
  210. char *dftty = CTTNAM;                   /* Remote by default, use normal */
  211. int dfloc = 0;                          /* controlling terminal name. */
  212. int dfprty = 0;                         /* Parity (0 = none) */
  213. int dfflow = 1;                         /* Xon/Xoff flow control */
  214. int backgrd = 0;                        /* Assume in foreground. */
  215. int ckxech = 0; /* 0 if system normally echoes console characters, else 1 */
  216.  
  217. /* Declarations of variables global within this module */
  218.  
  219. static long tcount;                     /* Elapsed time counter */
  220. static char *brnuls = "\0\0\0\0\0\0\0"; /* A string of nulls */
  221. static jmp_buf sjbuf, jjbuf;            /* Longjump buffer */
  222.  
  223. static int lkf = 0,                     /* Line lock flag */
  224.     conif = 0,                          /* Console interrupts on/off flag */
  225.     cgmf = 0,                           /* Flag that console modes saved */
  226.     xlocal = 0;                         /* Flag for tty local or remote */
  227.     curcarr = 0;                        /* Carrier mode: require/ignore. */
  228. int ttyfd = -1;                         /* TTY file descriptor */
  229. int tvtflg = 0;
  230. long ttspeed = -1;                      /* For saving speed */
  231. int ttflow = -9;                        /* For saving flow */
  232. int ttld = -1;                          /* Line discipline */
  233. int ttfdflg = 0;
  234. int ttpmsk = 0377;
  235. int ttprty = 0;
  236. int ttpflg = 0;                         /* Parity not sensed yet */
  237. int ttmdm = 0;
  238. int ttcarr = CAR_AUT;                   /* Carrier handling mode. */
  239. int telnetfd = 0;
  240. static int netconn = 0;
  241. int fdflag = 0;
  242. static char escchr;                     /* Escape or attn character */
  243. static int kerld = 0;                   /* Not selected, no special l.d. */
  244. int x25fd = 0;
  245.  
  246. #ifdef UXIII
  247.   static struct termio                  /* sgtty info... */
  248.     ttold, ttraw, tttvt,                /* for communication line */
  249.     ccold, ccraw, cccbrk;               /* and for console */
  250. #else
  251.   static struct sgttyb                  /* sgtty info... */
  252.     ttold, ttraw, tttvt, ttbuf,         /* for communication line */
  253.     ccold, ccraw, cccbrk;               /* and for console */
  254. #endif
  255.  
  256. char flfnam[80];                        /* uucp lock file path name */
  257. int haslock = 0;                        /* =1 if this kermit locked uucp */
  258.  
  259. static int inbufc = 0;                  /* stuff for efficient SIII raw line */
  260. static int ungotn = -1;                 /* pushback to unread character */
  261. static int conesc = 0;                  /* set to 1 if esc char (^\) typed */
  262.  
  263. static int ttlock();                    /* definition of ttlock subprocedure */
  264. static int ttunlck();                   /* and unlock subprocedure */
  265. static char ttnmsv[DEVNAMLEN];          /* copy of open path for tthang */
  266.  
  267. #ifdef datageneral
  268. FILE *ttfile,*ttfileout;                /* Files opened by ttopen */
  269.   
  270. struct p_nio_ex w_io_parms;             /* ?write system call structure */
  271. struct p_nio_ex r_io_parms;             /* ?read system call structure */
  272.  
  273. struct p_nio_ex io_parms;               /* open structure in ttopen */
  274. struct p_nio_ex x_io_parms;             /* ?read/?write structure for ttyfd */
  275. struct p_nio_ex xout_parms;             /* ?write structure for ttyfdout */
  276. struct p_screen x_io_scrn,
  277.        r_io_scrn,io_screen;             /* Edit-read structures */
  278.  
  279. int ttyfdout = -1;                      /* ?write Unix number for remote out */
  280. short timotty = 0;                      /* {Flag for timeouts (=1), value */
  281. short timocon = 0;                      /* tty is ttyfd..., con is Unix 0/1 */
  282. extern char *SPACMD;                    /* returns space in CURRENT dir */
  283. #endif
  284.  
  285. /* Timeout handler for communication line input functions */
  286.  
  287. SIGTYP
  288. timerh(foo) int foo; {                  /* we will try to use this */
  289.     ttimoff();
  290.     longjmp(sjbuf,1);
  291. }
  292.  
  293. /* Control-C trap for communication line input functions */
  294. /* These are not used in the VS implementation.  Instead, there is a task */
  295. /* called conint_mt that reads characters from the keyboard and sets a    */
  296. /* flag when it gets one.  It is then up to other routines (e.g., chkint()*/
  297. /* to determine what to do with the characters (and zero the flag)  --ENH */
  298.  
  299. int cc_int;                             /* Flag */
  300. SIGTYP (* occt)();                      /* For saving old SIGINT handler */
  301.  
  302. SIGTYP
  303. cctrap(foo) int foo; {                  /* Needs arg for ANSI C */
  304.   cc_int = 1;                           /* signal() prototype. */
  305.   return;
  306. }
  307.  
  308. #ifdef TTLEBUF
  309. VOID
  310. le_init() {                /* LocalEchoInit() */
  311.     int i;
  312.     for (i = 0; i < LEBUFSIZ; i++)
  313.       le_buf[i] = '\0';
  314.     le_start = 0;
  315.     le_end = 0;
  316.     le_data = 0;
  317. }
  318.  
  319. VOID
  320. le_clean() {                /* LocalEchoCleanup() */
  321.     le_init();
  322.     return;
  323. }
  324.  
  325. int
  326. le_inbuf() {
  327.     int rc = 0;
  328.     if (le_start != le_end) {
  329.     rc = (le_end -
  330.           le_start +
  331.           LEBUFSIZ) % LEBUFSIZ;
  332.     }  
  333.     debug(F111,"le_inbuf","chars waiting",rc);
  334.     return(rc);
  335. }
  336.  
  337. int
  338. #ifdef CK_ANSIC
  339. le_putchar(char ch)
  340. #else
  341. le_putchar(ch) char ch;
  342. #endif /* CK_ANSIC */
  343. /* le_putchar */ {
  344.     if ((le_start - le_end + LEBUFSIZ)%LEBUFSIZ == 1) {
  345.         debug(F110,"le_putchar","buffer is full",0);
  346.         return(-1);
  347.     }
  348.     le_buf[le_end++] = ch;
  349.     if (le_end == LEBUFSIZ)
  350.       le_end = 0;
  351.     le_data = 1;
  352.     return(0);
  353. }
  354.  
  355. int
  356. #ifdef CK_ANSIC
  357. le_puts(CHAR * s, int n)
  358. #else
  359. le_puts(s,n) CHAR * s; int n; 
  360. #endif /* CK_ANSIC */
  361. /* le_puts */ {
  362.     int rc = 0;
  363.     int i = 0;
  364.     CHAR * p = (CHAR *)"le_puts";
  365.     hexdump(p,s,n);
  366.     for (i = 0; i < n; i++) 
  367.       rc = le_putchar((char)s[i]);
  368.     debug(F101,"le_puts","",rc);
  369.     return(rc);
  370. }
  371.  
  372. int
  373. #ifdef CK_ANSIC
  374. le_putstr(CHAR * s)
  375. #else
  376. le_putstr(s) CHAR * s; 
  377. #endif /* CK_ANSIC */
  378. /* le_puts */ {
  379.     CHAR * p;
  380.     int rc = 0;
  381.     p = (CHAR *)"le_putstr";
  382.     hexdump(p,s,(int)strlen((char *)s));
  383.     for (p = s; *p && !rc; p++)
  384.       rc = le_putchar(*p);
  385.     return(rc);
  386. }
  387.  
  388. int 
  389. #ifdef CK_ANSIC
  390. le_getchar(CHAR * pch) 
  391. #else /* CK_ANSIC */
  392. le_getchar(pch) CHAR * pch; 
  393. #endif /* CK_ANSIC */
  394. /* le_getchar */ {
  395.     int rc = 0;
  396.     if (le_start != le_end) {
  397.         *pch = le_buf[le_start];
  398.         le_buf[le_start] = 0;
  399.         le_start++;
  400.  
  401.         if (le_start == LEBUFSIZ)
  402.           le_start = 0;
  403.  
  404.         if (le_start == le_end) {
  405.             le_data = 0;
  406.         }
  407.         rc++;
  408.     } else {
  409.         *pch = 0;
  410.     }
  411.     return(rc);
  412. }
  413. #endif /* TTLEBUF */
  414.  
  415.  
  416. /*  S Y S I N I T  --  System-dependent program initialization.  */
  417.  
  418. int
  419. sysinit() {
  420.  
  421. #ifdef datageneral
  422.      /* Set up many things on the DG system, for initialization, etc. */
  423.      
  424.      short flags[3];
  425.      char *username;
  426.      int err;
  427.      
  428.      signal(SIGALRM,SIG_IGN);
  429.  
  430.      /* Get the terminal type, since DG terminals are different from others,
  431.         especially in the way BS is handled ('\b' is EM).
  432.         termtype = 0 means a regular DG style terminal, and 
  433.         termtype = 1 means an ANSI style terminal with ^H for backspace.
  434.         If Kermit is run in batch or has redirected input, then we do not
  435.         want to test or set the console characteristics.
  436.      */
  437.      termtype = 0;
  438.      if (isatty(0)) {
  439.         if (sys_gchr(channel(0),1<<31,&flags))
  440.              { perror("sysinit: sys_gchr: "); return(1); }
  441.  
  442.         /* Only determine whether or not it is a $TTY */
  443.         if ((flags[1] & $DTYPE) == $TTY) termtype = 1;
  444.      }
  445.  
  446.      zero((char *) &w_io_parms, sizeof(w_io_parms));
  447.      w_io_parms.ich  = channel(1);                   /* stdout */
  448.      w_io_parms.isti = $IBIN|$RTDS|$ICRF|$OFOT;
  449.      w_io_parms.isti &= ~$IPST;
  450.      w_io_parms.imrs = MAXINBUF-1;
  451.      w_io_parms.ibad = -1;
  452.      w_io_parms.ircl = -1;
  453.  
  454.      zero((char *) &r_io_parms, sizeof(r_io_parms));
  455.      r_io_parms.ich  = channel(0);                   /* stdin */
  456.      r_io_parms.isti = $IBIN|$RTFX|$ICRF|$OFIN;
  457.      r_io_parms.isti &= ~$IPST;
  458.      r_io_parms.imrs = MAXINBUF-1;
  459.      r_io_parms.ibad = -1;
  460.      r_io_parms.ircl = -1;
  461.  
  462.      zero((char *) &r_io_scrn, sizeof(r_io_scrn));
  463.      r_io_parms.etsp = 0;              /* Screen management extension */
  464.      r_io_scrn.esfc &= ~$ESNE;         /* Echo input data */
  465.      r_io_scrn.esfc &= ~$ESSE;         /* No screen edit */
  466.      r_io_scrn.esfc |= $ESGT;          /* Dump ring buffer */
  467.  
  468.      zero((char *) &x_io_parms, sizeof(x_io_parms));
  469.      /* $RTDY must be used instead of $RTDS since this causes failure on
  470.       * the Prime, which is probably getting data overruns on output or
  471.       * missing data.  Also, $RTDY is more efficient and faster.
  472.       */
  473.      x_io_parms.isti = $IBIN|$RTFX|$ICRF|$OFIO|$IPKL;
  474.      x_io_parms.isti &= ~$IPST;
  475.      x_io_parms.imrs = MAXINBUF-1;
  476.      x_io_parms.ibad = -1;
  477.      x_io_parms.ircl = -1;
  478.  
  479.      /* IDEL would default to NULL, FF, CR, NL as delimiters.
  480.       * The only delimiters here are CR and NL, for data sensitive 
  481.       * records.
  482.       */
  483.      idel_tbl[0] = 0x24;
  484.      x_io_parms.idel = idel_tbl;
  485.  
  486.      zero((char *) &x_io_scrn, sizeof(x_io_scrn));
  487.      x_io_parms.etsp = &x_io_scrn;     /* Screen management extension */
  488.      x_io_parms.etsp |= BIT0;          /* Turn on the high bit */
  489.      x_io_scrn.esfc &= ~$ESNE;         /* Echo input data */
  490.      x_io_scrn.esfc &= ~$ESSE;         /* No screen edit */
  491.      x_io_scrn.esfc |= $ESGT;          /* Dump ring buffer */
  492.  
  493.      memcpy((char *) &xout_parms,(char *) &x_io_parms,sizeof(x_io_parms));
  494.      xout_parms.isti = $IBIN|$RTDY|$ICRF|$OFOT;
  495.      xout_parms.etsp = 0;              /* Screen management extension */
  496.  
  497.      username = getenv("LOGNAME");
  498.  
  499.      /* Zero the console characteristics arrays */
  500.      zero ((char *) charconin, sizeof(charconin));
  501.      zero ((char *) charconout, sizeof(charconout));
  502.      zero ((char *) chartty, sizeof(chartty));
  503.      zero ((char *) charttyin, sizeof(charttyin));
  504.      zero ((char *) charttyout, sizeof(charttyout));
  505.       
  506.      /* Initialize charconin & out, 
  507.       * and set up the console for CHAR/BREAK=BMOB 
  508.       */
  509.           if (sys_gechr( channel(0), (1<<31)|$CLMAX, charconin)) 
  510.                { perror("sysinit: gechr 0"); return(-1); }
  511.           if (sys_gechr( channel(1), (1<<31)|$CLMAX, charconout)) 
  512.                { perror("sysinit: gechr 1"); return(-1); }
  513.           charconin[4] &= ~$CBKM;
  514.           charconin[4] |= $CBBM;
  515.           if (sys_sechr( channel(0), (1<<31)|$CLMAX, charconin)) 
  516.                { perror("sysinit: sechr stdin "); return(-1); }
  517.           if (sys_sechr( channel(1), (1<<31)|$CLMAX, charconout))
  518.                { perror("sysinit: sechr stdout "); return(-1); }
  519.  
  520. #ifdef TTLEBUF
  521.      le_init();
  522. #endif /* TTLEBUF */
  523.  
  524.      return(0);
  525. }
  526.  
  527. /* S E T T O -- set timeout on the channel to period.
  528.                 Save the old characteristics in char***in[]. 
  529. */
  530. /* AOS/VS device timeouts are used sparingly in this implementation of    */
  531. /* Kermit.  In most cases, signals are used instead.                --ENH */
  532.  
  533. int setto(chan, period) int chan, period; 
  534. {
  535.      int isconsole = 0;
  536.      int iscon[2];       /* Flags because i/o could be redirected */
  537.  
  538.      /* Setting is done external to here, since they can distinguish the 
  539.         console from ttyfd device.  Both console channels must be set
  540.         the same.
  541.      */
  542.      if ( (chan == channel(0)) || (chan == channel(1)) ) {
  543.           isconsole = 1; zero((char *) iscon, sizeof(iscon));
  544.           chan = channel(0);
  545.           if (sys_gechr( channel(0), (1<<31)|$CLMAX, charconin)) 
  546.                if (isatty(0)) {
  547.                     iscon[0] = 1;
  548.                     perror("setto: gechr 0: "); 
  549.                     return(-1);
  550.                }
  551.           charcurr = charconin;
  552.           if (sys_gechr( channel(1), (1<<31)|$CLMAX, charconout)) 
  553.                if (isatty(1)) {
  554.                     iscon[1] = 1;
  555.                     perror("setto: gechr 1: "); 
  556.                     return(-1);
  557.                }
  558.           timocon = period;
  559.      }
  560.  
  561.      else {
  562.           if (sys_gechr( chan, (1<<31)|$CLMAX, chartty))
  563.                { perror("setto: gechr tty: "); return(-1); }
  564.           charcurr = chartty;
  565.           timotty = period;
  566.      }
  567.  
  568.      charcurr[1] |= (0100000>>$CTO);
  569.      if (sys_sechr( chan, (1<<31)|$CLMAX, charcurr))
  570.           if ((isconsole == 0) || iscon[0]) {
  571.                perror("setto: sechr: "); 
  572.                return(-1); 
  573.           }
  574.      if (sys_stom( chan, 1<<31, period)) 
  575.           if ((isconsole == 0) || iscon[0]) {
  576.                perror("setto: stom: "); 
  577.                return(-1);
  578.           }
  579.  
  580.      if (isconsole == 0) return(0);
  581.      
  582.      chan = channel(1);
  583.      charconout[1] |= (0100000>>$CTO);
  584.      if (sys_sechr( chan, (1<<31)|$CLMAX, charconout)) 
  585.           if (iscon[1]) {
  586.                perror("setto: sechr 1: "); 
  587.                return(-1);
  588.           }
  589.      if (sys_stom( chan, 1<<31, period)) 
  590.           if (iscon[1]) {
  591.                perror("setto: stom 1: "); 
  592.                return(-1);
  593.           }
  594.      return(0);
  595. }
  596.  
  597.  
  598. /* R E S T O -- reset timeouts to the previous values, and restore char */
  599.  
  600. int
  601. resto(chan) int chan;
  602. {
  603.      int i, chan0, chan1, iscon[2];
  604.  
  605.      if ( (chan==channel(0)) || (chan==channel(1)) ) {
  606.  
  607.           chan0 = channel(0);      chan1 = channel(1); 
  608.           iscon[0] = isatty(0);    iscon[1] = isatty(1);
  609.           charconin[1] &= ~(0100000>>$CTO);
  610.           if (sys_stom( chan0, 1<<31, -1)) 
  611.                if (iscon[0]) {
  612.                     perror("resto: stom 0: "); 
  613.                     return(-1);
  614.                }
  615.           for (i = 0; i < $CLMAX; i++) if (charconin[i] != 0) {
  616.                if (sys_sechr( chan0, (1<<31)|$CLMAX, charconin))
  617.                     if (iscon[0]) {
  618.                          perror("resto: sechr 0: "); 
  619.                          return(-1); 
  620.                     }
  621.                break;
  622.           }
  623.           charconout[1] &= ~(0100000>>$CTO);
  624.           if (sys_stom( chan1, 1<<31, -1)) 
  625.                if (iscon[1]) {
  626.                     perror("resto: stom 1: "); 
  627.                     return(-1);
  628.                }
  629.           for (i = 0; i < $CLMAX; i++) if (charconout[i] != 0) {
  630.                if (sys_sechr( chan1, (1<<31)|$CLMAX, charconout)) 
  631.                if (iscon[1]) {
  632.                     perror("resto: sechr 1: "); 
  633.                     return(-1);
  634.                }
  635.                break;
  636.           }
  637.  
  638.           timocon = 0; 
  639.      }
  640.      else {
  641.           chartty[1] &= ~(0100000>>$CTO);
  642.           if (sys_stom( chan, 1<<31, -1)) 
  643.                { perror("setto: stom tty: "); return(-1); }
  644.           for (i = 0; i < $CLMAX; i++) if (chartty[i] != 0) {
  645.                if (sys_sechr( chan, (1<<31)|$CLMAX, chartty))
  646.                     { perror("resto: sechr tty: "); return(-1); }
  647.                break;
  648.           }
  649.           timotty = 0; 
  650.      }
  651.       
  652.      return(0);
  653. }
  654.  
  655.  
  656. /* S E T F L O W -- Set flow control in the device. 
  657.      
  658.     The device is assumed to be an intelligent IAC, where a CHAR/ON/IFC/OFC
  659.     could be done.
  660.  
  661. */
  662. static int dgsetflow(chan) int chan;
  663. {
  664.      short termparms[$CLMAX];
  665.  
  666.      if (sys_gechr( chan, (1<<31)|$CLMAX, termparms)) 
  667.           { perror("dgsetflow: gechr "); return(-1); }
  668.  
  669.      bitset(&termparms[4],$XOFC,1);
  670.      bitset(&termparms[4],$XIFC,1);
  671.      
  672.      if (sys_sechr( chan, (1<<31)|$CLMAX, termparms)) 
  673.           { perror("dgsetflow: sechr "); return(-1); }
  674.  
  675.      return(0);
  676. }
  677.  
  678.  
  679. /* R E S F L O W -- Re-Set flow control in the device. 
  680.      
  681.     The device is assumed to be an intelligent IAC, where a CHAR/OFF/IFC/OFC
  682.     could be done.
  683.  
  684. */
  685. int resflow(chan) int chan;
  686. {
  687.      int i;
  688.      short termparms[$CLMAX];
  689.  
  690.      if (sys_gechr( chan, (1<<31)|$CLMAX, termparms)) 
  691.           { perror("resflow: gechr "); return(-1); }
  692.  
  693.      bitset(&termparms[4],$XOFC,0);
  694.      bitset(&termparms[4],$XIFC,0);
  695.      
  696.      if (sys_sechr( chan, (1<<31)|$CLMAX, termparms))
  697.           { perror("resflow: sechr "); return(-1); }
  698.  
  699.      return(0);
  700. }
  701.  
  702.  
  703. /* S E T S P E E D -- Set the baud rate when not possible thru IOCTL.
  704.      
  705.     The device is assumed to be an intelligent IAC, where a CHAR/ON/BAUD=
  706.     could be done.
  707.  
  708. */
  709. int setspeed(sp) int sp;
  710. {
  711.      short termparms[$CLMAX];
  712.  
  713.      /* ttyfd is the Unix file number for the tty device.  Setting the
  714.       * characteristics will set it for both ttyfd and ttyfdout, since
  715.       * it is the device itself which is affected, and not just the 
  716.       * channel.
  717.       */
  718.      if (sys_gechr( channel(ttyfd), (1<<31)|$CLMAX, termparms)) 
  719.           { perror("setspeed: gechr "); return(-1); }
  720.  
  721.      termparms[3] &= ~$BRMSK;            /* Zero out the previous setting */
  722.      termparms[3] |= sp;
  723.      
  724.      if (sys_sechr( channel(ttyfd), (1<<31)|$CLMAX, termparms)) 
  725.           { perror("setspeed: sechr "); return(-1); }
  726.  
  727.      return(0);
  728. }
  729. #endif datageneral
  730.  
  731. /*  S Y S C L E A N U P  --  System-dependent cleanup */
  732.  
  733. int
  734. syscleanup() {
  735.     return(0);
  736.  
  737. /*  T T O P E N  --  Open a tty for exclusive access.  */
  738.  
  739. /*
  740.   Returns:
  741.     0 on success
  742.    -5 if device is in use
  743.    -4 if access to device is denied
  744.    -3 if access to lock directory denied
  745.    -2 upon timeout waiting for device to open
  746.    -1 on other error
  747. /*
  748.   If called with lcl < 0, sets value of lcl as follows:
  749.   0: the terminal named by ttname is the job's controlling terminal.
  750.   1: the terminal named by ttname is not the job's controlling terminal.
  751.   But watch out: if a line is already open, or if requested line can't
  752.   be opened, then lcl remains (and is returned as) -1.
  753. */
  754. int
  755. ttopen(ttname,lcl,modem,timo) char *ttname; int *lcl, modem,timo; {
  756.  
  757.     /* AOS/VS special stuff */
  758.     FILE *dg_open();                    /* Custom file open */
  759.     int retrycnt = 0;                   /* Retry if Modem disc in progress */
  760.  
  761.     char *ctermid();                    /* Wish they all had this! */
  762.     char *x;
  763.     extern char* ttyname();
  764.     char cname[DEVNAMLEN+4];
  765.  
  766. #define NAMEFD
  767. #ifdef NAMEFD
  768.     int i, j; char *p;
  769.     debug(F101,"ttopen telnetfd","",telnetfd);
  770. #endif /* NAMEFD */
  771.  
  772.     debug(F111,"ttopen entry modem",ttname,modem);
  773.     debug(F101," ttyfd","",ttyfd);
  774.     debug(F101," lcl","",*lcl);
  775.  
  776.     if (ttyfd > -1) {
  777.         if (strncmp(ttname,ttnmsv,DEVNAMLEN))   /* are old & new the same? */
  778.             ttclos(ttyfd);                      /* no? - close old */
  779.         else                                    /* yes? - ignore this call */
  780.             return(0);                          /* and return */
  781.     }
  782.  
  783. #ifdef NETCONN
  784.     if (modem < 0) {                    /* means special code for net type */
  785.         int x;
  786.         ttmdm = modem;
  787.         modem = -modem;                 /* negative value is net type */
  788.         fdflag = 0;                     /* stdio not redirected */
  789.         ttyfdout = -1;                  /* only use ttyfd for nets */
  790.         netconn = 1;                    /* network connection */
  791.         debug (F111,"ttopen net",ttname,modem);
  792. #ifdef NAMEFD
  793.         for (p = ttname; isdigit(*p); p++) ; /* check for all digits */
  794.         if (*p == '\0' && telnetfd) {
  795.             ttyfd = atoi(ttname);       /* can we test if it's open? */
  796.             ttfdflg = 1;               /* we got an open file descriptor */
  797.             debug(F111,"ttopen got open network fd",ttname,ttyfd);
  798.             strncpy(ttnmsv,ttname,DEVNAMLEN);   /* remember the "name" */
  799.             x = 1;                      /* return code is "good" */
  800.             if (telnetfd) {
  801.                 ttnet = NET_TCPB;
  802.                 ttnproto = NP_TELNET;
  803.             }
  804.         } else {
  805. #endif /* NAMEFD */                             /* hostname or address */
  806.             x = netopen(ttname,lcl,modem);      /* (see ckcnet.h) */
  807.             if (x > -1) {
  808.                 strncpy(ttnmsv,ttname,DEVNAMLEN);
  809.             } else netconn = 0;
  810. #ifdef NAMEFD
  811.         }
  812. #endif NAMEFD
  813.  
  814. /* ENH - left out ifdef sony_news section */
  815.  
  816.         xlocal = *lcl = 1;              /* network connections are local */
  817.         debug(F101,"ttopen net x","",x);
  818. #ifdef COMMENT
  819. /* Let netopen() handle this. */
  820.         if ((x > -1) && (!x25fd))
  821.             x = tn_ini();               /* initialize telnet protocol */
  822. #endif /* COMMENT */
  823.         return(x);
  824.     } else {                            /* terminal device */
  825. #endif /* NETCONN */
  826.  
  827. #ifdef NAMEFD
  828. /*
  829.   This code lets you give Kermit an open file descriptor for a serial
  830.   communication device, rather than a device name.  Kermit assumes that the
  831.   line is already open, locked, conditioned with the right parameters, etc.
  832. */
  833.         for (p = ttname; isdigit(*p); p++) ;    /* check for all digits */
  834.         if (*p == '\0') {
  835.             ttyfd = atoi(ttname);               /* can we test if open? */
  836.             debug(F111,"ttopen got open fd",ttname,ttyfd);
  837.             strncpy(ttnmsv,ttname,DEVNAMLEN);   /* remember the "name" */
  838.             xlocal = *lcl = 1;                  /* assume it's local */
  839.             netconn = 0;                        /* assume not network */
  840.             tvtflg = 0;                         /* initialize modes? */
  841.             ttmdm = modem;                      /* remember modem type */
  842.             fdflag = 0;                         /* stdio not redirected */
  843.             ttfdflg = 1;                        /* flag we were opened */
  844.                                                 /* this way */
  845. /* ENH - left out ifdef sony_news */
  846.  
  847.             return(0);                          /* return success */
  848.         }
  849. #endif /* NAMEFD */
  850. #ifdef NETCONN
  851.     }                           
  852. #endif /* NETCONN */
  853.  
  854. /* Here we have to open a serial device of the given name */
  855.  
  856.     tvtflg = 0;                         /* flag for use by ttvt() */
  857.                                         /* 0 means ttvt() not called yet */
  858.     fdflag = (!isatty(0) || !isatty(1));/* flag for stdio redirected */
  859.     debug(F101,"ttopen fdflag","",fdflag);
  860.     ttmdm = modem;                      /* Make this available to other fns */
  861.     xlocal = *lcl;                      /* Make this available to other fns */
  862.  
  863. /* Code for handling bidirectional tty lines goes here.
  864. /* Use specified method for turning off logins and suppressing getty. */
  865.  
  866. #ifdef ACUCNTRL
  867.     /* Should put call to priv_on() here, but that would be very risky! */
  868.     acucntrl("disable",ttname);         /* acucntrl() program. */
  869.     /* and priv_off() here... */
  870. #else
  871. #ifdef ATT7300
  872.     if ((attmodem & DOGETY) == 0)       /* offgetty() program. */
  873.       attmodem |= offgetty(ttname);     /* Remember response.  */
  874. #endif /* ATT7300 */
  875. #endif /* ACUCNTRL */
  876.  
  877. #ifdef datageneral
  878.     /* A custom open is done for the device, but a FILE handle is also needed
  879.      * for doing other special operations on the device.  See sysinit() for
  880.      * the initialization of the x_io_parms and xout_parms structures.
  881.      *
  882.      * First open up the output channel ($OFOT) 
  883.      */
  884.     idel_tbl[0] = 0x4;             /* CR only */
  885.     xout_parms.idel = idel_tbl;
  886.     xout_parms.ifnp = ttname;
  887.  
  888. /*
  889.     ttotmo = 0;
  890.     saval = signal(SIGALRM,timerh);
  891.     if (timo > 0) {
  892.         alarm(timo);              
  893.         if (setjmp(sjbuf)) {
  894.         } else {
  895. */           /* Ignore timeout for now - let it take as long as it wants */
  896. retry:
  897.     if ((ttfileout =
  898.        dg_open(ttname, xout_parms.isti, xout_parms.isto, 
  899.                xout_parms.imrs,xout_parms.ires,xout_parms.idel))
  900.        == NULL) {
  901.           /* If a modem disconnect, or one in progress, wait and retry. */
  902.           if ((lasterror() == ERDCT) || (lasterror() == ERCDS))
  903.                if (retrycnt == 0) {
  904.                     retrycnt = 1; 
  905.                     sleep(2); 
  906.                     goto retry; 
  907.                }
  908.           ttyfdout = -1;
  909.           perror("ttopen: output_line: dg_open");
  910.           if ((lasterror() == EREO1) || (lasterror() == EREO2)) /* in use */
  911.               return(-5);                               /* EOF */
  912.           else if (lasterror() == ERFAD)
  913.               return(-4);                               /* access denied */
  914.           else                                          /* some other error */
  915.               return(-1);
  916.     }
  917.     /* Successfull opens fall through here! */
  918.     
  919.     ttyfdout = fileno(ttfileout);               /* Note that ttyfdout is */
  920.     xout_parms.ich = channel(ttyfdout);         /* only used for asynch  */
  921.     
  922.     /* Next, open up the input channel ($OFIN) */
  923.  
  924.     x_io_parms.ifnp = ttname;
  925.     /* IDEL would default to NULL, FF, CR, NL as delimiters.
  926.      * The only delimiters here are CR and NL, for data sensitive 
  927.      * records.
  928.      */
  929.     idel_tbl[0] = 0x24;
  930.     x_io_parms.idel = idel_tbl;
  931.  
  932.     if ((ttfile =
  933.        dg_open(ttname, x_io_parms.isti, x_io_parms.isto, 
  934.                x_io_parms.imrs,x_io_parms.ires,x_io_parms.idel,
  935.                (P_SCREEN *) x_io_parms.etsp))
  936.        == NULL) {
  937.           ttyfd = -1;
  938.           perror("ttopen: input_line: dg_open");
  939.           if ((lasterror() == EREO1) || (lasterror() == EREO2)) /* in use */
  940.               return(-5);                               /* EOF */
  941.           else if (lasterror() == ERFAD)
  942.               return(-4);                               /* access denied */
  943.           else                                          /* some other error */
  944.               return(-1);
  945.        }
  946.     else {
  947.           ttyfd = fileno(ttfile);
  948.           x_io_parms.ich = channel(ttyfd);
  949.     }
  950.  
  951. #endif
  952.  
  953.     /* Make sure it's a real tty. */
  954.     if (!isatty(ttyfd)) {
  955.         fprintf(stderr,"%s is not a tty!\n",ttname);
  956.         debug(F110,"ttopen not a tty",ttname,0);
  957.         close(ttyfd);
  958.         ttyfd = -1;
  959.         return(-1);
  960.     }
  961.  
  962.     strncpy(ttnmsv,ttname,DEVNAMLEN);   /* Open, keep copy of name locally. */
  963.  
  964. /* Caller wants us to figure out if line is controlling tty */
  965.  
  966.     debug(F111,"ttopen ok",ttname,*lcl);
  967.     if (*lcl == -1) {
  968.         if (strcmp(ttname,CTTNAM) == 0) {   /* "/dev/tty" always remote */
  969.             debug(F110," Same as CTTNAM",ttname,0);
  970.             xlocal = 0;
  971.         } else if (isatty(0)) {         /* Else, if stdin not redirected */
  972.             x = ttyname(0);             /* then compare its device name */
  973.             strncpy(cname,x,DEVNAMLEN); /* (copy from internal static buf) */
  974.             debug(F110," ttyname(0)",x,0);
  975.             x = ttyname(ttyfd);         /* ...with real name of ttname. */
  976.             xlocal = (strncmp(x,cname,DEVNAMLEN) == 0) ? 0 : 1;
  977.             debug(F111," ttyname",x,xlocal);
  978.         }                               /* Else, if stdin redirected... */
  979.     }    
  980.  
  981. /* Now check if line is locked -- if so fail, else lock for ourselves */
  982.  
  983.     lkf = 0;                            /* Check lock */
  984.     if (xlocal > 0) {
  985.         if (ttlock(ttname) < 0) {
  986.             fprintf(stderr,"Exclusive access to %s denied\n",ttname);
  987.             close(ttyfd); ttyfd = -1;
  988.             debug(F110," Access denied by lock",ttname,0);
  989.  
  990.             return(-3);
  991.         } else lkf = 1;
  992.     }
  993.  
  994. /* Got the line, now set the desired value for local. */
  995.  
  996.     if (*lcl != 0) *lcl = xlocal;
  997.  
  998. /* Request exclusive access on systems that allow it. */
  999.  
  1000. #ifdef TIOCEXCL
  1001.         if (ioctl(ttyfd,TIOCEXCL, NULL) < 0)
  1002.             fprintf(stderr,"Warning, problem getting exclusive access\n");
  1003. #endif
  1004.  
  1005. /* Get tty device settings */
  1006.  
  1007.     ioctl(ttyfd,TCGETA,&ttold);         /* Same deal for Sys III, Sys V */
  1008.     ioctl(ttyfd,TCGETA,&ttraw);
  1009.     ioctl(ttyfd,TCGETA,&tttvt);
  1010.  
  1011.     debug(F101,"ttopen, ttyfd","",ttyfd);
  1012.  
  1013.     debug(F101,"ttopen, ttyfdout","",ttyfdout);
  1014.     /* For DG, also get the tty extended device characteristics. */
  1015.     sys_gechr( channel(ttyfd), (1<<31)|$CLMAX, ch_ttold);
  1016.     sys_gechr( channel(ttyfd), (1<<31)|$CLMAX, ch_ttraw);
  1017.     sys_gechr( channel(ttyfd), (1<<31)|$CLMAX, ch_ttvt);
  1018.  
  1019.     debug(F101," lcl","",*lcl);
  1020.     debug(F111," lock file",flfnam,lkf);
  1021.     return(0);
  1022. }
  1023.  
  1024. /*  T T C L O S  --  Close the TTY, releasing any lock.  */
  1025. int
  1026. ttclos(foo) int foo; {
  1027.     int x = 0;
  1028.  
  1029.     debug(F101,"ttclos ttyfd","",ttyfd);
  1030.     if (ttyfd < 0) return(0);           /* Wasn't open. */
  1031.     if (ttfdflg) return(0);             /* If we got ttyfd from another */
  1032.                                         /* process, don't close it. */
  1033.     tvtflg = 0;
  1034.  
  1035. #ifdef  NETCONN
  1036.     if (netconn) {                      /* Network connection. */
  1037.         debug(F100,"ttclos closing net","",0);
  1038.         netclos();                      /* Close it. */
  1039.         netconn = 0;
  1040.         return(0);
  1041.     }
  1042. #endif  /* NETCONN */
  1043.  
  1044.     if (xlocal) {
  1045.         debug(F100,"ttclos skipping ttunlck for AOS/VS","",0);
  1046.         debug(F100,"ttclos about to call tthang()","",0);
  1047.     }
  1048.     if (ttyfd > 0) {
  1049.                                         /* & timer stuff &  moved closes in */
  1050.         saval = signal(SIGALRM,timerh); /* enable timer */
  1051.         alarm(5);                       /* allow 5 seconds for completion */
  1052.         if (setjmp(sjbuf)) {            /* timer went off */
  1053.             x = -1;                     /* set return value */
  1054.         } else {                        /* what we're really trying to do */
  1055.             if (xlocal) {
  1056.                 if (tthang())           /* Hang up first, then... */
  1057.                     fprintf(stderr,"Warning, problem hanging up the phone\n");
  1058.                 ttres();                /* reset device modes. */
  1059.             }
  1060. #ifdef TIOCEXCL
  1061. #ifdef TIOCNXCL
  1062.            if (ioctl(ttyfd, TIOCNXCL, NULL) < 0)
  1063.                 fprintf(stderr,"Problem relinquishing exclusive access\n");
  1064. #endif
  1065. #endif
  1066.  
  1067.             debug(F101,"ttclos, ttyfd","",ttyfd);
  1068.             debug(F101,"ttclos, ttyfdout","",ttyfdout);
  1069.             fclose(ttfile);                     /* Close it. */
  1070.  
  1071.             /* Close the output tty device */
  1072.             fclose(ttfileout);                  /* Close it. */
  1073.             x = 1;                              /* good return */
  1074.         }
  1075.         ttimoff();                              /* turn off timer */
  1076.         if (x < 0) {
  1077.             fprintf(stderr,"?Timed out closing device: %s\n",ttnmsv);
  1078.             debug(F100,"ttclos timed out","",0);
  1079.         }
  1080.     }
  1081.     ttyfd = -1;                         /* Mark it as closed. */
  1082.     ttyfdout = -1;                      /* Mark it as closed. */
  1083.  
  1084.     debug(F100,"ttclos done","",0);
  1085.     return(0);
  1086. }
  1087.  
  1088. /*  T T H A N G -- Hangup phone line */
  1089.  
  1090. tthang() {
  1091.     unsigned short ttc_save;
  1092.     int x;
  1093.  
  1094.     if (ttyfd < 0) return(0);           /* Not open. */
  1095.     if (xlocal < 1) return(0);
  1096.  
  1097. #ifdef NETCONN
  1098.     if (netconn) {                      /* Network connection. */
  1099.         return ((netclos() < 0) ?  -1 : 1); /* Close it */
  1100.     }
  1101. #endif /* NETCONN */
  1102.  
  1103.     ttc_save = ttraw.c_cflag;
  1104.     ttraw.c_cflag &= ~CBAUD;            /* swa: set baud rate to 0 to hangup */
  1105.     if (ioctl(ttyfd,TCSETAF,&ttraw) < 0) return(-1); /* do it */
  1106.     msleep(100);                        /* let things settle */
  1107.     ttraw.c_cflag = ttc_save;
  1108.     debug(F100, "tthang disconnecting line","",0);
  1109.     if (sys_sechr( channel(ttyfd), (1<<31)|$CLMAX, ch_ttraw)) 
  1110.          { perror("tthang: sechr "); return(-1); }
  1111.     if (ioctl(ttyfd,TCSETAF,&ttraw) < 0) return(-1); /* un-do it */
  1112.     return (0);
  1113. }
  1114.  
  1115.  
  1116. /*  T T R E S  --  Restore terminal to "normal" mode.  */
  1117.  
  1118. ttres() {                               /* Restore the tty to normal. */
  1119.     int x;
  1120.  
  1121.     if (ttyfd < 0) return(-1);          /* Not open. */
  1122.  
  1123.     if (ttfdflg) return(0);             /* Don't mess with terminal modes if */
  1124.                                         /* we got ttyfd from another process */
  1125. #ifdef  NETCONN
  1126.     if (netconn) return (0);            /* Network connection, do nothing */
  1127. #endif  /* NETCONN */
  1128.  
  1129.     x = (ioctl(ttyfd,TCSETAW,&ttold) < 0);       /* restore termio stuff */
  1130.  
  1131.     /* Un-set all the timeouts */
  1132.     if (timotty) {
  1133.          resto(channel(ttyfd));
  1134.          resto(channel(ttyfdout));
  1135.     }
  1136.     if (sys_sechr( channel(ttyfd), (1<<31)|$CLMAX, ch_ttold)) 
  1137.          { perror("ttres: sechr "); return(-1); }
  1138.  
  1139.     return(0);
  1140. }
  1141.  
  1142. /* Exclusive uucp file locking control */
  1143. /*
  1144.  by H. Fischer, creative non-Bell coding !
  1145.  copyright rights for lock modules assigned to Columbia University
  1146. */
  1147.  
  1148. /* The AOS/VS implementation does not use uucp locks.   --ENH */
  1149.  
  1150. static char *
  1151. xxlast(s,c) char *s; char c; {          /* Equivalent to strrchr() */
  1152.     int i;
  1153.     for (i = strlen(s); i > 0; i--)
  1154.         if ( s[i-1] == c ) return( s + (i - 1) );
  1155.     return(NULL);           
  1156. }
  1157. static
  1158. look4lk(ttname) char *ttname; {
  1159.     extern char *strcat(), *strcpy();
  1160.     char *device, *devname;
  1161.     char lockfil[50];                   /* Max length for lock file name */
  1162.     char *lockdir = "/usr/spool/uucp";
  1163.  
  1164.     device = ( (devname=xxlast(ttname,'/')) != NULL ? devname+1 : ttname);
  1165.  
  1166.     strcat( strcpy( lockfil, "LCK.." ), device );
  1167.  
  1168.     if (access( lockdir, 04 ) < 0) {    /* read access denied on lock dir */
  1169.         fprintf(stderr,"Warning, read access to lock directory denied\n");
  1170.         return( 1 );                    /* cannot check or set lock file */
  1171.     }
  1172.         
  1173.     strcat(strcat(strcpy(flfnam,lockdir),"/"), lockfil);
  1174.     debug(F110,"look4lk",flfnam,0);
  1175.  
  1176.     if ( ! access( flfnam, 00 ) ) {     /* print out lock file entry */
  1177.         char lckcmd[40] ;
  1178.         strcat( strcpy(lckcmd, "ls -l ") , flfnam);
  1179.         system(lckcmd);
  1180.         if (access(flfnam,02) == 0)
  1181.             printf("(You may type \"! rm %s\" to remove this file)\n",flfnam);
  1182.         return( -1 );
  1183.     }
  1184.     if ( access( lockdir, 02 ) < 0 ) {  /* lock file cannot be written */
  1185.         fprintf(stderr,"Warning, write access to lock directory denied\n");
  1186.         return( 1 );
  1187.     }
  1188.  
  1189.     return( 0 );                        /* okay to go ahead and lock */
  1190. }
  1191.  
  1192. /*  T T L O C K  */
  1193.  
  1194.  
  1195. static
  1196. ttlock(ttyfd) char *ttyfd; {            /* lock uucp if possible */
  1197.  
  1198. #ifdef datageneral
  1199.     /* The Data General locks a device when that device is opened.  So
  1200.      * return that the device is already locked.
  1201.      * Besides, because of internal multi-tasking, locking the device by
  1202.      * the ?ASSIGN call or an $IEXO flag would cause problem for the task
  1203.      * id that did not open the device first.
  1204.      */
  1205. #else datageneral
  1206.     int lck_fil, l4l;
  1207.     int pid_buf = getpid();             /* pid to save in lock file */
  1208.         
  1209.     haslock = 0;                        /* not locked yet */
  1210.     l4l = look4lk(ttyfd);
  1211.     if (l4l < 0) return (-1);           /* already locked */
  1212.     if (l4l == 1) return (0);           /* can't read/write lock directory */
  1213.     lck_fil = creat(flfnam, 0444);      /* create lock file ... */
  1214.     if (lck_fil < 0) return (-1);       /* create of lockfile failed */
  1215.                 /* creat leaves file handle open for writing -- hf */
  1216.     write (lck_fil, &pid_buf, sizeof(pid_buf) ); /* uucp expects int in file */
  1217.     close (lck_fil);
  1218. #endif datageneral
  1219.     haslock = 1;                        /* now is locked */
  1220.     return(0);
  1221. }
  1222.  
  1223. /*  T T U N L O C K  */
  1224.  
  1225. static
  1226. ttunlck() {                             /* kill uucp lock if possible */
  1227. #ifdef datageneral
  1228.     /* The DG automatically unlocks the device when it is closed, or when
  1229.      * the process is terminated for any reason.  Unlocking is not needed.
  1230.      * Also, see the note for ttlock().
  1231.      */
  1232.     return(0);
  1233. #else
  1234.     if (haslock) return( unlink( flfnam ) ); 
  1235. #endif
  1236.  
  1237. }
  1238.  
  1239. /*  T T P K T  --  Condition the communication line for packets. */
  1240. /*              or for modem dialing */
  1241.  
  1242. #define DIALING 4               /* flags (via flow) for modem handling */
  1243. #define CONNECT 5
  1244.  
  1245. /*  If called with speed > -1, also set the speed.  */
  1246.  
  1247. /*  Returns 0 on success, -1 on failure.  */
  1248.  
  1249. ttpkt(speed,xflow,parity) long speed; int xflow, parity; {
  1250.     int s2;
  1251.     int s = -1;
  1252.     int x;
  1253.     extern int flow;                    /* REAL flow-control setting */
  1254.  
  1255.     if (ttyfd < 0) return(-1);          /* Not open. */
  1256.  
  1257.     debug(F101,"ttpkt parity","",parity);
  1258.     debug(F101,"ttpkt xflow","",xflow);
  1259.     debug(F101,"ttpkt speed","",(int) speed);
  1260.  
  1261.     ttprty = parity;                    /* Let other tt functions see these. */
  1262.     ttpflg = 0;                         /* Parity not sensed yet */
  1263.     ttpmsk = ttprty ? 0177 : 0377;      /* Parity stripping mask */
  1264.     ttspeed = speed;
  1265.  
  1266. #ifdef NETCONN                          /* Nothing to do for telnet */
  1267.     if (netconn) return (0);
  1268. #endif /* NETCONN */
  1269.  
  1270.     if (ttfdflg && !isatty(ttyfd)) return(0);
  1271.  
  1272.     if (xflow != FLO_DIAL && xflow != FLO_DIAX)
  1273.       ttflow = xflow;                   /* Now make this available too. */
  1274.  
  1275.     if (xlocal) {
  1276.         s2 = (int) (speed / 10L);       /* convert bps to cps */
  1277.         s = ttsspd(s2);                 /* get associated speed */
  1278.         if (s < 0)
  1279.             return(-1);
  1280.         /* carrctl() call here in UNIX code */  
  1281.     }
  1282.                                         
  1283. #ifdef UXIII
  1284.     if (flow == FLO_XONX) ttraw.c_iflag |= (IXON|IXOFF);
  1285.     else if (flow == FLO_NONE) ttraw.c_iflag &= ~(IXON|IXOFF);
  1286.     else if (flow == FLO_KEEP) {
  1287.         ttraw.c_iflag &= ~(IXON|IXOFF);
  1288.         ttraw.c_iflag |= (ttold.c_iflag & (IXON|IXOFF));
  1289.     } else if (flow == FLO_RTSC) {
  1290.         /* RTS/CTS Flow control... */
  1291. #ifdef RTSXOFF
  1292.         /* This is the preferred way, according to SVID R4 */
  1293.         if (ioctl(ttyfd,TCGETX,&rctsx) > -1) {
  1294.             rctsx.x_hflag |= RTSXOFF | CTSXON;
  1295.             ioctl(ttyfd,TCSETX,&rctsx); /* Ignore errors for now. */
  1296.         }
  1297. #else
  1298. #ifdef CRTSCTS
  1299.         /* Found this one in <termios.h> */
  1300.         ttraw.c_iflag |= CRTSCTS;
  1301. #endif /* CRTSCRS */
  1302. #endif /* RTSXOFF */
  1303.     }
  1304.     if (flow == FLO_DTRC) {
  1305.         /* DTR/CD Flow control... */
  1306. #ifdef DTRXOFF
  1307.         /* This is straight out of SVID R3 */
  1308.         if (ioctl(ttyfd,TCGETX,&rctsx) > -1) {
  1309.             rctsx.x_hflag |= DTRXOFF | CDXON;
  1310.             ioctl(ttyfd,TCSETX,&rctsx); /* Ignore errors. */
  1311.         }
  1312. #endif /* DTRXOFF */
  1313.     }
  1314.     if (flow == DIALING)  ttraw.c_cflag |= CLOCAL|HUPCL;
  1315.     if (flow == CONNECT)  ttraw.c_cflag &= ~CLOCAL;
  1316.  
  1317.     ttraw.c_lflag &= ~(ICANON|ECHO);
  1318.     ttraw.c_lflag &= ~ISIG;
  1319.     ttraw.c_lflag |= NOFLSH;            /* Don't flush */
  1320.     ttraw.c_iflag |= (BRKINT|IGNPAR);
  1321.     ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|INPCK|ISTRIP|IXANY);
  1322.     ttraw.c_oflag &= ~OPOST;
  1323. #ifdef datageneral
  1324.     ttraw.c_lflag &= ~CSETPM;      /* No DG page mode */
  1325. #endif
  1326.     ttraw.c_cc[4] = 1;
  1327.     ttraw.c_cflag &= ~(CSIZE|PARENB);
  1328.     ttraw.c_cflag |= (CS8|CREAD);
  1329.     ttraw.c_cc[5] = 0;
  1330.  
  1331. #ifdef VINTR                            /* Turn off interrupt character */
  1332.     if (xlocal == 0)                    /* so ^C^C can break us out of */
  1333.       ttraw.c_cc[VINTR] = 0;            /* packet mode. */
  1334. #endif /* VINTR */
  1335.  
  1336.     if (s > -1) {
  1337.         ttraw.c_cflag &= ~CBAUD;
  1338.         ttraw.c_cflag |= s;             /* set speed */
  1339.     }
  1340.  
  1341.     if (ioctl(ttyfd,TCSETAW,&ttraw) < 0) return(-1);  /* set new modes . */
  1342. #ifdef datageneral
  1343.     if (flow == FLO_XONX) {
  1344.          dgsetflow(channel(ttyfdout));
  1345.          dgsetflow(channel(ttyfd));
  1346.     }
  1347.     if (flow == FLO_NONE) {
  1348.          resflow(channel(ttyfdout));
  1349.          resflow(channel(ttyfd));
  1350.     }
  1351.     /* if flow is FLO_KEEP, don't do anything */
  1352.     if (sys_gechr( channel(ttyfd), (1<<31)|$CLMAX, ch_ttraw)) 
  1353.          { perror("ttpkt: gechr: "); return(-1); }
  1354. #endif
  1355.  
  1356.     if (flow == DIALING) {
  1357. #ifdef datageneral
  1358. #ifndef aosvs
  1359.         if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0)) < 0 )
  1360.                 return(-1);
  1361. #endif
  1362. #else
  1363.         if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY) < 0 )
  1364.                 return(-1);
  1365.         close( open(ttnmsv,2) );        /* magic to force mode change!!! */
  1366. #endif
  1367.         }
  1368.  
  1369. #endif
  1370.  
  1371. #ifdef COMMENT
  1372.     ttflui();                           /* Flush any pending input */
  1373. #endif /* COMMENT */
  1374.     tvtflg = 0;
  1375.     return(0);
  1376. }
  1377.  
  1378. /*  T T V T -- Condition communication line for use as virtual terminal  */
  1379.  
  1380. ttvt(speed,flow) int speed, flow; {
  1381.     int s, s2;
  1382.  
  1383.     debug(F101,"ttvt ttyfd","",ttyfd);
  1384.     debug(F101,"ttvt tvtflg","",tvtflg);
  1385.     debug(F101,"ttvt speed","",speed);
  1386.  
  1387.     if (ttyfd < 0) return(-1);          /* Not open. */
  1388.  
  1389. #ifdef NETCONN
  1390.     if (netconn) {
  1391.         tvtflg = 1;                     /* Network connections */
  1392.         return(0);                      /* require no special setup */
  1393.     }
  1394. #endif /* NETCONN */
  1395.  
  1396.     if (tvtflg != 0 && speed == ttspeed && flow == ttflow && ttcarr == curcarr)
  1397.       return(0);                        /* Already been called. */
  1398.  
  1399.     if (ttfdflg && !isatty(ttyfd)) return(0);
  1400.  
  1401.     if (xlocal) {
  1402.         s2 = (int) (speed / 10L);       /* convert bps to cps */
  1403.         s = ttsspd(s2);                 /* Check the speed */
  1404.         /* ENH - UNIX has call to carrctl here */
  1405.     }
  1406.     if (flow == FLO_XONX) tttvt.c_iflag |= (IXON|IXOFF);
  1407.     else if (flow == FLO_KEEP) {
  1408.         tttvt.c_iflag &= ~(IXON|IXOFF); /* Turn off Xon/Xoff flags */
  1409.         tttvt.c_iflag |= (ttold.c_iflag & (IXON|IXOFF)); /* OR in old ones */
  1410.     }else if (flow == FLO_NONE) tttvt.c_iflag &= ~(IXON|IXOFF);
  1411.  
  1412.     if (flow == DIALING)  tttvt.c_cflag |= CLOCAL|HUPCL;
  1413.     if (flow == CONNECT)  tttvt.c_cflag &= ~CLOCAL;
  1414.  
  1415.     tttvt.c_lflag &= ~(ISIG|ICANON|ECHO);
  1416.     tttvt.c_iflag |= (IGNBRK|IGNPAR);
  1417.     tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|IUCLC|BRKINT|INPCK|ISTRIP|IXANY);
  1418.     tttvt.c_oflag &= ~OPOST;
  1419.     tttvt.c_cflag &= ~(CSIZE|PARENB);
  1420.     tttvt.c_cflag |= (CS8|CREAD);
  1421.     tttvt.c_cc[4] = 1;
  1422.     tttvt.c_cc[5] = 0;
  1423.  
  1424.     if (s > -1) {
  1425.         tttvt.c_cflag &= ~CBAUD;
  1426.         tttvt.c_cflag |= s; /* set speed */
  1427.     }
  1428.  
  1429.     if (ioctl(ttyfd,TCSETAW,&tttvt) < 0) return(-1);  /* set new modes . */
  1430.  
  1431. #ifdef datageneral
  1432.     if (flow == FLO_XONX) {
  1433.          dgsetflow(channel(ttyfdout));
  1434.          dgsetflow(channel(ttyfd));
  1435.     }
  1436.     if (flow == FLO_NONE) {
  1437.          resflow(channel(ttyfdout));
  1438.          resflow(channel(ttyfd));
  1439.     }
  1440.     if (sys_gechr( channel(ttyfd), (1<<31)|$CLMAX, ch_ttvt)) 
  1441.          { perror("ttvt: gechr: "); return(-1); }
  1442. #endif
  1443.  
  1444.     if (flow == DIALING) {
  1445. #ifdef datageneral
  1446. #ifndef aosvs
  1447.         if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0)) < 0 )
  1448.                 return(-1);
  1449. #endif
  1450. #else
  1451.         if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY) < 0 )
  1452.                 return(-1);
  1453.         close( open(ttnmsv,2) );        /* magic to force mode change!!! */
  1454. #endif
  1455.         }
  1456.  
  1457.     ttspeed = speed;                    /* Done, remember how we were */
  1458.     ttflow = flow;                      /* called, so we can decide how to */
  1459.     tvtflg = 1;                         /* respond next time. */
  1460.  
  1461.     debug(F101,"ttvt done","",tvtflg);
  1462.     return(0);
  1463. }
  1464.  
  1465. /*  T T S S P D  --  Return the internal baud rate code for 'speed'.  */
  1466.  
  1467. ttsspd(cps) {
  1468.     int s,s2,spdok;
  1469.  
  1470.     debug(F101,"ttsspd","",cps);
  1471.  
  1472. #ifdef  NETCONN
  1473.     if (netconn) return (0);
  1474. #endif  /* NETCONN */
  1475.  
  1476.     if (cps < 0) return(-1);
  1477.         spdok = 1;                      /* Assume arg ok */
  1478.         switch (cps) {
  1479.             case 0:   s = B0;    break; /* Just the common ones. */
  1480.             case 11:  s = B110;  break; /* The others from ttydev.h */
  1481.             case 15:  s = B150;  break; /* could also be included if */
  1482.             case 30:  s = B300;  break; /* necessary... */
  1483.             case 60:  s = B600;  break;
  1484.             case 120: s = B1200; break;
  1485.             case 180: s = B1800; break;
  1486.  
  1487.             case 240: s = B2400; break;
  1488.             case 480: s = B4800; break;
  1489.             case 960: s = B9600; break;
  1490. #ifdef datageneral
  1491.             /* ioctl() allows other speeds */
  1492.             case 5:     s = B50; break;
  1493.             case 7:     s = B75; break;
  1494.             case 13:    s = B134; break;
  1495.             case 360:   s = B3600; break;
  1496.             case 720:   s = B7200; break;
  1497.             case 1920:  s = B19000; break;
  1498.  
  1499.             /* Some speeds are supported by the hardware thru PMGR.
  1500.                We don't bother about 45.5 but it could be added.
  1501.             */
  1502.             case 38400:  if (setspeed($CR38K)) spdok = 0; s = 0; break;
  1503. #endif
  1504.             default:
  1505.                 spdok = 0;
  1506.                 fprintf(stderr,"Unsupported line speed - %d\n",cps * 10);
  1507.                 fprintf(stderr,"Current speed not changed\n");
  1508.                 break;
  1509.         }           
  1510.         if (spdok)
  1511.             return(s);
  1512.         else
  1513.             return(-1);
  1514.  }
  1515.  
  1516. /*  T T S C A R R  --  Set ttcarr variable, controlling carrier handling.
  1517.  *
  1518.  *  0 = Off: Always ignore carrier. E.g. you can connect without carrier.
  1519.  *  1 = On: Heed carrier, except during dialing. Carrier loss gives disconnect.
  1520.  *  2 = Auto: For "modem direct": The same as "Off".
  1521.  *            For real modem types: Heed carrier during connect, but ignore
  1522.  *                it anytime else.  Compatible with pre-5A C-Kermit versions.
  1523.  *
  1524.  * As you can see, this setting does not affect dialing, which always ignores
  1525.  * carrier (unless there is some special exception for some modem type).  It
  1526.  * does affect ttopen() if it is set before ttopen() is used.  This setting
  1527.  * takes effect on the next call to ttopen()/ttpkt()/ttvt().  And they are
  1528.  * (or should be) always called before any communications is tried, which
  1529.  * means that, practically speaking, the effect is immediate.
  1530.  *
  1531.  * Of course, nothing of this applies to remote mode (xlocal = 0).
  1532.  *
  1533.  * Someone has yet to uncover how to manipulate the carrier in the BSD
  1534.  * environment (or any non-termio using environment).  Until that time, this
  1535.  * will simply be a no-op for BSD.
  1536.  *
  1537.  * Note that in previous versions, the carrier was most often left unchanged
  1538.  * in ttpkt()/ttvt() unless they were called with DIALING or CONNECT.  This
  1539.  * has changed.  Now it is controlled by ttcarr in conjunction with these
  1540.  * modes.
  1541.  */
  1542. int
  1543. ttscarr(carrier) int carrier; {
  1544.     ttcarr = carrier;
  1545.     debug(F101, "ttscarr","",ttcarr);
  1546.     return(ttcarr);
  1547. }
  1548.  
  1549. int
  1550. ttgmdm() {                              /* Read modem signals */
  1551.     return(-3);                         /* ENH - return value of -3 means */
  1552. }                                       /* not implemented, which it's not */
  1553.                                         /* because this can't (easily) be */
  1554.                                         /* done in AOS/VS */
  1555.  
  1556. int
  1557. ttwmdm(mdmsig,timo) int mdmsig,timo; {  /* wait timo seconds for specified */
  1558.     return(-3);                         /* modem signals to appear */
  1559. }
  1560.  
  1561.  
  1562. long
  1563. ttgspd() {                              /* Get line speed */
  1564.     P_CHAR_EX   cp;                     /* characteristics packet */
  1565.     int         ac0,ac1,ac2,error;
  1566.     static int  baud_rate[] = {
  1567.                     50,75,110,134,150,300,600,1200,1800,2000,2400,3600,4800,
  1568.                     7200,9600,19200},
  1569.                 baud_rate_x[] = {45,38400};
  1570.  
  1571. #ifdef NETCONN
  1572.     if (netconn) return (-1);
  1573. #endif /* NETCONN */
  1574.  
  1575.     if (ttyfd < 0)
  1576.         return (-1);
  1577.     else {
  1578.         ac0 = channel(ttyfd);
  1579.         ac1 = $CLMAX | BIT0;
  1580.         ac2 = (P_CHAR_EX *) &cp;
  1581.         error = sys($GECHR,&ac0,&ac1,&ac2);
  1582.         if (error)
  1583.             return(-1);
  1584.  
  1585.         if (cp.char_br0bit == 0)
  1586.             return(baud_rate[cp.char_br_1_4]);
  1587.         else
  1588.             return(baud_rate_x[cp.char_br_1_4]);
  1589.     }
  1590. }
  1591.  
  1592. int
  1593. psuspend() {                            /* ENH - not possible in VS */
  1594.     return(-1);
  1595. }
  1596.  
  1597. /* Interrupt Functions */
  1598.  
  1599. /* Set up terminal interrupts on console terminal */
  1600.  
  1601. #ifdef UXIII
  1602. esctrp() {                              /* trap console escapes (^\) */
  1603.  
  1604.     conesc = 1;
  1605.     signal(SIGQUIT,SIG_IGN);            /* ignore until trapped */
  1606. }
  1607. #endif
  1608.  
  1609. /*  C O N I N T  --  Console Interrupt setter  */
  1610. VOID
  1611. conint(f,s) SIGTYP (*f)(), (*s)(); {    /* Set an interrupt trap. */
  1612.  
  1613.     if (!isatty(0)) {                   /* only for real ttys */
  1614.         debug(F101,"conint not a tty","",isatty(0));
  1615.         return;
  1616.     }
  1617.     if (backgrd) {                      /* must ignore signals in bkgrd */
  1618.         debug(F101,"conint backgrd ignoring signals","",backgrd);
  1619.         return;
  1620.     } else
  1621.       debug(F101,"conint foreground catching signals","",0);
  1622. /*
  1623.  Except for special cases below, ignore keyboard quit signal.
  1624.  ^\ too easily confused with connect escape, and besides, we don't want
  1625.  to leave lock files around.  (Frank Prindle)
  1626. */
  1627. #ifdef datageneral
  1628.     /* Set up the asynchronous task to read the console. 
  1629.      * But, I don't want them set up all the time, so I will kludge up the
  1630.      * call in  chkint() (ckuus3.c) to see if this asynch task is running:
  1631.      * conint_mt()
  1632.      */
  1633. #endif
  1634.     signal(SIGQUIT,SIG_IGN);
  1635.  
  1636. #ifdef UXIII
  1637.     signal(SIGQUIT,esctrp);             /* console escape in pkt modes */
  1638.     if (conesc) {                       /* clear out pending escapes */
  1639.         conesc = 0;
  1640.     }
  1641. #endif
  1642.  
  1643.     if (conif) return;                  /* Nothing to do if already on. */
  1644.  
  1645. /* check if invoked in background -- if so signals set to be ignored */
  1646.  
  1647.     if (signal(SIGINT,SIG_IGN) == SIG_IGN) {
  1648.         backgrd = 1;                    /*   means running in background */
  1649. #ifdef UXIII
  1650.         signal(SIGQUIT,SIG_IGN);        /*   must leave signals ignored */
  1651. #endif
  1652.         return;
  1653.     }
  1654.     signal(SIGINT,f);                   /* Function to trap to on interrupt. */
  1655.     signal(SIGHUP,f);                   /* Or hangup, so lock file cleared. */
  1656.     conif = 1;                          /* Flag console interrupts on. */
  1657. }
  1658.  
  1659.  
  1660. /*  C O N N O I  --  Reset console terminal interrupts */
  1661.  
  1662. connoi() {                              /* Console-no-interrupts */
  1663.  
  1664.     if (!isatty(0)) return(0);          /* only for real ttys */
  1665.     if (backgrd) return;                /* Ignore signals in background */
  1666.  
  1667. #ifdef datageneral
  1668.     /* Terminate the asynchronous task that reads the console for
  1669.      * interrupt characters. 
  1670.      * But, I don't want to kill this task all the time, so I will kludge 
  1671.      * up the call in input() (ckcfn2.c) to kill the asynch task if it
  1672.      * is running: connoi_mt()
  1673.      */
  1674. #endif
  1675.     signal(SIGINT,SIG_DFL);
  1676.     signal(SIGHUP,SIG_DFL);
  1677.     signal(SIGQUIT,SIG_DFL);
  1678.     conif = 0;                          /* Flag interrupt trapping off */
  1679. }
  1680.  
  1681. #ifdef datageneral
  1682. /* C O N I N T _ M T  -- Asynch read console task */
  1683.  
  1684. void conint_mt() {
  1685.     int count = 0;
  1686.  
  1687.     /* Any input waiting? */
  1688.     con_reads_mt = 1;                   /* Flag that task is active */
  1689.     conint_avl = 0;                     /* Flag that interrupt gotten */
  1690.     while (con_reads_mt)
  1691.         if ((conint_ch = coninc(2)) > 0) { /* If character at keyboard */
  1692.             conint_avl = 1;             /* we set the flag */
  1693.             while ((conint_avl) && (++count <= 5))
  1694.                 sleep(1);               /* & wait for char to be processed */
  1695.         }
  1696.         count = 0;                      /* initialize counter */
  1697.         conint_avl = 0;
  1698. }
  1699.  
  1700.  
  1701. /* C O N N O I _ M T  -- Kill asynch read console task */
  1702.  
  1703. connoi_mt() {
  1704.     conint_avl = 0;
  1705.     if (con_reads_mt) {
  1706.         con_reads_mt = 0;
  1707.         midkill(CONINT_TSK);
  1708.     }
  1709. }
  1710.  
  1711.  
  1712. /* C O N S T A _ M T  --  Start the console asynch read task */
  1713.  
  1714. consta_mt() {
  1715.     if ((con_reads_mt == 0)      /* Not already running */
  1716.      && (mtask(conint_mt, CONINT_STACK, CONINT_TSK, CONINT_PRI) != 0))
  1717.         perror("consta_mt: Can't initiate task:");
  1718. }
  1719. #endif datageneral
  1720.  
  1721. /* Private buffer for myread() and its companions.  Not for use by anything
  1722.  * else.  ttflui() is allowed to reset them to initial values.  ttchk() is
  1723.  * allowed to read my_count.
  1724.  *
  1725.  * my_item is an index into mybuf[].  Increment it *before* reading mybuf[].
  1726.  *
  1727.  * A global parity mask variable could be useful too.  We could use it to
  1728.  * let myread() strip the parity on its own, instead of stripping sign
  1729.  * bits as it does now.
  1730.  */
  1731.  
  1732. #define MYBUFLEN 256
  1733. #define PEEKTYPE long
  1734. static CHAR mybuf[MYBUFLEN];            /* Buffer, including push back */
  1735. static int my_count = 0;                /* Number of chars still in mybuf */
  1736. static int my_item = -1;                /* Last index read from mybuf[] */
  1737.  
  1738. /* myread() -- Efficient read of one character from communications line.
  1739.  *
  1740.  * Uses a private buffer to minimize the number of expensive read() system
  1741.  * calls.  Essentially performs the equivalent of read() of 1 character, which
  1742.  * is then returned.  By reading all available input from the system buffers
  1743.  * to the private buffer in one chunk, and then working from this buffer, the
  1744.  * number of system calls is reduced in any case where more than one character
  1745.  * arrives during the processing of the previous chunk, for instance high
  1746.  * baud rates or network type connections where input arrives in packets.
  1747.  * If the time needed for a read() system call approaches the time for more
  1748.  * than one character to arrive, then this mechanism automatically compensates
  1749.  * for that by performing bigger read()s less frequently.  If the system load
  1750.  * is high, the same mechanism compensates for that too.
  1751.  *
  1752.  * myread() is a macro that returns the next character from the buffer.  If the
  1753.  * buffer is empty, mygetbuf() is called.  See mygetbuf() for possible error
  1754.  * returns.
  1755.  *
  1756.  * This should be efficient enough for any one-character-at-a-time loops.
  1757.  * For even better efficiency you might use memcpy()/bcopy() or such between
  1758.  * buffers (since they are often better optimized for copying), but it may not
  1759.  * be worth it if you have to take an extra pass over the buffer to strip
  1760.  * parity and check for CTRL-C anyway.
  1761.  *
  1762.  * Note that if you have been using myread() from another program module, you
  1763.  * may have some trouble accessing this macro version and the private variables
  1764.  * it uses.  In that case, just add a function in this module, that invokes the
  1765.  * macro.
  1766.  */
  1767.  
  1768. #define myread()  (--my_count < 0 ? mygetbuf() : 255 & (int)mybuf[++my_item])
  1769.  
  1770.  
  1771. /* not used right now */
  1772. /*
  1773. myunrd(ch) CHAR ch; {
  1774.     ungotn = ch;
  1775. }
  1776. */
  1777.  
  1778. /* mygetbuf() -- Fill buffer for myread() and return first character.
  1779.  *
  1780.  * This function is what myread() uses when it can't get the next character
  1781.  * directly from its buffer.  First, it calls a system dependent myfillbuf()
  1782.  * to read at least one new character into the buffer, and then it returns
  1783.  * the first character just as myread() would have done.  This function also
  1784.  * is responsible for all error conditions that myread() can indicate.
  1785.  *
  1786.  * Returns: When OK     => a positive character, 0 or greater.
  1787.  *          When EOF    => -2.
  1788.  *          When error  => -3, error code in errno.
  1789.  *
  1790.  * Older myread()s additionally returned -1 to indicate that there was nothing
  1791.  * to read, upon which the caller would call myread() again until it got
  1792.  * something.  The new myread()/mygetbuf() always gets something.  If it
  1793.  * doesn't, then make it do so!  Any program that actually depends on the old
  1794.  * behaviour will break.
  1795.  *
  1796.  * The older version also used to return -2 both for EOF and other errors,
  1797.  * and used to set errno to 9999 on EOF.  The errno stuff is gone, EOF and
  1798.  * other errors now return different results, although Kermit currently never
  1799.  * checks to see which it was.  It just disconnects in both cases.
  1800.  *
  1801.  * Kermit lets the user use the quit key to perform some special commands
  1802.  * during file transfer.  This causes read(), and thus also mygetbuf(), to
  1803.  * finish without reading anything and return the EINTR error.  This should
  1804.  * be checked by the caller.  Mygetbuf() could retry the read() on EINTR,
  1805.  * but if there is nothing to read, this could delay Kermit's reaction to
  1806.  * the command, and make Kermit appear unresponsive.
  1807.  *
  1808.  * The debug() call should be removed for optimum performance.
  1809.  */
  1810. int
  1811. mygetbuf() {
  1812.     my_count = myfillbuf();                     
  1813.     /* debug(F101, "myfillbuf read", "", my_count); */
  1814.     if (my_count <= 0)
  1815.       return(my_count < 0 ? -3 : -2);
  1816.     --my_count;
  1817.     return(255 & (int)mybuf[my_item = 0]);
  1818. }
  1819.  
  1820. /* myfillbuf():
  1821.  * System-dependent read() into mybuf[], as many characters as possible.
  1822.  *
  1823.  * Returns: OK => number of characters read, always more than zero.
  1824.  *          EOF => 0
  1825.  *          Error => -1, error code in errno.
  1826.  *
  1827.  * If there is input available in the system's buffers, all of it should be
  1828.  * read into mybuf[] and the function return immediately.  If no input is
  1829.  * available, it should wait for a character to arrive, and return with that
  1830.  * one in mybuf[] as soon as possible.  It may wait somewhat past the first
  1831.  * character, but be aware that any such delay lengthens the packet turnaround
  1832.  * time during kermit file transfers.  Should never return with zero characters
  1833.  * unless EOF or irrecoverable read error.
  1834.  *
  1835.  * Correct functioning depends on the correct tty parameters being used.
  1836.  * Better control of current parameters is required than may have been the
  1837.  * case in older Kermit releases.  For instance, O_NDELAY (or equivalent) can
  1838.  * no longer be sometimes off and sometimes on like it used to, unless a
  1839.  * special myfillbuf() is written to handle that.  Otherwise the ordinary
  1840.  * myfillbuf()s may think they have come to EOF.
  1841.  *
  1842.  * If your system has a facility to directly perform the functioning of
  1843.  * myfillbuf(), then use it.  If the system can tell you how many characters
  1844.  * are available in its buffers, then read that amount (but not less than 1).
  1845.  * If the system can return a special indication when you try to read without
  1846.  * anything to read, while allowing you to read all there is when there is
  1847.  * something, you may loop until there is something to read, but probably that
  1848.  * is not good for the system load.
  1849.  */
  1850. int
  1851. myfillbuf() {
  1852.     int n;
  1853.     int retry_count = 5;                        /* max # of retries */
  1854.  
  1855. #ifdef NETCONN
  1856.     if (netconn) {
  1857.         n = read(ttyfd, mybuf, sizeof(mybuf));
  1858.         if (n <= 0)
  1859.       debug(F101,"myfillbuf() got error reading from network, ","",n);
  1860.         return(n);
  1861.     } else {                                      /* console read */
  1862. #endif /* NETCONN */
  1863.         while (1) {
  1864.             n = dgncinb(ttyfd, mybuf, sizeof(mybuf));
  1865.             if (n > 0) {
  1866.                 return(n);
  1867.             }
  1868.             if ((n == -EROVR) || (n == -1) || (n == -2) || (n == 0)) {
  1869.                 if (n == -EROVR)
  1870.                     debug(F101,"myfillbuf() got data overrun ind., ","",-n);
  1871.                 else if (n == -1)
  1872.                     debug(F101,"myfillbuf() got EOF ind., ","",n);
  1873.                 else if (n == -2)
  1874.                     debug(F101,"myfillbuf() got device timeout ind., ","",n);
  1875.                 else
  1876.                     debug(F101,"myfillbuf() got zero characters, ","",n);
  1877.                 if (--retry_count > 0) {
  1878.                     debug(F101,"myfillbuf() tries remaining, ","",retry_count);
  1879.                     sleep(1);   /* keep trying on data over- */
  1880.                     continue;   /* run, EOF (-1), timeout (-2) & 0 */
  1881.                 } 
  1882.             } else if (n < -2)                  /* VS errors complimented */
  1883.                 debug(F101,"myfillbuf() got AOS/VS error ","",-n);
  1884.             if (n == -1)                        /* EOF is -1, but caller */
  1885.                 n = 0;                          /* wants it to be zero   */
  1886.             else n = -1;                        /* all others -1 */
  1887.             return(n);
  1888.         }
  1889. #ifdef NETCONN
  1890.     }
  1891. #endif /* NETCONN */
  1892.  
  1893. /*  T T C H K  --  Tell how many characters are waiting in tty input buffer  */
  1894.  
  1895. ttchk() {
  1896.     return(in_chk(ttyfd));
  1897. }
  1898.  
  1899. /*  T T F L U I  --  Flush tty input buffer */
  1900.  
  1901. ttflui() {
  1902.     int ffd;
  1903.  
  1904. #ifndef UXIII
  1905.     long n;
  1906. #endif
  1907.  
  1908. #ifdef TTLEBUF
  1909.     ttpush = -1;            /* Clear the peek-ahead char */
  1910.     while (le_data && (le_inbuf() > 0)) {
  1911.         CHAR ch = '\0';
  1912.         if (le_getchar(&ch) > 0) {
  1913.             debug(F101,"ttflui le_inbuf ch","",ch);
  1914.         }
  1915.     }
  1916. #endif /* TTLEBUF */
  1917.  
  1918.     my_count = 0;                       /* Initialize myread() stuff */
  1919.     my_item = -1;
  1920.  
  1921. #ifdef NETCONN
  1922.     if (netconn) return(netflui());
  1923. #endif /* NETCONN */
  1924.  
  1925.     ffd = xlocal ? ttyfd : 0;           /* If not local, use stdin */
  1926.     debug(F101,"ttflui xlocal","",xlocal);
  1927.     debug(F101,"ttflui ttyfd","",ttyfd);
  1928.     debug(F101,"ttflui ffd","",ffd);
  1929.  
  1930.     if (ffd < 0) return(-1);            /* Not open. */
  1931.     
  1932.  
  1933. #ifdef UXIII
  1934. #ifdef datageneral
  1935.     /* Since $ESGT is turned on in the sys_read packets, there is never a need
  1936.      * to flush the input buffer -- the system automatically does it each time
  1937.      * a read is issued.
  1938.      */
  1939. #endif
  1940. #endif
  1941.  
  1942.     return(0);
  1943. }
  1944.  
  1945. int
  1946. ttfluo() {                              /* Flush output buffer - dummy */
  1947.     return(0);                          /* POSIX is only implementation */
  1948. }                                       /* that needs this */
  1949.  
  1950.  
  1951. /*  T T X I N  --  Get n characters from tty input buffer  */
  1952.  
  1953. /*  Returns number of characters actually gotten, or -1 on failure  */
  1954.  
  1955. /*  Intended for use only when it is known that n characters are actually */
  1956. /*  Available in the input buffer.  */
  1957.  
  1958. ttxin(n,buf) int n; CHAR *buf; {
  1959.     int i = 0, c = -2, x = 0;
  1960.  
  1961. #ifdef TTLEBUF
  1962.     if (ttpush >= 0) {
  1963.         buf[0] = ttpush;        /* Put pushed char in buffer*/
  1964.         ttpush = -1;            /* Clear the push buffer */
  1965.         if (ttchk() > 0)
  1966.       return(ttxin(n-1, &buf[1]) + 1);
  1967.         else 
  1968.       return(1);
  1969.     }
  1970.     if (le_data) {
  1971.         while (le_inbuf() > 0) {
  1972.         if (le_getchar(&buf[i])) {
  1973.                 i++;
  1974.                 n--;
  1975.             }
  1976.         }
  1977.         if (ttchk() > 0)
  1978.       return(ttxin(n,&buf[i])+i);
  1979.         else 
  1980.       return(i);
  1981.     }
  1982. #endif /* TTLEBUF */
  1983.  
  1984.     ttpmsk = (ttprty) ? 0177: 0377;             /* parity stripping mask */
  1985.     debug(F101,"ttxin: n","",n);
  1986.  
  1987.     for( x = 0; (x > -1) && (x < n) && (c = myread()) >= 0; )
  1988.       buf[x++] = c & ttpmsk;
  1989.  
  1990.     debug(F101," x","",x);                      
  1991.     for (c = 0; c < n; c++)
  1992.         buf[c] &= ttpmsk;
  1993.     if (x > 0) buf[x] = '\0';
  1994.     else if (x < 0) x = -1;
  1995.     return(x);
  1996. }
  1997.  
  1998. #define TTOLMAXT 5
  1999.  
  2000. /*  T T O L  --  Similar to "ttinl", but for writing.  */
  2001.  
  2002. ttol(s,n) int n; char *s; {
  2003.     int x,len,tries,outfd;
  2004.  
  2005. #ifdef NETCONN
  2006.     if (netconn) {
  2007.         if (ttyfd < 0) return (-1);
  2008.     } else
  2009. #endif /* NETCONN */
  2010.     if (ttyfdout < 0) return (-1);
  2011.  
  2012.     debug(F101,"ttol n","",n);
  2013.     tries = TTOLMAXT;
  2014.     len = n;
  2015.  
  2016.     while ((n > 0) && (tries-- > 0)) {
  2017.         debug(F101,"ttol try","",TTOLMAXT - tries);
  2018. #ifdef NETCONN
  2019.         if (netconn)
  2020.             x = write(ttyfd,s,n);
  2021.         else
  2022. #endif /* NETCONN */
  2023.         x = dgncoub(ttyfdout,s,n); 
  2024.         if (x == n) {
  2025.             debug(F101,"ttol ok","",x);
  2026.             return(len);
  2027.         } else if (x < 0) {
  2028.             debug(F101,"ttol failed","",lasterror());
  2029.             return(-1);
  2030.         } else {
  2031.             debug(F101,"ttol partial","",x);
  2032.             s += x;                     /* update buffer address for next */
  2033.             n -= x;                     /* update length for next read */
  2034.             if (x > 0) msleep(100);
  2035.         }
  2036.     }
  2037.     return((n < 1) ? len : -1);
  2038. }
  2039.  
  2040.  
  2041. /*  T T O C  --  Output a character to the communication line  */
  2042. /*
  2043.  This function should only be used for interactive, character-mode operations,
  2044.  like terminal connection, script execution, dialer i/o, where the overhead
  2045.  of the signals and alarms does not create a bottleneck.
  2046. */
  2047.  
  2048. ttoc(c) char c; {
  2049.     int x,xx;
  2050. #define TTOC_TMO 15
  2051.     c &= 0xff;
  2052.     /* debug(F101,"ttoc","",(CHAR) c); */
  2053. #ifdef NETCONN
  2054.     if (netconn) {
  2055.         if (ttyfd < 0) return(-1);
  2056.     } else
  2057. #endif /* NETCONN */
  2058.     if (ttyfdout < 0) return(-1);  /* Not open. */
  2059.     saval = signal(SIGALRM,timerh);
  2060.     xx = alarm(TTOC_TMO);
  2061.     if (xx < 0) xx = 0;                 /* Save old alarm value. */
  2062.     if (setjmp(sjbuf)) {
  2063.         ttimoff();
  2064.         if (xx - TTOC_TMO > 0) alarm(xx - TTOC_TMO); /* Restore previous one */
  2065. #ifdef NETCONN
  2066.         if (!netconn) {
  2067. #endif /* NETCONN */
  2068.             /* debug(F100,"ttoc timeout","",0); */
  2069.             if (ttflow == FLO_XONX) {
  2070.                 debug(F100,"ttoc flow","",ttflow);
  2071.                 /* issue clear device */
  2072.             }
  2073. #ifdef NETCONN
  2074.         }
  2075. #endif /* NETCONN */
  2076.         return(-1);
  2077.     } else {
  2078. #ifdef NETCONN
  2079.         if (netconn)                    /* use ttyfd for tcp connections */
  2080.             x = write(ttyfd,&c,1);
  2081.         else                            /* ttyfdout for local connections */
  2082. #endif /* NETCONN */
  2083.             x = (dgncoub(ttyfdout,&c,1)); 
  2084.         if (x != 1) {
  2085.             ttimoff();                  /* If error, turn off timer, */
  2086.             alarm(xx);
  2087.             debug(F101,"ttoc error x","",x);
  2088.             debug(F101,"ttoc last error","",lasterror());
  2089.             return (-1);
  2090.         }
  2091.     }
  2092.     ttimoff();
  2093.     alarm(xx);
  2094.     return (0);
  2095. }
  2096.  
  2097. /*  T T I N L  --  Read a record (up to break character) from comm line.  */
  2098. /*
  2099.  Reads up to "max" characters from the communication line, terminating on:
  2100.  
  2101.     (a) the packet length field if the "turn" argument is zero, or
  2102.     (b) on the packet-end character (eol) if the "turn" argument is nonzero
  2103.  
  2104.   and returns the number of characters read upon success, or if "max" was
  2105.   exceeded or the timeout interval expired before (a) or (b), returns -1.
  2106.  
  2107.   The characters that were input are copied into "dest" with their parity bits
  2108.   stripped if parity was selected.  Returns the number of characters read.
  2109.   Characters after the eol are available upon the next call to this function.
  2110.  
  2111.   The idea is to minimize the number of system calls per packet, and also to
  2112.   minimize timeouts.  This function is the inner loop of the program and must
  2113.   be as efficient as possible.  The current strategy is to use myread().
  2114.  
  2115.   WARNING: this function calls parchk(), which is defined in another module.
  2116.   Normally, ckutio.c does not depend on code from any other module, but there
  2117.   is an exception in this case because all the other ck?tio.c modules also
  2118.   need to call parchk(), so it's better to have it defined in a common place.
  2119. */
  2120.  
  2121. /* ENH -- assume PARSENSE */
  2122.  
  2123. #ifdef CTRLC
  2124. #undef CTRLC
  2125. #endif /* CTRLC */
  2126. #define CTRLC '\03'
  2127.  
  2128. int
  2129. ttinl(dest,max,timo,eol,start,turn) int max,timo,turn; CHAR *dest,eol,start; {
  2130.     int pktlen = -1;
  2131.     int j;
  2132.     CHAR ch;
  2133.     int lplen = 0;
  2134.     int havelen = 0;
  2135.  
  2136.     if (ttyfd < 0) return(-1);          /* Not open. */
  2137.     if (turn)
  2138.         debug(F101,"ttinl read until eol, turn","",turn);
  2139.     else
  2140.         debug(F101,"ttinl read packet-length characters, turn","",turn);
  2141.     debug(F101,"ttinl max","",max);
  2142.     debug(F101,"ttinl timo","",timo);
  2143.  
  2144.     *dest = '\0';                       /* Clear destination buffer */
  2145.  
  2146.     if (timo < 0) timo = 0;
  2147.    
  2148.     if (timo) {                         /* Don't time out if timo == 0 */
  2149.         saval = signal(SIGALRM,timerh); /* Enable timer interrupt */
  2150.         alarm(timo);                    /* Set it. */
  2151.     }
  2152.     if (setjmp(sjbuf)) {                /* Timer went off? */
  2153.         debug(F100,"ttinl timout","",0); /* Get here on timeout. */
  2154.         debug(F110," with",(char *) dest,0);
  2155.         ttimoff();                      /* Turn off timer */
  2156.         return(-1);                     /* and return error code. */
  2157.     } else {
  2158.         int i, m, n;
  2159.         int ccn = 0;
  2160.         int flag = 0;
  2161.  
  2162.         debug(F000,"ttinl start","",start);
  2163.         flag = 0;                       /* Start of packet flag */
  2164.  
  2165.         ttpmsk = m = (ttprty) ? 0177 : 0377; /* Set parity stripping mask. */
  2166.  
  2167. /* Now read into destination, stripping parity and looking for the */
  2168. /* the packet terminator, and also for two Ctrl-C's typed in a row. */
  2169.  
  2170.         i = 0;                          /* Destination index */
  2171.         debug(F101,"ttinl eol","",eol);
  2172.         while (i < max-1) {
  2173.             /* debug(F101,"ttinl i","",i); */
  2174.             if ((n = myread()) < 0) {
  2175.                 debug(F101,"ttinl myread failure, n","",n);
  2176.                 debug(F101,"ttinl myread errno,","",errno);
  2177.                 /* Don't let EINTR break packets. */
  2178.                 if (n == -3 && errno == EINTR && i > 0) {
  2179.                     debug(F101,"ttinl myread i","",i);
  2180.                     continue;
  2181.                 }
  2182.                 break;
  2183.             }
  2184.             debug(F101,"ttinl char","", (n & ttpmsk)); 
  2185. /*
  2186.   Figure out what the length is supposed to be in case the packet
  2187.   has no terminator (as with Honeywell GCOS-8 Kermit).
  2188. */
  2189. #ifndef xunchar
  2190. #define xunchar(ch) (((ch) - 32 ) & 0xFF )      /* Character to number */
  2191. #endif /* xunchar */
  2192.             if ((flag == 0) && ((n & 0x7f) == start)) flag = 1;
  2193.             if (flag) dest[i++] = n & ttpmsk;
  2194. /*
  2195.   If we have not been instructed to wait for a turnaround character, we
  2196.   can go by the packet length field.  If turn != 0, we must wait for the
  2197.   end of line (eol) character before returning.
  2198. */
  2199.             if (i == 2) {
  2200.                 pktlen = xunchar(dest[1] & 0x7f);
  2201.                 havelen = (pktlen > 1);
  2202.                 debug(F101,"ttinl length","",pktlen);
  2203.             } else if (i == 5 && pktlen == 0) {
  2204.                 lplen = xunchar(dest[4] & 0x7f);
  2205.             } else if (i == 6 && pktlen == 0) {
  2206.                 pktlen = lplen * 95 + xunchar(dest[5] & 0x7f) + 5;
  2207.                 havelen = 1;
  2208.                 debug(F101,"ttinl length","",pktlen);
  2209.             }
  2210.         /* Check cancellation */
  2211.             if (!xlocal && xfrcan && ((n & ttpmsk) == xfrchr)) {
  2212.                 if (++ccn >= xfrnum) {    /* If xfrnum in a row, bail out. */
  2213.                     if (timo) {         /* Clear timer. */
  2214.                         ttimoff();
  2215.                     }
  2216.                     fprintf(stderr,"^C...\r\n"); /* Echo Ctrl-C */
  2217.                     return(-2);
  2218.                 }
  2219.             } else ccn = 0;             /* Not ^C, so reset ^C counter, */
  2220.             if (flag == 0) {
  2221.                 debug(F101,"ttinl skipping","",n);
  2222.                 continue;
  2223.             }
  2224.  
  2225.     /* Check for end of packet */
  2226.  
  2227.             if (((n & 0x7f) == eol) || (!turn && havelen && (i > pktlen+1))) {
  2228.                 if ((n & 0x7f) != eol) {
  2229.                     debug(F101,"ttinl EOP length","",pktlen);
  2230.                     debug(F101,"ttinl i","",i);
  2231.                 } else debug(F101,"ttinl got eol","",eol);
  2232.                 dest[i] = '\0';         /* Terminate the string, */
  2233.  
  2234. /* Here's where we actually check and adjust the parity. */
  2235. /* The major flaw here is if parity is NONE (ttprty = 0) and the packets */
  2236. /* really do have no parity, then parchk() is called for every packet. */
  2237. /* In practice, this doesn't really harm efficiency noticably, but it would */
  2238. /* be better if ttinl() had a way of knowing to stop doing this once a */
  2239. /* particular file transfer had been started and checked. */
  2240.                 if (ttpflg++ == 0 && ttprty == 0) {
  2241.                     if ((ttprty = parchk(dest,start,i)) > 0) {
  2242.                         int j;
  2243.                         debug(F101,"ttinl senses parity","",ttprty);
  2244.                         debug(F110,"ttinl packet before",dest,0);
  2245.                         ttpmsk = 0x7f;
  2246.                         for (j = 0; j < i; j++)
  2247.                           dest[j] &= 0x7f;      /* Strip parity from packet */
  2248.                         debug(F110,"ttinl packet after ",dest,0);
  2249.                     } else debug(F101,"parchk","",ttprty);
  2250.                 }
  2251.                 if (timo) {                     /* Turn off timer. */
  2252.                     ttimoff();
  2253.                 }
  2254.                 debug(F111,"ttinl got", dest,i);
  2255.                 return(i);
  2256.             }
  2257.         }                               /* end of while() */
  2258.         ttimoff();
  2259.         return(-1);
  2260.     }
  2261.  
  2262. /*  T T I N C --  Read a character from the communication line  */
  2263. /*
  2264.  On success, returns the character that was read, >= 0.
  2265.  On failure, returns -1 or other negative myread error code.
  2266. */
  2267.  
  2268. int
  2269. ttinc(timo) int timo; {
  2270.     int n = 0;
  2271.     CHAR ch = 0;
  2272.  
  2273.     if (ttyfd < 0)            /* Not open. */
  2274.       return(-2);
  2275.  
  2276. #ifdef TTLEBUF
  2277.     if (ttpush >= 0) {
  2278.         debug(F111,"ttinc","ttpush",ttpush);
  2279.         ch = ttpush;
  2280.         ttpush = -1;
  2281.         return(ch);
  2282.     }
  2283.     if (le_data) {
  2284.         if (le_getchar(&ch) > 0) {
  2285.             debug(F111,"ttinc le_getchar","ch",ch);
  2286.             return(ch);
  2287.         }
  2288.     }
  2289. #endif /* TTLEBUF */
  2290.  
  2291.     if (timo <= 0) {                    /* Untimed. */
  2292.         /* comm line failure returns -1 thru myread, so no &= 0377 */
  2293.         n = myread();                   /* Wait for a character... */
  2294.         /* debug(F101,"ttinc n","",n); */
  2295.         return(n < 0 ? n : n & ttpmsk);
  2296.     } else {
  2297.         int xx;
  2298.         saval = signal(SIGALRM,timerh); /* Timed, set up timer. */
  2299.         xx = alarm(timo);               /* calls because I'm getting errors  */
  2300.         if (setjmp(sjbuf))              /* about these signal calls -- " the */
  2301.             n = -1;                     /* destination of a non-local GOTO is*/
  2302.         else {                          /* an inactive block" */
  2303.             n = myread();               /* If managing own buffer... */
  2304.             /* debug(F101,"ttinc myread","",n); */
  2305.         }
  2306.         ttimoff();
  2307. #ifdef NETCONN
  2308.         if (netconn) {
  2309.             if (n == -2) {              /* read() returns 0 */
  2310.                 netclos();              /* on network read failure */
  2311.                 netconn = 0;            /* ENH - deleted errno = ENOTCON */
  2312.             }
  2313.         }
  2314. #endif  /* NETCONN */
  2315.         return( (n < 0) ? n : (n & ttpmsk) ); /* Return masked char or neg. */
  2316.     }
  2317. }
  2318.  
  2319. /*  T T S N D B  --  Send a BREAK signal  */
  2320.  
  2321. ttsndb() {
  2322.     int x; long n; char spd;            /* In VS, the duration of the break */
  2323.                                         /* is until next write() or charac- */
  2324.     debug(F101,"ttsndb ttyfd","",ttyfd); /* teristics change                */
  2325.     if (ttyfd < 0) return(-1);          /* Not open. */
  2326.  
  2327. #ifdef NETCONN
  2328.     if (netconn)                        /* Send network BREAK */
  2329.       return(netbreak());
  2330. #endif /* NETCONN */
  2331.  
  2332. #ifdef UXIII
  2333. #ifdef datageneral
  2334.     if (sys_clrdv(channel(ttyfdout),1<<31,$CDSBRK)) {   /* Send a BREAK */
  2335.         perror("Can't send BREAK");
  2336.         return(-1);
  2337.     }
  2338.     return(0);
  2339. #endif
  2340. #endif
  2341. }
  2342.  
  2343. /* T T S N D L B  --  Send a "long" BREAK signal */
  2344.  
  2345. ttsndlb() {             /* In VS, they're long by default -- see ttsndb() */
  2346.     return(ttsndb());
  2347. }
  2348.  
  2349.  
  2350. /*  M S L E E P  --  Millisecond version of sleep().  */
  2351.  
  2352. /*
  2353.  Intended only for small intervals.  For big ones, just use sleep().
  2354. */
  2355.  
  2356. msleep(m) int m; {
  2357.  
  2358. #ifdef UXIII
  2359. #define CLOCK_TICK 17                   /* 1/60 sec */
  2360.     extern long times();
  2361.     long t1, t2, tarray[4];
  2362.     int t3;
  2363.  
  2364.     if (m <= 0) return(0);
  2365.     if ((t1 = times(tarray)) < 0) return(-1);
  2366.     while (1) {
  2367.         if ((t2 = times(tarray)) < 0) return(-1);
  2368.         t3 = ((int)(t2 - t1)) * CLOCK_TICK;
  2369.         if (t3 > m) return(t3);
  2370.     }
  2371. #endif
  2372. }
  2373.  
  2374.  
  2375. /*  R T I M E R --  Reset elapsed time counter  */
  2376.  
  2377. rtimer() {
  2378.     tcount = time( (long *) 0 );
  2379. }
  2380.  
  2381.  
  2382. /*  G T I M E R --  Get current value of elapsed time counter in seconds  */
  2383.  
  2384. gtimer() {
  2385.     int x;
  2386.     x = (int) (time( (long *) 0 ) - tcount);
  2387.     debug(F101,"gtimer","",x);
  2388.     /* rtimer(); */
  2389.     return( (x < 0) ? 0 : x );
  2390. }
  2391.  
  2392.  
  2393. /*  Z T I M E  --  Return date/time string  */
  2394.  
  2395. ztime(s) char **s; {
  2396.  
  2397. #ifdef UXIII
  2398.     extern long time();                 /* Sys III/V way to do it */
  2399.     char *ctime();
  2400.     long clock_storage;
  2401.  
  2402.     clock_storage = time( (long *) 0 );
  2403.     *s = ctime( &clock_storage );
  2404. #endif
  2405. }
  2406.  
  2407.  
  2408. /*  C O N G M  --  Get console terminal modes.  */
  2409.  
  2410. /*
  2411.  Saves current console mode, and establishes variables for switching between 
  2412.  current (presumably normal) mode and other modes.
  2413. */
  2414.  
  2415. congm() {
  2416.     if (backgrd || !isatty(0)) {  /* only for real ttys */
  2417.         cgmf = -1;
  2418.         return (-1);            /* it used to return a zero for this case */
  2419.     }
  2420.      ioctl(0,TCGETA,&ccold);
  2421.      ioctl(0,TCGETA,&cccbrk);
  2422.      ioctl(0,TCGETA,&ccraw);
  2423.      /* For DG, also get the tty extended device characteristics. */
  2424.      sys_gechr( channel(0), (1<<31)|$CLMAX, ch_ccold);
  2425.      sys_gechr( channel(0), (1<<31)|$CLMAX, ch_ccraw);
  2426.      sys_gechr( channel(0), (1<<31)|$CLMAX, ch_ccbrk);
  2427.      cgmf = 1;                          /* Flag that we got them. */
  2428. }
  2429.  
  2430.  
  2431.  
  2432. /*  C O N C B --  Put console in cbreak mode.  */
  2433.  
  2434. /*  Returns 0 if ok, -1 if not  */
  2435.  
  2436. concb(esc) char esc; {
  2437.     int x;
  2438.     debug(F101,"concb backgrd","",backgrd);
  2439.     if (!isatty(0)) return(0);          /* only for real ttys */
  2440.     debug(F100,"concb isatty","",0);
  2441.     if (backgrd) return(0);
  2442.     if (cgmf == 0) congm();             /* Get modes if necessary. */
  2443.     escchr = esc;                       /* Make this available to other fns */
  2444.     ckxech = 1;                         /* Program can echo characters */
  2445. #ifdef datageneral
  2446.     cccbrk.c_lflag |= CBREAK;
  2447. #endif
  2448.     cccbrk.c_lflag &= ~(ICANON|ECHO);
  2449.     cccbrk.c_cc[0] = 003;               /* interrupt char is control-c */
  2450.     cccbrk.c_cc[1] = escchr;            /* escape during packet modes */
  2451.     cccbrk.c_cc[4] = 1;
  2452.     cccbrk.c_cc[5] = 1;
  2453.     x = ioctl(0,TCSETAW,&cccbrk);       /* set new modes . */
  2454. #ifdef datageneral
  2455.     if (sys_gechr( channel(0), (1<<31)|$CLMAX, ch_ccbrk)) 
  2456.          { perror("concb: gechr: "); return(-1); }
  2457. #endif
  2458. #ifndef NOSETBUF
  2459.     if (x > -1) setbuf(stdout,NULL);    /* Make console unbuffered. */
  2460. #endif /* NOSETBUF */
  2461.     return(x);
  2462. }
  2463.  
  2464. /*  C O N B I N  --  Put console in binary mode  */
  2465.  
  2466. /*  Returns 0 if ok, -1 if not  */
  2467.  
  2468. conbin(esc) char esc; {
  2469. int filedes,filedes2;
  2470.  
  2471.     if (!isatty(0)) return(0);          /* only for real ttys */
  2472.     if (backgrd) return;                /* ... */
  2473.     if (cgmf == 0) congm();             /* Get modes if necessary. */
  2474.     escchr = esc;                       /* Make this available to other fns */
  2475.     ckxech = 1;                         /* Program can echo characters */
  2476.     ccraw.c_lflag &= ~(ISIG|ICANON|ECHO);
  2477.     ccraw.c_iflag |= (BRKINT|IGNPAR);
  2478.     ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|IXON|IXANY|IXOFF
  2479.                         |INPCK|ISTRIP);
  2480.     ccraw.c_oflag &= ~OPOST;
  2481.  
  2482. /*** Kermit used to put the console in 8-bit raw mode, but some users have
  2483.  *** pointed out that this should not be done, since some sites actually
  2484.  *** use terminals with parity settings on their Unix systems, and if we
  2485.  *** override the current settings and stop doing parity, then their terminals
  2486.  *** will display blotches for characters whose parity is wrong.  Therefore,
  2487.  *** the following two lines are commented out (Larry Afrin, Clemson U):
  2488.  ***
  2489.  ***   ccraw.c_cflag &= ~(PARENB|CSIZE);
  2490.  ***   ccraw.c_cflag |= (CS8|CREAD);
  2491.  ***
  2492.  *** Sys III/V sites that have trouble with this can restore these lines.
  2493.  ***/
  2494.     ccraw.c_cc[4] = 1;
  2495.     ccraw.c_cc[5] = 1;
  2496. #ifdef datageneral
  2497.     if (ioctl(0,TCSETAW,&ccraw)) return(-1);    /* set new modes . */
  2498.     if (sys_gechr( channel(0), (1<<31)|$CLMAX, ch_ccraw))
  2499.          { perror("conbin: gechr: "); return(-1); }
  2500.     return(0);
  2501. #else
  2502.     return(ioctl(0,TCSETAW,&ccraw) );   /* set new modes . */
  2503. #endif
  2504. }
  2505.  
  2506.  
  2507. /*  C O N R E S  --  Restore the console terminal  */
  2508.  
  2509. conres() {
  2510.     if (cgmf == 0) return(0);           /* Don't do anything if modes */
  2511.     if (!isatty(0)) return(0);          /* only for real ttys */
  2512.     if (backgrd) return;                /* ... */
  2513. #ifdef datageneral
  2514.     if (timocon) 
  2515.          /* Timeouts are set, so un-set them. */
  2516.          resto(channel(0));
  2517. #endif
  2518.     ckxech = 0;                         /* System should echo chars */
  2519. #ifdef datageneral
  2520.     if (ioctl(0,TCSETAW,&ccold)) return(-1);    /* set new modes . */
  2521.     if (sys_sechr( channel(0), (1<<31)|$CLMAX, ch_ccold))
  2522.          { perror("conres: sechr "); return(-1); }
  2523.     return(0);
  2524. #else
  2525.     return(ioctl(0,TCSETAW,&ccold));
  2526. #endif
  2527. }
  2528.  
  2529.  
  2530. /*  C O N O C  --  Output a character to the console terminal  */
  2531.  
  2532. conoc(c) char c; {
  2533.     write(1,&c,1);
  2534. }
  2535.  
  2536. /*  C O N X O  --  Write x characters to the console terminal  */
  2537.  
  2538. conxo(x,s) char *s; int x; {
  2539.     write(1,s,x);
  2540. }
  2541.  
  2542. /*  C O N O L  --  Write a line to the console terminal  */
  2543.  
  2544. conol(s) char *s; {
  2545.     int len;
  2546.     len = strlen(s);
  2547.     write(1,s,len);
  2548. }
  2549.  
  2550. /*  C O N O L A  --  Write an array of lines to the console terminal */
  2551.  
  2552. conola(s) char *s[]; {
  2553.     int i;
  2554.     for (i=0 ; *s[i] ; i++) conol(s[i]);
  2555. }
  2556.  
  2557. /*  C O N O L L  --  Output a string followed by CRLF  */
  2558.  
  2559. conoll(s) char *s; {
  2560.     conol(s);
  2561.     write(1,"\r\n",2);
  2562. }
  2563.  
  2564. /* Input buffer checking */
  2565.  
  2566. #ifdef SELECT
  2567. /*
  2568.   NOTE: This can be compiled and linked OK with SELECT defined
  2569.   but it doesn't work at all.  Anybody who cares and knows how
  2570.   to fix it, feel free.  The select() call always returns -1.
  2571. */
  2572. #include <:usr:include:sys:vs_tcp_types.h>
  2573. #include <:usr:include:sys:vs_tcp_time.h>
  2574. #endif /* SELECT */
  2575.  
  2576. in_chk(fd) int fd; {
  2577.     int x, n = 0;
  2578.  
  2579. #ifdef SELECT
  2580.     struct timeval tv;
  2581.     fd_set rfds;
  2582. #endif /* SELECT */
  2583.  
  2584. #ifdef TTLEBUF
  2585.     ttpush = -1;            /* Clear the peek-ahead char */
  2586.     while (le_data && (le_inbuf() > 0)) {
  2587.         CHAR ch = '\0';
  2588.         if (le_getchar(&ch) > 0) {
  2589.             debug(F101,"ttflui le_inbuf ch","",ch);
  2590.         }
  2591.     }
  2592. #endif /* TTLEBUF */
  2593.  
  2594.     if (fd < 0) return(0);
  2595.  
  2596. #ifdef SELECT
  2597.     FD_ZERO(&rfds);            /* Initialize them */
  2598.     FD_SET(fd,&rfds);            /* We want to look at this fd */
  2599.     tv.tv_sec = tv.tv_usec = 0L;    /* A 0-valued timeval structure */
  2600.     n = select(FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv);
  2601.     debug(F101,"in_chk select n","",n);
  2602. #endif /* SELECT */
  2603.     if (my_count > 0)
  2604.       n += my_count;
  2605.     debug(F101,"ttchk chars available, ","",n);
  2606.     return(n);
  2607. }
  2608.  
  2609. /*  C O N C H K  --  Return how many characters available at console  */
  2610.  
  2611. conchk() {
  2612.     int x; long n;
  2613.     if (backgrd)            /* There is no typeahead in batch */
  2614.       return;
  2615.     return(in_chk(0));
  2616. }
  2617.  
  2618.  
  2619. #ifdef datageneral
  2620.  
  2621. /* D G N C O U B -- Output len characters to the file number filenum */
  2622.  
  2623. dgncoub(filenum,chs,len) int filenum, len; char *chs; 
  2624. {
  2625.      int ac2,err;
  2626.  
  2627.      if (len == 0) return(0);
  2628.  
  2629.      if (filenum == ttyfdout) {
  2630.           xout_parms.ibad = chs;
  2631.           xout_parms.ircl = len;
  2632.           ac2 = &xout_parms;
  2633.      } else {
  2634.           w_io_parms.ich = channel(filenum);
  2635.           w_io_parms.ibad = chs;
  2636.           w_io_parms.ircl = len;
  2637.           ac2 = &w_io_parms;
  2638.      }
  2639.      
  2640.      if ((err = sys_write(ac2)) == 0)
  2641.          return(((P_NIO_EX *) ac2)->irlr);  /* ENH - change to return length */
  2642.      if ( err != ERLTL && err != EREOF ) {
  2643.           perror("dgncoub: sys_write ");
  2644.           return(-err);                     /* ENH - change to return */
  2645.      }                                      /* negative of error code */
  2646.      else return(((P_NIO_EX *) ac2)->irlr);
  2647. }
  2648.  
  2649.  
  2650. /* D G N C I N B -- System level read of len characters from file number 
  2651.    fileno.  The global DG i/o structures are used for this.
  2652.  
  2653.    Return codes:  irlr if data read ok, where irlr=length of data
  2654.                   -1 if EOF
  2655.                   -2 if timeout occured
  2656.                   -err if an AOS/VS error occured, where err is errno
  2657. */                  
  2658.  
  2659. int
  2660. dgncinb(filenum,chs,len) int filenum,len; char *chs; {               
  2661.      int ac2,                       /* I/O parameter address block */
  2662.          err,                       /* Error from sys_read */
  2663.          irlr;                      /* Number of bytes read */
  2664.      int rbe;                       /* Ring buffer empty on ESGT read */
  2665.  
  2666.      if (filenum == ttyfd) {
  2667.           x_io_parms.ibad = chs;
  2668.           x_io_parms.ircl = len;
  2669.           ac2 = (P_NIO_EX *) &x_io_parms;
  2670.           err = sys_read(ac2);
  2671.           irlr = x_io_parms.irlr;
  2672.           if (err == 0) {
  2673.               return(irlr);
  2674.           }
  2675.           rbe = (x_io_parms.etsp == 0) ? 0 : (x_io_scrn.esfc & $ESBE);
  2676.      } else {
  2677.           r_io_parms.ich  = channel(filenum); 
  2678.           r_io_parms.ibad = chs;
  2679.           r_io_parms.ircl = len;
  2680.           ac2 = (P_NIO_EX *) &r_io_parms;
  2681.           err = sys_read(ac2);
  2682.           irlr = r_io_parms.irlr;
  2683.           if (err == 0) {
  2684.               return(irlr);
  2685.           }
  2686.           rbe = (r_io_parms.etsp == 0) ? 0 : (r_io_scrn.esfc & $ESBE);
  2687.      }
  2688.      if ((err != ERLTL) && (err != ERDTO) && (err != EREOF)) {
  2689.      /*
  2690.         NOT line-too-long, timeout, or EOF errors.
  2691.             Don't print error when it is a data overrun.
  2692.          */
  2693.           if (err != EROVR) perror("dgncinb: sys_read error");
  2694.           return(-err);
  2695.      } else {
  2696.           /*
  2697.         If the system read buffer was empty when a screen management
  2698.             packet was supplied, then there is a virtual EOF condition.  
  2699.             So we return an EOF flag in that case (rbe != 0).
  2700.           */
  2701.           if ((err == EREOF) || rbe) return(-1); /* EOF */
  2702.           if (err == ERDTO) 
  2703.         if (irlr <= 0)        /* if no data, */ 
  2704.                   return (-2);        /* return -2 */
  2705.           return(irlr);            /* else chars read */
  2706.      }
  2707. }
  2708. #endif datageneral
  2709.  
  2710. /*  C O N I N C  --  Get a character from the console  */
  2711.  
  2712. coninc(timo) int timo; {
  2713.     int n = 0; char ch;
  2714.  
  2715.     if (timo <= 0) {            /* no timeout specified */
  2716.       while (1) {
  2717.         /* Binary input */
  2718.         n = dgncinb(0,&ch,1);
  2719.         if (n == 0) continue;
  2720.         if (n > 0)
  2721.             return(ch & 0377);                 /* Return the char if read */
  2722.         else {
  2723.             if (lasterror() == EINTR)
  2724.               if (conesc)  {            /* If by SIGQUIT, */
  2725.                  conesc = 0;            /* the conesc variable is set, */
  2726.                  return(escchr);        /* so return the escape character. */
  2727.               } else continue;           /* By other signal, try again. */
  2728.             else if (n == -2) {            /* won't happen unless ?STOM */
  2729.                 debug(F101,"coninc got timeout ","",n);   /* has happened */
  2730.                 continue;
  2731.             } else if (n == -1)                         /* behind our back */
  2732.                 debug(F101,"coninc got eof indication","",n);
  2733.             else if (n < -2)            /* -n = VS error code */
  2734.                 debug(F101,"coninc got AOS/VS error","",-n);
  2735.             return(-1);
  2736.         }
  2737.       }
  2738.     }
  2739.     saval = signal(SIGALRM,timerh);     /* else timeout specified */
  2740.     alarm(timo);
  2741.     if (setjmp(sjbuf)) n = -2;
  2742.     else 
  2743.         n = dgncinb(0, &ch, 1);
  2744.     ttimoff();                          /* Turn off timer */
  2745.     if (n > 0) return(ch & 0377);
  2746.     else {
  2747.         debug(F101, "coninc(timo) n","",n);
  2748.         debug(F101, "coninc(timo) errno","",lasterror());
  2749.         if ((lasterror() == EINTR) && conesc != 0) {
  2750.             conesc = 0;
  2751.             return(escchr);             /* User entered escape character. */
  2752.         } else if (n == -2)                        /* won't happen */
  2753.             debug(F101, "coninc got DEVICE timeout","",n);
  2754.         else if (n == -1)
  2755.             debug(F101,"coninc got eof indication","",n);
  2756.         else if (n < -2)                    /* -n = VS error code */
  2757.             debug(F101,"coninc got AOS/VS error","",-n);
  2758.         return(-1); 
  2759.         }
  2760.  
  2761.                 
  2762. }
  2763.  
  2764. /*  C O N G K S  --  Console Get Keyboard Scancode  */
  2765.  
  2766. #ifndef congks
  2767. /*
  2768.   This function needs to be filled in with the various system-dependent
  2769.   system calls used by SUNOS, NeXT OS, Xenix, Aviion, etc, to read a full
  2770.   keyboard scan code.  For now, it's a dummy.
  2771. */
  2772. int
  2773. congks(timo) int timo; {
  2774.     return(coninc(timo));
  2775. }
  2776. #endif /* congks */
  2777.  
  2778.  
  2779. /* These security routines are here, but they're not used.  There's no */
  2780. /* need for them in the AOS/VS implementation.  When they were here,   */
  2781. /* they caused superuser to be turned off when kermit was started with */
  2782. /* it on.  Seemed to cause problems instead of solve them.       --ENH */
  2783.  
  2784. int
  2785. priv_ini()                                  /* if superu is on, turn off    */
  2786. {
  2787.     int     ac0,ac1,ac2,error;
  2788.  
  2789.     ac0 = ac1 = ac2 = 0;
  2790.  
  2791.     error = sys( $SUSER, &ac0, &ac1, &ac2 );
  2792.     if( ac0 == -1 )                         /* if it's on...                */
  2793.         priv_off();                         /* turn it off                  */
  2794.  
  2795.     return  0;
  2796. }
  2797.  
  2798. int
  2799. priv_on()                                   /* turn superu on               */
  2800. {
  2801.     int     ac0,ac1,ac2,error;
  2802.  
  2803.     ac0 = -1;                               /* turn it on                   */
  2804.     ac1 = ac2 = 0;
  2805.  
  2806.     error = sys( $SUSER, &ac0, &ac1, &ac2 );
  2807.     if( error != NULL )
  2808.         error = -1;                         /* an error                     */
  2809.  
  2810.     return  error;
  2811. }
  2812.  
  2813. int
  2814. priv_off()
  2815. {
  2816.     int     ac0,ac1,ac2;
  2817.  
  2818.     ac0 = 1;                                /* turn it off                  */
  2819.     ac1 = ac2 = 0;
  2820.  
  2821.     return  sys( $SUSER, &ac0, &ac1, &ac2 );
  2822. }
  2823.  
  2824. int
  2825. priv_can()
  2826. {
  2827.     return  priv_off();
  2828. }
  2829.  
  2830. int
  2831. priv_chk()
  2832. {
  2833.     return  priv_off();
  2834. }
  2835.  
  2836. VOID
  2837. ttimoff() {                           /* Turn off any timer interrupts */
  2838.     alarm(0);
  2839.     if (saval)
  2840.       signal(SIGALRM,saval);
  2841.     else
  2842.       signal(SIGALRM,SIG_DFL);
  2843.     saval = NULL;
  2844. }
  2845.  
  2846. /* Similarly, this ctrlc_chk() routine is here, but it's not used. */
  2847.  
  2848. void
  2849. ctrlc_chk(buffer,n) int *buffer; int n; {
  2850. #nolist
  2851. #include <ckcker.h>
  2852. #list
  2853.     extern int local,what;
  2854.     int i;
  2855.     extern SIGTYP trap();
  2856.  
  2857.     debug(F101,"Entering ctrlc_chk -- number of chars in buf","",n);
  2858.     debug(F101,"ctrlc_chk local =","",local);
  2859.     debug(F101,"ctrlc_chk what =","",what);
  2860.     if (what == W_CONNECT)                  /* ignore ^C's in connect mode */
  2861.         return;
  2862.     if (what == W_NOTHING)                  /* don't know what's what here */
  2863.         return;                             /* so ignore ^C in case data   */
  2864.     if ((!local) &&
  2865.         ((what == W_SEND) || (what == W_RECV) || (what == W_REMO)))
  2866.         return;
  2867.     for (i = 0; i < n; i++)                 /* otherwise it's W_SEND, W_RECV */
  2868.                                             /* or W_REMOTE in local mode or  */
  2869.                                             /* W_COMMAND in either mode      */
  2870.         if ((buffer[i] & 0177) == CTRLC) {
  2871.             debug (F101,"Got ^C...","",what);
  2872.             my_count = 0;                   /* clear out buffer */
  2873.             trap(what);                     /* call signal handler */
  2874.         }
  2875. }
  2876.