]> granicus.if.org Git - apache/blob - support/httxt2dbm.c
Update scoreboard backport proposal with latest commit.
[apache] / support / httxt2dbm.c
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
37 static const char *input;
38 static const char *output;
39 static const char *format;
40 static const char *shortname;
41 static apr_file_t *errfile;
42 static 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
54 static 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
109 static 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
175 int 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