home | blog | art | now | git gpg | email | rss

nndm

nndm's not a display manager
git clone https://pollux.codes/git/nndm.git
Log | Files | Refs | README | LICENSE

nndm.c (1696B)


      1 #include <errno.h>
      2 #include <grp.h>
      3 #include <pwd.h>
      4 #include <stdarg.h>
      5 #include <stdio.h>
      6 #include <stdlib.h>
      7 #include <string.h>
      8 #include <sys/types.h>
      9 #include <unistd.h>
     10 
     11 void
     12 die(const char *fmt, ...) {
     13 	va_list ap;
     14 
     15 	va_start(ap, fmt);
     16 	vfprintf(stderr, fmt, ap);
     17 	va_end(ap);
     18 	exit(1);
     19 }
     20 
     21 int
     22 main(int argc, char **argv) {
     23 
     24 	// Check arguments
     25 	if(argc < 3)
     26 		die("Usage: nndm <user> <command> <args> ...");
     27 
     28 	char * user = argv[1];
     29 	char ** cmd = malloc((argc - 1) * sizeof(char *));
     30 	memcpy(cmd, &argv[2], (argc - 2) * sizeof(char *));
     31 	cmd[argc - 2] = NULL;
     32 
     33 	// Drop privileges
     34 	struct passwd *pwd;
     35 	uid_t uid;
     36 	gid_t gid;
     37 	char env[5][256] = {"HOME=", "SHELL=", "PATH=", "LOGNAME=", "USER="};
     38 
     39 	char *path = getenv("PATH");
     40 
     41 	if(!(pwd = getpwnam(user))) die("Couldn't find user: %s\n", strerror(errno));
     42 	uid = pwd->pw_uid;
     43 	gid = pwd->pw_gid;
     44 
     45 	strcat(env[0], pwd->pw_dir);
     46 	strcat(env[1], pwd->pw_shell);
     47 	strcat(env[2], path);
     48 	strcat(env[3], user);
     49 	strcat(env[4], user);
     50 
     51 	int ngroups = 16;
     52 	gid_t * groups = malloc(ngroups * sizeof(gid_t *));
     53 	if(getgrouplist(user, gid, groups, &ngroups) < 0) {
     54 		groups = realloc(groups, ngroups * sizeof(gid_t *));
     55 		(void) getgrouplist(user, gid, groups, &ngroups);
     56 	}
     57 
     58 	if(setgroups(ngroups, groups) < 0) die("Couldn't set groups: %s\n", strerror(errno));
     59 	if(setgid(gid) < 0) die("Couldn't set gid: %s\n", strerror(errno));
     60 	if(setuid(uid) < 0) die("Couldn't set uid: %s\n", strerror(errno));
     61 
     62 	if(chdir(pwd->pw_dir) < 0) die("Couldn't set working directory: %s\n", strerror(errno));
     63 
     64 	execvpe(cmd[0], (char **)cmd, (char *[6]){env[0], env[1], env[2], env[3], env[4], NULL});
     65 
     66 	die("Couldn't execve %s: %s\n", cmd[0], strerror(errno));
     67 }