xref: /csrg-svn/usr.sbin/vipw/vipw.c (revision 15650)
113736Ssam #ifndef lint
2*15650Sralph static char sccsid[] = "@(#)vipw.c	4.5 (Berkeley) 12/02/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  */
16*15650Sralph char	temp[] = "/etc/ptmp";
17*15650Sralph char	temp_pag[] = "/etc/ptmp.pag";
18*15650Sralph char	temp_dir[] = "/etc/ptmp.dir";
19*15650Sralph char	passwd[] = "/etc/passwd";
20*15650Sralph char	passwd_pag[] = "/etc/passwd.pag";
21*15650Sralph 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 
34*15650Sralph 	signal(SIGHUP, SIG_IGN);
3513736Ssam 	signal(SIGINT, SIG_IGN);
3613736Ssam 	signal(SIGQUIT, SIG_IGN);
37*15650Sralph 	signal(SIGTSTP, SIG_IGN);
3813736Ssam 	setbuf(stderr, NULL);
3914911Sralph 	umask(0);
4013736Ssam 	fd = open(temp, O_WRONLY|O_CREAT|O_EXCL, 0644);
4113736Ssam 	if (fd < 0) {
4213736Ssam 		if (errno == EEXIST) {
4313736Ssam 			fprintf(stderr, "vipw: password file busy\n");
4413736Ssam 			exit(1);
4513736Ssam 		}
4613736Ssam 		fprintf(stderr, "vipw: "); perror(temp);
4713736Ssam 		exit(1);
4813736Ssam 	}
4913736Ssam 	ft = fdopen(fd, "w");
5013736Ssam 	if (ft == NULL) {
5113736Ssam 		fprintf(stderr, "vipw: "); perror(temp);
5213736Ssam 		goto bad;
5313736Ssam 	}
5413736Ssam 	fp = fopen(passwd, "r");
5513736Ssam 	if (fp == NULL) {
5613736Ssam 		fprintf(stderr, "vipw: "); perror(passwd);
5713736Ssam 		goto bad;
5813736Ssam 	}
5913736Ssam 	while (fgets(buf, sizeof (buf) - 1, fp) != NULL)
6013736Ssam 		fputs(buf, ft);
6113736Ssam 	fclose(ft); fclose(fp);
6213736Ssam 	editor = getenv("EDITOR");
6313736Ssam 	if (editor == 0)
6413736Ssam 		editor = "vi";
6513736Ssam 	sprintf(buf, "%s %s", editor, temp);
6613736Ssam 	if (system(buf) == 0) {
6713736Ssam 		struct stat sbuf;
6813736Ssam 		int ok;
6913736Ssam 
7013736Ssam 		/* sanity checks */
7113736Ssam 		if (stat(temp, &sbuf) < 0) {
7213736Ssam 			fprintf(stderr,
7313736Ssam 			    "vipw: can't stat temp file, %s unchanged\n",
7413736Ssam 			    passwd);
7513736Ssam 			goto bad;
7613736Ssam 		}
7713736Ssam 		if (sbuf.st_size == 0) {
7813736Ssam 			fprintf(stderr, "vipw: bad temp file, %s unchanged\n",
7913736Ssam 			    passwd);
8013736Ssam 			goto bad;
8113736Ssam 		}
8213736Ssam 		ft = fopen(temp, "r");
8313736Ssam 		if (ft == NULL) {
8413736Ssam 			fprintf(stderr,
8513736Ssam 			    "vipw: can't reopen temp file, %s unchanged\n",
8613736Ssam 			    passwd);
8713736Ssam 			goto bad;
8813736Ssam 		}
8913736Ssam 		ok = 0;
9013736Ssam 		while (fgets(buf, sizeof (buf) - 1, ft) != NULL) {
9113736Ssam 			register char *cp;
9213736Ssam 
9313736Ssam 			cp = index(buf, '\n');
9413736Ssam 			if (cp == 0)
9513736Ssam 				continue;
9613736Ssam 			*cp = '\0';
9713736Ssam 			cp = index(buf, ':');
9813736Ssam 			if (cp == 0)
9913736Ssam 				continue;
10013736Ssam 			*cp = '\0';
10113736Ssam 			if (strcmp(buf, "root"))
10213736Ssam 				continue;
10313736Ssam 			/* password */
10413736Ssam 			cp = index(cp + 1, ':');
10513736Ssam 			if (cp == 0)
10613736Ssam 				break;
10713736Ssam 			/* uid */
10813736Ssam 			if (atoi(cp + 1) != 0)
10913736Ssam 				break;
11013736Ssam 			cp = index(cp + 1, ':');
11113736Ssam 			if (cp == 0)
11213736Ssam 				break;
11313736Ssam 			/* gid */
11413736Ssam 			cp = index(cp + 1, ':');
11513736Ssam 			if (cp == 0)
11613736Ssam 				break;
11713736Ssam 			/* gecos */
11813736Ssam 			cp = index(cp + 1, ':');
11913736Ssam 			if (cp == 0)
12013736Ssam 				break;
12113736Ssam 			/* login directory */
12213736Ssam 			if (strncmp(++cp, "/:"))
12313736Ssam 				break;
12413736Ssam 			cp += 2;
12513736Ssam 			if (*cp && strcmp(cp, "/bin/sh") &&
12613736Ssam 			    strcmp(cp, "/bin/csh"))
12713736Ssam 				break;
12813736Ssam 			ok++;
12913736Ssam 		}
13013736Ssam 		fclose(ft);
13113736Ssam 		if (ok) {
13215633Sralph 			if (makedb(temp) < 0)
13315633Sralph 				fprintf(stderr, "vipw: mkpasswd failed\n");
13415633Sralph 			else if (rename(temp_pag, passwd_pag) < 0)
13515633Sralph 				fprintf(stderr, "vipw: "), perror(temp_pag);
13615633Sralph 			else if (rename(temp_dir, passwd_dir) < 0)
13715633Sralph 				fprintf(stderr, "vipw: "), perror(temp_dir);
13815633Sralph 			else if (rename(temp, passwd) < 0)
13913736Ssam 				fprintf(stderr, "vipw: "), perror("rename");
14015166Sralph 			else
14115166Sralph 				exit(0);
14213736Ssam 		} else
14313736Ssam 			fprintf(stderr,
14413736Ssam 			    "vipw: you mangled the temp file, %s unchanged\n",
14513736Ssam 			    passwd);
14613736Ssam 	}
14713736Ssam bad:
148*15650Sralph 	unlink(temp_pag);
149*15650Sralph 	unlink(temp_dir);
15013736Ssam 	unlink(temp);
15115166Sralph 	exit(1);
15213736Ssam }
15315633Sralph 
15415633Sralph makedb(file)
15515633Sralph 	char *file;
15615633Sralph {
15715633Sralph 	int status, pid, w;
15815633Sralph 
15915633Sralph 	if ((pid = vfork()) == 0) {
16015633Sralph 		execl("/etc/mkpasswd", "mkpasswd", file, 0);
16115633Sralph 		_exit(127);
16215633Sralph 	}
16315633Sralph 	while ((w = wait(&status)) != pid && w != -1)
16415633Sralph 		;
16515633Sralph 	if (w == -1 || status != 0)
16615633Sralph 		status = -1;
16715633Sralph 	return(status);
16815633Sralph }
169