xref: /csrg-svn/old/mkpasswd/mkpasswd.c (revision 41567)
121151Sdist /*
233137Sbostic  * Copyright (c) 1980, 1983 Regents of the University of California.
333137Sbostic  * All rights reserved.
433137Sbostic  *
533137Sbostic  * Redistribution and use in source and binary forms are permitted
634778Sbostic  * provided that the above copyright notice and this paragraph are
734778Sbostic  * duplicated in all such forms and that any documentation,
834778Sbostic  * advertising materials, and other materials related to such
934778Sbostic  * distribution and use acknowledge that the software was developed
1034778Sbostic  * by the University of California, Berkeley.  The name of the
1134778Sbostic  * University may not be used to endorse or promote products derived
1234778Sbostic  * from this software without specific prior written permission.
1334778Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1434778Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1534778Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1621151Sdist  */
1721151Sdist 
1815664Sralph #ifndef lint
1921151Sdist char copyright[] =
2033137Sbostic "@(#) Copyright (c) 1980, 1983 Regents of the University of California.\n\
2121151Sdist  All rights reserved.\n";
2233137Sbostic #endif /* not lint */
2315664Sralph 
2421151Sdist #ifndef lint
25*41567Smarc static char sccsid[] = "@(#)mkpasswd.c	5.5 (Berkeley) 05/10/90";
2633137Sbostic #endif /* not lint */
2721151Sdist 
2836859Sbostic #include <sys/param.h>
2915664Sralph #include <sys/file.h>
3036859Sbostic #include <ndbm.h>
3136859Sbostic #include <pwd.h>
3215664Sralph #include <stdio.h>
3315664Sralph 
3436859Sbostic static FILE *_pw_fp;
3536859Sbostic static struct passwd _pw_passwd;
3636859Sbostic static off_t offset;
3736859Sbostic 
3836859Sbostic #define	MAXLINELENGTH	1024
3936859Sbostic static char line[MAXLINELENGTH];
4036859Sbostic 
4136859Sbostic /*
4236859Sbostic  * Mkpasswd does two things -- use the ``arg'' file to create ``arg''.{pag,dir}
4336859Sbostic  * for ndbm, and, if the -p flag is on, create a password file in the original
4436859Sbostic  * format.  It doesn't use the getpwent(3) routines because it has to figure
4536859Sbostic  * out offsets for the encrypted passwords to put in the dbm files.  One other
4636859Sbostic  * problem is that, since the addition of shadow passwords, getpwent(3) has to
4736859Sbostic  * use the dbm databases rather than simply scanning the actual file.  This
4836859Sbostic  * required the addition of a flag field to the dbm database to distinguish
4936859Sbostic  * between a record keyed by name, and one keyed by uid.
5036859Sbostic  */
5136859Sbostic 
5215664Sralph main(argc, argv)
5333137Sbostic 	int argc;
5436859Sbostic 	char **argv;
5515664Sralph {
5636859Sbostic 	extern int errno, optind;
5736859Sbostic 	register char *flag, *p, *t;
5836859Sbostic 	register int makeold;
5936859Sbostic 	FILE *oldfp;
6015664Sralph 	DBM *dp;
6115664Sralph 	datum key, content;
6236859Sbostic 	int ch;
6336859Sbostic 	char buf[8192], nbuf[50], *strerror();
6415664Sralph 
6536859Sbostic 	makeold = 0;
6636859Sbostic 	while ((ch = getopt(argc, argv, "pv")) != EOF)
6736859Sbostic 		switch(ch) {
6836859Sbostic 		case 'p':			/* create ``password.orig'' */
6936859Sbostic 			makeold = 1;
7036859Sbostic 			/* FALLTHROUGH */
7136859Sbostic 		case 'v':			/* backward compatible */
7236859Sbostic 			break;
7336859Sbostic 		case '?':
7436859Sbostic 		default:
7536859Sbostic 			usage();
7636859Sbostic 		}
7736859Sbostic 	argc -= optind;
7836859Sbostic 	argv += optind;
7936859Sbostic 
8036859Sbostic 	if (argc != 1)
8136859Sbostic 		usage();
8236859Sbostic 
8336859Sbostic 	if (!(_pw_fp = fopen(*argv, "r"))) {
8436859Sbostic 		(void)fprintf(stderr,
8536859Sbostic 		    "mkpasswd: %s: can't open for reading.\n", *argv);
8615664Sralph 		exit(1);
8715664Sralph 	}
8836859Sbostic 
8936859Sbostic 	rmall(*argv);
9033137Sbostic 	(void)umask(0);
9136859Sbostic 
9236859Sbostic 	/* open old password format file, dbm files */
9336859Sbostic 	if (makeold) {
9436859Sbostic 		int oldfd;
9536859Sbostic 
9636859Sbostic 		(void)sprintf(buf, "%s.orig", *argv);
9736859Sbostic 		if ((oldfd = open(buf, O_WRONLY|O_CREAT|O_EXCL, 0644)) < 0) {
9836859Sbostic 			(void)fprintf(stderr, "mkpasswd: %s: %s\n", buf,
9936859Sbostic 			    strerror(errno));
10017308Sralph 			exit(1);
10117308Sralph 		}
10236859Sbostic 		if (!(oldfp = fdopen(oldfd, "w"))) {
10336859Sbostic 			(void)fprintf(stderr, "mkpasswd: %s: fdopen failed.\n",
10436859Sbostic 			    buf);
10517308Sralph 			exit(1);
10617308Sralph 		}
10715664Sralph 	}
10836859Sbostic 	if (!(dp = dbm_open(*argv, O_WRONLY|O_CREAT|O_EXCL, 0644))) {
10936859Sbostic 		(void)fprintf(stderr, "mkpasswd: %s: %s\n", *argv,
11036859Sbostic 		    strerror(errno));
11136859Sbostic 		exit(1);
11236859Sbostic 	}
11336859Sbostic 
11436859Sbostic 	content.dptr = buf;
11536859Sbostic 	while (scanpw()) {
11636859Sbostic 		/* create dbm entry */
11736859Sbostic 		p = buf;
11836859Sbostic #define	COMPACT(e)	t = e; while (*p++ = *t++);
11936859Sbostic 		COMPACT(_pw_passwd.pw_name);
12036859Sbostic 		(void)sprintf(nbuf, "%ld", offset);
12136859Sbostic 		COMPACT(nbuf);
12236859Sbostic 		bcopy((char *)&_pw_passwd.pw_uid, p, sizeof(int));
12336859Sbostic 		p += sizeof(int);
12436859Sbostic 		bcopy((char *)&_pw_passwd.pw_gid, p, sizeof(int));
12536859Sbostic 		p += sizeof(int);
12636859Sbostic 		bcopy((char *)&_pw_passwd.pw_change, p, sizeof(time_t));
12736859Sbostic 		p += sizeof(time_t);
12836859Sbostic 		COMPACT(_pw_passwd.pw_class);
12936859Sbostic 		COMPACT(_pw_passwd.pw_gecos);
13036859Sbostic 		COMPACT(_pw_passwd.pw_dir);
13136859Sbostic 		COMPACT(_pw_passwd.pw_shell);
13236859Sbostic 		bcopy((char *)&_pw_passwd.pw_expire, p, sizeof(time_t));
13336859Sbostic 		p += sizeof(time_t);
13436859Sbostic 		flag = p;
13536859Sbostic 		*p++ = _PW_KEYBYNAME;
13636859Sbostic 		content.dsize = p - buf;
13736859Sbostic #ifdef debug
13836859Sbostic 		(void)printf("store %s, uid %d\n", _pw_passwd.pw_name,
13936859Sbostic 		    _pw_passwd.pw_uid);
14036859Sbostic #endif
14136859Sbostic 		key.dptr = _pw_passwd.pw_name;
14236859Sbostic 		key.dsize = strlen(_pw_passwd.pw_name);
14336859Sbostic 		if (dbm_store(dp, key, content, DBM_INSERT) < 0)
14436859Sbostic 			goto bad;
14536859Sbostic 		key.dptr = (char *)&_pw_passwd.pw_uid;
14636859Sbostic 		key.dsize = sizeof(int);
14736859Sbostic 		*flag = _PW_KEYBYUID;
14836859Sbostic 		if (dbm_store(dp, key, content, DBM_INSERT) < 0)
14936859Sbostic 			goto bad;
15036859Sbostic 
15136859Sbostic 		/* create original format password file entry */
15236859Sbostic 		if (!makeold)
15336859Sbostic 			continue;
15436859Sbostic 		fprintf(oldfp, "%s:*:%d:%d:%s:%s:%s\n", _pw_passwd.pw_name,
15536859Sbostic 		    _pw_passwd.pw_uid, _pw_passwd.pw_gid, _pw_passwd.pw_gecos,
15636859Sbostic 		    _pw_passwd.pw_dir, _pw_passwd.pw_shell);
15736859Sbostic 	}
15817308Sralph 	dbm_close(dp);
15915664Sralph 	exit(0);
16036859Sbostic 
16136859Sbostic bad:	(void)fprintf(stderr, "mkpasswd: dbm_store failed.\n");
16236859Sbostic 	rmall(*argv);
16336859Sbostic 	exit(1);
16415664Sralph }
16536859Sbostic 
16636859Sbostic rmall(fname)
16736859Sbostic 	char *fname;
16836859Sbostic {
16936859Sbostic 	register char *p;
17036859Sbostic 	char buf[MAXPATHLEN], *strcpy();
17136859Sbostic 
17236859Sbostic 	for (p = strcpy(buf, fname); *p; ++p);
17336859Sbostic 	bcopy(".pag", p, 5);
17436859Sbostic 	(void)unlink(buf);
17536859Sbostic 	bcopy(".dir", p, 5);
17636859Sbostic 	(void)unlink(buf);
17736859Sbostic 	bcopy(".orig", p, 6);
17836859Sbostic 	(void)unlink(buf);
17936859Sbostic }
18036859Sbostic 
18136859Sbostic usage()
18236859Sbostic {
18336859Sbostic 	(void)fprintf(stderr, "usage: mkpasswd [-p] passwd_file\n");
18436859Sbostic 	exit(1);
18536859Sbostic }
18636859Sbostic 
18736859Sbostic /* from libc/gen/getpwent.c */
18836859Sbostic 
18936859Sbostic static
19036859Sbostic scanpw()
19136859Sbostic {
19236859Sbostic 	register char *cp;
19336859Sbostic 	long atol(), ftell();
194*41567Smarc 	char *bp;
19536859Sbostic 	char *fgets(), *strsep(), *index();
19636859Sbostic 
19736859Sbostic 	for (;;) {
19836859Sbostic 		offset = ftell(_pw_fp);
19936859Sbostic 		if (!(fgets(line, sizeof(line), _pw_fp)))
20036859Sbostic 			return(0);
20136859Sbostic 		/* skip lines that are too big */
20236859Sbostic 		if (!index(line, '\n')) {
20336859Sbostic 			int ch;
20436859Sbostic 
20536859Sbostic 			while ((ch = getc(_pw_fp)) != '\n' && ch != EOF)
20636859Sbostic 				;
20736859Sbostic 			continue;
20836859Sbostic 		}
209*41567Smarc 		bp = line;
210*41567Smarc 		_pw_passwd.pw_name = strsep(&bp, ":\n");
211*41567Smarc 		_pw_passwd.pw_passwd = strsep(&bp, ":\n");
21236859Sbostic 		offset += _pw_passwd.pw_passwd - line;
213*41567Smarc 		if (!(cp = strsep(&bp, ":\n")))
21436859Sbostic 			continue;
21536859Sbostic 		_pw_passwd.pw_uid = atoi(cp);
216*41567Smarc 		if (!(cp = strsep(&bp, ":\n")))
21736859Sbostic 			continue;
21836859Sbostic 		_pw_passwd.pw_gid = atoi(cp);
219*41567Smarc 		_pw_passwd.pw_class = strsep(&bp, ":\n");
220*41567Smarc 		if (!(cp = strsep(&bp, ":\n")))
22136859Sbostic 			continue;
22236859Sbostic 		_pw_passwd.pw_change = atol(cp);
223*41567Smarc 		if (!(cp = strsep(&bp, ":\n")))
22436859Sbostic 			continue;
22536859Sbostic 		_pw_passwd.pw_expire = atol(cp);
226*41567Smarc 		_pw_passwd.pw_gecos = strsep(&bp, ":\n");
227*41567Smarc 		_pw_passwd.pw_dir = strsep(&bp, ":\n");
228*41567Smarc 		_pw_passwd.pw_shell = strsep(&bp, ":\n");
22936859Sbostic 		return(1);
23036859Sbostic 	}
23136859Sbostic 	/* NOTREACHED */
23236859Sbostic }
233