pwd_mkdb.c revision 1.36 1 1.36 jmmv /* $NetBSD: pwd_mkdb.c,v 1.36 2009/01/16 10:42:36 jmmv Exp $ */
2 1.36 jmmv
3 1.36 jmmv /*
4 1.36 jmmv * Copyright (c) 2000, 2009 The NetBSD Foundation, Inc.
5 1.36 jmmv * All rights reserved.
6 1.36 jmmv *
7 1.36 jmmv * Redistribution and use in source and binary forms, with or without
8 1.36 jmmv * modification, are permitted provided that the following conditions
9 1.36 jmmv * are met:
10 1.36 jmmv * 1. Redistributions of source code must retain the above copyright
11 1.36 jmmv * notice, this list of conditions and the following disclaimer.
12 1.36 jmmv * 2. Redistributions in binary form must reproduce the above copyright
13 1.36 jmmv * notice, this list of conditions and the following disclaimer in the
14 1.36 jmmv * documentation and/or other materials provided with the distribution.
15 1.36 jmmv *
16 1.36 jmmv * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 1.36 jmmv * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 1.36 jmmv * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 1.36 jmmv * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 1.36 jmmv * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 1.36 jmmv * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 1.36 jmmv * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 1.36 jmmv * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 1.36 jmmv * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 1.36 jmmv * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 1.36 jmmv * POSSIBILITY OF SUCH DAMAGE.
27 1.36 jmmv */
28 1.19 ad
29 1.11 fair /*
30 1.5 mycroft * Copyright (c) 1991, 1993, 1994
31 1.5 mycroft * The Regents of the University of California. All rights reserved.
32 1.26 agc *
33 1.26 agc * Redistribution and use in source and binary forms, with or without
34 1.26 agc * modification, are permitted provided that the following conditions
35 1.26 agc * are met:
36 1.26 agc * 1. Redistributions of source code must retain the above copyright
37 1.26 agc * notice, this list of conditions and the following disclaimer.
38 1.26 agc * 2. Redistributions in binary form must reproduce the above copyright
39 1.26 agc * notice, this list of conditions and the following disclaimer in the
40 1.26 agc * documentation and/or other materials provided with the distribution.
41 1.26 agc * 3. Neither the name of the University nor the names of its contributors
42 1.26 agc * may be used to endorse or promote products derived from this software
43 1.26 agc * without specific prior written permission.
44 1.26 agc *
45 1.26 agc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46 1.26 agc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 1.26 agc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 1.26 agc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49 1.26 agc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 1.26 agc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 1.26 agc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 1.26 agc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 1.26 agc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 1.26 agc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 1.26 agc * SUCH DAMAGE.
56 1.26 agc */
57 1.26 agc
58 1.26 agc /*
59 1.6 phil * Portions Copyright(C) 1994, Jason Downs. All rights reserved.
60 1.1 cgd *
61 1.1 cgd * Redistribution and use in source and binary forms, with or without
62 1.1 cgd * modification, are permitted provided that the following conditions
63 1.1 cgd * are met:
64 1.1 cgd * 1. Redistributions of source code must retain the above copyright
65 1.1 cgd * notice, this list of conditions and the following disclaimer.
66 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright
67 1.1 cgd * notice, this list of conditions and the following disclaimer in the
68 1.1 cgd * documentation and/or other materials provided with the distribution.
69 1.1 cgd *
70 1.27 agc * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
71 1.27 agc * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
72 1.27 agc * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
73 1.27 agc * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
74 1.27 agc * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
75 1.27 agc * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
76 1.27 agc * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
77 1.27 agc * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
78 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
79 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
80 1.1 cgd * SUCH DAMAGE.
81 1.1 cgd */
82 1.1 cgd
83 1.28 lukem #if HAVE_NBTOOL_CONFIG_H
84 1.28 lukem #include "nbtool_config.h"
85 1.23 tv #endif
86 1.23 tv
87 1.10 lukem #include <sys/cdefs.h>
88 1.28 lukem #if !defined(lint)
89 1.36 jmmv __COPYRIGHT("@(#) Copyright (c) 2000, 2009\
90 1.34 lukem The NetBSD Foundation, Inc. All rights reserved.\
91 1.34 lukem Copyright (c) 1991, 1993, 1994\
92 1.34 lukem The Regents of the University of California. All rights reserved.");
93 1.17 mycroft __SCCSID("from: @(#)pwd_mkdb.c 8.5 (Berkeley) 4/20/94");
94 1.36 jmmv __RCSID("$NetBSD: pwd_mkdb.c,v 1.36 2009/01/16 10:42:36 jmmv Exp $");
95 1.1 cgd #endif /* not lint */
96 1.1 cgd
97 1.29 jmc #if HAVE_NBTOOL_CONFIG_H
98 1.29 jmc #include "compat_pwd.h"
99 1.29 jmc #else
100 1.29 jmc #include <pwd.h>
101 1.29 jmc #endif
102 1.29 jmc
103 1.1 cgd #include <sys/param.h>
104 1.1 cgd #include <sys/stat.h>
105 1.5 mycroft
106 1.1 cgd #include <db.h>
107 1.24 tv #include <err.h>
108 1.1 cgd #include <errno.h>
109 1.5 mycroft #include <fcntl.h>
110 1.1 cgd #include <limits.h>
111 1.5 mycroft #include <signal.h>
112 1.1 cgd #include <stdio.h>
113 1.5 mycroft #include <stdlib.h>
114 1.1 cgd #include <string.h>
115 1.5 mycroft #include <unistd.h>
116 1.24 tv #include <util.h>
117 1.23 tv
118 1.22 ad #define MAX_CACHESIZE 8*1024*1024
119 1.22 ad #define MIN_CACHESIZE 2*1024*1024
120 1.22 ad
121 1.19 ad #define PERM_INSECURE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
122 1.19 ad #define PERM_SECURE (S_IRUSR | S_IWUSR)
123 1.1 cgd
124 1.28 lukem #if HAVE_NBTOOL_CONFIG_H
125 1.23 tv static const char __yp_token[] = "__YP!";
126 1.23 tv #else
127 1.22 ad /* Pull this out of the C library. */
128 1.6 phil extern const char __yp_token[];
129 1.23 tv #endif
130 1.6 phil
131 1.5 mycroft HASHINFO openinfo = {
132 1.5 mycroft 4096, /* bsize */
133 1.5 mycroft 32, /* ffactor */
134 1.5 mycroft 256, /* nelem */
135 1.22 ad 0, /* cachesize */
136 1.5 mycroft NULL, /* hash() */
137 1.5 mycroft 0 /* lorder */
138 1.5 mycroft };
139 1.1 cgd
140 1.22 ad #define FILE_INSECURE 0x01
141 1.22 ad #define FILE_SECURE 0x02
142 1.22 ad #define FILE_ORIG 0x04
143 1.22 ad
144 1.22 ad static char *pname; /* password file name */
145 1.22 ad static char prefix[MAXPATHLEN];
146 1.22 ad static char oldpwdfile[MAX(MAXPATHLEN, LINE_MAX * 2)];
147 1.22 ad static char pwd_db_tmp[MAX(MAXPATHLEN, LINE_MAX * 2)];
148 1.22 ad static char pwd_Sdb_tmp[MAX(MAXPATHLEN, LINE_MAX * 2)];
149 1.22 ad static int lorder = BYTE_ORDER;
150 1.22 ad static int clean;
151 1.22 ad
152 1.22 ad void bailout(void);
153 1.22 ad void cp(const char *, const char *, mode_t);
154 1.22 ad int deldbent(DB *, const char *, int, void *);
155 1.19 ad void error(const char *);
156 1.22 ad int getdbent(DB *, const char *, int, void *, struct passwd **);
157 1.22 ad void inconsistancy(void);
158 1.22 ad void install(const char *, const char *);
159 1.19 ad int main(int, char **);
160 1.22 ad void putdbents(DB *, struct passwd *, const char *, int, const char *, int,
161 1.22 ad int, int);
162 1.22 ad void putyptoken(DB *, const char *);
163 1.19 ad void rm(const char *);
164 1.19 ad int scan(FILE *, struct passwd *, int *, int *);
165 1.19 ad void usage(void);
166 1.22 ad void wr_error(const char *);
167 1.36 jmmv void checkversion(DB *);
168 1.36 jmmv uint32_t getversion(void);
169 1.35 christos void setversion(DB *);
170 1.35 christos
171 1.35 christos static __inline uint16_t swap16(uint16_t sw)
172 1.35 christos {
173 1.35 christos return ((sw & 0x00ff) << 8) |
174 1.35 christos ((sw & 0xff00) >> 8);
175 1.35 christos }
176 1.35 christos
177 1.35 christos static __inline uint32_t swap32(uint32_t sw) {
178 1.35 christos return ((sw & 0x000000ff) << 24) |
179 1.35 christos ((sw & 0x0000ff00) << 8) |
180 1.35 christos ((sw & 0x00ff0000) >> 8) |
181 1.35 christos ((sw & 0xff000000) >> 24);
182 1.35 christos }
183 1.35 christos
184 1.35 christos static __inline uint64_t swap64(uint64_t sw) {
185 1.35 christos return ((sw & 0x00000000000000ffULL) << 56) |
186 1.35 christos ((sw & 0x000000000000ff00ULL) << 40) |
187 1.35 christos ((sw & 0x0000000000ff0000ULL) >> 24) |
188 1.35 christos ((sw & 0x00000000ff000000ULL) << 8) |
189 1.35 christos ((sw & 0x000000ff00000000ULL) >> 8) |
190 1.35 christos ((sw & 0x0000ff0000000000ULL) >> 24) |
191 1.35 christos ((sw & 0x00ff000000000000ULL) >> 40) |
192 1.35 christos ((sw & 0xff00000000000000ULL) >> 56);
193 1.35 christos }
194 1.35 christos
195 1.35 christos #define SWAP(sw) \
196 1.35 christos ((sizeof(sw) == 2 ? (typeof(sw))swap16((uint16_t)sw) : \
197 1.35 christos (sizeof(sw) == 4 ? (typeof(sw))swap32((uint32_t)sw) : \
198 1.35 christos (sizeof(sw) == 8 ? (typeof(sw))swap64((uint64_t)sw) : abort(), 0))))
199 1.5 mycroft
200 1.5 mycroft int
201 1.19 ad main(int argc, char *argv[])
202 1.1 cgd {
203 1.22 ad int ch, makeold, tfd, lineno, found, rv, hasyp, secureonly;
204 1.22 ad struct passwd pwd, *tpwd;
205 1.22 ad char *username;
206 1.5 mycroft DB *dp, *edp;
207 1.1 cgd FILE *fp, *oldfp;
208 1.1 cgd sigset_t set;
209 1.22 ad int dbflg, uid_dbflg, newuser, olduid, flags;
210 1.22 ad char buf[MAXPATHLEN];
211 1.22 ad struct stat st;
212 1.22 ad u_int cachesize;
213 1.1 cgd
214 1.21 tron prefix[0] = '\0';
215 1.1 cgd makeold = 0;
216 1.22 ad oldfp = NULL;
217 1.22 ad username = NULL;
218 1.22 ad hasyp = 0;
219 1.22 ad secureonly = 0;
220 1.30 lukem found = 0;
221 1.30 lukem newuser = 0;
222 1.30 lukem dp = NULL;
223 1.31 sketch cachesize = 0;
224 1.22 ad
225 1.31 sketch while ((ch = getopt(argc, argv, "BLc:d:psu:v")) != -1)
226 1.22 ad switch (ch) {
227 1.22 ad case 'B': /* big-endian output */
228 1.22 ad lorder = BIG_ENDIAN;
229 1.22 ad break;
230 1.22 ad case 'L': /* little-endian output */
231 1.22 ad lorder = LITTLE_ENDIAN;
232 1.22 ad break;
233 1.31 sketch case 'c':
234 1.31 sketch cachesize = atoi(optarg) * 1024 * 1024;
235 1.31 sketch break;
236 1.19 ad case 'd': /* set prefix */
237 1.25 itojun strlcpy(prefix, optarg, sizeof(prefix));
238 1.8 lukem break;
239 1.1 cgd case 'p': /* create V7 "file.orig" */
240 1.1 cgd makeold = 1;
241 1.1 cgd break;
242 1.22 ad case 's': /* modify secure db only */
243 1.22 ad secureonly = 1;
244 1.1 cgd break;
245 1.22 ad case 'u': /* modify one user only */
246 1.22 ad username = optarg;
247 1.17 mycroft break;
248 1.22 ad case 'v': /* backward compatible */
249 1.17 mycroft break;
250 1.1 cgd case '?':
251 1.1 cgd default:
252 1.1 cgd usage();
253 1.1 cgd }
254 1.1 cgd argc -= optind;
255 1.1 cgd argv += optind;
256 1.1 cgd
257 1.1 cgd if (argc != 1)
258 1.1 cgd usage();
259 1.22 ad if (username != NULL)
260 1.22 ad if (username[0] == '+' || username[0] == '-')
261 1.22 ad usage();
262 1.22 ad if (secureonly)
263 1.22 ad makeold = 0;
264 1.4 cgd
265 1.1 cgd /*
266 1.5 mycroft * This could be changed to allow the user to interrupt.
267 1.5 mycroft * Probably not worth the effort.
268 1.1 cgd */
269 1.1 cgd sigemptyset(&set);
270 1.1 cgd sigaddset(&set, SIGTSTP);
271 1.1 cgd sigaddset(&set, SIGHUP);
272 1.1 cgd sigaddset(&set, SIGINT);
273 1.1 cgd sigaddset(&set, SIGQUIT);
274 1.1 cgd sigaddset(&set, SIGTERM);
275 1.1 cgd (void)sigprocmask(SIG_BLOCK, &set, (sigset_t *)NULL);
276 1.1 cgd
277 1.5 mycroft /* We don't care what the user wants. */
278 1.5 mycroft (void)umask(0);
279 1.5 mycroft
280 1.22 ad if (username == NULL)
281 1.22 ad flags = O_RDWR | O_CREAT | O_EXCL;
282 1.22 ad else
283 1.22 ad flags = O_RDWR;
284 1.22 ad
285 1.1 cgd pname = *argv;
286 1.1 cgd /* Open the original password file */
287 1.19 ad if ((fp = fopen(pname, "r")) == NULL)
288 1.1 cgd error(pname);
289 1.1 cgd
290 1.17 mycroft openinfo.lorder = lorder;
291 1.17 mycroft
292 1.22 ad if (fstat(fileno(fp), &st) == -1)
293 1.22 ad error(pname);
294 1.22 ad
295 1.31 sketch if (cachesize) {
296 1.31 sketch openinfo.cachesize = cachesize;
297 1.31 sketch } else {
298 1.31 sketch /* Tweak openinfo values for large passwd files. */
299 1.31 sketch cachesize = st.st_size * 20;
300 1.31 sketch if (cachesize > MAX_CACHESIZE)
301 1.31 sketch cachesize = MAX_CACHESIZE;
302 1.31 sketch else if (cachesize < MIN_CACHESIZE)
303 1.31 sketch cachesize = MIN_CACHESIZE;
304 1.31 sketch openinfo.cachesize = cachesize;
305 1.31 sketch }
306 1.22 ad
307 1.1 cgd /* Open the temporary insecure password database. */
308 1.22 ad if (!secureonly) {
309 1.22 ad (void)snprintf(pwd_db_tmp, sizeof(pwd_db_tmp), "%s%s.tmp",
310 1.22 ad prefix, _PATH_MP_DB);
311 1.22 ad if (username != NULL) {
312 1.22 ad snprintf(buf, sizeof(buf), "%s" _PATH_MP_DB, prefix);
313 1.22 ad cp(buf, pwd_db_tmp, PERM_INSECURE);
314 1.22 ad }
315 1.22 ad dp = dbopen(pwd_db_tmp, flags, PERM_INSECURE, DB_HASH,
316 1.22 ad &openinfo);
317 1.22 ad if (dp == NULL)
318 1.22 ad error(pwd_db_tmp);
319 1.22 ad clean |= FILE_INSECURE;
320 1.36 jmmv if (username != NULL)
321 1.36 jmmv checkversion(dp);
322 1.36 jmmv else
323 1.36 jmmv setversion(dp);
324 1.22 ad }
325 1.22 ad
326 1.22 ad /* Open the temporary encrypted password database. */
327 1.22 ad (void)snprintf(pwd_Sdb_tmp, sizeof(pwd_Sdb_tmp), "%s%s.tmp", prefix,
328 1.22 ad _PATH_SMP_DB);
329 1.22 ad if (username != NULL) {
330 1.22 ad snprintf(buf, sizeof(buf), "%s" _PATH_SMP_DB, prefix);
331 1.22 ad cp(buf, pwd_Sdb_tmp, PERM_SECURE);
332 1.22 ad }
333 1.22 ad edp = dbopen(pwd_Sdb_tmp, flags, PERM_SECURE, DB_HASH, &openinfo);
334 1.22 ad if (!edp)
335 1.22 ad error(pwd_Sdb_tmp);
336 1.22 ad clean |= FILE_SECURE;
337 1.36 jmmv if (username != NULL)
338 1.36 jmmv checkversion(edp);
339 1.36 jmmv else
340 1.36 jmmv setversion(edp);
341 1.1 cgd
342 1.1 cgd /*
343 1.1 cgd * Open file for old password file. Minor trickiness -- don't want to
344 1.1 cgd * chance the file already existing, since someone (stupidly) might
345 1.1 cgd * still be using this for permission checking. So, open it first and
346 1.5 mycroft * fdopen the resulting fd. The resulting file should be readable by
347 1.5 mycroft * everyone.
348 1.1 cgd */
349 1.1 cgd if (makeold) {
350 1.11 fair (void)snprintf(oldpwdfile, sizeof(oldpwdfile), "%s.orig",
351 1.19 ad pname);
352 1.19 ad if ((tfd = open(oldpwdfile, O_WRONLY | O_CREAT | O_EXCL,
353 1.19 ad PERM_INSECURE)) < 0)
354 1.11 fair error(oldpwdfile);
355 1.22 ad clean |= FILE_ORIG;
356 1.5 mycroft if ((oldfp = fdopen(tfd, "w")) == NULL)
357 1.11 fair error(oldpwdfile);
358 1.22 ad }
359 1.22 ad
360 1.22 ad if (username != NULL) {
361 1.22 ad uid_dbflg = 0;
362 1.22 ad dbflg = 0;
363 1.22 ad
364 1.22 ad /*
365 1.22 ad * Determine if this is a new entry.
366 1.22 ad */
367 1.22 ad if (getdbent(edp, pwd_Sdb_tmp, _PW_KEYBYNAME, username, &tpwd))
368 1.22 ad newuser = 1;
369 1.22 ad else {
370 1.22 ad newuser = 0;
371 1.22 ad olduid = tpwd->pw_uid;
372 1.22 ad }
373 1.22 ad
374 1.22 ad } else {
375 1.22 ad uid_dbflg = R_NOOVERWRITE;
376 1.22 ad dbflg = R_NOOVERWRITE;
377 1.1 cgd }
378 1.1 cgd
379 1.1 cgd /*
380 1.6 phil * If we see something go by that looks like YP, we save a special
381 1.6 phil * pointer record, which if YP is enabled in the C lib, will speed
382 1.6 phil * things up.
383 1.1 cgd */
384 1.19 ad for (lineno = 0; scan(fp, &pwd, &flags, &lineno);) {
385 1.9 thorpej /*
386 1.22 ad * Create original format password file entry.
387 1.9 thorpej */
388 1.11 fair if (makeold) {
389 1.5 mycroft (void)fprintf(oldfp, "%s:*:%d:%d:%s:%s:%s\n",
390 1.5 mycroft pwd.pw_name, pwd.pw_uid, pwd.pw_gid, pwd.pw_gecos,
391 1.5 mycroft pwd.pw_dir, pwd.pw_shell);
392 1.19 ad if (ferror(oldfp))
393 1.11 fair wr_error(oldpwdfile);
394 1.11 fair }
395 1.22 ad
396 1.22 ad if (username == NULL) {
397 1.22 ad /* Look like YP? */
398 1.22 ad if (pwd.pw_name[0] == '+' || pwd.pw_name[0] == '-')
399 1.22 ad hasyp++;
400 1.22 ad
401 1.22 ad /* Warn about potentially unsafe uid/gid overrides. */
402 1.22 ad if (pwd.pw_name[0] == '+') {
403 1.22 ad if ((flags & _PASSWORD_NOUID) == 0 &&
404 1.22 ad pwd.pw_uid == 0)
405 1.22 ad warnx("line %d: superuser override "
406 1.22 ad "in YP inclusion", lineno);
407 1.22 ad if ((flags & _PASSWORD_NOGID) == 0 &&
408 1.22 ad pwd.pw_gid == 0)
409 1.22 ad warnx("line %d: wheel override "
410 1.22 ad "in YP inclusion", lineno);
411 1.22 ad }
412 1.22 ad
413 1.22 ad /* Write the database entry out. */
414 1.22 ad if (!secureonly)
415 1.22 ad putdbents(dp, &pwd, "*", flags, pwd_db_tmp,
416 1.22 ad lineno, dbflg, uid_dbflg);
417 1.22 ad continue;
418 1.22 ad } else if (strcmp(username, pwd.pw_name) != 0)
419 1.22 ad continue;
420 1.22 ad
421 1.22 ad if (found) {
422 1.22 ad warnx("user `%s' listed twice in password file",
423 1.22 ad username);
424 1.22 ad bailout();
425 1.22 ad }
426 1.22 ad
427 1.22 ad /*
428 1.22 ad * Ensure that the text file and database agree on
429 1.22 ad * which line the record is from.
430 1.22 ad */
431 1.22 ad rv = getdbent(edp, pwd_Sdb_tmp, _PW_KEYBYNUM, &lineno, &tpwd);
432 1.22 ad if (newuser) {
433 1.22 ad if (rv == 0)
434 1.22 ad inconsistancy();
435 1.22 ad } else if (rv == -1 ||
436 1.22 ad strcmp(username, tpwd->pw_name) != 0)
437 1.22 ad inconsistancy();
438 1.22 ad else if (olduid != pwd.pw_uid) {
439 1.22 ad /*
440 1.22 ad * If we're changing UID, remove the BYUID
441 1.22 ad * record for the old UID only if it has the
442 1.22 ad * same username.
443 1.22 ad */
444 1.22 ad if (!getdbent(edp, pwd_Sdb_tmp, _PW_KEYBYUID, &olduid,
445 1.22 ad &tpwd)) {
446 1.22 ad if (strcmp(username, tpwd->pw_name) == 0) {
447 1.22 ad if (!secureonly)
448 1.22 ad deldbent(dp, pwd_db_tmp,
449 1.22 ad _PW_KEYBYUID, &olduid);
450 1.22 ad deldbent(edp, pwd_Sdb_tmp,
451 1.22 ad _PW_KEYBYUID, &olduid);
452 1.22 ad }
453 1.22 ad } else
454 1.22 ad inconsistancy();
455 1.22 ad }
456 1.22 ad
457 1.22 ad /*
458 1.22 ad * If there's an existing BYUID record for the new UID and
459 1.22 ad * the username doesn't match then be sure not to overwrite
460 1.22 ad * it.
461 1.22 ad */
462 1.22 ad if (!getdbent(edp, pwd_Sdb_tmp, _PW_KEYBYUID, &pwd.pw_uid,
463 1.22 ad &tpwd))
464 1.22 ad if (strcmp(username, tpwd->pw_name) != 0)
465 1.22 ad uid_dbflg = R_NOOVERWRITE;
466 1.22 ad
467 1.22 ad /* Write the database entries out */
468 1.22 ad if (!secureonly)
469 1.22 ad putdbents(dp, &pwd, "*", flags, pwd_db_tmp, lineno,
470 1.22 ad dbflg, uid_dbflg);
471 1.22 ad putdbents(edp, &pwd, pwd.pw_passwd, flags, pwd_Sdb_tmp,
472 1.22 ad lineno, dbflg, uid_dbflg);
473 1.22 ad
474 1.22 ad found = 1;
475 1.22 ad if (!makeold)
476 1.22 ad break;
477 1.22 ad }
478 1.22 ad
479 1.22 ad if (!secureonly) {
480 1.22 ad /* Store YP token if needed. */
481 1.22 ad if (hasyp)
482 1.22 ad putyptoken(dp, pwd_db_tmp);
483 1.22 ad
484 1.22 ad /* Close the insecure database. */
485 1.22 ad if ((*dp->close)(dp) < 0)
486 1.22 ad wr_error(pwd_db_tmp);
487 1.22 ad }
488 1.22 ad
489 1.22 ad /*
490 1.22 ad * If rebuilding the databases, we re-parse the text file and write
491 1.22 ad * the secure entries out in a separate pass.
492 1.22 ad */
493 1.22 ad if (username == NULL) {
494 1.22 ad rewind(fp);
495 1.22 ad for (lineno = 0; scan(fp, &pwd, &flags, &lineno);)
496 1.22 ad putdbents(edp, &pwd, pwd.pw_passwd, flags, pwd_Sdb_tmp,
497 1.22 ad lineno, dbflg, uid_dbflg);
498 1.22 ad
499 1.22 ad /* Store YP token if needed. */
500 1.22 ad if (hasyp)
501 1.22 ad putyptoken(edp, pwd_Sdb_tmp);
502 1.22 ad } else if (!found) {
503 1.22 ad warnx("user `%s' not found in password file", username);
504 1.22 ad bailout();
505 1.5 mycroft }
506 1.6 phil
507 1.22 ad /* Close the secure database. */
508 1.22 ad if ((*edp->close)(edp) < 0)
509 1.22 ad wr_error(pwd_Sdb_tmp);
510 1.22 ad
511 1.22 ad /* Install as the real password files. */
512 1.22 ad if (!secureonly)
513 1.22 ad install(pwd_db_tmp, _PATH_MP_DB);
514 1.22 ad install(pwd_Sdb_tmp, _PATH_SMP_DB);
515 1.6 phil
516 1.22 ad /* Install the V7 password file. */
517 1.5 mycroft if (makeold) {
518 1.19 ad if (fflush(oldfp) == EOF)
519 1.11 fair wr_error(oldpwdfile);
520 1.19 ad if (fclose(oldfp) == EOF)
521 1.11 fair wr_error(oldpwdfile);
522 1.22 ad install(oldpwdfile, _PATH_PASSWD);
523 1.5 mycroft }
524 1.5 mycroft
525 1.1 cgd /* Set master.passwd permissions, in case caller forgot. */
526 1.1 cgd (void)fchmod(fileno(fp), S_IRUSR|S_IWUSR);
527 1.19 ad if (fclose(fp) == EOF)
528 1.11 fair wr_error(pname);
529 1.1 cgd
530 1.19 ad /*
531 1.22 ad * Move the temporary master password file LAST -- chpass(1),
532 1.33 wiz * passwd(1), vipw(8) and friends all use its existence to block
533 1.22 ad * other incarnations of themselves. The rename means that
534 1.22 ad * everything is unlocked, as the original file can no longer be
535 1.22 ad * accessed.
536 1.19 ad */
537 1.19 ad install(pname, _PATH_MASTERPASSWD);
538 1.19 ad exit(EXIT_SUCCESS);
539 1.19 ad /* NOTREACHED */
540 1.1 cgd }
541 1.1 cgd
542 1.5 mycroft int
543 1.19 ad scan(FILE *fp, struct passwd *pw, int *flags, int *lineno)
544 1.1 cgd {
545 1.1 cgd static char line[LINE_MAX];
546 1.1 cgd char *p;
547 1.17 mycroft int oflags;
548 1.1 cgd
549 1.19 ad if (fgets(line, sizeof(line), fp) == NULL)
550 1.5 mycroft return (0);
551 1.19 ad (*lineno)++;
552 1.19 ad
553 1.1 cgd /*
554 1.1 cgd * ``... if I swallow anything evil, put your fingers down my
555 1.1 cgd * throat...''
556 1.1 cgd * -- The Who
557 1.1 cgd */
558 1.19 ad if ((p = strchr(line, '\n')) == NULL) {
559 1.5 mycroft warnx("line too long");
560 1.19 ad errno = EFTYPE; /* XXX */
561 1.19 ad error(pname);
562 1.1 cgd }
563 1.1 cgd *p = '\0';
564 1.15 lukem if (strcmp(line, "+") == 0)
565 1.15 lukem strcpy(line, "+:::::::::"); /* pw_scan() can't handle "+" */
566 1.17 mycroft oflags = 0;
567 1.17 mycroft if (!pw_scan(line, pw, &oflags)) {
568 1.19 ad warnx("at line #%d", *lineno);
569 1.19 ad errno = EFTYPE; /* XXX */
570 1.1 cgd error(pname);
571 1.1 cgd }
572 1.17 mycroft *flags = oflags;
573 1.5 mycroft
574 1.5 mycroft return (1);
575 1.1 cgd }
576 1.1 cgd
577 1.5 mycroft void
578 1.19 ad install(const char *from, const char *to)
579 1.1 cgd {
580 1.1 cgd char buf[MAXPATHLEN];
581 1.32 sketch char errbuf[BUFSIZ];
582 1.19 ad int sverrno;
583 1.1 cgd
584 1.19 ad snprintf(buf, sizeof(buf), "%s%s", prefix, to);
585 1.19 ad if (rename(from, buf)) {
586 1.19 ad sverrno = errno;
587 1.32 sketch (void)snprintf(errbuf, sizeof(errbuf), "%s to %s", from, buf);
588 1.1 cgd errno = sverrno;
589 1.32 sketch error(errbuf);
590 1.1 cgd }
591 1.1 cgd }
592 1.1 cgd
593 1.5 mycroft void
594 1.22 ad rm(const char *victim)
595 1.22 ad {
596 1.22 ad
597 1.22 ad if (unlink(victim) < 0)
598 1.22 ad warn("unlink(%s)", victim);
599 1.22 ad }
600 1.22 ad
601 1.22 ad void
602 1.22 ad cp(const char *from, const char *to, mode_t mode)
603 1.22 ad {
604 1.22 ad static char buf[MAXBSIZE];
605 1.22 ad int from_fd, rcount, to_fd, wcount, sverrno;
606 1.22 ad
607 1.22 ad if ((from_fd = open(from, O_RDONLY, 0)) < 0)
608 1.22 ad error(from);
609 1.22 ad if ((to_fd = open(to, O_WRONLY | O_CREAT | O_EXCL, mode)) < 0)
610 1.22 ad error(to);
611 1.22 ad while ((rcount = read(from_fd, buf, MAXBSIZE)) > 0) {
612 1.22 ad wcount = write(to_fd, buf, rcount);
613 1.22 ad if (rcount != wcount || wcount == -1) {
614 1.22 ad sverrno = errno;
615 1.22 ad (void)snprintf(buf, sizeof(buf), "%s to %s", from, to);
616 1.22 ad errno = sverrno;
617 1.22 ad error(buf);
618 1.22 ad }
619 1.22 ad }
620 1.22 ad
621 1.22 ad if (rcount < 0) {
622 1.22 ad sverrno = errno;
623 1.22 ad (void)snprintf(buf, sizeof(buf), "%s to %s", from, to);
624 1.22 ad errno = sverrno;
625 1.22 ad error(buf);
626 1.22 ad }
627 1.22 ad }
628 1.22 ad
629 1.22 ad void
630 1.19 ad wr_error(const char *str)
631 1.11 fair {
632 1.19 ad char errbuf[BUFSIZ];
633 1.19 ad int sverrno;
634 1.19 ad
635 1.19 ad sverrno = errno;
636 1.11 fair
637 1.11 fair (void)snprintf(errbuf, sizeof(errbuf),
638 1.19 ad "attempt to write %s failed", str);
639 1.11 fair
640 1.11 fair errno = sverrno;
641 1.11 fair error(errbuf);
642 1.11 fair }
643 1.11 fair
644 1.11 fair void
645 1.19 ad error(const char *str)
646 1.1 cgd {
647 1.5 mycroft
648 1.19 ad warn("%s", str);
649 1.22 ad bailout();
650 1.1 cgd }
651 1.1 cgd
652 1.5 mycroft void
653 1.22 ad inconsistancy(void)
654 1.11 fair {
655 1.19 ad
656 1.22 ad warnx("text files and databases are inconsistent");
657 1.22 ad warnx("re-build the databases without -u");
658 1.22 ad bailout();
659 1.11 fair }
660 1.11 fair
661 1.11 fair void
662 1.22 ad bailout(void)
663 1.1 cgd {
664 1.19 ad
665 1.22 ad if ((clean & FILE_ORIG) != 0)
666 1.11 fair rm(oldpwdfile);
667 1.22 ad if ((clean & FILE_SECURE) != 0)
668 1.11 fair rm(pwd_Sdb_tmp);
669 1.22 ad if ((clean & FILE_INSECURE) != 0)
670 1.11 fair rm(pwd_db_tmp);
671 1.22 ad
672 1.22 ad exit(EXIT_FAILURE);
673 1.1 cgd }
674 1.1 cgd
675 1.36 jmmv /*
676 1.36 jmmv * Ensures that an existing database is up to date.
677 1.36 jmmv *
678 1.36 jmmv * Makes sure that the version number of an existing database matches the
679 1.36 jmmv * version number setversion() writes. If it does not, this function aborts
680 1.36 jmmv * execution because updating the database without fully regenerating it will
681 1.36 jmmv * leave it inconsistent.
682 1.36 jmmv */
683 1.35 christos void
684 1.36 jmmv checkversion(DB *dp)
685 1.35 christos {
686 1.35 christos DBT data, key;
687 1.36 jmmv int ret;
688 1.35 christos
689 1.35 christos key.data = __UNCONST("VERSION");
690 1.35 christos key.size = strlen((const char *)key.data) + 1;
691 1.35 christos
692 1.36 jmmv ret = (*dp->get)(dp, &key, &data, 0);
693 1.36 jmmv if (ret == -1) {
694 1.36 jmmv warnx("cannot get VERSION record from database");
695 1.36 jmmv bailout();
696 1.36 jmmv }
697 1.36 jmmv
698 1.36 jmmv if (ret == 1 || *(int *)data.data != getversion()) {
699 1.36 jmmv warnx("databases are laid out according to an old version");
700 1.36 jmmv warnx("re-build the databases without -u");
701 1.36 jmmv bailout();
702 1.36 jmmv }
703 1.36 jmmv }
704 1.36 jmmv
705 1.36 jmmv /*
706 1.36 jmmv * Returns the version number we write to and expect from databases.
707 1.36 jmmv */
708 1.36 jmmv uint32_t
709 1.36 jmmv getversion(void)
710 1.36 jmmv {
711 1.36 jmmv uint32_t version = sizeof(time_t) != sizeof(int32_t);
712 1.35 christos if (lorder != BYTE_ORDER)
713 1.35 christos version = SWAP(version);
714 1.36 jmmv return version;
715 1.36 jmmv }
716 1.36 jmmv
717 1.36 jmmv void
718 1.36 jmmv setversion(DB *dp)
719 1.36 jmmv {
720 1.36 jmmv DBT data, key;
721 1.36 jmmv uint32_t version = getversion();
722 1.36 jmmv
723 1.36 jmmv key.data = __UNCONST("VERSION");
724 1.36 jmmv key.size = strlen((const char *)key.data) + 1;
725 1.36 jmmv
726 1.35 christos data.data = &version;
727 1.35 christos data.size = sizeof(uint32_t);
728 1.35 christos
729 1.35 christos if ((*dp->put)(dp, &key, &data, R_NOOVERWRITE) == -1)
730 1.35 christos wr_error("setversion");
731 1.35 christos }
732 1.35 christos
733 1.19 ad /*
734 1.19 ad * Write entries to a database for a single user.
735 1.19 ad *
736 1.19 ad * The databases actually contain three copies of the original data. Each
737 1.19 ad * password file entry is converted into a rough approximation of a ``struct
738 1.19 ad * passwd'', with the strings placed inline. This object is then stored as
739 1.19 ad * the data for three separate keys. The first key * is the pw_name field
740 1.19 ad * prepended by the _PW_KEYBYNAME character. The second key is the pw_uid
741 1.19 ad * field prepended by the _PW_KEYBYUID character. The third key is the line
742 1.19 ad * number in the original file prepended by the _PW_KEYBYNUM character.
743 1.19 ad * (The special characters are prepended to ensure that the keys do not
744 1.19 ad * collide.)
745 1.19 ad */
746 1.19 ad #define COMPACT(e) for (t = e; (*p++ = *t++) != '\0';)
747 1.19 ad
748 1.19 ad void
749 1.22 ad putdbents(DB *dp, struct passwd *pw, const char *passwd, int flags,
750 1.22 ad const char *fn, int lineno, int dbflg, int uid_dbflg)
751 1.19 ad {
752 1.19 ad struct passwd pwd;
753 1.19 ad char buf[MAX(MAXPATHLEN, LINE_MAX * 2)], tbuf[1024], *p;
754 1.19 ad DBT data, key;
755 1.19 ad const char *t;
756 1.19 ad u_int32_t x;
757 1.19 ad int len;
758 1.19 ad
759 1.19 ad memcpy(&pwd, pw, sizeof(pwd));
760 1.19 ad data.data = (u_char *)buf;
761 1.19 ad key.data = (u_char *)tbuf;
762 1.19 ad
763 1.19 ad if (lorder != BYTE_ORDER) {
764 1.35 christos pwd.pw_uid = SWAP(pwd.pw_uid);
765 1.35 christos pwd.pw_gid = SWAP(pwd.pw_gid);
766 1.35 christos pwd.pw_change = SWAP(pwd.pw_change);
767 1.35 christos pwd.pw_expire = SWAP(pwd.pw_expire);
768 1.19 ad }
769 1.19 ad
770 1.19 ad /* Create insecure data. */
771 1.19 ad p = buf;
772 1.19 ad COMPACT(pwd.pw_name);
773 1.19 ad COMPACT(passwd);
774 1.19 ad memmove(p, &pwd.pw_uid, sizeof(pwd.pw_uid));
775 1.19 ad p += sizeof(pwd.pw_uid);
776 1.19 ad memmove(p, &pwd.pw_gid, sizeof(pwd.pw_gid));
777 1.19 ad p += sizeof(pwd.pw_gid);
778 1.19 ad memmove(p, &pwd.pw_change, sizeof(pwd.pw_change));
779 1.19 ad p += sizeof(pwd.pw_change);
780 1.19 ad COMPACT(pwd.pw_class);
781 1.19 ad COMPACT(pwd.pw_gecos);
782 1.19 ad COMPACT(pwd.pw_dir);
783 1.19 ad COMPACT(pwd.pw_shell);
784 1.19 ad memmove(p, &pwd.pw_expire, sizeof(pwd.pw_expire));
785 1.19 ad p += sizeof(pwd.pw_expire);
786 1.19 ad x = flags;
787 1.19 ad if (lorder != BYTE_ORDER)
788 1.35 christos x = SWAP(x);
789 1.19 ad memmove(p, &x, sizeof(x));
790 1.19 ad p += sizeof(flags);
791 1.19 ad data.size = p - buf;
792 1.19 ad
793 1.19 ad /* Store insecure by name. */
794 1.19 ad tbuf[0] = _PW_KEYBYNAME;
795 1.19 ad len = strlen(pwd.pw_name);
796 1.19 ad memmove(tbuf + 1, pwd.pw_name, len);
797 1.19 ad key.size = len + 1;
798 1.22 ad if ((*dp->put)(dp, &key, &data, dbflg) == -1)
799 1.19 ad wr_error(fn);
800 1.22 ad
801 1.19 ad /* Store insecure by number. */
802 1.19 ad tbuf[0] = _PW_KEYBYNUM;
803 1.19 ad x = lineno;
804 1.19 ad if (lorder != BYTE_ORDER)
805 1.35 christos x = SWAP(x);
806 1.19 ad memmove(tbuf + 1, &x, sizeof(x));
807 1.19 ad key.size = sizeof(x) + 1;
808 1.22 ad if ((*dp->put)(dp, &key, &data, dbflg) == -1)
809 1.19 ad wr_error(fn);
810 1.19 ad
811 1.19 ad /* Store insecure by uid. */
812 1.19 ad tbuf[0] = _PW_KEYBYUID;
813 1.19 ad memmove(tbuf + 1, &pwd.pw_uid, sizeof(pwd.pw_uid));
814 1.19 ad key.size = sizeof(pwd.pw_uid) + 1;
815 1.22 ad if ((*dp->put)(dp, &key, &data, uid_dbflg) == -1)
816 1.22 ad wr_error(fn);
817 1.22 ad }
818 1.22 ad
819 1.22 ad int
820 1.22 ad deldbent(DB *dp, const char *fn, int type, void *keyp)
821 1.22 ad {
822 1.22 ad char tbuf[1024];
823 1.22 ad DBT key;
824 1.22 ad u_int32_t x;
825 1.22 ad int len, rv;
826 1.22 ad
827 1.22 ad key.data = (u_char *)tbuf;
828 1.22 ad
829 1.22 ad switch (tbuf[0] = type) {
830 1.22 ad case _PW_KEYBYNAME:
831 1.22 ad len = strlen((char *)keyp);
832 1.22 ad memcpy(tbuf + 1, keyp, len);
833 1.22 ad key.size = len + 1;
834 1.22 ad break;
835 1.22 ad
836 1.22 ad case _PW_KEYBYNUM:
837 1.22 ad case _PW_KEYBYUID:
838 1.22 ad x = *(int *)keyp;
839 1.22 ad if (lorder != BYTE_ORDER)
840 1.35 christos x = SWAP(x);
841 1.22 ad memmove(tbuf + 1, &x, sizeof(x));
842 1.22 ad key.size = sizeof(x) + 1;
843 1.22 ad break;
844 1.22 ad }
845 1.22 ad
846 1.22 ad if ((rv = (*dp->del)(dp, &key, 0)) == -1)
847 1.19 ad wr_error(fn);
848 1.22 ad return (rv);
849 1.22 ad }
850 1.22 ad
851 1.22 ad int
852 1.22 ad getdbent(DB *dp, const char *fn, int type, void *keyp, struct passwd **tpwd)
853 1.22 ad {
854 1.22 ad static char buf[MAX(MAXPATHLEN, LINE_MAX * 2)];
855 1.22 ad static struct passwd pwd;
856 1.22 ad char tbuf[1024], *p;
857 1.22 ad DBT key, data;
858 1.22 ad u_int32_t x;
859 1.22 ad int len, rv;
860 1.22 ad
861 1.22 ad data.data = (u_char *)buf;
862 1.22 ad data.size = sizeof(buf);
863 1.22 ad key.data = (u_char *)tbuf;
864 1.22 ad
865 1.22 ad switch (tbuf[0] = type) {
866 1.22 ad case _PW_KEYBYNAME:
867 1.22 ad len = strlen((char *)keyp);
868 1.22 ad memcpy(tbuf + 1, keyp, len);
869 1.22 ad key.size = len + 1;
870 1.22 ad break;
871 1.22 ad
872 1.22 ad case _PW_KEYBYNUM:
873 1.22 ad case _PW_KEYBYUID:
874 1.22 ad x = *(int *)keyp;
875 1.22 ad if (lorder != BYTE_ORDER)
876 1.35 christos x = SWAP(x);
877 1.22 ad memmove(tbuf + 1, &x, sizeof(x));
878 1.22 ad key.size = sizeof(x) + 1;
879 1.22 ad break;
880 1.22 ad }
881 1.22 ad
882 1.22 ad if ((rv = (*dp->get)(dp, &key, &data, 0)) == 1)
883 1.22 ad return (rv);
884 1.22 ad if (rv == -1)
885 1.22 ad error(pwd_Sdb_tmp);
886 1.22 ad
887 1.22 ad p = (char *)data.data;
888 1.22 ad
889 1.22 ad pwd.pw_name = p;
890 1.22 ad while (*p++ != '\0')
891 1.22 ad ;
892 1.22 ad pwd.pw_passwd = p;
893 1.22 ad while (*p++ != '\0')
894 1.22 ad ;
895 1.22 ad
896 1.22 ad memcpy(&pwd.pw_uid, p, sizeof(pwd.pw_uid));
897 1.22 ad p += sizeof(pwd.pw_uid);
898 1.22 ad memcpy(&pwd.pw_gid, p, sizeof(pwd.pw_gid));
899 1.22 ad p += sizeof(pwd.pw_gid);
900 1.22 ad memcpy(&pwd.pw_change, p, sizeof(pwd.pw_change));
901 1.22 ad p += sizeof(pwd.pw_change);
902 1.22 ad
903 1.22 ad pwd.pw_class = p;
904 1.22 ad while (*p++ != '\0')
905 1.22 ad ;
906 1.22 ad pwd.pw_gecos = p;
907 1.22 ad while (*p++ != '\0')
908 1.22 ad ;
909 1.22 ad pwd.pw_dir = p;
910 1.22 ad while (*p++ != '\0')
911 1.22 ad ;
912 1.22 ad pwd.pw_shell = p;
913 1.22 ad while (*p++ != '\0')
914 1.22 ad ;
915 1.22 ad
916 1.22 ad memcpy(&pwd.pw_expire, p, sizeof(pwd.pw_expire));
917 1.22 ad p += sizeof(pwd.pw_expire);
918 1.22 ad
919 1.22 ad if (lorder != BYTE_ORDER) {
920 1.35 christos pwd.pw_uid = SWAP(pwd.pw_uid);
921 1.35 christos pwd.pw_gid = SWAP(pwd.pw_gid);
922 1.35 christos pwd.pw_change = SWAP(pwd.pw_change);
923 1.35 christos pwd.pw_expire = SWAP(pwd.pw_expire);
924 1.22 ad }
925 1.22 ad
926 1.22 ad *tpwd = &pwd;
927 1.22 ad return (0);
928 1.19 ad }
929 1.19 ad
930 1.19 ad void
931 1.19 ad putyptoken(DB *dp, const char *fn)
932 1.19 ad {
933 1.19 ad DBT data, key;
934 1.19 ad
935 1.19 ad key.data = (u_char *)__yp_token;
936 1.19 ad key.size = strlen(__yp_token);
937 1.19 ad data.data = (u_char *)NULL;
938 1.19 ad data.size = 0;
939 1.19 ad
940 1.22 ad if ((*dp->put)(dp, &key, &data, R_NOOVERWRITE) == -1)
941 1.19 ad wr_error(fn);
942 1.19 ad }
943 1.19 ad
944 1.5 mycroft void
945 1.19 ad usage(void)
946 1.1 cgd {
947 1.5 mycroft
948 1.22 ad (void)fprintf(stderr,
949 1.31 sketch "usage: pwd_mkdb [-BLps] [-c cachesize] [-d directory] [-u user] file\n");
950 1.19 ad exit(EXIT_FAILURE);
951 1.1 cgd }
952