util.c revision 6db54801798f6021bb464de7b3fdcc9dc3150f7b
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering/* ====================================================================
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * Copyright (c) 1995-1999 The Apache Group. All rights reserved.
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * Redistribution and use in source and binary forms, with or without
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * modification, are permitted provided that the following conditions
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * 1. Redistributions of source code must retain the above copyright
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * notice, this list of conditions and the following disclaimer.
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * 2. Redistributions in binary form must reproduce the above copyright
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * notice, this list of conditions and the following disclaimer in
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * the documentation and/or other materials provided with the
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * distribution.
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * 3. All advertising materials mentioning features or use of this
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * software must display the following acknowledgment:
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * "This product includes software developed by the Apache Group
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * for use in the Apache HTTP server project (http://www.apache.org/)."
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * 4. The names "Apache Server" and "Apache Group" must not be used to
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * endorse or promote products derived from this software without
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * prior written permission. For written permission, please contact
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * apache@apache.org.
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * 5. Products derived from this software may not be called "Apache"
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * nor may "Apache" appear in their names without prior written
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * permission of the Apache Group.
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering * 6. Redistributions of any form whatsoever must retain the following
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * acknowledgment:
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * "This product includes software developed by the Apache Group
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * for use in the Apache HTTP server project (http://www.apache.org/)."
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * OF THE POSSIBILITY OF SUCH DAMAGE.
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * ====================================================================
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * This software consists of voluntary contributions made by many
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * individuals on behalf of the Apache Group and was originally based
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * on public domain software written at the National Center for
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * Supercomputing Applications, University of Illinois, Urbana-Champaign.
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * For more information on the Apache Group and the Apache HTTP server
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * project, please see <http://www.apache.org/>.
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * util.c: string utility things
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * 3/21/93 Rob McCool
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * 1995-96 Many changes by the Apache Group
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering/* Debugging aid:
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * #define DEBUG to trace all cfg_open*()/cfg_closefile() calls
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * #define DEBUG_CFG_LINES to trace every line read from the config files
c30a0c62fdbf6f11902be9db64ade99fb508adfdLennart Poettering/* stdio.h has been read in ap_config.h already. Add missing prototypes here: */
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering/* A bunch of functions in util.c scan strings looking for certain characters.
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * To make that more efficient we encode a lookup table. The test_char_table
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * is generated automatically by gen_test_char.c.
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering/* we assume the folks using this ensure 0 <= c < 256... which means
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * you need a cast to (unsigned char) first, you can't just plug a
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * char in here and get it to work, because if char is signed then it
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * will first be sign extended.
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering#define TEST_CHAR(c, f) (test_char_table[(unsigned)(c)] & (f))
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * Examine a field value (such as a media-/content-type) string and return
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * it sans any parameters; e.g., strip off any ';charset=foo' and the like.
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart PoetteringAPI_EXPORT(char *) ap_field_noparam(ap_context_t *p, const char *intype)
3c56cab44150ad47323970cfadfb0257c6305a74Ben Wolsieffer while ((semi > intype) && ap_isspace(semi[-1])) {
3c56cab44150ad47323970cfadfb0257c6305a74Ben Wolsieffer return ap_pstrndup(p, intype, semi - intype);
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart PoetteringAPI_EXPORT(char *) ap_ht_time(ap_context_t *p, ap_time_t t, const char *fmt, int gmt)
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering const char *f;
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering /* Convert %Z to "GMT" and %z to "+0000";
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering * on hosts that do not have a time zone string in struct tm,
6de0e0e500d9d534c6e4baab242fc2a146f021faLennart Poettering * strftime must assume its argument is local time.
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering for(strp = tf, f = fmt; strp < tf + sizeof(tf) - 6 && (*strp = *f)
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering if (*f != '%') continue;
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering switch (f[1]) {
c485437f50450c0087bae3df4aed462e4a86ee83Zbigniew Jędrzejewski-Szmek /* check return code? */
e2cc6eca73cd1df8be552d7c23f9ff3d69c06f1eLennart Poettering ap_strftime(ts, &retcode, MAX_STRING_LEN, fmt, &xt);
7b77ed8cf36e8eca6017791626044b61ae2d68e7Lennart Poettering/* Roy owes Rob beer. */
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering/* Rob owes Roy dinner. */
8e7fd6ade44ce5dde0867ba748c7978ed1206865Lennart Poettering/* These legacy comments would make a lot more sense if Roy hadn't
8e7fd6ade44ce5dde0867ba748c7978ed1206865Lennart Poettering * replaced the old later_than() routine with util_date.c.
8e7fd6ade44ce5dde0867ba748c7978ed1206865Lennart Poettering * Well, okay, they still wouldn't make any sense.
c485437f50450c0087bae3df4aed462e4a86ee83Zbigniew Jędrzejewski-Szmek/* Match = 0, NoMatch = 1, Abort = -1
e2cc6eca73cd1df8be552d7c23f9ff3d69c06f1eLennart Poettering * Based loosely on sections of wildmat.c by Rich Salz
e2cc6eca73cd1df8be552d7c23f9ff3d69c06f1eLennart Poettering * Hmmm... shouldn't this really go component by component?
7b77ed8cf36e8eca6017791626044b61ae2d68e7Lennart PoetteringAPI_EXPORT(int) ap_strcmp_match(const char *str, const char *exp)
8e7fd6ade44ce5dde0867ba748c7978ed1206865Lennart Poettering for (x = 0, y = 0; exp[y]; ++y, ++x) {
c485437f50450c0087bae3df4aed462e4a86ee83Zbigniew Jędrzejewski-Szmek if ((!str[x]) && (exp[y] != '*'))
8e7fd6ade44ce5dde0867ba748c7978ed1206865Lennart Poettering if ((ret = ap_strcmp_match(&str[x++], &exp[y])) != 1)
e2cc6eca73cd1df8be552d7c23f9ff3d69c06f1eLennart Poettering else if ((exp[y] != '?') && (str[x] != exp[y]))
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart PoetteringAPI_EXPORT(int) ap_strcasecmp_match(const char *str, const char *exp)
e2cc6eca73cd1df8be552d7c23f9ff3d69c06f1eLennart Poettering for (x = 0, y = 0; exp[y]; ++y, ++x) {
7b77ed8cf36e8eca6017791626044b61ae2d68e7Lennart Poettering if ((ret = ap_strcasecmp_match(&str[x++], &exp[y])) != 1)
7b77ed8cf36e8eca6017791626044b61ae2d68e7Lennart Poettering else if ((exp[y] != '?') && (ap_tolower(str[x]) != ap_tolower(exp[y])))
e2cc6eca73cd1df8be552d7c23f9ff3d69c06f1eLennart PoetteringAPI_EXPORT(int) ap_is_matchexp(const char *str)
2d62c530d2b4c2730abff715b7342f1402114513Lennart Poettering register int x;
2d62c530d2b4c2730abff715b7342f1402114513Lennart Poettering for (x = 0; str[x]; x++)
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering * Here's a pool-based interface to POSIX regex's regcomp().
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering * Note that we return regex_t instead of being passed one.
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering * The reason is that if you use an already-used regex_t structure,
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering * the memory that you've already allocated gets forgotten, and
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering * regfree() doesn't clear it. So we don't allow it.
cc3773810855956bad92337cee8fa193584ab62eLennart Poetteringstatic ap_status_t regex_cleanup(void *preg)
cc3773810855956bad92337cee8fa193584ab62eLennart PoetteringAPI_EXPORT(regex_t *) ap_pregcomp(ap_context_t *p, const char *pattern,
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering regex_t *preg = ap_palloc(p, sizeof(regex_t));
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering ap_register_cleanup(p, (void *) preg, regex_cleanup, regex_cleanup);
cc3773810855956bad92337cee8fa193584ab62eLennart PoetteringAPI_EXPORT(void) ap_pregfree(ap_context_t *p, regex_t * reg)
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering ap_kill_cleanup(p, (void *) reg, regex_cleanup);
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering * Apache stub function for the regex libraries regexec() to make sure the
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering * whole regex(3) API is available through the Apache (exported) namespace.
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering * This is especially important for the DSO situations of modules.
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering * DO NOT MAKE A MACRO OUT OF THIS FUNCTION!
2d62c530d2b4c2730abff715b7342f1402114513Lennart PoetteringAPI_EXPORT(int) ap_regexec(const regex_t *preg, const char *string,
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering size_t nmatch, regmatch_t pmatch[], int eflags)
65b5116220a8ebf8a260716152409aa05377aaccLennart Poettering return regexec(preg, string, nmatch, pmatch, eflags);
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart PoetteringAPI_EXPORT(size_t) ap_regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering return regerror(errcode, preg, errbuf, errbuf_size);
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering/* This function substitutes for $0-$9, filling in regular expression
2d62c530d2b4c2730abff715b7342f1402114513Lennart Poettering * submatches. Pass it the same nmatch and pmatch arguments that you
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering * passed ap_regexec(). pmatch should not be greater than the maximum number
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering * of subexpressions - i.e. one more than the re_nsub member of regex_t.
65b5116220a8ebf8a260716152409aa05377aaccLennart Poettering * input should be the string with the $-expressions, source should be the
int len;
if (!source)
return NULL;
if (!nmatch)
len = 0;
no = 0;
c = *src++;
len++;
no = 0;
c = *src++;
*dst++ = c;
return dest;
s = d = name;
#ifdef WIN32
memcpy(d, s, l);
char *res;
return res;
return ap_pstrdup(p, s);
for (x = 0, n = 0; path[x]; x++)
if (x == NULL) {
char *res;
if (!pos) {
return res;
++pos;
return res;
char *res;
for (x = 0; (*line)[x]; x++) {
pos = x;
return res;
++pos;
return res;
char *res;
if (!pos) {
return res;
++pos;
return res;
for (i = 0; i < len; ++i) {
return result;
char *res;
char quote;
++str;
if (!*str) {
++strend;
++strend;
++strend;
++strend;
return res;
#ifdef DEBUG
char ch;
return ch;
return (int)EOF;
return buf;
return NULL;
return APR_EBADF;
name);
return APR_EACCES;
#ifdef DEBUG
return stat;
return stat;
name);
return APR_EBADF;
return APR_SUCCESS;
void *param,
#ifdef DEBUG
return new_cfg;
return ch;
char *cp;
cp++;
cp--;
cp--;
cp--;
++src;
#ifdef DEBUG_CFG_LINES
register size_t i = 0;
if (c == EOF)
if (c == CR) {
if (c == LF) {
#ifdef DEBUG_CFG_LINES
buf[i] = c;
const unsigned char *token;
++ptr;
++ptr) {
if (in_qpair) {
in_qpair = 0;
switch (*ptr) {
++in_com;
--in_com;
return NULL;
++ptr;
return (const char *)token;
const char *tok_start;
const unsigned char *ptr;
unsigned char *pos;
char *token;
return NULL;
++ptr) {
if (in_qpair) {
in_qpair = 0;
switch (*ptr) {
addspace = 0;
addspace = 0;
++in_com;
addspace = 0;
--in_com;
addspace = 0;
addspace = 0;
return token;
const unsigned char *pos;
++ptr;
if (*ptr)
++ptr) {
if (in_qpair) {
in_qpair = 0;
if (good)
switch (*ptr) {
addspace = 0;
addspace = 0;
++in_com;
addspace = 0;
--in_com;
addspace = 0;
default : if (!good)
addspace = 0;
return good;
const char *tok_start;
char *token;
int tok_len;
++ptr;
while (*ptr)
++ptr;
return token;
const unsigned char *start_token;
if (!line)
s = (const unsigned char *)line;
start_token = s;
if (!line)
if ((lidx < 0) ||
char *cmd;
d = (unsigned char *)cmd;
s = (const unsigned char *)str;
return cmd;
register char digit;
#ifndef CHARSET_EBCDIC
return (digit);
badesc = 0;
badpath = 0;
if (y == NULL) {
return OK;
if (badesc)
return BAD_REQUEST;
else if (badpath)
return NOT_FOUND;
return OK;
return where;
const unsigned char *s = (const unsigned char *)segment;
unsigned char *d = (unsigned char *)copy;
d = c2x(c, d);
return copy;
const unsigned char *s = (const unsigned char *)path;
unsigned char *d = (unsigned char *)copy;
if (!partial) {
d = c2x(c, d);
return copy;
return ap_pstrndup(p, s, i);
const char *src2)
#ifndef HAVE_STRDUP
char *sdup;
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "Ouch! Out of memory in our strdup()!");
return NULL;
return sdup;
#ifndef HAVE_STRCASECMP
int strcasecmp(const char *a, const char *b)
if (diff)
return diff;
#ifndef HAVE_STRNCASECMP
int strncasecmp(const char *a, const char *b, int n)
int diff;
if (diff)
return diff;
#ifndef HAVE_STRSTR
return(s1);
return(s1);
s1++;
return(s1);
#ifndef HAVE_INITGROUPS
#if defined(QNX) || defined(MPE) || defined(BEOS) || defined(_OSD_POSIX) || defined(TPF) || defined(__TANDEM)
struct group *g;
int index = 0;
setgrent();
char **names;
endgrent();
#ifndef HAVE_WAITPID
int tmp_pid;
return tmp_pid;
while (*str) {
++str;
#ifdef WIN32
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "%s: bad user name %s", ap_server_argv0, name);
#ifdef WIN32
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "%s: bad group name %s", ap_server_argv0, name);
unsigned long my_addr;
*ports = 0;
if (p != NULL)
if (p != NULL)
if (p != NULL)
return my_addr;
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "Cannot resolve host name %s --- exiting!", w);
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "Host %s has multiple addresses ---", w);
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "you must choose one explicitly for use as");
if (p != NULL)
for (x = 0; p->h_aliases[x]; ++x) {
return NULL;
#ifndef MAXHOSTNAMELEN
char *server_hostname;
struct hostent *p;
#ifdef BEOS
return server_hostname;
/* simple 'pool' alloc()ing glue to ap_base64.c
char *decoded;
return decoded;
char *encoded;
return encoded;
#ifdef OS2
int loop;
int offset;
offset = 0;
int num_quotes = 0;
int len = 0;
while (*str) {
*dest = 0;
return quote_doubled_str;
#ifndef HAVE_STRERROR
extern char *const sys_errlist[];
char *semi;
if (semi) {
while (*str) {
++str;
if (semi) {
int newlen = 0;
newlen++;
newlen++;
inchr++;
newlen++;
inchr++;
return outstring;