#!/usr/bin/env python # # $Id$ # # Copyright (C) 2015-2016 Parsons Government Services ("PARSONS") # Portions copyright (C) 2014 Dragon Research Labs ("DRL") # Portions copyright (C) 2013 Internet Systems Consortium ("ISC") # # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notices and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND PARSONS, DRL, AND ISC DISCLAIM # ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL # PARSONS, DRL, OR ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS # OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. """ Cron job for rcynic and rpki-rtr in stock configuration. Locking code here works like FreeBSD's lockf(1) utility given -k and -t 0 options, which is both the sanest and simplest combination for our purposes. In theory this is portable to any Unix-like system. """ import os import sys import fcntl import errno import rpki.autoconf def run(*cmd, **kwargs): cwd = kwargs.pop("cwd", None) pid = os.fork() if pid == 0: if cwd is not None: os.chdir(cwd) os.closerange(3, os.sysconf("SC_OPEN_MAX")) os.execvp(cmd[0], cmd) os._exit(1) # pylint: disable=W0212 else: status = os.waitpid(pid, 0)[1] if status == 0: return elif os.WIFSIGNALED(status): sys.exit("Process %s exited with signal %s" % (" ".join(cmd), os.WTERMSIG(status))) elif os.WIFEXITED(status): sys.exit("Program %s exited with status %s" % (" ".join(cmd), os.WEXITSTATUS(status))) else: sys.exit("Program %s exited for unknown reason %s" % (" ".join(cmd), status)) try: lock = os.open(os.path.join(rpki.autoconf.RCYNIC_DIR, "data", "lock"), os.O_RDONLY | os.O_CREAT | os.O_NONBLOCK, 0666) fcntl.flock(lock, fcntl.LOCK_EX | fcntl.LOCK_NB) except (IOError, OSError), e: if e.errno == errno.EAGAIN: sys.exit(0) # Another instance of this script is already running, exit silently else: sys.exit("Error %r opening lock %r" % (e.strerror, os.path.join(rpki.autoconf.RCYNIC_DIR, "data/lock"))) run(os.path.join(rpki.autoconf.bindir, "rcynic")) run(os.path.join(rpki.autoconf.bindir, "rpki-rtr"), "cronjob", cwd = os.path.join(rpki.autoconf.RCYNIC_DIR, "rpki-rtr")) prog = os.path.join(rpki.autoconf.libexecdir, "rpkigui-rcynic") if os.path.exists(prog): run(prog) if rpki.autoconf.RCYNIC_HTML_DIR and os.path.exists(os.path.dirname(rpki.autoconf.RCYNIC_HTML_DIR)): run(os.path.join(rpki.autoconf.bindir, "rcynic-html"), os.path.join(rpki.autoconf.RCYNIC_DIR, "data/rcynic.xml"), rpki.autoconf.RCYNIC_HTML_DIR)