[Zope-Checkins] CVS: Zope/lib/python/Zope/Startup - ZctlLib.py:1.4 __init__.py:1.4 cmdline.py:1.4 datatypes.py:1.4 handlers.py:1.4 options.py:1.2 zopeschema.xml:1.4
Fred L. Drake, Jr.
fred@zope.com
Tue, 18 Mar 2003 16:38:20 -0500
Update of /cvs-repository/Zope/lib/python/Zope/Startup
In directory cvs.zope.org:/tmp/cvs-serv27358
Added Files:
ZctlLib.py __init__.py cmdline.py datatypes.py handlers.py
options.py zopeschema.xml
Log Message:
Merge startup code from the new-install-branch.
=== Zope/lib/python/Zope/Startup/ZctlLib.py 1.3 => 1.4 === (644/744 lines abridged)
--- /dev/null Tue Mar 18 16:38:19 2003
+++ Zope/lib/python/Zope/Startup/ZctlLib.py Tue Mar 18 16:37:49 2003
@@ -0,0 +1,741 @@
+##############################################################################
+#
+# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+ Zope appserver controller. This is akin to apache's apachectl,
+ except with an interactive interpreter if no commands are specified
+ on the command-line.
+"""
+
+__version__ = '$Revision$'[11:-2]
+
+import cmd
+import getopt
+import os
+import signal
+import sys
+import time
+
+try:
+ import readline
+except:
+ readline = None
+
+from Zope.Startup import getOptions, getOptionDescriptions, configure
+from Zope.Startup.misc import TextBlockFormatter
+from Zope.Startup.misc.lock_file import lock_file
+
+USAGE = """\
+
+zopectl: Zope appserver controller
+
+Usage:
+ zopectl [-h | --help] [--config=filepath or url] [additional options]
+
+Options:
+ -h or --help Print this message. Not compatible with the 'start'
+ or 'restart' command.
+
[-=- -=- -=- 644 lines omitted -=- -=- -=-]
+ self.cmdqueue.append(' '.join(args))
+ self.cmdqueue.append('EOF')
+
+ self.cmdloop()
+
+def get_pids(filename):
+ for line in open(filename).readlines():
+ pids = line.split()
+ if pids:
+ return [ int(x.strip()) for x in pids ]
+
+def win32kill(pid, sig):
+ # we ignore the signal on win32
+ try:
+ import win32api
+ import pywintypes
+ except:
+ print ("Could not open win32api module, have you installed the "
+ "'win32all' package?")
+ return 1
+ try:
+ handle = win32api.OpenProcess(1, 0, pid)
+ except pywintypes.error, why:
+ # process named by pid not running
+ return 1
+ try:
+ status = win32api.TerminateProcess(handle, 0)
+ except:
+ return 1
+ if status is None:
+ return 0
+ return 1
+
+def kill(pid, sig):
+ try:
+ os.kill(pid, sig)
+ except OSError, why:
+ return 1
+ else:
+ return 0
+
+def cmdquote(cmd):
+ if sys.platform == 'win32':
+ # ugh. win32 requires the command to be quoted. unix requires
+ # that the command *not* be quoted.
+ cmd = '"%s"' % cmd
+ return cmd
+
+if sys.platform == 'win32':
+ kill = win32kill
=== Zope/lib/python/Zope/Startup/__init__.py 1.3 => 1.4 ===
--- /dev/null Tue Mar 18 16:38:20 2003
+++ Zope/lib/python/Zope/Startup/__init__.py Tue Mar 18 16:37:49 2003
@@ -0,0 +1,275 @@
+##############################################################################
+#
+# Copyright (c) 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+""" Startup package. Responsible for startup configuration of Zope """
+
+import os
+import sys
+import socket
+import re
+
+import ZConfig
+
+from cmdline import getOptions, getOptionDescriptions # exported
+
+# global to hold config structures
+_schema = None
+_configuration = None
+
+def getConfiguration():
+ return _configuration
+
+def getSchema():
+ global _schema
+ if _schema is None:
+ here = os.path.dirname(__file__)
+ path = os.path.join(here, 'zopeschema.xml')
+ _schema = ZConfig.loadSchema(path)
+ return _schema
+
+def configure(config_location, options):
+ global _configuration
+ import handlers
+ schema = getSchema()
+ _configuration, handler = ZConfig.loadConfig(schema, config_location)
+ handlers.handleConfig(_configuration, handler, options)
+ return _configuration
+
+def start_zope(cfg):
+ # set up our initial logging environment (log everything to stderr
+ # if we're not in debug mode).
+ import zLOG
+
+ # don't initialize the event logger from the environment
+ zLOG._call_initialize = 0
+
+ from zLOG.LogHandlers import StartupHandler
+
+ # we log events to the root logger, which is backed by a
+ # "StartupHandler" log handler. The "StartupHandler" outputs to
+ # stderr but also buffers log messages. When the "real" loggers
+ # are set up, we flush accumulated messages in StartupHandler's
+ # buffers to the real logger.
+ startup_handler = StartupHandler(sys.stderr)
+ formatter = zLOG.EventLogger.formatters['file']
+ startup_handler.setFormatter(formatter)
+ if not cfg.debug_mode:
+ # prevent startup messages from going to stderr if we're not
+ # in debug mode
+ if os.path.exists('/dev/null'): # unix
+ devnull = '/dev/null'
+ else: # win32
+ devnull = 'nul:'
+ startup_handler = StartupHandler(open(devnull, 'w'))
+
+ # set up our event logger temporarily with a startup handler
+ event_logger = zLOG.EventLogger.EventLogger.logger
+ event_logger.addHandler(startup_handler)
+
+ # set a locale if one has been specified in the config
+ if cfg.locale:
+ do_locale(cfg.locale)
+
+ # Increase the number of threads
+ import ZServer
+ ZServer.setNumberOfThreads(cfg.zserver_threads)
+
+ # Start ZServer servers before we setuid so we can bind to low ports:
+ socket_err = (
+ 'There was a problem starting a server of type "%s". '
+ 'This may mean that your user does not have permission to '
+ 'bind to the port which the server is trying to use or the '
+ 'port may already be in use by another application.'
+ )
+ servers = []
+ for server in cfg.servers:
+ # create the server from the server factory
+ # set up in the config
+ try:
+ servers.append(server.create())
+ except socket.error:
+ raise ZConfig.ConfigurationError(socket_err
+ % server.servertype())
+ cfg.servers = servers
+
+ # do stuff that only applies to posix platforms (setuid, daemonizing)
+ if os.name == 'posix':
+ do_posix_stuff(cfg)
+
+ # Import Zope
+ import Zope
+ Zope.startup()
+
+ if not cfg.zserver_read_only_mode:
+ # lock_file is used for the benefit of zctl, so it can tell whether
+ # Zope is already running before attempting to fire it off again.
+ # We aren't concerned about locking the file to protect against
+ # other Zope instances running from our CLIENT_HOME, we just
+ # try to lock the file to signal that zctl should not try to
+ # start Zope if *it* can't lock the file; we don't panic
+ # if we can't lock it.
+ # we need a separate lock file because on win32, locks are not
+ # advisory, otherwise we would just use the pid file
+ from Zope.Startup.misc.lock_file import lock_file
+ lock_filename = cfg.lock_filename
+ try:
+ if os.path.exists(lock_filename):
+ os.unlink(lock_filename)
+ LOCK_FILE = open(lock_filename, 'w')
+ lock_file(LOCK_FILE)
+ except IOError:
+ pass
+
+ # Now that we've successfully setuid'd, we can log to
+ # somewhere other than stderr. Activate the configured logs:
+ if cfg.access is not None:
+ cfg.access()
+ if cfg.trace is not None:
+ cfg.trace()
+
+ # flush buffered startup messages to event logger
+ event_logger.removeHandler(startup_handler)
+ if cfg.eventlog is not None:
+ logger = cfg.eventlog()
+ startup_handler.flushBufferTo(logger)
+
+ zLOG.LOG('Zope', zLOG.INFO, 'Ready to handle requests')
+
+ # Start Medusa, Ye Hass!
+ try:
+ import Lifetime
+ Lifetime.loop()
+ sys.exit(ZServer.exit_code)
+ finally:
+ if not cfg.zserver_read_only_mode:
+ try:
+ os.unlink(cfg.pid_filename)
+ except OSError:
+ pass
+ try:
+ LOCK_FILE.close()
+ os.unlink(lock_filename)
+ except OSError:
+ pass
+
+def _warn_nobody():
+ import zLOG
+ zLOG.LOG("Zope", zLOG.INFO, ("Running Zope as 'nobody' can compromise "
+ "your Zope files; consider using a "
+ "dedicated user account for Zope"))
+
+def check_python_version():
+ # check for Python version
+ python_version = sys.version.split()[0]
+ optimum_version = '2.2.2'
+ if python_version < '2.2':
+ raise ZConfig.ConfigurationError(
+ 'Invalid python version ' + python_version)
+ if python_version[:3] == '2.2':
+ if python_version[4:5] < '2':
+ err = ('You are running Python version %s. This Python version '
+ 'has known bugs that may cause Zope to run improperly. '
+ 'Consider upgrading to Python %s\n' %
+ (python_version, optimum_version))
+ sys.stderr.write(err)
+
+def do_posix_stuff(cfg):
+ import zLOG
+ import zdaemon
+ import pwd
+ from Signals import Signals
+ Signals.registerZopeSignals()
+
+ # Warn if we were started as nobody.
+ if os.getuid():
+ if pwd.getpwuid(os.getuid())[0] == 'nobody':
+ _warn_nobody()
+
+ # Drop root privileges if we have them, and do some sanity checking
+ # to make sure we're not starting with an obviously insecure setup.
+ if os.getuid() == 0:
+ UID = cfg.effective_user
+ if UID == None:
+ msg = ('A user was not specified to setuid to; fix this to '
+ 'start as root (change the effective_user directive '
+ 'in zope.conf)')
+ zLOG.LOG('Zope', zLOG.PANIC, msg)
+ raise ZConfig.ConfigurationError(msg)
+ # stuff about client home faults removed (real effective user
+ # support now)
+ try:
+ UID = int(UID)
+ except (TypeError, ValueError):
+ pass
+ gid = None
+ if isinstance(UID, str):
+ uid = pwd.getpwnam(UID)[2]
+ gid = pwd.getpwnam(UID)[3]
+ elif isinstance(UID, int):
+ uid = pwd.getpwuid(UID)[2]
+ gid = pwd.getpwuid(UID)[3]
+ UID = pwd.getpwuid(UID)[0]
+ else:
+ zLOG.LOG("Zope", zLOG.ERROR, ("Can't find UID %s" % UID))
+ raise ZConfig.ConfigurationError('Cant find UID %s' % UID)
+ if UID == 'nobody':
+ _warn_nobody()
+ if gid is not None:
+ try:
+ import initgroups
+ initgroups.initgroups(UID, gid)
+ os.setgid(gid)
+ except OSError:
+ zLOG.LOG("Zope", zLOG.INFO,
+ 'Could not set group id of effective user',
+ error=sys.exc_info())
+ os.setuid(uid)
+ zLOG.LOG("Zope", zLOG.INFO,
+ 'Set effective user to "%s"' % UID)
+
+ if not cfg.debug_mode:
+ # umask is silly, blame POSIX. We have to set it to get its value.
+ current_umask = os.umask(0)
+ os.umask(current_umask)
+ if current_umask != 077:
+ current_umask = '%03o' % current_umask
+ zLOG.LOG("Zope", zLOG.INFO, (
+ 'Your umask of %s may be too permissive; for the security of '
+ 'your Zope data, it is recommended you use 077' % current_umask
+ ))
+
+
+def do_locale(locale_id):
+ # workaround to allow unicode encoding conversions in DTML
+ import codecs
+ dummy = codecs.lookup('iso-8859-1')
+
+ if locale_id is not None:
+ try:
+ import locale
+ except:
+ raise ZConfig.ConfigurationError(
+ 'The locale module could not be imported.\n'
+ 'To use localization options, you must ensure\n'
+ 'that the locale module is compiled into your\n'
+ 'Python installation.'
+ )
+ try:
+ locale.setlocale(locale.LC_ALL, locale_id)
+ except:
+ raise ZConfig.ConfigurationError(
+ 'The specified locale "%s" is not supported by your system.\n'
+ 'See your operating system documentation for more\n'
+ 'information on locale support.' % locale_id
+ )
=== Zope/lib/python/Zope/Startup/cmdline.py 1.3 => 1.4 ===
--- /dev/null Tue Mar 18 16:38:20 2003
+++ Zope/lib/python/Zope/Startup/cmdline.py Tue Mar 18 16:37:49 2003
@@ -0,0 +1,172 @@
+import getopt
+
+def getOptionDescriptions():
+ """ Temporary implementation """
+
+ short, long = getOptions()
+ n = 0
+ short_d = {}
+ long_d = {}
+
+ last = 0
+ n = 0
+
+ print short
+
+ if short:
+ while 1:
+ try:
+ opt = short[n]
+ except IndexError:
+ next = None
+ try:
+ next = short[n+1]
+ except IndexError:
+ next = None
+ if next == ':':
+ short_d[opt] = 1
+ n = n + 2
+ else:
+ if next is None and short.endswith(':'):
+ short_d[opt] = 1
+ else:
+ short_d[opt] = 0
+ n = n + 1
+ if next is None:
+ break
+
+ for opt in long:
+ if opt.endswith('='):
+ long_d[opt[:-1]] = 1
+ else:
+ long_d[opt] = 0
+
+ opts = []
+
+ short_l = short_d.items()
+ short_l.sort()
+ for k, v in short_l:
+ opts.append(' -%s%s' % (k, (v and ' <value>' or '')))
+
+ long_l = long_d.items()
+ long_l.sort()
+ for k, v in long_l:
+ opts.append(' --%s%s' % (k, (v and ' <value>' or '')))
+ return '\n'.join(opts)
+
+def getOptions():
+ short = 'Z:t:i:D:a:d:u:L:l:M:E:Xw:W:f:p:F:m:'
+ long = [
+ 'zserver-threads=',
+ 'python-check-interval=',
+ 'debug-mode=',
+ 'ip-address=',
+ 'dns-ip-address=',
+ 'effective-user=',
+ 'locale=',
+ 'access-log=',
+ 'trace-log=',
+ 'event-log=',
+ 'disable-servers',
+ 'http-server=',
+ 'webdav-source-server=',
+# XXX need to finish these
+# 'ftp-server=',
+# 'pcgi-server=',
+# 'fcgi-server=',
+# 'monitor-server=',
+# 'icp-server=',
+ ]
+ return short, long
+
+class CommandLineOptions:
+
+ def __call__(self, cfg, options):
+ import Zope.Startup.datatypes
+ import Zope.Startup.handlers
+ import ZConfig.datatypes
+
+ short, long = getOptions()
+ opts, args = getopt.getopt(options, short, long)
+
+ for k, v in opts:
+ # set up data that servers may rely on
+ if k in ('-t', '--zserver-threads'):
+ cfg.zserver_threads = int(v)
+ elif k in ('-i', '--python-check-interval'):
+ cfg.python_check_interval = int(v)
+ elif k in ('-D', '--debug-mode'):
+ datatype = ZConfig.datatypes.asBoolean
+ handler = Zope.Startup.handlers.debug_mode
+ v = datatype(v)
+ handler(v)
+ cfg.debug_mode = v
+ elif k in ('-i', '--ip-address'):
+ datatype = ZConfig.datatypes.IpaddrOrHostname()
+ cfg.ip_address = datatype(v)
+ elif k in ('-d', '--dns-ip-address'):
+ datatype = ZConfig.datatypes.IpaddrOrHostname()
+ cfg.dns_ip_address = datatype(v)
+ elif k in ('-u', '--effective-user'):
+ cfg.effective_user = v
+ elif k in ('-L', '--locale'):
+ datatype = ZConfig.datatypes.check_locale
+ cfg.locale = datatype(v)
+ elif k in ('-l', '--access-log'):
+ cfg.access = default_logger('access', v,
+ '%(message)s',
+ '%Y-%m-%dT%H:%M:%S')
+ elif k in ('-M', '--trace-log'):
+ cfg.trace = default_logger('trace', v,
+ '%(message)s',
+ '%Y-%m-%dT%H:%M:%S')
+ elif k in ('-E', '--event-log'):
+ cfg.trace = default_logger('event', v,
+ '------\n%(asctime)s %(message)s',
+ '%Y-%m-%dT%H:%M:%S')
+ elif k in ('-X', '--disable-servers'):
+ cfg.servers = []
+ else:
+ # continue if we've not matched, otherwise
+ # fall through to the pop statement below
+ continue
+
+ opts.pop(0) # pop non-server data from opts
+
+ factory = Zope.Startup.handlers.ServerFactoryFactory(cfg)
+
+ for k, v in opts:
+ # set up server data from what's left in opts,
+ # using repopulated cfg
+ if k in ('-w', '--http-server'):
+ datatype = ZConfig.datatypes.inet_address
+ host, port = datatype(v)
+ section = dummy()
+ section.ports = [(host, port)]
+ section.force_connection_close = 0
+ cfg.servers.append(['http_server',
+ factory.http_server(section)[0]])
+ if k in ('-W', '--webdav-source-server'):
+ datatype = ZConfig.datatypes.inet_address
+ host, port = datatype(v)
+ section = dummy()
+ section.ports = [(host, port)]
+ section.force_connection_close = 0
+ cfg.servers.append(['webdav_source_server',
+ factory.webdav_source_server(section)[0]])
+
+class dummy:
+ # used as a namespace generator
+ pass
+
+def default_logger(name, file, format, dateformat):
+ import Zope.Startup.datatypes
+ logger = dummy()
+ logger.level = 20
+ handler = dummy()
+ handler.file = file
+ handler.format = format
+ handler.dateformat = dateformat
+ handler.level = 20
+ handlers = [Zope.Startup.datatypes.file_handler(handler)]
+ return Zope.Startup.datatypes.LoggerWrapper(name, 20, handlers)
=== Zope/lib/python/Zope/Startup/datatypes.py 1.3 => 1.4 ===
--- /dev/null Tue Mar 18 16:38:20 2003
+++ Zope/lib/python/Zope/Startup/datatypes.py Tue Mar 18 16:37:49 2003
@@ -0,0 +1,91 @@
+##############################################################################
+#
+# Copyright (c) 2003 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+"""Datatypes for the Zope schema for use with ZConfig."""
+
+import os
+
+# generic datatypes
+
+def security_policy_implementation(value):
+ value = value.upper()
+ ok = ('PYTHON', 'C')
+ if value not in ok:
+ raise ValueError, (
+ "security_policy_implementation must be one of %s" % ok
+ )
+ return value
+
+def cgi_environment(section):
+ return section.environ
+
+# Datatype for the access and trace logs
+# (the loghandler datatypes come from the zLOG package)
+
+class LoggerFactory:
+ """
+ A factory used to create loggers while delaying actual logger
+ instance construction. We need to do this because we may want to
+ reference a logger before actually instantiating it (for example,
+ to allow the app time to set an effective user). An instance of
+ this wrapper is a callable which, when called, returns a logger
+ object.
+ """
+ def __init__(self, section):
+ self.name = section.getSectionName()
+ self.level = section.level
+ self.handler_factories = section.handlers
+ self.resolved = None
+
+ def __call__(self):
+ if self.resolved is None:
+ # set the logger up
+ import logging
+ logger = logging.getLogger(self.name)
+ logger.handlers = []
+ logger.propagate = 0
+ logger.setLevel(self.level)
+ for handler_factory in self.handler_factories:
+ handler = handler_factory()
+ logger.addHandler(handler)
+ self.resolved = logger
+ return self.resolved
+
+# DNS resolver
+
+def dns_resolver(hostname):
+ from ZServer.medusa import resolver
+ return resolver.caching_resolver(hostname)
+
+
+# Datatype for the root configuration object
+# (adds the softwarehome and zopehome fields; default values for some
+# computed paths)
+
+def root_config(section):
+ here = os.path.dirname(os.path.abspath(__file__))
+ swhome = os.path.dirname(os.path.dirname(here))
+ section.softwarehome = swhome
+ section.zopehome = os.path.dirname(os.path.dirname(swhome))
+ if section.cgi_environment is None:
+ section.cgi_environment = {}
+ if section.clienthome is None:
+ section.clienthome = os.path.join(section.instancehome, "var")
+ # set up defaults for pid_filename and lock_filename if they're
+ # not in the config
+ if section.pid_filename is None:
+ section.pid_filename = os.path.join(section.clienthome, 'Z2.pid')
+ if section.lock_filename is None:
+ section.lock_filename = os.path.join(section.clienthome, 'Z2.lock')
+ return section
=== Zope/lib/python/Zope/Startup/handlers.py 1.3 => 1.4 ===
--- /dev/null Tue Mar 18 16:38:20 2003
+++ Zope/lib/python/Zope/Startup/handlers.py Tue Mar 18 16:37:49 2003
@@ -0,0 +1,138 @@
+import os
+
+# top-level key handlers
+
+def _setenv(name, value):
+ if isinstance(value, str):
+ os.environ[name] = value
+ else:
+ os.environ[name] = `value`
+
+def debug_mode(value):
+ value and _setenv('Z_DEBUG_MODE', '1')
+ return value
+
+def enable_product_installation(value):
+ value and _setenv('FORCE_PRODUCT_LOAD', '1')
+ return value
+
+def locale(value):
+ import locale
+ locale.setlocale(locale.LC_ALL, value)
+ return value
+
+def zserver_read_only_mode(value):
+ value and _setenv('ZOPE_READ_ONLY', '1')
+ return value
+
+def automatically_quote_dtml_request_data(value):
+ not value and _setenv('ZOPE_DTML_REQUEST_AUTOQUOTE', '0')
+ return value
+
+def skip_authentication_checking(value):
+ value and _setenv('ZSP_AUTHENTICATED_SKIP', '1')
+ return value
+
+def skip_ownership_checking(value):
+ value and _setenv('ZSP_OWNEROUS_SKIP', '1')
+ return value
+
+def maximum_number_of_session_objects(value):
+ default = 1000
+ value not in (None, default) and _setenv('ZSESSION_OBJECT_LIMIT', value)
+ return value
+
+def session_add_notify_script_path(value):
+ value is not None and _setenv('ZSESSION_ADD_NOTIFY', value)
+ return value
+
+def session_delete_notify_script_path(value):
+ value is not None and _setenv('ZSESSION_DEL_NOTIFY', value)
+ return value
+
+def session_timeout_minutes(value):
+ default = 20
+ value not in (None, default) and _setenv('ZSESSION_TIMEOUT_MINS', value)
+ return value
+
+def suppress_all_access_rules(value):
+ value and _setenv('SUPPRESS_ACCESSRULE', value)
+ return value
+
+def suppress_all_site_roots(value):
+ value and _setenv('SUPPRESS_SITEROOT', value)
+ return value
+
+def database_quota_size(value):
+ value and _setenv('ZOPE_DATABASE_QUOTA', value)
+ return value
+
+def read_only_database(value):
+ value and _setenv('ZOPE_READ_ONLY', '1')
+ return value
+
+def zeo_client_name(value):
+ value and _setenv('ZEO_CLIENT', value)
+ return value
+
+def structured_text_header_level(value):
+ value is not None and _setenv('STX_DEFAULT_LEVEL', value)
+ return value
+
+def maximum_security_manager_stack_size(value):
+ value is not None and _setenv('Z_MAX_STACK_SIZE', value)
+ return value
+
+def publisher_profile_file(value):
+ value is not None and _setenv('PROFILE_PUBLISHER', value)
+ return value
+
+def http_realm(value):
+ value is not None and _setenv('Z_REALM', value)
+ return value
+
+def security_policy_implementation(value):
+ value not in ('C', None) and _setenv('ZOPE_SECURITY_POLICY', value)
+
+# server handlers
+
+def root_handler(config):
+ """ Mutate the configuration with defaults and perform
+ fixups of values that require knowledge about configuration
+ values outside of their context. """
+
+ # if no servers are defined, create default http server and ftp server
+ if not config.servers:
+ import ZServer.datatypes
+ config.servers = [
+ ZServer.datatypes.HTTPServerFactory(_DummyServerConfig(8080)),
+ ZServer.datatypes.FTPServerFactory(_DummyServerConfig(8021)),
+ ]
+
+ # prepare servers:
+ for factory in config.servers:
+ factory.prepare(config.ip_address or '',
+ config.dns_resolver,
+ "Zope",
+ config.cgi_environment,
+ config.port_base)
+
+
+class _DummyServerConfig:
+ class _Thing:
+ pass
+
+ def __init__(self, port):
+ import socket
+ self.address = self._Thing()
+ self.address.family = socket.AF_INET
+ self.address.address = '', port
+ self.force_connection_close = 0
+
+
+def handleConfig(config, multihandler):
+ handlers = {}
+ for name, value in globals().items():
+ if not name.startswith('_'):
+ handlers[name] = value
+ return multihandler(handlers)
=== Zope/lib/python/Zope/Startup/options.py 1.1 => 1.2 ===
--- /dev/null Tue Mar 18 16:38:20 2003
+++ Zope/lib/python/Zope/Startup/options.py Tue Mar 18 16:37:49 2003
@@ -0,0 +1,25 @@
+##############################################################################
+#
+# Copyright (c) 2003 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+"""Command-line processor for Zope."""
+
+import os
+
+import zdaemon.zdoptions
+
+
+class ZopeOptions(zdaemon.zdoptions.ZDOptions):
+
+ schemadir = os.path.dirname(os.path.abspath(__file__))
+ schemafile = "zopeschema.xml"
=== Zope/lib/python/Zope/Startup/zopeschema.xml 1.3 => 1.4 ===
--- /dev/null Tue Mar 18 16:38:20 2003
+++ Zope/lib/python/Zope/Startup/zopeschema.xml Tue Mar 18 16:37:49 2003
@@ -0,0 +1,260 @@
+<schema prefix="Zope.Startup.datatypes"
+ datatype=".root_config"
+ handler="root_handler">
+
+ <!-- type definitions -->
+
+ <import package="zLOG"/>
+ <import package="ZODB"/>
+ <import package="ZServer"/>
+
+ <sectiontype name="logger" datatype=".LoggerFactory">
+ <description>
+ This "logger" type only applies to access and request ("trace")
+ logging; event logging is handled by the zLOG package, which
+ provides the loghandler type used here.
+ </description>
+ <key name="level" datatype="zLOG.datatypes.logging_level" default="info"/>
+ <multisection type="loghandler" attribute="handlers" name="*"
+ required="yes"/>
+ </sectiontype>
+
+ <sectiontype name="cgi-environment"
+ datatype=".cgi_environment"
+ keytype="identifier">
+ <key name="+" attribute="environ"/>
+ </sectiontype>
+
+ <sectiontype name="zoperunner">
+ <description>
+ This section describes the options for zopectl. These options
+ have no default value specified in the schema; in some cases,
+ zopectl calculates a dynamic default, in others, the feature
+ associated with the option is disabled.
+
+ For those options that also have corresponding command-line
+ options, the command line option (short and long form) are given
+ here too.
+ </description>
+
+ <key name="daemon" datatype="boolean"
+ required="no" default="false">
+ <description>
+ Command-line option: -d or --daemon.
+
+ If this option is true, zdrun.py runs in the background as a
+ true daemon. It forks an child process which becomes the
+ subprocess manager, while the parent exits (making the shell
+ that started it believe it is done). The child process also
+ does the following:
+
+ - if the directory option is set, change into that directory
+
+ - redirect stdin, stdout and stderr to /dev/null
+
+ - call setsid() so it becomes a session leader
+
+ - call umask(022)
+ </description>
+ </key>
+
+ <key name="backoff-limit" datatype="integer"
+ required="no" default="10">
+ <description>
+ Command-line option: -b or --backoff-limit.
+
+ When the subprocess crashes, zdrun.py inserts a one-second
+ delay before it restarts it. When the subprocess crashes
+ again right away, the delay is incremented by one second, and
+ so on. What happens when the delay has reached the value of
+ backoff-limit (in seconds), depends on the value of the
+ forever option. If forever is false, zdrun.py gives up at
+ this point, and exits. An always-crashing subprocess will
+ have been restarted exactly backoff-limit times in this case.
+ If forever is true, zdrun.py continues to attempt to restart
+ the process, keeping the delay at backoff-limit seconds.
+
+ If the subprocess stays up for more than backoff-limit
+ seconds, the delay is reset to 1 second.
+ </description>
+ </key>
+
+ <key name="forever" datatype="boolean"
+ required="no" default="false">
+ <description>
+ Command-line option: -f or --forever.
+
+ If this option is true, zdrun.py will keep restarting a
+ crashing subprocess forever. If it is false, it will give up
+ after backoff-limit crashes in a row. See the description of
+ backoff-limit for details.
+ </description>
+ </key>
+
+ <key name="hang-around" datatype="boolean"
+ required="no" default="false">
+ <description>
+ If this option is true, the zdrun.py process will remain even
+ when the daemon subprocess is stopped. In this case, zopectl
+ will restart zdrun.py as necessary. If this option is false,
+ zdrun.py will exit when the daemon subprocess is stopped
+ (unless zdrun.py intends to restart it).
+ </description>
+ </key>
+
+ <key name="default-to-interactive" datatype="boolean"
+ required="no" default="true">
+ <description>
+ If this option is true, zopectl enters interactive mode
+ when it is invoked without a positional command argument. If
+ it is false, you must use the -i or --interactive command line
+ option to zopectl to enter interactive mode.
+ </description>
+ </key>
+
+ <key name="prompt" datatype="string"
+ required="no" default="zopectl>">
+ <description>
+ The prompt shown by zopectl program.
+ </description>
+ </key>
+
+ </sectiontype>
+
+ <!-- end of type definitions -->
+
+ <!-- schema begins -->
+
+ <key name="instancehome" datatype="existing-directory"
+ required="yes">
+ <description>
+ The top-level directory which contains the "instance" of the
+ application server.
+ </description>
+ </key>
+
+ <key name="clienthome" datatype="existing-directory">
+ <description>
+ The directory used to store the file-storage used to back the
+ ZODB database by default, as well as other files used by the
+ Zope application server to control the run-time behavior.
+ </description>
+ <metadefault>$INSTANCE_HOME/var</metadefault>
+ </key>
+
+ <key name="pid-filename" datatype="existing-dirpath"/>
+
+ <key name="lock-filename" datatype="existing-dirpath"/>
+
+ <key name="debug-mode" datatype="boolean" default="on"
+ handler="debug_mode"/>
+
+ <key name="effective-user"/>
+
+ <key name="enable-product-installation" datatype="boolean" default="on"
+ handler="enable_product_installation"/>
+
+ <key name="locale" datatype="locale" handler="locale"/>
+
+ <key name="zserver-threads" datatype="integer" default="4"/>
+
+ <key name="python-check-interval" datatype="integer" default="500">
+ <description>
+ Value passed to Python's sys.setcheckinterval() function. The
+ higher this is, the less frequently the Python interpreter
+ checks for keyboard interrupts. Setting this to higher values
+ also reduces the frequency of potential thread switches, which
+ can improve the performance of a busy server.
+ </description>
+ </key>
+
+ <key name="zserver-read-only-mode" datatype="boolean" default="off"
+ handler="zserver_read_only_mode">
+ <description>
+ If this variable is set, then the database is opened in read
+ only mode. If this variable is set to a string parsable by
+ DateTime.DateTime, then the database is opened read-only as of
+ the time given. Note that changes made by another process after
+ the database has been opened are not visible.
+ </description>
+ </key>
+
+ <key name="structured-text-header-level" datatype="integer" default="3"
+ handler="structured_text_header_level"/>
+
+ <key name="maximum-security-manager-stack-size" datatype="integer"
+ default="100" handler="maximum_security_manager_stack_size"/>
+
+ <key name="publisher-profile-file" handler="publisher_profile_file"/>
+
+ <section type="cgi-environment" attribute="cgi_environment" name="*"/>
+
+ <key name="dns-server" datatype=".dns_resolver" attribute="dns_resolver"/>
+
+ <key name="ip-address" datatype="ipaddr-or-hostname"/>
+
+ <key name="http-realm" default="Zope" handler="http_realm"/>
+
+ <key name="automatically-quote-dtml-request-data" datatype="boolean"
+ default="on" handler="automatically_quote_dtml_request_data"/>
+
+ <key name="security-policy-implementation"
+ datatype=".security_policy_implementation"
+ default="C" handler="security_policy_implementation"/>
+
+ <key name="skip-authentication-checking" datatype="boolean"
+ default="off" handler="skip_authentication_checking"/>
+
+ <key name="skip-ownership-checking" datatype="boolean"
+ default="off" handler="skip_ownership_checking"/>
+
+ <key name="maximum-number-of-session-objects" datatype="integer"
+ default="1000" handler="maximum_number_of_session_objects"/>
+
+ <key name="session-add-notify-script-path"
+ handler="session_add_notify_script_path"/>
+
+ <key name="session-delete-notify-script-path"
+ handler="session_add_notify_script_path"/>
+
+ <key name="session-timeout-minutes" datatype="integer"
+ default="20" handler="session_timeout_minutes"/>
+
+ <key name="suppress-all-access-rules" datatype="boolean"
+ default="off" handler="suppress_all_access_rules"/>
+
+ <key name="suppress-all-site-roots" datatype="boolean"
+ default="off" handler="suppress_all_site_roots"/>
+
+ <key name="database-quota-size" datatype="byte-size"
+ handler="database_quota_size"/>
+
+ <key name="read-only-database" datatype="boolean"
+ handler="read_only_database"/>
+
+ <key name="zeo-client-name"
+ handler="zeo_client_name"/>
+
+ <section type="eventlog" name="*" attribute="eventlog">
+ <description>
+ Describes the logging performed by zLOG.LOG() calls.
+ </description>
+ </section>
+
+ <section type="logger" name="access"/>
+
+ <section type="logger" name="trace"/>
+
+ <multisection type="server" name="*" attribute="servers"/>
+ <key name="port-base" datatype="integer" default="0">
+ <description>
+ Base port number that gets added to the specific port numbers
+ specified for the individual servers.
+ </description>
+ </key>
+
+ <multisection type="database" name="*" attribute="databases"/>
+
+ <section type="zoperunner" name="*" attribute="runner"/>
+
+</schema>