#!/usr/bin/python from __future__ import with_statement import cjson import contextlib import fcntl import os import getpass import select import socket import sys TIMEOUT = 5 @contextlib.contextmanager def lockfile(path, exclusive=True): f = open(path, 'w' if exclusive else 'r') fcntl.lockf(f, fcntl.LOCK_EX if self.exclusive else fcntl.LOCK_SH) try: yield finally: fcntl.lockf(f, fcntl.LOCK_UN) def do_send(s, sock_path, change): s.sendall(cjson.encode(change)) s.close() def do_recv(s, sock_path, change): def do_client(cl): global changes clf = cl.makefile('r') change = clf.read() changes.append(cjson.decode(change)) clf.close() cl.close() def collect_changes(s, timeout): global changes while True: if select.select([s], [], [], timeout) == ([], [], []): # Timed out break else: # Something to accept cl, _ = s.accept() do_client(cl) changes = [change] collect_changes(s, TIMEOUT) # Ok, we've timed out os.unlink(sock_path) # If anybody connected between when the select() timed out and we # unlinked, handle them now collect_changes(s, 0) def main(args): change = {} change['action'] = args[1] change['pocket'] = args[2] change['type'] = args[3] change['component'] = args[4] change['arch'] = args[5] change['package'] = args[6] args = args[7:] if change['action'] in ('add', 'replace'): change['new_version'] = args.pop(0) if change['action'] in ('remove', 'replace'): change['old_version'] = args.pop(0) change['args'] = args user = getpass.getuser() sock_path = os.path.join('/tmp/dagrouper-%s.sock' % user) with lockfile('/tmp/dagrouper-%s.lock' % user): s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) if os.path.exists(sock_path): s.connect(sock_path) bound = False else: s.bind(sock_path) bound = True if bound: do_receive(s, sock_path, change) else: do_send(s, sock_path, change) if __name__ == '__main__': pid = os.fork() if pid: os._exit(0) else: main(sys.argv)