home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / ckc072.zip / ckdtio.c < prev    next >
C/C++ Source or Header  |  1988-08-16  |  76KB  |  2,575 lines

  1. char *ckxv = "Data General tty I/O, 4C(039), 11 May 87";
  2.  
  3. /*  C K U T I O  */
  4.  
  5. /* C-Kermit interrupt, terminal control & i/o functions for Unix systems */
  6.  
  7. /*
  8.  Author: Frank da Cruz (SY.FDC@CU20B),
  9.  Columbia University Center for Computing Activities, January 1985.
  10.  Copyright (C) 1985, Trustees of Columbia University in the City of New York.
  11.  Permission is granted to any individual or institution to use, copy, or
  12.  redistribute this software so long as it is not sold for profit, provided this
  13.  copyright notice is retained. 
  14.   
  15.  This module was adapted to the Data General computers by:
  16.  
  17.     Phil Julian, SAS Institute, Inc., Box 8000, Cary, NC 27512-8000
  18.   
  19. */
  20. /* Includes for all Unixes (conditional includes come later) */
  21.  
  22. #ifdef datageneral
  23. /* Data General includes need to come here, esp. for items like DEVNAMLEN */
  24. #define MAXINBUF 2048                  /* See ckdcon.c for same definition. */
  25. #include <memory.h>
  26. #include <string.h>
  27. #include <dglib.h>
  28. #include <bit.h>
  29. #include <sysid.h>
  30. #include <sys_calls.h>
  31. #include <packets/normal_io.h>
  32. #include <multitask.h>                                  
  33. #define CONINT_TSK 20                   /* 16, 17 are taken IDs */
  34. #define CONINT_PRI 0                    /* Same as calling task */ 
  35. #define CONINT_STACK 0
  36. int con_reads_mt = 0;                   /* Flag if task is active */
  37. int conint_ch;                          /* MT character read */
  38. int conint_avl;                         /* Flag that char available */
  39. int termtype;
  40. /* Delimiter table -- defaults to CR only */
  41. short idel_tbl[7] = {0x4,0,0,0,0,0,0};
  42. #include <stdio.h>            /* Unix Standard i/o */
  43. #ifndef DEVNAMLEN
  44. #define DEVNAMLEN (L_ctermid + 6)
  45. #endif 
  46.  
  47. #else 
  48. #include <sys/types.h>            /* Types */
  49. #endif datageneral
  50.  
  51. #include <sys/dir.h>            /* Directory */
  52. #include <ctype.h>            /* Character types */
  53. /* Maximum length for the name of a tty device */
  54.  
  55. #ifndef DEVNAMLEN
  56. #define DEVNAMLEN 25
  57. #endif
  58.  
  59. #include <stdio.h>            /* Unix Standard i/o */
  60. #include <signal.h>            /* Interrupts */
  61. #include <setjmp.h>            /* Longjumps */
  62. #include "ckcdeb.h"            /* Typedefs, formats for debug() */
  63.  
  64. /* 4.1 BSD support added by Charles E. Brooks, EDN-VAX */
  65. /* Fortune 16:32 For:Pro 1.7 support mostly like 4.1, added by J-P Dumas */
  66.  
  67. #ifdef BSD4
  68. #define ANYBSD
  69. #ifdef MAXNAMLEN
  70. #define BSD42
  71. char *ckxsys = " 4.2 BSD";
  72. #else
  73. #ifdef FT17
  74. #define BSD41
  75. char *ckxsys = " For:Pro Fortune 1.7";
  76. #else
  77. #define BSD41
  78. #ifndef C70
  79. char *ckxsys = " 4.1 BSD";
  80. #endif
  81. #endif
  82. #endif
  83. #endif
  84.  
  85. /* 2.9bsd support contributed by Bradley Smith, UCLA */
  86. #ifdef BSD29
  87. #define ANYBSD
  88.  
  89. char *ckxsys = " 2.9 BSD";
  90. #endif
  91.  
  92. /*
  93.  Version 7 UNIX support contributed by Gregg Wonderly,
  94.  Oklahoma State University:  gregg@okstate.csnet
  95. */
  96. #ifdef    V7
  97. char *ckxsys = " Version 7 UNIX (tm)";
  98. #endif
  99.  
  100. /* BBN C70 support from Frank Wancho, WANCHO@SIMTEL20 */
  101. #ifdef C70
  102. char *ckxsys = " BBN C/70";
  103. #endif
  104.  
  105.  
  106. /* Amdahl UTS 2.4 (v7 derivative) for IBM 370 series compatible mainframes */
  107. /* Contributed by Garard Gaye, Jean-Pierre Dumas, DUMAS@SUMEX-AIM. */
  108. #ifdef UTS24
  109. char *ckxsys = " Amdahl UTS 2.4";
  110. #endif
  111.  
  112. /* Pro/Venix Version 1.x support from Columbia U. */
  113. #ifdef PROVX1
  114. char *ckxsys = " Pro-3xx Venix v1";
  115. #endif
  116.  
  117. /* Tower support contributed by John Bray, Auburn, Alabama */
  118. #ifdef TOWER1
  119. char *ckxsys = " NCR Tower 1632, OS 1.02";
  120. #endif
  121.  
  122. /* Sys III/V, Xenix, PC/IX support by Herm Fischer, Encino, CA */
  123. #ifdef UXIII
  124. #ifdef XENIX
  125. char *ckxsys = " Xenix/286";
  126.  
  127. #else
  128. #ifdef PCIX
  129. char *ckxsys = " PC/IX";
  130. #else
  131. #ifdef ISIII
  132. char *ckxsys = " Interactive Systems Corp System III";
  133.  
  134. #else
  135. /* Datageneral support contributed by Phil Julian, SAS Institute, Inc. */
  136. #ifdef dgux
  137. char *ckxsys = " Data General DG/UX";
  138. #else dgux
  139. #ifdef datageneral
  140. char *ckxsys = " Data General AOS/VS";
  141.  
  142. #else
  143. char *ckxsys = " AT&T System III/System V";
  144.  
  145. #endif
  146. #endif
  147. #endif
  148. #endif
  149. #endif
  150. #endif
  151.  
  152. /* Features... */
  153.  
  154.  
  155. /* Do own buffering, using unbuffered read() calls... */
  156. #ifdef UXIII
  157. #define MYREAD
  158. #endif
  159.  
  160. #ifdef BSD42
  161. #define MYREAD
  162. #include <errno.h>
  163. #endif
  164.  
  165. /*
  166.  Note - KERLD is the Berkeley Unix Berknet line driver, modified to pass
  167.  through all 8  bits, and to allow an arbitrary break character to be set.
  168.  Don't define this symbol unless you have made this modification to your
  169.  4.2BSD kernel!
  170. */
  171. #ifdef BSD4
  172. /* #define KERLD */  /* <-- note, commented out */
  173. #endif
  174.  
  175. /*
  176.  Variables available to outside world:
  177.  
  178.    dftty  -- Pointer to default tty name string, like "/dev/tty".
  179.    dfloc  -- 0 if dftty is console, 1 if external line.
  180.    dfprty -- Default parity
  181.    dfflow -- Default flow control
  182.    ckxech -- Flag for who echoes console typein:
  183.      1 - The program (system echo is turned off)
  184.      0 - The system (or front end, or terminal).
  185.    functions that want to do their own echoing should check this flag
  186.    before doing so.
  187.  
  188.    flfnam -- Name of lock file, including its path, e.g.,
  189.         "/usr/spool/uucp/LCK..cul0" or "/etc/locks/tty77"
  190.    hasLock -- Flag set if this kermit established a uucp lock.
  191.    inbufc -- number of tty line rawmode unread characters 
  192.         (system III/V unixes)
  193.    backgrd -- Flag indicating program executing in background ( & on 
  194.         end of shell command). Used to ignore INT and QUIT signals.
  195.  
  196.  Functions for assigned communication line (either external or console tty):
  197.  
  198.    sysinit()               -- System dependent program initialization
  199.    ttopen(ttname,local,mdmtyp) -- Open the named tty for exclusive access.
  200.    ttclos()                -- Close & reset the tty, releasing any access lock.
  201.    ttpkt(speed,flow)       -- Put the tty in packet mode and set the speed.
  202.    ttvt(speed,flow)        -- Put the tty in virtual terminal mode.
  203.                 or in DIALING or CONNECTED modem control state.
  204.    ttinl(dest,max,timo)    -- Timed read line from the tty.
  205.    ttinc(timo)             -- Timed read character from tty.
  206.    myread()           -- System 3 raw mode bulk buffer read, gives
  207.                --   subsequent chars one at a time and simulates
  208.                --   FIONREAD!
  209.    myunrd(c)           -- Places c back in buffer to be read (one only)
  210.  
  211.    ttchk()                 -- See how many characters in tty input buffer.
  212.    ttxin(n,buf)            -- Read n characters from tty (untimed).
  213.    ttol(string,length)     -- Write a string to the tty.
  214.    ttoc(c)                 -- Write a character to the tty.
  215.    ttflui()                -- Flush tty input buffer.
  216.  
  217.    ttlock(ttname)       -- Lock against uucp collisions (Sys III)
  218.    ttunlck()           -- Unlock "       "     "
  219.    look4lk(ttname)       -- Check if a lock file exists
  220. */
  221.  
  222. /*
  223. Functions for console terminal:
  224.  
  225.    congm()   -- Get console terminal modes.
  226.    concb(esc) -- Put the console in single-character wakeup mode with no echo.
  227.    conbin(esc) -- Put the console in binary (raw) mode.
  228.    conres()  -- Restore the console to mode obtained by congm().
  229.    conoc(c)  -- Unbuffered output, one character to console.
  230.    conol(s)  -- Unbuffered output, null-terminated string to the console.
  231.    conola(s) -- Unbuffered output, array of strings to the console.
  232.    conxo(n,s) -- Unbuffered output, n characters to the console.
  233.    conchk()  -- Check if characters available at console (bsd 4.2).
  234.  
  235.         Check if escape char (^\) typed at console (System III/V).
  236.    coninc(timo)  -- Timed get a character from the console.
  237.    conint()  -- Enable terminal interrupts on the console if not background.
  238.    connoi()  -- Disable terminal interrupts on the console if not background.
  239.  
  240. Time functions
  241.  
  242.    msleep(m) -- Millisecond sleep
  243.    ztime(&s) -- Return pointer to date/time string
  244.    rtimer() --  Reset timer
  245.    gtimer()  -- Get elapsed time since last call to rtimer()
  246. */
  247.  
  248. /* Conditional Includes */
  249.  
  250. #ifdef FT17
  251. #include <sys/file.h>              /* File information */
  252. #endif
  253.  
  254. #ifndef PROVX1
  255. #ifdef datageneral
  256. #include <sys/stat.h>
  257. #else
  258. #include <sys/file.h>              /* File information */
  259. #endif
  260. #endif
  261.  
  262. /* System III, System V */
  263.  
  264. #ifdef UXIII
  265. #ifdef datageneral
  266. /* Console and terminal characteristics vectors */
  267. #include <paru.h>
  268. short *charcurr;
  269. short charconin[$CLMAX];    /* Console input; channel 0 */
  270. short charconout[$CLMAX];   /* Console output; channel 1 */
  271. short chartty[$CLMAX];      /* generic tty channel */
  272. short charttyin[$CLMAX];    /* tty input; channel ttyfd */
  273. short charttyout[$CLMAX];   /* tty output; channel ttyfdout */
  274.  
  275. short ch_ttold[$CLMAX];
  276. short ch_ttraw[$CLMAX];
  277. short ch_ttvt[$CLMAX]; 
  278. short ch_ccold[$CLMAX];
  279. short ch_ccraw[$CLMAX];
  280. short ch_ccbrk[$CLMAX]; 
  281. #undef ECHO
  282. #include <sys/termio.h>
  283. /* Add synonymns for Unix type ioctl */
  284. #define TCSETAF TCSETA
  285. #define TCSETAW TCSETA
  286.  
  287. #else
  288. #include <termio.h>
  289. #include <sys/ioctl.h>
  290. #endif datageneral
  291.  
  292. #include <fcntl.h>            /* directory reading for locking */
  293. #include <errno.h>            /* error numbers for system returns */
  294. #endif
  295.  
  296. /* Not Sys III/V */
  297.  
  298. #ifndef UXIII
  299. #include <sgtty.h>            /* Set/Get tty modes */
  300. #ifndef PROVX1
  301. #ifndef V7
  302. #ifndef BSD41
  303. #include <sys/time.h>            /* Clock info (for break generation) */
  304. #endif
  305. #endif
  306. #endif
  307. #endif
  308.  
  309. #ifdef BSD41
  310.  
  311. #include <sys/timeb.h>            /* BSD 4.1 ... ceb */
  312. #endif
  313.  
  314. #ifdef BSD29
  315. #include <sys/timeb.h>            /* BSD 2.9 (Vic Abell, Purdue) */
  316. #endif
  317.  
  318. #ifdef TOWER1
  319. #include <sys/timeb.h>            /* Clock info for NCR Tower */
  320. #endif
  321.  
  322. /* Declarations */
  323.  
  324. long time();                /* All Unixes should have this... */
  325. extern int errno;            /* System call error return */
  326.  
  327. /* Special stuff for V7 input buffer peeking */
  328.  
  329. #ifdef    V7
  330. int kmem[2] = { -1, -1};
  331. char *initrawq(), *qaddr[2]={0,0};
  332. #define CON 0
  333. #define TTY 1
  334. #endif
  335.  
  336. /* dftty is the device name of the default device for file transfer */
  337. /* dfloc is 0 if dftty is the user's console terminal, 1 if an external line */
  338.  
  339. #ifdef PROVX1
  340.     char *dftty = "/dev/com1.dout"; /* Only example so far of a system */
  341.     int dfloc = 1;            /* that goes in local mode by default */
  342. #else
  343.     char *dftty = CTTNAM;        /* Remote by default, use normal */
  344.     int dfloc = 0;            /* controlling terminal name. */
  345. #endif
  346.  
  347.     int dfprty = 0;            /* Parity (0 = none) */
  348.     int dfflow = 1;            /* Xon/Xoff flow control */
  349.     int backgrd = 0;            /* Assume in foreground (no '&' ) */
  350.  
  351. int ckxech = 0; /* 0 if system normally echoes console characters, else 1 */
  352.  
  353. /* Declarations of variables global within this module */
  354.  
  355. static long tcount;            /* Elapsed time counter */
  356.  
  357. static char *brnuls = "\0\0\0\0\0\0\0"; /* A string of nulls */
  358.  
  359. static jmp_buf sjbuf, jjbuf;        /* Longjump buffer */
  360. static int lkf = 0,            /* Line lock flag */
  361.     conif = 0,                /* Console interrupts on/off flag */
  362.     cgmf = 0,                /* Flag that console modes saved */
  363.     xlocal = 0;                /* Flag for tty local or remote */
  364. int ttyfd = -1;            /* TTY file descriptor */
  365. static char escchr;            /* Escape or attn character */
  366.  
  367. /* Special line discipline, 4.2bsd only, and only with kernel mods... */
  368. #ifdef KERLD
  369.     static int kerld = 1;        /* Special Kermit line discipline... */
  370.     struct tchars oldc, newc;        /* Special characters */
  371.     int ld = NETLDISC;            /* Really a hack to "Berknet" l.d. */
  372.     int oldld;                /* Old discipline */
  373. #else
  374.     static int kerld = 0;        /* Not selected, no special l.d. */
  375. #endif
  376.  
  377. #ifdef BSD42
  378.     static struct timeval tv;        /* For getting time, from sys/time.h */
  379.     static struct timezone tz;
  380. #endif
  381.  
  382. #ifdef BSD29
  383.     static long clock;            /* For getting time from sys/time.h */
  384.     static struct timeb ftp;        /* And from sys/timeb.h */
  385. #endif
  386.  
  387. #ifdef BSD41
  388.     static long clock;            /* For getting time from sys/time.h */
  389.     static struct timeb ftp;        /* And from sys/timeb.h */
  390. #endif
  391.  
  392. #ifdef TOWER1
  393. static long clock;            /* For getting time from sys/time.h */
  394. static struct timeb ftp;        /* And from sys/timeb.h */
  395. #endif
  396.  
  397. #ifdef V7
  398. static long clock;
  399. #endif
  400.  
  401. #ifdef UXIII
  402.   static struct termio             /* sgtty info... */
  403.     ttold, ttraw, tttvt,        /* for communication line */
  404.     ccold, ccraw, cccbrk;        /* and for console */
  405. #else
  406.   static struct sgttyb             /* sgtty info... */
  407.     ttold, ttraw, tttvt, ttbuf,        /* for communication line */
  408.     ccold, ccraw, cccbrk;        /* and for console */
  409.  
  410. #endif
  411.  
  412. static char flfnam[80];            /* uucp lock file path name */
  413. static int hasLock = 0;            /* =1 if this kermit locked uucp */
  414. static int inbufc = 0;            /* stuff for efficient SIII raw line */
  415. static int ungotn = -1;            /* pushback to unread character */
  416. static int conesc = 0;            /* set to 1 if esc char (^\) typed */
  417.  
  418. static int ttlock();            /* definition of ttlock subprocedure */
  419. static int ttunlck();            /* and unlock subprocedure */
  420. static char ttnmsv[DEVNAMLEN];        /* copy of open path for tthang */
  421.  
  422. #ifdef datageneral
  423. FILE *ttfile,*ttfileout;                /* Files opened by ttopen */
  424.   
  425. struct p_nio_ex w_io_parms;             /* ?write system call structure */
  426. struct p_nio_ex r_io_parms;             /* ?read system call structure */
  427.  
  428. struct p_nio_ex io_parms;               /* open structure in ttopen */
  429. struct p_nio_ex x_io_parms;             /* ?read/?write structure for ttyfd */
  430. struct p_nio_ex xout_parms;             /* ?write structure for ttyfdout */
  431. struct p_screen x_io_scrn,
  432.        r_io_scrn,io_screen;             /* Edit-read structures */
  433.  
  434. int ttyfdout = -1;                      /* ?write Unix number for remote out */
  435. short timotty = 0;                      /* {Flag for timeouts (=1), value */
  436. short timocon = 0;                      /* tty is ttyfd..., con is Unix 0/1 */
  437. extern char *SPACMD;                    /* Need to supply ":udd:username" */
  438. #endif
  439.  
  440. /*  S Y S I N I T  --  System-dependent program initialization.  */
  441.  
  442. int sysinit() {
  443.  
  444. /* for now, nothing... */
  445. #ifdef datageneral
  446.      /* Set up many things on the DG system, for initialization, etc. */
  447.      
  448.      short flags[3];
  449.      char *username;
  450.      int err;
  451.      
  452.      /* Get the terminal type, since DG terminals are different from others,
  453.         especially in the way BS is handled ('\b' is EM).
  454.         termtype = 0 means a regular DG style terminal, and 
  455.         termtype = 1 means an ANSI style terminal with ^H for backspace.
  456.         If Kermit is run in batch or has redirected input, then we do not
  457.         want to test or set the console characteristics.
  458.      */
  459.      termtype = 0;
  460.      if (isatty(0)) {
  461.          if (sys_gchr(channel(0),1<<31,&flags))
  462.              { perror("sysinit: sys_gchr: "); return(1); }
  463.  
  464.         /* Only determine whether or not it is a $TTY */
  465.         if ((flags[1] & $DTYPE) == $TTY) termtype = 1;
  466.      }
  467.  
  468.      zero((char *) &w_io_parms, sizeof(w_io_parms));
  469.      w_io_parms.ich  = channel(1);              /* stdout */
  470.      w_io_parms.isti = $IBIN|$RTDS|$ICRF|$OFOT;
  471.      w_io_parms.isti &= ~$IPST;
  472.      w_io_parms.imrs = MAXINBUF-1;
  473.      w_io_parms.ibad = -1;
  474.      w_io_parms.ircl = -1;
  475.  
  476.      zero((char *) &r_io_parms, sizeof(r_io_parms));
  477.      r_io_parms.ich  = channel(0);              /* stdin */
  478.      r_io_parms.isti = $IBIN|$RTDS|$ICRF|$OFIN;
  479.      r_io_parms.isti &= ~$IPST;
  480.      r_io_parms.imrs = MAXINBUF-1;
  481.      r_io_parms.ibad = -1;
  482.      r_io_parms.ircl = -1;
  483.  
  484.      zero((char *) &r_io_scrn, sizeof(r_io_scrn));
  485.      r_io_parms.etsp = 0;              /* Screen management extension */
  486.      r_io_scrn.esfc &= ~$ESNE;           /* Echo input data */
  487.      r_io_scrn.esfc &= ~$ESSE;           /* No screen edit */
  488.      r_io_scrn.esfc |= $ESGT;           /* Dump ring buffer */
  489.  
  490.      zero((char *) &x_io_parms, sizeof(x_io_parms));
  491.      /* $RTDY must be used instead of $RTDS since this causes failure on
  492.       * the Prime, which is probably getting data overruns on output or
  493.       * missing data.  Also, $RTDY is more efficient and faster.
  494.       */
  495.      x_io_parms.isti = $IBIN|$RTDY|$ICRF|$OFIO|$IPKL;
  496.      x_io_parms.isti &= ~$IPST;
  497.      x_io_parms.imrs = MAXINBUF-1;
  498.      x_io_parms.ibad = -1;
  499.      x_io_parms.ircl = -1;
  500.      /* IDEL would default to NULL, FF, CR, NL as delimeters.
  501.       * The only delimeters here are CR and NL, for data sensitive 
  502.       * records.
  503.       */
  504.      idel_tbl[0] = 0x24;
  505.      x_io_parms.idel = idel_tbl;
  506.  
  507.      zero((char *) &x_io_scrn, sizeof(x_io_scrn));
  508.      x_io_parms.etsp = &x_io_scrn;     /* Screen management extension */
  509.      x_io_parms.etsp |= BIT0;           /* Turn on the high bit */
  510.      x_io_scrn.esfc &= ~$ESNE;           /* Echo input data */
  511.      x_io_scrn.esfc &= ~$ESSE;           /* No screen edit */
  512.      x_io_scrn.esfc |= $ESGT;           /* Dump ring buffer */
  513.  
  514.      memcpy((char *) &xout_parms,(char *) &x_io_parms,sizeof(x_io_parms));
  515.      xout_parms.isti = $IBIN|$RTDY|$ICRF|$OFOT;
  516.      xout_parms.etsp = 0;              /* Screen management extension */
  517.  
  518.      username = getenv("LOGNAME");
  519.      memcpy(SPACMD+11, username, min(31,strlen(username)));
  520.  
  521.      /* Zero the console characteristics arrays */
  522.      zero ((char *) charconin, sizeof(charconin));
  523.      zero ((char *) charconout, sizeof(charconout));
  524.      zero ((char *) chartty, sizeof(chartty));
  525.      zero ((char *) charttyin, sizeof(charttyin));
  526.      zero ((char *) charttyout, sizeof(charttyout));
  527.       
  528.      /* Initialize charconin & out, 
  529.       * and set up the console for CHAR/BREAK=BMOB 
  530.       */
  531.      if (isatty(0)) {
  532.           if (sys_gechr( channel(0), (1<<31)|$CLMAX, charconin)) 
  533.                { perror("sysinit: gechr 0"); return(-1); }
  534.           if (sys_gechr( channel(1), (1<<31)|$CLMAX, charconout)) 
  535.                { perror("sysinit: gechr 1"); return(-1); }
  536.           charconin[4] &= ~$CBKM;
  537.           charconin[4] |= $CBBM;
  538.           if (sys_sechr( channel(0), (1<<31)|$CLMAX, charconin)) 
  539.                { perror("sysinit: sechr "); return(-1); }
  540.      }
  541.       
  542.      return(0);
  543. }
  544.  
  545. /* S E T T O -- set timeout on the channel to period.
  546.                 Save the old characteristics in char***in[]. 
  547. */
  548.  
  549. int setto(chan, period) int chan, period; 
  550. {
  551.      int isconsole = 0;
  552.      int iscon[2];       /* Flags because i/o could be redirected */
  553.  
  554.      /* Setting is done external to here, since they can distinguish the 
  555.         console from ttyfd device.  Both console channels must be set
  556.         the same.
  557.      */
  558.      if ( (chan == channel(0)) || (chan == channel(1)) ) {
  559.           isconsole = 1; zero((char *) iscon, sizeof(iscon));
  560.           chan = channel(0);
  561.           if (sys_gechr( channel(0), (1<<31)|$CLMAX, charconin)) 
  562.                if (isatty(0)) {
  563.                     iscon[0] = 1;
  564.                     perror("setto: gechr 0: "); 
  565.                     return(-1);
  566.                }
  567.           charcurr = charconin;
  568.           if (sys_gechr( channel(1), (1<<31)|$CLMAX, charconout)) 
  569.                if (isatty(1)) {
  570.                     iscon[1] = 1;
  571.                     perror("setto: gechr 1: "); 
  572.                     return(-1);
  573.                }
  574.           timocon = period;
  575.      }
  576.  
  577.      else {
  578.           if (sys_gechr( chan, (1<<31)|$CLMAX, chartty))
  579.                { perror("setto: gechr tty: "); return(-1); }
  580.           charcurr = chartty;
  581.           timotty = period;
  582.      }
  583.  
  584.      charcurr[1] |= (0100000>>$CTO);
  585.      if (sys_sechr( chan, (1<<31)|$CLMAX, charcurr))
  586.           if ((isconsole == 0) || iscon[0]) {
  587.                perror("setto: sechr: "); 
  588.                return(-1); 
  589.           }
  590.      if (sys_stom( chan, 1<<31, period)) 
  591.           if ((isconsole == 0) || iscon[0]) {
  592.                perror("setto: stom: "); 
  593.                return(-1);
  594.           }
  595.  
  596.      if (isconsole == 0) return(0);
  597.      
  598.      chan = channel(1);
  599.      charconout[1] |= (0100000>>$CTO);
  600.      if (sys_sechr( chan, (1<<31)|$CLMAX, charconout)) 
  601.           if (iscon[1]) {
  602.                perror("setto: sechr 1: "); 
  603.                return(-1);
  604.           }
  605.      if (sys_stom( chan, 1<<31, period)) 
  606.           if (iscon[1]) {
  607.                perror("setto: stom 1: "); 
  608.                return(-1);
  609.           }
  610.      return(0);
  611. }
  612.  
  613.  
  614. /* R E S T O -- reset timeouts to the previous values, and restore char */
  615.  
  616. int resto(chan) int chan;
  617. {
  618.      int i, chan0, chan1, iscon[2];
  619.  
  620.      if ( (chan==channel(0)) || (chan==channel(1)) ) {
  621.  
  622.           chan0 = channel(0);      chan1 = channel(1); 
  623.           iscon[0] = isatty(0);    iscon[1] = isatty(1);
  624.           charconin[1] &= ~(0100000>>$CTO);
  625.           if (sys_stom( chan0, 1<<31, -1)) 
  626.                if (iscon[0]) {
  627.                     perror("resto: stom 0: "); 
  628.                     return(-1);
  629.                }
  630.           for (i = 0; i < $CLMAX; i++) if (charconin[i] != 0) {
  631.                if (sys_sechr( chan0, (1<<31)|$CLMAX, charconin))
  632.                     if (iscon[0]) {
  633.                          perror("resto: sechr 0: "); 
  634.                          return(-1); 
  635.                     }
  636.                break;
  637.           }
  638.           charconout[1] &= ~(0100000>>$CTO);
  639.           if (sys_stom( chan1, 1<<31, -1)) 
  640.                if (iscon[1]) {
  641.                     perror("resto: stom 1: "); 
  642.                     return(-1);
  643.                }
  644.           for (i = 0; i < $CLMAX; i++) if (charconout[i] != 0) {
  645.                if (sys_sechr( chan1, (1<<31)|$CLMAX, charconout)) 
  646.                if (iscon[1]) {
  647.                     perror("resto: sechr 1: "); 
  648.                     return(-1);
  649.                }
  650.                break;
  651.           }
  652.  
  653.           timocon = 0; 
  654.      }
  655.      else {
  656.           chartty[1] &= ~(0100000>>$CTO);
  657.           if (sys_stom( chan, 1<<31, -1)) 
  658.                { perror("setto: stom tty: "); return(-1); }
  659.           for (i = 0; i < $CLMAX; i++) if (chartty[i] != 0) {
  660.                if (sys_sechr( chan, (1<<31)|$CLMAX, chartty))
  661.                     { perror("resto: sechr tty: "); return(-1); }
  662.                break;
  663.           }
  664.           timotty = 0; 
  665.      }
  666.       
  667.      return(0);
  668. }
  669.  
  670.  
  671. /* S E T F L O W -- Set flow control in the device. 
  672.      
  673.     The device is assumed to be an intelligent IAC, where a CHAR/ON/IFC/OFC
  674.     could be done.
  675.  
  676. */
  677. int setflow(chan) int chan;
  678. {
  679.      short termparms[$CLMAX];
  680.  
  681.      if (sys_gechr( chan, (1<<31)|$CLMAX, termparms)) 
  682.           { perror("setflow: gechr "); return(-1); }
  683.  
  684.      bitset(&termparms[4],$XOFC,1);
  685.      bitset(&termparms[4],$XIFC,1);
  686.      
  687.      if (sys_sechr( chan, (1<<31)|$CLMAX, termparms)) 
  688.           { perror("setflow: sechr "); return(-1); }
  689.  
  690.      return(0);
  691. }
  692.  
  693.  
  694. /* R E S F L O W -- Re-Set flow control in the device. 
  695.      
  696.     The device is assumed to be an intelligent IAC, where a CHAR/OFF/IFC/OFC
  697.     could be done.
  698.  
  699. */
  700. int resflow(chan) int chan;
  701. {
  702.      int i;
  703.      short termparms[$CLMAX];
  704.  
  705.      if (sys_gechr( chan, (1<<31)|$CLMAX, termparms)) 
  706.           { perror("resflow: gechr "); return(-1); }
  707.  
  708.      bitset(&termparms[4],$XOFC,0);
  709.      bitset(&termparms[4],$XIFC,0);
  710.      
  711.      if (sys_sechr( chan, (1<<31)|$CLMAX, termparms))
  712.           { perror("resflow: sechr "); return(-1); }
  713.  
  714.      return(0);
  715. }
  716.  
  717.  
  718. /* S E T S P E E D -- Set the baud rate when not possible thru IOCTL.
  719.      
  720.     The device is assumed to be an intelligent IAC, where a CHAR/ON/BAUD=
  721.     could be done.
  722.  
  723. */
  724. int setspeed(sp) int sp;
  725. {
  726.      short termparms[$CLMAX];
  727.  
  728.      /* ttyfd is the Unix file number for the tty device.  Setting the
  729.       * characteristics will set it for both ttyfd and ttyfdout, since
  730.       * it is the device itself which is affected, and not just the 
  731.       * channel.
  732.       */
  733.      if (sys_gechr( channel(ttyfd), (1<<31)|$CLMAX, termparms)) 
  734.           { perror("setspeed: gechr "); return(-1); }
  735.  
  736.      termparms[3] &= ~$BRMSK;            /* Zero out the previous setting */
  737.      termparms[3] |= sp;
  738.      
  739.      if (sys_sechr( channel(ttyfd), (1<<31)|$CLMAX, termparms)) 
  740.           { perror("setspeed: sechr "); return(-1); }
  741.  
  742.      return(0);
  743. }
  744. #endif datageneral
  745.  
  746. /*  T T O P E N  --  Open a tty for exclusive access.  */
  747.  
  748. /*  Returns 0 on success, -1 on failure.  */
  749. /*
  750.   If called with lcl < 0, sets value of lcl as follows:
  751.   0: the terminal named by ttname is the job's controlling terminal.
  752.   1: the terminal named by ttname is not the job's controlling terminal.
  753.   But watch out: if a line is already open, or if requested line can't
  754.   be opened, then lcl remains (and is returned as) -1.
  755. */
  756. ttopen(ttname,lcl,modem) char *ttname; int *lcl, modem; {
  757.  
  758. #ifdef datageneral
  759.     /* AOS/VS special stuff */
  760.     FILE *dg_open();                    /* Custom file open */
  761.     int retrycnt = 0;                   /* Retry if Modem disc in progress */
  762. #endif
  763. #ifdef UXIII
  764.     char *ctermid();            /* Wish they all had this! */
  765. #endif
  766.  
  767.     char *x; extern char* ttyname();
  768.     char cname[DEVNAMLEN+4];
  769.  
  770.     if (ttyfd > -1) return(0);        /* If already open, ignore this call */
  771.     xlocal = *lcl;            /* Make this available to other fns */
  772. #ifdef NEWUUCP
  773.     acucntrl("disable",ttname);        /* Open getty on line (4.3BSD) */
  774. #endif
  775. #ifndef datageneral
  776. #ifdef UXIII
  777.     /* if modem connection, don't wait for carrier */
  778.     ttyfd = open(ttname,O_RDWR | (modem ? O_NDELAY : 0) );
  779. #endif
  780. #endif
  781.  
  782. #ifdef datageneral
  783.     /* A custom open is done for the device, but a FILE handle is also needed
  784.      * for doing other special operations on the device.  See sysinit() for
  785.      * the initialization of the x_io_parms and xout_parms structures.
  786.      *
  787.      * First open up the output channel ($OFOT) 
  788.      */
  789.     idel_tbl[0] = 0x4;             /* CR only */
  790.     xout_parms.idel = idel_tbl;
  791.     xout_parms.ifnp = ttname;
  792.  
  793. retry:
  794.     if ((ttfileout =
  795.        dg_open(ttname, xout_parms.isti, xout_parms.isto, 
  796.                xout_parms.imrs,xout_parms.ires,xout_parms.idel))
  797.        == NULL) {
  798.           /* If a modem disconnect, or one in progress, wait and retry. */
  799.           if ((errno == ERDCT) || (errno == ERCDS))
  800.                if (retrycnt == 0) {
  801.                     retrycnt = 1; 
  802.                     sleep(2); 
  803.                     goto retry; 
  804.                }
  805.           ttyfdout = -1;
  806.           perror("ttopen: output_line: dg_open");
  807.           return(-1);
  808.     }
  809.     /* Successfull opens fall through here! */
  810.     
  811.     ttyfdout = fileno(ttfileout);
  812.     xout_parms.ich = channel(ttyfdout);
  813.     
  814.  
  815.     /* Next, open up the input channel ($OFIN) */
  816.  
  817.     x_io_parms.ifnp = ttname;
  818.     /* IDEL would default to NULL, FF, CR, NL as delimeters.
  819.      * The only delimeters here are CR and NL, for data sensitive 
  820.      * records.
  821.      */
  822.     idel_tbl[0] = 0x24;
  823.     x_io_parms.idel = idel_tbl;
  824.  
  825.     if ((ttfile =
  826.        dg_open(ttname, x_io_parms.isti, x_io_parms.isto, 
  827.                x_io_parms.imrs,x_io_parms.ires,x_io_parms.idel,
  828.                (P_SCREEN *) x_io_parms.etsp))
  829.        == NULL) {
  830.           ttyfd = -1;
  831.           perror("ttopen: input_line: dg_open");
  832.           return(-1);
  833.        }
  834.     else {
  835.           ttyfd = fileno(ttfile);
  836.           x_io_parms.ich = channel(ttyfd);
  837.     }
  838.  
  839. #else datageneral
  840.     ttyfd = open(ttname,2);        /* Try to open for read/write */
  841.  
  842.     if (ttyfd < 0) {            /* If couldn't open, fail. */
  843.     perror(ttname);
  844.     return(-1);
  845.     }
  846. #endif
  847.  
  848.     strncpy(ttnmsv,ttname,DEVNAMLEN);    /* Open, keep copy of name locally. */
  849.  
  850. /* Caller wants us to figure out if line is controlling tty */
  851.  
  852.     debug(F111,"ttopen ok",ttname,*lcl);
  853.     if (*lcl == -1) {
  854.     if (strcmp(ttname,CTTNAM) == 0) {   /* "/dev/tty" always remote */
  855.         debug(F110," Same as CTTNAM",ttname,0);
  856.         xlocal = 0;
  857.     } else if (isatty(0)) {        /* Else, if stdin not redirected */
  858.         x = ttyname(0);        /* then compare its device name */
  859.         strncpy(cname,x,DEVNAMLEN);    /* (copy from internal static buf) */
  860.         debug(F110," ttyname(0)",x,0);
  861.         x = ttyname(ttyfd);     /* ...with real name of ttname. */
  862.         xlocal = (strncmp(x,cname,DEVNAMLEN) == 0) ? 0 : 1;
  863.         debug(F111," ttyname",x,xlocal);
  864.     } else {            /* Else, if stdin redirected... */
  865. #ifndef datageneral
  866. #ifdef UXIII
  867. /* Sys III/V provides nice ctermid() function to get name of controlling tty */
  868.             ctermid(cname);        /* Get name of controlling terminal */
  869.         debug(F110," ctermid",cname,0);
  870.         x = ttyname(ttyfd);     /* Compare with name of comm line. */
  871.         xlocal = (strncmp(x,cname,DEVNAMLEN) == 0) ? 0 : 1;
  872.         debug(F111," ttyname",x,xlocal);
  873. /* Just assume local, so "set speed" and similar commands will work */
  874. /* If not really local, how could it work anyway?... */
  875.  
  876.         xlocal = 1;
  877.         debug(F101," redirected stdin","",xlocal);
  878. #endif UXIII
  879. #endif datageneral
  880.         }
  881.     }    
  882.  
  883. /* Now check if line is locked -- if so fail, else lock for ourselves */
  884.  
  885.     lkf = 0;                /* Check lock */
  886.     if (xlocal > 0) {
  887.     if (ttlock(ttname) < 0) {
  888.         fprintf(stderr,"Exclusive access to %s denied\n",ttname);
  889.         close(ttyfd); ttyfd = -1;
  890.         debug(F110," Access denied by lock",ttname,0);
  891.  
  892.         return(-1);            /* Not if already locked */
  893.         } else lkf = 1;
  894.     }
  895.  
  896. /* Got the line, now set the desired value for local. */
  897.  
  898.     if (*lcl < 0) *lcl = xlocal;
  899.  
  900. /* Some special stuff for v7... */
  901.  
  902. #ifdef    V7
  903.     if (kmem[TTY] < 0) {    /*  If open, then skip this.  */
  904.         qaddr[TTY] = initrawq(ttyfd);    /* Init the queue. */
  905.         if ((kmem[TTY] = open("/dev/kmem", 0)) < 0) {
  906.             fprintf(stderr, "Can't read /dev/kmem in ttopen.\n");
  907.             perror("/dev/kmem");
  908.             exit(1);
  909.         }
  910.     }
  911. #endif    V7
  912.  
  913. /* Request exclusive access on systems that allow it. */
  914.  
  915. #ifndef XENIX
  916. /* Xenix exclusive access prevents open(close(...)) from working... */
  917. #ifdef TIOCEXCL
  918.         if (ioctl(ttyfd,TIOCEXCL, NULL) < 0)
  919.         fprintf(stderr,"Warning, problem getting exclusive access\n");
  920. #endif
  921. #endif
  922.  
  923. /* Get tty device settings */
  924.  
  925. #ifndef UXIII
  926.     gtty(ttyfd,&ttold);            /* Get sgtty info */
  927.     gtty(ttyfd,&ttraw);            /* And a copy of it for packets*/
  928.     gtty(ttyfd,&tttvt);            /* And one for virtual tty service */
  929. #else
  930.     ioctl(ttyfd,TCGETA,&ttold);        /* Same deal for Sys III, Sys V */
  931.     ioctl(ttyfd,TCGETA,&ttraw);
  932.     ioctl(ttyfd,TCGETA,&tttvt);
  933. #endif
  934.     debug(F101,"ttopen, ttyfd","",ttyfd);
  935. #ifdef datageneral
  936.     debug(F101,"ttopen, ttyfdout","",ttyfdout);
  937.  
  938.     /* For DG, also get the tty extended device characteristics. */
  939.     sys_gechr( channel(ttyfd), (1<<31)|$CLMAX, ch_ttold);
  940.     sys_gechr( channel(ttyfd), (1<<31)|$CLMAX, ch_ttraw);
  941.     sys_gechr( channel(ttyfd), (1<<31)|$CLMAX, ch_ttvt);
  942. #endif
  943.     debug(F101," lcl","",*lcl);
  944.     debug(F111," lock file",flfnam,lkf);
  945.     return(0);
  946. }
  947.  
  948. /*  T T C L O S  --  Close the TTY, releasing any lock.  */
  949.  
  950. ttclos() {
  951.     if (ttyfd < 0) return(0);        /* Wasn't open. */
  952.     if (xlocal) {
  953.     if (tthang())            /* Hang up phone line */
  954.         fprintf(stderr,"Warning, problem hanging up the phone\n");
  955. #ifndef datageneral
  956.         if (ttunlck())            /* Release uucp-style lock */
  957.         fprintf(stderr,"Warning, problem releasing lock\n");
  958. #endif
  959.     }
  960.     ttres();                /* Reset modes. */
  961. /* Relinquish exclusive access if we might have had it... */
  962. #ifndef XENIX
  963. #ifdef TIOCEXCL
  964. #ifdef TIOCNXCL
  965.     if (ioctl(ttyfd, TIOCNXCL, NULL) < 0)
  966.         fprintf(stderr,"Warning, problem relinquishing exclusive access\n");
  967. #endif
  968. #endif
  969. #endif
  970. #ifdef datageneral
  971.     debug(F101,"ttclos, ttyfd","",ttyfd);
  972.     debug(F101,"ttclos, ttyfdout","",ttyfdout);
  973.     fclose(ttfile);            /* Close it. */
  974.     ttyfd = -1;                /* Mark it as closed. */
  975.  
  976.     /* Close the output tty device */
  977.     fclose(ttfileout);                  /* Close it. */
  978.     ttyfdout = -1;            /* Mark it as closed. */
  979. #else
  980.     close(ttyfd);            /* Close it. */
  981. #ifdef NEWUUCP
  982.     acucntrl("enable",flfnam);        /* Close getty on line. */
  983. #endif
  984.     ttyfd = -1;                /* Mark it as closed. */
  985.  
  986. #endif
  987.     return(0);
  988. }
  989.  
  990. /*  T T H A N G -- Hangup phone line */
  991.  
  992. tthang() {
  993. #ifdef UXIII
  994.     unsigned short ttc_save;
  995. #endif
  996.  
  997.     if (ttyfd < 0) return(0);        /* Not open. */
  998. #ifdef ANYBSD
  999.     ioctl(ttyfd,TIOCCDTR,0);        /* Clear DTR */
  1000.     msleep(500);            /* Let things settle */
  1001.     ioctl(ttyfd,TIOCSDTR,0);        /* Restore DTR */
  1002. #endif
  1003. #ifdef UXIII
  1004.     ttc_save = ttraw.c_cflag;
  1005.      ttraw.c_cflag &= ~CBAUD;        /* swa: set baud rate to 0 to hangup */
  1006.     if (ioctl(ttyfd,TCSETAF,&ttraw) < 0) return(-1); /* do it */
  1007.     msleep(100);            /* let things settle */
  1008.     ttraw.c_cflag = ttc_save;
  1009. #ifndef XENIX        /* xenix cannot do close/open when carrier drops */
  1010.                 /* following corrects a PC/IX defficiency */
  1011. #ifndef aosvs
  1012.     ttc_save = fcntl(ttyfd,F_GETFL,0);
  1013. #endif
  1014. #ifdef datageneral
  1015.     if (sys_sechr( channel(ttyfd), (1<<31)|$CLMAX, ch_ttraw)) 
  1016.          { perror("tthang: sechr "); return(-1); }
  1017. #else
  1018.     close(ttyfd);        /* close/reopen file descriptor */
  1019.     if ((ttyfd = open(ttnmsv, ttc_save)) < 0) return(-1);
  1020. #endif 
  1021. #endif
  1022.     if (ioctl(ttyfd,TCSETAF,&ttraw) < 0) return(-1); /* un-do it */
  1023. #endif
  1024.     return (0);
  1025. }
  1026.  
  1027.  
  1028. /*  T T R E S  --  Restore terminal to "normal" mode.  */
  1029.  
  1030. ttres() {                /* Restore the tty to normal. */
  1031.     if (ttyfd < 0) return(-1);        /* Not open. */
  1032. #ifndef UXIII                /* except for sIII, */
  1033.     sleep(1);                /* Wait for pending i/o to finish. */
  1034. #endif                    /*   (sIII does wait in ioctls) */
  1035. #ifdef KERLD
  1036.     if (kerld) ioctl(ttyfd,TIOCSETD,&oldld); /* Restore old line discipline. */
  1037. #endif
  1038. #ifdef UXIII
  1039.     if (ioctl(ttyfd,TCSETAW,&ttold) < 0) return(-1); /* restore termio stuff */
  1040. #else
  1041.     if (stty(ttyfd,&ttold) < 0) return(-1); /* Restore sgtty stuff */
  1042. #endif
  1043. #ifdef KERLD
  1044.     if (kerld) ioctl(ttyfd,TIOCSETC,&oldc); /* Restore old special chars. */
  1045. #endif
  1046. #ifdef datageneral
  1047.     /* Un-set all the timeouts */
  1048.     if (timotty) {
  1049.          resto(channel(ttyfd));
  1050.          resto(channel(ttyfdout));
  1051.     }
  1052.     if (sys_sechr( channel(ttyfd), (1<<31)|$CLMAX, ch_ttold)) 
  1053.          { perror("ttres: sechr "); return(-1); }
  1054. #endif
  1055.  
  1056.     return(0);
  1057. }
  1058.  
  1059. /* Exclusive uucp file locking control */
  1060. /*
  1061.  by H. Fischer, creative non-Bell coding !
  1062.  copyright rights for lock modules assigned to Columbia University
  1063. */
  1064. static char *
  1065. xxlast(s,c) char *s; char c; {        /* Equivalent to strrchr() */
  1066.     int i;
  1067.     for (i = strlen(s); i > 0; i--)
  1068.         if ( s[i-1] == c ) return( s + (i - 1) );
  1069.     return(NULL);        
  1070. }
  1071. static
  1072. look4lk(ttname) char *ttname; {
  1073.     extern char *strcat(), *strcpy();
  1074.     char *device, *devname;
  1075.     char lockfil[50];            /* Max length for lock file name */
  1076.  
  1077. #ifdef ISIII
  1078.     char *lockdir = "/etc/locks";
  1079. #else
  1080. #ifdef ATT3BX
  1081.     char *lockdir = "/usr/spool/locks";
  1082. #else
  1083.     char *lockdir = "/usr/spool/uucp";
  1084. #endif
  1085. #endif
  1086.  
  1087.     device = ( (devname=xxlast(ttname,'/')) != NULL ? devname+1 : ttname);
  1088.  
  1089. #ifdef ISIII
  1090.     (void) strcpy( lockfil, device );
  1091. #else
  1092.     strcat( strcpy( lockfil, "LCK.." ), device );
  1093. #endif
  1094.  
  1095.  
  1096.     if (access( lockdir, 04 ) < 0) {    /* read access denied on lock dir */
  1097.     fprintf(stderr,"Warning, read access to lock directory denied\n");
  1098.     return( 1 );            /* cannot check or set lock file */
  1099.     }
  1100.     
  1101.     strcat(strcat(strcpy(flfnam,lockdir),"/"), lockfil);
  1102.     debug(F110,"look4lk",flfnam,0);
  1103.  
  1104.     if ( ! access( flfnam, 00 ) ) {    /* print out lock file entry */
  1105.     char lckcmd[40] ;
  1106.     strcat( strcpy(lckcmd, "ls -l ") , flfnam);
  1107.     system(lckcmd);
  1108.     if (access(flfnam,02) == 0)
  1109.         printf("(You may type \"! rm %s\" to remove this file)\n",flfnam);
  1110.     return( -1 );
  1111.     }
  1112.     if ( access( lockdir, 02 ) < 0 ) {    /* lock file cannot be written */
  1113.     fprintf(stderr,"Warning, write access to lock directory denied\n");
  1114.     return( 1 );
  1115.     }
  1116.  
  1117.     return( 0 );            /* okay to go ahead and lock */
  1118. }
  1119.  
  1120. /*  T T L O C K  */
  1121.  
  1122.  
  1123. static
  1124. ttlock(ttyfd) char *ttyfd; {        /* lock uucp if possible */
  1125. #ifdef ATT3BX
  1126.     FILE *lck_fild;
  1127. #endif
  1128. #ifdef datageneral
  1129.     /* The Data General locks a device when that device is opened.  So
  1130.      * return that the device is already locked.
  1131.      * Besides, because of internal multi-tasking, locking the device by
  1132.      * the ?ASSIGN call or an $IEXO flag would cause problem for the task
  1133.      * id that did not open the device first.
  1134.      */
  1135. #else datageneral
  1136.     int lck_fil, l4l;
  1137.     int pid_buf = getpid();        /* pid to save in lock file */
  1138.     
  1139.     hasLock = 0;            /* not locked yet */
  1140.     l4l = look4lk(ttyfd);
  1141.     if (l4l < 0) return (-1);        /* already locked */
  1142.     if (l4l == 1) return (0);        /* can't read/write lock directory */
  1143.     lck_fil = creat(flfnam, 0444);    /* create lock file ... */
  1144.     if (lck_fil < 0) return (-1);    /* create of lockfile failed */
  1145.         /* creat leaves file handle open for writing -- hf */
  1146. #ifdef ATT3BX
  1147.     fprintf((lck_fild = fdopen(lck_fil, "w")), "%10d\n", pid_buf);
  1148.     fflush(lck_fild);
  1149. #else
  1150.     write (lck_fil, &pid_buf, sizeof(pid_buf) ); /* uucp expects int in file */
  1151. #endif
  1152.     close (lck_fil);
  1153. #endif datageneral
  1154.     hasLock = 1;            /* now is locked */
  1155.     return(0);
  1156. }
  1157.  
  1158. /*  T T U N L O C K  */
  1159.  
  1160. static
  1161. ttunlck() {                /* kill uucp lock if possible */
  1162. #ifdef datageneral
  1163.     /* The DG automatically unlocks the device when it is closed, or when
  1164.      * the process is terminated for any reason.  Unlocking is not needed.
  1165.      * Also, see the note for ttlock().
  1166.      */
  1167.     return(0);
  1168. #else
  1169.     if (hasLock) return( unlink( flfnam ) ); 
  1170. #endif
  1171. }
  1172.  
  1173. /*  T T P K T  --  Condition the communication line for packets. */
  1174. /*        or for modem dialing */
  1175.  
  1176. #define DIALING    4        /* flags (via flow) for modem handling */
  1177. #define CONNECT 5
  1178.  
  1179. /*  If called with speed > -1, also set the speed.  */
  1180.  
  1181. /*  Returns 0 on success, -1 on failure.  */
  1182.  
  1183. ttpkt(speed,flow) int speed, flow; {
  1184.     int s;
  1185.     if (ttyfd < 0) return(-1);        /* Not open. */
  1186.  
  1187.  
  1188. #ifdef KERLD
  1189. /* Note, KERLD ignores the TANDEM, ECHO, and CRMOD bits */
  1190.     if (kerld) {
  1191.     ioctl(ttyfd,TIOCGETD,&oldld);    /* Get line discipline */
  1192.     ioctl(ttyfd,TIOCGETC,&oldc);    /* Get special chars */
  1193.     newc = oldc;            /* Copy special chars */
  1194.     newc.t_brkc = '\r';        /* Set CR to be break character */
  1195.     if(ioctl(ttyfd,TIOCSETC,&newc) < 0) return(-1);
  1196.     }
  1197. #endif
  1198.  
  1199.     s = ttsspd(speed);            /* Check the speed */
  1200.  
  1201. #ifndef UXIII
  1202.     if (flow == 1) ttraw.sg_flags |= TANDEM; /* Use XON/XOFF if selected */
  1203.     if (flow == 0) ttraw.sg_flags &= ~TANDEM;
  1204.     ttraw.sg_flags |= RAW;        /* Go into raw mode */
  1205.     ttraw.sg_flags &= ~(ECHO|CRMOD);    /* Use CR for break character */
  1206. #ifdef TOWER1
  1207.     ttraw.sg_flags &= ~ANYP;         /* Must tell Tower no parityr */
  1208. #endif
  1209.     if (s > -1) ttraw.sg_ispeed = ttraw.sg_ospeed = s; /* Do the speed */
  1210.     if (stty(ttyfd,&ttraw) < 0) return(-1);    /* Set the new modes. */
  1211.  
  1212.  
  1213. #ifdef MYREAD
  1214. #ifdef BSD4
  1215. /* Try to make reads nonblocking */
  1216.     if (kerld == 0) {
  1217.     if (fcntl(ttyfd,F_SETFL,fcntl(ttyfd,F_GETFL,0) & FNDELAY) == -1)
  1218.             return(-1);
  1219.     else return(0);
  1220.     }
  1221. #endif
  1222. #endif
  1223. #endif
  1224.  
  1225. #ifdef UXIII
  1226.     if (flow == 1) ttraw.c_iflag |= (IXON|IXOFF);
  1227.     if (flow == 0) ttraw.c_iflag &= ~(IXON|IXOFF);
  1228.  
  1229.     if (flow == DIALING)  ttraw.c_cflag |= CLOCAL|HUPCL;
  1230.     if (flow == CONNECT)  ttraw.c_cflag &= ~CLOCAL;
  1231.  
  1232.     ttraw.c_lflag &= ~(ICANON|ECHO);
  1233.     ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|INPCK|ISTRIP|IXANY);
  1234.     ttraw.c_oflag &= ~OPOST;
  1235. #ifdef datageneral
  1236.     ttraw.c_lflag &= ~CSETPM;      /* No DG page mode */
  1237. #endif
  1238.     ttraw.c_cc[4] = 1;
  1239.     ttraw.c_lflag |= ISIG;        /* do check for interrupt */
  1240.     ttraw.c_iflag |= (BRKINT|IGNPAR);
  1241.     ttraw.c_cflag &= ~(CSIZE|PARENB);
  1242.     ttraw.c_cflag |= (CS8|CREAD);
  1243.     ttraw.c_cc[5] = 0;
  1244.  
  1245.     if (s > -1) ttraw.c_cflag &= ~CBAUD, ttraw.c_cflag |= s; /* set speed */
  1246.  
  1247.     if (ioctl(ttyfd,TCSETAW,&ttraw) < 0) return(-1);  /* set new modes . */
  1248. #ifdef datageneral
  1249.     if (flow == 1) {
  1250.          setflow(channel(ttyfdout));
  1251.          setflow(channel(ttyfd));
  1252.     }
  1253.     if (flow == 0) {
  1254.          resflow(channel(ttyfdout));
  1255.          resflow(channel(ttyfd));
  1256.     }
  1257.     if (sys_gechr( channel(ttyfd), (1<<31)|$CLMAX, ch_ttraw)) 
  1258.          { perror("ttpkt: gechr: "); return(-1); }
  1259. #endif
  1260.  
  1261.     if (flow == DIALING) {
  1262. #ifdef datageneral
  1263. #ifndef aosvs
  1264.     if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0)) < 0 )
  1265.         return(-1);
  1266. #endif
  1267. #else
  1268.     if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY) < 0 )
  1269.         return(-1);
  1270.     close( open(ttnmsv,2) );    /* magic to force mode change!!! */
  1271. #endif
  1272.     }
  1273.  
  1274. #endif
  1275.  
  1276. #ifdef KERLD
  1277.     if (kerld) {
  1278.     if (ioctl(ttyfd,TIOCSETD,&ld) < 0)
  1279.         return(-1); /* Set line discpline. */
  1280.     }
  1281. #endif
  1282.  
  1283.     ttflui();                /* Flush any pending input */
  1284.     return(0);
  1285. }
  1286.  
  1287. /*  T T V T -- Condition communication line for use as virtual terminal  */
  1288.  
  1289. ttvt(speed,flow) int speed, flow; {
  1290.     int s;
  1291.     if (ttyfd < 0) return(-1);        /* Not open. */
  1292.  
  1293.     s = ttsspd(speed);            /* Check the speed */
  1294.  
  1295. #ifndef UXIII
  1296.     if (flow == 1) tttvt.sg_flags |= TANDEM; /* XON/XOFF if selected */
  1297.     if (flow == 0) tttvt.sg_flags &= ~TANDEM;
  1298.     tttvt.sg_flags |= RAW;        /* Raw mode */
  1299. #ifdef TOWER1
  1300.     tttvt.sg_flags &= ~(ECHO|ANYP);    /* No echo or system III ??? parity */
  1301. #else
  1302.     tttvt.sg_flags &= ~ECHO;        /* No echo */
  1303. #endif    
  1304.     if (s > -1) tttvt.sg_ispeed = tttvt.sg_ospeed = s; /* Do the speed */
  1305.     if (stty(ttyfd,&tttvt) < 0) return(-1);
  1306. #ifdef MYREAD
  1307. #ifdef BSD4
  1308. /* Make reads nonblocking */
  1309.     if (kerld == 0) {
  1310.     if (fcntl(ttyfd,F_SETFL,fcntl(ttyfd,F_GETFL,0) & FNDELAY) == -1)
  1311.         return(-1);
  1312.     else return(0);
  1313.     }
  1314. #endif
  1315. #endif
  1316.  
  1317.     if (flow == 1) tttvt.c_iflag |= (IXON|IXOFF);
  1318.     if (flow == 0) tttvt.c_iflag &= ~(IXON|IXOFF);
  1319.  
  1320.     if (flow == DIALING)  tttvt.c_cflag |= CLOCAL|HUPCL;
  1321.     if (flow == CONNECT)  tttvt.c_cflag &= ~CLOCAL;
  1322.  
  1323.     tttvt.c_lflag &= ~(ISIG|ICANON|ECHO);
  1324.     tttvt.c_iflag |= (IGNBRK|IGNPAR);
  1325.     tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|IUCLC|BRKINT|INPCK|ISTRIP|IXANY);
  1326.     tttvt.c_oflag &= ~OPOST;
  1327.     tttvt.c_cflag &= ~(CSIZE|PARENB);
  1328.     tttvt.c_cflag |= (CS8|CREAD);
  1329.     tttvt.c_cc[4] = 1;
  1330.     tttvt.c_cc[5] = 0;
  1331.  
  1332.     if (s > -1) tttvt.c_cflag &= ~CBAUD, tttvt.c_cflag |= s; /* set speed */
  1333.  
  1334.     if (ioctl(ttyfd,TCSETAW,&tttvt) < 0) return(-1);  /* set new modes . */
  1335.  
  1336. #ifdef datageneral
  1337.     if (flow == 1) {
  1338.          setflow(channel(ttyfdout));
  1339.          setflow(channel(ttyfd));
  1340.     }
  1341.     if (flow == 0) {
  1342.          resflow(channel(ttyfdout));
  1343.          resflow(channel(ttyfd));
  1344.     }
  1345.     if (sys_gechr( channel(ttyfd), (1<<31)|$CLMAX, ch_ttvt)) 
  1346.          { perror("ttvt: gechr: "); return(-1); }
  1347. #endif
  1348.  
  1349.     if (flow == DIALING) {
  1350. #ifdef datageneral
  1351. #ifndef aosvs
  1352.     if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0)) < 0 )
  1353.         return(-1);
  1354. #endif
  1355. #else
  1356.     if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY) < 0 )
  1357.         return(-1);
  1358.     close( open(ttnmsv,2) );    /* magic to force mode change!!! */
  1359. #endif
  1360.     }
  1361.     return(0);
  1362. #endif
  1363. }
  1364.  
  1365. /*  T T S S P D  --  Return the internal baud rate code for 'speed'.  */
  1366.  
  1367. ttsspd(speed) {
  1368.     int s, spdok;
  1369.  
  1370.     if (speed < 0) return(-1);
  1371.     spdok = 1;            /* Assume arg ok */
  1372.     switch (speed) {
  1373.         case 0:    s = B0;    break;    /* Just the common ones. */
  1374.         case 110:  s = B110;  break;    /* The others from ttydev.h */
  1375.         case 150:  s = B150;  break;    /* could also be included if */
  1376.         case 300:  s = B300;  break;    /* necessary... */
  1377.         case 600:  s = B600;  break;
  1378.         case 1200: s = B1200; break;
  1379.         case 1800: s = B1800; break;
  1380.  
  1381.         case 2400: s = B2400; break;
  1382.         case 4800: s = B4800; break;
  1383.         case 9600: s = B9600; break;
  1384. #ifdef PLEXUS
  1385.         case 19200: s = EXTA; break;
  1386. #else
  1387. #ifdef datageneral
  1388.             /* ioctl() allows other speeds */
  1389.             case 50:     s = B50; break;
  1390.             case 75:     s = B75; break;
  1391.             case 134:    s = B134; break;
  1392.             case 3600:   s = B3600; break;
  1393.             case 7200:   s = B7200; break;
  1394.             case 19200:  s = B19000; break;
  1395.  
  1396.             /* Some speeds are supported by the hardware thru PMGR.
  1397.                We don't bother about 45.5 but it could be added.
  1398.             */
  1399.             case 38400:  if (setspeed($CR38K)) spdok = 0; s = 0; break;
  1400. #endif
  1401. #endif
  1402.         default:
  1403.             spdok = 0;
  1404.         fprintf(stderr,"Unsupported line speed - %d\n",speed);
  1405.         fprintf(stderr,"Current speed not changed\n");
  1406.         break;
  1407.     }        
  1408.     if (spdok) return(s); else return(-1);
  1409.  }
  1410.  
  1411.  
  1412.  
  1413. /*  T T F L U I  --  Flush tty input buffer */
  1414.  
  1415. ttflui() {
  1416.  
  1417. #ifndef UXIII
  1418.     long n;
  1419. #endif
  1420.     if (ttyfd < 0) return(-1);        /* Not open. */
  1421.  
  1422.     ungotn = -1;            /* Initialize myread() stuff */
  1423.     inbufc = 0;
  1424.  
  1425. #ifdef UXIII
  1426. #ifdef datageneral
  1427.     /* Since $ESGT is turned on in the sys_read packets, there is never a need
  1428.      * to flush the input buffer -- the system automatically does it each time
  1429.      * a read is issued.
  1430.      */
  1431. #else
  1432.     if (ioctl(ttyfd,TCFLSH,0) < 0) perror("flush failed");
  1433. #endif
  1434. #else
  1435. #ifdef TIOCFLUSH
  1436. #ifdef ANYBSD
  1437.     n = FREAD;                /* Specify read queue */
  1438.     if (ioctl(ttyfd,TIOCFLUSH,&n) < 0) perror("flush failed");
  1439. #else
  1440.     if (ioctl(ttyfd,TIOCFLUSH,0) < 0) perror("flush failed");
  1441. #endif
  1442. #endif
  1443. #endif
  1444.     return(0);
  1445. }
  1446.  
  1447. /* Interrupt Functions */
  1448.  
  1449.  
  1450. /* Timeout handler for communication line input functions */
  1451.  
  1452. timerh() {
  1453.     longjmp(sjbuf,1);
  1454. }
  1455.  
  1456.  
  1457. /* Set up terminal interrupts on console terminal */
  1458.  
  1459. #ifdef UXIII
  1460. esctrp() {                /* trap console escapes (^\) */
  1461.  
  1462.     conesc = 1;
  1463.     signal(SIGQUIT,SIG_IGN);        /* ignore until trapped */
  1464. }
  1465. #endif
  1466.  
  1467. #ifdef V7
  1468. esctrp() {                /* trap console escapes (^\) */
  1469.     conesc = 1;
  1470.     signal(SIGQUIT,SIG_IGN);        /* ignore until trapped */
  1471. }
  1472. #endif
  1473.  
  1474.  
  1475. #ifdef C70
  1476. esctrp() {                /* trap console escapes (^\) */
  1477.     conesc = 1;
  1478.     signal(SIGQUIT,SIG_IGN);        /* ignore until trapped */
  1479. }
  1480. #endif
  1481.  
  1482. /*  C O N I N T  --  Console Interrupt setter  */
  1483.  
  1484. conint(f) int (*f)(); {            /* Set an interrupt trap. */
  1485.  
  1486.     if (!isatty(0)) return(0);        /* only for real ttys */
  1487.     if (backgrd) return;        /* must ignore signals in bkgrd */
  1488.  
  1489. /*
  1490.  Except for special cases below, ignore keyboard quit signal.
  1491.  ^\ too easily confused with connect escape, and besides, we don't want
  1492.  to leave lock files around.  (Frank Prindle)
  1493. */
  1494. #ifdef datageneral
  1495.     /* Set up the asynchronous task to read the console. 
  1496.      * But, I don't want them set up all the time, so I will kludge up the
  1497.      * call in  chkint() (ckuus3.c) to see if this asynch task is running:
  1498.      * conint_mt()
  1499.      */
  1500. #endif
  1501.     signal(SIGQUIT,SIG_IGN);
  1502.  
  1503. #ifdef UXIII
  1504.     signal(SIGQUIT,esctrp);        /* console escape in pkt modes */
  1505.     if (conesc) {            /* clear out pending escapes */
  1506.     conesc = 0;
  1507.     }
  1508. #endif
  1509.  
  1510. #ifdef V7
  1511.     signal(SIGQUIT,esctrp);        /* console escape in pkt modes */
  1512.     if (conesc) {            /* clear out pending escapes */
  1513.     conesc = 0;
  1514.     }
  1515. #endif
  1516.  
  1517.     if (conif) return;            /* Nothing to do if already on. */
  1518.  
  1519. /* check if invoked in background -- if so signals set to be ignored */
  1520.  
  1521.  
  1522.     if (signal(SIGINT,SIG_IGN) == SIG_IGN) {
  1523.     backgrd = 1;            /*   means running in background */
  1524. #ifdef UXIII
  1525.     signal(SIGQUIT,SIG_IGN);    /*   must leave signals ignored */
  1526. #endif
  1527. #ifdef V7
  1528.     signal(SIGQUIT,SIG_IGN);    /*   must leave signals ignored */
  1529. #endif
  1530.     return;
  1531.     }
  1532.     signal(SIGINT,f);            /* Function to trap to on interrupt. */
  1533.     signal(SIGHUP,f);            /* Or hangup, so lock file cleared. */
  1534.     conif = 1;                /* Flag console interrupts on. */
  1535. }
  1536.  
  1537.  
  1538. /*  C O N N O I  --  Reset console terminal interrupts */
  1539.  
  1540. connoi() {                /* Console-no-interrupts */
  1541.  
  1542.     if (!isatty(0)) return(0);        /* only for real ttys */
  1543.     if (backgrd) return;        /* Ignore signals in background */
  1544.  
  1545. #ifdef datageneral
  1546.     /* Terminate the asynchronous task that reads the console for
  1547.      * interrupt characters. 
  1548.      * But, I don't want to kill this task all the time, so I will kludge 
  1549.      * up the call in input() (ckcfn2.c) to kill the asynch task if it
  1550.      * is running: connoi_mt()
  1551.      */
  1552. #endif
  1553.     signal(SIGINT,SIG_DFL);
  1554.     signal(SIGHUP,SIG_DFL);
  1555.     signal(SIGQUIT,SIG_DFL);
  1556.     conif = 0;                /* Flag interrupt trapping off */
  1557. }
  1558.  
  1559. #ifdef datageneral
  1560. /* C O N I N T _ M T  -- Asynch read console task */
  1561.  
  1562. void conint_mt() {
  1563.     /* Any input waiting? */
  1564.     con_reads_mt = 1;                   /* Flag that task is active */
  1565.     conint_avl = 0;                     /* Flag that interrupt gotten */
  1566.     while (con_reads_mt)
  1567.         /* Get a char; 
  1568.          * then, wait 2 seconds for the system to respond to it. 
  1569.          */
  1570.         if ((conint_ch = coninc(2)) <= 0) {
  1571.             conint_avl = 1;
  1572.             sleep(5);
  1573.         }
  1574.     conint_avl = 0;
  1575. }
  1576.  
  1577.  
  1578. /* C O N N O I _ M T  -- Kill asynch read console task */
  1579.  
  1580. connoi_mt() {
  1581.     con_reads_mt = 0;
  1582.     conint_avl = 0;
  1583.     midkill(CONINT_TSK);
  1584. }
  1585.  
  1586.  
  1587. /* C O N S T A _ M T  --  Start the console asynch read task */
  1588.  
  1589. consta_mt() {
  1590.     if ((con_reads_mt == 0)      /* Not already running */
  1591.      && (mtask(conint_mt, CONINT_STACK, CONINT_TSK, CONINT_PRI) != 0))
  1592.         perror("consta_mt: Can't initiate task:");
  1593. }
  1594. #endif datageneral
  1595.  
  1596. /*  myread() -- For use by systems that can do nonblocking read() calls  */
  1597. /*
  1598.  Returns:
  1599.   -1  if no characters available,
  1600.   -2  upon error (such as disconnect),
  1601.   otherwise value of character (0 or greater)
  1602.  
  1603. */
  1604. myread() {
  1605.     static int inbuf_item;
  1606. #ifdef datageneral
  1607.     static CHAR inbuf[MAXINBUF];
  1608. #else
  1609.     static CHAR inbuf[257];
  1610. #endif
  1611.     CHAR readit;
  1612.     
  1613.     if (ungotn >= 0) {
  1614.     readit = ungotn;
  1615.     } else {
  1616.         if (inbufc > 0) {
  1617.         readit = inbuf[++inbuf_item];
  1618.         } else {
  1619. #ifdef datageneral
  1620.         if ((inbufc = dgncinb(ttyfd,inbuf,MAXINBUF-1)) == 0) {  
  1621.             /* end of file */
  1622.         return(-2);        /* end of file has no errno */
  1623.         }
  1624.         if (inbufc < 0) {        /* Real error */
  1625.              /* No data available if == -1.  Unix can never return -1 ?? */
  1626.              if (inbufc == -1) return(-1);
  1627.                 if ((inbufc == -ERDCT) || (inbufc == -ERCDS))
  1628.                      /* Modem disconnected, or in progress of same */
  1629.                  errno = 9999;    /* magic number for no carrier */
  1630. #else
  1631.         if ((inbufc = read(ttyfd,inbuf,256)) == 0) {  /* end of file */
  1632.             /* means carrier dropped on modem connection */
  1633.         errno = 9999;        /* magic number for no carrier */
  1634.         return(-2);        /* end of file has no errno */
  1635.         }
  1636.         if (inbufc < 0) {        /* Real error */
  1637. #endif
  1638.                 return(-2);
  1639.             }
  1640.         readit = inbuf[inbuf_item = 0];
  1641.     }
  1642.         inbufc--;    
  1643.     }
  1644.     ungotn = -1;
  1645.     return(readit);
  1646. }
  1647.  
  1648. myunrd(ch) CHAR ch; {            /* push back up to one character */
  1649.     ungotn = ch;
  1650. }
  1651.  
  1652. /*  I N I T R A W Q  --  Set up to read /DEV/KMEM for character count.  */
  1653.  
  1654. #ifdef    V7
  1655. /*
  1656.  Used in Version 7 to simulate Berkeley's FIONREAD ioctl call.  This
  1657.  eliminates blocking on a read, because we can read /dev/kmem to get the
  1658.  number of characters available for raw input.  If your system can't
  1659.  or you won't let it read /dev/kmem (the world that is) then you must
  1660.  figure out a different way to do the counting of characters available,
  1661.  or else replace this by a dummy function that always returns 0.
  1662. */
  1663. /*
  1664.  * Call this routine as: initrawq(tty)
  1665.  * where tty is the file descriptor of a terminal.  It will return
  1666.  * (as a char *) the kernel-mode memory address of the rawq character
  1667.  * count, which may then be read.  It has the side-effect of flushing
  1668.  * input on the terminal.
  1669.  */
  1670. /*
  1671.  * John Mackin, Physiology Dept., University of Sydney (Australia)
  1672.  * ...!decvax!mulga!physiol.su.oz!john
  1673.  *
  1674.  
  1675.  * Permission is hereby granted to do anything with this code, as
  1676.  * long as this comment is retained unmodified and no commercial
  1677.  * advantage is gained.
  1678.  */
  1679. #include <a.out.h>
  1680. #include <sys/proc.h>
  1681.  
  1682. char *initrawq(tty) int tty; {
  1683. #ifdef UTS24
  1684.     return(0);
  1685. #else
  1686. #ifdef BSD29
  1687.     return(0);
  1688. #else
  1689.     long lseek();
  1690.     static struct nlist nl[] = {
  1691.     {PROCNAME},
  1692.     {NPROCNAME},
  1693.     {""}
  1694.  
  1695.     };
  1696.     static struct proc *pp;
  1697.     char *malloc(), *qaddr, *p, c;
  1698.     int m, pid, me;
  1699.     NPTYPE xproc;            /* Its type is defined in makefile. */
  1700.     int catch();
  1701.  
  1702.     me = getpid();
  1703.     if ((m = open("/dev/kmem", 0)) < 0) err("kmem");
  1704.  
  1705.     nlist(BOOTNAME, nl);
  1706.     if (nl[0].n_type == 0) err("proc array");
  1707.  
  1708.     if (nl[1].n_type == 0) err("nproc");
  1709.  
  1710.     lseek(m, (long)(nl[1].n_value), 0);
  1711.     read (m, &xproc, sizeof(xproc));
  1712.     signal(SIGALRM, catch);
  1713.     if ((pid = fork()) == 0) {
  1714.     while(1)
  1715.         read(tty, &c, 1);
  1716.     }
  1717.     alarm(2);
  1718.  
  1719.     if(setjmp(jjbuf) == 0) {
  1720.     while(1)
  1721.         read(tty, &c, 1);
  1722.     }
  1723.     signal(SIGALRM, SIG_DFL);
  1724.  
  1725. #ifdef DIRECT
  1726.     pp = (struct proc *) nl[0].n_value;
  1727. #else 
  1728.     if (lseek(m, (long)(nl[0].n_value), 0) < 0L) err("seek");
  1729.     if (read(m, &pp, sizeof(pp)) != sizeof(pp))  err("no read of proc ptr");
  1730. #endif
  1731.     lseek(m, (long)(nl[1].n_value), 0);
  1732.     read(m, &xproc, sizeof(xproc));
  1733.  
  1734.     if (lseek(m, (long)pp, 0) < 0L) err("Can't seek to proc");
  1735.     if ((p = malloc(xproc * sizeof(struct proc))) == NULL) err("malloc");
  1736.     if (read(m,p,xproc * sizeof(struct proc)) != xproc*sizeof(struct proc))
  1737.         err("read proc table");
  1738.     for (pp = (struct proc *)p; xproc > 0; --xproc, ++pp) {
  1739.     if (pp -> p_pid == (short) pid) goto iout;
  1740.     }
  1741.     err("no such proc");
  1742.  
  1743. iout:
  1744.     close(m);
  1745.     qaddr = (char *)(pp -> p_wchan);
  1746.  
  1747.     free (p);
  1748.     kill(pid, SIGKILL);
  1749.     wait((int *)0);        /* Destroy the ZOMBIEs! */
  1750.     return (qaddr);
  1751. #endif
  1752. #endif
  1753. }
  1754.  
  1755. /*  More V7-support functions...  */
  1756.  
  1757. static
  1758. err(s) char *s; {
  1759.     char buf[200];
  1760.  
  1761.     sprintf(buf, "fatal error in initrawq: %s", s);
  1762.     perror(buf);
  1763.     doexit(1);
  1764. }
  1765.  
  1766. static
  1767. catch() {
  1768.     longjmp(jjbuf, -1);
  1769. }
  1770.  
  1771.  
  1772. /*  G E N B R K  --  Simulate a modem break.  */
  1773.  
  1774. #define    BSPEED    B150
  1775.  
  1776. genbrk(fn) int fn; {
  1777.     struct sgttyb ttbuf;
  1778.     int ret, sospeed;
  1779.  
  1780.     ret = ioctl(fn, TIOCGETP, &ttbuf);
  1781.     sospeed = ttbuf.sg_ospeed;
  1782.     ttbuf.sg_ospeed = BSPEED;
  1783.     ret = ioctl(fn, TIOCSETP, &ttbuf);
  1784.     ret = write(fn, "\0\0\0\0\0\0\0\0\0\0\0\0", 8);
  1785.     ttbuf.sg_ospeed = sospeed;
  1786.     ret = ioctl(fn, TIOCSETP, &ttbuf);
  1787.     ret = write(fn, "@", 1);
  1788.  
  1789.     return;
  1790. }
  1791. #endif    V7
  1792.  
  1793. /*  T T C H K  --  Tell how many characters are waiting in tty input buffer  */
  1794.  
  1795. ttchk() {
  1796.     int x; long n;
  1797. #ifdef datageneral
  1798.     /* FIONREAD is defined, so exit here */
  1799.     return(inbufc + (ungotn >= 0) );    
  1800. #endif
  1801. #ifdef FIONREAD
  1802.     x = ioctl(ttyfd, FIONREAD, &n);    /* Berkeley and maybe some others */
  1803.     debug(F101,"ttchk","",n);
  1804.     return((x < 0) ? 0 : n);
  1805. #else
  1806. #ifdef    V7
  1807.     lseek(kmem[TTY], (long) qaddr[TTY], 0);
  1808.     x = read(kmem[TTY], &n, sizeof(int));
  1809.     return((x == sizeof(int))? n: 0);
  1810. #else    V7
  1811. #ifdef UXIII
  1812.     return(inbufc + (ungotn >= 0) );    
  1813. #else
  1814. #ifdef C70
  1815.     return(inbufc + (ungotn >= 0) );
  1816. #else
  1817. #ifdef PROVX1
  1818.     x = ioctl(ttyfd, TIOCQCNT, &ttbuf);
  1819.     n = ttbuf.sg_ispeed & 0377;
  1820.     return((x < 0) ? 0 : n);
  1821. #else
  1822.     return(0);
  1823. #endif
  1824. #endif
  1825.  
  1826. #endif
  1827. #endif
  1828. #endif
  1829. }
  1830.  
  1831.  
  1832. /*  T T X I N  --  Get n characters from tty input buffer  */
  1833.  
  1834. /*  Returns number of characters actually gotten, or -1 on failure  */
  1835.  
  1836. /*  Intended for use only when it is known that n characters are actually */
  1837. /*  Available in the input buffer.  */
  1838.  
  1839. ttxin(n,buf) int n; char *buf; {
  1840.     int x;
  1841.     CHAR c;
  1842.  
  1843. #ifdef MYREAD
  1844.     for( x = 0; (x > -1) && (x < n); buf[x++] = myread() );
  1845. #else
  1846.     debug(F101,"ttxin: n","",n);
  1847.     x = read(ttyfd,buf,n);
  1848.     debug(F101," x","",x);
  1849. #endif
  1850.     if (x > 0) buf[x] = '\0';
  1851.     if (x < 0) x = -1;
  1852.     return(x);
  1853. }
  1854.  
  1855. /*  T T O L  --  Similar to "ttinl", but for writing.  */
  1856.  
  1857. ttol(s,n) int n; char *s; {
  1858.     int x;
  1859. #ifdef datageneral
  1860.     if (ttyfdout < 0) return(-1);    /* Not open. */
  1861.     x = dgncoub(ttyfdout,s,n); 
  1862. #else
  1863.     if (ttyfd < 0) return(-1);        /* Not open. */
  1864.     x = write(ttyfd,s,n);
  1865. #endif
  1866.     debug(F111,"ttol",s,n);
  1867.     if (x < 0) debug(F101,"ttol failed","",x);
  1868.     return(x);
  1869. }
  1870.  
  1871.  
  1872. /*  T T O C  --  Output a character to the communication line  */
  1873.  
  1874. ttoc(c) char c; {
  1875. #ifdef datageneral
  1876.     if (ttyfdout < 0) return(-1);    /* Not open. */
  1877.     return(dgncoub(ttyfdout,&c,1)); 
  1878. #else
  1879.     if (ttyfd < 0) return(-1);        /* Not open. */
  1880.     return(write(ttyfd,&c,1));
  1881. #endif
  1882. }
  1883. /*  T T I N L  --  Read a record (up to break character) from comm line.  */
  1884. /*
  1885.   If no break character encountered within "max", return "max" characters,
  1886.   with disposition of any remaining characters undefined.  Otherwise, return
  1887.   the characters that were read, including the break character, in "dest" and
  1888.   the number of characters read as the value of function, or 0 upon end of
  1889.   file, or -1 if an error occurred.  Times out & returns error if not completed
  1890.   within "timo" seconds.
  1891. */
  1892.  
  1893. ttinl(dest,max,timo,eol) int max,timo; char *dest; char eol; {
  1894.     int x, y;
  1895.     CHAR c;
  1896.  
  1897.     if (ttyfd < 0) return(-1);        /* Not open. */
  1898.     if (timo <= 0) {            /* Untimed read... */
  1899.  
  1900. #ifdef MYREAD
  1901.     for (x = c = 0; (x < max) && (c != eol); x++) {
  1902.          while ((y = myread()) == -1) ;
  1903.          if (y == -2) return(-1);
  1904.          dest[x] = c = y & 0377;
  1905.     }
  1906. #else
  1907.     x = read(ttyfd,dest,max);    /* Try to read. */
  1908. #endif
  1909.     return(x);            /* Return the count. */
  1910.     }
  1911.  
  1912. /* Timed read... */
  1913.  
  1914. #ifdef datageneral
  1915.      /* Peform timeout setting only once per device */
  1916.      if (timotty != timo) { 
  1917.           resto(channel(ttyfd));        /* Save previous settings */
  1918.           setto(channel(ttyfd),timo);   /* Set the new timeout values */
  1919.      }
  1920.      {
  1921. #else
  1922.     signal(SIGALRM,timerh);        /* Set up timeout action. */
  1923.     alarm(timo);            /* Set the timer. */
  1924.     if (setjmp(sjbuf))            /* Do this if timer went off. */
  1925.         x = -1;
  1926.     else if (kerld) {            /* Efficient Kermit line discipline */
  1927.     x = read(ttyfd,dest,max);    /* for 4.2bsd only... */
  1928.     } else {                /* Normal case... */
  1929. #endif        
  1930.     for (x = c = y = 0; (x < max) && (c != eol); x++) {
  1931. #ifdef MYREAD
  1932.             while ((y = myread()) == -1) /* Use own buffering if we can */
  1933.             ;
  1934.         if (y == -2) y++;
  1935.         c = y & 0377;
  1936. #else
  1937.         while ((y = read(ttyfd,&c,1)) == 0) /* Else call system */
  1938.             ;            /* ...for each character. */
  1939. #endif MYREAD
  1940.         if (y < 0) {
  1941. #ifdef datageneral
  1942.                resto(channel(ttyfd));
  1943. #else
  1944.            alarm(0);        /* Error, turn off timer, */
  1945.               signal(SIGALRM,SIG_DFL); /* and associated interrupt. */
  1946. #endif
  1947.            return(y);        /* Return the error indication. */
  1948.         }
  1949.             dest[x] = c;
  1950.     }
  1951.     x++;
  1952.     }
  1953.  
  1954. #ifndef datageneral
  1955.     alarm(0);                /* Success, turn off timer, */
  1956.     signal(SIGALRM,SIG_DFL);        /* and associated interrupt. */
  1957. #endif
  1958.     return(x);                /* Return the count. */
  1959. }
  1960.  
  1961. /*  T T I N C --  Read a character from the communication line  */
  1962.  
  1963. ttinc(timo) int timo; {
  1964.     int n = 0;
  1965.     CHAR ch = 0;
  1966.  
  1967.     if (ttyfd < 0) return(-1);        /* Not open. */
  1968.     if (timo <= 0) {            /* Untimed. */
  1969. #ifdef MYREAD
  1970.         /* comm line failure returns -1 thru myread, so no &= 0377 */
  1971.         while ((n = myread()) == -1) ;    /* Wait for a character... */
  1972.     if (n == -2) n++;
  1973.     return( n );
  1974. #else
  1975.     while ((n = read(ttyfd,&ch,1)) == 0) ; /* Wait for a character. */
  1976.     return( (n > 0) ? (ch & 0377) : n );
  1977. #endif
  1978.     }
  1979.  
  1980. #ifdef datageneral
  1981.     /* Peform timeout setting only once per device */
  1982.     if (timotty != timo) { 
  1983.          resto(channel(ttyfd));         /* Save previous settings */
  1984.          setto(channel(ttyfd),timo);    /* Set the new timeout value */
  1985.     }
  1986.     {
  1987. #else
  1988.     signal(SIGALRM,timerh);        /* Timed, set up timer. */
  1989.     alarm(timo);
  1990.     if (setjmp(sjbuf))
  1991.     n = -1;
  1992.     else {
  1993. #endif
  1994. #ifdef MYREAD
  1995.         while ((n = myread()) == -1) ;    /* If managing own buffer... */
  1996.     if (n == -2) {
  1997.         n++;
  1998.     } else {
  1999.         ch = n;
  2000.         n = 1;    
  2001.     }
  2002. #else
  2003.         n = read(ttyfd,&ch,1);        /* Otherwise call the system. */
  2004. #endif
  2005.     }
  2006. #ifndef datageneral
  2007.     alarm(0);                /* Turn off timer, */
  2008.     signal(SIGALRM,SIG_DFL);        /* and interrupt. */
  2009. #endif
  2010.     return( (n > 0) ? (ch & 0377) : n ); /* Return char or -1. */
  2011. }
  2012.  
  2013. /*  T T S N D B  --  Send a BREAK signal  */
  2014.  
  2015. ttsndb() {
  2016.     int x; long n; char spd;
  2017.  
  2018.     if (ttyfd < 0) return(-1);        /* Not open. */
  2019.  
  2020. #ifdef PROVX1
  2021.     gtty(ttyfd,&ttbuf);            /* Get current tty flags */
  2022.     spd = ttbuf.sg_ospeed;        /* Save speed */
  2023.     ttbuf.sg_ospeed = B50;        /* Change to 50 baud */
  2024.     stty(ttyfd,&ttbuf);            /*  ... */
  2025.     write(ttyfd,brnuls,3);        /* Send 3 nulls */
  2026.     ttbuf.sg_ospeed = spd;        /* Restore speed */
  2027.     stty(ttyfd,&ttbuf);            /*  ... */
  2028.     return(0);
  2029. #else
  2030. #ifdef UXIII
  2031. #ifdef datageneral
  2032.     if (sys_clrdv(channel(ttyfdout),1<<31,$CDSBRK)) {   /* Send a BREAK */
  2033. #else
  2034.     if (ioctl(ttyfd,TCSBRK,(char *)0) < 0) {            /* Send a BREAK */
  2035. #endif
  2036.         perror("Can't send BREAK");
  2037.     return(-1);
  2038.     }
  2039.     return(0);
  2040. #else
  2041. #ifdef ANYBSD
  2042.     n = FWRITE;                /* Flush output queue. */
  2043.     ioctl(ttyfd,TIOCFLUSH,&n);         /* Ignore any errors.. */
  2044.     if (ioctl(ttyfd,TIOCSBRK,(char *)0) < 0) {    /* Turn on BREAK */
  2045.         perror("Can't send BREAK");
  2046.     return(-1);
  2047.     }
  2048.     x = msleep(275);            /* Sleep for so many milliseconds */
  2049.     if (ioctl(ttyfd,TIOCCBRK,(char *)0) < 0) {    /* Turn off BREAK */
  2050.     perror("BREAK stuck!!!");
  2051.     doexit(1);            /* Get out, closing the line. */
  2052.                     /*   with exit status = 1 */
  2053.     }
  2054.     return(x);
  2055. #else
  2056. #ifdef    V7
  2057.     genbrk(ttyfd);            /* Simulate a BREAK */
  2058.     return(x);
  2059. #endif
  2060. #endif
  2061. #endif
  2062. #endif
  2063. }
  2064.  
  2065. /*  M S L E E P  --  Millisecond version of sleep().  */
  2066.  
  2067. /*
  2068.  Intended only for small intervals.  For big ones, just use sleep().
  2069. */
  2070.  
  2071. msleep(m) int m; {
  2072.  
  2073. #ifdef PROVX1
  2074.     if (m <= 0) return(0);
  2075.     sleep(-((m * 60 + 500) / 1000));
  2076.  
  2077.     return(0);
  2078. #endif
  2079.  
  2080. #ifdef ANYBSD
  2081.     int t1, t3, t4;
  2082.     if (m <= 0) return(0);
  2083. #ifndef BSD42
  2084. /* 2.9 and 4.1 BSD do it this way */
  2085.     if (ftime(&ftp) < 0) return(-1);    /* Get current time. */
  2086.     t1 = ((ftp.time & 0xff) * 1000) + ftp.millitm;
  2087.     while (1) {
  2088.     ftime(&ftp);            /* new time */
  2089.     t3 = (((ftp.time & 0xff) * 1000) + ftp.millitm) - t1;
  2090.     if (t3 > m) return (t3);
  2091.     }
  2092. #else
  2093. /* 4.2 & above can do it with select()... */
  2094.     if (gettimeofday(&tv, &tz) < 0) return(-1); /* Get current time. */
  2095.     t1 = tv.tv_sec;            /* Seconds */
  2096.  
  2097.     tv.tv_sec = 0;            /* Use select() */
  2098.     tv.tv_usec = m * 1000;
  2099.     return(select( 0, (int *)0, (int *)0, (int *)0, &tv) );
  2100. #endif
  2101. #endif
  2102.  
  2103. #ifdef UXIII
  2104. #ifdef XENIX
  2105. #define CLOCK_TICK 50            /* millisecs per clock tick */
  2106. #else
  2107. #define CLOCK_TICK 17            /* 1/60 sec */
  2108. #endif
  2109.     extern long times();
  2110.     long t1, t2, tarray[4];
  2111.     int t3;
  2112.  
  2113.     if (m <= 0) return(0);
  2114.     if ((t1 = times(tarray)) < 0) return(-1);
  2115.     while (1) {
  2116.     if ((t2 = times(tarray)) < 0) return(-1);
  2117.     t3 = ((int)(t2 - t1)) * CLOCK_TICK;
  2118.     if (t3 > m) return(t3);
  2119.     }
  2120. #endif
  2121.  
  2122.  
  2123. #ifdef TOWER1
  2124.     int t1, t3;
  2125.     if (m <= 0) return(0);
  2126.     if (ftime(&ftp) < 0) return(-1);        /* Get current time. */
  2127.     t1 = ((ftp.time & 0xff) * 1000) + ftp.millitm;
  2128.     while (1) {
  2129.     ftime(&ftp);                /* new time */
  2130.     t3 = (((ftp.time & 0xff) * 1000) + ftp.millitm) - t1;
  2131.     if (t3 > m) return (t3);
  2132.     }
  2133. #endif
  2134. }
  2135.  
  2136. /*  R T I M E R --  Reset elapsed time counter  */
  2137.  
  2138. rtimer() {
  2139.     tcount = time( (long *) 0 );
  2140. }
  2141.  
  2142.  
  2143. /*  G T I M E R --  Get current value of elapsed time counter in seconds  */
  2144.  
  2145. gtimer() {
  2146.     int x;
  2147.     x = (int) (time( (long *) 0 ) - tcount);
  2148.     rtimer();
  2149.     return( (x < 0) ? 0 : x );
  2150. }
  2151.  
  2152.  
  2153. /*  Z T I M E  --  Return date/time string  */
  2154.  
  2155. ztime(s) char **s; {
  2156.  
  2157. #ifdef UXIII
  2158.     extern long time();            /* Sys III/V way to do it */
  2159.     char *ctime();
  2160.     long clock_storage;
  2161.  
  2162.     clock_storage = time( (long *) 0 );
  2163.     *s = ctime( &clock_storage );
  2164. #endif
  2165.  
  2166. #ifdef PROVX1
  2167.     int utime[2];            /* Venix way */
  2168.     time(utime);
  2169.     *s = ctime(utime);
  2170. #endif
  2171.  
  2172. #ifdef ANYBSD
  2173.     char *asctime();            /* Berkeley way */
  2174.     struct tm *localtime();
  2175.     struct tm *tp;
  2176. #ifdef BSD42
  2177.     gettimeofday(&tv, &tz);        /* BSD 4.2 */
  2178.     time(&tv.tv_sec);
  2179.     tp = localtime(&tv.tv_sec);
  2180. #else
  2181.     time(&clock);            /* BSD 4.1, 2.9 ... ceb */
  2182.     tp = localtime(&clock);
  2183. #endif
  2184.     *s = asctime(tp);
  2185. #endif
  2186.  
  2187. #ifdef TOWER1
  2188.     char *asctime();            /* Tower way */
  2189.     struct tm *localtime();
  2190.     struct tm *tp;
  2191.  
  2192.     time(&clock);
  2193.     tp = localtime(&clock);
  2194.     *s = asctime(tp);
  2195. #endif
  2196. #ifdef V7
  2197.     char *asctime();            /* V7 way */
  2198.     struct tm *localtime();
  2199.     struct tm *tp;
  2200.  
  2201.     time(&clock);
  2202.     tp = localtime(&clock);
  2203.     *s = asctime(tp);
  2204. #endif
  2205. }
  2206.  
  2207. /*  C O N G M  --  Get console terminal modes.  */
  2208.  
  2209. /*
  2210.  Saves current console mode, and establishes variables for switching between 
  2211.  current (presumably normal) mode and other modes.
  2212. */
  2213.  
  2214. congm() {
  2215.     if (!isatty(0)) return(0);        /* only for real ttys */
  2216. #ifndef UXIII
  2217.      gtty(0,&ccold);            /* Structure for restoring */
  2218.      gtty(0,&cccbrk);            /* For setting CBREAK mode */
  2219.      gtty(0,&ccraw);            /* For setting RAW mode */
  2220. #else
  2221.      ioctl(0,TCGETA,&ccold);
  2222.      ioctl(0,TCGETA,&cccbrk);
  2223.      ioctl(0,TCGETA,&ccraw);
  2224. #ifdef datageneral
  2225.      /* For DG, also get the tty extended device characteristics. */
  2226.      sys_gechr( channel(0), (1<<31)|$CLMAX, ch_ccold);
  2227.      sys_gechr( channel(0), (1<<31)|$CLMAX, ch_ccraw);
  2228.      sys_gechr( channel(0), (1<<31)|$CLMAX, ch_ccbrk);
  2229. #endif
  2230. #endif
  2231.      cgmf = 1;                /* Flag that we got them. */
  2232. }
  2233.  
  2234.  
  2235.  
  2236. /*  C O N C B --  Put console in cbreak mode.  */
  2237.  
  2238. /*  Returns 0 if ok, -1 if not  */
  2239.  
  2240. concb(esc) char esc; {
  2241.     int x;
  2242.     if (!isatty(0)) return(0);        /* only for real ttys */
  2243.     if (cgmf == 0) congm();        /* Get modes if necessary. */
  2244.     escchr = esc;            /* Make this available to other fns */
  2245.     ckxech = 1;                /* Program can echo characters */
  2246. #ifndef UXIII
  2247.     cccbrk.sg_flags |= CBREAK;        /* Set to character wakeup, */
  2248.     cccbrk.sg_flags &= ~ECHO;        /* no echo. */
  2249.     x = stty(0,&cccbrk);
  2250. #else
  2251. #ifdef datageneral
  2252.     cccbrk.c_lflag |= CBREAK;
  2253. #endif
  2254.     cccbrk.c_lflag &= ~(ICANON|ECHO);
  2255.     cccbrk.c_cc[0] = 003;        /* interrupt char is control-c */
  2256.     cccbrk.c_cc[1] = escchr;        /* escape during packet modes */
  2257.     cccbrk.c_cc[4] = 1;
  2258.     cccbrk.c_cc[5] = 1;
  2259.     x = ioctl(0,TCSETAW,&cccbrk);      /* set new modes . */
  2260. #ifdef datageneral
  2261.     if (sys_gechr( channel(0), (1<<31)|$CLMAX, ch_ccbrk)) 
  2262.          { perror("concb: gechr: "); return(-1); }
  2263. #endif
  2264. #endif
  2265.     if (x > -1) setbuf(stdout,NULL);    /* Make console unbuffered. */
  2266. #ifdef    V7
  2267.     if (kmem[CON] < 0) {
  2268.     qaddr[CON] = initrawq(0);
  2269.     if((kmem[CON] = open("/dev/kmem", 0)) < 0) {
  2270.         fprintf(stderr, "Can't read /dev/kmem in concb.\n");
  2271.         perror("/dev/kmem");
  2272.         exit(1);
  2273.     }
  2274.     }
  2275. #endif    V7
  2276.     return(x);
  2277. }
  2278.  
  2279. /*  C O N B I N  --  Put console in binary mode  */
  2280.  
  2281. /*  Returns 0 if ok, -1 if not  */
  2282.  
  2283. conbin(esc) char esc; {
  2284. int filedes,filedes2;
  2285.  
  2286.     if (!isatty(0)) return(0);        /* only for real ttys */
  2287.     if (cgmf == 0) congm();        /* Get modes if necessary. */
  2288.     escchr = esc;            /* Make this available to other fns */
  2289.     ckxech = 1;                /* Program can echo characters */
  2290. #ifndef UXIII
  2291.     ccraw.sg_flags |= (RAW|TANDEM);       /* Set rawmode, XON/XOFF */
  2292.     ccraw.sg_flags &= ~(ECHO|CRMOD);      /* Set char wakeup, no echo */
  2293.     return(stty(0,&ccraw));
  2294. #else
  2295.     ccraw.c_lflag &= ~(ISIG|ICANON|ECHO);
  2296.     ccraw.c_iflag |= (BRKINT|IGNPAR);
  2297.     ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|IXON|IXANY|IXOFF
  2298.             |INPCK|ISTRIP);
  2299.     ccraw.c_oflag &= ~OPOST;
  2300.  
  2301. /*** Kermit used to put the console in 8-bit raw mode, but some users have
  2302.  *** pointed out that this should not be done, since some sites actually
  2303.  *** use terminals with parity settings on their Unix systems, and if we
  2304.  *** override the current settings and stop doing parity, then their terminals
  2305.  *** will display blotches for characters whose parity is wrong.  Therefore,
  2306.  *** the following two lines are commented out (Larry Afrin, Clemson U):
  2307.  ***
  2308.  ***   ccraw.c_cflag &= ~(PARENB|CSIZE);
  2309.  ***   ccraw.c_cflag |= (CS8|CREAD);
  2310.  ***
  2311.  *** Sys III/V sites that have trouble with this can restore these lines.
  2312.  ***/
  2313.     ccraw.c_cc[4] = 1;
  2314.     ccraw.c_cc[5] = 1;
  2315. #ifdef datageneral
  2316.     if (ioctl(0,TCSETAW,&ccraw)) return(-1);      /* set new modes . */
  2317.     if (sys_gechr( channel(0), (1<<31)|$CLMAX, ch_ccraw))
  2318.          { perror("conbin: gechr: "); return(-1); }
  2319.     return(0);
  2320. #else
  2321.     return(ioctl(0,TCSETAW,&ccraw) );      /* set new modes . */
  2322. #endif
  2323. #endif
  2324. }
  2325.  
  2326.  
  2327. /*  C O N R E S  --  Restore the console terminal  */
  2328.  
  2329. conres() {
  2330.     if (cgmf == 0) return(0);        /* Don't do anything if modes */
  2331.     if (!isatty(0)) return(0);        /* only for real ttys */
  2332. #ifdef datageneral
  2333.     if (timocon) 
  2334.          /* Timeouts are set, so un-set them. */
  2335.          resto(channel(0));
  2336. #endif
  2337. #ifndef UXIII                /* except for sIII, */
  2338.     sleep(1);                /*  not known! */
  2339. #endif                    /*   (sIII does wait in ioctls) */
  2340.     ckxech = 0;                /* System should echo chars */
  2341. #ifndef UXIII
  2342.     return(stty(0,&ccold));        /* Restore controlling tty */
  2343. #else
  2344. #ifdef datageneral
  2345.     if (ioctl(0,TCSETAW,&ccold)) return(-1);      /* set new modes . */
  2346.     if (sys_sechr( channel(0), (1<<31)|$CLMAX, ch_ccold))
  2347.          { perror("conres: sechr "); return(-1); }
  2348.     return(0);
  2349. #else
  2350.     return(ioctl(0,TCSETAW,&ccold));
  2351. #endif
  2352. #endif
  2353. }
  2354.  
  2355. /*  C O N O C  --  Output a character to the console terminal  */
  2356.  
  2357. conoc(c) char c; {
  2358.     write(1,&c,1);
  2359. }
  2360.  
  2361. /*  C O N X O  --  Write x characters to the console terminal  */
  2362.  
  2363. conxo(x,s) char *s; int x; {
  2364.     write(1,s,x);
  2365. }
  2366.  
  2367. /*  C O N O L  --  Write a line to the console terminal  */
  2368.  
  2369. conol(s) char *s; {
  2370.     int len;
  2371.     len = strlen(s);
  2372.     write(1,s,len);
  2373. }
  2374.  
  2375. /*  C O N O L A  --  Write an array of lines to the console terminal */
  2376.  
  2377. conola(s) char *s[]; {
  2378.     int i;
  2379.     for (i=0 ; *s[i] ; i++) conol(s[i]);
  2380. }
  2381.  
  2382. /*  C O N O L L  --  Output a string followed by CRLF  */
  2383.  
  2384. conoll(s) char *s; {
  2385.     conol(s);
  2386.     write(1,"\r\n",2);
  2387. }
  2388.  
  2389.  
  2390. /*  C O N C H K  --  Return how many characters available at console  */
  2391.  
  2392. conchk() {
  2393.     int x; long n;
  2394.  
  2395. #ifdef PROVX1 
  2396.     x = ioctl(0, TIOCQCNT, &ttbuf);
  2397.     n = ttbuf.sg_ispeed & 0377;
  2398.     return((x < 0) ? 0 : n);
  2399. #else
  2400. #ifdef V7
  2401.     lseek(kmem[CON], (long) qaddr[CON], 0);
  2402.     x = read(kmem[CON], &n, sizeof(int));
  2403.     return((x == sizeof(int))? n: 0);
  2404. #else
  2405. #ifdef UXIII
  2406.     if (conesc) {            /* Escape typed */
  2407.     conesc = 0;
  2408.     signal(SIGQUIT,esctrp);        /* Restore escape */
  2409.     return(1);
  2410.     }
  2411.     return(0);
  2412. #else
  2413. #ifdef C70
  2414.     if (conesc) {            /* Escape typed */
  2415.     conesc = 0;
  2416.     signal(SIGQUIT,esctrp);        /* Restore escape */
  2417.     return(1);
  2418.     }
  2419.     return(0);
  2420. #else
  2421. #ifdef FIONREAD
  2422.     x = ioctl(0, FIONREAD, &n);        /* BSD and maybe some others */
  2423.     return((x < 0) ? 0 : n);
  2424. #else
  2425.     return(0);                /* Others can't do. */
  2426. #endif
  2427. #endif
  2428. #endif
  2429. #endif
  2430. #endif
  2431. }
  2432.  
  2433. #ifdef datageneral
  2434.  
  2435. /* D G N C O U B -- Output len characters to the file number filenum */
  2436.  
  2437. dgncoub(filenum,chs,len) int filenum, len; char *chs; 
  2438. {
  2439.      int ac2,err;
  2440.  
  2441.      if (len == 0) return(0);
  2442.  
  2443.      if (filenum == ttyfdout) {
  2444.           xout_parms.ibad = chs;
  2445.           xout_parms.ircl = len;
  2446.           ac2 = &xout_parms;
  2447.      } else {
  2448.       w_io_parms.ich = channel(filenum);
  2449.           w_io_parms.ibad = chs;
  2450.           w_io_parms.ircl = len;
  2451.           ac2 = &w_io_parms;
  2452.      }
  2453.      
  2454.      if ((err = sys_write(ac2)) == 0) return(0);
  2455.      if ( err != ERLTL && err != EREOF ) {
  2456.           perror("dgncoub: sys_write ");
  2457.           return(err);
  2458.      }
  2459. }
  2460.  
  2461.  
  2462. /* D G N C I N B -- System level read of len characters from file number 
  2463.    fileno.  The global DG i/o structures are used for this.
  2464.  
  2465.    Return codes:  irlr if data read ok, where irlr=length of data
  2466.                   -1 if EOF
  2467.                   -2 if timeout occured
  2468.                   -err if an AOS/VS error occured, where err is errno
  2469. */                  
  2470.  
  2471. dgncinb(filenum,chs,len) int filenum, len; char *chs; 
  2472. {
  2473.      int ac2,                       /* I/O parameter address block */
  2474.          err,                       /* Error from sys_read */
  2475.          irlr;                      /* Number of bytes read */
  2476.      int rbe;                       /* Ring buffer empty on ESGT read */
  2477.  
  2478.      if (filenum == ttyfd) {
  2479.           x_io_parms.ibad = chs;
  2480.           x_io_parms.ircl = len;
  2481.           ac2 = &x_io_parms;
  2482.           err = sys_read(ac2);
  2483.           irlr = x_io_parms.irlr;
  2484.           if (err == 0) return(irlr);
  2485.           rbe = (x_io_parms.etsp == 0) ? 0 : (x_io_scrn.esfc & $ESBE);
  2486.      } else {
  2487.           r_io_parms.ich  = channel(filenum); 
  2488.           r_io_parms.ibad = chs;
  2489.           r_io_parms.ircl = len;
  2490.           ac2 = &r_io_parms;
  2491.           err = sys_read(ac2);
  2492.           irlr = r_io_parms.irlr;
  2493.           if (err == 0) return(irlr);
  2494.           rbe = (r_io_parms.etsp == 0) ? 0 : (r_io_scrn.esfc & $ESBE);
  2495.      }
  2496.  
  2497.      if ((err != ERLTL) && (err != ERDTO) && (err != EREOF)) {
  2498.           /* NOT line-too-long, timeout, or EOF errors.
  2499.            * Don't print error when it is a data overrun.
  2500.            */
  2501.           if (err != EROVR) perror("dgncinb: sys_read ");
  2502.           return(-err);
  2503.      } else {
  2504.           /* If the system read buffer was empty when a screen management
  2505.           * packet was supplied, then there is a virtual EOF condition.  
  2506.           * So we return an EOF flag in that case (rbe != 0).
  2507.           */
  2508.           if ((err == EREOF) || rbe) return(-1);            /* EOF */
  2509.           /* We got some data, even though we may have timed out getting it. */
  2510.           if (irlr > 0) return(irlr);                       /* Got data */
  2511.           if (err == ERDTO) return(-2);                     /* Timeout */
  2512.      }
  2513. }
  2514. #endif datageneral
  2515.  
  2516. /*  C O N I N C  --  Get a character from the console  */
  2517.  
  2518. coninc(timo) int timo; {
  2519.     int n = 0; char ch;
  2520.     if (timo <= 0 ) {            /* untimed */
  2521. #ifdef datageneral
  2522.         /* Binary input */
  2523.         n = dgncinb(0,&ch,1);
  2524. #else
  2525.     n = read(0, &ch, 1);        /* Read a character. */
  2526. #endif
  2527.     ch &= 0377;
  2528.     if (n > 0) return(ch);         /* Return the char if read */
  2529.     else 
  2530. #ifdef UXIII
  2531. #ifdef datageneral
  2532.         if (n != -2 && n != 0 && errno == EINTR)
  2533.              { perror("coninc: timo=0: "); return(escchr); }
  2534. #else
  2535.         if (n < 0 && errno == EINTR) /* if read was interrupted by QUIT */
  2536.         return(escchr);         /* user entered escape character */
  2537. #endif datageneral
  2538.         else            /* couldnt be ^c, sigint never returns */
  2539. #endif UXIII
  2540.         return(-1);          /* Return the char, or -1. */
  2541.     }
  2542. #ifdef datageneral
  2543.     /* Peform timeout setting only once per device */
  2544.     if (timocon != timo) { 
  2545.          resto(channel(0));             /* Save the previous values */
  2546.          setto(channel(0),timo);        /* Set the new timeout value */
  2547.     }
  2548.     n = dgncinb(0,&ch,1);
  2549.     ch &= 0377;
  2550. #else
  2551.     signal(SIGALRM,timerh);        /* Timed read, so set up timer */
  2552.     alarm(timo);
  2553.     if (setjmp(sjbuf)) n = -2;
  2554.     else {
  2555.     n = read(0, &ch, 1);
  2556.     ch &= 0377;
  2557.     }
  2558.     alarm(0);                /* Stop timing, we got our character */
  2559.     signal(SIGALRM,SIG_DFL);
  2560. #endif
  2561.     if (n > 0) return(ch);  
  2562.     else
  2563. #ifdef UXIII
  2564. #ifdef datageneral
  2565.     if (n != -2 && n != 0 && errno == EINTR)
  2566.          { perror("coninc: timo>0: "); return(escchr); }
  2567. #else
  2568.         if (n == -1 && errno == EINTR)  /* If read interrupted by QUIT, */
  2569.         return(escchr);        /* user entered escape character, */
  2570. #endif datageneral
  2571.         else                    /* can't be ^c, sigint never returns */
  2572. #endif UXIII
  2573.     return(-1);
  2574. }
  2575.