xref: /original-bsd/old/mkpasswd/mkpasswd.c (revision 29d43723)
1 /*
2  * Copyright (c) 1980, 1983 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #ifndef lint
19 char copyright[] =
20 "@(#) Copyright (c) 1980, 1983 Regents of the University of California.\n\
21  All rights reserved.\n";
22 #endif /* not lint */
23 
24 #ifndef lint
25 static char sccsid[] = "@(#)mkpasswd.c	5.4 (Berkeley) 02/22/89";
26 #endif /* not lint */
27 
28 #include <sys/param.h>
29 #include <sys/file.h>
30 #include <ndbm.h>
31 #include <pwd.h>
32 #include <stdio.h>
33 
34 static FILE *_pw_fp;
35 static struct passwd _pw_passwd;
36 static off_t offset;
37 
38 #define	MAXLINELENGTH	1024
39 static char line[MAXLINELENGTH];
40 
41 /*
42  * Mkpasswd does two things -- use the ``arg'' file to create ``arg''.{pag,dir}
43  * for ndbm, and, if the -p flag is on, create a password file in the original
44  * format.  It doesn't use the getpwent(3) routines because it has to figure
45  * out offsets for the encrypted passwords to put in the dbm files.  One other
46  * problem is that, since the addition of shadow passwords, getpwent(3) has to
47  * use the dbm databases rather than simply scanning the actual file.  This
48  * required the addition of a flag field to the dbm database to distinguish
49  * between a record keyed by name, and one keyed by uid.
50  */
51 
52 main(argc, argv)
53 	int argc;
54 	char **argv;
55 {
56 	extern int errno, optind;
57 	register char *flag, *p, *t;
58 	register int makeold;
59 	FILE *oldfp;
60 	DBM *dp;
61 	datum key, content;
62 	int ch;
63 	char buf[8192], nbuf[50], *strerror();
64 
65 	makeold = 0;
66 	while ((ch = getopt(argc, argv, "pv")) != EOF)
67 		switch(ch) {
68 		case 'p':			/* create ``password.orig'' */
69 			makeold = 1;
70 			/* FALLTHROUGH */
71 		case 'v':			/* backward compatible */
72 			break;
73 		case '?':
74 		default:
75 			usage();
76 		}
77 	argc -= optind;
78 	argv += optind;
79 
80 	if (argc != 1)
81 		usage();
82 
83 	if (!(_pw_fp = fopen(*argv, "r"))) {
84 		(void)fprintf(stderr,
85 		    "mkpasswd: %s: can't open for reading.\n", *argv);
86 		exit(1);
87 	}
88 
89 	rmall(*argv);
90 	(void)umask(0);
91 
92 	/* open old password format file, dbm files */
93 	if (makeold) {
94 		int oldfd;
95 
96 		(void)sprintf(buf, "%s.orig", *argv);
97 		if ((oldfd = open(buf, O_WRONLY|O_CREAT|O_EXCL, 0644)) < 0) {
98 			(void)fprintf(stderr, "mkpasswd: %s: %s\n", buf,
99 			    strerror(errno));
100 			exit(1);
101 		}
102 		if (!(oldfp = fdopen(oldfd, "w"))) {
103 			(void)fprintf(stderr, "mkpasswd: %s: fdopen failed.\n",
104 			    buf);
105 			exit(1);
106 		}
107 	}
108 	if (!(dp = dbm_open(*argv, O_WRONLY|O_CREAT|O_EXCL, 0644))) {
109 		(void)fprintf(stderr, "mkpasswd: %s: %s\n", *argv,
110 		    strerror(errno));
111 		exit(1);
112 	}
113 
114 	content.dptr = buf;
115 	while (scanpw()) {
116 		/* create dbm entry */
117 		p = buf;
118 #define	COMPACT(e)	t = e; while (*p++ = *t++);
119 		COMPACT(_pw_passwd.pw_name);
120 		(void)sprintf(nbuf, "%ld", offset);
121 		COMPACT(nbuf);
122 		bcopy((char *)&_pw_passwd.pw_uid, p, sizeof(int));
123 		p += sizeof(int);
124 		bcopy((char *)&_pw_passwd.pw_gid, p, sizeof(int));
125 		p += sizeof(int);
126 		bcopy((char *)&_pw_passwd.pw_change, p, sizeof(time_t));
127 		p += sizeof(time_t);
128 		COMPACT(_pw_passwd.pw_class);
129 		COMPACT(_pw_passwd.pw_gecos);
130 		COMPACT(_pw_passwd.pw_dir);
131 		COMPACT(_pw_passwd.pw_shell);
132 		bcopy((char *)&_pw_passwd.pw_expire, p, sizeof(time_t));
133 		p += sizeof(time_t);
134 		flag = p;
135 		*p++ = _PW_KEYBYNAME;
136 		content.dsize = p - buf;
137 #ifdef debug
138 		(void)printf("store %s, uid %d\n", _pw_passwd.pw_name,
139 		    _pw_passwd.pw_uid);
140 #endif
141 		key.dptr = _pw_passwd.pw_name;
142 		key.dsize = strlen(_pw_passwd.pw_name);
143 		if (dbm_store(dp, key, content, DBM_INSERT) < 0)
144 			goto bad;
145 		key.dptr = (char *)&_pw_passwd.pw_uid;
146 		key.dsize = sizeof(int);
147 		*flag = _PW_KEYBYUID;
148 		if (dbm_store(dp, key, content, DBM_INSERT) < 0)
149 			goto bad;
150 
151 		/* create original format password file entry */
152 		if (!makeold)
153 			continue;
154 		fprintf(oldfp, "%s:*:%d:%d:%s:%s:%s\n", _pw_passwd.pw_name,
155 		    _pw_passwd.pw_uid, _pw_passwd.pw_gid, _pw_passwd.pw_gecos,
156 		    _pw_passwd.pw_dir, _pw_passwd.pw_shell);
157 	}
158 	dbm_close(dp);
159 	exit(0);
160 
161 bad:	(void)fprintf(stderr, "mkpasswd: dbm_store failed.\n");
162 	rmall(*argv);
163 	exit(1);
164 }
165 
166 rmall(fname)
167 	char *fname;
168 {
169 	register char *p;
170 	char buf[MAXPATHLEN], *strcpy();
171 
172 	for (p = strcpy(buf, fname); *p; ++p);
173 	bcopy(".pag", p, 5);
174 	(void)unlink(buf);
175 	bcopy(".dir", p, 5);
176 	(void)unlink(buf);
177 	bcopy(".orig", p, 6);
178 	(void)unlink(buf);
179 }
180 
181 usage()
182 {
183 	(void)fprintf(stderr, "usage: mkpasswd [-p] passwd_file\n");
184 	exit(1);
185 }
186 
187 /* from libc/gen/getpwent.c */
188 
189 static
190 scanpw()
191 {
192 	register char *cp;
193 	long atol(), ftell();
194 	char *fgets(), *strsep(), *index();
195 
196 	for (;;) {
197 		offset = ftell(_pw_fp);
198 		if (!(fgets(line, sizeof(line), _pw_fp)))
199 			return(0);
200 		/* skip lines that are too big */
201 		if (!index(line, '\n')) {
202 			int ch;
203 
204 			while ((ch = getc(_pw_fp)) != '\n' && ch != EOF)
205 				;
206 			continue;
207 		}
208 		_pw_passwd.pw_name = strsep(line, ":\n");
209 		_pw_passwd.pw_passwd = strsep((char *)NULL, ":\n");
210 		offset += _pw_passwd.pw_passwd - line;
211 		if (!(cp = strsep((char *)NULL, ":\n")))
212 			continue;
213 		_pw_passwd.pw_uid = atoi(cp);
214 		if (!(cp = strsep((char *)NULL, ":\n")))
215 			continue;
216 		_pw_passwd.pw_gid = atoi(cp);
217 		_pw_passwd.pw_class = strsep((char *)NULL, ":\n");
218 		if (!(cp = strsep((char *)NULL, ":\n")))
219 			continue;
220 		_pw_passwd.pw_change = atol(cp);
221 		if (!(cp = strsep((char *)NULL, ":\n")))
222 			continue;
223 		_pw_passwd.pw_expire = atol(cp);
224 		_pw_passwd.pw_gecos = strsep((char *)NULL, ":\n");
225 		_pw_passwd.pw_dir = strsep((char *)NULL, ":\n");
226 		_pw_passwd.pw_shell = strsep((char *)NULL, ":\n");
227 		return(1);
228 	}
229 	/* NOTREACHED */
230 }
231