home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / old / ckermit60 / ckutio.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  270KB  |  9,116 lines

  1. #ifdef aegis
  2. char *ckxv = "Aegis Communications support, 6.0.169, 6 Sep 96";
  3. #else
  4. #ifdef Plan9
  5. char *ckxv = "Plan 9 Communications support, 6.0.169, 6 Sep 96";
  6. #else
  7. char *ckxv = "UNIX Communications support, 6.0.169, 6 Sep 96";
  8. #endif /* Plan9 */
  9. #endif /* aegis */
  10.  
  11. /*  C K U T I O  */
  12.  
  13. /* C-Kermit interrupt, communications control and I/O functions for UNIX */
  14.  
  15. /*
  16.   NOTE TO CONTRIBUTORS: This file, and all the other C-Kermit files, must be
  17.   compatible with C preprocessors that support only #ifdef, #else, #endif,
  18.   #define, and #undef.  Please do not use #if, logical operators, or other
  19.   preprocessor features in any of the portable C-Kermit modules.  You can,
  20.   of course, use these constructions in system-specific modules when they
  21.   are supported.
  22. */
  23.  
  24. /*
  25.   Author: Frank da Cruz (fdc@columbia.edu),
  26.   Columbia University Academic Information Systems, New York City.
  27.  
  28.   Copyright (C) 1985, 1996, Trustees of Columbia University in the City of New
  29.   York.  All rights reserved.
  30. */
  31.  
  32. /* Includes */
  33.  
  34. #include "ckcsym.h"            /* This must go first   */
  35. #include "ckcdeb.h"            /* This must go second  */
  36. #include <errno.h>            /* System error numbers */
  37.  
  38. #ifdef __386BSD__
  39. #define ENOTCONN 57
  40. #else
  41. #ifdef __bsdi__
  42. #define ENOTCONN 57
  43. #else
  44. #ifdef __FreeBSD__
  45. #define ENOTCONN 57
  46. #endif /* __FreeBSD__ */
  47. #endif /* __bsdi__ */
  48. #endif /* __386BSD__ */
  49.  
  50. #ifdef Plan9
  51. #define SELECT
  52. #include <sys/time.h>
  53. #include <select.h>
  54. #define FD_SETSIZE (3 * sizeof(long) * 8)
  55. static struct timeval tv;
  56. #endif /* Plan9 */
  57.  
  58. #include "ckcnet.h"            /* Symbols for network types. */
  59.  
  60. #ifdef XENIX /* Was M_UNIX but XENIX implies M_UNIX and applies to XENIX too */
  61. /*
  62.   <sys/socket.h> included above via "ckcnet.h" defines FIONREAD as
  63.   something.  Due to this, in_chk() uses the FIONREAD instead of RDCHK
  64.   and the hot keys during file transfer (X to cancel file etc) do not
  65.   work because FIONREAD doesn't work even though it is defined.
  66.  
  67.   NOTE: This might also be true elsewhere.
  68. */
  69. #ifdef FIONREAD
  70. #undef FIONREAD
  71. #endif /* FIONREAD */
  72. #endif /* XENIX */
  73.  
  74. #ifdef CK_SCOV5                /* Ditto for SCO OpenServer 5.0 */
  75. #ifdef FIONREAD
  76. #undef FIONREAD
  77. #endif /* FIONREAD */
  78. #endif /* XENIX */
  79.  
  80. /*
  81.   The directory-related includes are here because we need to test some
  82.   file-system-related symbols to find out which system we're being compiled
  83.   under.  For example, MAXNAMLEN is defined in BSD4.2 but not 4.1.
  84. */
  85. #ifdef SDIRENT                /* Directory bits... */
  86. #define DIRENT
  87. #endif /* SDIRENT */
  88.  
  89. #ifdef XNDIR
  90. #include <sys/ndir.h>
  91. #else /* !XNDIR */
  92. #ifdef NDIR
  93. #include <ndir.h>
  94. #else /* !NDIR, !XNDIR */
  95. #ifdef RTU
  96. #include "/usr/lib/ndir.h"
  97. #else /* !RTU, !NDIR, !XNDIR */
  98. #ifdef DIRENT
  99. #ifdef SDIRENT
  100. #include <sys/dirent.h>
  101. #else
  102. #include <dirent.h>
  103. #endif /* SDIRENT */
  104. #else /* !RTU, !NDIR, !XNDIR, !DIRENT, i.e. all others */
  105. #include <sys/dir.h>
  106. #endif /* DIRENT */
  107. #endif /* RTU */
  108. #endif /* NDIR */
  109. #endif /* XNDIR */
  110.  
  111. /* Definition of HZ, used in msleep() */
  112.  
  113. #ifdef MIPS
  114. #define HZ ( 1000 / CLOCK_TICK )
  115. #else
  116. #ifdef ATTSV
  117. #ifndef NAP
  118. #ifndef TRS16
  119. #include <sys/param.h>
  120. #else
  121. #define HZ ( 1000 / CLOCK_TICK )
  122. #endif /* TRS16 */
  123. #ifdef NAPHACK
  124. #define nap(x) (void)syscall(3112, (x))
  125. #define NAP
  126. #endif /* NAPHACK */
  127. #endif /* NAP */
  128. #endif /* ATTSV */
  129. #endif /* MIPS */
  130.  
  131. #ifdef M_UNIX
  132. #undef NGROUPS_MAX        /* Prevent multiple definition warnings */
  133. #endif /* M_UNIX */
  134.  
  135. /*
  136.   NOTE: HP-UX 8.0 has a <sys/poll.h>, but there is no corresponding
  137.   library routine, so _poll comes up undefined at link time.
  138. */
  139. #ifdef CK_POLL
  140. #ifndef AIXRS            /* IBM AIX needs special handling */
  141. #include <poll.h>        /* "standard" (SVID) i/o multiplexing, etc */
  142. #else /* AIXRS */
  143. #ifdef SVR4            /* AIX 3.2 is like SVID... */
  144. #include <poll.h>
  145. #else                /* But AIX 3.1 is not ... */
  146. #include <sys/poll.h>        /* The include file is in include/sys */
  147. #define events reqevents    /* And it does not map IBM-specific member */
  148. #define revents rtnevents    /* names to the System V equivalents */
  149. #endif /* SVR4 */
  150. #endif /* AIXRS */
  151. #endif /* CK_POLL */
  152.  
  153. #include <signal.h>                     /* Signals */
  154.  
  155. /* For setjmp and longjmp */
  156.  
  157. #ifndef ZILOG
  158. #include <setjmp.h>
  159. #else
  160. #include <setret.h>
  161. #endif /* ZILOG */
  162.  
  163. /* Maximum length for the name of a tty device */
  164.  
  165. #ifndef DEVNAMLEN
  166. #define DEVNAMLEN 32
  167. #endif /* DEVNAMLEN */
  168.  
  169. #ifdef    NETCONN
  170. #undef DEVNAMLEN
  171. #define DEVNAMLEN 256            /* Longer field for host:service */
  172. #endif  /* NETCONN */
  173.  
  174. /*
  175.   The following test differentiates between 4.1 BSD and 4.2 & later.
  176.   If you have a 4.1BSD system with the DIRENT library, this test could
  177.   mistakenly diagnose 4.2BSD and then later enable the use of system calls
  178.   that aren't defined.  If indeed there are such systems, we can use some
  179.   other way of testing for 4.1BSD, or add yet another compile-time switch.
  180. */  
  181. #ifdef BSD4
  182. #ifdef MAXNAMLEN
  183. #ifndef FT21                /* Except for Fortune. */
  184. #ifndef FT18
  185. #ifndef BELLV10                /* And Bell Labs Research UNIX V10 */
  186. #define BSD42
  187. #endif /* BELLV10 */
  188. #endif /* FT18 */
  189. #endif /* FT21 */
  190. #endif /* MAXNAMLEN */
  191. #endif /* BSD4 */
  192. /*
  193.  MINIX 1.0 support added by Charles Hedrick,
  194.  Rutgers University <hedrick@aramis.rutgers.edu>.
  195.  MINIX also has V7 enabled.
  196. */
  197. #ifdef MINIX
  198. #define TANDEM 0
  199. #define MYREAD
  200. #include <limits.h>
  201. #endif /* MINIX */
  202.  
  203. #ifdef CK_REDIR        /* <sys/wait.h> needed only for REDIRECT command. */
  204. /*
  205.   If anybody can figure out how to make this work with NeXTSTEP, be
  206.   my guest!  (NeXTBlah/NeXTBlah/bsd/sys/wait.h does not define WEXITSTATUS)
  207. */
  208. #ifndef CK_WAIT_H            /* If wait.h not already included... */
  209. #include <sys/wait.h>            /* Include it */
  210. #endif /* CK_WAIT_H */
  211. #endif /* CK_REDIR */
  212.  
  213. #include "ckuver.h"            /* Version herald */
  214. char *ckxsys = HERALD;
  215.  
  216. /* UUCP lockfile name definition */
  217.  
  218. #ifndef NOUUCP
  219.  
  220. /* Name of UUCP tty device lockfile */
  221.  
  222. #ifdef LINUXFSSTND
  223. #ifndef HDBUUCP
  224. #define HDBUUCP
  225. #endif /* HDBUUCP */
  226. #endif /* LINUXFSSTND */
  227.  
  228. #ifdef ACUCNTRL
  229. #define LCKDIR
  230. #endif /* ACUCNTRL */
  231.  
  232. /*
  233.   PIDSTRING means use ASCII string to represent pid in lockfile.
  234. */
  235. #ifndef PIDSTRING
  236. #ifdef HDBUUCP
  237. #define PIDSTRING
  238. #else
  239. #ifdef BSD44
  240. #define PIDSTRING
  241. #else
  242. #ifdef RTAIX
  243. #define PIDSTRING
  244. #else
  245. #ifdef AIXRS
  246. #define PIDSTRING
  247. #else
  248. #ifdef COHERENT
  249. #define PIDSTRING
  250. #endif /* COHERENT */
  251. #endif /* AIXRS */
  252. #endif /* RTAIX */
  253. #endif /* BSD44 */
  254. #endif /* HDBUUCP */
  255. #endif /* PIDSTRING */
  256.  
  257. /* Now the PIDSTRING exceptions... */
  258.  
  259. #ifdef HPUX10                /* HP-UX 10.00 */
  260. #ifdef PIDSTRING
  261. #undef PIDSTRING
  262. #endif /* PIDSTRING */
  263. #endif /* HPUX10 */
  264.  
  265. #ifdef __bsdi__                /* BSDI (at least thru 1.1) */
  266. #ifdef PIDSTRING
  267. #undef PIDSTRING
  268. #endif /* PIDSTRING */
  269. #endif /* __bsdi__ */
  270.  
  271. #ifdef OSF32                /* Digital UNIX (OSF/1) 3.2 */
  272. #ifdef PIDSTRING
  273. #undef PIDSTRING
  274. #endif /* PIDSTRING */
  275. #endif /* OSF32 */
  276.  
  277. /*
  278.   LOCK_DIR is the name of the lockfile directory.
  279.   If LOCK_DIR is already defined (e.g. on command line), we don't change it.
  280. */
  281. #ifndef LOCK_DIR
  282. #ifdef BSD44
  283. #ifdef __386BSD__
  284. #define LOCK_DIR "/var/spool/lock";
  285. #else
  286. #ifdef __FreeBSD__
  287. #define LOCK_DIR "/var/spool/lock";
  288. #else
  289. #ifdef __NetBSD__
  290. #define LOCK_DIR "/var/spool/lock";
  291. #else
  292. #define LOCK_DIR "/var/spool/uucp";
  293. #endif /* __NetBSD__ */
  294. #endif /* __FreeBSD__ */
  295. #endif /* __386BSD__ */
  296. #else
  297. #ifdef DGUX430
  298. #define LOCK_DIR "/var/spool/locks";
  299. #else
  300. #ifdef HPUX10
  301. #define LOCK_DIR "/var/spool/locks";
  302. #else
  303. #ifdef RTAIX                /* IBM RT PC AIX 2.2.1 */
  304. #define LOCK_DIR "/etc/locks";
  305. #else
  306. #ifdef AIXRS
  307. #define LOCK_DIR "/etc/locks";
  308. #else
  309. #ifdef ISIII
  310. #define LOCK_DIR "/etc/locks";
  311. #else
  312. #ifdef HDBUUCP
  313. #ifdef M_SYS5
  314. #define LOCK_DIR "/usr/spool/uucp";
  315. #else
  316. #ifdef M_UNIX
  317. #define LOCK_DIR "/usr/spool/uucp";
  318. #else
  319. #ifdef SVR4
  320. #define LOCK_DIR "/var/spool/locks";
  321. #else
  322. #ifdef SUNOS4
  323. #define LOCK_DIR "/var/spool/locks";
  324. #else
  325. #ifdef LINUXFSSTND
  326. #define LOCK_DIR "/var/lock";
  327. #else
  328. #define LOCK_DIR "/usr/spool/locks";
  329. #endif /* LINUXFSSTND */
  330. #endif /* SUNOS4 */
  331. #endif /* SVR4 */
  332. #endif /* M_UNIX */
  333. #endif /* M_SYS5 */
  334. #else
  335. #ifdef LCKDIR
  336. #define LOCK_DIR "/usr/spool/uucp/LCK";
  337. #else
  338. #ifdef COHERENT
  339. #define LOCK_DIR "/usr/spool/uucp";
  340. #else
  341. #define LOCK_DIR "/usr/spool/uucp";
  342. #endif /* COHERENT */
  343. #endif /* LCKDIR */
  344. #endif /* HDBUUCP */
  345. #endif /* ISIII */
  346. #endif /* AIXRS */
  347. #endif /* RTAIX */
  348. #endif /* HPUX10 */
  349. #endif /* DGUX430 */
  350. #endif /* BSD44 */
  351. #endif /* !LOCK_DIR (outside ifndef) */
  352.    
  353. #ifdef OSF2                /* OSF/1 2.0 or later */
  354. #ifdef LOCK_DIR                /* (maybe 1.x too, who knows...) */
  355. #undef LOCK_DIR
  356. #define LOCK_DIR "/var/spool/locks";
  357. #endif /* LOCK_DIR */
  358. #endif /* OSF2 */
  359.  
  360. #ifdef SVR4
  361. #ifndef BSD44
  362. #ifndef LOCKF
  363. #define LOCKF                /* Use lockf() on tty device in SVR4 */
  364. #endif /* LOCKF */
  365. #endif /* BSD44 */
  366. #endif /* SVR4 */
  367.  
  368. #ifdef NOLOCKF                /* But NOLOCKF cancels LOCKF */
  369. #ifdef LOCKF
  370. #undef LOCKF
  371. #endif /* LOCKF */
  372. #endif /* NOLOCKF */
  373.  
  374. #endif /* !NOUUCP */
  375.  
  376. /*
  377.   MYREAD means use our internally defined nonblocking buffered read routine.
  378. */
  379. #ifdef ATTSV
  380. #define MYREAD
  381. #endif /* ATTSV */
  382.  
  383. #ifdef ATT7300
  384. #ifndef MYREAD
  385. #define MYREAD
  386. #endif /* MYREAD */
  387. /* bits for attmodem: internal modem in use, restart getty */
  388. #define ISMODEM 1
  389. #define DOGETY 512
  390. #endif  /* ATT7300 */
  391.  
  392. #ifdef BSD42
  393. #define MYREAD
  394. #endif /* BSD42 */
  395.  
  396. #ifdef POSIX
  397. #define MYREAD
  398. #endif /* POSIX */
  399. #ifdef __bsdi__
  400. #ifndef O_NDELAY
  401. #define O_NDELAY O_NONBLOCK
  402. #endif /* O_NDELAY */
  403. #endif /* __bsdi__ */
  404.  
  405. /*
  406.  Variables available to outside world:
  407.  
  408.    dftty  -- Pointer to default tty name string, like "/dev/tty".
  409.    dfloc  -- 0 if dftty is console, 1 if external line.
  410.    dfprty -- Default parity
  411.    dfflow -- Default flow control
  412.    ckxech -- Flag for who echoes console typein:
  413.      1 - The program (system echo is turned off)
  414.      0 - The system (or front end, or terminal).
  415.    functions that want to do their own echoing should check this flag
  416.    before doing so.
  417.  
  418.    flfnam  -- Name of lock file, including its path, e.g.,
  419.                 "/usr/spool/uucp/LCK..cul0" or "/etc/locks/tty77"
  420.    lkflfn  -- Name of link to lock file, including its paths
  421.    haslock -- Flag set if this kermit established a uucp lock.
  422.    backgrd -- Flag indicating program executing in background ( & on
  423.                 end of shell command). Used to ignore INT and QUIT signals.
  424.    rtu_bug -- Set by stptrap().  RTU treats ^Z as EOF (but only when we handle
  425.                 SIGTSTP)
  426.  
  427.  Functions for assigned communication line (either external or console tty):
  428.  
  429.    sysinit()               -- System dependent program initialization
  430.    syscleanup()            -- System dependent program shutdown
  431.    ttopen(ttname,local,mdmtyp,timo) -- Open the named tty for exclusive access.
  432.    ttclos()                -- Close & reset the tty, releasing any access lock.
  433.    ttsspd(cps)             -- Set the transmission speed of the tty.
  434.    ttgspd()                -- Get (read) the the transmission speed of the tty.
  435.    ttpkt(speed,flow,parity) -- Put the tty in packet mode and set the speed.
  436.    ttvt(speed,flow)        -- Put the tty in virtual terminal mode.
  437.                                 or in DIALING or CONNECTED modem control state.
  438.    ttres()                 -- Restore original tty modes.
  439.    ttscarr(carrier)        -- Set carrier control mode, on/off/auto.
  440.    ttinl(dest,max,timo)    -- Timed read line from the tty.
  441.    ttinc(timo)             -- Timed read character from tty.
  442.    myread()                -- Raw mode bulk buffer read, gives subsequent
  443.                                 chars one at a time and simulates FIONREAD.
  444.    myunrd(c)               -- Places c back in buffer to be read (one only)
  445.    ttchk()                 -- See how many characters in tty input buffer.
  446.    ttxin(n,buf)            -- Read n characters from tty (untimed).
  447.    ttol(string,length)     -- Write a string to the tty.
  448.    ttoc(c)                 -- Write a character to the tty.
  449.    ttflui()                -- Flush tty input buffer.
  450.    ttsndb()                -- Send BREAK signal.
  451.    ttsndlb()               -- Send Long BREAK signal.
  452.  
  453.    ttlock(ttname)          -- "Lock" tty device against uucp collisions.
  454.    ttunlck()               -- Unlock tty device.
  455.  
  456.                               For ATT7300/Unix PC, System V:
  457.    attdial(ttname,speed,telnbr) -- dials ATT7300/Unix PC internal modem
  458.    offgetty(ttname)        -- Turns off getty(1m) for comms line
  459.    ongetty(ttname)         -- Restores getty() to comms line
  460. */
  461.  
  462. /*
  463. Functions for console terminal:
  464.  
  465.    congm()   -- Get console terminal modes.
  466.    concb(esc) -- Put the console in single-character wakeup mode with no echo.
  467.    conbin(esc) -- Put the console in binary (raw) mode.
  468.    conres()  -- Restore the console to mode obtained by congm().
  469.    conoc(c)  -- Unbuffered output, one character to console.
  470.    conol(s)  -- Unbuffered output, null-terminated string to the console.
  471.    conola(s) -- Unbuffered output, array of strings to the console.
  472.    conxo(n,s) -- Unbuffered output, n characters to the console.
  473.    conchk()  -- Check if characters available at console (bsd 4.2).
  474.                 Check if escape char (^\) typed at console (System III/V).
  475.    coninc(timo)  -- Timed get a character from the console.
  476.    congks(timo)  -- Timed get keyboard scan code.
  477.    conint()  -- Enable terminal interrupts on the console if not background.
  478.    connoi()  -- Disable terminal interrupts on the console if not background.
  479.  
  480. Time functions
  481.  
  482.    msleep(m) -- Millisecond sleep
  483.    ztime(&s) -- Return pointer to date/time string
  484.    rtimer() --  Reset timer
  485.    gtimer()  -- Get elapsed time since last call to rtimer()
  486. */
  487.  
  488. /* Conditional Includes */
  489.  
  490. /* Whether to include <sys/file.h> */
  491.  
  492. #ifdef RTU                /* RTU doesn't */
  493. #define NOFILEH
  494. #endif /* RTU */
  495.  
  496. #ifdef CIE                /* CIE does. */
  497. #undef NOFILEH
  498. #endif /* CIE */
  499.  
  500. #ifdef BSD41                /* 4.1 BSD doesn't */
  501. #define NOFILEH
  502. #endif /* BSD41 */
  503.  
  504. #ifdef is68k                /* is68k (whatever that is)  */
  505. #define NOFILEH
  506. #endif /* is68k */
  507.  
  508. #ifdef MINIX                /* MINIX */
  509. #define NOFILEH
  510. #endif /* MINIX */
  511.  
  512. #ifdef COHERENT                /* Coherent */
  513. #define NOFILEH
  514. #endif /* COHERENT */
  515.  
  516. #ifndef NOFILEH                /* Now include if selected. */
  517. #include <sys/file.h>
  518. #endif /* NOFILEH */
  519.  
  520. /* POSIX */
  521.  
  522. #ifdef BSD44ORPOSIX            /* POSIX uses termios.h */
  523. #define TERMIOS
  524. #ifdef __bsdi__
  525. #ifdef POSIX
  526. #undef _POSIX_SOURCE            /* Get extra stuff from termios.h */
  527. #endif /* POSIX */
  528. #endif /* __bsdi__ */
  529. #include <termios.h>
  530. #ifdef __bsdi__
  531. #ifdef POSIX
  532. #define _POSIX_SOURCE
  533. #endif /* POSIX */
  534. #endif /* __bsdi__ */
  535. #ifndef BSD44                /* Really POSIX */
  536. #ifndef CK_QNX32
  537. #define NOSYSIOCTLH            /* No ioctl's allowed. */
  538. #undef ultrix                /* Turn off any ultrix features. */
  539. #endif /* CK_QNX32 */
  540. #endif /* BSD44 */
  541. #endif /* POSIX */
  542.  
  543. /* System III, System V */
  544.  
  545. #ifdef ATTSV
  546. #ifndef BSD44
  547. #ifndef POSIX
  548. #include <termio.h>
  549. #endif /* POSIX */
  550. #endif /* BSD44 */
  551. /* #ifdef SVR4 */            /* Sys V R4 and later */
  552. #ifdef TERMIOX
  553. /* Need this for termiox structure, RTS/CTS and DTR/CD flow control */
  554. #include <termiox.h>
  555.   struct termiox rctsx;
  556. #else
  557. #ifdef STERMIOX
  558. #include <sys/termiox.h>
  559.   struct termiox rctsx;
  560. #endif /* STERMIOX */
  561. #endif /* TERMIOX */
  562. /* #endif */ /* SVR4 */
  563. #endif /* ATTSV */
  564.  
  565. #ifdef COHERENT            /* Use termio.h, not sgtty.h for Coherent */
  566. #include <termio.h>
  567. #endif /* COHERENT */
  568.  
  569. #ifdef MINIX                /* MINIX uses ioctl's */
  570. #define NOSYSIOCTLH            /* but has no <sys/ioctl.h> */
  571. #endif /* MINIX */
  572.  
  573. /* Others */
  574.  
  575. #ifndef NOSYSIOCTLH            /* Others use ioctl() */
  576. #ifdef SUN4S5
  577. /*
  578.   This is to get rid of cpp warning messages that occur because all of
  579.   these symbols are defined by both termios.h and ioctl.h on the SUN.
  580. */
  581. #undef ECHO
  582. #undef NL0
  583. #undef NL1
  584. #undef TAB0
  585. #undef TAB1
  586. #undef TAB2
  587. #undef XTABS
  588. #undef CR0
  589. #undef CR1
  590. #undef CR2
  591. #undef CR3
  592. #undef FF0
  593. #undef FF1
  594. #undef BS0
  595. #undef BS1
  596. #undef TOSTOP
  597. #undef FLUSHO
  598. #undef PENDIN
  599. #undef NOFLSH
  600. #endif /* SUN4S5 */
  601. #include <sys/ioctl.h>
  602. #endif /* NOSYSIOCTLH */
  603.  
  604. #ifdef BELLV10
  605. #include <sys/filio.h>            /* For FIONREAD */
  606. #ifdef FIONREAD
  607. #define MYREAD
  608. #endif /* MYREAD */
  609. #endif /* BELLV10 */
  610.  
  611. /* Whether to include <fcntl.h> */
  612.  
  613. #ifndef is68k                /* Only a few don't have this one. */
  614. #ifndef BSD41
  615. #ifndef FT21
  616. #ifndef FT18
  617. #ifndef COHERENT
  618. #include <fcntl.h>
  619. #endif /* COHERENT */
  620. #endif /* FT18 */
  621. #endif /* FT21 */
  622. #endif /* BSD41 */
  623. #endif /* not is68k */
  624.  
  625. #ifdef COHERENT
  626. #ifdef _I386
  627. #include <fcntl.h>
  628. #else
  629. #include <sys/fcntl.h>
  630. #endif /* _I386 */
  631. #endif /* COHERENT */
  632.  
  633. #ifdef ATT7300                /* Unix PC, internal modem dialer */
  634. #include <sys/phone.h>
  635. #endif /* ATT7300 */
  636.  
  637. #ifdef HPUX                /* HP-UX variations. */
  638. #define HPUXJOBCTL
  639. #include <sys/modem.h>            /* HP-UX modem signals */
  640. #ifdef hp9000s500            /* Model 500 */
  641. #undef HPUXJOBCTL
  642. #endif /* hp9000s500 */
  643. #ifdef HPUXPRE65
  644. #undef HPUXJOBCTL
  645. typedef long mflag;
  646. #endif /* HPUXPRE65 */
  647. #ifdef HPUXJOBCTL
  648. #include <sys/bsdtty.h>            /* HP-UX Berkeley tty support */
  649. #endif /* HPUXJOBCTL */
  650. #endif /* HPUX */
  651.  
  652. /* AT&T Sys V or POSIX */
  653.  
  654. #ifdef SVORPOSIX            /* Sys V or POSIX */
  655. #ifdef M_UNIX
  656. #include <sys/time.h>
  657. #else
  658. #ifdef OXOS                /* Olivetti X/OS */
  659. #include <sys/time.h>
  660. #else
  661. #ifdef BSD44                /* 4.4BSD */
  662. #include <sys/time.h>
  663. #else
  664. #ifdef __linux__            /* Linux */
  665. /* Kludge to fix redefinition in <linux/wait.h> */
  666. #undef WNOHANG
  667. #undef WUNTRACED
  668. #include <linux/fs.h>
  669. #include <linux/tty.h>
  670. #include <sys/time.h>
  671. #ifdef LINUXHISPEED
  672. #include <linux/serial.h>
  673. #endif /* LINUXHISPEED */
  674. #else
  675. #ifdef AIXRS                /* IBM AIX */
  676. #include <sys/time.h>
  677. #else
  678. #ifdef IRIX60
  679. #include <sys/time.h>
  680. #endif /* IRIX60 */
  681. #endif /* AIXRS */
  682. #endif /* __linux__ */
  683. #endif /* BSD44 */
  684. #endif /* OXOS */
  685. #endif /* M_UNIX */
  686.  
  687. #ifdef NOIEXTEN                /* This is broken on some systems */
  688. #undef IEXTEN                /* like Convex/OS 9.1 */
  689. #endif /* NOIEXTEN */
  690. #ifndef IEXTEN                /* Turn off ^O/^V processing. */
  691. #define IEXTEN 0            /* Needed, at least, on BSDI. */
  692. #endif /* IEXTEN */
  693.  
  694. #else /* BSD, V7, Coherent, Minix, et al. */
  695.  
  696. #include <sgtty.h>                      /* So we use <sgtty.h> */
  697. #ifndef BELLV10
  698. #ifndef PROVX1                /* Now <sys/time.h> ... */
  699. #ifndef V7
  700. #ifndef BSD41
  701. #ifndef COHERENT
  702. #include <sys/time.h>                   /* Clock info (for break generation) */
  703. #endif /* COHERENT */
  704. #endif /* BSD41 */
  705. #endif /* V7 */
  706. #endif /* PROVX1 */
  707. #endif /* BELLV10 */
  708. #endif /* SVORPOSIX */
  709.  
  710. #ifdef BELLV10
  711. #include <sys/timeb.h>
  712. #endif /* BELLV10 */
  713.  
  714. #ifdef PS2AIX10
  715. #include <sys/time.h>                   /* Clock info for PS/2 AIX 1.x */
  716. #endif /* PS2AIX10 */
  717.  
  718. #ifdef OSF                /* DEC OSF/1 1.0 */
  719. #include <sys/timeb.h>
  720. #endif /* OSF */
  721.  
  722. #ifdef BSD41                /* BSD 4.1 */
  723. #include <sys/timeb.h>
  724. #endif /* BSD41 */
  725.  
  726. #ifdef FT21                /* For:Pro 2.1 */
  727. #include <sys/timeb.h>
  728. #endif /* FT21 */
  729.  
  730. #ifdef BSD29                /* BSD 2.9 */
  731. #include <sys/timeb.h>
  732. #endif /* BSD29 */
  733.  
  734. #ifdef TOWER1
  735. #include <sys/timeb.h>                  /* Clock info for NCR Tower */
  736. #endif /* TOWER1 */
  737.  
  738. #ifdef COHERENT
  739. #include <sys/timeb.h>                  /* Clock info for NCR Tower */
  740. #endif /* COHERENT */
  741.  
  742. /*
  743.   Pick up definitions needed for select() if we don't have them already.
  744.   Normally they come from <sys/types.h> but some systems get them from
  745.   <sys/select.h>...  Rather than hardwire all of them into the source, we
  746.   include it if SELECT_H is defined in compile-time CFLAGS.
  747. */
  748. #ifdef SELECT_H
  749. #include <sys/select.h>
  750. #endif /* SELECT_H */
  751.  
  752. #ifdef aegis
  753. #include "/sys/ins/base.ins.c"
  754. #include "/sys/ins/error.ins.c"
  755. #include "/sys/ins/ios.ins.c"
  756. #include "/sys/ins/sio.ins.c"
  757. #include "/sys/ins/pad.ins.c"
  758. #include "/sys/ins/time.ins.c"
  759. #include "/sys/ins/pfm.ins.c"
  760. #include "/sys/ins/pgm.ins.c"
  761. #include "/sys/ins/ec2.ins.c"
  762. #include "/sys/ins/type_uids.ins.c"
  763. #include <default_acl.h>
  764. #undef TIOCEXCL
  765. #undef FIONREAD
  766. #endif /* aegis */
  767.  
  768. #ifdef sxaE50                /* PFU Compact A SX/A TISP V10/L50 */
  769. #undef FIONREAD
  770. #endif /* sxaE50 */
  771.  
  772. /* The following #defines are catch-alls for those systems */
  773. /* that didn't have or couldn't find <file.h>... */
  774.  
  775. #ifndef FREAD
  776. #define FREAD 0x01
  777. #endif /* FREAD */
  778.  
  779. #ifndef FWRITE
  780. #define FWRITE 0x10
  781. #endif /* FWRITE */
  782.  
  783. #ifndef O_RDONLY
  784. #define O_RDONLY 000
  785. #endif /* O_RDONLY */
  786.  
  787. /* Declarations */
  788.  
  789. #ifdef OXOS
  790. #undef TCGETA
  791. #undef TCSETA
  792. #undef TCSETAW
  793. #undef TCSETAF
  794. #define TCGETA TCGETS
  795. #define TCSETA TCSETS
  796. #define TCSETAW TCSETSW
  797. #define TCSETAF TCSETSF
  798. #define termio termios
  799. #endif /* OXOS */
  800.  
  801. #ifdef HPUX
  802. #include <time.h>
  803. #else
  804. #ifdef _POSIX_SOURCE            /* This includes MINIX */
  805. #ifndef AIXRS
  806. #include <time.h>
  807. #endif /* AIXRS */
  808. #ifdef __GNUC__
  809. #ifdef XENIX
  810. /*
  811.   Because Xenix <time.h> doesn't declare time() if we're using gcc.
  812. */
  813. time_t time();
  814. #endif /* XENIX */
  815. #endif /* __GNUC__ */
  816. #else
  817. time_t time();                /* All Unixes should have this... */
  818. #endif /* _POSIX_SOURCE */
  819. #endif /* HPUX */
  820. /* Special stuff for V7 input buffer peeking */
  821.  
  822. #ifdef  V7
  823. int kmem[2] = { -1, -1};
  824. char *initrawq(), *qaddr[2]={0,0};
  825. #define CON 0
  826. #define TTY 1
  827. #endif /* V7 */
  828.  
  829. /* dftty is the device name of the default device for file transfer */
  830. /* dfloc is 0 if dftty is the user's console terminal, 1 if an external line */
  831.  
  832. #ifndef DFTTY
  833. #ifdef PROVX1
  834.     char *dftty = "/dev/com1.dout"; /* Only example so far of a system */
  835.     char *dfmdm = "none";
  836.     int dfloc = 1;                  /* that goes in local mode by default */
  837. #else
  838.     char *dftty = CTTNAM;               /* Remote by default, use normal */
  839.     char *dfmdm = "none";
  840.     int dfloc = 0;                      /* controlling terminal name. */
  841. #endif /* PROVX1 */
  842. #else
  843.     char *dftty = DFTTY;        /* Default location specified on */
  844.     char *dfmdm = "none";        /* command line. */
  845.     int dfloc = 1;                      /* controlling terminal name. */
  846. #endif /* DFTTY */
  847.  
  848. #ifdef RTU
  849.     int rtu_bug = 0;            /* set to 1 when returning from SIGTSTP */
  850. #endif /* RTU */
  851.  
  852.     int dfprty = DEFPAR;                /* Default parity (0 = none) */
  853.     int ttprty = 0;                     /* The parity that is in use. */
  854.     int ttpflg = 0;            /* Parity not sensed yet. */
  855.     static int ttpmsk = 0xff;        /* Parity stripping mask. */
  856.     int ttmdm = 0;                      /* Modem in use. */
  857.     int ttcarr = CAR_AUT;        /* Carrier handling mode. */
  858.     int dfflow = FLO_XONX;        /* Default is Xon/Xoff */
  859.     int backgrd = 0;                    /* Assume in foreground (no '&' ) */
  860. #ifdef ultrix
  861.     int iniflags = 0;            /* fcntl flags for ttyfd */
  862. #endif /* ultrix */
  863.     int fdflag = 0;            /* Flag for redirected stdio */
  864.     int ttfdflg = 0;            /* Open File descriptor was given */
  865.     int tvtflg = 0;            /* Flag that ttvt has been called */
  866.     long ttspeed = -1L;            /* For saving speed */
  867.     int ttflow = -9;            /* For saving flow */
  868.     int ttld = -1;            /* Line discipline */
  869.  
  870. #ifdef sony_news
  871.     static int km_con = -1;        /* Kanji mode for console tty */
  872.     static int km_ext = -1;        /* Kanji mode for external device */
  873. #endif /* sony_news */
  874.  
  875. /*
  876.   Having this module rely on external globals is bad, but fixing this
  877.   requires overhaul of the ck*tio.c modules for all the different operating
  878.   systems supported by C-Kermit.  Left for a future release.
  879. */
  880. extern int ttnproto;            /* Defined in ckcnet.c */
  881. extern int ttnet;            /* Defined in ckcnet.c */
  882. extern int xfrcan, xfrchr, xfrnum;    /* Defined in ckcmai.c */
  883. extern int suspend;
  884.  
  885. int ckxech = 0; /* 0 if system normally echoes console characters, else 1 */
  886.  
  887. /* Declarations of variables global within this module */
  888.  
  889. static time_t tcount;            /* Elapsed time counter */
  890. static SIGTYP (*saval)() = NULL;    /* For saving alarm() handler */
  891. #ifndef NOJC
  892. static SIGTYP (*jchdlr)() = NULL;    /* For checking suspend handler */
  893. #endif /* NOJC */
  894. static int jcshell = -1;        /* And flag for result */
  895.  
  896. /*
  897.   BREAKNULS is defined for systems that simulate sending a BREAK signal
  898.   by sending a bunch of NUL characters at low speed.
  899. */
  900. #ifdef PROVX1
  901. #ifndef BREAKNULS
  902. #define BREAKNULS
  903. #endif /* BREAKNULS */
  904. #endif /* PROVX1 */
  905.  
  906. #ifdef V7
  907. #ifndef BREAKNULS
  908. #define BREAKNULS
  909. #endif /* BREAKNULS */
  910. #endif /* V7 */
  911.  
  912. #ifdef BREAKNULS
  913. static char                /* A string of nulls */
  914. *brnuls = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
  915. #endif /* BREAKNULS */
  916.  
  917. #ifdef CK_POSIX_SIG            /* Longjump buffers */
  918. static sigjmp_buf sjbuf;        /* POSIX signal handling */
  919. #else
  920. static jmp_buf sjbuf;
  921. #endif /* CK_POSIX_SIG */
  922.  
  923. #ifdef V7
  924. static jmp_buf jjbuf;
  925. #endif /* V7 */
  926.  
  927. /* static */                /* (Not static any more) */
  928. int ttyfd = -1;                /* TTY file descriptor */
  929.  
  930. #ifdef Plan9
  931. int ttyctlfd  = -1;   /* TTY control channel - What? UNIX doesn't have one? */
  932. int consctlfd = -1;            /* Console control channel */
  933. int noisefd = -1;            /* tone channel */
  934. static int ttylastspeed = -1;        /* So we can lie about the speed */
  935. #endif /* Plan9 */
  936.  
  937. int telnetfd = 0;            /* File descriptor is for telnet */
  938. int x25fd = 0;                /* File descriptor is for X.25 */
  939.  
  940. static int lkf = 0,                     /* Line lock flag */
  941.     cgmf = 0,                           /* Flag that console modes saved */
  942.     xlocal = 0,                         /* Flag for tty local or remote */
  943.     curcarr = 0;            /* Carrier mode: require/ignore. */
  944.  
  945. static int netconn = 0;            /* 1 if network connection active */
  946.  
  947. static char escchr;                     /* Escape or attn character */
  948.  
  949. #ifdef COHERENT
  950. #ifdef SELECT
  951.     static struct timeval tv;        /* Needed for -DSELECT in makefile */
  952. #endif /* SELECT */
  953. #endif /* COHERENT */
  954.  
  955. #ifdef QNX
  956.     static struct timeval tv;        /* For getting time, from sys/time.h */
  957.     static struct timezone tz;
  958. #else
  959. #ifdef SOLARIS
  960.     static struct timeval tv;        /* For getting time, from sys/time.h */
  961.     static struct timezone tz;
  962. #else
  963. #ifdef HPUX
  964.     static struct timeval tv;        /* For getting time, from sys/time.h */
  965.     static struct timezone tz;
  966. #else
  967. #ifdef __linux__
  968.     static struct timeval tv;        /* For getting time, from sys/time.h */
  969.     static struct timezone tz;
  970. #else
  971. #ifdef PS2AIX10
  972.     static struct timeval tv;        /* For getting time, from sys/time.h */
  973.     static struct timezone tz;
  974. #else
  975. #ifdef AIXRS
  976.     static struct timeval tv;        /* For getting time, from sys/time.h */
  977.     static struct timezone tz;
  978. #else
  979. #ifdef BSD44
  980.     static struct timeval tv;        /* For getting time, from sys/time.h */
  981.     static struct timezone tz;
  982. #else
  983. #ifdef BSD42
  984.     static struct timeval tv;        /* For getting time, from sys/time.h */
  985.     static struct timezone tz;
  986. #ifdef OSF
  987.     static struct timeb ftp;            /* And from sys/timeb.h */
  988. #endif /* OSF */
  989. #else
  990. #ifdef OXOS
  991.     static struct timeval tv;        /* For getting time, from sys/time.h */
  992.     static struct timezone tz;
  993. #else
  994. #ifdef SELECT
  995. #ifndef BELLV10
  996.     static struct timeval tv;
  997.     static struct timezone tz;
  998. #endif /* BELLV10 */
  999. #endif /* SELECT */
  1000. #endif /* OXOS */
  1001. #endif /* BSD42 */
  1002. #endif /* BSD44 */
  1003. #endif /* AIXRS */
  1004. #endif /* PS2AIX10 */
  1005. #endif /* __linux__ */
  1006. #endif /* HPUX */
  1007. #endif /* SOLARIS */
  1008. #endif /* QNX */
  1009.  
  1010. #ifdef BSD29
  1011.     static long xclock;            /* For getting time from sys/time.h */
  1012.     static struct timeb ftp;            /* And from sys/timeb.h */
  1013. #endif /* BSD29 */
  1014.  
  1015. #ifdef BSD41
  1016.     static long xclock;            /* For getting time from sys/time.h */
  1017.     static struct timeb ftp;            /* And from sys/timeb.h */
  1018. #endif /* BSD41 */
  1019.  
  1020. #ifdef BELLV10
  1021.     static long xclock;            /* For getting time from sys/time.h */
  1022.     static struct timeb ftp;            /* And from sys/timeb.h */
  1023. #endif /* BELLV10 */
  1024.  
  1025. #ifdef FT21
  1026.     static long xclock;            /* For getting time from sys/time.h */
  1027.     static struct timeb ftp;            /* And from sys/timeb.h */
  1028. #endif /* FT21 */
  1029.  
  1030. #ifdef TOWER1
  1031.     static long xclock;            /* For getting time from sys/time.h */
  1032.     static struct timeb ftp;        /* And from sys/timeb.h */
  1033. #endif /* TOWER1 */
  1034.  
  1035. #ifdef COHERENT
  1036.     static long xclock;            /* For getting time from sys/time.h */
  1037.     static struct timeb ftp;        /* And from sys/timeb.h */
  1038. #endif /* COHERENT */
  1039.  
  1040. #ifdef V7
  1041.     static long xclock;
  1042. #endif /* V7 */
  1043.  
  1044. /* sgtty/termio information... */
  1045.  
  1046. #ifdef BSD44ORPOSIX            /* POSIX or BSD44 */
  1047.   static struct termios
  1048.     ttold, ttraw, tttvt, ttcur,
  1049.     ccold, ccraw, cccbrk;
  1050. #else                    /* BSD, V7, etc */
  1051.  
  1052. #ifdef COHERENT                /* Hack alert... */
  1053. #define ATTSV
  1054. #endif /* COHERENT */
  1055.  
  1056. #ifdef ATTSV
  1057.   static struct termio ttold = {0};    /* Init'd for word alignment, */
  1058.   static struct termio ttraw = {0};    /* which is important for some */
  1059.   static struct termio tttvt = {0};    /* systems, like Zilog... */
  1060.   static struct termio ttcur = {0};
  1061.   static struct termio ccold = {0};
  1062.   static struct termio ccraw = {0};
  1063.   static struct termio cccbrk = {0};
  1064. #else
  1065.   static struct sgttyb                  /* sgtty info... */
  1066.     ttold, ttraw, tttvt, ttcur,     /* for communication line */
  1067.     ccold, ccraw, cccbrk;        /* and for console */
  1068. #ifdef BELLV10
  1069.   static struct ttydevb            /* Device info... */
  1070.     tdold, tdcur;            /* for communication device */
  1071. #endif /* BELLV10 */
  1072. #ifdef TIOCGETC
  1073.   static struct tchars tchold, tchnoi;
  1074.  
  1075.   static int tcharf;
  1076. #endif /* TIOCGETC */
  1077. #ifdef TIOCGLTC
  1078.   static struct ltchars ltchold, ltchnoi;
  1079.   static int ltcharf;
  1080. #endif /* TIOCGLTC */
  1081.   int lmodef = 0;            /* Local modes */
  1082.   int lmode = 0;
  1083. #endif /* ATTSV */
  1084. #endif /* BSD44ORPOSIX */
  1085.  
  1086. #ifdef PROVX1
  1087.   static struct sgttyb ttbuf;
  1088. #endif /* PROVX1 */
  1089.  
  1090. #ifdef ultrix
  1091. /* do we really need this? */
  1092.   static struct sgttyb vanilla;
  1093. #endif /* ultrix */
  1094.  
  1095. #ifdef ATT7300
  1096. static int attmodem = 0;                /* ATT7300 internal-modem status */
  1097. struct updata dialer = {0};        /* Condition dialer for data call */
  1098. #endif /* ATT7300 */
  1099.  
  1100. #ifndef NOUUCP
  1101. char flfnam[80];            /* UUCP lock file path name */
  1102. #ifdef HPUX10
  1103. char lock2[80];                /* Name of second lockfile */
  1104. #endif /* HPUX10 */
  1105. #else
  1106. char flfnam[8];
  1107. #endif /* NOUUCP */
  1108.  
  1109. #ifdef RTAIX
  1110. char lkflfn[80];            /* and possible link to it */
  1111. #endif /* RTAIX */
  1112. int haslock = 0;            /* =1 if this kermit locked uucp */
  1113.  
  1114. #ifndef OXOS
  1115. #ifdef SVORPOSIX
  1116. static int conesc = 0;                  /* set to 1 if esc char (^\) typed */
  1117. #else
  1118. #ifdef V7
  1119. static int conesc = 0;
  1120. #else
  1121. #ifdef C70
  1122. static int conesc = 0;
  1123. #endif /* C70 */
  1124. #endif /* V7 */
  1125. #endif /* SVORPOSIX */
  1126. #endif /* OXOS */
  1127.  
  1128. static char ttnmsv[DEVNAMLEN];        /* Copy of open path for tthang */
  1129.  
  1130. #ifdef aegis
  1131. static status_$t st;                    /* error status return value */
  1132. static short concrp = 0;                /* true if console is CRP pad */
  1133. #define CONBUFSIZ 10
  1134. static char conbuf[CONBUFSIZ];          /* console readahead buffer */
  1135. static int  conbufn = 0;                /* # chars in readahead buffer */
  1136. static char *conbufp;                   /* next char in readahead buffer */
  1137. static uid_$t ttyuid;                   /* tty type uid */
  1138. static uid_$t conuid;                   /* stdout type uid */
  1139.  
  1140. /* APOLLO Aegis main()
  1141.  * establish acl usage and cleanup handling
  1142.  *    this makes sure that CRP pads
  1143.  *    get restored to a usable mode
  1144.  */
  1145. main(argc,argv) int argc; char **argv; {
  1146.         status_$t status;
  1147.         pfm_$cleanup_rec dirty;
  1148.  
  1149.         PID_T pid = getpid();
  1150.  
  1151.         /* acl usage according to invoking environment */
  1152.         default_acl(USE_DEFENV);
  1153.  
  1154.         /* establish a cleanup continuation */
  1155.         status = pfm_$cleanup(dirty);
  1156.         if (status.all != pfm_$cleanup_set) {
  1157.                 /* only handle faults for the original process */
  1158.                 if (pid == getpid() && status.all > pgm_$max_severity) {
  1159.             /* blew up in main process */
  1160.             status_$t quo;
  1161.             pfm_$cleanup_rec clean;
  1162.  
  1163.             /* restore the console in any case */
  1164.             conres();
  1165.  
  1166.             /* attempt a clean exit */
  1167.             debug(F101, "cleanup fault status", "", status.all);
  1168.  
  1169.             /* doexit(), then send status to continuation */
  1170.             quo = pfm_$cleanup(clean);
  1171.             if (quo.all == pfm_$cleanup_set)
  1172.               doexit(pgm_$program_faulted,-1);
  1173.             else if (quo.all > pgm_$max_severity)
  1174.               pfm_$signal(quo); /* blew up in doexit() */
  1175.                 }
  1176.                 /* send to the original continuation */
  1177.                 pfm_$signal(status);
  1178.                 /*NOTREACHED*/
  1179.         }
  1180.         return(ckcmai(argc, argv));
  1181. }
  1182. #endif /* aegis */
  1183.  
  1184. /* ANSI-style prototypes for internal functions. */
  1185. /* Functions used outside this module are prototyped in ckcker.h. */
  1186.  
  1187. #ifdef apollo
  1188. _PROTOTYP( SIGTYP timerh, () );
  1189. _PROTOTYP( SIGTYP cctrap, () );
  1190. _PROTOTYP( SIGTYP esctrp, () );
  1191. _PROTOTYP( SIGTYP sig_ign, () );
  1192. #else
  1193. _PROTOTYP( SIGTYP timerh, (int) );
  1194. _PROTOTYP( SIGTYP cctrap, (int) );
  1195. _PROTOTYP( SIGTYP esctrp, (int) );
  1196. #endif /* apollo */
  1197. _PROTOTYP( int do_open, (char *) );
  1198. _PROTOTYP( static int in_chk, (int) );
  1199. _PROTOTYP( static int ttrpid, (char *) );
  1200. _PROTOTYP( static int ttlock, (char *) );
  1201. _PROTOTYP( static int ttunlck, (void) );
  1202. _PROTOTYP( int mygetbuf, (void) );
  1203. _PROTOTYP( int myfillbuf, (void) );
  1204. _PROTOTYP( VOID conbgt, (int) );
  1205. #ifdef ACUCNTRL
  1206. _PROTOTYP( VOID acucntrl, (char *, char *) );
  1207. #endif /* ACUCNTRL */
  1208.  
  1209. #ifdef BSD44ORPOSIX
  1210. _PROTOTYP( int carrctl, (struct termios *, int) );
  1211. #else
  1212. #ifdef ATTSV
  1213. _PROTOTYP( int carrctl, (struct termio *, int) );
  1214. #else
  1215. _PROTOTYP( int carrctl, (struct sgttyb *, int) );
  1216. #endif /* ATTSV */
  1217. #endif /* BSD44ORPOSIX */
  1218.  
  1219. #ifdef ATT7300
  1220. _PROTOTYP( int attdial, (char *, long, char *) );
  1221. _PROTOTYP( int offgetty, (char *) );
  1222. _PROTOTYP( int ongetty, (char *) );
  1223. #endif /* ATT7300 */
  1224.  
  1225. #ifdef BEBOX
  1226. #ifdef BE_DR_7
  1227. static double time_started = 0.0;
  1228. #include <kernel/OS.h>
  1229. struct ALARM_STRUCT {
  1230.     thread_id thread;
  1231.     int time;
  1232. };
  1233. static thread_id alarm_thread = -1;
  1234. static struct ALARM_STRUCT alarm_struct;
  1235. _PROTOTYP( long do_alarm, (void *) );
  1236. _PROTOTYP( unsigned int alarm, (unsigned int) );
  1237. _PROTOTYP( void alarm_expired, (void) );
  1238. #endif /* BE_DR_7 */
  1239. #endif /* BEBOX */
  1240.  
  1241. #ifdef CK_ANSIC
  1242. static char *
  1243. xxlast(char *s, char c)
  1244. #else
  1245. static char *
  1246. xxlast(s,c) char *s; char c;
  1247. #endif /* CK_ANSIC */
  1248. /* xxlast */ {        /*  Last occurrence of character c in string s. */
  1249.     int i;
  1250.     for (i = (int)strlen(s); i > 0; i--)
  1251.         if ( s[i-1] == c ) return( s + (i - 1) );
  1252.     return(NULL);
  1253. }
  1254.  
  1255. /* Timeout handler for communication line input functions */
  1256.  
  1257. SIGTYP
  1258. timerh(foo) int foo; {
  1259.     ttimoff();
  1260. #ifdef BEBOX
  1261.     alarm_expired();
  1262. #endif /* BEBOX */
  1263. #ifdef CK_POSIX_SIG
  1264.     siglongjmp(sjbuf,1);
  1265. #else
  1266.     longjmp(sjbuf,1);
  1267. #endif /* CK_POSIX_SIG */
  1268. }
  1269.  
  1270. /* Control-C trap for communication line input functions */
  1271.  
  1272. int cc_int;                /* Flag */
  1273. SIGTYP (* occt)();            /* For saving old SIGINT handler */
  1274.  
  1275. SIGTYP
  1276. cctrap(foo) int foo; {            /* Needs arg for ANSI C */
  1277.   cc_int = 1;                /* signal() prototype. */
  1278.   return;
  1279. }
  1280.  
  1281. /*  S Y S I N I T  --  System-dependent program initialization.  */
  1282.  
  1283. /*
  1284.  * ttgwsiz() returns:
  1285.  *    1    tt_rows and tt_cols are known, both altered, both > 0
  1286.  *    0    tt_rows and/or tt_cols are known, both altered, one or both <= 0
  1287.  *    -1   tt_rows and tt_cols are unknown and unaltered
  1288.  */
  1289.  
  1290. int
  1291. ttgwsiz() {
  1292. #ifndef NONAWS
  1293.     extern int tt_rows, tt_cols;
  1294.  
  1295. #ifdef QNX
  1296. /*
  1297.   NOTE: TIOCGWSIZ works here too, but only in the 32-bit version.
  1298.   This code works for both the 16- and 32-bit versions.
  1299. */
  1300.     extern int dev_size(int, int, int, int *, int *);
  1301.     int r, c;
  1302.  
  1303.     if (dev_size(0, -1, -1, &r, &c) == 0) {
  1304.     debug(F101,"ttgwsiz QNX r","",r);
  1305.     debug(F101,"ttgwsiz QNX c","",c);
  1306.     tt_rows = r;
  1307.     tt_cols = c;
  1308.     return ((r > 0 && c > 0) ? 1 : 0);
  1309.     } else return(-1);
  1310. #else /* QNX */
  1311. #ifdef TIOCGWINSZ
  1312.  
  1313. /* Note, this was M_UNIX, changed to XENIX to allow cross compilation... */
  1314. #ifdef XENIX                /* SCO UNIX 3.2v4.0 */
  1315. #include <sys/stream.h>            /* typedef mblk_t needed by ptem.h */
  1316. #include <sys/ptem.h>            /* for ttgwsiz() */
  1317. #endif /* XENIX */
  1318.  
  1319. #ifdef I386IX                /* Ditto for Interactive */
  1320. #include <sys/stream.h>
  1321. #include <sys/ptem.h>
  1322. #endif /* I386IX */
  1323.  
  1324. /* Note, the above might be needed for some other older SVR3 Intel makes... */
  1325.  
  1326.     struct winsize w;
  1327.     if (ioctl(0, (int)TIOCGWINSZ, (char *)&w) < 0)
  1328.     return(-1);
  1329.     else if (w.ws_row > 0 && w.ws_col > 0) {
  1330.     tt_rows = w.ws_row;
  1331.     tt_cols = w.ws_col;
  1332.     debug(F101,"ttgwsiz tt_rows","",tt_rows);
  1333.     debug(F101,"ttgwsiz tt_cols","",tt_cols);
  1334.     return(1);
  1335.     } else return(0);
  1336. #endif /* TIOCGWINSZ */
  1337. #endif /* QNX */
  1338. #endif /* NONAWS */
  1339. }
  1340.  
  1341. int
  1342. sysinit() {
  1343.     int x;
  1344. /*
  1345.   BEFORE ANYTHING ELSE: Initialize the setuid package.
  1346.   Change to the user's real user and group ID.
  1347.   If this can't be done, don't run at all.
  1348. */
  1349.     debug(F100,"sysinit calling priv_ini","",0);
  1350.     if (x = priv_ini()) {
  1351.     if (x & 1) fprintf(stderr,"Fatal: setuid failure.\n");
  1352.     if (x & 2) fprintf(stderr,"Fatal: setgid failure.\n");
  1353.     if (x & 4) fprintf(stderr,"Fatal: C-Kermit setuid to root!\n");
  1354.     exit(1);
  1355.     }
  1356. #ifndef NOJC
  1357. /*
  1358.   Get the initial job control state.
  1359.   If it is SIG_IGN, that means the shell does not support job control,
  1360.   and so we'd better not suspend ourselves.
  1361. */
  1362. #ifdef SIGTSTP
  1363.     jchdlr = signal(SIGTSTP,SIG_IGN);
  1364.     if (jchdlr == SIG_IGN) {
  1365.     jcshell = 0;
  1366.     debug(F100,"sysinit jchdlr: SIG_IGN","",0);
  1367.     } else if (jchdlr == SIG_DFL) {
  1368.     debug(F100,"sysinit jchdlr: SIG_DFL","",0);
  1369.     jcshell = 1;
  1370.     } else {
  1371.     debug(F100,"sysinit jchdlr: other","",0);
  1372.     jcshell = 3;
  1373.     }
  1374.     (VOID) signal(SIGTSTP,jchdlr);    /* Put it back... */
  1375. #endif /* SIGTSTP */
  1376. #endif /* NOJC */
  1377.  
  1378.     conbgt(0);                /* See if we're in the background */
  1379.     congm();                /* Get console modes */
  1380.  
  1381.     (VOID) signal(SIGALRM,SIG_IGN);    /* Ignore alarms */
  1382. #ifndef SIGUSR1                /* User-defined signals */
  1383. #define SIGUSR1 30
  1384. #endif /* SIGUSR1 */
  1385.  
  1386. #ifndef SIGUSR2
  1387. #define SIGUSR2 31
  1388. #endif /* SIGUSR2 */
  1389.  
  1390.     (VOID) signal(SIGUSR1,SIG_IGN);    /* Ignore user-defined signals */
  1391.     (VOID) signal(SIGUSR2,SIG_IGN);    /*  */
  1392.  
  1393. #ifdef SIGDANGER            /* Ignore danger signals */
  1394. /*
  1395.   This signal is sent when the system is low on swap space.  Processes
  1396.   that don't handle it are candidates for termination.  If swap space doesn't
  1397.   clear out enough, we still might be terminated via kill() -- nothing we can
  1398.   do about that!  Conceivably, this could be improved by installing a real
  1399.   signal handler that warns the user, but that would be pretty complicated,
  1400.   since we are not always in control of the screen -- e.g. during remote-mode
  1401.   file transfer.
  1402. */
  1403.     (VOID) signal(SIGDANGER,SIG_IGN);    /* e.g. on RS/6000 AIX */
  1404. #endif /* SIGDANGER */
  1405.  
  1406. #ifdef SIGPIPE
  1407. /*
  1408.   This one comes when a TCP/IP connection is broken by the remote.
  1409.   We prefer to catch this situation by examining error codes from write().
  1410. */
  1411.     (VOID) signal(SIGPIPE,SIG_IGN);
  1412. #endif /* SIGPIPE */
  1413.  
  1414. #ifdef ultrix
  1415.     gtty(0,&vanilla);            /* Get sgtty info */
  1416.     iniflags = fcntl(0,F_GETFL,0);    /* Get flags */
  1417. #else
  1418. #ifdef AUX
  1419.     set42sig();                /* Don't ask! (hakanson@cs.orst.edu) */
  1420. #endif /* AUX */
  1421. #endif /* ultrix */
  1422.  
  1423.     ttgwsiz();                /* Get window (screen) dimensions. */
  1424.  
  1425. #ifdef Plan9
  1426.     if (!backgrd) {
  1427.         consctlfd = open("/dev/consctl", O_WRONLY);
  1428.         /*noisefd = open("/dev/noise", O_WRONLY)*/
  1429.     }
  1430.     ckxech = 1;
  1431. #endif /* Plan9 */
  1432.  
  1433.     return(0);
  1434. }
  1435.  
  1436. /*  S Y S C L E A N U P  --  System-dependent program cleanup.  */
  1437.  
  1438. int
  1439. syscleanup() {
  1440. #ifdef ultrix
  1441.     stty(0,&vanilla);                   /* Get sgtty info */
  1442.     fcntl(0,F_SETFL,iniflags);        /* Restore flags */
  1443. #endif /* ultrix */
  1444.     /* No need to call anything in the suid package here, right? */
  1445.     return(0);
  1446. }
  1447.  
  1448. /*  T T O P E N  --  Open a tty for exclusive access.  */
  1449.  
  1450. /*
  1451.   Call with:
  1452.     ttname: character string - device name or network host name.
  1453.     lcl:
  1454.   If called with lcl < 0, sets value of lcl as follows:
  1455.   0: the terminal named by ttname is the job's controlling terminal.
  1456.   1: the terminal named by ttname is not the job's controlling terminal.
  1457.   But watch out: if a line is already open, or if requested line can't
  1458.   be opened, then lcl remains (and is returned as) -1.
  1459.     modem:
  1460.   Less than zero: ttname is a network host name.
  1461.   Zero or greater: ttname is a terminal device name.    
  1462.   Zero means a local connection (don't use modem signals).
  1463.   Positive means use modem signals.  
  1464.    timo:
  1465.   0 = no timer.
  1466.   nonzero = number of seconds to wait for open() to return before timing out.
  1467.  
  1468.   Returns:
  1469.     0 on success
  1470.    -5 if device is in use
  1471.    -4 if access to device is denied
  1472.    -3 if access to lock directory denied
  1473.    -2 upon timeout waiting for device to open
  1474.    -1 on other error
  1475. */
  1476. static int ttotmo = 0;            /* Timeout flag */
  1477. /* Flag kept here to avoid being clobbered by longjmp.  */
  1478.  
  1479. int
  1480. ttopen(ttname,lcl,modem,timo) char *ttname; int *lcl, modem, timo; {
  1481.  
  1482. #ifdef BSD44
  1483. #define ctermid(x) strcpy(x,"")
  1484. #else
  1485. #ifdef SVORPOSIX
  1486. #ifndef CIE
  1487.     extern char *ctermid();        /* Wish they all had this! */
  1488. #else                    /* CIE Regulus */
  1489. #define ctermid(x) strcpy(x,"")
  1490. #endif /* CIE */
  1491. #endif /* SVORPOSIX */
  1492. #endif /* BSD44 */
  1493.  
  1494. #ifdef ultrix
  1495.     int temp = 0;
  1496. #endif /* ultrix */
  1497.  
  1498.     char *x;                /* Worker string pointer */
  1499.  
  1500. #ifndef MINIX
  1501.     extern char* ttyname();
  1502. #endif /* MINIX */
  1503.     char cname[DEVNAMLEN+4];
  1504.  
  1505. #ifndef pdp11
  1506. #define NAMEFD     /* Feature to allow name to be an open file descriptor */
  1507. #endif /* pdp11 */
  1508.  
  1509. #ifdef NAMEFD
  1510.     char *p;
  1511.     debug(F101,"ttopen telnetfd","",telnetfd);
  1512. #endif /* NAMEFD */
  1513.  
  1514.     debug(F111,"ttopen entry modem",ttname,modem);
  1515.     debug(F101," ttyfd","",ttyfd);
  1516.     debug(F101," lcl","",*lcl);
  1517.  
  1518. #ifdef MAXNAMLEN
  1519.     debug(F100,"ttopen MAXNAMLEN defined","",0);
  1520. #else
  1521.     debug(F100,"ttopen MAXNAMLEN *NOT* defined","",0);
  1522. #endif
  1523.  
  1524. #ifdef BSD4
  1525.     debug(F100,"ttopen BSD4 defined","",0);
  1526. #else
  1527.     debug(F100,"ttopen BSD4 *NOT* defined","",0);
  1528. #endif
  1529.  
  1530. #ifdef BSD42
  1531.     debug(F100,"ttopen BSD42 defined","",0);
  1532. #else
  1533.     debug(F100,"ttopen BSD42 *NOT* defined","",0);
  1534. #endif /* BSD42 */
  1535.  
  1536. #ifdef MYREAD
  1537.     debug(F100,"ttopen MYREAD defined","",0);
  1538. #else
  1539.     debug(F100,"ttopen MYREAD *NOT* defined","",0);
  1540. #endif /* MYREAD */
  1541.  
  1542.     ttpmsk = 0xff;
  1543.     if (ttyfd > -1) {            /* if device already opened */
  1544.         if (strncmp(ttname,ttnmsv,DEVNAMLEN)) /* are new & old names equal? */
  1545.           ttclos(ttyfd);        /* no, close old ttname, open new */
  1546.         else                 /* else same, ignore this call, */
  1547.       return(0);            /* and return. */
  1548.     }
  1549.  
  1550. #ifdef    NETCONN
  1551.     if (modem < 0) {            /* modem < 0 = special code for net */
  1552.     int x;
  1553.     ttmdm = modem;
  1554.     modem = -modem;            /* Positive network type number */
  1555.     fdflag = 0;            /* Stdio not redirected. */
  1556.     netconn = 1;            /* And it's a network connection */
  1557.     debug(F111,"ttopen net",ttname,modem);
  1558. #ifdef NAMEFD
  1559.     for (p = ttname; isdigit(*p); p++) ; /* Check for all digits */
  1560.      if (*p == '\0' && (telnetfd || x25fd)) { /* Avoid X.121 addresses */
  1561.         ttyfd = atoi(ttname);    /* Is there a way to test it's open? */
  1562.         ttfdflg = 1;        /* We got an open file descriptor */
  1563.         debug(F111,"ttopen got open network fd",ttname,ttyfd);
  1564.         strncpy(ttnmsv,ttname,DEVNAMLEN); /* Remember the "name". */
  1565.         x = 1;            /* Return code is "good". */
  1566.         if (telnetfd) {
  1567.         ttnet = NET_TCPB;
  1568.         ttnproto = NP_TELNET;
  1569. #ifdef SUNX25
  1570.         } else if (x25fd) {
  1571.         ttnet = NET_SX25;
  1572.         ttnproto = NP_NONE;
  1573. #endif /* SUNX25 */        
  1574.         }
  1575.     } else {            /* Host name or address given */
  1576. #endif /* NAMEFD */
  1577.         x = netopen(ttname, lcl, modem); /* (see ckcnet.h) */
  1578.         if (x > -1) {
  1579.         strncpy(ttnmsv,ttname,DEVNAMLEN);
  1580.         } else netconn = 0;
  1581. #ifdef NAMEFD
  1582.     }
  1583. #endif /* NAMEFD */
  1584.  
  1585. #ifdef sony_news            /* Sony NEWS */
  1586.     if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) { /* Get Kanji mode */
  1587.         perror("ttopen error getting Kanji mode (network)");
  1588.         debug(F111,"ttopen error getting Kanji mode","network",0);
  1589.         km_ext = -1;        /* Make sure this stays undefined. */
  1590.     }
  1591. #endif /* sony_news */
  1592.  
  1593.     xlocal = *lcl = 1;        /* Network connections are local. */
  1594.     debug(F101,"ttopen net x","",x);
  1595. #ifdef COMMENT
  1596. /* Let netopen() do this */
  1597.     if (x > -1 && !x25fd)
  1598.       x = tn_ini();            /* Initialize TELNET protocol */
  1599. #endif /* COMMENT */
  1600.     return(x);
  1601.     } else {                /* Terminal device */
  1602. #endif    /* NETCONN */
  1603.  
  1604. #ifdef NAMEFD
  1605. /*
  1606.   This code lets you give Kermit an open file descriptor for a serial
  1607.   communication device, rather than a device name.  Kermit assumes that the
  1608.   line is already open, locked, conditioned with the right parameters, etc.
  1609. */
  1610.     for (p = ttname; isdigit(*p); p++) ; /* Check for all digits */
  1611.     if (*p == '\0') {
  1612.         ttyfd = atoi(ttname);    /* Is there a way to test it's open? */
  1613.         debug(F111,"ttopen got open fd",ttname,ttyfd);
  1614.         strncpy(ttnmsv,ttname,DEVNAMLEN); /* Remember the "name". */
  1615.         xlocal = *lcl = 1;        /* Assume it's local. */
  1616.         netconn = 0;        /* Assume it's not a network. */
  1617.         tvtflg = 0;            /* Might need to initialize modes. */
  1618.         ttmdm = modem;        /* Remember modem type. */
  1619.         fdflag = 0;            /* Stdio not redirected. */
  1620.         ttfdflg = 1;        /* Flag we were opened this way. */
  1621.  
  1622. #ifdef sony_news            /* Sony NEWS */
  1623.         /* Get device Kanji mode */
  1624.         if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) {
  1625.         perror("ttopen error getting Kanji mode");
  1626.         debug(F101,"ttopen error getting Kanji mode","",0);
  1627.         km_ext = -1;        /* Make sure this stays undefined. */
  1628.         }
  1629. #endif /* sony_news */
  1630.         return(0);            /* Return success */
  1631.     }
  1632. #endif /* NAMEFD */
  1633. #ifdef NETCONN
  1634.     }
  1635. #endif /* NETCONN */
  1636.  
  1637. /* Here we have to open a serial device of the given name. */
  1638.  
  1639.     occt = signal(SIGINT, cctrap);    /* Set Control-C trap, save old one */
  1640.  
  1641.     tvtflg = 0;            /* Flag for use by ttvt(). */
  1642.                 /* 0 = ttvt not called yet for this device */
  1643.  
  1644.     fdflag = (!isatty(0) || !isatty(1)); /* Flag for stdio redirected */
  1645.     debug(F101,"ttopen fdflag","",fdflag);
  1646.  
  1647.     ttmdm = modem;                      /* Make this available to other fns */
  1648.     xlocal = *lcl;                      /* Make this available to other fns */
  1649.  
  1650. /* Code for handling bidirectional tty lines goes here. */
  1651. /* Use specified method for turning off logins and suppressing getty. */
  1652.  
  1653. #ifdef ACUCNTRL
  1654.     /* Should put call to priv_on() here, but that would be very risky! */
  1655.     acucntrl("disable",ttname);         /* acucntrl() program. */
  1656.     /* and priv_off() here... */
  1657. #else
  1658. #ifdef ATT7300
  1659.     if ((attmodem & DOGETY) == 0)       /* offgetty() program. */
  1660.       attmodem |= offgetty(ttname);    /* Remember response.  */
  1661. #endif /* ATT7300 */
  1662. #endif /* ACUCNTRL */
  1663.  
  1664. /*
  1665.  In the following section, we open the tty device for read/write.
  1666.  If a modem has been specified via "set modem" prior to "set line"
  1667.  then the O_NDELAY parameter is used in the open, provided this symbol
  1668.  is defined (e.g. in fcntl.h), so that the program does not hang waiting
  1669.  for carrier (which in most cases won't be present because a connection
  1670.  has not been dialed yet).  O_NDELAY is removed later on in ttopen().  It
  1671.  would make more sense to first determine if the line is local before
  1672.  doing this, but because ttyname() requires a file descriptor, we have
  1673.  to open it first.  See do_open().
  1674.  
  1675.  Now open the device using the desired treatment of carrier.
  1676.  If carrier is REQUIRED, then open could hang forever, so an optional
  1677.  timer is provided.  If carrier is not required, the timer should never
  1678.  go off, and should do no harm...
  1679. */
  1680.     ttotmo = 0;                /* Flag no timeout */
  1681.     if (timo > 0) {
  1682.     int xx;
  1683.     saval = signal(SIGALRM,timerh);    /* Timed, set up timer. */
  1684.     xx = alarm(timo);        /* Timed open() */
  1685.     debug(F101,"ttopen alarm","",xx);
  1686.     if (
  1687. #ifdef CK_POSIX_SIG
  1688.         sigsetjmp(sjbuf,1)
  1689. #else
  1690.         setjmp(sjbuf)
  1691. #endif /* CK_POSIX_SIG */
  1692.         ) {
  1693.         ttotmo = 1;            /* Flag timeout. */
  1694.     } else ttyfd = do_open(ttname);
  1695.     ttimoff();
  1696.     debug(F111,"ttopen","modem",modem);
  1697.     debug(F101," ttyfd","",ttyfd);
  1698.     debug(F101," alarm return","",ttotmo);
  1699.     } else ttyfd = do_open(ttname);
  1700.     debug(F111,"ttopen ttyfd",ttname,ttyfd);
  1701.     if (ttyfd < 0) {            /* If couldn't open, fail. */
  1702. #ifdef ATT7300
  1703.     if (attmodem & DOGETY)        /* was getty(1m) running before us? */
  1704.       ongetty(ttnmsv);        /* yes, restart on tty line */
  1705.     attmodem &= ~DOGETY;        /* no phone in use, getty restored */
  1706. #else
  1707. #ifdef ACUCNTRL
  1708.         /* Should put call to priv_on() here, but that would be risky! */
  1709.     acucntrl("enable",ttname);    /* acucntrl() program. */    
  1710.     /* and priv_off() here... */
  1711. #endif /* ACUNTRL */
  1712. #endif /* ATT7300 */
  1713.  
  1714.     signal(SIGINT,occt);        /* Put old Ctrl-C trap back. */
  1715.     if (errno == EACCES) {        /* Device is protected against user */
  1716.         perror(ttname);        /* Print message */
  1717.         debug(F111,"ttopen tty access denied",ttname,errno);
  1718.         return(-4);
  1719.     } else return(ttotmo ? -2 : -1);
  1720.     }
  1721.  
  1722. #ifdef Plan9
  1723.     /* take this opportunity to open the control channel */
  1724.     if (p9openttyctl(ttname) < 0)
  1725. #else
  1726.     /* Make sure it's a real tty. */
  1727.     if (!isatty(ttyfd) && strcmp(ttname,"/dev/null"))
  1728. #endif /* Plan9 */
  1729.       {
  1730.     fprintf(stderr,"%s is not a terminal device\n",ttname);
  1731.     debug(F110,"ttopen not a tty",ttname,0);
  1732.     close(ttyfd);
  1733.     ttyfd = -1;
  1734.     signal(SIGINT,occt);
  1735.     return(-1);
  1736.     }
  1737.  
  1738. #ifdef aegis
  1739.     /* Apollo C runtime claims that console pads are tty devices, which
  1740.      * is reasonable, but they aren't any good for packet transfer. */
  1741.     ios_$inq_type_uid((short)ttyfd, ttyuid, st);
  1742.     if (st.all != status_$ok) {
  1743.         fprintf(stderr, "problem getting tty object type: ");
  1744.         error_$print(st);
  1745.     } else if (ttyuid != sio_$uid) { /* reject non-SIO lines */
  1746.         close(ttyfd); ttyfd = -1;
  1747.         errno = ENOTTY; perror(ttname);
  1748.         signal(SIGINT,occt);
  1749.         return(-1);
  1750.     }
  1751. #endif /* aegis */
  1752.  
  1753.     strncpy(ttnmsv,ttname,DEVNAMLEN);   /*  Keep copy of name locally. */
  1754.  
  1755. /* Caller wants us to figure out if line is controlling tty */
  1756.  
  1757.     if (*lcl < 0) {
  1758.     int x0 = 0, x1 = 0;
  1759.         if (strcmp(ttname,CTTNAM) == 0) {   /* "/dev/tty" always remote */
  1760.             xlocal = 0;
  1761.         debug(F111," ttname=CTTNAM",ttname,xlocal);
  1762.  
  1763.     /* If any of 0, 1, or 2 not redirected, we can use ttyname() to get */
  1764.     /* the name of the controlling terminal... */
  1765.  
  1766. /*
  1767.   Warning: on some UNIX systems (SVR4?), ttyname() reportedly opens /dev but
  1768.   never closes it.  If it is called often enough, we run out of file
  1769.   descriptors and subsequent open()'s of other devices or files can fail.
  1770. */
  1771.  
  1772.         } else if ((x0 = isatty(0)) || (x1 = isatty(1)) || isatty(2)) {
  1773. #ifndef MINIX
  1774.         if (x0)
  1775.           x = ttyname(0);        /* and compare it with the */
  1776.         else if (x1)        /* tty device name. */
  1777.           x = ttyname(1);
  1778.         else x = ttyname(2);
  1779.             strncpy(cname,x,DEVNAMLEN); /* (copy from internal static buf) */
  1780.         debug(F110," cname",x,0);
  1781. #ifdef BEBOX
  1782.             x = ttnmsv;            /* ttyname() is broken */
  1783. #else
  1784.             x = ttyname(ttyfd);         /* Get real name of ttname. */
  1785. #endif /* BEBOX */        
  1786.         if (x) {
  1787.         if (*x) {
  1788.             xlocal = (strncmp(x,cname,DEVNAMLEN) == 0) ? 0 : 1;
  1789.             debug(F111," ttyname",x,xlocal);
  1790.         }
  1791.         } else xlocal = 1;
  1792. #else
  1793.         xlocal = 1;            /* Can't do this test in MINIX */
  1794. #endif /* MINIX */
  1795.         } else {                        /* Else, if stdin redirected... */
  1796. #ifdef SVORPOSIX
  1797. /* System V provides nice ctermid() function to get name of controlling tty */
  1798.             ctermid(cname);             /* Get name of controlling terminal */
  1799.             debug(F110," ctermid",cname,0);
  1800.  
  1801.             x = ttyname(ttyfd);         /* Compare with name of comm line. */
  1802. #ifdef BEBOX
  1803.             xlocal = 1;            /* ttyname always returns /dev/tty */
  1804. #else
  1805.             xlocal = (strncmp(x,cname,DEVNAMLEN) == 0) ? 0 : 1;
  1806. #endif /* BEBOX */        
  1807.             debug(F111," ttyname",x,xlocal);
  1808. #else
  1809. /* Just assume local */
  1810.             xlocal = 1;
  1811. #endif /* SVORPOSIX */
  1812.             debug(F101," redirected stdin","",xlocal);
  1813.         }
  1814.     }
  1815.  
  1816. #ifndef NOFDZERO
  1817. /* Note, the following code was added so that Unix "idle-line" snoopers */
  1818. /* would not think Kermit was idle when it was transferring files, and */
  1819. /* maybe log people out. */
  1820.     if (xlocal == 0) {            /* Remote mode */
  1821.     if (fdflag == 0) {        /* Standard i/o is not redirected */
  1822.         debug(F100,"ttopen setting ttyfd = 0","",0);
  1823. #ifdef LYNXOS
  1824.         /* On Lynx OS, fd 0 is open for read only. */
  1825.         dup2(ttyfd,0);
  1826. #endif /* LYNXOS */
  1827.         close(ttyfd);        /* Use file descriptor 0 */
  1828.         ttyfd = 0;
  1829.     } else {            /* Standard i/o is redirected */
  1830.         debug(F101,"ttopen stdio redirected","",ttyfd);
  1831.     }
  1832.     }
  1833. #endif /* NOFDZERO */
  1834.  
  1835. /* Now check if line is locked -- if so fail, else lock for ourselves */
  1836. /* Note: After having done this, don't forget to delete the lock if you */
  1837. /* leave ttopen() with an error condition. */
  1838.  
  1839.     lkf = 0;                            /* Check lock */
  1840.     if (xlocal > 0) {
  1841.     int xx; int xpid;
  1842.         if ((xx = ttlock(ttname)) < 0) { /* Can't lock it. */
  1843.             debug(F111,"ttopen ttlock fails",ttname,xx);
  1844.         /* WARNING - This close() can hang if tty is an empty socket... */
  1845.             close(ttyfd);        /* Close the device. */
  1846.         ttyfd = -1;            /* Erase its file descriptor. */
  1847.         signal(SIGINT,occt);    /* Put old SIGINT back. */
  1848.         if (xx == -2) {        /* If lockfile says device in use, */
  1849. #ifndef NOUUCP
  1850.         debug(F111,"ttopen reading lockfile pid",flfnam,xx);
  1851.         priv_on();
  1852.         xpid = ttrpid(flfnam);    /* Try to read pid from lockfile */
  1853.         priv_off();        /* Turn privs back off. */
  1854.         if (xpid > -1) {    /* If we got a pid */
  1855.             printf("Locked by process %d\n",xpid); /* tell them. */
  1856.         } else if (*flfnam) {
  1857.             char *p = malloc(280); /* Print a directory listing. */
  1858. /*
  1859.   Note: priv_on() won't help here, because we do not pass privs along to
  1860.   to inferior processes, in this case ls.  So if the real user does not have
  1861.   directory-listing access to the lockfile directory, this will result in
  1862.   something like "not found".  That's why we try this only as a last resort.
  1863. */
  1864.             if (p) {        /* If we got the space... */
  1865.             extern char *DIRCMD;
  1866.             sprintf(p,"%s %s",DIRCMD,flfnam);
  1867.             zsyscmd(p);    /* Get listing. */
  1868.             if (p) {    /* free the space */
  1869.                 free(p);
  1870.                 p = NULL;
  1871.             }
  1872.             }
  1873.         }
  1874. #endif /* NOUUCP */
  1875.         return(-5);        /* Code for device in use */
  1876.         } else return(-3);        /* Access denied */
  1877.         } else lkf = 1;
  1878.     }
  1879.  
  1880. /* Got the line, now set the desired value for local. */
  1881.  
  1882.     if (*lcl != 0) *lcl = xlocal;
  1883.  
  1884. /* Some special stuff for v7... */
  1885.  
  1886. #ifdef  V7
  1887. #ifndef MINIX
  1888.     if (kmem[TTY] < 0) {        /*  If open, then skip this.  */
  1889.     qaddr[TTY] = initrawq(ttyfd);   /* Init the queue. */
  1890.     if ((kmem[TTY] = open("/dev/kmem", 0)) < 0) {
  1891.         fprintf(stderr, "Can't read /dev/kmem in ttopen.\n");
  1892.         perror("/dev/kmem");
  1893.         exit(1);
  1894.     }
  1895.     }
  1896. #endif /* !MINIX */
  1897. #endif /* V7 */
  1898.  
  1899. /* No failure returns after this point */
  1900.  
  1901. #ifdef ultrix
  1902.     ioctl(ttyfd, TIOCMODEM, &temp);
  1903. #ifdef TIOCSINUSE
  1904.     if (xlocal && ioctl(ttyfd, TIOCSINUSE, NULL) < 0) {
  1905.     fprintf(stderr, "Can't set in-use flag on %s.\n",ttname);
  1906.     perror("TIOCSINUSE");
  1907.     }
  1908. #endif /* TIOCSINUSE */
  1909. #endif /* ultrix */
  1910.  
  1911. /* Get tty device settings */
  1912.  
  1913. #ifdef BSD44ORPOSIX            /* POSIX */
  1914.     tcgetattr(ttyfd,&ttold);
  1915.     debug(F101,"ttopen tcgetattr ttold.c_lflag","",ttold.c_lflag);
  1916.     tcgetattr(ttyfd,&ttraw);
  1917.     tcgetattr(ttyfd,&tttvt);
  1918. #else                    /* BSD, V7, and all others */
  1919. #ifdef ATTSV                /* AT&T UNIX */
  1920.     ioctl(ttyfd,TCGETA,&ttold);
  1921.     debug(F101,"ttopen ioctl TCGETA ttold.c_lflag","",ttold.c_lflag);
  1922.     ioctl(ttyfd,TCGETA,&ttraw);
  1923.     ioctl(ttyfd,TCGETA,&tttvt);
  1924. #else
  1925. #ifdef BELLV10
  1926.     ioctl(ttyfd,TIOCGETP,&ttold);
  1927.     debug(F101,"ttopen BELLV10 ttold.sg_flags","",ttold.sg_flags);
  1928.     ioctl(ttyfd,TIOCGDEV,&tdold);
  1929.     debug(F101,"ttopen BELLV10 tdold.flags","",tdold.flags);
  1930. #else
  1931.     gtty(ttyfd,&ttold);
  1932.     debug(F101,"ttopen gtty ttold.sg_flags","",ttold.sg_flags);
  1933. #endif /* BELLV10 */
  1934.  
  1935. #ifdef sony_news            /* Sony NEWS */
  1936.     if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) { /* Get console Kanji mode */
  1937.     perror("ttopen error getting Kanji mode");
  1938.     debug(F101,"ttopen error getting Kanji mode","",0);
  1939.     km_ext = -1;            /* Make sure this stays undefined. */
  1940.     }
  1941. #endif /* sony_news */
  1942.  
  1943. #ifdef TIOCGETC
  1944.     tcharf = 0;                /* In remote mode, also get */
  1945.     if (xlocal == 0) {            /* special characters */
  1946.     if (ioctl(ttyfd,TIOCGETC,&tchold) < 0) {
  1947.         debug(F100,"ttopen TIOCGETC failed","",0);
  1948.     } else {
  1949.         tcharf = 1;            /* It worked. */
  1950.         ioctl(ttyfd,TIOCGETC,&tchnoi); /* Get another copy */
  1951.         debug(F100,"ttopen TIOCGETC ok","",0);
  1952.     }
  1953.     }    
  1954. #else
  1955.     debug(F100,"ttopen TIOCGETC not defined","",0);
  1956. #endif /* TIOCGETC */
  1957.  
  1958. #ifdef TIOCGLTC
  1959.     ltcharf = 0;            /* In remote mode, also get */
  1960.     if (xlocal == 0) {            /* local special characters */
  1961.     if (ioctl(ttyfd,TIOCGLTC,<chold) < 0) {
  1962.         debug(F100,"ttopen TIOCGLTC failed","",0);
  1963.     } else {
  1964.         ltcharf = 1;        /* It worked. */
  1965.         ioctl(ttyfd,TIOCGLTC,<chnoi); /* Get another copy */
  1966.         debug(F100,"ttopen TIOCGLTC ok","",0);
  1967.     }
  1968.     }    
  1969. #else
  1970.     debug(F100,"ttopen TIOCGLTC not defined","",0);
  1971. #endif /* TIOCGLTC */
  1972.  
  1973. #ifdef TIOCLGET
  1974.     lmodef = 0;
  1975.     if (ioctl(ttyfd,TIOCLGET,&lmode) < 0) {
  1976.     debug(F100,"ttopen TIOCLGET failed","",0);
  1977.     } else {
  1978.     lmodef = 1;
  1979.     debug(F100,"ttopen TIOCLGET ok","",0);
  1980.     }
  1981. #endif /* TIOCLGET */
  1982.  
  1983. #ifdef BELLV10
  1984.     ioctl(ttyfd,TIOCGETP,&ttraw);
  1985.     ioctl(ttyfd,TIOCGETP,&tttvt);
  1986. #else
  1987.     gtty(ttyfd,&ttraw);                 /* And a copy of it for packets*/
  1988.     gtty(ttyfd,&tttvt);                 /* And one for virtual tty service */
  1989. #endif /* BELLV10 */
  1990.  
  1991. #endif /* ATTSV */
  1992. #endif /* BSD44ORPOSIX */
  1993.  
  1994. /* Section for changing line discipline.  It's restored in ttres(). */
  1995.  
  1996. #ifdef AIXRS
  1997. #ifndef AIX41
  1998.     { union txname ld_name; int ld_idx = 0;
  1999.       ttld = 0;
  2000.         do {
  2001.         ld_name.tx_which = ld_idx++;
  2002.         ioctl(ttyfd, TXGETCD, &ld_name);
  2003.       if (!strncmp(ld_name.tx_name, "rts", 3))
  2004.           ttld |= 1;
  2005.         } while (*ld_name.tx_name);
  2006.         debug(F101,"AIX line discipline","",ttld);
  2007.       }
  2008. #endif /* AIX41 */
  2009. #endif /* AIXRS */
  2010.  
  2011. #ifdef BSD41
  2012. /* For 4.1BSD only, force "old" tty driver, new one botches TANDEM. */
  2013.     { int k;
  2014.       ioctl(ttyfd, TIOCGETD, &ttld);    /* Get and save line discipline */
  2015.       debug(F101,"4.1bsd line discipline","",ttld);
  2016.       k = OTTYDISC;            /* Switch to "old" discipline */
  2017.       k = ioctl(ttyfd, TIOCSETD, &k);
  2018.       debug(F101,"4.1bsd tiocsetd","",k);
  2019.     }
  2020. #endif /* BSD41 */
  2021.  
  2022. #ifdef aegis
  2023.     /* This was previously done before the last two TCGETA or gtty above,
  2024.      * in both the ATTSV and not-ATTSV case.  If it is not okay to have only
  2025.      * one copy if it here instead, give us a shout!
  2026.      */
  2027.     sio_$control((short)ttyfd, sio_$raw_nl, false, st);
  2028.     if (xlocal) {       /* ignore breaks from local line */
  2029.         sio_$control((short)ttyfd, sio_$int_enable, false, st);
  2030.         sio_$control((short)ttyfd, sio_$quit_enable, false, st);
  2031.     }
  2032. #endif /* aegis */
  2033.  
  2034. #ifdef VXVE
  2035.     ttraw.c_line = 0;                   /* STTY line 0 for VX/VE */
  2036.     tttvt.c_line = 0;                   /* STTY line 0 for VX/VE */
  2037.     ioctl(ttyfd,TCSETA,&ttraw);
  2038. #endif /* vxve */
  2039.  
  2040. /* If O_NDELAY was used during open(), then remove it now. */
  2041.  
  2042. #ifdef O_NDELAY
  2043.     if (fcntl(ttyfd, F_GETFL, 0) & O_NDELAY) {
  2044.  
  2045. #ifndef aegis
  2046.     if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY) < 0 )
  2047.         perror("Can't unset O_NDELAY");
  2048. #endif /* aegis */
  2049.     /* Some systems, notably Xenix (don't know how common this is in
  2050.      * other systems), need special treatment to get rid of the O_NDELAY
  2051.      * behaviour on read() with respect to carrier presence (i.e. read()
  2052.      * returning 0 when carrier absent), even though the above fcntl()
  2053.      * is enough to make read() wait for input when carrier is present.
  2054.      * This magic, in turn, requires CLOCAL for working when the carrier
  2055.      * is absent. But if xlocal == 0, presumably you already have CLOCAL
  2056.      * or you have a carrier, otherwise you wouldn't be running this.
  2057.      */
  2058. #ifdef ATTSV
  2059. #ifdef BSD44
  2060. #ifdef __bsdi__
  2061.     if (xlocal)
  2062.       ttraw.c_cflag |= CLOCAL;
  2063. #else
  2064. #ifdef __FreeBSD__
  2065.     if (xlocal)
  2066.       ttraw.c_cflag |= CLOCAL;
  2067. #endif /* __FreeBSD__ */
  2068. #endif /* __bsdi__ */
  2069.     if (tcsetattr(ttyfd, TCSADRAIN, &ttraw) < 0)
  2070.       perror("tcsetattr");
  2071. #else /* !BSD44 */
  2072.     if (xlocal) {
  2073.         ttraw.c_cflag |= CLOCAL;
  2074.         ioctl(ttyfd, TCSETA, &ttraw);
  2075.     }
  2076. #endif /* BSD44 */
  2077. #endif /* ATTSV */
  2078. #ifndef NOCOTFMC /* = NO Close(Open()) To Force Mode Change */
  2079. /* Reportedly lets uugetty grab the device in SCO UNIX 3.2 / XENIX 2.3 */
  2080.     close( priv_opn(ttname, O_RDWR) ); /* Magic to force change. */
  2081. #endif /* NOCOTFMC */
  2082.     }
  2083. #endif /* O_NDELAY */
  2084.  
  2085. /* Instruct the system how to treat the carrier, and set a few other tty
  2086.  * parameters.
  2087.  *
  2088.  * This also undoes the temporary setting of CLOCAL that may have been done
  2089.  * for the close(open()) above (except in Xenix).  Also throw in ~ECHO, to
  2090.  * prevent the other end of the line from sitting there talking to itself,
  2091.  * producing garbage when the user performs a connect.
  2092.  *
  2093.  * SCO Xenix unfortunately seems to ignore the actual state of CLOCAL.
  2094.  * Now it thinks CLOCAL is always on. It seems the only real solution for
  2095.  * Xenix is to switch between the lower and upper case device names.
  2096.  *
  2097.  * This section may at some future time expand into setting a complete
  2098.  * collection of tty parameters, or call a function shared with ttpkt()/
  2099.  * ttvt() that does so.  On the other hand, the initial parameters are not
  2100.  * that important, since ttpkt() or ttvt() should always fix that before
  2101.  * any communication is done.  Well, we'll see...
  2102.  */
  2103.     if (xlocal) {
  2104.         curcarr = -2;
  2105.     carrctl(&ttraw, ttcarr == CAR_ON);
  2106.  
  2107. #ifdef COHERENT
  2108. #define SVORPOSIX
  2109. #endif /* COHERENT */
  2110.  
  2111. #ifdef SVORPOSIX
  2112.     ttraw.c_lflag &= ~ECHO;
  2113.     ttold.c_lflag &= ~ECHO;
  2114. #ifdef BSD44ORPOSIX
  2115.     tcsetattr(ttyfd, TCSADRAIN, &ttraw);
  2116. #else
  2117.     ioctl(ttyfd, TCSETA, &ttraw);
  2118. #endif /* BSD44ORPOSIX */
  2119.  
  2120. #else /* BSD, etc */
  2121.     ttraw.sg_flags &= ~ECHO;
  2122.     ttold.sg_flags &= ~ECHO;
  2123. #ifdef BELLV10
  2124.     ioctl(ttyfd,TIOCSETP,&ttraw);
  2125. #else
  2126.     stty(ttyfd,&ttraw);
  2127. #endif /* BELLV10 */
  2128. #endif /* SVORPOSIX */
  2129.  
  2130. #ifdef COHERENT
  2131. #undef SVORPOSIX
  2132. #endif /* COHERENT */
  2133.  
  2134.     /* ttflui(); */  /*  This fails for some reason.  */
  2135.     }
  2136.     
  2137.     /* Get current speed */
  2138.  
  2139. #ifndef BEBOX
  2140.     ttspeed = ttgspd();
  2141. #else
  2142.     ttspeed = 19200;
  2143. #endif /* !BEBOX */
  2144.     debug(F101,"ttopen ttspeed","",ttspeed);
  2145.  
  2146.     /* Done, make entries in debug log, restore Ctrl-C trap, and return. */
  2147.  
  2148.     debug(F101,"ttopen, ttyfd","",ttyfd);
  2149.     debug(F101," lcl","",*lcl);
  2150.     debug(F111," lock file",flfnam,lkf);
  2151.     signal(SIGINT,occt);
  2152.     return(0);
  2153. }
  2154.  
  2155.  
  2156. /*  D O _ O P E N  --  Do the right kind of open() call for the tty. */
  2157.  
  2158. int
  2159. do_open(ttname) char *ttname; {
  2160.  
  2161. #ifndef    O_NDELAY            /* O_NDELAY not defined */
  2162.     return(priv_opn(ttname,2));
  2163. #else                    /* O_NDELAY defined */
  2164.  
  2165. #ifdef ATT7300
  2166. /*
  2167.  Open comms line without waiting for carrier so initial call does not hang
  2168.  because state of "modem" is likely unknown at the initial call  -jrd.
  2169.  If this is needed for the getty stuff to work, and the open would not work
  2170.  without O_NDELAY when getty is still on, then this special case is ok.
  2171.  Otherwise, get rid of it. -ske
  2172. */
  2173.     return(priv_opn(ttname, O_RDWR | O_NDELAY));
  2174.  
  2175. #else    /* !ATT7300 */
  2176.  
  2177.     /* Normal case. Use O_NDELAY according to SET CARRIER. See ttscarr(). */
  2178.   
  2179.     return(priv_opn(ttname, O_RDWR | ((ttcarr != CAR_ON) ? O_NDELAY : 0) ));
  2180.  
  2181. #endif    /* !ATT7300 */
  2182. #endif    /* O_NDELAY */
  2183. }
  2184.  
  2185. /*  T T C L O S  --  Close the TTY, releasing any lock.  */
  2186.  
  2187. int
  2188. ttclos(foo) int foo; {            /* Arg req'd for signal() prototype */
  2189.     int xx, x = 0;
  2190.  
  2191.     debug(F101,"ttclos ttyfd","",ttyfd);
  2192.     if (ttyfd < 0) return(0);           /* Wasn't open. */
  2193.  
  2194.     if (ttfdflg)            /* If we inherited ttyfd from */
  2195.       return(0);            /* another process, don't close it. */
  2196.  
  2197.     tvtflg = 0;                /* (some day get rid of this...) */
  2198.  
  2199. #ifdef    NETCONN
  2200.     if (netconn) {            /* If it's a network connection. */
  2201.     debug(F100,"ttclos closing net","",0);
  2202.     netclos();            /* Let the network module close it. */
  2203.     netconn = 0;            /* No more network connection. */
  2204.     debug(F101,"ttclos ttyfd after netclos","",ttyfd);
  2205.     return(0);
  2206.     }
  2207. #endif    /* NETCONN */
  2208.  
  2209.     if (xlocal) {            /* We're closing a SET LINE device */
  2210. #ifdef FT21                /* Fortune 2.1-specific items ... */
  2211.     ioctl(ttyfd,TIOCHPCL, NULL);
  2212. #endif /* FT21 */
  2213. #ifdef ultrix                /* Ultrix-specific items ... */
  2214. #ifdef TIOCSINUSE
  2215.     /* Unset the INUSE flag that we set in ttopen() */
  2216.     ioctl(ttyfd, TIOCSINUSE, NULL);
  2217. #endif /* TIOCSINUSE */
  2218.     ioctl(ttyfd, TIOCNMODEM, &x);
  2219. #ifdef COMMENT
  2220.     /* What was this? */
  2221.     ioctl(ttyfd, TIOCNCAR, NULL);
  2222. #endif /* COMMENT */
  2223. #endif /* ultrix */
  2224.     debug(F100,"ttclos about to call ttunlck","",0);
  2225.         if (ttunlck())                  /* Release uucp-style lock */
  2226.       fprintf(stderr,"Warning, problem releasing lock\r\n");
  2227.  
  2228.     }
  2229.     if (
  2230.     xlocal
  2231. #ifdef NOFDZERO
  2232.     || ttyfd > 0
  2233. #endif /* NOFDZERO */
  2234.     ) {
  2235.     saval = signal(SIGALRM,timerh); /* Enable timer interrupt. */
  2236.     xx = alarm(8);            /* Allow 8 seconds for this. */
  2237.     debug(F101,"ttclos alarm","",xx);
  2238.     if (
  2239. #ifdef CK_POSIX_SIG
  2240.         sigsetjmp(sjbuf,1)
  2241. #else
  2242.         setjmp(sjbuf)
  2243. #endif /* CK_POSIX_SIG */
  2244.         ) {                /* Timer went off? */
  2245.         x = -1;
  2246.     } else {            /* What we're really trying to do */
  2247.         debug(F100,"ttclos calling tthang()","",0);
  2248.         tthang();            /* Hang up first, then... */
  2249.         debug(F100,"ttclos calling ttres()","",0);
  2250.         ttres();            /* Reset device modes. */
  2251.     }
  2252.     debug(F101,"ttclos about to call close","",ttyfd);
  2253.     close(ttyfd);            /* Close the device. */
  2254.     x = 1;
  2255.     ttimoff();            /* Turn off timer. */
  2256.     if (x < 0) {
  2257.         fprintf(stderr,"?Timed out closing device: %s\n",ttnmsv);
  2258.         debug(F100,"ttclos timed out","",0);
  2259.     }
  2260.     }
  2261.  
  2262. /* For bidirectional lines, restore getty if it was there before. */
  2263.  
  2264.     if (xlocal) {
  2265.  
  2266. #ifdef ACUCNTRL                /* 4.3BSD acucntrl() method. */
  2267.     acucntrl("enable",ttnmsv);    /* Enable getty on the device. */
  2268. #else
  2269. #ifdef ATT7300                /* ATT UNIX PC (3B1, 7300) method. */
  2270.     if (attmodem & DOGETY)        /* Was getty(1m) running before us? */
  2271.       ongetty(ttnmsv);        /* Yes, restart getty on tty line */
  2272.     attmodem &= ~DOGETY;        /* No phone in use, getty restored */
  2273. #endif /* ATT7300 */
  2274. #endif /* System-dependent getty-restoring methods */
  2275.     }
  2276.  
  2277. #ifdef sony_news
  2278.     km_ext = -1;            /* Invalidate device's Kanji-mode */
  2279. #endif /* sony_news */
  2280.  
  2281.     ttyfd = -1;                         /* Invalidate the file descriptor. */
  2282.     debug(F100,"ttclos done","",0);
  2283.     return(0);
  2284. }
  2285.  
  2286. /*  T T H A N G  --  Hangup phone line or network connection.  */
  2287. /*
  2288.   Returns:
  2289.   0 if it does nothing.
  2290.   1 if it believes that it hung up successfully.
  2291.  -1 if it believes that the hangup attempt failed.
  2292. */
  2293.  
  2294. #define HUPTIME 500            /* Milliseconds for hangup */
  2295.  
  2296. int
  2297. tthang() {
  2298. #ifdef NOLOCAL
  2299.     return(0);
  2300. #else
  2301.     int x = 0;                /* Sometimes used as return code. */
  2302. #ifndef POSIX
  2303.     int z;                /* worker */
  2304. #endif /* POSIX */
  2305.  
  2306. #ifdef COHERENT
  2307. #define SVORPOSIX
  2308. #endif /* COHERENT */
  2309.  
  2310. #ifdef SVORPOSIX            /* AT&T, POSIX, HPUX declarations. */
  2311.     int spdsav;                /* for saving speed */
  2312. #ifdef BSD44ORPOSIX
  2313.     int spdsavi;
  2314. #endif /* BSD44ORPOSIX */
  2315. #ifdef HPUX
  2316. /*
  2317.   Early versions of HP-UX omitted the mflag typedef.  If you get complaints
  2318.   about it, just change it to long (or better still, unsigned long).
  2319. */
  2320.     mflag
  2321.       dtr_down = 00000000000,
  2322.       modem_rtn,
  2323.       modem_sav;
  2324.     char modem_state[64];
  2325. #endif /* HPUX */
  2326.     int flags;                /* fcntl flags */
  2327.     unsigned short ttc_save;
  2328. #endif /* SVORPOSIX */
  2329.  
  2330. #ifdef COHERENT
  2331. #undef SVORPOSIX
  2332. #endif /* COHERENT */
  2333.  
  2334.     if (ttyfd < 0) return(0);           /* Don't do this if not open  */
  2335.     if (xlocal < 1) return(0);        /* Don't do this if not local */
  2336.  
  2337. #ifdef NETCONN
  2338.     if (netconn)            /* Network connection. */
  2339.       return((netclos() < 0) ? -1 : 1);    /* Just close it. */
  2340. #endif /* NETCONN */
  2341.  
  2342. /* From here down, we handle real tty devices. */
  2343.  
  2344. #ifdef BSD44ORPOSIX
  2345. /* Should add some error checking here... */
  2346. /*
  2347.   NOTE: This should work for QNX too, but in case it doesn't, it is also
  2348.   possible to toggle DTR using qnx_ioctl(ttyfd,QCTL_DEV_CTL,&new,&old);
  2349.   see <sys/qioctl.h> and QNX News V10, Sep 96, p44.
  2350. */
  2351.     debug(F100,"tthang POSIX style","",0);
  2352.     tcgetattr(ttyfd, &ttcur);        /* Get current attributes */
  2353.     spdsav = cfgetospeed(&ttcur);    /* Get current speed */
  2354.     spdsavi = cfgetispeed(&ttcur);    /* Get current speed */
  2355.     cfsetospeed(&ttcur,B0);        /* Replace by 0 */
  2356.     cfsetispeed(&ttcur,B0);
  2357.     if (tcsetattr(ttyfd,TCSADRAIN,&ttcur) == -1)
  2358.       debug(F100,"tthang tcsetattr fails","",errno);
  2359.     msleep(HUPTIME);            /* Sleep */
  2360.     cfsetospeed(&ttcur,spdsav);        /* Restore previous speed */
  2361.     cfsetispeed(&ttcur,spdsavi);
  2362.     tcsetattr(ttyfd,TCSADRAIN,&ttcur);
  2363.     return(1);
  2364.  
  2365. #else /* BSD44ORPOSIX */
  2366.  
  2367. #ifdef aegis                /* Apollo Aegis */
  2368.     sio_$control((short)ttyfd, sio_$dtr, false, st);    /* DTR down */
  2369.     msleep(HUPTIME);                    /* pause */
  2370.     sio_$control((short)ttyfd, sio_$dtr, true,  st);    /* DTR up */
  2371.     return(1);
  2372. #endif /* aegis */
  2373.  
  2374. #ifdef ANYBSD                /* Any BSD version. */
  2375. #ifdef TIOCCDTR                /* Except those that don't have this */
  2376.     debug(F100,"tthang BSD style","",0);
  2377.     if (ioctl(ttyfd,TIOCCDTR,0) < 0) {    /* Clear DTR. */
  2378.     debug(F101,"tthang TIOCCDTR fails","",errno);
  2379.     return(-1);
  2380.     }
  2381.     msleep(HUPTIME);            /* For about 1/2 sec */
  2382.     errno = 0;
  2383.     x = ioctl(ttyfd,TIOCSDTR,0);    /* Restore DTR */
  2384.     if (x < 0) {
  2385.     /*
  2386.       For some reason, this tends to fail with "no such device or address"
  2387.       but the operation still works, probably because of the close/open
  2388.       later on.  So let's not scare the user unnecessarily here.
  2389.     */
  2390.     debug(F101,"tthang TIOCSDTR errno","",errno); /* Log the error */
  2391.     x = 1;                /* Pretend we succeeded */
  2392.     } else if (x == 0) x = 1;        /* Success */
  2393. #ifdef COMMENT
  2394. #ifdef FT21
  2395.     ioctl(ttyfd, TIOCSAVEMODES, 0);
  2396.     ioctl(ttyfd, TIOCHPCL, 0);
  2397.     close(ttyfd);            /* Yes, must do this twice */
  2398.     if ((ttyfd = open(ttnmsv,2)) < 0)    /* on Fortune computers... */
  2399.       return(-1);            /* (but why?) */
  2400.     else x = 1;
  2401. #endif /* FT21 */
  2402. #endif /* COMMENT */
  2403. #endif /* TIOCCDTR */
  2404.     close(do_open(ttnmsv));        /* Clear i/o error condition */
  2405.     errno = 0;
  2406. #ifdef COMMENT
  2407. /* This is definitely dangerous.  Why was it here? */
  2408.     z = ttvt(ttspeed,ttflow);        /* Restore modes. */
  2409.     debug(F101,"tthang ttvt returns","",z);
  2410.     return(z < 0 ? -1 : 1);
  2411. #else
  2412.     return(x);
  2413. #endif /* COMMENT */
  2414. #endif /* ANYBSD */
  2415.  
  2416. #ifdef ATTSV                
  2417. /* AT&T UNIX section, includes HP-UX and generic AT&T System III/V... */
  2418.  
  2419. #ifdef HPUX 
  2420. /* Hewlett Packard allows explicit manipulation of modem signals. */
  2421.  
  2422. #ifdef COMMENT
  2423. /* Old way... */
  2424.     debug(F100,"tthang HP-UX style","",0);
  2425.     if (ioctl(ttyfd,MCSETAF,&dtr_down) < 0)        /* lower DTR */
  2426.       return(-1);                           /* oops, can't. */
  2427.     msleep(HUPTIME);                       /* Pause half a second. */
  2428.     x = 1;                           /* Set return code */
  2429.     if (ioctl(ttyfd,MCGETA,&modem_rtn) > -1) {     /* Get line status. */
  2430.     if ((modem_rtn & MDCD) != 0)             /* Check if CD is low. */
  2431.       x = -1;                                  /* CD didn't drop, fail. */
  2432.     } else x = -1;
  2433.  
  2434.     /* Even if above calls fail, RTS & DTR should be turned back on. */
  2435.     modem_rtn = MRTS | MDTR;
  2436.     if (ioctl(ttyfd,MCSETAF,&modem_rtn) < 0) x = -1;
  2437.     return(x);
  2438. #else
  2439. /* New way, from Hellmuth Michaelis */
  2440.     debug(F100,"tthang HP-UX style, HPUXDEBUG","",0);
  2441.     if (ioctl(ttyfd,MCGETA,&modem_rtn) == -1) { /* Get current status. */
  2442.     debug(F100,"tthang HP-UX: can't get modem lines, NO HANGUP!","",0);
  2443.     return(-1);
  2444.     }
  2445.     sprintf(modem_state,"%#lx",modem_rtn);
  2446.     debug(F110,"tthang HP-UX: modem lines = ",modem_state,0); 
  2447.     modem_sav = modem_rtn;        /* Save current modem signals */
  2448.     modem_rtn &= ~MDTR;            /* Turn DTR bit off */
  2449.     sprintf(modem_state,"%#lx",modem_rtn);
  2450.     debug(F110,"tthang HP-UX: DTR down = ",modem_state,0); 
  2451.     if (ioctl(ttyfd,MCSETAF,&modem_rtn) < 0) { /* lower DTR */
  2452.     debug(F100,"tthang HP-UX: can't lower DTR!","",0);
  2453.     return(-1);            /* oops, can't. */
  2454.     }
  2455.     msleep(HUPTIME);            /* Pause half a second. */
  2456.     x = 1;                /* Set return code */
  2457.     if (ioctl(ttyfd,MCGETA,&modem_rtn) > -1) { /* Get line status. */
  2458.     sprintf(modem_state,"%#lx",modem_rtn);
  2459.     debug(F110,"tthang HP-UX: modem lines got = ",modem_state,0);    
  2460.     if ((modem_rtn & MDCD) != 0) {    /* Check if CD is low. */
  2461.         debug(F100,"tthang HP-UX: DCD not down","",0);
  2462.         x = -1;            /* CD didn't drop, fail. */
  2463.     } else {
  2464.         debug(F100,"tthang HP-UX: DCD down","",0);
  2465.     }
  2466.     } else {
  2467.     x = -1;
  2468.     debug(F100,"tthang HP-UX: can't get DCD status !","",0);
  2469.     }
  2470.  
  2471.     /* Even if above calls fail, DTR should be turned back on. */
  2472.  
  2473.     modem_sav |= MDTR;
  2474.     if (ioctl(ttyfd,MCSETAF,&modem_sav) < 0) {
  2475.     x = -1;
  2476.     debug(F100,"tthang HP-UX: can't set saved state","",0);
  2477.     } else {
  2478.     sprintf(modem_state,"%#lx",modem_sav);
  2479.     debug(F110,"tthang HP-UX: final modem lines = ",modem_state,0);    
  2480.     }        
  2481.     return(x);
  2482. #endif /* COMMENT */
  2483.  
  2484. #else /* AT&T but not HP-UX */
  2485.  
  2486. /* SVID for AT&T System V R3 defines ioctl's for handling modem signals. */
  2487. /* It is not known how many, if any, systems actually implement them, */
  2488. /* so we include them here in ifdef's. */
  2489.  
  2490. #ifndef _IBMR2
  2491. /*
  2492.   No modem-signal twiddling for IBM RT PC or RS/6000.
  2493.   In AIX 3.1 and earlier, the ioctl() call is broken.
  2494.   This code could be activated for AIX 3.1 with PTF 2006 or later
  2495.   (e.g. AIX 3.2), but close/open does the job too, so why bother.
  2496. */
  2497. #ifdef TIOCMBIS                /* Bit Set */
  2498. #ifdef TIOCMBIC                /* Bit Clear */
  2499. #ifdef TIOCM_DTR            /* DTR */
  2500.  
  2501. /* Clear DTR, sleep 300 msec, turn it back on. */
  2502. /* If any of the ioctl's return failure, go on to the next section. */
  2503.  
  2504.     z = TIOCM_DTR;            /* Code for DTR. */
  2505. #ifdef COMMENT
  2506. /*
  2507.   This was the cause of the troubles with the Solaris Port Monitor.
  2508.   The problem is: RTS never comes back on.  Moral: Don't do it!
  2509.   (But why doesn't it come back on?  See the TIOCMBIS call...)
  2510. */
  2511. #ifdef TIOCM_RTS            /* Lower RTS too if symbol is known. */
  2512.     z |= TIOCM_RTS;            
  2513. #endif /* TIOCM_RTS */
  2514. #endif /* COMMENT */
  2515.  
  2516.     debug(F101,"tthang TIOCM signal mask","",z);
  2517.     if (ioctl(ttyfd,TIOCMBIC,&z) > -1) {   /* Try to lower DTR. */
  2518.     debug(F100,"tthang TIOCMBIC ok","",0);
  2519.     msleep(HUPTIME);           /* Pause half a second. */
  2520.     if (ioctl(ttyfd,TIOCMBIS,&z) > -1) { /* Try to turn it back on. */
  2521.         debug(F100,"tthang TIOCMBIS ok","",0);
  2522. #ifndef CLSOPN
  2523.         return(1);            /* Success, done. */
  2524. #endif /* CLSOPN */
  2525.     } else {            /* Couldn't raise, continue. */
  2526.         debug(F101,"tthang TIOCMBIS errno","",errno);
  2527.     }
  2528.     } else {                /* Couldn't lower, continue. */
  2529.      debug(F101,"tthang TIOCMBIC errno","",errno);
  2530.     }
  2531. #endif /* TIOCM_DTR */
  2532. #endif /* TIOCMBIC */
  2533. #endif /* TIOCMBIS */
  2534. #endif /* _IBMR2 */
  2535. /*
  2536.   General AT&T UNIX case, not HPUX.  The following code is highly suspect.  No
  2537.   two AT&T-based systems seem to do this the same way.  The object is simply
  2538.   to turn off DTR and then turn it back on.  SVID says the universal method
  2539.   for turning off DTR is to set the speed to zero, and this does seem to do
  2540.   the trick in all cases.  But neither SVID nor any known man pages say how to
  2541.   turn DTR back on again.  Some variants, like most Xenix implementations,
  2542.   raise DTR again when the speed is restored to a nonzero value.  Others
  2543.   require the device to be closed and opened again, but this is risky because
  2544.   getty could seize the device during the instant it is closed.
  2545. */
  2546.  
  2547. /* Return code for ioctl failures... */
  2548. #ifdef ATT6300
  2549.     x = 1;                /* ATT6300 doesn't want to fail... */
  2550. #else
  2551.     x = -1;
  2552. #endif /* ATT6300 */
  2553.  
  2554.     debug(F100,"tthang get settings","",0);
  2555.     if (ioctl(ttyfd,TCGETA,&ttcur) < 0) /* Get current settings. */
  2556.       return(x);            /* Fail if this doesn't work. */
  2557.     if ((flags = fcntl(ttyfd,F_GETFL,0)) < 0) /* Get device flags. */
  2558.       return(x);
  2559.     ttc_save = ttcur.c_cflag;        /* Remember current speed. */
  2560.     spdsav = ttc_save & CBAUD;
  2561.     debug(F101,"tthang speed","",spdsav);
  2562.  
  2563. #ifdef O_NDELAY
  2564.     debug(F100,"tthang turning O_NDELAY on","",0);
  2565.     fcntl(ttyfd, F_SETFL, flags | O_NDELAY); /* Activate O_NDELAY */
  2566. #endif /* O_NDELAY */
  2567.  
  2568. #ifdef ATT7300 /* This is the way it is SUPPOSED to work */
  2569.     ttcur.c_cflag &= ~CBAUD;        /* Change the speed to zero.  */
  2570. #else
  2571. #ifdef RTAIX
  2572.     ttcur.c_cflag &= ~CBAUD;        /* Change the speed to zero.  */
  2573. #else          /* This way really works but may be dangerous */
  2574. #ifdef u3b2
  2575.     ttcur.c_cflag = ~(CBAUD|CLOCAL);    /* Special for AT&T 3B2s */
  2576.                     /* (CLOCAL must be OFF) */
  2577. #else
  2578. #ifdef SCO3R2                /* SCO UNIX 3.2 */
  2579. /*
  2580.   This is complete nonsense, but an SCO user claimed this change made
  2581.   hanging up work.  Comments from other SCO UNIX 3.2 users would be 
  2582.   appreciated.
  2583. */
  2584.     ttcur.c_cflag = CBAUD|B0;
  2585. #else
  2586. #ifdef AIXRS                /* AIX on RS/6000 */
  2587. /*
  2588.   Can't set speed to zero on AIX 3.1 on RS/6000 64-port adapter,
  2589.   even though you can do it on the built-in port and the 8- and 16-port
  2590.   adapters.  (Untested on 128-port adapter.)
  2591. */
  2592.     ttcur.c_cflag = CLOCAL|HUPCL|spdsav; /* Speed 0 causes EINVAL */
  2593. #else                    /* None of the above */
  2594. /*
  2595.   Set everything, including the speed, to zero, except for the CLOCAL
  2596.   and HUPCL bits.
  2597. */
  2598.     ttcur.c_cflag = CLOCAL|HUPCL;
  2599. #endif /* AIXRS */
  2600. #endif /* SCO3R2 */
  2601. #endif /* u3b2 */
  2602. #endif /* RTAIX */
  2603. #endif /* ATT7300 */
  2604.  
  2605. #ifdef COMMENT
  2606.     /* and if none of those work, try one of these... */
  2607.     ttcur.c_cflag = 0;
  2608.     ttcur.c_cflag = CLOCAL;
  2609.     ttcur.c_cflag &= ~(CBAUD|HUPCL);
  2610.     ttcur.c_cflag &= ~(CBAUD|CREAD);
  2611.     ttcur.c_cflag &= ~(CBAUD|CREAD|HUPCL);
  2612.     /* or other combinations */
  2613. #endif /* COMMENT */
  2614.  
  2615. #ifdef TCXONC
  2616.     debug(F100,"tthang TCXONC","",0);
  2617.     ioctl(ttyfd, TCXONC, 1);
  2618. #endif /* TCXONC */
  2619.  
  2620. #ifdef TIOCSTART
  2621.     debug(F100,"tthang TIOCSTART","",0);
  2622.     ioctl(ttyfd, TIOCSTART, 0);
  2623. #endif /* TIOCSTART */
  2624.  
  2625.     if (ioctl(ttyfd,TCSETAF,&ttcur) < 0) { /* Fail if we can't. */
  2626.     fcntl(ttyfd, F_SETFL, flags);    /* Restore flags */
  2627.     return(-1);            /* before returning. */
  2628.     }
  2629.     msleep(300);            /* Give modem time to notice. */
  2630.  
  2631. /* Now, even though it doesn't say this in SVID or any man page, we have */
  2632. /* to close and reopen the device.  This is not necessary for all systems, */
  2633. /* but it's impossible to predict which ones need it and which ones don't. */
  2634.  
  2635. #ifdef ATT7300
  2636. /*
  2637.   Special handling for ATT 7300 UNIX PC and 3B1, which have "phone"
  2638.   related ioctl's for their internal modems.  attmodem has getty status and 
  2639.   modem-in-use bit.  Reportedly the ATT7300/3B1 PIOCDISC call is necessary, 
  2640.   but also ruins the file descriptor, and no other phone(7) ioctl call can fix 
  2641.   it.  Whateverit does, it seems to escape detection with PIOCGETA and TCGETA.
  2642.   The only way to undo the damage is to close the fd and then reopen it.
  2643. */
  2644.     if (attmodem & ISMODEM) {
  2645.     debug(F100,"tthang attmodem close/open","",0);
  2646.     ioctl(ttyfd,PIOCUNHOLD,&dialer); /* Return call to handset. */
  2647.     ioctl(ttyfd,PIOCDISC,&dialer);    /* Disconnect phone. */
  2648.     close(ttyfd);            /* Close and reopen the fd. */
  2649.     ttyfd = priv_opn(ttnmsv, O_RDWR | O_NDELAY);
  2650.     attmodem &= ~ISMODEM;        /* Phone no longer in use. */
  2651.     }
  2652. #else /* !ATT7300 */
  2653. /* It seems we have to close and open the device for other AT&T systems */
  2654. /* too, and this is the place to do it.  The following code does the */
  2655. /* famous close(open(...)) magic by default.  If that doesn't work for you, */
  2656. /* then try uncommenting the following statement or putting -DCLSOPN in */
  2657. /* the makefile CFLAGS. */
  2658.  
  2659. /* #define CLSOPN */
  2660.  
  2661. #ifndef SCO32 /* Not needed by, and harmful to, SCO UNIX 3.2 / Xenix 2.3 */
  2662.  
  2663. #ifdef O_NDELAY
  2664. #define OPENFLGS O_RDWR | O_NDELAY
  2665. #else
  2666. #define OPENFLGS O_RDWR
  2667. #endif
  2668.  
  2669. #ifndef CLSOPN
  2670. /* This method is used by default, i.e. unless CLSOPN is defined. */
  2671. /* It is thought to be safer because there is no window where getty */
  2672. /* can seize control of the device.  The drawback is that it might not work. */
  2673.  
  2674.     debug(F101,"tthang close(open()), OPENFLGS","",OPENFLGS);
  2675.     close(priv_opn(ttnmsv, OPENFLGS));
  2676.  
  2677. #else
  2678. /* This method is used if you #define CLSOPN.  It is more likely to work */
  2679. /* than the previous method, but it's also more dangerous. */
  2680.  
  2681.     debug(F101,"tthang close/open, OPENFLGS","",OPENFLGS);
  2682.     close(ttyfd);
  2683.     msleep(10);
  2684.     ttyfd = priv_opn(ttnmsv, OPENFLGS);    /* Open it again */
  2685. #endif /* CLSOPN */
  2686. #undef OPENFLGS
  2687.  
  2688. #endif /* SCO32 */
  2689. #endif /* ATT7300 */
  2690.  
  2691. /* Now put all flags & modes back the way we found them. */
  2692. /* (Does the order of ioctl & fcntl matter ? ) */
  2693.  
  2694.     debug(F100,"tthang restore settings","",0);
  2695.     ttcur.c_cflag = ttc_save;        /* Get old speed back. */
  2696.     if (ioctl(ttyfd,TCSETAF,&ttcur) < 0) /* ioctl parameters. */
  2697.       return(-1); 
  2698. #ifdef O_NDELAY
  2699. /*
  2700.   This is required for IBM RT and RS/6000, probably helps elsewhere too (?).
  2701.   After closing a modem line, the modem will probably not be asserting
  2702.   carrier any more, so we should not require carrier any more.  If this
  2703.   causes trouble on non-IBM UNIXes, change the #ifdef to use _IBMR2 rather
  2704.   than O_NDELAY.
  2705. */
  2706.     flags &= ~O_NDELAY;            /* Don't require carrier on reopen */
  2707. #endif /* O_NDELAY */
  2708.     if (fcntl(ttyfd,F_SETFL,flags) < 0)    /* fcntl parameters */
  2709.       return(-1);
  2710.  
  2711.     return(1);
  2712. #endif /* not HPUX */
  2713. #endif /* ATTSV */
  2714. #endif /* BSD44ORPOSIX */
  2715. #endif /* NOLOCAL */
  2716. }
  2717.  
  2718. /*
  2719.   Major change in 5A(174).  We used to use LPASS8, if it was defined, to
  2720.   allow 8-bit data and Xon/Xoff flow control at the same time.  But this
  2721.   LPASS8 business seems to have been causing trouble for everybody but me!
  2722.   For example, Annex terminal servers, commonly used with Encore computers,
  2723.   do not support LPASS8 even though the Encore itself does.  Ditto for many
  2724.   other terminal servers, TELNET connections, rlogin connections, etc etc.
  2725.   Now, reportedly, even vanilla 4.3 BSD systems can't do this right on their
  2726.   serial lines, even though LPASS8 is a feature of 4.3BSD.  So let's turn it
  2727.   off for everybody.  That means we goes back to using raw mode, with no
  2728.   flow control.  Phooey.
  2729.  
  2730.   NOTE: This must be done before the first reference to LPASS8 in this file,
  2731.   and after the last #include statment.
  2732. */
  2733. #ifdef LPASS8
  2734. #undef LPASS8
  2735. #endif /* LPASS8 */
  2736.  
  2737. /*  T T R E S  --  Restore terminal to "normal" mode.  */
  2738.  
  2739. /* ske@pkmab.se: There are two choices for what this function should do.
  2740.  * (1) Restore the tty to current "normal" mode, with carrier treatment
  2741.  * according to ttcarr, to be used after every kermit command. (2) Restore
  2742.  * the tty to the state it was in before kermit opened it. These choices
  2743.  * conflict, since ttold can't hold both choices of tty parameters.  ttres()
  2744.  * is currently being called as in choice (1), but ttold basically holds
  2745.  * the initial parameters, as in (2), and the description at the beginning
  2746.  * of this file says (2).
  2747.  *
  2748.  * I don't think restoring tty parameters after all kermit commands makes
  2749.  * much of a difference.  Restoring them upon exit from kermit may be of
  2750.  * some use in some cases (when the line is not restored automatically on
  2751.  * close, by the operating system).
  2752.  *
  2753.  * I can't choose which one it should be, so I haven't changed it. It
  2754.  * probably works as it is, too. It would probably even work even with
  2755.  * ttres() entirely deleted...
  2756.  *
  2757.  * (from fdc: Actually, this function operates in remote mode too, so
  2758.  * it restores the console (command) terminal to whatever mode it was
  2759.  * in before packet operations began, so that commands work right again.)
  2760.  */
  2761. int
  2762. ttres() {                               /* Restore the tty to normal. */
  2763.     int x;
  2764.  
  2765.     if (ttyfd < 0) return(-1);          /* Not open. */
  2766.  
  2767.     if (ttfdflg) return(0);        /* Don't mess with terminal modes if */
  2768.                     /* we got ttyfd from another process */
  2769. #ifdef    NETCONN
  2770.     if (netconn) return (0);        /* Network connection, do nothing */
  2771. #endif    /* NETCONN */
  2772.  
  2773. /* Real terminal device, so restore its original modes */
  2774.  
  2775. #ifdef BSD44ORPOSIX            /* For POSIX like this */
  2776.     x = tcsetattr(ttyfd,TCSADRAIN,&ttold);
  2777. #else                    /* For all others... */
  2778. #ifdef ATTSV                            /* For AT&T versions... */
  2779.     x = ioctl(ttyfd,TCSETAW,&ttold);    /* Restore tty modes this way. */
  2780. #else
  2781. /* Here we restore the modes for BSD */
  2782.  
  2783. #ifdef LPASS8                /* Undo "pass8" if it were done */
  2784.     if (lmodef) {
  2785.     if (ioctl(ttyfd,TIOCLSET,&lmode) < 0)
  2786.       debug(F100,"ttres TIOCLSET failed","",0);
  2787.     else
  2788.       debug(F100,"ttres TIOCLSET ok","",0);
  2789.     }
  2790. #endif /* LPASS8 */
  2791.  
  2792. #ifdef CK_DTRCTS           /* Undo hardware flow if it were done */
  2793.     if (lmodef) {
  2794.      if (ioctl(ttyfd,TIOCLSET,&lmode) < 0)
  2795.        debug(F100,"ttres TIOCLSET failed","",0);
  2796.      else
  2797.        debug(F100,"ttres TIOCLSET ok","",0);
  2798.     }
  2799. #endif /* CK_DTRCTS */
  2800.  
  2801. #ifdef TIOCGETC                /* Put back special characters */
  2802.     if (tcharf && (xlocal == 0)) {
  2803.     if (ioctl(ttyfd,TIOCSETC,&tchold) < 0)
  2804.       debug(F100,"ttres TIOCSETC failed","",0);
  2805.     else
  2806.       debug(F100,"ttres TIOCSETC ok","",0);
  2807.     }
  2808. #endif /* TIOCGETC */
  2809.  
  2810. #ifdef TIOCGLTC                /* Put back local special characters */
  2811.     if (ltcharf && (xlocal == 0)) {
  2812.     if (ioctl(ttyfd,TIOCSLTC,<chold) < 0)
  2813.       debug(F100,"ttres TIOCSLTC failed","",0);
  2814.     else
  2815.       debug(F100,"ttres TIOCSLTC ok","",0);
  2816.     }
  2817. #endif /* TIOCGLTC */
  2818.  
  2819. #ifdef BELLV10
  2820.     x = ioctl(ttyfd,TIOCSETP,&ttold);    /* Restore both structs */
  2821.     x = ioctl(ttyfd,TIOCSDEV,&tdold);
  2822. #else
  2823.     x = stty(ttyfd,&ttold);             /* Restore tty modes the old way. */
  2824. #endif /* BELLV10 */
  2825.  
  2826.     if (!xlocal)
  2827.       msleep(100);            /* This replaces sleep(1)... */
  2828.                     /* Put back sleep(1) if tty is */
  2829.                     /* messed up after close. */
  2830. #endif /* ATTSV */
  2831. #endif /* BSD44ORPOSIX */
  2832.  
  2833.     debug(F101,"ttres tty modes restore","",x);
  2834. #ifndef QNX
  2835.     if (x < 0) debug(F101,"ttres errno","",errno);
  2836. #endif /* QNX */
  2837.  
  2838. #ifdef AIXRS
  2839. #ifndef AIX41
  2840.     x = ioctl(ttyfd, ttld & 1 ? TXADDCD : TXDELCD, "rts");
  2841.     debug(F101,"ttres AIX line discipline rts restore","",x);
  2842. #endif /* AIX41 */
  2843. #endif /* AIXRS */
  2844.  
  2845. #ifdef BSD41
  2846.     if (ttld > -1) {            /* Put back line discipline */
  2847.     x = ioctl(ttyfd, TIOCSETD, &ttld);
  2848.     debug(F101,"ttres line discipline restore","",x);
  2849.     if (x < 0) debug(F101,"...ioctl errno","",errno);
  2850.     ttld = -1;
  2851.     }
  2852. #endif /* BSD41 */
  2853.  
  2854. #ifdef sony_news
  2855.     x = xlocal ? km_ext : km_con;    /* Restore Kanji mode. */
  2856.     if (x != -1) {            /* Make sure we know original modes. */
  2857.     if (ioctl(ttyfd,TIOCKSET, &x) < 0) {
  2858.         perror("ttres can't set Kanji mode");
  2859.         debug(F101,"ttres error setting Kanji mode","",x);
  2860.         return(-1);
  2861.     }
  2862.     }
  2863.     debug(F100,"ttres set Kanji mode ok","",0);
  2864. #endif /* sony_news */
  2865.  
  2866.     tvtflg = 0;                /* Invalidate terminal mode settings */
  2867.     return(x);
  2868. }
  2869.  
  2870. #ifndef NOUUCP
  2871. #ifdef HPUX10
  2872.  
  2873. /* Aliases (different drivers) for HP-UX 10.00 dialout devices: */
  2874.  
  2875. static char *devprefix[] = { "tty", "ttyd", "cul", "cua", "" };
  2876.  
  2877. /*  T T C H K P I D  --  Check lockfile pid  */
  2878. /*
  2879.   Read pid from lockfile named f, check that it's still valid.
  2880.   If so, return 1.
  2881.   On failure to read pid, return 1.
  2882.   Otherwise, try to delete lockfile f and return 0 if successful, else 1.
  2883. */
  2884. static int
  2885. ttchkpid(f) char *f; {
  2886.     int pid, x;
  2887.     priv_on();
  2888.     pid = ttrpid(f);            /* Read pid from file. */
  2889.     priv_off();
  2890.     if (pid > -1) {            /* If we were able to read the pid.. */
  2891.     debug(F101,"ttchkpid pid","",pid);
  2892.     errno = 0;            /* See if process still exists. */
  2893.     x = kill((PID_T) pid,0);
  2894.     debug(F101,"ttchkpid kill","",x);
  2895.     debug(F101,"ttchkpid kill errno","",errno);
  2896.     if (x < 0 && errno == ESRCH) { /* pid is invalid */
  2897.         debug(F111,"removing stale lock",f,pid);
  2898.         if (!backgrd)
  2899.           printf("Removing stale lock %s (pid %d terminated)\n", f, pid);
  2900.         priv_on();
  2901.         x = unlink(f);        /* Remove the lockfile. */
  2902.         priv_off();
  2903.         debug(F111,"ttchkpid unlink",f,x);
  2904.         if (x > -1)
  2905.           return(0);        /* Device is not locked after all */
  2906.         else if (!backgrd)
  2907.           perror("Failure to remove stale lock file");
  2908.     }
  2909.     return(1);
  2910.     }
  2911. }
  2912. #endif /* HPUX10 */
  2913.  
  2914. /*  T T R P I D  --  Read pid from lockfile "name" (used by ttlock) */
  2915.  
  2916. static int
  2917. ttrpid(name) char *name; {
  2918.     int x, fd, pid;
  2919.  
  2920.     debug(F110,"ttrpid",name,0);
  2921.     if (!name) return(-1);
  2922.     if (!*name) return(-1);
  2923.     fd = open(name,O_RDONLY);        /* Try to open lockfile. */
  2924.     if (fd > 0) {
  2925.  
  2926. #ifdef PIDSTRING
  2927.     char buf[12];
  2928.     x = read(fd, buf, 11);        /* For HDBUUCP, read pid string */
  2929.     debug(F101,"ttrpid PIDSTRING read","",x);
  2930.     if (x < 0) return(-1);
  2931.     buf[11] = '\0';
  2932.     if (x == 11)
  2933.       x = sscanf(buf,"%d",&pid);    /* Get the integer pid from it. */
  2934. #else
  2935.     x = read(fd, (char *)&pid, sizeof(pid)); /* Else read integer pid */
  2936.     debug(F101,"ttrpid integer read","",x);
  2937. #endif /* PIDSTRING */
  2938.  
  2939.     if (x < 0) pid = -1;        /* Return any errors. */
  2940.     close(fd);            /* Close the lockfile. */
  2941.     } else pid = -1;
  2942.     debug(F101,"ttrpid pid","",pid);
  2943.     return(pid);
  2944. }
  2945. #endif /* NOUUCP */
  2946.  
  2947. /*  T T L O C K  */
  2948.  
  2949. /*
  2950.   This function attempts to coordinate use of the communication device with
  2951.   other copies of Kermit and any other program that follows the UUCP
  2952.   device-locking conventions, which, unfortunately, vary among different UNIX
  2953.   implementations.  The idea is to look for a file of a certain name, the
  2954.   "lockfile", in a certain directory.  If such a file is found, then the line
  2955.   is presumed to be in use, and Kermit should not use it.  If no such file is
  2956.   found, Kermit attempts to create one so that other programs will not use the
  2957.   same line at the same time.  Because the lockfile and/or the directory it's
  2958.   in might lack write permission for the person running Kermit, Kermit could
  2959.   find itself running setuid to uucp or other user that does have the
  2960.   necessary permissions.  At startup, Kermit has changed its effective uid to
  2961.   the user's real uid, and so ttlock() must switch back to the original
  2962.   effective uid in order to create the lockfile, and then back again to the
  2963.   real uid to prevent unauthorized access to other directories or files owned
  2964.   by the user the program is setuid to.
  2965.  
  2966.   Totally rewritten for C-Kermit 5A to eliminate windows of vulnerability,
  2967.   based on suggestions from Warren Tucker.  Call with pointer to name of 
  2968.   tty device.  Returns:
  2969.  
  2970.    0 on success
  2971.   -1 on failure
  2972.  
  2973.   Note: Once privileges are turned on using priv_on(), it is essential that
  2974.   they are turned off again before this function returns.
  2975. */
  2976. #ifdef SVR4                /* Lockfile uses device numbers. */
  2977. /*
  2978.   Although I can't find this in writing anywhere (e.g. in SVID for SVR4),
  2979.   it is the behavior of the "reference version" of SVR4, i.e. the Intel
  2980.   port from UNIX Systems Laboratories, then called Univel UnixWare,
  2981.   then called Novell UnixWare, now called SCO Unixware...
  2982. */
  2983. #ifndef LFDEVNO                /* Define this for SVR4 */
  2984. #ifndef AIXRS                /* But not for RS/6000 AIX 3.2, etc. */
  2985. #ifndef BSD44                /* If anybody else needs it... */
  2986. #ifndef __386BSD__
  2987. #ifndef __FreeBSD__
  2988. #ifndef HPUX10
  2989. #ifndef IRIX51                /* SGI IRIX 5.1 or later */
  2990. #ifndef CK_SCOV5            /* SCO Open Server 5.0 */
  2991. #define LFDEVNO
  2992. #endif /* CK_SCOV5 */
  2993. #endif /* IRIX51 */
  2994. #endif /* HPUX10 */
  2995. #endif /* __FreeBSD__ */
  2996. #endif /* __386BSD__ */
  2997. #endif /* BSD44 */
  2998. #endif /* AIXRS */
  2999. #endif /* LFDEVNO */            /* ... define it here or on CC */
  3000. #endif /* SVR4 */            /* command line. */
  3001.  
  3002. #ifdef COHERENT
  3003. #define LFDEVNO
  3004. #endif /* COHERENT */
  3005.  
  3006. #ifdef LFDEVNO
  3007. #include <sys/stat.h>            /* For major() & minor() macros. */
  3008.                     /* Should be in <sys/types.h>. */
  3009. #ifndef major                /* If we didn't find it */
  3010. #ifdef SVR4                /* then for Sys V R4 */
  3011. #include <sys/mkdev.h>            /* look here */
  3012. #else                    /* or for SunOS versions */
  3013. #ifdef SUNOS4                /* ... */
  3014. #include <sys/sysmacros.h>        /* look here */
  3015. #else                    /* Otherwise take a chance: */
  3016. #define    major(dev) ( (int) ( ((unsigned)(dev) >> 8) & 0xff))
  3017. #define    minor(dev) ( (int) ( (dev) & 0xff))
  3018. #endif /* SUNOS4 */
  3019. #endif /* SVR4 */
  3020. #endif /* major */
  3021. #endif /* LFDEVNO */
  3022. /*
  3023.   Note for RS/6000: routines ttylock(devicename), ttyunlock(devicename),
  3024.   and ttylocked(devicename) from the standard library (libc.a) could be 
  3025.   used here instead.  It's not clear whether there is any advantage in this.
  3026. */
  3027.  
  3028. static int
  3029. ttlock(ttdev) char *ttdev; {
  3030.     int x;
  3031.  
  3032. #ifdef NOUUCP
  3033.     strcpy(flfnam,"NOLOCK");
  3034.     haslock = 1;
  3035.     return(0);
  3036. #else /* !NOUUCP */
  3037.  
  3038. #ifndef HPUX10
  3039.  
  3040.     int lockfd;                /* File descriptor for lock file. */
  3041.     PID_T pid;                /* Process id of this process. */
  3042.     int fpid;                /* pid found in existing lockfile. */
  3043.     int tries;                /* How many times we've tried... */
  3044. #ifdef LFDEVNO
  3045.     struct stat devbuf;            /* For device numbers (SVR4). */
  3046. #endif /* LFDEVNO */
  3047.  
  3048. #ifdef PIDSTRING
  3049.     char pid_str[12];            /* My pid in string format. */
  3050. #endif /* PIDSTRING */
  3051.  
  3052.     char *device, *devname;
  3053.  
  3054. #define LFNAML 50            /* Max length for lock file name. */
  3055.     char lockfil[LFNAML];        /* Lock file name */
  3056. #ifdef RTAIX
  3057.     char lklockf[LFNAML];        /* Name for link to lock file  */
  3058. #endif /* RTAIX */
  3059.     char tmpnam[LFNAML+30];        /* Temporary lockfile name. */
  3060.     char *lockdir = LOCK_DIR;        /* Defined near top of this file, */
  3061.                     /* or on cc command line. */
  3062.  
  3063.     haslock = 0;                        /* Not locked yet. */
  3064.     *flfnam = '\0';            /* Lockfile name is empty. */
  3065.     pid = getpid();            /* Get id of this process. */
  3066.  
  3067. /*  Construct name of lockfile and temporary file */
  3068.  
  3069. /*  device  = name of tty device without the path, e.g. "ttyh8" */
  3070. /*  lockfil = name of lock file, without path, e.g. "LCK..ttyh8" */
  3071.  
  3072.     device = ((devname = xxlast(ttdev,'/')) != NULL ? devname+1 : ttdev);
  3073.  
  3074. #ifdef ISIII                /* Interactive System III, PC/IX */
  3075.     strcpy(lockfil, device);
  3076. #else
  3077. #ifdef LFDEVNO                /* Lockfilename has device numbers. */
  3078.     if (stat(ttdev,&devbuf) < 0)
  3079.       return(-1);
  3080. #ifdef COHERENT
  3081.     sprintf(lockfil,"LCK..%d.%d",
  3082.         major(devbuf.st_rdev),       /* major device number */
  3083.         0x1f & minor(devbuf.st_rdev)); /* minor device number */
  3084. #else
  3085.     sprintf(lockfil,"LK.%03d.%03d.%03d",
  3086.         major(devbuf.st_dev),    /* inode */
  3087.         major(devbuf.st_rdev),    /* major device number */
  3088.         minor(devbuf.st_rdev));    /* minor device number */
  3089. #endif /* COHERENT */
  3090. #else                    /* Others... */
  3091. #ifdef PTX                /* Dynix PTX */
  3092.     if (device != &ttdev[5] && strncmp(ttdev,"/dev/",5)==0) {
  3093.     sprintf(lockfil,"LCK..%.3s%s", &ttdev[5], device);
  3094.     } else
  3095. #endif /* PTX */
  3096.     sprintf(lockfil,"LCK..%s", device);
  3097. #ifdef RTAIX
  3098.     strcpy(lklockf,device);
  3099. #endif /* RTAIX */
  3100. #endif /* LFDEVNO */
  3101. #endif /* ISIII */
  3102.  
  3103. #ifdef CK_SCOV5                /* SCO Open Server 5.0 */
  3104.     {
  3105.     /* Lowercase the entire filename. */
  3106.         /* SCO says we must do this in V5.0 and later. */
  3107.     /* BUT... watch out for devices -- like Digiboard Portserver */
  3108.     /* That can have hundreds of ports... */
  3109.     char *p = (char *)(lockfil + 5);
  3110.     while (*p) { if (isupper(*p)) *p = (char) tolower(*p); p++; }
  3111.     }
  3112. #else
  3113. #ifdef M_XENIX                /* SCO Xenix */
  3114.     {
  3115.     int x; char c;
  3116.     x = (int)strlen(lockfil) - 1;    /* Get last letter of device name. */
  3117.     if (x > 0) {            /* If it's uppercase, lower it. */
  3118.         c = lockfil[x];
  3119.         if (c >= 'A' && c <= 'Z') lockfil[x] += ('a' - 'A');
  3120.     }
  3121.     }
  3122. #endif /* M_XENIX */
  3123. #endif /* CK_SCOV5 */
  3124.  
  3125. /*  flfnam = full lockfile pathname, e.g. "/usr/spool/uucp/LCK..ttyh8" */
  3126. /*  tmpnam = temporary unique, e.g. "/usr/spool/uucp/LTMP..pid" */
  3127.  
  3128.     sprintf(flfnam,"%s/%s",lockdir,lockfil);
  3129. #ifdef RTAIX
  3130.     sprintf(lkflfn,"%s/%s",lockdir,lklockf);
  3131. #endif /* RTAIX */
  3132.     sprintf(tmpnam,"%s/LTMP.%05d",lockdir,(int) pid);
  3133.     debug(F110,"ttlock flfnam",flfnam,0);
  3134.     debug(F110,"ttlock tmpnam",tmpnam,0);
  3135.  
  3136.     priv_on();                /* Turn on privileges if possible. */
  3137.     lockfd = creat(tmpnam, 0444);    /* Try to create temp lock file. */
  3138.     if (lockfd < 0) {            /* Create failed. */
  3139.     debug(F111,"ttlock creat failed",tmpnam,errno);
  3140.     if (errno == ENOENT) {
  3141.         perror(lockdir);        
  3142.         printf("UUCP not installed or Kermit misconfigured\n");
  3143.     } else {
  3144.         perror(lockdir);
  3145.         unlink(tmpnam);        /* Get rid of the temporary file. */
  3146.     }
  3147.     priv_off();            /* Turn off privileges!!! */
  3148.     return(-1);            /* Return failure code. */
  3149.     }
  3150. /* Now write the pid into the temp lockfile in the appropriate format */
  3151.  
  3152. #ifdef PIDSTRING            /* For Honey DanBer UUCP, */
  3153.     sprintf(                /* write PID as decimal string */
  3154.         pid_str,
  3155. #ifdef LINUXFSSTND            /* The "Linux File System Standard" */
  3156. #ifdef FSSTND10                /* Version 1.0 calls for */
  3157.         "%010d\n",            /* leading zeros */
  3158. #else                    /* while version 1.2 calls for */
  3159.         "%10d\n",            /* leading spaces */
  3160. #endif /* FSSTND10 */
  3161. #else
  3162. #ifdef COHERENT
  3163.         "%d\n",            /* with leading nothing */
  3164. #else
  3165.         "%10d\n",            /* with leading blanks */
  3166. #endif /* COHERENT */
  3167. #endif /* LINUXFSSTND */
  3168.         (int) pid
  3169.         );
  3170.     write(lockfd, pid_str, 11);
  3171.     debug(F111,"ttlock hdb pid string",pid_str,(int) pid);
  3172.  
  3173. #else /* Not PIDSTRING, use integer PID */
  3174.  
  3175.     write(lockfd, (char *)&pid, sizeof(pid) );
  3176.     debug(F101,"ttlock pid","",(int) pid);
  3177.  
  3178. #endif /* PIDSTRING */
  3179.  
  3180. /* Now try to rename the temp file to the real lock file name. */
  3181. /* This will fail if a lock file of that name already exists.  */
  3182.  
  3183.     close(lockfd);            /* Close the temp lockfile. */
  3184.     chmod(tmpnam,0444);            /* Permission for a valid lock. */    
  3185.     tries = 0;
  3186.     while (!haslock && tries++ < 2) {
  3187.     haslock = (link(tmpnam,flfnam) == 0); /* Create a link to it. */
  3188.     if (haslock) {                  /* If we got the lockfile */
  3189. #ifdef RTAIX
  3190.         link(flfnam,lkflfn);
  3191. #endif /* RTAIX */ 
  3192.  
  3193. #ifdef LOCKF
  3194. #ifdef F_TLOCK
  3195. /*
  3196.   Advisory file locking works on SVR4, so we use it.  In fact, it is
  3197.   necessary in some cases, e.g. when SLIP is involved.  But it still doesn't
  3198.   seem prevent multiple users accessing the same device by different names.
  3199. */
  3200.             while ( lockf(ttyfd, F_TLOCK, 0L) != 0 ) {
  3201.                 debug(F111, "ttlock: lockf returns errno", "", errno);
  3202.                 if ( (++tries >= 3) || (errno != EAGAIN) ) {
  3203.                     x = unlink(flfnam); /* remove the lockfile */
  3204.                     debug(F111,"ttlock unlink",flfnam,x);
  3205.                     haslock = 0;
  3206.             break;
  3207.         }
  3208.                 sleep(2);
  3209.         }
  3210.         if (haslock)        /* If we got an advisory lock */
  3211. #endif /* F_TLOCK */
  3212. #endif /* LOCKF */
  3213.           break;            /* We're done. */
  3214.  
  3215.     } else {            /* We didn't create a new lockfile. */
  3216.         if ((fpid = ttrpid(flfnam)) > -1) {    /* Read pid from old one. */
  3217.         if (fpid > 0) {
  3218.             debug(F101,"ttlock fpid","",fpid);
  3219.             errno = 0;        /* See if process still exists. */
  3220.             x = kill((PID_T) fpid,0);
  3221.             debug(F101,"ttlock kill","",x);
  3222.             debug(F101,"ttlock kill errno","",errno);
  3223.             if (x < 0 && errno == ESRCH) { /* pid is invalid */
  3224.             debug(F111,"ttlock removing stale lock",flfnam,
  3225.                   fpid);
  3226.             if (!backgrd)
  3227.               printf(
  3228.                 "Removing stale lock %s (pid %d terminated)\n",
  3229.                  flfnam,fpid);
  3230.             x = unlink(flfnam); /* remove the lockfile. */
  3231.             debug(F111,"ttlock unlink",flfnam,x);
  3232.             continue;    /* and go back and try again. */
  3233.             } else if ((x < 0 && errno == EPERM) || x == 0) {
  3234.             unlink(tmpnam);    /* Delete the tempfile */
  3235.             debug(F101,"ttlock found tty locked","",fpid);
  3236.             priv_off();    /* Turn off privs */
  3237.             return(-2);    /* Code for device is in use. */
  3238.             }
  3239.         } else {
  3240.             debug(F101,"ttlock can't get fpid","",fpid);
  3241.             break;
  3242.         }
  3243.         } else break;        /* Couldn't read pid from old file */
  3244.     }
  3245.     }
  3246.     unlink(tmpnam);            /* Unlink (remove) the temp file. */
  3247.     priv_off();                /* Turn off privs */
  3248.     return(haslock ? 0 : -1);        /* Return link's return code. */
  3249.  
  3250. #else /* HPUX10 */
  3251.  
  3252. /*
  3253.   HP-UX 10.00 gets its own copy of this routine.  The behavior of this routine
  3254.   is modeled after the observed behavior of the HP-UX 10.00 IC2 'cu' program.
  3255.   Dialout device names consist of a prefix, an instance (interface) number,
  3256.   the letter "p", and a port number, e.g.  tty0p0, cul1p0, cua0p1, etc.  Each
  3257.   physical device can have (at least) four names (drivers): "tty" (direct
  3258.   out), "cul" (dialout), "cua" (automatic dialout), and "ttyd" (dialin).  Each
  3259.   of these is followed by the <instance>p<port>, e.g. "0p0", which is referred
  3260.   to below as the "unit".  This routine checks for all four aliases of a given
  3261.   unit.  If it decides the device is free, then if it is a "cua" or "cul"
  3262.   device, it creates a second lockfile with the "ttyd" prefix.  This is
  3263.   exactly what cu does.  If the "set line" device does not happen to have a
  3264.   unit number, then it is used literally and no synomyms are searched for and
  3265.   only one lockfile is created.
  3266. */
  3267. #define LFNAML 80            /* Max length for lock file name. */
  3268.  
  3269.     int lockfd;                /* File descriptor for lock file. */
  3270.     PID_T pid;                /* Process ID of this process. */
  3271.     int fpid;                /* pid found in existing lockfile. */
  3272.     int tries;                /* How many times we've tried... */
  3273.     int i, k;                /* Workers */
  3274.  
  3275.     char *device, *devname;        /* "/dev/xxx", "xxx" */
  3276.     char *unit, *p;            /* <instance>p<port> part of xxx */
  3277.  
  3278.     char lockfil[LFNAML];        /* Lockfile name (no path) */
  3279.     char tmpnam[LFNAML];        /* Temporary lockfile name. */
  3280.     char *lockdir = "/var/spool/locks";    /* Lockfile directory */
  3281.  
  3282.     haslock = 0;                        /* Not locked yet. */
  3283.     *flfnam = '\0';            /* Lockfile name is empty. */
  3284.     lock2[0] = '\0';            /* Second one too. */
  3285.     pid = getpid();            /* Get my process ID */
  3286. /*
  3287.   Construct name of lockfile and temporary file...
  3288.   device  = name of tty device without the path, e.g. "tty0p0"
  3289.   lockfil = name of lock file, without path, e.g. "LCK..tty0p0"
  3290. */
  3291.     device = ((devname = xxlast(ttdev,'/')) != NULL ? devname+1 : ttdev);
  3292.     debug(F110,"TTLOCK device",device,0);
  3293.     sprintf(lockfil,"LCK..%s", device);
  3294.  
  3295.     k = 0;                /* Assume device is not locked */
  3296.     unit = device;            /* Unit = <instance>p<port> */
  3297.     while (*unit && !isdigit(*unit))    /* Search for digit... */
  3298.       unit++;
  3299.     p = unit;                /* Verify <num>p<num> format... */
  3300.     debug(F110,"TTLOCK unit 1",unit,0);
  3301.     while (*p && isdigit(*p++)) ;    /* This does not assume */
  3302.     if (*p++ == 'p')            /* any particular number of */
  3303.       while (*p && isdigit(*p++)) ;    /* digits before & after "p". */
  3304.     if (*p) unit = "";
  3305.     debug(F110,"TTLOCK unit 2",unit,0);
  3306.  
  3307.     if (*unit) {            /* Device name has unit number. */
  3308.     /* The following loop not only searches for the various lockfile    */
  3309.     /* synonyms, but also removes all -- not just one -- stale lockfile */
  3310.     /* for the device, should there be more than one.  See ttchkpid().  */
  3311.     for (i = 0; *devprefix[i]; i++) { /* For each driver... */
  3312.         /* Make lockfile name */
  3313.         sprintf(lock2,"%s/LCK..%s%s",lockdir,devprefix[i],unit);
  3314.         priv_on();            /* Privs on */
  3315.         k = zchki(lock2) != -1;    /* See if lockfile exists */
  3316.         priv_off();            /* Privs off */
  3317.         debug(F111,"TTLOCK check for lock A",lock2,k);
  3318.         if (k) if (ttchkpid(lock2)) { /* If pid still active, fail. */
  3319.         strcpy(flfnam,lock2);
  3320.         return(-2);
  3321.         }
  3322.     }
  3323.     } else {                /* Some other device-name format */
  3324.     /* This takes care of symbolic links, etc... */
  3325.     /* But does not chase them down! */
  3326.     sprintf(lock2,"%s/LCK..%s",lockdir,device); /* Use the name as-is */
  3327.     priv_on();
  3328.     k = zchki(lock2) != -1;        /* Check for existing lockfile */
  3329.     priv_off();
  3330.     debug(F111,"TTLOCK check for lock B",lock2,k);
  3331.     if (k) if (ttchkpid(lock2)) {    /* Check pid from lockfile */
  3332.         strcpy(flfnam,lock2);
  3333.         return(-2);
  3334.     }
  3335.     }
  3336. /*
  3337.   Get here only if there is no (more) lockfile, so now we make one (or two)...
  3338.   flfnam = full lockfile pathname, e.g. "/usr/spool/uucp/LCK..cul0p0".
  3339.   tmpnam = unique temporary filname, e.g. "/usr/spool/uucp/LTMP..pid".
  3340. */
  3341.     sprintf(flfnam,"%s/%s",lockdir,lockfil); /* Our SET LINE device */
  3342.  
  3343.     /* If dialout device, also make one for corresponding dialin device */
  3344.     lock2[0] = '\0';
  3345.     if (!strncmp(device,"cu",2) && *unit) 
  3346.       sprintf(lock2, "%s/LCK..ttyd%s", lockdir, unit);
  3347.  
  3348.     sprintf(tmpnam,"%s/LTMP.%05d",lockdir,(int) pid); /* Make temporary name */
  3349. #ifdef DEBUG
  3350.     if (deblog) {
  3351.     debug(F110,"TTLOCK flfnam",flfnam,0);
  3352.     debug(F110,"TTLOCK lock2",lock2,0);    
  3353.     debug(F110,"TTLOCK tmpnam",tmpnam,0);
  3354.     }
  3355. #endif /* DEBUG */
  3356. /*
  3357.    Lockfile permissions...
  3358.    444 is standard, HP-UX 10.00 uses 664.  It doesn't matter.
  3359.    Kermit uses 444; the difference lets us tell whether Kermit created
  3360.    the lock file.
  3361. */
  3362.     priv_on();                /* Turn on privileges. */
  3363.     lockfd = creat(tmpnam, 0444);    /* Try to create temporary file. */
  3364.     if (lockfd < 0) {            /* Create failed. */
  3365.     debug(F111,"ttlock creat failed",tmpnam,errno);
  3366.     if (errno == ENOENT) {
  3367.         perror(lockdir);        
  3368.         printf("UUCP not installed or Kermit misconfigured\n");
  3369.     } else {
  3370.         perror(lockdir);
  3371.         unlink(tmpnam);        /* Get rid of the temporary file. */
  3372.     }
  3373.     priv_off();            /* Turn off privileges!!! */
  3374.     return(-1);            /* Return failure code. */
  3375.     }
  3376.     debug(F110,"TTLOCK temp ok",tmpnam,0);
  3377.  
  3378. /* Now write our pid into the temp lockfile in integer format. */
  3379.  
  3380.     i = write(lockfd, (char *)&pid, sizeof(pid));
  3381.  
  3382. #ifdef DEBUG
  3383.     if (deblog) {
  3384.     debug(F101,"TTLOCK pid","",pid);
  3385.     debug(F101,"TTLOCK sizeof pid","",sizeof(pid));
  3386.     debug(F101,"TTLOCK write pid returns","",i);
  3387.     }
  3388. #endif /* DEBUG */
  3389.  
  3390. /*
  3391.   Now try to rename the temporary file to the real lockfile name.
  3392.   This will fail if a lock file of that name already exists, which
  3393.   will catch race conditions with other users.
  3394. */
  3395.     close(lockfd);            /* Close the temp lockfile. */
  3396.     chmod(tmpnam,0444);
  3397.  
  3398.     tries = 0;
  3399.     while (!haslock && tries++ < 2) {
  3400.     haslock = (link(tmpnam,flfnam) == 0); /* Create a link to it. */
  3401.     debug(F101,"TTLOCK link","",haslock);
  3402.     if (haslock) {            /* If we made the lockfile... */
  3403.   
  3404. #ifndef NOLOCKF                /* Can be canceled with -DNOLOCKF */
  3405. /*
  3406.   Create an advisory lock on the device through its file descriptor.
  3407.   This code actually seems to work.  If it is executed, and then another
  3408.   process tries to open the same device under a different name to circumvent
  3409.   the lockfile, they get a "device busy" error.
  3410. */
  3411.         debug(F100,"TTLOCK LOCKF code...","",0);
  3412.             while ( lockf(ttyfd, F_TLOCK, 0L) != 0 ) {
  3413.                 debug(F111, "TTLOCK lockf error", "", errno);
  3414.                 if ( (++tries >= 3) || (errno != EAGAIN) ) {
  3415.                     x = unlink(flfnam); /* Remove the lockfile */
  3416.             if (errno == EACCES)
  3417.               printf("Device already locked by another process\n");
  3418.                     haslock = 0;
  3419.             break;
  3420.         }
  3421.                 sleep(2);
  3422.         }
  3423. #endif /* NOLOCKF */
  3424.  
  3425.         if (haslock) {        /* If we made the lockfile ... */
  3426.         if (lock2[0]) {        /* if there is to be a 2nd lockfile */
  3427.             lockfd = creat(lock2, 0444); /* Create it */
  3428.             debug(F111,"TTLOCK lock2 creat", lock2, lockfd);
  3429.             if (lockfd > -1) {    /* Created OK, write pid. */
  3430.             write(lockfd, (char *)&pid, sizeof(pid) );
  3431.             close(lockfd);    /* Close and */
  3432.             chmod(lock2, 0444); /* set permissions. */
  3433.             } else {         /* Not OK, but don't fail. */
  3434.             lock2[0] = '\0'; /* Just remember it's not there. */
  3435.             }
  3436.         }
  3437.         break;            /* and we're done. */
  3438.         }
  3439.     }
  3440.     }
  3441.     unlink(tmpnam);            /* Unlink (remove) the temp file. */
  3442.     priv_off();                /* Turn off privs */
  3443.     i = haslock ? 0 : -1;        /* Our return value */
  3444.     debug(F101,"TTLOCK returns","",i);
  3445.     return(i);
  3446. #endif /* HPUX10 */
  3447. #endif /* !NOUUCP */
  3448. }
  3449.  
  3450. /*  T T U N L O C K  */
  3451.  
  3452. static int
  3453. ttunlck() {                             /* Remove UUCP lockfile(s). */
  3454. #ifndef NOUUCP
  3455.  
  3456.     if (haslock && *flfnam) {
  3457.     priv_on();            /* Turn privileges on.  */
  3458.     if (unlink(flfnam) < 0)        /* Remove the lockfile. */
  3459.       printf("Warning - Can't remove lockfile: %s\n", flfnam);
  3460.     *flfnam = '\0';            /* Erase the name. */
  3461.  
  3462. #ifdef RTAIX
  3463.     if (unlink(lkflfn) < 0)        /* Remove link to lockfile */
  3464.       printf("Warning - Can't remove secondary lockfile: %s\n", lkflfn);
  3465.     *lkflfn = '\0';
  3466. #else
  3467. #ifdef HPUX10
  3468.     if (lock2[0]) {            /* If there is a second lockfile, */
  3469.         if (unlink(lock2) < 0)    /*  remove it too. */
  3470.           printf("Warning - Can't remove secondary lockfile: %s\n",lock2);
  3471.         lock2[0] = '\0';        /* Forget its name. */
  3472.     }
  3473. #endif /* HPUX10 */
  3474. #endif /* RTAIX */
  3475.  
  3476. #ifdef LOCKF
  3477. #ifdef F_ULOCK
  3478.         (VOID) lockf(ttyfd, F_ULOCK, 0L); /* Remove advisory lock */
  3479. #endif /* F_ULOCK */
  3480. #endif /* LOCKF */
  3481.     priv_off();            /* Turn privileges off. */
  3482.     }
  3483. #endif /* !NOUUCP */
  3484.     return(0);
  3485. }
  3486.  
  3487. /*
  3488.   4.3BSD-style UUCP line direction control.
  3489.   (Stan Barber, Rice U, 1980-something...)
  3490. */
  3491. #ifndef NOUUCP
  3492. #ifdef ACUCNTRL
  3493. VOID
  3494. acucntrl(flag,ttname) char *flag, *ttname; {
  3495.     char x[DEVNAMLEN+32], *device, *devname;
  3496.  
  3497.     if (strcmp(ttname,CTTNAM) == 0 || xlocal == 0) /* If not local, */
  3498.       return;                /* just return. */
  3499.     device = ((devname = xxlast(ttname,'/')) != NULL ? devname+1 : ttname);
  3500.     if (strncmp(device,"LCK..",4) == 0) device += 5;
  3501.     sprintf(x,"/usr/lib/uucp/acucntrl %s %s",flag,device);
  3502.     debug(F110,"called ",x,0);
  3503.     zsyscmd(x);
  3504. }
  3505. #endif /* ACUCNTRL */
  3506. #endif /* NOUUCP */
  3507.  
  3508. /*
  3509.   T T H F L O W  --  Set or Reset hardware flow control.
  3510.  
  3511.   This is an attempt to collect all hardware-flow-control related code
  3512.   into a single module.  Thanks to Rick Sladkey and John Kohl for lots of
  3513.   help here.  Overview:
  3514.  
  3515.   Hardware flow control is not supported in many UNIX implementions.  Even
  3516.   when it is supported, there is no (ha ha) "standard" for the programming
  3517.   interface.  In general, 4.3BSD and earlier (sometimes), 4.4BSD, System V,
  3518.   SunOS, AIX, etc, have totally different methods.  (And, not strictly
  3519.   relevant here, the programming interface often brings one only to a no-op
  3520.   in the device driver!)
  3521.  
  3522.   Among all these, we have two major types of APIs: those in which hardware
  3523.   flow control is determined by bits in the same termio/termios/sgtty mode
  3524.   word(s) that are used for controlling such items as CBREAK vs RAW mode, and
  3525.   which are also used by the ttvt(), ttpkt(), conbin(), and concb() routines
  3526.   for changing terminal modes.  And those that use entirely different
  3527.   mechanisms.
  3528.  
  3529.   In the first category, it is important that any change in the mode bits be
  3530.   reflected in the relevant termio(s)/sgtty structure, so that subsequent
  3531.   changes to that structure do not wipe out the effects of this routine.  That
  3532.   is why a pointer, attrs, to the appropriate structure is passed as a
  3533.   parameter to this routine.
  3534.  
  3535.   The second category should give us no worries, since any changes to hardware
  3536.   flow control accomplished by this routine should not affect the termio(s)/
  3537.   sgtty structures, and therefore will not be undone by later changes to them.
  3538.  
  3539.   The second argument, status, means to turn on hardware flow control if
  3540.   nonzero, and to turn it off if zero.
  3541.  
  3542.   Returns: 0 on success, -1 on failure.
  3543. */
  3544. static int
  3545. tthflow(flow, status, attrs)
  3546.     int flow,                /* Type of flow control (ckcdeb.h) */
  3547.     status;                /* Nonzero = turn it on */
  3548.                     /* Zero = turn it off */
  3549. #ifdef BSD44ORPOSIX            /* POSIX or BSD44 */
  3550.     struct termios *attrs;
  3551. #else                    /* System V */
  3552. #ifdef ATTSV
  3553.     struct termio *attrs;
  3554. #else                    /* BSD, V7, etc */
  3555.     struct sgttyb *attrs;        /* sgtty info... */
  3556. #endif /* ATTSV */
  3557. #endif /* BSD44ORPOSIX */
  3558. /* tthflow */ {
  3559.  
  3560. #ifdef Plan9
  3561.     return p9tthflow(flow, status);
  3562. #else
  3563.  
  3564.     int x = 0;                /* tthflow() return code */
  3565.  
  3566. #ifndef OXOS                /* NOT Olivetti X/OS... */
  3567. /*
  3568.   For SunOS 4.0 and later in the BSD environment ...
  3569.  
  3570.   The declarations are copied and interpreted from the System V header files,
  3571.   so we don't actually have to pull in all the System V junk when building
  3572.   C-Kermit for SunOS in the BSD environment, which would be dangerous because
  3573.   having those symbols defined would cause us to take the wrong paths through
  3574.   the code.  The code in this section is used in both the BSD and Sys V SunOS
  3575.   versions.
  3576. */
  3577. #ifdef SUNOS41
  3578. /*
  3579.   In SunOS 4.1 and later, we use the POSIX calls rather than ioctl calls
  3580.   because GNU CC uses different formats for the _IOxxx macros than regular CC;
  3581.   the POSIX forms work for both.  But the POSIX calls are not available in
  3582.   SunOS 4.0.
  3583. */
  3584. #define CRTSCTS 0x80000000        /* RTS/CTS flow control */
  3585. #define TCSANOW 0            /* Do it now */
  3586.  
  3587.     struct termios {
  3588.     unsigned long c_iflag;        /* Input modes */
  3589.     unsigned long c_oflag;        /* Output modes */
  3590.     unsigned long c_cflag;        /* Control modes */
  3591.     unsigned long c_lflag;        /* Line discipline modes */
  3592.     char c_line;
  3593.     CHAR c_cc[17];
  3594.     };
  3595.     struct termios temp;
  3596.  
  3597. _PROTOTYP( int tcgetattr, (int, struct termios *) );
  3598. _PROTOTYP( int tcsetattr, (int, int, struct termios *) );
  3599. /*
  3600.   When CRTSCTS is set, SunOS won't do output unless both CTS and CD are
  3601.   asserted.  So we don't set CRTSCTS unless CD is up.  This should be OK,
  3602.   since we don't need RTS/CTS during dialing, and after dialing is complete,
  3603.   we should have CD.  If not, we still communicate, but without RTS/CTS.
  3604. */
  3605.     int mflags;                /* Modem signal flags */
  3606.     if (!status) {            /* Turn hard flow off */
  3607.     if (tcgetattr(ttyfd, &temp) > -1 && /* Get device attributes */
  3608.         (temp.c_cflag & CRTSCTS)) { /* Check for RTS/CTS */
  3609.         temp.c_cflag &= ~CRTSCTS;    /* It's there, remove it */
  3610.         x = tcsetattr(ttyfd,TCSANOW,&temp);
  3611.     }
  3612.     } else {                /* Turn hard flow on */
  3613.     if (ioctl(ttyfd,TIOCMGET,&mflags) > -1 && /* Get modem signals */
  3614.         (mflags & TIOCM_CAR)) {        /* Check for CD */
  3615.         debug(F100,"tthflow SunOS has CD","",0);
  3616.         if (tcgetattr(ttyfd, &temp) > -1 && /* Get device attributes */
  3617.         !(temp.c_cflag & CRTSCTS)) { /* Check for RTS/CTS */
  3618.         temp.c_cflag |= CRTSCTS;    /* Not there, add it */
  3619.         x = tcsetattr(ttyfd,TCSANOW,&temp);
  3620.         }
  3621.     } else {
  3622.         x = -1;
  3623.         debug(F100,"tthflow SunOS no CD","",0);
  3624.     }
  3625.     }
  3626. #else
  3627. #ifdef QNX
  3628.     struct termios temp;
  3629.     if (tcgetattr(ttyfd, &temp) > -1) {    /* Get device attributes */
  3630.     if (!status) {            /* Turn hard flow off */
  3631.         if ((temp.c_cflag & (IHFLOW|OHFLOW)) == (IHFLOW|OHFLOW)) {
  3632.         temp.c_cflag &= ~(IHFLOW|OHFLOW); /* It's there, remove it */
  3633.         attrs->c_cflag &= ~(IHFLOW|OHFLOW);
  3634.         x = tcsetattr(ttyfd,TCSANOW,&temp);
  3635.         }
  3636.     } else {            /* Turn hard flow on */
  3637.         if ((temp.c_cflag & (IHFLOW|OHFLOW)) != (IHFLOW|OHFLOW)) {
  3638.         temp.c_cflag |= (IHFLOW|OHFLOW); /* Not there, add it */
  3639.         temp.c_iflag &= ~(IXON|IXOFF);   /* Bye to IXON/IXOFF */
  3640.         ttraw.c_lflag |= IEXTEN;         /* Must be on */
  3641.         x = tcsetattr(ttyfd,TCSANOW,&temp);
  3642.         attrs->c_cflag |= (IHFLOW|OHFLOW);
  3643.         attrs->c_iflag &= ~(IXON|IXOFF);
  3644.         }
  3645.     }
  3646.     } else {
  3647.     x = -1;
  3648.     debug(F100, "tthflow QNX getattr fails", "", 0);
  3649.     }
  3650. #else
  3651. #ifdef POSIX_CRTSCTS
  3652. /*
  3653.   POSIX_CRTSCTS is defined in ckcdeb.h or on CC command line.
  3654.   Note: Do not assume CRTSCTS is a one-bit field!
  3655. */
  3656.     struct termios temp;
  3657.     if (tcgetattr(ttyfd, &temp) > -1) {    /* Get device attributes */
  3658.     if (!status) {            /* Turn hard flow off */
  3659.         if ((temp.c_cflag & CRTSCTS) == CRTSCTS) { /* Check for RTS/CTS */
  3660.         temp.c_cflag &= ~CRTSCTS;    /* It's there, remove it */
  3661.         attrs->c_cflag &= ~CRTSCTS;
  3662.         x = tcsetattr(ttyfd,TCSANOW,&temp);
  3663.         }
  3664.     } else {            /* Turn hard flow on */
  3665.         if ((temp.c_cflag & CRTSCTS) != CRTSCTS) {
  3666.         temp.c_cflag |= CRTSCTS; /* Not there, add it */
  3667.         temp.c_iflag &= ~(IXON|IXOFF|IXANY); /* Bye to IXON/IXOFF */
  3668.         x = tcsetattr(ttyfd,TCSANOW,&temp);
  3669.         attrs->c_cflag |= CRTSCTS;
  3670.         attrs->c_iflag &= ~(IXON|IXOFF|IXANY);
  3671.         }
  3672.     }
  3673.     } else {
  3674.     x = -1;
  3675.     debug(F100, "tthflow POSIX_CRTSCTS no attr", "", 0);
  3676.     }
  3677. #else
  3678. #ifdef SUNOS4
  3679. /*
  3680.   SunOS 4.0 (and maybe earlier?).  This code is dangerous because it
  3681.   prevents compilation with GNU gcc, which uses different formats for the
  3682.   _IORxxx macros than regular cc.  SunOS 4.1 and later can use the POSIX
  3683.   routines above, which work for both cc and gcc.
  3684. */
  3685. #define TCGETS _IOR(T, 8, struct termios) /* Get modes into termios struct */
  3686. #define TCSETS _IOW(T, 9, struct termios) /* Set modes from termios struct */
  3687. #define CRTSCTS 0x80000000          /* RTS/CTS flow control */
  3688.  
  3689.     struct termios {
  3690.         unsigned long c_iflag;        /* Input modes */
  3691.         unsigned long c_oflag;        /* Output modes */
  3692.         unsigned long c_cflag;        /* Control modes */
  3693.         unsigned long c_lflag;        /* Line discipline modes */
  3694.         char c_line;
  3695.         CHAR c_cc[17];
  3696.     };
  3697.     struct termios temp;
  3698.     if (ioctl(ttyfd,TCGETS,&temp) > -1) {    /* Get terminal modes. */
  3699.         if (status) {            /* Turn hard flow on */
  3700.         temp.c_cflag |= CRTSCTS;    /* Add RTS/CTS to them. */
  3701.         x = ioctl(ttyfd,TCSETS,&temp);    /* Set them again. */
  3702.         attrs->c_cflag |= CRTSCTS;    /* Add to global info. */
  3703.         } else {                /* Turn hard flow off */
  3704.         temp.c_cflag &= ~CRTSCTS;
  3705.         x = ioctl(ttyfd,TCSETS,&temp);
  3706.         attrs->c_cflag &= ~CRTSCTS;
  3707.         }
  3708.     }
  3709. #else                    /* Not SunOS 4.0 or later */
  3710. #ifdef AIXRS                /* IBM AIX RS/6000 */
  3711. #ifndef AIX41                /* But only pre-4.x == SVR4 */
  3712.     if (status) {
  3713.     if ((x = ioctl(ttyfd, TXADDCD, "rts")) < 0 && errno != EBUSY)
  3714.       debug(F100,"hardflow TXADDCD (rts) error", "", 0);
  3715.     } else {
  3716.     if ((x = ioctl(ttyfd, TXDELCD, "rts")) < 0 && errno != EINVAL)
  3717.       debug(F100,"hardflow TXDELCD (rts) error", "", 0);
  3718.     }
  3719. #endif /* AIX41 */
  3720. #else                    /* Not AIX RS/6000 */
  3721.  
  3722. #ifdef ATTSV                /* System V... */
  3723.  
  3724. #ifdef CK_SCOV5                /* SCO Open Server 5.0 */
  3725. #define CK_SCOUNIX
  3726. #else
  3727. #ifdef M_UNIX                /* SCO UNIX 3.2v4.x or earlier */
  3728. #define CK_SCOUNIX
  3729. #endif /* M_UNIX */
  3730. #endif /* CK_SCOV5 */
  3731.  
  3732. #ifdef CK_SCOUNIX
  3733. #ifdef POSIX                /* SCO - POSIX untested !!! */
  3734.     struct termios temp;
  3735.     if ((x = tcgetattr(ttyfd, &temp)) == -1)
  3736. #else  /* POSIX */
  3737.     struct termio temp;
  3738.     if ((x = ioctl(ttyfd, TCGETA, &temp)) == -1)
  3739. #endif /* POSIX */
  3740.     {
  3741.     debug(F100,"SCO hardflow get modes error", "", 0);
  3742.     } else {
  3743.     if (status) {            /* Turn it ON */
  3744.         temp.c_cflag |= RTSFLOW|CTSFLOW;
  3745.         attrs->c_cflag |= RTSFLOW|CTSFLOW;
  3746. #ifdef ORTSFL
  3747.         temp.c_cflag &= ~ORTSFL;
  3748.         attrs->c_cflag &= ~ORTSFL;
  3749. #endif /* ORTSFL */
  3750.         temp.c_iflag &= ~(IXON|IXOFF|IXANY);
  3751.         attrs->c_iflag &= ~(IXON|IXOFF|IXANY);
  3752.     } else {            /* Turn it OFF */
  3753. #ifdef ORTSFL
  3754.         temp.c_cflag &= ~(RTSFLOW|CTSFLOW|ORTSFL);
  3755.         attrs->c_cflag &= ~(RTSFLOW|CTSFLOW|ORTSFL);
  3756. #else  /* ORTSFL */
  3757.         temp.c_cflag &= ~(RTSFLOW|CTSFLOW);
  3758.         attrs->c_cflag &= ~(RTSFLOW|CTSFLOW);
  3759. #endif /* ORTSFL */
  3760.     }
  3761.     if ((x =
  3762. #ifdef POSIX
  3763.     tcsetattr(ttyfd, &temp)
  3764. #else
  3765.     ioctl(ttyfd, TCSETA, &temp)
  3766. #endif /* POSIX */
  3767.     )  == -1 )
  3768.       debug(F100,"SCO hardflow set modes error", "", 0);
  3769.     }
  3770. #else /* Not SCO UNIX */
  3771.     if (!status) {            /* Turn it OFF */
  3772. #ifdef RTSXOFF
  3773.     debug(F100,"tthflow ATTSV RTS/CTS OFF","",0);
  3774.     rctsx.x_hflag &= ~(RTSXOFF|CTSXON);
  3775.     x = ioctl(ttyfd,TCSETX,&rctsx);
  3776.     debug(F101,"tthflow ATTSV RTSXOFF OFF","",x);
  3777. #endif /* RTSXOFF */
  3778. #ifdef DTRXOFF
  3779.     debug(F100,"tthflow ATTSV DTR/CD OFF","",0);
  3780.     rctsx.x_hflag &= ~(DTRXOFF|CDXON);
  3781.     x = ioctl(ttyfd,TCSETX,&rctsx);
  3782.     debug(F101,"tthflow ATTSV DTRXOFF OFF","",x);
  3783. #endif /* DTRXOFF */
  3784.     } else {                /* Turn it ON. */
  3785.     if (flow == FLO_RTSC) {    /* RTS/CTS Flow control... */
  3786. #ifdef RTSXOFF
  3787.         /* This is the preferred way, according to SVID R4 */
  3788.         if (ioctl(ttyfd,TCGETX,&rctsx) > -1) {
  3789.         debug(F100,"tthflow ATTSV RTS/CTS ON","",0);
  3790.         rctsx.x_hflag |= RTSXOFF | CTSXON;
  3791.         x = ioctl(ttyfd,TCSETX,&rctsx);
  3792.         }
  3793. #else
  3794.         x = -1;
  3795. #endif /* RTSXOFF */
  3796.     } else if (flow == FLO_DTRC) {    /* DTR/CD Flow control... */
  3797. #ifdef DTRXOFF
  3798.         /* This is straight out of SVID R4 */
  3799.         if (ioctl(ttyfd,TCGETX,&rctsx) > -1) {
  3800.         debug(F100,"tthflow ATTSV DTR/CD ON","",0);
  3801.         rctsx.x_hflag &= ~(DTRXOFF|CDXON);
  3802.         x = ioctl(ttyfd,TCSETX,&rctsx);
  3803.         }
  3804. #else
  3805.         x = -1;
  3806. #endif /* DTRXOFF */
  3807.     }
  3808.     }
  3809. #endif /* CK_SCOUNIX */
  3810.  
  3811. #else /* not System V... */
  3812.  
  3813. #ifdef CK_DTRCTS
  3814. #ifdef LDODTR
  3815. #ifdef LDOCTS
  3816.     x = LDODTR | LDOCTS;        /* Found only on UTEK? */
  3817.     if (flow == FLO_DTRT && status) {    /* Use hardware flow control */
  3818.     if (lmodef) {
  3819.         x = ioctl(ttyfd,TIOCLBIS,&x);
  3820.         if (x < 0) {
  3821.             debug(F100,"hardflow TIOCLBIS error","",0);
  3822.         } else {
  3823.         lmodef++;
  3824.         debug(F100,"hardflow TIOCLBIS ok","",0);
  3825.         }
  3826.     }
  3827.     } else {
  3828.     if (lmodef) {
  3829.         x = ioctl(ttyfd,TIOCLBIC,&x);
  3830.         if (x < 0) {
  3831.             debug(F100,"hardflow TIOCLBIC error","",0);
  3832.         } else {
  3833.         lmodef++;
  3834.         debug(F100,"hardflow TIOCLBIC ok","",0);
  3835.         }
  3836.     }
  3837.     }
  3838. #endif /* LDODTR */
  3839. #endif /* LDOCTS */
  3840. #endif /* CK_DTRCTS */
  3841. #endif /* ATTSV */
  3842. #endif /* AIXRS */
  3843. #endif /* SUNOS4 */
  3844. #endif /* QNX */
  3845. #endif /* POSIX_CRTSCTS */
  3846. #endif /* SUNOS41 */
  3847.  
  3848. #else /* OXOS */
  3849.  
  3850.     struct termios temp;        /* Olivetti X/OS ... */
  3851.  
  3852.     x = ioctl(ttyfd,TCGETS,&temp);
  3853.     if (x == 0) {
  3854.     temp.c_cflag &= ~(CRTSCTS|CDTRCTS|CBRKFLOW|CDTRDSR|CRTSDSR);
  3855.     if (status) {
  3856.         switch (flow) {
  3857.           case FLO_RTSC: temp.c_cflag |= CRTSCTS; /* RTS/CTS (hard) */
  3858.         break;
  3859.           case FLO_DTRT: temp.c_cflag |= CDTRCTS; /* DTR/CTS (hard) */
  3860.         break;
  3861.         }
  3862.     }
  3863.     x = ioctl(ttyfd,TCSETS,&temp);
  3864.     }
  3865. #endif /* OXOS */
  3866.     return(x);
  3867.  
  3868. #endif /* Plan9 */
  3869.  
  3870. }
  3871.  
  3872. /*  T T P K T  --  Condition the communication line for packets */
  3873. /*                 or for modem dialing */
  3874.  
  3875. /*
  3876.   If called with speed > -1, also set the speed.
  3877.   Returns 0 on success, -1 on failure.
  3878.  
  3879.   NOTE: the "xflow" parameter is supposed to be the currently selected
  3880.   type of flow control, but for historical reasons, this parameter is also
  3881.   used to indicate that we are dialing.  Therefore, when the true flow
  3882.   control setting is needed, we access the external variable "flow", rather
  3883.   than trusting our "xflow" argument.
  3884. */
  3885. int
  3886. #ifdef CK_ANSIC
  3887. ttpkt(long speed, int xflow, int parity)
  3888. #else
  3889. ttpkt(speed,xflow,parity) long speed; int xflow, parity;
  3890. #endif /* CK_ANSIC */
  3891. /* ttpkt */ {
  3892. #ifndef NOLOCAL
  3893.     int s2;
  3894.     int s = -1;
  3895. #endif /* NOLOCAL */
  3896. #ifndef SVORPOSIX
  3897.     int x;
  3898. #endif /* SVORPOSIX */
  3899.     extern int flow;            /* REAL flow-control setting */
  3900.  
  3901.     if (ttyfd < 0) return(-1);          /* Not open. */
  3902.  
  3903.     debug(F101,"ttpkt parity","",parity);
  3904.     debug(F101,"ttpkt xflow","",xflow);
  3905.     debug(F101,"ttpkt speed","",(int) speed);
  3906.  
  3907.     ttprty = parity;                    /* Let other tt functions see these. */
  3908.     ttpflg = 0;                /* Parity not sensed yet */
  3909.     ttspeed = speed;            /* Make global copy for this module */
  3910.     ttpmsk = ttprty ? 0177 : 0377;    /* Parity stripping mask */
  3911.  
  3912.     debug(F101,"ttpkt ttpmsk","",ttpmsk);
  3913.     debug(F101,"ttpkt netconn","",netconn);
  3914.  
  3915. #ifdef NETCONN                /* Nothing to do for telnet */
  3916.     if (netconn) return (0);
  3917. #endif /* NETCONN */
  3918.  
  3919. #ifndef Plan9
  3920.     if (ttfdflg && !isatty(ttyfd)) return(0);
  3921. #endif /* Plan9 */
  3922.  
  3923. #ifdef COHERENT
  3924. #define SVORPOSIX
  3925. #endif /* COHERENT */
  3926.  
  3927. #ifndef SVORPOSIX            /* Berkeley, V7, etc. */
  3928. #ifdef LPASS8
  3929. /*
  3930.  For some reason, with BSD terminal drivers, you can't set FLOW to XON/XOFF
  3931.  after having previously set it to NONE without closing and reopening the
  3932.  device.  Unless there's something I overlooked below...
  3933. */
  3934.     if (ttflow == FLO_NONE && flow == FLO_XONX && xlocal == 0) {
  3935.     debug(F101,"ttpkt executing horrible flow kludge","",0);
  3936.     ttclos(0);            /* Close it */
  3937.     x = 0;
  3938.     ttopen(ttnmsv,&x,ttmdm,0);    /* Open it again */
  3939.     }
  3940. #endif /* LPASS8 */
  3941. #endif /* SVORPOSIX */
  3942.  
  3943. #ifdef COHERENT
  3944. #undef SVORPOSIX
  3945. #endif /* COHERENT */
  3946.  
  3947.     if (xflow != FLO_DIAL && xflow != FLO_DIAX)
  3948.       ttflow = xflow;            /* Now make this available too. */
  3949.  
  3950. #ifndef NOLOCAL
  3951.     if (xlocal) {
  3952.     s2 = (int) (speed / 10L);    /* Convert bps to cps */
  3953.     s = ttsspd(s2);            /* Check and set the speed */
  3954.     debug(F101,"ttpkt carrier","",xflow);
  3955.      carrctl(&ttraw, xflow != FLO_DIAL /* Carrier control */
  3956.         && (ttcarr == CAR_ON || (ttcarr == CAR_AUT && ttmdm != 0)));
  3957.     tvtflg = 0;            /* So ttvt() will work next time */
  3958.     }
  3959. #endif /* NOLOCAL */
  3960.  
  3961. #ifdef COHERENT
  3962. #define SVORPOSIX
  3963. #endif /* COHERENT */
  3964.  
  3965. #ifndef SVORPOSIX            /* BSD section */
  3966.     if (flow == FLO_RTSC ||        /* Hardware flow control */
  3967.     flow == FLO_DTRC ||
  3968.     flow == FLO_DTRT) {
  3969.     tthflow(flow, 1, &ttraw);
  3970.     debug(F100,"ttpkt hard flow, TANDEM off, RAW on","",0);
  3971.     ttraw.sg_flags &= ~TANDEM;    /* Turn off software flow control */
  3972.     ttraw.sg_flags |= RAW;        /* Enter raw mode */
  3973.     } else if (flow == FLO_NONE) {    /* No flow control */
  3974.     debug(F100,"ttpkt no flow, TANDEM off, RAW on","",0);
  3975.     ttraw.sg_flags &= ~TANDEM;    /* Turn off software flow control */
  3976.     tthflow(flow, 0, &ttraw);    /* Turn off any hardware f/c too */
  3977.     ttraw.sg_flags |= RAW;        /* Enter raw mode */
  3978.     } else if (flow == FLO_KEEP) {    /* Keep device's original setting */
  3979.     debug(F100,"ttpkt keeping original TANDEM","",0);
  3980.     ttraw.sg_flags &= ~TANDEM;
  3981.     ttraw.sg_flags |= (ttold.sg_flags & TANDEM);
  3982.     /* NOTE: We should also handle hardware flow control here! */
  3983.     }
  3984.  
  3985. /* SET FLOW XON/XOFF is in effect, or SET FLOW KEEP resulted in Xon/Xoff */
  3986.  
  3987.     if ((flow == FLO_XONX) || (ttraw.sg_flags & TANDEM)) {
  3988.     debug(F100,"ttpkt turning on TANDEM","",0);
  3989.     ttraw.sg_flags |= TANDEM;    /* So ask for it. */
  3990.  
  3991. #ifdef LPASS8                /* Can pass 8-bit data through? */
  3992. /* If the LPASS8 local mode is available, then flow control can always  */
  3993. /* be used, even if parity is none and we are transferring 8-bit data.  */
  3994. /* But we only need to do all this if Xon/Xoff is requested. */
  3995. /* BUT... this tends not to work through IP or LAT connections, terminal */
  3996. /* servers, telnet, rlogin, etc, so it is currently disabled. */
  3997.     x = LPASS8;            /* If LPASS8 defined, then */
  3998.     debug(F100,"ttpkt executing LPASS8 code","",0);
  3999.     if (lmodef) {            /* TIOCLBIS must be too. */
  4000.         x = ioctl(ttyfd,TIOCLBIS,&x); /* Try to set LPASS8. */
  4001.         if (x < 0) {
  4002.         debug(F100,"ttpkt TIOCLBIS error","",0);
  4003.         } else {
  4004.         lmodef++;
  4005.         debug(F100,"ttpkt TIOCLBIS ok","",0);
  4006.         }
  4007.     }
  4008. /*
  4009.  But if we use LPASS8 mode, we must explicitly turn off
  4010.  terminal interrupts of all kinds.
  4011. */
  4012. #ifdef TIOCGETC                /* Not rawmode, */
  4013.     if (tcharf && (xlocal == 0)) {    /* must turn off */
  4014.         tchnoi.t_intrc = -1;    /* interrupt character */
  4015.         tchnoi.t_quitc = -1;    /* and quit character. */
  4016.         tchnoi.t_startc = 17;    /* Make sure xon */
  4017.         tchnoi.t_stopc = 19;    /* and xoff not ignored. */
  4018. #ifndef NOBRKC
  4019.         tchnoi.t_eofc = -1;        /* eof character. */ 
  4020.         tchnoi.t_brkc = -1;        /* brk character. */ 
  4021. #endif /* NOBRKC */
  4022.         if (ioctl(ttyfd,TIOCSETC,&tchnoi) < 0) {
  4023.         debug(F100,"ttpkt TIOCSETC failed","",0);
  4024.         } else {
  4025.         tcharf = 1;
  4026.         debug(F100,"ttpkt TIOCSETC ok","",0);
  4027.         }
  4028. #ifdef COMMENT
  4029. /* only for paranoid debugging */
  4030.         if (tcharf) {
  4031.         struct tchars foo;
  4032.         char tchbuf[100];
  4033.         ioctl(0,TIOCGETC,&foo);
  4034.         sprintf(tchbuf,
  4035.             "intr=%d,quit=%d, start=%d, stop=%d, eof=%d, brk=%d",
  4036.             foo.t_intrc, foo.t_quitc, foo.t_startc,
  4037.             foo.t_stopc, foo.t_eofc,  foo.t_brkc);
  4038.         debug(F110,"ttpkt chars",tchbuf,0);
  4039.         }
  4040. #endif /* COMMENT */
  4041.     }
  4042.     ttraw.sg_flags |= CBREAK;    /* Needed for unknown reason */
  4043. #endif /* TIOCGETC */
  4044.  
  4045. /* Prevent suspend during packet mode */
  4046. #ifdef TIOCGLTC                /* Not rawmode, */
  4047.     if (ltcharf && (xlocal == 0)) {    /* must turn off */
  4048.         ltchnoi.t_suspc = -1;    /* suspend character */
  4049.         ltchnoi.t_dsuspc = -1;    /* and delayed suspend character */
  4050.         if (ioctl(ttyfd,TIOCSLTC,&tchnoi) < 0) {
  4051.         debug(F100,"ttpkt TIOCSLTC failed","",0);
  4052.         } else {
  4053.         ltcharf = 1;
  4054.         debug(F100,"ttpkt TIOCSLTC ok","",0);
  4055.         }
  4056.     }
  4057. #endif /* TIOCGLTC */
  4058.  
  4059. #else /* LPASS8 not defined */
  4060.  
  4061. /* Previously, BSD-based implementations always */
  4062. /* used rawmode for packets.  Now, we use rawmode only if parity is NONE. */
  4063. /* This allows the flow control requested above to actually work, but only */
  4064. /* if the user asks for parity (which also means they get 8th-bit quoting). */
  4065.  
  4066.     if (parity) {            /* If parity, */
  4067.         ttraw.sg_flags &= ~RAW;    /* use cooked mode */
  4068. #ifdef COMMENT
  4069. /* WHY??? */
  4070.         if (xlocal)
  4071. #endif /* COMMENT */
  4072.           ttraw.sg_flags |= CBREAK;
  4073.         debug(F101,"ttpkt cooked, cbreak, parity","",parity);
  4074. #ifdef TIOCGETC                /* Not rawmode, */
  4075.         if (tcharf && (xlocal == 0)) { /* must turn off */
  4076.         tchnoi.t_intrc = -1;    /* interrupt character */
  4077.         tchnoi.t_quitc = -1;    /* and quit character. */
  4078.         tchnoi.t_startc = 17;    /* Make sure xon */
  4079.         tchnoi.t_stopc = 19;    /* and xoff not ignored. */
  4080. #ifndef NOBRKC
  4081.         tchnoi.t_eofc = -1;    /* eof character. */ 
  4082.         tchnoi.t_brkc = -1;    /* brk character. */ 
  4083. #endif /* NOBRKC */
  4084.         if (ioctl(ttyfd,TIOCSETC,&tchnoi) < 0) {
  4085.             debug(F100,"ttpkt TIOCSETC failed","",0);
  4086.         } else {
  4087.             tcharf = 1;
  4088.             debug(F100,"ttpkt TIOCSETC ok","",0);
  4089.         }
  4090.         }
  4091. #endif /* TIOCGETC */
  4092. #ifdef TIOCGLTC                /* Not rawmode, */
  4093. /* Prevent suspend during packet mode */
  4094.         if (ltcharf && (xlocal == 0)) { /* must turn off */
  4095.         ltchnoi.t_suspc = -1;    /* suspend character */
  4096.         ltchnoi.t_dsuspc = -1;    /* and delayed suspend character */
  4097.         if (ioctl(ttyfd,TIOCSLTC,&tchnoi) < 0) {
  4098.             debug(F100,"ttpkt TIOCSLTC failed","",0);
  4099.         } else {
  4100.             ltcharf = 1;
  4101.             debug(F100,"ttpkt TIOCSLTC ok","",0);
  4102.         }
  4103.         }
  4104. #endif /* TIOCGLTC */
  4105.     } else {            /* If no parity, */
  4106.         ttraw.sg_flags |= RAW;    /* must use 8-bit raw mode. */
  4107.         debug(F101,"ttpkt setting rawmode, parity","",parity);
  4108.     }
  4109. #endif /* LPASS8 */
  4110.     } /* End of Xon/Xoff section */
  4111.  
  4112.     /* Don't echo, don't map CR to CRLF on output, don't fool with case */
  4113. #ifdef LCASE
  4114.     ttraw.sg_flags &= ~(ECHO|CRMOD|LCASE);
  4115. #else
  4116.     ttraw.sg_flags &= ~(ECHO|CRMOD);
  4117. #endif /* LCASE */
  4118.  
  4119. #ifdef TOWER1
  4120.     ttraw.sg_flags &= ~ANYP;            /* Must set this on old Towers */
  4121. #endif /* TOWER1 */
  4122.  
  4123. #ifdef BELLV10
  4124.     if (ioctl(ttyfd,TIOCSETP,&ttraw) < 0) return(-1); /* Set the new modes. */
  4125. #else
  4126.     if (stty(ttyfd,&ttraw) < 0) return(-1); /* Set the new modes. */
  4127. #endif /* BELLV10 */
  4128.     debug(F100,"ttpkt stty ok","",0);
  4129.  
  4130. #ifdef sony_news
  4131.     x = xlocal ? km_ext : km_con;    /* Put line in ASCII mode. */
  4132.     if (x != -1) {            /* Make sure we know original modes. */
  4133.     x &= ~KM_TTYPE;
  4134.     x |= KM_ASCII;
  4135.     if (ioctl(ttyfd,TIOCKSET, &x) < 0) {
  4136.         perror("ttpkt can't set ASCII mode");
  4137.         debug(F101,"ttpkt error setting ASCII mode","",x);
  4138.         return(-1);
  4139.     }
  4140.     }
  4141.     debug(F100,"ttpkt set ASCII mode ok","",0);
  4142. #endif /* sony_news */
  4143.  
  4144.     if (xlocal == 0)            /* Turn this off so we can read */
  4145.       signal(SIGINT,SIG_IGN);        /* Ctrl-C chars typed at console */
  4146.  
  4147.     tvtflg = 0;                /* So ttvt() will work next time */
  4148.     return(0);
  4149.  
  4150. #endif /* Not ATTSV or POSIX */
  4151.  
  4152. /* AT&T UNIX and POSIX */
  4153.  
  4154. #ifdef COHERENT
  4155. #define SVORPOSIX
  4156. #endif /* COHERENT */
  4157.  
  4158. #ifdef SVORPOSIX
  4159.     if (flow == FLO_XONX) {        /* Xon/Xoff */
  4160.     ttraw.c_iflag |= (IXON|IXOFF);
  4161.     tthflow(flow, 0, &ttraw);
  4162.     } else if (flow == FLO_NONE) {    /* None */
  4163.     /* NOTE: We should also turn off hardware flow control here! */
  4164.     ttraw.c_iflag &= ~(IXON|IXOFF);
  4165.     tthflow(flow, 0, &ttraw);
  4166.     } else if (flow == FLO_KEEP) {    /* Keep */
  4167.     ttraw.c_iflag &= ~(IXON|IXOFF);    /* Turn off Xon/Xoff flags */
  4168.     ttraw.c_iflag |= (ttold.c_iflag & (IXON|IXOFF)); /* OR in old ones */
  4169.     /* NOTE: We should also handle hardware flow control here! */
  4170. #ifdef __linux__
  4171. /* In Linux case, we do this, which is unlikely to be portable */
  4172.         ttraw.c_cflag &= ~CRTSCTS;    /* Turn off RTS/CTS flag */
  4173.         ttraw.c_cflag |= (ttold.c_cflag & CRTSCTS); /* OR in old one */
  4174. #endif /* __linux__ */
  4175.     } else if (flow == FLO_RTSC ||    /* Hardware */
  4176.            flow == FLO_DTRC ||
  4177.            flow == FLO_DTRT) {
  4178.     ttraw.c_iflag &= ~(IXON|IXOFF);    /* (190) */
  4179.     tthflow(flow, 1, &ttraw);
  4180.     }
  4181.     ttraw.c_lflag &= ~(ICANON|ECHO);
  4182.     ttraw.c_lflag &= ~ISIG;        /* Do NOT check for interrupt chars */
  4183.  
  4184. #ifndef OXOS
  4185. #ifdef QNX
  4186.     if (flow != FLO_RTSC && flow != FLO_DTRC && flow != FLO_DTRT)
  4187. #endif /* QNX */
  4188. #ifndef COHERENT
  4189.       ttraw.c_lflag &= ~IEXTEN;        /* Turn off ^O/^V processing */
  4190. #endif /* COHERENT */
  4191. #else /* OXOS */
  4192.     ttraw.c_cc[VDISCARD] = ttraw.c_cc[VLNEXT] = CDISABLE;
  4193. #endif /* OXOS */
  4194.     ttraw.c_lflag |= NOFLSH;        /* Don't flush */
  4195.     ttraw.c_iflag |= (BRKINT|IGNPAR);
  4196. #ifdef ATTSV
  4197. #ifdef BSD44
  4198.     ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|INPCK|ISTRIP|IXANY);
  4199. #else
  4200.     ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|INPCK|ISTRIP|IXANY);
  4201. #endif /* BSD44 */
  4202. #else /* POSIX */
  4203.     ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|INPCK|ISTRIP);
  4204. #endif /* ATTSV */
  4205.     ttraw.c_oflag &= ~OPOST;
  4206.     ttraw.c_cflag &= ~(CSIZE|PARENB);
  4207.     ttraw.c_cflag |= (CS8|CREAD|HUPCL);
  4208. #ifdef IX370
  4209.     ttraw.c_cc[4] = 48;  /* So Series/1 doesn't interrupt on every char */
  4210.     ttraw.c_cc[5] = 1;
  4211. #else
  4212. #ifndef VEOF    /* for DGUX this is VEOF, not VMIN */
  4213.     ttraw.c_cc[4] = 1;   /* [VMIN]  return max of this many characters or */
  4214. #else
  4215. #ifndef OXOS
  4216. #ifdef VMIN
  4217.     ttraw.c_cc[VMIN] = 1;
  4218. #endif /* VMIN */
  4219. #else /* OXOS */
  4220.     ttraw.c_min = 1;
  4221. #endif /* OXOS */
  4222. #endif /* VEOF */
  4223. #ifndef VEOL    /* for DGUX this is VEOL, not VTIME */
  4224.     ttraw.c_cc[5] = 0;     /* [VTIME] when this many secs/10 expire w/no input */
  4225. #else
  4226. #ifndef OXOS
  4227. #ifdef VTIME
  4228.     ttraw.c_cc[VTIME] = 0;
  4229. #endif /* VTIME */
  4230. #else /* OXOS */
  4231.     ttraw.c_time = 0;
  4232. #endif /* OXOS */
  4233. #endif /* VEOL */
  4234. #endif /* IX370 */
  4235.  
  4236. #ifdef VINTR                /* Turn off interrupt character */
  4237.     if (xlocal == 0)            /* so ^C^C can break us out of */
  4238.       ttraw.c_cc[VINTR] = 0;        /* packet mode. */
  4239. #endif /* VINTR */
  4240.  
  4241. #ifdef Plan9
  4242.     if (p9ttyparity('n') < 0)
  4243.     return -1;
  4244. #else
  4245. #ifdef BSD44ORPOSIX
  4246. #ifdef BEBOX
  4247.     ttraw.c_cc[VMIN] = 0;        /* DR7 can only poll. */
  4248. #endif /* BEBOX */
  4249.     if (tcsetattr(ttyfd,TCSADRAIN,&ttraw) < 0) return(-1);
  4250. #else /* ATTSV */
  4251.     if (ioctl(ttyfd,TCSETAW,&ttraw) < 0) return(-1);  /* set new modes . */
  4252. #endif /* BSD44ORPOSIX */
  4253. #endif /* Plan9 */
  4254.     tvtflg = 0;
  4255.     return(0);
  4256. #endif /* ATTSV */
  4257.  
  4258. #ifdef COHERENT
  4259. #undef SVORPOSIX
  4260. #endif /* COHERENT */
  4261.  
  4262. }
  4263.  
  4264. /*  T T S E T F L O W  --  Set flow control immediately.  */
  4265.  
  4266. int
  4267. ttsetflow(flow) int flow; {
  4268.     if (ttyfd < 0)            /* Communications channel must open */
  4269.       return(-1);
  4270.  
  4271.     if (flow == FLO_RTSC ||        /* Hardware flow control... */
  4272.     flow == FLO_DTRC ||
  4273.     flow == FLO_DTRT) {
  4274.     tthflow(flow, 1, &ttraw);
  4275. #ifndef SVORPOSIX
  4276.     ttraw.sg_flags &= ~TANDEM;    /* Turn off software flow control */
  4277. #else
  4278.     ttraw.c_iflag &= ~(IXON|IXOFF);
  4279. #endif /* SVORPOSIX */
  4280.  
  4281.     } else if (flow == FLO_XONX) {    /* Xon/Xoff... */
  4282.  
  4283. #ifndef SVORPOSIX
  4284.     ttraw.sg_flags |= TANDEM;
  4285. #else
  4286.     ttraw.c_iflag |= (IXON|IXOFF);
  4287. #endif /* SVORPOSIX */
  4288.     tthflow(FLO_RTSC, 0, &ttraw);    /* Turn off hardware flow control */
  4289.  
  4290.     } else if (flow == FLO_NONE) {    /* No flow control */
  4291.  
  4292. #ifndef SVORPOSIX
  4293.     ttraw.sg_flags &= ~TANDEM;    /* Turn off software flow control */
  4294. #else
  4295.     ttraw.c_iflag &= ~(IXON|IXOFF);
  4296. #endif /* SVORPOSIX */
  4297.     tthflow(FLO_RTSC, 0, &ttraw);    /* Turn off any hardware f/c too */
  4298.     }
  4299.  
  4300. /* Set the new modes... */
  4301.  
  4302. #ifndef SVORPOSIX            /* BSD and friends */
  4303. #ifdef BELLV10
  4304.     if (ioctl(ttyfd,TIOCSETP,&ttraw) < 0)
  4305.       return(-1);
  4306. #else
  4307.     if (stty(ttyfd,&ttraw) < 0)
  4308.       return(-1);
  4309. #endif /* BELLV10 */
  4310. #else
  4311. #ifdef BSD44ORPOSIX            /* POSIX */
  4312.     if (tcsetattr(ttyfd,TCSADRAIN,&ttraw) < 0)
  4313.       return(-1);
  4314. #else                    /* System V */
  4315.     if (ioctl(ttyfd,TCSETAW,&ttraw) < 0)
  4316.       return(-1);
  4317. #endif /* BSD44ORPOSIX */
  4318. #endif /* SVORPOSIX */
  4319.     return(0);
  4320. }
  4321.  
  4322. /*  T T V T -- Condition communication line for use as virtual terminal  */
  4323.  
  4324. #ifndef NOLOCAL
  4325. int
  4326. #ifdef CK_ANSIC
  4327. ttvt(long speed, int flow)
  4328. #else
  4329. ttvt(speed,flow) long speed; int flow;
  4330. #endif /* CK_ANSIC */
  4331. /* ttvt */ {
  4332.     int s, s2;
  4333.  
  4334.     debug(F101,"ttvt ttyfd","",ttyfd);
  4335.     debug(F101,"ttvt tvtflg","",tvtflg);
  4336.     debug(F101,"ttvt speed","",speed);
  4337.     debug(F101,"ttvt flow","",flow);
  4338.     if (ttyfd < 0) return(-1);          /* Not open. */
  4339. #ifdef NETCONN
  4340.     ttpmsk = 0xff;
  4341.     if (netconn) {
  4342.     tvtflg = 1;            /* Network connections */
  4343.     debug(F100,"ttvt network connection, skipping...","",0);
  4344.     return(0);            /* require no special setup */
  4345.     }
  4346. #endif /* NETCONN */
  4347.  
  4348.     if (tvtflg != 0 && speed == ttspeed && flow == ttflow && ttcarr == curcarr)
  4349.       {
  4350.       debug(F100,"ttvt modes already set, skipping...","",0);
  4351.       return(0);            /* Already been called. */
  4352.       }
  4353.  
  4354.     if (ttfdflg
  4355. #ifndef Plan9
  4356.     && !isatty(ttyfd)
  4357. #endif /* Plan9 */
  4358.     ) {
  4359.     debug(F100,"ttvt using external fd, skipping...","",0);
  4360.     return(0);
  4361.     }
  4362.  
  4363.     debug(F100,"ttvt setting modes...","",0);
  4364.  
  4365.     if (xlocal) {            /* For external lines... */
  4366.     s2 = (int) (speed / 10L);
  4367.     s = ttsspd(s2);            /* Check/set the speed */
  4368.     carrctl(&tttvt, flow != FLO_DIAL /* Do carrier control */
  4369.         && (ttcarr == CAR_ON || (ttcarr == CAR_AUT && ttmdm != 0)));
  4370.     } else
  4371.       s = s2 = -1;
  4372.  
  4373. #ifdef COHERENT
  4374. #define SVORPOSIX
  4375. #endif /* COHERENT */
  4376.  
  4377. #ifndef SVORPOSIX
  4378.     /* Berkeley, V7, etc */
  4379.     if (flow == FLO_RTSC ||        /* Hardware flow control */
  4380.     flow == FLO_DTRC ||
  4381.     flow == FLO_DTRT)
  4382.       tthflow(flow, 1, &tttvt);
  4383.     if (flow == FLO_XONX) {        /* Xon/Xoff flow control */
  4384.     tttvt.sg_flags |= TANDEM;    /* Ask for it. */
  4385.     tthflow(flow, 0, &tttvt);    /* Turn off hardware f/c */
  4386.     } else if (flow == FLO_KEEP) {
  4387.     tttvt.sg_flags &= ~TANDEM;
  4388.     tttvt.sg_flags |= (ttold.sg_flags & TANDEM);
  4389.     /* NOTE: We should also handle hardware flow control here! */
  4390.     } else if (flow == FLO_NONE) {
  4391.     tttvt.sg_flags &= ~TANDEM;    /* No Xon/Xoff */
  4392.     tthflow(flow, 0, &tttvt);    /* Turn off hardware f/c */
  4393.     }
  4394.     tttvt.sg_flags |= RAW;              /* Raw mode in all cases */
  4395. #ifdef TOWER1
  4396.     tttvt.sg_flags &= ~(ECHO|ANYP);     /* No echo or parity */
  4397. #else
  4398.     tttvt.sg_flags &= ~ECHO;            /* No echo */
  4399. #endif /* TOWER1 */
  4400.  
  4401. #ifdef BELLV10
  4402.     if (ioctl(ttyfd,TIOCSETP,&tttvt) < 0) /* Set the new modes */
  4403.       return(-1);
  4404. #else
  4405.     if (stty(ttyfd,&tttvt) < 0)        /* Set the new modes */
  4406.       return(-1);
  4407. #endif /* BELLV10 */
  4408.  
  4409. #else /* It is ATTSV or POSIX */
  4410.  
  4411.     if (flow == FLO_RTSC ||        /* Hardware flow control */
  4412.     flow == FLO_DTRC ||
  4413.     flow == FLO_DTRT) {
  4414.     tthflow(flow, 1, &tttvt);
  4415.     } else if (flow == FLO_XONX) {    /* Software flow control */
  4416.     tttvt.c_iflag |= (IXON|IXOFF);    /* On if requested. */
  4417.     tthflow(flow, 0, &tttvt);    /* Turn off hardware f/c */
  4418.     } else if (flow == FLO_KEEP) {
  4419.     tttvt.c_iflag &= ~(IXON|IXOFF);    /* Turn off Xon/Xoff flags */
  4420.     tttvt.c_iflag |= (ttold.c_iflag & (IXON|IXOFF)); /* OR in old ones */
  4421.     /* NOTE: We should also handle hardware flow control here! */
  4422. #ifdef __linux__
  4423.         tttvt.c_cflag &= ~CRTSCTS;    /* Turn off RTS/CTS flag */
  4424.         tttvt.c_cflag |= (ttold.c_cflag & CRTSCTS); /* OR in old one */
  4425. #endif /* __linux__ */
  4426.     } else if (flow == FLO_NONE) {    /* NONE */
  4427.     tthflow(flow, 0, &tttvt);    /* Turn off hardware f/c */
  4428.     tttvt.c_iflag &= ~(IXON|IXOFF);    /* Turn off Xon/Xoff */
  4429.     }
  4430.  
  4431. #ifndef OXOS
  4432. #ifdef COHERENT
  4433.     tttvt.c_lflag &= ~(ISIG|ICANON|ECHO);
  4434. #else
  4435.     tttvt.c_lflag &= ~(ISIG|ICANON|ECHO|IEXTEN);
  4436. #endif /* COHERENT */
  4437. #ifdef QNX
  4438.     /* Needed for hwfc */
  4439.     if (flow == FLO_RTSC || flow == FLO_DTRC || flow == FLO_DTRT)
  4440.       tttvt.c_lflag |= IEXTEN;
  4441. #endif /* QNX */
  4442. #else /* OXOS */
  4443.     tttvt.c_lflag &= ~(ISIG|ICANON|ECHO);
  4444.     tttvt.c_cc[VDISCARD] = tttvt.c_cc[VLNEXT] = CDISABLE;
  4445. #endif /* OXOS */
  4446.     tttvt.c_iflag |= (IGNBRK|IGNPAR);
  4447. #ifdef ATTSV
  4448. #ifdef BSD44
  4449.     tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|BRKINT|INPCK|ISTRIP|IXANY);
  4450. #else
  4451.     tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|IUCLC|BRKINT|INPCK|ISTRIP|IXANY);
  4452. #endif /* BSD44 */
  4453. #else /* POSIX */
  4454.     tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|BRKINT|INPCK|ISTRIP);
  4455. #endif /* ATTSV */
  4456.     tttvt.c_oflag &= ~OPOST;
  4457.     tttvt.c_cflag &= ~(CSIZE|PARENB);
  4458.     tttvt.c_cflag |= (CS8|CREAD|HUPCL);
  4459. #ifndef VEOF    /* DGUX termio has VEOF at entry 4, see comment above */
  4460.     tttvt.c_cc[4] = 1;
  4461. #else
  4462. #ifndef OXOS
  4463. #ifdef VMIN
  4464.     tttvt.c_cc[VMIN] = 1;
  4465. #endif /* VMIN */
  4466. #else /* OXOS */
  4467.     tttvt.c_min = 1;
  4468. #endif /* OXOS */
  4469. #endif /* VEOF */
  4470. #ifndef VEOL    /* DGUX termio has VEOL at entry 5, see comment above */
  4471.     tttvt.c_cc[5] = 0;
  4472. #else
  4473. #ifndef OXOS
  4474. #ifdef VTIME
  4475.     tttvt.c_cc[VTIME] = 0;
  4476. #endif /* VTIME */
  4477. #else /* OXOS */
  4478.     tttvt.c_time = 0;
  4479. #endif /* OXOS */
  4480. #endif /* VEOL */
  4481.  
  4482. #ifdef Plan9
  4483.     if (p9ttyparity('n') < 0)
  4484.       return -1;
  4485. #else
  4486. #ifdef BSD44ORPOSIX
  4487. #ifdef BEBOX
  4488.     tttvt.c_cc[VMIN] = 0;        /* DR7 can only poll. */
  4489. #endif /* BEBOX */
  4490.     if (tcsetattr(ttyfd,TCSADRAIN,&tttvt) < 0) return(-1);
  4491. #else /* ATTSV */
  4492.     if (ioctl(ttyfd,TCSETAW,&tttvt) < 0) return(-1);  /* set new modes . */
  4493. #endif /* BSD44ORPOSIX */
  4494. #endif /* Plan9 */
  4495. #endif /* ATTSV */
  4496.  
  4497.     ttspeed = speed;            /* Done, remember how we were */
  4498.     ttflow = flow;            /* called, so we can decide how to */
  4499.     tvtflg = 1;                /* respond next time. */
  4500.     debug(F101,"ttvt done","",tvtflg);
  4501.     return(0);
  4502.  
  4503. #ifdef COHERENT
  4504. #undef SVORPOSIX
  4505. #endif /* COHERENT */
  4506.  
  4507. }
  4508. #endif /* NOLOCAL */
  4509.  
  4510. /*  T T S S P D  --  Checks and sets transmission rate.  */
  4511.  
  4512. /*  Call with speed in characters (not bits!) per second. */
  4513. /*  Returns -1 on failure, 0 if it did nothing, 1 if it changed the speed. */
  4514.  
  4515. #ifndef NOLOCAL
  4516. int
  4517. ttsspd(cps) int cps; {
  4518. #ifdef POSIX
  4519. /* Watch out, speed_t should be unsigned, so don't compare with -1, etc... */
  4520.     speed_t                
  4521. #else
  4522.     int
  4523. #endif /* POSIX */
  4524.       s, s2;
  4525.     int ok = 1;                /* Speed check result, assume ok */
  4526.  
  4527. #ifdef __linux__            /* Linux... */
  4528. #ifdef ASYNC_SPD_MASK
  4529.     unsigned int spd_flags = 0;
  4530.     struct serial_struct serinfo;
  4531. #endif /* ASYNC_SPD_MASK */
  4532. #endif /* __linux__ */
  4533.  
  4534.     debug(F101,"ttsspd cps","",cps);
  4535.     debug(F101,"ttsspd ttyfd","",ttyfd);
  4536.     debug(F101,"ttsspd xlocal","",xlocal);
  4537.  
  4538.     if (ttyfd < 0 || xlocal == 0 )    /* Don't set speed on console */
  4539.       return(0);
  4540.  
  4541. #ifdef    NETCONN
  4542.     if (netconn)
  4543.       return(0);
  4544. #endif    /* NETCONN */
  4545.  
  4546.     if (cps < 0) return(-1);
  4547.     s = s2 = 0;                /* NB: s and s2 might be unsigned */
  4548.  
  4549.     /* First check that the given speed is valid. */
  4550.  
  4551. #ifdef Plan9
  4552.     ok = 1;
  4553. #else
  4554.     switch (cps) {
  4555. #ifndef MINIX
  4556.       case 0:   s = B0;    break;
  4557.       case 5:   s = B50;   break;
  4558.       case 7:   s = B75;   break;
  4559. #endif /* MINIX */
  4560.       case 11:  s = B110;  break;
  4561. #ifndef MINIX
  4562.       case 15:  s = B150;  break;
  4563.       case 20:  s = B200;  break;
  4564. #endif /* MINIX */
  4565.       case 30:  s = B300;  break;
  4566. #ifndef MINIX
  4567.       case 60:  s = B600;  break;
  4568. #endif /* MINIX */
  4569.       case 120: s = B1200; break;
  4570. #ifndef MINIX
  4571.       case 180: s = B1800; break;
  4572. #endif /* MINIX */
  4573.       case 240: s = B2400; break;
  4574.       case 480: s = B4800; break;
  4575. #ifndef MINIX
  4576.       case 888: s = B75; s2 = B1200; break; /* 888 = 75/1200 split speed */
  4577. #endif /* MINIX */
  4578.       case 960: s = B9600; break;
  4579. #ifdef B14400
  4580.       case 1440: s = B14400; break;
  4581. #endif /* B14400 */
  4582. #ifdef B19200
  4583.       case 1920: s = B19200; break;
  4584. #else
  4585. #ifdef EXTA
  4586.       case 1920: s = EXTA; break;
  4587. #endif /* EXTA */
  4588. #endif /* B19200 */
  4589. #ifdef B28800
  4590.       case 2880: s = B28800; break;
  4591. #endif /* B28800 */
  4592. #ifdef B38400
  4593.       case 3840: s = B38400;
  4594. #ifdef __linux__
  4595. #ifdef ASYNC_SPD_MASK
  4596.         spd_flags = ~ASYNC_SPD_MASK;    /* Nonzero, but zero flags */
  4597. #endif /* ASYNC_SPD_MASK */
  4598. #endif /* __linux__ */
  4599.     break;
  4600. #else /* B38400 not defined... */
  4601. #ifdef EXTB
  4602.       case 3840: s = EXTB; break;
  4603. #endif /* EXTB */
  4604. #endif /* B38400 */
  4605.  
  4606. #ifdef HPUX
  4607. #ifdef _B57600
  4608.       case 5760: s = _B57600; break;
  4609. #endif /* _B57600 */
  4610. #ifdef _B115200
  4611.       case 11520: s = _B115200; break;
  4612. #endif /* _B115200 */
  4613. #else
  4614. #ifdef __linux__
  4615. #ifdef ASYNC_SPD_MASK
  4616. /*
  4617.   This bit from <carlo@sg.tn.tudelft.nl>:
  4618.   "Only note to make is maybe this: When the ASYNC_SPD_CUST flags are set then
  4619.   setting the speed to 38400 will set the custom speed (and ttgspd returns
  4620.   38400), but speeds 57600 and 115200 won't work any more because I didn't
  4621.   want to mess up the speed flags when someone is doing sophisticated stuff
  4622.   like custom speeds..."
  4623. */
  4624.       case 5760: s = B38400; spd_flags = ASYNC_SPD_HI; break;
  4625.       case 11520: s = B38400; spd_flags = ASYNC_SPD_VHI; break;
  4626. #endif /* ASYNC_SPD_MASK */
  4627. #else
  4628. #ifdef QNX
  4629. #ifdef B57600
  4630.       case 5760: s = B57600; break;
  4631. #endif /* B57600 */
  4632. #ifdef B76800
  4633.       case 7680: s = B76800; break;
  4634. #endif /* B76800 */
  4635. #ifdef B115200
  4636.       case 11520: s = B115200; break;
  4637. #endif /* B115200 */
  4638. #else
  4639. #ifdef B57600
  4640.       case 5760: s = B57600; break;
  4641. #endif /* B57600 */
  4642. #ifdef B115200
  4643.       case 11520: s = B115200; break;
  4644. #endif /* B115200 */
  4645. #endif /* QNX */
  4646. #endif /* __linux__ */
  4647. #endif /* HPUX */
  4648.       default:
  4649.     ok = 0;                /* Good speed not found, so not ok */
  4650.     break;
  4651.     }
  4652. #endif /* Plan9 */
  4653.     debug(F101,"ttsspd ok","",ok);
  4654.     debug(F101,"ttsspd s","",s);
  4655.  
  4656.     if (!ok) {
  4657.     debug(F100,"ttsspd fails","",0);
  4658.     return(-1);
  4659.     } else {
  4660. #ifdef BSD44ORPOSIX
  4661.     int x;
  4662. #endif /* BSD44ORPOSIX */
  4663.  
  4664.     if (!s2) s2 = s;        /* Set input speed */
  4665.  
  4666. #ifdef Plan9
  4667.     if (p9ttsspd(cps) < 0)
  4668.       return -1;
  4669. #else
  4670. #ifdef BSD44ORPOSIX
  4671.     x = tcgetattr(ttyfd,&ttcur);    /* Get current speed */
  4672.     debug(F101,"ttsspd tcgetattr","",x);
  4673.     if (x < 0)
  4674.       return(-1);
  4675. #ifdef __linux__
  4676. #ifdef ASYNC_SPD_MASK
  4677.     debug(F101,"ttsspd spd_flags","",spd_flags);
  4678.     if (spd_flags && spd_flags != ASYNC_SPD_CUST) {
  4679.         if (ioctl(ttyfd, TIOCGSERIAL, &serinfo) < 0) {
  4680.         debug(F100,"ttsspd: TIOCGSERIAL failed","",0);
  4681.         return(-1);
  4682.         } else debug(F100,"ttsspd: TIOCGSERIAL ok","",0);
  4683.         serinfo.flags &= ~ASYNC_SPD_MASK;
  4684.         serinfo.flags |= (spd_flags & ASYNC_SPD_MASK);
  4685.         if (ioctl(ttyfd, TIOCSSERIAL, &serinfo) < 0)
  4686.           return(-1);
  4687.     }
  4688. #endif /* ASYNC_SPD_MASK */
  4689. #endif /* __linux__ */
  4690.     cfsetospeed(&ttcur,s);
  4691.     cfsetispeed(&ttcur,s2);
  4692.     cfsetospeed(&ttraw,s);
  4693.     cfsetispeed(&ttraw,s2);
  4694.     cfsetospeed(&tttvt,s);
  4695.     cfsetispeed(&tttvt,s2);
  4696.     cfsetospeed(&ttold,s);
  4697.     cfsetispeed(&ttold,s2);
  4698.     x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
  4699.     debug(F101,"ttsspd tcsetattr","",x);
  4700.     if (x < 0) return(-1);
  4701. #else
  4702. #ifdef ATTSV
  4703.     if (cps == 888) return(-1);    /* No split speeds, sorry. */
  4704.     if (ioctl(ttyfd,TCGETA,&ttcur) < 0) return(-1);
  4705.     ttcur.c_cflag &= ~CBAUD;
  4706.     ttcur.c_cflag |= s;
  4707.     tttvt.c_cflag &= ~CBAUD;
  4708.     tttvt.c_cflag |= s;
  4709.     ttraw.c_cflag &= ~CBAUD;
  4710.     ttraw.c_cflag |= s;
  4711.     ttold.c_cflag &= ~CBAUD;
  4712.     ttold.c_cflag |= s;
  4713.     if (ioctl(ttyfd,TCSETAW,&ttcur) < 0) return(-1);
  4714. #else
  4715. #ifdef BELLV10
  4716.     if (ioctl(ttyfd,TIOCGDEV,&tdcur) < 0) return(-1);
  4717.     tdcur.ispeed = s2;
  4718.     tdcur.ospeed = s;
  4719.     errno = 0;
  4720.     ok = ioctl(ttyfd,TIOCSDEV,&tdcur);
  4721.     debug(F101,"ttsspd BELLV10 ioctl","",ok);
  4722.     if (ok < 0) {
  4723.         perror(ttnmsv);
  4724.         debug(F101,"ttsspd BELLV10 errno","",ok);
  4725.         return(-1);
  4726.     }
  4727. #else
  4728.     if (gtty(ttyfd,&ttcur) < 0) return(-1);
  4729.     ttcur.sg_ospeed = s; ttcur.sg_ispeed = s2;
  4730.     tttvt.sg_ospeed = s; tttvt.sg_ispeed = s2;
  4731.     ttraw.sg_ospeed = s; ttraw.sg_ispeed = s2;
  4732.     ttold.sg_ospeed = s; ttold.sg_ispeed = s2;
  4733.     if (stty(ttyfd,&ttcur) < 0) return(-1);
  4734. #endif /* BELLV10 */
  4735. #endif /* ATTSV */
  4736. #endif /* BSD44ORPOSIX */
  4737. #endif /* Plan9 */
  4738.     }
  4739.     return(1);                /* Return 1 = success. */
  4740. }
  4741. #endif /* NOLOCAL */
  4742.  
  4743. /* C O N G S P D  -  Get speed of console terminal  */
  4744.  
  4745. long
  4746. congspd() {
  4747. /*
  4748.   This is a disgusting hack.  The right way to do this would be to pass an
  4749.   argument to ttgspd(), but then we'd need to change the Kermit API and
  4750.   all of the ck?tio.c modules.  (Currently used only for rlogin.)
  4751. */
  4752.     int t1, t2;
  4753.     long spd;
  4754. #ifdef NETCONN
  4755.     t2 = netconn;
  4756.     netconn = 0;
  4757. #endif /* NETCONN */
  4758.     t1 = ttyfd;
  4759.     ttyfd = -1;
  4760.     spd = ttgspd();
  4761.     debug(F101,"congspd","",spd);
  4762. #ifdef NETCONN
  4763.     netconn = t2;
  4764. #endif /* NETCONN */
  4765.     ttyfd = t1;
  4766.     return(spd);
  4767. }
  4768.  
  4769. /* T T G S P D  -  Get speed of currently selected tty line  */
  4770.  
  4771. /*
  4772.   Unreliable.  After SET LINE, it returns an actual speed, but not necessarily
  4773.   the real speed.  On some systems, it returns the line's nominal speed, from
  4774.   /etc/ttytab.  Even if you SET SPEED to something else, this function might
  4775.   not notice.
  4776. */
  4777. long
  4778. ttgspd() {                /* Get current serial device speed */
  4779. #ifdef POSIX
  4780.     speed_t                /* Should be unsigned */
  4781. #else
  4782.     int                    /* Isn't unsigned */
  4783. #endif /* POSIX */
  4784.       s;
  4785.     long ss;
  4786. #ifdef __linux__
  4787. #ifdef ASYNC_SPD_MASK
  4788.     unsigned int spd_flags = 0;
  4789.     struct serial_struct serinfo;
  4790. #endif /* ASYNC_SPD_MASK */
  4791. #endif /* __linux__ */
  4792.  
  4793. #ifdef NETCONN
  4794.     if (netconn) return(-1);        /* -1 if network connection */
  4795. #endif /* NETCONN */
  4796.  
  4797.     debug(F101,"ttgspd ttyfd","",ttyfd);
  4798. #ifdef Plan9
  4799.     if (ttyfd < 0)
  4800.       ss = -1;
  4801.     else
  4802.       ss = ttylastspeed;
  4803. #else
  4804. #ifdef __linux__
  4805. #ifdef ASYNC_SPD_MASK
  4806.     debug(F100,"ttgspd Linux ASYNC_SPD_MASK defined","",0);
  4807. #else
  4808.     debug(F100,"ttgspd Linux ASYNC_SPD_MASK not defined","",0);
  4809. #endif /* ASYNC_SPD_MASK */
  4810. #endif /* __linux__ */
  4811.  
  4812.     if (ttyfd < 0) {
  4813. #ifdef BSD44ORPOSIX
  4814.     s = cfgetospeed(&ccold);
  4815.     debug(F101,"ttgspd cfgetospeed 1 BSDORPOSIX","",s);
  4816. #else
  4817. #ifdef ATTSV
  4818.     s = ccold.c_cflag & CBAUD;
  4819.     debug(F101,"ttgspd cfgetospeed 1 ATTSV","",s);
  4820. #else
  4821.     s = ccold.sg_ospeed;        /* (obtained by congm()) */
  4822.     debug(F101,"ttgspd cfgetospeed 1 catch-all","",s);
  4823. #endif /* ATTSV */
  4824. #endif /* BSD44ORPOSIX */
  4825.  
  4826.     } else {
  4827. #ifdef BSD44ORPOSIX
  4828.     if (tcgetattr(ttyfd,&ttcur) < 0) return(-1);
  4829.     s = cfgetospeed(&ttcur);
  4830.     debug(F101,"ttgspd cfgetospeed 2 BSDORPOSIX","",s);
  4831. #ifdef __linux__
  4832. #ifdef ASYNC_SPD_MASK
  4833.     if (ioctl(ttyfd,TIOCGSERIAL,&serinfo) > -1)
  4834.       spd_flags = serinfo.flags & ASYNC_SPD_MASK;
  4835.     debug(F101,"ttgspd spd_flags","",spd_flags);
  4836. #endif /* ASYNC_SPD_MASK */
  4837. #endif /* __linux__ */
  4838. #else
  4839. #ifdef ATTSV
  4840.     if (ioctl(ttyfd,TCGETA,&ttcur) < 0) return(-1);
  4841.     s = ttcur.c_cflag & CBAUD;
  4842.     debug(F101,"ttgspd cfgetospeed 2 ATTSV","",s);
  4843. #else
  4844. #ifdef BELLV10
  4845.     if (ioctl(ttyfd,TIOCGDEV,&tdcur) < 0) return(-1);
  4846.     s = tdcur.ospeed;
  4847.     debug(F101,"ttgspd cfgetospeed 2 BELLV10","",s);
  4848. #else
  4849.     if (gtty(ttyfd,&ttcur) < 0) return(-1);
  4850.     s = ttcur.sg_ospeed;
  4851.     debug(F101,"ttgspd cfgetospeed 2 catch-all","",s);
  4852. #endif /* BELLV10 */
  4853. #endif /* ATTSV */
  4854. #endif /* BSD44ORPOSIX */
  4855.     }
  4856.     debug(F101,"ttgspd code","",s);
  4857. #ifdef __linux__
  4858. #ifdef ASYNC_SPD_MASK
  4859.     debug(F101,"ttgspd spd_flags","",spd_flags);
  4860. #endif /* ASYNC_SPD_MASK */
  4861. #endif /* __linux__ */
  4862.     switch (s) {
  4863. #ifdef B0
  4864.       case B0:    ss = 0L; break;
  4865. #endif /* B0 */
  4866.  
  4867. #ifndef MINIX
  4868. /*
  4869.  MINIX defines the Bxx symbols to be bps/100, so B50==B75, B110==B134==B150,
  4870.  etc, making for many "duplicate case in switch" errors, which are fatal.
  4871. */
  4872. #ifdef B50
  4873.       case B50:   ss = 50L; break;
  4874. #endif /* B50 */
  4875. #ifdef B75
  4876.       case B75:   ss = 75L; break;
  4877. #endif /* B75 */
  4878. #endif /* MINIX */
  4879.  
  4880. #ifdef B110
  4881.       case B110:  ss = 110L; break;
  4882. #endif /* B110 */
  4883.  
  4884. #ifndef MINIX
  4885. #ifdef B134
  4886.       case B134:  ss = 134L; break;
  4887. #endif /* B134 */
  4888. #ifdef B150
  4889.       case B150:  ss = 150L; break;
  4890. #endif /* B150 */
  4891. #endif /* MINIX */
  4892.  
  4893. #ifdef B200
  4894.       case B200:  ss = 200L; break;
  4895. #endif /* B200 */
  4896.  
  4897. #ifdef B300
  4898.       case B300:  ss = 300L; break;
  4899. #endif /* B300 */
  4900.  
  4901. #ifdef B600
  4902.       case B600:  ss = 600L; break;
  4903. #endif /* B600 */
  4904.  
  4905. #ifdef B1200
  4906.       case B1200: ss = 1200L; break;
  4907. #endif /* B1200 */
  4908.  
  4909. #ifdef B1800
  4910.       case B1800: ss = 1800L; break;
  4911. #endif /* B1800 */
  4912.  
  4913. #ifdef B2400
  4914.       case B2400: ss = 2400L; break;
  4915. #endif /* B2400 */
  4916.  
  4917. #ifdef B4800
  4918.       case B4800: ss = 4800L; break;
  4919. #endif /* B4800 */
  4920.  
  4921. #ifdef B9600
  4922.       case B9600: ss = 9600L; break;
  4923. #endif /* B9600 */
  4924.  
  4925. #ifdef B19200
  4926.       case B19200: ss = 19200L; break;
  4927. #else
  4928. #ifdef EXTA
  4929.       case EXTA: ss = 19200L; break;
  4930. #endif /* EXTA */
  4931. #endif /* B19200 */
  4932.  
  4933. #ifndef MINIX
  4934. #ifdef B38400
  4935.       case B38400:
  4936.         ss = 38400L;
  4937. #ifdef __linux__
  4938. #ifdef ASYNC_SPD_MASK
  4939.         switch(spd_flags) {
  4940.           case ASYNC_SPD_HI:  ss =  57600L; break;
  4941.           case ASYNC_SPD_VHI: ss = 115200L; break;
  4942.     }
  4943. #endif /* ASYNC_SPD_MASK */
  4944. #endif /* __linux__ */
  4945.         break;
  4946. #else
  4947. #ifdef EXTB
  4948.       case EXTB: ss = 38400L; break;
  4949. #endif /* EXTB */
  4950. #endif /* B38400 */
  4951. #endif /* MINIX */
  4952.  
  4953. #ifdef HPUX
  4954. #ifdef _B57600
  4955.       case _B57600: ss = 57600L; break;
  4956. #endif /* _B57600 */
  4957. #ifdef _B115200
  4958.       case _B115200: ss = 115200L; break;
  4959. #endif /* _B115200 */
  4960. #else
  4961. #ifdef QNX
  4962. #ifdef B57600
  4963.       case B57600: ss = 57600L; break;
  4964. #endif /* B57600 */
  4965. #ifdef B76800
  4966.       case B76800: ss = 76800L; break;
  4967. #endif /* B76800 */
  4968. #ifdef B115200
  4969.       case B115200: ss = 115200L; break;
  4970. #endif /* B115200 */
  4971. #else
  4972. #ifdef B57600
  4973.       case B57600: ss = 57600L; break;
  4974. #endif /* B57600 */
  4975. #ifdef B115200
  4976.       case B115200: ss = 115200L; break;
  4977. #endif /* B115200 */
  4978. #endif /* QNX */
  4979. #endif /* HPUX */
  4980.  
  4981.       default:
  4982.     ss = -1; break;
  4983.     }
  4984. #endif /* Plan9 */
  4985.     debug(F101,"ttgspd speed","",ss);
  4986.     return(ss);
  4987. }
  4988.  
  4989. /* ckumyr.c by Kristoffer Eriksson, ske@pkmab.se, 15 Mar 1990. */
  4990.  
  4991. #ifdef COHERENT
  4992. #ifdef FIONREAD
  4993. #undef FIONREAD
  4994. #endif /* FIONREAD */
  4995. #define FIONREAD TIOCQUERY
  4996. #define PEEKTYPE int
  4997. #else  /* Not COHERENT */
  4998. #define PEEKTYPE long
  4999. #endif /* COHERENT */
  5000.  
  5001. #ifdef MYREAD
  5002.  
  5003. /* Private buffer for myread() and its companions.  Not for use by anything
  5004.  * else.  ttflui() is allowed to reset them to initial values.  ttchk() is
  5005.  * allowed to read my_count.
  5006.  *
  5007.  * my_item is an index into mybuf[].  Increment it *before* reading mybuf[].
  5008.  *
  5009.  * A global parity mask variable could be useful too.  We could use it to
  5010.  * let myread() strip the parity on its own, instead of stripping sign
  5011.  * bits as it does now.
  5012.  */
  5013. #ifdef BIGBUFOK
  5014. #define MYBUFLEN 4096
  5015. #else
  5016. #ifdef pdp11
  5017. #define MYBUFLEN 256
  5018. #else
  5019. #define MYBUFLEN 1024
  5020. #endif /* pdp11 */
  5021. #endif /* BIGBUFOK */
  5022.  
  5023. #ifdef SUNX25
  5024. #undef MYBUFLEN
  5025. #define MYBUFLEN 256
  5026.  
  5027. /*
  5028.   On X.25 connections, there is an extra control byte at the beginning.
  5029. */
  5030. static CHAR x25buf[MYBUFLEN+1];        /* Communication device input buffer */
  5031. static CHAR  *mybuf = x25buf+1;
  5032. #else
  5033. static CHAR mybuf[MYBUFLEN];
  5034. #endif /* SUNX25 */
  5035.  
  5036. static int my_count = 0;        /* Number of chars still in mybuf */
  5037. static int my_item = -1;        /* Last index read from mybuf[] */
  5038.  
  5039. /* myread() -- Efficient read of one character from communications line.
  5040.  *
  5041.  * Uses a private buffer to minimize the number of expensive read() system
  5042.  * calls.  Essentially performs the equivalent of read() of 1 character, which
  5043.  * is then returned.  By reading all available input from the system buffers
  5044.  * to the private buffer in one chunk, and then working from this buffer, the
  5045.  * number of system calls is reduced in any case where more than one character
  5046.  * arrives during the processing of the previous chunk, for instance high
  5047.  * baud rates or network type connections where input arrives in packets.
  5048.  * If the time needed for a read() system call approaches the time for more
  5049.  * than one character to arrive, then this mechanism automatically compensates
  5050.  * for that by performing bigger read()s less frequently.  If the system load
  5051.  * is high, the same mechanism compensates for that too.
  5052.  *
  5053.  * myread() is a macro that returns the next character from the buffer.  If the
  5054.  * buffer is empty, mygetbuf() is called.  See mygetbuf() for possible error
  5055.  * returns.
  5056.  *
  5057.  * This should be efficient enough for any one-character-at-a-time loops.
  5058.  * For even better efficiency you might use memcpy()/bcopy() or such between
  5059.  * buffers (since they are often better optimized for copying), but it may not
  5060.  * be worth it if you have to take an extra pass over the buffer to strip
  5061.  * parity and check for CTRL-C anyway.
  5062.  *
  5063.  * Note that if you have been using myread() from another program module, you
  5064.  * may have some trouble accessing this macro version and the private variables
  5065.  * it uses.  In that case, just add a function in this module, that invokes the
  5066.  * macro.
  5067.  */
  5068. #define myread()  (--my_count < 0 ? mygetbuf() : 255 & (int)mybuf[++my_item])
  5069.  
  5070. /* Specification: Push back up to one character onto myread()'s queue.
  5071.  *
  5072.  * This implementation: Push back characters into mybuf. At least one character
  5073.  * must have been read through myread() before myunrd() may be used.  After
  5074.  * EOF or read error, again, myunrd() can not be used.  Sometimes more than
  5075.  * one character can be pushed back, but only one character is guaranteed.
  5076.  * Since a previous myread() must have read its character out of mybuf[],
  5077.  * that guarantees that there is space for at least one character.  If push
  5078.  * back was really needed after EOF, a small addition could provide that.
  5079.  *
  5080.  * myunrd() is currently not called from anywhere inside kermit...
  5081.  */
  5082. #ifdef NOTUSED
  5083. myunrd(ch) CHAR ch; {
  5084.     if (my_item >= 0) {
  5085.     mybuf[my_item--] = ch;
  5086.     ++my_count;
  5087.     }
  5088. }
  5089. #endif
  5090.  
  5091. /* mygetbuf() -- Fill buffer for myread() and return first character.
  5092.  *
  5093.  * This function is what myread() uses when it can't get the next character
  5094.  * directly from its buffer.  First, it calls a system dependent myfillbuf()
  5095.  * to read at least one new character into the buffer, and then it returns
  5096.  * the first character just as myread() would have done.  This function also
  5097.  * is responsible for all error conditions that myread() can indicate.
  5098.  *
  5099.  * Returns: When OK    => a positive character, 0 or greater.
  5100.  *        When EOF    => -2.
  5101.  *        When error    => -3, error code in errno.
  5102.  *
  5103.  * Older myread()s additionally returned -1 to indicate that there was nothing
  5104.  * to read, upon which the caller would call myread() again until it got
  5105.  * something.  The new myread()/mygetbuf() always gets something.  If it 
  5106.  * doesn't, then make it do so!  Any program that actually depends on the old
  5107.  * behaviour will break.
  5108.  *
  5109.  * The older version also used to return -2 both for EOF and other errors,
  5110.  * and used to set errno to 9999 on EOF.  The errno stuff is gone, EOF and
  5111.  * other errors now return different results, although Kermit currently never
  5112.  * checks to see which it was.  It just disconnects in both cases.
  5113.  *
  5114.  * Kermit lets the user use the quit key to perform some special commands
  5115.  * during file transfer.  This causes read(), and thus also mygetbuf(), to
  5116.  * finish without reading anything and return the EINTR error.  This should
  5117.  * be checked by the caller.  Mygetbuf() could retry the read() on EINTR,
  5118.  * but if there is nothing to read, this could delay Kermit's reaction to
  5119.  * the command, and make Kermit appear unresponsive.
  5120.  *
  5121.  * The debug() call should be removed for optimum performance.
  5122.  */
  5123. int
  5124. mygetbuf() {
  5125.     errno = 0;
  5126.     my_count = myfillbuf();
  5127. #ifdef DEBUG
  5128.     if (deblog) debug(F101, "myfillbuf read", "", my_count);
  5129. #endif /* DEBUG */
  5130.     if (my_count <= 0) {
  5131.     debug(F101,"mygetbuf errno","",errno);
  5132. #ifdef TCPSOCKET
  5133.     if (netconn && ttnet == NET_TCPB && errno != 0) {
  5134.         if (errno != EINTR) {
  5135.         perror("TCP/IP");    /* Say why */
  5136.         ttclos(0);        /* Close the connection. */
  5137.         }
  5138.         return(-3);
  5139.     }
  5140. #endif /* TCPSOCKET */
  5141.     if (!netconn && xlocal && errno) {
  5142.         if (errno != EINTR) {
  5143.         perror("SERIAL");    /* Say why */
  5144.         ttclos(0);        /* Close the connection. */
  5145.         }
  5146.         return(-3);
  5147.     }
  5148.     /* Otherwise do what we used to do . . . */
  5149.     return(my_count < 0 ? -3 : -2);
  5150.     }
  5151.     --my_count;
  5152.     return((unsigned)(0xff & mybuf[my_item = 0]));
  5153. }
  5154.  
  5155. /* myfillbuf():
  5156.  * System-dependent read() into mybuf[], as many characters as possible.
  5157.  *
  5158.  * Returns: OK => number of characters read, always more than zero.
  5159.  *          EOF => 0
  5160.  *          Error => -1, error code in errno.
  5161.  *
  5162.  * If there is input available in the system's buffers, all of it should be
  5163.  * read into mybuf[] and the function return immediately.  If no input is
  5164.  * available, it should wait for a character to arrive, and return with that
  5165.  * one in mybuf[] as soon as possible.  It may wait somewhat past the first
  5166.  * character, but be aware that any such delay lengthens the packet turnaround
  5167.  * time during kermit file transfers.  Should never return with zero characters
  5168.  * unless EOF or irrecoverable read error.
  5169.  *
  5170.  * Correct functioning depends on the correct tty parameters being used.
  5171.  * Better control of current parameters is required than may have been the
  5172.  * case in older Kermit releases.  For instance, O_NDELAY (or equivalent) can 
  5173.  * no longer be sometimes off and sometimes on like it used to, unless a 
  5174.  * special myfillbuf() is written to handle that.  Otherwise the ordinary 
  5175.  * myfillbuf()s may think they have come to EOF.
  5176.  *
  5177.  * If your system has a facility to directly perform the functioning of
  5178.  * myfillbuf(), then use it.  If the system can tell you how many characters
  5179.  * are available in its buffers, then read that amount (but not less than 1).
  5180.  * If the system can return a special indication when you try to read without
  5181.  * anything to read, while allowing you to read all there is when there is
  5182.  * something, you may loop until there is something to read, but probably that
  5183.  * is not good for the system load.
  5184.  */
  5185.  
  5186. #ifdef SVORPOSIX
  5187.     /* This is for System III/V with VMIN>0, VTIME=0 and O_NDELAY off,
  5188.      * and CLOCAL set any way you like.  This way, read() will do exactly
  5189.      * what is required by myfillbuf(): If there is data in the buffers
  5190.      * of the O.S., all available data is read into mybuf, up to the size
  5191.      * of mybuf.  If there is none, the first character to arrive is
  5192.      * awaited and returned.
  5193.      */
  5194. int
  5195. myfillbuf() {
  5196. #ifdef sxaE50
  5197.     /* From S. Dezawa at Fujifilm in Japan.  I don't know why this is */
  5198.     /* necessary for the sxa E50, but it is. */
  5199.     return read(ttyfd, mybuf, 255);
  5200. #else
  5201. #ifdef BEBOX
  5202.     int n;
  5203.     while (1) {
  5204.         n = read(ttyfd, mybuf, sizeof(mybuf));
  5205.         if (n > 0) {
  5206.             debug(F101,"SVORPOSIX myfillbuf","",n);
  5207.             return(n);
  5208.         }
  5209.         snooze(1000.0);
  5210.     }
  5211. #else
  5212.     int n;
  5213.     n = read(ttyfd, mybuf, sizeof(mybuf));
  5214.     debug(F101,"SVORPOSIX myfillbuf","",n);
  5215.     return(n);
  5216. #endif /* BEBOX */
  5217. #endif /* sxaE50 */
  5218. }
  5219.  
  5220. #else /* not AT&T or POSIX */
  5221.  
  5222. #ifdef aegis
  5223.     /* This is quoted from the old myread().  The semantics seem to be
  5224.      * alright, but maybe errno would not need to be set even when
  5225.      * there is no error?  I don't know aegis.
  5226.      */
  5227. int
  5228. myfillbuf() {
  5229.     int count;
  5230.  
  5231.     count = ios_$get((short)ttyfd, ios_$cond_opt, mybuf, 256L, st);
  5232.     errno = EIO;
  5233.     if (st.all == ios_$get_conditional_failed) /* get at least one */
  5234.       count = ios_$get((short)ttyfd, 0, mybuf, 1L, st);
  5235.     if (st.all == ios_$end_of_file)
  5236.       return(0);
  5237.     else if (st.all != status_$ok) {
  5238.     errno = EIO;
  5239.     return(-1);
  5240.     }
  5241.     return(count);
  5242. }
  5243. #else /* !aegis */
  5244.  
  5245. #ifdef FIONREAD
  5246.     /* This is for systems with FIONREAD.  FIONREAD returns the number
  5247.      * of characters available for reading. If none are available, wait
  5248.      * until something arrives, otherwise return all there is.
  5249.      */
  5250. int
  5251. myfillbuf() {
  5252.     PEEKTYPE avail;
  5253.     int x;
  5254.  
  5255. #ifdef SUNX25
  5256. /*
  5257.   SunLink X.25 support in this routine from Stefaan A. Eeckels, Eurostat (CEC).
  5258.   Depends on SunOS having FIONREAD, not because we use it, but just so this
  5259.   code is grouped correctly within the #ifdefs.  Let's hope Solaris keeps it.
  5260.  
  5261.   We call x25xin() instead of read() so that Q-Bit packets, which contain
  5262.   X.25 service-level information (e.g. PAD parameter changes), can be processed
  5263.   transparently to the upper-level code.  This is a blocking read, and so
  5264.   we depend on higher-level code (such as ttinc()) to set any necessary alarms.
  5265. */    
  5266.     extern int nettype;
  5267.     if (netconn && nettype == NET_SX25) {
  5268.     while ((x = x25xin(sizeof(x25buf), x25buf)) < 1) ;
  5269.     return(x - 1);            /* "-1" compensates for extra status byte */
  5270.     }    
  5271. #endif /* SUNX25 */
  5272.  
  5273.     errno = 0;
  5274.     x = ioctl(ttyfd, FIONREAD, &avail);
  5275. #ifdef DEBUG
  5276.     if (deblog) {
  5277.     debug(F101,"myfillbuf FIONREAD","",x);
  5278.     debug(F101,"myfillbuf FIONREAD avail","",avail);
  5279.     debug(F101,"myfillbuf FIONREAD errno","",errno);
  5280.     }
  5281. #endif /* DEBUG */
  5282.     if (x < 0 || avail == 0)
  5283.       avail = 1;
  5284.  
  5285.     if (avail > MYBUFLEN)
  5286.       avail = MYBUFLEN;
  5287.  
  5288.     errno = 0;
  5289.     x = read(ttyfd, mybuf, (int) avail);
  5290. #ifdef DEBUG
  5291.     if (deblog) {
  5292.     debug(F101,"myfillbuf avail","",avail);
  5293.     debug(F101,"myfillbuf read","",x);
  5294.     debug(F101,"myfillbuf read errno","",errno);
  5295.     }
  5296. #endif /* DEBUG */
  5297.     return(x);
  5298. }
  5299.  
  5300. #else /* !FIONREAD */
  5301. /* Add other systems here, between #ifdef and #else, e.g. NETCONN. */
  5302. /* When there is no other possibility, read 1 character at a time. */
  5303. int
  5304. myfillbuf() {
  5305.     return read(ttyfd, mybuf, 1);
  5306. }
  5307.  
  5308. #endif /* !FIONREAD */
  5309. #endif /* !aegis */
  5310. #endif /* !ATTSV */
  5311.  
  5312. #endif /* MYREAD */
  5313.  
  5314. /*  T T F L U I  --  Flush tty input buffer */
  5315.  
  5316. int
  5317. ttflui() {
  5318. #ifdef BSD44
  5319.     int n;
  5320. #endif /* BSD44 */
  5321. #ifndef SVORPOSIX
  5322.     int n;
  5323. #endif /* SVORPOSIX */
  5324. #ifdef Plan9
  5325.     int n;
  5326. #endif /* Plan9 */
  5327.  
  5328. #ifdef MYREAD
  5329. /*
  5330.   Flush internal MYREAD buffer *FIRST*, in all cases.
  5331. */
  5332.     my_count = 0;            /* Reset count to zero */
  5333.     my_item = -1;            /* And buffer index to -1 */
  5334. #endif /* MYREAD */
  5335.  
  5336. #ifdef NETCONN
  5337. /*
  5338.   Network flush is done specially, in the network support module.
  5339. */
  5340.     debug(F100,"ttflui netflui","",0);
  5341.     if (netconn) return(netflui());
  5342. #endif /* NETCONN */
  5343.  
  5344.     debug(F101,"ttflui ttyfd","",ttyfd);
  5345.     if (ttyfd < 0) return(-1);
  5346.  
  5347. #ifdef aegis
  5348.     sio_$control((short)ttyfd, sio_$flush_in, true, st);
  5349.     if (st.all != status_$ok) {
  5350.     fprintf(stderr, "flush failed: "); error_$print(st);
  5351.     } else {      /* sometimes the flush doesn't work */
  5352.         for (;;) {
  5353.         char buf[256];
  5354.             /* eat all the characters that shouldn't be available */
  5355.             ios_$get((short)ttyfd, ios_$cond_opt, buf, 256L, st); /* (void) */
  5356.             if (st.all == ios_$get_conditional_failed) break;
  5357.             fprintf(stderr, "flush failed(2): "); error_$print(st);
  5358.         }
  5359.     }
  5360. #else
  5361. #ifdef BSD44                /* 4.4 BSD */
  5362.     n = FREAD;                          /* Specify read queue */
  5363.     debug(F100,"ttflui BSD44","",0);
  5364.     ioctl(ttyfd,TIOCFLUSH,&n);
  5365. #else
  5366. #ifdef Plan9
  5367. #undef POSIX                /* Uh oh... */
  5368. #endif /* Plan9 */
  5369. #ifdef POSIX                /* POSIX */
  5370.     debug(F100,"ttflui POSIX","",0);
  5371.     tcflush(ttyfd,TCIFLUSH);
  5372. #else
  5373. #ifdef ATTSV                /* System V */
  5374. #ifndef VXVE
  5375.     debug(F100,"ttflui ATTSV","",0);
  5376.     ioctl(ttyfd,TCFLSH,0);
  5377. #endif /* VXVE */
  5378. #else                    /* Not BSD44, POSIX, or Sys V */
  5379. #ifdef TIOCFLUSH            /* Those with TIOCFLUSH defined */
  5380. #ifdef ANYBSD                /* Berkeley */
  5381.     n = FREAD;                          /* Specify read queue */
  5382.     debug(F100,"ttflui TIOCFLUSH ANYBSD","",0);
  5383.     ioctl(ttyfd,TIOCFLUSH,&n);
  5384. #else                    /* Others (V7, etc) */
  5385.     debug(F100,"ttflui TIOCFLUSH","",0);
  5386.     ioctl(ttyfd,TIOCFLUSH,0);
  5387. #endif /* ANYBSD */
  5388. #else                    /* All others... */
  5389. /*
  5390.   No system call (that we know about) for input buffer flushing.
  5391.   So see how many there are and read them in a loop, using ttinc().
  5392.   ttinc() is buffered, so we're not getting charged with a system call 
  5393.   per character, just a function call.
  5394. */
  5395.     if ((n = ttchk()) > 0) {
  5396.     debug(F101,"ttflui read loop","",n);
  5397.     while ((n--) && ttinc(0) > 0) ;
  5398.     }
  5399. #endif /* TIOCFLUSH */
  5400. #endif /* ATTSV */
  5401. #endif /* POSIX */
  5402. #ifdef Plan9
  5403. #define POSIX
  5404. #endif /* Plan9 */
  5405. #endif /* BSD44 */
  5406. #endif /* aegis */
  5407.     return(0);
  5408. }
  5409.  
  5410. void
  5411. ttflux() {
  5412. #ifdef MYREAD
  5413. /*
  5414.   Flush internal MYREAD buffer.
  5415. */
  5416.     my_count = 0;            /* Reset count to zero */
  5417.     my_item = -1;            /* And buffer index to -1 */
  5418. #endif /* MYREAD */
  5419. }
  5420.  
  5421. int
  5422. ttfluo() {                /* Flush output buffer */
  5423. #ifdef Plan9
  5424.     return 0;
  5425. #else
  5426. #ifdef POSIX
  5427.     return(tcflush(ttyfd,TCOFLUSH));
  5428. #else
  5429. #ifdef OXOS
  5430.     return(ioctl(ttyfd,TCFLSH,1));
  5431. #else
  5432.     return(0);                /* All others, nothing */
  5433. #endif /* OXOS */
  5434. #endif /* POSIX */
  5435. #endif /* Plan9 */
  5436. }
  5437.  
  5438. /* Interrupt Functions */
  5439.  
  5440. /* Set up terminal interrupts on console terminal */
  5441.  
  5442. #ifndef FIONREAD            /* We don't need esctrp() */
  5443. #ifndef SELECT                /* if we have any of these... */
  5444. #ifndef CK_POLL
  5445. #ifndef RDCHK
  5446.  
  5447. #ifndef OXOS
  5448. #ifdef SVORPOSIX
  5449. SIGTYP
  5450. esctrp(foo) int foo; {            /* trap console escapes (^\) */
  5451.     signal(SIGQUIT,SIG_IGN);            /* ignore until trapped */
  5452.     conesc = 1;
  5453.     debug(F101,"esctrp caught SIGQUIT","",conesc);
  5454. }
  5455. #endif /* SVORPOSIX */
  5456. #endif /* OXOS */
  5457.  
  5458. #ifdef V7
  5459. SIGTYP
  5460. esctrp(foo) int foo; {            /* trap console escapes (^\) */
  5461.     signal(SIGQUIT,SIG_IGN);            /* ignore until trapped */
  5462.     conesc = 1;
  5463.     debug(F101,"esctrp caught SIGQUIT","",conesc);
  5464. }
  5465. #endif /* V7 */
  5466.  
  5467. #ifdef C70
  5468. SIGTYP
  5469. esctrp(foo) int foo; {            /* trap console escapes (^\) */
  5470.     conesc = 1;
  5471.     signal(SIGQUIT,SIG_IGN);            /* ignore until trapped */
  5472. }
  5473. #endif /* C70 */
  5474.  
  5475. #endif /* RDCHK */
  5476. #endif /* CK_POLL */
  5477. #endif /* SELECT */
  5478. #endif /* FIONREAD */
  5479.  
  5480. /*  C O N B G T  --  Background Test  */
  5481.  
  5482. static int jc = 0;            /* 0 = no job control */
  5483.  
  5484. /*
  5485.   Call with flag == 1 to prevent signal test, which can not be expected
  5486.   to work during file transfer, when SIGINT probably *is* set to SIG_IGN.  
  5487.  
  5488.   Call with flag == 0 to use the signal test, but only if the process-group
  5489.   test fails, as it does on some UNIX systems, where getpgrp() is buggy,
  5490.   requires an argument when the man page says it doesn't, or vice versa.
  5491.  
  5492.   If flag == 0 and the process-group test fails, then we determine background
  5493.   status simply (but not necessarily reliably) from isatty().
  5494.  
  5495.   conbgt() sets the global backgrd = 1 if we appear to be in the background,
  5496.   and to 0 if we seem to be in the foreground.  conbgt() is highly prone to
  5497.   misbehavior.
  5498. */
  5499. VOID
  5500. conbgt(flag) int flag; {
  5501.     int x = -1,                /* process group or SIGINT test */
  5502.         y = 0;                /* isatty() test */
  5503. /*
  5504.   Check for background operation, even if not running on real tty, so that
  5505.   background flag can be set correctly.  If background status is detected,
  5506.   then Kermit will not issue its interactive prompt or most messages.
  5507.   If your prompt goes away, you can blame (and fix?) this function.
  5508. */
  5509.  
  5510. /* Use process-group test if possible. */
  5511.  
  5512. #ifdef POSIX                /* We can do it in POSIX */
  5513. #define PGROUP_T
  5514. #else
  5515. #ifdef BSD4                /* and in BSD 4.x. */
  5516. #define PGROUP_T
  5517. #else
  5518. #ifdef HPUXJOBCTL            /* and in most HP-UX's */
  5519. #define PGROUP_T
  5520. #else
  5521. #ifdef TIOCGPGRP            /* and anyplace that has this ioctl. */
  5522. #define PGROUP_T
  5523. #endif /* TIOCGPGRP */
  5524. #endif /* HPUXJOBCTL */
  5525. #endif /* BSD4 */
  5526. #endif /* POSIX */
  5527.  
  5528. #ifdef MIPS                /* Except if it doesn't work... */
  5529. #undef PGROUP_T
  5530. #endif /* MIPS */
  5531.  
  5532. #ifdef PGROUP_T
  5533. /*
  5534.   Semi-reliable process-group test.  Check whether this process's group is
  5535.   the same as the controlling terminal's process group.  This works if the
  5536.   getpgrp() call doesn't lie (as it does in the SUNOS System V environment).
  5537. */
  5538.     PID_T mypgrp = (PID_T)0;        /* Kermit's process group */
  5539.     PID_T ctpgrp = (PID_T)0;        /* The terminal's process group */
  5540. #ifndef _POSIX_SOURCE
  5541. /*
  5542.   The getpgrp() prototype is obtained from system header files for POSIX 
  5543.   and Sys V R4 compilations.  Other systems, who knows.  Some complain about
  5544.   a duplicate declaration here, others don't, so it's safer to leave it in
  5545.   if we don't know for certain.
  5546. */
  5547. #ifndef SVR4
  5548. #ifndef PS2AIX10
  5549.     extern PID_T getpgrp();
  5550. #endif /* PS2AIX10 */
  5551. #endif /* SVR4 */
  5552. #endif /* _POSIX_SOURCE */
  5553.  
  5554. /* Get my process group. */
  5555.  
  5556. #ifdef SVR3 /* Maybe this should be ATTSV? */
  5557. /* This function is not described in SVID R2 */
  5558.     mypgrp = getpgrp();
  5559.     debug(F101,"ATTSV conbgt process group","",(int) mypgrp);
  5560. #else
  5561. #ifdef POSIX
  5562.     mypgrp = getpgrp();
  5563.     debug(F101,"POSIX conbgt process group","",(int) mypgrp);
  5564. #else
  5565. #ifdef OSFPC
  5566.     mypgrp = getpgrp();
  5567.     debug(F101,"OSF conbgt process group","",(int) mypgrp);
  5568. #else
  5569. #ifdef QNX
  5570.     mypgrp = getpgrp();
  5571.     debug(F101,"QNX conbgt process group","",(int) mypgrp);
  5572. #else
  5573. #ifdef OSF40
  5574.     mypgrp = getpgrp();
  5575.     debug(F101,"Digital UNIX 4.0 conbgt process group","",(int) mypgrp);
  5576. #else /* BSD, V7, etc */
  5577.     mypgrp = getpgrp(0);
  5578.     debug(F101,"BSD conbgt process group","",(int) mypgrp);
  5579. #endif /* OSF40 */
  5580. #endif /* QNX */
  5581. #endif /* OSFPC */
  5582. #endif /* POSIX */
  5583. #endif /* SVR3 */
  5584.  
  5585. /* Now get controlling tty's process group */
  5586. #ifdef BSD44ORPOSIX
  5587.     ctpgrp = tcgetpgrp(1);        /* The POSIX way */
  5588.     debug(F101,"POSIX conbgt terminal process group","",(int) ctpgrp);
  5589. #else
  5590.     ioctl(1, TIOCGPGRP, &ctpgrp);    /* Or the BSD way */
  5591.     debug(F101,"non-POSIX conbgt terminal process group","",(int) ctpgrp);
  5592. #endif /* BSD44ORPOSIX */
  5593.  
  5594.     if ((mypgrp > (PID_T) 0) && (ctpgrp > (PID_T) 0))
  5595.       x = (mypgrp == ctpgrp) ? 0 : 1;    /* If they differ, then background. */
  5596.     else x = -1;            /* If error, remember. */
  5597.     debug(F101,"conbgt process group test","",x);
  5598. #endif /* PGROUP_T */
  5599.  
  5600. /* Try to see if job control is available */
  5601.  
  5602. #ifdef NOJC                /* User override */
  5603.     jc = 0;                /* No job control allowed */
  5604.     debug(F111,"NOJC","jc",jc);
  5605. #else
  5606. #ifdef BSD44
  5607.     jc = 1;
  5608. #else
  5609. #ifdef SVR4ORPOSIX            /* POSIX actually tells us */
  5610.     debug(F100,"SVR4ORPOSIX jc test...","",0);
  5611. #ifdef _SC_JOB_CONTROL
  5612. #ifdef __bsdi__
  5613.     jc = 1;
  5614. #else
  5615. #ifdef __386BSD__
  5616.     jc = 1;
  5617. #else
  5618.     jc = sysconf(_SC_JOB_CONTROL);    /* Whatever system says */
  5619.     if (jc < 0) {
  5620.     debug(F101,"sysconf fails, jcshell","",jcshell);
  5621.     jc = (jchdlr == SIG_DFL) ? 1 : 0;
  5622.     } else
  5623.       debug(F111,"sysconf(_SC_JOB_CONTROL)","jc",jc);
  5624. #endif /* __386BSD__ */
  5625. #endif /* __bsdi__ */
  5626. #else
  5627. #ifdef _POSIX_JOB_CONTROL
  5628.     jc = 1;                /* By definition */
  5629.     debug(F111,"_POSIX_JOB_CONTROL is defined","jc",jc);
  5630. #else
  5631.     jc = 0;                /* Assume job control not allowed */
  5632.     debug(F111,"SVR4ORPOSIX _SC/POSIX_JOB_CONTROL not defined","jc",jc);
  5633. #endif /* _POSIX_JOB_CONTROL */
  5634. #endif /* _SC_JOB_CONTROL */
  5635. #else
  5636. #ifdef BSD4
  5637.     jc = 1;                /* Job control allowed */
  5638.     debug(F111,"BSD job control","jc",jc);
  5639. #else
  5640. #ifdef SVR3JC
  5641.     jc = 1;                /* JC allowed */
  5642.     debug(F111,"SVR3 job control","jc",jc);
  5643. #else
  5644. #ifdef OXOS
  5645.     jc = 1;                /* JC allowed */
  5646.     debug(F111,"X/OS job control","jc",jc);
  5647. #else
  5648. #ifdef HPUX9
  5649.     jc = 1;                /* JC allowed */
  5650.     debug(F111,"HP-UX 9.0 job control","jc",jc);
  5651. #else
  5652. #ifdef HPUX9
  5653.     jc = 1;                /* JC allowed */
  5654.     debug(F111,"HP-UX 10.0 job control","jc",jc);
  5655. #else
  5656.     jc = 0;                /* JC not allowed */
  5657.     debug(F111,"job control catch-all","jc",jc);
  5658. #endif /* HPUX10 */
  5659. #endif /* HPUX9 */
  5660. #endif /* OXOS */
  5661. #endif /* SVR3JC */
  5662. #endif /* BSD4 */
  5663. #endif /* SVR4ORPOSIX */
  5664. #endif /* BSD44 */
  5665. #endif /* NOJC */
  5666.     debug(F101,"conbgt jc","",jc);
  5667. #ifndef NOJC
  5668.     debug(F101,"conbgt jcshell","",jcshell);
  5669. /*
  5670.   At this point, if jc == 1 but jcshell == 0, it means that the OS supports
  5671.   job control, but the shell or other process we are running under does not
  5672.   (jcshell is set in sysinit()) and so if we suspend ourselves, nothing good
  5673.   will come of it.  So...
  5674. */
  5675.     if (jc < 0) jc = 0;
  5676.     if (jc > 0 && jcshell == 0) jc = 0;
  5677. #endif /* NOJC */
  5678.  
  5679. /*
  5680.   Another background test.
  5681.   Test if SIGINT (terminal interrupt) is set to SIG_IGN (ignore),
  5682.   which is done by the shell (sh) if the program is started with '&'.
  5683.   Unfortunately, this is NOT done by csh or ksh so watch out!
  5684.   Note, it's safe to set SIGINT to SIG_IGN here, because further down
  5685.   we always set it to something else.
  5686. */
  5687.     if (x < 0 && !flag) {        /* Didn't get good results above... */
  5688.  
  5689.     SIGTYP (*osigint)();
  5690.  
  5691.     osigint = signal(SIGINT,SIG_IGN);    /* What is SIGINT set to? */
  5692.     x = (osigint == SIG_IGN) ? 1 : 0;    /* SIG_IGN? */
  5693.     debug(F101,"conbgt osigint","",osigint);
  5694.     debug(F101,"conbgt signal test","",x);
  5695.     }
  5696.  
  5697. /* Also check to see if we're running with redirected stdio. */
  5698. /* This is not really background operation, but we want to act as though */
  5699. /* it were. */
  5700.  
  5701.     y = (isatty(0) && isatty(1)) ? 1 : 0;
  5702.     debug(F101,"conbgt isatty test","",y);
  5703.  
  5704. #ifdef BSD29
  5705. /* The process group and/or signal test doesn't work under these... */
  5706.     backgrd = !y;
  5707. #else
  5708. #ifdef sxaE50
  5709.     backgrd = !y;
  5710. #else
  5711. #ifdef MINIX
  5712.     backgrd = !y;
  5713. #else
  5714.     if (x > -1)
  5715.       backgrd = (x || !y) ? 1 : 0;
  5716.     else backgrd = !y;
  5717. #endif /* BSD29 */
  5718. #endif /* sxaE50 */
  5719. #endif /* MINIX */
  5720.     debug(F101,"conbgt backgrd","",backgrd);
  5721. }
  5722.  
  5723. /*  C O N I N T  --  Console Interrupt setter  */
  5724.  
  5725. /*
  5726.   First arg is pointer to function to handle SIGTERM & SIGINT (like Ctrl-C).
  5727.   Second arg is pointer to function to handle SIGTSTP (suspend).
  5728. */
  5729.  
  5730. VOID                    /* Set terminal interrupt traps. */
  5731. #ifdef CK_ANSIC
  5732. #ifdef apollo
  5733. conint(f,s) SIGTYP (*f)(), (*s)();
  5734. #else
  5735. conint(SIGTYP (*f)(int), SIGTYP (*s)(int))
  5736. #endif /* apollo */
  5737. #else
  5738. conint(f,s) SIGTYP (*f)(), (*s)();
  5739. #endif /* CK_ANSIC */
  5740. /* conint */ {
  5741.  
  5742.     conbgt(0);                /* Do background test. */
  5743.  
  5744. /* Set the desired handlers for hangup and software termination. */
  5745.  
  5746.     signal(SIGTERM,f);                  /* Software termination */
  5747.  
  5748. #ifdef COMMENT
  5749. /*
  5750.   Prior to edit 184, we used to trap SIGHUP here.  That is clearly wrong;
  5751.   on some systems, it would leave the user's process on the terminal after
  5752.   the phone hung up.  But the trap was here for a reason: most likely some
  5753.   UNIX systems (init, getty, or login) fail to properly restore the terminal
  5754.   modes after regaining control of a hung-up-upon login terminal.  Therefore
  5755.   removing this trap is likely to cause problems too.  A more sensible
  5756.   approach would be to use a special handler for HANGUP, which would restore
  5757.   the terminal modes and then exit().  But that could leave zombie processes
  5758.   around (like the lower CONNECT fork, or any fork started by zxcmd()), but
  5759.   there is probably no clean, portable, reliable way for Kermit to kill all
  5760.   its forks.  So we just exit() and hope that UNIX fixes the terminal modes
  5761.   before the next person tries to log in.
  5762. */
  5763.     signal(SIGHUP,f);                   /* Hangup */
  5764. #endif /* COMMENT */
  5765.  
  5766. /* Now handle keyboard stop, quit, and interrupt signals. */
  5767. /* Check if invoked in background -- if so signals set to be ignored. */
  5768. /* However, if running under a job control shell, don't ignore them. */
  5769. /* We won't be getting any, as we aren't in the terminal's process group. */
  5770.  
  5771.     debug(F101,"conint backgrd","",backgrd);
  5772.     debug(F101,"conint jc","",jc);
  5773.  
  5774.     if (backgrd && !jc) {        /* In background, ignore signals */
  5775.     debug(F101,"conint background ignoring signals, jc","",jc);
  5776. #ifdef SIGTSTP
  5777.         signal(SIGTSTP,SIG_IGN);        /* Keyboard stop */
  5778. #endif /* SIGTSTP */
  5779.         signal(SIGQUIT,SIG_IGN);        /* Keyboard quit */
  5780.         signal(SIGINT,SIG_IGN);         /* Keyboard interrupt */
  5781.     } else {                /* Else in foreground or suspended */
  5782.     debug(F101,"conint foreground catching signals, jc","",jc);
  5783.         signal(SIGINT,f);               /* Catch terminal interrupt */
  5784.  
  5785. #ifdef SIGTSTP                /* Keyboard stop (suspend) */
  5786.     debug(F101,"conint SIGSTSTP","",s);
  5787.     if (s == NULL) s = SIG_DFL;
  5788. #ifdef NOJC                /* No job control allowed. */
  5789.     signal(SIGTSTP,SIG_IGN);
  5790. #else                    /* Job control allowed */
  5791.     if (jc)                /* if available. */
  5792.       signal(SIGTSTP,s);
  5793.     else
  5794.       signal(SIGTSTP,SIG_IGN);
  5795. #endif /* NOJC */
  5796. #endif /* SIGTSTP */
  5797.  
  5798. #ifndef OXOS
  5799. #ifdef SVORPOSIX
  5800. #ifndef FIONREAD            /* Watch out, we don't know this... */
  5801. #ifndef SELECT
  5802. #ifndef CK_POLL
  5803. #ifndef RDCHK
  5804.         signal(SIGQUIT,esctrp);         /* Quit signal, Sys III/V. */
  5805. #endif /* RDCHK */
  5806. #endif /* CK_POLL */
  5807. #endif /* SELECT */
  5808. #endif /* FIONREAD */
  5809.         if (conesc) conesc = 0;         /* Clear out pending escapes */
  5810. #else
  5811. #ifdef V7
  5812.         signal(SIGQUIT,esctrp);         /* V7 like Sys III/V */
  5813.         if (conesc) conesc = 0;
  5814. #else
  5815. #ifdef aegis
  5816.         signal(SIGQUIT,f);              /* Apollo, catch it like others. */
  5817. #else
  5818.         signal(SIGQUIT,SIG_IGN);        /* Others, ignore like 4D & earlier. */
  5819. #endif /* aegis */
  5820. #endif /* V7 */
  5821. #endif /* SVORPOSIX */
  5822. #endif /* OXOS */
  5823.     }
  5824. }
  5825.  
  5826.  
  5827. /*  C O N N O I  --  Reset console terminal interrupts */
  5828.  
  5829. SIGTYP                    /* Dummy function to ignore signals */
  5830. #ifdef CK_ANSIC
  5831. sig_ign(int foo)
  5832. #else
  5833. sig_ign(foo) int foo;
  5834. #endif /* CK_ANSIC */
  5835. /* sig_IGN */ {                /* Just like the real one, but has  */
  5836. }                    /* different address. */
  5837.  
  5838. VOID
  5839. connoi() {                              /* Console-no-interrupts */
  5840.  
  5841.     debug(F100,"connoi","",0);
  5842. #ifdef SIGTSTP
  5843.     signal(SIGTSTP,SIG_DFL);
  5844. #endif /* SIGTSTP */
  5845.     /* Note the locally defined replacement for SIG_IGN that is used here */
  5846.     /* for the SIGINT setting.  This is done so that the Sys V background */
  5847.     /* test -- (signal(SIGINT,SIG_IGN) == SIG_IGN) -- can work.  If we use */
  5848.     /* the real SIG_IGN here, then conint will always decide that this */ 
  5849.     /* program is running in the background! */
  5850.  
  5851.     signal(SIGINT,sig_ign);        /* <--- note! */
  5852.  
  5853.     signal(SIGHUP,SIG_DFL);
  5854.     signal(SIGQUIT,SIG_IGN);
  5855.     signal(SIGTERM,SIG_IGN);
  5856. }
  5857.  
  5858. /*  I N I T R A W Q  --  Set up to read /dev/kmem for character count.  */
  5859.  
  5860. #ifdef  V7
  5861. /*
  5862.  Used in Version 7 to simulate Berkeley's FIONREAD ioctl call.  This
  5863.  eliminates blocking on a read, because we can read /dev/kmem to get the
  5864.  number of characters available for raw input.  If your system can't
  5865.  or you won't let the world read /dev/kmem then you must figure out a
  5866.  different way to do the counting of characters available, or else replace
  5867.  this by a dummy function that always returns 0.
  5868. */
  5869. /*
  5870.  * Call this routine as: initrawq(tty)
  5871.  * where tty is the file descriptor of a terminal.  It will return
  5872.  * (as a char *) the kernel-mode memory address of the rawq character
  5873.  * count, which may then be read.  It has the side-effect of flushing
  5874.  * input on the terminal.
  5875.  */
  5876. /*
  5877.  * John Mackin, Physiology Dept., University of Sydney (Australia)
  5878.  * ...!decvax!mulga!physiol.su.oz!john
  5879.  *
  5880.  * Permission is hereby granted to do anything with this code, as
  5881.  * long as this comment is retained unmodified and no commercial
  5882.  * advantage is gained.
  5883.  */
  5884. #ifndef MINIX
  5885. #ifndef COHERENT
  5886. #include <a.out.h>
  5887. #include <sys/proc.h>
  5888. #endif /* COHERENT */
  5889. #endif /* MINIX */
  5890.  
  5891. #ifdef COHERENT
  5892. #include <l.out.h>
  5893. #include <sys/proc.h>
  5894. #endif /* COHERENT */
  5895.  
  5896. char *
  5897. initrawq(tty) int tty; {
  5898. #ifdef MINIX
  5899.     return(0);
  5900. #else
  5901. #ifdef UTS24
  5902.     return(0);
  5903. #else
  5904. #ifdef BSD29
  5905.     return(0);
  5906. #else
  5907.     long lseek();
  5908.     static struct nlist nl[] = {
  5909.         {PROCNAME},
  5910.         {NPROCNAME},
  5911.         {""}
  5912.     };
  5913.     static struct proc *pp;
  5914.     char *qaddr, *p, c;
  5915.     int m;
  5916.     PID_T pid, me;
  5917.     NPTYPE xproc;                       /* Its type is defined in makefile. */
  5918.     int catch();
  5919.  
  5920.     me = getpid();
  5921.     if ((m = open("/dev/kmem", 0)) < 0) err("kmem");
  5922.     nlist(BOOTNAME, nl);
  5923.     if (nl[0].n_type == 0) err("proc array");
  5924.  
  5925.     if (nl[1].n_type == 0) err("nproc");
  5926.  
  5927.     lseek(m, (long)(nl[1].n_value), 0);
  5928.     read (m, &xproc, sizeof(xproc));
  5929.     saval = signal(SIGALRM, catch);
  5930.     if ((pid = fork()) == 0) {
  5931.         while(1)
  5932.             read(tty, &c, 1);
  5933.     }
  5934.     alarm(2);
  5935.  
  5936.     if(setjmp(jjbuf) == 0) {
  5937.         while(1)
  5938.       read(tty, &c, 1);
  5939.     }
  5940.     signal(SIGALRM, SIG_DFL);
  5941.  
  5942. #ifdef DIRECT
  5943.     pp = (struct proc *) nl[0].n_value;
  5944. #else
  5945.     if (lseek(m, (long)(nl[0].n_value), 0) < 0L) err("seek");
  5946.     if (read(m, &pp, sizeof(pp)) != sizeof(pp))  err("no read of proc ptr");
  5947. #endif
  5948.     lseek(m, (long)(nl[1].n_value), 0);
  5949.     read(m, &xproc, sizeof(xproc));
  5950.  
  5951.     if (lseek(m, (long)pp, 0) < 0L) err("Can't seek to proc");
  5952.     if ((p = malloc(xproc * sizeof(struct proc))) == NULL) err("malloc");
  5953.     if (read(m,p,xproc * sizeof(struct proc)) != xproc*sizeof(struct proc))
  5954.         err("read proc table");
  5955.     for (pp = (struct proc *)p; xproc > 0; --xproc, ++pp) {
  5956.         if (pp -> p_pid == (short) pid) goto iout;
  5957.     }
  5958.     err("no such proc");
  5959.  
  5960. iout:
  5961.     close(m);
  5962.     qaddr = (char *)(pp -> p_wchan);
  5963.     free (p);
  5964.     kill(pid, SIGKILL);
  5965.     wait((WAIT_T *)0);
  5966.     return (qaddr);
  5967. #endif
  5968. #endif
  5969. #endif
  5970. }
  5971.  
  5972. /*  More V7-support functions...  */
  5973.  
  5974. static VOID
  5975. err(s) char *s; {
  5976.     char buf[200];
  5977.  
  5978.     sprintf(buf, "fatal error in initrawq: %s", s);
  5979.     perror(buf);
  5980.     doexit(1,-1);
  5981. }
  5982.  
  5983. static VOID
  5984. catch(foo) int foo; {
  5985.     longjmp(jjbuf, -1);
  5986. }
  5987.  
  5988.  
  5989. /*  G E N B R K  --  Simulate a modem break.  */
  5990.  
  5991. #ifdef MINIX
  5992. #define BSPEED B110
  5993. #else
  5994. #define BSPEED B150
  5995. #endif /* MINIX */
  5996.  
  5997. VOID
  5998. genbrk(fn,msec) int fn, msec; {
  5999.     struct sgttyb ttbuf;
  6000.     int ret, sospeed, x, y;
  6001.  
  6002.     ret = ioctl(fn, TIOCGETP, &ttbuf);
  6003.     sospeed = ttbuf.sg_ospeed;
  6004.     ttbuf.sg_ospeed = BSPEED;
  6005.     ret = ioctl(fn, TIOCSETP, &ttbuf);
  6006.     y = (int)strlen(brnuls);
  6007.     x = ( BSPEED * 100 ) / msec;
  6008.     if (x > y) x = y;
  6009.     ret = write(fn, brnuls, (( BSPEED * 100 ) / msec ));
  6010.     ttbuf.sg_ospeed = sospeed;
  6011.     ret = ioctl(fn, TIOCSETP, &ttbuf);
  6012.     ret = write(fn, "@", 1);
  6013.     return;
  6014. }
  6015. #endif /* V7 */
  6016.  
  6017. /*
  6018.   I N C H K  --  Check if chars waiting to be read on given file descriptor.
  6019.   Returns number of characters waiting, 0 or greater.
  6020.  
  6021.   This routine is a merger of ttchk() and conchk().
  6022.   Conchk calls it with 0; ttchk() calls it with ttyfd.
  6023. */
  6024. static int
  6025. in_chk(fd) int fd; {
  6026.     int x, n = 0;            /* Return value */
  6027.  
  6028.     if (fd < 0) return(0);
  6029.  
  6030. #ifdef FIONREAD
  6031.     x = ioctl(fd, FIONREAD, &n);    /* BSD and hopefully others */
  6032.     debug(F101,"in_chk FIONREAD return code","",x);
  6033.     debug(F101,"in_chk FIONREAD count","",n);
  6034. #else /* FIONREAD not defined */
  6035. #ifdef  V7
  6036. #ifdef MINIX
  6037.     n = 0;
  6038. #else
  6039.     lseek(kmem[TTY], (long) qaddr[TTY], 0); /* 7th Edition Unix */
  6040.     x = read(kmem[TTY], &n, sizeof(int));
  6041.     if (x != sizeof(int)) n = 0;
  6042. #endif /* MINIX */
  6043. #else /* Not V7 */
  6044. #ifdef PROVX1
  6045.     x = ioctl(fd, TIOCQCNT, &ttbuf);    /* DEC Pro/3xx Venix V.1 */
  6046.     n = ttbuf.sg_ispeed & 0377;
  6047.     if (x < 0) n = 0;
  6048. #else
  6049. #ifdef RDCHK                /* This mostly SCO-specific */
  6050.     n = rdchk(fd);
  6051.     debug(F101,"in_chk rdchk","",n);
  6052. #else /* No RDCHK */
  6053. #ifdef SELECT
  6054. #ifdef Plan9
  6055.     /* only allow select on the console ... don't ask */
  6056.     if (fd == 0 && ttyfd != 0)
  6057. #endif /* Plan9 */
  6058.       {
  6059.     fd_set rfds;            /* Read file descriptors */
  6060. #ifdef BELLV10
  6061.     FD_ZERO(rfds);            /* Initialize them */
  6062.     FD_SET(fd,rfds);        /* We want to look at this fd */
  6063. #else
  6064.     FD_ZERO(&rfds);            /* Initialize them */
  6065.     FD_SET(fd,&rfds);        /* We want to look at this fd */
  6066.     tv.tv_sec = tv.tv_usec = 0L;    /* A 0-valued timeval structure */
  6067. #endif /* BELLV10 */
  6068. #ifdef Plan9
  6069.     n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
  6070. #else
  6071. #ifdef BELLV10
  6072.     n = select( 128, rfds, (fd_set *)0, (fd_set *)0, 0 );
  6073. #else
  6074. #ifdef BSD44
  6075.     n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
  6076. #else
  6077. #ifdef BSD43
  6078.     n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
  6079. #else
  6080. #ifdef SOLARIS
  6081.     n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
  6082. #else
  6083. #ifdef QNX
  6084.     n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
  6085. #else
  6086. #ifdef COHERENT
  6087.     n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
  6088. #else
  6089. #ifdef SVR4
  6090.     n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
  6091. #else
  6092.     n = select( FD_SETSIZE, &rfds, (int *)0, (int *)0, &tv );
  6093. #endif /* SVR4 */
  6094. #endif /* COHERENT */
  6095. #endif /* QNX */
  6096. #endif /* SOLARIS */
  6097. #endif /* BSD43 */
  6098. #endif /* BSD44 */
  6099. #endif /* BELLV10 */
  6100. #endif /* Plan9 */
  6101.     debug(F101,"in_chk select n","",n);
  6102.     }
  6103. #else  /* Not SELECT */
  6104. #ifdef CK_POLL
  6105.     {
  6106.       struct pollfd pfd;
  6107.  
  6108.       pfd.fd = fd;
  6109.       pfd.events = POLLIN;
  6110.       pfd.revents = 0;
  6111.       n = poll(&pfd, 1, 0);
  6112.       debug(F101,"in_chk poll","",n);
  6113.       if ((n > 0) && (pfd.revents & POLLIN))
  6114.     n = 1;
  6115.     }
  6116. #endif /* CK_POLL */
  6117. #endif /* SELECT */
  6118. #endif /* RDCHK */
  6119. #endif /* PROVX1 */
  6120. #endif /* V7 */
  6121. #endif /* FIONREAD */
  6122.  
  6123. /* From here down, treat console and communication device differently... */
  6124.  
  6125.     if (fd == 0 && ttyfd != 0) {    /* Console */
  6126.  
  6127. #ifdef SVORPOSIX
  6128. #ifndef FIONREAD
  6129. #ifndef SELECT
  6130. #ifndef CK_POLL
  6131. #ifndef RDCHK
  6132. /*
  6133.   This is the hideous hack used in System V and POSIX systems that don't
  6134.   support FIONREAD, rdchk(), select(), poll(), etc, in which the user's
  6135.   CONNECT-mode escape character is attached to SIGQUIT.  Used, obviously,
  6136.   only on the console.
  6137. */
  6138.     if (conesc) {            /* Escape character typed == SIGQUIT */
  6139.         debug(F100,"in_chk conesc","",conesc);
  6140.         conesc = 0;
  6141.         signal(SIGQUIT,esctrp);    /* Restore signal */
  6142.         n += 1;
  6143.     }
  6144. #endif /* RDCHK */
  6145. #endif /* CK_POLL */
  6146. #endif /* SELECT */
  6147. #endif /* FIONREAD */
  6148. #endif /* SVORPOSIX */
  6149.  
  6150.     return(n);            /* Done with console */
  6151.     }
  6152.  
  6153. /* Communications device, might also have stuff buffered. */
  6154.  
  6155. #ifdef MYREAD
  6156. /*
  6157.   For myread() users, add the contents of myread()'s private buffer.
  6158.   Sometimes, this is all there is to construct a result of in_chk(ttyfd) on.
  6159. */
  6160.     debug(F101,"in_chk my_count","",my_count);
  6161.     if (my_count > 0)
  6162.       n += my_count;
  6163. #endif /* MYREAD */
  6164.  
  6165.     return(n < 0 ? 0 : n);
  6166. }
  6167.  
  6168.  
  6169. /*  T T C H K  --  Tell how many characters are waiting in tty input buffer  */
  6170.  
  6171. /*  Some callers of this want to know whether there is something to read
  6172.  *  either in the system buffers or in our private buffers (and mostly don't
  6173.  *  care how many characters, just whether it's more than zero or not), while
  6174.  *  some others would be better off with the number of characters in our
  6175.  *  private buffers only.
  6176.  *
  6177.  *  Some systems can say how many characters there are in the system buffers.
  6178.  *  Others can not. For those that can't, the number in the private buffers
  6179.  *  will have to do (or should we put the tty into O_NDELAY-mode and try to
  6180.  *  read one character?). If the system can tell whether there is zero or
  6181.  *  more than zero characters, we can return 1 in the latter case even if the
  6182.  *  private buffer is empty. (That is good for sliding windows.)
  6183.  */
  6184. int
  6185. ttchk() {
  6186.     return(in_chk(ttyfd));
  6187. }
  6188.  
  6189. /*  T T X I N  --  Get n characters from tty input buffer  */
  6190.  
  6191. /*  Returns number of characters actually gotten, or -1 on failure  */
  6192.  
  6193. /*  Intended for use only when it is known that n characters are actually */
  6194. /*  Available in the input buffer.  */
  6195.  
  6196. int
  6197. ttxin(n,buf) int n; CHAR *buf; {
  6198.     register int x, c;
  6199.  
  6200.     debug(F101,"ttxin n","",n);
  6201.     if (n < 1) return(0);
  6202. #ifdef COMMENT
  6203.     ttpmsk = (ttprty) ? 0177 : 0377;    /* Parity stripping mask. */
  6204.     debug(F101,"ttxin ttpmsk","",ttpmsk);
  6205. #endif /* COMMENT */
  6206.  
  6207. #ifdef SUNX25
  6208.     if (netconn && (ttnet == NET_SX25))    /* X.25 connection */
  6209.       return(x25xin(n,buf));
  6210. #endif /* SUNX25 */
  6211.  
  6212. #ifdef MYREAD
  6213.     debug(F101,"ttxin MYREAD","",0);
  6214.     c = -2;
  6215.     for( x = 0; (x > -1) && (x < n) && (c = myread()) >= 0; )
  6216.       buf[x++] = c & ttpmsk;
  6217.     if (c < 0) {
  6218.     debug(F101,"ttxin myread returns","",c);
  6219.     if (c == -3) x = -1;
  6220.     }
  6221. #else
  6222.     x = read(ttyfd,buf,n);
  6223.     for (c = 0; c < n; c++) buf[c] &= ttpmsk;
  6224.     debug(F101," x","",x);
  6225. #endif /* MYREAD */
  6226.     if (x > 0) buf[x] = '\0';
  6227.     if (x < 0) x = -1;
  6228.     return(x);
  6229. }
  6230.  
  6231. /*  T T O L  --  Write string s, length n, to communication device.  */
  6232. /*
  6233.   Returns:
  6234.    >= 0 on success, number of characters actually written.
  6235.    -1 on failure.
  6236. */
  6237. #define TTOLMAXT 5
  6238. int
  6239. ttol(s,n) int n; CHAR *s; {
  6240.     int x, len, tries;
  6241.     if (ttyfd < 0)            /* Not open? */
  6242.       return(-3);
  6243.  
  6244.     debug(F101,"ttol n","",n);
  6245.     debug(F110,"ttol s",s,0);
  6246.  
  6247.     tries = TTOLMAXT;            /* Allow up to this many tries */
  6248.     len = n;                /* Remember original length */
  6249.     while (n > 0 && tries-- > 0) {    /* Be persistent */
  6250.     debug(F101,"ttol try","",TTOLMAXT - tries);
  6251.     x = write(ttyfd,s,n);        /* Write string to device */
  6252.     if (x == n) {            /* Worked? */
  6253.         debug(F101,"ttol ok","",x);    /* OK */
  6254.         return(len);        /* Done */
  6255.     } else if (x < 0) {        /* No, got error? */
  6256.         debug(F101,"ttol failed","",errno);
  6257. #ifdef TCPSOCKET
  6258.         if (netconn && ttnet == NET_TCPB) {
  6259.         if (errno) perror("TCP/IP"); /* Say why */
  6260.         ttclos(0);        /* Close the connection. */
  6261.         }
  6262. #endif /* TCPSOCKET */
  6263.         return(-1);
  6264.     } else {            /* No error, so partial success */
  6265.         debug(F101,"ttol partial","",x);
  6266.         s += x;            /* Point to part not written yet */
  6267.         n -= x;            /* Adjust length */
  6268.         if (x > 0) msleep(100);    /* Wait 100 msec */
  6269.     }                /* Go back and try again */
  6270.     }
  6271.     return(n < 1 ? len : -1);        /* Return the results */
  6272. }
  6273.  
  6274. /*  T T O C  --  Output a character to the communication line  */
  6275.  
  6276. /*
  6277.  This function should only be used for interactive, character-mode operations,
  6278.  like terminal connection, script execution, dialer i/o, where the overhead
  6279.  of the signals and alarms does not create a bottleneck.
  6280. */
  6281. int
  6282. #ifdef CK_ANSIC
  6283. ttoc(char c)
  6284. #else
  6285. ttoc(c) char c;
  6286. #endif /* CK_ANSIC */
  6287. /* ttoc */ {
  6288. #define TTOC_TMO 15            /* Timeout in case we get stuck */
  6289.     int xx;
  6290.     c &= 0xff;
  6291.     /* debug(F101,"ttoc","",(CHAR) c); */
  6292.     if (ttyfd < 0)            /* Check for not open. */
  6293.       return(-1);
  6294.     saval = signal(SIGALRM,timerh);    /* Enable timer interrupt */
  6295.     xx = alarm(TTOC_TMO);        /* for this many seconds. */
  6296.     if (xx < 0) xx = 0;            /* Save old alarm value. */
  6297.     /* debug(F101,"ttoc alarm","",xx); */
  6298.     if (
  6299. #ifdef CK_POSIX_SIG
  6300.     sigsetjmp(sjbuf,1)
  6301. #else
  6302.     setjmp(sjbuf)
  6303. #endif /* CK_POSIX_SIG */
  6304.     ) {        /* Timer went off? */
  6305.     ttimoff();            /* Yes, cancel this alarm. */
  6306.     if (xx - TTOC_TMO > 0) alarm(xx - TTOC_TMO); /* Restore previous one */
  6307.         /* debug(F100,"ttoc timeout","",0); */
  6308. #ifdef NETCONN
  6309.     if (!netconn) {
  6310. #endif /* NETCONN */
  6311.         debug(F101,"ttoc timeout","",c);
  6312.         if (ttflow == FLO_XONX) {
  6313.         debug(F101,"ttoc flow","",ttflow); /* Maybe we're xoff'd */
  6314. #ifndef Plan9
  6315. #ifdef POSIX
  6316.         /* POSIX way to unstick. */
  6317.         debug(F100,"ttoc tcflow","",tcflow(ttyfd,TCOON));
  6318. #else
  6319. #ifdef BSD4                /* Berkeley way to do it. */
  6320. #ifdef TIOCSTART
  6321. /* .... Used to be "ioctl(ttyfd, TIOCSTART, 0);".  Who knows? */
  6322.         {
  6323.           int x = 0;
  6324.           debug(F101,"ttoc TIOCSTART","",ioctl(ttyfd, TIOCSTART, &x));
  6325.         }
  6326. #endif /* TIOCSTART */
  6327. #endif /* BSD4 */
  6328.                     /* Is there a Sys V way to do this? */
  6329. #endif /* POSIX */
  6330. #endif /* Plan9 */
  6331.         }
  6332. #ifdef NETCONN
  6333.         }
  6334. #endif /* NETCONN */
  6335.     return(-1);            /* Return failure code. */
  6336.     } else {
  6337.     if (write(ttyfd,&c,1) < 1) {    /* Try to write the character. */
  6338.         ttimoff();            /* Failed, turn off the alarm. */
  6339.         alarm(xx);            /* Restore previous alarm. */
  6340.         debug(F101,"ttoc error","",errno); /* Log the error, */
  6341.         return(-1);            /* and return the error code. */
  6342.     }
  6343.     }
  6344.     ttimoff();                /* Success, turn off the alarm. */
  6345.     alarm(xx);                /* Restore previous alarm. */
  6346.     return(0);                /* Return good code. */
  6347. }
  6348.  
  6349. /*  T T I N L  --  Read a record (up to break character) from comm line.  */
  6350. /*
  6351.   Reads up to "max" characters from the communication line, terminating on:
  6352.  
  6353.     (a) the packet length field if the "turn" argument is zero, or
  6354.     (b) on the packet-end character (eol) if the "turn" argument is nonzero
  6355.     (c) a certain number of Ctrl-C's in a row
  6356.  
  6357.   and returns the number of characters read upon success, or if "max" was
  6358.   exceeded or the timeout interval expired before (a) or (b), returns -1.
  6359.  
  6360.   The characters that were input are copied into "dest" with their parity bits
  6361.   stripped if parity was selected.  Returns the number of characters read.
  6362.   Characters after the eol are available upon the next call to this function.
  6363.  
  6364.   The idea is to minimize the number of system calls per packet, and also to
  6365.   minimize timeouts.  This function is the inner loop of the program and must
  6366.   be as efficient as possible.  The current strategy is to use myread().
  6367.  
  6368.   WARNING: this function calls parchk(), which is defined in another module.
  6369.   Normally, ckutio.c does not depend on code from any other module, but there
  6370.   is an exception in this case because all the other ck?tio.c modules also
  6371.   need to call parchk(), so it's better to have it defined in a common place.
  6372.  
  6373.   Since this function has grown to have its fingers so deeply into the 
  6374.   protocol, it is slated for removal: rpack() should take care of everything.
  6375. */
  6376. #ifdef CTRLC
  6377. #undef CTRLC
  6378. #endif /* CTRLC */
  6379. #define CTRLC '\03'
  6380. /*
  6381.   We have four different declarations here because:
  6382.   (a) to allow Kermit to be built without the automatic parity sensing feature
  6383.   (b) one of each type for ANSI C, one for non-ANSI.
  6384. */
  6385. int
  6386. #ifdef PARSENSE
  6387. #ifdef CK_ANSIC
  6388. ttinl(CHAR *dest, int max,int timo, CHAR eol, CHAR start, int turn)
  6389. #else
  6390. ttinl(dest,max,timo,eol,start,turn) int max,timo,turn; CHAR *dest, eol, start;
  6391. #endif /* CK_ANSIC */
  6392. #else /* not PARSENSE */
  6393. #ifdef CK_ANSIC
  6394. ttinl(CHAR *dest, int max,int timo, CHAR eol)
  6395. #else
  6396. ttinl(dest,max,timo,eol) int max,timo; CHAR *dest, eol;
  6397. #endif /* __SDTC__ */
  6398. #endif /* PARSENSE */
  6399. /* ttinl */ {
  6400.  
  6401. #ifndef MYREAD
  6402.     CHAR ch;
  6403. #endif /* MYREAD */
  6404. #ifdef PARSENSE
  6405.     int pktlen = -1;
  6406.     int lplen = 0;
  6407.     int havelen = 0;
  6408. #endif /* PARSENSE */
  6409.     int cc = 0;                /* Character count */
  6410.  
  6411.     if (ttyfd < 0) return(-3);          /* Not open. */
  6412.  
  6413.     debug(F101,"ttinl max","",max);
  6414.     debug(F101,"ttinl timo","",timo);
  6415.  
  6416.     *dest = '\0';                       /* Clear destination buffer */
  6417.     if (timo < 0) timo = 0;        /* Safety */
  6418.     if (timo) {                /* Don't time out if timo == 0 */
  6419.     int xx;
  6420.     saval = signal(SIGALRM,timerh);    /* Enable timer interrupt */
  6421.     xx = alarm(timo);        /* Set it. */
  6422.     debug(F101,"ttinl alarm","",xx);
  6423.     }
  6424.     if (
  6425. #ifdef CK_POSIX_SIG
  6426.     sigsetjmp(sjbuf,1)
  6427. #else
  6428.     setjmp(sjbuf)
  6429. #endif /* CK_POSIX_SIG */
  6430.     ) {                /* Timer went off? */
  6431.     debug(F100,"ttinl timout","",0); /* Get here on timeout. */
  6432.     /* debug(F110," with",(char *) dest,0); */
  6433.     ttimoff();            /* Turn off timer */
  6434.     return(-1);            /* and return error code. */
  6435.     } else {
  6436.     register int i, /* m, */ n;    /* local variables */
  6437.     int ccn = 0;
  6438. #ifdef PARSENSE
  6439.     int flag = 0;
  6440.     debug(F000,"ttinl start","",start);
  6441. #endif /* PARSENSE */
  6442.  
  6443.     ttpmsk = (ttprty) ? 0177 : 0377; /* Set parity stripping mask. */
  6444. #ifdef COMMENT
  6445.     m == ttpmsk;
  6446. #endif /* COMMENT */
  6447.  
  6448. #ifdef COMMENT
  6449. /*
  6450.   No longer needed.
  6451. */
  6452. #ifdef SUNX25
  6453.         if (netconn && (ttnet == NET_SX25))
  6454. #ifdef PARSENSE
  6455.       return(x25inl(dest,max,timo,eol,start));
  6456. #else
  6457.       return(x25inl(dest,max,timo,eol));
  6458. #endif /* PARSENSE */
  6459. #endif /* SUNX25 */
  6460. #endif /* COMMENT */
  6461.  
  6462. /* Now read into destination, stripping parity and looking for the */
  6463. /* the packet terminator, and also for several Ctrl-C's typed in a row. */
  6464.  
  6465.     i = 0;                /* Destination index */
  6466.     debug(F101,"ttinl eol","",eol);
  6467.  
  6468. #ifdef MYREAD
  6469.     while (i < max-1) {
  6470.         /* debug(F101,"ttinl i","",i); */
  6471.         if ((n = myread()) < 0) {    /* Timeout or i/o error? */
  6472. #ifdef DEBUG
  6473.         if (deblog) {
  6474.             debug(F101,"ttinl myread failure, n","",n);
  6475.             debug(F101,"ttinl myread errno","",errno);
  6476.         }
  6477. #endif /* DEBUG */
  6478.         /* Don't let EINTR break packets. */
  6479.         if (n == -3 && errno == EINTR && i > 0) {
  6480.             debug(F101,"ttinl myread i","",i);
  6481.             continue;
  6482.         } else if (n == -2 && netconn /* && timo == 0 */ ) {
  6483.             /* Here we try to catch broken network connections */
  6484.             /* even when ioctl() and read() do not catch them */
  6485.             debug(F100,"ttinl untimed network myread fails","",0);
  6486.             n = -3;        /* Upgrade the error */
  6487.             ttclos(0);
  6488.         }
  6489.         break;            /* Break out of while loop */
  6490.         }
  6491. #else
  6492.     while ((i < max-1)  &&  (n = read(ttyfd, &ch, 1)) > 0) {
  6493.         n = ch;
  6494. #endif /* MYREAD */
  6495.  
  6496.         /* debug(F101,"ttinl char","", (n & ttpmsk)); */
  6497.  
  6498. #ifdef PARSENSE
  6499. /*
  6500.   Figure out what the length is supposed to be in case the packet
  6501.   has no terminator (as with Honeywell GCOS-8 Kermit).
  6502. */
  6503. #ifndef xunchar
  6504. #define xunchar(ch) (((ch) - 32 ) & 0xFF )    /* Character to number */
  6505. #endif /* xunchar */
  6506.         if ((flag == 0) && ((n & 0x7f) == start)) flag = 1;
  6507.         if (flag) dest[i++] = n & ttpmsk;
  6508. #ifdef COMMENT
  6509.         /* if (!flag && cc++ > (max / 2)) return(-1); */
  6510. #endif /* COMMENT */
  6511. /*
  6512.   If we have not been instructed to wait for a turnaround character, we
  6513.   can go by the packet length field.  If turn != 0, we must wait for the
  6514.   end of line (eol) character before returning.
  6515. */
  6516.         if (i == 2) {
  6517.         pktlen = xunchar(dest[1] & 0x7f);
  6518.         havelen = (pktlen > 1);
  6519.         debug(F101,"ttinl length","",pktlen);
  6520.         } else if (i == 5 && pktlen == 0) {
  6521.         lplen = xunchar(dest[4] & 0x7f);
  6522.         } else if (i == 6 && pktlen == 0) {
  6523.         pktlen = lplen * 95 + xunchar(dest[5] & 0x7f) + 5;
  6524.         havelen = 1;
  6525.         debug(F101,"ttinl length","",pktlen);
  6526.         }
  6527. #else
  6528.         dest[i++] = n & ttpmsk;
  6529. #endif /* PARSENSE */
  6530. /*
  6531.   Use parity mask, rather than always stripping parity, to check for
  6532.   cancellation.  Otherwise, runs like \x03\x83\x03 in packet could cancel
  6533.   the transfer when parity is NONE.
  6534. */
  6535.         /* Check cancellation */
  6536.         if (!xlocal && xfrcan && ((n & ttpmsk) == xfrchr)) {
  6537.         if (++ccn >= xfrnum) {    /* If xfrnum in a row, bail out. */
  6538.             if (timo) {        /* Clear timer. */
  6539.             ttimoff();
  6540.             }
  6541.             fprintf(stderr,"^C...\r\n"); /* Echo Ctrl-C */
  6542.             return(-2);
  6543.         }
  6544.         } else ccn = 0;        /* No cancellation, reset counter, */
  6545.  
  6546. #ifdef PARSENSE
  6547.         if (flag == 0) {
  6548.         debug(F101,"ttinl skipping","",n);
  6549.         continue;
  6550.         }
  6551. #endif /* PARSENSE */
  6552.  
  6553.     /* Check for end of packet */
  6554.  
  6555.         if (
  6556. #ifdef PARSENSE
  6557. /*
  6558.   Purely length-driven if SET HANDSHAKE NONE (i.e. turn == 0).
  6559.   This allows packet terminators and handshake characters to appear
  6560.   literally inside a packet data field.
  6561. */
  6562.         (havelen && (i > pktlen+1) &&
  6563.          (!turn || (turn && (n & 0x7f) == eol)))
  6564. #ifdef COMMENT
  6565.         (!turn && havelen && (i > pktlen+1)) ||
  6566.         (turn && havelen && (i > pktlen+1) && (n & 0x7f) == eol)
  6567. #endif /* COMMENT */
  6568. #else /* !PARSENSE */
  6569. /*
  6570.   Built without PARSENSE, so just look for packet terminator.
  6571. */
  6572.         ((n & 0x7f) == eol)
  6573. #endif /* PARSENSE */
  6574.         ) {
  6575. #ifndef PARSENSE
  6576.         debug(F101,"ttinl got eol","",eol);
  6577.         dest[i] = '\0';        /* Yes, terminate the string, */
  6578.         /* debug(F101,"ttinl i","",i); */
  6579. #else
  6580.         if ((n & 0x7f) != eol) {
  6581.             debug(F101,"ttinl EOP length","",pktlen);
  6582.             debug(F101,"ttinl i","",i);
  6583.         } else debug(F101,"ttinl got eol","",eol);
  6584.         dest[i] = '\0';        /* Terminate the string, */
  6585.         /* Parity checked yet? */
  6586.             if (ttpflg++ == 0 && ttprty == 0) {
  6587.             if ((ttprty = parchk(dest,start,i)) > 0) { /* No, check. */
  6588.             int j;
  6589.             debug(F101,"ttinl senses parity","",ttprty);
  6590.             debug(F110,"ttinl packet before",dest,0);
  6591.             ttpmsk = 0x7f;
  6592.             for (j = 0; j < i; j++)
  6593.               dest[j] &= 0x7f;    /* Strip parity from packet */
  6594.             debug(F110,"ttinl packet after ",dest,0);
  6595.             } else ttprty = 0;    /* restore if parchk error */
  6596.         }
  6597. #endif /* PARSENSE */
  6598.         if (timo) {            /* Turn off timer. */
  6599.             ttimoff();
  6600.         }
  6601.         debug(F111,"ttinl got", dest,i);
  6602.         return(i);
  6603.         }
  6604.     }                /* end of while() */
  6605.     ttimoff();
  6606.     return(n);
  6607.     }
  6608. }
  6609.  
  6610. /*  T T I N C --  Read a character from the communication line  */
  6611. /*
  6612.  On success, returns the character that was read, >= 0.
  6613.  On failure, returns -1 or other negative myread error code,
  6614.    or -2 if connection is broken or ttyfd < 0.
  6615. */
  6616. int
  6617. ttinc(timo) int timo; {
  6618.  
  6619.     int n = 0;
  6620. #ifndef MYREAD
  6621.     CHAR ch = 0;
  6622. #endif /* MYREAD */
  6623.  
  6624.     if (ttyfd < 0) return(-2);          /* Not open. */
  6625.     if ((timo <= 0)            /* Untimed. */
  6626. #ifdef MYREAD
  6627.     || (my_count > 0)        /* Buffered char already waiting. */
  6628. #endif /* MYREAD */
  6629.     ) {
  6630. #ifdef MYREAD
  6631.         /* Comm line failure returns -1 thru myread, so no &= 0377 */
  6632.     n = myread();            /* Wait for a character... */
  6633.     /* debug(F000,"ttinc MYREAD n","",n); */
  6634. #ifdef TCPSOCKET
  6635.     if (netconn && (ttnproto == NP_TELNET) && (n > -1))
  6636.       return((unsigned)(n & 0xff));
  6637.     else
  6638. #endif /* TCPSOCKET */
  6639.     return(n < 0 ? n : (unsigned)(n & ttpmsk));
  6640. #else
  6641.         while ((n = read(ttyfd,&ch,1)) == 0) /* Wait for a character. */
  6642.         /* Shouldn't have to loop in ver 5A. */
  6643. #ifdef NETCONN      
  6644.       if (netconn) {        /* Special handling for net */
  6645.           netclos();        /* If read() returns 0 it means */
  6646.           netconn = 0;        /* the connection has dropped. */
  6647.           errno = ENOTCONN;
  6648.           return(-2);
  6649.       }
  6650. #endif /* NETCONN */
  6651.       ;
  6652.      /* debug(F000,"ttinc","",ch); */
  6653. #ifdef TCPSOCKET
  6654.     if (netconn && (ttnproto == NP_TELNET) && (n > -1))
  6655.       return((unsigned)(n & 0xff));
  6656.     else
  6657. #endif /* TCPSOCKET */
  6658.         return( (n < 1) ? -3 : (unsigned)(ch & ttpmsk) );
  6659. #endif /* MYREAD */
  6660.     } else {                /* Timed read */
  6661.     int xx;
  6662.     saval = signal(SIGALRM,timerh);    /* Set up handler, save old one. */
  6663.     xx = alarm(timo);        /* Set alarm, save old one. */
  6664.     if (
  6665. #ifdef CK_POSIX_SIG
  6666.         sigsetjmp(sjbuf,1)
  6667. #else
  6668.         setjmp(sjbuf)
  6669. #endif /* CK_POSIX_SIG */
  6670.         ) {        /* Timer expired */
  6671.         n = -1;            /* set flag */
  6672.     } else {
  6673. #ifdef MYREAD
  6674.         n = myread();        /* If managing own buffer... */
  6675.         /* debug(F101,"ttinc myread","",n); */
  6676. #else
  6677.         n = read(ttyfd,&ch,1);    /* Otherwise call the system. */
  6678.         /* debug(F101,"ttinc read","",n); */
  6679.         if (n > 0)
  6680.           n = ch & 255;
  6681.         else
  6682.           n = (n < 0) ? -3 : -2;    /* Special return codes. */
  6683. #endif /* MYREAD */
  6684.     }
  6685.     ttimoff();            /* Turn off the timer */
  6686. /* #ifdef COMMENT */
  6687.     if (n == -1) xx -= timo;    /* and restore any previous alarm */
  6688.     if (xx < 0) xx = 0;        /* adjusted by timeout interval */
  6689.     alarm(xx);            /* if timer expired. */
  6690. /* #endif */ /* COMMENT */
  6691. #ifdef NETCONN
  6692.     if (netconn) {
  6693.         if (n == -2) {        /* read() returns 0 */
  6694.         netclos();        /* on network read failure */
  6695.         netconn = 0;
  6696.         errno = ENOTCONN;
  6697.         }
  6698.     }
  6699. #endif    /* NETCONN */
  6700. #ifdef TCPSOCKET
  6701.     if (netconn && (ttnproto == NP_TELNET) && (n > -1))
  6702.       return((unsigned)(n & 0xff));
  6703.     else
  6704. #endif /* TCPSOCKET */
  6705.       /* Return masked char or neg. */
  6706.       return( (n < 0) ? n : (unsigned)(n & ttpmsk) );
  6707.     }
  6708. }
  6709.  
  6710. /*  S N D B R K  --  Send a BREAK signal of the given duration  */
  6711.  
  6712. #ifndef NOLOCAL
  6713. static int
  6714. #ifdef CK_ANSIC
  6715. sndbrk(int msec) {            /* Argument is milliseconds */
  6716. #else
  6717. sndbrk(msec) int msec; {
  6718. #endif /* CK_ANSIC */
  6719. #ifndef POSIX
  6720.     int x, n;
  6721. #endif /* POSIX */
  6722.  
  6723. #ifdef OXOS
  6724. #define BSDBREAK
  6725. #endif /* OXOS */
  6726.  
  6727. #ifdef ANYBSD
  6728. #define BSDBREAK
  6729. #endif /* ANYBSD */
  6730.  
  6731. #ifdef BSD44
  6732. #define BSDBREAK
  6733. #endif /* BSD44 */
  6734.  
  6735. #ifdef COHERENT
  6736. #define BSDBREAK
  6737. #endif /* COHERENT */
  6738.  
  6739. #ifdef BELLV10
  6740. #ifdef BSDBREAK
  6741. #undef BSDBREAK
  6742. #endif /* BSDBREAK */
  6743. #endif /* BELLV10 */
  6744.  
  6745. #ifdef PROVX1
  6746.     char spd;
  6747. #endif /* PROVX1 */
  6748.  
  6749.     debug(F101,"ttsndb ttyfd","",ttyfd);
  6750.     if (ttyfd < 0) return(-1);          /* Not open. */
  6751.  
  6752. #ifdef Plan9
  6753.     return p9sndbrk(msec);
  6754. #else
  6755. #ifdef NETCONN
  6756.     if (netconn)             /* Send network BREAK */
  6757.       return(netbreak());
  6758. #endif /* NETCONN */
  6759.  
  6760.     if (msec < 1 || msec > 5000) return(-1); /* Bad argument */
  6761.  
  6762. #ifdef POSIX                /* Easy in POSIX */
  6763.     debug(F101,"sndbrk POSIX","",msec);
  6764.     return(tcsendbreak(ttyfd,msec / 375));
  6765. #else
  6766. #ifdef PROVX1
  6767.     gtty(ttyfd,&ttbuf);                 /* Get current tty flags */
  6768.     spd = ttbuf.sg_ospeed;              /* Save speed */
  6769.     ttbuf.sg_ospeed = B50;              /* Change to 50 baud */
  6770.     stty(ttyfd,&ttbuf);                 /*  ... */
  6771.     n = (int)strlen(brnuls);        /* Send the right number of nulls */
  6772.     x = msec / 91;
  6773.     if (x > n) x = n;
  6774.     write(ttyfd,brnuls,n);
  6775.     ttbuf.sg_ospeed = spd;              /* Restore speed */
  6776.     stty(ttyfd,&ttbuf);                 /*  ... */
  6777.     return(0);
  6778. #else
  6779. #ifdef aegis
  6780.     sio_$control((short)ttyfd, sio_$send_break, msec, st);
  6781.     return(0);
  6782. #else
  6783. #ifdef BSDBREAK
  6784.     n = FWRITE;                         /* Flush output queue. */
  6785. /* Watch out for int vs long problems in &n arg! */
  6786.     debug(F101,"sndbrk BSDBREAK","",msec);
  6787.     ioctl(ttyfd,TIOCFLUSH,&n);          /* Ignore any errors.. */
  6788.     if (ioctl(ttyfd,TIOCSBRK,(char *)0) < 0) {  /* Turn on BREAK */
  6789.         perror("Can't send BREAK");
  6790.         return(-1);
  6791.     }
  6792.     x = msleep(msec);                    /* Sleep for so many milliseconds */
  6793.     if (ioctl(ttyfd,TIOCCBRK,(char *)0) < 0) {  /* Turn off BREAK */
  6794.         perror("BREAK stuck!!!");
  6795.         doexit(BAD_EXIT,-1);        /* Get out, closing the line. */
  6796.                                         /*   with bad exit status */
  6797.     }
  6798.     return(x);
  6799. #else
  6800. #ifdef ATTSV
  6801. /*
  6802.   No way to send a long BREAK in Sys V, so send a bunch of regular ones.
  6803.   (Actually, Sys V R4 is *supposed* to have the POSIX tcsendbreak() function,
  6804.   but there's no way for this code to know for sure.)
  6805. */
  6806.     debug(F101,"sndbrk ATTSV","",msec);
  6807.     x = msec / 275;
  6808.     for (n = 0; n < x; n++) {
  6809.     /* Reportedly the cast breaks this function on some systems */
  6810.     /* But then why was it here in the first place? */
  6811.     if (ioctl(ttyfd,TCSBRK, /* (char *) */ 0) < 0) {
  6812.         perror("Can't send BREAK");
  6813.         return(-1);
  6814.     }
  6815.     }
  6816.     return(0);
  6817. #else
  6818. #ifdef  V7
  6819.     debug(F101,"sndbrk V7","",msec);
  6820.     return(genbrk(ttyfd,250));        /* Simulate a BREAK */
  6821. #else
  6822.     debug(F101,"sndbrk catchall","",msec);
  6823.     ttoc(0);ttoc(0);ttoc(0);ttoc(0);
  6824.     return(0);
  6825. #endif /* V7 */
  6826. #endif /* BSDBREAK */
  6827. #endif /* ATTSV */
  6828. #endif /* aegis */
  6829. #endif /* PROVX1 */
  6830. #endif /* POSIX */
  6831. #endif /* Plan9 */
  6832. }
  6833.  
  6834. /*  T T S N D B  --  Send a BREAK signal  */
  6835.  
  6836. int
  6837. ttsndb() {
  6838.     return(sndbrk(275));
  6839. }
  6840.  
  6841. /*  T T S N D L B  --  Send a Long BREAK signal  */
  6842.  
  6843. int
  6844. ttsndlb() {
  6845.     return(sndbrk(1500));
  6846. }
  6847. #endif /* NOLOCAL */
  6848.  
  6849. /*  M S L E E P  --  Millisecond version of sleep().  */
  6850.  
  6851. /*
  6852.   Call with number of milliseconds (thousandths of seconds) to sleep.
  6853.   Intended only for small intervals.  For big ones, just use sleep().
  6854.   Highly system-dependent.
  6855.   Returns 0 always, even if it didn't work.
  6856. */
  6857.  
  6858. /* Define MSLFTIME for systems that must use an ftime() loop. */
  6859. #ifdef ANYBSD                /* For pre-4.2 BSD versions */
  6860. #ifndef BSD4
  6861. #define MSLFTIME
  6862. #endif /* BSD4 */
  6863. #endif /* ANYBSD */
  6864.  
  6865. #ifdef TOWER1                /* NCR Tower OS 1.0 */
  6866. #define MSLFTIME
  6867. #endif /* TOWER1 */
  6868.  
  6869. #ifdef COHERENT         /* Coherent... */
  6870. #ifndef _I386           /* Maybe Coherent/386 should get this, too */
  6871. #define MSLFTIME        /* Opinions are divided */
  6872. #endif /* _I386 */
  6873. #endif /* COHERENT */
  6874.  
  6875. #ifdef GETMSEC
  6876.  
  6877. /* Millisecond timer */
  6878.  
  6879. static long msecbase = 0L;        /* Unsigned long not portable */
  6880.  
  6881. long
  6882. getmsec() {                /* Milliseconds since base time */
  6883.     struct timeval xv;
  6884.     struct timezone xz;
  6885.     long secs, msecs;
  6886.     if (gettimeofday(&tv, &tz) < 0)
  6887.       return(-1);
  6888.     if (msecbase == 0L) {        /* First call, set base time. */
  6889.     msecbase = tv.tv_sec;
  6890.     debug(F101,"getmsec base","",msecbase);
  6891.     }
  6892.     return(((tv.tv_sec - msecbase) * 1000L) + (tv.tv_usec / 1000L));
  6893. }
  6894. #endif /* GETMSEC */
  6895.  
  6896. int
  6897. msleep(m) int m; {
  6898.  
  6899. #ifdef Plan9
  6900.     return _SLEEP(m);
  6901. #else
  6902. #ifdef SELECT
  6903.     int t1, x;
  6904.     debug(F101,"msleep SELECT 1","",m);
  6905.     if (m <= 0) return(0);
  6906.     if (m >= 1000) {            /* Catch big arguments. */
  6907.     sleep(m/1000);
  6908.     m = m % 1000;
  6909.     if (m < 10) return(0);
  6910.     }
  6911.     debug(F101,"msleep SELECT 2","",m);
  6912. #ifdef BELLV10
  6913.     x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, m );
  6914.     debug(F101,"msleep BELLV10 select","",x);
  6915. #else
  6916. #ifndef COHERENT
  6917. /* Hmmm...  what's all this then?  */
  6918.     if (gettimeofday(&tv, &tz) < 0) return(-1); /* Get current time. */
  6919.     t1 = tv.tv_sec;                     /* Seconds */
  6920. #endif /* COHERENT */
  6921.     tv.tv_sec = 0;                      /* Use select() */
  6922.     tv.tv_usec = m * 1000L;
  6923. #ifdef BSD44
  6924.     x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
  6925.     debug(F101,"msleep BSD44 select","",x);
  6926. #else
  6927. #ifdef __linux__
  6928.     x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
  6929.     debug(F101,"msleep __linux__ select","",x);
  6930. #else
  6931. #ifdef BSD43
  6932.     x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
  6933.     debug(F101,"msleep BSD43 select","",x);
  6934. #else
  6935. #ifdef QNX
  6936.     x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
  6937.     debug(F101,"msleep QNX select","",x);
  6938. #else
  6939. #ifdef COHERENT
  6940.     x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
  6941.     debug(F101,"msleep COHERENT select","",x);
  6942. #else
  6943. #ifdef HPUX1000                /* 10.00 only, not 10.10 or later */
  6944.     x = select( 0, (int *)0, (int *)0, (int *)0, &tv );
  6945.     debug(F101,"msleep HP-UX 10.00 select","",x);
  6946. #else
  6947. #ifdef SVR4
  6948.     x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
  6949.     debug(F101,"msleep SVR4 select","",x);
  6950. #else
  6951. #ifdef OSF40
  6952.     x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
  6953.     debug(F101,"msleep BSD43 select","",x);
  6954. #else
  6955.     x = select( 0, (int *)0, (int *)0, (int *)0, &tv );
  6956.     debug(F101,"msleep catch-all select","",x);
  6957. #endif /* OSF40 */
  6958. #endif /* HP1000 */
  6959. #endif /* SVR4 */
  6960. #endif /* COHERENT */
  6961. #endif /* QNX */
  6962. #endif /* BSD43 */
  6963. #endif /* __linux__ */
  6964. #endif /* BSD44 */
  6965. #endif /* BELLV10 */
  6966.     return(0);
  6967.  
  6968. #else                    /* Not SELECT */
  6969. #ifdef CK_POLL                /* We have poll() */
  6970.     struct pollfd pfd;            /* Supply a valid address for poll() */
  6971.  
  6972. #ifdef ODT30                /* But in SCO ODT 3.0 */
  6973. #ifdef NAP                /* we should use nap() instead */
  6974.     debug(F101,"msleep ODT 3.0 NAP","",m); /* because using poll() here */
  6975.     nap((long)m);               /* seems to break dialing. */
  6976.     return(0);
  6977. #else
  6978.     debug(F101,"msleep ODT 3.0 POLL","",m);
  6979.     poll(&pfd, 0, m);
  6980.     return(0);
  6981. #endif /* NAP */
  6982. #else
  6983.     debug(F101,"msleep POLL","",m);
  6984.     poll(&pfd, 0, m);
  6985.     return(0);
  6986. #endif /* ODT30 */
  6987.  
  6988. /*
  6989.   We could handle the above more cleanly by just letting nap() take
  6990.   always take precedence over poll() in this routine, but there is no way
  6991.   to know whether that would break something else.
  6992. */
  6993.  
  6994. #else                    /* Not POLL */
  6995. #ifdef USLEEP
  6996. /*
  6997.   "This routine is implemented using setitimer(2); it requires eight
  6998.   system calls...".  In other words, it might take 5 minutes to sleep
  6999.   for 100 milliseconds...
  7000. */
  7001.     debug(F101,"msleep USLEEP","",m);
  7002.     if (m >= 1000) {            /* Catch big arguments. */
  7003.     sleep(m/1000);
  7004.     m = m % 1000;
  7005.     if (m < 10) return(0);
  7006.     }
  7007.     usleep((unsigned int)(m * 1000));
  7008.     return(0);
  7009. #else
  7010. #ifdef aegis
  7011.     time_$clock_t dur;
  7012.  
  7013.     debug(F101,"msleep aegis","",m);
  7014.     dur.c2.high16 = 0;
  7015.     dur.c2.low32  = 250 * m; /* one millisecond = 250 four microsecond ticks */
  7016.     time_$wait(time_$relative, dur, st);
  7017.     return(0);
  7018. #else
  7019. #ifdef PROVX1
  7020.     debug(F101,"msleep Venix","",m);
  7021.     if (m <= 0) return(0);
  7022.     sleep(-((m * 60 + 500) / 1000));
  7023.     return(0);
  7024. #else
  7025. #ifdef NAP
  7026.     debug(F101,"msleep NAP","",m);
  7027.     nap((long)m);
  7028.     return(0);
  7029. #else
  7030. #ifdef ATTSV
  7031. #ifndef BSD44
  7032.     extern long times();        /* Or #include <times.h> ? */
  7033. #endif /* BSD44 */
  7034.     long t1, t2, tarray[4];
  7035.     int t3;
  7036.  
  7037. #ifdef COMMENT
  7038. /* This better be picked up in ckcdeb.h... */
  7039.     char *getenv();
  7040. #endif /* COMMENT */
  7041.     char *cp = getenv("HZ");
  7042.     int CLOCK_TICK;
  7043.     int hertz;
  7044.  
  7045.     if (cp && (hertz = atoi(cp))) {
  7046.         CLOCK_TICK  = 1000 / hertz;
  7047.     } else {                /* probably single user mode */
  7048. #ifdef HZ
  7049.         CLOCK_TICK  = 1000 / HZ;    
  7050. #else
  7051.     static warned = 0;
  7052.     /* HZ always exists in, for instance, SCO Xenix, so you don't have to
  7053.      * make special #ifdefs for XENIX here, like in ver 4F. Also, if you
  7054.      * have Xenix, you have should have nap(), so the best is to use -DNAP
  7055.      * in the makefile. Most systems have HZ.
  7056.      */
  7057.     CLOCK_TICK = 17;        /* 1/60 sec */
  7058.     if (!warned) {
  7059.           printf("warning: environment variable HZ bad... using HZ=%d\r\n",
  7060.          1000 / CLOCK_TICK);
  7061.           warned = 1;
  7062.     }
  7063. #endif /* !HZ */
  7064.     }
  7065.     debug(F101,"msleep ATTSV","",m);
  7066.     if (m <= 0) return(0);
  7067.     if (m >= 1000) {            /* Catch big arguments. */
  7068.     sleep(m/1000);
  7069.     m = m % 1000;
  7070.     if (m < 10) return(0);
  7071.     }
  7072.     if ((t1 = times(tarray)) < 0) return(-1);
  7073.     while (1) {
  7074.         if ((t2 = times(tarray)) < 0) return(-1);
  7075.         t3 = ((int)(t2 - t1)) * CLOCK_TICK;
  7076.         if (t3 > m) return(t3);
  7077.     }
  7078. #else /* Not ATTSV */
  7079. #ifdef MSLFTIME                /* Use ftime() loop... */
  7080.     int t1, t3 = 0;
  7081.     debug(F101,"msleep MSLFTIME","",m);
  7082.     if (m <= 0) return(0);
  7083.     if (m >= 1000) {            /* Catch big arguments. */
  7084.     sleep(m/1000);
  7085.     m = m % 1000;
  7086.     if (m < 10) return(0);
  7087.     }
  7088. #ifdef QNX
  7089.     ftime(&ftp);            /* void ftime() in QNX */
  7090. #else
  7091.     if (ftime(&ftp) < 0) return(-1);    /* Get base time. */
  7092. #endif /* QNX */
  7093.     t1 = ((ftp.time & 0xff) * 1000) + ftp.millitm;
  7094.     while (1) {
  7095.         ftime(&ftp);            /* Get current time and compare. */
  7096.         t3 = (((ftp.time & 0xff) * 1000) + ftp.millitm) - t1;
  7097.         if (t3 > m) return(0);
  7098.     }
  7099. #else
  7100. /* This includes true POSIX, which has no way to do this. */
  7101.     debug(F101,"msleep busy loop","",m);
  7102.     if (m >= 1000) {            /* Catch big arguments. */
  7103.     sleep(m/1000);
  7104.     m = m % 1000;
  7105.     if (m < 10) return(0);
  7106.     }
  7107.     if (m > 0) while (m > 0) m--;    /* Just a dumb busy loop */
  7108.     return(0);
  7109. #endif /* MSLFTIME */
  7110. #endif /* ATTSV */
  7111. #endif /* NAP */
  7112. #endif /* PROVX1 */
  7113. #endif /* aegis */
  7114. #endif /* SELECT */
  7115. #endif /* CK_POLL */
  7116. #endif /* USLEEP */
  7117. #endif /* Plan9 */
  7118. }
  7119.  
  7120. /*  R T I M E R --  Reset elapsed time counter  */
  7121.  
  7122. VOID
  7123. rtimer() {
  7124.     tcount = time( (time_t *) 0 );
  7125. }
  7126.  
  7127.  
  7128. /*  G T I M E R --  Get current value of elapsed time counter in seconds  */
  7129.  
  7130. int
  7131. gtimer() {
  7132.     int x;
  7133.     x = (int) (time( (time_t *) 0 ) - tcount);
  7134.     debug(F101,"gtimer","",x);
  7135.     return( (x < 0) ? 0 : x );
  7136. }
  7137.  
  7138.  
  7139. /*  Z T I M E  --  Return date/time string  */
  7140.  
  7141. VOID
  7142. ztime(s) char **s; {
  7143.  
  7144. #undef ZTIMEV7                /* Which systems need to use */
  7145. #ifdef COHERENT                /* old UNIX Version 7 way... */
  7146. #define ZTIMEV7
  7147. #endif /* COHERENT */
  7148. #ifdef TOWER1
  7149. #define ZTIMEV7
  7150. #endif /* TOWER1 */
  7151. #ifdef ANYBSD
  7152. #ifndef BSD42
  7153. #define ZTIMEV7
  7154. #endif /* BSD42 */
  7155. #endif /* ANYBSD */
  7156. #ifdef V7
  7157. #ifndef MINIX
  7158. #define ZTIMEV7
  7159. #endif /* MINIX */
  7160. #endif /* V7 */
  7161. #ifdef POSIX
  7162. #define ZTIMEV7
  7163. #endif /* POSIX */
  7164.  
  7165. #ifdef HPUX1020
  7166. /*
  7167.   Prototypes are in <time.h>, included above.
  7168. */
  7169.     time_t clock_storage;
  7170.     clock_storage = time((void *) 0);
  7171.     *s = ctime(&clock_storage);
  7172.     debug(F110,"ztime: HPUX 10.20",*s,0);
  7173. #else
  7174. #ifdef ATTSV                /* AT&T way */
  7175. /*  extern long time(); */        /* Theoretically these should */
  7176.     char *ctime();            /* already been dcl'd in <time.h> */
  7177.     long clock_storage;
  7178.     clock_storage = time(
  7179. #ifdef IRIX60
  7180.              (time_t *)
  7181. #else
  7182.              (long *)
  7183. #endif /* IRIX60 */
  7184.              0 );
  7185.     *s = ctime( &clock_storage );
  7186.     debug(F110,"ztime: ATTSV",*s,0);
  7187. #else
  7188. #ifdef PROVX1                /* Venix 1.0 way */
  7189.     int utime[2];
  7190.     time(utime);
  7191.     *s = ctime(utime);
  7192.     debug(F110,"ztime: PROVX1",*s,0);
  7193. #else
  7194. #ifdef BSD42                /* 4.2BSD way */
  7195.     char *asctime();
  7196.     struct tm *localtime();
  7197.     struct tm *tp;
  7198.     gettimeofday(&tv, &tz);
  7199.     time(&tv.tv_sec);
  7200.     tp = localtime(&tv.tv_sec);
  7201.     *s = asctime(tp);
  7202.     debug(F110,"ztime: BSD42",*s,0);
  7203. #else
  7204. #ifdef MINIX                /* MINIX way */
  7205. #ifdef COMMENT
  7206.     extern long time();            /* Already got these from <time.h> */
  7207.     extern char *ctime();
  7208. #endif /* COMMENT */
  7209.     time_t utime[2];
  7210.     time(utime);
  7211.     *s = ctime(utime);
  7212.     debug(F110,"ztime: MINIX",*s,0);
  7213. #else
  7214. #ifdef ZTIMEV7                /* The regular way */
  7215.     char *asctime();
  7216.     struct tm *localtime();
  7217.     struct tm *tp;
  7218. #ifdef BEBOX
  7219.     unsigned long xclock;
  7220. #else
  7221.     long xclock;
  7222. #endif /* BEBOX */
  7223.     time(&xclock);
  7224.     tp = localtime(&xclock);
  7225.     *s = asctime(tp);
  7226.     debug(F110,"ztime: ZTIMEV7",*s,0);
  7227. #else                    /* Catch-all for others... */
  7228.     *s = "Day Mon 00 00:00:00 0000\n"    /* Return dummy in asctime() format */
  7229.     debug(F110,"ztime: catch-all",*s,0);
  7230. #endif /* ZTIMEV7 */
  7231. #endif /* MINIX */
  7232. #endif /* BSD42 */
  7233. #endif /* PROVX1 */
  7234. #endif /* ATTSV */
  7235. #endif /* HPUX1020 */
  7236. }
  7237.  
  7238. /*  C O N G M  --  Get console terminal modes.  */
  7239.  
  7240. /*
  7241.   Saves initial console mode, and establishes variables for switching
  7242.   between current (presumably normal) mode and other modes.
  7243.   Should be called when program starts, but only after establishing
  7244.   whether program is in the foreground or background.
  7245.   Returns 1 if it got the modes OK, 0 if it did nothing, -1 on error.
  7246. */
  7247. int
  7248. congm() {
  7249.     int fd;
  7250.     if (backgrd || !isatty(0)) {    /* If in background. */
  7251.     cgmf = -1;            /* Don't bother, modes are garbage. */
  7252.     return(-1);
  7253.     }
  7254.     if (cgmf > 0) return(0);        /* Already did this. */
  7255.     debug(F100,"congm getting modes","",0); /* Need to do it. */
  7256. #ifdef aegis
  7257.     ios_$inq_type_uid(ios_$stdin, conuid, st);
  7258.     if (st.all != status_$ok) {
  7259.     fprintf(stderr, "problem getting stdin objtype: ");
  7260.     error_$print(st);
  7261.     }
  7262.     concrp = (conuid == mbx_$uid);
  7263.     conbufn = 0;
  7264. #endif /* aegis */
  7265.  
  7266. #ifndef BEBOX
  7267.     if ((fd = open(CTTNAM,2)) < 0) {    /* Open controlling terminal */
  7268. #ifdef COMMENT
  7269.     fprintf(stderr,"Error opening %s\n", CTTNAM);
  7270.     perror("congm");
  7271.     return(-1);
  7272. #else
  7273.     fd = 0;
  7274. #endif /* COMMENT */
  7275.     }
  7276. #else
  7277.     fd = 0;
  7278. #endif /* !BEBOX */
  7279. #ifdef BSD44ORPOSIX
  7280.     if (tcgetattr(fd,&ccold) < 0) return(-1);
  7281.     if (tcgetattr(fd,&cccbrk) < 0) return(-1);
  7282.     if (tcgetattr(fd,&ccraw) < 0) return(-1);
  7283. #else
  7284. #ifdef ATTSV
  7285.     if (ioctl(fd,TCGETA,&ccold)  < 0) return(-1);
  7286.     if (ioctl(fd,TCGETA,&cccbrk) < 0) return(-1);
  7287.     if (ioctl(fd,TCGETA,&ccraw)  < 0) return(-1);
  7288. #ifdef VXVE
  7289.     cccbrk.c_line = 0;            /* STTY line 0 for CDC VX/VE */
  7290.     if (ioctl(fd,TCSETA,&cccbrk) < 0) return(-1);
  7291.     ccraw.c_line = 0;            /* STTY line 0 for CDC VX/VE */
  7292.     if (ioctl(fd,TCSETA,&ccraw) < 0) return(-1);
  7293. #endif /* VXVE */
  7294. #else
  7295. #ifdef BELLV10
  7296.     if (ioctl(fd,TIOCGETP,&ccold) < 0) return(-1);
  7297.     if (ioctl(fd,TIOCGETP,&cccbrk) < 0) return(-1);
  7298.     if (ioctl(fd,TIOCGETP,&ccraw) < 0) return(-1);
  7299. #else
  7300.     if (gtty(fd,&ccold) < 0) return(-1);
  7301.     if (gtty(fd,&cccbrk) < 0) return(-1);
  7302.     if (gtty(fd,&ccraw) < 0) return(-1);
  7303. #endif /* BELLV10 */
  7304. #endif /* ATTSV */
  7305. #endif /* BSD44ORPOSIX */
  7306. #ifdef sony_news            /* Sony NEWS */
  7307.     if (ioctl(fd,TIOCKGET,&km_con) < 0) { /* Get console Kanji mode */
  7308.     perror("congm error getting Kanji mode");
  7309.     debug(F101,"congm error getting Kanji mode","",0);
  7310.     km_con = -1;            /* Make sure this stays undefined. */
  7311.     return(-1);
  7312.     }
  7313. #endif /* sony_news */
  7314.     if (fd > 0)
  7315.       close(fd);
  7316.     cgmf = 1;                /* Flag that we got them. */
  7317.     return(1);
  7318. }
  7319.  
  7320.  
  7321. /*  C O N C B --  Put console in cbreak mode.  */
  7322.  
  7323. /*  Returns 0 if ok, -1 if not  */
  7324.  
  7325. int
  7326. #ifdef CK_ANSIC
  7327. concb(char esc)
  7328. #else
  7329. concb(esc) char esc;
  7330. #endif /* CK_ANSIC */
  7331. /* concb */ {
  7332.     int x;
  7333.     debug(F101,"concb cgmf","",cgmf);
  7334.     debug(F101,"concb backgrd","",backgrd);
  7335.  
  7336.     if (cgmf < 1)            /* Did we get console modes yet? */
  7337.       if (!backgrd)            /* No, in background? */
  7338.     congm();            /* No, try to get them now. */
  7339.     if (cgmf < 1)            /* Still don't have them? */
  7340.       return(0);            /* Give up. */
  7341.     debug(F101,"concb ttyfd","",ttyfd);
  7342.     debug(F101,"concb ttfdflg","",ttfdflg);
  7343.     if (ttfdflg && ttyfd >= 0 && ttyfd < 3)
  7344.       return(0);
  7345.     if (!isatty(0)) return(0);          /* Only for real ttys */
  7346.     debug(F100,"concb isatty","",0);
  7347.     debug(F101,"concb suspend","",suspend);
  7348.     if (backgrd) return(0);        /* Do nothing if in background. */
  7349.     escchr = esc;                       /* Make this available to other fns */
  7350.     ckxech = 1;                         /* Program can echo characters */
  7351. #ifdef aegis
  7352.     conbufn = 0;
  7353.     if (concrp) return(write(1, "\035\002", 2));
  7354.     if (conuid == input_pad_$uid) {pad_$raw(ios_$stdin, st); return(0);}
  7355. #endif /* aegis */
  7356.  
  7357. #ifdef COHERENT
  7358. #define SVORPOSIX
  7359. #endif /* COHERENT */
  7360.  
  7361. #ifdef Plan9
  7362.     x = p9concb();
  7363. #else
  7364. #ifndef SVORPOSIX            /* BSD, V7, etc */
  7365.     cccbrk.sg_flags |= CBREAK;          /* Set to character wakeup, */
  7366.     cccbrk.sg_flags &= ~ECHO;           /* no echo. */
  7367. #ifdef BELLV10
  7368.     x = ioctl(0,TIOCSETP,&cccbrk);
  7369. #else
  7370.     x = stty(0,&cccbrk);
  7371. #endif /* BELLV10 */
  7372. #else                    /* Sys V and POSIX */
  7373. #ifndef OXOS
  7374.     debug(F101,"concb cccbrk.c_flag","",cccbrk.c_lflag);
  7375. #ifdef QNX
  7376.     /* Don't mess with IEXTEN */
  7377.     cccbrk.c_lflag &= ~(ICANON|ECHO);
  7378. #else
  7379. #ifdef COHERENT
  7380.     cccbrk.c_lflag &= ~(ICANON|ECHO);
  7381. #else
  7382.     cccbrk.c_lflag &= ~(ICANON|ECHO|IEXTEN);
  7383. #endif /* COHERENT */
  7384. #endif /* QNX */
  7385.     cccbrk.c_lflag |= ISIG;        /* Allow SIGINT, etc, in command mode. */
  7386. #else /* OXOS */
  7387.     debug(F100,"concb OXOS is defined","",0);
  7388.     cccbrk.c_lflag &= ~(ICANON|ECHO);
  7389.     cccbrk.c_cc[VDISCARD] = cccbrk.c_cc[VLNEXT] = CDISABLE;
  7390. #endif /* OXOS */
  7391. #ifdef VSUSP
  7392.     debug(F101,"concb c_cc[VSUSP]","",cccbrk.c_cc[VSUSP]);
  7393. #endif /* VSUSP */
  7394. #ifndef VINTR
  7395.     debug(F101,"concb c_cc[0]","",cccbrk.c_cc[0]);
  7396.     cccbrk.c_cc[0] = 003;               /* Interrupt char is Control-C */
  7397. #else
  7398.     debug(F101,"concb c_cc[VINTR]","",cccbrk.c_cc[0]);
  7399.     cccbrk.c_cc[VINTR] = 003;
  7400. #endif /* VINTR */
  7401. #ifndef VQUIT
  7402.     cccbrk.c_cc[1] = escchr;            /* escape during packet modes */
  7403. #else
  7404.     cccbrk.c_cc[VQUIT] = escchr;
  7405. #endif /* VQUIT */
  7406. #ifndef VEOF
  7407.     cccbrk.c_cc[4] = 1;
  7408. #else
  7409. #ifndef OXOS
  7410. #ifdef VMIN
  7411.     cccbrk.c_cc[VMIN] = 1;
  7412. #endif /* VMIN */
  7413. #else /* OXOS */
  7414.     cccbrk.c_min = 1;
  7415. #endif /* OXOS */
  7416. #endif /* VEOF */
  7417. #ifdef ZILOG
  7418.     cccbrk.c_cc[5] = 0;
  7419. #else
  7420. #ifndef VEOL
  7421.     cccbrk.c_cc[5] = 1;
  7422. #else
  7423. #ifndef OXOS
  7424. #ifdef VTIME
  7425.     cccbrk.c_cc[VTIME] = 1;
  7426. #endif /* VTIME */
  7427. #else /* OXOS */
  7428.     cccbrk.c_time = 1;
  7429. #endif /* OXOS */
  7430. #endif /* VEOL */
  7431. #endif /* ZILOG */
  7432. #ifdef BSD44ORPOSIX            /* Set new modes */
  7433.     x = tcsetattr(0,TCSADRAIN,&cccbrk);
  7434. #else /* ATTSV */                  /* or the POSIX way */
  7435.     x = ioctl(0,TCSETAW,&cccbrk);    /* the Sys V way */
  7436. #endif /* BSD44ORPOSIX */
  7437. #endif /* SVORPOSIX */
  7438.  
  7439. #ifdef COHERENT
  7440. #undef SVORPOSIX
  7441. #endif /* COHERENT */
  7442.  
  7443. #ifndef aegis
  7444. #ifndef NOSETBUF
  7445.     if (x > -1) setbuf(stdout,NULL);    /* Make console unbuffered. */
  7446. #endif /* NOSETBUF */
  7447. #endif /* aegis */
  7448.  
  7449. #ifdef  V7
  7450. #ifndef MINIX
  7451.     if (kmem[CON] < 0) {
  7452.         qaddr[CON] = initrawq(0);
  7453.         if((kmem[CON] = open("/dev/kmem", 0)) < 0) {
  7454.             fprintf(stderr, "Can't read /dev/kmem in concb.\n");
  7455.             perror("/dev/kmem");
  7456.             exit(1);
  7457.         }
  7458.     }
  7459. #endif /* MINIX */
  7460. #endif /* V7 */
  7461. #endif /* Plan9 */
  7462.     debug(F101,"concb returns","",x);
  7463.     return(x);
  7464. }
  7465.  
  7466. /*  C O N B I N  --  Put console in binary mode  */
  7467.  
  7468. /*  Returns 0 if ok, -1 if not  */
  7469.  
  7470. int
  7471. #ifdef CK_ANSIC
  7472. conbin(char esc)
  7473. #else
  7474. conbin(esc) char esc;
  7475. #endif /* CK_ANSIC */
  7476. /* conbin */  {
  7477.     if (!isatty(0)) return(0);          /* only for real ttys */
  7478.     congm();                /* Get modes if necessary. */
  7479.     debug(F100,"conbin","",0);
  7480.     escchr = esc;                       /* Make this available to other fns */
  7481.     ckxech = 1;                         /* Program can echo characters */
  7482. #ifdef aegis
  7483.     conbufn = 0;
  7484.     if (concrp) return(write(1, "\035\002", 2));
  7485.     if (conuid == input_pad_$uid) {
  7486.     pad_$raw(ios_$stdin, st);
  7487.     return(0);
  7488.       }
  7489. #endif /* aegis */
  7490.  
  7491. #ifdef COHERENT
  7492. #define SVORPOSIX
  7493. #endif /* COHERENT */
  7494.  
  7495. #ifdef Plan9
  7496.     return p9conbin();
  7497. #else
  7498. #ifdef SVORPOSIX
  7499. #ifndef OXOS
  7500. #ifdef QNX
  7501.     ccraw.c_lflag &= ~(ISIG|ICANON|ECHO);
  7502. #else
  7503. #ifdef COHERENT
  7504.     ccraw.c_lflag &= ~(ISIG|ICANON|ECHO);
  7505. #else
  7506.     ccraw.c_lflag &= ~(ISIG|ICANON|ECHO|IEXTEN);
  7507. #endif /* COHERENT */
  7508. #endif /* QNX */
  7509. #else /* OXOS */
  7510.     ccraw.c_lflag &= ~(ISIG|ICANON|ECHO);
  7511.     ccraw.c_cc[VDISCARD] = ccraw.c_cc[VLNEXT] = CDISABLE;
  7512. #endif /* OXOS */
  7513.     ccraw.c_iflag |= (BRKINT|IGNPAR);
  7514. /*
  7515.   Note that for terminal sessions we disable Xon/Xoff flow control to allow
  7516.   the passage ^Q and ^S as data characters for EMACS, and to allow XMODEM
  7517.   transfers to work when C-Kermit is in the middle, etc.  Hardware flow
  7518.   control, if in use, is not affected.
  7519. */
  7520. #ifdef ATTSV
  7521. #ifdef BSD44
  7522.     ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IXON|IXANY|IXOFF
  7523.                         |INPCK|ISTRIP);
  7524. #else
  7525.     ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|IXON|IXANY|IXOFF
  7526.                         |INPCK|ISTRIP);
  7527. #endif /* BSD44 */
  7528. #else /* POSIX */
  7529.     ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IXON|IXOFF|INPCK|ISTRIP);
  7530. #endif /* ATTSV */
  7531.     ccraw.c_oflag &= ~OPOST;
  7532. #ifdef COMMENT
  7533. /*
  7534.   WHAT THE HECK WAS THIS FOR?
  7535.   The B9600 setting (obviously) prevents CONNECT from working at any
  7536.   speed other than 9600 when you are logged in to the 7300 on a serial
  7537.   line.  Maybe some of the other flags are necessary -- if so, put back
  7538.   the ones that are needed.  This code is supposed to work the same, no
  7539.   matter whether you are logged in to the 7300 on the real console device,
  7540.   or through a serial port.
  7541. */
  7542. #ifdef ATT7300
  7543.     ccraw.c_cflag = CLOCAL | B9600 | CS8 | CREAD | HUPCL;
  7544. #endif /* ATT7300 */
  7545. #endif /* COMMENT */
  7546.  
  7547. /*** Kermit used to put the console in 8-bit raw mode, but some users have
  7548.  *** pointed out that this should not be done, since some sites actually
  7549.  *** use terminals with parity settings on their Unix systems, and if we
  7550.  *** override the current settings and stop doing parity, then their terminals
  7551.  *** will display blotches for characters whose parity is wrong.  Therefore,
  7552.  *** the following two lines are commented out (Larry Afrin, Clemson U):
  7553.  ***
  7554.  ***   ccraw.c_cflag &= ~(PARENB|CSIZE);
  7555.  ***   ccraw.c_cflag |= (CS8|CREAD);
  7556.  ***
  7557.  *** Sys III/V sites that have trouble with this can restore these lines.
  7558.  ***/
  7559. #ifndef VINTR
  7560.     ccraw.c_cc[0] = 003;        /* Interrupt char is Ctrl-C */
  7561. #else
  7562.     ccraw.c_cc[VINTR] = 003;
  7563. #endif /* VINTR */
  7564. #ifndef VQUIT
  7565.     ccraw.c_cc[1] = escchr;        /* Escape during packet mode */
  7566. #else
  7567.     ccraw.c_cc[VQUIT] = escchr;
  7568. #endif /* VQUIT */
  7569. #ifndef VEOF
  7570.     ccraw.c_cc[4] = 1;
  7571. #else
  7572. #ifndef OXOS
  7573. #ifdef VMIN
  7574.     ccraw.c_cc[VMIN] = 1;
  7575. #endif /* VMIN */
  7576. #else /* OXOS */
  7577.     ccraw.c_min = 1;
  7578. #endif /* OXOS */
  7579. #endif /* VEOF */
  7580.  
  7581. #ifdef ZILOG
  7582.     ccraw.c_cc[5] = 0;
  7583. #else
  7584. #ifndef VEOL
  7585.     ccraw.c_cc[5] = 1;
  7586. #else
  7587. #ifndef OXOS
  7588. #ifdef VTIME
  7589.     ccraw.c_cc[VTIME] = 1;
  7590. #endif /* VTIME */
  7591. #else /* OXOS */
  7592.     ccraw.c_time = 1;
  7593. #endif /* OXOS */
  7594. #endif /* VEOL */
  7595. #endif /* ZILOG */
  7596.  
  7597. #ifdef BSD44ORPOSIX
  7598.     return(tcsetattr(0,TCSADRAIN,&ccraw));
  7599. #else
  7600.     return(ioctl(0,TCSETAW,&ccraw));    /* Set new modes. */
  7601. #endif /* BSD44ORPOSIX */
  7602.  
  7603. #else /* Berkeley, etc. */
  7604.     ccraw.sg_flags |= (RAW|TANDEM);     /* Set rawmode, XON/XOFF (ha) */
  7605.     ccraw.sg_flags &= ~(ECHO|CRMOD);    /* Set char wakeup, no echo */
  7606. #ifdef BELLV10
  7607.     return(ioctl(0,TIOCSETP,&ccraw));
  7608. #else
  7609.     return(stty(0,&ccraw));
  7610. #endif /* BELLV10 */
  7611. #endif /* SVORPOSIX */
  7612. #endif /* Plan9 */
  7613.  
  7614. #ifdef COHERENT
  7615. #undef SVORPOSIX
  7616. #endif /* COHERENT */
  7617.  
  7618. }
  7619.  
  7620.  
  7621. /*  C O N R E S  --  Restore the console terminal  */
  7622.  
  7623. int
  7624. conres() {
  7625.     debug(F101,"conres cgmf","",cgmf);
  7626.     if (cgmf < 1) return(0);        /* Do nothing if modes unchanged */
  7627.     if (!isatty(0)) return(0);          /* only for real ttys */
  7628.     debug(F100,"conres isatty ok","",0);
  7629.     ckxech = 0;                         /* System should echo chars */
  7630.  
  7631. #ifdef aegis
  7632.     conbufn = 0;
  7633.     if (concrp) return(write(1, "\035\001", 2));
  7634.     if (conuid == input_pad_$uid) {
  7635.     pad_$cooked(ios_$stdin, st);
  7636.     return(0);
  7637.     }
  7638. #endif /* aegis */
  7639.  
  7640. #ifdef Plan9
  7641.     p9conres();
  7642. #else
  7643. #ifdef BSD44ORPOSIX
  7644.     debug(F100,"conres restoring tcsetattr","",0);
  7645.     return(tcsetattr(0,TCSADRAIN,&ccold));
  7646. #else
  7647. #ifdef ATTSV
  7648.     debug(F100,"conres restoring ioctl","",0);
  7649.     return(ioctl(0,TCSETAW,&ccold));
  7650. #else /* BSD, V7, and friends */
  7651. #ifdef sony_news            /* Sony NEWS */
  7652.     if (km_con != -1)
  7653.       ioctl(0,TIOCKSET,&km_con);    /* Restore console Kanji mode */
  7654. #endif /* sony_news */
  7655.     msleep(100);
  7656.     debug(F100,"conres restoring stty","",0);
  7657. #ifdef BELLV10
  7658.     return(ioctl(0,TIOCSETP,&ccold));
  7659. #else
  7660.     return(stty(0,&ccold));
  7661. #endif /* BELLV10 */
  7662. #endif /* ATTSV */
  7663. #endif /* BSD44ORPOSIX */
  7664. #endif /* Plan9 */
  7665. }
  7666.  
  7667. /*  C O N O C  --  Output a character to the console terminal  */
  7668.  
  7669. int
  7670. #ifdef CK_ANSIC
  7671. conoc(char c)
  7672. #else
  7673. conoc(c) char c;
  7674. #endif /* CK_ANSIC */
  7675. /* conoc */ {
  7676. #ifdef Plan9
  7677.     return conwrite(&c,1);
  7678. #else
  7679.     return(write(1,&c,1));
  7680. #endif /* Plan9 */
  7681. }
  7682.  
  7683. /*  C O N X O  --  Write x characters to the console terminal  */
  7684.  
  7685. int
  7686. conxo(x,s) int x; char *s; {
  7687. #ifdef Plan9
  7688.     return(conwrite(s,x));
  7689. #else
  7690.     return(write(1,s,x));
  7691. #endif /* Plan9 */
  7692. }
  7693.  
  7694. /*  C O N O L  --  Write a line to the console terminal  */
  7695.  
  7696. int
  7697. conol(s) char *s; {
  7698.     int len;
  7699.     len = (int)strlen(s);
  7700. #ifdef Plan9
  7701.     return(conwrite(s,len));
  7702. #else
  7703.     return(write(1,s,len));
  7704. #endif /* Plan9 */
  7705. }
  7706.  
  7707. /*  C O N O L A  --  Write an array of lines to the console terminal */
  7708.  
  7709. int
  7710. conola(s) char *s[]; {
  7711.     int i;
  7712.     for (i=0 ; *s[i] ; i++) if (conol(s[i]) < 0) return(-1);;
  7713.     return(0);
  7714. }
  7715.  
  7716. /*  C O N O L L  --  Output a string followed by CRLF  */
  7717.  
  7718. int
  7719. conoll(s) char *s; {
  7720.     conol(s);
  7721. #ifdef Plan9
  7722.     return(conwrite("\r\n", 2));
  7723. #else
  7724.     return(write(1,"\r\n",2));
  7725. #endif /* Plan9 */
  7726. }
  7727.  
  7728. /*  C O N C H K  --  Return how many characters available at console  */
  7729. /*
  7730.   We could also use select() here to cover a few more systems that are not
  7731.   covered by any of the following, e.g. HP-UX 9.0x on the model 800.
  7732. */
  7733. int
  7734. conchk() {
  7735.     static int contyp = 0;        /* +1 for isatty, -1 otherwise */
  7736.  
  7737.     if (contyp == 0)            /* This prevents unnecessary */
  7738.       contyp = (isatty(0) ? 1 : -1);    /* duplicated calls to isatty() */
  7739.     debug(F101,"conchk contyp","",contyp);
  7740.     if (backgrd || (contyp < 0))
  7741.       return(0);
  7742.  
  7743. #ifdef aegis
  7744.     if (conbufn > 0) return(conbufn);   /* use old count if nonzero */
  7745.  
  7746.     /* read in more characters */
  7747.     conbufn = ios_$get(ios_$stdin,
  7748.               ios_$cond_opt, conbuf, (long)sizeof(conbuf), st);
  7749.     if (st.all != status_$ok) conbufn = 0;
  7750.     conbufp = conbuf;
  7751.     return(conbufn);
  7752. #else
  7753.     return(in_chk(0));
  7754. #endif /* aegis */
  7755. }
  7756.  
  7757. /*  C O N I N C  --  Get a character from the console  */
  7758. /*
  7759.   Call with timo > 0 to do a timed read, timo == 0 to do an untimed blocking
  7760.   read.  Upon success, returns the character.  Upon failure, returns -1.
  7761.   A timed read that does not complete within the timeout period returns -1.
  7762. */
  7763. int
  7764. coninc(timo) int timo; {
  7765.     int n = 0; CHAR ch;
  7766.     int xx;
  7767. #ifdef aegis                /* Apollo Aegis only... */
  7768.     debug(F101,"coninc timo","",timo);
  7769.     fflush(stdout);
  7770.     if (conchk() > 0) {
  7771.     --conbufn;
  7772.     return((unsigned)(*conbufp++ & 0xff));
  7773.     }
  7774. #endif /* aegis */
  7775.  
  7776.     if (timo <= 0 ) {                   /* Untimed, blocking read. */
  7777.     while (1) {            /* Keep trying till we get one. */
  7778.         n = read(0, &ch, 1);    /* Read a character. */
  7779.         if (n == 0) continue;    /* Shouldn't happen. */
  7780.         if (n > 0)            /* If read was successful, */
  7781.           return((unsigned)(ch & 0xff)); /* return the character. */
  7782.  
  7783. /* Come here if read() returned an error. */
  7784.  
  7785.         debug(F101, "coninc(0) errno","",errno); /* Log the error. */
  7786. #ifndef OXOS
  7787. #ifdef SVORPOSIX
  7788. #ifdef CIE                             /* CIE Regulus has no EINTR symbol? */
  7789. #ifndef EINTR
  7790. #define EINTR 4
  7791. #endif /* EINTR */
  7792. #endif /* CIE */
  7793. /*
  7794.   This routine is used for several different purposes.  In CONNECT mode, it is
  7795.   used to do an untimed, blocking read from the keyboard in the lower CONNECT
  7796.   fork.  During local-mode file transfer, it reads a character from the
  7797.   console to interrupt the file transfer (like A for a status report, X to
  7798.   cancel a file, etc).  Obviously, we don't want the reads in the latter case
  7799.   to be blocking, or the file transfer would stop until the user typed
  7800.   something.  Unfortunately, System V does not allow the console device input
  7801.   buffer to be sampled nondestructively (e.g. by conchk()), so a kludge is
  7802.   used instead.  During local-mode file transfer, the SIGQUIT signal is armed
  7803.   and trapped by esctrp(), and this routine pretends to have read the quit
  7804.   character from the keyboard normally.  But, kludge or no kludge, the read()
  7805.   issued by this command, under System V only, can fail if a signal -- ANY
  7806.   signal -- is caught while the read is pending.  This can occur not only when
  7807.   the user types the quit character, but also during telnet negotiations, when
  7808.   the lower CONNECT fork signals the upper one about an echoing mode change.
  7809.   When this happens, we have to post the read() again.  This is apparently not
  7810.   a problem in BSD-based UNIX versions.
  7811. */
  7812.         if (errno == EINTR)        /* Read interrupted. */
  7813.           if (conesc)  {        /* If by SIGQUIT, */
  7814.           conesc = 0;        /* the conesc variable is set, */
  7815.           return(escchr);    /* so return the escape character. */
  7816.          } else continue;        /* By other signal, try again. */
  7817. #else
  7818. /*
  7819.   This might be dangerous, but let's do this on non-System V versions too,
  7820.   since at least one SunOS 4.1.2 user complains of immediate disconnections
  7821.   upon first making a TELNET connection.
  7822. */
  7823.         if (errno == EINTR)        /* Read interrupted. */
  7824.           continue;
  7825. #endif /* SVORPOSIX */
  7826. #else /* OXOS */
  7827.         if (errno == EINTR)        /* Read interrupted. */
  7828.           continue;
  7829. #endif /* OXOS */
  7830.         return(-1);            /* Error */
  7831.     }
  7832.     }
  7833.  
  7834.     if (timo <= 0)
  7835.       /* This should never happen */
  7836.       debug(F100,"coninc HORRIBLE ERROR","",0);
  7837.  
  7838. /* Timed read... */
  7839.  
  7840.     saval = signal(SIGALRM,timerh);    /* Set up timeout handler. */
  7841.     xx = alarm(timo);            /* Set the alarm. */
  7842.     debug(F101,"coninc alarm set","",xx);
  7843.     if (
  7844. #ifdef CK_POSIX_SIG
  7845.     sigsetjmp(sjbuf,1)
  7846. #else
  7847.     setjmp(sjbuf)
  7848. #endif /* CK_POSIX_SIG */
  7849.     )                /* The read() timed out. */
  7850.       n = -2;                /* Code for timeout. */
  7851.     else
  7852.       n = read(0, &ch, 1);
  7853.     ttimoff();                /* Turn off timer */
  7854.     if (n > 0)                /* Got character OK. */
  7855.       return((unsigned)(ch & 0xff));    /* Return it. */
  7856.  
  7857. /*
  7858.   read() returned an error.  Same deal as above, but without the loop.
  7859. */
  7860.     debug(F101, "coninc(timo) n","",n);
  7861.     debug(F101, "coninc(timo) errno","",errno);
  7862. #ifndef OXOS
  7863. #ifdef SVORPOSIX
  7864.     if (n == -1 && errno == EINTR && conesc != 0) {
  7865.     conesc = 0;
  7866.     return(escchr);            /* User entered escape character. */
  7867.     } else                /* n == 0 shouldn't happen. */
  7868. #endif /* SVORPOSIX */
  7869. #endif /* ! OXOS */
  7870.       return(-1);
  7871. }
  7872.  
  7873. /*  C O N G K S  --  Console Get Keyboard Scancode  */
  7874.  
  7875. #ifndef congks
  7876. /*
  7877.   This function needs to be filled in with the various system-dependent
  7878.   system calls used by SUNOS, NeXT OS, Xenix, Aviion, etc, to read a full
  7879.   keyboard scan code.  For now, it's a dummy.
  7880. */
  7881. int
  7882. congks(timo) int timo; {
  7883.     return(coninc(timo));
  7884. }
  7885. #endif /* congks */
  7886.  
  7887. #ifdef ATT7300
  7888.  
  7889. /*  A T T D I A L  --  Dial up the remote system using internal modem
  7890.  * Purpose: to open and dial a number on the internal modem available on the
  7891.  * ATT7300 UNIX PC.  Written by Joe Doupnik. Superceeds version written by
  7892.  * Richard E. Hill, Dickinson, TX. which employed dial(3c).
  7893.  * Uses information in <sys/phone.h> and our status int attmodem.
  7894.  */
  7895. attdial(ttname,speed,telnbr) char *ttname,*telnbr; long speed; {
  7896.     char *telnum;
  7897.     int ttclos();
  7898.  
  7899.     attmodem &= ~ISMODEM;                       /* modem not in use yet */
  7900.                     /* Ensure O_NDELAY is set, else i/o traffic hangs */
  7901.                     /* We turn this flag off once the dial is complete */
  7902.     fcntl(ttyfd, F_SETFL, fcntl(ttyfd, F_GETFL, 0) | O_NDELAY);
  7903.  
  7904.     /* Condition line, check availability & DATA mode, turn on speaker */
  7905.     if (ioctl(ttyfd,PIOCOFFHOOK, &dialer) == -1) {
  7906.         printf("cannot access phone\n");
  7907.         ttclos(0);
  7908.         return (-2);
  7909.     }
  7910.     ioctl(ttyfd,PIOCGETP,&dialer);      /* get phone dialer parameters */
  7911.  
  7912.     if (dialer.c_lineparam & VOICE) {    /* phone must be in DATA mode */
  7913.         printf(" Should not dial with modem in VOICE mode.\n");
  7914.         printf(" Exit Kermit, switch to DATA and retry call.\n");
  7915.         ttclos(0);
  7916.         return (-2);
  7917.     }
  7918. #ifdef ATTTONED                /* Old way, tone dialing only. */
  7919.     dialer.c_lineparam = DATA | DTMF;    /* Dial with tones, */
  7920.     dialer.c_lineparam &= ~PULSE;    /* not with pulses. */
  7921. #else
  7922.     /* Leave current pulse/tone state alone. */
  7923.     /* But what about DATA?  Add it back if you have trouble. */
  7924.     /* sys/phone says you get DATA automatically by opening device RDWR */
  7925. #endif
  7926.     dialer.c_waitdialtone = 5;                  /* wait 5 sec for dialtone */
  7927. #ifdef COMMENT
  7928.     dialer.c_feedback = SPEAKERON|NORMSPK|RINGON;  /* control speaker */
  7929. #else
  7930.     /* sys/phone says RINGON used only for incoming voice calls */
  7931.     dialer.c_feedback &= ~(SOFTSPK|LOUDSPK);
  7932.     dialer.c_feedback |= SPEAKERON|NORMSPK;
  7933. #endif
  7934.     dialer.c_waitflash = 500;                   /* 0.5 sec flash hook */
  7935.     if(ioctl(ttyfd,PIOCSETP,&dialer) == -1) {   /* set phone parameters */
  7936.         printf("Cannot set modem characteristics\n");
  7937.         ttclos(0);
  7938.         return (-2);
  7939.     }
  7940.     ioctl(ttyfd,PIOCRECONN,0);        /* Turns on speaker for pulse */
  7941.  
  7942. #ifdef COMMENT
  7943.     fprintf(stderr,"Phone line status. line_par:%o dialtone_wait:%o \
  7944. line_status:%o feedback:%o\n",
  7945.     dialer.c_lineparam, dialer.c_waitdialtone,
  7946.     dialer.c_linestatus, dialer.c_feedback);
  7947. #endif
  7948.  
  7949.     attmodem |= ISMODEM;                        /* modem is now in-use */
  7950.     sleep(1);
  7951.     for (telnum = telnbr; *telnum != '\0'; telnum++)    /* dial number */
  7952. #ifdef ATTTONED
  7953.       /* Tone dialing only */
  7954.       if (ioctl(ttyfd,PIOCDIAL,telnum) != 0) {
  7955.       perror("Error in dialing");
  7956.       ttclos(0);
  7957.       return(-2);
  7958.       }
  7959. #else /* Allow Pulse or Tone dialing */
  7960.     switch (*telnum) {
  7961.       case 't': case 'T': case '%':    /* Tone dialing requested */
  7962.     dialer.c_lineparam |= DTMF;
  7963.     dialer.c_lineparam &= ~PULSE;
  7964.     if (ioctl(ttyfd,PIOCSETP,&dialer) == -1) {
  7965.         printf("Cannot set modem to tone dialing\n");
  7966.         ttclos(0);
  7967.         return(-2);
  7968.     }
  7969.     break;
  7970.       case 'd': case 'D': case 'p': case 'P': case '^':
  7971.     dialer.c_lineparam |= PULSE;
  7972.     dialer.c_lineparam &= ~DTMF;
  7973.     if (ioctl(ttyfd,PIOCSETP,&dialer) == -1) {
  7974.         printf("Cannot set modem to pulse dialing\n");
  7975.         ttclos(0);
  7976.         return(-2);
  7977.     }
  7978.     break;
  7979.       default:
  7980.         if (ioctl(ttyfd,PIOCDIAL,telnum) != 0) {
  7981.         perror("Dialing error");
  7982.         ttclos(0);
  7983.         return(-2);
  7984.     }
  7985.     break;
  7986.     }
  7987. #endif
  7988.  
  7989.     ioctl(ttyfd,PIOCDIAL,"@");        /* terminator for data call */
  7990.     do {                /* wait for modems to Connect */
  7991.         if (ioctl(ttyfd,PIOCGETP,&dialer) != 0)    { /* get params */
  7992.         perror("Cannot get modems to connect");
  7993.         ttclos(0);
  7994.         return(-2);
  7995.     }
  7996.     } while ((dialer.c_linestatus & MODEMCONNECTED) == 0);
  7997.     /* Turn off O_NDELAY flag now. */
  7998.     fcntl(ttyfd, F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY);
  7999.     signal(SIGHUP, ttclos);             /* hangup on loss of carrier */
  8000.     return(0);                          /* return success */
  8001. }
  8002.  
  8003. /*
  8004.   Offgetty, ongetty functions. These function get the 'getty(1m)' off
  8005.   and restore it to the indicated line.  Shell's return codes are:
  8006.     0: Can't do it.  Probably a user logged on.
  8007.     1: No need.  No getty on that line.
  8008.     2: Done, you should restore the getty when you're done.
  8009.   DOGETY System(3), however, returns them as 0, 256, 512, respectively.
  8010.   Thanks to Kevin O'Gorman, Anarm Software Systems.
  8011.  
  8012.    getoff.sh looks like:   geton.sh looks like:
  8013.      setgetty $1 0           setgetty $1 1
  8014.      err=$?                  exit $?
  8015.      sleep 2
  8016.      exit $err
  8017. */
  8018.  
  8019. /*  O F F G E T T Y  --  Turn off getty(1m) for the communications tty line
  8020.  * and get status so it can be restarted after the line is hung up.
  8021.  */
  8022. int
  8023. offgetty(ttname) char *ttname; {
  8024.     char temp[30];
  8025.     while (*ttname != '\0') ttname++;       /* seek terminator of path */
  8026.     ttname -= 3;                            /* get last 3 chars of name */
  8027.     sprintf(temp,"/usr/bin/getoff.sh %s",ttname);
  8028.     return(zsyscmd(temp));
  8029. }
  8030.  
  8031. /*  O N G E T T Y  --  Turn on getty(1m) for the communications tty line */
  8032.  
  8033. int
  8034. ongetty(ttname) char *ttname; {
  8035.     char temp[30];
  8036.     while (*ttname != '\0') ttname++;       /* comms tty path name */
  8037.     ttname -= 3;
  8038.     sprintf(temp,"/usr/bin/geton.sh %s",ttname);
  8039.     return(zsyscmd(temp));
  8040. }
  8041. #endif /* ATT7300 */
  8042.  
  8043. /*  T T S C A R R  --  Set ttcarr variable, controlling carrier handling.
  8044.  *
  8045.  *  0 = Off: Always ignore carrier. E.g. you can connect without carrier.
  8046.  *  1 = On: Heed carrier, except during dialing. Carrier loss gives disconnect.
  8047.  *  2 = Auto: For "modem direct": The same as "Off".
  8048.  *            For real modem types: Heed carrier during connect, but ignore
  8049.  *                it anytime else.  Compatible with pre-5A C-Kermit versions.
  8050.  *
  8051.  * As you can see, this setting does not affect dialing, which always ignores
  8052.  * carrier (unless there is some special exception for some modem type).  It
  8053.  * does affect ttopen() if it is set before ttopen() is used.  This setting
  8054.  * takes effect on the next call to ttopen()/ttpkt()/ttvt().  And they are
  8055.  * (or should be) always called before any communications is tried, which
  8056.  * means that, practically speaking, the effect is immediate.
  8057.  *
  8058.  * Of course, nothing of this applies to remote mode (xlocal = 0).
  8059.  *
  8060.  * Someone has yet to uncover how to manipulate the carrier in the BSD
  8061.  * environment (or any non-termio using environment).  Until that time, this
  8062.  * will simply be a no-op for BSD.
  8063.  *
  8064.  * Note that in previous versions, the carrier was most often left unchanged
  8065.  * in ttpkt()/ttvt() unless they were called with FLO_DIAL or FLO_DIAX.  This
  8066.  * has changed.  Now it is controlled by ttcarr in conjunction with these
  8067.  * modes.
  8068.  */
  8069. int
  8070. ttscarr(carrier) int carrier; {
  8071.     ttcarr = carrier;
  8072.     debug(F101, "ttscarr","",ttcarr);
  8073.     return(ttcarr);
  8074. }
  8075.  
  8076. /* C A R R C T L  --  Set tty modes for carrier treatment.
  8077.  *
  8078.  * Sets the appropriate bits in a termio or sgttyb struct for carrier control
  8079.  * (actually, there are no bits in sgttyb for that), or performs any other
  8080.  * operations needed to control this on the current system.  The function does
  8081.  * not do the actual TCSETA or stty, since often we want to set other bits too
  8082.  * first.  Don't call this function when xlocal is 0, or the tty is not opened.
  8083.  *
  8084.  * We don't know how to do anything like carrier control on non-ATTSV systems,
  8085.  * except, apparently, ultrix.  See above.  It is also known that this doesn't
  8086.  * have much effect on a Xenix system.  For Xenix, one should switch back and
  8087.  * forth between the upper and lower case device files.  Maybe later. 
  8088.  * Presently, Xenix will stick to the mode it was opened with.
  8089.  *
  8090.  * carrier: 0 = ignore carrier, 1 = require carrier.
  8091.  * The current state is saved in curcarr, and checked to save labour.
  8092.  */
  8093. #ifdef SVORPOSIX
  8094. int
  8095. #ifdef BSD44ORPOSIX
  8096. carrctl(ttpar, carrier)    struct termios *ttpar; int carrier;
  8097. #else /* ATTSV */
  8098. carrctl(ttpar, carrier)    struct termio *ttpar; int carrier;
  8099. #endif /* BSD44ORPOSIX */
  8100. /* carrctl */ {
  8101.     debug(F101, "carrctl","",carrier);
  8102.     if (carrier)
  8103.       ttpar->c_cflag &= ~CLOCAL;
  8104.     else
  8105.       ttpar->c_cflag |= CLOCAL;
  8106.     return(0);
  8107. }
  8108. #else /* Berkeley, V7, et al... */
  8109. int
  8110. carrctl(ttpar, carrier) struct sgttyb *ttpar; int carrier; {
  8111.     debug(F101, "carrctl","",carrier);
  8112.     if (carrier == curcarr)
  8113.       return(0);
  8114.     curcarr = carrier;
  8115. #ifdef ultrix
  8116. #ifdef COMMENT
  8117. /*
  8118.   Old code from somebody at DEC that tends to get stuck, time out, etc.
  8119. */
  8120.     if (carrier) {
  8121.     ioctl(ttyfd, TIOCMODEM, &temp);
  8122.     ioctl(ttyfd, TIOCHPCL, 0);
  8123.     } else {
  8124.     /* (According to the manuals, TIOCNCAR should be preferred */
  8125.     /* over TIOCNMODEM...) */
  8126.     ioctl(ttyfd, TIOCNMODEM, &temp);
  8127.     }
  8128. #else
  8129. /*
  8130.   New code from Jamie Watson that, he says, eliminates the problems.
  8131. */
  8132.     if (carrier) {
  8133.     ioctl(ttyfd, TIOCCAR);
  8134.     ioctl(ttyfd, TIOCHPCL);
  8135.     } else {
  8136.     ioctl(ttyfd, TIOCNCAR);
  8137.     }
  8138. #endif /* COMMENT */
  8139. #endif /* ultrix */
  8140.     return(0);
  8141. }
  8142. #endif /* SVORPOSIX */
  8143.  
  8144.  
  8145. /*  T T G M D M  --  Get modem signals  */
  8146. /*
  8147.  Looks for RS-232 modem signals, and returns those that are on in as its
  8148.  return value, in a bit mask composed of the BM_xxx values defined in ckcdeb.h.
  8149.  Returns: 
  8150.  -3 Not implemented
  8151.  -2 if the communication device does not have modem control (e.g. telnet)
  8152.  -1 on error.
  8153.  >= 0 on success, with a bit mask containing the modem signals that are on.
  8154. */
  8155.  
  8156. /*
  8157.   Define the symbol K_MDMCTL if we have Sys V R3 / 4.3 BSD style
  8158.   modem control, namely the TIOCMGET ioctl.
  8159. */
  8160.  
  8161. #ifdef BSD43
  8162. #define K_MDMCTL
  8163. #endif
  8164.  
  8165. #ifdef SUNOS4
  8166. #define K_MDMCTL
  8167. #endif
  8168.  
  8169. #ifdef QNX
  8170. #define K_MDMCTL
  8171. #else
  8172. #ifdef TIOCMGET
  8173. #define K_MDMCTL
  8174. #endif /* TIOCMGET */
  8175. #endif /* QNX */
  8176.  
  8177. int
  8178. ttgmdm() {
  8179.  
  8180. #ifdef QNX
  8181. #include <sys/qioctl.h>
  8182.  
  8183.     unsigned long y, mdmbits[2] = { 0L, 0L };
  8184.     int z = 0;
  8185.  
  8186.     if (!qnx_ioctl( ttyfd, QCTL_DEV_CTL, &mdmbits[0], 8, &mdmbits[0], 4)) {
  8187.     y = mdmbits[0];
  8188.     if (y & 0x100000L) z |= BM_CTS;    /* Values from comment */
  8189.     if (y & 0x200000L) z |= BM_DSR;    /* in sys/qioctl.h */
  8190.     if (y & 0x800000L) z |= BM_DCD;
  8191.     if (y & 0x400000L) z |= BM_RNG;
  8192.     if (y & 0x000001L) z |= BM_DTR;
  8193.     if (y & 0x000002L) z |= BM_RTS;
  8194.     return(z);
  8195.     } else return(-1);
  8196. #else
  8197. #ifdef HPUX                /* HPUX has its own way */
  8198.     int x, z;
  8199.  
  8200. #ifdef HPUX10                /* Modem flag word */
  8201.     mflag y;                /* mflag typedef'd in <sys/modem.h> */
  8202. #else
  8203. #ifdef HPUX9
  8204.     mflag y;
  8205. #else
  8206. #ifdef HPUX8
  8207.     mflag y;
  8208. #else
  8209.     unsigned long y;            /* Not sure about pre-8.0... */
  8210. #endif /* HPUX8 */
  8211. #endif /* HPUX9 */
  8212. #endif /* HPUX10 */
  8213.  
  8214.     if (netconn)            /* Network connection */
  8215.       return(-2);            /* No modem signals */
  8216.  
  8217.     if (xlocal)                /* Get modem signals */
  8218.       x = ioctl(ttyfd,MCGETA,&y);
  8219.     else
  8220.       x = ioctl(0,MCGETA,&y);
  8221.     if (x < 0) return(-1);
  8222.     debug(F101,"ttgmdm","",y);
  8223.  
  8224.     z = 0;                /* Initialize return value */
  8225.  
  8226. /* Now set bits for each modem signal that is reported to be on. */
  8227.  
  8228. #ifdef MCTS
  8229.     /* Clear To Send */
  8230.     if (y & MCTS) z |= BM_CTS;
  8231. #endif
  8232. #ifdef MDSR
  8233.     /* Data Set Ready */
  8234.     if (y & MDSR) z |= BM_DSR;
  8235. #endif
  8236. #ifdef MDCD
  8237.     /* Carrier */
  8238.     if (y & MDCD) z |= BM_DCD;
  8239. #endif
  8240. #ifdef MRI
  8241.     /* Ring Indicate */
  8242.     if (y & MRI) z |= BM_RNG;
  8243. #endif
  8244. #ifdef MDTR
  8245.     /* Data Terminal Ready */
  8246.     if (y & MDTR) z |= BM_DTR;
  8247. #endif
  8248. #ifdef MRTS
  8249.     /* Request To Send */
  8250.     if (y & MRTS) z |= BM_RTS;
  8251. #endif
  8252.     return(z);
  8253.  
  8254. #else /* ! HPUX */
  8255.  
  8256. #ifdef K_MDMCTL
  8257. /*
  8258.   Note, <sys/ttycom> might have already been included by by <sys/ioctl.h>.
  8259.   Hence the following ifndef on a symbol which is defined there.
  8260. */
  8261. #ifndef TIOCMGET
  8262. #include <sys/ttycom.h>
  8263. #endif /* TIOCMGET */
  8264.  
  8265.     int x, y, z;
  8266.  
  8267.     if (netconn)            /* Network connection */
  8268.       return(-2);            /* No modem signals */
  8269.  
  8270.     if (xlocal)
  8271.       x = ioctl(ttyfd,TIOCMGET,&y);    /* Get modem signals. */
  8272.     else
  8273.       x = ioctl(0,TIOCMGET,&y);
  8274.     debug(F101,"ttgmdm ioctl","",x);
  8275.     if (x < 0) {
  8276.     debug(F101,"ttgmdm errno","",errno);
  8277.     return(-1);
  8278.     } else debug(F101,"ttgmdm bits","",y);
  8279.  
  8280.     z = 0;                /* Initialize return value. */
  8281. #ifdef TIOCM_CTS
  8282.     /* Clear To Send */
  8283.     if (y & TIOCM_CTS) z |= BM_CTS;
  8284. #endif
  8285. #ifdef TIOCM_DSR
  8286.     /* Data Set Ready */
  8287.     if (y & TIOCM_DSR) z |= BM_DSR;
  8288. #endif
  8289. #ifdef TIOCM_CAR
  8290.     /* Carrier */
  8291.     if (y & TIOCM_CAR) z |= BM_DCD;
  8292. #endif
  8293. #ifdef TIOCM_RNG
  8294.     /* Ring Indicate */
  8295.     if (y & TIOCM_RNG) z |= BM_RNG;
  8296. #endif
  8297. #ifdef TIOCM_DTR
  8298.     /* Data Terminal Ready */
  8299.     if (y & TIOCM_DTR) z |= BM_DTR;
  8300. #endif
  8301. #ifdef TIOCM_RTS
  8302.     /* Request To Send */
  8303.     if (y & TIOCM_RTS) z |= BM_RTS;
  8304. #endif
  8305.     return(z);
  8306.  
  8307. #else /* !K_MDMCTL catch-All */
  8308.  
  8309.     if (netconn)            /* Network connection */
  8310.       return(-2);            /* No modem signals */
  8311.  
  8312.     return(-3);                /* Sorry, I don't know how... */
  8313.  
  8314. #endif /* K_MDMCTL */
  8315. #endif /* HPUX */
  8316. #endif /* QNX */
  8317. }
  8318.  
  8319. /*  P S U S P E N D  --  Put this process in the background.  */
  8320.  
  8321. /*
  8322.   Call with flag nonzero if suspending is allowed, zero if not allowed.
  8323.   Returns 0 on apparent success, -1 on failure (flag was zero, or
  8324.   kill() returned an error code.
  8325. */
  8326. int
  8327. psuspend(flag) int flag; {
  8328.  
  8329. #ifdef RTU
  8330.     extern int rtu_bug;
  8331. #endif /* RTU */
  8332.  
  8333.     if (flag == 0) return(-1);
  8334.  
  8335. #ifdef NOJC
  8336.     return(-1);
  8337. #else
  8338. #ifdef SIGTSTP
  8339. /*
  8340.   The big question here is whether job control is *really* supported.
  8341.   There's no way Kermit can know for sure.  The fact that SIGTSTP is
  8342.   defined does not guarantee the Unix kernel supports it, and the fact
  8343.   that the Unix kernel supports it doesn't guarantee that the user's
  8344.   shell (or other process that invoked Kermit) supports it.
  8345. */
  8346. #ifdef RTU
  8347.     rtu_bug = 1;
  8348. #endif /* RTU */
  8349.     if (kill(0,SIGSTOP) < 0
  8350. #ifdef MIPS
  8351. /* Let's try this for MIPS too. */
  8352.     && kill(getpid(),SIGSTOP) < 0
  8353. #endif /* MIPS */
  8354.     ) {                /* If job control, suspend the job */
  8355.     perror("suspend");
  8356.     debug(F101,"psuspend error","",errno);
  8357.     return(-1);
  8358.     }
  8359.     debug(F100,"psuspend ok","",0);
  8360.     return(0);
  8361. #else
  8362.     return(-1);
  8363. #endif /* SIGTSTP */
  8364. #endif /* NOJC */
  8365. }
  8366.  
  8367. /*
  8368.   setuid package, by Kristoffer Eriksson, with contributions from Dean
  8369.   Long and fdc.
  8370. */
  8371.  
  8372. /* The following is for SCO when CK_ANSILIBS is defined... */
  8373. #ifdef M_UNIX
  8374. #ifdef CK_ANSILIBS
  8375. #ifndef NOGETID_PROTOS
  8376. #define NOGETID_PROTOS
  8377. #endif /* NOGETID_PROTOS */
  8378. #endif /* CK_ANSILIBS */
  8379. #endif /* M_UNIX */
  8380.  
  8381. #ifndef _POSIX_SOURCE
  8382. #ifndef SUNOS4
  8383. #ifndef NEXT
  8384. #ifndef PS2AIX10
  8385. #ifndef sequent
  8386. #ifndef NOGETID_PROTOS
  8387. extern UID_T getuid(), geteuid(), getreuid();
  8388. extern GID_T getgid(), getegid(), getregid();
  8389. #endif /* NOGETID_PROTOS */
  8390. #endif /* sequent */
  8391. #endif /* PS2AIX10 */
  8392. #endif /* NEXT */
  8393. #endif /* SUNOS4 */
  8394. #endif /* _POSIX_SOURCE */
  8395.  
  8396. /*
  8397. Subject: Set-user-id
  8398. To: fdc@watsun.cc.columbia.edu (Frank da Cruz)
  8399. Date: Sat, 21 Apr 90 4:48:25 MES
  8400. From: Kristoffer Eriksson <ske@pkmab.se>
  8401.  
  8402. This is a set of functions to be used in programs that may be run set-user-id
  8403. and/or set-group-id. They handle both the case where the program is not run
  8404. with such privileges (nothing special happens then), and the case where one
  8405. or both of these set-id modes are used.  The program is made to run with the
  8406. user's real user and group ids most of the time, except for when more
  8407. privileges are needed.  Don't set-user-id to "root".
  8408.  
  8409. This works on System V and POSIX.  In BSD, it depends on the
  8410. "saved-set-user-id" feature.
  8411. */
  8412.  
  8413. #define UID_ROOT 0            /* Root user and group ids */
  8414. #define GID_ROOT 0
  8415.  
  8416. /*
  8417.   The following code defines the symbol SETEUID for UNIX systems based
  8418.   on BSD4.4 (either -Encumbered or -Lite).  This program will then use
  8419.   seteuid() and setegid() instead of setuid() and setgid(), which still
  8420.   don't allow arbitrary switching.  It also avoids setreuid() and
  8421.   setregid(), which are included in BSD4.4 for compatibility only, are
  8422.   insecure, and print warnings to stderr under at least one system (NetBSD
  8423.   1.0).  Note that POSIX systems should still use setuid() and setgid();
  8424.   the seteuid() and setegid() functions are BSD4.4 extensions to the
  8425.   POSIX model.  Mike Long <mike.long@analog.com>, 8/94.
  8426. */
  8427. #ifdef BSD44
  8428. #define SETEUID
  8429. #endif /* BSD44 */
  8430.  
  8431. /*
  8432.   The following construction automatically defines the symbol SETREUID for
  8433.   UNIX versions based on Berkeley Unix 4.2 and 4.3.  If this symbol is 
  8434.   defined, then this program will use getreuid() and getregid() calls in
  8435.   preference to getuid() and getgid(), which in Berkeley-based Unixes do
  8436.   not allow arbitrary switching back and forth of real & effective uid.
  8437.   This construction also allows -DSETREUID to be put on the cc command line
  8438.   for any system that has and wants to use setre[ug]id().  It also prevents
  8439.   automatic definition of SETREUID if -DNOSETREU is included on the cc 
  8440.   command line (or otherwise defined).
  8441. */
  8442. #ifdef FT18                /* None of this for Fortune. */
  8443. #define NOSETREU
  8444. #endif /* FT18 */
  8445.  
  8446. #ifdef ANYBSD
  8447. #ifndef BSD29
  8448. #ifndef BSD41
  8449. #ifndef SETREUID
  8450. #ifndef NOSETREU
  8451. #ifndef SETEUID
  8452. #define SETREUID
  8453. #endif /* SETEUID */
  8454. #endif /* NOSETREU */                   
  8455. #endif /* SETREUID */
  8456. #endif /* !BSD41 */
  8457. #endif /* !BSD29 */
  8458. #endif /* ANYBSD */
  8459.  
  8460. /* Variables for user and group IDs. */
  8461.  
  8462. static UID_T realuid = (UID_T) -1, privuid = (UID_T) -1;
  8463. static GID_T realgid = (GID_T) -1, privgid = (GID_T) -1;
  8464.  
  8465.  
  8466. /* P R I V _ I N I  --  Initialize privileges package  */
  8467.  
  8468. /* Called as early as possible in a set-uid or set-gid program to store the
  8469.  * set-to uid and/or gid and step down to the users real uid and gid. The
  8470.  * stored id's can be temporarily restored (allowed in System V) during
  8471.  * operations that require the privilege.  Most of the time, the program
  8472.  * should execute in unpriviliged state, to not impose any security threat.
  8473.  *
  8474.  * Note: Don't forget that access() always uses the real id:s to determine
  8475.  * file access, even with privileges restored.
  8476.  *
  8477.  * Returns an error mask, with error values or:ed together:
  8478.  *   1 if setuid() fails,
  8479.  *   2 if setgid() fails, and
  8480.  *   4 if the program is set-user-id to "root", which can't be handled.
  8481.  *
  8482.  * Only the return value 0 indicates real success. In case of failure,
  8483.  * those privileges that could be reduced have been, at least, but the
  8484.  * program should be aborted none-the-less.
  8485.  *
  8486.  * Also note that these functions do not expect the uid or gid to change
  8487.  * without their knowing. It may work if it is only done temporarily, but
  8488.  * you're on your own.
  8489.  */
  8490. int
  8491. priv_ini() {
  8492.     int err = 0;
  8493.  
  8494.     /* Save real ID:s. */
  8495.     realuid = getuid();
  8496.     realgid = getgid();
  8497.  
  8498.     /* Save current effective ID:s, those set to at program exec. */
  8499.     privuid = geteuid();
  8500.     privgid = getegid();
  8501.  
  8502.     /* If running set-uid, go down to real uid, otherwise remember that
  8503.      * no privileged uid is available.
  8504.      *
  8505.      * Exceptions:
  8506.      *
  8507.      * 1) If the real uid is already "root" and the set-uid uid (the
  8508.      * initial effective uid) is not "root", then we would have trouble
  8509.      * if we went "down" to "root" here, and then temporarily back to the
  8510.      * set-uid uid (not "root") and then again tried to become "root". I
  8511.      * think the "saved set-uid" is lost when changing uid from effective
  8512.      * uid "root", which changes all uid, not only the effective uid. But
  8513.      * in this situation, we can simply go to "root" and stay there all
  8514.      * the time. That should give sufficient privilege (understatement!),
  8515.      * and give the right uids for subprocesses.
  8516.      *
  8517.      * 2) If the set-uid (the initial effective uid) is "root", and we
  8518.      * change uid to the real uid, we can't change it back to "root" when
  8519.      * we need the privilege, for the same reason as in 1). Thus, we can't
  8520.      * handle programs that are set-user-id to "root" at all. The program
  8521.      * should be stopped.  Use some other uid.  "root" is probably too
  8522.      * privileged for such things, anyway. (The uid is reverted to the
  8523.      * real uid until termination.)
  8524.      *
  8525.      * These two exceptions have the effect that the "root" uid will never
  8526.      * be one of the two uids that are being switched between, which also
  8527.      * means we don't have to check for such cases in the switching
  8528.      * functions.
  8529.      *
  8530.      * Note that exception 1) is handled by these routines (by constantly
  8531.      * running with uid "root", while exception 2) is a serious error, and
  8532.      * is not provided for at all in the switching functions.
  8533.      */
  8534.     if (realuid == privuid)
  8535.     privuid = (UID_T) -1;        /* Not running set-user-id. */
  8536.  
  8537.     /* If running set-gid, go down to real gid, otherwise remember that
  8538.      * no privileged gid is available.
  8539.      *
  8540.      * There are no exception like there is for the user id, since there
  8541.      * is no group id that is privileged in the manner of uid "root".
  8542.      * There could be equivalent problems for group changing if the
  8543.      * program sometimes ran with uid "root" and sometimes not, but
  8544.      * that is already avoided as explained above.
  8545.      *
  8546.      * Thus we can expect always to be able to switch to the "saved set-
  8547.      * gid" when we want, and back to the real gid again. You may also
  8548.      * draw the conclusion that set-gid provides for fewer hassles than
  8549.      * set-uid.
  8550.      */
  8551.  
  8552.     if (realgid == privgid)        /* If not running set-user-id, */
  8553.       privgid = (GID_T) -1;        /*  remember it this way. */
  8554.  
  8555.     err = priv_off();            /* Turn off setuid privilege. */
  8556.  
  8557.     if (privuid == UID_ROOT)        /* If setuid to root, */
  8558.       err |= 4;                /* return this error. */
  8559.  
  8560.     if (realuid == UID_ROOT)        /* If real id is root, */
  8561.       privuid = (UID_T) -1;        /* stay root at all times. */
  8562.  
  8563.     return(err);
  8564. }
  8565.  
  8566.  
  8567. /* Macros for hiding the differences in UID/GID setting between various Unix
  8568.  * systems. These macros should always be called with both the privileged ID
  8569.  * and the non-privileged ID. The one in the second argument, will become the
  8570.  * effective ID. The one in the first argument will be retained for later
  8571.  * retrieval.
  8572.  */
  8573. #ifdef SETREUID
  8574. #ifdef SAVEDUID
  8575. /* On BSD systems with the saved-UID feature, we just juggle the effective
  8576.  * UID back and forth, and leave the real UID at its true value.  The kernel
  8577.  * allows switching to both the current real UID, the effective UID, and the
  8578.  * UID which the program is set-UID to.  The saved set-UID always holds the
  8579.  * privileged UID for us, and the real UID will always be the non-privileged,
  8580.  * and we can freely choose one of them for the effective UID at any time.
  8581.  */
  8582. #define switchuid(hidden,active) setreuid( (UID_T) -1, active)
  8583. #define switchgid(hidden,active) setregid( (GID_T) -1, active)
  8584.  
  8585. #else   /* SETREUID,!SAVEDUID */
  8586.  
  8587. /* On systems with setreXid() but without the saved-UID feature, notably
  8588.  * BSD 4.2, we swap the real and effective UIDs each time.  It's
  8589.  * the effective UID that we are interested in, but we have to retain the
  8590.  * unused UID somewhere to enable us to restore it later, and we do this
  8591.  * in the real UID.  The kernel only allows switching to either the current 
  8592.  * real or the effective UID, unless you're "root".
  8593.  */
  8594. #define switchuid(hidden,active)    setreuid(hidden,active)
  8595. #define switchgid(hidden,active)    setregid(hidden,active)
  8596. #endif
  8597.  
  8598. #else /* !SETREUID, !SAVEDUID */
  8599.  
  8600. #ifdef SETEUID
  8601. /*
  8602.   BSD 4.4 works similarly to System V and POSIX (see below), but uses
  8603.   seteXid() instead of setXid() to change effective IDs.  In addition, the
  8604.   seteXid() functions work the same for "root" as for other users.
  8605. */
  8606. #define switchuid(hidden,active)    seteuid(active)
  8607. #define switchgid(hidden,active)    setegid(active)
  8608.  
  8609. #else /* !SETEUID */
  8610.  
  8611. /* On System V and POSIX, the only thing we can change is the effective UID
  8612.  * (unless the current effective UID is "root", but initsuid() avoids that for
  8613.  * us).  The kernel allows switching to the current real UID or to the saved
  8614.  * set-UID.  These are always set to the non-privileged UID and the privileged
  8615.  * UID, respectively, and we only change the effective UID.  This breaks if
  8616.  * the current effective UID is "root", though, because for "root" setuid/gid
  8617.  * becomes more powerful, which is why initsuid() treats "root" specially.
  8618.  * Note: That special treatment maybe could be ignored for BSD?  Note: For
  8619.  * systems that don't fit any of these four cases, we simply can't support
  8620.  * set-UID.
  8621.  */
  8622. #define switchuid(hidden,active)    setuid(active)
  8623. #define switchgid(hidden,active)    setgid(active)
  8624.  
  8625. #endif /* SETEUID */
  8626. #endif /* SETREUID */
  8627.   
  8628.  
  8629. /* P R I V _ O N  --  Turn on the setuid and/or setgid */
  8630.  
  8631. /* Go to the privileged uid (gid) that the program is set-user-id
  8632.  * (set-group-id) to, unless the program is running unprivileged.
  8633.  * If setuid() fails, return value will be 1. If getuid() fails it
  8634.  * will be 2.  Return immediately after first failure, and the function
  8635.  * tries to restore any partial work done.  Returns 0 on success.
  8636.  * Group id is changed first, since it is less serious than user id.
  8637.  */
  8638. int
  8639. priv_on() {
  8640.     if (privgid != (GID_T) -1)
  8641.       if (switchgid(realgid,privgid))
  8642.         return(2);
  8643.  
  8644.     if (privuid != (UID_T) -1)
  8645.       if (switchuid(realuid,privuid)) {
  8646.       if (privgid != (GID_T) -1)
  8647.         switchgid(privgid,realgid);
  8648.       return(1);
  8649.       }
  8650.     return(0);
  8651. }
  8652.  
  8653. /* P R I V _ O F F  --  Turn on the real uid and gid */
  8654.  
  8655. /* Return to the unprivileged uid (gid) after an temporary visit to
  8656.  * privileged status, unless the program is running without set-user-id
  8657.  * (set-group-id). Returns 1 for failure in setuid() and 2 for failure
  8658.  * in setgid() or:ed together. The functions tries to return both uid
  8659.  * and gid to unprivileged state, regardless of errors. Returns 0 on
  8660.  * success.
  8661.  */
  8662. int
  8663. priv_off() {
  8664.     int err = 0;
  8665.  
  8666.     if (privuid != (UID_T) -1)
  8667.        if (switchuid(privuid,realuid))
  8668.       err |= 1;
  8669.  
  8670.     if (privgid != (GID_T) -1)
  8671.        if (switchgid(privgid,realgid))
  8672.     err |= 2;
  8673.  
  8674.     return(err);
  8675. }
  8676.  
  8677. /* Turn off privilege permanently.  No going back.  This is necessary before
  8678.  * a fork() on BSD43 machines that don't save the setUID or setGID, because
  8679.  * we swap the real and effective ids, and we don't want to let the forked
  8680.  * process swap them again and get the privilege back. It will work on other
  8681.  * machines too, such that you can rely on its effect always being the same,
  8682.  * for instance, even when you're in priv_on() state when this is called.
  8683.  * (Well, that part about "permanent" is on System V only true if you follow
  8684.  * this with a call to exec(), but that's what we want it for anyway.)
  8685.  * Added by Dean Long -- dlong@midgard.ucsc.edu
  8686.  */
  8687. int
  8688. priv_can() {
  8689.  
  8690. #ifdef SETREUID
  8691.     int err = 0;
  8692.     if (privuid != (UID_T) -1)
  8693.        if (setreuid(realuid,realuid))
  8694.       err |= 1;
  8695.  
  8696.     if (privgid != (GID_T) -1)
  8697.         if (setregid(realgid,realgid))
  8698.        err |= 2;
  8699.  
  8700.     return(err);
  8701.  
  8702. #else
  8703. #ifdef SETEUID
  8704.     int err = 0;
  8705.     if (privuid != (UID_T) -1)
  8706.     if (setuid(realuid)) {
  8707.         debug(F101,"setuid failed","",errno);
  8708.         err |= 1;
  8709.         debug(F101,"ruid","",getuid());
  8710.         debug(F101,"euid","",geteuid());
  8711.     }
  8712.     debug(F101,"setuid","",realuid);
  8713.     if (privgid != (GID_T) -1)
  8714.         if (setgid(realgid)) {
  8715.         debug(F101,"setgid failed","",errno);
  8716.         err |= 2;
  8717.         debug(F101,"rgid","",getgid());
  8718.         debug(F101,"egid","",getegid());
  8719.     }
  8720.     debug(F101,"setgid","",realgid);
  8721.     return(err);
  8722. #else
  8723.     /* Easy way of using setuid()/setgid() instead of setreuid()/setregid().*/
  8724.     return(priv_off());
  8725. #endif /* SETEUID */
  8726. #endif /* SETREUID */
  8727. }
  8728.  
  8729. /* P R I V _ O P N  --  For opening protected files or devices. */
  8730.  
  8731. int
  8732. priv_opn(name, modes) char *name; int modes; {
  8733.     int x;
  8734.     priv_on();                /* Turn privileges on */
  8735.     x = open(name, modes);        /* Try to open the device */
  8736.     priv_off();                /* Turn privileges off */
  8737.     return(x);                /* Return open's return code */
  8738. }
  8739.  
  8740. /*  P R I V _ C H K  --  Check privileges.  */
  8741.  
  8742. /*  Try to turn them off.  If turning them off did not succeed, cancel them */
  8743.  
  8744. int
  8745. priv_chk() {
  8746.     int x, y = 0;
  8747.     x = priv_off();            /* Turn off privs. */
  8748.     if (x != 0 || getuid() == privuid || geteuid() == privuid)
  8749.       y = priv_can();
  8750.     if (x != 0 || getgid() == privgid || getegid() == privgid)
  8751.       y = y | priv_can();
  8752.     return(y);
  8753. }
  8754.  
  8755. UID_T
  8756. real_uid() {
  8757.     return(realuid);
  8758. }
  8759.  
  8760. VOID
  8761. ttimoff() {                /* Turn off any timer interrupts */
  8762.     /* int xx; */
  8763. /*
  8764.   As of 5A(183), we set SIGALRM to SIG_IGN (to ignore alarms) rather than to
  8765.   SIG_DFL (to catch alarms, or if there is no handler, to exit).  This is to
  8766.   cure (mask, really) a deeper problem with stray alarms that occurs on some
  8767.   systems, possibly having to do with sleep(), that caused core dumps.  It
  8768.   should be OK to do this, because no code in this module uses nested alarms.
  8769.   (But we still have to watch out for SCRIPT and DIAL...)
  8770. */
  8771.     /* xx = */ alarm(0);
  8772.     /* debug(F101,"ttimoff alarm","",xx); */
  8773.     if (saval) {            /* Restore any previous */
  8774.     signal(SIGALRM,saval);        /* alarm handler. */
  8775.     /* debug(F101,"ttimoff alarm restoring saval","",saval); */
  8776.     saval = NULL;
  8777.     } else {
  8778.     signal(SIGALRM,SIG_IGN);    /* Used to be SIG_DFL */
  8779.     /* debug(F100,"ttimoff alarm SIG_IGN","",0); */
  8780.     }
  8781. }
  8782.  
  8783. #ifdef CK_REDIR
  8784. int
  8785. ttruncmd(s) char *s; {
  8786.     int r = 0;                /* Return code */
  8787.                     /* 0 = failure, 1 = success */
  8788. #ifdef WIFEXITED
  8789. #ifndef WEXITSTATUS
  8790. #ifdef w_retcode
  8791. #define WEXITSTATUS(x) ((x).w_retcode)
  8792. #endif /* w_retcode */
  8793. #endif /* WEXITSTATUS */
  8794. #ifdef WEXITSTATUS
  8795. #define CK_FUN_OK
  8796. #endif /* WEXITSTATUS */
  8797. #endif /* WIFEXITED */
  8798. #ifdef NEXT
  8799. #define waitpid(pid,status,option) wait4((pid),(status),(option),NULL)
  8800. #else
  8801. #ifdef sony_news
  8802. #define waitpid(pid,status,option) wait4((pid),(status),(option),NULL)
  8803. #endif /* sony_news */
  8804. #endif /* NEXT */
  8805.  
  8806. #ifdef CK_FUN_OK
  8807.     PID_T pid;
  8808.  
  8809.     if (ttyfd == -1) {
  8810.     printf("?Sorry, device is not open\n");
  8811.     return(0);
  8812.     }
  8813.     conres();                /* Make console normal  */
  8814.     if ((pid = fork()) == 0) {        /* Make a child fork */
  8815.     /* give it stdin,out to the line */
  8816.     if (priv_can())            /* Turn off privs. */
  8817.       exit(1);
  8818.     dup2(ttyfd, 0);
  8819.     dup2(ttyfd, 1);
  8820.     _exit(system(s) ? BAD_EXIT : 0);
  8821.     } else {
  8822.     WAIT_T status;            /* This is int for all but NeXT */
  8823.     SIGTYP (*istat)(), (*qstat)();
  8824.  
  8825.     if (pid == (PID_T) -1)        /* fork() failed? */
  8826.       return(0);
  8827.     istat = signal(SIGINT,SIG_IGN); /* Let the fork handle keyboard */
  8828.     qstat = signal(SIGQUIT,SIG_IGN); /* interrupts itself... */
  8829.  
  8830.     if (waitpid(pid, &status, 0) != pid) {
  8831.         printf("?Can't wait for child process?\r\n");
  8832.     } else {
  8833.         if (WIFEXITED(status)) {
  8834.         if (WEXITSTATUS(status)) {
  8835.             printf("?Command exit status: %d\r\n",
  8836.                WEXITSTATUS(status));
  8837.         } else r = 1;
  8838.         } else {
  8839.         printf("?Command did not exit - cancelling it now.\r\n");
  8840.         kill(pid, SIGKILL);
  8841.         }
  8842.     }
  8843.     signal(SIGINT,istat);        /* Restore interrupts */
  8844.     signal(SIGQUIT,qstat);
  8845.     }
  8846.     concb((char)escchr);        /* Restore console to CBREAK mode */
  8847. #else
  8848.     printf("?Sorry, can't execute this command - pieces missing.\n");
  8849. #endif /* CK_FUN_OK */
  8850.     return(r);
  8851. }
  8852. #endif /* CK_REDIR */
  8853.  
  8854. #ifdef OXOS
  8855. #undef kill
  8856. #endif /* OXOS */
  8857.  
  8858. #ifdef OXOS
  8859. int
  8860. priv_kill(pid, sig) int pid, sig; {
  8861.     int    i;
  8862.  
  8863.     if (priv_on())
  8864.     debug(F100,"priv_kill priv_on failed","",0);
  8865.     i = kill(pid, sig);
  8866.     if (priv_off())
  8867.     debug(F100,"priv_kill priv_off failed","",0);
  8868.     return(i);
  8869. }
  8870. #endif /* OXOS */
  8871.  
  8872. #ifdef BEBOX
  8873. #ifdef BE_DR_7
  8874. /*
  8875.   alarm() function not supplied with Be OS DR7 - this one contributed by
  8876.   Neal P. Murphy.
  8877. */
  8878.  
  8879. /*
  8880.   This should mimic the UNIX/POSIX alarm() function well enough, with the
  8881.   caveat that one's SIGALRM handler must call alarm_expired() to clean up vars
  8882.   and wait for the alarm thread to finish.
  8883. */
  8884. unsigned int
  8885. alarm(unsigned int seconds) {
  8886.     long time_left = 0;
  8887.  
  8888. /* If an alarm is active, turn it off, saving the unused time */
  8889.     if (alarm_thread != -1) {
  8890.         /* We'll be generous and count partial seconds as whole seconds. */
  8891.         time_left = alarm_struct.time -
  8892.       ((system_time() - time_started) / 1000000.0);
  8893.  
  8894.         /* Kill the alarm thread */
  8895.         kill_thread (alarm_thread);
  8896.  
  8897.         /* We need to clean up as though the alarm occured. */
  8898.         time_started = 0;
  8899.         alarm_struct.thread = -1;
  8900.         alarm_struct.time = 0;
  8901.         alarm_expired();
  8902.     }
  8903.  
  8904. /* Set a new alarm clock, if requested. */
  8905.     if (seconds > 0) {
  8906.         alarm_struct.thread = find_thread(NULL);
  8907.         alarm_struct.time = seconds;
  8908.         time_started = system_time();
  8909.         alarm_thread = spawn_thread (do_alarm,
  8910.                                      "alarm_thread",
  8911.                                      B_NORMAL_PRIORITY,
  8912.                                      (void *) &alarm_struct
  8913.                      );
  8914.         resume_thread (alarm_thread);
  8915.     }
  8916.  
  8917. /* Now return [unused time | 0] */
  8918.     return ((unsigned int) time_left);
  8919. }
  8920.  
  8921. /*
  8922.   This function is the departure from UNIX/POSIX alarm handling. In the case
  8923.   of Be's missing alarm() function, this stuff needs to be done in the SIGALRM
  8924.   handler. When Be implements alarm(), this function call can be eliminated
  8925.   from user's SIGALRM signal handlers.
  8926. */
  8927.  
  8928. void
  8929. alarm_expired(void) {
  8930.     long ret_val;
  8931.  
  8932.     if (alarm_thread != -1) {
  8933.         wait_for_thread (alarm_thread, &ret_val);
  8934.         alarm_thread = -1;
  8935.     }
  8936. }
  8937.  
  8938. /*
  8939.   This is the function that snoozes the requisite number of seconds and then
  8940.   SIGALRMs the calling thread. Note that kill() wants a pid_t arg, whilst Be
  8941.   uses thread_id; currently they are both typdef'ed as long, but I'll do the
  8942.   cast anyway. This function is run in a separate thread.
  8943. */
  8944.  
  8945. long
  8946. do_alarm (void *alarm_struct) {
  8947.     snooze ((double) ((struct ALARM_STRUCT *) alarm_struct)->time * 1000000.0);
  8948.     kill ((pid_t)((struct ALARM_STRUCT *) alarm_struct)->thread, SIGALRM);
  8949.     time_started = 0;
  8950.     ((struct ALARM_STRUCT *) alarm_struct)->thread = -1;
  8951.     ((struct ALARM_STRUCT *) alarm_struct)->time = 0;
  8952. }
  8953. #endif /* BE_DR_7 */
  8954. #endif /* BEBOX */
  8955.  
  8956. #ifdef Plan9
  8957.  
  8958. int
  8959. p9ttyctl(char letter, int num, int param) {
  8960.     char cmd[20];
  8961.     int len;
  8962.  
  8963.     if (ttyctlfd < 0)
  8964.       return -1;
  8965.  
  8966.     cmd[0] = letter;
  8967.     if (num)
  8968.       len = sprintf(cmd + 1, "%d", param) + 1;
  8969.     else {
  8970.     cmd[1] = param;
  8971.     len = 2;
  8972.     }
  8973.     if (write(ttyctlfd, cmd, len) == len) {
  8974.     cmd[len] = 0;
  8975.     /* fprintf(stdout, "wrote '%s'\n", cmd); */
  8976.     return 0;
  8977.     }
  8978.     return -1;
  8979. }
  8980.  
  8981. int
  8982. p9ttyparity(char l) {
  8983.     return p9ttyctl('p', 0, l);
  8984. }
  8985.  
  8986. int
  8987. p9tthflow(int flow, int status) {
  8988.     return p9ttyctl('m', 1, status);
  8989. }
  8990.  
  8991. int
  8992. p9ttsspd(int cps) {
  8993.     if (p9ttyctl('b', 1, cps * 10) < 0)
  8994.       return -1;
  8995.     ttylastspeed = cps * 10;
  8996.     return 0;
  8997. }
  8998.  
  8999. int
  9000. p9openttyctl(char *ttname) {
  9001.     char name[100];
  9002.  
  9003.     if (ttyctlfd >= 0) {
  9004.     close(ttyctlfd);
  9005.     ttyctlfd = -1;
  9006.     ttylastspeed = -1;
  9007.     }
  9008.     sprintf(name, "%sctl", ttname);
  9009.     ttyctlfd = open(name, 1);
  9010.     return ttyctlfd;
  9011. }
  9012.  
  9013. int
  9014. p9concb() {
  9015.     if (consctlfd >= 0) {
  9016.     if (write(consctlfd, "rawon", 5) == 5)
  9017.       return 0;
  9018.     }
  9019.     return -1;
  9020. }
  9021.  
  9022. int
  9023. p9conbin() {
  9024.     return p9concb();
  9025. }
  9026.  
  9027. int
  9028. p9conres() {
  9029.     if (consctlfd >= 0) {
  9030.     if (write(consctlfd, "rawoff", 6) == 6)
  9031.       return 0;
  9032.     }
  9033.     return -1;
  9034. }
  9035.  
  9036. int
  9037. p9sndbrk(int msec) {
  9038.     if (ttyctlfd >= 0) {
  9039.     char cmd[20];
  9040.     int i = sprintf(cmd, "k%d", msec);
  9041.     if (write(ttyctlfd, cmd, i) == i)
  9042.       return 0;
  9043.     }
  9044.     return -1;
  9045. }
  9046.  
  9047. int
  9048. conwrite(char *buf, int n) {
  9049.     int x;
  9050.     static int length = 0;
  9051.     static int holdingcr = 0;
  9052.     int normal = 0;
  9053.     for (x = 0; x < n; x++) {
  9054.     char c = buf[x];
  9055.     if (c == 007) {
  9056.         if (normal) {
  9057.         write(1, buf + (x - normal), normal);
  9058.         length += normal;
  9059.         normal = 0;
  9060.         }
  9061.         /* write(noisefd, "1000 300", 8); */
  9062.         holdingcr = 0;
  9063.     } else if (c == '\r') {
  9064.         if (normal) {
  9065.         write(1, buf + (x - normal), normal);
  9066.         length += normal;
  9067.         normal = 0;
  9068.         }
  9069.         holdingcr = 1;
  9070.     } else if (c == '\n') {
  9071.         write(1, buf + (x - normal), normal + 1);
  9072.         normal = 0;
  9073.         length = 0;
  9074.         holdingcr = 0;
  9075.     } else if (c == '\b') {
  9076.         if (normal) {
  9077.         write(1, buf + (x - normal), normal);
  9078.         length += normal;
  9079.         normal = 0;
  9080.         }
  9081.         if (length) {
  9082.         write(1, &c, 1);
  9083.         length--;
  9084.         }
  9085.         holdingcr = 0;
  9086.     } else {
  9087.         if (holdingcr) {
  9088.         char b = '\b';
  9089.         while (length-- > 0)
  9090.           write(1, &b, 1);
  9091.         length = 0;    /* compiler bug */
  9092.         }
  9093.         holdingcr = 0;
  9094.         normal++;
  9095.     }
  9096.     }
  9097.     if (normal) {
  9098.     write(1, buf + (x - normal), normal);
  9099.     length += normal;
  9100.     }
  9101.     return n;
  9102. }
  9103.  
  9104. void
  9105. conprint(char *fmt, ...) {
  9106.     char buf[1000];
  9107.  
  9108.     va_list ap;
  9109.     int i;
  9110.  
  9111.     va_start(ap, fmt);
  9112.     i = vsprintf(buf, fmt, ap);
  9113.     conwrite(buf, i);
  9114. }
  9115. #endif /* Plan9 */
  9116.