xref: /original-bsd/usr.bin/su/su.c (revision c43e4352)
1 #ifndef lint
2 static char *sccsid = "@(#)su.c	4.6 (Berkeley) 07/06/83";
3 #endif
4 
5 #include <stdio.h>
6 #include <pwd.h>
7 #include <sys/types.h>
8 #include <sys/time.h>
9 #include <sys/resource.h>
10 
11 char	userbuf[16]	= "USER=";
12 char	homebuf[128]	= "HOME=";
13 char	shellbuf[128]	= "SHELL=";
14 char	pathbuf[128]	= "PATH=:/usr/ucb:/bin:/usr/bin";
15 char	*cleanenv[] = { userbuf, homebuf, shellbuf, pathbuf, 0, 0 };
16 char	*user = "root";
17 char	*shell = "/bin/sh";
18 int	fulllogin;
19 int	fastlogin;
20 
21 extern char	**environ;
22 struct	passwd *pwd,*getpwnam();
23 char	*crypt();
24 char	*getpass();
25 char	*getenv();
26 
27 main(argc,argv)
28 	int argc;
29 	char *argv[];
30 {
31 	char *password;
32 
33 again:
34 	if (argc > 1 && strcmp(argv[1], "-f") == 0) {
35 		fastlogin++;
36 		argc--, argv++;
37 		goto again;
38 	}
39 	if (argc > 1 && strcmp(argv[1], "-") == 0) {
40 		fulllogin++;
41 		argc--, argv++;
42 		goto again;
43 	}
44 	if (argc > 1 && argv[1][0] != '-') {
45 		user = argv[1];
46 		argc--, argv++;
47 	}
48 	if (strcmp(user, "root") == 0)
49 		setpriority(PRIO_PROCESS, 0, -2);
50 	if ((pwd = getpwnam(user)) == NULL) {
51 		fprintf(stderr, "Unknown login: %s\n", user);
52 		exit(1);
53 	}
54 	if (pwd->pw_passwd[0] == '\0' || getuid() == 0)
55 		goto ok;
56 	password = getpass("Password:");
57 	if (strcmp(pwd->pw_passwd, crypt(password, pwd->pw_passwd)) != 0) {
58 		fprintf(stderr, "Sorry\n");
59 		if (pwd->pw_uid == 0) {
60 			FILE *console = fopen("/dev/console", "w");
61 			if (console != NULL) {
62 				fprintf(console, "BADSU: %s %s\r\n",
63 					getlogin(), ttyname(2));
64 				fclose(console);
65 			}
66 		}
67 		exit(2);
68 	}
69 ok:
70 	endpwent();
71 	if (pwd->pw_uid == 0) {
72 		FILE *console = fopen("/dev/console", "w");
73 		if (console != NULL) {
74 			fprintf(console, "SU: %s %s\r\n",
75 				getlogin(), ttyname(2));
76 			fclose(console);
77 		}
78 	}
79 	if (setgid(pwd->pw_gid) < 0) {
80 		perror("su: setgid");
81 		exit(3);
82 	}
83 	if (initgroups(user, pwd->pw_gid)) {
84 		fprintf(stderr, "su: initgroups failed\n");
85 		exit(4);
86 	}
87 	if (setuid(pwd->pw_uid) < 0) {
88 		perror("su: setuid");
89 		exit(5);
90 	}
91 	if (pwd->pw_shell && *pwd->pw_shell)
92 		shell = pwd->pw_shell;
93 	if (fulllogin) {
94 		cleanenv[4] = getenv("TERM");
95 		environ = cleanenv;
96 	}
97 	if (strcmp(user, "root"))
98 		setenv("USER", pwd->pw_name, userbuf);
99 	setenv("SHELL", shell, shellbuf);
100 	setenv("HOME", pwd->pw_dir, homebuf);
101 	setpriority(PRIO_PROCESS, 0, 0);
102 	if (fastlogin) {
103 		*argv-- = "-f";
104 		*argv = "su";
105 	} else if (fulllogin) {
106 		if (chdir(pwd->pw_dir) < 0) {
107 			fprintf(stderr, "No directory\n");
108 			exit(6);
109 		}
110 		*argv = "-su";
111 	} else
112 		*argv = "su";
113 	execv(shell, argv);
114 	fprintf(stderr, "No shell\n");
115 	exit(7);
116 }
117 
118 setenv(ename, eval, buf)
119 	char *ename, *eval, *buf;
120 {
121 	register char *cp, *dp;
122 	register char **ep = environ;
123 
124 	/*
125 	 * this assumes an environment variable "ename" already exists
126 	 */
127 	while (dp = *ep++) {
128 		for (cp = ename; *cp == *dp && *cp; cp++, dp++)
129 			continue;
130 		if (*cp == 0 && (*dp == '=' || *dp == 0)) {
131 			strcat(buf, eval);
132 			*--ep = buf;
133 			return;
134 		}
135 	}
136 }
137 
138 char *
139 getenv(ename)
140 	char *ename;
141 {
142 	register char *cp, *dp;
143 	register char **ep = environ;
144 
145 	while (dp = *ep++) {
146 		for (cp = ename; *cp == *dp && *cp; cp++, dp++)
147 			continue;
148 		if (*cp == 0 && (*dp == '=' || *dp == 0))
149 			return (*--ep);
150 	}
151 	return ((char *)0);
152 }
153