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