home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / ck9197.zip / ckutio.c < prev    next >
C/C++ Source or Header  |  2000-02-21  |  382KB  |  13,130 lines

  1. #ifdef aegis
  2. char *ckxv = "Aegis Communications support, 7.0.231, 31 Dec 1999";
  3. #else
  4. #ifdef Plan9
  5. char *ckxv = "Plan 9 Communications support, 7.0.231, 31 Dec 1999";
  6. #else
  7. char *ckxv = "UNIX Communications support, 7.0.231, 31 Dec 1999";
  8. #endif /* Plan9 */
  9. #endif /* aegis */
  10.  
  11. /*  C K U T I O  */
  12.  
  13. /* C-Kermit interrupt, communications control and I/O functions for UNIX */
  14.  
  15. /*
  16.   Author: Frank da Cruz (fdc@columbia.edu),
  17.   Columbia University Academic Information Systems, New York City.
  18.  
  19.   Copyright (C) 1985, 2000,
  20.     Trustees of Columbia University in the City of New York.
  21.     All rights reserved.  See the C-Kermit COPYING.TXT file or the
  22.     copyright text in the ckcmai.c module for disclaimer and permissions.
  23. */
  24.  
  25. /*
  26.   NOTE TO CONTRIBUTORS: This file, and all the other C-Kermit files, must be
  27.   compatible with C preprocessors that support only #ifdef, #else, #endif,
  28.   #define, and #undef.  Please do not use #if, logical operators, or other
  29.   preprocessor features in any of the portable C-Kermit modules.  You can,
  30.   of course, use these constructions in platform-specific modules when they
  31.   are supported by all compilers/preprocessors that could be used on that
  32.   platform.
  33. */
  34.  
  35. extern int nettype;            /* Defined in ckcmai.c */
  36.  
  37. /* Includes */
  38.  
  39. #include "ckcsym.h"            /* This must go first   */
  40. #include "ckcdeb.h"            /* This must go second  */
  41.  
  42. #ifdef OSF13
  43. #ifdef CK_ANSIC
  44. #ifdef _NO_PROTO
  45. #undef _NO_PROTO
  46. #endif /* _NO_PROTO */
  47. #endif /* CK_ANSIC */
  48. #endif /* OSF13 */
  49.  
  50. #include <errno.h>            /* System error numbers */
  51.  
  52. #ifdef __386BSD__
  53. #define ENOTCONN 57
  54. #else
  55. #ifdef __bsdi__
  56. #define ENOTCONN 57
  57. #else
  58. #ifdef __FreeBSD__
  59. #define ENOTCONN 57
  60. #endif /* __FreeBSD__ */
  61. #endif /* __bsdi__ */
  62. #endif /* __386BSD__ */
  63.  
  64. #ifdef SCO_OSR504
  65. #define NBBY 8
  66. #endif /* SCO_OSR504 */
  67.  
  68. #ifdef Plan9
  69. #define SELECT
  70. #include <sys/time.h>
  71. #include <select.h>
  72. #define FD_SETSIZE (3 * sizeof(long) * 8)
  73. static struct timeval tv;
  74. #endif /* Plan9 */
  75.  
  76. #ifdef CLIX
  77. #include <sys/time.h>
  78. #endif /* CLIX */
  79.  
  80. #include "ckcnet.h"            /* Symbols for network types. */
  81. #ifdef CK_SSL
  82. #include "ck_ssl.h"
  83. #endif /* CK_SSL */
  84.  
  85. /*
  86.   The directory-related includes are here because we need to test some
  87.   file-system-related symbols to find out which system we're being compiled
  88.   under.  For example, MAXNAMLEN is defined in BSD4.2 but not 4.1.
  89. */
  90. #ifdef SDIRENT                /* Directory bits... */
  91. #define DIRENT
  92. #endif /* SDIRENT */
  93.  
  94. #ifdef XNDIR
  95. #include <sys/ndir.h>
  96. #else /* !XNDIR */
  97. #ifdef NDIR
  98. #include <ndir.h>
  99. #else /* !NDIR, !XNDIR */
  100. #ifdef RTU
  101. #include "/usr/lib/ndir.h"
  102. #else /* !RTU, !NDIR, !XNDIR */
  103. #ifdef DIRENT
  104. #ifdef SDIRENT
  105. #include <sys/dirent.h>
  106. #else
  107. #include <dirent.h>
  108. #endif /* SDIRENT */
  109. #else /* !RTU, !NDIR, !XNDIR, !DIRENT, i.e. all others */
  110. #include <sys/dir.h>
  111. #endif /* DIRENT */
  112. #endif /* RTU */
  113. #endif /* NDIR */
  114. #endif /* XNDIR */
  115.  
  116. #ifdef QNX
  117. #include <sys/dev.h>
  118. #endif /* QNX */
  119.  
  120. #ifdef HPUX5
  121. #ifndef TCPSOCKET
  122. /* I don't know why this is needed here since we never reference bzero(). */
  123. /* But without it C-Kermit won't link in an HP-UX 5.xx non-TCP build. */
  124. void
  125. bzero(s,n) char *s; int n; {
  126.     extern char * memset();
  127.     memset(s,0,n);
  128. }
  129. #endif /* TCPSOCKET */
  130. #endif /* HPUX5 */
  131.  
  132. /* Definition of HZ, used in msleep() */
  133.  
  134. #ifdef MIPS
  135. #define HZ ( 1000 / CLOCK_TICK )
  136. #else
  137. #ifdef ATTSV
  138. #ifndef NAP
  139. #ifndef TRS16
  140. #include <sys/param.h>
  141. #else
  142. #define HZ ( 1000 / CLOCK_TICK )
  143. #endif /* TRS16 */
  144. #ifdef NAPHACK
  145. #define nap(x) (void)syscall(3112, (x))
  146. #define NAP
  147. #endif /* NAPHACK */
  148. #endif /* NAP */
  149. #endif /* ATTSV */
  150. #endif /* MIPS */
  151.  
  152. #ifdef M_UNIX
  153. #undef NGROUPS_MAX        /* Prevent multiple definition warnings */
  154. #endif /* M_UNIX */
  155.  
  156. /*
  157.   NOTE: HP-UX 8.0 has a <sys/poll.h>, but there is no corresponding
  158.   library routine, so _poll comes up undefined at link time.
  159. */
  160. #ifdef CK_POLL
  161. #ifndef AIXRS            /* IBM AIX needs special handling */
  162. #include <poll.h>        /* "standard" (SVID) i/o multiplexing, etc */
  163. #else /* AIXRS */
  164. #ifdef SVR4            /* AIX 3.2 is like SVID... */
  165. #include <poll.h>
  166. #else                /* But AIX 3.1 is not ... */
  167. #include <sys/poll.h>        /* The include file is in include/sys */
  168. #define events reqevents    /* And it does not map IBM-specific member */
  169. #define revents rtnevents    /* names to the System V equivalents */
  170. #endif /* SVR4 */
  171. #endif /* AIXRS */
  172. #endif /* CK_POLL */
  173.  
  174. #include <signal.h>                     /* Signals */
  175.  
  176. /* For setjmp and longjmp */
  177.  
  178. #ifndef ZILOG
  179. #include <setjmp.h>
  180. #else
  181. #include <setret.h>
  182. #endif /* ZILOG */
  183.  
  184. /* Maximum length for the name of a tty device */
  185.  
  186. #ifndef DEVNAMLEN
  187. #define DEVNAMLEN 32
  188. #endif /* DEVNAMLEN */
  189.  
  190. #ifdef    NETCONN
  191. #undef DEVNAMLEN
  192. #define DEVNAMLEN 256            /* Longer field for host:service */
  193. #endif  /* NETCONN */
  194.  
  195. /*
  196.   The following test differentiates between 4.1 BSD and 4.2 & later.
  197.   If you have a 4.1BSD system with the DIRENT library, this test could
  198.   mistakenly diagnose 4.2BSD and then later enable the use of system calls
  199.   that aren't defined.  If indeed there are such systems, we can use some
  200.   other way of testing for 4.1BSD, or add yet another compile-time switch.
  201. */
  202. #ifdef BSD4
  203. #ifdef MAXNAMLEN
  204. #ifndef FT21                /* Except for Fortune. */
  205. #ifndef FT18
  206. #ifndef BELLV10                /* And Bell Labs Research UNIX V10 */
  207. #define BSD42
  208. #endif /* BELLV10 */
  209. #endif /* FT18 */
  210. #endif /* FT21 */
  211. #endif /* MAXNAMLEN */
  212. #endif /* BSD4 */
  213. /*
  214.   Minix 2.0 support added by Terry McConnell,
  215.   Syracuse University <tmc@barnyard.syr.edu>
  216.   No more sgtty interface, posix compliant.
  217. */
  218. #ifdef MINIX2
  219. #define _MINIX   /* Needed for some Minix header files */
  220. #undef MINIX     /* Old minix 1.0: used sgtty interface */
  221. #define BSD44ORPOSIX
  222. #define SVORPOSIX
  223. #define DCLTIMEVAL
  224. #define NOFILEH
  225. #include <sys/types.h>
  226. #include <sys/ioctl.h>
  227. #include <termios.h>
  228. #include <limits.h>
  229. #undef TIOCGETC    /* defined in sys/ioctl.h, but not really supported */
  230. #define TANDEM 0
  231. #endif /* MINIX2 */
  232.  
  233. /*
  234.  MINIX 1.0 support added by Charles Hedrick,
  235.  Rutgers University <hedrick@aramis.rutgers.edu>.
  236.  MINIX also has V7 enabled.
  237. */
  238. #ifdef MINIX
  239. #define TANDEM 0
  240. #define MYREAD
  241. #define NOSYSIOCTLH
  242. #include <limits.h>
  243. #endif /* MINIX */
  244.  
  245. #ifdef CK_REDIR        /* <sys/wait.h> needed only for REDIRECT command. */
  246. /*
  247.   If anybody can figure out how to make this work with NeXTSTEP, be
  248.   my guest!  (NeXTBlah/NeXTBlah/bsd/sys/wait.h does not define WEXITSTATUS)
  249. */
  250. #ifndef CK_WAIT_H            /* If wait.h not already included... */
  251. #include <sys/wait.h>            /* Include it */
  252. #endif /* CK_WAIT_H */
  253. #endif /* CK_REDIR */
  254.  
  255. #include "ckuver.h"            /* Version herald */
  256. char *ckxsys = HERALD;
  257.  
  258. #ifdef CK_UTSNAME
  259. #include <sys/utsname.h>
  260. #ifdef UW7
  261. #ifndef SYS_NMLN
  262. #define SYS_NMLN 257
  263. #endif /* NMLN */
  264. #endif /* UW7 */
  265. #ifdef HPUX9PLUS
  266. static int hpis800 = 0;
  267. #endif /* HPUX9PLUS */
  268. #ifdef SYS_NMLN
  269. #define CK_SYSNMLN SYS_NMLN
  270. #else
  271. #ifdef _SYS_NMLN
  272. #define CK_SYSNMLN _SYS_NMLN
  273. #else
  274. #ifdef UTSLEN
  275. #define CK_SYSNMLN UTSLEN
  276. #else
  277. #define CK_SYSNMLN 31
  278. #endif /* UTSLEN */
  279. #endif /* _SYS_NMLN */
  280. #endif /* SYS_NMLN */
  281. char unm_mch[CK_SYSNMLN+1] = { '\0', '\0' };
  282. char unm_mod[CK_SYSNMLN+1] = { '\0', '\0' };
  283. char unm_nam[CK_SYSNMLN+1] = { '\0', '\0' };
  284. char unm_rel[CK_SYSNMLN+1] = { '\0', '\0' };
  285. char unm_ver[CK_SYSNMLN+1] = { '\0', '\0' };
  286. #endif /* CK_UTSNAME */
  287.  
  288. #ifdef CIE
  289. #include <stat.h>            /* For chasing symlinks, etc. */
  290. #else
  291. #include <sys/stat.h>
  292. #endif /* CIE */
  293.  
  294. /* UUCP lockfile material... */
  295.  
  296. #ifndef NOUUCP
  297. #ifdef USETTYLOCK
  298. #ifdef USE_UU_LOCK
  299. #include <libutil.h>
  300. #endif /* USE_UU_LOCK */
  301. #else  /* USETTYLOCK */
  302.  
  303. /* Name of UUCP tty device lockfile */
  304.  
  305. #ifdef LINUXFSSTND
  306. #ifndef HDBUUCP
  307. #define HDBUUCP
  308. #endif /* HDBUUCP */
  309. #endif /* LINUXFSSTND */
  310.  
  311. #ifdef ACUCNTRL
  312. #define LCKDIR
  313. #endif /* ACUCNTRL */
  314.  
  315. /*
  316.   PIDSTRING means use ASCII string to represent pid in lockfile.
  317. */
  318. #ifndef PIDSTRING
  319. #ifdef HDBUUCP
  320. #define PIDSTRING
  321. #else
  322. #ifdef BSD44
  323. #define PIDSTRING
  324. #else
  325. #ifdef RTAIX
  326. #define PIDSTRING
  327. #else
  328. #ifdef AIXRS
  329. #define PIDSTRING
  330. #else
  331. #ifdef COHERENT
  332. #define PIDSTRING
  333. #endif /* COHERENT */
  334. #endif /* AIXRS */
  335. #endif /* RTAIX */
  336. #endif /* BSD44 */
  337. #endif /* HDBUUCP */
  338. #endif /* PIDSTRING */
  339.  
  340. /* Now the PIDSTRING exceptions... */
  341.  
  342. #ifdef PIDSTRING
  343. #ifdef HPUX
  344. #undef PIDSTRING
  345. #endif /* HPUX */
  346. #endif /* PIDSTRING */
  347.  
  348. #ifdef __bsdi__                /* BSDI (at least thru 1.1) */
  349. #ifdef PIDSTRING
  350. #undef PIDSTRING
  351. #endif /* PIDSTRING */
  352. #endif /* __bsdi__ */
  353.  
  354. #ifdef OSF32                /* Digital UNIX (OSF/1) 3.2 */
  355. #ifdef PIDSTRING
  356. #undef PIDSTRING
  357. #endif /* PIDSTRING */
  358. #endif /* OSF32 */
  359.  
  360. /*
  361.   LOCK_DIR is the name of the lockfile directory.
  362.   If LOCK_DIR is already defined (e.g. on command line), we don't change it.
  363. */
  364. #ifndef LOCK_DIR
  365. #ifdef BSD44
  366. #ifdef __386BSD__
  367. #define LOCK_DIR "/var/spool/lock"
  368. #else
  369. #ifdef __FreeBSD__
  370. #define LOCK_DIR "/var/spool/lock"
  371. #else
  372. #ifdef __NetBSD__
  373. #define LOCK_DIR "/var/spool/lock"
  374. #else
  375. #define LOCK_DIR "/var/spool/uucp"
  376. #endif /* __NetBSD__ */
  377. #endif /* __FreeBSD__ */
  378. #endif /* __386BSD__ */
  379. #else
  380. #ifdef DGUX430
  381. #define LOCK_DIR "/var/spool/locks"
  382. #else
  383. #ifdef HPUX10
  384. #define LOCK_DIR "/var/spool/locks"
  385. #else
  386. #ifdef RTAIX                /* IBM RT PC AIX 2.2.1 */
  387. #define LOCK_DIR "/etc/locks"
  388. #else
  389. #ifdef AIXRS
  390. #define LOCK_DIR "/etc/locks"
  391. #else
  392. #ifdef ISIII
  393. #define LOCK_DIR "/etc/locks"
  394. #else
  395. #ifdef HDBUUCP
  396. #ifdef M_SYS5
  397. #define LOCK_DIR "/usr/spool/uucp"
  398. #else
  399. #ifdef M_UNIX
  400. #define LOCK_DIR "/usr/spool/uucp"
  401. #else
  402. #ifdef SVR4
  403. #define LOCK_DIR "/var/spool/locks"
  404. #else
  405. #ifdef SUNOS4
  406. #define LOCK_DIR "/var/spool/locks"
  407. #else
  408. #ifdef LINUXFSSTND
  409. #define LOCK_DIR "/var/lock";
  410. #else
  411. #define LOCK_DIR "/usr/spool/locks"
  412. #endif /* LINUXFSSTND */
  413. #endif /* SUNOS4 */
  414. #endif /* SVR4 */
  415. #endif /* M_UNIX */
  416. #endif /* M_SYS5 */
  417. #else
  418. #ifdef LCKDIR
  419. #define LOCK_DIR "/usr/spool/uucp/LCK"
  420. #else
  421. #ifdef COHERENT
  422. #define LOCK_DIR "/usr/spool/uucp"
  423. #else
  424. #define LOCK_DIR "/usr/spool/uucp"
  425. #endif /* COHERENT */
  426. #endif /* LCKDIR */
  427. #endif /* HDBUUCP */
  428. #endif /* ISIII */
  429. #endif /* AIXRS */
  430. #endif /* RTAIX */
  431. #endif /* HPUX10 */
  432. #endif /* DGUX430 */
  433. #endif /* BSD44 */
  434. #endif /* !LOCK_DIR (outside ifndef) */
  435.  
  436. #ifdef OSF2                /* OSF/1 2.0 or later */
  437. #ifdef LOCK_DIR                /* (maybe 1.x too, who knows...) */
  438. #undef LOCK_DIR
  439. #define LOCK_DIR "/var/spool/locks"
  440. #endif /* LOCK_DIR */
  441. #endif /* OSF2 */
  442.  
  443. #ifdef SVR4
  444. #ifndef BSD44
  445. #ifndef LOCKF
  446. #define LOCKF                /* Use lockf() on tty device in SVR4 */
  447. #endif /* LOCKF */
  448. #endif /* BSD44 */
  449. #endif /* SVR4 */
  450.  
  451. #ifdef NOLOCKF                /* But NOLOCKF cancels LOCKF */
  452. #ifdef LOCKF
  453. #undef LOCKF
  454. #endif /* LOCKF */
  455. #endif /* NOLOCKF */
  456.  
  457. /* More about this below... */
  458.  
  459. #endif /* USETTYLOCK */
  460. #endif /* NOUUCP */
  461.  
  462. /*
  463.   MYREAD means use our internally defined nonblocking buffered read routine.
  464. */
  465. #ifdef ATTSV
  466. #define MYREAD
  467. #endif /* ATTSV */
  468.  
  469. #ifdef ATT7300
  470. #ifndef MYREAD
  471. #define MYREAD
  472. #endif /* MYREAD */
  473. /* bits for attmodem: internal modem in use, restart getty */
  474. #define ISMODEM 1
  475. #define DOGETY 512
  476. #endif  /* ATT7300 */
  477.  
  478. #ifdef BSD42
  479. #define MYREAD
  480. #endif /* BSD42 */
  481.  
  482. #ifdef POSIX
  483. #define MYREAD
  484. #endif /* POSIX */
  485. #ifdef __bsdi__
  486. #ifndef O_NDELAY
  487. #define O_NDELAY O_NONBLOCK
  488. #endif /* O_NDELAY */
  489. #endif /* __bsdi__ */
  490.  
  491. /*
  492.  Variables available to outside world:
  493.  
  494.    dftty  -- Pointer to default tty name string, like "/dev/tty".
  495.    dfloc  -- 0 if dftty is console, 1 if external line.
  496.    dfprty -- Default parity
  497.    dfflow -- Default flow control
  498.    ckxech -- Flag for who echoes console typein:
  499.      1 - The program (system echo is turned off)
  500.      0 - The system (or front end, or terminal).
  501.    functions that want to do their own echoing should check this flag
  502.    before doing so.
  503.  
  504.    flfnam  -- Name of lock file, including its path, e.g.,
  505.                 "/usr/spool/uucp/LCK..cul0" or "/etc/locks/tty77"
  506.    lkflfn  -- Name of link to lock file, including its paths
  507.    haslock -- Flag set if this kermit established a uucp lock.
  508.    lockpid -- PID of other process that has desired line open, as string.
  509.    backgrd -- Flag indicating program executing in background ( & on
  510.                 end of shell command). Used to ignore INT and QUIT signals.
  511.    rtu_bug -- Set by stptrap().  RTU treats ^Z as EOF (but only when we handle
  512.                 SIGTSTP)
  513.  
  514.  Functions for assigned communication line (either external or console tty):
  515.  
  516.    sysinit()               -- System dependent program initialization
  517.    syscleanup()            -- System dependent program shutdown
  518.    ttopen(ttname,local,mdmtyp,timo) -- Open the named tty for exclusive access.
  519.    ttclos()                -- Close & reset the tty, releasing any access lock.
  520.    ttsspd(cps)             -- Set the transmission speed of the tty.
  521.    ttgspd()                -- Get (read) the the transmission speed of the tty.
  522.    ttpkt(speed,flow,parity) -- Put the tty in packet mode and set the speed.
  523.    ttvt(speed,flow)        -- Put the tty in virtual terminal mode.
  524.                                 or in DIALING or CONNECTED modem control state.
  525.    ttres()                 -- Restore original tty modes.
  526.    ttscarr(carrier)        -- Set carrier control mode, on/off/auto.
  527.    ttinl(dest,max,timo)    -- Timed read line from the tty.
  528.    ttinc(timo)             -- Timed read character from tty.
  529.    myread()                -- Raw mode bulk buffer read, gives subsequent
  530.                                 chars one at a time and simulates FIONREAD.
  531.    myunrd(c)               -- Places c back in buffer to be read (one only)
  532.    ttchk()                 -- See how many characters in tty input buffer.
  533.    ttxin(n,buf)            -- Read n characters from tty (untimed).
  534.    ttol(string,length)     -- Write a string to the tty.
  535.    ttoc(c)                 -- Write a character to the tty.
  536.    ttflui()                -- Flush tty input buffer.
  537.    ttsndb()                -- Send BREAK signal.
  538.    ttsndlb()               -- Send Long BREAK signal.
  539.  
  540.    ttlock(ttname)          -- "Lock" tty device against uucp collisions.
  541.    ttunlck()               -- Unlock tty device.
  542.  
  543.                               For ATT7300/Unix PC, System V:
  544.    attdial(ttname,speed,telnbr) -- dials ATT7300/Unix PC internal modem
  545.    offgetty(ttname)        -- Turns off getty(1m) for comms line
  546.    ongetty(ttname)         -- Restores getty() to comms line
  547. */
  548.  
  549. /*
  550. Functions for console terminal:
  551.  
  552.    congm()   -- Get console terminal modes.
  553.    concb(esc) -- Put the console in single-character wakeup mode with no echo.
  554.    conbin(esc) -- Put the console in binary (raw) mode.
  555.    conres()  -- Restore the console to mode obtained by congm().
  556.    conoc(c)  -- Unbuffered output, one character to console.
  557.    conol(s)  -- Unbuffered output, null-terminated string to the console.
  558.    conola(s) -- Unbuffered output, array of strings to the console.
  559.    conxo(n,s) -- Unbuffered output, n characters to the console.
  560.    conchk()  -- Check if characters available at console (bsd 4.2).
  561.                 Check if escape char (^\) typed at console (System III/V).
  562.    coninc(timo)  -- Timed get a character from the console.
  563.    congks(timo)  -- Timed get keyboard scan code.
  564.    conint()  -- Enable terminal interrupts on the console if not background.
  565.    connoi()  -- Disable terminal interrupts on the console if not background.
  566.  
  567. Time functions
  568.  
  569.    msleep(m) -- Millisecond sleep
  570.    ztime(&s) -- Return pointer to date/time string
  571.    rtimer() --  Reset timer
  572.    gtimer()  -- Get elapsed time since last call to rtimer()
  573. */
  574.  
  575. /* Conditional Includes */
  576.  
  577. /* Whether to include <sys/file.h> */
  578.  
  579. #ifdef RTU                /* RTU doesn't */
  580. #define NOFILEH
  581. #endif /* RTU */
  582.  
  583. #ifdef CIE                /* CIE does. */
  584. #undef NOFILEH
  585. #endif /* CIE */
  586.  
  587. #ifdef BSD41                /* 4.1 BSD doesn't */
  588. #define NOFILEH
  589. #endif /* BSD41 */
  590.  
  591. #ifdef is68k                /* is68k (whatever that is)  */
  592. #define NOFILEH
  593. #endif /* is68k */
  594.  
  595. #ifdef MINIX                /* MINIX */
  596. #define NOFILEH
  597. #endif /* MINIX */
  598.  
  599. #ifdef COHERENT                /* Coherent */
  600. #define NOFILEH
  601. #endif /* COHERENT */
  602.  
  603. #ifndef NOFILEH                /* Now include if selected. */
  604. #include <sys/file.h>
  605. #endif /* NOFILEH */
  606.  
  607. /* POSIX */
  608.  
  609. #ifdef BSD44ORPOSIX            /* POSIX uses termios.h */
  610. #define TERMIOS
  611. #ifdef __bsdi__
  612. #ifdef POSIX
  613. #undef _POSIX_SOURCE            /* Get extra stuff from termios.h */
  614. #endif /* POSIX */
  615. #endif /* __bsdi__ */
  616. #include <termios.h>
  617. #ifdef LINUX
  618. #include <sys/ioctl.h>
  619. #endif /* LINUX */
  620. #ifdef QNX16
  621. #include <ioctl.h>
  622. #endif /* QNX16 */
  623. #ifdef __bsdi__
  624. #ifdef POSIX
  625. #define _POSIX_SOURCE
  626. #endif /* POSIX */
  627. #endif /* __bsdi__ */
  628. #ifndef BSD44                /* Really POSIX */
  629. #ifndef CK_QNX32            /* was CK_QNX32 */
  630. #define NOSYSIOCTLH            /* No ioctl's allowed. */
  631. #undef ultrix                /* Turn off any ultrix features. */
  632. #endif /* CK_QNX32 */
  633. #endif /* BSD44 */
  634. #endif /* POSIX */
  635.  
  636. /* System III, System V */
  637.  
  638. #ifdef ATTSV
  639. #ifndef BSD44
  640. #ifndef POSIX
  641. #include <termio.h>
  642. #endif /* POSIX */
  643. #endif /* BSD44 */
  644. #ifdef TERMIOX
  645. /* Need this for termiox structure, RTS/CTS and DTR/CD flow control */
  646. #include <termiox.h>
  647.   struct termiox rctsx;
  648. #else
  649. #ifdef STERMIOX
  650. #ifdef SCO_OSR504
  651. /* Sorry, this is truly disgusting but it's SCO's fault. */
  652. #ifndef _SVID3
  653. #define _CK_SVID3_X
  654. #define _SVID3
  655. #endif /* _SVID3 */
  656. #endif /* SCO_OSR504 */
  657. #include <sys/termiox.h>
  658.   struct termiox rctsx;
  659. #ifdef CK_SVID3_X
  660. #undef _SVID3
  661. #undef CK_SVID3_X
  662. #endif /* CK_SVID3_X */
  663. #endif /* STERMIOX */
  664. #endif /* TERMIOX */
  665. #endif /* ATTSV */
  666.  
  667. #ifdef COHERENT            /* Use termio.h, not sgtty.h for Coherent */
  668. #include <termio.h>
  669. #endif /* COHERENT */
  670.  
  671. #ifdef MINIX                /* MINIX uses ioctl's */
  672. #define NOSYSIOCTLH            /* but has no <sys/ioctl.h> */
  673. #endif /* MINIX */
  674.  
  675. /* Others */
  676.  
  677. #ifndef NOSYSIOCTLH            /* Others use ioctl() */
  678. #ifdef SUN4S5
  679. /*
  680.   This is to get rid of cpp warning messages that occur because all of
  681.   these symbols are defined by both termios.h and ioctl.h on the SUN.
  682. */
  683. #undef ECHO
  684. #undef NL0
  685. #undef NL1
  686. #undef TAB0
  687. #undef TAB1
  688. #undef TAB2
  689. #undef XTABS
  690. #undef CR0
  691. #undef CR1
  692. #undef CR2
  693. #undef CR3
  694. #undef FF0
  695. #undef FF1
  696. #undef BS0
  697. #undef BS1
  698. #undef TOSTOP
  699. #undef FLUSHO
  700. #undef PENDIN
  701. #undef NOFLSH
  702. #endif /* SUN4S5 */
  703. #include <sys/ioctl.h>
  704. #endif /* NOSYSIOCTLH */
  705. /*
  706.   We really, really, REALLY want FIONREAD, because it is the only way to find
  707.   out not just *if* stuff is waiting to be read, but how much, which is
  708.   critical to our sliding-window and streaming procedures, not to mention
  709.   efficiency of CONNECT, etc.
  710. */
  711. #ifdef BELLV10
  712. #include <sys/filio.h>            /* For FIONREAD */
  713. #ifdef FIONREAD
  714. #define MYREAD
  715. #endif /* MYREAD */
  716. #endif /* BELLV10 */
  717.  
  718. #ifndef FIONREAD
  719. /* It wasn't found in ioctl.h or term*.h - try these places: */
  720. #ifdef UNIXWARE
  721. #include <sys/filio.h>
  722. #else
  723. #ifdef SOLARIS
  724. #include <sys/filio.h>
  725. #endif /* SOLARIS */
  726. #endif /* UNIXWARE */
  727. #endif /* FIONREAD */
  728.  
  729. #ifdef XENIX /* Was M_UNIX but XENIX implies M_UNIX and applies to XENIX too */
  730. /*
  731.   <sys/socket.h> included above via "ckcnet.h" defines FIONREAD as
  732.   something.  Due to this, in_chk() uses the FIONREAD instead of RDCHK
  733.   and the hot keys during file transfer (X to cancel file etc) do not
  734.   work because FIONREAD doesn't work even though it is defined.
  735.  
  736.   NOTE: This might also be true elsewhere.
  737. */
  738. #ifdef FIONREAD
  739. #undef FIONREAD
  740. #endif /* FIONREAD */
  741. #endif /* XENIX */
  742.  
  743. #ifdef CK_SCOV5                /* Ditto for SCO OpenServer 5.0 */
  744. #ifdef FIONREAD
  745. #undef FIONREAD
  746. #endif /* FIONREAD */
  747. #endif /* XENIX */
  748.  
  749. /* Whether to include <fcntl.h> */
  750.  
  751. #ifndef is68k                /* Only a few don't have this one. */
  752. #ifndef BSD41
  753. #ifndef FT21
  754. #ifndef FT18
  755. #ifndef COHERENT
  756. #include <fcntl.h>
  757. #endif /* COHERENT */
  758. #endif /* FT18 */
  759. #endif /* FT21 */
  760. #endif /* BSD41 */
  761. #endif /* not is68k */
  762.  
  763. #ifdef COHERENT
  764. #ifdef _I386
  765. #include <fcntl.h>
  766. #else
  767. #include <sys/fcntl.h>
  768. #endif /* _I386 */
  769. #endif /* COHERENT */
  770.  
  771. #ifdef ATT7300                /* Unix PC, internal modem dialer */
  772. #include <sys/phone.h>
  773. #endif /* ATT7300 */
  774.  
  775. #ifdef HPUX                /* HP-UX variations. */
  776. #define HPUXJOBCTL
  777. #include <sys/modem.h>            /* HP-UX modem signals */
  778. #ifdef hp9000s500            /* Model 500 */
  779. #undef HPUXJOBCTL
  780. #endif /* hp9000s500 */
  781. #ifdef HPUXPRE65
  782. #undef HPUXJOBCTL
  783. typedef long mflag;
  784. #endif /* HPUXPRE65 */
  785. #ifdef HPUXJOBCTL
  786. #include <sys/bsdtty.h>            /* HP-UX Berkeley tty support */
  787. #endif /* HPUXJOBCTL */
  788. #endif /* HPUX */
  789.  
  790. /*
  791.   Which time.h files to include... See ckcdeb.h for defaults.
  792.   Note that 0, 1, 2, or all 3 of these can be included according to
  793.   the symbol definitions.
  794. */
  795. #ifndef NOTIMEH
  796. #ifdef TIMEH
  797. #include <time.h>
  798. #endif /* TIMEH */
  799. #endif /* NOTIMEH */
  800.  
  801. #ifndef NOSYSTIMEH
  802. #ifdef SYSTIMEH
  803. #include <sys/time.h>
  804. #endif /* SYSTIMEH */
  805. #endif /* NOSYSTIMEH */
  806.  
  807. #ifndef NOSYSTIMEBH
  808. #ifdef SYSTIMEBH
  809. #include <sys/timeb.h>
  810. #endif /* SYSTIMEBH */
  811. #endif /* NOSYSTIMEBH */
  812.  
  813. #ifdef DCLTIMEVAL
  814. /*
  815.   In certain POSIX builds (like Unixware 7), <[sys/]time.h> refuses to
  816.   define the structs we need to access the higher speeds, so we have to
  817.   do it ourselves.
  818. */
  819. struct timeval {
  820.     long tv_sec;
  821.     long tv_usec;
  822. };
  823. struct timezone {
  824.     int tz_minuteswest;
  825.     int tz_dsttime;
  826. };
  827. #endif /* DCLTIMEVAL */
  828.  
  829. #ifdef __linux__
  830. /* THIS IS OBSOLETE since about Linux 0.92 */
  831. #ifdef OLINUXHISPEED
  832. #include <linux/serial.h>
  833. #endif /* OLINUXHISPEED */
  834. #ifdef __alpha__            /* Linux on DEC Alpha */
  835. #ifndef __GLIBC__            /* But not with glibc */
  836. #include <asm/termios.h>
  837. #endif /* __GLIBC__ */
  838. #endif /* __alpha__ */
  839. #endif /* __linux__ */
  840.  
  841. #ifdef NOIEXTEN                /* This is broken on some systems */
  842. #undef IEXTEN                /* like Convex/OS 9.1 */
  843. #endif /* NOIEXTEN */
  844. #ifndef IEXTEN                /* Turn off ^O/^V processing. */
  845. #define IEXTEN 0            /* Needed, at least, on BSDI. */
  846. #endif /* IEXTEN */
  847. /*
  848.   Pick up definitions needed for select() if we don't have them already.
  849.   Normally they come from <sys/types.h> but some systems get them from
  850.   <sys/select.h>...  Rather than hardwire all of them into the source, we
  851.   include it if SELECT_H is defined in compile-time CFLAGS.
  852. */
  853. #ifndef SCO_OSR504
  854. #ifdef SELECT_H
  855. #include <sys/select.h>
  856. #endif /* SELECT_H */
  857. #endif /* SCO_OSR504 */
  858.  
  859. #ifdef aegis
  860. #include "/sys/ins/base.ins.c"
  861. #include "/sys/ins/error.ins.c"
  862. #include "/sys/ins/ios.ins.c"
  863. #include "/sys/ins/sio.ins.c"
  864. #include "/sys/ins/pad.ins.c"
  865. #include "/sys/ins/time.ins.c"
  866. #include "/sys/ins/pfm.ins.c"
  867. #include "/sys/ins/pgm.ins.c"
  868. #include "/sys/ins/ec2.ins.c"
  869. #include "/sys/ins/type_uids.ins.c"
  870. #include <default_acl.h>
  871. #undef TIOCEXCL
  872. #undef FIONREAD
  873. #endif /* aegis */
  874.  
  875. #ifdef sxaE50                /* PFU Compact A SX/A TISP V10/L50 */
  876. #undef FIONREAD
  877. #endif /* sxaE50 */
  878.  
  879. /* The following #defines are catch-alls for those systems */
  880. /* that didn't have or couldn't find <file.h>... */
  881.  
  882. #ifndef FREAD
  883. #define FREAD 0x01
  884. #endif /* FREAD */
  885.  
  886. #ifndef FWRITE
  887. #define FWRITE 0x10
  888. #endif /* FWRITE */
  889.  
  890. #ifndef O_RDONLY
  891. #define O_RDONLY 000
  892. #endif /* O_RDONLY */
  893.  
  894. #ifdef SVORPOSIX
  895. /*
  896.   Modem signals are also forbidden in the POSIX world.  But some POSIX-based
  897.   platforms let us at them anyway if we know where to look.
  898. */
  899. #ifndef NEEDMDMDEFS
  900. /* Doesn't work for Linux */
  901. #ifdef UNIXWARE7
  902. #define NEEDMDMDEFS
  903. #endif /* UNIXWARE7 */
  904. #endif /* NEEDMDMDEFS */
  905.  
  906. #ifdef NEEDMDMDEFS
  907. #ifndef TIOCMGET
  908. #define TIOCMGET (('t'<<8)|29)
  909. #endif /* TIOCMGET */
  910.  
  911. #ifndef TIOCM_DTR
  912. #define TIOCM_DTR 0x0002
  913. #endif /* TIOCM_DTR */
  914. #ifndef TIOCM_RTS
  915. #define TIOCM_RTS 0x0004
  916. #endif /* TIOCM_RTS */
  917. #ifndef TIOCM_CTS
  918. #define TIOCM_CTS 0x0020
  919. #endif /* TIOCM_CTS */
  920. #ifndef TIOCM_CAR
  921. #define TIOCM_CAR 0x0040
  922. #endif /* TIOCM_CAR */
  923. #ifndef TIOCM_RNG
  924. #define TIOCM_RNG 0x0080
  925. #endif /* TIOCM_RNG */
  926. #ifndef TIOCM_DSR
  927. #define TIOCM_DSR 0x0100
  928. #endif /* TIOCM_DSR */
  929. #endif /* NEEDMDMDEFS */
  930. #endif /* SVORPOSIX */
  931.  
  932. /* Declarations */
  933.  
  934. #ifdef OXOS
  935. #undef TCGETA
  936. #undef TCSETA
  937. #undef TCSETAW
  938. #undef TCSETAF
  939. #define TCGETA TCGETS
  940. #define TCSETA TCSETS
  941. #define TCSETAW TCSETSW
  942. #define TCSETAF TCSETSF
  943. #define termio termios
  944. #endif /* OXOS */
  945.  
  946. #ifdef SVORPOSIX            /* AT&T Sys V or POSIX */
  947. #ifdef UNIXWAREPOSIX            /* UnixWare 7 POSIX build */
  948. /*
  949.   In Unixware POSIX builds, <[sys/]time.h> refuses to define the
  950.   structs we need to access the higher speeds, so we have to do it
  951.   ourselves.
  952. */
  953. struct timeval {
  954.     long tv_sec;
  955.     long tv_usec;
  956. };
  957. struct timezone {
  958.     int tz_minuteswest;
  959.     int tz_dsttime;
  960. };
  961. #endif /* UNIXWAREPOSIX */
  962. #endif /* SVORPOSIX */
  963.  
  964. #ifdef __GNUC__
  965. #ifdef XENIX
  966. /*
  967.   Because Xenix <time.h> doesn't declare time() if we're using gcc.
  968. */
  969. time_t time();
  970. #endif /* XENIX */
  971. #endif /* __GNUC__ */
  972.  
  973. /* Special stuff for V7 input buffer peeking */
  974.  
  975. #ifdef  V7
  976. int kmem[2] = { -1, -1};
  977. char *initrawq(), *qaddr[2]={0,0};
  978. #define CON 0
  979. #define TTY 1
  980. #endif /* V7 */
  981.  
  982. /* dftty is the device name of the default device for file transfer */
  983. /* dfloc is 0 if dftty is the user's console terminal, 1 if an external line */
  984.  
  985. #ifdef BEOS
  986.     char * dftty = NULL;
  987.     char *dfmdm = "none";
  988.     int dfloc = 0;                  /* that goes in local mode by default */
  989. #else
  990. #ifndef DFTTY
  991. #ifdef PROVX1
  992.     char *dftty = "/dev/com1.dout"; /* Only example so far of a system */
  993.     char *dfmdm = "none";
  994.     int dfloc = 1;                  /* that goes in local mode by default */
  995. #else
  996.     char *dftty = CTTNAM;               /* Remote by default, use normal */
  997.     char *dfmdm = "none";
  998.     int dfloc = 0;                      /* controlling terminal name. */
  999. #endif /* PROVX1 */
  1000. #else
  1001.     char *dftty = DFTTY;        /* Default location specified on */
  1002.     char *dfmdm = "none";        /* command line. */
  1003.     int dfloc = 1;                      /* controlling terminal name. */
  1004. #endif /* DFTTY */
  1005. #endif /* BEOS */
  1006.  
  1007.     char cttnam[DEVNAMLEN+1] = { '\0', '\0' }; /* Determined at runtime */
  1008.  
  1009. #ifdef RTU
  1010.     int rtu_bug = 0;            /* set to 1 when returning from SIGTSTP */
  1011. #endif /* RTU */
  1012.  
  1013.     int dfprty = DEFPAR;                /* Default parity (0 = none) */
  1014.     int ttprty = 0;                     /* The parity that is in use. */
  1015.     static int ttpmsk = 0xff;        /* Parity stripping mask. */
  1016.     int ttmdm = 0;                      /* Modem in use. */
  1017.     int ttcarr = CAR_AUT;        /* Carrier handling mode. */
  1018.     int dfflow = FLO_NONE;        /* Default flow control is NONE */
  1019.     int backgrd = 0;                    /* Assume in foreground (no '&' ) */
  1020. #ifdef F_SETFL
  1021.     int iniflags = -1;            /* fcntl flags for ttyfd */
  1022. #endif /* F_SETFL */
  1023.     int fdflag = 0;            /* Flag for redirected stdio */
  1024.     int ttfdflg = 0;            /* Open File descriptor was given */
  1025.     int tvtflg = 0;            /* Flag that ttvt has been called */
  1026.     long ttspeed = -1L;            /* For saving speed */
  1027.     int ttflow = -9;            /* For saving flow */
  1028.     int ttld = -1;            /* Line discipline */
  1029.  
  1030. #ifdef sony_news
  1031.     static int km_con = -1;        /* Kanji mode for console tty */
  1032.     static int km_ext = -1;        /* Kanji mode for external device */
  1033. #endif /* sony_news */
  1034.  
  1035. #ifdef PARSENSE
  1036.     static int needpchk = 1;        /* Need parity check */
  1037. #else
  1038.     static int needpchk = 0;
  1039. #endif /* PARSENSE */
  1040.  
  1041. #ifdef HWPARITY
  1042. /*
  1043.   Unfortunately we must do this with global variables rather than through the
  1044.   tt...() APIs to avoid changing the APIs and the many modules that use them.
  1045.   If hwparity != 0, this indicates 8 data bits + parity, rather than 7 data
  1046.   bits + parity or 8 data bits and no parity, and overrides the regular parity
  1047.   variable, which is communicated to this module thru ttpkt(), and represented
  1048.   locally by the ttprty variable.
  1049. */
  1050.     extern int hwparity;        /* Hardware parity */
  1051.     extern int stopbits;        /* Stop bits */
  1052. #endif /* HWPARITY */
  1053.  
  1054. #ifdef TCPSOCKET
  1055. #ifdef TCP_NODELAY
  1056. static int nodelay_sav = -1;
  1057. #endif /* TCP_NODELAY */
  1058. #endif /* TCPSOCKET */
  1059.  
  1060. static int sigint_ign = 0;        /* SIGINT is ignored */
  1061.  
  1062. /*
  1063.   Having this module rely on external globals is bad, but fixing this
  1064.   requires overhaul of the ck*tio.c modules for all the different operating
  1065.   systems supported by C-Kermit.  Left for a future release.
  1066. */
  1067. extern int ttnproto;            /* Defined in ckcnet.c */
  1068. extern int ttnet;            /* Defined in ckcnet.c */
  1069. extern int nopush, xfrcan, xfrchr, xfrnum; /* Defined in ckcmai.c */
  1070. extern int suspend, wasclosed;
  1071. extern int inserver, local;
  1072.  
  1073. int ckxech = 0; /* 0 if system normally echoes console characters, else 1 */
  1074.  
  1075. int ckmaxfiles = 0;            /* Max number of open files */
  1076.  
  1077. #ifdef CK_ENCRYPTION            /* Kerberos */
  1078. #include "ckuath.h"
  1079. extern int me_encrypt, u_encrypt;
  1080. #endif /* CK_ENCRYPTION */
  1081.  
  1082. /* Declarations of variables global within this module */
  1083.  
  1084. #ifdef TTLEBUF                /* See ckcnet.h */
  1085. int ttpush = -1;
  1086. #define LEBUFSIZ 4096
  1087. static CHAR le_buf[LEBUFSIZ];
  1088. static int le_start = 0, le_end = 0, le_data = 0;
  1089. #endif /* TTLEBUF */
  1090.  
  1091. static time_t tcount = (time_t)0;    /* Elapsed time counter */
  1092.  
  1093. static SIGTYP (*saval)()     = NULL;    /* For saving alarm() handler */
  1094. static SIGTYP (*savquit)()   = NULL;    /* and other signal handlers */
  1095. #ifdef SIGUSR1
  1096. static SIGTYP (*savusr1)()   = NULL;
  1097. #endif /* SIGUSR1 */
  1098. #ifdef SIGUSR2
  1099. static SIGTYP (*savusr2)()   = NULL;
  1100. #endif /* SIGUSR2 */
  1101. #ifdef SIGPIPE
  1102. static SIGTYP (*savpipe)()   = NULL;
  1103. #endif /* SIGPIPE */
  1104. #ifdef SIGDANGER
  1105. static SIGTYP (*savdanger)() = NULL;
  1106. #endif /* SIGDANGER */
  1107.  
  1108. #ifndef NOJC
  1109. static SIGTYP (*jchdlr)()    = NULL;    /* For checking suspend handler */
  1110. #endif /* NOJC */
  1111. static int jcshell = -1;        /* And flag for result */
  1112.  
  1113. /*
  1114.   BREAKNULS is defined for systems that simulate sending a BREAK signal
  1115.   by sending a bunch of NUL characters at low speed.
  1116. */
  1117. #ifdef PROVX1
  1118. #ifndef BREAKNULS
  1119. #define BREAKNULS
  1120. #endif /* BREAKNULS */
  1121. #endif /* PROVX1 */
  1122.  
  1123. #ifdef V7
  1124. #ifndef BREAKNULS
  1125. #define BREAKNULS
  1126. #endif /* BREAKNULS */
  1127. #endif /* V7 */
  1128.  
  1129. #ifdef BREAKNULS
  1130. static char                /* A string of nulls */
  1131. *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";
  1132. #endif /* BREAKNULS */
  1133.  
  1134. #ifdef CK_POSIX_SIG            /* Longjump buffers */
  1135. static sigjmp_buf sjbuf;        /* POSIX signal handling */
  1136. #else
  1137. static jmp_buf sjbuf;
  1138. #endif /* CK_POSIX_SIG */
  1139.  
  1140. #ifdef V7
  1141. static jmp_buf jjbuf;
  1142. #endif /* V7 */
  1143.  
  1144. /* static */                /* (Not static any more) */
  1145. int ttyfd = -1;                /* TTY file descriptor */
  1146.  
  1147. int ttpipe = 0;                /* NETCMD: Use pipe instead of ttyfd */
  1148. int ttpty  = 0;                         /* NETPTY: Use pty instead of ttfyd */
  1149.  
  1150. #ifdef NETCMD
  1151. static int pipe0[2], pipe1[2];        /* Pipes for net i/o */
  1152. static PID_T ttpid = 0;            /* Process ID for fork */
  1153. static int fdin, fdout;            /* File descriptors for pipe */
  1154. static FILE * ttout = NULL;        /* File pointer for output pipe */
  1155. #ifdef DCLFDOPEN
  1156. /* fdopen() needs declaring because it's not declared in <stdio.h> */
  1157. _PROTOTYP( FILE * fdopen, (int, char *) );
  1158. #endif /* DCLFDOPEN */
  1159. #endif /* NETCMD */
  1160.  
  1161. extern int pexitstat, quiet;
  1162.  
  1163. #ifdef Plan9
  1164. int ttyctlfd  = -1;   /* TTY control channel - What? UNIX doesn't have one? */
  1165. int consctlfd = -1;            /* Console control channel */
  1166. int noisefd = -1;            /* tone channel */
  1167. static int ttylastspeed = -1;        /* So we can lie about the speed */
  1168. #endif /* Plan9 */
  1169.  
  1170. int telnetfd = 0;            /* File descriptor is for telnet */
  1171. int x25fd = 0;                /* File descriptor is for X.25 */
  1172.  
  1173. char lockpid[16] = { '\0', '\0' };    /* PID stored in lockfile, as string */
  1174.  
  1175. static int lkf = 0,                     /* Line lock flag */
  1176.     cgmf = 0,                           /* Flag that console modes saved */
  1177.     xlocal = 0,                         /* Flag for tty local or remote */
  1178.     curcarr = 0;            /* Carrier mode: require/ignore. */
  1179.  
  1180. static int netconn = 0;            /* 1 if network connection active */
  1181.  
  1182. static char escchr;                     /* Escape or attn character */
  1183.  
  1184. #ifdef CK_SCO32V4
  1185. #include <sys/time.h>
  1186. #endif /* CK_SCO32V4 */
  1187.  
  1188. #ifdef HAVE_TV
  1189.     static struct timeval tv;        /* For getting time, from sys/time.h */
  1190. #endif /* HAVE_TV */
  1191. #ifdef HAVE_TZ
  1192.     static struct timezone tz;
  1193. #endif /* HAVE_TZ */
  1194.  
  1195. #ifdef OSF
  1196.     static struct timeb ftp;            /* And from sys/timeb.h */
  1197. #endif /* OSF */
  1198.  
  1199. #ifdef BSD29
  1200.     static long xclock;            /* For getting time from sys/time.h */
  1201.     static struct timeb ftp;            /* And from sys/timeb.h */
  1202. #endif /* BSD29 */
  1203.  
  1204. #ifdef BSD41
  1205.     static long xclock;            /* For getting time from sys/time.h */
  1206.     static struct timeb ftp;            /* And from sys/timeb.h */
  1207. #endif /* BSD41 */
  1208.  
  1209. #ifdef BELLV10
  1210.     static long xclock;            /* For getting time from sys/time.h */
  1211.     static struct timeb ftp;            /* And from sys/timeb.h */
  1212. #endif /* BELLV10 */
  1213.  
  1214. #ifdef FT21
  1215.     static long xclock;            /* For getting time from sys/time.h */
  1216.     static struct timeb ftp;            /* And from sys/timeb.h */
  1217. #endif /* FT21 */
  1218.  
  1219. #ifdef TOWER1
  1220.     static long xclock;            /* For getting time from sys/time.h */
  1221.     static struct timeb ftp;        /* And from sys/timeb.h */
  1222. #endif /* TOWER1 */
  1223.  
  1224. #ifdef COHERENT
  1225.     static long xclock;            /* For getting time from sys/time.h */
  1226.     static struct timeb ftp;        /* And from sys/timeb.h */
  1227. #endif /* COHERENT */
  1228.  
  1229. #ifdef V7
  1230.     static long xclock;
  1231. #endif /* V7 */
  1232.  
  1233. /* sgtty/termio information... */
  1234.  
  1235. #ifdef BSD44ORPOSIX            /* POSIX or BSD44 */
  1236.   static struct termios
  1237.     ttold, ttraw, tttvt, ttcur,
  1238.     ccold, ccraw, cccbrk;
  1239. #else                    /* BSD, V7, etc */
  1240.  
  1241. #ifdef COHERENT                /* Hack alert... */
  1242. #define ATTSV
  1243. #endif /* COHERENT */
  1244.  
  1245. #ifdef ATTSV
  1246.   static struct termio ttold = {0};    /* Init'd for word alignment, */
  1247.   static struct termio ttraw = {0};    /* which is important for some */
  1248.   static struct termio tttvt = {0};    /* systems, like Zilog... */
  1249.   static struct termio ttcur = {0};
  1250.   static struct termio ccold = {0};
  1251.   static struct termio ccraw = {0};
  1252.   static struct termio cccbrk = {0};
  1253. #else
  1254.   static struct sgttyb                  /* sgtty info... */
  1255.     ttold, ttraw, tttvt, ttcur,     /* for communication line */
  1256.     ccold, ccraw, cccbrk;        /* and for console */
  1257. #ifdef BELLV10
  1258.   static struct ttydevb            /* Device info... */
  1259.     tdold, tdcur;            /* for communication device */
  1260. #endif /* BELLV10 */
  1261. #ifdef TIOCGETC
  1262.   static struct tchars tchold, tchnoi;
  1263.  
  1264.   static int tcharf;
  1265. #endif /* TIOCGETC */
  1266. #ifdef TIOCGLTC
  1267.   static struct ltchars ltchold, ltchnoi;
  1268.   static int ltcharf;
  1269. #endif /* TIOCGLTC */
  1270.   int lmodef = 0;            /* Local modes */
  1271.   int lmode = 0;
  1272. #endif /* ATTSV */
  1273. #endif /* BSD44ORPOSIX */
  1274.  
  1275. #ifdef COMMENT
  1276. /* It picks up the speeds but they don't work */
  1277. #ifdef UNIXWARE                /* For higher serial speeds */
  1278. #ifdef UW7                /* in Unixware 7.0 */
  1279. #include <sys/asyc.h>            /* This picks up 57600 and 115200 */
  1280. #endif /* UW7 */
  1281. #endif /* UNIXWARE */
  1282. #endif /* COMMENT */
  1283.  
  1284. #ifdef PROVX1
  1285.   static struct sgttyb ttbuf;
  1286. #endif /* PROVX1 */
  1287.  
  1288. #ifdef ultrix
  1289. /* do we really need this? */
  1290.   static struct sgttyb vanilla;
  1291. #endif /* ultrix */
  1292.  
  1293. #ifdef ATT7300
  1294. static int attmodem = 0;                /* ATT7300 internal-modem status */
  1295. struct updata dialer = {0};        /* Condition dialer for data call */
  1296. #endif /* ATT7300 */
  1297.  
  1298. #ifndef NOUUCP
  1299. #define FLFNAML 128
  1300. #ifndef USETTYLOCK
  1301. #ifdef RTAIX
  1302. char lkflfn[128] = { '\0', '\0' };    /* and possible link to it */
  1303. #endif /* RTAIX */
  1304. char lock2[128] =  { '\0', '\0' };    /* Name of second lockfile */
  1305. #endif /* USETTYLOCK */
  1306. #else
  1307. #define FLFNAML 7
  1308. #endif /* NOUUCP */
  1309. char flfnam[FLFNAML+1] = { '\0', '\0' }; /* UUCP lock file path name */
  1310.  
  1311. int haslock = 0;            /* =1 if this kermit locked uucp */
  1312.  
  1313. #ifndef OXOS
  1314. #ifdef SVORPOSIX
  1315. static int conesc = 0;                  /* set to 1 if esc char (^\) typed */
  1316. #else
  1317. #ifdef V7
  1318. static int conesc = 0;
  1319. #else
  1320. #ifdef C70
  1321. static int conesc = 0;
  1322. #endif /* C70 */
  1323. #endif /* V7 */
  1324. #endif /* SVORPOSIX */
  1325. #endif /* OXOS */
  1326.  
  1327. static char ttnmsv[DEVNAMLEN+1];    /* Local copy of comm device name */
  1328. #ifdef USETTYLOCK
  1329. static char lockname[DEVNAMLEN+1];    /* Ditto, the part after "/dev/". */
  1330. #endif /* USETTYLOCK */
  1331.  
  1332. #ifdef aegis
  1333. static status_$t st;                    /* error status return value */
  1334. static short concrp = 0;                /* true if console is CRP pad */
  1335. #define CONBUFSIZ 10
  1336. static char conbuf[CONBUFSIZ];          /* console readahead buffer */
  1337. static int  conbufn = 0;                /* # chars in readahead buffer */
  1338. static char *conbufp;                   /* next char in readahead buffer */
  1339. static uid_$t ttyuid;                   /* tty type uid */
  1340. static uid_$t conuid;                   /* stdout type uid */
  1341.  
  1342. /* APOLLO Aegis main()
  1343.  * establish acl usage and cleanup handling
  1344.  *    this makes sure that CRP pads
  1345.  *    get restored to a usable mode
  1346.  */
  1347. main(argc,argv) int argc; char **argv; {
  1348.         status_$t status;
  1349.         pfm_$cleanup_rec dirty;
  1350.  
  1351.         PID_T pid = getpid();
  1352.  
  1353.         /* acl usage according to invoking environment */
  1354.         default_acl(USE_DEFENV);
  1355.  
  1356.         /* establish a cleanup continuation */
  1357.         status = pfm_$cleanup(dirty);
  1358.         if (status.all != pfm_$cleanup_set) {
  1359.                 /* only handle faults for the original process */
  1360.                 if (pid == getpid() && status.all > pgm_$max_severity) {
  1361.             /* blew up in main process */
  1362.             status_$t quo;
  1363.             pfm_$cleanup_rec clean;
  1364.  
  1365.             /* restore the console in any case */
  1366.             conres();
  1367.  
  1368.             /* attempt a clean exit */
  1369.             debug(F101, "cleanup fault status", "", status.all);
  1370.  
  1371.             /* doexit(), then send status to continuation */
  1372.             quo = pfm_$cleanup(clean);
  1373.             if (quo.all == pfm_$cleanup_set)
  1374.               doexit(pgm_$program_faulted,-1);
  1375.             else if (quo.all > pgm_$max_severity)
  1376.               pfm_$signal(quo); /* blew up in doexit() */
  1377.                 }
  1378.                 /* send to the original continuation */
  1379.                 pfm_$signal(status);
  1380.                 /*NOTREACHED*/
  1381.         }
  1382.         return(ckcmai(argc, argv));
  1383. }
  1384. #endif /* aegis */
  1385.  
  1386. /* ANSI-style prototypes for internal functions. */
  1387. /* Functions used outside this module are prototyped in ckcker.h. */
  1388.  
  1389. #ifdef apollo
  1390. _PROTOTYP( SIGTYP timerh, () );
  1391. _PROTOTYP( SIGTYP cctrap, () );
  1392. _PROTOTYP( SIGTYP esctrp, () );
  1393. _PROTOTYP( SIGTYP sig_ign, () );
  1394. #else
  1395. _PROTOTYP( SIGTYP timerh, (int) );
  1396. _PROTOTYP( SIGTYP cctrap, (int) );
  1397. _PROTOTYP( SIGTYP esctrp, (int) );
  1398. #endif /* apollo */
  1399. _PROTOTYP( int do_open, (char *) );
  1400. _PROTOTYP( static int in_chk, (int, int) );
  1401. _PROTOTYP( static int ttrpid, (char *) );
  1402. _PROTOTYP( static int ttchkpid, (char *) );
  1403. _PROTOTYP( static int ttlock, (char *) );
  1404. _PROTOTYP( static int ttunlck, (void) );
  1405. _PROTOTYP( int mygetbuf, (void) );
  1406. _PROTOTYP( int myfillbuf, (void) );
  1407. _PROTOTYP( VOID conbgt, (int) );
  1408. #ifdef ACUCNTRL
  1409. _PROTOTYP( VOID acucntrl, (char *, char *) );
  1410. #endif /* ACUCNTRL */
  1411.  
  1412. #ifdef BSD44ORPOSIX
  1413. _PROTOTYP( int carrctl, (struct termios *, int) );
  1414. #else
  1415. #ifdef ATTSV
  1416. _PROTOTYP( int carrctl, (struct termio *, int) );
  1417. #else
  1418. _PROTOTYP( int carrctl, (struct sgttyb *, int) );
  1419. #endif /* ATTSV */
  1420. #endif /* BSD44ORPOSIX */
  1421.  
  1422. #ifdef ATT7300
  1423. _PROTOTYP( int attdial, (char *, long, char *) );
  1424. _PROTOTYP( int offgetty, (char *) );
  1425. _PROTOTYP( int ongetty, (char *) );
  1426. #endif /* ATT7300 */
  1427.  
  1428. #ifdef BEOSORBEBOX
  1429. #ifdef SELECT
  1430.     /* BeOS is not capable of using SELECT on anything but sockets */
  1431. #undef SELECT
  1432. #endif /* SELECT */
  1433. #include <kernel/OS.h>
  1434. /* #ifdef BE_DR_7 */
  1435. static double time_started = 0.0;
  1436. struct ALARM_STRUCT {
  1437.     thread_id thread;
  1438.     int time;
  1439. };
  1440. static thread_id alarm_thread = -1;
  1441. static struct ALARM_STRUCT alarm_struct;
  1442. _PROTOTYP( long do_alarm, (void *) );
  1443. _PROTOTYP( unsigned int alarm, (unsigned int) );
  1444. _PROTOTYP( void alarm_expired, (void) );
  1445. /* #endif */ /* BE_DR_7 */
  1446. #endif /* BEOSORBEBOX */
  1447.  
  1448. #ifndef xunchar
  1449. #define xunchar(ch) (((ch) - 32 ) & 0xFF )    /* Character to number */
  1450. #endif /* xunchar */
  1451.  
  1452. #ifdef CK_ANSIC
  1453. static char *
  1454. xxlast(char *s, char c)
  1455. #else
  1456. static char *
  1457. xxlast(s,c) char *s; char c;
  1458. #endif /* CK_ANSIC */
  1459. /* xxlast */ {        /*  Last occurrence of character c in string s. */
  1460.     int i;
  1461.     for (i = (int)strlen(s); i > 0; i--)
  1462.       if (s[i-1] == c ) return(s + (i - 1));
  1463.     return(NULL);
  1464. }
  1465.  
  1466. /* Timeout handler for communication line input functions */
  1467.  
  1468. SIGTYP
  1469. timerh(foo) int foo; {
  1470.     ttimoff();
  1471. #ifdef BEOSORBEBOX
  1472. /* #ifdef BE_DR_7 */
  1473.     alarm_expired();
  1474. /* #endif */ /* BE_DR_7 */
  1475. #endif /* BEOSORBEBOX */
  1476. #ifdef CK_POSIX_SIG
  1477.     siglongjmp(sjbuf,1);
  1478. #else
  1479.     longjmp(sjbuf,1);
  1480. #endif /* CK_POSIX_SIG */
  1481. }
  1482.  
  1483. SIGTYP
  1484. xtimerh(foo) int foo; {            /* Like timerh() but does */
  1485. #ifdef BEOSORBEBOX            /* not reset the itslef */
  1486. /* #ifdef BE_DR_7 */
  1487.     alarm_expired();
  1488. /* #endif */ /* BE_DR_7 */
  1489. #endif /* BEOSORBEBOX */
  1490. #ifdef CK_POSIX_SIG
  1491.     siglongjmp(sjbuf,1);
  1492. #else
  1493.     longjmp(sjbuf,1);
  1494. #endif /* CK_POSIX_SIG */
  1495. }
  1496.  
  1497.  
  1498. /* Control-C trap for communication line input functions */
  1499.  
  1500. int cc_int;                /* Flag */
  1501. SIGTYP (* occt)();            /* For saving old SIGINT handler */
  1502.  
  1503. SIGTYP
  1504. cctrap(foo) int foo; {            /* Needs arg for ANSI C */
  1505.   cc_int = 1;                /* signal() prototype. */
  1506.   return;
  1507. }
  1508.  
  1509. /*  S Y S I N I T  --  System-dependent program initialization.  */
  1510.  
  1511. /*
  1512.  * ttgwsiz() returns:
  1513.  *    1    tt_rows and tt_cols are known, both altered, both > 0
  1514.  *    0    tt_rows and/or tt_cols are known, both altered, one or both <= 0
  1515.  *    -1   tt_rows and tt_cols are unknown and unaltered
  1516.  */
  1517.  
  1518. #ifndef NONAWS
  1519. extern int tt_rows, tt_cols;
  1520. #endif /* NONAWS */
  1521.  
  1522. static int
  1523. xttgwsiz() {
  1524.     char *p;
  1525.     int rows = 0, cols = 0;
  1526.     p = getenv("LINES");
  1527.     debug(F110,"xttgwsiz LINES",p,0);
  1528.     if (p) {
  1529.     rows = atol(p);
  1530.     if (rows > 0) {
  1531.         p = getenv("COLUMNS");
  1532.         debug(F110,"xttgwsiz COLUMNS",p,0);
  1533.         if (p) {
  1534.         cols = atol(p);
  1535.         if (cols > 0) {
  1536.             tt_rows = rows;
  1537.             tt_cols = cols;
  1538.             return(1);
  1539.         }
  1540.         return(0);
  1541.         }
  1542.     }
  1543.     }
  1544.     return(-1);
  1545. }
  1546.  
  1547. #ifdef TTLEBUF
  1548. VOID
  1549. le_init() {                /* LocalEchoInit() */
  1550.     int i;
  1551.     for (i = 0; i < LEBUFSIZ; i++)
  1552.       le_buf[i] = '\0';
  1553.     le_start = 0;
  1554.     le_end = 0;
  1555.     le_data = 0;
  1556. }
  1557.  
  1558. VOID
  1559. le_clean() {                /* LocalEchoCleanup() */
  1560.     le_init();
  1561.     return;
  1562. }
  1563.  
  1564. int
  1565. le_inbuf() {
  1566.     int rc = 0;
  1567.     if (le_start != le_end) {
  1568.     rc = (le_end -
  1569.           le_start +
  1570.           LEBUFSIZ) % LEBUFSIZ;
  1571.     }
  1572.     debug(F111,"le_inbuf","chars waiting",rc);
  1573.     return(rc);
  1574. }
  1575.  
  1576. int
  1577. #ifdef CK_ANSIC
  1578. le_putchar(CHAR ch)
  1579. #else
  1580. le_putchar(ch) CHAR ch;
  1581. #endif /* CK_ANSIC */
  1582. /* le_putchar */ {
  1583. #ifdef COMMENT
  1584.     /* In UNIX we do not have another thread taking chars out of the buffer */
  1585.     while ((le_start - le_end == 1) ||
  1586.             (le_start == 0 && le_end == LEBUFSIZ - 1)) {
  1587.     /* Buffer is full */
  1588.         debug(F111,"le_putchar","Buffer is Full",ch);
  1589.         ReleaseLocalEchoMutex() ;
  1590.         msleep(250);
  1591.         RequestLocalEchoMutex( SEM_INDEFINITE_WAIT ) ;
  1592.     }
  1593. #else
  1594.     if ((le_start - le_end + LEBUFSIZ)%LEBUFSIZ == 1) {
  1595.         debug(F110,"le_putchar","buffer is full",0);
  1596.         return(-1);
  1597.     }
  1598. #endif /* COMMENT */
  1599.     le_buf[le_end++] = ch;
  1600.     if (le_end == LEBUFSIZ)
  1601.       le_end = 0;
  1602.     le_data = 1;
  1603.     return(0);
  1604. }
  1605.  
  1606. int
  1607. #ifdef CK_ANSIC
  1608. le_puts(CHAR * s, int n)
  1609. #else
  1610. le_puts(s,n) CHAR * s; int n;
  1611. #endif /* CK_ANSIC */
  1612. /* le_puts */ {
  1613.     int rc = 0;
  1614.     int i = 0;
  1615.     CHAR * p = (CHAR *)"le_puts";
  1616.     hexdump(p,s,n);
  1617.     for (i = 0; i < n; i++)
  1618.       rc = le_putchar((char)s[i]);
  1619.     debug(F101,"le_puts","",rc);
  1620.     return(rc);
  1621. }
  1622.  
  1623. int
  1624. #ifdef CK_ANSIC
  1625. le_putstr(CHAR * s)
  1626. #else
  1627. le_putstr(s) CHAR * s;
  1628. #endif /* CK_ANSIC */
  1629. /* le_puts */ {
  1630.     CHAR * p;
  1631.     int rc = 0;
  1632.     p = (CHAR *)"le_putstr";
  1633.     hexdump(p,s,(int)strlen((char *)s));
  1634.     for (p = s; *p && !rc; p++)
  1635.       rc = le_putchar(*p);
  1636.     return(rc);
  1637. }
  1638.  
  1639. int
  1640. #ifdef CK_ANSIC
  1641. le_getchar(CHAR * pch)
  1642. #else /* CK_ANSIC */
  1643. le_getchar(pch) CHAR * pch;
  1644. #endif /* CK_ANSIC */
  1645. /* le_gatchar */ {
  1646.     int rc = 0;
  1647.     if (le_start != le_end) {
  1648.         *pch = le_buf[le_start];
  1649.         le_buf[le_start] = 0;
  1650.         le_start++;
  1651.  
  1652.         if (le_start == LEBUFSIZ)
  1653.           le_start = 0;
  1654.  
  1655.         if (le_start == le_end) {
  1656.             le_data = 0;
  1657.         }
  1658.         rc++;
  1659.     } else {
  1660.         *pch = 0;
  1661.     }
  1662.     return(rc);
  1663. }
  1664. #endif /* TTLEBUF */
  1665.  
  1666. #ifdef COMMENT
  1667. /*
  1668.   Some systems like OSF/1 use TIOCGSIZE instead of TIOCGWINSZ.
  1669.   But as far as I know, whenever TIOCGSIZE is defined, it is
  1670.   equated to TIOCGWINSZ.  For cases where this is not done, try this:
  1671. */
  1672. #ifndef TIOCGWINSZ
  1673. #ifdef TIOCGSIZE
  1674. #define TIOCGWINSZ TIOCGSIZE
  1675. #endif /* TIOCGSIZE */
  1676. #endif /* TIOCGWINSZ */
  1677. #endif /* COMMENT */
  1678.  
  1679. int
  1680. ttgwsiz() {
  1681.     int x = 0;
  1682. #ifndef NONAWS
  1683. #ifdef QNX
  1684. /*
  1685.   NOTE: TIOCGWSIZ works here too, but only in the 32-bit version.
  1686.   This code works for both the 16- and 32-bit versions.
  1687. */
  1688.     extern int dev_size(int, int, int, int *, int *);
  1689.     int r, c;
  1690.  
  1691.     if (dev_size(0, -1, -1, &r, &c) == 0) {
  1692.     debug(F101,"ttgwsiz QNX r","",r);
  1693.     debug(F101,"ttgwsiz QNX c","",c);
  1694.     tt_rows = r;
  1695.     tt_cols = c;
  1696.     return ((r > 0 && c > 0) ? 1 : 0);
  1697.     } else return(xttgwsiz());
  1698. #else /* QNX */
  1699. #ifdef TIOCGWINSZ
  1700.  
  1701. /* Note, this was M_UNIX, changed to XENIX to allow cross compilation... */
  1702. #ifdef XENIX                /* SCO UNIX 3.2v4.0 */
  1703. #include <sys/stream.h>            /* typedef mblk_t needed by ptem.h */
  1704. #include <sys/ptem.h>            /* for ttgwsiz() */
  1705. #endif /* XENIX */
  1706.  
  1707. #ifdef I386IX                /* Ditto for Interactive */
  1708. #include <sys/stream.h>
  1709. #include <sys/ptem.h>
  1710. #endif /* I386IX */
  1711.  
  1712. /* Note, the above might be needed for some other older SVR3 Intel makes... */
  1713.  
  1714.     struct winsize w;
  1715. #ifdef IKSD
  1716.     if (inserver)
  1717.       return(xttgwsiz());
  1718. #endif /* IKSD */
  1719.     x = ioctl(0, (int)TIOCGWINSZ, (char *)&w);
  1720.     debug(F101,"ttgwsiz TIOCGWINSZ","",x);
  1721.     if (x < 0) {
  1722.     return(xttgwsiz());
  1723.     } else if (w.ws_row > 0 && w.ws_col > 0) {
  1724.     tt_rows = w.ws_row;
  1725.     tt_cols = w.ws_col;
  1726.     debug(F101,"ttgwsiz tt_rows","",tt_rows);
  1727.     debug(F101,"ttgwsiz tt_cols","",tt_cols);
  1728.     return(1);
  1729.     } else {
  1730.     debug(F100,"ttgwsiz TIOCGWINSZ 00","",0);
  1731.     return(xttgwsiz());
  1732.     }
  1733. #else
  1734.     return(xttgwsiz());
  1735. #endif /* TIOCGWINSZ */
  1736. #endif /* QNX */
  1737. #endif /* NONAWS */
  1738. }
  1739.  
  1740. SIGTYP
  1741. sighup(foo) int foo; {            /* SIGHUP handler */
  1742.     backgrd = 1;
  1743.     debug(F100,"***************","",0);
  1744.     debug(F100,"SIGHUP received","",0);
  1745.     debug(F100,"***************","",0);
  1746.     doexit(BAD_EXIT,-1);
  1747.     /*NOTREACHED*/
  1748.     SIGRETURN;                /* Shut picky compilers up... */
  1749. }
  1750.  
  1751. #ifdef CK_SCO32V4
  1752. /* Exists but there is no prototype in the header files */
  1753. _PROTOTYP( char * ttyname, (int) );
  1754. #else
  1755. #ifdef SV68R3V6
  1756. _PROTOTYP( char * ttyname, (int) );
  1757. #else
  1758. #ifdef ultrix
  1759. _PROTOTYP( char * ttyname, (int) );
  1760. #else
  1761. #ifdef HPUX6
  1762. _PROTOTYP( char * ttyname, (int) );
  1763. #else
  1764. #ifdef HPUX5
  1765. _PROTOTYP( char * ttyname, (int) );
  1766. #else
  1767. #ifdef PS2AIX10
  1768. _PROTOTYP( char * ttyname, (int) );
  1769. #else
  1770. #ifdef BSD42
  1771. _PROTOTYP( char * ttyname, (int) );
  1772. #endif /* BSD42 */
  1773. #endif /* PS2AIX10 */
  1774. #endif /* HPUX5 */
  1775. #endif /* HPUX6 */
  1776. #endif /* ultrix */
  1777. #endif /* SV68R3V6 */
  1778. #endif /* CK_SCO32V4 */
  1779.  
  1780. #ifndef SIGUSR1                /* User-defined signals */
  1781. #define SIGUSR1 30
  1782. #endif /* SIGUSR1 */
  1783.  
  1784. #ifndef SIGUSR2
  1785. #define SIGUSR2 31
  1786. #endif /* SIGUSR2 */
  1787.  
  1788. /*
  1789.   ignorsigs() sets certain signals to SIG_IGN.  But when a signal is
  1790.   ignored, it remains ignored across exec(), so we have to restore these
  1791.   signals before exec(), which is the purpose of restorsigs().
  1792. */
  1793. static VOID
  1794. ignorsigs() {                /* Ignore these signals */
  1795.     savquit = signal(SIGQUIT,SIG_IGN);    /* Ignore Quit signal */
  1796.  
  1797. #ifdef SIGDANGER            /* Ignore danger signals */
  1798. /*
  1799.   This signal is sent when the system is low on swap space.  Processes
  1800.   that don't handle it are candidates for termination.  If swap space doesn't
  1801.   clear out enough, we still might be terminated via kill() -- nothing we can
  1802.   do about that!  Conceivably, this could be improved by installing a real
  1803.   signal handler that warns the user, but that would be pretty complicated,
  1804.   since we are not always in control of the screen -- e.g. during remote-mode
  1805.   file transfer.
  1806. */
  1807.     savdanger = signal(SIGDANGER,SIG_IGN); /* e.g. in AIX */
  1808. #endif /* SIGDANGER */
  1809. #ifdef SIGPIPE
  1810. /*
  1811.   This one comes when a TCP/IP connection is broken by the remote.
  1812.   We prefer to catch this situation by examining error codes from write().
  1813. */
  1814.     savpipe = signal(SIGPIPE,SIG_IGN);
  1815. #endif /* SIGPIPE */
  1816.     savusr1 = signal(SIGUSR1,SIG_IGN);    /* Ignore user-defined signals */
  1817.     savusr2 = signal(SIGUSR2,SIG_IGN);
  1818. }
  1819.  
  1820. VOID
  1821. restorsigs() {                /* Restore these signals */
  1822.     (VOID) signal(SIGQUIT,savquit);    /* (used in ckufio.c) */
  1823. #ifdef SIGDANGER
  1824.     (VOID) signal(SIGDANGER,savdanger);
  1825. #endif /* SIGDANGER */
  1826. #ifdef SIGPIPE
  1827.     (VOID) signal(SIGPIPE,savpipe);
  1828. #endif /* SIGPIPE */
  1829.     (VOID) signal(SIGUSR1,savusr1);
  1830.     (VOID) signal(SIGUSR2,savusr2);
  1831. }
  1832.  
  1833. int
  1834. sysinit() {
  1835.     int x;
  1836.     char * s;
  1837. #ifdef CK_UTSNAME
  1838.     struct utsname name;
  1839. #endif /* CK_UTSNAME */
  1840.  
  1841.     extern char startupdir[];
  1842. /*
  1843.   BEFORE ANYTHING ELSE: Initialize the setuid package.
  1844.   Change to the user's real user and group ID.
  1845.   If this can't be done, don't run at all.
  1846. */
  1847.     debug(F100,"sysinit calling priv_ini","",0);
  1848.     if (x = priv_ini()) {
  1849.     if (x & 1) fprintf(stderr,"Fatal: setuid failure.\n");
  1850.     if (x & 2) fprintf(stderr,"Fatal: setgid failure.\n");
  1851.     if (x & 4) fprintf(stderr,"Fatal: C-Kermit setuid to root!\n");
  1852.     exit(1);
  1853.     }
  1854.     signal(SIGINT,SIG_IGN);        /* Ignore interrupts at first */
  1855.     signal(SIGHUP,sighup);        /* Catch SIGHUP */
  1856.  
  1857. #ifndef NOJC
  1858. /*
  1859.   Get the initial job control state.
  1860.   If it is SIG_IGN, that means the shell does not support job control,
  1861.   and so we'd better not suspend ourselves.
  1862. */
  1863. #ifdef SIGTSTP
  1864.     jchdlr = signal(SIGTSTP,SIG_IGN);
  1865.     if (jchdlr == SIG_IGN) {
  1866.     jcshell = 0;
  1867.     debug(F100,"sysinit jchdlr: SIG_IGN","",0);
  1868.     } else if (jchdlr == SIG_DFL) {
  1869.     debug(F100,"sysinit jchdlr: SIG_DFL","",0);
  1870.     jcshell = 1;
  1871.     } else {
  1872.     debug(F100,"sysinit jchdlr: other","",0);
  1873.     jcshell = 3;
  1874.     }
  1875.     (VOID) signal(SIGTSTP,jchdlr);    /* Put it back... */
  1876. #endif /* SIGTSTP */
  1877. #endif /* NOJC */
  1878.  
  1879.     conbgt(0);                /* See if we're in the background */
  1880.     congm();                /* Get console modes */
  1881.  
  1882.     (VOID) signal(SIGALRM,SIG_IGN);    /* Ignore alarms */
  1883.  
  1884.     ignorsigs();            /* Ignore some other signals */
  1885.  
  1886. #ifdef F_SETFL
  1887.     iniflags = fcntl(0,F_GETFL,0);    /* Get stdin flags */
  1888. #endif /* F_SETFL */
  1889.  
  1890. #ifdef ultrix
  1891.     gtty(0,&vanilla);            /* Get sgtty info */
  1892. #else
  1893. #ifdef AUX
  1894.     set42sig();                /* Don't ask! (hakanson@cs.orst.edu) */
  1895. #endif /* AUX */
  1896. #endif /* ultrix */
  1897. /*
  1898.   Warning: on some UNIX systems (SVR4?), ttyname() reportedly opens /dev but
  1899.   never closes it.  If it is called often enough, we run out of file
  1900.   descriptors and subsequent open()'s of other devices or files can fail.
  1901. */
  1902.     s = NULL;
  1903. #ifndef MINIX
  1904.     if (isatty(0))            /* Name of controlling terminal */
  1905.       s = ttyname(0);
  1906.     else if (isatty(1))
  1907.       s = ttyname(1);
  1908.     else if (isatty(2))
  1909.       s = ttyname(2);
  1910.     debug(F110,"sysinit ttyname(0)",s,0);
  1911. #endif /* MINIX */
  1912.  
  1913. #ifdef BEOS
  1914.     if (!dftty)
  1915.       makestr(&dftty,s);
  1916. #endif /* BEOS */
  1917.  
  1918.     if (s)
  1919.       ckstrncpy((char *)cttnam,s,DEVNAMLEN+1);
  1920. #ifdef SVORPOSIX
  1921.     if (!cttnam[0])
  1922.       ctermid(cttnam);
  1923. #endif /* SVORPOSIX */
  1924.     if (!cttnam[0])
  1925.       ckstrncpy((char *)cttnam,dftty,DEVNAMLEN+1);
  1926.     debug(F110,"sysinit CTTNAM",CTTNAM,0);
  1927.     debug(F110,"sysinit cttnam",cttnam,0);
  1928.  
  1929.     ttgwsiz();                /* Get window (screen) dimensions. */
  1930.  
  1931. #ifdef _SC_OPEN_MAX
  1932.     ckmaxfiles = sysconf(_SC_OPEN_MAX);
  1933. #endif /* _SC_OPEN_MAX */
  1934.  
  1935. #ifdef Plan9
  1936.     if (!backgrd) {
  1937.         consctlfd = open("/dev/consctl", O_WRONLY);
  1938.         /*noisefd = open("/dev/noise", O_WRONLY)*/
  1939.     }
  1940.     ckxech = 1;
  1941. #endif /* Plan9 */
  1942.  
  1943. #ifdef CK_UTSNAME
  1944.     if (uname(&name) > -1) {
  1945.     ckstrncpy(unm_mch,name.machine,CK_SYSNMLN);
  1946.     ckstrncpy(unm_nam,name.sysname,CK_SYSNMLN);
  1947.     ckstrncpy(unm_rel,name.release,CK_SYSNMLN);
  1948.     ckstrncpy(unm_ver,name.version,CK_SYSNMLN);
  1949. #ifdef DEBUG
  1950.     if (deblog) {
  1951.         debug(F110,"sysinit uname machine",unm_mch,0);
  1952.         debug(F110,"sysinit uname sysname",unm_nam,0);
  1953.         debug(F110,"sysinit uname release",unm_rel,0);
  1954.         debug(F110,"sysinit uname version",unm_ver,0);
  1955.     }
  1956. #endif /* DEBUG */
  1957.  
  1958. #ifdef HPUX9PLUS
  1959.     if (name.machine[5] == '8')
  1960.       hpis800 = 1;
  1961.     else
  1962.       hpis800 = 0;
  1963.     debug(F101,"sysinit hpis800","",hpis800);
  1964. #endif /* HPUX9PLUS */
  1965.     }
  1966. #endif /* CK_UTSNAME */
  1967.  
  1968. #ifdef CK_ENVIRONMENT
  1969.     {
  1970.     extern char tn_env_acct[], tn_env_disp[], tn_env_job[],
  1971.     tn_env_prnt[], tn_env_sys[], uidbuf[];
  1972.         extern char * whoami();
  1973.     char *p;
  1974. #ifdef CKSENDUID
  1975.         uidbuf[0] = '\0';
  1976. #ifdef IKSD
  1977.         if (!inserver) {
  1978. #endif /* IKSD */
  1979.             p = getenv("USER");
  1980.             debug(F110,"sysinit uidbuf from USER",uidbuf,0);
  1981.             if (!p) {
  1982.                 p = getenv("LOGNAME");
  1983.                 debug(F110,"sysinit uidbuf from LOGNAME",uidbuf,0);
  1984.             }
  1985.             if (!p) {
  1986.                 p = whoami();
  1987.                 debug(F110,"sysinit uidbuf from whoami()",uidbuf,0);
  1988.             }
  1989.             if (p)
  1990.           ckstrncpy(uidbuf,p,UIDBUFLEN);
  1991. #ifdef IKSD
  1992.         }
  1993. #endif /* IKSD */
  1994.     debug(F110,"sysinit final uidbuf",uidbuf,0);
  1995. #endif /* CKSENDUID */
  1996.  
  1997.     if (p = getenv("JOB")) ckstrncpy(tn_env_job,p,63);
  1998.     if (p = getenv("ACCT")) ckstrncpy(tn_env_acct,p,63);
  1999.     if (p = getenv("PRINTER")) ckstrncpy(tn_env_prnt,p,63);
  2000.     if (p = getenv("DISPLAY")) ckstrncpy(tn_env_disp,p,63);
  2001. #ifdef aegis
  2002.     strcpy(tn_env_sys,"Aegis");
  2003. #else
  2004. #ifdef Plan9
  2005.     strcpy(tn_env_sys,"Plan9");
  2006. #else
  2007.     strcpy(tn_env_sys,"UNIX");
  2008. #endif /* Plan9 */
  2009. #endif /* aegis */
  2010.     }
  2011. #endif /* CK_ENVIRONMENT */
  2012. #ifdef CK_SNDLOC
  2013.     {
  2014.     extern char * tn_loc;
  2015.     char *p;
  2016.     if (p = getenv("LOCATION"))
  2017.       if (tn_loc = (char *)malloc((int)strlen(p)+1))
  2018.         strcpy(tn_loc,p);
  2019.     }
  2020. #endif /* CK_SNDLOC */
  2021.  
  2022.     ckstrncpy(startupdir, zgtdir(), CKMAXPATH);
  2023.     startupdir[CKMAXPATH] = '\0';
  2024.     x = strlen(startupdir);
  2025.     if (x <= 0) {
  2026.     startupdir[0] = '/';
  2027.     startupdir[1] = '\0';
  2028.     } else if (startupdir[x-1] != '/') {
  2029.     startupdir[x] = '/';
  2030.     startupdir[x+1] = '\0';
  2031.     }
  2032.     debug(F110,"sysinit startupdir",startupdir,0);
  2033. #ifdef TTLEBUF
  2034.     le_init();
  2035. #endif /* TTLEBUF */
  2036.     return(0);
  2037. }
  2038.  
  2039. /*  S Y S C L E A N U P  --  System-dependent program cleanup.  */
  2040.  
  2041. int
  2042. syscleanup() {
  2043. #ifdef F_SETFL
  2044.     if (iniflags > -1)
  2045.       fcntl(0,F_SETFL,iniflags);    /* Restore stdin flags */
  2046. #endif /* F_SETFL */
  2047. #ifdef ultrix
  2048.     stty(0,&vanilla);                   /* Get sgtty info */
  2049. #endif /* ultrix */
  2050. #ifdef NETCMD
  2051.     if (ttpid) kill(ttpid,9);
  2052. #endif /* NETCMD */
  2053.     return(0);
  2054. }
  2055.  
  2056. /*  T T O P E N  --  Open a tty for exclusive access.  */
  2057.  
  2058. /*
  2059.   Call with:
  2060.     ttname: character string - device name or network host name.
  2061.     lcl:
  2062.   If called with lcl < 0, sets value of lcl as follows:
  2063.   0: the terminal named by ttname is the job's controlling terminal.
  2064.   1: the terminal named by ttname is not the job's controlling terminal.
  2065.   But watch out: if a line is already open, or if requested line can't
  2066.   be opened, then lcl remains (and is returned as) -1.
  2067.     modem:
  2068.   Less than zero: ttname is a network host name.
  2069.   Zero or greater: ttname is a terminal device name.
  2070.   Zero means a local connection (don't use modem signals).
  2071.   Positive means use modem signals.
  2072.    timo:
  2073.   0 = no timer.
  2074.   nonzero = number of seconds to wait for open() to return before timing out.
  2075.  
  2076.   Returns:
  2077.     0 on success
  2078.    -5 if device is in use
  2079.    -4 if access to device is denied
  2080.    -3 if access to lock directory denied
  2081.    -2 upon timeout waiting for device to open
  2082.    -1 on other error
  2083. */
  2084. static int ttotmo = 0;            /* Timeout flag */
  2085. /* Flag kept here to avoid being clobbered by longjmp.  */
  2086.  
  2087. int
  2088. ttopen(ttname,lcl,modem,timo) char *ttname; int *lcl, modem, timo; {
  2089.  
  2090. #ifdef BSD44
  2091. #define ctermid(x) strcpy(x,"")
  2092. #else
  2093. #ifdef SVORPOSIX
  2094. #ifndef CIE
  2095.     extern char *ctermid();        /* Wish they all had this! */
  2096. #else                    /* CIE Regulus */
  2097. #define ctermid(x) strcpy(x,"")
  2098. #endif /* CIE */
  2099. #endif /* SVORPOSIX */
  2100. #endif /* BSD44 */
  2101.  
  2102. #ifdef ultrix
  2103.     int temp = 0;
  2104. #endif /* ultrix */
  2105.  
  2106.     char *x;                /* Worker string pointer */
  2107.     int y;
  2108.  
  2109. #ifndef pdp11
  2110. #define NAMEFD     /* Feature to allow name to be an open file descriptor */
  2111. #endif /* pdp11 */
  2112.  
  2113. #ifdef NAMEFD
  2114.     char *p;
  2115.     debug(F101,"ttopen telnetfd","",telnetfd);
  2116. #endif /* NAMEFD */
  2117.  
  2118.     debug(F111,"ttopen entry modem",ttname,modem);
  2119.     debug(F101," ttyfd","",ttyfd);
  2120.     debug(F101," lcl","",*lcl);
  2121.  
  2122. #ifdef MAXNAMLEN
  2123.     debug(F100,"ttopen MAXNAMLEN defined","",0);
  2124. #else
  2125.     debug(F100,"ttopen MAXNAMLEN *NOT* defined","",0);
  2126. #endif
  2127.  
  2128. #ifdef BSD4
  2129.     debug(F100,"ttopen BSD4 defined","",0);
  2130. #else
  2131.     debug(F100,"ttopen BSD4 *NOT* defined","",0);
  2132. #endif /* BSD4 */
  2133.  
  2134. #ifdef BSD42
  2135.     debug(F100,"ttopen BSD42 defined","",0);
  2136. #else
  2137.     debug(F100,"ttopen BSD42 *NOT* defined","",0);
  2138. #endif /* BSD42 */
  2139.  
  2140. #ifdef MYREAD
  2141.     debug(F100,"ttopen MYREAD defined","",0);
  2142. #else
  2143.     debug(F100,"ttopen MYREAD *NOT* defined","",0);
  2144. #endif /* MYREAD */
  2145.  
  2146.     ttpmsk = 0xff;
  2147.     lockpid[0] = '\0';
  2148.  
  2149.     if (ttyfd > -1) {            /* if device already opened */
  2150.     debug(F110,"ttopen ttname",ttname,0);
  2151.     debug(F110,"ttopen ttnmsv",ttnmsv,0);
  2152.         if (strncmp(ttname,ttnmsv,DEVNAMLEN)) /* are new & old names equal? */
  2153.           ttclos(ttyfd);        /* no, close old ttname, open new */
  2154.         else                 /* else same, ignore this call, */
  2155.       return(0);            /* and return. */
  2156.     }
  2157.     wasclosed = 0;
  2158.     ttpipe = 0;                /* Assume it's not a pipe */
  2159.     ttpty = 0;
  2160.  
  2161. #ifdef    NETCONN
  2162.     if (modem < 0) {            /* modem < 0 = special code for net */
  2163.     int x;
  2164.     ttmdm = modem;
  2165.     modem = -modem;            /* Positive network type number */
  2166.     fdflag = 0;            /* Stdio not redirected. */
  2167.     netconn = 1;            /* And it's a network connection */
  2168.     debug(F111,"ttopen net",ttname,modem);
  2169. #ifdef NAMEFD
  2170.     for (p = ttname; isdigit(*p); p++) ; /* Check for all digits */
  2171.      if (*p == '\0' && (telnetfd || x25fd)) { /* Avoid X.121 addresses */
  2172.         ttyfd = atoi(ttname);    /* Is there a way to test it's open? */
  2173.         ttfdflg = 1;        /* We got an open file descriptor */
  2174.         debug(F111,"ttopen got open network fd",ttname,ttyfd);
  2175.         ckstrncpy(ttnmsv,ttname,DEVNAMLEN); /* Remember the "name". */
  2176.         x = 1;            /* Return code is "good". */
  2177.         if (telnetfd) {
  2178.         ttnet = NET_TCPB;
  2179.         if (ttnproto != NP_TCPRAW)
  2180.           ttnproto = NP_TELNET;
  2181. #ifdef SUNX25
  2182.         } else if (x25fd) {
  2183.         ttnet = NET_SX25;
  2184.         ttnproto = NP_NONE;
  2185. #endif /* SUNX25 */
  2186.         }
  2187.     } else {            /* Host name or address given */
  2188. #ifdef NETPTY
  2189.         if (modem == NET_PTY) {
  2190.         int x;
  2191.         if (nopush) {
  2192.             debug(F100,"ttopen PTY: nopush","",0);
  2193.             return(-1);
  2194.         }
  2195.                 ttnet = NET_PTY;
  2196.         ttnproto = NP_NONE;
  2197.                 netconn = 1;            /* but we don't use network i/o */
  2198.                 ttpty = 1;
  2199.                 debug(F110,"ttopen PTY",ttname,0);
  2200.         x = do_pty(ttname);
  2201.         if (x > -1) {
  2202.             ckstrncpy(ttnmsv,ttname,DEVNAMLEN);
  2203.             xlocal = *lcl = 1;    /* It's local */
  2204.         } else {
  2205.             ttpty = 0;
  2206.             netconn = 0;
  2207.         }
  2208.         return(x);
  2209.         }
  2210. #endif /* NETPTY */
  2211. #ifdef NETCMD
  2212. /*
  2213.   dup2() is not available on older System V platforms like AT&T 3Bx.  For
  2214.   those systems we punt by not defining NETCMD, but we might be able to do
  2215.   better -- see workarounds for this problem in ckufio.c (search for dup2).
  2216. */
  2217.         if (modem == NET_CMD) {
  2218.         if (nopush) {
  2219.             debug(F100,"ttopen pipe: nopush","",0);
  2220.             return(-1);
  2221.         }
  2222.         if (pipe(pipe0) || pipe(pipe1)) {
  2223.             perror("Pipe error");
  2224.             return(-1);
  2225.         }
  2226.         ttpid = fork();        /* Make a fork */
  2227.  
  2228.         switch (ttpid) {
  2229.           case -1:        /* Error making fork */
  2230.             close(pipe0[0]);
  2231.             close(pipe0[1]);
  2232.             close(pipe1[0]);
  2233.             close(pipe1[1]);
  2234.             perror("Fork error");
  2235.             return(-1);
  2236.           case 0:        /* Child. */
  2237.             close(pipe0[0]);
  2238.             close(pipe1[1]);
  2239.             dup2(pipe0[1], 1);
  2240.             close(pipe0[1]);
  2241.             dup2(pipe1[0], 0);
  2242.             close(pipe1[0]);
  2243.             system(ttname);
  2244.             _exit(0);
  2245.           default:        /* Parent */
  2246.             close(pipe0[1]);
  2247.             close(pipe1[0]);
  2248.             fdin = pipe0[0];    /* Read from pipe */
  2249.             fdout = pipe1[1];    /* Write to pipe */
  2250.             ttout = fdopen(fdout,"w"); /* Get stream so we can */
  2251.             if (!ttout) {    /* make it unbuffered. */
  2252.             perror("fdopen failure");
  2253.             return(-1);
  2254.             }
  2255.             setbuf(ttout,NULL);
  2256.             ckstrncpy(ttnmsv,ttname,DEVNAMLEN);
  2257.             xlocal = *lcl = 1;    /* It's local */
  2258.             netconn = 1;    /* Call it a network connection */
  2259.             ttmdm = modem;    /* Remember network type */
  2260.             ttyfd = fdin;
  2261.             ttpipe = 1;
  2262.             return(0);
  2263.         }
  2264.         }
  2265. #endif /* NETCMD */
  2266. #endif /* NAMEFD */
  2267.         x = netopen(ttname, lcl, modem); /* (see ckcnet.h) */
  2268.         if (x > -1) {
  2269.         ckstrncpy(ttnmsv,ttname,DEVNAMLEN);
  2270.         } else netconn = 0;
  2271. #ifdef NAMEFD
  2272.     }
  2273. #endif /* NAMEFD */
  2274.  
  2275. #ifdef sony_news            /* Sony NEWS */
  2276.     if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) { /* Get Kanji mode */
  2277.         perror("ttopen error getting Kanji mode (network)");
  2278.         debug(F111,"ttopen error getting Kanji mode","network",0);
  2279.         km_ext = -1;        /* Make sure this stays undefined. */
  2280.     }
  2281. #endif /* sony_news */
  2282.  
  2283.     xlocal = *lcl = 1;        /* Network connections are local. */
  2284.     debug(F101,"ttopen net x","",x);
  2285. #ifdef COMMENT
  2286. /* Let netopen() do this */
  2287.     if (x > -1 && !x25fd)
  2288.       x = tn_ini();            /* Initialize TELNET protocol */
  2289. #endif /* COMMENT */
  2290.     return(x);
  2291.     } else {                /* Terminal device */
  2292. #endif    /* NETCONN */
  2293.  
  2294. #ifdef NAMEFD
  2295. /*
  2296.   This code lets you give Kermit an open file descriptor for a serial
  2297.   communication device, rather than a device name.  Kermit assumes that the
  2298.   line is already open, locked, conditioned with the right parameters, etc.
  2299. */
  2300.     for (p = ttname; isdigit(*p); p++) ; /* Check for all digits */
  2301.     if (*p == '\0') {
  2302.         ttyfd = atoi(ttname);    /* Is there a way to test it's open? */
  2303.         debug(F111,"ttopen got open fd",ttname,ttyfd);
  2304.         ckstrncpy(ttnmsv,ttname,DEVNAMLEN); /* Remember the "name". */
  2305.         if (ttyfd == 0)        /* If it's stdio... */
  2306.           xlocal = *lcl = 0;    /* we're in remote mode */
  2307.         else            /* otherwise */
  2308.           xlocal = *lcl = 1;    /* local mode. */
  2309.         netconn = 0;        /* Assume it's not a network. */
  2310.         tvtflg = 0;            /* Might need to initialize modes. */
  2311.         ttmdm = modem;        /* Remember modem type. */
  2312.         fdflag = 0;            /* Stdio not redirected. */
  2313.         ttfdflg = 1;        /* Flag we were opened this way. */
  2314.  
  2315. #ifdef sony_news            /* Sony NEWS */
  2316.         /* Get device Kanji mode */
  2317.         if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) {
  2318.         perror("ttopen error getting Kanji mode");
  2319.         debug(F101,"ttopen error getting Kanji mode","",0);
  2320.         km_ext = -1;        /* Make sure this stays undefined. */
  2321.         }
  2322. #endif /* sony_news */
  2323.         return(0);            /* Return success */
  2324.     }
  2325. #endif /* NAMEFD */
  2326. #ifdef NETCONN
  2327.     }
  2328. #endif /* NETCONN */
  2329.  
  2330. /* Here we have to open a serial device of the given name. */
  2331.  
  2332.     netconn = 0;            /* So it's not a network connection */
  2333.     occt = signal(SIGINT, cctrap);    /* Set Control-C trap, save old one */
  2334.     sigint_ign = 0;
  2335.  
  2336.     tvtflg = 0;            /* Flag for use by ttvt(). */
  2337.                 /* 0 = ttvt not called yet for this device */
  2338.  
  2339.     fdflag = (!isatty(0) || !isatty(1)); /* Flag for stdio redirected */
  2340.     debug(F101,"ttopen fdflag","",fdflag);
  2341.  
  2342.     ttmdm = modem;                      /* Make this available to other fns */
  2343.     xlocal = *lcl;                      /* Make this available to other fns */
  2344.  
  2345. /* Code for handling bidirectional tty lines goes here. */
  2346. /* Use specified method for turning off logins and suppressing getty. */
  2347.  
  2348. #ifdef ACUCNTRL
  2349.     /* Should put call to priv_on() here, but that would be very risky! */
  2350.     acucntrl("disable",ttname);         /* acucntrl() program. */
  2351.     /* and priv_off() here... */
  2352. #else
  2353. #ifdef ATT7300
  2354.     if ((attmodem & DOGETY) == 0)       /* offgetty() program. */
  2355.       attmodem |= offgetty(ttname);    /* Remember response.  */
  2356. #endif /* ATT7300 */
  2357. #endif /* ACUCNTRL */
  2358. /*
  2359.  In the following section, we open the tty device for read/write.
  2360.  If a modem has been specified via "set modem" prior to "set line"
  2361.  then the O_NDELAY parameter is used in the open, provided this symbol
  2362.  is defined (e.g. in fcntl.h), so that the program does not hang waiting
  2363.  for carrier (which in most cases won't be present because a connection
  2364.  has not been dialed yet).  O_NDELAY is removed later on in ttopen().  It
  2365.  would make more sense to first determine if the line is local before
  2366.  doing this, but because ttyname() requires a file descriptor, we have
  2367.  to open it first.  See do_open().
  2368.  
  2369.  Now open the device using the desired treatment of carrier.
  2370.  If carrier is REQUIRED, then open could hang forever, so an optional
  2371.  timer is provided.  If carrier is not required, the timer should never
  2372.  go off, and should do no harm...
  2373. */
  2374.     ttotmo = 0;                /* Flag no timeout */
  2375.     debug(F101,"ttopen timo","",timo);
  2376.     debug(F101,"ttopen xlocal","",xlocal);
  2377.     if (timo > 0) {
  2378.     int xx;
  2379.     saval = signal(SIGALRM,timerh);    /* Timed, set up timer. */
  2380.     xx = alarm(timo);        /* Timed open() */
  2381.     debug(F101,"ttopen alarm","",xx);
  2382.     if (
  2383. #ifdef CK_POSIX_SIG
  2384.         sigsetjmp(sjbuf,1)
  2385. #else
  2386.         setjmp(sjbuf)
  2387. #endif /* CK_POSIX_SIG */
  2388.         ) {
  2389.         ttotmo = 1;            /* Flag timeout. */
  2390.     } else ttyfd = do_open(ttname);
  2391.     ttimoff();
  2392.     debug(F111,"ttopen","modem",modem);
  2393.     debug(F101,"ttopen ttyfd","",ttyfd);
  2394.     debug(F101,"ttopen alarm return","",ttotmo);
  2395.     } else {
  2396.     errno = 0;
  2397.     ttyfd = do_open(ttname);
  2398.     }
  2399.     debug(F111,"ttopen ttyfd",ttname,ttyfd);
  2400.     if (ttyfd < 0) {            /* If couldn't open, fail. */
  2401.     debug(F101,"ttopen errno","",errno);
  2402.     if (errno > 0 && !quiet)
  2403.       perror(ttname);        /* Print message */
  2404.  
  2405. #ifdef ATT7300
  2406.     if (attmodem & DOGETY)        /* was getty(1m) running before us? */
  2407.       ongetty(ttnmsv);        /* yes, restart on tty line */
  2408.     attmodem &= ~DOGETY;        /* no phone in use, getty restored */
  2409. #else
  2410. #ifdef ACUCNTRL
  2411.         /* Should put call to priv_on() here, but that would be risky! */
  2412.     acucntrl("enable",ttname);    /* acucntrl() program. */
  2413.     /* and priv_off() here... */
  2414. #endif /* ACUNTRL */
  2415. #endif /* ATT7300 */
  2416.  
  2417.     signal(SIGINT,occt);        /* Put old Ctrl-C trap back. */
  2418.     if (errno == EACCES) {        /* Device is protected against user */
  2419.         debug(F110,"ttopen EACCESS",ttname,0); /* Return -4 */
  2420.         return(-4);
  2421.     } else return(ttotmo ? -2 : -1); /* Otherwise -2 if timeout, or -1 */
  2422.     }
  2423.  
  2424. #ifdef Plan9
  2425.     /* take this opportunity to open the control channel */
  2426.     if (p9openttyctl(ttname) < 0)
  2427. #else
  2428.     /* Make sure it's a real tty. */
  2429.     if (!isatty(ttyfd) && strcmp(ttname,"/dev/null"))
  2430. #endif /* Plan9 */
  2431.       {
  2432.     fprintf(stderr,"%s is not a terminal device\n",ttname);
  2433.     debug(F111,"ttopen not a tty",ttname,errno);
  2434.     close(ttyfd);
  2435.     ttyfd = -1;
  2436.     wasclosed = 1;
  2437.     signal(SIGINT,occt);
  2438.     return(-1);
  2439.     }
  2440.  
  2441. #ifdef aegis
  2442.     /* Apollo C runtime claims that console pads are tty devices, which
  2443.      * is reasonable, but they aren't any good for packet transfer. */
  2444.     ios_$inq_type_uid((short)ttyfd, ttyuid, st);
  2445.     if (st.all != status_$ok) {
  2446.         fprintf(stderr, "problem getting tty object type: ");
  2447.         error_$print(st);
  2448.     } else if (ttyuid != sio_$uid) { /* reject non-SIO lines */
  2449.         close(ttyfd); ttyfd = -1;
  2450.         wasclosed = 1;
  2451.         errno = ENOTTY; perror(ttname);
  2452.         signal(SIGINT,occt);
  2453.         return(-1);
  2454.     }
  2455. #endif /* aegis */
  2456.  
  2457.     sigint_ign = (occt == SIG_IGN) ? 1 : 0;
  2458.  
  2459.     ckstrncpy(ttnmsv,ttname,DEVNAMLEN);    /* Keep copy of name locally. */
  2460.  
  2461. /* Caller wants us to figure out if line is controlling tty */
  2462.  
  2463.     if (*lcl < 0) {
  2464.         if (strcmp(ttname,CTTNAM) == 0) { /* "/dev/tty" always remote */
  2465.             xlocal = 0;
  2466.         debug(F111,"ttopen ttname=CTTNAM",ttname,xlocal);
  2467.         } else if (strcmp(ttname,cttnam) == 0) {
  2468.             xlocal = 0;
  2469.         debug(F111,"ttopen ttname=cttnam",ttname,xlocal);
  2470.     } else if (cttnam[0]) {
  2471. #ifdef BEBOX_DR7
  2472.             x = ttnmsv;            /* ttyname() is broken */
  2473. #else
  2474.             x = ttyname(ttyfd);         /* Get real name of ttname. */
  2475. #endif /* BEBOX_DR7 */
  2476.         if (!x) x = "";
  2477.         if (*x)
  2478.           xlocal = ((strncmp(x,cttnam,DEVNAMLEN) == 0) ? 0 : 1);
  2479.         else
  2480.           xlocal = 1;
  2481.             debug(F111,"ttopen ttyname(ttyfd) xlocal",x,xlocal);
  2482.         }
  2483.     }
  2484.  
  2485. #ifndef NOFDZERO
  2486. /* Note, the following code was added so that Unix "idle-line" snoopers */
  2487. /* would not think Kermit was idle when it was transferring files, and */
  2488. /* maybe log people out. */
  2489.     if (xlocal == 0) {            /* Remote mode */
  2490.     if (fdflag == 0) {        /* Standard i/o is not redirected */
  2491.         debug(F100,"ttopen setting ttyfd = 0","",0);
  2492. #ifdef LYNXOS
  2493.         /* On Lynx OS, fd 0 is open for read only. */
  2494.         dup2(ttyfd,0);
  2495. #endif /* LYNXOS */
  2496.         close(ttyfd);        /* Use file descriptor 0 */
  2497.         ttyfd = 0;
  2498.     } else {            /* Standard i/o is redirected */
  2499.         debug(F101,"ttopen stdio redirected","",ttyfd);
  2500.     }
  2501.     }
  2502. #endif /* NOFDZERO */
  2503.  
  2504. /* Now check if line is locked -- if so fail, else lock for ourselves */
  2505. /* Note: After having done this, don't forget to delete the lock if you */
  2506. /* leave ttopen() with an error condition. */
  2507.  
  2508.     lkf = 0;                            /* Check lock */
  2509.     if (xlocal > 0) {
  2510.     int xx; int xpid;
  2511.         if ((xx = ttlock(ttname)) < 0) { /* Can't lock it. */
  2512.             debug(F111,"ttopen ttlock fails",ttname,xx);
  2513.         /* WARNING - This close() can hang if tty is an empty socket... */
  2514.             close(ttyfd);        /* Close the device. */
  2515.         ttyfd = -1;            /* Erase its file descriptor. */
  2516.         wasclosed = 1;
  2517.         signal(SIGINT,occt);    /* Put old SIGINT back. */
  2518.         sigint_ign = (occt == SIG_IGN) ? 1 : 0;
  2519.         if (xx == -2) {        /* If lockfile says device in use, */
  2520. #ifndef NOUUCP
  2521.         debug(F111,"ttopen reading lockfile pid",flfnam,xx);
  2522.         xpid = ttrpid(flfnam);    /* Try to read pid from lockfile */
  2523.         if (xpid > -1) {    /* If we got a pid */
  2524.             printf("Locked by process %d\n",xpid); /* tell them. */
  2525.             sprintf(lockpid,"%d",xpid);    /* Record it too */
  2526.             debug(F110,"ttopen lockpid",lockpid,0);
  2527.         } else if (*flfnam) {
  2528.             char *p = malloc(280); /* Print a directory listing. */
  2529. /*
  2530.   Note: priv_on() won't help here, because we do not pass privs along to
  2531.   to inferior processes, in this case ls.  So if the real user does not have
  2532.   directory-listing access to the lockfile directory, this will result in
  2533.   something like "not found".  That's why we try this only as a last resort.
  2534. */
  2535.             if (p) {        /* If we got the space... */
  2536.             extern char *DIRCMD;
  2537.             sprintf(p,"%s %s",DIRCMD,flfnam);
  2538.             zsyscmd(p);    /* Get listing. */
  2539.             if (p) {    /* free the space */
  2540.                 free(p);
  2541.                 p = NULL;
  2542.             }
  2543.             }
  2544.         }
  2545. #endif /* NOUUCP */
  2546.         return(-5);        /* Code for device in use */
  2547.         } else return(-3);        /* Access denied */
  2548.         } else lkf = 1;
  2549.     }
  2550.  
  2551. /* Got the line, now set the desired value for local. */
  2552.  
  2553.     if (*lcl != 0) *lcl = xlocal;
  2554.  
  2555. /* Some special stuff for v7... */
  2556.  
  2557. #ifdef  V7
  2558. #ifndef MINIX
  2559.     if (kmem[TTY] < 0) {        /*  If open, then skip this.  */
  2560.     qaddr[TTY] = initrawq(ttyfd);   /* Init the queue. */
  2561.     if ((kmem[TTY] = open("/dev/kmem", 0)) < 0) {
  2562.         fprintf(stderr, "Can't read /dev/kmem in ttopen.\n");
  2563.         perror("/dev/kmem");
  2564.         exit(1);
  2565.     }
  2566.     }
  2567. #endif /* !MINIX */
  2568. #endif /* V7 */
  2569.  
  2570. /* No failure returns after this point */
  2571.  
  2572. #ifdef ultrix
  2573.     ioctl(ttyfd, TIOCMODEM, &temp);
  2574. #ifdef TIOCSINUSE
  2575.     if (xlocal && ioctl(ttyfd, TIOCSINUSE, NULL) < 0) {
  2576.     if (!quiet)
  2577.       perror(ttname);
  2578.     }
  2579. #endif /* TIOCSINUSE */
  2580. #endif /* ultrix */
  2581.  
  2582. /* Get tty device settings  */
  2583.  
  2584. #ifdef BSD44ORPOSIX            /* POSIX */
  2585.     tcgetattr(ttyfd,&ttold);
  2586.     debug(F101,"ttopen tcgetattr ttold.c_lflag","",ttold.c_lflag);
  2587.     tcgetattr(ttyfd,&ttraw);
  2588.     debug(F101,"ttopen tcgetattr ttraw.c_lflag","",ttraw.c_lflag);
  2589.     tcgetattr(ttyfd,&tttvt);
  2590.     debug(F101,"ttopen tcgetattr tttvt.c_lflag","",tttvt.c_lflag);
  2591. #else                    /* BSD, V7, and all others */
  2592. #ifdef ATTSV                /* AT&T UNIX */
  2593.     ioctl(ttyfd,TCGETA,&ttold);
  2594.     debug(F101,"ttopen ioctl TCGETA ttold.c_lflag","",ttold.c_lflag);
  2595.     ioctl(ttyfd,TCGETA,&ttraw);
  2596.     ioctl(ttyfd,TCGETA,&tttvt);
  2597. #else
  2598. #ifdef BELLV10
  2599.     ioctl(ttyfd,TIOCGETP,&ttold);
  2600.     debug(F101,"ttopen BELLV10 ttold.sg_flags","",ttold.sg_flags);
  2601.     ioctl(ttyfd,TIOCGDEV,&tdold);
  2602.     debug(F101,"ttopen BELLV10 tdold.flags","",tdold.flags);
  2603. #else
  2604.     gtty(ttyfd,&ttold);
  2605.     debug(F101,"ttopen gtty ttold.sg_flags","",ttold.sg_flags);
  2606. #endif /* BELLV10 */
  2607.  
  2608. #ifdef sony_news            /* Sony NEWS */
  2609.     if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) { /* Get console Kanji mode */
  2610.     perror("ttopen error getting Kanji mode");
  2611.     debug(F101,"ttopen error getting Kanji mode","",0);
  2612.     km_ext = -1;            /* Make sure this stays undefined. */
  2613.     }
  2614. #endif /* sony_news */
  2615.  
  2616. #ifdef TIOCGETC
  2617.     debug(F100,"ttopen TIOCGETC","",0);
  2618.     tcharf = 0;                /* In remote mode, also get */
  2619.     if (xlocal == 0) {            /* special characters */
  2620.     if (ioctl(ttyfd,TIOCGETC,&tchold) < 0) {
  2621.         debug(F100,"ttopen TIOCGETC failed","",0);
  2622.     } else {
  2623.         tcharf = 1;            /* It worked. */
  2624.         ioctl(ttyfd,TIOCGETC,&tchnoi); /* Get another copy */
  2625.         debug(F100,"ttopen TIOCGETC ok","",0);
  2626.     }
  2627.     }
  2628. #else
  2629.     debug(F100,"ttopen TIOCGETC not defined","",0);
  2630. #endif /* TIOCGETC */
  2631.  
  2632. #ifdef TIOCGLTC
  2633.     debug(F100,"ttopen TIOCGLTC","",0);
  2634.     ltcharf = 0;            /* In remote mode, also get */
  2635.     if (xlocal == 0) {            /* local special characters */
  2636.     if (ioctl(ttyfd,TIOCGLTC,<chold) < 0) {
  2637.         debug(F100,"ttopen TIOCGLTC failed","",0);
  2638.     } else {
  2639.         ltcharf = 1;        /* It worked. */
  2640.         ioctl(ttyfd,TIOCGLTC,<chnoi); /* Get another copy */
  2641.         debug(F100,"ttopen TIOCGLTC ok","",0);
  2642.     }
  2643.     }
  2644. #else
  2645.     debug(F100,"ttopen TIOCGLTC not defined","",0);
  2646. #endif /* TIOCGLTC */
  2647.  
  2648. #ifdef TIOCLGET
  2649.     debug(F100,"ttopen TIOCLGET","",0);
  2650.     lmodef = 0;
  2651.     if (ioctl(ttyfd,TIOCLGET,&lmode) < 0) {
  2652.     debug(F100,"ttopen TIOCLGET failed","",0);
  2653.     } else {
  2654.     lmodef = 1;
  2655.     debug(F100,"ttopen TIOCLGET ok","",0);
  2656.     }
  2657. #endif /* TIOCLGET */
  2658.  
  2659. #ifdef BELLV10
  2660.     ioctl(ttyfd,TIOCGETP,&ttraw);
  2661.     ioctl(ttyfd,TIOCGETP,&tttvt);
  2662. #else
  2663.     gtty(ttyfd,&ttraw);                 /* And a copy of it for packets*/
  2664.     gtty(ttyfd,&tttvt);                 /* And one for virtual tty service */
  2665. #endif /* BELLV10 */
  2666.  
  2667. #endif /* ATTSV */
  2668. #endif /* BSD44ORPOSIX */
  2669.  
  2670. /* Section for changing line discipline.  It's restored in ttres(). */
  2671.  
  2672. #ifdef AIXRS
  2673. #ifndef AIX41
  2674.     { union txname ld_name; int ld_idx = 0;
  2675.       ttld = 0;
  2676.         do {
  2677.         ld_name.tx_which = ld_idx++;
  2678.         ioctl(ttyfd, TXGETCD, &ld_name);
  2679.       if (!strncmp(ld_name.tx_name, "rts", 3))
  2680.           ttld |= 1;
  2681.         } while (*ld_name.tx_name);
  2682.         debug(F101,"AIX line discipline","",ttld);
  2683.       }
  2684. #endif /* AIX41 */
  2685. #endif /* AIXRS */
  2686.  
  2687. #ifdef BSD41
  2688. /* For 4.1BSD only, force "old" tty driver, new one botches TANDEM. */
  2689.     { int k;
  2690.       ioctl(ttyfd, TIOCGETD, &ttld);    /* Get and save line discipline */
  2691.       debug(F101,"4.1bsd line discipline","",ttld);
  2692.       k = OTTYDISC;            /* Switch to "old" discipline */
  2693.       k = ioctl(ttyfd, TIOCSETD, &k);
  2694.       debug(F101,"4.1bsd tiocsetd","",k);
  2695.     }
  2696. #endif /* BSD41 */
  2697.  
  2698. #ifdef aegis
  2699.     /* This was previously done before the last two TCGETA or gtty above,
  2700.      * in both the ATTSV and not-ATTSV case.  If it is not okay to have only
  2701.      * one copy if it here instead, give us a shout!
  2702.      */
  2703.     sio_$control((short)ttyfd, sio_$raw_nl, false, st);
  2704.     if (xlocal) {       /* ignore breaks from local line */
  2705.         sio_$control((short)ttyfd, sio_$int_enable, false, st);
  2706.         sio_$control((short)ttyfd, sio_$quit_enable, false, st);
  2707.     }
  2708. #endif /* aegis */
  2709.  
  2710. #ifdef VXVE
  2711.     ttraw.c_line = 0;                   /* STTY line 0 for VX/VE */
  2712.     tttvt.c_line = 0;                   /* STTY line 0 for VX/VE */
  2713.     ioctl(ttyfd,TCSETA,&ttraw);
  2714. #endif /* vxve */
  2715.  
  2716. /* If O_NDELAY was used during open(), then remove it now. */
  2717.  
  2718. #ifdef O_NDELAY
  2719.     debug(F100,"ttopen O_NDELAY","",0);
  2720.     if (fcntl(ttyfd, F_GETFL, 0) & O_NDELAY) {
  2721.     debug(F100,"ttopen fcntl O_NDELAY","",0);
  2722. #ifndef aegis
  2723.     if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY) < 0) {
  2724.         debug(F100,"ttopen fcntl failure to unset O_NDELAY","",0);
  2725.         perror("Can't unset O_NDELAY");
  2726.     }
  2727. #endif /* aegis */
  2728.     /* Some systems, notably Xenix (don't know how common this is in
  2729.      * other systems), need special treatment to get rid of the O_NDELAY
  2730.      * behaviour on read() with respect to carrier presence (i.e. read()
  2731.      * returning 0 when carrier absent), even though the above fcntl()
  2732.      * is enough to make read() wait for input when carrier is present.
  2733.      * This magic, in turn, requires CLOCAL for working when the carrier
  2734.      * is absent. But if xlocal == 0, presumably you already have CLOCAL
  2735.      * or you have a carrier, otherwise you wouldn't be running this.
  2736.      */
  2737.     debug(F101,"ttopen xlocal","",xlocal);
  2738. #ifdef ATTSV
  2739. #ifdef BSD44ORPOSIX
  2740. #ifdef COMMENT                /* 12 Aug 1997 */
  2741. #ifdef __bsdi__
  2742.     if (xlocal)
  2743.       ttraw.c_cflag |= CLOCAL;
  2744. #else
  2745. #ifdef __FreeBSD__
  2746.     if (xlocal)
  2747.       ttraw.c_cflag |= CLOCAL;
  2748. #endif /* __FreeBSD__ */
  2749. #endif /* __bsdi__ */
  2750. #else /* Not COMMENT */
  2751. #ifdef CLOCAL
  2752.     if (xlocal)            /* Unset this if it's defined. */
  2753.       ttraw.c_cflag |= CLOCAL;
  2754. #endif /* CLOCAL */
  2755. #endif /* COMMENT */
  2756.     debug(F100,"ttopen calling POSIX tcseattr","",0);
  2757.     if (tcsetattr(ttyfd, TCSADRAIN, &ttraw) < 0) {
  2758.         debug(F100,"ttopen POSIX tcseattr fails","",0);
  2759.         perror("tcsetattr");
  2760.     }
  2761. #else /* !BSD44ORPOSIX */
  2762.     if (xlocal) {
  2763.         ttraw.c_cflag |= CLOCAL;
  2764.         debug(F100,"ttopen calling ioctl(TCSETA)","",0);
  2765.         errno = 0;
  2766.         if (ioctl(ttyfd, TCSETA, &ttraw) < 0) {
  2767.                 debug(F101,"ttopen ioctl(TCSETA) fails","",errno);
  2768.                 perror("ioctl(TCSETA)");
  2769.             }
  2770.     }
  2771. #endif /* BSD44ORPOSIX */
  2772. #endif /* ATTSV */
  2773. #ifndef NOCOTFMC /* = NO Close(Open()) To Force Mode Change */
  2774. /* Reportedly lets uugetty grab the device in SCO UNIX 3.2 / XENIX 2.3 */
  2775.     debug(F100,"ttopen executing close/open","",0);
  2776.     close( priv_opn(ttname, O_RDWR) ); /* Magic to force change. */
  2777. #endif /* NOCOTFMC */
  2778.     }
  2779. #endif /* O_NDELAY */
  2780.  
  2781. /* Instruct the system how to treat the carrier, and set a few other tty
  2782.  * parameters.
  2783.  *
  2784.  * This also undoes the temporary setting of CLOCAL that may have been done
  2785.  * for the close(open()) above (except in Xenix).  Also throw in ~ECHO, to
  2786.  * prevent the other end of the line from sitting there talking to itself,
  2787.  * producing garbage when the user performs a connect.
  2788.  *
  2789.  * SCO Xenix unfortunately seems to ignore the actual state of CLOCAL.
  2790.  * Now it thinks CLOCAL is always on. It seems the only real solution for
  2791.  * Xenix is to switch between the lower and upper case device names.
  2792.  *
  2793.  * This section may at some future time expand into setting a complete
  2794.  * collection of tty parameters, or call a function shared with ttpkt()/
  2795.  * ttvt() that does so.  On the other hand, the initial parameters are not
  2796.  * that important, since ttpkt() or ttvt() should always fix that before
  2797.  * any communication is done.  Well, we'll see...
  2798.  */
  2799.     if (xlocal) {
  2800.         curcarr = -2;
  2801.     debug(F100,"ttopen calling carrctl","",0);
  2802.     carrctl(&ttraw, ttcarr == CAR_ON);
  2803.     debug(F100,"ttopen carrctl ok","",0);
  2804.  
  2805. #ifdef COHERENT
  2806. #define SVORPOSIX
  2807. #endif /* COHERENT */
  2808.  
  2809. #ifdef SVORPOSIX
  2810.     ttraw.c_lflag &= ~ECHO;
  2811.     ttold.c_lflag &= ~ECHO;
  2812. #ifdef BSD44ORPOSIX
  2813.     y = tcsetattr(ttyfd, TCSADRAIN, &ttraw);
  2814.     debug(F101,"ttopen tcsetattr","",y);
  2815. #else
  2816.     y = ioctl(ttyfd, TCSETA, &ttraw);
  2817.     debug(F100,"ttopen ioctl","",y);
  2818. #endif /* BSD44ORPOSIX */
  2819.  
  2820. #else /* BSD, etc */
  2821.     ttraw.sg_flags &= ~ECHO;
  2822.     ttold.sg_flags &= ~ECHO;
  2823. #ifdef BELLV10
  2824.     y = ioctl(ttyfd,TIOCSETP,&ttraw);
  2825.     debug(F100,"ttopen ioctl","",y);
  2826. #else
  2827.     y = stty(ttyfd,&ttraw);
  2828.     debug(F100,"ttopen stty","",y);
  2829. #endif /* BELLV10 */
  2830. #endif /* SVORPOSIX */
  2831.  
  2832. #ifdef COHERENT
  2833. #undef SVORPOSIX
  2834. #endif /* COHERENT */
  2835.  
  2836.     /* ttflui(); */  /*  This fails for some reason.  */
  2837.     }
  2838.  
  2839.     /* Get current speed */
  2840.  
  2841. #ifndef BEBOX
  2842.     ttspeed = ttgspd();
  2843. #else
  2844.     ttspeed = 19200;
  2845. #endif /* !BEBOX */
  2846.     debug(F101,"ttopen ttspeed","",ttspeed);
  2847.  
  2848.     /* Done, make entries in debug log, restore Ctrl-C trap, and return. */
  2849.  
  2850.     debug(F101,"ttopen ttyfd","",ttyfd);
  2851.     debug(F101,"ttopen *lcl","",*lcl);
  2852.     debug(F111,"ttopen lock file",flfnam,lkf);
  2853.     signal(SIGINT,occt);
  2854.     sigint_ign = (occt == SIG_IGN) ? 1 : 0;
  2855.     return(0);
  2856. }
  2857.  
  2858.  
  2859. /*  D O _ O P E N  --  Do the right kind of open() call for the tty. */
  2860.  
  2861. int
  2862. do_open(ttname) char *ttname; {
  2863.  
  2864. #ifndef    O_NDELAY            /* O_NDELAY not defined */
  2865.     return(priv_opn(ttname,2));
  2866. #else                    /* O_NDELAY defined */
  2867.  
  2868. #ifdef ATT7300
  2869. /*
  2870.  Open comms line without waiting for carrier so initial call does not hang
  2871.  because state of "modem" is likely unknown at the initial call  -jrd.
  2872.  If this is needed for the getty stuff to work, and the open would not work
  2873.  without O_NDELAY when getty is still on, then this special case is ok.
  2874.  Otherwise, get rid of it. -ske
  2875. */
  2876.     return(priv_opn(ttname, O_RDWR | O_NDELAY));
  2877.  
  2878. #else    /* !ATT7300 */
  2879.  
  2880.     /* Normal case. Use O_NDELAY according to SET CARRIER. See ttscarr(). */
  2881.  
  2882.     return(priv_opn(ttname, O_RDWR | ((ttcarr != CAR_ON) ? O_NDELAY : 0) ));
  2883.  
  2884. #endif    /* !ATT7300 */
  2885. #endif    /* O_NDELAY */
  2886. }
  2887.  
  2888. /*  T T C L O S  --  Close the TTY, releasing any lock.  */
  2889.  
  2890. static int ttc_state = 0;        /* ttclose() state */
  2891. static char * ttc_nam[] = { "setup", "hangup", "reset", "close" };
  2892.  
  2893. int
  2894. ttclos(foo) int foo; {            /* Arg req'd for signal() prototype */
  2895.     int xx, x = 0;
  2896.  
  2897.     debug(F101,"ttclos ttyfd","",ttyfd);
  2898.     debug(F101,"ttclos netconn","",netconn);
  2899.     debug(F101,"ttclos xlocal","",xlocal);
  2900. #ifdef NOFDZERO
  2901.     debug(F100,"ttclos NOFDZERO","",0);
  2902. #endif /* NOFDZERO */
  2903.  
  2904. #ifdef COMMENT
  2905. #ifdef TTLEBUF
  2906.     le_init();                /* No need for any of this */
  2907. #endif /* TTLEBUF */
  2908. #endif /* COMMENT */
  2909.  
  2910.     if (ttyfd < 0)            /* Wasn't open. */
  2911.       return(0);
  2912.  
  2913.     if (ttfdflg)            /* If we inherited ttyfd from */
  2914.       return(0);            /* another process, don't close it. */
  2915.  
  2916.     tvtflg = 0;                /* (some day get rid of this...) */
  2917.  
  2918. #ifdef IKSD
  2919.     if (inserver) {
  2920. #ifdef TNCODE
  2921.           tn_push();                    /* Place any waiting data into input*/
  2922.           tn_sopt(DO,TELOPT_LOGOUT);    /* Send LOGOUT option before close */
  2923.           TELOPT_UNANSWERED_DO(TELOPT_LOGOUT) = 1;
  2924.           tn_reset();                   /* The Reset Telnet Option table.  */
  2925. #endif /* TNCODE */
  2926. #ifdef CK_SSL
  2927.       if (ssl_active_flag) {
  2928.           if (ssl_debug_flag)
  2929.         BIO_printf(bio_err,"calling SSL_shutdown(ssl)\n");
  2930.           SSL_shutdown(ssl_con);
  2931.           SSL_free(ssl_con);
  2932.           ssl_con = NULL;
  2933.           ssl_active_flag = 0;
  2934.       }
  2935.       if (tls_active_flag) {
  2936.           if (ssl_debug_flag)
  2937.         BIO_printf(bio_err,"calling SSL_shutdown(tls)\n");
  2938.           SSL_shutdown(tls_con);
  2939.           SSL_free(tls_con);
  2940.           tls_con = NULL;
  2941.           tls_active_flag = 0;
  2942.       }
  2943. #endif /* CK_SSL */
  2944.     }
  2945. #endif /* IKSD */
  2946. #ifdef NETCMD
  2947.     if (ttpipe) {            /* We've been using a pipe */
  2948.     /* ttpipe = 0; */
  2949.     if (ttpid > 0) {
  2950.         int wstat;
  2951. #ifdef OSF40
  2952.         union wait statusp_w;
  2953.         int statusp;
  2954. #else
  2955.         int statusp;
  2956. #endif /* OSF40 */
  2957.         close(fdin);        /* Close these. */
  2958.         close(fdout);
  2959.         fdin = fdout = -1;
  2960.         kill(ttpid,1);        /* Kill fork with SIGHUP */
  2961.         while (1) {
  2962.         wstat = wait(
  2963. #ifdef OSF40
  2964.                  &statusp_w
  2965. #else
  2966.                  &statusp
  2967. #endif /* OSF40 */
  2968.                  );
  2969.         if (wstat == ttpid || wstat == -1)
  2970.           break;
  2971. #ifdef OSF40
  2972.         statusp = (*(int *)&(statusp_w));
  2973. #endif /* OSF40 */
  2974.         pexitstat = (statusp & 0xff) ? statusp : statusp >> 8;
  2975.         }
  2976.         ttpid = 0;
  2977.     }
  2978.     netconn = 0;
  2979.     wasclosed = 1;
  2980.     ttyfd = -1;
  2981.     return(0);
  2982.     }
  2983. #endif /* NETCMD */
  2984. #ifdef NETPTY
  2985.     if (ttpty) {
  2986. #ifndef NODOPTY
  2987.         end_pty();
  2988. #endif /* NODOPTY */
  2989.         close(ttyfd);
  2990.     netconn = 0;
  2991.     wasclosed = 1;
  2992.         ttpty = 0;
  2993.         ttyfd = -1;
  2994.         return(0);
  2995.     }
  2996. #endif /* NETPTY */
  2997.  
  2998. #ifdef    NETCONN
  2999.     if (netconn) {            /* If it's a network connection. */
  3000.     debug(F100,"ttclos closing net","",0);
  3001.     netclos();            /* Let the network module close it. */
  3002.     netconn = 0;            /* No more network connection. */
  3003.     debug(F101,"ttclos ttyfd after netclos","",ttyfd); /* Should be -1 */
  3004.     return(0);
  3005.     }
  3006. #endif    /* NETCONN */
  3007.  
  3008.     if (xlocal) {            /* We're closing a SET LINE device */
  3009. #ifdef FT21                /* Fortune 2.1-specific items ... */
  3010.     ioctl(ttyfd,TIOCHPCL, NULL);
  3011. #endif /* FT21 */
  3012. #ifdef ultrix                /* Ultrix-specific items ... */
  3013. #ifdef TIOCSINUSE
  3014.     /* Unset the INUSE flag that we set in ttopen() */
  3015.     ioctl(ttyfd, TIOCSINUSE, NULL);
  3016. #endif /* TIOCSINUSE */
  3017.     ioctl(ttyfd, TIOCNMODEM, &x);
  3018. #ifdef COMMENT
  3019.     /* What was this? */
  3020.     ioctl(ttyfd, TIOCNCAR, NULL);
  3021. #endif /* COMMENT */
  3022. #endif /* ultrix */
  3023.     debug(F100,"ttclos about to call ttunlck","",0);
  3024.         if (ttunlck())                  /* Release uucp-style lock */
  3025.       fprintf(stderr,"Warning, problem releasing lock\r\n");
  3026.     }
  3027.  
  3028.     /* This is to prevent us from sticking in tthang() or close(). */
  3029.  
  3030. #ifdef O_NDELAY
  3031. #ifndef aegis
  3032.     if (ttyfd > 0) {            /* But skip it on stdin. */
  3033.     debug(F100,"ttclos setting O_NDELAY","",0);
  3034.     x = fcntl(ttyfd,F_SETFL,fcntl(ttyfd,F_GETFL, 0)|O_NDELAY);
  3035. #ifdef DEBUG
  3036.     if (deblog && x == -1) {
  3037.         perror("Warning - Can't set O_NDELAY");
  3038.         debug(F101,"ttclos fcntl failure to set O_NDELAY","",x);
  3039.     }
  3040. #endif /* DEBUG */
  3041.     }
  3042. #endif /* aegis */
  3043. #endif /* O_NDELAY */
  3044.  
  3045.     x = 0;
  3046.     ttc_state = 0;
  3047.     if (xlocal
  3048. #ifdef NOFDZERO
  3049.     || ttyfd > 0
  3050. #endif /* NOFDZERO */
  3051.     ) {
  3052.     saval = signal(SIGALRM,xtimerh); /* Enable timer interrupt. */
  3053.     xx = alarm(8);            /* Allow 8 seconds. */
  3054.     debug(F101,"ttclos alarm","",xx);
  3055.     if (
  3056. #ifdef CK_POSIX_SIG
  3057.         sigsetjmp(sjbuf,1)
  3058. #else
  3059.         setjmp(sjbuf)
  3060. #endif /* CK_POSIX_SIG */
  3061.         ) {                /* Timer went off? */
  3062.         x = -1;
  3063. #ifdef DEBUG
  3064.         debug(F111,"ttclos ALARM TRAP errno",ckitoa(ttc_state),errno);
  3065.         printf("ttclos() timeout: %s\n", ttc_nam[ttc_state]);
  3066. #endif /* DEBUG */
  3067.     }
  3068.     errno = 0;
  3069.     debug(F101,"ttclos A","",ttc_state);
  3070.     if (ttc_state < 1) {
  3071.         ttc_state = 1;
  3072.         alarm(8);            /* Re-arm the timer */
  3073.         debug(F101,"ttclos calling tthang()","",x);
  3074.         x = tthang();        /* Hang up first, then... */
  3075.         debug(F101,"ttclos tthang()","",x);
  3076.     }
  3077.     debug(F101,"ttclos B","",ttc_state);
  3078.     if (ttc_state < 2) {
  3079.         ttc_state = 2;
  3080.         debug(F101,"ttclos calling ttres()","",x);
  3081.         alarm(8);            /* Re-arm the timer */
  3082.         x = ttres();        /* Reset device modes. */
  3083.         debug(F101,"ttclos ttres()","",x);
  3084.     }
  3085.     debug(F101,"ttclos C","",ttc_state);
  3086.     if (ttc_state < 3) {
  3087.         ttc_state = 3;
  3088.         errno = 0;
  3089.         debug(F101,"ttclos calling close","",x);
  3090.         alarm(8);            /* Re-arm the timer */
  3091.         x = close(ttyfd);        /* Close the device. */
  3092.         debug(F101,"ttclos close()","",x);
  3093.     }
  3094.     debug(F101,"ttclos D","",ttc_state);
  3095.     ttimoff();            /* Turn off timer. */
  3096.     if (x < 0) {
  3097.         printf("?WARNING - close failed: %s\n",ttnmsv);
  3098. #ifdef DEBUG
  3099.         if (deblog) {
  3100.         printf("errno = %d\n", errno);
  3101.         debug(F101,"ttclos failed","",errno);
  3102.         }
  3103. #endif /* DEBUG */
  3104.     }
  3105.     }
  3106.  
  3107. /* For bidirectional lines, restore getty if it was there before. */
  3108.  
  3109. #ifdef ACUCNTRL                /* 4.3BSD acucntrl() method. */
  3110.     if (xlocal) {
  3111.     debug(F100,"ttclos ACUCNTRL","",0);
  3112.     acucntrl("enable",ttnmsv);    /* Enable getty on the device. */
  3113.     }
  3114. #else
  3115. #ifdef ATT7300                /* ATT UNIX PC (3B1, 7300) method. */
  3116.     if (xlocal) {
  3117.     debug(F100,"ttclos ATT7300 ongetty","",0);
  3118.     if (attmodem & DOGETY)        /* Was getty(1m) running before us? */
  3119.       ongetty(ttnmsv);        /* Yes, restart getty on tty line */
  3120.     attmodem &= ~DOGETY;        /* No phone in use, getty restored */
  3121.     }
  3122. #endif /* ATT7300 */
  3123. #endif /* System-dependent getty-restoring methods */
  3124.  
  3125. #ifdef sony_news
  3126.     km_ext = -1;            /* Invalidate device's Kanji-mode */
  3127. #endif /* sony_news */
  3128.  
  3129.     ttyfd = -1;                         /* Invalidate the file descriptor. */
  3130.     wasclosed = 1;
  3131.     debug(F100,"ttclos done","",0);
  3132.     return(0);
  3133. }
  3134.  
  3135. /*  T T H A N G  --  Hangup phone line or network connection.  */
  3136. /*
  3137.   Returns:
  3138.   0 if it does nothing.
  3139.   1 if it believes that it hung up successfully.
  3140.  -1 if it believes that the hangup attempt failed.
  3141. */
  3142.  
  3143. #define HUPTIME 500            /* Milliseconds for hangup */
  3144.  
  3145. /* Define HUP_POSIX to force non-POSIX builds to use the POSIX hangup method */
  3146.  
  3147. #ifdef UNIXWARE                /* Such as Unixware 1.x, 2.x */
  3148. #ifndef POSIX
  3149. #ifndef HUP_POSIX
  3150. #define HUP_POSIX
  3151. #endif /* HUP_POSIX */
  3152. #endif /* POSIX */
  3153. #endif /* UNIXWARE */
  3154.  
  3155. int
  3156. tthang() {
  3157. #ifdef NOLOCAL
  3158.     return(0);
  3159. #else
  3160.     int x = 0;                /* Sometimes used as return code. */
  3161. #ifndef POSIX
  3162.     int z;                /* worker */
  3163. #endif /* POSIX */
  3164.  
  3165. #ifdef COHERENT
  3166. #define SVORPOSIX
  3167. #endif /* COHERENT */
  3168.  
  3169. #ifdef SVORPOSIX            /* AT&T, POSIX, HPUX declarations. */
  3170.     int spdsav;                /* for saving speed */
  3171. #ifdef HUP_POSIX
  3172.     int spdsavi;
  3173. #else
  3174. #ifdef BSD44ORPOSIX
  3175.     int spdsavi;
  3176. #endif /* BSD44ORPOSIX */
  3177. #endif /* HUP_POSIX */
  3178. #ifdef HPUX
  3179. /*
  3180.   Early versions of HP-UX omitted the mflag typedef.  If you get complaints
  3181.   about it, just change it to long (or better still, unsigned long).
  3182. */
  3183.     mflag
  3184.       dtr_down = 00000000000,
  3185.       modem_rtn,
  3186.       modem_sav;
  3187.     char modem_state[64];
  3188. #endif /* HPUX */
  3189.     int flags;                /* fcntl flags */
  3190.     unsigned short ttc_save;
  3191. #endif /* SVORPOSIX */
  3192.  
  3193. #ifdef COHERENT
  3194. #undef SVORPOSIX
  3195. #endif /* COHERENT */
  3196.  
  3197.     if (ttyfd < 0) return(0);           /* Don't do this if not open  */
  3198.     if (xlocal < 1) return(0);        /* Don't do this if not local */
  3199.  
  3200. #ifdef NETCMD
  3201.     if (ttpipe)
  3202.       return((ttclos(0) < 0) ? -1 : 1);
  3203. #endif /* NETCMD */
  3204. #ifdef NETPTY
  3205.     if (ttpty)
  3206.       return((ttclos(0) < 0) ? -1 : 1);
  3207. #endif /* NETPTY */
  3208. #ifdef NETCONN
  3209.     if (netconn)            /* Network connection. */
  3210.       return((netclos() < 0) ? -1 : 1);    /* Just close it. */
  3211. #endif /* NETCONN */
  3212.  
  3213. /* From here down, we handle real tty devices. */
  3214. #ifdef HUP_POSIX
  3215. /*
  3216.   e.g. for Unixware 2, where we don't have a full POSIX build, we
  3217.   still have to use POSIX-style hangup.  Thus the duplication of this
  3218.   and the next case, the only difference being we use a local termios
  3219.   struct here, since a different model is used elsewhere.
  3220. */
  3221.     {
  3222.     struct termios ttcur;
  3223.     int x;
  3224.     debug(F100,"tthang HUP_POSIX style","",0);
  3225.     x = tcgetattr(ttyfd, &ttcur);    /* Get current attributes */
  3226.     debug(F111,"tthang tcgetattr",ckitoa(errno),x);
  3227.     if (x < 0) return(-1);
  3228.     spdsav = cfgetospeed(&ttcur);    /* Get current speed */
  3229.     debug(F111,"tthang cfgetospeed",ckitoa(errno),spdsav);
  3230.     spdsavi = cfgetispeed(&ttcur);    /* Get current speed */
  3231.     debug(F111,"tthang cfgetispeed",ckitoa(errno),spdsavi);
  3232.     x = cfsetospeed(&ttcur,B0);    /* Replace by 0 */
  3233.     debug(F111,"tthang cfsetospeed",ckitoa(errno),x);
  3234.     if (x < 0) return(-1);
  3235.     x = cfsetispeed(&ttcur,B0);
  3236.     debug(F111,"tthang cfsetispeed",ckitoa(errno),x);
  3237.     if (x < 0) return(-1);
  3238.     x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
  3239.     debug(F111,"tthang tcsetattr B0",ckitoa(errno),x);
  3240.     if (x < 0) return(-1);
  3241.     msleep(HUPTIME);        /* Sleep 0.5 sec */
  3242.     x = cfsetospeed(&ttcur,spdsav); /* Restore prev speed */
  3243.     if (x < 0) return(-1);
  3244.     debug(F111,"tthang cfsetospeed prev",ckitoa(errno),x);
  3245.     x = cfsetispeed(&ttcur,spdsavi);
  3246.     debug(F111,"tthang cfsetispeed prev",ckitoa(errno),x);
  3247.     if (x < 0) return(-1);
  3248.     x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
  3249.     debug(F111,"tthang tcsetattr restore",ckitoa(errno),x);
  3250.     if (x < 0) return(-1);
  3251.     return(1);
  3252.     }
  3253. #else
  3254. #ifdef BSD44ORPOSIX
  3255. /*
  3256.   NOTE: This should work for QNX too, but in case it doesn't, it is also
  3257.   possible to toggle DTR using qnx_ioctl(ttyfd,QCTL_DEV_CTL,&new,&old);
  3258.   see <sys/qioctl.h> and QNX News V10, Sep 96, p44.
  3259.   Newer versions of QNX also have a tcdropline(howlong) function.
  3260. */
  3261.     {
  3262.     int x;
  3263.     debug(F100,"tthang POSIX style","",0);
  3264.     x = tcgetattr(ttyfd, &ttcur);    /* Get current attributes */
  3265.     debug(F111,"tthang tcgetattr",ckitoa(errno),x);
  3266.     if (x < 0) return(-1);
  3267.     spdsav = cfgetospeed(&ttcur);    /* Get current speed */
  3268.     debug(F111,"tthang cfgetospeed",ckitoa(errno),spdsav);
  3269.     spdsavi = cfgetispeed(&ttcur);    /* Get current speed */
  3270.     debug(F111,"tthang cfgetispeed",ckitoa(errno),spdsavi);
  3271.     x = cfsetospeed(&ttcur,B0);    /* Replace by 0 */
  3272.     debug(F111,"tthang cfsetospeed",ckitoa(errno),x);
  3273.     if (x < 0) return(-1);
  3274.     x = cfsetispeed(&ttcur,B0);
  3275.     debug(F111,"tthang cfsetispeed",ckitoa(errno),x);
  3276.     if (x < 0) return(-1);
  3277.     x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
  3278.     debug(F111,"tthang tcsetattr B0",ckitoa(errno),x);
  3279.     if (x < 0) return(-1);
  3280.     msleep(HUPTIME);        /* Sleep 0.5 sec */
  3281.     x = cfsetospeed(&ttcur,spdsav); /* Restore prev speed */
  3282.     if (x < 0) return(-1);
  3283.     debug(F111,"tthang cfsetospeed prev",ckitoa(errno),x);
  3284.     x = cfsetispeed(&ttcur,spdsavi);
  3285.     debug(F111,"tthang cfsetispeed prev",ckitoa(errno),x);
  3286.     if (x < 0) return(-1);
  3287.     x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
  3288.     debug(F111,"tthang tcsetattr restore",ckitoa(errno),x);
  3289.     if (x < 0) return(-1);
  3290.     return(1);
  3291.     }
  3292.  
  3293.  
  3294. #else /* BSD44ORPOSIX */
  3295.  
  3296. #ifdef aegis                /* Apollo Aegis */
  3297.     sio_$control((short)ttyfd, sio_$dtr, false, st);    /* DTR down */
  3298.     msleep(HUPTIME);                    /* pause */
  3299.     sio_$control((short)ttyfd, sio_$dtr, true,  st);    /* DTR up */
  3300.     return(1);
  3301. #endif /* aegis */
  3302.  
  3303. #ifdef ANYBSD                /* Any BSD version. */
  3304. #ifdef TIOCCDTR                /* Except those that don't have this */
  3305.     debug(F100,"tthang BSD style","",0);
  3306.     if (ioctl(ttyfd,TIOCCDTR,0) < 0) {    /* Clear DTR. */
  3307.     debug(F101,"tthang TIOCCDTR fails","",errno);
  3308.     return(-1);
  3309.     }
  3310.     msleep(HUPTIME);            /* For about 1/2 sec */
  3311.     errno = 0;
  3312.     x = ioctl(ttyfd,TIOCSDTR,0);    /* Restore DTR */
  3313.     if (x < 0) {
  3314.     /*
  3315.       For some reason, this tends to fail with "no such device or address"
  3316.       but the operation still works, probably because of the close/open
  3317.       later on.  So let's not scare the user unnecessarily here.
  3318.     */
  3319.     debug(F101,"tthang TIOCSDTR errno","",errno); /* Log the error */
  3320.     x = 1;                /* Pretend we succeeded */
  3321.     } else if (x == 0) x = 1;        /* Success */
  3322. #ifdef COMMENT
  3323. #ifdef FT21
  3324.     ioctl(ttyfd, TIOCSAVEMODES, 0);
  3325.     ioctl(ttyfd, TIOCHPCL, 0);
  3326.     close(ttyfd);            /* Yes, must do this twice */
  3327.     if ((ttyfd = open(ttnmsv,2)) < 0)    /* on Fortune computers... */
  3328.       return(-1);            /* (but why?) */
  3329.     else x = 1;
  3330. #endif /* FT21 */
  3331. #endif /* COMMENT */
  3332. #endif /* TIOCCDTR */
  3333.     close(do_open(ttnmsv));        /* Clear i/o error condition */
  3334.     errno = 0;
  3335. #ifdef COMMENT
  3336. /* This is definitely dangerous.  Why was it here? */
  3337.     z = ttvt(ttspeed,ttflow);        /* Restore modes. */
  3338.     debug(F101,"tthang ttvt returns","",z);
  3339.     return(z < 0 ? -1 : 1);
  3340. #else
  3341.     return(x);
  3342. #endif /* COMMENT */
  3343. #endif /* ANYBSD */
  3344.  
  3345. #ifdef ATTSV
  3346. /* AT&T UNIX section, includes HP-UX and generic AT&T System III/V... */
  3347.  
  3348. #ifdef HPUX
  3349. /* Hewlett Packard allows explicit manipulation of modem signals. */
  3350.  
  3351. #ifdef COMMENT
  3352. /* Old way... */
  3353.     debug(F100,"tthang HP-UX style","",0);
  3354.     if (ioctl(ttyfd,MCSETAF,&dtr_down) < 0)        /* lower DTR */
  3355.       return(-1);                           /* oops, can't. */
  3356.     msleep(HUPTIME);                       /* Pause half a second. */
  3357.     x = 1;                           /* Set return code */
  3358.     if (ioctl(ttyfd,MCGETA,&modem_rtn) > -1) {     /* Get line status. */
  3359.     if ((modem_rtn & MDCD) != 0)             /* Check if CD is low. */
  3360.       x = -1;                                  /* CD didn't drop, fail. */
  3361.     } else x = -1;
  3362.  
  3363.     /* Even if above calls fail, RTS & DTR should be turned back on. */
  3364.     modem_rtn = MRTS | MDTR;
  3365.     if (ioctl(ttyfd,MCSETAF,&modem_rtn) < 0) x = -1;
  3366.     return(x);
  3367. #else
  3368. /* New way, from Hellmuth Michaelis */
  3369.     debug(F100,"tthang HP-UX style, HPUXDEBUG","",0);
  3370.     if (ioctl(ttyfd,MCGETA,&modem_rtn) == -1) { /* Get current status. */
  3371.     debug(F100,"tthang HP-UX: can't get modem lines, NO HANGUP!","",0);
  3372.     return(-1);
  3373.     }
  3374.     sprintf(modem_state,"%#lx",modem_rtn);
  3375.     debug(F110,"tthang HP-UX: modem lines = ",modem_state,0);
  3376.     modem_sav = modem_rtn;        /* Save current modem signals */
  3377.     modem_rtn &= ~MDTR;            /* Turn DTR bit off */
  3378.     sprintf(modem_state,"%#lx",modem_rtn);
  3379.     debug(F110,"tthang HP-UX: DTR down = ",modem_state,0);
  3380.     if (ioctl(ttyfd,MCSETAF,&modem_rtn) < 0) { /* lower DTR */
  3381.     debug(F100,"tthang HP-UX: can't lower DTR!","",0);
  3382.     return(-1);            /* oops, can't. */
  3383.     }
  3384.     msleep(HUPTIME);            /* Pause half a second. */
  3385.     x = 1;                /* Set return code */
  3386.     if (ioctl(ttyfd,MCGETA,&modem_rtn) > -1) { /* Get line status. */
  3387.     sprintf(modem_state,"%#lx",modem_rtn);
  3388.     debug(F110,"tthang HP-UX: modem lines got = ",modem_state,0);
  3389.     if ((modem_rtn & MDCD) != 0) {    /* Check if CD is low. */
  3390.         debug(F100,"tthang HP-UX: DCD not down","",0);
  3391.         x = -1;            /* CD didn't drop, fail. */
  3392.     } else {
  3393.         debug(F100,"tthang HP-UX: DCD down","",0);
  3394.     }
  3395.     } else {
  3396.     x = -1;
  3397.     debug(F100,"tthang HP-UX: can't get DCD status !","",0);
  3398.     }
  3399.  
  3400.     /* Even if above calls fail, DTR should be turned back on. */
  3401.  
  3402.     modem_sav |= MDTR;
  3403.     if (ioctl(ttyfd,MCSETAF,&modem_sav) < 0) {
  3404.     x = -1;
  3405.     debug(F100,"tthang HP-UX: can't set saved state","",0);
  3406.     } else {
  3407.     sprintf(modem_state,"%#lx",modem_sav);
  3408.     debug(F110,"tthang HP-UX: final modem lines = ",modem_state,0);
  3409.     }
  3410.     return(x);
  3411. #endif /* COMMENT */
  3412.  
  3413. #else /* AT&T but not HP-UX */
  3414.  
  3415. /* SVID for AT&T System V R3 defines ioctl's for handling modem signals. */
  3416. /* It is not known how many, if any, systems actually implement them, */
  3417. /* so we include them here in ifdef's. */
  3418.  
  3419. /*
  3420.   Unixware has the TIOCMxxx symbols defined, but calling ioctl() with them
  3421.   gives error 22 (invalid argument).
  3422. */
  3423. #ifndef _IBMR2
  3424. /*
  3425.   No modem-signal twiddling for IBM RT PC or RS/6000.
  3426.   In AIX 3.1 and earlier, the ioctl() call is broken.
  3427.   This code could be activated for AIX 3.1 with PTF 2006 or later
  3428.   (e.g. AIX 3.2), but close/open does the job too, so why bother.
  3429. */
  3430. #ifdef TIOCMBIS                /* Bit Set */
  3431. #ifdef TIOCMBIC                /* Bit Clear */
  3432. #ifdef TIOCM_DTR            /* DTR */
  3433.  
  3434. /* Clear DTR, sleep 300 msec, turn it back on. */
  3435. /* If any of the ioctl's return failure, go on to the next section. */
  3436.  
  3437.     z = TIOCM_DTR;            /* Code for DTR. */
  3438. #ifdef COMMENT
  3439. /*
  3440.   This was the cause of the troubles with the Solaris Port Monitor.
  3441.   The problem is: RTS never comes back on.  Moral: Don't do it!
  3442.   (But why doesn't it come back on?  See the TIOCMBIS call...)
  3443. */
  3444. #ifdef TIOCM_RTS            /* Lower RTS too if symbol is known. */
  3445.     z |= TIOCM_RTS;
  3446. #endif /* TIOCM_RTS */
  3447. #endif /* COMMENT */
  3448.  
  3449.     debug(F101,"tthang TIOCM signal mask","",z);
  3450.     if (ioctl(ttyfd,TIOCMBIC,&z) > -1) {   /* Try to lower DTR. */
  3451.     debug(F100,"tthang TIOCMBIC ok","",0);
  3452.     msleep(HUPTIME);           /* Pause half a second. */
  3453.     if (ioctl(ttyfd,TIOCMBIS,&z) > -1) { /* Try to turn it back on. */
  3454.         debug(F100,"tthang TIOCMBIS ok","",0);
  3455. #ifndef CLSOPN
  3456.         return(1);            /* Success, done. */
  3457. #endif /* CLSOPN */
  3458.     } else {            /* Couldn't raise, continue. */
  3459.         debug(F101,"tthang TIOCMBIS errno","",errno);
  3460.     }
  3461.     } else {                /* Couldn't lower, continue. */
  3462.      debug(F101,"tthang TIOCMBIC errno","",errno);
  3463.     }
  3464. #endif /* TIOCM_DTR */
  3465. #endif /* TIOCMBIC */
  3466. #endif /* TIOCMBIS */
  3467. #endif /* _IBMR2 */
  3468.  
  3469. /*
  3470.   General AT&T UNIX case, not HPUX.  The following code is highly suspect.  No
  3471.   two AT&T-based systems seem to do this the same way.  The object is simply
  3472.   to turn off DTR and then turn it back on.  SVID says the universal method
  3473.   for turning off DTR is to set the speed to zero, and this does seem to do
  3474.   the trick in all cases.  But neither SVID nor any known man pages say how to
  3475.   turn DTR back on again.  Some variants, like most Xenix implementations,
  3476.   raise DTR again when the speed is restored to a nonzero value.  Others
  3477.   require the device to be closed and opened again, but this is risky because
  3478.   getty could seize the device during the instant it is closed.
  3479. */
  3480.  
  3481. /* Return code for ioctl failures... */
  3482. #ifdef ATT6300
  3483.     x = 1;                /* ATT6300 doesn't want to fail... */
  3484. #else
  3485.     x = -1;
  3486. #endif /* ATT6300 */
  3487.  
  3488.     debug(F100,"tthang get settings","",0);
  3489.     if (ioctl(ttyfd,TCGETA,&ttcur) < 0) /* Get current settings. */
  3490.       return(x);            /* Fail if this doesn't work. */
  3491.     if ((flags = fcntl(ttyfd,F_GETFL,0)) < 0) /* Get device flags. */
  3492.       return(x);
  3493.     ttc_save = ttcur.c_cflag;        /* Remember current speed. */
  3494.     spdsav = ttc_save & CBAUD;
  3495.     debug(F101,"tthang speed","",spdsav);
  3496.  
  3497. #ifdef O_NDELAY
  3498.     debug(F100,"tthang turning O_NDELAY on","",0);
  3499.     fcntl(ttyfd, F_SETFL, flags | O_NDELAY); /* Activate O_NDELAY */
  3500. #endif /* O_NDELAY */
  3501.  
  3502. #ifdef ATT7300 /* This is the way it is SUPPOSED to work */
  3503.     ttcur.c_cflag &= ~CBAUD;        /* Change the speed to zero.  */
  3504. #else
  3505. #ifdef RTAIX
  3506.     ttcur.c_cflag &= ~CBAUD;        /* Change the speed to zero.  */
  3507. #else          /* This way really works but may be dangerous */
  3508. #ifdef u3b2
  3509.     ttcur.c_cflag = ~(CBAUD|CLOCAL);    /* Special for AT&T 3B2s */
  3510.                     /* (CLOCAL must be OFF) */
  3511. #else
  3512. #ifdef SCO3R2                /* SCO UNIX 3.2 */
  3513. /*
  3514.   This is complete nonsense, but an SCO user claimed this change made
  3515.   hanging up work.  Comments from other SCO UNIX 3.2 users would be
  3516.   appreciated.
  3517. */
  3518.     ttcur.c_cflag = CBAUD|B0;
  3519. #else
  3520. #ifdef AIXRS                /* AIX on RS/6000 */
  3521. /*
  3522.   Can't set speed to zero on AIX 3.1 on RS/6000 64-port adapter,
  3523.   even though you can do it on the built-in port and the 8- and 16-port
  3524.   adapters.  (Untested on 128-port adapter.)
  3525. */
  3526.     ttcur.c_cflag = CLOCAL|HUPCL|spdsav; /* Speed 0 causes EINVAL */
  3527. #else                    /* None of the above */
  3528. /*
  3529.   Set everything, including the speed, to zero, except for the CLOCAL
  3530.   and HUPCL bits.
  3531. */
  3532.     ttcur.c_cflag = CLOCAL|HUPCL;
  3533. #endif /* AIXRS */
  3534. #endif /* SCO3R2 */
  3535. #endif /* u3b2 */
  3536. #endif /* RTAIX */
  3537. #endif /* ATT7300 */
  3538.  
  3539. #ifdef COMMENT
  3540.     /* and if none of those work, try one of these... */
  3541.     ttcur.c_cflag = 0;
  3542.     ttcur.c_cflag = CLOCAL;
  3543.     ttcur.c_cflag &= ~(CBAUD|HUPCL);
  3544.     ttcur.c_cflag &= ~(CBAUD|CREAD);
  3545.     ttcur.c_cflag &= ~(CBAUD|CREAD|HUPCL);
  3546.     /* or other combinations */
  3547. #endif /* COMMENT */
  3548.  
  3549. #ifdef TCXONC
  3550.     debug(F100,"tthang TCXONC","",0);
  3551.     if (ioctl(ttyfd, TCXONC, 1) < 0) {
  3552.     debug(F101,"tthang TCXONC failed","",errno);
  3553.     }
  3554. #endif /* TCXONC */
  3555.  
  3556. #ifdef TIOCSTART
  3557.     debug(F100,"tthang TIOCSTART","",0);
  3558.     if (ioctl(ttyfd, TIOCSTART, 0) < 0) {
  3559.     debug(F101,"tthang TIOCSTART failed","",errno);
  3560.     }
  3561. #endif /* TIOCSTART */
  3562.  
  3563.     if (ioctl(ttyfd,TCSETAF,&ttcur) < 0) { /* Fail if we can't. */
  3564.     debug(F101,"tthang TCSETAF failed","",errno);
  3565.     fcntl(ttyfd, F_SETFL, flags);    /* Restore flags */
  3566.     return(-1);            /* before returning. */
  3567.     }
  3568.     msleep(300);            /* Give modem time to notice. */
  3569.  
  3570. #ifndef NOCOTFMC
  3571.  
  3572. /* Now, even though it doesn't say this in SVID or any man page, we have */
  3573. /* to close and reopen the device.  This is not necessary for all systems, */
  3574. /* but it's impossible to predict which ones need it and which ones don't. */
  3575.  
  3576. #ifdef ATT7300
  3577. /*
  3578.   Special handling for ATT 7300 UNIX PC and 3B1, which have "phone"
  3579.   related ioctl's for their internal modems.  attmodem has getty status and
  3580.   modem-in-use bit.  Reportedly the ATT7300/3B1 PIOCDISC call is necessary,
  3581.   but also ruins the file descriptor, and no other phone(7) ioctl call can fix
  3582.   it.  Whateverit does, it seems to escape detection with PIOCGETA and TCGETA.
  3583.   The only way to undo the damage is to close the fd and then reopen it.
  3584. */
  3585.     if (attmodem & ISMODEM) {
  3586.     debug(F100,"tthang attmodem close/open","",0);
  3587.     ioctl(ttyfd,PIOCUNHOLD,&dialer); /* Return call to handset. */
  3588.     ioctl(ttyfd,PIOCDISC,&dialer);    /* Disconnect phone. */
  3589.     close(ttyfd);            /* Close and reopen the fd. */
  3590.     ttyfd = priv_opn(ttnmsv, O_RDWR | O_NDELAY);
  3591.     attmodem &= ~ISMODEM;        /* Phone no longer in use. */
  3592.     }
  3593. #else /* !ATT7300 */
  3594. /* It seems we have to close and open the device for other AT&T systems */
  3595. /* too, and this is the place to do it.  The following code does the */
  3596. /* famous close(open(...)) magic by default.  If that doesn't work for you, */
  3597. /* then try uncommenting the following statement or putting -DCLSOPN in */
  3598. /* the makefile CFLAGS. */
  3599.  
  3600. /* #define CLSOPN */
  3601.  
  3602. #ifndef SCO32 /* Not needed by, and harmful to, SCO UNIX 3.2 / Xenix 2.3 */
  3603.  
  3604. #ifdef O_NDELAY
  3605. #define OPENFLGS O_RDWR | O_NDELAY
  3606. #else
  3607. #define OPENFLGS O_RDWR
  3608. #endif
  3609.  
  3610. #ifndef CLSOPN
  3611. /* This method is used by default, i.e. unless CLSOPN is defined. */
  3612. /* It is thought to be safer because there is no window where getty */
  3613. /* can seize control of the device.  The drawback is that it might not work. */
  3614.  
  3615.     debug(F101,"tthang close(open()), OPENFLGS","",OPENFLGS);
  3616.     close(priv_opn(ttnmsv, OPENFLGS));
  3617.  
  3618. #else
  3619. /* This method is used if you #define CLSOPN.  It is more likely to work */
  3620. /* than the previous method, but it's also more dangerous. */
  3621.  
  3622.     debug(F101,"tthang close/open, OPENFLGS","",OPENFLGS);
  3623.     close(ttyfd);
  3624.     msleep(10);
  3625.     ttyfd = priv_opn(ttnmsv, OPENFLGS);    /* Open it again */
  3626. #endif /* CLSOPN */
  3627. #undef OPENFLGS
  3628.  
  3629. #endif /* SCO32 */
  3630. #endif /* ATT7300 */
  3631.  
  3632. #endif /* NOCOTFMC */
  3633.  
  3634. /* Now put all flags & modes back the way we found them. */
  3635. /* (Does the order of ioctl & fcntl matter ? ) */
  3636.  
  3637.     debug(F100,"tthang restore settings","",0);
  3638.     ttcur.c_cflag = ttc_save;        /* Get old speed back. */
  3639.     if (ioctl(ttyfd,TCSETAF,&ttcur) < 0) /* ioctl parameters. */
  3640.       return(-1);
  3641. #ifdef O_NDELAY
  3642. /*
  3643.   This is required for IBM RT and RS/6000, probably helps elsewhere too (?).
  3644.   After closing a modem line, the modem will probably not be asserting
  3645.   carrier any more, so we should not require carrier any more.  If this
  3646.   causes trouble on non-IBM UNIXes, change the #ifdef to use _IBMR2 rather
  3647.   than O_NDELAY.
  3648. */
  3649.     flags &= ~O_NDELAY;            /* Don't require carrier on reopen */
  3650. #endif /* O_NDELAY */
  3651.     if (fcntl(ttyfd,F_SETFL,flags) < 0)    /* fcntl parameters */
  3652.       return(-1);
  3653.  
  3654.     return(1);
  3655. #endif /* not HPUX */
  3656. #endif /* ATTSV */
  3657. #endif /* BSD44ORPOSIX */
  3658. #endif /* HUP_POSIX */
  3659. #endif /* NOLOCAL */
  3660. }
  3661.  
  3662. /*
  3663.   Major change in 5A(174).  We used to use LPASS8, if it was defined, to
  3664.   allow 8-bit data and Xon/Xoff flow control at the same time.  But this
  3665.   LPASS8 business seems to have been causing trouble for everybody but me!
  3666.   For example, Annex terminal servers, commonly used with Encore computers,
  3667.   do not support LPASS8 even though the Encore itself does.  Ditto for many
  3668.   other terminal servers, TELNET connections, rlogin connections, etc etc.
  3669.   Now, reportedly, even vanilla 4.3 BSD systems can't do this right on their
  3670.   serial lines, even though LPASS8 is a feature of 4.3BSD.  So let's turn it
  3671.   off for everybody.  That means we goes back to using raw mode, with no
  3672.   flow control.  Phooey.
  3673.  
  3674.   NOTE: This must be done before the first reference to LPASS8 in this file,
  3675.   and after the last #include statment.
  3676. */
  3677. #ifdef LPASS8
  3678. #undef LPASS8
  3679. #endif /* LPASS8 */
  3680.  
  3681. /*  T T R E S  --  Restore terminal to "normal" mode.  */
  3682.  
  3683. /* ske@pkmab.se: There are two choices for what this function should do.
  3684.  * (1) Restore the tty to current "normal" mode, with carrier treatment
  3685.  * according to ttcarr, to be used after every kermit command. (2) Restore
  3686.  * the tty to the state it was in before kermit opened it. These choices
  3687.  * conflict, since ttold can't hold both choices of tty parameters.  ttres()
  3688.  * is currently being called as in choice (1), but ttold basically holds
  3689.  * the initial parameters, as in (2), and the description at the beginning
  3690.  * of this file says (2).
  3691.  *
  3692.  * I don't think restoring tty parameters after all kermit commands makes
  3693.  * much of a difference.  Restoring them upon exit from kermit may be of
  3694.  * some use in some cases (when the line is not restored automatically on
  3695.  * close, by the operating system).
  3696.  *
  3697.  * I can't choose which one it should be, so I haven't changed it. It
  3698.  * probably works as it is, too. It would probably even work even with
  3699.  * ttres() entirely deleted...
  3700.  *
  3701.  * (from fdc: Actually, this function operates in remote mode too, so
  3702.  * it restores the console (command) terminal to whatever mode it was
  3703.  * in before packet operations began, so that commands work right again.)
  3704.  */
  3705. int
  3706. ttres() {                               /* Restore the tty to normal. */
  3707.     int x;
  3708.  
  3709.     if (ttyfd < 0) return(-1);          /* Not open. */
  3710.  
  3711.     if (ttfdflg) return(0);        /* Don't mess with terminal modes if */
  3712.                     /* we got ttyfd from another process */
  3713. #ifdef    NETCONN
  3714.     if (netconn) {            /* Network connection */
  3715.         tvtflg = 0;
  3716. #ifdef TCPSOCKET
  3717. #ifdef TCP_NODELAY
  3718.         {
  3719.         extern int tcp_nodelay;    /* Just put this back if necessary */
  3720.         if (ttnet == NET_TCPB) {
  3721.         if (nodelay_sav > -1) {
  3722.             no_delay(nodelay_sav);
  3723.             nodelay_sav = -1;
  3724.         }
  3725.         }
  3726.         }
  3727. #endif /* TCP_NODELAY */
  3728. #endif /* TCPSOCKET */
  3729.     return(0);
  3730.     }
  3731. #endif    /* NETCONN */
  3732. #ifdef NETCMD
  3733.     if (ttpipe) return(0);
  3734. #endif /* NETCMD */
  3735. #ifdef NETPTY
  3736.     if (ttpty) return(0);
  3737. #endif /* NETPTY */
  3738.  
  3739. /* Real terminal device, so restore its original modes */
  3740.  
  3741. #ifdef BSD44ORPOSIX            /* For POSIX like this */
  3742.     debug(F100,"ttres BSD44ORPOSIX","",0);
  3743.     x = tcsetattr(ttyfd,TCSADRAIN,&ttold);
  3744. #else                    /* For all others... */
  3745. #ifdef ATTSV                            /* For AT&T versions... */
  3746.     debug(F100,"ttres ATTSV","",0);
  3747.     x = ioctl(ttyfd,TCSETAW,&ttold);    /* Restore tty modes this way. */
  3748. #else
  3749. /* Here we restore the modes for BSD */
  3750.  
  3751. #ifdef LPASS8                /* Undo "pass8" if it were done */
  3752.     if (lmodef) {
  3753.     if (ioctl(ttyfd,TIOCLSET,&lmode) < 0)
  3754.       debug(F100,"ttres TIOCLSET failed","",0);
  3755.     else
  3756.       debug(F100,"ttres TIOCLSET ok","",0);
  3757.     }
  3758. #endif /* LPASS8 */
  3759.  
  3760. #ifdef CK_DTRCTS           /* Undo hardware flow if it were done */
  3761.     if (lmodef) {
  3762.      if (ioctl(ttyfd,TIOCLSET,&lmode) < 0)
  3763.        debug(F100,"ttres TIOCLSET failed","",0);
  3764.      else
  3765.        debug(F100,"ttres TIOCLSET ok","",0);
  3766.     }
  3767. #endif /* CK_DTRCTS */
  3768.  
  3769. #ifdef TIOCGETC                /* Put back special characters */
  3770.     if (tcharf && (xlocal == 0)) {
  3771.     if (ioctl(ttyfd,TIOCSETC,&tchold) < 0)
  3772.       debug(F100,"ttres TIOCSETC failed","",0);
  3773.     else
  3774.       debug(F100,"ttres TIOCSETC ok","",0);
  3775.     }
  3776. #endif /* TIOCGETC */
  3777.  
  3778. #ifdef TIOCGLTC                /* Put back local special characters */
  3779.     if (ltcharf && (xlocal == 0)) {
  3780.     if (ioctl(ttyfd,TIOCSLTC,<chold) < 0)
  3781.       debug(F100,"ttres TIOCSLTC failed","",0);
  3782.     else
  3783.       debug(F100,"ttres TIOCSLTC ok","",0);
  3784.     }
  3785. #endif /* TIOCGLTC */
  3786.  
  3787. #ifdef BELLV10
  3788.     debug(F100,"ttres BELLV10","",0);
  3789.     x = ioctl(ttyfd,TIOCSETP,&ttold);    /* Restore both structs */
  3790.     x = ioctl(ttyfd,TIOCSDEV,&tdold);
  3791. #else
  3792.     debug(F100,"ttres stty","",0);
  3793.     x = stty(ttyfd,&ttold);             /* Restore tty modes the old way. */
  3794. #endif /* BELLV10 */
  3795.  
  3796.     if (!xlocal)
  3797.       msleep(100);            /* This replaces sleep(1)... */
  3798.                     /* Put back sleep(1) if tty is */
  3799.                     /* messed up after close. */
  3800. #endif /* ATTSV */
  3801. #endif /* BSD44ORPOSIX */
  3802.  
  3803.     debug(F101,"ttres result","",x);
  3804. #ifndef QNX
  3805.     if (x < 0) debug(F101,"ttres errno","",errno);
  3806. #endif /* QNX */
  3807.  
  3808. #ifdef AIXRS
  3809. #ifndef AIX41
  3810.     x = ioctl(ttyfd, ttld & 1 ? TXADDCD : TXDELCD, "rts");
  3811.     debug(F101,"ttres AIX line discipline rts restore","",x);
  3812. #endif /* AIX41 */
  3813. #endif /* AIXRS */
  3814.  
  3815. #ifdef BSD41
  3816.     if (ttld > -1) {            /* Put back line discipline */
  3817.     x = ioctl(ttyfd, TIOCSETD, &ttld);
  3818.     debug(F101,"ttres BSD41 line discipline restore","",x);
  3819.     if (x < 0) debug(F101,"...ioctl errno","",errno);
  3820.     ttld = -1;
  3821.     }
  3822. #endif /* BSD41 */
  3823.  
  3824. #ifdef sony_news
  3825.     x = xlocal ? km_ext : km_con;    /* Restore Kanji mode. */
  3826.     if (x != -1) {            /* Make sure we know original modes. */
  3827.     if (ioctl(ttyfd,TIOCKSET, &x) < 0) {
  3828.         perror("ttres can't set Kanji mode");
  3829.         debug(F101,"ttres error setting Kanji mode","",x);
  3830.         return(-1);
  3831.     }
  3832.     }
  3833.     debug(F100,"ttres set Kanji mode ok","",0);
  3834. #endif /* sony_news */
  3835.  
  3836.     tvtflg = 0;                /* Invalidate terminal mode settings */
  3837.     debug(F101,"ttres return code","",x);
  3838.     return(x);
  3839. }
  3840.  
  3841. #ifndef NOUUCP
  3842.  
  3843. /*  T T C H K P I D  --  Check lockfile pid  */
  3844. /*
  3845.   Read pid from lockfile named f, check that it's still valid.
  3846.   If so, return 1.
  3847.   On failure to read pid, return 1.
  3848.   Otherwise, try to delete lockfile f and return 0 if successful, else 1.
  3849. */
  3850. static int
  3851. ttchkpid(f) char *f; {
  3852.     int pid, mypid, x;
  3853.     pid = ttrpid(f);            /* Read pid from file. */
  3854.     if (pid > -1) {            /* If we were able to read the pid.. */
  3855.     debug(F101,"ttchkpid lock pid","",pid);
  3856.     errno = 0;            /* See if process still exists. */
  3857.     mypid = (int)getpid();        /* Get my own pid. */
  3858.     debug(F101,"ttchkpid my pid","",mypid);
  3859.     if (pid == mypid) {        /* It's me! */
  3860.         x = -1;            /* So I can delete it */
  3861.         errno = ESRCH;        /* pretend it's invalid */
  3862.     } else {            /* It's not me */
  3863.         x = kill((PID_T)pid, 0);    /* See if it's a live process */
  3864.         debug(F101,"ttchkpid kill errno","",errno);
  3865.     }
  3866.     debug(F101,"ttchkpid pid test","",x);
  3867.     if (x < 0 && errno == ESRCH) { /* pid is invalid */
  3868.         debug(F111,"removing stale lock",f,pid);
  3869.         if (!backgrd)
  3870.           printf("Removing stale lock %s (pid %d terminated)\n", f, pid);
  3871.         priv_on();
  3872.         x = unlink(f);        /* Remove the lockfile. */
  3873.         priv_off();
  3874.         debug(F111,"ttchkpid unlink",f,x);
  3875.         if (x > -1)
  3876.           return(0);        /* Device is not locked after all */
  3877.         else if (!backgrd)
  3878.           perror(f);
  3879.     }
  3880.     return(1);
  3881.     }
  3882.     return(1);                /* Failure to read pid */
  3883. }
  3884.  
  3885. #ifdef HPUX
  3886.  
  3887. /* Aliases (different drivers) for HP-UX dialout devices: */
  3888.  
  3889. static char *devprefix[] = { "tty", "ttyd", "cul", "cua", "cuad", "culd", "" };
  3890. static int ttydexists = 0;
  3891.  
  3892. #endif /* HPUX */
  3893.  
  3894. /*  T T R P I D  --  Read pid from lockfile "name" */
  3895.  
  3896. static int
  3897. ttrpid(name) char *name; {
  3898.     long len;
  3899.     int x, i, fd, pid, flag;
  3900.     short spid;
  3901.     char buf[32];
  3902.  
  3903.     debug(F110,"ttrpid",name,0);
  3904.     if (!name) return(-1);
  3905.     if (!*name) return(-1);
  3906.     priv_on();
  3907.     len = zchki(name);            /* Get file length */
  3908.     priv_off();
  3909.     debug(F101,"ttrpid zchki","",len);
  3910.     if (len < 0)
  3911.       return(-1);
  3912.     if (len > 31)
  3913.       return(-1);
  3914.     priv_on();
  3915.     fd = open(name,O_RDONLY);        /* Try to open lockfile. */
  3916.     priv_off();
  3917.     debug(F101,"ttrpid fd","",fd);
  3918.     if (fd <= 0)
  3919.       return(-1);
  3920. /*
  3921.   Here we try to be flexible and allow for all different binary and string
  3922.   formats at runtime, rather than a specific format for each configuration
  3923.   hardwired at compile time.
  3924. */
  3925.     pid = -1;
  3926. #ifndef COHERENT
  3927. /*
  3928.   COHERENT uses a string PID but without leading spaces or 0's, so there is
  3929.   no way to tell from the file's length whether it contains a string or binary
  3930.   pid.  So for COHERENT only, we only allow string pids.  For all others, we
  3931.   decide based on the size of the lockfile.
  3932. */
  3933.     if (len > 4) {            /* If file > 4 bytes it's a string */
  3934. #endif /* COHERENT */
  3935.     x = read(fd,buf,len);
  3936.     debug(F111,"ttrpid string read",buf,x);
  3937.     if (x < 0) {
  3938.         pid = -1;
  3939.     } else {
  3940.         buf[31] = '\0';
  3941.         x = sscanf(buf,"%d",&pid);    /* Get the integer pid from it. */
  3942.     }
  3943. #ifndef COHERENT
  3944.     } else if (len == 4) {        /* 4 bytes so binary */
  3945.     x = read(fd, (char *)&pid, 4);    /* Read the bytes into an int */
  3946.     debug(F101,"ttrpid integer read","",x);
  3947.     if (x < 4)
  3948.       pid = -1;
  3949.     } else if (len == 2) {        /* 2 bytes binary */
  3950.     x = read(fd, (char *)&spid, 2);    /* Read the bytes into a short */
  3951.     debug(F101,"ttrpid short read","",x);
  3952.     if (x < 2)
  3953.       pid = -1;
  3954.     else
  3955.       pid = spid;
  3956.     } else
  3957.       pid = -1;
  3958. #endif /* COHERENT */
  3959.     close(fd);                /* Close the lockfile */
  3960.     debug(F101,"ttrpid pid","",pid);
  3961.     return(pid);
  3962. }
  3963. #endif /* NOUUCP */
  3964.  
  3965. /*  T T L O C K  */
  3966.  
  3967. /*
  3968.   This function attempts to coordinate use of the communication device with
  3969.   other copies of Kermit and any other program that follows the UUCP
  3970.   device-locking conventions, which, unfortunately, vary among different UNIX
  3971.   implementations.  The idea is to look for a file of a certain name, the
  3972.   "lockfile", in a certain directory.  If such a file is found, then the line
  3973.   is presumed to be in use, and Kermit should not use it.  If no such file is
  3974.   found, Kermit attempts to create one so that other programs will not use the
  3975.   same line at the same time.  Because the lockfile and/or the directory it's
  3976.   in might lack write permission for the person running Kermit, Kermit could
  3977.   find itself running setuid to uucp or other user that does have the
  3978.   necessary permissions.  At startup, Kermit has changed its effective uid to
  3979.   the user's real uid, and so ttlock() must switch back to the original
  3980.   effective uid in order to create the lockfile, and then back again to the
  3981.   real uid to prevent unauthorized access to other directories or files owned
  3982.   by the user the program is setuid to.
  3983.  
  3984.   Totally rewritten for C-Kermit 5A to eliminate windows of vulnerability,
  3985.   based on suggestions from Warren Tucker.  Call with pointer to name of
  3986.   tty device.  Returns:
  3987.  
  3988.    0 on success
  3989.   -1 on failure
  3990.  
  3991.   Note: Once privileges are turned on using priv_on(), it is essential that
  3992.   they are turned off again before this function returns.
  3993. */
  3994. #ifdef SVR4                /* Lockfile uses device numbers. */
  3995. /*
  3996.   Although I can't find this in writing anywhere (e.g. in SVID for SVR4),
  3997.   it is the behavior of the "reference version" of SVR4, i.e. the Intel
  3998.   port from UNIX Systems Laboratories, then called Univel UnixWare,
  3999.   then called Novell UnixWare, now called SCO Unixware...  It also makes
  4000.   much more sense than device-name-based lockfiles, since there can be
  4001.   multiple names for the same device, symlinks, etc.
  4002. */
  4003. #ifndef LFDEVNO                /* Define this for SVR4 */
  4004. #ifndef AIXRS                /* But not for RS/6000 AIX 3.2, etc. */
  4005. #ifndef BSD44                /* If anybody else needs it... */
  4006. #ifndef __386BSD__
  4007. #ifndef __FreeBSD__
  4008. #ifndef HPUX10
  4009. #ifndef IRIX51                /* SGI IRIX 5.1 or later */
  4010. #ifndef CK_SCOV5            /* SCO Open Server 5.0 */
  4011. #define LFDEVNO
  4012. #endif /* CK_SCOV5 */
  4013. #endif /* IRIX51 */
  4014. #endif /* HPUX10 */
  4015. #endif /* __FreeBSD__ */
  4016. #endif /* __386BSD__ */
  4017. #endif /* BSD44 */
  4018. #endif /* AIXRS */
  4019. #endif /* LFDEVNO */            /* ... define it here or on CC */
  4020. #endif /* SVR4 */            /* command line. */
  4021.  
  4022. #ifdef COHERENT
  4023. #define LFDEVNO
  4024. #endif /* COHERENT */
  4025.  
  4026. /*
  4027.   For platforms where the lockfile name is made from inode/major/minor
  4028.   device number, as in SVR4.  Which, if we must have lockfiles at all, is
  4029.   by far the best format, since it eliminates all the confusion that stems
  4030.   from multiple names (or drivers) for the same port, not to mention
  4031.   symlinks.  It might even be a good idea to start using this form even
  4032.   on platforms where it's not supported, alongside the normal forms for those
  4033.   platforms, in order to get people used to it...
  4034. */
  4035. #ifdef LFDEVNO
  4036. #ifndef major                /* If we didn't find it */
  4037. #ifdef SVR4                /* then for Sys V R4 */
  4038. #include <sys/mkdev.h>            /* look here */
  4039. #else                    /* or for SunOS versions */
  4040. #ifdef SUNOS4                /* ... */
  4041. #include <sys/sysmacros.h>        /* look here */
  4042. #else                    /* Otherwise take a chance: */
  4043. #define    major(dev) ( (int) ( ((unsigned)(dev) >> 8) & 0xff))
  4044. #define    minor(dev) ( (int) ( (dev) & 0xff))
  4045. #endif /* SUNOS4 */
  4046. #endif /* SVR4 */
  4047. #endif /* major */
  4048. #endif /* LFDEVNO */
  4049.  
  4050. /* No advisory locks if F_TLOCK and F_ULOCK are not defined at this point */
  4051.  
  4052. #ifdef LOCKF
  4053. #ifndef F_TLOCK
  4054. #undef LOCKF
  4055. #ifndef NOLOCKF
  4056. #define NOLOCKF
  4057. #endif /* NOLOCKF */
  4058. #endif /* F_TLOCK */
  4059. #endif /* LOCKF */
  4060.  
  4061. #ifdef LOCKF
  4062. #ifndef F_ULOCK
  4063. #undef LOCKF
  4064. #ifndef NOLOCKF
  4065. #define NOLOCKF
  4066. #endif /* NOLOCKF */
  4067. #endif /* F_ULOCK */
  4068. #endif /* LOCKF */
  4069.  
  4070. static char linkto[DEVNAMLEN+1];
  4071. static char * linkdev = NULL;
  4072.  
  4073. #ifndef NOUUCP
  4074. #ifdef USETTYLOCK
  4075. char * uucplockdir = "";
  4076. #else
  4077. #ifdef LOCK_DIR
  4078. char * uucplockdir = LOCK_DIR;
  4079. #else
  4080. char * uucplockdir = "";
  4081. #endif /* LOCK_DIR */
  4082. #endif /* USETTYLOCK */
  4083. #else
  4084. char * uucplockdir = "";
  4085. #endif /* NOUUCP */
  4086.  
  4087. #ifdef QNX
  4088. int                    /* Visible to outside world */
  4089. qnxopencount() {            /* Get QNX device open count */
  4090.     struct _dev_info_entry info;
  4091.     int x;
  4092.  
  4093.     x = -1;                /* Unknown */
  4094.     if (ttyfd > -1) {
  4095.     if (!dev_info(ttyfd, &info)) {
  4096.         debug(F101,"ttlock QNX open_count","",info.open_count);
  4097.         x = info.open_count;
  4098.     }
  4099.     }
  4100.     return(x);
  4101. }
  4102. #endif /* QNX */
  4103.  
  4104. static int
  4105. ttlock(ttdev) char *ttdev; {
  4106.  
  4107.     int x, n;
  4108.     int islink = 0;
  4109.  
  4110. #ifdef NOUUCP
  4111. #ifdef QNX
  4112.     extern int qnxportlock;
  4113.  
  4114.     if ((x = qnxopencount()) < 0)
  4115.       return(x);
  4116.     if (x > 1) {            /* 1 = me */
  4117.     if (qnxportlock)
  4118.       return(-2);            /* Indicate device is in use */
  4119.     else if (!quiet)
  4120.       printf("WARNING: \"%s\" looks busy...\n",ttdev);
  4121.     }
  4122. #endif /* QNX */
  4123.     strcpy(flfnam,"NOLOCK");
  4124.     haslock = 1;
  4125.     return(0);
  4126. #else /* !NOUUCP */
  4127.  
  4128. #ifdef USETTYLOCK
  4129.     haslock = 0;                        /* Not locked yet. */
  4130.     *flfnam = '\0';            /* Lockfile name is empty. */
  4131.     if (!strncmp(ttdev,"/dev/",5) && ttdev[5])
  4132.       ckstrncpy(lockname,ttdev+5,DEVNAMLEN);
  4133.     else
  4134.       ckstrncpy(lockname,ttdev,DEVNAMLEN);
  4135. /*
  4136.   This might be overkill, but it's not clear from the man pages whether
  4137.   ttylock() can be called without calling ttylocked() first, since the doc
  4138.   says that ttylocked() removes any stale lockfiles, but it does not say this
  4139.   about ttylock().  Also the docs don't say what ttylocked() returns in the
  4140.   case when it finds and removes a stale lockfile.  So one or both calls to
  4141.   to ttylocked() might be superfluous, but they should do no harm.  Also I'm
  4142.   assuming that we have to do all the same ID swapping, etc, with these
  4143.   routines as we do without them.  Thus the priv_on/off() sandwich.
  4144. */
  4145. #ifdef USE_UU_LOCK
  4146.     priv_on();                /* Turn on privs */
  4147.     x = uu_lock(lockname);        /* Try to set the lock */
  4148.     priv_off();                /* Turn privs off */
  4149.     debug(F111,"ttlock uu_lock",lockname,x);
  4150.     switch (x) {
  4151.       case UU_LOCK_INUSE:
  4152.     return(-2);
  4153.       case UU_LOCK_OK:
  4154. #ifdef BSD44
  4155.     sprintf(flfnam,"/var/spool/lock/LCK..%s",lockname);
  4156. #endif /* BSD44 */
  4157.     haslock = 1;
  4158.     return(0);
  4159.       default:
  4160.     return(-1);
  4161.     }
  4162. #else  /* USE_UU_LOCK */
  4163.     priv_on();                /* Turn on privs */
  4164.     if (ttylocked(lockname)) {        /* This should remove any stale lock */
  4165.     if (ttylocked(lockname)) {    /* so check again. */
  4166.         priv_off();
  4167.         return(-5);            /* Still locked, fail. */
  4168.     }
  4169.     }
  4170.     x = ttylock(lockname);        /* Lock it. */
  4171.     priv_off();                /* Turn off privs */
  4172.  
  4173.     debug(F111,"ttlock lockname",lockname,x);
  4174.     if (x > -1) {
  4175.     /*
  4176.       We don't really know the name of the lockfile, but
  4177.       this is what the man page says it is.  In USETTYLOCK
  4178.           builds, it is used only for display by SHOW COMM.
  4179.     */
  4180.     sprintf(flfnam,"/etc/locks/LCK..%s",lockname);
  4181.     haslock = 1;
  4182.     }
  4183.     return(x);
  4184. #endif /* USE_UU_LOCK */
  4185. #else  /* Systems that don't have ttylock()... */
  4186.  
  4187. #ifndef HPUX
  4188.  
  4189.     int lockfd;                /* File descriptor for lock file. */
  4190.     PID_T pid;                /* Process id of this process. */
  4191.     int tries;                /* How many times we've tried... */
  4192.     struct stat devbuf;            /* For device numbers (SVR4). */
  4193.  
  4194. #ifdef PIDSTRING
  4195.     char pid_str[12];            /* My pid in string format. */
  4196. #endif /* PIDSTRING */
  4197.  
  4198.     char *device, *devname;
  4199.  
  4200. #define LFNAML 50            /* Max length for lock file name. */
  4201.     char lockfil[LFNAML];        /* Lock file name */
  4202. #ifdef RTAIX
  4203.     char lklockf[LFNAML];        /* Name for link to lock file  */
  4204. #endif /* RTAIX */
  4205. #ifdef CKSYMLINK
  4206.     char symlock[LFNAML];        /* Name for symlink lockfile name */
  4207. #endif /* CKSYMLINK */
  4208.     char tmpnam[LFNAML+30];        /* Temporary lockfile name. */
  4209.     char *lockdir = LOCK_DIR;        /* Defined near top of this file, */
  4210.                     /* or on cc command line. */
  4211.     haslock = 0;                        /* Not locked yet. */
  4212.     *flfnam = '\0';            /* Lockfile name is empty. */
  4213.     lock2[0] = '\0';            /* Clear secondary lockfile name. */
  4214.     pid = getpid();            /* Get id of this process. */
  4215.  
  4216. /*  Construct name of lockfile and temporary file */
  4217.  
  4218. /*  device  = name of tty device without the path, e.g. "ttyh8" */
  4219. /*  lockfil = name of lock file, without path, e.g. "LCK..ttyh8" */
  4220.  
  4221.     device = ((devname = xxlast(ttdev,'/')) != NULL ? devname+1 : ttdev);
  4222.  
  4223.     if (stat(ttdev,&devbuf) < 0)
  4224.       return(-1);
  4225.  
  4226. #ifdef CKSYMLINK
  4227.     islink = 1;                /* Assume it's a symlink */
  4228.     linkto[0] = '\0';            /* But we don't know to what */
  4229. #ifdef COMMENT
  4230. /*
  4231.   This is undependable.  If it worked it would save the readlink call if
  4232.   we knew the device name was not a link.
  4233. */
  4234. #ifdef S_ISLNK
  4235.     islink = S_ISLNK(devbuf.st_mode);
  4236.     debug(F101,"ttlock stat S_ISLNK","",islink);
  4237. #endif /* S_ISLNK */
  4238. #endif /* COMMENT */
  4239.     if (islink) {
  4240.     n = readlink(ttdev,linkto,DEVNAMLEN); /* See if it's a link */
  4241.     debug(F111,"ttlock readlink",ttdev,n);
  4242.     if (n > -1)            /* It is */
  4243.       linkto[n] = '\0';
  4244.     else                /* It's not */
  4245.       islink = 0;
  4246.     debug(F111,"ttlock link",linkto,islink);
  4247.     }
  4248.     if (islink) {
  4249.     linkdev = (devname = xxlast(linkto,'/')) ? devname + 1 : linkto;
  4250.     debug(F110,"ttlock linkdev",linkdev,0);
  4251.     }
  4252. #endif /* CKSYMLINK */
  4253.  
  4254. /*
  4255.   On SCO platforms, if we don't have a symlink, then let's pretend the
  4256.   name given for the device is a symlink, because later we will change
  4257.   the name if it contains any uppercase characters.
  4258. */
  4259. #ifdef CK_SCOV5                /* SCO Open Server 5.0 */
  4260.     if (!islink) {
  4261.     islink = 1;
  4262.     ckstrncpy(linkto,ttdev,DEVNAMLEN);
  4263.     linkdev = (devname = xxlast(linkto,'/')) ? devname + 1 : linkto;
  4264.     debug(F110,"ttlock linkdev",linkdev,0);
  4265.     }
  4266. #else
  4267. #ifdef M_XENIX                /* SCO Xenix or UNIX */
  4268.     if (!islink) {
  4269.     islink = 1;
  4270.     ckstrncpy(linkto,ttdev,DEVNAMLEN);
  4271.     linkdev = (devname = xxlast(linkto,'/')) ? devname + 1 : linkto;
  4272.     debug(F110,"ttlock linkdev",linkdev,0);
  4273.     }
  4274. #endif /* M_XENIX */
  4275. #endif /* CK_SCOV5 */
  4276.  
  4277. #ifdef ISIII                /* Interactive System III, PC/IX */
  4278.     ckstrncpy(lockfil, device, DEVNAMLEN);
  4279. #else  /* not ISIII */
  4280. #ifdef LFDEVNO                /* Lockfilename has device numbers. */
  4281. #ifdef COHERENT
  4282.     sprintf(lockfil,"LCK..%d.%d",
  4283.         major(devbuf.st_rdev),       /* major device number */
  4284.         0x1f & minor(devbuf.st_rdev)); /* minor device number */
  4285. #else
  4286.     sprintf(lockfil,"LK.%03d.%03d.%03d",
  4287.         major(devbuf.st_dev),    /* inode */
  4288.         major(devbuf.st_rdev),    /* major device number */
  4289.         minor(devbuf.st_rdev));    /* minor device number */
  4290. #endif /* COHERENT */
  4291. #else                    /* Others... */
  4292. #ifdef PTX                /* Dynix PTX */
  4293.     if (device != &ttdev[5] && strncmp(ttdev,"/dev/",5)==0) {
  4294.     sprintf(lockfil,"LCK..%.3s%s", &ttdev[5], device);
  4295.     } else
  4296. #endif /* PTX */
  4297.     sprintf(lockfil,"LCK..%s", device);
  4298. #ifdef RTAIX
  4299.     ckstrncpy(lklockf,device,DEVNAMLEN);
  4300. #endif /* RTAIX */
  4301. #ifdef CKSYMLINK
  4302.     symlock[0] = '\0';
  4303.     if (islink)
  4304.       sprintf(symlock,"LCK..%s", linkdev);
  4305. #endif /* CKSYMLINK */
  4306. #endif /* LFDEVNO */
  4307. #endif /* ISIII */
  4308.  
  4309. #ifdef CK_SCOV5                /* SCO Open Server 5.0 */
  4310.     {
  4311.     /* Lowercase the entire filename. */
  4312.         /* SCO says we must do this in V5.0 and later. */
  4313.     /* BUT... watch out for devices -- like Digiboard Portserver */
  4314.     /* That can have hundreds of ports... */
  4315.     char *p = (char *)(lockfil + 5);
  4316.     while (*p) { if (isupper(*p)) *p = (char) tolower(*p); p++; }
  4317.     }
  4318. #ifdef CKSYMLINK
  4319.     if (islink) {            /* If no change */
  4320.     if (!strcmp(lockfil,symlock)) {    /* then no second lockfile needed */
  4321.         islink = 0;
  4322.         symlock[0] = '\0';
  4323.     }
  4324.     }
  4325. #endif /* CKSYMLINK */
  4326. #else
  4327. #ifdef M_XENIX                /* SCO Xenix or UNIX */
  4328.     {
  4329.     int x; char c;
  4330.     x = (int)strlen(lockfil) - 1;    /* Get last letter of device name. */
  4331.     if (x > 0) {            /* If it's uppercase, lower it. */
  4332.         c = lockfil[x];
  4333.         if (c >= 'A' && c <= 'Z') lockfil[x] += ('a' - 'A');
  4334.     }
  4335.     }
  4336. #ifdef CKSYMLINK
  4337.     if (islink) {
  4338.     if (!strcmp(lockfil,symlock)) {    /* No change */
  4339.         islink = 0;            /* so no second lockfile */
  4340.         symlock[0] = '\0';
  4341.     }
  4342.     }
  4343. #endif /* CKSYMLINK */
  4344. #endif /* M_XENIX */
  4345. #endif /* CK_SCOV5 */
  4346.  
  4347. /*  flfnam = full lockfile pathname, e.g. "/usr/spool/uucp/LCK..ttyh8" */
  4348. /*  tmpnam = temporary unique, e.g. "/usr/spool/uucp/LTMP..pid" */
  4349.  
  4350.     sprintf(flfnam,"%s/%s",lockdir,lockfil);
  4351. #ifdef RTAIX
  4352.     sprintf(lkflfn,"%s/%s",lockdir,lklockf);
  4353. #endif /* RTAIX */
  4354. #ifdef CKSYMLINK
  4355.     /* If it's a link then also make a lockfile for the real name */
  4356.     debug(F111,"ttlock link symlock",symlock,islink);
  4357.     if (islink && symlock[0]) {
  4358.     /* But only if the lockfile names would be different. */
  4359.     /* WARNING: They won't be, e.g. for /dev/ttyd2 => /hw/ttys/ttyd2 */
  4360.     sprintf(lock2,"%s/%s",lockdir,symlock); /* No, make 2nd lockfile */
  4361.     debug(F110,"ttlock lock2",lock2,0);
  4362.     if (!strcmp(lock2,flfnam)) {    /* Are lockfile names the same? */
  4363.         debug(F100,"ttlock lock2 cleared","",0);
  4364.         lock2[0] = '\0';        /* Clear secondary lockfile name. */
  4365.     }
  4366.     }
  4367. #endif /* CKSYMLINK */
  4368.     sprintf(tmpnam,"%s/LTMP.%05d",lockdir,(int) pid);
  4369.     debug(F110,"ttlock flfnam",flfnam,0);
  4370.     debug(F110,"ttlock tmpnam",tmpnam,0);
  4371.  
  4372.     priv_on();                /* Turn on privileges if possible. */
  4373.     lockfd = creat(tmpnam, 0444);    /* Try to create temp lock file. */
  4374.     if (lockfd < 0) {            /* Create failed. */
  4375.     debug(F111,"ttlock creat failed",tmpnam,errno);
  4376.     if (errno == ENOENT) {
  4377.         perror(lockdir);
  4378.         printf("UUCP not installed or Kermit misconfigured\n");
  4379.     } else {
  4380.         if (!quiet)
  4381.           perror(lockdir);
  4382.         unlink(tmpnam);        /* Get rid of the temporary file. */
  4383.     }
  4384.     priv_off();            /* Turn off privileges!!! */
  4385.     return(-1);            /* Return failure code. */
  4386.     }
  4387. /* Now write the pid into the temp lockfile in the appropriate format */
  4388.  
  4389. #ifdef PIDSTRING            /* For Honey DanBer UUCP, */
  4390.     sprintf(                /* write PID as decimal string */
  4391.         pid_str,
  4392. #ifdef LINUXFSSTND            /* The "Linux File System Standard" */
  4393. #ifdef FSSTND10                /* Version 1.0 calls for */
  4394.         "%010d\n",            /* leading zeros */
  4395. #else                    /* while version 1.2 calls for */
  4396.         "%10d\n",            /* leading spaces */
  4397. #endif /* FSSTND10 */
  4398. #else
  4399. #ifdef COHERENT
  4400.         "%d\n",            /* with leading nothing */
  4401. #else
  4402.         "%10d\n",            /* with leading blanks */
  4403. #endif /* COHERENT */
  4404. #endif /* LINUXFSSTND */
  4405.         (int) pid
  4406.         );
  4407.     write(lockfd, pid_str, 11);
  4408.     debug(F111,"ttlock hdb pid string",pid_str,(int) pid);
  4409.  
  4410. #else /* Not PIDSTRING, use integer PID */
  4411.  
  4412.     write(lockfd, (char *)&pid, sizeof(pid) );
  4413.     debug(F101,"ttlock pid","",(int) pid);
  4414.  
  4415. #endif /* PIDSTRING */
  4416.  
  4417. /* Now try to rename the temp file to the real lock file name. */
  4418. /* This will fail if a lock file of that name already exists.  */
  4419.  
  4420.     close(lockfd);            /* Close the temp lockfile. */
  4421.     chmod(tmpnam,0444);            /* Permission for a valid lock. */
  4422.     tries = 0;
  4423.     while (!haslock && tries++ < 2) {
  4424.     haslock = (link(tmpnam,flfnam) == 0); /* Create a link to it. */
  4425.     if (haslock) {                  /* If we got the lockfile */
  4426. #ifdef RTAIX
  4427.         link(flfnam,lkflfn);
  4428. #endif /* RTAIX */
  4429. #ifdef CKSYMLINK
  4430.         if (islink && lock2[0])
  4431.           link(flfnam,lock2);
  4432. #endif /* CKSYMLINK */
  4433.  
  4434. #ifdef LOCKF
  4435. /*
  4436.   Advisory file locking works on SVR4, so we use it.  In fact, it is
  4437.   necessary in some cases, e.g. when SLIP is involved.  But it still doesn't
  4438.   seem to prevent multiple users accessing the same device by different names.
  4439. */
  4440.             while (lockf(ttyfd, F_TLOCK, 0L) != 0) {
  4441.                 debug(F111, "ttlock: lockf returns errno", "", errno);
  4442.                 if ((++tries >= 3) || (errno != EAGAIN)) {
  4443.                     x = unlink(flfnam); /* remove the lockfile */
  4444. #ifdef RTAIX
  4445.             unlink(lkflfn);    /* And any links to it... */
  4446. #endif /* RTAIX */
  4447. #ifdef CKSYMLINK
  4448.             if (islink && lock2[0])
  4449.               unlink(lock2);    /* ditto... */
  4450. #endif /* CKSYMLINK */
  4451.                     debug(F111,"ttlock unlink",flfnam,x);
  4452.                     haslock = 0;
  4453.             break;
  4454.         }
  4455.                 sleep(2);
  4456.         }
  4457.         if (haslock)        /* If we got an advisory lock */
  4458. #endif /* LOCKF */
  4459.           break;            /* We're done. */
  4460.  
  4461.     } else {            /* We didn't create a new lockfile. */
  4462.         priv_off();
  4463.         if (ttchkpid(flfnam)) {    /* Check existing lockfile */
  4464.         priv_on();        /* cause ttchkpid turns priv_off... */
  4465.         unlink(tmpnam);        /* Delete the tempfile */
  4466.         debug(F100,"ttlock found tty locked","",0);
  4467.         priv_off();        /* Turn off privs */
  4468.         return(-2);        /* Code for device is in use. */
  4469.         }
  4470.         priv_on();
  4471.     }
  4472.     }
  4473.     unlink(tmpnam);            /* Unlink (remove) the temp file. */
  4474.     priv_off();                /* Turn off privs */
  4475.     return(haslock ? 0 : -1);        /* Return link's return code. */
  4476.  
  4477. #else /* HPUX */
  4478.  
  4479. /*
  4480.   HP-UX gets its own copy of this routine, modeled after the observed behavior
  4481.   of the HP-UX 'cu' program.  HP-UX serial device names consist of a base name
  4482.   such as "tty", "ttyd", "cua", "cul", "cuad", or "culd", followed by a unit
  4483.   designator which is a string of digits, possibly containing an imbedded
  4484.   letter "p".  Examples (for base name "tty"):
  4485.  
  4486.      /dev/tty0, /dev/tty00, dev/ttyd00, /dev/tty0p0
  4487.  
  4488.   According to the HP-UX UUCP manual of 1988, the "0p0" notation has been
  4489.   used on Series 800 since HP-UX 2.00, and the "non-p" notation was used
  4490.   on other models.  In HP-UX 10.00, "0p0" notation was adopted for all models.
  4491.   However, we make and enforce no such distinctions; either notation is
  4492.   accepted on any model or HP-UX version as a valid unit designator.
  4493.  
  4494.   If a valid unit is specified (as opposed to a designer name or symlink), we
  4495.   check for all aliases of the given unit according to the devprefix[] array.
  4496.   If no lockfiles are found for the given unit, we can have the device; we
  4497.   create a lockfile LCK..name in the lockfile directory appropriate for the
  4498.   HP-UX version (/var/spool/locks for 10.00 and later, /usr/spool/uucp for
  4499.   9.xx and earlier).  If it is a "cua" or "cul" device, a second lockfile is
  4500.   created with the "ttyd" prefix.  This is exactly what cu does.
  4501.  
  4502.   If the "set line" device does not have a valid unit designator, then it is
  4503.   used literally and no synomyms are searched for and only one lockfile is
  4504.   created.
  4505.  
  4506.   -fdc, March 1998.
  4507. */
  4508. #define LFNAML 80            /* Max length for lock file name. */
  4509.  
  4510.     int lockfd;                /* File descriptor for lock file. */
  4511.     PID_T pid;                /* Process ID of this process. */
  4512.     int fpid;                /* pid found in existing lockfile. */
  4513.     int tries;                /* How many times we've tried... */
  4514.     int i, k;                /* Workers */
  4515.  
  4516.     char *device, *devname;        /* "/dev/xxx", "xxx" */
  4517.     char *unit, *p;            /* <instance>p<port> part of xxx */
  4518.  
  4519.     char lockfil[LFNAML];        /* Lockfile name (no path) */
  4520.     char tmpnam[LFNAML];        /* Temporary lockfile name. */
  4521.  
  4522. #ifdef HPUX10                /* Lockfile directory */
  4523.     char *lockdir = "/var/spool/locks";    /* Always this for 10.00 and higher */
  4524. #else  /* HP-UX 9.xx and below */
  4525. #ifdef LOCK_DIR
  4526.     char *lockdir = LOCK_DIR;        /* Defined near top of this file */
  4527. #else
  4528.     char *lockdir = "/usr/spool/uucp";    /* or not... */
  4529. #endif /* LOCK_DIR */
  4530. #endif /* HPUX10 */
  4531.  
  4532.     haslock = 0;                        /* Not locked yet. */
  4533.     *flfnam = '\0';            /* Lockfile name is empty. */
  4534.     lock2[0] = '\0';            /* Second one too. */
  4535.     pid = getpid();            /* Get my process ID */
  4536. /*
  4537.   Construct name of lockfile and temporary file...
  4538.   device  = name of tty device without the path, e.g. "tty0p0"
  4539.   lockfil = name of lock file, without path, e.g. "LCK..tty0p0"
  4540. */
  4541.     device = ((devname = xxlast(ttdev,'/')) != NULL ? devname+1 : ttdev);
  4542.     debug(F110,"TTLOCK device",device,0);
  4543.     sprintf(lockfil,"LCK..%s", device);
  4544.  
  4545.     k = 0;                /* Assume device is not locked */
  4546.     n = 0;                /* Digit counter */
  4547.     unit = device;            /* Unit = <instance>p<port> */
  4548.     while (*unit && !isdigit(*unit))    /* Search for digit... */
  4549.       unit++;
  4550.     p = unit;                /* Verify <num>p<num> format... */
  4551.     debug(F110,"TTLOCK unit 1",unit,0);
  4552. /*
  4553.   The unit number is recognized as:
  4554.   (a) any sequence of digits that runs to the end of the string.
  4555.   (b) any (a) that includes one and only one letter "p", with at least
  4556.       one digit before and after it.
  4557. */
  4558.     while (isdigit(*p)) p++, n++;    /* Get a run of digits */
  4559.     if (*p && n > 0) {            /* Have a "p"? */
  4560.     if (*p == 'p' && isdigit(*(p+1))) {
  4561.         p++;
  4562.         n = 0;
  4563.         while (isdigit(*p)) p++, n++;
  4564.     }
  4565.     }
  4566.     if (n == 0 || *p) unit = "";
  4567.     debug(F110,"TTLOCK unit 2",unit,0);
  4568.  
  4569.     if (*unit) {            /* Device name has unit number. */
  4570.     /* The following loop not only searches for the various lockfile    */
  4571.     /* synonyms, but also removes all -- not just one -- stale lockfile */
  4572.     /* for the device, should there be more than one.  See ttchkpid().  */
  4573.     ttydexists = 0;
  4574.     for (i = 0; *devprefix[i]; i++) { /* For each driver... */
  4575.         /* Make device name */
  4576.         sprintf(lock2,"/dev/%s%s",devprefix[i],unit);
  4577.         priv_on();            /* Privs on */
  4578.         k = zchki(lock2) != -1;    /* See if device exists */
  4579.         priv_off();            /* Privs off */
  4580.         debug(F111,"TTLOCK exist",lock2,k);
  4581.             if (k) {
  4582.         if (!strcmp(devprefix[i],"ttyd")) /* ttyd device exists */
  4583.           ttydexists = 1;
  4584.         /* Make lockfile name */
  4585.         sprintf(lock2,"%s/LCK..%s%s",lockdir,devprefix[i],unit);
  4586.         debug(F110,"TTLOCK checking",lock2,0);
  4587.         priv_on();        /* Privs on */
  4588.         k = zchki(lock2) != -1;    /* See if lockfile exists */
  4589.         priv_off();        /* Privs off */
  4590.         debug(F111,"TTLOCK check for lock A",lock2,k);
  4591.         if (k) if (ttchkpid(lock2)) { /* If pid still active, fail. */
  4592.             ckstrncpy(flfnam,lock2,FLFNAML);
  4593.             return(-2);
  4594.         }
  4595.         }
  4596.     }
  4597.     } else {                /* Some other device-name format */
  4598.     /* This takes care of symbolic links, etc... */
  4599.     /* But does not chase them down! */
  4600.     sprintf(lock2,"%s/LCK..%s",lockdir,device); /* Use the name as-is */
  4601.     priv_on();
  4602.     k = zchki(lock2) != -1;        /* Check for existing lockfile */
  4603.     priv_off();
  4604.     debug(F111,"TTLOCK check for lock B",lock2,k);
  4605.     if (k) if (ttchkpid(lock2)) {    /* Check pid from lockfile */
  4606.         ckstrncpy(flfnam,lock2,FLFNAML);
  4607.         debug(F110,"TTLOCK in use",device,0);
  4608.         debug(F101,"TTLOCK returns","",-2);
  4609.         return(-2);
  4610.     }
  4611.     }
  4612. /*
  4613.   Get here only if there is no (more) lockfile, so now we make one (or two)...
  4614.   flfnam = full lockfile pathname, e.g. "/usr/spool/uucp/LCK..cul0p0".
  4615.   tmpnam = unique temporary filname, e.g. "/usr/spool/uucp/LTMP..pid".
  4616. */
  4617.     sprintf(flfnam,"%s/%s",lockdir,lockfil); /* Our SET LINE device */
  4618.  
  4619.     /* If dialout device, also make one for corresponding dialin device */
  4620.     lock2[0] = '\0';
  4621.     if (!strncmp(device,"cu",2) && *unit && ttydexists)
  4622.       sprintf(lock2, "%s/LCK..ttyd%s", lockdir, unit);
  4623.  
  4624.     sprintf(tmpnam,"%s/LTMP.%05d",lockdir,(int) pid); /* Make temporary name */
  4625. #ifdef DEBUG
  4626.     if (deblog) {
  4627.     debug(F110,"TTLOCK flfnam",flfnam,0);
  4628.     debug(F110,"TTLOCK lock2",lock2,0);
  4629.     debug(F110,"TTLOCK tmpnam",tmpnam,0);
  4630.     }
  4631. #endif /* DEBUG */
  4632. /*
  4633.    Lockfile permissions...
  4634.    444 is standard, HP-UX 10.00 uses 664.  It doesn't matter.
  4635.    Kermit uses 444; the difference lets us tell whether Kermit created
  4636.    the lock file.
  4637. */
  4638.     priv_on();                /* Turn on privileges. */
  4639.     lockfd = creat(tmpnam, 0444);    /* Try to create temporary file. */
  4640.     if (lockfd < 0) {            /* Create failed. */
  4641.     debug(F111,"TTLOCK creat failed",tmpnam,errno);
  4642.     if (errno == ENOENT) {
  4643.         perror(lockdir);
  4644.         printf("UUCP not installed or Kermit misconfigured\n");
  4645.     } else {
  4646.         if (!quiet)
  4647.           perror(lockdir);
  4648.         unlink(tmpnam);        /* Get rid of the temporary file. */
  4649.     }
  4650.     priv_off();            /* Turn off privileges!!! */
  4651.     debug(F101,"TTLOCK returns","",-1);
  4652.     return(-1);            /* Return failure code. */
  4653.     }
  4654.     debug(F110,"TTLOCK temp ok",tmpnam,0);
  4655.  
  4656. /* Now write our pid into the temp lockfile in integer format. */
  4657.  
  4658.     i = write(lockfd, (char *)&pid, sizeof(pid));
  4659.  
  4660. #ifdef DEBUG
  4661.     if (deblog) {
  4662.     debug(F101,"TTLOCK pid","",pid);
  4663.     debug(F101,"TTLOCK sizeof pid","",sizeof(pid));
  4664.     debug(F101,"TTLOCK write pid returns","",i);
  4665.     }
  4666. #endif /* DEBUG */
  4667.  
  4668. /*
  4669.   Now try to rename the temporary file to the real lockfile name.
  4670.   This will fail if a lock file of that name already exists, which
  4671.   will catch race conditions with other users.
  4672. */
  4673.     close(lockfd);            /* Close the temp lockfile. */
  4674.     chmod(tmpnam,0444);
  4675.  
  4676.     tries = 0;
  4677.     while (!haslock && tries++ < 2) {
  4678.     haslock = (link(tmpnam,flfnam) == 0); /* Create a link to it. */
  4679.     debug(F101,"TTLOCK link","",haslock);
  4680.     if (haslock) {            /* If we made the lockfile... */
  4681.  
  4682. #ifdef LOCKF                /* Can be canceled with -DNOLOCKF */
  4683. /*
  4684.   Create an advisory lock on the device through its file descriptor.
  4685.   This code actually seems to work.  If it is executed, and then another
  4686.   process tries to open the same device under a different name to circumvent
  4687.   the lockfile, they get a "device busy" error.
  4688. */
  4689.         debug(F100,"TTLOCK LOCKF code...","",0);
  4690.             while ( lockf(ttyfd, F_TLOCK, 0L) != 0 ) {
  4691.                 debug(F111, "TTLOCK lockf error", "", errno);
  4692.                 if ((++tries >= 3) || (errno != EAGAIN)) {
  4693.                     x = unlink(flfnam); /* Remove the lockfile */
  4694.             if (errno == EACCES && !quiet)
  4695.               printf("Device already locked by another process\n");
  4696.                     haslock = 0;
  4697.             break;
  4698.         }
  4699.                 sleep(2);
  4700.         }
  4701. #endif /* LOCKF */
  4702.  
  4703.         if (haslock) {        /* If we made the lockfile ... */
  4704.         if (lock2[0]) {        /* if there is to be a 2nd lockfile */
  4705.             lockfd = creat(lock2, 0444); /* Create it */
  4706.             debug(F111,"TTLOCK lock2 creat", lock2, lockfd);
  4707.             if (lockfd > -1) {    /* Created OK, write pid. */
  4708.             write(lockfd, (char *)&pid, sizeof(pid) );
  4709.             close(lockfd);    /* Close and */
  4710.             chmod(lock2, 0444); /* set permissions. */
  4711.             } else {         /* Not OK, but don't fail. */
  4712.             lock2[0] = '\0'; /* Just remember it's not there. */
  4713.             }
  4714.         }
  4715.         break;            /* and we're done. */
  4716.         }
  4717.     }
  4718.     }
  4719.     unlink(tmpnam);            /* Unlink (remove) the temp file. */
  4720.     priv_off();                /* Turn off privs */
  4721.     i = haslock ? 0 : -1;        /* Our return value */
  4722.     debug(F101,"TTLOCK returns","",i);
  4723.     return(i);
  4724. #endif /* HPUX */
  4725. #endif /* USETTYLOCK */
  4726. #endif /* !NOUUCP */
  4727. }
  4728.  
  4729. /*  T T U N L O C K  */
  4730.  
  4731. static int
  4732. ttunlck() {                             /* Remove UUCP lockfile(s). */
  4733. #ifndef NOUUCP
  4734.     int x;
  4735.  
  4736.     debug(F111,"ttunlck",flfnam,haslock);
  4737.  
  4738. #ifdef USETTYLOCK
  4739.  
  4740.     if (haslock && *flfnam) {
  4741.     int x;
  4742.     priv_on();            /* Turn on privs */
  4743. #ifdef USE_UU_LOCK
  4744.     x = uu_unlock(lockname);
  4745. #else  /* USE_UU_LOCK */
  4746.     x = ttyunlock(lockname);    /* Try to unlock */
  4747. #endif /* USE_UU_LOCK */
  4748.     priv_off();            /* Turn off privs */
  4749.     if (x < 0 && !quiet)
  4750.       printf("Warning - Can't remove lockfile: %s\n", flfnam);
  4751.  
  4752.     *flfnam = '\0';            /* Erase the name. */
  4753.     haslock = 0;
  4754.     return(0);
  4755.     }
  4756.  
  4757. #else  /* No ttylock()... */
  4758.  
  4759.     if (haslock && *flfnam) {
  4760.     /* Don't remove lockfile if we didn't make it ourselves */
  4761.     if ((x = ttrpid(flfnam)) != (int)getpid()) {
  4762.         debug(F111,"ttunlck lockfile seized",flfnam,x);
  4763.         printf("Warning - Lockfile %s seized by pid %d\n",
  4764.            flfnam,
  4765.            x
  4766.            );
  4767.         return(0);
  4768.     }
  4769.     priv_on();            /* Turn privileges on.  */
  4770.     errno = 0;
  4771.     x = unlink(flfnam);        /* Remove the lockfile. */
  4772.     debug(F111,"ttunlck unlink",flfnam,x);
  4773.     if (x < 0) {
  4774.         if (errno && !quiet)
  4775.           perror(ttnmsv);
  4776.         printf("Warning - Can't remove lockfile: %s\n", flfnam);
  4777.     }
  4778.     haslock = 0;
  4779.     *flfnam = '\0';            /* Erase the name. */
  4780.  
  4781. #ifdef RTAIX
  4782.     errno = 0;
  4783.     x = unlink(lkflfn);        /* Remove link to lockfile */
  4784.     debug(F111,"ttunlck AIX link unlink",lkflfn,x);
  4785.     if (x < 0) {
  4786.         if (errno && !quiet)
  4787.           perror(ttnmsv);
  4788.         printf("Warning - Can't remove link to lockfile: %s\n", lkflfn);
  4789.     }
  4790.     *lkflfn = '\0';
  4791. #else
  4792.     if (lock2[0]) {            /* If there is a second lockfile, */
  4793.         errno = 0;
  4794.         x = unlink(lock2);        /*  remove it too. */
  4795.         debug(F111,"ttunlck lock2 unlink",lock2,x);
  4796.         if (x < 0) {
  4797.         if (errno && !quiet)
  4798.           perror(ttnmsv);
  4799.         printf("Warning - Can't remove secondary lockfile: %s\n",
  4800.                lock2
  4801.                );
  4802.         }
  4803.         lock2[0] = '\0';        /* Forget its name. */
  4804.     }
  4805. #endif /* RTAIX */
  4806.  
  4807. #ifdef LOCKF
  4808.         (VOID) lockf(ttyfd, F_ULOCK, 0L); /* Remove advisory lock */
  4809. #endif /* LOCKF */
  4810.     priv_off();            /* Turn privileges off. */
  4811.     }
  4812. #endif /* USETTYLOCK */
  4813. #endif /* !NOUUCP */
  4814.     return(0);
  4815. }
  4816.  
  4817. /*
  4818.   4.3BSD-style UUCP line direction control.
  4819.   (Stan Barber, Rice U, 1980-something...)
  4820. */
  4821. #ifndef NOUUCP
  4822. #ifdef ACUCNTRL
  4823. VOID
  4824. acucntrl(flag,ttname) char *flag, *ttname; {
  4825.     char x[DEVNAMLEN+32], *device, *devname;
  4826.  
  4827.     if (strcmp(ttname,CTTNAM) == 0 || xlocal == 0) /* If not local, */
  4828.       return;                /* just return. */
  4829.     device = ((devname = xxlast(ttname,'/')) != NULL ? devname+1 : ttname);
  4830.     if (strncmp(device,"LCK..",4) == 0) device += 5;
  4831.     sprintf(x,"/usr/lib/uucp/acucntrl %s %s",flag,device);
  4832.     debug(F110,"called ",x,0);
  4833.     zsyscmd(x);
  4834. }
  4835. #endif /* ACUCNTRL */
  4836. #endif /* NOUUCP */
  4837.  
  4838. /*
  4839.   T T H F L O W  --  Set or Reset hardware flow control.
  4840.  
  4841.   This is an attempt to collect all hardware-flow-control related code
  4842.   into a single module.  Thanks to Rick Sladkey and John Kohl for lots of
  4843.   help here.  Overview:
  4844.  
  4845.   Hardware flow control is not supported in many UNIX implementions.  Even
  4846.   when it is supported, there is no (ha ha) "standard" for the programming
  4847.   interface.  In general, 4.3BSD and earlier (sometimes), 4.4BSD, System V,
  4848.   SunOS, AIX, etc, have totally different methods.  (And, not strictly
  4849.   relevant here, the programming interface often brings one only to a no-op
  4850.   in the device driver!)
  4851.  
  4852.   Among all these, we have two major types of APIs: those in which hardware
  4853.   flow control is determined by bits in the same termio/termios/sgtty mode
  4854.   word(s) that are used for controlling such items as CBREAK vs RAW mode, and
  4855.   which are also used by the ttvt(), ttpkt(), conbin(), and concb() routines
  4856.   for changing terminal modes.  And those that use entirely different
  4857.   mechanisms.
  4858.  
  4859.   In the first category, it is important that any change in the mode bits be
  4860.   reflected in the relevant termio(s)/sgtty structure, so that subsequent
  4861.   changes to that structure do not wipe out the effects of this routine.  That
  4862.   is why a pointer, attrs, to the appropriate structure is passed as a
  4863.   parameter to this routine.
  4864.  
  4865.   The second category should give us no worries, since any changes to hardware
  4866.   flow control accomplished by this routine should not affect the termio(s)/
  4867.   sgtty structures, and therefore will not be undone by later changes to them.
  4868.  
  4869.   The second argument, status, means to turn on hardware flow control if
  4870.   nonzero, and to turn it off if zero.
  4871.  
  4872.   Returns: 0 on apparent success, -1 on probable failure.
  4873. */
  4874. static int
  4875. tthflow(flow, status, attrs)
  4876.     int flow,                /* Type of flow control (ckcdeb.h) */
  4877.     status;                /* Nonzero = turn it on */
  4878.                     /* Zero = turn it off */
  4879. #ifdef BSD44ORPOSIX            /* POSIX or BSD44 */
  4880.     struct termios *attrs;
  4881. #else                    /* System V */
  4882. #ifdef ATTSV
  4883. #ifdef ATT7300
  4884. #ifdef UNIX351M
  4885. /* AT&T UNIX 3.51m can set but not test for hardware flow control */
  4886. #define RTSFLOW CTSCD
  4887. #define CTSFLOW CTSCD
  4888. #endif /* ATT7300 */
  4889. #endif /* UNIX351M */
  4890.     struct termio *attrs;
  4891. #else                    /* BSD, V7, etc */
  4892.     struct sgttyb *attrs;        /* sgtty info... */
  4893. #endif /* ATTSV */
  4894. #endif /* BSD44ORPOSIX */
  4895. /* tthflow */ {
  4896.  
  4897.     int x = 0;                /* tthflow() return code */
  4898.  
  4899. #ifdef Plan9
  4900.     return p9tthflow(flow, status);
  4901. #else
  4902.  
  4903. #ifndef OXOS                /* NOT Olivetti X/OS... */
  4904. /*
  4905.   For SunOS 4.0 and later in the BSD environment ...
  4906.  
  4907.   The declarations are copied and interpreted from the System V header files,
  4908.   so we don't actually have to pull in all the System V junk when building
  4909.   C-Kermit for SunOS in the BSD environment, which would be dangerous because
  4910.   having those symbols defined would cause us to take the wrong paths through
  4911.   the code.  The code in this section is used in both the BSD and Sys V SunOS
  4912.   versions.
  4913. */
  4914. #ifdef SUNOS41
  4915. /*
  4916.   In SunOS 4.1 and later, we use the POSIX calls rather than ioctl calls
  4917.   because GNU CC uses different formats for the _IOxxx macros than regular CC;
  4918.   the POSIX forms work for both.  But the POSIX calls are not available in
  4919.   SunOS 4.0.
  4920. */
  4921. #define CRTSCTS 0x80000000        /* RTS/CTS flow control */
  4922. #define TCSANOW 0            /* Do it now */
  4923.  
  4924.     struct termios {
  4925.     unsigned long c_iflag;        /* Input modes */
  4926.     unsigned long c_oflag;        /* Output modes */
  4927.     unsigned long c_cflag;        /* Control modes */
  4928.     unsigned long c_lflag;        /* Line discipline modes */
  4929.     char c_line;
  4930.     CHAR c_cc[17];
  4931.     };
  4932.     struct termios temp;
  4933.  
  4934. _PROTOTYP( int tcgetattr, (int, struct termios *) );
  4935. _PROTOTYP( int tcsetattr, (int, int, struct termios *) );
  4936. /*
  4937.   When CRTSCTS is set, SunOS won't do output unless both CTS and CD are
  4938.   asserted.  So we don't set CRTSCTS unless CD is up.  This should be OK,
  4939.   since we don't need RTS/CTS during dialing, and after dialing is complete,
  4940.   we should have CD.  If not, we still communicate, but without RTS/CTS.
  4941. */
  4942.     int mflags;                /* Modem signal flags */
  4943.  
  4944. #ifdef NETCMD
  4945.     if (ttpipe) return(0);
  4946. #endif /* NETCMD */
  4947. #ifdef NETPTY
  4948.     if (ttpty) return(0);
  4949. #endif /* NETPTY */
  4950.  
  4951.     debug(F101,"tthflow SUNOS41 entry status","",status);
  4952.     if (!status) {            /* Turn hard flow off */
  4953.     if (tcgetattr(ttyfd, &temp) > -1 && /* Get device attributes */
  4954.         (temp.c_cflag & CRTSCTS)) { /* Check for RTS/CTS */
  4955.         temp.c_cflag &= ~CRTSCTS;    /* It's there, remove it */
  4956.         x = tcsetattr(ttyfd,TCSANOW,&temp);
  4957.     }
  4958.     } else {                /* Turn hard flow on */
  4959.     if (ioctl(ttyfd,TIOCMGET,&mflags) > -1 && /* Get modem signals */
  4960.         (mflags & TIOCM_CAR)) {        /* Check for CD */
  4961.         debug(F100,"tthflow SunOS has CD","",0);
  4962.         if (tcgetattr(ttyfd, &temp) > -1 && /* Get device attributes */
  4963.         !(temp.c_cflag & CRTSCTS)) { /* Check for RTS/CTS */
  4964.         temp.c_cflag |= CRTSCTS;    /* Not there, add it */
  4965.         x = tcsetattr(ttyfd,TCSANOW,&temp);
  4966.         }
  4967.     } else {
  4968.         x = -1;
  4969.         debug(F100,"tthflow SunOS no CD","",0);
  4970.     }
  4971.     }
  4972. #else
  4973. #ifdef QNX
  4974.     struct termios temp;
  4975. #ifdef NETCMD
  4976.     if (ttpipe) return(0);
  4977. #endif /* NETCMD */
  4978. #ifdef NETPTY
  4979.     if (ttpty) return(0);
  4980. #endif /* NETPTY */
  4981.     debug(F101,"tthflow QNX entry status","",status);
  4982.     if (tcgetattr(ttyfd, &temp) > -1) {    /* Get device attributes */
  4983.     if (!status) {            /* Turn hard flow off */
  4984.         if ((temp.c_cflag & (IHFLOW|OHFLOW)) == (IHFLOW|OHFLOW)) {
  4985.         temp.c_cflag &= ~(IHFLOW|OHFLOW); /* It's there, remove it */
  4986.         attrs->c_cflag &= ~(IHFLOW|OHFLOW);
  4987.         x = tcsetattr(ttyfd,TCSANOW,&temp);
  4988.         }
  4989.     } else {            /* Turn hard flow on */
  4990.         if ((temp.c_cflag & (IHFLOW|OHFLOW)) != (IHFLOW|OHFLOW)) {
  4991.         temp.c_cflag |= (IHFLOW|OHFLOW); /* Not there, add it */
  4992.         temp.c_iflag &= ~(IXON|IXOFF);   /* Bye to IXON/IXOFF */
  4993.         ttraw.c_lflag |= IEXTEN;         /* Must be on */
  4994.         x = tcsetattr(ttyfd,TCSANOW,&temp);
  4995.         attrs->c_cflag |= (IHFLOW|OHFLOW);
  4996.         attrs->c_iflag &= ~(IXON|IXOFF);
  4997.         }
  4998.     }
  4999.     } else {
  5000.     x = -1;
  5001.     debug(F100, "tthflow QNX getattr fails", "", 0);
  5002.     }
  5003. #else
  5004. #ifdef POSIX_CRTSCTS
  5005. /*
  5006.   POSIX_CRTSCTS is defined in ckcdeb.h or on CC command line.
  5007.   Note: Do not assume CRTSCTS is a one-bit field!
  5008. */
  5009.     struct termios temp;
  5010. #ifdef NETCMD
  5011.     if (ttpipe) return(0);
  5012. #endif /* NETCMD */
  5013. #ifdef NETPTY
  5014.     if (ttpty) return(0);
  5015. #endif /* NETPTY */
  5016.     debug(F101,"tthflow POSIX_CRTSCTS entry status","",status);
  5017.     errno = 0;
  5018.     x = tcgetattr(ttyfd, &temp);
  5019.     debug(F111,"tthflow POSIX_CRTSCTS tcgetattr",ckitoa(x),errno);
  5020.     errno = 0;
  5021.     if (x < 0) {
  5022.     x = -1;
  5023.     } else {
  5024.     if (!status) {            /* Turn hard flow off */
  5025.         if (
  5026. #ifdef COMMENT
  5027.         /* This can fail because of sign extension */
  5028.         /* e.g. in Linux where it's Bit 31 */
  5029.         (temp.c_cflag & CRTSCTS) == CRTSCTS
  5030. #else
  5031.         (temp.c_cflag & CRTSCTS) != 0
  5032. #endif /* COMMENT */
  5033.         ) {
  5034.         temp.c_cflag &= ~CRTSCTS;    /* It's there, remove it */
  5035.         attrs->c_cflag &= ~CRTSCTS;
  5036.         x = tcsetattr(ttyfd,TCSANOW,&temp);
  5037.         debug(F111,"tthflow POSIX_CRTSCTS OFF tcsetattr",
  5038.               ckitoa(x),errno);
  5039.         }
  5040.     } else {            /* Turn hard flow on */
  5041.         if (
  5042. #ifdef COMMENT
  5043.         /* This can fail because of sign extension */
  5044.         (temp.c_cflag & CRTSCTS) != CRTSCTS
  5045. #else
  5046.         (temp.c_cflag & CRTSCTS) == 0
  5047. #endif /* COMMENT */
  5048.         ) {
  5049.         temp.c_cflag |= CRTSCTS; /* Not there, add it */
  5050.         temp.c_iflag &= ~(IXON|IXOFF|IXANY); /* Bye to IXON/IXOFF */
  5051.         x = tcsetattr(ttyfd,TCSANOW,&temp);
  5052.         debug(F111,"tthflow POSIX_CRTSCTS ON tcsetattr",
  5053.               ckitoa(x),errno);
  5054.         attrs->c_cflag |= CRTSCTS;
  5055.         attrs->c_iflag &= ~(IXON|IXOFF|IXANY);
  5056.         }
  5057.     }
  5058.     }
  5059. #else
  5060. #ifdef SUNOS4
  5061. /*
  5062.   SunOS 4.0 (and maybe earlier?).  This code is dangerous because it
  5063.   prevents compilation with GNU gcc, which uses different formats for the
  5064.   _IORxxx macros than regular cc.  SunOS 4.1 and later can use the POSIX
  5065.   routines above, which work for both cc and gcc.
  5066. */
  5067. #define TCGETS _IOR(T, 8, struct termios) /* Get modes into termios struct */
  5068. #define TCSETS _IOW(T, 9, struct termios) /* Set modes from termios struct */
  5069. #define CRTSCTS 0x80000000          /* RTS/CTS flow control */
  5070.  
  5071.     struct termios {
  5072.     unsigned long c_iflag;        /* Input modes */
  5073.     unsigned long c_oflag;        /* Output modes */
  5074.     unsigned long c_cflag;        /* Control modes */
  5075.     unsigned long c_lflag;        /* Line discipline modes */
  5076.     char c_line;
  5077.     CHAR c_cc[17];
  5078.     };
  5079.     struct termios temp;
  5080. #ifdef NETCMD
  5081.     if (ttpipe) return(0);
  5082. #endif /* NETCMD */
  5083. #ifdef NETPTY
  5084.     if (ttpty) return(0);
  5085. #endif /* NETPTY */
  5086.     debug(F101,"tthflow entry status","",status);
  5087.     if (ioctl(ttyfd,TCGETS,&temp) > -1) { /* Get terminal modes. */
  5088.     if (status) {            /* Turn hard flow on */
  5089.         temp.c_cflag |= CRTSCTS;    /* Add RTS/CTS to them. */
  5090.         x = ioctl(ttyfd,TCSETS,&temp); /* Set them again. */
  5091.         attrs->c_cflag |= CRTSCTS;    /* Add to global info. */
  5092.     } else {            /* Turn hard flow off */
  5093.         temp.c_cflag &= ~CRTSCTS;
  5094.         x = ioctl(ttyfd,TCSETS,&temp);
  5095.         attrs->c_cflag &= ~CRTSCTS;
  5096.     }
  5097.     }
  5098. #else                    /* Not SunOS 4.0 or later */
  5099. #ifdef AIXRS                /* IBM AIX RS/6000 */
  5100. #ifndef AIX41                /* But only pre-4.x == SVR4 */
  5101. #ifdef NETCMD
  5102.     if (ttpipe) return(0);
  5103. #endif /* NETCMD */
  5104. #ifdef NETPTY
  5105.     if (ttpty) return(0);
  5106. #endif /* NETPTY */
  5107.     if (status) {
  5108.     if ((x = ioctl(ttyfd, TXADDCD, "rts")) < 0 && errno != EBUSY)
  5109.       debug(F100,"hardflow TXADDCD (rts) error", "", 0);
  5110.     } else {
  5111.     if ((x = ioctl(ttyfd, TXDELCD, "rts")) < 0 && errno != EINVAL)
  5112.       debug(F100,"hardflow TXDELCD (rts) error", "", 0);
  5113.     }
  5114. #endif /* AIX41 */
  5115. #else                    /* Not AIX RS/6000 */
  5116.  
  5117. #ifdef ATTSV                /* System V... */
  5118.  
  5119. #ifdef CK_SCOV5                /* SCO Open Server 5.0 */
  5120. #define CK_SCOUNIX
  5121. #else
  5122. #ifdef M_UNIX                /* SCO UNIX 3.2v4.x or earlier */
  5123. #define CK_SCOUNIX
  5124. #endif /* M_UNIX */
  5125. #endif /* CK_SCOV5 */
  5126.  
  5127. #ifdef SCO_FORCE_RTSXOFF
  5128. #ifdef CK_SCOUNIX            /* But not SCO OpenServer 5.0.4 */
  5129. #ifdef SCO_OSR504            /* or later... */
  5130. #undef CK_SCOUNIX
  5131. #endif /* SCO_OSR504 */
  5132. #endif /* CK_SCOUNIX */
  5133. #endif /* SCO_FORCE_RTSXOFF */
  5134.  
  5135. #ifdef CK_SCOUNIX
  5136. #ifdef POSIX
  5137.     struct termios temp;
  5138. #ifdef NETCMD
  5139.     if (ttpipe) return(0);
  5140. #endif /* NETCMD */
  5141. #ifdef NETPTY
  5142.     if (ttpty) return(0);
  5143. #endif /* NETPTY */
  5144.     debug(F101,"tthflow SCOUNIX POSIX entry status","",status);
  5145.     errno = 0;
  5146.     x = tcgetattr(ttyfd, &temp);
  5147.     debug(F111,"tthflow SCO UNIX POSIX tcgetattr",ckitoa(x),errno);
  5148. #else /* POSIX */
  5149.     struct termio temp;
  5150. #ifdef NETCMD
  5151.     if (ttpipe) return(0);
  5152. #endif /* NETCMD */
  5153. #ifdef NETPTY
  5154.     if (ttpty) return(0);
  5155. #endif /* NETPTY */
  5156.     debug(F101,"tthflow SCOUNIX non-POSIX entry status","",status);
  5157.     x = ioctl(ttyfd, TCGETA, &temp);
  5158.     debug(F111,"tthflow SCO UNIX non-POSIX TCGETA",ckitoa(x),errno);
  5159. #endif /* POSIX */
  5160. /*
  5161.   This is not really POSIX, since POSIX does not deal with hardware flow
  5162.   control, but we are using the POSIX APIs.  In fact, RTSFLOW and CTSFLOW
  5163.   are defined in termio.h, but within #ifndef _POSIX_SOURCE..#endif.  So
  5164.   let's try forcing their definitions here.
  5165. */
  5166. #ifndef CTSFLOW
  5167. #define CTSFLOW 0020000
  5168.     debug(F101,"tthflow SCO defining CTSFLOW","",CTSFLOW);
  5169. #else
  5170.     debug(F101,"tthflow SCO CTSFLOW","",CTSFLOW);
  5171. #endif /* CTSFLOW */
  5172. #ifndef RTSFLOW
  5173. #define RTSFLOW 0040000
  5174.     debug(F101,"tthflow SCO defining RTSFLOW","",RTSFLOW);
  5175. #else
  5176.     debug(F101,"tthflow SCO RTSFLOW","",RTSFLOW);
  5177. #endif /* RTSFLOW */
  5178. #ifndef ORTSFL
  5179. #define ORTSFL 0100000
  5180.     debug(F101,"tthflow SCO defining ORTSFL","",ORTSFL);
  5181. #else
  5182.     debug(F101,"tthflow SCO ORTSFL","",ORTSFL);
  5183. #endif /* ORTSFL */
  5184.  
  5185.     if (x != -1) {
  5186.     if (status) {            /* Turn it ON */
  5187.         temp.c_cflag |= RTSFLOW|CTSFLOW;
  5188.         attrs->c_cflag |= RTSFLOW|CTSFLOW;
  5189. #ifdef ORTSFL
  5190.         temp.c_cflag &= ~ORTSFL;
  5191.         attrs->c_cflag &= ~ORTSFL;
  5192. #endif /* ORTSFL */
  5193.         temp.c_iflag &= ~(IXON|IXOFF|IXANY);
  5194.         attrs->c_iflag &= ~(IXON|IXOFF|IXANY);
  5195.     } else {            /* Turn it OFF */
  5196. #ifdef ORTSFL
  5197.         temp.c_cflag &= ~(RTSFLOW|CTSFLOW|ORTSFL);
  5198.         attrs->c_cflag &= ~(RTSFLOW|CTSFLOW|ORTSFL);
  5199. #else  /* ORTSFL */
  5200.         temp.c_cflag &= ~(RTSFLOW|CTSFLOW);
  5201.         attrs->c_cflag &= ~(RTSFLOW|CTSFLOW);
  5202. #endif /* ORTSFL */
  5203.     }
  5204. #ifdef POSIX
  5205.     x = tcsetattr(ttyfd, TCSADRAIN, &temp);
  5206. #else
  5207.     x = ioctl(ttyfd, TCSETA, &temp);
  5208. #endif /* POSIX */
  5209.     debug(F101,"tthflow SCO set modes","",x);
  5210.     }
  5211. #else /* Not SCO UNIX */
  5212. #ifdef NETCMD
  5213.     if (ttpipe) return(0);
  5214. #endif /* NETCMD */
  5215. #ifdef NETPTY
  5216.     if (ttpty) return(0);
  5217. #endif /* NETPTY */
  5218.     if (!status) {            /* Turn it OFF */
  5219. #ifdef RTSXOFF
  5220.     debug(F100,"tthflow ATTSV RTS/CTS OFF","",0);
  5221.     rctsx.x_hflag &= ~(RTSXOFF|CTSXON);
  5222. #ifdef TCSETX
  5223.     x = ioctl(ttyfd,TCSETX,&rctsx);
  5224.     debug(F101,"tthflow ATTSV TCSETX OFF","",x);
  5225. #else
  5226.     x = -1
  5227.     debug(F100,"tthflow TCSETX not defined","",0);
  5228. #endif /* TCSETX */
  5229. #else
  5230.     debug(F100,"tthflow ATTSV RTSXOFF not defined","",0);
  5231. #endif /* RTSXOFF */
  5232. #ifdef DTRXOFF
  5233.     debug(F100,"tthflow ATTSV DTR/CD OFF","",0);
  5234.     rctsx.x_hflag &= ~(DTRXOFF|CDXON);
  5235.     x = ioctl(ttyfd,TCSETX,&rctsx);
  5236.     debug(F101,"tthflow ATTSV DTRXOFF OFF","",x);
  5237. #else
  5238.     debug(F100,"tthflow ATTSV DTRXOFF not defined","",0);
  5239. #endif /* DTRXOFF */
  5240.     } else {                /* Turn it ON. */
  5241.     if (flow == FLO_RTSC) {    /* RTS/CTS Flow control... */
  5242.         debug(F100,"tthflow ATTSV RTS/CTS ON","",0);
  5243. #ifdef RTSXOFF
  5244.         /* This is the preferred way, according to SVID3 */
  5245. #ifdef TCGETX
  5246.         x = ioctl(ttyfd,TCGETX,&rctsx);
  5247.         debug(F101,"tthflow TCGETX","",x);
  5248.         if (x > -1) {
  5249.         rctsx.x_hflag |= RTSXOFF | CTSXON;
  5250.         x = ioctl(ttyfd,TCSETX,&rctsx);
  5251.         debug(F100,"tthflow ATTSV ioctl","",x);
  5252.         }
  5253. #else
  5254.         debug(F100,"tthflow TCGETX not defined","",0);
  5255.         x = -1
  5256. #endif /* TCGETX */
  5257. #else
  5258.         debug(F100,"tthflow RTSXOFF not defined","",0);
  5259.         x = -1;
  5260. #endif /* RTSXOFF */
  5261.     } else if (flow == FLO_DTRC) {    /* DTR/CD Flow control... */
  5262.         debug(F100,"tthflow ATTSV DTR/CD ON","",0);
  5263. #ifdef DTRXOFF
  5264.         /* This is straight out of SVID R4 */
  5265.         if (ioctl(ttyfd,TCGETX,&rctsx) > -1) {
  5266.         rctsx.x_hflag &= ~(DTRXOFF|CDXON);
  5267.         x = ioctl(ttyfd,TCSETX,&rctsx);
  5268.         }
  5269. #else
  5270.         debug(F100,"tthflow ATTSV DTRXOFF not defined","",0);
  5271.         x = -1;
  5272. #endif /* DTRXOFF */
  5273.     }
  5274.     }
  5275. #endif /* CK_SCOUNIX */
  5276.  
  5277. #else /* not System V... */
  5278.  
  5279. #ifdef CK_DTRCTS
  5280. #ifdef LDODTR
  5281. #ifdef LDOCTS
  5282. #ifdef NETCMD
  5283.     if (ttpipe) return(0);
  5284. #endif /* NETCMD */
  5285. #ifdef NETPTY
  5286.     if (ttpty) return(0);
  5287. #endif /* NETPTY */
  5288.     x = LDODTR | LDOCTS;        /* Found only on UTEK? */
  5289.     if (flow == FLO_DTRT && status) {    /* Use hardware flow control */
  5290.     if (lmodef) {
  5291.         x = ioctl(ttyfd,TIOCLBIS,&x);
  5292.         if (x < 0) {
  5293.             debug(F100,"hardflow TIOCLBIS error","",0);
  5294.         } else {
  5295.         lmodef++;
  5296.         debug(F100,"hardflow TIOCLBIS ok","",0);
  5297.         }
  5298.     }
  5299.     } else {
  5300.     if (lmodef) {
  5301.         x = ioctl(ttyfd,TIOCLBIC,&x);
  5302.         if (x < 0) {
  5303.             debug(F100,"hardflow TIOCLBIC error","",0);
  5304.         } else {
  5305.         lmodef++;
  5306.         debug(F100,"hardflow TIOCLBIC ok","",0);
  5307.         }
  5308.     }
  5309.     }
  5310. #endif /* LDODTR */
  5311. #endif /* LDOCTS */
  5312. #endif /* CK_DTRCTS */
  5313. #endif /* ATTSV */
  5314. #endif /* AIXRS */
  5315. #endif /* SUNOS4 */
  5316. #endif /* QNX */
  5317. #endif /* POSIX_CRTSCTS */
  5318. #endif /* SUNOS41 */
  5319.  
  5320. #else /* OXOS */
  5321.  
  5322.     struct termios temp;        /* Olivetti X/OS ... */
  5323.  
  5324. #ifdef NETCMD
  5325.     if (ttpipe) return(0);
  5326. #endif /* NETCMD */
  5327. #ifdef NETPTY
  5328.     if (ttpty) return(0);
  5329. #endif /* NETPTY */
  5330.     x = ioctl(ttyfd,TCGETS,&temp);
  5331.     if (x == 0) {
  5332.     temp.c_cflag &= ~(CRTSCTS|CDTRCTS|CBRKFLOW|CDTRDSR|CRTSDSR);
  5333.     if (status) {
  5334.         switch (flow) {
  5335.           case FLO_RTSC: temp.c_cflag |= CRTSCTS; /* RTS/CTS (hard) */
  5336.         break;
  5337.           case FLO_DTRT: temp.c_cflag |= CDTRCTS; /* DTR/CTS (hard) */
  5338.         break;
  5339.         }
  5340.     }
  5341.     x = ioctl(ttyfd,TCSETS,&temp);
  5342.     }
  5343. #endif /* OXOS */
  5344.     return(x);
  5345.  
  5346. #endif /* Plan9 */
  5347. }
  5348.  
  5349. /*  T T P K T  --  Condition the communication line for packets */
  5350. /*                 or for modem dialing */
  5351.  
  5352. /*
  5353.   If called with speed > -1, also set the speed.
  5354.   Returns 0 on success, -1 on failure.
  5355.  
  5356.   NOTE: the "xflow" parameter is supposed to be the currently selected
  5357.   type of flow control, but for historical reasons, this parameter is also
  5358.   used to indicate that we are dialing.  Therefore, when the true flow
  5359.   control setting is needed, we access the external variable "flow", rather
  5360.   than trusting our "xflow" argument.
  5361. */
  5362. int
  5363. #ifdef CK_ANSIC
  5364. ttpkt(long speed, int xflow, int parity)
  5365. #else
  5366. ttpkt(speed,xflow,parity) long speed; int xflow, parity;
  5367. #endif /* CK_ANSIC */
  5368. /* ttpkt */ {
  5369. #ifndef NOLOCAL
  5370.     int s2;
  5371.     int s = -1;
  5372. #endif /* NOLOCAL */
  5373. #ifndef SVORPOSIX
  5374.     int x;
  5375. #endif /* SVORPOSIX */
  5376.     extern int flow;            /* REAL flow-control setting */
  5377.  
  5378.     if (ttyfd < 0) return(-1);          /* Not open. */
  5379.  
  5380.     debug(F101,"ttpkt parity","",parity);
  5381.     debug(F101,"ttpkt xflow","",xflow);
  5382.     debug(F101,"ttpkt speed","",(int) speed);
  5383.  
  5384.     ttprty = parity;                    /* Let other tt functions see these. */
  5385.     ttspeed = speed;            /* Make global copy for this module */
  5386.     ttpmsk = ttprty ? 0177 : 0377;    /* Parity stripping mask */
  5387. #ifdef PARSENSE
  5388.     needpchk = ttprty ? 0 : 1;        /* Parity check needed? */
  5389. #else
  5390.     needpchk = 0;
  5391. #endif /* PARSENSE */
  5392.  
  5393.     debug(F101,"ttpkt ttpmsk","",ttpmsk);
  5394.     debug(F101,"ttpkt netconn","",netconn);
  5395.  
  5396. #ifdef NETCONN                /* No mode-changing for telnet */
  5397.     if (netconn) {
  5398. #ifdef TCPSOCKET
  5399. #ifdef TCP_NODELAY
  5400.         if (ttnet == NET_TCPB) {    /* But turn off Nagle */
  5401.             extern int tcp_nodelay;
  5402.             nodelay_sav = tcp_nodelay;
  5403.             no_delay(1);
  5404.         }
  5405. #endif /* TCP_NODELAY */
  5406. #endif /* TCPSOCKET */
  5407.         return(0);
  5408.     }
  5409. #endif /* NETCONN */
  5410. #ifdef NETCMD
  5411.     if (ttpipe) return(0);
  5412. #endif /* NETCMD */
  5413. #ifdef NETPTY
  5414.     if (ttpty) return(0);
  5415. #endif /* NETPTY */
  5416.  
  5417. #ifndef Plan9
  5418.     if (ttfdflg && !isatty(ttyfd)) return(0);
  5419. #endif /* Plan9 */
  5420.  
  5421. #ifdef COHERENT
  5422. #define SVORPOSIX
  5423. #endif /* COHERENT */
  5424.  
  5425. #ifndef SVORPOSIX            /* Berkeley, V7, etc. */
  5426. #ifdef LPASS8
  5427. /*
  5428.  For some reason, with BSD terminal drivers, you can't set FLOW to XON/XOFF
  5429.  after having previously set it to NONE without closing and reopening the
  5430.  device.  Unless there's something I overlooked below...
  5431. */
  5432.     if (ttflow == FLO_NONE && flow == FLO_XONX && xlocal == 0) {
  5433.     debug(F101,"ttpkt executing horrible flow kludge","",0);
  5434.     ttclos(0);            /* Close it */
  5435.     x = 0;
  5436.     ttopen(ttnmsv,&x,ttmdm,0);    /* Open it again */
  5437.     }
  5438. #endif /* LPASS8 */
  5439. #endif /* SVORPOSIX */
  5440.  
  5441. #ifdef COHERENT                /* This must be vestigial since we */
  5442. #undef SVORPOSIX            /* reverse it a few lines below... */
  5443. #endif /* COHERENT */
  5444.  
  5445.     if (xflow != FLO_DIAL && xflow != FLO_DIAX)
  5446.       ttflow = xflow;            /* Now make this available too. */
  5447.  
  5448. #ifndef NOLOCAL
  5449.     if (xlocal) {
  5450.     s2 = (int) (speed / 10L);    /* Convert bps to cps */
  5451.     debug(F101,"ttpkt calling ttsspd","",s2);
  5452.     s = ttsspd(s2);            /* Check and set the speed */
  5453.     debug(F101,"ttpkt ttsspd result","",s);
  5454.      carrctl(&ttraw, xflow != FLO_DIAL /* Carrier control */
  5455.         && (ttcarr == CAR_ON || (ttcarr == CAR_AUT && ttmdm != 0)));
  5456.     tvtflg = 0;            /* So ttvt() will work next time */
  5457.     }
  5458. #endif /* NOLOCAL */
  5459.  
  5460. #ifdef COHERENT
  5461. #define SVORPOSIX
  5462. #endif /* COHERENT */
  5463.  
  5464. #ifndef SVORPOSIX            /* BSD section */
  5465.     if (flow == FLO_RTSC ||        /* Hardware flow control */
  5466.     flow == FLO_DTRC ||
  5467.     flow == FLO_DTRT) {
  5468.     tthflow(flow, 1, &ttraw);
  5469.     debug(F100,"ttpkt hard flow, TANDEM off, RAW on","",0);
  5470.     ttraw.sg_flags &= ~TANDEM;    /* Turn off software flow control */
  5471.     ttraw.sg_flags |= RAW;        /* Enter raw mode */
  5472.     } else if (flow == FLO_NONE) {    /* No flow control */
  5473.     debug(F100,"ttpkt no flow, TANDEM off, RAW on","",0);
  5474.     ttraw.sg_flags &= ~TANDEM;    /* Turn off software flow control */
  5475.     tthflow(flow, 0, &ttraw);    /* Turn off any hardware f/c too */
  5476.     ttraw.sg_flags |= RAW;        /* Enter raw mode */
  5477.     } else if (flow == FLO_KEEP) {    /* Keep device's original setting */
  5478.     debug(F100,"ttpkt keeping original TANDEM","",0);
  5479.     ttraw.sg_flags &= ~TANDEM;
  5480.     ttraw.sg_flags |= (ttold.sg_flags & TANDEM);
  5481.     /* NOTE: We should also handle hardware flow control here! */
  5482.     }
  5483.  
  5484. /* SET FLOW XON/XOFF is in effect, or SET FLOW KEEP resulted in Xon/Xoff */
  5485.  
  5486.     if ((flow == FLO_XONX) || (ttraw.sg_flags & TANDEM)) {
  5487.     debug(F100,"ttpkt turning on TANDEM","",0);
  5488.     ttraw.sg_flags |= TANDEM;    /* So ask for it. */
  5489.  
  5490. #ifdef LPASS8                /* Can pass 8-bit data through? */
  5491. /* If the LPASS8 local mode is available, then flow control can always  */
  5492. /* be used, even if parity is none and we are transferring 8-bit data.  */
  5493. /* But we only need to do all this if Xon/Xoff is requested. */
  5494. /* BUT... this tends not to work through IP or LAT connections, terminal */
  5495. /* servers, telnet, rlogin, etc, so it is currently disabled. */
  5496.     x = LPASS8;            /* If LPASS8 defined, then */
  5497.     debug(F100,"ttpkt executing LPASS8 code","",0);
  5498.     if (lmodef) {            /* TIOCLBIS must be too. */
  5499.         x = ioctl(ttyfd,TIOCLBIS,&x); /* Try to set LPASS8. */
  5500.         if (x < 0) {
  5501.         debug(F100,"ttpkt TIOCLBIS error","",0);
  5502.         } else {
  5503.         lmodef++;
  5504.         debug(F100,"ttpkt TIOCLBIS ok","",0);
  5505.         }
  5506.     }
  5507. /*
  5508.  But if we use LPASS8 mode, we must explicitly turn off
  5509.  terminal interrupts of all kinds.
  5510. */
  5511. #ifdef TIOCGETC                /* Not rawmode, */
  5512.     if (tcharf && (xlocal == 0)) {    /* must turn off */
  5513.         tchnoi.t_intrc = -1;    /* interrupt character */
  5514.         tchnoi.t_quitc = -1;    /* and quit character. */
  5515.         tchnoi.t_startc = 17;    /* Make sure xon */
  5516.         tchnoi.t_stopc = 19;    /* and xoff not ignored. */
  5517. #ifndef NOBRKC
  5518.         tchnoi.t_eofc = -1;        /* eof character. */
  5519.         tchnoi.t_brkc = -1;        /* brk character. */
  5520. #endif /* NOBRKC */
  5521.         if (ioctl(ttyfd,TIOCSETC,&tchnoi) < 0) {
  5522.         debug(F100,"ttpkt TIOCSETC failed","",0);
  5523.         } else {
  5524.         tcharf = 1;
  5525.         debug(F100,"ttpkt TIOCSETC ok","",0);
  5526.         }
  5527. #ifdef COMMENT
  5528. /* only for paranoid debugging */
  5529.         if (tcharf) {
  5530.         struct tchars foo;
  5531.         char tchbuf[100];
  5532.         ioctl(0,TIOCGETC,&foo);
  5533.         sprintf(tchbuf,
  5534.             "intr=%d,quit=%d, start=%d, stop=%d, eof=%d, brk=%d",
  5535.             foo.t_intrc, foo.t_quitc, foo.t_startc,
  5536.             foo.t_stopc, foo.t_eofc,  foo.t_brkc);
  5537.         debug(F110,"ttpkt chars",tchbuf,0);
  5538.         }
  5539. #endif /* COMMENT */
  5540.     }
  5541.     ttraw.sg_flags |= CBREAK;    /* Needed for unknown reason */
  5542. #endif /* TIOCGETC */
  5543.  
  5544. /* Prevent suspend during packet mode */
  5545. #ifdef TIOCGLTC                /* Not rawmode, */
  5546.     if (ltcharf && (xlocal == 0)) {    /* must turn off */
  5547.         ltchnoi.t_suspc = -1;    /* suspend character */
  5548.         ltchnoi.t_dsuspc = -1;    /* and delayed suspend character */
  5549.         if (ioctl(ttyfd,TIOCSLTC,&tchnoi) < 0) {
  5550.         debug(F100,"ttpkt TIOCSLTC failed","",0);
  5551.         } else {
  5552.         ltcharf = 1;
  5553.         debug(F100,"ttpkt TIOCSLTC ok","",0);
  5554.         }
  5555.     }
  5556. #endif /* TIOCGLTC */
  5557.  
  5558. #else /* LPASS8 not defined */
  5559.  
  5560. /* Previously, BSD-based implementations always */
  5561. /* used rawmode for packets.  Now, we use rawmode only if parity is NONE. */
  5562. /* This allows the flow control requested above to actually work, but only */
  5563. /* if the user asks for parity (which also means they get 8th-bit quoting). */
  5564.  
  5565.     if (parity) {            /* If parity, */
  5566.         ttraw.sg_flags &= ~RAW;    /* use cooked mode */
  5567. #ifdef COMMENT
  5568. /* WHY??? */
  5569.         if (xlocal)
  5570. #endif /* COMMENT */
  5571.           ttraw.sg_flags |= CBREAK;
  5572.         debug(F101,"ttpkt cooked, cbreak, parity","",parity);
  5573. #ifdef TIOCGETC                /* Not rawmode, */
  5574.         if (tcharf && (xlocal == 0)) { /* must turn off */
  5575.         tchnoi.t_intrc = -1;    /* interrupt character */
  5576.         tchnoi.t_quitc = -1;    /* and quit character. */
  5577.         tchnoi.t_startc = 17;    /* Make sure xon */
  5578.         tchnoi.t_stopc = 19;    /* and xoff not ignored. */
  5579. #ifndef NOBRKC
  5580.         tchnoi.t_eofc = -1;    /* eof character. */
  5581.         tchnoi.t_brkc = -1;    /* brk character. */
  5582. #endif /* NOBRKC */
  5583.         if (ioctl(ttyfd,TIOCSETC,&tchnoi) < 0) {
  5584.             debug(F100,"ttpkt TIOCSETC failed","",0);
  5585.         } else {
  5586.             tcharf = 1;
  5587.             debug(F100,"ttpkt TIOCSETC ok","",0);
  5588.         }
  5589.         }
  5590. #endif /* TIOCGETC */
  5591. #ifdef TIOCGLTC                /* Not rawmode, */
  5592. /* Prevent suspend during packet mode */
  5593.         if (ltcharf && (xlocal == 0)) { /* must turn off */
  5594.         ltchnoi.t_suspc = -1;    /* suspend character */
  5595.         ltchnoi.t_dsuspc = -1;    /* and delayed suspend character */
  5596.         if (ioctl(ttyfd,TIOCSLTC,&tchnoi) < 0) {
  5597.             debug(F100,"ttpkt TIOCSLTC failed","",0);
  5598.         } else {
  5599.             ltcharf = 1;
  5600.             debug(F100,"ttpkt TIOCSLTC ok","",0);
  5601.         }
  5602.         }
  5603. #endif /* TIOCGLTC */
  5604.     } else {            /* If no parity, */
  5605.         ttraw.sg_flags |= RAW;    /* must use 8-bit raw mode. */
  5606.         debug(F101,"ttpkt setting rawmode, parity","",parity);
  5607.     }
  5608. #endif /* LPASS8 */
  5609.     } /* End of Xon/Xoff section */
  5610.  
  5611.     /* Don't echo, don't map CR to CRLF on output, don't fool with case */
  5612. #ifdef LCASE
  5613.     ttraw.sg_flags &= ~(ECHO|CRMOD|LCASE);
  5614. #else
  5615.     ttraw.sg_flags &= ~(ECHO|CRMOD);
  5616. #endif /* LCASE */
  5617.  
  5618. #ifdef TOWER1
  5619.     ttraw.sg_flags &= ~ANYP;            /* Must set this on old Towers */
  5620. #endif /* TOWER1 */
  5621.  
  5622. #ifdef BELLV10
  5623.     if (ioctl(ttyfd,TIOCSETP,&ttraw) < 0) /* Set the new modes. */
  5624.       return(-1);
  5625. #else
  5626.     errno = 0;
  5627.     if (stty(ttyfd,&ttraw) < 0) {       /* Set the new modes. */
  5628.         debug(F101,"ttpkt stty failed","",errno);
  5629.         return(-1);
  5630.     }
  5631. #endif /* BELLV10 */
  5632.     debug(F100,"ttpkt stty ok","",0);
  5633.  
  5634. #ifdef sony_news
  5635.     x = xlocal ? km_ext : km_con;    /* Put line in ASCII mode. */
  5636.     if (x != -1) {            /* Make sure we know original modes. */
  5637.     x &= ~KM_TTYPE;
  5638.     x |= KM_ASCII;
  5639.     if (ioctl(ttyfd,TIOCKSET, &x) < 0) {
  5640.         perror("ttpkt can't set ASCII mode");
  5641.         debug(F101,"ttpkt error setting ASCII mode","",x);
  5642.         return(-1);
  5643.     }
  5644.     }
  5645.     debug(F100,"ttpkt set ASCII mode ok","",0);
  5646. #endif /* sony_news */
  5647.  
  5648.     if (xlocal == 0) {            /* Turn this off so we can read */
  5649.     signal(SIGINT,SIG_IGN);        /* Ctrl-C chars typed at console */
  5650.     sigint_ign = 1;
  5651.     }
  5652.     tvtflg = 0;                /* So ttvt() will work next time */
  5653.     debug(F100,"ttpkt success","",0);
  5654.     return(0);
  5655.  
  5656. #endif /* Not ATTSV or POSIX */
  5657.  
  5658. /* AT&T UNIX and POSIX */
  5659.  
  5660. #ifdef COHERENT
  5661. #define SVORPOSIX
  5662. #endif /* COHERENT */
  5663.  
  5664. #ifdef SVORPOSIX
  5665.     if (flow == FLO_XONX) {        /* Xon/Xoff */
  5666.     ttraw.c_iflag |= (IXON|IXOFF);
  5667.     tthflow(flow, 0, &ttraw);
  5668.     } else if (flow == FLO_NONE) {    /* None */
  5669.     /* NOTE: We should also turn off hardware flow control here! */
  5670.     ttraw.c_iflag &= ~(IXON|IXOFF);
  5671.     tthflow(flow, 0, &ttraw);
  5672.     } else if (flow == FLO_KEEP) {    /* Keep */
  5673.     ttraw.c_iflag &= ~(IXON|IXOFF);    /* Turn off Xon/Xoff flags */
  5674.     ttraw.c_iflag |= (ttold.c_iflag & (IXON|IXOFF)); /* OR in old ones */
  5675.     /* NOTE: We should also handle hardware flow control here! */
  5676. #ifdef POSIX_CRTSCTS
  5677. /* In Linux case, we do this, which is unlikely to be portable */
  5678.         ttraw.c_cflag &= ~CRTSCTS;    /* Turn off RTS/CTS flag */
  5679.         ttraw.c_cflag |= (ttold.c_cflag & CRTSCTS); /* OR in old one */
  5680. #endif /* POSIX_CRTSCTS */
  5681.     } else if (flow == FLO_RTSC ||    /* Hardware */
  5682.            flow == FLO_DTRC ||
  5683.            flow == FLO_DTRT) {
  5684.     ttraw.c_iflag &= ~(IXON|IXOFF);    /* (190) */
  5685.     tthflow(flow, 1, &ttraw);
  5686.     }
  5687.     ttraw.c_lflag &= ~(ICANON|ECHO);
  5688.     ttraw.c_lflag &= ~ISIG;        /* Do NOT check for interrupt chars */
  5689.  
  5690. #ifndef OXOS
  5691. #ifdef QNX
  5692.     if (flow != FLO_RTSC && flow != FLO_DTRC && flow != FLO_DTRT)
  5693. #endif /* QNX */
  5694. #ifndef COHERENT
  5695.       ttraw.c_lflag &= ~IEXTEN;        /* Turn off ^O/^V processing */
  5696. #endif /* COHERENT */
  5697. #else /* OXOS */
  5698.     ttraw.c_cc[VDISCARD] = ttraw.c_cc[VLNEXT] = CDISABLE;
  5699. #endif /* OXOS */
  5700.     ttraw.c_lflag |= NOFLSH;        /* Don't flush */
  5701.     ttraw.c_iflag |= IGNPAR;        /* Ignore parity errors */
  5702. #ifdef ATTSV
  5703. #ifdef BSD44
  5704.     ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|INPCK|ISTRIP|IXANY);
  5705. #else
  5706.     ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|INPCK|ISTRIP|IXANY);
  5707. #endif /* BSD44 */
  5708. #else /* POSIX */
  5709.     ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|INPCK|ISTRIP);
  5710. #endif /* ATTSV */
  5711.     ttraw.c_oflag &= ~OPOST;
  5712.     ttraw.c_cflag &= ~(CSIZE);
  5713.     ttraw.c_cflag |= (CS8|CREAD|HUPCL);
  5714.  
  5715. #ifdef HWPARITY
  5716.     if (hwparity && xlocal) {        /* Hardware parity & stop bits */
  5717. #ifdef CSTOPB
  5718.     if (stopbits == 2) {
  5719.         ttraw.c_cflag |= CSTOPB;    /* 2 stop bits */
  5720.         debug(F100,"ttpkt 2 stopbits","",0);
  5721.     } else if (stopbits == 1) {
  5722.         ttraw.c_cflag &= ~(CSTOPB);    /* 1 stop bit */
  5723.         debug(F100,"ttpkt 1 stopbit","",0);
  5724.     }
  5725. #else
  5726.     debug(F101,"ttpkt CSTOPB not def","",stopbits);
  5727. #endif /* CSTOPB */
  5728.     ttraw.c_cflag |= PARENB;    /* Enable parity */
  5729.     switch (hwparity) {
  5730.       case 'e':            /* Even */
  5731.         ttraw.c_cflag &= ~(PARODD);
  5732.         debug(F100,"ttpkt 8 bits + even parity","",0);
  5733.         break;
  5734.       case 'o':            /* Odd */
  5735.         ttraw.c_cflag |= PARODD;
  5736.         debug(F100,"ttpkt 8 bits + odd parity","",0);
  5737.         break;
  5738.       case 'm':            /* Mark */
  5739.       case 's':            /* Space */
  5740.         debug(F100,"ttpkt 8 bits + invalid parity","",0);
  5741.         break;
  5742.     }
  5743.     } else {                /* We handle parity ourselves */
  5744. #endif /* HWPARITY */
  5745.     ttraw.c_cflag &= ~(PARENB);    /* Don't enable parity */
  5746. #ifdef HWPARITY
  5747.     }
  5748. #endif /* HWPARITY */
  5749.  
  5750. #ifdef IX370
  5751.     ttraw.c_cc[4] = 48;  /* So Series/1 doesn't interrupt on every char */
  5752.     ttraw.c_cc[5] = 1;
  5753. #else
  5754. #ifndef VEOF                /* for DGUX this is VEOF, not VMIN */
  5755.     ttraw.c_cc[4] = 1;   /* [VMIN]  return max of this many characters or */
  5756. #else
  5757. #ifndef OXOS
  5758. #ifdef VMIN
  5759.     ttraw.c_cc[VMIN] = 1;
  5760. #endif /* VMIN */
  5761. #else /* OXOS */
  5762.     ttraw.c_min = 1;
  5763. #endif /* OXOS */
  5764. #endif /* VEOF */
  5765. #ifndef VEOL                /* for DGUX this is VEOL, not VTIME */
  5766.     ttraw.c_cc[5] = 0;     /* [VTIME] when this many secs/10 expire w/no input */
  5767. #else
  5768. #ifndef OXOS
  5769. #ifdef VTIME
  5770.     ttraw.c_cc[VTIME] = 0;
  5771. #endif /* VTIME */
  5772. #else /* OXOS */
  5773.     ttraw.c_time = 0;
  5774. #endif /* OXOS */
  5775. #endif /* VEOL */
  5776. #endif /* IX370 */
  5777.  
  5778. #ifdef VINTR                /* Turn off interrupt character */
  5779.     if (xlocal == 0)            /* so ^C^C can break us out of */
  5780.       ttraw.c_cc[VINTR] = 0;        /* packet mode. */
  5781. #endif /* VINTR */
  5782.  
  5783. #ifdef Plan9
  5784.     if (p9ttyparity('n') < 0)
  5785.     return -1;
  5786. #else
  5787. #ifdef BSD44ORPOSIX
  5788. #ifdef BEOSORBEBOX
  5789.     ttraw.c_cc[VMIN] = 0;        /* DR7 can only poll. */
  5790. #endif /* BEOSORBEBOX */
  5791.     debug(F100,"ttpkt calling tcsetattr(TCSETAW)","",0);
  5792.     errno = 0;
  5793.     if (tcsetattr(ttyfd,TCSADRAIN,&ttraw) < 0) {
  5794.         debug(F101,"ttpkt BSD44ORPOSIX tcsetattr(TCSADRAIN) fail","",errno);
  5795.         return(-1);
  5796.     }
  5797. #else /* BSD44ORPOSIX */
  5798.     errno = 0;
  5799.     debug(F100,"ttpkt calling ioctl(TCSETAW)","",0);
  5800.     if (ioctl(ttyfd,TCSETAW,&ttraw) < 0) {  /* set new modes . */
  5801.         debug(F100,"ttpkt ATTSV ioctl(TCSETAW) fail","",errno);
  5802.         return(-1);
  5803.     }
  5804. #endif /* BSD44ORPOSIX */
  5805. #endif /* Plan9 */
  5806.     tvtflg = 0;
  5807.     debug(F100,"ttpkt success","",0);
  5808.     return(0);
  5809. #endif /* ATTSV */
  5810.  
  5811. #ifdef COHERENT
  5812. #undef SVORPOSIX
  5813. #endif /* COHERENT */
  5814.  
  5815. }
  5816.  
  5817. /*  T T S E T F L O W  --  Set flow control immediately.  */
  5818.  
  5819. #ifdef COHERENT
  5820. #define SVORPOSIX
  5821. #endif /* COHERENT */
  5822.  
  5823. int
  5824. ttsetflow(flow) int flow; {
  5825.     if (ttyfd < 0)            /* Communications channel must open */
  5826.       return(-1);
  5827.  
  5828.     debug(F101,"ttsetflow","",flow);
  5829.  
  5830. #ifdef NETCMD
  5831.     if (ttpipe) return(0);
  5832. #endif /* NETCMD */
  5833. #ifdef NETPTY
  5834.     if (ttpty) return(0);
  5835. #endif /* NETPTY */
  5836.  
  5837. #ifdef COMMENT
  5838.     /* This seems to hurt... */
  5839.     if (flow == FLO_KEEP)
  5840.       return(0);
  5841. #endif /* COMMENT */
  5842.  
  5843.     if (flow == FLO_RTSC ||        /* Hardware flow control... */
  5844.     flow == FLO_DTRC ||
  5845.     flow == FLO_DTRT) {
  5846.     tthflow(flow, 1, &ttraw);
  5847. #ifndef SVORPOSIX
  5848.     ttraw.sg_flags &= ~TANDEM;    /* Turn off software flow control */
  5849. #else
  5850.     ttraw.c_iflag &= ~(IXON|IXOFF);
  5851. #endif /* SVORPOSIX */
  5852.  
  5853.     } else if (flow == FLO_XONX) {    /* Xon/Xoff... */
  5854.  
  5855. #ifndef SVORPOSIX
  5856.     ttraw.sg_flags |= TANDEM;
  5857. #else
  5858.     ttraw.c_iflag |= (IXON|IXOFF);
  5859. #endif /* SVORPOSIX */
  5860.     tthflow(FLO_RTSC, 0, &ttraw);    /* Turn off hardware flow control */
  5861.  
  5862.     } else if (flow == FLO_NONE) {    /* No flow control */
  5863.  
  5864. #ifndef SVORPOSIX
  5865.     ttraw.sg_flags &= ~TANDEM;    /* Turn off software flow control */
  5866. #else
  5867.     ttraw.c_iflag &= ~(IXON|IXOFF);
  5868. #endif /* SVORPOSIX */
  5869.     tthflow(FLO_RTSC, 0, &ttraw);    /* Turn off any hardware f/c too */
  5870.     }
  5871.  
  5872. /* Set the new modes... */
  5873.  
  5874. #ifndef SVORPOSIX            /* BSD and friends */
  5875. #ifdef BELLV10
  5876.     if (ioctl(ttyfd,TIOCSETP,&ttraw) < 0)
  5877.       return(-1);
  5878. #else
  5879. #ifndef MINIX2
  5880.     if (stty(ttyfd,&ttraw) < 0)
  5881.       return(-1);
  5882. #endif /* MINIX2 */
  5883. #endif /* BELLV10 */
  5884. #else
  5885. #ifdef BSD44ORPOSIX            /* POSIX */
  5886.     if (tcsetattr(ttyfd,TCSADRAIN,&ttraw) < 0)
  5887.       return(-1);
  5888. #else                    /* System V */
  5889.     if (ioctl(ttyfd,TCSETAW,&ttraw) < 0)
  5890.       return(-1);
  5891. #endif /* BSD44ORPOSIX */
  5892. #endif /* SVORPOSIX */
  5893.     return(0);
  5894. }
  5895. #ifdef COHERENT
  5896. #undef SVORPOSIX
  5897. #endif /* COHERENT */
  5898.  
  5899. /*  T T V T -- Condition communication device for use as virtual terminal. */
  5900.  
  5901. int
  5902. #ifdef CK_ANSIC
  5903. ttvt(long speed, int flow)
  5904. #else
  5905. ttvt(speed,flow) long speed; int flow;
  5906. #endif /* CK_ANSIC */
  5907. /* ttvt */ {
  5908.     int s, s2;
  5909.  
  5910.     debug(F101,"ttvt ttyfd","",ttyfd);
  5911.     debug(F101,"ttvt tvtflg","",tvtflg);
  5912.     debug(F101,"ttvt speed","",speed);
  5913.     debug(F101,"ttvt flow","",flow);
  5914.  
  5915.     ttpmsk = 0xff;
  5916. #ifdef NOLOCAL
  5917.     return(conbin((char)escchr));
  5918. #else
  5919.     if (ttyfd < 0) {            /* Not open. */
  5920.     if (ttchk() < 0)
  5921.       return(-1);
  5922.     else                /* But maybe something buffered. */
  5923.       return(0);
  5924.     }
  5925. #ifdef NETCMD
  5926.     if (ttpipe) return(0);
  5927. #endif /* NETCMD */
  5928. #ifdef NETPTY
  5929.     if (ttpty) return(0);
  5930. #endif /* NETPTY */
  5931. #ifdef NETCONN
  5932.     if (netconn) {
  5933.     tvtflg = 1;            /* Network connections... */
  5934.     debug(F100,"ttvt network connection, skipping...","",0);
  5935. #ifdef TCPSOCKET
  5936. #ifdef TCP_NODELAY
  5937.         {
  5938.         extern int tcp_nodelay;
  5939.         if (ttnet == NET_TCPB) {
  5940.         if (nodelay_sav > -1) {
  5941.             no_delay(nodelay_sav);
  5942.             nodelay_sav = -1;
  5943.         }
  5944.         }
  5945.         }
  5946. #endif /* TCP_NODELAY */
  5947. #endif /* TCPSOCKET */
  5948.     return(0);            /* ... require no special setup */
  5949.     }
  5950. #endif /* NETCONN */
  5951.  
  5952.     if (tvtflg != 0 && speed == ttspeed && flow == ttflow && ttcarr == curcarr)
  5953.       {
  5954.       debug(F100,"ttvt modes already set, skipping...","",0);
  5955.       return(0);            /* Already been called. */
  5956.       }
  5957.  
  5958.     if (ttfdflg
  5959. #ifndef Plan9
  5960.     && !isatty(ttyfd)
  5961. #endif /* Plan9 */
  5962.     ) {
  5963.     debug(F100,"ttvt using external fd, skipping...","",0);
  5964.     return(0);
  5965.     }
  5966.  
  5967.     debug(F100,"ttvt setting modes...","",0);
  5968.  
  5969.     if (xlocal) {            /* For external lines... */
  5970.     s2 = (int) (speed / 10L);
  5971.     s = ttsspd(s2);            /* Check/set the speed */
  5972.     carrctl(&tttvt, flow != FLO_DIAL /* Do carrier control */
  5973.         && (ttcarr == CAR_ON || (ttcarr == CAR_AUT && ttmdm != 0)));
  5974.     } else
  5975.       s = s2 = -1;
  5976.  
  5977. #ifdef COHERENT
  5978. #define SVORPOSIX
  5979. #endif /* COHERENT */
  5980.  
  5981. #ifndef SVORPOSIX
  5982.     /* Berkeley, V7, etc */
  5983.     if (flow == FLO_RTSC ||        /* Hardware flow control */
  5984.     flow == FLO_DTRC ||
  5985.     flow == FLO_DTRT) {
  5986.     tthflow(flow, 1, &tttvt);
  5987.     debug(F100,"ttvt hard flow, TANDEM off","",0);
  5988.     tttvt.sg_flags &= ~TANDEM;    /* Turn off software flow control */
  5989.     } else if (flow == FLO_XONX) {    /* Xon/Xoff flow control */
  5990.     debug(F100,"ttvt TANDEM on","",0);
  5991.     tttvt.sg_flags |= TANDEM;    /* Ask for it. */
  5992.     tthflow(flow, 0, &tttvt);    /* Turn off hardware f/c */
  5993.     } else if (flow == FLO_NONE) {
  5994.     debug(F100,"ttvt no flow, TANDEM off, RAW on","",0);
  5995.     tttvt.sg_flags &= ~TANDEM;    /* Turn off software flow control */
  5996.     tthflow(flow, 0, &tttvt);    /* Turn off any hardware f/c too */
  5997.     tttvt.sg_flags |= RAW;        /* Enter raw mode */
  5998.     } else if (flow == FLO_KEEP) {    /* Keep device's original setting */
  5999.     debug(F100,"ttvt keeping original TANDEM","",0);
  6000.     tttvt.sg_flags &= ~TANDEM;
  6001.     tttvt.sg_flags |= (ttold.sg_flags & TANDEM);
  6002.     /* NOTE: We should also handle hardware flow control here! */
  6003.     }
  6004.     tttvt.sg_flags |= RAW;              /* Raw mode in all cases */
  6005. #ifdef TOWER1
  6006.     tttvt.sg_flags &= ~(ECHO|ANYP);     /* No echo or parity */
  6007. #else
  6008.     tttvt.sg_flags &= ~ECHO;            /* No echo */
  6009. #endif /* TOWER1 */
  6010.  
  6011. #ifdef BELLV10
  6012.     if (ioctl(ttyfd,TIOCSETP,&tttvt) < 0) /* Set the new modes */
  6013.       return(-1);
  6014. #else
  6015.     if (stty(ttyfd,&tttvt) < 0)        /* Set the new modes */
  6016.       return(-1);
  6017. #endif /* BELLV10 */
  6018.  
  6019. #else /* It is ATTSV or POSIX */
  6020.  
  6021.     if (flow == FLO_XONX) {        /* Software flow control */
  6022.     tttvt.c_iflag |= (IXON|IXOFF);    /* On if requested. */
  6023.     tthflow(flow, 0, &tttvt);    /* Turn off hardware f/c */
  6024.     debug(F100,"ttvt SVORPOSIX flow XON/XOFF","",0);
  6025.     } else if (flow == FLO_NONE) {    /* NONE */
  6026.     tttvt.c_iflag &= ~(IXON|IXOFF);    /* Turn off Xon/Xoff */
  6027.     tthflow(flow, 0, &tttvt);    /* Turn off hardware f/c */
  6028.     debug(F100,"ttvt SVORPOSIX flow NONE","",0);
  6029.     } else if (flow == FLO_KEEP) {
  6030.     tttvt.c_iflag &= ~(IXON|IXOFF);    /* Turn off Xon/Xoff flags */
  6031.     tttvt.c_iflag |= (ttold.c_iflag & (IXON|IXOFF)); /* OR in old ones */
  6032. #ifdef POSIX_CRTSCTS
  6033.         tttvt.c_cflag &= ~CRTSCTS;    /* Turn off RTS/CTS flag */
  6034.         tttvt.c_cflag |= (ttold.c_cflag & CRTSCTS); /* OR in old one */
  6035. #endif /* POSIX_CRTSCTS */
  6036.     debug(F100,"ttvt SVORPOSIX flow KEEP","",0);
  6037.     } else if (flow == FLO_RTSC ||    /* Hardware flow control */
  6038.            flow == FLO_DTRC ||
  6039.            flow == FLO_DTRT) {
  6040.     tttvt.c_iflag &= ~(IXON|IXOFF);    /* (196) */
  6041.     tthflow(flow, 1, &tttvt);
  6042.     debug(F100,"ttvt SVORPOSIX flow HARD","",0);
  6043.     }
  6044. #ifndef OXOS
  6045. #ifdef COHERENT
  6046.     tttvt.c_lflag &= ~(ISIG|ICANON|ECHO);
  6047. #else
  6048.     tttvt.c_lflag &= ~(ISIG|ICANON|ECHO|IEXTEN);
  6049. #endif /* COHERENT */
  6050. #ifdef QNX
  6051.     /* Needed for hwfc */
  6052.     if (flow == FLO_RTSC || flow == FLO_DTRC || flow == FLO_DTRT)
  6053.       tttvt.c_lflag |= IEXTEN;
  6054. #endif /* QNX */
  6055. #else /* OXOS */
  6056.     tttvt.c_lflag &= ~(ISIG|ICANON|ECHO);
  6057.     tttvt.c_cc[VDISCARD] = tttvt.c_cc[VLNEXT] = CDISABLE;
  6058. #endif /* OXOS */
  6059.  
  6060.     tttvt.c_iflag |= (IGNBRK|IGNPAR);
  6061.  
  6062. /* Parity */
  6063.  
  6064. #ifdef HWPARITY
  6065.     if (hwparity && xlocal) {        /* Hardware parity */
  6066. #ifdef CSTOPB
  6067.     if (stopbits == 2) {
  6068.         ttraw.c_cflag |= CSTOPB;    /* 2 stop bits */
  6069.         debug(F100,"ttpkt 2 stopbits","",0);
  6070.     } else if (stopbits == 1) {
  6071.         ttraw.c_cflag &= ~(CSTOPB);    /* 1 stop bit */
  6072.         debug(F100,"ttpkt 1 stopbit","",0);
  6073.     }
  6074. #endif /* CSTOPB */
  6075.     tttvt.c_cflag |= PARENB;    /* Enable parity */
  6076.     switch (hwparity) {
  6077.       case 'e':            /* Even */
  6078.         tttvt.c_cflag &= ~(PARODD);
  6079.         debug(F100,"ttvt 8 bits + even parity","",0);
  6080.         break;
  6081.       case 'o':            /* Odd */
  6082.         tttvt.c_cflag |= PARODD;
  6083.         debug(F100,"ttvt 8 bits + odd parity","",0);
  6084.         break;
  6085.       case 'm':            /* Mark */
  6086.       case 's':            /* Space */
  6087.         debug(F100,"ttvt 8 bits + invalid parity","",0);
  6088.         break;
  6089.     }
  6090.     } else {                /* We handle parity ourselves */
  6091. #endif /* HWPARITY */
  6092.     tttvt.c_cflag &= ~(PARENB);    /* Don't enable parity */
  6093. #ifdef HWPARITY
  6094.     }
  6095. #endif /* HWPARITY */
  6096.  
  6097. #ifdef ATTSV
  6098. #ifdef BSD44
  6099.     /* Things not to do... */
  6100.     tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|INPCK|ISTRIP|IXANY);
  6101. #else
  6102.     tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|IUCLC|INPCK|ISTRIP|IXANY);
  6103. #endif /* BSD44 */
  6104. #else /* POSIX */
  6105.     tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|INPCK|ISTRIP);
  6106. #endif /* ATTSV */
  6107.     tttvt.c_cflag &= ~(CSIZE);        /* Zero out the char size field */
  6108.     tttvt.c_cflag |= (CS8|CREAD|HUPCL);    /* Char size 8, enable receiver, hup */
  6109.     tttvt.c_oflag &= ~OPOST;        /* Don't postprocess output */
  6110. #ifndef VEOF /* DGUX termio has VEOF at entry 4, see comment above */
  6111.     tttvt.c_cc[4] = 1;
  6112. #else
  6113. #ifndef OXOS
  6114. #ifdef VMIN
  6115.     tttvt.c_cc[VMIN] = 1;
  6116. #endif /* VMIN */
  6117. #else /* OXOS */
  6118.     tttvt.c_min = 1;
  6119. #endif /* OXOS */
  6120. #endif /* VEOF */
  6121. #ifndef VEOL    /* DGUX termio has VEOL at entry 5, see comment above */
  6122.     tttvt.c_cc[5] = 0;
  6123. #else
  6124. #ifndef OXOS
  6125. #ifdef VTIME
  6126.     tttvt.c_cc[VTIME] = 0;
  6127. #endif /* VTIME */
  6128. #else /* OXOS */
  6129.     tttvt.c_time = 0;
  6130. #endif /* OXOS */
  6131. #endif /* VEOL */
  6132.  
  6133. #ifdef Plan9
  6134.     if (p9ttyparity('n') < 0)
  6135.       return -1;
  6136. #else
  6137. #ifdef BSD44ORPOSIX
  6138. #ifdef BEOSORBEBOX
  6139.     tttvt.c_cc[VMIN] = 0;        /* DR7 can only poll. */
  6140. #endif /* BEOSORBEBOX */
  6141.     if (tcsetattr(ttyfd,TCSADRAIN,&tttvt) < 0) return(-1);
  6142. #else /* ATTSV */
  6143.     if (ioctl(ttyfd,TCSETAW,&tttvt) < 0) return(-1);  /* set new modes . */
  6144. #endif /* BSD44ORPOSIX */
  6145. #endif /* Plan9 */
  6146. #endif /* ATTSV */
  6147.  
  6148.     ttspeed = speed;            /* Done, remember how we were */
  6149.     ttflow = flow;            /* called, so we can decide how to */
  6150.     tvtflg = 1;                /* respond next time. */
  6151.     debug(F101,"ttvt done","",tvtflg);
  6152.     return(0);
  6153.  
  6154. #ifdef COHERENT
  6155. #undef SVORPOSIX
  6156. #endif /* COHERENT */
  6157.  
  6158. #endif /* NOLOCAL */
  6159. }
  6160.  
  6161. #ifndef NOLOCAL
  6162.  
  6163. /* Serial speed department . . . */
  6164.  
  6165. /*
  6166.   Plan 9's native speed setting interface lets you set anything you like,
  6167.   but will fail if the hardware doesn't like it, so we allow all the common
  6168.   speeds.
  6169. */
  6170. #ifdef Plan9
  6171. #ifndef B50
  6172. #define B50 50
  6173. #endif /* B50 */
  6174. #ifndef B75
  6175. #define B75 75
  6176. #endif /* B75 */
  6177. #ifndef B110
  6178. #define B110 110
  6179. #endif /* B110 */
  6180. #ifndef B134
  6181. #define B134 134
  6182. #endif /* B134 */
  6183. #ifndef B200
  6184. #define B200 200
  6185. #endif /* B200 */
  6186. #ifndef B300
  6187. #define B300 300
  6188. #endif /* B300 */
  6189. #ifndef B1200
  6190. #define B1200 1200
  6191. #endif /* B1200 */
  6192. #ifndef B1800
  6193. #define B1800 1800
  6194. #endif /* B1800 */
  6195. #ifndef B2400
  6196. #define B2400 2400
  6197. #endif /* B2400 */
  6198. #ifndef B4800
  6199. #define B4800 4800
  6200. #endif /* B4800 */
  6201. #ifndef B9600
  6202. #define B9600 9600
  6203. #endif /* B9600 */
  6204. #ifndef B14400
  6205. #define B14400 14400
  6206. #endif /* B14400 */
  6207. #ifndef B19200
  6208. #define B19200 19200
  6209. #endif /* B19200 */
  6210. #ifndef B28800
  6211. #define B28800 28800
  6212. #endif /* B28800 */
  6213. #ifndef B38400
  6214. #define B38400 38400
  6215. #endif /* B38400 */
  6216. #ifndef B57600
  6217. #define B57600 57600
  6218. #endif /* B57600 */
  6219. #ifndef B76800
  6220. #define B76800 76800
  6221. #endif /* B76800 */
  6222. #ifndef B115200
  6223. #define B115200 115200
  6224. #endif /* B115200 */
  6225. #ifndef B230400
  6226. #define B230400 230400
  6227. #endif /* B230400 */
  6228. #ifndef B460800
  6229. #define B460800 460800
  6230. #endif /* B460800 */
  6231. #ifndef B921600
  6232. #define B921600 921600
  6233. #endif /* B921600 */
  6234. #endif /* Plan9 */
  6235.  
  6236. /*  T T S S P D  --  Checks and sets transmission rate.  */
  6237.  
  6238. /*  Call with speed in characters (not bits!) per second. */
  6239. /*  Returns -1 on failure, 0 if it did nothing, 1 if it changed the speed. */
  6240.  
  6241. #ifdef USETCSETSPEED
  6242. /*
  6243.   The tcsetspeed() / tcgetspeed() interface lets you pass any number at all
  6244.   to be used as a speed to be set, rather than forcing a choice from a
  6245.   predefined list.  It seems to be peculiar to UnixWare 7.
  6246.  
  6247.   These are the function codes to be passed to tc[gs]etspeed(),
  6248.   but for some reason they don't seem to be picked up from termios.h.
  6249. */
  6250. #ifndef TCS_ALL
  6251. #define TCS_ALL 0
  6252. #endif /* TCS_ALL */
  6253. #ifndef TCS_IN
  6254. #define TCS_IN 1
  6255. #endif /* TCS_IN */
  6256. #ifndef TCS_OUT
  6257. #define TCS_OUT 2
  6258. #endif /* TCS_OUT */
  6259. #endif /* USETCSETSPEED */
  6260.  
  6261. int
  6262. ttsspd(cps) int cps; {
  6263.     int x;
  6264. #ifdef POSIX
  6265. /* Watch out, speed_t should be unsigned, so don't compare with -1, etc... */
  6266.     speed_t
  6267. #else
  6268.     int
  6269. #endif /* POSIX */
  6270.       s, s2;
  6271.     int ok = 1;                /* Speed check result, assume ok */
  6272.  
  6273. #ifdef OLINUXHISPEED
  6274.     unsigned int spd_flags = 0;
  6275.     struct serial_struct serinfo;
  6276. #endif /* OLINUXHISPEED */
  6277.  
  6278.     debug(F101,"ttsspd cps","",cps);
  6279.     debug(F101,"ttsspd ttyfd","",ttyfd);
  6280.     debug(F101,"ttsspd xlocal","",xlocal);
  6281.  
  6282.     if (ttyfd < 0 || xlocal == 0 )    /* Don't set speed on console */
  6283.       return(0);
  6284.  
  6285. #ifdef    NETCONN
  6286.     if (netconn)
  6287.       return(0);
  6288. #endif    /* NETCONN */
  6289. #ifdef NETCMD
  6290.     if (ttpipe) return(0);
  6291. #endif /* NETCMD */
  6292. #ifdef NETPTY
  6293.     if (ttpty) return(0);
  6294. #endif /* NETPTY */
  6295.  
  6296.     if (cps < 0) return(-1);
  6297.     s = s2 = 0;                /* NB: s and s2 might be unsigned */
  6298.  
  6299. #ifdef USETCSETSPEED
  6300.  
  6301.     s = cps * 10L;
  6302.  
  6303.     x = tcgetattr(ttyfd,&ttcur);    /* Get current speed */
  6304.     debug(F101,"ttsspd tcgetattr","",x);
  6305.     if (x < 0)
  6306.       return(-1);
  6307.     debug(F101,"ttsspd TCSETSPEED speed","",s);
  6308.  
  6309.     errno = 0;
  6310.     if (s == 8880L) {            /* 75/1200 split speed requested */
  6311.     tcsetspeed(TCS_IN, &ttcur, 1200L);
  6312.     tcsetspeed(TCS_OUT, &ttcur, 75L);
  6313.     } else
  6314.       tcsetspeed(TCS_ALL, &ttcur, s);    /* Put new speed in structs */
  6315. #ifdef DEBUG
  6316.     if (errno & deblog) {
  6317.     debug(F101,"ttsspd TCSETSPEED errno","",errno);
  6318.     }
  6319. #endif /* DEBUG */
  6320.  
  6321. #ifdef COMMENT
  6322.     tcsetspeed(TCS_ALL, &ttraw, s);
  6323.     tcsetspeed(TCS_ALL, &tttvt, s);
  6324.     tcsetspeed(TCS_ALL, &ttold, s);
  6325. #else
  6326.     if (s == 8880L) {            /* 75/1200 split speed requested */
  6327.     tcsetspeed(TCS_IN, &ttraw, 1200L);
  6328.     tcsetspeed(TCS_OUT, &ttraw, 75L);
  6329.     tcsetspeed(TCS_IN, &tttvt, 1200L);
  6330.     tcsetspeed(TCS_OUT, &tttvt, 75L);
  6331.     tcsetspeed(TCS_IN, &ttold, 1200L);
  6332.     tcsetspeed(TCS_OUT, &ttold, 75L);
  6333.     } else {
  6334.     tcsetspeed(TCS_ALL, &ttraw, s);
  6335.     tcsetspeed(TCS_ALL, &tttvt, s);
  6336.     tcsetspeed(TCS_ALL, &ttold, s);
  6337.     }
  6338. #endif /* COMMENT */
  6339.  
  6340.     x = tcsetattr(ttyfd,TCSADRAIN,&ttcur); /* Set the speed */
  6341.     debug(F101,"ttsspd tcsetattr","",x);
  6342.     if (x < 0)
  6343.       return(-1);
  6344.  
  6345. #else  /* Not USETCSETSPEED */
  6346.  
  6347. #ifdef MINIX2        /* Hack alert */
  6348. #define MINIX        /* Use pre-2.0 speed selection for Minix 2.0 as well */
  6349. #endif /* MINIX2 */
  6350.  
  6351.     /* First check that the given speed is valid. */
  6352.  
  6353.     switch (cps) {
  6354. #ifndef MINIX
  6355.       case 0:   s = B0;    break;
  6356.       case 5:   s = B50;   break;
  6357.       case 7:   s = B75;   break;
  6358. #endif /* MINIX */
  6359.       case 11:  s = B110;  break;
  6360. #ifndef MINIX
  6361.       case 13:  s = B134;  break;
  6362.       case 15:  s = B150;  break;
  6363.       case 20:  s = B200;  break;
  6364. #endif /* MINIX */
  6365.       case 30:  s = B300;  break;
  6366. #ifndef MINIX
  6367.       case 60:  s = B600;  break;
  6368. #endif /* MINIX */
  6369.       case 120: s = B1200; break;
  6370. #ifndef MINIX
  6371.       case 180: s = B1800; break;
  6372. #endif /* MINIX */
  6373.       case 240: s = B2400; break;
  6374.       case 480: s = B4800; break;
  6375. #ifndef MINIX
  6376.       case 888: s = B75; s2 = B1200; break; /* 888 = 75/1200 split speed */
  6377. #endif /* MINIX */
  6378. #ifdef B7200
  6379.       case 720: s = B7200; break;
  6380. #endif /* B7200 */
  6381.       case 960: s = B9600; break;
  6382. #ifdef B14400
  6383.       case 1440: s = B14400; break;
  6384. #endif /* B14400 */
  6385. #ifdef B19200
  6386.       case 1920: s = B19200; break;
  6387. #else
  6388. #ifdef EXTA
  6389.       case 1920: s = EXTA; break;
  6390. #endif /* EXTA */
  6391. #endif /* B19200 */
  6392. #ifdef B28800
  6393.       case 2880: s = B28800; break;
  6394. #endif /* B28800 */
  6395. #ifdef B38400
  6396.       case 3840: s = B38400;
  6397. #ifdef OLINUXHISPEED
  6398.         spd_flags = ~ASYNC_SPD_MASK;    /* Nonzero, but zero flags */
  6399. #endif /* OLINUXHISPEED */
  6400.     break;
  6401. #else /* B38400 not defined... */
  6402. #ifdef EXTB
  6403.       case 3840: s = EXTB; break;
  6404. #endif /* EXTB */
  6405. #endif /* B38400 */
  6406.  
  6407. #ifdef HPUX
  6408. #ifdef _B57600
  6409.       case 5760: s = _B57600; break;
  6410. #endif /* _B57600 */
  6411. #ifdef _B115200
  6412.       case 11520: s = _B115200; break;
  6413. #endif /* _B115200 */
  6414. #else
  6415. #ifdef OLINUXHISPEED
  6416. /*
  6417.   This bit from <carlo@sg.tn.tudelft.nl>:
  6418.   "Only note to make is maybe this: When the ASYNC_SPD_CUST flags are set then
  6419.   setting the speed to 38400 will set the custom speed (and ttgspd returns
  6420.   38400), but speeds 57600 and 115200 won't work any more because I didn't
  6421.   want to mess up the speed flags when someone is doing sophisticated stuff
  6422.   like custom speeds..."
  6423. */
  6424.       case 5760: s = B38400; spd_flags = ASYNC_SPD_HI; break;
  6425.       case 11520: s = B38400; spd_flags = ASYNC_SPD_VHI; break;
  6426. #else
  6427. #ifdef B57600
  6428.       case 5760: s = B57600; break;
  6429. #endif /* B57600 */
  6430. #ifdef B76800
  6431.       case 7680: s = B76800; break;
  6432. #endif /* B76800 */
  6433. #ifdef B115200
  6434.       case 11520: s = B115200; break;
  6435. #endif /* B115200 */
  6436. #endif /* OLINUXHISPEED */
  6437. #ifdef B153600
  6438.       case 15360: s = B153600; break;
  6439. #endif /* B153600 */
  6440. #ifdef B230400
  6441.       case 23040: s = B230400; break;
  6442. #endif /* B230400 */
  6443. #ifdef B307200
  6444.       case 30720: s = B307200; break;
  6445. #endif /* B307200 */
  6446. #ifdef B460800
  6447.       case 46080: s = B460800; break;
  6448. #endif /* 460800 */
  6449. #ifdef B921600
  6450.       case 92160: s = B921600; break;
  6451. #endif /* B921600 */
  6452. #endif /* HPUX */
  6453.       default:
  6454.     ok = 0;                /* Good speed not found, so not ok */
  6455.     break;
  6456.     }
  6457.     debug(F101,"ttsspd ok","",ok);
  6458.     debug(F101,"ttsspd s","",s);
  6459.  
  6460.     if (!ok) {
  6461.     debug(F100,"ttsspd fails","",0);
  6462.     return(-1);
  6463.     } else {
  6464.     if (!s2) s2 = s;        /* Set input speed */
  6465. #ifdef Plan9
  6466.     if (p9ttsspd(cps) < 0)
  6467.       return(-1);
  6468. #else
  6469. #ifdef BSD44ORPOSIX
  6470.     x = tcgetattr(ttyfd,&ttcur);    /* Get current speed */
  6471.     debug(F101,"ttsspd tcgetattr","",x);
  6472.     if (x < 0)
  6473.       return(-1);
  6474. #ifdef OLINUXHISPEED
  6475.     debug(F101,"ttsspd spd_flags","",spd_flags);
  6476.     if (spd_flags && spd_flags != ASYNC_SPD_CUST) {
  6477.         if (ioctl(ttyfd, TIOCGSERIAL, &serinfo) < 0) {
  6478.         debug(F100,"ttsspd: TIOCGSERIAL failed","",0);
  6479.         return(-1);
  6480.         } else debug(F100,"ttsspd: TIOCGSERIAL ok","",0);
  6481.         serinfo.flags &= ~ASYNC_SPD_MASK;
  6482.         serinfo.flags |= (spd_flags & ASYNC_SPD_MASK);
  6483.         if (ioctl(ttyfd, TIOCSSERIAL, &serinfo) < 0)
  6484.           return(-1);
  6485.     }
  6486. #endif /* OLINUXHISPEED */
  6487.     cfsetospeed(&ttcur,s);
  6488.     cfsetispeed(&ttcur,s2);
  6489.     cfsetospeed(&ttraw,s);
  6490.     cfsetispeed(&ttraw,s2);
  6491.     cfsetospeed(&tttvt,s);
  6492.     cfsetispeed(&tttvt,s2);
  6493.     cfsetospeed(&ttold,s);
  6494.     cfsetispeed(&ttold,s2);
  6495.     x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
  6496.     debug(F101,"ttsspd tcsetattr","",x);
  6497.     if (x < 0) return(-1);
  6498. #else
  6499. #ifdef ATTSV
  6500.     if (cps == 888) return(-1);    /* No split speeds, sorry. */
  6501.     x = ioctl(ttyfd,TCGETA,&ttcur);
  6502.     debug(F101,"ttsspd TCGETA ioctl","",x);
  6503.     if (x < 0) return(-1);
  6504.     ttcur.c_cflag &= ~CBAUD;
  6505.     ttcur.c_cflag |= s;
  6506.     tttvt.c_cflag &= ~CBAUD;
  6507.     tttvt.c_cflag |= s;
  6508.     ttraw.c_cflag &= ~CBAUD;
  6509.     ttraw.c_cflag |= s;
  6510.     ttold.c_cflag &= ~CBAUD;
  6511.     ttold.c_cflag |= s;
  6512.     x = ioctl(ttyfd,TCSETAW,&ttcur);
  6513.     debug(F101,"ttsspd TCSETAW ioctl","",x);
  6514.     if (x < 0) return(-1);
  6515. #else
  6516. #ifdef BELLV10
  6517.     x = ioctl(ttyfd,TIOCGDEV,&tdcur);
  6518.     debug(F101,"ttsspd TIOCGDEV ioctl","",x);
  6519.     if (x < 0) return(-1);
  6520.     tdcur.ispeed = s2;
  6521.     tdcur.ospeed = s;
  6522.     errno = 0;
  6523.     ok = ioctl(ttyfd,TIOCSDEV,&tdcur);
  6524.     debug(F101,"ttsspd BELLV10 ioctl","",ok);
  6525.     if (ok < 0) {
  6526.         perror(ttnmsv);
  6527.         debug(F101,"ttsspd BELLV10 errno","",ok);
  6528.         return(-1);
  6529.     }
  6530. #else
  6531.     x = gtty(ttyfd,&ttcur);
  6532.     debug(F101,"ttsspd gtty","",x);
  6533.     if (x < 0) return(-1);
  6534.     ttcur.sg_ospeed = s; ttcur.sg_ispeed = s2;
  6535.     tttvt.sg_ospeed = s; tttvt.sg_ispeed = s2;
  6536.     ttraw.sg_ospeed = s; ttraw.sg_ispeed = s2;
  6537.     ttold.sg_ospeed = s; ttold.sg_ispeed = s2;
  6538.     x = stty(ttyfd,&ttcur);
  6539.     debug(F101,"ttsspd stty","",x);
  6540.     if (x < 0) return(-1);
  6541. #endif /* BELLV10 */
  6542. #endif /* ATTSV */
  6543. #endif /* BSD44ORPOSIX */
  6544. #endif /* Plan9 */
  6545.     }
  6546.     return(1);                /* Return 1 = success. */
  6547. #endif /* USETCSETSPEED */
  6548. }
  6549.  
  6550. #endif /* NOLOCAL */
  6551.  
  6552. /* C O N G S P D  -  Get speed of console terminal  */
  6553.  
  6554. long
  6555. congspd() {
  6556. /*
  6557.   This is a disgusting hack.  The right way to do this would be to pass an
  6558.   argument to ttgspd(), but then we'd need to change the Kermit API and
  6559.   all of the ck?tio.c modules.  (Currently used only for rlogin.)
  6560. */
  6561.     int t1, t2;
  6562.     long spd;
  6563. #ifdef NETCONN
  6564.  
  6565.     t2 = netconn;
  6566.     netconn = 0;
  6567. #endif /* NETCONN */
  6568.     t1 = ttyfd;
  6569.     ttyfd = -1;
  6570.     spd = ttgspd();
  6571.     debug(F101,"congspd","",spd);
  6572. #ifdef NETCONN
  6573.     netconn = t2;
  6574. #endif /* NETCONN */
  6575.     ttyfd = t1;
  6576.     return(spd);
  6577. }
  6578.  
  6579. /*  T T S P D L I S T  -- Get list of serial speeds allowed on this platform */
  6580.  
  6581. #define NSPDLIST 64
  6582. static long spdlist[NSPDLIST];
  6583. /*
  6584.   As written, this picks up the speeds known at compile time, and thus
  6585.   apply to the system where C-Kermit was built, rather than to the one where
  6586.   it is running.  Suggestions for improvement are always welcome.
  6587. */
  6588. long *
  6589. ttspdlist() {
  6590.     int i;
  6591.     for (i = 0; i < NSPDLIST; i++)    /* Initialize the list */
  6592.       spdlist[i] = -1L;
  6593.     i = 1;
  6594.  
  6595. #ifdef USETCSETSPEED            /* No way to find out what's legal */
  6596.  
  6597.     spdlist[i++] = 50L;
  6598. #ifndef UW7
  6599.     spdlist[i++] = 75L;
  6600. #endif /* UW7 */
  6601.     spdlist[i++] = 110L;
  6602. #ifndef UW7
  6603.     spdlist[i++] = 134L;
  6604. #endif /* UW7 */
  6605.     spdlist[i++] = 150L;
  6606.     spdlist[i++] = 200L;
  6607.     spdlist[i++] = 300L;
  6608.     spdlist[i++] = 600L;
  6609.     spdlist[i++] = 1200L;
  6610.     spdlist[i++] = 1800L;
  6611.     spdlist[i++] = 2400L;
  6612.     spdlist[i++] = 4800L;
  6613.     spdlist[i++] = 8880L;
  6614.     spdlist[i++] = 9600L;
  6615.     spdlist[i++] = 14400L;
  6616.     spdlist[i++] = 19200L;
  6617.     spdlist[i++] = 28800L;
  6618. #ifndef UW7
  6619.     spdlist[i++] = 33600L;
  6620. #endif /* UW7 */
  6621.     spdlist[i++] = 38400L;
  6622.     spdlist[i++] = 57600L;
  6623.     spdlist[i++] = 76800L;
  6624.     spdlist[i++] = 115200L;
  6625. #ifndef UW7
  6626.     spdlist[i++] = 153600L;
  6627.     spdlist[i++] = 230400L;
  6628.     spdlist[i++] = 307200L;
  6629.     spdlist[i++] = 460800L;
  6630.     spdlist[i++] = 921600L;
  6631. #endif /* UW7 */
  6632.  
  6633. #else  /* USETCSETSPEED */
  6634.  
  6635. #ifdef B50
  6636.     spdlist[i++] = 50L;
  6637. #endif /* B50 */
  6638. #ifdef B75
  6639.     spdlist[i++] = 75L;
  6640. #endif /* B75 */
  6641. #ifdef B110
  6642.     spdlist[i++] = 110L;
  6643. #endif /* B110 */
  6644. #ifdef B134
  6645.     spdlist[i++] = 134L;
  6646. #endif /* B134 */
  6647. #ifdef B150
  6648.     spdlist[i++] = 150L;
  6649. #endif /* B150 */
  6650. #ifdef B200
  6651.     spdlist[i++] = 200L;
  6652. #endif /* B200 */
  6653. #ifdef B300
  6654.     spdlist[i++] = 300L;
  6655. #endif /* B300 */
  6656. #ifdef B600
  6657.     spdlist[i++] = 600L;
  6658. #endif /* B600 */
  6659. #ifdef B1200
  6660.     spdlist[i++] = 1200L;
  6661. #endif /* B1200 */
  6662. #ifdef B1800
  6663.     spdlist[i++] = 1800L;
  6664. #endif /* B1800 */
  6665. #ifdef B2400
  6666.     spdlist[i++] = 2400L;
  6667. #endif /* B2400 */
  6668. #ifdef B4800
  6669.     spdlist[i++] = 4800L;
  6670. #endif /* B4800 */
  6671. #ifdef B9600
  6672.     spdlist[i++] = 9600L;
  6673. #endif /* B9600 */
  6674. #ifdef B14400
  6675.     spdlist[i++] = 14400L;
  6676. #endif /* B14400 */
  6677. #ifdef B19200
  6678.     spdlist[i++] = 19200L;
  6679. #else
  6680. #ifdef EXTA
  6681.     spdlist[i++] = 19200L;
  6682. #endif /* EXTA */
  6683. #endif /* B19200 */
  6684. #ifdef B28800
  6685.     spdlist[i++] = 28800L;
  6686. #endif /* B28800 */
  6687. #ifdef B33600
  6688.     spdlist[i++] = 33600L;
  6689. #endif /* B33600 */
  6690. #ifdef B38400
  6691.     spdlist[i++] = 38400L;
  6692. #else
  6693. #ifdef EXTB
  6694.     spdlist[i++] = 38400L;
  6695. #endif /* EXTB */
  6696. #endif /* B38400 */
  6697. #ifdef _B57600
  6698.     spdlist[i++] = 57600L;
  6699. #else
  6700. #ifdef B57600
  6701.     spdlist[i++] = 57600L;
  6702. #endif /* B57600 */
  6703. #endif /* _B57600 */
  6704. #ifdef B76800
  6705.     spdlist[i++] = 76800L;
  6706. #endif /* B76800 */
  6707. #ifdef _B115200
  6708.     spdlist[i++] = 115200L;
  6709. #else
  6710. #ifdef B115200
  6711.     spdlist[i++] = 115200L;
  6712. #endif /* B115200 */
  6713. #endif /* _B115200 */
  6714. #ifdef B153600
  6715.     spdlist[i++] = 153600L;
  6716. #endif /* B153600 */
  6717. #ifdef B230400
  6718.     spdlist[i++] = 230400L;
  6719. #endif /* B230400 */
  6720. #ifdef B307200
  6721.     spdlist[i++] = 307200L;
  6722. #endif /* B307200 */
  6723. #ifdef B460800
  6724.     spdlist[i++] = 460800L;
  6725. #endif /* B460800 */
  6726. #ifdef B921600
  6727.     spdlist[i++] = 921600L;
  6728. #endif /* B921600 */
  6729. #endif /* USETCSETSPEED */
  6730.     spdlist[0] = i - 1;            /* Return count in 0th element */
  6731.     return((long *)spdlist);
  6732. }
  6733.  
  6734. /* T T G S P D  -  Get speed of currently selected tty line  */
  6735.  
  6736. /*
  6737.   Unreliable.  After SET LINE, it returns an actual speed, but not necessarily
  6738.   the real speed.  On some systems, it returns the line's nominal speed, from
  6739.   /etc/ttytab.  Even if you SET SPEED to something else, this function might
  6740.   not notice.
  6741. */
  6742. long
  6743. ttgspd() {                /* Get current serial device speed */
  6744. #ifdef NOLOCAL
  6745.     return(-1L);
  6746. #else
  6747. #ifdef POSIX
  6748.     speed_t                /* Should be unsigned */
  6749. #else
  6750.     int                    /* Isn't unsigned */
  6751. #endif /* POSIX */
  6752.       s;
  6753.     int x;
  6754.     long ss;
  6755. #ifdef OLINUXHISPEED
  6756.     unsigned int spd_flags = 0;
  6757.     struct serial_struct serinfo;
  6758. #endif /* OLINUXHISPEED */
  6759.  
  6760. #ifdef NETCONN
  6761.     if (netconn) return(-1);        /* -1 if network connection */
  6762. #endif /* NETCONN */
  6763. #ifdef NETCMD
  6764.     if (ttpipe) return(-1);
  6765. #endif /* NETCMD */
  6766. #ifdef NETPTY
  6767.     if (ttpty) return(-1);
  6768. #endif /* NETPTY */
  6769.  
  6770.     debug(F101,"ttgspd ttyfd","",ttyfd);
  6771.  
  6772. #ifdef USETCSETSPEED
  6773.  
  6774.     x = tcgetattr(ttyfd,&ttcur);    /* Get current speed */
  6775.     debug(F101,"ttgspd tcgetattr","",x);
  6776.     if (x < 0)
  6777.       return(-1);
  6778.     errno = 0;
  6779.     s = tcgetspeed(TCS_ALL, &ttcur);
  6780.     debug(F101,"ttsspd TCGETSPEED speed","",s);
  6781.     if (s == 0) {
  6782.     long s1, s2;
  6783.     s1 = tcgetspeed(TCS_IN, &ttcur);
  6784.     s2 = tcgetspeed(TCS_OUT, &ttcur);
  6785.     if (s1 == 1200L && s2 == 75L)
  6786.       return(8880L);
  6787.     }
  6788. #ifdef DEBUG
  6789.     if (errno & deblog) {
  6790.     debug(F101,"ttsspd TCGETSPEED errno","",errno);
  6791.     }
  6792. #endif /* DEBUG */
  6793.     return(s);
  6794.  
  6795. #else  /* Not USETCSETSPEED */
  6796.  
  6797. #ifdef Plan9
  6798.     if (ttyfd < 0)
  6799.       ss = -1;
  6800.     else
  6801.       ss = ttylastspeed;
  6802. #else
  6803. #ifdef OLINUXHISPEED
  6804.     debug(F100,"ttgspd Linux OLINUXHISPEED","",0);
  6805. #endif /* OLINUXHISPEED */
  6806.  
  6807.     if (ttyfd < 0) {
  6808. #ifdef BSD44ORPOSIX
  6809.     s = cfgetospeed(&ccold);
  6810.     debug(F101,"ttgspd cfgetospeed 1 POSIX","",s);
  6811. #else
  6812. #ifdef ATTSV
  6813.     s = ccold.c_cflag & CBAUD;
  6814.     debug(F101,"ttgspd c_cflag CBAUD 1 ATTSV","",s);
  6815. #else
  6816.     s = ccold.sg_ospeed;        /* (obtained by congm()) */
  6817.     debug(F101,"ttgspd sg_ospeed 1","",s);
  6818. #endif /* ATTSV */
  6819. #endif /* BSD44POSIX */
  6820.  
  6821.     } else {
  6822. #ifdef BSD44ORPOSIX
  6823.     if (tcgetattr(ttyfd,&ttcur) < 0) return(-1);
  6824.     s = cfgetospeed(&ttcur);
  6825.     debug(F101,"ttgspd cfgetospeed 2 BSDORPOSIX","",s);
  6826. #ifdef OLINUXHISPEED
  6827.     if (ioctl(ttyfd,TIOCGSERIAL,&serinfo) > -1)
  6828.       spd_flags = serinfo.flags & ASYNC_SPD_MASK;
  6829.     debug(F101,"ttgspd spd_flags","",spd_flags);
  6830. #endif /* OLINUXHISPEED */
  6831. #else
  6832. #ifdef ATTSV
  6833.     x = ioctl(ttyfd,TCGETA,&ttcur);
  6834.     debug(F101,"ttgspd ioctl 2 ATTSV x","",x);
  6835.     debug(F101,"ttgspd ioctl 2 ATTSV errno","",errno);
  6836.     if (x < 0) return(-1);
  6837.     s = ttcur.c_cflag & CBAUD;
  6838.     debug(F101,"ttgspd ioctl 2 ATTSV speed","",s);
  6839. #else
  6840. #ifdef BELLV10
  6841.     x = ioctl(ttyfd,TIOCGDEV,&tdcur);
  6842.     debug(F101,"ttgspd ioctl 2 BELLV10 x","",x);
  6843.     if (x < 0) return(-1);
  6844.     s = tdcur.ospeed;
  6845.     debug(F101,"ttgspd ioctl 2 BELLV10 speed","",s);
  6846. #else
  6847.     x = gtty(ttyfd,&ttcur);
  6848.     debug(F101,"ttgspd gtty 2 x","",x);
  6849.     debug(F101,"ttgspd gtty 2 errno","",errno);
  6850.     if (x < 0) return(-1);
  6851.     s = ttcur.sg_ospeed;
  6852.     debug(F101,"ttgspd gtty 2 speed","",s);
  6853. #endif /* BELLV10 */
  6854. #endif /* ATTSV */
  6855. #endif /* BSD44ORPOSIX */
  6856.     }
  6857.     debug(F101,"ttgspd code","",s);
  6858. #ifdef OLINUXHISPEED
  6859.     debug(F101,"ttgspd spd_flags","",spd_flags);
  6860. #endif /* OLINUXHISPEED */
  6861.     switch (s) {
  6862. #ifdef B0
  6863.       case B0:    ss = 0L; break;
  6864. #endif /* B0 */
  6865.  
  6866. #ifndef MINIX
  6867. /*
  6868.  MINIX defines the Bxx symbols to be bps/100, so B50==B75, B110==B134==B150,
  6869.  etc, making for many "duplicate case in switch" errors, which are fatal.
  6870. */
  6871. #ifdef B50
  6872.       case B50:   ss = 50L; break;
  6873. #endif /* B50 */
  6874. #ifdef B75
  6875.       case B75:   ss = 75L; break;
  6876. #endif /* B75 */
  6877. #endif /* MINIX */
  6878.  
  6879. #ifdef B110
  6880.       case B110:  ss = 110L; break;
  6881. #endif /* B110 */
  6882.  
  6883. #ifndef MINIX
  6884. #ifdef B134
  6885.       case B134:  ss = 134L; break;
  6886. #endif /* B134 */
  6887. #ifdef B150
  6888.       case B150:  ss = 150L; break;
  6889. #endif /* B150 */
  6890. #endif /* MINIX */
  6891.  
  6892. #ifdef B200
  6893.       case B200:  ss = 200L; break;
  6894. #endif /* B200 */
  6895.  
  6896. #ifdef B300
  6897.       case B300:  ss = 300L; break;
  6898. #endif /* B300 */
  6899.  
  6900. #ifdef B600
  6901.       case B600:  ss = 600L; break;
  6902. #endif /* B600 */
  6903.  
  6904. #ifdef B1200
  6905.       case B1200: ss = 1200L; break;
  6906. #endif /* B1200 */
  6907.  
  6908. #ifdef B1800
  6909.       case B1800: ss = 1800L; break;
  6910. #endif /* B1800 */
  6911.  
  6912. #ifdef B2400
  6913.       case B2400: ss = 2400L; break;
  6914. #endif /* B2400 */
  6915.  
  6916. #ifdef B4800
  6917.       case B4800: ss = 4800L; break;
  6918. #endif /* B4800 */
  6919.  
  6920. #ifdef B7200
  6921.       case B7200: ss = 7200L; break;
  6922. #endif /* B7200 */
  6923.  
  6924. #ifdef B9600
  6925.       case B9600: ss = 9600L; break;
  6926. #endif /* B9600 */
  6927.  
  6928. #ifdef B19200
  6929.       case B19200: ss = 19200L; break;
  6930. #else
  6931. #ifdef EXTA
  6932.       case EXTA: ss = 19200L; break;
  6933. #endif /* EXTA */
  6934. #endif /* B19200 */
  6935.  
  6936. #ifdef MINIX2
  6937. /* End of hack to make MINIX2 use MINIX1 speed setting */
  6938. #undef MINIX
  6939. #endif /* MINIX2 */
  6940.  
  6941. #ifndef MINIX
  6942. #ifdef B38400
  6943.       case B38400:
  6944.         ss = 38400L;
  6945. #ifdef OLINUXHISPEED
  6946.         switch(spd_flags) {
  6947.           case ASYNC_SPD_HI:  ss =  57600L; break;
  6948.           case ASYNC_SPD_VHI: ss = 115200L; break;
  6949.     }
  6950. #endif /* OLINUXHISPEED */
  6951.         break;
  6952. #else
  6953. #ifdef EXTB
  6954.       case EXTB: ss = 38400L; break;
  6955. #endif /* EXTB */
  6956. #endif /* B38400 */
  6957. #endif /* MINIX */
  6958.  
  6959. #ifdef HPUX
  6960. #ifdef _B57600
  6961.       case _B57600: ss = 57600L; break;
  6962. #endif /* _B57600 */
  6963. #ifdef _B115200
  6964.       case _B115200: ss = 115200L; break;
  6965. #endif /* _B115200 */
  6966. #else
  6967. #ifdef B57600
  6968.       case B57600: ss = 57600L; break;
  6969. #endif /* B57600 */
  6970. #ifdef B76800
  6971.       case B76800: ss = 76800L; break;
  6972. #endif /* B76800 */
  6973. #ifdef B115200
  6974.       case B115200: ss = 115200L; break;
  6975. #endif /* B115200 */
  6976. #ifdef B153600
  6977.       case B153600: ss = 153600L; break;
  6978. #endif /* B153600 */
  6979. #ifdef B230400
  6980.       case B230400: ss = 230400L; break;
  6981. #endif /* B230400 */
  6982. #ifdef B307200
  6983.       case B307200: ss = 307200L; break;
  6984. #endif /* B307200 */
  6985. #ifdef B460800
  6986.       case B460800: ss = 460800L; break;
  6987. #endif /* B460800 */
  6988. #endif /* HPUX */
  6989. #ifdef B921600
  6990.       case 92160: ss = 921600L; break;
  6991. #endif /* B921600 */
  6992.       default:
  6993.     ss = -1; break;
  6994.     }
  6995. #endif /* Plan9 */
  6996.     debug(F101,"ttgspd speed","",ss);
  6997.     return(ss);
  6998.  
  6999. #endif /* USETCSETSPEED */
  7000. #endif /* NOLOCAL */
  7001. }
  7002. #ifdef MINIX2                /* Another hack alert */
  7003. #define MINIX
  7004. #endif /* MINIX2 */
  7005.  
  7006. /*
  7007.   FIONREAD data type...  This has been defined as "long" for many, many
  7008.   years, and it worked OK until 64-bit platforms appeared.  Thus we use
  7009.   int for 64-bit platforms, but keep long for the others.  If we changed
  7010.   the default PEEKTYPE to int, this would probably break 16-bit builds
  7011.   (note that sizeof(long) == sizeof(int) on most 32-bit platforms), many
  7012.   of which we have no way of testing any more.  Therefore, do not change
  7013.   the default definition of PEEKTYPE -- only add exceptions to it as needed.
  7014. */
  7015. #ifdef COHERENT
  7016. #ifdef FIONREAD
  7017. #undef FIONREAD
  7018. #endif /* FIONREAD */
  7019. /* #define FIONREAD TIOCQUERY */
  7020. /* #define PEEKTYPE int */
  7021. #else  /* Not COHERENT... */
  7022.  
  7023. #ifdef OSF32                /* Digital UNIX 3.2 or higher */
  7024. #define PEEKTYPE int
  7025. #else
  7026. #define PEEKTYPE long            /* Elsewhere (see notes above) */
  7027. #endif /* OSF32 */
  7028. #endif /* COHERENT */
  7029.  
  7030. /* ckumyr.c by Kristoffer Eriksson, ske@pkmab.se, 15 Mar 1990. */
  7031.  
  7032. #ifdef MYREAD
  7033.  
  7034. /* Private buffer for myread() and its companions.  Not for use by anything
  7035.  * else.  ttflui() is allowed to reset them to initial values.  ttchk() is
  7036.  * allowed to read my_count.
  7037.  *
  7038.  * my_item is an index into mybuf[].  Increment it *before* reading mybuf[].
  7039.  *
  7040.  * A global parity mask variable could be useful too.  We could use it to
  7041.  * let myread() strip the parity on its own, instead of stripping sign
  7042.  * bits as it does now.
  7043.  */
  7044. #ifdef BIGBUFOK
  7045. #define MYBUFLEN 32768
  7046. #else
  7047. #ifdef pdp11
  7048. #define MYBUFLEN 256
  7049. #else
  7050. #define MYBUFLEN 1024
  7051. #endif /* pdp11 */
  7052. #endif /* BIGBUFOK */
  7053.  
  7054. #ifdef ANYX25
  7055. #undef MYBUFLEN
  7056. #define MYBUFLEN 256
  7057. /*
  7058.   On X.25 connections, there is an extra control byte at the beginning.
  7059. */
  7060. static CHAR x25buf[MYBUFLEN+1];        /* Communication device input buffer */
  7061. static CHAR  *mybuf = x25buf+1;
  7062. #else
  7063. static CHAR mybuf[MYBUFLEN];
  7064. #endif /* ANYX25 */
  7065.  
  7066. static int my_count = 0;        /* Number of chars still in mybuf */
  7067. static int my_item = -1;        /* Last index read from mybuf[]   */
  7068.  
  7069. /*  T T P E E K  --  Peek into our internal communications input buffers. */
  7070.  
  7071. /*
  7072.   NOTE: This routine is peculiar to UNIX, and is used only by the
  7073.   select()-based CONNECT module, ckucns.c.  It need not be replicated in
  7074.   the ck?tio.c of other platforms.
  7075. */
  7076. int
  7077. ttpeek() {
  7078.     int rc = 0;
  7079. #ifdef TTLEBUF
  7080.     if (ttpush >= 0)
  7081.       rc++;
  7082.     rc += le_inbuf();
  7083.     if (rc > 0)
  7084.       return(rc);
  7085.     else
  7086. #endif /* TTLEBUF */
  7087.  
  7088. #ifdef MYREAD
  7089.     return(my_count);
  7090. #else
  7091.     return(0);
  7092. #endif /* MYREAD */
  7093. }
  7094.  
  7095. /* myread() -- Efficient read of one character from communications line.
  7096.  *
  7097.  * Uses a private buffer to minimize the number of expensive read() system
  7098.  * calls.  Essentially performs the equivalent of read() of 1 character, which
  7099.  * is then returned.  By reading all available input from the system buffers
  7100.  * to the private buffer in one chunk, and then working from this buffer, the
  7101.  * number of system calls is reduced in any case where more than one character
  7102.  * arrives during the processing of the previous chunk, for instance high
  7103.  * baud rates or network type connections where input arrives in packets.
  7104.  * If the time needed for a read() system call approaches the time for more
  7105.  * than one character to arrive, then this mechanism automatically compensates
  7106.  * for that by performing bigger read()s less frequently.  If the system load
  7107.  * is high, the same mechanism compensates for that too.
  7108.  *
  7109.  * myread() is a macro that returns the next character from the buffer.  If the
  7110.  * buffer is empty, mygetbuf() is called.  See mygetbuf() for possible error
  7111.  * returns.
  7112.  *
  7113.  * This should be efficient enough for any one-character-at-a-time loops.
  7114.  * For even better efficiency you might use memcpy()/bcopy() or such between
  7115.  * buffers (since they are often better optimized for copying), but it may not
  7116.  * be worth it if you have to take an extra pass over the buffer to strip
  7117.  * parity and check for CTRL-C anyway.
  7118.  *
  7119.  * Note that if you have been using myread() from another program module, you
  7120.  * may have some trouble accessing this macro version and the private variables
  7121.  * it uses.  In that case, just add a function in this module, that invokes the
  7122.  * macro.
  7123.  */
  7124. #define myread() (--my_count < 0 ? mygetbuf() : 255 & (int)mybuf[++my_item])
  7125.  
  7126. /* Specification: Push back up to one character onto myread()'s queue.
  7127.  *
  7128.  * This implementation: Push back characters into mybuf. At least one character
  7129.  * must have been read through myread() before myunrd() may be used.  After
  7130.  * EOF or read error, again, myunrd() can not be used.  Sometimes more than
  7131.  * one character can be pushed back, but only one character is guaranteed.
  7132.  * Since a previous myread() must have read its character out of mybuf[],
  7133.  * that guarantees that there is space for at least one character.  If push
  7134.  * back was really needed after EOF, a small addition could provide that.
  7135.  *
  7136.  * myunrd() is currently not called from anywhere inside kermit...
  7137.  */
  7138. #ifdef COMMENT /* not used */
  7139. myunrd(ch) CHAR ch; {
  7140.     if (my_item >= 0) {
  7141.     mybuf[my_item--] = ch;
  7142.     ++my_count;
  7143.     }
  7144. }
  7145. #endif /* COMMENT */
  7146.  
  7147. /*  T T P U S H B A C K  --  Put n bytes back into the myread buffer */
  7148.  
  7149. static CHAR * pushbuf = NULL;
  7150. static int pushed = 0;
  7151.  
  7152. int
  7153. ttpushback(s,n) CHAR * s; int n; {
  7154.     debug(F101,"ttpushback n","",n);
  7155.     if (pushbuf || n > MYBUFLEN || n < 1)
  7156.       return(-1);
  7157.     debug(F101,"ttpushback my_count","",my_count);
  7158.     if (my_count > 0) {
  7159.     if (!(pushbuf = (CHAR *)malloc(n+1)))
  7160.       return(-1);
  7161.     memcpy(pushbuf,mybuf,my_count);
  7162.     pushed = my_count;
  7163.     }
  7164.     memcpy(mybuf,s,n);
  7165.     my_count = n;
  7166.     my_item = -1;
  7167.     return(0);
  7168. }
  7169.  
  7170. /* mygetbuf() -- Fill buffer for myread() and return first character.
  7171.  *
  7172.  * This function is what myread() uses when it can't get the next character
  7173.  * directly from its buffer.  First, it calls a system dependent myfillbuf()
  7174.  * to read at least one new character into the buffer, and then it returns
  7175.  * the first character just as myread() would have done.  This function also
  7176.  * is responsible for all error conditions that myread() can indicate.
  7177.  *
  7178.  * Returns: When OK    => a positive character, 0 or greater.
  7179.  *        When EOF    => -2.
  7180.  *        When error    => -3, error code in errno.
  7181.  *
  7182.  * Older myread()s additionally returned -1 to indicate that there was nothing
  7183.  * to read, upon which the caller would call myread() again until it got
  7184.  * something.  The new myread()/mygetbuf() always gets something.  If it
  7185.  * doesn't, then make it do so!  Any program that actually depends on the old
  7186.  * behaviour will break.
  7187.  *
  7188.  * The older version also used to return -2 both for EOF and other errors,
  7189.  * and used to set errno to 9999 on EOF.  The errno stuff is gone, EOF and
  7190.  * other errors now return different results, although Kermit currently never
  7191.  * checks to see which it was.  It just disconnects in both cases.
  7192.  *
  7193.  * Kermit lets the user use the quit key to perform some special commands
  7194.  * during file transfer.  This causes read(), and thus also mygetbuf(), to
  7195.  * finish without reading anything and return the EINTR error.  This should
  7196.  * be checked by the caller.  Mygetbuf() could retry the read() on EINTR,
  7197.  * but if there is nothing to read, this could delay Kermit's reaction to
  7198.  * the command, and make Kermit appear unresponsive.
  7199.  *
  7200.  * The debug() call should be removed for optimum performance.
  7201.  */
  7202. int
  7203. mygetbuf() {
  7204.     int x;
  7205.     errno = 0;
  7206. #ifdef DEBUG
  7207.     if (deblog && my_count > 0)
  7208.       debug(F101,"mygetbuf IMPROPERLY CALLED with my_count","",my_count);
  7209. #endif /* DEBUG */
  7210.     if (my_count <= 0)
  7211.       my_count = myfillbuf();
  7212.  
  7213. #ifdef DEBUG
  7214.     if (deblog) debug(F101, "mygetbuf read", "", my_count);
  7215. #endif /* DEBUG */
  7216.     x = my_count;
  7217.     if (my_count <= 0) {
  7218.     my_count = 0;
  7219.     my_item = -1;
  7220.     debug(F101,"mygetbuf errno","",errno);
  7221. #ifdef TCPSOCKET
  7222.     if (netconn && ttnet == NET_TCPB && errno != 0) {
  7223.         if (errno != EINTR) {
  7224.         debug(F101,"mygetbuf TCP error","",errno);
  7225.         ttclos(0);        /* Close the connection. */
  7226.         }
  7227.         return(-3);
  7228.     }
  7229. #endif /* TCPSOCKET */
  7230.     if (!netconn && xlocal && errno) {
  7231.         if (errno != EINTR) {
  7232.         debug(F101,"mygetbuf SERIAL error","",errno);
  7233.         x = -3;
  7234.         ttclos(0);        /* Close the connection. */
  7235.         }
  7236.     }
  7237.     return((x < 0) ? -3 : -2);
  7238.     }
  7239.     --my_count;
  7240.     return((unsigned)(0xff & mybuf[my_item = 0]));
  7241. }
  7242.  
  7243. /* myfillbuf():
  7244.  * System-dependent read() into mybuf[], as many characters as possible.
  7245.  *
  7246.  * Returns: OK => number of characters read, always more than zero.
  7247.  *          EOF => 0
  7248.  *          Error => -1, error code in errno.
  7249.  *
  7250.  * If there is input available in the system's buffers, all of it should be
  7251.  * read into mybuf[] and the function return immediately.  If no input is
  7252.  * available, it should wait for a character to arrive, and return with that
  7253.  * one in mybuf[] as soon as possible.  It may wait somewhat past the first
  7254.  * character, but be aware that any such delay lengthens the packet turnaround
  7255.  * time during kermit file transfers.  Should never return with zero characters
  7256.  * unless EOF or irrecoverable read error.
  7257.  *
  7258.  * Correct functioning depends on the correct tty parameters being used.
  7259.  * Better control of current parameters is required than may have been the
  7260.  * case in older Kermit releases.  For instance, O_NDELAY (or equivalent) can
  7261.  * no longer be sometimes off and sometimes on like it used to, unless a
  7262.  * special myfillbuf() is written to handle that.  Otherwise the ordinary
  7263.  * myfillbuf()s may think they have come to EOF.
  7264.  *
  7265.  * If your system has a facility to directly perform the functioning of
  7266.  * myfillbuf(), then use it.  If the system can tell you how many characters
  7267.  * are available in its buffers, then read that amount (but not less than 1).
  7268.  * If the system can return a special indication when you try to read without
  7269.  * anything to read, while allowing you to read all there is when there is
  7270.  * something, you may loop until there is something to read, but probably that
  7271.  * is not good for the system load.
  7272.  */
  7273.  
  7274. #ifdef SVORPOSIX
  7275.     /* This is for System III/V with VMIN>0, VTIME=0 and O_NDELAY off,
  7276.      * and CLOCAL set any way you like.  This way, read() will do exactly
  7277.      * what is required by myfillbuf(): If there is data in the buffers
  7278.      * of the O.S., all available data is read into mybuf, up to the size
  7279.      * of mybuf.  If there is none, the first character to arrive is
  7280.      * awaited and returned.
  7281.      */
  7282. int
  7283. myfillbuf() {
  7284.     int fd, n;
  7285. #ifdef NETCMD
  7286.     if (ttpipe)
  7287.       fd = fdin;
  7288.     else
  7289. #endif /* NETCMD */
  7290.       fd = ttyfd;
  7291.  
  7292. #ifdef sxaE50
  7293.     /* From S. Dezawa at Fujifilm in Japan.  I don't know why this is */
  7294.     /* necessary for the sxa E50, but it is. */
  7295.     return read(fd, mybuf, 255);
  7296. #else
  7297. #ifdef BEOSORBEBOX
  7298.     while (1) {
  7299. #ifdef NETCONN
  7300.         if (netconn) {
  7301.             n = netxin(sizeof(mybuf), (char *)mybuf);
  7302.             debug(F101,"BEBOX SVORPOSIX network myfillbuf","",n);
  7303.     }
  7304.         else
  7305. #endif /* NETCONN */
  7306.       n = read(fd, mybuf, sizeof(mybuf));
  7307.     debug(F101,"BEBOX SVORPOSIX notnet myfillbuf","",n);
  7308.         if (n > 0)
  7309.       return(n);
  7310.         snooze(1000.0);
  7311.     }
  7312. #else /* BEOSORBEBOX */
  7313.     errno = 0;
  7314.     debug(F100,"SVORPOSIX myfillbuf calling read()","",0);
  7315. #ifdef IBMX25
  7316.     if (netconn && (nettype == NET_IX25)) {
  7317.     /* can't use sizeof because mybuf is a pointer, and not an array! */
  7318.     n = x25xin( MYBUFLEN, mybuf );
  7319.     } else
  7320. #endif /* IBMX25 */
  7321.  
  7322. #ifdef CK_SSL
  7323.       if (ssl_active_flag || tls_active_flag) {
  7324.       int error, n = 0;
  7325.       while (n == 0) {
  7326.           if (ssl_active_flag)
  7327.                 n = SSL_read(ssl_con, (char *)mybuf, sizeof(mybuf));
  7328.           else if (tls_active_flag)
  7329.                 n = SSL_read(tls_con, (char *)mybuf, sizeof(mybuf));
  7330.               else
  7331.         break;
  7332.           switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,n)) {
  7333.         case SSL_ERROR_NONE:
  7334.           if (n > 0)
  7335.                     return(n);
  7336.           if (n < 0)
  7337.                     return(-2);
  7338.           msleep(50);
  7339.           break;
  7340.         case SSL_ERROR_WANT_WRITE:
  7341.         case SSL_ERROR_WANT_READ:
  7342.           return(-1);
  7343.         case SSL_ERROR_SYSCALL:
  7344.         case SSL_ERROR_WANT_X509_LOOKUP:
  7345.         case SSL_ERROR_SSL:
  7346.         case SSL_ERROR_ZERO_RETURN:
  7347.         default:
  7348.           ttclos(0);
  7349.           return(-3);
  7350.             }
  7351.         }
  7352.     }
  7353. #endif /* CK_SSL */
  7354. #ifdef RLOGCODE
  7355. #ifdef CK_KERBEROS
  7356. #ifdef KRB4
  7357.     if (ttnproto == NP_EK4LOGIN) {
  7358.         if ((n = krb4_des_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
  7359.       return(-3);
  7360.         else
  7361.       return(n);
  7362.     }
  7363. #endif /* KRB4 */
  7364. #ifdef KRB5
  7365.     if (ttnproto == NP_EK5LOGIN) {
  7366.         if ((n = krb5_des_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
  7367.       return(-3);
  7368.         else
  7369.       return(n);
  7370.     }
  7371. #endif /* KRB5 */
  7372. #endif /* CK_KERBEROS */
  7373. #endif /* RLOGCODE */
  7374.  
  7375. #ifdef NETPTY
  7376. #ifdef HAVE_PTYTRAP
  7377.     /* Special handling for HP-UX pty i/o */
  7378.   ptyread:
  7379.     if (ttpty && pty_trap_pending(ttyfd) > 0) {
  7380.         if (pty_trap_handler(ttyfd) > 0) {
  7381.             ttclos(0);
  7382.             return(-3);
  7383.         }
  7384.     }
  7385. #endif /* HAVE_PTYTRAP */
  7386. #endif /* NETPTY */
  7387.     n = read(fd, mybuf, sizeof(mybuf));
  7388.     debug(F101,"SVORPOSIX myfillbuf","",n);
  7389.     debug(F101,"SVORPOSIX myfillbuf ttcarr","",ttcarr);
  7390.     debug(F101,"SVORPOSIX myfillbuf errno","",errno);
  7391.     if (n < 1) {
  7392. #ifdef NETPTY
  7393. #ifdef HAVE_PTYTRAP
  7394.         /* When we have a PTY trap in place the connection cannot */
  7395.         /* be closed until the trap receives a close indication.  */
  7396.         if (n == 0 && ttpty)
  7397.             goto ptyread;
  7398. #endif /* HAVE_PTYTRAP */
  7399. #endif /* NETPTY */
  7400.         return(-3);
  7401.     }
  7402.     return(n);
  7403. #endif /* BEOSORBEBOX */
  7404. #endif /* sxaE50 */
  7405. }
  7406.  
  7407. #else /* not AT&T or POSIX */
  7408.  
  7409. #ifdef aegis
  7410.     /* This is quoted from the old myread().  The semantics seem to be
  7411.      * alright, but maybe errno would not need to be set even when
  7412.      * there is no error?  I don't know aegis.
  7413.      */
  7414. int
  7415. myfillbuf() {
  7416.     int count;
  7417. #ifdef NETCMD
  7418.     if (ttpipe)
  7419.       fd = fdin;
  7420.     else
  7421. #endif /* NETCMD */
  7422.       fd = ttyfd;
  7423.  
  7424.     count = ios_$get((short)fd, ios_$cond_opt, mybuf, 256L, st);
  7425.     errno = EIO;
  7426.     if (st.all == ios_$get_conditional_failed) /* get at least one */
  7427.       count = ios_$get((short)fd, 0, mybuf, 1L, st);
  7428.     if (st.all == ios_$end_of_file)
  7429.       return(-3);
  7430.     else if (st.all != status_$ok) {
  7431.     errno = EIO;
  7432.     return(-1);
  7433.     }
  7434.     return(count > 0 ? count : -3);
  7435. }
  7436. #else /* !aegis */
  7437.  
  7438. #ifdef FIONREAD
  7439.     /* This is for systems with FIONREAD.  FIONREAD returns the number
  7440.      * of characters available for reading. If none are available, wait
  7441.      * until something arrives, otherwise return all there is.
  7442.      */
  7443. int
  7444. myfillbuf() {
  7445.     PEEKTYPE avail = 0;
  7446.     int x, fd;
  7447. #ifdef NETCMD
  7448.     if (ttpipe)
  7449.       fd = fdin;
  7450.     else
  7451. #endif /* NETCMD */
  7452.       fd = ttyfd;
  7453.  
  7454. #ifdef SUNX25
  7455. /*
  7456.   SunLink X.25 support in this routine from Stefaan A. Eeckels, Eurostat (CEC).
  7457.   Depends on SunOS having FIONREAD, not because we use it, but just so this
  7458.   code is grouped correctly within the #ifdefs.  Let's hope Solaris keeps it.
  7459.  
  7460.   We call x25xin() instead of read() so that Q-Bit packets, which contain
  7461.   X.25 service-level information (e.g. PAD parameter changes), can be processed
  7462.   transparently to the upper-level code.  This is a blocking read, and so
  7463.   we depend on higher-level code (such as ttinc()) to set any necessary alarms.
  7464. */
  7465.     extern int nettype;
  7466.     if (netconn && nettype == NET_SX25) {
  7467.     while ((x = x25xin(sizeof(x25buf), x25buf)) < 1) ;
  7468.     return(x - 1);            /* "-1" compensates for extra status byte */
  7469.     }
  7470. #endif /* SUNX25 */
  7471.  
  7472. #ifdef CK_SSL
  7473.     if (ssl_active_flag || tls_active_flag) {
  7474.         int error, n = 0;
  7475.         while (n == 0) {
  7476.             if (ssl_active_flag)
  7477.           n = SSL_read(ssl_con, (char *)mybuf, sizeof(mybuf));
  7478.             else
  7479.           n = SSL_read(tls_con, (char *)mybuf, sizeof(mybuf));
  7480.             switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,n)) {
  7481.           case SSL_ERROR_NONE:
  7482.                 if (n > 0)
  7483.           return(n);
  7484.                 if (n < 0)
  7485.           return(-2);
  7486.                 msleep(50);
  7487.                 break;
  7488.           case SSL_ERROR_WANT_WRITE:
  7489.           case SSL_ERROR_WANT_READ:
  7490.                 return(-1);
  7491.           case SSL_ERROR_SYSCALL:
  7492.           case SSL_ERROR_WANT_X509_LOOKUP:
  7493.           case SSL_ERROR_SSL:
  7494.           case SSL_ERROR_ZERO_RETURN:
  7495.           default:
  7496.                 ttclos(0);
  7497.                 return(-2);
  7498.             }
  7499.         }
  7500.     }
  7501. #endif /* CK_SSL */
  7502. #ifdef RLOGCODE
  7503. #ifdef CK_KERBEROS
  7504. #ifdef KRB4
  7505.     if (ttnproto == NP_EK4LOGIN) {
  7506.         if ((x = krb4_des_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
  7507.       return(-1);
  7508.         else
  7509.       return(x);
  7510.     }
  7511. #endif /* KRB4 */
  7512. #ifdef KRB5
  7513.     if (ttnproto == NP_EK5LOGIN) {
  7514.         if ((x = krb5_des_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
  7515.       return(-1);
  7516.         else
  7517.       return(x);
  7518.     }
  7519. #endif /* KRB5 */
  7520. #endif /* CK_KERBEROS */
  7521. #endif /* RLOGCODE */
  7522.  
  7523.     errno = 0;
  7524.     debug(F101,"myfillbuf calling FIONREAD ioctl","",xlocal);
  7525.     x = ioctl(fd, FIONREAD, &avail);
  7526. #ifdef DEBUG
  7527.     if (deblog) {
  7528.     debug(F101,"myfillbuf FIONREAD","",x);
  7529.     debug(F101,"myfillbuf FIONREAD avail","",avail);
  7530.     debug(F101,"myfillbuf FIONREAD errno","",errno);
  7531.     }
  7532. #endif /* DEBUG */
  7533.     if (x < 0 || avail == 0)
  7534.       avail = 1;
  7535.  
  7536.     if (avail > MYBUFLEN)
  7537.       avail = MYBUFLEN;
  7538.  
  7539.     errno = 0;
  7540.  
  7541.     x = read(fd, mybuf, (int) avail);
  7542. #ifdef DEBUG
  7543.     if (deblog) {
  7544.     debug(F101,"myfillbuf avail","",avail);
  7545.     debug(F101,"myfillbuf read","",x);
  7546.     debug(F101,"myfillbuf read errno","",errno);
  7547.         if (x > 0)
  7548.       hexdump("myfillbuf mybuf",mybuf,x);
  7549.     }
  7550. #endif /* DEBUG */
  7551.     if (x < 1) x = -3;            /* read 0 == connection loss */
  7552.     return(x);
  7553. }
  7554.  
  7555. #else /* !FIONREAD */
  7556. /* Add other systems here, between #ifdef and #else, e.g. NETCONN. */
  7557. /* When there is no other possibility, read 1 character at a time. */
  7558. int
  7559. myfillbuf() {
  7560.     int x;
  7561.  
  7562. #ifdef CK_SSL
  7563.     if (ssl_active_flag || tls_active_flag) {
  7564.         int error, n = 0;
  7565.         while (n == 0) {
  7566.             if (ssl_active_flag)
  7567.           n = SSL_read(ssl_con, (char *)mybuf, sizeof(mybuf));
  7568.             else
  7569.           count = SSL_read(tls_con, (char *)mybuf, sizeof(mybuf));
  7570.             switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,n)) {
  7571.           case SSL_ERROR_NONE:
  7572.                 if (n > 0)
  7573.           return(n);
  7574.                 if (n < 0)
  7575.           return(-2);
  7576.                 msleep(50);
  7577.                 break;
  7578.           case SSL_ERROR_WANT_WRITE:
  7579.           case SSL_ERROR_WANT_READ:
  7580.                 return(-1);
  7581.           case SSL_ERROR_SYSCALL:
  7582.           case SSL_ERROR_WANT_X509_LOOKUP:
  7583.           case SSL_ERROR_SSL:
  7584.           case SSL_ERROR_ZERO_RETURN:
  7585.           default:
  7586.                 ttclos(0);
  7587.                 return(-2);
  7588.             }
  7589.         }
  7590.     }
  7591. #endif /* CK_SSL */
  7592. #ifdef RLOGCODE
  7593. #ifdef CK_KERBEROS
  7594. #ifdef KRB4
  7595.     if (ttnproto == NP_EK4LOGIN) {
  7596.         if ((len = krb4_des_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
  7597.       return(-1);
  7598.         else
  7599.       return(len);
  7600.     }
  7601. #endif /* KRB4 */
  7602. #ifdef KRB5
  7603.     if (ttnproto == NP_EK5LOGIN) {
  7604.         if ((len = krb5_des_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
  7605.       return(-1);
  7606.         else
  7607.       return(len);
  7608.     }
  7609. #endif /* KRB5 */
  7610. #endif /* CK_KERBEROS */
  7611. #endif /* RLOGCODE */
  7612.  
  7613. #ifdef NETCMD
  7614.     if (ttpipe)
  7615.       fd = fdin;
  7616.     else
  7617. #endif /* NETCMD */
  7618.       fd = ttyfd;
  7619.     x = read(fd, mybuf, 1);
  7620.     return(x > 0 ? x : -3);
  7621. }
  7622.  
  7623. #endif /* !FIONREAD */
  7624. #endif /* !aegis */
  7625. #endif /* !ATTSV */
  7626.  
  7627. #endif /* MYREAD */
  7628.  
  7629. #ifdef MINIX2
  7630. #undef MINIX
  7631. #endif /* MINIX2 */
  7632.  
  7633. /*  T T _ T N O P T  --  Handle Telnet negotions in incoming data */
  7634. /*
  7635.   Call with the IAC that was encountered.
  7636.   Returns:
  7637.    -3: If connection has dropped or gone bad.
  7638.    -2: On Telnet protocol error resulting in inconsistent states.
  7639.     0: If negotiation OK and caller has nothing to do.
  7640.     1: If packet start character has changed (new value is in global stchr).
  7641.   255: If there was a quoted IAC as data.
  7642.    or: Not at all if we got a legitimate Telnet Logout request.
  7643. */
  7644. #ifdef TCPSOCKET
  7645. static int
  7646. tt_tnopt(n) int n; {            /* Handle Telnet options */
  7647.     /* In case caller did not already check these conditions...  */
  7648.     if (n == IAC &&
  7649.     ((xlocal && netconn && (ttnproto == NP_TELNET)) ||
  7650.      (!xlocal && sstelnet))) {
  7651.     extern int duplex;
  7652.     extern int server;
  7653.     int tx = 0;
  7654.     debug(F100,"ttinl calling tn_doop()","",0);
  7655.     tx = tn_doop((CHAR)(n & 0xff),duplex,ttinc);
  7656.     debug(F111,"ttinl tn_doop() returned","tx",tx);
  7657.     switch (tx) {
  7658.       case 0:
  7659.         return(0);
  7660.       case -1:            /* I/O error */
  7661.         ttimoff();            /* Turn off timer */
  7662.         return(-3);
  7663.           case -2:            /* Connection failed. */
  7664.           case -3:
  7665.         ttimoff();            /* Turn off timer */
  7666.         ttclos(0);
  7667.         return(-3);
  7668.       case 1:            /* ECHO change */
  7669.         duplex = 1;
  7670.         return(0);
  7671.       case 2:            /* ECHO change */
  7672.         duplex = 0;
  7673.         return(0);
  7674.       case 3:            /* Quoted IAC */
  7675.         n = 255;
  7676.         return((unsigned)255);
  7677. #ifdef IKS_OPTION
  7678.       case 4: {
  7679.           if (TELOPT_SB(TELOPT_KERMIT).kermit.u_start && server
  7680. #ifdef IKSD
  7681.           && !inserver
  7682. #endif /* IKSD */
  7683.           ) {            /* Remote in Server mode */
  7684.           ttimoff();        /* Turn off timer */
  7685.           debug(F100,"u_start and !inserver","",0);
  7686.           return(-2);        /* End server mode */
  7687.           } else if (!TELOPT_SB(TELOPT_KERMIT).kermit.me_start &&
  7688.              server
  7689.              ) {        /* I'm no longer in Server Mode */
  7690.           debug(F100,"me_start and server","",0);
  7691.           ttimoff();
  7692.           return(-2);
  7693.           }
  7694.           return(0);
  7695.       }
  7696.       case 5: {            /* Start character change */
  7697.           /* extern CHAR stchr; */
  7698.           /* start = stchr; */
  7699.           return(1);
  7700.       }
  7701. #endif /* IKS_OPTION */
  7702.       case 6:            /* Remote Logout */
  7703.         ttimoff();
  7704.         ttclos(0);
  7705. #ifdef IKSD
  7706.         if (inserver && !local)
  7707.           doexit(GOOD_EXIT,0);
  7708.         else
  7709. #endif /* IKSD */
  7710.           return(-2);
  7711.       default:
  7712.         return(0);
  7713.     }
  7714.     } else
  7715.       return(0);
  7716. }
  7717. #endif /* TCPSOCKET */
  7718.  
  7719. /*  T T F L U I  --  Flush tty input buffer */
  7720.  
  7721. void
  7722. ttflux() {                /* But first... */
  7723. #ifdef MYREAD
  7724. /*
  7725.   Flush internal MYREAD buffer.
  7726. */
  7727. #ifdef TCPSOCKET
  7728.     int dotnopts, x;
  7729.     dotnopts = (((xlocal && netconn && (ttnproto == NP_TELNET)) ||
  7730.          (!xlocal && sstelnet)));
  7731. #endif /* TCPSOCKET */
  7732.     debug(F101,"ttflux my_count","",my_count);
  7733. #ifdef TCPSOCKET
  7734.     if (dotnopts) {
  7735.     CHAR ch = '\0';
  7736.         while (my_count > 0) {
  7737.         ch = myread();
  7738. #ifdef CK_ENCRYPTION
  7739.             if (TELOPT_U(TELOPT_ENCRYPTION))
  7740.           ck_tn_decrypt(&ch,1);
  7741. #endif /* CK_ENCRYPTION */
  7742.             if (ch == IAC)
  7743.           x = tt_tnopt(ch);
  7744.         }
  7745.     } else
  7746. #endif /* TCPSOCKET */
  7747. #ifdef COMMENT
  7748. #ifdef CK_ENCRYPTION
  7749.     if (TELOPT_U(TELOPT_ENCRYPTION) && my_count > 0)
  7750.       ck_tn_decrypt(&mybuf[my_item+1],my_count);
  7751. #endif /* CK_ENCRYPTION */
  7752. #endif /* COMMENT */
  7753.     my_count = 0;            /* Reset count to zero */
  7754.     my_item = -1;            /* And buffer index to -1 */
  7755. #endif /* MYREAD */
  7756. }
  7757.  
  7758. int
  7759. ttflui() {
  7760.     int n, fd;
  7761. #ifdef TCPSOCKET
  7762.     int dotnopts;
  7763.     dotnopts = (((xlocal && netconn && (ttnproto == NP_TELNET)) ||
  7764.          (!xlocal && sstelnet)));
  7765. #endif /* TCPSOCKET */
  7766.  
  7767. #ifdef NETCMD
  7768.     if (ttpipe)
  7769.       fd = fdin;
  7770.     else
  7771. #endif /* NETCMD */
  7772.       fd = ttyfd;
  7773.  
  7774. #ifdef TTLEBUF
  7775.     ttpush = -1;            /* Clear the peek-ahead char */
  7776.     while (le_data && (le_inbuf() > 0)) {
  7777.         CHAR ch = '\0';
  7778.         if (le_getchar(&ch) > 0) {    /* Clear any more... */
  7779.             debug(F101,"ttflui le_inbuf ch","",ch);
  7780.         }
  7781.     }
  7782. #endif /* TTLEBUF */
  7783.     debug(F101,"ttflui ttpipe","",ttpipe);
  7784.  
  7785. #ifdef MYREAD
  7786. /*
  7787.   Flush internal MYREAD buffer *NEXT*, in all cases.
  7788. */
  7789.     ttflux();
  7790. #endif /* MYREAD */
  7791.  
  7792. #ifdef NETCONN
  7793. /* Network flush is done specially, in the network support module. */
  7794.     if ((netconn || sstelnet) && !ttpipe && !ttpty) {
  7795.     debug(F100,"ttflui netflui","",0);
  7796.     return(netflui());
  7797.     }
  7798. #endif /* NETCONN */
  7799.  
  7800.     debug(F101,"ttflui ttyfd","",ttyfd); /* Not network */
  7801.     if (ttyfd < 0)
  7802.       return(-1);
  7803.  
  7804. #ifdef aegis
  7805.     sio_$control((short)yfd, sio_$flush_in, true, st);
  7806.     if (st.all != status_$ok) {
  7807.     fprintf(stderr, "flush failed: "); error_$print(st);
  7808.     } else {      /* sometimes the flush doesn't work */
  7809.         for (;;) {
  7810.         char buf[256];
  7811.             /* eat all the characters that shouldn't be available */
  7812.             ios_$get((short)fd, ios_$cond_opt, buf, 256L, st); /* (void) */
  7813.             if (st.all == ios_$get_conditional_failed) break;
  7814.             fprintf(stderr, "flush failed(2): "); error_$print(st);
  7815.         }
  7816.     }
  7817. #else
  7818. #ifdef BSD44                /* 4.4 BSD */
  7819.     n = FREAD;                          /* Specify read queue */
  7820.     debug(F100,"ttflui BSD44","",0);
  7821.     ioctl(fd,TIOCFLUSH,&n);
  7822. #else
  7823. #ifdef Plan9
  7824. #undef POSIX                /* Uh oh... */
  7825. #endif /* Plan9 */
  7826. #ifdef POSIX                /* POSIX */
  7827.     debug(F100,"ttflui POSIX","",0);
  7828.     tcflush(fd,TCIFLUSH);
  7829. #else
  7830. #ifdef ATTSV                /* System V */
  7831. #ifndef VXVE
  7832.     debug(F100,"ttflui ATTSV","",0);
  7833.     ioctl(fd,TCFLSH,0);
  7834. #endif /* VXVE */
  7835. #else                    /* Not BSD44, POSIX, or Sys V */
  7836. #ifdef TIOCFLUSH            /* Those with TIOCFLUSH defined */
  7837. #ifdef ANYBSD                /* Berkeley */
  7838.     n = FREAD;                          /* Specify read queue */
  7839.     debug(F100,"ttflui TIOCFLUSH ANYBSD","",0);
  7840.     ioctl(fd,TIOCFLUSH,&n);
  7841. #else                    /* Others (V7, etc) */
  7842.     debug(F100,"ttflui TIOCFLUSH","",0);
  7843.     ioctl(fd,TIOCFLUSH,0);
  7844. #endif /* ANYBSD */
  7845. #else                    /* All others... */
  7846. /*
  7847.   No system call (that we know about) for input buffer flushing.
  7848.   So see how many there are and read them in a loop, using ttinc().
  7849.   ttinc() is buffered, so we're not getting charged with a system call
  7850.   per character, just a function call.
  7851. */
  7852.     if ((n = ttchk()) > 0) {
  7853.     debug(F101,"ttflui read loop","",n);
  7854.     while ((n--) && ttinc(0) > 0) ;
  7855.     }
  7856. #endif /* TIOCFLUSH */
  7857. #endif /* ATTSV */
  7858. #endif /* POSIX */
  7859. #ifdef Plan9
  7860. #define POSIX
  7861. #endif /* Plan9 */
  7862. #endif /* BSD44 */
  7863. #endif /* aegis */
  7864.     return(0);
  7865. }
  7866.  
  7867. int
  7868. ttfluo() {                /* Flush output buffer */
  7869.     int fd;
  7870. #ifdef NETCMD
  7871.     if (ttpipe)
  7872.       fd = fdout;
  7873.     else
  7874. #endif /* NETCMD */
  7875.       fd = ttyfd;
  7876.  
  7877. #ifdef Plan9
  7878.     return 0;
  7879. #else
  7880. #ifdef POSIX
  7881.     return(tcflush(fd,TCOFLUSH));
  7882. #else
  7883. #ifdef OXOS
  7884.     return(ioctl(fd,TCFLSH,1));
  7885. #else
  7886.     return(0);                /* All others, nothing */
  7887. #endif /* OXOS */
  7888. #endif /* POSIX */
  7889. #endif /* Plan9 */
  7890. }
  7891.  
  7892. /* Interrupt Functions */
  7893.  
  7894. /* Set up terminal interrupts on console terminal */
  7895.  
  7896. #ifndef FIONREAD            /* We don't need esctrp() */
  7897. #ifndef SELECT                /* if we have any of these... */
  7898. #ifndef CK_POLL
  7899. #ifndef RDCHK
  7900.  
  7901. #ifndef OXOS
  7902. #ifdef SVORPOSIX
  7903. SIGTYP
  7904. esctrp(foo) int foo; {            /* trap console escapes (^\) */
  7905.     signal(SIGQUIT,SIG_IGN);            /* ignore until trapped */
  7906.     conesc = 1;
  7907.     debug(F101,"esctrp caught SIGQUIT","",conesc);
  7908. }
  7909. #endif /* SVORPOSIX */
  7910. #endif /* OXOS */
  7911.  
  7912. #ifdef V7
  7913. #ifndef MINIX2
  7914. SIGTYP
  7915. esctrp(foo) int foo; {            /* trap console escapes (^\) */
  7916.     signal(SIGQUIT,SIG_IGN);            /* ignore until trapped */
  7917.     conesc = 1;
  7918.     debug(F101,"esctrp caught SIGQUIT","",conesc);
  7919. }
  7920. #endif /* MINIX2 */
  7921. #endif /* V7 */
  7922.  
  7923. #ifdef C70
  7924. SIGTYP
  7925. esctrp(foo) int foo; {            /* trap console escapes (^\) */
  7926.     conesc = 1;
  7927.     signal(SIGQUIT,SIG_IGN);            /* ignore until trapped */
  7928. }
  7929. #endif /* C70 */
  7930.  
  7931. #endif /* RDCHK */
  7932. #endif /* CK_POLL */
  7933. #endif /* SELECT */
  7934. #endif /* FIONREAD */
  7935.  
  7936. /*  C O N B G T  --  Background Test  */
  7937.  
  7938. static int jc = 0;            /* 0 = no job control */
  7939.  
  7940. /*
  7941.   Call with flag == 1 to prevent signal test, which can not be expected
  7942.   to work during file transfer, when SIGINT probably *is* set to SIG_IGN.
  7943.  
  7944.   Call with flag == 0 to use the signal test, but only if the process-group
  7945.   test fails, as it does on some UNIX systems, where getpgrp() is buggy,
  7946.   requires an argument when the man page says it doesn't, or vice versa.
  7947.  
  7948.   If flag == 0 and the process-group test fails, then we determine background
  7949.   status simply (but not necessarily reliably) from isatty().
  7950.  
  7951.   conbgt() sets the global backgrd = 1 if we appear to be in the background,
  7952.   and to 0 if we seem to be in the foreground.  conbgt() is highly prone to
  7953.   misbehavior.
  7954. */
  7955. VOID
  7956. conbgt(flag) int flag; {
  7957.     int x = -1,                /* process group or SIGINT test */
  7958.         y = 0;                /* isatty() test */
  7959. /*
  7960.   Check for background operation, even if not running on real tty, so that
  7961.   background flag can be set correctly.  If background status is detected,
  7962.   then Kermit will not issue its interactive prompt or most messages.
  7963.   If your prompt goes away, you can blame (and fix?) this function.
  7964. */
  7965.  
  7966. /* Use process-group test if possible. */
  7967.  
  7968. #ifdef POSIX                /* We can do it in POSIX */
  7969. #define PGROUP_T
  7970. #else
  7971. #ifdef BSD4                /* and in BSD 4.x. */
  7972. #define PGROUP_T
  7973. #else
  7974. #ifdef HPUXJOBCTL            /* and in most HP-UX's */
  7975. #define PGROUP_T
  7976. #else
  7977. #ifdef TIOCGPGRP            /* and anyplace that has this ioctl. */
  7978. #define PGROUP_T
  7979. #endif /* TIOCGPGRP */
  7980. #endif /* HPUXJOBCTL */
  7981. #endif /* BSD4 */
  7982. #endif /* POSIX */
  7983.  
  7984. #ifdef MIPS                /* Except if it doesn't work... */
  7985. #undef PGROUP_T
  7986. #endif /* MIPS */
  7987.  
  7988. #ifdef PGROUP_T
  7989. /*
  7990.   Semi-reliable process-group test.  Check whether this process's group is
  7991.   the same as the controlling terminal's process group.  This works if the
  7992.   getpgrp() call doesn't lie (as it does in the SUNOS System V environment).
  7993. */
  7994.     PID_T mypgrp = (PID_T)0;        /* Kermit's process group */
  7995.     PID_T ctpgrp = (PID_T)0;        /* The terminal's process group */
  7996. #ifndef _POSIX_SOURCE
  7997. /*
  7998.   The getpgrp() prototype is obtained from system header files for POSIX
  7999.   and Sys V R4 compilations.  Other systems, who knows.  Some complain about
  8000.   a duplicate declaration here, others don't, so it's safer to leave it in
  8001.   if we don't know for certain.
  8002. */
  8003. #ifndef SVR4
  8004. #ifndef PS2AIX10
  8005. #ifndef HPUX9
  8006.     extern PID_T getpgrp();
  8007. #endif /* HPUX9 */
  8008. #endif /* PS2AIX10 */
  8009. #endif /* SVR4 */
  8010. #endif /* _POSIX_SOURCE */
  8011.  
  8012. /* Get my process group. */
  8013.  
  8014. #ifdef SVR3 /* Maybe this should be ATTSV? */
  8015. /* This function is not described in SVID R2 */
  8016.     mypgrp = getpgrp();
  8017.     /* debug(F101,"ATTSV conbgt process group","",(int) mypgrp); */
  8018. #else
  8019. #ifdef POSIX
  8020.     mypgrp = getpgrp();
  8021.     /* debug(F101,"POSIX conbgt process group","",(int) mypgrp); */
  8022. #else
  8023. #ifdef OSFPC
  8024.     mypgrp = getpgrp();
  8025.     /* debug(F101,"OSF conbgt process group","",(int) mypgrp); */
  8026. #else
  8027. #ifdef QNX
  8028.     mypgrp = getpgrp();
  8029.     /* debug(F101,"QNX conbgt process group","",(int) mypgrp); */
  8030. #else
  8031. #ifdef OSF32                /* (was OSF40) */
  8032.     mypgrp = getpgrp();
  8033.     /* debug(F101,"Digital UNIX conbgt process group","",(int) mypgrp); */
  8034. #else /* BSD, V7, etc */
  8035. #ifdef MINIX2
  8036.     mypgrp = getpgrp();
  8037. #else
  8038.     mypgrp = getpgrp(0);
  8039. #endif /* MINIX2 */
  8040.     /* debug(F101,"BSD conbgt process group","",(int) mypgrp); */
  8041. #endif /* OSF32 */
  8042. #endif /* QNX */
  8043. #endif /* OSFPC */
  8044. #endif /* POSIX */
  8045. #endif /* SVR3 */
  8046.  
  8047. #ifdef MINIX2
  8048. #undef BSD44ORPOSIX
  8049. #endif /* MINIX2 */
  8050.  
  8051. /* Now get controlling tty's process group */
  8052. #ifdef BSD44ORPOSIX
  8053.     ctpgrp = tcgetpgrp(1);        /* The POSIX way */
  8054.     /* debug(F101,"POSIX conbgt terminal process group","",(int) ctpgrp); */
  8055. #else
  8056.     ioctl(1, TIOCGPGRP, &ctpgrp);    /* Or the BSD way */
  8057.    /* debug(F101,"non-POSIX conbgt terminal process group","",(int) ctpgrp); */
  8058. #endif /* BSD44ORPOSIX */
  8059.  
  8060. #ifdef MINIX2
  8061. #define BSD44ORPOSIX
  8062. #endif /* MINIX2 */
  8063.  
  8064.     if ((mypgrp > (PID_T) 0) && (ctpgrp > (PID_T) 0))
  8065.       x = (mypgrp == ctpgrp) ? 0 : 1;    /* If they differ, then background. */
  8066.     else x = -1;            /* If error, remember. */
  8067.     debug(F101,"conbgt process group test","",x);
  8068. #endif /* PGROUP_T */
  8069.  
  8070. /* Try to see if job control is available */
  8071.  
  8072. #ifdef NOJC                /* User override */
  8073.     jc = 0;                /* No job control allowed */
  8074.     debug(F111,"NOJC","jc",jc);
  8075. #else
  8076. #ifdef BSD44
  8077.     jc = 1;
  8078. #else
  8079. #ifdef SVR4ORPOSIX            /* POSIX actually tells us */
  8080.     debug(F100,"SVR4ORPOSIX jc test...","",0);
  8081. #ifdef _SC_JOB_CONTROL
  8082. #ifdef __bsdi__
  8083.     jc = 1;
  8084. #else
  8085. #ifdef __386BSD__
  8086.     jc = 1;
  8087. #else
  8088.     jc = sysconf(_SC_JOB_CONTROL);    /* Whatever system says */
  8089.     if (jc < 0) {
  8090.     debug(F101,"sysconf fails, jcshell","",jcshell);
  8091.     jc = (jchdlr == SIG_DFL) ? 1 : 0;
  8092.     } else
  8093.       debug(F111,"sysconf(_SC_JOB_CONTROL)","jc",jc);
  8094. #endif /* __386BSD__ */
  8095. #endif /* __bsdi__ */
  8096. #else
  8097. #ifdef _POSIX_JOB_CONTROL
  8098.     jc = 1;                /* By definition */
  8099.     debug(F111,"_POSIX_JOB_CONTROL is defined","jc",jc);
  8100. #else
  8101.     jc = 0;                /* Assume job control not allowed */
  8102.     debug(F111,"SVR4ORPOSIX _SC/POSIX_JOB_CONTROL not defined","jc",jc);
  8103. #endif /* _POSIX_JOB_CONTROL */
  8104. #endif /* _SC_JOB_CONTROL */
  8105. #else
  8106. #ifdef BSD4
  8107.     jc = 1;                /* Job control allowed */
  8108.     debug(F111,"BSD job control","jc",jc);
  8109. #else
  8110. #ifdef SVR3JC
  8111.     jc = 1;                /* JC allowed */
  8112.     debug(F111,"SVR3 job control","jc",jc);
  8113. #else
  8114. #ifdef OXOS
  8115.     jc = 1;                /* JC allowed */
  8116.     debug(F111,"X/OS job control","jc",jc);
  8117. #else
  8118. #ifdef HPUX9
  8119.     jc = 1;                /* JC allowed */
  8120.     debug(F111,"HP-UX 9.0 job control","jc",jc);
  8121. #else
  8122. #ifdef HPUX10
  8123.     jc = 1;                /* JC allowed */
  8124.     debug(F111,"HP-UX 10.0 job control","jc",jc);
  8125. #else
  8126.     jc = 0;                /* JC not allowed */
  8127.     debug(F111,"job control catch-all","jc",jc);
  8128. #endif /* HPUX10 */
  8129. #endif /* HPUX9 */
  8130. #endif /* OXOS */
  8131. #endif /* SVR3JC */
  8132. #endif /* BSD4 */
  8133. #endif /* SVR4ORPOSIX */
  8134. #endif /* BSD44 */
  8135. #endif /* NOJC */
  8136.     debug(F101,"conbgt jc","",jc);
  8137. #ifndef NOJC
  8138.     debug(F101,"conbgt jcshell","",jcshell);
  8139. /*
  8140.   At this point, if jc == 1 but jcshell == 0, it means that the OS supports
  8141.   job control, but the shell or other process we are running under does not
  8142.   (jcshell is set in sysinit()) and so if we suspend ourselves, nothing good
  8143.   will come of it.  So...
  8144. */
  8145.     if (jc < 0) jc = 0;
  8146.     if (jc > 0 && jcshell == 0) jc = 0;
  8147. #endif /* NOJC */
  8148.  
  8149. /*
  8150.   Another background test.
  8151.   Test if SIGINT (terminal interrupt) is set to SIG_IGN (ignore),
  8152.   which is done by the shell (sh) if the program is started with '&'.
  8153.   Unfortunately, this is NOT done by csh or ksh so watch out!
  8154.   Note, it's safe to set SIGINT to SIG_IGN here, because further down
  8155.   we always set it to something else.
  8156.   Note: as of 16 Jul 1999, we also skip this test if we set SIGINT to
  8157.   SIG_IGN ourselves.
  8158. */
  8159.     if (x < 0 && !flag && !sigint_ign) { /* Didn't get good results above... */
  8160.  
  8161.     SIGTYP (*osigint)();
  8162.  
  8163.     osigint = signal(SIGINT,SIG_IGN);    /* What is SIGINT set to? */
  8164.     sigint_ign = 1;
  8165.     x = (osigint == SIG_IGN) ? 1 : 0;    /* SIG_IGN? */
  8166.     debug(F101,"conbgt osigint","",osigint);
  8167.     debug(F101,"conbgt signal test","",x);
  8168.     }
  8169.  
  8170. /* Also check to see if we're running with redirected stdio. */
  8171. /* This is not really background operation, but we want to act as though */
  8172. /* it were. */
  8173.  
  8174. #ifdef IKSD
  8175.     if (inserver) {            /* Internet Kermit Server */
  8176.     backgrd = 0;            /* is not in the background */
  8177.     return;
  8178.     }
  8179. #endif /* IKSD */
  8180.  
  8181.     y = (isatty(0) && isatty(1)) ? 1 : 0;
  8182.     debug(F101,"conbgt isatty test","",y);
  8183.  
  8184. #ifdef BSD29
  8185. /* The process group and/or signal test doesn't work under these... */
  8186.     backgrd = !y;
  8187. #else
  8188. #ifdef sxaE50
  8189.     backgrd = !y;
  8190. #else
  8191. #ifdef MINIX
  8192.     backgrd = !y;
  8193. #else
  8194. #ifdef MINIX2
  8195.     backgrd = !y;
  8196. #else
  8197.     if (x > -1)
  8198.       backgrd = (x || !y) ? 1 : 0;
  8199.     else backgrd = !y;
  8200. #endif /* BSD29 */
  8201. #endif /* sxaE50 */
  8202. #endif /* MINIX */
  8203. #endif /* MINIX2 */
  8204.     debug(F101,"conbgt backgrd","",backgrd);
  8205. }
  8206.  
  8207. /*  C O N I N T  --  Console Interrupt setter  */
  8208.  
  8209. /*
  8210.   First arg is pointer to function to handle SIGTERM & SIGINT (like Ctrl-C).
  8211.   Second arg is pointer to function to handle SIGTSTP (suspend).
  8212. */
  8213.  
  8214. VOID                    /* Set terminal interrupt traps. */
  8215. #ifdef CK_ANSIC
  8216. #ifdef apollo
  8217. conint(f,s) SIGTYP (*f)(), (*s)();
  8218. #else
  8219. conint(SIGTYP (*f)(int), SIGTYP (*s)(int))
  8220. #endif /* apollo */
  8221. #else
  8222. conint(f,s) SIGTYP (*f)(), (*s)();
  8223. #endif /* CK_ANSIC */
  8224. /* conint */ {
  8225.  
  8226.     conbgt(0);                /* Do background test. */
  8227.  
  8228. /* Set the desired handlers for hangup and software termination. */
  8229.  
  8230. #ifdef SIGTERM
  8231.     signal(SIGTERM,f);                  /* Software termination */
  8232. #endif /* SIGTERM */
  8233.  
  8234. /*
  8235.   Prior to July 1999 we used to call sighup() here but now it's called in
  8236.   sysinit() so SIGHUP can be caught during execution of the init file or
  8237.   a kerbang script.
  8238. */
  8239.  
  8240. /* Now handle keyboard stop, quit, and interrupt signals. */
  8241. /* Check if invoked in background -- if so signals set to be ignored. */
  8242. /* However, if running under a job control shell, don't ignore them. */
  8243. /* We won't be getting any, as we aren't in the terminal's process group. */
  8244.  
  8245.     debug(F101,"conint backgrd","",backgrd);
  8246.     debug(F101,"conint jc","",jc);
  8247.  
  8248.     if (backgrd && !jc) {        /* In background, ignore signals */
  8249.     debug(F101,"conint background ignoring signals, jc","",jc);
  8250. #ifdef SIGTSTP
  8251.         signal(SIGTSTP,SIG_IGN);        /* Keyboard stop */
  8252. #endif /* SIGTSTP */
  8253.         signal(SIGQUIT,SIG_IGN);        /* Keyboard quit */
  8254.         signal(SIGINT,SIG_IGN);         /* Keyboard interrupt */
  8255.     sigint_ign = 1;
  8256.     } else {                /* Else in foreground or suspended */
  8257.     debug(F101,"conint foreground catching signals, jc","",jc);
  8258.         signal(SIGINT,f);               /* Catch terminal interrupt */
  8259.     sigint_ign = (f == SIG_IGN) ? 1 : 0;
  8260.  
  8261. #ifdef SIGTSTP                /* Keyboard stop (suspend) */
  8262.     /* debug(F101,"conint SIGSTSTP","",s); */
  8263.     if (s == NULL) s = SIG_DFL;
  8264. #ifdef NOJC                /* No job control allowed. */
  8265.     signal(SIGTSTP,SIG_IGN);
  8266. #else                    /* Job control allowed */
  8267.     if (jc)                /* if available. */
  8268.       signal(SIGTSTP,s);
  8269.     else
  8270.       signal(SIGTSTP,SIG_IGN);
  8271. #endif /* NOJC */
  8272. #endif /* SIGTSTP */
  8273.  
  8274. #ifndef OXOS
  8275. #ifdef SVORPOSIX
  8276. #ifndef FIONREAD            /* Watch out, we don't know this... */
  8277. #ifndef SELECT
  8278. #ifndef CK_POLL
  8279. #ifndef RDCHK
  8280.         signal(SIGQUIT,esctrp);         /* Quit signal, Sys III/V. */
  8281. #endif /* RDCHK */
  8282. #endif /* CK_POLL */
  8283. #endif /* SELECT */
  8284. #endif /* FIONREAD */
  8285.         if (conesc) conesc = 0;         /* Clear out pending escapes */
  8286. #else
  8287. #ifdef V7
  8288.         signal(SIGQUIT,esctrp);         /* V7 like Sys III/V */
  8289.         if (conesc) conesc = 0;
  8290. #else
  8291. #ifdef aegis
  8292.         signal(SIGQUIT,f);              /* Apollo, catch it like others. */
  8293. #else
  8294.         signal(SIGQUIT,SIG_IGN);        /* Others, ignore like 4D & earlier. */
  8295. #endif /* aegis */
  8296. #endif /* V7 */
  8297. #endif /* SVORPOSIX */
  8298. #endif /* OXOS */
  8299.     }
  8300. }
  8301.  
  8302.  
  8303. /*  C O N N O I  --  Reset console terminal interrupts */
  8304.  
  8305. VOID
  8306. connoi() {                              /* Console-no-interrupts */
  8307.  
  8308.     debug(F100,"connoi","",0);
  8309. #ifdef SIGTSTP
  8310.     signal(SIGTSTP,SIG_IGN);        /* Suspend */
  8311. #endif /* SIGTSTP */
  8312.     conint(SIG_IGN,SIG_IGN);        /* Interrupt */
  8313.     sigint_ign = 1;            /* Remember we did this ourselves */
  8314. #ifdef SIGQUIT
  8315.     signal(SIGQUIT,SIG_IGN);        /* Quit */
  8316. #endif /* SIGQUIT */
  8317. #ifdef SIGTERM
  8318.     signal(SIGTERM,SIG_IGN);        /* Term */
  8319. #endif /* SIGTERM */
  8320. }
  8321.  
  8322. /*  I N I T R A W Q  --  Set up to read /dev/kmem for character count.  */
  8323.  
  8324. #ifdef  V7
  8325. /*
  8326.  Used in Version 7 to simulate Berkeley's FIONREAD ioctl call.  This
  8327.  eliminates blocking on a read, because we can read /dev/kmem to get the
  8328.  number of characters available for raw input.  If your system can't
  8329.  or you won't let the world read /dev/kmem then you must figure out a
  8330.  different way to do the counting of characters available, or else replace
  8331.  this by a dummy function that always returns 0.
  8332. */
  8333. /*
  8334.  * Call this routine as: initrawq(tty)
  8335.  * where tty is the file descriptor of a terminal.  It will return
  8336.  * (as a char *) the kernel-mode memory address of the rawq character
  8337.  * count, which may then be read.  It has the side-effect of flushing
  8338.  * input on the terminal.
  8339.  */
  8340. /*
  8341.  * John Mackin, Physiology Dept., University of Sydney (Australia)
  8342.  * ...!decvax!mulga!physiol.su.oz!john
  8343.  *
  8344.  * Permission is hereby granted to do anything with this code, as
  8345.  * long as this comment is retained unmodified and no commercial
  8346.  * advantage is gained.
  8347.  */
  8348. #ifndef MINIX
  8349. #ifndef MINIX2
  8350. #ifndef COHERENT
  8351. #include <a.out.h>
  8352. #include <sys/proc.h>
  8353. #endif /* COHERENT */
  8354. #endif /* MINIX2 */
  8355. #endif /* MINIX */
  8356.  
  8357. #ifdef COHERENT
  8358. #include <l.out.h>
  8359. #include <sys/proc.h>
  8360. #endif /* COHERENT */
  8361.  
  8362. char *
  8363. initrawq(tty) int tty; {
  8364. #ifdef MINIX
  8365.     return(0);
  8366. #else
  8367. #ifdef MINIX2
  8368.     return(0);
  8369. #else
  8370. #ifdef UTS24
  8371.     return(0);
  8372. #else
  8373. #ifdef BSD29
  8374.     return(0);
  8375. #else
  8376.     long lseek();
  8377.     static struct nlist nl[] = {
  8378.         {PROCNAME},
  8379.         {NPROCNAME},
  8380.         {""}
  8381.     };
  8382.     static struct proc *pp;
  8383.     char *qaddr, *p, c;
  8384.     int m;
  8385.     PID_T pid, me;
  8386.     NPTYPE xproc;                       /* Its type is defined in makefile. */
  8387.     int catch();
  8388.  
  8389.     me = getpid();
  8390.     if ((m = open("/dev/kmem", 0)) < 0) err("kmem");
  8391.     nlist(BOOTNAME, nl);
  8392.     if (nl[0].n_type == 0) err("proc array");
  8393.  
  8394.     if (nl[1].n_type == 0) err("nproc");
  8395.  
  8396.     lseek(m, (long)(nl[1].n_value), 0);
  8397.     read (m, &xproc, sizeof(xproc));
  8398.     saval = signal(SIGALRM, catch);
  8399.     if ((pid = fork()) == 0) {
  8400.         while(1)
  8401.             read(tty, &c, 1);
  8402.     }
  8403.     alarm(2);
  8404.  
  8405.     if(setjmp(jjbuf) == 0) {
  8406.         while(1)
  8407.       read(tty, &c, 1);
  8408.     }
  8409.     signal(SIGALRM, SIG_DFL);
  8410.  
  8411. #ifdef DIRECT
  8412.     pp = (struct proc *) nl[0].n_value;
  8413. #else
  8414.     if (lseek(m, (long)(nl[0].n_value), 0) < 0L) err("seek");
  8415.     if (read(m, &pp, sizeof(pp)) != sizeof(pp))  err("no read of proc ptr");
  8416. #endif
  8417.     lseek(m, (long)(nl[1].n_value), 0);
  8418.     read(m, &xproc, sizeof(xproc));
  8419.  
  8420.     if (lseek(m, (long)pp, 0) < 0L) err("Can't seek to proc");
  8421.     if ((p = malloc(xproc * sizeof(struct proc))) == NULL) err("malloc");
  8422.     if (read(m,p,xproc * sizeof(struct proc)) != xproc*sizeof(struct proc))
  8423.         err("read proc table");
  8424.     for (pp = (struct proc *)p; xproc > 0; --xproc, ++pp) {
  8425.         if (pp -> p_pid == (short) pid) goto iout;
  8426.     }
  8427.     err("no such proc");
  8428.  
  8429. iout:
  8430.     close(m);
  8431.     qaddr = (char *)(pp -> p_wchan);
  8432.     free (p);
  8433.     kill(pid, SIGKILL);
  8434.     wait((WAIT_T *)0);
  8435.     return (qaddr);
  8436. #endif
  8437. #endif
  8438. #endif
  8439. #endif
  8440. }
  8441.  
  8442. /*  More V7-support functions...  */
  8443.  
  8444. static VOID
  8445. err(s) char *s; {
  8446.     char buf[200];
  8447.  
  8448.     sprintf(buf, "fatal error in initrawq: %s", s);
  8449.     perror(buf);
  8450.     doexit(1,-1);
  8451. }
  8452.  
  8453. static VOID
  8454. catch(foo) int foo; {
  8455.     longjmp(jjbuf, -1);
  8456. }
  8457.  
  8458.  
  8459. /*  G E N B R K  --  Simulate a modem break.  */
  8460.  
  8461. #ifdef MINIX
  8462. #define BSPEED B110
  8463. #else
  8464. #ifdef MINIX2
  8465. #define BSPEED B110
  8466. #else
  8467. #define BSPEED B150
  8468. #endif /* MINIX2 */
  8469. #endif /* MINIX */
  8470.  
  8471. #ifndef MINIX2
  8472. VOID
  8473. genbrk(fn,msec) int fn, msec; {
  8474.     struct sgttyb ttbuf;
  8475.     int ret, sospeed, x, y;
  8476.  
  8477.     ret = ioctl(fn, TIOCGETP, &ttbuf);
  8478.     sospeed = ttbuf.sg_ospeed;
  8479.     ttbuf.sg_ospeed = BSPEED;
  8480.     ret = ioctl(fn, TIOCSETP, &ttbuf);
  8481.     y = (int)strlen(brnuls);
  8482.     x = ( BSPEED * 100 ) / msec;
  8483.     if (x > y) x = y;
  8484.     ret = write(fn, brnuls, (( BSPEED * 100 ) / msec ));
  8485.     ttbuf.sg_ospeed = sospeed;
  8486.     ret = ioctl(fn, TIOCSETP, &ttbuf);
  8487.     ret = write(fn, "@", 1);
  8488.     return;
  8489. }
  8490. #endif /* MINIX2 */
  8491.  
  8492. #ifdef MINIX2
  8493. int
  8494. genbrk(fn,msec) int fn, msec; {
  8495.     struct termios ttbuf;
  8496.     int ret, x, y;
  8497.     speed_t sospeed;
  8498.  
  8499.     ret = tcgetattr(fn, &ttbuf);
  8500.     sospeed = ttbuf.c_ospeed;
  8501.     ttbuf.c_ospeed = BSPEED;
  8502.     ret = tcsetattr(fn,TCSADRAIN, &ttbuf);
  8503.     y = (int)strlen(brnuls);
  8504.     x = ( BSPEED * 100 ) / msec;
  8505.     if (x > y) x = y;
  8506.     ret = write(fn, brnuls, (( BSPEED * 100 ) / msec ));
  8507.     ttbuf.c_ospeed = sospeed;
  8508.     ret = tcsetattr(fn, TCSADRAIN, &ttbuf);
  8509.     ret = write(fn, "@", 1);
  8510.     return ret;
  8511. }
  8512. #endif /* MINIX2 */
  8513. #endif /* V7 */
  8514.  
  8515. /*
  8516.   I N C H K  --  Check if chars waiting to be read on given file descriptor.
  8517.  
  8518.   This routine is a merger of ttchk() and conchk().
  8519.   Call with:
  8520.     channel == 0 to check console.
  8521.     channel == 1 to check communications connection.
  8522.   and:
  8523.     fd = file descriptor.
  8524.   Returns:
  8525.    >= 0: number of characters waiting, 0 or greater,
  8526.      -1: on any kind of error,
  8527.      -2: if there is (definitely) no connection.
  8528.   Note: In UNIX we don't have to call nettchk() because a socket
  8529.   file descriptor works just like in serial i/o, ioctls and all.
  8530.   (But this will change if we add non-file-descriptor channels,
  8531.   such as IBM X.25 for AIX...)
  8532. */
  8533. static int
  8534. in_chk(channel, fd) int channel, fd; {
  8535.     int x, n = 0;            /* Workers, n = return value */
  8536.     extern int clsondisc;        /* Close on disconnect */
  8537. /*
  8538.   The first section checks to make sure we have a connection,
  8539.   but only if we're in local mode.
  8540. */
  8541. #ifdef DEBUG
  8542.     if (deblog) {
  8543.     char buf[16];
  8544.     sprintf(buf,"%d",fd);        /* File descriptor */
  8545.     debug(F111,"in_chk entry",buf,channel);
  8546.     debug(F101,"in_chk ttyfd","",ttyfd);
  8547.     debug(F101,"in_chk ttpty","",ttpty);
  8548.     }
  8549. #endif /* DEBUG */
  8550. /*
  8551.   But don't say connection is gone if we have any buffered-stuff.
  8552. */
  8553. #ifdef TTLEBUF
  8554.     debug(F101,"in_chk ttpush","",ttpush);
  8555.     if (channel == 1) {
  8556.     if (ttpush >= 0)
  8557.       n++;
  8558.     n += le_inbuf();
  8559.     if (n > 0)
  8560.       return(n);
  8561.     }
  8562. #endif /* TTLEBUF */
  8563.  
  8564. #ifdef NETPTY
  8565. #ifdef HAVE_PTYTRAP
  8566.     /* Special handling for HP-UX pty i/o */
  8567.     if (ttpty && pty_trap_pending(ttyfd) > 0) {
  8568.         if (pty_trap_handler(ttyfd) > 0) {
  8569.             ttclos(0);
  8570.             return(-2);
  8571.         }
  8572.     }
  8573. #endif /* HAVE_PTYTRAP */
  8574. #endif /* NETPTY */
  8575.  
  8576.     if (channel) {            /* Checking communications channel */
  8577.     if (ttyfd < 0) {        /* No connection */
  8578.       return(-2);            /* That's what this means */
  8579.     } else if (xlocal &&        /* In local mode */
  8580.            !netconn &&        /* Serial connection */
  8581.            ttcarr != CAR_OFF    /* with CARRIER WATCH ON (or AUTO) */
  8582. #ifdef COMMENT
  8583. #ifdef MYREAD
  8584. /*
  8585.   Seems like this would be a good idea but it prevents C-Kermit from
  8586.   popping back to the prompt automatically when carrier drops.  However,
  8587.   commenting this out prevents us from seeing the NO CARRIER message.
  8588.   Needs more work...
  8589. */
  8590.            && my_count < 1    /* Nothing in our internal buffer */
  8591. #endif /* MYREAD */
  8592. #endif /* COMMENT */
  8593.            ) {
  8594.         int x;
  8595.         x = ttgmdm();        /* So get modem signals */
  8596.         if (x > -1) {        /* Check for carrier */
  8597.         if (!(x & BM_DCD)) {    /* No carrier */
  8598.             debug(F101,"in_chk carrier lost","",x);
  8599.             if (clsondisc) {    /* If "close-on-disconnect" */
  8600.             debug(F100,"in_chk close-on-disconnect","",0);
  8601.             ttclos(0);    /* close device & release lock. */
  8602.             }
  8603.             return(-2);        /* This means "disconnected" */
  8604.         }
  8605.         }
  8606.     }
  8607.     }
  8608.  
  8609. /* We seem to have a connection so now see if any bytes are waiting on it */
  8610.  
  8611. #ifdef CK_SSL
  8612.     if (ssl_active_flag) {
  8613.         n += SSL_pending(ssl_con);
  8614.         debug(F101,"in_chk SSL_pending","",n);
  8615.         if (n < 0)            /* Is this right? */
  8616.       return(-1);
  8617.         else
  8618.       return(n);
  8619.     } else if (tls_active_flag) {
  8620.         n += SSL_pending(tls_con);
  8621.         debug(F101,"in_chk TLS_pending","",n);
  8622.         if (n < 0)            /* Is this right? */
  8623.       return(-1);
  8624.         else
  8625.       return(n);
  8626.     }
  8627. #endif /* CK_SSL */
  8628. #ifdef RLOGCODE
  8629. #ifdef CK_KERBEROS
  8630.     /* It is not safe to read any data when using encrypted Klogin */
  8631.     if (ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN) {
  8632. #ifdef KRB4
  8633.         if (ttnproto == NP_EK4LOGIN) {
  8634.             n += krb4_des_avail(ttyfd);
  8635.             debug(F101,"in_chk krb4_des_avail","",n);
  8636.         }
  8637. #endif /* KRB4 */
  8638. #ifdef KRB5
  8639.         if (ttnproto == NP_EK5LOGIN) {
  8640.             n += krb5_des_avail(ttyfd);
  8641.             debug(F101,"in_chk krb5_des_avail","",n);
  8642.         }
  8643. #endif /* KRB5 */
  8644.         if (n < 0)            /* Is this right? */
  8645.       return(-1);
  8646.         else
  8647.       return(n);
  8648.     }
  8649. #endif /* CK_KERBEROS */
  8650. #endif /* RLOGCODE */
  8651.  
  8652.     errno = 0;                /* Reset this so we log good info */
  8653. #ifdef FIONREAD
  8654.     x = ioctl(fd, FIONREAD, &n);    /* BSD and lots of others */
  8655. #ifdef DEBUG                /* (the more the better) */
  8656.     if (deblog) {
  8657.     debug(F101,"in_chk FIONREAD return code","",x);
  8658.     debug(F101,"in_chk FIONREAD count","",n);
  8659.     debug(F101,"in_chk FIONREAD errno","",errno);
  8660.     }
  8661. #endif /* DEBUG */
  8662. #else /* FIONREAD not defined */
  8663. /*
  8664.   Here, if (netconn && ttnet == NET_TCPB), we might try calling recvmsg()
  8665.   with flags MSG_PEEK|MSG_DONTWAIT on the socket (ttyfd), except this is not
  8666.   portable (MSG_DONTWAIT isn't defined in any of the <sys/socket.h> files
  8667.   that I looked at, but it is needed to prevent the call from blocking), and
  8668.   the msghdr struct differs from place to place, so we would need another
  8669.   avalanche of ifdefs.  Still, when FIONREAD is not available, this is the
  8670.   only other known method of asking the OS for the *number* of characters
  8671.   available for reading.
  8672. */
  8673. #ifdef V7                /* UNIX V7: look in kernel memory */
  8674. #ifdef MINIX
  8675.     n = 0;                /* But not in MINIX */
  8676. #else
  8677. #ifdef MINIX2
  8678.     n = 0;
  8679. #else
  8680.     lseek(kmem[TTY], (long) qaddr[TTY], 0); /* 7th Edition Unix */
  8681.     x = read(kmem[TTY], &n, sizeof(int));
  8682.     if (x != sizeof(int))
  8683.       n = 0;
  8684. #endif /* MINIX2 */
  8685. #endif /* MINIX */
  8686. #else /* Not V7 */
  8687. #ifdef PROVX1
  8688.     x = ioctl(fd, TIOCQCNT, &ttbuf);    /* DEC Pro/3xx Venix V.1 */
  8689.     n = ttbuf.sg_ispeed & 0377;        /* Circa 1984 */
  8690.     if (x < 0) n = 0;
  8691. #else
  8692. #ifdef MYREAD
  8693. /*
  8694.   Here we skip all the undependable and expensive calls below if we
  8695.   already have something in our internal buffer.  This tends to work quite
  8696.   nicely, so the only really bad case remaining is the one in which neither
  8697.   FIONREAD or MYREAD are defined, which is increasingly rare these days.
  8698. */
  8699.     if (channel != 0 && my_count > 0) {
  8700.     debug(F101,"in_chk buf my_count","",my_count);
  8701.     n = my_count;            /* n was 0 before we got here */
  8702.     return(n);
  8703.     }
  8704. #endif /* MYREAD */
  8705. /*
  8706.   rdchk(), select(), and poll() tell us *if* data is available to be read, but
  8707.   not how much, so these should be used only as a final resort.  Especially
  8708.   since these calls tend to add a lot overhead.
  8709. */
  8710. #ifdef RDCHK                /* This mostly SCO-specific */
  8711.     n = rdchk(fd);
  8712.     debug(F101,"in_chk rdchk","",n);
  8713. #else /* No RDCHK */
  8714. #ifdef SELECT
  8715. #ifdef Plan9
  8716.     /* Only allows select on the console ... don't ask */
  8717.     if (channel == 0)
  8718. #endif /* Plan9 */
  8719.       {
  8720.     fd_set rfds;            /* Read file descriptors */
  8721. #ifdef BELLV10
  8722.     FD_ZERO(rfds);            /* Initialize them */
  8723.     FD_SET(fd,rfds);        /* We want to look at this fd */
  8724. #else
  8725.     FD_ZERO(&rfds);            /* Initialize them */
  8726.     FD_SET(fd,&rfds);        /* We want to look at this fd */
  8727.     tv.tv_sec = tv.tv_usec = 0L;    /* A 0-valued timeval structure */
  8728. #endif /* BELLV10 */
  8729. #ifdef Plan9
  8730.     n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
  8731.     debug(F101,"in_chk Plan 9 select","",n);
  8732. #else
  8733. #ifdef BELLV10
  8734.     n = select( 128, rfds, (fd_set *)0, (fd_set *)0, 0 );
  8735.     debug(F101,"in_chk BELLV10 select","",n);
  8736. #else
  8737. #ifdef BSD44
  8738.     n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
  8739.     debug(F101,"in_chk BSD44 select","",n);
  8740. #else
  8741. #ifdef BSD43
  8742.     n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
  8743.     debug(F101,"in_chk BSD43 select","",n);
  8744. #else
  8745. #ifdef SOLARIS
  8746.     n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
  8747.     debug(F101,"in_chk SOLARIS select","",n);
  8748. #else
  8749. #ifdef QNX
  8750.     n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
  8751.     debug(F101,"in_chk QNX select","",n);
  8752. #else
  8753. #ifdef COHERENT
  8754.     n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
  8755.     debug(F101,"in_chk COHERENT select","",n);
  8756. #else
  8757. #ifdef SVR4
  8758.     n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
  8759.     debug(F101,"in_chk SVR4 select","",n);
  8760. #else
  8761. #ifdef __linux__
  8762.     n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
  8763.     debug(F101,"in_chk LINUX select","",n);
  8764. #else
  8765.     n = select( FD_SETSIZE, &rfds, (int *)0, (int *)0, &tv );
  8766.     debug(F101,"in_chk catchall select","",n);
  8767. #endif /* __linux__ */
  8768. #endif /* SVR4 */
  8769. #endif /* COHERENT */
  8770. #endif /* QNX */
  8771. #endif /* SOLARIS */
  8772. #endif /* BSD43 */
  8773. #endif /* BSD44 */
  8774. #endif /* BELLV10 */
  8775. #endif /* Plan9 */
  8776.     }
  8777. #else  /* Not SELECT */
  8778. #ifdef CK_POLL
  8779.     {
  8780.       struct pollfd pfd;
  8781.  
  8782.       pfd.fd = fd;
  8783.       pfd.events = POLLIN;
  8784.       pfd.revents = 0;
  8785.       n = poll(&pfd, 1, 0);
  8786.       debug(F101,"in_chk poll","",n);
  8787.       if ((n > 0) && (pfd.revents & POLLIN))
  8788.     n = 1;
  8789.     }
  8790. #endif /* CK_POLL */
  8791. #endif /* SELECT */
  8792. #endif /* RDCHK */
  8793. #endif /* PROVX1 */
  8794. #endif /* V7 */
  8795. #endif /* FIONREAD */
  8796.  
  8797. /* From here down, treat console and communication device differently... */
  8798.  
  8799.     if (channel == 0) {            /* Console */
  8800.  
  8801. #ifdef SVORPOSIX
  8802. #ifndef FIONREAD
  8803. #ifndef SELECT
  8804. #ifndef CK_POLL
  8805. #ifndef RDCHK
  8806. /*
  8807.   This is the hideous hack used in System V and POSIX systems that don't
  8808.   support FIONREAD, rdchk(), select(), poll(), etc, in which the user's
  8809.   CONNECT-mode escape character is attached to SIGQUIT.  Used, obviously,
  8810.   only on the console.
  8811. */
  8812.     if (conesc) {            /* Escape character typed == SIGQUIT */
  8813.         debug(F100,"in_chk conesc","",conesc);
  8814.         conesc = 0;
  8815.         signal(SIGQUIT,esctrp);    /* Restore signal */
  8816.         n += 1;
  8817.     }
  8818. #endif /* RDCHK */
  8819. #endif /* CK_POLL */
  8820. #endif /* SELECT */
  8821. #endif /* FIONREAD */
  8822. #endif /* SVORPOSIX */
  8823.  
  8824.     return(n);            /* Done with console */
  8825.     }
  8826.  
  8827.     if (channel != 0) {            /* Communications connection */
  8828.  
  8829. #ifdef MYREAD
  8830. #ifndef FIONREAD
  8831. /*
  8832.   select() or rdchk(), etc, has told us that something is waiting, but we
  8833.   don't know how much.  So we do a read to get it and then we know.  Note:
  8834.   This read is NOT nonblocking if nothing is there (because of VMIN=1), but
  8835.   it should be safe in this case since the OS tells us at least one byte is
  8836.   waiting to be read, and MYREAD reads return as much as is there without
  8837.   waiting for any more.  Controlled tests on Solaris and Unixware (with
  8838.   FIONREAD deliberately undefined) show this to be true.
  8839. */
  8840.     debug(F101,"in_chk read my_count","",my_count);
  8841.     debug(F101,"in_chk read n","",n);
  8842.     if (n > 0 && my_count == 0) {
  8843.         /* This also catches disconnects etc */
  8844.         /* Do what mygetbuf does except don't grab a character */
  8845.         my_count = myfillbuf();
  8846.         my_item = -1;        /* ^^^ */
  8847.         debug(F101,"in_chk myfillbuf my_count","",my_count);
  8848.         if (my_count < 0)
  8849.           return(-1);
  8850.         else
  8851.           n = 0;            /* NB: n is replaced by my_count */
  8852.     }
  8853. #endif /* FIONREAD */
  8854. /*
  8855.   Here we add whatever we think is unread to what is still in our
  8856.   our internal buffer.  Thus the importance of setting n to 0 just above.
  8857. */
  8858.     debug(F101,"in_chk my_count","",my_count);
  8859.     debug(F101,"in_chk n","",n);
  8860.     if (my_count > 0)
  8861.       n += my_count;
  8862. #endif /* MYREAD */
  8863.     }
  8864.     debug(F101,"in_chk result","",n);
  8865.  
  8866.     /* Errors here don't prove the connection has dropped so just say 0 */
  8867.  
  8868.     return(n < 0 ? 0 : n);
  8869. }
  8870.  
  8871.  
  8872. /*  T T C H K  --  Tell how many characters are waiting in tty input buffer  */
  8873.  
  8874. int
  8875. ttchk() {
  8876.     int fd;
  8877. #ifdef NETCMD
  8878.     if (ttpipe)
  8879.       fd = fdin;
  8880.     else
  8881. #endif /* NETCMD */
  8882.       fd = ttyfd;
  8883.     return(in_chk(1,fd));
  8884. }
  8885.  
  8886. /*  T T X I N  --  Get n characters from tty input buffer  */
  8887.  
  8888. /*  Returns number of characters actually gotten, or -1 on failure  */
  8889.  
  8890. /*  Intended for use only when it is known that n characters are actually */
  8891. /*  Available in the input buffer.  */
  8892.  
  8893. int
  8894. ttxin(n,buf) int n; CHAR *buf; {
  8895.     register int x = 0, i = 0, c = -2;
  8896.     char cc;
  8897.     int fd;
  8898.  
  8899.     if (n < 1)                /* Nothing to do */
  8900.       return(0);
  8901.  
  8902. #ifdef TTLEBUF
  8903.     if (ttpush >= 0) {
  8904.         buf[0] = ttpush;        /* Put pushed char in buffer*/
  8905.         ttpush = -1;            /* Clear the push buffer */
  8906.         if (ttchk() > 0)
  8907.       return(ttxin(n-1, &buf[1]) + 1);
  8908.         else
  8909.       return(1);
  8910.     }
  8911.     if (le_data) {
  8912.         while (le_inbuf() > 0) {
  8913.         if (le_getchar(&buf[i])) {
  8914.                 i++;
  8915.                 n--;
  8916.             }
  8917.         }
  8918.         if (ttchk() > 0)
  8919.       return(ttxin(n,&buf[i])+i);
  8920.         else
  8921.       return(i);
  8922.     }
  8923. #endif /* TTLEBUF */
  8924.  
  8925. #ifdef NETCMD
  8926.     if (ttpipe)
  8927.       fd = fdin;
  8928.     else
  8929. #endif /* NETCMD */
  8930.       fd = ttyfd;
  8931.  
  8932. #ifdef SUNX25
  8933.     if (netconn && (ttnet == NET_SX25))    /* X.25 connection */
  8934.       return(x25xin(n,buf));
  8935. #endif /* SUNX25 */
  8936.  
  8937. #ifdef IBMX25
  8938.     /* riehm: possibly not needed. Test worked with normal reads and writes */
  8939.     if (netconn && (ttnet == NET_IX25))    { /* X.25 connection */
  8940.     x = x25xin(n,buf);
  8941.     if (x > 0) buf[x] = '\0';
  8942.     return(x);
  8943.     }
  8944. #endif /* IBMX25 */
  8945.  
  8946. #ifdef MYREAD
  8947.     debug(F101,"ttxin MYREAD","",n);
  8948.     while (x < n) {
  8949.     c = myread();
  8950.     if (c < 0) {
  8951.         debug(F101,"ttxin myread returns","",c);
  8952.         if (c == -3) x = -1;
  8953.         break;
  8954.         }
  8955.     buf[x++] = c & ttpmsk;
  8956. #ifdef RLOGCODE
  8957. #ifdef CK_KERBEROS
  8958.         /* It is impossible to know how many characters are waiting */
  8959.         /* to be read when you are using Encrypted Rlogin or SSL    */
  8960.         /* as the transport since the number of real data bytes     */
  8961.         /* can be greater or less than the number of bytes on the   */
  8962.         /* wire which is what ttchk() returns.                      */
  8963.         if (netconn && (ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN))
  8964.       if (ttchk() <= 0)
  8965.         break;
  8966. #endif /* CK_KERBEROS */
  8967. #endif /* RLOGCODE */
  8968. #ifdef CK_SSL
  8969.         if (ssl_active_flag || tls_active_flag)
  8970.       if (ttchk() <= 0)
  8971.         break;
  8972. #endif /* CK_SSL */
  8973.     }
  8974. #else
  8975.     debug(F101,"ttxin READ","",n);
  8976.     x = read(fd,buf,n);
  8977.     for (c = 0; c < n; c++)        /* Strip any parity */
  8978.       buf[c] &= ttpmsk;
  8979. #endif /* MYREAD */
  8980.  
  8981.     debug(F101,"ttxin x","",x);        /* Done */
  8982.     if (x > 0) buf[x] = '\0';
  8983.     if (x < 0) x = -1;
  8984.     return(x);
  8985. }
  8986.  
  8987. /*  T T O L  --  Write string s, length n, to communication device.  */
  8988. /*
  8989.   Returns:
  8990.    >= 0 on success, number of characters actually written.
  8991.    -1 on failure.
  8992. */
  8993. #ifdef CK_ENCRYPTION
  8994. CHAR * xpacket = NULL;
  8995. int nxpacket = 0;
  8996. #endif /* CK_ENCRYPTION */
  8997.  
  8998. #define TTOLMAXT 5
  8999. int
  9000. ttol(s,n) int n; CHAR *s; {
  9001.     int x, len, tries, fd;
  9002. #ifdef CKXXCHAR
  9003.     extern int dblflag;            /* For SET SEND DOUBLE-CHARACTER */
  9004.     extern short dblt[];
  9005.     CHAR *p = NULL, *p2, *s2, c;
  9006.     int n2 = 0;
  9007. #endif /* CKXXCHAR */
  9008.  
  9009.     if (ttyfd < 0)            /* Not open? */
  9010.       return(-3);
  9011. #ifdef DEBUG
  9012.     if (deblog) hexdump("ttol s",s,n);
  9013. #endif /* DEBUG */
  9014.  
  9015. #ifdef NETCMD
  9016.     if (ttpipe)
  9017.       fd = fdout;
  9018.     else
  9019. #endif /* NETCMD */
  9020.       fd = ttyfd;
  9021.  
  9022. #ifdef CKXXCHAR
  9023. /*  Double any characters that must be doubled.  */
  9024.     debug(F101,"ttol dblflag","",dblflag);
  9025.     if (dblflag) {
  9026.     p = (CHAR *) malloc(n + n + 1);
  9027.     if (p) {
  9028.         s2 = s;
  9029.         p2 = p;
  9030.         n2 = 0;
  9031.         while (*s2) {
  9032.         c = *s2++;
  9033.         *p2++ = c;
  9034.         n2++;
  9035.         if (dblt[(unsigned) c] & 2) {
  9036.             *p2++ = c;
  9037.             n2++;
  9038.         }
  9039.         }
  9040.         s = p;
  9041.         n = n2;
  9042.         s[n] = '\0';
  9043.     }
  9044.     }
  9045.     debug(F111,"ttol doubled",s,n);
  9046. #endif /* CKXXCHAR */
  9047.  
  9048.     tries = TTOLMAXT;            /* Allow up to this many tries */
  9049.     len = n;                /* Remember original length */
  9050.  
  9051. #ifdef CK_ENCRYPTION
  9052. /*
  9053.   This is to avoid encrypting a packet that is already encrypted, e.g.
  9054.   when we resend a packet directly out of the packet buffer, and also to
  9055.   avoid encrypting a constant (literal) string, which can cause a memory
  9056.   fault.
  9057. */
  9058.     if (TELOPT_ME(TELOPT_ENCRYPTION)) {
  9059.     int x;
  9060.     if (nxpacket < n) {
  9061.         if (xpacket) {
  9062.         free(xpacket);
  9063.         xpacket = NULL;
  9064.         nxpacket = 0;
  9065.         }
  9066.         x = n > 10240 ? n : 10240;
  9067.         xpacket = (CHAR *)malloc(x);
  9068.         if (!xpacket) {
  9069.         fprintf(stderr,"ttol malloc failure\n");
  9070.         return(-1);
  9071.         } else
  9072.           nxpacket = x;
  9073.     }
  9074.     memcpy((char *)xpacket,(char *)s,n);
  9075.     s = xpacket;
  9076.     ck_tn_encrypt((char *)s,n);
  9077.     }
  9078. #endif /* CK_ENCRYPTION */
  9079.  
  9080.     while (n > 0 &&
  9081.        (tries-- > 0
  9082. #ifdef CK_ENCRYPTION
  9083.         /* keep trying if we are encrypting */
  9084.         || TELOPT_ME(TELOPT_ENCRYPTION)
  9085. #endif /* CK_ENCRYPTION */
  9086.             )) {            /* Be persistent */
  9087.     debug(F101,"ttol try","",TTOLMAXT - tries);
  9088. #ifdef BEOSORBEBOX
  9089.         if (netconn && !ttpipe && !ttpty)
  9090.       x = nettol(s,n);        /* Write string to device */
  9091.         else
  9092. #endif /* BEOSORBEBOX */
  9093. #ifdef IBMX25
  9094.       if (ttnet == NET_IX25)
  9095.         /*
  9096.          * this is a more controlled way of writing to X25
  9097.          * STREAMS, however write should also work!
  9098.          */
  9099.         x = x25write(ttyfd, s, n);
  9100.       else
  9101. #endif /* IBMX25 */
  9102. #ifdef CK_SSL
  9103.         if (ssl_active_flag || tls_active_flag) {
  9104.         int error;
  9105.         /* Write using SSL */
  9106.         if (ssl_active_flag)
  9107.                   x = SSL_write(ssl_con, s, n);
  9108.         else
  9109.                   x = SSL_write(tls_con, s, n);
  9110.         switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,x)) {
  9111.           case SSL_ERROR_NONE:
  9112.             break;
  9113.           case SSL_ERROR_WANT_WRITE:
  9114.           case SSL_ERROR_WANT_READ:
  9115.             x = 0;
  9116.             break;
  9117.           case SSL_ERROR_SYSCALL:
  9118.           case SSL_ERROR_WANT_X509_LOOKUP:
  9119.           case SSL_ERROR_SSL:
  9120.           case SSL_ERROR_ZERO_RETURN:
  9121.           default:
  9122.             ttclos(0);
  9123.             return(-3);
  9124.         }
  9125.         } else
  9126. #endif /* CK_SSL */
  9127. #ifdef RLOGCODE
  9128. #ifdef CK_KERBEROS
  9129. #ifdef KRB4
  9130.         if (ttnproto == NP_EK4LOGIN) {
  9131.         return(krb4_des_write(ttyfd,s,n));
  9132.         } else
  9133. #endif /* KRB4 */
  9134. #ifdef KRB5
  9135.             if (ttnproto == NP_EK5LOGIN) {
  9136.                 return(krb5_des_write(ttyfd,s,n));
  9137.             } else
  9138. #endif /* KRB5 */
  9139. #endif /* CK_KERBEROS */
  9140. #endif /* RLOGCODE */
  9141.           x = write(fd,s,n);    /* Write string to device */
  9142.  
  9143.     if (x == n) {            /* Worked? */
  9144.         debug(F101,"ttol ok","",x);    /* OK */
  9145. #ifdef CKXXCHAR
  9146.         if (p) free(p);
  9147. #endif /* CKXXCHAR */
  9148.         return(len);        /* Done */
  9149.     } else if (x < 0) {        /* No, got error? */
  9150.         debug(F101,"ttol write error","",errno);
  9151. #ifdef EWOULDBLOCK
  9152.         if (errno == EWOULDBLOCK) {
  9153.         msleep(10);
  9154.         continue;
  9155.         } else
  9156. #endif /* EWOULDBLOCK */
  9157. #ifdef TCPSOCKET
  9158.         if (netconn && ttnet == NET_TCPB) {
  9159.         debug(F101,"ttol TCP error","",errno);
  9160.         ttclos(0);        /* Close the connection. */
  9161.         x = -3;
  9162.         }
  9163. #endif /* TCPSOCKET */
  9164. #ifdef CKXXCHAR
  9165.         if (p) free(p);
  9166. #endif /* CKXXCHAR */
  9167.         return(x);
  9168.     } else {            /* No error, so partial success */
  9169.         debug(F101,"ttol partial","",x); /* This never happens */
  9170.         s += x;            /* Point to part not written yet */
  9171.         n -= x;            /* Adjust length */
  9172.         if (x > 0) msleep(10);    /* Wait 10 msec */
  9173.     }                /* Go back and try again */
  9174.     }
  9175. #ifdef CKXXCHAR
  9176.     if (p) free(p);
  9177. #endif /* CKXXCHAR */
  9178.     return(n < 1 ? len : -1);        /* Return the results */
  9179. }
  9180.  
  9181. /*  T T O C  --  Output a character to the communication line  */
  9182.  
  9183. /*
  9184.  This function should only be used for interactive, character-mode operations,
  9185.  like terminal connection, script execution, dialer i/o, where the overhead
  9186.  of the signals and alarms does not create a bottleneck.
  9187. */
  9188. int
  9189. #ifdef CK_ANSIC
  9190. ttoc(char c)
  9191. #else
  9192. ttoc(c) char c;
  9193. #endif /* CK_ANSIC */
  9194. /* ttoc */ {
  9195. #define TTOC_TMO 15            /* Timeout in case we get stuck */
  9196.     int xx, fd;
  9197.  
  9198.     if (ttyfd < 0)            /* Check for not open. */
  9199.       return(-1);
  9200.  
  9201. #ifdef NETCMD
  9202.     if (ttpipe)
  9203.       fd = fdout;
  9204.     else
  9205. #endif /* NETCMD */
  9206.       fd = ttyfd;
  9207.  
  9208.     c &= 0xff;
  9209.     /* debug(F101,"ttoc","",(CHAR) c); */
  9210.     saval = signal(SIGALRM,timerh);    /* Enable timer interrupt */
  9211.     xx = alarm(TTOC_TMO);        /* for this many seconds. */
  9212.     if (xx < 0) xx = 0;            /* Save old alarm value. */
  9213.     /* debug(F101,"ttoc alarm","",xx); */
  9214.     if (
  9215. #ifdef CK_POSIX_SIG
  9216.     sigsetjmp(sjbuf,1)
  9217. #else
  9218.     setjmp(sjbuf)
  9219. #endif /* CK_POSIX_SIG */
  9220.     ) {        /* Timer went off? */
  9221.     ttimoff();            /* Yes, cancel this alarm. */
  9222.     if (xx - TTOC_TMO > 0) alarm(xx - TTOC_TMO); /* Restore previous one */
  9223.         /* debug(F100,"ttoc timeout","",0); */
  9224. #ifdef NETCONN
  9225.     if (!netconn) {
  9226. #endif /* NETCONN */
  9227.         debug(F101,"ttoc timeout","",c);
  9228.         if (ttflow == FLO_XONX) {
  9229.         debug(F101,"ttoc flow","",ttflow); /* Maybe we're xoff'd */
  9230. #ifndef Plan9
  9231. #ifdef POSIX
  9232.         /* POSIX way to unstick. */
  9233.         debug(F100,"ttoc tcflow","",tcflow(ttyfd,TCOON));
  9234. #else
  9235. #ifdef BSD4                /* Berkeley way to do it. */
  9236. #ifdef TIOCSTART
  9237. /* .... Used to be "ioctl(ttyfd, TIOCSTART, 0);".  Who knows? */
  9238.         {
  9239.           int x = 0;
  9240.           debug(F101,"ttoc TIOCSTART","",ioctl(ttyfd, TIOCSTART, &x));
  9241.         }
  9242. #endif /* TIOCSTART */
  9243. #endif /* BSD4 */
  9244.                     /* Is there a Sys V way to do this? */
  9245. #endif /* POSIX */
  9246. #endif /* Plan9 */
  9247.         }
  9248. #ifdef NETCONN
  9249.         }
  9250. #endif /* NETCONN */
  9251.     return(-1);            /* Return failure code. */
  9252.     } else {
  9253.         int rc;
  9254. #ifdef BEOSORBEBOX
  9255. #ifdef NETCONN
  9256.         if (netconn && !ttpipe && !ttpty)
  9257.       rc = nettoc(c);
  9258.         else
  9259. #endif /*  BEOSORBEBOX */
  9260. #endif /* NETCONN */
  9261. #ifdef CK_ENCRYPTION
  9262.       if (TELOPT_ME(TELOPT_ENCRYPTION))
  9263.         ck_tn_encrypt(&c,1);
  9264. #endif /* CK_ENCRYPTION */
  9265. #ifdef IBMX25
  9266.     /* riehm: maybe this isn't necessary after all. Test program
  9267.      * worked fine with data being sent and retrieved with normal
  9268.      * read's and writes!
  9269.      */
  9270.     if (ttnet == NET_IX25)
  9271.       rc = x25write(ttyfd,&c,1); /* as above for X25 streams */
  9272.     else
  9273. #endif /* IBMX25 */
  9274. #ifdef CK_SSL
  9275.       if (ssl_active_flag || tls_active_flag) {
  9276.           int error;
  9277.           /* Write using SSL */
  9278.           if (ssl_active_flag)
  9279.                 rc = SSL_write(ssl_con, &c, 1);
  9280.           else
  9281.                 rc = SSL_write(tls_con, &c, 1);
  9282.           switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,rc)){
  9283.         case SSL_ERROR_NONE:
  9284.           break;
  9285.         case SSL_ERROR_WANT_WRITE:
  9286.         case SSL_ERROR_WANT_READ:
  9287.           rc = 0;
  9288.           break;
  9289.         case SSL_ERROR_SYSCALL:
  9290.         case SSL_ERROR_WANT_X509_LOOKUP:
  9291.         case SSL_ERROR_SSL:
  9292.         case SSL_ERROR_ZERO_RETURN:
  9293.         default:
  9294.           ttclos(0);
  9295.           return(-1);
  9296.           }
  9297.       } else
  9298. #endif /* CK_SSL */
  9299. #ifdef RLOGCODE
  9300. #ifdef CK_KERBEROS
  9301. #ifdef KRB4
  9302.       if (ttnproto == NP_EK4LOGIN) {
  9303.           rc = (krb4_des_write(ttyfd,&c,1) == 1);
  9304.       } else
  9305. #endif /* KRB4 */
  9306. #ifdef KRB5
  9307.           if (ttnproto == NP_EK5LOGIN) {
  9308.               rc = (krb5_des_write(ttyfd,&c,1) == 1);
  9309.           } else
  9310. #endif /* KRB5 */
  9311. #endif /* CK_KERBEROS */
  9312. #endif /* RLOGCODE */
  9313.         rc = write(fd,&c,1);    /* Try to write the character. */
  9314.     if (rc < 1) {            /* Failed */
  9315.         ttimoff();            /* Turn off the alarm. */
  9316.         alarm(xx);            /* Restore previous alarm. */
  9317.         debug(F101,"ttoc errno","",errno); /* Log the error, */
  9318.         return(-1);            /* and return the error code. */
  9319.     }
  9320.     }
  9321.     ttimoff();                /* Success, turn off the alarm. */
  9322.     alarm(xx);                /* Restore previous alarm. */
  9323.     return(0);                /* Return good code. */
  9324. }
  9325.  
  9326. /*  T T I N L  --  Read a record (up to break character) from comm line.  */
  9327. /*
  9328.   Reads up to "max" characters from the communication line, terminating on:
  9329.     (a) the packet length field if the "turn" argument is zero, or
  9330.     (b) on the packet-end character (eol) if the "turn" argument is nonzero
  9331.     (c) a certain number of Ctrl-C's in a row
  9332.  
  9333.   Returns:
  9334.     >= 0, the number of characters read upon success;
  9335.     -1 if "max" exceeded, timeout, or other correctable error;
  9336.     -2 on user interruption (c);
  9337.     -3 on fatal error like connection lost.
  9338.  
  9339.   The characters that were input are copied into "dest" with their parity bits
  9340.   stripped if parity was selected.  Returns the number of characters read.
  9341.   Characters after the eol are available upon the next call to this function.
  9342.  
  9343.   The idea is to minimize the number of system calls per packet, and also to
  9344.   minimize timeouts.  This function is the inner loop of the protocol and must
  9345.   be as efficient as possible.  The current strategy is to use myread().
  9346.  
  9347.   WARNING: This function calls parchk(), which is defined in another module.
  9348.   Normally, ckutio.c does not depend on code from any other module, but there
  9349.   is an exception in this case because all the other ck?tio.c modules also
  9350.   need to call parchk(), so it's better to have it defined in a common place.
  9351. */
  9352. #ifdef CTRLC
  9353. #undef CTRLC
  9354. #endif /* CTRLC */
  9355. #define CTRLC '\03'
  9356. /*
  9357.   We have four different declarations here because:
  9358.   (a) to allow Kermit to be built without the automatic parity sensing feature
  9359.   (b) one of each type for ANSI C, one for non-ANSI.
  9360. */
  9361.  
  9362. static int csave = -1;
  9363.  
  9364. #ifndef NOXFER
  9365. int
  9366. #ifdef PARSENSE
  9367. #ifdef CK_ANSIC
  9368. ttinl(CHAR *dest, int max,int timo, CHAR eol, CHAR start, int turn)
  9369. #else
  9370. ttinl(dest,max,timo,eol,start,turn) int max,timo,turn; CHAR *dest, eol, start;
  9371. #endif /* CK_ANSIC */
  9372. #else /* not PARSENSE */
  9373. #ifdef CK_ANSIC
  9374. ttinl(CHAR *dest, int max,int timo, CHAR eol)
  9375. #else
  9376. ttinl(dest,max,timo,eol) int max,timo; CHAR *dest, eol;
  9377. #endif /* __SDTC__ */
  9378. #endif /* PARSENSE */
  9379. /* ttinl */ {
  9380.  
  9381. #ifndef MYREAD
  9382.     CHAR ch, dum;
  9383. #endif /* MYREAD */
  9384. #ifdef PARSENSE
  9385.     int pktlen = -1;
  9386.     int lplen = 0;
  9387.     int havelen = 0;
  9388. #endif /* PARSENSE */
  9389.     int cc = 0;                /* Character count */
  9390.     int fd;
  9391.     int sopmask = 0xff;            /* Start-Of-Packet mask */
  9392. #ifdef CKXXCHAR
  9393.     extern short dblt[];        /* Ignore-character table */
  9394.     extern int ignflag;
  9395. #endif /* CKXXCHAR */
  9396. #ifdef TCPSOCKET
  9397.     extern CHAR stchr;
  9398. #endif /* TCPSOCKET */
  9399.     int x;
  9400.  
  9401.     if (ttyfd < 0) return(-3);          /* Not open. */
  9402.  
  9403.     debug(F101,"ttinl max","",max);
  9404.     debug(F101,"ttinl timo","",timo);
  9405.  
  9406. #ifdef NETCMD
  9407.     if (ttpipe)
  9408.       fd = fdin;
  9409.     else
  9410. #endif /* NETCMD */
  9411.       fd = ttyfd;
  9412.  
  9413. #ifdef COMMENT
  9414.     if (xlocal && conchk() > 0)        /* Allow for console interruptions */
  9415.       return(-1);
  9416. #endif /* COMMENT */
  9417.  
  9418.     *dest = '\0';                       /* Clear destination buffer */
  9419.     if (timo < 0) timo = 0;        /* Safety */
  9420.     if (timo) {                /* Don't time out if timo == 0 */
  9421.     int xx;
  9422.     saval = signal(SIGALRM,timerh);    /* Enable timer interrupt */
  9423.     xx = alarm(timo);        /* Set it. */
  9424.     debug(F101,"ttinl alarm","",xx);
  9425.     }
  9426.     if (
  9427. #ifdef CK_POSIX_SIG
  9428.     sigsetjmp(sjbuf,1)
  9429. #else
  9430.     setjmp(sjbuf)
  9431. #endif /* CK_POSIX_SIG */
  9432.     ) {                /* Timer went off? */
  9433.     debug(F100,"ttinl timout","",0); /* Get here on timeout. */
  9434.     /* debug(F110," with",(char *) dest,0); */
  9435.     ttimoff();            /* Turn off timer */
  9436.     return(-1);            /* and return error code. */
  9437.     } else {
  9438.     register int i, n;        /* local variables */
  9439.     int ccn = 0;
  9440. #ifdef PARSENSE
  9441.     register int flag = 0;
  9442.     debug(F000,"ttinl start","",start);
  9443. #endif /* PARSENSE */
  9444.  
  9445.     ttpmsk = ttprty ? 0177 : 0377;    /* Set parity stripping mask. */
  9446.     sopmask = needpchk ? 0177 : ttpmsk; /* And SOP matching mask. */
  9447.  
  9448. /* Now read into destination, stripping parity and looking for the */
  9449. /* the packet terminator, and also for several Ctrl-C's typed in a row. */
  9450.  
  9451.     i = 0;                /* Destination index */
  9452.     debug(F101,"ttinl eol","",eol);
  9453.  
  9454.     while (i < max-1) {
  9455. #ifdef MYREAD
  9456.         /* debug(F101,"ttinl i","",i); */
  9457.         errno = 0;
  9458.         if (csave > -1) {
  9459.             n = csave;
  9460.         debug(F101,"ttinl unsaving","",n);
  9461.         } else
  9462. #ifdef COMMENT
  9463.           if (xlocal && conchk() > 0) {
  9464.           /* Here we could catch keyboard interruptions. */
  9465.           /* But this would be VERY expensive. */
  9466.           /* We could also do it in myread() but it would be */
  9467.           /* expensive there too -- even if done with select()... */
  9468.           }
  9469. #endif /* COMMENT */
  9470.           if ((n = myread()) < 0) {    /* Timeout or i/o error? */
  9471. #ifdef DEBUG
  9472.         if (deblog) {
  9473.             debug(F101,"ttinl myread failure, n","",n);
  9474.             debug(F101,"ttinl myread errno","",errno);
  9475.         }
  9476. #endif /* DEBUG */
  9477.         /* Don't let EINTR break packets. */
  9478.         if (n == -3) {
  9479.             if (errno == EINTR && i > 0) {
  9480.             debug(F111,"ttinl EINTR myread i","continuing",i);
  9481.             continue;
  9482.             } else {
  9483.             debug(F110,"ttinl non-EINTR -3","closing",0);
  9484.             wasclosed = 1;
  9485.             ttimoff();    /* Turn off timer */
  9486.             ttclos(0);
  9487.             return(n);
  9488.             }
  9489.         } else if (n == -2 && netconn /* && timo == 0 */ ) {
  9490.             /* Here we try to catch broken network connections */
  9491.             /* even when ioctl() and read() do not catch them */
  9492.             debug(F111,"ttinl network myread failure","closing",n);
  9493.             wasclosed = 1;
  9494.             ttimoff();
  9495.             ttclos(0);
  9496.             return(-3);
  9497.         }
  9498.         break;            /* Break out of while loop */
  9499.         }
  9500.  
  9501. #else /* not MYREAD (is this code used anywhere any more?) */
  9502.  
  9503.         if (csave > -1)        /* Char saved from last time */
  9504.           ch = csave;
  9505.         else if ((n = read(fd, &ch, 1)) < 1)
  9506.           break;            /* Error - break out of while loop */
  9507.         n = ch;
  9508.  
  9509. #endif /* MYREAD */
  9510.  
  9511.         /* Get here with char in n */
  9512.  
  9513. #ifdef CK_ENCRYPTION
  9514.         /* If csave > -1 we already decrypted this character */
  9515.         /* So don't decrypt it again */
  9516.         if (TELOPT_U(TELOPT_ENCRYPTION) && csave == -1) {
  9517.         CHAR ch = n;
  9518.         ck_tn_decrypt(&ch,1);
  9519.         n = ch;
  9520.         }
  9521. #endif /* CK_ENCRYPTION */
  9522.  
  9523.         csave = -1;            /* Unflag that we unsaved a char */
  9524.  
  9525. #ifdef TCPSOCKET
  9526.         if (n == IAC &&        /* Handle Telnet options */
  9527.         ((xlocal && netconn && (ttnproto == NP_TELNET)) ||
  9528.         (!xlocal && sstelnet))) {
  9529.         n = tt_tnopt(n);
  9530.         if (n < 0)
  9531.           return(n);
  9532.         else if (n == 1)
  9533.           start = stchr;
  9534.         if (n != 255)        /* No data - go back for next char */
  9535.           continue;
  9536.         }                /* Quoted IAC - keep going */
  9537. #endif /* TCPSOCKET */
  9538. #ifdef CKXXCHAR
  9539.         if (ignflag)
  9540.           if (dblt[(unsigned) n] & 1) /* Character to ignore? */
  9541.         continue;
  9542. #endif /* CKXXCHAR */
  9543.  
  9544. /*
  9545.   Use parity mask, rather than always stripping parity, to check for
  9546.   cancellation.  Otherwise, runs like \x03\x83\x03 in a packet could cancel
  9547.   the transfer when parity is NONE.  (Note that \x03\x03\x03 is extremely
  9548.   unlikely due to run-length encoding.)
  9549. */
  9550.         /* Check cancellation */
  9551.         if (!xlocal && xfrcan && ((n & ttpmsk) == xfrchr)) {
  9552.         if (++ccn >= xfrnum) {    /* If xfrnum in a row, bail out. */
  9553.             if (timo) {        /* Clear timer. */
  9554.             ttimoff();
  9555.             }
  9556.             if (xfrchr < 32)
  9557.               printf("^%c...\r\n",(char)(xfrchr+64));
  9558.             else
  9559.               printf("Canceled...\r\n");
  9560.             return(-2);
  9561.         }
  9562.         } else ccn = 0;        /* No cancellation, reset counter, */
  9563.  
  9564. #ifdef PARSENSE
  9565.         if (flag == 0) {        /* Find the Start-Of-Packet. */
  9566.         if ((n & sopmask) == start) { /* Got it */
  9567.             flag = 1;
  9568.         } else {        /* Keep looking... */
  9569.             debug(F000,"ttinl skipping","",n);
  9570.             continue;
  9571.         }
  9572.         }
  9573.         dest[i++] = n & ttpmsk;
  9574. /*
  9575.   If we have not been instructed to wait for a turnaround character, we
  9576.   can go by the packet length field.  If turn != 0, we must wait for the
  9577.   end of line (eol) character before returning.  This is an egregious
  9578.   violation of all principles of layering...
  9579. */
  9580.         if (!havelen) {
  9581.         if (i == 2) {
  9582.             pktlen = xunchar(dest[1] & 0x7f);
  9583.             if (pktlen > 1) {
  9584.             havelen = 1;
  9585.             debug(F101,"ttinl length","",pktlen);
  9586.             }
  9587.         } else if (i == 5 && pktlen == 0) {
  9588.             lplen = xunchar(dest[4] & 0x7f);
  9589.         } else if (i == 6 && pktlen == 0) {
  9590.             pktlen = lplen * 95 + xunchar(dest[5] & 0x7f) + 5;
  9591.             havelen = 1;
  9592.             debug(F101,"ttinl extended length","",pktlen);
  9593.         }
  9594.         }
  9595.  
  9596. /*
  9597.   Suppose we looked at the sequence number here and found it was out of
  9598.   range?  This would mean either (a) incoming packets had SOP unprefixed
  9599.   and we are out of sync, or (b) the packet is damaged.  Since (a) is bad
  9600.   practice, let's ignore it.  So what should we do here if we know the
  9601.   packet is damaged?
  9602.  
  9603.    1. Nothing -- keep trying to read the packet till we find what we think
  9604.       is the end, or we time out, and let the upper layer decide what to
  9605.       do.  But since either the packet is corrupt or we are out of sync,
  9606.       our criterion for finding the end does not apply and we are likely
  9607.       to time out (or swallow a piece of the next packet) if our assumed
  9608.       length is too long.  (This was the behavior prior to version 7.0.)
  9609.  
  9610.    2. set flag = 0 and continue?  This would force us to wait for the
  9611.       next packet to come in, and therefore (in the nonwindowing case),
  9612.       would force a timeout in the other Kermit.
  9613.  
  9614.    3. set flag = 0 and continue, but only if the window size is > 1 and
  9615.       the window is not blocked?  Talk about cheating!
  9616.  
  9617.    4. Return a failure code and let the upper layer decide what to do.
  9618.       This should be equivalent to 3, but without the cheating.  So let's
  9619.       do it that way...
  9620. */
  9621.         if (i == 3) {        /* Peek at sequence number */
  9622.         x = xunchar(dest[i-1]);    /* If it's not in range... */
  9623.         if (x < 0 || x > 63) {
  9624.             debug(F111,"ttinl bad seq",dest,x);
  9625.             if (timo) ttimoff();
  9626.             return(-1);        /* return a nonfatal error */
  9627.         }
  9628.         }
  9629.  
  9630. #else /* PARSENSE */
  9631.         dest[i++] = n & ttpmsk;
  9632. #endif /* PARSENSE */
  9633.  
  9634.     /* Check for end of packet */
  9635.  
  9636.         if (
  9637. #ifdef PARSENSE
  9638. /*
  9639.   Purely length-driven if SET HANDSHAKE NONE (i.e. turn == 0).
  9640.   This allows packet terminators and handshake characters to appear
  9641.   literally inside a packet data field.
  9642. */
  9643.         (havelen && (i > pktlen+1) &&
  9644.          (!turn || (turn && (n & 0x7f) == turn))) /* (turn, not eol) */
  9645. #else /* !PARSENSE */
  9646. /*
  9647.   Built without PARSENSE, so just look for packet terminator.
  9648. */
  9649.         ((n & 0x7f) == eol)
  9650. #endif /* PARSENSE */
  9651.         ) {
  9652. #ifndef PARSENSE
  9653.         debug(F101,"ttinl got eol","",eol); /* (or turn) */
  9654.         dest[i] = '\0';        /* Yes, terminate the string, */
  9655.         /* debug(F101,"ttinl i","",i); */
  9656. #else
  9657. #ifdef DEBUG
  9658.         if (deblog) {
  9659.             if ((n & 0x7f) != eol) {
  9660.             debug(F101,"ttinl EOP length","",pktlen);
  9661.             debug(F101,"ttinl i","",i);
  9662. #ifdef MYREAD
  9663. #ifdef PARSENSE
  9664. /*
  9665.   We read a packet based on its length.  This leaves the EOP character still
  9666.   unread, and so ttchk() will always return at least 1 because of this.  But
  9667.   if we know it is there, we can safely get rid of it.  So...
  9668. */
  9669.             {
  9670.                 int x;
  9671.                 while (my_count > 0) {
  9672.                 x = ttinc(0);
  9673.                 /* Start of next packet */
  9674.                 if (x == start) { /* Save for next time */
  9675.                     csave = (unsigned)((unsigned)x & 0xff);
  9676.                     debug(F000,"ttinl csaved","",x);
  9677.                     break;
  9678.                 }
  9679.                 debug(F000,"ttinl removed","",x);
  9680.                 }
  9681.             }
  9682. #endif /* PARSENSE */
  9683. #endif /* MYREAD */
  9684.  
  9685.             } else debug(F101,"ttinl got eol","",eol); /* (or turn) */
  9686.         }
  9687. #endif /* DEBUG */
  9688.         dest[i] = '\0';        /* Terminate the string, */
  9689.             if (needpchk) {        /* Parity checked yet? */
  9690.             if (ttprty == 0) {    /* No, check. */
  9691.             if ((ttprty = parchk(dest,start,i)) > 0) {
  9692.                 int j;
  9693.                 debug(F101,"ttinl senses parity","",ttprty);
  9694.                 debug(F110,"ttinl packet before",dest,0);
  9695.                 ttpmsk = 0x7f;
  9696.                 for (j = 0; j < i; j++)
  9697.                   dest[j] &= 0x7f;    /* Strip parity from packet */
  9698.                 debug(F110,"ttinl packet after ",dest,0);
  9699.             } else ttprty = 0; /* Restore if parchk error */
  9700.             }
  9701.             sopmask = ttprty;
  9702.             needpchk = 0;
  9703.         }
  9704. #endif /* PARSENSE */
  9705.         if (timo) {        /* Turn off timer. */
  9706.             ttimoff();
  9707.         }
  9708.         debug(F011,"ttinl got", dest, (i < 60) ? i : -60);
  9709.         return(i);
  9710.         }
  9711.     } /* End of while() */
  9712.     ttimoff();
  9713.     return(n);
  9714.     }
  9715. }
  9716. #endif /* NOXFER */
  9717.  
  9718. /*  T T I N C --  Read a character from the communication line  */
  9719. /*
  9720.  On success, returns the character that was read, >= 0.
  9721.  On failure, returns -1 or other negative myread error code,
  9722.    or -2 if connection is broken or ttyfd < 0.
  9723.    or -3 if session limit has expired,
  9724.    or -4 if something or other...
  9725.  NOTE: The API does not provide for ttinc() returning a special code
  9726.  upon timeout, but we need it.  So for this we have a global variable,
  9727.  ttinctimo.
  9728. */
  9729. static int ttinctimo = 0;        /* Yuk */
  9730.  
  9731. int
  9732. ttinc(timo) int timo; {
  9733.  
  9734.     int n = 0, fd;
  9735.     int is_tn = 0;
  9736.     CHAR ch = 0;
  9737.  
  9738.     ttinctimo = 0;
  9739.  
  9740.     if (ttyfd < 0) return(-2);          /* Not open. */
  9741.  
  9742.     is_tn = (xlocal && netconn && ttnproto == NP_TELNET) ||
  9743.         (!xlocal && sstelnet);
  9744.  
  9745. #ifdef TTLEBUF
  9746.     if (ttpush >= 0) {
  9747.         debug(F111,"ttinc","ttpush",ttpush);
  9748.         ch = ttpush;
  9749.         ttpush = -1;
  9750.         return(ch);
  9751.     }
  9752.     if (le_data) {
  9753.         if (le_getchar(&ch) > 0) {
  9754.             debug(F111,"ttinc le_getchar","ch",ch);
  9755.             return(ch);
  9756.         }
  9757.     }
  9758. #endif /* TTLEBUF */
  9759.  
  9760. #ifdef NETCMD
  9761.     if (ttpipe)
  9762.       fd = fdin;
  9763.     else
  9764. #endif /* NETCMD */
  9765.       fd = ttyfd;
  9766.  
  9767.     if ((timo <= 0)            /* Untimed. */
  9768. #ifdef MYREAD
  9769.     || (my_count > 0)        /* Buffered char already waiting. */
  9770. #endif /* MYREAD */
  9771.     ) {
  9772. #ifdef MYREAD
  9773.         /* Comm line failure returns -1 thru myread, so no &= 0377 */
  9774.     n = myread();            /* Wait for a character... */
  9775.     /* debug(F000,"ttinc MYREAD n","",n); */
  9776. #ifdef CK_ENCRYPTION
  9777.     /* debug(F101,"ttinc u_encrypt","",TELOPT_U(TELOPT_ENCRYPTION)); */
  9778.     if (TELOPT_U(TELOPT_ENCRYPTION) && n >= 0) {
  9779.         ch = n;
  9780.         ck_tn_decrypt(&ch,1);
  9781.         n = ch;
  9782.     }
  9783. #endif /* CK_ENCRYPTION */
  9784.  
  9785. #ifdef NETPTY
  9786.     if (ttpty && n < 0) {
  9787.         debug(F101,"ttinc error on pty","",n);
  9788.         ttclos(0);
  9789.         return(n);
  9790.     }
  9791. #endif /* NETPTY */
  9792.  
  9793. #ifdef TNCODE
  9794.     if ((n > -1) && is_tn)
  9795.       return((unsigned)(n & 0xff));
  9796.     else
  9797. #endif /* TNCODE */
  9798.       return(n < 0 ? n : (unsigned)(n & ttpmsk));
  9799.  
  9800. #else  /* MYREAD */
  9801.  
  9802.         while ((n = read(fd,&ch,1)) == 0) /* Wait for a character. */
  9803.         /* Shouldn't have to loop in ver 5A. */
  9804. #ifdef NETCONN
  9805.       if (netconn) {        /* Special handling for net */
  9806.           netclos();        /* If read() returns 0 it means */
  9807.           netconn = 0;        /* the connection has dropped. */
  9808.           errno = ENOTCONN;
  9809.           return(-2);
  9810.       }
  9811. #endif /* NETCONN */
  9812.       ;
  9813.     /* debug(F101,"ttinc","",ch); */
  9814. #ifdef TNCODE
  9815.     if ((n > 0) && is_tn) {
  9816. #ifdef CK_ENCRYPTION
  9817.         if (TELOPT_U(TELOPT_ENCRYPTION)) {
  9818.         ck_tn_decrypt(&ch,1);
  9819.         n = ch;
  9820.         }
  9821. #endif /* CK_ENCRYPTION */
  9822.         return((unsigned)(ch & 0xff));
  9823.     } else
  9824. #endif /* TNCODE */
  9825.         return((n < 0) ? -4 : ((n == 0) ? -1 : (unsigned)(ch & ttpmsk)));
  9826. #endif /* MYREAD */
  9827.  
  9828.     } else {                /* Timed read */
  9829.  
  9830.     int oldalarm;
  9831.     saval = signal(SIGALRM,timerh);    /* Set up handler, save old one. */
  9832.     oldalarm = alarm(timo);        /* Set alarm, save old one. */
  9833.     if (
  9834. #ifdef CK_POSIX_SIG
  9835.         sigsetjmp(sjbuf,1)
  9836. #else
  9837.         setjmp(sjbuf)
  9838. #endif /* CK_POSIX_SIG */
  9839.         ) {                /* Timer expired */
  9840.         ttinctimo = 1;
  9841.         n = -1;            /* set flag */
  9842.     } else {
  9843. #ifdef MYREAD
  9844.         n = myread();        /* If managing own buffer... */
  9845.         debug(F101,"ttinc myread","",n);
  9846.         ch = n;
  9847. #else
  9848.         n = read(fd,&ch,1);        /* Otherwise call the system. */
  9849.         if (n == 0) n = -1;
  9850.         debug(F101,"ttinc read","",n);
  9851. #endif /* MYREAD */
  9852.  
  9853. #ifdef CK_ENCRYPTION
  9854.         if (TELOPT_U(TELOPT_ENCRYPTION) && n >= 0) {
  9855.         ck_tn_decrypt(&ch,1);
  9856.         }
  9857. #endif /* CK_ENCRYPTION */
  9858.         if (n >= 0)
  9859.           n = (unsigned) (ch & 0xff);
  9860.         else
  9861.           n = (n < 0) ? -4 : -2;    /* Special return codes. */
  9862.     }
  9863.     ttimoff();            /* Turn off the timer */
  9864.     if (oldalarm > 0) {
  9865.         if (n == -1)        /* and restore any previous alarm */
  9866.           oldalarm -= timo;
  9867.         if (oldalarm < 0)        /* adjusted by our timeout interval */
  9868.           oldalarm = 0;
  9869.         if (oldalarm) {
  9870.             debug(F101,"ttinc restoring oldalarm","",oldalarm);
  9871.         alarm(oldalarm);
  9872.         }
  9873.     }
  9874. #ifdef NETCONN
  9875.     if (netconn) {
  9876.         if (n == -2) {        /* read() returns 0 */
  9877.         netclos();        /* on network read failure */
  9878.         netconn = 0;
  9879.         errno = ENOTCONN;
  9880.         }
  9881.     }
  9882. #endif    /* NETCONN */
  9883. #ifdef TNCODE
  9884.     if ((n > -1) && is_tn)
  9885.       return((unsigned)(n & 0xff));
  9886.     else
  9887. #endif /* TNCODE */
  9888.       /* Return masked char or neg. */
  9889.       return( (n < 0) ? n : (unsigned)(n & ttpmsk) );
  9890.     }
  9891. }
  9892.  
  9893. /*  S N D B R K  --  Send a BREAK signal of the given duration  */
  9894.  
  9895. static int
  9896. #ifdef CK_ANSIC
  9897. sndbrk(int msec) {            /* Argument is milliseconds */
  9898. #else
  9899. sndbrk(msec) int msec; {
  9900. #endif /* CK_ANSIC */
  9901. #ifndef POSIX
  9902.     int x, n;
  9903. #endif /* POSIX */
  9904.  
  9905. #ifdef OXOS
  9906. #define BSDBREAK
  9907. #endif /* OXOS */
  9908.  
  9909. #ifdef ANYBSD
  9910. #define BSDBREAK
  9911. #endif /* ANYBSD */
  9912.  
  9913. #ifdef BSD44
  9914. #define BSDBREAK
  9915. #endif /* BSD44 */
  9916.  
  9917. #ifdef COHERENT
  9918. #ifdef BSDBREAK
  9919. #undef BSDBREAK
  9920. #endif /* BSDBREAK */
  9921. #endif /* COHERENT */
  9922.  
  9923. #ifdef BELLV10
  9924. #ifdef BSDBREAK
  9925. #undef BSDBREAK
  9926. #endif /* BSDBREAK */
  9927. #endif /* BELLV10 */
  9928.  
  9929. #ifdef PROVX1
  9930.     char spd;
  9931. #endif /* PROVX1 */
  9932.  
  9933.     debug(F101,"ttsndb ttyfd","",ttyfd);
  9934.     if (ttyfd < 0) return(-1);          /* Not open. */
  9935.  
  9936. #ifdef Plan9
  9937.     return p9sndbrk(msec);
  9938. #else
  9939. #ifdef NETCONN
  9940. #ifdef NETCMD
  9941.     if (ttpipe)                /* Pipe */
  9942.       return(ttoc('\0'));
  9943. #endif /* NETCMD */
  9944. #ifdef NETPTY
  9945.     if (ttpty)
  9946.       return(ttoc('\0'));
  9947. #endif /* NETPTY */
  9948.     if (netconn)             /* Send network BREAK */
  9949.       return(netbreak());
  9950. #endif /* NETCONN */
  9951.  
  9952.     if (msec < 1 || msec > 5000) return(-1); /* Bad argument */
  9953.  
  9954. #ifdef POSIX                /* Easy in POSIX */
  9955.     debug(F101,"sndbrk POSIX","",msec);
  9956.     return(tcsendbreak(ttyfd,msec / 375));
  9957. #else
  9958. #ifdef PROVX1
  9959.     gtty(ttyfd,&ttbuf);                 /* Get current tty flags */
  9960.     spd = ttbuf.sg_ospeed;              /* Save speed */
  9961.     ttbuf.sg_ospeed = B50;              /* Change to 50 baud */
  9962.     stty(ttyfd,&ttbuf);                 /*  ... */
  9963.     n = (int)strlen(brnuls);        /* Send the right number of nulls */
  9964.     x = msec / 91;
  9965.     if (x > n) x = n;
  9966.     write(ttyfd,brnuls,n);
  9967.     ttbuf.sg_ospeed = spd;              /* Restore speed */
  9968.     stty(ttyfd,&ttbuf);                 /*  ... */
  9969.     return(0);
  9970. #else
  9971. #ifdef aegis
  9972.     sio_$control((short)ttyfd, sio_$send_break, msec, st);
  9973.     return(0);
  9974. #else
  9975. #ifdef BSDBREAK
  9976.     n = FWRITE;                         /* Flush output queue. */
  9977. /* Watch out for int vs long problems in &n arg! */
  9978.     debug(F101,"sndbrk BSDBREAK","",msec);
  9979.     ioctl(ttyfd,TIOCFLUSH,&n);          /* Ignore any errors.. */
  9980.     if (ioctl(ttyfd,TIOCSBRK,(char *)0) < 0) {  /* Turn on BREAK */
  9981.         perror("Can't send BREAK");
  9982.         return(-1);
  9983.     }
  9984.     x = msleep(msec);                    /* Sleep for so many milliseconds */
  9985.     if (ioctl(ttyfd,TIOCCBRK,(char *)0) < 0) {  /* Turn off BREAK */
  9986.         perror("BREAK stuck!!!");
  9987.         doexit(BAD_EXIT,-1);        /* Get out, closing the line. */
  9988.                                         /*   with bad exit status */
  9989.     }
  9990.     return(x);
  9991. #else
  9992. #ifdef ATTSV
  9993. /*
  9994.   No way to send a long BREAK in Sys V, so send a bunch of regular ones.
  9995.   (Actually, Sys V R4 is *supposed* to have the POSIX tcsendbreak() function,
  9996.   but there's no way for this code to know for sure.)
  9997. */
  9998.     debug(F101,"sndbrk ATTSV","",msec);
  9999.     x = msec / 275;
  10000.     for (n = 0; n < x; n++) {
  10001.     /* Reportedly the cast breaks this function on some systems */
  10002.     /* But then why was it here in the first place? */
  10003.     if (ioctl(ttyfd,TCSBRK, /* (char *) */ 0) < 0) {
  10004.         perror("Can't send BREAK");
  10005.         return(-1);
  10006.     }
  10007.     }
  10008.     return(0);
  10009. #else
  10010. #ifdef  V7
  10011.     debug(F101,"sndbrk V7","",msec);
  10012.     return(genbrk(ttyfd,250));        /* Simulate a BREAK */
  10013. #else
  10014.     debug(F101,"sndbrk catchall","",msec);
  10015.     ttoc(0);ttoc(0);ttoc(0);ttoc(0);
  10016.     return(0);
  10017. #endif /* V7 */
  10018. #endif /* BSDBREAK */
  10019. #endif /* ATTSV */
  10020. #endif /* aegis */
  10021. #endif /* PROVX1 */
  10022. #endif /* POSIX */
  10023. #endif /* Plan9 */
  10024. }
  10025.  
  10026. /*  T T S N D B  --  Send a BREAK signal  */
  10027.  
  10028. int
  10029. ttsndb() {
  10030.     return(sndbrk(275));
  10031. }
  10032.  
  10033. /*  T T S N D L B  --  Send a Long BREAK signal  */
  10034.  
  10035. int
  10036. ttsndlb() {
  10037.     return(sndbrk(1500));
  10038. }
  10039.  
  10040. /*  M S L E E P  --  Millisecond version of sleep().  */
  10041.  
  10042. /*
  10043.   Call with number of milliseconds (thousandths of seconds) to sleep.
  10044.   Intended only for small intervals.  For big ones, just use sleep().
  10045.   Highly system-dependent.
  10046.   Returns 0 always, even if it didn't work.
  10047. */
  10048.  
  10049. /* Define MSLFTIME for systems that must use an ftime() loop. */
  10050. #ifdef ANYBSD                /* For pre-4.2 BSD versions */
  10051. #ifndef BSD4
  10052. #define MSLFTIME
  10053. #endif /* BSD4 */
  10054. #endif /* ANYBSD */
  10055.  
  10056. #ifdef TOWER1                /* NCR Tower OS 1.0 */
  10057. #define MSLFTIME
  10058. #endif /* TOWER1 */
  10059.  
  10060. #ifdef COHERENT         /* Coherent... */
  10061. #ifndef _I386           /* Maybe Coherent/386 should get this, too */
  10062. #define MSLFTIME        /* Opinions are divided */
  10063. #endif /* _I386 */
  10064. #endif /* COHERENT */
  10065.  
  10066. #ifdef COMMENT
  10067. #ifdef GETMSEC
  10068.  
  10069. /* Millisecond timer */
  10070.  
  10071. static long msecbase = 0L;        /* Unsigned long not portable */
  10072.  
  10073. long
  10074. getmsec() {                /* Milliseconds since base time */
  10075.     struct timeval xv;
  10076.     struct timezone xz;
  10077.     long secs, msecs;
  10078.     if (
  10079. #ifdef GTODONEARG
  10080.     gettimeofday(&tv)
  10081. #else
  10082. #ifdef PTX
  10083.     gettimeofday(&tv, NULL)
  10084. #else
  10085.     gettimeofday(&tv, &tz)
  10086. #endif /* PTX */
  10087. #endif /* GTODONEARG */
  10088.     < 0)
  10089.       return(-1);
  10090.     if (msecbase == 0L) {        /* First call, set base time. */
  10091.     msecbase = tv.tv_sec;
  10092.     debug(F101,"getmsec base","",msecbase);
  10093.     }
  10094.     return(((tv.tv_sec - msecbase) * 1000L) + (tv.tv_usec / 1000L));
  10095. }
  10096. #endif /* GETMSEC */
  10097. #endif /* COMMENT */
  10098.  
  10099. #ifdef SELECT
  10100. int
  10101. ttwait(fd, secs) int fd, secs; {
  10102.     int x;
  10103.     fd_set rfds;
  10104.     FD_ZERO(&rfds);
  10105.     FD_SET(fd,&rfds);
  10106.     tv.tv_sec = secs;
  10107.     tv.tv_usec = 0L;
  10108.     errno = 0;
  10109.     if ((x = select(FD_SETSIZE,
  10110. #ifdef HPUX9
  10111.             (int *)
  10112. #else
  10113. #ifdef HPUX1000
  10114.             (int *)
  10115. #endif /* HPUX1000 */
  10116. #endif /* HPUX9 */
  10117.             &rfds,
  10118.             0, 0, &tv)) < 0) {
  10119.     debug(F101,"ttwait select errno","",errno);
  10120.     return(0);
  10121.     } else {
  10122.     debug(F101,"ttwait OK","",errno);
  10123.     x = FD_ISSET(fd, &rfds);
  10124.     debug(F101,"ttwait select x","",x);
  10125.     return(x ? 1 : 0);
  10126.     }
  10127. }
  10128. #endif /* SELECT */
  10129.  
  10130. int
  10131. msleep(m) int m; {
  10132. /*
  10133.   Other possibilities here are:
  10134.    nanosleep(), reportedly defined in POSIX.4.
  10135.    sginap(), IRIX only (back to what IRIX version I don't know).
  10136. */
  10137. #ifdef Plan9
  10138.     return _SLEEP(m);
  10139. #else
  10140. #ifdef BEOSORBEBOX
  10141.     snooze(m*1000);
  10142. #else /* BEOSORBEBOX */
  10143. #ifdef SELECT
  10144.     int t1, x;
  10145.     debug(F101,"msleep SELECT 1","",m);
  10146.     if (m <= 0) return(0);
  10147.     if (m >= 1000) {            /* Catch big arguments. */
  10148.     sleep(m/1000);
  10149.     m = m % 1000;
  10150.     if (m < 10) return(0);
  10151.     }
  10152.     debug(F101,"msleep SELECT 2","",m);
  10153. #ifdef BELLV10
  10154.     x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, m );
  10155.     debug(F101,"msleep BELLV10 select","",x);
  10156. #else /* BELLV10 */
  10157. #ifdef HPUX9
  10158.     gettimeofday(&tv, &tz);
  10159. #else
  10160.  
  10161. #ifndef COHERENT
  10162. #ifdef GTODONEARG
  10163.     if (gettimeofday(&tv) < 0)
  10164. #else
  10165. #ifdef PTX
  10166.     if (gettimeofday(&tv,NULL) < 0)
  10167. #else
  10168.     if (gettimeofday(&tv, &tz) < 0)
  10169. #endif /* PTX */
  10170. #endif /* GTODONEARG */
  10171.       return(-1);
  10172.     t1 = tv.tv_sec;                     /* Seconds */
  10173. #endif /* COHERENT */
  10174. #endif /* HPUX9 */
  10175.     tv.tv_sec = 0;                      /* Use select() */
  10176.     tv.tv_usec = m * 1000L;
  10177. #ifdef BSD44
  10178.     x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
  10179.     debug(F101,"msleep BSD44 select","",x);
  10180. #else /* BSD44 */
  10181. #ifdef __linux__
  10182.     x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
  10183.     debug(F101,"msleep __linux__ select","",x);
  10184. #else /* __linux__ */
  10185. #ifdef BSD43
  10186.     x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
  10187.     debug(F101,"msleep BSD43 select","",x);
  10188. #else /* BSD43 */
  10189. #ifdef QNX
  10190.     x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
  10191.     debug(F101,"msleep QNX select","",x);
  10192. #else /* QNX */
  10193. #ifdef COHERENT
  10194.     x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
  10195.     debug(F101,"msleep COHERENT select","",x);
  10196. #else /* COHERENT */
  10197. #ifdef HPUX1000                /* 10.00 only, not 10.10 or later */
  10198.     x = select( 0, (int *)0, (int *)0, (int *)0, &tv );
  10199.     debug(F101,"msleep HP-UX 10.00 select","",x);
  10200. #else /* HPUX1000 */
  10201. #ifdef SVR4
  10202.     x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
  10203.     debug(F101,"msleep SVR4 select","",x);
  10204. #else /* SVR4 */
  10205. #ifdef OSF40
  10206.     x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
  10207.     debug(F101,"msleep OSF40 select","",x);
  10208. #else /* OSF40 */
  10209. #ifdef PTX
  10210.     x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
  10211.     debug(F101,"msleep OSF40 select","",x);
  10212. #else
  10213.     x = select( 0, (int *)0, (int *)0, (int *)0, &tv );
  10214.     debug(F101,"msleep catch-all select","",x);
  10215. #endif /* PTX */
  10216. #endif /* OSF40 */
  10217. #endif /* HP1000 */
  10218. #endif /* SVR4 */
  10219. #endif /* COHERENT */
  10220. #endif /* QNX */
  10221. #endif /* BSD43 */
  10222. #endif /* __linux__ */
  10223. #endif /* BSD44 */
  10224. #endif /* BELLV10 */
  10225.     return(0);
  10226.  
  10227. #else                    /* Not SELECT */
  10228. #ifdef CK_POLL                /* We have poll() */
  10229.     struct pollfd pfd;            /* Supply a valid address for poll() */
  10230.  
  10231. #ifdef ODT30                /* But in SCO ODT 3.0 */
  10232. #ifdef NAP                /* we should use nap() instead */
  10233.     debug(F101,"msleep ODT 3.0 NAP","",m); /* because using poll() here */
  10234.     nap((long)m);               /* seems to break dialing. */
  10235.     return(0);
  10236. #else
  10237.     debug(F101,"msleep ODT 3.0 POLL","",m);
  10238.     poll(&pfd, 0, m);
  10239.     return(0);
  10240. #endif /* NAP */
  10241. #else
  10242.     debug(F101,"msleep POLL","",m);
  10243.     poll(&pfd, 0, m);
  10244.     return(0);
  10245. #endif /* ODT30 */
  10246.  
  10247. /*
  10248.   We could handle the above more cleanly by just letting nap() take
  10249.   always take precedence over poll() in this routine, but there is no way
  10250.   to know whether that would break something else.
  10251. */
  10252.  
  10253. #else                    /* Not POLL */
  10254. #ifdef USLEEP
  10255. /*
  10256.   "This routine is implemented using setitimer(2); it requires eight
  10257.   system calls...".  In other words, it might take 5 minutes to sleep
  10258.   10 milliseconds...
  10259. */
  10260.     debug(F101,"msleep USLEEP","",m);
  10261.     if (m >= 1000) {            /* Catch big arguments. */
  10262.     sleep(m/1000);
  10263.     m = m % 1000;
  10264.     if (m < 10) return(0);
  10265.     }
  10266.     usleep((unsigned int)(m * 1000));
  10267.     return(0);
  10268. #else
  10269. #ifdef aegis
  10270.     time_$clock_t dur;
  10271.     debug(F101,"msleep aegis","",m);
  10272.     dur.c2.high16 = 0;
  10273.     dur.c2.low32  = 250 * m; /* one millisecond = 250 four microsecond ticks */
  10274.     time_$wait(time_$relative, dur, st);
  10275.     return(0);
  10276. #else
  10277. #ifdef PROVX1
  10278.     debug(F101,"msleep Venix","",m);
  10279.     if (m <= 0) return(0);
  10280.     sleep(-((m * 60 + 500) / 1000));
  10281.     return(0);
  10282. #else
  10283. #ifdef NAP
  10284.     debug(F101,"msleep NAP","",m);
  10285.     nap((long)m);
  10286.     return(0);
  10287. #else
  10288. #ifdef ATTSV
  10289. #ifndef BSD44
  10290.     extern long times();        /* Or #include <times.h> ? */
  10291. #endif /* BSD44 */
  10292.     long t1, t2, tarray[4];
  10293.     int t3;
  10294.     char *cp = getenv("HZ");
  10295.     int CLOCK_TICK;
  10296.     int hertz;
  10297.  
  10298.     if (cp && (hertz = atoi(cp))) {
  10299.         CLOCK_TICK  = 1000 / hertz;
  10300.     } else {                /* probably single user mode */
  10301. #ifdef HZ
  10302.         CLOCK_TICK  = 1000 / HZ;
  10303. #else
  10304.     static warned = 0;
  10305.     /* HZ always exists in, for instance, SCO Xenix, so you don't have to
  10306.      * make special #ifdefs for XENIX here, like in ver 4F. Also, if you
  10307.      * have Xenix, you have should have nap(), so the best is to use -DNAP
  10308.      * in the makefile. Most systems have HZ.
  10309.      */
  10310.     CLOCK_TICK = 17;        /* 1/60 sec */
  10311.     if (!warned) {
  10312.           printf("warning: environment variable HZ bad... using HZ=%d\r\n",
  10313.          1000 / CLOCK_TICK);
  10314.           warned = 1;
  10315.     }
  10316. #endif /* !HZ */
  10317.     }
  10318.     debug(F101,"msleep ATTSV","",m);
  10319.     if (m <= 0) return(0);
  10320.     if (m >= 1000) {            /* Catch big arguments. */
  10321.     sleep(m/1000);
  10322.     m = m % 1000;
  10323.     if (m < 10) return(0);
  10324.     }
  10325.     if ((t1 = times(tarray)) < 0) return(-1);
  10326.     while (1) {
  10327.         if ((t2 = times(tarray)) < 0) return(-1);
  10328.         t3 = ((int)(t2 - t1)) * CLOCK_TICK;
  10329.         if (t3 > m) return(t3);
  10330.     }
  10331. #else /* Not ATTSV */
  10332. #ifdef MSLFTIME                /* Use ftime() loop... */
  10333.     int t1, t3 = 0;
  10334.     debug(F101,"msleep MSLFTIME","",m);
  10335.     if (m <= 0) return(0);
  10336.     if (m >= 1000) {            /* Catch big arguments. */
  10337.     sleep(m/1000);
  10338.     m = m % 1000;
  10339.     if (m < 10) return(0);
  10340.     }
  10341. #ifdef QNX
  10342.     ftime(&ftp);            /* void ftime() in QNX */
  10343. #else
  10344.     if (ftime(&ftp) < 0) return(-1);    /* Get base time. */
  10345. #endif /* QNX */
  10346.     t1 = ((ftp.time & 0xff) * 1000) + ftp.millitm;
  10347.     while (1) {
  10348.         ftime(&ftp);            /* Get current time and compare. */
  10349.         t3 = (((ftp.time & 0xff) * 1000) + ftp.millitm) - t1;
  10350.         if (t3 > m) return(0);
  10351.     }
  10352. #else
  10353. /* This includes true POSIX, which has no way to do this. */
  10354.     debug(F101,"msleep busy loop","",m);
  10355.     if (m >= 1000) {            /* Catch big arguments. */
  10356.     sleep(m/1000);
  10357.     m = m % 1000;
  10358.     if (m < 10) return(0);
  10359.     }
  10360.     if (m > 0) while (m > 0) m--;    /* Just a dumb busy loop */
  10361.     return(0);
  10362. #endif /* MSLFTIME */
  10363. #endif /* ATTSV */
  10364. #endif /* NAP */
  10365. #endif /* PROVX1 */
  10366. #endif /* aegis */
  10367. #endif /* CK_POLL */
  10368. #endif /* SELECT */
  10369. #endif /* BEOSORBEBOX */
  10370. #endif /* USLEEP */
  10371. #endif /* Plan9 */
  10372. }
  10373.  
  10374. /*  R T I M E R --  Reset elapsed time counter  */
  10375.  
  10376. VOID
  10377. rtimer() {
  10378.     tcount = time( (time_t *) 0 );
  10379. }
  10380.  
  10381.  
  10382. /*  G T I M E R --  Get current value of elapsed time counter in seconds  */
  10383.  
  10384. int
  10385. gtimer() {
  10386.     int x;
  10387.     x = (int) (time( (time_t *) 0 ) - tcount);
  10388.     debug(F101,"gtimer","",x);
  10389.     return( (x < 0) ? 0 : x );
  10390. }
  10391.  
  10392. #ifdef GFTIMER
  10393. /*
  10394.   Floating-point timers.  Require not only floating point support, but
  10395.   also gettimeofday().
  10396. */
  10397. static struct timeval tzero;
  10398.  
  10399. VOID
  10400. rftimer() {
  10401. #ifdef GTODONEARG    /* Account for Mot's definition */
  10402.     (VOID) gettimeofday(&tzero);
  10403. #else
  10404.     (VOID) gettimeofday(&tzero, (struct timezone *)0);
  10405. #endif /* GTODONEARG */
  10406. }
  10407.  
  10408. CKFLOAT
  10409. gftimer() {
  10410.     struct timeval tnow, tdelta;
  10411.     CKFLOAT s, sb;
  10412. #ifdef DEBUG
  10413.     char fpbuf[64];
  10414. #endif /* DEBUG */
  10415. #ifdef GTODONEARG    /* Acount for Mot's definition */
  10416.     (VOID) gettimeofday(&tnow);
  10417. #else
  10418.     (VOID) gettimeofday(&tnow, (struct timezone *)0);
  10419. #endif /* GTODONEARG */
  10420.     tdelta.tv_sec = tnow.tv_sec - tzero.tv_sec;
  10421.     tdelta.tv_usec = tnow.tv_usec - tzero.tv_usec;
  10422.     if (tdelta.tv_usec < 0) {
  10423.     tdelta.tv_sec--;
  10424.     tdelta.tv_usec += 1000000;
  10425.     }
  10426.     s = (CKFLOAT) tdelta.tv_sec + ((CKFLOAT) tdelta.tv_usec / 1000000.0);
  10427.     if (s < GFMINTIME)
  10428.       s = GFMINTIME;
  10429. #ifdef DEBUG
  10430.     if (deblog) {
  10431.     sprintf(fpbuf,"%f",s);
  10432.     debug(F110,"gftimer",fpbuf,0);
  10433.     }
  10434. #endif /* DEBUG */
  10435.     return(s);
  10436. }
  10437. #endif /* GFTIMER */
  10438.  
  10439.  
  10440. /*  Z T I M E  --  Return asctime()-format date/time string  */
  10441. /*
  10442.   NOTE: as a side effect of calling this routine, we can also set the
  10443.   following two variables, giving the micro- and milliseconds (fractions of
  10444.   seconds) of the clock time.  Currently this is done only in BSD-based builds
  10445.   that use gettimeofday().  When these variables are not filled in, they are
  10446.   left with a value of -1L.
  10447. */
  10448. VOID
  10449. ztime(s) char **s; {
  10450.  
  10451. #ifdef GFTIMER
  10452. /*
  10453.   The gettimeofday() method, which also sets ztmsec and ztusec, works for
  10454.   all GFTIMER builds.  NOTE: ztmsec and ztusec are defined in ckcmai.c,
  10455.   and extern declarations for them are in ckcdeb.h; thus they are
  10456.   declared in this file by inclusion of ckcdeb.h.
  10457. */
  10458.     char *asctime();
  10459.     struct tm *localtime();
  10460.     struct tm *tp;
  10461.     ztmsec = -1L;
  10462.     ztusec = -1L;
  10463.  
  10464. #ifdef GTODONEARG
  10465.     /* No 2nd arg in Motorola SV88 and some others */
  10466.     if (gettimeofday(&tv) > -1)
  10467. #else
  10468. #ifndef COHERENT
  10469. #ifdef PTX
  10470.     if (gettimeofday(&tv,NULL) > -1)
  10471. #else
  10472.     if (gettimeofday(&tv,&tz) > -1)
  10473. #endif /* PTX */
  10474. #endif /* COHERENT */
  10475. #endif /* GTODONEARG */
  10476.       {                    /* Fill in tm struct */
  10477.     ztusec = tv.tv_usec;        /* Microseconds */
  10478.     ztmsec = ztusec / 1000L;    /* Milliseconds */
  10479. #ifdef HPUX9
  10480.     {
  10481.         time_t zz;
  10482.         zz = tv.tv_sec;
  10483.         tp = localtime(&zz);    /* Convert to local time */
  10484.     }
  10485. #else
  10486. #ifdef HPUX1000
  10487.     {
  10488.         time_t zz;
  10489.         zz = tv.tv_sec;
  10490.         tp = localtime(&zz);
  10491.     }
  10492. #else
  10493. #ifdef LINUX
  10494.     {   /* avoid unaligned access trap on 64-bit platforms */
  10495.         time_t zz;
  10496.         zz = tv.tv_sec;
  10497.         tp = localtime(&zz);
  10498.     }
  10499. #else
  10500. #ifdef MACOSX
  10501.     tp = localtime((time_t *)&tv.tv_sec); /* Convert to local time */
  10502. #else
  10503.     tp = localtime(&tv.tv_sec);
  10504. #endif /* MACOSX */
  10505. #endif /* LINUX */
  10506. #endif /* HPUX1000 */
  10507. #endif /* HPUX9 */
  10508.     *s = asctime(tp);        /* Convert result to ASCII string */
  10509.     debug(F111,"ztime GFTIMER gettimeofday",*s,ztusec);
  10510.     }
  10511. #else  /* Not GFTIMER */
  10512.  
  10513. #undef ZTIMEV7                /* Which systems need to use */
  10514. #ifdef COHERENT                /* old UNIX Version 7 way... */
  10515. #define ZTIMEV7
  10516. #endif /* COHERENT */
  10517. #ifdef TOWER1
  10518. #define ZTIMEV7
  10519. #endif /* TOWER1 */
  10520. #ifdef ANYBSD
  10521. #ifndef BSD42
  10522. #define ZTIMEV7
  10523. #endif /* BSD42 */
  10524. #endif /* ANYBSD */
  10525. #ifdef V7
  10526. #ifndef MINIX
  10527. #define ZTIMEV7
  10528. #endif /* MINIX */
  10529. #endif /* V7 */
  10530. #ifdef POSIX
  10531. #define ZTIMEV7
  10532. #endif /* POSIX */
  10533.  
  10534. #ifdef HPUX1020
  10535. /*
  10536.   Prototypes are in <time.h>, included above.
  10537. */
  10538.     time_t clock_storage;
  10539.     clock_storage = time((void *) 0);
  10540.     *s = ctime(&clock_storage);
  10541.     debug(F110,"ztime: HPUX 10.20",*s,0);
  10542. #else
  10543. #ifdef ATTSV                /* AT&T way */
  10544. /*  extern long time(); */        /* Theoretically these should */
  10545.     char *ctime();            /* already been dcl'd in <time.h> */
  10546.     time_t clock_storage;
  10547.     clock_storage = time(
  10548. #ifdef IRIX60
  10549.              (time_t *)
  10550. #else
  10551. #ifdef BSD44
  10552.              (time_t *)
  10553. #else
  10554.              (long *)
  10555. #endif /* BSD44 */
  10556. #endif /* IRIX60 */
  10557.              0 );
  10558.     *s = ctime( &clock_storage );
  10559.     debug(F110,"ztime: ATTSV",*s,0);
  10560. #else
  10561. #ifdef PROVX1                /* Venix 1.0 way */
  10562.     int utime[2];
  10563.     time(utime);
  10564.     *s = ctime(utime);
  10565.     debug(F110,"ztime: PROVX1",*s,0);
  10566. #else
  10567. #ifdef BSD42                /* 4.2BSD way */
  10568.     char *asctime();
  10569.     struct tm *localtime();
  10570.     struct tm *tp;
  10571.     gettimeofday(&tv, &tz);
  10572.     ztusec = tv.tv_usec;
  10573.     ztmsec = tv.tv_usec / 1000L;
  10574.     tp = localtime(&tv.tv_sec);
  10575.     *s = asctime(tp);
  10576.     debug(F111,"ztime: BSD42",*s,ztusec);
  10577. #else
  10578. #ifdef MINIX                /* MINIX way */
  10579. #ifdef COMMENT
  10580.     extern long time();            /* Already got these from <time.h> */
  10581.     extern char *ctime();
  10582. #endif /* COMMENT */
  10583.     time_t utime[2];
  10584.     time(utime);
  10585.     *s = ctime(utime);
  10586.     debug(F110,"ztime: MINIX",*s,0);
  10587. #else
  10588. #ifdef ZTIMEV7                /* The regular way */
  10589.     char *asctime();
  10590.     struct tm *localtime();
  10591.     struct tm *tp;
  10592.     long xclock;            /* or unsigned long for BeBox? */
  10593.     time(&xclock);
  10594.     tp = localtime(&xclock);
  10595.     *s = asctime(tp);
  10596.     debug(F110,"ztime: ZTIMEV7",*s,0);
  10597. #else                    /* Catch-all for others... */
  10598.     *s = "Day Mon 00 00:00:00 0000\n";    /* Return dummy in asctime() format */
  10599.     debug(F110,"ztime: catch-all",*s,0);
  10600. #endif /* ZTIMEV7 */
  10601. #endif /* MINIX */
  10602. #endif /* BSD42 */
  10603. #endif /* PROVX1 */
  10604. #endif /* ATTSV */
  10605. #endif /* HPUX1020 */
  10606. #endif /* GFTIMER */
  10607. }
  10608.  
  10609. /*  C O N G M  --  Get console terminal modes.  */
  10610.  
  10611. /*
  10612.   Saves initial console mode, and establishes variables for switching
  10613.   between current (presumably normal) mode and other modes.
  10614.   Should be called when program starts, but only after establishing
  10615.   whether program is in the foreground or background.
  10616.   Returns 1 if it got the modes OK, 0 if it did nothing, -1 on error.
  10617. */
  10618. int
  10619. congm() {
  10620.     int fd;
  10621.     if (backgrd || !isatty(0)) {    /* If in background. */
  10622.     cgmf = -1;            /* Don't bother, modes are garbage. */
  10623.     return(-1);
  10624.     }
  10625.     if (cgmf > 0) return(0);        /* Already did this. */
  10626.     debug(F100,"congm getting modes","",0); /* Need to do it. */
  10627. #ifdef aegis
  10628.     ios_$inq_type_uid(ios_$stdin, conuid, st);
  10629.     if (st.all != status_$ok) {
  10630.     fprintf(stderr, "problem getting stdin objtype: ");
  10631.     error_$print(st);
  10632.     }
  10633.     concrp = (conuid == mbx_$uid);
  10634.     conbufn = 0;
  10635. #endif /* aegis */
  10636.  
  10637. #ifndef BEBOX
  10638.     if ((fd = open(CTTNAM,2)) < 0) {    /* Open controlling terminal */
  10639. #ifdef COMMENT
  10640.     fprintf(stderr,"Error opening %s\n", CTTNAM);
  10641.     perror("congm");
  10642.     return(-1);
  10643. #else
  10644.     fd = 0;
  10645. #endif /* COMMENT */
  10646.     }
  10647. #else
  10648.     fd = 0;
  10649. #endif /* !BEBOX */
  10650. #ifdef BSD44ORPOSIX
  10651.     if (tcgetattr(fd,&ccold) < 0) return(-1);
  10652.     if (tcgetattr(fd,&cccbrk) < 0) return(-1);
  10653.     if (tcgetattr(fd,&ccraw) < 0) return(-1);
  10654. #else
  10655. #ifdef ATTSV
  10656.     if (ioctl(fd,TCGETA,&ccold)  < 0) return(-1);
  10657.     if (ioctl(fd,TCGETA,&cccbrk) < 0) return(-1);
  10658.     if (ioctl(fd,TCGETA,&ccraw)  < 0) return(-1);
  10659. #ifdef VXVE
  10660.     cccbrk.c_line = 0;            /* STTY line 0 for CDC VX/VE */
  10661.     if (ioctl(fd,TCSETA,&cccbrk) < 0) return(-1);
  10662.     ccraw.c_line = 0;            /* STTY line 0 for CDC VX/VE */
  10663.     if (ioctl(fd,TCSETA,&ccraw) < 0) return(-1);
  10664. #endif /* VXVE */
  10665. #else
  10666. #ifdef BELLV10
  10667.     if (ioctl(fd,TIOCGETP,&ccold) < 0) return(-1);
  10668.     if (ioctl(fd,TIOCGETP,&cccbrk) < 0) return(-1);
  10669.     if (ioctl(fd,TIOCGETP,&ccraw) < 0) return(-1);
  10670.     debug(F101,"cccbrk.sg_flags orig","", cccbrk.sg_flags);
  10671. #else
  10672.     if (gtty(fd,&ccold) < 0) return(-1);
  10673.     if (gtty(fd,&cccbrk) < 0) return(-1);
  10674.     if (gtty(fd,&ccraw) < 0) return(-1);
  10675. #endif /* BELLV10 */
  10676. #endif /* ATTSV */
  10677. #endif /* BSD44ORPOSIX */
  10678. #ifdef sony_news            /* Sony NEWS */
  10679.     if (ioctl(fd,TIOCKGET,&km_con) < 0) { /* Get console Kanji mode */
  10680.     perror("congm error getting Kanji mode");
  10681.     debug(F101,"congm error getting Kanji mode","",0);
  10682.     km_con = -1;            /* Make sure this stays undefined. */
  10683.     return(-1);
  10684.     }
  10685. #endif /* sony_news */
  10686.     if (fd > 0)
  10687.       close(fd);
  10688.     cgmf = 1;                /* Flag that we got them. */
  10689.     return(1);
  10690. }
  10691.  
  10692.  
  10693. /*  C O N C B --  Put console in cbreak mode.  */
  10694.  
  10695. /*  Returns 0 if ok, -1 if not  */
  10696.  
  10697. int
  10698. #ifdef CK_ANSIC
  10699. concb(char esc)
  10700. #else
  10701. concb(esc) char esc;
  10702. #endif /* CK_ANSIC */
  10703. /* concb */ {
  10704.     int x;
  10705.     debug(F101,"concb cgmf","",cgmf);
  10706.     debug(F101,"concb backgrd","",backgrd);
  10707.  
  10708.     if (cgmf < 1)            /* Did we get console modes yet? */
  10709.       if (!backgrd)            /* No, in background? */
  10710.     congm();            /* No, try to get them now. */
  10711.     if (cgmf < 1)            /* Still don't have them? */
  10712.       return(0);            /* Give up. */
  10713.     debug(F101,"concb ttyfd","",ttyfd);
  10714.     debug(F101,"concb ttfdflg","",ttfdflg);
  10715. #ifdef COMMENT
  10716.     /* This breaks returning to prompt after protocol with "-l 0" */
  10717.     /* Commented out July 1998 */
  10718.     if (ttfdflg && ttyfd >= 0 && ttyfd < 3)
  10719.       return(0);
  10720. #endif /* COMMENT */
  10721.     x = isatty(0);
  10722.     debug(F101,"concb isatty","",x);
  10723.     if (!x) return(0);            /* Only when running on real ttys */
  10724.     debug(F101,"concb suspend","",suspend);
  10725.     if (backgrd) return(0);        /* Do nothing if in background. */
  10726.     escchr = esc;                       /* Make this available to other fns */
  10727.     ckxech = 1;                         /* Program can echo characters */
  10728. #ifdef aegis
  10729.     conbufn = 0;
  10730.     if (concrp) return(write(1, "\035\002", 2));
  10731.     if (conuid == input_pad_$uid) {pad_$raw(ios_$stdin, st); return(0);}
  10732. #endif /* aegis */
  10733.  
  10734. #ifdef COHERENT
  10735. #define SVORPOSIX
  10736. #endif /* COHERENT */
  10737.  
  10738. #ifdef Plan9
  10739.     x = p9concb();
  10740. #else
  10741. #ifndef SVORPOSIX            /* BSD, V7, etc */
  10742.     debug(F101,"cccbrk.sg_flags concb 1","", cccbrk.sg_flags);
  10743.     debug(F101,"concb stty CBREAK","",0);
  10744.     cccbrk.sg_flags |= (CBREAK|CRMOD);    /* Set to character wakeup, */
  10745.     cccbrk.sg_flags &= ~ECHO;           /* no echo. */
  10746.     debug(F101,"cccbrk.sg_flags concb 2","", cccbrk.sg_flags);
  10747. #ifdef BELLV10
  10748.     x = ioctl(0,TIOCSETP,&cccbrk);
  10749. #else
  10750.     x = stty(0,&cccbrk);
  10751.     debug(F101,"cccbrk.sg_flags concb x","", x);
  10752. #endif /* BELLV10 */
  10753. #else                    /* Sys V and POSIX */
  10754. #ifndef OXOS
  10755.     debug(F101,"concb cccbrk.c_flag","",cccbrk.c_lflag);
  10756. #ifdef QNX
  10757.     /* Don't mess with IEXTEN */
  10758.     cccbrk.c_lflag &= ~(ICANON|ECHO);
  10759. #else
  10760. #ifdef COHERENT
  10761.     cccbrk.c_lflag &= ~(ICANON|ECHO);
  10762. #else
  10763.     cccbrk.c_lflag &= ~(ICANON|ECHO|IEXTEN);
  10764. #endif /* COHERENT */
  10765. #endif /* QNX */
  10766.     cccbrk.c_lflag |= ISIG;        /* Allow signals in command mode. */
  10767.     cccbrk.c_iflag |= IGNBRK;        /* But ignore BREAK signal */
  10768.     cccbrk.c_iflag &= ~BRKINT;
  10769.  
  10770. #else /* OXOS */
  10771.     debug(F100,"concb OXOS is defined","",0);
  10772.     cccbrk.c_lflag &= ~(ICANON|ECHO);
  10773.     cccbrk.c_cc[VDISCARD] = cccbrk.c_cc[VLNEXT] = CDISABLE;
  10774. #endif /* OXOS */
  10775. #ifdef COMMENT
  10776. /*
  10777.   Believe it or not, in SCO UNIX, VSUSP is greater than NCC, and so this
  10778.   array reference is out of bounds.  It's only a debug() call so who needs it.
  10779. */
  10780. #ifdef VSUSP
  10781.     debug(F101,"concb c_cc[VSUSP]","",cccbrk.c_cc[VSUSP]);
  10782. #endif /* VSUSP */
  10783. #endif /* COMMENT */
  10784. #ifndef VINTR
  10785.     debug(F101,"concb c_cc[0]","",cccbrk.c_cc[0]);
  10786.     cccbrk.c_cc[0] = 003;               /* Interrupt char is Control-C */
  10787. #else
  10788.     debug(F101,"concb c_cc[VINTR]","",cccbrk.c_cc[0]);
  10789.     cccbrk.c_cc[VINTR] = 003;
  10790. #endif /* VINTR */
  10791. #ifndef VQUIT
  10792.     cccbrk.c_cc[1] = escchr;            /* escape during packet modes */
  10793. #else
  10794.     cccbrk.c_cc[VQUIT] = escchr;
  10795. #endif /* VQUIT */
  10796. #ifndef VEOF
  10797.     cccbrk.c_cc[4] = 1;
  10798. #else
  10799. #ifndef OXOS
  10800. #ifdef VMIN
  10801.     cccbrk.c_cc[VMIN] = 1;
  10802. #endif /* VMIN */
  10803. #else /* OXOS */
  10804.     cccbrk.c_min = 1;
  10805. #endif /* OXOS */
  10806. #endif /* VEOF */
  10807. #ifdef ZILOG
  10808.     cccbrk.c_cc[5] = 0;
  10809. #else
  10810. #ifndef VEOL
  10811.     cccbrk.c_cc[5] = 1;
  10812. #else
  10813. #ifndef OXOS
  10814. #ifdef VTIME
  10815.     cccbrk.c_cc[VTIME] = 1;
  10816. #endif /* VTIME */
  10817. #else /* OXOS */
  10818.     cccbrk.c_time = 1;
  10819. #endif /* OXOS */
  10820. #endif /* VEOL */
  10821. #endif /* ZILOG */
  10822. #ifdef BSD44ORPOSIX            /* Set new modes */
  10823.     x = tcsetattr(0,TCSADRAIN,&cccbrk);
  10824. #else /* ATTSV */                  /* or the POSIX way */
  10825.     x = ioctl(0,TCSETAW,&cccbrk);    /* the Sys V way */
  10826. #endif /* BSD44ORPOSIX */
  10827. #endif /* SVORPOSIX */
  10828.  
  10829. #ifdef COHERENT
  10830. #undef SVORPOSIX
  10831. #endif /* COHERENT */
  10832.  
  10833. #ifndef aegis
  10834. #ifndef NOSETBUF
  10835.     if (x > -1) setbuf(stdout,NULL);    /* Make console unbuffered. */
  10836. #endif /* NOSETBUF */
  10837. #endif /* aegis */
  10838.  
  10839. #ifdef  V7
  10840. #ifndef MINIX
  10841.     if (kmem[CON] < 0) {
  10842.         qaddr[CON] = initrawq(0);
  10843.         if((kmem[CON] = open("/dev/kmem", 0)) < 0) {
  10844.             fprintf(stderr, "Can't read /dev/kmem in concb.\n");
  10845.             perror("/dev/kmem");
  10846.             exit(1);
  10847.         }
  10848.     }
  10849. #endif /* MINIX */
  10850. #endif /* V7 */
  10851. #endif /* Plan9 */
  10852.     debug(F101,"concb returns","",x);
  10853.     return(x);
  10854. }
  10855.  
  10856. /*  C O N B I N  --  Put console in binary mode  */
  10857.  
  10858. /*  Returns 0 if ok, -1 if not  */
  10859.  
  10860. int
  10861. #ifdef CK_ANSIC
  10862. conbin(char esc)
  10863. #else
  10864. conbin(esc) char esc;
  10865. #endif /* CK_ANSIC */
  10866. /* conbin */  {
  10867.  
  10868.     if (!isatty(0)) return(0);          /* only for real ttys */
  10869.     congm();                /* Get modes if necessary. */
  10870.     debug(F100,"conbin","",0);
  10871.     escchr = esc;                       /* Make this available to other fns */
  10872.     ckxech = 1;                         /* Program can echo characters */
  10873. #ifdef aegis
  10874.     conbufn = 0;
  10875.     if (concrp) return(write(1, "\035\002", 2));
  10876.     if (conuid == input_pad_$uid) {
  10877.     pad_$raw(ios_$stdin, st);
  10878.     return(0);
  10879.       }
  10880. #endif /* aegis */
  10881.  
  10882. #ifdef COHERENT
  10883. #define SVORPOSIX
  10884. #endif /* COHERENT */
  10885.  
  10886. #ifdef Plan9
  10887.     return p9conbin();
  10888. #else
  10889. #ifdef SVORPOSIX
  10890. #ifndef OXOS
  10891. #ifdef QNX
  10892.     ccraw.c_lflag &= ~(ISIG|ICANON|ECHO);
  10893. #else
  10894. #ifdef COHERENT
  10895.     ccraw.c_lflag &= ~(ISIG|ICANON|ECHO);
  10896. #else
  10897.     ccraw.c_lflag &= ~(ISIG|ICANON|ECHO|IEXTEN);
  10898. #endif /* COHERENT */
  10899. #endif /* QNX */
  10900. #else /* OXOS */
  10901.     ccraw.c_lflag &= ~(ISIG|ICANON|ECHO);
  10902.     ccraw.c_cc[VDISCARD] = ccraw.c_cc[VLNEXT] = CDISABLE;
  10903. #endif /* OXOS */
  10904.     ccraw.c_iflag |= IGNPAR;
  10905. /*
  10906.   Note that for terminal sessions we disable Xon/Xoff flow control to allow
  10907.   the passage ^Q and ^S as data characters for EMACS, and to allow XMODEM
  10908.   transfers to work when C-Kermit is in the middle, etc.  Hardware flow
  10909.   control, if in use, is not affected.
  10910. */
  10911. #ifdef ATTSV
  10912. #ifdef BSD44
  10913.     ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IXON|IXANY|IXOFF
  10914.                         |INPCK|ISTRIP);
  10915. #else
  10916.     ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|IXON|IXANY|IXOFF
  10917.                         |INPCK|ISTRIP);
  10918. #endif /* BSD44 */
  10919. #else /* POSIX */
  10920.     ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IXON|IXOFF|INPCK|ISTRIP);
  10921. #endif /* ATTSV */
  10922.     ccraw.c_oflag &= ~OPOST;
  10923. #ifdef COMMENT
  10924. /*
  10925.   WHAT THE HECK WAS THIS FOR?
  10926.   The B9600 setting (obviously) prevents CONNECT from working at any
  10927.   speed other than 9600 when you are logged in to the 7300 on a serial
  10928.   line.  Maybe some of the other flags are necessary -- if so, put back
  10929.   the ones that are needed.  This code is supposed to work the same, no
  10930.   matter whether you are logged in to the 7300 on the real console device,
  10931.   or through a serial port.
  10932. */
  10933. #ifdef ATT7300
  10934.     ccraw.c_cflag = CLOCAL | B9600 | CS8 | CREAD | HUPCL;
  10935. #endif /* ATT7300 */
  10936. #endif /* COMMENT */
  10937.  
  10938. /*** Kermit used to put the console in 8-bit raw mode, but some users have
  10939.  *** pointed out that this should not be done, since some sites actually
  10940.  *** use terminals with parity settings on their Unix systems, and if we
  10941.  *** override the current settings and stop doing parity, then their terminals
  10942.  *** will display blotches for characters whose parity is wrong.  Therefore,
  10943.  *** the following two lines are commented out (Larry Afrin, Clemson U):
  10944.  ***
  10945.  ***   ccraw.c_cflag &= ~(PARENB|CSIZE);
  10946.  ***   ccraw.c_cflag |= (CS8|CREAD);
  10947.  ***
  10948.  *** Sys III/V sites that have trouble with this can restore these lines.
  10949.  ***/
  10950. #ifndef VINTR
  10951.     ccraw.c_cc[0] = 003;        /* Interrupt char is Ctrl-C */
  10952. #else
  10953.     ccraw.c_cc[VINTR] = 003;
  10954. #endif /* VINTR */
  10955. #ifndef VQUIT
  10956.     ccraw.c_cc[1] = escchr;        /* Escape during packet mode */
  10957. #else
  10958.     ccraw.c_cc[VQUIT] = escchr;
  10959. #endif /* VQUIT */
  10960. #ifndef VEOF
  10961.     ccraw.c_cc[4] = 1;
  10962. #else
  10963. #ifndef OXOS
  10964. #ifdef VMIN
  10965.     ccraw.c_cc[VMIN] = 1;
  10966. #endif /* VMIN */
  10967. #else /* OXOS */
  10968.     ccraw.c_min = 1;
  10969. #endif /* OXOS */
  10970. #endif /* VEOF */
  10971.  
  10972. #ifdef ZILOG
  10973.     ccraw.c_cc[5] = 0;
  10974. #else
  10975. #ifndef VEOL
  10976.     ccraw.c_cc[5] = 1;
  10977. #else
  10978. #ifndef OXOS
  10979. #ifdef VTIME
  10980.     ccraw.c_cc[VTIME] = 1;
  10981. #endif /* VTIME */
  10982. #else /* OXOS */
  10983.     ccraw.c_time = 1;
  10984. #endif /* OXOS */
  10985. #endif /* VEOL */
  10986. #endif /* ZILOG */
  10987.  
  10988. #ifdef BSD44ORPOSIX
  10989.     return(tcsetattr(0,TCSADRAIN,&ccraw));
  10990. #else
  10991.     return(ioctl(0,TCSETAW,&ccraw));    /* Set new modes. */
  10992. #endif /* BSD44ORPOSIX */
  10993.  
  10994. #else /* Berkeley, etc. */
  10995.     ccraw.sg_flags |= (RAW|TANDEM);     /* Set rawmode, XON/XOFF (ha) */
  10996.     ccraw.sg_flags &= ~(ECHO|CRMOD);    /* Set char wakeup, no echo */
  10997. #ifdef BELLV10
  10998.     return(ioctl(0,TIOCSETP,&ccraw));
  10999. #else
  11000.     return(stty(0,&ccraw));
  11001. #endif /* BELLV10 */
  11002. #endif /* SVORPOSIX */
  11003. #endif /* Plan9 */
  11004.  
  11005. #ifdef COHERENT
  11006. #undef SVORPOSIX
  11007. #endif /* COHERENT */
  11008.  
  11009. }
  11010.  
  11011.  
  11012. /*  C O N R E S  --  Restore the console terminal  */
  11013.  
  11014. int
  11015. conres() {
  11016.     debug(F101,"conres cgmf","",cgmf);
  11017.  
  11018.     if (cgmf < 1) return(0);        /* Do nothing if modes unchanged */
  11019.     if (!isatty(0)) return(0);          /* only for real ttys */
  11020.     debug(F100,"conres isatty ok","",0);
  11021.     ckxech = 0;                         /* System should echo chars */
  11022.  
  11023. #ifdef aegis
  11024.     conbufn = 0;
  11025.     if (concrp) return(write(1, "\035\001", 2));
  11026.     if (conuid == input_pad_$uid) {
  11027.     pad_$cooked(ios_$stdin, st);
  11028.     return(0);
  11029.     }
  11030. #endif /* aegis */
  11031.  
  11032. #ifdef Plan9
  11033.     p9conres();
  11034. #else
  11035. #ifdef BSD44ORPOSIX
  11036.     debug(F100,"conres restoring tcsetattr","",0);
  11037.     return(tcsetattr(0,TCSADRAIN,&ccold));
  11038. #else
  11039. #ifdef ATTSV
  11040.     debug(F100,"conres restoring ioctl","",0);
  11041.     return(ioctl(0,TCSETAW,&ccold));
  11042. #else /* BSD, V7, and friends */
  11043. #ifdef sony_news            /* Sony NEWS */
  11044.     if (km_con != -1)
  11045.       ioctl(0,TIOCKSET,&km_con);    /* Restore console Kanji mode */
  11046. #endif /* sony_news */
  11047.     msleep(100);
  11048.     debug(F100,"conres restoring stty","",0);
  11049. #ifdef BELLV10
  11050.     return(ioctl(0,TIOCSETP,&ccold));
  11051. #else
  11052.     return(stty(0,&ccold));
  11053. #endif /* BELLV10 */
  11054. #endif /* ATTSV */
  11055. #endif /* BSD44ORPOSIX */
  11056. #endif /* Plan9 */
  11057. }
  11058.  
  11059. /*  C O N O C  --  Output a character to the console terminal  */
  11060.  
  11061. int
  11062. #ifdef CK_ANSIC
  11063. conoc(char c)
  11064. #else
  11065. conoc(c) char c;
  11066. #endif /* CK_ANSIC */
  11067. /* conoc */ {
  11068.  
  11069. #ifdef IKSD
  11070.     if (inserver && !local)
  11071.       return(ttoc(c));
  11072.  
  11073. #ifdef CK_ENCRYPTION
  11074.     if (inserver && TELOPT_ME(TELOPT_ENCRYPTION))
  11075.         ck_tn_encrypt(&c,1);
  11076. #endif /* CK_ENCRYPTION */
  11077. #endif /* IKSD */
  11078.  
  11079. #ifdef Plan9
  11080.     return conwrite(&c,1);
  11081. #else
  11082.     return(write(1,&c,1));
  11083. #endif /* Plan9 */
  11084. }
  11085.  
  11086. /*  C O N X O  --  Write x characters to the console terminal  */
  11087.  
  11088. int
  11089. conxo(x,s) int x; char *s; {
  11090.  
  11091. #ifdef IKSD
  11092.     if (inserver && !local)
  11093.       return(ttol((CHAR *)s,x));
  11094.  
  11095. #ifdef CK_ENCRYPTION
  11096.     if (inserver && TELOPT_ME(TELOPT_ENCRYPTION))
  11097.         ck_tn_encrypt(s,x);
  11098. #endif /* CK_ENCRYPTION */
  11099. #endif /* IKSD */
  11100.  
  11101. #ifdef Plan9
  11102.     return(conwrite(s,x));
  11103. #else
  11104.     return(write(1,s,x));
  11105. #endif /* Plan9 */
  11106. }
  11107.  
  11108. /*  C O N O L  --  Write a line to the console terminal  */
  11109.  
  11110. int
  11111. conol(s) char *s; {
  11112.     int len;
  11113.     if (!s) s = "";            /* Always do this! */
  11114.     len = strlen(s);
  11115.  
  11116. #ifdef IKSD
  11117.     if (inserver && !local)
  11118.       return(ttol((CHAR *)s,len));
  11119.  
  11120. #ifdef CK_ENCRYPTION
  11121.     if (inserver && TELOPT_ME(TELOPT_ENCRYPTION)) {
  11122.     if (nxpacket < len) {
  11123.         if (xpacket) {
  11124.         free(xpacket);
  11125.         xpacket = NULL;
  11126.         nxpacket = 0;
  11127.         }
  11128.         len = len > 10240 ? len : 10240;
  11129.         xpacket = (char *)malloc(len);
  11130.         if (!xpacket) {
  11131.         fprintf(stderr,"ttol malloc failure\n");
  11132.         return(-1);
  11133.         } else
  11134.           nxpacket = len;
  11135.     }
  11136.     memcpy(xpacket,s,len);
  11137.     s = xpacket;
  11138.     ck_tn_encrypt(s,len);
  11139.     }
  11140. #endif /* CK_ENCRYPTION */
  11141. #endif /* IKSD */
  11142.  
  11143. #ifdef Plan9
  11144.     return(conwrite(s,len));
  11145. #else
  11146.     return(write(1,s,len));
  11147. #endif /* Plan9 */
  11148. }
  11149.  
  11150. /*  C O N O L A  --  Write an array of lines to the console terminal */
  11151.  
  11152. int
  11153. conola(s) char *s[]; {
  11154.     char * p;
  11155.     int i, x;
  11156.  
  11157.  
  11158.     if (!s) return(0);
  11159.     for (i = 0; ; i++) {
  11160.     p = s[i];
  11161.     if (!p) p = "";            /* Let's not dump core shall we? */
  11162.     if (!*p)
  11163.       break;
  11164. #ifdef IKSD
  11165.     if (inserver && !local)
  11166.       x = ttol((CHAR *)p,(int)strlen(p));
  11167.     else
  11168. #endif /* IKSD */
  11169.       x = conol(p);
  11170.     if (x < 0)
  11171.       return(-1);
  11172.     }
  11173.     return(0);
  11174. }
  11175.  
  11176. /*  C O N O L L  --  Output a string followed by CRLF  */
  11177.  
  11178. int
  11179. conoll(s) char *s; {
  11180.     CHAR buf[3];
  11181.     buf[0] = '\r';
  11182.     buf[1] = '\n';
  11183.     buf[2] = '\0';
  11184.     if (!s) s = "";
  11185.  
  11186. #ifdef IKSD
  11187.     if (inserver && !local) {
  11188.     ttol((CHAR *)s,(int)strlen(s));
  11189.     return(ttol(buf,2));
  11190.     }
  11191. #endif /* IKSD */
  11192.  
  11193.     conol(s);
  11194. #ifdef IKSD
  11195. #ifdef CK_ENCRYPTION
  11196.     if (inserver && TELOPT_ME(TELOPT_ENCRYPTION))
  11197.       ck_tn_encrypt(buf,2);
  11198. #endif /* CK_ENCRYPTION */
  11199. #endif /* IKSD */
  11200.  
  11201. #ifdef Plan9
  11202.     return(conwrite(buf, 2));
  11203. #else
  11204.     return(write(1,buf,2));
  11205. #endif /* Plan9 */
  11206. }
  11207.  
  11208. /*  C O N C H K  --  Return how many characters available at console  */
  11209. /*
  11210.   We could also use select() here to cover a few more systems that are not
  11211.   covered by any of the following, e.g. HP-UX 9.0x on the model 800.
  11212. */
  11213. int
  11214. conchk() {
  11215.     static int contyp = 0;        /* +1 for isatty, -1 otherwise */
  11216.  
  11217.     if (contyp == 0)            /* This prevents unnecessary */
  11218.       contyp = (isatty(0) ? 1 : -1);    /* duplicated calls to isatty() */
  11219.     debug(F101,"conchk contyp","",contyp);
  11220.     if (backgrd || (contyp < 0))
  11221.       return(0);
  11222.  
  11223. #ifdef aegis
  11224.     if (conbufn > 0) return(conbufn);   /* use old count if nonzero */
  11225.  
  11226.     /* read in more characters */
  11227.     conbufn = ios_$get(ios_$stdin,
  11228.               ios_$cond_opt, conbuf, (long)sizeof(conbuf), st);
  11229.     if (st.all != status_$ok) conbufn = 0;
  11230.     conbufp = conbuf;
  11231.     return(conbufn);
  11232. #else
  11233. #ifdef IKSD
  11234.     if (inserver && !local)
  11235.       return(in_chk(1,ttyfd));
  11236.     else
  11237. #endif /* IKSD */
  11238.       return(in_chk(0,0));
  11239. #endif /* aegis */
  11240. }
  11241.  
  11242. /*  C O N I N C  --  Get a character from the console  */
  11243. /*
  11244.   Call with timo > 0 to do a timed read, timo == 0 to do an untimed blocking
  11245.   read.  Upon success, returns the character.  Upon failure, returns -1.
  11246.   A timed read that does not complete within the timeout period returns -2.
  11247. */
  11248. int
  11249. coninc(timo) int timo; {
  11250.     int n = 0; CHAR ch;
  11251.     int xx;
  11252.  
  11253.     errno = 0;                /* Clear this */
  11254. #ifdef IKSD
  11255.     if (inserver && !local) {
  11256.     xx = ttinc(timo);
  11257.     if (xx < 0)
  11258.       return(ttinctimo ? -2 : -1);
  11259.     else
  11260.       return(xx);
  11261.     }
  11262. #endif /* IKSD */
  11263.  
  11264. #ifdef aegis                /* Apollo Aegis only... */
  11265.     debug(F101,"coninc timo","",timo);
  11266.     fflush(stdout);
  11267.     if (conchk() > 0) {
  11268.     --conbufn;
  11269.     return((unsigned)(*conbufp++ & 0xff));
  11270.     }
  11271. #endif /* aegis */
  11272.  
  11273. #ifdef TTLEBUF
  11274.     if (
  11275. #ifdef IKSD
  11276.     inserver &&
  11277. #endif /* IKSD */
  11278.     !xlocal
  11279.     ) {
  11280.     if (ttpush >= 0) {
  11281.         debug(F111,"ttinc","ttpush",ttpush);
  11282.         ch = ttpush;
  11283.         ttpush = -1;
  11284.         return(ch);
  11285.     }
  11286.     if (le_data) {
  11287.         if (le_getchar(&ch) > 0) {
  11288.         debug(F111,"ttinc LocalEchoInBuf","ch",ch);
  11289.         return(ch);
  11290.         }
  11291.     }
  11292.     }
  11293. #endif /* TTLEBUF */
  11294.  
  11295.     if (timo <= 0) {            /* Untimed, blocking read. */
  11296.     while (1) {            /* Keep trying till we get one. */
  11297.         n = read(0, &ch, 1);    /* Read a character. */
  11298.         if (n == 0) continue;    /* Shouldn't happen. */
  11299.         if (n > 0) {        /* If read was successful, */
  11300. #ifdef IKSD
  11301. #ifdef CK_ENCRYPTION
  11302.                 debug(F100,"coninc decrypt 1","",0);
  11303.                 if (inserver && !local && TELOPT_U(TELOPT_ENCRYPTION))
  11304.           ck_tn_decrypt(&ch,1);
  11305. #endif /* CK_ENCRYPTION */
  11306. #endif /* IKSD */
  11307.         return((unsigned)(ch & 0xff)); /* return the character. */
  11308.             }
  11309.  
  11310. /* Come here if read() returned an error. */
  11311.  
  11312.         debug(F101, "coninc(0) errno","",errno); /* Log the error. */
  11313. #ifndef OXOS
  11314. #ifdef SVORPOSIX
  11315. #ifdef CIE                             /* CIE Regulus has no EINTR symbol? */
  11316. #ifndef EINTR
  11317. #define EINTR 4
  11318. #endif /* EINTR */
  11319. #endif /* CIE */
  11320. /*
  11321.   This routine is used for several different purposes.  In CONNECT mode, it is
  11322.   used to do an untimed, blocking read from the keyboard in the lower CONNECT
  11323.   fork.  During local-mode file transfer, it reads a character from the
  11324.   console to interrupt the file transfer (like A for a status report, X to
  11325.   cancel a file, etc).  Obviously, we don't want the reads in the latter case
  11326.   to be blocking, or the file transfer would stop until the user typed
  11327.   something.  Unfortunately, System V does not allow the console device input
  11328.   buffer to be sampled nondestructively (e.g. by conchk()), so a kludge is
  11329.   used instead.  During local-mode file transfer, the SIGQUIT signal is armed
  11330.   and trapped by esctrp(), and this routine pretends to have read the quit
  11331.   character from the keyboard normally.  But, kludge or no kludge, the read()
  11332.   issued by this command, under System V only, can fail if a signal -- ANY
  11333.   signal -- is caught while the read is pending.  This can occur not only when
  11334.   the user types the quit character, but also during telnet negotiations, when
  11335.   the lower CONNECT fork signals the upper one about an echoing mode change.
  11336.   When this happens, we have to post the read() again.  This is apparently not
  11337.   a problem in BSD-based UNIX versions.
  11338. */
  11339.         if (errno == EINTR)        /* Read interrupted. */
  11340.           if (conesc)  {        /* If by SIGQUIT, */
  11341.           conesc = 0;        /* the conesc variable is set, */
  11342.           return(escchr);    /* so return the escape character. */
  11343.          } else continue;        /* By other signal, try again. */
  11344. #else
  11345. /*
  11346.   This might be dangerous, but let's do this on non-System V versions too,
  11347.   since at least one SunOS 4.1.2 user complains of immediate disconnections
  11348.   upon first making a TELNET connection.
  11349. */
  11350.         if (errno == EINTR)        /* Read interrupted. */
  11351.           continue;
  11352. #endif /* SVORPOSIX */
  11353. #else /* OXOS */
  11354.         if (errno == EINTR)        /* Read interrupted. */
  11355.           continue;
  11356. #endif /* OXOS */
  11357.         return(-1);            /* Error */
  11358.     }
  11359.     }
  11360. #ifdef DEBUG
  11361.     if (deblog && timo <= 0) {
  11362.     debug(F100,"coninc timeout logic error","",0);
  11363.     timo = 1;
  11364.     }
  11365. #endif /* DEBUG */
  11366.  
  11367. /* Timed read... */
  11368.  
  11369.     saval = signal(SIGALRM,timerh);    /* Set up timeout handler. */
  11370.     xx = alarm(timo);            /* Set the alarm. */
  11371.     debug(F101,"coninc alarm set","",timo);
  11372.     if (
  11373. #ifdef CK_POSIX_SIG
  11374.     sigsetjmp(sjbuf,1)
  11375. #else
  11376.     setjmp(sjbuf)
  11377. #endif /* CK_POSIX_SIG */
  11378.     )                /* The read() timed out. */
  11379.       n = -2;                /* Code for timeout. */
  11380.     else
  11381.       n = read(0, &ch, 1);
  11382.     ttimoff();                /* Turn off timer */
  11383.     if (n > 0) {            /* Got character OK. */
  11384. #ifdef IKSD
  11385. #ifdef CK_ENCRYPTION
  11386.         debug(F100,"coninc decrypt 2","",0);
  11387.         if (inserver && !local && TELOPT_U(TELOPT_ENCRYPTION))
  11388.       ck_tn_decrypt(&ch,1);
  11389. #endif /* CK_ENCRYPTION */
  11390. #endif /* IKSD */
  11391.     return((unsigned)(ch & 0xff));    /* Return it. */
  11392.     }
  11393. /*
  11394.   read() returned an error.  Same deal as above, but without the loop.
  11395. */
  11396.     debug(F101, "coninc(timo) n","",n);
  11397.     debug(F101, "coninc(timo) errno","",errno);
  11398. #ifndef OXOS
  11399. #ifdef SVORPOSIX
  11400.     if (n == -1 && errno == EINTR && conesc != 0) {
  11401.     conesc = 0;
  11402.     return(escchr);            /* User entered escape character. */
  11403.     }
  11404. #endif /* SVORPOSIX */
  11405.     if (n == 0 && errno > 0) {        /* It's an error */
  11406.     return(-1);
  11407.     }
  11408. #endif /* ! OXOS */
  11409.     return(n);
  11410. }
  11411.  
  11412. /*  C O N G K S  --  Console Get Keyboard Scancode  */
  11413.  
  11414. #ifndef congks
  11415. /*
  11416.   This function needs to be filled in with the various system-dependent
  11417.   system calls used by SUNOS, NeXT OS, Xenix, Aviion, etc, to read a full
  11418.   keyboard scan code.  For now, it's a dummy.
  11419. */
  11420. int
  11421. congks(timo) int timo; {
  11422.  
  11423. #ifdef IKSD
  11424.     if (inserver && !local)
  11425.       return(ttinc(timo));
  11426. #endif /* IKSD */
  11427.  
  11428.     return(coninc(timo));
  11429. }
  11430. #endif /* congks */
  11431.  
  11432. #ifdef ATT7300
  11433.  
  11434. /*  A T T D I A L  --  Dial up the remote system using internal modem
  11435.  * Purpose: to open and dial a number on the internal modem available on the
  11436.  * ATT7300 UNIX PC.  Written by Joe Doupnik. Superceeds version written by
  11437.  * Richard E. Hill, Dickinson, TX. which employed dial(3c).
  11438.  * Uses information in <sys/phone.h> and our status int attmodem.
  11439.  */
  11440. attdial(ttname,speed,telnbr) char *ttname,*telnbr; long speed; {
  11441.     char *telnum;
  11442.  
  11443.     attmodem &= ~ISMODEM;                       /* modem not in use yet */
  11444.                     /* Ensure O_NDELAY is set, else i/o traffic hangs */
  11445.                     /* We turn this flag off once the dial is complete */
  11446.     fcntl(ttyfd, F_SETFL, fcntl(ttyfd, F_GETFL, 0) | O_NDELAY);
  11447.  
  11448.     /* Condition line, check availability & DATA mode, turn on speaker */
  11449.     if (ioctl(ttyfd,PIOCOFFHOOK, &dialer) == -1) {
  11450.         printf("cannot access phone\n");
  11451.         ttclos(0);
  11452.         return (-2);
  11453.     }
  11454.     ioctl(ttyfd,PIOCGETP,&dialer);      /* get phone dialer parameters */
  11455.  
  11456.     if (dialer.c_lineparam & VOICE) {    /* phone must be in DATA mode */
  11457.         printf(" Should not dial with modem in VOICE mode.\n");
  11458.         printf(" Exit Kermit, switch to DATA and retry call.\n");
  11459.         ttclos(0);
  11460.         return (-2);
  11461.     }
  11462. #ifdef ATTTONED                /* Old way, tone dialing only. */
  11463.     dialer.c_lineparam = DATA | DTMF;    /* Dial with tones, */
  11464.     dialer.c_lineparam &= ~PULSE;    /* not with pulses. */
  11465. #else
  11466.     /* Leave current pulse/tone state alone. */
  11467.     /* But what about DATA?  Add it back if you have trouble. */
  11468.     /* sys/phone says you get DATA automatically by opening device RDWR */
  11469. #endif
  11470.     dialer.c_waitdialtone = 5;                  /* wait 5 sec for dialtone */
  11471. #ifdef COMMENT
  11472.     dialer.c_feedback = SPEAKERON|NORMSPK|RINGON;  /* control speaker */
  11473. #else
  11474.     /* sys/phone says RINGON used only for incoming voice calls */
  11475.     dialer.c_feedback &= ~(SOFTSPK|LOUDSPK);
  11476.     dialer.c_feedback |= SPEAKERON|NORMSPK;
  11477. #endif
  11478.     dialer.c_waitflash = 500;                   /* 0.5 sec flash hook */
  11479.     if(ioctl(ttyfd,PIOCSETP,&dialer) == -1) {   /* set phone parameters */
  11480.         printf("Cannot set modem characteristics\n");
  11481.         ttclos(0);
  11482.         return (-2);
  11483.     }
  11484.     ioctl(ttyfd,PIOCRECONN,0);        /* Turns on speaker for pulse */
  11485.  
  11486. #ifdef COMMENT
  11487.     fprintf(stderr,"Phone line status. line_par:%o dialtone_wait:%o \
  11488. line_status:%o feedback:%o\n",
  11489.     dialer.c_lineparam, dialer.c_waitdialtone,
  11490.     dialer.c_linestatus, dialer.c_feedback);
  11491. #endif
  11492.  
  11493.     attmodem |= ISMODEM;                        /* modem is now in-use */
  11494.     sleep(1);
  11495.     for (telnum = telnbr; *telnum != '\0'; telnum++)    /* dial number */
  11496. #ifdef ATTTONED
  11497.       /* Tone dialing only */
  11498.       if (ioctl(ttyfd,PIOCDIAL,telnum) != 0) {
  11499.       perror("Error in dialing");
  11500.       ttclos(0);
  11501.       return(-2);
  11502.       }
  11503. #else /* Allow Pulse or Tone dialing */
  11504.     switch (*telnum) {
  11505.       case 't': case 'T': case '%':    /* Tone dialing requested */
  11506.     dialer.c_lineparam |= DTMF;
  11507.     dialer.c_lineparam &= ~PULSE;
  11508.     if (ioctl(ttyfd,PIOCSETP,&dialer) == -1) {
  11509.         printf("Cannot set modem to tone dialing\n");
  11510.         ttclos(0);
  11511.         return(-2);
  11512.     }
  11513.     break;
  11514.       case 'd': case 'D': case 'p': case 'P': case '^':
  11515.     dialer.c_lineparam |= PULSE;
  11516.     dialer.c_lineparam &= ~DTMF;
  11517.     if (ioctl(ttyfd,PIOCSETP,&dialer) == -1) {
  11518.         printf("Cannot set modem to pulse dialing\n");
  11519.         ttclos(0);
  11520.         return(-2);
  11521.     }
  11522.     break;
  11523.       default:
  11524.         if (ioctl(ttyfd,PIOCDIAL,telnum) != 0) {
  11525.         perror("Dialing error");
  11526.         ttclos(0);
  11527.         return(-2);
  11528.     }
  11529.     break;
  11530.     }
  11531. #endif
  11532.  
  11533.     ioctl(ttyfd,PIOCDIAL,"@");        /* terminator for data call */
  11534.     do {                /* wait for modems to Connect */
  11535.         if (ioctl(ttyfd,PIOCGETP,&dialer) != 0)    { /* get params */
  11536.         perror("Cannot get modems to connect");
  11537.         ttclos(0);
  11538.         return(-2);
  11539.     }
  11540.     } while ((dialer.c_linestatus & MODEMCONNECTED) == 0);
  11541.     /* Turn off O_NDELAY flag now. */
  11542.     fcntl(ttyfd, F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY);
  11543.     signal(SIGHUP, sighup);             /* hangup on loss of carrier */
  11544.     return(0);                          /* return success */
  11545. }
  11546.  
  11547. /*
  11548.   Offgetty, ongetty functions. These function get the 'getty(1m)' off
  11549.   and restore it to the indicated line.  Shell's return codes are:
  11550.     0: Can't do it.  Probably a user logged on.
  11551.     1: No need.  No getty on that line.
  11552.     2: Done, you should restore the getty when you're done.
  11553.   DOGETY System(3), however, returns them as 0, 256, 512, respectively.
  11554.   Thanks to Kevin O'Gorman, Anarm Software Systems.
  11555.  
  11556.    getoff.sh looks like:   geton.sh looks like:
  11557.      setgetty $1 0           setgetty $1 1
  11558.      err=$?                  exit $?
  11559.      sleep 2
  11560.      exit $err
  11561. */
  11562.  
  11563. /*  O F F G E T T Y  --  Turn off getty(1m) for the communications tty line
  11564.  * and get status so it can be restarted after the line is hung up.
  11565.  */
  11566. int
  11567. offgetty(ttname) char *ttname; {
  11568.     char temp[30];
  11569.     while (*ttname != '\0') ttname++;       /* seek terminator of path */
  11570.     ttname -= 3;                            /* get last 3 chars of name */
  11571.     sprintf(temp,"/usr/bin/getoff.sh %s",ttname);
  11572.     return(zsyscmd(temp));
  11573. }
  11574.  
  11575. /*  O N G E T T Y  --  Turn on getty(1m) for the communications tty line */
  11576.  
  11577. int
  11578. ongetty(ttname) char *ttname; {
  11579.     char temp[30];
  11580.     while (*ttname != '\0') ttname++;       /* comms tty path name */
  11581.     ttname -= 3;
  11582.     sprintf(temp,"/usr/bin/geton.sh %s",ttname);
  11583.     return(zsyscmd(temp));
  11584. }
  11585. #endif /* ATT7300 */
  11586.  
  11587. /*  T T S C A R R  --  Set ttcarr variable, controlling carrier handling.
  11588.  *
  11589.  *  0 = Off: Always ignore carrier. E.g. you can connect without carrier.
  11590.  *  1 = On: Heed carrier, except during dialing. Carrier loss gives disconnect.
  11591.  *  2 = Auto: For "modem direct": The same as "Off".
  11592.  *            For real modem types: Heed carrier during connect, but ignore
  11593.  *                it anytime else.  Compatible with pre-5A C-Kermit versions.
  11594.  *
  11595.  * As you can see, this setting does not affect dialing, which always ignores
  11596.  * carrier (unless there is some special exception for some modem type).  It
  11597.  * does affect ttopen() if it is set before ttopen() is used.  This setting
  11598.  * takes effect on the next call to ttopen()/ttpkt()/ttvt().  And they are
  11599.  * (or should be) always called before any communications is tried, which
  11600.  * means that, practically speaking, the effect is immediate.
  11601.  *
  11602.  * Of course, nothing of this applies to remote mode (xlocal = 0).
  11603.  *
  11604.  * Someone has yet to uncover how to manipulate the carrier in the BSD
  11605.  * environment (or any non-termio using environment).  Until that time, this
  11606.  * will simply be a no-op for BSD.
  11607.  *
  11608.  * Note that in previous versions, the carrier was most often left unchanged
  11609.  * in ttpkt()/ttvt() unless they were called with FLO_DIAL or FLO_DIAX.  This
  11610.  * has changed.  Now it is controlled by ttcarr in conjunction with these
  11611.  * modes.
  11612.  */
  11613. int
  11614. ttscarr(carrier) int carrier; {
  11615.     ttcarr = carrier;
  11616.     debug(F101, "ttscarr","",ttcarr);
  11617.     return(ttcarr);
  11618. }
  11619.  
  11620. /* C A R R C T L  --  Set tty modes for carrier treatment.
  11621.  *
  11622.  * Sets the appropriate bits in a termio or sgttyb struct for carrier control
  11623.  * (actually, there are no bits in sgttyb for that), or performs any other
  11624.  * operations needed to control this on the current system.  The function does
  11625.  * not do the actual TCSETA or stty, since often we want to set other bits too
  11626.  * first.  Don't call this function when xlocal is 0, or the tty is not opened.
  11627.  *
  11628.  * We don't know how to do anything like carrier control on non-ATTSV systems,
  11629.  * except, apparently, ultrix.  See above.  It is also known that this doesn't
  11630.  * have much effect on a Xenix system.  For Xenix, one should switch back and
  11631.  * forth between the upper and lower case device files.  Maybe later.
  11632.  * Presently, Xenix will stick to the mode it was opened with.
  11633.  *
  11634.  * carrier: 0 = ignore carrier, 1 = require carrier.
  11635.  * The current state is saved in curcarr, and checked to save labour.
  11636.  */
  11637. #ifdef SVORPOSIX
  11638. int
  11639. #ifdef BSD44ORPOSIX
  11640. carrctl(ttpar, carrier)    struct termios *ttpar; int carrier;
  11641. #else /* ATTSV */
  11642. carrctl(ttpar, carrier)    struct termio *ttpar; int carrier;
  11643. #endif /* BSD44ORPOSIX */
  11644. /* carrctl */ {
  11645.     debug(F101, "carrctl","",carrier);
  11646.     if (carrier)
  11647.       ttpar->c_cflag &= ~CLOCAL;
  11648.     else
  11649.       ttpar->c_cflag |= CLOCAL;
  11650.     return(0);
  11651. }
  11652. #else /* Berkeley, V7, et al... */
  11653. int
  11654. carrctl(ttpar, carrier) struct sgttyb *ttpar; int carrier; {
  11655.     debug(F101, "carrctl","",carrier);
  11656.     if (carrier == curcarr)
  11657.       return(0);
  11658.     curcarr = carrier;
  11659. #ifdef ultrix
  11660. #ifdef COMMENT
  11661. /*
  11662.   Old code from somebody at DEC that tends to get stuck, time out, etc.
  11663. */
  11664.     if (carrier) {
  11665.     ioctl(ttyfd, TIOCMODEM, &temp);
  11666.     ioctl(ttyfd, TIOCHPCL, 0);
  11667.     } else {
  11668.     /* (According to the manuals, TIOCNCAR should be preferred */
  11669.     /* over TIOCNMODEM...) */
  11670.     ioctl(ttyfd, TIOCNMODEM, &temp);
  11671.     }
  11672. #else
  11673. /*
  11674.   New code from Jamie Watson that, he says, eliminates the problems.
  11675. */
  11676.     if (carrier) {
  11677.     ioctl(ttyfd, TIOCCAR);
  11678.     ioctl(ttyfd, TIOCHPCL);
  11679.     } else {
  11680.     ioctl(ttyfd, TIOCNCAR);
  11681.     }
  11682. #endif /* COMMENT */
  11683. #endif /* ultrix */
  11684.     return(0);
  11685. }
  11686. #endif /* SVORPOSIX */
  11687.  
  11688.  
  11689. /*  T T G M D M  --  Get modem signals  */
  11690. /*
  11691.  Looks for RS-232 modem signals, and returns those that are on in as its
  11692.  return value, in a bit mask composed of the BM_xxx values defined in ckcdeb.h.
  11693.  Returns:
  11694.  -3 Not implemented
  11695.  -2 if the communication device does not have modem control (e.g. telnet)
  11696.  -1 on error.
  11697.  >= 0 on success, with a bit mask containing the modem signals that are on.
  11698. */
  11699.  
  11700. /*
  11701.   Define the symbol K_MDMCTL if we have Sys V R3 / 4.3 BSD style
  11702.   modem control, namely the TIOCMGET ioctl.
  11703. */
  11704.  
  11705. #ifdef BSD43
  11706. #define K_MDMCTL
  11707. #endif /* BSD43 */
  11708.  
  11709. #ifdef SUNOS4
  11710. #define K_MDMCTL
  11711. #endif /* SUNOS4 */
  11712.  
  11713. /*
  11714.   SCO OpenServer R5.0.4.  The TIOCMGET definition is hardwired in because it
  11715.   is skipped in termio.h when _POSIX_SOURCE is defined.  But _POSIX_SOURCE
  11716.   must be defined in order to get the high serial speeds that are new to
  11717.   5.0.4.  However, the regular SCO drivers do not implement TIOCMGET, so the
  11718.   ioctl() returns -1 with errno 22 (invalid function).  But third-party
  11719.   drivers, e.g. for Digiboard, do implement it, and so it should work on ports
  11720.   driven by those drivers.
  11721. */
  11722. #ifdef SCO_OSR504
  11723. #ifndef TIOCMGET
  11724. #define TIOCMGET (('t'<<8)|29)
  11725. #endif /* TIOCMGET */
  11726. #endif /* SCO_OSR504 */
  11727.  
  11728. #ifdef QNX
  11729. #define K_MDMCTL
  11730. #else
  11731. #ifdef TIOCMGET
  11732. #define K_MDMCTL
  11733. #endif /* TIOCMGET */
  11734. #endif /* QNX */
  11735. /*
  11736.   "A serial communication program that can't read modem signals
  11737.    is like a car without windows."
  11738. */
  11739. int
  11740. ttgmdm() {
  11741.  
  11742. #ifdef QNX
  11743. #include <sys/qioctl.h>
  11744.  
  11745.     unsigned long y, mdmbits[2] = { 0L, 0L };
  11746.     int z = 0;
  11747.  
  11748.     if (xlocal && ttyfd < 0)
  11749.       return(-1);
  11750.  
  11751. #ifdef NETCMD
  11752.     if (ttpipe) return(-2);
  11753. #endif /* NETCMD */
  11754. #ifdef NETPTY
  11755.     if (ttpty) return(-2);
  11756. #endif /* NETPTY */
  11757.  
  11758.     if (!qnx_ioctl(ttyfd, QCTL_DEV_CTL, &mdmbits[0], 8, &mdmbits[0], 4)) {
  11759.     y = mdmbits[0];
  11760.     if (y & 0x100000L) z |= BM_CTS;    /* Values from comment */
  11761.     if (y & 0x200000L) z |= BM_DSR;    /* in sys/qioctl.h */
  11762.     if (y & 0x800000L) z |= BM_DCD;
  11763.     if (y & 0x400000L) z |= BM_RNG;
  11764.     if (y & 0x000001L) z |= BM_DTR;
  11765.     if (y & 0x000002L) z |= BM_RTS;
  11766.     return(z);
  11767.     } else return(-1);
  11768. #else
  11769. #ifdef HPUX                /* HPUX has its own way */
  11770.     int x, z;
  11771.  
  11772. #ifdef HPUX10                /* Modem flag word */
  11773.     mflag y;                /* mflag typedef'd in <sys/modem.h> */
  11774. #else
  11775. #ifdef HPUX9
  11776.     mflag y;
  11777. #else
  11778. #ifdef HPUX8
  11779.     mflag y;
  11780. #else
  11781.     unsigned long y;            /* Not sure about pre-8.0... */
  11782. #endif /* HPUX8 */
  11783. #endif /* HPUX9 */
  11784. #endif /* HPUX10 */
  11785.  
  11786.     if (xlocal && ttyfd < 0)
  11787.       return(-1);
  11788.  
  11789.     if (netconn)            /* Network connection */
  11790.       return(-2);            /* No modem signals */
  11791.  
  11792. #ifdef NETCMD
  11793.     if (ttpipe) return(-2);
  11794. #endif /* NETCMD */
  11795. #ifdef NETPTY
  11796.     if (ttpty) return(-2);
  11797. #endif /* NETPTY */
  11798.  
  11799.     if (xlocal)                /* Get modem signals */
  11800.       x = ioctl(ttyfd,MCGETA,&y);
  11801.     else
  11802.       x = ioctl(0,MCGETA,&y);
  11803.     if (x < 0) return(-1);
  11804.     debug(F101,"ttgmdm","",y);
  11805.  
  11806.     z = 0;                /* Initialize return value */
  11807.  
  11808. /* Now set bits for each modem signal that is reported to be on. */
  11809.  
  11810. #ifdef MCTS
  11811.     /* Clear To Send */
  11812.     if (y & MCTS) z |= BM_CTS;
  11813. #endif
  11814. #ifdef MDSR
  11815.     /* Data Set Ready */
  11816.     if (y & MDSR) z |= BM_DSR;
  11817. #endif
  11818. #ifdef MDCD
  11819.     /* Carrier */
  11820.     if (y & MDCD) z |= BM_DCD;
  11821. #endif
  11822. #ifdef MRI
  11823.     /* Ring Indicate */
  11824.     if (y & MRI) z |= BM_RNG;
  11825. #endif
  11826. #ifdef MDTR
  11827.     /* Data Terminal Ready */
  11828.     if (y & MDTR) z |= BM_DTR;
  11829. #endif
  11830. #ifdef MRTS
  11831.     /* Request To Send */
  11832.     if (y & MRTS) z |= BM_RTS;
  11833. #endif
  11834.     return(z);
  11835.  
  11836. #else /* ! HPUX */
  11837.  
  11838. #ifdef K_MDMCTL
  11839. /*
  11840.   Note, TIOCMGET might already have been defined in <sys/ioctl.h> or elsewhere.
  11841.   If not, we try including <sys/ttycom.h> -- if this blows up then more ifdefs
  11842.   are needed.
  11843. */
  11844. #ifndef TIOCMGET
  11845. #include <sys/ttycom.h>
  11846. #endif /* TIOCMGET */
  11847.  
  11848.     int x, y, z;
  11849.  
  11850.     debug(F100,"ttgmdm K_MDMCTL defined","",0);
  11851.  
  11852.     if (netconn)            /* Network connection */
  11853.       return(-2);            /* No modem signals */
  11854.  
  11855. #ifdef NETCMD
  11856.     if (ttpipe) return(-2);
  11857. #endif /* NETCMD */
  11858. #ifdef NETPTY
  11859.     if (ttpty) return(-2);
  11860. #endif /* NETPTY */
  11861.  
  11862.     if (xlocal && ttyfd < 0)
  11863.       return(-1);
  11864.  
  11865.     if (xlocal)
  11866.       x = ioctl(ttyfd,TIOCMGET,&y);    /* Get modem signals. */
  11867.     else
  11868.       x = ioctl(0,TIOCMGET,&y);
  11869.     debug(F101,"ttgmdm TIOCMGET ioctl","",x);
  11870.     if (x < 0) {
  11871.     debug(F101,"ttgmdm errno","",errno);
  11872.     return(-1);
  11873.     }
  11874.     debug(F101,"ttgmdm bits","",y);
  11875.  
  11876.     z = 0;                /* Initialize return value. */
  11877. #ifdef TIOCM_CTS
  11878.     /* Clear To Send */
  11879.     if (y & TIOCM_CTS) z |= BM_CTS;
  11880. #endif
  11881. #ifdef TIOCM_DSR
  11882.     /* Data Set Ready */
  11883.     if (y & TIOCM_DSR) z |= BM_DSR;
  11884. #endif
  11885. #ifdef TIOCM_CAR
  11886.     /* Carrier */
  11887.     if (y & TIOCM_CAR) z |= BM_DCD;
  11888. #endif
  11889. #ifdef TIOCM_RNG
  11890.     /* Ring Indicate */
  11891.     if (y & TIOCM_RNG) z |= BM_RNG;
  11892. #endif
  11893. #ifdef TIOCM_DTR
  11894.     /* Data Terminal Ready */
  11895.     if (y & TIOCM_DTR) z |= BM_DTR;
  11896. #endif
  11897. #ifdef TIOCM_RTS
  11898.     /* Request To Send */
  11899.     if (y & TIOCM_RTS) z |= BM_RTS;
  11900. #endif
  11901.     return(z);
  11902.  
  11903. #else /* !K_MDMCTL catch-All */
  11904.  
  11905.     debug(F100,"ttgmdm K_MDMCTL not defined","",0);
  11906. #ifdef TIOCMGET
  11907.     debug(F100,"ttgmdm TIOCMGET defined","",0);
  11908. #else
  11909.     debug(F100,"ttgmdm TIOCMGET not defined","",0);
  11910. #endif /* TIOCMGET */
  11911. #ifdef _SVID3
  11912.     debug(F100,"ttgmdm _SVID3 defined","",0);
  11913. #else
  11914.     debug(F100,"ttgmdm _SVID3 not defined","",0);
  11915. #endif /* _SVID3 */
  11916.  
  11917.     if (netconn)            /* Network connection */
  11918.       return(-2);            /* No modem signals */
  11919.  
  11920. #ifdef NETCMD
  11921.     if (ttpipe) return(-2);
  11922. #endif /* NETCMD */
  11923. #ifdef NETPTY
  11924.     if (ttpty) return(-2);
  11925. #endif /* NETPTY */
  11926.  
  11927.     return(-3);                /* Sorry, I don't know how... */
  11928.  
  11929. #endif /* K_MDMCTL */
  11930. #endif /* HPUX */
  11931. #endif /* QNX */
  11932. }
  11933.  
  11934. /*  P S U S P E N D  --  Put this process in the background.  */
  11935.  
  11936. /*
  11937.   Call with flag nonzero if suspending is allowed, zero if not allowed.
  11938.   Returns 0 on apparent success, -1 on failure (flag was zero, or
  11939.   kill() returned an error code.
  11940. */
  11941. int
  11942. psuspend(flag) int flag; {
  11943.  
  11944. #ifdef RTU
  11945.     extern int rtu_bug;
  11946. #endif /* RTU */
  11947.  
  11948.     if (flag == 0) return(-1);
  11949.  
  11950. #ifdef NOJC
  11951.     return(-1);
  11952. #else
  11953. #ifdef SIGTSTP
  11954. /*
  11955.   The big question here is whether job control is *really* supported.
  11956.   There's no way Kermit can know for sure.  The fact that SIGTSTP is
  11957.   defined does not guarantee the Unix kernel supports it, and the fact
  11958.   that the Unix kernel supports it doesn't guarantee that the user's
  11959.   shell (or other process that invoked Kermit) supports it.
  11960. */
  11961. #ifdef RTU
  11962.     rtu_bug = 1;
  11963. #endif /* RTU */
  11964.     if (kill(0,SIGSTOP) < 0
  11965. #ifdef MIPS
  11966. /* Let's try this for MIPS too. */
  11967.     && kill(getpid(),SIGSTOP) < 0
  11968. #endif /* MIPS */
  11969.     ) {                /* If job control, suspend the job */
  11970.     perror("suspend");
  11971.     debug(F101,"psuspend error","",errno);
  11972.     return(-1);
  11973.     }
  11974.     debug(F100,"psuspend ok","",0);
  11975.     return(0);
  11976. #else
  11977.     return(-1);
  11978. #endif /* SIGTSTP */
  11979. #endif /* NOJC */
  11980. }
  11981.  
  11982. /*
  11983.   setuid package, by Kristoffer Eriksson, with contributions from Dean
  11984.   Long and fdc.
  11985. */
  11986.  
  11987. /* The following is for SCO when CK_ANSILIBS is defined... */
  11988. #ifdef M_UNIX
  11989. #ifdef CK_ANSILIBS
  11990. #ifndef NOGETID_PROTOS
  11991. #define NOGETID_PROTOS
  11992. #endif /* NOGETID_PROTOS */
  11993. #endif /* CK_ANSILIBS */
  11994. #endif /* M_UNIX */
  11995.  
  11996. #ifndef _POSIX_SOURCE
  11997. #ifndef SUNOS4
  11998. #ifndef NEXT
  11999. #ifndef PS2AIX10
  12000. #ifndef sequent
  12001. #ifndef HPUX9
  12002. #ifndef COHERENT
  12003. #ifndef NOGETID_PROTOS
  12004. extern UID_T getuid(), geteuid(), getreuid();
  12005. extern GID_T getgid(), getegid(), getregid();
  12006. #endif /* NOGETID_PROTOS */
  12007. #else
  12008. extern UID_T getreuid();
  12009. extern GID_T getregid();
  12010. #endif /* COHERENT */
  12011. #endif /* HPUX9 */
  12012. #endif /* sequent */
  12013. #endif /* PS2AIX10 */
  12014. #endif /* NEXT */
  12015. #endif /* SUNOS4 */
  12016. #endif /* _POSIX_SOURCE */
  12017.  
  12018. /*
  12019. Subject: Set-user-id
  12020. To: fdc@watsun.cc.columbia.edu (Frank da Cruz)
  12021. Date: Sat, 21 Apr 90 4:48:25 MES
  12022. From: Kristoffer Eriksson <ske@pkmab.se>
  12023.  
  12024. This is a set of functions to be used in programs that may be run set-user-id
  12025. and/or set-group-id. They handle both the case where the program is not run
  12026. with such privileges (nothing special happens then), and the case where one
  12027. or both of these set-id modes are used.  The program is made to run with the
  12028. user's real user and group ids most of the time, except for when more
  12029. privileges are needed.  Don't set-user-id to "root".
  12030.  
  12031. This works on System V and POSIX.  In BSD, it depends on the
  12032. "saved-set-user-id" feature.
  12033. */
  12034.  
  12035. #define UID_ROOT 0            /* Root user and group ids */
  12036. #define GID_ROOT 0
  12037.  
  12038. /*
  12039.   The following code defines the symbol SETEUID for UNIX systems based
  12040.   on BSD4.4 (either -Encumbered or -Lite).  This program will then use
  12041.   seteuid() and setegid() instead of setuid() and setgid(), which still
  12042.   don't allow arbitrary switching.  It also avoids setreuid() and
  12043.   setregid(), which are included in BSD4.4 for compatibility only, are
  12044.   insecure, and print warnings to stderr under at least one system (NetBSD
  12045.   1.0).  Note that POSIX systems should still use setuid() and setgid();
  12046.   the seteuid() and setegid() functions are BSD4.4 extensions to the
  12047.   POSIX model.  Mike Long <mike.long@analog.com>, 8/94.
  12048. */
  12049. #ifdef BSD44
  12050. #define SETEUID
  12051. #endif /* BSD44 */
  12052.  
  12053. /*
  12054.   The following construction automatically defines the symbol SETREUID for
  12055.   UNIX versions based on Berkeley Unix 4.2 and 4.3.  If this symbol is
  12056.   defined, then this program will use getreuid() and getregid() calls in
  12057.   preference to getuid() and getgid(), which in Berkeley-based Unixes do
  12058.   not allow arbitrary switching back and forth of real & effective uid.
  12059.   This construction also allows -DSETREUID to be put on the cc command line
  12060.   for any system that has and wants to use setre[ug]id().  It also prevents
  12061.   automatic definition of SETREUID if -DNOSETREU is included on the cc
  12062.   command line (or otherwise defined).
  12063. */
  12064. #ifdef FT18                /* None of this for Fortune. */
  12065. #define NOSETREU
  12066. #endif /* FT18 */
  12067.  
  12068. #ifdef ANYBSD
  12069. #ifndef BSD29
  12070. #ifndef BSD41
  12071. #ifndef SETREUID
  12072. #ifndef NOSETREU
  12073. #ifndef SETEUID
  12074. #define SETREUID
  12075. #endif /* SETEUID */
  12076. #endif /* NOSETREU */
  12077. #endif /* SETREUID */
  12078. #endif /* !BSD41 */
  12079. #endif /* !BSD29 */
  12080. #endif /* ANYBSD */
  12081.  
  12082. /* Variables for user and group IDs. */
  12083.  
  12084. static UID_T realuid = (UID_T) -1, privuid = (UID_T) -1;
  12085. static GID_T realgid = (GID_T) -1, privgid = (GID_T) -1;
  12086.  
  12087.  
  12088. /* P R I V _ I N I  --  Initialize privileges package  */
  12089.  
  12090. /* Called as early as possible in a set-uid or set-gid program to store the
  12091.  * set-to uid and/or gid and step down to the users real uid and gid. The
  12092.  * stored id's can be temporarily restored (allowed in System V) during
  12093.  * operations that require the privilege.  Most of the time, the program
  12094.  * should execute in unpriviliged state, to not impose any security threat.
  12095.  *
  12096.  * Note: Don't forget that access() always uses the real id:s to determine
  12097.  * file access, even with privileges restored.
  12098.  *
  12099.  * Returns an error mask, with error values or:ed together:
  12100.  *   1 if setuid() fails,
  12101.  *   2 if setgid() fails, and
  12102.  *   4 if the program is set-user-id to "root", which can't be handled.
  12103.  *
  12104.  * Only the return value 0 indicates real success. In case of failure,
  12105.  * those privileges that could be reduced have been, at least, but the
  12106.  * program should be aborted none-the-less.
  12107.  *
  12108.  * Also note that these functions do not expect the uid or gid to change
  12109.  * without their knowing. It may work if it is only done temporarily, but
  12110.  * you're on your own.
  12111.  */
  12112. int
  12113. priv_ini() {
  12114.     int err = 0;
  12115.  
  12116.     /* Save real ID:s. */
  12117.     realuid = getuid();
  12118.     realgid = getgid();
  12119.  
  12120.     /* Save current effective ID:s, those set to at program exec. */
  12121.     privuid = geteuid();
  12122.     privgid = getegid();
  12123.  
  12124.     /* If running set-uid, go down to real uid, otherwise remember that
  12125.      * no privileged uid is available.
  12126.      *
  12127.      * Exceptions:
  12128.      *
  12129.      * 1) If the real uid is already "root" and the set-uid uid (the
  12130.      * initial effective uid) is not "root", then we would have trouble
  12131.      * if we went "down" to "root" here, and then temporarily back to the
  12132.      * set-uid uid (not "root") and then again tried to become "root". I
  12133.      * think the "saved set-uid" is lost when changing uid from effective
  12134.      * uid "root", which changes all uid, not only the effective uid. But
  12135.      * in this situation, we can simply go to "root" and stay there all
  12136.      * the time. That should give sufficient privilege (understatement!),
  12137.      * and give the right uids for subprocesses.
  12138.      *
  12139.      * 2) If the set-uid (the initial effective uid) is "root", and we
  12140.      * change uid to the real uid, we can't change it back to "root" when
  12141.      * we need the privilege, for the same reason as in 1). Thus, we can't
  12142.      * handle programs that are set-user-id to "root" at all. The program
  12143.      * should be stopped.  Use some other uid.  "root" is probably too
  12144.      * privileged for such things, anyway. (The uid is reverted to the
  12145.      * real uid until termination.)
  12146.      *
  12147.      * These two exceptions have the effect that the "root" uid will never
  12148.      * be one of the two uids that are being switched between, which also
  12149.      * means we don't have to check for such cases in the switching
  12150.      * functions.
  12151.      *
  12152.      * Note that exception 1) is handled by these routines (by constantly
  12153.      * running with uid "root", while exception 2) is a serious error, and
  12154.      * is not provided for at all in the switching functions.
  12155.      */
  12156.     if (realuid == privuid)
  12157.     privuid = (UID_T) -1;        /* Not running set-user-id. */
  12158.  
  12159.     /* If running set-gid, go down to real gid, otherwise remember that
  12160.      * no privileged gid is available.
  12161.      *
  12162.      * There are no exception like there is for the user id, since there
  12163.      * is no group id that is privileged in the manner of uid "root".
  12164.      * There could be equivalent problems for group changing if the
  12165.      * program sometimes ran with uid "root" and sometimes not, but
  12166.      * that is already avoided as explained above.
  12167.      *
  12168.      * Thus we can expect always to be able to switch to the "saved set-
  12169.      * gid" when we want, and back to the real gid again. You may also
  12170.      * draw the conclusion that set-gid provides for fewer hassles than
  12171.      * set-uid.
  12172.      */
  12173.  
  12174.     if (realgid == privgid)        /* If not running set-user-id, */
  12175.       privgid = (GID_T) -1;        /*  remember it this way. */
  12176.  
  12177.     err = priv_off();            /* Turn off setuid privilege. */
  12178.  
  12179.     if (privuid == UID_ROOT)        /* If setuid to root, */
  12180.       err |= 4;                /* return this error. */
  12181.  
  12182.     if (realuid == UID_ROOT) {        /* If real id is root, */
  12183.     privuid = (UID_T) -1;        /* stay root at all times. */
  12184. #ifdef ATT7300
  12185.     /* If Kermit installed SUID uucp and user is running as root */
  12186.     err &= ~1;            /* System V R0 does not save UID */
  12187. #endif /* ATT7300 */
  12188.     }
  12189.     return(err);
  12190. }
  12191.  
  12192.  
  12193. /* Macros for hiding the differences in UID/GID setting between various Unix
  12194.  * systems. These macros should always be called with both the privileged ID
  12195.  * and the non-privileged ID. The one in the second argument, will become the
  12196.  * effective ID. The one in the first argument will be retained for later
  12197.  * retrieval.
  12198.  */
  12199. #ifdef SETREUID
  12200. #ifdef SAVEDUID
  12201. /* On BSD systems with the saved-UID feature, we just juggle the effective
  12202.  * UID back and forth, and leave the real UID at its true value.  The kernel
  12203.  * allows switching to both the current real UID, the effective UID, and the
  12204.  * UID which the program is set-UID to.  The saved set-UID always holds the
  12205.  * privileged UID for us, and the real UID will always be the non-privileged,
  12206.  * and we can freely choose one of them for the effective UID at any time.
  12207.  */
  12208. #define switchuid(hidden,active) setreuid( (UID_T) -1, active)
  12209. #define switchgid(hidden,active) setregid( (GID_T) -1, active)
  12210.  
  12211. #else   /* SETREUID,!SAVEDUID */
  12212.  
  12213. /* On systems with setreXid() but without the saved-UID feature, notably
  12214.  * BSD 4.2, we swap the real and effective UIDs each time.  It's
  12215.  * the effective UID that we are interested in, but we have to retain the
  12216.  * unused UID somewhere to enable us to restore it later, and we do this
  12217.  * in the real UID.  The kernel only allows switching to either the current
  12218.  * real or the effective UID, unless you're "root".
  12219.  */
  12220. #define switchuid(hidden,active)    setreuid(hidden,active)
  12221. #define switchgid(hidden,active)    setregid(hidden,active)
  12222. #endif
  12223.  
  12224. #else /* !SETREUID, !SAVEDUID */
  12225.  
  12226. #ifdef SETEUID
  12227. /*
  12228.   BSD 4.4 works similarly to System V and POSIX (see below), but uses
  12229.   seteXid() instead of setXid() to change effective IDs.  In addition, the
  12230.   seteXid() functions work the same for "root" as for other users.
  12231. */
  12232. #define switchuid(hidden,active)    seteuid(active)
  12233. #define switchgid(hidden,active)    setegid(active)
  12234.  
  12235. #else /* !SETEUID */
  12236.  
  12237. /* On System V and POSIX, the only thing we can change is the effective UID
  12238.  * (unless the current effective UID is "root", but initsuid() avoids that for
  12239.  * us).  The kernel allows switching to the current real UID or to the saved
  12240.  * set-UID.  These are always set to the non-privileged UID and the privileged
  12241.  * UID, respectively, and we only change the effective UID.  This breaks if
  12242.  * the current effective UID is "root", though, because for "root" setuid/gid
  12243.  * becomes more powerful, which is why initsuid() treats "root" specially.
  12244.  * Note: That special treatment maybe could be ignored for BSD?  Note: For
  12245.  * systems that don't fit any of these four cases, we simply can't support
  12246.  * set-UID.
  12247.  */
  12248. #define switchuid(hidden,active)    setuid(active)
  12249. #define switchgid(hidden,active)    setgid(active)
  12250.  
  12251. #endif /* SETEUID */
  12252. #endif /* SETREUID */
  12253.  
  12254.  
  12255. /* P R I V _ O N  --  Turn on the setuid and/or setgid */
  12256.  
  12257. /* Go to the privileged uid (gid) that the program is set-user-id
  12258.  * (set-group-id) to, unless the program is running unprivileged.
  12259.  * If setuid() fails, return value will be 1. If getuid() fails it
  12260.  * will be 2.  Return immediately after first failure, and the function
  12261.  * tries to restore any partial work done.  Returns 0 on success.
  12262.  * Group id is changed first, since it is less serious than user id.
  12263.  */
  12264. int
  12265. priv_on() {
  12266.     if (privgid != (GID_T) -1)
  12267.       if (switchgid(realgid,privgid))
  12268.         return(2);
  12269.  
  12270.     if (privuid != (UID_T) -1)
  12271.       if (switchuid(realuid,privuid)) {
  12272.       if (privgid != (GID_T) -1)
  12273.         switchgid(privgid,realgid);
  12274.       return(1);
  12275.       }
  12276.     return(0);
  12277. }
  12278.  
  12279. /* P R I V _ O F F  --  Turn on the real uid and gid */
  12280.  
  12281. /* Return to the unprivileged uid (gid) after an temporary visit to
  12282.  * privileged status, unless the program is running without set-user-id
  12283.  * (set-group-id). Returns 1 for failure in setuid() and 2 for failure
  12284.  * in setgid() or:ed together. The functions tries to return both uid
  12285.  * and gid to unprivileged state, regardless of errors. Returns 0 on
  12286.  * success.
  12287.  */
  12288. int
  12289. priv_off() {
  12290.     int err = 0;
  12291.  
  12292.     if (privuid != (UID_T) -1)
  12293.        if (switchuid(privuid,realuid))
  12294.       err |= 1;
  12295.  
  12296.     if (privgid != (GID_T) -1)
  12297.        if (switchgid(privgid,realgid))
  12298.     err |= 2;
  12299.  
  12300.     return(err);
  12301. }
  12302.  
  12303. /* Turn off privilege permanently.  No going back.  This is necessary before
  12304.  * a fork() on BSD43 machines that don't save the setUID or setGID, because
  12305.  * we swap the real and effective ids, and we don't want to let the forked
  12306.  * process swap them again and get the privilege back. It will work on other
  12307.  * machines too, such that you can rely on its effect always being the same,
  12308.  * for instance, even when you're in priv_on() state when this is called.
  12309.  * (Well, that part about "permanent" is on System V only true if you follow
  12310.  * this with a call to exec(), but that's what we want it for anyway.)
  12311.  * Added by Dean Long -- dlong@midgard.ucsc.edu
  12312.  */
  12313. int
  12314. priv_can() {
  12315.  
  12316. #ifdef SETREUID
  12317.     int err = 0;
  12318.     if (privuid != (UID_T) -1)
  12319.        if (setreuid(realuid,realuid))
  12320.       err |= 1;
  12321.  
  12322.     if (privgid != (GID_T) -1)
  12323.         if (setregid(realgid,realgid))
  12324.        err |= 2;
  12325.  
  12326.     return(err);
  12327.  
  12328. #else
  12329. #ifdef SETEUID
  12330.     int err = 0;
  12331.     if (privuid != (UID_T) -1)
  12332.     if (setuid(realuid)) {
  12333.         debug(F101,"setuid failed","",errno);
  12334.         err |= 1;
  12335.         debug(F101,"ruid","",getuid());
  12336.         debug(F101,"euid","",geteuid());
  12337.     }
  12338.     debug(F101,"setuid","",realuid);
  12339.     if (privgid != (GID_T) -1)
  12340.         if (setgid(realgid)) {
  12341.         debug(F101,"setgid failed","",errno);
  12342.         err |= 2;
  12343.         debug(F101,"rgid","",getgid());
  12344.         debug(F101,"egid","",getegid());
  12345.     }
  12346.     debug(F101,"setgid","",realgid);
  12347.     return(err);
  12348. #else
  12349.     /* Easy way of using setuid()/setgid() instead of setreuid()/setregid().*/
  12350.     return(priv_off());
  12351. #endif /* SETEUID */
  12352. #endif /* SETREUID */
  12353. }
  12354.  
  12355. /* P R I V _ O P N  --  For opening protected files or devices. */
  12356.  
  12357. int
  12358. priv_opn(name, modes) char *name; int modes; {
  12359.     int x;
  12360.     priv_on();                /* Turn privileges on */
  12361.     x = open(name, modes);        /* Try to open the device */
  12362.     priv_off();                /* Turn privileges off */
  12363.     return(x);                /* Return open's return code */
  12364. }
  12365.  
  12366. /*  P R I V _ C H K  --  Check privileges.  */
  12367.  
  12368. /*  Try to turn them off.  If turning them off did not succeed, cancel them */
  12369.  
  12370. int
  12371. priv_chk() {
  12372.     int x, y = 0;
  12373.     x = priv_off();            /* Turn off privs. */
  12374.     if (x != 0 || getuid() == privuid || geteuid() == privuid)
  12375.       y = priv_can();
  12376.     if (x != 0 || getgid() == privgid || getegid() == privgid)
  12377.       y = y | priv_can();
  12378.     return(y);
  12379. }
  12380.  
  12381. UID_T
  12382. real_uid() {
  12383.     return(realuid);
  12384. }
  12385.  
  12386. VOID
  12387. ttimoff() {                /* Turn off any timer interrupts */
  12388.     /* int xx; */
  12389. /*
  12390.   As of 5A(183), we set SIGALRM to SIG_IGN (to ignore alarms) rather than to
  12391.   SIG_DFL (to catch alarms, or if there is no handler, to exit).  This is to
  12392.   cure (mask, really) a deeper problem with stray alarms that occurs on some
  12393.   systems, possibly having to do with sleep(), that caused core dumps.  It
  12394.   should be OK to do this, because no code in this module uses nested alarms.
  12395.   (But we still have to watch out for SCRIPT and DIAL...)
  12396. */
  12397.     /* xx = */ alarm(0);
  12398.     /* debug(F101,"ttimoff alarm","",xx); */
  12399.     if (saval) {            /* Restore any previous */
  12400.     signal(SIGALRM,saval);        /* alarm handler. */
  12401.     /* debug(F101,"ttimoff alarm restoring saval","",saval); */
  12402.     saval = NULL;
  12403.     } else {
  12404.     signal(SIGALRM,SIG_IGN);    /* Used to be SIG_DFL */
  12405.     /* debug(F100,"ttimoff alarm SIG_IGN","",0); */
  12406.     }
  12407. }
  12408.  
  12409. #ifdef CK_REDIR
  12410. #ifdef COMMENT
  12411. /* Old way - not portable */
  12412. int
  12413. ttruncmd(s) char *s; {
  12414.     int r = 0;                /* Return code */
  12415.                     /* 0 = failure, 1 = success */
  12416. #ifdef WIFEXITED
  12417. #ifndef WEXITSTATUS
  12418. #ifdef w_retcode
  12419. #define WEXITSTATUS(x) ((x).w_retcode)
  12420. #endif /* w_retcode */
  12421. #endif /* WEXITSTATUS */
  12422. #ifdef WEXITSTATUS
  12423. #define CK_FUN_OK
  12424. #endif /* WEXITSTATUS */
  12425. #endif /* WIFEXITED */
  12426. #ifdef NEXT
  12427. #define waitpid(pid,status,option) wait4((pid),(status),(option),NULL)
  12428. #else
  12429. #ifdef sony_news
  12430. #define waitpid(pid,status,option) wait4((pid),(status),(option),NULL)
  12431. #endif /* sony_news */
  12432. #endif /* NEXT */
  12433.  
  12434. #ifdef CK_FUN_OK
  12435.     PID_T pid;
  12436.  
  12437.     if (ttyfd == -1) {
  12438.     printf("?Sorry, device is not open\n");
  12439.     return(0);
  12440.     }
  12441.     if (nopush) {
  12442.     debug(F100,"ttruncmd fail: nopush","",0);
  12443.     return(0);
  12444.     }
  12445.     conres();                /* Make console normal  */
  12446.     if ((pid = fork()) == 0) {        /* Make a child fork */
  12447.     /* give it stdin,out to the line */
  12448.     if (priv_can())            /* Turn off privs. */
  12449.       exit(1);
  12450.     dup2(ttyfd, 0);
  12451.     dup2(ttyfd, 1);
  12452.     _exit(system(s) ? BAD_EXIT : 0);
  12453.     } else {
  12454.     WAIT_T status;            /* This is int for all but NeXT */
  12455.     SIGTYP (*istat)(), (*qstat)();
  12456.  
  12457.     if (pid == (PID_T) -1)        /* fork() failed? */
  12458.       return(0);
  12459.     istat = signal(SIGINT,SIG_IGN); /* Let the fork handle keyboard */
  12460.     qstat = signal(SIGQUIT,SIG_IGN); /* interrupts itself... */
  12461.  
  12462.     if (waitpid(pid, &status, 0) != pid) {
  12463.         printf("?Can't wait for child process?\r\n");
  12464.     } else {
  12465.         if (WIFEXITED(status)) {
  12466.         if (WEXITSTATUS(status)) {
  12467.             printf("?Command exit status: %d\r\n",
  12468.                WEXITSTATUS(status));
  12469.         } else r = 1;
  12470.         } else {
  12471.         printf("?Command did not exit - cancelling it now.\r\n");
  12472.         kill(pid, SIGKILL);
  12473.         }
  12474.     }
  12475.     signal(SIGINT,istat);        /* Restore interrupts */
  12476.     signal(SIGQUIT,qstat);
  12477.     }
  12478.     concb((char)escchr);        /* Restore console to CBREAK mode */
  12479. #else
  12480.     printf("?Sorry, can't execute this command - pieces missing.\n");
  12481. #endif /* CK_FUN_OK */
  12482.     return(r);
  12483. }
  12484. #else
  12485. int
  12486. ttruncmd(s) char *s; {
  12487.     PID_T pid;                /* pid of lower fork */
  12488.     int wstat;                /* for wait() */
  12489.     int x;
  12490. #ifdef OSF40
  12491. /*
  12492.   This is to shut up warnings from DECC - if it causes trouble, just remove
  12493.   it, since the warnings don't seem to affect correct operation at runtime.
  12494. */
  12495.     union wait statusp_w;
  12496.     int statusp;
  12497. #else
  12498.     int statusp;
  12499. #endif /* OSF40 */
  12500.  
  12501.     if (ttyfd == -1) {
  12502.     printf("?Sorry, device is not open\n");
  12503.     return(0);
  12504.     }
  12505.     if (nopush) {
  12506.     debug(F100,"ttruncmd fail: nopush","",0);
  12507.     return(0);
  12508.     }
  12509.     conres();                /* Make console normal  */
  12510.     pexitstat = -4;
  12511.     if ((pid = fork()) == 0) {        /* Make a child fork */
  12512.     if (priv_can())            /* Child: turn off privs. */
  12513.       exit(1);
  12514.     dup2(ttyfd, 0);            /* Give stdin/out to the line */
  12515.     dup2(ttyfd, 1);
  12516.     x = system(s);
  12517.     debug(F101,"ttruncmd system",s,x);
  12518.     _exit(x ? BAD_EXIT : 0);
  12519.     } else {
  12520.     SIGTYP (*istat)(), (*qstat)();
  12521.     if (pid == (PID_T) -1)        /* fork() failed? */
  12522.       return(0);
  12523.     istat = signal(SIGINT,SIG_IGN); /* Let the fork handle keyboard */
  12524.     qstat = signal(SIGQUIT,SIG_IGN); /* interrupts itself... */
  12525.  
  12526. #ifdef COMMENT
  12527.         while (((wstat = wait(
  12528. #ifdef OSF40
  12529.                   &statusp_w
  12530. #else
  12531.                   &statusp
  12532. #endif /* OSF40 */
  12533.                   )) != pid)
  12534.            && (wstat != -1))
  12535.       ;
  12536. #else  /* Not COMMENT */
  12537.         while (1) {
  12538.         wstat = wait(
  12539. #ifdef OSF40
  12540.              &statusp_w
  12541. #else
  12542.              &statusp
  12543. #endif /* OSF40 */
  12544.              );
  12545.         debug(F101,"ttruncmd wait","",wstat);
  12546.         if (wstat == pid || wstat == -1)
  12547.           break;
  12548.     }
  12549. #endif /* COMMENT */
  12550.  
  12551. #ifdef OSF40
  12552.     statusp = (*(int *)&(statusp_w));
  12553. #endif /* OSF40 */
  12554.  
  12555.     pexitstat = (statusp & 0xff) ? statusp : statusp >> 8;
  12556.     debug(F101,"ttruncmd wait statusp","",statusp);
  12557.     debug(F101,"ttruncmd wait pexitstat","",pexitstat);
  12558.     signal(SIGINT,istat);        /* Restore interrupts */
  12559.     signal(SIGQUIT,qstat);
  12560.     }
  12561.     concb((char)escchr);        /* Restore console to CBREAK mode */
  12562.     return(statusp == 0 ? 1 : 0);
  12563. }
  12564. #endif /* COMMENT */
  12565. #endif /* CK_REDIR */
  12566.  
  12567. struct tm *
  12568. #ifdef CK_ANSIC
  12569. cmdate2tm(char * date, int gmt)         /* date as "yyyymmdd hh:mm:ss" */
  12570. #else
  12571. cmdate2tm(date,gmt) char * date; int gmt;
  12572. #endif
  12573. {
  12574.     /* date as "yyyymmdd hh:mm:ss" */
  12575.     static struct tm _tm;
  12576.     time_t now;
  12577.  
  12578.     if (strlen(date) != 17 ||
  12579.     date[8] != ' ' ||
  12580.     date[11] != ':' ||
  12581.     date[14] != ':')
  12582.       return(NULL);
  12583.  
  12584.     time(&now);
  12585.     if (gmt)
  12586.       _tm = *gmtime(&now);
  12587.     else
  12588.       _tm = *localtime(&now);
  12589.     _tm.tm_year = (date[0]-'0')*1000 + (date[1]-'0')*100 +
  12590.                   (date[2]-'0')*10   + (date[3]-'0')-1900;
  12591.     _tm.tm_mon  = (date[4]-'0')*10   + (date[5]-'0')-1;
  12592.     _tm.tm_mday = (date[6]-'0')*10   + (date[7]-'0');
  12593.     _tm.tm_hour = (date[9]-'0')*10   + (date[10]-'0');
  12594.     _tm.tm_min  = (date[12]-'0')*10  + (date[13]-'0');
  12595.     _tm.tm_sec  = (date[15]-'0')*10  + (date[16]-'0');
  12596.  
  12597.     _tm.tm_wday = 0;
  12598.     _tm.tm_yday = 0;
  12599.  
  12600.     return(&_tm);
  12601. }
  12602.  
  12603. #ifdef OXOS
  12604. #undef kill
  12605. #endif /* OXOS */
  12606.  
  12607. #ifdef OXOS
  12608. int
  12609. priv_kill(pid, sig) int pid, sig; {
  12610.     int    i;
  12611.  
  12612.     if (priv_on())
  12613.     debug(F100,"priv_kill priv_on failed","",0);
  12614.     i = kill(pid, sig);
  12615.     if (priv_off())
  12616.     debug(F100,"priv_kill priv_off failed","",0);
  12617.     return(i);
  12618. }
  12619. #endif /* OXOS */
  12620.  
  12621. #ifdef BEOSORBEBOX
  12622. /* #ifdef BE_DR_7 */
  12623. /*
  12624.   alarm() function not supplied with Be OS DR7 - this one contributed by
  12625.   Neal P. Murphy.
  12626. */
  12627.  
  12628. /*
  12629.   This should mimic the UNIX/POSIX alarm() function well enough, with the
  12630.   caveat that one's SIGALRM handler must call alarm_expired() to clean up vars
  12631.   and wait for the alarm thread to finish.
  12632. */
  12633. unsigned int
  12634. alarm(unsigned int seconds) {
  12635.     long time_left = 0;
  12636.  
  12637. /* If an alarm is active, turn it off, saving the unused time */
  12638.     if (alarm_thread != -1) {
  12639.         /* We'll be generous and count partial seconds as whole seconds. */
  12640.         time_left = alarm_struct.time -
  12641.       ((system_time() - time_started) / 1000000.0);
  12642.  
  12643.         /* Kill the alarm thread */
  12644.         kill_thread (alarm_thread);
  12645.  
  12646.         /* We need to clean up as though the alarm occured. */
  12647.         time_started = 0;
  12648.         alarm_struct.thread = -1;
  12649.         alarm_struct.time = 0;
  12650.         alarm_expired();
  12651.     }
  12652.  
  12653. /* Set a new alarm clock, if requested. */
  12654.     if (seconds > 0) {
  12655.         alarm_struct.thread = find_thread(NULL);
  12656.         alarm_struct.time = seconds;
  12657.         time_started = system_time();
  12658.         alarm_thread = spawn_thread (do_alarm,
  12659.                                      "alarm_thread",
  12660.                                      B_NORMAL_PRIORITY,
  12661.                                      (void *) &alarm_struct
  12662.                      );
  12663.         resume_thread (alarm_thread);
  12664.     }
  12665.  
  12666. /* Now return [unused time | 0] */
  12667.     return ((unsigned int) time_left);
  12668. }
  12669.  
  12670. /*
  12671.   This function is the departure from UNIX/POSIX alarm handling. In the case
  12672.   of Be's missing alarm() function, this stuff needs to be done in the SIGALRM
  12673.   handler. When Be implements alarm(), this function call can be eliminated
  12674.   from user's SIGALRM signal handlers.
  12675. */
  12676.  
  12677. void
  12678. alarm_expired(void) {
  12679.     long ret_val;
  12680.  
  12681.     if (alarm_thread != -1) {
  12682.         wait_for_thread (alarm_thread, &ret_val);
  12683.         alarm_thread = -1;
  12684.     }
  12685. }
  12686.  
  12687. /*
  12688.   This is the function that snoozes the requisite number of seconds and then
  12689.   SIGALRMs the calling thread. Note that kill() wants a pid_t arg, whilst Be
  12690.   uses thread_id; currently they are both typdef'ed as long, but I'll do the
  12691.   cast anyway. This function is run in a separate thread.
  12692. */
  12693.  
  12694. long
  12695. do_alarm (void *alarm_struct) {
  12696.     snooze ((double) ((struct ALARM_STRUCT *) alarm_struct)->time * 1000000.0);
  12697.     kill ((pid_t)((struct ALARM_STRUCT *) alarm_struct)->thread, SIGALRM);
  12698.     time_started = 0;
  12699.     ((struct ALARM_STRUCT *) alarm_struct)->thread = -1;
  12700.     ((struct ALARM_STRUCT *) alarm_struct)->time = 0;
  12701. }
  12702. /* #endif */ /* BE_DR_7 */
  12703. #endif /* BEOSORBEBOX */
  12704.  
  12705. #ifdef Plan9
  12706.  
  12707. int
  12708. p9ttyctl(char letter, int num, int param) {
  12709.     char cmd[20];
  12710.     int len;
  12711.  
  12712.     if (ttyctlfd < 0)
  12713.       return -1;
  12714.  
  12715.     cmd[0] = letter;
  12716.     if (num)
  12717.       len = sprintf(cmd + 1, "%d", param) + 1;
  12718.     else {
  12719.     cmd[1] = param;
  12720.     len = 2;
  12721.     }
  12722.     if (write(ttyctlfd, cmd, len) == len) {
  12723.     cmd[len] = 0;
  12724.     /* fprintf(stdout, "wrote '%s'\n", cmd); */
  12725.     return 0;
  12726.     }
  12727.     return -1;
  12728. }
  12729.  
  12730. int
  12731. p9ttyparity(char l) {
  12732.     return p9ttyctl('p', 0, l);
  12733. }
  12734.  
  12735. int
  12736. p9tthflow(int flow, int status) {
  12737.     return p9ttyctl('m', 1, status);
  12738. }
  12739.  
  12740. int
  12741. p9ttsspd(int cps) {
  12742.     if (p9ttyctl('b', 1, cps * 10) < 0)
  12743.       return -1;
  12744.     ttylastspeed = cps * 10;
  12745.     return 0;
  12746. }
  12747.  
  12748. int
  12749. p9openttyctl(char *ttname) {
  12750.     char name[100];
  12751.  
  12752.     if (ttyctlfd >= 0) {
  12753.     close(ttyctlfd);
  12754.     ttyctlfd = -1;
  12755.     ttylastspeed = -1;
  12756.     }
  12757.     sprintf(name, "%sctl", ttname);
  12758.     ttyctlfd = open(name, 1);
  12759.     return ttyctlfd;
  12760. }
  12761.  
  12762. int
  12763. p9concb() {
  12764.     if (consctlfd >= 0) {
  12765.     if (write(consctlfd, "rawon", 5) == 5)
  12766.       return 0;
  12767.     }
  12768.     return -1;
  12769. }
  12770.  
  12771. int
  12772. p9conbin() {
  12773.     return p9concb();
  12774. }
  12775.  
  12776. int
  12777. p9conres() {
  12778.     if (consctlfd >= 0) {
  12779.     if (write(consctlfd, "rawoff", 6) == 6)
  12780.       return 0;
  12781.     }
  12782.     return -1;
  12783. }
  12784.  
  12785. int
  12786. p9sndbrk(int msec) {
  12787.     if (ttyctlfd >= 0) {
  12788.     char cmd[20];
  12789.     int i = sprintf(cmd, "k%d", msec);
  12790.     if (write(ttyctlfd, cmd, i) == i)
  12791.       return 0;
  12792.     }
  12793.     return -1;
  12794. }
  12795.  
  12796. int
  12797. conwrite(char *buf, int n) {
  12798.     int x;
  12799.     static int length = 0;
  12800.     static int holdingcr = 0;
  12801.     int normal = 0;
  12802.     for (x = 0; x < n; x++) {
  12803.     char c = buf[x];
  12804.     if (c == 007) {
  12805.         if (normal) {
  12806.         write(1, buf + (x - normal), normal);
  12807.         length += normal;
  12808.         normal = 0;
  12809.         }
  12810.         /* write(noisefd, "1000 300", 8); */
  12811.         holdingcr = 0;
  12812.     } else if (c == '\r') {
  12813.         if (normal) {
  12814.         write(1, buf + (x - normal), normal);
  12815.         length += normal;
  12816.         normal = 0;
  12817.         }
  12818.         holdingcr = 1;
  12819.     } else if (c == '\n') {
  12820.         write(1, buf + (x - normal), normal + 1);
  12821.         normal = 0;
  12822.         length = 0;
  12823.         holdingcr = 0;
  12824.     } else if (c == '\b') {
  12825.         if (normal) {
  12826.         write(1, buf + (x - normal), normal);
  12827.         length += normal;
  12828.         normal = 0;
  12829.         }
  12830.         if (length) {
  12831.         write(1, &c, 1);
  12832.         length--;
  12833.         }
  12834.         holdingcr = 0;
  12835.     } else {
  12836.         if (holdingcr) {
  12837.         char b = '\b';
  12838.         while (length-- > 0)
  12839.           write(1, &b, 1);
  12840.         length = 0;    /* compiler bug */
  12841.         }
  12842.         holdingcr = 0;
  12843.         normal++;
  12844.     }
  12845.     }
  12846.     if (normal) {
  12847.     write(1, buf + (x - normal), normal);
  12848.     length += normal;
  12849.     }
  12850.     return n;
  12851. }
  12852.  
  12853. void
  12854. conprint(char *fmt, ...) {
  12855.     char buf[1000];
  12856.  
  12857.     va_list ap;
  12858.     int i;
  12859.  
  12860.     va_start(ap, fmt);
  12861.     i = vsprintf(buf, fmt, ap);
  12862.     conwrite(buf, i);
  12863. }
  12864. #endif /* Plan9 */
  12865.  
  12866. /* fprintf, printf, perror replacements... */
  12867.  
  12868. /* f p r i n t f */
  12869.  
  12870. #ifdef UNIX
  12871. #ifdef CK_ANSIC
  12872. #include <stdarg.h>
  12873. #else /* CK_ANSIC */
  12874. #include <varargs.h>
  12875. #endif /* CK_ANSIC */
  12876. static char str1[1024];
  12877. static char str2[1024];
  12878. #ifdef fprintf
  12879. #undef fprintf
  12880. int
  12881. #ifdef CK_ANSIC
  12882. ckxfprintf(FILE * file, const char * format, ...)
  12883. #else /* CK_ANSIC */
  12884. ckxfprintf(va_alist) va_dcl
  12885. #endif /* CK_ANSIC */
  12886. /* ckxfprintf */ {
  12887.     int i, j, len, got_cr;
  12888.     va_list args;
  12889.     int rc = 0;
  12890.  
  12891. #ifdef CK_ANSIC
  12892.     va_start(args, format);
  12893. #else /* CK_ANSIC */
  12894.     char * format;
  12895.     FILE * file;
  12896.     va_start(args);
  12897.     file = va_arg(args,FILE *);
  12898.     format = va_arg(args,char *);
  12899. #endif /* CK_ANSIC */
  12900.  
  12901.     if (!inserver || (file != stdout && file != stderr && file != stdin)) {
  12902.     rc = vfprintf(file,format,args);
  12903.     } else {
  12904.     unsigned int c;
  12905.         rc = vsprintf(str1, format, args);
  12906.         for (i = 0, j = 0, len = strlen(str1), got_cr = 0;
  12907.          i < len && j < 1022;
  12908.          i++, j++ ) {
  12909.         /* We can't use 255 as a case label because of signed chars */
  12910.         c = (unsigned)(str1[i] & 0xff);
  12911. #ifdef TNCODE
  12912.         if (c == 255) {
  12913.         if (got_cr && !TELOPT_ME(TELOPT_BINARY))
  12914.           str2[j++] = '\0';
  12915.         str2[j++] = IAC;
  12916.         str2[j] = IAC;
  12917.         got_cr = 0;
  12918.         } else
  12919. #endif /* TNCODE */
  12920.         switch (c) {
  12921.           case '\r':
  12922.                 if (got_cr
  12923. #ifdef TNCODE
  12924.             && !TELOPT_ME(TELOPT_BINARY)
  12925. #endif /* TNCODE */
  12926.             )
  12927.           str2[j++] = '\0';
  12928.                 str2[j] = str1[i];
  12929.                 got_cr = 1;
  12930.                 break;
  12931.           case '\n':
  12932.                 if (!got_cr)
  12933.           str2[j++] = '\r';
  12934.                 str2[j] = str1[i];
  12935.                 got_cr = 0;
  12936.                 break;
  12937.           default:
  12938.                 if (got_cr
  12939. #ifdef TNCODE
  12940.             && !TELOPT_ME(TELOPT_BINARY)
  12941. #endif /* TNCODE */
  12942.             )
  12943.           str2[j++] = '\0';
  12944.                 str2[j] = str1[i];
  12945.                 got_cr = 0;
  12946.             }
  12947.         }
  12948.         if (got_cr
  12949. #ifdef TNCODE
  12950.              && !TELOPT_ME(TELOPT_BINARY)
  12951. #endif /* TNCODE */
  12952.              )
  12953.             str2[j++] = '\0';
  12954. #ifdef CK_ENCRYPTION
  12955. #ifdef TNCODE
  12956.         if (TELOPT_ME(TELOPT_ENCRYPTION))
  12957.       ck_tn_encrypt(str2,j);
  12958. #endif /* TNCODE */
  12959. #endif /* CK_ENCRYPTION */
  12960. #ifdef CK_SSL
  12961.     if (inserver && ssl_active_flag) {
  12962.         /* Write using SSL */
  12963.         rc = SSL_write(ssl_con, str2, j);
  12964.         debug(F111,"ckxfprintf","SSL_write",rc);
  12965.     } else if (inserver && tls_active_flag) {
  12966.         /* Write using SSL */
  12967.         rc = SSL_write(tls_con, str2, j);
  12968.         debug(F111,"ckxfprintf","TLS_write",rc);
  12969.     } else
  12970. #endif /* CK_SSL */
  12971.         fwrite(str2,sizeof(char),j,stdout);
  12972.     }
  12973.     va_end(args);
  12974.     return(rc);
  12975. }
  12976. #endif /* fprintf */
  12977.  
  12978. /* p r i n t f */
  12979.  
  12980. #ifdef printf
  12981. #undef printf
  12982. int
  12983. #ifdef CK_ANSIC
  12984. ckxprintf(const char * format, ...)
  12985. #else /* CK_ANSIC */
  12986. ckxprintf(va_alist) va_dcl
  12987. #endif /* CK_ANSIC */
  12988. /* ckxprintf */ {
  12989.     int i, j, len, got_cr;
  12990.     va_list args;
  12991.     int rc = 0;
  12992.  
  12993. #ifdef CK_ANSIC
  12994.     va_start(args, format);
  12995. #else /* CK_ANSIC */
  12996.     char * format;
  12997.     va_start(args);
  12998.     format = va_arg(args,char *);
  12999. #endif /* CK_ANSIC */
  13000.  
  13001.     if (!inserver) {
  13002.     rc = vprintf(format, args);
  13003.     } else {
  13004.     unsigned int c;
  13005.         rc = vsprintf(str1, format, args);
  13006.         for (i = 0, j = 0, len = strlen(str1), got_cr=0;
  13007.          i < len && j < 1022;
  13008.          i++, j++ ) {
  13009.         c = (unsigned)(str1[i] & 0xff);
  13010. #ifdef TNCODE
  13011.         if (c == 255) {
  13012.         if (got_cr && !TELOPT_ME(TELOPT_BINARY))
  13013.           str2[j++] = '\0';
  13014.         str2[j++] = IAC;
  13015.         str2[j] = IAC;
  13016.         got_cr = 0;
  13017.         } else
  13018. #endif /* TNCODE */
  13019.         switch (c) {
  13020.           case '\r':
  13021.                 if (got_cr
  13022. #ifdef TNCODE
  13023.             && !TELOPT_ME(TELOPT_BINARY)
  13024. #endif /* TNCODE */
  13025.             )
  13026.           str2[j++] = '\0';
  13027.                 str2[j] = str1[i];
  13028.                 got_cr = 1;
  13029.                 break;
  13030.           case '\n':
  13031.                 if (!got_cr)
  13032.           str2[j++] = '\r';
  13033.                 str2[j] = str1[i];
  13034.                 got_cr = 0;
  13035.                 break;
  13036.           default:
  13037.                 if (got_cr
  13038. #ifdef TNCODE
  13039.             && !TELOPT_ME(TELOPT_BINARY)
  13040. #endif /* TNCODE */
  13041.             )
  13042.           str2[j++] = '\0';
  13043.                 str2[j] = str1[i];
  13044.                 got_cr = 0;
  13045.                 break;
  13046.         }
  13047.         }
  13048.         if (got_cr
  13049. #ifdef TNCODE
  13050.              && !TELOPT_ME(TELOPT_BINARY)
  13051. #endif /* TNCODE */
  13052.              )
  13053.             str2[j++] = '\0';
  13054. #ifdef CK_ENCRYPTION
  13055. #ifdef TNCODE
  13056.         if (TELOPT_ME(TELOPT_ENCRYPTION))
  13057.       ck_tn_encrypt(str2,j);
  13058. #endif /* TNCODE */
  13059. #endif /* CK_ENCRYPTION */
  13060. #ifdef CK_SSL
  13061.           if (inserver && ssl_active_flag) {
  13062.               /* Write using SSL */
  13063.               rc = SSL_write(ssl_con, str2, j);
  13064.               debug(F111,"ckxprintf","SSL_write",rc);
  13065.           } else if (inserver && tls_active_flag) {
  13066.               /* Write using SSL */
  13067.               rc = SSL_write(tls_con, str2, j);
  13068.               debug(F111,"ckxprintf","TLS_write",rc);
  13069.           } else
  13070. #endif /* CK_SSL */
  13071.         rc = fwrite(str2,sizeof(char),j,stdout);
  13072.     }
  13073.     va_end(args);
  13074.     return(rc);
  13075. }
  13076. #endif /* printf */
  13077.  
  13078. /*  p e r r o r  */
  13079.  
  13080. #ifdef perror
  13081. #undef perror
  13082. _PROTOTYP(char * ck_errstr,(VOID));
  13083. #ifdef NEXT
  13084. void
  13085. #else
  13086. #ifdef CK_SCOV5
  13087. void
  13088. #else
  13089. int
  13090. #endif /* CK_SCOV5 */
  13091. #endif /* NEXT */
  13092. #ifdef CK_ANSIC
  13093. ckxperror(const char * str)
  13094. #else /* CK_ANSIC */
  13095. ckxperror(str) char * str;
  13096. #endif /* CK_ANSIC */
  13097. /* ckxperror */ {
  13098.     char * errstr = ck_errstr();
  13099. #ifndef NEXT
  13100. #ifndef CK_SCOV5
  13101.     return
  13102. #endif /* CK_SCOV5 */
  13103. #endif /* NEXT */
  13104.       ckxprintf("%s%s %s\n",str,*errstr?":":"",errstr);
  13105. }
  13106. #endif /* perror */
  13107. #endif /* UNIX */
  13108.  
  13109. #ifdef MINIX2
  13110.  
  13111. /* Minix doesn't have a gettimeofday call. We fake one here using time(2) */
  13112.  
  13113. int
  13114. gettimeofday(struct timeval *tp, struct timezone *tzp) {
  13115.     tp->tv_usec = 0L;            /* Close enough for horseshoes */
  13116.     if(time(&(tp->tv_sec))==-1)
  13117.       return(-1);
  13118.     return(0);
  13119. }
  13120.  
  13121. /* Minix does not support symbolic links. We implement a version of
  13122.    readlink that always fails */
  13123.  
  13124. int
  13125. readlink(const char *path, void *buf, size_t bufsiz) {
  13126.     errno = ENOSYS;
  13127.     return(-1);
  13128. }
  13129. #endif /* MINIX2 */
  13130.