xref: /csrg-svn/old/mkpasswd/mkpasswd.c (revision 36859)
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*36859Sbostic static char sccsid[] = "@(#)mkpasswd.c	5.4 (Berkeley) 02/22/89";
2633137Sbostic #endif /* not lint */
2721151Sdist 
28*36859Sbostic #include <sys/param.h>
2915664Sralph #include <sys/file.h>
30*36859Sbostic #include <ndbm.h>
31*36859Sbostic #include <pwd.h>
3215664Sralph #include <stdio.h>
3315664Sralph 
34*36859Sbostic static FILE *_pw_fp;
35*36859Sbostic static struct passwd _pw_passwd;
36*36859Sbostic static off_t offset;
37*36859Sbostic 
38*36859Sbostic #define	MAXLINELENGTH	1024
39*36859Sbostic static char line[MAXLINELENGTH];
40*36859Sbostic 
41*36859Sbostic /*
42*36859Sbostic  * Mkpasswd does two things -- use the ``arg'' file to create ``arg''.{pag,dir}
43*36859Sbostic  * for ndbm, and, if the -p flag is on, create a password file in the original
44*36859Sbostic  * format.  It doesn't use the getpwent(3) routines because it has to figure
45*36859Sbostic  * out offsets for the encrypted passwords to put in the dbm files.  One other
46*36859Sbostic  * problem is that, since the addition of shadow passwords, getpwent(3) has to
47*36859Sbostic  * use the dbm databases rather than simply scanning the actual file.  This
48*36859Sbostic  * required the addition of a flag field to the dbm database to distinguish
49*36859Sbostic  * between a record keyed by name, and one keyed by uid.
50*36859Sbostic  */
51*36859Sbostic 
5215664Sralph main(argc, argv)
5333137Sbostic 	int argc;
54*36859Sbostic 	char **argv;
5515664Sralph {
56*36859Sbostic 	extern int errno, optind;
57*36859Sbostic 	register char *flag, *p, *t;
58*36859Sbostic 	register int makeold;
59*36859Sbostic 	FILE *oldfp;
6015664Sralph 	DBM *dp;
6115664Sralph 	datum key, content;
62*36859Sbostic 	int ch;
63*36859Sbostic 	char buf[8192], nbuf[50], *strerror();
6415664Sralph 
65*36859Sbostic 	makeold = 0;
66*36859Sbostic 	while ((ch = getopt(argc, argv, "pv")) != EOF)
67*36859Sbostic 		switch(ch) {
68*36859Sbostic 		case 'p':			/* create ``password.orig'' */
69*36859Sbostic 			makeold = 1;
70*36859Sbostic 			/* FALLTHROUGH */
71*36859Sbostic 		case 'v':			/* backward compatible */
72*36859Sbostic 			break;
73*36859Sbostic 		case '?':
74*36859Sbostic 		default:
75*36859Sbostic 			usage();
76*36859Sbostic 		}
77*36859Sbostic 	argc -= optind;
78*36859Sbostic 	argv += optind;
79*36859Sbostic 
80*36859Sbostic 	if (argc != 1)
81*36859Sbostic 		usage();
82*36859Sbostic 
83*36859Sbostic 	if (!(_pw_fp = fopen(*argv, "r"))) {
84*36859Sbostic 		(void)fprintf(stderr,
85*36859Sbostic 		    "mkpasswd: %s: can't open for reading.\n", *argv);
8615664Sralph 		exit(1);
8715664Sralph 	}
88*36859Sbostic 
89*36859Sbostic 	rmall(*argv);
9033137Sbostic 	(void)umask(0);
91*36859Sbostic 
92*36859Sbostic 	/* open old password format file, dbm files */
93*36859Sbostic 	if (makeold) {
94*36859Sbostic 		int oldfd;
95*36859Sbostic 
96*36859Sbostic 		(void)sprintf(buf, "%s.orig", *argv);
97*36859Sbostic 		if ((oldfd = open(buf, O_WRONLY|O_CREAT|O_EXCL, 0644)) < 0) {
98*36859Sbostic 			(void)fprintf(stderr, "mkpasswd: %s: %s\n", buf,
99*36859Sbostic 			    strerror(errno));
10017308Sralph 			exit(1);
10117308Sralph 		}
102*36859Sbostic 		if (!(oldfp = fdopen(oldfd, "w"))) {
103*36859Sbostic 			(void)fprintf(stderr, "mkpasswd: %s: fdopen failed.\n",
104*36859Sbostic 			    buf);
10517308Sralph 			exit(1);
10617308Sralph 		}
10715664Sralph 	}
108*36859Sbostic 	if (!(dp = dbm_open(*argv, O_WRONLY|O_CREAT|O_EXCL, 0644))) {
109*36859Sbostic 		(void)fprintf(stderr, "mkpasswd: %s: %s\n", *argv,
110*36859Sbostic 		    strerror(errno));
111*36859Sbostic 		exit(1);
112*36859Sbostic 	}
113*36859Sbostic 
114*36859Sbostic 	content.dptr = buf;
115*36859Sbostic 	while (scanpw()) {
116*36859Sbostic 		/* create dbm entry */
117*36859Sbostic 		p = buf;
118*36859Sbostic #define	COMPACT(e)	t = e; while (*p++ = *t++);
119*36859Sbostic 		COMPACT(_pw_passwd.pw_name);
120*36859Sbostic 		(void)sprintf(nbuf, "%ld", offset);
121*36859Sbostic 		COMPACT(nbuf);
122*36859Sbostic 		bcopy((char *)&_pw_passwd.pw_uid, p, sizeof(int));
123*36859Sbostic 		p += sizeof(int);
124*36859Sbostic 		bcopy((char *)&_pw_passwd.pw_gid, p, sizeof(int));
125*36859Sbostic 		p += sizeof(int);
126*36859Sbostic 		bcopy((char *)&_pw_passwd.pw_change, p, sizeof(time_t));
127*36859Sbostic 		p += sizeof(time_t);
128*36859Sbostic 		COMPACT(_pw_passwd.pw_class);
129*36859Sbostic 		COMPACT(_pw_passwd.pw_gecos);
130*36859Sbostic 		COMPACT(_pw_passwd.pw_dir);
131*36859Sbostic 		COMPACT(_pw_passwd.pw_shell);
132*36859Sbostic 		bcopy((char *)&_pw_passwd.pw_expire, p, sizeof(time_t));
133*36859Sbostic 		p += sizeof(time_t);
134*36859Sbostic 		flag = p;
135*36859Sbostic 		*p++ = _PW_KEYBYNAME;
136*36859Sbostic 		content.dsize = p - buf;
137*36859Sbostic #ifdef debug
138*36859Sbostic 		(void)printf("store %s, uid %d\n", _pw_passwd.pw_name,
139*36859Sbostic 		    _pw_passwd.pw_uid);
140*36859Sbostic #endif
141*36859Sbostic 		key.dptr = _pw_passwd.pw_name;
142*36859Sbostic 		key.dsize = strlen(_pw_passwd.pw_name);
143*36859Sbostic 		if (dbm_store(dp, key, content, DBM_INSERT) < 0)
144*36859Sbostic 			goto bad;
145*36859Sbostic 		key.dptr = (char *)&_pw_passwd.pw_uid;
146*36859Sbostic 		key.dsize = sizeof(int);
147*36859Sbostic 		*flag = _PW_KEYBYUID;
148*36859Sbostic 		if (dbm_store(dp, key, content, DBM_INSERT) < 0)
149*36859Sbostic 			goto bad;
150*36859Sbostic 
151*36859Sbostic 		/* create original format password file entry */
152*36859Sbostic 		if (!makeold)
153*36859Sbostic 			continue;
154*36859Sbostic 		fprintf(oldfp, "%s:*:%d:%d:%s:%s:%s\n", _pw_passwd.pw_name,
155*36859Sbostic 		    _pw_passwd.pw_uid, _pw_passwd.pw_gid, _pw_passwd.pw_gecos,
156*36859Sbostic 		    _pw_passwd.pw_dir, _pw_passwd.pw_shell);
157*36859Sbostic 	}
15817308Sralph 	dbm_close(dp);
15915664Sralph 	exit(0);
160*36859Sbostic 
161*36859Sbostic bad:	(void)fprintf(stderr, "mkpasswd: dbm_store failed.\n");
162*36859Sbostic 	rmall(*argv);
163*36859Sbostic 	exit(1);
16415664Sralph }
165*36859Sbostic 
166*36859Sbostic rmall(fname)
167*36859Sbostic 	char *fname;
168*36859Sbostic {
169*36859Sbostic 	register char *p;
170*36859Sbostic 	char buf[MAXPATHLEN], *strcpy();
171*36859Sbostic 
172*36859Sbostic 	for (p = strcpy(buf, fname); *p; ++p);
173*36859Sbostic 	bcopy(".pag", p, 5);
174*36859Sbostic 	(void)unlink(buf);
175*36859Sbostic 	bcopy(".dir", p, 5);
176*36859Sbostic 	(void)unlink(buf);
177*36859Sbostic 	bcopy(".orig", p, 6);
178*36859Sbostic 	(void)unlink(buf);
179*36859Sbostic }
180*36859Sbostic 
181*36859Sbostic usage()
182*36859Sbostic {
183*36859Sbostic 	(void)fprintf(stderr, "usage: mkpasswd [-p] passwd_file\n");
184*36859Sbostic 	exit(1);
185*36859Sbostic }
186*36859Sbostic 
187*36859Sbostic /* from libc/gen/getpwent.c */
188*36859Sbostic 
189*36859Sbostic static
190*36859Sbostic scanpw()
191*36859Sbostic {
192*36859Sbostic 	register char *cp;
193*36859Sbostic 	long atol(), ftell();
194*36859Sbostic 	char *fgets(), *strsep(), *index();
195*36859Sbostic 
196*36859Sbostic 	for (;;) {
197*36859Sbostic 		offset = ftell(_pw_fp);
198*36859Sbostic 		if (!(fgets(line, sizeof(line), _pw_fp)))
199*36859Sbostic 			return(0);
200*36859Sbostic 		/* skip lines that are too big */
201*36859Sbostic 		if (!index(line, '\n')) {
202*36859Sbostic 			int ch;
203*36859Sbostic 
204*36859Sbostic 			while ((ch = getc(_pw_fp)) != '\n' && ch != EOF)
205*36859Sbostic 				;
206*36859Sbostic 			continue;
207*36859Sbostic 		}
208*36859Sbostic 		_pw_passwd.pw_name = strsep(line, ":\n");
209*36859Sbostic 		_pw_passwd.pw_passwd = strsep((char *)NULL, ":\n");
210*36859Sbostic 		offset += _pw_passwd.pw_passwd - line;
211*36859Sbostic 		if (!(cp = strsep((char *)NULL, ":\n")))
212*36859Sbostic 			continue;
213*36859Sbostic 		_pw_passwd.pw_uid = atoi(cp);
214*36859Sbostic 		if (!(cp = strsep((char *)NULL, ":\n")))
215*36859Sbostic 			continue;
216*36859Sbostic 		_pw_passwd.pw_gid = atoi(cp);
217*36859Sbostic 		_pw_passwd.pw_class = strsep((char *)NULL, ":\n");
218*36859Sbostic 		if (!(cp = strsep((char *)NULL, ":\n")))
219*36859Sbostic 			continue;
220*36859Sbostic 		_pw_passwd.pw_change = atol(cp);
221*36859Sbostic 		if (!(cp = strsep((char *)NULL, ":\n")))
222*36859Sbostic 			continue;
223*36859Sbostic 		_pw_passwd.pw_expire = atol(cp);
224*36859Sbostic 		_pw_passwd.pw_gecos = strsep((char *)NULL, ":\n");
225*36859Sbostic 		_pw_passwd.pw_dir = strsep((char *)NULL, ":\n");
226*36859Sbostic 		_pw_passwd.pw_shell = strsep((char *)NULL, ":\n");
227*36859Sbostic 		return(1);
228*36859Sbostic 	}
229*36859Sbostic 	/* NOTREACHED */
230*36859Sbostic }
231