#!/usr/bin/python3 # SPDX-License-Identifier: AGPL-3.0-or-later import argparse import logging import os import sys import plinth.log EXIT_SYNTAX = 10 EXIT_PERM = 20 # Set up logging plinth.log.pipe_to_syslog(to_stderr='tty') logger = logging.getLogger(os.path.basename(__file__)) def reserved_for_root(fun): def wrapped(*args, **kwargs): if os.getuid() != 0: logger.critical('This action is reserved for root') sys.exit(EXIT_PERM) return fun(*args, **kwargs) return wrapped def main(): if not sys.stdin.isatty(): print('WARNING: Output will not be shown. Check syslog for logs', file=sys.stderr) parser = argparse.ArgumentParser() group = parser.add_mutually_exclusive_group(required=True) group.add_argument('-i', nargs='+', dest='ipc') # Select the first non-empty dict item adict = vars(parser.parse_args()) generator = (kv for kv in adict.items() if kv[1] is not None) subcommand, arguments = next(generator) function = globals()['subcommand_' + subcommand] try: function(*arguments) except Exception as e: logger.exception(e) _log_additional_info() sys.exit(1) @reserved_for_root def subcommand_ipc(module_name, action_name, *args): import plinth.modules.email_server.audit as audit # We only run actions defined in the audit module if module_name not in audit.__all__: logger.critical('Bad module name: %r', module_name) sys.exit(EXIT_SYNTAX) module = getattr(audit, module_name) function = getattr(module, 'action_' + action_name, None) if function is None: logger.critical('Bad action: %s/%r', module_name, action_name) sys.exit(EXIT_SYNTAX) function(*args) def _log_additional_info(): import grp import pwd resu = ','.join(pwd.getpwuid(uid).pw_name for uid in os.getresuid()) resg = ','.join(grp.getgrgid(gid).gr_name for gid in os.getresgid()) pyver = sys.version.replace('\n', ' ') logger.error('--- Additional Information ---') logger.error('resuid=%s, resgid=%s', resu, resg) logger.error('argv=%r, cwd=%r', sys.argv, os.getcwd()) logger.error('pyver=%s (%s)', pyver, os.uname().machine) if __name__ == '__main__': main()