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 }