xref: /original-bsd/usr.bin/su/su.c (revision 92d3de31)
1 #ifndef lint
2 static char *sccsid = "@(#)su.c	4.4 (Berkeley) 4.4";
3 #endif
4 
5 #include <stdio.h>
6 #include <pwd.h>
7 
8 struct	passwd *pwd,*getpwnam();
9 char	*crypt();
10 char	*getpass();
11 
12 main(argc,argv)
13 	int argc;
14 	char **argv;
15 {
16 	char *nptr = "root";
17 	char *password;
18 	char *shell = "/bin/sh";
19 
20 	if (argc > 1)
21 		nptr = argv[1];
22 	if ((pwd = getpwnam(nptr)) == NULL) {
23 		printf("Unknown id: %s\n",nptr);
24 		exit(1);
25 	}
26 	if (pwd->pw_passwd[0] == '\0' || getuid() == 0)
27 		goto ok;
28 	password = getpass("Password:");
29 	if (strcmp(pwd->pw_passwd, crypt(password, pwd->pw_passwd)) != 0) {
30 		printf("Sorry\n");
31 		if (pwd->pw_uid == 0) {
32 			FILE *console = fopen("/dev/console", "w");
33 			if (console != NULL) {
34 				fprintf(console, "BADSU: %s %s\r\n",
35 					getlogin(), ttyname(2));
36 				fclose(console);
37 			}
38 		}
39 		exit(2);
40 	}
41 ok:
42 	endpwent();
43 	if (pwd->pw_uid == 0) {
44 		FILE *console = fopen("/dev/console", "w");
45 		if (console != NULL) {
46 			fprintf(console, "SU: %s %s\r\n",
47 				getlogin(), ttyname(2));
48 			fclose(console);
49 		}
50 	}
51 	if (setgid(pwd->pw_gid) < 0) {
52 		perror("su: setgid");
53 		exit(3);
54 	}
55 	if (initgroups(nptr, pwd->pw_gid)) {
56 		fprintf(stderr, "su: initgroups failed\n");
57 		exit(4);
58 	}
59 	if (setuid(pwd->pw_uid) < 0) {
60 		perror("su: setuid");
61 		exit(5);
62 	}
63 	if (pwd->pw_shell && *pwd->pw_shell)
64 		shell = pwd->pw_shell;
65 	homeis(pwd->pw_dir);
66 	shellis(shell);
67 	execl(shell, "su", 0);
68 	printf("No shell\n");
69 	exit(3);
70 }
71 
72 char	**environ;
73 
74 homeis(hp)
75 	char *hp;
76 {
77 	register char *cp, *dp;
78 	register char **ep = environ;
79 	static char homebuf[128];
80 
81 	while (dp = *ep++) {
82 		for (cp = "HOME"; *cp == *dp && *cp; cp++, dp++)
83 			continue;
84 		if (*cp == 0 && (*dp == '=' || *dp == 0)) {
85 			strcpy(homebuf, "HOME=");
86 			strcat(homebuf, hp);
87 			*--ep = homebuf;
88 			return;
89 		}
90 	}
91 }
92 
93 shellis(sp)
94 	char *sp;
95 {
96 	register char *cp, *dp;
97 	register char **ep = environ;
98 	static char shellbuf[128];
99 
100 	while (dp = *ep++) {
101 		for (cp = "SHELL"; *cp == *dp && *cp; cp++, dp++)
102 			continue;
103 		if (*cp == 0 && (*dp == '=' || *dp == 0)) {
104 			strcpy(shellbuf, "SHELL=");
105 			strcat(shellbuf, sp);
106 			*--ep = shellbuf;
107 			return;
108 		}
109 	}
110 }
111