login.c - ubase - suckless linux base utils
HTML git clone git://git.suckless.org/ubase
DIR Log
DIR Files
DIR Refs
DIR README
DIR LICENSE
---
login.c (2363B)
---
1 /* See LICENSE file for copyright and license details. */
2 #include <sys/ioctl.h>
3 #include <sys/types.h>
4
5 #include <errno.h>
6 #include <grp.h>
7 #include <pwd.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <time.h>
12 #include <unistd.h>
13 #include <utmp.h>
14
15 #include "config.h"
16 #include "passwd.h"
17 #include "util.h"
18
19 /* Write utmp entry */
20 static void
21 writeutmp(const char *user, const char *tty)
22 {
23 struct utmp usr;
24 FILE *fp;
25
26 memset(&usr, 0, sizeof(usr));
27
28 usr.ut_type = USER_PROCESS;
29 usr.ut_pid = getpid();
30 strlcpy(usr.ut_user, user, sizeof(usr.ut_user));
31 strlcpy(usr.ut_line, tty, sizeof(usr.ut_line));
32 usr.ut_tv.tv_sec = time(NULL);
33
34 fp = fopen(UTMP_PATH, "a");
35 if (fp) {
36 if (fwrite(&usr, sizeof(usr), 1, fp) != 1)
37 if (ferror(fp))
38 weprintf("%s: write error:", UTMP_PATH);
39 fclose(fp);
40 } else {
41 weprintf("fopen %s:", UTMP_PATH);
42 }
43 }
44
45 static int
46 dologin(struct passwd *pw, int preserve)
47 {
48 char *shell = pw->pw_shell[0] == '\0' ? "/bin/sh" : pw->pw_shell;
49
50 if (preserve == 0)
51 clearenv();
52 setenv("HOME", pw->pw_dir, 1);
53 setenv("SHELL", shell, 1);
54 setenv("USER", pw->pw_name, 1);
55 setenv("LOGNAME", pw->pw_name, 1);
56 setenv("PATH", ENV_PATH, 1);
57 if (chdir(pw->pw_dir) < 0)
58 eprintf("chdir %s:", pw->pw_dir);
59 execlp(shell, shell, "-l", NULL);
60 weprintf("execlp %s:", shell);
61 return (errno == ENOENT) ? 127 : 126;
62 }
63
64 static void
65 usage(void)
66 {
67 eprintf("usage: %s [-p] username\n", argv0);
68 }
69
70 int
71 main(int argc, char *argv[])
72 {
73 struct passwd *pw;
74 char *pass, *user;
75 char *tty;
76 uid_t uid;
77 gid_t gid;
78 int pflag = 0;
79
80 ARGBEGIN {
81 case 'p':
82 pflag = 1;
83 break;
84 default:
85 usage();
86 } ARGEND;
87
88 if (argc < 1)
89 usage();
90
91 if (isatty(0) == 0 || isatty(1) == 0 || isatty(2) == 0)
92 eprintf("no tty");
93
94 user = argv[0];
95 errno = 0;
96 pw = getpwnam(user);
97 if (!pw) {
98 if (errno)
99 eprintf("getpwnam %s:", user);
100 else
101 eprintf("who are you?\n");
102 }
103
104 uid = pw->pw_uid;
105 gid = pw->pw_gid;
106
107 /* Flush pending input */
108 ioctl(0, TCFLSH, (void *)0);
109
110 pass = getpass("Password: ");
111 if (!pass)
112 eprintf("getpass:");
113 if (pw_check(pw, pass) <= 0)
114 exit(1);
115
116 tty = ttyname(0);
117 if (!tty)
118 eprintf("ttyname:");
119
120 writeutmp(user, tty);
121
122 if (initgroups(user, gid) < 0)
123 eprintf("initgroups:");
124 if (setgid(gid) < 0)
125 eprintf("setgid:");
126 if (setuid(uid) < 0)
127 eprintf("setuid:");
128
129 return dologin(pw, pflag);
130 }