2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
38 #if defined(_CRAY) || (defined(__hpux) && !defined(HAVE_UTMPX_H))
39 # define PARENT_DOES_UTMP
52 #elif defined(HAVE_UTMP_H)
54 #endif /* HAVE_UTMPX_H */
56 #ifdef HAVE_STRUCT_UTMP_UT_HOST
57 int utmp_len
= sizeof(wtmp
.ut_host
);
59 int utmp_len
= MaxHostNameLen
;
64 #define UTMP_FILE _PATH_UTMP
66 #define UTMP_FILE "/etc/utmp"
70 /* really, mac os uses wtmpx (or asl) */
75 #if !defined(WTMP_FILE) && defined(_PATH_WTMP)
76 #define WTMP_FILE _PATH_WTMP
79 #ifndef PARENT_DOES_UTMP
81 char wtmpf
[] = WTMP_FILE
;
83 char wtmpf
[] = "/usr/adm/wtmp";
85 char utmpf
[] = UTMP_FILE
;
86 #else /* PARENT_DOES_UTMP */
88 char wtmpf
[] = WTMP_FILE
;
90 char wtmpf
[] = "/etc/wtmp";
92 #endif /* PARENT_DOES_UTMP */
98 #if !(defined(__sgi) || defined(__linux) || defined(_AIX)) && defined(HAVE_SYS_TTY)
118 #ifdef HAVE_TERMIOS_H
129 #ifdef HAVE_LIBUTIL_H
135 # define TCSANOW TCSETS
136 # define TCSADRAIN TCSETSW
137 # define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t)
140 # define TCSANOW TCSETA
141 # define TCSADRAIN TCSETAW
142 # define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t)
144 # define TCSANOW TIOCSETA
145 # define TCSADRAIN TIOCSETAW
146 # define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t)
149 # define tcsetattr(f, a, t) ioctl(f, a, t)
150 # define cfsetospeed(tp, val) (tp)->c_cflag &= ~CBAUD; \
151 (tp)->c_cflag |= (val)
152 # define cfgetospeed(tp) ((tp)->c_cflag & CBAUD)
154 # define cfsetispeed(tp, val) (tp)->c_cflag &= ~CIBAUD; \
155 (tp)->c_cflag |= ((val)<<IBSHIFT)
156 # define cfgetispeed(tp) (((tp)->c_cflag & CIBAUD)>>IBSHIFT)
158 # define cfsetispeed(tp, val) (tp)->c_cflag &= ~CBAUD; \
159 (tp)->c_cflag |= (val)
160 # define cfgetispeed(tp) ((tp)->c_cflag & CBAUD)
162 # endif /* TCSANOW */
163 struct termios termbuf
, termbuf2
; /* pty control structure */
165 static int ttyfd
= -1;
166 int really_stream
= 0;
168 #define really_stream 0
171 const char *new_login
= _PATH_LOGIN
;
178 * These three routines are used to get and set the "termbuf" structure
179 * to and from the kernel. init_termbuf() gets the current settings.
180 * copy_termbuf() hands in a new "termbuf" to write to the kernel, and
181 * set_termbuf() writes the structure into the kernel.
189 tcgetattr(ttyfd
, &termbuf
);
192 tcgetattr(ourpty
, &termbuf
);
200 * Only make the necessary changes.
202 if (memcmp(&termbuf
, &termbuf2
, sizeof(termbuf
))) {
205 tcsetattr(ttyfd
, TCSANOW
, &termbuf
);
208 tcsetattr(ourpty
, TCSANOW
, &termbuf
);
214 * spcset(func, valp, valpp)
216 * This function takes various special characters (func), and
217 * sets *valp to the current value of that character, and
218 * *valpp to point to where in the "termbuf" structure that
221 * It returns the SLC_ level of support for this function.
226 spcset(int func
, cc_t
*valp
, cc_t
**valpp
)
229 #define setval(a, b) *valp = termbuf.c_cc[a]; \
230 *valpp = &termbuf.c_cc[a]; \
232 #define defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT);
236 setval(VEOF
, SLC_VARIABLE
);
238 setval(VERASE
, SLC_VARIABLE
);
240 setval(VKILL
, SLC_VARIABLE
);
242 setval(VINTR
, SLC_VARIABLE
|SLC_FLUSHIN
|SLC_FLUSHOUT
);
244 setval(VQUIT
, SLC_VARIABLE
|SLC_FLUSHIN
|SLC_FLUSHOUT
);
247 setval(VSTART
, SLC_VARIABLE
);
253 setval(VSTOP
, SLC_VARIABLE
);
259 setval(VWERASE
, SLC_VARIABLE
);
265 setval(VREPRINT
, SLC_VARIABLE
);
271 setval(VLNEXT
, SLC_VARIABLE
);
276 #if !defined(VDISCARD) && defined(VFLUSHO)
277 # define VDISCARD VFLUSHO
280 setval(VDISCARD
, SLC_VARIABLE
|SLC_FLUSHOUT
);
286 setval(VSUSP
, SLC_VARIABLE
|SLC_FLUSHIN
);
292 setval(VEOL
, SLC_VARIABLE
);
296 setval(VEOL2
, SLC_VARIABLE
);
300 setval(VSTATUS
, SLC_VARIABLE
);
313 return(SLC_NOSUPPORT
);
321 * Return the number of pty's configured into the system.
329 if ((numptys
= sysconf(_SC_CRAY_NPTY
)) != -1)
332 #endif /* _SC_CRAY_NPTY */
340 * Allocate a pty. As a side effect, the external character
341 * array "line" contains the name of the slave side.
343 * Returns the file descriptor of the opened pty.
346 static int ptyslavefd
= -1;
348 static char Xline
[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
352 char myline
[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
355 #if !defined(HAVE_PTSNAME) && defined(STREAMSPTY)
356 static char *ptsname(int fd
)
366 int getpty(int *ptynum
)
368 #if defined(HAVE_OPENPTY) || defined(__linux) || defined(__osf__) /* XXX */
372 if(openpty(&master
, &slave
, line
, 0, 0) == 0){
377 #endif /* HAVE_OPENPTY .... */
382 p
= _getpty(&master
, O_RDWR
, 0600, 1);
385 strlcpy(line
, p
, sizeof(Xline
));
392 char *clone
[] = { "/dev/ptc", "/dev/ptmx", "/dev/ptm",
393 "/dev/ptym/clone", 0 };
397 for(q
=clone
; *q
; q
++){
406 strlcpy(line
, ptsname(p
), sizeof(Xline
));
412 #endif /* STREAMSPTY */
420 snprintf(line
, sizeof(Xline
), "/dev/ptyXX");
424 snprintf(line
, sizeof(Xline
), "/dev/ptym/ptyXX");
430 for (cp
= "pqrstuvwxyzPQRST"; *cp
; cp
++) {
436 * This stat() check is just to keep us from
437 * looping through all 256 combinations if there
438 * aren't that many ptys available.
440 if (stat(line
, &stb
) < 0)
442 for (i
= 0; i
< 16; i
++) {
443 *p2
= "0123456789abcdef"[i
];
444 p
= open(line
, O_RDWR
);
453 for (p1
= &line
[8]; *p1
; p1
++)
460 if (ioctl(p
, TIOCGPGRP
, &dummy
) == 0
466 #endif /* SunOS == 40 */
474 extern lowpty
, highpty
;
478 for (*ptynum
= lowpty
; *ptynum
<= highpty
; (*ptynum
)++) {
479 snprintf(myline
, sizeof(myline
), "/dev/pty/%03d", *ptynum
);
483 snprintf(line
, sizeof(Xline
), "/dev/ttyp%03d", *ptynum
);
485 * Here are some shenanigans to make sure that there
486 * are no listeners lurking on the line.
488 if(stat(line
, &sb
) < 0) {
492 if(sb
.st_uid
|| sb
.st_gid
|| sb
.st_mode
!= 0600) {
501 * Now it should be safe...check for accessability.
503 if (access(line
, 6) == 0)
506 /* no tty side to pty so skip it */
519 return (termbuf
.c_lflag
& ECHO
);
525 return((termbuf
.c_iflag
& IXON
) ? 1 : 0);
531 return((termbuf
.c_iflag
& IXANY
) ? 1 : 0);
538 termbuf
.c_lflag
|= ECHO
;
540 termbuf
.c_lflag
&= ~ECHO
;
546 return(!(termbuf
.c_lflag
& ICANON
));
553 termbuf
.c_iflag
&= ~ISTRIP
;
555 termbuf
.c_iflag
|= ISTRIP
;
560 tty_binaryout(int on
)
563 termbuf
.c_cflag
&= ~(CSIZE
|PARENB
);
564 termbuf
.c_cflag
|= CS8
;
565 termbuf
.c_oflag
&= ~OPOST
;
567 termbuf
.c_cflag
&= ~CSIZE
;
568 termbuf
.c_cflag
|= CS7
|PARENB
;
569 termbuf
.c_oflag
|= OPOST
;
576 return(!(termbuf
.c_iflag
& ISTRIP
));
580 tty_isbinaryout(void)
582 return(!(termbuf
.c_oflag
&OPOST
));
590 return (termbuf
.c_oflag
& OXTABS
);
593 return ((termbuf
.c_oflag
& TABDLY
) == TAB3
);
598 tty_setsofttab(int on
)
602 termbuf
.c_oflag
|= OXTABS
;
605 termbuf
.c_oflag
&= ~TABDLY
;
606 termbuf
.c_oflag
|= TAB3
;
610 termbuf
.c_oflag
&= ~OXTABS
;
613 termbuf
.c_oflag
&= ~TABDLY
;
614 termbuf
.c_oflag
|= TAB0
;
623 return (!(termbuf
.c_lflag
& ECHOCTL
));
626 return (!(termbuf
.c_lflag
& TCTLECH
));
628 # if !defined(ECHOCTL) && !defined(TCTLECH)
629 return (0); /* assumes ctl chars are echoed '^x' */
634 tty_setlitecho(int on
)
638 termbuf
.c_lflag
&= ~ECHOCTL
;
640 termbuf
.c_lflag
|= ECHOCTL
;
644 termbuf
.c_lflag
&= ~TCTLECH
;
646 termbuf
.c_lflag
|= TCTLECH
;
653 return (termbuf
.c_iflag
& ICRNL
);
657 * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD).
666 * A table of available terminal speeds
672 { 0, B0
}, { 50, B50
}, { 75, B75
},
673 { 110, B110
}, { 134, B134
}, { 150, B150
},
674 { 200, B200
}, { 300, B300
}, { 600, B600
},
675 { 1200, B1200
}, { 1800, B1800
}, { 2400, B2400
},
704 #endif /* DECODE_BUAD */
710 struct termspeeds
*tp
;
712 for (tp
= termspeeds
; (tp
->speed
!= -1) && (val
> tp
->speed
); tp
++)
714 if (tp
->speed
== -1) /* back up to last valid value */
716 cfsetospeed(&termbuf
, tp
->value
);
717 #else /* DECODE_BUAD */
718 cfsetospeed(&termbuf
, val
);
719 #endif /* DECODE_BUAD */
726 struct termspeeds
*tp
;
728 for (tp
= termspeeds
; (tp
->speed
!= -1) && (val
> tp
->speed
); tp
++)
730 if (tp
->speed
== -1) /* back up to last valid value */
732 cfsetispeed(&termbuf
, tp
->value
);
733 #else /* DECODE_BAUD */
734 cfsetispeed(&termbuf
, val
);
735 #endif /* DECODE_BAUD */
738 #ifdef PARENT_DOES_UTMP
739 extern struct utmp wtmp
;
742 extern void utmp_sig_init (void);
743 extern void utmp_sig_reset (void);
744 extern void utmp_sig_wait (void);
745 extern void utmp_sig_notify (int);
746 # endif /* PARENT_DOES_UTMP */
750 /* I_FIND seems to live a life of its own */
751 static int my_find(int fd
, char *module
)
753 #if defined(I_FIND) && defined(I_LIST)
755 static struct str_list sl
;
760 n
= ioctl(fd
, I_LIST
, 0);
762 perror("ioctl(fd, I_LIST, 0)");
765 sl
.sl_modlist
=(struct str_mlist
*)malloc(n
* sizeof(struct str_mlist
));
767 n
= ioctl(fd
, I_LIST
, &sl
);
769 perror("ioctl(fd, I_LIST, n)");
775 for(i
=0; i
<sl
.sl_nmods
; i
++)
776 if(!strcmp(sl
.sl_modlist
[i
].l_name
, module
))
782 static void maybe_push_modules(int fd
, char **modules
)
787 for(p
=modules
; *p
; p
++){
788 err
= my_find(fd
, *p
);
791 if(err
< 0 && errno
!= EINVAL
)
792 fatalperror(net
, "my_find()");
793 /* module not pushed or does not exist */
795 /* p points to null or to an already pushed module, now push all
796 modules before this one */
798 for(p
--; p
>= modules
; p
--){
799 err
= ioctl(fd
, I_PUSH
, *p
);
800 if(err
< 0 && errno
!= EINVAL
)
801 fatalperror(net
, "I_PUSH");
809 * Open the slave side of the pty, and do any initialization
810 * that is necessary. The return value is a file descriptor
811 * for the slave side.
813 void getptyslave(void)
819 * Opening the slave side may cause initilization of the
820 * kernel tty structure. We need remember the state of
821 * if linemode was turned on
822 * terminal window size
824 * so that we can re-set them if we need to.
829 * Make sure that we don't have a controlling tty, and
830 * that we are the session (process group) leader.
835 fatalperror(net
, "setsid()");
838 t
= open(_PATH_TTY
, O_RDWR
);
840 ioctl(t
, TIOCNOTTY
, (char *)0);
846 # ifdef PARENT_DOES_UTMP
848 * Wait for our parent to get the utmp stuff to get done.
855 fatalperror(net
, line
);
862 * Not all systems have (or need) modules ttcompat and pckt so
863 * don't flag it as a fatal error if they don't exist.
868 /* these are the streams modules that we want pushed. note
869 that they are in reverse order, ptem will be pushed
870 first. maybe_push_modules() will try to push all modules
871 before the first one that isn't already pushed. i.e if
872 ldterm is pushed, only ttcompat will be attempted.
874 all this is because we don't know which modules are
875 available, and we don't know which modules are already
876 pushed (via autopush, for instance).
880 char *ttymodules
[] = { "ttcompat", "ldterm", "ptem", NULL
};
881 char *ptymodules
[] = { "pckt", NULL
};
883 maybe_push_modules(t
, ttymodules
);
884 maybe_push_modules(ourpty
, ptymodules
);
888 * set up the tty modes as we like them to be.
892 if (def_row
|| def_col
) {
893 memset(&ws
, 0, sizeof(ws
));
896 ioctl(t
, TIOCSWINSZ
, (char *)&ws
);
901 * Settings for sgtty based systems
905 * Settings for UNICOS (and HPUX)
907 # if defined(_CRAY) || defined(__hpux)
908 termbuf
.c_oflag
= OPOST
|ONLCR
|TAB3
;
909 termbuf
.c_iflag
= IGNPAR
|ISTRIP
|ICRNL
|IXON
;
910 termbuf
.c_lflag
= ISIG
|ICANON
|ECHO
|ECHOE
|ECHOK
;
911 termbuf
.c_cflag
= EXTB
|HUPCL
|CS8
;
915 * Settings for all other termios/termio based
916 * systems, other than 4.4BSD. In 4.4BSD the
917 * kernel does the initial terminal setup.
919 # if !(defined(_CRAY) || defined(__hpux)) && (BSD <= 43)
923 termbuf
.c_lflag
|= ECHO
;
924 termbuf
.c_oflag
|= ONLCR
|OXTABS
;
925 termbuf
.c_iflag
|= ICRNL
;
926 termbuf
.c_iflag
&= ~IXOFF
;
928 tty_rspeed((def_rspeed
> 0) ? def_rspeed
: 9600);
929 tty_tspeed((def_tspeed
> 0) ? def_tspeed
: 9600);
932 * Set the tty modes, and make this our controlling tty.
935 if (login_tty(t
) == -1)
936 fatalperror(net
, "login_tty");
949 * Open the specified slave side of the pty,
950 * making sure that we have a clean tty.
953 int cleanopen(char *line
)
957 if (ptyslavefd
!= -1)
965 * Make sure that other people can't open the
966 * slave side of the connection.
976 t
= open(line
, O_RDWR
|O_NOCTTY
);
982 * Hangup anybody else using this ttyp, then reopen it for
985 # if !(defined(_CRAY) || defined(__hpux)) && (BSD <= 43) && !defined(STREAMSPTY)
986 signal(SIGHUP
, SIG_IGN
);
991 signal(SIGHUP
, SIG_DFL
);
992 t
= open(line
, O_RDWR
|O_NOCTTY
);
996 # if defined(_CRAY) && defined(TCVHUP)
999 signal(SIGHUP
, SIG_IGN
);
1000 ioctl(t
, TCVHUP
, (char *)0);
1001 signal(SIGHUP
, SIG_DFL
);
1003 i
= open(line
, O_RDWR
);
1010 # endif /* defined(CRAY) && defined(TCVHUP) */
1014 #if !defined(BSD4_4)
1016 int login_tty(int t
)
1018 /* Dont need to set this as the controlling PTY on steams sockets,
1019 * don't abort on failure. */
1020 # if defined(TIOCSCTTY) && !defined(__hpux)
1021 if (ioctl(t
, TIOCSCTTY
, (char *)0) < 0 && !really_stream
)
1022 fatalperror(net
, "ioctl(sctty)");
1025 * Close the hard fd to /dev/ttypXXX, and re-open through
1026 * the indirect /dev/tty interface.
1029 if ((t
= open("/dev/tty", O_RDWR
)) < 0)
1030 fatalperror(net
, "open(/dev/tty)");
1034 * We get our controlling tty assigned as a side-effect
1035 * of opening up a tty device. But on BSD based systems,
1036 * this only happens if our process group is zero. The
1037 * setsid() call above may have set our pgrp, so clear
1038 * it out before opening the tty...
1043 setpgrp(0, 0); /* if setpgid isn't available, setpgrp
1044 probably takes arguments */
1046 close(open(line
, O_RDWR
));
1058 #endif /* BSD <= 43 */
1061 * This comes from ../../bsd/tty.c and should not really be here.
1065 * Clean the tty name. Return a pointer to the cleaned version.
1068 static char * clean_ttyname (char *) __attribute__((unused
));
1071 clean_ttyname (char *tty
)
1075 if (strncmp (res
, _PATH_DEV
, strlen(_PATH_DEV
)) == 0)
1076 res
+= strlen(_PATH_DEV
);
1077 if (strncmp (res
, "pty/", 4) == 0)
1079 if (strncmp (res
, "ptym/", 5) == 0)
1085 * Generate a name usable as an `ut_id', typically without `tty'.
1088 #ifdef HAVE_STRUCT_UTMP_UT_ID
1094 if (strncmp (res
, "pts/", 4) == 0)
1096 if (strncmp (res
, "tty", 3) == 0)
1105 * Given a hostname, do whatever
1106 * is necessary to startup the login process on the slave side of the pty.
1111 startslave(const char *host
, const char *utmp_host
,
1112 int autologin
, char *autoname
)
1116 #ifdef AUTHENTICATION
1117 if (!autoname
|| !autoname
[0])
1120 if (autologin
< auth_level
) {
1121 fatal(net
, "Authorization failed");
1128 "\r\n*** Connection not encrypted! "
1129 "Communication may be eavesdropped. ***\r\n";
1131 if (!no_warn
&& (encrypt_output
== 0 || decrypt_input
== 0))
1133 writenet(tbuf
, strlen(tbuf
));
1135 # ifdef PARENT_DOES_UTMP
1137 # endif /* PARENT_DOES_UTMP */
1139 if ((i
= fork()) < 0)
1140 fatalperror(net
, "fork");
1142 # ifdef PARENT_DOES_UTMP
1144 * Cray parent will create utmp entry for child and send
1145 * signal to child to tell when done. Child waits for signal
1146 * before doing anything important.
1152 utmp_sig_reset(); /* reset handler to default */
1154 * Create utmp entry for child
1156 wtmp
.ut_time
= time(NULL
);
1157 wtmp
.ut_type
= LOGIN_PROCESS
;
1159 strncpy(wtmp
.ut_user
, "LOGIN", sizeof(wtmp
.ut_user
));
1160 strncpy(wtmp
.ut_host
, utmp_host
, sizeof(wtmp
.ut_host
));
1161 strncpy(wtmp
.ut_line
, clean_ttyname(line
), sizeof(wtmp
.ut_line
));
1162 #ifdef HAVE_STRUCT_UTMP_UT_ID
1163 strncpy(wtmp
.ut_id
, wtmp
.ut_line
+ 3, sizeof(wtmp
.ut_id
));
1168 if ((i
= open(wtmpf
, O_WRONLY
|O_APPEND
)) >= 0) {
1169 write(i
, &wtmp
, sizeof(struct utmp
));
1173 signal(WJSIGNAL
, sigjob
);
1175 utmp_sig_notify(pid
);
1176 # endif /* PARENT_DOES_UTMP */
1180 /* if we authenticated via K5, try and join the PAG */
1183 start_login(host
, autologin
, autoname
);
1189 extern char **environ
;
1197 if ((*envp
= getenv("TZ")))
1199 #if defined(_CRAY) || defined(__hpux)
1201 *envp
++ = "TZ=GMT0";
1210 * We only accept the environment variables listed below.
1216 static const char *reject
[] = {
1221 static const char *accept
[] = {
1222 "XAUTH=", "XAUTHORITY=", "DISPLAY=",
1236 for (cpp2
= cpp
= environ
; *cpp
; cpp
++) {
1239 for(p
= reject
; *p
; p
++)
1240 if(strncmp(*cpp
, *p
, strlen(*p
)) == 0) {
1247 for(p
= accept
; *p
; p
++)
1248 if(strncmp(*cpp
, *p
, strlen(*p
)) == 0)
1263 static void addarg(struct arg_val
*, const char*);
1268 * Assuming that we are now running as a child processes, this
1269 * function will turn us into the login process.
1273 start_login(const char *host
, int autologin
, char *name
)
1275 struct arg_val argv
;
1280 encrypt_output
= NULL
;
1281 decrypt_input
= NULL
;
1292 * Create utmp entry for child
1295 clean_tty
= clean_ttyname(line
);
1296 memset(&utmpx
, 0, sizeof(utmpx
));
1297 strncpy(utmpx
.ut_user
, ".telnet", sizeof(utmpx
.ut_user
));
1298 strncpy(utmpx
.ut_line
, clean_tty
, sizeof(utmpx
.ut_line
));
1299 #ifdef HAVE_STRUCT_UTMP_UT_ID
1300 strncpy(utmpx
.ut_id
, make_id(clean_tty
), sizeof(utmpx
.ut_id
));
1304 utmpx
.ut_type
= LOGIN_PROCESS
;
1306 gettimeofday (&tv
, NULL
);
1307 utmpx
.ut_tv
.tv_sec
= tv
.tv_sec
;
1308 utmpx
.ut_tv
.tv_usec
= tv
.tv_usec
;
1310 if (pututxline(&utmpx
) == NULL
)
1311 fatal(net
, "pututxline failed");
1318 * -h : pass on name of host.
1319 * WARNING: -h is accepted by login if and only if
1321 * -p : don't clobber the environment (so terminal type stays set).
1323 * -f : force this login, he has already been authenticated
1326 /* init argv structure */
1329 argv
.argv
=malloc(0); /*so we can call realloc later */
1330 addarg(&argv
, "login");
1331 addarg(&argv
, "-h");
1332 addarg(&argv
, host
);
1333 addarg(&argv
, "-p");
1337 user
= getenv("USER");
1338 #ifdef AUTHENTICATION
1339 if (auth_level
< 0 || autologin
!= AUTH_VALID
) {
1341 printf("User not authenticated. ");
1343 printf("Using one-time password\r\n");
1345 printf("Using plaintext username and password\r\n");
1348 addarg(&argv
, "-a");
1349 addarg(&argv
, "otp");
1352 syslog(LOG_INFO
, "unauthenticated access from %s (%s)",
1353 host
, user
? user
: "unknown user");
1355 if (auth_level
>= 0 && autologin
== AUTH_VALID
)
1356 addarg(&argv
, "-f");
1359 addarg(&argv
, "--");
1360 addarg(&argv
, strdup(user
));
1362 if (getenv("USER")) {
1364 * Assume that login will set the USER variable
1365 * correctly. For SysV systems, this means that
1366 * USER will no longer be set, just LOGNAME by
1367 * login. (The problem is that if the auto-login
1368 * fails, and the user then specifies a different
1369 * account name, he can get logged in with both
1370 * LOGNAME and USER in his environment, but the
1371 * USER value will be wrong.
1377 * This sleep(1) is in here so that telnetd can
1378 * finish up with the tty. There's a race condition
1379 * the login banner message gets lost...
1383 execv(new_login
, argv
.argv
);
1385 syslog(LOG_ERR
, "%s: %m", new_login
);
1386 fatalperror_errno(net
, new_login
, save_errno
);
1391 addarg(struct arg_val
*argv
, const char *val
)
1393 if(argv
->size
<= argv
->argc
+1) {
1394 argv
->argv
= realloc(argv
->argv
, sizeof(char*) * (argv
->size
+ 10));
1395 if (argv
->argv
== NULL
)
1396 fatal (net
, "realloc: out of memory");
1399 if((argv
->argv
[argv
->argc
++] = strdup(val
)) == NULL
)
1400 fatal (net
, "strdup: out of memory");
1401 argv
->argv
[argv
->argc
] = NULL
;
1408 * This is the function called by cleanup() to
1409 * remove the utmp entry for this person.
1416 struct utmpx utmpx
, *non_save_utxp
;
1417 char *clean_tty
= clean_ttyname(line
);
1420 * This updates the utmpx and utmp entries and make a wtmp/x entry
1424 memset(&utmpx
, 0, sizeof(utmpx
));
1425 strncpy(utmpx
.ut_line
, clean_tty
, sizeof(utmpx
.ut_line
));
1426 utmpx
.ut_type
= LOGIN_PROCESS
;
1427 non_save_utxp
= getutxline(&utmpx
);
1428 if (non_save_utxp
) {
1433 utxp
= malloc(sizeof(struct utmpx
));
1434 *utxp
= *non_save_utxp
;
1435 user0
= utxp
->ut_user
[0];
1436 utxp
->ut_user
[0] = '\0';
1437 utxp
->ut_type
= DEAD_PROCESS
;
1438 #ifdef HAVE_STRUCT_UTMPX_UT_EXIT
1439 #ifdef _STRUCT___EXIT_STATUS
1440 utxp
->ut_exit
.__e_termination
= 0;
1441 utxp
->ut_exit
.__e_exit
= 0;
1442 #elif defined(__osf__) /* XXX */
1443 utxp
->ut_exit
.ut_termination
= 0;
1444 utxp
->ut_exit
.ut_exit
= 0;
1446 utxp
->ut_exit
.e_termination
= 0;
1447 utxp
->ut_exit
.e_exit
= 0;
1450 gettimeofday (&tv
, NULL
);
1451 utxp
->ut_tv
.tv_sec
= tv
.tv_sec
;
1452 utxp
->ut_tv
.tv_usec
= tv
.tv_usec
;
1456 utxp
->ut_user
[0] = user0
;
1457 updwtmpx(WTMPX_FILE
, utxp
);
1458 #elif defined(WTMP_FILE)
1459 /* This is a strange system with a utmpx and a wtmp! */
1461 int f
= open(wtmpf
, O_WRONLY
|O_APPEND
);
1464 strncpy(wtmp
.ut_line
, clean_tty
, sizeof(wtmp
.ut_line
));
1465 strncpy(wtmp
.ut_name
, "", sizeof(wtmp
.ut_name
));
1466 #ifdef HAVE_STRUCT_UTMP_UT_HOST
1467 strncpy(wtmp
.ut_host
, "", sizeof(wtmp
.ut_host
));
1469 wtmp
.ut_time
= time(NULL
);
1470 write(f
, &wtmp
, sizeof(wtmp
));
1481 #if !defined(HAVE_UTMPX_H) && !(defined(_CRAY) || defined(__hpux)) && BSD <= 43
1487 struct utmp
*u
, *utmp
;
1490 char *clean_tty
= clean_ttyname(line
);
1492 f
= open(utmpf
, O_RDWR
);
1495 utmp
= (struct utmp
*)malloc((unsigned)statbf
.st_size
);
1497 syslog(LOG_ERR
, "utmp malloc failed");
1498 if (statbf
.st_size
&& utmp
) {
1499 nutmp
= read(f
, utmp
, (int)statbf
.st_size
);
1500 nutmp
/= sizeof(struct utmp
);
1502 for (u
= utmp
; u
< &utmp
[nutmp
] ; u
++) {
1503 if (strncmp(u
->ut_line
,
1505 sizeof(u
->ut_line
)) ||
1508 lseek(f
, ((long)u
)-((long)utmp
), L_SET
);
1509 strncpy(u
->ut_name
, "", sizeof(u
->ut_name
));
1510 #ifdef HAVE_STRUCT_UTMP_UT_HOST
1511 strncpy(u
->ut_host
, "", sizeof(u
->ut_host
));
1513 u
->ut_time
= time(NULL
);
1514 write(f
, u
, sizeof(wtmp
));
1521 f
= open(wtmpf
, O_WRONLY
|O_APPEND
);
1523 strncpy(wtmp
.ut_line
, clean_tty
, sizeof(wtmp
.ut_line
));
1524 strncpy(wtmp
.ut_name
, "", sizeof(wtmp
.ut_name
));
1525 #ifdef HAVE_STRUCT_UTMP_UT_HOST
1526 strncpy(wtmp
.ut_host
, "", sizeof(wtmp
.ut_host
));
1528 wtmp
.ut_time
= time(NULL
);
1529 write(f
, &wtmp
, sizeof(wtmp
));
1535 line
[strlen("/dev/")] = 'p';
1541 #if defined(__hpux) && !defined(HAVE_UTMPX_H)
1547 int fd
; /* for /etc/wtmp */
1549 utmp
.ut_type
= USER_PROCESS
;
1550 strncpy(utmp
.ut_line
, clean_ttyname(line
), sizeof(utmp
.ut_line
));
1552 utptr
= getutline(&utmp
);
1553 /* write it out only if it exists */
1555 utptr
->ut_type
= DEAD_PROCESS
;
1556 utptr
->ut_time
= time(NULL
);
1558 /* set wtmp entry if wtmp file exists */
1559 if ((fd
= open(wtmpf
, O_WRONLY
| O_APPEND
)) >= 0) {
1560 write(fd
, utptr
, sizeof(utmp
));
1568 line
[14] = line
[13];
1569 line
[13] = line
[12];
1583 * This is the routine to call when we are all through, to
1584 * clean up anything that needs to be cleaned up.
1587 #ifdef PARENT_DOES_UTMP
1593 static int incleanup
= 0;
1595 int child_status
; /* status of child process as returned by waitpid */
1596 int flags
= WNOHANG
|WUNTRACED
;
1599 * 1: Pick up the zombie, if we are being called
1600 * as the signal handler.
1601 * 2: If we are a nested cleanup(), return.
1602 * 3: Try to clean up TMPDIR.
1603 * 4: Fill in utmp with shutdown of process.
1604 * 5: Close down the network and pty connections.
1605 * 6: Finish up the TMPDIR cleanup, if needed.
1607 if (sig
== SIGCHLD
) {
1608 while (waitpid(-1, &child_status
, flags
) > 0)
1610 /* Check if the child process was stopped
1611 * rather than exited. We want cleanup only if
1612 * the child has died.
1614 if (WIFSTOPPED(child_status
)) {
1618 t
= sigblock(sigmask(SIGCHLD
));
1626 t
= cleantmp(&wtmp
);
1627 setutent(); /* just to make sure */
1639 #else /* PARENT_DOES_UTMP */
1644 #if defined(HAVE_UTMPX_H) || !defined(HAVE_LOGWTMP)
1648 vhangup(); /* XXX */
1654 p
= line
+ sizeof("/dev/") - 1;
1667 #endif /* PARENT_DOES_UTMP */
1669 #ifdef PARENT_DOES_UTMP
1674 * These three functions are used to coordinate the handling of
1675 * the utmp file between the server and the soon-to-be-login shell.
1676 * The server actually creates the utmp structure, the child calls
1677 * utmp_sig_wait(), until the server calls utmp_sig_notify() and
1678 * signals the future-login shell to proceed.
1680 static int caught
=0; /* NZ when signal intercepted */
1681 static void (*func
)(); /* address of previous handler */
1688 signal(SIGUSR1
, func
);
1695 * register signal handler for UTMP creation
1697 if ((int)(func
= signal(SIGUSR1
, _utmp_sig_rcv
)) == -1)
1698 fatalperror(net
, "telnetd/signal");
1704 signal(SIGUSR1
, func
); /* reset handler to default */
1708 # define sigoff() /* do nothing */
1709 # define sigon() /* do nothing */
1716 * Wait for parent to write our utmp entry.
1719 while (caught
== 0) {
1720 pause(); /* wait until we get a signal (sigon) */
1721 sigoff(); /* turn off signals while we check caught */
1723 sigon(); /* turn on signals again */
1727 utmp_sig_notify(pid
)
1733 static int gotsigjob
= 0;
1743 while ((jid
= waitjob(NULL
)) != -1) {
1748 jobend(jid
, NULL
, NULL
);
1754 * called by jobend() before calling cleantmp()
1755 * to find the correct $TMPDIR to cleanup.
1762 struct utmp
*cur
= NULL
;
1764 setutent(); /* just to make sure */
1765 while (cur
= getutent()) {
1766 if ( (cur
->ut_type
!= NULL
) && (jid
== cur
->ut_jid
) ) {
1775 * Clean up the TMPDIR that login created.
1776 * The first time this is called we pick up the info
1777 * from the utmp. If the job has already gone away,
1778 * then we'll clean up and be done. If not, then
1779 * when this is called the second time it will wait
1780 * for the signal that the job is done.
1787 static int first
= 1;
1788 int mask
, omask
, ret
;
1789 extern struct utmp
*getutid (const struct utmp
*_Id
);
1792 mask
= sigmask(WJSIGNAL
);
1795 omask
= sigblock(mask
);
1796 while (gotsigjob
== 0)
1801 setutent(); /* just to make sure */
1805 syslog(LOG_ERR
, "Can't get /etc/utmp entry to clean TMPDIR");
1809 * Nothing to clean up if the user shell was never started.
1811 if (utp
->ut_type
!= USER_PROCESS
|| utp
->ut_jid
== 0)
1815 * Block the WJSIGNAL while we are in jobend().
1817 omask
= sigblock(mask
);
1818 ret
= jobend(utp
->ut_jid
, utp
->ut_tpath
, utp
->ut_user
);
1824 jobend(jid
, path
, user
)
1829 static int saved_jid
= 0;
1830 static int pty_saved_jid
= 0;
1831 static char saved_path
[sizeof(wtmp
.ut_tpath
)+1];
1832 static char saved_user
[sizeof(wtmp
.ut_user
)+1];
1835 * this little piece of code comes into play
1836 * only when ptyreconnect is used to reconnect
1837 * to an previous session.
1839 * this is the only time when the
1840 * "saved_jid != jid" code is executed.
1843 if ( saved_jid
&& saved_jid
!= jid
) {
1844 if (!path
) { /* called from signal handler */
1845 pty_saved_jid
= jid
;
1847 pty_saved_jid
= saved_jid
;
1852 strlcpy(saved_path
, path
, sizeof(saved_path
));
1853 strlcpy(saved_user
, user
, sizeof(saved_user
));
1855 if (saved_jid
== 0) {
1860 /* if the jid has changed, get the correct entry from the utmp file */
1862 if ( saved_jid
!= jid
) {
1863 struct utmp
*utp
= NULL
;
1864 struct utmp
*jid_getutid();
1866 utp
= jid_getutid(pty_saved_jid
);
1869 syslog(LOG_ERR
, "Can't get /etc/utmp entry to clean TMPDIR");
1873 cleantmpdir(jid
, utp
->ut_tpath
, utp
->ut_user
);
1877 cleantmpdir(jid
, saved_path
, saved_user
);
1882 * Fork a child process to clean up the TMPDIR
1884 cleantmpdir(jid
, tpath
, user
)
1891 syslog(LOG_ERR
, "TMPDIR cleanup(%s): fork() failed: %m\n",
1895 execl(CLEANTMPCMD
, CLEANTMPCMD
, user
, tpath
, NULL
);
1896 syslog(LOG_ERR
, "TMPDIR cleanup(%s): execl(%s) failed: %m\n",
1897 tpath
, CLEANTMPCMD
);
1901 * Forget about child. We will exit, and
1902 * /etc/init will pick it up.
1908 #endif /* defined(PARENT_DOES_UTMP) */