home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / inetutils-1.2-src.tgz / tar.out / fsf / inetutils / telnetd / sys_term.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  48KB  |  2,291 lines

  1. /*
  2.  * Copyright (c) 1989, 1993
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static char sccsid[] = "@(#)sys_term.c    8.4 (Berkeley) 5/30/95";
  36. #endif /* not lint */
  37.  
  38. #ifdef HAVE_CONFIG_H
  39. #include <config.h>
  40. #endif
  41.  
  42. #include "telnetd.h"
  43.  
  44. #if    defined(AUTHENTICATION)
  45. #include <libtelnet/auth.h>
  46. #endif
  47.  
  48. #if defined(CRAY) || defined(__hpux)
  49. # define PARENT_DOES_UTMP
  50. #endif
  51.  
  52. #ifdef    NEWINIT
  53. #include <initreq.h>
  54. int    utmp_len = MAXHOSTNAMELEN;    /* sizeof(init_request.host) */
  55. #else    /* NEWINIT*/
  56. # ifdef    UTMPX
  57. # include <utmpx.h>
  58. struct    utmpx wtmp;
  59. # else
  60. # include <utmp.h>
  61. struct    utmp wtmp;
  62. # endif /* UTMPX */
  63.  
  64. int    utmp_len = sizeof(wtmp.ut_host);
  65. # ifndef PARENT_DOES_UTMP
  66. char    wtmpf[]    = "/usr/adm/wtmp";
  67. char    utmpf[] = "/etc/utmp";
  68. # else /* PARENT_DOES_UTMP */
  69. char    wtmpf[]    = "/etc/wtmp";
  70. # endif /* PARENT_DOES_UTMP */
  71.  
  72. # ifdef CRAY
  73. #include <tmpdir.h>
  74. #include <sys/wait.h>
  75. #  if (UNICOS_LVL == '7.0') || (UNICOS_LVL == '7.1')
  76. #   define UNICOS7x
  77. #  endif
  78.  
  79. #  ifdef UNICOS7x
  80. #include <sys/sysv.h>
  81. #include <sys/secstat.h>
  82. extern int secflag;
  83. extern struct sysv sysv;
  84. #  endif /* UNICOS7x */
  85. # endif    /* CRAY */
  86. #endif    /* NEWINIT */
  87.  
  88. #ifdef    STREAMSPTY
  89. #include <sac.h>
  90. #include <sys/stropts.h>
  91. #endif
  92.  
  93. #define SCPYN(a, b)    (void) strncpy(a, b, sizeof(a))
  94. #define SCMPN(a, b)    strncmp(a, b, sizeof(a))
  95.  
  96. #ifdef    STREAMS
  97. #include <sys/stream.h>
  98. #endif
  99. #ifdef __hpux
  100. #include <sys/resource.h>
  101. #include <sys/proc.h>
  102. #endif
  103. #ifdef HAVE_SYS_TTY_H
  104. #include <sys/tty.h>
  105. #endif
  106. #ifdef    t_erase
  107. #undef    t_erase
  108. #undef    t_kill
  109. #undef    t_intrc
  110. #undef    t_quitc
  111. #undef    t_startc
  112. #undef    t_stopc
  113. #undef    t_eofc
  114. #undef    t_brkc
  115. #undef    t_suspc
  116. #undef    t_dsuspc
  117. #undef    t_rprntc
  118. #undef    t_flushc
  119. #undef    t_werasc
  120. #undef    t_lnextc
  121. #endif
  122.  
  123. #if defined(UNICOS5) && defined(CRAY2) && !defined(EXTPROC)
  124. # define EXTPROC 0400
  125. #endif
  126.  
  127. #ifndef    USE_TERMIO
  128. struct termbuf {
  129.     struct sgttyb sg;
  130.     struct tchars tc;
  131.     struct ltchars ltc;
  132.     int state;
  133.     int lflags;
  134. } termbuf, termbuf2;
  135. # define    cfsetospeed(tp, val)    (tp)->sg.sg_ospeed = (val)
  136. # define    cfsetispeed(tp, val)    (tp)->sg.sg_ispeed = (val)
  137. # define    cfgetospeed(tp)        (tp)->sg.sg_ospeed
  138. # define    cfgetispeed(tp)        (tp)->sg.sg_ispeed
  139. #else    /* USE_TERMIO */
  140. # ifdef    SYSV_TERMIO
  141. #    define termios termio
  142. # endif
  143. # ifndef    TCSANOW
  144. #  ifdef TCSETS
  145. #   define    TCSANOW        TCSETS
  146. #   define    TCSADRAIN    TCSETSW
  147. #   define    tcgetattr(f, t)    ioctl(f, TCGETS, (char *)t)
  148. #  else
  149. #   ifdef TCSETA
  150. #    define    TCSANOW        TCSETA
  151. #    define    TCSADRAIN    TCSETAW
  152. #    define    tcgetattr(f, t)    ioctl(f, TCGETA, (char *)t)
  153. #   else
  154. #    define    TCSANOW        TIOCSETA
  155. #    define    TCSADRAIN    TIOCSETAW
  156. #    define    tcgetattr(f, t)    ioctl(f, TIOCGETA, (char *)t)
  157. #   endif
  158. #  endif
  159. #  define    tcsetattr(f, a, t)    ioctl(f, a, t)
  160. #  define    cfsetospeed(tp, val)    (tp)->c_cflag &= ~CBAUD; \
  161.                     (tp)->c_cflag |= (val)
  162. #  define    cfgetospeed(tp)        ((tp)->c_cflag & CBAUD)
  163. #  ifdef CIBAUD
  164. #   define    cfsetispeed(tp, val)    (tp)->c_cflag &= ~CIBAUD; \
  165.                     (tp)->c_cflag |= ((val)<<IBSHIFT)
  166. #   define    cfgetispeed(tp)        (((tp)->c_cflag & CIBAUD)>>IBSHIFT)
  167. #  else
  168. #   define    cfsetispeed(tp, val)    (tp)->c_cflag &= ~CBAUD; \
  169.                     (tp)->c_cflag |= (val)
  170. #   define    cfgetispeed(tp)        ((tp)->c_cflag & CBAUD)
  171. #  endif
  172. # endif /* TCSANOW */
  173. struct termios termbuf, termbuf2;    /* pty control structure */
  174. # ifdef  STREAMSPTY
  175. int ttyfd = -1;
  176. # endif
  177. #endif    /* USE_TERMIO */
  178.  
  179. /*
  180.  * init_termbuf()
  181.  * copy_termbuf(cp)
  182.  * set_termbuf()
  183.  *
  184.  * These three routines are used to get and set the "termbuf" structure
  185.  * to and from the kernel.  init_termbuf() gets the current settings.
  186.  * copy_termbuf() hands in a new "termbuf" to write to the kernel, and
  187.  * set_termbuf() writes the structure into the kernel.
  188.  */
  189.  
  190.     void
  191. init_termbuf()
  192. {
  193. #ifndef    USE_TERMIO
  194.     (void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg);
  195.     (void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc);
  196.     (void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc);
  197. # ifdef    TIOCGSTATE
  198.     (void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state);
  199. # endif
  200. #else
  201. # ifdef  STREAMSPTY
  202.     (void) tcgetattr(ttyfd, &termbuf);
  203. # else
  204.     (void) tcgetattr(pty, &termbuf);
  205. # endif
  206. #endif
  207.     termbuf2 = termbuf;
  208. }
  209.  
  210. #if    defined(LINEMODE) && defined(TIOCPKT_IOCTL)
  211.     void
  212. copy_termbuf(cp, len)
  213.     char *cp;
  214.     int len;
  215. {
  216.     if (len > sizeof(termbuf))
  217.         len = sizeof(termbuf);
  218.     memmove((char *)&termbuf, cp, len);
  219.     termbuf2 = termbuf;
  220. }
  221. #endif    /* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */
  222.  
  223.     void
  224. set_termbuf()
  225. {
  226.     /*
  227.      * Only make the necessary changes.
  228.      */
  229. #ifndef    USE_TERMIO
  230.     if (memcmp((char *)&termbuf.sg, (char *)&termbuf2.sg,
  231.                             sizeof(termbuf.sg)))
  232.         (void) ioctl(pty, TIOCSETN, (char *)&termbuf.sg);
  233.     if (memcmp((char *)&termbuf.tc, (char *)&termbuf2.tc,
  234.                             sizeof(termbuf.tc)))
  235.         (void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc);
  236.     if (memcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc,
  237.                             sizeof(termbuf.ltc)))
  238.         (void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc);
  239.     if (termbuf.lflags != termbuf2.lflags)
  240.         (void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags);
  241. #else    /* USE_TERMIO */
  242.     if (memcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf)))
  243. # ifdef  STREAMSPTY
  244.         (void) tcsetattr(ttyfd, TCSANOW, &termbuf);
  245. # else
  246.         (void) tcsetattr(pty, TCSANOW, &termbuf);
  247. # endif
  248. # if    defined(CRAY2) && defined(UNICOS5)
  249.     needtermstat = 1;
  250. # endif
  251. #endif    /* USE_TERMIO */
  252. }
  253.  
  254.  
  255. /*
  256.  * spcset(func, valp, valpp)
  257.  *
  258.  * This function takes various special characters (func), and
  259.  * sets *valp to the current value of that character, and
  260.  * *valpp to point to where in the "termbuf" structure that
  261.  * value is kept.
  262.  *
  263.  * It returns the SLC_ level of support for this function.
  264.  */
  265.  
  266. #ifndef    USE_TERMIO
  267.     int
  268. spcset(func, valp, valpp)
  269.     int func;
  270.     cc_t *valp;
  271.     cc_t **valpp;
  272. {
  273.     switch(func) {
  274.     case SLC_EOF:
  275.         *valp = termbuf.tc.t_eofc;
  276.         *valpp = (cc_t *)&termbuf.tc.t_eofc;
  277.         return(SLC_VARIABLE);
  278.     case SLC_EC:
  279.         *valp = termbuf.sg.sg_erase;
  280.         *valpp = (cc_t *)&termbuf.sg.sg_erase;
  281.         return(SLC_VARIABLE);
  282.     case SLC_EL:
  283.         *valp = termbuf.sg.sg_kill;
  284.         *valpp = (cc_t *)&termbuf.sg.sg_kill;
  285.         return(SLC_VARIABLE);
  286.     case SLC_IP:
  287.         *valp = termbuf.tc.t_intrc;
  288.         *valpp = (cc_t *)&termbuf.tc.t_intrc;
  289.         return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
  290.     case SLC_ABORT:
  291.         *valp = termbuf.tc.t_quitc;
  292.         *valpp = (cc_t *)&termbuf.tc.t_quitc;
  293.         return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
  294.     case SLC_XON:
  295.         *valp = termbuf.tc.t_startc;
  296.         *valpp = (cc_t *)&termbuf.tc.t_startc;
  297.         return(SLC_VARIABLE);
  298.     case SLC_XOFF:
  299.         *valp = termbuf.tc.t_stopc;
  300.         *valpp = (cc_t *)&termbuf.tc.t_stopc;
  301.         return(SLC_VARIABLE);
  302.     case SLC_AO:
  303.         *valp = termbuf.ltc.t_flushc;
  304.         *valpp = (cc_t *)&termbuf.ltc.t_flushc;
  305.         return(SLC_VARIABLE);
  306.     case SLC_SUSP:
  307.         *valp = termbuf.ltc.t_suspc;
  308.         *valpp = (cc_t *)&termbuf.ltc.t_suspc;
  309.         return(SLC_VARIABLE);
  310.     case SLC_EW:
  311.         *valp = termbuf.ltc.t_werasc;
  312.         *valpp = (cc_t *)&termbuf.ltc.t_werasc;
  313.         return(SLC_VARIABLE);
  314.     case SLC_RP:
  315.         *valp = termbuf.ltc.t_rprntc;
  316.         *valpp = (cc_t *)&termbuf.ltc.t_rprntc;
  317.         return(SLC_VARIABLE);
  318.     case SLC_LNEXT:
  319.         *valp = termbuf.ltc.t_lnextc;
  320.         *valpp = (cc_t *)&termbuf.ltc.t_lnextc;
  321.         return(SLC_VARIABLE);
  322.     case SLC_FORW1:
  323.         *valp = termbuf.tc.t_brkc;
  324.         *valpp = (cc_t *)&termbuf.ltc.t_lnextc;
  325.         return(SLC_VARIABLE);
  326.     case SLC_BRK:
  327.     case SLC_SYNCH:
  328.     case SLC_AYT:
  329.     case SLC_EOR:
  330.         *valp = (cc_t)0;
  331.         *valpp = (cc_t *)0;
  332.         return(SLC_DEFAULT);
  333.     default:
  334.         *valp = (cc_t)0;
  335.         *valpp = (cc_t *)0;
  336.         return(SLC_NOSUPPORT);
  337.     }
  338. }
  339.  
  340. #else    /* USE_TERMIO */
  341.  
  342.     int
  343. spcset(func, valp, valpp)
  344.     int func;
  345.     cc_t *valp;
  346.     cc_t **valpp;
  347. {
  348.  
  349. #define    setval(a, b)    *valp = termbuf.c_cc[a]; \
  350.             *valpp = &termbuf.c_cc[a]; \
  351.             return(b);
  352. #define    defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT);
  353.  
  354.     switch(func) {
  355.     case SLC_EOF:
  356.         setval(VEOF, SLC_VARIABLE);
  357.     case SLC_EC:
  358.         setval(VERASE, SLC_VARIABLE);
  359.     case SLC_EL:
  360.         setval(VKILL, SLC_VARIABLE);
  361.     case SLC_IP:
  362.         setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
  363.     case SLC_ABORT:
  364.         setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
  365.     case SLC_XON:
  366. #ifdef    VSTART
  367.         setval(VSTART, SLC_VARIABLE);
  368. #else
  369.         defval(0x13);
  370. #endif
  371.     case SLC_XOFF:
  372. #ifdef    VSTOP
  373.         setval(VSTOP, SLC_VARIABLE);
  374. #else
  375.         defval(0x11);
  376. #endif
  377.     case SLC_EW:
  378. #ifdef    VWERASE
  379.         setval(VWERASE, SLC_VARIABLE);
  380. #else
  381.         defval(0);
  382. #endif
  383.     case SLC_RP:
  384. #ifdef    VREPRINT
  385.         setval(VREPRINT, SLC_VARIABLE);
  386. #else
  387.         defval(0);
  388. #endif
  389.     case SLC_LNEXT:
  390. #ifdef    VLNEXT
  391.         setval(VLNEXT, SLC_VARIABLE);
  392. #else
  393.         defval(0);
  394. #endif
  395.     case SLC_AO:
  396. #if    !defined(VDISCARD) && defined(VFLUSHO)
  397. # define VDISCARD VFLUSHO
  398. #endif
  399. #ifdef    VDISCARD
  400.         setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT);
  401. #else
  402.         defval(0);
  403. #endif
  404.     case SLC_SUSP:
  405. #ifdef    VSUSP
  406.         setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN);
  407. #else
  408.         defval(0);
  409. #endif
  410. #ifdef    VEOL
  411.     case SLC_FORW1:
  412.         setval(VEOL, SLC_VARIABLE);
  413. #endif
  414. #ifdef    VEOL2
  415.     case SLC_FORW2:
  416.         setval(VEOL2, SLC_VARIABLE);
  417. #endif
  418.     case SLC_AYT:
  419. #ifdef    VSTATUS
  420.         setval(VSTATUS, SLC_VARIABLE);
  421. #else
  422.         defval(0);
  423. #endif
  424.  
  425.     case SLC_BRK:
  426.     case SLC_SYNCH:
  427.     case SLC_EOR:
  428.         defval(0);
  429.  
  430.     default:
  431.         *valp = 0;
  432.         *valpp = 0;
  433.         return(SLC_NOSUPPORT);
  434.     }
  435. }
  436. #endif    /* USE_TERMIO */
  437.  
  438. #ifdef CRAY
  439. /*
  440.  * getnpty()
  441.  *
  442.  * Return the number of pty's configured into the system.
  443.  */
  444.     int
  445. getnpty()
  446. {
  447. #ifdef _SC_CRAY_NPTY
  448.     int numptys;
  449.  
  450.     if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1)
  451.         return numptys;
  452.     else
  453. #endif /* _SC_CRAY_NPTY */
  454.         return 128;
  455. }
  456. #endif /* CRAY */
  457.  
  458. #ifndef    convex
  459. /*
  460.  * getpty()
  461.  *
  462.  * Allocate a pty.  As a side effect, the external character
  463.  * array "line" contains the name of the slave side.
  464.  *
  465.  * Returns the file descriptor of the opened pty.
  466.  */
  467. #ifndef    __GNUC__
  468. char *line = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
  469. #else
  470. static char Xline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
  471. char *line = Xline;
  472. #endif
  473. #ifdef    CRAY
  474. char *myline = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
  475. #endif    /* CRAY */
  476.  
  477.     int
  478. getpty(ptynum)
  479. int *ptynum;
  480. {
  481.     register int p;
  482. #ifdef    STREAMSPTY
  483.     int t;
  484.     char *ptsname();
  485.  
  486.     p = open("/dev/ptmx", O_RDWR);
  487.     if (p > 0) {
  488.         grantpt(p);
  489.         unlockpt(p);
  490.         strcpy(line, ptsname(p));
  491.         return(p);
  492.     }
  493.  
  494. #else    /* ! STREAMSPTY */
  495. #ifndef CRAY
  496.     register char *cp, *p1, *p2;
  497.     register int i;
  498. #if defined(sun) && defined(TIOCGPGRP) && BSD < 199207
  499.     int dummy;
  500. #endif
  501.  
  502. #ifndef    __hpux
  503.     (void) sprintf(line, "/dev/ptyXX");
  504.     p1 = &line[8];
  505.     p2 = &line[9];
  506. #else
  507.     (void) sprintf(line, "/dev/ptym/ptyXX");
  508.     p1 = &line[13];
  509.     p2 = &line[14];
  510. #endif
  511.  
  512.     for (cp = "pqrstuvwxyzPQRST"; *cp; cp++) {
  513.         struct stat stb;
  514.  
  515.         *p1 = *cp;
  516.         *p2 = '0';
  517.         /*
  518.          * This stat() check is just to keep us from
  519.          * looping through all 256 combinations if there
  520.          * aren't that many ptys available.
  521.          */
  522.         if (stat(line, &stb) < 0)
  523.             break;
  524.         for (i = 0; i < 16; i++) {
  525.             *p2 = "0123456789abcdef"[i];
  526.             p = open(line, O_RDWR);
  527.             if (p > 0) {
  528. #ifndef    __hpux
  529.                 line[5] = 't';
  530. #else
  531.                 for (p1 = &line[8]; *p1; p1++)
  532.                     *p1 = *(p1+1);
  533.                 line[9] = 't';
  534. #endif
  535.                 chown(line, 0, 0);
  536.                 chmod(line, 0600);
  537. #if defined(sun) && defined(TIOCGPGRP) && BSD < 199207
  538.                 if (ioctl(p, TIOCGPGRP, &dummy) == 0
  539.                     || errno != EIO) {
  540.                     chmod(line, 0666);
  541.                     close(p);
  542.                     line[5] = 'p';
  543.                 } else
  544. #endif /* defined(sun) && defined(TIOCGPGRP) && BSD < 199207 */
  545.                     return(p);
  546.             }
  547.         }
  548.     }
  549. #else    /* CRAY */
  550.     extern lowpty, highpty;
  551.     struct stat sb;
  552.  
  553.     for (*ptynum = lowpty; *ptynum <= highpty; (*ptynum)++) {
  554.         (void) sprintf(myline, "/dev/pty/%03d", *ptynum);
  555.         p = open(myline, O_RDWR);
  556.         if (p < 0)
  557.             continue;
  558.         (void) sprintf(line, "/dev/ttyp%03d", *ptynum);
  559.         /*
  560.          * Here are some shenanigans to make sure that there
  561.          * are no listeners lurking on the line.
  562.          */
  563.         if(stat(line, &sb) < 0) {
  564.             (void) close(p);
  565.             continue;
  566.         }
  567.         if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) {
  568.             chown(line, 0, 0);
  569.             chmod(line, 0600);
  570.             (void)close(p);
  571.             p = open(myline, O_RDWR);
  572.             if (p < 0)
  573.                 continue;
  574.         }
  575.         /*
  576.          * Now it should be safe...check for accessability.
  577.          */
  578.         if (access(line, 6) == 0)
  579.             return(p);
  580.         else {
  581.             /* no tty side to pty so skip it */
  582.             (void) close(p);
  583.         }
  584.     }
  585. #endif    /* CRAY */
  586. #endif    /* STREAMSPTY */
  587.     return(-1);
  588. }
  589. #endif    /* convex */
  590.  
  591. #ifdef    LINEMODE
  592. /*
  593.  * tty_flowmode()    Find out if flow control is enabled or disabled.
  594.  * tty_linemode()    Find out if linemode (external processing) is enabled.
  595.  * tty_setlinemod(on)    Turn on/off linemode.
  596.  * tty_isecho()        Find out if echoing is turned on.
  597.  * tty_setecho(on)    Enable/disable character echoing.
  598.  * tty_israw()        Find out if terminal is in RAW mode.
  599.  * tty_binaryin(on)    Turn on/off BINARY on input.
  600.  * tty_binaryout(on)    Turn on/off BINARY on output.
  601.  * tty_isediting()    Find out if line editing is enabled.
  602.  * tty_istrapsig()    Find out if signal trapping is enabled.
  603.  * tty_setedit(on)    Turn on/off line editing.
  604.  * tty_setsig(on)    Turn on/off signal trapping.
  605.  * tty_issofttab()    Find out if tab expansion is enabled.
  606.  * tty_setsofttab(on)    Turn on/off soft tab expansion.
  607.  * tty_islitecho()    Find out if typed control chars are echoed literally
  608.  * tty_setlitecho()    Turn on/off literal echo of control chars
  609.  * tty_tspeed(val)    Set transmit speed to val.
  610.  * tty_rspeed(val)    Set receive speed to val.
  611.  */
  612.  
  613. #ifdef convex
  614. static int linestate;
  615. #endif
  616.  
  617.     int
  618. tty_linemode()
  619. {
  620. #ifndef convex
  621. #ifdef    USE_TERMIO
  622. #ifdef EXTPROC
  623.     return(termbuf.c_lflag & EXTPROC);
  624. #else
  625.     return 0;        /* Can't ever set it either. */
  626. #endif /* EXTPROC */
  627. #else /* !USE_TERMIO */
  628.     return(termbuf.state & TS_EXTPROC);
  629. #endif /* USE_TERMIO */
  630. #else /* convex */
  631.     return(linestate);
  632. #endif /* !convex */
  633. }
  634.  
  635.     void
  636. tty_setlinemode(on)
  637.     int on;
  638. {
  639. #ifdef    TIOCEXT
  640. # ifndef convex
  641.     set_termbuf();
  642. # else
  643.     linestate = on;
  644. # endif
  645.     (void) ioctl(pty, TIOCEXT, (char *)&on);
  646. # ifndef convex
  647.     init_termbuf();
  648. # endif
  649. #else    /* !TIOCEXT */
  650. # ifdef    EXTPROC
  651.     if (on)
  652.         termbuf.c_lflag |= EXTPROC;
  653.     else
  654.         termbuf.c_lflag &= ~EXTPROC;
  655. # endif
  656. #endif    /* TIOCEXT */
  657. }
  658. #endif    /* LINEMODE */
  659.  
  660.     int
  661. tty_isecho()
  662. {
  663. #ifndef USE_TERMIO
  664.     return (termbuf.sg.sg_flags & ECHO);
  665. #else
  666.     return (termbuf.c_lflag & ECHO);
  667. #endif
  668. }
  669.  
  670.     int
  671. tty_flowmode()
  672. {
  673. #ifndef USE_TERMIO
  674.     return(((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0) ? 1 : 0);
  675. #else
  676.     return((termbuf.c_iflag & IXON) ? 1 : 0);
  677. #endif
  678. }
  679.  
  680.     int
  681. tty_restartany()
  682. {
  683. #ifndef USE_TERMIO
  684. # ifdef    DECCTQ
  685.     return((termbuf.lflags & DECCTQ) ? 0 : 1);
  686. # else
  687.     return(-1);
  688. # endif
  689. #else
  690.     return((termbuf.c_iflag & IXANY) ? 1 : 0);
  691. #endif
  692. }
  693.  
  694.     void
  695. tty_setecho(on)
  696.     int on;
  697. {
  698. #ifndef    USE_TERMIO
  699.     if (on)
  700.         termbuf.sg.sg_flags |= ECHO|CRMOD;
  701.     else
  702.         termbuf.sg.sg_flags &= ~(ECHO|CRMOD);
  703. #else
  704.     if (on)
  705.         termbuf.c_lflag |= ECHO;
  706.     else
  707.         termbuf.c_lflag &= ~ECHO;
  708. #endif
  709. }
  710.  
  711.     int
  712. tty_israw()
  713. {
  714. #ifndef USE_TERMIO
  715.     return(termbuf.sg.sg_flags & RAW);
  716. #else
  717.     return(!(termbuf.c_lflag & ICANON));
  718. #endif
  719. }
  720.  
  721. #if    defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
  722.     int
  723. tty_setraw(on)
  724. {
  725. #  ifndef USE_TERMIO
  726.     if (on)
  727.         termbuf.sg.sg_flags |= RAW;
  728.     else
  729.         termbuf.sg.sg_flags &= ~RAW;
  730. #  else
  731.     if (on)
  732.         termbuf.c_lflag &= ~ICANON;
  733.     else
  734.         termbuf.c_lflag |= ICANON;
  735. #  endif
  736. }
  737. #endif
  738.  
  739.     void
  740. tty_binaryin(on)
  741.     int on;
  742. {
  743. #ifndef    USE_TERMIO
  744.     if (on)
  745.         termbuf.lflags |= LPASS8;
  746.     else
  747.         termbuf.lflags &= ~LPASS8;
  748. #else
  749.     if (on) {
  750.         termbuf.c_iflag &= ~ISTRIP;
  751.     } else {
  752.         termbuf.c_iflag |= ISTRIP;
  753.     }
  754. #endif
  755. }
  756.  
  757.     void
  758. tty_binaryout(on)
  759.     int on;
  760. {
  761. #ifndef    USE_TERMIO
  762.     if (on)
  763.         termbuf.lflags |= LLITOUT;
  764.     else
  765.         termbuf.lflags &= ~LLITOUT;
  766. #else
  767.     if (on) {
  768.         termbuf.c_cflag &= ~(CSIZE|PARENB);
  769.         termbuf.c_cflag |= CS8;
  770.         termbuf.c_oflag &= ~OPOST;
  771.     } else {
  772.         termbuf.c_cflag &= ~CSIZE;
  773.         termbuf.c_cflag |= CS7|PARENB;
  774.         termbuf.c_oflag |= OPOST;
  775.     }
  776. #endif
  777. }
  778.  
  779.     int
  780. tty_isbinaryin()
  781. {
  782. #ifndef    USE_TERMIO
  783.     return(termbuf.lflags & LPASS8);
  784. #else
  785.     return(!(termbuf.c_iflag & ISTRIP));
  786. #endif
  787. }
  788.  
  789.     int
  790. tty_isbinaryout()
  791. {
  792. #ifndef    USE_TERMIO
  793.     return(termbuf.lflags & LLITOUT);
  794. #else
  795.     return(!(termbuf.c_oflag&OPOST));
  796. #endif
  797. }
  798.  
  799. #ifdef    LINEMODE
  800.     int
  801. tty_isediting()
  802. {
  803. #ifndef USE_TERMIO
  804.     return(!(termbuf.sg.sg_flags & (CBREAK|RAW)));
  805. #else
  806.     return(termbuf.c_lflag & ICANON);
  807. #endif
  808. }
  809.  
  810.     int
  811. tty_istrapsig()
  812. {
  813. #ifndef USE_TERMIO
  814.     return(!(termbuf.sg.sg_flags&RAW));
  815. #else
  816.     return(termbuf.c_lflag & ISIG);
  817. #endif
  818. }
  819.  
  820.     void
  821. tty_setedit(on)
  822.     int on;
  823. {
  824. #ifndef USE_TERMIO
  825.     if (on)
  826.         termbuf.sg.sg_flags &= ~CBREAK;
  827.     else
  828.         termbuf.sg.sg_flags |= CBREAK;
  829. #else
  830.     if (on)
  831.         termbuf.c_lflag |= ICANON;
  832.     else
  833.         termbuf.c_lflag &= ~ICANON;
  834. #endif
  835. }
  836.  
  837.     void
  838. tty_setsig(on)
  839.     int on;
  840. {
  841. #ifndef    USE_TERMIO
  842.     if (on)
  843.         ;
  844. #else
  845.     if (on)
  846.         termbuf.c_lflag |= ISIG;
  847.     else
  848.         termbuf.c_lflag &= ~ISIG;
  849. #endif
  850. }
  851. #endif    /* LINEMODE */
  852.  
  853.     int
  854. tty_issofttab()
  855. {
  856. #ifndef    USE_TERMIO
  857.     return (termbuf.sg.sg_flags & XTABS);
  858. #else
  859. # ifdef    OXTABS
  860.     return (termbuf.c_oflag & OXTABS);
  861. # endif
  862. # ifdef    TABDLY
  863.     return ((termbuf.c_oflag & TABDLY) == TAB3);
  864. # endif
  865. #endif
  866. }
  867.  
  868.     void
  869. tty_setsofttab(on)
  870.     int on;
  871. {
  872. #ifndef    USE_TERMIO
  873.     if (on)
  874.         termbuf.sg.sg_flags |= XTABS;
  875.     else
  876.         termbuf.sg.sg_flags &= ~XTABS;
  877. #else
  878.     if (on) {
  879. # ifdef    OXTABS
  880.         termbuf.c_oflag |= OXTABS;
  881. # endif
  882. # ifdef    TABDLY
  883.         termbuf.c_oflag &= ~TABDLY;
  884.         termbuf.c_oflag |= TAB3;
  885. # endif
  886.     } else {
  887. # ifdef    OXTABS
  888.         termbuf.c_oflag &= ~OXTABS;
  889. # endif
  890. # ifdef    TABDLY
  891.         termbuf.c_oflag &= ~TABDLY;
  892.         termbuf.c_oflag |= TAB0;
  893. # endif
  894.     }
  895. #endif
  896. }
  897.  
  898.     int
  899. tty_islitecho()
  900. {
  901. #ifndef    USE_TERMIO
  902.     return (!(termbuf.lflags & LCTLECH));
  903. #else
  904. # ifdef    ECHOCTL
  905.     return (!(termbuf.c_lflag & ECHOCTL));
  906. # endif
  907. # ifdef    TCTLECH
  908.     return (!(termbuf.c_lflag & TCTLECH));
  909. # endif
  910. # if    !defined(ECHOCTL) && !defined(TCTLECH)
  911.     return (0);    /* assumes ctl chars are echoed '^x' */
  912. # endif
  913. #endif
  914. }
  915.  
  916.     void
  917. tty_setlitecho(on)
  918.     int on;
  919. {
  920. #ifndef    USE_TERMIO
  921.     if (on)
  922.         termbuf.lflags &= ~LCTLECH;
  923.     else
  924.         termbuf.lflags |= LCTLECH;
  925. #else
  926. # ifdef    ECHOCTL
  927.     if (on)
  928.         termbuf.c_lflag &= ~ECHOCTL;
  929.     else
  930.         termbuf.c_lflag |= ECHOCTL;
  931. # endif
  932. # ifdef    TCTLECH
  933.     if (on)
  934.         termbuf.c_lflag &= ~TCTLECH;
  935.     else
  936.         termbuf.c_lflag |= TCTLECH;
  937. # endif
  938. #endif
  939. }
  940.  
  941.     int
  942. tty_iscrnl()
  943. {
  944. #ifndef    USE_TERMIO
  945.     return (termbuf.sg.sg_flags & CRMOD);
  946. #else
  947.     return (termbuf.c_iflag & ICRNL);
  948. #endif
  949. }
  950.  
  951. /*
  952.  * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD).
  953.  */
  954. #if B4800 != 4800
  955. #define    DECODE_BAUD
  956. #endif
  957.  
  958. #ifdef    DECODE_BAUD
  959.  
  960. /*
  961.  * A table of available terminal speeds
  962.  */
  963. struct termspeeds {
  964.     int    speed;
  965.     int    value;
  966. } termspeeds[] = {
  967.     { 0,     B0 },    { 50,    B50 },   { 75,    B75 },
  968.     { 110,   B110 },  { 134,   B134 },  { 150,   B150 },
  969.     { 200,   B200 },  { 300,   B300 },  { 600,   B600 },
  970.     { 1200,  B1200 }, { 1800,  B1800 }, { 2400,  B2400 },
  971.     { 4800,   B4800 },
  972. #ifdef    B7200
  973.     { 7200,  B7200 },
  974. #endif
  975.     { 9600,   B9600 },
  976. #ifdef    B14400
  977.     { 14400,  B14400 },
  978. #endif
  979. #ifdef    B19200
  980.     { 19200,  B19200 },
  981. #endif
  982. #ifdef    B28800
  983.     { 28800,  B28800 },
  984. #endif
  985. #ifdef    B38400
  986.     { 38400,  B38400 },
  987. #endif
  988. #ifdef    B57600
  989.     { 57600,  B57600 },
  990. #endif
  991. #ifdef    B115200
  992.     { 115200, B115200 },
  993. #endif
  994. #ifdef    B230400
  995.     { 230400, B230400 },
  996. #endif
  997.     { -1,     0 }
  998. };
  999. #endif    /* DECODE_BUAD */
  1000.  
  1001.     void
  1002. tty_tspeed(val)
  1003.     int val;
  1004. {
  1005. #ifdef    DECODE_BAUD
  1006.     register struct termspeeds *tp;
  1007.  
  1008.     for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
  1009.         ;
  1010.     if (tp->speed == -1)    /* back up to last valid value */
  1011.         --tp;
  1012.     cfsetospeed(&termbuf, tp->value);
  1013. #else    /* DECODE_BUAD */
  1014.     cfsetospeed(&termbuf, val);
  1015. #endif    /* DECODE_BUAD */
  1016. }
  1017.  
  1018.     void
  1019. tty_rspeed(val)
  1020.     int val;
  1021. {
  1022. #ifdef    DECODE_BAUD
  1023.     register struct termspeeds *tp;
  1024.  
  1025.     for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
  1026.         ;
  1027.     if (tp->speed == -1)    /* back up to last valid value */
  1028.         --tp;
  1029.     cfsetispeed(&termbuf, tp->value);
  1030. #else    /* DECODE_BAUD */
  1031.     cfsetispeed(&termbuf, val);
  1032. #endif    /* DECODE_BAUD */
  1033. }
  1034.  
  1035. #if    defined(CRAY2) && defined(UNICOS5)
  1036.     int
  1037. tty_isnewmap()
  1038. {
  1039.     return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) &&
  1040.             !(termbuf.c_oflag & ONLRET));
  1041. }
  1042. #endif
  1043.  
  1044. #ifdef PARENT_DOES_UTMP
  1045. # ifndef NEWINIT
  1046. extern    struct utmp wtmp;
  1047. extern char wtmpf[];
  1048. # else    /* NEWINIT */
  1049. int    gotalarm;
  1050.  
  1051.     /* ARGSUSED */
  1052.     void
  1053. nologinproc(sig)
  1054.     int sig;
  1055. {
  1056.     gotalarm++;
  1057. }
  1058. # endif    /* NEWINIT */
  1059. #endif /* PARENT_DOES_UTMP */
  1060.  
  1061. #ifndef    NEWINIT
  1062. # ifdef PARENT_DOES_UTMP
  1063. extern void utmp_sig_init P((void));
  1064. extern void utmp_sig_reset P((void));
  1065. extern void utmp_sig_wait P((void));
  1066. extern void utmp_sig_notify P((int));
  1067. # endif /* PARENT_DOES_UTMP */
  1068. #endif
  1069.  
  1070. /*
  1071.  * getptyslave()
  1072.  *
  1073.  * Open the slave side of the pty, and do any initialization
  1074.  * that is necessary.  The return value is a file descriptor
  1075.  * for the slave side.
  1076.  */
  1077.     int
  1078. getptyslave()
  1079. {
  1080.     register int t = -1;
  1081.  
  1082. #if    !defined(CRAY) || !defined(NEWINIT)
  1083. # ifdef    LINEMODE
  1084.     int waslm;
  1085. # endif
  1086. # ifdef    TIOCGWINSZ
  1087.     struct winsize ws;
  1088.     extern int def_row, def_col;
  1089. # endif
  1090.     extern int def_tspeed, def_rspeed;
  1091.     /*
  1092.      * Opening the slave side may cause initilization of the
  1093.      * kernel tty structure.  We need remember the state of
  1094.      *     if linemode was turned on
  1095.      *    terminal window size
  1096.      *    terminal speed
  1097.      * so that we can re-set them if we need to.
  1098.      */
  1099. # ifdef    LINEMODE
  1100.     waslm = tty_linemode();
  1101. # endif
  1102.  
  1103.  
  1104.     /*
  1105.      * Make sure that we don't have a controlling tty, and
  1106.      * that we are the session (process group) leader.
  1107.      */
  1108. # ifdef    TIOCNOTTY
  1109.     t = open(_PATH_TTY, O_RDWR);
  1110.     if (t >= 0) {
  1111.         (void) ioctl(t, TIOCNOTTY, (char *)0);
  1112.         (void) close(t);
  1113.     }
  1114. # endif
  1115.  
  1116.  
  1117. # ifdef PARENT_DOES_UTMP
  1118.     /*
  1119.      * Wait for our parent to get the utmp stuff to get done.
  1120.      */
  1121.     utmp_sig_wait();
  1122. # endif
  1123.  
  1124.     t = cleanopen(line);
  1125.     if (t < 0)
  1126.         fatalperror(net, line);
  1127.  
  1128. #ifdef  STREAMSPTY
  1129. #ifdef    USE_TERMIO
  1130.     ttyfd = t;
  1131. #endif
  1132.     if (ioctl(t, I_PUSH, "ptem") < 0) 
  1133.         fatal(net, "I_PUSH ptem");
  1134.     if (ioctl(t, I_PUSH, "ldterm") < 0)
  1135.         fatal(net, "I_PUSH ldterm");
  1136.     if (ioctl(t, I_PUSH, "ttcompat") < 0)
  1137.         fatal(net, "I_PUSH ttcompat");
  1138.     if (ioctl(pty, I_PUSH, "pckt") < 0)
  1139.         fatal(net, "I_PUSH pckt");
  1140. #endif
  1141.  
  1142.     /*
  1143.      * set up the tty modes as we like them to be.
  1144.      */
  1145.     init_termbuf();
  1146. # ifdef    TIOCGWINSZ
  1147.     if (def_row || def_col) {
  1148.         memset((char *)&ws, 0, sizeof(ws));
  1149.         ws.ws_col = def_col;
  1150.         ws.ws_row = def_row;
  1151.         (void)ioctl(t, TIOCSWINSZ, (char *)&ws);
  1152.     }
  1153. # endif
  1154.  
  1155.     /*
  1156.      * Settings for sgtty based systems
  1157.      */
  1158. # ifndef    USE_TERMIO
  1159.     termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS;
  1160. # endif    /* USE_TERMIO */
  1161.  
  1162.     /*
  1163.      * Settings for UNICOS (and HPUX)
  1164.      */
  1165. # if defined(CRAY) || defined(__hpux)
  1166.     termbuf.c_oflag = OPOST|ONLCR|TAB3;
  1167.     termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
  1168.     termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
  1169.     termbuf.c_cflag = EXTB|HUPCL|CS8;
  1170. # endif
  1171.  
  1172.     /*
  1173.      * Settings for all other termios/termio based
  1174.      * systems, other than 4.4BSD.  In 4.4BSD the
  1175.      * kernel does the initial terminal setup.
  1176.      */
  1177. # if defined(USE_TERMIO) && !(defined(CRAY) || defined(__hpux)) && (BSD <= 43)
  1178. #  ifndef    OXTABS
  1179. #   define OXTABS    0
  1180. #  endif
  1181.     termbuf.c_lflag |= ECHO;
  1182.     termbuf.c_oflag |= ONLCR|OXTABS;
  1183.     termbuf.c_iflag |= ICRNL;
  1184.     termbuf.c_iflag &= ~IXOFF;
  1185. # endif /* defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43) */
  1186.     tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600);
  1187.     tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600);
  1188. # ifdef    LINEMODE
  1189.     if (waslm)
  1190.         tty_setlinemode(1);
  1191. # endif    /* LINEMODE */
  1192.  
  1193.     /*
  1194.      * Set the tty modes, and make this our controlling tty.
  1195.      */
  1196.     set_termbuf();
  1197.     if (login_tty(t) == -1)
  1198.         fatalperror(net, "login_tty");
  1199. #endif    /* !defined(CRAY) || !defined(NEWINIT) */
  1200.     if (net > 2)
  1201.         (void) close(net);
  1202. #if    defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
  1203.     /*
  1204.      * Leave the pty open so that we can write out the rlogin
  1205.      * protocol for /bin/login, if the authentication works.
  1206.      */
  1207. #else
  1208.     if (pty > 2) {
  1209.         (void) close(pty);
  1210.         pty = -1;
  1211.     }
  1212. #endif
  1213. }
  1214.  
  1215. #if    !defined(CRAY) || !defined(NEWINIT)
  1216. #ifndef    O_NOCTTY
  1217. #define    O_NOCTTY    0
  1218. #endif
  1219. /*
  1220.  * Open the specified slave side of the pty,
  1221.  * making sure that we have a clean tty.
  1222.  */
  1223.     int
  1224. cleanopen(line)
  1225.     char *line;
  1226. {
  1227.     register int t;
  1228. #ifdef    UNICOS7x
  1229.     struct secstat secbuf;
  1230. #endif    /* UNICOS7x */
  1231.  
  1232. #ifndef STREAMSPTY
  1233.     /*
  1234.      * Make sure that other people can't open the
  1235.      * slave side of the connection.
  1236.      */
  1237.     (void) chown(line, 0, 0);
  1238.     (void) chmod(line, 0600);
  1239. #endif
  1240.  
  1241. # if !defined(CRAY) && (BSD > 43)
  1242.     (void) revoke(line);
  1243. # endif
  1244. #ifdef    UNICOS7x
  1245.     if (secflag) {
  1246.         if (secstat(line, &secbuf) < 0)
  1247.             return(-1);
  1248.         if (setulvl(secbuf.st_slevel) < 0)
  1249.             return(-1);
  1250.         if (setucmp(secbuf.st_compart) < 0)
  1251.             return(-1);
  1252.     }
  1253. #endif    /* UNICOS7x */
  1254.  
  1255.     t = open(line, O_RDWR|O_NOCTTY);
  1256.  
  1257. #ifdef    UNICOS7x
  1258.     if (secflag) {
  1259.         if (setulvl(sysv.sy_minlvl) < 0)
  1260.             return(-1);
  1261.         if (setucmp(0) < 0)
  1262.             return(-1);
  1263.     }
  1264. #endif    /* UNICOS7x */
  1265.  
  1266.     if (t < 0)
  1267.         return(-1);
  1268.  
  1269.     /*
  1270.      * Hangup anybody else using this ttyp, then reopen it for
  1271.      * ourselves.
  1272.      */
  1273. # if !(defined(CRAY) || defined(__hpux)) && (BSD <= 43) && !defined(STREAMSPTY)
  1274.     (void) signal(SIGHUP, SIG_IGN);
  1275.     vhangup();
  1276.     (void) signal(SIGHUP, SIG_DFL);
  1277.     t = open(line, O_RDWR|O_NOCTTY);
  1278.     if (t < 0)
  1279.         return(-1);
  1280. # endif
  1281. # if    defined(CRAY) && defined(TCVHUP)
  1282.     {
  1283.         register int i;
  1284.         (void) signal(SIGHUP, SIG_IGN);
  1285.         (void) ioctl(t, TCVHUP, (char *)0);
  1286.         (void) signal(SIGHUP, SIG_DFL);
  1287.  
  1288. #ifdef    UNICOS7x
  1289.         if (secflag) {
  1290.             if (secstat(line, &secbuf) < 0)
  1291.                 return(-1);
  1292.             if (setulvl(secbuf.st_slevel) < 0)
  1293.                 return(-1);
  1294.             if (setucmp(secbuf.st_compart) < 0)
  1295.                 return(-1);
  1296.         }
  1297. #endif    /* UNICOS7x */
  1298.  
  1299.         i = open(line, O_RDWR);
  1300.  
  1301. #ifdef    UNICOS7x
  1302.         if (secflag) {
  1303.             if (setulvl(sysv.sy_minlvl) < 0)
  1304.                 return(-1);
  1305.             if (setucmp(0) < 0)
  1306.                 return(-1);
  1307.         }
  1308. #endif    /* UNICOS7x */
  1309.  
  1310.         if (i < 0)
  1311.             return(-1);
  1312.         (void) close(t);
  1313.         t = i;
  1314.     }
  1315. # endif    /* defined(CRAY) && defined(TCVHUP) */
  1316.     return(t);
  1317. }
  1318. #endif    /* !defined(CRAY) || !defined(NEWINIT) */
  1319.  
  1320. #if BSD <= 43
  1321.  
  1322.     int
  1323. login_tty(t)
  1324.     int t;
  1325. {
  1326.     if (setsid() < 0) {
  1327. #ifdef ultrix
  1328.         /*
  1329.          * The setsid() may have failed because we
  1330.          * already have a pgrp == pid.  Zero out
  1331.          * our pgrp and try again...
  1332.          */
  1333.         if ((setpgrp(0, 0) < 0) || (setsid() < 0))
  1334. #endif
  1335.             fatalperror(net, "setsid()");
  1336.     }
  1337. # ifdef    TIOCSCTTY
  1338.     if (ioctl(t, TIOCSCTTY, (char *)0) < 0)
  1339.         fatalperror(net, "ioctl(sctty)");
  1340. #  if defined(CRAY)
  1341.     /*
  1342.      * Close the hard fd to /dev/ttypXXX, and re-open through
  1343.      * the indirect /dev/tty interface.
  1344.      */
  1345.     close(t);
  1346.     if ((t = open("/dev/tty", O_RDWR)) < 0)
  1347.         fatalperror(net, "open(/dev/tty)");
  1348. #  endif
  1349. # else
  1350.     /*
  1351.      * We get our controlling tty assigned as a side-effect
  1352.      * of opening up a tty device.  But on BSD based systems,
  1353.      * this only happens if our process group is zero.  The
  1354.      * setsid() call above may have set our pgrp, so clear
  1355.      * it out before opening the tty...
  1356.      */
  1357. #  ifndef SOLARIS
  1358.     (void) setpgrp(0, 0);
  1359. #  else
  1360.     (void) setpgrp();
  1361. #  endif
  1362.     close(open(line, O_RDWR));
  1363. # endif
  1364.     if (t != 0)
  1365.         (void) dup2(t, 0);
  1366.     if (t != 1)
  1367.         (void) dup2(t, 1);
  1368.     if (t != 2)
  1369.         (void) dup2(t, 2);
  1370.     if (t > 2)
  1371.         close(t);
  1372.     return(0);
  1373. }
  1374. #endif    /* BSD <= 43 */
  1375.  
  1376. #ifdef    NEWINIT
  1377. char *gen_id = "fe";
  1378. #endif
  1379.  
  1380. /*
  1381.  * startslave(host)
  1382.  *
  1383.  * Given a hostname, do whatever
  1384.  * is necessary to startup the login process on the slave side of the pty.
  1385.  */
  1386.  
  1387. /* ARGSUSED */
  1388.     void
  1389. startslave(host, autologin, autoname)
  1390.     char *host;
  1391.     int autologin;
  1392.     char *autoname;
  1393. {
  1394.     register int i;
  1395.     long time();
  1396.     char name[256];
  1397. #ifdef    NEWINIT
  1398.     extern char *ptyip;
  1399.     struct init_request request;
  1400.     void nologinproc();
  1401.     register int n;
  1402. #endif    /* NEWINIT */
  1403.  
  1404. #if    defined(AUTHENTICATION)
  1405.     if (!autoname || !autoname[0])
  1406.         autologin = 0;
  1407.  
  1408.     if (autologin < auth_level) {
  1409.         fatal(net, "Authorization failed");
  1410.         exit(1);
  1411.     }
  1412. #endif
  1413.  
  1414. #ifndef    NEWINIT
  1415. # ifdef    PARENT_DOES_UTMP
  1416.     utmp_sig_init();
  1417. # endif    /* PARENT_DOES_UTMP */
  1418.  
  1419.     if ((i = fork()) < 0)
  1420.         fatalperror(net, "fork");
  1421.     if (i) {
  1422. # ifdef PARENT_DOES_UTMP
  1423.         /*
  1424.          * Cray parent will create utmp entry for child and send
  1425.          * signal to child to tell when done.  Child waits for signal
  1426.          * before doing anything important.
  1427.          */
  1428.         register int pid = i;
  1429.         void sigjob P((int));
  1430.  
  1431.         setpgrp();
  1432.         utmp_sig_reset();        /* reset handler to default */
  1433.         /*
  1434.          * Create utmp entry for child
  1435.          */
  1436.         (void) time(&wtmp.ut_time);
  1437.         wtmp.ut_type = LOGIN_PROCESS;
  1438.         wtmp.ut_pid = pid;
  1439.         SCPYN(wtmp.ut_user, "LOGIN");
  1440.         SCPYN(wtmp.ut_host, host);
  1441.         SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1);
  1442. #ifndef    __hpux
  1443.         SCPYN(wtmp.ut_id, wtmp.ut_line+3);
  1444. #else
  1445.         SCPYN(wtmp.ut_id, wtmp.ut_line+7);
  1446. #endif
  1447.         pututline(&wtmp);
  1448.         endutent();
  1449.         if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) {
  1450.             (void) write(i, (char *)&wtmp, sizeof(struct utmp));
  1451.             (void) close(i);
  1452.         }
  1453. #ifdef    CRAY
  1454.         (void) signal(WJSIGNAL, sigjob);
  1455. #endif
  1456.         utmp_sig_notify(pid);
  1457. # endif    /* PARENT_DOES_UTMP */
  1458.     } else {
  1459.         getptyslave(autologin);
  1460.         start_login(host, autologin, autoname);
  1461.         /*NOTREACHED*/
  1462.     }
  1463. #else    /* NEWINIT */
  1464.  
  1465.     /*
  1466.      * Init will start up login process if we ask nicely.  We only wait
  1467.      * for it to start up and begin normal telnet operation.
  1468.      */
  1469.     if ((i = open(INIT_FIFO, O_WRONLY)) < 0) {
  1470.         char tbuf[128];
  1471.         (void) sprintf(tbuf, "Can't open %s\n", INIT_FIFO);
  1472.         fatalperror(net, tbuf);
  1473.     }
  1474.     memset((char *)&request, 0, sizeof(request));
  1475.     request.magic = INIT_MAGIC;
  1476.     SCPYN(request.gen_id, gen_id);
  1477.     SCPYN(request.tty_id, &line[8]);
  1478.     SCPYN(request.host, host);
  1479.     SCPYN(request.term_type, terminaltype ? terminaltype : "network");
  1480. #if    !defined(UNICOS5)
  1481.     request.signal = SIGCLD;
  1482.     request.pid = getpid();
  1483. #endif
  1484. #ifdef BFTPDAEMON
  1485.     /*
  1486.      * Are we working as the bftp daemon?
  1487.      */
  1488.     if (bftpd) {
  1489.         SCPYN(request.exec_name, BFTPPATH);
  1490.     }
  1491. #endif /* BFTPDAEMON */
  1492.     if (write(i, (char *)&request, sizeof(request)) < 0) {
  1493.         char tbuf[128];
  1494.         (void) sprintf(tbuf, "Can't write to %s\n", INIT_FIFO);
  1495.         fatalperror(net, tbuf);
  1496.     }
  1497.     (void) close(i);
  1498.     (void) signal(SIGALRM, nologinproc);
  1499.     for (i = 0; ; i++) {
  1500.         char tbuf[128];
  1501.         alarm(15);
  1502.         n = read(pty, ptyip, BUFSIZ);
  1503.         if (i == 3 || n >= 0 || !gotalarm)
  1504.             break;
  1505.         gotalarm = 0;
  1506.         sprintf(tbuf, "telnetd: waiting for /etc/init to start login process on %s\r\n", line);
  1507.         (void) write(net, tbuf, strlen(tbuf));
  1508.     }
  1509.     if (n < 0 && gotalarm)
  1510.         fatal(net, "/etc/init didn't start login process");
  1511.     pcc += n;
  1512.     alarm(0);
  1513.     (void) signal(SIGALRM, SIG_DFL);
  1514.  
  1515.     return;
  1516. #endif    /* NEWINIT */
  1517. }
  1518.  
  1519. char    *envinit[3];
  1520. extern char **environ;
  1521.  
  1522.     void
  1523. init_env()
  1524. {
  1525.     extern char *getenv();
  1526.     char **envp;
  1527.  
  1528.     envp = envinit;
  1529.     if (*envp = getenv("TZ"))
  1530.         *envp++ -= 3;
  1531. #if    defined(CRAY) || defined(__hpux)
  1532.     else
  1533.         *envp++ = "TZ=GMT0";
  1534. #endif
  1535.     *envp = 0;
  1536.     environ = envinit;
  1537. }
  1538.  
  1539. #ifndef    NEWINIT
  1540.  
  1541. /*
  1542.  * start_login(host)
  1543.  *
  1544.  * Assuming that we are now running as a child processes, this
  1545.  * function will turn us into the login process.
  1546.  */
  1547.  
  1548.     void
  1549. start_login(host, autologin, name)
  1550.     char *host;
  1551.     int autologin;
  1552.     char *name;
  1553. {
  1554.     register char *cp;
  1555.     register char **argv;
  1556.     char **addarg();
  1557.     extern char *getenv();
  1558. #ifdef    UTMPX
  1559.     register int pid = getpid();
  1560.     struct utmpx utmpx;
  1561. #endif
  1562. #ifdef SOLARIS
  1563.     char *term;
  1564.     char termbuf[64];
  1565. #endif
  1566.  
  1567. #ifdef    UTMPX
  1568.     /*
  1569.      * Create utmp entry for child
  1570.      */
  1571.  
  1572.     memset(&utmpx, 0, sizeof(utmpx));
  1573.     SCPYN(utmpx.ut_user, ".telnet");
  1574.     SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1);
  1575.     utmpx.ut_pid = pid;
  1576.     utmpx.ut_id[0] = 't';
  1577.     utmpx.ut_id[1] = 'n';
  1578.     utmpx.ut_id[2] = SC_WILDC;
  1579.     utmpx.ut_id[3] = SC_WILDC;
  1580.     utmpx.ut_type = LOGIN_PROCESS;
  1581.     (void) time(&utmpx.ut_tv.tv_sec);
  1582.     if (pututxline(&utmpx) == NULL)
  1583.         fatal(net, "pututxline failed");
  1584. #endif
  1585.  
  1586.     /*
  1587.      * -h : pass on name of host.
  1588.      *        WARNING:  -h is accepted by login if and only if
  1589.      *            getuid() == 0.
  1590.      * -p : don't clobber the environment (so terminal type stays set).
  1591.      *
  1592.      * -f : force this login, he has already been authenticated
  1593.      */
  1594.     argv = addarg(0, "login");
  1595.  
  1596. #if    !defined(NO_LOGIN_H)
  1597.  
  1598. # if    defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
  1599.     /*
  1600.      * Don't add the "-h host" option if we are going
  1601.      * to be adding the "-r host" option down below...
  1602.      */
  1603.     if ((auth_level < 0) || (autologin != AUTH_VALID))
  1604. # endif
  1605.     {
  1606.         argv = addarg(argv, "-h");
  1607.         argv = addarg(argv, host);
  1608. #ifdef    SOLARIS
  1609.         /*
  1610.          * SVR4 version of -h takes TERM= as second arg, or -
  1611.          */
  1612.         term = getenv("TERM");
  1613.         if (term == NULL || term[0] == 0) {
  1614.             term = "-";
  1615.         } else {
  1616.             strcpy(termbuf, "TERM=");
  1617.             strncat(termbuf, term, sizeof(termbuf) - 6);
  1618.             term = termbuf;
  1619.         }
  1620.         argv = addarg(argv, term);
  1621. #endif
  1622.     }
  1623. #endif
  1624. #if    !defined(NO_LOGIN_P)
  1625.     argv = addarg(argv, "-p");
  1626. #endif
  1627. #ifdef    LINEMODE
  1628.     /*
  1629.      * Set the environment variable "LINEMODE" to either
  1630.      * "real" or "kludge" if we are operating in either
  1631.      * real or kludge linemode.
  1632.      */
  1633.     if (lmodetype == REAL_LINEMODE)
  1634.         setenv("LINEMODE", "real", 1);
  1635. # ifdef KLUDGELINEMODE
  1636.     else if (lmodetype == KLUDGE_LINEMODE || lmodetype == KLUDGE_OK)
  1637.         setenv("LINEMODE", "kludge", 1);
  1638. # endif
  1639. #endif
  1640. #ifdef    BFTPDAEMON
  1641.     /*
  1642.      * Are we working as the bftp daemon?  If so, then ask login
  1643.      * to start bftp instead of shell.
  1644.      */
  1645.     if (bftpd) {
  1646.         argv = addarg(argv, "-e");
  1647.         argv = addarg(argv, BFTPPATH);
  1648.     } else 
  1649. #endif
  1650. #if    defined (SecurID)
  1651.     /*
  1652.      * don't worry about the -f that might get sent.
  1653.      * A -s is supposed to override it anyhow.
  1654.      */
  1655.     if (require_SecurID)
  1656.         argv = addarg(argv, "-s");
  1657. #endif
  1658. #if    defined (AUTHENTICATION)
  1659.     if (auth_level >= 0 && autologin == AUTH_VALID) {
  1660. # if    !defined(NO_LOGIN_F)
  1661.         argv = addarg(argv, "-f");
  1662.         argv = addarg(argv, name);
  1663. # else
  1664. #  if defined(LOGIN_R)
  1665.         /*
  1666.          * We don't have support for "login -f", but we
  1667.          * can fool /bin/login into thinking that we are
  1668.          * rlogind, and allow us to log in without a
  1669.          * password.  The rlogin protocol expects
  1670.          *    local-user\0remote-user\0term/speed\0
  1671.          */
  1672.  
  1673.         if (pty > 2) {
  1674.             register char *cp;
  1675.             char speed[128];
  1676.             int isecho, israw, xpty, len;
  1677.             extern int def_rspeed;
  1678. #  ifndef LOGIN_HOST
  1679.             /*
  1680.              * Tell login that we are coming from "localhost".
  1681.              * If we passed in the real host name, then the
  1682.              * user would have to allow .rhost access from
  1683.              * every machine that they want authenticated
  1684.              * access to work from, which sort of defeats
  1685.              * the purpose of an authenticated login...
  1686.              * So, we tell login that the session is coming
  1687.              * from "localhost", and the user will only have
  1688.              * to have "localhost" in their .rhost file.
  1689.              */
  1690. #            define LOGIN_HOST "localhost"
  1691. #  endif
  1692.             argv = addarg(argv, "-r");
  1693.             argv = addarg(argv, LOGIN_HOST);
  1694.  
  1695.             xpty = pty;
  1696. # ifndef  STREAMSPTY
  1697.             pty = 0;
  1698. # else
  1699.             ttyfd = 0;
  1700. # endif
  1701.             init_termbuf();
  1702.             isecho = tty_isecho();
  1703.             israw = tty_israw();
  1704.             if (isecho || !israw) {
  1705.                 tty_setecho(0);        /* Turn off echo */
  1706.                 tty_setraw(1);        /* Turn on raw */
  1707.                 set_termbuf();
  1708.             }
  1709.             len = strlen(name)+1;
  1710.             write(xpty, name, len);
  1711.             write(xpty, name, len);
  1712.             sprintf(speed, "%s/%d", (cp = getenv("TERM")) ? cp : "",
  1713.                 (def_rspeed > 0) ? def_rspeed : 9600);
  1714.             len = strlen(speed)+1;
  1715.             write(xpty, speed, len);
  1716.  
  1717.             if (isecho || !israw) {
  1718.                 init_termbuf();
  1719.                 tty_setecho(isecho);
  1720.                 tty_setraw(israw);
  1721.                 set_termbuf();
  1722.                 if (!israw) {
  1723.                     /*
  1724.                      * Write a newline to ensure
  1725.                      * that login will be able to
  1726.                      * read the line...
  1727.                      */
  1728.                     write(xpty, "\n", 1);
  1729.                 }
  1730.             }
  1731.             pty = xpty;
  1732.         }
  1733. #  else
  1734.         argv = addarg(argv, name);
  1735. #  endif
  1736. # endif
  1737.     } else
  1738. #endif
  1739.     if (getenv("USER")) {
  1740.         argv = addarg(argv, getenv("USER"));
  1741. #if    defined(LOGIN_ARGS) && defined(NO_LOGIN_P)
  1742.         {
  1743.             register char **cpp;
  1744.             for (cpp = environ; *cpp; cpp++)
  1745.                 argv = addarg(argv, *cpp);
  1746.         }
  1747. #endif
  1748.         /*
  1749.          * Assume that login will set the USER variable
  1750.          * correctly.  For SysV systems, this means that
  1751.          * USER will no longer be set, just LOGNAME by
  1752.          * login.  (The problem is that if the auto-login
  1753.          * fails, and the user then specifies a different
  1754.          * account name, he can get logged in with both
  1755.          * LOGNAME and USER in his environment, but the
  1756.          * USER value will be wrong.
  1757.          */
  1758.         unsetenv("USER");
  1759.     }
  1760. #ifdef    SOLARIS
  1761.     else {
  1762.         char **p;
  1763.  
  1764.         argv = addarg(argv, "");    /* no login name */
  1765.         for (p = environ; *p; p++) {
  1766.             argv = addarg(argv, *p);
  1767.         }
  1768.     }
  1769. #endif    /* SOLARIS */
  1770. #if    defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
  1771.     if (pty > 2)
  1772.         close(pty);
  1773. #endif
  1774.     closelog();
  1775.     /*
  1776.      * This sleep(1) is in here so that telnetd can
  1777.      * finish up with the tty.  There's a race condition
  1778.      * the login banner message gets lost...
  1779.      */
  1780.     sleep(1);
  1781.     execv(PATH_LOGIN, argv);
  1782.  
  1783.     syslog(LOG_ERR, "%s: %m\n", PATH_LOGIN);
  1784.     fatalperror(net, PATH_LOGIN);
  1785.     /*NOTREACHED*/
  1786. }
  1787.  
  1788.     char **
  1789. addarg(argv, val)
  1790.     register char **argv;
  1791.     register char *val;
  1792. {
  1793.     register char **cpp;
  1794.  
  1795.     if (argv == NULL) {
  1796.         /*
  1797.          * 10 entries, a leading length, and a null
  1798.          */
  1799.         argv = (char **)malloc(sizeof(*argv) * 12);
  1800.         if (argv == NULL)
  1801.             return(NULL);
  1802.         *argv++ = (char *)10;
  1803.         *argv = (char *)0;
  1804.     }
  1805.     for (cpp = argv; *cpp; cpp++)
  1806.         ;
  1807.     if (cpp == &argv[(int)argv[-1]]) {
  1808.         --argv;
  1809.         *argv = (char *)((int)(*argv) + 10);
  1810.         argv = (char **)realloc(argv, sizeof(*argv)*((int)(*argv) + 2));
  1811.         if (argv == NULL)
  1812.             return(NULL);
  1813.         argv++;
  1814.         cpp = &argv[(int)argv[-1] - 10];
  1815.     }
  1816.     *cpp++ = val;
  1817.     *cpp = 0;
  1818.     return(argv);
  1819. }
  1820. #endif    /* NEWINIT */
  1821.  
  1822. /*
  1823.  * cleanup()
  1824.  *
  1825.  * This is the routine to call when we are all through, to
  1826.  * clean up anything that needs to be cleaned up.
  1827.  */
  1828.     /* ARGSUSED */
  1829.     void
  1830. cleanup(sig)
  1831.     int sig;
  1832. {
  1833. #ifndef    PARENT_DOES_UTMP
  1834. # if (BSD > 43) || defined(convex)
  1835.     char *p;
  1836.  
  1837.     p = line + sizeof("/dev/") - 1;
  1838.     if (logout(p))
  1839.         logwtmp(p, "", "");
  1840.     (void)chmod(line, 0666);
  1841.     (void)chown(line, 0, 0);
  1842.     *p = 'p';
  1843.     (void)chmod(line, 0666);
  1844.     (void)chown(line, 0, 0);
  1845.     (void) shutdown(net, 2);
  1846.     exit(1);
  1847. # else
  1848.     void rmut();
  1849.  
  1850.     rmut();
  1851.     vhangup();    /* XXX */
  1852.     (void) shutdown(net, 2);
  1853.     exit(1);
  1854. # endif
  1855. #else    /* PARENT_DOES_UTMP */
  1856. # ifdef    NEWINIT
  1857.     (void) shutdown(net, 2);
  1858.     exit(1);
  1859. # else    /* NEWINIT */
  1860. #  ifdef CRAY
  1861.     static int incleanup = 0;
  1862.     register int t;
  1863.     int child_status; /* status of child process as returned by waitpid */
  1864.     int flags = WNOHANG|WUNTRACED;
  1865.  
  1866.     /*
  1867.      * 1: Pick up the zombie, if we are being called
  1868.      *    as the signal handler.
  1869.      * 2: If we are a nested cleanup(), return.
  1870.      * 3: Try to clean up TMPDIR.
  1871.      * 4: Fill in utmp with shutdown of process.
  1872.      * 5: Close down the network and pty connections.
  1873.      * 6: Finish up the TMPDIR cleanup, if needed.
  1874.      */
  1875.     if (sig == SIGCHLD) {
  1876.         while (waitpid(-1, &child_status, flags) > 0)
  1877.             ;    /* VOID */
  1878.         /* Check if the child process was stopped
  1879.          * rather than exited.  We want cleanup only if
  1880.          * the child has died.
  1881.          */
  1882.         if (WIFSTOPPED(child_status)) {
  1883.             return;
  1884.         }
  1885.     }
  1886.     t = sigblock(sigmask(SIGCHLD));
  1887.     if (incleanup) {
  1888.         sigsetmask(t);
  1889.         return;
  1890.     }
  1891.     incleanup = 1;
  1892.     sigsetmask(t);
  1893. #ifdef    UNICOS7x
  1894.     if (secflag) {
  1895.         /*
  1896.          *    We need to set ourselves back to a null
  1897.          *    label to clean up.
  1898.          */
  1899.  
  1900.         setulvl(sysv.sy_minlvl);
  1901.         setucmp((long)0);
  1902.     }
  1903. #endif    /* UNICOS7x */
  1904.  
  1905.     t = cleantmp(&wtmp);
  1906.     setutent();    /* just to make sure */
  1907. #  endif /* CRAY */
  1908.     rmut(line);
  1909.     close(pty);
  1910.     (void) shutdown(net, 2);
  1911. #  ifdef CRAY
  1912.     if (t == 0)
  1913.         cleantmp(&wtmp);
  1914. #  endif /* CRAY */
  1915.     exit(1);
  1916. # endif    /* NEWINT */
  1917. #endif    /* PARENT_DOES_UTMP */
  1918. }
  1919.  
  1920. #if defined(PARENT_DOES_UTMP) && !defined(NEWINIT)
  1921. /*
  1922.  * _utmp_sig_rcv
  1923.  * utmp_sig_init
  1924.  * utmp_sig_wait
  1925.  *    These three functions are used to coordinate the handling of
  1926.  *    the utmp file between the server and the soon-to-be-login shell.
  1927.  *    The server actually creates the utmp structure, the child calls
  1928.  *    utmp_sig_wait(), until the server calls utmp_sig_notify() and
  1929.  *    signals the future-login shell to proceed.
  1930.  */
  1931. static int caught=0;        /* NZ when signal intercepted */
  1932. static void (*func)();        /* address of previous handler */
  1933.  
  1934.     void
  1935. _utmp_sig_rcv(sig)
  1936.     int sig;
  1937. {
  1938.     caught = 1;
  1939.     (void) signal(SIGUSR1, func);
  1940. }
  1941.  
  1942.     void
  1943. utmp_sig_init()
  1944. {
  1945.     /*
  1946.      * register signal handler for UTMP creation
  1947.      */
  1948.     if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1)
  1949.         fatalperror(net, "telnetd/signal");
  1950. }
  1951.  
  1952.     void
  1953. utmp_sig_reset()
  1954. {
  1955.     (void) signal(SIGUSR1, func);    /* reset handler to default */
  1956. }
  1957.  
  1958. # ifdef __hpux
  1959. # define sigoff() /* do nothing */
  1960. # define sigon() /* do nothing */
  1961. # endif
  1962.  
  1963.     void
  1964. utmp_sig_wait()
  1965. {
  1966.     /*
  1967.      * Wait for parent to write our utmp entry.
  1968.      */
  1969.     sigoff();
  1970.     while (caught == 0) {
  1971.         pause();    /* wait until we get a signal (sigon) */
  1972.         sigoff();    /* turn off signals while we check caught */
  1973.     }
  1974.     sigon();        /* turn on signals again */
  1975. }
  1976.  
  1977.     void
  1978. utmp_sig_notify(pid)
  1979. {
  1980.     kill(pid, SIGUSR1);
  1981. }
  1982.  
  1983. # ifdef CRAY
  1984. static int gotsigjob = 0;
  1985.  
  1986.     /*ARGSUSED*/
  1987.     void
  1988. sigjob(sig)
  1989.     int sig;
  1990. {
  1991.     register int jid;
  1992.     register struct jobtemp *jp;
  1993.  
  1994.     while ((jid = waitjob(NULL)) != -1) {
  1995.         if (jid == 0) {
  1996.             return;
  1997.         }
  1998.         gotsigjob++;
  1999.         jobend(jid, NULL, NULL);
  2000.     }
  2001. }
  2002.  
  2003. /*
  2004.  *    jid_getutid:
  2005.  *        called by jobend() before calling cleantmp()
  2006.  *        to find the correct $TMPDIR to cleanup.
  2007.  */
  2008.  
  2009.     struct utmp *
  2010. jid_getutid(jid)
  2011.     int jid;
  2012. {
  2013.     struct utmp *cur = NULL;
  2014.  
  2015.     setutent();    /* just to make sure */
  2016.     while (cur = getutent()) {
  2017.         if ( (cur->ut_type != NULL) && (jid == cur->ut_jid) ) {
  2018.             return(cur);
  2019.         }
  2020.     }
  2021.  
  2022.     return(0);
  2023. }
  2024.  
  2025. /*
  2026.  * Clean up the TMPDIR that login created.
  2027.  * The first time this is called we pick up the info
  2028.  * from the utmp.  If the job has already gone away,
  2029.  * then we'll clean up and be done.  If not, then
  2030.  * when this is called the second time it will wait
  2031.  * for the signal that the job is done.
  2032.  */
  2033.     int
  2034. cleantmp(wtp)
  2035.     register struct utmp *wtp;
  2036. {
  2037.     struct utmp *utp;
  2038.     static int first = 1;
  2039.     register int mask, omask, ret;
  2040.     extern struct utmp *getutid P((const struct utmp *_Id));
  2041.  
  2042.  
  2043.     mask = sigmask(WJSIGNAL);
  2044.  
  2045.     if (first == 0) {
  2046.         omask = sigblock(mask);
  2047.         while (gotsigjob == 0)
  2048.             sigpause(omask);
  2049.         return(1);
  2050.     }
  2051.     first = 0;
  2052.     setutent();    /* just to make sure */
  2053.  
  2054.     utp = getutid(wtp);
  2055.     if (utp == 0) {
  2056.         syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR");
  2057.         return(-1);
  2058.     }
  2059.     /*
  2060.      * Nothing to clean up if the user shell was never started.
  2061.      */
  2062.     if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0)
  2063.         return(1);
  2064.  
  2065.     /*
  2066.      * Block the WJSIGNAL while we are in jobend().
  2067.      */
  2068.     omask = sigblock(mask);
  2069.     ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user);
  2070.     sigsetmask(omask);
  2071.     return(ret);
  2072. }
  2073.  
  2074.     int
  2075. jobend(jid, path, user)
  2076.     register int jid;
  2077.     register char *path;
  2078.     register char *user;
  2079. {
  2080.     static int saved_jid = 0;
  2081.     static int pty_saved_jid = 0;
  2082.     static char saved_path[sizeof(wtmp.ut_tpath)+1];
  2083.     static char saved_user[sizeof(wtmp.ut_user)+1];
  2084.  
  2085.     /*
  2086.      * this little piece of code comes into play
  2087.      * only when ptyreconnect is used to reconnect
  2088.      * to an previous session.
  2089.      *
  2090.      * this is the only time when the
  2091.      * "saved_jid != jid" code is executed.
  2092.      */
  2093.  
  2094.     if ( saved_jid && saved_jid != jid ) {
  2095.         if (!path) {    /* called from signal handler */
  2096.             pty_saved_jid = jid;
  2097.         } else {
  2098.             pty_saved_jid = saved_jid;
  2099.         }
  2100.     }
  2101.  
  2102.     if (path) {
  2103.         strncpy(saved_path, path, sizeof(wtmp.ut_tpath));
  2104.         strncpy(saved_user, user, sizeof(wtmp.ut_user));
  2105.         saved_path[sizeof(saved_path)] = '\0';
  2106.         saved_user[sizeof(saved_user)] = '\0';
  2107.     }
  2108.     if (saved_jid == 0) {
  2109.         saved_jid = jid;
  2110.         return(0);
  2111.     }
  2112.  
  2113.     /* if the jid has changed, get the correct entry from the utmp file */
  2114.  
  2115.     if ( saved_jid != jid ) {
  2116.         struct utmp *utp = NULL;
  2117.         struct utmp *jid_getutid();
  2118.  
  2119.         utp = jid_getutid(pty_saved_jid);
  2120.  
  2121.         if (utp == 0) {
  2122.             syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR");
  2123.             return(-1);
  2124.         }
  2125.  
  2126.         cleantmpdir(jid, utp->ut_tpath, utp->ut_user);
  2127.         return(1);
  2128.     }
  2129.  
  2130.     cleantmpdir(jid, saved_path, saved_user);
  2131.     return(1);
  2132. }
  2133.  
  2134. /*
  2135.  * Fork a child process to clean up the TMPDIR
  2136.  */
  2137. cleantmpdir(jid, tpath, user)
  2138.     register int jid;
  2139.     register char *tpath;
  2140.     register char *user;
  2141. {
  2142.     switch(fork()) {
  2143.     case -1:
  2144.         syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m\n",
  2145.                             tpath);
  2146.         break;
  2147.     case 0:
  2148.         execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0);
  2149.         syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m\n",
  2150.                             tpath, CLEANTMPCMD);
  2151.         exit(1);
  2152.     default:
  2153.         /*
  2154.          * Forget about child.  We will exit, and
  2155.          * /etc/init will pick it up.
  2156.          */
  2157.         break;
  2158.     }
  2159. }
  2160. # endif /* CRAY */
  2161. #endif    /* defined(PARENT_DOES_UTMP) && !defined(NEWINIT) */
  2162.  
  2163. /*
  2164.  * rmut()
  2165.  *
  2166.  * This is the function called by cleanup() to
  2167.  * remove the utmp entry for this person.
  2168.  */
  2169.  
  2170. #ifdef    UTMPX
  2171.     void
  2172. rmut()
  2173. {
  2174.     register f;
  2175.     int found = 0;
  2176.     struct utmp *u, *utmp;
  2177.     int nutmp;
  2178.     struct stat statbf;
  2179.  
  2180.     struct utmpx *utxp, utmpx;
  2181.  
  2182.     /*
  2183.      * This updates the utmpx and utmp entries and make a wtmp/x entry
  2184.      */
  2185.  
  2186.     SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1);
  2187.     utxp = getutxline(&utmpx);
  2188.     if (utxp) {
  2189.         utxp->ut_type = DEAD_PROCESS;
  2190.         utxp->ut_exit.e_termination = 0;
  2191.         utxp->ut_exit.e_exit = 0;
  2192.         (void) time(&utmpx.ut_tv.tv_sec);
  2193.         utmpx.ut_tv.tv_usec = 0;
  2194.         modutx(utxp);
  2195.     }
  2196.     endutxent();
  2197. }  /* end of rmut */
  2198. #endif
  2199.  
  2200. #if    !defined(UTMPX) && !(defined(CRAY) || defined(__hpux)) && BSD <= 43
  2201.     void
  2202. rmut()
  2203. {
  2204.     register f;
  2205.     int found = 0;
  2206.     struct utmp *u, *utmp;
  2207.     int nutmp;
  2208.     struct stat statbf;
  2209.  
  2210.     f = open(utmpf, O_RDWR);
  2211.     if (f >= 0) {
  2212.         (void) fstat(f, &statbf);
  2213.         utmp = (struct utmp *)malloc((unsigned)statbf.st_size);
  2214.         if (!utmp)
  2215.             syslog(LOG_ERR, "utmp malloc failed");
  2216.         if (statbf.st_size && utmp) {
  2217.             nutmp = read(f, (char *)utmp, (int)statbf.st_size);
  2218.             nutmp /= sizeof(struct utmp);
  2219.         
  2220.             for (u = utmp ; u < &utmp[nutmp] ; u++) {
  2221.                 if (SCMPN(u->ut_line, line+5) ||
  2222.                     u->ut_name[0]==0)
  2223.                     continue;
  2224.                 (void) lseek(f, ((long)u)-((long)utmp), L_SET);
  2225.                 SCPYN(u->ut_name, "");
  2226.                 SCPYN(u->ut_host, "");
  2227.                 (void) time(&u->ut_time);
  2228.                 (void) write(f, (char *)u, sizeof(wtmp));
  2229.                 found++;
  2230.             }
  2231.         }
  2232.         (void) close(f);
  2233.     }
  2234.     if (found) {
  2235.         f = open(wtmpf, O_WRONLY|O_APPEND);
  2236.         if (f >= 0) {
  2237.             SCPYN(wtmp.ut_line, line+5);
  2238.             SCPYN(wtmp.ut_name, "");
  2239.             SCPYN(wtmp.ut_host, "");
  2240.             (void) time(&wtmp.ut_time);
  2241.             (void) write(f, (char *)&wtmp, sizeof(wtmp));
  2242.             (void) close(f);
  2243.         }
  2244.     }
  2245.     (void) chmod(line, 0666);
  2246.     (void) chown(line, 0, 0);
  2247.     line[strlen("/dev/")] = 'p';
  2248.     (void) chmod(line, 0666);
  2249.     (void) chown(line, 0, 0);
  2250. }  /* end of rmut */
  2251. #endif    /* CRAY */
  2252.  
  2253. #ifdef __hpux
  2254. rmut (line)
  2255. char *line;
  2256. {
  2257.     struct utmp utmp;
  2258.     struct utmp *utptr;
  2259.     int fd;            /* for /etc/wtmp */
  2260.  
  2261.     utmp.ut_type = USER_PROCESS;
  2262.     (void) strncpy(utmp.ut_id, line+12, sizeof(utmp.ut_id));
  2263.     (void) setutent();
  2264.     utptr = getutid(&utmp);
  2265.     /* write it out only if it exists */
  2266.     if (utptr) {
  2267.         utptr->ut_type = DEAD_PROCESS;
  2268.         utptr->ut_time = time((long *) 0);
  2269.         (void) pututline(utptr);
  2270.         /* set wtmp entry if wtmp file exists */
  2271.         if ((fd = open(wtmpf, O_WRONLY | O_APPEND)) >= 0) {
  2272.             (void) write(fd, utptr, sizeof(utmp));
  2273.             (void) close(fd);
  2274.         }
  2275.     }
  2276.     (void) endutent();
  2277.  
  2278.     (void) chmod(line, 0666);
  2279.     (void) chown(line, 0, 0);
  2280.     line[14] = line[13];
  2281.     line[13] = line[12];
  2282.     line[8] = 'm';
  2283.     line[9] = '/';
  2284.     line[10] = 'p';
  2285.     line[11] = 't';
  2286.     line[12] = 'y';
  2287.     (void) chmod(line, 0666);
  2288.     (void) chown(line, 0, 0);
  2289. }
  2290. #endif
  2291.