From: foobar Date: Fri, 6 Jan 2006 21:19:16 +0000 (+0000) Subject: Nuke unused files X-Git-Tag: RELEASE_1_0_4~79 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=713127f5ee5cb76f1f7d220556968a790b48ff8e;p=php Nuke unused files --- diff --git a/sapi/cgi/libfcgi/LICENSE.TERMS b/sapi/cgi/libfcgi/LICENSE.TERMS deleted file mode 100644 index 7e6bdfded7..0000000000 --- a/sapi/cgi/libfcgi/LICENSE.TERMS +++ /dev/null @@ -1,28 +0,0 @@ -This FastCGI application library source and object code (the -"Software") and its documentation (the "Documentation") are -copyrighted by Open Market, Inc ("Open Market"). The following terms -apply to all files associated with the Software and Documentation -unless explicitly disclaimed in individual files. - -Open Market permits you to use, copy, modify, distribute, and license -this Software and the Documentation for any purpose, provided that -existing copyright notices are retained in all copies and that this -notice is included verbatim in any distributions. No written -agreement, license, or royalty fee is required for any of the -authorized uses. Modifications to this Software and Documentation may -be copyrighted by their authors and need not follow the licensing -terms described here. If modifications to this Software and -Documentation have new licensing terms, the new terms must be clearly -indicated on the first page of each file where they apply. - -OPEN MARKET MAKES NO EXPRESS OR IMPLIED WARRANTY WITH RESPECT TO THE -SOFTWARE OR THE DOCUMENTATION, INCLUDING WITHOUT LIMITATION ANY -WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN -NO EVENT SHALL OPEN MARKET BE LIABLE TO YOU OR ANY THIRD PARTY FOR ANY -DAMAGES ARISING FROM OR RELATING TO THIS SOFTWARE OR THE -DOCUMENTATION, INCLUDING, WITHOUT LIMITATION, ANY INDIRECT, SPECIAL OR -CONSEQUENTIAL DAMAGES OR SIMILAR DAMAGES, INCLUDING LOST PROFITS OR -LOST DATA, EVEN IF OPEN MARKET HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS". -OPEN MARKET HAS NO LIABILITY IN CONTRACT, TORT, NEGLIGENCE OR -OTHERWISE ARISING OUT OF THIS SOFTWARE OR THE DOCUMENTATION. diff --git a/sapi/cgi/libfcgi/acinclude.m4 b/sapi/cgi/libfcgi/acinclude.m4 deleted file mode 100644 index cd610142e9..0000000000 --- a/sapi/cgi/libfcgi/acinclude.m4 +++ /dev/null @@ -1,389 +0,0 @@ -dnl $Id$ - -AC_DEFUN([FCGI_COMMON_CHECKS], [ - AC_MSG_CHECKING([for sun_len in sys/un.h]) - AC_EGREP_HEADER([sun_len], [sys/un.h], - [AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_SOCKADDR_UN_SUN_LEN], [1], - [Define if sockaddr_un in sys/un.h contains a sun_len component])], - AC_MSG_RESULT([no])) - - AC_MSG_CHECKING([for fpos_t in stdio.h]) - AC_EGREP_HEADER([fpos_t], [stdio.h], - [AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_FPOS], [1], - [Define if the fpos_t typedef is in stdio.h])], - AC_MSG_RESULT([no])) - - AC_CHECK_HEADERS([sys/socket.h netdb.h netinet/in.h arpa/inet.h]) - AC_CHECK_HEADERS([sys/time.h limits.h sys/param.h unistd.h]) - - AC_MSG_CHECKING([for a fileno() prototype in stdio.h]) - AC_EGREP_HEADER([fileno], [stdio.h], - [AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_FILENO_PROTO], [1], - [Define if there's a fileno() prototype in stdio.h])], - AC_MSG_RESULT([no])) - - if test "$HAVE_SYS_SOCKET_H"; then - AC_MSG_CHECKING([for socklen_t in sys/socket.h]) - AC_EGREP_HEADER([socklen_t], [sys/socket.h], - [AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_SOCKLEN], [1], - [Define if the socklen_t typedef is in sys/socket.h])], - AC_MSG_RESULT([no])) - fi - - #-------------------------------------------------------------------- - # Do we need cross-process locking on this platform? - #-------------------------------------------------------------------- - AC_MSG_CHECKING([whether cross-process locking is required by accept()]) - case "`uname -sr`" in - IRIX\ 5.* | SunOS\ 5.* | UNIX_System_V\ 4.0) - AC_MSG_RESULT([yes]) - AC_DEFINE([USE_LOCKING], [1], - [Define if cross-process locking is required by accept()]) - ;; - *) - AC_MSG_RESULT([no]) - ;; - esac - - #-------------------------------------------------------------------- - # Does va_arg(arg, long double) crash the compiler? - # hpux 9.04 compiler does and so does Stratus FTX (uses HP's compiler) - #-------------------------------------------------------------------- - AC_MSG_CHECKING([whether va_arg(arg, long double) crashes the compiler]) - AC_TRY_COMPILE([#include ], - [long double lDblArg; va_list arg; lDblArg = va_arg(arg, long double);], - AC_MSG_RESULT([no]), - [AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_VA_ARG_LONG_DOUBLE_BUG], [1], - [Define if va_arg(arg, long double) crashes the compiler])]) - - AC_C_CONST -]) - - -dnl @synopsis ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) -dnl -dnl This macro figures out how to build C programs using POSIX -dnl threads. It sets the PTHREAD_LIBS output variable to the threads -dnl library and linker flags, and the PTHREAD_CFLAGS output variable -dnl to any special C compiler flags that are needed. (The user can also -dnl force certain compiler flags/libs to be tested by setting these -dnl environment variables.) -dnl -dnl Also sets PTHREAD_CC to any special C compiler that is needed for -dnl multi-threaded programs (defaults to the value of CC otherwise). -dnl (This is necessary on AIX to use the special cc_r compiler alias.) -dnl -dnl If you are only building threads programs, you may wish to -dnl use these variables in your default LIBS, CFLAGS, and CC: -dnl -dnl LIBS="$PTHREAD_LIBS $LIBS" -dnl CFLAGS="$CFLAGS $PTHREAD_CFLAGS" -dnl CC="$PTHREAD_CC" -dnl -dnl In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute -dnl constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE -dnl to that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). -dnl -dnl ACTION-IF-FOUND is a list of shell commands to run if a threads -dnl library is found, and ACTION-IF-NOT-FOUND is a list of commands -dnl to run it if it is not found. If ACTION-IF-FOUND is not specified, -dnl the default action will define HAVE_PTHREAD. -dnl -dnl Please let the authors know if this macro fails on any platform, -dnl or if you have any other suggestions or comments. This macro was -dnl based on work by SGJ on autoconf scripts for FFTW (www.fftw.org) -dnl (with help from M. Frigo), as well as ac_pthread and hb_pthread -dnl macros posted by AFC to the autoconf macro repository. We are also -dnl grateful for the helpful feedback of numerous users. -dnl -dnl @version $Id$ -dnl @author Steven G. Johnson and Alejandro Forero Cuervo - -AC_DEFUN([ACX_PTHREAD], [ -AC_REQUIRE([AC_CANONICAL_HOST]) -acx_pthread_ok=no - -# First, check if the POSIX threads header, pthread.h, is available. -# If it isn't, don't bother looking for the threads libraries. -AC_CHECK_HEADER(pthread.h, , acx_pthread_ok=noheader) - -# We must check for the threads library under a number of different -# names; the ordering is very important because some systems -# (e.g. DEC) have both -lpthread and -lpthreads, where one of the -# libraries is broken (non-POSIX). - -# First of all, check if the user has set any of the PTHREAD_LIBS, -# etcetera environment variables, and if threads linking works using -# them: -if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then - save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - save_LIBS="$LIBS" - LIBS="$PTHREAD_LIBS $LIBS" - AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) - AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes) - AC_MSG_RESULT($acx_pthread_ok) - if test x"$acx_pthread_ok" = xno; then - PTHREAD_LIBS="" - PTHREAD_CFLAGS="" - fi - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" -fi - -# Create a list of thread flags to try. Items starting with a "-" are -# C compiler flags, and other items are library names, except for "none" -# which indicates that we try without any flags at all. - -acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt" - -# The ordering *is* (sometimes) important. Some notes on the -# individual items follow: - -# pthreads: AIX (must check this before -lpthread) -# none: in case threads are in libc; should be tried before -Kthread and -# other compiler flags to prevent continual compiler warnings -# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) -# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) -# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) -# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) -# -pthreads: Solaris/gcc -# -mthreads: Mingw32/gcc, Lynx/gcc -# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it -# doesn't hurt to check since this sometimes defines pthreads too; -# also defines -D_REENTRANT) -# pthread: Linux, etcetera -# --thread-safe: KAI C++ - -case "${host_cpu}-${host_os}" in - *solaris*) - - # On Solaris (at least, for some versions), libc contains stubbed - # (non-functional) versions of the pthreads routines, so link-based - # tests will erroneously succeed. (We need to link with -pthread or - # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather - # a function called by this macro, so we could check for that, but - # who knows whether they'll stub that too in a future libc.) So, - # we'll just look for -pthreads and -lpthread first: - - acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags" - ;; -esac - -if test x"$acx_pthread_ok" = xno; then -for flag in $acx_pthread_flags; do - - case $flag in - none) - AC_MSG_CHECKING([whether pthreads work without any flags]) - ;; - - -*) - AC_MSG_CHECKING([whether pthreads work with $flag]) - PTHREAD_CFLAGS="$flag" - ;; - - *) - AC_MSG_CHECKING([for the pthreads library -l$flag]) - PTHREAD_LIBS="-l$flag" - ;; - esac - - save_LIBS="$LIBS" - save_CFLAGS="$CFLAGS" - LIBS="$PTHREAD_LIBS $LIBS" - CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - - # Check for various functions. We must include pthread.h, - # since some functions may be macros. (On the Sequent, we - # need a special flag -Kthread to make this header compile.) - # We check for pthread_join because it is in -lpthread on IRIX - # while pthread_create is in libc. We check for pthread_attr_init - # due to DEC craziness with -lpthreads. We check for - # pthread_cleanup_push because it is one of the few pthread - # functions on Solaris that doesn't have a non-functional libc stub. - # We try pthread_create on general principles. - AC_TRY_LINK([#include ], - [pthread_t th; pthread_join(th, 0); - pthread_attr_init(0); pthread_cleanup_push(0, 0); - pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], - [acx_pthread_ok=yes]) - - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" - - AC_MSG_RESULT($acx_pthread_ok) - if test "x$acx_pthread_ok" = xyes; then - break; - fi - - PTHREAD_LIBS="" - PTHREAD_CFLAGS="" -done -fi - -# Various other checks: -if test "x$acx_pthread_ok" = xyes; then - save_LIBS="$LIBS" - LIBS="$PTHREAD_LIBS $LIBS" - save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - - # Detect AIX lossage: threads are created detached by default - # and the JOINABLE attribute has a nonstandard name (UNDETACHED). - AC_MSG_CHECKING([for joinable pthread attribute]) - AC_TRY_LINK([#include ], - [int attr=PTHREAD_CREATE_JOINABLE;], - ok=PTHREAD_CREATE_JOINABLE, ok=unknown) - if test x"$ok" = xunknown; then - AC_TRY_LINK([#include ], - [int attr=PTHREAD_CREATE_UNDETACHED;], - ok=PTHREAD_CREATE_UNDETACHED, ok=unknown) - fi - if test x"$ok" != xPTHREAD_CREATE_JOINABLE; then - AC_DEFINE(PTHREAD_CREATE_JOINABLE, $ok, - [Define to the necessary symbol if this constant - uses a non-standard name on your system.]) - fi - AC_MSG_RESULT(${ok}) - if test x"$ok" = xunknown; then - AC_MSG_WARN([we do not know how to create joinable pthreads]) - fi - - AC_MSG_CHECKING([if more special flags are required for pthreads]) - flag=no - case "${host_cpu}-${host_os}" in - *-aix* | *-freebsd*) flag="-D_THREAD_SAFE";; - *solaris* | alpha*-osf*) flag="-D_REENTRANT";; - esac - AC_MSG_RESULT(${flag}) - if test "x$flag" != xno; then - PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" - fi - - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" - - # More AIX lossage: must compile with cc_r - AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC}) -else - PTHREAD_CC="$CC" -fi - -AC_SUBST(PTHREAD_LIBS) -AC_SUBST(PTHREAD_CFLAGS) -AC_SUBST(PTHREAD_CC) - -# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: -if test x"$acx_pthread_ok" = xyes; then - ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) - : -else - acx_pthread_ok=no - $2 -fi - -])dnl ACX_PTHREAD - - - -dnl @synopsis AC_PROG_CC_WARNINGS([ANSI]) -dnl -dnl Enables a reasonable set of warnings for the C compiler. Optionally, -dnl if the first argument is nonempty, turns on flags which enforce and/or -dnl enable proper ANSI C if such flags are known to the compiler used. -dnl -dnl Currently this macro knows about GCC, Solaris C compiler, -dnl Digital Unix C compiler, C for AIX Compiler, HP-UX C compiler, -dnl and IRIX C compiler. -dnl -dnl @version $Id$ -dnl @author Ville Laurikari -dnl -AC_DEFUN([AC_PROG_CC_WARNINGS], [ - ansi=$1 - if test -z "$ansi"; then - msg="for C compiler warning flags" - else - msg="for C compiler warning and ANSI conformance flags" - fi - AC_CACHE_CHECK($msg, ac_cv_prog_cc_warnings, [ - if test -n "$CC"; then - cat > conftest.c <&1 | grep "Xc.*strict ANSI C" > /dev/null 2>&1 && - $CC -c -v -Xc conftest.c > /dev/null 2>&1 && - test -f conftest.o; then - if test -z "$ansi"; then - ac_cv_prog_cc_warnings="-v" - else - ac_cv_prog_cc_warnings="-v -Xc" - fi - - dnl HP-UX C compiler - elif $CC > /dev/null 2>&1 && - $CC -c -Aa +w1 conftest.c > /dev/null 2>&1 && - test -f conftest.o; then - if test -z "$ansi"; then - ac_cv_prog_cc_warnings="+w1" - else - ac_cv_prog_cc_warnings="+w1 -Aa" - fi - - dnl Digital Unix C compiler - elif ! $CC > /dev/null 2>&1 && - $CC -c -verbose -w0 -warnprotos -std1 conftest.c > /dev/null 2>&1 && - test -f conftest.o; then - if test -z "$ansi"; then - ac_cv_prog_cc_warnings="-verbose -w0 -warnprotos" - else - ac_cv_prog_cc_warnings="-verbose -w0 -warnprotos -std1" - fi - - dnl C for AIX Compiler - elif $CC > /dev/null 2>&1 | grep AIX > /dev/null 2>&1 && - $CC -c -qlanglvl=ansi -qinfo=all conftest.c > /dev/null 2>&1 && - test -f conftest.o; then - if test -z "$ansi"; then - ac_cv_prog_cc_warnings="-qsrcmsg -qinfo=all:noppt:noppc:noobs:nocnd" - else - ac_cv_prog_cc_warnings="-qsrcmsg -qinfo=all:noppt:noppc:noobs:nocnd -qlanglvl=ansi" - fi - - dnl IRIX C compiler - elif $CC -fullwarn -ansi -ansiE > /dev/null 2>&1 && - test -f conftest.o; then - if test -z "$ansi"; then - ac_cv_prog_cc_warnings="-fullwarn" - else - ac_cv_prog_cc_warnings="-fullwarn -ansi -ansiE" - fi - - fi - rm -f conftest.* - fi - if test -n "$ac_cv_prog_cc_warnings"; then - CFLAGS="$CFLAGS $ac_cv_prog_cc_warnings" - else - ac_cv_prog_cc_warnings="unknown" - fi - ]) -]) - - diff --git a/sapi/cgi/libfcgi/fcgi_stdio.c b/sapi/cgi/libfcgi/fcgi_stdio.c deleted file mode 100644 index 39a56315fd..0000000000 --- a/sapi/cgi/libfcgi/fcgi_stdio.c +++ /dev/null @@ -1,801 +0,0 @@ -/* - * fcgi_stdio.c -- - * - * FastCGI-stdio compatibility package - * - * - * Copyright (c) 1996 Open Market, Inc. - * - * See the file "LICENSE.TERMS" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. - * - */ - -#ifndef lint -static const char rcsid[] = "$Id$"; -#endif /* not lint */ - -#include /* for errno */ -#include /* for va_arg */ -#include /* for malloc */ -#include /* for strerror */ - -#include "fcgi_config.h" - -#ifdef HAVE_UNISTD_H -#include -#endif - -#ifdef _WIN32 -#define DLLAPI __declspec(dllexport) -#endif - -#include "fcgiapp.h" -#include "fcgios.h" -#include "fcgimisc.h" - -#define NO_FCGI_DEFINES -#include "fcgi_stdio.h" -#undef NO_FCGI_DEFINES - -#ifndef _WIN32 - -extern char **environ; - -#ifdef HAVE_FILENO_PROTO -#include -#else -extern int fileno(FILE *stream); -#endif - -extern FILE *fdopen(int fildes, const char *type); -extern FILE *popen(const char *command, const char *type); -extern int pclose(FILE *stream); - -#else /* _WIN32 */ - -#define popen _popen -#define pclose _pclose - -#endif /* _WIN32 */ - -FCGI_FILE _fcgi_sF[3]; - - -/* - *---------------------------------------------------------------------- - * - * FCGI_Accept -- - * - * Accepts a new request from the HTTP server and creates - * a conventional execution environment for the request. - * - * If the application was invoked as a FastCGI server, - * the first call to FCGI_Accept indicates that the application - * has completed its initialization and is ready to accept - * a request. Subsequent calls to FCGI_Accept indicate that - * the application has completed its processing of the - * current request and is ready to accept a new request. - * - * If the application was invoked as a CGI program, the first - * call to FCGI_Accept is essentially a no-op and the second - * call returns EOF (-1). - * - * Results: - * 0 for successful call, -1 for error (application should exit). - * - * Side effects: - * If the application was invoked as a FastCGI server, - * and this is not the first call to this procedure, - * FCGI_Accept first performs the equivalent of FCGI_Finish. - * - * On every call, FCGI_Accept accepts the new request and - * reads the FCGI_PARAMS stream into an environment array, - * i.e. a NULL-terminated array of strings of the form - * ``name=value''. It assigns a pointer to this array - * to the global variable environ, used by the standard - * library function getenv. It creates new FCGI_FILE *s - * representing input from the HTTP server, output to the HTTP - * server, and error output to the HTTP server, and assigns these - * new files to stdin, stdout, and stderr respectively. - * - * DO NOT mutate or retain pointers to environ or any values - * contained in it (e.g. to the result of calling getenv(3)), - * since these are freed by the next call to FCGI_Finish or - * FCGI_Accept. In particular do not use setenv(3) or putenv(3) - * in conjunction with FCGI_Accept. - * - *---------------------------------------------------------------------- - */ -static int acceptCalled = FALSE; -static int isCGI = FALSE; - -int FCGI_Accept(void) -{ - if(!acceptCalled) { - /* - * First call to FCGI_Accept. Is application running - * as FastCGI or as CGI? - */ - isCGI = FCGX_IsCGI(); - acceptCalled = TRUE; - atexit(&FCGI_Finish); - } else if(isCGI) { - /* - * Not first call to FCGI_Accept and running as CGI means - * application is done. - */ - return(EOF); - } - if(isCGI) { - FCGI_stdin->stdio_stream = stdin; - FCGI_stdin->fcgx_stream = NULL; - FCGI_stdout->stdio_stream = stdout; - FCGI_stdout->fcgx_stream = NULL; - FCGI_stderr->stdio_stream = stderr; - FCGI_stderr->fcgx_stream = NULL; - } else { - FCGX_Stream *in, *out, *error; - FCGX_ParamArray envp; - int acceptResult = FCGX_Accept(&in, &out, &error, &envp); - if(acceptResult < 0) { - return acceptResult; - } - FCGI_stdin->stdio_stream = NULL; - FCGI_stdin->fcgx_stream = in; - FCGI_stdout->stdio_stream = NULL; - FCGI_stdout->fcgx_stream = out; - FCGI_stderr->stdio_stream = NULL; - FCGI_stderr->fcgx_stream = error; - environ = envp; - } - return 0; -} - -/* - *---------------------------------------------------------------------- - * - * FCGI_Finish -- - * - * Finishes the current request from the HTTP server. - * - * Side effects: - * - * Flushes any buffered output to the HTTP server. Then frees - * all storage allocated by the previous call, including all - * storage reachable from the value of environ set by the previous - * call to FCGI_Accept. - * - * DO NOT use stdin, stdout, stderr, or environ between calling - * FCGI_Finish and calling FCGI_Accept. - * - * DO NOT mutate or retain pointers to environ or any values - * contained in it (e.g. to the result of calling getenv(3)), - * since these are freed by the next call to FCGI_Finish or - * FCGI_Accept. In particular do not use setenv(3) or putenv(3) - * in conjunction with FCGI_Accept. - * - *---------------------------------------------------------------------- - */ -void FCGI_Finish(void) -{ - if(!acceptCalled || isCGI) { - return; - } - FCGX_Finish(); - FCGI_stdin->fcgx_stream = NULL; - FCGI_stdout->fcgx_stream = NULL; - FCGI_stderr->fcgx_stream = NULL; - environ = NULL; -} - -/* - *---------------------------------------------------------------------- - * - * FCGI_StartFilterData -- - * - * - * The current request is for the filter role, and stdin is - * positioned at EOF of FCGI_STDIN. The call repositions - * stdin to the start of FCGI_DATA. - * If the preconditions are not met (e.g. FCGI_STDIN has not - * been read to EOF), the call sets the stream error code to - * FCGX_CALL_SEQ_ERROR. - * - * Results: - * 0 for a normal return, < 0 for error - * - *---------------------------------------------------------------------- - */ -int FCGI_StartFilterData(void) -{ - if(FCGI_stdin->stdio_stream) { - return -1; - } else { - return FCGX_StartFilterData(FCGI_stdin->fcgx_stream); - } -} - -/* - *---------------------------------------------------------------------- - * - * FCGI_SetExitStatus -- - * - * Sets the exit status for the current request. The exit status - * is the status code the request would have exited with, had - * the request been run as a CGI program. You can call - * FCGI_SetExitStatus several times during a request; the last call - * before the request ends (by calling FCGI_Accept) determines the - * value. - * - *---------------------------------------------------------------------- - */ -void FCGI_SetExitStatus(int status) -{ - if(FCGI_stdin->fcgx_stream) { - FCGX_SetExitStatus(status, FCGI_stdin->fcgx_stream); - } -} - -/* - *---------------------------------------------------------------------- - * - * FCGI_perror -- - * - * Wrapper for function defined in H&S Section 11.2 - * - *---------------------------------------------------------------------- - */ -void FCGI_perror(const char *str) -{ - FCGI_fputs(str, FCGI_stderr); - FCGI_fputs(": ", FCGI_stderr); - FCGI_fputs(strerror(OS_Errno), FCGI_stderr); - return; -} - -/* - *---------------------------------------------------------------------- - * - * FCGI_OpenFromFILE -- - * - * Constructs a new FCGI_FILE * from the FILE *stream. - * - * Results: - * NULL if stream == NULL or storage could not be allocated, - * otherwise the new FCGI_FILE *. - * - *---------------------------------------------------------------------- - */ -static FCGI_FILE *FCGI_OpenFromFILE(FILE *stream) -{ - FCGI_FILE *fp; - - if (stream == NULL) - return NULL; - - fp = (FCGI_FILE *) malloc(sizeof(FCGI_FILE)); - if (fp != NULL) - { - fp->stdio_stream = stream; - fp->fcgx_stream = NULL; - } - - return fp; -} - -/* - *---------------------------------------------------------------------- - * - * FCGI_fopen, FCGI_fclose, FCGI_fflush, FCGI_freopen -- - * - * Wrappers for functions defined in H&S Section 15.2 - * - *---------------------------------------------------------------------- - */ -FCGI_FILE *FCGI_fopen(const char *path, const char *mode) -{ - FILE * file = fopen(path, mode); - FCGI_FILE * fcgi_file = FCGI_OpenFromFILE(file); - - if (file && !fcgi_file) - fclose(file); - - return fcgi_file; -} - -int FCGI_fclose(FCGI_FILE *fp) -{ - int n = EOF; - if(fp->stdio_stream) { - n = fclose(fp->stdio_stream); - fp->stdio_stream = NULL; - } else if(fp->fcgx_stream) { - n = FCGX_FClose(fp->fcgx_stream); - fp->fcgx_stream = NULL; - } - if((fp != FCGI_stdin) && (fp != FCGI_stdout) && (fp != FCGI_stderr)) { - free(fp); - } - return n; -} - -int FCGI_fflush(FCGI_FILE *fp) -{ - if(fp == NULL) - return fflush(NULL); - if(fp->stdio_stream) - return fflush(fp->stdio_stream); - else if(fp->fcgx_stream) - return FCGX_FFlush(fp->fcgx_stream); - return EOF; -} - -FCGI_FILE *FCGI_freopen(const char *path, const char *mode, - FCGI_FILE *fp) -{ - if(fp->stdio_stream) { - if(freopen(path, mode, fp->stdio_stream) == NULL) - return NULL; - else - return fp; - } else if(fp->fcgx_stream) { - (void) FCGX_FClose(fp->fcgx_stream); - fp->stdio_stream = fopen(path, mode); - if(fp->stdio_stream == NULL) - return NULL; - else { - fp->fcgx_stream = NULL; - return fp; - } - } - return NULL; -} - -/* - *---------------------------------------------------------------------- - * - * FCGI_setvbuf, FCGI_setbuf -- - * - * Wrappers for functions defined in H&S Section 15.3 - * - *---------------------------------------------------------------------- - */ -int FCGI_setvbuf(FCGI_FILE *fp, char *buf, int bufmode, size_t size) -{ - if(fp->stdio_stream) - return setvbuf(fp->stdio_stream, buf, bufmode, size); - else { - return -1; - } -} - -void FCGI_setbuf(FCGI_FILE *fp, char *buf) -{ - if(fp->stdio_stream) - setbuf(fp->stdio_stream, buf); -} - -/* - *---------------------------------------------------------------------- - * - * FCGI_fseek, FCGI_ftell, FCGI_rewind, FCGI_fgetpos, FCGI_fsetpos -- - * - * Wrappers for functions defined in H&S Section 15.5 - * - *---------------------------------------------------------------------- - */ -int FCGI_fseek(FCGI_FILE *fp, long offset, int whence) -{ - if(fp->stdio_stream) - return fseek(fp->stdio_stream, offset, whence); - else { - OS_SetErrno(ESPIPE); - return -1; - } -} - -int FCGI_ftell(FCGI_FILE *fp) -{ - if(fp->stdio_stream) - return ftell(fp->stdio_stream); - else { - OS_SetErrno(ESPIPE); - return -1; - } -} - -void FCGI_rewind(FCGI_FILE *fp) -{ - if(fp->stdio_stream) - rewind(fp->stdio_stream); - else - OS_SetErrno(ESPIPE); -} - -#ifdef HAVE_FPOS -int FCGI_fgetpos(FCGI_FILE *fp, fpos_t *pos) -{ - if(fp->stdio_stream) - return fgetpos(fp->stdio_stream, pos); - else { - OS_SetErrno(ESPIPE); - return -1; - } -} - -int FCGI_fsetpos(FCGI_FILE *fp, const fpos_t *pos) -{ - if(fp->stdio_stream) - return fsetpos(fp->stdio_stream, pos); - else { - OS_SetErrno(ESPIPE); - return -1; - } -} -#endif - -/* - *---------------------------------------------------------------------- - * - * FCGI_fgetc, FCGI_getchar, FCGI_ungetc -- - * - * Wrappers for functions defined in H&S Section 15.6 - * - * XXX: getc and getchar are generally defined as macros - * for performance reasons - * - *---------------------------------------------------------------------- - */ -int FCGI_fgetc(FCGI_FILE *fp) -{ - if(fp->stdio_stream) - return fgetc(fp->stdio_stream); - else if(fp->fcgx_stream) - return FCGX_GetChar(fp->fcgx_stream); - return EOF; -} - -int FCGI_getchar(void) -{ - return FCGI_fgetc(FCGI_stdin); -} - -int FCGI_ungetc(int c, FCGI_FILE *fp) -{ - if(fp->stdio_stream) - return ungetc(c, fp->stdio_stream); - else if(fp->fcgx_stream) - return FCGX_UnGetChar(c, fp->fcgx_stream); - return EOF; -} - -/* - *---------------------------------------------------------------------- - * - * FCGI_fgets, FCGI_gets -- - * - * Wrappers for functions defined in H&S Section 15.7 - * - *---------------------------------------------------------------------- - */ -char *FCGI_fgets(char *str, int size, FCGI_FILE *fp) -{ - if(fp->stdio_stream) - return fgets(str, size, fp->stdio_stream); - else if(fp->fcgx_stream) - return FCGX_GetLine(str, size, fp->fcgx_stream); - return NULL; -} - -/* - * The gets() function reads characters from the standard input stream - * into the array pointed to by str until a newline character is read - * or an end-of-file condition is encountered. The newline character - * is discarded and the string is terminated with a null character. - */ -char *FCGI_gets(char *str) -{ - char *s; - int c; - - for (s = str; ((c = FCGI_getchar()) != '\n');) { - if(c == EOF) { - if(s == str) - return NULL; - else - break; - } else - *s++ = (char) c; - } - *s = 0; - return str; -} - -/* - *---------------------------------------------------------------------- - * - * Wrappers for functions defined in H&S Section 15.8 - * - * XXX: missing: fscanf, scanf - * - *---------------------------------------------------------------------- - */ - -/* - *---------------------------------------------------------------------- - * - * FCGI_fputc, FCGI_putchar -- - * - * Wrappers for functions defined in H&S Section 15.9 - * - * XXX: putc and putchar are generally defined as macros - * for performance reasons - * - *---------------------------------------------------------------------- - */ -int FCGI_fputc(int c, FCGI_FILE *fp) -{ - if(fp->stdio_stream) - return fputc(c, fp->stdio_stream); - else if(fp->fcgx_stream) - return FCGX_PutChar(c, fp->fcgx_stream); - else return EOF; -} - -int FCGI_putchar(int c) -{ - return FCGI_fputc(c, FCGI_stdout); -} - -/* - *---------------------------------------------------------------------- - * - * FCGI_fputs, FCGI_puts - * - * Wrappers for functions defined in H&S Section 15.10 - * - *---------------------------------------------------------------------- - */ -int FCGI_fputs(const char *str, FCGI_FILE *fp) -{ - if(fp->stdio_stream) - return fputs(str, fp->stdio_stream); - else if(fp->fcgx_stream) - return FCGX_PutS(str, fp->fcgx_stream); - return EOF; -} - -int FCGI_puts(const char *str) -{ - int n; - if(FCGI_stdout->stdio_stream) { - n = fputs(str, FCGI_stdout->stdio_stream); - if(n < 0) - return n; - else - return fputc('\n', FCGI_stdout->stdio_stream); - } else if(FCGI_stdout->fcgx_stream) { - n = FCGX_PutS(str, FCGI_stdout->fcgx_stream); - if(n < 0) - return n; - else - return FCGX_PutChar('\n', FCGI_stdout->fcgx_stream); - } - return EOF; -} - -/* - *---------------------------------------------------------------------- - * - * FCGI_fprintf, FCGI_printf -- - * - * Wrappers for functions defined in H&S Section 15.11 - * - *---------------------------------------------------------------------- - */ -int FCGI_fprintf(FCGI_FILE *fp, const char *format, ...) -{ - va_list ap; - int n = 0; - va_start(ap, format); - if(fp->stdio_stream) - n = vfprintf(fp->stdio_stream, format, ap); - else if(fp->fcgx_stream) - n = FCGX_VFPrintF(fp->fcgx_stream, format, ap); - va_end(ap); - return n; -} - -int FCGI_printf(const char *format, ...) -{ - va_list ap; - int n; - va_start(ap, format); - n = FCGI_vfprintf(FCGI_stdout, format, ap); - va_end(ap); - return n; -} - -/* - *---------------------------------------------------------------------- - * - * FCGI_vfprintf, FCGI_vprintf -- - * - * Wrappers for functions defined in H&S Section 15.12 - * - *---------------------------------------------------------------------- - */ -int FCGI_vfprintf(FCGI_FILE *fp, const char *format, va_list ap) -{ - if(fp->stdio_stream) - return vfprintf(fp->stdio_stream, format, ap); - else if(fp->fcgx_stream) - return FCGX_VFPrintF(fp->fcgx_stream, format, ap); - return EOF; -} - -int FCGI_vprintf(const char *format, va_list ap) -{ - if(FCGI_stdout->stdio_stream) - return vfprintf(FCGI_stdout->stdio_stream, format, ap); - else if(FCGI_stdout->fcgx_stream) - return FCGX_VFPrintF(FCGI_stdout->fcgx_stream, format, ap); - return EOF; -} - -/* - *---------------------------------------------------------------------- - * - * FCGI_fread, FCGI_fwrite -- - * - * Wrappers for functions defined in H&S Section 15.13 - * - *---------------------------------------------------------------------- - */ -size_t FCGI_fread(void *ptr, size_t size, size_t nmemb, FCGI_FILE *fp) -{ - int n; - if(fp->stdio_stream) - return fread(ptr, size, nmemb, fp->stdio_stream); - else if(fp->fcgx_stream) { - if((size * nmemb) == 0) { - return 0; - } - n = FCGX_GetStr((char *) ptr, size * nmemb, fp->fcgx_stream); - return (n/size); - } - return (size_t)EOF; -} - -size_t FCGI_fwrite(void *ptr, size_t size, size_t nmemb, FCGI_FILE *fp) -{ - int n; - if(fp->stdio_stream) - return fwrite(ptr, size, nmemb, fp->stdio_stream); - else if(fp->fcgx_stream) { - if((size * nmemb) == 0) { - return 0; - } - n = FCGX_PutStr((char *) ptr, size * nmemb, fp->fcgx_stream); - return (n/size); - } - return (size_t)EOF; -} - -/* - *---------------------------------------------------------------------- - * - * FCGI_feof, FCGI_ferror, FCGI_clearerr -- - * - * Wrappers for functions defined in H&S Section 15.14 - * - *---------------------------------------------------------------------- - */ -int FCGI_feof(FCGI_FILE *fp) -{ - if(fp->stdio_stream) { - return feof(fp->stdio_stream); - } else if (fp->fcgx_stream){ - return FCGX_HasSeenEOF(fp->fcgx_stream); - } - return -1; - -} - -int FCGI_ferror(FCGI_FILE *fp) -{ - if(fp->stdio_stream) { - return ferror(fp->stdio_stream); - } else if(fp->fcgx_stream) { - return FCGX_GetError(fp->fcgx_stream); - } - return -1; -} - -void FCGI_clearerr(FCGI_FILE *fp) -{ - if(fp->stdio_stream) { - clearerr(fp->stdio_stream); - } else if(fp->fcgx_stream) { - FCGX_ClearError(fp->fcgx_stream); - } - return; -} - -/* - *---------------------------------------------------------------------- - * - * FCGI_tmpfile -- - * - * Wrappers for function defined in H&S Section 15.16 - * - *---------------------------------------------------------------------- - */ -FCGI_FILE *FCGI_tmpfile(void) -{ - FILE * file = tmpfile(); - FCGI_FILE * fcgi_file = FCGI_OpenFromFILE(file); - - if (file && !fcgi_file) - fclose(file); - - return fcgi_file; -} - -/* - *---------------------------------------------------------------------- - * - * FCGI_fileno, FCGI_fdopen, FCGI_popen, FCGI_pclose -- - * - * Wrappers for POSIX, X/OPEN functions not in ISO C - * - *---------------------------------------------------------------------- - */ -int FCGI_fileno(FCGI_FILE *fp) -{ - if(fp->stdio_stream) - return fileno(fp->stdio_stream); - else - return -1; -} - -FCGI_FILE *FCGI_fdopen(int fd, const char *mode) -{ - FILE * file = fdopen(fd, mode); - FCGI_FILE * fcgi_file = FCGI_OpenFromFILE(file); - - if (file && !fcgi_file) - fclose(file); - - return fcgi_file; -} - -FCGI_FILE *FCGI_popen(const char *cmd, const char *type) -{ - FILE * file = popen(cmd, type); - FCGI_FILE * fcgi_file = FCGI_OpenFromFILE(file); - - if (file && !fcgi_file) - pclose(file); - - return fcgi_file; -} - -int FCGI_pclose(FCGI_FILE *fp) -{ - int n = EOF; - if (fp->stdio_stream) { - n = pclose(fp->stdio_stream); - fp->stdio_stream = NULL; - } else if(fp->fcgx_stream) { - /* - * The caller is deeply confused; don't free the storage. - */ - return EOF; - } - if((fp != FCGI_stdin) && (fp != FCGI_stdout) && (fp != FCGI_stderr)) { - free(fp); - } - return n; -} diff --git a/sapi/cgi/libfcgi/fcgiapp.c b/sapi/cgi/libfcgi/fcgiapp.c deleted file mode 100644 index cc57c93c7e..0000000000 --- a/sapi/cgi/libfcgi/fcgiapp.c +++ /dev/null @@ -1,2323 +0,0 @@ -/* - * fcgiapp.c -- - * - * FastCGI application library: request-at-a-time - * - * - * Copyright (c) 1996 Open Market, Inc. - * - * See the file "LICENSE.TERMS" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. - * - */ -#ifndef lint -static const char rcsid[] = "$Id$"; -#endif /* not lint */ - -#include -#include -#include /* for fcntl */ -#include -#include /* for memchr() */ -#include -#include -#include -#include -#include - -#include "fcgi_config.h" - -#ifdef HAVE_SYS_SOCKET_H -#include /* for getpeername */ -#endif - -#ifdef HAVE_SYS_TIME_H -#include -#endif - -#ifdef HAVE_UNISTD_H -#include -#endif - -#ifdef HAVE_LIMITS_H -#include -#endif - -#ifdef _WIN32 -#define DLLAPI __declspec(dllexport) -#endif - -#include "fcgimisc.h" -#include "fastcgi.h" -#include "fcgios.h" -#include "fcgiapp.h" - -/* - * This is a workaround for one version of the HP C compiler - * (c89 on HP-UX 9.04, also Stratus FTX), which will dump core - * if given 'long double' for varargs. - */ -#ifdef HAVE_VA_ARG_LONG_DOUBLE_BUG -#define LONG_DOUBLE double -#else -#define LONG_DOUBLE long double -#endif - -/* - * Globals - */ -static int libInitialized = 0; -static int isFastCGI = -1; -static char *webServerAddressList = NULL; -static FCGX_Request the_request; -void _FCGX_FreeStream(FCGX_Stream **streamPtr, int freeData); - -void FCGX_ShutdownPending(void) -{ - OS_ShutdownPending(); -} - -static void *Malloc(size_t size) -{ - void *result = malloc(size); - ASSERT(size == 0 || result != NULL); - return result; -} - -static char *StringCopy(char *str) -{ - int strLen = strlen(str); - char *newString = (char *)Malloc(strLen + 1); - memcpy(newString, str, strLen); - newString[strLen] = '\000'; - return newString; -} - - -/* - *---------------------------------------------------------------------- - * - * FCGX_GetChar -- - * - * Reads a byte from the input stream and returns it. - * - * Results: - * The byte, or EOF (-1) if the end of input has been reached. - * - *---------------------------------------------------------------------- - */ -int FCGX_GetChar(FCGX_Stream *stream) -{ - if(stream->rdNext != stream->stop) - return *stream->rdNext++; - if(stream->isClosed || !stream->isReader) - return EOF; - stream->fillBuffProc(stream); - stream->stopUnget = stream->rdNext; - if(stream->rdNext != stream->stop) - return *stream->rdNext++; - ASSERT(stream->isClosed); /* bug in fillBufProc if not */ - return EOF; -} - -/* - *---------------------------------------------------------------------- - * - * FCGX_GetStr -- - * - * Reads up to n consecutive bytes from the input stream - * into the character array str. Performs no interpretation - * of the input bytes. - * - * Results: - * Number of bytes read. If result is smaller than n, - * the end of input has been reached. - * - *---------------------------------------------------------------------- - */ -int FCGX_GetStr(char *str, int n, FCGX_Stream *stream) -{ - int m, bytesMoved; - - if(n <= 0) { - return 0; - } - /* - * Fast path: n bytes are already available - */ - if(n <= (stream->stop - stream->rdNext)) { - memcpy(str, stream->rdNext, n); - stream->rdNext += n; - return n; - } - /* - * General case: stream is closed or buffer fill procedure - * needs to be called - */ - bytesMoved = 0; - for (;;) { - if(stream->rdNext != stream->stop) { - m = min(n - bytesMoved, stream->stop - stream->rdNext); - memcpy(str, stream->rdNext, m); - bytesMoved += m; - stream->rdNext += m; - if(bytesMoved == n) - return bytesMoved; - str += m; - } - if(stream->isClosed || !stream->isReader) - return bytesMoved; - stream->fillBuffProc(stream); - stream->stopUnget = stream->rdNext; - } -} - -/* - *---------------------------------------------------------------------- - * - * FCGX_GetLine -- - * - * Reads up to n-1 consecutive bytes from the input stream - * into the character array str. Stops before n-1 bytes - * have been read if '\n' or EOF is read. The terminating '\n' - * is copied to str. After copying the last byte into str, - * stores a '\0' terminator. - * - * Results: - * NULL if EOF is the first thing read from the input stream, - * str otherwise. - * - *---------------------------------------------------------------------- - */ -char *FCGX_GetLine(char *str, int n, FCGX_Stream *stream) -{ - int c; - char *p = str; - - n--; - while (n > 0) { - c = FCGX_GetChar(stream); - if(c == EOF) { - if(p == str) - return NULL; - else - break; - } - *p++ = (char) c; - n--; - if(c == '\n') - break; - } - *p = '\0'; - return str; -} - -/* - *---------------------------------------------------------------------- - * - * FCGX_UnGetChar -- - * - * Pushes back the character c onto the input stream. One - * character of pushback is guaranteed once a character - * has been read. No pushback is possible for EOF. - * - * Results: - * Returns c if the pushback succeeded, EOF if not. - * - *---------------------------------------------------------------------- - */ -int FCGX_UnGetChar(int c, FCGX_Stream *stream) { - if(c == EOF - || stream->isClosed - || !stream->isReader - || stream->rdNext == stream->stopUnget) - return EOF; - --(stream->rdNext); - *stream->rdNext = (unsigned char) c; - return c; -} - -/* - *---------------------------------------------------------------------- - * - * FCGX_HasSeenEOF -- - * - * Returns EOF if end-of-file has been detected while reading - * from stream; otherwise returns 0. - * - * Note that FCGX_HasSeenEOF(s) may return 0, yet an immediately - * following FCGX_GetChar(s) may return EOF. This function, like - * the standard C stdio function feof, does not provide the - * ability to peek ahead. - * - * Results: - * EOF if end-of-file has been detected, 0 if not. - * - *---------------------------------------------------------------------- - */ -int FCGX_HasSeenEOF(FCGX_Stream *stream) { - return (stream->isClosed) ? EOF : 0; -} - -/* - *---------------------------------------------------------------------- - * - * FCGX_PutChar -- - * - * Writes a byte to the output stream. - * - * Results: - * The byte, or EOF (-1) if an error occurred. - * - *---------------------------------------------------------------------- - */ -int FCGX_PutChar(int c, FCGX_Stream *stream) -{ - if(stream->wrNext != stream->stop) - return (*stream->wrNext++ = (unsigned char) c); - if(stream->isClosed || stream->isReader) - return EOF; - stream->emptyBuffProc(stream, FALSE); - if(stream->wrNext != stream->stop) - return (*stream->wrNext++ = (unsigned char) c); - ASSERT(stream->isClosed); /* bug in emptyBuffProc if not */ - return EOF; -} - -/* - *---------------------------------------------------------------------- - * - * FCGX_PutStr -- - * - * Writes n consecutive bytes from the character array str - * into the output stream. Performs no interpretation - * of the output bytes. - * - * Results: - * Number of bytes written (n) for normal return, - * EOF (-1) if an error occurred. - * - *---------------------------------------------------------------------- - */ -int FCGX_PutStr(const char *str, int n, FCGX_Stream *stream) -{ - int m, bytesMoved; - - /* - * Fast path: room for n bytes in the buffer - */ - if(n <= (stream->stop - stream->wrNext)) { - memcpy(stream->wrNext, str, n); - stream->wrNext += n; - return n; - } - /* - * General case: stream is closed or buffer empty procedure - * needs to be called - */ - bytesMoved = 0; - for (;;) { - if(stream->wrNext != stream->stop) { - m = min(n - bytesMoved, stream->stop - stream->wrNext); - memcpy(stream->wrNext, str, m); - bytesMoved += m; - stream->wrNext += m; - if(bytesMoved == n) - return bytesMoved; - str += m; - } - if(stream->isClosed || stream->isReader) - return -1; - stream->emptyBuffProc(stream, FALSE); - } -} - -/* - *---------------------------------------------------------------------- - * - * FCGX_PutS -- - * - * Writes a character string to the output stream. - * - * Results: - * number of bytes written for normal return, - * EOF (-1) if an error occurred. - * - *---------------------------------------------------------------------- - */ -int FCGX_PutS(const char *str, FCGX_Stream *stream) -{ - return FCGX_PutStr(str, strlen(str), stream); -} - -/* - *---------------------------------------------------------------------- - * - * FCGX_FPrintF -- - * - * Performs output formatting and writes the results - * to the output stream. - * - * Results: - * number of bytes written for normal return, - * EOF (-1) if an error occurred. - * - *---------------------------------------------------------------------- - */ -int FCGX_FPrintF(FCGX_Stream *stream, const char *format, ...) -{ - int result; - va_list ap; - va_start(ap, format); - result = FCGX_VFPrintF(stream, format, ap); - va_end(ap); - return result; -} - -/* - *---------------------------------------------------------------------- - * - * FCGX_VFPrintF -- - * - * Performs output formatting and writes the results - * to the output stream. - * - * Results: - * number of bytes written for normal return, - * EOF (-1) if an error occurred. - * - *---------------------------------------------------------------------- - */ - -#define PRINTF_BUFFLEN 100 - /* - * More than sufficient space for all unmodified conversions - * except %s and %f. - */ -#define FMT_BUFFLEN 25 - /* - * Max size of a format specifier is 1 + 5 + 7 + 7 + 2 + 1 + slop - */ -static void CopyAndAdvance(char **destPtr, char **srcPtr, int n); - -int FCGX_VFPrintF(FCGX_Stream *stream, const char *format, va_list arg) -{ - char *f, *fStop, *percentPtr, *p, *fmtBuffPtr, *buffPtr; - int op, performedOp, sizeModifier, buffCount = 0, buffLen, specifierLength; - int fastPath, n, auxBuffLen = 0, buffReqd, minWidth, precision, exp; - char *auxBuffPtr = NULL; - int streamCount = 0; - char fmtBuff[FMT_BUFFLEN]; - char buff[PRINTF_BUFFLEN]; - - int intArg; - short shortArg; - long longArg; - unsigned unsignedArg; - unsigned long uLongArg; - unsigned short uShortArg; - char *charPtrArg = NULL; - void *voidPtrArg; - int *intPtrArg; - long *longPtrArg; - short *shortPtrArg; - double doubleArg = 0.0; - LONG_DOUBLE lDoubleArg = 0.0L; - - fmtBuff[0] = '%'; - f = (char *) format; - fStop = f + strlen(f); - while (f != fStop) { - percentPtr = (char *)memchr(f, '%', fStop - f); - if(percentPtr == NULL) percentPtr = fStop; - if(percentPtr != f) { - if(FCGX_PutStr(f, percentPtr - f, stream) < 0) - goto ErrorReturn; - streamCount += percentPtr - f; - f = percentPtr; - if(f == fStop) break; - } - fastPath = TRUE; - /* - * The following loop always executes either once or twice. - */ - for (;;) { - if(fastPath) { - /* - * Fast path: Scan optimistically, hoping that no flags, - * minimum field width, or precision are specified. - * Use the preallocated buffer, which is large enough - * for all fast path cases. If the conversion specifier - * is really more complex, run the loop a second time - * using the slow path. - * Note that fast path execution of %s bypasses the buffer - * and %f is not attempted on the fast path due to - * its large buffering requirements. - */ - op = *(percentPtr + 1); - switch(op) { - case 'l': - case 'L': - case 'h': - sizeModifier = op; - op = *(percentPtr + 2); - fmtBuff[1] = (char) sizeModifier; - fmtBuff[2] = (char) op; - fmtBuff[3] = '\0'; - specifierLength = 3; - break; - default: - sizeModifier = ' '; - fmtBuff[1] = (char) op; - fmtBuff[2] = '\0'; - specifierLength = 2; - break; - } - buffPtr = buff; - buffLen = PRINTF_BUFFLEN; - } else { - /* - * Slow path: Scan the conversion specifier and construct - * a new format string, compute an upper bound on the - * amount of buffering that sprintf will require, - * and allocate a larger buffer if necessary. - */ - p = percentPtr + 1; - fmtBuffPtr = &fmtBuff[1]; - /* - * Scan flags - */ - n = strspn(p, "-0+ #"); - if(n > 5) - goto ErrorReturn; - CopyAndAdvance(&fmtBuffPtr, &p, n); - /* - * Scan minimum field width - */ - n = strspn(p, "0123456789"); - if(n == 0) { - if(*p == '*') { - minWidth = va_arg(arg, int); - if(abs(minWidth) > 999999) - goto ErrorReturn; - /* - * The following use of strlen rather than the - * value returned from sprintf is because SUNOS4 - * returns a char * instead of an int count. - */ - sprintf(fmtBuffPtr, "%d", minWidth); - fmtBuffPtr += strlen(fmtBuffPtr); - p++; - } else { - minWidth = 0; - } - } else if(n <= 6) { - minWidth = strtol(p, NULL, 10); - CopyAndAdvance(&fmtBuffPtr, &p, n); - } else { - goto ErrorReturn; - } - /* - * Scan precision - */ - if(*p == '.') { - CopyAndAdvance(&fmtBuffPtr, &p, 1); - n = strspn(p, "0123456789"); - if(n == 0) { - if(*p == '*') { - precision = va_arg(arg, int); - if(precision < 0) precision = 0; - if(precision > 999999) - goto ErrorReturn; - /* - * The following use of strlen rather than the - * value returned from sprintf is because SUNOS4 - * returns a char * instead of an int count. - */ - sprintf(fmtBuffPtr, "%d", precision); - fmtBuffPtr += strlen(fmtBuffPtr); - p++; - } else { - precision = 0; - } - } else if(n <= 6) { - precision = strtol(p, NULL, 10); - CopyAndAdvance(&fmtBuffPtr, &p, n); - } else { - goto ErrorReturn; - } - } else { - precision = -1; - } - /* - * Scan size modifier and conversion operation - */ - switch(*p) { - case 'l': - case 'L': - case 'h': - sizeModifier = *p; - CopyAndAdvance(&fmtBuffPtr, &p, 1); - break; - default: - sizeModifier = ' '; - break; - } - op = *p; - CopyAndAdvance(&fmtBuffPtr, &p, 1); - ASSERT(fmtBuffPtr - fmtBuff < FMT_BUFFLEN); - *fmtBuffPtr = '\0'; - specifierLength = p - percentPtr; - /* - * Bound the required buffer size. For s and f - * conversions this requires examining the argument. - */ - switch(op) { - case 'd': - case 'i': - case 'u': - case 'o': - case 'x': - case 'X': - case 'c': - case 'p': - buffReqd = max(precision, 46); - break; - case 's': - charPtrArg = va_arg(arg, char *); - if (!charPtrArg) charPtrArg = "(null)"; - if(precision == -1) { - buffReqd = strlen(charPtrArg); - } else { - p = (char *)memchr(charPtrArg, '\0', precision); - buffReqd = - (p == NULL) ? precision : p - charPtrArg; - } - break; - case 'f': - switch(sizeModifier) { - case ' ': - doubleArg = va_arg(arg, double); - frexp(doubleArg, &exp); - break; - case 'L': - lDoubleArg = va_arg(arg, LONG_DOUBLE); - /* XXX Need to check for the presence of - * frexpl() and use it if available */ - frexp((double) lDoubleArg, &exp); - break; - default: - goto ErrorReturn; - } - if(precision == -1) precision = 6; - buffReqd = precision + 3 + ((exp > 0) ? exp/3 : 0); - break; - case 'e': - case 'E': - case 'g': - case 'G': - if(precision == -1) precision = 6; - buffReqd = precision + 8; - break; - case 'n': - case '%': - default: - goto ErrorReturn; - break; - } - buffReqd = max(buffReqd + 10, minWidth); - /* - * Allocate the buffer - */ - if(buffReqd <= PRINTF_BUFFLEN) { - buffPtr = buff; - buffLen = PRINTF_BUFFLEN; - } else { - if(auxBuffPtr == NULL || buffReqd > auxBuffLen) { - if(auxBuffPtr != NULL) free(auxBuffPtr); - auxBuffPtr = (char *)Malloc(buffReqd); - auxBuffLen = buffReqd; - if(auxBuffPtr == NULL) - goto ErrorReturn; - } - buffPtr = auxBuffPtr; - buffLen = auxBuffLen; - } - } - /* - * This giant switch statement requires the following variables - * to be set up: op, sizeModifier, arg, buffPtr, fmtBuff. - * When fastPath == FALSE and op == 's' or 'f', the argument - * has been read into charPtrArg, doubleArg, or lDoubleArg. - * The statement produces the boolean performedOp, TRUE iff - * the op/sizeModifier were executed and argument consumed; - * if performedOp, the characters written into buffPtr[] - * and the character count buffCount (== EOF meaning error). - * - * The switch cases are arranged in the same order as in the - * description of fprintf in section 15.11 of Harbison and Steele. - */ - performedOp = TRUE; - switch(op) { - case 'd': - case 'i': - switch(sizeModifier) { - case ' ': - intArg = va_arg(arg, int); - sprintf(buffPtr, fmtBuff, intArg); - buffCount = strlen(buffPtr); - break; - case 'l': - longArg = va_arg(arg, long); - sprintf(buffPtr, fmtBuff, longArg); - buffCount = strlen(buffPtr); - break; - case 'h': - shortArg = (short) va_arg(arg, int); - sprintf(buffPtr, fmtBuff, shortArg); - buffCount = strlen(buffPtr); - break; - default: - goto ErrorReturn; - } - break; - case 'u': - case 'o': - case 'x': - case 'X': - switch(sizeModifier) { - case ' ': - unsignedArg = va_arg(arg, unsigned); - sprintf(buffPtr, fmtBuff, unsignedArg); - buffCount = strlen(buffPtr); - break; - case 'l': - uLongArg = va_arg(arg, unsigned long); - sprintf(buffPtr, fmtBuff, uLongArg); - buffCount = strlen(buffPtr); - break; - case 'h': - uShortArg = (unsigned short) va_arg(arg, int); - sprintf(buffPtr, fmtBuff, uShortArg); - buffCount = strlen(buffPtr); - break; - default: - goto ErrorReturn; - } - break; - case 'c': - switch(sizeModifier) { - case ' ': - intArg = va_arg(arg, int); - sprintf(buffPtr, fmtBuff, intArg); - buffCount = strlen(buffPtr); - break; - case 'l': - /* - * XXX: Allowed by ISO C Amendment 1, but - * many platforms don't yet support wint_t - */ - goto ErrorReturn; - default: - goto ErrorReturn; - } - break; - case 's': - switch(sizeModifier) { - case ' ': - if(fastPath) { - buffPtr = va_arg(arg, char *); - buffCount = strlen(buffPtr); - buffLen = buffCount + 1; - } else { - sprintf(buffPtr, fmtBuff, charPtrArg); - buffCount = strlen(buffPtr); - } - break; - case 'l': - /* - * XXX: Don't know how to convert a sequence - * of wide characters into a byte stream, or - * even how to predict the buffering required. - */ - goto ErrorReturn; - default: - goto ErrorReturn; - } - break; - case 'p': - if(sizeModifier != ' ') - goto ErrorReturn; - voidPtrArg = va_arg(arg, void *); - sprintf(buffPtr, fmtBuff, voidPtrArg); - buffCount = strlen(buffPtr); - break; - case 'n': - switch(sizeModifier) { - case ' ': - intPtrArg = va_arg(arg, int *); - *intPtrArg = streamCount; - break; - case 'l': - longPtrArg = va_arg(arg, long *); - *longPtrArg = streamCount; - break; - case 'h': - shortPtrArg = (short *) va_arg(arg, short *); - *shortPtrArg = (short) streamCount; - break; - default: - goto ErrorReturn; - } - buffCount = 0; - break; - case 'f': - if(fastPath) { - performedOp = FALSE; - break; - } - switch(sizeModifier) { - case ' ': - sprintf(buffPtr, fmtBuff, doubleArg); - buffCount = strlen(buffPtr); - break; - case 'L': - sprintf(buffPtr, fmtBuff, lDoubleArg); - buffCount = strlen(buffPtr); - break; - default: - goto ErrorReturn; - } - break; - case 'e': - case 'E': - case 'g': - case 'G': - switch(sizeModifier) { - case ' ': - doubleArg = va_arg(arg, double); - sprintf(buffPtr, fmtBuff, doubleArg); - buffCount = strlen(buffPtr); - break; - case 'L': - lDoubleArg = va_arg(arg, LONG_DOUBLE); - sprintf(buffPtr, fmtBuff, lDoubleArg); - buffCount = strlen(buffPtr); - break; - default: - goto ErrorReturn; - } - break; - case '%': - if(sizeModifier != ' ') - goto ErrorReturn; - buff[0] = '%'; - buffCount = 1; - break; - case '\0': - goto ErrorReturn; - default: - performedOp = FALSE; - break; - } /* switch(op) */ - if(performedOp) break; - if(!fastPath) - goto ErrorReturn; - fastPath = FALSE; - } /* for (;;) */ - ASSERT(buffCount < buffLen); - if(buffCount > 0) { - if(FCGX_PutStr(buffPtr, buffCount, stream) < 0) - goto ErrorReturn; - streamCount += buffCount; - } else if(buffCount < 0) { - goto ErrorReturn; - } - f += specifierLength; - } /* while(f != fStop) */ - goto NormalReturn; - ErrorReturn: - streamCount = -1; - NormalReturn: - if(auxBuffPtr != NULL) free(auxBuffPtr); - return streamCount; -} - -/* - * Copy n characters from *srcPtr to *destPtr, then increment - * both *srcPtr and *destPtr by n. - */ -static void CopyAndAdvance(char **destPtr, char **srcPtr, int n) -{ - char *dest = *destPtr; - char *src = *srcPtr; - int i; - for (i = 0; i < n; i++) - *dest++ = *src++; - *destPtr = dest; - *srcPtr = src; -} - -/* - *---------------------------------------------------------------------- - * - * FCGX_FFlush -- - * - * Flushes any buffered output. - * - * Server-push is a legitimate application of FCGX_FFlush. - * Otherwise, FCGX_FFlush is not very useful, since FCGX_Accept - * does it implicitly. FCGX_FFlush may reduce performance - * by increasing the total number of operating system calls - * the application makes. - * - * Results: - * EOF (-1) if an error occurred. - * - *---------------------------------------------------------------------- - */ -int FCGX_FFlush(FCGX_Stream *stream) -{ - if(!stream || stream->isClosed || stream->isReader) - return 0; - stream->emptyBuffProc(stream, FALSE); - return (stream->isClosed) ? -1 : 0; -} - -/* - *---------------------------------------------------------------------- - * - * FCGX_FClose -- - * - * Performs FCGX_FFlush and closes the stream. - * - * This is not a very useful operation, since FCGX_Accept - * does it implicitly. Closing the out stream before the - * err stream results in an extra write if there's nothing - * in the err stream, and therefore reduces performance. - * - * Results: - * EOF (-1) if an error occurred. - * - *---------------------------------------------------------------------- - */ -int FCGX_FClose(FCGX_Stream *stream) -{ - if (stream == NULL) return 0; - - if(!stream->wasFCloseCalled) { - if(!stream->isReader) { - stream->emptyBuffProc(stream, TRUE); - } - stream->wasFCloseCalled = TRUE; - stream->isClosed = TRUE; - if(stream->isReader) { - stream->wrNext = stream->stop = stream->rdNext; - } else { - stream->rdNext = stream->stop = stream->wrNext; - } - } - return (stream->FCGI_errno == 0) ? 0 : EOF; -} - -/* - *---------------------------------------------------------------------- - * - * SetError -- - * - * An error has occurred; save the error code in the stream - * for diagnostic purposes and set the stream state so that - * reads return EOF and writes have no effect. - * - *---------------------------------------------------------------------- - */ -static void SetError(FCGX_Stream *stream, int FCGI_errno) -{ - /* - * Preserve only the first error. - */ - if(stream->FCGI_errno == 0) { - stream->FCGI_errno = FCGI_errno; - stream->isClosed = TRUE; - } -} - -/* - *---------------------------------------------------------------------- - * - * FCGX_GetError -- - * - * Return the stream error code. 0 means no error, > 0 - * is an errno(2) error, < 0 is an FCGX_errno error. - * - *---------------------------------------------------------------------- - */ -int FCGX_GetError(FCGX_Stream *stream) { - return stream->FCGI_errno; -} - -/* - *---------------------------------------------------------------------- - * - * FCGX_ClearError -- - * - * Clear the stream error code and end-of-file indication. - * - *---------------------------------------------------------------------- - */ -void FCGX_ClearError(FCGX_Stream *stream) { - stream->FCGI_errno = 0; - /* - * stream->isClosed = FALSE; - * XXX: should clear isClosed but work is needed to make it safe - * to do so. For example, if an application calls FClose, gets - * an I/O error on the write, calls ClearError and retries - * the FClose, FClose (really EmptyBuffProc) will write a second - * EOF record. If an application calls PutChar instead of FClose - * after the ClearError, the application will write more data. - * The stream's state must discriminate between various states - * of the stream that are now all lumped under isClosed. - */ -} - - - -/* - *---------------------------------------------------------------------- - * - * NewParams -- - * - * Creates a new Params structure. - * - * Results: - * Pointer to the new structure. - * - *---------------------------------------------------------------------- - */ -static ParamsPtr NewParams(int length) -{ - ParamsPtr result; - result = (Params *)Malloc(sizeof(Params)); - result->vec = (char **)Malloc(length * sizeof(char *)); - result->length = length; - result->cur = result->vec; - *result->cur = NULL; - return result; -} - -/* - *---------------------------------------------------------------------- - * - * FreeParams -- - * - * Frees a Params structure and all the parameters it contains. - * - * Side effects: - * env becomes invalid. - * - *---------------------------------------------------------------------- - */ -static void FreeParams(ParamsPtr *paramsPtrPtr) -{ - ParamsPtr paramsPtr = *paramsPtrPtr; - char **p; - if(paramsPtr == NULL) { - return; - } - for (p = paramsPtr->vec; p < paramsPtr->cur; p++) { - free(*p); - } - free(paramsPtr->vec); - free(paramsPtr); - *paramsPtrPtr = NULL; -} - -/* - *---------------------------------------------------------------------- - * - * PutParam -- - * - * Add a name/value pair to a Params structure. - * - * Results: - * None. - * - * Side effects: - * Parameters structure updated. - * - *---------------------------------------------------------------------- - */ -static void PutParam(ParamsPtr paramsPtr, char *nameValue) -{ - int size; - - *paramsPtr->cur++ = nameValue; - size = paramsPtr->cur - paramsPtr->vec; - if(size >= paramsPtr->length) { - paramsPtr->length *= 2; - paramsPtr->vec = (FCGX_ParamArray)realloc(paramsPtr->vec, paramsPtr->length * sizeof(char *)); - paramsPtr->cur = paramsPtr->vec + size; - } - *paramsPtr->cur = NULL; -} - - -void FCGX_PutEnv(FCGX_Request *request, char *var) -{ - char *nameValue; - char *e, **p; - int len; - - if (!strchr(var,'=')) { - return; - } - nameValue = StringCopy(var); - e = strchr(nameValue,'='); - *e = 0; - - /* find the name and replace it */ - len = strlen(nameValue); - - for (p = request->envp; p && *p; ++p) { - if((strncmp(nameValue, *p, len) == 0) && ((*p)[len] == '=')) { - free(*p); - *e = '='; - *p = nameValue; - return; - } - } - *e = '='; - /* this is a new var, add it to the environment */ - PutParam(request->paramsPtr,nameValue); - request->envp = request->paramsPtr->vec; -} - - -/* - *---------------------------------------------------------------------- - * - * FCGX_GetParam -- obtain value of FCGI parameter in environment - * - * - * Results: - * Value bound to name, NULL if name not present in the - * environment envp. Caller must not mutate the result - * or retain it past the end of this request. - * - *---------------------------------------------------------------------- - */ -char *FCGX_GetParam(const char *name, FCGX_ParamArray envp) -{ - int len; - char **p; - - if (name == NULL || envp == NULL) return NULL; - - len = strlen(name); - - for (p = envp; p && *p; ++p) { - if((strncmp(name, *p, len) == 0) && ((*p)[len] == '=')) { - return *p+len+1; - } - } - return NULL; -} - -/* - *---------------------------------------------------------------------- - * - * Start of FastCGI-specific code - * - *---------------------------------------------------------------------- - */ - -/* - *---------------------------------------------------------------------- - * - * ReadParams -- - * - * Reads FastCGI name-value pairs from stream until EOF. Converts - * each pair to name=value format and adds it to Params structure. - * - *---------------------------------------------------------------------- - */ -static int ReadParams(Params *paramsPtr, FCGX_Stream *stream) -{ - int nameLen, valueLen; - unsigned char lenBuff[3]; - char *nameValue; - - while((nameLen = FCGX_GetChar(stream)) != EOF) { - /* - * Read name length (one or four bytes) and value length - * (one or four bytes) from stream. - */ - if((nameLen & 0x80) != 0) { - if(FCGX_GetStr((char *) &lenBuff[0], 3, stream) != 3) { - SetError(stream, FCGX_PARAMS_ERROR); - return -1; - } - nameLen = ((nameLen & 0x7f) << 24) + (lenBuff[0] << 16) - + (lenBuff[1] << 8) + lenBuff[2]; - } - if((valueLen = FCGX_GetChar(stream)) == EOF) { - SetError(stream, FCGX_PARAMS_ERROR); - return -1; - } - if((valueLen & 0x80) != 0) { - if(FCGX_GetStr((char *) &lenBuff[0], 3, stream) != 3) { - SetError(stream, FCGX_PARAMS_ERROR); - return -1; - } - valueLen = ((valueLen & 0x7f) << 24) + (lenBuff[0] << 16) - + (lenBuff[1] << 8) + lenBuff[2]; - } - /* - * nameLen and valueLen are now valid; read the name and value - * from stream and construct a standard environment entry. - */ - nameValue = (char *)Malloc(nameLen + valueLen + 2); - if(FCGX_GetStr(nameValue, nameLen, stream) != nameLen) { - SetError(stream, FCGX_PARAMS_ERROR); - free(nameValue); - return -1; - } - *(nameValue + nameLen) = '='; - if(FCGX_GetStr(nameValue + nameLen + 1, valueLen, stream) - != valueLen) { - SetError(stream, FCGX_PARAMS_ERROR); - free(nameValue); - return -1; - } - *(nameValue + nameLen + valueLen + 1) = '\0'; - PutParam(paramsPtr, nameValue); - } - return 0; -} - -/* - *---------------------------------------------------------------------- - * - * MakeHeader -- - * - * Constructs an FCGI_Header struct. - * - *---------------------------------------------------------------------- - */ -static FCGI_Header MakeHeader( - int type, - int requestId, - int contentLength, - int paddingLength) -{ - FCGI_Header header; - ASSERT(contentLength >= 0 && contentLength <= FCGI_MAX_LENGTH); - ASSERT(paddingLength >= 0 && paddingLength <= 0xff); - header.version = FCGI_VERSION_1; - header.type = (unsigned char) type; - header.requestIdB1 = (unsigned char) ((requestId >> 8) & 0xff); - header.requestIdB0 = (unsigned char) ((requestId ) & 0xff); - header.contentLengthB1 = (unsigned char) ((contentLength >> 8) & 0xff); - header.contentLengthB0 = (unsigned char) ((contentLength ) & 0xff); - header.paddingLength = (unsigned char) paddingLength; - header.reserved = 0; - return header; -} - -/* - *---------------------------------------------------------------------- - * - * MakeEndRequestBody -- - * - * Constructs an FCGI_EndRequestBody struct. - * - *---------------------------------------------------------------------- - */ -static FCGI_EndRequestBody MakeEndRequestBody( - int appStatus, - int protocolStatus) -{ - FCGI_EndRequestBody body; - body.appStatusB3 = (unsigned char) ((appStatus >> 24) & 0xff); - body.appStatusB2 = (unsigned char) ((appStatus >> 16) & 0xff); - body.appStatusB1 = (unsigned char) ((appStatus >> 8) & 0xff); - body.appStatusB0 = (unsigned char) ((appStatus ) & 0xff); - body.protocolStatus = (unsigned char) protocolStatus; - memset(body.reserved, 0, sizeof(body.reserved)); - return body; -} - -/* - *---------------------------------------------------------------------- - * - * MakeUnknownTypeBody -- - * - * Constructs an FCGI_MakeUnknownTypeBody struct. - * - *---------------------------------------------------------------------- - */ -static FCGI_UnknownTypeBody MakeUnknownTypeBody( - int type) -{ - FCGI_UnknownTypeBody body; - body.type = (unsigned char) type; - memset(body.reserved, 0, sizeof(body.reserved)); - return body; -} - -/* - *---------------------------------------------------------------------- - * - * AlignInt8 -- - * - * Returns the smallest integer greater than or equal to n - * that's a multiple of 8. - * - *---------------------------------------------------------------------- - */ -static int AlignInt8(unsigned n) { - return (n + 7) & (UINT_MAX - 7); -} - -/* - *---------------------------------------------------------------------- - * - * AlignPtr8 -- - * - * Returns the smallest pointer greater than or equal to p - * that's a multiple of 8. - * - *---------------------------------------------------------------------- - */ -static unsigned char *AlignPtr8(unsigned char *p) { - unsigned long u = (unsigned long) p; - u = ((u + 7) & (ULONG_MAX - 7)) - u; - return p + u; -} - - -/* - * State associated with a stream - */ -typedef struct FCGX_Stream_Data { - unsigned char *buff; /* buffer after alignment */ - int bufflen; /* number of bytes buff can store */ - unsigned char *mBuff; /* buffer as returned by Malloc */ - unsigned char *buffStop; /* reader: last valid byte + 1 of entire buffer. - * stop generally differs from buffStop for - * readers because of record structure. - * writer: buff + bufflen */ - int type; /* reader: FCGI_PARAMS or FCGI_STDIN - * writer: FCGI_STDOUT or FCGI_STDERR */ - int eorStop; /* reader: stop stream at end-of-record */ - int skip; /* reader: don't deliver content bytes */ - int contentLen; /* reader: bytes of unread content */ - int paddingLen; /* reader: bytes of unread padding */ - int isAnythingWritten; /* writer: data has been written to ipcFd */ - int rawWrite; /* writer: write data without stream headers */ - FCGX_Request *reqDataPtr; /* request data not specific to one stream */ -} FCGX_Stream_Data; - -/* - *---------------------------------------------------------------------- - * - * WriteCloseRecords -- - * - * Writes an EOF record for the stream content if necessary. - * If this is the last writer to close, writes an FCGI_END_REQUEST - * record. - * - *---------------------------------------------------------------------- - */ -static void WriteCloseRecords(struct FCGX_Stream *stream) -{ - FCGX_Stream_Data *data = (FCGX_Stream_Data *)stream->data; - /* - * Enter rawWrite mode so final records won't be encapsulated as - * stream data. - */ - data->rawWrite = TRUE; - /* - * Generate EOF for stream content if needed. - */ - if(!(data->type == FCGI_STDERR - && stream->wrNext == data->buff - && !data->isAnythingWritten)) { - FCGI_Header header; - header = MakeHeader(data->type, data->reqDataPtr->requestId, 0, 0); - FCGX_PutStr((char *) &header, sizeof(header), stream); - }; - /* - * Generate FCGI_END_REQUEST record if needed. - */ - if(data->reqDataPtr->nWriters == 1) { - FCGI_EndRequestRecord endRequestRecord; - endRequestRecord.header = MakeHeader(FCGI_END_REQUEST, - data->reqDataPtr->requestId, - sizeof(endRequestRecord.body), 0); - endRequestRecord.body = MakeEndRequestBody( - data->reqDataPtr->appStatus, FCGI_REQUEST_COMPLETE); - FCGX_PutStr((char *) &endRequestRecord, - sizeof(endRequestRecord), stream); - } - data->reqDataPtr->nWriters--; -} - - - -static int write_it_all(int fd, char *buf, int len) -{ - int wrote; - - while (len) { - wrote = OS_Write(fd, buf, len); - if (wrote < 0) - return wrote; - len -= wrote; - buf += wrote; - } - return len; -} - -/* - *---------------------------------------------------------------------- - * - * EmptyBuffProc -- - * - * Encapsulates any buffered stream content in a FastCGI - * record. Writes the data, making the buffer empty. - * - *---------------------------------------------------------------------- - */ -static void EmptyBuffProc(struct FCGX_Stream *stream, int doClose) -{ - FCGX_Stream_Data *data = (FCGX_Stream_Data *)stream->data; - int cLen, eLen; - /* - * If the buffer contains stream data, fill in the header. - * Pad the record to a multiple of 8 bytes in length. Padding - * can't overflow the buffer because the buffer is a multiple - * of 8 bytes in length. If the buffer contains no stream - * data, reclaim the space reserved for the header. - */ - if(!data->rawWrite) { - cLen = stream->wrNext - data->buff - sizeof(FCGI_Header); - if(cLen > 0) { - eLen = AlignInt8(cLen); - /* - * Giving the padding a well-defined value keeps Purify happy. - */ - memset(stream->wrNext, 0, eLen - cLen); - stream->wrNext += eLen - cLen; - *((FCGI_Header *) data->buff) - = MakeHeader(data->type, - data->reqDataPtr->requestId, cLen, eLen - cLen); - } else { - stream->wrNext = data->buff; - } - } - if(doClose) { - WriteCloseRecords(stream); - }; - if (stream->wrNext != data->buff) { - data->isAnythingWritten = TRUE; - if (write_it_all(data->reqDataPtr->ipcFd, (char *)data->buff, stream->wrNext - data->buff) < 0) { - SetError(stream, OS_Errno); - return; - } - stream->wrNext = data->buff; - } - /* - * The buffer is empty. - */ - if(!data->rawWrite) { - stream->wrNext += sizeof(FCGI_Header); - } -} - -/* - * Return codes for Process* functions - */ -#define STREAM_RECORD 0 -#define SKIP 1 -#define BEGIN_RECORD 2 -#define MGMT_RECORD 3 - -/* - *---------------------------------------------------------------------- - * - * ProcessManagementRecord -- - * - * Reads and responds to a management record. The only type of - * management record this library understands is FCGI_GET_VALUES. - * The only variables that this library's FCGI_GET_VALUES - * understands are FCGI_MAX_CONNS, FCGI_MAX_REQS, and FCGI_MPXS_CONNS. - * Ignore other FCGI_GET_VALUES variables; respond to other - * management records with a FCGI_UNKNOWN_TYPE record. - * - *---------------------------------------------------------------------- - */ -static int ProcessManagementRecord(int type, FCGX_Stream *stream) -{ - FCGX_Stream_Data *data = (FCGX_Stream_Data *)stream->data; - ParamsPtr paramsPtr = NewParams(3); - char **pPtr; - char response[64]; /* 64 = 8 + 3*(1+1+14+1)* + padding */ - char *responseP = &response[FCGI_HEADER_LEN]; - char *name, value = '\0'; - int len, paddedLen; - if(type == FCGI_GET_VALUES) { - ReadParams(paramsPtr, stream); - if((FCGX_GetError(stream) != 0) || (data->contentLen != 0)) { - FreeParams(¶msPtr); - return FCGX_PROTOCOL_ERROR; - } - for (pPtr = paramsPtr->vec; pPtr < paramsPtr->cur; pPtr++) { - name = *pPtr; - *(strchr(name, '=')) = '\0'; - if(strcmp(name, FCGI_MAX_CONNS) == 0) { - value = '1'; - } else if(strcmp(name, FCGI_MAX_REQS) == 0) { - value = '1'; - } else if(strcmp(name, FCGI_MPXS_CONNS) == 0) { - value = '0'; - } else { - name = NULL; - } - if(name != NULL) { - len = strlen(name); - sprintf(responseP, "%c%c%s%c", len, 1, name, value); - responseP += len + 3; - } - } - len = responseP - &response[FCGI_HEADER_LEN]; - paddedLen = AlignInt8(len); - *((FCGI_Header *) response) - = MakeHeader(FCGI_GET_VALUES_RESULT, FCGI_NULL_REQUEST_ID, - len, paddedLen - len); - FreeParams(¶msPtr); - } else { - paddedLen = len = sizeof(FCGI_UnknownTypeBody); - ((FCGI_UnknownTypeRecord *) response)->header - = MakeHeader(FCGI_UNKNOWN_TYPE, FCGI_NULL_REQUEST_ID, - len, 0); - ((FCGI_UnknownTypeRecord *) response)->body - = MakeUnknownTypeBody(type); - } - if (write_it_all(data->reqDataPtr->ipcFd, response, FCGI_HEADER_LEN + paddedLen) < 0) { - SetError(stream, OS_Errno); - return -1; - } - - return MGMT_RECORD; -} - -/* - *---------------------------------------------------------------------- - * - * ProcessBeginRecord -- - * - * Reads an FCGI_BEGIN_REQUEST record. - * - * Results: - * BEGIN_RECORD for normal return. FCGX_PROTOCOL_ERROR for - * protocol error. SKIP for attempt to multiplex - * connection. -1 for error from write (errno in stream). - * - * Side effects: - * In case of BEGIN_RECORD return, stores requestId, role, - * keepConnection values, and sets isBeginProcessed = TRUE. - * - *---------------------------------------------------------------------- - */ -static int ProcessBeginRecord(int requestId, FCGX_Stream *stream) -{ - FCGX_Stream_Data *data = (FCGX_Stream_Data *)stream->data; - FCGI_BeginRequestBody body; - if(requestId == 0 || data->contentLen != sizeof(body)) { - return FCGX_PROTOCOL_ERROR; - } - if(data->reqDataPtr->isBeginProcessed) { - /* - * The Web server is multiplexing the connection. This library - * doesn't know how to handle multiplexing, so respond with - * FCGI_END_REQUEST{protocolStatus = FCGI_CANT_MPX_CONN} - */ - FCGI_EndRequestRecord endRequestRecord; - endRequestRecord.header = MakeHeader(FCGI_END_REQUEST, - requestId, sizeof(endRequestRecord.body), 0); - endRequestRecord.body - = MakeEndRequestBody(0, FCGI_CANT_MPX_CONN); - if (write_it_all(data->reqDataPtr->ipcFd, (char *)&endRequestRecord, sizeof(endRequestRecord)) < 0) { - SetError(stream, OS_Errno); - return -1; - } - - return SKIP; - } - /* - * Accept this new request. Read the record body. - */ - data->reqDataPtr->requestId = requestId; - if(FCGX_GetStr((char *) &body, sizeof(body), stream) - != sizeof(body)) { - return FCGX_PROTOCOL_ERROR; - } - data->reqDataPtr->keepConnection = (body.flags & FCGI_KEEP_CONN); - data->reqDataPtr->role = (body.roleB1 << 8) + body.roleB0; - data->reqDataPtr->isBeginProcessed = TRUE; - return BEGIN_RECORD; -} - -/* - *---------------------------------------------------------------------- - * - * ProcessHeader -- - * - * Interprets FCGI_Header. Processes FCGI_BEGIN_REQUEST and - * management records here; extracts information from stream - * records (FCGI_PARAMS, FCGI_STDIN) into stream. - * - * Results: - * >= 0 for a normal return, < 0 for error - * - * Side effects: - * XXX: Many (more than there used to be). - * If !stream->isRequestIdSet, ProcessHeader initializes - * stream->requestId from header and sets stream->isRequestIdSet - * to TRUE. ProcessHeader also sets stream->contentLen to header's - * contentLength, and sets stream->paddingLen to the header's - * paddingLength. - * - *---------------------------------------------------------------------- - */ -static int ProcessHeader(FCGI_Header header, FCGX_Stream *stream) -{ - FCGX_Stream_Data *data = (FCGX_Stream_Data *)stream->data; - int requestId; - if(header.version != FCGI_VERSION_1) { - return FCGX_UNSUPPORTED_VERSION; - } - requestId = (header.requestIdB1 << 8) - + header.requestIdB0; - data->contentLen = (header.contentLengthB1 << 8) - + header.contentLengthB0; - data->paddingLen = header.paddingLength; - if(header.type == FCGI_BEGIN_REQUEST) { - return ProcessBeginRecord(requestId, stream); - } - if(requestId == FCGI_NULL_REQUEST_ID) { - return ProcessManagementRecord(header.type, stream); - } - if(requestId != data->reqDataPtr->requestId) { - return SKIP; - } - if(header.type != data->type) { - return FCGX_PROTOCOL_ERROR; - } - return STREAM_RECORD; -} - -/* - *---------------------------------------------------------------------- - * - * FillBuffProc -- - * - * Reads bytes from the ipcFd, supplies bytes to a stream client. - * - *---------------------------------------------------------------------- - */ -static void FillBuffProc(FCGX_Stream *stream) -{ - FCGX_Stream_Data *data = (FCGX_Stream_Data *)stream->data; - FCGI_Header header; - int headerLen = 0; - int status, count; - - for (;;) { - /* - * If data->buff is empty, do a read. - */ - if(stream->rdNext == data->buffStop) { - count = OS_Read(data->reqDataPtr->ipcFd, (char *)data->buff, - data->bufflen); - if(count <= 0) { - SetError(stream, (count == 0 ? FCGX_PROTOCOL_ERROR : OS_Errno)); - return; - } - stream->rdNext = data->buff; - data->buffStop = data->buff + count; - } - /* - * Now data->buff is not empty. If the current record contains - * more content bytes, deliver all that are present in data->buff. - */ - if(data->contentLen > 0) { - count = min(data->contentLen, data->buffStop - stream->rdNext); - data->contentLen -= count; - if(!data->skip) { - stream->wrNext = stream->stop = stream->rdNext + count; - return; - } else { - stream->rdNext += count; - if(data->contentLen > 0) { - continue; - } else { - data->skip = FALSE; - } - } - } - /* - * If the current record (whose content has been fully consumed by - * the client) was padded, skip over the padding bytes. - */ - if(data->paddingLen > 0) { - count = min(data->paddingLen, data->buffStop - stream->rdNext); - data->paddingLen -= count; - stream->rdNext += count; - if(data->paddingLen > 0) { - continue; - } - } - /* - * All done with the current record, including the padding. - * If we're in a recursive call from ProcessHeader, deliver EOF. - */ - if(data->eorStop) { - stream->stop = stream->rdNext; - stream->isClosed = TRUE; - return; - } - /* - * Fill header with bytes from the input buffer. - */ - count = min((int)sizeof(header) - headerLen, - data->buffStop - stream->rdNext); - memcpy(((char *)(&header)) + headerLen, stream->rdNext, count); - headerLen += count; - stream->rdNext += count; - if(headerLen < sizeof(header)) { - continue; - }; - headerLen = 0; - /* - * Interpret header. eorStop prevents ProcessHeader from reading - * past the end-of-record when using stream to read content. - */ - data->eorStop = TRUE; - stream->stop = stream->rdNext; - status = ProcessHeader(header, stream); - data->eorStop = FALSE; - stream->isClosed = FALSE; - switch(status) { - case STREAM_RECORD: - /* - * If this stream record header marked the end of stream - * data deliver EOF to the stream client, otherwise loop - * and deliver data. - * - * XXX: If this is final stream and - * stream->rdNext != data->buffStop, buffered - * data is next request (server pipelining)? - */ - if(data->contentLen == 0) { - stream->wrNext = stream->stop = stream->rdNext; - stream->isClosed = TRUE; - return; - } - break; - case SKIP: - data->skip = TRUE; - break; - case BEGIN_RECORD: - /* - * If this header marked the beginning of a new - * request, return role information to caller. - */ - return; - break; - case MGMT_RECORD: - break; - default: - ASSERT(status < 0); - SetError(stream, status); - return; - break; - } - } -} - -/* - *---------------------------------------------------------------------- - * - * NewStream -- - * - * Creates a stream to read or write from an open ipcFd. - * The stream performs reads/writes of up to bufflen bytes. - * - *---------------------------------------------------------------------- - */ -static FCGX_Stream *NewStream( - FCGX_Request *reqDataPtr, int bufflen, int isReader, int streamType) -{ - /* - * XXX: It would be a lot cleaner to have a NewStream that only - * knows about the type FCGX_Stream, with all other - * necessary data passed in. It appears that not just - * data and the two procs are needed for initializing stream, - * but also data->buff and data->buffStop. This has implications - * for procs that want to swap buffers, too. - */ - FCGX_Stream *stream = (FCGX_Stream *)Malloc(sizeof(FCGX_Stream)); - FCGX_Stream_Data *data = (FCGX_Stream_Data *)Malloc(sizeof(FCGX_Stream_Data)); - data->reqDataPtr = reqDataPtr; - bufflen = AlignInt8(min(max(bufflen, 32), FCGI_MAX_LENGTH + 1)); - data->bufflen = bufflen; - data->mBuff = (unsigned char *)Malloc(bufflen); - data->buff = AlignPtr8(data->mBuff); - if(data->buff != data->mBuff) { - data->bufflen -= 8; - } - if(isReader) { - data->buffStop = data->buff; - } else { - data->buffStop = data->buff + data->bufflen; - } - data->type = streamType; - data->eorStop = FALSE; - data->skip = FALSE; - data->contentLen = 0; - data->paddingLen = 0; - data->isAnythingWritten = FALSE; - data->rawWrite = FALSE; - - stream->data = data; - stream->isReader = isReader; - stream->isClosed = FALSE; - stream->wasFCloseCalled = FALSE; - stream->FCGI_errno = 0; - if(isReader) { - stream->fillBuffProc = FillBuffProc; - stream->emptyBuffProc = NULL; - stream->rdNext = data->buff; - stream->stop = stream->rdNext; - stream->stopUnget = data->buff; - stream->wrNext = stream->stop; - } else { - stream->fillBuffProc = NULL; - stream->emptyBuffProc = EmptyBuffProc; - stream->wrNext = data->buff + sizeof(FCGI_Header); - stream->stop = data->buffStop; - stream->stopUnget = NULL; - stream->rdNext = stream->stop; - } - return stream; -} - -/* - *---------------------------------------------------------------------- - * - * FCGX_FreeStream -- - * - * Frees all storage allocated when *streamPtr was created, - * and nulls out *streamPtr. - * - *---------------------------------------------------------------------- - */ -void FCGX_FreeStream(FCGX_Stream **streamPtr) -{ - _FCGX_FreeStream(streamPtr, TRUE); -} - -void _FCGX_FreeStream(FCGX_Stream **streamPtr, int freeData) -{ - FCGX_Stream *stream = *streamPtr; - FCGX_Stream_Data *data; - if(stream == NULL) { - return; - } - data = (FCGX_Stream_Data *)stream->data; - if (freeData && data->reqDataPtr) free(data->reqDataPtr); - data->reqDataPtr = NULL; - free(data->mBuff); - free(data); - free(stream); - *streamPtr = NULL; -} - -/* - *---------------------------------------------------------------------- - * - * SetReaderType -- - * - * Re-initializes the stream to read data of the specified type. - * - *---------------------------------------------------------------------- - */ -static FCGX_Stream *SetReaderType(FCGX_Stream *stream, int streamType) -{ - FCGX_Stream_Data *data = (FCGX_Stream_Data *)stream->data; - ASSERT(stream->isReader); - data->type = streamType; - data->eorStop = FALSE; - data->skip = FALSE; - data->contentLen = 0; - data->paddingLen = 0; - stream->wrNext = stream->stop = stream->rdNext; - stream->isClosed = FALSE; - return stream; -} - -/* - *---------------------------------------------------------------------- - * - * NewReader -- - * - * Creates a stream to read streamType records for the given - * request. The stream performs OS reads of up to bufflen bytes. - * - *---------------------------------------------------------------------- - */ -static FCGX_Stream *NewReader(FCGX_Request *reqDataPtr, int bufflen, int streamType) -{ - return NewStream(reqDataPtr, bufflen, TRUE, streamType); -} - -/* - *---------------------------------------------------------------------- - * - * NewWriter -- - * - * Creates a stream to write streamType FastCGI records, using - * the ipcFd and RequestId contained in *reqDataPtr. - * The stream performs OS writes of up to bufflen bytes. - * - *---------------------------------------------------------------------- - */ -static FCGX_Stream *NewWriter(FCGX_Request *reqDataPtr, int bufflen, int streamType) -{ - return NewStream(reqDataPtr, bufflen, FALSE, streamType); -} - -/* - *---------------------------------------------------------------------- - * - * FCGX_CreateWriter -- - * - * Creates a stream to write streamType FastCGI records, using - * the given ipcFd and request Id. This function is provided - * for use by cgi-fcgi. In order to be defensive against misuse, - * this function leaks a little storage; cgi-fcgi doesn't care. - * - *---------------------------------------------------------------------- - */ -FCGX_Stream *FCGX_CreateWriter( - int ipcFd, - int requestId, - int bufflen, - int streamType) -{ - FCGX_Request *reqDataPtr = (FCGX_Request *)Malloc(sizeof(FCGX_Request)); - reqDataPtr->ipcFd = ipcFd; - reqDataPtr->requestId = requestId; - /* - * Suppress writing an FCGI_END_REQUEST record. - */ - reqDataPtr->nWriters = 2; - return NewWriter(reqDataPtr, bufflen, streamType); -} - -/* - *====================================================================== - * Control - *====================================================================== - */ - -/* - *---------------------------------------------------------------------- - * - * FCGX_IsCGI -- - * - * This routine determines if the process is running as a CGI or - * FastCGI process. The distinction is made by determining whether - * FCGI_LISTENSOCK_FILENO is a listener ipcFd or the end of a - * pipe (ie. standard in). - * - * Results: - * TRUE if the process is a CGI process, FALSE if FastCGI. - * - *---------------------------------------------------------------------- - */ -int FCGX_IsCGI(void) -{ - if (isFastCGI != -1) { - return !isFastCGI; - } - - if (!libInitialized) { - int rc = FCGX_Init(); - if (rc) { - /* exit() isn't great, but hey */ - /* exit((rc < 0) ? rc : -rc); */ - return 0; - } - } - - isFastCGI = OS_IsFcgi(FCGI_LISTENSOCK_FILENO); - - return !isFastCGI; -} - -/* - *---------------------------------------------------------------------- - * - * FCGX_Finish -- - * - * Finishes the current request from the HTTP server. - * - * Side effects: - * - * Finishes the request accepted by (and frees any - * storage allocated by) the previous call to FCGX_Accept. - * - * DO NOT retain pointers to the envp array or any strings - * contained in it (e.g. to the result of calling FCGX_GetParam), - * since these will be freed by the next call to FCGX_Finish - * or FCGX_Accept. - * - *---------------------------------------------------------------------- - */ - -void FCGX_Finish(void) -{ - FCGX_Finish_r(&the_request); -} - -/* - *---------------------------------------------------------------------- - * - * FCGX_Finish_r -- - * - * Finishes the current request from the HTTP server. - * - * Side effects: - * - * Finishes the request accepted by (and frees any - * storage allocated by) the previous call to FCGX_Accept. - * - * DO NOT retain pointers to the envp array or any strings - * contained in it (e.g. to the result of calling FCGX_GetParam), - * since these will be freed by the next call to FCGX_Finish - * or FCGX_Accept. - * - *---------------------------------------------------------------------- - */ -void FCGX_Finish_r(FCGX_Request *reqDataPtr) -{ - int close; - - if (reqDataPtr == NULL) { - return; - } - - close = !reqDataPtr->keepConnection; - - /* This should probably use a 'status' member instead of 'in' */ - if (reqDataPtr->in) { - close |= FCGX_FClose(reqDataPtr->err); - close |= FCGX_FClose(reqDataPtr->out); - - close |= FCGX_GetError(reqDataPtr->in); - } - - FCGX_Free(reqDataPtr, close); -} - -void FCGX_Free(FCGX_Request * request, int close) -{ - if (request == NULL) - return; - - _FCGX_FreeStream(&request->in, FALSE); - _FCGX_FreeStream(&request->out, FALSE); - _FCGX_FreeStream(&request->err, FALSE); - FreeParams(&request->paramsPtr); - request->envp = NULL; - - if (close) { - OS_IpcClose(request->ipcFd); - request->ipcFd = -1; - } -} - -int FCGX_OpenSocket(const char *path, int backlog) -{ - int rc = OS_CreateLocalIpcFd(path, backlog, 1); - if (rc == FCGI_LISTENSOCK_FILENO && isFastCGI == 0) { - /* XXX probably need to call OS_LibInit() again for Win */ - isFastCGI = 1; - } - return rc; -} - -int FCGX_InitRequest(FCGX_Request *request, int sock, int flags) -{ - memset(request, 0, sizeof(FCGX_Request)); - - /* @@@ Should check that sock is open and listening */ - request->listen_sock = sock; - - /* @@@ Should validate against "known" flags */ - request->flags = flags; - - request->ipcFd = -1; - - return 0; -} - -/* - *---------------------------------------------------------------------- - * - * FCGX_Init -- - * - * Initilize the FCGX library. This is called by FCGX_Accept() - * but must be called by the user when using FCGX_Accept_r(). - * - * Results: - * 0 for successful call. - * - *---------------------------------------------------------------------- - */ -int FCGX_Init(void) -{ - char *p; - - if (libInitialized) { - return 0; - } - - FCGX_InitRequest(&the_request, FCGI_LISTENSOCK_FILENO, 0); - - if (OS_LibInit(NULL) == -1) { - return OS_Errno ? OS_Errno : -9997; - } - - p = getenv("FCGI_WEB_SERVER_ADDRS"); - webServerAddressList = p ? StringCopy(p) : NULL; - - libInitialized = 1; - return 0; -} - -/* - *---------------------------------------------------------------------- - * - * FCGX_Accept -- - * - * Accepts a new request from the HTTP server. - * - * Results: - * 0 for successful call, -1 for error. - * - * Side effects: - * - * Finishes the request accepted by (and frees any - * storage allocated by) the previous call to FCGX_Accept. - * Creates input, output, and error streams and - * assigns them to *in, *out, and *err respectively. - * Creates a parameters data structure to be accessed - * via getenv(3) (if assigned to environ) or by FCGX_GetParam - * and assigns it to *envp. - * - * DO NOT retain pointers to the envp array or any strings - * contained in it (e.g. to the result of calling FCGX_GetParam), - * since these will be freed by the next call to FCGX_Finish - * or FCGX_Accept. - * - *---------------------------------------------------------------------- - */ - -int FCGX_Accept( - FCGX_Stream **in, - FCGX_Stream **out, - FCGX_Stream **err, - FCGX_ParamArray *envp) -{ - int rc; - - if (! libInitialized) { - rc = FCGX_Init(); - if (rc) { - return rc; - } - } - - rc = FCGX_Accept_r(&the_request); - - *in = the_request.in; - *out = the_request.out; - *err = the_request.err; - *envp = the_request.envp; - - return rc; -} - -/* - *---------------------------------------------------------------------- - * - * FCGX_Accept_r -- - * - * Accepts a new request from the HTTP server. - * - * Results: - * 0 for successful call, -1 for error. - * - * Side effects: - * - * Finishes the request accepted by (and frees any - * storage allocated by) the previous call to FCGX_Accept. - * Creates input, output, and error streams and - * assigns them to *in, *out, and *err respectively. - * Creates a parameters data structure to be accessed - * via getenv(3) (if assigned to environ) or by FCGX_GetParam - * and assigns it to *envp. - * - * DO NOT retain pointers to the envp array or any strings - * contained in it (e.g. to the result of calling FCGX_GetParam), - * since these will be freed by the next call to FCGX_Finish - * or FCGX_Accept. - * - *---------------------------------------------------------------------- - */ -int FCGX_Accept_r(FCGX_Request *reqDataPtr) -{ - if (!libInitialized) { - return -9998; - } - - /* Finish the current request, if any. */ - FCGX_Finish_r(reqDataPtr); - - for (;;) { - /* - * If a connection isn't open, accept a new connection (blocking). - * If an OS error occurs in accepting the connection, - * return -1 to the caller, who should exit. - */ - if (reqDataPtr->ipcFd < 0) { - int fail_on_intr = reqDataPtr->flags & FCGI_FAIL_ACCEPT_ON_INTR; - - reqDataPtr->ipcFd = OS_Accept(reqDataPtr->listen_sock, fail_on_intr, webServerAddressList); - if (reqDataPtr->ipcFd < 0) { - return (errno > 0) ? (0 - errno) : -9999; - } - } - /* - * A connection is open. Read from the connection in order to - * get the request's role and environment. If protocol or other - * errors occur, close the connection and try again. - */ - reqDataPtr->isBeginProcessed = FALSE; - reqDataPtr->in = NewReader(reqDataPtr, 8192, 0); - FillBuffProc(reqDataPtr->in); - if(!reqDataPtr->isBeginProcessed) { - goto TryAgain; - } - { - char *roleStr; - switch(reqDataPtr->role) { - case FCGI_RESPONDER: - roleStr = "FCGI_ROLE=RESPONDER"; - break; - case FCGI_AUTHORIZER: - roleStr = "FCGI_ROLE=AUTHORIZER"; - break; - case FCGI_FILTER: - roleStr = "FCGI_ROLE=FILTER"; - break; - default: - goto TryAgain; - } - reqDataPtr->paramsPtr = NewParams(30); - PutParam(reqDataPtr->paramsPtr, StringCopy(roleStr)); - } - SetReaderType(reqDataPtr->in, FCGI_PARAMS); - if(ReadParams(reqDataPtr->paramsPtr, reqDataPtr->in) >= 0) { - /* - * Finished reading the environment. No errors occurred, so - * leave the connection-retry loop. - */ - break; - } - - /* - * Close the connection and try again. - */ -TryAgain: - FCGX_Free(reqDataPtr, 1); - - } /* for (;;) */ - /* - * Build the remaining data structures representing the new - * request and return successfully to the caller. - */ - SetReaderType(reqDataPtr->in, FCGI_STDIN); - reqDataPtr->out = NewWriter(reqDataPtr, 8192, FCGI_STDOUT); - reqDataPtr->err = NewWriter(reqDataPtr, 512, FCGI_STDERR); - reqDataPtr->nWriters = 2; - reqDataPtr->envp = reqDataPtr->paramsPtr->vec; - return 0; -} - -/* - *---------------------------------------------------------------------- - * - * FCGX_StartFilterData -- - * - * stream is an input stream for a FCGI_FILTER request. - * stream is positioned at EOF on FCGI_STDIN. - * Repositions stream to the start of FCGI_DATA. - * If the preconditions are not met (e.g. FCGI_STDIN has not - * been read to EOF) sets the stream error code to - * FCGX_CALL_SEQ_ERROR. - * - * Results: - * 0 for a normal return, < 0 for error - * - *---------------------------------------------------------------------- - */ - -int FCGX_StartFilterData(FCGX_Stream *stream) -{ - FCGX_Stream_Data *data = (FCGX_Stream_Data *)stream->data; - if(data->reqDataPtr->role != FCGI_FILTER - || !stream->isReader - || !stream->isClosed - || data->type != FCGI_STDIN) { - SetError(stream, FCGX_CALL_SEQ_ERROR); - return -1; - } - SetReaderType(stream, FCGI_DATA); - return 0; -} - -/* - *---------------------------------------------------------------------- - * - * FCGX_SetExitStatus -- - * - * Sets the exit status for stream's request. The exit status - * is the status code the request would have exited with, had - * the request been run as a CGI program. You can call - * SetExitStatus several times during a request; the last call - * before the request ends determines the value. - * - *---------------------------------------------------------------------- - */ - -void FCGX_SetExitStatus(int status, FCGX_Stream *stream) -{ - FCGX_Stream_Data *data = (FCGX_Stream_Data *)stream->data; - data->reqDataPtr->appStatus = status; -} - diff --git a/sapi/cgi/libfcgi/include/fastcgi.h b/sapi/cgi/libfcgi/include/fastcgi.h deleted file mode 100644 index 36b4725ba1..0000000000 --- a/sapi/cgi/libfcgi/include/fastcgi.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * fastcgi.h -- - * - * Defines for the FastCGI protocol. - * - * - * Copyright (c) 1995-1996 Open Market, Inc. - * - * See the file "LICENSE.TERMS" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. - * - * $Id$ - */ - -#ifndef _FASTCGI_H -#define _FASTCGI_H - -/* - * Listening socket file number - */ -#define FCGI_LISTENSOCK_FILENO 0 - -typedef struct { - unsigned char version; - unsigned char type; - unsigned char requestIdB1; - unsigned char requestIdB0; - unsigned char contentLengthB1; - unsigned char contentLengthB0; - unsigned char paddingLength; - unsigned char reserved; -} FCGI_Header; - -#define FCGI_MAX_LENGTH 0xffff - -/* - * Number of bytes in a FCGI_Header. Future versions of the protocol - * will not reduce this number. - */ -#define FCGI_HEADER_LEN 8 - -/* - * Value for version component of FCGI_Header - */ -#define FCGI_VERSION_1 1 - -/* - * Values for type component of FCGI_Header - */ -#define FCGI_BEGIN_REQUEST 1 -#define FCGI_ABORT_REQUEST 2 -#define FCGI_END_REQUEST 3 -#define FCGI_PARAMS 4 -#define FCGI_STDIN 5 -#define FCGI_STDOUT 6 -#define FCGI_STDERR 7 -#define FCGI_DATA 8 -#define FCGI_GET_VALUES 9 -#define FCGI_GET_VALUES_RESULT 10 -#define FCGI_UNKNOWN_TYPE 11 -#define FCGI_MAXTYPE (FCGI_UNKNOWN_TYPE) - -/* - * Value for requestId component of FCGI_Header - */ -#define FCGI_NULL_REQUEST_ID 0 - - -typedef struct { - unsigned char roleB1; - unsigned char roleB0; - unsigned char flags; - unsigned char reserved[5]; -} FCGI_BeginRequestBody; - -typedef struct { - FCGI_Header header; - FCGI_BeginRequestBody body; -} FCGI_BeginRequestRecord; - -/* - * Mask for flags component of FCGI_BeginRequestBody - */ -#define FCGI_KEEP_CONN 1 - -/* - * Values for role component of FCGI_BeginRequestBody - */ -#define FCGI_RESPONDER 1 -#define FCGI_AUTHORIZER 2 -#define FCGI_FILTER 3 - - -typedef struct { - unsigned char appStatusB3; - unsigned char appStatusB2; - unsigned char appStatusB1; - unsigned char appStatusB0; - unsigned char protocolStatus; - unsigned char reserved[3]; -} FCGI_EndRequestBody; - -typedef struct { - FCGI_Header header; - FCGI_EndRequestBody body; -} FCGI_EndRequestRecord; - -/* - * Values for protocolStatus component of FCGI_EndRequestBody - */ -#define FCGI_REQUEST_COMPLETE 0 -#define FCGI_CANT_MPX_CONN 1 -#define FCGI_OVERLOADED 2 -#define FCGI_UNKNOWN_ROLE 3 - - -/* - * Variable names for FCGI_GET_VALUES / FCGI_GET_VALUES_RESULT records - */ -#define FCGI_MAX_CONNS "FCGI_MAX_CONNS" -#define FCGI_MAX_REQS "FCGI_MAX_REQS" -#define FCGI_MPXS_CONNS "FCGI_MPXS_CONNS" - - -typedef struct { - unsigned char type; - unsigned char reserved[7]; -} FCGI_UnknownTypeBody; - -typedef struct { - FCGI_Header header; - FCGI_UnknownTypeBody body; -} FCGI_UnknownTypeRecord; - -#endif /* _FASTCGI_H */ - diff --git a/sapi/cgi/libfcgi/include/fcgi_config.h b/sapi/cgi/libfcgi/include/fcgi_config.h deleted file mode 100644 index 07236793b2..0000000000 --- a/sapi/cgi/libfcgi/include/fcgi_config.h +++ /dev/null @@ -1,7 +0,0 @@ -/* hack workaround for libfcgi configure */ -#ifdef _WIN32 -#include "fcgi_config_win32.h" -#else -#include -#endif - diff --git a/sapi/cgi/libfcgi/include/fcgi_config_win32.h b/sapi/cgi/libfcgi/include/fcgi_config_win32.h deleted file mode 100644 index a9ec224deb..0000000000 --- a/sapi/cgi/libfcgi/include/fcgi_config_win32.h +++ /dev/null @@ -1,108 +0,0 @@ -/* fcgi_config.h. Generated automatically by configure. */ -/* fcgi_config.h.in. Generated automatically from configure.in by autoheader. */ - -/* Define if you have the header file. */ -#define HAVE_ARPA_INET_H 1 - -/* Define if you have the header file. */ -#define HAVE_DLFCN_H 1 - -/* Define if there's a fileno() prototype in stdio.h */ -#define HAVE_FILENO_PROTO 1 - -/* Define if the fpos_t typedef is in stdio.h */ -#define HAVE_FPOS 1 - -/* Define if you have the header file. */ -#define HAVE_INTTYPES_H 1 - -/* Define if you have the `dnet_stub' library (-ldnet_stub). */ -/* #undef HAVE_LIBDNET_STUB */ - -/* Define if you have the `ieee' library (-lieee). */ -/* #undef HAVE_LIBIEEE */ - -/* Define if you have the `nsl' library (-lnsl). */ -#define HAVE_LIBNSL 1 - -/* Define if you have the pthread library */ -#define HAVE_LIBPTHREAD 1 - -/* Define if you have the `resolv' library (-lresolv). */ -#define HAVE_LIBRESOLV 1 - -/* Define if you have the `socket' library (-lsocket). */ -#define HAVE_LIBSOCKET 1 - -/* Define if you have the header file. */ -#define HAVE_LIMITS_H 1 - -/* Define if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define if you have the header file. */ -/* #define HAVE_NETDB_H 1 */ - -/* Define if you have the header file. */ -#define HAVE_NETINET_IN_H 1 - -/* Define if sockaddr_un in sys/un.h contains a sun_len component */ -/* #undef HAVE_SOCKADDR_UN_SUN_LEN */ - -/* Define if the socklen_t typedef is in sys/socket.h */ -/* #undef HAVE_SOCKLEN */ - -/* Define if you have the header file. */ -/* #undef HAVE_STDINT_H */ - -/* Define if you have the header file. */ -#define HAVE_STDLIB_H 1 - -/* Define if you have the `strerror' function. */ -#define HAVE_STRERROR 1 - -/* Define if you have the header file. */ -#define HAVE_STRINGS_H 1 - -/* Define if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define if you have the header file. */ -/* #define HAVE_SYS_PARAM_H 1 */ - -/* Define if you have the header file. */ -/*#define HAVE_SYS_SOCKET_H 1*/ - -/* Define if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define if you have the header file. */ -/*#define HAVE_SYS_TIME_H 1*/ - -/* Define if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define if you have the header file. */ -/*#define HAVE_UNISTD_H 1*/ - -/* Define if va_arg(arg, long double) crashes the compiler */ -/* #undef HAVE_VA_ARG_LONG_DOUBLE_BUG */ - -/* Name of package */ -#define PACKAGE "fcgi" - -/* Define if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Define if cross-process locking is required by accept() */ -#define USE_LOCKING 1 - -/* Version number of package */ -#define VERSION "2.2.2" - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define as `__inline' if that's what the C compiler calls it, or to nothing - if it is not supported. */ -/* #undef inline */ diff --git a/sapi/cgi/libfcgi/include/fcgi_config_x86.h b/sapi/cgi/libfcgi/include/fcgi_config_x86.h deleted file mode 100644 index f56b3af75d..0000000000 --- a/sapi/cgi/libfcgi/include/fcgi_config_x86.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Default fcgi_config.h when building on WinNT (configure is not run). - */ - -/* Define if you have the header file. */ -#undef HAVE_ARPA_INET_H - -/* Define if there's a fileno() prototype in stdio.h */ -#undef HAVE_FILENO_PROTO - -/* Define if you have the header file. */ -#undef HAVE_INTTYPES_H - -/* Define if we have f{set,get}pos functions */ -#define HAVE_FPOS 1 - -/* Define if you have the `dnet_stub' library (-ldnet_stub). */ -#undef HAVE_LIBDNET_STUB - -/* Define if you have the `ieee' library (-lieee). */ -#undef HAVE_LIBIEEE - -/* Define if you have the `nsl' library (-lnsl). */ -#undef HAVE_LIBNSL - -/* Define if you have the pthread library */ -#undef HAVE_LIBPTHREAD - -/* Define if you have the `resolv' library (-lresolv). */ -#undef HAVE_LIBRESOLV - -/* Define if you have the `socket' library (-lsocket). */ -#undef HAVE_LIBSOCKET - -/* Define if you have the header file. */ -#define HAVE_LIMITS_H 1 - -/* Define if we need cross-process locking */ -#undef USE_LOCKING - -/* Define if you have the header file. */ -#undef HAVE_MEMORY_H - -/* Define if you have the header file. */ -#undef HAVE_NETDB_H - -/* Define if you have the header file. */ -#undef HAVE_NETINET_IN_H - -/* Define if sockaddr_un in sys/un.h contains a sun_len component */ -#undef HAVE_SOCKADDR_UN_SUN_LEN - -/* Define if the socklen_t typedef is in sys/socket.h */ -#undef HAVE_SOCKLEN - -/* Define if you have the header file. */ -#undef HAVE_STDINT_H - -/* Define if you have the header file. */ -#undef HAVE_STDLIB_H - -/* Define if you have the `strerror' function. */ -#define HAVE_STRERROR 1 - -/* Define if you have the header file. */ -#undef HAVE_STRINGS_H - -/* Define if you have the header file. */ -#undef HAVE_STRING_H - -/* Define if you have the header file. */ -#undef HAVE_SYS_PARAM_H - -/* Define if you have the header file. */ -#undef HAVE_SYS_SOCKET_H - -/* Define if you have the header file. */ -#undef HAVE_SYS_STAT_H - -/* Define if you have the header file. */ -#undef HAVE_SYS_TIME_H - -/* Define if you have the header file. */ -#undef HAVE_SYS_TYPES_H - -/* Define if you have the header file. */ -#undef HAVE_UNISTD_H - -/* Define if va_arg(arg, long double) crashes the compiler */ -#undef HAVE_VA_ARG_LONG_DOUBLE_BUG - -/* Define if you have the ANSI C header files. */ -#undef STDC_HEADERS - -/* Define to empty if `const' does not conform to ANSI C. */ -#undef const - -/* Define as `__inline' if that's what the C compiler calls it, or to nothing - if it is not supported. */ -#undef inline - -/* Define to `int' if does not define. */ -#undef ssize_t diff --git a/sapi/cgi/libfcgi/include/fcgi_stdio.h b/sapi/cgi/libfcgi/include/fcgi_stdio.h deleted file mode 100644 index 518462b591..0000000000 --- a/sapi/cgi/libfcgi/include/fcgi_stdio.h +++ /dev/null @@ -1,249 +0,0 @@ -/* - * fcgi_stdio.h -- - * - * FastCGI-stdio compatibility package - * - * - * Copyright (c) 1996 Open Market, Inc. - * - * See the file "LICENSE.TERMS" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. - * - * $Id$ - */ - -#ifndef _FCGI_STDIO -#define _FCGI_STDIO 1 - -#include -#include -#include "fcgiapp.h" - -#if defined (c_plusplus) || defined (__cplusplus) -extern "C" { -#endif - -#ifndef DLLAPI -#ifdef _WIN32 -#if defined(_LIB) || defined(FCGI_STATIC) -#define DLLAPI -#else -#define DLLAPI __declspec(dllimport) -#endif -#else -#define DLLAPI -#endif -#endif - -/* - * Wrapper type for FILE - */ - -typedef struct { - FILE *stdio_stream; - FCGX_Stream *fcgx_stream; -} FCGI_FILE; - -/* - * The four new functions and two new macros - */ - -DLLAPI int FCGI_Accept(void); -DLLAPI void FCGI_Finish(void); -DLLAPI int FCGI_StartFilterData(void); -DLLAPI void FCGI_SetExitStatus(int status); - -#define FCGI_ToFILE(fcgi_file) (fcgi_file->stdio_stream) -#define FCGI_ToFcgiStream(fcgi_file) (fcgi_file->fcgx_stream) - -/* - * Wrapper stdin, stdout, and stderr variables, set up by FCGI_Accept() - */ - -DLLAPI extern FCGI_FILE _fcgi_sF[]; -#define FCGI_stdin (&_fcgi_sF[0]) -#define FCGI_stdout (&_fcgi_sF[1]) -#define FCGI_stderr (&_fcgi_sF[2]) - -/* - * Wrapper function prototypes, grouped according to sections - * of Harbison & Steele, "C: A Reference Manual," fourth edition, - * Prentice-Hall, 1995. - */ - -DLLAPI void FCGI_perror(const char *str); - -DLLAPI FCGI_FILE *FCGI_fopen(const char *path, const char *mode); -DLLAPI int FCGI_fclose(FCGI_FILE *fp); -DLLAPI int FCGI_fflush(FCGI_FILE *fp); -DLLAPI FCGI_FILE *FCGI_freopen(const char *path, const char *mode, FCGI_FILE *fp); - -DLLAPI int FCGI_setvbuf(FCGI_FILE *fp, char *buf, int bufmode, size_t size); -DLLAPI void FCGI_setbuf(FCGI_FILE *fp, char *buf); - -DLLAPI int FCGI_fseek(FCGI_FILE *fp, long offset, int whence); -DLLAPI int FCGI_ftell(FCGI_FILE *fp); -DLLAPI void FCGI_rewind(FCGI_FILE *fp); -#ifdef HAVE_FPOS -DLLAPI int FCGI_fgetpos(FCGI_FILE *fp, fpos_t *pos); -DLLAPI int FCGI_fsetpos(FCGI_FILE *fp, const fpos_t *pos); -#endif -DLLAPI int FCGI_fgetc(FCGI_FILE *fp); -DLLAPI int FCGI_getchar(void); -DLLAPI int FCGI_ungetc(int c, FCGI_FILE *fp); - -DLLAPI char *FCGI_fgets(char *str, int size, FCGI_FILE *fp); -DLLAPI char *FCGI_gets(char *str); - -/* - * Not yet implemented - * - * int FCGI_fscanf(FCGI_FILE *fp, const char *format, ...); - * int FCGI_scanf(const char *format, ...); - * - */ - -DLLAPI int FCGI_fputc(int c, FCGI_FILE *fp); -DLLAPI int FCGI_putchar(int c); - -DLLAPI int FCGI_fputs(const char *str, FCGI_FILE *fp); -DLLAPI int FCGI_puts(const char *str); - -DLLAPI int FCGI_fprintf(FCGI_FILE *fp, const char *format, ...); -DLLAPI int FCGI_printf(const char *format, ...); - -DLLAPI int FCGI_vfprintf(FCGI_FILE *fp, const char *format, va_list ap); -DLLAPI int FCGI_vprintf(const char *format, va_list ap); - -DLLAPI size_t FCGI_fread(void *ptr, size_t size, size_t nmemb, FCGI_FILE *fp); -DLLAPI size_t FCGI_fwrite(void *ptr, size_t size, size_t nmemb, FCGI_FILE *fp); - -DLLAPI int FCGI_feof(FCGI_FILE *fp); -DLLAPI int FCGI_ferror(FCGI_FILE *fp); -DLLAPI void FCGI_clearerr(FCGI_FILE *fp); - -DLLAPI FCGI_FILE *FCGI_tmpfile(void); - -DLLAPI int FCGI_fileno(FCGI_FILE *fp); -DLLAPI FCGI_FILE *FCGI_fdopen(int fd, const char *mode); -DLLAPI FCGI_FILE *FCGI_popen(const char *cmd, const char *type); -DLLAPI int FCGI_pclose(FCGI_FILE *); - -/* - * The remaining definitions are for application programs, - * not for fcgi_stdio.c - */ - -#ifndef NO_FCGI_DEFINES - -/* - * Replace standard types, variables, and functions with FastCGI wrappers. - * Use undef in case a macro is already defined. - */ - -#undef FILE -#define FILE FCGI_FILE - -#undef stdin -#define stdin FCGI_stdin -#undef stdout -#define stdout FCGI_stdout -#undef stderr -#define stderr FCGI_stderr - -#undef perror -#define perror FCGI_perror - -#undef fopen -#define fopen FCGI_fopen -#undef fclose -#define fclose FCGI_fclose -#undef fflush -#define fflush FCGI_fflush -#undef freopen -#define freopen FCGI_freopen - -#undef setvbuf -#define setvbuf FCGI_setvbuf -#undef setbuf -#define setbuf FCGI_setbuf - -#undef fseek -#define fseek FCGI_fseek -#undef ftell -#define ftell FCGI_ftell -#undef rewind -#define rewind FCGI_rewind -#undef fgetpos -#define fgetpos FCGI_fgetpos -#undef fsetpos -#define fsetpos FCGI_fsetpos - -#undef fgetc -#define fgetc FCGI_fgetc -#undef getc -#define getc FCGI_fgetc -#undef getchar -#define getchar FCGI_getchar -#undef ungetc -#define ungetc FCGI_ungetc - -#undef fgets -#define fgets FCGI_fgets -#undef gets -#define gets FCGI_gets - -#undef fputc -#define fputc FCGI_fputc -#undef putc -#define putc FCGI_fputc -#undef putchar -#define putchar FCGI_putchar - -#undef fputs -#define fputs FCGI_fputs -#undef puts -#define puts FCGI_puts - -#undef fprintf -#define fprintf FCGI_fprintf -#undef printf -#define printf FCGI_printf - -#undef vfprintf -#define vfprintf FCGI_vfprintf -#undef vprintf -#define vprintf FCGI_vprintf - -#undef fread -#define fread FCGI_fread -#undef fwrite -#define fwrite FCGI_fwrite - -#undef feof -#define feof FCGI_feof -#undef ferror -#define ferror FCGI_ferror -#undef clearerr -#define clearerr FCGI_clearerr - -#undef tmpfile -#define tmpfile FCGI_tmpfile - -#undef fileno -#define fileno FCGI_fileno -#undef fdopen -#define fdopen FCGI_fdopen -#undef popen -#define popen FCGI_popen -#undef pclose -#define pclose FCGI_pclose - -#endif /* NO_FCGI_DEFINES */ - -#if defined (__cplusplus) || defined (c_plusplus) -} /* terminate extern "C" { */ -#endif - -#endif /* _FCGI_STDIO */ - diff --git a/sapi/cgi/libfcgi/include/fcgiapp.h b/sapi/cgi/libfcgi/include/fcgiapp.h deleted file mode 100644 index 8e35e0776c..0000000000 --- a/sapi/cgi/libfcgi/include/fcgiapp.h +++ /dev/null @@ -1,640 +0,0 @@ -/* - * fcgiapp.h -- - * - * Definitions for FastCGI application server programs - * - * - * Copyright (c) 1996 Open Market, Inc. - * - * See the file "LICENSE.TERMS" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. - * - * $Id$ - */ - -#ifndef _FCGIAPP_H -#define _FCGIAPP_H - -/* Hack to see if we are building TCL - TCL needs varargs not stdarg */ -#ifndef TCL_LIBRARY -#include -#else -#include -#endif - -#ifndef DLLAPI -#ifdef _WIN32 -#if defined(_LIB) || defined(FCGI_STATIC) -#define DLLAPI -#else -#define DLLAPI __declspec(dllimport) -#endif -#else -#define DLLAPI -#endif -#endif - -#if defined (c_plusplus) || defined (__cplusplus) -extern "C" { -#endif - -/* - * Error codes. Assigned to avoid conflict with EOF and errno(2). - */ -#define FCGX_UNSUPPORTED_VERSION -2 -#define FCGX_PROTOCOL_ERROR -3 -#define FCGX_PARAMS_ERROR -4 -#define FCGX_CALL_SEQ_ERROR -5 - -/* - * This structure defines the state of a FastCGI stream. - * Streams are modeled after the FILE type defined in stdio.h. - * (We wouldn't need our own if platform vendors provided a - * standard way to subclass theirs.) - * The state of a stream is private and should only be accessed - * by the procedures defined below. - */ -typedef struct FCGX_Stream { - unsigned char *rdNext; /* reader: first valid byte - * writer: equals stop */ - unsigned char *wrNext; /* writer: first free byte - * reader: equals stop */ - unsigned char *stop; /* reader: last valid byte + 1 - * writer: last free byte + 1 */ - unsigned char *stopUnget; /* reader: first byte of current buffer - * fragment, for ungetc - * writer: undefined */ - int isReader; - int isClosed; - int wasFCloseCalled; - int FCGI_errno; /* error status */ - void (*fillBuffProc) (struct FCGX_Stream *stream); - void (*emptyBuffProc) (struct FCGX_Stream *stream, int doClose); - void *data; -} FCGX_Stream; - -/* - * An environment (as defined by environ(7)): A NULL-terminated array - * of strings, each string having the form name=value. - */ -typedef char **FCGX_ParamArray; - -/* - * A vector of pointers representing the parameters received - * by a FastCGI application server, with the vector's length - * and last valid element so adding new parameters is efficient. - */ - -typedef struct Params { - FCGX_ParamArray vec; /* vector of strings */ - int length; /* number of string vec can hold */ - char **cur; /* current item in vec; *cur == NULL */ -} Params; -typedef Params *ParamsPtr; - -/* - * FCGX_Request Flags - * - * Setting FCGI_FAIL_ACCEPT_ON_INTR prevents FCGX_Accept() from - * restarting upon being interrupted. - */ -#define FCGI_FAIL_ACCEPT_ON_INTR 1 - -/* - * FCGX_Request -- State associated with a request. - * - * Its exposed for API simplicity, I expect parts of it to change! - */ -typedef struct FCGX_Request { - int requestId; /* valid if isBeginProcessed */ - int role; - FCGX_Stream *in; - FCGX_Stream *out; - FCGX_Stream *err; - FCGX_ParamArray envp; - - /* Don't use anything below here */ - - ParamsPtr paramsPtr; - int ipcFd; /* < 0 means no connection */ - int isBeginProcessed; /* FCGI_BEGIN_REQUEST seen */ - int keepConnection; /* don't close ipcFd at end of request */ - int appStatus; - int nWriters; /* number of open writers (0..2) */ - int flags; - int listen_sock; -} FCGX_Request; - - -/* - *====================================================================== - * Control - *====================================================================== - */ - -/* - *---------------------------------------------------------------------- - * - * FCGX_IsCGI -- - * - * Returns TRUE iff this process appears to be a CGI process - * rather than a FastCGI process. - * - *---------------------------------------------------------------------- - */ -DLLAPI int FCGX_IsCGI(void); - -/* - *---------------------------------------------------------------------- - * - * FCGX_Init -- - * - * Initialize the FCGX library. Call in multi-threaded apps - * before calling FCGX_Accept_r(). - * - * Returns 0 upon success. - * - *---------------------------------------------------------------------- - */ -DLLAPI int FCGX_Init(void); - -/* - *---------------------------------------------------------------------- - * - * FCGX_OpenSocket -- - * - * Create a FastCGI listen socket. - * - * path is the Unix domain socket (named pipe for WinNT), or a colon - * followed by a port number. e.g. "/tmp/fastcgi/mysocket", ":5000" - * - * backlog is the listen queue depth used in the listen() call. - * - * Returns the socket's file descriptor or -1 on error. - * - *---------------------------------------------------------------------- - */ -DLLAPI int FCGX_OpenSocket(const char *path, int backlog); - -/* - *---------------------------------------------------------------------- - * - * FCGX_InitRequest -- - * - * Initialize a FCGX_Request for use with FCGX_Accept_r(). - * - * sock is a file descriptor returned by FCGX_OpenSocket() or 0 (default). - * The only supported flag at this time is FCGI_FAIL_ON_INTR. - * - * Returns 0 upon success. - *---------------------------------------------------------------------- - */ -DLLAPI int FCGX_InitRequest(FCGX_Request *request, int sock, int flags); - -/* - *---------------------------------------------------------------------- - * - * FCGX_Accept_r -- - * - * Accept a new request (multi-thread safe). Be sure to call - * FCGX_Init() first. - * - * Results: - * 0 for successful call, -1 for error. - * - * Side effects: - * - * Finishes the request accepted by (and frees any - * storage allocated by) the previous call to FCGX_Accept. - * Creates input, output, and error streams and - * assigns them to *in, *out, and *err respectively. - * Creates a parameters data structure to be accessed - * via getenv(3) (if assigned to environ) or by FCGX_GetParam - * and assigns it to *envp. - * - * DO NOT retain pointers to the envp array or any strings - * contained in it (e.g. to the result of calling FCGX_GetParam), - * since these will be freed by the next call to FCGX_Finish - * or FCGX_Accept. - * - * DON'T use the FCGX_Request, its structure WILL change. - * - *---------------------------------------------------------------------- - */ -DLLAPI int FCGX_Accept_r(FCGX_Request *request); - -/* - *---------------------------------------------------------------------- - * - * FCGX_Finish_r -- - * - * Finish the request (multi-thread safe). - * - * Side effects: - * - * Finishes the request accepted by (and frees any - * storage allocated by) the previous call to FCGX_Accept. - * - * DO NOT retain pointers to the envp array or any strings - * contained in it (e.g. to the result of calling FCGX_GetParam), - * since these will be freed by the next call to FCGX_Finish - * or FCGX_Accept. - * - *---------------------------------------------------------------------- - */ -DLLAPI void FCGX_Finish_r(FCGX_Request *request); - -/* - *---------------------------------------------------------------------- - * - * FCGX_Free -- - * - * Free the memory and, if close is true, - * IPC FD associated with the request (multi-thread safe). - * - *---------------------------------------------------------------------- - */ -DLLAPI void FCGX_Free(FCGX_Request * request, int close); - -/* - *---------------------------------------------------------------------- - * - * FCGX_Accept -- - * - * Accept a new request (NOT multi-thread safe). - * - * Results: - * 0 for successful call, -1 for error. - * - * Side effects: - * - * Finishes the request accepted by (and frees any - * storage allocated by) the previous call to FCGX_Accept. - * Creates input, output, and error streams and - * assigns them to *in, *out, and *err respectively. - * Creates a parameters data structure to be accessed - * via getenv(3) (if assigned to environ) or by FCGX_GetParam - * and assigns it to *envp. - * - * DO NOT retain pointers to the envp array or any strings - * contained in it (e.g. to the result of calling FCGX_GetParam), - * since these will be freed by the next call to FCGX_Finish - * or FCGX_Accept. - * - *---------------------------------------------------------------------- - */ -DLLAPI int FCGX_Accept( - FCGX_Stream **in, - FCGX_Stream **out, - FCGX_Stream **err, - FCGX_ParamArray *envp); - -/* - *---------------------------------------------------------------------- - * - * FCGX_Finish -- - * - * Finish the current request (NOT multi-thread safe). - * - * Side effects: - * - * Finishes the request accepted by (and frees any - * storage allocated by) the previous call to FCGX_Accept. - * - * DO NOT retain pointers to the envp array or any strings - * contained in it (e.g. to the result of calling FCGX_GetParam), - * since these will be freed by the next call to FCGX_Finish - * or FCGX_Accept. - * - *---------------------------------------------------------------------- - */ -DLLAPI void FCGX_Finish(void); - -/* - *---------------------------------------------------------------------- - * - * FCGX_StartFilterData -- - * - * stream is an input stream for a FCGI_FILTER request. - * stream is positioned at EOF on FCGI_STDIN. - * Repositions stream to the start of FCGI_DATA. - * If the preconditions are not met (e.g. FCGI_STDIN has not - * been read to EOF) sets the stream error code to - * FCGX_CALL_SEQ_ERROR. - * - * Results: - * 0 for a normal return, < 0 for error - * - *---------------------------------------------------------------------- - */ -DLLAPI int FCGX_StartFilterData(FCGX_Stream *stream); - -/* - *---------------------------------------------------------------------- - * - * FCGX_SetExitStatus -- - * - * Sets the exit status for stream's request. The exit status - * is the status code the request would have exited with, had - * the request been run as a CGI program. You can call - * SetExitStatus several times during a request; the last call - * before the request ends determines the value. - * - *---------------------------------------------------------------------- - */ -DLLAPI void FCGX_SetExitStatus(int status, FCGX_Stream *stream); - -/* - *====================================================================== - * Parameters - *====================================================================== - */ - -/* - *---------------------------------------------------------------------- - * - * FCGX_GetParam -- obtain value of FCGI parameter in environment - * - * - * Results: - * Value bound to name, NULL if name not present in the - * environment envp. Caller must not mutate the result - * or retain it past the end of this request. - * - *---------------------------------------------------------------------- - */ -DLLAPI char *FCGX_GetParam(const char *name, FCGX_ParamArray envp); -DLLAPI void FCGX_PutEnv(FCGX_Request *request, char *nameValue); - -/* - *====================================================================== - * Readers - *====================================================================== - */ - -/* - *---------------------------------------------------------------------- - * - * FCGX_GetChar -- - * - * Reads a byte from the input stream and returns it. - * - * Results: - * The byte, or EOF (-1) if the end of input has been reached. - * - *---------------------------------------------------------------------- - */ -DLLAPI int FCGX_GetChar(FCGX_Stream *stream); - -/* - *---------------------------------------------------------------------- - * - * FCGX_UnGetChar -- - * - * Pushes back the character c onto the input stream. One - * character of pushback is guaranteed once a character - * has been read. No pushback is possible for EOF. - * - * Results: - * Returns c if the pushback succeeded, EOF if not. - * - *---------------------------------------------------------------------- - */ -DLLAPI int FCGX_UnGetChar(int c, FCGX_Stream *stream); - -/* - *---------------------------------------------------------------------- - * - * FCGX_GetStr -- - * - * Reads up to n consecutive bytes from the input stream - * into the character array str. Performs no interpretation - * of the input bytes. - * - * Results: - * Number of bytes read. If result is smaller than n, - * the end of input has been reached. - * - *---------------------------------------------------------------------- - */ -DLLAPI int FCGX_GetStr(char *str, int n, FCGX_Stream *stream); - -/* - *---------------------------------------------------------------------- - * - * FCGX_GetLine -- - * - * Reads up to n-1 consecutive bytes from the input stream - * into the character array str. Stops before n-1 bytes - * have been read if '\n' or EOF is read. The terminating '\n' - * is copied to str. After copying the last byte into str, - * stores a '\0' terminator. - * - * Results: - * NULL if EOF is the first thing read from the input stream, - * str otherwise. - * - *---------------------------------------------------------------------- - */ -DLLAPI char *FCGX_GetLine(char *str, int n, FCGX_Stream *stream); - -/* - *---------------------------------------------------------------------- - * - * FCGX_HasSeenEOF -- - * - * Returns EOF if end-of-file has been detected while reading - * from stream; otherwise returns 0. - * - * Note that FCGX_HasSeenEOF(s) may return 0, yet an immediately - * following FCGX_GetChar(s) may return EOF. This function, like - * the standard C stdio function feof, does not provide the - * ability to peek ahead. - * - * Results: - * EOF if end-of-file has been detected, 0 if not. - * - *---------------------------------------------------------------------- - */ - -DLLAPI int FCGX_HasSeenEOF(FCGX_Stream *stream); - -/* - *====================================================================== - * Writers - *====================================================================== - */ - -/* - *---------------------------------------------------------------------- - * - * FCGX_PutChar -- - * - * Writes a byte to the output stream. - * - * Results: - * The byte, or EOF (-1) if an error occurred. - * - *---------------------------------------------------------------------- - */ -DLLAPI int FCGX_PutChar(int c, FCGX_Stream *stream); - -/* - *---------------------------------------------------------------------- - * - * FCGX_PutStr -- - * - * Writes n consecutive bytes from the character array str - * into the output stream. Performs no interpretation - * of the output bytes. - * - * Results: - * Number of bytes written (n) for normal return, - * EOF (-1) if an error occurred. - * - *---------------------------------------------------------------------- - */ -DLLAPI int FCGX_PutStr(const char *str, int n, FCGX_Stream *stream); - -/* - *---------------------------------------------------------------------- - * - * FCGX_PutS -- - * - * Writes a null-terminated character string to the output stream. - * - * Results: - * number of bytes written for normal return, - * EOF (-1) if an error occurred. - * - *---------------------------------------------------------------------- - */ -DLLAPI int FCGX_PutS(const char *str, FCGX_Stream *stream); - -/* - *---------------------------------------------------------------------- - * - * FCGX_FPrintF, FCGX_VFPrintF -- - * - * Performs printf-style output formatting and writes the results - * to the output stream. - * - * Results: - * number of bytes written for normal return, - * EOF (-1) if an error occurred. - * - *---------------------------------------------------------------------- - */ -DLLAPI int FCGX_FPrintF(FCGX_Stream *stream, const char *format, ...); - -DLLAPI int FCGX_VFPrintF(FCGX_Stream *stream, const char *format, va_list arg); - -/* - *---------------------------------------------------------------------- - * - * FCGX_FFlush -- - * - * Flushes any buffered output. - * - * Server-push is a legitimate application of FCGX_FFlush. - * Otherwise, FCGX_FFlush is not very useful, since FCGX_Accept - * does it implicitly. Calling FCGX_FFlush in non-push applications - * results in extra writes and therefore reduces performance. - * - * Results: - * EOF (-1) if an error occurred. - * - *---------------------------------------------------------------------- - */ -DLLAPI int FCGX_FFlush(FCGX_Stream *stream); - -/* - *====================================================================== - * Both Readers and Writers - *====================================================================== - */ - -/* - *---------------------------------------------------------------------- - * - * FCGX_FClose -- - * - * Closes the stream. For writers, flushes any buffered - * output. - * - * Close is not a very useful operation since FCGX_Accept - * does it implicitly. Closing the out stream before the - * err stream results in an extra write if there's nothing - * in the err stream, and therefore reduces performance. - * - * Results: - * EOF (-1) if an error occurred. - * - *---------------------------------------------------------------------- - */ -DLLAPI int FCGX_FClose(FCGX_Stream *stream); - -/* - *---------------------------------------------------------------------- - * - * FCGX_GetError -- - * - * Return the stream error code. 0 means no error, > 0 - * is an errno(2) error, < 0 is an FastCGI error. - * - *---------------------------------------------------------------------- - */ -DLLAPI int FCGX_GetError(FCGX_Stream *stream); - -/* - *---------------------------------------------------------------------- - * - * FCGX_ClearError -- - * - * Clear the stream error code and end-of-file indication. - * - *---------------------------------------------------------------------- - */ -DLLAPI void FCGX_ClearError(FCGX_Stream *stream); - -/* - *---------------------------------------------------------------------- - * - * FCGX_CreateWriter -- - * - * Create a FCGX_Stream (used by cgi-fcgi). This shouldn't - * be needed by a FastCGI applictaion. - * - *---------------------------------------------------------------------- - */ -DLLAPI FCGX_Stream *FCGX_CreateWriter( - int socket, - int requestId, - int bufflen, - int streamType); - -/* - *---------------------------------------------------------------------- - * - * FCGX_FreeStream -- - * - * Free a FCGX_Stream (used by cgi-fcgi). This shouldn't - * be needed by a FastCGI applictaion. - * - *---------------------------------------------------------------------- - */ -DLLAPI void FCGX_FreeStream(FCGX_Stream **stream); - -/* ---------------------------------------------------------------------- - * - * Prevent the lib from accepting any new requests. Signal handler safe. - * - * ---------------------------------------------------------------------- - */ -DLLAPI void FCGX_ShutdownPending(void); - -#if defined (__cplusplus) || defined (c_plusplus) -} /* terminate extern "C" { */ -#endif - -#endif /* _FCGIAPP_H */ diff --git a/sapi/cgi/libfcgi/include/fcgiappmisc.h b/sapi/cgi/libfcgi/include/fcgiappmisc.h deleted file mode 100644 index db8651a44b..0000000000 --- a/sapi/cgi/libfcgi/include/fcgiappmisc.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * fcgiappmisc.h -- - * - * Functions implemented by fcgiapp.h that aren't needed - * by normal applications, but may be useful to special - * applications. - * - * - * Copyright (c) 1996 Open Market, Inc. - * - * See the file "LICENSE.TERMS" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. - * - * $Id$ - */ - -#ifndef _FCGIAPPMISC_H -#define _FCGIAPPMISC_H - -#include "fcgiapp.h" /* for FCGX_Stream */ - -#if defined (c_plusplus) || defined (__cplusplus) -extern "C" { -#endif - -#ifdef _WIN32 -#ifndef DLLAPI -#ifdef FCGI_STATIC -#define DLLAPI -#else -#define DLLAPI __declspec(dllimport) -#endif -#endif -#else -#define DLLAPI -#endif - -DLLAPI FCGX_Stream *CreateWriter( - int socket, - int requestId, - int bufflen, - int streamType); - -DLLAPI void FreeStream(FCGX_Stream **stream); - -#if defined (__cplusplus) || defined (c_plusplus) -} /* terminate extern "C" { */ -#endif - -#endif /* _FCGIAPPMISC_H */ diff --git a/sapi/cgi/libfcgi/include/fcgimisc.h b/sapi/cgi/libfcgi/include/fcgimisc.h deleted file mode 100644 index 20ee4a0cf0..0000000000 --- a/sapi/cgi/libfcgi/include/fcgimisc.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * fcgimisc.h -- - * - * Miscellaneous definitions - * - * - * Copyright (c) 1996 Open Market, Inc. - * - * See the file "LICENSE.TERMS" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. - * - * $Id$ - */ - -#ifndef _FCGIMISC_H -#define _FCGIMISC_H - -#ifndef FALSE -#define FALSE (0) -#endif - -#ifndef TRUE -#define TRUE (1) -#endif - -#ifndef min -#define min(a,b) ((a) < (b) ? (a) : (b)) -#endif - -#ifndef max -#define max(a,b) ((a) > (b) ? (a) : (b)) -#endif - -#ifndef ASSERT -#define ASSERT(assertion) assert(assertion) -#endif - -#endif /* _FCGIMISC_H */ diff --git a/sapi/cgi/libfcgi/include/fcgio.h b/sapi/cgi/libfcgi/include/fcgio.h deleted file mode 100644 index 865bff385b..0000000000 --- a/sapi/cgi/libfcgi/include/fcgio.h +++ /dev/null @@ -1,147 +0,0 @@ -// -// Provides support for FastCGI via C++ iostreams. -// -// $Id$ -// -// This work is based on routines written by George Feinberg. They -// have been mostly re-written and extensively changed by -// Michael Richards. -// -// Rewritten again with bug fixes and numerous enhancements by -// Michael Shell. -// -// And rewritten again by Rob Saccoccio. -// -// Special Thanks to Dietmar Kuehl for his help and the numerous custom -// streambuf examples on his web site. -// -// Copyright (c) 2000 Tux the Linux Penguin -// Copyright (c) 2001 Rob Saccoccio and Chelsea Networks -// -// You are free to use this software without charge or royalty -// as long as this notice is not removed or altered, and recognition -// is given to the author(s) -// -// This code is offered as-is without any warranty either expressed or -// implied; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. If it breaks, you get to keep -// both halves. - -#ifndef FCGIO_H -#define FCGIO_H - -#include - -#include "fcgiapp.h" - -#ifndef DLLAPI -#ifdef _WIN32 -#define DLLAPI __declspec(dllimport) -#else -#define DLLAPI -#endif -#endif - -/* - * fcgi_streambuf - */ -class fcgi_streambuf : public streambuf -{ -public: - - // Note that if no buf is assigned (the default), iostream methods - // such as peek(), unget() and putback() will fail. If a buf is - // assigned, I/O is a bit less effecient and output streams will - // have to be flushed (or the streambuf destroyed) before the next - // call to "accept". - DLLAPI fcgi_streambuf(FCGX_Stream * fcgx, char * buf, int len); - - DLLAPI fcgi_streambuf(char * buf, int len); - - DLLAPI fcgi_streambuf(FCGX_Stream * fcgx = NULL); - - DLLAPI ~fcgi_streambuf(void); - - DLLAPI int attach(FCGX_Stream * fcgx); - -protected: - - // Consume the put area (if buffered) and c (if c is not EOF). - DLLAPI virtual int overflow(int); - - // Flush the put area (if buffered) and the FCGX buffer to the client. - DLLAPI virtual int sync(); - - // Remove and return the current character. - DLLAPI virtual int uflow(); - - // Fill the get area (if buffered) and return the current character. - DLLAPI virtual int underflow(); - - // Use a buffer. The only reasons that a buffer would be useful is - // to support the use of the unget()/putback() or seek() methods. Using - // a buffer will result in less efficient I/O. Note: the underlying - // FastCGI library (FCGX) maintains its own input and output buffers. - DLLAPI virtual streambuf * setbuf(char * buf, int len); - - DLLAPI virtual int xsgetn(char * s, int n); - DLLAPI virtual int xsputn(const char * s, int n); - -private: - - FCGX_Stream * fcgx; - - // buf is just handy to have around - char * buf; - - // this isn't kept by the base class - int bufsize; - - void init(FCGX_Stream * fcgx, char * buf, int bufsize); - - void reset(void); -}; - -/* - * fcgi_istream - deprecated - */ -class fcgi_istream : public istream -{ -public: - - // deprecated - DLLAPI fcgi_istream(FCGX_Stream * fcgx = NULL); - - // deprecated - DLLAPI ~fcgi_istream(void) {} - - // deprecated - DLLAPI virtual void attach(FCGX_Stream * fcgx); - -private: - - fcgi_streambuf fcgi_strmbuf; -}; - -/* - * fcgi_ostream - deprecated - */ -class fcgi_ostream : public ostream -{ -public: - - // deprecated - DLLAPI fcgi_ostream(FCGX_Stream * fcgx = NULL); - - // deprecated - DLLAPI ~fcgi_ostream(void) {} - - // deprecated - DLLAPI virtual void attach(FCGX_Stream *fcgx); - -private: - - fcgi_streambuf fcgi_strmbuf; -}; - -#endif /* FCGIO_H */ diff --git a/sapi/cgi/libfcgi/include/fcgios.h b/sapi/cgi/libfcgi/include/fcgios.h deleted file mode 100644 index e0f8373fb7..0000000000 --- a/sapi/cgi/libfcgi/include/fcgios.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * fcgios.h -- - * - * Description of file. - * - * - * Copyright (c) 1996 Open Market, Inc. - * All rights reserved. - * - * This file contains proprietary and confidential information and - * remains the unpublished property of Open Market, Inc. Use, - * disclosure, or reproduction is prohibited except as permitted by - * express written license agreement with Open Market, Inc. - * - * Bill Snapper - * snapper@openmarket.com - */ -#ifndef _FCGIOS_H -#define _FCGIOS_H - -#ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#include -#include -#endif - -#include "fcgi_config.h" - -#ifdef HAVE_SYS_TIME_H -#include -#endif - -#if defined (c_plusplus) || defined (__cplusplus) -extern "C" { -#endif - -#ifdef _WIN32 -#define OS_Errno GetLastError() -#define OS_SetErrno(err) SetLastError(err) -#ifndef O_NONBLOCK -#define O_NONBLOCK 0x0004 /* no delay */ -#endif -#else /* !_WIN32 */ -#define OS_Errno errno -#define OS_SetErrno(err) errno = (err) -#endif /* !_WIN32 */ - -#ifndef DLLAPI -#ifdef _WIN32 -#if defined(_LIB) || defined(FCGI_STATIC) -#define DLLAPI -#else -#define DLLAPI __declspec(dllimport) -#endif -#else -#define DLLAPI -#endif -#endif - - -/* This is the initializer for a "struct timeval" used in a select() call - * right after a new request is accept()ed to determine readablity. Its - * a drop-dead timer. Its only used for AF_UNIX sockets (not TCP sockets). - * Its a workaround for a kernel bug in Linux 2.0.x and SCO Unixware. - * Making this as small as possible, yet remain reliable would be best. - * 2 seconds is very conservative. 0,0 is not reliable. The shorter the - * timeout, the faster request processing will recover. The longer the - * timeout, the more likely this application being "busy" will cause other - * requests to abort and cause more dead sockets that need this timeout. */ -#define READABLE_UNIX_FD_DROP_DEAD_TIMEVAL 2,0 - -#ifndef STDIN_FILENO -#define STDIN_FILENO 0 -#endif - -#ifndef STDOUT_FILENO -#define STDOUT_FILENO 1 -#endif - -#ifndef STDERR_FILENO -#define STDERR_FILENO 2 -#endif - -#ifndef MAXPATHLEN -#define MAXPATHLEN 1024 -#endif - -#ifndef X_OK -#define X_OK 0x01 -#endif - -#ifndef _CLIENTDATA -# if defined(__STDC__) || defined(__cplusplus) - typedef void *ClientData; -# else - typedef int *ClientData; -# endif /* __STDC__ */ -#define _CLIENTDATA -#endif -#define MUTEX_VARNAME "_FCGI_MUTEX_" -#define SHUTDOWN_EVENT_NAME "_FCGI_SHUTDOWN_EVENT_" - -typedef void (*OS_AsyncProc) (ClientData clientData, int len); - -DLLAPI int OS_LibInit(int stdioFds[3]); -DLLAPI void OS_LibShutdown(void); -DLLAPI int OS_CreateLocalIpcFd(const char *bindPath, int backlog, int bCreateMutex); -DLLAPI int OS_FcgiConnect(char *bindPath); -DLLAPI int OS_Read(int fd, char * buf, size_t len); -DLLAPI int OS_Write(int fd, char * buf, size_t len); -#ifdef _WIN32 -DLLAPI int OS_SpawnChild(char *execPath, int listenFd, PROCESS_INFORMATION *pInfo, char *env); -#else -DLLAPI int OS_SpawnChild(char *execPath, int listenfd); -#endif -DLLAPI int OS_AsyncReadStdin(void *buf, int len, OS_AsyncProc procPtr, - ClientData clientData); -DLLAPI int OS_AsyncRead(int fd, int offset, void *buf, int len, - OS_AsyncProc procPtr, ClientData clientData); -DLLAPI int OS_AsyncWrite(int fd, int offset, void *buf, int len, - OS_AsyncProc procPtr, ClientData clientData); -DLLAPI int OS_Close(int fd); -DLLAPI int OS_CloseRead(int fd); -DLLAPI int OS_DoIo(struct timeval *tmo); -DLLAPI int OS_Accept(int listen_sock, int fail_on_intr, const char *webServerAddrs); -DLLAPI int OS_IpcClose(int ipcFd); -DLLAPI int OS_IsFcgi(int sock); -DLLAPI void OS_SetFlags(int fd, int flags); - -DLLAPI void OS_ShutdownPending(void); - -#ifdef _WIN32 -DLLAPI int OS_SetImpersonate(void); -#endif - -#if defined (__cplusplus) || defined (c_plusplus) -} /* terminate extern "C" { */ -#endif - -#endif /* _FCGIOS_H */ diff --git a/sapi/cgi/libfcgi/libfcgi.m4 b/sapi/cgi/libfcgi/libfcgi.m4 deleted file mode 100644 index 28e73d46a0..0000000000 --- a/sapi/cgi/libfcgi/libfcgi.m4 +++ /dev/null @@ -1,77 +0,0 @@ -dnl $Id$ -dnl -dnl This file is an input file used by the GNU "autoconf" program to -dnl generate the file "configure", which is run during the build -dnl to configure the system for the local environment. - -#AC_INIT -#AM_INIT_AUTOMAKE(fcgi, 2.2.3-SNAP-0203171857) - -#AM_CONFIG_HEADER(include/fcgi_config.h) - -#AC_PROG_CC -#AC_PROG_CPP -#AC_PROG_INSTALL -#AC_PROG_LIBTOOL - -#AC_PROG_CXX - -#AC_LANG([C++]) - -#dnl autoconf defaults CXX to 'g++', so its unclear whether it exists/works -#AC_MSG_CHECKING([whether $CXX works]) -#AC_TRY_COMPILE([#include ], -# [std::cout << "ok";], -# [AC_MSG_RESULT(yes) -# LIBFCGIXX=libfcgi++.la -# ECHO_CPP=echo-cpp${EXEEXT} -# AC_MSG_CHECKING([whether cin has a streambuf assignment operator]) -# AC_TRY_COMPILE([#include ], -# [cin = static_cast(0);], -# [AC_MSG_RESULT(yes) -# AC_DEFINE([HAVE_IOSTREAM_WITHASSIGN_STREAMBUF], [1], -# [Define if cin/cout/cerr has a streambuf assignment operator])], -# [AC_MSG_RESULT(no)]) -# AC_MSG_CHECKING([whether char_type is defined in the context of streambuf]) -# AC_TRY_COMPILE([#include ], -# [class fcgi_streambuf : public std::streambuf { char_type ct; }], -# [AC_MSG_RESULT(yes) -# AC_DEFINE([HAVE_STREAMBUF_CHAR_TYPE], [1], -# [Define if char_type is defined in the context of streambuf])], -# [AC_MSG_RESULT(no)])], -# [AC_MSG_RESULT(no)]) -#AC_SUBST(LIBFCGIXX) -#AC_SUBST(ECHO_CPP) - -#AC_LANG([C]) - -AC_CHECK_LIB([nsl], [gethostbyname]) -AC_CHECK_LIB([socket], [socket]) - -ACX_PTHREAD([THREADED=threaded${EXEEXT}]) -AC_SUBST([THREADED]) - -FCGI_COMMON_CHECKS - -AC_REPLACE_FUNCS([strerror]) - -#AC_C_INLINE - -#-------------------------------------------------------------------- -# This is a little hokie in that it avoids including config.guess -# and config.sub in the distribution, but its been working so far. -# Windows builds don't run configure so we should be safe fixing -# this to 'unix' (at least for now). -#-------------------------------------------------------------------- -#SYSTEM=unix -#AC_SUBST([SYSTEM]) - -#AC_PROG_CC_WARNINGS - -#AC_CONFIG_FILES([Makefile -# cgi-fcgi/Makefile -# include/Makefile -# libfcgi/Makefile -# examples/Makefile]) - -#AC_OUTPUT diff --git a/sapi/cgi/libfcgi/os_unix.c b/sapi/cgi/libfcgi/os_unix.c deleted file mode 100644 index bbaf112621..0000000000 --- a/sapi/cgi/libfcgi/os_unix.c +++ /dev/null @@ -1,1273 +0,0 @@ -/* - * os_unix.c -- - * - * Description of file. - * - * - * Copyright (c) 1995 Open Market, Inc. - * All rights reserved. - * - * This file contains proprietary and confidential information and - * remains the unpublished property of Open Market, Inc. Use, - * disclosure, or reproduction is prohibited except as permitted by - * express written license agreement with Open Market, Inc. - * - * Bill Snapper - * snapper@openmarket.com - */ - -#ifndef lint -static const char rcsid[] = "$Id$"; -#endif /* not lint */ - -#include "fcgi_config.h" - -#include - -#ifdef HAVE_NETINET_IN_H -#include -#endif - -#include -#include -#include -#include /* for fcntl */ -#include -#include /* for memchr() */ -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_NETDB_H -#include -#endif - -#ifdef HAVE_SYS_SOCKET_H -#include /* for getpeername */ -#endif - -#ifdef HAVE_UNISTD_H -#include -#endif - -#include "fastcgi.h" -#include "fcgimisc.h" -#include "fcgios.h" - -#ifndef INADDR_NONE -#define INADDR_NONE ((unsigned long) -1) -#endif - -/* - * This structure holds an entry for each oustanding async I/O operation. - */ -typedef struct { - OS_AsyncProc procPtr; /* callout completion procedure */ - ClientData clientData; /* caller private data */ - int fd; - int len; - int offset; - void *buf; - int inUse; -} AioInfo; - -/* - * Entries in the async I/O table are allocated 2 per file descriptor. - * - * Read Entry Index = fd * 2 - * Write Entry Index = (fd * 2) + 1 - */ -#define AIO_RD_IX(fd) (fd * 2) -#define AIO_WR_IX(fd) ((fd * 2) + 1) - -static int asyncIoInUse = FALSE; -static int asyncIoTableSize = 16; -static AioInfo *asyncIoTable = NULL; - -static int libInitialized = FALSE; - -static fd_set readFdSet; -static fd_set writeFdSet; - -static fd_set readFdSetPost; -static int numRdPosted = 0; -static fd_set writeFdSetPost; -static int numWrPosted = 0; -static int volatile maxFd = -1; - -static int shutdownPending = FALSE; -static int shutdownNow = FALSE; - -#ifndef HAVE_STRLCPY -#define strlcpy php_strlcpy -#endif -size_t strlcpy(char *dst, const char *src, size_t siz); - -void OS_ShutdownPending() -{ - shutdownPending = TRUE; -} - -static void OS_Sigusr1Handler(int signo) -{ - OS_ShutdownPending(); -} - -static void OS_SigpipeHandler(int signo) -{ - ; -} - -static void installSignalHandler(int signo, const struct sigaction * act, int force) -{ - struct sigaction sa; - - sigaction(signo, NULL, &sa); - - if (force || sa.sa_handler == SIG_DFL) - { - sigaction(signo, act, NULL); - } -} - -static void OS_InstallSignalHandlers(int force) -{ - struct sigaction sa; - - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - - sa.sa_handler = OS_SigpipeHandler; - installSignalHandler(SIGPIPE, &sa, force); - - sa.sa_handler = OS_Sigusr1Handler; - installSignalHandler(SIGUSR1, &sa, force); -} - -/* - *-------------------------------------------------------------- - * - * OS_LibInit -- - * - * Set up the OS library for use. - * - * NOTE: This function is really only needed for application - * asynchronous I/O. It will most likely change in the - * future to setup the multi-threaded environment. - * - * Results: - * Returns 0 if success, -1 if not. - * - * Side effects: - * Async I/O table allocated and initialized. - * - *-------------------------------------------------------------- - */ -int OS_LibInit(int stdioFds[3]) -{ - if(libInitialized) - return 0; - - asyncIoTable = (AioInfo *)malloc(asyncIoTableSize * sizeof(AioInfo)); - if(asyncIoTable == NULL) { - errno = ENOMEM; - return -1; - } - memset((char *) asyncIoTable, 0, - asyncIoTableSize * sizeof(AioInfo)); - - FD_ZERO(&readFdSet); - FD_ZERO(&writeFdSet); - FD_ZERO(&readFdSetPost); - FD_ZERO(&writeFdSetPost); - - OS_InstallSignalHandlers(FALSE); - - libInitialized = TRUE; - - return 0; -} - -/* - *-------------------------------------------------------------- - * - * OS_LibShutdown -- - * - * Shutdown the OS library. - * - * Results: - * None. - * - * Side effects: - * Memory freed, fds closed. - * - *-------------------------------------------------------------- - */ -void OS_LibShutdown() -{ - if(!libInitialized) - return; - - free(asyncIoTable); - asyncIoTable = NULL; - libInitialized = FALSE; - return; -} - -/* - *---------------------------------------------------------------------- - * - * OS_BuildSockAddrUn -- - * - * Using the pathname bindPath, fill in the sockaddr_un structure - * *servAddrPtr and the length of this structure *servAddrLen. - * - * The format of the sockaddr_un structure changed incompatibly in - * 4.3BSD Reno. Digital UNIX supports both formats, other systems - * support one or the other. - * - * Results: - * 0 for normal return, -1 for failure (bindPath too long). - * - *---------------------------------------------------------------------- - */ - -static int OS_BuildSockAddrUn(const char *bindPath, - struct sockaddr_un *servAddrPtr, - int *servAddrLen) -{ - int bindPathLen = strlen(bindPath); - -#ifdef HAVE_SOCKADDR_UN_SUN_LEN /* 4.3BSD Reno and later: BSDI, DEC */ - if(bindPathLen >= sizeof(servAddrPtr->sun_path)) { - return -1; - } -#else /* 4.3 BSD Tahoe: Solaris, HPUX, DEC, ... */ - if(bindPathLen > sizeof(servAddrPtr->sun_path)) { - return -1; - } -#endif - memset((char *) servAddrPtr, 0, sizeof(*servAddrPtr)); - servAddrPtr->sun_family = AF_UNIX; - memcpy(servAddrPtr->sun_path, bindPath, bindPathLen); -#ifdef HAVE_SOCKADDR_UN_SUN_LEN /* 4.3BSD Reno and later: BSDI, DEC */ - *servAddrLen = sizeof(servAddrPtr->sun_len) - + sizeof(servAddrPtr->sun_family) - + bindPathLen + 1; - servAddrPtr->sun_len = *servAddrLen; -#else /* 4.3 BSD Tahoe: Solaris, HPUX, DEC, ... */ - *servAddrLen = sizeof(servAddrPtr->sun_family) + bindPathLen; -#endif - return 0; -} -union SockAddrUnion { - struct sockaddr_un unixVariant; - struct sockaddr_in inetVariant; -}; - -/* - * OS_CreateLocalIpcFd -- - * - * This procedure is responsible for creating the listener socket - * on Unix for local process communication. It will create a - * domain socket or a TCP/IP socket bound to "localhost" and return - * a file descriptor to it to the caller. - * bCreateMutex is ignored for unix - * - * Results: - * Listener socket created. This call returns either a valid - * file descriptor or -1 on error. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ -int OS_CreateLocalIpcFd(const char *bindPath, int backlog, int bCreateMutex) -{ - int listenSock, servLen; - union SockAddrUnion sa; - int tcp = FALSE; - unsigned long tcp_ia = 0; - char *tp; - short port = 0; - char host[MAXPATHLEN]; - - strlcpy(host, bindPath, MAXPATHLEN-1); - if((tp = strchr(host, ':')) != 0) { - *tp++ = 0; - if((port = atoi(tp)) == 0) { - *--tp = ':'; - } else { - tcp = TRUE; - } - } - if(tcp) { - if (!*host || !strcmp(host,"*")) { - tcp_ia = htonl(INADDR_ANY); - } else { - tcp_ia = inet_addr(host); - if (tcp_ia == INADDR_NONE) { - struct hostent * hep; - hep = gethostbyname(host); - if ((!hep) || (hep->h_addrtype != AF_INET || !hep->h_addr_list[0])) { - fprintf(stderr, "Cannot resolve host name %s -- exiting!\n", host); - return -1; - } - if (hep->h_addr_list[1]) { - fprintf(stderr, "Host %s has multiple addresses ---\n", host); - fprintf(stderr, "you must choose one explicitly!!!\n"); - return -1; - } - tcp_ia = ((struct in_addr *) (hep->h_addr))->s_addr; - } - } - } - - if(tcp) { - listenSock = socket(AF_INET, SOCK_STREAM, 0); - if(listenSock >= 0) { - int flag = 1; - if(setsockopt(listenSock, SOL_SOCKET, SO_REUSEADDR, - (char *) &flag, sizeof(flag)) < 0) { - fprintf(stderr, "Can't set SO_REUSEADDR.\n"); - return -1; - } - } - } else { - listenSock = socket(AF_UNIX, SOCK_STREAM, 0); - } - if(listenSock < 0) { - return -1; - } - - /* - * Bind the listening socket. - */ - if(tcp) { - memset((char *) &sa.inetVariant, 0, sizeof(sa.inetVariant)); - sa.inetVariant.sin_family = AF_INET; - sa.inetVariant.sin_addr.s_addr = tcp_ia; - sa.inetVariant.sin_port = htons(port); - servLen = sizeof(sa.inetVariant); - } else { - unlink(bindPath); - if(OS_BuildSockAddrUn(bindPath, &sa.unixVariant, &servLen)) { - fprintf(stderr, "Listening socket's path name is too long.\n"); - return -1; - } - } - if(bind(listenSock, (struct sockaddr *) &sa.unixVariant, servLen) < 0 - || listen(listenSock, backlog) < 0) { - perror("bind/listen"); - return -1; - } - - return listenSock; -} - -/* - *---------------------------------------------------------------------- - * - * OS_FcgiConnect -- - * - * Create the socket and connect to the remote application if - * possible. - * - * This was lifted from the cgi-fcgi application and was abstracted - * out because Windows NT does not have a domain socket and must - * use a named pipe which has a different API altogether. - * - * Results: - * -1 if fail or a valid file descriptor if connection succeeds. - * - * Side effects: - * Remote connection established. - * - *---------------------------------------------------------------------- - */ -int OS_FcgiConnect(char *bindPath) -{ - union SockAddrUnion sa; - int servLen, resultSock; - int connectStatus; - char *tp; - char host[MAXPATHLEN]; - short port = 0; - int tcp = FALSE; - - strlcpy(host, bindPath, MAXPATHLEN-1); - if((tp = strchr(host, ':')) != 0) { - *tp++ = 0; - if((port = atoi(tp)) == 0) { - *--tp = ':'; - } else { - tcp = TRUE; - } - } - if(tcp == TRUE) { - struct hostent *hp; - if((hp = gethostbyname((*host ? host : "localhost"))) == NULL) { - fprintf(stderr, "Unknown host: %s\n", bindPath); - return -1; - } - sa.inetVariant.sin_family = AF_INET; - memcpy(&sa.inetVariant.sin_addr, hp->h_addr, hp->h_length); - sa.inetVariant.sin_port = htons(port); - servLen = sizeof(sa.inetVariant); - resultSock = socket(AF_INET, SOCK_STREAM, 0); - } else { - if(OS_BuildSockAddrUn(bindPath, &sa.unixVariant, &servLen)) { - fprintf(stderr, "Listening socket's path name is too long.\n"); - return -1; - } - resultSock = socket(AF_UNIX, SOCK_STREAM, 0); - } - - ASSERT(resultSock >= 0); - connectStatus = connect(resultSock, (struct sockaddr *) &sa.unixVariant, - servLen); - if(connectStatus >= 0) { - return resultSock; - } else { - /* - * Most likely (errno == ENOENT || errno == ECONNREFUSED) - * and no FCGI application server is running. - */ - close(resultSock); - return -1; - } -} - -/* - *-------------------------------------------------------------- - * - * OS_Read -- - * - * Pass through to the unix read function. - * - * Results: - * Returns number of byes read, 0, or -1 failure: errno - * contains actual error. - * - * Side effects: - * None. - * - *-------------------------------------------------------------- - */ -int OS_Read(int fd, char * buf, size_t len) -{ - if (shutdownNow) return -1; - return(read(fd, buf, len)); -} - -/* - *-------------------------------------------------------------- - * - * OS_Write -- - * - * Pass through to unix write function. - * - * Results: - * Returns number of byes read, 0, or -1 failure: errno - * contains actual error. - * - * Side effects: - * none. - * - *-------------------------------------------------------------- - */ -int OS_Write(int fd, char * buf, size_t len) -{ - if (shutdownNow) return -1; - return(write(fd, buf, len)); -} - -/* - *---------------------------------------------------------------------- - * - * OS_SpawnChild -- - * - * Spawns a new FastCGI listener process. - * - * Results: - * 0 if success, -1 if error. - * - * Side effects: - * Child process spawned. - * - *---------------------------------------------------------------------- - */ -int OS_SpawnChild(char *appPath, int listenFd) -{ - int forkResult; - - forkResult = fork(); - if(forkResult < 0) { - return -1; - } - - if(forkResult == 0) { - /* - * Close STDIN unconditionally. It's used by the parent - * process for CGI communication. The FastCGI applciation - * will be replacing this with the FastCGI listenFd IF - * STDIN_FILENO is the same as FCGI_LISTENSOCK_FILENO - * (which it is on Unix). Regardless, STDIN, STDOUT, and - * STDERR will be closed as the FastCGI process uses a - * multiplexed socket in their place. - */ - close(STDIN_FILENO); - - /* - * If the listenFd is already the value of FCGI_LISTENSOCK_FILENO - * we're set. If not, change it so the child knows where to - * get the listen socket from. - */ - if(listenFd != FCGI_LISTENSOCK_FILENO) { - dup2(listenFd, FCGI_LISTENSOCK_FILENO); - close(listenFd); - } - - close(STDOUT_FILENO); - close(STDERR_FILENO); - - /* - * We're a child. Exec the application. - * - * XXX: entire environment passes through - */ - execl(appPath, appPath, NULL); - /* - * XXX: Can't do this as we've already closed STDERR!!! - * - * perror("exec"); - */ - return -1; - } - return 0; -} - -/* - *-------------------------------------------------------------- - * - * OS_AsyncReadStdin -- - * - * This initiates an asynchronous read on the standard - * input handle. - * - * The abstraction is necessary because Windows NT does not - * have a clean way of "select"ing a file descriptor for - * I/O. - * - * Results: - * -1 if error, 0 otherwise. - * - * Side effects: - * Asynchronous bit is set in the readfd variable and - * request is enqueued. - * - *-------------------------------------------------------------- - */ -int OS_AsyncReadStdin(void *buf, int len, OS_AsyncProc procPtr, - ClientData clientData) -{ - int index = AIO_RD_IX(STDIN_FILENO); - - asyncIoInUse = TRUE; - ASSERT(asyncIoTable[index].inUse == 0); - asyncIoTable[index].procPtr = procPtr; - asyncIoTable[index].clientData = clientData; - asyncIoTable[index].fd = STDIN_FILENO; - asyncIoTable[index].len = len; - asyncIoTable[index].offset = 0; - asyncIoTable[index].buf = buf; - asyncIoTable[index].inUse = 1; - FD_SET(STDIN_FILENO, &readFdSet); - if(STDIN_FILENO > maxFd) - maxFd = STDIN_FILENO; - return 0; -} - -static void GrowAsyncTable(void) -{ - int oldTableSize = asyncIoTableSize; - - asyncIoTableSize = asyncIoTableSize * 2; - asyncIoTable = (AioInfo *)realloc(asyncIoTable, asyncIoTableSize * sizeof(AioInfo)); - if(asyncIoTable == NULL) { - errno = ENOMEM; - exit(errno); - } - memset((char *) &asyncIoTable[oldTableSize], 0, - oldTableSize * sizeof(AioInfo)); - -} - -/* - *-------------------------------------------------------------- - * - * OS_AsyncRead -- - * - * This initiates an asynchronous read on the file - * handle which may be a socket or named pipe. - * - * We also must save the ProcPtr and ClientData, so later - * when the io completes, we know who to call. - * - * We don't look at any results here (the ReadFile may - * return data if it is cached) but do all completion - * processing in OS_Select when we get the io completion - * port done notifications. Then we call the callback. - * - * Results: - * -1 if error, 0 otherwise. - * - * Side effects: - * Asynchronous I/O operation is queued for completion. - * - *-------------------------------------------------------------- - */ -int OS_AsyncRead(int fd, int offset, void *buf, int len, - OS_AsyncProc procPtr, ClientData clientData) -{ - int index = AIO_RD_IX(fd); - - ASSERT(asyncIoTable != NULL); - asyncIoInUse = TRUE; - - if(fd > maxFd) - maxFd = fd; - - if(index >= asyncIoTableSize) { - GrowAsyncTable(); - } - - ASSERT(asyncIoTable[index].inUse == 0); - asyncIoTable[index].procPtr = procPtr; - asyncIoTable[index].clientData = clientData; - asyncIoTable[index].fd = fd; - asyncIoTable[index].len = len; - asyncIoTable[index].offset = offset; - asyncIoTable[index].buf = buf; - asyncIoTable[index].inUse = 1; - FD_SET(fd, &readFdSet); - return 0; -} - -/* - *-------------------------------------------------------------- - * - * OS_AsyncWrite -- - * - * This initiates an asynchronous write on the "fake" file - * descriptor (which may be a file, socket, or named pipe). - * We also must save the ProcPtr and ClientData, so later - * when the io completes, we know who to call. - * - * We don't look at any results here (the WriteFile generally - * completes immediately) but do all completion processing - * in OS_DoIo when we get the io completion port done - * notifications. Then we call the callback. - * - * Results: - * -1 if error, 0 otherwise. - * - * Side effects: - * Asynchronous I/O operation is queued for completion. - * - *-------------------------------------------------------------- - */ -int OS_AsyncWrite(int fd, int offset, void *buf, int len, - OS_AsyncProc procPtr, ClientData clientData) -{ - int index = AIO_WR_IX(fd); - - asyncIoInUse = TRUE; - - if(fd > maxFd) - maxFd = fd; - - if(index >= asyncIoTableSize) { - GrowAsyncTable(); - } - - ASSERT(asyncIoTable[index].inUse == 0); - asyncIoTable[index].procPtr = procPtr; - asyncIoTable[index].clientData = clientData; - asyncIoTable[index].fd = fd; - asyncIoTable[index].len = len; - asyncIoTable[index].offset = offset; - asyncIoTable[index].buf = buf; - asyncIoTable[index].inUse = 1; - FD_SET(fd, &writeFdSet); - return 0; -} - -/* - *-------------------------------------------------------------- - * - * OS_Close -- - * - * Closes the descriptor. This is a pass through to the - * Unix close. - * - * Results: - * 0 for success, -1 on failure - * - * Side effects: - * None. - * - *-------------------------------------------------------------- - */ -int OS_Close(int fd) -{ - if (fd == -1) - return 0; - - if (asyncIoInUse) { - int index = AIO_RD_IX(fd); - - FD_CLR(fd, &readFdSet); - FD_CLR(fd, &readFdSetPost); - if (asyncIoTable[index].inUse != 0) { - asyncIoTable[index].inUse = 0; - } - - FD_CLR(fd, &writeFdSet); - FD_CLR(fd, &writeFdSetPost); - index = AIO_WR_IX(fd); - if (asyncIoTable[index].inUse != 0) { - asyncIoTable[index].inUse = 0; - } - - if (maxFd == fd) { - maxFd--; - } - } - return close(fd); -} - -/* - *-------------------------------------------------------------- - * - * OS_CloseRead -- - * - * Cancel outstanding asynchronous reads and prevent subsequent - * reads from completing. - * - * Results: - * Socket or file is shutdown. Return values mimic Unix shutdown: - * 0 success, -1 failure - * - *-------------------------------------------------------------- - */ -int OS_CloseRead(int fd) -{ - if(asyncIoTable[AIO_RD_IX(fd)].inUse != 0) { - asyncIoTable[AIO_RD_IX(fd)].inUse = 0; - FD_CLR(fd, &readFdSet); - } - - return shutdown(fd, 0); -} - -/* - *-------------------------------------------------------------- - * - * OS_DoIo -- - * - * This function was formerly OS_Select. It's purpose is - * to pull I/O completion events off the queue and dispatch - * them to the appropriate place. - * - * Results: - * Returns 0. - * - * Side effects: - * Handlers are called. - * - *-------------------------------------------------------------- - */ -int OS_DoIo(struct timeval *tmo) -{ - int fd, len, selectStatus; - OS_AsyncProc procPtr; - ClientData clientData; - AioInfo *aioPtr; - fd_set readFdSetCpy; - fd_set writeFdSetCpy; - - asyncIoInUse = TRUE; - FD_ZERO(&readFdSetCpy); - FD_ZERO(&writeFdSetCpy); - - for(fd = 0; fd <= maxFd; fd++) { - if(FD_ISSET(fd, &readFdSet)) { - FD_SET(fd, &readFdSetCpy); - } - if(FD_ISSET(fd, &writeFdSet)) { - FD_SET(fd, &writeFdSetCpy); - } - } - - /* - * If there were no completed events from a prior call, see if there's - * any work to do. - */ - if(numRdPosted == 0 && numWrPosted == 0) { - selectStatus = select((maxFd+1), &readFdSetCpy, &writeFdSetCpy, - NULL, tmo); - if(selectStatus < 0) { - /*exit(errno);*/ - /* not sure what's best to do here */ - return -1; - } - - for(fd = 0; fd <= maxFd; fd++) { - /* - * Build up a list of completed events. We'll work off of - * this list as opposed to looping through the read and write - * fd sets since they can be affected by a callbacl routine. - */ - if(FD_ISSET(fd, &readFdSetCpy)) { - numRdPosted++; - FD_SET(fd, &readFdSetPost); - FD_CLR(fd, &readFdSet); - } - - if(FD_ISSET(fd, &writeFdSetCpy)) { - numWrPosted++; - FD_SET(fd, &writeFdSetPost); - FD_CLR(fd, &writeFdSet); - } - } - } - - if(numRdPosted == 0 && numWrPosted == 0) - return 0; - - for(fd = 0; fd <= maxFd; fd++) { - /* - * Do reads and dispatch callback. - */ - if(FD_ISSET(fd, &readFdSetPost) - && asyncIoTable[AIO_RD_IX(fd)].inUse) { - - numRdPosted--; - FD_CLR(fd, &readFdSetPost); - aioPtr = &asyncIoTable[AIO_RD_IX(fd)]; - - len = read(aioPtr->fd, aioPtr->buf, aioPtr->len); - - procPtr = aioPtr->procPtr; - aioPtr->procPtr = NULL; - clientData = aioPtr->clientData; - aioPtr->inUse = 0; - - (*procPtr)(clientData, len); - } - - /* - * Do writes and dispatch callback. - */ - if(FD_ISSET(fd, &writeFdSetPost) && - asyncIoTable[AIO_WR_IX(fd)].inUse) { - - numWrPosted--; - FD_CLR(fd, &writeFdSetPost); - aioPtr = &asyncIoTable[AIO_WR_IX(fd)]; - - len = write(aioPtr->fd, aioPtr->buf, aioPtr->len); - - procPtr = aioPtr->procPtr; - aioPtr->procPtr = NULL; - clientData = aioPtr->clientData; - aioPtr->inUse = 0; - (*procPtr)(clientData, len); - } - } - return 0; -} - -/* - * Not all systems have strdup(). - * @@@ autoconf should determine whether or not this is needed, but for now.. - */ -static char * str_dup(const char * str) -{ - char * sdup = (char *) malloc(strlen(str) + 1); - - if (sdup) - strcpy(sdup, str); - - return sdup; -} - -/* - *---------------------------------------------------------------------- - * - * ClientAddrOK -- - * - * Checks if a client address is in a list of allowed addresses - * - * Results: - * TRUE if address list is empty or client address is present - * in the list, FALSE otherwise. - * - *---------------------------------------------------------------------- - */ -static int ClientAddrOK(struct sockaddr_in *saPtr, const char *clientList) -{ - int result = FALSE; - char *clientListCopy, *cur, *next; - - if (clientList == NULL || *clientList == '\0') { - return TRUE; - } - - clientListCopy = str_dup(clientList); - - for (cur = clientListCopy; cur != NULL; cur = next) { - next = strchr(cur, ','); - if (next != NULL) { - *next++ = '\0'; - } - if (inet_addr(cur) == saPtr->sin_addr.s_addr) { - result = TRUE; - break; - } - } - - free(clientListCopy); - return result; -} - -/* - *---------------------------------------------------------------------- - * - * AcquireLock -- - * - * On platforms that implement concurrent calls to accept - * on a shared listening ipcFd, returns 0. On other platforms, - * acquires an exclusive lock across all processes sharing a - * listening ipcFd, blocking until the lock has been acquired. - * - * Results: - * 0 for successful call, -1 in case of system error (fatal). - * - * Side effects: - * This process now has the exclusive lock. - * - *---------------------------------------------------------------------- - */ -static int AcquireLock(int sock, int fail_on_intr) -{ -#ifdef USE_LOCKING - do { - struct flock lock; - lock.l_type = F_WRLCK; - lock.l_start = 0; - lock.l_whence = SEEK_SET; - lock.l_len = 0; - - if (fcntl(sock, F_SETLKW, &lock) != -1) - return 0; - } while (errno == EINTR - && ! fail_on_intr - && ! shutdownPending); - - return -1; - -#else - return 0; -#endif -} - -/* - *---------------------------------------------------------------------- - * - * ReleaseLock -- - * - * On platforms that implement concurrent calls to accept - * on a shared listening ipcFd, does nothing. On other platforms, - * releases an exclusive lock acquired by AcquireLock. - * - * Results: - * 0 for successful call, -1 in case of system error (fatal). - * - * Side effects: - * This process no longer holds the lock. - * - *---------------------------------------------------------------------- - */ -static int ReleaseLock(int sock) -{ -#ifdef USE_LOCKING - do { - struct flock lock; - lock.l_type = F_UNLCK; - lock.l_start = 0; - lock.l_whence = SEEK_SET; - lock.l_len = 0; - - if (fcntl(sock, F_SETLK, &lock) != -1) - return 0; - } while (errno == EINTR); - - return -1; - -#else - return 0; -#endif -} - -/********************************************************************** - * Determine if the errno resulting from a failed accept() warrants a - * retry or exit(). Based on Apache's http_main.c accept() handling - * and Stevens' Unix Network Programming Vol 1, 2nd Ed, para. 15.6. - */ -static int is_reasonable_accept_errno (const int error) -{ - switch (error) { -#ifdef EPROTO - /* EPROTO on certain older kernels really means ECONNABORTED, so - * we need to ignore it for them. See discussion in new-httpd - * archives nh.9701 search for EPROTO. Also see nh.9603, search - * for EPROTO: There is potentially a bug in Solaris 2.x x<6, and - * other boxes that implement tcp sockets in userland (i.e. on top of - * STREAMS). On these systems, EPROTO can actually result in a fatal - * loop. See PR#981 for example. It's hard to handle both uses of - * EPROTO. */ - case EPROTO: -#endif -#ifdef ECONNABORTED - case ECONNABORTED: -#endif - /* Linux generates the rest of these, other tcp stacks (i.e. - * bsd) tend to hide them behind getsockopt() interfaces. They - * occur when the net goes sour or the client disconnects after the - * three-way handshake has been done in the kernel but before - * userland has picked up the socket. */ -#ifdef ECONNRESET - case ECONNRESET: -#endif -#ifdef ETIMEDOUT - case ETIMEDOUT: -#endif -#ifdef EHOSTUNREACH - case EHOSTUNREACH: -#endif -#ifdef ENETUNREACH - case ENETUNREACH: -#endif - return 1; - - default: - return 0; - } -} - -/********************************************************************** - * This works around a problem on Linux 2.0.x and SCO Unixware (maybe - * others?). When a connect() is made to a Unix Domain socket, but its - * not accept()ed before the web server gets impatient and close()s, an - * accept() results in a valid file descriptor, but no data to read. - * This causes a block on the first read() - which never returns! - * - * Another approach to this is to write() to the socket to provoke a - * SIGPIPE, but this is a pain because of the FastCGI protocol, the fact - * that whatever is written has to be universally ignored by all FastCGI - * web servers, and a SIGPIPE handler has to be installed which returns - * (or SIGPIPE is ignored). - * - * READABLE_UNIX_FD_DROP_DEAD_TIMEVAL = 2,0 by default. - * - * Making it shorter is probably safe, but I'll leave that to you. Making - * it 0,0 doesn't work reliably. The shorter you can reliably make it, - * the faster your application will be able to recover (waiting 2 seconds - * may _cause_ the problem when there is a very high demand). At any rate, - * this is better than perma-blocking. - */ -static int is_af_unix_keeper(const int fd) -{ - struct timeval tval = { READABLE_UNIX_FD_DROP_DEAD_TIMEVAL }; - fd_set read_fds; - - FD_ZERO(&read_fds); - FD_SET(fd, &read_fds); - - return select(fd + 1, &read_fds, NULL, NULL, &tval) >= 0 && FD_ISSET(fd, &read_fds); -} - -/* - *---------------------------------------------------------------------- - * - * OS_Accept -- - * - * Accepts a new FastCGI connection. This routine knows whether - * we're dealing with TCP based sockets or NT Named Pipes for IPC. - * - * Results: - * -1 if the operation fails, otherwise this is a valid IPC fd. - * - * Side effects: - * New IPC connection is accepted. - * - *---------------------------------------------------------------------- - */ -int OS_Accept(int listen_sock, int fail_on_intr, const char *webServerAddrs) -{ - int socket = -1; - union { - struct sockaddr_un un; - struct sockaddr_in in; - } sa; - - for (;;) { - if (AcquireLock(listen_sock, fail_on_intr)) - return -1; - - for (;;) { - do { -#ifdef HAVE_SOCKLEN - socklen_t len = sizeof(sa); -#else - int len = sizeof(sa); -#endif - if (shutdownPending) break; - /* There's a window here */ - - socket = accept(listen_sock, (struct sockaddr *)&sa, &len); - } while (socket < 0 - && errno == EINTR - && ! fail_on_intr - && ! shutdownPending); - - if (socket < 0) { - if (shutdownPending || ! is_reasonable_accept_errno(errno)) { - int errnoSave = errno; - - ReleaseLock(listen_sock); - - if (! shutdownPending) { - errno = errnoSave; - } - - return (-1); - } - errno = 0; - } - else { /* socket >= 0 */ - int set = 1; - - if (sa.in.sin_family != AF_INET) - break; - -#ifdef TCP_NODELAY - /* No replies to outgoing data, so disable Nagle */ - setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char *)&set, sizeof(set)); -#endif - - /* Check that the client IP address is approved */ - if (ClientAddrOK(&sa.in, webServerAddrs)) - break; - - close(socket); - } /* socket >= 0 */ - } /* for(;;) */ - - if (ReleaseLock(listen_sock)) - return (-1); - - if (sa.in.sin_family != AF_UNIX || is_af_unix_keeper(socket)) - break; - - close(socket); - } /* while(1) - lock */ - - return (socket); -} - -/* - *---------------------------------------------------------------------- - * - * OS_IpcClose - * - * OS IPC routine to close an IPC connection. - * - * Results: - * - * - * Side effects: - * IPC connection is closed. - * - *---------------------------------------------------------------------- - */ -int OS_IpcClose(int ipcFd) -{ - return OS_Close(ipcFd); -} - -/* - *---------------------------------------------------------------------- - * - * OS_IsFcgi -- - * - * Determines whether this process is a FastCGI process or not. - * - * Results: - * Returns 1 if FastCGI, 0 if not. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ -int OS_IsFcgi(int sock) -{ - union { - struct sockaddr_in in; - struct sockaddr_un un; - } sa; -#ifdef HAVE_SOCKLEN - socklen_t len = sizeof(sa); -#else - int len = sizeof(sa); -#endif - - errno = 0; - - if (getpeername(sock, (struct sockaddr *)&sa, &len) != 0 && errno == ENOTCONN) { - return TRUE; - } - else { - return FALSE; - } -} - -/* - *---------------------------------------------------------------------- - * - * OS_SetFlags -- - * - * Sets selected flag bits in an open file descriptor. - * - *---------------------------------------------------------------------- - */ -void OS_SetFlags(int fd, int flags) -{ - int val; - if((val = fcntl(fd, F_GETFL, 0)) < 0) { - return; - } - val |= flags; - if(fcntl(fd, F_SETFL, val) < 0) { - return; - } -} diff --git a/sapi/cgi/libfcgi/os_win32.c b/sapi/cgi/libfcgi/os_win32.c deleted file mode 100644 index 723ef81060..0000000000 --- a/sapi/cgi/libfcgi/os_win32.c +++ /dev/null @@ -1,2067 +0,0 @@ -/* - * os_win32.c -- - * - * - * Copyright (c) 1995 Open Market, Inc. - * All rights reserved. - * - * This file contains proprietary and confidential information and - * remains the unpublished property of Open Market, Inc. Use, - * disclosure, or reproduction is prohibited except as permitted by - * express written license agreement with Open Market, Inc. - * - * Bill Snapper - * snapper@openmarket.com - * - * (Special thanks to Karen and Bill. They made my job much easier and - * significantly more enjoyable.) - */ -#ifndef lint -static const char rcsid[] = "$Id$"; -#endif /* not lint */ - -#define WIN32_LEAN_AND_MEAN -#include -#include -#include -#include -#include -#include - -#define DLLAPI __declspec(dllexport) - -#include "fcgimisc.h" -#include "fcgios.h" - -#define WIN32_OPEN_MAX 128 /* XXX: Small hack */ - -/* - * millisecs to wait for a client connection before checking the - * shutdown flag (then go back to waiting for a connection, etc). - */ -#define ACCEPT_TIMEOUT 1000 - -#define LOCALHOST "localhost" - -static HANDLE hIoCompPort = INVALID_HANDLE_VALUE; -static HANDLE hStdinCompPort = INVALID_HANDLE_VALUE; -static HANDLE hStdinThread = INVALID_HANDLE_VALUE; - -static HANDLE stdioHandles[3] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, - INVALID_HANDLE_VALUE}; - -static HANDLE acceptMutex = INVALID_HANDLE_VALUE; - -static BOOLEAN shutdownPending = FALSE; -static BOOLEAN shutdownNow = FALSE; - -static BOOLEAN bImpersonate = FALSE; -/* - * An enumeration of the file types - * supported by the FD_TABLE structure. - * - * XXX: Not all currently supported. This allows for future - * functionality. - */ -typedef enum { - FD_UNUSED, - FD_FILE_SYNC, - FD_FILE_ASYNC, - FD_SOCKET_SYNC, - FD_SOCKET_ASYNC, - FD_PIPE_SYNC, - FD_PIPE_ASYNC -} FILE_TYPE; - -typedef union { - HANDLE fileHandle; - SOCKET sock; - unsigned int value; -} DESCRIPTOR; - -/* - * Structure used to map file handle and socket handle - * values into values that can be used to create unix-like - * select bitmaps, read/write for both sockets/files. - */ -struct FD_TABLE { - DESCRIPTOR fid; - FILE_TYPE type; - char *path; - DWORD Errno; - unsigned long instance; - int status; - int offset; /* only valid for async file writes */ - LPDWORD offsetHighPtr; /* pointers to offset high and low words */ - LPDWORD offsetLowPtr; /* only valid for async file writes (logs) */ - HANDLE hMapMutex; /* mutex handle for multi-proc offset update */ - LPVOID ovList; /* List of associated OVERLAPPED_REQUESTs */ -}; - -/* - * XXX Note there is no dyanmic sizing of this table, so if the - * number of open file descriptors exceeds WIN32_OPEN_MAX the - * app will blow up. - */ -static struct FD_TABLE fdTable[WIN32_OPEN_MAX]; - -static CRITICAL_SECTION fdTableCritical; - -struct OVERLAPPED_REQUEST { - OVERLAPPED overlapped; - unsigned long instance; /* file instance (won't match after a close) */ - OS_AsyncProc procPtr; /* callback routine */ - ClientData clientData; /* callback argument */ - ClientData clientData1; /* additional clientData */ -}; -typedef struct OVERLAPPED_REQUEST *POVERLAPPED_REQUEST; - -static const char *bindPathPrefix = "\\\\.\\pipe\\FastCGI\\"; - -static FILE_TYPE listenType = FD_UNUSED; - -// XXX This should be a DESCRIPTOR -static HANDLE hListen = INVALID_HANDLE_VALUE; - -static OVERLAPPED listenOverlapped; -static BOOLEAN libInitialized = FALSE; - -/* - *-------------------------------------------------------------- - * - * Win32NewDescriptor -- - * - * Set up for I/O descriptor masquerading. - * - * Results: - * Returns "fake id" which masquerades as a UNIX-style "small - * non-negative integer" file/socket descriptor. - * Win32_* routine below will "do the right thing" based on the - * descriptor's actual type. -1 indicates failure. - * - * Side effects: - * Entry in fdTable is reserved to represent the socket/file. - * - *-------------------------------------------------------------- - */ -static int Win32NewDescriptor(FILE_TYPE type, int fd, int desiredFd) -{ - int index = -1; - - EnterCriticalSection(&fdTableCritical); - - /* - * If desiredFd is set, try to get this entry (this is used for - * mapping stdio handles). Otherwise try to get the fd entry. - * If this is not available, find a the first empty slot. . - */ - if (desiredFd >= 0 && desiredFd < WIN32_OPEN_MAX) - { - if (fdTable[desiredFd].type == FD_UNUSED) - { - index = desiredFd; - } - } - else if (fd > 0) - { - if (fd < WIN32_OPEN_MAX && fdTable[fd].type == FD_UNUSED) - { - index = fd; - } - else - { - int i; - - for (i = 1; i < WIN32_OPEN_MAX; ++i) - { - if (fdTable[i].type == FD_UNUSED) - { - index = i; - break; - } - } - } - } - - if (index != -1) - { - fdTable[index].fid.value = fd; - fdTable[index].type = type; - fdTable[index].path = NULL; - fdTable[index].Errno = NO_ERROR; - fdTable[index].status = 0; - fdTable[index].offset = -1; - fdTable[index].offsetHighPtr = fdTable[index].offsetLowPtr = NULL; - fdTable[index].hMapMutex = NULL; - fdTable[index].ovList = NULL; - } - - LeaveCriticalSection(&fdTableCritical); - return index; -} - -/* - *-------------------------------------------------------------- - * - * StdinThread-- - * - * This thread performs I/O on stadard input. It is needed - * because you can't guarantee that all applications will - * create standard input with sufficient access to perform - * asynchronous I/O. Since we don't want to block the app - * reading from stdin we make it look like it's using I/O - * completion ports to perform async I/O. - * - * Results: - * Data is read from stdin and posted to the io completion - * port. - * - * Side effects: - * None. - * - *-------------------------------------------------------------- - */ -static void StdinThread(LPDWORD startup){ - - int doIo = TRUE; - unsigned long fd; - unsigned long bytesRead; - POVERLAPPED_REQUEST pOv; - - // Touch the arg to prevent warning - startup = NULL; - - while(doIo) { - /* - * Block until a request to read from stdin comes in or a - * request to terminate the thread arrives (fd = -1). - */ - if (!GetQueuedCompletionStatus(hStdinCompPort, &bytesRead, &fd, - (LPOVERLAPPED *)&pOv, (DWORD)-1) && !pOv) { - doIo = 0; - break; - } - - ASSERT((fd == STDIN_FILENO) || (fd == -1)); - if(fd == -1) { - doIo = 0; - break; - } - ASSERT(pOv->clientData1 != NULL); - - if(ReadFile(stdioHandles[STDIN_FILENO], pOv->clientData1, bytesRead, - &bytesRead, NULL)) { - PostQueuedCompletionStatus(hIoCompPort, bytesRead, - STDIN_FILENO, (LPOVERLAPPED)pOv); - } else { - doIo = 0; - break; - } - } - - ExitThread(0); -} - -void OS_ShutdownPending(void) -{ - shutdownPending = TRUE; -} - -/* XXX Need a shutdown now event */ -static DWORD WINAPI ShutdownRequestThread(LPVOID arg) -{ - HANDLE shutdownEvent = (HANDLE) arg; - WaitForSingleObject(shutdownEvent, INFINITE); - shutdownPending = TRUE; - // Before an accept() is entered the shutdownPending flag is checked. - // If set, OS_Accept() will return -1. If not, it waits - // on a connection request for one second, checks the flag, & repeats. - // Only one process/thread is allowed to do this at time by - // wrapping the accept() with mutex. - return 0; -} - -int OS_SetImpersonate(void) -{ - char *os_name = NULL; - os_name = getenv("OS"); - if (os_name && stricmp(os_name, "Windows_NT") == 0) { - bImpersonate = TRUE; - return 1; - } - return 0; -} - -/* - *-------------------------------------------------------------- - * - * OS_LibInit -- - * - * Set up the OS library for use. - * - * Results: - * Returns 0 if success, -1 if not. - * - * Side effects: - * Sockets initialized, pseudo file descriptors setup, etc. - * - *-------------------------------------------------------------- - */ -int OS_LibInit(int stdioFds[3]) -{ - WORD wVersion; - WSADATA wsaData; - int err; - int fakeFd; - DWORD threadId; - char *cLenPtr = NULL; - char *val = NULL; - - if(libInitialized) - return 0; - - InitializeCriticalSection(&fdTableCritical); - - /* - * Initialize windows sockets library. - */ - wVersion = MAKEWORD(2,0); - err = WSAStartup( wVersion, &wsaData ); - if (err) { - fprintf(stderr, "Error starting Windows Sockets. Error: %d", - WSAGetLastError()); - //exit(111); - return -1; - } - - /* - * Create the I/O completion port to be used for our I/O queue. - */ - if (hIoCompPort == INVALID_HANDLE_VALUE) { - hIoCompPort = CreateIoCompletionPort (INVALID_HANDLE_VALUE, NULL, - 0, 1); - if(hIoCompPort == INVALID_HANDLE_VALUE) { - printf("

OS_LibInit Failed CreateIoCompletionPort! ERROR: %d

\r\n\r\n", - GetLastError()); - return -1; - } - } - - /* - * If a shutdown event is in the env, save it (I don't see any to - * remove it from the environment out from under the application). - * Spawn a thread to wait on the shutdown request. - */ - val = getenv(SHUTDOWN_EVENT_NAME); - if (val != NULL) - { - HANDLE shutdownEvent = (HANDLE) atoi(val); - - if (! CreateThread(NULL, 0, ShutdownRequestThread, - shutdownEvent, 0, NULL)) - { - return -1; - } - } - - /* - * If an accept mutex is in the env, save it and remove it. - */ - val = getenv(MUTEX_VARNAME); - if (val != NULL) - { - acceptMutex = (HANDLE) atoi(val); - } - - - /* - * Determine if this library is being used to listen for FastCGI - * connections. This is communicated by STDIN containing a - * valid handle to a listener object. In this case, both the - * "stdout" and "stderr" handles will be INVALID (ie. closed) by - * the starting process. - * - * The trick is determining if this is a pipe or a socket... - * - * XXX: Add the async accept test to determine socket or handle to a - * pipe!!! - */ - if((GetStdHandle(STD_OUTPUT_HANDLE) == INVALID_HANDLE_VALUE) && - (GetStdHandle(STD_ERROR_HANDLE) == INVALID_HANDLE_VALUE) && - (GetStdHandle(STD_INPUT_HANDLE) != INVALID_HANDLE_VALUE) ) - { - DWORD pipeMode = PIPE_READMODE_BYTE | PIPE_WAIT; - HANDLE oldStdIn = GetStdHandle(STD_INPUT_HANDLE); - - // Move the handle to a "low" number - if (! DuplicateHandle(GetCurrentProcess(), oldStdIn, - GetCurrentProcess(), &hListen, - 0, TRUE, DUPLICATE_SAME_ACCESS)) - { - return -1; - } - - if (! SetStdHandle(STD_INPUT_HANDLE, hListen)) - { - return -1; - } - - CloseHandle(oldStdIn); - - /* - * Set the pipe handle state so that it operates in wait mode. - * - * NOTE: The listenFd is not mapped to a pseudo file descriptor - * as all work done on it is contained to the OS library. - * - * XXX: Initial assumption is that SetNamedPipeHandleState will - * fail if this is an IP socket... - */ - if (SetNamedPipeHandleState(hListen, &pipeMode, NULL, NULL)) - { - listenType = FD_PIPE_SYNC; - listenOverlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - } - else - { - listenType = FD_SOCKET_SYNC; - } - } - - /* - * If there are no stdioFds passed in, we're done. - */ - if(stdioFds == NULL) { - libInitialized = 1; - return 0; - } - - /* - * Setup standard input asynchronous I/O. There is actually a separate - * thread spawned for this purpose. The reason for this is that some - * web servers use anonymous pipes for the connection between itself - * and a CGI application. Anonymous pipes can't perform asynchronous - * I/O or use I/O completion ports. Therefore in order to present a - * consistent I/O dispatch model to an application we emulate I/O - * completion port behavior by having the standard input thread posting - * messages to the hIoCompPort which look like a complete overlapped - * I/O structure. This keeps the event dispatching simple from the - * application perspective. - */ - stdioHandles[STDIN_FILENO] = GetStdHandle(STD_INPUT_HANDLE); - - if(!SetHandleInformation(stdioHandles[STDIN_FILENO], - HANDLE_FLAG_INHERIT, 0)) { -/* - * XXX: Causes error when run from command line. Check KB - err = GetLastError(); - DebugBreak(); - exit(99); - */ - return -1; - } - - if ((fakeFd = Win32NewDescriptor(FD_PIPE_SYNC, - (int)stdioHandles[STDIN_FILENO], - STDIN_FILENO)) == -1) { - return -1; - } else { - /* - * Set stdin equal to our pseudo FD and create the I/O completion - * port to be used for async I/O. - */ - stdioFds[STDIN_FILENO] = fakeFd; - } - - /* - * Create the I/O completion port to be used for communicating with - * the thread doing I/O on standard in. This port will carry read - * and possibly thread termination requests to the StdinThread. - */ - if (hStdinCompPort == INVALID_HANDLE_VALUE) { - hStdinCompPort = CreateIoCompletionPort (INVALID_HANDLE_VALUE, NULL, - 0, 1); - if(hStdinCompPort == INVALID_HANDLE_VALUE) { - printf("

OS_LibInit Failed CreateIoCompletionPort: STDIN! ERROR: %d

\r\n\r\n", - GetLastError()); - return -1; - } - } - - /* - * Create the thread that will read stdin if the CONTENT_LENGTH - * is non-zero. - */ - if((cLenPtr = getenv("CONTENT_LENGTH")) != NULL && - atoi(cLenPtr) > 0) { - hStdinThread = CreateThread(NULL, 8192, - (LPTHREAD_START_ROUTINE)&StdinThread, - NULL, 0, &threadId); - if (hStdinThread == NULL) { - printf("

OS_LibInit Failed to create STDIN thread! ERROR: %d

\r\n\r\n", - GetLastError()); - return -1; - } - } - - /* - * STDOUT will be used synchronously. - * - * XXX: May want to convert this so that it could be used for OVERLAPPED - * I/O later. If so, model it after the Stdin I/O as stdout is - * also incapable of async I/O on some servers. - */ - stdioHandles[STDOUT_FILENO] = GetStdHandle(STD_OUTPUT_HANDLE); - if(!SetHandleInformation(stdioHandles[STDOUT_FILENO], - HANDLE_FLAG_INHERIT, FALSE)) { - //exit(99); - return -1; - } - - if ((fakeFd = Win32NewDescriptor(FD_PIPE_SYNC, - (int)stdioHandles[STDOUT_FILENO], - STDOUT_FILENO)) == -1) { - return -1; - } else { - /* - * Set stdout equal to our pseudo FD - */ - stdioFds[STDOUT_FILENO] = fakeFd; - } - - stdioHandles[STDERR_FILENO] = GetStdHandle(STD_ERROR_HANDLE); - if(!SetHandleInformation(stdioHandles[STDERR_FILENO], - HANDLE_FLAG_INHERIT, FALSE)) { - //exit(99); - return -1; - } - if ((fakeFd = Win32NewDescriptor(FD_PIPE_SYNC, - (int)stdioHandles[STDERR_FILENO], - STDERR_FILENO)) == -1) { - return -1; - } else { - /* - * Set stderr equal to our pseudo FD - */ - stdioFds[STDERR_FILENO] = fakeFd; - } - - return 0; -} - -/* - *-------------------------------------------------------------- - * - * OS_LibShutdown -- - * - * Shutdown the OS library. - * - * Results: - * None. - * - * Side effects: - * Memory freed, handles closed. - * - *-------------------------------------------------------------- - */ -void OS_LibShutdown() -{ - - if (hIoCompPort != INVALID_HANDLE_VALUE) - { - CloseHandle(hIoCompPort); - hIoCompPort = INVALID_HANDLE_VALUE; - } - - if (hStdinCompPort != INVALID_HANDLE_VALUE) - { - CloseHandle(hStdinCompPort); - hStdinCompPort = INVALID_HANDLE_VALUE; - } - - if (acceptMutex != INVALID_HANDLE_VALUE) - { - ReleaseMutex(acceptMutex); - CloseHandle(acceptMutex); - } - - /* we only want to do this if we're not a web server */ - if (stdioHandles[0] != INVALID_HANDLE_VALUE) { - DisconnectNamedPipe(hListen); - CancelIo(hListen); - if (bImpersonate) RevertToSelf(); - } - - DeleteCriticalSection(&fdTableCritical); - WSACleanup(); -} - -/* - *-------------------------------------------------------------- - * - * Win32FreeDescriptor -- - * - * Free I/O descriptor entry in fdTable. - * - * Results: - * Frees I/O descriptor entry in fdTable. - * - * Side effects: - * None. - * - *-------------------------------------------------------------- - */ -static void Win32FreeDescriptor(int fd) -{ - /* Catch it if fd is a bogus value */ - ASSERT((fd >= 0) && (fd < WIN32_OPEN_MAX)); - - EnterCriticalSection(&fdTableCritical); - - if (fdTable[fd].type != FD_UNUSED) - { - switch (fdTable[fd].type) - { - case FD_FILE_SYNC: - case FD_FILE_ASYNC: - - /* Free file path string */ - ASSERT(fdTable[fd].path != NULL); - - free(fdTable[fd].path); - fdTable[fd].path = NULL; - break; - case FD_PIPE_ASYNC: - break; - default: - break; - } - - ASSERT(fdTable[fd].path == NULL); - - fdTable[fd].type = FD_UNUSED; - fdTable[fd].path = NULL; - fdTable[fd].Errno = NO_ERROR; - fdTable[fd].offsetHighPtr = fdTable[fd].offsetLowPtr = NULL; - - if (fdTable[fd].hMapMutex != NULL) - { - CloseHandle(fdTable[fd].hMapMutex); - fdTable[fd].hMapMutex = NULL; - } - } - - LeaveCriticalSection(&fdTableCritical); - - return; -} - -static short getPort(const char * bindPath) -{ - short port = 0; - char * p = strchr(bindPath, ':'); - - if (p && *++p) - { - char buf[6]; - - strncpy(buf, p, 6); - buf[5] = '\0'; - - port = (short) atoi(buf); - } - - return port; -} - -/** -This function builds a Dacl which grants the creator of the objects -FILE_ALL_ACCESS and Everyone FILE_GENERIC_READ and FILE_GENERIC_WRITE -access to the object. - -This Dacl allows for higher security than a NULL Dacl, which is common for -named-pipes, as this only grants the creator/owner write access to the -security descriptor, and grants Everyone the ability to "use" the named-pipe. -This scenario prevents a malevolent user from disrupting service by preventing -arbitrary access manipulation. -**/ -BOOL -BuildNamedPipeAcl( - PACL pAcl, - PDWORD cbAclSize - ) -{ - DWORD dwAclSize; - - SID_IDENTIFIER_AUTHORITY siaWorld = SECURITY_WORLD_SID_AUTHORITY; - SID_IDENTIFIER_AUTHORITY siaCreator = SECURITY_CREATOR_SID_AUTHORITY; - - BYTE BufEveryoneSid[32]; - BYTE BufOwnerSid[32]; - - PSID pEveryoneSid = (PSID)BufEveryoneSid; - PSID pOwnerSid = (PSID)BufOwnerSid; - - // - // compute size of acl - // - dwAclSize = sizeof(ACL) + - 2 * ( sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) ) + - GetSidLengthRequired( 1 ) + // well-known Everyone Sid - GetSidLengthRequired( 1 ) ; // well-known Creator Owner Sid - - if(*cbAclSize < dwAclSize) { - *cbAclSize = dwAclSize; - return FALSE; - } - - *cbAclSize = dwAclSize; - - // - // intialize well known sids - // - - if(!InitializeSid(pEveryoneSid, &siaWorld, 1)) return FALSE; - *GetSidSubAuthority(pEveryoneSid, 0) = SECURITY_WORLD_RID; - - if(!InitializeSid(pOwnerSid, &siaCreator, 1)) return FALSE; - *GetSidSubAuthority(pOwnerSid, 0) = SECURITY_CREATOR_OWNER_RID; - - if(!InitializeAcl(pAcl, dwAclSize, ACL_REVISION)) - return FALSE; - - // - // - if(!AddAccessAllowedAce( - pAcl, - ACL_REVISION, - FILE_GENERIC_READ | FILE_GENERIC_WRITE, - pEveryoneSid - )) - return FALSE; - - // - // - return AddAccessAllowedAce( - pAcl, - ACL_REVISION, - FILE_ALL_ACCESS, - pOwnerSid - ); -} - - -/* - * OS_CreateLocalIpcFd -- - * - * This procedure is responsible for creating the listener pipe - * on Windows NT for local process communication. It will create a - * named pipe and return a file descriptor to it to the caller. - * - * Results: - * Listener pipe created. This call returns either a valid - * pseudo file descriptor or -1 on error. - * - * Side effects: - * Listener pipe and IPC address are stored in the FCGI info - * structure. - * 'errno' will set on errors (-1 is returned). - * - *---------------------------------------------------------------------- - */ -int OS_CreateLocalIpcFd(const char *bindPath, int backlog, int bCreateMutex) -{ - int pseudoFd = -1; - short port = getPort(bindPath); - HANDLE mutex = INVALID_HANDLE_VALUE; - char mutexEnvString[100]; - - if (bCreateMutex) { - mutex = CreateMutex(NULL, FALSE, NULL); - if (! SetHandleInformation(mutex, HANDLE_FLAG_INHERIT, TRUE)) - { - CloseHandle(mutex); - return -3; - } - // This is a nail for listening to more than one port.. - // This should really be handled by the caller. - _snprintf(mutexEnvString, sizeof(mutexEnvString)-1, MUTEX_VARNAME "=%d", (int) mutex); - putenv(mutexEnvString); - } - - // There's nothing to be gained (at the moment) by a shutdown Event - - if (port && *bindPath != ':' && strncmp(bindPath, LOCALHOST, strlen(LOCALHOST))) - { - fprintf(stderr, "To start a service on a TCP port can not " - "specify a host name.\n" - "You should either use \"localhost:\" or " - " just use \":.\"\n"); - //exit(1); - if (bCreateMutex) CloseHandle(mutexEnvString); - return -1; - } - - listenType = (port) ? FD_SOCKET_SYNC : FD_PIPE_ASYNC; - - if (port) - { - SOCKET listenSock; - struct sockaddr_in sockAddr; - int sockLen = sizeof(sockAddr); - - memset(&sockAddr, 0, sizeof(sockAddr)); - sockAddr.sin_family = AF_INET; - sockAddr.sin_addr.s_addr = htonl(INADDR_ANY); - sockAddr.sin_port = htons(port); - - listenSock = socket(AF_INET, SOCK_STREAM, 0); - if (listenSock == INVALID_SOCKET) - { - if (bCreateMutex)CloseHandle(mutexEnvString); - return -4; - } - - if (bind(listenSock, (struct sockaddr *) &sockAddr, sockLen) ) - { - if (bCreateMutex)CloseHandle(mutexEnvString); - return -12; - } - - if (listen(listenSock, backlog)) - { - if (bCreateMutex)CloseHandle(mutexEnvString); - return -5; - } - - pseudoFd = Win32NewDescriptor(listenType, listenSock, -1); - - if (pseudoFd == -1) - { - if (bCreateMutex)CloseHandle(mutexEnvString); - closesocket(listenSock); - return -6; - } - - hListen = (HANDLE) listenSock; - } - else - { - SECURITY_ATTRIBUTES sa; - SECURITY_DESCRIPTOR sd; - BYTE AclBuf[ 64 ]; - DWORD cbAclSize = 64; - PACL pAcl = (PACL)AclBuf; - - HANDLE hListenPipe = INVALID_HANDLE_VALUE; - char *pipePath = malloc(strlen(bindPathPrefix) + strlen(bindPath) + 1); - - if (! pipePath) - { - if (bCreateMutex)CloseHandle(mutexEnvString); - return -7; - } - - strcpy(pipePath, bindPathPrefix); - strcat(pipePath, bindPath); - - if (bImpersonate) { - // get the security attributes for Everybody to connect - // we do this so that multithreaded servers that run - // threads under secured users can access pipes created - // by a system level thread (for instance, IIS) - // - // suppress errors regarding startup directory, etc - // - SetErrorMode(SEM_FAILCRITICALERRORS); - - if(!BuildNamedPipeAcl(pAcl, &cbAclSize)) { - fprintf(stderr, "BuildNamedPipeAcl"); - return -100; - } - - if(!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) { - fprintf(stderr, "InitializeSecurityDescriptor"); - return -100; - } - - if(!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) { - fprintf(stderr, "SetSecurityDescriptorDacl"); - return -100; - } - - sa.nLength = sizeof(SECURITY_ATTRIBUTES); - sa.lpSecurityDescriptor = &sd; // default Dacl of caller - sa.bInheritHandle = TRUE; - - } - - hListenPipe = CreateNamedPipe(pipePath, - PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, - PIPE_TYPE_BYTE | PIPE_WAIT | PIPE_READMODE_BYTE, - PIPE_UNLIMITED_INSTANCES, - 4096, 4096, 0, bImpersonate?&sa:NULL); - - free(pipePath); - - if (hListenPipe == INVALID_HANDLE_VALUE) - { - if (bCreateMutex)CloseHandle(mutexEnvString); - return -8; - } - - if (! SetHandleInformation(hListenPipe, HANDLE_FLAG_INHERIT, TRUE)) - { - if (bCreateMutex)CloseHandle(mutexEnvString); - return -9; - } - - pseudoFd = Win32NewDescriptor(listenType, (int) hListenPipe, -1); - - if (pseudoFd == -1) - { - if (bCreateMutex)CloseHandle(mutexEnvString); - CloseHandle(hListenPipe); - return -10; - } - - hListen = (HANDLE) hListenPipe; - } - - return pseudoFd; -} - -/* - *---------------------------------------------------------------------- - * - * OS_FcgiConnect -- - * - * Create the pipe pathname connect to the remote application if - * possible. - * - * Results: - * -1 if fail or a valid handle if connection succeeds. - * - * Side effects: - * Remote connection established. - * - *---------------------------------------------------------------------- - */ -int OS_FcgiConnect(char *bindPath) -{ - short port = getPort(bindPath); - int pseudoFd = -1; - unsigned int flags = FILE_FLAG_OVERLAPPED; - if (port) - { - struct hostent *hp; - char *host = NULL; - struct sockaddr_in sockAddr; - int sockLen = sizeof(sockAddr); - SOCKET sock; - - if (*bindPath != ':') - { - char * p = strchr(bindPath, ':'); - if (p) { - int len = p - bindPath + 1; - - host = (char *)malloc(len); - if (!host) { - fprintf(stderr, "Unable to allocate memory\n"); - return -1; - } - strncpy(host, bindPath, len); - host[len-1] = '\0'; - } - } - - hp = gethostbyname(host ? host : LOCALHOST); - - if (host) - { - free(host); - } - - if (hp == NULL) - { - fprintf(stderr, "Unknown host: %s\n", bindPath); - return -1; - } - - memset(&sockAddr, 0, sizeof(sockAddr)); - sockAddr.sin_family = AF_INET; - memcpy(&sockAddr.sin_addr, hp->h_addr, hp->h_length); - sockAddr.sin_port = htons(port); - - sock = socket(AF_INET, SOCK_STREAM, 0); - if (sock == INVALID_SOCKET) - { - return -1; - } - - if (connect(sock, (struct sockaddr *) &sockAddr, sockLen) == SOCKET_ERROR) - { - closesocket(sock); - return -1; - } - - pseudoFd = Win32NewDescriptor(FD_SOCKET_SYNC, sock, -1); - if (pseudoFd == -1) - { - closesocket(sock); - return -1; - } - } - else - { - char *pipePath = malloc(strlen(bindPathPrefix) + strlen(bindPath) + 1); - HANDLE hPipe; - - if (! pipePath) - { - return -1; - } - - strcpy(pipePath, bindPathPrefix); - strcat(pipePath, bindPath); - - if (bImpersonate) { - flags |= SECURITY_SQOS_PRESENT | SECURITY_IMPERSONATION; - } - - hPipe = CreateFile(pipePath, - GENERIC_WRITE | GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - OPEN_EXISTING, - flags, - NULL); - - free(pipePath); - - if( hPipe == INVALID_HANDLE_VALUE || hPipe == 0) - { - return -1; - } - - pseudoFd = Win32NewDescriptor(FD_PIPE_ASYNC, (int) hPipe, -1); - - if (pseudoFd == -1) - { - CloseHandle(hPipe); - return -1; - } - - /* - * Set stdin equal to our pseudo FD and create the I/O completion - * port to be used for async I/O. - */ - if (! CreateIoCompletionPort(hPipe, hIoCompPort, pseudoFd, 1)) - { - Win32FreeDescriptor(pseudoFd); - CloseHandle(hPipe); - return -1; - } - } - - return pseudoFd; -} - -/* - *-------------------------------------------------------------- - * - * OS_Read -- - * - * Pass through to the appropriate NT read function. - * - * Results: - * Returns number of byes read. Mimics unix read:. - * n bytes read, 0 or -1 failure: errno contains actual error - * - * Side effects: - * None. - * - *-------------------------------------------------------------- - */ -int OS_Read(int fd, char * buf, size_t len) -{ - DWORD bytesRead; - int ret = -1; - - ASSERT((fd >= 0) && (fd < WIN32_OPEN_MAX)); - - if (shutdownNow) return -1; - - switch (fdTable[fd].type) - { - case FD_FILE_SYNC: - case FD_FILE_ASYNC: - case FD_PIPE_SYNC: - case FD_PIPE_ASYNC: - - if (ReadFile(fdTable[fd].fid.fileHandle, buf, len, &bytesRead, NULL)) - { - ret = bytesRead; - } - else - { - fdTable[fd].Errno = GetLastError(); - ret = -1; - } - - break; - - case FD_SOCKET_SYNC: - case FD_SOCKET_ASYNC: - - ret = recv(fdTable[fd].fid.sock, buf, len, 0); - if (ret == SOCKET_ERROR) - { - fdTable[fd].Errno = WSAGetLastError(); - ret = -1; - } - - break; - - default: - - ASSERT(0); - } - - return ret; -} - -/* - *-------------------------------------------------------------- - * - * OS_Write -- - * - * Perform a synchronous OS write. - * - * Results: - * Returns number of bytes written. Mimics unix write: - * n bytes written, 0 or -1 failure (??? couldn't find man page). - * - * Side effects: - * none. - * - *-------------------------------------------------------------- - */ -int OS_Write(int fd, char * buf, size_t len) -{ - DWORD bytesWritten; - int ret = -1; - - ASSERT(fd >= 0 && fd < WIN32_OPEN_MAX); - - if (shutdownNow) return -1; - - switch (fdTable[fd].type) - { - case FD_FILE_SYNC: - case FD_FILE_ASYNC: - case FD_PIPE_SYNC: - case FD_PIPE_ASYNC: - - if (WriteFile(fdTable[fd].fid.fileHandle, buf, len, &bytesWritten, NULL)) - { - ret = bytesWritten; - } - else - { - fdTable[fd].Errno = GetLastError(); - } - - break; - - case FD_SOCKET_SYNC: - case FD_SOCKET_ASYNC: - - ret = send(fdTable[fd].fid.sock, buf, len, 0); - if (ret == SOCKET_ERROR) - { - fdTable[fd].Errno = WSAGetLastError(); - ret = -1; - } - - break; - - default: - - ASSERT(0); - } - - return ret; -} - -/* - *---------------------------------------------------------------------- - * - * OS_SpawnChild -- - * - * Spawns a new server listener process, and stores the information - * relating to the child in the supplied record. A wait handler is - * registered on the child's completion. This involves creating - * a process on NT and preparing a command line with the required - * state (currently a -childproc flag and the server socket to use - * for accepting connections). - * - * Results: - * 0 if success, -1 if error. - * - * Side effects: - * Child process spawned. - * - *---------------------------------------------------------------------- - */ -int OS_SpawnChild(char *execPath, int listenFd, PROCESS_INFORMATION *pInfo, char *env) -{ - STARTUPINFO StartupInfo; - BOOL success; - - memset((void *)&StartupInfo, 0, sizeof(STARTUPINFO)); - StartupInfo.cb = sizeof (STARTUPINFO); - StartupInfo.lpReserved = NULL; - StartupInfo.lpReserved2 = NULL; - StartupInfo.cbReserved2 = 0; - StartupInfo.lpDesktop = NULL; - StartupInfo.wShowWindow = SW_HIDE; - /* - * FastCGI on NT will set the listener pipe HANDLE in the stdin of - * the new process. The fact that there is a stdin and NULL handles - * for stdout and stderr tells the FastCGI process that this is a - * FastCGI process and not a CGI process. - */ - StartupInfo.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW; - /* - * XXX: Do I have to dup the handle before spawning the process or is - * it sufficient to use the handle as it's reference counted - * by NT anyway? - */ - StartupInfo.hStdInput = fdTable[listenFd].fid.fileHandle; - StartupInfo.hStdOutput = INVALID_HANDLE_VALUE; - StartupInfo.hStdError = INVALID_HANDLE_VALUE; - - /* - * Make the listener socket inheritable. - */ - success = SetHandleInformation(StartupInfo.hStdInput, HANDLE_FLAG_INHERIT, - TRUE); - if(!success) { - //exit(99); - return -1; - } - - /* - * XXX: Might want to apply some specific security attributes to the - * processes. - */ - success = CreateProcess(execPath, /* LPCSTR address of module name */ - NULL, /* LPCSTR address of command line */ - NULL, /* Process security attributes */ - NULL, /* Thread security attributes */ - TRUE, /* Inheritable Handes inherited. */ - 0, /* DWORD creation flags */ - env, /* Use parent environment block */ - NULL, /* Address of current directory name */ - &StartupInfo, /* Address of STARTUPINFO */ - pInfo); /* Address of PROCESS_INFORMATION */ - if(success) { - return 0; - } else { - return -1; - } -} - -/* - *-------------------------------------------------------------- - * - * OS_AsyncReadStdin -- - * - * This initiates an asynchronous read on the standard - * input handle. This handle is not guaranteed to be - * capable of performing asynchronous I/O so we send a - * message to the StdinThread to do the synchronous read. - * - * Results: - * -1 if error, 0 otherwise. - * - * Side effects: - * Asynchronous message is queued to the StdinThread and an - * overlapped structure is allocated/initialized. - * - *-------------------------------------------------------------- - */ -int OS_AsyncReadStdin(void *buf, int len, OS_AsyncProc procPtr, - ClientData clientData) -{ - POVERLAPPED_REQUEST pOv; - - ASSERT(fdTable[STDIN_FILENO].type != FD_UNUSED); - - pOv = (POVERLAPPED_REQUEST)malloc(sizeof(struct OVERLAPPED_REQUEST)); - ASSERT(pOv); - memset((void *)pOv, 0, sizeof(struct OVERLAPPED_REQUEST)); - pOv->clientData1 = (ClientData)buf; - pOv->instance = fdTable[STDIN_FILENO].instance; - pOv->procPtr = procPtr; - pOv->clientData = clientData; - - PostQueuedCompletionStatus(hStdinCompPort, len, STDIN_FILENO, - (LPOVERLAPPED)pOv); - return 0; -} - -/* - *-------------------------------------------------------------- - * - * OS_AsyncRead -- - * - * This initiates an asynchronous read on the file - * handle which may be a socket or named pipe. - * - * We also must save the ProcPtr and ClientData, so later - * when the io completes, we know who to call. - * - * We don't look at any results here (the ReadFile may - * return data if it is cached) but do all completion - * processing in OS_Select when we get the io completion - * port done notifications. Then we call the callback. - * - * Results: - * -1 if error, 0 otherwise. - * - * Side effects: - * Asynchronous I/O operation is queued for completion. - * - *-------------------------------------------------------------- - */ -int OS_AsyncRead(int fd, int offset, void *buf, int len, - OS_AsyncProc procPtr, ClientData clientData) -{ - DWORD bytesRead; - POVERLAPPED_REQUEST pOv; - - /* - * Catch any bogus fd values - */ - ASSERT((fd >= 0) && (fd < WIN32_OPEN_MAX)); - /* - * Confirm that this is an async fd - */ - ASSERT(fdTable[fd].type != FD_UNUSED); - ASSERT(fdTable[fd].type != FD_FILE_SYNC); - ASSERT(fdTable[fd].type != FD_PIPE_SYNC); - ASSERT(fdTable[fd].type != FD_SOCKET_SYNC); - - pOv = (POVERLAPPED_REQUEST)malloc(sizeof(struct OVERLAPPED_REQUEST)); - ASSERT(pOv); - memset((void *)pOv, 0, sizeof(struct OVERLAPPED_REQUEST)); - /* - * Only file offsets should be non-zero, but make sure. - */ - if (fdTable[fd].type == FD_FILE_ASYNC) - if (fdTable[fd].offset >= 0) - pOv->overlapped.Offset = fdTable[fd].offset; - else - pOv->overlapped.Offset = offset; - pOv->instance = fdTable[fd].instance; - pOv->procPtr = procPtr; - pOv->clientData = clientData; - bytesRead = fd; - /* - * ReadFile returns: TRUE success, FALSE failure - */ - if (!ReadFile(fdTable[fd].fid.fileHandle, buf, len, &bytesRead, - (LPOVERLAPPED)pOv)) { - fdTable[fd].Errno = GetLastError(); - if(fdTable[fd].Errno == ERROR_NO_DATA || - fdTable[fd].Errno == ERROR_PIPE_NOT_CONNECTED) { - PostQueuedCompletionStatus(hIoCompPort, 0, fd, (LPOVERLAPPED)pOv); - return 0; - } - if(fdTable[fd].Errno != ERROR_IO_PENDING) { - PostQueuedCompletionStatus(hIoCompPort, 0, fd, (LPOVERLAPPED)pOv); - return -1; - } - fdTable[fd].Errno = 0; - } - return 0; -} - -/* - *-------------------------------------------------------------- - * - * OS_AsyncWrite -- - * - * This initiates an asynchronous write on the "fake" file - * descriptor (which may be a file, socket, or named pipe). - * We also must save the ProcPtr and ClientData, so later - * when the io completes, we know who to call. - * - * We don't look at any results here (the WriteFile generally - * completes immediately) but do all completion processing - * in OS_DoIo when we get the io completion port done - * notifications. Then we call the callback. - * - * Results: - * -1 if error, 0 otherwise. - * - * Side effects: - * Asynchronous I/O operation is queued for completion. - * - *-------------------------------------------------------------- - */ -int OS_AsyncWrite(int fd, int offset, void *buf, int len, - OS_AsyncProc procPtr, ClientData clientData) -{ - DWORD bytesWritten; - POVERLAPPED_REQUEST pOv; - - /* - * Catch any bogus fd values - */ - ASSERT((fd >= 0) && (fd < WIN32_OPEN_MAX)); - /* - * Confirm that this is an async fd - */ - ASSERT(fdTable[fd].type != FD_UNUSED); - ASSERT(fdTable[fd].type != FD_FILE_SYNC); - ASSERT(fdTable[fd].type != FD_PIPE_SYNC); - ASSERT(fdTable[fd].type != FD_SOCKET_SYNC); - - pOv = (POVERLAPPED_REQUEST)malloc(sizeof(struct OVERLAPPED_REQUEST)); - ASSERT(pOv); - memset((void *)pOv, 0, sizeof(struct OVERLAPPED_REQUEST)); - /* - * Only file offsets should be non-zero, but make sure. - */ - if (fdTable[fd].type == FD_FILE_ASYNC) - /* - * Only file opened via OS_AsyncWrite with - * O_APPEND will have an offset != -1. - */ - if (fdTable[fd].offset >= 0) - /* - * If the descriptor has a memory mapped file - * handle, take the offsets from there. - */ - if (fdTable[fd].hMapMutex != NULL) { - /* - * Wait infinitely; this *should* not cause problems. - */ - WaitForSingleObject(fdTable[fd].hMapMutex, INFINITE); - - /* - * Retrieve the shared offset values. - */ - pOv->overlapped.OffsetHigh = *(fdTable[fd].offsetHighPtr); - pOv->overlapped.Offset = *(fdTable[fd].offsetLowPtr); - - /* - * Update the shared offset values for the next write - */ - *(fdTable[fd].offsetHighPtr) += 0; /* XXX How do I handle overflow */ - *(fdTable[fd].offsetLowPtr) += len; - - ReleaseMutex(fdTable[fd].hMapMutex); - } else - pOv->overlapped.Offset = fdTable[fd].offset; - else - pOv->overlapped.Offset = offset; - pOv->instance = fdTable[fd].instance; - pOv->procPtr = procPtr; - pOv->clientData = clientData; - bytesWritten = fd; - /* - * WriteFile returns: TRUE success, FALSE failure - */ - if (!WriteFile(fdTable[fd].fid.fileHandle, buf, len, &bytesWritten, - (LPOVERLAPPED)pOv)) { - fdTable[fd].Errno = GetLastError(); - if(fdTable[fd].Errno != ERROR_IO_PENDING) { - PostQueuedCompletionStatus(hIoCompPort, 0, fd, (LPOVERLAPPED)pOv); - return -1; - } - fdTable[fd].Errno = 0; - } - if (fdTable[fd].offset >= 0) - fdTable[fd].offset += len; - return 0; -} - -/* - *-------------------------------------------------------------- - * - * OS_Close -- - * - * Closes the descriptor with routine appropriate for - * descriptor's type. - * - * Results: - * Socket or file is closed. Return values mimic Unix close: - * 0 success, -1 failure - * - * Side effects: - * Entry in fdTable is marked as free. - * - *-------------------------------------------------------------- - */ -int OS_Close(int fd) -{ - int ret = 0; - - /* - * Catch it if fd is a bogus value - */ - ASSERT((fd >= 0) && (fd < WIN32_OPEN_MAX)); - ASSERT(fdTable[fd].type != FD_UNUSED); - - switch (fdTable[fd].type) { - case FD_PIPE_SYNC: - case FD_PIPE_ASYNC: - case FD_FILE_SYNC: - case FD_FILE_ASYNC: - /* - * CloseHandle returns: TRUE success, 0 failure - */ - /* - XXX don't close here, fcgi apps fail if we do so - need to examine resource leaks if any might exist - if (CloseHandle(fdTable[fd].fid.fileHandle) == FALSE) - ret = -1; - */ - break; - case FD_SOCKET_SYNC: - case FD_SOCKET_ASYNC: - /* - * Closing a socket that has an async read outstanding causes a - * tcp reset and possible data loss. The shutdown call seems to - * prevent this. - */ - - /* shutdown(fdTable[fd].fid.sock, SD_BOTH); */ - - { - char buf[16]; - int r; - - shutdown(fdTable[fd].fid.sock,SD_SEND); - - do - { - r = recv(fdTable[fd].fid.sock,buf,16,0); - } while (r > 0); - } - /* - * closesocket returns: 0 success, SOCKET_ERROR failure - */ - if (closesocket(fdTable[fd].fid.sock) == SOCKET_ERROR) - ret = -1; - break; - default: - return -1; /* fake failure */ - } - - Win32FreeDescriptor(fd); - return ret; -} - -/* - *-------------------------------------------------------------- - * - * OS_CloseRead -- - * - * Cancel outstanding asynchronous reads and prevent subsequent - * reads from completing. - * - * Results: - * Socket or file is shutdown. Return values mimic Unix shutdown: - * 0 success, -1 failure - * - *-------------------------------------------------------------- - */ -int OS_CloseRead(int fd) -{ - int ret = 0; - - /* - * Catch it if fd is a bogus value - */ - ASSERT((fd >= 0) && (fd < WIN32_OPEN_MAX)); - ASSERT(fdTable[fd].type == FD_SOCKET_ASYNC - || fdTable[fd].type == FD_SOCKET_SYNC); - - if (shutdown(fdTable[fd].fid.sock,SD_RECEIVE) == SOCKET_ERROR) - ret = -1; - return ret; -} - -/* - *-------------------------------------------------------------- - * - * OS_DoIo -- - * - * This function was formerly OS_Select. It's purpose is - * to pull I/O completion events off the queue and dispatch - * them to the appropriate place. - * - * Results: - * Returns 0. - * - * Side effects: - * Handlers are called. - * - *-------------------------------------------------------------- - */ -int OS_DoIo(struct timeval *tmo) -{ - unsigned long fd; - unsigned long bytes; - POVERLAPPED_REQUEST pOv; - struct timeb tb; - int ms; - int ms_last; - int err; - - /* XXX - * We can loop in here, but not too long, as wait handlers - * must run. - * For cgi stdin, apparently select returns when io completion - * ports don't, so don't wait the full timeout. - */ - if(tmo) - ms = (tmo->tv_sec*1000 + tmo->tv_usec/1000) / 2; - else - ms = 1000; - ftime(&tb); - ms_last = tb.time*1000 + tb.millitm; - while (ms >= 0) { - if(tmo && (ms = tmo->tv_sec*1000 + tmo->tv_usec/1000)> 100) - ms = 100; - if (!GetQueuedCompletionStatus(hIoCompPort, &bytes, &fd, - (LPOVERLAPPED *)&pOv, ms) && !pOv) { - err = WSAGetLastError(); - return 0; /* timeout */ - } - - ASSERT((fd >= 0) && (fd < WIN32_OPEN_MAX)); - /* call callback if descriptor still valid */ - ASSERT(pOv); - if(pOv->instance == fdTable[fd].instance) - (*pOv->procPtr)(pOv->clientData, bytes); - free(pOv); - - ftime(&tb); - ms -= (tb.time*1000 + tb.millitm - ms_last); - ms_last = tb.time*1000 + tb.millitm; - } - return 0; -} - -static int isAddrOK(struct sockaddr_in * inet_sockaddr, const char * okAddrs) -{ - static const char *token = " ,;:\t"; - char *ipaddr; - char *p; - - if (okAddrs == NULL) return TRUE; - - ipaddr = inet_ntoa(inet_sockaddr->sin_addr); - p = strstr(okAddrs, ipaddr); - - if (p == NULL) return FALSE; - - if (p == okAddrs) - { - p += strlen(ipaddr); - return (strchr(token, *p) != NULL); - } - - if (strchr(token, *--p) != NULL) - { - p += strlen(ipaddr) + 1; - return (strchr(token, *p) != NULL); - } - - return FALSE; -} - -#ifndef NO_WSAACEPT -static int CALLBACK isAddrOKCallback(LPWSABUF lpCallerId, - LPWSABUF dc0, - LPQOS dc1, - LPQOS dc2, - LPWSABUF dc3, - LPWSABUF dc4, - GROUP *dc5, - DWORD data) -{ - struct sockaddr_in *sockaddr = (struct sockaddr_in *) lpCallerId->buf; - - // Touch the args to avoid warnings - dc0 = NULL; dc1 = NULL; dc2 = NULL; dc3 = NULL; dc4 = NULL; dc5 = NULL; - - if ((void *) data == NULL) return CF_ACCEPT; - - if (sockaddr->sin_family != AF_INET) return CF_ACCEPT; - - return isAddrOK(sockaddr, (const char *) data) ? CF_ACCEPT : CF_REJECT; -} -#endif - -static printLastError(const char * text) -{ - LPVOID buf; - - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - GetLastError(), - 0, - (LPTSTR) &buf, - 0, - NULL - ); - - fprintf(stderr, "%s: %s\n", text, (LPCTSTR) buf); - LocalFree(buf); -} - -static int acceptNamedPipe() -{ - int ipcFd = -1; - - if (! ConnectNamedPipe(hListen, &listenOverlapped)) - { - switch (GetLastError()) - { - case ERROR_PIPE_CONNECTED: - - // A client connected after CreateNamedPipe but - // before ConnectNamedPipe. Its a good connection. - - break; - - case ERROR_IO_PENDING: - - // Wait for a connection to complete. - - while (WaitForSingleObject(listenOverlapped.hEvent, - ACCEPT_TIMEOUT) == WAIT_TIMEOUT) - { - if (shutdownPending) - { - OS_LibShutdown(); - return -1; - } - } - - break; - - case ERROR_PIPE_LISTENING: - - // The pipe handle is in nonblocking mode. - - case ERROR_NO_DATA: - - // The previous client closed its handle (and we failed - // to call DisconnectNamedPipe) - - default: - - printLastError("unexpected ConnectNamedPipe() error"); - } - } - - // - // impersonate the client - // - if(bImpersonate && !ImpersonateNamedPipeClient(hListen)) { - DisconnectNamedPipe(hListen); - } else { - ipcFd = Win32NewDescriptor(FD_PIPE_SYNC, (int) hListen, -1); - if (ipcFd == -1) - { - DisconnectNamedPipe(hListen); - if (bImpersonate) RevertToSelf(); - } - } - - return ipcFd; -} - -static int acceptSocket(const char *webServerAddrs) -{ - SOCKET hSock; - int ipcFd = -1; - - for (;;) - { - struct sockaddr sockaddr; - int sockaddrLen = sizeof(sockaddr); - - for (;;) - { - const struct timeval timeout = {1, 0}; - fd_set readfds; - - FD_ZERO(&readfds); - FD_SET((unsigned int) hListen, &readfds); - - if (select(0, &readfds, NULL, NULL, &timeout) == 0) - { - if (shutdownPending) - { - OS_LibShutdown(); - return -1; - } - } - else - { - break; - } - } - -#if NO_WSAACEPT - hSock = accept((SOCKET) hListen, &sockaddr, &sockaddrLen); - - if (hSock == INVALID_SOCKET) - { - break; - } - - if (isAddrOK((struct sockaddr_in *) &sockaddr, webServerAddrs)) - { - break; - } - - closesocket(hSock); -#else - hSock = WSAAccept((unsigned int) hListen, - &sockaddr, - &sockaddrLen, - isAddrOKCallback, - (DWORD) webServerAddrs); - - if (hSock != INVALID_SOCKET) - { - break; - } - - if (WSAGetLastError() != WSAECONNREFUSED) - { - break; - } -#endif - } - - if (hSock == INVALID_SOCKET) - { - /* Use FormatMessage() */ - fprintf(stderr, "accept()/WSAAccept() failed: %d", WSAGetLastError()); - return -1; - } - - ipcFd = Win32NewDescriptor(FD_SOCKET_SYNC, hSock, -1); - if (ipcFd == -1) - { - closesocket(hSock); - } - - return ipcFd; -} - -/* - *---------------------------------------------------------------------- - * - * OS_Accept -- - * - * Accepts a new FastCGI connection. This routine knows whether - * we're dealing with TCP based sockets or NT Named Pipes for IPC. - * - * fail_on_intr is ignored in the Win lib. - * - * Results: - * -1 if the operation fails, otherwise this is a valid IPC fd. - * - *---------------------------------------------------------------------- - */ -int OS_Accept(int listen_sock, int fail_on_intr, const char *webServerAddrs) -{ - int ipcFd = -1; - - // Touch args to prevent warnings - listen_sock = 0; fail_on_intr = 0; - - // @todo Muliple listen sockets and sockets other than 0 are not - // supported due to the use of globals. - - if (shutdownPending) - { - OS_LibShutdown(); - return -1; - } - - // The mutex is to keep other processes (and threads, when supported) - // from going into the accept cycle. The accept cycle needs to - // periodically break out to check the state of the shutdown flag - // and there's no point to having more than one thread do that. - - if (acceptMutex != INVALID_HANDLE_VALUE) - { - DWORD ret; - while ((ret = WaitForSingleObject(acceptMutex, ACCEPT_TIMEOUT)) == WAIT_TIMEOUT) - { - if (shutdownPending) break; - } - if (ret == WAIT_FAILED) { - printLastError("WaitForSingleObject() failed"); - return -1; - } - } - - if (shutdownPending) - { - OS_LibShutdown(); - } - else if (listenType == FD_PIPE_SYNC) - { - ipcFd = acceptNamedPipe(); - } - else if (listenType == FD_SOCKET_SYNC) - { - ipcFd = acceptSocket(webServerAddrs); - } - else - { - fprintf(stderr, "unknown listenType (%d)\n", listenType); - } - - if (acceptMutex != INVALID_HANDLE_VALUE) - { - ReleaseMutex(acceptMutex); - } - - return ipcFd; -} - -/* - *---------------------------------------------------------------------- - * - * OS_IpcClose - * - * OS IPC routine to close an IPC connection. - * - * Results: - * - * - * Side effects: - * IPC connection is closed. - * - *---------------------------------------------------------------------- - */ -int OS_IpcClose(int ipcFd) -{ - if (ipcFd == -1) - return 0; - - /* - * Catch it if fd is a bogus value - */ - ASSERT((ipcFd >= 0) && (ipcFd < WIN32_OPEN_MAX)); - ASSERT(fdTable[ipcFd].type != FD_UNUSED); - - switch(listenType) { - - case FD_PIPE_SYNC: - /* - * Make sure that the client (ie. a Web Server in this case) has - * read all data from the pipe before we disconnect. - */ - if(!FlushFileBuffers(fdTable[ipcFd].fid.fileHandle)) - return -1; - if(DisconnectNamedPipe(fdTable[ipcFd].fid.fileHandle)) { - OS_Close(ipcFd); - if (bImpersonate) RevertToSelf(); - return 0; - } else { - return -1; - } - break; - - case FD_SOCKET_SYNC: - OS_Close(ipcFd); - return 0; - break; - - case FD_UNUSED: - default: - //exit(106); - return -1; - break; - } - return -1; -} - -/* - *---------------------------------------------------------------------- - * - * OS_IsFcgi -- - * - * Determines whether this process is a FastCGI process or not. - * - * Results: - * Returns 1 if FastCGI, 0 if not. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ -int OS_IsFcgi(int sock) -{ - // Touch args to prevent warnings - sock = 0; - - /* XXX This is broken for sock */ - - return (listenType != FD_UNUSED); -} - -/* - *---------------------------------------------------------------------- - * - * OS_SetFlags -- - * - * Sets selected flag bits in an open file descriptor. Currently - * this is only to put a SOCKET into non-blocking mode. - * - *---------------------------------------------------------------------- - */ -void OS_SetFlags(int fd, int flags) -{ - unsigned long pLong = 1L; - - if (fdTable[fd].type == FD_SOCKET_SYNC && flags == O_NONBLOCK) { - if (ioctlsocket(fdTable[fd].fid.sock, FIONBIO, &pLong) == - SOCKET_ERROR) { - //exit(WSAGetLastError()); - SetLastError(WSAGetLastError()); - return; - } - if (!CreateIoCompletionPort((HANDLE)fdTable[fd].fid.sock, - hIoCompPort, fd, 1)) { - //err = GetLastError(); - //exit(err); - return; - } - - fdTable[fd].type = FD_SOCKET_ASYNC; - } - return; -} - diff --git a/sapi/cgi/libfcgi/strerror.c b/sapi/cgi/libfcgi/strerror.c deleted file mode 100644 index fac7c8eda2..0000000000 --- a/sapi/cgi/libfcgi/strerror.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * The terms in the file "LICENSE.TERMS" do not apply to this file. - * See terms below. - * - * Copyright (c) 1988 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. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -/*static char *sccsid = "from: @(#)strerror.c 5.6 (Berkeley) 5/4/91";*/ -static char *rcsid = "$Id$"; -#endif /* LIBC_SCCS and not lint */ - -#include "fcgi_config.h" - -#if ! defined (HAVE_STRERROR) -#include - -/* - * Since perror() is not allowed to change the contents of strerror()'s - * static buffer, both functions supply their own buffers to the - * internal function __strerror(). - */ - -char * -__strerror(int num, char *buf) -{ -#define UPREFIX "Unknown error: " - extern char *sys_errlist[]; - extern int sys_nerr; - register unsigned int errnum; - register char *p, *t; - char tmp[40]; - - errnum = num; /* convert to unsigned */ - if (errnum < sys_nerr) - return(sys_errlist[errnum]); - - /* Do this by hand, so we don't include stdio(3). */ - t = tmp; - do { - *t++ = "0123456789"[errnum % 10]; - } while (errnum /= 10); - - strcpy (buf, UPREFIX); - for (p = buf + sizeof(UPREFIX) -1;;) { - *p++ = *--t; - if (t <= tmp) - break; - } - - return buf; -} - - -char * -strerror(int num) -{ - static char buf[40]; /* 64-bit number + slop */ - return __strerror(num, buf); -} - -#endif