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