1/* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17/* 18 * httxt2dbm.c: simple program for converting RewriteMap text files to DBM 19 * Rewrite databases for the Apache HTTP server 20 * 21 */ 22 23#include "apr.h" 24#include "apr_lib.h" 25#include "apr_strings.h" 26#include "apr_file_io.h" 27#include "apr_file_info.h" 28#include "apr_pools.h" 29#include "apr_getopt.h" 30#include "apu.h" 31#include "apr_dbm.h" 32 33#if APR_HAVE_STDLIB_H 34#include <stdlib.h> /* for atexit() */ 35#endif 36 37static const char *input; 38static const char *output; 39static const char *format; 40static const char *shortname; 41static apr_file_t *errfile; 42static int verbose; 43 44/* From mod_rewrite.c */ 45#ifndef REWRITE_MAX_TXT_MAP_LINE 46#define REWRITE_MAX_TXT_MAP_LINE 1024 47#endif 48 49#define NL APR_EOL_STR 50 51#define AVAIL "available" 52#define UNAVAIL "unavailable" 53 54static void usage(void) 55{ 56 const char *have_sdbm; 57 const char *have_gdbm; 58 const char *have_ndbm; 59 const char *have_db; 60 61#if APU_HAVE_SDBM 62 have_sdbm = AVAIL; 63#else 64 have_sdbm = UNAVAIL; 65#endif 66#if APU_HAVE_GDBM 67 have_gdbm = AVAIL; 68#else 69 have_gdbm = UNAVAIL; 70#endif 71#if APU_HAVE_NDBM 72 have_ndbm = AVAIL; 73#else 74 have_ndbm = UNAVAIL; 75#endif 76#if APU_HAVE_DB 77 have_db = AVAIL; 78#else 79 have_db = UNAVAIL; 80#endif 81 82 apr_file_printf(errfile, 83 "%s -- Program to Create DBM Files for use by RewriteMap" NL 84 "Usage: %s [-v] [-f format] -i SOURCE_TXT -o OUTPUT_DBM" NL 85 NL 86 "Options: " NL 87 " -v More verbose output" NL 88 NL 89 " -i Source Text File. If '-', use stdin." NL 90 NL 91 " -o Output DBM." NL 92 NL 93 " -f DBM Format. If not specified, will use the APR Default." NL 94 " GDBM for GDBM files (%s)" NL 95 " SDBM for SDBM files (%s)" NL 96 " DB for berkeley DB files (%s)" NL 97 " NDBM for NDBM files (%s)" NL 98 " default for the default DBM type" NL 99 NL, 100 shortname, 101 shortname, 102 have_gdbm, 103 have_sdbm, 104 have_db, 105 have_ndbm); 106} 107 108 109static apr_status_t to_dbm(apr_dbm_t *dbm, apr_file_t *fp, apr_pool_t *pool) 110{ 111 apr_status_t rv = APR_SUCCESS; 112 char line[REWRITE_MAX_TXT_MAP_LINE + 1]; /* +1 for \0 */ 113 apr_datum_t dbmkey; 114 apr_datum_t dbmval; 115 apr_pool_t* p; 116 117 apr_pool_create(&p, pool); 118 119 while (apr_file_gets(line, sizeof(line), fp) == APR_SUCCESS) { 120 char *c, *value; 121 122 if (*line == '#' || apr_isspace(*line)) { 123 continue; 124 } 125 126 c = line; 127 128 while (*c && !apr_isspace(*c)) { 129 ++c; 130 } 131 132 if (!*c) { 133 /* no value. solid line of data. */ 134 continue; 135 } 136 137 dbmkey.dptr = apr_pstrmemdup(p, line, c - line); 138 dbmkey.dsize = (c - line); 139 140 while (apr_isspace(*c)) { 141 ++c; 142 } 143 144 if (!*c) { 145 apr_pool_clear(p); 146 continue; 147 } 148 149 value = c; 150 151 while (*c && !apr_isspace(*c)) { 152 ++c; 153 } 154 155 dbmval.dptr = apr_pstrmemdup(p, value, c - value); 156 dbmval.dsize = (c - value); 157 158 if (verbose) { 159 apr_file_printf(errfile, " '%s' -> '%s'" NL, 160 dbmkey.dptr, dbmval.dptr); 161 } 162 163 rv = apr_dbm_store(dbm, dbmkey, dbmval); 164 165 apr_pool_clear(p); 166 167 if (rv != APR_SUCCESS) { 168 break; 169 } 170 } 171 172 return rv; 173} 174 175int main(int argc, const char *const argv[]) 176{ 177 apr_pool_t *pool; 178 apr_status_t rv = APR_SUCCESS; 179 apr_getopt_t *opt; 180 const char *opt_arg; 181 char ch; 182 apr_file_t *infile; 183 apr_dbm_t *outdbm; 184 185 apr_app_initialize(&argc, &argv, NULL); 186 atexit(apr_terminate); 187 188 verbose = 0; 189 format = NULL; 190 input = NULL; 191 output = NULL; 192 193 apr_pool_create(&pool, NULL); 194 195 if (argc) { 196 shortname = apr_filepath_name_get(argv[0]); 197 } 198 else { 199 shortname = "httxt2dbm"; 200 } 201 202 apr_file_open_stderr(&errfile, pool); 203 rv = apr_getopt_init(&opt, pool, argc, argv); 204 205 if (rv != APR_SUCCESS) { 206 apr_file_printf(errfile, "Error: apr_getopt_init failed." NL NL); 207 return 1; 208 } 209 210 if (argc <= 1) { 211 usage(); 212 return 1; 213 } 214 215 while ((rv = apr_getopt(opt, "vf::i::o::", &ch, &opt_arg)) == APR_SUCCESS) { 216 switch (ch) { 217 case 'v': 218 if (verbose) { 219 apr_file_printf(errfile, "Error: -v can only be passed once" NL NL); 220 usage(); 221 return 1; 222 } 223 verbose = 1; 224 break; 225 case 'f': 226 if (format) { 227 apr_file_printf(errfile, "Error: -f can only be passed once" NL NL); 228 usage(); 229 return 1; 230 } 231 format = apr_pstrdup(pool, opt_arg); 232 break; 233 case 'i': 234 if (input) { 235 apr_file_printf(errfile, "Error: -i can only be passed once" NL NL); 236 usage(); 237 return 1; 238 } 239 input = apr_pstrdup(pool, opt_arg); 240 break; 241 case 'o': 242 if (output) { 243 apr_file_printf(errfile, "Error: -o can only be passed once" NL NL); 244 usage(); 245 return 1; 246 } 247 output = apr_pstrdup(pool, opt_arg); 248 break; 249 } 250 } 251 252 if (rv != APR_EOF) { 253 apr_file_printf(errfile, "Error: Parsing Arguments Failed" NL NL); 254 usage(); 255 return 1; 256 } 257 258 if (!input) { 259 apr_file_printf(errfile, "Error: No input file specified." NL NL); 260 usage(); 261 return 1; 262 } 263 264 if (!output) { 265 apr_file_printf(errfile, "Error: No output DBM specified." NL NL); 266 usage(); 267 return 1; 268 } 269 270 if (!format) { 271 format = "default"; 272 } 273 274 if (verbose) { 275 apr_file_printf(errfile, "DBM Format: %s" NL, format); 276 } 277 278 if (!strcmp(input, "-")) { 279 rv = apr_file_open_stdin(&infile, pool); 280 } 281 else { 282 rv = apr_file_open(&infile, input, APR_READ|APR_BUFFERED, 283 APR_OS_DEFAULT, pool); 284 } 285 286 if (rv != APR_SUCCESS) { 287 apr_file_printf(errfile, 288 "Error: Cannot open input file '%s': (%d) %pm" NL NL, 289 input, rv, &rv); 290 return 1; 291 } 292 293 if (verbose) { 294 apr_file_printf(errfile, "Input File: %s" NL, input); 295 } 296 297 rv = apr_dbm_open_ex(&outdbm, format, output, APR_DBM_RWCREATE, 298 APR_OS_DEFAULT, pool); 299 300 if (APR_STATUS_IS_ENOTIMPL(rv)) { 301 apr_file_printf(errfile, 302 "Error: The requested DBM Format '%s' is not available." NL NL, 303 format); 304 return 1; 305 } 306 307 if (rv != APR_SUCCESS) { 308 apr_file_printf(errfile, 309 "Error: Cannot open output DBM '%s': (%d) %pm" NL NL, 310 output, rv, &rv); 311 return 1; 312 } 313 314 if (verbose) { 315 apr_file_printf(errfile, "DBM File: %s" NL, output); 316 } 317 318 rv = to_dbm(outdbm, infile, pool); 319 320 if (rv != APR_SUCCESS) { 321 apr_file_printf(errfile, 322 "Error: Converting to DBM: (%d) %pm" NL NL, 323 rv, &rv); 324 return 1; 325 } 326 327 apr_dbm_close(outdbm); 328 329 if (verbose) { 330 apr_file_printf(errfile, "Conversion Complete." NL); 331 } 332 333 return 0; 334} 335 336