su.c - ubase - suckless linux base utils | |
git clone git://git.suckless.org/ubase | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
su.c (2052B) | |
--- | |
1 /* See LICENSE file for copyright and license details. */ | |
2 #include <sys/types.h> | |
3 | |
4 #include <errno.h> | |
5 #include <grp.h> | |
6 #include <pwd.h> | |
7 #include <stdio.h> | |
8 #include <stdlib.h> | |
9 #include <string.h> | |
10 #include <unistd.h> | |
11 | |
12 #include "passwd.h" | |
13 #include "util.h" | |
14 | |
15 extern char **environ; | |
16 | |
17 static int lflag = 0; | |
18 static int pflag = 0; | |
19 | |
20 static void | |
21 usage(void) | |
22 { | |
23 eprintf("usage: %s [-lp] [username]\n", argv0); | |
24 } | |
25 | |
26 int | |
27 main(int argc, char *argv[]) | |
28 { | |
29 char *usr, *pass; | |
30 char *shell, *envshell, *term; | |
31 struct passwd *pw; | |
32 char *newargv[3]; | |
33 uid_t uid; | |
34 | |
35 ARGBEGIN { | |
36 case 'l': | |
37 lflag = 1; | |
38 break; | |
39 case 'p': | |
40 pflag = 1; | |
41 break; | |
42 default: | |
43 usage(); | |
44 } ARGEND; | |
45 | |
46 if (argc > 1) | |
47 usage(); | |
48 usr = argc > 0 ? argv[0] : "root"; | |
49 | |
50 errno = 0; | |
51 pw = getpwnam(usr); | |
52 if (!pw) { | |
53 if (errno) | |
54 eprintf("getpwnam: %s:", usr); | |
55 else | |
56 eprintf("who are you?\n"); | |
57 } | |
58 | |
59 uid = getuid(); | |
60 if (uid) { | |
61 pass = getpass("Password: "); | |
62 if (!pass) | |
63 eprintf("getpass:"); | |
64 if (pw_check(pw, pass) <= 0) | |
65 exit(1); | |
66 } | |
67 | |
68 if (initgroups(usr, pw->pw_gid) < 0) | |
69 eprintf("initgroups:"); | |
70 if (setgid(pw->pw_gid) < 0) | |
71 eprintf("setgid:"); | |
72 if (setuid(pw->pw_uid) < 0) | |
73 eprintf("setuid:"); | |
74 | |
75 shell = pw->pw_shell[0] == '\0' ? "/bin/sh" : pw->pw_shell; | |
76 if (lflag) { | |
77 term = getenv("TERM"); | |
78 clearenv(); | |
79 setenv("HOME", pw->pw_dir, 1); | |
80 setenv("SHELL", shell, 1); | |
81 setenv("USER", pw->pw_name, 1); | |
82 setenv("LOGNAME", pw->pw_name, 1); | |
83 setenv("TERM", term ? term : "linux", 1); | |
84 if (chdir(pw->pw_dir) < 0) | |
85 eprintf("chdir %s:", pw->pw_dir); | |
86 newargv[0] = shell; | |
87 newargv[1] = "-l"; | |
88 newargv[2] = NULL; | |
89 } else { | |
90 if (pflag) { | |
91 envshell = getenv("SHELL"); | |
92 if (envshell && envshell[0] != '\0') | |
93 shell = envshell; | |
94 } else { | |
95 setenv("HOME", pw->pw_dir, 1); | |
96 setenv("SHELL", shell, 1); | |
97 if (strcmp(pw->pw_name, "root") != 0) { | |
98 setenv("USER", pw->pw_name, 1); | |
99 setenv("LOGNAME", pw->pw_name, 1); | |
100 } | |
101 } | |
102 newargv[0] = shell; | |
103 newargv[1] = NULL; | |
104 } | |
105 execve(shell, newargv, environ); | |
106 weprintf("execve %s:", shell); | |
107 return (errno == ENOENT) ? 127 : 126; | |
108 } |