#!/usr/bin/env python import sys, os import getopt, syslog import pwd, grp import Backend, Pivot, Config SCRIPT = "slapd-pivot" PIDFILE = None class Log: def __init__(self): syslog.openlog('slapd-pivot') def write(self, string): string = string.encode("utf-8", "replace").strip("\n\r") if string: syslog.syslog(syslog.LOG_WARNING | syslog.LOG_DAEMON, string) def flush(self): pass def failure(msg, details = None): if details: msg += ": " + details print >> sys.stderr, "%s: %s" % (SCRIPT, msg) sys.exit(1) def usage(): print >> sys.stderr, "usage: %s -f config [-d level] [-p pidfile]" % SCRIPT sys.exit(2) def run_server(): server = Backend.Server(Config.require("sock-file"), Pivot.Database) try: print >> sys.stderr, "%s starting up..." % SCRIPT server.serve_forever() except KeyboardInterrupt: sys.exit(0) def drop_privileges(): group = Config.option("unix-group") if group: try: group = int(group) except ValueError: try: group = grp.getgrnam(group)[2] except KeyError: failure("invalid group: %s" % group) os.setegid(group) user = Config.option("unix-user") if user: try: user = int(user) except ValueError: try: user = pwd.getpwnam(user)[2] except KeyError: failure("invalid user: %s" % user) os.seteuid(user) def daemon(): # do the UNIX double-fork magic, see Stevens' "Advanced # Programming in the UNIX Environment" for details (ISBN 0201563177) try: pid = os.fork() if pid > 0: # exit first parent sys.exit(0) except OSError, e: failure("couldn't fork to daemon", e.strerror) # decouple from parent environment os.setsid() os.umask(0) # do second fork try: pid = os.fork() if pid > 0: # exit from second parent, print eventual PID before if PIDFILE: open(PIDFILE,'w').write("%d" % pid) sys.exit(0) except OSError, e: failure("couldn't fork to daemon", e.strerror) os.chdir("/") sys.stderr = Log() if __name__ == '__main__': daemonize = True config = "/usr/local/etc/slapd-pivot.conf" try: opts, args = getopt.getopt(sys.argv[1:], 'd:f:g:p:u:') except getopt.GetoptError: usage() for (opt, oarg) in opts: if opt == "-d": try: daemonize = False level = int(oarg) if level >= 4: Backend.debug = True except: failure("invalid debug level", oarg) elif opt == '-f': config = oarg elif opt == '-p': PIDFILE = oarg # No extra arguments if args: usage() try: # Load up our config file Config.load(config) except Config.Error, ex: failure(str(ex)) # Change to a user that was specified drop_privileges() # Become a daemon if requested if daemonize: daemon() # And off we go run_server()