master xplshn/aruu / cmd / pseudo / login.c
  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}