xref: /freebsd/contrib/sendmail/makemap/makemap.c (revision d39bd2c1388b520fcba9abed1932acacead60fba)
1c2aa98e2SPeter Wemm /*
22fb4f839SGregory Neil Shapiro  * Copyright (c) 1998-2002, 2004, 2008, 2020 Proofpoint, Inc. and its suppliers.
33299c2f1SGregory Neil Shapiro  *	All rights reserved.
4c2aa98e2SPeter Wemm  * Copyright (c) 1992 Eric P. Allman.  All rights reserved.
5c2aa98e2SPeter Wemm  * Copyright (c) 1992, 1993
6c2aa98e2SPeter Wemm  *	The Regents of the University of California.  All rights reserved.
7c2aa98e2SPeter Wemm  *
8c2aa98e2SPeter Wemm  * By using this file, you agree to the terms and conditions set
9c2aa98e2SPeter Wemm  * forth in the LICENSE file which can be found at the top level of
10c2aa98e2SPeter Wemm  * the sendmail distribution.
11c2aa98e2SPeter Wemm  *
12c2aa98e2SPeter Wemm  */
13c2aa98e2SPeter Wemm 
1412ed1c7cSGregory Neil Shapiro #include <sm/gen.h>
1512ed1c7cSGregory Neil Shapiro 
1612ed1c7cSGregory Neil Shapiro SM_IDSTR(copyright,
175dd76dd0SGregory Neil Shapiro "@(#) Copyright (c) 1998-2002, 2004 Proofpoint, Inc. and its suppliers.\n\
183299c2f1SGregory Neil Shapiro 	All rights reserved.\n\
193299c2f1SGregory Neil Shapiro      Copyright (c) 1992 Eric P. Allman.  All rights reserved.\n\
203299c2f1SGregory Neil Shapiro      Copyright (c) 1992, 1993\n\
2112ed1c7cSGregory Neil Shapiro 	The Regents of the University of California.  All rights reserved.\n")
223299c2f1SGregory Neil Shapiro 
234313cc83SGregory Neil Shapiro SM_IDSTR(id, "@(#)$Id: makemap.c,v 8.183 2013-11-22 20:51:52 ca Exp $")
243299c2f1SGregory Neil Shapiro 
25e0e1e2d0SGregory Neil Shapiro 
26c2aa98e2SPeter Wemm #include <sys/types.h>
27c2aa98e2SPeter Wemm #ifndef ISC_UNIX
28c2aa98e2SPeter Wemm # include <sys/file.h>
295b0945b5SGregory Neil Shapiro #endif
303299c2f1SGregory Neil Shapiro #include <ctype.h>
313299c2f1SGregory Neil Shapiro #include <stdlib.h>
323299c2f1SGregory Neil Shapiro #include <unistd.h>
333299c2f1SGregory Neil Shapiro #ifdef EX_OK
343299c2f1SGregory Neil Shapiro # undef EX_OK		/* unistd.h may have another use for this */
355b0945b5SGregory Neil Shapiro #endif
363299c2f1SGregory Neil Shapiro #include <sysexits.h>
373299c2f1SGregory Neil Shapiro #include <sendmail/sendmail.h>
385b0945b5SGregory Neil Shapiro #include <sm/path.h>
393299c2f1SGregory Neil Shapiro #include <sendmail/pathnames.h>
403299c2f1SGregory Neil Shapiro #include <libsmdb/smdb.h>
412fb4f839SGregory Neil Shapiro #if USE_EAI
422fb4f839SGregory Neil Shapiro # include <sm/ixlen.h>
432fb4f839SGregory Neil Shapiro #endif
44c2aa98e2SPeter Wemm 
45c2aa98e2SPeter Wemm uid_t	RealUid;
46c2aa98e2SPeter Wemm gid_t	RealGid;
47c2aa98e2SPeter Wemm char	*RealUserName;
48c2aa98e2SPeter Wemm uid_t	RunAsUid;
4941f3d2ceSGregory Neil Shapiro gid_t	RunAsGid;
50c2aa98e2SPeter Wemm char	*RunAsUserName;
51c2aa98e2SPeter Wemm int	Verbose = 2;
5212ed1c7cSGregory Neil Shapiro bool	DontInitGroups = false;
5376b7bf71SPeter Wemm uid_t	TrustedUid = 0;
543299c2f1SGregory Neil Shapiro BITMAP256 DontBlameSendmail;
55c2aa98e2SPeter Wemm 
56*d39bd2c1SGregory Neil Shapiro static bool verbose = false;
57*d39bd2c1SGregory Neil Shapiro static int exitstat;
58*d39bd2c1SGregory Neil Shapiro 
59c2aa98e2SPeter Wemm #define BUFSIZE		1024
605b0945b5SGregory Neil Shapiro #define ISASCII(c)	isascii((unsigned char)(c))
61*d39bd2c1SGregory Neil Shapiro #define ISSPACE(c)	(ISASCII(c) && isspace(c))
625b0945b5SGregory Neil Shapiro #define ISSEP(c) (sep == '\0' ? ISASCII(c) && isspace(c) : (c) == sep)
633299c2f1SGregory Neil Shapiro 
645b0945b5SGregory Neil Shapiro static void usage __P((const char *));
655b0945b5SGregory Neil Shapiro static char *readcf __P((const char *, char *, bool));
66*d39bd2c1SGregory Neil Shapiro static void db_put __P((SMDB_DATABASE *, SMDB_DBENT, SMDB_DBENT, int, const char *, int, const char *));
67684b2a5fSGregory Neil Shapiro 
683299c2f1SGregory Neil Shapiro static void
usage(progname)693299c2f1SGregory Neil Shapiro usage(progname)
705b0945b5SGregory Neil Shapiro 	const char *progname;
713299c2f1SGregory Neil Shapiro {
7212ed1c7cSGregory Neil Shapiro 	sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
73bfb62e91SGregory Neil Shapiro 		      "Usage: %s [-C cffile] [-N] [-c cachesize] [-D commentchar]\n",
7412ed1c7cSGregory Neil Shapiro 		      progname);
75bfb62e91SGregory Neil Shapiro 	sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
76*d39bd2c1SGregory Neil Shapiro 		      "       %*s [-d] [-e] [-f] [-i type] [-l] [-o] [-r] [-s] [-t delimiter]\n",
77bfb62e91SGregory Neil Shapiro 		      (int) strlen(progname), "");
782fb4f839SGregory Neil Shapiro #if _FFR_TESTS
792fb4f839SGregory Neil Shapiro 	sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
802fb4f839SGregory Neil Shapiro 		      "       %*s [-S n]\n",
812fb4f839SGregory Neil Shapiro 		      (int) strlen(progname), "");
822fb4f839SGregory Neil Shapiro #endif
83bfb62e91SGregory Neil Shapiro 	sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
84bfb62e91SGregory Neil Shapiro 		      "       %*s [-u] [-v] type mapname\n",
85bfb62e91SGregory Neil Shapiro 		      (int) strlen(progname), "");
863299c2f1SGregory Neil Shapiro 	exit(EX_USAGE);
873299c2f1SGregory Neil Shapiro }
88c2aa98e2SPeter Wemm 
895b0945b5SGregory Neil Shapiro /*
90*d39bd2c1SGregory Neil Shapiro **  DB_PUT -- do the DB insert
91*d39bd2c1SGregory Neil Shapiro **
92*d39bd2c1SGregory Neil Shapiro **	Parameters:
93*d39bd2c1SGregory Neil Shapiro **		database -- DB to use
94*d39bd2c1SGregory Neil Shapiro **		db_key -- key
95*d39bd2c1SGregory Neil Shapiro **		db_val -- value
96*d39bd2c1SGregory Neil Shapiro **		putflags -- flags for smdb_put()
97*d39bd2c1SGregory Neil Shapiro **		mapname -- name of map (for error reporting)
98*d39bd2c1SGregory Neil Shapiro **		lineno -- line number (for error reporting)
99*d39bd2c1SGregory Neil Shapiro **		progname -- name of program (for error reporting)
100*d39bd2c1SGregory Neil Shapiro **
101*d39bd2c1SGregory Neil Shapiro **	Returns:
102*d39bd2c1SGregory Neil Shapiro **		none.
103*d39bd2c1SGregory Neil Shapiro **
104*d39bd2c1SGregory Neil Shapiro **	Side effects:
105*d39bd2c1SGregory Neil Shapiro **		Sets exitstat so makemap exits with error if put fails
106*d39bd2c1SGregory Neil Shapiro */
107*d39bd2c1SGregory Neil Shapiro 
108*d39bd2c1SGregory Neil Shapiro static void
db_put(database,db_key,db_val,putflags,mapname,lineno,progname)109*d39bd2c1SGregory Neil Shapiro db_put(database, db_key, db_val, putflags, mapname, lineno, progname)
110*d39bd2c1SGregory Neil Shapiro 	SMDB_DATABASE *database;
111*d39bd2c1SGregory Neil Shapiro 	SMDB_DBENT db_key, db_val;
112*d39bd2c1SGregory Neil Shapiro 	int putflags;
113*d39bd2c1SGregory Neil Shapiro 	const char *mapname;
114*d39bd2c1SGregory Neil Shapiro 	int lineno;
115*d39bd2c1SGregory Neil Shapiro 	const char *progname;
116*d39bd2c1SGregory Neil Shapiro {
117*d39bd2c1SGregory Neil Shapiro 	int errcode;
118*d39bd2c1SGregory Neil Shapiro 
119*d39bd2c1SGregory Neil Shapiro 	if (verbose)
120*d39bd2c1SGregory Neil Shapiro 	{
121*d39bd2c1SGregory Neil Shapiro 		(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
122*d39bd2c1SGregory Neil Shapiro 				     "key=`%s', val=`%s'\n",
123*d39bd2c1SGregory Neil Shapiro 				     (char *) db_key.data,
124*d39bd2c1SGregory Neil Shapiro 				     (char *) db_val.data);
125*d39bd2c1SGregory Neil Shapiro 	}
126*d39bd2c1SGregory Neil Shapiro 
127*d39bd2c1SGregory Neil Shapiro 	errcode = database->smdb_put(database, &db_key, &db_val, putflags);
128*d39bd2c1SGregory Neil Shapiro 	if (0 == errcode)
129*d39bd2c1SGregory Neil Shapiro 		return;
130*d39bd2c1SGregory Neil Shapiro 
131*d39bd2c1SGregory Neil Shapiro 	(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "%s: %s: ",
132*d39bd2c1SGregory Neil Shapiro 			     progname, mapname);
133*d39bd2c1SGregory Neil Shapiro 	if (lineno >= 0)
134*d39bd2c1SGregory Neil Shapiro 		(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "line %u: ",
135*d39bd2c1SGregory Neil Shapiro 				     lineno);
136*d39bd2c1SGregory Neil Shapiro 	(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "key %s: ",
137*d39bd2c1SGregory Neil Shapiro 			     (char *) db_key.data);
138*d39bd2c1SGregory Neil Shapiro 	if (SMDBE_KEY_EXIST == errcode)
139*d39bd2c1SGregory Neil Shapiro 	{
140*d39bd2c1SGregory Neil Shapiro 		(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
141*d39bd2c1SGregory Neil Shapiro 				     "duplicate key\n");
142*d39bd2c1SGregory Neil Shapiro 		exitstat = EX_DATAERR;
143*d39bd2c1SGregory Neil Shapiro 	}
144*d39bd2c1SGregory Neil Shapiro 	else
145*d39bd2c1SGregory Neil Shapiro 	{
146*d39bd2c1SGregory Neil Shapiro 		(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
147*d39bd2c1SGregory Neil Shapiro 				     "put error: %s\n", sm_errstring(errcode));
148*d39bd2c1SGregory Neil Shapiro 		exitstat = EX_IOERR;
149*d39bd2c1SGregory Neil Shapiro 	}
150*d39bd2c1SGregory Neil Shapiro }
151*d39bd2c1SGregory Neil Shapiro 
152*d39bd2c1SGregory Neil Shapiro /*
1535b0945b5SGregory Neil Shapiro **  READCF -- read some settings from configuration file.
1545b0945b5SGregory Neil Shapiro **
1555b0945b5SGregory Neil Shapiro **	Parameters:
1565b0945b5SGregory Neil Shapiro **		cfile -- configuration file name.
1575b0945b5SGregory Neil Shapiro **		mapfile -- file name of map to look up (if not NULL/empty)
1585b0945b5SGregory Neil Shapiro **			Note: this finds the first match, so in case someone
1595b0945b5SGregory Neil Shapiro **			uses the same map file for different maps, they are
1605b0945b5SGregory Neil Shapiro **			hopefully using the same map type.
1615b0945b5SGregory Neil Shapiro **		fullpath -- compare the full paths or just the "basename"s?
1625b0945b5SGregory Neil Shapiro **			(even excluding any .ext !)
1635b0945b5SGregory Neil Shapiro **
1645b0945b5SGregory Neil Shapiro **	Returns:
1655b0945b5SGregory Neil Shapiro **		pointer to map class name (static!)
1665b0945b5SGregory Neil Shapiro */
1675b0945b5SGregory Neil Shapiro 
1685b0945b5SGregory Neil Shapiro static char *
readcf(cfile,mapfile,fullpath)1695b0945b5SGregory Neil Shapiro readcf(cfile, mapfile, fullpath)
1705b0945b5SGregory Neil Shapiro 	const char *cfile;
1715b0945b5SGregory Neil Shapiro 	char *mapfile;
1725b0945b5SGregory Neil Shapiro 	bool fullpath;
1735b0945b5SGregory Neil Shapiro {
1745b0945b5SGregory Neil Shapiro 	SM_FILE_T *cfp;
1755b0945b5SGregory Neil Shapiro 	char buf[MAXLINE];
1765b0945b5SGregory Neil Shapiro 	static char classbuf[MAXLINE];
177*d39bd2c1SGregory Neil Shapiro 	char *classname, *mapname;
1785b0945b5SGregory Neil Shapiro 	char *p;
1795b0945b5SGregory Neil Shapiro 
1805b0945b5SGregory Neil Shapiro 	if ((cfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, cfile,
1815b0945b5SGregory Neil Shapiro 			      SM_IO_RDONLY, NULL)) == NULL)
1825b0945b5SGregory Neil Shapiro 	{
1835b0945b5SGregory Neil Shapiro 		sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
1845b0945b5SGregory Neil Shapiro 			      "makemap: %s: %s\n",
1855b0945b5SGregory Neil Shapiro 			      cfile, sm_errstring(errno));
1865b0945b5SGregory Neil Shapiro 		exit(EX_NOINPUT);
1875b0945b5SGregory Neil Shapiro 	}
1885b0945b5SGregory Neil Shapiro 	classname = NULL;
1895b0945b5SGregory Neil Shapiro 	classbuf[0] = '\0';
1905b0945b5SGregory Neil Shapiro 
191*d39bd2c1SGregory Neil Shapiro 	mapname = mapfile;
1925b0945b5SGregory Neil Shapiro 	if (!fullpath && mapfile != NULL)
1935b0945b5SGregory Neil Shapiro 	{
1945b0945b5SGregory Neil Shapiro 		p = strrchr(mapfile, '/');
1955b0945b5SGregory Neil Shapiro 		if (p != NULL)
1965b0945b5SGregory Neil Shapiro 			mapfile = ++p;
197*d39bd2c1SGregory Neil Shapiro 		mapname = strdup(mapfile);
198*d39bd2c1SGregory Neil Shapiro 		if (NULL == mapname)
199*d39bd2c1SGregory Neil Shapiro 		{
200*d39bd2c1SGregory Neil Shapiro 			sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
201*d39bd2c1SGregory Neil Shapiro 			      "makemap: strdup(%s) failed: %s\n",
202*d39bd2c1SGregory Neil Shapiro 			      mapfile, sm_errstring(errno));
203*d39bd2c1SGregory Neil Shapiro 			exit(EX_OSERR);
204*d39bd2c1SGregory Neil Shapiro 		}
205*d39bd2c1SGregory Neil Shapiro 		if ((p = strchr(mapname, '.')) != NULL)
2065b0945b5SGregory Neil Shapiro 			*p = '\0';
2075b0945b5SGregory Neil Shapiro 	}
2085b0945b5SGregory Neil Shapiro 
2095b0945b5SGregory Neil Shapiro 	while (sm_io_fgets(cfp, SM_TIME_DEFAULT, buf, sizeof(buf)) >= 0)
2105b0945b5SGregory Neil Shapiro 	{
2115b0945b5SGregory Neil Shapiro 		char *b;
2125b0945b5SGregory Neil Shapiro 
2135b0945b5SGregory Neil Shapiro 		if ((b = strchr(buf, '\n')) != NULL)
2145b0945b5SGregory Neil Shapiro 			*b = '\0';
2155b0945b5SGregory Neil Shapiro 
2165b0945b5SGregory Neil Shapiro 		b = buf;
2175b0945b5SGregory Neil Shapiro 		switch (*b++)
2185b0945b5SGregory Neil Shapiro 		{
2195b0945b5SGregory Neil Shapiro 		  case 'O':		/* option */
2205b0945b5SGregory Neil Shapiro #if HASFCHOWN
2215b0945b5SGregory Neil Shapiro 			if (strncasecmp(b, " TrustedUser", 12) == 0 &&
2225b0945b5SGregory Neil Shapiro 			    !(ISASCII(b[12]) && isalnum(b[12])))
2235b0945b5SGregory Neil Shapiro 			{
2245b0945b5SGregory Neil Shapiro 				b = strchr(b, '=');
2255b0945b5SGregory Neil Shapiro 				if (b == NULL)
2265b0945b5SGregory Neil Shapiro 					continue;
2275b0945b5SGregory Neil Shapiro 				while (ISASCII(*++b) && isspace(*b))
2285b0945b5SGregory Neil Shapiro 					continue;
2295b0945b5SGregory Neil Shapiro 				if (ISASCII(*b) && isdigit(*b))
2305b0945b5SGregory Neil Shapiro 					TrustedUid = atoi(b);
2315b0945b5SGregory Neil Shapiro 				else
2325b0945b5SGregory Neil Shapiro 				{
2335b0945b5SGregory Neil Shapiro 					struct passwd *pw;
2345b0945b5SGregory Neil Shapiro 
2355b0945b5SGregory Neil Shapiro 					TrustedUid = 0;
2365b0945b5SGregory Neil Shapiro 					pw = getpwnam(b);
2375b0945b5SGregory Neil Shapiro 					if (pw == NULL)
2385b0945b5SGregory Neil Shapiro 						(void) sm_io_fprintf(smioerr,
2395b0945b5SGregory Neil Shapiro 								     SM_TIME_DEFAULT,
2405b0945b5SGregory Neil Shapiro 								     "TrustedUser: unknown user %s\n", b);
2415b0945b5SGregory Neil Shapiro 					else
2425b0945b5SGregory Neil Shapiro 						TrustedUid = pw->pw_uid;
2435b0945b5SGregory Neil Shapiro 				}
2445b0945b5SGregory Neil Shapiro 
2455b0945b5SGregory Neil Shapiro # ifdef UID_MAX
2465b0945b5SGregory Neil Shapiro 				if (TrustedUid > UID_MAX)
2475b0945b5SGregory Neil Shapiro 				{
2485b0945b5SGregory Neil Shapiro 					(void) sm_io_fprintf(smioerr,
2495b0945b5SGregory Neil Shapiro 							     SM_TIME_DEFAULT,
2505b0945b5SGregory Neil Shapiro 							     "TrustedUser: uid value (%ld) > UID_MAX (%ld)",
2515b0945b5SGregory Neil Shapiro 						(long) TrustedUid,
2525b0945b5SGregory Neil Shapiro 						(long) UID_MAX);
2535b0945b5SGregory Neil Shapiro 					TrustedUid = 0;
2545b0945b5SGregory Neil Shapiro 				}
2555b0945b5SGregory Neil Shapiro # endif /* UID_MAX */
2565b0945b5SGregory Neil Shapiro 			}
2575b0945b5SGregory Neil Shapiro #endif /* HASFCHOWN */
2585b0945b5SGregory Neil Shapiro 			break;
2595b0945b5SGregory Neil Shapiro 
2605b0945b5SGregory Neil Shapiro 		  case 'K':		/* Keyfile (map) */
2615b0945b5SGregory Neil Shapiro 			if (classname != NULL)	/* found it already */
2625b0945b5SGregory Neil Shapiro 				continue;
263*d39bd2c1SGregory Neil Shapiro 			if (mapname == NULL || *mapname == '\0')
2645b0945b5SGregory Neil Shapiro 				continue;
2655b0945b5SGregory Neil Shapiro 
2665b0945b5SGregory Neil Shapiro 			/* cut off trailing spaces */
267*d39bd2c1SGregory Neil Shapiro 			for (p = buf + strlen(buf) - 1;
268*d39bd2c1SGregory Neil Shapiro 			     ISASCII(*p) && isspace(*p) && p > buf; p--)
2695b0945b5SGregory Neil Shapiro 				*p = '\0';
2705b0945b5SGregory Neil Shapiro 
2715b0945b5SGregory Neil Shapiro 			/* find the last argument */
2725b0945b5SGregory Neil Shapiro 			p = strrchr(buf, ' ');
2735b0945b5SGregory Neil Shapiro 			if (p == NULL)
2745b0945b5SGregory Neil Shapiro 				continue;
275*d39bd2c1SGregory Neil Shapiro 			b = strstr(p, mapname);
2765b0945b5SGregory Neil Shapiro 			if (b == NULL)
2775b0945b5SGregory Neil Shapiro 				continue;
2785b0945b5SGregory Neil Shapiro 			if (b <= buf)
2795b0945b5SGregory Neil Shapiro 				continue;
2805b0945b5SGregory Neil Shapiro 			if (!fullpath)
2815b0945b5SGregory Neil Shapiro 			{
2825b0945b5SGregory Neil Shapiro 				p = strrchr(b, '.');
2835b0945b5SGregory Neil Shapiro 				if (p != NULL)
2845b0945b5SGregory Neil Shapiro 					*p = '\0';
2855b0945b5SGregory Neil Shapiro 			}
2865b0945b5SGregory Neil Shapiro 
2875b0945b5SGregory Neil Shapiro 			/* allow trailing white space? */
288*d39bd2c1SGregory Neil Shapiro 			if (strcmp(mapname, b) != 0)
2895b0945b5SGregory Neil Shapiro 				continue;
2905b0945b5SGregory Neil Shapiro 			/* SM_ASSERT(b > buf); */
2915b0945b5SGregory Neil Shapiro 			--b;
2925b0945b5SGregory Neil Shapiro 			if (!ISASCII(*b))
2935b0945b5SGregory Neil Shapiro 				continue;
2945b0945b5SGregory Neil Shapiro 			if (!isspace(*b) && fullpath)
2955b0945b5SGregory Neil Shapiro 				continue;
2965b0945b5SGregory Neil Shapiro 			if (!fullpath && !(SM_IS_DIR_DELIM(*b) || isspace(*b)))
2975b0945b5SGregory Neil Shapiro 				continue;
2985b0945b5SGregory Neil Shapiro 
2995b0945b5SGregory Neil Shapiro 			/* basically from readcf.c */
3005b0945b5SGregory Neil Shapiro 			for (b = buf + 1; ISASCII(*b) && isspace(*b); b++)
3015b0945b5SGregory Neil Shapiro 				;
3025b0945b5SGregory Neil Shapiro 			if (!(ISASCII(*b) && isalnum(*b)))
3035b0945b5SGregory Neil Shapiro 			{
3045b0945b5SGregory Neil Shapiro 				/* syserr("readcf: config K line: no map name"); */
3055b0945b5SGregory Neil Shapiro 				return NULL;
3065b0945b5SGregory Neil Shapiro 			}
3075b0945b5SGregory Neil Shapiro 
3085b0945b5SGregory Neil Shapiro 			while ((ISASCII(*++b) && isalnum(*b)) || *b == '_' || *b == '.')
3095b0945b5SGregory Neil Shapiro 				;
3105b0945b5SGregory Neil Shapiro 			if (*b != '\0')
3115b0945b5SGregory Neil Shapiro 				*b++ = '\0';
3125b0945b5SGregory Neil Shapiro 			while (ISASCII(*b) && isspace(*b))
3135b0945b5SGregory Neil Shapiro 				b++;
3145b0945b5SGregory Neil Shapiro 			if (!(ISASCII(*b) && isalnum(*b)))
3155b0945b5SGregory Neil Shapiro 			{
3165b0945b5SGregory Neil Shapiro 				/* syserr("readcf: config K line, map %s: no map class", b); */
3175b0945b5SGregory Neil Shapiro 				return NULL;
3185b0945b5SGregory Neil Shapiro 			}
3195b0945b5SGregory Neil Shapiro 			classname = b;
3205b0945b5SGregory Neil Shapiro 			while (ISASCII(*++b) && isalnum(*b))
3215b0945b5SGregory Neil Shapiro 				;
3225b0945b5SGregory Neil Shapiro 			if (*b != '\0')
3235b0945b5SGregory Neil Shapiro 				*b++ = '\0';
3245b0945b5SGregory Neil Shapiro 			(void) sm_strlcpy(classbuf, classname, sizeof classbuf);
3255b0945b5SGregory Neil Shapiro 			break;
3265b0945b5SGregory Neil Shapiro 
3275b0945b5SGregory Neil Shapiro 		  default:
3285b0945b5SGregory Neil Shapiro 			continue;
3295b0945b5SGregory Neil Shapiro 		}
3305b0945b5SGregory Neil Shapiro 	}
3315b0945b5SGregory Neil Shapiro 	(void) sm_io_close(cfp, SM_TIME_DEFAULT);
3325b0945b5SGregory Neil Shapiro 
333*d39bd2c1SGregory Neil Shapiro 	/* not really needed because it is just a "one time leak" */
334*d39bd2c1SGregory Neil Shapiro 	if (mapname != mapfile && mapname != NULL)
335*d39bd2c1SGregory Neil Shapiro 	{
336*d39bd2c1SGregory Neil Shapiro 		free(mapname);
337*d39bd2c1SGregory Neil Shapiro 		mapname = NULL;
338*d39bd2c1SGregory Neil Shapiro 	}
3395b0945b5SGregory Neil Shapiro 	return classbuf;
3405b0945b5SGregory Neil Shapiro }
3415b0945b5SGregory Neil Shapiro 
342c2aa98e2SPeter Wemm int
main(argc,argv)343c2aa98e2SPeter Wemm main(argc, argv)
344c2aa98e2SPeter Wemm 	int argc;
345c2aa98e2SPeter Wemm 	char **argv;
346c2aa98e2SPeter Wemm {
347c2aa98e2SPeter Wemm 	char *progname;
348c2aa98e2SPeter Wemm 	char *cfile;
34912ed1c7cSGregory Neil Shapiro 	bool inclnull = false;
35012ed1c7cSGregory Neil Shapiro 	bool notrunc = false;
35112ed1c7cSGregory Neil Shapiro 	bool allowreplace = false;
35212ed1c7cSGregory Neil Shapiro 	bool allowempty = false;
35312ed1c7cSGregory Neil Shapiro 	bool foldcase = true;
35412ed1c7cSGregory Neil Shapiro 	bool unmake = false;
355*d39bd2c1SGregory Neil Shapiro #if _FFR_MM_ALIASES
356*d39bd2c1SGregory Neil Shapiro 	/*
357*d39bd2c1SGregory Neil Shapiro 	**  NOTE: this does not work properly:
358*d39bd2c1SGregory Neil Shapiro 	**  sendmail does address rewriting which is not done here.
359*d39bd2c1SGregory Neil Shapiro 	*/
360*d39bd2c1SGregory Neil Shapiro 
361*d39bd2c1SGregory Neil Shapiro 	bool aliases = false;
362*d39bd2c1SGregory Neil Shapiro #endif
3635b0945b5SGregory Neil Shapiro 	bool didreadcf = false;
3643299c2f1SGregory Neil Shapiro 	char sep = '\0';
36512ed1c7cSGregory Neil Shapiro 	char comment = '#';
366c2aa98e2SPeter Wemm 	int opt;
36776b7bf71SPeter Wemm 	char *typename = NULL;
3685b0945b5SGregory Neil Shapiro 	char *fallback = NULL;
36976b7bf71SPeter Wemm 	char *mapname = NULL;
37012ed1c7cSGregory Neil Shapiro 	unsigned int lineno;
371c2aa98e2SPeter Wemm 	int mode;
3723299c2f1SGregory Neil Shapiro 	int smode;
37376b7bf71SPeter Wemm 	int putflags = 0;
3743299c2f1SGregory Neil Shapiro 	long sff = SFF_ROOTOK|SFF_REGONLY;
375c2aa98e2SPeter Wemm 	struct passwd *pw;
3763299c2f1SGregory Neil Shapiro 	SMDB_DATABASE *database;
3773299c2f1SGregory Neil Shapiro 	SMDB_CURSOR *cursor;
3783299c2f1SGregory Neil Shapiro 	SMDB_DBENT db_key, db_val;
3793299c2f1SGregory Neil Shapiro 	SMDB_DBPARAMS params;
3803299c2f1SGregory Neil Shapiro 	SMDB_USER_INFO user_info;
381c2aa98e2SPeter Wemm 	char ibuf[BUFSIZE];
382c2aa98e2SPeter Wemm 	static char rnamebuf[MAXNAME];	/* holds RealUserName */
383c2aa98e2SPeter Wemm 	extern char *optarg;
384c2aa98e2SPeter Wemm 	extern int optind;
3852fb4f839SGregory Neil Shapiro #if USE_EAI
3862fb4f839SGregory Neil Shapiro 	bool ascii = true;
3872fb4f839SGregory Neil Shapiro #endif
3882fb4f839SGregory Neil Shapiro #if _FFR_TESTS
3892fb4f839SGregory Neil Shapiro 	int slp = 0;
3902fb4f839SGregory Neil Shapiro #endif
391c2aa98e2SPeter Wemm 
3923299c2f1SGregory Neil Shapiro 	memset(&params, '\0', sizeof params);
3933299c2f1SGregory Neil Shapiro 	params.smdbp_cache_size = 1024 * 1024;
3943299c2f1SGregory Neil Shapiro 
3953299c2f1SGregory Neil Shapiro 	progname = strrchr(argv[0], '/');
3963299c2f1SGregory Neil Shapiro 	if (progname != NULL)
3973299c2f1SGregory Neil Shapiro 		progname++;
3983299c2f1SGregory Neil Shapiro 	else
399c2aa98e2SPeter Wemm 		progname = argv[0];
40012ed1c7cSGregory Neil Shapiro 	cfile = getcfname(0, 0, SM_GET_SENDMAIL_CF, NULL);
401c2aa98e2SPeter Wemm 
4023299c2f1SGregory Neil Shapiro 	clrbitmap(DontBlameSendmail);
403c2aa98e2SPeter Wemm 	RunAsUid = RealUid = getuid();
404c2aa98e2SPeter Wemm 	RunAsGid = RealGid = getgid();
405c2aa98e2SPeter Wemm 	pw = getpwuid(RealUid);
406c2aa98e2SPeter Wemm 	if (pw != NULL)
40712ed1c7cSGregory Neil Shapiro 		(void) sm_strlcpy(rnamebuf, pw->pw_name, sizeof rnamebuf);
408c2aa98e2SPeter Wemm 	else
40912ed1c7cSGregory Neil Shapiro 		(void) sm_snprintf(rnamebuf, sizeof rnamebuf,
41012ed1c7cSGregory Neil Shapiro 		    "Unknown UID %d", (int) RealUid);
411c2aa98e2SPeter Wemm 	RunAsUserName = RealUserName = rnamebuf;
4123299c2f1SGregory Neil Shapiro 	user_info.smdbu_id = RunAsUid;
4133299c2f1SGregory Neil Shapiro 	user_info.smdbu_group_id = RunAsGid;
41412ed1c7cSGregory Neil Shapiro 	(void) sm_strlcpy(user_info.smdbu_name, RunAsUserName,
4153299c2f1SGregory Neil Shapiro 		       SMDB_MAX_USER_NAME_LEN);
416c2aa98e2SPeter Wemm 
4175b0945b5SGregory Neil Shapiro #define OPTIONS		"C:D:Nc:defi:Llorst:uvx"
418*d39bd2c1SGregory Neil Shapiro #if _FFR_MM_ALIASES
419*d39bd2c1SGregory Neil Shapiro # define A_OPTIONS		"a"
420*d39bd2c1SGregory Neil Shapiro #else
421*d39bd2c1SGregory Neil Shapiro # define A_OPTIONS
422*d39bd2c1SGregory Neil Shapiro #endif
4232fb4f839SGregory Neil Shapiro #if _FFR_TESTS
4242fb4f839SGregory Neil Shapiro # define X_OPTIONS		"S:"
4252fb4f839SGregory Neil Shapiro #else
4262fb4f839SGregory Neil Shapiro # define X_OPTIONS
4272fb4f839SGregory Neil Shapiro #endif
428*d39bd2c1SGregory Neil Shapiro 	while ((opt = getopt(argc, argv, A_OPTIONS OPTIONS X_OPTIONS)) != -1)
429c2aa98e2SPeter Wemm 	{
430c2aa98e2SPeter Wemm 		switch (opt)
431c2aa98e2SPeter Wemm 		{
432c2aa98e2SPeter Wemm 		  case 'C':
433c2aa98e2SPeter Wemm 			cfile = optarg;
434c2aa98e2SPeter Wemm 			break;
435c2aa98e2SPeter Wemm 
436c2aa98e2SPeter Wemm 		  case 'N':
43712ed1c7cSGregory Neil Shapiro 			inclnull = true;
438c2aa98e2SPeter Wemm 			break;
439c2aa98e2SPeter Wemm 
440*d39bd2c1SGregory Neil Shapiro #if _FFR_MM_ALIASES
441*d39bd2c1SGregory Neil Shapiro 		  case 'a':
442*d39bd2c1SGregory Neil Shapiro 			/* Note: this doesn't verify e-mail addresses */
443*d39bd2c1SGregory Neil Shapiro 			sep = ':';
444*d39bd2c1SGregory Neil Shapiro 			aliases = true;
445*d39bd2c1SGregory Neil Shapiro 			break;
446*d39bd2c1SGregory Neil Shapiro #endif
447*d39bd2c1SGregory Neil Shapiro 
448c2aa98e2SPeter Wemm 		  case 'c':
4493299c2f1SGregory Neil Shapiro 			params.smdbp_cache_size = atol(optarg);
450c2aa98e2SPeter Wemm 			break;
451c2aa98e2SPeter Wemm 
452c2aa98e2SPeter Wemm 		  case 'd':
45312ed1c7cSGregory Neil Shapiro 			params.smdbp_allow_dup = true;
4543299c2f1SGregory Neil Shapiro 			break;
4553299c2f1SGregory Neil Shapiro 
4563299c2f1SGregory Neil Shapiro 		  case 'e':
45712ed1c7cSGregory Neil Shapiro 			allowempty = true;
458c2aa98e2SPeter Wemm 			break;
459c2aa98e2SPeter Wemm 
460c2aa98e2SPeter Wemm 		  case 'f':
46112ed1c7cSGregory Neil Shapiro 			foldcase = false;
462c2aa98e2SPeter Wemm 			break;
463c2aa98e2SPeter Wemm 
4645b0945b5SGregory Neil Shapiro 		  case 'i':
4655b0945b5SGregory Neil Shapiro 			fallback =optarg;
4665b0945b5SGregory Neil Shapiro 			break;
4675b0945b5SGregory Neil Shapiro 
46812ed1c7cSGregory Neil Shapiro 		  case 'D':
46912ed1c7cSGregory Neil Shapiro 			comment = *optarg;
47012ed1c7cSGregory Neil Shapiro 			break;
47112ed1c7cSGregory Neil Shapiro 
4725b0945b5SGregory Neil Shapiro 		  case 'L':
4735b0945b5SGregory Neil Shapiro 			smdb_print_available_types(false);
4745b0945b5SGregory Neil Shapiro 			sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4755b0945b5SGregory Neil Shapiro 				      "cf\nCF\n");
4765b0945b5SGregory Neil Shapiro 			exit(EX_OK);
4775b0945b5SGregory Neil Shapiro 			break;
4785b0945b5SGregory Neil Shapiro 
47976b7bf71SPeter Wemm 		  case 'l':
4805b0945b5SGregory Neil Shapiro 			smdb_print_available_types(false);
48176b7bf71SPeter Wemm 			exit(EX_OK);
48276b7bf71SPeter Wemm 			break;
48376b7bf71SPeter Wemm 
484c2aa98e2SPeter Wemm 		  case 'o':
48512ed1c7cSGregory Neil Shapiro 			notrunc = true;
486c2aa98e2SPeter Wemm 			break;
487c2aa98e2SPeter Wemm 
488c2aa98e2SPeter Wemm 		  case 'r':
48912ed1c7cSGregory Neil Shapiro 			allowreplace = true;
490c2aa98e2SPeter Wemm 			break;
491c2aa98e2SPeter Wemm 
4922fb4f839SGregory Neil Shapiro #if _FFR_TESTS
4932fb4f839SGregory Neil Shapiro 		  case 'S':
4942fb4f839SGregory Neil Shapiro 			slp = atoi(optarg);
4952fb4f839SGregory Neil Shapiro 			break;
4962fb4f839SGregory Neil Shapiro #endif
4972fb4f839SGregory Neil Shapiro 
498c2aa98e2SPeter Wemm 		  case 's':
4993299c2f1SGregory Neil Shapiro 			setbitn(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail);
5003299c2f1SGregory Neil Shapiro 			setbitn(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail);
5013299c2f1SGregory Neil Shapiro 			setbitn(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail);
5023299c2f1SGregory Neil Shapiro 			setbitn(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail);
5033299c2f1SGregory Neil Shapiro 			break;
5043299c2f1SGregory Neil Shapiro 
5053299c2f1SGregory Neil Shapiro 		  case 't':
5063299c2f1SGregory Neil Shapiro 			if (optarg == NULL || *optarg == '\0')
5073299c2f1SGregory Neil Shapiro 			{
50812ed1c7cSGregory Neil Shapiro 				sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
50912ed1c7cSGregory Neil Shapiro 					      "Invalid separator\n");
5103299c2f1SGregory Neil Shapiro 				break;
5113299c2f1SGregory Neil Shapiro 			}
5123299c2f1SGregory Neil Shapiro 			sep = *optarg;
5133299c2f1SGregory Neil Shapiro 			break;
5143299c2f1SGregory Neil Shapiro 
5153299c2f1SGregory Neil Shapiro 		  case 'u':
51612ed1c7cSGregory Neil Shapiro 			unmake = true;
517c2aa98e2SPeter Wemm 			break;
518c2aa98e2SPeter Wemm 
519c2aa98e2SPeter Wemm 		  case 'v':
52012ed1c7cSGregory Neil Shapiro 			verbose = true;
521c2aa98e2SPeter Wemm 			break;
522c2aa98e2SPeter Wemm 
5235b0945b5SGregory Neil Shapiro 		  case 'x':
5245b0945b5SGregory Neil Shapiro 			smdb_print_available_types(true);
5255b0945b5SGregory Neil Shapiro 			exit(EX_OK);
5265b0945b5SGregory Neil Shapiro 			break;
5275b0945b5SGregory Neil Shapiro 
528c2aa98e2SPeter Wemm 		  default:
5293299c2f1SGregory Neil Shapiro 			usage(progname);
5303299c2f1SGregory Neil Shapiro 			/* NOTREACHED */
531c2aa98e2SPeter Wemm 		}
532c2aa98e2SPeter Wemm 	}
533c2aa98e2SPeter Wemm 
5343299c2f1SGregory Neil Shapiro 	if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail))
535c2aa98e2SPeter Wemm 		sff |= SFF_NOSLINK;
5363299c2f1SGregory Neil Shapiro 	if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail))
537c2aa98e2SPeter Wemm 		sff |= SFF_NOHLINK;
5383299c2f1SGregory Neil Shapiro 	if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail))
539c2aa98e2SPeter Wemm 		sff |= SFF_NOWLINK;
540c2aa98e2SPeter Wemm 
541c2aa98e2SPeter Wemm 	argc -= optind;
542c2aa98e2SPeter Wemm 	argv += optind;
543c2aa98e2SPeter Wemm 	if (argc != 2)
5443299c2f1SGregory Neil Shapiro 	{
5453299c2f1SGregory Neil Shapiro 		usage(progname);
5463299c2f1SGregory Neil Shapiro 		/* NOTREACHED */
5473299c2f1SGregory Neil Shapiro 	}
548c2aa98e2SPeter Wemm 	else
549c2aa98e2SPeter Wemm 	{
550c2aa98e2SPeter Wemm 		typename = argv[0];
551c2aa98e2SPeter Wemm 		mapname = argv[1];
552c2aa98e2SPeter Wemm 	}
553c2aa98e2SPeter Wemm 
5545b0945b5SGregory Neil Shapiro #define TYPEFROMCF	(strcasecmp(typename, "cf") == 0)
5555b0945b5SGregory Neil Shapiro #define FULLPATHFROMCF	(strcmp(typename, "cf") == 0)
5565b0945b5SGregory Neil Shapiro 
5573299c2f1SGregory Neil Shapiro #if HASFCHOWN
5585b0945b5SGregory Neil Shapiro 	if (geteuid() == 0)
5595dd76dd0SGregory Neil Shapiro 	{
5605b0945b5SGregory Neil Shapiro 		if (TYPEFROMCF)
5615b0945b5SGregory Neil Shapiro 			typename = readcf(cfile, mapname, FULLPATHFROMCF);
562c2aa98e2SPeter Wemm 		else
5635b0945b5SGregory Neil Shapiro 			(void) readcf(cfile, NULL, false);
5645b0945b5SGregory Neil Shapiro 		didreadcf = true;
565c2aa98e2SPeter Wemm 	}
5663299c2f1SGregory Neil Shapiro #endif /* HASFCHOWN */
5673299c2f1SGregory Neil Shapiro 
5683299c2f1SGregory Neil Shapiro 	if (!params.smdbp_allow_dup && !allowreplace)
5693299c2f1SGregory Neil Shapiro 		putflags = SMDBF_NO_OVERWRITE;
5703299c2f1SGregory Neil Shapiro 
5713299c2f1SGregory Neil Shapiro 	if (unmake)
572c2aa98e2SPeter Wemm 	{
5733299c2f1SGregory Neil Shapiro 		mode = O_RDONLY;
5743299c2f1SGregory Neil Shapiro 		smode = S_IRUSR;
575c2aa98e2SPeter Wemm 	}
576c2aa98e2SPeter Wemm 	else
577c2aa98e2SPeter Wemm 	{
578c2aa98e2SPeter Wemm 		mode = O_RDWR;
579c2aa98e2SPeter Wemm 		if (!notrunc)
5803299c2f1SGregory Neil Shapiro 		{
581c2aa98e2SPeter Wemm 			mode |= O_CREAT|O_TRUNC;
5823299c2f1SGregory Neil Shapiro 			sff |= SFF_CREAT;
583c2aa98e2SPeter Wemm 		}
5843299c2f1SGregory Neil Shapiro 		smode = S_IWUSR;
585c2aa98e2SPeter Wemm 	}
5863299c2f1SGregory Neil Shapiro 
5873299c2f1SGregory Neil Shapiro 	params.smdbp_num_elements = 4096;
5883299c2f1SGregory Neil Shapiro 
5895b0945b5SGregory Neil Shapiro 	if (!didreadcf && TYPEFROMCF)
5905b0945b5SGregory Neil Shapiro 	{
5915b0945b5SGregory Neil Shapiro 		typename = readcf(cfile, mapname, FULLPATHFROMCF);
5925b0945b5SGregory Neil Shapiro 		didreadcf = true;
5935b0945b5SGregory Neil Shapiro 	}
5945b0945b5SGregory Neil Shapiro 	if (didreadcf && (typename == NULL || *typename == '\0'))
5955b0945b5SGregory Neil Shapiro 	{
5965b0945b5SGregory Neil Shapiro 		if (fallback != NULL && *fallback != '\0')
5975b0945b5SGregory Neil Shapiro 		{
5985b0945b5SGregory Neil Shapiro 			typename = fallback;
5995b0945b5SGregory Neil Shapiro 			if (verbose)
6005b0945b5SGregory Neil Shapiro 				(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
6015b0945b5SGregory Neil Shapiro 				     "%s: mapfile %s: not found in %s, using fallback %s\n",
6025b0945b5SGregory Neil Shapiro 				     progname, mapname, cfile, fallback);
6035b0945b5SGregory Neil Shapiro 		}
6045b0945b5SGregory Neil Shapiro 		else
6055b0945b5SGregory Neil Shapiro 		{
6065b0945b5SGregory Neil Shapiro 			(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
6075b0945b5SGregory Neil Shapiro 				     "%s: mapfile %s: not found in %s\n",
6085b0945b5SGregory Neil Shapiro 				     progname, mapname, cfile);
6095b0945b5SGregory Neil Shapiro 			exit(EX_DATAERR);
6105b0945b5SGregory Neil Shapiro 		}
6115b0945b5SGregory Neil Shapiro 	}
6125b0945b5SGregory Neil Shapiro 
6135b0945b5SGregory Neil Shapiro 	/*
6145b0945b5SGregory Neil Shapiro 	**  Note: if "implicit" is selected it does not work like
6155b0945b5SGregory Neil Shapiro 	**  sendmail: it will just use the first available DB type,
6165b0945b5SGregory Neil Shapiro 	**  it won't try several (for -u) to find one that "works".
6175b0945b5SGregory Neil Shapiro 	*/
6185b0945b5SGregory Neil Shapiro 
6193299c2f1SGregory Neil Shapiro 	errno = smdb_open_database(&database, mapname, mode, smode, sff,
6203299c2f1SGregory Neil Shapiro 				   typename, &user_info, &params);
6213299c2f1SGregory Neil Shapiro 	if (errno != SMDBE_OK)
622c2aa98e2SPeter Wemm 	{
6233299c2f1SGregory Neil Shapiro 		char *hint;
6243299c2f1SGregory Neil Shapiro 
6253299c2f1SGregory Neil Shapiro 		if (errno == SMDBE_UNSUPPORTED_DB_TYPE &&
6263299c2f1SGregory Neil Shapiro 		    (hint = smdb_db_definition(typename)) != NULL)
62712ed1c7cSGregory Neil Shapiro 			(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
6283299c2f1SGregory Neil Shapiro 					     "%s: Need to recompile with -D%s for %s support\n",
6293299c2f1SGregory Neil Shapiro 					     progname, hint, typename);
6303299c2f1SGregory Neil Shapiro 		else
63112ed1c7cSGregory Neil Shapiro 			(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
6323299c2f1SGregory Neil Shapiro 					     "%s: error opening type %s map %s: %s\n",
63312ed1c7cSGregory Neil Shapiro 					     progname, typename, mapname,
63412ed1c7cSGregory Neil Shapiro 					     sm_errstring(errno));
635c2aa98e2SPeter Wemm 		exit(EX_CANTCREAT);
636c2aa98e2SPeter Wemm 	}
6373299c2f1SGregory Neil Shapiro 
6383299c2f1SGregory Neil Shapiro 	(void) database->smdb_sync(database, 0);
6393299c2f1SGregory Neil Shapiro 
640d995d2baSGregory Neil Shapiro 	if (!unmake && geteuid() == 0 && TrustedUid != 0)
641c2aa98e2SPeter Wemm 	{
6423299c2f1SGregory Neil Shapiro 		errno = database->smdb_set_owner(database, TrustedUid, -1);
6433299c2f1SGregory Neil Shapiro 		if (errno != SMDBE_OK)
644c2aa98e2SPeter Wemm 		{
64512ed1c7cSGregory Neil Shapiro 			(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
6463299c2f1SGregory Neil Shapiro 					     "WARNING: ownership change on %s failed %s",
64712ed1c7cSGregory Neil Shapiro 					     mapname, sm_errstring(errno));
648c2aa98e2SPeter Wemm 		}
649c2aa98e2SPeter Wemm 	}
650c2aa98e2SPeter Wemm 
651c2aa98e2SPeter Wemm 	/*
652c2aa98e2SPeter Wemm 	**  Copy the data
653c2aa98e2SPeter Wemm 	*/
654c2aa98e2SPeter Wemm 
655c2aa98e2SPeter Wemm 	exitstat = EX_OK;
6563299c2f1SGregory Neil Shapiro 	if (unmake)
6573299c2f1SGregory Neil Shapiro 	{
6583299c2f1SGregory Neil Shapiro 		errno = database->smdb_cursor(database, &cursor, 0);
6593299c2f1SGregory Neil Shapiro 		if (errno != SMDBE_OK)
6603299c2f1SGregory Neil Shapiro 		{
6613299c2f1SGregory Neil Shapiro 
66212ed1c7cSGregory Neil Shapiro 			(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
6633299c2f1SGregory Neil Shapiro 					     "%s: cannot make cursor for type %s map %s\n",
6643299c2f1SGregory Neil Shapiro 					     progname, typename, mapname);
6653299c2f1SGregory Neil Shapiro 			exit(EX_SOFTWARE);
6663299c2f1SGregory Neil Shapiro 		}
6673299c2f1SGregory Neil Shapiro 
6683299c2f1SGregory Neil Shapiro 		memset(&db_key, '\0', sizeof db_key);
6693299c2f1SGregory Neil Shapiro 		memset(&db_val, '\0', sizeof db_val);
6703299c2f1SGregory Neil Shapiro 
671c46d91b7SGregory Neil Shapiro 		for (lineno = 0; ; lineno++)
6723299c2f1SGregory Neil Shapiro 		{
6733299c2f1SGregory Neil Shapiro 			errno = cursor->smdbc_get(cursor, &db_key, &db_val,
6743299c2f1SGregory Neil Shapiro 						  SMDB_CURSOR_GET_NEXT);
6753299c2f1SGregory Neil Shapiro 			if (errno != SMDBE_OK)
676c46d91b7SGregory Neil Shapiro 				break;
677c46d91b7SGregory Neil Shapiro 
67812ed1c7cSGregory Neil Shapiro 			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
679e3793f76SGregory Neil Shapiro 					     "%.*s%c%.*s\n",
680c46d91b7SGregory Neil Shapiro 					     (int) db_key.size,
681c46d91b7SGregory Neil Shapiro 					     (char *) db_key.data,
682e3793f76SGregory Neil Shapiro 					     (sep != '\0') ? sep : '\t',
683c46d91b7SGregory Neil Shapiro 					     (int) db_val.size,
684c46d91b7SGregory Neil Shapiro 					     (char *)db_val.data);
6853299c2f1SGregory Neil Shapiro 
6863299c2f1SGregory Neil Shapiro 		}
6873299c2f1SGregory Neil Shapiro 		(void) cursor->smdbc_close(cursor);
6883299c2f1SGregory Neil Shapiro 	}
6893299c2f1SGregory Neil Shapiro 	else
6903299c2f1SGregory Neil Shapiro 	{
6913299c2f1SGregory Neil Shapiro 		lineno = 0;
69212ed1c7cSGregory Neil Shapiro 		while (sm_io_fgets(smioin, SM_TIME_DEFAULT, ibuf, sizeof ibuf)
693552d4955SGregory Neil Shapiro 		       >= 0)
694c2aa98e2SPeter Wemm 		{
695c2aa98e2SPeter Wemm 			register char *p;
696c2aa98e2SPeter Wemm 
697c2aa98e2SPeter Wemm 			lineno++;
698c2aa98e2SPeter Wemm 
699c2aa98e2SPeter Wemm 			/*
700c2aa98e2SPeter Wemm 			**  Parse the line.
701c2aa98e2SPeter Wemm 			*/
702c2aa98e2SPeter Wemm 
703c2aa98e2SPeter Wemm 			p = strchr(ibuf, '\n');
704c2aa98e2SPeter Wemm 			if (p != NULL)
705c2aa98e2SPeter Wemm 				*p = '\0';
70612ed1c7cSGregory Neil Shapiro 			else if (!sm_io_eof(smioin))
707c2aa98e2SPeter Wemm 			{
70812ed1c7cSGregory Neil Shapiro 				(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
70912ed1c7cSGregory Neil Shapiro 						     "%s: %s: line %u: line too long (%ld bytes max)\n",
71012ed1c7cSGregory Neil Shapiro 						     progname, mapname, lineno,
71112ed1c7cSGregory Neil Shapiro 						     (long) sizeof ibuf);
7123299c2f1SGregory Neil Shapiro 				exitstat = EX_DATAERR;
713c2aa98e2SPeter Wemm 				continue;
714c2aa98e2SPeter Wemm 			}
715c2aa98e2SPeter Wemm 
71612ed1c7cSGregory Neil Shapiro 			if (ibuf[0] == '\0' || ibuf[0] == comment)
717c2aa98e2SPeter Wemm 				continue;
7185b0945b5SGregory Neil Shapiro 			if (sep == '\0' && ISASCII(ibuf[0]) && isspace(ibuf[0]))
719c2aa98e2SPeter Wemm 			{
72012ed1c7cSGregory Neil Shapiro 				(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
72112ed1c7cSGregory Neil Shapiro 						     "%s: %s: line %u: syntax error (leading space)\n",
722c2aa98e2SPeter Wemm 						     progname, mapname, lineno);
7233299c2f1SGregory Neil Shapiro 				exitstat = EX_DATAERR;
724c2aa98e2SPeter Wemm 				continue;
725c2aa98e2SPeter Wemm 			}
726c2aa98e2SPeter Wemm 
7273299c2f1SGregory Neil Shapiro 			memset(&db_key, '\0', sizeof db_key);
7283299c2f1SGregory Neil Shapiro 			memset(&db_val, '\0', sizeof db_val);
729c46d91b7SGregory Neil Shapiro 			db_key.data = ibuf;
7303299c2f1SGregory Neil Shapiro 
7312fb4f839SGregory Neil Shapiro #if USE_EAI
7322fb4f839SGregory Neil Shapiro 			db_key.size = 0;
7332fb4f839SGregory Neil Shapiro 			if (foldcase)
7342fb4f839SGregory Neil Shapiro 			{
7352fb4f839SGregory Neil Shapiro 				for (p = ibuf; *p != '\0' && !ISSEP(*p); p++)
7362fb4f839SGregory Neil Shapiro 				{
7372fb4f839SGregory Neil Shapiro 					if (!ISASCII(*p))
7382fb4f839SGregory Neil Shapiro 						ascii = false;
7392fb4f839SGregory Neil Shapiro 				}
7402fb4f839SGregory Neil Shapiro 				if (!ascii)
7412fb4f839SGregory Neil Shapiro 				{
7422fb4f839SGregory Neil Shapiro 					char sep;
7432fb4f839SGregory Neil Shapiro 					char *lkey;
7442fb4f839SGregory Neil Shapiro 
7452fb4f839SGregory Neil Shapiro 					sep = *p;
7462fb4f839SGregory Neil Shapiro 					*p = '\0';
7472fb4f839SGregory Neil Shapiro 
7482fb4f839SGregory Neil Shapiro 					lkey = sm_lowercase(ibuf);
7492fb4f839SGregory Neil Shapiro 					db_key.data = lkey;
7502fb4f839SGregory Neil Shapiro 					db_key.size = strlen(lkey);
7512fb4f839SGregory Neil Shapiro 					*p = sep;
7522fb4f839SGregory Neil Shapiro 				}
7532fb4f839SGregory Neil Shapiro 			}
7542fb4f839SGregory Neil Shapiro 			if (ascii)
7552fb4f839SGregory Neil Shapiro #endif /* USE_EAI */
7562fb4f839SGregory Neil Shapiro 			/* NOTE: see if () above! */
7572fb4f839SGregory Neil Shapiro 			for (p = ibuf; *p != '\0' && !ISSEP(*p); p++)
758c2aa98e2SPeter Wemm 			{
7595b0945b5SGregory Neil Shapiro 				if (foldcase && ISASCII(*p) && isupper(*p))
760c2aa98e2SPeter Wemm 					*p = tolower(*p);
761c2aa98e2SPeter Wemm 			}
7622fb4f839SGregory Neil Shapiro #if USE_EAI
7632fb4f839SGregory Neil Shapiro 			if (0 == db_key.size)
7642fb4f839SGregory Neil Shapiro #endif
765c46d91b7SGregory Neil Shapiro 				db_key.size = p - ibuf;
766c2aa98e2SPeter Wemm 			if (inclnull)
767c46d91b7SGregory Neil Shapiro 				db_key.size++;
7683299c2f1SGregory Neil Shapiro 
769c2aa98e2SPeter Wemm 			if (*p != '\0')
770c2aa98e2SPeter Wemm 				*p++ = '\0';
77112ed1c7cSGregory Neil Shapiro 			while (*p != '\0' && ISSEP(*p))
772c2aa98e2SPeter Wemm 				p++;
773*d39bd2c1SGregory Neil Shapiro #if _FFR_MM_ALIASES
774*d39bd2c1SGregory Neil Shapiro 			while (aliases && *p != '\0' && ISSPACE(*p))
775*d39bd2c1SGregory Neil Shapiro 				p++;
776*d39bd2c1SGregory Neil Shapiro #endif
7773299c2f1SGregory Neil Shapiro 			if (!allowempty && *p == '\0')
778c2aa98e2SPeter Wemm 			{
77912ed1c7cSGregory Neil Shapiro 				(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
78012ed1c7cSGregory Neil Shapiro 						     "%s: %s: line %u: no RHS for LHS %s\n",
7813299c2f1SGregory Neil Shapiro 						     progname, mapname, lineno,
782c46d91b7SGregory Neil Shapiro 						     (char *) db_key.data);
7833299c2f1SGregory Neil Shapiro 				exitstat = EX_DATAERR;
784c2aa98e2SPeter Wemm 				continue;
785c2aa98e2SPeter Wemm 			}
7863299c2f1SGregory Neil Shapiro 
787c46d91b7SGregory Neil Shapiro 			db_val.data = p;
788c46d91b7SGregory Neil Shapiro 			db_val.size = strlen(p);
789c2aa98e2SPeter Wemm 			if (inclnull)
790c46d91b7SGregory Neil Shapiro 				db_val.size++;
791c2aa98e2SPeter Wemm 
792c2aa98e2SPeter Wemm 			/*
793c2aa98e2SPeter Wemm 			**  Do the database insert.
794c2aa98e2SPeter Wemm 			*/
795c2aa98e2SPeter Wemm 
796*d39bd2c1SGregory Neil Shapiro 			db_put(database, db_key, db_val, putflags, mapname,
797*d39bd2c1SGregory Neil Shapiro 				lineno, progname);
798*d39bd2c1SGregory Neil Shapiro 		}
799*d39bd2c1SGregory Neil Shapiro #if _FFR_MM_ALIASES
800*d39bd2c1SGregory Neil Shapiro 		if (aliases)
801c2aa98e2SPeter Wemm 		{
802*d39bd2c1SGregory Neil Shapiro 			char magic[2] = "@";
803c2aa98e2SPeter Wemm 
804*d39bd2c1SGregory Neil Shapiro 			db_key.data = magic;
805*d39bd2c1SGregory Neil Shapiro 			db_val.data = magic;
806*d39bd2c1SGregory Neil Shapiro 			db_key.size = 1;
807*d39bd2c1SGregory Neil Shapiro 			db_val.size = 1;
808*d39bd2c1SGregory Neil Shapiro 			db_put(database, db_key, db_val, putflags, mapname, -1,
809*d39bd2c1SGregory Neil Shapiro 				progname);
810c2aa98e2SPeter Wemm 		}
811*d39bd2c1SGregory Neil Shapiro #endif /* _FFR_MM_ALIASES */
812c2aa98e2SPeter Wemm 	}
813c2aa98e2SPeter Wemm 
8142fb4f839SGregory Neil Shapiro #if _FFR_TESTS
8152fb4f839SGregory Neil Shapiro 	if (slp > 0)
8162fb4f839SGregory Neil Shapiro 		sleep(slp);
8172fb4f839SGregory Neil Shapiro #endif
8182fb4f839SGregory Neil Shapiro 
819c2aa98e2SPeter Wemm 	/*
820c2aa98e2SPeter Wemm 	**  Now close the database.
821c2aa98e2SPeter Wemm 	*/
822c2aa98e2SPeter Wemm 
8233299c2f1SGregory Neil Shapiro 	errno = database->smdb_close(database);
8243299c2f1SGregory Neil Shapiro 	if (errno != SMDBE_OK)
825c2aa98e2SPeter Wemm 	{
82612ed1c7cSGregory Neil Shapiro 		(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
82712ed1c7cSGregory Neil Shapiro 				     "%s: close(%s): %s\n",
82812ed1c7cSGregory Neil Shapiro 				     progname, mapname, sm_errstring(errno));
829c2aa98e2SPeter Wemm 		exitstat = EX_IOERR;
830c2aa98e2SPeter Wemm 	}
8313299c2f1SGregory Neil Shapiro 	smdb_free_database(database);
832c2aa98e2SPeter Wemm 
833c2aa98e2SPeter Wemm 	exit(exitstat);
83412ed1c7cSGregory Neil Shapiro 
8353299c2f1SGregory Neil Shapiro 	/* NOTREACHED */
8363299c2f1SGregory Neil Shapiro 	return exitstat;
837c2aa98e2SPeter Wemm }
838