/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * httxt2dbm.c: simple program for converting RewriteMap text files to DBM * Rewrite databases for the Apache HTTP server * */ #include "apr.h" #include "apr_lib.h" #include "apr_strings.h" #include "apr_file_io.h" #include "apr_file_info.h" #include "apr_pools.h" #include "apr_getopt.h" #include "apu.h" #include "apr_dbm.h" #if APR_HAVE_STDLIB_H #include /* for atexit() */ #endif static const char *input; static const char *output; static const char *format; static const char *shortname; static apr_file_t *errfile; static int verbose; /* From mod_rewrite.c */ #ifndef REWRITE_MAX_TXT_MAP_LINE #define REWRITE_MAX_TXT_MAP_LINE 1024 #endif #define NL APR_EOL_STR #define AVAIL "available" #define UNAVAIL "unavailable" static void usage(void) { const char *have_sdbm; const char *have_gdbm; const char *have_ndbm; const char *have_db; #if APU_HAVE_SDBM have_sdbm = AVAIL; #else have_sdbm = UNAVAIL; #endif #if APU_HAVE_GDBM have_gdbm = AVAIL; #else have_gdbm = UNAVAIL; #endif #if APU_HAVE_NDBM have_ndbm = AVAIL; #else have_ndbm = UNAVAIL; #endif #if APU_HAVE_DB have_db = AVAIL; #else have_db = UNAVAIL; #endif apr_file_printf(errfile, "%s -- Program to Create DBM Files for use by RewriteMap" NL "Usage: %s [-v] [-f format] -i SOURCE_TXT -o OUTPUT_DBM" NL NL "Options: " NL " -v More verbose output" NL NL " -i Source Text File. If '-', use stdin." NL NL " -o Output DBM." NL NL " -f DBM Format. If not specified, will use the APR Default." NL " GDBM for GDBM files (%s)" NL " SDBM for SDBM files (%s)" NL " DB for berkeley DB files (%s)" NL " NDBM for NDBM files (%s)" NL " default for the default DBM type" NL NL, shortname, shortname, have_gdbm, have_sdbm, have_db, have_ndbm); } static apr_status_t to_dbm(apr_dbm_t *dbm, apr_file_t *fp, apr_pool_t *pool) { apr_status_t rv = APR_SUCCESS; char line[REWRITE_MAX_TXT_MAP_LINE + 1]; /* +1 for \0 */ apr_datum_t dbmkey; apr_datum_t dbmval; apr_pool_t* p; apr_pool_create(&p, pool); while (apr_file_gets(line, sizeof(line), fp) == APR_SUCCESS) { char *c, *value; if (*line == '#' || apr_isspace(*line)) { continue; } c = line; while (*c && !apr_isspace(*c)) { ++c; } if (!*c) { /* no value. solid line of data. */ continue; } dbmkey.dptr = apr_pstrmemdup(p, line, c - line); dbmkey.dsize = (c - line); while (apr_isspace(*c)) { ++c; } if (!*c) { apr_pool_clear(p); continue; } value = c; while (*c && !apr_isspace(*c)) { ++c; } dbmval.dptr = apr_pstrmemdup(p, value, c - value); dbmval.dsize = (c - value); if (verbose) { apr_file_printf(errfile, " '%s' -> '%s'" NL, dbmkey.dptr, dbmval.dptr); } rv = apr_dbm_store(dbm, dbmkey, dbmval); apr_pool_clear(p); if (rv != APR_SUCCESS) { break; } } return rv; } int main(int argc, const char *const argv[]) { apr_pool_t *pool; apr_status_t rv = APR_SUCCESS; apr_getopt_t *opt; const char *opt_arg; char ch; apr_file_t *infile; apr_dbm_t *outdbm; apr_app_initialize(&argc, &argv, NULL); atexit(apr_terminate); verbose = 0; format = NULL; input = NULL; output = NULL; apr_pool_create(&pool, NULL); if (argc) { shortname = apr_filepath_name_get(argv[0]); } else { shortname = "httxt2dbm"; } apr_file_open_stderr(&errfile, pool); rv = apr_getopt_init(&opt, pool, argc, argv); if (rv != APR_SUCCESS) { apr_file_printf(errfile, "Error: apr_getopt_init failed." NL NL); return 1; } if (argc <= 1) { usage(); return 1; } while ((rv = apr_getopt(opt, "vf::i::o::", &ch, &opt_arg)) == APR_SUCCESS) { switch (ch) { case 'v': if (verbose) { apr_file_printf(errfile, "Error: -v can only be passed once" NL NL); usage(); return 1; } verbose = 1; break; case 'f': if (format) { apr_file_printf(errfile, "Error: -f can only be passed once" NL NL); usage(); return 1; } format = apr_pstrdup(pool, opt_arg); break; case 'i': if (input) { apr_file_printf(errfile, "Error: -i can only be passed once" NL NL); usage(); return 1; } input = apr_pstrdup(pool, opt_arg); break; case 'o': if (output) { apr_file_printf(errfile, "Error: -o can only be passed once" NL NL); usage(); return 1; } output = apr_pstrdup(pool, opt_arg); break; } } if (rv != APR_EOF) { apr_file_printf(errfile, "Error: Parsing Arguments Failed" NL NL); usage(); return 1; } if (!input) { apr_file_printf(errfile, "Error: No input file specified." NL NL); usage(); return 1; } if (!output) { apr_file_printf(errfile, "Error: No output DBM specified." NL NL); usage(); return 1; } if (!format) { format = "default"; } if (verbose) { apr_file_printf(errfile, "DBM Format: %s" NL, format); } if (!strcmp(input, "-")) { rv = apr_file_open_stdin(&infile, pool); } else { rv = apr_file_open(&infile, input, APR_READ|APR_BUFFERED, APR_OS_DEFAULT, pool); } if (rv != APR_SUCCESS) { apr_file_printf(errfile, "Error: Cannot open input file '%s': (%d) %pm" NL NL, input, rv, &rv); return 1; } if (verbose) { apr_file_printf(errfile, "Input File: %s" NL, input); } rv = apr_dbm_open_ex(&outdbm, format, output, APR_DBM_RWCREATE, APR_OS_DEFAULT, pool); if (APR_STATUS_IS_ENOTIMPL(rv)) { apr_file_printf(errfile, "Error: The requested DBM Format '%s' is not available." NL NL, format); return 1; } if (rv != APR_SUCCESS) { apr_file_printf(errfile, "Error: Cannot open output DBM '%s': (%d) %pm" NL NL, output, rv, &rv); return 1; } if (verbose) { apr_file_printf(errfile, "DBM File: %s" NL, output); } rv = to_dbm(outdbm, infile, pool); if (rv != APR_SUCCESS) { apr_file_printf(errfile, "Error: Converting to DBM: (%d) %pm" NL NL, rv, &rv); return 1; } apr_dbm_close(outdbm); if (verbose) { apr_file_printf(errfile, "Conversion Complete." NL); } return 0; }