X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=roundup%2Fscripts%2Froundup_server.py;h=afe9d5edead6b4c96705337df4dee7a33af33a70;hb=3026636ec44af3e8bfa4f231be5f20e2c450a2ab;hp=9179a6ecbd873b68739b64e51c8db319806afb8b;hpb=eeb6be8329abc3d6fbe305945b6064fcc76afc5c;p=roundup.git diff --git a/roundup/scripts/roundup_server.py b/roundup/scripts/roundup_server.py index 9179a6e..afe9d5e 100644 --- a/roundup/scripts/roundup_server.py +++ b/roundup/scripts/roundup_server.py @@ -16,7 +16,7 @@ # """ HTTP Server that serves roundup. -$Id: roundup_server.py,v 1.7 2002-09-04 07:32:55 richard Exp $ +$Id: roundup_server.py,v 1.18 2003-02-06 05:43:49 richard Exp $ """ # python version check @@ -34,8 +34,12 @@ from roundup.i18n import _ ## Configuration # -# This indicates where the Roundup instance lives -ROUNDUP_INSTANCE_HOMES = { +# This indicates where the Roundup trackers live. They're given as NAME -> +# TRACKER_HOME, where the NAME part is used in the URL to select the +# appropriate reacker. +# Make sure the NAME part doesn't include any url-unsafe characters like +# spaces, as these confuse the cookie handling in browsers like IE. +TRACKER_HOMES = { 'bar': '/tmp/bar', } @@ -55,9 +59,8 @@ ROUNDUP_USER = None ## end configuration # - class RoundupRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): - ROUNDUP_INSTANCE_HOMES = ROUNDUP_INSTANCE_HOMES + TRACKER_HOMES = TRACKER_HOMES ROUNDUP_USER = ROUNDUP_USER def run_cgi(self): @@ -93,18 +96,20 @@ class RoundupRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): do_GET = do_POST = do_HEAD = send_head = run_cgi def index(self): - ''' Print up an index of the available instances + ''' Print up an index of the available trackers ''' self.send_response(200) self.send_header('Content-Type', 'text/html') self.end_headers() w = self.wfile.write - w(_('Roundup instances index\n')) - w(_('

Roundup instances index

    \n')) - for instance in self.ROUNDUP_INSTANCE_HOMES.keys(): - w(_('
  1. %(instance_name)s\n')%{ - 'instance_url': urllib.quote(instance), - 'instance_name': cgi.escape(instance)}) + w(_('Roundup trackers index\n')) + w(_('

    Roundup trackers index

      \n')) + keys = self.TRACKER_HOMES.keys() + keys.sort() + for tracker in keys: + w(_('
    1. %(tracker_name)s\n')%{ + 'tracker_url': urllib.quote(tracker), + 'tracker_name': cgi.escape(tracker)}) w(_('
    ')) def inner_run_cgi(self): @@ -118,14 +123,14 @@ class RoundupRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): else: query = '' - # figure the instance + # figure the tracker if rest == '/': return self.index() l_path = rest.split('/') - instance_name = urllib.unquote(l_path[1]) - if self.ROUNDUP_INSTANCE_HOMES.has_key(instance_name): - instance_home = self.ROUNDUP_INSTANCE_HOMES[instance_name] - instance = roundup.instance.open(instance_home) + tracker_name = urllib.unquote(l_path[1]) + if self.TRACKER_HOMES.has_key(tracker_name): + tracker_home = self.TRACKER_HOMES[tracker_name] + tracker = roundup.instance.open(tracker_home) else: raise client.NotFound @@ -137,7 +142,7 @@ class RoundupRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): # Set up the CGI environment env = {} - env['INSTANCE_NAME'] = instance_name + env['TRACKER_NAME'] = tracker_name env['REQUEST_METHOD'] = self.command env['PATH_INFO'] = urllib.unquote(rest) if query: @@ -153,6 +158,7 @@ class RoundupRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): co = filter(None, self.headers.getheaders('cookie')) if co: env['HTTP_COOKIE'] = ', '.join(co) + env['HTTP_AUTHORIZATION'] = self.headers.getheader('authorization') env['SCRIPT_NAME'] = '' env['SERVER_NAME'] = self.server.server_name env['SERVER_PORT'] = str(self.server.server_port) @@ -161,31 +167,79 @@ class RoundupRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): decoded_query = query.replace('+', ' ') # do the roundup thang - c = instance.Client(instance, self, env) + c = tracker.Client(tracker, self, env) c.main() def usage(message=''): if message: message = _('Error: %(error)s\n\n')%{'error': message} print _('''%(message)sUsage: -roundup-server [-n hostname] [-p port] [-l file] [-d file] [name=instance home]* +roundup-server [-n hostname] [-p port] [-l file] [-d file] [name=tracker home]* -n: sets the host name -p: sets the port to listen on -l: sets a filename to log to (instead of stdout) -d: daemonize, and write the server's PID to the nominated file - name=instance home - Sets the instance home(s) to use. The name is how the instance is + name=tracker home + Sets the tracker home(s) to use. The name is how the tracker is identified in the URL (it's the first part of the URL path). The - instance home is the directory that was identified when you did + tracker home is the directory that was identified when you did "roundup-admin init". You may specify any number of these name=home pairs on the command-line. For convenience, you may edit the - ROUNDUP_INSTANCE_HOMES variable in the roundup-server file instead. + TRACKER_HOMES variable in the roundup-server file instead. + Make sure the name part doesn't include any url-unsafe characters like + spaces, as these confuse the cookie handling in browsers like IE. ''')%locals() sys.exit(0) +def daemonize(pidfile): + ''' Turn this process into a daemon. + - make sure the sys.std(in|out|err) are completely cut off + - make our parent PID 1 + + Write our new PID to the pidfile. + + From A.M. Kuuchling (possibly originally Greg Ward) with + modification from Oren Tirosh, and finally a small mod from me. + ''' + # Fork once + if os.fork() != 0: + os._exit(0) + + # Create new session + os.setsid() + + # Second fork to force PPID=1 + pid = os.fork() + if pid: + pidfile = open(pidfile, 'w') + pidfile.write(str(pid)) + pidfile.close() + os._exit(0) + + os.chdir("/") + os.umask(0) + + # close off sys.std(in|out|err), redirect to devnull so the file + # descriptors can't be used again + devnull = os.open('/dev/null', 0) + os.dup2(devnull, 0) + os.dup2(devnull, 1) + os.dup2(devnull, 2) + +def abspath(path): + ''' Make the given path an absolute path. + + Code from Zope-Coders posting of 2002-10-06 by GvR. + ''' + if not os.path.isabs(path): + path = os.path.join(os.getcwd(), path) + return os.path.normpath(path) + def run(): + ''' Script entry point - handle args and figure out what to to. + ''' hostname = '' port = 8080 pidfile = None @@ -193,7 +247,7 @@ def run(): try: # handle the command-line args try: - optlist, args = getopt.getopt(sys.argv[1:], 'n:p:u:d:l:') + optlist, args = getopt.getopt(sys.argv[1:], 'n:p:u:d:l:h') except getopt.GetoptError, e: usage(str(e)) @@ -202,8 +256,8 @@ def run(): if opt == '-n': hostname = arg elif opt == '-p': port = int(arg) elif opt == '-u': user = arg - elif opt == '-d': pidfile = arg - elif opt == '-l': logfile = arg + elif opt == '-d': pidfile = abspath(arg) + elif opt == '-l': logfile = abspath(arg) elif opt == '-h': usage() if hasattr(os, 'getuid'): @@ -225,7 +279,7 @@ def run(): if not os.getuid() and user is None: raise ValueError, _("Can't run as root!") - # handle instance specs + # handle tracker specs if args: d = {} for arg in args: @@ -234,7 +288,7 @@ def run(): except ValueError: raise ValueError, _("Instances must be name=home") d[name] = home - RoundupRequestHandler.ROUNDUP_INSTANCE_HOMES = d + RoundupRequestHandler.TRACKER_HOMES = d except SystemExit: raise except: @@ -247,173 +301,25 @@ def run(): # fork? if pidfile: - pid = os.fork() - if pid: - print 'forking', pid - open(pidfile, 'w').write(str(pid)) - return + if not hasattr(os, 'fork'): + print "Sorry, you can't run the server as a daemon on this" \ + 'Operating System' + sys.exit(0) + daemonize(pidfile) - # redirect stdout/stderr + # redirect stdout/stderr to our logfile if logfile: - sys.stdout = sys.stderr = open(logfile, 'a') + # appending, unbuffered + sys.stdout = sys.stderr = open(logfile, 'a', 0) httpd = BaseHTTPServer.HTTPServer(address, RoundupRequestHandler) print _('Roundup server started on %(address)s')%locals() - httpd.serve_forever() + try: + httpd.serve_forever() + except KeyboardInterrupt: + print 'Keyboard Interrupt: exiting' if __name__ == '__main__': run() -# -# $Log: not supported by cvs2svn $ -# Revision 1.6 2002/08/30 08:33:28 richard -# new CGI frontend support -# -# Revision 1.5 2002/03/14 23:59:24 richard -# . #517734 ] web header customisation is obscure -# -# Revision 1.4 2002/02/21 07:02:54 richard -# The correct var is "HTTP_HOST" -# -# Revision 1.3 2002/02/21 06:57:39 richard -# . Added popup help for classes using the classhelp html template function. -# - add -# to an item page, and it generates a link to a popup window which displays -# the id, name and description for the priority class. The description -# field won't exist in most installations, but it will be added to the -# default templates. -# -# Revision 1.2 2002/01/29 20:07:15 jhermann -# Conversion to generated script stubs -# -# Revision 1.1 2002/01/29 19:53:08 jhermann -# Moved scripts from top-level dir to roundup.scripts subpackage -# -# Revision 1.25 2002/01/05 02:21:21 richard -# fixes -# -# Revision 1.24 2002/01/05 02:19:03 richard -# i18n'ification -# -# Revision 1.23 2001/12/15 23:47:07 richard -# sys module went away... -# -# Revision 1.22 2001/12/13 00:20:01 richard -# . Centralised the python version check code, bumped version to 2.1.1 (really -# needs to be 2.1.2, but that isn't released yet :) -# -# Revision 1.21 2001/12/02 05:06:16 richard -# . We now use weakrefs in the Classes to keep the database reference, so -# the close() method on the database is no longer needed. -# I bumped the minimum python requirement up to 2.1 accordingly. -# . #487480 ] roundup-server -# . #487476 ] INSTALL.txt -# -# I also cleaned up the change message / post-edit stuff in the cgi client. -# There's now a clearly marked "TODO: append the change note" where I believe -# the change note should be added there. The "changes" list will obviously -# have to be modified to be a dict of the changes, or somesuch. -# -# More testing needed. -# -# Revision 1.20 2001/11/26 22:55:56 richard -# Feature: -# . Added INSTANCE_NAME to configuration - used in web and email to identify -# the instance. -# . Added EMAIL_SIGNATURE_POSITION to indicate where to place the roundup -# signature info in e-mails. -# . Some more flexibility in the mail gateway and more error handling. -# . Login now takes you to the page you back to the were denied access to. -# -# Fixed: -# . Lots of bugs, thanks Roché and others on the devel mailing list! -# -# Revision 1.19 2001/11/12 22:51:04 jhermann -# Fixed option & associated error handling -# -# Revision 1.18 2001/11/01 22:04:37 richard -# Started work on supporting a pop3-fetching server -# Fixed bugs: -# . bug #477104 ] HTML tag error in roundup-server -# . bug #477107 ] HTTP header problem -# -# Revision 1.17 2001/10/29 23:55:44 richard -# Fix to CGI top-level index (thanks Juergen Hermann) -# -# Revision 1.16 2001/10/27 00:12:21 richard -# Fixed roundup-server for windows, thanks Juergen Hermann. -# -# Revision 1.15 2001/10/12 02:23:26 richard -# Didn't clean up after myself :) -# -# Revision 1.14 2001/10/12 02:20:32 richard -# server now handles setuid'ing much better -# -# Revision 1.13 2001/10/05 02:23:24 richard -# . roundup-admin create now prompts for property info if none is supplied -# on the command-line. -# . hyperdb Class getprops() method may now return only the mutable -# properties. -# . Login now uses cookies, which makes it a whole lot more flexible. We can -# now support anonymous user access (read-only, unless there's an -# "anonymous" user, in which case write access is permitted). Login -# handling has been moved into cgi_client.Client.main() -# . The "extended" schema is now the default in roundup init. -# . The schemas have had their page headings modified to cope with the new -# login handling. Existing installations should copy the interfaces.py -# file from the roundup lib directory to their instance home. -# . Incorrectly had a Bizar Software copyright on the cgitb.py module from -# Ping - has been removed. -# . Fixed a whole bunch of places in the CGI interface where we should have -# been returning Not Found instead of throwing an exception. -# . Fixed a deviation from the spec: trying to modify the 'id' property of -# an item now throws an exception. -# -# Revision 1.12 2001/09/29 13:27:00 richard -# CGI interfaces now spit up a top-level index of all the instances they can -# serve. -# -# Revision 1.11 2001/08/07 00:24:42 richard -# stupid typo -# -# Revision 1.10 2001/08/07 00:15:51 richard -# Added the copyright/license notice to (nearly) all files at request of -# Bizar Software. -# -# Revision 1.9 2001/08/05 07:44:36 richard -# Instances are now opened by a special function that generates a unique -# module name for the instances on import time. -# -# Revision 1.8 2001/08/03 01:28:33 richard -# Used the much nicer load_package, pointed out by Steve Majewski. -# -# Revision 1.7 2001/08/03 00:59:34 richard -# Instance import now imports the instance using imp.load_module so that -# we can have instance homes of "roundup" or other existing python package -# names. -# -# Revision 1.6 2001/07/29 07:01:39 richard -# Added vim command to all source so that we don't get no steenkin' tabs :) -# -# Revision 1.5 2001/07/24 01:07:59 richard -# Added command-line arg handling to roundup-server so it's more useful -# out-of-the-box. -# -# Revision 1.4 2001/07/23 10:31:45 richard -# disabled the reloading until it can be done properly -# -# Revision 1.3 2001/07/23 08:53:44 richard -# Fixed the ROUNDUPS decl in roundup-server -# Move the installation notes to INSTALL -# -# Revision 1.2 2001/07/23 04:05:05 anthonybaxter -# actually quit if python version wrong -# -# Revision 1.1 2001/07/23 03:46:48 richard -# moving the bin files to facilitate out-of-the-boxness -# -# Revision 1.1 2001/07/22 11:15:45 richard -# More Grande Splite stuff -# -# # vim: set filetype=python ts=4 sw=4 et si