BSD 4_4_Lite2 release
[unix-history] / usr / src / libexec / telnetd / sys_term.c
index 1ba42e6..58d2e98 100644 (file)
 /*
 /*
- * Copyright (c) 1989 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  *
- * %sccs.include.redist.c%
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)sys_term.c 5.16 (Berkeley) %G%";
+static char sccsid[] = "@(#)sys_term.c 8.4 (Berkeley) 5/30/95";
 #endif /* not lint */
 
 #include "telnetd.h"
 #include "pathnames.h"
 
 #endif /* not lint */
 
 #include "telnetd.h"
 #include "pathnames.h"
 
-#if    defined(AUTHENTICATE)
+#if    defined(AUTHENTICATION)
 #include <libtelnet/auth.h>
 #endif
 
 #include <libtelnet/auth.h>
 #endif
 
+#if defined(CRAY) || defined(__hpux)
+# define PARENT_DOES_UTMP
+#endif
+
 #ifdef NEWINIT
 #include <initreq.h>
 #ifdef NEWINIT
 #include <initreq.h>
+int    utmp_len = MAXHOSTNAMELEN;      /* sizeof(init_request.host) */
 #else  /* NEWINIT*/
 #else  /* NEWINIT*/
-#include <utmp.h>
+# ifdef        UTMPX
+# include <utmpx.h>
+struct utmpx wtmp;
+# else
+# include <utmp.h>
 struct utmp wtmp;
 struct utmp wtmp;
+# endif /* UTMPX */
 
 
-# ifndef CRAY
+int    utmp_len = sizeof(wtmp.ut_host);
+# ifndef PARENT_DOES_UTMP
 char   wtmpf[] = "/usr/adm/wtmp";
 char   utmpf[] = "/etc/utmp";
 char   wtmpf[] = "/usr/adm/wtmp";
 char   utmpf[] = "/etc/utmp";
-# else /* CRAY */
+# else /* PARENT_DOES_UTMP */
 char   wtmpf[] = "/etc/wtmp";
 char   wtmpf[] = "/etc/wtmp";
+# endif /* PARENT_DOES_UTMP */
+
+# ifdef CRAY
 #include <tmpdir.h>
 #include <sys/wait.h>
 #include <tmpdir.h>
 #include <sys/wait.h>
+#  if (UNICOS_LVL == '7.0') || (UNICOS_LVL == '7.1')
+#   define UNICOS7x
+#  endif
+
+#  ifdef UNICOS7x
+#include <sys/sysv.h>
+#include <sys/secstat.h>
+extern int secflag;
+extern struct sysv sysv;
+#  endif /* UNICOS7x */
 # endif        /* CRAY */
 #endif /* NEWINIT */
 
 # endif        /* CRAY */
 #endif /* NEWINIT */
 
+#ifdef STREAMSPTY
+#include <sac.h>
+#include <sys/stropts.h>
+#endif
+
 #define SCPYN(a, b)    (void) strncpy(a, b, sizeof(a))
 #define SCMPN(a, b)    strncmp(a, b, sizeof(a))
 
 #ifdef STREAMS
 #include <sys/stream.h>
 #endif
 #define SCPYN(a, b)    (void) strncpy(a, b, sizeof(a))
 #define SCMPN(a, b)    strncmp(a, b, sizeof(a))
 
 #ifdef STREAMS
 #include <sys/stream.h>
 #endif
+#ifdef __hpux
+#include <sys/resource.h>
+#include <sys/proc.h>
+#endif
 #include <sys/tty.h>
 #ifdef t_erase
 #undef t_erase
 #include <sys/tty.h>
 #ifdef t_erase
 #undef t_erase
@@ -107,6 +166,9 @@ struct termbuf {
 #  endif
 # endif /* TCSANOW */
 struct termios termbuf, termbuf2;      /* pty control structure */
 #  endif
 # endif /* TCSANOW */
 struct termios termbuf, termbuf2;      /* pty control structure */
+# ifdef  STREAMSPTY
+int ttyfd = -1;
+# endif
 #endif /* USE_TERMIO */
 
 /*
 #endif /* USE_TERMIO */
 
 /*
@@ -131,7 +193,11 @@ init_termbuf()
        (void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state);
 # endif
 #else
        (void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state);
 # endif
 #else
+# ifdef  STREAMSPTY
+       (void) tcgetattr(ttyfd, &termbuf);
+# else
        (void) tcgetattr(pty, &termbuf);
        (void) tcgetattr(pty, &termbuf);
+# endif
 #endif
        termbuf2 = termbuf;
 }
 #endif
        termbuf2 = termbuf;
 }
@@ -144,7 +210,7 @@ copy_termbuf(cp, len)
 {
        if (len > sizeof(termbuf))
                len = sizeof(termbuf);
 {
        if (len > sizeof(termbuf))
                len = sizeof(termbuf);
-       bcopy(cp, (char *)&termbuf, len);
+       memmove((char *)&termbuf, cp, len);
        termbuf2 = termbuf;
 }
 #endif /* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */
        termbuf2 = termbuf;
 }
 #endif /* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */
@@ -156,19 +222,25 @@ set_termbuf()
         * Only make the necessary changes.
         */
 #ifndef        USE_TERMIO
         * Only make the necessary changes.
         */
 #ifndef        USE_TERMIO
-       if (bcmp((char *)&termbuf.sg, (char *)&termbuf2.sg, sizeof(termbuf.sg)))
+       if (memcmp((char *)&termbuf.sg, (char *)&termbuf2.sg,
+                                                       sizeof(termbuf.sg)))
                (void) ioctl(pty, TIOCSETN, (char *)&termbuf.sg);
                (void) ioctl(pty, TIOCSETN, (char *)&termbuf.sg);
-       if (bcmp((char *)&termbuf.tc, (char *)&termbuf2.tc, sizeof(termbuf.tc)))
+       if (memcmp((char *)&termbuf.tc, (char *)&termbuf2.tc,
+                                                       sizeof(termbuf.tc)))
                (void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc);
                (void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc);
-       if (bcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc,
+       if (memcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc,
                                                        sizeof(termbuf.ltc)))
                (void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc);
        if (termbuf.lflags != termbuf2.lflags)
                (void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags);
 #else  /* USE_TERMIO */
                                                        sizeof(termbuf.ltc)))
                (void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc);
        if (termbuf.lflags != termbuf2.lflags)
                (void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags);
 #else  /* USE_TERMIO */
-       if (bcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf)))
+       if (memcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf)))
+# ifdef  STREAMSPTY
+               (void) tcsetattr(ttyfd, TCSANOW, &termbuf);
+# else
                (void) tcsetattr(pty, TCSANOW, &termbuf);
                (void) tcsetattr(pty, TCSANOW, &termbuf);
-# if   defined(CRAY2) && defined(UNCIOS5)
+# endif
+# if   defined(CRAY2) && defined(UNICOS5)
        needtermstat = 1;
 # endif
 #endif /* USE_TERMIO */
        needtermstat = 1;
 # endif
 #endif /* USE_TERMIO */
@@ -398,44 +470,87 @@ char *myline = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
 #endif /* CRAY */
 
        int
 #endif /* CRAY */
 
        int
-getpty()
+getpty(ptynum)
+int *ptynum;
 {
        register int p;
 {
        register int p;
+#ifdef STREAMSPTY
+       int t;
+       char *ptsname();
+
+       p = open("/dev/ptmx", 2);
+       if (p > 0) {
+               grantpt(p);
+               unlockpt(p);
+               strcpy(line, ptsname(p));
+               return(p);
+       }
+
+#else  /* ! STREAMSPTY */
 #ifndef CRAY
 #ifndef CRAY
-       register char c, *p1, *p2;
+       register char *cp, *p1, *p2;
        register int i;
        register int i;
+#if defined(sun) && defined(TIOCGPGRP) && BSD < 199207
+       int dummy;
+#endif
 
 
+#ifndef        __hpux
        (void) sprintf(line, "/dev/ptyXX");
        p1 = &line[8];
        p2 = &line[9];
        (void) sprintf(line, "/dev/ptyXX");
        p1 = &line[8];
        p2 = &line[9];
+#else
+       (void) sprintf(line, "/dev/ptym/ptyXX");
+       p1 = &line[13];
+       p2 = &line[14];
+#endif
 
 
-       for (c = 'p'; c <= 's'; c++) {
+       for (cp = "pqrstuvwxyzPQRST"; *cp; cp++) {
                struct stat stb;
 
                struct stat stb;
 
-               *p1 = c;
+               *p1 = *cp;
                *p2 = '0';
                *p2 = '0';
+               /*
+                * This stat() check is just to keep us from
+                * looping through all 256 combinations if there
+                * aren't that many ptys available.
+                */
                if (stat(line, &stb) < 0)
                        break;
                for (i = 0; i < 16; i++) {
                        *p2 = "0123456789abcdef"[i];
                        p = open(line, 2);
                        if (p > 0) {
                if (stat(line, &stb) < 0)
                        break;
                for (i = 0; i < 16; i++) {
                        *p2 = "0123456789abcdef"[i];
                        p = open(line, 2);
                        if (p > 0) {
+#ifndef        __hpux
                                line[5] = 't';
                                line[5] = 't';
-                               return(p);
+#else
+                               for (p1 = &line[8]; *p1; p1++)
+                                       *p1 = *(p1+1);
+                               line[9] = 't';
+#endif
+                               chown(line, 0, 0);
+                               chmod(line, 0600);
+#if defined(sun) && defined(TIOCGPGRP) && BSD < 199207
+                               if (ioctl(p, TIOCGPGRP, &dummy) == 0
+                                   || errno != EIO) {
+                                       chmod(line, 0666);
+                                       close(p);
+                                       line[5] = 'p';
+                               } else
+#endif /* defined(sun) && defined(TIOCGPGRP) && BSD < 199207 */
+                                       return(p);
                        }
                }
        }
 #else  /* CRAY */
                        }
                }
        }
 #else  /* CRAY */
-       register int npty;
        extern lowpty, highpty;
        struct stat sb;
 
        extern lowpty, highpty;
        struct stat sb;
 
-       for (npty = lowpty; npty <= highpty; npty++) {
-               (void) sprintf(myline, "/dev/pty/%03d", npty);
+       for (*ptynum = lowpty; *ptynum <= highpty; (*ptynum)++) {
+               (void) sprintf(myline, "/dev/pty/%03d", *ptynum);
                p = open(myline, 2);
                if (p < 0)
                        continue;
                p = open(myline, 2);
                if (p < 0)
                        continue;
-               (void) sprintf(line, "/dev/ttyp%03d", npty);
+               (void) sprintf(line, "/dev/ttyp%03d", *ptynum);
                /*
                 * Here are some shenanigans to make sure that there
                 * are no listeners lurking on the line.
                /*
                 * Here are some shenanigans to make sure that there
                 * are no listeners lurking on the line.
@@ -463,6 +578,7 @@ getpty()
                }
        }
 #endif /* CRAY */
                }
        }
 #endif /* CRAY */
+#endif /* STREAMSPTY */
        return(-1);
 }
 #endif /* convex */
        return(-1);
 }
 #endif /* convex */
@@ -489,16 +605,6 @@ getpty()
  * tty_rspeed(val)     Set receive speed to val.
  */
 
  * tty_rspeed(val)     Set receive speed to val.
  */
 
-       int
-tty_flowmode()
-{
-#ifndef USE_TERMIO
-       return(((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0) ? 1 : 0);
-#else
-       return(termbuf.c_iflag & IXON ? 1 : 0);
-#endif
-}
-
 #ifdef convex
 static int linestate;
 #endif
 #ifdef convex
 static int linestate;
 #endif
@@ -540,6 +646,7 @@ tty_setlinemode(on)
 # endif
 #endif /* TIOCEXT */
 }
 # endif
 #endif /* TIOCEXT */
 }
+#endif /* LINEMODE */
 
        int
 tty_isecho()
 
        int
 tty_isecho()
@@ -550,7 +657,30 @@ tty_isecho()
        return (termbuf.c_lflag & ECHO);
 #endif
 }
        return (termbuf.c_lflag & ECHO);
 #endif
 }
-#endif /* LINEMODE */
+
+       int
+tty_flowmode()
+{
+#ifndef USE_TERMIO
+       return(((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0) ? 1 : 0);
+#else
+       return((termbuf.c_iflag & IXON) ? 1 : 0);
+#endif
+}
+
+       int
+tty_restartany()
+{
+#ifndef USE_TERMIO
+# ifdef        DECCTQ
+       return((termbuf.lflags & DECCTQ) ? 0 : 1);
+# else
+       return(-1);
+# endif
+#else
+       return((termbuf.c_iflag & IXANY) ? 1 : 0);
+#endif
+}
 
        void
 tty_setecho(on)
 
        void
 tty_setecho(on)
@@ -569,7 +699,6 @@ tty_setecho(on)
 #endif
 }
 
 #endif
 }
 
-#if    defined(LINEMODE) && defined(KLUDGELINEMODE)
        int
 tty_israw()
 {
        int
 tty_israw()
 {
@@ -579,7 +708,24 @@ tty_israw()
        return(!(termbuf.c_lflag & ICANON));
 #endif
 }
        return(!(termbuf.c_lflag & ICANON));
 #endif
 }
-#endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */
+
+#if    defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
+       int
+tty_setraw(on)
+{
+#  ifndef USE_TERMIO
+       if (on)
+               termbuf.sg.sg_flags |= RAW;
+       else
+               termbuf.sg.sg_flags &= ~RAW;
+#  else
+       if (on)
+               termbuf.c_lflag &= ~ICANON;
+       else
+               termbuf.c_lflag |= ICANON;
+#  endif
+}
+#endif
 
        void
 tty_binaryin(on)
 
        void
 tty_binaryin(on)
@@ -793,6 +939,15 @@ tty_iscrnl()
 #endif
 }
 
 #endif
 }
 
+/*
+ * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD).
+ */
+#if B4800 != 4800
+#define        DECODE_BAUD
+#endif
+
+#ifdef DECODE_BAUD
+
 /*
  * A table of available terminal speeds
  */
 /*
  * A table of available terminal speeds
  */
@@ -800,34 +955,72 @@ struct termspeeds {
        int     speed;
        int     value;
 } termspeeds[] = {
        int     speed;
        int     value;
 } termspeeds[] = {
-       { 0,     B0 },    { 50,    B50 },   { 75,    B75 },
-       { 110,   B110 },  { 134,   B134 },  { 150,   B150 },
-       { 200,   B200 },  { 300,   B300 },  { 600,   B600 },
-       { 1200,  B1200 }, { 1800,  B1800 }, { 2400,  B2400 },
-       { 4800,  B4800 }, { 9600,  B9600 }, { 19200, B9600 },
-       { 38400, B9600 }, { -1,    B9600 }
+       { 0,      B0 },      { 50,    B50 },    { 75,     B75 },
+       { 110,    B110 },    { 134,   B134 },   { 150,    B150 },
+       { 200,    B200 },    { 300,   B300 },   { 600,    B600 },
+       { 1200,   B1200 },   { 1800,  B1800 },  { 2400,   B2400 },
+       { 4800,   B4800 },
+#ifdef B7200
+       { 7200,  B7200 },
+#endif
+       { 9600,   B9600 },
+#ifdef B14400
+       { 14400,  B14400 },
+#endif
+#ifdef B19200
+       { 19200,  B19200 },
+#endif
+#ifdef B28800
+       { 28800,  B28800 },
+#endif
+#ifdef B38400
+       { 38400,  B38400 },
+#endif
+#ifdef B57600
+       { 57600,  B57600 },
+#endif
+#ifdef B115200
+       { 115200, B115200 },
+#endif
+#ifdef B230400
+       { 230400, B230400 },
+#endif
+       { -1,     0 }
 };
 };
+#endif /* DECODE_BUAD */
 
        void
 tty_tspeed(val)
        int val;
 {
 
        void
 tty_tspeed(val)
        int val;
 {
+#ifdef DECODE_BAUD
        register struct termspeeds *tp;
 
        for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
                ;
        register struct termspeeds *tp;
 
        for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
                ;
+       if (tp->speed == -1)    /* back up to last valid value */
+               --tp;
        cfsetospeed(&termbuf, tp->value);
        cfsetospeed(&termbuf, tp->value);
+#else  /* DECODE_BUAD */
+       cfsetospeed(&termbuf, val);
+#endif /* DECODE_BUAD */
 }
 
        void
 tty_rspeed(val)
        int val;
 {
 }
 
        void
 tty_rspeed(val)
        int val;
 {
+#ifdef DECODE_BAUD
        register struct termspeeds *tp;
 
        for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
                ;
        register struct termspeeds *tp;
 
        for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
                ;
+       if (tp->speed == -1)    /* back up to last valid value */
+               --tp;
        cfsetispeed(&termbuf, tp->value);
        cfsetispeed(&termbuf, tp->value);
+#else  /* DECODE_BAUD */
+       cfsetispeed(&termbuf, val);
+#endif /* DECODE_BAUD */
 }
 
 #if    defined(CRAY2) && defined(UNICOS5)
 }
 
 #if    defined(CRAY2) && defined(UNICOS5)
@@ -839,7 +1032,7 @@ tty_isnewmap()
 }
 #endif
 
 }
 #endif
 
-#ifdef CRAY
+#ifdef PARENT_DOES_UTMP
 # ifndef NEWINIT
 extern struct utmp wtmp;
 extern char wtmpf[];
 # ifndef NEWINIT
 extern struct utmp wtmp;
 extern char wtmpf[];
@@ -854,15 +1047,15 @@ nologinproc(sig)
        gotalarm++;
 }
 # endif        /* NEWINIT */
        gotalarm++;
 }
 # endif        /* NEWINIT */
-#endif /* CRAY */
+#endif /* PARENT_DOES_UTMP */
 
 #ifndef        NEWINIT
 
 #ifndef        NEWINIT
-# ifdef        CRAY
+# ifdef PARENT_DOES_UTMP
 extern void utmp_sig_init P((void));
 extern void utmp_sig_reset P((void));
 extern void utmp_sig_wait P((void));
 extern void utmp_sig_notify P((int));
 extern void utmp_sig_init P((void));
 extern void utmp_sig_reset P((void));
 extern void utmp_sig_wait P((void));
 extern void utmp_sig_notify P((int));
-# endif
+# endif /* PARENT_DOES_UTMP */
 #endif
 
 /*
 #endif
 
 /*
@@ -912,7 +1105,7 @@ getptyslave()
 # endif
 
 
 # endif
 
 
-# ifdef        CRAY
+# ifdef PARENT_DOES_UTMP
        /*
         * Wait for our parent to get the utmp stuff to get done.
         */
        /*
         * Wait for our parent to get the utmp stuff to get done.
         */
@@ -923,13 +1116,27 @@ getptyslave()
        if (t < 0)
                fatalperror(net, line);
 
        if (t < 0)
                fatalperror(net, line);
 
+#ifdef  STREAMSPTY
+#ifdef USE_TERMIO
+       ttyfd = t;
+#endif
+       if (ioctl(t, I_PUSH, "ptem") < 0)
+               fatal(net, "I_PUSH ptem");
+       if (ioctl(t, I_PUSH, "ldterm") < 0)
+               fatal(net, "I_PUSH ldterm");
+       if (ioctl(t, I_PUSH, "ttcompat") < 0)
+               fatal(net, "I_PUSH ttcompat");
+       if (ioctl(pty, I_PUSH, "pckt") < 0)
+               fatal(net, "I_PUSH pckt");
+#endif
+
        /*
         * set up the tty modes as we like them to be.
         */
        init_termbuf();
 # ifdef        TIOCGWINSZ
        if (def_row || def_col) {
        /*
         * set up the tty modes as we like them to be.
         */
        init_termbuf();
 # ifdef        TIOCGWINSZ
        if (def_row || def_col) {
-               bzero((char *)&ws, sizeof(ws));
+               memset((char *)&ws, 0, sizeof(ws));
                ws.ws_col = def_col;
                ws.ws_row = def_row;
                (void)ioctl(t, TIOCSWINSZ, (char *)&ws);
                ws.ws_col = def_col;
                ws.ws_row = def_row;
                (void)ioctl(t, TIOCSWINSZ, (char *)&ws);
@@ -944,9 +1151,9 @@ getptyslave()
 # endif        /* USE_TERMIO */
 
        /*
 # endif        /* USE_TERMIO */
 
        /*
-        * Settings for UNICOS
+        * Settings for UNICOS (and HPUX)
         */
         */
-# ifdef        CRAY
+# if defined(CRAY) || defined(__hpux)
        termbuf.c_oflag = OPOST|ONLCR|TAB3;
        termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
        termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
        termbuf.c_oflag = OPOST|ONLCR|TAB3;
        termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
        termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
@@ -958,7 +1165,7 @@ getptyslave()
         * systems, other than 4.4BSD.  In 4.4BSD the
         * kernel does the initial terminal setup.
         */
         * systems, other than 4.4BSD.  In 4.4BSD the
         * kernel does the initial terminal setup.
         */
-# if defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43)
+# if defined(USE_TERMIO) && !(defined(CRAY) || defined(__hpux)) && (BSD <= 43)
 #  ifndef      OXTABS
 #   define OXTABS      0
 #  endif
 #  ifndef      OXTABS
 #   define OXTABS      0
 #  endif
@@ -983,8 +1190,17 @@ getptyslave()
 #endif /* !defined(CRAY) || !defined(NEWINIT) */
        if (net > 2)
                (void) close(net);
 #endif /* !defined(CRAY) || !defined(NEWINIT) */
        if (net > 2)
                (void) close(net);
-       if (pty > 2)
+#if    defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
+       /*
+        * Leave the pty open so that we can write out the rlogin
+        * protocol for /bin/login, if the authentication works.
+        */
+#else
+       if (pty > 2) {
                (void) close(pty);
                (void) close(pty);
+               pty = -1;
+       }
+#endif
 }
 
 #if    !defined(CRAY) || !defined(NEWINIT)
 }
 
 #if    !defined(CRAY) || !defined(NEWINIT)
@@ -1000,18 +1216,44 @@ cleanopen(line)
        char *line;
 {
        register int t;
        char *line;
 {
        register int t;
+#ifdef UNICOS7x
+       struct secstat secbuf;
+#endif /* UNICOS7x */
 
 
+#ifndef STREAMSPTY
        /*
         * Make sure that other people can't open the
         * slave side of the connection.
         */
        (void) chown(line, 0, 0);
        (void) chmod(line, 0600);
        /*
         * Make sure that other people can't open the
         * slave side of the connection.
         */
        (void) chown(line, 0, 0);
        (void) chmod(line, 0600);
+#endif
 
 # if !defined(CRAY) && (BSD > 43)
        (void) revoke(line);
 # endif
 
 # if !defined(CRAY) && (BSD > 43)
        (void) revoke(line);
 # endif
+#ifdef UNICOS7x
+       if (secflag) {
+               if (secstat(line, &secbuf) < 0)
+                       return(-1);
+               if (setulvl(secbuf.st_slevel) < 0)
+                       return(-1);
+               if (setucmp(secbuf.st_compart) < 0)
+                       return(-1);
+       }
+#endif /* UNICOS7x */
+
        t = open(line, O_RDWR|O_NOCTTY);
        t = open(line, O_RDWR|O_NOCTTY);
+
+#ifdef UNICOS7x
+       if (secflag) {
+               if (setulvl(sysv.sy_minlvl) < 0)
+                       return(-1);
+               if (setucmp(0) < 0)
+                       return(-1);
+       }
+#endif /* UNICOS7x */
+
        if (t < 0)
                return(-1);
 
        if (t < 0)
                return(-1);
 
@@ -1019,7 +1261,7 @@ cleanopen(line)
         * Hangup anybody else using this ttyp, then reopen it for
         * ourselves.
         */
         * Hangup anybody else using this ttyp, then reopen it for
         * ourselves.
         */
-# if !defined(CRAY) && (BSD <= 43)
+# if !(defined(CRAY) || defined(__hpux)) && (BSD <= 43) && !defined(STREAMSPTY)
        (void) signal(SIGHUP, SIG_IGN);
        vhangup();
        (void) signal(SIGHUP, SIG_DFL);
        (void) signal(SIGHUP, SIG_IGN);
        vhangup();
        (void) signal(SIGHUP, SIG_DFL);
@@ -1033,8 +1275,29 @@ cleanopen(line)
                (void) signal(SIGHUP, SIG_IGN);
                (void) ioctl(t, TCVHUP, (char *)0);
                (void) signal(SIGHUP, SIG_DFL);
                (void) signal(SIGHUP, SIG_IGN);
                (void) ioctl(t, TCVHUP, (char *)0);
                (void) signal(SIGHUP, SIG_DFL);
-               setpgrp();
+
+#ifdef UNICOS7x
+               if (secflag) {
+                       if (secstat(line, &secbuf) < 0)
+                               return(-1);
+                       if (setulvl(secbuf.st_slevel) < 0)
+                               return(-1);
+                       if (setucmp(secbuf.st_compart) < 0)
+                               return(-1);
+               }
+#endif /* UNICOS7x */
+
                i = open(line, O_RDWR);
                i = open(line, O_RDWR);
+
+#ifdef UNICOS7x
+               if (secflag) {
+                       if (setulvl(sysv.sy_minlvl) < 0)
+                               return(-1);
+                       if (setucmp(0) < 0)
+                               return(-1);
+               }
+#endif /* UNICOS7x */
+
                if (i < 0)
                        return(-1);
                (void) close(t);
                if (i < 0)
                        return(-1);
                (void) close(t);
@@ -1046,16 +1309,26 @@ cleanopen(line)
 #endif /* !defined(CRAY) || !defined(NEWINIT) */
 
 #if BSD <= 43
 #endif /* !defined(CRAY) || !defined(NEWINIT) */
 
 #if BSD <= 43
+
        int
 login_tty(t)
        int t;
 {
        int
 login_tty(t)
        int t;
 {
-       if (setsid() < 0)
-               fatalperror(net, "setsid()");
+       if (setsid() < 0) {
+#ifdef ultrix
+               /*
+                * The setsid() may have failed because we
+                * already have a pgrp == pid.  Zero out
+                * our pgrp and try again...
+                */
+               if ((setpgrp(0, 0) < 0) || (setsid() < 0))
+#endif
+                       fatalperror(net, "setsid()");
+       }
 # ifdef        TIOCSCTTY
        if (ioctl(t, TIOCSCTTY, (char *)0) < 0)
                fatalperror(net, "ioctl(sctty)");
 # ifdef        TIOCSCTTY
        if (ioctl(t, TIOCSCTTY, (char *)0) < 0)
                fatalperror(net, "ioctl(sctty)");
-#  if defined(CRAY) && defined(SESS_CTTY)      /* SESS_CTTY is in param.h */
+#  if defined(CRAY)
        /*
         * Close the hard fd to /dev/ttypXXX, and re-open through
         * the indirect /dev/tty interface.
        /*
         * Close the hard fd to /dev/ttypXXX, and re-open through
         * the indirect /dev/tty interface.
@@ -1065,6 +1338,18 @@ login_tty(t)
                fatalperror(net, "open(/dev/tty)");
 #  endif
 # else
                fatalperror(net, "open(/dev/tty)");
 #  endif
 # else
+       /*
+        * We get our controlling tty assigned as a side-effect
+        * of opening up a tty device.  But on BSD based systems,
+        * this only happens if our process group is zero.  The
+        * setsid() call above may have set our pgrp, so clear
+        * it out before opening the tty...
+        */
+#  ifndef SOLARIS
+       (void) setpgrp(0, 0);
+#  else
+       (void) setpgrp();
+#  endif
        close(open(line, O_RDWR));
 # endif
        if (t != 0)
        close(open(line, O_RDWR));
 # endif
        if (t != 0)
@@ -1107,7 +1392,7 @@ startslave(host, autologin, autoname)
        register int n;
 #endif /* NEWINIT */
 
        register int n;
 #endif /* NEWINIT */
 
-#if    defined(AUTHENTICATE)
+#if    defined(AUTHENTICATION)
        if (!autoname || !autoname[0])
                autologin = 0;
 
        if (!autoname || !autoname[0])
                autologin = 0;
 
@@ -1118,14 +1403,14 @@ startslave(host, autologin, autoname)
 #endif
 
 #ifndef        NEWINIT
 #endif
 
 #ifndef        NEWINIT
-# ifdef        CRAY
+# ifdef        PARENT_DOES_UTMP
        utmp_sig_init();
        utmp_sig_init();
-# endif        /* CRAY */
+# endif        /* PARENT_DOES_UTMP */
 
        if ((i = fork()) < 0)
                fatalperror(net, "fork");
        if (i) {
 
        if ((i = fork()) < 0)
                fatalperror(net, "fork");
        if (i) {
-# ifdef        CRAY
+# ifdef PARENT_DOES_UTMP
                /*
                 * Cray parent will create utmp entry for child and send
                 * signal to child to tell when done.  Child waits for signal
                /*
                 * Cray parent will create utmp entry for child and send
                 * signal to child to tell when done.  Child waits for signal
@@ -1145,18 +1430,24 @@ startslave(host, autologin, autoname)
                SCPYN(wtmp.ut_user, "LOGIN");
                SCPYN(wtmp.ut_host, host);
                SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1);
                SCPYN(wtmp.ut_user, "LOGIN");
                SCPYN(wtmp.ut_host, host);
                SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1);
+#ifndef        __hpux
                SCPYN(wtmp.ut_id, wtmp.ut_line+3);
                SCPYN(wtmp.ut_id, wtmp.ut_line+3);
+#else
+               SCPYN(wtmp.ut_id, wtmp.ut_line+7);
+#endif
                pututline(&wtmp);
                endutent();
                if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) {
                        (void) write(i, (char *)&wtmp, sizeof(struct utmp));
                        (void) close(i);
                }
                pututline(&wtmp);
                endutent();
                if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) {
                        (void) write(i, (char *)&wtmp, sizeof(struct utmp));
                        (void) close(i);
                }
+#ifdef CRAY
                (void) signal(WJSIGNAL, sigjob);
                (void) signal(WJSIGNAL, sigjob);
+#endif
                utmp_sig_notify(pid);
                utmp_sig_notify(pid);
-# endif        /* CRAY */
+# endif        /* PARENT_DOES_UTMP */
        } else {
        } else {
-               getptyslave();
+               getptyslave(autologin);
                start_login(host, autologin, autoname);
                /*NOTREACHED*/
        }
                start_login(host, autologin, autoname);
                /*NOTREACHED*/
        }
@@ -1228,7 +1519,7 @@ init_env()
        envp = envinit;
        if (*envp = getenv("TZ"))
                *envp++ -= 3;
        envp = envinit;
        if (*envp = getenv("TZ"))
                *envp++ -= 3;
-#ifdef CRAY
+#if    defined(CRAY) || defined(__hpux)
        else
                *envp++ = "TZ=GMT0";
 #endif
        else
                *envp++ = "TZ=GMT0";
 #endif
@@ -1254,6 +1545,34 @@ start_login(host, autologin, name)
        register char *cp;
        register char **argv;
        char **addarg();
        register char *cp;
        register char **argv;
        char **addarg();
+       extern char *getenv();
+#ifdef UTMPX
+       register int pid = getpid();
+       struct utmpx utmpx;
+#endif
+#ifdef SOLARIS
+       char *term;
+       char termbuf[64];
+#endif
+
+#ifdef UTMPX
+       /*
+        * Create utmp entry for child
+        */
+
+       memset(&utmpx, 0, sizeof(utmpx));
+       SCPYN(utmpx.ut_user, ".telnet");
+       SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1);
+       utmpx.ut_pid = pid;
+       utmpx.ut_id[0] = 't';
+       utmpx.ut_id[1] = 'n';
+       utmpx.ut_id[2] = SC_WILDC;
+       utmpx.ut_id[3] = SC_WILDC;
+       utmpx.ut_type = LOGIN_PROCESS;
+       (void) time(&utmpx.ut_tv.tv_sec);
+       if (pututxline(&utmpx) == NULL)
+               fatal(net, "pututxline failed");
+#endif
 
        /*
         * -h : pass on name of host.
 
        /*
         * -h : pass on name of host.
@@ -1264,11 +1583,51 @@ start_login(host, autologin, name)
         * -f : force this login, he has already been authenticated
         */
        argv = addarg(0, "login");
         * -f : force this login, he has already been authenticated
         */
        argv = addarg(0, "login");
-       argv = addarg(argv, "-h");
-       argv = addarg(argv, host);
+
+#if    !defined(NO_LOGIN_H)
+
+# if   defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
+       /*
+        * Don't add the "-h host" option if we are going
+        * to be adding the "-r host" option down below...
+        */
+       if ((auth_level < 0) || (autologin != AUTH_VALID))
+# endif
+       {
+               argv = addarg(argv, "-h");
+               argv = addarg(argv, host);
+#ifdef SOLARIS
+               /*
+                * SVR4 version of -h takes TERM= as second arg, or -
+                */
+               term = getenv("TERM");
+               if (term == NULL || term[0] == 0) {
+                       term = "-";
+               } else {
+                       strcpy(termbuf, "TERM=");
+                       strncat(termbuf, term, sizeof(termbuf) - 6);
+                       term = termbuf;
+               }
+               argv = addarg(argv, term);
+#endif
+       }
+#endif
 #if    !defined(NO_LOGIN_P)
        argv = addarg(argv, "-p");
 #endif
 #if    !defined(NO_LOGIN_P)
        argv = addarg(argv, "-p");
 #endif
+#ifdef LINEMODE
+       /*
+        * Set the environment variable "LINEMODE" to either
+        * "real" or "kludge" if we are operating in either
+        * real or kludge linemode.
+        */
+       if (lmodetype == REAL_LINEMODE)
+               setenv("LINEMODE", "real", 1);
+# ifdef KLUDGELINEMODE
+       else if (lmodetype == KLUDGE_LINEMODE || lmodetype == KLUDGE_OK)
+               setenv("LINEMODE", "kludge", 1);
+# endif
+#endif
 #ifdef BFTPDAEMON
        /*
         * Are we working as the bftp daemon?  If so, then ask login
 #ifdef BFTPDAEMON
        /*
         * Are we working as the bftp daemon?  If so, then ask login
@@ -1277,7 +1636,7 @@ start_login(host, autologin, name)
        if (bftpd) {
                argv = addarg(argv, "-e");
                argv = addarg(argv, BFTPPATH);
        if (bftpd) {
                argv = addarg(argv, "-e");
                argv = addarg(argv, BFTPPATH);
-       } else 
+       } else
 #endif
 #if    defined (SecurID)
        /*
 #endif
 #if    defined (SecurID)
        /*
@@ -1287,25 +1646,129 @@ start_login(host, autologin, name)
        if (require_SecurID)
                argv = addarg(argv, "-s");
 #endif
        if (require_SecurID)
                argv = addarg(argv, "-s");
 #endif
-#if    defined (AUTHENTICATE)
+#if    defined (AUTHENTICATION)
        if (auth_level >= 0 && autologin == AUTH_VALID) {
 # if   !defined(NO_LOGIN_F)
                argv = addarg(argv, "-f");
        if (auth_level >= 0 && autologin == AUTH_VALID) {
 # if   !defined(NO_LOGIN_F)
                argv = addarg(argv, "-f");
+               argv = addarg(argv, name);
+# else
+#  if defined(LOGIN_R)
+               /*
+                * We don't have support for "login -f", but we
+                * can fool /bin/login into thinking that we are
+                * rlogind, and allow us to log in without a
+                * password.  The rlogin protocol expects
+                *      local-user\0remote-user\0term/speed\0
+                */
+
+               if (pty > 2) {
+                       register char *cp;
+                       char speed[128];
+                       int isecho, israw, xpty, len;
+                       extern int def_rspeed;
+#  ifndef LOGIN_HOST
+                       /*
+                        * Tell login that we are coming from "localhost".
+                        * If we passed in the real host name, then the
+                        * user would have to allow .rhost access from
+                        * every machine that they want authenticated
+                        * access to work from, which sort of defeats
+                        * the purpose of an authenticated login...
+                        * So, we tell login that the session is coming
+                        * from "localhost", and the user will only have
+                        * to have "localhost" in their .rhost file.
+                        */
+#                      define LOGIN_HOST "localhost"
+#  endif
+                       argv = addarg(argv, "-r");
+                       argv = addarg(argv, LOGIN_HOST);
+
+                       xpty = pty;
+# ifndef  STREAMSPTY
+                       pty = 0;
+# else
+                       ttyfd = 0;
 # endif
 # endif
+                       init_termbuf();
+                       isecho = tty_isecho();
+                       israw = tty_israw();
+                       if (isecho || !israw) {
+                               tty_setecho(0);         /* Turn off echo */
+                               tty_setraw(1);          /* Turn on raw */
+                               set_termbuf();
+                       }
+                       len = strlen(name)+1;
+                       write(xpty, name, len);
+                       write(xpty, name, len);
+                       sprintf(speed, "%s/%d", (cp = getenv("TERM")) ? cp : "",
+                               (def_rspeed > 0) ? def_rspeed : 9600);
+                       len = strlen(speed)+1;
+                       write(xpty, speed, len);
+
+                       if (isecho || !israw) {
+                               init_termbuf();
+                               tty_setecho(isecho);
+                               tty_setraw(israw);
+                               set_termbuf();
+                               if (!israw) {
+                                       /*
+                                        * Write a newline to ensure
+                                        * that login will be able to
+                                        * read the line...
+                                        */
+                                       write(xpty, "\n", 1);
+                               }
+                       }
+                       pty = xpty;
+               }
+#  else
                argv = addarg(argv, name);
                argv = addarg(argv, name);
+#  endif
+# endif
        } else
 #endif
        if (getenv("USER")) {
                argv = addarg(argv, getenv("USER"));
        } else
 #endif
        if (getenv("USER")) {
                argv = addarg(argv, getenv("USER"));
-#if    defined(CRAY) && defined(NO_LOGIN_P)
+#if    defined(LOGIN_ARGS) && defined(NO_LOGIN_P)
                {
                        register char **cpp;
                        for (cpp = environ; *cpp; cpp++)
                                argv = addarg(argv, *cpp);
                }
 #endif
                {
                        register char **cpp;
                        for (cpp = environ; *cpp; cpp++)
                                argv = addarg(argv, *cpp);
                }
 #endif
+               /*
+                * Assume that login will set the USER variable
+                * correctly.  For SysV systems, this means that
+                * USER will no longer be set, just LOGNAME by
+                * login.  (The problem is that if the auto-login
+                * fails, and the user then specifies a different
+                * account name, he can get logged in with both
+                * LOGNAME and USER in his environment, but the
+                * USER value will be wrong.
+                */
+               unsetenv("USER");
        }
        }
+#ifdef SOLARIS
+       else {
+               char **p;
+
+               argv = addarg(argv, "");        /* no login name */
+               for (p = environ; *p; p++) {
+                       argv = addarg(argv, *p);
+               }
+       }
+#endif /* SOLARIS */
+#if    defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
+       if (pty > 2)
+               close(pty);
+#endif
        closelog();
        closelog();
+       /*
+        * This sleep(1) is in here so that telnetd can
+        * finish up with the tty.  There's a race condition
+        * the login banner message gets lost...
+        */
+       sleep(1);
        execv(_PATH_LOGIN, argv);
 
        syslog(LOG_ERR, "%s: %m\n", _PATH_LOGIN);
        execv(_PATH_LOGIN, argv);
 
        syslog(LOG_ERR, "%s: %m\n", _PATH_LOGIN);
@@ -1335,7 +1798,7 @@ addarg(argv, val)
        if (cpp == &argv[(int)argv[-1]]) {
                --argv;
                *argv = (char *)((int)(*argv) + 10);
        if (cpp == &argv[(int)argv[-1]]) {
                --argv;
                *argv = (char *)((int)(*argv) + 10);
-               argv = (char **)realloc(argv, (int)(*argv) + 2);
+               argv = (char **)realloc(argv, sizeof(*argv)*((int)(*argv) + 2));
                if (argv == NULL)
                        return(NULL);
                argv++;
                if (argv == NULL)
                        return(NULL);
                argv++;
@@ -1358,7 +1821,7 @@ addarg(argv, val)
 cleanup(sig)
        int sig;
 {
 cleanup(sig)
        int sig;
 {
-#ifndef        CRAY
+#ifndef        PARENT_DOES_UTMP
 # if (BSD > 43) || defined(convex)
        char *p;
 
 # if (BSD > 43) || defined(convex)
        char *p;
 
@@ -1380,13 +1843,16 @@ cleanup(sig)
        (void) shutdown(net, 2);
        exit(1);
 # endif
        (void) shutdown(net, 2);
        exit(1);
 # endif
-#else  /* CRAY */
+#else  /* PARENT_DOES_UTMP */
 # ifdef        NEWINIT
        (void) shutdown(net, 2);
        exit(1);
 # else /* NEWINIT */
 # ifdef        NEWINIT
        (void) shutdown(net, 2);
        exit(1);
 # else /* NEWINIT */
+#  ifdef CRAY
        static int incleanup = 0;
        register int t;
        static int incleanup = 0;
        register int t;
+       int child_status; /* status of child process as returned by waitpid */
+       int flags = WNOHANG|WUNTRACED;
 
        /*
         * 1: Pick up the zombie, if we are being called
 
        /*
         * 1: Pick up the zombie, if we are being called
@@ -1397,9 +1863,17 @@ cleanup(sig)
         * 5: Close down the network and pty connections.
         * 6: Finish up the TMPDIR cleanup, if needed.
         */
         * 5: Close down the network and pty connections.
         * 6: Finish up the TMPDIR cleanup, if needed.
         */
-       if (sig == SIGCHLD)
-               while (waitpid(-1, 0, WNOHANG) > 0)
+       if (sig == SIGCHLD) {
+               while (waitpid(-1, &child_status, flags) > 0)
                        ;       /* VOID */
                        ;       /* VOID */
+               /* Check if the child process was stopped
+                * rather than exited.  We want cleanup only if
+                * the child has died.
+                */
+               if (WIFSTOPPED(child_status)) {
+                       return;
+               }
+       }
        t = sigblock(sigmask(SIGCHLD));
        if (incleanup) {
                sigsetmask(t);
        t = sigblock(sigmask(SIGCHLD));
        if (incleanup) {
                sigsetmask(t);
@@ -1407,20 +1881,34 @@ cleanup(sig)
        }
        incleanup = 1;
        sigsetmask(t);
        }
        incleanup = 1;
        sigsetmask(t);
+#ifdef UNICOS7x
+       if (secflag) {
+               /*
+                *      We need to set ourselves back to a null
+                *      label to clean up.
+                */
+
+               setulvl(sysv.sy_minlvl);
+               setucmp((long)0);
+       }
+#endif /* UNICOS7x */
 
        t = cleantmp(&wtmp);
        setutent();     /* just to make sure */
 
        t = cleantmp(&wtmp);
        setutent();     /* just to make sure */
+#  endif /* CRAY */
        rmut(line);
        close(pty);
        (void) shutdown(net, 2);
        rmut(line);
        close(pty);
        (void) shutdown(net, 2);
+#  ifdef CRAY
        if (t == 0)
                cleantmp(&wtmp);
        if (t == 0)
                cleantmp(&wtmp);
+#  endif /* CRAY */
        exit(1);
 # endif        /* NEWINT */
        exit(1);
 # endif        /* NEWINT */
-#endif /* CRAY */
+#endif /* PARENT_DOES_UTMP */
 }
 
 }
 
-#if    defined(CRAY) && !defined(NEWINIT)
+#if defined(PARENT_DOES_UTMP) && !defined(NEWINIT)
 /*
  * _utmp_sig_rcv
  * utmp_sig_init
 /*
  * _utmp_sig_rcv
  * utmp_sig_init
@@ -1458,6 +1946,11 @@ utmp_sig_reset()
        (void) signal(SIGUSR1, func);   /* reset handler to default */
 }
 
        (void) signal(SIGUSR1, func);   /* reset handler to default */
 }
 
+# ifdef __hpux
+# define sigoff() /* do nothing */
+# define sigon() /* do nothing */
+# endif
+
        void
 utmp_sig_wait()
 {
        void
 utmp_sig_wait()
 {
@@ -1478,6 +1971,7 @@ utmp_sig_notify(pid)
        kill(pid, SIGUSR1);
 }
 
        kill(pid, SIGUSR1);
 }
 
+# ifdef CRAY
 static int gotsigjob = 0;
 
        /*ARGSUSED*/
 static int gotsigjob = 0;
 
        /*ARGSUSED*/
@@ -1497,6 +1991,28 @@ sigjob(sig)
        }
 }
 
        }
 }
 
+/*
+ *     jid_getutid:
+ *             called by jobend() before calling cleantmp()
+ *             to find the correct $TMPDIR to cleanup.
+ */
+
+       struct utmp *
+jid_getutid(jid)
+       int jid;
+{
+       struct utmp *cur = NULL;
+
+       setutent();     /* just to make sure */
+       while (cur = getutent()) {
+               if ( (cur->ut_type != NULL) && (jid == cur->ut_jid) ) {
+                       return(cur);
+               }
+       }
+
+       return(0);
+}
+
 /*
  * Clean up the TMPDIR that login created.
  * The first time this is called we pick up the info
 /*
  * Clean up the TMPDIR that login created.
  * The first time this is called we pick up the info
@@ -1512,7 +2028,8 @@ cleantmp(wtp)
        struct utmp *utp;
        static int first = 1;
        register int mask, omask, ret;
        struct utmp *utp;
        static int first = 1;
        register int mask, omask, ret;
-       extern struct utmp *getutid P((struct utmp *));
+       extern struct utmp *getutid P((const struct utmp *_Id));
+
 
        mask = sigmask(WJSIGNAL);
 
 
        mask = sigmask(WJSIGNAL);
 
@@ -1552,9 +2069,27 @@ jobend(jid, path, user)
        register char *user;
 {
        static int saved_jid = 0;
        register char *user;
 {
        static int saved_jid = 0;
+       static int pty_saved_jid = 0;
        static char saved_path[sizeof(wtmp.ut_tpath)+1];
        static char saved_user[sizeof(wtmp.ut_user)+1];
 
        static char saved_path[sizeof(wtmp.ut_tpath)+1];
        static char saved_user[sizeof(wtmp.ut_user)+1];
 
+       /*
+        * this little piece of code comes into play
+        * only when ptyreconnect is used to reconnect
+        * to an previous session.
+        *
+        * this is the only time when the
+        * "saved_jid != jid" code is executed.
+        */
+
+       if ( saved_jid && saved_jid != jid ) {
+               if (!path) {    /* called from signal handler */
+                       pty_saved_jid = jid;
+               } else {
+                       pty_saved_jid = saved_jid;
+               }
+       }
+
        if (path) {
                strncpy(saved_path, path, sizeof(wtmp.ut_tpath));
                strncpy(saved_user, user, sizeof(wtmp.ut_user));
        if (path) {
                strncpy(saved_path, path, sizeof(wtmp.ut_tpath));
                strncpy(saved_user, user, sizeof(wtmp.ut_user));
@@ -1565,6 +2100,24 @@ jobend(jid, path, user)
                saved_jid = jid;
                return(0);
        }
                saved_jid = jid;
                return(0);
        }
+
+       /* if the jid has changed, get the correct entry from the utmp file */
+
+       if ( saved_jid != jid ) {
+               struct utmp *utp = NULL;
+               struct utmp *jid_getutid();
+
+               utp = jid_getutid(pty_saved_jid);
+
+               if (utp == 0) {
+                       syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR");
+                       return(-1);
+               }
+
+               cleantmpdir(jid, utp->ut_tpath, utp->ut_user);
+               return(1);
+       }
+
        cleantmpdir(jid, saved_path, saved_user);
        return(1);
 }
        cleantmpdir(jid, saved_path, saved_user);
        return(1);
 }
@@ -1595,7 +2148,8 @@ cleantmpdir(jid, tpath, user)
                break;
        }
 }
                break;
        }
 }
-#endif /* defined(CRAY) && !defined(NEWINIT) */
+# endif /* CRAY */
+#endif /* defined(PARENT_DOES_UTMP) && !defined(NEWINIT) */
 
 /*
  * rmut()
 
 /*
  * rmut()
@@ -1604,7 +2158,37 @@ cleantmpdir(jid, tpath, user)
  * remove the utmp entry for this person.
  */
 
  * remove the utmp entry for this person.
  */
 
-#if    !defined(CRAY) && BSD <= 43
+#ifdef UTMPX
+       void
+rmut()
+{
+       register f;
+       int found = 0;
+       struct utmp *u, *utmp;
+       int nutmp;
+       struct stat statbf;
+
+       struct utmpx *utxp, utmpx;
+
+       /*
+        * This updates the utmpx and utmp entries and make a wtmp/x entry
+        */
+
+       SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1);
+       utxp = getutxline(&utmpx);
+       if (utxp) {
+               utxp->ut_type = DEAD_PROCESS;
+               utxp->ut_exit.e_termination = 0;
+               utxp->ut_exit.e_exit = 0;
+               (void) time(&utmpx.ut_tv.tv_sec);
+               utmpx.ut_tv.tv_usec = 0;
+               modutx(utxp);
+       }
+       endutxent();
+}  /* end of rmut */
+#endif
+
+#if    !defined(UTMPX) && !(defined(CRAY) || defined(__hpux)) && BSD <= 43
        void
 rmut()
 {
        void
 rmut()
 {
@@ -1623,7 +2207,7 @@ rmut()
                if (statbf.st_size && utmp) {
                        nutmp = read(f, (char *)utmp, (int)statbf.st_size);
                        nutmp /= sizeof(struct utmp);
                if (statbf.st_size && utmp) {
                        nutmp = read(f, (char *)utmp, (int)statbf.st_size);
                        nutmp /= sizeof(struct utmp);
-               
+
                        for (u = utmp ; u < &utmp[nutmp] ; u++) {
                                if (SCMPN(u->ut_line, line+5) ||
                                    u->ut_name[0]==0)
                        for (u = utmp ; u < &utmp[nutmp] ; u++) {
                                if (SCMPN(u->ut_line, line+5) ||
                                    u->ut_name[0]==0)
@@ -1656,3 +2240,42 @@ rmut()
        (void) chown(line, 0, 0);
 }  /* end of rmut */
 #endif /* CRAY */
        (void) chown(line, 0, 0);
 }  /* end of rmut */
 #endif /* CRAY */
+
+#ifdef __hpux
+rmut (line)
+char *line;
+{
+       struct utmp utmp;
+       struct utmp *utptr;
+       int fd;                 /* for /etc/wtmp */
+
+       utmp.ut_type = USER_PROCESS;
+       (void) strncpy(utmp.ut_id, line+12, sizeof(utmp.ut_id));
+       (void) setutent();
+       utptr = getutid(&utmp);
+       /* write it out only if it exists */
+       if (utptr) {
+               utptr->ut_type = DEAD_PROCESS;
+               utptr->ut_time = time((long *) 0);
+               (void) pututline(utptr);
+               /* set wtmp entry if wtmp file exists */
+               if ((fd = open(wtmpf, O_WRONLY | O_APPEND)) >= 0) {
+                       (void) write(fd, utptr, sizeof(utmp));
+                       (void) close(fd);
+               }
+       }
+       (void) endutent();
+
+       (void) chmod(line, 0666);
+       (void) chown(line, 0, 0);
+       line[14] = line[13];
+       line[13] = line[12];
+       line[8] = 'm';
+       line[9] = '/';
+       line[10] = 'p';
+       line[11] = 't';
+       line[12] = 'y';
+       (void) chmod(line, 0666);
+       (void) chown(line, 0, 0);
+}
+#endif