1*13736Ssam #ifndef lint 2*13736Ssam static char sccsid[] = "@(#)vipw.c 4.1 (Berkeley) 07/03/83"; 3*13736Ssam #endif 4*13736Ssam 5*13736Ssam #include <sys/types.h> 6*13736Ssam #include <sys/stat.h> 7*13736Ssam #include <sys/file.h> 8*13736Ssam 9*13736Ssam #include <stdio.h> 10*13736Ssam #include <errno.h> 11*13736Ssam #include <signal.h> 12*13736Ssam 13*13736Ssam /* 14*13736Ssam * Password file editor with locking. 15*13736Ssam */ 16*13736Ssam char *temp = "/etc/ptmp"; 17*13736Ssam char *passwd = "/etc/passwd"; 18*13736Ssam char buf[BUFSIZ]; 19*13736Ssam char *getenv(); 20*13736Ssam char *index(); 21*13736Ssam extern int errno; 22*13736Ssam 23*13736Ssam main(argc, argv) 24*13736Ssam char *argv[]; 25*13736Ssam { 26*13736Ssam int fd; 27*13736Ssam FILE *ft, *fp; 28*13736Ssam char *editor; 29*13736Ssam 30*13736Ssam signal(SIGINT, SIG_IGN); 31*13736Ssam signal(SIGQUIT, SIG_IGN); 32*13736Ssam signal(SIGHUP, SIG_IGN); 33*13736Ssam setbuf(stderr, NULL); 34*13736Ssam fd = open(temp, O_WRONLY|O_CREAT|O_EXCL, 0644); 35*13736Ssam if (fd < 0) { 36*13736Ssam if (errno == EEXIST) { 37*13736Ssam fprintf(stderr, "vipw: password file busy\n"); 38*13736Ssam exit(1); 39*13736Ssam } 40*13736Ssam fprintf(stderr, "vipw: "); perror(temp); 41*13736Ssam exit(1); 42*13736Ssam } 43*13736Ssam ft = fdopen(fd, "w"); 44*13736Ssam if (ft == NULL) { 45*13736Ssam fprintf(stderr, "vipw: "); perror(temp); 46*13736Ssam goto bad; 47*13736Ssam } 48*13736Ssam fp = fopen(passwd, "r"); 49*13736Ssam if (fp == NULL) { 50*13736Ssam fprintf(stderr, "vipw: "); perror(passwd); 51*13736Ssam goto bad; 52*13736Ssam } 53*13736Ssam while (fgets(buf, sizeof (buf) - 1, fp) != NULL) 54*13736Ssam fputs(buf, ft); 55*13736Ssam fclose(ft); fclose(fp); 56*13736Ssam editor = getenv("EDITOR"); 57*13736Ssam if (editor == 0) 58*13736Ssam editor = "vi"; 59*13736Ssam sprintf(buf, "%s %s", editor, temp); 60*13736Ssam if (system(buf) == 0) { 61*13736Ssam struct stat sbuf; 62*13736Ssam int ok; 63*13736Ssam 64*13736Ssam /* sanity checks */ 65*13736Ssam if (stat(temp, &sbuf) < 0) { 66*13736Ssam fprintf(stderr, 67*13736Ssam "vipw: can't stat temp file, %s unchanged\n", 68*13736Ssam passwd); 69*13736Ssam goto bad; 70*13736Ssam } 71*13736Ssam if (sbuf.st_size == 0) { 72*13736Ssam fprintf(stderr, "vipw: bad temp file, %s unchanged\n", 73*13736Ssam passwd); 74*13736Ssam goto bad; 75*13736Ssam } 76*13736Ssam ft = fopen(temp, "r"); 77*13736Ssam if (ft == NULL) { 78*13736Ssam fprintf(stderr, 79*13736Ssam "vipw: can't reopen temp file, %s unchanged\n", 80*13736Ssam passwd); 81*13736Ssam goto bad; 82*13736Ssam } 83*13736Ssam ok = 0; 84*13736Ssam while (fgets(buf, sizeof (buf) - 1, ft) != NULL) { 85*13736Ssam register char *cp; 86*13736Ssam 87*13736Ssam cp = index(buf, '\n'); 88*13736Ssam if (cp == 0) 89*13736Ssam continue; 90*13736Ssam *cp = '\0'; 91*13736Ssam cp = index(buf, ':'); 92*13736Ssam if (cp == 0) 93*13736Ssam continue; 94*13736Ssam *cp = '\0'; 95*13736Ssam if (strcmp(buf, "root")) 96*13736Ssam continue; 97*13736Ssam /* password */ 98*13736Ssam cp = index(cp + 1, ':'); 99*13736Ssam if (cp == 0) 100*13736Ssam break; 101*13736Ssam /* uid */ 102*13736Ssam if (atoi(cp + 1) != 0) 103*13736Ssam break; 104*13736Ssam cp = index(cp + 1, ':'); 105*13736Ssam if (cp == 0) 106*13736Ssam break; 107*13736Ssam /* gid */ 108*13736Ssam cp = index(cp + 1, ':'); 109*13736Ssam if (cp == 0) 110*13736Ssam break; 111*13736Ssam /* gecos */ 112*13736Ssam cp = index(cp + 1, ':'); 113*13736Ssam if (cp == 0) 114*13736Ssam break; 115*13736Ssam /* login directory */ 116*13736Ssam if (strncmp(++cp, "/:")) 117*13736Ssam break; 118*13736Ssam cp += 2; 119*13736Ssam if (*cp && strcmp(cp, "/bin/sh") && 120*13736Ssam strcmp(cp, "/bin/csh")) 121*13736Ssam break; 122*13736Ssam ok++; 123*13736Ssam } 124*13736Ssam fclose(ft); 125*13736Ssam if (ok) { 126*13736Ssam if (rename(temp, passwd) < 0) 127*13736Ssam fprintf(stderr, "vipw: "), perror("rename"); 128*13736Ssam } else 129*13736Ssam fprintf(stderr, 130*13736Ssam "vipw: you mangled the temp file, %s unchanged\n", 131*13736Ssam passwd); 132*13736Ssam } 133*13736Ssam bad: 134*13736Ssam unlink(temp); 135*13736Ssam } 136