184d9c625SLionel Sambuc /* $NetBSD: main.c,v 1.64 2013/08/12 13:54:33 joerg Exp $ */
2a06e2ab3SBen Gras
3a06e2ab3SBen Gras /*-
4a06e2ab3SBen Gras * Copyright (c) 1980, 1993
5a06e2ab3SBen Gras * The Regents of the University of California. All rights reserved.
6a06e2ab3SBen Gras *
7a06e2ab3SBen Gras * Redistribution and use in source and binary forms, with or without
8a06e2ab3SBen Gras * modification, are permitted provided that the following conditions
9a06e2ab3SBen Gras * are met:
10a06e2ab3SBen Gras * 1. Redistributions of source code must retain the above copyright
11a06e2ab3SBen Gras * notice, this list of conditions and the following disclaimer.
12a06e2ab3SBen Gras * 2. Redistributions in binary form must reproduce the above copyright
13a06e2ab3SBen Gras * notice, this list of conditions and the following disclaimer in the
14a06e2ab3SBen Gras * documentation and/or other materials provided with the distribution.
15a06e2ab3SBen Gras * 3. Neither the name of the University nor the names of its contributors
16a06e2ab3SBen Gras * may be used to endorse or promote products derived from this software
17a06e2ab3SBen Gras * without specific prior written permission.
18a06e2ab3SBen Gras *
19a06e2ab3SBen Gras * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20a06e2ab3SBen Gras * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21a06e2ab3SBen Gras * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22a06e2ab3SBen Gras * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23a06e2ab3SBen Gras * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24a06e2ab3SBen Gras * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25a06e2ab3SBen Gras * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26a06e2ab3SBen Gras * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27a06e2ab3SBen Gras * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28a06e2ab3SBen Gras * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29a06e2ab3SBen Gras * SUCH DAMAGE.
30a06e2ab3SBen Gras */
31a06e2ab3SBen Gras
32a06e2ab3SBen Gras #include <sys/cdefs.h>
33a06e2ab3SBen Gras
34a06e2ab3SBen Gras #ifndef lint
35a06e2ab3SBen Gras __COPYRIGHT("@(#) Copyright (c) 1980, 1993\
36a06e2ab3SBen Gras The Regents of the University of California. All rights reserved.");
37a06e2ab3SBen Gras #endif /* not lint */
38a06e2ab3SBen Gras
39a06e2ab3SBen Gras #ifndef lint
40a06e2ab3SBen Gras #if 0
41a06e2ab3SBen Gras static char sccsid[] = "from: @(#)main.c 8.1 (Berkeley) 6/20/93";
42a06e2ab3SBen Gras #else
4384d9c625SLionel Sambuc __RCSID("$NetBSD: main.c,v 1.64 2013/08/12 13:54:33 joerg Exp $");
44a06e2ab3SBen Gras #endif
45a06e2ab3SBen Gras #endif /* not lint */
46a06e2ab3SBen Gras
47a06e2ab3SBen Gras #include <sys/param.h>
48a06e2ab3SBen Gras #include <sys/ioctl.h>
49a06e2ab3SBen Gras #include <sys/resource.h>
50a06e2ab3SBen Gras #include <sys/utsname.h>
51a06e2ab3SBen Gras
52a06e2ab3SBen Gras #include <ctype.h>
53a06e2ab3SBen Gras #include <errno.h>
54a06e2ab3SBen Gras #include <fcntl.h>
55a06e2ab3SBen Gras #include <limits.h>
56a06e2ab3SBen Gras #include <pwd.h>
57a06e2ab3SBen Gras #include <setjmp.h>
58a06e2ab3SBen Gras #include <signal.h>
5984d9c625SLionel Sambuc #include <stdio.h>
60a06e2ab3SBen Gras #include <stdlib.h>
61a06e2ab3SBen Gras #include <string.h>
62a06e2ab3SBen Gras #include <syslog.h>
63a06e2ab3SBen Gras #include <term.h>
6484d9c625SLionel Sambuc #include <termios.h>
65a06e2ab3SBen Gras #include <time.h>
66a06e2ab3SBen Gras #include <ttyent.h>
67a06e2ab3SBen Gras #include <unistd.h>
68a06e2ab3SBen Gras #include <util.h>
69a06e2ab3SBen Gras
70a06e2ab3SBen Gras #include "gettytab.h"
71a06e2ab3SBen Gras #include "pathnames.h"
72a06e2ab3SBen Gras #include "extern.h"
73a06e2ab3SBen Gras
74a06e2ab3SBen Gras extern char editedhost[];
75a06e2ab3SBen Gras
76a06e2ab3SBen Gras /*
77a06e2ab3SBen Gras * Set the amount of running time that getty should accumulate
78a06e2ab3SBen Gras * before deciding that something is wrong and exit.
79a06e2ab3SBen Gras */
80a06e2ab3SBen Gras #define GETTY_TIMEOUT 60 /* seconds */
81a06e2ab3SBen Gras
82a06e2ab3SBen Gras /* defines for auto detection of incoming PPP calls (->PAP/CHAP) */
83a06e2ab3SBen Gras
84a06e2ab3SBen Gras #define PPP_FRAME 0x7e /* PPP Framing character */
85a06e2ab3SBen Gras #define PPP_STATION 0xff /* "All Station" character */
86a06e2ab3SBen Gras #define PPP_ESCAPE 0x7d /* Escape Character */
87a06e2ab3SBen Gras #define PPP_CONTROL 0x03 /* PPP Control Field */
88a06e2ab3SBen Gras #define PPP_CONTROL_ESCAPED 0x23 /* PPP Control Field, escaped */
89a06e2ab3SBen Gras #define PPP_LCP_HI 0xc0 /* LCP protocol - high byte */
90a06e2ab3SBen Gras #define PPP_LCP_LOW 0x21 /* LCP protocol - low byte */
91a06e2ab3SBen Gras
92a06e2ab3SBen Gras struct termios tmode, omode;
93a06e2ab3SBen Gras
94a06e2ab3SBen Gras int crmod, digit_or_punc, lower, upper;
95a06e2ab3SBen Gras
96a06e2ab3SBen Gras char hostname[MAXHOSTNAMELEN + 1];
97a06e2ab3SBen Gras struct utsname kerninfo;
98a06e2ab3SBen Gras char name[LOGIN_NAME_MAX];
99a06e2ab3SBen Gras char dev[] = _PATH_DEV;
100a06e2ab3SBen Gras char ttyn[32];
101a06e2ab3SBen Gras char lockfile[512];
102a06e2ab3SBen Gras uid_t ttyowner;
103a06e2ab3SBen Gras char *rawttyn;
104a06e2ab3SBen Gras
105a06e2ab3SBen Gras #define OBUFSIZ 128
106a06e2ab3SBen Gras #define TABBUFSIZ 512
107a06e2ab3SBen Gras
108a06e2ab3SBen Gras char defent[TABBUFSIZ];
109a06e2ab3SBen Gras char tabent[TABBUFSIZ];
110a06e2ab3SBen Gras
111a06e2ab3SBen Gras char *env[128];
112a06e2ab3SBen Gras
113a06e2ab3SBen Gras const unsigned char partab[] = {
114a06e2ab3SBen Gras 0001,0201,0201,0001,0201,0001,0001,0201,
115a06e2ab3SBen Gras 0202,0004,0003,0205,0005,0206,0201,0001,
116a06e2ab3SBen Gras 0201,0001,0001,0201,0001,0201,0201,0001,
117a06e2ab3SBen Gras 0001,0201,0201,0001,0201,0001,0001,0201,
118a06e2ab3SBen Gras 0200,0000,0000,0200,0000,0200,0200,0000,
119a06e2ab3SBen Gras 0000,0200,0200,0000,0200,0000,0000,0200,
120a06e2ab3SBen Gras 0000,0200,0200,0000,0200,0000,0000,0200,
121a06e2ab3SBen Gras 0200,0000,0000,0200,0000,0200,0200,0000,
122a06e2ab3SBen Gras 0200,0000,0000,0200,0000,0200,0200,0000,
123a06e2ab3SBen Gras 0000,0200,0200,0000,0200,0000,0000,0200,
124a06e2ab3SBen Gras 0000,0200,0200,0000,0200,0000,0000,0200,
125a06e2ab3SBen Gras 0200,0000,0000,0200,0000,0200,0200,0000,
126a06e2ab3SBen Gras 0000,0200,0200,0000,0200,0000,0000,0200,
127a06e2ab3SBen Gras 0200,0000,0000,0200,0000,0200,0200,0000,
128a06e2ab3SBen Gras 0200,0000,0000,0200,0000,0200,0200,0000,
129a06e2ab3SBen Gras 0000,0200,0200,0000,0200,0000,0000,0201
130a06e2ab3SBen Gras };
131a06e2ab3SBen Gras
132a06e2ab3SBen Gras #define ERASE tmode.c_cc[VERASE]
133a06e2ab3SBen Gras #define KILL tmode.c_cc[VKILL]
134a06e2ab3SBen Gras #define EOT tmode.c_cc[VEOF]
135a06e2ab3SBen Gras
136a06e2ab3SBen Gras static void clearscreen(void);
137a06e2ab3SBen Gras
13884d9c625SLionel Sambuc sigjmp_buf timeout;
139a06e2ab3SBen Gras
14084d9c625SLionel Sambuc __dead static void
141a06e2ab3SBen Gras /*ARGSUSED*/
dingdong(int signo)142a06e2ab3SBen Gras dingdong(int signo)
143a06e2ab3SBen Gras {
144a06e2ab3SBen Gras
145a06e2ab3SBen Gras (void)alarm(0);
146a06e2ab3SBen Gras (void)signal(SIGALRM, SIG_DFL);
14784d9c625SLionel Sambuc siglongjmp(timeout, 1);
148a06e2ab3SBen Gras }
149a06e2ab3SBen Gras
15084d9c625SLionel Sambuc sigjmp_buf intrupt;
151a06e2ab3SBen Gras
15284d9c625SLionel Sambuc __dead static void
153a06e2ab3SBen Gras /*ARGSUSED*/
interrupt(int signo)154a06e2ab3SBen Gras interrupt(int signo)
155a06e2ab3SBen Gras {
156a06e2ab3SBen Gras
157a06e2ab3SBen Gras (void)signal(SIGINT, interrupt);
15884d9c625SLionel Sambuc siglongjmp(intrupt, 1);
159a06e2ab3SBen Gras }
160a06e2ab3SBen Gras
16184d9c625SLionel Sambuc #if !defined(__minix)
162a06e2ab3SBen Gras /*
163a06e2ab3SBen Gras * Action to take when getty is running too long.
164a06e2ab3SBen Gras */
16584d9c625SLionel Sambuc __dead static void
166a06e2ab3SBen Gras /*ARGSUSED*/
timeoverrun(int signo)167a06e2ab3SBen Gras timeoverrun(int signo)
168a06e2ab3SBen Gras {
169a06e2ab3SBen Gras
170a06e2ab3SBen Gras syslog(LOG_ERR, "getty exiting due to excessive running time");
171a06e2ab3SBen Gras exit(1);
172a06e2ab3SBen Gras }
17384d9c625SLionel Sambuc #endif /* !defined(__minix) */
174a06e2ab3SBen Gras
175a06e2ab3SBen Gras static int getname(void);
176a06e2ab3SBen Gras static void oflush(void);
177a06e2ab3SBen Gras static void prompt(void);
178a06e2ab3SBen Gras static int putchr(int);
179a06e2ab3SBen Gras static void putf(const char *);
180a06e2ab3SBen Gras static void xputs(const char *);
181a06e2ab3SBen Gras
182a06e2ab3SBen Gras #define putpad(s) tputs(s, 1, putchr)
183a06e2ab3SBen Gras
184a06e2ab3SBen Gras int
main(int argc,char * argv[],char * envp[])185a06e2ab3SBen Gras main(int argc, char *argv[], char *envp[])
186a06e2ab3SBen Gras {
187a06e2ab3SBen Gras const char *progname;
18884d9c625SLionel Sambuc int repcnt = 0, failopenlogged = 0, first_time = 1;
189a06e2ab3SBen Gras struct rlimit limit;
190a06e2ab3SBen Gras struct passwd *pw;
191a06e2ab3SBen Gras int rval;
19284d9c625SLionel Sambuc /* this is used past the siglongjmp, so make sure it is not cached
19384d9c625SLionel Sambuc in registers that might become invalid. */
19484d9c625SLionel Sambuc volatile int uugetty = 0;
19584d9c625SLionel Sambuc const char * volatile tname = "default";
196a06e2ab3SBen Gras
197a06e2ab3SBen Gras (void)signal(SIGINT, SIG_IGN);
198a06e2ab3SBen Gras openlog("getty", LOG_PID, LOG_AUTH);
199a06e2ab3SBen Gras (void)gethostname(hostname, sizeof(hostname));
200a06e2ab3SBen Gras hostname[sizeof(hostname) - 1] = '\0';
201a06e2ab3SBen Gras if (hostname[0] == '\0')
202a06e2ab3SBen Gras (void)strlcpy(hostname, "Amnesiac", sizeof(hostname));
203a06e2ab3SBen Gras (void)uname(&kerninfo);
204a06e2ab3SBen Gras
205a06e2ab3SBen Gras progname = getprogname();
206a06e2ab3SBen Gras if (progname[0] == 'u' && progname[1] == 'u')
207a06e2ab3SBen Gras uugetty = 1;
208a06e2ab3SBen Gras
209a06e2ab3SBen Gras /*
210a06e2ab3SBen Gras * Find id of uucp login (if present) so we can chown tty properly.
211a06e2ab3SBen Gras */
212a06e2ab3SBen Gras if (uugetty && (pw = getpwnam("uucp")))
213a06e2ab3SBen Gras ttyowner = pw->pw_uid;
214a06e2ab3SBen Gras else
215a06e2ab3SBen Gras ttyowner = 0;
216a06e2ab3SBen Gras
217a06e2ab3SBen Gras /*
218a06e2ab3SBen Gras * Limit running time to deal with broken or dead lines.
219a06e2ab3SBen Gras */
22084d9c625SLionel Sambuc #if !defined(__minix)
221a06e2ab3SBen Gras (void)signal(SIGXCPU, timeoverrun);
222ac5b3e53SLionel Sambuc #endif /* !defined(__minix) */
223a06e2ab3SBen Gras limit.rlim_max = RLIM_INFINITY;
224a06e2ab3SBen Gras limit.rlim_cur = GETTY_TIMEOUT;
225a06e2ab3SBen Gras (void)setrlimit(RLIMIT_CPU, &limit);
226a06e2ab3SBen Gras
227a06e2ab3SBen Gras /*
228a06e2ab3SBen Gras * The following is a work around for vhangup interactions
229a06e2ab3SBen Gras * which cause great problems getting window systems started.
230a06e2ab3SBen Gras * If the tty line is "-", we do the old style getty presuming
231a06e2ab3SBen Gras * that the file descriptors are already set up for us.
232a06e2ab3SBen Gras * J. Gettys - MIT Project Athena.
233a06e2ab3SBen Gras */
234a06e2ab3SBen Gras if (argc <= 2 || strcmp(argv[2], "-") == 0) {
235a06e2ab3SBen Gras (void)strlcpy(ttyn, ttyname(0), sizeof(ttyn));
236a06e2ab3SBen Gras }
237a06e2ab3SBen Gras else {
238a06e2ab3SBen Gras int i;
239a06e2ab3SBen Gras
240a06e2ab3SBen Gras rawttyn = argv[2];
241a06e2ab3SBen Gras (void)strlcpy(ttyn, dev, sizeof(ttyn));
242a06e2ab3SBen Gras (void)strlcat(ttyn, argv[2], sizeof(ttyn));
243a06e2ab3SBen Gras if (uugetty) {
244a06e2ab3SBen Gras (void)chown(ttyn, ttyowner, 0);
245a06e2ab3SBen Gras (void)strlcpy(lockfile, _PATH_LOCK,
246a06e2ab3SBen Gras sizeof(lockfile));
247a06e2ab3SBen Gras (void)strlcat(lockfile, argv[2],
248a06e2ab3SBen Gras sizeof(lockfile));
249a06e2ab3SBen Gras /*
250a06e2ab3SBen Gras * wait for lockfiles to go away before we try
251a06e2ab3SBen Gras * to open
252a06e2ab3SBen Gras */
253a06e2ab3SBen Gras if (pidlock(lockfile, 0, 0, 0) != 0) {
254a06e2ab3SBen Gras syslog(LOG_ERR,
255a06e2ab3SBen Gras "%s: can't create lockfile", ttyn);
256a06e2ab3SBen Gras exit(1);
257a06e2ab3SBen Gras }
258a06e2ab3SBen Gras (void)unlink(lockfile);
259a06e2ab3SBen Gras }
260a06e2ab3SBen Gras if (strcmp(argv[0], "+") != 0) {
261a06e2ab3SBen Gras (void)chown(ttyn, ttyowner, 0);
262a06e2ab3SBen Gras (void)chmod(ttyn, 0600);
26384d9c625SLionel Sambuc #if !defined(__minix)
264a06e2ab3SBen Gras (void)revoke(ttyn);
26584d9c625SLionel Sambuc #endif /* !defined(__minix) */
266a06e2ab3SBen Gras if (ttyaction(ttyn, "getty", "root"))
267a06e2ab3SBen Gras syslog(LOG_WARNING, "%s: ttyaction failed",
268a06e2ab3SBen Gras ttyn);
269a06e2ab3SBen Gras /*
270a06e2ab3SBen Gras * Delay the open so DTR stays down long enough
271a06e2ab3SBen Gras * to be detected.
272a06e2ab3SBen Gras */
273a06e2ab3SBen Gras (void)sleep(2);
274a06e2ab3SBen Gras while ((i = open(ttyn, O_RDWR)) == -1) {
275a06e2ab3SBen Gras if ((repcnt % 10 == 0) &&
276a06e2ab3SBen Gras (errno != ENXIO || !failopenlogged)) {
277a06e2ab3SBen Gras syslog(LOG_WARNING, "%s: %m", ttyn);
278a06e2ab3SBen Gras closelog();
279a06e2ab3SBen Gras failopenlogged = 1;
280a06e2ab3SBen Gras }
281a06e2ab3SBen Gras repcnt++;
282a06e2ab3SBen Gras (void)sleep(60);
283a06e2ab3SBen Gras }
284a06e2ab3SBen Gras if (uugetty && pidlock(lockfile, 0, 0, 0) != 0) {
285a06e2ab3SBen Gras syslog(LOG_ERR, "%s: can't create lockfile",
286a06e2ab3SBen Gras ttyn);
287a06e2ab3SBen Gras exit(1);
288a06e2ab3SBen Gras }
289a06e2ab3SBen Gras if (uugetty)
290a06e2ab3SBen Gras (void)chown(lockfile, ttyowner, 0);
291a06e2ab3SBen Gras (void)login_tty(i);
292a06e2ab3SBen Gras }
293a06e2ab3SBen Gras }
294a06e2ab3SBen Gras
295a06e2ab3SBen Gras /* Start with default tty settings */
296a06e2ab3SBen Gras if (tcgetattr(0, &tmode) < 0) {
297a06e2ab3SBen Gras syslog(LOG_ERR, "%s: %m", ttyn);
298a06e2ab3SBen Gras exit(1);
299a06e2ab3SBen Gras }
300a06e2ab3SBen Gras omode = tmode;
301a06e2ab3SBen Gras
302a06e2ab3SBen Gras gettable("default", defent);
303a06e2ab3SBen Gras gendefaults();
304a06e2ab3SBen Gras if (argc > 1)
305a06e2ab3SBen Gras tname = argv[1];
306a06e2ab3SBen Gras for (;;) {
307*0a6a1f1dSLionel Sambuc #if !defined(__minix)
308a06e2ab3SBen Gras int off;
309*0a6a1f1dSLionel Sambuc #endif /* !defined(__minix) */
310a06e2ab3SBen Gras
311a06e2ab3SBen Gras rval = 0;
312a06e2ab3SBen Gras gettable(tname, tabent);
313a06e2ab3SBen Gras if (OPset || EPset || APset)
314a06e2ab3SBen Gras APset++, OPset++, EPset++;
315a06e2ab3SBen Gras setdefaults();
316*0a6a1f1dSLionel Sambuc #if !defined(__minix)
317a06e2ab3SBen Gras off = 0;
318*0a6a1f1dSLionel Sambuc #endif /* !defined(__minix) */
319a06e2ab3SBen Gras (void)tcflush(0, TCIOFLUSH); /* clear out the crap */
320*0a6a1f1dSLionel Sambuc #if !defined(__minix)
321a06e2ab3SBen Gras (void)ioctl(0, FIONBIO, &off); /* turn off non-blocking mode */
322a06e2ab3SBen Gras (void)ioctl(0, FIOASYNC, &off); /* ditto for async mode */
32384d9c625SLionel Sambuc #endif /* !defined(__minix) */
324a06e2ab3SBen Gras
325a06e2ab3SBen Gras if (IS)
326a06e2ab3SBen Gras (void)cfsetispeed(&tmode, (speed_t)IS);
327a06e2ab3SBen Gras else if (SP)
328a06e2ab3SBen Gras (void)cfsetispeed(&tmode, (speed_t)SP);
329a06e2ab3SBen Gras if (OS)
330a06e2ab3SBen Gras (void)cfsetospeed(&tmode, (speed_t)OS);
331a06e2ab3SBen Gras else if (SP)
332a06e2ab3SBen Gras (void)cfsetospeed(&tmode, (speed_t)SP);
333a06e2ab3SBen Gras setflags(0);
334a06e2ab3SBen Gras setchars();
335a06e2ab3SBen Gras if (tcsetattr(0, TCSANOW, &tmode) < 0) {
336a06e2ab3SBen Gras syslog(LOG_ERR, "%s: %m", ttyn);
337a06e2ab3SBen Gras exit(1);
338a06e2ab3SBen Gras }
339a06e2ab3SBen Gras if (AB) {
340a06e2ab3SBen Gras tname = autobaud();
341a06e2ab3SBen Gras continue;
342a06e2ab3SBen Gras }
343a06e2ab3SBen Gras if (PS) {
344a06e2ab3SBen Gras tname = portselector();
345a06e2ab3SBen Gras continue;
346a06e2ab3SBen Gras }
347a06e2ab3SBen Gras if (CS)
348a06e2ab3SBen Gras clearscreen();
349a06e2ab3SBen Gras if (CL && *CL)
350a06e2ab3SBen Gras putpad(CL);
351a06e2ab3SBen Gras edithost(HE);
352a06e2ab3SBen Gras
353a06e2ab3SBen Gras /*
354a06e2ab3SBen Gras * If this is the first time through this, and an
355a06e2ab3SBen Gras * issue file has been given, then send it.
356a06e2ab3SBen Gras */
357a06e2ab3SBen Gras if (first_time != 0 && IF != NULL) {
358a06e2ab3SBen Gras char buf[_POSIX2_LINE_MAX];
359a06e2ab3SBen Gras FILE *fp;
360a06e2ab3SBen Gras
361a06e2ab3SBen Gras if ((fp = fopen(IF, "r")) != NULL) {
362a06e2ab3SBen Gras while (fgets(buf, sizeof(buf) - 1, fp) != NULL)
363a06e2ab3SBen Gras putf(buf);
364a06e2ab3SBen Gras (void)fclose(fp);
365a06e2ab3SBen Gras }
366a06e2ab3SBen Gras }
367a06e2ab3SBen Gras first_time = 0;
368a06e2ab3SBen Gras
369a06e2ab3SBen Gras if (IM && *IM)
370a06e2ab3SBen Gras putf(IM);
371a06e2ab3SBen Gras oflush();
37284d9c625SLionel Sambuc if (sigsetjmp(timeout, 1)) {
373a06e2ab3SBen Gras tmode.c_ispeed = tmode.c_ospeed = 0;
374a06e2ab3SBen Gras (void)tcsetattr(0, TCSANOW, &tmode);
375a06e2ab3SBen Gras exit(1);
376a06e2ab3SBen Gras }
377a06e2ab3SBen Gras if (TO) {
378a06e2ab3SBen Gras (void)signal(SIGALRM, dingdong);
379a06e2ab3SBen Gras (void)alarm((unsigned int)TO);
380a06e2ab3SBen Gras }
381a06e2ab3SBen Gras if (NN) {
382a06e2ab3SBen Gras name[0] = '\0';
383a06e2ab3SBen Gras lower = 1;
384a06e2ab3SBen Gras upper = digit_or_punc = 0;
385a06e2ab3SBen Gras } else if (AL) {
386a06e2ab3SBen Gras const char *p = AL;
387a06e2ab3SBen Gras char *q = name;
388a06e2ab3SBen Gras
389a06e2ab3SBen Gras while (*p && q < &name[sizeof name - 1]) {
390a06e2ab3SBen Gras if (isupper((unsigned char)*p))
391a06e2ab3SBen Gras upper = 1;
392a06e2ab3SBen Gras else if (islower((unsigned char)*p))
393a06e2ab3SBen Gras lower = 1;
394a06e2ab3SBen Gras else if (isdigit((unsigned char)*p))
395a06e2ab3SBen Gras digit_or_punc = 1;
396a06e2ab3SBen Gras *q++ = *p++;
397a06e2ab3SBen Gras }
398a06e2ab3SBen Gras } else if ((rval = getname()) == 2) {
399a06e2ab3SBen Gras setflags(2);
400a06e2ab3SBen Gras (void)execle(PP, "ppplogin", ttyn, (char *) 0, env);
401a06e2ab3SBen Gras syslog(LOG_ERR, "%s: %m", PP);
402a06e2ab3SBen Gras exit(1);
403a06e2ab3SBen Gras }
404a06e2ab3SBen Gras
405a06e2ab3SBen Gras if (rval || AL || NN) {
406a06e2ab3SBen Gras int i;
407a06e2ab3SBen Gras
408a06e2ab3SBen Gras oflush();
409a06e2ab3SBen Gras (void)alarm(0);
410a06e2ab3SBen Gras (void)signal(SIGALRM, SIG_DFL);
411a06e2ab3SBen Gras if (name[0] == '-') {
412a06e2ab3SBen Gras xputs("user names may not start with '-'.");
413a06e2ab3SBen Gras continue;
414a06e2ab3SBen Gras }
415a06e2ab3SBen Gras if (!(upper || lower || digit_or_punc))
416a06e2ab3SBen Gras continue;
417a06e2ab3SBen Gras setflags(2);
418a06e2ab3SBen Gras if (crmod) {
419a06e2ab3SBen Gras tmode.c_iflag |= ICRNL;
420a06e2ab3SBen Gras tmode.c_oflag |= ONLCR;
421a06e2ab3SBen Gras }
422a06e2ab3SBen Gras #if XXX
423a06e2ab3SBen Gras if (upper || UC)
424a06e2ab3SBen Gras tmode.sg_flags |= LCASE;
425a06e2ab3SBen Gras if (lower || LC)
426a06e2ab3SBen Gras tmode.sg_flags &= ~LCASE;
427a06e2ab3SBen Gras #endif
428a06e2ab3SBen Gras if (tcsetattr(0, TCSANOW, &tmode) < 0) {
429a06e2ab3SBen Gras syslog(LOG_ERR, "%s: %m", ttyn);
430a06e2ab3SBen Gras exit(1);
431a06e2ab3SBen Gras }
432a06e2ab3SBen Gras (void)signal(SIGINT, SIG_DFL);
433a06e2ab3SBen Gras for (i = 0; envp[i] != NULL; i++)
434a06e2ab3SBen Gras env[i] = envp[i];
435a06e2ab3SBen Gras makeenv(&env[i]);
436a06e2ab3SBen Gras
437a06e2ab3SBen Gras limit.rlim_max = RLIM_INFINITY;
438a06e2ab3SBen Gras limit.rlim_cur = RLIM_INFINITY;
439a06e2ab3SBen Gras (void)setrlimit(RLIMIT_CPU, &limit);
440a06e2ab3SBen Gras if (NN)
441a06e2ab3SBen Gras (void)execle(LO, "login", AL ? "-fp" : "-p",
442a06e2ab3SBen Gras NULL, env);
443a06e2ab3SBen Gras else
444a06e2ab3SBen Gras (void)execle(LO, "login", AL ? "-fp" : "-p",
445a06e2ab3SBen Gras "--", name, NULL, env);
446a06e2ab3SBen Gras syslog(LOG_ERR, "%s: %m", LO);
447a06e2ab3SBen Gras exit(1);
448a06e2ab3SBen Gras }
449a06e2ab3SBen Gras (void)alarm(0);
450a06e2ab3SBen Gras (void)signal(SIGALRM, SIG_DFL);
451a06e2ab3SBen Gras (void)signal(SIGINT, SIG_IGN);
452a06e2ab3SBen Gras if (NX && *NX)
453a06e2ab3SBen Gras tname = NX;
454a06e2ab3SBen Gras if (uugetty)
455a06e2ab3SBen Gras (void)unlink(lockfile);
456a06e2ab3SBen Gras }
457a06e2ab3SBen Gras }
458a06e2ab3SBen Gras
459a06e2ab3SBen Gras static int
getname(void)460a06e2ab3SBen Gras getname(void)
461a06e2ab3SBen Gras {
462a06e2ab3SBen Gras int c;
463a06e2ab3SBen Gras char *np;
464a06e2ab3SBen Gras unsigned char cs;
465a06e2ab3SBen Gras int ppp_state, ppp_connection;
466a06e2ab3SBen Gras
467a06e2ab3SBen Gras /*
468a06e2ab3SBen Gras * Interrupt may happen if we use CBREAK mode
469a06e2ab3SBen Gras */
47084d9c625SLionel Sambuc if (sigsetjmp(intrupt, 1)) {
471a06e2ab3SBen Gras (void)signal(SIGINT, SIG_IGN);
472a06e2ab3SBen Gras return (0);
473a06e2ab3SBen Gras }
474a06e2ab3SBen Gras (void)signal(SIGINT, interrupt);
475a06e2ab3SBen Gras setflags(1);
476a06e2ab3SBen Gras prompt();
477a06e2ab3SBen Gras if (PF > 0) {
478a06e2ab3SBen Gras oflush();
479a06e2ab3SBen Gras (void)sleep((unsigned int)PF);
480a06e2ab3SBen Gras PF = 0;
481a06e2ab3SBen Gras }
482a06e2ab3SBen Gras if (tcsetattr(0, TCSANOW, &tmode) < 0) {
483a06e2ab3SBen Gras syslog(LOG_ERR, "%s: %m", ttyn);
484a06e2ab3SBen Gras exit(1);
485a06e2ab3SBen Gras }
486a06e2ab3SBen Gras crmod = digit_or_punc = lower = upper = 0;
487a06e2ab3SBen Gras ppp_state = ppp_connection = 0;
488a06e2ab3SBen Gras np = name;
489a06e2ab3SBen Gras for (;;) {
490a06e2ab3SBen Gras oflush();
491a06e2ab3SBen Gras if (read(STDIN_FILENO, &cs, 1) <= 0)
492a06e2ab3SBen Gras exit(0);
493a06e2ab3SBen Gras if ((c = cs&0177) == 0)
494a06e2ab3SBen Gras return (0);
495a06e2ab3SBen Gras
496a06e2ab3SBen Gras /*
497a06e2ab3SBen Gras * PPP detection state machine..
498a06e2ab3SBen Gras * Look for sequences:
499a06e2ab3SBen Gras * PPP_FRAME, PPP_STATION, PPP_ESCAPE, PPP_CONTROL_ESCAPED or
500a06e2ab3SBen Gras * PPP_FRAME, PPP_STATION, PPP_CONTROL (deviant from RFC)
501a06e2ab3SBen Gras * See RFC1662.
502a06e2ab3SBen Gras * Derived from code from Michael Hancock <michaelh@cet.co.jp>
503a06e2ab3SBen Gras * and Erik 'PPP' Olson <eriko@wrq.com>
504a06e2ab3SBen Gras */
505a06e2ab3SBen Gras if (PP && cs == PPP_FRAME) {
506a06e2ab3SBen Gras ppp_state = 1;
507a06e2ab3SBen Gras } else if (ppp_state == 1 && cs == PPP_STATION) {
508a06e2ab3SBen Gras ppp_state = 2;
509a06e2ab3SBen Gras } else if (ppp_state == 2 && cs == PPP_ESCAPE) {
510a06e2ab3SBen Gras ppp_state = 3;
511a06e2ab3SBen Gras } else if ((ppp_state == 2 && cs == PPP_CONTROL) ||
512a06e2ab3SBen Gras (ppp_state == 3 && cs == PPP_CONTROL_ESCAPED)) {
513a06e2ab3SBen Gras ppp_state = 4;
514a06e2ab3SBen Gras } else if (ppp_state == 4 && cs == PPP_LCP_HI) {
515a06e2ab3SBen Gras ppp_state = 5;
516a06e2ab3SBen Gras } else if (ppp_state == 5 && cs == PPP_LCP_LOW) {
517a06e2ab3SBen Gras ppp_connection = 1;
518a06e2ab3SBen Gras break;
519a06e2ab3SBen Gras } else {
520a06e2ab3SBen Gras ppp_state = 0;
521a06e2ab3SBen Gras }
522a06e2ab3SBen Gras
523a06e2ab3SBen Gras if (c == EOT)
524a06e2ab3SBen Gras exit(1);
525a06e2ab3SBen Gras if (c == '\r' || c == '\n' ||
526a06e2ab3SBen Gras np >= &name[LOGIN_NAME_MAX - 1]) {
527a06e2ab3SBen Gras *np = '\0';
528a06e2ab3SBen Gras putf("\r\n");
529a06e2ab3SBen Gras break;
530a06e2ab3SBen Gras }
531a06e2ab3SBen Gras if (islower(c))
532a06e2ab3SBen Gras lower = 1;
533a06e2ab3SBen Gras else if (isupper(c))
534a06e2ab3SBen Gras upper = 1;
535a06e2ab3SBen Gras else if (c == ERASE || c == '#' || c == '\b') {
536a06e2ab3SBen Gras if (np > name) {
537a06e2ab3SBen Gras np--;
538a06e2ab3SBen Gras if (cfgetospeed(&tmode) >= 1200)
539a06e2ab3SBen Gras xputs("\b \b");
540a06e2ab3SBen Gras else
541a06e2ab3SBen Gras putchr(cs);
542a06e2ab3SBen Gras }
543a06e2ab3SBen Gras continue;
544a06e2ab3SBen Gras } else if (c == KILL || c == '@') {
545a06e2ab3SBen Gras putchr(cs);
546a06e2ab3SBen Gras putchr('\r');
547a06e2ab3SBen Gras if (cfgetospeed(&tmode) < 1200)
548a06e2ab3SBen Gras putchr('\n');
549a06e2ab3SBen Gras /* this is the way they do it down under ... */
550a06e2ab3SBen Gras else if (np > name)
551a06e2ab3SBen Gras xputs(
552a06e2ab3SBen Gras " \r");
553a06e2ab3SBen Gras prompt();
554a06e2ab3SBen Gras np = name;
555a06e2ab3SBen Gras continue;
556a06e2ab3SBen Gras } else if (isdigit(c) || c == '_')
557a06e2ab3SBen Gras digit_or_punc = 1;
558a06e2ab3SBen Gras if (IG && (c <= ' ' || c > 0176))
559a06e2ab3SBen Gras continue;
560a06e2ab3SBen Gras *np++ = c;
561a06e2ab3SBen Gras putchr(cs);
562a06e2ab3SBen Gras
563a06e2ab3SBen Gras /*
564a06e2ab3SBen Gras * An MS-Windows direct connect PPP "client" won't send its
565a06e2ab3SBen Gras * first PPP packet until we respond to its "CLIENT" poll
566a06e2ab3SBen Gras * with a CRLF sequence. We cater to yet another broken
567a06e2ab3SBen Gras * implementation of a previously-standard protocol...
568a06e2ab3SBen Gras */
569a06e2ab3SBen Gras *np = '\0';
570a06e2ab3SBen Gras if (strstr(name, "CLIENT"))
571a06e2ab3SBen Gras putf("\r\n");
572a06e2ab3SBen Gras }
573a06e2ab3SBen Gras (void)signal(SIGINT, SIG_IGN);
574a06e2ab3SBen Gras *np = 0;
575a06e2ab3SBen Gras if (c == '\r')
576a06e2ab3SBen Gras crmod = 1;
577a06e2ab3SBen Gras if ((upper && !lower && !LC) || UC)
578a06e2ab3SBen Gras for (np = name; *np; np++)
579a06e2ab3SBen Gras *np = tolower((unsigned char)*np);
580a06e2ab3SBen Gras return (1 + ppp_connection);
581a06e2ab3SBen Gras }
582a06e2ab3SBen Gras
583a06e2ab3SBen Gras static void
xputs(const char * s)584a06e2ab3SBen Gras xputs(const char *s)
585a06e2ab3SBen Gras {
586a06e2ab3SBen Gras while (*s)
587a06e2ab3SBen Gras putchr(*s++);
588a06e2ab3SBen Gras }
589a06e2ab3SBen Gras
590a06e2ab3SBen Gras char outbuf[OBUFSIZ];
591a06e2ab3SBen Gras size_t obufcnt = 0;
592a06e2ab3SBen Gras
593a06e2ab3SBen Gras static int
putchr(int cc)594a06e2ab3SBen Gras putchr(int cc)
595a06e2ab3SBen Gras {
596a06e2ab3SBen Gras unsigned char c;
597a06e2ab3SBen Gras
598a06e2ab3SBen Gras c = cc;
599a06e2ab3SBen Gras if (!NP) {
600a06e2ab3SBen Gras c |= partab[c&0177] & 0200;
601a06e2ab3SBen Gras if (OP)
602a06e2ab3SBen Gras c ^= 0200;
603a06e2ab3SBen Gras }
604a06e2ab3SBen Gras if (!UB) {
605a06e2ab3SBen Gras outbuf[obufcnt++] = c;
606a06e2ab3SBen Gras if (obufcnt >= OBUFSIZ)
607a06e2ab3SBen Gras oflush();
608a06e2ab3SBen Gras return 1;
609a06e2ab3SBen Gras }
610a06e2ab3SBen Gras return write(STDOUT_FILENO, &c, 1);
611a06e2ab3SBen Gras }
612a06e2ab3SBen Gras
613a06e2ab3SBen Gras static void
oflush(void)614a06e2ab3SBen Gras oflush(void)
615a06e2ab3SBen Gras {
616a06e2ab3SBen Gras if (obufcnt)
617a06e2ab3SBen Gras (void)write(STDOUT_FILENO, outbuf, obufcnt);
618a06e2ab3SBen Gras obufcnt = 0;
619a06e2ab3SBen Gras }
620a06e2ab3SBen Gras
621a06e2ab3SBen Gras static void
prompt(void)622a06e2ab3SBen Gras prompt(void)
623a06e2ab3SBen Gras {
624a06e2ab3SBen Gras
625a06e2ab3SBen Gras putf(LM);
626a06e2ab3SBen Gras if (CO)
627a06e2ab3SBen Gras putchr('\n');
628a06e2ab3SBen Gras }
629a06e2ab3SBen Gras
630a06e2ab3SBen Gras static void
putf(const char * cp)631a06e2ab3SBen Gras putf(const char *cp)
632a06e2ab3SBen Gras {
633a06e2ab3SBen Gras time_t t;
634a06e2ab3SBen Gras char *slash, db[100];
635a06e2ab3SBen Gras
636a06e2ab3SBen Gras while (*cp) {
637a06e2ab3SBen Gras if (*cp != '%') {
638a06e2ab3SBen Gras putchr(*cp++);
639a06e2ab3SBen Gras continue;
640a06e2ab3SBen Gras }
641a06e2ab3SBen Gras switch (*++cp) {
642a06e2ab3SBen Gras
643a06e2ab3SBen Gras case 't':
644a06e2ab3SBen Gras if ((slash = strstr(ttyn, "/pts/")) == NULL)
645a06e2ab3SBen Gras slash = strrchr(ttyn, '/');
646a06e2ab3SBen Gras if (slash == NULL)
647a06e2ab3SBen Gras xputs(ttyn);
648a06e2ab3SBen Gras else
649a06e2ab3SBen Gras xputs(&slash[1]);
650a06e2ab3SBen Gras break;
651a06e2ab3SBen Gras
652a06e2ab3SBen Gras case 'h':
653a06e2ab3SBen Gras xputs(editedhost);
654a06e2ab3SBen Gras break;
655a06e2ab3SBen Gras
656a06e2ab3SBen Gras case 'd':
657a06e2ab3SBen Gras (void)time(&t);
658a06e2ab3SBen Gras (void)strftime(db, sizeof(db),
659a06e2ab3SBen Gras "%l:%M%p on %A, %d %B %Y", localtime(&t));
660a06e2ab3SBen Gras xputs(db);
661a06e2ab3SBen Gras break;
662a06e2ab3SBen Gras
663a06e2ab3SBen Gras case 's':
664a06e2ab3SBen Gras xputs(kerninfo.sysname);
665a06e2ab3SBen Gras break;
666a06e2ab3SBen Gras
667a06e2ab3SBen Gras case 'm':
668a06e2ab3SBen Gras xputs(kerninfo.machine);
669a06e2ab3SBen Gras break;
670a06e2ab3SBen Gras
671a06e2ab3SBen Gras case 'r':
672a06e2ab3SBen Gras xputs(kerninfo.release);
673a06e2ab3SBen Gras break;
674a06e2ab3SBen Gras
675a06e2ab3SBen Gras case 'v':
676a06e2ab3SBen Gras xputs(kerninfo.version);
677a06e2ab3SBen Gras break;
678a06e2ab3SBen Gras
679a06e2ab3SBen Gras case '%':
680a06e2ab3SBen Gras putchr('%');
681a06e2ab3SBen Gras break;
682a06e2ab3SBen Gras }
683a06e2ab3SBen Gras if (*cp)
684a06e2ab3SBen Gras cp++;
685a06e2ab3SBen Gras }
686a06e2ab3SBen Gras }
687a06e2ab3SBen Gras
688a06e2ab3SBen Gras static void
clearscreen(void)689a06e2ab3SBen Gras clearscreen(void)
690a06e2ab3SBen Gras {
691a06e2ab3SBen Gras struct ttyent *typ;
692a06e2ab3SBen Gras int err;
693a06e2ab3SBen Gras
694a06e2ab3SBen Gras if (rawttyn == NULL)
695a06e2ab3SBen Gras return;
696a06e2ab3SBen Gras
697a06e2ab3SBen Gras typ = getttynam(rawttyn);
698a06e2ab3SBen Gras
699a06e2ab3SBen Gras if ((typ == NULL) || (typ->ty_type == NULL) ||
700a06e2ab3SBen Gras (typ->ty_type[0] == 0))
701a06e2ab3SBen Gras return;
702a06e2ab3SBen Gras
703a06e2ab3SBen Gras if (setupterm(typ->ty_type, 0, &err) == ERR)
704a06e2ab3SBen Gras return;
705a06e2ab3SBen Gras
706a06e2ab3SBen Gras if (clear_screen)
707a06e2ab3SBen Gras putpad(clear_screen);
708a06e2ab3SBen Gras
709a06e2ab3SBen Gras del_curterm(cur_term);
710a06e2ab3SBen Gras cur_term = NULL;
711a06e2ab3SBen Gras }
712