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 }