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