morpheus-base

morpheus base system
git clone git://git.2f30.org/morpheus-base
Log | Files | Refs

login.c (2406B)


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