2.9BSD/usr/src/cmd/su.c

Compare this file to the similar file:
Show the results in this format:

#include <whoami.h>
#include <stdio.h>
#include <pwd.h>
#include <sys/types.h>
#include <sys/stat.h>

#define	DFLT_SHELL	"/bin/sh"
#define	PATH	"PATH=:/bin:/usr/ucb:/usr/bin"		/* default path */
#define	SULOGFILE	"/usr/adm/sulog"

struct	passwd *pwd,*getpwnam();
char	*crypt();
char	*getpass();
char	*getenv();
char	**environ;
int	ruid, rgid;
char	homedir[64] = "HOME=";
char	term[64] = "TERM=unknown";
char	shell[64] = "SHELL=";
char	user[64] = "USER=";

char	*envinit[8] = {homedir, PATH, term, shell, user, 0, 0};
#define	E_TERMCAP	5		/* where to put termcap in envinit */

main(argc,argv)
int	argc;
char	**argv;
{
	register char **p;
	char *nptr;
	char *password;
	register char *cp;
	register char *cp2;
	char hometmp[50];
	char *sh = DFLT_SHELL;
	int minusflag = 0;
	int new_uid, new_gid;

	if (argc > 1 && argv[1][0]=='-') {
		minusflag++;
		argc--;
		argv++;
	}
	if(argc > 1)
		nptr = argv[1];
	else
		nptr = "root";
	if((pwd=getpwnam(nptr)) == NULL) {
		printf("Unknown id: %s\n",nptr);
		exit(1);
	}
	ruid = getuid();
	rgid = getgid();
	/*
	 * If the new user has no password, force the use
	 * of his shell.
	 */
	if (pwd->pw_passwd[0] == '\0')
		minusflag++;
	if(pwd->pw_passwd[0] == '\0' || ruid == 0)
		goto ok;
#ifdef	UCB_GRPMAST
	if ((ruid == rgid) && (rgid == pwd->pw_gid))
		goto ok;
#endif
	password = getpass("Password:  ");
	if(strcmp(pwd->pw_passwd, crypt(password, pwd->pw_passwd)) != 0) {
		if (pwd->pw_uid == 0)
			sulog(ruid, nptr, password);
		printf("Sorry\n");
		exit(2);
	}

ok:
	endpwent();

	/*
	 * ``All information is contained in a static area so it must  be
	 * copied if it is to be saved.'' - getpwent(3)
	 */
	new_uid = pwd->pw_uid;
	new_gid = pwd->pw_gid;
	     
	if (pwd->pw_uid == 0)
		sulog(ruid, nptr, (char *) NULL);
	setgid(new_gid);
	setuid(new_uid);
	if (minusflag) {
		if (pwd->pw_shell && *pwd->pw_shell)
			sh = pwd->pw_shell;
		strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
		strncat(shell, sh, sizeof(shell)-7);
		strncat(user, pwd->pw_name, sizeof(user)-5);
		if ((cp=getenv("TERM")) != NULL)
			strncpy(term+5, cp, sizeof(term)-5);
		for (p=environ; *p; p++)
			if (strncmp(*p, "TERMCAP=", 8) == 0) {
				envinit[E_TERMCAP] = *p;
				break;
			}
		if (chdir(pwd->pw_dir) < 0)
			perror(pwd->pw_dir);
		environ = envinit;
	} else {
		if ((cp=getenv("SHELL")) != NULL)
		    sh = cp;
	}
	if(strcmp(sh,"/bin/csh") != 0)
		execl(sh, "su", 0);
	else
		execl(sh, "_su", 0);
	printf("No shell\n");
	exit(3);
}

sulog(whoid, whoto, password)
	register char	*whoto, *password;
{
	register FILE	*logf;
	int	i;
	long	now;
	char	*ttyn, *ttyname();
	struct	stat statb;
	struct passwd *getpwuid();
	
	if (stat(SULOGFILE, &statb) < 0)
		return;
	if ((logf = fopen (SULOGFILE, "a")) == NULL)
		return;
	
	for (i = 0; i < 3; i++)
		if ((ttyn = ttyname(i)) != NULL)
			break;
	time (&now);
	fprintf (logf, "%24.24s  %-8.8s  %-8.8s-> %-8.8s  ",
			ctime(&now), ttyn+5, getpwuid(whoid)->pw_name, whoto);
	if (password == (char *) 0)
		fprintf(logf, "OK\n");
	else
		fprintf(logf, "BAD: PW = '%s'\n", password);
	fclose (logf);
}