martin 97/10/26 12:20:08
Modified: src CHANGES src/main http_config.c http_config.h http_core.c httpd.h util.c src/modules/standard mod_auth.c mod_digest.c mod_imap.c mod_info.c mod_mime.c Log: Invent new structure and associated methods to handle config file reading. Add "custom" hook to use config file cfg_getline() on something which is not a FILE Reviewed by: Paul +1, Dean +1 Revision Changes Path 1.476 +4 -0 apachen/src/CHANGES Index: CHANGES =================================================================== RCS file: /home/cvs/apachen/src/CHANGES,v retrieving revision 1.475 retrieving revision 1.476 diff -u -u -r1.475 -r1.476 --- CHANGES 1997/10/26 13:43:27 1.475 +++ CHANGES 1997/10/26 20:19:14 1.476 @@ -1,4 +1,8 @@ Changes with Apache 1.3b3 + *) Invent new structure and associated methods to handle config file + reading. Add "custom" hook to use config file cfg_getline() on + something which is not a FILE* [Martin Kraemer] + *) Make single-exe Windows install. [Ben Laurie and Eric Esselink] *) Make CGI work under Win95. [Ben Laurie and Paul Sutton] 1.84 +10 -16 apachen/src/main/http_config.c Index: http_config.c =================================================================== RCS file: /home/cvs/apachen/src/main/http_config.c,v retrieving revision 1.83 retrieving revision 1.84 diff -u -u -r1.83 -r1.84 --- http_config.c 1997/10/22 20:29:35 1.83 +++ http_config.c 1997/10/26 20:19:37 1.84 @@ -793,7 +793,6 @@ const command_rec *cmd; module *mod = top_module; - ++parms->config_line; if ((l[0] == '#') || (!l[0])) return NULL; @@ -834,7 +833,7 @@ { char l[MAX_STRING_LEN]; - while (!(cfg_getline(l, MAX_STRING_LEN, parms->infile))) { + while (!(cfg_getline(l, MAX_STRING_LEN, parms->config_file))) { const char *errmsg = handle_command(parms, config, l); if (errmsg) return errmsg; @@ -888,7 +887,7 @@ */ cmd_parms default_parms = -{NULL, 0, -1, NULL, 0, NULL, NULL, NULL, NULL}; +{NULL, 0, -1, NULL, NULL, NULL, NULL, NULL, NULL}; API_EXPORT(char *) server_root_relative(pool *p, char *file) { @@ -899,7 +898,6 @@ void process_resource_config(server_rec *s, char *fname, pool *p, pool *ptemp) { - FILE *cfg; const char *errmsg; cmd_parms parms; struct stat finfo; @@ -915,38 +913,35 @@ /* GCC's initialization extensions are soooo nice here... */ parms = default_parms; - parms.config_file = fname; parms.pool = p; parms.temp_pool = ptemp; parms.server = s; parms.override = (RSRC_CONF | OR_ALL) & ~(OR_AUTHCFG | OR_LIMIT); - if (!(cfg = fopen(fname, "r"))) { + if (!(parms.config_file = pcfg_openfile(p,fname))) { perror("fopen"); fprintf(stderr, "httpd: could not open document config file %s\n", fname); exit(1); } - parms.infile = cfg; - errmsg = srm_command_loop(&parms, s->lookup_defaults); if (errmsg) { fprintf(stderr, "Syntax error on line %d of %s:\n", - parms.config_line, fname); + parms.config_file->line_number, fname); fprintf(stderr, "%s\n", errmsg); exit(1); } - fclose(cfg); + cfg_closefile(parms.config_file); } int parse_htaccess(void **result, request_rec *r, int override, const char *d, const char *access_name) { - FILE *f = NULL; + configfile_t *f = NULL; cmd_parms parms; const char *errmsg; char *filename = NULL; @@ -973,17 +968,16 @@ while (!f && access_name[0]) { char *w = getword_conf(r->pool, &access_name); filename = make_full_path(r->pool, d, w); - f = pfopen(r->pool, filename, "r"); + f = pcfg_openfile(r->pool, filename); } if (f) { dc = create_per_dir_config(r->pool); - parms.infile = f; - parms.config_file = filename; + parms.config_file = f; errmsg = srm_command_loop(&parms, dc); - pfclose(r->pool, f); + cfg_closefile(f); if (errmsg) { aplog_error(APLOG_MARK, APLOG_ALERT, r->server, "%s: %s", filename, errmsg); @@ -997,7 +991,7 @@ dc = NULL; else { aplog_error(APLOG_MARK, APLOG_CRIT, r->server, - "%s pfopen: unable to check htaccess file, ensure it is readable", + "%s pcfg_openfile: unable to check htaccess file, ensure it is readable", filename); return HTTP_FORBIDDEN; } 1.54 +1 -3 apachen/src/main/http_config.h Index: http_config.h =================================================================== RCS file: /home/cvs/apachen/src/main/http_config.h,v retrieving revision 1.53 retrieving revision 1.54 diff -u -u -r1.53 -r1.54 --- http_config.h 1997/10/22 20:29:36 1.53 +++ http_config.h 1997/10/26 20:19:38 1.54 @@ -135,9 +135,7 @@ int override; /* Which allow-override bits are set */ int limited; /* Which methods are <Limit>ed */ - char *config_file; /* Filename cmd read from */ - int config_line; /* Line cmd read from */ - FILE *infile; /* fd for more lines (not currently used) */ + configfile_t *config_file; /* Config file structure from pcfg_openfile() */ pool *pool; /* Pool to allocate new storage in */ pool *temp_pool; /* Pool for scratch memory; persists during 1.133 +1 -1 apachen/src/main/http_core.c Index: http_core.c =================================================================== RCS file: /home/cvs/apachen/src/main/http_core.c,v retrieving revision 1.132 retrieving revision 1.133 diff -u -u -r1.132 -r1.133 --- http_core.c 1997/10/22 21:49:45 1.132 +++ http_core.c 1997/10/26 20:19:39 1.133 @@ -994,7 +994,7 @@ if ((!not && found) || (not && !found)) return NULL; - while (nest && !(cfg_getline (l, MAX_STRING_LEN, cmd->infile))) { + while (nest && !(cfg_getline (l, MAX_STRING_LEN, cmd->config_file))) { if (!strncasecmp(l, "<IfModule", 9)) nest++; if (!strcasecmp(l, "</IfModule>")) 1.164 +28 -1 apachen/src/main/httpd.h Index: httpd.h =================================================================== RCS file: /home/cvs/apachen/src/main/httpd.h,v retrieving revision 1.163 retrieving revision 1.164 diff -u -u -r1.163 -r1.164 --- httpd.h 1997/10/25 22:35:17 1.163 +++ httpd.h 1997/10/26 20:19:40 1.164 @@ -806,7 +806,34 @@ API_EXPORT(int) ind(const char *, char); /* Sigh... */ API_EXPORT(int) rind(const char *, char); -API_EXPORT(int) cfg_getline(char *s, int n, FILE *f); +/* Common structure for reading of config files / passwd files etc. */ +typedef struct { + int (*getch) (void *param); /* a getc()-like function */ + void *(*getstr) (void *buf, size_t bufsiz, void *param); /* a fgets()-like function */ + int (*close) (void *param); /* a fclose()-like function */ + void *param; /* the argument passed to getc()/close()/gets() */ + const char *name; /* the filename / description */ + unsigned line_number; /* current line number, starting at 1 */ +} configfile_t; + +/* Open a configfile_t as FILE, return open configfile_t struct pointer */ +API_EXPORT(configfile_t *) pcfg_openfile(pool *p, const char *name); + +/* Allocate a configfile_t handle with user defined functions and params */ +API_EXPORT(configfile_t *) pcfg_open_custom(pool *p, const char *descr, + void *param, + int(*getc)(void*), + void *(*gets) (void *buf, size_t bufsiz, void *param), + int(*close)(void*)); + +/* Read one line from open configfile_t, strip LF, increase line number */ +API_EXPORT(int) cfg_getline(char *buf, size_t bufsize, configfile_t *cfp); + +/* Read one char from open configfile_t, increase line number upon LF */ +API_EXPORT(int) cfg_getc(configfile_t *cfp); + +/* Detach from open configfile_t, calling the close handler */ +API_EXPORT(int) cfg_closefile(configfile_t *fp); #ifdef NEED_STRERROR char *strerror(int err); 1.73 +147 -28 apachen/src/main/util.c Index: util.c =================================================================== RCS file: /home/cvs/apachen/src/main/util.c,v retrieving revision 1.72 retrieving revision 1.73 diff -u -u -r1.72 -r1.73 --- util.c 1997/10/22 20:29:50 1.72 +++ util.c 1997/10/26 20:19:40 1.73 @@ -59,8 +59,16 @@ * */ +/* Debugging aid: + * #define DEBUG to trace all cfg_open*()/cfg_closefile() calls + * #define DEBUG_CFG_LINES to trace every line read from the config files + */ + #include "httpd.h" #include "http_conf_globals.h" /* for user_id & group_id */ +#if defined(DEBUG)||defined(DEBUG_CFG_LINES) +#include "http_log.h" +#endif const char month_snames[12][4] = { @@ -653,40 +661,151 @@ } #endif -API_EXPORT(int) cfg_getline(char *s, int n, FILE *f) + +/* Open a configfile_t as FILE, return open configfile_t struct pointer */ +API_EXPORT(configfile_t *) pcfg_openfile(pool *p, const char *name) { - register int i = 0, c; + configfile_t *new_cfg; + FILE *file = fopen(name, "r"); + +#ifdef DEBUG + aplog_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, NULL, "Opening config file %s (%s)", name, file == NULL ? strerror(errno) : "successful"); +#endif - s[0] = '\0'; - /* skip leading whitespace */ - do { - c = getc(f); - } while (c == '\t' || c == ' '); + if (file == NULL) + return NULL; - if (c == EOF) - return 1; + new_cfg = palloc(p, sizeof (*new_cfg)); + new_cfg->param = file; + new_cfg->name = pstrdup(p, name); + new_cfg->getch = (int(*)(void*))fgetc; + new_cfg->getstr = (void *(*)(void *,size_t,void *))fgets; + new_cfg->close = (int(*)(void*))fclose; + new_cfg->line_number = 0; + return new_cfg; +} - while (1) { - if ((c == '\t') || (c == ' ')) { - s[i++] = ' '; - while ((c == '\t') || (c == ' ')) - c = getc(f); - } - if (c == CR) { - c = getc(f); - } - if (c == EOF || c == 0x4 || c == LF || i == (n - 1)) { - /* blast trailing whitespace */ - while (i && (s[i - 1] == ' ')) - --i; - s[i] = '\0'; - return 0; - } - s[i] = c; - ++i; - c = getc(f); + +/* Allocate a configfile_t handle with user defined functions and params */ +API_EXPORT(configfile_t *) pcfg_open_custom(pool *p, const char *descr, + void *param, + int(*getch)(void*), + void *(*getstr) (void *buf, size_t bufsiz, void *param), + int(*close)(void*)) +{ + configfile_t *new_cfg = palloc(p, sizeof (*new_cfg)); +#ifdef DEBUG + aplog_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, NULL, "Opening config handler %s", descr); +#endif + new_cfg->param = param; + new_cfg->name = descr; + new_cfg->getch = getch; + new_cfg->getstr = getstr; + new_cfg->close = close; + new_cfg->line_number = 0; + return new_cfg; +} + + +/* Read one character from a configfile_t */ +API_EXPORT(int) cfg_getc(configfile_t *cfp) +{ + register int ch = cfp->getch(cfp->param); + if (ch == LF) + ++cfp->line_number; + return ch; +} + + +/* Read one line from open configfile_t, strip LF, increase line number */ +/* If custom handler does not define a getstr() function, read char by char */ +API_EXPORT(int) cfg_getline(char *buf, size_t bufsize, configfile_t *cfp) +{ + /* If a "get string" function is defined, use it */ + if (cfp->getstr != NULL) { + char *src, *dst; + ++cfp->line_number; + if (cfp->getstr(buf, bufsize, cfp->param) == NULL) + return 1; + + /* Compress the line, reducing all blanks and tabs to one space. + * Leading and trailing white space is eliminated completely + */ + src = dst = buf; + while (isspace(*src)) + ++src; + while (*src != '\0') + { + /* Copy words */ + while (!isspace(*dst = *src) && *src != '\0') { + ++src; + ++dst; + } + *dst++ = ' '; + while (isspace(*src)) + ++src; + } + *dst = '\0'; + /* blast trailing whitespace */ + while (--dst >= buf && isspace(*dst)) + *dst = '\0'; + +#ifdef DEBUG_CFG_LINES + aplog_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, NULL, "Read config: %s", buf); +#endif + return 0; + } else { + /* No "get string" function defined; read character by character */ + register int c; + register size_t i = 0; + + buf[0] = '\0'; + /* skip leading whitespace */ + do { + c = cfp->getch(cfp->param); + } while (c == '\t' || c == ' '); + + if (c == EOF) + return 1; + + while (1) { + if ((c == '\t') || (c == ' ')) { + buf[i++] = ' '; + while ((c == '\t') || (c == ' ')) + c = cfp->getch(cfp->param); + } + if (c == CR) { + /* silently ignore CR (_assume_ that a LF follows) */ + c = cfp->getch(cfp->param); + } else if (c == LF) { + /* increase line number and return on LF */ + ++cfp->line_number; + } + if (c == EOF || c == 0x4 || c == LF || i == (bufsize - 1)) { + /* blast trailing whitespace */ + while (i > 0 && isspace(buf[i - 1])) + --i; + buf[i] = '\0'; +#ifdef DEBUG_CFG_LINES + aplog_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, NULL, "Read config: %s", buf); +#endif + return 0; + } + buf[i] = c; + ++i; + c = cfp->getch(cfp->param); + } } } + +API_EXPORT(int) cfg_closefile(configfile_t *fp) +{ +#ifdef DEBUG + aplog_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, NULL, "Done with config file %s", fp->name); +#endif + return (fp->close == NULL) ? 0 : fp->close(fp->param); +} + /* Retrieve a token, spacing over it and returning a pointer to * the first non-white byte afterwards. Note that these tokens 1.30 +10 -7 apachen/src/modules/standard/mod_auth.c Index: mod_auth.c =================================================================== RCS file: /home/cvs/apachen/src/modules/standard/mod_auth.c,v retrieving revision 1.29 retrieving revision 1.30 diff -u -u -r1.29 -r1.30 --- mod_auth.c 1997/10/22 20:30:14 1.29 +++ mod_auth.c 1997/10/26 20:20:03 1.30 @@ -117,11 +117,11 @@ static char *get_pw(request_rec *r, char *user, char *auth_pwfile) { - FILE *f; + configfile_t *f; char l[MAX_STRING_LEN]; const char *rpw, *w; - if (!(f = pfopen(r->pool, auth_pwfile, "r"))) { + if (!(f = pcfg_openfile(r->pool, auth_pwfile))) { aplog_error(APLOG_MARK, APLOG_ERR, r->server, "Could not open password file: %s", auth_pwfile); return NULL; @@ -133,24 +133,27 @@ w = getword(r->pool, &rpw, ':'); if (!strcmp(user, w)) { - pfclose(r->pool, f); + cfg_closefile(f); return getword(r->pool, &rpw, ':'); } } - pfclose(r->pool, f); + cfg_closefile(f); return NULL; } static table *groups_for_user(pool *p, char *user, char *grpfile) { - FILE *f; + configfile_t *f; table *grps = make_table(p, 15); pool *sp; char l[MAX_STRING_LEN]; const char *group_name, *ll, *w; - if (!(f = pfopen(p, grpfile, "r"))) + if (!(f = pcfg_openfile(p, grpfile))) { +/*add? aplog_error(APLOG_MARK, APLOG_ERR, NULL, + "Could not open group file: %s", grpfile);*/ return NULL; + } sp = make_sub_pool(p); @@ -170,7 +173,7 @@ } } } - pfclose(p, f); + cfg_closefile(f); destroy_pool(sp); return grps; } 1.26 +4 -4 apachen/src/modules/standard/mod_digest.c Index: mod_digest.c =================================================================== RCS file: /home/cvs/apachen/src/modules/standard/mod_digest.c,v retrieving revision 1.25 retrieving revision 1.26 diff -u -u -r1.25 -r1.26 --- mod_digest.c 1997/10/22 20:30:18 1.25 +++ mod_digest.c 1997/10/26 20:20:04 1.26 @@ -102,12 +102,12 @@ char *get_hash(request_rec *r, char *user, char *auth_pwfile) { - FILE *f; + configfile_t *f; char l[MAX_STRING_LEN]; const char *rpw; char *w, *x; - if (!(f = pfopen(r->pool, auth_pwfile, "r"))) { + if (!(f = pcfg_openfile(r->pool, auth_pwfile))) { aplog_error(APLOG_MARK, APLOG_ERR, r->server, "Could not open password file: %s", auth_pwfile); return NULL; @@ -120,11 +120,11 @@ x = getword(r->pool, &rpw, ':'); if (x && w && !strcmp(user, w) && !strcmp(auth_name(r), x)) { - pfclose(r->pool, f); + cfg_closefile(f); return pstrdup(r->pool, rpw); } } - pfclose(r->pool, f); + cfg_closefile(f); return NULL; } 1.35 +6 -6 apachen/src/modules/standard/mod_imap.c Index: mod_imap.c =================================================================== RCS file: /home/cvs/apachen/src/modules/standard/mod_imap.c,v retrieving revision 1.34 retrieving revision 1.35 diff -u -u -r1.34 -r1.35 --- mod_imap.c 1997/10/22 20:30:21 1.34 +++ mod_imap.c 1997/10/26 20:20:04 1.35 @@ -654,12 +654,12 @@ char *imap_base = icr->imap_base ? icr->imap_base : IMAP_BASE_DEFAULT; - FILE *imap; + configfile_t *imap; if (r->method_number != M_GET) return DECLINED; - imap = pfopen(r->pool, r->filename, "r"); + imap = pcfg_openfile(r->pool, r->filename); if (!imap) return NOT_FOUND; @@ -780,7 +780,7 @@ if (!strcasecmp(directive, "poly")) { /* poly */ if (pointinpoly(testpoint, pointarray)) { - pfclose(r->pool, imap); + cfg_closefile(imap); imap_url(r, base, value, redirect); return (imap_reply(r, redirect)); } @@ -790,7 +790,7 @@ if (!strcasecmp(directive, "circle")) { /* circle */ if (pointincircle(testpoint, pointarray)) { - pfclose(r->pool, imap); + cfg_closefile(imap); imap_url(r, base, value, redirect); return (imap_reply(r, redirect)); } @@ -800,7 +800,7 @@ if (!strcasecmp(directive, "rect")) { /* rect */ if (pointinrect(testpoint, pointarray)) { - pfclose(r->pool, imap); + cfg_closefile(imap); imap_url(r, base, value, redirect); return (imap_reply(r, redirect)); } @@ -819,7 +819,7 @@ } /* nothing matched, so we get another line! */ - pfclose(r->pool, imap); /* we are done with the map file, so close it */ + cfg_closefile(imap); /* we are done with the map file, so close it */ if (showmenu) { menu_footer(r); /* finish the menu and we are done */ 1.31 +3 -3 apachen/src/modules/standard/mod_info.c Index: mod_info.c =================================================================== RCS file: /home/cvs/apachen/src/modules/standard/mod_info.c,v retrieving revision 1.30 retrieving revision 1.31 diff -u -u -r1.30 -r1.31 --- mod_info.c 1997/10/22 20:30:23 1.30 +++ mod_info.c 1997/10/26 20:20:05 1.31 @@ -155,11 +155,11 @@ request_rec *r) { char s[MAX_STRING_LEN]; - FILE *fp; + configfile_t *fp; info_cfg_lines *new, *ret = NULL, *prev = NULL; char *t, *tt, o, *msg; - fp = pfopen(p, filename, "r"); + fp = pcfg_openfile(p, filename); if (!fp) { msg = pstrcat(r->pool, "mod_info: couldn't open config file ", filename, NULL); @@ -199,7 +199,7 @@ } prev = new; } - pfclose(p, fp); + cfg_closefile(fp); return (ret); } 1.27 +3 -3 apachen/src/modules/standard/mod_mime.c Index: mod_mime.c =================================================================== RCS file: /home/cvs/apachen/src/modules/standard/mod_mime.c,v retrieving revision 1.26 retrieving revision 1.27 diff -u -u -r1.26 -r1.27 --- mod_mime.c 1997/10/22 20:30:25 1.26 +++ mod_mime.c 1997/10/26 20:20:05 1.27 @@ -190,7 +190,7 @@ static void init_mime(server_rec *s, pool *p) { - FILE *f; + configfile_t *f; char l[MAX_STRING_LEN]; int x; char *types_confname = get_module_config(s->module_config, &mime_module); @@ -200,7 +200,7 @@ types_confname = server_root_relative(p, types_confname); - if (!(f = fopen(types_confname, "r"))) { + if (!(f = pcfg_openfile(p, types_confname))) { perror("fopen"); fprintf(stderr, "httpd: could not open mime types file %s\n", types_confname); @@ -223,7 +223,7 @@ table_set(hash_buckets[hash(ext[0])], ext, ct); } } - fclose(f); + cfg_closefile(f); } /* note that the proxy module uses this via mime_find_ct */