Commit 843451b7 authored by 's avatar

*** empty log message ***

parent 1802f92d
README.MrCreosote - JeffBauer@bigfoot.com - May 21, 1998
MrCreosote is a lightweight message-passing idiom I use
to debug multi-processor/multi-user code sometimes.i
It's basically just a matter of tossing out datagrams
(connectionless sockets). I'll document it later, in
case anyone finds it useful for debugging. For now,
just ignore the contents of this directory.
/* creosote.c */
#include "creosote.h"
struct MrCreosote CreosoteServer;
void closeMrCreosote()
{
struct MrCreosote *c = &CreosoteServer;
if (c->socket)
{
#ifdef UNIX
close(c->socket);
#endif
#ifdef WIN32
closesocket(c->socket);
WSACleanup();
#endif
}
c->socket = 0;
}
#ifdef UNIX
int initializeMrCreosote()
{
struct MrCreosote *c = &CreosoteServer;
SOCKADDR_IN addr, *serv;
creosote_socket *s;
serv = &(c->serv_addr);
s = &(c->socket);
c->port = CREOSOTE_PORT;
strcpy(c->host, CREOSOTE_HOST);
bzero(serv, sizeof(*serv));
serv->sin_family = AF_INET;
serv->sin_addr.s_addr = inet_addr(c->host);
serv->sin_port = htons(c->port);
if ((*s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
return(-1);
}
bzero((char *) &addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(0);
if (bind(*s, (struct sockaddr *) &addr, sizeof(addr)) < 0)
{
return(-1);
}
return(0);
}
#endif
#ifdef WIN32
int initializeMrCreosote()
{
struct MrCreosote *c = &CreosoteServer;
SOCKADDR_IN *serv;
creosote_socket *s;
WSADATA WsaData;
int enable = 1;
s = &(c->socket);
if (!c->port)
{
c->port = CREOSOTE_PORT;
}
if (!c->host[0])
{
strcpy(c->host, CREOSOTE_HOST);
}
if (0 != WSAStartup(MAKEWORD(2,0), &WsaData))
{
return(-1);
}
/* Set the address */
serv = &(c->serv_addr);
serv->sin_family = AF_INET;
serv->sin_addr.s_addr = inet_addr(c->host);
serv->sin_port = htons((short)c->port);
/* Create socket */
*s = socket(AF_INET, SOCK_DGRAM, 0);
if (INVALID_SOCKET == *s) { return(-1); }
/* Permit the socket to broadcast */
if (SOCKET_ERROR == setsockopt(*s, SOL_SOCKET, SO_BROADCAST, (char *) &enable, sizeof(enable)))
{
return(-1);
}
return(0);
}
#endif
void setMrCreosoteHost(char *host)
{
/*
If not using localhost, setMrCreosoteHost() must be called
before initializeMrCreosote().
*/
strcpy(CreosoteServer.host, host);
}
void setMrCreosotePort(int port)
{
/* must be done before initializeMrCreosote() is called */
CreosoteServer.port = port;
}
void spewMrCreosote(char *msg)
{
struct MrCreosote *c = &CreosoteServer;
sendto(c->socket, msg, strlen(msg), 0, (struct sockaddr *) &(c->serv_addr), sizeof(c->serv_addr));
}
#if 0
int main(int argc, char *argv[])
{
if ( (initializeMrCreosote()) < 0)
{
printf("initializeMrCreosote() failed\n");
exit(1);
}
spew("Hello, world");
closeMrCreosote();
return(0);
}
#endif
/* creosote.h */
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#define CREOSOTE_HOST "127.0.0.1"
#define CREOSOTE_PORT 7739
#define spew(x) spewMrCreosote(x)
#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>
typedef int creosote_socket;
typedef struct sockaddr_in SOCKADDR_IN;
#endif
#ifdef WIN32
#include <windows.h>
#include <iostream.h>
#include <winsock.h>
typedef SOCKET creosote_socket;
#endif
struct MrCreosote
{
char host[256];
int port;
creosote_socket socket;
SOCKADDR_IN serv_addr;
};
/* Declarations */
void closeMrCreosote();
int initializeMrCreosote();
void spewMrCreosote(char *msg);
#!/usr/bin/env python
# creosote.py - lightweight message passing with datagrams
# JeffBauer@bigfoot.com
import sys, socket
BUFSIZE = 1024
PORT = 7739
def spew(msg, host='localhost', port=PORT):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind('', 0)
s.sendto(msg, (host, port))
def bucket(port=PORT, logfile=None):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind('', port)
print 'creosote bucket waiting on port: %s' % port
if logfile:
f = open(logfile, 'a+')
while 1:
data, addr = s.recvfrom(BUFSIZE)
print `data`[1:-1]
if logfile:
f.write(`data`[1:-1]+'\n')
f.flush()
class MrCreosote:
"""lightweight message passing with datagrams"""
def __init__(self, host='localhost', port=PORT):
self.host = host
self.port = port
self.client = None
self.disabled = 0
self.redirect_server = None
self.redirect_client = None
def bucket(self, logfile=None):
bucket(self.port, logfile)
def redirector(self, host, port=PORT):
if self.disabled:
return
if self.redirect_server == None:
self.redirect_server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.redirect_server.bind('', self.port)
if self.redirect_client == None:
self.redirect_client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.redirect_client.bind('', 0)
while 1:
data, addr = self.redirect_server.recvfrom(BUFSIZE)
self.redirect_client.sendto(data, (host, port))
def spew(self, msg):
if self.disabled:
return
if self.client == None:
self.client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.client.bind('', 0)
self.client.sendto(msg, (self.host, self.port))
if __name__ == '__main__':
"""usage: creosote [message]"""
if len(sys.argv) < 2:
bucket()
else:
from string import joinfields
spew(joinfields(sys.argv[1:],' '))
README.parseinfo - JeffBauer@bigfoot.com - May 21, 1998
parseinfo is an executable to test the parsing the pcgi
info file. Although pcgifile.py can be used to test
how the pcgi-wrapper is expected to react "in vitro"
(i.e. as a CGI process) the parseinfo program actually
runs the info file through the parser code (although
it performs no further environment testing).
usage: parseinfo <pcgi-info-file>
sample output:
r->sw_info /export/home/jbauer/tmp/pcgiinfo
r->sw_name
r->sw_home
r->sw_exe /usr/local/bin/python
r->procpath /export/home/jbauer/var/pcgitime.pid
r->sockpath /export/home/jbauer/var/pcgitime.socket
r->modpath /export/home/jbauer/www/cgi-bin/pcgitime.py
r->pubpath /export/home/jbauer/www/cgi-bin/pcgi_publisher.py
r->procid 0
r->insertPath
r->pythonPath .:/usr/local/lib/python1.5:/var/share/s0/python
CloseFileDescriptors 0
pcgifile.py - JeffBauer@bigfoot.com - May 21, 1998
The pcgifile.py is a sanity tester for pcgi info files and
can be run as a stand-alone program or a CGI script. For
more information, refer to:
http://starship.skyport.net/crew/jbauer/persistcgi/pcgifile/
#!/usr/bin/env python
# killpcgi.py - kill a running pcgi process
# Copyright(c) 1998, Jeff Bauer, All rights reserved.
# killpcgi is a convenience script to kill a running
# pcgi process, provided that it is running on a
# Unix system. You pass it the path of the pcgi info
# file, and killpcgi will kill the running process and
# remove the socket/pid files.
#
# killpcgi has been built at the request of several users,
# but you may want to first examine the script and modify it
# to suit your environment.
#
# Bugs: skimpy error handling
# 0.3a minor win32 exception caught
# 0.2a Added support for NT - 8/8/98
# 0.1a Initial version
__version__ = "0.3a"
def win32_kill(pid):
"""posix-style kill command for the Win32 environment"""
import win32api, pywintypes
try:
handle = win32api.OpenProcess(1, 0, pid)
except pywintypes.error:
return -1
return (0 != win32api.TerminateProcess(handle, 0))
def killpcgi(pcgiInfoFile):
import os, sys, string
delimiter = '='
pidFile = None
socketFile = None
infoFile = open(pcgiInfoFile, 'r')
for i in infoFile.readlines():
if delimiter in i:
n,v = string.split(string.strip(i), delimiter)
if n == 'PCGI_PID_FILE':
pidFile = v
elif n == 'PCGI_SOCKET_FILE':
socketFile = v
infoFile.close()
if pidFile is None:
print "unknown pid file"
else:
f = open(pidFile)
pid = int(f.read())
f.close()
if os.name == 'nt':
if not win32_kill(pid):
print "process %d killed" % pid
elif os.name == 'posix':
if os.kill(pid, 0):
print "process %d doesn't appear to be running" % pid
else:
# safety measure (exclude it if you're fearless)
if os.system('/bin/ps -p %d | grep python > /dev/null' % pid):
print "process %d doesn't appear to be python" % pid
else:
os.kill(pid, 15)
print "process %d killed" % pid
# conservative approach: don't remove pid/socket files
# unless we're reasonably certain we have killed the
# running process
os.unlink(pidFile)
if socketFile is not None:
os.unlink(socketFile)
else:
print "kill not supported for platform:", os.name
if __name__ == '__main__':
import sys
usage = "usage: killpcgi pcgi-info-file"
if len(sys.argv) < 2:
print usage
else:
killpcgi(sys.argv[1])
This diff is collapsed.
# Makefile.nt
VERSION = 2.0a4
CC = cl
CFLAGS = /W3 /DWIN32 /I..
LIBS = wsock32.lib
SRCDIR= ..
CREOSOTE_DIR = $(SRCDIR)/MrCreosote
CORE = $(SRCDIR)/pcgi.h #parseinfo.c
.c.obj:
$(CC) /c $(CFLAGS) $*.c
all: pcgi-wrapper.exe parseinfo.exe creosote.obj
creosote.obj: $(CREOSOTE_DIR)/creosote.c $(CREOSOTE_DIR)/creosote.h
$(CC) /c $(CFLAGS) /I$(CREOSOTE_DIR) /Focreosote.obj $(CREOSOTE_DIR)/creosote.c
parseinfo1.obj: $(SRCDIR)/parseinfo.c $(CORE)
$(CC) /c $(CFLAGS) /DMAIN_PARSEINFO /Foparseinfo1.obj $(SRCDIR)/parseinfo.c
parseinfo2.obj: $(SRCDIR)/parseinfo.c $(CORE)
$(CC) /c $(CFLAGS) $(SRCDIR)/parseinfo.c /Foparseinfo2.obj
pcgi-wrapper1.obj: $(SRCDIR)/pcgi-wrapper.c $(CORE)
$(CC) /c $(CFLAGS) /I$(CREOSOTE_DIR) /DPCGI_WRAPPER_MAIN /DCREOSOTE /DVERSION=\"$(VERSION)\" /Fopcgi-wrapper1.obj $(SRCDIR)/pcgi-wrapper.c
pcgi-wrapper2.obj: $(SRCDIR)/pcgi-wrapper.c $(CORE)
$(CC) /c $(CFLAGS) /I$(CREOSOTE_DIR) /DCREOSOTE /Fopcgi-wrapper2.obj $(SRCDIR)/pcgi-wrapper.c
parseinfo.exe: parseinfo1.obj pcgi-wrapper2.obj creosote.obj
link /OUT:parseinfo.exe parseinfo1.obj pcgi-wrapper2.obj creosote.obj $(LIBS)
pcgi-wrapper.exe: pcgi-wrapper1.obj parseinfo2.obj creosote.obj
link /OUT:pcgi-wrapper.exe pcgi-wrapper1.obj parseinfo2.obj creosote.obj $(LIBS)
README.NT - one day this will grow up and become a real README file.
PCGI 2.0a4 Win32 binary release (alpha 4) August 10, 1998
contact: jeffbauer@bigfoot.com
What is this?
The collection of files below is the first Win32
release of PCGI, the Persistent CGI wrapper for
Bobo applications. For more information about Bobo,
go to Digital Creations site: http://www.digicool.com
Files (in relative order of importance):
pcgi-wrapper.exe - the main program
pcgi_publisher.py - modified to handle both Unix & Win32
pcgifile.py - indispensible for tracking down problems
pcgitime.py - sample module
pcgitest - sample PCGI info file
killpcgi.py - handy for killing the running process
parseinfo.exe - used only when necessary (to view the pcgi
info file the way pcgi-wrapper sees it)
For information about Persistent CGI, check out:
http://starship.skyport.net/crew/jbauer/persistcgi/
(This information may soon move over to www.digicool.com)
Platforms tested?
Apache/Win32 1.3.1 running on NT 4.0. However, it should
run on any Win32 platform running a server supporting http.
Basic checklist to get the sample application up and running:
0. Install Python, Bobo, and a web server on your machine.
If you haven't got these things already working, please
see my notes on the subject:
http://starship.skyport.net/crew/jbauer/apachenotes/
1. Put pcgi-wrapper.exe where you normally place your
binary executables, or in cgi-bin.
2. Put pcgi_publisher.py in a directory where you normally
put your .py scripts -- cgi-bin is okay, but you will
specify the path in your info file, regardless.
3. Put pcgitest & pcgitime.py in cgi-bin. You will have
to modify the first #! she-bang line in pcgitest to
match the path of where you put pcgi-wrapper.exe. Also,
all directives must match your environment -- the examples
included are for illustration purposes only. Please
read the online (URL above) PCGI documentation for
further information.
4. Run your setup against pcgifile.py, a sanity check
described in:
http://starship.skyport.net/crew/jbauer/persistcgi/pcgifile/
http://starship.skyport.net/crew/jbauer/persistcgi/howto
5. Give me feedback, please: jeffbauer@bigfoot.com
-------------------
Microsoft IIS Notes:
Amos Latteier notes that some web servers, notably Microsoft's IIS,
cannot deal with the first line in a CGI program like Apache:
#!C:\WINNT\system32\pcgi-wrapper.exe
The solution is to use a .pcgi extension for your info file and create
a file association between .pcgi and pcgi-wrapper.exe with an IIS script
map registry entry, e.g.:
.pcgi C:\winnt\system32\pcgi-wrapper.exe %s
Now info files with the .pcgi extension will execute as cgi
programs.
[Amos further notes in a posting to the Bobo list:]
IIS 4 by default sends a custom 404 error message which masks
Bobo's 404 error information. This effectively keeps you from
seeing what Bobo is trying to tell you about why it is not
publishing your object. To get rid of this annoyance go to
the web site properties dialog in the Microsoft Management
Console application. Click on the "Custom Errors" tab. Choose
the 404 error and change it to use "Default" error message.
Voila, you're back in business, and can read Bobo information in
the source of your 404 error messages now.
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