nss-pam-ldapd branch master updated. 0.8.12-81-gd54243a
[
Date Prev][
Date Next]
[
Thread Prev][
Thread Next]
nss-pam-ldapd branch master updated. 0.8.12-81-gd54243a
- From: Commits of the nss-pam-ldapd project <nss-pam-ldapd-commits [at] lists.arthurdejong.org>
- To: nss-pam-ldapd-commits [at] lists.arthurdejong.org
- Reply-to: nss-pam-ldapd-users [at] lists.arthurdejong.org
- Subject: nss-pam-ldapd branch master updated. 0.8.12-81-gd54243a
- Date: Sat, 23 Feb 2013 17:28:10 +0100 (CET)
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "nss-pam-ldapd".
The branch, master has been updated
via d54243ab8eab01afad0b7877f7ae7bef310b091d (commit)
via c75599db1ab14c9a4e502ff767a6f588f74f03be (commit)
via efca5ca5599bbad982ac4f259047c7f07337951a (commit)
via 22be9b0ba4b8ab3fbcd76bf5fce858779cc7056c (commit)
from c12768a087ba0bf4f0e2be92c7b9874ad236951e (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
http://arthurdejong.org/git/nss-pam-ldapd/commit/?id=d54243ab8eab01afad0b7877f7ae7bef310b091d
commit d54243ab8eab01afad0b7877f7ae7bef310b091d
Author: Arthur de Jong <arthur@arthurdejong.org>
Date: Sat Feb 23 17:27:09 2013 +0100
document the log option
diff --git a/man/nslcd.conf.5.xml b/man/nslcd.conf.5.xml
index b3c7414..b43baa3 100644
--- a/man/nslcd.conf.5.xml
+++ b/man/nslcd.conf.5.xml
@@ -111,6 +111,27 @@
</listitem>
</varlistentry>
+ <varlistentry id="log">
+ <term><option>log</option> <replaceable>SCHEME</replaceable>
<optional><replaceable>LEVEL</replaceable></optional></term>
+ <listitem>
+ <para>
+ This option controls the way logging is done.
+ The <replaceable>SCHEME</replaceable> argument may either be
+ <literal>none</literal>, <literal>syslog</literal> or an absolute
+ file name.
+ The <replaceable>LEVEL</replaceable> argument is optional and specifies
+ the log level.
+ The log level may be one of: <literal>crit</literal>,
+ <literal>error</literal>, <literal>warning</literal>,
+ <literal>notice</literal>, <literal>info</literal> or
+ <literal>debug</literal>. The default log level is
<literal>info</literal>.
+ All messages with the specified loglevel or higher are logged.
+ This option can be supplied multiple times.
+ If this option is omitted <literal>syslog info</literal> is assumed.
+ </para>
+ </listitem>
+ </varlistentry>
+
</variablelist>
</refsect2>
http://arthurdejong.org/git/nss-pam-ldapd/commit/?id=c75599db1ab14c9a4e502ff767a6f588f74f03be
commit c75599db1ab14c9a4e502ff767a6f588f74f03be
Author: Arthur de Jong <arthur@arthurdejong.org>
Date: Sat Feb 23 17:02:14 2013 +0100
handle the log configuration option in pynslcd
diff --git a/pynslcd/cfg.py b/pynslcd/cfg.py
index 132cf91..ab6668b 100644
--- a/pynslcd/cfg.py
+++ b/pynslcd/cfg.py
@@ -33,6 +33,8 @@ threads = 5
uid = None
# the group id nslcd should be run as
gid = None
+# the configured loggers
+logs = []
# the LDAP server to use
# FIXME: support multiple servers and have a fail-over mechanism
@@ -79,7 +81,6 @@ tls_ciphers = None
tls_cert = None
tls_key = None
-
# other options
pagesize = 0
nss_initgroups_ignoreusers = set()
@@ -93,6 +94,12 @@ pam_password_prohibit_message = None
_boolean_options = {'on': True, 'yes': True, 'true': True, '1': True,
'off': False, 'no': False, 'false': False, '0': False}
+# allowed log levels (we log notice which is unsupported in Python to warning)
+_log_levels = {'crit': logging.CRITICAL, 'error': logging.ERROR,
+ 'err': logging.ERROR, 'warning': logging.WARNING,
+ 'notice': logging.WARNING, 'info': logging.INFO,
+ 'debug': logging.DEBUG, 'none': logging.INFO}
+
# allowed values for scope option
if not hasattr(ldap, 'SCOPE_CHILDREN') and ldap.VENDOR_VERSION >= 20400:
ldap.SCOPE_CHILDREN = 3 # OpenLDAP extension
@@ -187,6 +194,13 @@ def read(filename):
if m:
globals()[m.group('keyword').lower()] = m.group('value')
continue
+ # log <SCHEME> [<LEVEL>]
+ m = re.match('log\s+(?P<scheme>syslog|/\S*)(\s+(?P<level>%s))?' %
+ '|'.join(_log_levels.keys()),
+ line, re.IGNORECASE)
+ if m:
+ logs.append((m.group('scheme'),
_log_levels[str(m.group('level')).lower()]))
+ continue
# uri <URI>
m = re.match('uri\s+(?P<uri>\S+)', line, re.IGNORECASE)
if m:
@@ -299,6 +313,9 @@ def read(filename):
continue
# unrecognised line
raise ParseError(filename, lineno, 'error parsing line %r' % line)
+ # if logging is not configured, default to syslog
+ if not logs:
+ log.append('syslog', logging.INFO)
# dump config (debugging code)
for k, v in globals().items():
if not k.startswith('_'):
diff --git a/pynslcd/pynslcd.py b/pynslcd/pynslcd.py
index f06ac11..bdd3a96 100755
--- a/pynslcd/pynslcd.py
+++ b/pynslcd/pynslcd.py
@@ -2,7 +2,7 @@
# pynslcd.py - main daemon module
#
-# Copyright (C) 2010, 2011, 2012 Arthur de Jong
+# Copyright (C) 2010, 2011, 2012, 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
@@ -50,10 +50,8 @@ checkonly = False
class MyFormatter(logging.Formatter):
def format(self, record):
- msg = super(MyFormatter, self).format(record)
- if record.levelno == logging.DEBUG:
- msg = 'DEBUG: %s' % msg
- return msg
+ record.prefix = 'DEBUG: ' if record.levelno == logging.DEBUG else ''
+ return super(MyFormatter, self).format(record)
class MySysLogHandler(logging.Handler):
@@ -78,11 +76,8 @@ class MySysLogHandler(logging.Handler):
# configure logging
-formatter = MyFormatter('%(message)s')
stderrhandler = logging.StreamHandler(sys.stderr)
-stderrhandler.setFormatter(formatter)
-sysloghandler = MySysLogHandler()
-sysloghandler.setFormatter(formatter)
+stderrhandler.setFormatter(MyFormatter('pynslcd: %(prefix)s%(message)s'))
logging.getLogger().addHandler(stderrhandler)
logging.getLogger().setLevel(logging.INFO)
@@ -91,7 +86,7 @@ def display_version(fp):
fp.write('%(PACKAGE_STRING)s\n'
'Written by Arthur de Jong.\n'
'\n'
- 'Copyright (C) 2010-2012 Arthur de Jong\n'
+ 'Copyright (C) 2010-2013 Arthur de Jong\n'
'This is free software; see the source for copying conditions.
There is NO\n'
'warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.\n'
% {'PACKAGE_STRING': constants.PACKAGE_STRING, })
@@ -320,11 +315,21 @@ if __name__ == '__main__':
})
# start daemon
with daemon:
- # start normal logging to syslog
- if not debugging:
- logging.getLogger().addHandler(sysloghandler)
- logging.info('version %s starting', constants.VERSION)
try:
+ # start normal logging as configured
+ if not debugging:
+ for method, level in cfg.logs:
+ if method == 'syslog':
+ handler = MySysLogHandler()
+
handler.setFormatter(MyFormatter('%(prefix)s%(message)s'))
+ else:
+ handler = logging.FileHandler(method, encoding='utf-8')
+ handler.setFormatter(MyFormatter('%(asctime)s
%(prefix)s%(message)s'))
+ handler.setLevel(level)
+ logging.getLogger().addHandler(handler)
+ logging.getLogger().setLevel(min(level for method, level in
cfg.logs))
+ logging.getLogger().removeHandler(stderrhandler)
+ logging.info('version %s starting', constants.VERSION)
# create socket
nslcd_serversocket = create_socket()
# load supplementary groups
http://arthurdejong.org/git/nss-pam-ldapd/commit/?id=efca5ca5599bbad982ac4f259047c7f07337951a
commit efca5ca5599bbad982ac4f259047c7f07337951a
Author: Arthur de Jong <arthur@arthurdejong.org>
Date: Sat Feb 23 17:01:55 2013 +0100
handle the log configuration option in nslcd
diff --git a/nslcd/cfg.c b/nslcd/cfg.c
index 651fd3f..afb4af7 100644
--- a/nslcd/cfg.c
+++ b/nslcd/cfg.c
@@ -282,6 +282,53 @@ static void handle_gid(const char *filename, int lnr,
exit(EXIT_FAILURE);
}
+static int parse_loglevel(const char *filename, int lnr, const char *value)
+{
+ if (strcasecmp(value, "crit") == 0)
+ return LOG_CRIT;
+ else if ((strcasecmp(value, "error") == 0) || (strcasecmp(value, "err") ==
0))
+ return LOG_ERR;
+ else if (strcasecmp(value, "warning")==0)
+ return LOG_WARNING;
+ else if (strcasecmp(value, "notice")==0)
+ return LOG_NOTICE;
+ else if (strcasecmp(value, "info")==0)
+ return LOG_INFO;
+ else if (strcasecmp(value, "debug")==0)
+ return LOG_DEBUG;
+ else
+ {
+ log_log(LOG_ERR, "%s:%d: not a log level '%s'",
+ filename, lnr, value);
+ exit(EXIT_FAILURE);
+ }
+}
+
+static void handle_log(const char *filename, int lnr,
+ const char *keyword, char *line)
+{
+ int level = LOG_INFO;
+ char scheme[64];
+ char loglevel[32];
+ check_argumentcount(filename, lnr, keyword,
+ get_token(&line, scheme, sizeof(scheme)) != NULL);
+ if (get_token(&line, loglevel, sizeof(loglevel)) != NULL)
+ level = parse_loglevel(filename, lnr, loglevel);
+ get_eol(filename, lnr, keyword, &line);
+ if (strcasecmp(scheme, "none") == 0)
+ log_addlogging_none();
+ else if (strcasecmp(scheme, "syslog") == 0)
+ log_addlogging_syslog(level);
+ else if (scheme[0] == '/')
+ log_addlogging_file(level, scheme);
+ else
+ {
+ log_log(LOG_ERR, "%s:%d: %s: invalid argument '%s'",
+ filename, lnr, keyword, scheme);
+ exit(EXIT_FAILURE);
+ }
+}
+
/* add a single URI to the list of URIs in the configuration */
static void add_uri(const char *filename, int lnr,
struct ldap_config *cfg, const char *uri)
@@ -1066,6 +1113,10 @@ static void cfg_read(const char *filename, struct
ldap_config *cfg)
{
handle_gid(filename, lnr, keyword, line, &cfg->gid);
}
+ else if (strcasecmp(keyword, "log") == 0)
+ {
+ handle_log(filename, lnr, keyword, line);
+ }
/* general connection options */
else if (strcasecmp(keyword, "uri") == 0)
{
@@ -1418,6 +1469,7 @@ static void cfg_dump(void)
log_log(LOG_DEBUG, "CFG: gid %d", nslcd_cfg->gid);
else
log_log(LOG_DEBUG, "CFG: # gid not set");
+ log_log_config();
for (i = 0; i < (NSS_LDAP_CONFIG_MAX_URIS + 1); i++)
if (nslcd_cfg->uris[i].uri != NULL)
log_log(LOG_DEBUG, "CFG: uri %s", nslcd_cfg->uris[i].uri);
diff --git a/nslcd/log.c b/nslcd/log.c
index bd7bf7d..0676cf6 100644
--- a/nslcd/log.c
+++ b/nslcd/log.c
@@ -42,6 +42,7 @@
/* storage for logging modes */
static struct log_cfg {
int loglevel;
+ const char *scheme;
FILE *fp; /* NULL == syslog */
struct log_cfg *next;
} *loglist = NULL;
@@ -80,7 +81,7 @@ void log_setdefaultloglevel(int loglevel)
}
/* add logging method to configuration list */
-static void addlogging(int loglevel, FILE *fp)
+static void addlogging(int loglevel, const char *scheme, FILE *fp)
{
struct log_cfg *tmp, *lst;
/* create new logstruct */
@@ -90,8 +91,9 @@ static void addlogging(int loglevel, FILE *fp)
log_log(LOG_CRIT, "malloc() returned NULL");
exit(EXIT_FAILURE);
}
- tmp->fp = fp;
tmp->loglevel = loglevel;
+ tmp->scheme = scheme;
+ tmp->fp = fp;
tmp->next = NULL;
/* save the struct in the list */
if (loglist == NULL)
@@ -107,6 +109,12 @@ static void addlogging(int loglevel, FILE *fp)
void log_addlogging_file(int loglevel, const char *filename)
{
FILE *fp;
+ filename = strdup(filename);
+ if (filename == NULL)
+ {
+ log_log(LOG_CRIT, "strdup() returned NULL");
+ exit(EXIT_FAILURE);
+ }
fp = fopen(filename, "a");
if (fp == NULL)
{
@@ -114,21 +122,21 @@ void log_addlogging_file(int loglevel, const char
*filename)
filename, strerror(errno));
exit(1);
}
- addlogging(loglevel, fp);
+ addlogging(loglevel, filename, fp);
}
/* configure logging to syslog */
void log_addlogging_syslog(int loglevel)
{
openlog(PACKAGE, LOG_PID, LOG_DAEMON);
- addlogging(loglevel, NULL);
+ addlogging(loglevel, "syslog", NULL);
}
/* configure a null logging mode (no logging) */
void log_addlogging_none()
{
/* this is a hack, but it's so easy */
- addlogging(LOG_EMERG, NULL);
+ addlogging(LOG_EMERG, "none", NULL);
}
/* start the logging with the configured logging methods
@@ -294,3 +302,31 @@ void log_log(int pri, const char *format, ...)
}
}
}
+
+static const char *loglevel2str(int loglevel)
+{
+ switch (loglevel)
+ {
+ case LOG_CRIT: return "crit";
+ case LOG_ERR: return "error";
+ case LOG_WARNING: return "warning";
+ case LOG_NOTICE: return "notice";
+ case LOG_INFO: return "info";
+ case LOG_DEBUG: return "debug";
+ default: return "???";
+ }
+}
+
+/* log the logging configuration on DEBUG loglevel */
+void log_log_config(void)
+{
+ struct log_cfg *lst;
+ for (lst = loglist; lst != NULL; lst = lst->next)
+ {
+ if (lst->loglevel == LOG_EMERG)
+ log_log(LOG_DEBUG, "CFG: log %s", lst->scheme);
+ else
+ log_log(LOG_DEBUG, "CFG: log %s %s", lst->scheme,
+ loglevel2str(lst->loglevel));
+ }
+}
diff --git a/nslcd/log.h b/nslcd/log.h
index 3cf8cb1..277daa7 100644
--- a/nslcd/log.h
+++ b/nslcd/log.h
@@ -59,4 +59,7 @@ void log_setrequest(const char *format, ...)
void log_log(int pri, const char *format, ...)
LIKE_PRINTF(2, 3);
+/* log the logging configuration on DEBUG loglevel */
+void log_log_config(void);
+
#endif /* not NSLCD__LOG_H */
diff --git a/nslcd/nslcd.c b/nslcd/nslcd.c
index 0356f61..4be063a 100644
--- a/nslcd/nslcd.c
+++ b/nslcd/nslcd.c
@@ -681,6 +681,14 @@ int main(int argc, char *argv[])
#ifdef HAVE_PTHREAD_TIMEDJOIN_NP
struct timespec ts;
#endif /* HAVE_PTHREAD_TIMEDJOIN_NP */
+ /* close all file descriptors (except stdin/out/err) */
+ i = sysconf(_SC_OPEN_MAX) - 1;
+ /* if the system does not have OPEN_MAX just close the first 32 and
+ hope we closed enough */
+ if (i < 0)
+ i = 32;
+ for (; i > 3; i--)
+ close(i);
/* parse the command line */
parse_cmdline(argc, argv);
/* clean the environment */
@@ -727,14 +735,6 @@ int main(int argc, char *argv[])
NSLCD_PIDFILE, strerror(errno));
exit(EXIT_FAILURE);
}
- /* close all file descriptors (except stdin/out/err) */
- i = sysconf(_SC_OPEN_MAX) - 1;
- /* if the system does not have OPEN_MAX just close the first 32 and
- hope we closed enough */
- if (i < 0)
- i = 32;
- for (; i > 3; i--)
- close(i);
/* daemonize */
if ((!nslcd_debugging) && (daemon(0, 0) < 0))
{
http://arthurdejong.org/git/nss-pam-ldapd/commit/?id=22be9b0ba4b8ab3fbcd76bf5fce858779cc7056c
commit 22be9b0ba4b8ab3fbcd76bf5fce858779cc7056c
Author: Arthur de Jong <arthur@arthurdejong.org>
Date: Sat Feb 23 17:01:21 2013 +0100
implement functions for configuring alternative logging
diff --git a/nslcd/log.c b/nslcd/log.c
index 1911b5c..bd7bf7d 100644
--- a/nslcd/log.c
+++ b/nslcd/log.c
@@ -31,6 +31,7 @@
#include <string.h>
#include <time.h>
#include <pthread.h>
+#include <strings.h>
#include "log.h"
@@ -38,12 +39,16 @@
#undef PACKAGE
#define PACKAGE "nslcd"
+/* storage for logging modes */
+static struct log_cfg {
+ int loglevel;
+ FILE *fp; /* NULL == syslog */
+ struct log_cfg *next;
+} *loglist = NULL;
+
/* default loglevel when no logging is configured */
static int prelogging_loglevel = LOG_INFO;
-/* loglevel to use before logging to syslog */
-static int loglevel = LOG_INFO;
-
#define MAX_REQUESTID_LENGTH 40
#ifdef TLS
@@ -69,16 +74,69 @@ static void tls_init_keys(void)
#endif /* no TLS, use pthreads */
/* set loglevel when no logging is configured */
-void log_setdefaultloglevel(int pri)
+void log_setdefaultloglevel(int loglevel)
+{
+ prelogging_loglevel = loglevel;
+}
+
+/* add logging method to configuration list */
+static void addlogging(int loglevel, FILE *fp)
+{
+ struct log_cfg *tmp, *lst;
+ /* create new logstruct */
+ tmp = (struct log_cfg *)malloc(sizeof(struct log_cfg));
+ if (tmp == NULL)
+ {
+ log_log(LOG_CRIT, "malloc() returned NULL");
+ exit(EXIT_FAILURE);
+ }
+ tmp->fp = fp;
+ tmp->loglevel = loglevel;
+ tmp->next = NULL;
+ /* save the struct in the list */
+ if (loglist == NULL)
+ loglist = tmp;
+ else
+ {
+ for (lst = loglist; lst->next != NULL; lst = lst->next);
+ lst->next = tmp;
+ }
+}
+
+/* configure logging to a file */
+void log_addlogging_file(int loglevel, const char *filename)
{
- prelogging_loglevel = pri;
+ FILE *fp;
+ fp = fopen(filename, "a");
+ if (fp == NULL)
+ {
+ log_log(LOG_ERR, "cannot open logfile (%s) for appending: %s",
+ filename, strerror(errno));
+ exit(1);
+ }
+ addlogging(loglevel, fp);
+}
+
+/* configure logging to syslog */
+void log_addlogging_syslog(int loglevel)
+{
+ openlog(PACKAGE, LOG_PID, LOG_DAEMON);
+ addlogging(loglevel, NULL);
+}
+
+/* configure a null logging mode (no logging) */
+void log_addlogging_none()
+{
+ /* this is a hack, but it's so easy */
+ addlogging(LOG_EMERG, NULL);
}
/* start the logging with the configured logging methods
if no method is configured yet, logging is done to syslog */
void log_startlogging(void)
{
- openlog(PACKAGE, LOG_PID, LOG_DAEMON);
+ if (loglist == NULL)
+ log_addlogging_syslog(LOG_INFO);
prelogging_loglevel = -1;
}
@@ -163,6 +221,7 @@ void log_setrequest(const char *format, ...)
void log_log(int pri, const char *format, ...)
{
int res;
+ struct log_cfg *lst;
char buffer[200];
va_list ap;
#ifndef TLS
@@ -202,14 +261,36 @@ void log_log(int pri, const char *format, ...)
}
else
{
- if (pri <= loglevel)
+ for (lst = loglist; lst != NULL; lst = lst->next)
{
- if ((requestid != NULL) && (requestid[0] != '\0'))
- syslog(pri, "[%s] <%s> %s", sessionid, requestid, buffer);
- else if ((sessionid != NULL) && (sessionid[0] != '\0'))
- syslog(pri, "[%s] %s", sessionid, buffer);
- else
- syslog(pri, "%s", buffer);
+ if (pri <= lst->loglevel)
+ {
+ if (lst->fp == NULL)
+ {
+ if ((requestid != NULL) && (requestid[0] != '\0'))
+ syslog(pri, "[%s] <%s> %s%s", sessionid, requestid,
+ pri == LOG_DEBUG ? "DEBUG: " : "", buffer);
+ else if ((sessionid != NULL) && (sessionid[0] != '\0'))
+ syslog(pri, "[%s] %s%s", sessionid,
+ pri == LOG_DEBUG ? "DEBUG: " : "", buffer);
+ else
+ syslog(pri, "%s%s",
+ pri == LOG_DEBUG ? "DEBUG: " : "", buffer);
+ }
+ else
+ {
+ if ((requestid != NULL) && (requestid[0] != '\0'))
+ fprintf(lst->fp, "%s: [%s] <%s> %s%s\n", PACKAGE, sessionid,
requestid,
+ pri == LOG_DEBUG ? "DEBUG: " : "", buffer);
+ else if ((sessionid != NULL) && (sessionid[0] != '\0'))
+ fprintf(lst->fp, "%s: [%s] %s%s\n", PACKAGE, sessionid,
+ pri == LOG_DEBUG ? "DEBUG: " : "", buffer);
+ else
+ fprintf(lst->fp, "%s: %s%s\n", PACKAGE,
+ pri == LOG_DEBUG ? "DEBUG: " : "", buffer);
+ fflush(lst->fp);
+ }
+ }
}
}
}
diff --git a/nslcd/log.h b/nslcd/log.h
index c88613b..3cf8cb1 100644
--- a/nslcd/log.h
+++ b/nslcd/log.h
@@ -1,7 +1,7 @@
/*
log.h - definitions of logging funtions
- Copyright (C) 2002, 2003, 2007, 2008, 2010, 2011, 2012 Arthur de Jong
+ Copyright (C) 2002, 2003, 2007, 2008, 2010, 2011, 2012, 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
@@ -27,7 +27,16 @@
#include "compat/attrs.h"
/* set loglevel when no logging is configured */
-void log_setdefaultloglevel(int pri);
+void log_setdefaultloglevel(int loglevel);
+
+/* configure logging to a file */
+void log_addlogging_file(int loglevel, const char *filename);
+
+/* configure logging to syslog */
+void log_addlogging_syslog(int loglevel);
+
+/* configure a null logging mode (no logging) */
+void log_addlogging_none(void);
/* start the logging with the configured logging methods
if no method is configured yet, logging is done to syslog */
-----------------------------------------------------------------------
Summary of changes:
man/nslcd.conf.5.xml | 21 +++++++
nslcd/cfg.c | 52 ++++++++++++++++++
nslcd/log.c | 143 +++++++++++++++++++++++++++++++++++++++++++++-----
nslcd/log.h | 16 +++++-
nslcd/nslcd.c | 16 +++---
pynslcd/cfg.py | 19 ++++++-
pynslcd/pynslcd.py | 33 +++++++-----
7 files changed, 262 insertions(+), 38 deletions(-)
hooks/post-receive
--
nss-pam-ldapd
--
To unsubscribe send an email to
nss-pam-ldapd-commits-unsubscribe@lists.arthurdejong.org or see
http://lists.arthurdejong.org/nss-pam-ldapd-commits/
- nss-pam-ldapd branch master updated. 0.8.12-81-gd54243a,
Commits of the nss-pam-ldapd project