master xplshn/aruu / cmd / pseudo / login.c
  1/* See LICENSE file for copyright and license details. */
  2
  3#include <sys/ioctl.h>
  4#include <sys/types.h>
  5
  6#include <errno.h>
  7#include <grp.h>
  8#include <pwd.h>
  9#include <stdio.h>
 10#include <stdlib.h>
 11#include <string.h>
 12#include <time.h>
 13#include <unistd.h>
 14#include <utmp.h>
 15
 16#include "config.h"
 17#include "passwd.h"
 18#include "util.h"
 19#include "wexec.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  wexecvp_self(shell, (char *const[]){shell, "-l", NULL});
 62  weprintf("wexecvp %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  {
 87    // ?man -p: preserve file attributes
 88    case 'p':
 89      pflag = 1;
 90      break;
 91    default:
 92      usage();
 93  }
 94  ARGEND;
 95
 96  if (argc < 1)
 97    usage();
 98
 99  if (isatty(0) == 0 || isatty(1) == 0 || isatty(2) == 0)
100    eprintf("no tty");
101
102  user  = argv[0];
103  errno = 0;
104  pw    = getpwnam(user);
105  if (!pw) {
106    if (errno)
107      eprintf("getpwnam %s:", user);
108    else
109      eprintf("who are you?\n");
110  }
111
112  uid = pw->pw_uid;
113  gid = pw->pw_gid;
114
115  /* Flush pending input */
116  ioctl(0, TCFLSH, (void *)0);
117
118  pass = getpass("Password: ");
119  if (!pass)
120    eprintf("getpass:");
121  if (pw_check(pw, pass) <= 0)
122    exit(1);
123
124  tty = ttyname(0);
125  if (!tty)
126    eprintf("ttyname:");
127
128  writeutmp(user, tty);
129
130  if (initgroups(user, gid) < 0)
131    eprintf("initgroups:");
132  if (setgid(gid) < 0)
133    eprintf("setgid:");
134  if (setuid(uid) < 0)
135    eprintf("setuid:");
136
137  return dologin(pw, pflag);
138}