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 }