pwd_mkdb.c revision 30260
139221Sgibbs/*-
265942Sgibbs * Copyright (c) 1991, 1993, 1994
365942Sgibbs *	The Regents of the University of California.  All rights reserved.
439221Sgibbs *
571717Sgibbs * Redistribution and use in source and binary forms, with or without
639221Sgibbs * modification, are permitted provided that the following conditions
739221Sgibbs * are met:
839221Sgibbs * 1. Redistributions of source code must retain the above copyright
939221Sgibbs *    notice, this list of conditions and the following disclaimer.
1039221Sgibbs * 2. Redistributions in binary form must reproduce the above copyright
1139221Sgibbs *    notice, this list of conditions and the following disclaimer in the
1239221Sgibbs *    documentation and/or other materials provided with the distribution.
1339221Sgibbs * 3. All advertising materials mentioning features or use of this software
1439221Sgibbs *    must display the following acknowledgement:
1539221Sgibbs *	This product includes software developed by the University of
1639221Sgibbs *	California, Berkeley and its contributors.
1739221Sgibbs * 4. Neither the name of the University nor the names of its contributors
1839221Sgibbs *    may be used to endorse or promote products derived from this software
1939221Sgibbs *    without specific prior written permission.
2039221Sgibbs *
2139221Sgibbs * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2239221Sgibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2339221Sgibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2439221Sgibbs * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2539221Sgibbs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2639221Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2739221Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2839221Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2965942Sgibbs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3065942Sgibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3150477Speter * SUCH DAMAGE.
3239221Sgibbs */
3339221Sgibbs
3465942Sgibbs#ifndef lint
3539221Sgibbsstatic const char copyright[] =
3655953Speter"@(#) Copyright (c) 1991, 1993, 1994\n\
3739221Sgibbs	The Regents of the University of California.  All rights reserved.\n";
3839221Sgibbs#endif /* not lint */
3945791Speter
4039221Sgibbs#ifndef lint
4165942Sgibbs#if 0
4265942Sgibbsstatic char sccsid[] = "@(#)pwd_mkdb.c	8.5 (Berkeley) 4/20/94";
4363457Sgibbs#endif
4465942Sgibbsstatic const char rcsid[] =
4565942Sgibbs	"$Id$";
4665942Sgibbs#endif /* not lint */
4765942Sgibbs
4865942Sgibbs#include <sys/param.h>
4965942Sgibbs#include <sys/stat.h>
5065942Sgibbs
5165942Sgibbs#include <db.h>
5239221Sgibbs#include <err.h>
5365942Sgibbs#include <errno.h>
5465942Sgibbs#include <fcntl.h>
5545791Speter#include <limits.h>
5665942Sgibbs#include <pwd.h>
5739221Sgibbs#include <signal.h>
5856823Speter#include <stdio.h>
5945791Speter#include <stdlib.h>
6065942Sgibbs#include <string.h>
6139221Sgibbs#include <unistd.h>
6271390Sgibbs
6365942Sgibbs#include "pw_scan.h"
6465942Sgibbs
6565942Sgibbs#define	INSECURE	1
6665942Sgibbs#define	SECURE		2
6765942Sgibbs#define	PERM_INSECURE	(S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
6865942Sgibbs#define	PERM_SECURE	(S_IRUSR|S_IWUSR)
6939221Sgibbs
7065942SgibbsHASHINFO openinfo = {
7165942Sgibbs	4096,		/* bsize */
7265942Sgibbs	32,		/* ffactor */
7365942Sgibbs	256,		/* nelem */
7465942Sgibbs	2048 * 1024,	/* cachesize */
7565942Sgibbs	NULL,		/* hash() */
7665942Sgibbs	0		/* lorder */
7765942Sgibbs};
7865942Sgibbs
7965942Sgibbsstatic enum state { FILE_INSECURE, FILE_SECURE, FILE_ORIG } clean;
8065942Sgibbsstatic struct passwd pwd;			/* password structure */
8165942Sgibbsstatic char *pname;				/* password file name */
8265942Sgibbsstatic char prefix[MAXPATHLEN];
8365942Sgibbs
8445791Speterstatic int Cflag;	/* flag for comments */
8545791Speterstatic char line[LINE_MAX];
8645791Speter
8745791Spetervoid	cleanup __P((void));
8845791Spetervoid	error __P((char *));
8945791Spetervoid	cp __P((char *, char *, mode_t mode));
9045791Spetervoid	mv __P((char *, char *));
9165942Sgibbsint	scan __P((FILE *, struct passwd *));
9245791Speterstatic void	usage __P((void));
9365942Sgibbs
9465942Sgibbsint
9565942Sgibbsmain(argc, argv)
9639221Sgibbs	int argc;
9745791Speter	char *argv[];
9865942Sgibbs{
9965942Sgibbs	DB *dp, *sdp, *pw_db;
10045791Speter	DBT data, sdata, key;
10165942Sgibbs	FILE *fp, *oldfp;
10265942Sgibbs	sigset_t set;
10339221Sgibbs	int ch, cnt, ypcnt, len, makeold, tfd, yp_enabled = 0;
10439221Sgibbs	char *p, *t;
10539221Sgibbs	char buf[MAX(MAXPATHLEN, LINE_MAX * 2)], tbuf[1024];
10645791Speter	char sbuf[MAX(MAXPATHLEN, LINE_MAX * 2)];
10739221Sgibbs	char buf2[MAXPATHLEN];
10865942Sgibbs	char sbuf2[MAXPATHLEN];
10965942Sgibbs	char *username;
11065942Sgibbs	u_int method, methoduid;
11165942Sgibbs	int cflag;
11239221Sgibbs
11365942Sgibbs	cflag = 0;
11465942Sgibbs	strcpy(prefix, _PATH_PWD);
11565942Sgibbs	makeold = 0;
11639221Sgibbs	username = NULL;
11765942Sgibbs	while ((ch = getopt(argc, argv, "cd:pu:v")) != -1)
11865942Sgibbs		switch(ch) {
11965942Sgibbs		case 'c':                       /* verify only */
12065942Sgibbs			cflag = 1;
12165942Sgibbs			break;
12265942Sgibbs		case 'd':
12365942Sgibbs			strncpy(prefix, optarg, sizeof prefix - 1);
12465942Sgibbs			break;
12565942Sgibbs		case 'p':			/* create V7 "file.orig" */
12671390Sgibbs			makeold = 1;
12765942Sgibbs			break;
12865942Sgibbs		case 'u':			/* only update this record */
12965942Sgibbs			username = optarg;
13071390Sgibbs			break;
13171390Sgibbs		case 'v':                       /* backward compatible */
13265942Sgibbs			break;
13365942Sgibbs		default:
13449860Sgibbs			usage();
13539221Sgibbs		}
13639221Sgibbs	argc -= optind;
13739221Sgibbs	argv += optind;
13839221Sgibbs
13965942Sgibbs	if (argc != 1 || (username && (*username == '+' || *username == '-')))
14039221Sgibbs		usage();
14165942Sgibbs
14265942Sgibbs	/*
14339221Sgibbs	 * This could be changed to allow the user to interrupt.
14439221Sgibbs	 * Probably not worth the effort.
14545967Sgibbs	 */
14645967Sgibbs	sigemptyset(&set);
14765942Sgibbs	sigaddset(&set, SIGTSTP);
14865942Sgibbs	sigaddset(&set, SIGHUP);
14939221Sgibbs	sigaddset(&set, SIGINT);
15065942Sgibbs	sigaddset(&set, SIGQUIT);
15165942Sgibbs	sigaddset(&set, SIGTERM);
15265942Sgibbs	(void)sigprocmask(SIG_BLOCK, &set, (sigset_t *)NULL);
15365942Sgibbs
15465942Sgibbs	/* We don't care what the user wants. */
15547274Sgibbs	(void)umask(0);
15647274Sgibbs
15739221Sgibbs	pname = *argv;
15865942Sgibbs	/* Open the original password file */
15939221Sgibbs	if (!(fp = fopen(pname, "r")))
16039221Sgibbs		error(pname);
16165942Sgibbs
16265942Sgibbs	/* check only if password database is valid */
16339221Sgibbs	if (cflag) {
16465942Sgibbs		for (cnt = 1; scan(fp, &pwd); ++cnt);
16565942Sgibbs		exit(0);
16639221Sgibbs	}
16771390Sgibbs
16865942Sgibbs	/* Open the temporary insecure password database. */
16965942Sgibbs	(void)snprintf(buf, sizeof(buf), "%s/%s.tmp", prefix, _MP_DB);
17065942Sgibbs	(void)snprintf(sbuf, sizeof(sbuf), "%s/%s.tmp", prefix, _SMP_DB);
17165942Sgibbs	if (username) {
17265942Sgibbs		(void)snprintf(buf2, sizeof(buf2), "%s/%s", prefix, _MP_DB);
17339221Sgibbs		(void)snprintf(sbuf2, sizeof(sbuf2), "%s/%s", prefix, _SMP_DB);
17465942Sgibbs
17565942Sgibbs		clean = FILE_INSECURE;
17665942Sgibbs		cp(buf2, buf, PERM_INSECURE);
17765942Sgibbs		dp = dbopen(buf,
17865942Sgibbs		    O_RDWR|O_EXCL, PERM_INSECURE, DB_HASH, &openinfo);
17965942Sgibbs		if (dp == NULL)
18065942Sgibbs			error(buf);
18139221Sgibbs
18265942Sgibbs		clean = FILE_SECURE;
18374094Sgibbs		cp(sbuf2, sbuf, PERM_SECURE);
18465942Sgibbs		sdp = dbopen(sbuf,
18565942Sgibbs		    O_RDWR|O_EXCL, PERM_SECURE, DB_HASH, &openinfo);
18639221Sgibbs		if (sdp == NULL)
18765942Sgibbs			error(sbuf);
18865942Sgibbs
18965942Sgibbs		/*
19065942Sgibbs		 * Do some trouble to check if we should store this users
19165942Sgibbs		 * uid. Don't use getpwnam/getpwuid as that interferes
19265942Sgibbs		 * with NIS.
19365942Sgibbs		 */
19465942Sgibbs		pw_db = dbopen(_PATH_MP_DB, O_RDONLY, 0, DB_HASH, NULL);
19539221Sgibbs		if (!pw_db)
19639221Sgibbs			error(_MP_DB);
19745791Speter		buf[0] = _PW_KEYBYNAME;
19845791Speter		len = strlen(username);
19945791Speter
20045791Speter		/* Only check that username fits in buffer */
20170204Sgibbs		memmove(buf + 1, username, MIN(len, sizeof(buf) - 1));
20245791Speter		key.data = (u_char *)buf;
20345791Speter		key.size = len + 1;
20445791Speter		if ((pw_db->get)(pw_db, &key, &data, 0) == 0) {
20545791Speter			p = (char *)data.data;
20645791Speter
20745791Speter			/* jump over pw_name and pw_passwd, to get to pw_uid */
20870204Sgibbs			while (*p++)
20945791Speter				;
21045791Speter			while (*p++)
21145791Speter				;
21245791Speter
21345791Speter			buf[0] = _PW_KEYBYUID;
214			memmove(buf + 1, p, sizeof(int));
215			key.data = (u_char *)buf;
216			key.size = sizeof(int) + 1;
217
218			if ((pw_db->get)(pw_db, &key, &data, 0) == 0) {
219				/* First field of data.data holds pw_pwname */
220				if (!strcmp(data.data, username))
221					methoduid = 0;
222				else
223					methoduid = R_NOOVERWRITE;
224			} else {
225				methoduid = R_NOOVERWRITE;
226			}
227		} else {
228			methoduid = R_NOOVERWRITE;
229		}
230		(void)(pw_db->close)(pw_db);
231		method = 0;
232	} else {
233		dp = dbopen(buf,
234		    O_RDWR|O_CREAT|O_EXCL, PERM_INSECURE, DB_HASH, &openinfo);
235		if (dp == NULL)
236			error(buf);
237		clean = FILE_INSECURE;
238
239		sdp = dbopen(sbuf,
240		    O_RDWR|O_CREAT|O_EXCL, PERM_SECURE, DB_HASH, &openinfo);
241		if (sdp == NULL)
242			error(sbuf);
243		clean = FILE_SECURE;
244
245		method = R_NOOVERWRITE;
246		methoduid = R_NOOVERWRITE;
247	}
248
249	/*
250	 * Open file for old password file.  Minor trickiness -- don't want to
251	 * chance the file already existing, since someone (stupidly) might
252	 * still be using this for permission checking.  So, open it first and
253	 * fdopen the resulting fd.  The resulting file should be readable by
254	 * everyone.
255	 */
256	if (makeold) {
257		(void)snprintf(buf, sizeof(buf), "%s.orig", pname);
258		if ((tfd = open(buf,
259		    O_WRONLY|O_CREAT|O_EXCL, PERM_INSECURE)) < 0)
260			error(buf);
261		if ((oldfp = fdopen(tfd, "w")) == NULL)
262			error(buf);
263		clean = FILE_ORIG;
264	}
265
266	/*
267	 * The databases actually contain three copies of the original data.
268	 * Each password file entry is converted into a rough approximation
269	 * of a ``struct passwd'', with the strings placed inline.  This
270	 * object is then stored as the data for three separate keys.  The
271	 * first key * is the pw_name field prepended by the _PW_KEYBYNAME
272	 * character.  The second key is the pw_uid field prepended by the
273	 * _PW_KEYBYUID character.  The third key is the line number in the
274	 * original file prepended by the _PW_KEYBYNUM character.  (The special
275	 * characters are prepended to ensure that the keys do not collide.)
276	 */
277	ypcnt = 1;
278	data.data = (u_char *)buf;
279	sdata.data = (u_char *)sbuf;
280	key.data = (u_char *)tbuf;
281	for (cnt = 1; scan(fp, &pwd); ++cnt) {
282		if (!Cflag &&
283		    (pwd.pw_name[0] == '+' || pwd.pw_name[0] == '-'))
284			yp_enabled = 1;
285#define	COMPACT(e)	t = e; while ((*p++ = *t++));
286		if (!Cflag &&
287		    (!username || (strcmp(username, pwd.pw_name) == 0))) {
288			/* Create insecure data. */
289			p = buf;
290			COMPACT(pwd.pw_name);
291			COMPACT("*");
292			memmove(p, &pwd.pw_uid, sizeof(int));
293			p += sizeof(int);
294			memmove(p, &pwd.pw_gid, sizeof(int));
295			p += sizeof(int);
296			memmove(p, &pwd.pw_change, sizeof(time_t));
297			p += sizeof(time_t);
298			COMPACT(pwd.pw_class);
299			COMPACT(pwd.pw_gecos);
300			COMPACT(pwd.pw_dir);
301			COMPACT(pwd.pw_shell);
302			memmove(p, &pwd.pw_expire, sizeof(time_t));
303			p += sizeof(time_t);
304			memmove(p, &pwd.pw_fields, sizeof pwd.pw_fields);
305			p += sizeof pwd.pw_fields;
306			data.size = p - buf;
307
308			/* Create secure data. */
309			p = sbuf;
310			COMPACT(pwd.pw_name);
311			COMPACT(pwd.pw_passwd);
312			memmove(p, &pwd.pw_uid, sizeof(int));
313			p += sizeof(int);
314			memmove(p, &pwd.pw_gid, sizeof(int));
315			p += sizeof(int);
316			memmove(p, &pwd.pw_change, sizeof(time_t));
317			p += sizeof(time_t);
318			COMPACT(pwd.pw_class);
319			COMPACT(pwd.pw_gecos);
320			COMPACT(pwd.pw_dir);
321			COMPACT(pwd.pw_shell);
322			memmove(p, &pwd.pw_expire, sizeof(time_t));
323			p += sizeof(time_t);
324			memmove(p, &pwd.pw_fields, sizeof pwd.pw_fields);
325			p += sizeof pwd.pw_fields;
326			sdata.size = p - sbuf;
327
328			/* Store insecure by name. */
329			tbuf[0] = _PW_KEYBYNAME;
330			len = strlen(pwd.pw_name);
331			memmove(tbuf + 1, pwd.pw_name, len);
332			key.size = len + 1;
333			if ((dp->put)(dp, &key, &data, method) == -1)
334				error("put");
335
336			/* Store insecure by number. */
337			tbuf[0] = _PW_KEYBYNUM;
338			memmove(tbuf + 1, &cnt, sizeof(cnt));
339			key.size = sizeof(cnt) + 1;
340			if ((dp->put)(dp, &key, &data, method) == -1)
341				error("put");
342
343			/* Store insecure by uid. */
344			tbuf[0] = _PW_KEYBYUID;
345			memmove(tbuf + 1, &pwd.pw_uid, sizeof(pwd.pw_uid));
346			key.size = sizeof(pwd.pw_uid) + 1;
347			if ((dp->put)(dp, &key, &data, methoduid) == -1)
348				error("put");
349
350			/* Store secure by name. */
351			tbuf[0] = _PW_KEYBYNAME;
352			len = strlen(pwd.pw_name);
353			memmove(tbuf + 1, pwd.pw_name, len);
354			key.size = len + 1;
355			if ((sdp->put)(sdp, &key, &sdata, method) == -1)
356				error("put");
357
358			/* Store secure by number. */
359			tbuf[0] = _PW_KEYBYNUM;
360			memmove(tbuf + 1, &cnt, sizeof(cnt));
361			key.size = sizeof(cnt) + 1;
362			if ((sdp->put)(sdp, &key, &sdata, method) == -1)
363				error("put");
364
365			/* Store secure by uid. */
366			tbuf[0] = _PW_KEYBYUID;
367			memmove(tbuf + 1, &pwd.pw_uid, sizeof(pwd.pw_uid));
368			key.size = sizeof(pwd.pw_uid) + 1;
369			if ((sdp->put)(sdp, &key, &sdata, methoduid) == -1)
370				error("put");
371
372			/* Store insecure and secure special plus and special minus */
373			if (pwd.pw_name[0] == '+' || pwd.pw_name[0] == '-') {
374				tbuf[0] = _PW_KEYYPBYNUM;
375				memmove(tbuf + 1, &ypcnt, sizeof(cnt));
376				ypcnt++;
377				key.size = sizeof(cnt) + 1;
378				if ((dp->put)(dp, &key, &data, method) == -1)
379					error("put");
380				if ((sdp->put)(sdp, &key, &sdata, method) == -1)
381					error("put");
382			}
383		}
384		/* Create original format password file entry */
385		if (Cflag && makeold)	/* copy comments */
386			(void)fprintf(oldfp, "%s\n", line);
387		else if (makeold) {
388			char uidstr[20];
389			char gidstr[20];
390
391			snprintf(uidstr, sizeof(uidstr), "%d", pwd.pw_uid);
392			snprintf(gidstr, sizeof(gidstr), "%d", pwd.pw_gid);
393
394			(void)fprintf(oldfp, "%s:*:%s:%s:%s:%s:%s\n",
395			    pwd.pw_name, pwd.pw_fields & _PWF_UID ? uidstr : "",
396			    pwd.pw_fields & _PWF_GID ? gidstr : "",
397			    pwd.pw_gecos, pwd.pw_dir, pwd.pw_shell);
398		}
399	}
400	/* If YP enabled, set flag. */
401	if (yp_enabled) {
402		buf[0] = yp_enabled + 2;
403		data.size = 1;
404		tbuf[0] = _PW_KEYYPENABLED;
405		key.size = 1;
406		if ((dp->put)(dp, &key, &data, method) == -1)
407			error("put");
408		if ((sdp->put)(sdp, &key, &data, method) == -1)
409			error("put");
410	}
411
412	if ((dp->close)(dp) == -1)
413		error("close");
414	if ((sdp->close)(sdp) == -1)
415		error("close");
416	if (makeold) {
417		(void)fflush(oldfp);
418		(void)fclose(oldfp);
419	}
420
421	/* Set master.passwd permissions, in case caller forgot. */
422	(void)fchmod(fileno(fp), S_IRUSR|S_IWUSR);
423	(void)fclose(fp);
424
425	/* Install as the real password files. */
426	(void)snprintf(buf, sizeof(buf), "%s/%s.tmp", prefix, _MP_DB);
427	(void)snprintf(buf2, sizeof(buf2), "%s/%s", prefix, _MP_DB);
428	mv(buf, buf2);
429	(void)snprintf(buf, sizeof(buf), "%s/%s.tmp", prefix, _SMP_DB);
430	(void)snprintf(buf2, sizeof(buf2), "%s/%s", prefix, _SMP_DB);
431	mv(buf, buf2);
432	if (makeold) {
433		(void)snprintf(buf2, sizeof(buf2), "%s/%s", prefix, _PASSWD);
434		(void)snprintf(buf, sizeof(buf), "%s.orig", pname);
435		mv(buf, buf2);
436	}
437	/*
438	 * Move the master password LAST -- chpass(1), passwd(1) and vipw(8)
439	 * all use flock(2) on it to block other incarnations of themselves.
440	 * The rename means that everything is unlocked, as the original file
441	 * can no longer be accessed.
442	 */
443	(void)snprintf(buf, sizeof(buf), "%s/%s", prefix, _MASTERPASSWD);
444	mv(pname, buf);
445	exit(0);
446}
447
448int
449scan(fp, pw)
450	FILE *fp;
451	struct passwd *pw;
452{
453	static int lcnt;
454	char *p;
455
456	if (!fgets(line, sizeof(line), fp))
457		return (0);
458	++lcnt;
459	/*
460	 * ``... if I swallow anything evil, put your fingers down my
461	 * throat...''
462	 *	-- The Who
463	 */
464	if (!(p = strchr(line, '\n'))) {
465		warnx("line too long");
466		goto fmt;
467
468	}
469	*p = '\0';
470
471#ifdef PASSWD_IGNORE_COMMENTS
472	/*
473	 * Ignore comments: ^[ \t]*#
474	 */
475	for (p = line; *p != '\0'; p++)
476		if (*p != ' ' && *p != '\t')
477			break;
478	if (*p == '#' || *p == '\0') {
479		Cflag = 1;
480		return(1);
481	} else
482		Cflag = 0;
483#endif
484
485	if (!pw_scan(line, pw)) {
486		warnx("at line #%d", lcnt);
487fmt:		errno = EFTYPE;	/* XXX */
488		error(pname);
489	}
490
491	return (1);
492}
493
494void
495cp(from, to, mode)
496	char *from, *to;
497	mode_t mode;
498{
499	static char buf[MAXBSIZE];
500	int from_fd, rcount, to_fd, wcount;
501
502	if ((from_fd = open(from, O_RDONLY, 0)) < 0)
503		error(from);
504	if ((to_fd = open(to, O_WRONLY|O_CREAT|O_EXCL, mode)) < 0)
505		error(to);
506	while ((rcount = read(from_fd, buf, MAXBSIZE)) > 0) {
507		wcount = write(to_fd, buf, rcount);
508		if (rcount != wcount || wcount == -1) {
509			int sverrno = errno;
510
511			(void)snprintf(buf, sizeof(buf), "%s to %s", from, to);
512			errno = sverrno;
513			error(buf);
514		}
515	}
516	if (rcount < 0) {
517		int sverrno = errno;
518
519		(void)snprintf(buf, sizeof(buf), "%s to %s", from, to);
520		errno = sverrno;
521		error(buf);
522	}
523}
524
525
526void
527mv(from, to)
528	char *from, *to;
529{
530	char buf[MAXPATHLEN];
531
532	if (rename(from, to)) {
533		int sverrno = errno;
534		(void)snprintf(buf, sizeof(buf), "%s to %s", from, to);
535		errno = sverrno;
536		error(buf);
537	}
538}
539
540void
541error(name)
542	char *name;
543{
544
545	warn("%s", name);
546	cleanup();
547	exit(1);
548}
549
550void
551cleanup()
552{
553	char buf[MAXPATHLEN];
554
555	switch(clean) {
556	case FILE_ORIG:
557		(void)snprintf(buf, sizeof(buf), "%s.orig", pname);
558		(void)unlink(buf);
559		/* FALLTHROUGH */
560	case FILE_SECURE:
561		(void)snprintf(buf, sizeof(buf), "%s/%s.tmp", prefix, _SMP_DB);
562		(void)unlink(buf);
563		/* FALLTHROUGH */
564	case FILE_INSECURE:
565		(void)snprintf(buf, sizeof(buf), "%s/%s.tmp", prefix, _MP_DB);
566		(void)unlink(buf);
567	}
568}
569
570static void
571usage()
572{
573
574	(void)fprintf(stderr,
575"usage: pwd_mkdb [-c] [-p] [-d <dest dir>] [-u <local username>] file\n");
576	exit(1);
577}
578