utmp.c - utmp - simple login manager  
 (HTM) git clone git://git.suckless.org/utmp
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) 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 }