httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From c...@hyperreal.org
Subject cvs commit: apache-apr/apr/lib Makefile.in apr_cpystrn.c apr_execve.c apr_fnmatch.c apr_md5.c apr_signal.c apr_slack.c apr_snprintf.c
Date Wed, 24 Mar 1999 18:39:14 GMT
coar        99/03/24 10:39:13

  Added:       apr      .cvsignore configure.in
               apr/include .cvsignore apr_config.h.in apr_fnmatch.h
                        apr_lib.h apr_md5.h
               apr/lib  Makefile.in apr_cpystrn.c apr_execve.c
                        apr_fnmatch.c apr_md5.c apr_signal.c apr_slack.c
                        apr_snprintf.c
  Log:
  	First barely-partial cut at starting libapr (based on libap),
  	by someone learning autoconf as he goes along..
  
  Revision  Changes    Path
  1.1                  apache-apr/apr/.cvsignore
  
  Index: .cvsignore
  ===================================================================
  Makefile
  Makefile.tmpl
  configure
  config.log
  config.status
  config.cache
  
  
  
  1.1                  apache-apr/apr/configure.in
  
  Index: configure.in
  ===================================================================
   dnl Process this file with autoconf to produce a configure script.
  AC_INIT(configure.in)
  
  AC_CONFIG_HEADER(include/apr_config.h)
  
  AC_ARG_WITH(optim,[  --with-optim="FLAGS"      compiler optimisation flags],
  	[OPTIM="$withval"])
  
  dnl Checks for programs.
  AC_PROG_RANLIB
  
  dnl Checks for libraries.
  SYS_HW=`(uname -m) 2>/dev/null` || SYS_HW="unknown"
  SYS_VER=`(uname -v) 2>/dev/null` || SYS_VER="unknown"
  SYS_SW=`(uname -s) 2>/dev/null` || SYS_SW="unknown"
  SYS_REL=`(uname -r) 2>/dev/null` || SYS_REL="unknown"
  
  if (echo "$SYS_SW" | grep -qi 'Linux'); then
      SYS_KV=`echo $SYS_REL | awk -F. '{printf "%s%s", $1, $2}'`
      LDLIBS="$LDLIBS -ldl"
      PLATFORM="-DLINUX=$SYS_KV"
  fi
  
  if test "$SYS_SW" = "AIX"; then
      SYS_KV=`(oslevel) 2>/dev/null` || SYS_KV="0.0.0.0"
      SYS_KV=`echo $SYS_KV | awk -F. '{printf "%s%s%s", $1, $2, $3}'`
      PLATFORM="-DAIX=$SYS_KV"
  fi
  
  dnl Checks for header files.
  AC_HEADER_STDC
  
  AC_CHECK_HEADERS(crypt.h)
  AC_CHECK_HEADERS(ctype.h)
  AC_CHECK_HEADERS(dir.h)
  AC_CHECK_HEADERS(dirent.h)
  AC_CHECK_HEADERS(errno.h)
  AC_CHECK_HEADERS(net/errno.h)
  AC_CHECK_HEADERS(fcntl.h)
  AC_CHECK_HEADERS(features.h)
  AC_CHECK_HEADERS(grp.h)
  AC_CHECK_HEADERS(io.h)
  AC_CHECK_HEADERS(limits.h)
  AC_CHECK_HEADERS(malloc.h)
  AC_CHECK_HEADERS(math.h)
  AC_CHECK_HEADERS(memory.h)
  AC_CHECK_HEADERS(netdb.h)
  AC_CHECK_HEADERS(osreldate.h)
  AC_CHECK_HEADERS(process.h)
  AC_CHECK_HEADERS(pwd.h)
  AC_CHECK_HEADERS(setjmp.h)
  AC_CHECK_HEADERS(signal.h)
  AC_CHECK_HEADERS(stdarg.h)
  AC_CHECK_HEADERS(stddef.h)
  AC_CHECK_HEADERS(stdio.h)
  AC_CHECK_HEADERS(stdlib.h)
  AC_CHECK_HEADERS(string.h)
  AC_CHECK_HEADERS(sysapi.h)
  AC_CHECK_HEADERS(sysgtime.h)
  AC_CHECK_HEADERS(time.h)
  AC_CHECK_HEADERS(sys/time.h)
  AC_CHECK_HEADERS(sys/times.h)
  AC_CHECK_HEADERS(tpfeq.h)
  AC_CHECK_HEADERS(tpfio.h)
  AC_CHECK_HEADERS(unistd.h)
  AC_CHECK_HEADERS(unix.h)
  AC_CHECK_HEADERS(winsock.h)
  
  AC_CHECK_HEADERS(arpa/inet.h)
  AC_CHECK_HEADERS(netinet/in.h)
  
  AC_CHECK_HEADERS(sys/file.h)
  AC_CHECK_HEADERS(sys/ioctl.h)
  AC_CHECK_HEADERS(sys/mman.h)
  AC_CHECK_HEADERS(sys/param.h)
  AC_CHECK_HEADERS(sys/resource.h)
  AC_CHECK_HEADERS(sys/select.h)
  AC_CHECK_HEADERS(sys/socket.h)
  AC_CHECK_HEADERS(sys/stat.h)
  AC_CHECK_HEADERS(sys/types.h)
  AC_CHECK_HEADERS(sys/wait.h)
  
  dnl Checks for typedefs, structures, and compiler characteristics.
  AC_C_CONST
  AC_TYPE_SIZE_T
  AC_FUNC_MMAP
  AC_FUNC_SETPGRP
  
  dnl Checks for library functions.
  
  AC_SUBST(LDLIBS)
  AC_SUBST(OPTIM)
  AC_SUBST(PLATFORM)
  AC_OUTPUT(lib/Makefile)
  
  
  
  1.1                  apache-apr/apr/include/.cvsignore
  
  	<<Binary file>>
  
  
  1.1                  apache-apr/apr/include/apr_config.h.in
  
  Index: apr_config.h.in
  ===================================================================
  /*
   * Start..
   */
  #ifndef APR_CONFIG_H
  #define APR_CONFIG_H
  
  /*
   * Just in case someone's building with a C++ compiler, isolate our
   * work appropriately.
   */
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  /*
   * List of header files which exist for this platform.
   */
  #undef HAVE_CRYPT_H
  #undef HAVE_CTYPE_H
  #undef HAVE_DIR_H
  #undef HAVE_DIRENT_H
  #undef HAVE_ERRNO_H
  #undef HAVE_NET_ERRNO_H
  #undef HAVE_FCNTL_H
  #undef HAVE_FEATURES_H
  #undef HAVE_GRP_Ho
  #undef HAVE_IO_H
  #undef HAVE_LIMITS_H
  #undef HAVE_MALLOC_H
  #undef HAVE_MATH_H
  #undef HAVE_MEMORY_H
  #undef HAVE_NETDB_H
  #undef HAVE_OSRELDATE_H
  #undef HAVE_PROCESS_H
  #undef HAVE_PWD_H
  #undef HAVE_SETJMP_H
  #undef HAVE_SIGNAL_H
  #undef HAVE_STDARG_H
  #undef HAVE_STDDEF_H
  #undef HAVE_STDIO_H
  #undef HAVE_STDLIB_H
  #undef HAVE_STRING_H
  #undef HAVE_SYSAPI_H
  #undef HAVE_SYSGTIME_H
  #undef HAVE_TIME_H
  #undef HAVE_SYS_TIME_H
  #undef HAVE_SYS_TIMES_H
  #undef HAVE_TPFEQ_H
  #undef HAVE_TPFIO_H
  #undef HAVE_UNISTD_H
  #undef HAVE_UNIX_H
  #undef HAVE_WINSOCK_H
  
  #undef HAVE_ARPA_INET_H
  #undef HAVE_NETINET_IN_H
  
  #undef HAVE_SYS_FILE_H
  #undef HAVE_SYS_IOCTL_H
  #undef HAVE_SYS_MMAN_H
  #undef HAVE_SYS_PARAM_H
  #undef HAVE_SYS_RESOURCE_H
  #undef HAVE_SYS_SELECT_H
  #undef HAVE_SYS_SOCKET_H
  #undef HAVE_SYS_STAT_H
  #undef HAVE_SYS_TYPES_H
  #undef HAVE_SYS_WAIT_H
  
  /*
   * List of features/library functions available, which we'll use if
   * they're compatible.
   */
  #undef HAVE_MMAP
  
  #define API_EXPORT(type) type
  
  /*
   * We now know what we have, so make use of it.
   */
  
  #ifdef HAVE_CRYPT_H
  #include <crypt.h>
  #endif
  
  #ifdef HAVE_CTYPE_H
  #include <ctype.h>
  #endif
  
  #ifdef HAVE_DIR_H
  #include <dir.h>
  #endif
  
  #ifdef HAVE_DIRENT_H
  #include <dirent.h>
  #endif
  
  #ifdef HAVE_ERRNO_H
  #include <errno.h>
  #endif
  
  #ifdef HAVE_NET_ERRNO_H
  #include <net/errno.h>
  #endif
  
  #ifdef HAVE_FCNTL_H
  #include <fcntl.h>
  #endif
  
  #ifdef HAVE_GRP_H
  #include <grp.h>
  #endif
  
  #ifdef HAVE_IO_H
  #include <io.h>
  #endif
  
  #ifdef HAVE_LIMITS_H
  #include <limits.h>
  #endif
  
  #ifdef HAVE_MALLOC_H
  #include <malloc.h>
  #endif
  
  #ifdef HAVE_MATH_H
  #include <math.h>
  #endif
  
  #ifdef HAVE_MEMORY_H
  #include <memory.h>
  #endif
  
  #ifdef HAVE_NETDB_H
  #include <netdb.h>
  #endif
  
  
  #ifdef HAVE_PROCESS_H
  #include <process.h>
  #endif
  
  #ifdef HAVE_PWD_H
  #include <pwd.h>
  #endif
  
  #ifdef HAVE_SETJMP_H
  #include <setjmp.h>
  #endif
  
  #ifdef HAVE_SIGNAL_H
  #include <signal.h>
  #endif
  
  #ifdef HAVE_STDARG_H
  #include <stdarg.h>
  #endif
  
  #ifdef HAVE_STDDEF_H
  #include <stddef.h>
  #endif
  
  #ifdef HAVE_STDIO_H
  #include <stdio.h>
  #endif
  
  #ifdef HAVE_STDLIB_H
  #include <stdlib.h>
  #endif
  
  #ifdef HAVE_STRING_H
  #include <string.h>
  #endif
  
  #ifdef TPF
  #ifdef HAVE_TPFEQ_H
  #include <tpfeq.h>
  #endif
  #ifdef HAVE_TPFIO_H
  #include <tpfio.h>
  #endif
  #ifdef HAVE_OSRELDATE_H
  #include <osreldate.h>
  #endif
  #ifdef HAVE_SYSAPI_H
  #include <sysapi.h>
  #endif
  #ifdef HAVE_SYSGTIME_H
  #include <sysgtime.h>
  #endif
  #endif /* TPF */
  
  #ifdef HAVE_TIME_H
  #include <time.h>
  #endif
  
  #ifdef HAVE_SYS_TIME_H
  #include <sys/time.h>
  #endif
  
  #ifdef HAVE_SYS_TIMES_H
  #include <sys/times.h>
  #endif
  
  #ifdef HAVE_UNISTD_H
  #include <unistd.h>
  #endif
  
  #ifdef HAVE_UNIX_H
  #include <unix.h>
  #endif
  
  #ifdef HAVE_ARPA_INET_H
  #include <arpa/inet.h>
  #endif
  
  #ifdef HAVE_NETINET_IN_H
  #include <netinet/in.h>
  #endif
  
  #ifdef HAVE_SYS_FILE_H
  #include <sys/file.h>
  #endif
  
  #ifdef HAVE_SYS_IOCTL_H
  #include <sys/ioctl.h>
  #endif
  
  #ifdef HAVE_SYS_MMAN_H
  #include <sys/mman.h>
  #endif
  
  #ifdef HAVE_SYS_PARAM_H
  #include <sys/param.h>
  #endif
  
  #ifdef HAVE_SYS_RESOURCE_H
  #include <sys/resource.h>
  #endif
  
  #ifdef HAVE_SYS_SELECT_H
  #include <sys/select.h>
  #endif
  
  #ifdef HAVE_SYS_SOCKET_H
  #include <sys/socket.h>
  #endif
  
  #ifdef HAVE_SYS_STAT_H
  #include <sys/stat.h>
  #endif
  
  #ifdef HAVE_SYS_TYPES_H
  #include <sys/types.h>
  #endif
  
  #ifdef HAVE__SYS_WAIT_H
  #include <sys/wait.h>
  #endif
  
  /*
   * Platform-specific definitions.
   */
  #ifdef _OSD_POSIX
  #define NEED_HASHBANG_EMUL
  #undef bzero
  #endif /* _OSD_POSIX */
  
  #ifdef UTS21
  #define NEED_HASHBANG_EMUL
  #define NO_USE_SIGACTION
  #endif
  
  #ifdef TPF
  #define NO_USE_SIGACTION
  #define NO_SLACK
  #endif
  
  #ifdef LYNXOS
  #define NO_USE_SIGACTION
  #endif
  
  #ifdef __MACHTEN__
  #define NO_USE_SIGACTION
  #endif
  
  #ifdef NEWOS
  #define NO_USE_SIGACTION
  #endif
  
  #ifdef RISCIX
  #define NO_USE_SIGACTION
  #endif
  
  #ifdef MPE
  #define NO_SLACK
  #endif
  
  #ifdef AUX3
  #define NO_SLACK
  #endif
  
  #ifdef NEXT
  #define NO_USE_SIGACTION
  #endif
  /*
   * IF we're on a Linux platform, AND the kernel is 2.0 or later, AND
   * we have the features.h header file available, include it.
   */
  #ifdef LINUX
  #if (LINUX >= 20) && defined(HAVE_FEATURES_H)
  #include <features.h>
  #endif
  #endif
  
  /*
   * Now things that are dependent upon our derived platform settings.
   */
  #ifdef NEED_HASHBANG_MULTI
  extern int apr_execle(const char *filename, const char *arg,...);
  extern int apr_execve(const char *filename, const char *argv[],
  		      const char *envp[]);
  /*
   * apr_execle() is a wrapper function around apr_execve().
   */
  #define execle  apr_execle
  #define execve(path,argv,envp)  apr_execve(path,argv,envp)
  #endif
  
  #ifdef CHARSET_EBCDIC
  #include "ebcdic.h"
  #endif
  
  #ifndef NO_USE_SIGACTION
  /*
   * Replace signal function with sigaction equivalent
   */
  typedef void Sigfunc(int);
  
  #if defined(SIG_IGN) && !defined(SIG_ERR)
  #define SIG_ERR ((Sigfunc *)-1)
  #endif
  
  /*
   * For some strange reason, QNX defines signal to signal. Eliminate it.
   */
  #ifdef signal
  #undef signal
  #endif
  #define signal(s,f)     apr_signal(s,f)
  Sigfunc *signal(int signo, Sigfunc * func);
  #endif /* NO_USE_SIGACTION */
  
  /*
   * Reserve some filehandles to workaround problems in many
   * third party libraries that are compiled with a small FD_SETSIZE.  There
   * should be no reason to lower this, because it's only advisory.  If a file
   * can't be allocated above this number then it will remain in the "slack"
   * area.
   *
   * Only the low slack line is used by default.  If HIGH_SLACK_LINE is defined
   * then an attempt is also made to keep all non-FILE * files above the high
   * slack line.  This is to work around a Solaris C library limitation, where it
   * uses an unsigned char to store the file descriptor.
   */
  #ifndef LOW_SLACK_LINE
  #define LOW_SLACK_LINE  15
  #endif
  /* #define HIGH_SLACK_LINE      255 */
  
  /*
   * The apr_slack() function takes a fd, and tries to move it above the
   * indicated line.  It returns an fd which may or may not have moved
   * above the line, and never fails.  If the high line was requested
   * and it fails it will also try the low line.
   */
  #ifdef NO_SLACK
  #define apr_slack(fd,line)   (fd)
  #else
  int apr_slack(int fd, int line);
  #define APR_SLACK_LOW    1
  #define APR_SLACK_HIGH   2
  #endif
  
  /*
   * Close up the C++ enclosure.
   */
  #ifdef __cplusplus
  }
  #endif
  
  /*
   * End..
   */
  #endif  /* ! APR_CONFIG_H */
  
  
  
  1.1                  apache-apr/apr/include/apr_fnmatch.h
  
  Index: apr_fnmatch.h
  ===================================================================
  /*-
   * Copyright (c) 1992, 1993
   *	The Regents of the University of California.  All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in the
   *    documentation and/or other materials provided with the distribution.
   * 3. All advertising materials mentioning features or use of this software
   *    must display the following acknowledgement:
   *	This product includes software developed by the University of
   *	California, Berkeley and its contributors.
   * 4. Neither the name of the University nor the names of its contributors
   *    may be used to endorse or promote products derived from this software
   *    without specific prior written permission.
   *
   * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   *
   *	@(#)fnmatch.h	8.1 (Berkeley) 6/2/93
   */
  
  /* This file has been modified by the Apache Group. */
  
  #include "apr_config.h"
  
  #ifndef	_APR_FNMATCH_H_
  #define	_APR_FNMATCH_H_
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  #define	FNM_NOMATCH	1	/* Match failed. */
  
  #define	FNM_NOESCAPE	0x01	/* Disable backslash escaping. */
  #define	FNM_PATHNAME	0x02	/* Slash must be matched by slash. */
  #define	FNM_PERIOD	0x04	/* Period must be matched by period. */
  /* This flag is an Apache addition */
  #define FNM_CASE_BLIND  0x08    /* Compare characters case-insensitively. */
  
  API_EXPORT(int) apr_fnmatch(const char *pattern, const char *strings,
  			    int flags);
  
  /* this function is an Apache addition */
  API_EXPORT(extern int) ap_is_fnmatch(const char *pattern);
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif /* !_FNMATCH_H_ */
  
  
  
  1.1                  apache-apr/apr/include/apr_lib.h
  
  Index: apr_lib.h
  ===================================================================
  /* ====================================================================
   * Copyright (c) 1998-1999 The Apache Group.  All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. All advertising materials mentioning features or use of this
   *    software must display the following acknowledgment:
   *    "This product includes software developed by the Apache Group
   *    for use in the Apache HTTP server project (http://www.apache.org/)."
   *
   * 4. The names "Apache Server" and "Apache Group" must not be used to
   *    endorse or promote products derived from this software without
   *    prior written permission. For written permission, please contact
   *    apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * 6. Redistributions of any form whatsoever must retain the following
   *    acknowledgment:
   *    "This product includes software developed by the Apache Group
   *    for use in the Apache HTTP server project (http://www.apache.org/)."
   *
   * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
   * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
   * OF THE POSSIBILITY OF SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Group and was originally based
   * on public domain software written at the National Center for
   * Supercomputing Applications, University of Illinois, Urbana-Champaign.
   * For more information on the Apache Group and the Apache HTTP server
   * project, please see <http://www.apache.org/>.
   *
   * The apr_vsnprintf/apr_snprintf functions are based on, and used with the
   * permission of, the  SIO stdio-replacement strx_* functions by Panos
   * Tsirigotis <panos@alumni.cs.colorado.edu> for xinetd.
   */
  
  #ifndef APR_LIB_H
  #define APR_LIB_H
  
  #include "apr_config.h"
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  API_EXPORT(char *) apr_cpystrn(char *, const char *, size_t);
  int apr_slack(int, int);
  int apr_execle(const char *, const char *, ...);
  int apr_execve(const char *, const char *argv[], const char *envp[]);
  
  /* small utility macros to make things easier to read */
  
  #ifdef WIN32
  #define apr_killpg(x, y)
  #else
  #ifdef NO_KILLPG
  #define apr_killpg(x, y)		(kill (-(x), (y)))
  #else
  #define apr_killpg(x, y)		(killpg ((x), (y)))
  #endif
  #endif /* WIN32 */
  
  /* apr_vformatter() is a generic printf-style formatting routine
   * with some extensions.  The extensions are:
   *
   * %pA	takes a struct in_addr *, and prints it as a.b.c.d
   * %pI	takes a struct sockaddr_in * and prints it as a.b.c.d:port
   * %pp  takes a void * and outputs it in hex
   *
   * The %p hacks are to force gcc's printf warning code to skip
   * over a pointer argument without complaining.  This does
   * mean that the ANSI-style %p (output a void * in hex format) won't
   * work as expected at all, but that seems to be a fair trade-off
   * for the increased robustness of having printf-warnings work.
   *
   * Additionally, apr_vformatter allows for arbitrary output methods
   * using the apr_vformatter_buff and flush_func.
   *
   * The apr_vformatter_buff has two elements curpos and endpos.
   * curpos is where apr_vformatter will write the next byte of output.
   * It proceeds writing output to curpos, and updating curpos, until
   * either the end of output is reached, or curpos == endpos (i.e. the
   * buffer is full).
   *
   * If the end of output is reached, apr_vformatter returns the
   * number of bytes written.
   *
   * When the buffer is full, the flush_func is called.  The flush_func
   * can return -1 to indicate that no further output should be attempted,
   * and apr_vformatter will return immediately with -1.  Otherwise
   * the flush_func should flush the buffer in whatever manner is
   * appropriate, re-initialize curpos and endpos, and return 0.
   *
   * Note that flush_func is only invoked as a result of attempting to
   * write another byte at curpos when curpos >= endpos.  So for
   * example, it's possible when the output exactly matches the buffer
   * space available that curpos == endpos will be true when
   * apr_vformatter returns.
   *
   * apr_vformatter does not call out to any other code, it is entirely
   * self-contained.  This allows the callers to do things which are
   * otherwise "unsafe".  For example, apr_psprintf uses the "scratch"
   * space at the unallocated end of a block, and doesn't actually
   * complete the allocation until apr_vformatter returns.  apr_psprintf
   * would be completely broken if apr_vformatter were to call anything
   * that used a apr_pool_t.  Similarly http_bprintf() uses the "scratch"
   * space at the end of its output buffer, and doesn't actually note
   * that the space is in use until it either has to flush the buffer
   * or until apr_vformatter returns.
   */
  
  typedef struct apr_vformatter_buff_t {
      char *curpos;
      char *endpos;
  } apr_vformatter_buff_t;
  
  API_EXPORT(int) apr_vformatter(int (*flush_func)(apr_vformatter_buff_t *b),
  			       apr_vformatter_buff_t *, const char *fmt,
  			       va_list ap);
  
  /* These are snprintf implementations based on apr_vformatter().
   *
   * Note that various standards and implementations disagree on the return
   * value of snprintf, and side-effects due to %n in the formatting string.
   * apr_snprintf behaves as follows:
   *
   * Process the format string until the entire string is exhausted, or
   * the buffer fills.  If the buffer fills then stop processing immediately
   * (so no further %n arguments are processed), and return the buffer
   * length.  In all cases the buffer is NUL terminated.
   *
   * In no event does apr_snprintf return a negative number.  It's not possible
   * to distinguish between an output which was truncated, and an output which
   * exactly filled the buffer.
   */
  API_EXPORT(int) apr_snprintf(char *buf, size_t len, const char *format, ...)
  	__attribute__((format(printf,3,4)));
  API_EXPORT(int) apr_vsnprintf(char *buf, size_t len, const char *format,
  			      va_list ap);
  
  /*
   * Pool stuff.
   */
  typedef struct apr_pool_t apr_pool_t;
  typedef struct apr_mutex_t apr_mutex_t;
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif	/* ! APR_LIB_H */
  
  
  
  1.1                  apache-apr/apr/include/apr_md5.h
  
  Index: apr_md5.h
  ===================================================================
  /*
   * This is work is derived from material Copyright RSA Data Security, Inc.
   *
   * The RSA copyright statement and Licence for that original material is
   * included below. This is followed by the Apache copyright statement and
   * licence for the modifications made to that material.
   */
  
  /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
     rights reserved.
  
     License to copy and use this software is granted provided that it
     is identified as the "RSA Data Security, Inc. MD5 Message-Digest
     Algorithm" in all material mentioning or referencing this software
     or this function.
  
     License is also granted to make and use derivative works provided
     that such works are identified as "derived from the RSA Data
     Security, Inc. MD5 Message-Digest Algorithm" in all material
     mentioning or referencing the derived work.
  
     RSA Data Security, Inc. makes no representations concerning either
     the merchantability of this software or the suitability of this
     software for any particular purpose. It is provided "as is"
     without express or implied warranty of any kind.
  
     These notices must be retained in any copies of any part of this
     documentation and/or software.
   */
  
  /* ====================================================================
   * Copyright (c) 1996-1999 The Apache Group.  All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. All advertising materials mentioning features or use of this
   *    software must display the following acknowledgment:
   *    "This product includes software developed by the Apache Group
   *    for use in the Apache HTTP server project (http://www.apache.org/)."
   *
   * 4. The names "Apache Server" and "Apache Group" must not be used to
   *    endorse or promote products derived from this software without
   *    prior written permission. For written permission, please contact
   *    apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * 6. Redistributions of any form whatsoever must retain the following
   *    acknowledgment:
   *    "This product includes software developed by the Apache Group
   *    for use in the Apache HTTP server project (http://www.apache.org/)."
   *
   * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
   * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
   * OF THE POSSIBILITY OF SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Group and was originally based
   * on public domain software written at the National Center for
   * Supercomputing Applications, University of Illinois, Urbana-Champaign.
   * For more information on the Apache Group and the Apache HTTP server
   * project, please see <http://www.apache.org/>.
   *
   */
  
  #ifndef APACHE_MD5_H
  #define APACHE_MD5_H
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  /* MD5.H - header file for MD5C.C */
  
  /* UINT4 defines a four byte word */
  typedef unsigned int UINT4;
  
  /* MD5 context. */
  typedef struct {
      UINT4 state[4];		/* state (ABCD) */
      UINT4 count[2];		/* number of bits, modulo 2^64 (lsb first) */
      unsigned char buffer[64];	/* input buffer */
  } APR_MD5_CTX;
  
  API_EXPORT(void) apr_MD5Init(APR_MD5_CTX * context);
  API_EXPORT(void) apr_MD5Update(APR_MD5_CTX * context, const unsigned char *input,
  			   unsigned int inputLen);
  API_EXPORT(void) apr_MD5Final(unsigned char digest[16], APR_MD5_CTX * context);
  API_EXPORT(void) apr_MD5Encode(const char *password, const char *salt,
  			      char *result, size_t nbytes);
  API_EXPORT(char *) apr_validate_password(const char *passwd, const char *hash);
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif	/* !APACHE_MD5_H */
  
  
  
  1.1                  apache-apr/apr/lib/Makefile.in
  
  Index: Makefile.in
  ===================================================================
  #CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
  #LIBS=$(EXTRA_LIBS) $(LIBS1)
  #INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
  #LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
  
  CFLAGS=@PLATFORM@ @CFLAGS@ @OPTIM@
  LDLIBS=@LDLIBS@
  LDFLAGS=@LDFLAGS@ $(LDLIBS)
  INCDIR=../include
  INCLUDES=-I$(INCDIR)
  
  LIB=libapr.a
  
  #OBJS=ap_execve.o ap_cpystrn.o ap_signal.o \
  #     ap_slack.o ap_snprintf.o ap_fnmatch.o ap_md5c.o
  
  OBJS=apr_cpystrn.o \
  	apr_fnmatch.o \
  	apr_execve.o \
  	apr_md5.o \
  	apr_signal.o \
  	apr_slack.o \
  	apr_snprintf.o
  
  .c.o:
  	$(CC) $(CFLAGS) -c $(INCLUDES) $<
  
  all: $(LIB)
  
  clean:
  	$(RM) -f *.o *.a *.so
  
  distclean: clean
  	-$(RM) -f Makefile
  
  $(OBJS): Makefile
  
  $(LIB): $(OBJS)
  	$(RM) -f $@
  	$(AR) cr $@ $(OBJS)
  	@RANLIB@ $@
  
  # We really don't expect end users to use this rule.  It works only with
  # gcc, and rebuilds Makefile.tmpl.  You have to re-run Configure after
  # using it.
  depend:
  	cp Makefile.in Makefile.in.bak \
  	    && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.in > Makefile.new \
  	    && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
  	    && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
  	           -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
  		> Makefile.in \
  	    && rm Makefile.new
  
  # DO NOT REMOVE
  apr_cpystrn.o: apr_cpystrn.c $(INCDIR)/apr_config.h
  apr_execve.o: apr_execve.c $(INCDIR)/apr_config.h
  apr_fnmatch.o: apr_fnmatch.c $(INCDIR)/apr_config.h \
   $(INCDIR)/apr_fnmatch.h
  apr_md5c.o: apr_md5c.c $(INCDIR)/apr_config.h \
   $(INCDIR)/apr_md5.h $(INCDIR)/apr_lib.h
  apr_signal.o: apr_signal.c $(INCDIR)/apr_config.h
  apr_slack.o: apr_slack.c $(INCDIR)/apr_config.h
  apr_snprintf.o: apr_snprintf.c $(INCDIR)/apr_config.h \
   $(INCDIR)/apr_lib.h
  
  
  
  1.1                  apache-apr/apr/lib/apr_cpystrn.c
  
  Index: apr_cpystrn.c
  ===================================================================
  /* ====================================================================
   * Copyright (c) 1995-1999 The Apache Group.  All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. All advertising materials mentioning features or use of this
   *    software must display the following acknowledgment:
   *    "This product includes software developed by the Apache Group
   *    for use in the Apache HTTP server project (http://www.apache.org/)."
   *
   * 4. The names "Apache Server" and "Apache Group" must not be used to
   *    endorse or promote products derived from this software without
   *    prior written permission. For written permission, please contact
   *    apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * 6. Redistributions of any form whatsoever must retain the following
   *    acknowledgment:
   *    "This product includes software developed by the Apache Group
   *    for use in the Apache HTTP server project (http://www.apache.org/)."
   *
   * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
   * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
   * OF THE POSSIBILITY OF SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Group and was originally based
   * on public domain software written at the National Center for
   * Supercomputing Applications, University of Illinois, Urbana-Champaign.
   * For more information on the Apache Group and the Apache HTTP server
   * project, please see <http://www.apache.org/>.
   *
   */
  
  #include "apr_config.h"
  
  /*
   * Apache's "replacement" for the strncpy() function. We roll our
   * own to implement these specific changes:
   *   (1) strncpy() doesn't always null terminate and we want it to.
   *   (2) strncpy() null fills, which is bogus, esp. when copy 8byte
   *       strings into 8k blocks.
   *   (3) Instead of returning the pointer to the beginning of
   *       the destination string, we return a pointer to the
   *       terminating '\0' to allow us to "check" for truncation
   *
   * apr_cpystrn() follows the same call structure as strncpy().
   */
  
  API_EXPORT(char *) apr_cpystrn(char *dst, const char *src, size_t dst_size)
  {
  
      char *d, *end;
  
      if (dst_size == 0) {
          return (dst);
      }
  
      d = dst;
      end = dst + dst_size - 1;
  
      for (; d < end; ++d, ++src) {
  	if (!(*d = *src)) {
  	    return (d);
  	}
      }
  
      *d = '\0';	/* always null terminate */
  
      return (d);
  }
  
  
  
  1.1                  apache-apr/apr/lib/apr_execve.c
  
  Index: apr_execve.c
  ===================================================================
  /* ====================================================================
   * Copyright (c) 1998-1999 The Apache Group.  All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. All advertising materials mentioning features or use of this
   *    software must display the following acknowledgment:
   *    "This product includes software developed by the Apache Group
   *    for use in the Apache HTTP server project (http://www.apache.org/)."
   *
   * 4. The names "Apache Server" and "Apache Group" must not be used to
   *    endorse or promote products derived from this software without
   *    prior written permission. For written permission, please contact
   *    apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * 6. Redistributions of any form whatsoever must retain the following
   *    acknowledgment:
   *    "This product includes software developed by the Apache Group
   *    for use in the Apache HTTP server project (http://www.apache.org/)."
   *
   * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
   * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
   * OF THE POSSIBILITY OF SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Group and was originally based
   * on public domain software written at the National Center for
   * Supercomputing Applications, University of Illinois, Urbana-Champaign.
   * For more information on the Apache Group and the Apache HTTP server
   * project, please see <http://www.apache.org/>.
   *
   */
  
  /*
   * Portions of this code are under this license:
   *
   * Copyright (c) 1980, 1991 The Regents of the University of California.
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in the
   *    documentation and/or other materials provided with the distribution.
   * 3. All advertising materials mentioning features or use of this software
   *    must display the following acknowledgement:
   *	This product includes software developed by the University of
   *	California, Berkeley and its contributors.
   * 4. Neither the name of the University nor the names of its contributors
   *    may be used to endorse or promote products derived from this software
   *    without specific prior written permission.
   *
   * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   */
  
  #include "apr_config.h"
  
  /*---------------------------------------------------------------*/
  
  #ifdef NEED_HASHBANG_EMUL
  
  #undef execle
  #undef execve
  
  static const char **hashbang(const char *filename, char **argv);
  
  
  /* Historically, a list of arguments on the stack was often treated as
   * being equivalent to an array (since they already were "contiguous"
   * on the stack, and the arguments were pushed in the correct order).
   * On today's processors, this is not necessarily equivalent, because
   * often arguments are padded or passed partially in registers,
   * or the stack direction is backwards.
   * To be on the safe side, we copy the argument list to our own
   * local argv[] array. The va_arg logic makes sure we do the right thing.
   * XXX: malloc() is used because we expect to be overlaid soon.
   */
  int apr_execle(const char *filename, const char *argv0, ...)
  {
      va_list adummy;
      char **envp;
      char **argv;
      int argc, ret;
  
      /* First pass: Count arguments on stack */
      va_start(adummy, argv0);
      for (argc = 1; va_arg(adummy, char *) != NULL; ++argc) {
  	continue;
      }
      va_end(adummy);
  
      if ((argv = (char **) malloc((argc + 2) * sizeof(*argv))) == NULL) {
  	fprintf(stderr, "Ouch!  Out of memory in apr_execle()!\n");
  	return -1;
      }
  
      /* Pass two --- copy the argument strings into the result space */
      va_start(adummy, argv0);
      argv[0] = argv0;
      for (argc = 1; (argv[argc] = va_arg(adummy, char *)) != NULL; ++argc) {
  	continue;
      }
      envp = va_arg(adummy, char **);
      va_end(adummy);
  
      ret = apr_execve(filename, argv, envp);
      free(argv);
  
      return ret;
  }
  
  /* Count number of entries in vector "args", including the trailing NULL entry
   */
  static int
  count_args(const char **args)
  {
      int i;
      for (i = 0; args[i] != NULL; ++i) {
  	continue;
      }
      return i+1;
  }
  
  /* Emulate the execve call, respecting a #!/interpreter line if present.
   * On "real" unixes, the kernel does this.
   * We have to fiddle with the argv array to make it work on platforms
   * which don't support the "hashbang" interpreter line by default.
   */
  int apr_execve(const char *filename, const char *argv[],
  	      const char *envp[])
  {
      const char **script_argv;
      extern char **environ;
  
      if (envp == NULL) {
  	envp = (const char **) environ;
      }
  
      /* Try to execute the file directly first: */
      execve(filename, argv, envp);
  
      /* Still with us? Then something went seriously wrong.
       * From the (linux) man page:
       * EACCES The file is not a regular file.
       * EACCES Execute permission is denied for the file.
       * EACCES Search  permission  is denied on a component of the path prefix.
       * EPERM  The file system is mounted noexec.
       * EPERM  The file system is mounted nosuid and the file  has an SUID
       *        or SGID bit set.
       * E2BIG  The argument list is too big.
       * ENOEXEC The magic number in the file is incorrect.
       * EFAULT filename  points  outside  your  accessible address space.
       * ENAMETOOLONG filename is too long.
       * ENOENT The file does not exist.
       * ENOMEM Insufficient kernel memory was available.
       * ENOTDIR A component of the path prefix is not a  directory.
       * ELOOP  filename contains a circular reference (i.e., via a symbolic link)
       */
  
      if (errno == ENOEXEC) {
  	/* Probably a script.
  	 * Have a look; if there's a "#!" header then try to emulate
  	 * the feature found in all modern OS's:
  	 * Interpret the line following the #! as a command line
  	 * in shell style.
  	 */
  	if ((script_argv = hashbang(filename, argv)) != NULL) {
  
  	    /* new filename is the interpreter to call */
  	    filename = script_argv[0];
  
  	    /* Restore argv[0] as on entry */
  	    if (argv[0] != NULL) {
  		script_argv[0] = argv[0];
  	    }
  
  	    execve(filename, script_argv, envp);
  
  	    free(script_argv);
  	}
  	/*
  	 * Script doesn't start with a hashbang line!
  	 * So, try to have the default shell execute it.
  	 * For this, the size of argv must be increased by one
  	 * entry: the shell's name. The remaining args are appended.
  	 */
  	else {
  	    int i = count_args(argv) + 1;   /* +1 for leading SHELL_PATH */
  
  	    if ((script_argv = malloc(sizeof(*script_argv) * i)) == NULL) {
  		fprintf(stderr, "Ouch!  Out of memory in apr_execve()!\n");
  		return -1;
  	    }
  
  	    script_argv[0] = SHELL_PATH;
  
  	    while (i > 0) {
  		script_argv[i] = argv[i-1];
  		--i;
  	    }
  
  	    execve(SHELL_PATH, script_argv, envp);
  
  	    free(script_argv);
  	}
      }
      return -1;
  }
  
  /*---------------------------------------------------------------*/
  
  /*
   * From: peter@zeus.dialix.oz.au (Peter Wemm)
   * (taken from tcsh)
   * If exec() fails look first for a #! [word] [word] ....
   * If it is, splice the header into the argument list and retry.
   * Return value: the original argv array (sans argv[0]), with the
   * script's argument list prepended.
   * XXX: malloc() is used so that everything can be free()ed after a failure.
   */
  #define HACKBUFSZ 1024		/* Max chars in #! vector */
  #define HACKVECSZ 128		/* Max words in #! vector */
  static const char **hashbang(const char *filename, char **argv)
  {
      char lbuf[HACKBUFSZ];
      char *sargv[HACKVECSZ];
      const char **newargv;
      char *p, *ws;
      int fd;
      int sargc = 0;
      int i, j;
  #ifdef WIN32
      int fw = 0;			/* found at least one word */
      int first_word = 0;
  #endif /* WIN32 */
  
      if ((fd = open(filename, O_RDONLY)) == -1) {
  	return NULL;
      }
  
      if (read(fd, (char *) lbuf, 2) != 2
  	|| lbuf[0] != '#' || lbuf[1] != '!'
  	|| read(fd, (char *) lbuf, HACKBUFSZ) <= 0) {
  	close(fd);
  	return NULL;
      }
  
      close(fd);
  
      ws = NULL;			/* word started = 0 */
  
      for (p = lbuf; p < &lbuf[HACKBUFSZ];) {
  	switch (*p) {
  	case ' ':
  	case '\t':
  #ifdef NEW_CRLF
  	case '\r':
  #endif /*NEW_CRLF */
  	    if (ws) {		/* a blank after a word.. save it */
  		*p = '\0';
  #ifndef WIN32
  		if (sargc < HACKVECSZ - 1) {
  		    sargv[sargc++] = ws;
  		}
  		ws = NULL;
  #else /* WIN32 */
  		if (sargc < HACKVECSZ - 1) {
  		    sargv[sargc] = first_word ? NULL : hb_subst(ws);
  		    if (sargv[sargc] == NULL) {
  			sargv[sargc] = ws;
  		    }
  		    sargc++;
  		}
  		ws = NULL;
  		fw = 1;
  		first_word = 1;
  #endif /* WIN32 */
  	    }
  	    p++;
  	    continue;
  
  	case '\0':		/* Whoa!! what the hell happened */
  	    return NULL;
  
  	case '\n':		/* The end of the line. */
  	    if (
  #ifdef WIN32
  		   fw ||
  #endif /* WIN32 */
  		   ws) {	/* terminate the last word */
  		*p = '\0';
  #ifndef WIN32
  		if (sargc < HACKVECSZ - 1) {
  		    sargv[sargc++] = ws;
  		}
  #else /* WIN32 */
  		if (sargc < HACKVECSZ - 1) {	/* deal with the 1-word case */
  		    sargv[sargc] = first_word ? NULL : hb_subst(ws);
  		    if (sargv[sargc] == NULL) {
  			sargv[sargc] = ws;
  		    }
  		    sargc++;
  		}
  #endif /* !WIN32 */
  		sargv[sargc] = NULL;
  	    }
  	    /* Count number of entries in the old argv vector */
  	    for (i = 0; argv[i] != NULL; ++i) {
  		continue;
  	    }
  	    ++i;
  
  	    newargv = (char **) malloc((p - lbuf + 1)
                        + (i + sargc + 1) * sizeof(*newargv));
  	    if (newargv == NULL) {
  		fprintf(stderr, "Ouch!  Out of memory in hashbang()!\n");
  		return NULL;
  	    }
  	    ws = &((char *) newargv)[(i + sargc + 1) * sizeof(*newargv)];
  
  	    /* Copy entries to allocated memory */
  	    for (j = 0; j < sargc; ++j) {
  		newargv[j] = strcpy(ws, sargv[j]);
  		ws += strlen(ws) + 1;	/* skip trailing '\0' */
  	    }
  	    newargv[sargc] = filename;
  
  	    /* Append the old array. The old argv[0] is skipped. */
  	    if (i > 1) {
  		memcpy(&newargv[sargc + 1], &argv[1],
                         (i - 1) * sizeof(*newargv));
  	    }
  	
  	    newargv[sargc + i] = NULL;
  
  	    ws = NULL;
  
  	    return newargv;
  
  	default:
  	    if (!ws) {		/* Start a new word? */
  		ws = p;
  	    }
  	    p++;
  	    break;
  	}
      }
      return NULL;
  }
  #else
  extern void apr_execve_is_not_here(void);
  void apr_execve_is_not_here(void) {}
  #endif /* NEED_HASHBANG_EMUL */
  
  
  
  1.1                  apache-apr/apr/lib/apr_fnmatch.c
  
  Index: apr_fnmatch.c
  ===================================================================
  /*
   * Copyright (c) 1989, 1993, 1994
   *      The Regents of the University of California.  All rights reserved.
   *
   * This code is derived from software contributed to Berkeley by
   * Guido van Rossum.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in the
   *    documentation and/or other materials provided with the distribution.
   * 3. All advertising materials mentioning features or use of this software
   *    must display the following acknowledgement:
   *      This product includes software developed by the University of
   *      California, Berkeley and its contributors.
   * 4. Neither the name of the University nor the names of its contributors
   *    may be used to endorse or promote products derived from this software
   *    without specific prior written permission.
   *
   * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   */
  
  #if defined(LIBC_SCCS) && !defined(lint)
  static char sccsid[] = "@(#)fnmatch.c	8.2 (Berkeley) 4/16/94";
  #endif /* LIBC_SCCS and not lint */
  
  /*
   * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6.
   * Compares a filename or pathname to a pattern.
   */
  
  #include "apr_config.h"
  #include "apr_fnmatch.h"
  
  #define	EOS	'\0'
  
  static const char *rangematch(const char *, int, int);
  
  API_EXPORT(int) apr_fnmatch(const char *pattern, const char *string, int flags)
  {
      const char *stringstart;
      char c, test;
  
      for (stringstart = string;;) {
  	switch (c = *pattern++) {
  	case EOS:
  	    return (*string == EOS ? 0 : FNM_NOMATCH);
  	case '?':
  	    if (*string == EOS) {
  		return (FNM_NOMATCH);
  	    }
  	    if (*string == '/' && (flags & FNM_PATHNAME)) {
  		return (FNM_NOMATCH);
  	    }
  	    if (*string == '.' && (flags & FNM_PERIOD) &&
  		(string == stringstart ||
  		 ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) {
  		return (FNM_NOMATCH);
  	    }
  	    ++string;
  	    break;
  	case '*':
  	    c = *pattern;
  	    /* Collapse multiple stars. */
  	    while (c == '*') {
  		c = *++pattern;
  	    }
  
  	    if (*string == '.' && (flags & FNM_PERIOD) &&
  		(string == stringstart ||
  		 ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) {
  		return (FNM_NOMATCH);
  	    }
  
  	    /* Optimize for pattern with * at end or before /. */
  	    if (c == EOS) {
  		if (flags & FNM_PATHNAME) {
  		    return (strchr(string, '/') == NULL ? 0 : FNM_NOMATCH);
  		}
  		else {
  		    return (0);
  		}
  	    }
  	    else if (c == '/' && flags & FNM_PATHNAME) {
  	        if ((string = strchr(string, '/')) == NULL) {
  		    return (FNM_NOMATCH);
  		}
  		break;
  	    }
  
  	    /* General case, use recursion. */
  	    while ((test = *string) != EOS) {
  	        if (!apr_fnmatch(pattern, string, flags & ~FNM_PERIOD)) {
  		    return (0);
  		}
  		if (test == '/' && flags & FNM_PATHNAME) {
  		    break;
  		}
  		++string;
  	    }
  	    return (FNM_NOMATCH);
  	case '[':
  	    if (*string == EOS) {
  		return (FNM_NOMATCH);
  	    }
  	    if (*string == '/' && flags & FNM_PATHNAME) {
  		return (FNM_NOMATCH);
  	    }
  	    if (*string == '.' && (flags & FNM_PERIOD) &&
  		(string == stringstart ||
  		 ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) {
  	        return (FNM_NOMATCH);
  	    }
  	    if ((pattern = rangematch(pattern, *string, flags)) == NULL) {
  		return (FNM_NOMATCH);
  	    }
  	    ++string;
  	    break;
  	case '\\':
  	    if (!(flags & FNM_NOESCAPE)) {
  		if ((c = *pattern++) == EOS) {
  		    c = '\\';
  		    --pattern;
  		}
  	    }
  	    /* FALLTHROUGH */
  	default:
  	    if (flags & FNM_CASE_BLIND) {
  	        if (apr_tolower(c) != apr_tolower(*string)) {
  		    return (FNM_NOMATCH);
  		}
  	    }
  	    else if (c != *string) {
  	        return (FNM_NOMATCH);
  	    }
  	    string++;
  	    break;
  	}
      /* NOTREACHED */
      }
  }
  
  static const char *rangematch(const char *pattern, int test, int flags)
  {
      int negate, ok;
      char c, c2;
  
      /*
       * A bracket expression starting with an unquoted circumflex
       * character produces unspecified results (IEEE 1003.2-1992,
       * 3.13.2).  This implementation treats it like '!', for
       * consistency with the regular expression syntax.
       * J.T. Conklin (conklin@ngai.kaleida.com)
       */
      if ((negate = (*pattern == '!' || *pattern == '^'))) {
  	++pattern;
      }
  
      for (ok = 0; (c = *pattern++) != ']';) {
          if (c == '\\' && !(flags & FNM_NOESCAPE)) {
  	    c = *pattern++;
  	}
  	if (c == EOS) {
  	    return (NULL);
  	}
  	if (*pattern == '-' && (c2 = *(pattern + 1)) != EOS && c2 != ']') {
  	    pattern += 2;
  	    if (c2 == '\\' && !(flags & FNM_NOESCAPE)) {
  		c2 = *pattern++;
  	    }
  	    if (c2 == EOS) {
  		return (NULL);
  	    }
  	    if ((c <= test && test <= c2)
  		|| ((flags & FNM_CASE_BLIND)
  		    && ((apr_tolower(c) <= apr_tolower(test))
  			&& (apr_tolower(test) <= apr_tolower(c2))))) {
  		ok = 1;
  	    }
  	}
  	else if ((c == test)
  		 || ((flags & FNM_CASE_BLIND)
  		     && (apr_tolower(c) == apr_tolower(test)))) {
  	    ok = 1;
  	}
      }
      return (ok == negate ? NULL : pattern);
  }
  
  
  /* This function is an Apache addition */
  /* return non-zero if pattern has any glob chars in it */
  API_EXPORT(int) apr_is_fnmatch(const char *pattern)
  {
      int nesting;
  
      nesting = 0;
      while (*pattern) {
  	switch (*pattern) {
  	case '?':
  	case '*':
  	    return 1;
  
  	case '\\':
  	    if (*pattern++ == '\0') {
  		return 0;
  	    }
  	    break;
  
  	case '[':	/* '[' is only a glob if it has a matching ']' */
  	    ++nesting;
  	    break;
  
  	case ']':
  	    if (nesting) {
  		return 1;
  	    }
  	    break;
  	}
  	++pattern;
      }
      return 0;
  }
  
  
  
  1.1                  apache-apr/apr/lib/apr_md5.c
  
  Index: apr_md5.c
  ===================================================================
  /*
   * This is work is derived from material Copyright RSA Data Security, Inc.
   *
   * The RSA copyright statement and Licence for that original material is
   * included below. This is followed by the Apache copyright statement and
   * licence for the modifications made to that material.
   */
  
  /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
   */
  
  /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
     rights reserved.
  
     License to copy and use this software is granted provided that it
     is identified as the "RSA Data Security, Inc. MD5 Message-Digest
     Algorithm" in all material mentioning or referencing this software
     or this function.
  
     License is also granted to make and use derivative works provided
     that such works are identified as "derived from the RSA Data
     Security, Inc. MD5 Message-Digest Algorithm" in all material
     mentioning or referencing the derived work.
  
     RSA Data Security, Inc. makes no representations concerning either
     the merchantability of this software or the suitability of this
     software for any particular purpose. It is provided "as is"
     without express or implied warranty of any kind.
  
     These notices must be retained in any copies of any part of this
     documentation and/or software.
   */
  
  /* ====================================================================
   * Copyright (c) 1996-1999 The Apache Group.  All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. All advertising materials mentioning features or use of this
   *    software must display the following acknowledgment:
   *    "This product includes software developed by the Apache Group
   *    for use in the Apache HTTP server project (http://www.apache.org/)."
   *
   * 4. The names "Apache Server" and "Apache Group" must not be used to
   *    endorse or promote products derived from this software without
   *    prior written permission. For written permission, please contact
   *    apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * 6. Redistributions of any form whatsoever must retain the following
   *    acknowledgment:
   *    "This product includes software developed by the Apache Group
   *    for use in the Apache HTTP server project (http://www.apache.org/)."
   *
   * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
   * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
   * OF THE POSSIBILITY OF SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Group and was originally based
   * on public domain software written at the National Center for
   * Supercomputing Applications, University of Illinois, Urbana-Champaign.
   * For more information on the Apache Group and the Apache HTTP server
   * project, please see <http://www.apache.org/>.
   *
   */
  
  /*
   * The apr_MD5Encode() routine uses much code obtained from the FreeBSD 3.0
   * MD5 crypt() function, which is licenced as follows:
   * ----------------------------------------------------------------------------
   * "THE BEER-WARE LICENSE" (Revision 42):
   * <phk@login.dknet.dk> wrote this file.  As long as you retain this notice you
   * can do whatever you want with this stuff. If we meet some day, and you think
   * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
   * ----------------------------------------------------------------------------
   */
  
  #include "apr_config.h"
  #include "apr_md5.h"
  #include "apr_lib.h"
  
  /* Constants for MD5Transform routine.
   */
  
  #define S11 7
  #define S12 12
  #define S13 17
  #define S14 22
  #define S21 5
  #define S22 9
  #define S23 14
  #define S24 20
  #define S31 4
  #define S32 11
  #define S33 16
  #define S34 23
  #define S41 6
  #define S42 10
  #define S43 15
  #define S44 21
  
  static void MD5Transform(UINT4 state[4], const unsigned char block[64]);
  static void Encode(unsigned char *output, const UINT4 *input,
  		   unsigned int len);
  static void Decode(UINT4 *output, const unsigned char *input,
  		   unsigned int len);
  
  static unsigned char PADDING[64] =
  {
      0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  };
  
  /* F, G, H and I are basic MD5 functions.
   */
  #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
  #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
  #define H(x, y, z) ((x) ^ (y) ^ (z))
  #define I(x, y, z) ((y) ^ ((x) | (~z)))
  
  /* ROTATE_LEFT rotates x left n bits.
   */
  #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
  
  /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
     Rotation is separate from addition to prevent recomputation.
   */
  #define FF(a, b, c, d, x, s, ac) { \
   (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
   (a) = ROTATE_LEFT ((a), (s)); \
   (a) += (b); \
    }
  #define GG(a, b, c, d, x, s, ac) { \
   (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
   (a) = ROTATE_LEFT ((a), (s)); \
   (a) += (b); \
    }
  #define HH(a, b, c, d, x, s, ac) { \
   (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
   (a) = ROTATE_LEFT ((a), (s)); \
   (a) += (b); \
    }
  #define II(a, b, c, d, x, s, ac) { \
   (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
   (a) = ROTATE_LEFT ((a), (s)); \
   (a) += (b); \
    }
  
  /* MD5 initialization. Begins an MD5 operation, writing a new context.
   */
  API_EXPORT(void) apr_MD5Init(APR_MD5_CTX * context)
  {
      context->count[0] = context->count[1] = 0;
      /* Load magic initialization constants. */
      context->state[0] = 0x67452301;
      context->state[1] = 0xefcdab89;
      context->state[2] = 0x98badcfe;
      context->state[3] = 0x10325476;
  }
  
  /* MD5 block update operation. Continues an MD5 message-digest
     operation, processing another message block, and updating the
     context.
   */
  API_EXPORT(void) apr_MD5Update(APR_MD5_CTX * context, const unsigned char *input,
  			   unsigned int inputLen)
  {
      unsigned int i, idx, partLen;
  
      /* Compute number of bytes mod 64 */
      idx = (unsigned int) ((context->count[0] >> 3) & 0x3F);
  
      /* Update number of bits */
      if ((context->count[0] += ((UINT4) inputLen << 3)) < ((UINT4) inputLen << 3))
  	context->count[1]++;
      context->count[1] += (UINT4) inputLen >> 29;
  
      partLen = 64 - idx;
  
      /* Transform as many times as possible. */
  #ifndef CHARSET_EBCDIC
      if (inputLen >= partLen) {
  	memcpy(&context->buffer[idx], input, partLen);
  	MD5Transform(context->state, context->buffer);
  
  	for (i = partLen; i + 63 < inputLen; i += 64)
  	    MD5Transform(context->state, &input[i]);
  
  	idx = 0;
      }
      else
  	i = 0;
  
      /* Buffer remaining input */
      memcpy(&context->buffer[idx], &input[i], inputLen - i);
  #else /*CHARSET_EBCDIC*/
      if (inputLen >= partLen) {
  	ebcdic2ascii_strictly(&context->buffer[idx], input, partLen);
  	MD5Transform(context->state, context->buffer);
  
  	for (i = partLen; i + 63 < inputLen; i += 64) {
  	    unsigned char inp_tmp[64];
  	    ebcdic2ascii_strictly(inp_tmp, &input[i], 64);
  	    MD5Transform(context->state, inp_tmp);
  	}
  
  	idx = 0;
      }
      else
  	i = 0;
  
      /* Buffer remaining input */
      ebcdic2ascii_strictly(&context->buffer[idx], &input[i], inputLen - i);
  #endif /*CHARSET_EBCDIC*/
  }
  
  /* MD5 finalization. Ends an MD5 message-digest operation, writing the
     the message digest and zeroizing the context.
   */
  API_EXPORT(void) apr_MD5Final(unsigned char digest[16], APR_MD5_CTX * context)
  {
      unsigned char bits[8];
      unsigned int idx, padLen;
  
  
      /* Save number of bits */
      Encode(bits, context->count, 8);
  
  #ifdef CHARSET_EBCDIC
      /* XXX: @@@: In order to make this no more complex than necessary,
       * this kludge converts the bits[] array using the ascii-to-ebcdic
       * table, because the following apr_MD5Update() re-translates
       * its input (ebcdic-to-ascii).
       * Otherwise, we would have to pass a "conversion" flag to apr_MD5Update()
       */
      ascii2ebcdic(bits,bits,8);
  
      /* Since everything is converted to ascii within apr_MD5Update(), 
       * the initial 0x80 (PADDING[0]) must be stored as 0x20 
       */
      PADDING[0] = os_toebcdic[0x80];
  #endif /*CHARSET_EBCDIC*/
  
      /* Pad out to 56 mod 64. */
      idx = (unsigned int) ((context->count[0] >> 3) & 0x3f);
      padLen = (idx < 56) ? (56 - idx) : (120 - idx);
      apr_MD5Update(context, PADDING, padLen);
  
      /* Append length (before padding) */
      apr_MD5Update(context, bits, 8);
  
      /* Store state in digest */
      Encode(digest, context->state, 16);
  
      /* Zeroize sensitive information. */
      memset(context, 0, sizeof(*context));
  }
  
  /* MD5 basic transformation. Transforms state based on block. */
  static void MD5Transform(UINT4 state[4], const unsigned char block[64])
  {
      UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
  
      Decode(x, block, 64);
  
      /* Round 1 */
      FF(a, b, c, d, x[0], S11, 0xd76aa478);	/* 1 */
      FF(d, a, b, c, x[1], S12, 0xe8c7b756);	/* 2 */
      FF(c, d, a, b, x[2], S13, 0x242070db);	/* 3 */
      FF(b, c, d, a, x[3], S14, 0xc1bdceee);	/* 4 */
      FF(a, b, c, d, x[4], S11, 0xf57c0faf);	/* 5 */
      FF(d, a, b, c, x[5], S12, 0x4787c62a);	/* 6 */
      FF(c, d, a, b, x[6], S13, 0xa8304613);	/* 7 */
      FF(b, c, d, a, x[7], S14, 0xfd469501);	/* 8 */
      FF(a, b, c, d, x[8], S11, 0x698098d8);	/* 9 */
      FF(d, a, b, c, x[9], S12, 0x8b44f7af);	/* 10 */
      FF(c, d, a, b, x[10], S13, 0xffff5bb1);	/* 11 */
      FF(b, c, d, a, x[11], S14, 0x895cd7be);	/* 12 */
      FF(a, b, c, d, x[12], S11, 0x6b901122);	/* 13 */
      FF(d, a, b, c, x[13], S12, 0xfd987193);	/* 14 */
      FF(c, d, a, b, x[14], S13, 0xa679438e);	/* 15 */
      FF(b, c, d, a, x[15], S14, 0x49b40821);	/* 16 */
  
      /* Round 2 */
      GG(a, b, c, d, x[1], S21, 0xf61e2562);	/* 17 */
      GG(d, a, b, c, x[6], S22, 0xc040b340);	/* 18 */
      GG(c, d, a, b, x[11], S23, 0x265e5a51);	/* 19 */
      GG(b, c, d, a, x[0], S24, 0xe9b6c7aa);	/* 20 */
      GG(a, b, c, d, x[5], S21, 0xd62f105d);	/* 21 */
      GG(d, a, b, c, x[10], S22, 0x2441453);	/* 22 */
      GG(c, d, a, b, x[15], S23, 0xd8a1e681);	/* 23 */
      GG(b, c, d, a, x[4], S24, 0xe7d3fbc8);	/* 24 */
      GG(a, b, c, d, x[9], S21, 0x21e1cde6);	/* 25 */
      GG(d, a, b, c, x[14], S22, 0xc33707d6);	/* 26 */
      GG(c, d, a, b, x[3], S23, 0xf4d50d87);	/* 27 */
      GG(b, c, d, a, x[8], S24, 0x455a14ed);	/* 28 */
      GG(a, b, c, d, x[13], S21, 0xa9e3e905);	/* 29 */
      GG(d, a, b, c, x[2], S22, 0xfcefa3f8);	/* 30 */
      GG(c, d, a, b, x[7], S23, 0x676f02d9);	/* 31 */
      GG(b, c, d, a, x[12], S24, 0x8d2a4c8a);	/* 32 */
  
      /* Round 3 */
      HH(a, b, c, d, x[5], S31, 0xfffa3942);	/* 33 */
      HH(d, a, b, c, x[8], S32, 0x8771f681);	/* 34 */
      HH(c, d, a, b, x[11], S33, 0x6d9d6122);	/* 35 */
      HH(b, c, d, a, x[14], S34, 0xfde5380c);	/* 36 */
      HH(a, b, c, d, x[1], S31, 0xa4beea44);	/* 37 */
      HH(d, a, b, c, x[4], S32, 0x4bdecfa9);	/* 38 */
      HH(c, d, a, b, x[7], S33, 0xf6bb4b60);	/* 39 */
      HH(b, c, d, a, x[10], S34, 0xbebfbc70);	/* 40 */
      HH(a, b, c, d, x[13], S31, 0x289b7ec6);	/* 41 */
      HH(d, a, b, c, x[0], S32, 0xeaa127fa);	/* 42 */
      HH(c, d, a, b, x[3], S33, 0xd4ef3085);	/* 43 */
      HH(b, c, d, a, x[6], S34, 0x4881d05);	/* 44 */
      HH(a, b, c, d, x[9], S31, 0xd9d4d039);	/* 45 */
      HH(d, a, b, c, x[12], S32, 0xe6db99e5);	/* 46 */
      HH(c, d, a, b, x[15], S33, 0x1fa27cf8);	/* 47 */
      HH(b, c, d, a, x[2], S34, 0xc4ac5665);	/* 48 */
  
      /* Round 4 */
      II(a, b, c, d, x[0], S41, 0xf4292244);	/* 49 */
      II(d, a, b, c, x[7], S42, 0x432aff97);	/* 50 */
      II(c, d, a, b, x[14], S43, 0xab9423a7);	/* 51 */
      II(b, c, d, a, x[5], S44, 0xfc93a039);	/* 52 */
      II(a, b, c, d, x[12], S41, 0x655b59c3);	/* 53 */
      II(d, a, b, c, x[3], S42, 0x8f0ccc92);	/* 54 */
      II(c, d, a, b, x[10], S43, 0xffeff47d);	/* 55 */
      II(b, c, d, a, x[1], S44, 0x85845dd1);	/* 56 */
      II(a, b, c, d, x[8], S41, 0x6fa87e4f);	/* 57 */
      II(d, a, b, c, x[15], S42, 0xfe2ce6e0);	/* 58 */
      II(c, d, a, b, x[6], S43, 0xa3014314);	/* 59 */
      II(b, c, d, a, x[13], S44, 0x4e0811a1);	/* 60 */
      II(a, b, c, d, x[4], S41, 0xf7537e82);	/* 61 */
      II(d, a, b, c, x[11], S42, 0xbd3af235);	/* 62 */
      II(c, d, a, b, x[2], S43, 0x2ad7d2bb);	/* 63 */
      II(b, c, d, a, x[9], S44, 0xeb86d391);	/* 64 */
  
      state[0] += a;
      state[1] += b;
      state[2] += c;
      state[3] += d;
  
      /* Zeroize sensitive information. */
      memset(x, 0, sizeof(x));
  }
  
  /* Encodes input (UINT4) into output (unsigned char). Assumes len is
     a multiple of 4.
   */
  static void Encode(unsigned char *output, const UINT4 *input, unsigned int len)
  {
      unsigned int i, j;
      UINT4 k;
  
      for (i = 0, j = 0; j < len; i++, j += 4) {
  	k = input[i];
  	output[j] = (unsigned char) (k & 0xff);
  	output[j + 1] = (unsigned char) ((k >> 8) & 0xff);
  	output[j + 2] = (unsigned char) ((k >> 16) & 0xff);
  	output[j + 3] = (unsigned char) ((k >> 24) & 0xff);
      }
  }
  
  /* Decodes input (unsigned char) into output (UINT4). Assumes len is
   * a multiple of 4.
   */
  static void Decode(UINT4 *output, const unsigned char *input, unsigned int len)
  {
      unsigned int i, j;
  
      for (i = 0, j = 0; j < len; i++, j += 4)
  	output[i] = ((UINT4) input[j]) | (((UINT4) input[j + 1]) << 8) |
  	    (((UINT4) input[j + 2]) << 16) | (((UINT4) input[j + 3]) << 24);
  }
  
  /*
   * Define the Magic String prefix that identifies a password as being
   * hashed using our algorithm.
   */
  static const char *apr1_id = "$apr1$";
  
  /*
   * The following MD5 password encryption code was largely borrowed from
   * the FreeBSD 3.0 /usr/src/lib/libcrypt/crypt.c file, which is
   * licenced as stated at the top of this file.
   */
  
  static void to64(char *s, unsigned long v, int n)
  {
      static unsigned char itoa64[] =         /* 0 ... 63 => ASCII - 64 */
  	"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
  
      while (--n >= 0) {
  	*s++ = itoa64[v&0x3f];
  	v >>= 6;
      }
  }
  
  API_EXPORT(void) apr_MD5Encode(const char *pw, const char *salt,
  			      char *result, size_t nbytes)
  {
      /*
       * Minimum size is 8 bytes for salt, plus 1 for the trailing NUL,
       * plus 4 for the '$' separators, plus the password hash itself.
       * Let's leave a goodly amount of leeway.
       */
  
      char passwd[120], *p;
      const char *sp, *ep;
      unsigned char final[16];
      int sl, pl, i;
      APR_MD5_CTX ctx, ctx1;
      unsigned long l;
  
      /* 
       * Refine the salt first.  It's possible we were given an already-hashed
       * string as the salt argument, so extract the actual salt value from it
       * if so.  Otherwise just use the string up to the first '$' as the salt.
       */
      sp = salt;
  
      /*
       * If it starts with the magic string, then skip that.
       */
      if (!strncmp(sp, apr1_id, strlen(apr1_id))) {
  	sp += strlen(apr1_id);
      }
  
      /*
       * It stops at the first '$' or 8 chars, whichever comes first
       */
      for (ep = sp; (*ep != '\0') && (*ep != '$') && (ep < (sp + 8)); ep++) {
  	continue;
      }
  
      /*
       * Get the length of the true salt
       */
      sl = ep - sp;
  
      /*
       * 'Time to make the doughnuts..'
       */
      apr_MD5Init(&ctx);
  
      /*
       * The password first, since that is what is most unknown
       */
      apr_MD5Update(&ctx, pw, strlen(pw));
  
      /*
       * Then our magic string
       */
      apr_MD5Update(&ctx, apr1_id, strlen(apr1_id));
  
      /*
       * Then the raw salt
       */
      apr_MD5Update(&ctx, sp, sl);
  
      /*
       * Then just as many characters of the MD5(pw, salt, pw)
       */
      apr_MD5Init(&ctx1);
      apr_MD5Update(&ctx1, pw, strlen(pw));
      apr_MD5Update(&ctx1, sp, sl);
      apr_MD5Update(&ctx1, pw, strlen(pw));
      apr_MD5Final(final, &ctx1);
      for(pl = strlen(pw); pl > 0; pl -= 16) {
  	apr_MD5Update(&ctx, final, (pl > 16) ? 16 : pl);
      }
  
      /*
       * Don't leave anything around in vm they could use.
       */
      memset(final, 0, sizeof(final));
  
      /*
       * Then something really weird...
       */
      for (i = strlen(pw); i != 0; i >>= 1) {
  	if (i & 1) {
  	    apr_MD5Update(&ctx, final, 1);
  	}
  	else {
  	    apr_MD5Update(&ctx, pw, 1);
  	}
      }
  
      /*
       * Now make the output string.  We know our limitations, so we
       * can use the string routines without bounds checking.
       */
      strcpy(passwd, apr1_id);
      strncat(passwd, sp, sl);
      strcat(passwd, "$");
  
      apr_MD5Final(final, &ctx);
  
      /*
       * And now, just to make sure things don't run too fast..
       * On a 60 Mhz Pentium this takes 34 msec, so you would
       * need 30 seconds to build a 1000 entry dictionary...
       */
      for (i = 0; i < 1000; i++) {
  	apr_MD5Init(&ctx1);
  	if (i & 1) {
  	    apr_MD5Update(&ctx1, pw, strlen(pw));
  	}
  	else {
  	    apr_MD5Update(&ctx1, final, 16);
  	}
  	if (i % 3) {
  	    apr_MD5Update(&ctx1, sp, sl);
  	}
  
  	if (i % 7) {
  	    apr_MD5Update(&ctx1, pw, strlen(pw));
  	}
  
  	if (i & 1) {
  	    apr_MD5Update(&ctx1, final, 16);
  	}
  	else {
  	    apr_MD5Update(&ctx1, pw, strlen(pw));
  	}
  	apr_MD5Final(final,&ctx1);
      }
  
      p = passwd + strlen(passwd);
  
      l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p, l, 4); p += 4;
      l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p, l, 4); p += 4;
      l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p, l, 4); p += 4;
      l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p, l, 4); p += 4;
      l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p, l, 4); p += 4;
      l =                    final[11]                ; to64(p, l, 2); p += 2;
      *p = '\0';
  
      /*
       * Don't leave anything around in vm they could use.
       */
      memset(final, 0, sizeof(final));
  
      apr_cpystrn(result, passwd, nbytes - 1);
  }
  
  /*
   * Validate a plaintext password against a smashed one.  Use either
   * crypt() (if available) or apr_MD5Encode(), depending upon the format
   * of the smashed input password.  Return NULL if they match, or
   * an explanatory text string if they don't.
   */
  
  API_EXPORT(char *) apr_validate_password(const char *passwd, const char *hash)
  {
      char sample[120];
      char *crypt_pw;
  
      if (!strncmp(hash, apr1_id, strlen(apr1_id))) {
  	/*
  	 * The hash was created using our custom algorithm.
  	 */
  	apr_MD5Encode(passwd, hash, sample, sizeof(sample));
      }
      else {
  	/*
  	 * It's not our algorithm, so feed it to crypt() if possible.
  	 */
  #ifdef WIN32
  	return "crypt() unavailable on Win32, cannot validate password";
  #else
  	crypt_pw = crypt(passwd, hash);
  	apr_cpystrn(sample, crypt_pw, sizeof(sample) - 1);
  #endif
      }
      return (strcmp(sample, hash) == 0) ? NULL : "password mismatch";
  }
  
  
  
  1.1                  apache-apr/apr/lib/apr_signal.c
  
  Index: apr_signal.c
  ===================================================================
  /* ====================================================================
   * Copyright (c) 1995-1999 The Apache Group.  All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. All advertising materials mentioning features or use of this
   *    software must display the following acknowledgment:
   *    "This product includes software developed by the Apache Group
   *    for use in the Apache HTTP server project (http://www.apache.org/)."
   *
   * 4. The names "Apache Server" and "Apache Group" must not be used to
   *    endorse or promote products derived from this software without
   *    prior written permission. For written permission, please contact
   *    apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * 6. Redistributions of any form whatsoever must retain the following
   *    acknowledgment:
   *    "This product includes software developed by the Apache Group
   *    for use in the Apache HTTP server project (http://www.apache.org/)."
   *
   * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
   * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
   * OF THE POSSIBILITY OF SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Group and was originally based
   * on public domain software written at the National Center for
   * Supercomputing Applications, University of Illinois, Urbana-Champaign.
   * For more information on the Apache Group and the Apache HTTP server
   * project, please see <http://www.apache.org/>.
   *
   */
  
  #include "apr_config.h"
  
  #ifndef NO_USE_SIGACTION
  /*
   * Replace standard signal() with the more reliable sigaction equivalent
   * from W. Richard Stevens' "Advanced Programming in the UNIX Environment"
   * (the version that does not automatically restart system calls).
   */
  Sigfunc *signal(int signo, Sigfunc * func)
  {
      struct sigaction act, oact;
  
      act.sa_handler = func;
      sigemptyset(&act.sa_mask);
      act.sa_flags = 0;
  #ifdef  SA_INTERRUPT		/* SunOS */
      act.sa_flags |= SA_INTERRUPT;
  #endif
      if (sigaction(signo, &act, &oact) < 0)
  	return SIG_ERR;
      return oact.sa_handler;
  }
  #else
  /* need some function in this file, otherwise the linker on NeXT bitches */
  void apr_signal_is_not_here(void) {}
  #endif
  
  
  
  1.1                  apache-apr/apr/lib/apr_slack.c
  
  Index: apr_slack.c
  ===================================================================
  /* ====================================================================
   * Copyright (c) 1995-1999 The Apache Group.  All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. All advertising materials mentioning features or use of this
   *    software must display the following acknowledgment:
   *    "This product includes software developed by the Apache Group
   *    for use in the Apache HTTP server project (http://www.apache.org/)."
   *
   * 4. The names "Apache Server" and "Apache Group" must not be used to
   *    endorse or promote products derived from this software without
   *    prior written permission. For written permission, please contact
   *    apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * 6. Redistributions of any form whatsoever must retain the following
   *    acknowledgment:
   *    "This product includes software developed by the Apache Group
   *    for use in the Apache HTTP server project (http://www.apache.org/)."
   *
   * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
   * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
   * OF THE POSSIBILITY OF SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Group and was originally based
   * on public domain software written at the National Center for
   * Supercomputing Applications, University of Illinois, Urbana-Champaign.
   * For more information on the Apache Group and the Apache HTTP server
   * project, please see <http://www.apache.org/>.
   *
   */
  
  /*
   * apr_slack.c: File descriptor preallocation
   * 
   * 3/21/93 Rob McCool
   * 1995-96 Many changes by the Apache Group
   * 
   */
  
  #include "apr_config.h"
  #ifdef APACHE
  #include "http_log.h"
  #endif
  
  #ifndef NO_SLACK
  int apr_slack(int fd, int line)
  {
  #if !defined(F_DUPFD)
      return fd;
  #else
      static int low_warned;
      int new_fd;
  
  #ifdef HIGH_SLACK_LINE
      if (line == APR_SLACK_HIGH && fd < HIGH_SLACK_LINE) {
  	new_fd = fcntl(fd, F_DUPFD, HIGH_SLACK_LINE);
  	if (new_fd != -1) {
  	    close(fd);
  	    return new_fd;
  	}
      }
  #endif
      /* otherwise just assume line == APR_SLACK_LOW */
      if (fd >= LOW_SLACK_LINE) {
  	return fd;
      }
      new_fd = fcntl(fd, F_DUPFD, LOW_SLACK_LINE);
      if (new_fd == -1) {
  	if (!low_warned) {
  
  #ifdef APACHE
  	    /* Give them a warning here, because we really can't predict
  	     * how libraries and such are going to fail.  If we can't
  	     * do this F_DUPFD there's a good chance that apache has too
  	     * few descriptors available to it.  Note we don't warn on
  	     * the high line, because if it fails we'll eventually try
  	     * the low line...
  	     */
  	    apr_log_error(APLOG_MARK, APLOG_WARNING, NULL,
  		        "unable to open a file descriptor above %u, "
  			"you may need to increase the number of descriptors",
  			LOW_SLACK_LINE);
  #endif /* APACHE */
  	    low_warned = 1;
  	}
  	return fd;
      }
      close(fd);
      return new_fd;
  #endif
  }
  #else
  /* need at least one function in the file for some linkers */
  void apr_slack_is_not_here(void) {}
  #endif /* NO_SLACK */
  
  
  
  1.1                  apache-apr/apr/lib/apr_snprintf.c
  
  Index: apr_snprintf.c
  ===================================================================
  /* ====================================================================
   * Copyright (c) 1995-1999 The Apache Group.  All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. All advertising materials mentioning features or use of this
   *    software must display the following acknowledgment:
   *    "This product includes software developed by the Apache Group
   *    for use in the Apache HTTP server project (http://www.apache.org/)."
   *
   * 4. The names "Apache Server" and "Apache Group" must not be used to
   *    endorse or promote products derived from this software without
   *    prior written permission. For written permission, please contact
   *    apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * 6. Redistributions of any form whatsoever must retain the following
   *    acknowledgment:
   *    "This product includes software developed by the Apache Group
   *    for use in the Apache HTTP server project (http://www.apache.org/)."
   *
   * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
   * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
   * OF THE POSSIBILITY OF SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Group and was originally based
   * on public domain software written at the National Center for
   * Supercomputing Applications, University of Illinois, Urbana-Champaign.
   * For more information on the Apache Group and the Apache HTTP server
   * project, please see <http://www.apache.org/>.
   *
   * This code is based on, and used with the permission of, the
   * SIO stdio-replacement strx_* functions by Panos Tsirigotis
   * <panos@alumni.cs.colorado.edu> for xinetd.
   */
  
  #include "apr_config.h"
  #include "apr_lib.h"
  
  typedef enum {
      NO = 0, YES = 1
  } boolean_e;
  
  #ifndef FALSE
  #define FALSE			0
  #endif
  #ifndef TRUE
  #define TRUE			1
  #endif
  #define NUL			'\0'
  #define INT_NULL		((int *)0)
  #define WIDE_INT		long
  
  typedef WIDE_INT wide_int;
  typedef unsigned WIDE_INT u_wide_int;
  typedef int bool_int;
  
  #define S_NULL			"(null)"
  #define S_NULL_LEN		6
  
  #define FLOAT_DIGITS		6
  #define EXPONENT_LENGTH		10
  
  /*
   * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions
   *
   * XXX: this is a magic number; do not decrease it
   */
  #define NUM_BUF_SIZE		512
  
  /*
   * cvt.c - IEEE floating point formatting routines for FreeBSD
   * from GNU libc-4.6.27.  Modified to be thread safe.
   */
  
  /*
   *    apr_ecvt converts to decimal
   *      the number of digits is specified by ndigit
   *      decpt is set to the position of the decimal point
   *      sign is set to 0 for positive, 1 for negative
   */
  
  #define	NDIG	80
  
  /* buf must have at least NDIG bytes */
  static char *apr_cvt(double arg, int ndigits, int *decpt, int *sign, int eflag, char *buf)
  {
      register int r2;
      double fi, fj;
      register char *p, *p1;
  
      if (ndigits >= NDIG - 1)
  	ndigits = NDIG - 2;
      r2 = 0;
      *sign = 0;
      p = &buf[0];
      if (arg < 0) {
  	*sign = 1;
  	arg = -arg;
      }
      arg = modf(arg, &fi);
      p1 = &buf[NDIG];
      /*
       * Do integer part
       */
      if (fi != 0) {
  	p1 = &buf[NDIG];
  	while (fi != 0) {
  	    fj = modf(fi / 10, &fi);
  	    *--p1 = (int) ((fj + .03) * 10) + '0';
  	    r2++;
  	}
  	while (p1 < &buf[NDIG])
  	    *p++ = *p1++;
      }
      else if (arg > 0) {
  	while ((fj = arg * 10) < 1) {
  	    arg = fj;
  	    r2--;
  	}
      }
      p1 = &buf[ndigits];
      if (eflag == 0)
  	p1 += r2;
      *decpt = r2;
      if (p1 < &buf[0]) {
  	buf[0] = '\0';
  	return (buf);
      }
      while (p <= p1 && p < &buf[NDIG]) {
  	arg *= 10;
  	arg = modf(arg, &fj);
  	*p++ = (int) fj + '0';
      }
      if (p1 >= &buf[NDIG]) {
  	buf[NDIG - 1] = '\0';
  	return (buf);
      }
      p = p1;
      *p1 += 5;
      while (*p1 > '9') {
  	*p1 = '0';
  	if (p1 > buf)
  	    ++ * --p1;
  	else {
  	    *p1 = '1';
  	    (*decpt)++;
  	    if (eflag == 0) {
  		if (p > buf)
  		    *p = '0';
  		p++;
  	    }
  	}
      }
      *p = '\0';
      return (buf);
  }
  
  static char *apr_ecvt(double arg, int ndigits, int *decpt, int *sign, char *buf)
  {
      return (apr_cvt(arg, ndigits, decpt, sign, 1, buf));
  }
  
  static char *apr_fcvt(double arg, int ndigits, int *decpt, int *sign, char *buf)
  {
      return (apr_cvt(arg, ndigits, decpt, sign, 0, buf));
  }
  
  /*
   * apr_gcvt  - Floating output conversion to
   * minimal length string
   */
  
  static char *apr_gcvt(double number, int ndigit, char *buf, boolean_e altform)
  {
      int sign, decpt;
      register char *p1, *p2;
      register int i;
      char buf1[NDIG];
  
      p1 = apr_ecvt(number, ndigit, &decpt, &sign, buf1);
      p2 = buf;
      if (sign)
  	*p2++ = '-';
      for (i = ndigit - 1; i > 0 && p1[i] == '0'; i--)
  	ndigit--;
      if ((decpt >= 0 && decpt - ndigit > 4)
  	|| (decpt < 0 && decpt < -3)) {		/* use E-style */
  	decpt--;
  	*p2++ = *p1++;
  	*p2++ = '.';
  	for (i = 1; i < ndigit; i++)
  	    *p2++ = *p1++;
  	*p2++ = 'e';
  	if (decpt < 0) {
  	    decpt = -decpt;
  	    *p2++ = '-';
  	}
  	else
  	    *p2++ = '+';
  	if (decpt / 100 > 0)
  	    *p2++ = decpt / 100 + '0';
  	if (decpt / 10 > 0)
  	    *p2++ = (decpt % 100) / 10 + '0';
  	*p2++ = decpt % 10 + '0';
      }
      else {
  	if (decpt <= 0) {
  	    if (*p1 != '0')
  		*p2++ = '.';
  	    while (decpt < 0) {
  		decpt++;
  		*p2++ = '0';
  	    }
  	}
  	for (i = 1; i <= ndigit; i++) {
  	    *p2++ = *p1++;
  	    if (i == decpt)
  		*p2++ = '.';
  	}
  	if (ndigit < decpt) {
  	    while (ndigit++ < decpt)
  		*p2++ = '0';
  	    *p2++ = '.';
  	}
      }
      if (p2[-1] == '.' && !altform)
  	p2--;
      *p2 = '\0';
      return (buf);
  }
  
  /*
   * The INS_CHAR macro inserts a character in the buffer and writes
   * the buffer back to disk if necessary
   * It uses the char pointers sp and bep:
   *      sp points to the next available character in the buffer
   *      bep points to the end-of-buffer+1
   * While using this macro, note that the nextb pointer is NOT updated.
   *
   * NOTE: Evaluation of the c argument should not have any side-effects
   */
  #define INS_CHAR(c, sp, bep, cc)				\
  	    {							\
  		if (sp >= bep) {				\
  		    vbuff->curpos = sp;                         \
  		    if (flush_func(vbuff))			\
  			return -1;				\
  		    sp = vbuff->curpos;				\
  		    bep = vbuff->endpos;			\
  		} 						\
  		*sp++ = (c);					\
  		cc++; 						\
  	    }
  
  #define NUM( c )			( c - '0' )
  
  #define STR_TO_DEC( str, num )		\
      num = NUM( *str++ ) ;		\
      while ( apr_isdigit( *str ) )		\
      {					\
  	num *= 10 ;			\
  	num += NUM( *str++ ) ;		\
      }
  
  /*
   * This macro does zero padding so that the precision
   * requirement is satisfied. The padding is done by
   * adding '0's to the left of the string that is going
   * to be printed.
   */
  #define FIX_PRECISION( adjust, precision, s, s_len )	\
      if ( adjust )					\
  	while ( s_len < precision )			\
  	{						\
  	    *--s = '0' ;				\
  	    s_len++ ;					\
  	}
  
  /*
   * Macro that does padding. The padding is done by printing
   * the character ch.
   */
  #define PAD( width, len, ch )	do		\
  	{					\
  	    INS_CHAR( ch, sp, bep, cc ) ;	\
  	    width-- ;				\
  	}					\
  	while ( width > len )
  
  /*
   * Prefix the character ch to the string str
   * Increase length
   * Set the has_prefix flag
   */
  #define PREFIX( str, length, ch )	 *--str = ch ; length++ ; has_prefix = YES
  
  
  /*
   * Convert num to its decimal format.
   * Return value:
   *   - a pointer to a string containing the number (no sign)
   *   - len contains the length of the string
   *   - is_negative is set to TRUE or FALSE depending on the sign
   *     of the number (always set to FALSE if is_unsigned is TRUE)
   *
   * The caller provides a buffer for the string: that is the buf_end argument
   * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
   * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
   */
  static char *conv_10(register wide_int num, register bool_int is_unsigned,
  		     register bool_int *is_negative, char *buf_end,
  		     register int *len)
  {
      register char *p = buf_end;
      register u_wide_int magnitude;
  
      if (is_unsigned) {
  	magnitude = (u_wide_int) num;
  	*is_negative = FALSE;
      }
      else {
  	*is_negative = (num < 0);
  
  	/*
  	 * On a 2's complement machine, negating the most negative integer 
  	 * results in a number that cannot be represented as a signed integer.
  	 * Here is what we do to obtain the number's magnitude:
  	 *      a. add 1 to the number
  	 *      b. negate it (becomes positive)
  	 *      c. convert it to unsigned
  	 *      d. add 1
  	 */
  	if (*is_negative) {
  	    wide_int t = num + 1;
  
  	    magnitude = ((u_wide_int) -t) + 1;
  	}
  	else
  	    magnitude = (u_wide_int) num;
      }
  
      /*
       * We use a do-while loop so that we write at least 1 digit 
       */
      do {
  	register u_wide_int new_magnitude = magnitude / 10;
  
  	*--p = (char) (magnitude - new_magnitude * 10 + '0');
  	magnitude = new_magnitude;
      }
      while (magnitude);
  
      *len = buf_end - p;
      return (p);
  }
  
  
  
  static char *conv_in_addr(struct in_addr *ia, char *buf_end, int *len)
  {
      unsigned addr = ntohl(ia->s_addr);
      char *p = buf_end;
      bool_int is_negative;
      int sub_len;
  
      p = conv_10((addr & 0x000000FF)      , TRUE, &is_negative, p, &sub_len);
      *--p = '.';
      p = conv_10((addr & 0x0000FF00) >>  8, TRUE, &is_negative, p, &sub_len);
      *--p = '.';
      p = conv_10((addr & 0x00FF0000) >> 16, TRUE, &is_negative, p, &sub_len);
      *--p = '.';
      p = conv_10((addr & 0xFF000000) >> 24, TRUE, &is_negative, p, &sub_len);
  
      *len = buf_end - p;
      return (p);
  }
  
  
  
  static char *conv_sockaddr_in(struct sockaddr_in *si, char *buf_end, int *len)
  {
      char *p = buf_end;
      bool_int is_negative;
      int sub_len;
  
      p = conv_10(ntohs(si->sin_port), TRUE, &is_negative, p, &sub_len);
      *--p = ':';
      p = conv_in_addr(&si->sin_addr, p, &sub_len);
  
      *len = buf_end - p;
      return (p);
  }
  
  
  
  /*
   * Convert a floating point number to a string formats 'f', 'e' or 'E'.
   * The result is placed in buf, and len denotes the length of the string
   * The sign is returned in the is_negative argument (and is not placed
   * in buf).
   */
  static char *conv_fp(register char format, register double num,
      boolean_e add_dp, int precision, bool_int *is_negative,
      char *buf, int *len)
  {
      register char *s = buf;
      register char *p;
      int decimal_point;
      char buf1[NDIG];
  
      if (format == 'f')
  	p = apr_fcvt(num, precision, &decimal_point, is_negative, buf1);
      else			/* either e or E format */
  	p = apr_ecvt(num, precision + 1, &decimal_point, is_negative, buf1);
  
      /*
       * Check for Infinity and NaN
       */
      if (apr_isalpha(*p)) {
  	*len = strlen(strcpy(buf, p));
  	*is_negative = FALSE;
  	return (buf);
      }
  
      if (format == 'f') {
  	if (decimal_point <= 0) {
  	    *s++ = '0';
  	    if (precision > 0) {
  		*s++ = '.';
  		while (decimal_point++ < 0)
  		    *s++ = '0';
  	    }
  	    else if (add_dp)
  		*s++ = '.';
  	}
  	else {
  	    while (decimal_point-- > 0)
  		*s++ = *p++;
  	    if (precision > 0 || add_dp)
  		*s++ = '.';
  	}
      }
      else {
  	*s++ = *p++;
  	if (precision > 0 || add_dp)
  	    *s++ = '.';
      }
  
      /*
       * copy the rest of p, the NUL is NOT copied
       */
      while (*p)
  	*s++ = *p++;
  
      if (format != 'f') {
  	char temp[EXPONENT_LENGTH];	/* for exponent conversion */
  	int t_len;
  	bool_int exponent_is_negative;
  
  	*s++ = format;		/* either e or E */
  	decimal_point--;
  	if (decimal_point != 0) {
  	    p = conv_10((wide_int) decimal_point, FALSE, &exponent_is_negative,
  			&temp[EXPONENT_LENGTH], &t_len);
  	    *s++ = exponent_is_negative ? '-' : '+';
  
  	    /*
  	     * Make sure the exponent has at least 2 digits
  	     */
  	    if (t_len == 1)
  		*s++ = '0';
  	    while (t_len--)
  		*s++ = *p++;
  	}
  	else {
  	    *s++ = '+';
  	    *s++ = '0';
  	    *s++ = '0';
  	}
      }
  
      *len = s - buf;
      return (buf);
  }
  
  
  /*
   * Convert num to a base X number where X is a power of 2. nbits determines X.
   * For example, if nbits is 3, we do base 8 conversion
   * Return value:
   *      a pointer to a string containing the number
   *
   * The caller provides a buffer for the string: that is the buf_end argument
   * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
   * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
   */
  static char *conv_p2(register u_wide_int num, register int nbits,
  		     char format, char *buf_end, register int *len)
  {
      register int mask = (1 << nbits) - 1;
      register char *p = buf_end;
      static const char low_digits[] = "0123456789abcdef";
      static const char upper_digits[] = "0123456789ABCDEF";
      register const char *digits = (format == 'X') ? upper_digits : low_digits;
  
      do {
  	*--p = digits[num & mask];
  	num >>= nbits;
      }
      while (num);
  
      *len = buf_end - p;
      return (p);
  }
  
  
  /*
   * Do format conversion placing the output in buffer
   */
  API_EXPORT(int) apr_vformatter(int (*flush_func)(apr_vformatter_buff_t *),
      apr_vformatter_buff_t *vbuff, const char *fmt, va_list ap)
  {
      register char *sp;
      register char *bep;
      register int cc = 0;
      register int i;
  
      register char *s = NULL;
      char *q;
      int s_len;
  
      register int min_width = 0;
      int precision = 0;
      enum {
  	LEFT, RIGHT
      } adjust;
      char pad_char;
      char prefix_char;
  
      double fp_num;
      wide_int i_num = (wide_int) 0;
      u_wide_int ui_num;
  
      char num_buf[NUM_BUF_SIZE];
      char char_buf[2];		/* for printing %% and %<unknown> */
  
      /*
       * Flag variables
       */
      boolean_e is_long;
      boolean_e alternate_form;
      boolean_e print_sign;
      boolean_e print_blank;
      boolean_e adjust_precision;
      boolean_e adjust_width;
      bool_int is_negative;
  
      sp = vbuff->curpos;
      bep = vbuff->endpos;
  
      while (*fmt) {
  	if (*fmt != '%') {
  	    INS_CHAR(*fmt, sp, bep, cc);
  	}
  	else {
  	    /*
  	     * Default variable settings
  	     */
  	    adjust = RIGHT;
  	    alternate_form = print_sign = print_blank = NO;
  	    pad_char = ' ';
  	    prefix_char = NUL;
  
  	    fmt++;
  
  	    /*
  	     * Try to avoid checking for flags, width or precision
  	     */
  	    if (!apr_islower(*fmt)) {
  		/*
  		 * Recognize flags: -, #, BLANK, +
  		 */
  		for (;; fmt++) {
  		    if (*fmt == '-')
  			adjust = LEFT;
  		    else if (*fmt == '+')
  			print_sign = YES;
  		    else if (*fmt == '#')
  			alternate_form = YES;
  		    else if (*fmt == ' ')
  			print_blank = YES;
  		    else if (*fmt == '0')
  			pad_char = '0';
  		    else
  			break;
  		}
  
  		/*
  		 * Check if a width was specified
  		 */
  		if (apr_isdigit(*fmt)) {
  		    STR_TO_DEC(fmt, min_width);
  		    adjust_width = YES;
  		}
  		else if (*fmt == '*') {
  		    min_width = va_arg(ap, int);
  		    fmt++;
  		    adjust_width = YES;
  		    if (min_width < 0) {
  			adjust = LEFT;
  			min_width = -min_width;
  		    }
  		}
  		else
  		    adjust_width = NO;
  
  		/*
  		 * Check if a precision was specified
  		 *
  		 * XXX: an unreasonable amount of precision may be specified
  		 * resulting in overflow of num_buf. Currently we
  		 * ignore this possibility.
  		 */
  		if (*fmt == '.') {
  		    adjust_precision = YES;
  		    fmt++;
  		    if (apr_isdigit(*fmt)) {
  			STR_TO_DEC(fmt, precision);
  		    }
  		    else if (*fmt == '*') {
  			precision = va_arg(ap, int);
  			fmt++;
  			if (precision < 0)
  			    precision = 0;
  		    }
  		    else
  			precision = 0;
  		}
  		else
  		    adjust_precision = NO;
  	    }
  	    else
  		adjust_precision = adjust_width = NO;
  
  	    /*
  	     * Modifier check
  	     */
  	    if (*fmt == 'l') {
  		is_long = YES;
  		fmt++;
  	    }
  	    else {
  		if (*fmt == 'h')  /* "short" backward compatibility */
  		    ++fmt;
  		is_long = NO;
  	    }
  
  	    /*
  	     * Argument extraction and printing.
  	     * First we determine the argument type.
  	     * Then, we convert the argument to a string.
  	     * On exit from the switch, s points to the string that
  	     * must be printed, s_len has the length of the string
  	     * The precision requirements, if any, are reflected in s_len.
  	     *
  	     * NOTE: pad_char may be set to '0' because of the 0 flag.
  	     *   It is reset to ' ' by non-numeric formats
  	     */
  	    switch (*fmt) {
  	    case 'u':
  		if (is_long)
  		    i_num = va_arg(ap, u_wide_int);
  		else
  		    i_num = (wide_int) va_arg(ap, unsigned int);
  		s = conv_10(i_num, 1, &is_negative,
  			    &num_buf[NUM_BUF_SIZE], &s_len);
  		FIX_PRECISION(adjust_precision, precision, s, s_len);
  		break;
  
  	    case 'd':
  	    case 'i':
  		if (is_long)
  		    i_num = va_arg(ap, wide_int);
  		else
  		    i_num = (wide_int) va_arg(ap, int);
  		s = conv_10(i_num, 0, &is_negative,
  			    &num_buf[NUM_BUF_SIZE], &s_len);
  		FIX_PRECISION(adjust_precision, precision, s, s_len);
  
  		if (is_negative)
  		    prefix_char = '-';
  		else if (print_sign)
  		    prefix_char = '+';
  		else if (print_blank)
  		    prefix_char = ' ';
  		break;
  
  
  	    case 'o':
  		if (is_long)
  		    ui_num = va_arg(ap, u_wide_int);
  		else
  		    ui_num = (u_wide_int) va_arg(ap, unsigned int);
  		s = conv_p2(ui_num, 3, *fmt,
  			    &num_buf[NUM_BUF_SIZE], &s_len);
  		FIX_PRECISION(adjust_precision, precision, s, s_len);
  		if (alternate_form && *s != '0') {
  		    *--s = '0';
  		    s_len++;
  		}
  		break;
  
  
  	    case 'x':
  	    case 'X':
  		if (is_long)
  		    ui_num = (u_wide_int) va_arg(ap, u_wide_int);
  		else
  		    ui_num = (u_wide_int) va_arg(ap, unsigned int);
  		s = conv_p2(ui_num, 4, *fmt,
  			    &num_buf[NUM_BUF_SIZE], &s_len);
  		FIX_PRECISION(adjust_precision, precision, s, s_len);
  		if (alternate_form && i_num != 0) {
  		    *--s = *fmt;	/* 'x' or 'X' */
  		    *--s = '0';
  		    s_len += 2;
  		}
  		break;
  
  
  	    case 's':
  		s = va_arg(ap, char *);
  		if (s != NULL) {
  		    s_len = strlen(s);
  		    if (adjust_precision && precision < s_len)
  			s_len = precision;
  		}
  		else {
  		    s = S_NULL;
  		    s_len = S_NULL_LEN;
  		}
  		pad_char = ' ';
  		break;
  
  
  	    case 'f':
  	    case 'e':
  	    case 'E':
  		fp_num = va_arg(ap, double);
  		/*
  		 * * We use &num_buf[ 1 ], so that we have room for the sign
  		 */
  		s = conv_fp(*fmt, fp_num, alternate_form,
  			(adjust_precision == NO) ? FLOAT_DIGITS : precision,
  			    &is_negative, &num_buf[1], &s_len);
  		if (is_negative)
  		    prefix_char = '-';
  		else if (print_sign)
  		    prefix_char = '+';
  		else if (print_blank)
  		    prefix_char = ' ';
  		break;
  
  
  	    case 'g':
  	    case 'G':
  		if (adjust_precision == NO)
  		    precision = FLOAT_DIGITS;
  		else if (precision == 0)
  		    precision = 1;
  		/*
  		 * * We use &num_buf[ 1 ], so that we have room for the sign
  		 */
  		s = apr_gcvt(va_arg(ap, double), precision, &num_buf[1],
  		            alternate_form);
  		if (*s == '-')
  		    prefix_char = *s++;
  		else if (print_sign)
  		    prefix_char = '+';
  		else if (print_blank)
  		    prefix_char = ' ';
  
  		s_len = strlen(s);
  
  		if (alternate_form && (q = strchr(s, '.')) == NULL) {
  		    s[s_len++] = '.';
  		    s[s_len] = '\0'; /* delimit for following strchr() */
  		}
  		if (*fmt == 'G' && (q = strchr(s, 'e')) != NULL)
  		    *q = 'E';
  		break;
  
  
  	    case 'c':
  		char_buf[0] = (char) (va_arg(ap, int));
  		s = &char_buf[0];
  		s_len = 1;
  		pad_char = ' ';
  		break;
  
  
  	    case '%':
  		char_buf[0] = '%';
  		s = &char_buf[0];
  		s_len = 1;
  		pad_char = ' ';
  		break;
  
  
  	    case 'n':
  		*(va_arg(ap, int *)) = cc;
  		break;
  
  		/*
  		 * This is where we extend the printf format, with a second
  		 * type specifier
  		 */
  	    case 'p':
  		switch(*++fmt) {
  		    /*
  		     * If the pointer size is equal to the size of an unsigned
  		     * integer we convert the pointer to a hex number, otherwise 
  		     * we print "%p" to indicate that we don't handle "%p".
  		     */
  		case 'p':
  		    ui_num = (u_wide_int) va_arg(ap, void *);
  
  		    if (sizeof(char *) <= sizeof(u_wide_int))
  				s = conv_p2(ui_num, 4, 'x',
  					    &num_buf[NUM_BUF_SIZE], &s_len);
  		    else {
  			s = "%p";
  			s_len = 2;
  			prefix_char = NUL;
  		    }
  		    pad_char = ' ';
  		    break;
  
  		    /* print a struct sockaddr_in as a.b.c.d:port */
  		case 'I':
  		    {
  			struct sockaddr_in *si;
  
  			si = va_arg(ap, struct sockaddr_in *);
  			if (si != NULL) {
  			    s = conv_sockaddr_in(si, &num_buf[NUM_BUF_SIZE], &s_len);
  			    if (adjust_precision && precision < s_len)
  				s_len = precision;
  			}
  			else {
  			    s = S_NULL;
  			    s_len = S_NULL_LEN;
  			}
  			pad_char = ' ';
  		    }
  		    break;
  
  		    /* print a struct in_addr as a.b.c.d */
  		case 'A':
  		    {
  			struct in_addr *ia;
  
  			ia = va_arg(ap, struct in_addr *);
  			if (ia != NULL) {
  			    s = conv_in_addr(ia, &num_buf[NUM_BUF_SIZE], &s_len);
  			    if (adjust_precision && precision < s_len)
  				s_len = precision;
  			}
  			else {
  			    s = S_NULL;
  			    s_len = S_NULL_LEN;
  			}
  			pad_char = ' ';
  		    }
  		    break;
  
  		case NUL:
  		    /* if %p ends the string, oh well ignore it */
  		    continue;
  
  		default:
  		    s = "bogus %p";
  		    s_len = 8;
  		    prefix_char = NUL;
  		    break;
  		}
  		break;
  
  	    case NUL:
  		/*
  		 * The last character of the format string was %.
  		 * We ignore it.
  		 */
  		continue;
  
  
  		/*
  		 * The default case is for unrecognized %'s.
  		 * We print %<char> to help the user identify what
  		 * option is not understood.
  		 * This is also useful in case the user wants to pass
  		 * the output of format_converter to another function
  		 * that understands some other %<char> (like syslog).
  		 * Note that we can't point s inside fmt because the
  		 * unknown <char> could be preceded by width etc.
  		 */
  	    default:
  		char_buf[0] = '%';
  		char_buf[1] = *fmt;
  		s = char_buf;
  		s_len = 2;
  		pad_char = ' ';
  		break;
  	    }
  
  	    if (prefix_char != NUL && s != S_NULL && s != char_buf) {
  		*--s = prefix_char;
  		s_len++;
  	    }
  
  	    if (adjust_width && adjust == RIGHT && min_width > s_len) {
  		if (pad_char == '0' && prefix_char != NUL) {
  		    INS_CHAR(*s, sp, bep, cc);
  		    s++;
  		    s_len--;
  		    min_width--;
  		}
  		PAD(min_width, s_len, pad_char);
  	    }
  
  	    /*
  	     * Print the string s. 
  	     */
  	    for (i = s_len; i != 0; i--) {
  		INS_CHAR(*s, sp, bep, cc);
  		s++;
  	    }
  
  	    if (adjust_width && adjust == LEFT && min_width > s_len)
  		PAD(min_width, s_len, pad_char);
  	}
  	fmt++;
      }
      vbuff->curpos = sp;
      return cc;
  }
  
  
  static int snprintf_flush(apr_vformatter_buff_t *vbuff)
  {
      /* if the buffer fills we have to abort immediately, there is no way
       * to "flush" an apr_snprintf... there's nowhere to flush it to.
       */
      return -1;
  }
  
  
  API_EXPORT(int) apr_snprintf(char *buf, size_t len, const char *format,...)
  {
      int cc;
      va_list ap;
      apr_vformatter_buff_t vbuff;
  
      if (len == 0)
  	return 0;
  
      /* save one byte for nul terminator */
      vbuff.curpos = buf;
      vbuff.endpos = buf + len - 1;
      va_start(ap, format);
      cc = apr_vformatter(snprintf_flush, &vbuff, format, ap);
      va_end(ap);
      *vbuff.curpos = '\0';
      return (cc == -1) ? len : cc;
  }
  
  
  API_EXPORT(int) apr_vsnprintf(char *buf, size_t len, const char *format,
  			     va_list ap)
  {
      int cc;
      apr_vformatter_buff_t vbuff;
  
      if (len == 0)
  	return 0;
  
      /* save one byte for nul terminator */
      vbuff.curpos = buf;
      vbuff.endpos = buf + len - 1;
      cc = apr_vformatter(snprintf_flush, &vbuff, format, ap);
      *vbuff.curpos = '\0';
      return (cc == -1) ? len : cc;
  }
  
  
  

Mime
View raw message