(linenum→info "unix/slp.c:2238")

glibc/2.7/nss/makedb.c

    1: /* Create simple DB database from textual input.
    2:    Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
    3:    This file is part of the GNU C Library.
    4:    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
    5: 
    6:    The GNU C Library is free software; you can redistribute it and/or
    7:    modify it under the terms of the GNU Lesser General Public
    8:    License as published by the Free Software Foundation; either
    9:    version 2.1 of the License, or (at your option) any later version.
   10: 
   11:    The GNU C Library is distributed in the hope that it will be useful,
   12:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   13:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   14:    Lesser General Public License for more details.
   15: 
   16:    You should have received a copy of the GNU Lesser General Public
   17:    License along with the GNU C Library; if not, write to the Free
   18:    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   19:    02111-1307 USA.  */
   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: /* Get libc version number.  */
   37: #include "../version.h"
   38: 
   39: #define PACKAGE _libc_intl_domainname
   40: 
   41: /* If non-zero convert key to lower case.  */
   42: static int to_lowercase;
   43: 
   44: /* If non-zero print content of input file, one entry per line.  */
   45: static int do_undo;
   46: 
   47: /* If non-zero do not print informational messages.  */
   48: static int be_quiet;
   49: 
   50: /* Name of output file.  */
   51: static const char *output_name;
   52: 
   53: /* Name and version of program.  */
   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: /* Definitions of arguments for argp functions.  */
   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: /* Short description of program.  */
   70: static const char doc[] = N_("Create simple DB database from textual input.");
   71: 
   72: /* Strings for arguments in help texts.  */
   73: static const char args_doc[] = N_("\
   74: INPUT-FILE OUTPUT-FILE\n-o OUTPUT-FILE INPUT-FILE\n-u INPUT-FILE");
   75: 
   76: /* Prototype for option handler.  */
   77: static error_t parse_opt (int key, char *arg, struct argp_state *state);
   78: 
   79: /* Function to print some extra text in the help message.  */
   80: static char *more_help (int key, const char *text, void *input);
   81: 
   82: /* Data structure to communicate with argp functions.  */
   83: static struct argp argp =
   84: {
   85:   options, parse_opt, args_doc, doc, NULL, more_help
   86: };
   87: 
   88: 
   89: /* Prototypes for local functions.  */
   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:   /* Set locale via LC_ALL.  */
  106:   setlocale (LC_ALL, "");
  107: 
  108:   /* Set the text message domain.  */
  109:   textdomain (_libc_intl_domainname);
  110: 
  111:   /* Initialize local variables.  */
  112:   input_name = NULL;
  113: 
  114:   /* Parse and process arguments.  */
  115:   argp_parse (&argp, argc, argv, 0, &remaining, NULL);
  116: 
  117:   /* Determine file names.  */
  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:   /* First load the shared object to initialize version dependend
  140:      variables.  */
  141:   if (load_db () != NSS_STATUS_SUCCESS)
  142:     error (EXIT_FAILURE, 0, gettext ("No usable database library found."));
  143: 
  144:   /* Special handling if we are asked to print the database.  */
  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:   /* Open input file.  */
  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:       /* Get the access rights from the source file.  The output file should
  174:          have the same.  */
  175:       if (fstat (fileno (input_file), &st) >= 0)
  176:         mode = st.st_mode & ACCESSPERMS;
  177:     }
  178: 
  179:   /* Open output file.  This must not be standard output so we don't
  180:      handle "-" and "/dev/stdout" special.  */
  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:   /* Start the real work.  */
  187:   status = process_input (input_file, input_name, db_file, to_lowercase,
  188:                           be_quiet);
  189: 
  190:   /* Close files.  */
  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: /* Handle program arguments.  */
  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:       /* We print some extra information.  */
  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: /* Print the version information.  */
  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:         /* This means end of file or some bug.  */
  282:         break;
  283:       if (n == 0)
  284:         /* Short read.  Probably interrupted system call. */
  285:         continue;
  286: 
  287:       ++linenr;
  288: 
  289:       if (line[n - 1] == '\n')
  290:         /* Remove trailing newline.  */
  291:         line[--n] = '\0';
  292: 
  293:       cp = line;
  294:       while (isspace (*cp))
  295:         ++cp;
  296: 
  297:       if (*cp == '#')
  298:         /* First non-space character in line '#': it's a comment.  */
  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:         /* It's an empty line.  */
  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:       /* Store the value.  */
  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:               /* This is no real error.  Just give a warning.  */
  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: }
Syntax (Markdown)