utmp

simple login manager
git clone git://git.suckless.org/utmp
Log | Files | Refs | README | LICENSE

utmp.c (1737B)


      1 
      2 
      3 #include <errno.h>
      4 #include <stdarg.h>
      5 #include <stdlib.h>
      6 #include <stdio.h>
      7 #include <string.h>
      8 #include <signal.h>
      9 
     10 #include <sys/types.h>
     11 #include <unistd.h>
     12 #include <pwd.h>
     13 #include <grp.h>
     14 #include <sys/wait.h>
     15 
     16 
     17 struct passwd *pw;
     18 gid_t egid, gid;
     19 
     20 
     21 void
     22 die(const char *fmt, ...)
     23 {
     24 	va_list va;
     25 	va_start(va, fmt);
     26 	vfprintf(stderr, fmt, va);
     27 	putc('\n', stderr);
     28 	va_end(va);
     29 	exit(EXIT_FAILURE);
     30 }
     31 
     32 int
     33 main(int argc, char *argv[])
     34 {
     35 	int status;
     36 	size_t len;
     37 	uid_t uid;
     38 	sigset_t set;
     39 	char *p, argv0[FILENAME_MAX], *sh;
     40 	extern void addutmp(void), delutmp(void);
     41 
     42 	egid = getegid();
     43 	gid = getgid();
     44 	setgid(gid);
     45 
     46 	errno = 0;
     47 	if ((pw = getpwuid(uid = getuid())) == NULL) {
     48 		if(errno)
     49 			die("utmp:getpwuid:%s", strerror(errno));
     50 		else
     51 			die("utmp:who are you?");
     52 	}
     53 
     54 	setenv("LOGNAME", pw->pw_name, 1);
     55 	setenv("USER", pw->pw_name, 1);
     56 	setenv("SHELL", pw->pw_shell, 1);
     57 	setenv("HOME", pw->pw_dir, 1);
     58 
     59 	if ((p = strrchr(pw->pw_shell, '/')) == NULL)
     60 		die("incorrect shell field of passwd");
     61 	if ((len = strlen(++p)) > sizeof(argv0) - 2)
     62 		die("shell name too long");
     63 	argv0[0] = '-';
     64 	memcpy(&argv0[1], p, len);
     65 
     66 	sigfillset(&set);
     67 	sigprocmask(SIG_BLOCK, &set, NULL);
     68 
     69 	switch (fork()) {
     70 	case 0:
     71 		sigprocmask(SIG_UNBLOCK, &set, NULL);
     72 		sh = pw->pw_shell;
     73 		argv[0] = argv0;
     74 		execv(sh, argv);
     75 		die("error executing shell(%s):%s", sh, strerror(errno));
     76 	case -1:
     77 		die("error spawning child:%s", strerror(errno));
     78 	default:
     79 		addutmp();
     80 		signal(SIGINT, SIG_IGN);
     81 		signal(SIGTERM, SIG_IGN);
     82 		signal(SIGHUP, SIG_IGN);
     83 		sigprocmask(SIG_UNBLOCK, &set, NULL);
     84 
     85 		if (wait(&status) == -1)
     86 			perror("utmp:error waiting child");
     87 		delutmp();
     88 	}
     89 	return (WIFEXITED(status)) ? WEXITSTATUS(status) : EXIT_FAILURE;
     90 }