1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21: #include <argp.h>
22: #include <ctype.h>
23: #include <dlfcn.h>
24: #include <errno.h>
25: #include <error.h>
26: #include <fcntl.h>
27: #include <libintl.h>
28: #include <locale.h>
29: #include <stdio.h>
30: #include <stdint.h>
31: #include <stdlib.h>
32: #include <string.h>
33: #include <sys/stat.h>
34: #include "nss_db/dummy-db.h"
35:
36:
37: #include "../version.h"
38:
39: #define PACKAGE _libc_intl_domainname
40:
41:
42: static int to_lowercase;
43:
44:
45: static int do_undo;
46:
47:
48: static int be_quiet;
49:
50:
51: static const char *output_name;
52:
53:
54: static void print_version (FILE *stream, struct argp_state *state);
55: void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
56:
57:
58: static const struct argp_option options[] =
59: {
60: { "fold-case", 'f', NULL, 0, N_("Convert key to lower case") },
61: { "output", 'o', N_("NAME"), 0, N_("Write output to file NAME") },
62: { "quiet", 'q', NULL, 0,
63: N_("Do not print messages while building database") },
64: { "undo", 'u', NULL, 0,
65: N_("Print content of database file, one entry a line") },
66: { NULL, 0, NULL, 0, NULL }
67: };
68:
69:
70: static const char doc[] = N_("Create simple DB database from textual input.");
71:
72:
73: static const char args_doc[] = N_("\
74: INPUT-FILE OUTPUT-FILE\n-o OUTPUT-FILE INPUT-FILE\n-u INPUT-FILE");
75:
76:
77: static error_t parse_opt (int key, char *arg, struct argp_state *state);
78:
79:
80: static char *more_help (int key, const char *text, void *input);
81:
82:
83: static struct argp argp =
84: {
85: options, parse_opt, args_doc, doc, NULL, more_help
86: };
87:
88:
89:
90: static int process_input (FILE *input, const char *inname, NSS_DB *output,
91: int to_lowercase, int be_quiet);
92: static int print_database (NSS_DB *db);
93:
94:
95: int
96: main (int argc, char *argv[])
97: {
98: const char *input_name;
99: FILE *input_file;
100: NSS_DB *db_file;
101: int status;
102: int remaining;
103: int mode = 0666;
104:
105:
106: setlocale (LC_ALL, "");
107:
108:
109: textdomain (_libc_intl_domainname);
110:
111:
112: input_name = NULL;
113:
114:
115: argp_parse (&argp, argc, argv, 0, &remaining, NULL);
116:
117:
118: if (do_undo || output_name != NULL)
119: {
120: if (remaining + 1 != argc)
121: {
122: wrong_arguments:
123: error (0, 0, gettext ("wrong number of arguments"));
124: argp_help (&argp, stdout, ARGP_HELP_SEE,
125: program_invocation_short_name);
126: exit (1);
127: }
128: input_name = argv[remaining];
129: }
130: else
131: {
132: if (remaining + 2 != argc)
133: goto wrong_arguments;
134:
135: input_name = argv[remaining++];
136: output_name = argv[remaining];
137: }
138:
139:
140:
141: if (load_db () != NSS_STATUS_SUCCESS)
142: error (EXIT_FAILURE, 0, gettext ("No usable database library found."));
143:
144:
145: if (do_undo)
146: {
147: dbopen (input_name, db_rdonly, 0666, &db_file);
148: if (db_file == NULL)
149: error (EXIT_FAILURE, 0, gettext ("cannot open database file `%s': %s"),
150: input_name,
151: (errno == EINVAL ? gettext ("incorrectly formatted file")
152: : strerror (errno)));
153:
154: status = print_database (db_file);
155:
156: db_file->close (db_file->db, 0);
157:
158: return status;
159: }
160:
161:
162: if (strcmp (input_name, "-") == 0 || strcmp (input_name, "/dev/stdin") == 0)
163: input_file = stdin;
164: else
165: {
166: struct stat st;
167:
168: input_file = fopen (input_name, "r");
169: if (input_file == NULL)
170: error (EXIT_FAILURE, errno, gettext ("cannot open input file `%s'"),
171: input_name);
172:
173:
174:
175: if (fstat (fileno (input_file), &st) >= 0)
176: mode = st.st_mode & ACCESSPERMS;
177: }
178:
179:
180:
181: dbopen (output_name, DB_CREATE | db_truncate, mode, &db_file);
182: if (db_file == NULL)
183: error (EXIT_FAILURE, errno, gettext ("cannot open output file `%s'"),
184: output_name);
185:
186:
187: status = process_input (input_file, input_name, db_file, to_lowercase,
188: be_quiet);
189:
190:
191: if (input_file != stdin)
192: fclose (input_file);
193: db_file->close (db_file->db, 0);
194:
195: return status;
196: }
197:
198:
199:
200: static error_t
201: parse_opt (int key, char *arg, struct argp_state *state)
202: {
203: switch (key)
204: {
205: case 'f':
206: to_lowercase = 1;
207: break;
208: case 'o':
209: output_name = arg;
210: break;
211: case 'q':
212: be_quiet = 1;
213: break;
214: case 'u':
215: do_undo = 1;
216: break;
217: default:
218: return ARGP_ERR_UNKNOWN;
219: }
220: return 0;
221: }
222:
223:
224: static char *
225: more_help (int key, const char *text, void *input)
226: {
227: switch (key)
228: {
229: case ARGP_KEY_HELP_EXTRA:
230:
231: return strdup (gettext ("\
232: For bug reporting instructions, please see:\n\
233: <http://www.gnu.org/software/libc/bugs.html>.\n"));
234: default:
235: break;
236: }
237: return (char *) text;
238: }
239:
240:
241: static void
242: print_version (FILE *stream, struct argp_state *state)
243: {
244: fprintf (stream, "makedb (GNU %s) %s\n", PACKAGE, VERSION);
245: fprintf (stream, gettext ("\
246: Copyright (C) %s Free Software Foundation, Inc.\n\
247: This is free software; see the source for copying conditions. There is NO\n\
248: warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
249: "), "2000");
250: fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
251: }
252:
253:
254: static int
255: process_input (input, inname, output, to_lowercase, be_quiet)
256: FILE *input;
257: const char *inname;
258: NSS_DB *output;
259: int to_lowercase;
260: int be_quiet;
261: {
262: char *line;
263: size_t linelen;
264: int status;
265: size_t linenr;
266:
267: line = NULL;
268: linelen = 0;
269: status = EXIT_SUCCESS;
270: linenr = 0;
271:
272: while (!feof (input))
273: {
274: DBT key;
275: DBT val;
276: char *cp;
277: int n;
278:
279: n = getline (&line, &linelen, input);
280: if (n < 0)
281:
282: break;
283: if (n == 0)
284:
285: continue;
286:
287: ++linenr;
288:
289: if (line[n - 1] == '\n')
290:
291: line[--n] = '\0';
292:
293: cp = line;
294: while (isspace (*cp))
295: ++cp;
296:
297: if (*cp == '#')
298:
299: continue;
300:
301: key.data = cp;
302: while (*cp != '\0' && !isspace (*cp))
303: {
304: if (to_lowercase)
305: *cp = tolower (*cp);
306: ++cp;
307: }
308:
309: if (key.data == cp)
310:
311: continue;
312:
313: key.size = cp - (char *) key.data;
314: key.flags = 0;
315:
316: while (isspace (*cp))
317: ++cp;
318:
319: val.data = cp;
320: val.size = (&line[n] - cp) + 1;
321: val.flags = 0;
322:
323:
324: status = output->put (output->db, NULL, &key, &val, db_nooverwrite);
325: if (status != 0)
326: {
327: if (status == db_keyexist)
328: {
329: if (!be_quiet)
330: error_at_line (0, 0, inname, linenr,
331: gettext ("duplicate key"));
332:
333: status = 0;
334: continue;
335: }
336: else
337: error (0, status, gettext ("while writing database file"));
338:
339: status = EXIT_FAILURE;
340:
341: clearerr (input);
342: break;
343: }
344: }
345:
346: if (ferror (input))
347: {
348: error (0, 0, gettext ("problems while reading `%s'"), inname);
349: status = EXIT_FAILURE;
350: }
351:
352: return status;
353: }
354:
355:
356: static int
357: print_database (db)
358: NSS_DB *db;
359: {
360: DBT key;
361: DBT val;
362: NSS_DBC *cursor;
363: int status;
364:
365: status = db->cursor (db->db, NULL, &cursor);
366: if (status != 0)
367: {
368: error (0, status, gettext ("while reading database"));
369: return EXIT_FAILURE;
370: }
371:
372: key.flags = 0;
373: val.flags = 0;
374: status = cursor->c_get (cursor->cursor, &key, &val, db_first);
375: while (status == 0)
376: {
377: printf ("%.*s %s\n", (int) key.size, (char *) key.data,
378: (char *) val.data);
379:
380: status = cursor->c_get (cursor->cursor, &key, &val, db_next);
381: }
382:
383: if (status != db_notfound)
384: {
385: error (0, status, gettext ("while reading database"));
386: return EXIT_FAILURE;
387: }
388:
389: return EXIT_SUCCESS;
390: }