xref: /csrg-svn/usr.sbin/vipw/vipw.c (revision 13736)
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