Removed copied version of python-daemon, now using python 2.6 version from Debian
authorJean-Michel Nirgal Vourgère <jmv@nirgal.com>
Mon, 17 Jan 2011 17:22:21 +0000 (17:22 +0000)
committerJean-Michel Nirgal Vourgère <jmv@nirgal.com>
Mon, 17 Jan 2011 17:22:21 +0000 (17:22 +0000)
INSTALL
bin/daemon/__init__.py [deleted file]
bin/daemon/daemon.py [deleted file]
bin/daemon/pidlockfile.py [deleted file]
bin/daemon/runner.py [deleted file]
bin/daemon/version/__init__.py [deleted file]
bin/daemon/version/version_info.py [deleted file]
bin/inputs/run.py

diff --git a/INSTALL b/INSTALL
index 3f20c323106fbb8229daa6c6583cb44176e378d3..cf8ec2308e6e19f50ec1dfab4f0bf0ea934eb451 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -15,15 +15,12 @@ apache2
 libapache2-mod-python
 python-django
 bzip2
+python-daemon
+ntp
 
 python-decoratedstr (from nirgal.com)
 python-htmlentities (from nirgal.com)
 
-=Recommanded packages
-===================
-ntp
-python-daemon
-
 
 = File system setup
 ===================
diff --git a/bin/daemon/__init__.py b/bin/daemon/__init__.py
deleted file mode 100644 (file)
index d8dc171..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# daemon/__init__.py
-# Part of python-daemon, an implementation of PEP 3143.
-#
-# Copyright © 2009–2010 Ben Finney <ben+python@benfinney.id.au>
-# Copyright © 2006 Robert Niederreiter
-#
-# This is free software: you may copy, modify, and/or distribute this work
-# under the terms of the Python Software Foundation License, version 2 or
-# later as published by the Python Software Foundation.
-# No warranty expressed or implied. See the file LICENSE.PSF-2 for details.
-
-""" Library to implement a well-behaved Unix daemon process.
-
-    This library implements the well-behaved daemon specification of
-    :pep:`3143`, "Standard daemon process library".
-
-    A well-behaved Unix daemon process is tricky to get right, but the
-    required steps are much the same for every daemon program. A
-    `DaemonContext` instance holds the behaviour and configured
-    process environment for the program; use the instance as a context
-    manager to enter a daemon state.
-
-    Simple example of usage::
-
-        import daemon
-
-        from spam import do_main_program
-
-        with daemon.DaemonContext():
-            do_main_program()
-
-    Customisation of the steps to become a daemon is available by
-    setting options on the `DaemonContext` instance; see the
-    documentation for that class for each option.
-
-    """
-
-import version
-from daemon import DaemonContext
-
-\f
-_version = version.version
-_copyright = version.copyright
-_license = version.license
-_url = "http://pypi.python.org/pypi/python-daemon/"
diff --git a/bin/daemon/daemon.py b/bin/daemon/daemon.py
deleted file mode 100644 (file)
index 28db695..0000000
+++ /dev/null
@@ -1,776 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# daemon/daemon.py
-# Part of python-daemon, an implementation of PEP 3143.
-#
-# Copyright © 2008–2010 Ben Finney <ben+python@benfinney.id.au>
-# Copyright © 2007–2008 Robert Niederreiter, Jens Klein
-# Copyright © 2004–2005 Chad J. Schroeder
-# Copyright © 2003 Clark Evans
-# Copyright © 2002 Noah Spurrier
-# Copyright © 2001 Jürgen Hermann
-#
-# This is free software: you may copy, modify, and/or distribute this work
-# under the terms of the Python Software Foundation License, version 2 or
-# later as published by the Python Software Foundation.
-# No warranty expressed or implied. See the file LICENSE.PSF-2 for details.
-
-""" Daemon process behaviour.
-    """
-
-import os
-import sys
-import resource
-import errno
-import signal
-import socket
-import atexit
-
-\f
-class DaemonError(Exception):
-    """ Base exception class for errors from this module. """
-
-
-class DaemonOSEnvironmentError(DaemonError, OSError):
-    """ Exception raised when daemon OS environment setup receives error. """
-
-
-class DaemonProcessDetachError(DaemonError, OSError):
-    """ Exception raised when process detach fails. """
-
-\f
-class DaemonContext(object):
-    """ Context for turning the current program into a daemon process.
-
-        A `DaemonContext` instance represents the behaviour settings and
-        process context for the program when it becomes a daemon. The
-        behaviour and environment is customised by setting options on the
-        instance, before calling the `open` method.
-
-        Each option can be passed as a keyword argument to the `DaemonContext`
-        constructor, or subsequently altered by assigning to an attribute on
-        the instance at any time prior to calling `open`. That is, for
-        options named `wibble` and `wubble`, the following invocation::
-
-            foo = daemon.DaemonContext(wibble=bar, wubble=baz)
-            foo.open()
-
-        is equivalent to::
-
-            foo = daemon.DaemonContext()
-            foo.wibble = bar
-            foo.wubble = baz
-            foo.open()
-
-        The following options are defined.
-
-        `files_preserve`
-            :Default: ``None``
-
-            List of files that should *not* be closed when starting the
-            daemon. If ``None``, all open file descriptors will be closed.
-
-            Elements of the list are file descriptors (as returned by a file
-            object's `fileno()` method) or Python `file` objects. Each
-            specifies a file that is not to be closed during daemon start.
-
-        `chroot_directory`
-            :Default: ``None``
-
-            Full path to a directory to set as the effective root directory of
-            the process. If ``None``, specifies that the root directory is not
-            to be changed.
-
-        `working_directory`
-            :Default: ``'/'``
-
-            Full path of the working directory to which the process should
-            change on daemon start.
-
-            Since a filesystem cannot be unmounted if a process has its
-            current working directory on that filesystem, this should either
-            be left at default or set to a directory that is a sensible “home
-            directory” for the daemon while it is running.
-
-        `umask`
-            :Default: ``0``
-
-            File access creation mask (“umask”) to set for the process on
-            daemon start.
-
-            Since a process inherits its umask from its parent process,
-            starting the daemon will reset the umask to this value so that
-            files are created by the daemon with access modes as it expects.
-
-        `pidfile`
-            :Default: ``None``
-
-            Context manager for a PID lock file. When the daemon context opens
-            and closes, it enters and exits the `pidfile` context manager.
-
-        `detach_process`
-            :Default: ``None``
-
-            If ``True``, detach the process context when opening the daemon
-            context; if ``False``, do not detach.
-
-            If unspecified (``None``) during initialisation of the instance,
-            this will be set to ``True`` by default, and ``False`` only if
-            detaching the process is determined to be redundant; for example,
-            in the case when the process was started by `init`, by `initd`, or
-            by `inetd`.
-
-        `signal_map`
-            :Default: system-dependent
-
-            Mapping from operating system signals to callback actions.
-
-            The mapping is used when the daemon context opens, and determines
-            the action for each signal's signal handler:
-
-            * A value of ``None`` will ignore the signal (by setting the
-              signal action to ``signal.SIG_IGN``).
-
-            * A string value will be used as the name of an attribute on the
-              ``DaemonContext`` instance. The attribute's value will be used
-              as the action for the signal handler.
-
-            * Any other value will be used as the action for the
-              signal handler. See the ``signal.signal`` documentation
-              for details of the signal handler interface.
-
-            The default value depends on which signals are defined on the
-            running system. Each item from the list below whose signal is
-            actually defined in the ``signal`` module will appear in the
-            default map:
-
-            * ``signal.SIGTTIN``: ``None``
-
-            * ``signal.SIGTTOU``: ``None``
-
-            * ``signal.SIGTSTP``: ``None``
-
-            * ``signal.SIGTERM``: ``'terminate'``
-
-            Depending on how the program will interact with its child
-            processes, it may need to specify a signal map that
-            includes the ``signal.SIGCHLD`` signal (received when a
-            child process exits). See the specific operating system's
-            documentation for more detail on how to determine what
-            circumstances dictate the need for signal handlers.
-
-        `uid`
-            :Default: ``os.getuid()``
-
-        `gid`
-            :Default: ``os.getgid()``
-
-            The user ID (“UID”) value and group ID (“GID”) value to switch
-            the process to on daemon start.
-
-            The default values, the real UID and GID of the process, will
-            relinquish any effective privilege elevation inherited by the
-            process.
-
-        `prevent_core`
-            :Default: ``True``
-
-            If true, prevents the generation of core files, in order to avoid
-            leaking sensitive information from daemons run as `root`.
-
-        `stdin`
-            :Default: ``None``
-
-        `stdout`
-            :Default: ``None``
-
-        `stderr`
-            :Default: ``None``
-
-            Each of `stdin`, `stdout`, and `stderr` is a file-like object
-            which will be used as the new file for the standard I/O stream
-            `sys.stdin`, `sys.stdout`, and `sys.stderr` respectively. The file
-            should therefore be open, with a minimum of mode 'r' in the case
-            of `stdin`, and mode 'w+' in the case of `stdout` and `stderr`.
-
-            If the object has a `fileno()` method that returns a file
-            descriptor, the corresponding file will be excluded from being
-            closed during daemon start (that is, it will be treated as though
-            it were listed in `files_preserve`).
-
-            If ``None``, the corresponding system stream is re-bound to the
-            file named by `os.devnull`.
-
-        """
-
-    def __init__(
-        self,
-        chroot_directory=None,
-        working_directory='/',
-        umask=0,
-        uid=None,
-        gid=None,
-        prevent_core=True,
-        detach_process=None,
-        files_preserve=None,
-        pidfile=None,
-        stdin=None,
-        stdout=None,
-        stderr=None,
-        signal_map=None,
-        ):
-        """ Set up a new instance. """
-        self.chroot_directory = chroot_directory
-        self.working_directory = working_directory
-        self.umask = umask
-        self.prevent_core = prevent_core
-        self.files_preserve = files_preserve
-        self.pidfile = pidfile
-        self.stdin = stdin
-        self.stdout = stdout
-        self.stderr = stderr
-
-        if uid is None:
-            uid = os.getuid()
-        self.uid = uid
-        if gid is None:
-            gid = os.getgid()
-        self.gid = gid
-
-        if detach_process is None:
-            detach_process = is_detach_process_context_required()
-        self.detach_process = detach_process
-
-        if signal_map is None:
-            signal_map = make_default_signal_map()
-        self.signal_map = signal_map
-
-        self._is_open = False
-
-    @property
-    def is_open(self):
-        """ ``True`` if the instance is currently open. """
-        return self._is_open
-
-    def open(self):
-        """ Become a daemon process.
-            :Return: ``None``
-
-            Open the daemon context, turning the current program into a daemon
-            process. This performs the following steps:
-
-            * If this instance's `is_open` property is true, return
-              immediately. This makes it safe to call `open` multiple times on
-              an instance.
-
-            * If the `prevent_core` attribute is true, set the resource limits
-              for the process to prevent any core dump from the process.
-
-            * If the `chroot_directory` attribute is not ``None``, set the
-              effective root directory of the process to that directory (via
-              `os.chroot`).
-
-              This allows running the daemon process inside a “chroot gaol”
-              as a means of limiting the system's exposure to rogue behaviour
-              by the process. Note that the specified directory needs to
-              already be set up for this purpose.
-
-            * Set the process UID and GID to the `uid` and `gid` attribute
-              values.
-
-            * Close all open file descriptors. This excludes those listed in
-              the `files_preserve` attribute, and those that correspond to the
-              `stdin`, `stdout`, or `stderr` attributes.
-
-            * Change current working directory to the path specified by the
-              `working_directory` attribute.
-
-            * Reset the file access creation mask to the value specified by
-              the `umask` attribute.
-
-            * If the `detach_process` option is true, detach the current
-              process into its own process group, and disassociate from any
-              controlling terminal.
-
-            * Set signal handlers as specified by the `signal_map` attribute.
-
-            * If any of the attributes `stdin`, `stdout`, `stderr` are not
-              ``None``, bind the system streams `sys.stdin`, `sys.stdout`,
-              and/or `sys.stderr` to the files represented by the
-              corresponding attributes. Where the attribute has a file
-              descriptor, the descriptor is duplicated (instead of re-binding
-              the name).
-
-            * If the `pidfile` attribute is not ``None``, enter its context
-              manager.
-
-            * Mark this instance as open (for the purpose of future `open` and
-              `close` calls).
-
-            * Register the `close` method to be called during Python's exit
-              processing.
-
-            When the function returns, the running program is a daemon
-            process.
-
-            """
-        if self.is_open:
-            return
-
-        if self.chroot_directory is not None:
-            change_root_directory(self.chroot_directory)
-
-        if self.prevent_core:
-            prevent_core_dump()
-
-        change_file_creation_mask(self.umask)
-        change_working_directory(self.working_directory)
-        change_process_owner(self.uid, self.gid)
-
-        if self.detach_process:
-            detach_process_context()
-
-        signal_handler_map = self._make_signal_handler_map()
-        set_signal_handlers(signal_handler_map)
-
-        exclude_fds = self._get_exclude_file_descriptors()
-        close_all_open_files(exclude=exclude_fds)
-
-        redirect_stream(sys.stdin, self.stdin)
-        redirect_stream(sys.stdout, self.stdout)
-        redirect_stream(sys.stderr, self.stderr)
-
-        if self.pidfile is not None:
-            self.pidfile.__enter__()
-
-        self._is_open = True
-
-        register_atexit_function(self.close)
-
-    def __enter__(self):
-        """ Context manager entry point. """
-        self.open()
-        return self
-
-    def close(self):
-        """ Exit the daemon process context.
-            :Return: ``None``
-
-            Close the daemon context. This performs the following steps:
-
-            * If this instance's `is_open` property is false, return
-              immediately. This makes it safe to call `close` multiple times
-              on an instance.
-
-            * If the `pidfile` attribute is not ``None``, exit its context
-              manager.
-
-            * Mark this instance as closed (for the purpose of future `open`
-              and `close` calls).
-
-            """
-        if not self.is_open:
-            return
-
-        if self.pidfile is not None:
-            # Follow the interface for telling a context manager to exit,
-            # <URL:http://docs.python.org/library/stdtypes.html#typecontextmanager>.
-            self.pidfile.__exit__(None, None, None)
-
-        self._is_open = False
-
-    def __exit__(self, exc_type, exc_value, traceback):
-        """ Context manager exit point. """
-        self.close()
-
-    def terminate(self, signal_number, stack_frame):
-        """ Signal handler for end-process signals.
-            :Return: ``None``
-
-            Signal handler for the ``signal.SIGTERM`` signal. Performs the
-            following step:
-
-            * Raise a ``SystemExit`` exception explaining the signal.
-
-            """
-        exception = SystemExit(
-            "Terminating on signal %(signal_number)r"
-                % vars())
-        raise exception
-
-    def _get_exclude_file_descriptors(self):
-        """ Return the set of file descriptors to exclude closing.
-
-            Returns a set containing the file descriptors for the
-            items in `files_preserve`, and also each of `stdin`,
-            `stdout`, and `stderr`:
-
-            * If the item is ``None``, it is omitted from the return
-              set.
-
-            * If the item has a ``fileno()`` method, that method's
-              return value is in the return set.
-
-            * Otherwise, the item is in the return set verbatim.
-
-            """
-        files_preserve = self.files_preserve
-        if files_preserve is None:
-            files_preserve = []
-        files_preserve.extend(
-            item for item in [self.stdin, self.stdout, self.stderr]
-            if hasattr(item, 'fileno'))
-        exclude_descriptors = set()
-        for item in files_preserve:
-            if item is None:
-                continue
-            if hasattr(item, 'fileno'):
-                exclude_descriptors.add(item.fileno())
-            else:
-                exclude_descriptors.add(item)
-        return exclude_descriptors
-
-    def _make_signal_handler(self, target):
-        """ Make the signal handler for a specified target object.
-
-            If `target` is ``None``, returns ``signal.SIG_IGN``. If
-            `target` is a string, returns the attribute of this
-            instance named by that string. Otherwise, returns `target`
-            itself.
-
-            """
-        if target is None:
-            result = signal.SIG_IGN
-        elif isinstance(target, basestring):
-            name = target
-            result = getattr(self, name)
-        else:
-            result = target
-
-        return result
-
-    def _make_signal_handler_map(self):
-        """ Make the map from signals to handlers for this instance.
-
-            Constructs a map from signal numbers to handlers for this
-            context instance, suitable for passing to
-            `set_signal_handlers`.
-
-            """
-        signal_handler_map = dict(
-            (signal_number, self._make_signal_handler(target))
-            for (signal_number, target) in self.signal_map.items())
-        return signal_handler_map
-
-\f
-def change_working_directory(directory):
-    """ Change the working directory of this process.
-        """
-    try:
-        os.chdir(directory)
-    except Exception, exc:
-        error = DaemonOSEnvironmentError(
-            "Unable to change working directory (%(exc)s)"
-            % vars())
-        raise error
-
-
-def change_root_directory(directory):
-    """ Change the root directory of this process.
-
-        Sets the current working directory, then the process root
-        directory, to the specified `directory`. Requires appropriate
-        OS privileges for this process.
-
-        """
-    try:
-        os.chdir(directory)
-        os.chroot(directory)
-    except Exception, exc:
-        error = DaemonOSEnvironmentError(
-            "Unable to change root directory (%(exc)s)"
-            % vars())
-        raise error
-
-
-def change_file_creation_mask(mask):
-    """ Change the file creation mask for this process.
-        """
-    try:
-        os.umask(mask)
-    except Exception, exc:
-        error = DaemonOSEnvironmentError(
-            "Unable to change file creation mask (%(exc)s)"
-            % vars())
-        raise error
-
-
-def change_process_owner(uid, gid):
-    """ Change the owning UID and GID of this process.
-
-        Sets the GID then the UID of the process (in that order, to
-        avoid permission errors) to the specified `gid` and `uid`
-        values. Requires appropriate OS privileges for this process.
-
-        """
-    try:
-        os.setgid(gid)
-        os.setuid(uid)
-    except Exception, exc:
-        error = DaemonOSEnvironmentError(
-            "Unable to change file creation mask (%(exc)s)"
-            % vars())
-        raise error
-
-\f
-def prevent_core_dump():
-    """ Prevent this process from generating a core dump.
-
-        Sets the soft and hard limits for core dump size to zero. On
-        Unix, this prevents the process from creating core dump
-        altogether.
-
-        """
-    core_resource = resource.RLIMIT_CORE
-
-    try:
-        # Ensure the resource limit exists on this platform, by requesting
-        # its current value
-        core_limit_prev = resource.getrlimit(core_resource)
-    except ValueError, exc:
-        error = DaemonOSEnvironmentError(
-            "System does not support RLIMIT_CORE resource limit (%(exc)s)"
-            % vars())
-        raise error
-
-    # Set hard and soft limits to zero, i.e. no core dump at all
-    core_limit = (0, 0)
-    resource.setrlimit(core_resource, core_limit)
-
-\f
-def detach_process_context():
-    """ Detach the process context from parent and session.
-
-        Detach from the parent process and session group, allowing the
-        parent to exit while this process continues running.
-
-        Reference: “Advanced Programming in the Unix Environment”,
-        section 13.3, by W. Richard Stevens, published 1993 by
-        Addison-Wesley.
-    
-        """
-
-    def fork_then_exit_parent(error_message):
-        """ Fork a child process, then exit the parent process.
-
-            If the fork fails, raise a ``DaemonProcessDetachError``
-            with ``error_message``.
-
-            """
-        try:
-            pid = os.fork()
-            if pid > 0:
-                os._exit(0)
-        except OSError, exc:
-            exc_errno = exc.errno
-            exc_strerror = exc.strerror
-            error = DaemonProcessDetachError(
-                "%(error_message)s: [%(exc_errno)d] %(exc_strerror)s" % vars())
-            raise error
-
-    fork_then_exit_parent(error_message="Failed first fork")
-    os.setsid()
-    fork_then_exit_parent(error_message="Failed second fork")
-
-\f
-def is_process_started_by_init():
-    """ Determine if the current process is started by `init`.
-
-        The `init` process has the process ID of 1; if that is our
-        parent process ID, return ``True``, otherwise ``False``.
-    
-        """
-    result = False
-
-    init_pid = 1
-    if os.getppid() == init_pid:
-        result = True
-
-    return result
-
-
-def is_socket(fd):
-    """ Determine if the file descriptor is a socket.
-
-        Return ``False`` if querying the socket type of `fd` raises an
-        error; otherwise return ``True``.
-
-        """
-    result = False
-
-    file_socket = socket.fromfd(fd, socket.AF_INET, socket.SOCK_RAW)
-
-    try:
-        socket_type = file_socket.getsockopt(
-            socket.SOL_SOCKET, socket.SO_TYPE)
-    except socket.error, exc:
-        exc_errno = exc.args[0]
-        if exc_errno == errno.ENOTSOCK:
-            # Socket operation on non-socket
-            pass
-        else:
-            # Some other socket error
-            result = True
-    else:
-        # No error getting socket type
-        result = True
-
-    return result
-
-
-def is_process_started_by_superserver():
-    """ Determine if the current process is started by the superserver.
-
-        The internet superserver creates a network socket, and
-        attaches it to the standard streams of the child process. If
-        that is the case for this process, return ``True``, otherwise
-        ``False``.
-    
-        """
-    result = False
-
-    stdin_fd = sys.__stdin__.fileno()
-    if is_socket(stdin_fd):
-        result = True
-
-    return result
-
-
-def is_detach_process_context_required():
-    """ Determine whether detaching process context is required.
-
-        Return ``True`` if the process environment indicates the
-        process is already detached:
-
-        * Process was started by `init`; or
-
-        * Process was started by `inetd`.
-
-        """
-    result = True
-    if is_process_started_by_init() or is_process_started_by_superserver():
-        result = False
-
-    return result
-
-\f
-def close_file_descriptor_if_open(fd):
-    """ Close a file descriptor if already open.
-
-        Close the file descriptor `fd`, suppressing an error in the
-        case the file was not open.
-
-        """
-    try:
-        os.close(fd)
-    except OSError, exc:
-        if exc.errno == errno.EBADF:
-            # File descriptor was not open
-            pass
-        else:
-            error = DaemonOSEnvironmentError(
-                "Failed to close file descriptor %(fd)d"
-                " (%(exc)s)"
-                % vars())
-            raise error
-
-
-MAXFD = 2048
-
-def get_maximum_file_descriptors():
-    """ Return the maximum number of open file descriptors for this process.
-
-        Return the process hard resource limit of maximum number of
-        open file descriptors. If the limit is “infinity”, a default
-        value of ``MAXFD`` is returned.
-
-        """
-    limits = resource.getrlimit(resource.RLIMIT_NOFILE)
-    result = limits[1]
-    if result == resource.RLIM_INFINITY:
-        result = MAXFD
-    return result
-
-
-def close_all_open_files(exclude=set()):
-    """ Close all open file descriptors.
-
-        Closes every file descriptor (if open) of this process. If
-        specified, `exclude` is a set of file descriptors to *not*
-        close.
-
-        """
-    maxfd = get_maximum_file_descriptors()
-    for fd in reversed(range(maxfd)):
-        if fd not in exclude:
-            close_file_descriptor_if_open(fd)
-
-\f
-def redirect_stream(system_stream, target_stream):
-    """ Redirect a system stream to a specified file.
-
-        `system_stream` is a standard system stream such as
-        ``sys.stdout``. `target_stream` is an open file object that
-        should replace the corresponding system stream object.
-
-        If `target_stream` is ``None``, defaults to opening the
-        operating system's null device and using its file descriptor.
-
-        """
-    if target_stream is None:
-        target_fd = os.open(os.devnull, os.O_RDWR)
-    else:
-        target_fd = target_stream.fileno()
-    os.dup2(target_fd, system_stream.fileno())
-
-\f
-def make_default_signal_map():
-    """ Make the default signal map for this system.
-
-        The signals available differ by system. The map will not
-        contain any signals not defined on the running system.
-
-        """
-    name_map = {
-        'SIGTSTP': None,
-        'SIGTTIN': None,
-        'SIGTTOU': None,
-        'SIGTERM': 'terminate',
-        }
-    signal_map = dict(
-        (getattr(signal, name), target)
-        for (name, target) in name_map.items()
-        if hasattr(signal, name))
-
-    return signal_map
-
-
-def set_signal_handlers(signal_handler_map):
-    """ Set the signal handlers as specified.
-
-        The `signal_handler_map` argument is a map from signal number
-        to signal handler. See the `signal` module for details.
-
-        """
-    for (signal_number, handler) in signal_handler_map.items():
-        signal.signal(signal_number, handler)
-
-
-def register_atexit_function(func):
-    """ Register a function for processing at program exit.
-
-        The function `func` is registered for a call with no arguments
-        at program exit.
-
-        """
-    atexit.register(func)
diff --git a/bin/daemon/pidlockfile.py b/bin/daemon/pidlockfile.py
deleted file mode 100644 (file)
index c38beae..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# daemon/pidlockfile.py
-# Part of python-daemon, an implementation of PEP 3143.
-#
-# Copyright © 2008–2010 Ben Finney <ben+python@benfinney.id.au>
-#
-# This is free software: you may copy, modify, and/or distribute this work
-# under the terms of the Python Software Foundation License, version 2 or
-# later as published by the Python Software Foundation.
-# No warranty expressed or implied. See the file LICENSE.PSF-2 for details.
-
-""" Lockfile behaviour implemented via Unix PID files.
-    """
-
-import os
-import errno
-
-from lockfile import (
-    LinkFileLock,
-    AlreadyLocked, LockFailed,
-    NotLocked, NotMyLock,
-    )
-
-\f
-class PIDFileError(Exception):
-    """ Abstract base class for errors specific to PID files. """
-
-class PIDFileParseError(ValueError, PIDFileError):
-    """ Raised when parsing contents of PID file fails. """
-
-\f
-class PIDLockFile(LinkFileLock, object):
-    """ Lockfile implemented as a Unix PID file.
-
-        The PID file is named by the attribute `path`. When locked,
-        the file will be created with a single line of text,
-        containing the process ID (PID) of the process that acquired
-        the lock.
-
-        The lock is acquired and maintained as per `LinkFileLock`.
-
-        """
-
-    def read_pid(self):
-        """ Get the PID from the lock file.
-            """
-        result = read_pid_from_pidfile(self.path)
-        return result
-
-    def acquire(self, *args, **kwargs):
-        """ Acquire the lock.
-
-            Locks the PID file then creates the PID file for this
-            lock. The `timeout` parameter is used as for the
-            `LinkFileLock` class.
-
-            """
-        super(PIDLockFile, self).acquire(*args, **kwargs)
-        try:
-            write_pid_to_pidfile(self.path)
-        except OSError, exc:
-            error = LockFailed("%(exc)s" % vars())
-            raise error
-
-    def release(self):
-        """ Release the lock.
-
-            Removes the PID file then releases the lock, or raises an
-            error if the current process does not hold the lock.
-
-            """
-        if self.i_am_locking():
-            remove_existing_pidfile(self.path)
-        super(PIDLockFile, self).release()
-
-    def break_lock(self):
-        """ Break an existing lock.
-
-            If the lock is held, breaks the lock and removes the PID
-            file.
-
-            """
-        super(PIDLockFile, self).break_lock()
-        remove_existing_pidfile(self.path)
-
-\f
-class TimeoutPIDLockFile(PIDLockFile):
-    """ Lockfile with default timeout, implemented as a Unix PID file.
-
-        This uses the ``PIDLockFile`` implementation, with the
-        following changes:
-
-        * The `acquire_timeout` parameter to the initialiser will be
-          used as the default `timeout` parameter for the `acquire`
-          method.
-
-        """
-
-    def __init__(self, path, acquire_timeout=None, *args, **kwargs):
-        """ Set up the parameters of a DaemonRunnerLock. """
-        self.acquire_timeout = acquire_timeout
-        super(TimeoutPIDLockFile, self).__init__(path, *args, **kwargs)
-
-    def acquire(self, timeout=None, *args, **kwargs):
-        """ Acquire the lock. """
-        if timeout is None:
-            timeout = self.acquire_timeout
-        super(TimeoutPIDLockFile, self).acquire(timeout, *args, **kwargs)
-
-\f
-def read_pid_from_pidfile(pidfile_path):
-    """ Read the PID recorded in the named PID file.
-
-        Read and return the numeric PID recorded as text in the named
-        PID file. If the PID file does not exist, return ``None``. If
-        the content is not a valid PID, raise ``PIDFileParseError``.
-
-        """
-    pid = None
-    pidfile = None
-    try:
-        pidfile = open(pidfile_path, 'r')
-    except IOError, exc:
-        if exc.errno == errno.ENOENT:
-            pass
-        else:
-            raise
-
-    if pidfile:
-        # According to the FHS 2.3 section on PID files in ‘/var/run’:
-        #
-        #   The file must consist of the process identifier in
-        #   ASCII-encoded decimal, followed by a newline character. …
-        #
-        #   Programs that read PID files should be somewhat flexible
-        #   in what they accept; i.e., they should ignore extra
-        #   whitespace, leading zeroes, absence of the trailing
-        #   newline, or additional lines in the PID file.
-
-        line = pidfile.readline().strip()
-        try:
-            pid = int(line)
-        except ValueError:
-            raise PIDFileParseError(
-                "PID file %(pidfile_path)r contents invalid" % vars())
-        pidfile.close()
-
-    return pid
-
-
-def write_pid_to_pidfile(pidfile_path):
-    """ Write the PID in the named PID file.
-
-        Get the numeric process ID (“PID”) of the current process
-        and write it to the named file as a line of text.
-
-        """
-    open_flags = (os.O_CREAT | os.O_EXCL | os.O_WRONLY)
-    open_mode = (
-        ((os.R_OK | os.W_OK) << 6) |
-        ((os.R_OK) << 3) |
-        ((os.R_OK)))
-    pidfile_fd = os.open(pidfile_path, open_flags, open_mode)
-    pidfile = os.fdopen(pidfile_fd, 'w')
-
-    # According to the FHS 2.3 section on PID files in ‘/var/run’:
-    #
-    #   The file must consist of the process identifier in
-    #   ASCII-encoded decimal, followed by a newline character. For
-    #   example, if crond was process number 25, /var/run/crond.pid
-    #   would contain three characters: two, five, and newline.
-
-    pid = os.getpid()
-    line = "%(pid)d\n" % vars()
-    pidfile.write(line)
-    pidfile.close()
-
-
-def remove_existing_pidfile(pidfile_path):
-    """ Remove the named PID file if it exists.
-
-        Remove the named PID file. Ignore the condition if the file
-        does not exist, since that only means we are already in the
-        desired state.
-
-        """
-    try:
-        os.remove(pidfile_path)
-    except OSError, exc:
-        if exc.errno == errno.ENOENT:
-            pass
-        else:
-            raise
diff --git a/bin/daemon/runner.py b/bin/daemon/runner.py
deleted file mode 100644 (file)
index 0642695..0000000
+++ /dev/null
@@ -1,229 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# daemon/runner.py
-# Part of python-daemon, an implementation of PEP 3143.
-#
-# Copyright © 2009–2010 Ben Finney <ben+python@benfinney.id.au>
-# Copyright © 2007–2008 Robert Niederreiter, Jens Klein
-# Copyright © 2003 Clark Evans
-# Copyright © 2002 Noah Spurrier
-# Copyright © 2001 Jürgen Hermann
-#
-# This is free software: you may copy, modify, and/or distribute this work
-# under the terms of the Python Software Foundation License, version 2 or
-# later as published by the Python Software Foundation.
-# No warranty expressed or implied. See the file LICENSE.PSF-2 for details.
-
-""" Daemon runner library.
-    """
-
-import sys
-import os
-import signal
-import errno
-
-import pidlockfile
-
-from daemon import DaemonContext
-
-\f
-class DaemonRunnerError(Exception):
-    """ Abstract base class for errors from DaemonRunner. """
-
-class DaemonRunnerInvalidActionError(ValueError, DaemonRunnerError):
-    """ Raised when specified action for DaemonRunner is invalid. """
-
-class DaemonRunnerStartFailureError(RuntimeError, DaemonRunnerError):
-    """ Raised when failure starting DaemonRunner. """
-
-class DaemonRunnerStopFailureError(RuntimeError, DaemonRunnerError):
-    """ Raised when failure stopping DaemonRunner. """
-
-\f
-class DaemonRunner(object):
-    """ Controller for a callable running in a separate background process.
-
-        The first command-line argument is the action to take:
-
-        * 'start': Become a daemon and call `app.run()`.
-        * 'stop': Exit the daemon process specified in the PID file.
-        * 'restart': Stop, then start.
-
-        """
-
-    start_message = "started with pid %(pid)d"
-
-    def __init__(self, app):
-        """ Set up the parameters of a new runner.
-
-            The `app` argument must have the following attributes:
-
-            * `stdin_path`, `stdout_path`, `stderr_path`: Filesystem
-              paths to open and replace the existing `sys.stdin`,
-              `sys.stdout`, `sys.stderr`.
-
-            * `pidfile_path`: Absolute filesystem path to a file that
-              will be used as the PID file for the daemon. If
-              ``None``, no PID file will be used.
-
-            * `pidfile_timeout`: Used as the default acquisition
-              timeout value supplied to the runner's PID lock file.
-
-            * `run`: Callable that will be invoked when the daemon is
-              started.
-            
-            """
-        self.parse_args()
-        self.app = app
-        self.daemon_context = DaemonContext()
-        self.daemon_context.stdin = open(app.stdin_path, 'r')
-        self.daemon_context.stdout = open(app.stdout_path, 'w+')
-        self.daemon_context.stderr = open(
-            app.stderr_path, 'w+', buffering=0)
-
-        self.pidfile = None
-        if app.pidfile_path is not None:
-            self.pidfile = make_pidlockfile(
-                app.pidfile_path, app.pidfile_timeout)
-        self.daemon_context.pidfile = self.pidfile
-
-    def _usage_exit(self, argv):
-        """ Emit a usage message, then exit.
-            """
-        progname = os.path.basename(argv[0])
-        usage_exit_code = 2
-        action_usage = "|".join(self.action_funcs.keys())
-        message = "usage: %(progname)s %(action_usage)s" % vars()
-        emit_message(message)
-        sys.exit(usage_exit_code)
-
-    def parse_args(self, argv=None):
-        """ Parse command-line arguments.
-            """
-        if argv is None:
-            argv = sys.argv
-
-        min_args = 2
-        if len(argv) < min_args:
-            self._usage_exit(argv)
-
-        self.action = argv[1]
-        if self.action not in self.action_funcs:
-            self._usage_exit(argv)
-
-    def _start(self):
-        """ Open the daemon context and run the application.
-            """
-        if is_pidfile_stale(self.pidfile):
-            self.pidfile.break_lock()
-
-        try:
-            self.daemon_context.open()
-        except pidlockfile.AlreadyLocked:
-            pidfile_path = self.pidfile.path
-            raise DaemonRunnerStartFailureError(
-                "PID file %(pidfile_path)r already locked" % vars())
-
-        pid = os.getpid()
-        message = self.start_message % vars()
-        emit_message(message)
-
-        self.app.run()
-
-    def _terminate_daemon_process(self):
-        """ Terminate the daemon process specified in the current PID file.
-            """
-        pid = self.pidfile.read_pid()
-        try:
-            os.kill(pid, signal.SIGTERM)
-        except OSError, exc:
-            raise DaemonRunnerStopFailureError(
-                "Failed to terminate %(pid)d: %(exc)s" % vars())
-
-    def _stop(self):
-        """ Exit the daemon process specified in the current PID file.
-            """
-        if not self.pidfile.is_locked():
-            pidfile_path = self.pidfile.path
-            raise DaemonRunnerStopFailureError(
-                "PID file %(pidfile_path)r not locked" % vars())
-
-        if is_pidfile_stale(self.pidfile):
-            self.pidfile.break_lock()
-        else:
-            self._terminate_daemon_process()
-
-    def _restart(self):
-        """ Stop, then start.
-            """
-        self._stop()
-        self._start()
-
-    action_funcs = {
-        'start': _start,
-        'stop': _stop,
-        'restart': _restart,
-        }
-
-    def _get_action_func(self):
-        """ Return the function for the specified action.
-
-            Raises ``DaemonRunnerInvalidActionError`` if the action is
-            unknown.
-
-            """
-        try:
-            func = self.action_funcs[self.action]
-        except KeyError:
-            raise DaemonRunnerInvalidActionError(
-                "Unknown action: %(action)r" % vars(self))
-        return func
-
-    def do_action(self):
-        """ Perform the requested action.
-            """
-        func = self._get_action_func()
-        func(self)
-
-
-def emit_message(message, stream=None):
-    """ Emit a message to the specified stream (default `sys.stderr`). """
-    if stream is None:
-        stream = sys.stderr
-    stream.write("%(message)s\n" % vars())
-    stream.flush()
-
-
-def make_pidlockfile(path, acquire_timeout):
-    """ Make a PIDLockFile instance with the given filesystem path. """
-    if not isinstance(path, basestring):
-        error = ValueError("Not a filesystem path: %(path)r" % vars())
-        raise error
-    if not os.path.isabs(path):
-        error = ValueError("Not an absolute path: %(path)r" % vars())
-        raise error
-    lockfile = pidlockfile.TimeoutPIDLockFile(path, acquire_timeout)
-
-    return lockfile
-
-
-def is_pidfile_stale(pidfile):
-    """ Determine whether a PID file is stale.
-
-        Return ``True`` (“stale”) if the contents of the PID file are
-        valid but do not match the PID of a currently-running process;
-        otherwise return ``False``.
-
-        """
-    result = False
-
-    pidfile_pid = pidfile.read_pid()
-    if pidfile_pid is not None:
-        try:
-            os.kill(pidfile_pid, signal.SIG_DFL)
-        except OSError, exc:
-            if exc.errno == errno.ESRCH:
-                # The specified PID does not exist
-                result = True
-
-    return result
diff --git a/bin/daemon/version/__init__.py b/bin/daemon/version/__init__.py
deleted file mode 100644 (file)
index d2eafa6..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# daemon/version/__init__.py
-# Part of python-daemon, an implementation of PEP 3143.
-#
-# Copyright © 2008–2010 Ben Finney <ben+python@benfinney.id.au>
-# This is free software: you may copy, modify, and/or distribute this work
-# under the terms of the Python Software Foundation License, version 2 or
-# later as published by the Python Software Foundation.
-# No warranty expressed or implied. See the file LICENSE.PSF-2 for details.
-
-""" Version information for the python-daemon distribution. """
-
-from version_info import version_info
-
-version_info['version_string'] = u"1.5.5"
-
-version_short = u"%(version_string)s" % version_info
-version_full = u"%(version_string)s.r%(revno)s" % version_info
-version = version_short
-
-author_name = u"Ben Finney"
-author_email = u"ben+python@benfinney.id.au"
-author = u"%(author_name)s <%(author_email)s>" % vars()
-
-copyright_year_begin = u"2001"
-date = version_info['date'].split(' ', 1)[0]
-copyright_year = date.split('-')[0]
-copyright_year_range = copyright_year_begin
-if copyright_year > copyright_year_begin:
-    copyright_year_range += u"–%(copyright_year)s" % vars()
-
-copyright = (
-    u"Copyright © %(copyright_year_range)s %(author)s and others"
-    ) % vars()
-license = u"PSF-2+"
diff --git a/bin/daemon/version/version_info.py b/bin/daemon/version/version_info.py
deleted file mode 100644 (file)
index cdbf280..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/usr/bin/env python
-"""This file is automatically generated by generate_version_info
-It uses the current working tree to determine the revision.
-So don't edit it. :)
-"""
-
-version_info = {'branch_nick': u'python-daemon.devel',
- 'build_date': '2009-05-22 19:50:06 +1000',
- 'clean': None,
- 'date': '2009-05-22 19:47:30 +1000',
- 'revision_id': 'ben+python@benfinney.id.au-20090522094730-p4vsa0reh7ktt4e1',
- 'revno': 145}
-
-revisions = {}
-
-file_revisions = {}
-
-
-
-if __name__ == '__main__':
-    print 'revision: %(revno)d' % version_info
-    print 'nick: %(branch_nick)s' % version_info
-    print 'revision id: %(revision_id)s' % version_info
index c14e21e2e853be21356f2a3fdacac620dd5c5128..461036555083e1d91c19eb8c2e2287b83f7d209b 100644 (file)
@@ -21,34 +21,7 @@ from ais.inputs.tcpout import TcpOutService
 from ais.gpsdec import AivdmProcessor
 
 
-def main():
-    from optparse import OptionParser
-    parser = OptionParser('%prog [options] SOURCE*')
-    parser.add_option('-d', '--debug',
-        help='Debug mode',
-        action='store_true', dest='debug', default=False)
-    parser.add_option('--stdout',
-        help="Print incoming packets to stdout",
-        action='store_true', dest='stdout', default=False)
-    parser.add_option('--background',
-        help='Run in the background',
-        action='store_true', dest='daemonize', default=False)
-    parser.add_option('--db',
-        help='Process packets locally',
-        action='store_true', dest='todb', default=False)
-    options, args = parser.parse_args()
-
-
-    if options.daemonize:
-        try:
-            from daemon import DaemonContext
-        except ImportError:
-            from ais.daemon import DaemonContext
-
-        stderr = file('/var/log/ais/daemon.stderr', 'w+', 0664)
-        dctx = DaemonContext(stdout=stderr, stderr=stderr, umask=002)
-        dctx.open()
-
+def mainloop(options, args):
     if options.debug:
         loglevel = logging.DEBUG
     else:
@@ -60,7 +33,7 @@ def main():
     # create file handler which logs even debug messages
     #utc=True is python 2.6 specific
     #fh = logging.handlers.TimedRotatingFileHandler('/var/log/ais/daemon', when='D', backupCount=7, utc=True)
-    fh = logging.handlers.TimedRotatingFileHandler('/var/log/ais/daemon', when='D', backupCount=7)
+    fh = logging.handlers.TimedRotatingFileHandler('/var/log/ais/daemon', when='D', backupCount=7, utc=True)
     #fh.setLevel(logging.DEBUG)
 
     # create console handler with a higher log level
@@ -163,5 +136,33 @@ def main():
         logging.critical('Received SIGINT. Shuting down.')
         raise
 
+def main():
+    from optparse import OptionParser
+    parser = OptionParser('%prog [options] SOURCE*')
+    parser.add_option('-d', '--debug',
+        help='Debug mode',
+        action='store_true', dest='debug', default=False)
+    parser.add_option('--stdout',
+        help="Print incoming packets to stdout",
+        action='store_true', dest='stdout', default=False)
+    parser.add_option('--background',
+        help='Run in the background',
+        action='store_true', dest='daemonize', default=False)
+    parser.add_option('--db',
+        help='Process packets locally',
+        action='store_true', dest='todb', default=False)
+    options, args = parser.parse_args()
+
+
+    if options.daemonize:
+        from daemon import DaemonContext
+        #import lockfile
+        stderr = file('/var/log/ais/daemon.stderr', 'w+', 0664)
+        #pidfile = lockfile.FileLock('/var/run/ais/input.pid')
+        with DaemonContext(stdout=stderr, stderr=stderr, umask=002):#, pidfile=pidfile):
+            mainloop(options, args)
+    else:
+        mainloop(options, args)
+
 if __name__ == '__main__':
     main()