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