home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / c-kermit / ckdtio.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  97KB  |  2,888 lines

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