#!/usr/bin/env python from __future__ import print_function import argparse import os import pwd import sys import syslog from subprocess import Popen, PIPE, STDOUT from pipes import quote VERSION = '1.1' def is_root(): return os.getuid() == 0 class SplineStartup(object): def __init__(self): self.options = None self._parse_args() if self.options.syslog: syslog.openlog(logoption=syslog.LOG_PID) def _parse_args(self): parser = argparse.ArgumentParser(description='Startup for users.') parser.add_argument('action', metavar='ACTION', nargs='?', default='start', help='argument supplied to each called ' 'script (default: %(default)s)') parser.add_argument('-q', '--quiet', action='store_true', help='only log error messages') parser.add_argument('-v', '--verbose', action='store_true', help='print extra debugging mesasges to stderr') parser.add_argument('-V', '--version', action='version', version='%(prog)s ' + VERSION) parser.add_argument('-n', '--dry-run', action='store_true', help="print script names which would run, " "but don't run them") parser.add_argument('-s', '--syslog', action='store_true', help='log to syslog and not to stderr') if is_root(): parser.add_argument('-u', '--user', metavar='USER', action='append', help='user to execute scripts (by default all ' 'users with 1000 <= uid < 2000 are used)') self.options = parser.parse_args() def _perror(self, msg): if self.options.syslog: syslog.syslog(syslog.LOG_CRIT, msg) else: print('[ERROR] %s' % msg, file=sys.stderr) def _pinfo(self, msg): if self.options.syslog: syslog.syslog(syslog.LOG_INFO, msg) elif not self.options.quiet: print('[INFO] %s' % msg, file=sys.stderr) def _pdebug(self, msg): if self.options.syslog: syslog.syslog(syslog.LOG_DEBUG, msg) elif self.options.verbose: print('[DEBUG] %s' % msg, file=sys.stderr) def _call(self, cmd): self._pinfo('Calling: %s' % ' '.join(cmd)) if not self.options.dry_run: proc = Popen(cmd, stdout=PIPE, stderr=STDOUT) output, _ = proc.communicate() output = output.strip() if output != '': for line in output.split('\n'): self._pinfo(line) return proc.wait() else: return 0 def _run_scripts(self, user, action, su=True): self._pdebug("Running scripts for user '%s'" % user.pw_name) dir = os.path.join(user.pw_dir, 'etc', 'rc.d') args = ['--arg=%s' % quote(action)] if action == 'stop': args.append('--reverse') if not os.path.isdir(dir): return True if su: returnvalue = self._call(['su', '-', user.pw_name, '-c', 'run-parts %s -- %s' % (' '.join(args), quote(dir))]) else: returnvalue = self._call(['run-parts'] + args + ['--', dir]) return returnvalue == 0 def run(self): if not is_root(): user = pwd.getpwuid(os.getuid()) self._run_scripts(user, self.options.action, False) return if self.options.user is not None: for username in self.options.user: try: user = pwd.getpwnam(username) self._run_scripts(user, self.options.action) except KeyError: self._perror("Invalid user '%s'" % user) else: for user in pwd.getpwall(): if user.pw_uid < 1000 or user.pw_uid >= 2000: continue self._run_scripts(user, self.options.action) if __name__ == '__main__': app = SplineStartup() app.run()