su.c - ubase - suckless linux base utils
(HTM) git clone git://git.suckless.org/ubase
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) 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 }