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 }