1: /*
   2:  * Copyright (c) 1987 Regents of the University of California.
   3:  * All rights reserved.
   4:  *
   5:  * Redistribution and use in source and binary forms are permitted
   6:  * provided that the above copyright notice and this paragraph are
   7:  * duplicated in all such forms and that any documentation,
   8:  * advertising materials, and other materials related to such
   9:  * distribution and use acknowledge that the software was developed
  10:  * by the University of California, Berkeley.  The name of the
  11:  * University may not be used to endorse or promote products derived
  12:  * from this software without specific prior written permission.
  13:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15:  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16:  */
  17: 
  18: #if !defined(lint) && defined(DOSCCS)
  19: char copyright[] =
  20: "@(#) Copyright (c) 1987 Regents of the University of California.\n\
  21:  All rights reserved.\n";
  22: 
  23: static char sccsid[] = "@(#)vipw.c	5.9.1 (2.11BSD) 1996/1/12";
  24: #endif /* not lint */
  25: 
  26: #include <sys/param.h>
  27: #include <sys/stat.h>
  28: #include <sys/signal.h>
  29: #include <sys/file.h>
  30: #include <sys/time.h>
  31: #include <sys/resource.h>
  32: #include <errno.h>
  33: #include <pwd.h>
  34: #include <stdio.h>
  35: #include <strings.h>
  36: #include <stdlib.h>
  37: 
  38: char *passwd, *temp;
  39: 
  40: main()
  41: {
  42:     register int n, fd_passwd, fd;
  43:     struct rlimit rlim;
  44:     struct stat s1, s2;
  45:     FILE *tfp;
  46:     char *fend, *tend;
  47:     char buf[1024], from[MAXPATHLEN], to[MAXPATHLEN];
  48: 
  49:     (void)signal(SIGHUP, SIG_IGN);
  50:     (void)signal(SIGINT, SIG_IGN);
  51:     (void)signal(SIGQUIT, SIG_IGN);
  52:     (void)signal(SIGTSTP, SIG_IGN);
  53: 
  54:     rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
  55:     (void)setrlimit(RLIMIT_CPU, &rlim);
  56:     (void)setrlimit(RLIMIT_FSIZE, &rlim);
  57: 
  58:     (void)umask(0);
  59: 
  60:     temp = _PATH_PTMP;
  61:     if ((fd = open(temp, O_RDWR|O_CREAT|O_EXCL, 0600)) < 0) {
  62:         if (errno == EEXIST)
  63:             (void)fprintf(stderr, "vipw: password file busy.\n");
  64:         else
  65:             (void)fprintf(stderr,
  66:                 "vipw: %s: %s\n", temp, strerror(errno));
  67:         exit(1);
  68:     }
  69:     passwd = _PATH_MASTERPASSWD;
  70:     if ((fd_passwd = open(passwd, O_RDONLY, 0)) < 0) {
  71:         (void)fprintf(stderr, "vipw: %s: %s\n", passwd,
  72:             strerror(errno));
  73:         exit(1);
  74:     }
  75:     while ((n = read(fd_passwd, buf, sizeof(buf))) > 0)
  76:         if (write(fd, buf, n) != n)
  77:             goto syserr;
  78: 
  79:     if (n == -1 || close(fd_passwd)) {
  80: syserr:     (void)fprintf(stderr, "vipw: %s: %s; ",
  81:             passwd, strerror(errno));
  82:         stop(1);
  83:     }
  84:     if (!(tfp = fdopen(fd, "r"))) {
  85:         (void)fprintf(stderr, "vipw: %s: %s; ",
  86:             temp, strerror(errno));
  87:         stop(1);
  88:     }
  89: 
  90:     for (;;) {
  91:         (void)fstat(fd, &s1);
  92:         if (edit()) {
  93:             (void)fprintf(stderr, "vipw: edit failed; ");
  94:             stop(1);
  95:         }
  96:         (void)fstat(fd, &s2);
  97:         if (s1.st_mtime == s2.st_mtime) {
  98:             (void)fprintf(stderr, "vipw: no changes made; ");
  99:             stop(0);
 100:         }
 101:         rewind(tfp);
 102:         if (!check(tfp))
 103:             break;
 104:         if (prompt())
 105:             stop(0);
 106:     }
 107: 
 108:     switch(fork()) {
 109:     case 0:
 110:         break;
 111:     case -1:
 112:         (void)fprintf(stderr, "vipw: can't fork; ");
 113:         stop(1);
 114:         /* NOTREACHED */
 115:     default:
 116:         exit(0);
 117:         /* NOTREACHED */
 118:     }
 119: 
 120:     if (makedb(temp)) {
 121:         (void)fprintf(stderr, "vipw: mkpasswd failed; ");
 122:         stop(1);
 123:     }
 124: 
 125:     /*
 126: 	 * possible race; have to rename four files, and someone could slip
 127: 	 * in between them.  LOCK_EX and rename the ``passwd.dir'' file first
 128: 	 * so that getpwent(3) can't slip in; the lock should never fail and
 129: 	 * it's unclear what to do if it does.  Rename ``ptmp'' last so that
 130: 	 * passwd/vipw/chpass can't slip in.
 131: 	 */
 132:     (void)setpriority(PRIO_PROCESS, 0, -20);
 133:     fend = strcpy(from, temp) + strlen(temp);
 134:     tend = strcpy(to, _PATH_PASSWD) + strlen(_PATH_PASSWD);
 135:     bcopy(".dir", fend, 5);
 136:     bcopy(".dir", tend, 5);
 137:     if ((fd = open(from, O_RDONLY, 0)) >= 0)
 138:         (void)flock(fd, LOCK_EX);
 139:     /* here we go... */
 140:     (void)rename(from, to);
 141:     bcopy(".pag", fend, 5);
 142:     bcopy(".pag", tend, 5);
 143:     (void)rename(from, to);
 144:     bcopy(".orig", fend, 6);
 145:     (void)rename(from, _PATH_PASSWD);
 146:     (void)rename(temp, passwd);
 147:     /* done! */
 148:     exit(0);
 149: }
 150: 
 151: check(tfp)
 152:     FILE *tfp;
 153: {
 154:     long id;
 155:     int root;
 156:     register int lcnt;
 157:     register char *p, *sh;
 158:     char buf[256], *getusershell();
 159:     char *bp;
 160: 
 161:     for (lcnt = 1; fgets(buf, sizeof(buf), tfp); ++lcnt) {
 162:         bp = buf;
 163:         /* skip lines that are too big */
 164:         if (!(p = index(buf, '\n'))) {
 165:             (void)fprintf(stderr, "vipw: line too long");
 166:             goto bad;
 167:         }
 168:         *p = '\0';
 169:         if (!(p = strsep(&bp, ":")))    /* login */
 170:             goto general;
 171:         root = !strcmp(p, "root");
 172:         (void)strsep(&bp, ":");     /* passwd */
 173:         if (!(p = strsep(&bp, ":")))    /* uid */
 174:             goto general;
 175:         id = atol(p);
 176:         if (root && id) {
 177:             (void)fprintf(stderr, "vipw: root uid should be 0");
 178:             goto bad;
 179:         }
 180:         if (id > USHRT_MAX) {
 181:             (void)fprintf(stderr, "vipw: %s > max uid value (%u)",
 182:                 p, USHRT_MAX);
 183:             goto bad;
 184:         }
 185:         if (!(p = strsep(&bp, ":")))    /* gid */
 186:             goto general;
 187:         id = atol(p);
 188:         if (id > USHRT_MAX) {
 189:             (void)fprintf(stderr, "vipw: %s > max gid value (%u)",
 190:                 p, USHRT_MAX);
 191:             goto bad;
 192:         }
 193:         (void)strsep(&bp, ":");     /* class */
 194:         (void)strsep(&bp, ":");     /* change */
 195:         (void)strsep(&bp, ":");     /* expire */
 196:         (void)strsep(&bp, ":");     /* gecos */
 197:         (void)strsep(&bp, ":");     /* directory */
 198:         if (!(p = strsep(&bp, ":")))    /* shell */
 199:             goto general;
 200:         if (root && *p)             /* empty == /bin/sh */
 201:             for (setusershell();;)
 202:                 if (!(sh = getusershell())) {
 203:                     (void)fprintf(stderr,
 204:                         "vipw: warning, unknown root shell.\n");
 205:                     break;
 206:                 }
 207:                 else if (!strcmp(p, sh))
 208:                     break;
 209:         if (strsep(&bp, ":")) { /* too many */
 210: general:        (void)fprintf(stderr, "vipw: corrupted entry");
 211: bad:            (void)fprintf(stderr, "; line #%d.\n", lcnt);
 212:             (void)fflush(stderr);
 213:             return(1);
 214:         }
 215:     }
 216:     return(0);
 217: }
 218: 
 219: makedb(file)
 220:     char *file;
 221: {
 222:     int status, pid, w;
 223: 
 224:     if (!(pid = vfork())) {
 225:         execl(_PATH_MKPASSWD, "mkpasswd", "-p", file, NULL);
 226:         _exit(127);
 227:     }
 228:     while ((w = wait(&status)) != pid && w != -1);
 229:     return(w == -1 || status);
 230: }
 231: 
 232: edit()
 233: {
 234:     int status, pid, w;
 235:     char *p, *editor;
 236: 
 237:     if (editor = getenv("EDITOR")) {
 238:         if (p = rindex(editor, '/'))
 239:             ++p;
 240:         else
 241:             p = editor;
 242:     }
 243:     else
 244:         p = editor = "vi";
 245:     if (!(pid = vfork())) {
 246:         execlp(editor, p, temp, NULL);
 247:         (void)fprintf(stderr, "vipw: %s: %s\n", editor,
 248:             strerror(errno));
 249:         _exit(127);
 250:     }
 251:     while ((w = wait(&status)) != pid && w != -1);
 252:     return(w == -1 || status);
 253: }
 254: 
 255: prompt()
 256: {
 257:     register int c;
 258: 
 259:     for (;;) {
 260:         (void)printf("re-edit the password file? [y]: ");
 261:         (void)fflush(stdout);
 262:         c = getchar();
 263:         if (c != EOF && c != (int)'\n')
 264:             while (getchar() != (int)'\n');
 265:         return(c == (int)'n');
 266:     }
 267:     /* NOTREACHED */
 268: }
 269: 
 270: stop(val)
 271:     int val;
 272: {
 273:     (void)fprintf(stderr, "%s unchanged.\n", passwd);
 274:     (void)unlink(temp);
 275:     exit(val);
 276: }

Defined functions

check defined in line 151; used 1 times
edit defined in line 232; used 1 times
  • in line 92
main defined in line 40; never used
makedb defined in line 219; used 1 times
prompt defined in line 255; used 1 times
stop defined in line 270; used 7 times

Defined variables

copyright defined in line 19; never used
passwd defined in line 38; used 6 times
sccsid defined in line 23; never used
temp defined in line 38; used 10 times
Last modified: 1996-01-13
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 996
Valid CSS Valid XHTML 1.0 Strict