home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / ckc095.zip / ckutio.c < prev    next >
C/C++ Source or Header  |  1989-08-31  |  85KB  |  2,590 lines

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