708 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			708 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*	$NetBSD: main.c,v 1.64 2013/08/12 13:54:33 joerg Exp $	*/
 | 
						|
 | 
						|
/*-
 | 
						|
 * Copyright (c) 1980, 1993
 | 
						|
 *	The Regents of the University of California.  All rights reserved.
 | 
						|
 *
 | 
						|
 * 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. 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.
 | 
						|
 */
 | 
						|
 | 
						|
#include <sys/cdefs.h>
 | 
						|
 | 
						|
#ifndef lint
 | 
						|
__COPYRIGHT("@(#) Copyright (c) 1980, 1993\
 | 
						|
 The Regents of the University of California.  All rights reserved.");
 | 
						|
#endif /* not lint */
 | 
						|
 | 
						|
#ifndef lint
 | 
						|
#if 0
 | 
						|
static char sccsid[] = "from: @(#)main.c	8.1 (Berkeley) 6/20/93";
 | 
						|
#else
 | 
						|
__RCSID("$NetBSD: main.c,v 1.64 2013/08/12 13:54:33 joerg Exp $");
 | 
						|
#endif
 | 
						|
#endif /* not lint */
 | 
						|
 | 
						|
#include <sys/param.h>
 | 
						|
#include <sys/ioctl.h>
 | 
						|
#include <sys/resource.h>
 | 
						|
#include <sys/utsname.h>
 | 
						|
 | 
						|
#include <ctype.h>
 | 
						|
#include <errno.h>
 | 
						|
#include <fcntl.h>
 | 
						|
#include <limits.h>
 | 
						|
#include <pwd.h>
 | 
						|
#include <setjmp.h>
 | 
						|
#include <signal.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <string.h>
 | 
						|
#include <syslog.h>
 | 
						|
#include <term.h>
 | 
						|
#include <termios.h>
 | 
						|
#include <time.h>
 | 
						|
#include <ttyent.h>
 | 
						|
#include <unistd.h>
 | 
						|
#include <util.h>
 | 
						|
 | 
						|
#include "gettytab.h"
 | 
						|
#include "pathnames.h"
 | 
						|
#include "extern.h"
 | 
						|
 | 
						|
extern char editedhost[];
 | 
						|
 | 
						|
/*
 | 
						|
 * Set the amount of running time that getty should accumulate
 | 
						|
 * before deciding that something is wrong and exit.
 | 
						|
 */
 | 
						|
#define GETTY_TIMEOUT	60 /* seconds */
 | 
						|
 | 
						|
/* defines for auto detection of incoming PPP calls (->PAP/CHAP) */
 | 
						|
 | 
						|
#define PPP_FRAME           0x7e  /* PPP Framing character */
 | 
						|
#define PPP_STATION         0xff  /* "All Station" character */
 | 
						|
#define PPP_ESCAPE          0x7d  /* Escape Character */
 | 
						|
#define PPP_CONTROL         0x03  /* PPP Control Field */
 | 
						|
#define PPP_CONTROL_ESCAPED 0x23  /* PPP Control Field, escaped */
 | 
						|
#define PPP_LCP_HI          0xc0  /* LCP protocol - high byte */
 | 
						|
#define PPP_LCP_LOW         0x21  /* LCP protocol - low byte */
 | 
						|
 | 
						|
struct termios tmode, omode;
 | 
						|
 | 
						|
int crmod, digit_or_punc, lower, upper;
 | 
						|
 | 
						|
char	hostname[MAXHOSTNAMELEN + 1];
 | 
						|
struct	utsname kerninfo;
 | 
						|
char	name[LOGIN_NAME_MAX];
 | 
						|
char	dev[] = _PATH_DEV;
 | 
						|
char	ttyn[32];
 | 
						|
char	lockfile[512];
 | 
						|
uid_t	ttyowner;
 | 
						|
char	*rawttyn;
 | 
						|
 | 
						|
#define	OBUFSIZ		128
 | 
						|
#define	TABBUFSIZ	512
 | 
						|
 | 
						|
char	defent[TABBUFSIZ];
 | 
						|
char	tabent[TABBUFSIZ];
 | 
						|
 | 
						|
char	*env[128];
 | 
						|
 | 
						|
const unsigned char partab[] = {
 | 
						|
	0001,0201,0201,0001,0201,0001,0001,0201,
 | 
						|
	0202,0004,0003,0205,0005,0206,0201,0001,
 | 
						|
	0201,0001,0001,0201,0001,0201,0201,0001,
 | 
						|
	0001,0201,0201,0001,0201,0001,0001,0201,
 | 
						|
	0200,0000,0000,0200,0000,0200,0200,0000,
 | 
						|
	0000,0200,0200,0000,0200,0000,0000,0200,
 | 
						|
	0000,0200,0200,0000,0200,0000,0000,0200,
 | 
						|
	0200,0000,0000,0200,0000,0200,0200,0000,
 | 
						|
	0200,0000,0000,0200,0000,0200,0200,0000,
 | 
						|
	0000,0200,0200,0000,0200,0000,0000,0200,
 | 
						|
	0000,0200,0200,0000,0200,0000,0000,0200,
 | 
						|
	0200,0000,0000,0200,0000,0200,0200,0000,
 | 
						|
	0000,0200,0200,0000,0200,0000,0000,0200,
 | 
						|
	0200,0000,0000,0200,0000,0200,0200,0000,
 | 
						|
	0200,0000,0000,0200,0000,0200,0200,0000,
 | 
						|
	0000,0200,0200,0000,0200,0000,0000,0201
 | 
						|
};
 | 
						|
 | 
						|
#define	ERASE	tmode.c_cc[VERASE]
 | 
						|
#define	KILL	tmode.c_cc[VKILL]
 | 
						|
#define	EOT	tmode.c_cc[VEOF]
 | 
						|
 | 
						|
static void	clearscreen(void);
 | 
						|
 | 
						|
sigjmp_buf timeout;
 | 
						|
 | 
						|
__dead static void
 | 
						|
/*ARGSUSED*/
 | 
						|
dingdong(int signo)
 | 
						|
{
 | 
						|
 | 
						|
	(void)alarm(0);
 | 
						|
	(void)signal(SIGALRM, SIG_DFL);
 | 
						|
	siglongjmp(timeout, 1);
 | 
						|
}
 | 
						|
 | 
						|
sigjmp_buf intrupt;
 | 
						|
 | 
						|
__dead static void
 | 
						|
/*ARGSUSED*/
 | 
						|
interrupt(int signo)
 | 
						|
{
 | 
						|
 | 
						|
	(void)signal(SIGINT, interrupt);
 | 
						|
	siglongjmp(intrupt, 1);
 | 
						|
}
 | 
						|
 | 
						|
#if !defined(__minix)
 | 
						|
/*
 | 
						|
 * Action to take when getty is running too long.
 | 
						|
 */
 | 
						|
__dead static void
 | 
						|
/*ARGSUSED*/
 | 
						|
timeoverrun(int signo)
 | 
						|
{
 | 
						|
 | 
						|
	syslog(LOG_ERR, "getty exiting due to excessive running time");
 | 
						|
	exit(1);
 | 
						|
}
 | 
						|
#endif /* !defined(__minix) */
 | 
						|
 | 
						|
static int	getname(void);
 | 
						|
static void	oflush(void);
 | 
						|
static void	prompt(void);
 | 
						|
static int	putchr(int);
 | 
						|
static void	putf(const char *);
 | 
						|
static void	xputs(const char *);
 | 
						|
 | 
						|
#define putpad(s) tputs(s, 1, putchr)
 | 
						|
 | 
						|
int
 | 
						|
main(int argc, char *argv[], char *envp[])
 | 
						|
{
 | 
						|
	const char *progname;
 | 
						|
	int repcnt = 0, failopenlogged = 0, first_time = 1;
 | 
						|
	struct rlimit limit;
 | 
						|
	struct passwd *pw;
 | 
						|
	int rval;
 | 
						|
	/* this is used past the siglongjmp, so make sure it is not cached
 | 
						|
	   in registers that might become invalid. */
 | 
						|
	volatile int uugetty = 0;
 | 
						|
	const char * volatile tname = "default";
 | 
						|
 | 
						|
	(void)signal(SIGINT, SIG_IGN);
 | 
						|
	openlog("getty", LOG_PID, LOG_AUTH);
 | 
						|
	(void)gethostname(hostname, sizeof(hostname));
 | 
						|
	hostname[sizeof(hostname) - 1] = '\0';
 | 
						|
	if (hostname[0] == '\0')
 | 
						|
		(void)strlcpy(hostname, "Amnesiac", sizeof(hostname));
 | 
						|
	(void)uname(&kerninfo);
 | 
						|
 | 
						|
	progname = getprogname();
 | 
						|
	if (progname[0] == 'u' && progname[1] == 'u')
 | 
						|
		uugetty = 1;
 | 
						|
 | 
						|
	/*
 | 
						|
	 * Find id of uucp login (if present) so we can chown tty properly.
 | 
						|
	 */
 | 
						|
	if (uugetty && (pw = getpwnam("uucp")))
 | 
						|
		ttyowner = pw->pw_uid;
 | 
						|
	else
 | 
						|
		ttyowner = 0;
 | 
						|
 | 
						|
	/*
 | 
						|
	 * Limit running time to deal with broken or dead lines.
 | 
						|
	 */
 | 
						|
#if !defined(__minix)
 | 
						|
	(void)signal(SIGXCPU, timeoverrun);
 | 
						|
#endif /* !defined(__minix) */
 | 
						|
	limit.rlim_max = RLIM_INFINITY;
 | 
						|
	limit.rlim_cur = GETTY_TIMEOUT;
 | 
						|
	(void)setrlimit(RLIMIT_CPU, &limit);
 | 
						|
 | 
						|
	/*
 | 
						|
	 * The following is a work around for vhangup interactions
 | 
						|
	 * which cause great problems getting window systems started.
 | 
						|
	 * If the tty line is "-", we do the old style getty presuming
 | 
						|
	 * that the file descriptors are already set up for us.
 | 
						|
	 * J. Gettys - MIT Project Athena.
 | 
						|
	 */
 | 
						|
	if (argc <= 2 || strcmp(argv[2], "-") == 0) {
 | 
						|
		(void)strlcpy(ttyn, ttyname(0), sizeof(ttyn));
 | 
						|
	}
 | 
						|
	else {
 | 
						|
		int i;
 | 
						|
 | 
						|
		rawttyn = argv[2];
 | 
						|
		(void)strlcpy(ttyn, dev, sizeof(ttyn));
 | 
						|
		(void)strlcat(ttyn, argv[2], sizeof(ttyn));
 | 
						|
		if (uugetty)  {
 | 
						|
			(void)chown(ttyn, ttyowner, 0);
 | 
						|
			(void)strlcpy(lockfile, _PATH_LOCK,
 | 
						|
				sizeof(lockfile));
 | 
						|
			(void)strlcat(lockfile, argv[2],
 | 
						|
				sizeof(lockfile));
 | 
						|
			/*
 | 
						|
			 * wait for lockfiles to go away before we try
 | 
						|
			 * to open
 | 
						|
			 */
 | 
						|
			if (pidlock(lockfile, 0, 0, 0) != 0)  {
 | 
						|
				syslog(LOG_ERR,
 | 
						|
					"%s: can't create lockfile", ttyn);
 | 
						|
				exit(1);
 | 
						|
			}
 | 
						|
			(void)unlink(lockfile);
 | 
						|
		}
 | 
						|
		if (strcmp(argv[0], "+") != 0) {
 | 
						|
			(void)chown(ttyn, ttyowner, 0);
 | 
						|
			(void)chmod(ttyn, 0600);
 | 
						|
#if !defined(__minix)
 | 
						|
			(void)revoke(ttyn);
 | 
						|
#endif /* !defined(__minix) */
 | 
						|
			if (ttyaction(ttyn, "getty", "root"))
 | 
						|
				syslog(LOG_WARNING, "%s: ttyaction failed",
 | 
						|
					ttyn);
 | 
						|
			/*
 | 
						|
			 * Delay the open so DTR stays down long enough
 | 
						|
			 * to be detected.
 | 
						|
			 */
 | 
						|
			(void)sleep(2);
 | 
						|
			while ((i = open(ttyn, O_RDWR)) == -1) {
 | 
						|
				if ((repcnt % 10 == 0) &&
 | 
						|
				    (errno != ENXIO || !failopenlogged)) {
 | 
						|
					syslog(LOG_WARNING, "%s: %m", ttyn);
 | 
						|
					closelog();
 | 
						|
					failopenlogged = 1;
 | 
						|
				}
 | 
						|
				repcnt++;
 | 
						|
				(void)sleep(60);
 | 
						|
			}
 | 
						|
			if (uugetty && pidlock(lockfile, 0, 0, 0) != 0)  {
 | 
						|
				syslog(LOG_ERR, "%s: can't create lockfile",
 | 
						|
					ttyn);
 | 
						|
				exit(1);
 | 
						|
			}
 | 
						|
			if (uugetty)
 | 
						|
				(void)chown(lockfile, ttyowner, 0);
 | 
						|
			(void)login_tty(i);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/* Start with default tty settings */
 | 
						|
	if (tcgetattr(0, &tmode) < 0) {
 | 
						|
		syslog(LOG_ERR, "%s: %m", ttyn);
 | 
						|
		exit(1);
 | 
						|
	}
 | 
						|
	omode = tmode;
 | 
						|
 | 
						|
	gettable("default", defent);
 | 
						|
	gendefaults();
 | 
						|
	if (argc > 1)
 | 
						|
		tname = argv[1];
 | 
						|
	for (;;) {
 | 
						|
		int off;
 | 
						|
 | 
						|
		rval = 0;
 | 
						|
		gettable(tname, tabent);
 | 
						|
		if (OPset || EPset || APset)
 | 
						|
			APset++, OPset++, EPset++;
 | 
						|
		setdefaults();
 | 
						|
		off = 0;
 | 
						|
		(void)tcflush(0, TCIOFLUSH);	/* clear out the crap */
 | 
						|
#ifndef  __minix
 | 
						|
		(void)ioctl(0, FIONBIO, &off);	/* turn off non-blocking mode */
 | 
						|
		(void)ioctl(0, FIOASYNC, &off);	/* ditto for async mode */
 | 
						|
#endif /* !defined(__minix) */
 | 
						|
 | 
						|
		if (IS)
 | 
						|
			(void)cfsetispeed(&tmode, (speed_t)IS);
 | 
						|
		else if (SP)
 | 
						|
			(void)cfsetispeed(&tmode, (speed_t)SP);
 | 
						|
		if (OS)
 | 
						|
			(void)cfsetospeed(&tmode, (speed_t)OS);
 | 
						|
		else if (SP)
 | 
						|
			(void)cfsetospeed(&tmode, (speed_t)SP);
 | 
						|
		setflags(0);
 | 
						|
		setchars();
 | 
						|
		if (tcsetattr(0, TCSANOW, &tmode) < 0) {
 | 
						|
			syslog(LOG_ERR, "%s: %m", ttyn);
 | 
						|
			exit(1);
 | 
						|
		}
 | 
						|
		if (AB) {
 | 
						|
			tname = autobaud();
 | 
						|
			continue;
 | 
						|
		}
 | 
						|
		if (PS) {
 | 
						|
			tname = portselector();
 | 
						|
			continue;
 | 
						|
		}
 | 
						|
		if (CS)
 | 
						|
			clearscreen();
 | 
						|
		if (CL && *CL)
 | 
						|
			putpad(CL);
 | 
						|
		edithost(HE);
 | 
						|
 | 
						|
		/*
 | 
						|
		 * If this is the first time through this, and an
 | 
						|
		 * issue file has been given, then send it.
 | 
						|
		 */
 | 
						|
		if (first_time != 0 && IF != NULL) {
 | 
						|
			char buf[_POSIX2_LINE_MAX];
 | 
						|
			FILE *fp;
 | 
						|
 | 
						|
			if ((fp = fopen(IF, "r")) != NULL) {
 | 
						|
				while (fgets(buf, sizeof(buf) - 1, fp) != NULL)
 | 
						|
					putf(buf);
 | 
						|
				(void)fclose(fp);
 | 
						|
			}
 | 
						|
		}
 | 
						|
		first_time = 0;
 | 
						|
 | 
						|
		if (IM && *IM)
 | 
						|
			putf(IM);
 | 
						|
		oflush();
 | 
						|
		if (sigsetjmp(timeout, 1)) {
 | 
						|
			tmode.c_ispeed = tmode.c_ospeed = 0;
 | 
						|
			(void)tcsetattr(0, TCSANOW, &tmode);
 | 
						|
			exit(1);
 | 
						|
		}
 | 
						|
		if (TO) {
 | 
						|
			(void)signal(SIGALRM, dingdong);
 | 
						|
			(void)alarm((unsigned int)TO);
 | 
						|
		}
 | 
						|
		if (NN) {
 | 
						|
			name[0] = '\0';
 | 
						|
			lower = 1;
 | 
						|
			upper = digit_or_punc = 0;
 | 
						|
		} else if (AL) {
 | 
						|
			const char *p = AL;
 | 
						|
			char *q = name;
 | 
						|
 | 
						|
			while (*p && q < &name[sizeof name - 1]) {
 | 
						|
				if (isupper((unsigned char)*p))
 | 
						|
					upper = 1;
 | 
						|
				else if (islower((unsigned char)*p))
 | 
						|
					lower = 1;
 | 
						|
				else if (isdigit((unsigned char)*p))
 | 
						|
					digit_or_punc = 1;
 | 
						|
				*q++ = *p++;
 | 
						|
			}
 | 
						|
		} else if ((rval = getname()) == 2) {
 | 
						|
			setflags(2);
 | 
						|
			(void)execle(PP, "ppplogin", ttyn, (char *) 0, env);
 | 
						|
			syslog(LOG_ERR, "%s: %m", PP);
 | 
						|
			exit(1);
 | 
						|
		}
 | 
						|
 | 
						|
		if (rval || AL || NN) {
 | 
						|
			int i;
 | 
						|
 | 
						|
			oflush();
 | 
						|
			(void)alarm(0);
 | 
						|
			(void)signal(SIGALRM, SIG_DFL);
 | 
						|
			if (name[0] == '-') {
 | 
						|
				xputs("user names may not start with '-'.");
 | 
						|
				continue;
 | 
						|
			}
 | 
						|
			if (!(upper || lower || digit_or_punc))
 | 
						|
				continue;
 | 
						|
			setflags(2);
 | 
						|
			if (crmod) {
 | 
						|
				tmode.c_iflag |= ICRNL;
 | 
						|
				tmode.c_oflag |= ONLCR;
 | 
						|
			}
 | 
						|
#if XXX
 | 
						|
			if (upper || UC)
 | 
						|
				tmode.sg_flags |= LCASE;
 | 
						|
			if (lower || LC)
 | 
						|
				tmode.sg_flags &= ~LCASE;
 | 
						|
#endif
 | 
						|
			if (tcsetattr(0, TCSANOW, &tmode) < 0) {
 | 
						|
				syslog(LOG_ERR, "%s: %m", ttyn);
 | 
						|
				exit(1);
 | 
						|
			}
 | 
						|
			(void)signal(SIGINT, SIG_DFL);
 | 
						|
			for (i = 0; envp[i] != NULL; i++)
 | 
						|
				env[i] = envp[i];
 | 
						|
			makeenv(&env[i]);
 | 
						|
 | 
						|
			limit.rlim_max = RLIM_INFINITY;
 | 
						|
			limit.rlim_cur = RLIM_INFINITY;
 | 
						|
			(void)setrlimit(RLIMIT_CPU, &limit);
 | 
						|
			if (NN)
 | 
						|
				(void)execle(LO, "login", AL ? "-fp" : "-p",
 | 
						|
				    NULL, env);
 | 
						|
			else
 | 
						|
				(void)execle(LO, "login", AL ? "-fp" : "-p",
 | 
						|
				    "--", name, NULL, env);
 | 
						|
			syslog(LOG_ERR, "%s: %m", LO);
 | 
						|
			exit(1);
 | 
						|
		}
 | 
						|
		(void)alarm(0);
 | 
						|
		(void)signal(SIGALRM, SIG_DFL);
 | 
						|
		(void)signal(SIGINT, SIG_IGN);
 | 
						|
		if (NX && *NX)
 | 
						|
			tname = NX;
 | 
						|
		if (uugetty)
 | 
						|
			(void)unlink(lockfile);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
getname(void)
 | 
						|
{
 | 
						|
	int c;
 | 
						|
	char *np;
 | 
						|
	unsigned char cs;
 | 
						|
	int ppp_state, ppp_connection;
 | 
						|
 | 
						|
	/*
 | 
						|
	 * Interrupt may happen if we use CBREAK mode
 | 
						|
	 */
 | 
						|
	if (sigsetjmp(intrupt, 1)) {
 | 
						|
		(void)signal(SIGINT, SIG_IGN);
 | 
						|
		return (0);
 | 
						|
	}
 | 
						|
	(void)signal(SIGINT, interrupt);
 | 
						|
	setflags(1);
 | 
						|
	prompt();
 | 
						|
	if (PF > 0) {
 | 
						|
		oflush();
 | 
						|
		(void)sleep((unsigned int)PF);
 | 
						|
		PF = 0;
 | 
						|
	}
 | 
						|
	if (tcsetattr(0, TCSANOW, &tmode) < 0) {
 | 
						|
		syslog(LOG_ERR, "%s: %m", ttyn);
 | 
						|
		exit(1);
 | 
						|
	}
 | 
						|
	crmod = digit_or_punc = lower = upper = 0;
 | 
						|
	ppp_state = ppp_connection = 0;
 | 
						|
	np = name;
 | 
						|
	for (;;) {
 | 
						|
		oflush();
 | 
						|
		if (read(STDIN_FILENO, &cs, 1) <= 0)
 | 
						|
			exit(0);
 | 
						|
		if ((c = cs&0177) == 0)
 | 
						|
			return (0);
 | 
						|
 | 
						|
		/*
 | 
						|
		 * PPP detection state machine..
 | 
						|
		 * Look for sequences:
 | 
						|
		 * PPP_FRAME, PPP_STATION, PPP_ESCAPE, PPP_CONTROL_ESCAPED or
 | 
						|
		 * PPP_FRAME, PPP_STATION, PPP_CONTROL (deviant from RFC)
 | 
						|
		 * See RFC1662.
 | 
						|
		 * Derived from code from Michael Hancock <michaelh@cet.co.jp>
 | 
						|
		 * and Erik 'PPP' Olson <eriko@wrq.com>
 | 
						|
		 */
 | 
						|
		if (PP && cs == PPP_FRAME) {
 | 
						|
			ppp_state = 1;
 | 
						|
		} else if (ppp_state == 1 && cs == PPP_STATION) {
 | 
						|
			ppp_state = 2;
 | 
						|
		} else if (ppp_state == 2 && cs == PPP_ESCAPE) {
 | 
						|
			ppp_state = 3;
 | 
						|
		} else if ((ppp_state == 2 && cs == PPP_CONTROL) ||
 | 
						|
		    (ppp_state == 3 && cs == PPP_CONTROL_ESCAPED)) {
 | 
						|
			ppp_state = 4;
 | 
						|
		} else if (ppp_state == 4 && cs == PPP_LCP_HI) {
 | 
						|
			ppp_state = 5;
 | 
						|
		} else if (ppp_state == 5 && cs == PPP_LCP_LOW) {
 | 
						|
			ppp_connection = 1;
 | 
						|
			break;
 | 
						|
		} else {
 | 
						|
			ppp_state = 0;
 | 
						|
		}
 | 
						|
 | 
						|
		if (c == EOT)
 | 
						|
			exit(1);
 | 
						|
		if (c == '\r' || c == '\n' ||
 | 
						|
		    np >= &name[LOGIN_NAME_MAX - 1]) {
 | 
						|
			*np = '\0';
 | 
						|
			putf("\r\n");
 | 
						|
			break;
 | 
						|
		}
 | 
						|
		if (islower(c))
 | 
						|
			lower = 1;
 | 
						|
		else if (isupper(c))
 | 
						|
			upper = 1;
 | 
						|
		else if (c == ERASE || c == '#' || c == '\b') {
 | 
						|
			if (np > name) {
 | 
						|
				np--;
 | 
						|
				if (cfgetospeed(&tmode) >= 1200)
 | 
						|
					xputs("\b \b");
 | 
						|
				else
 | 
						|
					putchr(cs);
 | 
						|
			}
 | 
						|
			continue;
 | 
						|
		} else if (c == KILL || c == '@') {
 | 
						|
			putchr(cs);
 | 
						|
			putchr('\r');
 | 
						|
			if (cfgetospeed(&tmode) < 1200)
 | 
						|
				putchr('\n');
 | 
						|
			/* this is the way they do it down under ... */
 | 
						|
			else if (np > name)
 | 
						|
				xputs(
 | 
						|
				    "                                     \r");
 | 
						|
			prompt();
 | 
						|
			np = name;
 | 
						|
			continue;
 | 
						|
		} else if (isdigit(c) || c == '_')
 | 
						|
			digit_or_punc = 1;
 | 
						|
		if (IG && (c <= ' ' || c > 0176))
 | 
						|
			continue;
 | 
						|
		*np++ = c;
 | 
						|
		putchr(cs);
 | 
						|
 | 
						|
		/*
 | 
						|
		 * An MS-Windows direct connect PPP "client" won't send its
 | 
						|
		 * first PPP packet until we respond to its "CLIENT" poll
 | 
						|
		 * with a CRLF sequence.  We cater to yet another broken
 | 
						|
		 * implementation of a previously-standard protocol...
 | 
						|
		 */
 | 
						|
		*np = '\0';
 | 
						|
		if (strstr(name, "CLIENT"))
 | 
						|
			putf("\r\n");
 | 
						|
	}
 | 
						|
	(void)signal(SIGINT, SIG_IGN);
 | 
						|
	*np = 0;
 | 
						|
	if (c == '\r')
 | 
						|
		crmod = 1;
 | 
						|
	if ((upper && !lower && !LC) || UC)
 | 
						|
		for (np = name; *np; np++)
 | 
						|
			*np = tolower((unsigned char)*np);
 | 
						|
	return (1 + ppp_connection);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
xputs(const char *s)
 | 
						|
{
 | 
						|
	while (*s)
 | 
						|
		putchr(*s++);
 | 
						|
}
 | 
						|
 | 
						|
char	outbuf[OBUFSIZ];
 | 
						|
size_t	obufcnt = 0;
 | 
						|
 | 
						|
static int
 | 
						|
putchr(int cc)
 | 
						|
{
 | 
						|
	unsigned char c;
 | 
						|
 | 
						|
	c = cc;
 | 
						|
	if (!NP) {
 | 
						|
		c |= partab[c&0177] & 0200;
 | 
						|
		if (OP)
 | 
						|
			c ^= 0200;
 | 
						|
	}
 | 
						|
	if (!UB) {
 | 
						|
		outbuf[obufcnt++] = c;
 | 
						|
		if (obufcnt >= OBUFSIZ)
 | 
						|
			oflush();
 | 
						|
		return 1;
 | 
						|
	}
 | 
						|
	return write(STDOUT_FILENO, &c, 1);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
oflush(void)
 | 
						|
{
 | 
						|
	if (obufcnt)
 | 
						|
		(void)write(STDOUT_FILENO, outbuf, obufcnt);
 | 
						|
	obufcnt = 0;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
prompt(void)
 | 
						|
{
 | 
						|
 | 
						|
	putf(LM);
 | 
						|
	if (CO)
 | 
						|
		putchr('\n');
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
putf(const char *cp)
 | 
						|
{
 | 
						|
	time_t t;
 | 
						|
	char *slash, db[100];
 | 
						|
 | 
						|
	while (*cp) {
 | 
						|
		if (*cp != '%') {
 | 
						|
			putchr(*cp++);
 | 
						|
			continue;
 | 
						|
		}
 | 
						|
		switch (*++cp) {
 | 
						|
 | 
						|
		case 't':
 | 
						|
			if ((slash = strstr(ttyn, "/pts/")) == NULL)
 | 
						|
				slash = strrchr(ttyn, '/');
 | 
						|
			if (slash == NULL)
 | 
						|
				xputs(ttyn);
 | 
						|
			else
 | 
						|
				xputs(&slash[1]);
 | 
						|
			break;
 | 
						|
 | 
						|
		case 'h':
 | 
						|
			xputs(editedhost);
 | 
						|
			break;
 | 
						|
 | 
						|
		case 'd':
 | 
						|
			(void)time(&t);
 | 
						|
			(void)strftime(db, sizeof(db),
 | 
						|
			    "%l:%M%p on %A, %d %B %Y", localtime(&t));
 | 
						|
			xputs(db);
 | 
						|
			break;
 | 
						|
 | 
						|
		case 's':
 | 
						|
			xputs(kerninfo.sysname);
 | 
						|
			break;
 | 
						|
 | 
						|
		case 'm':
 | 
						|
			xputs(kerninfo.machine);
 | 
						|
			break;
 | 
						|
 | 
						|
		case 'r':
 | 
						|
			xputs(kerninfo.release);
 | 
						|
			break;
 | 
						|
 | 
						|
		case 'v':
 | 
						|
			xputs(kerninfo.version);
 | 
						|
			break;
 | 
						|
 | 
						|
		case '%':
 | 
						|
			putchr('%');
 | 
						|
			break;
 | 
						|
		}
 | 
						|
		if (*cp)
 | 
						|
			cp++;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
clearscreen(void)
 | 
						|
{
 | 
						|
	struct ttyent *typ;
 | 
						|
	int err;
 | 
						|
 | 
						|
	if (rawttyn == NULL)
 | 
						|
		return;
 | 
						|
 | 
						|
	typ = getttynam(rawttyn);
 | 
						|
 | 
						|
	if ((typ == NULL) || (typ->ty_type == NULL) ||
 | 
						|
	    (typ->ty_type[0] == 0))
 | 
						|
		return;
 | 
						|
 | 
						|
	if (setupterm(typ->ty_type, 0, &err) == ERR)
 | 
						|
		return;
 | 
						|
 | 
						|
	if (clear_screen)
 | 
						|
		putpad(clear_screen);
 | 
						|
 | 
						|
	del_curterm(cur_term);
 | 
						|
	cur_term = NULL;
 | 
						|
}
 |