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 char errbuf[120]; 43static int verbose; 44 45/* From mod_rewrite.c */ 46#ifndef REWRITE_MAX_TXT_MAP_LINE 47#define REWRITE_MAX_TXT_MAP_LINE 1024 48#endif 49 50#define NL APR_EOL_STR 51 52#define AVAIL "available" 53#define UNAVAIL "unavailable" 54 55static void usage(void) 56{ 57 const char *have_sdbm; 58 const char *have_gdbm; 59 const char *have_ndbm; 60 const char *have_db; 61 62#if APU_HAVE_SDBM 63 have_sdbm = AVAIL; 64#else 65 have_sdbm = UNAVAIL; 66#endif 67#if APU_HAVE_GDBM 68 have_gdbm = AVAIL; 69#else 70 have_gdbm = UNAVAIL; 71#endif 72#if APU_HAVE_NDBM 73 have_ndbm = AVAIL; 74#else 75 have_ndbm = UNAVAIL; 76#endif 77#if APU_HAVE_DB 78 have_db = AVAIL; 79#else 80 have_db = UNAVAIL; 81#endif 82 83 apr_file_printf(errfile, 84 "%s -- Program to Create DBM Files for use by RewriteMap" NL 85 "Usage: %s [-v] [-f format] -i SOURCE_TXT -o OUTPUT_DBM" NL 86 NL 87 "Options: " NL 88 " -v More verbose output"NL 89 NL 90 " -i Source Text File. If '-', use stdin."NL 91 NL 92 " -o Output DBM."NL 93 NL 94 " -f DBM Format. If not specified, will use the APR Default." NL 95 " GDBM for GDBM files (%s)" NL 96 " SDBM for SDBM files (%s)" NL 97 " DB for berkeley DB files (%s)" NL 98 " NDBM for NDBM files (%s)" NL 99 " default for the default DBM type" NL 100 NL, 101 shortname, 102 shortname, 103 have_gdbm, 104 have_sdbm, 105 have_db, 106 have_ndbm); 107} 108 109 110static apr_status_t to_dbm(apr_dbm_t *dbm, apr_file_t *fp, apr_pool_t *pool) 111{ 112 apr_status_t rv = APR_SUCCESS; 113 char line[REWRITE_MAX_TXT_MAP_LINE + 1]; /* +1 for \0 */ 114 apr_datum_t dbmkey; 115 apr_datum_t dbmval; 116 apr_pool_t* p; 117 118 apr_pool_create(&p, pool); 119 120 while (apr_file_gets(line, sizeof(line), fp) == APR_SUCCESS) { 121 char *c, *value; 122 123 if (*line == '#' || apr_isspace(*line)) { 124 continue; 125 } 126 127 c = line; 128 129 while (*c && !apr_isspace(*c)) { 130 ++c; 131 } 132 133 if (!*c) { 134 /* no value. solid line of data. */ 135 continue; 136 } 137 138 dbmkey.dptr = apr_pstrmemdup(p, line, c - line); 139 dbmkey.dsize = (c - line); 140 141 while (*c && apr_isspace(*c)) { 142 ++c; 143 } 144 145 if (!*c) { 146 apr_pool_clear(p); 147 continue; 148 } 149 150 value = c; 151 152 while (*c && !apr_isspace(*c)) { 153 ++c; 154 } 155 156 dbmval.dptr = apr_pstrmemdup(p, value, c - value); 157 dbmval.dsize = (c - line); 158 159 if (verbose) { 160 apr_file_printf(errfile, " '%s' -> '%s'"NL, 161 dbmkey.dptr, dbmval.dptr); 162 } 163 164 rv = apr_dbm_store(dbm, dbmkey, dbmval); 165 166 apr_pool_clear(p); 167 168 if (rv != APR_SUCCESS) { 169 break; 170 } 171 } 172 173 return rv; 174} 175 176int main(int argc, const char *const argv[]) 177{ 178 apr_pool_t *pool; 179 apr_status_t rv = APR_SUCCESS; 180 apr_getopt_t *opt; 181 const char *optarg; 182 char ch; 183 apr_file_t *infile; 184 apr_dbm_t *outdbm; 185 186 apr_app_initialize(&argc, &argv, NULL); 187 atexit(apr_terminate); 188 189 verbose = 0; 190 format = NULL; 191 input = NULL; 192 output = NULL; 193 194 apr_pool_create(&pool, NULL); 195 196 if (argc) { 197 shortname = apr_filepath_name_get(argv[0]); 198 } 199 else { 200 shortname = "httxt2dbm"; 201 } 202 203 apr_file_open_stderr(&errfile, pool); 204 rv = apr_getopt_init(&opt, pool, argc, argv); 205 206 if (rv != APR_SUCCESS) { 207 apr_file_printf(errfile, "Error: apr_getopt_init failed."NL NL); 208 return 1; 209 } 210 211 if (argc <= 1) { 212 usage(); 213 return 1; 214 } 215 216 while ((rv = apr_getopt(opt, "vf::i::o::", &ch, &optarg)) == APR_SUCCESS) { 217 switch (ch) { 218 case 'v': 219 if (verbose) { 220 apr_file_printf(errfile, "Error: -v can only be passed once" NL NL); 221 usage(); 222 return 1; 223 } 224 verbose = 1; 225 break; 226 case 'f': 227 if (format) { 228 apr_file_printf(errfile, "Error: -f can only be passed once" NL NL); 229 usage(); 230 return 1; 231 } 232 format = apr_pstrdup(pool, optarg); 233 break; 234 case 'i': 235 if (input) { 236 apr_file_printf(errfile, "Error: -i can only be passed once" NL NL); 237 usage(); 238 return 1; 239 } 240 input = apr_pstrdup(pool, optarg); 241 break; 242 case 'o': 243 if (output) { 244 apr_file_printf(errfile, "Error: -o can only be passed once" NL NL); 245 usage(); 246 return 1; 247 } 248 output = apr_pstrdup(pool, optarg); 249 break; 250 } 251 } 252 253 if (rv != APR_EOF) { 254 apr_file_printf(errfile, "Error: Parsing Arguments Failed" NL NL); 255 usage(); 256 return 1; 257 } 258 259 if (!input) { 260 apr_file_printf(errfile, "Error: No input file specified." NL NL); 261 usage(); 262 return 1; 263 } 264 265 if (!output) { 266 apr_file_printf(errfile, "Error: No output DBM specified." NL NL); 267 usage(); 268 return 1; 269 } 270 271 if (!format) { 272 format = "default"; 273 } 274 275 if (verbose) { 276 apr_file_printf(errfile, "DBM Format: %s"NL, format); 277 } 278 279 if (!strcmp(input, "-")) { 280 rv = apr_file_open_stdin(&infile, pool); 281 } 282 else { 283 rv = apr_file_open(&infile, input, APR_READ|APR_BUFFERED, 284 APR_OS_DEFAULT, pool); 285 } 286 287 if (rv != APR_SUCCESS) { 288 apr_file_printf(errfile, 289 "Error: Cannot open input file '%s': (%d) %s" NL NL, 290 input, rv, apr_strerror(rv, errbuf, sizeof(errbuf))); 291 return 1; 292 } 293 294 if (verbose) { 295 apr_file_printf(errfile, "Input File: %s"NL, input); 296 } 297 298 rv = apr_dbm_open_ex(&outdbm, format, output, APR_DBM_RWCREATE, 299 APR_OS_DEFAULT, pool); 300 301 if (APR_STATUS_IS_ENOTIMPL(rv)) { 302 apr_file_printf(errfile, 303 "Error: The requested DBM Format '%s' is not available." NL NL, 304 format); 305 return 1; 306 } 307 308 if (rv != APR_SUCCESS) { 309 apr_file_printf(errfile, 310 "Error: Cannot open output DBM '%s': (%d) %s" NL NL, 311 output, rv, apr_strerror(rv, errbuf, sizeof(errbuf))); 312 return 1; 313 } 314 315 if (verbose) { 316 apr_file_printf(errfile, "DBM File: %s"NL, output); 317 } 318 319 rv = to_dbm(outdbm, infile, pool); 320 321 if (rv != APR_SUCCESS) { 322 apr_file_printf(errfile, 323 "Error: Converting to DBM: (%d) %s" NL NL, 324 rv, apr_strerror(rv, errbuf, sizeof(errbuf))); 325 return 1; 326 } 327 328 apr_dbm_close(outdbm); 329 330 if (verbose) { 331 apr_file_printf(errfile, "Conversion Complete." NL); 332 } 333 334 return 0; 335} 336 337