113736Ssam #ifndef lint 2*15633Sralph static char sccsid[] = "@(#)vipw.c 4.4 (Berkeley) 12/01/83"; 313736Ssam #endif 413736Ssam 513736Ssam #include <sys/types.h> 613736Ssam #include <sys/stat.h> 713736Ssam #include <sys/file.h> 813736Ssam 913736Ssam #include <stdio.h> 1013736Ssam #include <errno.h> 1113736Ssam #include <signal.h> 1213736Ssam 1313736Ssam /* 1413736Ssam * Password file editor with locking. 1513736Ssam */ 1613736Ssam char *temp = "/etc/ptmp"; 17*15633Sralph char *temp_pag = "/etc/ptmp.pag"; 18*15633Sralph char *temp_dir = "/etc/ptmp.dir"; 1913736Ssam char *passwd = "/etc/passwd"; 20*15633Sralph char *passwd_pag = "/etc/passwd.pag"; 21*15633Sralph char *passwd_dir = "/etc/passwd.dir"; 2213736Ssam char buf[BUFSIZ]; 2313736Ssam char *getenv(); 2413736Ssam char *index(); 2513736Ssam extern int errno; 2613736Ssam 2713736Ssam main(argc, argv) 2813736Ssam char *argv[]; 2913736Ssam { 3013736Ssam int fd; 3113736Ssam FILE *ft, *fp; 3213736Ssam char *editor; 3313736Ssam 3413736Ssam signal(SIGINT, SIG_IGN); 3513736Ssam signal(SIGQUIT, SIG_IGN); 3613736Ssam signal(SIGHUP, SIG_IGN); 3713736Ssam setbuf(stderr, NULL); 3814911Sralph umask(0); 3913736Ssam fd = open(temp, O_WRONLY|O_CREAT|O_EXCL, 0644); 4013736Ssam if (fd < 0) { 4113736Ssam if (errno == EEXIST) { 4213736Ssam fprintf(stderr, "vipw: password file busy\n"); 4313736Ssam exit(1); 4413736Ssam } 4513736Ssam fprintf(stderr, "vipw: "); perror(temp); 4613736Ssam exit(1); 4713736Ssam } 4813736Ssam ft = fdopen(fd, "w"); 4913736Ssam if (ft == NULL) { 5013736Ssam fprintf(stderr, "vipw: "); perror(temp); 5113736Ssam goto bad; 5213736Ssam } 5313736Ssam fp = fopen(passwd, "r"); 5413736Ssam if (fp == NULL) { 5513736Ssam fprintf(stderr, "vipw: "); perror(passwd); 5613736Ssam goto bad; 5713736Ssam } 5813736Ssam while (fgets(buf, sizeof (buf) - 1, fp) != NULL) 5913736Ssam fputs(buf, ft); 6013736Ssam fclose(ft); fclose(fp); 6113736Ssam editor = getenv("EDITOR"); 6213736Ssam if (editor == 0) 6313736Ssam editor = "vi"; 6413736Ssam sprintf(buf, "%s %s", editor, temp); 6513736Ssam if (system(buf) == 0) { 6613736Ssam struct stat sbuf; 6713736Ssam int ok; 6813736Ssam 6913736Ssam /* sanity checks */ 7013736Ssam if (stat(temp, &sbuf) < 0) { 7113736Ssam fprintf(stderr, 7213736Ssam "vipw: can't stat temp file, %s unchanged\n", 7313736Ssam passwd); 7413736Ssam goto bad; 7513736Ssam } 7613736Ssam if (sbuf.st_size == 0) { 7713736Ssam fprintf(stderr, "vipw: bad temp file, %s unchanged\n", 7813736Ssam passwd); 7913736Ssam goto bad; 8013736Ssam } 8113736Ssam ft = fopen(temp, "r"); 8213736Ssam if (ft == NULL) { 8313736Ssam fprintf(stderr, 8413736Ssam "vipw: can't reopen temp file, %s unchanged\n", 8513736Ssam passwd); 8613736Ssam goto bad; 8713736Ssam } 8813736Ssam ok = 0; 8913736Ssam while (fgets(buf, sizeof (buf) - 1, ft) != NULL) { 9013736Ssam register char *cp; 9113736Ssam 9213736Ssam cp = index(buf, '\n'); 9313736Ssam if (cp == 0) 9413736Ssam continue; 9513736Ssam *cp = '\0'; 9613736Ssam cp = index(buf, ':'); 9713736Ssam if (cp == 0) 9813736Ssam continue; 9913736Ssam *cp = '\0'; 10013736Ssam if (strcmp(buf, "root")) 10113736Ssam continue; 10213736Ssam /* password */ 10313736Ssam cp = index(cp + 1, ':'); 10413736Ssam if (cp == 0) 10513736Ssam break; 10613736Ssam /* uid */ 10713736Ssam if (atoi(cp + 1) != 0) 10813736Ssam break; 10913736Ssam cp = index(cp + 1, ':'); 11013736Ssam if (cp == 0) 11113736Ssam break; 11213736Ssam /* gid */ 11313736Ssam cp = index(cp + 1, ':'); 11413736Ssam if (cp == 0) 11513736Ssam break; 11613736Ssam /* gecos */ 11713736Ssam cp = index(cp + 1, ':'); 11813736Ssam if (cp == 0) 11913736Ssam break; 12013736Ssam /* login directory */ 12113736Ssam if (strncmp(++cp, "/:")) 12213736Ssam break; 12313736Ssam cp += 2; 12413736Ssam if (*cp && strcmp(cp, "/bin/sh") && 12513736Ssam strcmp(cp, "/bin/csh")) 12613736Ssam break; 12713736Ssam ok++; 12813736Ssam } 12913736Ssam fclose(ft); 13013736Ssam if (ok) { 131*15633Sralph if (makedb(temp) < 0) 132*15633Sralph fprintf(stderr, "vipw: mkpasswd failed\n"); 133*15633Sralph else if (rename(temp_pag, passwd_pag) < 0) 134*15633Sralph fprintf(stderr, "vipw: "), perror(temp_pag); 135*15633Sralph else if (rename(temp_dir, passwd_dir) < 0) 136*15633Sralph fprintf(stderr, "vipw: "), perror(temp_dir); 137*15633Sralph else if (rename(temp, passwd) < 0) 13813736Ssam fprintf(stderr, "vipw: "), perror("rename"); 13915166Sralph else 14015166Sralph exit(0); 14113736Ssam } else 14213736Ssam fprintf(stderr, 14313736Ssam "vipw: you mangled the temp file, %s unchanged\n", 14413736Ssam passwd); 14513736Ssam } 14613736Ssam bad: 14713736Ssam unlink(temp); 14815166Sralph exit(1); 14913736Ssam } 150*15633Sralph 151*15633Sralph makedb(file) 152*15633Sralph char *file; 153*15633Sralph { 154*15633Sralph int status, pid, w; 155*15633Sralph 156*15633Sralph if ((pid = vfork()) == 0) { 157*15633Sralph execl("/etc/mkpasswd", "mkpasswd", file, 0); 158*15633Sralph _exit(127); 159*15633Sralph } 160*15633Sralph while ((w = wait(&status)) != pid && w != -1) 161*15633Sralph ; 162*15633Sralph if (w == -1 || status != 0) 163*15633Sralph status = -1; 164*15633Sralph return(status); 165*15633Sralph } 166