use_kerberos = 0;
main(argc, argv)	int argc;	char **argv;{	extern char **environ;	register struct passwd *pwd;	register char *p, **g;	struct group *gr;	uid_t ruid;	int asme, ch, asthem, fastlogin, prio;	enum { UNSET, YES, NO } iscsh = UNSET;	char *user, *shell, *avshell, *username, *cleanenv[10], **np;	char shellbuf[MAXPATHLEN], avshellbuf[MAXPATHLEN];	asme = asthem = fastlogin = 0;	while ((ch = getopt(argc, argv, ARGSTR)) != -1)		switch((char)ch) {#ifdef KERBEROS		case 'K':			use_kerberos = 0;			break;#endif		case 'f':			fastlogin = 1;			break;		case '-':		case 'l':			asme = 0;			asthem = 1;			break;		case 'm':			asme = 1;			asthem = 0;			break;		case '?':		default:			(void)fprintf(stderr,			    "usage: su [%s] [login [shell arguments]]\n",			    ARGSTR);			exit(1);		}	argv += optind;	errno = 0;	prio = getpriority(PRIO_PROCESS, 0);	if (errno)		prio = 0;	(void)setpriority(PRIO_PROCESS, 0, -2);	openlog("su", LOG_CONS, 0);	/* get current login name and shell */	ruid = getuid();	username = getlogin();	if (username == NULL || (pwd = getpwnam(username)) == NULL ||	    pwd->pw_uid != ruid)		pwd = getpwuid(ruid);	if (pwd == NULL)		errx(1, "who are you?");	if ((username = strdup(pwd->pw_name)) == NULL)		err(1, "can't allocate memory");	if (asme)		if (pwd->pw_shell && *pwd->pw_shell) {			shell = strncpy(shellbuf, pwd->pw_shell, sizeof(shellbuf) - 1);			shellbuf[sizeof(shellbuf) - 1] = '\0';		} else {			shell = _PATH_BSHELL;			iscsh = NO;		}	/* get target login information, default to root */	user = *argv ? *argv : "root";	np = *argv ? argv : argv-1;	if ((pwd = getpwnam(user)) == NULL)		errx(1, "unknown login %s", user);	if ((user = strdup(pwd->pw_name)) == NULL)		err(1, "can't allocate memory");	if (ruid) {#ifdef KERBEROS	    if (!use_kerberos || kerberos(username, user, pwd->pw_uid))#endif	    {		use_kerberos = 0;		/* only allow those in group zero to su to root. */		if (pwd->pw_uid == 0 && (gr = getgrgid((gid_t)0))		    && gr->gr_mem && *(gr->gr_mem))			for (g = gr->gr_mem;; ++g) {				if (!*g)					errx(1, "you are not in the correct group to su %s.", user);				if (strcmp(username, *g) == 0)					break;		}		/* if target requires a password, verify it */		if (*pwd->pw_passwd) {			p = getpass("Password:");#ifdef SKEY			if (strcasecmp(p, "s/key") == 0) {				if (skey_authenticate(user))					goto badlogin;			} else#endif			if (strcmp(pwd->pw_passwd, crypt(p, pwd->pw_passwd))) {badlogin:				fprintf(stderr, "Sorry\n");				syslog(LOG_AUTH|LOG_WARNING,					"BAD SU %s to %s%s", username,					user, ontty());				exit(1);			}		}	    }	    if (pwd->pw_expire && time(NULL) >= pwd->pw_expire) {		    fprintf(stderr, "Sorry - account expired\n");		    syslog(LOG_AUTH|LOG_WARNING, "BAD SU %s to %s%s", username,			    user, ontty());		    exit(1);	    }	}	if (asme) {		/* if asme and non-standard target shell, must be root */		if (!chshell(pwd->pw_shell) && ruid)			errx(1, "permission denied (shell).");	} else if (pwd->pw_shell && *pwd->pw_shell) {		shell = pwd->pw_shell;		iscsh = UNSET;	} else {		shell = _PATH_BSHELL;		iscsh = NO;	}	if (p = strrchr(shell, '/'))		avshell = p+1;	else		avshell = shell;	/* if we're forking a csh, we want to slightly muck the args */	if (iscsh == UNSET)		iscsh = strcmp(avshell, "csh") ? NO : YES;#if defined(KERBEROS) || defined(KERBEROS5)	/* Fork so that we can call kdestroy */	if (use_kerberos)	    dofork();#endif	/* set permissions */	if (setegid(pwd->pw_gid) < 0)		err(1, "setegid");	if (setgid(pwd->pw_gid) < 0)		err(1, "setgid");	if (initgroups(user, pwd->pw_gid))		err(1, "initgroups failed");	if (seteuid(pwd->pw_uid) < 0)		err(1, "seteuid");	if (setuid(pwd->pw_uid) < 0)		err(1, "setuid");	if (!asme) {		if (asthem) {			p = getenv("TERM");			cleanenv[0] = NULL;			environ = cleanenv;			(void)setenv("PATH", _PATH_DEFPATH, 1);			if (p)				(void)setenv("TERM", p, 1);			seteuid(pwd->pw_uid);			setegid(pwd->pw_gid);			if (chdir(pwd->pw_dir) < 0)				errx(1, "no directory");			seteuid(0);			setegid(0);	/* XXX use a saved gid instead? */		}		if (asthem || pwd->pw_uid) {			(void)setenv("LOGNAME", pwd->pw_name, 1);			(void)setenv("USER", pwd->pw_name, 1);		}		(void)setenv("HOME", pwd->pw_dir, 1);		(void)setenv("SHELL", shell, 1);	}	if (iscsh == YES) {		if (fastlogin)			*np-- = "-f";		if (asme)			*np-- = "-m";	}	if (asthem) {		avshellbuf[0] = '-';		strncpy(avshellbuf+1, avshell, sizeof(avshellbuf) - 2);		avshellbuf[sizeof(avshellbuf) - 1] = '\0';		avshell = avshellbuf;	} else if (iscsh == YES) {		/* csh strips the first character... */		avshellbuf[0] = '_';		strncpy(avshellbuf+1, avshell, sizeof(avshellbuf) - 2);		avshellbuf[sizeof(avshellbuf) - 1] = '\0';		avshell = avshellbuf;	}				*np = avshell;	if (ruid != 0)		syslog(LOG_NOTICE|LOG_AUTH, "%s to %s%s",		    username, user, ontty());	(void)setpriority(PRIO_PROCESS, 0, prio);	execv(shell, np);	err(1, shell);}