[Zope-CVS] CVS: Packages/pcgi - .cvsignore:1.1 Makefile.in:1.1 README.txt:1.1 config.h.in:1.1 configure:1.1 configure.in:1.1 install-sh:1.1 manifest:1.1 parseinfo.c:1.1 pcgi-wrapper.c:1.1 pcgi.h:1.1 pcgi_publisher.py:1.1

Fred L. Drake, Jr. fred@zope.com
Thu, 20 Mar 2003 15:39:56 -0500


Update of /cvs-repository/Packages/pcgi
In directory cvs.zope.org:/tmp/cvs-serv8256

Added Files:
	.cvsignore Makefile.in README.txt config.h.in configure 
	configure.in install-sh manifest parseinfo.c pcgi-wrapper.c 
	pcgi.h pcgi_publisher.py 
Log Message:
Make the PCGI support code available via CVS without having to maintain and
distribute it as part of the Zope application server.  The appserver still
contains the necessary support to allow a PCGI-capable web server to talk
to it.


=== Added File Packages/pcgi/.cvsignore ===
config.log
config.cache
config.status
Makefile
pcgi-wrapper
*.pyc


=== Added File Packages/pcgi/Makefile.in ===
### 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@

CFLAGS= @CFLAGS@
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)



=== Added File Packages/pcgi/README.txt ===
README notes for Persistent CGI - version 2.0 alpha 4

What it is?

  Persistent CGI is an architecture designed by Zope Corporation
  http://www.zope.com to publish web objects as long-running
  processes.  The pcgi component is an integral part of ZC's
  Zope product, but is also provided to web 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 Zope mailing list:  zope@zope.org
  Contact me:  jeffbauer@bigfoot.com


Have fun.

-Jeff



=== Added File Packages/pcgi/config.h.in ===
/* 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


=== Added File Packages/pcgi/configure === (1444/1544 lines abridged)
#! /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=

[-=- -=- -=- 1444 lines omitted -=- -=- -=-]

    # 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



=== Added File Packages/pcgi/configure.in ===
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.0a5

# 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_MSG_CHECKING(for union semun)
AC_TRY_LINK([#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>],
[union semun semun;],
AC_DEFINE(HAVE_UNION_SEMUN) AC_MSG_RESULT(yes),AC_MSG_RESULT(no))

AC_OUTPUT(Makefile)


=== Added File Packages/pcgi/install-sh ===
#!/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


=== Added File Packages/pcgi/manifest ===
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


=== Added File Packages/pcgi/parseinfo.c === (562/662 lines abridged)
/* 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))
    {

[-=- -=- -=- 562 lines omitted -=- -=- -=-]

#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


=== Added File Packages/pcgi/pcgi-wrapper.c === (840/940 lines abridged)
/* 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.0a5  29 October 1998
    - (brian) fixed arg type mismatch for semctl

  - 2.0a4  10 August 1998
    - (jeff) fixed Win32 local socket host address issues

  - 2.0a4  8 August 1998
    - (jeff) added Win32 support
*/

[-=- -=- -=- 840 lines omitted -=- -=- -=-]

    }

    /*
    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


=== Added File Packages/pcgi/pcgi.h ===
/* 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>
#include <fcntl.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

#ifdef HAVE_UNION_SEMUN
#define UNION_SEMUN union semun
#else
#define UNION_SEMUN \
    union semun { \
        int val; \
        struct semid_ds *buf; \
        ushort *array; \
    } arg;
#endif

#define PCGI_H  1
#endif


=== Added File Packages/pcgi/pcgi_publisher.py ===
# 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"

import string, sys, os

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 ZPublisher import publish_module
        except ImportError:
            try:
                from cgi_module_publisher import publish_module
            except ImportError:
                return self.fatalError(
                    "unable to import publish_module from ZPublisher")

        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']

    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.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]]=''
        size = atoi(conn.recv(10))
        if size > 1048576:
            ### write large upload data to a file ###
            from tempfile import TemporaryFile
            stdin = TemporaryFile('w+b')
            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()

        stdout_len=len(stdout)
        conn.send('%010d' % len(stdout))
        to_send=stdout_len
        if to_send > 0:
            while 1:
                sent = conn.send(stdout)
                if sent == to_send:
                    break
                else:
                    to_send = to_send - sent
                    stdout = stdout[sent:]

        stderr_len=len(stderr)
        conn.send('%010d' % stderr_len)
        to_send=stderr_len
        if to_send > 0:
            while 1:
                sent = conn.send(stderr)
                if sent == to_send:
                    break
                else:
                    to_send = to_send - sent
                    stderr = stderr[sent:]

        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)

        stdlog('stderr')
        stdlog('stdout')

        while not self.error:
            conn, accept = self.sock.accept()
            try:
                self.handler(conn)
            except socket.error:
                pass

def stdlog(name):
    NAME=string.upper(name)+'_LOG'
    if os.environ.has_key(NAME):
        f=os.environ[NAME]
    else:
        f='/dev/null'
    try: f=open(f,'a')
    except: f=None
    getattr(sys, name).close()
    if f is not None: setattr(sys, name, f)

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