home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 3 Comm / 03-Comm.zip / CK5A188S.ZIP / ckutio.c < prev    next >
C/C++ Source or Header  |  1992-11-23  |  198KB  |  6,447 lines

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