ubase

suckless linux base utils
git clone git@git.2f30.org/ubase.git
Log | Files | Refs | README | 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 }