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.4 (Berkeley) 05/21/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 37 /* Unlimited resource limits. */ 38 rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY; 39 (void)setrlimit(RLIMIT_CPU, &rlim); 40 (void)setrlimit(RLIMIT_FSIZE, &rlim); 41 (void)setrlimit(RLIMIT_STACK, &rlim); 42 (void)setrlimit(RLIMIT_DATA, &rlim); 43 (void)setrlimit(RLIMIT_RSS, &rlim); 44 45 /* Don't drop core (not really necessary, but GP's). */ 46 rlim.rlim_cur = rlim.rlim_max = 0; 47 (void)setrlimit(RLIMIT_CORE, &rlim); 48 49 /* Turn off signals. */ 50 (void)signal(SIGALRM, SIG_IGN); 51 (void)signal(SIGHUP, SIG_IGN); 52 (void)signal(SIGINT, SIG_IGN); 53 (void)signal(SIGPIPE, SIG_IGN); 54 (void)signal(SIGQUIT, SIG_IGN); 55 (void)signal(SIGTERM, SIG_IGN); 56 (void)signal(SIGTSTP, SIG_IGN); 57 (void)signal(SIGTTOU, SIG_IGN); 58 59 /* Create with exact permissions. */ 60 (void)umask(0); 61 } 62 63 static int lockfd; 64 pw_lock() 65 { 66 /* 67 * If the master password file doesn't exist, the system is hosed. 68 * Might as well try to build one. 69 * Open should allow flock'ing the file; see 4.4BSD. XXX 70 */ 71 lockfd = open(_PATH_MASTERPASSWD, O_RDONLY, 0); 72 if (lockfd < 0) { 73 (void)fprintf(stderr, "%s: %s: %s\n", 74 progname, _PATH_MASTERPASSWD, strerror(errno)); 75 exit(1); 76 } 77 if (flock(lockfd, LOCK_EX|LOCK_NB)) { 78 (void)fprintf(stderr, 79 "%s: the password db is busy.\n", progname); 80 exit(1); 81 } 82 return(lockfd); 83 } 84 85 pw_tmp() 86 { 87 static char path[MAXPATHLEN] = _PATH_MASTERPASSWD; 88 int fd; 89 char *p; 90 91 if (p = rindex(path, '/')) 92 ++p; 93 else 94 p = path; 95 (void)sprintf(p, "%s.XXXXXX", progname); 96 if ((fd = mkstemp(path)) == -1) { 97 (void)fprintf(stderr, 98 "%s: %s: %s\n", progname, path, strerror(errno)); 99 exit(1); 100 } 101 tempname = path; 102 return(fd); 103 } 104 105 pw_mkdb() 106 { 107 union wait pstat; 108 pid_t pid; 109 110 (void)printf("%s: rebuilding the database...\n", progname); 111 (void)fflush(stdout); 112 if (!(pid = vfork())) { 113 execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", tempname, NULL); 114 pw_error(_PATH_PWD_MKDB, 1, 1); 115 } 116 pid = waitpid(pid, (int *)&pstat, 0); 117 if (pid == -1 || pstat.w_status) 118 return(0); 119 (void)printf("%s: done\n", progname); 120 return(1); 121 } 122 123 pw_edit(notsetuid) 124 int notsetuid; 125 { 126 union wait pstat; 127 pid_t pid; 128 char *p, *editor; 129 130 if (!(editor = getenv("EDITOR"))) 131 editor = _PATH_VI; 132 if (p = rindex(editor, '/')) 133 ++p; 134 else 135 p = editor; 136 137 if (!(pid = vfork())) { 138 if (notsetuid) { 139 (void)setgid(getgid()); 140 (void)setuid(getuid()); 141 } 142 execlp(editor, p, tempname, NULL); 143 _exit(1); 144 } 145 pid = waitpid(pid, (int *)&pstat, 0); 146 if (pid == -1 || pstat.w_status) 147 pw_error(editor, 1, 1); 148 } 149 150 pw_prompt() 151 { 152 register int c; 153 154 for (;;) { 155 (void)printf("re-edit the password file? [y]: "); 156 (void)fflush(stdout); 157 c = getchar(); 158 if (c != EOF && c != (int)'\n') 159 while (getchar() != (int)'\n'); 160 if (c == (int)'n') 161 pw_error((char *)NULL, 0, 0); 162 break; 163 } 164 } 165 166 pw_error(name, err, eval) 167 char *name; 168 int err, eval; 169 { 170 int sverrno; 171 172 if (err) { 173 sverrno = errno; 174 (void)fprintf(stderr, "%s: ", progname); 175 if (name) 176 (void)fprintf(stderr, "%s: ", name); 177 (void)fprintf(stderr, "%s\n", strerror(sverrno)); 178 } 179 (void)fprintf(stderr, 180 "%s: %s unchanged\n", progname, _PATH_MASTERPASSWD); 181 (void)unlink(tempname); 182 exit(eval); 183 } 184