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
36 RCSID("$Id: sys_term.c 22390 2007-12-31 10:12:48Z lha $");
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 #if !defined(WTMP_FILE) && defined(_PATH_WTMP)
71 #define WTMP_FILE _PATH_WTMP
74 #ifndef PARENT_DOES_UTMP
76 char wtmpf[] = WTMP_FILE;
78 char wtmpf[] = "/usr/adm/wtmp";
80 char utmpf[] = UTMP_FILE;
81 #else /* PARENT_DOES_UTMP */
83 char wtmpf[] = WTMP_FILE;
85 char wtmpf[] = "/etc/wtmp";
87 #endif /* PARENT_DOES_UTMP */
93 #if !(defined(__sgi) || defined(__linux) || defined(_AIX)) && defined(HAVE_SYS_TTY)
113 #ifdef HAVE_TERMIOS_H
124 #ifdef HAVE_LIBUTIL_H
130 # define TCSANOW TCSETS
131 # define TCSADRAIN TCSETSW
132 # define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t)
135 # define TCSANOW TCSETA
136 # define TCSADRAIN TCSETAW
137 # define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t)
139 # define TCSANOW TIOCSETA
140 # define TCSADRAIN TIOCSETAW
141 # define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t)
144 # define tcsetattr(f, a, t) ioctl(f, a, t)
145 # define cfsetospeed(tp, val) (tp)->c_cflag &= ~CBAUD; \
146 (tp)->c_cflag |= (val)
147 # define cfgetospeed(tp) ((tp)->c_cflag & CBAUD)
149 # define cfsetispeed(tp, val) (tp)->c_cflag &= ~CIBAUD; \
150 (tp)->c_cflag |= ((val)<<IBSHIFT)
151 # define cfgetispeed(tp) (((tp)->c_cflag & CIBAUD)>>IBSHIFT)
153 # define cfsetispeed(tp, val) (tp)->c_cflag &= ~CBAUD; \
154 (tp)->c_cflag |= (val)
155 # define cfgetispeed(tp) ((tp)->c_cflag & CBAUD)
157 # endif /* TCSANOW */
158 struct termios termbuf, termbuf2; /* pty control structure */
160 static int ttyfd = -1;
161 int really_stream = 0;
164 const char *new_login = _PATH_LOGIN;
171 * These three routines are used to get and set the "termbuf" structure
172 * to and from the kernel. init_termbuf() gets the current settings.
173 * copy_termbuf() hands in a new "termbuf" to write to the kernel, and
174 * set_termbuf() writes the structure into the kernel.
182 tcgetattr(ttyfd, &termbuf);
185 tcgetattr(ourpty, &termbuf);
193 * Only make the necessary changes.
195 if (memcmp(&termbuf, &termbuf2, sizeof(termbuf))) {
198 tcsetattr(ttyfd, TCSANOW, &termbuf);
201 tcsetattr(ourpty, TCSANOW, &termbuf);
207 * spcset(func, valp, valpp)
209 * This function takes various special characters (func), and
210 * sets *valp to the current value of that character, and
211 * *valpp to point to where in the "termbuf" structure that
214 * It returns the SLC_ level of support for this function.
219 spcset(int func, cc_t *valp, cc_t **valpp)
222 #define setval(a, b) *valp = termbuf.c_cc[a]; \
223 *valpp = &termbuf.c_cc[a]; \
225 #define defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT);
229 setval(VEOF, SLC_VARIABLE);
231 setval(VERASE, SLC_VARIABLE);
233 setval(VKILL, SLC_VARIABLE);
235 setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
237 setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
240 setval(VSTART, SLC_VARIABLE);
246 setval(VSTOP, SLC_VARIABLE);
252 setval(VWERASE, SLC_VARIABLE);
258 setval(VREPRINT, SLC_VARIABLE);
264 setval(VLNEXT, SLC_VARIABLE);
269 #if !defined(VDISCARD) && defined(VFLUSHO)
270 # define VDISCARD VFLUSHO
273 setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT);
279 setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN);
285 setval(VEOL, SLC_VARIABLE);
289 setval(VEOL2, SLC_VARIABLE);
293 setval(VSTATUS, SLC_VARIABLE);
306 return(SLC_NOSUPPORT);
314 * Return the number of pty's configured into the system.
322 if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1)
325 #endif /* _SC_CRAY_NPTY */
333 * Allocate a pty. As a side effect, the external character
334 * array "line" contains the name of the slave side.
336 * Returns the file descriptor of the opened pty.
339 static int ptyslavefd = -1;
341 static char Xline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
345 char myline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
348 #if !defined(HAVE_PTSNAME) && defined(STREAMSPTY)
349 static char *ptsname(int fd)
359 int getpty(int *ptynum)
361 #if defined(HAVE_OPENPTY) || defined(__linux) || defined(__osf__) /* XXX */
365 if(openpty(&master, &slave, line, 0, 0) == 0){
370 #endif /* HAVE_OPENPTY .... */
375 p = _getpty(&master, O_RDWR, 0600, 1);
378 strlcpy(line, p, sizeof(Xline));
385 char *clone[] = { "/dev/ptc", "/dev/ptmx", "/dev/ptm",
386 "/dev/ptym/clone", 0 };
390 for(q=clone; *q; q++){
399 strlcpy(line, ptsname(p), sizeof(Xline));
405 #endif /* STREAMSPTY */
413 snprintf(line, sizeof(Xline), "/dev/ptyXX");
417 snprintf(line, sizeof(Xline), "/dev/ptym/ptyXX");
423 for (cp = "pqrstuvwxyzPQRST"; *cp; cp++) {
429 * This stat() check is just to keep us from
430 * looping through all 256 combinations if there
431 * aren't that many ptys available.
433 if (stat(line, &stb) < 0)
435 for (i = 0; i < 16; i++) {
436 *p2 = "0123456789abcdef"[i];
437 p = open(line, O_RDWR);
446 for (p1 = &line[8]; *p1; p1++)
453 if (ioctl(p, TIOCGPGRP, &dummy) == 0
459 #endif /* SunOS == 40 */
467 extern lowpty, highpty;
471 for (*ptynum = lowpty; *ptynum <= highpty; (*ptynum)++) {
472 snprintf(myline, sizeof(myline), "/dev/pty/%03d", *ptynum);
476 snprintf(line, sizeof(Xline), "/dev/ttyp%03d", *ptynum);
478 * Here are some shenanigans to make sure that there
479 * are no listeners lurking on the line.
481 if(stat(line, &sb) < 0) {
485 if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) {
494 * Now it should be safe...check for accessability.
496 if (access(line, 6) == 0)
499 /* no tty side to pty so skip it */
512 return (termbuf.c_lflag & ECHO);
518 return((termbuf.c_iflag & IXON) ? 1 : 0);
524 return((termbuf.c_iflag & IXANY) ? 1 : 0);
531 termbuf.c_lflag |= ECHO;
533 termbuf.c_lflag &= ~ECHO;
539 return(!(termbuf.c_lflag & ICANON));
546 termbuf.c_iflag &= ~ISTRIP;
548 termbuf.c_iflag |= ISTRIP;
553 tty_binaryout(int on)
556 termbuf.c_cflag &= ~(CSIZE|PARENB);
557 termbuf.c_cflag |= CS8;
558 termbuf.c_oflag &= ~OPOST;
560 termbuf.c_cflag &= ~CSIZE;
561 termbuf.c_cflag |= CS7|PARENB;
562 termbuf.c_oflag |= OPOST;
569 return(!(termbuf.c_iflag & ISTRIP));
573 tty_isbinaryout(void)
575 return(!(termbuf.c_oflag&OPOST));
583 return (termbuf.c_oflag & OXTABS);
586 return ((termbuf.c_oflag & TABDLY) == TAB3);
591 tty_setsofttab(int on)
595 termbuf.c_oflag |= OXTABS;
598 termbuf.c_oflag &= ~TABDLY;
599 termbuf.c_oflag |= TAB3;
603 termbuf.c_oflag &= ~OXTABS;
606 termbuf.c_oflag &= ~TABDLY;
607 termbuf.c_oflag |= TAB0;
616 return (!(termbuf.c_lflag & ECHOCTL));
619 return (!(termbuf.c_lflag & TCTLECH));
621 # if !defined(ECHOCTL) && !defined(TCTLECH)
622 return (0); /* assumes ctl chars are echoed '^x' */
627 tty_setlitecho(int on)
631 termbuf.c_lflag &= ~ECHOCTL;
633 termbuf.c_lflag |= ECHOCTL;
637 termbuf.c_lflag &= ~TCTLECH;
639 termbuf.c_lflag |= TCTLECH;
646 return (termbuf.c_iflag & ICRNL);
650 * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD).
659 * A table of available terminal speeds
665 { 0, B0 }, { 50, B50 }, { 75, B75 },
666 { 110, B110 }, { 134, B134 }, { 150, B150 },
667 { 200, B200 }, { 300, B300 }, { 600, B600 },
668 { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 },
697 #endif /* DECODE_BUAD */
703 struct termspeeds *tp;
705 for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
707 if (tp->speed == -1) /* back up to last valid value */
709 cfsetospeed(&termbuf, tp->value);
710 #else /* DECODE_BUAD */
711 cfsetospeed(&termbuf, val);
712 #endif /* DECODE_BUAD */
719 struct termspeeds *tp;
721 for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
723 if (tp->speed == -1) /* back up to last valid value */
725 cfsetispeed(&termbuf, tp->value);
726 #else /* DECODE_BAUD */
727 cfsetispeed(&termbuf, val);
728 #endif /* DECODE_BAUD */
731 #ifdef PARENT_DOES_UTMP
732 extern struct utmp wtmp;
735 extern void utmp_sig_init (void);
736 extern void utmp_sig_reset (void);
737 extern void utmp_sig_wait (void);
738 extern void utmp_sig_notify (int);
739 # endif /* PARENT_DOES_UTMP */
743 /* I_FIND seems to live a life of its own */
744 static int my_find(int fd, char *module)
746 #if defined(I_FIND) && defined(I_LIST)
748 static struct str_list sl;
753 n = ioctl(fd, I_LIST, 0);
755 perror("ioctl(fd, I_LIST, 0)");
758 sl.sl_modlist=(struct str_mlist*)malloc(n * sizeof(struct str_mlist));
760 n = ioctl(fd, I_LIST, &sl);
762 perror("ioctl(fd, I_LIST, n)");
768 for(i=0; i<sl.sl_nmods; i++)
769 if(!strcmp(sl.sl_modlist[i].l_name, module))
775 static void maybe_push_modules(int fd, char **modules)
780 for(p=modules; *p; p++){
781 err = my_find(fd, *p);
784 if(err < 0 && errno != EINVAL)
785 fatalperror(net, "my_find()");
786 /* module not pushed or does not exist */
788 /* p points to null or to an already pushed module, now push all
789 modules before this one */
791 for(p--; p >= modules; p--){
792 err = ioctl(fd, I_PUSH, *p);
793 if(err < 0 && errno != EINVAL)
794 fatalperror(net, "I_PUSH");
802 * Open the slave side of the pty, and do any initialization
803 * that is necessary. The return value is a file descriptor
804 * for the slave side.
806 void getptyslave(void)
812 * Opening the slave side may cause initilization of the
813 * kernel tty structure. We need remember the state of
814 * if linemode was turned on
815 * terminal window size
817 * so that we can re-set them if we need to.
822 * Make sure that we don't have a controlling tty, and
823 * that we are the session (process group) leader.
828 fatalperror(net, "setsid()");
831 t = open(_PATH_TTY, O_RDWR);
833 ioctl(t, TIOCNOTTY, (char *)0);
839 # ifdef PARENT_DOES_UTMP
841 * Wait for our parent to get the utmp stuff to get done.
848 fatalperror(net, line);
855 * Not all systems have (or need) modules ttcompat and pckt so
856 * don't flag it as a fatal error if they don't exist.
861 /* these are the streams modules that we want pushed. note
862 that they are in reverse order, ptem will be pushed
863 first. maybe_push_modules() will try to push all modules
864 before the first one that isn't already pushed. i.e if
865 ldterm is pushed, only ttcompat will be attempted.
867 all this is because we don't know which modules are
868 available, and we don't know which modules are already
869 pushed (via autopush, for instance).
873 char *ttymodules[] = { "ttcompat", "ldterm", "ptem", NULL };
874 char *ptymodules[] = { "pckt", NULL };
876 maybe_push_modules(t, ttymodules);
877 maybe_push_modules(ourpty, ptymodules);
881 * set up the tty modes as we like them to be.
885 if (def_row || def_col) {
886 memset(&ws, 0, sizeof(ws));
889 ioctl(t, TIOCSWINSZ, (char *)&ws);
894 * Settings for sgtty based systems
898 * Settings for UNICOS (and HPUX)
900 # if defined(_CRAY) || defined(__hpux)
901 termbuf.c_oflag = OPOST|ONLCR|TAB3;
902 termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
903 termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
904 termbuf.c_cflag = EXTB|HUPCL|CS8;
908 * Settings for all other termios/termio based
909 * systems, other than 4.4BSD. In 4.4BSD the
910 * kernel does the initial terminal setup.
912 # if !(defined(_CRAY) || defined(__hpux)) && (BSD <= 43)
916 termbuf.c_lflag |= ECHO;
917 termbuf.c_oflag |= ONLCR|OXTABS;
918 termbuf.c_iflag |= ICRNL;
919 termbuf.c_iflag &= ~IXOFF;
921 tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600);
922 tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600);
925 * Set the tty modes, and make this our controlling tty.
928 if (login_tty(t) == -1)
929 fatalperror(net, "login_tty");
942 * Open the specified slave side of the pty,
943 * making sure that we have a clean tty.
946 int cleanopen(char *line)
950 if (ptyslavefd != -1)
958 * Make sure that other people can't open the
959 * slave side of the connection.
969 t = open(line, O_RDWR|O_NOCTTY);
975 * Hangup anybody else using this ttyp, then reopen it for
978 # if !(defined(_CRAY) || defined(__hpux)) && (BSD <= 43) && !defined(STREAMSPTY)
979 signal(SIGHUP, SIG_IGN);
984 signal(SIGHUP, SIG_DFL);
985 t = open(line, O_RDWR|O_NOCTTY);
989 # if defined(_CRAY) && defined(TCVHUP)
992 signal(SIGHUP, SIG_IGN);
993 ioctl(t, TCVHUP, (char *)0);
994 signal(SIGHUP, SIG_DFL);
996 i = open(line, O_RDWR);
1003 # endif /* defined(CRAY) && defined(TCVHUP) */
1007 #if !defined(BSD4_4)
1009 int login_tty(int t)
1011 # if defined(TIOCSCTTY) && !defined(__hpux)
1012 if (ioctl(t, TIOCSCTTY, (char *)0) < 0)
1013 fatalperror(net, "ioctl(sctty)");
1016 * Close the hard fd to /dev/ttypXXX, and re-open through
1017 * the indirect /dev/tty interface.
1020 if ((t = open("/dev/tty", O_RDWR)) < 0)
1021 fatalperror(net, "open(/dev/tty)");
1025 * We get our controlling tty assigned as a side-effect
1026 * of opening up a tty device. But on BSD based systems,
1027 * this only happens if our process group is zero. The
1028 * setsid() call above may have set our pgrp, so clear
1029 * it out before opening the tty...
1034 setpgrp(0, 0); /* if setpgid isn't available, setpgrp
1035 probably takes arguments */
1037 close(open(line, O_RDWR));
1049 #endif /* BSD <= 43 */
1052 * This comes from ../../bsd/tty.c and should not really be here.
1056 * Clean the tty name. Return a pointer to the cleaned version.
1059 static char * clean_ttyname (char *) __attribute__((unused));
1062 clean_ttyname (char *tty)
1066 if (strncmp (res, _PATH_DEV, strlen(_PATH_DEV)) == 0)
1067 res += strlen(_PATH_DEV);
1068 if (strncmp (res, "pty/", 4) == 0)
1070 if (strncmp (res, "ptym/", 5) == 0)
1076 * Generate a name usable as an `ut_id', typically without `tty'.
1079 #ifdef HAVE_STRUCT_UTMP_UT_ID
1085 if (strncmp (res, "pts/", 4) == 0)
1087 if (strncmp (res, "tty", 3) == 0)
1096 * Given a hostname, do whatever
1097 * is necessary to startup the login process on the slave side of the pty.
1102 startslave(const char *host, const char *utmp_host,
1103 int autologin, char *autoname)
1107 #ifdef AUTHENTICATION
1108 if (!autoname || !autoname[0])
1111 if (autologin < auth_level) {
1112 fatal(net, "Authorization failed");
1119 "\r\n*** Connection not encrypted! "
1120 "Communication may be eavesdropped. ***\r\n";
1122 if (!no_warn && (encrypt_output == 0 || decrypt_input == 0))
1124 writenet(tbuf, strlen(tbuf));
1126 # ifdef PARENT_DOES_UTMP
1128 # endif /* PARENT_DOES_UTMP */
1130 if ((i = fork()) < 0)
1131 fatalperror(net, "fork");
1133 # ifdef PARENT_DOES_UTMP
1135 * Cray parent will create utmp entry for child and send
1136 * signal to child to tell when done. Child waits for signal
1137 * before doing anything important.
1143 utmp_sig_reset(); /* reset handler to default */
1145 * Create utmp entry for child
1147 wtmp.ut_time = time(NULL);
1148 wtmp.ut_type = LOGIN_PROCESS;
1150 strncpy(wtmp.ut_user, "LOGIN", sizeof(wtmp.ut_user));
1151 strncpy(wtmp.ut_host, utmp_host, sizeof(wtmp.ut_host));
1152 strncpy(wtmp.ut_line, clean_ttyname(line), sizeof(wtmp.ut_line));
1153 #ifdef HAVE_STRUCT_UTMP_UT_ID
1154 strncpy(wtmp.ut_id, wtmp.ut_line + 3, sizeof(wtmp.ut_id));
1159 if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) {
1160 write(i, &wtmp, sizeof(struct utmp));
1164 signal(WJSIGNAL, sigjob);
1166 utmp_sig_notify(pid);
1167 # endif /* PARENT_DOES_UTMP */
1171 /* if we authenticated via K5, try and join the PAG */
1174 start_login(host, autologin, autoname);
1180 extern char **environ;
1188 if ((*envp = getenv("TZ")))
1190 #if defined(_CRAY) || defined(__hpux)
1192 *envp++ = "TZ=GMT0";
1201 * We only accept the environment variables listed below.
1207 static const char *reject[] = {
1212 static const char *accept[] = {
1213 "XAUTH=", "XAUTHORITY=", "DISPLAY=",
1227 for (cpp2 = cpp = environ; *cpp; cpp++) {
1230 for(p = reject; *p; p++)
1231 if(strncmp(*cpp, *p, strlen(*p)) == 0) {
1238 for(p = accept; *p; p++)
1239 if(strncmp(*cpp, *p, strlen(*p)) == 0)
1254 static void addarg(struct arg_val*, const char*);
1259 * Assuming that we are now running as a child processes, this
1260 * function will turn us into the login process.
1264 start_login(const char *host, int autologin, char *name)
1266 struct arg_val argv;
1271 encrypt_output = NULL;
1272 decrypt_input = NULL;
1283 * Create utmp entry for child
1286 clean_tty = clean_ttyname(line);
1287 memset(&utmpx, 0, sizeof(utmpx));
1288 strncpy(utmpx.ut_user, ".telnet", sizeof(utmpx.ut_user));
1289 strncpy(utmpx.ut_line, clean_tty, sizeof(utmpx.ut_line));
1290 #ifdef HAVE_STRUCT_UTMP_UT_ID
1291 strncpy(utmpx.ut_id, make_id(clean_tty), sizeof(utmpx.ut_id));
1295 utmpx.ut_type = LOGIN_PROCESS;
1297 gettimeofday (&tv, NULL);
1298 utmpx.ut_tv.tv_sec = tv.tv_sec;
1299 utmpx.ut_tv.tv_usec = tv.tv_usec;
1301 if (pututxline(&utmpx) == NULL)
1302 fatal(net, "pututxline failed");
1309 * -h : pass on name of host.
1310 * WARNING: -h is accepted by login if and only if
1312 * -p : don't clobber the environment (so terminal type stays set).
1314 * -f : force this login, he has already been authenticated
1317 /* init argv structure */
1320 argv.argv=malloc(0); /*so we can call realloc later */
1321 addarg(&argv, "login");
1322 addarg(&argv, "-h");
1323 addarg(&argv, host);
1324 addarg(&argv, "-p");
1328 user = getenv("USER");
1329 #ifdef AUTHENTICATION
1330 if (auth_level < 0 || autologin != AUTH_VALID) {
1332 printf("User not authenticated. ");
1334 printf("Using one-time password\r\n");
1336 printf("Using plaintext username and password\r\n");
1339 addarg(&argv, "-a");
1340 addarg(&argv, "otp");
1343 syslog(LOG_INFO, "unauthenticated access from %s (%s)",
1344 host, user ? user : "unknown user");
1346 if (auth_level >= 0 && autologin == AUTH_VALID)
1347 addarg(&argv, "-f");
1350 addarg(&argv, "--");
1351 addarg(&argv, strdup(user));
1353 if (getenv("USER")) {
1355 * Assume that login will set the USER variable
1356 * correctly. For SysV systems, this means that
1357 * USER will no longer be set, just LOGNAME by
1358 * login. (The problem is that if the auto-login
1359 * fails, and the user then specifies a different
1360 * account name, he can get logged in with both
1361 * LOGNAME and USER in his environment, but the
1362 * USER value will be wrong.
1368 * This sleep(1) is in here so that telnetd can
1369 * finish up with the tty. There's a race condition
1370 * the login banner message gets lost...
1374 execv(new_login, argv.argv);
1376 syslog(LOG_ERR, "%s: %m", new_login);
1377 fatalperror_errno(net, new_login, save_errno);
1382 addarg(struct arg_val *argv, const char *val)
1384 if(argv->size <= argv->argc+1) {
1385 argv->argv = realloc(argv->argv, sizeof(char*) * (argv->size + 10));
1386 if (argv->argv == NULL)
1387 fatal (net, "realloc: out of memory");
1390 if((argv->argv[argv->argc++] = strdup(val)) == NULL)
1391 fatal (net, "strdup: out of memory");
1392 argv->argv[argv->argc] = NULL;
1399 * This is the function called by cleanup() to
1400 * remove the utmp entry for this person.
1407 struct utmpx utmpx, *non_save_utxp;
1408 char *clean_tty = clean_ttyname(line);
1411 * This updates the utmpx and utmp entries and make a wtmp/x entry
1415 memset(&utmpx, 0, sizeof(utmpx));
1416 strncpy(utmpx.ut_line, clean_tty, sizeof(utmpx.ut_line));
1417 utmpx.ut_type = LOGIN_PROCESS;
1418 non_save_utxp = getutxline(&utmpx);
1419 if (non_save_utxp) {
1424 utxp = malloc(sizeof(struct utmpx));
1425 *utxp = *non_save_utxp;
1426 user0 = utxp->ut_user[0];
1427 utxp->ut_user[0] = '\0';
1428 utxp->ut_type = DEAD_PROCESS;
1429 #ifdef HAVE_STRUCT_UTMPX_UT_EXIT
1430 #ifdef _STRUCT___EXIT_STATUS
1431 utxp->ut_exit.__e_termination = 0;
1432 utxp->ut_exit.__e_exit = 0;
1433 #elif defined(__osf__) /* XXX */
1434 utxp->ut_exit.ut_termination = 0;
1435 utxp->ut_exit.ut_exit = 0;
1437 utxp->ut_exit.e_termination = 0;
1438 utxp->ut_exit.e_exit = 0;
1441 gettimeofday (&tv, NULL);
1442 utxp->ut_tv.tv_sec = tv.tv_sec;
1443 utxp->ut_tv.tv_usec = tv.tv_usec;
1447 utxp->ut_user[0] = user0;
1448 updwtmpx(WTMPX_FILE, utxp);
1449 #elif defined(WTMP_FILE)
1450 /* This is a strange system with a utmpx and a wtmp! */
1452 int f = open(wtmpf, O_WRONLY|O_APPEND);
1455 strncpy(wtmp.ut_line, clean_tty, sizeof(wtmp.ut_line));
1456 strncpy(wtmp.ut_name, "", sizeof(wtmp.ut_name));
1457 #ifdef HAVE_STRUCT_UTMP_UT_HOST
1458 strncpy(wtmp.ut_host, "", sizeof(wtmp.ut_host));
1460 wtmp.ut_time = time(NULL);
1461 write(f, &wtmp, sizeof(wtmp));
1472 #if !defined(HAVE_UTMPX_H) && !(defined(_CRAY) || defined(__hpux)) && BSD <= 43
1478 struct utmp *u, *utmp;
1481 char *clean_tty = clean_ttyname(line);
1483 f = open(utmpf, O_RDWR);
1486 utmp = (struct utmp *)malloc((unsigned)statbf.st_size);
1488 syslog(LOG_ERR, "utmp malloc failed");
1489 if (statbf.st_size && utmp) {
1490 nutmp = read(f, utmp, (int)statbf.st_size);
1491 nutmp /= sizeof(struct utmp);
1493 for (u = utmp ; u < &utmp[nutmp] ; u++) {
1494 if (strncmp(u->ut_line,
1496 sizeof(u->ut_line)) ||
1499 lseek(f, ((long)u)-((long)utmp), L_SET);
1500 strncpy(u->ut_name, "", sizeof(u->ut_name));
1501 #ifdef HAVE_STRUCT_UTMP_UT_HOST
1502 strncpy(u->ut_host, "", sizeof(u->ut_host));
1504 u->ut_time = time(NULL);
1505 write(f, u, sizeof(wtmp));
1512 f = open(wtmpf, O_WRONLY|O_APPEND);
1514 strncpy(wtmp.ut_line, clean_tty, sizeof(wtmp.ut_line));
1515 strncpy(wtmp.ut_name, "", sizeof(wtmp.ut_name));
1516 #ifdef HAVE_STRUCT_UTMP_UT_HOST
1517 strncpy(wtmp.ut_host, "", sizeof(wtmp.ut_host));
1519 wtmp.ut_time = time(NULL);
1520 write(f, &wtmp, sizeof(wtmp));
1526 line[strlen("/dev/")] = 'p';
1532 #if defined(__hpux) && !defined(HAVE_UTMPX_H)
1538 int fd; /* for /etc/wtmp */
1540 utmp.ut_type = USER_PROCESS;
1541 strncpy(utmp.ut_line, clean_ttyname(line), sizeof(utmp.ut_line));
1543 utptr = getutline(&utmp);
1544 /* write it out only if it exists */
1546 utptr->ut_type = DEAD_PROCESS;
1547 utptr->ut_time = time(NULL);
1549 /* set wtmp entry if wtmp file exists */
1550 if ((fd = open(wtmpf, O_WRONLY | O_APPEND)) >= 0) {
1551 write(fd, utptr, sizeof(utmp));
1559 line[14] = line[13];
1560 line[13] = line[12];
1574 * This is the routine to call when we are all through, to
1575 * clean up anything that needs to be cleaned up.
1578 #ifdef PARENT_DOES_UTMP
1584 static int incleanup = 0;
1586 int child_status; /* status of child process as returned by waitpid */
1587 int flags = WNOHANG|WUNTRACED;
1590 * 1: Pick up the zombie, if we are being called
1591 * as the signal handler.
1592 * 2: If we are a nested cleanup(), return.
1593 * 3: Try to clean up TMPDIR.
1594 * 4: Fill in utmp with shutdown of process.
1595 * 5: Close down the network and pty connections.
1596 * 6: Finish up the TMPDIR cleanup, if needed.
1598 if (sig == SIGCHLD) {
1599 while (waitpid(-1, &child_status, flags) > 0)
1601 /* Check if the child process was stopped
1602 * rather than exited. We want cleanup only if
1603 * the child has died.
1605 if (WIFSTOPPED(child_status)) {
1609 t = sigblock(sigmask(SIGCHLD));
1617 t = cleantmp(&wtmp);
1618 setutent(); /* just to make sure */
1630 #else /* PARENT_DOES_UTMP */
1635 #if defined(HAVE_UTMPX_H) || !defined(HAVE_LOGWTMP)
1639 vhangup(); /* XXX */
1645 p = line + sizeof("/dev/") - 1;
1658 #endif /* PARENT_DOES_UTMP */
1660 #ifdef PARENT_DOES_UTMP
1665 * These three functions are used to coordinate the handling of
1666 * the utmp file between the server and the soon-to-be-login shell.
1667 * The server actually creates the utmp structure, the child calls
1668 * utmp_sig_wait(), until the server calls utmp_sig_notify() and
1669 * signals the future-login shell to proceed.
1671 static int caught=0; /* NZ when signal intercepted */
1672 static void (*func)(); /* address of previous handler */
1679 signal(SIGUSR1, func);
1686 * register signal handler for UTMP creation
1688 if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1)
1689 fatalperror(net, "telnetd/signal");
1695 signal(SIGUSR1, func); /* reset handler to default */
1699 # define sigoff() /* do nothing */
1700 # define sigon() /* do nothing */
1707 * Wait for parent to write our utmp entry.
1710 while (caught == 0) {
1711 pause(); /* wait until we get a signal (sigon) */
1712 sigoff(); /* turn off signals while we check caught */
1714 sigon(); /* turn on signals again */
1718 utmp_sig_notify(pid)
1724 static int gotsigjob = 0;
1734 while ((jid = waitjob(NULL)) != -1) {
1739 jobend(jid, NULL, NULL);
1745 * called by jobend() before calling cleantmp()
1746 * to find the correct $TMPDIR to cleanup.
1753 struct utmp *cur = NULL;
1755 setutent(); /* just to make sure */
1756 while (cur = getutent()) {
1757 if ( (cur->ut_type != NULL) && (jid == cur->ut_jid) ) {
1766 * Clean up the TMPDIR that login created.
1767 * The first time this is called we pick up the info
1768 * from the utmp. If the job has already gone away,
1769 * then we'll clean up and be done. If not, then
1770 * when this is called the second time it will wait
1771 * for the signal that the job is done.
1778 static int first = 1;
1779 int mask, omask, ret;
1780 extern struct utmp *getutid (const struct utmp *_Id);
1783 mask = sigmask(WJSIGNAL);
1786 omask = sigblock(mask);
1787 while (gotsigjob == 0)
1792 setutent(); /* just to make sure */
1796 syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR");
1800 * Nothing to clean up if the user shell was never started.
1802 if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0)
1806 * Block the WJSIGNAL while we are in jobend().
1808 omask = sigblock(mask);
1809 ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user);
1815 jobend(jid, path, user)
1820 static int saved_jid = 0;
1821 static int pty_saved_jid = 0;
1822 static char saved_path[sizeof(wtmp.ut_tpath)+1];
1823 static char saved_user[sizeof(wtmp.ut_user)+1];
1826 * this little piece of code comes into play
1827 * only when ptyreconnect is used to reconnect
1828 * to an previous session.
1830 * this is the only time when the
1831 * "saved_jid != jid" code is executed.
1834 if ( saved_jid && saved_jid != jid ) {
1835 if (!path) { /* called from signal handler */
1836 pty_saved_jid = jid;
1838 pty_saved_jid = saved_jid;
1843 strlcpy(saved_path, path, sizeof(saved_path));
1844 strlcpy(saved_user, user, sizeof(saved_user));
1846 if (saved_jid == 0) {
1851 /* if the jid has changed, get the correct entry from the utmp file */
1853 if ( saved_jid != jid ) {
1854 struct utmp *utp = NULL;
1855 struct utmp *jid_getutid();
1857 utp = jid_getutid(pty_saved_jid);
1860 syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR");
1864 cleantmpdir(jid, utp->ut_tpath, utp->ut_user);
1868 cleantmpdir(jid, saved_path, saved_user);
1873 * Fork a child process to clean up the TMPDIR
1875 cleantmpdir(jid, tpath, user)
1882 syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m\n",
1886 execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, NULL);
1887 syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m\n",
1888 tpath, CLEANTMPCMD);
1892 * Forget about child. We will exit, and
1893 * /etc/init will pick it up.
1899 #endif /* defined(PARENT_DOES_UTMP) */