memset(&utmpx, 0, sizeof(utmpx));
memset((void *)&utmpx, 0, sizeof(utmpx));
start_login(host, autologin, name)	char *host;	int autologin;	char *name;{	register char **argv;	char **addarg();	extern char *getenv();	extern char *getstr();	extern char *gettyname;#define	TABBUFSIZ	512	char	defent[TABBUFSIZ];	char	defstrs[TABBUFSIZ];#undef	TABBUFSIZ	char *loginprog = NULL;#ifdef	UTMPX	register int pid = getpid();	struct utmpx utmpx;#endif#ifdef SOLARIS	char *term;	char termbuf[64];#endif#ifdef	UTMPX	/*	 * Create utmp entry for child	 */	memset(&utmpx, 0, sizeof(utmpx));	SCPYN(utmpx.ut_user, ".telnet");	SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1);	utmpx.ut_pid = pid;	utmpx.ut_id[0] = 't';	utmpx.ut_id[1] = 'n';	utmpx.ut_id[2] = SC_WILDC;	utmpx.ut_id[3] = SC_WILDC;	utmpx.ut_type = LOGIN_PROCESS;	(void) time(&utmpx.ut_tv.tv_sec);	if (makeutx(&utmpx) == NULL)		fatal(net, "makeutx failed");#endif	scrub_env();	/*	 * -h : pass on name of host.	 *		WARNING:  -h is accepted by login if and only if	 *			getuid() == 0.	 * -p : don't clobber the environment (so terminal type stays set).	 *	 * -f : force this login, he has already been authenticated	 */	argv = addarg(0, "login");#if	!defined(NO_LOGIN_H)# if	defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)	/*	 * Don't add the "-h host" option if we are going	 * to be adding the "-r host" option down below...	 */	if ((auth_level < 0) || (autologin != AUTH_VALID))# endif	{		argv = addarg(argv, "-h");		argv = addarg(argv, host);#ifdef	SOLARIS		/*		 * SVR4 version of -h takes TERM= as second arg, or -		 */		term = getenv("TERM");		if (term == NULL || term[0] == 0) {			term = "-";		} else {			strcpy(termbuf, "TERM=");			strncat(termbuf, term, sizeof(termbuf) - 6);			term = termbuf;		}		argv = addarg(argv, term);#endif	}#endif#if	!defined(NO_LOGIN_P)	argv = addarg(argv, "-p");#endif#ifdef	LINEMODE	/*	 * Set the environment variable "LINEMODE" to either	 * "real" or "kludge" if we are operating in either	 * real or kludge linemode.	 */	if (lmodetype == REAL_LINEMODE)		setenv("LINEMODE", "real", 1);# ifdef KLUDGELINEMODE	else if (lmodetype == KLUDGE_LINEMODE || lmodetype == KLUDGE_OK)		setenv("LINEMODE", "kludge", 1);# endif#endif#ifdef	BFTPDAEMON	/*	 * Are we working as the bftp daemon?  If so, then ask login	 * to start bftp instead of shell.	 */	if (bftpd) {		argv = addarg(argv, "-e");		argv = addarg(argv, BFTPPATH);	} else#endif#if	defined (SecurID)	/*	 * don't worry about the -f that might get sent.	 * A -s is supposed to override it anyhow.	 */	if (require_SecurID)		argv = addarg(argv, "-s");#endif#if	defined (AUTHENTICATION)	if (auth_level >= 0 && autologin == AUTH_VALID) {# if	!defined(NO_LOGIN_F)		argv = addarg(argv, "-f");		argv = addarg(argv, "--");		argv = addarg(argv, name);# else#  if defined(LOGIN_R)		/*		 * We don't have support for "login -f", but we		 * can fool /bin/login into thinking that we are		 * rlogind, and allow us to log in without a		 * password.  The rlogin protocol expects		 *	local-user\0remote-user\0term/speed\0		 */		if (pty > 2) {			register char *cp;			char speed[128];			int isecho, israw, xpty, len;			extern int def_rspeed;#  ifndef LOGIN_HOST			/*			 * Tell login that we are coming from "localhost".			 * If we passed in the real host name, then the			 * user would have to allow .rhost access from			 * every machine that they want authenticated			 * access to work from, which sort of defeats			 * the purpose of an authenticated login...			 * So, we tell login that the session is coming			 * from "localhost", and the user will only have			 * to have "localhost" in their .rhost file.			 */#			define LOGIN_HOST "localhost"#  endif			argv = addarg(argv, "-r");			argv = addarg(argv, LOGIN_HOST);			xpty = pty;# ifndef  STREAMSPTY			pty = 0;# else			ttyfd = 0;# endif			init_termbuf();			isecho = tty_isecho();			israw = tty_israw();			if (isecho || !israw) {				tty_setecho(0);		/* Turn off echo */				tty_setraw(1);		/* Turn on raw */				set_termbuf();			}			len = strlen(name)+1;			write(xpty, name, len);			write(xpty, name, len);			sprintf(speed, "%s/%d", (cp = getenv("TERM")) ? cp : "",				(def_rspeed > 0) ? def_rspeed : 9600);			len = strlen(speed)+1;			write(xpty, speed, len);			if (isecho || !israw) {				init_termbuf();				tty_setecho(isecho);				tty_setraw(israw);				set_termbuf();				if (!israw) {					/*					 * Write a newline to ensure					 * that login will be able to					 * read the line...					 */					write(xpty, "\n", 1);				}			}			pty = xpty;		}#  else		argv = addarg(argv, "--");		argv = addarg(argv, name);#  endif# endif	} else#endif	if (getenv("USER")) {		argv = addarg(argv, "--");		argv = addarg(argv, getenv("USER"));#if	defined(LOGIN_ARGS) && defined(NO_LOGIN_P)		{			register char **cpp;			for (cpp = environ; *cpp; cpp++)				argv = addarg(argv, *cpp);		}#endif		/*		 * Assume that login will set the USER variable		 * correctly.  For SysV systems, this means that		 * USER will no longer be set, just LOGNAME by		 * login.  (The problem is that if the auto-login		 * fails, and the user then specifies a different		 * account name, he can get logged in with both		 * LOGNAME and USER in his environment, but the		 * USER value will be wrong.		 */		unsetenv("USER");	}#ifdef	SOLARIS	else {		char **p;		argv = addarg(argv, "");	/* no login name */		for (p = environ; *p; p++) {			argv = addarg(argv, *p);		}	}#endif	/* SOLARIS */#if	defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)	if (pty > 2)		close(pty);#endif	if (getent(defent, gettyname) == 1) {		char *cp = defstrs;		loginprog = getstr("lo", &cp);	}	if (loginprog == NULL)		loginprog = _PATH_LOGIN;	closelog();	/*	 * This sleep(1) is in here so that telnetd can	 * finish up with the tty.  There's a race condition	 * the login banner message gets lost...	 */	sleep(1);	execv(loginprog, argv);	syslog(LOG_ERR, "%s: %m\n", loginprog);	fatalperror(net, loginprog);	/*NOTREACHED*/}