xref: /src/contrib/sendmail/makemap/makemap.c (revision d39bd2c1388b520fcba9abed1932acacead60fba)
158162a73SPeter Wemm /*
228fbd282SGregory Neil Shapiro  * Copyright (c) 1998-2002, 2004, 2008, 2020 Proofpoint, Inc. and its suppliers.
306f25ae9SGregory Neil Shapiro  *	All rights reserved.
4c2aa98e2SPeter Wemm  * Copyright (c) 1992 Eric P. Allman.  All rights reserved.
558162a73SPeter Wemm  * Copyright (c) 1992, 1993
658162a73SPeter Wemm  *	The Regents of the University of California.  All rights reserved.
758162a73SPeter 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.
1158162a73SPeter Wemm  *
1258162a73SPeter Wemm  */
1358162a73SPeter Wemm 
1440266059SGregory Neil Shapiro #include <sm/gen.h>
1540266059SGregory Neil Shapiro 
1640266059SGregory Neil Shapiro SM_IDSTR(copyright,
17c1bfccf7SGregory Neil Shapiro "@(#) Copyright (c) 1998-2002, 2004 Proofpoint, Inc. and its suppliers.\n\
1806f25ae9SGregory Neil Shapiro 	All rights reserved.\n\
1906f25ae9SGregory Neil Shapiro      Copyright (c) 1992 Eric P. Allman.  All rights reserved.\n\
2006f25ae9SGregory Neil Shapiro      Copyright (c) 1992, 1993\n\
2140266059SGregory Neil Shapiro 	The Regents of the University of California.  All rights reserved.\n")
2206f25ae9SGregory Neil Shapiro 
234a67213fSGregory Neil Shapiro SM_IDSTR(id, "@(#)$Id: makemap.c,v 8.183 2013-11-22 20:51:52 ca Exp $")
2406f25ae9SGregory Neil Shapiro 
2558162a73SPeter Wemm 
2658162a73SPeter Wemm #include <sys/types.h>
2758162a73SPeter Wemm #ifndef ISC_UNIX
2858162a73SPeter Wemm # include <sys/file.h>
29cee0d44aSGregory Neil Shapiro #endif
3006f25ae9SGregory Neil Shapiro #include <ctype.h>
3106f25ae9SGregory Neil Shapiro #include <stdlib.h>
3206f25ae9SGregory Neil Shapiro #include <unistd.h>
3306f25ae9SGregory Neil Shapiro #ifdef EX_OK
3406f25ae9SGregory Neil Shapiro # undef EX_OK		/* unistd.h may have another use for this */
35cee0d44aSGregory Neil Shapiro #endif
3606f25ae9SGregory Neil Shapiro #include <sysexits.h>
3706f25ae9SGregory Neil Shapiro #include <sendmail/sendmail.h>
38cee0d44aSGregory Neil Shapiro #include <sm/path.h>
3906f25ae9SGregory Neil Shapiro #include <sendmail/pathnames.h>
4006f25ae9SGregory Neil Shapiro #include <libsmdb/smdb.h>
4128fbd282SGregory Neil Shapiro #if USE_EAI
4228fbd282SGregory Neil Shapiro # include <sm/ixlen.h>
4328fbd282SGregory Neil Shapiro #endif
4458162a73SPeter Wemm 
45f3a1fc34SPeter Wemm uid_t	RealUid;
46f3a1fc34SPeter Wemm gid_t	RealGid;
47f3a1fc34SPeter Wemm char	*RealUserName;
48f3a1fc34SPeter Wemm uid_t	RunAsUid;
49*ffb83623SGregory Neil Shapiro gid_t	RunAsGid;
50f3a1fc34SPeter Wemm char	*RunAsUserName;
51f3a1fc34SPeter Wemm int	Verbose = 2;
5240266059SGregory Neil Shapiro bool	DontInitGroups = false;
53065a643dSPeter Wemm uid_t	TrustedUid = 0;
5406f25ae9SGregory Neil Shapiro BITMAP256 DontBlameSendmail;
55f3a1fc34SPeter Wemm 
56850ef5aeSGregory Neil Shapiro static bool verbose = false;
57850ef5aeSGregory Neil Shapiro static int exitstat;
58850ef5aeSGregory Neil Shapiro 
5958162a73SPeter Wemm #define BUFSIZE		1024
60cee0d44aSGregory Neil Shapiro #define ISASCII(c)	isascii((unsigned char)(c))
61850ef5aeSGregory Neil Shapiro #define ISSPACE(c)	(ISASCII(c) && isspace(c))
62cee0d44aSGregory Neil Shapiro #define ISSEP(c) (sep == '\0' ? ISASCII(c) && isspace(c) : (c) == sep)
6306f25ae9SGregory Neil Shapiro 
64cee0d44aSGregory Neil Shapiro static void usage __P((const char *));
65cee0d44aSGregory Neil Shapiro static char *readcf __P((const char *, char *, bool));
66850ef5aeSGregory Neil Shapiro static void db_put __P((SMDB_DATABASE *, SMDB_DBENT, SMDB_DBENT, int, const char *, int, const char *));
67b6bacd31SGregory Neil Shapiro 
6806f25ae9SGregory Neil Shapiro static void
usage(progname)6906f25ae9SGregory Neil Shapiro usage(progname)
70cee0d44aSGregory Neil Shapiro 	const char *progname;
7106f25ae9SGregory Neil Shapiro {
7240266059SGregory Neil Shapiro 	sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
73e92d3f3fSGregory Neil Shapiro 		      "Usage: %s [-C cffile] [-N] [-c cachesize] [-D commentchar]\n",
7440266059SGregory Neil Shapiro 		      progname);
75e92d3f3fSGregory Neil Shapiro 	sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
76850ef5aeSGregory Neil Shapiro 		      "       %*s [-d] [-e] [-f] [-i type] [-l] [-o] [-r] [-s] [-t delimiter]\n",
77e92d3f3fSGregory Neil Shapiro 		      (int) strlen(progname), "");
7828fbd282SGregory Neil Shapiro #if _FFR_TESTS
7928fbd282SGregory Neil Shapiro 	sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
8028fbd282SGregory Neil Shapiro 		      "       %*s [-S n]\n",
8128fbd282SGregory Neil Shapiro 		      (int) strlen(progname), "");
8228fbd282SGregory Neil Shapiro #endif
83e92d3f3fSGregory Neil Shapiro 	sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
84e92d3f3fSGregory Neil Shapiro 		      "       %*s [-u] [-v] type mapname\n",
85e92d3f3fSGregory Neil Shapiro 		      (int) strlen(progname), "");
8606f25ae9SGregory Neil Shapiro 	exit(EX_USAGE);
8706f25ae9SGregory Neil Shapiro }
8858162a73SPeter Wemm 
89cee0d44aSGregory Neil Shapiro /*
90850ef5aeSGregory Neil Shapiro **  DB_PUT -- do the DB insert
91850ef5aeSGregory Neil Shapiro **
92850ef5aeSGregory Neil Shapiro **	Parameters:
93850ef5aeSGregory Neil Shapiro **		database -- DB to use
94850ef5aeSGregory Neil Shapiro **		db_key -- key
95850ef5aeSGregory Neil Shapiro **		db_val -- value
96850ef5aeSGregory Neil Shapiro **		putflags -- flags for smdb_put()
97850ef5aeSGregory Neil Shapiro **		mapname -- name of map (for error reporting)
98850ef5aeSGregory Neil Shapiro **		lineno -- line number (for error reporting)
99850ef5aeSGregory Neil Shapiro **		progname -- name of program (for error reporting)
100850ef5aeSGregory Neil Shapiro **
101850ef5aeSGregory Neil Shapiro **	Returns:
102850ef5aeSGregory Neil Shapiro **		none.
103850ef5aeSGregory Neil Shapiro **
104850ef5aeSGregory Neil Shapiro **	Side effects:
105850ef5aeSGregory Neil Shapiro **		Sets exitstat so makemap exits with error if put fails
106850ef5aeSGregory Neil Shapiro */
107850ef5aeSGregory Neil Shapiro 
108850ef5aeSGregory Neil Shapiro static void
db_put(database,db_key,db_val,putflags,mapname,lineno,progname)109850ef5aeSGregory Neil Shapiro db_put(database, db_key, db_val, putflags, mapname, lineno, progname)
110850ef5aeSGregory Neil Shapiro 	SMDB_DATABASE *database;
111850ef5aeSGregory Neil Shapiro 	SMDB_DBENT db_key, db_val;
112850ef5aeSGregory Neil Shapiro 	int putflags;
113850ef5aeSGregory Neil Shapiro 	const char *mapname;
114850ef5aeSGregory Neil Shapiro 	int lineno;
115850ef5aeSGregory Neil Shapiro 	const char *progname;
116850ef5aeSGregory Neil Shapiro {
117850ef5aeSGregory Neil Shapiro 	int errcode;
118850ef5aeSGregory Neil Shapiro 
119850ef5aeSGregory Neil Shapiro 	if (verbose)
120850ef5aeSGregory Neil Shapiro 	{
121850ef5aeSGregory Neil Shapiro 		(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
122850ef5aeSGregory Neil Shapiro 				     "key=`%s', val=`%s'\n",
123850ef5aeSGregory Neil Shapiro 				     (char *) db_key.data,
124850ef5aeSGregory Neil Shapiro 				     (char *) db_val.data);
125850ef5aeSGregory Neil Shapiro 	}
126850ef5aeSGregory Neil Shapiro 
127850ef5aeSGregory Neil Shapiro 	errcode = database->smdb_put(database, &db_key, &db_val, putflags);
128850ef5aeSGregory Neil Shapiro 	if (0 == errcode)
129850ef5aeSGregory Neil Shapiro 		return;
130850ef5aeSGregory Neil Shapiro 
131850ef5aeSGregory Neil Shapiro 	(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "%s: %s: ",
132850ef5aeSGregory Neil Shapiro 			     progname, mapname);
133850ef5aeSGregory Neil Shapiro 	if (lineno >= 0)
134850ef5aeSGregory Neil Shapiro 		(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "line %u: ",
135850ef5aeSGregory Neil Shapiro 				     lineno);
136850ef5aeSGregory Neil Shapiro 	(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "key %s: ",
137850ef5aeSGregory Neil Shapiro 			     (char *) db_key.data);
138850ef5aeSGregory Neil Shapiro 	if (SMDBE_KEY_EXIST == errcode)
139850ef5aeSGregory Neil Shapiro 	{
140850ef5aeSGregory Neil Shapiro 		(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
141850ef5aeSGregory Neil Shapiro 				     "duplicate key\n");
142850ef5aeSGregory Neil Shapiro 		exitstat = EX_DATAERR;
143850ef5aeSGregory Neil Shapiro 	}
144850ef5aeSGregory Neil Shapiro 	else
145850ef5aeSGregory Neil Shapiro 	{
146850ef5aeSGregory Neil Shapiro 		(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
147850ef5aeSGregory Neil Shapiro 				     "put error: %s\n", sm_errstring(errcode));
148850ef5aeSGregory Neil Shapiro 		exitstat = EX_IOERR;
149850ef5aeSGregory Neil Shapiro 	}
150850ef5aeSGregory Neil Shapiro }
151850ef5aeSGregory Neil Shapiro 
152850ef5aeSGregory Neil Shapiro /*
153cee0d44aSGregory Neil Shapiro **  READCF -- read some settings from configuration file.
154cee0d44aSGregory Neil Shapiro **
155cee0d44aSGregory Neil Shapiro **	Parameters:
156cee0d44aSGregory Neil Shapiro **		cfile -- configuration file name.
157cee0d44aSGregory Neil Shapiro **		mapfile -- file name of map to look up (if not NULL/empty)
158cee0d44aSGregory Neil Shapiro **			Note: this finds the first match, so in case someone
159cee0d44aSGregory Neil Shapiro **			uses the same map file for different maps, they are
160cee0d44aSGregory Neil Shapiro **			hopefully using the same map type.
161cee0d44aSGregory Neil Shapiro **		fullpath -- compare the full paths or just the "basename"s?
162cee0d44aSGregory Neil Shapiro **			(even excluding any .ext !)
163cee0d44aSGregory Neil Shapiro **
164cee0d44aSGregory Neil Shapiro **	Returns:
165cee0d44aSGregory Neil Shapiro **		pointer to map class name (static!)
166cee0d44aSGregory Neil Shapiro */
167cee0d44aSGregory Neil Shapiro 
168cee0d44aSGregory Neil Shapiro static char *
readcf(cfile,mapfile,fullpath)169cee0d44aSGregory Neil Shapiro readcf(cfile, mapfile, fullpath)
170cee0d44aSGregory Neil Shapiro 	const char *cfile;
171cee0d44aSGregory Neil Shapiro 	char *mapfile;
172cee0d44aSGregory Neil Shapiro 	bool fullpath;
173cee0d44aSGregory Neil Shapiro {
174cee0d44aSGregory Neil Shapiro 	SM_FILE_T *cfp;
175cee0d44aSGregory Neil Shapiro 	char buf[MAXLINE];
176cee0d44aSGregory Neil Shapiro 	static char classbuf[MAXLINE];
177850ef5aeSGregory Neil Shapiro 	char *classname, *mapname;
178cee0d44aSGregory Neil Shapiro 	char *p;
179cee0d44aSGregory Neil Shapiro 
180cee0d44aSGregory Neil Shapiro 	if ((cfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, cfile,
181cee0d44aSGregory Neil Shapiro 			      SM_IO_RDONLY, NULL)) == NULL)
182cee0d44aSGregory Neil Shapiro 	{
183cee0d44aSGregory Neil Shapiro 		sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
184cee0d44aSGregory Neil Shapiro 			      "makemap: %s: %s\n",
185cee0d44aSGregory Neil Shapiro 			      cfile, sm_errstring(errno));
186cee0d44aSGregory Neil Shapiro 		exit(EX_NOINPUT);
187cee0d44aSGregory Neil Shapiro 	}
188cee0d44aSGregory Neil Shapiro 	classname = NULL;
189cee0d44aSGregory Neil Shapiro 	classbuf[0] = '\0';
190cee0d44aSGregory Neil Shapiro 
191850ef5aeSGregory Neil Shapiro 	mapname = mapfile;
192cee0d44aSGregory Neil Shapiro 	if (!fullpath && mapfile != NULL)
193cee0d44aSGregory Neil Shapiro 	{
194cee0d44aSGregory Neil Shapiro 		p = strrchr(mapfile, '/');
195cee0d44aSGregory Neil Shapiro 		if (p != NULL)
196cee0d44aSGregory Neil Shapiro 			mapfile = ++p;
197850ef5aeSGregory Neil Shapiro 		mapname = strdup(mapfile);
198850ef5aeSGregory Neil Shapiro 		if (NULL == mapname)
199850ef5aeSGregory Neil Shapiro 		{
200850ef5aeSGregory Neil Shapiro 			sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
201850ef5aeSGregory Neil Shapiro 			      "makemap: strdup(%s) failed: %s\n",
202850ef5aeSGregory Neil Shapiro 			      mapfile, sm_errstring(errno));
203850ef5aeSGregory Neil Shapiro 			exit(EX_OSERR);
204850ef5aeSGregory Neil Shapiro 		}
205850ef5aeSGregory Neil Shapiro 		if ((p = strchr(mapname, '.')) != NULL)
206cee0d44aSGregory Neil Shapiro 			*p = '\0';
207cee0d44aSGregory Neil Shapiro 	}
208cee0d44aSGregory Neil Shapiro 
209cee0d44aSGregory Neil Shapiro 	while (sm_io_fgets(cfp, SM_TIME_DEFAULT, buf, sizeof(buf)) >= 0)
210cee0d44aSGregory Neil Shapiro 	{
211cee0d44aSGregory Neil Shapiro 		char *b;
212cee0d44aSGregory Neil Shapiro 
213cee0d44aSGregory Neil Shapiro 		if ((b = strchr(buf, '\n')) != NULL)
214cee0d44aSGregory Neil Shapiro 			*b = '\0';
215cee0d44aSGregory Neil Shapiro 
216cee0d44aSGregory Neil Shapiro 		b = buf;
217cee0d44aSGregory Neil Shapiro 		switch (*b++)
218cee0d44aSGregory Neil Shapiro 		{
219cee0d44aSGregory Neil Shapiro 		  case 'O':		/* option */
220cee0d44aSGregory Neil Shapiro #if HASFCHOWN
221cee0d44aSGregory Neil Shapiro 			if (strncasecmp(b, " TrustedUser", 12) == 0 &&
222cee0d44aSGregory Neil Shapiro 			    !(ISASCII(b[12]) && isalnum(b[12])))
223cee0d44aSGregory Neil Shapiro 			{
224cee0d44aSGregory Neil Shapiro 				b = strchr(b, '=');
225cee0d44aSGregory Neil Shapiro 				if (b == NULL)
226cee0d44aSGregory Neil Shapiro 					continue;
227cee0d44aSGregory Neil Shapiro 				while (ISASCII(*++b) && isspace(*b))
228cee0d44aSGregory Neil Shapiro 					continue;
229cee0d44aSGregory Neil Shapiro 				if (ISASCII(*b) && isdigit(*b))
230cee0d44aSGregory Neil Shapiro 					TrustedUid = atoi(b);
231cee0d44aSGregory Neil Shapiro 				else
232cee0d44aSGregory Neil Shapiro 				{
233cee0d44aSGregory Neil Shapiro 					struct passwd *pw;
234cee0d44aSGregory Neil Shapiro 
235cee0d44aSGregory Neil Shapiro 					TrustedUid = 0;
236cee0d44aSGregory Neil Shapiro 					pw = getpwnam(b);
237cee0d44aSGregory Neil Shapiro 					if (pw == NULL)
238cee0d44aSGregory Neil Shapiro 						(void) sm_io_fprintf(smioerr,
239cee0d44aSGregory Neil Shapiro 								     SM_TIME_DEFAULT,
240cee0d44aSGregory Neil Shapiro 								     "TrustedUser: unknown user %s\n", b);
241cee0d44aSGregory Neil Shapiro 					else
242cee0d44aSGregory Neil Shapiro 						TrustedUid = pw->pw_uid;
243cee0d44aSGregory Neil Shapiro 				}
244cee0d44aSGregory Neil Shapiro 
245cee0d44aSGregory Neil Shapiro # ifdef UID_MAX
246cee0d44aSGregory Neil Shapiro 				if (TrustedUid > UID_MAX)
247cee0d44aSGregory Neil Shapiro 				{
248cee0d44aSGregory Neil Shapiro 					(void) sm_io_fprintf(smioerr,
249cee0d44aSGregory Neil Shapiro 							     SM_TIME_DEFAULT,
250cee0d44aSGregory Neil Shapiro 							     "TrustedUser: uid value (%ld) > UID_MAX (%ld)",
251cee0d44aSGregory Neil Shapiro 						(long) TrustedUid,
252cee0d44aSGregory Neil Shapiro 						(long) UID_MAX);
253cee0d44aSGregory Neil Shapiro 					TrustedUid = 0;
254cee0d44aSGregory Neil Shapiro 				}
255cee0d44aSGregory Neil Shapiro # endif /* UID_MAX */
256cee0d44aSGregory Neil Shapiro 			}
257cee0d44aSGregory Neil Shapiro #endif /* HASFCHOWN */
258cee0d44aSGregory Neil Shapiro 			break;
259cee0d44aSGregory Neil Shapiro 
260cee0d44aSGregory Neil Shapiro 		  case 'K':		/* Keyfile (map) */
261cee0d44aSGregory Neil Shapiro 			if (classname != NULL)	/* found it already */
262cee0d44aSGregory Neil Shapiro 				continue;
263850ef5aeSGregory Neil Shapiro 			if (mapname == NULL || *mapname == '\0')
264cee0d44aSGregory Neil Shapiro 				continue;
265cee0d44aSGregory Neil Shapiro 
266cee0d44aSGregory Neil Shapiro 			/* cut off trailing spaces */
267850ef5aeSGregory Neil Shapiro 			for (p = buf + strlen(buf) - 1;
268850ef5aeSGregory Neil Shapiro 			     ISASCII(*p) && isspace(*p) && p > buf; p--)
269cee0d44aSGregory Neil Shapiro 				*p = '\0';
270cee0d44aSGregory Neil Shapiro 
271cee0d44aSGregory Neil Shapiro 			/* find the last argument */
272cee0d44aSGregory Neil Shapiro 			p = strrchr(buf, ' ');
273cee0d44aSGregory Neil Shapiro 			if (p == NULL)
274cee0d44aSGregory Neil Shapiro 				continue;
275850ef5aeSGregory Neil Shapiro 			b = strstr(p, mapname);
276cee0d44aSGregory Neil Shapiro 			if (b == NULL)
277cee0d44aSGregory Neil Shapiro 				continue;
278cee0d44aSGregory Neil Shapiro 			if (b <= buf)
279cee0d44aSGregory Neil Shapiro 				continue;
280cee0d44aSGregory Neil Shapiro 			if (!fullpath)
281cee0d44aSGregory Neil Shapiro 			{
282cee0d44aSGregory Neil Shapiro 				p = strrchr(b, '.');
283cee0d44aSGregory Neil Shapiro 				if (p != NULL)
284cee0d44aSGregory Neil Shapiro 					*p = '\0';
285cee0d44aSGregory Neil Shapiro 			}
286cee0d44aSGregory Neil Shapiro 
287cee0d44aSGregory Neil Shapiro 			/* allow trailing white space? */
288850ef5aeSGregory Neil Shapiro 			if (strcmp(mapname, b) != 0)
289cee0d44aSGregory Neil Shapiro 				continue;
290cee0d44aSGregory Neil Shapiro 			/* SM_ASSERT(b > buf); */
291cee0d44aSGregory Neil Shapiro 			--b;
292cee0d44aSGregory Neil Shapiro 			if (!ISASCII(*b))
293cee0d44aSGregory Neil Shapiro 				continue;
294cee0d44aSGregory Neil Shapiro 			if (!isspace(*b) && fullpath)
295cee0d44aSGregory Neil Shapiro 				continue;
296cee0d44aSGregory Neil Shapiro 			if (!fullpath && !(SM_IS_DIR_DELIM(*b) || isspace(*b)))
297cee0d44aSGregory Neil Shapiro 				continue;
298cee0d44aSGregory Neil Shapiro 
299cee0d44aSGregory Neil Shapiro 			/* basically from readcf.c */
300cee0d44aSGregory Neil Shapiro 			for (b = buf + 1; ISASCII(*b) && isspace(*b); b++)
301cee0d44aSGregory Neil Shapiro 				;
302cee0d44aSGregory Neil Shapiro 			if (!(ISASCII(*b) && isalnum(*b)))
303cee0d44aSGregory Neil Shapiro 			{
304cee0d44aSGregory Neil Shapiro 				/* syserr("readcf: config K line: no map name"); */
305cee0d44aSGregory Neil Shapiro 				return NULL;
306cee0d44aSGregory Neil Shapiro 			}
307cee0d44aSGregory Neil Shapiro 
308cee0d44aSGregory Neil Shapiro 			while ((ISASCII(*++b) && isalnum(*b)) || *b == '_' || *b == '.')
309cee0d44aSGregory Neil Shapiro 				;
310cee0d44aSGregory Neil Shapiro 			if (*b != '\0')
311cee0d44aSGregory Neil Shapiro 				*b++ = '\0';
312cee0d44aSGregory Neil Shapiro 			while (ISASCII(*b) && isspace(*b))
313cee0d44aSGregory Neil Shapiro 				b++;
314cee0d44aSGregory Neil Shapiro 			if (!(ISASCII(*b) && isalnum(*b)))
315cee0d44aSGregory Neil Shapiro 			{
316cee0d44aSGregory Neil Shapiro 				/* syserr("readcf: config K line, map %s: no map class", b); */
317cee0d44aSGregory Neil Shapiro 				return NULL;
318cee0d44aSGregory Neil Shapiro 			}
319cee0d44aSGregory Neil Shapiro 			classname = b;
320cee0d44aSGregory Neil Shapiro 			while (ISASCII(*++b) && isalnum(*b))
321cee0d44aSGregory Neil Shapiro 				;
322cee0d44aSGregory Neil Shapiro 			if (*b != '\0')
323cee0d44aSGregory Neil Shapiro 				*b++ = '\0';
324cee0d44aSGregory Neil Shapiro 			(void) sm_strlcpy(classbuf, classname, sizeof classbuf);
325cee0d44aSGregory Neil Shapiro 			break;
326cee0d44aSGregory Neil Shapiro 
327cee0d44aSGregory Neil Shapiro 		  default:
328cee0d44aSGregory Neil Shapiro 			continue;
329cee0d44aSGregory Neil Shapiro 		}
330cee0d44aSGregory Neil Shapiro 	}
331cee0d44aSGregory Neil Shapiro 	(void) sm_io_close(cfp, SM_TIME_DEFAULT);
332cee0d44aSGregory Neil Shapiro 
333850ef5aeSGregory Neil Shapiro 	/* not really needed because it is just a "one time leak" */
334850ef5aeSGregory Neil Shapiro 	if (mapname != mapfile && mapname != NULL)
335850ef5aeSGregory Neil Shapiro 	{
336850ef5aeSGregory Neil Shapiro 		free(mapname);
337850ef5aeSGregory Neil Shapiro 		mapname = NULL;
338850ef5aeSGregory Neil Shapiro 	}
339cee0d44aSGregory Neil Shapiro 	return classbuf;
340cee0d44aSGregory Neil Shapiro }
341cee0d44aSGregory Neil Shapiro 
342c2aa98e2SPeter Wemm int
main(argc,argv)34358162a73SPeter Wemm main(argc, argv)
34458162a73SPeter Wemm 	int argc;
34558162a73SPeter Wemm 	char **argv;
34658162a73SPeter Wemm {
34758162a73SPeter Wemm 	char *progname;
348c2aa98e2SPeter Wemm 	char *cfile;
34940266059SGregory Neil Shapiro 	bool inclnull = false;
35040266059SGregory Neil Shapiro 	bool notrunc = false;
35140266059SGregory Neil Shapiro 	bool allowreplace = false;
35240266059SGregory Neil Shapiro 	bool allowempty = false;
35340266059SGregory Neil Shapiro 	bool foldcase = true;
35440266059SGregory Neil Shapiro 	bool unmake = false;
355850ef5aeSGregory Neil Shapiro #if _FFR_MM_ALIASES
356850ef5aeSGregory Neil Shapiro 	/*
357850ef5aeSGregory Neil Shapiro 	**  NOTE: this does not work properly:
358850ef5aeSGregory Neil Shapiro 	**  sendmail does address rewriting which is not done here.
359850ef5aeSGregory Neil Shapiro 	*/
360850ef5aeSGregory Neil Shapiro 
361850ef5aeSGregory Neil Shapiro 	bool aliases = false;
362850ef5aeSGregory Neil Shapiro #endif
363cee0d44aSGregory Neil Shapiro 	bool didreadcf = false;
36406f25ae9SGregory Neil Shapiro 	char sep = '\0';
36540266059SGregory Neil Shapiro 	char comment = '#';
36658162a73SPeter Wemm 	int opt;
367065a643dSPeter Wemm 	char *typename = NULL;
368cee0d44aSGregory Neil Shapiro 	char *fallback = NULL;
369065a643dSPeter Wemm 	char *mapname = NULL;
37040266059SGregory Neil Shapiro 	unsigned int lineno;
37158162a73SPeter Wemm 	int mode;
37206f25ae9SGregory Neil Shapiro 	int smode;
373065a643dSPeter Wemm 	int putflags = 0;
37406f25ae9SGregory Neil Shapiro 	long sff = SFF_ROOTOK|SFF_REGONLY;
375c2aa98e2SPeter Wemm 	struct passwd *pw;
37606f25ae9SGregory Neil Shapiro 	SMDB_DATABASE *database;
37706f25ae9SGregory Neil Shapiro 	SMDB_CURSOR *cursor;
37806f25ae9SGregory Neil Shapiro 	SMDB_DBENT db_key, db_val;
37906f25ae9SGregory Neil Shapiro 	SMDB_DBPARAMS params;
38006f25ae9SGregory Neil Shapiro 	SMDB_USER_INFO user_info;
38158162a73SPeter Wemm 	char ibuf[BUFSIZE];
382f3a1fc34SPeter Wemm 	static char rnamebuf[MAXNAME];	/* holds RealUserName */
38358162a73SPeter Wemm 	extern char *optarg;
38458162a73SPeter Wemm 	extern int optind;
38528fbd282SGregory Neil Shapiro #if USE_EAI
38628fbd282SGregory Neil Shapiro 	bool ascii = true;
38728fbd282SGregory Neil Shapiro #endif
38828fbd282SGregory Neil Shapiro #if _FFR_TESTS
38928fbd282SGregory Neil Shapiro 	int slp = 0;
39028fbd282SGregory Neil Shapiro #endif
39158162a73SPeter Wemm 
39206f25ae9SGregory Neil Shapiro 	memset(&params, '\0', sizeof params);
39306f25ae9SGregory Neil Shapiro 	params.smdbp_cache_size = 1024 * 1024;
39406f25ae9SGregory Neil Shapiro 
39506f25ae9SGregory Neil Shapiro 	progname = strrchr(argv[0], '/');
39606f25ae9SGregory Neil Shapiro 	if (progname != NULL)
39706f25ae9SGregory Neil Shapiro 		progname++;
39806f25ae9SGregory Neil Shapiro 	else
39958162a73SPeter Wemm 		progname = argv[0];
40040266059SGregory Neil Shapiro 	cfile = getcfname(0, 0, SM_GET_SENDMAIL_CF, NULL);
40158162a73SPeter Wemm 
40206f25ae9SGregory Neil Shapiro 	clrbitmap(DontBlameSendmail);
403f3a1fc34SPeter Wemm 	RunAsUid = RealUid = getuid();
404f3a1fc34SPeter Wemm 	RunAsGid = RealGid = getgid();
405f3a1fc34SPeter Wemm 	pw = getpwuid(RealUid);
406f3a1fc34SPeter Wemm 	if (pw != NULL)
40740266059SGregory Neil Shapiro 		(void) sm_strlcpy(rnamebuf, pw->pw_name, sizeof rnamebuf);
408f3a1fc34SPeter Wemm 	else
40940266059SGregory Neil Shapiro 		(void) sm_snprintf(rnamebuf, sizeof rnamebuf,
41040266059SGregory Neil Shapiro 		    "Unknown UID %d", (int) RealUid);
411f3a1fc34SPeter Wemm 	RunAsUserName = RealUserName = rnamebuf;
41206f25ae9SGregory Neil Shapiro 	user_info.smdbu_id = RunAsUid;
41306f25ae9SGregory Neil Shapiro 	user_info.smdbu_group_id = RunAsGid;
41440266059SGregory Neil Shapiro 	(void) sm_strlcpy(user_info.smdbu_name, RunAsUserName,
41506f25ae9SGregory Neil Shapiro 		       SMDB_MAX_USER_NAME_LEN);
416f3a1fc34SPeter Wemm 
417cee0d44aSGregory Neil Shapiro #define OPTIONS		"C:D:Nc:defi:Llorst:uvx"
418850ef5aeSGregory Neil Shapiro #if _FFR_MM_ALIASES
419850ef5aeSGregory Neil Shapiro # define A_OPTIONS		"a"
420850ef5aeSGregory Neil Shapiro #else
421850ef5aeSGregory Neil Shapiro # define A_OPTIONS
422850ef5aeSGregory Neil Shapiro #endif
42328fbd282SGregory Neil Shapiro #if _FFR_TESTS
42428fbd282SGregory Neil Shapiro # define X_OPTIONS		"S:"
42528fbd282SGregory Neil Shapiro #else
42628fbd282SGregory Neil Shapiro # define X_OPTIONS
42728fbd282SGregory Neil Shapiro #endif
428850ef5aeSGregory Neil Shapiro 	while ((opt = getopt(argc, argv, A_OPTIONS OPTIONS X_OPTIONS)) != -1)
42958162a73SPeter Wemm 	{
43058162a73SPeter Wemm 		switch (opt)
43158162a73SPeter Wemm 		{
432c2aa98e2SPeter Wemm 		  case 'C':
433c2aa98e2SPeter Wemm 			cfile = optarg;
434c2aa98e2SPeter Wemm 			break;
435c2aa98e2SPeter Wemm 
43658162a73SPeter Wemm 		  case 'N':
43740266059SGregory Neil Shapiro 			inclnull = true;
43858162a73SPeter Wemm 			break;
43958162a73SPeter Wemm 
440850ef5aeSGregory Neil Shapiro #if _FFR_MM_ALIASES
441850ef5aeSGregory Neil Shapiro 		  case 'a':
442850ef5aeSGregory Neil Shapiro 			/* Note: this doesn't verify e-mail addresses */
443850ef5aeSGregory Neil Shapiro 			sep = ':';
444850ef5aeSGregory Neil Shapiro 			aliases = true;
445850ef5aeSGregory Neil Shapiro 			break;
446850ef5aeSGregory Neil Shapiro #endif
447850ef5aeSGregory Neil Shapiro 
448fcf445deSPeter Wemm 		  case 'c':
44906f25ae9SGregory Neil Shapiro 			params.smdbp_cache_size = atol(optarg);
450fcf445deSPeter Wemm 			break;
451fcf445deSPeter Wemm 
45258162a73SPeter Wemm 		  case 'd':
45340266059SGregory Neil Shapiro 			params.smdbp_allow_dup = true;
45406f25ae9SGregory Neil Shapiro 			break;
45506f25ae9SGregory Neil Shapiro 
45606f25ae9SGregory Neil Shapiro 		  case 'e':
45740266059SGregory Neil Shapiro 			allowempty = true;
45858162a73SPeter Wemm 			break;
45958162a73SPeter Wemm 
46058162a73SPeter Wemm 		  case 'f':
46140266059SGregory Neil Shapiro 			foldcase = false;
46258162a73SPeter Wemm 			break;
46358162a73SPeter Wemm 
464cee0d44aSGregory Neil Shapiro 		  case 'i':
465cee0d44aSGregory Neil Shapiro 			fallback =optarg;
466cee0d44aSGregory Neil Shapiro 			break;
467cee0d44aSGregory Neil Shapiro 
46840266059SGregory Neil Shapiro 		  case 'D':
46940266059SGregory Neil Shapiro 			comment = *optarg;
47040266059SGregory Neil Shapiro 			break;
47140266059SGregory Neil Shapiro 
472cee0d44aSGregory Neil Shapiro 		  case 'L':
473cee0d44aSGregory Neil Shapiro 			smdb_print_available_types(false);
474cee0d44aSGregory Neil Shapiro 			sm_io_fprintf(smioout, SM_TIME_DEFAULT,
475cee0d44aSGregory Neil Shapiro 				      "cf\nCF\n");
476cee0d44aSGregory Neil Shapiro 			exit(EX_OK);
477cee0d44aSGregory Neil Shapiro 			break;
478cee0d44aSGregory Neil Shapiro 
479065a643dSPeter Wemm 		  case 'l':
480cee0d44aSGregory Neil Shapiro 			smdb_print_available_types(false);
481065a643dSPeter Wemm 			exit(EX_OK);
482065a643dSPeter Wemm 			break;
483065a643dSPeter Wemm 
48458162a73SPeter Wemm 		  case 'o':
48540266059SGregory Neil Shapiro 			notrunc = true;
48658162a73SPeter Wemm 			break;
48758162a73SPeter Wemm 
48858162a73SPeter Wemm 		  case 'r':
48940266059SGregory Neil Shapiro 			allowreplace = true;
49058162a73SPeter Wemm 			break;
49158162a73SPeter Wemm 
49228fbd282SGregory Neil Shapiro #if _FFR_TESTS
49328fbd282SGregory Neil Shapiro 		  case 'S':
49428fbd282SGregory Neil Shapiro 			slp = atoi(optarg);
49528fbd282SGregory Neil Shapiro 			break;
49628fbd282SGregory Neil Shapiro #endif
49728fbd282SGregory Neil Shapiro 
498f3a1fc34SPeter Wemm 		  case 's':
49906f25ae9SGregory Neil Shapiro 			setbitn(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail);
50006f25ae9SGregory Neil Shapiro 			setbitn(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail);
50106f25ae9SGregory Neil Shapiro 			setbitn(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail);
50206f25ae9SGregory Neil Shapiro 			setbitn(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail);
50306f25ae9SGregory Neil Shapiro 			break;
50406f25ae9SGregory Neil Shapiro 
50506f25ae9SGregory Neil Shapiro 		  case 't':
50606f25ae9SGregory Neil Shapiro 			if (optarg == NULL || *optarg == '\0')
50706f25ae9SGregory Neil Shapiro 			{
50840266059SGregory Neil Shapiro 				sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
50940266059SGregory Neil Shapiro 					      "Invalid separator\n");
51006f25ae9SGregory Neil Shapiro 				break;
51106f25ae9SGregory Neil Shapiro 			}
51206f25ae9SGregory Neil Shapiro 			sep = *optarg;
51306f25ae9SGregory Neil Shapiro 			break;
51406f25ae9SGregory Neil Shapiro 
51506f25ae9SGregory Neil Shapiro 		  case 'u':
51640266059SGregory Neil Shapiro 			unmake = true;
517f3a1fc34SPeter Wemm 			break;
518f3a1fc34SPeter Wemm 
51958162a73SPeter Wemm 		  case 'v':
52040266059SGregory Neil Shapiro 			verbose = true;
52158162a73SPeter Wemm 			break;
52258162a73SPeter Wemm 
523cee0d44aSGregory Neil Shapiro 		  case 'x':
524cee0d44aSGregory Neil Shapiro 			smdb_print_available_types(true);
525cee0d44aSGregory Neil Shapiro 			exit(EX_OK);
526cee0d44aSGregory Neil Shapiro 			break;
527cee0d44aSGregory Neil Shapiro 
52858162a73SPeter Wemm 		  default:
52906f25ae9SGregory Neil Shapiro 			usage(progname);
53006f25ae9SGregory Neil Shapiro 			/* NOTREACHED */
53158162a73SPeter Wemm 		}
53258162a73SPeter Wemm 	}
53358162a73SPeter Wemm 
53406f25ae9SGregory Neil Shapiro 	if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail))
535c2aa98e2SPeter Wemm 		sff |= SFF_NOSLINK;
53606f25ae9SGregory Neil Shapiro 	if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail))
537c2aa98e2SPeter Wemm 		sff |= SFF_NOHLINK;
53806f25ae9SGregory Neil Shapiro 	if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail))
539c2aa98e2SPeter Wemm 		sff |= SFF_NOWLINK;
540c2aa98e2SPeter Wemm 
54158162a73SPeter Wemm 	argc -= optind;
54258162a73SPeter Wemm 	argv += optind;
54358162a73SPeter Wemm 	if (argc != 2)
54406f25ae9SGregory Neil Shapiro 	{
54506f25ae9SGregory Neil Shapiro 		usage(progname);
54606f25ae9SGregory Neil Shapiro 		/* NOTREACHED */
54706f25ae9SGregory Neil Shapiro 	}
54858162a73SPeter Wemm 	else
54958162a73SPeter Wemm 	{
55058162a73SPeter Wemm 		typename = argv[0];
55158162a73SPeter Wemm 		mapname = argv[1];
55258162a73SPeter Wemm 	}
55358162a73SPeter Wemm 
554cee0d44aSGregory Neil Shapiro #define TYPEFROMCF	(strcasecmp(typename, "cf") == 0)
555cee0d44aSGregory Neil Shapiro #define FULLPATHFROMCF	(strcmp(typename, "cf") == 0)
556cee0d44aSGregory Neil Shapiro 
55706f25ae9SGregory Neil Shapiro #if HASFCHOWN
558cee0d44aSGregory Neil Shapiro 	if (geteuid() == 0)
559c1bfccf7SGregory Neil Shapiro 	{
560cee0d44aSGregory Neil Shapiro 		if (TYPEFROMCF)
561cee0d44aSGregory Neil Shapiro 			typename = readcf(cfile, mapname, FULLPATHFROMCF);
562c2aa98e2SPeter Wemm 		else
563cee0d44aSGregory Neil Shapiro 			(void) readcf(cfile, NULL, false);
564cee0d44aSGregory Neil Shapiro 		didreadcf = true;
565c2aa98e2SPeter Wemm 	}
56606f25ae9SGregory Neil Shapiro #endif /* HASFCHOWN */
56706f25ae9SGregory Neil Shapiro 
56806f25ae9SGregory Neil Shapiro 	if (!params.smdbp_allow_dup && !allowreplace)
56906f25ae9SGregory Neil Shapiro 		putflags = SMDBF_NO_OVERWRITE;
57006f25ae9SGregory Neil Shapiro 
57106f25ae9SGregory Neil Shapiro 	if (unmake)
57258162a73SPeter Wemm 	{
57306f25ae9SGregory Neil Shapiro 		mode = O_RDONLY;
57406f25ae9SGregory Neil Shapiro 		smode = S_IRUSR;
575c2aa98e2SPeter Wemm 	}
576606a9934SPeter Wemm 	else
577c2aa98e2SPeter Wemm 	{
57858162a73SPeter Wemm 		mode = O_RDWR;
57958162a73SPeter Wemm 		if (!notrunc)
58006f25ae9SGregory Neil Shapiro 		{
58158162a73SPeter Wemm 			mode |= O_CREAT|O_TRUNC;
58206f25ae9SGregory Neil Shapiro 			sff |= SFF_CREAT;
58358162a73SPeter Wemm 		}
58406f25ae9SGregory Neil Shapiro 		smode = S_IWUSR;
585ff37c899SPeter Wemm 	}
58606f25ae9SGregory Neil Shapiro 
58706f25ae9SGregory Neil Shapiro 	params.smdbp_num_elements = 4096;
58806f25ae9SGregory Neil Shapiro 
589cee0d44aSGregory Neil Shapiro 	if (!didreadcf && TYPEFROMCF)
590cee0d44aSGregory Neil Shapiro 	{
591cee0d44aSGregory Neil Shapiro 		typename = readcf(cfile, mapname, FULLPATHFROMCF);
592cee0d44aSGregory Neil Shapiro 		didreadcf = true;
593cee0d44aSGregory Neil Shapiro 	}
594cee0d44aSGregory Neil Shapiro 	if (didreadcf && (typename == NULL || *typename == '\0'))
595cee0d44aSGregory Neil Shapiro 	{
596cee0d44aSGregory Neil Shapiro 		if (fallback != NULL && *fallback != '\0')
597cee0d44aSGregory Neil Shapiro 		{
598cee0d44aSGregory Neil Shapiro 			typename = fallback;
599cee0d44aSGregory Neil Shapiro 			if (verbose)
600cee0d44aSGregory Neil Shapiro 				(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
601cee0d44aSGregory Neil Shapiro 				     "%s: mapfile %s: not found in %s, using fallback %s\n",
602cee0d44aSGregory Neil Shapiro 				     progname, mapname, cfile, fallback);
603cee0d44aSGregory Neil Shapiro 		}
604cee0d44aSGregory Neil Shapiro 		else
605cee0d44aSGregory Neil Shapiro 		{
606cee0d44aSGregory Neil Shapiro 			(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
607cee0d44aSGregory Neil Shapiro 				     "%s: mapfile %s: not found in %s\n",
608cee0d44aSGregory Neil Shapiro 				     progname, mapname, cfile);
609cee0d44aSGregory Neil Shapiro 			exit(EX_DATAERR);
610cee0d44aSGregory Neil Shapiro 		}
611cee0d44aSGregory Neil Shapiro 	}
612cee0d44aSGregory Neil Shapiro 
613cee0d44aSGregory Neil Shapiro 	/*
614cee0d44aSGregory Neil Shapiro 	**  Note: if "implicit" is selected it does not work like
615cee0d44aSGregory Neil Shapiro 	**  sendmail: it will just use the first available DB type,
616cee0d44aSGregory Neil Shapiro 	**  it won't try several (for -u) to find one that "works".
617cee0d44aSGregory Neil Shapiro 	*/
618cee0d44aSGregory Neil Shapiro 
61906f25ae9SGregory Neil Shapiro 	errno = smdb_open_database(&database, mapname, mode, smode, sff,
62006f25ae9SGregory Neil Shapiro 				   typename, &user_info, &params);
62106f25ae9SGregory Neil Shapiro 	if (errno != SMDBE_OK)
622f3a1fc34SPeter Wemm 	{
62306f25ae9SGregory Neil Shapiro 		char *hint;
62406f25ae9SGregory Neil Shapiro 
62506f25ae9SGregory Neil Shapiro 		if (errno == SMDBE_UNSUPPORTED_DB_TYPE &&
62606f25ae9SGregory Neil Shapiro 		    (hint = smdb_db_definition(typename)) != NULL)
62740266059SGregory Neil Shapiro 			(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
62806f25ae9SGregory Neil Shapiro 					     "%s: Need to recompile with -D%s for %s support\n",
62906f25ae9SGregory Neil Shapiro 					     progname, hint, typename);
63006f25ae9SGregory Neil Shapiro 		else
63140266059SGregory Neil Shapiro 			(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
63206f25ae9SGregory Neil Shapiro 					     "%s: error opening type %s map %s: %s\n",
63340266059SGregory Neil Shapiro 					     progname, typename, mapname,
63440266059SGregory Neil Shapiro 					     sm_errstring(errno));
635f3a1fc34SPeter Wemm 		exit(EX_CANTCREAT);
636f3a1fc34SPeter Wemm 	}
63706f25ae9SGregory Neil Shapiro 
63806f25ae9SGregory Neil Shapiro 	(void) database->smdb_sync(database, 0);
63906f25ae9SGregory Neil Shapiro 
64042e5d165SGregory Neil Shapiro 	if (!unmake && geteuid() == 0 && TrustedUid != 0)
641c2aa98e2SPeter Wemm 	{
64206f25ae9SGregory Neil Shapiro 		errno = database->smdb_set_owner(database, TrustedUid, -1);
64306f25ae9SGregory Neil Shapiro 		if (errno != SMDBE_OK)
644c2aa98e2SPeter Wemm 		{
64540266059SGregory Neil Shapiro 			(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
64606f25ae9SGregory Neil Shapiro 					     "WARNING: ownership change on %s failed %s",
64740266059SGregory Neil Shapiro 					     mapname, sm_errstring(errno));
648c2aa98e2SPeter Wemm 		}
649c2aa98e2SPeter Wemm 	}
65058162a73SPeter Wemm 
65158162a73SPeter Wemm 	/*
65258162a73SPeter Wemm 	**  Copy the data
65358162a73SPeter Wemm 	*/
65458162a73SPeter Wemm 
65558162a73SPeter Wemm 	exitstat = EX_OK;
65606f25ae9SGregory Neil Shapiro 	if (unmake)
65706f25ae9SGregory Neil Shapiro 	{
65806f25ae9SGregory Neil Shapiro 		errno = database->smdb_cursor(database, &cursor, 0);
65906f25ae9SGregory Neil Shapiro 		if (errno != SMDBE_OK)
66006f25ae9SGregory Neil Shapiro 		{
66106f25ae9SGregory Neil Shapiro 
66240266059SGregory Neil Shapiro 			(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
66306f25ae9SGregory Neil Shapiro 					     "%s: cannot make cursor for type %s map %s\n",
66406f25ae9SGregory Neil Shapiro 					     progname, typename, mapname);
66506f25ae9SGregory Neil Shapiro 			exit(EX_SOFTWARE);
66606f25ae9SGregory Neil Shapiro 		}
66706f25ae9SGregory Neil Shapiro 
66806f25ae9SGregory Neil Shapiro 		memset(&db_key, '\0', sizeof db_key);
66906f25ae9SGregory Neil Shapiro 		memset(&db_val, '\0', sizeof db_val);
67006f25ae9SGregory Neil Shapiro 
671193538b7SGregory Neil Shapiro 		for (lineno = 0; ; lineno++)
67206f25ae9SGregory Neil Shapiro 		{
67306f25ae9SGregory Neil Shapiro 			errno = cursor->smdbc_get(cursor, &db_key, &db_val,
67406f25ae9SGregory Neil Shapiro 						  SMDB_CURSOR_GET_NEXT);
67506f25ae9SGregory Neil Shapiro 			if (errno != SMDBE_OK)
676193538b7SGregory Neil Shapiro 				break;
677193538b7SGregory Neil Shapiro 
67840266059SGregory Neil Shapiro 			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
679e8e0e582SGregory Neil Shapiro 					     "%.*s%c%.*s\n",
680193538b7SGregory Neil Shapiro 					     (int) db_key.size,
681193538b7SGregory Neil Shapiro 					     (char *) db_key.data,
682e8e0e582SGregory Neil Shapiro 					     (sep != '\0') ? sep : '\t',
683193538b7SGregory Neil Shapiro 					     (int) db_val.size,
684193538b7SGregory Neil Shapiro 					     (char *)db_val.data);
68506f25ae9SGregory Neil Shapiro 
68606f25ae9SGregory Neil Shapiro 		}
68706f25ae9SGregory Neil Shapiro 		(void) cursor->smdbc_close(cursor);
68806f25ae9SGregory Neil Shapiro 	}
68906f25ae9SGregory Neil Shapiro 	else
69006f25ae9SGregory Neil Shapiro 	{
69106f25ae9SGregory Neil Shapiro 		lineno = 0;
69240266059SGregory Neil Shapiro 		while (sm_io_fgets(smioin, SM_TIME_DEFAULT, ibuf, sizeof ibuf)
693e388eeddSGregory Neil Shapiro 		       >= 0)
69458162a73SPeter Wemm 		{
69558162a73SPeter Wemm 			register char *p;
69658162a73SPeter Wemm 
69758162a73SPeter Wemm 			lineno++;
69858162a73SPeter Wemm 
69958162a73SPeter Wemm 			/*
70058162a73SPeter Wemm 			**  Parse the line.
70158162a73SPeter Wemm 			*/
70258162a73SPeter Wemm 
70358162a73SPeter Wemm 			p = strchr(ibuf, '\n');
70458162a73SPeter Wemm 			if (p != NULL)
70558162a73SPeter Wemm 				*p = '\0';
70640266059SGregory Neil Shapiro 			else if (!sm_io_eof(smioin))
70758162a73SPeter Wemm 			{
70840266059SGregory Neil Shapiro 				(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
70940266059SGregory Neil Shapiro 						     "%s: %s: line %u: line too long (%ld bytes max)\n",
71040266059SGregory Neil Shapiro 						     progname, mapname, lineno,
71140266059SGregory Neil Shapiro 						     (long) sizeof ibuf);
71206f25ae9SGregory Neil Shapiro 				exitstat = EX_DATAERR;
71358162a73SPeter Wemm 				continue;
71458162a73SPeter Wemm 			}
71558162a73SPeter Wemm 
71640266059SGregory Neil Shapiro 			if (ibuf[0] == '\0' || ibuf[0] == comment)
71758162a73SPeter Wemm 				continue;
718cee0d44aSGregory Neil Shapiro 			if (sep == '\0' && ISASCII(ibuf[0]) && isspace(ibuf[0]))
71958162a73SPeter Wemm 			{
72040266059SGregory Neil Shapiro 				(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
72140266059SGregory Neil Shapiro 						     "%s: %s: line %u: syntax error (leading space)\n",
72258162a73SPeter Wemm 						     progname, mapname, lineno);
72306f25ae9SGregory Neil Shapiro 				exitstat = EX_DATAERR;
72458162a73SPeter Wemm 				continue;
72558162a73SPeter Wemm 			}
726c2aa98e2SPeter Wemm 
72706f25ae9SGregory Neil Shapiro 			memset(&db_key, '\0', sizeof db_key);
72806f25ae9SGregory Neil Shapiro 			memset(&db_val, '\0', sizeof db_val);
729193538b7SGregory Neil Shapiro 			db_key.data = ibuf;
73006f25ae9SGregory Neil Shapiro 
73128fbd282SGregory Neil Shapiro #if USE_EAI
73228fbd282SGregory Neil Shapiro 			db_key.size = 0;
73328fbd282SGregory Neil Shapiro 			if (foldcase)
73428fbd282SGregory Neil Shapiro 			{
73528fbd282SGregory Neil Shapiro 				for (p = ibuf; *p != '\0' && !ISSEP(*p); p++)
73628fbd282SGregory Neil Shapiro 				{
73728fbd282SGregory Neil Shapiro 					if (!ISASCII(*p))
73828fbd282SGregory Neil Shapiro 						ascii = false;
73928fbd282SGregory Neil Shapiro 				}
74028fbd282SGregory Neil Shapiro 				if (!ascii)
74128fbd282SGregory Neil Shapiro 				{
74228fbd282SGregory Neil Shapiro 					char sep;
74328fbd282SGregory Neil Shapiro 					char *lkey;
74428fbd282SGregory Neil Shapiro 
74528fbd282SGregory Neil Shapiro 					sep = *p;
74628fbd282SGregory Neil Shapiro 					*p = '\0';
74728fbd282SGregory Neil Shapiro 
74828fbd282SGregory Neil Shapiro 					lkey = sm_lowercase(ibuf);
74928fbd282SGregory Neil Shapiro 					db_key.data = lkey;
75028fbd282SGregory Neil Shapiro 					db_key.size = strlen(lkey);
75128fbd282SGregory Neil Shapiro 					*p = sep;
75228fbd282SGregory Neil Shapiro 				}
75328fbd282SGregory Neil Shapiro 			}
75428fbd282SGregory Neil Shapiro 			if (ascii)
75528fbd282SGregory Neil Shapiro #endif /* USE_EAI */
75628fbd282SGregory Neil Shapiro 			/* NOTE: see if () above! */
75728fbd282SGregory Neil Shapiro 			for (p = ibuf; *p != '\0' && !ISSEP(*p); p++)
758c2aa98e2SPeter Wemm 			{
759cee0d44aSGregory Neil Shapiro 				if (foldcase && ISASCII(*p) && isupper(*p))
76058162a73SPeter Wemm 					*p = tolower(*p);
76158162a73SPeter Wemm 			}
76228fbd282SGregory Neil Shapiro #if USE_EAI
76328fbd282SGregory Neil Shapiro 			if (0 == db_key.size)
76428fbd282SGregory Neil Shapiro #endif
765193538b7SGregory Neil Shapiro 				db_key.size = p - ibuf;
76658162a73SPeter Wemm 			if (inclnull)
767193538b7SGregory Neil Shapiro 				db_key.size++;
76806f25ae9SGregory Neil Shapiro 
76958162a73SPeter Wemm 			if (*p != '\0')
77058162a73SPeter Wemm 				*p++ = '\0';
77140266059SGregory Neil Shapiro 			while (*p != '\0' && ISSEP(*p))
77258162a73SPeter Wemm 				p++;
773850ef5aeSGregory Neil Shapiro #if _FFR_MM_ALIASES
774850ef5aeSGregory Neil Shapiro 			while (aliases && *p != '\0' && ISSPACE(*p))
775850ef5aeSGregory Neil Shapiro 				p++;
776850ef5aeSGregory Neil Shapiro #endif
77706f25ae9SGregory Neil Shapiro 			if (!allowempty && *p == '\0')
77858162a73SPeter Wemm 			{
77940266059SGregory Neil Shapiro 				(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
78040266059SGregory Neil Shapiro 						     "%s: %s: line %u: no RHS for LHS %s\n",
78106f25ae9SGregory Neil Shapiro 						     progname, mapname, lineno,
782193538b7SGregory Neil Shapiro 						     (char *) db_key.data);
78306f25ae9SGregory Neil Shapiro 				exitstat = EX_DATAERR;
78458162a73SPeter Wemm 				continue;
78558162a73SPeter Wemm 			}
78606f25ae9SGregory Neil Shapiro 
787193538b7SGregory Neil Shapiro 			db_val.data = p;
788193538b7SGregory Neil Shapiro 			db_val.size = strlen(p);
78958162a73SPeter Wemm 			if (inclnull)
790193538b7SGregory Neil Shapiro 				db_val.size++;
79158162a73SPeter Wemm 
79258162a73SPeter Wemm 			/*
79358162a73SPeter Wemm 			**  Do the database insert.
79458162a73SPeter Wemm 			*/
79558162a73SPeter Wemm 
796850ef5aeSGregory Neil Shapiro 			db_put(database, db_key, db_val, putflags, mapname,
797850ef5aeSGregory Neil Shapiro 				lineno, progname);
798850ef5aeSGregory Neil Shapiro 		}
799850ef5aeSGregory Neil Shapiro #if _FFR_MM_ALIASES
800850ef5aeSGregory Neil Shapiro 		if (aliases)
80158162a73SPeter Wemm 		{
802850ef5aeSGregory Neil Shapiro 			char magic[2] = "@";
80358162a73SPeter Wemm 
804850ef5aeSGregory Neil Shapiro 			db_key.data = magic;
805850ef5aeSGregory Neil Shapiro 			db_val.data = magic;
806850ef5aeSGregory Neil Shapiro 			db_key.size = 1;
807850ef5aeSGregory Neil Shapiro 			db_val.size = 1;
808850ef5aeSGregory Neil Shapiro 			db_put(database, db_key, db_val, putflags, mapname, -1,
809850ef5aeSGregory Neil Shapiro 				progname);
810c2aa98e2SPeter Wemm 		}
811850ef5aeSGregory Neil Shapiro #endif /* _FFR_MM_ALIASES */
81258162a73SPeter Wemm 	}
81358162a73SPeter Wemm 
81428fbd282SGregory Neil Shapiro #if _FFR_TESTS
81528fbd282SGregory Neil Shapiro 	if (slp > 0)
81628fbd282SGregory Neil Shapiro 		sleep(slp);
81728fbd282SGregory Neil Shapiro #endif
81828fbd282SGregory Neil Shapiro 
81958162a73SPeter Wemm 	/*
82058162a73SPeter Wemm 	**  Now close the database.
82158162a73SPeter Wemm 	*/
82258162a73SPeter Wemm 
82306f25ae9SGregory Neil Shapiro 	errno = database->smdb_close(database);
82406f25ae9SGregory Neil Shapiro 	if (errno != SMDBE_OK)
82558162a73SPeter Wemm 	{
82640266059SGregory Neil Shapiro 		(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
82740266059SGregory Neil Shapiro 				     "%s: close(%s): %s\n",
82840266059SGregory Neil Shapiro 				     progname, mapname, sm_errstring(errno));
82958162a73SPeter Wemm 		exitstat = EX_IOERR;
83058162a73SPeter Wemm 	}
83106f25ae9SGregory Neil Shapiro 	smdb_free_database(database);
83258162a73SPeter Wemm 
83358162a73SPeter Wemm 	exit(exitstat);
83440266059SGregory Neil Shapiro 
83506f25ae9SGregory Neil Shapiro 	/* NOTREACHED */
83606f25ae9SGregory Neil Shapiro 	return exitstat;
83758162a73SPeter Wemm }
838