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

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