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 }