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