Commit 8aa9ea13 authored by Paul Querna's avatar Paul Querna
Browse files

Add the httxt2dbm utility to create DBM files for RewriteMap. This replaces...

Add the httxt2dbm utility to create DBM files for RewriteMap.  This replaces the txt2dbm script in the manual, and allows the use of any available DBM format.


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@209539 13f79535-47bb-0310-9956-ffa450edef68
parent ea57a114
Loading
Loading
Loading
Loading
+3 −0
Changes for CHANGES: 3 added lines, 0 removed lines.
Original line number Diff line number Diff line
Changes with Apache 2.1.7
  [Remove entries to the current 2.0 section below, when backported]
  *) Add httxt2dbm to support/ for creating RewriteMap DBM Files.
     [Paul Querna]
  *) Fixed complaints about unpackaged files within the RPM build
     after changes to the config files. [Graham Leggett]
+6 −1
Changes for support/Makefile.in: 6 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -3,7 +3,7 @@ DISTCLEAN_TARGETS = apxs apachectl dbmmanage log_server_status \

CLEAN_TARGETS = suexec

PROGRAMS = htpasswd htdigest rotatelogs logresolve ab checkgid htdbm htcacheclean
PROGRAMS = htpasswd htdigest rotatelogs logresolve ab checkgid htdbm htcacheclean httxt2dbm
TARGETS  = $(PROGRAMS)

PROGRAM_LDADD        = $(UTIL_LDFLAGS) $(PROGRAM_DEPENDENCIES) $(EXTRA_LIBS) $(AP_LIBS)
@@ -65,3 +65,8 @@ suexec: $(suexec_OBJECTS)
htcacheclean_OBJECTS = htcacheclean.lo
htcacheclean: $(htcacheclean_OBJECTS)
	$(LINK) $(htcacheclean_LTFLAGS) $(htcacheclean_OBJECTS) $(PROGRAM_LDADD)

httxt2dbm_OBJECTS = httxt2dbm.lo
httxt2dbm: $(httxt2dbm_OBJECTS)
	$(LINK) $(httxt2dbm_LTFLAGS) $(httxt2dbm_OBJECTS) $(PROGRAM_LDADD)

support/httxt2dbm.c

0 → 100644
+333 −0
Changes for support/httxt2dbm.c: 333 added lines, 0 removed lines.
Original line number Diff line number Diff line
/* Copyright 2005 The Apache Software Foundation or its licensors, as
 * applicable.
 *
 * Licensed 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"


static const char *input;
static const char *output;
static const char *format;
static const char *shortname;
static apr_file_t *errfile;
static char errbuf[120];
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(*c && 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 - line);

        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 *optarg;
    char ch;
    apr_file_t *infile;
    apr_dbm_t *outdbm;

    apr_initialize();
    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, &optarg)) == 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, optarg);
            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, optarg);
            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, optarg);
            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) %s" NL NL,
                         input, rv, apr_strerror(rv, errbuf, sizeof(errbuf)));
        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) %s" NL NL,
                         output, rv, apr_strerror(rv, errbuf, sizeof(errbuf)));
        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) %s" NL NL,
                         rv, apr_strerror(rv, errbuf, sizeof(errbuf)));
        return 1;
    }

    apr_dbm_close(outdbm);

    if (verbose) {
        apr_file_printf(errfile, "Conversion Complete." NL);
    }

    return 0;
}