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

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