On 03/29/2011 11:29 PM, s...@apache.org wrote: > Author: sf > Date: Tue Mar 29 21:29:34 2011 > New Revision: 1086756 > > URL: http://svn.apache.org/viewvc?rev=1086756&view=rev > Log: > Change the ap_cfg_getline() and ap_cfg_getc() to return an error code. > > Also: > - Make ap_cfg_getline() return APR_ENOSPC if a config line is too long. > - Add ap_pcfg_strerror() function to convert ap_cfg_getline's return value > into a nice message. > - Adjust definition of ap_configfile_t accordingly. > > Not bumping MMN because it has already been bumped today. > > Modified: > httpd/httpd/trunk/docs/manual/developer/new_api_2_4.xml > httpd/httpd/trunk/include/ap_mmn.h > httpd/httpd/trunk/include/http_config.h > httpd/httpd/trunk/modules/lua/mod_lua.c > httpd/httpd/trunk/server/config.c > httpd/httpd/trunk/server/util.c >
> Modified: httpd/httpd/trunk/server/util.c > URL: > http://svn.apache.org/viewvc/httpd/httpd/trunk/server/util.c?rev=1086756&r1=1086755&r2=1086756&view=diff > ============================================================================== > --- httpd/httpd/trunk/server/util.c (original) > +++ httpd/httpd/trunk/server/util.c Tue Mar 29 21:29:34 2011 > @@ -874,170 +864,156 @@ AP_DECLARE(apr_status_t) ap_pcfg_openfil > > > /* Allocate a ap_configfile_t handle with user defined functions and params > */ > -AP_DECLARE(ap_configfile_t *) ap_pcfg_open_custom(apr_pool_t *p, > - const char *descr, > - void *param, > - int(*getch)(void *param), > - void *(*getstr) (void *buf, size_t bufsiz, void > *param), > - int(*close_func)(void *param)) > +AP_DECLARE(ap_configfile_t *) ap_pcfg_open_custom( > + apr_pool_t *p, const char *descr, void *param, > + apr_status_t (*getc_func) (char *ch, void *param), > + apr_status_t (*gets_func) (void *buf, size_t bufsize, void > *param), > + apr_status_t (*close_func) (void *param)) > { > ap_configfile_t *new_cfg = apr_palloc(p, sizeof(*new_cfg)); > -#ifdef DEBUG > - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, 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->getch = getc_func; > + new_cfg->getstr = gets_func; > new_cfg->close = close_func; > new_cfg->line_number = 0; > return new_cfg; > } > > /* Read one character from a configfile_t */ > -AP_DECLARE(int) ap_cfg_getc(ap_configfile_t *cfp) > +AP_DECLARE(apr_status_t) ap_cfg_getc(char *ch, ap_configfile_t *cfp) > { > - register int ch = cfp->getch(cfp->param); > - if (ch == LF) > + apr_status_t rc = cfp->getch(ch, cfp->param); > + if (rc == APR_SUCCESS && *ch == LF) > ++cfp->line_number; > - return ch; > + return rc; > +} > + > +AP_DECLARE(const char *) ap_pcfg_strerror(apr_pool_t *p, ap_configfile_t > *cfp, > + apr_status_t rc) > +{ > + char buf[MAX_STRING_LEN]; > + if (rc == APR_SUCCESS) > + return NULL; > + return apr_psprintf(p, "Error reading %s at line %d: %s", > + cfp->name, cfp->line_number, > + rc == APR_ENOSPC ? "Line too long" > + : apr_strerror(rc, buf, > sizeof(buf))); > } > > /* Read one line from open ap_configfile_t, strip LF, increase line number */ > /* If custom handler does not define a getstr() function, read char by char > */ > -AP_DECLARE(int) ap_cfg_getline(char *buf, size_t bufsize, ap_configfile_t > *cfp) > +AP_DECLARE(apr_status_t) ap_cfg_getline(char *buf, size_t bufsize, > ap_configfile_t *cfp) > { > + apr_status_t rc; > + char *src, *dst; > /* If a "get string" function is defined, use it */ > if (cfp->getstr != NULL) { > - char *src, *dst; > char *cp; > char *cbuf = buf; > size_t cbufsize = bufsize; > > while (1) { > ++cfp->line_number; > - if (cfp->getstr(cbuf, cbufsize, cfp->param) == NULL) > - return 1; > + rc = cfp->getstr(cbuf, cbufsize, cfp->param); > + if (rc == APR_EOF) { > + if (cbuf != buf) { > + *cbuf = '\0'; > + break; > + } > + else { > + return APR_EOF; > + } > + } > + if (rc != APR_SUCCESS) { > + return rc; > + } > > /* > * check for line continuation, > * i.e. match [^\\]\\[\r]\n only > */ > cp = cbuf; > - while (cp < cbuf+cbufsize && *cp != '\0') > - cp++; > + cp += strlen(cp); > if (cp > cbuf && cp[-1] == LF) { > cp--; > if (cp > cbuf && cp[-1] == CR) > cp--; > if (cp > cbuf && cp[-1] == '\\') { > cp--; > - if (!(cp > cbuf && cp[-1] == '\\')) { > - /* > - * line continuation requested - > - * then remove backslash and continue > - */ > - cbufsize -= (cp-cbuf); > - cbuf = cp; > - continue; Why don't we consider escaped backslashes as literals any longer? > - } > - else { > - /* > - * no real continuation because escaped - > - * then just remove escape character > - */ > - for ( ; cp < cbuf+cbufsize && *cp != '\0'; cp++) > - cp[0] = cp[1]; > - } > + /* > + * line continuation requested - > + * then remove backslash and continue > + */ > + cbufsize -= (cp-cbuf); > + cbuf = cp; > + continue; > } > } > + else if (cp - buf >= bufsize - 1) { > + return APR_ENOSPC; > + } > break; > } > - > - /* > - * Leading and trailing white space is eliminated completely > - */ > - src = buf; > - while (apr_isspace(*src)) > - ++src; > - /* blast trailing whitespace */ > - dst = &src[strlen(src)]; > - while (--dst >= src && apr_isspace(*dst)) > - *dst = '\0'; > - /* Zap leading whitespace by shifting */ > - if (src != buf) > - for (dst = buf; (*dst++ = *src++) != '\0'; ) > - ; > - > -#ifdef DEBUG_CFG_LINES > - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, 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; > + 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; > - > - if(bufsize < 2) { > + if (bufsize < 2) { > /* too small, assume caller is crazy */ > - return 1; > + return APR_EINVAL; > } > + buf[0] = '\0'; > > 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); Why don't we ignore CR any longer? > + char c; > + rc = cfp->getch(&c, cfp->param); > + if (rc == APR_EOF) { > + if (i > 0) > + break; > + else > + return APR_EOF; > } > + if (rc != APR_SUCCESS) > + return rc; > if (c == LF) { > - /* increase line number and return on LF */ > ++cfp->line_number; > - } > - if (c == EOF || c == 0x4 || c == LF || i >= (bufsize - 2)) { > - /* > - * check for line continuation > - */ > + /* check for line continuation */ > if (i > 0 && buf[i-1] == '\\') { > i--; > - if (!(i > 0 && buf[i-1] == '\\')) { > - /* line is continued */ > - c = cfp->getch(cfp->param); > - continue; > - } > - /* else nothing needs be done because > - * then the backslash is escaped and > - * we just strip to a single one > - */ > + continue; > } > - /* blast trailing whitespace */ > - while (i > 0 && apr_isspace(buf[i - 1])) > - --i; > - buf[i] = '\0'; > -#ifdef DEBUG_CFG_LINES > - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, > - "Read config: %s", buf); > -#endif > - return 0; > + else { > + break; > + } > + } > + else if (i >= bufsize - 2) { > + return APR_ENOSPC; > } > buf[i] = c; > ++i; > - c = cfp->getch(cfp->param); > } > + buf[i] = '\0'; > } > + > + /* > + * Leading and trailing white space is eliminated completely > + */ > + src = buf; > + while (apr_isspace(*src)) > + ++src; > + /* blast trailing whitespace */ > + dst = &src[strlen(src)]; > + while (--dst >= src && apr_isspace(*dst)) > + *dst = '\0'; > + /* Zap leading whitespace by shifting */ > + if (src != buf) > + memmove(buf, src, dst - src + 2); > + > +#ifdef DEBUG_CFG_LINES > + ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL, "Read config: '%s'", > buf); > +#endif > + return APR_SUCCESS; > } > > /* Size an HTTP header field list item, as separated by a comma. > > > > Regards RĂ¼diger