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