1 /*- 2 * Copyright (c) 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)pw_util.c 5.1 (Berkeley) 02/12/91"; 10 #endif /* not lint */ 11 12 /* 13 * This file is used by all the "password" programs; vipw(8), chpass(1), 14 * and passwd(1). 15 */ 16 17 #include <sys/param.h> 18 #include <sys/wait.h> 19 #include <sys/time.h> 20 #include <sys/resource.h> 21 #include <signal.h> 22 #include <fcntl.h> 23 #include <pwd.h> 24 #include <errno.h> 25 #include <stdio.h> 26 #include <paths.h> 27 #include <string.h> 28 #include <stdlib.h> 29 30 extern char *progname; 31 extern char *tempname; 32 33 pw_init() 34 { 35 struct rlimit rlim; 36 sigset_t set; 37 38 /* Unlimited cpu, file size. */ 39 rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY; 40 (void)setrlimit(RLIMIT_CPU, &rlim); 41 (void)setrlimit(RLIMIT_FSIZE, &rlim); 42 43 /* Don't drop core (not really necessary, but GP's). */ 44 rlim.rlim_cur = rlim.rlim_max = 0; 45 (void)setrlimit(RLIMIT_CORE, &rlim); 46 47 /* Turn off usual signals. */ 48 sigemptyset(&set); 49 (void)sigaddset(&set, SIGTSTP); 50 (void)sigaddset(&set, SIGHUP); 51 (void)sigaddset(&set, SIGINT); 52 (void)sigaddset(&set, SIGQUIT); 53 (void)sigaddset(&set, SIGTERM); 54 (void)sigprocmask(SIG_BLOCK, &set, (sigset_t *)NULL); 55 56 /* Create with exact permissions. */ 57 (void)umask(0); 58 } 59 60 static int lockfd; 61 pw_lock() 62 { 63 /* 64 * If the master password file doesn't exist, the system is hosed. 65 * Might as well try to build one. 66 * Open should allow flock'ing the file; see 4.4BSD. XXX 67 */ 68 lockfd = open(_PATH_MASTERPASSWD, O_RDONLY, 0); 69 if (lockfd < 0) { 70 (void)fprintf(stderr, "%s: %s: %s\n", 71 progname, _PATH_MASTERPASSWD, strerror(errno)); 72 exit(1); 73 } 74 if (flock(lockfd, LOCK_EX)) { 75 (void)fprintf(stderr, 76 "%s: the password db is busy.\n", progname); 77 exit(1); 78 } 79 return(lockfd); 80 } 81 82 pw_tmp() 83 { 84 static char path[MAXPATHLEN] = _PATH_MASTERPASSWD; 85 int fd; 86 char *p; 87 88 if (p = rindex(path, '/')) 89 ++p; 90 else 91 p = path; 92 (void)sprintf(p, "%s.XXXXXX", progname); 93 if ((fd = mkstemp(path)) == -1) { 94 (void)fprintf(stderr, 95 "%s: %s: %s\n", progname, path, strerror(errno)); 96 exit(1); 97 } 98 tempname = path; 99 return(fd); 100 } 101 102 pw_mkdb() 103 { 104 union wait pstat; 105 pid_t pid; 106 107 (void)printf("%s: rebuilding the database...\n", progname); 108 (void)fflush(stdout); 109 if (!(pid = vfork())) { 110 execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", tempname, NULL); 111 pw_error(_PATH_PWD_MKDB, 1, 1); 112 } 113 pid = waitpid(pid, (int *)&pstat, 0); 114 if (pid == -1 || pstat.w_status) 115 return(0); 116 (void)printf("%s: done\n", progname); 117 return(1); 118 } 119 120 pw_edit(notsetuid) 121 int notsetuid; 122 { 123 union wait pstat; 124 pid_t pid; 125 char *p, *editor; 126 127 if (!(editor = getenv("EDITOR"))) 128 editor = _PATH_VI; 129 if (p = rindex(editor, '/')) 130 ++p; 131 else 132 p = editor; 133 134 if (!(pid = vfork())) { 135 if (notsetuid) { 136 (void)setgid(getgid()); 137 (void)setuid(getuid()); 138 } 139 execlp(editor, p, tempname, NULL); 140 pw_error(editor, 1, 1); 141 } 142 pid = waitpid(pid, (int *)&pstat, 0); 143 return (pid == -1 ? 1 : pstat.w_status); 144 } 145 146 pw_prompt() 147 { 148 register int c; 149 150 for (;;) { 151 (void)printf("re-edit the password file? [y]: "); 152 (void)fflush(stdout); 153 c = getchar(); 154 if (c != EOF && c != (int)'\n') 155 while (getchar() != (int)'\n'); 156 if (c == (int)'n') 157 pw_error((char *)NULL, 0, 0); 158 break; 159 } 160 } 161 162 pw_error(name, err, eval) 163 char *name; 164 int err, eval; 165 { 166 int sverrno; 167 168 if (err) { 169 sverrno = errno; 170 (void)fprintf(stderr, "%s: ", progname); 171 if (name) 172 (void)fprintf(stderr, "%s: ", name); 173 (void)fprintf(stderr, "%s\n", strerror(sverrno)); 174 } 175 (void)fprintf(stderr, 176 "%s: %s unchanged\n", progname, _PATH_MASTERPASSWD); 177 (void)unlink(tempname); 178 exit(eval); 179 } 180