Commit 1802f92d authored by 's avatar

initial

parent 6501f1f8
#!/usr/local/bin/pcgi-wrapper
# example pcgi info file - JeffBauer@bigfoot.com
# substitute 'BogusDirectory' with appropriate path
# To invoke from browser: http://.../cgi-bin/pcgitest/getTime
PCGI_PUBLISHER=/BogusDirectory/pcgi_publisher.py
PCGI_MODULE_PATH=/BogusDirectory/pcgitime.py
PCGI_SOCKET_FILE=/tmp/pcgitest.socket
PCGI_PID_FILE=/tmp/pcgitest.pid
# pcgitime.py - example pcgi script - JeffBauer@bigfoot.com
from time import asctime, localtime, time
beginTime = "<html><pre>time started: %s" % asctime(localtime(time()))
def getTime(arg=None):
"""It's later than you think (don't remove this docstring)"""
return "%s\ncurrent time: %s" % (beginTime, asctime(localtime(time())))
### Makefile.in - Persistent CGI configuration ###
### start of system configuration section ###
prefix= @prefix@
exec_prefix= @exec_prefix@
BINDIR= $(exec_prefix)/bin
srcdir= @srcdir@
VPATH = @srcdir@
VERSION= @VERSION@
MACHDEP= @MACHDEP@
CC = @CC@
DEFS= @DEFS@ -DUNIX -DOPT_NO_STDERR -DCLOSE_FDS
LIBS= @LIBS@
creosotedir = $(srcdir)/MrCreosote
testdir = $(srcdir)/Test
utildir = $(srcdir)/Util
### end of system configuration section ###
.c.o:
$(CC) -c $(CPPFLAGS) $(DEFS) -I. -I$(srcdir) $(CFLAGS) $<
PROGS = pcgi-wrapper $(creosotedir)/pcgi-creosote $(testdir)/parseinfo
SRCS = pcgi-wrapper.c parseinfo.c $(creosotedir)/creosote.c
OBJS1 = pcgi-wrapper.o parseinfo.o
OBJS2 = $(creosotedir)/pcgi-wrapper.o parseinfo.o $(creosotedir)/creosote.o
OBJS3 = $(srcdir)/pcgi-wrapper.o $(testdir)/parseinfo.o
HDRS = pcgi.h $(creosotedir)/creosote.h
# --with-XXX options for configure
WITH=
MANIFEST=$(srcdir)/manifest
# default path permission settings
DIRMODE= 775
EXEMODE= 755
FILEMODE= 644
# Portable install script (configure doesn't always guess right)
INSTALL= ./install-sh -c
INSTALL_PROGRAM=${INSTALL} -m $(EXEMODE)
INSTALL_DATA= ${INSTALL} -m $(FILEMODE)
##################################################
all: pcgi-wrapper $(testdir)/parseinfo
pcgi-wrapper.o: pcgi-wrapper.c pcgi.h
$(CC) -c -I. -I$(srcdir) $(CFLAGS) -DPCGI_WRAPPER_MAIN -DVERSION=\"$(VERSION)\" $(DEFS) $(srcdir)/pcgi-wrapper.c
parseinfo.o: parseinfo.c pcgi.h
$(CC) -c -I. -I$(srcdir) $(CFLAGS) $(DEFS) $(srcdir)/parseinfo.c
pcgi-wrapper: pcgi-wrapper.o parseinfo.o
$(CC) $(LIBS) $(LDFLAGS) -o pcgi-wrapper $(OBJS1)
### begin CREOSOTE stuff ###
$(creosotedir)/creosote.o: $(creosotedir)/creosote.c $(creosotedir)/creosote.h
$(CC) -c -o $(creosotedir)/creosote.o -I. -I$(srcdir) -I$(creosotedir) $(CFLAGS) -DCREOSOTE $(DEFS) $(creosotedir)/creosote.c
$(creosotedir)/pcgi-wrapper.o: $(srcdir)/pcgi-wrapper.c
$(CC) -c -o $(creosotedir)/pcgi-wrapper.o -I. -I$(srcdir) -I$(creosotedir) $(CFLAGS) -DPCGI_WRAPPER_MAIN -DCREOSOTE $(DEFS) $(srcdir)/pcgi-wrapper.c
creosote: $(creosotedir)/pcgi-creosote
$(creosotedir)/pcgi-creosote: $(creosotedir)/pcgi-wrapper.o parseinfo.o $(creosotedir)/creosote.o
$(CC) $(LIBS) $(LDFLAGS) -o $(creosotedir)/pcgi-creosote $(OBJS2)
### end CREOSOTE stuff ###
### begin TEST stuff ###
$(testdir)/parseinfo.o: $(srcdir)/parseinfo.c
$(CC) -c -o $(testdir)/parseinfo.o -I. -I$(srcdir) -I$(testdir) $(CFLAGS) -DMAIN_PARSEINFO $(DEFS) $(srcdir)/parseinfo.c
$(testdir)/pcgi-wrapper.o: $(srcdir)/pcgi-wrapper.c
$(CC) -c -o $(testdir)/pcgi-wrapper.o -I. -I$(srcdir) -I$(testdir) $(CFLAGS) $(DEFS) $(srcdir)/pcgi-wrapper.c
parseinfo: $(testdir)/parseinfo
$(testdir)/parseinfo: $(testdir)/parseinfo.o $(testdir)/pcgi-wrapper.o
$(CC) $(LIBS) $(LDFLAGS) -o $(testdir)/parseinfo $(testdir)/parseinfo.o $(testdir)/pcgi-wrapper.o
### end TEST stuff ###
install: bininstall
bininstall: altbininstall
cp pcgi-wrapper $(BINDIR)
chmod a+rx $(BINDIR)/pcgi-wrapper
-if test -f $(BINDIR)/pcgi-wrapper; \
then rm -f $(BINDIR)/pcgi-wrapper; \
else true; \
fi
(cd $(BINDIR); ln pcgi-wrapper$(VERSION) pcgi-wrapper)
altbininstall: pcgi-wrapper
@for i in $(BINDIR); \
do \
if test ! -d $$i; then \
echo "Creating directory $$i"; \
mkdir $$i; \
chmod $(DIRMODE) $$i; \
else true; \
fi; \
done
$(INSTALL_PROGRAM) pcgi-wrapper $(BINDIR)/pcgi-wrapper$(VERSION)
clean:
rm -f $(PROGS) *.o *.out core $(creosotedir)/*.o $(testdir)/*.o $(utildir)/*.o Win32/*.obj
distclean: clean
rm -f Makefile autoconf.h config.status config.cache config.log *~
tarball:
cd $(srcdir); mkdir pcgi-$(VERSION)
cpio -pd < $(MANIFEST) pcgi-$(VERSION)
tar -czf $(srcdir)/pcgi-$(VERSION).tgz pcgi-$(VERSION)
rm -rf pcgi-$(VERSION)
# Build the toplevel Makefile
#Makefile: Makefile.in config.status
# CONFIG_FILES=Makefile $(SHELL) config.status
# Run the configure script, calling it with --recheck if config.status exists
#config.status: $(srcdir)/configure
# if test -f config.status; \
# then $(SHELL) config.status --recheck; \
# $(SHELL) config.status; \
# else $(SHELL) $(srcdir)/configure $(WITH); \
# fi
# Rebuild the configure script from configure.in
autoconf:
(cd $(srcdir); autoconf)
(cd $(srcdir); autoheader)
README notes for Persistent CGI - version 2.0 alpha 4
What it is?
Persistent CGI is an architecture designed by Digital Creations
http://www.digicool.com to publish web objects as long-running
processes. The pcgi component is an integral part of DC's
Principia product, but is also provided to Bobo developers
under open software terms. Please review the copyright appearing
in the source code for full details.
How to build?
Unix:
./configure
make
make install <-- only copies the binary, not the .py modules
Win32:
cd Win32
nmake /f Makefile.nt
A Win32 binary (pcgi-wrapper.exe) is included with the source
distribution.
How to use?
See the HOWTO section in notes I have published:
http://starship.skyport.net/crew/jbauer/persistcgi/
How to get help?
Subscribe to the Bobo mailing list: bobo@digicool.com
Contact me: jeffbauer@bigfoot.com
Have fun.
-Jeff
/* config.h.in. Generated automatically from configure.in by autoheader. */
/* Define to empty if the keyword does not work. */
#undef const
/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
#undef HAVE_SYS_WAIT_H
/* Define to `int' if <sys/types.h> doesn't define. */
#undef pid_t
/* Define as the return type of signal handlers (int or void). */
#undef RETSIGTYPE
/* Define if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define if you have the putenv function. */
#undef HAVE_PUTENV
/* Define if you have the socket function. */
#undef HAVE_SOCKET
/* Define if you have the strerror function. */
#undef HAVE_STRERROR
/* Define if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated automatically using autoconf version 2.12
# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
#
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
# Defaults:
ac_help=
ac_default_prefix=/usr/local
# Any additions from configure.in:
# Initialize some variables set by options.
# The variables have the same names as the options, with
# dashes changed to underlines.
build=NONE
cache_file=./config.cache
exec_prefix=NONE
host=NONE
no_create=
nonopt=NONE
no_recursion=
prefix=NONE
program_prefix=NONE
program_suffix=NONE
program_transform_name=s,x,x,
silent=
site=
srcdir=
target=NONE
verbose=
x_includes=NONE
x_libraries=NONE
bindir='${exec_prefix}/bin'
sbindir='${exec_prefix}/sbin'
libexecdir='${exec_prefix}/libexec'
datadir='${prefix}/share'
sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
libdir='${exec_prefix}/lib'
includedir='${prefix}/include'
oldincludedir='/usr/include'
infodir='${prefix}/info'
mandir='${prefix}/man'
# Initialize some other variables.
subdirs=
MFLAGS= MAKEFLAGS=
# Maximum number of lines to put in a shell here document.
ac_max_here_lines=12
ac_prev=
for ac_option
do
# If the previous option needs an argument, assign it.
if test -n "$ac_prev"; then
eval "$ac_prev=\$ac_option"
ac_prev=
continue
fi
case "$ac_option" in
-*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
*) ac_optarg= ;;
esac
# Accept the important Cygnus configure options, so we can diagnose typos.
case "$ac_option" in
-bindir | --bindir | --bindi | --bind | --bin | --bi)
ac_prev=bindir ;;
-bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
bindir="$ac_optarg" ;;
-build | --build | --buil | --bui | --bu)
ac_prev=build ;;
-build=* | --build=* | --buil=* | --bui=* | --bu=*)
build="$ac_optarg" ;;
-cache-file | --cache-file | --cache-fil | --cache-fi \
| --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
ac_prev=cache_file ;;
-cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
| --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
cache_file="$ac_optarg" ;;
-datadir | --datadir | --datadi | --datad | --data | --dat | --da)
ac_prev=datadir ;;
-datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
| --da=*)
datadir="$ac_optarg" ;;
-disable-* | --disable-*)
ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
# Reject names that are not valid shell variable names.
if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
{ echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
fi
ac_feature=`echo $ac_feature| sed 's/-/_/g'`
eval "enable_${ac_feature}=no" ;;
-enable-* | --enable-*)
ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
# Reject names that are not valid shell variable names.
if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
{ echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
fi
ac_feature=`echo $ac_feature| sed 's/-/_/g'`
case "$ac_option" in
*=*) ;;
*) ac_optarg=yes ;;
esac
eval "enable_${ac_feature}='$ac_optarg'" ;;
-exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
| --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
| --exec | --exe | --ex)
ac_prev=exec_prefix ;;
-exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
| --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
| --exec=* | --exe=* | --ex=*)
exec_prefix="$ac_optarg" ;;
-gas | --gas | --ga | --g)
# Obsolete; use --with-gas.
with_gas=yes ;;
-help | --help | --hel | --he)
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat << EOF
Usage: configure [options] [host]
Options: [defaults in brackets after descriptions]
Configuration:
--cache-file=FILE cache test results in FILE
--help print this message
--no-create do not create output files
--quiet, --silent do not print \`checking...' messages
--version print the version of autoconf that created configure
Directory and file names:
--prefix=PREFIX install architecture-independent files in PREFIX
[$ac_default_prefix]
--exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
[same as prefix]
--bindir=DIR user executables in DIR [EPREFIX/bin]
--sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
--libexecdir=DIR program executables in DIR [EPREFIX/libexec]
--datadir=DIR read-only architecture-independent data in DIR
[PREFIX/share]
--sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
--sharedstatedir=DIR modifiable architecture-independent data in DIR
[PREFIX/com]
--localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
--libdir=DIR object code libraries in DIR [EPREFIX/lib]
--includedir=DIR C header files in DIR [PREFIX/include]
--oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
--infodir=DIR info documentation in DIR [PREFIX/info]
--mandir=DIR man documentation in DIR [PREFIX/man]
--srcdir=DIR find the sources in DIR [configure dir or ..]
--program-prefix=PREFIX prepend PREFIX to installed program names
--program-suffix=SUFFIX append SUFFIX to installed program names
--program-transform-name=PROGRAM
run sed PROGRAM on installed program names
EOF
cat << EOF
Host type:
--build=BUILD configure for building on BUILD [BUILD=HOST]
--host=HOST configure for HOST [guessed]
--target=TARGET configure for TARGET [TARGET=HOST]
Features and packages:
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
--x-includes=DIR X include files are in DIR
--x-libraries=DIR X library files are in DIR
EOF
if test -n "$ac_help"; then
echo "--enable and --with options recognized:$ac_help"
fi
exit 0 ;;
-host | --host | --hos | --ho)
ac_prev=host ;;
-host=* | --host=* | --hos=* | --ho=*)
host="$ac_optarg" ;;
-includedir | --includedir | --includedi | --included | --include \
| --includ | --inclu | --incl | --inc)
ac_prev=includedir ;;
-includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
| --includ=* | --inclu=* | --incl=* | --inc=*)
includedir="$ac_optarg" ;;
-infodir | --infodir | --infodi | --infod | --info | --inf)
ac_prev=infodir ;;
-infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
infodir="$ac_optarg" ;;
-libdir | --libdir | --libdi | --libd)
ac_prev=libdir ;;
-libdir=* | --libdir=* | --libdi=* | --libd=*)
libdir="$ac_optarg" ;;
-libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
| --libexe | --libex | --libe)
ac_prev=libexecdir ;;
-libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
| --libexe=* | --libex=* | --libe=*)
libexecdir="$ac_optarg" ;;
-localstatedir | --localstatedir | --localstatedi | --localstated \
| --localstate | --localstat | --localsta | --localst \
| --locals | --local | --loca | --loc | --lo)
ac_prev=localstatedir ;;
-localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
| --localstate=* | --localstat=* | --localsta=* | --localst=* \
| --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
localstatedir="$ac_optarg" ;;
-mandir | --mandir | --mandi | --mand | --man | --ma | --m)
ac_prev=mandir ;;
-mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
mandir="$ac_optarg" ;;
-nfp | --nfp | --nf)
# Obsolete; use --without-fp.
with_fp=no ;;
-no-create | --no-create | --no-creat | --no-crea | --no-cre \
| --no-cr | --no-c)
no_create=yes ;;
-no-recursion | --no-recursion | --no-recursio | --no-recursi \
| --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
no_recursion=yes ;;
-oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
| --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
| --oldin | --oldi | --old | --ol | --o)
ac_prev=oldincludedir ;;
-oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
| --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
| --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
oldincludedir="$ac_optarg" ;;
-prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
ac_prev=prefix ;;
-prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
prefix="$ac_optarg" ;;
-program-prefix | --program-prefix | --program-prefi | --program-pref \
| --program-pre | --program-pr | --program-p)
ac_prev=program_prefix ;;
-program-prefix=* | --program-prefix=* | --program-prefi=* \
| --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
program_prefix="$ac_optarg" ;;
-program-suffix | --program-suffix | --program-suffi | --program-suff \
| --program-suf | --program-su | --program-s)
ac_prev=program_suffix ;;
-program-suffix=* | --program-suffix=* | --program-suffi=* \
| --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
program_suffix="$ac_optarg" ;;
-program-transform-name | --program-transform-name \
| --program-transform-nam | --program-transform-na \
| --program-transform-n | --program-transform- \
| --program-transform | --program-transfor \
| --program-transfo | --program-transf \
| --program-trans | --program-tran \
| --progr-tra | --program-tr | --program-t)
ac_prev=program_transform_name ;;
-program-transform-name=* | --program-transform-name=* \
| --program-transform-nam=* | --program-transform-na=* \
| --program-transform-n=* | --program-transform-=* \
| --program-transform=* | --program-transfor=* \
| --program-transfo=* | --program-transf=* \
| --program-trans=* | --program-tran=* \
| --progr-tra=* | --program-tr=* | --program-t=*)
program_transform_name="$ac_optarg" ;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil)
silent=yes ;;
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
ac_prev=sbindir ;;
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
| --sbi=* | --sb=*)
sbindir="$ac_optarg" ;;
-sharedstatedir | --sharedstatedir | --sharedstatedi \
| --sharedstated | --sharedstate | --sharedstat | --sharedsta \
| --sharedst | --shareds | --shared | --share | --shar \
| --sha | --sh)
ac_prev=sharedstatedir ;;
-sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
| --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
| --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
| --sha=* | --sh=*)
sharedstatedir="$ac_optarg" ;;
-site | --site | --sit)
ac_prev=site ;;
-site=* | --site=* | --sit=*)
site="$ac_optarg" ;;
-srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
ac_prev=srcdir ;;
-srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
srcdir="$ac_optarg" ;;
-sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
| --syscon | --sysco | --sysc | --sys | --sy)
ac_prev=sysconfdir ;;
-sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
| --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
sysconfdir="$ac_optarg" ;;
-target | --target | --targe | --targ | --tar | --ta | --t)
ac_prev=target ;;
-target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
target="$ac_optarg" ;;
-v | -verbose | --verbose | --verbos | --verbo | --verb)
verbose=yes ;;
-version | --version | --versio | --versi | --vers)
echo "configure generated by autoconf version 2.12"
exit 0 ;;
-with-* | --with-*)
ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
# Reject names that are not valid shell variable names.
if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
{ echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
fi
ac_package=`echo $ac_package| sed 's/-/_/g'`
case "$ac_option" in
*=*) ;;
*) ac_optarg=yes ;;
esac
eval "with_${ac_package}='$ac_optarg'" ;;
-without-* | --without-*)
ac_package=`echo $ac_option|sed -e 's/-*without-//'`
# Reject names that are not valid shell variable names.
if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
{ echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
fi
ac_package=`echo $ac_package| sed 's/-/_/g'`
eval "with_${ac_package}=no" ;;
--x)
# Obsolete; use --with-x.
with_x=yes ;;
-x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
| --x-incl | --x-inc | --x-in | --x-i)
ac_prev=x_includes ;;
-x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
| --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
x_includes="$ac_optarg" ;;
-x-libraries | --x-libraries | --x-librarie | --x-librari \
| --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
ac_prev=x_libraries ;;
-x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
| --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
x_libraries="$ac_optarg" ;;
-*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
;;
*)
if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
echo "configure: warning: $ac_option: invalid host type" 1>&2
fi
if test "x$nonopt" != xNONE; then
{ echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
fi
nonopt="$ac_option"
;;
esac
done
if test -n "$ac_prev"; then
{ echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
fi
trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
# File descriptor usage:
# 0 standard input
# 1 file creation
# 2 errors and warnings
# 3 some systems may open it to /dev/tty
# 4 used on the Kubota Titan
# 6 checking for... messages and results
# 5 compiler messages saved in config.log
if test "$silent" = yes; then
exec 6>/dev/null
else
exec 6>&1
fi
exec 5>./config.log
echo "\
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
" 1>&5
# Strip out --no-create and --no-recursion so they do not pile up.
# Also quote any args containing shell metacharacters.
ac_configure_args=
for ac_arg
do
case "$ac_arg" in
-no-create | --no-create | --no-creat | --no-crea | --no-cre \
| --no-cr | --no-c) ;;
-no-recursion | --no-recursion | --no-recursio | --no-recursi \
| --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
*" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
ac_configure_args="$ac_configure_args '$ac_arg'" ;;
*) ac_configure_args="$ac_configure_args $ac_arg" ;;
esac
done
# NLS nuisances.
# Only set these to C if already set. These must not be set unconditionally
# because not all systems understand e.g. LANG=C (notably SCO).
# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
# Non-C LC_CTYPE values break the ctype check.
if test "${LANG+set}" = set; then LANG=C; export LANG; fi
if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
# confdefs.h avoids OS command line length limits that DEFS can exceed.
rm -rf conftest* confdefs.h
# AIX cpp loses on an empty file, so make sure it contains at least a newline.
echo > confdefs.h
# A filename unique to this package, relative to the directory that
# configure is in, which we can look for to find out if srcdir is correct.
ac_unique_file=pcgi.h
# Find the source files, if location was not specified.
if test -z "$srcdir"; then
ac_srcdir_defaulted=yes
# Try the directory containing this script, then its parent.
ac_prog=$0
ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
srcdir=$ac_confdir
if test ! -r $srcdir/$ac_unique_file; then
srcdir=..
fi
else
ac_srcdir_defaulted=no
fi
if test ! -r $srcdir/$ac_unique_file; then
if test "$ac_srcdir_defaulted" = yes; then
{ echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
else
{ echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
fi
fi
srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
# Prefer explicitly selected file to automatically selected ones.
if test -z "$CONFIG_SITE"; then
if test "x$prefix" != xNONE; then
CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
else
CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
fi
fi
for ac_site_file in $CONFIG_SITE; do
if test -r "$ac_site_file"; then
echo "loading site script $ac_site_file"
. "$ac_site_file"
fi
done
if test -r "$cache_file"; then
echo "loading cache $cache_file"
. $cache_file
else
echo "creating cache $cache_file"
> $cache_file
fi
ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
ac_cpp='$CPP $CPPFLAGS'
ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
cross_compiling=$ac_cv_prog_cc_cross
if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
# Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
ac_n= ac_c='
' ac_t=' '
else
ac_n=-n ac_c= ac_t=
fi
else
ac_n= ac_c='\c' ac_t=
fi
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:525: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
for ac_dir in $PATH; do
test -z "$ac_dir" && ac_dir=.
if test -f $ac_dir/$ac_word; then
ac_cv_prog_CC="gcc"
break
fi
done
IFS="$ac_save_ifs"
fi
fi
CC="$ac_cv_prog_CC"
if test -n "$CC"; then
echo "$ac_t""$CC" 1>&6
else
echo "$ac_t""no" 1>&6
fi
if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:554: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
ac_prog_rejected=no
for ac_dir in $PATH; do
test -z "$ac_dir" && ac_dir=.
if test -f $ac_dir/$ac_word; then
if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
ac_prog_rejected=yes
continue
fi
ac_cv_prog_CC="cc"
break
fi
done
IFS="$ac_save_ifs"
if test $ac_prog_rejected = yes; then
# We found a bogon in the path, so make sure we never use it.
set dummy $ac_cv_prog_CC
shift
if test $# -gt 0; then
# We chose a different compiler from the bogus one.
# However, it has the same basename, so the bogon will be chosen
# first if we set CC to just the basename; use the full file name.
shift
set dummy "$ac_dir/$ac_word" "$@"
shift
ac_cv_prog_CC="$@"
fi
fi
fi
fi
CC="$ac_cv_prog_CC"
if test -n "$CC"; then
echo "$ac_t""$CC" 1>&6
else
echo "$ac_t""no" 1>&6
fi
test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
fi
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
echo "configure:602: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
ac_cpp='$CPP $CPPFLAGS'
ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
cross_compiling=$ac_cv_prog_cc_cross
cat > conftest.$ac_ext <<EOF
#line 612 "configure"
#include "confdefs.h"
main(){return(0);}
EOF
if { (eval echo configure:616: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
ac_cv_prog_cc_works=yes
# If we can't run a trivial program, we are probably using a cross compiler.
if (./conftest; exit) 2>/dev/null; then
ac_cv_prog_cc_cross=no
else
ac_cv_prog_cc_cross=yes
fi
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
ac_cv_prog_cc_works=no
fi
rm -fr conftest*
echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
if test $ac_cv_prog_cc_works = no; then
{ echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
fi
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
echo "configure:636: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
cross_compiling=$ac_cv_prog_cc_cross
echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
echo "configure:641: checking whether we are using GNU C" >&5
if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.c <<EOF
#ifdef __GNUC__
yes;
#endif
EOF
if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:650: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
ac_cv_prog_gcc=yes
else
ac_cv_prog_gcc=no
fi
fi
echo "$ac_t""$ac_cv_prog_gcc" 1>&6
if test $ac_cv_prog_gcc = yes; then
GCC=yes
ac_test_CFLAGS="${CFLAGS+set}"
ac_save_CFLAGS="$CFLAGS"
CFLAGS=
echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
echo "configure:665: checking whether ${CC-cc} accepts -g" >&5
if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
echo 'void f(){}' > conftest.c
if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
ac_cv_prog_cc_g=yes
else
ac_cv_prog_cc_g=no
fi
rm -f conftest*
fi
echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
if test "$ac_test_CFLAGS" = set; then
CFLAGS="$ac_save_CFLAGS"
elif test $ac_cv_prog_cc_g = yes; then
CFLAGS="-g -O2"
else
CFLAGS="-O2"
fi
else
GCC=
test "${CFLAGS+set}" = set || CFLAGS="-g"
fi
echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
echo "configure:693: checking how to run the C preprocessor" >&5
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
CPP=
fi
if test -z "$CPP"; then
if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
# This must be in double quotes, not single quotes, because CPP may get
# substituted into the Makefile and "${CC-cc}" will confuse make.
CPP="${CC-cc} -E"
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp.
cat > conftest.$ac_ext <<EOF
#line 708 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:714: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
:
else
echo "$ac_err" >&5
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
rm -rf conftest*
CPP="${CC-cc} -E -traditional-cpp"
cat > conftest.$ac_ext <<EOF
#line 725 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:731: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
:
else
echo "$ac_err" >&5
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
rm -rf conftest*
CPP=/lib/cpp
fi
rm -f conftest*
fi
rm -f conftest*
ac_cv_prog_CPP="$CPP"
fi
CPP="$ac_cv_prog_CPP"
else
ac_cv_prog_CPP="$CPP"
fi
echo "$ac_t""$CPP" 1>&6
# Set VERSION here so we only need to edit it in one place
VERSION=2.0a4
# Set name for machine-dependent library files
echo $ac_n "checking MACHDEP""... $ac_c" 1>&6
echo "configure:761: checking MACHDEP" >&5
if test -z "$MACHDEP"
then
ac_sys_system=`uname -s`
if test "$ac_sys_system" = "AIX" ; then
ac_sys_release=`uname -v`
else
ac_sys_release=`uname -r`
fi
ac_md_system=`echo $ac_sys_system | tr -d '/ ' | tr '[A-Z]' '[a-z]'`
ac_md_release=`echo $ac_sys_release | tr -d '/ ' | sed 's/\..*//'`
MACHDEP="$ac_md_system$ac_md_release"
case $MACHDEP in
'') MACHDEP="unknown";;
esac
fi
echo "$ac_t""$MACHDEP" 1>&6
case $ac_sys_system in
hp*|HP*)
case $CC in
cc|*/cc) CC="$CC -Aa -D_HPUX_SOURCE";;
esac;;
esac
if test "$ac_sys_system" != IRIX
then
echo $ac_n "checking for inet_addr in -lnsl""... $ac_c" 1>&6
echo "configure:792: checking for inet_addr in -lnsl" >&5
ac_lib_var=`echo nsl'_'inet_addr | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_save_LIBS="$LIBS"
LIBS="-lnsl $LIBS"
cat > conftest.$ac_ext <<EOF
#line 800 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
builtin and then its argument prototype would still apply. */
char inet_addr();
int main() {
inet_addr()
; return 0; }
EOF
if { (eval echo configure:811: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=no"
fi
rm -f conftest*
LIBS="$ac_save_LIBS"
fi
if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
echo "$ac_t""yes" 1>&6
LIBS="-lnsl $LIBS"
else
echo "$ac_t""no" 1>&6
fi
# SVR4
echo $ac_n "checking for socket in -lsocket""... $ac_c" 1>&6
echo "configure:832: checking for socket in -lsocket" >&5
ac_lib_var=`echo socket'_'socket | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_save_LIBS="$LIBS"
LIBS="-lsocket $LIBS $LIBS"
cat > conftest.$ac_ext <<EOF
#line 840 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
builtin and then its argument prototype would still apply. */
char socket();
int main() {
socket()
; return 0; }
EOF
if { (eval echo configure:851: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=no"
fi
rm -f conftest*
LIBS="$ac_save_LIBS"
fi
if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
echo "$ac_t""yes" 1>&6
LIBS="-lsocket $LIBS"
else
echo "$ac_t""no" 1>&6
fi
# SVR4 sockets
fi
echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
echo "configure:874: checking for ANSI C header files" >&5
if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 879 "configure"
#include "confdefs.h"
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <float.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:887: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
rm -rf conftest*
ac_cv_header_stdc=yes
else
echo "$ac_err" >&5
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
rm -rf conftest*
ac_cv_header_stdc=no
fi
rm -f conftest*
if test $ac_cv_header_stdc = yes; then
# SunOS 4.x string.h does not declare mem*, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
#line 904 "configure"
#include "confdefs.h"
#include <string.h>
EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
egrep "memchr" >/dev/null 2>&1; then
:
else
rm -rf conftest*
ac_cv_header_stdc=no
fi
rm -f conftest*
fi
if test $ac_cv_header_stdc = yes; then
# ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
#line 922 "configure"
#include "confdefs.h"
#include <stdlib.h>
EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
egrep "free" >/dev/null 2>&1; then
:
else
rm -rf conftest*
ac_cv_header_stdc=no
fi
rm -f conftest*
fi
if test $ac_cv_header_stdc = yes; then
# /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
if test "$cross_compiling" = yes; then
:
else
cat > conftest.$ac_ext <<EOF
#line 943 "configure"
#include "confdefs.h"
#include <ctype.h>
#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
int main () { int i; for (i = 0; i < 256; i++)
if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
exit (0); }
EOF
if { (eval echo configure:954: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
:
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
rm -fr conftest*
ac_cv_header_stdc=no
fi
rm -fr conftest*
fi
fi
fi
echo "$ac_t""$ac_cv_header_stdc" 1>&6
if test $ac_cv_header_stdc = yes; then
cat >> confdefs.h <<\EOF
#define STDC_HEADERS 1
EOF
fi
echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6
echo "configure:978: checking for sys/wait.h that is POSIX.1 compatible" >&5
if eval "test \"`echo '$''{'ac_cv_header_sys_wait_h'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 983 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/wait.h>
#ifndef WEXITSTATUS
#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
#endif
#ifndef WIFEXITED
#define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
#endif
int main() {
int s;
wait (&s);
s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
; return 0; }
EOF
if { (eval echo configure:999: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_header_sys_wait_h=yes
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
rm -rf conftest*
ac_cv_header_sys_wait_h=no
fi
rm -f conftest*
fi
echo "$ac_t""$ac_cv_header_sys_wait_h" 1>&6
if test $ac_cv_header_sys_wait_h = yes; then
cat >> confdefs.h <<\EOF
#define HAVE_SYS_WAIT_H 1
EOF
fi
for ac_hdr in unistd.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:1023: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1028 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1033: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
rm -rf conftest*
eval "ac_cv_header_$ac_safe=yes"
else
echo "$ac_err" >&5
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
rm -rf conftest*
eval "ac_cv_header_$ac_safe=no"
fi
rm -f conftest*
fi
if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
echo "$ac_t""yes" 1>&6
ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
cat >> confdefs.h <<EOF
#define $ac_tr_hdr 1
EOF
else
echo "$ac_t""no" 1>&6
fi
done
echo $ac_n "checking for working const""... $ac_c" 1>&6
echo "configure:1061: checking for working const" >&5
if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1066 "configure"
#include "confdefs.h"
int main() {
/* Ultrix mips cc rejects this. */
typedef int charset[2]; const charset x;
/* SunOS 4.1.1 cc rejects this. */
char const *const *ccp;
char **p;
/* NEC SVR4.0.2 mips cc rejects this. */
struct point {int x, y;};
static struct point const zero = {0,0};
/* AIX XL C 1.02.0.0 rejects this.
It does not let you subtract one const X* pointer from another in an arm
of an if-expression whose if-part is not a constant expression */
const char *g = "string";
ccp = &g + (g ? g-g : 0);
/* HPUX 7.0 cc rejects these. */
++ccp;
p = (char**) ccp;
ccp = (char const *const *) p;
{ /* SCO 3.2v4 cc rejects this. */
char *t;
char const *s = 0 ? (char *) 0 : (char const *) 0;
*t++ = 0;
}
{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
int x[] = {25, 17};
const int *foo = &x[0];
++foo;
}
{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
typedef const int *iptr;
iptr p = 0;
++p;
}
{ /* AIX XL C 1.02.0.0 rejects this saying
"k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
struct s { int j; const int *ap[3]; };
struct s *b; b->j = 5;
}
{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
const int foo = 10;
}
; return 0; }
EOF
if { (eval echo configure:1115: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_c_const=yes
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
rm -rf conftest*
ac_cv_c_const=no
fi
rm -f conftest*
fi
echo "$ac_t""$ac_cv_c_const" 1>&6
if test $ac_cv_c_const = no; then
cat >> confdefs.h <<\EOF
#define const
EOF
fi
echo $ac_n "checking for pid_t""... $ac_c" 1>&6
echo "configure:1136: checking for pid_t" >&5
if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1141 "configure"
#include "confdefs.h"
#include <sys/types.h>
#if STDC_HEADERS
#include <stdlib.h>
#include <stddef.h>
#endif
EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
egrep "pid_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
rm -rf conftest*
ac_cv_type_pid_t=yes
else
rm -rf conftest*
ac_cv_type_pid_t=no
fi
rm -f conftest*
fi
echo "$ac_t""$ac_cv_type_pid_t" 1>&6
if test $ac_cv_type_pid_t = no; then
cat >> confdefs.h <<\EOF
#define pid_t int
EOF
fi
echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
echo "configure:1170: checking return type of signal handlers" >&5
if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1175 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <signal.h>
#ifdef signal
#undef signal
#endif
#ifdef __cplusplus
extern "C" void (*signal (int, void (*)(int)))(int);
#else
void (*signal ()) ();
#endif
int main() {
int i;
; return 0; }
EOF
if { (eval echo configure:1192: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_type_signal=void
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
rm -rf conftest*
ac_cv_type_signal=int
fi
rm -f conftest*
fi
echo "$ac_t""$ac_cv_type_signal" 1>&6
cat >> confdefs.h <<EOF
#define RETSIGTYPE $ac_cv_type_signal
EOF
for ac_func in putenv socket strerror
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
echo "configure:1213: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1218 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
builtin and then its argument prototype would still apply. */
char $ac_func();
int main() {
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
choke me
#else
$ac_func();
#endif
; return 0; }
EOF
if { (eval echo configure:1241: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
rm -rf conftest*
eval "ac_cv_func_$ac_func=no"
fi
rm -f conftest*
fi
if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
echo "$ac_t""yes" 1>&6
ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
cat >> confdefs.h <<EOF
#define $ac_tr_func 1
EOF
else
echo "$ac_t""no" 1>&6
fi
done
trap '' 1 2 15
cat > confcache <<\EOF
# This file is a shell script that caches the results of configure
# tests run on this system so they can be shared between configure
# scripts and configure runs. It is not useful on other systems.
# If it contains results you don't want to keep, you may remove or edit it.
#
# By default, configure uses ./config.cache as the cache file,
# creating it if it does not exist already. You can give configure
# the --cache-file=FILE option to use a different cache file; that is
# what configure does when it calls configure scripts in
# subdirectories, so they share the cache.
# Giving --cache-file=/dev/null disables caching, for debugging configure.
# config.status only pays attention to the cache file if you give it the
# --recheck option to rerun configure.
#
EOF
# The following way of writing the cache mishandles newlines in values,
# but we know of no workaround that is simple, portable, and efficient.
# So, don't put newlines in cache variables' values.
# Ultrix sh set writes to stderr and can't be redirected directly,
# and sets the high bit in the cache file unless we assign to the vars.
(set) 2>&1 |
case `(ac_space=' '; set) 2>&1` in
*ac_space=\ *)
# `set' does not quote correctly, so add quotes (double-quote substitution
# turns \\\\ into \\, and sed turns \\ into \).
sed -n \
-e "s/'/'\\\\''/g" \
-e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
;;
*)
# `set' quotes correctly as required by POSIX, so do not add quotes.
sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
;;
esac >> confcache
if cmp -s $cache_file confcache; then
:
else
if test -w $cache_file; then
echo "updating cache $cache_file"
cat confcache > $cache_file
else
echo "not updating unwritable cache $cache_file"
fi
fi
rm -f confcache
trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
test "x$prefix" = xNONE && prefix=$ac_default_prefix
# Let make expand exec_prefix.
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
# Any assignment to VPATH causes Sun make to only execute
# the first set of double-colon rules, so remove it if not needed.
# If there is a colon in the path, we need to keep it.
if test "x$srcdir" = x.; then
ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
fi
trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
# Transform confdefs.h into DEFS.
# Protect against shell expansion while executing Makefile rules.
# Protect against Makefile macro expansion.
cat > conftest.defs <<\EOF
s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
s%\[%\\&%g
s%\]%\\&%g
s%\$%$$%g
EOF
DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
rm -f conftest.defs
# Without the "./", some shells look in PATH for config.status.
: ${CONFIG_STATUS=./config.status}
echo creating $CONFIG_STATUS
rm -f $CONFIG_STATUS
cat > $CONFIG_STATUS <<EOF
#! /bin/sh
# Generated automatically by configure.
# Run this file to recreate the current configuration.
# This directory was configured as follows,
# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
#
# $0 $ac_configure_args
#
# Compiler output produced by configure, useful for debugging
# configure, is in ./config.log if it exists.
ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
for ac_option
do
case "\$ac_option" in
-recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
-version | --version | --versio | --versi | --vers | --ver | --ve | --v)
echo "$CONFIG_STATUS generated by autoconf version 2.12"
exit 0 ;;
-help | --help | --hel | --he | --h)
echo "\$ac_cs_usage"; exit 0 ;;
*) echo "\$ac_cs_usage"; exit 1 ;;
esac
done
ac_given_srcdir=$srcdir
trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
EOF
cat >> $CONFIG_STATUS <<EOF
# Protect against being on the right side of a sed subst in config.status.
sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
$ac_vpsub
$extrasub
s%@CFLAGS@%$CFLAGS%g
s%@CPPFLAGS@%$CPPFLAGS%g
s%@CXXFLAGS@%$CXXFLAGS%g
s%@DEFS@%$DEFS%g
s%@LDFLAGS@%$LDFLAGS%g
s%@LIBS@%$LIBS%g
s%@exec_prefix@%$exec_prefix%g
s%@prefix@%$prefix%g
s%@program_transform_name@%$program_transform_name%g
s%@bindir@%$bindir%g
s%@sbindir@%$sbindir%g
s%@libexecdir@%$libexecdir%g
s%@datadir@%$datadir%g
s%@sysconfdir@%$sysconfdir%g
s%@sharedstatedir@%$sharedstatedir%g
s%@localstatedir@%$localstatedir%g
s%@libdir@%$libdir%g
s%@includedir@%$includedir%g
s%@oldincludedir@%$oldincludedir%g
s%@infodir@%$infodir%g
s%@mandir@%$mandir%g
s%@CC@%$CC%g
s%@CPP@%$CPP%g
s%@VERSION@%$VERSION%g
s%@MACHDEP@%$MACHDEP%g
CEOF
EOF
cat >> $CONFIG_STATUS <<\EOF
# Split the substitutions into bite-sized pieces for seds with
# small command number limits, like on Digital OSF/1 and HP-UX.
ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
ac_file=1 # Number of current file.
ac_beg=1 # First line for current file.
ac_end=$ac_max_sed_cmds # Line after last line for current file.
ac_more_lines=:
ac_sed_cmds=""
while $ac_more_lines; do
if test $ac_beg -gt 1; then
sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
else
sed "${ac_end}q" conftest.subs > conftest.s$ac_file
fi
if test ! -s conftest.s$ac_file; then
ac_more_lines=false
rm -f conftest.s$ac_file
else
if test -z "$ac_sed_cmds"; then
ac_sed_cmds="sed -f conftest.s$ac_file"
else
ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
fi
ac_file=`expr $ac_file + 1`
ac_beg=$ac_end
ac_end=`expr $ac_end + $ac_max_sed_cmds`
fi
done
if test -z "$ac_sed_cmds"; then
ac_sed_cmds=cat
fi
EOF
cat >> $CONFIG_STATUS <<EOF
CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
EOF
cat >> $CONFIG_STATUS <<\EOF
for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
# Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
case "$ac_file" in
*:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
*) ac_file_in="${ac_file}.in" ;;
esac
# Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
# Remove last slash and all that follows it. Not all systems have dirname.
ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
# The file is in a subdirectory.
test ! -d "$ac_dir" && mkdir "$ac_dir"
ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
# A "../" for each directory in $ac_dir_suffix.
ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
else
ac_dir_suffix= ac_dots=
fi
case "$ac_given_srcdir" in
.) srcdir=.
if test -z "$ac_dots"; then top_srcdir=.
else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
/*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
*) # Relative path.
srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
top_srcdir="$ac_dots$ac_given_srcdir" ;;
esac
echo creating "$ac_file"
rm -f "$ac_file"
configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
case "$ac_file" in
*Makefile*) ac_comsub="1i\\
# $configure_input" ;;
*) ac_comsub= ;;
esac
ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
sed -e "$ac_comsub
s%@configure_input@%$configure_input%g
s%@srcdir@%$srcdir%g
s%@top_srcdir@%$top_srcdir%g
" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
fi; done
rm -f conftest.s*
EOF
cat >> $CONFIG_STATUS <<EOF
EOF
cat >> $CONFIG_STATUS <<\EOF
exit 0
EOF
chmod +x $CONFIG_STATUS
rm -fr confdefs* $ac_clean_files
test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
dnl Process this file with autoconf to produce a configure script.
AC_INIT(pcgi.h)
AC_PROG_CC
AC_PROG_CPP
# Set VERSION here so we only need to edit it in one place
AC_SUBST(VERSION)
VERSION=2.0a4
# Set name for machine-dependent library files
AC_SUBST(MACHDEP)
AC_MSG_CHECKING(MACHDEP)
if test -z "$MACHDEP"
then
ac_sys_system=`uname -s`
if test "$ac_sys_system" = "AIX" ; then
ac_sys_release=`uname -v`
else
ac_sys_release=`uname -r`
fi
ac_md_system=`echo $ac_sys_system | tr -d '[/ ]' | tr '[[A-Z]]' '[[a-z]]'`
ac_md_release=`echo $ac_sys_release | tr -d '[/ ]' | sed 's/\..*//'`
MACHDEP="$ac_md_system$ac_md_release"
case $MACHDEP in
'') MACHDEP="unknown";;
esac
fi
AC_MSG_RESULT($MACHDEP)
dnl Checks for programs.
dnl Checks for libraries.
case $ac_sys_system in
hp*|HP*)
case $CC in
cc|*/cc) CC="$CC -Aa -D_HPUX_SOURCE";;
esac;;
esac
if test "$ac_sys_system" != IRIX
then
AC_CHECK_LIB(nsl, inet_addr, [LIBS="-lnsl $LIBS"]) # SVR4
AC_CHECK_LIB(socket, socket, [LIBS="-lsocket $LIBS"], [], $LIBS) # SVR4 sockets
fi
dnl Checks for header files.
AC_HEADER_STDC
AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS(unistd.h)
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_TYPE_PID_T
dnl Checks for library functions.
AC_TYPE_SIGNAL
AC_CHECK_FUNCS(putenv socket strerror)
AC_OUTPUT(Makefile)
#!/bin/sh
#
# install - install a program, script, or datafile
# This comes from X11R5; it is not part of GNU.
#
# $XConsortium: install.sh,v 1.2 89/12/18 14:47:22 jim Exp $
#
# This script is compatible with the BSD install script, but was written
# from scratch.
#
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
# put in absolute paths if you don't have them in your path; or use env. vars.
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
chmodprog="${CHMODPROG-chmod}"
chownprog="${CHOWNPROG-chown}"
chgrpprog="${CHGRPPROG-chgrp}"
stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
instcmd="$mvprog"
chmodcmd=""
chowncmd=""
chgrpcmd=""
stripcmd=""
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=""
dst=""
while [ x"$1" != x ]; do
case $1 in
-c) instcmd="$cpprog"
shift
continue;;
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
-s) stripcmd="$stripprog"
shift
continue;;
*) if [ x"$src" = x ]
then
src=$1
else
dst=$1
fi
shift
continue;;
esac
done
if [ x"$src" = x ]
then
echo "install: no input file specified"
exit 1
fi
if [ x"$dst" = x ]
then
echo "install: no destination specified"
exit 1
fi
# If destination is a directory, append the input filename; if your system
# does not like double slashes in filenames, you may need to add some logic
if [ -d $dst ]
then
dst="$dst"/`basename $src`
fi
# Make a temp file name in the proper directory.
dstdir=`dirname $dst`
dsttmp=$dstdir/#inst.$$#
# Move or copy the file name to the temp name
$doit $instcmd $src $dsttmp
# and set any options; do chmod last to preserve setuid bits
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; fi
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; fi
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; fi
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; fi
# Now rename the file to the real destination.
$doit $rmcmd $dst
$doit $mvcmd $dsttmp $dst
exit 0
Example/pcgitest
Example/pcgitime.py
Makefile.in
MrCreosote/README.MrCreosote
MrCreosote/creosote.c
MrCreosote/creosote.h
MrCreosote/creosote.py
README
Test/README.parseinfo
Util/README
Util/killpcgi.py
Util/pcgifile.py
Win32/Makefile.nt
Win32/README.NT
Win32/parseinfo.exe
Win32/pcgi-wrapper.exe
config.h.in
configure
configure.in
install-sh
manifest
parseinfo.c
pcgi_publisher.py
pcgi-wrapper.c
pcgi.h
/* parseinfo.c - module to parse the pcgi info file
Copyright (c) 1998, Digital Creations, Fredericksburg, VA, USA. All
rights reserved. This software includes contributions from Jeff Bauer.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
o Redistributions of source code must retain the above copyright
notice, this list of conditions, and the disclaimer that follows.
o 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.
o All advertising materials mentioning features or use of this
software must display the following acknowledgement:
This product includes software developed by Digital Creations
and its contributors.
o Neither the name of Digital Creations nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS *AS IS* AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "pcgi.h"
extern char **environ;
extern int CloseFileDescriptors;
int pcgiAssignCloseFileDescriptors(pcgiResource *r, char *val)
{
if ((CloseFileDescriptors = pcgiTruthValue(val[0]) < 0))
{
sprintf(r->errmsg, "unknown value for PCGI_CLOSE_FDS: %s", val);
return(-1);
}
return(0);
}
int pcgiAssignPublisher(pcgiResource *r)
{
/*
// Determine the publisher path based on the current values
// of the pcgiResource structure.
*/
char *p, *pBegin, *pEnd, testdir[MAXSZ];
char combinedPaths[MAXPATH+MAXPATH+2];
if (r->pubpath[0]) /* assignment already made, our work is done :) */
{
return(0);
}
/*
// Look through the PCGI_INSERT_PATH directories for the publisher.
*/
strcat(combinedPaths, r->insertPath);
strcat(combinedPaths, ":");
strcat(combinedPaths, r->pythonPath);
pBegin = combinedPaths;
pEnd = pBegin + strlen(combinedPaths);
while(pBegin < pEnd)
{
p = pBegin;
do {
if (*p == ':' || *p == '\0')
break;
} while(*p++);
strncpy(testdir, pBegin, p-pBegin);
testdir[p-pBegin] = '\0';
if ((pcgiAssignPublisherPath(testdir, r))==0)
{
return(0);
}
if (p == pBegin)
{
pBegin++;
}
else
{
pBegin = p;
}
}
/*
// Run through a gauntlet of misc. attempts to find the publisher.
*/
if (r->modpath[0])
{
if ((pcgiAssignPublisherPath(r->modpath, r)) == 0)
return(0);
}
if (r->sw_info[0])
{
if ((pcgiAssignPublisherPath(r->sw_info, r)) == 0)
return(0);
}
if (r->sw_home[0])
{
if ((pcgiAssignPublisherPath(r->sw_home, r)) == 0)
return(0);
}
if (r->sw_exe[0])
{
if ((pcgiAssignPublisherPath(r->sw_exe, r)) == 0)
return(0);
}
return(-1);
}
#define PubCount 4 /* variations on a publisher name */
int pcgiAssignPublisherPath(char *path, pcgiResource *r)
{
/*
// Attempt to assign the path to the publisher, return 0 for success,
// otherwise -1.
*/
char *p[PubCount];
char testdir[MAXSZ], pubpath[MAXSZ];
int i, len;
struct stat statbuf;
p[0] = PUBLISHER_NAME_1;
p[1] = PUBLISHER_NAME_2;
p[2] = PUBLISHER_NAME_3;
p[3] = PUBLISHER_NAME_4;
strcpy(testdir, path);
len = strlen(testdir);
if (len < 1 || (MAXSZ <= len + strlen(PUBLISHER_NAME_1) + 1))
{
return(-1);
}
if (PATHSEP == testdir[len-1])
{
testdir[len-1] = '\0'; /* truncate trailing slash */
}
if (stat(testdir, &statbuf) == -1)
{
return(-1); /* unable to stat path */
}
if (!(statbuf.st_mode & S_IFDIR))
{
/*
// If the supplied path was not a directory, assume it was
// a file and get the directory portion of it.
*/
while(len > 0)
{
if (PATHSEP == testdir[--len])
{
testdir[len] = '\0';
break;
}
}
if (len < 1) { return(-1); }
}
for (i=0; i < PubCount; i++)
{
sprintf(pubpath, "%s%c%s", testdir, PATHSEP, p[i]);
if (stat(pubpath, &statbuf) != -1)
{
if (statbuf.st_mode & S_IREAD)
{
strcpy(r->pubpath, pubpath);
return(0);
}
}
}
return(-1);
}
int pcgiEnvironmentToResourceAssignment(pcgiResource *r)
{
/*
// Read in the environment and make whatever appropriate assignments
// prior to reading in the pcgi info file. Values from the pcgi info
// override environment settings.
//
// This function is necessary because the user may want to set
// an enviroment variable globally (e.g. PCGI_PUBLISHER from
// a httpd .conf file),
*/
char **env;
char *p = NULL;
char buf[MAXSZ];
char *nam, *val;
for (env=environ; *env != 0; env++)
{
if (strlen(*env) >= MAXSZ)
{
continue;
}
strcpy(buf, *env);
if ((p = strchr(buf,'=')) != NULL)
{
*p++ = '\0';
nam = buf;
val = p;
if((strncmp(nam, "SOFTWARE_", strlen("SOFTWARE_")))==0)
{
if((strcmp(nam,"SOFTWARE_NAME"))==0)
strcpy(r->sw_name, val);
else if((strcmp(nam,"SOFTWARE_HOME"))==0)
strcpy(r->sw_home, val);
else if((strcmp(nam,"SOFTWARE_EXE"))==0)
strcpy(r->sw_exe, val);
}
if((strcmp(nam,"PYTHONPATH"))==0)
{
/* TODO: check strlen against MAXPATH */
strcpy(r->pythonPath, val);
}
else if((strncmp(nam, "PCGI_", strlen("PCGI_")))==0)
{
if ((strcmp(nam,"PCGI_CLOSE_FDS"))==0)
{
if ((pcgiAssignCloseFileDescriptors(r, val)) < 0)
return(-1);
}
else if ((strcmp(nam,"PCGI_DISPLAY_ERRORS"))==0)
r->displayErrors = pcgiTruthValue(val[0]);
else if ((strcmp(nam,"PCGI_ERROR_LOG"))==0)
strcpy(r->errlog, val);
else if ((strcmp(nam,"PCGI_EXE"))==0)
strcpy(r->sw_exe, val);
else if ((strcmp(nam,"PCGI_HOST"))==0)
strcpy(r->sockhost, val);
else if ((strcmp(nam,"PCGI_INSERT_PATH"))==0 ||
(strcmp(nam,"PCGI_WORKING_DIR")))
{
if (strlen(val) >= MAXPATH)
{
strcpy(r->errmsg, "pcgiEnvironmentToResourceAssignment() length exceeds MAXPATH");
return(-1);
}
strcpy(r->insertPath, val);
}
else if ((strcmp(nam,"PCGI_MODULE_PATH"))==0)
strcpy(r->modpath, val);
else if ((strcmp(nam,"PCGI_NAME"))==0)
strcpy(r->sw_name, val);
else if ((strcmp(nam,"PCGI_PID_FILE"))==0)
strcpy(r->procpath, val);
else if ((strcmp(nam,"PCGI_PORT"))==0)
r->sockport = atoi(val);
else if ((strcmp(nam,"PCGI_PUBLISHER"))==0)
strcpy(r->pubpath, val);
else if ((strcmp(nam,"PCGI_SOCKET_FILE"))==0)
strcpy(r->sockpath, val);
}
}
}
return(0);
}
/*
// pcgiParseInfo: Parse info file named in resource->sw_info
*/
int pcgiParseInfo(pcgiResource *r)
{
FILE *f;
char buf[256];
char *v=NULL;
char *p=NULL;
struct stat statbuf;
int _newStyleDirectives = 0;
int _oldStyleLineCount = 0;
enum { oldStyleSocketFile, oldStyleProcessIdFile, oldStyleWorkDir, oldStyleModPath };
if ((pcgiEnvironmentToResourceAssignment(r)) < 0)
{
if (!r->errmsg[0])
strcpy(r->errmsg, "pcgiEnvironmentToResourceAssignment() error");
return(-1);
}
if((f=fopen(r->sw_info, "r")) == NULL)
{
sprintf(r->errmsg, "unable to open info file: %s", r->sw_info);
return(-1);
}
pcgiPutNameValueInEnvironment("PCGI_INFO_FILE", r->sw_info);
while(fgets(buf, 255, f) != NULL)
{
/* XXX - TODO: trim leading, trailing whitespace */
#ifdef WIN32
amendPathSeparators(buf);
#endif
if((buf[0] != '#') && (buf[0] != '\n'))
{
p=(strrchr(buf,'\0')-sizeof(char));
while((p >= buf) && (isspace(*p)))
{
*p=0;
p--;
}
if ((p=strchr(buf,'=')) != NULL)
{
_newStyleDirectives = 1;
if ((pcgiPutEnvironment(buf) < 0))
{
strcpy(r->errmsg, "pcgiPutEnvironment() failed");
fclose(f);
return(-1);
}
*p=0;
p++;
if((strcmp(buf,"SOFTWARE_NAME"))==0)
{
strcpy(r->sw_name, p);
}
else if((strcmp(buf,"SOFTWARE_HOME"))==0)
{
strcpy(r->sw_home, p);
}
else if((strcmp(buf,"SOFTWARE_EXE"))==0)
{
strcpy(r->sw_exe, p);
}
else if((strcmp(buf,"PCGI_CLOSE_FDS"))==0)
{
if ((pcgiAssignCloseFileDescriptors(r, p)) < 0)
return(-1);
}
else if ((strcmp(buf,"PCGI_DISPLAY_ERRORS"))==0)
r->displayErrors = pcgiTruthValue(p[0]);
else if((strcmp(buf,"PCGI_ERROR_LOG"))==0)
{
strcpy(r->errlog, p);
}
else if((strcmp(buf,"PCGI_EXE"))==0)
{
strcpy(r->sw_exe, p);
}
else if((strcmp(buf,"PCGI_HOST"))==0)
{
strcpy(r->sockhost, p);
}
else if((strcmp(buf,"PCGI_INSERT_PATH"))==0)
{
strcpy(r->insertPath, p);
}
else if((strcmp(buf,"PCGI_MODULE_PATH"))==0)
{
strcpy(r->modpath, p);
}
else if((strcmp(buf,"PCGI_NAME"))==0)
{
strcpy(r->sw_name, p);
}
else if((strcmp(buf,"PCGI_PID_FILE"))==0)
{
strcpy(r->procpath, p);
}
else if((strcmp(buf,"PCGI_PORT"))==0)
{
r->sockport = atoi(p);
}
else if((strcmp(buf,"PCGI_PUBLISHER"))==0)
{
strcpy(r->pubpath, p);
}
else if((strcmp(buf,"PCGI_SOCKET_FILE"))==0)
{
strcpy(r->sockpath, p);
}
else if((strcmp(buf,"PCGI_WORKING_DIR"))==0)
{
strcpy(r->insertPath, p);
}
else if((strcmp(buf,"PYTHONPATH"))==0)
{
strcpy(r->pythonPath, p);
}
}
else /* old-style (deprecated) directives */
{
/* assume old style where the first four lines correspond to */
/* 1. path of the socket file */
/* 2. path of the process id file */
/* 3. working directory (to be added to path by publisher) */
/* 4. path of the module to be published */
if (_newStyleDirectives)
{
strcpy(r->errmsg, "pcgi info file mixes old and new style directives (new style uses name=value)");
fclose(f);
return(-1);
}
if (oldStyleSocketFile == _oldStyleLineCount)
{
strcpy(r->sockpath, buf);
pcgiPutNameValueInEnvironment("PCGI_SOCKET_FILE", buf);
}
else if (oldStyleProcessIdFile == _oldStyleLineCount)
{
strcpy(r->procpath, buf);
pcgiPutNameValueInEnvironment("PCGI_PID_FILE", buf);
}
else if (oldStyleWorkDir == _oldStyleLineCount)
{
strcpy(r->insertPath, buf);
if ((pcgiPutNameValueInEnvironment("PCGI_INSERT_PATH", buf)) < 0)
{
strcpy(r->errmsg, "pcgiPutNameValueInEnvironment() error");
fclose(f);
return(-1);
}
}
else if (oldStyleModPath == _oldStyleLineCount)
{
strcpy(r->modpath, buf);
if ((pcgiPutNameValueInEnvironment("PCGI_MODULE_PATH", buf)) < 0)
{
strcpy(r->errmsg, "pcgiPutNameValueInEnvironment() error");
fclose(f);
return(-1);
}
}
else
{
strcpy(r->errmsg, "oldStyleLineCount exceeds maximum");
fclose(f);
return(-1);
}
_oldStyleLineCount++;
}
}
}
fclose(f);
/*
// Post-parsing work: decide if we have enough info to make it work.
*/
/*
// If the location of the publisher was not specified, try to
// locate it.
*/
if (!r->pubpath[0])
{
pcgiAssignPublisher(r);
}
if (!r->pubpath[0])
{
strcpy(r->errmsg, "unable to determine the publisher location");
return(-1);
}
else
{
if (stat(r->pubpath, &statbuf) == -1)
{
sprintf(r->errmsg, "missing publisher: %s", r->pubpath);
return(-1);
}
else
{
if (!(statbuf.st_mode & S_IREAD))
{
sprintf(r->errmsg, "publisher read error: %s", r->pubpath);
return(-1);
}
}
}
/*
// Assign defaults, where necessary, for backward compatibility.
*/
if (r->sw_name[0] && r->sw_home[0])
{
if (!r->sw_exe[0])
{
strcpy(r->sw_exe,"/usr/local/bin/python1.4");
pcgiPutNameValueInEnvironment("SOFTWARE_EXE", r->sw_exe);
}
if (!r->procpath[0])
{
sprintf(r->procpath,"%s/var/%s.pid", r->sw_home,r->sw_name);
pcgiPutNameValueInEnvironment("PCGI_PID_FILE", r->procpath);
}
if (!r->sockpath[0])
{
sprintf(r->sockpath,"%s/var/%s.soc", r->sw_home,r->sw_name);
pcgiPutNameValueInEnvironment("PCGI_SOCKET_FILE", r->sockpath);
}
}
/*
// Other than r->pubpath, the other required attributes to complete
// the process are: r->procpath & r->sockpath.
*/
if (!r->sockpath[0])
{
strcpy(r->errmsg, "missing parameter: PCGI_SOCKET_FILE");
return(-1);
}
if (!r->procpath[0])
{
strcpy(r->errmsg, "missing parameter: PCGI_PID_FILE");
return(-1);
}
/* Add this at a later date: jhb - 8/10/98 */
/*
if (r->sockport && !r->sockhost[0])
{
strcpy(r->errmsg, "unable to determine hostname, recommend specifying: PCGI_HOST");
return(-1);
}
*/
return(0);
}
int pcgiPutEnvironment(char *buf)
{
/*
// Stick a copy of the name=value pair in the
// process environment. Note that this would
// leak and need to be changed for any pcgi
// implementations that work as web server api
// extensions...
*/
char *v = NULL;
if((v=malloc(strlen(buf) + sizeof(char))) == NULL)
{
return(-1);
}
strcpy(v, buf);
if(putenv(v))
{
return(-1);
}
return(0);
}
int pcgiPutNameValueInEnvironment(char *name, char *value)
{
/*
// Slight modification to pcgiPutEnvironment(), convenience function.
*/
char *v = NULL;
if ((v=malloc(strlen(name) + strlen(value) + (2 * sizeof(char)))) == NULL)
return(-1);
sprintf(v, "%s=%s", name, value);
if(putenv(v))
return(-1);
return(0);
}
int pcgiTruthValue(char v)
{
if (v=='1' || v=='t' || v=='T' || v=='y' || v=='Y')
return 1;
else if (v=='0' || v=='f' || v=='F' || v=='n' || v=='N')
return 0;
else
return -1;
}
#ifdef WIN32
/*
This function lets both Unix & Win32 info files
to use the same '/' character as a path separator.
However it does this by assuming that we always
want '\' backslashes as path separators in a
Win32 environment.
*/
void amendPathSeparators(char *src)
{
char ch, *ptr;
ptr = src;
while ((ch = *src++))
{
if (ch == PATHSEP_UNIX) { *ptr = PATHSEP_WIN32; }
*ptr++;
}
}
#endif
#ifdef MAIN_PARSEINFO
int main(int argc, char *argv[])
{
/* char **env; */
pcgiResource resource;
pcgiResource *r = &resource;
if (argc < 2)
{
printf("usage: parseinfo <pcgi-info-file>\n");
return(-1);
}
#ifdef CLOSE_FDS
CloseFileDescriptors = 1;
#endif
/* initialize pcgiResource */
memset(r,0,sizeof(pcgiResource));
r->conn=-1;
strcpy(r->sw_info, argv[1]);
if ((pcgiParseInfo(r)) < 0)
{
printf("error parsing info file: %s\n", r->sw_info);
printf(" %s\n", r->errmsg);
return(-1);
}
printf("pcgi resource attributes:\n");
printf(" %-20s %s\n", "r->sw_info", r->sw_info);
printf(" %-20s %s\n", "r->sw_name", r->sw_name);
printf(" %-20s %s\n", "r->sw_home", r->sw_home);
printf(" %-20s %s\n", "r->sw_exe", r->sw_exe);
printf(" %-20s %s\n", "r->procpath", r->procpath);
printf(" %-20s %s\n", "r->sockpath", r->sockpath);
printf(" %-20s %s\n", "r->modpath", r->modpath);
printf(" %-20s %s\n", "r->pubpath", r->pubpath);
printf(" %-20s %d\n", "r->procid", r->procid);
printf(" %-20s %s\n", "r->insertPath", r->insertPath);
printf(" %-20s %s\n", "r->pythonPath", r->pythonPath);
printf(" %-20s %d\n", "r->sockport", r->sockport);
printf(" %-20s %s\n", "r->sockhost", r->sockhost);
printf(" %-20s %d\n", "r->displayErrors", r->displayErrors);
printf(" %-20s %d\n", "CloseFileDescriptors", CloseFileDescriptors);
/* printf("\nenvironment:\n"); */
/* for (env=environ; *env != 0; env++) */
/* printf(" %s\n", *env); */
}
#endif
/* pcgi-wrapper.c - Persistent CGI wrapper module
Copyright (c) 1998, Digital Creations, Fredericksburg, VA, USA. All
rights reserved. This software includes contributions from Jeff Bauer.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
o Redistributions of source code must retain the above copyright
notice, this list of conditions, and the disclaimer that follows.
o 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.
o All advertising materials mentioning features or use of this
software must display the following acknowledgement:
This product includes software developed by Digital Creations
and its contributors.
o Neither the name of Digital Creations 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.
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
- 2.0a4 10 August 1998
-fixed Win32 local socket host address issues
- 2.0a4 8 August 1998
-added Win32 support
*/
#include "pcgi.h"
#ifdef CREOSOTE
#include "creosote.h" /* used for debugging */
char spewbuf[1024]; /* yes, it's a global, but only for debugging */
#endif
static char _id_[]="$Id: pcgi-wrapper.c,v 1.1 1998/10/19 20:04:37 brian Exp $";
/* Globals, OR: "I'll know I'll hate myself in the morning" */
extern char **environ;
int CloseFileDescriptors = 0;
#if UNIX
int g_lock = 0;
#endif
#if PCGI_WRAPPER_MAIN
int main(int argc, char *argv[])
{ pcgiResource resource;
pcgiResource *r=&resource;
long l =0;
char t[10] ={0};
char *estatus=NULL;
char *emsg =NULL;
char *p =NULL;
char **env;
#ifdef CREOSOTE
initializeMrCreosote();
/* spew("pcgi-wrapper main()"); */
#endif
#ifdef CLOSE_FDS
CloseFileDescriptors = 1;
#endif
/*
// Initialize resource info
*/
memset(r,0,sizeof(pcgiResource));
r->conn=-1;
if (argc < 2)
{
onError(E_500, "No pcgi info file given!", r);
}
strcpy(r->sw_info, argv[1]);
if ((pcgiParseInfo(r)) < 0)
{
onError(E_500, "Error parsing pcgi info file", r);
}
/*
// Copy environment to resource
*/
for(env=environ; *env != 0; env++)
{
r->sz_env+=(strlen(*env)+sizeof(char));
}
if((r->p_env=malloc(((sizeof(char) * r->sz_env)+(sizeof(char)*HDRLEN))))==NULL)
{
onError(E_500, "Error allocating env", r);
}
p=r->p_env;
sprintf(p, HDRFMT, r->sz_env);
if (p[0] != '0')
{
if (!r->errmsg[0])
strcpy(r->errmsg, ERR123_BAD_ENV_HEADER);
onError(E_500, "Error allocating env", r);
}
p+=HDRLEN;
for(env=environ; *env != 0; env++)
{ l=strlen(*env);
memcpy(p, *env, l);
p+=l;
*p=0;
p++;
}
/*
// Copy stdin to resource
*/
p=getenv("CONTENT_LENGTH");
if((p != NULL) && ((r->sz_input=atol(p)) > 0))
{
if((r->p_input=malloc(((sizeof(char) * r->sz_input)+
(sizeof(char)*HDRLEN))))==NULL)
{
onError(E_500, "Error allocating stdin", r);
}
p=r->p_input;
sprintf(p, HDRFMT, r->sz_input);
if (p[0] != '0')
{
if (!r->errmsg[0])
strcpy(r->errmsg, ERR124_BAD_STDIN_HEADER);
onError(E_500, "Error allocating stdin", r);
}
p+=HDRLEN;
if(pcgiRead(STDIN_FILENO, p, r->sz_input) != r->sz_input)
{
onError(E_500, "Error reading stdin", r);
}
}
else
{
if((r->p_input=malloc(sizeof(char)*HDRLEN))==NULL)
{
onError(E_500, "Error allocating stdin", r);
}
sprintf(r->p_input, HDRFMT, 0);
}
/*
// Attempt to connect
*/
if ((r->conn = pcgiConnect(r)) < 0)
{
if(pcgiVerifyProc(r) < 0)
{
if(pcgiStartProc(r) < 0)
{
if (!r->errmsg[0])
strcpy(r->errmsg, ERR101_FAILURE_DURING_START);
onError(E_500, "Failed to start resource", r);
}
if ((r->conn=pcgiConnect(r)) < 0)
{
if (!r->errmsg[0])
strcpy(r->errmsg, ERR102_FAILURE_DURING_CONNECT);
onError(E_503, strerror(errno), r);
}
}
else
{
if (!r->errmsg[0])
strcpy(r->errmsg, ERR103_UNABLE_VERIFY_RUNNING);
onError(E_503, "pcgiVerifyProc failed", r);
}
}
/*
// Send environment and stdin
*/
#ifdef WIN32
if (pcgiWriteSocket(r->conn,r->p_env,(r->sz_env+HDRLEN)) != (r->sz_env+HDRLEN))
#endif
#ifdef UNIX
if (pcgiWrite(r->conn,r->p_env,(r->sz_env+HDRLEN)) != (r->sz_env+HDRLEN))
#endif
{
if (!r->errmsg[0])
strcpy(r->errmsg, ERR104_ENVIRONMENT_SEND);
onError(E_500, "Error sending env", r);
}
#ifdef WIN32
if (pcgiWriteSocket(r->conn,r->p_input,(r->sz_input+HDRLEN)) != (r->sz_input+HDRLEN))
#endif
#ifdef UNIX
if (pcgiWrite(r->conn,r->p_input,(r->sz_input+HDRLEN)) != (r->sz_input+HDRLEN))
#endif
{
if (!r->errmsg[0])
strcpy(r->errmsg, ERR105_STDIN_SEND);
onError(E_500, "Error sending stdin", r);
}
#ifdef WIN32
shutdown(r->conn, 1); /* shutdown the socket so we can receive */
#endif
/*
// Receive stdout and stderr
*/
t[0]='\0';
#ifdef WIN32
if (!pcgiReadSocket(r->conn, t, HDRLEN))
#endif
#ifdef UNIX
if (!pcgiRead(r->conn, t, HDRLEN))
#endif
{
if (!r->errmsg[0])
strcpy(r->errmsg, ERR106_STDOUT_READ_HEADER);
onError(E_503, strerror(errno), r);
}
if (strlen(t) <= 0)
{
if (!r->errmsg[0])
sprintf(r->errmsg, "%s (%d)", ERR107_BAD_STDOUT_STRLEN, strlen(t));
onError(E_503, strerror(errno), r);
}
if (t[0] != '0')
{
/* XXX - Later: process this as out-of-bound stdin data */
sprintf(r->errmsg, "t[0] = %d", (int) t[0]);
onError(E_500, "unexpected out-of-bound data in stdin", r);
}
else
{
r->sz_output=atol(t);
l=(sizeof(char) * r->sz_output) + sizeof(char);
r->p_output=(char *)malloc(l);
memset(r->p_output,0,l);
#ifdef WIN32
if (pcgiReadSocket(r->conn,r->p_output,r->sz_output) != r->sz_output)
#endif
#ifdef UNIX
if (pcgiRead(r->conn,r->p_output,r->sz_output) != r->sz_output)
#endif
{
if (!r->errmsg[0])
strcpy(r->errmsg, ERR108_STDOUT_READ_BODY);
onError(E_500, "Error receiving stdout", r);
}
}
t[0]='\0';
#ifdef WIN32
if (!pcgiReadSocket(r->conn, t, HDRLEN))
#endif
#ifdef UNIX
if (!pcgiRead(r->conn, t, HDRLEN))
#endif
{
if (!r->errmsg[0])
strcpy(r->errmsg, ERR109_STDERR_READ_HEADER);
onError(E_500, "Error receiving stderr size", r);
}
if (strlen(t) <= 0)
{
if (!r->errmsg[0])
sprintf(r->errmsg, "%s (%d)", ERR110_BAD_STDERR_STRLEN, strlen(t));
onError(E_500, "Error receiving stderr size", r);
}
if (t[0] != '0')
{
/* XXX - Later: process this as out-of-bound stderr data */
sprintf(r->errmsg, "t[0] = %d", (int) t[0]);
onError(E_500, "unexpected out-of-bound data in stderr", r);
}
else
{
r->sz_error=atol(t);
if (r->sz_error > 0)
{
l=(sizeof(char) * r->sz_error) + sizeof(char);
r->p_error=(char *)malloc(l);
memset(r->p_error,0,l);
#ifdef WIN32
if (pcgiReadSocket(r->conn, r->p_error, r->sz_error) != r->sz_error)
#endif
#ifdef UNIX
if (pcgiRead(r->conn, r->p_error, r->sz_error) != r->sz_error)
#endif
{
if (!r->errmsg[0])
strcpy(r->errmsg, ERR111_STDERR_READ_BODY);
onError(E_500, "Error receiving stderr", r);
}
}
}
#ifdef UNIX
close(r->conn);
#endif
#ifdef WIN32
closesocket(r->conn);
#endif
/*
// Return stdout and stderr to server
*/
if (r->sz_output != 0)
{
if (pcgiWrite(STDOUT_FILENO,r->p_output,r->sz_output) != r->sz_output)
{
if (!r->errmsg[0])
strcpy(r->errmsg, "(112) Error returning stdout to server");
onError(E_500, ERR112_STDOUT_TO_SERVER, r);
}
free(r->p_output);
r->p_output=NULL;
}
if (r->sz_error != 0)
{
if (pcgiWrite(STDERR_FILENO,r->p_error,r->sz_error) != r->sz_error)
{
if (!r->errmsg[0])
strcpy(r->errmsg, ERR113_STDOUT_TO_SERVER);
onError(E_500, "Error returning stderr", r);
}
free(r->p_error);
r->p_error=NULL;
}
/*
// Free env & input buffers, release lock if needed
*/
free(r->p_env);
r->p_env=NULL;
free(r->p_input);
r->p_input=NULL;
cleanup();
fflush(stdout);
fflush(stderr);
/*exit(0);*/
return 0;
}
#endif /* end of main(): PCGI_WRAPPER_MAIN */
/*
// onError: fatal pcgi error
*/
void onError(char *estatus, char *emsg, pcgiResource *r)
{
FILE *f;
time_t now;
#ifdef VERSION
/* If VERSION isn't defined as a string, everything will blow up here
during compilation. */
char *pcgi_version="pcgi-wrapper-version " VERSION;
#else
char *pcgi_version = "";
#endif
char *displayError = "";
if (r != NULL)
{
#ifdef UNIX
if(r->conn != -1) close(r->conn);
cleanup();
#endif
#ifdef WIN32
if (r->conn)
{
shutdown(r->conn, 1);
closesocket(r->conn);
WSACleanup();
}
#endif
if (r->errlog[0])
{
if((f=fopen(r->errlog, "ab")) != NULL)
{
now = time(NULL);
fprintf(f, "%s pcgi-wrapper: %s %s\n",
ctime(&now), emsg, r->errmsg);
fclose(f);
}
}
if(r->p_env!=NULL) free(r->p_env);
if(r->p_input!=NULL) free(r->p_input);
}
if (r->displayErrors)
displayError = r->errmsg;
printf(errorHtml, estatus, displayError, emsg, pcgi_version);
fflush(stdout);
fflush(stderr);
exit(0);
}
/*
// pcgiWrite: write n bytes to a an fd
*/
long pcgiWrite(pcgi_socket fd, const char *ptr, long nbytes)
{
long done = 0;
long notdone = nbytes;
const char *cptr = (const char *)ptr;
while (notdone > 0)
{
done = write(fd, cptr, notdone);
if (done <= 0)
{
return (done);
}
notdone -= done;
cptr += done;
}
return ((nbytes - notdone));
}
#ifdef WIN32
long pcgiWriteSocket(pcgi_socket fd, const char *ptr, long nbytes)
{
/* The successful completion of a send does not indicate */
/* that the data was successfully delivered. */
int count;
int req;
long bytesSent = 0;
/* begin superKludge(tm) - only for testing, do not leave in place XXX */
/* if (STDOUT_FILENO == (int)fd) */
/* { */
/* printf("%s", ptr); */
/* return 0; */
/* } */
/* end superKludge(tm) - only for testing, do not leave in place XXX */
while ( bytesSent < nbytes )
{
req = nbytes - bytesSent;
count = send(fd, ptr + bytesSent, req, 0);
if (SOCKET_ERROR == count)
{
return(-1);
}
bytesSent += (long) count;
}
return(bytesSent);
}
#endif
/*
// pcgiRead: read n bytes from an fd
*/
long pcgiRead(pcgi_socket fd, char *ptr, long n)
{
long done = 0;
long notdone = n;
char *cptr = ptr;
while (notdone > 0)
{
done = read(fd, cptr, notdone);
if (done < 0)
return (done); /* ERROR */
else if (done == 0)
break; /* EOF */
notdone -= done;
cptr += done;
}
return ((n - notdone));
}
#ifdef WIN32
long pcgiReadSocket(pcgi_socket fd, char *ptr, long nbytes)
{
int count;
int req;
long bytesRecv = 0;
while ( bytesRecv < nbytes )
{
req = nbytes - bytesRecv;
count = recv(fd, ptr + bytesRecv, req, 0);
if (SOCKET_ERROR == count)
{
/* TODO: add error reporting by calling WSAGetLastError */
return(-1);
}
bytesRecv += (long) count;
}
return(bytesRecv);
}
#endif
/*
// pcgiVerifyProc: check to see if a resource is running
*/
int pcgiVerifyProc(pcgiResource *r)
{ FILE *f;
char p[10];
memset(p,0,10);
if (r->procid == 0)
{ if((f=fopen(r->procpath, "r")) == NULL)
return(-1);
if(fgets(p, HDRLEN, f) == NULL)
return(-1);
fclose(f);
if(!(strlen(p) > 0))
return(-1);
r->procid=atoi(p);
}
#ifdef UNIX
return(kill(r->procid, 13));
#endif
#ifdef WIN32
if ((NULL == OpenProcess(PROCESS_VM_READ, FALSE, r->procid)))
{
return(-1);
}
return(0);
#endif
}
/*
// pcgiConnect: return fd of a connected socket
*/
#ifdef UNIX
pcgi_socket pcgiConnect(pcgiResource *r)
{
struct sockaddr_un s;
pcgi_socket fd;
int addrlen=0;
int connected=-1;
int attempted=0;
int retry=10;
int delay=1;
memset((char *) &s, 0, sizeof(s));
s.sun_family=AF_UNIX;
strcpy(s.sun_path, r->sockpath);
addrlen = sizeof(struct sockaddr_un); /* force to use sizeof(s) */
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
{
if (!r->errmsg[0])
strcpy(r->errmsg, ERR114_UNABLE_TO_OPEN_SOCKET);
return (-1);
}
while ((connected < 0) && (attempted <= retry))
{
if ((connected=connect(fd, (struct sockaddr *) &s, addrlen)) < 0)
{
if((errno!=ECONNREFUSED) && (errno!=ENOENT))
{
if (!r->errmsg[0])
strcpy(r->errmsg, ERR115_CONNECTION_REFUSED);
return(-1);
}
sleep(delay);
attempted++;
}
}
if (!(connected < 0))
{
if (!r->errmsg[0])
sprintf(r->errmsg, "%s, fd=%d", ERR116_UNABLE_TO_CONNECT, fd);
return (fd);
}
return (connected);
}
#endif /* UNIX pcgiConnect */
#ifdef WIN32
pcgi_socket pcgiConnect(pcgiResource *r)
{
pcgi_socket destSocket;
SOCKADDR_IN destSockAddr;
unsigned long destAddr;
int connected = SOCKET_ERROR;
int attempted = 0;
int status;
WSADATA WsaData;
char hostName[MAXSZ];
LPHOSTENT hostEnt;
SOCKADDR_IN hostAddr;
/* initialize the Windows Socket DLL */
/* TODO: move this startup code outside of pcgiConnect */
if (0 != WSAStartup(MAKEWORD(2, 0), &WsaData))
{
return(-1);
}
/* destAddr = inet_addr("192.168.2.43"); */
hostAddr.sin_addr.s_addr = INADDR_ANY; /* init local address */
/* Bug: assumes r->sockhost is the host name, we should also
check to see if it is the xxx.xxx.xxx.xxx octet string and
act accordingly */
if (r->sockhost[0])
strcpy(hostName, r->sockhost);
else if (SOCKET_ERROR == gethostname(hostName, MAXSZ))
return(-1);
hostEnt = gethostbyname((LPSTR) hostName);
if (hostEnt)
{
/* resolve hostname for local address */
hostAddr.sin_addr.s_addr = *((u_long FAR*) (hostEnt->h_addr));
}
if (INADDR_ANY == hostAddr.sin_addr.s_addr)
{
return(-1);
}
destAddr = hostAddr.sin_addr.s_addr;
memcpy(&destSockAddr.sin_addr, &destAddr, sizeof(destAddr));
destSockAddr.sin_port = htons((short)r->sockport);
destSockAddr.sin_family = AF_INET;
/* create socket */
destSocket = socket(AF_INET, SOCK_STREAM, 0);
if (INVALID_SOCKET == destSocket)
{
return(-1);
}
/* Connect */
/* The code below blithely duplicates the Unix version. */
/* TODO: add better recovery/error handling. */
while ((SOCKET_ERROR == connected) && (attempted <= CONNRETRY))
{
connected = connect(destSocket, (LPSOCKADDR) &destSockAddr, sizeof(destSockAddr));
if (SOCKET_ERROR == connected)
{
status = WSAGetLastError();
if ((status != WSAECONNREFUSED) && (status != ENOENT))
{
return(-1);
}
sleep(CONNDELAY);
attempted++;
}
}
if (SOCKET_ERROR == connected)
{
closesocket(destSocket);
WSACleanup();
return(-1);
}
return(destSocket);
}
#endif /* Win32 pcgiConnect */
#ifdef UNIX
static sig_atomic_t sigflag;
static sigset_t nmask, omask, zmask;
#endif
#ifdef UNIX
void pcgiSIG(int s)
{
sigflag=1;
return;
}
#endif
void cleanup()
{
#ifdef UNIX
if (g_lock > 0)
{
semctl(g_lock, 1, IPC_RMID, (union semun)sem_idx);
}
#endif
}
/*
// pcgiStartProc: manages starting a pcgi resource.
*/
#ifdef UNIX
int pcgiStartProc(pcgiResource *r)
{
pid_t pid;
char *p = NULL;
int i = 0;
if ((p=strrchr(r->sw_exe, PATHSEP))==NULL)
{
p = r->sw_exe;
}
else
{
p++;
}
/* Set up signal handlers to coordinate timing */
signal(SIGUSR1, pcgiSIG);
signal(SIGUSR2, pcgiSIG);
sigemptyset(&zmask);
sigemptyset(&nmask);
sigaddset(&nmask, SIGUSR1);
sigaddset(&nmask, SIGUSR2);
sigprocmask(SIG_BLOCK, &nmask, &omask);
/* Make sure another wrapper isn't already doing a restart */
if ((r->lock=semget(101, 1, 0700 | IPC_CREAT | IPC_EXCL)) == -1)
{
if (errno == EACCES)
strcpy(r->errmsg, ERR117_LOCK_ERROR_EACCES);
else if (errno == EEXIST)
strcpy(r->errmsg, ERR118_LOCK_ERROR_EEXIST);
else if (errno == EINVAL)
strcpy(r->errmsg, ERR119_LOCK_ERROR_EINVAL);
else if (errno == ENOENT)
strcpy(r->errmsg, ERR120_LOCK_ERROR_ENOENT);
else if (errno == ENOSPC)
strcpy(r->errmsg, ERR121_LOCK_ERROR_ENOSPC);
else
sprintf(r->errmsg, "%s, %d", ERR122_LOCK_ERROR_OTHER, errno);
return(-1);
}
/* Keep us from dying without cleaning up our semaphore by
setting signal handlers to ensure that the sem will always
be released. We don't set handlers for SIGUSR1 SIGUSR2 or
SIGCHLD, because we need those to coordinate with the child
process(es) that we fork. */
g_lock = r->lock;
for(i=0; i<32; i++)
{
if ((i!=SIGUSR1) && (i!=SIGUSR2) && (i != SIGCHLD))
{
signal(i, (void *)cleanup);
}
}
/* If the old socket file exists and we have write permission,
attempt to remove it. */
if (r->sockport == 0 && access(r->sockpath, W_OK) == 0)
{
unlink(r->sockpath);
}
/* Fork a child which forks a child -- this is so that
init will inherit the grandchild (so it won't die) */
if ((pid = fork()) < 0)
{
semctl(r->lock, 1, IPC_RMID, (union semun)0);
return(-1);
}
else if (pid == 0)
{
if ((pid = fork()) < 0)
{
return(-1);
}
else if (pid > 0)
{ /* Let child know we're going away so it can start */
kill(pid, SIGUSR1);
exit(0);
}
setsid();
chdir("/");
/* Wait for parent to go away */
while(sigflag == 0)
sigsuspend(&zmask);
sigflag = 0;
sigprocmask(SIG_SETMASK, &omask, NULL);
/* Platform oddities... */
if (CloseFileDescriptors)
{
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
}
execl(r->sw_exe,
p,
r->pubpath,
(char *)0);
exit(0);
}
/* Wait for the first child to finish */
if (waitpid(pid, NULL, 0) < 0)
{ semctl(r->lock, 1, IPC_RMID, (union semun)0);
return(-1);
}
/*
// Release restart lock!
*/
semctl(r->lock, 1, IPC_RMID, (union semun)0);
/*
// Reset signal handlers
*/
for(i=0; i<10; i++)
{
signal(i, SIG_DFL);
}
sleep(2);
return (0);
}
#endif /* UNIX pcgiStartProc */
#ifdef WIN32
int pcgiStartProc(pcgiResource *r)
{
HANDLE mutex = 0;
char pythonExecutable[256];
char command_line[1024];
BOOL createProcessStatus;
STARTUPINFO StartupInfo;
PROCESS_INFORMATION ProcessInfo;
int waitStatus;
GetStartupInfo(&StartupInfo);
/* Is another wrapper attempting a restart? */
mutex = CreateMutex(NULL, FALSE, MUTEX_NAME);
if (NULL == mutex)
{
//TODO: add error reporting
return(-1);
}
waitStatus = WaitForSingleObject(mutex, (AUTODELAY * 1000));
if (WAIT_TIMEOUT == waitStatus)
{
//TODO: add error reporting
return(-1);
}
else if (WAIT_FAILED == waitStatus)
{
//TODO: add error handling by calling GetLastError()
return(-1);
}
/*
Travel beyond this point requires calling the
ReleaseMutex function. Fortunately, the Win32
mutex is automatically released when a process
terminates, but we could still encounter a
situation where the process is hung or stalled ...
*/
if (r->sw_exe[0])
strcpy(pythonExecutable, r->sw_exe);
else
strcpy(pythonExecutable, "python");
sprintf(command_line, "%s %s", pythonExecutable, r->pubpath);
createProcessStatus = CreateProcess(
NULL,
command_line,
NULL,
NULL,
FALSE,
DETACHED_PROCESS,
NULL,
NULL,
&StartupInfo,
&ProcessInfo);
/* wait a little bit to give the published
application enough time to initialize itself */
//Yech!!!
sleep(AUTODELAY); // <<<-- use a ReadySignal(tm), if available :)
ReleaseMutex(mutex);
CloseHandle(mutex);
if (0 == createProcessStatus)
{
//TODO: report more information about failure
return(-1);
}
else
{
r->procid = ProcessInfo.dwProcessId; /* assign process id */
return(0);
}
}
#endif
/* pcgi.h - Persistent CGI header file for pcgi-wrapper.c, parseinfo.c
Copyright (c) 1998, Digital Creations, Fredericksburg, VA, USA. All
rights reserved. This software includes contributions from Jeff Bauer.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
o Redistributions of source code must retain the above copyright
notice, this list of conditions, and the disclaimer that follows.
o 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.
o All advertising materials mentioning features or use of this
software must display the following acknowledgement:
This product includes software developed by Digital Creations
and its contributors.
o Neither the name of Digital Creations 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.
*/
#ifndef PCGI_H
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef UNIX
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
#ifdef WIN32
#include <windows.h>
#include <io.h>
#include <iostream.h>
#include <winsock.h>
#endif
#define MAXLINEBUFFER 12
#define PATHSEP_UNIX '/'
#define PATHSEP_WIN32 '\\'
#define DEFAULT_SOCK_PORT 7244
/*#define DEFAULT_SOCK_HOST "127.0.0.1"*/
#define MAXPATH 1024
#define PUBLISHER_NAME_1 "pcgi_publisher.py"
#define PUBLISHER_NAME_2 "pcgi_publisher.pyc"
#define PUBLISHER_NAME_3 "pcgi_publisher.pyo"
#define PUBLISHER_NAME_4 "pcgi_publisher"
#define HDRLEN 10
#define HDRFMT "%010ld"
#ifdef UNIX
#define PATHSEP PATHSEP_UNIX
typedef int pcgi_socket;
#endif
#ifdef WIN32
#define PATHSEP PATHSEP_WIN32
typedef SOCKET pcgi_socket;
#define sleep(x) Sleep(x * 1000)
#define read(x,y,z) _read(x,y,z)
#define write(x,y,z) _write(x,y,z)
#define MUTEX_NAME "pcgiMutex"
#define AUTODELAY 5
#define CONNRETRY 0
#define CONNDELAY 1
#endif
#ifndef CREOSOTE
/* no-op in case someone forgets to remove a spew() in their debug code */
#define spew(x)
#endif
#ifndef STDIN_FILENO
#define STDIN_FILENO 0
#endif
#ifndef STDOUT_FILENO
#define STDOUT_FILENO 1
#endif
#ifndef STDERR_FILENO
#define STDERR_FILENO 2
#endif
#define MAXSZ 256
#define RKEY 99
#define E_500 "500 Server Error"
#define E_503 "503 Service Unavailable"
#define ERR101_FAILURE_DURING_START "(101) failure during start"
#define ERR102_FAILURE_DURING_CONNECT "(102) failure during connect"
#define ERR103_UNABLE_VERIFY_RUNNING "(103) unable to verify if process is running"
#define ERR104_ENVIRONMENT_SEND "(104) environment send"
#define ERR105_STDIN_SEND "(105) stdin send"
#define ERR106_STDOUT_READ_HEADER "(106) stdout read header"
#define ERR107_BAD_STDOUT_STRLEN "(107) bad stdout strlen"
#define ERR108_STDOUT_READ_BODY "(108) stdout read body"
#define ERR109_STDERR_READ_HEADER "(109 stderr read header"
#define ERR110_BAD_STDERR_STRLEN "(110) bad stderr strlen"
#define ERR111_STDERR_READ_BODY "(111) stderr read body"
#define ERR112_STDOUT_TO_SERVER "(112) error returning stdout to server"
#define ERR113_STDOUT_TO_SERVER "(113) error returning stderr to server"
#define ERR114_UNABLE_TO_OPEN_SOCKET "(114) unable to open socket"
#define ERR115_CONNECTION_REFUSED "(115) connection refused"
#define ERR116_UNABLE_TO_CONNECT "(116) unable to connect"
#define ERR117_LOCK_ERROR_EACCES "(117) lock error: EACCES"
#define ERR118_LOCK_ERROR_EEXIST "(118) lock error: EEXIST"
#define ERR119_LOCK_ERROR_EINVAL "(119) lock error: EINVAL"
#define ERR120_LOCK_ERROR_ENOENT "(120) lock error: ENOENT"
#define ERR121_LOCK_ERROR_ENOSPC "(121) lock error: ENOSPC"
#define ERR122_LOCK_ERROR_OTHER "(122) lock error"
#define ERR123_BAD_ENV_HEADER "(123) bad environment header"
#define ERR124_BAD_STDIN_HEADER "(124) bad stdin header"
/* #define onError(s,x) {estatus=s; emsg=x; goto error;} */
typedef struct resource_tag
{
char sw_info [MAXSZ]; /* path to pcgi info file */
char sw_name [MAXSZ]; /* module name */
char sw_home [MAXSZ]; /* home path */
char sw_exe [MAXSZ]; /* path to executable, e.g. /usr/local/bin/python */
char procpath [MAXSZ]; /* path to file containing pid */
char sockpath [MAXSZ]; /* binding path for UNIX, Win32 named pipes */
char pubpath [MAXSZ]; /* path to pcgi_publisher.py(c) */
int sockport; /* port number, if INET socket */
char sockhost [MAXSZ]; /* hostname, if INET socket */
char modpath [MAXSZ]; /* module path */
char errmsg [MAXSZ]; /* last error, brief message */
char errlog [MAXSZ]; /* fully qualified path to error log file */
char insertPath [MAXPATH]; /* insert path by publisher */
char pythonPath [MAXPATH]; /* PYTHONPATH, if provided */
short displayErrors; /* displayErrors = 0,1 */
long sz_env;
long sz_input;
long sz_output;
long sz_error;
char *p_env;
char *p_input;
char *p_output;
char *p_error;
int procid;
int conn;
int lock;
} pcgiResource;
static char errorHtml[]=
"Status: %s\n"
"Content-Type: text/html\n"
"Pragma: nocache\n"
"Expires: Thu, 01 Dec 1994 16:00:00 GMT\n\n"
"<HTML>\n"
"<HEAD>\n"
"<TITLE>Temporarily Unavailable</TITLE>\n"
"</HEAD>\n"
"<BODY BGCOLOR=\"#FFFFFF\">\n"
"<TABLE BORDER=\"0\" WIDTH=\"100%%\">\n"
"<TR>\n"
" <TD WIDTH=\"10%%\">\n"
" <CENTER>\n"
" <B><FONT SIZE=\"+6\" COLOR=\"#77003B\">!</FONT></B>\n"
" </CENTER>\n"
" </TD>\n"
" <TD WIDTH=\"90%%\"><BR>\n"
" <FONT SIZE=\"+2\">Temporarily Unavailable</FONT>\n"
" <P>\n"
" The resource you requested is temporarily unavailable - "
"please try again later.\n"
" </TD>\n"
"</TR>\n"
"</TABLE>\n"
"%s\n"
"<!--\n%s\n%s\n-->\n"
"</BODY></HTML>";
/* To ensure backward compatibility with pcgi info files, */
/* don't change the order of the first 4 enum elements. */
enum { resource_sockpath=0,
resource_procpath=1,
resource_workdir=2,
resource_modpath=3, /* remaining elements not order dependent */
resource_sockport,
resource_sockhost,
resource_exepath,
resource_exefile,
resource_pubpath,
resource_ENUM };
/* Declarations */
void cleanup(void);
void onError(char *, char *, pcgiResource *);
int pcgiAssignPublisherPath(char *, pcgiResource *);
int pcgiPutEnvironment(char *);
long pcgiRead(pcgi_socket, char *, long);
long pcgiWrite(pcgi_socket, const char *, long);
int pcgiVerifyProc(pcgiResource *);
pcgi_socket pcgiConnect(pcgiResource *);
int pcgiStartProc(pcgiResource *);
int pcgiParseInfo(pcgiResource *);
int pcgiPutNameValueInEnvironment(char *, char *);
void pcgiSIG(int);
void pcgiPrintEnvironment();
void pcgiPrintResourceInfo(pcgiResource *);
int pcgiTruthValue(char);
#ifdef WIN32
void amendPathSeparators(char *);
long pcgiReadSocket(pcgi_socket, char *, long);
long pcgiWriteSocket(pcgi_socket, const char *, long);
#endif
#define PCGI_H 1
#endif
# PCGIPublisher.py
# Persistent CGI Publisher - jeffbauer@bigfoot.com
#
# Copyright (c) 1998, Digital Creations, Fredericksburg, VA, USA. All
# rights reserved. This software includes contributions from Jeff Bauer.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# o Redistributions of source code must retain the above copyright
# notice, this list of conditions, and the disclaimer that follows.
#
# o 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.
#
# o All advertising materials mentioning features or use of this
# software must display the following acknowledgement:
#
# This product includes software developed by Digital Creations
# and its contributors.
#
# o Neither the name of Digital Creations 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.
#
# 2.0 alpha4:
# - adds NT support, using INET sockets
# - added Mike Fletcher's Microsoft IIS hack, suggested by Amos Latteier
#
# 2.0 alpha3:
# - adds error checking
# - expands header to 10 bytes (extra byte defines an out-of-band msg)
#
# 2.0 alpha1:
# - add support for new PCGI_ directives
# - re-write module as a class, rather than a set of functions
__version__ = "2.0a4"
class PCGIPublisher:
def __init__(self, resource=None):
### resources passed from the environment, info file or pcgi-wrapper
self.errorLogFile = None
self.hostname = None
self.port = 0
self.insertPath = None
self.moduleName = None
self.modulePath = None
self.socketFile = None
self.pidFile = None
self.swhome = None
self.sock = None
### bound imports ###
self.StringIO = None
self.publish_module = None
### other ###
self.bufsize = 8192
self.error = 0
if resource is None:
self.getResources()
else:
self.resource = resource
self.initPCGI()
def cleanup(self):
if self.socketFile:
import os
if os.path.exists(self.socketFile):
try:
os.unlink(self.socketFile)
except os.error:
pass
def getResources(self):
"""
Obtain the publisher resources from the environment. Done here
in a separate method to make it easy to override, because we may
not always and forever obtain our resources from the environment.
"""
import os
self.resource = os.environ
def fatalError(self, errmsg=''):
if self.errorLogFile:
import sys, traceback, StringIO
try:
from time import asctime, localtime, time
timeStamp = asctime(localtime(time()))
except ImportError:
timeStamp = '???'
try:
f = open(self.errorLogFile, 'a+')
f.write("%s %s\n" % (timeStamp, errmsg))
if sys.exc_type != 'SystemExit':
trace=StringIO.StringIO()
traceback.print_exception(sys.exc_type,
sys.exc_value,
sys.exc_traceback,
None,
trace)
f.write(" %s\n" % trace.getvalue())
f.close()
except IOError:
pass
self.cleanup()
self.error = 1
def initPCGI(self):
import os
self.initPrincipia()
if self.resource.has_key('PCGI_ERROR_LOG'):
self.errorLogFile = self.resource['PCGI_ERROR_LOG']
if self.resource.has_key('PCGI_HOST'):
self.hostname = self.resource['PCGI_HOST']
if self.resource.has_key('PCGI_INSERT_PATH'):
self.insertPath = self.resource['PCGI_INSERT_PATH']
if self.resource.has_key('PCGI_MODULE_PATH'):
self.modulePath = self.resource['PCGI_MODULE_PATH']
if self.resource.has_key('PCGI_NAME'):
self.moduleName = self.resource['PCGI_NAME']
if self.resource.has_key('PCGI_PID_FILE'):
self.pidFile = self.resource['PCGI_PID_FILE']
if self.resource.has_key('PCGI_PORT'):
import string
try: self.port = string.atoi(self.resource['PCGI_PORT'])
except ValueError: pass
if self.resource.has_key('PCGI_SOCKET_FILE'):
self.socketFile = self.resource['PCGI_SOCKET_FILE']
self.insertSysPath()
if not self.moduleName:
return self.fatalError("missing module name, try specifying PCGI_NAME")
### TODO: probably should make an attempt to import self.moduleName
### to provide the user with earliest possible response.
try:
from cStringIO import StringIO
except:
from StringIO import StringIO
self.StringIO = StringIO
try:
from cgi_module_publisher import publish_module
except ImportError:
return self.fatalError("unable to import publish_module from cgi_module_publisher")
self.publish_module = publish_module
if not self.pidFile:
return self.fatalError("missing pid file")
### create pid file ###
try:
f = open(self.pidFile, 'wb')
f.write(str(os.getpid()))
f.close()
except IOError:
return self.fatalError("unable to write to pid file: %s" % self.pidFile)
import socket
if not self.socketFile:
return self.fatalError("missing socket file")
if self.port:
if os.sep == '/':
return self.fatalError("INET sockets not yet available on Unix")
if self.hostname is None:
self.hostname = socket.gethostname()
try:
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.bind(self.hostname, self.port)
except socket.error:
return self.fatalError("error binding to socket: %s" % self.socketFile)
try:
sf = open(self.socketFile, 'wb')
sf.write("%s\n%s\n" % (self.hostname, self.port))
sf.close()
except IOError:
return self.fatalError("error attempting to write socket file: %s" % self.socketFile)
else:
try: os.unlink(self.socketFile)
except os.error: pass
try:
self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
self.sock.bind(self.socketFile)
except socket.error:
return self.fatalError("error binding to socket: %s" % self.socketFile)
try: os.chmod(self.socketFile, 0777)
except os.error: pass
def initPrincipia(self):
if self.resource.has_key('SOFTWARE_NAME'):
self.moduleName = self.resource['SOFTWARE_NAME']
if self.resource.has_key('SOFTWARE_HOME'):
import sys
builtin=sys.modules['__builtin__']
self.swhome=self.resource['SOFTWARE_HOME']
while self.swhome[-1:]=='/' or self.swhome[-1:]=='\\':
self.swhome=self.swhome[:-1]
builtin.SOFTWARE_HOME=self.swhome
builtin.CUSTOMER_HOME=self.swhome
builtin.SOFTWARE_URL=''
def insertSysPath(self, insertPath=None):
import os, sys, string
if insertPath is None:
insertPath = self.insertPath
if insertPath:
sys.path[0:0]=string.split(insertPath,':')
elif self.swhome:
sys.path[0:0]=['%s/lib/python' % self.swhome,
'%s/lib/python/Components' % self.swhome,
'%s/lib/python/Components/%s' % (self.swhome, sys.platform),
'%s/lib/python/python' % self.swhome,
'%s/lib/python/python/%s' % (self.swhome, sys.platform),
]
elif self.resource.has_key('PCGI_WORKING_DIR'):
### Note: PCGI_WORKING_DIR is a deprecated pcgi directive ###
workDir = self.resource['PCGI_WORKING_DIR']
while workDir[-1:]=='/' or workDir[-1:]=='\\':
workDir=workDir[:-1]
sys.path[0:0]=[workDir]
else:
pass
# The present assumption is that if the module path isn't in
# sys.path, we want it put there, even if the PCGI_INSERT_PATH
# directive has been specified.
if self.modulePath:
d, s = os.path.split(self.modulePath)
if not d in sys.path:
sys.path[0:0] = [d]
# If the moduleName is not known at this time, we make a
# reasonable guess based on the path. It might behoove the
# user to explicitly specify PCGI_NAME, however.
if not self.moduleName:
import string
self.moduleName = string.splitfields(s,'.')[0]
def handler(self, conn):
from string import split, join, atoi
hdr = conn.recv(10)
size = atoi(hdr)
buff = []
while size > 0:
data = conn.recv(size)
size = size - len(data)
buff.append(data)
### XXX - Later: add out-of-band data handling ###
if (hdr[0] != '0'):
return
env = {}
for i in filter(None, split(join(buff,''),'\000')):
e = split(i,'=')
if len(e) > 2:
env[e[0]] = join(e[1:],'=')
else:
env[e[0]] = e[1]
size = atoi(conn.recv(10))
if size > 1048576:
### write large upload data to a file ###
from tempfile import TemporaryFile
stdin = TemporaryFile('wb')
bufsize = self.bufsize
while size > 0:
if size < bufsize:
bufsize=size
data = conn.recv(bufsize)
size = size - len(data)
stdin.write(data)
stdin.seek(0,0)
else:
### use StringIO for smaller data ###
buff = []
while size > 0:
data = conn.recv(size)
size = size-len(data)
buff.append(data)
stdin = self.StringIO(join(buff,''))
stdout = self.StringIO()
stderr = self.StringIO()
### IIS hack to fix broken PATH_INFO
### taken from Mike Fletcher's win_cgi_module_publisher
import string
if env.has_key('SERVER_SOFTWARE') and string.find(env['SERVER_SOFTWARE'],'Microsoft-IIS') != -1:
script = filter(None,string.split(string.strip(env['SCRIPT_NAME']),'/'))
path = filter(None,string.split(string.strip(env['PATH_INFO']),'/'))
env['PATH_INFO'] = string.join(path[len(script):],'/')
try:
self.publish_module(self.moduleName,stdin=stdin,stdout=stdout,stderr=stderr,environ=env)
except:
self.fatalError("unable to publish module")
stdin.close()
stdout=stdout.getvalue()
stderr=stderr.getvalue()
conn.send('%010d' % len(stdout))
if len(stdout) > 0:
conn.send(stdout)
conn.send('%010d' % len(stderr))
if len(stderr) > 0:
conn.send(stderr)
conn.close()
def listen(self):
"""
Note to sub-classes: Aside from the constructor, listen() should
be the only method you *must* invoke.
"""
if self.error:
return self.fatalError("attempt to listen after fatal error")
import os, sys
if not self.sock:
return self.fatalError("no socket available")
self.sock.listen(512)
try: sys.stderr.close()
except: pass
while not self.error:
conn, accept = self.sock.accept()
try:
self.handler(conn)
except socket.error:
pass
def main():
try:
import os, sys, string, traceback
pcgiPublisher = PCGIPublisher(os.environ)
if not pcgiPublisher.error:
pcgiPublisher.listen()
except ImportError:
print "Content-type: text/html"
print
print "PCGIPublisher catastrophic import error"
if __name__ == '__main__':
try:
main()
finally:
import os
if os.environ.has_key('PCGI_SOCKET_FILE'):
try: os.unlink(os.environ['PCGI_SOCKET_FILE'])
except os.error: pass
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment