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