xref: /csrg-svn/usr.sbin/vipw/vipw.c (revision 21186)
1*21186Sdist /*
2*21186Sdist  * Copyright (c) 1980 Regents of the University of California.
3*21186Sdist  * All rights reserved.  The Berkeley software License Agreement
4*21186Sdist  * specifies the terms and conditions for redistribution.
5*21186Sdist  */
6*21186Sdist 
713736Ssam #ifndef lint
8*21186Sdist char copyright[] =
9*21186Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\
10*21186Sdist  All rights reserved.\n";
11*21186Sdist #endif not lint
1213736Ssam 
13*21186Sdist #ifndef lint
14*21186Sdist static char sccsid[] = "@(#)vipw.c	5.1 (Berkeley) 05/28/85";
15*21186Sdist #endif not lint
16*21186Sdist 
1713736Ssam #include <sys/types.h>
1813736Ssam #include <sys/stat.h>
1913736Ssam #include <sys/file.h>
2013736Ssam 
2113736Ssam #include <stdio.h>
2213736Ssam #include <errno.h>
2313736Ssam #include <signal.h>
2413736Ssam 
2513736Ssam /*
2613736Ssam  * Password file editor with locking.
2713736Ssam  */
2815650Sralph char	temp[] = "/etc/ptmp";
2915650Sralph char	temp_pag[] = "/etc/ptmp.pag";
3015650Sralph char	temp_dir[] = "/etc/ptmp.dir";
3115650Sralph char	passwd[] = "/etc/passwd";
3215650Sralph char	passwd_pag[] = "/etc/passwd.pag";
3315650Sralph char	passwd_dir[] = "/etc/passwd.dir";
3413736Ssam char	buf[BUFSIZ];
3513736Ssam char	*getenv();
3613736Ssam char	*index();
3713736Ssam extern	int errno;
3813736Ssam 
3913736Ssam main(argc, argv)
4013736Ssam 	char *argv[];
4113736Ssam {
4213736Ssam 	int fd;
4313736Ssam 	FILE *ft, *fp;
4413736Ssam 	char *editor;
4513736Ssam 
4615650Sralph 	signal(SIGHUP, SIG_IGN);
4713736Ssam 	signal(SIGINT, SIG_IGN);
4813736Ssam 	signal(SIGQUIT, SIG_IGN);
4913736Ssam 	setbuf(stderr, NULL);
5014911Sralph 	umask(0);
5113736Ssam 	fd = open(temp, O_WRONLY|O_CREAT|O_EXCL, 0644);
5213736Ssam 	if (fd < 0) {
5313736Ssam 		if (errno == EEXIST) {
5413736Ssam 			fprintf(stderr, "vipw: password file busy\n");
5513736Ssam 			exit(1);
5613736Ssam 		}
5713736Ssam 		fprintf(stderr, "vipw: "); perror(temp);
5813736Ssam 		exit(1);
5913736Ssam 	}
6013736Ssam 	ft = fdopen(fd, "w");
6113736Ssam 	if (ft == NULL) {
6213736Ssam 		fprintf(stderr, "vipw: "); perror(temp);
6313736Ssam 		goto bad;
6413736Ssam 	}
6513736Ssam 	fp = fopen(passwd, "r");
6613736Ssam 	if (fp == NULL) {
6713736Ssam 		fprintf(stderr, "vipw: "); perror(passwd);
6813736Ssam 		goto bad;
6913736Ssam 	}
7013736Ssam 	while (fgets(buf, sizeof (buf) - 1, fp) != NULL)
7113736Ssam 		fputs(buf, ft);
7213736Ssam 	fclose(ft); fclose(fp);
7313736Ssam 	editor = getenv("EDITOR");
7413736Ssam 	if (editor == 0)
7513736Ssam 		editor = "vi";
7613736Ssam 	sprintf(buf, "%s %s", editor, temp);
7713736Ssam 	if (system(buf) == 0) {
7813736Ssam 		struct stat sbuf;
7913736Ssam 		int ok;
8013736Ssam 
8113736Ssam 		/* sanity checks */
8213736Ssam 		if (stat(temp, &sbuf) < 0) {
8313736Ssam 			fprintf(stderr,
8413736Ssam 			    "vipw: can't stat temp file, %s unchanged\n",
8513736Ssam 			    passwd);
8613736Ssam 			goto bad;
8713736Ssam 		}
8813736Ssam 		if (sbuf.st_size == 0) {
8913736Ssam 			fprintf(stderr, "vipw: bad temp file, %s unchanged\n",
9013736Ssam 			    passwd);
9113736Ssam 			goto bad;
9213736Ssam 		}
9313736Ssam 		ft = fopen(temp, "r");
9413736Ssam 		if (ft == NULL) {
9513736Ssam 			fprintf(stderr,
9613736Ssam 			    "vipw: can't reopen temp file, %s unchanged\n",
9713736Ssam 			    passwd);
9813736Ssam 			goto bad;
9913736Ssam 		}
10013736Ssam 		ok = 0;
10113736Ssam 		while (fgets(buf, sizeof (buf) - 1, ft) != NULL) {
10213736Ssam 			register char *cp;
10313736Ssam 
10413736Ssam 			cp = index(buf, '\n');
10513736Ssam 			if (cp == 0)
10613736Ssam 				continue;
10713736Ssam 			*cp = '\0';
10813736Ssam 			cp = index(buf, ':');
10913736Ssam 			if (cp == 0)
11013736Ssam 				continue;
11113736Ssam 			*cp = '\0';
11213736Ssam 			if (strcmp(buf, "root"))
11313736Ssam 				continue;
11413736Ssam 			/* password */
11513736Ssam 			cp = index(cp + 1, ':');
11613736Ssam 			if (cp == 0)
11713736Ssam 				break;
11813736Ssam 			/* uid */
11913736Ssam 			if (atoi(cp + 1) != 0)
12013736Ssam 				break;
12113736Ssam 			cp = index(cp + 1, ':');
12213736Ssam 			if (cp == 0)
12313736Ssam 				break;
12413736Ssam 			/* gid */
12513736Ssam 			cp = index(cp + 1, ':');
12613736Ssam 			if (cp == 0)
12713736Ssam 				break;
12813736Ssam 			/* gecos */
12913736Ssam 			cp = index(cp + 1, ':');
13013736Ssam 			if (cp == 0)
13113736Ssam 				break;
13213736Ssam 			/* login directory */
13318108Sbloom 			if (strncmp(++cp, "/:", 2))
13413736Ssam 				break;
13513736Ssam 			cp += 2;
13613736Ssam 			if (*cp && strcmp(cp, "/bin/sh") &&
13713736Ssam 			    strcmp(cp, "/bin/csh"))
13813736Ssam 				break;
13913736Ssam 			ok++;
14013736Ssam 		}
14113736Ssam 		fclose(ft);
14213736Ssam 		if (ok) {
14315633Sralph 			if (makedb(temp) < 0)
14415633Sralph 				fprintf(stderr, "vipw: mkpasswd failed\n");
14515633Sralph 			else if (rename(temp_pag, passwd_pag) < 0)
14615633Sralph 				fprintf(stderr, "vipw: "), perror(temp_pag);
14715633Sralph 			else if (rename(temp_dir, passwd_dir) < 0)
14815633Sralph 				fprintf(stderr, "vipw: "), perror(temp_dir);
14915633Sralph 			else if (rename(temp, passwd) < 0)
15013736Ssam 				fprintf(stderr, "vipw: "), perror("rename");
15115166Sralph 			else
15215166Sralph 				exit(0);
15313736Ssam 		} else
15413736Ssam 			fprintf(stderr,
15513736Ssam 			    "vipw: you mangled the temp file, %s unchanged\n",
15613736Ssam 			    passwd);
15713736Ssam 	}
15813736Ssam bad:
15915650Sralph 	unlink(temp_pag);
16015650Sralph 	unlink(temp_dir);
16113736Ssam 	unlink(temp);
16215166Sralph 	exit(1);
16313736Ssam }
16415633Sralph 
16515633Sralph makedb(file)
16615633Sralph 	char *file;
16715633Sralph {
16815633Sralph 	int status, pid, w;
16915633Sralph 
17015633Sralph 	if ((pid = vfork()) == 0) {
17115633Sralph 		execl("/etc/mkpasswd", "mkpasswd", file, 0);
17215633Sralph 		_exit(127);
17315633Sralph 	}
17415633Sralph 	while ((w = wait(&status)) != pid && w != -1)
17515633Sralph 		;
17615633Sralph 	if (w == -1 || status != 0)
17715633Sralph 		status = -1;
17815633Sralph 	return(status);
17915633Sralph }
180