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