diff options
author | Arthur de Jong <arthur@arthurdejong.org> | 2013-03-29 20:13:45 +0100 |
---|---|---|
committer | Arthur de Jong <arthur@arthurdejong.org> | 2013-03-29 20:13:45 +0100 |
commit | 11b1739afc43b5e444a5ac173b08b13b5b5fbc07 (patch) | |
tree | de6c8fe916409b12932fe54df040a97f9f74b2f1 | |
parent | 65a65adbf953ee8da43a76db2cd03a064a80cd46 (diff) |
Functionality for clearing the nscd cache in pynslcd
-rw-r--r-- | pynslcd/Makefile.am | 2 | ||||
-rw-r--r-- | pynslcd/nscd.py | 107 |
2 files changed, 108 insertions, 1 deletions
diff --git a/pynslcd/Makefile.am b/pynslcd/Makefile.am index cff5629..6203d12 100644 --- a/pynslcd/Makefile.am +++ b/pynslcd/Makefile.am @@ -20,7 +20,7 @@ pynslcddir = $(datadir)/pynslcd pynslcd_PYTHON = pynslcd.py attmap.py cache.py cfg.py common.py expr.py \ - mypidfile.py search.py tio.py \ + mypidfile.py nscd.py search.py tio.py \ alias.py ether.py group.py host.py netgroup.py network.py \ pam.py passwd.py protocol.py rpc.py service.py shadow.py nodist_pynslcd_PYTHON = constants.py diff --git a/pynslcd/nscd.py b/pynslcd/nscd.py new file mode 100644 index 0000000..89cb483 --- /dev/null +++ b/pynslcd/nscd.py @@ -0,0 +1,107 @@ + +# nscd.py - functions for invalidating the nscd cache +# +# Copyright (C) 2013 Arthur de Jong +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301 USA + +import fcntl +import logging +import os +import subprocess +import struct + + +# the file descriptor used for sending messages to the child process +signalfd = None + + +# mapping between map name and signal character +_db_to_char = dict( + aliases='A', ethers='E', group='G', hosts='H', netgroup='U', + networks='N', passwd='P', protocols='L', rpc='R', services='V', + shadow='S', + ) +_char_to_db = dict((reversed(item) for item in _db_to_char.items())) + + +def exec_invalidate(db): + logging.debug('nscd_invalidator: nscd -i %s', db) + try: + p = subprocess.Popen(['nscd', '-i', 'passwd'], + bufsize=4096, close_fds=True, + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + output, ignored = p.communicate() + if output: + output = ': %s' % output[:1024].strip() + if p.returncode == 0: + logging.debug('nscd_invalidator: nscd -i %s (pid %d) success%s', + db, p.pid, output) + elif p.returncode > 0: + logging.debug('nscd_invalidator: nscd -i %s (pid %d) failed (%d)%s', + db, p.pid, p.returncode, output) + else: # p.returncode < 0 + logging.error('nscd_invalidator: nscd -i %s (pid %d) killed by signal %d%s', + db, p.pid, -p.returncode, output) + except: + logging.warn('nscd_invalidator: nscd -i %s failed', db, exc_info=True) + + +def loop(fd): + # set process title + try: + import setproctitle + setproctitle.setproctitle('(nscd invalidator)') + except ImportError: + pass + # set up clean environment + os.chdir('/') + os.environ['PATH'] = '/usr/sbin:/usr/bin:/sbin:/bin' + while True: + db = os.read(fd, 1) + # FIXME: define the characters and maps somewhere + if db == '': + break + db = _char_to_db.get(db, None) + if db: + exec_invalidate(db) + + +def start_invalidator(): + r, w = os.pipe() + # mark write end as non-blocking + flags = fcntl.fcntl(w, fcntl.F_GETFL) + fcntl.fcntl(w, fcntl.F_SETFL, flags | os.O_NONBLOCK) + cpid = os.fork() + if cpid == 0: + # we are the child + os.close(w) + loop(r) + os._exit(1) + # we are the parent + global signalfd + signalfd = w + os.close(r) + + +def invalidate(db=None): + if signalfd is None: + return # nothing to do + db = _db_to_char.get(db, '') + try: + os.write(signalfd, db) + except: + logging.warn('nscd_invalidator: nscd -i %s failed', db, exc_info=True) |