4.4BSD snapshot (revision 8.1); add 1993 to copyright
[unix-history] / usr / src / usr.sbin / vipw / vipw.c
index 030adbd..c30bbd6 100644 (file)
+/*
+ * Copyright (c) 1987, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1987, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)vipw.c     4.7 (Berkeley) %G%";
-#endif
+static char sccsid[] = "@(#)vipw.c     8.1 (Berkeley) %G%";
+#endif /* not lint */
 
 #include <sys/types.h>
 #include <sys/stat.h>
 
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <sys/file.h>
-
+#include <pwd.h>
 #include <stdio.h>
 #include <stdio.h>
-#include <errno.h>
-#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
 
 
-/*
- * Password file editor with locking.
- */
-char   temp[] = "/etc/ptmp";
-char   temp_pag[] = "/etc/ptmp.pag";
-char   temp_dir[] = "/etc/ptmp.dir";
-char   passwd[] = "/etc/passwd";
-char   passwd_pag[] = "/etc/passwd.pag";
-char   passwd_dir[] = "/etc/passwd.dir";
-char   buf[BUFSIZ];
-char   *getenv();
-char   *index();
-extern int errno;
+char *progname = "vipw";
+char *tempname;
 
 
-main(argc, argv)
-       char *argv[];
+main()
 {
 {
-       int fd;
-       FILE *ft, *fp;
-       char *editor;
-
-       signal(SIGHUP, SIG_IGN);
-       signal(SIGINT, SIG_IGN);
-       signal(SIGQUIT, SIG_IGN);
-       setbuf(stderr, NULL);
-       umask(0);
-       fd = open(temp, O_WRONLY|O_CREAT|O_EXCL, 0644);
-       if (fd < 0) {
-               if (errno == EEXIST) {
-                       fprintf(stderr, "vipw: password file busy\n");
-                       exit(1);
-               }
-               fprintf(stderr, "vipw: "); perror(temp);
-               exit(1);
-       }
-       ft = fdopen(fd, "w");
-       if (ft == NULL) {
-               fprintf(stderr, "vipw: "); perror(temp);
-               goto bad;
-       }
-       fp = fopen(passwd, "r");
-       if (fp == NULL) {
-               fprintf(stderr, "vipw: "); perror(passwd);
-               goto bad;
-       }
-       while (fgets(buf, sizeof (buf) - 1, fp) != NULL)
-               fputs(buf, ft);
-       fclose(ft); fclose(fp);
-       editor = getenv("EDITOR");
-       if (editor == 0)
-               editor = "vi";
-       sprintf(buf, "%s %s", editor, temp);
-       if (system(buf) == 0) {
-               struct stat sbuf;
-               int ok;
+       register int pfd, tfd;
+       struct stat begin, end;
 
 
-               /* sanity checks */
-               if (stat(temp, &sbuf) < 0) {
-                       fprintf(stderr,
-                           "vipw: can't stat temp file, %s unchanged\n",
-                           passwd);
-                       goto bad;
-               }
-               if (sbuf.st_size == 0) {
-                       fprintf(stderr, "vipw: bad temp file, %s unchanged\n",
-                           passwd);
-                       goto bad;
-               }
-               ft = fopen(temp, "r");
-               if (ft == NULL) {
-                       fprintf(stderr,
-                           "vipw: can't reopen temp file, %s unchanged\n",
-                           passwd);
-                       goto bad;
-               }
-               ok = 0;
-               while (fgets(buf, sizeof (buf) - 1, ft) != NULL) {
-                       register char *cp;
+       pw_init();
+       pfd = pw_lock();
+       tfd = pw_tmp();
+       copyfile(pfd, tfd);
+       (void)close(tfd);
 
 
-                       cp = index(buf, '\n');
-                       if (cp == 0)
-                               continue;
-                       *cp = '\0';
-                       cp = index(buf, ':');
-                       if (cp == 0)
-                               continue;
-                       *cp = '\0';
-                       if (strcmp(buf, "root"))
-                               continue;
-                       /* password */
-                       cp = index(cp + 1, ':');
-                       if (cp == 0)
-                               break;
-                       /* uid */
-                       if (atoi(cp + 1) != 0)
-                               break;
-                       cp = index(cp + 1, ':');
-                       if (cp == 0)
-                               break;
-                       /* gid */
-                       cp = index(cp + 1, ':');
-                       if (cp == 0)
-                               break;
-                       /* gecos */
-                       cp = index(cp + 1, ':');
-                       if (cp == 0)
-                               break;
-                       /* login directory */
-                       if (strncmp(++cp, "/:", 2))
-                               break;
-                       cp += 2;
-                       if (*cp && strcmp(cp, "/bin/sh") &&
-                           strcmp(cp, "/bin/csh"))
-                               break;
-                       ok++;
+       for (;;) {
+               if (stat(tempname, &begin))
+                       pw_error(tempname, 1, 1);
+               pw_edit(0);
+               if (stat(tempname, &end))
+                       pw_error(tempname, 1, 1);
+               if (begin.st_mtime == end.st_mtime) {
+                       (void)fprintf(stderr, "vipw: no changes made\n");
+                       pw_error((char *)NULL, 0, 0);
                }
                }
-               fclose(ft);
-               if (ok) {
-                       if (makedb(temp) < 0)
-                               fprintf(stderr, "vipw: mkpasswd failed\n");
-                       else if (rename(temp_pag, passwd_pag) < 0)
-                               fprintf(stderr, "vipw: "), perror(temp_pag);
-                       else if (rename(temp_dir, passwd_dir) < 0)
-                               fprintf(stderr, "vipw: "), perror(temp_dir);
-                       else if (rename(temp, passwd) < 0)
-                               fprintf(stderr, "vipw: "), perror("rename");
-                       else
-                               exit(0);
-               } else
-                       fprintf(stderr,
-                           "vipw: you mangled the temp file, %s unchanged\n",
-                           passwd);
+               if (pw_mkdb())
+                       break;
+               pw_prompt();
        }
        }
-bad:
-       unlink(temp_pag);
-       unlink(temp_dir);
-       unlink(temp);
-       exit(1);
+       exit(0);
 }
 
 }
 
-makedb(file)
-       char *file;
+copyfile(from, to)
+       register int from, to;
 {
 {
-       int status, pid, w;
-
-       if ((pid = vfork()) == 0) {
-               execl("/etc/mkpasswd", "mkpasswd", file, 0);
-               _exit(127);
-       }
-       while ((w = wait(&status)) != pid && w != -1)
-               ;
-       if (w == -1 || status != 0)
-               status = -1;
-       return(status);
+       register int nr, nw, off;
+       char buf[8*1024];
+       
+       while ((nr = read(from, buf, sizeof(buf))) > 0)
+               for (off = 0; off < nr; nr -= nw, off += nw)
+                       if ((nw = write(to, buf + off, nr)) < 0)
+                               pw_error(tempname, 1, 1);
+       if (nr < 0)
+               pw_error(_PATH_MASTERPASSWD, 1, 1);
 }
 }