ckutio.c
上传用户:dufan58
上传日期:2007-01-05
资源大小:3407k
文件大小:361k
源码类别:

通讯/手机编程

开发平台:

Windows_Unix

  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. /*  C K U T I O  */
  11. /* C-Kermit interrupt, communications control and I/O functions for UNIX */
  12. /*
  13.   Author: Frank da Cruz (fdc@columbia.edu),
  14.   Columbia University Academic Information Systems, New York City.
  15.   Copyright (C) 1985, 2000,
  16.     Trustees of Columbia University in the City of New York.
  17.     All rights reserved.  See the C-Kermit COPYING.TXT file or the
  18.     copyright text in the ckcmai.c module for disclaimer and permissions.
  19. */
  20. /*
  21.   NOTE TO CONTRIBUTORS: This file, and all the other C-Kermit files, must be
  22.   compatible with C preprocessors that support only #ifdef, #else, #endif,
  23.   #define, and #undef.  Please do not use #if, logical operators, or other
  24.   preprocessor features in any of the portable C-Kermit modules.  You can,
  25.   of course, use these constructions in platform-specific modules when they
  26.   are supported by all compilers/preprocessors that could be used on that
  27.   platform.
  28. */
  29. extern int nettype; /* Defined in ckcmai.c */
  30. /* Includes */
  31. #include "ckcsym.h" /* This must go first   */
  32. #include "ckcdeb.h" /* This must go second  */
  33. #ifdef OSF13
  34. #ifdef CK_ANSIC
  35. #ifdef _NO_PROTO
  36. #undef _NO_PROTO
  37. #endif /* _NO_PROTO */
  38. #endif /* CK_ANSIC */
  39. #endif /* OSF13 */
  40. #include <errno.h> /* System error numbers */
  41. #ifdef __386BSD__
  42. #define ENOTCONN 57
  43. #else
  44. #ifdef __bsdi__
  45. #define ENOTCONN 57
  46. #else
  47. #ifdef __FreeBSD__
  48. #define ENOTCONN 57
  49. #endif /* __FreeBSD__ */
  50. #endif /* __bsdi__ */
  51. #endif /* __386BSD__ */
  52. #ifdef SCO_OSR504
  53. #define NBBY 8
  54. #endif /* SCO_OSR504 */
  55. #ifdef Plan9
  56. #define SELECT
  57. #include <sys/time.h>
  58. #include <select.h>
  59. #define FD_SETSIZE (3 * sizeof(long) * 8)
  60. static struct timeval tv;
  61. #endif /* Plan9 */
  62. #ifdef CLIX
  63. #include <sys/time.h>
  64. #endif /* CLIX */
  65. #include "ckcnet.h" /* Symbols for network types. */
  66. #ifdef CK_SSL
  67. #include "ck_ssl.h"
  68. #endif /* CK_SSL */
  69. /*
  70.   The directory-related includes are here because we need to test some
  71.   file-system-related symbols to find out which system we're being compiled
  72.   under.  For example, MAXNAMLEN is defined in BSD4.2 but not 4.1.
  73. */
  74. #ifdef SDIRENT /* Directory bits... */
  75. #define DIRENT
  76. #endif /* SDIRENT */
  77. #ifdef XNDIR
  78. #include <sys/ndir.h>
  79. #else /* !XNDIR */
  80. #ifdef NDIR
  81. #include <ndir.h>
  82. #else /* !NDIR, !XNDIR */
  83. #ifdef RTU
  84. #include "/usr/lib/ndir.h"
  85. #else /* !RTU, !NDIR, !XNDIR */
  86. #ifdef DIRENT
  87. #ifdef SDIRENT
  88. #include <sys/dirent.h>
  89. #else
  90. #include <dirent.h>
  91. #endif /* SDIRENT */
  92. #else /* !RTU, !NDIR, !XNDIR, !DIRENT, i.e. all others */
  93. #include <sys/dir.h>
  94. #endif /* DIRENT */
  95. #endif /* RTU */
  96. #endif /* NDIR */
  97. #endif /* XNDIR */
  98. #ifdef QNX
  99. #include <sys/dev.h>
  100. #endif /* QNX */
  101. #ifdef HPUX5
  102. #ifndef TCPSOCKET
  103. /* I don't know why this is needed here since we never reference bzero(). */
  104. /* But without it C-Kermit won't link in an HP-UX 5.xx non-TCP build. */
  105. void
  106. bzero(s,n) char *s; int n; {
  107.     extern char * memset();
  108.     memset(s,0,n);
  109. }
  110. #endif /* TCPSOCKET */
  111. #endif /* HPUX5 */
  112. /* Definition of HZ, used in msleep() */
  113. #ifdef MIPS
  114. #define HZ ( 1000 / CLOCK_TICK )
  115. #else
  116. #ifdef ATTSV
  117. #ifndef NAP
  118. #ifndef TRS16
  119. #include <sys/param.h>
  120. #else
  121. #define HZ ( 1000 / CLOCK_TICK )
  122. #endif /* TRS16 */
  123. #ifdef NAPHACK
  124. #define nap(x) (void)syscall(3112, (x))
  125. #define NAP
  126. #endif /* NAPHACK */
  127. #endif /* NAP */
  128. #endif /* ATTSV */
  129. #endif /* MIPS */
  130. #ifdef M_UNIX
  131. #undef NGROUPS_MAX /* Prevent multiple definition warnings */
  132. #endif /* M_UNIX */
  133. /*
  134.   NOTE: HP-UX 8.0 has a <sys/poll.h>, but there is no corresponding
  135.   library routine, so _poll comes up undefined at link time.
  136. */
  137. #ifdef CK_POLL
  138. #ifndef AIXRS /* IBM AIX needs special handling */
  139. #include <poll.h> /* "standard" (SVID) i/o multiplexing, etc */
  140. #else /* AIXRS */
  141. #ifdef SVR4 /* AIX 3.2 is like SVID... */
  142. #include <poll.h>
  143. #else /* But AIX 3.1 is not ... */
  144. #include <sys/poll.h> /* The include file is in include/sys */
  145. #define events reqevents /* And it does not map IBM-specific member */
  146. #define revents rtnevents /* names to the System V equivalents */
  147. #endif /* SVR4 */
  148. #endif /* AIXRS */
  149. #endif /* CK_POLL */
  150. #include <signal.h>                     /* Signals */
  151. /* For setjmp and longjmp */
  152. #ifndef ZILOG
  153. #include <setjmp.h>
  154. #else
  155. #include <setret.h>
  156. #endif /* ZILOG */
  157. /* Maximum length for the name of a tty device */
  158. #ifndef DEVNAMLEN
  159. #define DEVNAMLEN 32
  160. #endif /* DEVNAMLEN */
  161. #ifdef NETCONN
  162. #undef DEVNAMLEN
  163. #define DEVNAMLEN 256 /* Longer field for host:service */
  164. #endif  /* NETCONN */
  165. /*
  166.   The following test differentiates between 4.1 BSD and 4.2 & later.
  167.   If you have a 4.1BSD system with the DIRENT library, this test could
  168.   mistakenly diagnose 4.2BSD and then later enable the use of system calls
  169.   that aren't defined.  If indeed there are such systems, we can use some
  170.   other way of testing for 4.1BSD, or add yet another compile-time switch.
  171. */
  172. #ifdef BSD4
  173. #ifdef MAXNAMLEN
  174. #ifndef FT21 /* Except for Fortune. */
  175. #ifndef FT18
  176. #ifndef BELLV10 /* And Bell Labs Research UNIX V10 */
  177. #define BSD42
  178. #endif /* BELLV10 */
  179. #endif /* FT18 */
  180. #endif /* FT21 */
  181. #endif /* MAXNAMLEN */
  182. #endif /* BSD4 */
  183. /*
  184.   Minix 2.0 support added by Terry McConnell,
  185.   Syracuse University <tmc@barnyard.syr.edu>
  186.   No more sgtty interface, posix compliant.
  187. */
  188. #ifdef MINIX2
  189. #define _MINIX   /* Needed for some Minix header files */
  190. #undef MINIX     /* Old minix 1.0: used sgtty interface */
  191. #define BSD44ORPOSIX
  192. #define SVORPOSIX
  193. #define DCLTIMEVAL
  194. #define NOFILEH
  195. #include <sys/types.h>
  196. #include <sys/ioctl.h>
  197. #include <termios.h>
  198. #include <limits.h>
  199. #undef TIOCGETC    /* defined in sys/ioctl.h, but not really supported */
  200. #define TANDEM 0
  201. #endif /* MINIX2 */
  202. /*
  203.  MINIX 1.0 support added by Charles Hedrick,
  204.  Rutgers University <hedrick@aramis.rutgers.edu>.
  205.  MINIX also has V7 enabled.
  206. */
  207. #ifdef MINIX
  208. #define TANDEM 0
  209. #define MYREAD
  210. #define NOSYSIOCTLH
  211. #include <limits.h>
  212. #endif /* MINIX */
  213. #ifdef CK_REDIR /* <sys/wait.h> needed only for REDIRECT command. */
  214. /*
  215.   If anybody can figure out how to make this work with NeXTSTEP, be
  216.   my guest!  (NeXTBlah/NeXTBlah/bsd/sys/wait.h does not define WEXITSTATUS)
  217. */
  218. #ifndef CK_WAIT_H /* If wait.h not already included... */
  219. #include <sys/wait.h> /* Include it */
  220. #endif /* CK_WAIT_H */
  221. #endif /* CK_REDIR */
  222. #include "ckuver.h" /* Version herald */
  223. char *ckxsys = HERALD;
  224. #ifdef CK_UTSNAME
  225. #include <sys/utsname.h>
  226. #ifdef UW7
  227. #ifndef SYS_NMLN
  228. #define SYS_NMLN 257
  229. #endif /* NMLN */
  230. #endif /* UW7 */
  231. #ifdef HPUX9PLUS
  232. static int hpis800 = 0;
  233. #endif /* HPUX9PLUS */
  234. #ifdef SYS_NMLN
  235. #define CK_SYSNMLN SYS_NMLN
  236. #else
  237. #ifdef _SYS_NMLN
  238. #define CK_SYSNMLN _SYS_NMLN
  239. #else
  240. #ifdef UTSLEN
  241. #define CK_SYSNMLN UTSLEN
  242. #else
  243. #define CK_SYSNMLN 31
  244. #endif /* UTSLEN */
  245. #endif /* _SYS_NMLN */
  246. #endif /* SYS_NMLN */
  247. char unm_mch[CK_SYSNMLN+1] = { '', '' };
  248. char unm_mod[CK_SYSNMLN+1] = { '', '' };
  249. char unm_nam[CK_SYSNMLN+1] = { '', '' };
  250. char unm_rel[CK_SYSNMLN+1] = { '', '' };
  251. char unm_ver[CK_SYSNMLN+1] = { '', '' };
  252. #endif /* CK_UTSNAME */
  253. #ifdef CIE
  254. #include <stat.h> /* For chasing symlinks, etc. */
  255. #else
  256. #include <sys/stat.h>
  257. #endif /* CIE */
  258. /* UUCP lockfile material... */
  259. #ifndef NOUUCP
  260. #ifdef USETTYLOCK
  261. #ifdef USE_UU_LOCK
  262. #include <libutil.h>
  263. #endif /* USE_UU_LOCK */
  264. #else  /* USETTYLOCK */
  265. /* Name of UUCP tty device lockfile */
  266. #ifdef LINUXFSSTND
  267. #ifndef HDBUUCP
  268. #define HDBUUCP
  269. #endif /* HDBUUCP */
  270. #endif /* LINUXFSSTND */
  271. #ifdef ACUCNTRL
  272. #define LCKDIR
  273. #endif /* ACUCNTRL */
  274. /*
  275.   PIDSTRING means use ASCII string to represent pid in lockfile.
  276. */
  277. #ifndef PIDSTRING
  278. #ifdef HDBUUCP
  279. #define PIDSTRING
  280. #else
  281. #ifdef BSD44
  282. #define PIDSTRING
  283. #else
  284. #ifdef RTAIX
  285. #define PIDSTRING
  286. #else
  287. #ifdef AIXRS
  288. #define PIDSTRING
  289. #else
  290. #ifdef COHERENT
  291. #define PIDSTRING
  292. #endif /* COHERENT */
  293. #endif /* AIXRS */
  294. #endif /* RTAIX */
  295. #endif /* BSD44 */
  296. #endif /* HDBUUCP */
  297. #endif /* PIDSTRING */
  298. /* Now the PIDSTRING exceptions... */
  299. #ifdef PIDSTRING
  300. #ifdef HPUX
  301. #undef PIDSTRING
  302. #endif /* HPUX */
  303. #endif /* PIDSTRING */
  304. #ifdef __bsdi__ /* BSDI (at least thru 1.1) */
  305. #ifdef PIDSTRING
  306. #undef PIDSTRING
  307. #endif /* PIDSTRING */
  308. #endif /* __bsdi__ */
  309. #ifdef OSF32 /* Digital UNIX (OSF/1) 3.2 */
  310. #ifdef PIDSTRING
  311. #undef PIDSTRING
  312. #endif /* PIDSTRING */
  313. #endif /* OSF32 */
  314. /*
  315.   LOCK_DIR is the name of the lockfile directory.
  316.   If LOCK_DIR is already defined (e.g. on command line), we don't change it.
  317. */
  318. #ifndef LOCK_DIR
  319. #ifdef BSD44
  320. #ifdef __386BSD__
  321. #define LOCK_DIR "/var/spool/lock"
  322. #else
  323. #ifdef __FreeBSD__
  324. #define LOCK_DIR "/var/spool/lock"
  325. #else
  326. #ifdef __NetBSD__
  327. #define LOCK_DIR "/var/spool/lock"
  328. #else
  329. #define LOCK_DIR "/var/spool/uucp"
  330. #endif /* __NetBSD__ */
  331. #endif /* __FreeBSD__ */
  332. #endif /* __386BSD__ */
  333. #else
  334. #ifdef DGUX430
  335. #define LOCK_DIR "/var/spool/locks"
  336. #else
  337. #ifdef HPUX10
  338. #define LOCK_DIR "/var/spool/locks"
  339. #else
  340. #ifdef RTAIX /* IBM RT PC AIX 2.2.1 */
  341. #define LOCK_DIR "/etc/locks"
  342. #else
  343. #ifdef AIXRS
  344. #define LOCK_DIR "/etc/locks"
  345. #else
  346. #ifdef ISIII
  347. #define LOCK_DIR "/etc/locks"
  348. #else
  349. #ifdef HDBUUCP
  350. #ifdef M_SYS5
  351. #define LOCK_DIR "/usr/spool/uucp"
  352. #else
  353. #ifdef M_UNIX
  354. #define LOCK_DIR "/usr/spool/uucp"
  355. #else
  356. #ifdef SVR4
  357. #define LOCK_DIR "/var/spool/locks"
  358. #else
  359. #ifdef SUNOS4
  360. #define LOCK_DIR "/var/spool/locks"
  361. #else
  362. #ifdef LINUXFSSTND
  363. #define LOCK_DIR "/var/lock";
  364. #else
  365. #define LOCK_DIR "/usr/spool/locks"
  366. #endif /* LINUXFSSTND */
  367. #endif /* SUNOS4 */
  368. #endif /* SVR4 */
  369. #endif /* M_UNIX */
  370. #endif /* M_SYS5 */
  371. #else
  372. #ifdef LCKDIR
  373. #define LOCK_DIR "/usr/spool/uucp/LCK"
  374. #else
  375. #ifdef COHERENT
  376. #define LOCK_DIR "/usr/spool/uucp"
  377. #else
  378. #define LOCK_DIR "/usr/spool/uucp"
  379. #endif /* COHERENT */
  380. #endif /* LCKDIR */
  381. #endif /* HDBUUCP */
  382. #endif /* ISIII */
  383. #endif /* AIXRS */
  384. #endif /* RTAIX */
  385. #endif /* HPUX10 */
  386. #endif /* DGUX430 */
  387. #endif /* BSD44 */
  388. #endif /* !LOCK_DIR (outside ifndef) */
  389. #ifdef OSF2 /* OSF/1 2.0 or later */
  390. #ifdef LOCK_DIR /* (maybe 1.x too, who knows...) */
  391. #undef LOCK_DIR
  392. #define LOCK_DIR "/var/spool/locks"
  393. #endif /* LOCK_DIR */
  394. #endif /* OSF2 */
  395. #ifdef SVR4
  396. #ifndef BSD44
  397. #ifndef LOCKF
  398. #define LOCKF /* Use lockf() on tty device in SVR4 */
  399. #endif /* LOCKF */
  400. #endif /* BSD44 */
  401. #endif /* SVR4 */
  402. #ifdef NOLOCKF /* But NOLOCKF cancels LOCKF */
  403. #ifdef LOCKF
  404. #undef LOCKF
  405. #endif /* LOCKF */
  406. #endif /* NOLOCKF */
  407. /* More about this below... */
  408. #endif /* USETTYLOCK */
  409. #endif /* NOUUCP */
  410. /*
  411.   MYREAD means use our internally defined nonblocking buffered read routine.
  412. */
  413. #ifdef ATTSV
  414. #define MYREAD
  415. #endif /* ATTSV */
  416. #ifdef ATT7300
  417. #ifndef MYREAD
  418. #define MYREAD
  419. #endif /* MYREAD */
  420. /* bits for attmodem: internal modem in use, restart getty */
  421. #define ISMODEM 1
  422. #define DOGETY 512
  423. #endif  /* ATT7300 */
  424. #ifdef BSD42
  425. #define MYREAD
  426. #endif /* BSD42 */
  427. #ifdef POSIX
  428. #define MYREAD
  429. #endif /* POSIX */
  430. #ifdef __bsdi__
  431. #ifndef O_NDELAY
  432. #define O_NDELAY O_NONBLOCK
  433. #endif /* O_NDELAY */
  434. #endif /* __bsdi__ */
  435. /*
  436.  Variables available to outside world:
  437.    dftty  -- Pointer to default tty name string, like "/dev/tty".
  438.    dfloc  -- 0 if dftty is console, 1 if external line.
  439.    dfprty -- Default parity
  440.    dfflow -- Default flow control
  441.    ckxech -- Flag for who echoes console typein:
  442.      1 - The program (system echo is turned off)
  443.      0 - The system (or front end, or terminal).
  444.    functions that want to do their own echoing should check this flag
  445.    before doing so.
  446.    flfnam  -- Name of lock file, including its path, e.g.,
  447.                 "/usr/spool/uucp/LCK..cul0" or "/etc/locks/tty77"
  448.    lkflfn  -- Name of link to lock file, including its paths
  449.    haslock -- Flag set if this kermit established a uucp lock.
  450.    lockpid -- PID of other process that has desired line open, as string.
  451.    backgrd -- Flag indicating program executing in background ( & on
  452.                 end of shell command). Used to ignore INT and QUIT signals.
  453.    rtu_bug -- Set by stptrap().  RTU treats ^Z as EOF (but only when we handle
  454.                 SIGTSTP)
  455.  Functions for assigned communication line (either external or console tty):
  456.    sysinit()               -- System dependent program initialization
  457.    syscleanup()            -- System dependent program shutdown
  458.    ttopen(ttname,local,mdmtyp,timo) -- Open the named tty for exclusive access.
  459.    ttclos()                -- Close & reset the tty, releasing any access lock.
  460.    ttsspd(cps)             -- Set the transmission speed of the tty.
  461.    ttgspd()                -- Get (read) the the transmission speed of the tty.
  462.    ttpkt(speed,flow,parity) -- Put the tty in packet mode and set the speed.
  463.    ttvt(speed,flow)        -- Put the tty in virtual terminal mode.
  464.                                 or in DIALING or CONNECTED modem control state.
  465.    ttres()                 -- Restore original tty modes.
  466.    ttscarr(carrier)        -- Set carrier control mode, on/off/auto.
  467.    ttinl(dest,max,timo)    -- Timed read line from the tty.
  468.    ttinc(timo)             -- Timed read character from tty.
  469.    myread()                -- Raw mode bulk buffer read, gives subsequent
  470.                                 chars one at a time and simulates FIONREAD.
  471.    myunrd(c)               -- Places c back in buffer to be read (one only)
  472.    ttchk()                 -- See how many characters in tty input buffer.
  473.    ttxin(n,buf)            -- Read n characters from tty (untimed).
  474.    ttol(string,length)     -- Write a string to the tty.
  475.    ttoc(c)                 -- Write a character to the tty.
  476.    ttflui()                -- Flush tty input buffer.
  477.    ttsndb()                -- Send BREAK signal.
  478.    ttsndlb()               -- Send Long BREAK signal.
  479.    ttlock(ttname)          -- "Lock" tty device against uucp collisions.
  480.    ttunlck()               -- Unlock tty device.
  481.                               For ATT7300/Unix PC, System V:
  482.    attdial(ttname,speed,telnbr) -- dials ATT7300/Unix PC internal modem
  483.    offgetty(ttname)        -- Turns off getty(1m) for comms line
  484.    ongetty(ttname)         -- Restores getty() to comms line
  485. */
  486. /*
  487. Functions for console terminal:
  488.    congm()   -- Get console terminal modes.
  489.    concb(esc) -- Put the console in single-character wakeup mode with no echo.
  490.    conbin(esc) -- Put the console in binary (raw) mode.
  491.    conres()  -- Restore the console to mode obtained by congm().
  492.    conoc(c)  -- Unbuffered output, one character to console.
  493.    conol(s)  -- Unbuffered output, null-terminated string to the console.
  494.    conola(s) -- Unbuffered output, array of strings to the console.
  495.    conxo(n,s) -- Unbuffered output, n characters to the console.
  496.    conchk()  -- Check if characters available at console (bsd 4.2).
  497.                 Check if escape char (^) typed at console (System III/V).
  498.    coninc(timo)  -- Timed get a character from the console.
  499.    congks(timo)  -- Timed get keyboard scan code.
  500.    conint()  -- Enable terminal interrupts on the console if not background.
  501.    connoi()  -- Disable terminal interrupts on the console if not background.
  502. Time functions
  503.    msleep(m) -- Millisecond sleep
  504.    ztime(&s) -- Return pointer to date/time string
  505.    rtimer() --  Reset timer
  506.    gtimer()  -- Get elapsed time since last call to rtimer()
  507. */
  508. /* Conditional Includes */
  509. /* Whether to include <sys/file.h> */
  510. #ifdef RTU /* RTU doesn't */
  511. #define NOFILEH
  512. #endif /* RTU */
  513. #ifdef CIE /* CIE does. */
  514. #undef NOFILEH
  515. #endif /* CIE */
  516. #ifdef BSD41 /* 4.1 BSD doesn't */
  517. #define NOFILEH
  518. #endif /* BSD41 */
  519. #ifdef is68k /* is68k (whatever that is)  */
  520. #define NOFILEH
  521. #endif /* is68k */
  522. #ifdef MINIX /* MINIX */
  523. #define NOFILEH
  524. #endif /* MINIX */
  525. #ifdef COHERENT /* Coherent */
  526. #define NOFILEH
  527. #endif /* COHERENT */
  528. #ifndef NOFILEH /* Now include if selected. */
  529. #include <sys/file.h>
  530. #endif /* NOFILEH */
  531. /* POSIX */
  532. #ifdef BSD44ORPOSIX /* POSIX uses termios.h */
  533. #define TERMIOS
  534. #ifdef __bsdi__
  535. #ifdef POSIX
  536. #undef _POSIX_SOURCE /* Get extra stuff from termios.h */
  537. #endif /* POSIX */
  538. #endif /* __bsdi__ */
  539. #include <termios.h>
  540. #ifdef LINUX
  541. #include <sys/ioctl.h>
  542. #endif /* LINUX */
  543. #ifdef QNX16
  544. #include <ioctl.h>
  545. #endif /* QNX16 */
  546. #ifdef __bsdi__
  547. #ifdef POSIX
  548. #define _POSIX_SOURCE
  549. #endif /* POSIX */
  550. #endif /* __bsdi__ */
  551. #ifndef BSD44 /* Really POSIX */
  552. #ifndef CK_QNX32 /* was CK_QNX32 */
  553. #define NOSYSIOCTLH /* No ioctl's allowed. */
  554. #undef ultrix /* Turn off any ultrix features. */
  555. #endif /* CK_QNX32 */
  556. #endif /* BSD44 */
  557. #endif /* POSIX */
  558. /* System III, System V */
  559. #ifdef ATTSV
  560. #ifndef BSD44
  561. #ifndef POSIX
  562. #include <termio.h>
  563. #endif /* POSIX */
  564. #endif /* BSD44 */
  565. #ifdef TERMIOX
  566. /* Need this for termiox structure, RTS/CTS and DTR/CD flow control */
  567. #include <termiox.h>
  568.   struct termiox rctsx;
  569. #else
  570. #ifdef STERMIOX
  571. #ifdef SCO_OSR504
  572. /* Sorry, this is truly disgusting but it's SCO's fault. */
  573. #ifndef _SVID3
  574. #define _CK_SVID3_X
  575. #define _SVID3
  576. #endif /* _SVID3 */
  577. #endif /* SCO_OSR504 */
  578. #include <sys/termiox.h>
  579.   struct termiox rctsx;
  580. #ifdef CK_SVID3_X
  581. #undef _SVID3
  582. #undef CK_SVID3_X
  583. #endif /* CK_SVID3_X */
  584. #endif /* STERMIOX */
  585. #endif /* TERMIOX */
  586. #endif /* ATTSV */
  587. #ifdef COHERENT /* Use termio.h, not sgtty.h for Coherent */
  588. #include <termio.h>
  589. #endif /* COHERENT */
  590. #ifdef MINIX /* MINIX uses ioctl's */
  591. #define NOSYSIOCTLH /* but has no <sys/ioctl.h> */
  592. #endif /* MINIX */
  593. /* Others */
  594. #ifndef NOSYSIOCTLH /* Others use ioctl() */
  595. #ifdef SUN4S5
  596. /*
  597.   This is to get rid of cpp warning messages that occur because all of
  598.   these symbols are defined by both termios.h and ioctl.h on the SUN.
  599. */
  600. #undef ECHO
  601. #undef NL0
  602. #undef NL1
  603. #undef TAB0
  604. #undef TAB1
  605. #undef TAB2
  606. #undef XTABS
  607. #undef CR0
  608. #undef CR1
  609. #undef CR2
  610. #undef CR3
  611. #undef FF0
  612. #undef FF1
  613. #undef BS0
  614. #undef BS1
  615. #undef TOSTOP
  616. #undef FLUSHO
  617. #undef PENDIN
  618. #undef NOFLSH
  619. #endif /* SUN4S5 */
  620. #include <sys/ioctl.h>
  621. #endif /* NOSYSIOCTLH */
  622. /*
  623.   We really, really, REALLY want FIONREAD, because it is the only way to find
  624.   out not just *if* stuff is waiting to be read, but how much, which is
  625.   critical to our sliding-window and streaming procedures, not to mention
  626.   efficiency of CONNECT, etc.
  627. */
  628. #ifdef BELLV10
  629. #include <sys/filio.h> /* For FIONREAD */
  630. #ifdef FIONREAD
  631. #define MYREAD
  632. #endif /* MYREAD */
  633. #endif /* BELLV10 */
  634. #ifndef FIONREAD
  635. /* It wasn't found in ioctl.h or term*.h - try these places: */
  636. #ifdef UNIXWARE
  637. #include <sys/filio.h>
  638. #else
  639. #ifdef SOLARIS
  640. #include <sys/filio.h>
  641. #endif /* SOLARIS */
  642. #endif /* UNIXWARE */
  643. #endif /* FIONREAD */
  644. #ifdef XENIX /* Was M_UNIX but XENIX implies M_UNIX and applies to XENIX too */
  645. /*
  646.   <sys/socket.h> included above via "ckcnet.h" defines FIONREAD as
  647.   something.  Due to this, in_chk() uses the FIONREAD instead of RDCHK
  648.   and the hot keys during file transfer (X to cancel file etc) do not
  649.   work because FIONREAD doesn't work even though it is defined.
  650.   NOTE: This might also be true elsewhere.
  651. */
  652. #ifdef FIONREAD
  653. #undef FIONREAD
  654. #endif /* FIONREAD */
  655. #endif /* XENIX */
  656. #ifdef CK_SCOV5 /* Ditto for SCO OpenServer 5.0 */
  657. #ifdef FIONREAD
  658. #undef FIONREAD
  659. #endif /* FIONREAD */
  660. #endif /* XENIX */
  661. /* Whether to include <fcntl.h> */
  662. #ifndef is68k /* Only a few don't have this one. */
  663. #ifndef BSD41
  664. #ifndef FT21
  665. #ifndef FT18
  666. #ifndef COHERENT
  667. #include <fcntl.h>
  668. #endif /* COHERENT */
  669. #endif /* FT18 */
  670. #endif /* FT21 */
  671. #endif /* BSD41 */
  672. #endif /* not is68k */
  673. #ifdef COHERENT
  674. #ifdef _I386
  675. #include <fcntl.h>
  676. #else
  677. #include <sys/fcntl.h>
  678. #endif /* _I386 */
  679. #endif /* COHERENT */
  680. #ifdef ATT7300 /* Unix PC, internal modem dialer */
  681. #include <sys/phone.h>
  682. #endif /* ATT7300 */
  683. #ifdef HPUX /* HP-UX variations. */
  684. #define HPUXJOBCTL
  685. #include <sys/modem.h> /* HP-UX modem signals */
  686. #ifdef hp9000s500 /* Model 500 */
  687. #undef HPUXJOBCTL
  688. #endif /* hp9000s500 */
  689. #ifdef HPUXPRE65
  690. #undef HPUXJOBCTL
  691. typedef long mflag;
  692. #endif /* HPUXPRE65 */
  693. #ifdef HPUXJOBCTL
  694. #include <sys/bsdtty.h> /* HP-UX Berkeley tty support */
  695. #endif /* HPUXJOBCTL */
  696. #endif /* HPUX */
  697. /*
  698.   Which time.h files to include... See ckcdeb.h for defaults.
  699.   Note that 0, 1, 2, or all 3 of these can be included according to
  700.   the symbol definitions.
  701. */
  702. #ifndef NOTIMEH
  703. #ifdef TIMEH
  704. #include <time.h>
  705. #endif /* TIMEH */
  706. #endif /* NOTIMEH */
  707. #ifndef NOSYSTIMEH
  708. #ifdef SYSTIMEH
  709. #include <sys/time.h>
  710. #endif /* SYSTIMEH */
  711. #endif /* NOSYSTIMEH */
  712. #ifndef NOSYSTIMEBH
  713. #ifdef SYSTIMEBH
  714. #include <sys/timeb.h>
  715. #endif /* SYSTIMEBH */
  716. #endif /* NOSYSTIMEBH */
  717. #ifdef DCLTIMEVAL
  718. /*
  719.   In certain POSIX builds (like Unixware 7), <[sys/]time.h> refuses to
  720.   define the structs we need to access the higher speeds, so we have to
  721.   do it ourselves.
  722. */
  723. struct timeval {
  724.     long tv_sec;
  725.     long tv_usec;
  726. };
  727. struct timezone {
  728.     int tz_minuteswest;
  729.     int tz_dsttime;
  730. };
  731. #endif /* DCLTIMEVAL */
  732. #ifdef __linux__
  733. /* THIS IS OBSOLETE since about Linux 0.92 */
  734. #ifdef OLINUXHISPEED
  735. #include <linux/serial.h>
  736. #endif /* OLINUXHISPEED */
  737. #ifdef __alpha__ /* Linux on DEC Alpha */
  738. #ifndef __GLIBC__ /* But not with glibc */
  739. #include <asm/termios.h>
  740. #endif /* __GLIBC__ */
  741. #endif /* __alpha__ */
  742. #endif /* __linux__ */
  743. #ifdef NOIEXTEN /* This is broken on some systems */
  744. #undef IEXTEN /* like Convex/OS 9.1 */
  745. #endif /* NOIEXTEN */
  746. #ifndef IEXTEN /* Turn off ^O/^V processing. */
  747. #define IEXTEN 0 /* Needed, at least, on BSDI. */
  748. #endif /* IEXTEN */
  749. /*
  750.   Pick up definitions needed for select() if we don't have them already.
  751.   Normally they come from <sys/types.h> but some systems get them from
  752.   <sys/select.h>...  Rather than hardwire all of them into the source, we
  753.   include it if SELECT_H is defined in compile-time CFLAGS.
  754. */
  755. #ifndef SCO_OSR504
  756. #ifdef SELECT_H
  757. #include <sys/select.h>
  758. #endif /* SELECT_H */
  759. #endif /* SCO_OSR504 */
  760. #ifdef aegis
  761. #include "/sys/ins/base.ins.c"
  762. #include "/sys/ins/error.ins.c"
  763. #include "/sys/ins/ios.ins.c"
  764. #include "/sys/ins/sio.ins.c"
  765. #include "/sys/ins/pad.ins.c"
  766. #include "/sys/ins/time.ins.c"
  767. #include "/sys/ins/pfm.ins.c"
  768. #include "/sys/ins/pgm.ins.c"
  769. #include "/sys/ins/ec2.ins.c"
  770. #include "/sys/ins/type_uids.ins.c"
  771. #include <default_acl.h>
  772. #undef TIOCEXCL
  773. #undef FIONREAD
  774. #endif /* aegis */
  775. #ifdef sxaE50 /* PFU Compact A SX/A TISP V10/L50 */
  776. #undef FIONREAD
  777. #endif /* sxaE50 */
  778. /* The following #defines are catch-alls for those systems */
  779. /* that didn't have or couldn't find <file.h>... */
  780. #ifndef FREAD
  781. #define FREAD 0x01
  782. #endif /* FREAD */
  783. #ifndef FWRITE
  784. #define FWRITE 0x10
  785. #endif /* FWRITE */
  786. #ifndef O_RDONLY
  787. #define O_RDONLY 000
  788. #endif /* O_RDONLY */
  789. #ifdef SVORPOSIX
  790. /*
  791.   Modem signals are also forbidden in the POSIX world.  But some POSIX-based
  792.   platforms let us at them anyway if we know where to look.
  793. */
  794. #ifndef NEEDMDMDEFS
  795. /* Doesn't work for Linux */
  796. #ifdef UNIXWARE7
  797. #define NEEDMDMDEFS
  798. #endif /* UNIXWARE7 */
  799. #endif /* NEEDMDMDEFS */
  800. #ifdef NEEDMDMDEFS
  801. #ifndef TIOCMGET
  802. #define TIOCMGET (('t'<<8)|29)
  803. #endif /* TIOCMGET */
  804. #ifndef TIOCM_DTR
  805. #define TIOCM_DTR 0x0002
  806. #endif /* TIOCM_DTR */
  807. #ifndef TIOCM_RTS
  808. #define TIOCM_RTS 0x0004
  809. #endif /* TIOCM_RTS */
  810. #ifndef TIOCM_CTS
  811. #define TIOCM_CTS 0x0020
  812. #endif /* TIOCM_CTS */
  813. #ifndef TIOCM_CAR
  814. #define TIOCM_CAR 0x0040
  815. #endif /* TIOCM_CAR */
  816. #ifndef TIOCM_RNG
  817. #define TIOCM_RNG 0x0080
  818. #endif /* TIOCM_RNG */
  819. #ifndef TIOCM_DSR
  820. #define TIOCM_DSR 0x0100
  821. #endif /* TIOCM_DSR */
  822. #endif /* NEEDMDMDEFS */
  823. #endif /* SVORPOSIX */
  824. /* Declarations */
  825. #ifdef OXOS
  826. #undef TCGETA
  827. #undef TCSETA
  828. #undef TCSETAW
  829. #undef TCSETAF
  830. #define TCGETA TCGETS
  831. #define TCSETA TCSETS
  832. #define TCSETAW TCSETSW
  833. #define TCSETAF TCSETSF
  834. #define termio termios
  835. #endif /* OXOS */
  836. #ifdef SVORPOSIX /* AT&T Sys V or POSIX */
  837. #ifdef UNIXWAREPOSIX /* UnixWare 7 POSIX build */
  838. /*
  839.   In Unixware POSIX builds, <[sys/]time.h> refuses to define the
  840.   structs we need to access the higher speeds, so we have to do it
  841.   ourselves.
  842. */
  843. struct timeval {
  844.     long tv_sec;
  845.     long tv_usec;
  846. };
  847. struct timezone {
  848.     int tz_minuteswest;
  849.     int tz_dsttime;
  850. };
  851. #endif /* UNIXWAREPOSIX */
  852. #endif /* SVORPOSIX */
  853. #ifdef __GNUC__
  854. #ifdef XENIX
  855. /*
  856.   Because Xenix <time.h> doesn't declare time() if we're using gcc.
  857. */
  858. time_t time();
  859. #endif /* XENIX */
  860. #endif /* __GNUC__ */
  861. /* Special stuff for V7 input buffer peeking */
  862. #ifdef  V7
  863. int kmem[2] = { -1, -1};
  864. char *initrawq(), *qaddr[2]={0,0};
  865. #define CON 0
  866. #define TTY 1
  867. #endif /* V7 */
  868. /* dftty is the device name of the default device for file transfer */
  869. /* dfloc is 0 if dftty is the user's console terminal, 1 if an external line */
  870. #ifdef BEOS
  871.     char * dftty = NULL;
  872.     char *dfmdm = "none";
  873.     int dfloc = 0;                  /* that goes in local mode by default */
  874. #else
  875. #ifndef DFTTY
  876. #ifdef PROVX1
  877.     char *dftty = "/dev/com1.dout"; /* Only example so far of a system */
  878.     char *dfmdm = "none";
  879.     int dfloc = 1;                  /* that goes in local mode by default */
  880. #else
  881.     char *dftty = CTTNAM;               /* Remote by default, use normal */
  882.     char *dfmdm = "none";
  883.     int dfloc = 0;                      /* controlling terminal name. */
  884. #endif /* PROVX1 */
  885. #else
  886.     char *dftty = DFTTY; /* Default location specified on */
  887.     char *dfmdm = "none"; /* command line. */
  888.     int dfloc = 1;                      /* controlling terminal name. */
  889. #endif /* DFTTY */
  890. #endif /* BEOS */
  891.     char cttnam[DEVNAMLEN+1] = { '', '' }; /* Determined at runtime */
  892. #ifdef RTU
  893.     int rtu_bug = 0;     /* set to 1 when returning from SIGTSTP */
  894. #endif /* RTU */
  895.     int dfprty = DEFPAR;                /* Default parity (0 = none) */
  896.     int ttprty = 0;                     /* The parity that is in use. */
  897.     static int ttpmsk = 0xff; /* Parity stripping mask. */
  898.     int ttmdm = 0;                      /* Modem in use. */
  899.     int ttcarr = CAR_AUT; /* Carrier handling mode. */
  900.     int dfflow = FLO_NONE; /* Default flow control is NONE */
  901.     int backgrd = 0;                    /* Assume in foreground (no '&' ) */
  902. #ifdef F_SETFL
  903.     int iniflags = -1; /* fcntl flags for ttyfd */
  904. #endif /* F_SETFL */
  905.     int fdflag = 0; /* Flag for redirected stdio */
  906.     int ttfdflg = 0; /* Open File descriptor was given */
  907.     int tvtflg = 0; /* Flag that ttvt has been called */
  908.     long ttspeed = -1L; /* For saving speed */
  909.     int ttflow = -9; /* For saving flow */
  910.     int ttld = -1; /* Line discipline */
  911. #ifdef sony_news
  912.     static int km_con = -1; /* Kanji mode for console tty */
  913.     static int km_ext = -1; /* Kanji mode for external device */
  914. #endif /* sony_news */
  915. #ifdef PARSENSE
  916.     static int needpchk = 1; /* Need parity check */
  917. #else
  918.     static int needpchk = 0;
  919. #endif /* PARSENSE */
  920. #ifdef HWPARITY
  921. /*
  922.   Unfortunately we must do this with global variables rather than through the
  923.   tt...() APIs to avoid changing the APIs and the many modules that use them.
  924.   If hwparity != 0, this indicates 8 data bits + parity, rather than 7 data
  925.   bits + parity or 8 data bits and no parity, and overrides the regular parity
  926.   variable, which is communicated to this module thru ttpkt(), and represented
  927.   locally by the ttprty variable.
  928. */
  929.     extern int hwparity; /* Hardware parity */
  930.     extern int stopbits; /* Stop bits */
  931. #endif /* HWPARITY */
  932. #ifdef TCPSOCKET
  933. #ifdef TCP_NODELAY
  934. static int nodelay_sav = -1;
  935. #endif /* TCP_NODELAY */
  936. #endif /* TCPSOCKET */
  937. static int sigint_ign = 0; /* SIGINT is ignored */
  938. /*
  939.   Having this module rely on external globals is bad, but fixing this
  940.   requires overhaul of the ck*tio.c modules for all the different operating
  941.   systems supported by C-Kermit.  Left for a future release.
  942. */
  943. extern int ttnproto; /* Defined in ckcnet.c */
  944. extern int ttnet; /* Defined in ckcnet.c */
  945. extern int nopush, xfrcan, xfrchr, xfrnum; /* Defined in ckcmai.c */
  946. extern int suspend, wasclosed;
  947. extern int inserver, local;
  948. int ckxech = 0; /* 0 if system normally echoes console characters, else 1 */
  949. int ckmaxfiles = 0; /* Max number of open files */
  950. #ifdef CK_ENCRYPTION /* Kerberos */
  951. #include "ckuath.h"
  952. extern int me_encrypt, u_encrypt;
  953. #endif /* CK_ENCRYPTION */
  954. /* Declarations of variables global within this module */
  955. #ifdef TTLEBUF /* See ckcnet.h */
  956. int ttpush = -1;
  957. #define LEBUFSIZ 4096
  958. static CHAR le_buf[LEBUFSIZ];
  959. static int le_start = 0, le_end = 0, le_data = 0;
  960. #endif /* TTLEBUF */
  961. static time_t tcount = (time_t)0; /* Elapsed time counter */
  962. static SIGTYP (*saval)()     = NULL; /* For saving alarm() handler */
  963. static SIGTYP (*savquit)()   = NULL; /* and other signal handlers */
  964. #ifdef SIGUSR1
  965. static SIGTYP (*savusr1)()   = NULL;
  966. #endif /* SIGUSR1 */
  967. #ifdef SIGUSR2
  968. static SIGTYP (*savusr2)()   = NULL;
  969. #endif /* SIGUSR2 */
  970. #ifdef SIGPIPE
  971. static SIGTYP (*savpipe)()   = NULL;
  972. #endif /* SIGPIPE */
  973. #ifdef SIGDANGER
  974. static SIGTYP (*savdanger)() = NULL;
  975. #endif /* SIGDANGER */
  976. #ifndef NOJC
  977. static SIGTYP (*jchdlr)()    = NULL; /* For checking suspend handler */
  978. #endif /* NOJC */
  979. static int jcshell = -1; /* And flag for result */
  980. /*
  981.   BREAKNULS is defined for systems that simulate sending a BREAK signal
  982.   by sending a bunch of NUL characters at low speed.
  983. */
  984. #ifdef PROVX1
  985. #ifndef BREAKNULS
  986. #define BREAKNULS
  987. #endif /* BREAKNULS */
  988. #endif /* PROVX1 */
  989. #ifdef V7
  990. #ifndef BREAKNULS
  991. #define BREAKNULS
  992. #endif /* BREAKNULS */
  993. #endif /* V7 */
  994. #ifdef BREAKNULS
  995. static char /* A string of nulls */
  996. *brnuls = "";
  997. #endif /* BREAKNULS */
  998. #ifdef CK_POSIX_SIG /* Longjump buffers */
  999. static sigjmp_buf sjbuf; /* POSIX signal handling */
  1000. #else
  1001. static jmp_buf sjbuf;
  1002. #endif /* CK_POSIX_SIG */
  1003. #ifdef V7
  1004. static jmp_buf jjbuf;
  1005. #endif /* V7 */
  1006. /* static */ /* (Not static any more) */
  1007. int ttyfd = -1; /* TTY file descriptor */
  1008. int ttpipe = 0; /* NETCMD: Use pipe instead of ttyfd */
  1009. int ttpty  = 0;                         /* NETPTY: Use pty instead of ttfyd */
  1010. #ifdef NETCMD
  1011. static int pipe0[2], pipe1[2]; /* Pipes for net i/o */
  1012. static PID_T ttpid = 0; /* Process ID for fork */
  1013. static int fdin, fdout; /* File descriptors for pipe */
  1014. static FILE * ttout = NULL; /* File pointer for output pipe */
  1015. #ifdef DCLFDOPEN
  1016. /* fdopen() needs declaring because it's not declared in <stdio.h> */
  1017. _PROTOTYP( FILE * fdopen, (int, char *) );
  1018. #endif /* DCLFDOPEN */
  1019. #endif /* NETCMD */
  1020. extern int pexitstat, quiet;
  1021. #ifdef Plan9
  1022. int ttyctlfd  = -1;   /* TTY control channel - What? UNIX doesn't have one? */
  1023. int consctlfd = -1; /* Console control channel */
  1024. int noisefd = -1; /* tone channel */
  1025. static int ttylastspeed = -1; /* So we can lie about the speed */
  1026. #endif /* Plan9 */
  1027. int telnetfd = 0; /* File descriptor is for telnet */
  1028. int x25fd = 0; /* File descriptor is for X.25 */
  1029. char lockpid[16] = { '', '' }; /* PID stored in lockfile, as string */
  1030. static int lkf = 0,                     /* Line lock flag */
  1031.     cgmf = 0,                           /* Flag that console modes saved */
  1032.     xlocal = 0,                         /* Flag for tty local or remote */
  1033.     curcarr = 0; /* Carrier mode: require/ignore. */
  1034. static int netconn = 0; /* 1 if network connection active */
  1035. static char escchr;                     /* Escape or attn character */
  1036. #ifdef CK_SCO32V4
  1037. #include <sys/time.h>
  1038. #endif /* CK_SCO32V4 */
  1039. #ifdef HAVE_TV
  1040.     static struct timeval tv; /* For getting time, from sys/time.h */
  1041. #endif /* HAVE_TV */
  1042. #ifdef HAVE_TZ
  1043.     static struct timezone tz;
  1044. #endif /* HAVE_TZ */
  1045. #ifdef OSF
  1046.     static struct timeb ftp;            /* And from sys/timeb.h */
  1047. #endif /* OSF */
  1048. #ifdef BSD29
  1049.     static long xclock; /* For getting time from sys/time.h */
  1050.     static struct timeb ftp;            /* And from sys/timeb.h */
  1051. #endif /* BSD29 */
  1052. #ifdef BSD41
  1053.     static long xclock; /* For getting time from sys/time.h */
  1054.     static struct timeb ftp;            /* And from sys/timeb.h */
  1055. #endif /* BSD41 */
  1056. #ifdef BELLV10
  1057.     static long xclock; /* For getting time from sys/time.h */
  1058.     static struct timeb ftp;            /* And from sys/timeb.h */
  1059. #endif /* BELLV10 */
  1060. #ifdef FT21
  1061.     static long xclock; /* For getting time from sys/time.h */
  1062.     static struct timeb ftp;            /* And from sys/timeb.h */
  1063. #endif /* FT21 */
  1064. #ifdef TOWER1
  1065.     static long xclock; /* For getting time from sys/time.h */
  1066.     static struct timeb ftp; /* And from sys/timeb.h */
  1067. #endif /* TOWER1 */
  1068. #ifdef COHERENT
  1069.     static long xclock; /* For getting time from sys/time.h */
  1070.     static struct timeb ftp; /* And from sys/timeb.h */
  1071. #endif /* COHERENT */
  1072. #ifdef V7
  1073.     static long xclock;
  1074. #endif /* V7 */
  1075. /* sgtty/termio information... */
  1076. #ifdef BSD44ORPOSIX /* POSIX or BSD44 */
  1077.   static struct termios
  1078.     ttold, ttraw, tttvt, ttcur,
  1079.     ccold, ccraw, cccbrk;
  1080. #else /* BSD, V7, etc */
  1081. #ifdef COHERENT /* Hack alert... */
  1082. #define ATTSV
  1083. #endif /* COHERENT */
  1084. #ifdef ATTSV
  1085.   static struct termio ttold = {0}; /* Init'd for word alignment, */
  1086.   static struct termio ttraw = {0}; /* which is important for some */
  1087.   static struct termio tttvt = {0}; /* systems, like Zilog... */
  1088.   static struct termio ttcur = {0};
  1089.   static struct termio ccold = {0};
  1090.   static struct termio ccraw = {0};
  1091.   static struct termio cccbrk = {0};
  1092. #else
  1093.   static struct sgttyb                  /* sgtty info... */
  1094.     ttold, ttraw, tttvt, ttcur,  /* for communication line */
  1095.     ccold, ccraw, cccbrk; /* and for console */
  1096. #ifdef BELLV10
  1097.   static struct ttydevb /* Device info... */
  1098.     tdold, tdcur; /* for communication device */
  1099. #endif /* BELLV10 */
  1100. #ifdef TIOCGETC
  1101.   static struct tchars tchold, tchnoi;
  1102.   static int tcharf;
  1103. #endif /* TIOCGETC */
  1104. #ifdef TIOCGLTC
  1105.   static struct ltchars ltchold, ltchnoi;
  1106.   static int ltcharf;
  1107. #endif /* TIOCGLTC */
  1108.   int lmodef = 0; /* Local modes */
  1109.   int lmode = 0;
  1110. #endif /* ATTSV */
  1111. #endif /* BSD44ORPOSIX */
  1112. #ifdef COMMENT
  1113. /* It picks up the speeds but they don't work */
  1114. #ifdef UNIXWARE /* For higher serial speeds */
  1115. #ifdef UW7 /* in Unixware 7.0 */
  1116. #include <sys/asyc.h> /* This picks up 57600 and 115200 */
  1117. #endif /* UW7 */
  1118. #endif /* UNIXWARE */
  1119. #endif /* COMMENT */
  1120. #ifdef PROVX1
  1121.   static struct sgttyb ttbuf;
  1122. #endif /* PROVX1 */
  1123. #ifdef ultrix
  1124. /* do we really need this? */
  1125.   static struct sgttyb vanilla;
  1126. #endif /* ultrix */
  1127. #ifdef ATT7300
  1128. static int attmodem = 0;                /* ATT7300 internal-modem status */
  1129. struct updata dialer = {0}; /* Condition dialer for data call */
  1130. #endif /* ATT7300 */
  1131. #ifndef NOUUCP
  1132. #define FLFNAML 128
  1133. #ifndef USETTYLOCK
  1134. #ifdef RTAIX
  1135. char lkflfn[128] = { '', '' }; /* and possible link to it */
  1136. #endif /* RTAIX */
  1137. char lock2[128] =  { '', '' }; /* Name of second lockfile */
  1138. #endif /* USETTYLOCK */
  1139. #else
  1140. #define FLFNAML 7
  1141. #endif /* NOUUCP */
  1142. char flfnam[FLFNAML+1] = { '', '' }; /* UUCP lock file path name */
  1143. int haslock = 0; /* =1 if this kermit locked uucp */
  1144. #ifndef OXOS
  1145. #ifdef SVORPOSIX
  1146. static int conesc = 0;                  /* set to 1 if esc char (^) typed */
  1147. #else
  1148. #ifdef V7
  1149. static int conesc = 0;
  1150. #else
  1151. #ifdef C70
  1152. static int conesc = 0;
  1153. #endif /* C70 */
  1154. #endif /* V7 */
  1155. #endif /* SVORPOSIX */
  1156. #endif /* OXOS */
  1157. static char ttnmsv[DEVNAMLEN+1]; /* Local copy of comm device name */
  1158. #ifdef USETTYLOCK
  1159. static char lockname[DEVNAMLEN+1]; /* Ditto, the part after "/dev/". */
  1160. #endif /* USETTYLOCK */
  1161. #ifdef aegis
  1162. static status_$t st;                    /* error status return value */
  1163. static short concrp = 0;                /* true if console is CRP pad */
  1164. #define CONBUFSIZ 10
  1165. static char conbuf[CONBUFSIZ];          /* console readahead buffer */
  1166. static int  conbufn = 0;                /* # chars in readahead buffer */
  1167. static char *conbufp;                   /* next char in readahead buffer */
  1168. static uid_$t ttyuid;                   /* tty type uid */
  1169. static uid_$t conuid;                   /* stdout type uid */
  1170. /* APOLLO Aegis main()
  1171.  * establish acl usage and cleanup handling
  1172.  *    this makes sure that CRP pads
  1173.  *    get restored to a usable mode
  1174.  */
  1175. main(argc,argv) int argc; char **argv; {
  1176.         status_$t status;
  1177.         pfm_$cleanup_rec dirty;
  1178.         PID_T pid = getpid();
  1179.         /* acl usage according to invoking environment */
  1180.         default_acl(USE_DEFENV);
  1181.         /* establish a cleanup continuation */
  1182.         status = pfm_$cleanup(dirty);
  1183.         if (status.all != pfm_$cleanup_set) {
  1184.                 /* only handle faults for the original process */
  1185.                 if (pid == getpid() && status.all > pgm_$max_severity) {
  1186.     /* blew up in main process */
  1187.     status_$t quo;
  1188.     pfm_$cleanup_rec clean;
  1189.     /* restore the console in any case */
  1190.     conres();
  1191.     /* attempt a clean exit */
  1192.     debug(F101, "cleanup fault status", "", status.all);
  1193.     /* doexit(), then send status to continuation */
  1194.     quo = pfm_$cleanup(clean);
  1195.     if (quo.all == pfm_$cleanup_set)
  1196.       doexit(pgm_$program_faulted,-1);
  1197.     else if (quo.all > pgm_$max_severity)
  1198.       pfm_$signal(quo); /* blew up in doexit() */
  1199.                 }
  1200.                 /* send to the original continuation */
  1201.                 pfm_$signal(status);
  1202.                 /*NOTREACHED*/
  1203.     }
  1204.         return(ckcmai(argc, argv));
  1205. }
  1206. #endif /* aegis */
  1207. /* ANSI-style prototypes for internal functions. */
  1208. /* Functions used outside this module are prototyped in ckcker.h. */
  1209. #ifdef apollo
  1210. _PROTOTYP( SIGTYP timerh, () );
  1211. _PROTOTYP( SIGTYP cctrap, () );
  1212. _PROTOTYP( SIGTYP esctrp, () );
  1213. _PROTOTYP( SIGTYP sig_ign, () );
  1214. #else
  1215. _PROTOTYP( SIGTYP timerh, (int) );
  1216. _PROTOTYP( SIGTYP cctrap, (int) );
  1217. _PROTOTYP( SIGTYP esctrp, (int) );
  1218. #endif /* apollo */
  1219. _PROTOTYP( int do_open, (char *) );
  1220. _PROTOTYP( static int in_chk, (int, int) );
  1221. _PROTOTYP( static int ttrpid, (char *) );
  1222. _PROTOTYP( static int ttchkpid, (char *) );
  1223. _PROTOTYP( static int ttlock, (char *) );
  1224. _PROTOTYP( static int ttunlck, (void) );
  1225. _PROTOTYP( int mygetbuf, (void) );
  1226. _PROTOTYP( int myfillbuf, (void) );
  1227. _PROTOTYP( VOID conbgt, (int) );
  1228. #ifdef ACUCNTRL
  1229. _PROTOTYP( VOID acucntrl, (char *, char *) );
  1230. #endif /* ACUCNTRL */
  1231. #ifdef BSD44ORPOSIX
  1232. _PROTOTYP( int carrctl, (struct termios *, int) );
  1233. #else
  1234. #ifdef ATTSV
  1235. _PROTOTYP( int carrctl, (struct termio *, int) );
  1236. #else
  1237. _PROTOTYP( int carrctl, (struct sgttyb *, int) );
  1238. #endif /* ATTSV */
  1239. #endif /* BSD44ORPOSIX */
  1240. #ifdef ATT7300
  1241. _PROTOTYP( int attdial, (char *, long, char *) );
  1242. _PROTOTYP( int offgetty, (char *) );
  1243. _PROTOTYP( int ongetty, (char *) );
  1244. #endif /* ATT7300 */
  1245. #ifdef BEOSORBEBOX
  1246. #ifdef SELECT
  1247.     /* BeOS is not capable of using SELECT on anything but sockets */
  1248. #undef SELECT
  1249. #endif /* SELECT */
  1250. #include <kernel/OS.h>
  1251. /* #ifdef BE_DR_7 */
  1252. static double time_started = 0.0;
  1253. struct ALARM_STRUCT {
  1254.     thread_id thread;
  1255.     int time;
  1256. };
  1257. static thread_id alarm_thread = -1;
  1258. static struct ALARM_STRUCT alarm_struct;
  1259. _PROTOTYP( long do_alarm, (void *) );
  1260. _PROTOTYP( unsigned int alarm, (unsigned int) );
  1261. _PROTOTYP( void alarm_expired, (void) );
  1262. /* #endif */ /* BE_DR_7 */
  1263. #endif /* BEOSORBEBOX */
  1264. #ifndef xunchar
  1265. #define xunchar(ch) (((ch) - 32 ) & 0xFF ) /* Character to number */
  1266. #endif /* xunchar */
  1267. #ifdef CK_ANSIC
  1268. static char *
  1269. xxlast(char *s, char c)
  1270. #else
  1271. static char *
  1272. xxlast(s,c) char *s; char c;
  1273. #endif /* CK_ANSIC */
  1274. /* xxlast */ { /*  Last occurrence of character c in string s. */
  1275.     int i;
  1276.     for (i = (int)strlen(s); i > 0; i--)
  1277.       if (s[i-1] == c ) return(s + (i - 1));
  1278.     return(NULL);
  1279. }
  1280. /* Timeout handler for communication line input functions */
  1281. SIGTYP
  1282. timerh(foo) int foo; {
  1283.     ttimoff();
  1284. #ifdef BEOSORBEBOX
  1285. /* #ifdef BE_DR_7 */
  1286.     alarm_expired();
  1287. /* #endif */ /* BE_DR_7 */
  1288. #endif /* BEOSORBEBOX */
  1289. #ifdef CK_POSIX_SIG
  1290.     siglongjmp(sjbuf,1);
  1291. #else
  1292.     longjmp(sjbuf,1);
  1293. #endif /* CK_POSIX_SIG */
  1294. }
  1295. SIGTYP
  1296. xtimerh(foo) int foo; { /* Like timerh() but does */
  1297. #ifdef BEOSORBEBOX /* not reset the itslef */
  1298. /* #ifdef BE_DR_7 */
  1299.     alarm_expired();
  1300. /* #endif */ /* BE_DR_7 */
  1301. #endif /* BEOSORBEBOX */
  1302. #ifdef CK_POSIX_SIG
  1303.     siglongjmp(sjbuf,1);
  1304. #else
  1305.     longjmp(sjbuf,1);
  1306. #endif /* CK_POSIX_SIG */
  1307. }
  1308. /* Control-C trap for communication line input functions */
  1309. int cc_int; /* Flag */
  1310. SIGTYP (* occt)(); /* For saving old SIGINT handler */
  1311. SIGTYP
  1312. cctrap(foo) int foo; { /* Needs arg for ANSI C */
  1313.   cc_int = 1; /* signal() prototype. */
  1314.   return;
  1315. }
  1316. /*  S Y S I N I T  --  System-dependent program initialization.  */
  1317. /*
  1318.  * ttgwsiz() returns:
  1319.  * 1    tt_rows and tt_cols are known, both altered, both > 0
  1320.  * 0    tt_rows and/or tt_cols are known, both altered, one or both <= 0
  1321.  * -1   tt_rows and tt_cols are unknown and unaltered
  1322.  */
  1323. #ifndef NONAWS
  1324. extern int tt_rows, tt_cols;
  1325. #endif /* NONAWS */
  1326. static int
  1327. xttgwsiz() {
  1328.     char *p;
  1329.     int rows = 0, cols = 0;
  1330.     p = getenv("LINES");
  1331.     debug(F110,"xttgwsiz LINES",p,0);
  1332.     if (p) {
  1333. rows = atol(p);
  1334. if (rows > 0) {
  1335.     p = getenv("COLUMNS");
  1336.     debug(F110,"xttgwsiz COLUMNS",p,0);
  1337.     if (p) {
  1338. cols = atol(p);
  1339. if (cols > 0) {
  1340.     tt_rows = rows;
  1341.     tt_cols = cols;
  1342.     return(1);
  1343. }
  1344. return(0);
  1345.     }
  1346. }
  1347.     }
  1348.     return(-1);
  1349. }
  1350. #ifdef TTLEBUF
  1351. VOID
  1352. le_init() { /* LocalEchoInit() */
  1353.     int i;
  1354.     for (i = 0; i < LEBUFSIZ; i++)
  1355.       le_buf[i] = '';
  1356.     le_start = 0;
  1357.     le_end = 0;
  1358.     le_data = 0;
  1359. }
  1360. VOID
  1361. le_clean() { /* LocalEchoCleanup() */
  1362.     le_init();
  1363.     return;
  1364. }
  1365. int
  1366. le_inbuf() {
  1367.     int rc = 0;
  1368.     if (le_start != le_end) {
  1369. rc = (le_end -
  1370.       le_start +
  1371.       LEBUFSIZ) % LEBUFSIZ;
  1372.     }
  1373.     debug(F111,"le_inbuf","chars waiting",rc);
  1374.     return(rc);
  1375. }
  1376. int
  1377. #ifdef CK_ANSIC
  1378. le_putchar(CHAR ch)
  1379. #else
  1380. le_putchar(ch) CHAR ch;
  1381. #endif /* CK_ANSIC */
  1382. /* le_putchar */ {
  1383. #ifdef COMMENT
  1384.     /* In UNIX we do not have another thread taking chars out of the buffer */
  1385.     while ((le_start - le_end == 1) ||
  1386.             (le_start == 0 && le_end == LEBUFSIZ - 1)) {
  1387. /* Buffer is full */
  1388.         debug(F111,"le_putchar","Buffer is Full",ch);
  1389.         ReleaseLocalEchoMutex() ;
  1390.         msleep(250);
  1391.         RequestLocalEchoMutex( SEM_INDEFINITE_WAIT ) ;
  1392.     }
  1393. #else
  1394.     if ((le_start - le_end + LEBUFSIZ)%LEBUFSIZ == 1) {
  1395.         debug(F110,"le_putchar","buffer is full",0);
  1396.         return(-1);
  1397.     }
  1398. #endif /* COMMENT */
  1399.     le_buf[le_end++] = ch;
  1400.     if (le_end == LEBUFSIZ)
  1401.       le_end = 0;
  1402.     le_data = 1;
  1403.     return(0);
  1404. }
  1405. int
  1406. #ifdef CK_ANSIC
  1407. le_puts(CHAR * s, int n)
  1408. #else
  1409. le_puts(s,n) CHAR * s; int n;
  1410. #endif /* CK_ANSIC */
  1411. /* le_puts */ {
  1412.     int rc = 0;
  1413.     int i = 0;
  1414.     CHAR * p = (CHAR *)"le_puts";
  1415.     hexdump(p,s,n);
  1416.     for (i = 0; i < n; i++)
  1417.       rc = le_putchar((char)s[i]);
  1418.     debug(F101,"le_puts","",rc);
  1419.     return(rc);
  1420. }
  1421. int
  1422. #ifdef CK_ANSIC
  1423. le_putstr(CHAR * s)
  1424. #else
  1425. le_putstr(s) CHAR * s;
  1426. #endif /* CK_ANSIC */
  1427. /* le_puts */ {
  1428.     CHAR * p;
  1429.     int rc = 0;
  1430.     p = (CHAR *)"le_putstr";
  1431.     hexdump(p,s,(int)strlen((char *)s));
  1432.     for (p = s; *p && !rc; p++)
  1433.       rc = le_putchar(*p);
  1434.     return(rc);
  1435. }
  1436. int
  1437. #ifdef CK_ANSIC
  1438. le_getchar(CHAR * pch)
  1439. #else /* CK_ANSIC */
  1440. le_getchar(pch) CHAR * pch;
  1441. #endif /* CK_ANSIC */
  1442. /* le_gatchar */ {
  1443.     int rc = 0;
  1444.     if (le_start != le_end) {
  1445.         *pch = le_buf[le_start];
  1446.         le_buf[le_start] = 0;
  1447.         le_start++;
  1448.         if (le_start == LEBUFSIZ)
  1449.           le_start = 0;
  1450.         if (le_start == le_end) {
  1451.             le_data = 0;
  1452.         }
  1453.         rc++;
  1454.     } else {
  1455.         *pch = 0;
  1456.     }
  1457.     return(rc);
  1458. }
  1459. #endif /* TTLEBUF */
  1460. #ifdef COMMENT
  1461. /*
  1462.   Some systems like OSF/1 use TIOCGSIZE instead of TIOCGWINSZ.
  1463.   But as far as I know, whenever TIOCGSIZE is defined, it is
  1464.   equated to TIOCGWINSZ.  For cases where this is not done, try this:
  1465. */
  1466. #ifndef TIOCGWINSZ
  1467. #ifdef TIOCGSIZE
  1468. #define TIOCGWINSZ TIOCGSIZE
  1469. #endif /* TIOCGSIZE */
  1470. #endif /* TIOCGWINSZ */
  1471. #endif /* COMMENT */
  1472. int
  1473. ttgwsiz() {
  1474.     int x = 0;
  1475. #ifndef NONAWS
  1476. #ifdef QNX
  1477. /*
  1478.   NOTE: TIOCGWSIZ works here too, but only in the 32-bit version.
  1479.   This code works for both the 16- and 32-bit versions.
  1480. */
  1481.     extern int dev_size(int, int, int, int *, int *);
  1482.     int r, c;
  1483.     if (dev_size(0, -1, -1, &r, &c) == 0) {
  1484. debug(F101,"ttgwsiz QNX r","",r);
  1485. debug(F101,"ttgwsiz QNX c","",c);
  1486. tt_rows = r;
  1487. tt_cols = c;
  1488. return ((r > 0 && c > 0) ? 1 : 0);
  1489.     } else return(xttgwsiz());
  1490. #else /* QNX */
  1491. #ifdef TIOCGWINSZ
  1492. /* Note, this was M_UNIX, changed to XENIX to allow cross compilation... */
  1493. #ifdef XENIX /* SCO UNIX 3.2v4.0 */
  1494. #include <sys/stream.h> /* typedef mblk_t needed by ptem.h */
  1495. #include <sys/ptem.h> /* for ttgwsiz() */
  1496. #endif /* XENIX */
  1497. #ifdef I386IX /* Ditto for Interactive */
  1498. #include <sys/stream.h>
  1499. #include <sys/ptem.h>
  1500. #endif /* I386IX */
  1501. /* Note, the above might be needed for some other older SVR3 Intel makes... */
  1502.     struct winsize w;
  1503. #ifdef IKSD
  1504.     if (inserver)
  1505.       return(xttgwsiz());
  1506. #endif /* IKSD */
  1507.     x = ioctl(0, (int)TIOCGWINSZ, (char *)&w);
  1508.     debug(F101,"ttgwsiz TIOCGWINSZ","",x);
  1509.     if (x < 0) {
  1510. return(xttgwsiz());
  1511.     } else if (w.ws_row > 0 && w.ws_col > 0) {
  1512. tt_rows = w.ws_row;
  1513. tt_cols = w.ws_col;
  1514. debug(F101,"ttgwsiz tt_rows","",tt_rows);
  1515. debug(F101,"ttgwsiz tt_cols","",tt_cols);
  1516. return(1);
  1517.     } else {
  1518. debug(F100,"ttgwsiz TIOCGWINSZ 00","",0);
  1519. return(xttgwsiz());
  1520.     }
  1521. #else
  1522.     return(xttgwsiz());
  1523. #endif /* TIOCGWINSZ */
  1524. #endif /* QNX */
  1525. #endif /* NONAWS */
  1526. }
  1527. SIGTYP
  1528. sighup(foo) int foo; { /* SIGHUP handler */
  1529.     backgrd = 1;
  1530.     debug(F100,"***************","",0);
  1531.     debug(F100,"SIGHUP received","",0);
  1532.     debug(F100,"***************","",0);
  1533.     doexit(BAD_EXIT,-1);
  1534.     /*NOTREACHED*/
  1535.     SIGRETURN; /* Shut picky compilers up... */
  1536. }
  1537. #ifdef CK_SCO32V4
  1538. /* Exists but there is no prototype in the header files */
  1539. _PROTOTYP( char * ttyname, (int) );
  1540. #else
  1541. #ifdef SV68R3V6
  1542. _PROTOTYP( char * ttyname, (int) );
  1543. #else
  1544. #ifdef ultrix
  1545. _PROTOTYP( char * ttyname, (int) );
  1546. #else
  1547. #ifdef HPUX6
  1548. _PROTOTYP( char * ttyname, (int) );
  1549. #else
  1550. #ifdef HPUX5
  1551. _PROTOTYP( char * ttyname, (int) );
  1552. #else
  1553. #ifdef PS2AIX10
  1554. _PROTOTYP( char * ttyname, (int) );
  1555. #else
  1556. #ifdef BSD42
  1557. _PROTOTYP( char * ttyname, (int) );
  1558. #endif /* BSD42 */
  1559. #endif /* PS2AIX10 */
  1560. #endif /* HPUX5 */
  1561. #endif /* HPUX6 */
  1562. #endif /* ultrix */
  1563. #endif /* SV68R3V6 */
  1564. #endif /* CK_SCO32V4 */
  1565. #ifndef SIGUSR1 /* User-defined signals */
  1566. #define SIGUSR1 30
  1567. #endif /* SIGUSR1 */
  1568. #ifndef SIGUSR2
  1569. #define SIGUSR2 31
  1570. #endif /* SIGUSR2 */
  1571. /*
  1572.   ignorsigs() sets certain signals to SIG_IGN.  But when a signal is
  1573.   ignored, it remains ignored across exec(), so we have to restore these
  1574.   signals before exec(), which is the purpose of restorsigs().
  1575. */
  1576. static VOID
  1577. ignorsigs() { /* Ignore these signals */
  1578.     savquit = signal(SIGQUIT,SIG_IGN); /* Ignore Quit signal */
  1579. #ifdef SIGDANGER /* Ignore danger signals */
  1580. /*
  1581.   This signal is sent when the system is low on swap space.  Processes
  1582.   that don't handle it are candidates for termination.  If swap space doesn't
  1583.   clear out enough, we still might be terminated via kill() -- nothing we can
  1584.   do about that!  Conceivably, this could be improved by installing a real
  1585.   signal handler that warns the user, but that would be pretty complicated,
  1586.   since we are not always in control of the screen -- e.g. during remote-mode
  1587.   file transfer.
  1588. */
  1589.     savdanger = signal(SIGDANGER,SIG_IGN); /* e.g. in AIX */
  1590. #endif /* SIGDANGER */
  1591. #ifdef SIGPIPE
  1592. /*
  1593.   This one comes when a TCP/IP connection is broken by the remote.
  1594.   We prefer to catch this situation by examining error codes from write().
  1595. */
  1596.     savpipe = signal(SIGPIPE,SIG_IGN);
  1597. #endif /* SIGPIPE */
  1598.     savusr1 = signal(SIGUSR1,SIG_IGN); /* Ignore user-defined signals */
  1599.     savusr2 = signal(SIGUSR2,SIG_IGN);
  1600. }
  1601. VOID
  1602. restorsigs() { /* Restore these signals */
  1603.     (VOID) signal(SIGQUIT,savquit); /* (used in ckufio.c) */
  1604. #ifdef SIGDANGER
  1605.     (VOID) signal(SIGDANGER,savdanger);
  1606. #endif /* SIGDANGER */
  1607. #ifdef SIGPIPE
  1608.     (VOID) signal(SIGPIPE,savpipe);
  1609. #endif /* SIGPIPE */
  1610.     (VOID) signal(SIGUSR1,savusr1);
  1611.     (VOID) signal(SIGUSR2,savusr2);
  1612. }
  1613. int
  1614. sysinit() {
  1615.     int x;
  1616.     char * s;
  1617. #ifdef CK_UTSNAME
  1618.     struct utsname name;
  1619. #endif /* CK_UTSNAME */
  1620.     extern char startupdir[];
  1621. /*
  1622.   BEFORE ANYTHING ELSE: Initialize the setuid package.
  1623.   Change to the user's real user and group ID.
  1624.   If this can't be done, don't run at all.
  1625. */
  1626.     debug(F100,"sysinit calling priv_ini","",0);
  1627.     if (x = priv_ini()) {
  1628. if (x & 1) fprintf(stderr,"Fatal: setuid failure.n");
  1629. if (x & 2) fprintf(stderr,"Fatal: setgid failure.n");
  1630. if (x & 4) fprintf(stderr,"Fatal: C-Kermit setuid to root!n");
  1631. exit(1);
  1632.     }
  1633.     signal(SIGINT,SIG_IGN); /* Ignore interrupts at first */
  1634.     signal(SIGHUP,sighup); /* Catch SIGHUP */
  1635. #ifndef NOJC
  1636. /*
  1637.   Get the initial job control state.
  1638.   If it is SIG_IGN, that means the shell does not support job control,
  1639.   and so we'd better not suspend ourselves.
  1640. */
  1641. #ifdef SIGTSTP
  1642.     jchdlr = signal(SIGTSTP,SIG_IGN);
  1643.     if (jchdlr == SIG_IGN) {
  1644. jcshell = 0;
  1645. debug(F100,"sysinit jchdlr: SIG_IGN","",0);
  1646.     } else if (jchdlr == SIG_DFL) {
  1647. debug(F100,"sysinit jchdlr: SIG_DFL","",0);
  1648. jcshell = 1;
  1649.     } else {
  1650. debug(F100,"sysinit jchdlr: other","",0);
  1651. jcshell = 3;
  1652.     }
  1653.     (VOID) signal(SIGTSTP,jchdlr); /* Put it back... */
  1654. #endif /* SIGTSTP */
  1655. #endif /* NOJC */
  1656.     conbgt(0); /* See if we're in the background */
  1657.     congm(); /* Get console modes */
  1658.     (VOID) signal(SIGALRM,SIG_IGN); /* Ignore alarms */
  1659.     ignorsigs(); /* Ignore some other signals */
  1660. #ifdef F_SETFL
  1661.     iniflags = fcntl(0,F_GETFL,0); /* Get stdin flags */
  1662. #endif /* F_SETFL */
  1663. #ifdef ultrix
  1664.     gtty(0,&vanilla); /* Get sgtty info */
  1665. #else
  1666. #ifdef AUX
  1667.     set42sig(); /* Don't ask! (hakanson@cs.orst.edu) */
  1668. #endif /* AUX */
  1669. #endif /* ultrix */
  1670. /*
  1671.   Warning: on some UNIX systems (SVR4?), ttyname() reportedly opens /dev but
  1672.   never closes it.  If it is called often enough, we run out of file
  1673.   descriptors and subsequent open()'s of other devices or files can fail.
  1674. */
  1675.     s = NULL;
  1676. #ifndef MINIX
  1677.     if (isatty(0)) /* Name of controlling terminal */
  1678.       s = ttyname(0);
  1679.     else if (isatty(1))
  1680.       s = ttyname(1);
  1681.     else if (isatty(2))
  1682.       s = ttyname(2);
  1683.     debug(F110,"sysinit ttyname(0)",s,0);
  1684. #endif /* MINIX */
  1685. #ifdef BEOS
  1686.     if (!dftty)
  1687.       makestr(&dftty,s);
  1688. #endif /* BEOS */
  1689.     if (s)
  1690.       ckstrncpy((char *)cttnam,s,DEVNAMLEN+1);
  1691. #ifdef SVORPOSIX
  1692.     if (!cttnam[0])
  1693.       ctermid(cttnam);
  1694. #endif /* SVORPOSIX */
  1695.     if (!cttnam[0])
  1696.       ckstrncpy((char *)cttnam,dftty,DEVNAMLEN+1);
  1697.     debug(F110,"sysinit CTTNAM",CTTNAM,0);
  1698.     debug(F110,"sysinit cttnam",cttnam,0);
  1699.     ttgwsiz(); /* Get window (screen) dimensions. */
  1700. #ifdef _SC_OPEN_MAX
  1701.     ckmaxfiles = sysconf(_SC_OPEN_MAX);
  1702. #endif /* _SC_OPEN_MAX */
  1703. #ifdef Plan9
  1704.     if (!backgrd) {
  1705.      consctlfd = open("/dev/consctl", O_WRONLY);
  1706.      /*noisefd = open("/dev/noise", O_WRONLY)*/
  1707.     }
  1708.     ckxech = 1;
  1709. #endif /* Plan9 */
  1710. #ifdef CK_UTSNAME
  1711.     if (uname(&name) > -1) {
  1712. ckstrncpy(unm_mch,name.machine,CK_SYSNMLN);
  1713. ckstrncpy(unm_nam,name.sysname,CK_SYSNMLN);
  1714. ckstrncpy(unm_rel,name.release,CK_SYSNMLN);
  1715. ckstrncpy(unm_ver,name.version,CK_SYSNMLN);
  1716. #ifdef DEBUG
  1717. if (deblog) {
  1718.     debug(F110,"sysinit uname machine",unm_mch,0);
  1719.     debug(F110,"sysinit uname sysname",unm_nam,0);
  1720.     debug(F110,"sysinit uname release",unm_rel,0);
  1721.     debug(F110,"sysinit uname version",unm_ver,0);
  1722. }
  1723. #endif /* DEBUG */
  1724. #ifdef HPUX9PLUS
  1725. if (name.machine[5] == '8')
  1726.   hpis800 = 1;
  1727. else
  1728.   hpis800 = 0;
  1729. debug(F101,"sysinit hpis800","",hpis800);
  1730. #endif /* HPUX9PLUS */
  1731.     }
  1732. #endif /* CK_UTSNAME */
  1733. #ifdef CK_ENVIRONMENT
  1734.     {
  1735. extern char tn_env_acct[], tn_env_disp[], tn_env_job[],
  1736. tn_env_prnt[], tn_env_sys[], uidbuf[];
  1737.         extern char * whoami();
  1738. char *p;
  1739. #ifdef CKSENDUID
  1740.         uidbuf[0] = '';
  1741. #ifdef IKSD
  1742.         if (!inserver) {
  1743. #endif /* IKSD */
  1744.             p = getenv("USER");
  1745.             debug(F110,"sysinit uidbuf from USER",uidbuf,0);
  1746.             if (!p) {
  1747.                 p = getenv("LOGNAME");
  1748.                 debug(F110,"sysinit uidbuf from LOGNAME",uidbuf,0);
  1749.             }
  1750.             if (!p) {
  1751.                 p = whoami();
  1752.                 debug(F110,"sysinit uidbuf from whoami()",uidbuf,0);
  1753.             }
  1754.             if (p)
  1755.       ckstrncpy(uidbuf,p,UIDBUFLEN);
  1756. #ifdef IKSD
  1757.         }
  1758. #endif /* IKSD */
  1759. debug(F110,"sysinit final uidbuf",uidbuf,0);
  1760. #endif /* CKSENDUID */
  1761. if (p = getenv("JOB")) ckstrncpy(tn_env_job,p,63);
  1762. if (p = getenv("ACCT")) ckstrncpy(tn_env_acct,p,63);
  1763. if (p = getenv("PRINTER")) ckstrncpy(tn_env_prnt,p,63);
  1764. if (p = getenv("DISPLAY")) ckstrncpy(tn_env_disp,p,63);
  1765. #ifdef aegis
  1766. strcpy(tn_env_sys,"Aegis");
  1767. #else
  1768. #ifdef Plan9
  1769. strcpy(tn_env_sys,"Plan9");
  1770. #else
  1771. strcpy(tn_env_sys,"UNIX");
  1772. #endif /* Plan9 */
  1773. #endif /* aegis */
  1774.     }
  1775. #endif /* CK_ENVIRONMENT */
  1776. #ifdef CK_SNDLOC
  1777.     {
  1778. extern char * tn_loc;
  1779. char *p;
  1780. if (p = getenv("LOCATION"))
  1781.   if (tn_loc = (char *)malloc((int)strlen(p)+1))
  1782.     strcpy(tn_loc,p);
  1783.     }
  1784. #endif /* CK_SNDLOC */
  1785.     ckstrncpy(startupdir, zgtdir(), CKMAXPATH);
  1786.     startupdir[CKMAXPATH] = '';
  1787.     x = strlen(startupdir);
  1788.     if (x <= 0) {
  1789. startupdir[0] = '/';
  1790. startupdir[1] = '';
  1791.     } else if (startupdir[x-1] != '/') {
  1792. startupdir[x] = '/';
  1793. startupdir[x+1] = '';
  1794.     }
  1795.     debug(F110,"sysinit startupdir",startupdir,0);
  1796. #ifdef TTLEBUF
  1797.     le_init();
  1798. #endif /* TTLEBUF */
  1799.     return(0);
  1800. }
  1801. /*  S Y S C L E A N U P  --  System-dependent program cleanup.  */
  1802. int
  1803. syscleanup() {
  1804. #ifdef F_SETFL
  1805.     if (iniflags > -1)
  1806.       fcntl(0,F_SETFL,iniflags); /* Restore stdin flags */
  1807. #endif /* F_SETFL */
  1808. #ifdef ultrix
  1809.     stty(0,&vanilla);                   /* Get sgtty info */
  1810. #endif /* ultrix */
  1811. #ifdef NETCMD
  1812.     if (ttpid) kill(ttpid,9);
  1813. #endif /* NETCMD */
  1814.     return(0);
  1815. }
  1816. /*  T T O P E N  --  Open a tty for exclusive access.  */
  1817. /*
  1818.   Call with:
  1819.     ttname: character string - device name or network host name.
  1820.     lcl:
  1821.   If called with lcl < 0, sets value of lcl as follows:
  1822.   0: the terminal named by ttname is the job's controlling terminal.
  1823.   1: the terminal named by ttname is not the job's controlling terminal.
  1824.   But watch out: if a line is already open, or if requested line can't
  1825.   be opened, then lcl remains (and is returned as) -1.
  1826.     modem:
  1827.   Less than zero: ttname is a network host name.
  1828.   Zero or greater: ttname is a terminal device name.
  1829.   Zero means a local connection (don't use modem signals).
  1830.   Positive means use modem signals.
  1831.    timo:
  1832.   0 = no timer.
  1833.   nonzero = number of seconds to wait for open() to return before timing out.
  1834.   Returns:
  1835.     0 on success
  1836.    -5 if device is in use
  1837.    -4 if access to device is denied
  1838.    -3 if access to lock directory denied
  1839.    -2 upon timeout waiting for device to open
  1840.    -1 on other error
  1841. */
  1842. static int ttotmo = 0; /* Timeout flag */
  1843. /* Flag kept here to avoid being clobbered by longjmp.  */
  1844. int
  1845. ttopen(ttname,lcl,modem,timo) char *ttname; int *lcl, modem, timo; {
  1846. #ifdef BSD44
  1847. #define ctermid(x) strcpy(x,"")
  1848. #else
  1849. #ifdef SVORPOSIX
  1850. #ifndef CIE
  1851.     extern char *ctermid(); /* Wish they all had this! */
  1852. #else /* CIE Regulus */
  1853. #define ctermid(x) strcpy(x,"")
  1854. #endif /* CIE */
  1855. #endif /* SVORPOSIX */
  1856. #endif /* BSD44 */
  1857. #ifdef ultrix
  1858.     int temp = 0;
  1859. #endif /* ultrix */
  1860.     char *x; /* Worker string pointer */
  1861.     int y;
  1862. #ifndef pdp11
  1863. #define NAMEFD  /* Feature to allow name to be an open file descriptor */
  1864. #endif /* pdp11 */
  1865. #ifdef NAMEFD
  1866.     char *p;
  1867.     debug(F101,"ttopen telnetfd","",telnetfd);
  1868. #endif /* NAMEFD */
  1869.     debug(F111,"ttopen entry modem",ttname,modem);
  1870.     debug(F101," ttyfd","",ttyfd);
  1871.     debug(F101," lcl","",*lcl);
  1872. #ifdef MAXNAMLEN
  1873.     debug(F100,"ttopen MAXNAMLEN defined","",0);
  1874. #else
  1875.     debug(F100,"ttopen MAXNAMLEN *NOT* defined","",0);
  1876. #endif
  1877. #ifdef BSD4
  1878.     debug(F100,"ttopen BSD4 defined","",0);
  1879. #else
  1880.     debug(F100,"ttopen BSD4 *NOT* defined","",0);
  1881. #endif /* BSD4 */
  1882. #ifdef BSD42
  1883.     debug(F100,"ttopen BSD42 defined","",0);
  1884. #else
  1885.     debug(F100,"ttopen BSD42 *NOT* defined","",0);
  1886. #endif /* BSD42 */
  1887. #ifdef MYREAD
  1888.     debug(F100,"ttopen MYREAD defined","",0);
  1889. #else
  1890.     debug(F100,"ttopen MYREAD *NOT* defined","",0);
  1891. #endif /* MYREAD */
  1892.     ttpmsk = 0xff;
  1893.     lockpid[0] = '';
  1894.     if (ttyfd > -1) { /* if device already opened */
  1895. debug(F110,"ttopen ttname",ttname,0);
  1896. debug(F110,"ttopen ttnmsv",ttnmsv,0);
  1897.         if (strncmp(ttname,ttnmsv,DEVNAMLEN)) /* are new & old names equal? */
  1898.           ttclos(ttyfd); /* no, close old ttname, open new */
  1899.         else  /* else same, ignore this call, */
  1900.   return(0); /* and return. */
  1901.     }
  1902.     wasclosed = 0;
  1903.     ttpipe = 0; /* Assume it's not a pipe */
  1904.     ttpty = 0;
  1905. #ifdef NETCONN
  1906.     if (modem < 0) { /* modem < 0 = special code for net */
  1907. int x;
  1908. ttmdm = modem;
  1909. modem = -modem; /* Positive network type number */
  1910. fdflag = 0; /* Stdio not redirected. */
  1911. netconn = 1; /* And it's a network connection */
  1912. debug(F111,"ttopen net",ttname,modem);
  1913. #ifdef NAMEFD
  1914. for (p = ttname; isdigit(*p); p++) ; /* Check for all digits */
  1915.   if (*p == '' && (telnetfd || x25fd)) { /* Avoid X.121 addresses */
  1916.     ttyfd = atoi(ttname); /* Is there a way to test it's open? */
  1917.     ttfdflg = 1; /* We got an open file descriptor */
  1918.     debug(F111,"ttopen got open network fd",ttname,ttyfd);
  1919.     ckstrncpy(ttnmsv,ttname,DEVNAMLEN); /* Remember the "name". */
  1920.     x = 1; /* Return code is "good". */
  1921.     if (telnetfd) {
  1922. ttnet = NET_TCPB;
  1923. if (ttnproto != NP_TCPRAW)
  1924.   ttnproto = NP_TELNET;
  1925. #ifdef SUNX25
  1926.     } else if (x25fd) {
  1927. ttnet = NET_SX25;
  1928. ttnproto = NP_NONE;
  1929. #endif /* SUNX25 */
  1930.     }
  1931. } else { /* Host name or address given */
  1932. #ifdef NETPTY
  1933.     if (modem == NET_PTY) {
  1934. int x;
  1935. if (nopush) {
  1936.     debug(F100,"ttopen PTY: nopush","",0);
  1937.     return(-1);
  1938. }
  1939.                 ttnet = NET_PTY;
  1940. ttnproto = NP_NONE;
  1941.                 netconn = 1;            /* but we don't use network i/o */
  1942.                 ttpty = 1;
  1943.                 debug(F110,"ttopen PTY",ttname,0);
  1944. x = do_pty(ttname);
  1945. if (x > -1) {
  1946.     ckstrncpy(ttnmsv,ttname,DEVNAMLEN);
  1947.     xlocal = *lcl = 1; /* It's local */
  1948. } else {
  1949.     ttpty = 0;
  1950.     netconn = 0;
  1951. }
  1952. return(x);
  1953.     }
  1954. #endif /* NETPTY */
  1955. #ifdef NETCMD
  1956. /*
  1957.   dup2() is not available on older System V platforms like AT&T 3Bx.  For
  1958.   those systems we punt by not defining NETCMD, but we might be able to do
  1959.   better -- see workarounds for this problem in ckufio.c (search for dup2).
  1960. */
  1961.     if (modem == NET_CMD) {
  1962. if (nopush) {
  1963.     debug(F100,"ttopen pipe: nopush","",0);
  1964.     return(-1);
  1965. }
  1966. if (pipe(pipe0) || pipe(pipe1)) {
  1967.     perror("Pipe error");
  1968.     return(-1);
  1969. }
  1970. ttpid = fork(); /* Make a fork */
  1971. switch (ttpid) {
  1972.   case -1: /* Error making fork */
  1973.     close(pipe0[0]);
  1974.     close(pipe0[1]);
  1975.     close(pipe1[0]);
  1976.     close(pipe1[1]);
  1977.     perror("Fork error");
  1978.     return(-1);
  1979.   case 0: /* Child. */
  1980.     close(pipe0[0]);
  1981.     close(pipe1[1]);
  1982.     dup2(pipe0[1], 1);
  1983.     close(pipe0[1]);
  1984.     dup2(pipe1[0], 0);
  1985.     close(pipe1[0]);
  1986.     system(ttname);
  1987.     _exit(0);
  1988.   default: /* Parent */
  1989.     close(pipe0[1]);
  1990.     close(pipe1[0]);
  1991.     fdin = pipe0[0]; /* Read from pipe */
  1992.     fdout = pipe1[1]; /* Write to pipe */
  1993.     ttout = fdopen(fdout,"w"); /* Get stream so we can */
  1994.     if (!ttout) { /* make it unbuffered. */
  1995. perror("fdopen failure");
  1996. return(-1);
  1997.     }
  1998.     setbuf(ttout,NULL);
  1999.     ckstrncpy(ttnmsv,ttname,DEVNAMLEN);
  2000.     xlocal = *lcl = 1; /* It's local */
  2001.     netconn = 1; /* Call it a network connection */
  2002.     ttmdm = modem; /* Remember network type */
  2003.     ttyfd = fdin;
  2004.     ttpipe = 1;
  2005.     return(0);
  2006. }
  2007.     }
  2008. #endif /* NETCMD */
  2009. #endif /* NAMEFD */
  2010.     x = netopen(ttname, lcl, modem); /* (see ckcnet.h) */
  2011.     if (x > -1) {
  2012. ckstrncpy(ttnmsv,ttname,DEVNAMLEN);
  2013.     } else netconn = 0;
  2014. #ifdef NAMEFD
  2015. }
  2016. #endif /* NAMEFD */
  2017. #ifdef sony_news /* Sony NEWS */
  2018. if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) { /* Get Kanji mode */
  2019.     perror("ttopen error getting Kanji mode (network)");
  2020.     debug(F111,"ttopen error getting Kanji mode","network",0);
  2021.     km_ext = -1; /* Make sure this stays undefined. */
  2022. }
  2023. #endif /* sony_news */
  2024. xlocal = *lcl = 1; /* Network connections are local. */
  2025. debug(F101,"ttopen net x","",x);
  2026. #ifdef COMMENT
  2027. /* Let netopen() do this */
  2028. if (x > -1 && !x25fd)
  2029.   x = tn_ini(); /* Initialize TELNET protocol */
  2030. #endif /* COMMENT */
  2031. return(x);
  2032.     } else { /* Terminal device */
  2033. #endif /* NETCONN */
  2034. #ifdef NAMEFD
  2035. /*
  2036.   This code lets you give Kermit an open file descriptor for a serial
  2037.   communication device, rather than a device name.  Kermit assumes that the
  2038.   line is already open, locked, conditioned with the right parameters, etc.
  2039. */
  2040. for (p = ttname; isdigit(*p); p++) ; /* Check for all digits */
  2041. if (*p == '') {
  2042.     ttyfd = atoi(ttname); /* Is there a way to test it's open? */
  2043.     debug(F111,"ttopen got open fd",ttname,ttyfd);
  2044.     ckstrncpy(ttnmsv,ttname,DEVNAMLEN); /* Remember the "name". */
  2045.     if (ttyfd == 0) /* If it's stdio... */
  2046.       xlocal = *lcl = 0; /* we're in remote mode */
  2047.     else /* otherwise */
  2048.       xlocal = *lcl = 1; /* local mode. */
  2049.     netconn = 0; /* Assume it's not a network. */
  2050.     tvtflg = 0; /* Might need to initialize modes. */
  2051.     ttmdm = modem; /* Remember modem type. */
  2052.     fdflag = 0; /* Stdio not redirected. */
  2053.     ttfdflg = 1; /* Flag we were opened this way. */
  2054. #ifdef sony_news /* Sony NEWS */
  2055.     /* Get device Kanji mode */
  2056.     if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) {
  2057. perror("ttopen error getting Kanji mode");
  2058. debug(F101,"ttopen error getting Kanji mode","",0);
  2059. km_ext = -1; /* Make sure this stays undefined. */
  2060.     }
  2061. #endif /* sony_news */
  2062.     return(0); /* Return success */
  2063. }
  2064. #endif /* NAMEFD */
  2065. #ifdef NETCONN
  2066.     }
  2067. #endif /* NETCONN */
  2068. /* Here we have to open a serial device of the given name. */
  2069.     netconn = 0; /* So it's not a network connection */
  2070.     occt = signal(SIGINT, cctrap); /* Set Control-C trap, save old one */
  2071.     sigint_ign = 0;
  2072.     tvtflg = 0; /* Flag for use by ttvt(). */
  2073. /* 0 = ttvt not called yet for this device */
  2074.     fdflag = (!isatty(0) || !isatty(1)); /* Flag for stdio redirected */
  2075.     debug(F101,"ttopen fdflag","",fdflag);
  2076.     ttmdm = modem;                      /* Make this available to other fns */
  2077.     xlocal = *lcl;                      /* Make this available to other fns */
  2078. /* Code for handling bidirectional tty lines goes here. */
  2079. /* Use specified method for turning off logins and suppressing getty. */
  2080. #ifdef ACUCNTRL
  2081.     /* Should put call to priv_on() here, but that would be very risky! */
  2082.     acucntrl("disable",ttname);         /* acucntrl() program. */
  2083.     /* and priv_off() here... */
  2084. #else
  2085. #ifdef ATT7300
  2086.     if ((attmodem & DOGETY) == 0)       /* offgetty() program. */
  2087.       attmodem |= offgetty(ttname); /* Remember response.  */
  2088. #endif /* ATT7300 */
  2089. #endif /* ACUCNTRL */
  2090. /*
  2091.  In the following section, we open the tty device for read/write.
  2092.  If a modem has been specified via "set modem" prior to "set line"
  2093.  then the O_NDELAY parameter is used in the open, provided this symbol
  2094.  is defined (e.g. in fcntl.h), so that the program does not hang waiting
  2095.  for carrier (which in most cases won't be present because a connection
  2096.  has not been dialed yet).  O_NDELAY is removed later on in ttopen().  It
  2097.  would make more sense to first determine if the line is local before
  2098.  doing this, but because ttyname() requires a file descriptor, we have
  2099.  to open it first.  See do_open().
  2100.  Now open the device using the desired treatment of carrier.
  2101.  If carrier is REQUIRED, then open could hang forever, so an optional
  2102.  timer is provided.  If carrier is not required, the timer should never
  2103.  go off, and should do no harm...
  2104. */
  2105.     ttotmo = 0; /* Flag no timeout */
  2106.     debug(F101,"ttopen timo","",timo);
  2107.     debug(F101,"ttopen xlocal","",xlocal);
  2108.     if (timo > 0) {
  2109. int xx;
  2110. saval = signal(SIGALRM,timerh); /* Timed, set up timer. */
  2111. xx = alarm(timo); /* Timed open() */
  2112. debug(F101,"ttopen alarm","",xx);
  2113. if (
  2114. #ifdef CK_POSIX_SIG
  2115.     sigsetjmp(sjbuf,1)
  2116. #else
  2117.     setjmp(sjbuf)
  2118. #endif /* CK_POSIX_SIG */
  2119.     ) {
  2120.     ttotmo = 1; /* Flag timeout. */
  2121. } else ttyfd = do_open(ttname);
  2122. ttimoff();
  2123. debug(F111,"ttopen","modem",modem);
  2124. debug(F101,"ttopen ttyfd","",ttyfd);
  2125. debug(F101,"ttopen alarm return","",ttotmo);
  2126.     } else {
  2127. errno = 0;
  2128. ttyfd = do_open(ttname);
  2129.     }
  2130.     debug(F111,"ttopen ttyfd",ttname,ttyfd);
  2131.     if (ttyfd < 0) { /* If couldn't open, fail. */
  2132. debug(F101,"ttopen errno","",errno);
  2133. if (errno > 0 && !quiet)
  2134.   perror(ttname); /* Print message */
  2135. #ifdef ATT7300
  2136. if (attmodem & DOGETY) /* was getty(1m) running before us? */
  2137.   ongetty(ttnmsv); /* yes, restart on tty line */
  2138. attmodem &= ~DOGETY; /* no phone in use, getty restored */
  2139. #else
  2140. #ifdef ACUCNTRL
  2141.         /* Should put call to priv_on() here, but that would be risky! */
  2142. acucntrl("enable",ttname); /* acucntrl() program. */
  2143. /* and priv_off() here... */
  2144. #endif /* ACUNTRL */
  2145. #endif /* ATT7300 */
  2146. signal(SIGINT,occt); /* Put old Ctrl-C trap back. */
  2147. if (errno == EACCES) { /* Device is protected against user */
  2148.     debug(F110,"ttopen EACCESS",ttname,0); /* Return -4 */
  2149.     return(-4);
  2150. } else return(ttotmo ? -2 : -1); /* Otherwise -2 if timeout, or -1 */
  2151.     }
  2152. #ifdef Plan9
  2153.     /* take this opportunity to open the control channel */
  2154.     if (p9openttyctl(ttname) < 0)
  2155. #else
  2156.     /* Make sure it's a real tty. */
  2157.     if (!isatty(ttyfd) && strcmp(ttname,"/dev/null"))
  2158. #endif /* Plan9 */
  2159.       {
  2160. fprintf(stderr,"%s is not a terminal devicen",ttname);
  2161. debug(F111,"ttopen not a tty",ttname,errno);
  2162. close(ttyfd);
  2163. ttyfd = -1;
  2164. wasclosed = 1;
  2165. signal(SIGINT,occt);
  2166. return(-1);
  2167.     }
  2168. #ifdef aegis
  2169. /* Apollo C runtime claims that console pads are tty devices, which
  2170.  * is reasonable, but they aren't any good for packet transfer. */
  2171. ios_$inq_type_uid((short)ttyfd, ttyuid, st);
  2172. if (st.all != status_$ok) {
  2173.     fprintf(stderr, "problem getting tty object type: ");
  2174.     error_$print(st);
  2175. } else if (ttyuid != sio_$uid) { /* reject non-SIO lines */
  2176.     close(ttyfd); ttyfd = -1;
  2177.     wasclosed = 1;
  2178.     errno = ENOTTY; perror(ttname);
  2179.     signal(SIGINT,occt);
  2180.     return(-1);
  2181. }
  2182. #endif /* aegis */
  2183.     sigint_ign = (occt == SIG_IGN) ? 1 : 0;
  2184.     ckstrncpy(ttnmsv,ttname,DEVNAMLEN); /* Keep copy of name locally. */
  2185. /* Caller wants us to figure out if line is controlling tty */
  2186.     if (*lcl < 0) {
  2187.         if (strcmp(ttname,CTTNAM) == 0) { /* "/dev/tty" always remote */
  2188.             xlocal = 0;
  2189.     debug(F111,"ttopen ttname=CTTNAM",ttname,xlocal);
  2190.         } else if (strcmp(ttname,cttnam) == 0) {
  2191.             xlocal = 0;
  2192.     debug(F111,"ttopen ttname=cttnam",ttname,xlocal);
  2193. } else if (cttnam[0]) {
  2194. #ifdef BEBOX_DR7
  2195.             x = ttnmsv; /* ttyname() is broken */
  2196. #else
  2197.             x = ttyname(ttyfd);         /* Get real name of ttname. */
  2198. #endif /* BEBOX_DR7 */
  2199.     if (!x) x = "";
  2200.     if (*x)
  2201.       xlocal = ((strncmp(x,cttnam,DEVNAMLEN) == 0) ? 0 : 1);
  2202.     else
  2203.       xlocal = 1;
  2204.             debug(F111,"ttopen ttyname(ttyfd) xlocal",x,xlocal);
  2205.         }
  2206.     }
  2207. #ifndef NOFDZERO
  2208. /* Note, the following code was added so that Unix "idle-line" snoopers */
  2209. /* would not think Kermit was idle when it was transferring files, and */
  2210. /* maybe log people out. */
  2211.     if (xlocal == 0) { /* Remote mode */
  2212. if (fdflag == 0) { /* Standard i/o is not redirected */
  2213.     debug(F100,"ttopen setting ttyfd = 0","",0);
  2214. #ifdef LYNXOS
  2215.     /* On Lynx OS, fd 0 is open for read only. */
  2216.     dup2(ttyfd,0);
  2217. #endif /* LYNXOS */
  2218.     close(ttyfd); /* Use file descriptor 0 */
  2219.     ttyfd = 0;
  2220. } else { /* Standard i/o is redirected */
  2221.     debug(F101,"ttopen stdio redirected","",ttyfd);
  2222. }
  2223.     }
  2224. #endif /* NOFDZERO */
  2225. /* Now check if line is locked -- if so fail, else lock for ourselves */
  2226. /* Note: After having done this, don't forget to delete the lock if you */
  2227. /* leave ttopen() with an error condition. */
  2228.     lkf = 0;                            /* Check lock */
  2229.     if (xlocal > 0) {
  2230. int xx; int xpid;
  2231.         if ((xx = ttlock(ttname)) < 0) { /* Can't lock it. */
  2232.             debug(F111,"ttopen ttlock fails",ttname,xx);
  2233.     /* WARNING - This close() can hang if tty is an empty socket... */
  2234.             close(ttyfd); /* Close the device. */
  2235.     ttyfd = -1; /* Erase its file descriptor. */
  2236.     wasclosed = 1;
  2237.     signal(SIGINT,occt); /* Put old SIGINT back. */
  2238.     sigint_ign = (occt == SIG_IGN) ? 1 : 0;
  2239.     if (xx == -2) { /* If lockfile says device in use, */
  2240. #ifndef NOUUCP
  2241. debug(F111,"ttopen reading lockfile pid",flfnam,xx);
  2242. xpid = ttrpid(flfnam); /* Try to read pid from lockfile */
  2243. if (xpid > -1) { /* If we got a pid */
  2244.     printf("Locked by process %dn",xpid); /* tell them. */
  2245.     sprintf(lockpid,"%d",xpid); /* Record it too */
  2246.     debug(F110,"ttopen lockpid",lockpid,0);
  2247. } else if (*flfnam) {
  2248.     char *p = malloc(280); /* Print a directory listing. */
  2249. /*
  2250.   Note: priv_on() won't help here, because we do not pass privs along to
  2251.   to inferior processes, in this case ls.  So if the real user does not have
  2252.   directory-listing access to the lockfile directory, this will result in
  2253.   something like "not found".  That's why we try this only as a last resort.
  2254. */
  2255.     if (p) { /* If we got the space... */
  2256. extern char *DIRCMD;
  2257. sprintf(p,"%s %s",DIRCMD,flfnam);
  2258. zsyscmd(p); /* Get listing. */
  2259. if (p) { /* free the space */
  2260.     free(p);
  2261.     p = NULL;
  2262. }
  2263.     }
  2264. }
  2265. #endif /* NOUUCP */
  2266. return(-5); /* Code for device in use */
  2267.     } else return(-3); /* Access denied */
  2268.         } else lkf = 1;
  2269.     }
  2270. /* Got the line, now set the desired value for local. */
  2271.     if (*lcl != 0) *lcl = xlocal;
  2272. /* Some special stuff for v7... */
  2273. #ifdef  V7
  2274. #ifndef MINIX
  2275.     if (kmem[TTY] < 0) { /*  If open, then skip this.  */
  2276. qaddr[TTY] = initrawq(ttyfd);   /* Init the queue. */
  2277. if ((kmem[TTY] = open("/dev/kmem", 0)) < 0) {
  2278.     fprintf(stderr, "Can't read /dev/kmem in ttopen.n");
  2279.     perror("/dev/kmem");
  2280.     exit(1);
  2281. }
  2282.     }
  2283. #endif /* !MINIX */
  2284. #endif /* V7 */
  2285. /* No failure returns after this point */
  2286. #ifdef ultrix
  2287.     ioctl(ttyfd, TIOCMODEM, &temp);
  2288. #ifdef TIOCSINUSE
  2289.     if (xlocal && ioctl(ttyfd, TIOCSINUSE, NULL) < 0) {
  2290. if (!quiet)
  2291.   perror(ttname);
  2292.     }
  2293. #endif /* TIOCSINUSE */
  2294. #endif /* ultrix */
  2295. /* Get tty device settings  */
  2296. #ifdef BSD44ORPOSIX /* POSIX */
  2297.     tcgetattr(ttyfd,&ttold);
  2298.     debug(F101,"ttopen tcgetattr ttold.c_lflag","",ttold.c_lflag);
  2299.     tcgetattr(ttyfd,&ttraw);
  2300.     debug(F101,"ttopen tcgetattr ttraw.c_lflag","",ttraw.c_lflag);
  2301.     tcgetattr(ttyfd,&tttvt);
  2302.     debug(F101,"ttopen tcgetattr tttvt.c_lflag","",tttvt.c_lflag);
  2303. #else /* BSD, V7, and all others */
  2304. #ifdef ATTSV /* AT&T UNIX */
  2305.     ioctl(ttyfd,TCGETA,&ttold);
  2306.     debug(F101,"ttopen ioctl TCGETA ttold.c_lflag","",ttold.c_lflag);
  2307.     ioctl(ttyfd,TCGETA,&ttraw);
  2308.     ioctl(ttyfd,TCGETA,&tttvt);
  2309. #else
  2310. #ifdef BELLV10
  2311.     ioctl(ttyfd,TIOCGETP,&ttold);
  2312.     debug(F101,"ttopen BELLV10 ttold.sg_flags","",ttold.sg_flags);
  2313.     ioctl(ttyfd,TIOCGDEV,&tdold);
  2314.     debug(F101,"ttopen BELLV10 tdold.flags","",tdold.flags);
  2315. #else
  2316.     gtty(ttyfd,&ttold);
  2317.     debug(F101,"ttopen gtty ttold.sg_flags","",ttold.sg_flags);
  2318. #endif /* BELLV10 */
  2319. #ifdef sony_news /* Sony NEWS */
  2320.     if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) { /* Get console Kanji mode */
  2321. perror("ttopen error getting Kanji mode");
  2322. debug(F101,"ttopen error getting Kanji mode","",0);
  2323. km_ext = -1; /* Make sure this stays undefined. */
  2324.     }
  2325. #endif /* sony_news */
  2326. #ifdef TIOCGETC
  2327.     debug(F100,"ttopen TIOCGETC","",0);
  2328.     tcharf = 0; /* In remote mode, also get */
  2329.     if (xlocal == 0) { /* special characters */
  2330. if (ioctl(ttyfd,TIOCGETC,&tchold) < 0) {
  2331.     debug(F100,"ttopen TIOCGETC failed","",0);
  2332. } else {
  2333.     tcharf = 1; /* It worked. */
  2334.     ioctl(ttyfd,TIOCGETC,&tchnoi); /* Get another copy */
  2335.     debug(F100,"ttopen TIOCGETC ok","",0);
  2336. }
  2337.     }
  2338. #else
  2339.     debug(F100,"ttopen TIOCGETC not defined","",0);
  2340. #endif /* TIOCGETC */
  2341. #ifdef TIOCGLTC
  2342.     debug(F100,"ttopen TIOCGLTC","",0);
  2343.     ltcharf = 0; /* In remote mode, also get */
  2344.     if (xlocal == 0) { /* local special characters */
  2345. if (ioctl(ttyfd,TIOCGLTC,&ltchold) < 0) {
  2346.     debug(F100,"ttopen TIOCGLTC failed","",0);
  2347. } else {
  2348.     ltcharf = 1; /* It worked. */
  2349.     ioctl(ttyfd,TIOCGLTC,&ltchnoi); /* Get another copy */
  2350.     debug(F100,"ttopen TIOCGLTC ok","",0);
  2351. }
  2352.     }
  2353. #else
  2354.     debug(F100,"ttopen TIOCGLTC not defined","",0);
  2355. #endif /* TIOCGLTC */
  2356. #ifdef TIOCLGET
  2357.     debug(F100,"ttopen TIOCLGET","",0);
  2358.     lmodef = 0;
  2359.     if (ioctl(ttyfd,TIOCLGET,&lmode) < 0) {
  2360. debug(F100,"ttopen TIOCLGET failed","",0);
  2361.     } else {
  2362. lmodef = 1;
  2363. debug(F100,"ttopen TIOCLGET ok","",0);
  2364.     }
  2365. #endif /* TIOCLGET */
  2366. #ifdef BELLV10
  2367.     ioctl(ttyfd,TIOCGETP,&ttraw);
  2368.     ioctl(ttyfd,TIOCGETP,&tttvt);
  2369. #else
  2370.     gtty(ttyfd,&ttraw);                 /* And a copy of it for packets*/
  2371.     gtty(ttyfd,&tttvt);                 /* And one for virtual tty service */
  2372. #endif /* BELLV10 */
  2373. #endif /* ATTSV */
  2374. #endif /* BSD44ORPOSIX */
  2375. /* Section for changing line discipline.  It's restored in ttres(). */
  2376. #ifdef AIXRS
  2377. #ifndef AIX41
  2378.     { union txname ld_name; int ld_idx = 0;
  2379.       ttld = 0;
  2380.         do {
  2381.      ld_name.tx_which = ld_idx++;
  2382.      ioctl(ttyfd, TXGETCD, &ld_name);
  2383.   if (!strncmp(ld_name.tx_name, "rts", 3))
  2384.        ttld |= 1;
  2385.         } while (*ld_name.tx_name);
  2386.         debug(F101,"AIX line discipline","",ttld);
  2387.       }
  2388. #endif /* AIX41 */
  2389. #endif /* AIXRS */
  2390. #ifdef BSD41
  2391. /* For 4.1BSD only, force "old" tty driver, new one botches TANDEM. */
  2392.     { int k;
  2393.       ioctl(ttyfd, TIOCGETD, &ttld); /* Get and save line discipline */
  2394.       debug(F101,"4.1bsd line discipline","",ttld);
  2395.       k = OTTYDISC; /* Switch to "old" discipline */
  2396.       k = ioctl(ttyfd, TIOCSETD, &k);
  2397.       debug(F101,"4.1bsd tiocsetd","",k);
  2398.     }
  2399. #endif /* BSD41 */
  2400. #ifdef aegis
  2401.     /* This was previously done before the last two TCGETA or gtty above,
  2402.      * in both the ATTSV and not-ATTSV case.  If it is not okay to have only
  2403.      * one copy if it here instead, give us a shout!
  2404.      */
  2405.     sio_$control((short)ttyfd, sio_$raw_nl, false, st);
  2406.     if (xlocal) {       /* ignore breaks from local line */
  2407.         sio_$control((short)ttyfd, sio_$int_enable, false, st);
  2408.         sio_$control((short)ttyfd, sio_$quit_enable, false, st);
  2409.     }
  2410. #endif /* aegis */
  2411. #ifdef VXVE
  2412.     ttraw.c_line = 0;                   /* STTY line 0 for VX/VE */
  2413.     tttvt.c_line = 0;                   /* STTY line 0 for VX/VE */
  2414.     ioctl(ttyfd,TCSETA,&ttraw);
  2415. #endif /* vxve */
  2416. /* If O_NDELAY was used during open(), then remove it now. */
  2417. #ifdef O_NDELAY
  2418.     debug(F100,"ttopen O_NDELAY","",0);
  2419.     if (fcntl(ttyfd, F_GETFL, 0) & O_NDELAY) {
  2420. debug(F100,"ttopen fcntl O_NDELAY","",0);
  2421. #ifndef aegis
  2422. if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY) < 0) {
  2423.     debug(F100,"ttopen fcntl failure to unset O_NDELAY","",0);
  2424.     perror("Can't unset O_NDELAY");
  2425. }
  2426. #endif /* aegis */
  2427. /* Some systems, notably Xenix (don't know how common this is in
  2428.  * other systems), need special treatment to get rid of the O_NDELAY
  2429.  * behaviour on read() with respect to carrier presence (i.e. read()
  2430.  * returning 0 when carrier absent), even though the above fcntl()
  2431.  * is enough to make read() wait for input when carrier is present.
  2432.  * This magic, in turn, requires CLOCAL for working when the carrier
  2433.  * is absent. But if xlocal == 0, presumably you already have CLOCAL
  2434.  * or you have a carrier, otherwise you wouldn't be running this.
  2435.  */
  2436. debug(F101,"ttopen xlocal","",xlocal);
  2437. #ifdef ATTSV
  2438. #ifdef BSD44ORPOSIX
  2439. #ifdef COMMENT /* 12 Aug 1997 */
  2440. #ifdef __bsdi__
  2441. if (xlocal)
  2442.   ttraw.c_cflag |= CLOCAL;
  2443. #else
  2444. #ifdef __FreeBSD__
  2445. if (xlocal)
  2446.   ttraw.c_cflag |= CLOCAL;
  2447. #endif /* __FreeBSD__ */
  2448. #endif /* __bsdi__ */
  2449. #else /* Not COMMENT */
  2450. #ifdef CLOCAL
  2451. if (xlocal) /* Unset this if it's defined. */
  2452.   ttraw.c_cflag |= CLOCAL;
  2453. #endif /* CLOCAL */
  2454. #endif /* COMMENT */
  2455. debug(F100,"ttopen calling POSIX tcseattr","",0);
  2456. if (tcsetattr(ttyfd, TCSADRAIN, &ttraw) < 0) {
  2457.     debug(F100,"ttopen POSIX tcseattr fails","",0);
  2458.     perror("tcsetattr");
  2459. }
  2460. #else /* !BSD44ORPOSIX */
  2461. if (xlocal) {
  2462.     ttraw.c_cflag |= CLOCAL;
  2463.     debug(F100,"ttopen calling ioctl(TCSETA)","",0);
  2464.     errno = 0;
  2465.     if (ioctl(ttyfd, TCSETA, &ttraw) < 0) {
  2466.                 debug(F101,"ttopen ioctl(TCSETA) fails","",errno);
  2467.                 perror("ioctl(TCSETA)");
  2468.             }
  2469. }
  2470. #endif /* BSD44ORPOSIX */
  2471. #endif /* ATTSV */
  2472. #ifndef NOCOTFMC /* = NO Close(Open()) To Force Mode Change */
  2473. /* Reportedly lets uugetty grab the device in SCO UNIX 3.2 / XENIX 2.3 */
  2474. debug(F100,"ttopen executing close/open","",0);
  2475. close( priv_opn(ttname, O_RDWR) ); /* Magic to force change. */
  2476. #endif /* NOCOTFMC */
  2477.     }
  2478. #endif /* O_NDELAY */
  2479. /* Instruct the system how to treat the carrier, and set a few other tty
  2480.  * parameters.
  2481.  *
  2482.  * This also undoes the temporary setting of CLOCAL that may have been done
  2483.  * for the close(open()) above (except in Xenix).  Also throw in ~ECHO, to
  2484.  * prevent the other end of the line from sitting there talking to itself,
  2485.  * producing garbage when the user performs a connect.
  2486.  *
  2487.  * SCO Xenix unfortunately seems to ignore the actual state of CLOCAL.
  2488.  * Now it thinks CLOCAL is always on. It seems the only real solution for
  2489.  * Xenix is to switch between the lower and upper case device names.
  2490.  *
  2491.  * This section may at some future time expand into setting a complete
  2492.  * collection of tty parameters, or call a function shared with ttpkt()/
  2493.  * ttvt() that does so.  On the other hand, the initial parameters are not
  2494.  * that important, since ttpkt() or ttvt() should always fix that before
  2495.  * any communication is done.  Well, we'll see...
  2496.  */
  2497.     if (xlocal) {
  2498.      curcarr = -2;
  2499. debug(F100,"ttopen calling carrctl","",0);
  2500. carrctl(&ttraw, ttcarr == CAR_ON);
  2501. debug(F100,"ttopen carrctl ok","",0);
  2502. #ifdef COHERENT
  2503. #define SVORPOSIX
  2504. #endif /* COHERENT */
  2505. #ifdef SVORPOSIX
  2506. ttraw.c_lflag &= ~ECHO;
  2507. ttold.c_lflag &= ~ECHO;
  2508. #ifdef BSD44ORPOSIX
  2509. y = tcsetattr(ttyfd, TCSADRAIN, &ttraw);
  2510. debug(F101,"ttopen tcsetattr","",y);
  2511. #else
  2512. y = ioctl(ttyfd, TCSETA, &ttraw);
  2513. debug(F100,"ttopen ioctl","",y);
  2514. #endif /* BSD44ORPOSIX */
  2515. #else /* BSD, etc */
  2516. ttraw.sg_flags &= ~ECHO;
  2517. ttold.sg_flags &= ~ECHO;
  2518. #ifdef BELLV10
  2519. y = ioctl(ttyfd,TIOCSETP,&ttraw);
  2520. debug(F100,"ttopen ioctl","",y);
  2521. #else
  2522. y = stty(ttyfd,&ttraw);
  2523. debug(F100,"ttopen stty","",y);
  2524. #endif /* BELLV10 */
  2525. #endif /* SVORPOSIX */
  2526. #ifdef COHERENT
  2527. #undef SVORPOSIX
  2528. #endif /* COHERENT */
  2529. /* ttflui(); */  /*  This fails for some reason.  */
  2530.     }
  2531.     /* Get current speed */
  2532. #ifndef BEBOX
  2533.     ttspeed = ttgspd();
  2534. #else
  2535.     ttspeed = 19200;
  2536. #endif /* !BEBOX */
  2537.     debug(F101,"ttopen ttspeed","",ttspeed);
  2538.     /* Done, make entries in debug log, restore Ctrl-C trap, and return. */
  2539.     debug(F101,"ttopen ttyfd","",ttyfd);
  2540.     debug(F101,"ttopen *lcl","",*lcl);
  2541.     debug(F111,"ttopen lock file",flfnam,lkf);
  2542.     signal(SIGINT,occt);
  2543.     sigint_ign = (occt == SIG_IGN) ? 1 : 0;
  2544.     return(0);
  2545. }
  2546. /*  D O _ O P E N  --  Do the right kind of open() call for the tty. */
  2547. int
  2548. do_open(ttname) char *ttname; {
  2549. #ifndef O_NDELAY /* O_NDELAY not defined */
  2550.     return(priv_opn(ttname,2));
  2551. #else /* O_NDELAY defined */
  2552. #ifdef ATT7300
  2553. /*
  2554.  Open comms line without waiting for carrier so initial call does not hang
  2555.  because state of "modem" is likely unknown at the initial call  -jrd.
  2556.  If this is needed for the getty stuff to work, and the open would not work
  2557.  without O_NDELAY when getty is still on, then this special case is ok.
  2558.  Otherwise, get rid of it. -ske
  2559. */
  2560.     return(priv_opn(ttname, O_RDWR | O_NDELAY));
  2561. #else /* !ATT7300 */
  2562.     /* Normal case. Use O_NDELAY according to SET CARRIER. See ttscarr(). */
  2563.     return(priv_opn(ttname, O_RDWR | ((ttcarr != CAR_ON) ? O_NDELAY : 0) ));
  2564. #endif /* !ATT7300 */
  2565. #endif /* O_NDELAY */
  2566. }
  2567. /*  T T C L O S  --  Close the TTY, releasing any lock.  */
  2568. static int ttc_state = 0; /* ttclose() state */
  2569. static char * ttc_nam[] = { "setup", "hangup", "reset", "close" };
  2570. int
  2571. ttclos(foo) int foo; { /* Arg req'd for signal() prototype */
  2572.     int xx, x = 0;
  2573.     debug(F101,"ttclos ttyfd","",ttyfd);
  2574.     debug(F101,"ttclos netconn","",netconn);
  2575.     debug(F101,"ttclos xlocal","",xlocal);
  2576. #ifdef NOFDZERO
  2577.     debug(F100,"ttclos NOFDZERO","",0);
  2578. #endif /* NOFDZERO */
  2579. #ifdef COMMENT
  2580. #ifdef TTLEBUF
  2581.     le_init(); /* No need for any of this */
  2582. #endif /* TTLEBUF */
  2583. #endif /* COMMENT */
  2584.     if (ttyfd < 0) /* Wasn't open. */
  2585.       return(0);
  2586.     if (ttfdflg) /* If we inherited ttyfd from */
  2587.       return(0); /* another process, don't close it. */
  2588.     tvtflg = 0; /* (some day get rid of this...) */
  2589. #ifdef IKSD
  2590.     if (inserver) {
  2591. #ifdef TNCODE
  2592.           tn_push();                    /* Place any waiting data into input*/
  2593.           tn_sopt(DO,TELOPT_LOGOUT);    /* Send LOGOUT option before close */
  2594.           TELOPT_UNANSWERED_DO(TELOPT_LOGOUT) = 1;
  2595.           tn_reset();                   /* The Reset Telnet Option table.  */
  2596. #endif /* TNCODE */
  2597. #ifdef CK_SSL
  2598.   if (ssl_active_flag) {
  2599.       if (ssl_debug_flag)
  2600. BIO_printf(bio_err,"calling SSL_shutdown(ssl)n");
  2601.       SSL_shutdown(ssl_con);
  2602.       SSL_free(ssl_con);
  2603.       ssl_con = NULL;
  2604.       ssl_active_flag = 0;
  2605.   }
  2606.   if (tls_active_flag) {
  2607.       if (ssl_debug_flag)
  2608. BIO_printf(bio_err,"calling SSL_shutdown(tls)n");
  2609.       SSL_shutdown(tls_con);
  2610.       SSL_free(tls_con);
  2611.       tls_con = NULL;
  2612.       tls_active_flag = 0;
  2613.   }
  2614. #endif /* CK_SSL */
  2615.     }
  2616. #endif /* IKSD */
  2617. #ifdef NETCMD
  2618.     if (ttpipe) { /* We've been using a pipe */
  2619. /* ttpipe = 0; */
  2620. if (ttpid > 0) {
  2621.     int wstat;
  2622. #ifdef OSF40
  2623.     union wait statusp_w;
  2624.     int statusp;
  2625. #else
  2626.     int statusp;
  2627. #endif /* OSF40 */
  2628.     close(fdin); /* Close these. */
  2629.     close(fdout);
  2630.     fdin = fdout = -1;
  2631.     kill(ttpid,1); /* Kill fork with SIGHUP */
  2632.     while (1) {
  2633. wstat = wait(
  2634. #ifdef OSF40
  2635.      &statusp_w
  2636. #else
  2637.      &statusp
  2638. #endif /* OSF40 */
  2639.      );
  2640. if (wstat == ttpid || wstat == -1)
  2641.   break;
  2642. #ifdef OSF40
  2643. statusp = (*(int *)&(statusp_w));
  2644. #endif /* OSF40 */
  2645. pexitstat = (statusp & 0xff) ? statusp : statusp >> 8;
  2646.     }
  2647.     ttpid = 0;
  2648. }
  2649. netconn = 0;
  2650. wasclosed = 1;
  2651. ttyfd = -1;
  2652. return(0);
  2653.     }
  2654. #endif /* NETCMD */
  2655. #ifdef NETPTY
  2656.     if (ttpty) {
  2657. #ifndef NODOPTY
  2658.         end_pty();
  2659. #endif /* NODOPTY */
  2660.         close(ttyfd);
  2661. netconn = 0;
  2662. wasclosed = 1;
  2663.         ttpty = 0;
  2664.         ttyfd = -1;
  2665.         return(0);
  2666.     }
  2667. #endif /* NETPTY */
  2668. #ifdef NETCONN
  2669.     if (netconn) { /* If it's a network connection. */
  2670. debug(F100,"ttclos closing net","",0);
  2671. netclos(); /* Let the network module close it. */
  2672. netconn = 0; /* No more network connection. */
  2673. debug(F101,"ttclos ttyfd after netclos","",ttyfd); /* Should be -1 */
  2674. return(0);
  2675.     }
  2676. #endif /* NETCONN */
  2677.     if (xlocal) { /* We're closing a SET LINE device */
  2678. #ifdef FT21 /* Fortune 2.1-specific items ... */
  2679. ioctl(ttyfd,TIOCHPCL, NULL);
  2680. #endif /* FT21 */
  2681. #ifdef ultrix /* Ultrix-specific items ... */
  2682. #ifdef TIOCSINUSE
  2683. /* Unset the INUSE flag that we set in ttopen() */
  2684. ioctl(ttyfd, TIOCSINUSE, NULL);
  2685. #endif /* TIOCSINUSE */
  2686. ioctl(ttyfd, TIOCNMODEM, &x);
  2687. #ifdef COMMENT
  2688. /* What was this? */
  2689. ioctl(ttyfd, TIOCNCAR, NULL);
  2690. #endif /* COMMENT */
  2691. #endif /* ultrix */
  2692. debug(F100,"ttclos about to call ttunlck","",0);
  2693.         if (ttunlck())                  /* Release uucp-style lock */
  2694.   fprintf(stderr,"Warning, problem releasing lockrn");
  2695.     }
  2696.     /* This is to prevent us from sticking in tthang() or close(). */
  2697. #ifdef O_NDELAY
  2698. #ifndef aegis
  2699.     if (ttyfd > 0) { /* But skip it on stdin. */
  2700. debug(F100,"ttclos setting O_NDELAY","",0);
  2701. x = fcntl(ttyfd,F_SETFL,fcntl(ttyfd,F_GETFL, 0)|O_NDELAY);
  2702. #ifdef DEBUG
  2703. if (deblog && x == -1) {
  2704.     perror("Warning - Can't set O_NDELAY");
  2705.     debug(F101,"ttclos fcntl failure to set O_NDELAY","",x);
  2706. }
  2707. #endif /* DEBUG */
  2708.     }
  2709. #endif /* aegis */
  2710. #endif /* O_NDELAY */
  2711.     x = 0;
  2712.     ttc_state = 0;
  2713.     if (xlocal
  2714. #ifdef NOFDZERO
  2715. || ttyfd > 0
  2716. #endif /* NOFDZERO */
  2717. ) {
  2718. saval = signal(SIGALRM,xtimerh); /* Enable timer interrupt. */
  2719. xx = alarm(8); /* Allow 8 seconds. */
  2720. debug(F101,"ttclos alarm","",xx);
  2721. if (
  2722. #ifdef CK_POSIX_SIG
  2723.     sigsetjmp(sjbuf,1)
  2724. #else
  2725.     setjmp(sjbuf)
  2726. #endif /* CK_POSIX_SIG */
  2727.     ) { /* Timer went off? */
  2728.     x = -1;
  2729. #ifdef DEBUG
  2730.     debug(F111,"ttclos ALARM TRAP errno",ckitoa(ttc_state),errno);
  2731.     printf("ttclos() timeout: %sn", ttc_nam[ttc_state]);
  2732. #endif /* DEBUG */
  2733. }
  2734. errno = 0;
  2735. debug(F101,"ttclos A","",ttc_state);
  2736. if (ttc_state < 1) {
  2737.     ttc_state = 1;
  2738.     alarm(8); /* Re-arm the timer */
  2739.     debug(F101,"ttclos calling tthang()","",x);
  2740.     x = tthang(); /* Hang up first, then... */
  2741.     debug(F101,"ttclos tthang()","",x);
  2742. }
  2743. debug(F101,"ttclos B","",ttc_state);
  2744. if (ttc_state < 2) {
  2745.     ttc_state = 2;
  2746.     debug(F101,"ttclos calling ttres()","",x);
  2747.     alarm(8); /* Re-arm the timer */
  2748.     x = ttres(); /* Reset device modes. */
  2749.     debug(F101,"ttclos ttres()","",x);
  2750. }
  2751. debug(F101,"ttclos C","",ttc_state);
  2752. if (ttc_state < 3) {
  2753.     ttc_state = 3;
  2754.     errno = 0;
  2755.     debug(F101,"ttclos calling close","",x);
  2756.     alarm(8); /* Re-arm the timer */
  2757.     x = close(ttyfd); /* Close the device. */
  2758.     debug(F101,"ttclos close()","",x);
  2759. }
  2760. debug(F101,"ttclos D","",ttc_state);
  2761. ttimoff(); /* Turn off timer. */
  2762. if (x < 0) {
  2763.     printf("?WARNING - close failed: %sn",ttnmsv);
  2764. #ifdef DEBUG
  2765.     if (deblog) {
  2766. printf("errno = %dn", errno);
  2767. debug(F101,"ttclos failed","",errno);
  2768.     }
  2769. #endif /* DEBUG */
  2770. }
  2771.     }
  2772. /* For bidirectional lines, restore getty if it was there before. */
  2773. #ifdef ACUCNTRL /* 4.3BSD acucntrl() method. */
  2774.     if (xlocal) {
  2775. debug(F100,"ttclos ACUCNTRL","",0);
  2776. acucntrl("enable",ttnmsv); /* Enable getty on the device. */
  2777.     }
  2778. #else
  2779. #ifdef ATT7300 /* ATT UNIX PC (3B1, 7300) method. */
  2780.     if (xlocal) {
  2781. debug(F100,"ttclos ATT7300 ongetty","",0);
  2782. if (attmodem & DOGETY) /* Was getty(1m) running before us? */
  2783.   ongetty(ttnmsv); /* Yes, restart getty on tty line */
  2784. attmodem &= ~DOGETY; /* No phone in use, getty restored */
  2785.     }
  2786. #endif /* ATT7300 */
  2787. #endif /* System-dependent getty-restoring methods */
  2788. #ifdef sony_news
  2789.     km_ext = -1; /* Invalidate device's Kanji-mode */
  2790. #endif /* sony_news */
  2791.     ttyfd = -1;                         /* Invalidate the file descriptor. */
  2792.     wasclosed = 1;
  2793.     debug(F100,"ttclos done","",0);
  2794.     return(0);
  2795. }
  2796. /*  T T H A N G  --  Hangup phone line or network connection.  */
  2797. /*
  2798.   Returns:
  2799.   0 if it does nothing.
  2800.   1 if it believes that it hung up successfully.
  2801.  -1 if it believes that the hangup attempt failed.
  2802. */
  2803. #define HUPTIME 500 /* Milliseconds for hangup */
  2804. /* Define HUP_POSIX to force non-POSIX builds to use the POSIX hangup method */
  2805. #ifdef UNIXWARE /* Such as Unixware 1.x, 2.x */
  2806. #ifndef POSIX
  2807. #ifndef HUP_POSIX
  2808. #define HUP_POSIX
  2809. #endif /* HUP_POSIX */
  2810. #endif /* POSIX */
  2811. #endif /* UNIXWARE */
  2812. int
  2813. tthang() {
  2814. #ifdef NOLOCAL
  2815.     return(0);
  2816. #else
  2817.     int x = 0; /* Sometimes used as return code. */
  2818. #ifndef POSIX
  2819.     int z; /* worker */
  2820. #endif /* POSIX */
  2821. #ifdef COHERENT
  2822. #define SVORPOSIX
  2823. #endif /* COHERENT */
  2824. #ifdef SVORPOSIX /* AT&T, POSIX, HPUX declarations. */
  2825.     int spdsav; /* for saving speed */
  2826. #ifdef HUP_POSIX
  2827.     int spdsavi;
  2828. #else
  2829. #ifdef BSD44ORPOSIX
  2830.     int spdsavi;
  2831. #endif /* BSD44ORPOSIX */
  2832. #endif /* HUP_POSIX */
  2833. #ifdef HPUX
  2834. /*
  2835.   Early versions of HP-UX omitted the mflag typedef.  If you get complaints
  2836.   about it, just change it to long (or better still, unsigned long).
  2837. */
  2838.     mflag
  2839.       dtr_down = 00000000000,
  2840.       modem_rtn,
  2841.       modem_sav;
  2842.     char modem_state[64];
  2843. #endif /* HPUX */
  2844.     int flags; /* fcntl flags */
  2845.     unsigned short ttc_save;
  2846. #endif /* SVORPOSIX */
  2847. #ifdef COHERENT
  2848. #undef SVORPOSIX
  2849. #endif /* COHERENT */
  2850.     if (ttyfd < 0) return(0);           /* Don't do this if not open  */
  2851.     if (xlocal < 1) return(0); /* Don't do this if not local */
  2852. #ifdef NETCMD
  2853.     if (ttpipe)
  2854.       return((ttclos(0) < 0) ? -1 : 1);
  2855. #endif /* NETCMD */
  2856. #ifdef NETPTY
  2857.     if (ttpty)
  2858.       return((ttclos(0) < 0) ? -1 : 1);
  2859. #endif /* NETPTY */
  2860. #ifdef NETCONN
  2861.     if (netconn) /* Network connection. */
  2862.       return((netclos() < 0) ? -1 : 1); /* Just close it. */
  2863. #endif /* NETCONN */
  2864. /* From here down, we handle real tty devices. */
  2865. #ifdef HUP_POSIX
  2866. /*
  2867.   e.g. for Unixware 2, where we don't have a full POSIX build, we
  2868.   still have to use POSIX-style hangup.  Thus the duplication of this
  2869.   and the next case, the only difference being we use a local termios
  2870.   struct here, since a different model is used elsewhere.
  2871. */
  2872.     {
  2873. struct termios ttcur;
  2874. int x;
  2875. debug(F100,"tthang HUP_POSIX style","",0);
  2876. x = tcgetattr(ttyfd, &ttcur); /* Get current attributes */
  2877. debug(F111,"tthang tcgetattr",ckitoa(errno),x);
  2878. if (x < 0) return(-1);
  2879. spdsav = cfgetospeed(&ttcur); /* Get current speed */
  2880. debug(F111,"tthang cfgetospeed",ckitoa(errno),spdsav);
  2881. spdsavi = cfgetispeed(&ttcur); /* Get current speed */
  2882. debug(F111,"tthang cfgetispeed",ckitoa(errno),spdsavi);
  2883. x = cfsetospeed(&ttcur,B0); /* Replace by 0 */
  2884. debug(F111,"tthang cfsetospeed",ckitoa(errno),x);
  2885. if (x < 0) return(-1);
  2886. x = cfsetispeed(&ttcur,B0);
  2887. debug(F111,"tthang cfsetispeed",ckitoa(errno),x);
  2888. if (x < 0) return(-1);
  2889. x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
  2890. debug(F111,"tthang tcsetattr B0",ckitoa(errno),x);
  2891. if (x < 0) return(-1);
  2892. msleep(HUPTIME); /* Sleep 0.5 sec */
  2893. x = cfsetospeed(&ttcur,spdsav); /* Restore prev speed */
  2894. if (x < 0) return(-1);
  2895. debug(F111,"tthang cfsetospeed prev",ckitoa(errno),x);
  2896. x = cfsetispeed(&ttcur,spdsavi);
  2897. debug(F111,"tthang cfsetispeed prev",ckitoa(errno),x);
  2898. if (x < 0) return(-1);
  2899. x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
  2900. debug(F111,"tthang tcsetattr restore",ckitoa(errno),x);
  2901. if (x < 0) return(-1);
  2902. return(1);
  2903.     }
  2904. #else
  2905. #ifdef BSD44ORPOSIX
  2906. /*
  2907.   NOTE: This should work for QNX too, but in case it doesn't, it is also
  2908.   possible to toggle DTR using qnx_ioctl(ttyfd,QCTL_DEV_CTL,&new,&old);
  2909.   see <sys/qioctl.h> and QNX News V10, Sep 96, p44.
  2910.   Newer versions of QNX also have a tcdropline(howlong) function.
  2911. */
  2912.     {
  2913. int x;
  2914. debug(F100,"tthang POSIX style","",0);
  2915. x = tcgetattr(ttyfd, &ttcur); /* Get current attributes */
  2916. debug(F111,"tthang tcgetattr",ckitoa(errno),x);
  2917. if (x < 0) return(-1);
  2918. spdsav = cfgetospeed(&ttcur); /* Get current speed */
  2919. debug(F111,"tthang cfgetospeed",ckitoa(errno),spdsav);
  2920. spdsavi = cfgetispeed(&ttcur); /* Get current speed */
  2921. debug(F111,"tthang cfgetispeed",ckitoa(errno),spdsavi);
  2922. x = cfsetospeed(&ttcur,B0); /* Replace by 0 */
  2923. debug(F111,"tthang cfsetospeed",ckitoa(errno),x);
  2924. if (x < 0) return(-1);
  2925. x = cfsetispeed(&ttcur,B0);
  2926. debug(F111,"tthang cfsetispeed",ckitoa(errno),x);
  2927. if (x < 0) return(-1);
  2928. x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
  2929. debug(F111,"tthang tcsetattr B0",ckitoa(errno),x);
  2930. if (x < 0) return(-1);
  2931. msleep(HUPTIME); /* Sleep 0.5 sec */
  2932. x = cfsetospeed(&ttcur,spdsav); /* Restore prev speed */
  2933. if (x < 0) return(-1);
  2934. debug(F111,"tthang cfsetospeed prev",ckitoa(errno),x);
  2935. x = cfsetispeed(&ttcur,spdsavi);
  2936. debug(F111,"tthang cfsetispeed prev",ckitoa(errno),x);
  2937. if (x < 0) return(-1);
  2938. x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
  2939. debug(F111,"tthang tcsetattr restore",ckitoa(errno),x);
  2940. if (x < 0) return(-1);
  2941. return(1);
  2942.     }
  2943. #else /* BSD44ORPOSIX */
  2944. #ifdef aegis /* Apollo Aegis */
  2945.     sio_$control((short)ttyfd, sio_$dtr, false, st);    /* DTR down */
  2946.     msleep(HUPTIME); /* pause */
  2947.     sio_$control((short)ttyfd, sio_$dtr, true,  st);    /* DTR up */
  2948.     return(1);
  2949. #endif /* aegis */
  2950. #ifdef ANYBSD /* Any BSD version. */
  2951. #ifdef TIOCCDTR /* Except those that don't have this */
  2952.     debug(F100,"tthang BSD style","",0);
  2953.     if (ioctl(ttyfd,TIOCCDTR,0) < 0) { /* Clear DTR. */
  2954. debug(F101,"tthang TIOCCDTR fails","",errno);
  2955. return(-1);
  2956.     }
  2957.     msleep(HUPTIME); /* For about 1/2 sec */
  2958.     errno = 0;
  2959.     x = ioctl(ttyfd,TIOCSDTR,0); /* Restore DTR */
  2960.     if (x < 0) {
  2961. /*
  2962.   For some reason, this tends to fail with "no such device or address"
  2963.   but the operation still works, probably because of the close/open
  2964.   later on.  So let's not scare the user unnecessarily here.
  2965. */
  2966. debug(F101,"tthang TIOCSDTR errno","",errno); /* Log the error */
  2967. x = 1; /* Pretend we succeeded */
  2968.     } else if (x == 0) x = 1; /* Success */
  2969. #ifdef COMMENT
  2970. #ifdef FT21
  2971.     ioctl(ttyfd, TIOCSAVEMODES, 0);
  2972.     ioctl(ttyfd, TIOCHPCL, 0);
  2973.     close(ttyfd); /* Yes, must do this twice */
  2974.     if ((ttyfd = open(ttnmsv,2)) < 0) /* on Fortune computers... */
  2975.       return(-1); /* (but why?) */
  2976.     else x = 1;
  2977. #endif /* FT21 */
  2978. #endif /* COMMENT */
  2979. #endif /* TIOCCDTR */
  2980.     close(do_open(ttnmsv)); /* Clear i/o error condition */
  2981.     errno = 0;
  2982. #ifdef COMMENT
  2983. /* This is definitely dangerous.  Why was it here? */
  2984.     z = ttvt(ttspeed,ttflow); /* Restore modes. */
  2985.     debug(F101,"tthang ttvt returns","",z);
  2986.     return(z < 0 ? -1 : 1);
  2987. #else
  2988.     return(x);
  2989. #endif /* COMMENT */
  2990. #endif /* ANYBSD */
  2991. #ifdef ATTSV
  2992. /* AT&T UNIX section, includes HP-UX and generic AT&T System III/V... */
  2993. #ifdef HPUX
  2994. /* Hewlett Packard allows explicit manipulation of modem signals. */
  2995. #ifdef COMMENT
  2996. /* Old way... */
  2997.     debug(F100,"tthang HP-UX style","",0);
  2998.     if (ioctl(ttyfd,MCSETAF,&dtr_down) < 0)        /* lower DTR */
  2999.       return(-1);                 /* oops, can't. */
  3000.     msleep(HUPTIME);            /* Pause half a second. */
  3001.     x = 1;            /* Set return code */
  3002.     if (ioctl(ttyfd,MCGETA,&modem_rtn) > -1) {     /* Get line status. */
  3003. if ((modem_rtn & MDCD) != 0)          /* Check if CD is low. */
  3004.   x = -1;                                  /* CD didn't drop, fail. */
  3005.     } else x = -1;
  3006.     /* Even if above calls fail, RTS & DTR should be turned back on. */
  3007.     modem_rtn = MRTS | MDTR;
  3008.     if (ioctl(ttyfd,MCSETAF,&modem_rtn) < 0) x = -1;
  3009.     return(x);
  3010. #else
  3011. /* New way, from Hellmuth Michaelis */
  3012.     debug(F100,"tthang HP-UX style, HPUXDEBUG","",0);
  3013.     if (ioctl(ttyfd,MCGETA,&modem_rtn) == -1) { /* Get current status. */
  3014. debug(F100,"tthang HP-UX: can't get modem lines, NO HANGUP!","",0);
  3015. return(-1);
  3016.     }
  3017.     sprintf(modem_state,"%#lx",modem_rtn);
  3018.     debug(F110,"tthang HP-UX: modem lines = ",modem_state,0);
  3019.     modem_sav = modem_rtn; /* Save current modem signals */
  3020.     modem_rtn &= ~MDTR; /* Turn DTR bit off */
  3021.     sprintf(modem_state,"%#lx",modem_rtn);
  3022.     debug(F110,"tthang HP-UX: DTR down = ",modem_state,0);
  3023.     if (ioctl(ttyfd,MCSETAF,&modem_rtn) < 0) { /* lower DTR */
  3024. debug(F100,"tthang HP-UX: can't lower DTR!","",0);
  3025. return(-1); /* oops, can't. */
  3026.     }
  3027.     msleep(HUPTIME); /* Pause half a second. */
  3028.     x = 1; /* Set return code */
  3029.     if (ioctl(ttyfd,MCGETA,&modem_rtn) > -1) { /* Get line status. */
  3030. sprintf(modem_state,"%#lx",modem_rtn);
  3031. debug(F110,"tthang HP-UX: modem lines got = ",modem_state,0);
  3032. if ((modem_rtn & MDCD) != 0) { /* Check if CD is low. */
  3033.     debug(F100,"tthang HP-UX: DCD not down","",0);
  3034.     x = -1; /* CD didn't drop, fail. */
  3035. } else {
  3036.     debug(F100,"tthang HP-UX: DCD down","",0);
  3037. }
  3038.     } else {
  3039. x = -1;
  3040. debug(F100,"tthang HP-UX: can't get DCD status !","",0);
  3041.     }
  3042.     /* Even if above calls fail, DTR should be turned back on. */
  3043.     modem_sav |= MDTR;
  3044.     if (ioctl(ttyfd,MCSETAF,&modem_sav) < 0) {
  3045. x = -1;
  3046. debug(F100,"tthang HP-UX: can't set saved state","",0);
  3047.     } else {
  3048. sprintf(modem_state,"%#lx",modem_sav);
  3049. debug(F110,"tthang HP-UX: final modem lines = ",modem_state,0);
  3050.     }
  3051.     return(x);
  3052. #endif /* COMMENT */
  3053. #else /* AT&T but not HP-UX */
  3054. /* SVID for AT&T System V R3 defines ioctl's for handling modem signals. */
  3055. /* It is not known how many, if any, systems actually implement them, */
  3056. /* so we include them here in ifdef's. */
  3057. /*
  3058.   Unixware has the TIOCMxxx symbols defined, but calling ioctl() with them
  3059.   gives error 22 (invalid argument).
  3060. */
  3061. #ifndef _IBMR2
  3062. /*
  3063.   No modem-signal twiddling for IBM RT PC or RS/6000.
  3064.   In AIX 3.1 and earlier, the ioctl() call is broken.
  3065.   This code could be activated for AIX 3.1 with PTF 2006 or later
  3066.   (e.g. AIX 3.2), but close/open does the job too, so why bother.
  3067. */
  3068. #ifdef TIOCMBIS /* Bit Set */
  3069. #ifdef TIOCMBIC /* Bit Clear */
  3070. #ifdef TIOCM_DTR /* DTR */
  3071. /* Clear DTR, sleep 300 msec, turn it back on. */
  3072. /* If any of the ioctl's return failure, go on to the next section. */
  3073.     z = TIOCM_DTR; /* Code for DTR. */
  3074. #ifdef COMMENT
  3075. /*
  3076.   This was the cause of the troubles with the Solaris Port Monitor.
  3077.   The problem is: RTS never comes back on.  Moral: Don't do it!
  3078.   (But why doesn't it come back on?  See the TIOCMBIS call...)
  3079. */
  3080. #ifdef TIOCM_RTS /* Lower RTS too if symbol is known. */
  3081.     z |= TIOCM_RTS;
  3082. #endif /* TIOCM_RTS */
  3083. #endif /* COMMENT */
  3084.     debug(F101,"tthang TIOCM signal mask","",z);
  3085.     if (ioctl(ttyfd,TIOCMBIC,&z) > -1) {   /* Try to lower DTR. */
  3086. debug(F100,"tthang TIOCMBIC ok","",0);
  3087. msleep(HUPTIME);    /* Pause half a second. */
  3088. if (ioctl(ttyfd,TIOCMBIS,&z) > -1) { /* Try to turn it back on. */
  3089.     debug(F100,"tthang TIOCMBIS ok","",0);
  3090. #ifndef CLSOPN
  3091.     return(1); /* Success, done. */
  3092. #endif /* CLSOPN */
  3093. } else { /* Couldn't raise, continue. */
  3094.     debug(F101,"tthang TIOCMBIS errno","",errno);
  3095. }
  3096.     } else { /* Couldn't lower, continue. */
  3097.   debug(F101,"tthang TIOCMBIC errno","",errno);
  3098.     }
  3099. #endif /* TIOCM_DTR */
  3100. #endif /* TIOCMBIC */
  3101. #endif /* TIOCMBIS */
  3102. #endif /* _IBMR2 */
  3103. /*
  3104.   General AT&T UNIX case, not HPUX.  The following code is highly suspect.  No
  3105.   two AT&T-based systems seem to do this the same way.  The object is simply
  3106.   to turn off DTR and then turn it back on.  SVID says the universal method
  3107.   for turning off DTR is to set the speed to zero, and this does seem to do
  3108.   the trick in all cases.  But neither SVID nor any known man pages say how to
  3109.   turn DTR back on again.  Some variants, like most Xenix implementations,
  3110.   raise DTR again when the speed is restored to a nonzero value.  Others
  3111.   require the device to be closed and opened again, but this is risky because
  3112.   getty could seize the device during the instant it is closed.
  3113. */
  3114. /* Return code for ioctl failures... */
  3115. #ifdef ATT6300
  3116.     x = 1; /* ATT6300 doesn't want to fail... */
  3117. #else
  3118.     x = -1;
  3119. #endif /* ATT6300 */
  3120.     debug(F100,"tthang get settings","",0);
  3121.     if (ioctl(ttyfd,TCGETA,&ttcur) < 0) /* Get current settings. */
  3122.       return(x); /* Fail if this doesn't work. */
  3123.     if ((flags = fcntl(ttyfd,F_GETFL,0)) < 0) /* Get device flags. */
  3124.       return(x);
  3125.     ttc_save = ttcur.c_cflag; /* Remember current speed. */
  3126.     spdsav = ttc_save & CBAUD;
  3127.     debug(F101,"tthang speed","",spdsav);
  3128. #ifdef O_NDELAY
  3129.     debug(F100,"tthang turning O_NDELAY on","",0);
  3130.     fcntl(ttyfd, F_SETFL, flags | O_NDELAY); /* Activate O_NDELAY */
  3131. #endif /* O_NDELAY */
  3132. #ifdef ATT7300 /* This is the way it is SUPPOSED to work */
  3133.     ttcur.c_cflag &= ~CBAUD; /* Change the speed to zero.  */
  3134. #else
  3135. #ifdef RTAIX
  3136.     ttcur.c_cflag &= ~CBAUD; /* Change the speed to zero.  */
  3137. #else          /* This way really works but may be dangerous */
  3138. #ifdef u3b2
  3139.     ttcur.c_cflag = ~(CBAUD|CLOCAL); /* Special for AT&T 3B2s */
  3140. /* (CLOCAL must be OFF) */
  3141. #else
  3142. #ifdef SCO3R2 /* SCO UNIX 3.2 */
  3143. /*
  3144.   This is complete nonsense, but an SCO user claimed this change made
  3145.   hanging up work.  Comments from other SCO UNIX 3.2 users would be
  3146.   appreciated.
  3147. */
  3148.     ttcur.c_cflag = CBAUD|B0;
  3149. #else
  3150. #ifdef AIXRS /* AIX on RS/6000 */
  3151. /*
  3152.   Can't set speed to zero on AIX 3.1 on RS/6000 64-port adapter,
  3153.   even though you can do it on the built-in port and the 8- and 16-port
  3154.   adapters.  (Untested on 128-port adapter.)
  3155. */
  3156.     ttcur.c_cflag = CLOCAL|HUPCL|spdsav; /* Speed 0 causes EINVAL */
  3157. #else /* None of the above */
  3158. /*
  3159.   Set everything, including the speed, to zero, except for the CLOCAL
  3160.   and HUPCL bits.
  3161. */
  3162.     ttcur.c_cflag = CLOCAL|HUPCL;
  3163. #endif /* AIXRS */
  3164. #endif /* SCO3R2 */
  3165. #endif /* u3b2 */
  3166. #endif /* RTAIX */
  3167. #endif /* ATT7300 */
  3168. #ifdef COMMENT
  3169.     /* and if none of those work, try one of these... */
  3170.     ttcur.c_cflag = 0;
  3171.     ttcur.c_cflag = CLOCAL;
  3172.     ttcur.c_cflag &= ~(CBAUD|HUPCL);
  3173.     ttcur.c_cflag &= ~(CBAUD|CREAD);
  3174.     ttcur.c_cflag &= ~(CBAUD|CREAD|HUPCL);
  3175.     /* or other combinations */
  3176. #endif /* COMMENT */
  3177. #ifdef TCXONC
  3178.     debug(F100,"tthang TCXONC","",0);
  3179.     if (ioctl(ttyfd, TCXONC, 1) < 0) {
  3180. debug(F101,"tthang TCXONC failed","",errno);
  3181.     }
  3182. #endif /* TCXONC */
  3183. #ifdef TIOCSTART
  3184.     debug(F100,"tthang TIOCSTART","",0);
  3185.     if (ioctl(ttyfd, TIOCSTART, 0) < 0) {
  3186. debug(F101,"tthang TIOCSTART failed","",errno);
  3187.     }
  3188. #endif /* TIOCSTART */
  3189.     if (ioctl(ttyfd,TCSETAF,&ttcur) < 0) { /* Fail if we can't. */
  3190. debug(F101,"tthang TCSETAF failed","",errno);
  3191. fcntl(ttyfd, F_SETFL, flags); /* Restore flags */
  3192. return(-1); /* before returning. */
  3193.     }
  3194.     msleep(300); /* Give modem time to notice. */
  3195. #ifndef NOCOTFMC
  3196. /* Now, even though it doesn't say this in SVID or any man page, we have */
  3197. /* to close and reopen the device.  This is not necessary for all systems, */
  3198. /* but it's impossible to predict which ones need it and which ones don't. */
  3199. #ifdef ATT7300
  3200. /*
  3201.   Special handling for ATT 7300 UNIX PC and 3B1, which have "phone"
  3202.   related ioctl's for their internal modems.  attmodem has getty status and
  3203.   modem-in-use bit.  Reportedly the ATT7300/3B1 PIOCDISC call is necessary,
  3204.   but also ruins the file descriptor, and no other phone(7) ioctl call can fix
  3205.   it.  Whateverit does, it seems to escape detection with PIOCGETA and TCGETA.
  3206.   The only way to undo the damage is to close the fd and then reopen it.
  3207. */
  3208.     if (attmodem & ISMODEM) {
  3209. debug(F100,"tthang attmodem close/open","",0);
  3210. ioctl(ttyfd,PIOCUNHOLD,&dialer); /* Return call to handset. */
  3211. ioctl(ttyfd,PIOCDISC,&dialer); /* Disconnect phone. */
  3212. close(ttyfd); /* Close and reopen the fd. */
  3213. ttyfd = priv_opn(ttnmsv, O_RDWR | O_NDELAY);
  3214. attmodem &= ~ISMODEM; /* Phone no longer in use. */
  3215.     }
  3216. #else /* !ATT7300 */
  3217. /* It seems we have to close and open the device for other AT&T systems */
  3218. /* too, and this is the place to do it.  The following code does the */
  3219. /* famous close(open(...)) magic by default.  If that doesn't work for you, */
  3220. /* then try uncommenting the following statement or putting -DCLSOPN in */
  3221. /* the makefile CFLAGS. */
  3222. /* #define CLSOPN */
  3223. #ifndef SCO32 /* Not needed by, and harmful to, SCO UNIX 3.2 / Xenix 2.3 */
  3224. #ifdef O_NDELAY
  3225. #define OPENFLGS O_RDWR | O_NDELAY
  3226. #else
  3227. #define OPENFLGS O_RDWR
  3228. #endif
  3229. #ifndef CLSOPN
  3230. /* This method is used by default, i.e. unless CLSOPN is defined. */
  3231. /* It is thought to be safer because there is no window where getty */
  3232. /* can seize control of the device.  The drawback is that it might not work. */
  3233.     debug(F101,"tthang close(open()), OPENFLGS","",OPENFLGS);
  3234.     close(priv_opn(ttnmsv, OPENFLGS));
  3235. #else
  3236. /* This method is used if you #define CLSOPN.  It is more likely to work */
  3237. /* than the previous method, but it's also more dangerous. */
  3238.     debug(F101,"tthang close/open, OPENFLGS","",OPENFLGS);
  3239.     close(ttyfd);
  3240.     msleep(10);
  3241.     ttyfd = priv_opn(ttnmsv, OPENFLGS); /* Open it again */
  3242. #endif /* CLSOPN */
  3243. #undef OPENFLGS
  3244. #endif /* SCO32 */
  3245. #endif /* ATT7300 */
  3246. #endif /* NOCOTFMC */
  3247. /* Now put all flags & modes back the way we found them. */
  3248. /* (Does the order of ioctl & fcntl matter ? ) */
  3249.     debug(F100,"tthang restore settings","",0);
  3250.     ttcur.c_cflag = ttc_save; /* Get old speed back. */
  3251.     if (ioctl(ttyfd,TCSETAF,&ttcur) < 0) /* ioctl parameters. */
  3252.       return(-1);
  3253. #ifdef O_NDELAY
  3254. /*
  3255.   This is required for IBM RT and RS/6000, probably helps elsewhere too (?).
  3256.   After closing a modem line, the modem will probably not be asserting
  3257.   carrier any more, so we should not require carrier any more.  If this
  3258.   causes trouble on non-IBM UNIXes, change the #ifdef to use _IBMR2 rather
  3259.   than O_NDELAY.
  3260. */
  3261.     flags &= ~O_NDELAY; /* Don't require carrier on reopen */
  3262. #endif /* O_NDELAY */
  3263.     if (fcntl(ttyfd,F_SETFL,flags) < 0) /* fcntl parameters */
  3264.       return(-1);
  3265.     return(1);
  3266. #endif /* not HPUX */
  3267. #endif /* ATTSV */
  3268. #endif /* BSD44ORPOSIX */
  3269. #endif /* HUP_POSIX */
  3270. #endif /* NOLOCAL */
  3271. }
  3272. /*
  3273.   Major change in 5A(174).  We used to use LPASS8, if it was defined, to
  3274.   allow 8-bit data and Xon/Xoff flow control at the same time.  But this
  3275.   LPASS8 business seems to have been causing trouble for everybody but me!
  3276.   For example, Annex terminal servers, commonly used with Encore computers,
  3277.   do not support LPASS8 even though the Encore itself does.  Ditto for many
  3278.   other terminal servers, TELNET connections, rlogin connections, etc etc.
  3279.   Now, reportedly, even vanilla 4.3 BSD systems can't do this right on their
  3280.   serial lines, even though LPASS8 is a feature of 4.3BSD.  So let's turn it
  3281.   off for everybody.  That means we goes back to using raw mode, with no
  3282.   flow control.  Phooey.
  3283.   NOTE: This must be done before the first reference to LPASS8 in this file,
  3284.   and after the last #include statment.
  3285. */
  3286. #ifdef LPASS8
  3287. #undef LPASS8
  3288. #endif /* LPASS8 */
  3289. /*  T T R E S  --  Restore terminal to "normal" mode.  */
  3290. /* ske@pkmab.se: There are two choices for what this function should do.
  3291.  * (1) Restore the tty to current "normal" mode, with carrier treatment
  3292.  * according to ttcarr, to be used after every kermit command. (2) Restore
  3293.  * the tty to the state it was in before kermit opened it. These choices
  3294.  * conflict, since ttold can't hold both choices of tty parameters.  ttres()
  3295.  * is currently being called as in choice (1), but ttold basically holds
  3296.  * the initial parameters, as in (2), and the description at the beginning
  3297.  * of this file says (2).
  3298.  *
  3299.  * I don't think restoring tty parameters after all kermit commands makes
  3300.  * much of a difference.  Restoring them upon exit from kermit may be of
  3301.  * some use in some cases (when the line is not restored automatically on
  3302.  * close, by the operating system).
  3303.  *
  3304.  * I can't choose which one it should be, so I haven't changed it. It
  3305.  * probably works as it is, too. It would probably even work even with
  3306.  * ttres() entirely deleted...
  3307.  *
  3308.  * (from fdc: Actually, this function operates in remote mode too, so
  3309.  * it restores the console (command) terminal to whatever mode it was
  3310.  * in before packet operations began, so that commands work right again.)
  3311.  */
  3312. int
  3313. ttres() {                               /* Restore the tty to normal. */
  3314.     int x;
  3315.     if (ttyfd < 0) return(-1);          /* Not open. */
  3316.     if (ttfdflg) return(0); /* Don't mess with terminal modes if */
  3317. /* we got ttyfd from another process */
  3318. #ifdef NETCONN
  3319.     if (netconn) { /* Network connection */
  3320.         tvtflg = 0;
  3321. #ifdef TCPSOCKET
  3322. #ifdef TCP_NODELAY
  3323.         {
  3324.     extern int tcp_nodelay; /* Just put this back if necessary */
  3325.     if (ttnet == NET_TCPB) {
  3326. if (nodelay_sav > -1) {
  3327.     no_delay(nodelay_sav);
  3328.     nodelay_sav = -1;
  3329. }
  3330.     }
  3331.         }
  3332. #endif /* TCP_NODELAY */
  3333. #endif /* TCPSOCKET */
  3334. return(0);
  3335.     }
  3336. #endif /* NETCONN */
  3337. #ifdef NETCMD
  3338.     if (ttpipe) return(0);
  3339. #endif /* NETCMD */
  3340. #ifdef NETPTY
  3341.     if (ttpty) return(0);
  3342. #endif /* NETPTY */
  3343. /* Real terminal device, so restore its original modes */
  3344. #ifdef BSD44ORPOSIX /* For POSIX like this */
  3345.     debug(F100,"ttres BSD44ORPOSIX","",0);
  3346.     x = tcsetattr(ttyfd,TCSADRAIN,&ttold);
  3347. #else /* For all others... */
  3348. #ifdef ATTSV                            /* For AT&T versions... */
  3349.     debug(F100,"ttres ATTSV","",0);
  3350.     x = ioctl(ttyfd,TCSETAW,&ttold); /* Restore tty modes this way. */
  3351. #else
  3352. /* Here we restore the modes for BSD */
  3353. #ifdef LPASS8 /* Undo "pass8" if it were done */
  3354.     if (lmodef) {
  3355. if (ioctl(ttyfd,TIOCLSET,&lmode) < 0)
  3356.   debug(F100,"ttres TIOCLSET failed","",0);
  3357. else
  3358.   debug(F100,"ttres TIOCLSET ok","",0);
  3359.     }
  3360. #endif /* LPASS8 */
  3361. #ifdef CK_DTRCTS    /* Undo hardware flow if it were done */
  3362.     if (lmodef) {
  3363.   if (ioctl(ttyfd,TIOCLSET,&lmode) < 0)
  3364.     debug(F100,"ttres TIOCLSET failed","",0);
  3365.   else
  3366.     debug(F100,"ttres TIOCLSET ok","",0);
  3367.     }
  3368. #endif /* CK_DTRCTS */
  3369. #ifdef TIOCGETC /* Put back special characters */
  3370.     if (tcharf && (xlocal == 0)) {
  3371. if (ioctl(ttyfd,TIOCSETC,&tchold) < 0)
  3372.   debug(F100,"ttres TIOCSETC failed","",0);
  3373. else
  3374.   debug(F100,"ttres TIOCSETC ok","",0);
  3375.     }
  3376. #endif /* TIOCGETC */
  3377. #ifdef TIOCGLTC /* Put back local special characters */
  3378.     if (ltcharf && (xlocal == 0)) {
  3379. if (ioctl(ttyfd,TIOCSLTC,&ltchold) < 0)
  3380.   debug(F100,"ttres TIOCSLTC failed","",0);
  3381. else
  3382.   debug(F100,"ttres TIOCSLTC ok","",0);
  3383.     }
  3384. #endif /* TIOCGLTC */
  3385. #ifdef BELLV10
  3386.     debug(F100,"ttres BELLV10","",0);
  3387.     x = ioctl(ttyfd,TIOCSETP,&ttold); /* Restore both structs */
  3388.     x = ioctl(ttyfd,TIOCSDEV,&tdold);
  3389. #else
  3390.     debug(F100,"ttres stty","",0);
  3391.     x = stty(ttyfd,&ttold);             /* Restore tty modes the old way. */
  3392. #endif /* BELLV10 */
  3393.     if (!xlocal)
  3394.       msleep(100); /* This replaces sleep(1)... */
  3395. /* Put back sleep(1) if tty is */
  3396. /* messed up after close. */
  3397. #endif /* ATTSV */
  3398. #endif /* BSD44ORPOSIX */
  3399.     debug(F101,"ttres result","",x);
  3400. #ifndef QNX
  3401.     if (x < 0) debug(F101,"ttres errno","",errno);
  3402. #endif /* QNX */
  3403. #ifdef AIXRS
  3404. #ifndef AIX41
  3405.     x = ioctl(ttyfd, ttld & 1 ? TXADDCD : TXDELCD, "rts");
  3406.     debug(F101,"ttres AIX line discipline rts restore","",x);
  3407. #endif /* AIX41 */
  3408. #endif /* AIXRS */
  3409. #ifdef BSD41
  3410.     if (ttld > -1) { /* Put back line discipline */
  3411. x = ioctl(ttyfd, TIOCSETD, &ttld);
  3412. debug(F101,"ttres BSD41 line discipline restore","",x);
  3413. if (x < 0) debug(F101,"...ioctl errno","",errno);
  3414. ttld = -1;
  3415.     }
  3416. #endif /* BSD41 */
  3417. #ifdef sony_news
  3418.     x = xlocal ? km_ext : km_con; /* Restore Kanji mode. */
  3419.     if (x != -1) { /* Make sure we know original modes. */
  3420. if (ioctl(ttyfd,TIOCKSET, &x) < 0) {
  3421.     perror("ttres can't set Kanji mode");
  3422.     debug(F101,"ttres error setting Kanji mode","",x);
  3423.     return(-1);
  3424. }
  3425.     }
  3426.     debug(F100,"ttres set Kanji mode ok","",0);
  3427. #endif /* sony_news */
  3428.     tvtflg = 0; /* Invalidate terminal mode settings */
  3429.     debug(F101,"ttres return code","",x);
  3430.     return(x);
  3431. }
  3432. #ifndef NOUUCP
  3433. /*  T T C H K P I D  --  Check lockfile pid  */
  3434. /*
  3435.   Read pid from lockfile named f, check that it's still valid.
  3436.   If so, return 1.
  3437.   On failure to read pid, return 1.
  3438.   Otherwise, try to delete lockfile f and return 0 if successful, else 1.
  3439. */
  3440. static int
  3441. ttchkpid(f) char *f; {
  3442.     int pid, mypid, x;
  3443.     pid = ttrpid(f); /* Read pid from file. */
  3444.     if (pid > -1) { /* If we were able to read the pid.. */
  3445. debug(F101,"ttchkpid lock pid","",pid);
  3446. errno = 0; /* See if process still exists. */
  3447. mypid = (int)getpid(); /* Get my own pid. */
  3448. debug(F101,"ttchkpid my pid","",mypid);
  3449. if (pid == mypid) { /* It's me! */
  3450.     x = -1; /* So I can delete it */
  3451.     errno = ESRCH; /* pretend it's invalid */
  3452. } else { /* It's not me */
  3453.     x = kill((PID_T)pid, 0); /* See if it's a live process */
  3454.     debug(F101,"ttchkpid kill errno","",errno);
  3455. }
  3456. debug(F101,"ttchkpid pid test","",x);
  3457. if (x < 0 && errno == ESRCH) { /* pid is invalid */
  3458.     debug(F111,"removing stale lock",f,pid);
  3459.     if (!backgrd)
  3460.       printf("Removing stale lock %s (pid %d terminated)n", f, pid);
  3461.     priv_on();
  3462.     x = unlink(f); /* Remove the lockfile. */
  3463.     priv_off();
  3464.     debug(F111,"ttchkpid unlink",f,x);
  3465.     if (x > -1)
  3466.       return(0); /* Device is not locked after all */
  3467.     else if (!backgrd)
  3468.       perror(f);
  3469. }
  3470. return(1);
  3471.     }
  3472.     return(1); /* Failure to read pid */
  3473. }
  3474. #ifdef HPUX
  3475. /* Aliases (different drivers) for HP-UX dialout devices: */
  3476. static char *devprefix[] = { "tty", "ttyd", "cul", "cua", "cuad", "culd", "" };
  3477. static int ttydexists = 0;
  3478. #endif /* HPUX */
  3479. /*  T T R P I D  --  Read pid from lockfile "name" */
  3480. static int
  3481. ttrpid(name) char *name; {
  3482.     long len;
  3483.     int x, i, fd, pid, flag;
  3484.     short spid;
  3485.     char buf[32];
  3486.     debug(F110,"ttrpid",name,0);
  3487.     if (!name) return(-1);
  3488.     if (!*name) return(-1);
  3489.     priv_on();
  3490.     len = zchki(name); /* Get file length */
  3491.     priv_off();
  3492.     debug(F101,"ttrpid zchki","",len);
  3493.     if (len < 0)
  3494.       return(-1);
  3495.     if (len > 31)
  3496.       return(-1);
  3497.     priv_on();
  3498.     fd = open(name,O_RDONLY); /* Try to open lockfile. */
  3499.     priv_off();
  3500.     debug(F101,"ttrpid fd","",fd);
  3501.     if (fd <= 0)
  3502.       return(-1);
  3503. /*
  3504.   Here we try to be flexible and allow for all different binary and string
  3505.   formats at runtime, rather than a specific format for each configuration
  3506.   hardwired at compile time.
  3507. */
  3508.     pid = -1;
  3509. #ifndef COHERENT
  3510. /*
  3511.   COHERENT uses a string PID but without leading spaces or 0's, so there is
  3512.   no way to tell from the file's length whether it contains a string or binary
  3513.   pid.  So for COHERENT only, we only allow string pids.  For all others, we
  3514.   decide based on the size of the lockfile.
  3515. */
  3516.     if (len > 4) { /* If file > 4 bytes it's a string */
  3517. #endif /* COHERENT */
  3518. x = read(fd,buf,len);
  3519. debug(F111,"ttrpid string read",buf,x);
  3520. if (x < 0) {
  3521.     pid = -1;
  3522. } else {
  3523.     buf[31] = '';
  3524.     x = sscanf(buf,"%d",&pid); /* Get the integer pid from it. */
  3525. }
  3526. #ifndef COHERENT
  3527.     } else if (len == 4) { /* 4 bytes so binary */
  3528. x = read(fd, (char *)&pid, 4); /* Read the bytes into an int */
  3529. debug(F101,"ttrpid integer read","",x);
  3530. if (x < 4)
  3531.   pid = -1;
  3532.     } else if (len == 2) { /* 2 bytes binary */
  3533. x = read(fd, (char *)&spid, 2); /* Read the bytes into a short */
  3534. debug(F101,"ttrpid short read","",x);
  3535. if (x < 2)
  3536.   pid = -1;
  3537. else
  3538.   pid = spid;
  3539.     } else
  3540.       pid = -1;
  3541. #endif /* COHERENT */
  3542.     close(fd); /* Close the lockfile */
  3543.     debug(F101,"ttrpid pid","",pid);
  3544.     return(pid);
  3545. }
  3546. #endif /* NOUUCP */
  3547. /*  T T L O C K  */
  3548. /*
  3549.   This function attempts to coordinate use of the communication device with
  3550.   other copies of Kermit and any other program that follows the UUCP
  3551.   device-locking conventions, which, unfortunately, vary among different UNIX
  3552.   implementations.  The idea is to look for a file of a certain name, the
  3553.   "lockfile", in a certain directory.  If such a file is found, then the line
  3554.   is presumed to be in use, and Kermit should not use it.  If no such file is
  3555.   found, Kermit attempts to create one so that other programs will not use the
  3556.   same line at the same time.  Because the lockfile and/or the directory it's
  3557.   in might lack write permission for the person running Kermit, Kermit could
  3558.   find itself running setuid to uucp or other user that does have the
  3559.   necessary permissions.  At startup, Kermit has changed its effective uid to
  3560.   the user's real uid, and so ttlock() must switch back to the original
  3561.   effective uid in order to create the lockfile, and then back again to the
  3562.   real uid to prevent unauthorized access to other directories or files owned
  3563.   by the user the program is setuid to.
  3564.   Totally rewritten for C-Kermit 5A to eliminate windows of vulnerability,
  3565.   based on suggestions from Warren Tucker.  Call with pointer to name of
  3566.   tty device.  Returns:
  3567.    0 on success
  3568.   -1 on failure
  3569.   Note: Once privileges are turned on using priv_on(), it is essential that
  3570.   they are turned off again before this function returns.
  3571. */
  3572. #ifdef SVR4 /* Lockfile uses device numbers. */
  3573. /*
  3574.   Although I can't find this in writing anywhere (e.g. in SVID for SVR4),
  3575.   it is the behavior of the "reference version" of SVR4, i.e. the Intel
  3576.   port from UNIX Systems Laboratories, then called Univel UnixWare,
  3577.   then called Novell UnixWare, now called SCO Unixware...  It also makes
  3578.   much more sense than device-name-based lockfiles, since there can be
  3579.   multiple names for the same device, symlinks, etc.
  3580. */
  3581. #ifndef LFDEVNO /* Define this for SVR4 */
  3582. #ifndef AIXRS /* But not for RS/6000 AIX 3.2, etc. */
  3583. #ifndef BSD44 /* If anybody else needs it... */
  3584. #ifndef __386BSD__
  3585. #ifndef __FreeBSD__
  3586. #ifndef HPUX10
  3587. #ifndef IRIX51 /* SGI IRIX 5.1 or later */
  3588. #ifndef CK_SCOV5 /* SCO Open Server 5.0 */
  3589. #define LFDEVNO
  3590. #endif /* CK_SCOV5 */
  3591. #endif /* IRIX51 */
  3592. #endif /* HPUX10 */
  3593. #endif /* __FreeBSD__ */
  3594. #endif /* __386BSD__ */
  3595. #endif /* BSD44 */
  3596. #endif /* AIXRS */
  3597. #endif /* LFDEVNO */ /* ... define it here or on CC */
  3598. #endif /* SVR4 */ /* command line. */
  3599. #ifdef COHERENT
  3600. #define LFDEVNO
  3601. #endif /* COHERENT */
  3602. /*
  3603.   For platforms where the lockfile name is made from inode/major/minor
  3604.   device number, as in SVR4.  Which, if we must have lockfiles at all, is
  3605.   by far the best format, since it eliminates all the confusion that stems
  3606.   from multiple names (or drivers) for the same port, not to mention
  3607.   symlinks.  It might even be a good idea to start using this form even
  3608.   on platforms where it's not supported, alongside the normal forms for those
  3609.   platforms, in order to get people used to it...
  3610. */
  3611. #ifdef LFDEVNO
  3612. #ifndef major /* If we didn't find it */
  3613. #ifdef SVR4 /* then for Sys V R4 */
  3614. #include <sys/mkdev.h> /* look here */
  3615. #else /* or for SunOS versions */
  3616. #ifdef SUNOS4 /* ... */
  3617. #include <sys/sysmacros.h> /* look here */
  3618. #else /* Otherwise take a chance: */
  3619. #define major(dev) ( (int) ( ((unsigned)(dev) >> 8) & 0xff))
  3620. #define minor(dev) ( (int) ( (dev) & 0xff))
  3621. #endif /* SUNOS4 */
  3622. #endif /* SVR4 */
  3623. #endif /* major */
  3624. #endif /* LFDEVNO */
  3625. /* No advisory locks if F_TLOCK and F_ULOCK are not defined at this point */
  3626. #ifdef LOCKF
  3627. #ifndef F_TLOCK
  3628. #undef LOCKF
  3629. #ifndef NOLOCKF
  3630. #define NOLOCKF
  3631. #endif /* NOLOCKF */
  3632. #endif /* F_TLOCK */
  3633. #endif /* LOCKF */
  3634. #ifdef LOCKF
  3635. #ifndef F_ULOCK
  3636. #undef LOCKF
  3637. #ifndef NOLOCKF
  3638. #define NOLOCKF
  3639. #endif /* NOLOCKF */
  3640. #endif /* F_ULOCK */
  3641. #endif /* LOCKF */
  3642. static char linkto[DEVNAMLEN+1];
  3643. static char * linkdev = NULL;
  3644. #ifndef NOUUCP
  3645. #ifdef USETTYLOCK
  3646. char * uucplockdir = "";
  3647. #else
  3648. #ifdef LOCK_DIR
  3649. char * uucplockdir = LOCK_DIR;
  3650. #else
  3651. char * uucplockdir = "";
  3652. #endif /* LOCK_DIR */
  3653. #endif /* USETTYLOCK */
  3654. #else
  3655. char * uucplockdir = "";
  3656. #endif /* NOUUCP */
  3657. #ifdef QNX
  3658. int /* Visible to outside world */
  3659. qnxopencount() { /* Get QNX device open count */
  3660.     struct _dev_info_entry info;
  3661.     int x;
  3662.     x = -1; /* Unknown */
  3663.     if (ttyfd > -1) {
  3664. if (!dev_info(ttyfd, &info)) {
  3665.     debug(F101,"ttlock QNX open_count","",info.open_count);
  3666.     x = info.open_count;
  3667. }
  3668.     }
  3669.     return(x);
  3670. }
  3671. #endif /* QNX */
  3672. static int
  3673. ttlock(ttdev) char *ttdev; {
  3674.     int x, n;
  3675.     int islink = 0;
  3676. #ifdef NOUUCP
  3677. #ifdef QNX
  3678.     extern int qnxportlock;
  3679.     if ((x = qnxopencount()) < 0)
  3680.       return(x);
  3681.     if (x > 1) { /* 1 = me */
  3682. if (qnxportlock)
  3683.   return(-2); /* Indicate device is in use */
  3684. else if (!quiet)
  3685.   printf("WARNING: "%s" looks busy...n",ttdev);
  3686.     }
  3687. #endif /* QNX */
  3688.     strcpy(flfnam,"NOLOCK");
  3689.     haslock = 1;
  3690.     return(0);
  3691. #else /* !NOUUCP */
  3692. #ifdef USETTYLOCK
  3693.     haslock = 0;                        /* Not locked yet. */
  3694.     *flfnam = ''; /* Lockfile name is empty. */
  3695.     if (!strncmp(ttdev,"/dev/",5) && ttdev[5])
  3696.       ckstrncpy(lockname,ttdev+5,DEVNAMLEN);
  3697.     else
  3698.       ckstrncpy(lockname,ttdev,DEVNAMLEN);
  3699. /*
  3700.   This might be overkill, but it's not clear from the man pages whether
  3701.   ttylock() can be called without calling ttylocked() first, since the doc
  3702.   says that ttylocked() removes any stale lockfiles, but it does not say this
  3703.   about ttylock().  Also the docs don't say what ttylocked() returns in the
  3704.   case when it finds and removes a stale lockfile.  So one or both calls to
  3705.   to ttylocked() might be superfluous, but they should do no harm.  Also I'm
  3706.   assuming that we have to do all the same ID swapping, etc, with these
  3707.   routines as we do without them.  Thus the priv_on/off() sandwich.
  3708. */
  3709. #ifdef USE_UU_LOCK
  3710.     priv_on(); /* Turn on privs */
  3711.     x = uu_lock(lockname); /* Try to set the lock */
  3712.     priv_off(); /* Turn privs off */
  3713.     debug(F111,"ttlock uu_lock",lockname,x);
  3714.     switch (x) {
  3715.       case UU_LOCK_INUSE:
  3716. return(-2);
  3717.       case UU_LOCK_OK:
  3718. #ifdef BSD44
  3719. sprintf(flfnam,"/var/spool/lock/LCK..%s",lockname);
  3720. #endif /* BSD44 */
  3721. haslock = 1;
  3722. return(0);
  3723.       default:
  3724. return(-1);
  3725.     }
  3726. #else  /* USE_UU_LOCK */
  3727.     priv_on(); /* Turn on privs */
  3728.     if (ttylocked(lockname)) { /* This should remove any stale lock */
  3729. if (ttylocked(lockname)) { /* so check again. */
  3730.     priv_off();
  3731.     return(-5); /* Still locked, fail. */
  3732. }
  3733.     }
  3734.     x = ttylock(lockname); /* Lock it. */
  3735.     priv_off(); /* Turn off privs */
  3736.     debug(F111,"ttlock lockname",lockname,x);
  3737.     if (x > -1) {
  3738. /*
  3739.   We don't really know the name of the lockfile, but
  3740.   this is what the man page says it is.  In USETTYLOCK
  3741.           builds, it is used only for display by SHOW COMM.
  3742. */
  3743. sprintf(flfnam,"/etc/locks/LCK..%s",lockname);
  3744. haslock = 1;
  3745.     }
  3746.     return(x);
  3747. #endif /* USE_UU_LOCK */
  3748. #else  /* Systems that don't have ttylock()... */
  3749. #ifndef HPUX
  3750.     int lockfd; /* File descriptor for lock file. */
  3751.     PID_T pid; /* Process id of this process. */
  3752.     int tries; /* How many times we've tried... */
  3753.     struct stat devbuf; /* For device numbers (SVR4). */
  3754. #ifdef PIDSTRING
  3755.     char pid_str[12]; /* My pid in string format. */
  3756. #endif /* PIDSTRING */
  3757.     char *device, *devname;
  3758. #define LFNAML 50 /* Max length for lock file name. */
  3759.     char lockfil[LFNAML]; /* Lock file name */
  3760. #ifdef RTAIX
  3761.     char lklockf[LFNAML]; /* Name for link to lock file  */
  3762. #endif /* RTAIX */
  3763. #ifdef CKSYMLINK
  3764.     char symlock[LFNAML]; /* Name for symlink lockfile name */
  3765. #endif /* CKSYMLINK */
  3766.     char tmpnam[LFNAML+30]; /* Temporary lockfile name. */
  3767.     char *lockdir = LOCK_DIR; /* Defined near top of this file, */
  3768. /* or on cc command line. */
  3769.     haslock = 0;                        /* Not locked yet. */
  3770.     *flfnam = ''; /* Lockfile name is empty. */
  3771.     lock2[0] = ''; /* Clear secondary lockfile name. */
  3772.     pid = getpid(); /* Get id of this process. */
  3773. /*  Construct name of lockfile and temporary file */
  3774. /*  device  = name of tty device without the path, e.g. "ttyh8" */
  3775. /*  lockfil = name of lock file, without path, e.g. "LCK..ttyh8" */
  3776.     device = ((devname = xxlast(ttdev,'/')) != NULL ? devname+1 : ttdev);
  3777.     if (stat(ttdev,&devbuf) < 0)
  3778.       return(-1);
  3779. #ifdef CKSYMLINK
  3780.     islink = 1; /* Assume it's a symlink */
  3781.     linkto[0] = ''; /* But we don't know to what */
  3782. #ifdef COMMENT
  3783. /*
  3784.   This is undependable.  If it worked it would save the readlink call if
  3785.   we knew the device name was not a link.
  3786. */
  3787. #ifdef S_ISLNK
  3788.     islink = S_ISLNK(devbuf.st_mode);
  3789.     debug(F101,"ttlock stat S_ISLNK","",islink);
  3790. #endif /* S_ISLNK */
  3791. #endif /* COMMENT */
  3792.     if (islink) {
  3793. n = readlink(ttdev,linkto,DEVNAMLEN); /* See if it's a link */
  3794. debug(F111,"ttlock readlink",ttdev,n);
  3795. if (n > -1) /* It is */
  3796.   linkto[n] = '';
  3797. else /* It's not */
  3798.   islink = 0;
  3799. debug(F111,"ttlock link",linkto,islink);
  3800.     }
  3801.     if (islink) {
  3802. linkdev = (devname = xxlast(linkto,'/')) ? devname + 1 : linkto;
  3803. debug(F110,"ttlock linkdev",linkdev,0);
  3804.     }
  3805. #endif /* CKSYMLINK */
  3806. /*
  3807.   On SCO platforms, if we don't have a symlink, then let's pretend the
  3808.   name given for the device is a symlink, because later we will change
  3809.   the name if it contains any uppercase characters.
  3810. */
  3811. #ifdef CK_SCOV5 /* SCO Open Server 5.0 */
  3812.     if (!islink) {
  3813. islink = 1;
  3814. ckstrncpy(linkto,ttdev,DEVNAMLEN);
  3815. linkdev = (devname = xxlast(linkto,'/')) ? devname + 1 : linkto;
  3816. debug(F110,"ttlock linkdev",linkdev,0);
  3817.     }
  3818. #else
  3819. #ifdef M_XENIX /* SCO Xenix or UNIX */
  3820.     if (!islink) {
  3821. islink = 1;
  3822. ckstrncpy(linkto,ttdev,DEVNAMLEN);
  3823. linkdev = (devname = xxlast(linkto,'/')) ? devname + 1 : linkto;
  3824. debug(F110,"ttlock linkdev",linkdev,0);
  3825.     }
  3826. #endif /* M_XENIX */
  3827. #endif /* CK_SCOV5 */
  3828. #ifdef ISIII /* Interactive System III, PC/IX */
  3829.     ckstrncpy(lockfil, device, DEVNAMLEN);
  3830. #else  /* not ISIII */
  3831. #ifdef LFDEVNO /* Lockfilename has device numbers. */
  3832. #ifdef COHERENT
  3833.     sprintf(lockfil,"LCK..%d.%d",
  3834.     major(devbuf.st_rdev),    /* major device number */
  3835.     0x1f & minor(devbuf.st_rdev)); /* minor device number */
  3836. #else
  3837.     sprintf(lockfil,"LK.%03d.%03d.%03d",
  3838.     major(devbuf.st_dev), /* inode */
  3839.     major(devbuf.st_rdev), /* major device number */
  3840.     minor(devbuf.st_rdev)); /* minor device number */
  3841. #endif /* COHERENT */
  3842. #else /* Others... */
  3843. #ifdef PTX /* Dynix PTX */
  3844.     if (device != &ttdev[5] && strncmp(ttdev,"/dev/",5)==0) {
  3845. sprintf(lockfil,"LCK..%.3s%s", &ttdev[5], device);
  3846.     } else
  3847. #endif /* PTX */
  3848.     sprintf(lockfil,"LCK..%s", device);
  3849. #ifdef RTAIX
  3850.     ckstrncpy(lklockf,device,DEVNAMLEN);
  3851. #endif /* RTAIX */
  3852. #ifdef CKSYMLINK
  3853.     symlock[0] = '';
  3854.     if (islink)
  3855.       sprintf(symlock,"LCK..%s", linkdev);
  3856. #endif /* CKSYMLINK */
  3857. #endif /* LFDEVNO */
  3858. #endif /* ISIII */
  3859. #ifdef CK_SCOV5 /* SCO Open Server 5.0 */
  3860.     {
  3861. /* Lowercase the entire filename. */
  3862.         /* SCO says we must do this in V5.0 and later. */
  3863. /* BUT... watch out for devices -- like Digiboard Portserver */
  3864. /* That can have hundreds of ports... */
  3865. char *p = (char *)(lockfil + 5);
  3866. while (*p) { if (isupper(*p)) *p = (char) tolower(*p); p++; }
  3867.     }
  3868. #ifdef CKSYMLINK
  3869.     if (islink) { /* If no change */
  3870. if (!strcmp(lockfil,symlock)) { /* then no second lockfile needed */
  3871.     islink = 0;
  3872.     symlock[0] = '';
  3873. }
  3874.     }
  3875. #endif /* CKSYMLINK */
  3876. #else
  3877. #ifdef M_XENIX /* SCO Xenix or UNIX */
  3878.     {
  3879. int x; char c;
  3880. x = (int)strlen(lockfil) - 1; /* Get last letter of device name. */
  3881. if (x > 0) { /* If it's uppercase, lower it. */
  3882.     c = lockfil[x];
  3883.     if (c >= 'A' && c <= 'Z') lockfil[x] += ('a' - 'A');
  3884. }
  3885.     }
  3886. #ifdef CKSYMLINK
  3887.     if (islink) {
  3888. if (!strcmp(lockfil,symlock)) { /* No change */
  3889.     islink = 0; /* so no second lockfile */
  3890.     symlock[0] = '';
  3891. }
  3892.     }
  3893. #endif /* CKSYMLINK */
  3894. #endif /* M_XENIX */
  3895. #endif /* CK_SCOV5 */
  3896. /*  flfnam = full lockfile pathname, e.g. "/usr/spool/uucp/LCK..ttyh8" */
  3897. /*  tmpnam = temporary unique, e.g. "/usr/spool/uucp/LTMP..pid" */
  3898.     sprintf(flfnam,"%s/%s",lockdir,lockfil);
  3899. #ifdef RTAIX
  3900.     sprintf(lkflfn,"%s/%s",lockdir,lklockf);
  3901. #endif /* RTAIX */
  3902. #ifdef CKSYMLINK
  3903.     /* If it's a link then also make a lockfile for the real name */
  3904.     debug(F111,"ttlock link symlock",symlock,islink);
  3905.     if (islink && symlock[0]) {
  3906. /* But only if the lockfile names would be different. */
  3907. /* WARNING: They won't be, e.g. for /dev/ttyd2 => /hw/ttys/ttyd2 */
  3908. sprintf(lock2,"%s/%s",lockdir,symlock); /* No, make 2nd lockfile */
  3909. debug(F110,"ttlock lock2",lock2,0);
  3910. if (!strcmp(lock2,flfnam)) { /* Are lockfile names the same? */
  3911.     debug(F100,"ttlock lock2 cleared","",0);
  3912.     lock2[0] = ''; /* Clear secondary lockfile name. */
  3913. }
  3914.     }
  3915. #endif /* CKSYMLINK */
  3916.     sprintf(tmpnam,"%s/LTMP.%05d",lockdir,(int) pid);
  3917.     debug(F110,"ttlock flfnam",flfnam,0);
  3918.     debug(F110,"ttlock tmpnam",tmpnam,0);
  3919.     priv_on(); /* Turn on privileges if possible. */
  3920.     lockfd = creat(tmpnam, 0444); /* Try to create temp lock file. */
  3921.     if (lockfd < 0) { /* Create failed. */
  3922. debug(F111,"ttlock creat failed",tmpnam,errno);
  3923. if (errno == ENOENT) {
  3924.     perror(lockdir);