xref: /titanic_52/usr/src/cmd/sendmail/aux/makemap.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1998-2002, 2004 Sendmail, Inc. and its suppliers.
3*7c478bd9Sstevel@tonic-gate  *	All rights reserved.
4*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1992 Eric P. Allman.  All rights reserved.
5*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1992, 1993
6*7c478bd9Sstevel@tonic-gate  *	The Regents of the University of California.  All rights reserved.
7*7c478bd9Sstevel@tonic-gate  *
8*7c478bd9Sstevel@tonic-gate  * By using this file, you agree to the terms and conditions set
9*7c478bd9Sstevel@tonic-gate  * forth in the LICENSE file which can be found at the top level of
10*7c478bd9Sstevel@tonic-gate  * the sendmail distribution.
11*7c478bd9Sstevel@tonic-gate  *
12*7c478bd9Sstevel@tonic-gate  */
13*7c478bd9Sstevel@tonic-gate 
14*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
15*7c478bd9Sstevel@tonic-gate 
16*7c478bd9Sstevel@tonic-gate #include <sm/gen.h>
17*7c478bd9Sstevel@tonic-gate 
18*7c478bd9Sstevel@tonic-gate SM_IDSTR(copyright,
19*7c478bd9Sstevel@tonic-gate "@(#) Copyright (c) 1998-2002, 2004 Sendmail, Inc. and its suppliers.\n\
20*7c478bd9Sstevel@tonic-gate 	All rights reserved.\n\
21*7c478bd9Sstevel@tonic-gate      Copyright (c) 1992 Eric P. Allman.  All rights reserved.\n\
22*7c478bd9Sstevel@tonic-gate      Copyright (c) 1992, 1993\n\
23*7c478bd9Sstevel@tonic-gate 	The Regents of the University of California.  All rights reserved.\n")
24*7c478bd9Sstevel@tonic-gate 
25*7c478bd9Sstevel@tonic-gate SM_IDSTR(id, "@(#)$Id: makemap.c,v 8.177 2004/08/03 23:57:24 ca Exp $")
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate 
28*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
29*7c478bd9Sstevel@tonic-gate #ifndef ISC_UNIX
30*7c478bd9Sstevel@tonic-gate # include <sys/file.h>
31*7c478bd9Sstevel@tonic-gate #endif /* ! ISC_UNIX */
32*7c478bd9Sstevel@tonic-gate #include <ctype.h>
33*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
34*7c478bd9Sstevel@tonic-gate #include <unistd.h>
35*7c478bd9Sstevel@tonic-gate #ifdef EX_OK
36*7c478bd9Sstevel@tonic-gate # undef EX_OK		/* unistd.h may have another use for this */
37*7c478bd9Sstevel@tonic-gate #endif /* EX_OK */
38*7c478bd9Sstevel@tonic-gate #include <sysexits.h>
39*7c478bd9Sstevel@tonic-gate #include <sendmail/sendmail.h>
40*7c478bd9Sstevel@tonic-gate #include <sendmail/pathnames.h>
41*7c478bd9Sstevel@tonic-gate #include <libsmdb/smdb.h>
42*7c478bd9Sstevel@tonic-gate 
43*7c478bd9Sstevel@tonic-gate uid_t	RealUid;
44*7c478bd9Sstevel@tonic-gate gid_t	RealGid;
45*7c478bd9Sstevel@tonic-gate char	*RealUserName;
46*7c478bd9Sstevel@tonic-gate uid_t	RunAsUid;
47*7c478bd9Sstevel@tonic-gate uid_t	RunAsGid;
48*7c478bd9Sstevel@tonic-gate char	*RunAsUserName;
49*7c478bd9Sstevel@tonic-gate int	Verbose = 2;
50*7c478bd9Sstevel@tonic-gate bool	DontInitGroups = false;
51*7c478bd9Sstevel@tonic-gate uid_t	TrustedUid = 0;
52*7c478bd9Sstevel@tonic-gate BITMAP256 DontBlameSendmail;
53*7c478bd9Sstevel@tonic-gate 
54*7c478bd9Sstevel@tonic-gate #define BUFSIZE		1024
55*7c478bd9Sstevel@tonic-gate #define ISSEP(c) (sep == '\0' ? isascii(c) && isspace(c) : (c) == sep)
56*7c478bd9Sstevel@tonic-gate 
57*7c478bd9Sstevel@tonic-gate static void usage __P((char *));
58*7c478bd9Sstevel@tonic-gate 
59*7c478bd9Sstevel@tonic-gate static void
60*7c478bd9Sstevel@tonic-gate usage(progname)
61*7c478bd9Sstevel@tonic-gate 	char *progname;
62*7c478bd9Sstevel@tonic-gate {
63*7c478bd9Sstevel@tonic-gate 	sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
64*7c478bd9Sstevel@tonic-gate 		      "Usage: %s [-C cffile] [-N] [-c cachesize] [-D commentchar]\n",
65*7c478bd9Sstevel@tonic-gate 		      progname);
66*7c478bd9Sstevel@tonic-gate 	sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
67*7c478bd9Sstevel@tonic-gate 		      "       %*s [-d] [-e] [-f] [-l] [-o] [-r] [-s] [-t delimiter]\n",
68*7c478bd9Sstevel@tonic-gate 		      (int) strlen(progname), "");
69*7c478bd9Sstevel@tonic-gate 	sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
70*7c478bd9Sstevel@tonic-gate 		      "       %*s [-u] [-v] type mapname\n",
71*7c478bd9Sstevel@tonic-gate 		      (int) strlen(progname), "");
72*7c478bd9Sstevel@tonic-gate 	exit(EX_USAGE);
73*7c478bd9Sstevel@tonic-gate }
74*7c478bd9Sstevel@tonic-gate 
75*7c478bd9Sstevel@tonic-gate int
76*7c478bd9Sstevel@tonic-gate main(argc, argv)
77*7c478bd9Sstevel@tonic-gate 	int argc;
78*7c478bd9Sstevel@tonic-gate 	char **argv;
79*7c478bd9Sstevel@tonic-gate {
80*7c478bd9Sstevel@tonic-gate 	char *progname;
81*7c478bd9Sstevel@tonic-gate 	char *cfile;
82*7c478bd9Sstevel@tonic-gate 	bool inclnull = false;
83*7c478bd9Sstevel@tonic-gate 	bool notrunc = false;
84*7c478bd9Sstevel@tonic-gate 	bool allowreplace = false;
85*7c478bd9Sstevel@tonic-gate 	bool allowempty = false;
86*7c478bd9Sstevel@tonic-gate 	bool verbose = false;
87*7c478bd9Sstevel@tonic-gate 	bool foldcase = true;
88*7c478bd9Sstevel@tonic-gate 	bool unmake = false;
89*7c478bd9Sstevel@tonic-gate 	char sep = '\0';
90*7c478bd9Sstevel@tonic-gate 	char comment = '#';
91*7c478bd9Sstevel@tonic-gate 	int exitstat;
92*7c478bd9Sstevel@tonic-gate 	int opt;
93*7c478bd9Sstevel@tonic-gate 	char *typename = NULL;
94*7c478bd9Sstevel@tonic-gate 	char *mapname = NULL;
95*7c478bd9Sstevel@tonic-gate 	unsigned int lineno;
96*7c478bd9Sstevel@tonic-gate 	int st;
97*7c478bd9Sstevel@tonic-gate 	int mode;
98*7c478bd9Sstevel@tonic-gate 	int smode;
99*7c478bd9Sstevel@tonic-gate 	int putflags = 0;
100*7c478bd9Sstevel@tonic-gate 	long sff = SFF_ROOTOK|SFF_REGONLY;
101*7c478bd9Sstevel@tonic-gate 	struct passwd *pw;
102*7c478bd9Sstevel@tonic-gate 	SMDB_DATABASE *database;
103*7c478bd9Sstevel@tonic-gate 	SMDB_CURSOR *cursor;
104*7c478bd9Sstevel@tonic-gate 	SMDB_DBENT db_key, db_val;
105*7c478bd9Sstevel@tonic-gate 	SMDB_DBPARAMS params;
106*7c478bd9Sstevel@tonic-gate 	SMDB_USER_INFO user_info;
107*7c478bd9Sstevel@tonic-gate 	char ibuf[BUFSIZE];
108*7c478bd9Sstevel@tonic-gate #if HASFCHOWN
109*7c478bd9Sstevel@tonic-gate 	SM_FILE_T *cfp;
110*7c478bd9Sstevel@tonic-gate 	char buf[MAXLINE];
111*7c478bd9Sstevel@tonic-gate #endif /* HASFCHOWN */
112*7c478bd9Sstevel@tonic-gate 	static char rnamebuf[MAXNAME];	/* holds RealUserName */
113*7c478bd9Sstevel@tonic-gate 	extern char *optarg;
114*7c478bd9Sstevel@tonic-gate 	extern int optind;
115*7c478bd9Sstevel@tonic-gate 
116*7c478bd9Sstevel@tonic-gate 	memset(&params, '\0', sizeof params);
117*7c478bd9Sstevel@tonic-gate 	params.smdbp_cache_size = 1024 * 1024;
118*7c478bd9Sstevel@tonic-gate 
119*7c478bd9Sstevel@tonic-gate 	progname = strrchr(argv[0], '/');
120*7c478bd9Sstevel@tonic-gate 	if (progname != NULL)
121*7c478bd9Sstevel@tonic-gate 		progname++;
122*7c478bd9Sstevel@tonic-gate 	else
123*7c478bd9Sstevel@tonic-gate 		progname = argv[0];
124*7c478bd9Sstevel@tonic-gate 	cfile = getcfname(0, 0, SM_GET_SENDMAIL_CF, NULL);
125*7c478bd9Sstevel@tonic-gate 
126*7c478bd9Sstevel@tonic-gate 	clrbitmap(DontBlameSendmail);
127*7c478bd9Sstevel@tonic-gate 	RunAsUid = RealUid = getuid();
128*7c478bd9Sstevel@tonic-gate 	RunAsGid = RealGid = getgid();
129*7c478bd9Sstevel@tonic-gate 	pw = getpwuid(RealUid);
130*7c478bd9Sstevel@tonic-gate 	if (pw != NULL)
131*7c478bd9Sstevel@tonic-gate 		(void) sm_strlcpy(rnamebuf, pw->pw_name, sizeof rnamebuf);
132*7c478bd9Sstevel@tonic-gate 	else
133*7c478bd9Sstevel@tonic-gate 		(void) sm_snprintf(rnamebuf, sizeof rnamebuf,
134*7c478bd9Sstevel@tonic-gate 		    "Unknown UID %d", (int) RealUid);
135*7c478bd9Sstevel@tonic-gate 	RunAsUserName = RealUserName = rnamebuf;
136*7c478bd9Sstevel@tonic-gate 	user_info.smdbu_id = RunAsUid;
137*7c478bd9Sstevel@tonic-gate 	user_info.smdbu_group_id = RunAsGid;
138*7c478bd9Sstevel@tonic-gate 	(void) sm_strlcpy(user_info.smdbu_name, RunAsUserName,
139*7c478bd9Sstevel@tonic-gate 		       SMDB_MAX_USER_NAME_LEN);
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate #define OPTIONS		"C:D:Nc:deflorst:uv"
142*7c478bd9Sstevel@tonic-gate 	while ((opt = getopt(argc, argv, OPTIONS)) != -1)
143*7c478bd9Sstevel@tonic-gate 	{
144*7c478bd9Sstevel@tonic-gate 		switch (opt)
145*7c478bd9Sstevel@tonic-gate 		{
146*7c478bd9Sstevel@tonic-gate 		  case 'C':
147*7c478bd9Sstevel@tonic-gate 			cfile = optarg;
148*7c478bd9Sstevel@tonic-gate 			break;
149*7c478bd9Sstevel@tonic-gate 
150*7c478bd9Sstevel@tonic-gate 		  case 'N':
151*7c478bd9Sstevel@tonic-gate 			inclnull = true;
152*7c478bd9Sstevel@tonic-gate 			break;
153*7c478bd9Sstevel@tonic-gate 
154*7c478bd9Sstevel@tonic-gate 		  case 'c':
155*7c478bd9Sstevel@tonic-gate 			params.smdbp_cache_size = atol(optarg);
156*7c478bd9Sstevel@tonic-gate 			break;
157*7c478bd9Sstevel@tonic-gate 
158*7c478bd9Sstevel@tonic-gate 		  case 'd':
159*7c478bd9Sstevel@tonic-gate 			params.smdbp_allow_dup = true;
160*7c478bd9Sstevel@tonic-gate 			break;
161*7c478bd9Sstevel@tonic-gate 
162*7c478bd9Sstevel@tonic-gate 		  case 'e':
163*7c478bd9Sstevel@tonic-gate 			allowempty = true;
164*7c478bd9Sstevel@tonic-gate 			break;
165*7c478bd9Sstevel@tonic-gate 
166*7c478bd9Sstevel@tonic-gate 		  case 'f':
167*7c478bd9Sstevel@tonic-gate 			foldcase = false;
168*7c478bd9Sstevel@tonic-gate 			break;
169*7c478bd9Sstevel@tonic-gate 
170*7c478bd9Sstevel@tonic-gate 		  case 'D':
171*7c478bd9Sstevel@tonic-gate 			comment = *optarg;
172*7c478bd9Sstevel@tonic-gate 			break;
173*7c478bd9Sstevel@tonic-gate 
174*7c478bd9Sstevel@tonic-gate 		  case 'l':
175*7c478bd9Sstevel@tonic-gate 			smdb_print_available_types();
176*7c478bd9Sstevel@tonic-gate 			exit(EX_OK);
177*7c478bd9Sstevel@tonic-gate 			break;
178*7c478bd9Sstevel@tonic-gate 
179*7c478bd9Sstevel@tonic-gate 		  case 'o':
180*7c478bd9Sstevel@tonic-gate 			notrunc = true;
181*7c478bd9Sstevel@tonic-gate 			break;
182*7c478bd9Sstevel@tonic-gate 
183*7c478bd9Sstevel@tonic-gate 		  case 'r':
184*7c478bd9Sstevel@tonic-gate 			allowreplace = true;
185*7c478bd9Sstevel@tonic-gate 			break;
186*7c478bd9Sstevel@tonic-gate 
187*7c478bd9Sstevel@tonic-gate 		  case 's':
188*7c478bd9Sstevel@tonic-gate 			setbitn(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail);
189*7c478bd9Sstevel@tonic-gate 			setbitn(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail);
190*7c478bd9Sstevel@tonic-gate 			setbitn(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail);
191*7c478bd9Sstevel@tonic-gate 			setbitn(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail);
192*7c478bd9Sstevel@tonic-gate 			break;
193*7c478bd9Sstevel@tonic-gate 
194*7c478bd9Sstevel@tonic-gate 		  case 't':
195*7c478bd9Sstevel@tonic-gate 			if (optarg == NULL || *optarg == '\0')
196*7c478bd9Sstevel@tonic-gate 			{
197*7c478bd9Sstevel@tonic-gate 				sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
198*7c478bd9Sstevel@tonic-gate 					      "Invalid separator\n");
199*7c478bd9Sstevel@tonic-gate 				break;
200*7c478bd9Sstevel@tonic-gate 			}
201*7c478bd9Sstevel@tonic-gate 			sep = *optarg;
202*7c478bd9Sstevel@tonic-gate 			break;
203*7c478bd9Sstevel@tonic-gate 
204*7c478bd9Sstevel@tonic-gate 		  case 'u':
205*7c478bd9Sstevel@tonic-gate 			unmake = true;
206*7c478bd9Sstevel@tonic-gate 			break;
207*7c478bd9Sstevel@tonic-gate 
208*7c478bd9Sstevel@tonic-gate 		  case 'v':
209*7c478bd9Sstevel@tonic-gate 			verbose = true;
210*7c478bd9Sstevel@tonic-gate 			break;
211*7c478bd9Sstevel@tonic-gate 
212*7c478bd9Sstevel@tonic-gate 		  default:
213*7c478bd9Sstevel@tonic-gate 			usage(progname);
214*7c478bd9Sstevel@tonic-gate 			/* NOTREACHED */
215*7c478bd9Sstevel@tonic-gate 		}
216*7c478bd9Sstevel@tonic-gate 	}
217*7c478bd9Sstevel@tonic-gate 
218*7c478bd9Sstevel@tonic-gate 	if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail))
219*7c478bd9Sstevel@tonic-gate 		sff |= SFF_NOSLINK;
220*7c478bd9Sstevel@tonic-gate 	if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail))
221*7c478bd9Sstevel@tonic-gate 		sff |= SFF_NOHLINK;
222*7c478bd9Sstevel@tonic-gate 	if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail))
223*7c478bd9Sstevel@tonic-gate 		sff |= SFF_NOWLINK;
224*7c478bd9Sstevel@tonic-gate 
225*7c478bd9Sstevel@tonic-gate 	argc -= optind;
226*7c478bd9Sstevel@tonic-gate 	argv += optind;
227*7c478bd9Sstevel@tonic-gate 	if (argc != 2)
228*7c478bd9Sstevel@tonic-gate 	{
229*7c478bd9Sstevel@tonic-gate 		usage(progname);
230*7c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
231*7c478bd9Sstevel@tonic-gate 	}
232*7c478bd9Sstevel@tonic-gate 	else
233*7c478bd9Sstevel@tonic-gate 	{
234*7c478bd9Sstevel@tonic-gate 		typename = argv[0];
235*7c478bd9Sstevel@tonic-gate 		mapname = argv[1];
236*7c478bd9Sstevel@tonic-gate 	}
237*7c478bd9Sstevel@tonic-gate 
238*7c478bd9Sstevel@tonic-gate #if HASFCHOWN
239*7c478bd9Sstevel@tonic-gate 	/* Find TrustedUser value in sendmail.cf */
240*7c478bd9Sstevel@tonic-gate 	if ((cfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, cfile, SM_IO_RDONLY,
241*7c478bd9Sstevel@tonic-gate 			      NULL)) == NULL)
242*7c478bd9Sstevel@tonic-gate 	{
243*7c478bd9Sstevel@tonic-gate 		sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "makemap: %s: %s",
244*7c478bd9Sstevel@tonic-gate 			      cfile, sm_errstring(errno));
245*7c478bd9Sstevel@tonic-gate 		exit(EX_NOINPUT);
246*7c478bd9Sstevel@tonic-gate 	}
247*7c478bd9Sstevel@tonic-gate 	while (sm_io_fgets(cfp, SM_TIME_DEFAULT, buf, sizeof(buf)) != NULL)
248*7c478bd9Sstevel@tonic-gate 	{
249*7c478bd9Sstevel@tonic-gate 		register char *b;
250*7c478bd9Sstevel@tonic-gate 
251*7c478bd9Sstevel@tonic-gate 		if ((b = strchr(buf, '\n')) != NULL)
252*7c478bd9Sstevel@tonic-gate 			*b = '\0';
253*7c478bd9Sstevel@tonic-gate 
254*7c478bd9Sstevel@tonic-gate 		b = buf;
255*7c478bd9Sstevel@tonic-gate 		switch (*b++)
256*7c478bd9Sstevel@tonic-gate 		{
257*7c478bd9Sstevel@tonic-gate 		  case 'O':		/* option */
258*7c478bd9Sstevel@tonic-gate 			if (strncasecmp(b, " TrustedUser", 12) == 0 &&
259*7c478bd9Sstevel@tonic-gate 			    !(isascii(b[12]) && isalnum(b[12])))
260*7c478bd9Sstevel@tonic-gate 			{
261*7c478bd9Sstevel@tonic-gate 				b = strchr(b, '=');
262*7c478bd9Sstevel@tonic-gate 				if (b == NULL)
263*7c478bd9Sstevel@tonic-gate 					continue;
264*7c478bd9Sstevel@tonic-gate 				while (isascii(*++b) && isspace(*b))
265*7c478bd9Sstevel@tonic-gate 					continue;
266*7c478bd9Sstevel@tonic-gate 				if (isascii(*b) && isdigit(*b))
267*7c478bd9Sstevel@tonic-gate 					TrustedUid = atoi(b);
268*7c478bd9Sstevel@tonic-gate 				else
269*7c478bd9Sstevel@tonic-gate 				{
270*7c478bd9Sstevel@tonic-gate 					TrustedUid = 0;
271*7c478bd9Sstevel@tonic-gate 					pw = getpwnam(b);
272*7c478bd9Sstevel@tonic-gate 					if (pw == NULL)
273*7c478bd9Sstevel@tonic-gate 						(void) sm_io_fprintf(smioerr,
274*7c478bd9Sstevel@tonic-gate 								     SM_TIME_DEFAULT,
275*7c478bd9Sstevel@tonic-gate 								     "TrustedUser: unknown user %s\n", b);
276*7c478bd9Sstevel@tonic-gate 					else
277*7c478bd9Sstevel@tonic-gate 						TrustedUid = pw->pw_uid;
278*7c478bd9Sstevel@tonic-gate 				}
279*7c478bd9Sstevel@tonic-gate 
280*7c478bd9Sstevel@tonic-gate # ifdef UID_MAX
281*7c478bd9Sstevel@tonic-gate 				if (TrustedUid > UID_MAX)
282*7c478bd9Sstevel@tonic-gate 				{
283*7c478bd9Sstevel@tonic-gate 					(void) sm_io_fprintf(smioerr,
284*7c478bd9Sstevel@tonic-gate 							     SM_TIME_DEFAULT,
285*7c478bd9Sstevel@tonic-gate 							     "TrustedUser: uid value (%ld) > UID_MAX (%ld)",
286*7c478bd9Sstevel@tonic-gate 						(long) TrustedUid,
287*7c478bd9Sstevel@tonic-gate 						(long) UID_MAX);
288*7c478bd9Sstevel@tonic-gate 					TrustedUid = 0;
289*7c478bd9Sstevel@tonic-gate 				}
290*7c478bd9Sstevel@tonic-gate # endif /* UID_MAX */
291*7c478bd9Sstevel@tonic-gate 				break;
292*7c478bd9Sstevel@tonic-gate 			}
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate 
295*7c478bd9Sstevel@tonic-gate 		  default:
296*7c478bd9Sstevel@tonic-gate 			continue;
297*7c478bd9Sstevel@tonic-gate 		}
298*7c478bd9Sstevel@tonic-gate 	}
299*7c478bd9Sstevel@tonic-gate 	(void) sm_io_close(cfp, SM_TIME_DEFAULT);
300*7c478bd9Sstevel@tonic-gate #endif /* HASFCHOWN */
301*7c478bd9Sstevel@tonic-gate 
302*7c478bd9Sstevel@tonic-gate 	if (!params.smdbp_allow_dup && !allowreplace)
303*7c478bd9Sstevel@tonic-gate 		putflags = SMDBF_NO_OVERWRITE;
304*7c478bd9Sstevel@tonic-gate 
305*7c478bd9Sstevel@tonic-gate 	if (unmake)
306*7c478bd9Sstevel@tonic-gate 	{
307*7c478bd9Sstevel@tonic-gate 		mode = O_RDONLY;
308*7c478bd9Sstevel@tonic-gate 		smode = S_IRUSR;
309*7c478bd9Sstevel@tonic-gate 	}
310*7c478bd9Sstevel@tonic-gate 	else
311*7c478bd9Sstevel@tonic-gate 	{
312*7c478bd9Sstevel@tonic-gate 		mode = O_RDWR;
313*7c478bd9Sstevel@tonic-gate 		if (!notrunc)
314*7c478bd9Sstevel@tonic-gate 		{
315*7c478bd9Sstevel@tonic-gate 			mode |= O_CREAT|O_TRUNC;
316*7c478bd9Sstevel@tonic-gate 			sff |= SFF_CREAT;
317*7c478bd9Sstevel@tonic-gate 		}
318*7c478bd9Sstevel@tonic-gate 		smode = S_IWUSR;
319*7c478bd9Sstevel@tonic-gate 	}
320*7c478bd9Sstevel@tonic-gate 
321*7c478bd9Sstevel@tonic-gate 	params.smdbp_num_elements = 4096;
322*7c478bd9Sstevel@tonic-gate 
323*7c478bd9Sstevel@tonic-gate 	errno = smdb_open_database(&database, mapname, mode, smode, sff,
324*7c478bd9Sstevel@tonic-gate 				   typename, &user_info, &params);
325*7c478bd9Sstevel@tonic-gate 	if (errno != SMDBE_OK)
326*7c478bd9Sstevel@tonic-gate 	{
327*7c478bd9Sstevel@tonic-gate 		char *hint;
328*7c478bd9Sstevel@tonic-gate 
329*7c478bd9Sstevel@tonic-gate 		if (errno == SMDBE_UNSUPPORTED_DB_TYPE &&
330*7c478bd9Sstevel@tonic-gate 		    (hint = smdb_db_definition(typename)) != NULL)
331*7c478bd9Sstevel@tonic-gate 			(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
332*7c478bd9Sstevel@tonic-gate 					     "%s: Need to recompile with -D%s for %s support\n",
333*7c478bd9Sstevel@tonic-gate 					     progname, hint, typename);
334*7c478bd9Sstevel@tonic-gate 		else
335*7c478bd9Sstevel@tonic-gate 			(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
336*7c478bd9Sstevel@tonic-gate 					     "%s: error opening type %s map %s: %s\n",
337*7c478bd9Sstevel@tonic-gate 					     progname, typename, mapname,
338*7c478bd9Sstevel@tonic-gate 					     sm_errstring(errno));
339*7c478bd9Sstevel@tonic-gate 		exit(EX_CANTCREAT);
340*7c478bd9Sstevel@tonic-gate 	}
341*7c478bd9Sstevel@tonic-gate 
342*7c478bd9Sstevel@tonic-gate 	(void) database->smdb_sync(database, 0);
343*7c478bd9Sstevel@tonic-gate 
344*7c478bd9Sstevel@tonic-gate 	if (!unmake && geteuid() == 0 && TrustedUid != 0)
345*7c478bd9Sstevel@tonic-gate 	{
346*7c478bd9Sstevel@tonic-gate 		errno = database->smdb_set_owner(database, TrustedUid, -1);
347*7c478bd9Sstevel@tonic-gate 		if (errno != SMDBE_OK)
348*7c478bd9Sstevel@tonic-gate 		{
349*7c478bd9Sstevel@tonic-gate 			(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
350*7c478bd9Sstevel@tonic-gate 					     "WARNING: ownership change on %s failed %s",
351*7c478bd9Sstevel@tonic-gate 					     mapname, sm_errstring(errno));
352*7c478bd9Sstevel@tonic-gate 		}
353*7c478bd9Sstevel@tonic-gate 	}
354*7c478bd9Sstevel@tonic-gate 
355*7c478bd9Sstevel@tonic-gate 	/*
356*7c478bd9Sstevel@tonic-gate 	**  Copy the data
357*7c478bd9Sstevel@tonic-gate 	*/
358*7c478bd9Sstevel@tonic-gate 
359*7c478bd9Sstevel@tonic-gate 	exitstat = EX_OK;
360*7c478bd9Sstevel@tonic-gate 	if (unmake)
361*7c478bd9Sstevel@tonic-gate 	{
362*7c478bd9Sstevel@tonic-gate 		errno = database->smdb_cursor(database, &cursor, 0);
363*7c478bd9Sstevel@tonic-gate 		if (errno != SMDBE_OK)
364*7c478bd9Sstevel@tonic-gate 		{
365*7c478bd9Sstevel@tonic-gate 
366*7c478bd9Sstevel@tonic-gate 			(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
367*7c478bd9Sstevel@tonic-gate 					     "%s: cannot make cursor for type %s map %s\n",
368*7c478bd9Sstevel@tonic-gate 					     progname, typename, mapname);
369*7c478bd9Sstevel@tonic-gate 			exit(EX_SOFTWARE);
370*7c478bd9Sstevel@tonic-gate 		}
371*7c478bd9Sstevel@tonic-gate 
372*7c478bd9Sstevel@tonic-gate 		memset(&db_key, '\0', sizeof db_key);
373*7c478bd9Sstevel@tonic-gate 		memset(&db_val, '\0', sizeof db_val);
374*7c478bd9Sstevel@tonic-gate 
375*7c478bd9Sstevel@tonic-gate 		for (lineno = 0; ; lineno++)
376*7c478bd9Sstevel@tonic-gate 		{
377*7c478bd9Sstevel@tonic-gate 			errno = cursor->smdbc_get(cursor, &db_key, &db_val,
378*7c478bd9Sstevel@tonic-gate 						  SMDB_CURSOR_GET_NEXT);
379*7c478bd9Sstevel@tonic-gate 			if (errno != SMDBE_OK)
380*7c478bd9Sstevel@tonic-gate 				break;
381*7c478bd9Sstevel@tonic-gate 
382*7c478bd9Sstevel@tonic-gate 			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
383*7c478bd9Sstevel@tonic-gate 					     "%.*s\t%.*s\n",
384*7c478bd9Sstevel@tonic-gate 					     (int) db_key.size,
385*7c478bd9Sstevel@tonic-gate 					     (char *) db_key.data,
386*7c478bd9Sstevel@tonic-gate 					     (int) db_val.size,
387*7c478bd9Sstevel@tonic-gate 					     (char *)db_val.data);
388*7c478bd9Sstevel@tonic-gate 
389*7c478bd9Sstevel@tonic-gate 		}
390*7c478bd9Sstevel@tonic-gate 		(void) cursor->smdbc_close(cursor);
391*7c478bd9Sstevel@tonic-gate 	}
392*7c478bd9Sstevel@tonic-gate 	else
393*7c478bd9Sstevel@tonic-gate 	{
394*7c478bd9Sstevel@tonic-gate 		lineno = 0;
395*7c478bd9Sstevel@tonic-gate 		while (sm_io_fgets(smioin, SM_TIME_DEFAULT, ibuf, sizeof ibuf)
396*7c478bd9Sstevel@tonic-gate 		       != NULL)
397*7c478bd9Sstevel@tonic-gate 		{
398*7c478bd9Sstevel@tonic-gate 			register char *p;
399*7c478bd9Sstevel@tonic-gate 
400*7c478bd9Sstevel@tonic-gate 			lineno++;
401*7c478bd9Sstevel@tonic-gate 
402*7c478bd9Sstevel@tonic-gate 			/*
403*7c478bd9Sstevel@tonic-gate 			**  Parse the line.
404*7c478bd9Sstevel@tonic-gate 			*/
405*7c478bd9Sstevel@tonic-gate 
406*7c478bd9Sstevel@tonic-gate 			p = strchr(ibuf, '\n');
407*7c478bd9Sstevel@tonic-gate 			if (p != NULL)
408*7c478bd9Sstevel@tonic-gate 				*p = '\0';
409*7c478bd9Sstevel@tonic-gate 			else if (!sm_io_eof(smioin))
410*7c478bd9Sstevel@tonic-gate 			{
411*7c478bd9Sstevel@tonic-gate 				(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
412*7c478bd9Sstevel@tonic-gate 						     "%s: %s: line %u: line too long (%ld bytes max)\n",
413*7c478bd9Sstevel@tonic-gate 						     progname, mapname, lineno,
414*7c478bd9Sstevel@tonic-gate 						     (long) sizeof ibuf);
415*7c478bd9Sstevel@tonic-gate 				exitstat = EX_DATAERR;
416*7c478bd9Sstevel@tonic-gate 				continue;
417*7c478bd9Sstevel@tonic-gate 			}
418*7c478bd9Sstevel@tonic-gate 
419*7c478bd9Sstevel@tonic-gate 			if (ibuf[0] == '\0' || ibuf[0] == comment)
420*7c478bd9Sstevel@tonic-gate 				continue;
421*7c478bd9Sstevel@tonic-gate 			if (sep == '\0' && isascii(ibuf[0]) && isspace(ibuf[0]))
422*7c478bd9Sstevel@tonic-gate 			{
423*7c478bd9Sstevel@tonic-gate 				(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
424*7c478bd9Sstevel@tonic-gate 						     "%s: %s: line %u: syntax error (leading space)\n",
425*7c478bd9Sstevel@tonic-gate 						     progname, mapname, lineno);
426*7c478bd9Sstevel@tonic-gate 				exitstat = EX_DATAERR;
427*7c478bd9Sstevel@tonic-gate 				continue;
428*7c478bd9Sstevel@tonic-gate 			}
429*7c478bd9Sstevel@tonic-gate 
430*7c478bd9Sstevel@tonic-gate 			memset(&db_key, '\0', sizeof db_key);
431*7c478bd9Sstevel@tonic-gate 			memset(&db_val, '\0', sizeof db_val);
432*7c478bd9Sstevel@tonic-gate 			db_key.data = ibuf;
433*7c478bd9Sstevel@tonic-gate 
434*7c478bd9Sstevel@tonic-gate 			for (p = ibuf; *p != '\0' && !(ISSEP(*p)); p++)
435*7c478bd9Sstevel@tonic-gate 			{
436*7c478bd9Sstevel@tonic-gate 				if (foldcase && isascii(*p) && isupper(*p))
437*7c478bd9Sstevel@tonic-gate 					*p = tolower(*p);
438*7c478bd9Sstevel@tonic-gate 			}
439*7c478bd9Sstevel@tonic-gate 			db_key.size = p - ibuf;
440*7c478bd9Sstevel@tonic-gate 			if (inclnull)
441*7c478bd9Sstevel@tonic-gate 				db_key.size++;
442*7c478bd9Sstevel@tonic-gate 
443*7c478bd9Sstevel@tonic-gate 			if (*p != '\0')
444*7c478bd9Sstevel@tonic-gate 				*p++ = '\0';
445*7c478bd9Sstevel@tonic-gate 			while (*p != '\0' && ISSEP(*p))
446*7c478bd9Sstevel@tonic-gate 				p++;
447*7c478bd9Sstevel@tonic-gate 			if (!allowempty && *p == '\0')
448*7c478bd9Sstevel@tonic-gate 			{
449*7c478bd9Sstevel@tonic-gate 				(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
450*7c478bd9Sstevel@tonic-gate 						     "%s: %s: line %u: no RHS for LHS %s\n",
451*7c478bd9Sstevel@tonic-gate 						     progname, mapname, lineno,
452*7c478bd9Sstevel@tonic-gate 						     (char *) db_key.data);
453*7c478bd9Sstevel@tonic-gate 				exitstat = EX_DATAERR;
454*7c478bd9Sstevel@tonic-gate 				continue;
455*7c478bd9Sstevel@tonic-gate 			}
456*7c478bd9Sstevel@tonic-gate 
457*7c478bd9Sstevel@tonic-gate 			db_val.data = p;
458*7c478bd9Sstevel@tonic-gate 			db_val.size = strlen(p);
459*7c478bd9Sstevel@tonic-gate 			if (inclnull)
460*7c478bd9Sstevel@tonic-gate 				db_val.size++;
461*7c478bd9Sstevel@tonic-gate 
462*7c478bd9Sstevel@tonic-gate 			/*
463*7c478bd9Sstevel@tonic-gate 			**  Do the database insert.
464*7c478bd9Sstevel@tonic-gate 			*/
465*7c478bd9Sstevel@tonic-gate 
466*7c478bd9Sstevel@tonic-gate 			if (verbose)
467*7c478bd9Sstevel@tonic-gate 			{
468*7c478bd9Sstevel@tonic-gate 				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
469*7c478bd9Sstevel@tonic-gate 						     "key=`%s', val=`%s'\n",
470*7c478bd9Sstevel@tonic-gate 						     (char *) db_key.data,
471*7c478bd9Sstevel@tonic-gate 						     (char *) db_val.data);
472*7c478bd9Sstevel@tonic-gate 			}
473*7c478bd9Sstevel@tonic-gate 
474*7c478bd9Sstevel@tonic-gate 			errno = database->smdb_put(database, &db_key, &db_val,
475*7c478bd9Sstevel@tonic-gate 						   putflags);
476*7c478bd9Sstevel@tonic-gate 			switch (errno)
477*7c478bd9Sstevel@tonic-gate 			{
478*7c478bd9Sstevel@tonic-gate 			  case SMDBE_KEY_EXIST:
479*7c478bd9Sstevel@tonic-gate 				st = 1;
480*7c478bd9Sstevel@tonic-gate 				break;
481*7c478bd9Sstevel@tonic-gate 
482*7c478bd9Sstevel@tonic-gate 			  case 0:
483*7c478bd9Sstevel@tonic-gate 				st = 0;
484*7c478bd9Sstevel@tonic-gate 				break;
485*7c478bd9Sstevel@tonic-gate 
486*7c478bd9Sstevel@tonic-gate 			  default:
487*7c478bd9Sstevel@tonic-gate 				st = -1;
488*7c478bd9Sstevel@tonic-gate 				break;
489*7c478bd9Sstevel@tonic-gate 			}
490*7c478bd9Sstevel@tonic-gate 
491*7c478bd9Sstevel@tonic-gate 			if (st < 0)
492*7c478bd9Sstevel@tonic-gate 			{
493*7c478bd9Sstevel@tonic-gate 				(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
494*7c478bd9Sstevel@tonic-gate 						     "%s: %s: line %u: key %s: put error: %s\n",
495*7c478bd9Sstevel@tonic-gate 						     progname, mapname, lineno,
496*7c478bd9Sstevel@tonic-gate 						     (char *) db_key.data,
497*7c478bd9Sstevel@tonic-gate 						     sm_errstring(errno));
498*7c478bd9Sstevel@tonic-gate 				exitstat = EX_IOERR;
499*7c478bd9Sstevel@tonic-gate 			}
500*7c478bd9Sstevel@tonic-gate 			else if (st > 0)
501*7c478bd9Sstevel@tonic-gate 			{
502*7c478bd9Sstevel@tonic-gate 				(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
503*7c478bd9Sstevel@tonic-gate 						     "%s: %s: line %u: key %s: duplicate key\n",
504*7c478bd9Sstevel@tonic-gate 						     progname, mapname,
505*7c478bd9Sstevel@tonic-gate 						     lineno,
506*7c478bd9Sstevel@tonic-gate 						     (char *) db_key.data);
507*7c478bd9Sstevel@tonic-gate 				exitstat = EX_DATAERR;
508*7c478bd9Sstevel@tonic-gate 			}
509*7c478bd9Sstevel@tonic-gate 		}
510*7c478bd9Sstevel@tonic-gate 	}
511*7c478bd9Sstevel@tonic-gate 
512*7c478bd9Sstevel@tonic-gate 	/*
513*7c478bd9Sstevel@tonic-gate 	**  Now close the database.
514*7c478bd9Sstevel@tonic-gate 	*/
515*7c478bd9Sstevel@tonic-gate 
516*7c478bd9Sstevel@tonic-gate 	errno = database->smdb_close(database);
517*7c478bd9Sstevel@tonic-gate 	if (errno != SMDBE_OK)
518*7c478bd9Sstevel@tonic-gate 	{
519*7c478bd9Sstevel@tonic-gate 		(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
520*7c478bd9Sstevel@tonic-gate 				     "%s: close(%s): %s\n",
521*7c478bd9Sstevel@tonic-gate 				     progname, mapname, sm_errstring(errno));
522*7c478bd9Sstevel@tonic-gate 		exitstat = EX_IOERR;
523*7c478bd9Sstevel@tonic-gate 	}
524*7c478bd9Sstevel@tonic-gate 	smdb_free_database(database);
525*7c478bd9Sstevel@tonic-gate 
526*7c478bd9Sstevel@tonic-gate 	exit(exitstat);
527*7c478bd9Sstevel@tonic-gate 
528*7c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
529*7c478bd9Sstevel@tonic-gate 	return exitstat;
530*7c478bd9Sstevel@tonic-gate }
531