| /* 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 <stdlib.h> /* 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; |
| } |
| |