lists.arthurdejong.org
RSS feed

nss-pam-ldapd branch master updated. 0.9.7-9-g5a84be2

[Date Prev][Date Next] [Thread Prev][Thread Next]

nss-pam-ldapd branch master updated. 0.9.7-9-g5a84be2



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  5a84be23ea6bc1eb8168a69d10e6c94c9c1413a8 (commit)
       via  9c803d72a512d1374a29e1cdc51449ad495862cb (commit)
       via  a357131d4bb98e21a5b376f02d8e61ecc3a5039c (commit)
       via  58c7a9406c143b41516a7c99d1b190db203f3ace (commit)
       via  5173e553375285c0e2ad91e67079e4b179dc6335 (commit)
      from  53f797bf8a5433d68b21023fbd960ba79385be54 (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 -----------------------------------------------------------------
https://arthurdejong.org/git/nss-pam-ldapd/commit/?id=5a84be23ea6bc1eb8168a69d10e6c94c9c1413a8

commit 5a84be23ea6bc1eb8168a69d10e6c94c9c1413a8
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Sun Jun 4 22:14:15 2017 +0200

    Make nslcd-utils Python 3 compatible
    
    This changes the getent.ldap and chsh.ldap commands to be compatible
    with Python 2 and Python 3 with the same code.
    
    This does switch to raw I/O because Python 3 does not support bufferred
    I/O on sockets.

diff --git a/utils/chsh.py b/utils/chsh.py
index 2f81f13..c48459d 100755
--- a/utils/chsh.py
+++ b/utils/chsh.py
@@ -60,7 +60,7 @@ if __name__ == '__main__':
     password = user.get_passwd()
     # prompt for a shell if it was not specified on the command line
     if shell is None:
-        print 'Enter the new value, or press ENTER for the default'
+        print('Enter the new value, or press ENTER for the default')
         shell = ask_shell(user.shell)
         shells.check(shell, user.asroot)
     # perform the modification
diff --git a/utils/cmdline.py b/utils/cmdline.py
index 2fd428f..a268f98 100644
--- a/utils/cmdline.py
+++ b/utils/cmdline.py
@@ -46,7 +46,7 @@ class VersionAction(argparse.Action):
             help=help)
 
     def __call__(self, parser, namespace, values, option_string=None):
-        print version_string
+        print(version_string)
         parser.exit()
 
 
@@ -64,5 +64,5 @@ class ListShellsAction(argparse.Action):
     def __call__(self, parser, namespace, values, option_string=None):
         import shells
         for shell in shells.list_shells():
-            print shell
+            print(shell)
         parser.exit()
diff --git a/utils/getent.py b/utils/getent.py
index f28a9cf..ae00c5e 100755
--- a/utils/getent.py
+++ b/utils/getent.py
@@ -55,10 +55,10 @@ parser.add_argument('keys', metavar='KEY', nargs='*',
 
 def write_aliases(con):
     while con.get_response() == constants.NSLCD_RESULT_BEGIN:
-        print '%-16s%s' % (
+        print('%-16s%s' % (
                 con.read_string() + ': ',
                 ', '.join(con.read_stringlist()),
-            )
+            ))
 
 
 def getent_aliases(database, keys=None):
@@ -75,7 +75,7 @@ def write_ethers(con):
     while con.get_response() == constants.NSLCD_RESULT_BEGIN:
         name = con.read_string()
         ether = con.read_ether()
-        print '%s %s' % (ether, name)
+        print('%s %s' % (ether, name))
 
 
 def getent_ethers(database, keys=None):
@@ -94,12 +94,12 @@ def getent_ethers(database, keys=None):
 
 def write_group(con):
     while con.get_response() == constants.NSLCD_RESULT_BEGIN:
-        print '%s:%s:%d:%s' % (
+        print('%s:%s:%d:%s' % (
                 con.read_string(),
                 con.read_string(),
                 con.read_int32(),
                 ','.join(con.read_stringlist()),
-            )
+            ))
 
 
 def getent_group(database, keys=None):
@@ -147,7 +147,7 @@ def write_hosts(con, db_af):
         names = ' '.join([con.read_string()] + con.read_stringlist())
         for af, address in con.read_addresslist():
             if db_af in (af, None):
-                print '%-15s %s' % (address, names)
+                print('%-15s %s' % (address, names))
 
 
 def getent_hosts(database, keys=None):
@@ -211,11 +211,11 @@ def _get_getgroups(con, recurse, netgroups=None):
 
 def write_netgroup(con, recurse):
     for name, members, tripples in _get_getgroups(con, recurse):
-        print '%-15s %s' % (name, ' '.join(
+        print('%-15s %s' % (name, ' '.join(
                 members +
                 ['(%s, %s, %s)' % (host, user, domain)
                  for host, user, domain in tripples]
-            ))
+            )))
 
 
 def getent_netgroup(database, keys=None):
@@ -235,7 +235,7 @@ def write_networks(con, db_af):
         names = ' '.join([con.read_string()] + con.read_stringlist())
         for af, address in con.read_addresslist():
             if db_af in (af, None):
-                print '%-22s %s' % (names, address)
+                print('%-22s %s' % (names, address))
 
 
 def getent_networks(database, keys=None):
@@ -260,7 +260,7 @@ def getent_networks(database, keys=None):
 
 def write_passwd(con):
     while con.get_response() == constants.NSLCD_RESULT_BEGIN:
-        print '%s:%s:%d:%d:%s:%s:%s' % (
+        print('%s:%s:%d:%d:%s:%s:%s' % (
                 con.read_string(),
                 con.read_string(),
                 con.read_int32(),
@@ -268,7 +268,7 @@ def write_passwd(con):
                 con.read_string(),
                 con.read_string(),
                 con.read_string(),
-            )
+            ))
 
 
 def getent_passwd(database, keys=None):
@@ -290,7 +290,7 @@ def write_protocols(con):
         name = con.read_string()
         aliases = con.read_stringlist()
         number = con.read_int32()
-        print '%-21s %d %s' % (name, number, ' '.join(aliases))
+        print('%-21s %d %s' % (name, number, ' '.join(aliases)))
 
 
 def getent_protocols(database, keys=None):
@@ -312,7 +312,7 @@ def write_rpc(con):
         name = con.read_string()
         aliases = con.read_stringlist()
         number = con.read_int32()
-        print '%-15s %d  %s' % (name, number, ' '.join(aliases))
+        print('%-15s %d  %s' % (name, number, ' '.join(aliases)))
 
 
 def getent_rpc(database, keys=None):
@@ -335,7 +335,7 @@ def write_services(con):
         aliases = con.read_stringlist()
         number = con.read_int32()
         protocol = con.read_string()
-        print '%-21s %d/%s %s' % (name, number, protocol, ' '.join(aliases))
+        print('%-21s %d/%s %s' % (name, number, protocol, ' '.join(aliases)))
 
 
 def getent_services(database, keys=None):
@@ -364,7 +364,7 @@ def _shadow_value2str(number):
 
 def write_shadow(con):
     while con.get_response() == constants.NSLCD_RESULT_BEGIN:
-        print '%s:%s:%s:%s:%s:%s:%s:%s:%s' % (
+        print('%s:%s:%s:%s:%s:%s:%s:%s:%s' % (
                 con.read_string(),
                 con.read_string(),
                 _shadow_value2str(con.read_int32()),
@@ -374,7 +374,7 @@ def write_shadow(con):
                 _shadow_value2str(con.read_int32()),
                 _shadow_value2str(con.read_int32()),
                 _shadow_value2str(con.read_int32()),
-            )
+            ))
 
 
 def getent_shadow(database, keys=None):
@@ -415,5 +415,5 @@ if __name__ == '__main__':
         else:
             parser.error('Unknown database: %s' % args.database)
     except struct.error:
-        print 'Problem communicating with nslcd'
+        print('Problem communicating with nslcd')
         sys.exit(1)
diff --git a/utils/nslcd.py b/utils/nslcd.py
index 0ea8257..bb720a3 100644
--- a/utils/nslcd.py
+++ b/utils/nslcd.py
@@ -2,7 +2,7 @@
 
 # nslcd.py - functions for doing nslcd requests
 #
-# Copyright (C) 2013 Arthur de Jong
+# Copyright (C) 2013-2017 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
@@ -23,6 +23,7 @@ import fcntl
 import os
 import socket
 import struct
+import sys
 
 import constants
 
@@ -40,7 +41,7 @@ class NslcdClient(object):
         # connect to nslcd
         self.sock.connect(constants.NSLCD_SOCKET)
         #self.sock.setblocking(1)
-        self.fp = os.fdopen(self.sock.fileno(), 'r+b', 1024 * 1024)
+        self.fp = os.fdopen(self.sock.fileno(), 'r+b', 0)
         # write a request header with a request code
         self.action = action
         self.write_int32(constants.NSLCD_VERSION)
@@ -52,31 +53,47 @@ class NslcdClient(object):
     def write_int32(self, value):
         self.write(_int32.pack(value))
 
-    def write_string(self, value):
+    def write_bytes(self, value):
         self.write_int32(len(value))
         self.write(value)
 
+    def write_string(self, value):
+        if sys.version_info[0] >= 3:
+            value = value.encode('utf-8')
+        self.write_bytes(value.encode('utf-8'))
+
     def write_ether(self, value):
         value = struct.pack('BBBBBB', *(int(x, 16) for x in value.split(':')))
         self.write(value)
 
     def write_address(self, af, value):
         self.write_int32(af)
-        self.write_string(value)
+        self.write_bytes(value)
 
     def read(self, size):
-        return self.fp.read(size)
+        value = b''
+        while len(value) < size:
+            data = self.fp.read(size - len(value))
+            if not data:
+                raise IOError('NSLCD protocol cut short')
+            value += data
+        return value
 
     def read_int32(self):
         return _int32.unpack(self.read(_int32.size))[0]
 
+    def read_bytes(self):
+        return self.read(self.read_int32())
+
     def read_string(self):
-        num = self.read_int32()
-        return self.read(num)
+        value = self.read_bytes()
+        if sys.version_info[0] >= 3:
+            value = value.decode('utf-8')
+        return value
 
     def read_stringlist(self):
         num = self.read_int32()
-        return [self.read_string() for x in xrange(num)]
+        return [self.read_string() for x in range(num)]
 
     def read_ether(self):
         value = self.fp.read(6)
@@ -84,11 +101,11 @@ class NslcdClient(object):
 
     def read_address(self):
         af = self.read_int32()
-        return af, socket.inet_ntop(af, self.read_string())
+        return af, socket.inet_ntop(af, self.read_bytes())
 
     def read_addresslist(self):
         num = self.read_int32()
-        return [self.read_address() for x in xrange(num)]
+        return [self.read_address() for x in range(num)]
 
     def get_response(self):
         # complete the request if required and check response header
diff --git a/utils/shells.py b/utils/shells.py
index cc3fca1..dcabfaf 100644
--- a/utils/shells.py
+++ b/utils/shells.py
@@ -51,14 +51,14 @@ def check(shell, asroot=False):
     if not asroot:
         if not shell:
             # FIXME: print to stderr
-            print '%s: empty shell not allowed' % sys.argv[0]
+            print('%s: empty shell not allowed' % sys.argv[0])
         else:
             # FIXME: print to stderr
-            print '%s: %s is an invalid shell' % (sys.argv[0], shell)
+            print('%s: %s is an invalid shell' % (sys.argv[0], shell))
         sys.exit(1)
     # warn if something seems wrong
     if not shell:
         # FIXME: print to stderr
-        print '%s: Warning: setting empty shell' % sys.argv[0]
+        print('%s: Warning: setting empty shell' % sys.argv[0])
     elif not shellexists(shell):
-        print '%s: Warning: %s does not exist' % (sys.argv[0], shell)
+        print('%s: Warning: %s does not exist' % (sys.argv[0], shell))
diff --git a/utils/users.py b/utils/users.py
index 3387318..25fb9da 100644
--- a/utils/users.py
+++ b/utils/users.py
@@ -43,8 +43,8 @@ class User(object):
         """Check if the user we want to modify is an LDAP user and whether
         we may modify the user information."""
         if self.asroot and self.myuid != 0:
-            print "%s: you may not modify user '%s'.\n" % \
-                    (sys.argv[0], self.username)
+            print("%s: you may not modify user '%s'.\n" %
+                  (sys.argv[0], self.username))
             sys.exit(1)
         # FIXME: check if the user is an LDAP user
 

https://arthurdejong.org/git/nss-pam-ldapd/commit/?id=9c803d72a512d1374a29e1cdc51449ad495862cb

commit 9c803d72a512d1374a29e1cdc51449ad495862cb
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Sun Jun 4 18:06:00 2017 +0200

    Add tests for getent.ldap command
    
    This more or less duplicates the tests from test_nsscmds.sh to
    test_ldapcmds.sh with some modifications for the differences in output.
    
    This also extends the test_nsscmds.sh tests to handle the case where
    shadow lookups do not go through LDAP.

diff --git a/tests/Makefile.am b/tests/Makefile.am
index 66b5da5..d3a622b 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,7 +1,7 @@
 # Makefile.am - use automake to generate Makefile.in
 #
 # Copyright (C) 2006 West Consulting
-# Copyright (C) 2006-2014 Arthur de Jong
+# Copyright (C) 2006-2017 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
@@ -20,7 +20,8 @@
 
 TESTS = test_dict test_set test_tio test_expr test_getpeercred test_cfg \
         test_attmap test_myldap.sh test_common test_nsscmds.sh \
-        test_pamcmds.sh test_manpages.sh test_clock test_tio_timeout
+        test_ldapcmds.sh test_pamcmds.sh test_manpages.sh test_clock \
+        test_tio_timeout
 if HAVE_PYTHON
   TESTS += test_pycompile.sh test_pylint.sh
 endif
@@ -37,8 +38,8 @@ check_PROGRAMS = test_dict test_set test_tio test_expr 
test_getpeercred \
                  lookup_groupbyuser
 
 EXTRA_DIST = README nslcd-test.conf usernames.txt testenv.sh test_myldap.sh \
-             test_nsscmds.sh  test_pamcmds.sh test_pamcmds.expect \
-             test_manpages.sh \
+             test_nsscmds.sh test_ldapcmds.sh test_pamcmds.sh \
+             test_pamcmds.expect test_manpages.sh \
              test_pycompile.sh test_pylint.sh pylint.rc test_doctest.sh \
              test_pynslcd_cache.py \
              setup_slapd.sh config.ldif test.ldif
diff --git a/tests/test_nsscmds.sh b/tests/test_ldapcmds.sh
similarity index 79%
copy from tests/test_nsscmds.sh
copy to tests/test_ldapcmds.sh
index 7c8056a..17b81c8 100755
--- a/tests/test_nsscmds.sh
+++ b/tests/test_ldapcmds.sh
@@ -1,8 +1,8 @@
 #!/bin/sh
 
-# test_nsscmds.sh - simple test script to check output of name lookup commands
+# test_ldapcmds.sh - simple test script to test lookups
 #
-# Copyright (C) 2007-2014 Arthur de Jong
+# Copyright (C) 2017 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
@@ -21,8 +21,6 @@
 
 # This script expects to be run in an environment where nss-pam-ldapd
 # is deployed with an LDAP server with the proper content (and nslcd running).
-# It's probably best to run this in an environment without nscd (this breaks
-# the services tests).
 
 set -e
 
@@ -30,20 +28,26 @@ set -e
 srcdir="${srcdir-`dirname "$0"`}"
 builddir="${builddir-`dirname "$0"`}"
 top_builddir="${top_builddir-${builddir}/..}"
+python="${PYTHON-python}"
 
 # ensure that we are running in the test environment
-"$srcdir/testenv.sh" check || exit 77
+"$srcdir/testenv.sh" check_nslcd || exit 77
 
-# preload our own NSS module
-if [ -e "$top_builddir/nss/nss_ldap.so" ]
+# if Python is missing, ignore
+if ! ${python} --version > /dev/null 2> /dev/null
 then
-  LD_PRELOAD="$top_builddir/nss/nss_ldap.so"
-  export LD_PRELOAD
+  echo "Python (${python}) not found"
+  exit 77
 fi
 
 # the total number of errors
 FAIL=0
 
+getent_ldap() {
+  cmd="(cd "'"'"${top_builddir}/utils"'"'"; ${python} getent.py $1)"
+  eval "$cmd"
+}
+
 check() {
   # the command to execute
   cmd="$1"
@@ -51,9 +55,9 @@ check() {
   expectfile=`mktemp -t expected.XXXXXX 2> /dev/null || tempfile -s .expected 
2> /dev/null`
   cat > "$expectfile"
   # run the command
-  echo 'test_nsscmds.sh: checking "'"$cmd"'"'
+  echo 'test_ldapcmds.sh: checking "'"getent.ldap $cmd"'"'
   actualfile=`mktemp -t actual.XXXXXX 2> /dev/null || tempfile -s .actual 2> 
/dev/null`
-  eval "$cmd" > "$actualfile" 2>&1 || true
+  getent_ldap "$cmd" > "$actualfile" 2>&1 || true
   # check for differences
   diff -Nauwi "$expectfile" "$actualfile" || FAIL=`expr $FAIL + 1`
   # remove temporary files
@@ -62,80 +66,64 @@ check() {
 
 ###########################################################################
 
-if grep '^aliases.*ldap' /etc/nsswitch.conf > /dev/null 2>&1
-then
-echo "test_nsscmds.sh: testing aliases..."
-
-# note that this doesn't work if /etc/aliases contains anything
+echo "test_ldapcmds.sh: testing aliases..."
 
 # check all aliases
-check "getent aliases|sort" << EOM
+check "aliases|sort" << EOM
 bar2:           foobar@example.com
 bar:            foobar@example.com
 foo:            bar@example.com
 EOM
 
 # get alias by name
-check "getent aliases foo" << EOM
+check "aliases foo" << EOM
 foo:            bar@example.com
 EOM
 
 # get alias by second name
-check "getent aliases bar2" << EOM
+check "aliases bar2" << EOM
 bar2:           foobar@example.com
 EOM
 
 # get alias by different case
-check "getent aliases FOO" << EOM
+check "aliases FOO" << EOM
 foo:            bar@example.com
 EOM
 
-fi  # end of aliases tests
-
 ###########################################################################
 
-if grep '^ethers.*ldap' /etc/nsswitch.conf > /dev/null 2>&1
-then
-echo "test_nsscmds.sh: testing ether..."
+echo "test_ldapcmds.sh: testing ether..."
 
 # get an entry by hostname
-check "getent ethers testhost" << EOM
+check "ethers testhost" << EOM
 0:18:8a:54:1a:8e testhost
 EOM
 
 # get an entry by alias name
-check "getent ethers testhostalias" << EOM
+check "ethers testhostalias" << EOM
 0:18:8a:54:1a:8e testhostalias
 EOM
 
 # get an entry by hostname with different case
-check "getent ethers TESTHOST" << EOM
+check "ethers TESTHOST" << EOM
 0:18:8a:54:1a:8e testhost
 EOM
 
 # get an entry by ethernet address
-check "getent ethers 0:18:8a:54:1a:8b" << EOM
+check "ethers 0:18:8a:54:1a:8b" << EOM
 0:18:8a:54:1a:8b testhost2
 EOM
 
-# get entry by ip address
-# this does not currently work, but maybe it should
-#check "getent ethers 192.0.2.123" << EOM
-#0:18:8a:54:1a:8e testhost
-#EOM
-
 # get all ethers (unsupported)
-check "getent ethers" << EOM
-Enumeration not supported on ethers
+check "ethers|sort" << EOM
+0:18:8a:54:1a:8b testhost2
+0:18:8a:54:1a:8e testhost
+0:18:8a:54:1a:8e testhostalias
 EOM
 
-fi  # end of ethers tests
-
 ###########################################################################
 
-if grep '^group.*ldap' /etc/nsswitch.conf > /dev/null 2>&1
-then
-echo "test_nsscmds.sh: testing group..."
+echo "test_ldapcmds.sh: testing group..."
 
 # function to sort group members of a group
 sortgroup() {
@@ -148,381 +136,366 @@ sortgroup() {
   done
 }
 
-check "getent group testgroup | sortgroup" << EOM
+check "group testgroup | sortgroup" << EOM
 testgroup:*:6100:arthur,test,testuser4
 EOM
 
-# this does not work because users is in /etc/group but it would
-# be nice if libc supported this
-#check "getent group users" << EOM
-#users:*:100:arthur,test
-#EOM
+check "group users" << EOM
+users:*:100:arthur,test
+EOM
 
 # group with different case should not be found
-check "getent group TESTGROUP" << EOM
+check "group TESTGROUP" << EOM
 EOM
 
-check "getent group 6100 | sortgroup" << EOM
+check "group 6100 | sortgroup" << EOM
 testgroup:*:6100:arthur,test,testuser4
 EOM
 
-check "groups arthur | sed 's/^.*://'" << EOM
-users testgroup testgroup2 grp4 grp5 grp6 grp7 grp8 grp9 grp10 grp11 grp12 
grp13 grp14 grp15 grp16 grp17 grp18
-EOM
-
-check "groups testuser4 | sed 's/^.* *: *//'" << EOM
-users testgroup testgroup2
-EOM
-
-check "getent group | egrep '^(testgroup|users|root):' | sortgroup" << EOM
-$(egrep '^(testgroup|users|root):' /etc/group)
+check "group.bymember arthur | sed 's/:.*//' | sort" << EOM
+grp10
+grp11
+grp12
+grp13
+grp14
+grp15
+grp16
+grp17
+grp18
+grp4
+grp5
+grp6
+grp7
+grp8
+grp9
+testgroup
+testgroup2
+users
+EOM
+
+check "group.bymember testuser4 | sed 's/:.*//' | sort" << EOM
+testgroup
+testgroup2
+EOM
+
+check "group | egrep '^(testgroup|users):' | sortgroup" << EOM
 testgroup:*:6100:arthur,test,testuser4
 users:*:100:arthur,test
 EOM
 
-check "getent group | wc -l" << EOM
-`grep -c '^[^#].*:' /etc/group | awk '{print $1 + 23}'`
+check "group | wc -l" << EOM
+23
 EOM
 
-check "getent group | grep ^largegroup | sortgroup" << EOM
+check "group | grep ^largegroup | sortgroup" << EOM
 
largegroup:*:1005:akraskouskas,alat,ameisinger,bdevera,behrke,bmoldan,btempel,cjody,clouder,cmanno,dbye,dciviello,dfirpo,dgivliani,dgosser,emcquiddy,enastasi,fcunard,gcubbison,gdaub,gdreitzler,ghanauer,gpomerance,gsusoev,gtinnel,gvollrath,gzuhlke,hgalavis,hhaffey,hhydrick,hmachesky,hpaek,hpolk,hsweezer,htomlinson,hzagami,igurwell,ihashbarger,jyeater,kbradbury,khathway,kklavetter,lbuchtel,lgandee,lkhubba,lmauracher,lseehafer,lvittum,mblanchet,mbodley,mciaccia,mjuris,ndipanfilo,nfilipek,nfunchess,ngata,ngullett,nkraker,nriofrio,nroepke,nrybij,oclunes,oebrani,okveton,osaines,otrevor,pdossous,phaye,psowa,purquilla,rkoonz,rlatessa,rworkowski,sdebry,sgurski,showe,slaforge,tabdelal,testusr2,testusr3,tfalconeri,tpaa,uschweyen,utrezize,vchevalier,vdelnegro,vleyton,vmedici,vmigliori,vpender,vwaltmann,wbrettschneide,wselim,wvalcin,wworf,yautin,ykisak,zgingrich,znightingale,zwinterbottom
 EOM
 
-check "getent group largegroup | sortgroup" << EOM
+check "group largegroup | sortgroup" << EOM
 
largegroup:*:1005:akraskouskas,alat,ameisinger,bdevera,behrke,bmoldan,btempel,cjody,clouder,cmanno,dbye,dciviello,dfirpo,dgivliani,dgosser,emcquiddy,enastasi,fcunard,gcubbison,gdaub,gdreitzler,ghanauer,gpomerance,gsusoev,gtinnel,gvollrath,gzuhlke,hgalavis,hhaffey,hhydrick,hmachesky,hpaek,hpolk,hsweezer,htomlinson,hzagami,igurwell,ihashbarger,jyeater,kbradbury,khathway,kklavetter,lbuchtel,lgandee,lkhubba,lmauracher,lseehafer,lvittum,mblanchet,mbodley,mciaccia,mjuris,ndipanfilo,nfilipek,nfunchess,ngata,ngullett,nkraker,nriofrio,nroepke,nrybij,oclunes,oebrani,okveton,osaines,otrevor,pdossous,phaye,psowa,purquilla,rkoonz,rlatessa,rworkowski,sdebry,sgurski,showe,slaforge,tabdelal,testusr2,testusr3,tfalconeri,tpaa,uschweyen,utrezize,vchevalier,vdelnegro,vleyton,vmedici,vmigliori,vpender,vwaltmann,wbrettschneide,wselim,wvalcin,wworf,yautin,ykisak,zgingrich,znightingale,zwinterbottom
 EOM
 
-check "getent group | grep ^hugegroup | sortgroup" << EOM
+check "group | grep ^hugegroup | sortgroup" << EOM
 
hugegroup:*:1006:ablackstock,abortignon,achhor,ademosthenes,adenicola,adishaw,aesbensen,aferge,afredin,afuchs,agarbett,agimm,agordner,ahandy,ajaquess,akertzman,akomsthoeft,akraskouskas,akravetz,alamour,alat,alienhard,amanganelli,amaslyn,amayorga,amccroskey,amcgraw,amckinney,ameisinger,aponcedeleon,apurdon,areid,arosel,ascheno,ascovel,asemons,ashuey,asivley,astrunk,atollefsrud,atonkin,awhitt,aziernicki,badair,baigner,bbeckfield,bbrenton,bcoletta,bcolorado,bdadds,bdaughenbaugh,bdevera,bdominga,behrke,beon,bfishbeck,bgavagan,bguthary,bharnois,bhelverson,bjolly,blovig,bluellen,bmadamba,bmarlin,bmarszalek,bmicklos,bmoling,bouten,bphou,bpinedo,brodgerson,broher,bromano,bscadden,bsibal,bstrede,bswantak,btempel,btheim,bveeneman,bwinterton,bwynes,cabare,carguellez,cbarlup,cbartnick,cbelardo,cbleimehl,cbotdorf,cbourek,cbrechbill,cbrom,ccyganiewicz,cdeckard,cdegravelle,cdickes,cdrumm,cfasone,cflenner,cfleurantin,cgaler,cgalinol,cgaudette,cghianni,charriman,cjody,cjuntunen,ckerska,ckistenmacher,cklem,ckodish,clapenta,clewicki,clouder,cmafnas,cmanno,cmcanulty,cmellberg,cmiramon,cnabzdyk,cnoriego,cpaccione,cpalmios,cparee,cpencil,cpentreath,cpinela,cpluid,critchie,cscullion,csever,csoomaroo,cspilis,cswigert,ctenny,ctetteh,ctuzzo,cwank,cweiss,dasiedu,daubert,dbarriball,dbertels,dblazejewski,dcaltabiano,dciullo,ddeguire,ddigerolamo,denriquez,deshmon,dfirpo,dflore,dfollman,dgiacomazzi,dgivliani,dgosser,dhammontree,dhendon,dhindsman,dholdaway,dlablue,dlanois,dlargo,dledenbach,dlongbotham,dloubier,dmahapatra,dmarchizano,dmcgillen,dminozzi,dnegri,dpebbles,draymundo,dscheurer,dsharr,dsherard,dsteever,dtashjian,dtornow,dtuholski,dwittlinger,dzurek,eaguire,eathey,ebattee,ebeachem,eberkman,ebusk,ecelestin,ecolden,ecordas,ediga,edrinkwater,edurick,egospatrick,egrago,ehathcock,ehindbaugh,ejeppesen,ekalfas,ekenady,ekeuper,eklein,eklunder,ekurter,emanikowski,emargulis,emcquiddy,emehta,eorsten,eparham,epeterson,epoinelli,erathert,erostad,eserrett,esheehan,esonia,esproull,esthill,estockwin,etunby,ewicks,ewilles,ewismer,ewuitschick,eyounglas,eziebert,fagro,faleo,farquette,fbeatrice,fberra,fberyman,fbielecki,fburrough,fcha,fcunard,ffigert,fgoben,fgrashot,fhain,fhalon,fkeef,fmarchi,fmilsaps,fnottage,fparness,fplayfair,fsapien,fsavela,fsirianni,fsplinter,fsunderland,fsymmonds,fthein,fvallian,fvascones,fverfaille,fvinal,fwidhalm,gallanson,gapkin,garchambeault,gbitar,gbolay,gcarlini,gcervantez,gchounlapane,gclapham,gcobane,gconver,gcukaj,gcummer,gcurnutt,gdaub,gdeblasio,gdeyarmond,gdrilling,gearnshaw,gfaire,gfedewa,ggehrke,ggillim,ghann,ghelderman,ghumbles,gishii,gjankowiak,gkerens,glafontaine,gloebs,gmackinder,gmassi,gmilian,gmings,gmoen,gparkersmith,gpomerance,gportolese,greiff,gsantella,gschaumburg,gshrode,gtinnel,guresti,gvollrath,gwaud,habby,hbastidos,hbetterman,hbickford,hbraim,hbrandow,hbrehmer,hbukovsky,hcafourek,hcarrizal,hchaviano,hcintron,hcowles,hcusta,hdoiel,hdyner,hfludd,hgalavis,hhaffey,hhagee,hhartranft,hholyfield,hhysong,hkarney,hkinderknecht,hkippes,hkohlmeyer,hlauchaire,hlemon,hlichota,hliverman,hloftis,hlynema,hmateer,hmatonak,hmiazga,hmogush,hmuscaro,hpalmquist,hpimpare,hpolintan,hrapisura,hrenart,hriech,hsabol,hschelb,hschoepfer,hspiry,hstreitnatter,hsweezer,htilzer,htomlinson,htsuha,hvannette,hveader,hwestermark,hwoodert,hzagami,hzinda,iambrosino,ibeto,ibreitbart,ibuzo,ibyles,ichewning,icoard,ideveyra,ienglert,igizzi,ihalford,ihanneman,ihegener,ihernan,iherrarte,ihimmelwright,ihoa,iiffert,ikadar,ikulbida,ilacourse,ilamberth,ilawbaugh,ileaman,ilevian,imarungo,imcbay,imensah,imicthell,imillin,imuehl,inarain,iogasawara,iroiger,iseipel,isowder,isplonskowski,istallcup,istarring,isteinlicht,ithum,ivanschaack,iweibe,iyorgey,iyorks,jamber,jappleyard,jbielicki,jbjorkman,jcaroll,jdodge,jeuresti,jeverton,jglotzbecker,jherkenratt,jholzmiller,jjumalon,jkimpton,jknight,jlebouf,jlunney,jmartha,jmarugg,jmatty,joligee,jquicksall,jrees,jreigh,jroman,jscheitlin,jseen,jsegundo,jsenavanh,jskafec,jspohn,jsweezy,jvillaire,jwinterton,jzych,kaanerud,kalguire,kbarnthouse,kbartolet,kbattershell,kbrevitz,kbrugal,kcofrancesco,kcomparoni,kconkey,kdevincent,kepps,kfaure,kfend,kgarced,kgremminger,khartness,kheadlon,khovanesian,kjoslyn,klitehiser,klundsten,klurie,kmallach,kmandolfo,kmarzili,kmayoras,kmcardle,kmcguire,kmedcaf,kmeester,kmisove,kmoesch,kmosko,kmuros,kolexa,kottomaniello,kpalka,kpannunzio,kpenale,kpuebla,krahman,kseisler,kshippy,ksiering,ksollitto,ksparling,kstachurski,kthede,ktoni,ktriblett,ktuccio,ktuner,kwidrick,kwinterling,kwirght,laksamit,lautovino,lbanco,lbassin,lbove,lbuchtel,lcanestrini,lcaudell,lcavez,lcocherell,lcoulon,lcremer,leberhardt,lfarraj,lfichtner,lgadomski,lgandee,lgradilla,lhuggler,limbrogno,ljomes,lkimel,llarmore,llasher,lmadruga,lmauracher,lmcgeary,lmichaud,lmuehlberger,lnormand,lparrish,lpeagler,lpintor,lpitek,lpondexter,lrandall,lringuette,lschenkelberg,lschnorbus,lschollmeier,lseabold,lseehafer,lshilling,lsivic,lsobrino,lsous,lspielvogel,lvaleriano,lvanconant,lwedner,lyoula,mallmand,maustine,mbeagley,mbodley,mbravata,mcampagnone,mcaram,mcashett,mcasida,mcoch,mcolehour,mcontreras,mdanos,mdecourcey,mdedon,mdickinson,mdimaio,mdoering,mdyce,meconomides,mespinel,mfaeth,mfeil,mferandez,mfitzherbert,mgavet,mgayden,mground,mheilbrun,mhollings,mjeon,mkibler,mkofoed,mlaverde,mlenning,mlinak,mlinardi,mmangiamele,mmattu,mmcchristian,mmerriwether,mmesidor,mneubacher,moller,moser,mpanahon,mpark,mpellew,mpilon,mpizzaro,mpytko,mquigg,mredd,mrizer,mruppel,mrydelek,mskeele,mstirn,mswogger,mtanzi,mtintle,mvanbergen,mvanpelt,mvas,mvedder,mviverette,myokoyama,nagerton,nasmar,nbuford,nbugtong,ncermeno,nchrisman,nciucci,ndesautels,ndrumgole,nedgin,nendicott,nerbach,nevan,nforti,nfunchess,ngiesler,nglathar,ngrowney,ngullett,nhayer,nhelfinstine,nhija,ninnella,njordon,nkempon,nkubley,nlainhart,nlatchaw,nlemma,nlinarez,nlohmiller,nmccolm,nmoren,nnamanworth,nnickel,nousdahl,nphan,nramones,nranck,nridinger,nriofrio,nrybij,nrysavy,nschmig,nsiemonsma,nslaby,nspolar,nvyhnal,nwescott,nwiker,oahyou,oalthouse,obeaufait,obenallack,obercier,obihl,ocalleo,ochasten,oclunes,oconerly,ocrabbs,oebrani,ofelcher,ohatto,ohearl,ohedlund,ohoffert,ohove,ojerabek,okave,okveton,omalvaez,omasone,omatula,omcdaid,oolivarez,oosterhouse,opeet,opizzuti,opoch,oport,opuglisi,oreiss,osaber,oscarpello,oshough,ovibbert,owhelchel,owhitelow,pahles,pbascom,pbeckerdite,pbiggart,pbondroff,pbrentano,pcaposole,pcornn,pdauterman,pdech,pdischinger,pduitscher,pdulac,pdurando,pfavolise,pgiegerich,pgreenier,pgrybel,phalkett,pheathcock,phyer,pmineo,pminnis,ppedraja,ppeper,pphuaphes,prepasky,prowena,psabado,psalesky,pschrayter,psharits,psiroky,psundeen,pthornberry,ptoenjes,ptraweek,purquilla,pvierthaler,pvirelli,pviviani,pwademan,pwashuk,pwetherwax,pwhitmire,pwohlenhaus,pwutzke,qhanly,ralspach,rbernhagen,rbillingsly,rbloomstrand,rbrisby,rcheshier,rchevrette,rdubs,rdubuisson,redling,rfassinger,rfauerbach,rfidel,rginer,rgoonez,rgramby,rgriffies,rguinane,rheinzmann,rkraszewski,rlambertus,rlatessa,rlosinger,rmandril,rmcstay,rnordby,rpastorin,rpikes,rpinilla,rpitter,rramirez,rrasual,rschkade,rtole,rtooker,saben,sackles,sarndt,saycock,sbemo,sbettridge,sbloise,sbonnie,sbrabyn,scocuzza,sdebry,senrico,sestergard,sgefroh,sgirsh,sgropper,sgunder,sgurski,shaith,sherzberg,showe,sjankauskas,skanjirathinga,skoegler,slaningham,slaudeman,slerew,smccaie,smillian,smullowney,snotari,spolmer,srees,srubenfield,sscheiern,sskone,sskyers,sspagnuolo,sstough,sstuemke,svandewalle,svielle,svogler,svongal,swoodie,tabdelal,tairth,tbagne,tbattista,tboxx,tcacal,tcossa,tcrissinger,tdonathan,teliades,tfalconeri,tfetherston,tgelen,tgindhart,tguinnip,tharr,thelfritz,thoch,thynson,tkeala,tkelly,tkhora,tlana,tlowers,tmalecki,tmarkus,tmccaffity,tmccamish,tmcmickle,tmelland,tmorr,tmurata,tmysinger,tnaillon,tnitzel,tpaa,tplatko,tredfearn,tsablea,tsann,tschnepel,tsearle,tsepulueda,tsowells,tstalworth,tvehrs,tvrooman,tyounglas,ualway,uazatyan,ubenken,ubieniek,ubynum,udatu,uednilao,ueriks,uflander,ugerpheide,ugreenberg,uhayakawa,uholecek,ulanigan,umarbury,umosser,upater,upellam,uransford,urosentrance,uschweyen,usevera,uslavinski,uspittler,uvanmatre,uwalpole,uweyand,vbaldasaro,vbigalow,vbonder,vburton,vchevalier,vcrofton,vdesir,vdolan,veisenhardt,vemily,venfort,vfeigel,vglidden,vkrug,vlubic,vmaynard,vmedici,vnazzal,vnery,vpeairs,vpender,vpiraino,vrodick,vrunyon,vsefcovic,vstirman,vtowell,vtresch,vtrumpp,vwabasha,vwaltmann,vwisinger,vwokwicz,wbrill,wclokecloak,wconces,wconstantino,wcreggett,wdagrella,wdevenish,wdovey,wenglander,werrick,wesguerra,wganther,wkhazaleh,wleiva,wlynch,wmailey,wmendell,wnunziata,wottesen,wselim,wstjean,wtruman,wvalcin,wvermeulen,xeppley,xlantey,xrahaim,yautin,ycerasoli,ycobetto,ycostaneda,yduft,yeven,yfrymoyer,ygockel,yhenriques,ykimbel,yolivier,yschmuff,ysnock,yvdberg,zanderlik,zborgmeyer,zbuscaglia,zculp,zfarler,zhaulk,zkutchera,zmeeker,zneeb,zratti,zscammahorn,zvagt,zwinterbottom
 EOM
 
-check "getent group hugegroup | sortgroup" << EOM
+check "group hugegroup | sortgroup" << EOM
 
hugegroup:*:1006:ablackstock,abortignon,achhor,ademosthenes,adenicola,adishaw,aesbensen,aferge,afredin,afuchs,agarbett,agimm,agordner,ahandy,ajaquess,akertzman,akomsthoeft,akraskouskas,akravetz,alamour,alat,alienhard,amanganelli,amaslyn,amayorga,amccroskey,amcgraw,amckinney,ameisinger,aponcedeleon,apurdon,areid,arosel,ascheno,ascovel,asemons,ashuey,asivley,astrunk,atollefsrud,atonkin,awhitt,aziernicki,badair,baigner,bbeckfield,bbrenton,bcoletta,bcolorado,bdadds,bdaughenbaugh,bdevera,bdominga,behrke,beon,bfishbeck,bgavagan,bguthary,bharnois,bhelverson,bjolly,blovig,bluellen,bmadamba,bmarlin,bmarszalek,bmicklos,bmoling,bouten,bphou,bpinedo,brodgerson,broher,bromano,bscadden,bsibal,bstrede,bswantak,btempel,btheim,bveeneman,bwinterton,bwynes,cabare,carguellez,cbarlup,cbartnick,cbelardo,cbleimehl,cbotdorf,cbourek,cbrechbill,cbrom,ccyganiewicz,cdeckard,cdegravelle,cdickes,cdrumm,cfasone,cflenner,cfleurantin,cgaler,cgalinol,cgaudette,cghianni,charriman,cjody,cjuntunen,ckerska,ckistenmacher,cklem,ckodish,clapenta,clewicki,clouder,cmafnas,cmanno,cmcanulty,cmellberg,cmiramon,cnabzdyk,cnoriego,cpaccione,cpalmios,cparee,cpencil,cpentreath,cpinela,cpluid,critchie,cscullion,csever,csoomaroo,cspilis,cswigert,ctenny,ctetteh,ctuzzo,cwank,cweiss,dasiedu,daubert,dbarriball,dbertels,dblazejewski,dcaltabiano,dciullo,ddeguire,ddigerolamo,denriquez,deshmon,dfirpo,dflore,dfollman,dgiacomazzi,dgivliani,dgosser,dhammontree,dhendon,dhindsman,dholdaway,dlablue,dlanois,dlargo,dledenbach,dlongbotham,dloubier,dmahapatra,dmarchizano,dmcgillen,dminozzi,dnegri,dpebbles,draymundo,dscheurer,dsharr,dsherard,dsteever,dtashjian,dtornow,dtuholski,dwittlinger,dzurek,eaguire,eathey,ebattee,ebeachem,eberkman,ebusk,ecelestin,ecolden,ecordas,ediga,edrinkwater,edurick,egospatrick,egrago,ehathcock,ehindbaugh,ejeppesen,ekalfas,ekenady,ekeuper,eklein,eklunder,ekurter,emanikowski,emargulis,emcquiddy,emehta,eorsten,eparham,epeterson,epoinelli,erathert,erostad,eserrett,esheehan,esonia,esproull,esthill,estockwin,etunby,ewicks,ewilles,ewismer,ewuitschick,eyounglas,eziebert,fagro,faleo,farquette,fbeatrice,fberra,fberyman,fbielecki,fburrough,fcha,fcunard,ffigert,fgoben,fgrashot,fhain,fhalon,fkeef,fmarchi,fmilsaps,fnottage,fparness,fplayfair,fsapien,fsavela,fsirianni,fsplinter,fsunderland,fsymmonds,fthein,fvallian,fvascones,fverfaille,fvinal,fwidhalm,gallanson,gapkin,garchambeault,gbitar,gbolay,gcarlini,gcervantez,gchounlapane,gclapham,gcobane,gconver,gcukaj,gcummer,gcurnutt,gdaub,gdeblasio,gdeyarmond,gdrilling,gearnshaw,gfaire,gfedewa,ggehrke,ggillim,ghann,ghelderman,ghumbles,gishii,gjankowiak,gkerens,glafontaine,gloebs,gmackinder,gmassi,gmilian,gmings,gmoen,gparkersmith,gpomerance,gportolese,greiff,gsantella,gschaumburg,gshrode,gtinnel,guresti,gvollrath,gwaud,habby,hbastidos,hbetterman,hbickford,hbraim,hbrandow,hbrehmer,hbukovsky,hcafourek,hcarrizal,hchaviano,hcintron,hcowles,hcusta,hdoiel,hdyner,hfludd,hgalavis,hhaffey,hhagee,hhartranft,hholyfield,hhysong,hkarney,hkinderknecht,hkippes,hkohlmeyer,hlauchaire,hlemon,hlichota,hliverman,hloftis,hlynema,hmateer,hmatonak,hmiazga,hmogush,hmuscaro,hpalmquist,hpimpare,hpolintan,hrapisura,hrenart,hriech,hsabol,hschelb,hschoepfer,hspiry,hstreitnatter,hsweezer,htilzer,htomlinson,htsuha,hvannette,hveader,hwestermark,hwoodert,hzagami,hzinda,iambrosino,ibeto,ibreitbart,ibuzo,ibyles,ichewning,icoard,ideveyra,ienglert,igizzi,ihalford,ihanneman,ihegener,ihernan,iherrarte,ihimmelwright,ihoa,iiffert,ikadar,ikulbida,ilacourse,ilamberth,ilawbaugh,ileaman,ilevian,imarungo,imcbay,imensah,imicthell,imillin,imuehl,inarain,iogasawara,iroiger,iseipel,isowder,isplonskowski,istallcup,istarring,isteinlicht,ithum,ivanschaack,iweibe,iyorgey,iyorks,jamber,jappleyard,jbielicki,jbjorkman,jcaroll,jdodge,jeuresti,jeverton,jglotzbecker,jherkenratt,jholzmiller,jjumalon,jkimpton,jknight,jlebouf,jlunney,jmartha,jmarugg,jmatty,joligee,jquicksall,jrees,jreigh,jroman,jscheitlin,jseen,jsegundo,jsenavanh,jskafec,jspohn,jsweezy,jvillaire,jwinterton,jzych,kaanerud,kalguire,kbarnthouse,kbartolet,kbattershell,kbrevitz,kbrugal,kcofrancesco,kcomparoni,kconkey,kdevincent,kepps,kfaure,kfend,kgarced,kgremminger,khartness,kheadlon,khovanesian,kjoslyn,klitehiser,klundsten,klurie,kmallach,kmandolfo,kmarzili,kmayoras,kmcardle,kmcguire,kmedcaf,kmeester,kmisove,kmoesch,kmosko,kmuros,kolexa,kottomaniello,kpalka,kpannunzio,kpenale,kpuebla,krahman,kseisler,kshippy,ksiering,ksollitto,ksparling,kstachurski,kthede,ktoni,ktriblett,ktuccio,ktuner,kwidrick,kwinterling,kwirght,laksamit,lautovino,lbanco,lbassin,lbove,lbuchtel,lcanestrini,lcaudell,lcavez,lcocherell,lcoulon,lcremer,leberhardt,lfarraj,lfichtner,lgadomski,lgandee,lgradilla,lhuggler,limbrogno,ljomes,lkimel,llarmore,llasher,lmadruga,lmauracher,lmcgeary,lmichaud,lmuehlberger,lnormand,lparrish,lpeagler,lpintor,lpitek,lpondexter,lrandall,lringuette,lschenkelberg,lschnorbus,lschollmeier,lseabold,lseehafer,lshilling,lsivic,lsobrino,lsous,lspielvogel,lvaleriano,lvanconant,lwedner,lyoula,mallmand,maustine,mbeagley,mbodley,mbravata,mcampagnone,mcaram,mcashett,mcasida,mcoch,mcolehour,mcontreras,mdanos,mdecourcey,mdedon,mdickinson,mdimaio,mdoering,mdyce,meconomides,mespinel,mfaeth,mfeil,mferandez,mfitzherbert,mgavet,mgayden,mground,mheilbrun,mhollings,mjeon,mkibler,mkofoed,mlaverde,mlenning,mlinak,mlinardi,mmangiamele,mmattu,mmcchristian,mmerriwether,mmesidor,mneubacher,moller,moser,mpanahon,mpark,mpellew,mpilon,mpizzaro,mpytko,mquigg,mredd,mrizer,mruppel,mrydelek,mskeele,mstirn,mswogger,mtanzi,mtintle,mvanbergen,mvanpelt,mvas,mvedder,mviverette,myokoyama,nagerton,nasmar,nbuford,nbugtong,ncermeno,nchrisman,nciucci,ndesautels,ndrumgole,nedgin,nendicott,nerbach,nevan,nforti,nfunchess,ngiesler,nglathar,ngrowney,ngullett,nhayer,nhelfinstine,nhija,ninnella,njordon,nkempon,nkubley,nlainhart,nlatchaw,nlemma,nlinarez,nlohmiller,nmccolm,nmoren,nnamanworth,nnickel,nousdahl,nphan,nramones,nranck,nridinger,nriofrio,nrybij,nrysavy,nschmig,nsiemonsma,nslaby,nspolar,nvyhnal,nwescott,nwiker,oahyou,oalthouse,obeaufait,obenallack,obercier,obihl,ocalleo,ochasten,oclunes,oconerly,ocrabbs,oebrani,ofelcher,ohatto,ohearl,ohedlund,ohoffert,ohove,ojerabek,okave,okveton,omalvaez,omasone,omatula,omcdaid,oolivarez,oosterhouse,opeet,opizzuti,opoch,oport,opuglisi,oreiss,osaber,oscarpello,oshough,ovibbert,owhelchel,owhitelow,pahles,pbascom,pbeckerdite,pbiggart,pbondroff,pbrentano,pcaposole,pcornn,pdauterman,pdech,pdischinger,pduitscher,pdulac,pdurando,pfavolise,pgiegerich,pgreenier,pgrybel,phalkett,pheathcock,phyer,pmineo,pminnis,ppedraja,ppeper,pphuaphes,prepasky,prowena,psabado,psalesky,pschrayter,psharits,psiroky,psundeen,pthornberry,ptoenjes,ptraweek,purquilla,pvierthaler,pvirelli,pviviani,pwademan,pwashuk,pwetherwax,pwhitmire,pwohlenhaus,pwutzke,qhanly,ralspach,rbernhagen,rbillingsly,rbloomstrand,rbrisby,rcheshier,rchevrette,rdubs,rdubuisson,redling,rfassinger,rfauerbach,rfidel,rginer,rgoonez,rgramby,rgriffies,rguinane,rheinzmann,rkraszewski,rlambertus,rlatessa,rlosinger,rmandril,rmcstay,rnordby,rpastorin,rpikes,rpinilla,rpitter,rramirez,rrasual,rschkade,rtole,rtooker,saben,sackles,sarndt,saycock,sbemo,sbettridge,sbloise,sbonnie,sbrabyn,scocuzza,sdebry,senrico,sestergard,sgefroh,sgirsh,sgropper,sgunder,sgurski,shaith,sherzberg,showe,sjankauskas,skanjirathinga,skoegler,slaningham,slaudeman,slerew,smccaie,smillian,smullowney,snotari,spolmer,srees,srubenfield,sscheiern,sskone,sskyers,sspagnuolo,sstough,sstuemke,svandewalle,svielle,svogler,svongal,swoodie,tabdelal,tairth,tbagne,tbattista,tboxx,tcacal,tcossa,tcrissinger,tdonathan,teliades,tfalconeri,tfetherston,tgelen,tgindhart,tguinnip,tharr,thelfritz,thoch,thynson,tkeala,tkelly,tkhora,tlana,tlowers,tmalecki,tmarkus,tmccaffity,tmccamish,tmcmickle,tmelland,tmorr,tmurata,tmysinger,tnaillon,tnitzel,tpaa,tplatko,tredfearn,tsablea,tsann,tschnepel,tsearle,tsepulueda,tsowells,tstalworth,tvehrs,tvrooman,tyounglas,ualway,uazatyan,ubenken,ubieniek,ubynum,udatu,uednilao,ueriks,uflander,ugerpheide,ugreenberg,uhayakawa,uholecek,ulanigan,umarbury,umosser,upater,upellam,uransford,urosentrance,uschweyen,usevera,uslavinski,uspittler,uvanmatre,uwalpole,uweyand,vbaldasaro,vbigalow,vbonder,vburton,vchevalier,vcrofton,vdesir,vdolan,veisenhardt,vemily,venfort,vfeigel,vglidden,vkrug,vlubic,vmaynard,vmedici,vnazzal,vnery,vpeairs,vpender,vpiraino,vrodick,vrunyon,vsefcovic,vstirman,vtowell,vtresch,vtrumpp,vwabasha,vwaltmann,vwisinger,vwokwicz,wbrill,wclokecloak,wconces,wconstantino,wcreggett,wdagrella,wdevenish,wdovey,wenglander,werrick,wesguerra,wganther,wkhazaleh,wleiva,wlynch,wmailey,wmendell,wnunziata,wottesen,wselim,wstjean,wtruman,wvalcin,wvermeulen,xeppley,xlantey,xrahaim,yautin,ycerasoli,ycobetto,ycostaneda,yduft,yeven,yfrymoyer,ygockel,yhenriques,ykimbel,yolivier,yschmuff,ysnock,yvdberg,zanderlik,zborgmeyer,zbuscaglia,zculp,zfarler,zhaulk,zkutchera,zmeeker,zneeb,zratti,zscammahorn,zvagt,zwinterbottom
 EOM
 
-check "getent group nstgrp1 | sortgroup" << EOM
+check "group nstgrp1 | sortgroup" << EOM
 nstgrp1:*:800:testusr2
 EOM
 
-check "getent group nstgrp2 | sortgroup" << EOM
+check "group nstgrp2 | sortgroup" << EOM
 nstgrp2:*:801:testusr2,testusr3
 EOM
 
-check "getent group nstgrp3 | sortgroup" << EOM
+check "group nstgrp3 | sortgroup" << EOM
 nstgrp3:*:802:testusr2,testusr3
 EOM
 
-check "groups testusr2 | sed 's/^.* *: *//'" << EOM
-users largegroup testgroup2 nstgrp1 nstgrp2 nstgrp3
+check "group.bymember testusr2 | sed 's/:.*//' | sort" << EOM
+largegroup
+nstgrp1
+nstgrp2
+nstgrp3
+testgroup2
 EOM
 
-check "groups testusr3 | sed 's/^.* *: *//'" << EOM
-users largegroup nstgrp2 nstgrp3
+check "group.bymember testusr3 | sed 's/:.*//' | sort" << EOM
+largegroup
+nstgrp2
+nstgrp3
 EOM
 
-fi  # end of group tests
-
 ###########################################################################
 
-if grep '^hosts.*ldap' /etc/nsswitch.conf > /dev/null 2>&1
-then
-echo "test_nsscmds.sh: testing hosts..."
+echo "test_ldapcmds.sh: testing hosts..."
 
-check "getent hosts testhost" << EOM
+check "hosts testhost" << EOM
 192.0.2.123        testhost testhostalias
 EOM
 
-check "getent hosts testhostalias" << EOM
+check "hosts testhostalias" << EOM
 192.0.2.123        testhost testhostalias
 EOM
 
 # check hostname with different case
-check "getent hosts TESTHOST" << EOM
+check "hosts TESTHOST" << EOM
 192.0.2.123        testhost testhostalias
 EOM
 
-check "getent hosts 192.0.2.123" << EOM
+check "hosts 192.0.2.123" << EOM
 192.0.2.123        testhost testhostalias
 EOM
 
-check "getent hosts | grep testhost | sort" << EOM
+check "hosts | grep testhost | sort" << EOM
 192.0.2.123        testhost testhostalias
 192.0.2.124        testhost2
 192.0.2.126        testhost4
+2001:db8::7e27:ac1d testhost4
+2001:db8::dead:beef testhost2
+2001:db8::feed:c0de testhost3
 EOM
 
-check "getent hosts 2001:db8::dead:beef" << EOM
+check "hosts 2001:db8::dead:beef | sort" << EOM
+192.0.2.124     testhost2
 2001:db8::dead:beef testhost2
 EOM
 
-check "getent ahosts testhost2" << EOM
-2001:db8::dead:beef STREAM testhost2
-2001:db8::dead:beef DGRAM
-2001:db8::dead:beef RAW
-192.0.2.124     STREAM
-192.0.2.124     DGRAM
-192.0.2.124     RAW
+check "hostsv4 testhost2" << EOM
+192.0.2.124     testhost2
 EOM
 
-check "getent hosts testhost3" << EOM
-2001:db8::feed:c0de testhost3
+check "hostsv6 testhost2" << EOM
+2001:db8::dead:beef testhost2
 EOM
 
-check "getent ahosts testhost3" << EOM
-2001:db8::feed:c0de STREAM testhost3
-2001:db8::feed:c0de DGRAM
-2001:db8::feed:c0de RAW
+check "hostsv4 192.0.2.124" << EOM
+192.0.2.124     testhost2
 EOM
 
-check "getent ahosts testhost4" << EOM
-2001:db8::7e27:ac1d STREAM testhost4
-2001:db8::7e27:ac1d DGRAM
-2001:db8::7e27:ac1d RAW
-192.0.2.126     STREAM
-192.0.2.126     DGRAM
-192.0.2.126     RAW
+check "hostsv6 2001:db8::dead:beef" << EOM
+2001:db8::dead:beef testhost2
 EOM
 
-fi  # end of hosts tests
+check "hostsv4 2001:db8::dead:beef" << EOM
+EOM
+
+check "hostsv6 192.0.2.124" << EOM
+EOM
 
 ###########################################################################
 
-if grep '^netgroup.*ldap' /etc/nsswitch.conf > /dev/null 2>&1
-then
-echo "test_nsscmds.sh: testing netgroup..."
+echo "test_ldapcmds.sh: testing netgroup..."
 
 # check netgroup lookup of test netgroup
-check "getent netgroup tstnetgroup" << EOM
+check "netgroup tstnetgroup" << EOM
 tstnetgroup          ( , arthur, ) (noot, , )
 EOM
 
 # check netgroup lookup with different case
-check "getent netgroup TSTNETGROUP" << EOM
+check "netgroup TSTNETGROUP" << EOM
 EOM
 
-fi  # end of netgroup tests
+# check netgroup lookup of test netgroup without recursion
+check "netgroup.norec tstnetgroup" << EOM
+tstnetgroup     tst3netgroup tst2netgroup (, arthur, )
+EOM
 
 ###########################################################################
 
-if grep '^networks.*ldap' /etc/nsswitch.conf > /dev/null 2>&1
-then
-echo "test_nsscmds.sh: testing networks..."
+echo "test_ldapcmds.sh: testing networks..."
 
-check "getent networks testnet" << EOM
+check "networks testnet" << EOM
 testnet               192.0.2.0
 EOM
 
 # check network name with different case
-check "getent networks TESTNET" << EOM
+check "networks TESTNET" << EOM
 testnet               192.0.2.0
 EOM
 
-check "getent networks 192.0.2.0" << EOM
+check "networks 192.0.2.0" << EOM
 testnet               192.0.2.0
 EOM
 
-check "getent networks | grep testnet" << EOM
+check "networks | grep testnet" << EOM
 testnet               192.0.2.0
 EOM
 
-fi  # end of networks tests
-
 ###########################################################################
 
-if grep '^passwd.*ldap' /etc/nsswitch.conf > /dev/null 2>&1
-then
-echo "test_nsscmds.sh: testing passwd..."
+echo "test_ldapcmds.sh: testing passwd..."
 
-check "getent passwd ecolden" << EOM
+check "passwd ecolden | sed 's/:[x*]:/:x:/'" << EOM
 ecolden:x:5972:1000:Estelle Colden:/home/ecolden:/bin/bash
 EOM
 
-check "getent passwd arthur" << EOM
+check "passwd arthur | sed 's/:[x*]:/:x:/'" << EOM
 arthur:x:1000:100:Arthur de Jong:/home/arthur:/bin/bash
 EOM
 
 # check username with different case
-check "getent passwd ARTHUR" << EOM
+check "passwd ARTHUR" << EOM
 EOM
 
-check "getent passwd 4089" << EOM
+check "passwd 4089 | sed 's/:[x*]:/:x:/'" << EOM
 jguzzetta:x:4089:1000:Josephine Guzzetta:/home/jguzzetta:/bin/bash
 EOM
 
 # count the number of passwd entries in the 4000-5999 range
-check "getent passwd | grep -c ':x:[45][0-9][0-9][0-9]:'" << EOM
+check "passwd | grep -c ':[x*]:[45][0-9][0-9][0-9]:'" << EOM
 2000
 EOM
 
-fi  # end of passwd tests
-
 ###########################################################################
 
-if grep '^protocols.*ldap' /etc/nsswitch.conf > /dev/null 2>&1
-then
-echo "test_nsscmds.sh: testing protocols..."
+echo "test_ldapcmds.sh: testing protocols..."
 
-check "getent protocols protfoo" << EOM
+check "protocols protfoo" << EOM
 protfoo               253 protfooalias
 EOM
 
-check "getent protocols protfooalias" << EOM
+check "protocols protfooalias" << EOM
 protfoo               253 protfooalias
 EOM
 
 # check protocol with different case
-check "getent protocols PROTFOO" << EOM
+check "protocols PROTFOO" << EOM
 EOM
 
 # test protocol alias with different case
-check "getent protocols PROTFOOALIAS" << EOM
+check "protocols PROTFOOALIAS" << EOM
 EOM
 
-check "getent protocols 253" << EOM
+check "protocols 253" << EOM
 protfoo               253 protfooalias
 EOM
 
-check "getent protocols icmp" << EOM
-icmp                  1 ICMP
-EOM
-
-check "getent protocols | grep protfoo" << EOM
+check "protocols | grep protfoo" << EOM
 protfoo               253 protfooalias
 EOM
 
-fi  # end of protocols tests
-
 ###########################################################################
 
-if grep '^rpc.*ldap' /etc/nsswitch.conf > /dev/null 2>&1
-then
-echo "test_nsscmds.sh: testing rpc..."
+echo "test_ldapcmds.sh: testing rpc..."
 
-check "getent rpc rpcfoo" << EOM
+check "rpc rpcfoo" << EOM
 rpcfoo          160002  rpcfooalias
 EOM
 
-check "getent rpc rpcfooalias" << EOM
+check "rpc rpcfooalias" << EOM
 rpcfoo          160002  rpcfooalias
 EOM
 
 # test rpc name with different case
-check "getent rpc RPCFOO" << EOM
+check "rpc RPCFOO" << EOM
 EOM
 
-check "getent rpc 160002" << EOM
+check "rpc 160002" << EOM
 rpcfoo          160002  rpcfooalias
 EOM
 
-check "getent rpc | grep rpcfoo" << EOM
+check "rpc | grep rpcfoo" << EOM
 rpcfoo          160002  rpcfooalias
 EOM
 
-fi  # end of rpc tests
-
 ###########################################################################
 
-if grep '^services.*ldap' /etc/nsswitch.conf > /dev/null 2>&1
-then
-echo "test_nsscmds.sh: testing services..."
+echo "test_ldapcmds.sh: testing services..."
 
-check "getent services foosrv" << EOM
+check "services foosrv" << EOM
 foosrv                15349/tcp
 EOM
 
-check "getent services foosrv/tcp" << EOM
+check "services foosrv/tcp" << EOM
 foosrv                15349/tcp
 EOM
 
-check "getent services foosrv/udp" << EOM
+check "services foosrv/udp" << EOM
 EOM
 
 # check with different case
-check "getent services FOOSRV" << EOM
+check "services FOOSRV" << EOM
 EOM
 
 # check protocol name case sensitivity (TCP is commonly an alias)
-check "getent services foosrv/tCp" << EOM
+check "services foosrv/tCp" << EOM
 EOM
 
-check "getent services 15349/tcp" << EOM
+check "services 15349/tcp" << EOM
 foosrv                15349/tcp
 EOM
 
-check "getent services 15349/udp" << EOM
+check "services 15349/udp" << EOM
 EOM
 
-check "getent services barsrv" << EOM
+check "services barsrv | sort" << EOM
 barsrv                15350/tcp
+barsrv                15350/udp
 EOM
 
-check "getent services barsrv/tcp" << EOM
+check "services barsrv/tcp" << EOM
 barsrv                15350/tcp
 EOM
 
-check "getent services barsrv/udp" << EOM
+check "services barsrv/udp" << EOM
 barsrv                15350/udp
 EOM
 
-check "getent services | egrep '(foo|bar)srv' | sort" << EOM
+check "services | egrep '(foo|bar)srv' | sort" << EOM
 barsrv                15350/tcp
 barsrv                15350/udp
 foosrv                15349/tcp
 EOM
 
-check "getent services sssin" << EOM
+check "services sssin" << EOM
 sssin                 5000/tcp SSSIN
 EOM
 
-check "getent services SSSIN" << EOM
+check "services SSSIN" << EOM
 sssin                 5000/tcp SSSIN
 EOM
 
-check "getent services | wc -l" << EOM
-`grep -c '^[^#].' /etc/services | awk '{print $1 + 4}'`
+check "services | sort" << EOM
+barsrv                15350/tcp
+barsrv                15350/udp
+foosrv                15349/tcp
+sssin                 5000/tcp SSSIN
 EOM
 
-fi  # end of services tests
-
 ###########################################################################
 
-if grep '^shadow.*ldap' /etc/nsswitch.conf > /dev/null 2>&1
-then
-echo "test_nsscmds.sh: testing shadow..."
+echo "test_ldapcmds.sh: testing shadow..."
 
 # NOTE: the output of this should depend on whether we are root or not
 
-check "getent shadow ecordas" << EOM
+check "shadow ecordas" << EOM
 ecordas:*::::7:2::0
 EOM
 
-check "getent shadow adishaw" << EOM
+check "shadow adishaw" << EOM
 adishaw:*:12302:::7:2::0
 EOM
 
 # check case-sensitivity
-check "getent shadow ADISHAW" << EOM
-EOM
-
-# check if the number of passwd entries matches the number of shadow entries
-check "getent shadow | wc -l" << EOM
-`getent passwd | wc -l`
+check "shadow ADISHAW" << EOM
 EOM
 
 # check if the names of users match between passwd and shadow
-getent passwd | sed 's/:.*//' | sort | \
-  check "getent shadow | sed 's/:.*//' | sort"
-
-fi  # end of shadow tests
+getent_ldap "passwd | sed 's/:.*//' | sort" | \
+  check "shadow | sed 's/:.*//' | sort"
 
 ###########################################################################
 # determine the result
 
 if [ $FAIL -eq 0 ]
 then
-  echo "test_nsscmds.sh: all tests passed"
+  echo "test_ldapcmds.sh: all tests passed"
   exit 0
 else
-  echo "test_nsscmds.sh: $FAIL TESTS FAILED"
+  echo "test_ldapcmds.sh: $FAIL TESTS FAILED"
   exit 1
 fi
diff --git a/tests/test_nsscmds.sh b/tests/test_nsscmds.sh
index 7c8056a..846ad43 100755
--- a/tests/test_nsscmds.sh
+++ b/tests/test_nsscmds.sh
@@ -2,7 +2,7 @@
 
 # test_nsscmds.sh - simple test script to check output of name lookup commands
 #
-# Copyright (C) 2007-2014 Arthur de Jong
+# Copyright (C) 2007-2017 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
@@ -333,11 +333,11 @@ if grep '^passwd.*ldap' /etc/nsswitch.conf > /dev/null 
2>&1
 then
 echo "test_nsscmds.sh: testing passwd..."
 
-check "getent passwd ecolden" << EOM
+check "getent passwd ecolden | sed 's/:[x*]:/:x:/'" << EOM
 ecolden:x:5972:1000:Estelle Colden:/home/ecolden:/bin/bash
 EOM
 
-check "getent passwd arthur" << EOM
+check "getent passwd arthur | sed 's/:[x*]:/:x:/'" << EOM
 arthur:x:1000:100:Arthur de Jong:/home/arthur:/bin/bash
 EOM
 
@@ -345,12 +345,12 @@ EOM
 check "getent passwd ARTHUR" << EOM
 EOM
 
-check "getent passwd 4089" << EOM
+check "getent passwd 4089 | sed 's/:[x*]:/:x:/'" << EOM
 jguzzetta:x:4089:1000:Josephine Guzzetta:/home/jguzzetta:/bin/bash
 EOM
 
 # count the number of passwd entries in the 4000-5999 range
-check "getent passwd | grep -c ':x:[45][0-9][0-9][0-9]:'" << EOM
+check "getent passwd | grep -c ':[x*]:[45][0-9][0-9][0-9]:'" << EOM
 2000
 EOM
 
diff --git a/tests/testenv.sh b/tests/testenv.sh
index 4d807b8..9a0a866 100755
--- a/tests/testenv.sh
+++ b/tests/testenv.sh
@@ -2,7 +2,7 @@
 
 # testenv.sh - script to check test environment
 #
-# Copyright (C) 2011-2015 Arthur de Jong
+# Copyright (C) 2011-2017 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
@@ -77,7 +77,7 @@ nss_enable()
   return 0
 }
 
-# check nsswitch.conf
+# check nsswitch.conf to see if dbs use ldap
 check_nsswitch() {
   required="${1:-passwd group}"
   if [ -r /etc/nsswitch.conf ]
@@ -171,6 +171,7 @@ check_nslcd_running() {
 
 case "$1" in
   nss_enable)
+    # modify /etc/nsswitch.conf to enable ldap for db
     shift
     while [ $# -gt 0 ]
     do
@@ -180,6 +181,7 @@ case "$1" in
     exit 0
     ;;
   check)
+    # perform all tests for test environment
     res=0
     check_nsswitch || res=1
     check_pam || res=1
@@ -190,15 +192,27 @@ case "$1" in
     exit $res
     ;;
   check_nss)
+    # check nsswitch.conf to see if dbs use ldap
     shift
     check_nsswitch "$*" || exit 1
     exit 0
     ;;
   check_ldap)
+    # check availability of LDAP server
+    # (optional URI and BASE arguments)
     shift
     check_ldap_server "$@" || exit 1
     exit 0
     ;;
+  check_nslcd)
+    # check nslcd availability
+    res=0
+    check_ldap_server || res=1
+    check_nslcd_conf || res=1
+    check_nslcd_running || res=1
+    [ $res -eq 0 ] && echo "$script: test environment OK"  || true
+    exit $res
+    ;;
   *)
     echo "Usage: $0 {nss_enable|check|check_nss|check_ldap}" >&2
     exit 1

https://arthurdejong.org/git/nss-pam-ldapd/commit/?id=a357131d4bb98e21a5b376f02d8e61ecc3a5039c

commit a357131d4bb98e21a5b376f02d8e61ecc3a5039c
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Sun Jun 4 00:04:42 2017 +0200

    Fix output of getent.ldap networks
    
    Contrary to the hosts output the network name is listed first.

diff --git a/utils/getent.py b/utils/getent.py
index a508cb9..f28a9cf 100755
--- a/utils/getent.py
+++ b/utils/getent.py
@@ -235,7 +235,7 @@ def write_networks(con, db_af):
         names = ' '.join([con.read_string()] + con.read_stringlist())
         for af, address in con.read_addresslist():
             if db_af in (af, None):
-                print '%-15s %s' % (address, names)
+                print '%-22s %s' % (names, address)
 
 
 def getent_networks(database, keys=None):

https://arthurdejong.org/git/nss-pam-ldapd/commit/?id=58c7a9406c143b41516a7c99d1b190db203f3ace

commit 58c7a9406c143b41516a7c99d1b190db203f3ace
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Sat Jun 3 23:31:54 2017 +0200

    Fix IPv6 lookups in getent.ldap

diff --git a/utils/getent.py b/utils/getent.py
index 71f1bf8..a508cb9 100755
--- a/utils/getent.py
+++ b/utils/getent.py
@@ -161,7 +161,7 @@ def getent_hosts(database, keys=None):
         if ipv4_addr and db_af in (socket.AF_INET, None):
             con = NslcdClient(constants.NSLCD_ACTION_HOST_BYADDR)
             con.write_address(socket.AF_INET, ipv4_addr)
-        elif ipv6_addr and db_af in (socket.AF_INET, None):
+        elif ipv6_addr and db_af in (socket.AF_INET6, None):
             con = NslcdClient(constants.NSLCD_ACTION_HOST_BYADDR)
             con.write_address(socket.AF_INET6, ipv6_addr)
         else:
@@ -249,7 +249,7 @@ def getent_networks(database, keys=None):
         if ipv4_addr and db_af in (socket.AF_INET, None):
             con = NslcdClient(constants.NSLCD_ACTION_NETWORK_BYADDR)
             con.write_address(socket.AF_INET, ipv4_addr)
-        elif ipv6_addr and db_af in (socket.AF_INET, None):
+        elif ipv6_addr and db_af in (socket.AF_INET6, None):
             con = NslcdClient(constants.NSLCD_ACTION_NETWORK_BYADDR)
             con.write_address(socket.AF_INET6, ipv6_addr)
         else:

https://arthurdejong.org/git/nss-pam-ldapd/commit/?id=5173e553375285c0e2ad91e67079e4b179dc6335

commit 5173e553375285c0e2ad91e67079e4b179dc6335
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Sat Jun 3 23:16:47 2017 +0200

    Accept multiple key arguments to getent.ldap
    
    This allows supplying multiple arguments to getent.ldap that will each
    act as a search key for lookups, similar to what normal getent allows.

diff --git a/man/getent.ldap.1.xml b/man/getent.ldap.1.xml
index 3d1c93f..24f24bd 100644
--- a/man/getent.ldap.1.xml
+++ b/man/getent.ldap.1.xml
@@ -3,9 +3,9 @@
                    "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd";>
 
 <!--
-   getent.ldap.1.xml - docbook manual page for chsh.ldap
+   getent.ldap.1.xml - docbook manual page for getent.ldap
 
-   Copyright (C) 2013-2016 Arthur de Jong
+   Copyright (C) 2013-2017 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,7 +50,7 @@
    <command>getent.ldap</command>
    <arg choice="opt"><replaceable>options</replaceable></arg>
    <arg><replaceable>DATABASE</replaceable></arg>
-   <arg choice="opt"><replaceable>KEY</replaceable></arg>
+   <arg choice="opt"><replaceable>KEY...</replaceable></arg>
   </cmdsynopsis>
  </refsynopsisdiv>
 
diff --git a/utils/getent.py b/utils/getent.py
index 85563ca..71f1bf8 100755
--- a/utils/getent.py
+++ b/utils/getent.py
@@ -3,7 +3,7 @@
 
 # getent.py - program for querying nslcd
 #
-# Copyright (C) 2013-2016 Arthur de Jong
+# Copyright (C) 2013-2017 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
@@ -49,16 +49,11 @@ parser = argparse.ArgumentParser(
 parser.add_argument('-V', '--version', action=VersionAction)
 parser.add_argument('database', metavar='DATABASE',
                     help='any database supported by nslcd')
-parser.add_argument('key', metavar='KEY', nargs='?',
+parser.add_argument('keys', metavar='KEY', nargs='*',
                     help='filter returned database values by key')
 
 
-def getent_aliases(database, key=None):
-    if not key:
-        con = NslcdClient(constants.NSLCD_ACTION_ALIAS_ALL)
-    else:
-        con = NslcdClient(constants.NSLCD_ACTION_ALIAS_BYNAME)
-        con.write_string(key)
+def write_aliases(con):
     while con.get_response() == constants.NSLCD_RESULT_BEGIN:
         print '%-16s%s' % (
                 con.read_string() + ': ',
@@ -66,33 +61,38 @@ def getent_aliases(database, key=None):
             )
 
 
-def getent_ethers(database, key=None):
-    if not key:
-        con = NslcdClient(constants.NSLCD_ACTION_ETHER_ALL)
-    elif re.match('^[0-9a-fA-F]{1,2}(:[0-9a-fA-F]{1,2}){5}$', key):
-        con = NslcdClient(constants.NSLCD_ACTION_ETHER_BYETHER)
-        con.write_ether(key)
-    else:
-        con = NslcdClient(constants.NSLCD_ACTION_ETHER_BYNAME)
+def getent_aliases(database, keys=None):
+    if not keys:
+        write_aliases(NslcdClient(constants.NSLCD_ACTION_ALIAS_ALL))
+        return
+    for key in keys:
+        con = NslcdClient(constants.NSLCD_ACTION_ALIAS_BYNAME)
         con.write_string(key)
+        write_aliases(con)
+
+
+def write_ethers(con):
     while con.get_response() == constants.NSLCD_RESULT_BEGIN:
         name = con.read_string()
         ether = con.read_ether()
         print '%s %s' % (ether, name)
 
 
-def getent_group(database, key=None):
-    if not key:
-        con = NslcdClient(constants.NSLCD_ACTION_GROUP_ALL)
-    elif database == 'group.bymember':
-        con = NslcdClient(constants.NSLCD_ACTION_GROUP_BYMEMBER)
-        con.write_string(key)
-    elif re.match('^\d+$', key):
-        con = NslcdClient(constants.NSLCD_ACTION_GROUP_BYGID)
-        con.write_int32(int(key))
-    else:
-        con = NslcdClient(constants.NSLCD_ACTION_GROUP_BYNAME)
-        con.write_string(key)
+def getent_ethers(database, keys=None):
+    if not keys:
+        write_ethers(NslcdClient(constants.NSLCD_ACTION_ETHER_ALL))
+        return
+    for key in keys:
+        if re.match('^[0-9a-fA-F]{1,2}(:[0-9a-fA-F]{1,2}){5}$', key):
+            con = NslcdClient(constants.NSLCD_ACTION_ETHER_BYETHER)
+            con.write_ether(key)
+        else:
+            con = NslcdClient(constants.NSLCD_ACTION_ETHER_BYNAME)
+            con.write_string(key)
+        write_ethers(con)
+
+
+def write_group(con):
     while con.get_response() == constants.NSLCD_RESULT_BEGIN:
         print '%s:%s:%d:%s' % (
                 con.read_string(),
@@ -102,6 +102,23 @@ def getent_group(database, key=None):
             )
 
 
+def getent_group(database, keys=None):
+    if not keys:
+        write_group(NslcdClient(constants.NSLCD_ACTION_GROUP_ALL))
+        return
+    for key in keys:
+        if database == 'group.bymember':
+            con = NslcdClient(constants.NSLCD_ACTION_GROUP_BYMEMBER)
+            con.write_string(key)
+        elif re.match('^\d+$', key):
+            con = NslcdClient(constants.NSLCD_ACTION_GROUP_BYGID)
+            con.write_int32(int(key))
+        else:
+            con = NslcdClient(constants.NSLCD_ACTION_GROUP_BYNAME)
+            con.write_string(key)
+        write_group(con)
+
+
 def _get_ipv4(value):
     try:
         return socket.inet_pton(socket.AF_INET, value)
@@ -125,11 +142,20 @@ def _get_af(database):
         return None
 
 
-def getent_hosts(database, key=None):
+def write_hosts(con, db_af):
+    while con.get_response() == constants.NSLCD_RESULT_BEGIN:
+        names = ' '.join([con.read_string()] + con.read_stringlist())
+        for af, address in con.read_addresslist():
+            if db_af in (af, None):
+                print '%-15s %s' % (address, names)
+
+
+def getent_hosts(database, keys=None):
     db_af = _get_af(database)
-    if not key:
-        con = NslcdClient(constants.NSLCD_ACTION_HOST_ALL)
-    else:
+    if not keys:
+        write_hosts(NslcdClient(constants.NSLCD_ACTION_HOST_ALL), db_af)
+        return
+    for key in keys:
         ipv4_addr = _get_ipv4(key)
         ipv6_addr = _get_ipv6(key)
         if ipv4_addr and db_af in (socket.AF_INET, None):
@@ -141,11 +167,7 @@ def getent_hosts(database, key=None):
         else:
             con = NslcdClient(constants.NSLCD_ACTION_HOST_BYNAME)
             con.write_string(key)
-    while con.get_response() == constants.NSLCD_RESULT_BEGIN:
-        names = ' '.join([con.read_string()] + con.read_stringlist())
-        for af, address in con.read_addresslist():
-            if db_af in (af, None):
-                print '%-15s %s' % (address, names)
+        write_hosts(con, db_af)
 
 
 def _read_netgroup(con):
@@ -187,13 +209,8 @@ def _get_getgroups(con, recurse, netgroups=None):
             yield (name, [], tripples)
 
 
-def getent_netgroup(database, key=None):
-    if not key:
-        con = NslcdClient(constants.NSLCD_ACTION_NETGROUP_ALL)
-    else:
-        con = NslcdClient(constants.NSLCD_ACTION_NETGROUP_BYNAME)
-        con.write_string(key)
-    for name, members, tripples in _get_getgroups(con, database == 'netgroup'):
+def write_netgroup(con, recurse):
+    for name, members, tripples in _get_getgroups(con, recurse):
         print '%-15s %s' % (name, ' '.join(
                 members +
                 ['(%s, %s, %s)' % (host, user, domain)
@@ -201,11 +218,32 @@ def getent_netgroup(database, key=None):
             ))
 
 
-def getent_networks(database, key=None):
+def getent_netgroup(database, keys=None):
+    recurse = database == 'netgroup'
+    if not keys:
+        write_netgroup(
+            NslcdClient(constants.NSLCD_ACTION_NETGROUP_ALL), recurse)
+        return
+    for key in keys:
+        con = NslcdClient(constants.NSLCD_ACTION_NETGROUP_BYNAME)
+        con.write_string(key)
+        write_netgroup(con, recurse)
+
+
+def write_networks(con, db_af):
+    while con.get_response() == constants.NSLCD_RESULT_BEGIN:
+        names = ' '.join([con.read_string()] + con.read_stringlist())
+        for af, address in con.read_addresslist():
+            if db_af in (af, None):
+                print '%-15s %s' % (address, names)
+
+
+def getent_networks(database, keys=None):
     db_af = _get_af(database)
-    if not key:
-        con = NslcdClient(constants.NSLCD_ACTION_NETWORK_ALL)
-    else:
+    if not keys:
+        write_networks(NslcdClient(constants.NSLCD_ACTION_NETWORK_ALL), db_af)
+        return
+    for key in keys:
         ipv4_addr = _get_ipv4(key)
         ipv6_addr = _get_ipv6(key)
         if ipv4_addr and db_af in (socket.AF_INET, None):
@@ -217,22 +255,10 @@ def getent_networks(database, key=None):
         else:
             con = NslcdClient(constants.NSLCD_ACTION_NETWORK_BYNAME)
             con.write_string(key)
-    while con.get_response() == constants.NSLCD_RESULT_BEGIN:
-        names = ' '.join([con.read_string()] + con.read_stringlist())
-        for af, address in con.read_addresslist():
-            if db_af in (af, None):
-                print '%-15s %s' % (address, names)
+        write_networks(con, db_af)
 
 
-def getent_passwd(database, key=None):
-    if not key:
-        con = NslcdClient(constants.NSLCD_ACTION_PASSWD_ALL)
-    elif re.match('^\d+$', key):
-        con = NslcdClient(constants.NSLCD_ACTION_PASSWD_BYUID)
-        con.write_int32(int(key))
-    else:
-        con = NslcdClient(constants.NSLCD_ACTION_PASSWD_BYNAME)
-        con.write_string(key)
+def write_passwd(con):
     while con.get_response() == constants.NSLCD_RESULT_BEGIN:
         print '%s:%s:%d:%d:%s:%s:%s' % (
                 con.read_string(),
@@ -245,15 +271,21 @@ def getent_passwd(database, key=None):
             )
 
 
-def getent_protocols(database, key=None):
-    if not key:
-        con = NslcdClient(constants.NSLCD_ACTION_PROTOCOL_ALL)
-    elif re.match('^\d+$', key):
-        con = NslcdClient(constants.NSLCD_ACTION_PROTOCOL_BYNUMBER)
-        con.write_int32(int(key))
-    else:
-        con = NslcdClient(constants.NSLCD_ACTION_PROTOCOL_BYNAME)
-        con.write_string(key)
+def getent_passwd(database, keys=None):
+    if not keys:
+        write_passwd(NslcdClient(constants.NSLCD_ACTION_PASSWD_ALL))
+        return
+    for key in keys:
+        if re.match('^\d+$', key):
+            con = NslcdClient(constants.NSLCD_ACTION_PASSWD_BYUID)
+            con.write_int32(int(key))
+        else:
+            con = NslcdClient(constants.NSLCD_ACTION_PASSWD_BYNAME)
+            con.write_string(key)
+        write_passwd(con)
+
+
+def write_protocols(con):
     while con.get_response() == constants.NSLCD_RESULT_BEGIN:
         name = con.read_string()
         aliases = con.read_stringlist()
@@ -261,15 +293,21 @@ def getent_protocols(database, key=None):
         print '%-21s %d %s' % (name, number, ' '.join(aliases))
 
 
-def getent_rpc(database, key=None):
-    if not key:
-        con = NslcdClient(constants.NSLCD_ACTION_RPC_ALL)
-    elif re.match('^\d+$', key):
-        con = NslcdClient(constants.NSLCD_ACTION_RPC_BYNUMBER)
-        con.write_int32(int(key))
-    else:
-        con = NslcdClient(constants.NSLCD_ACTION_RPC_BYNAME)
-        con.write_string(key)
+def getent_protocols(database, keys=None):
+    if not keys:
+        write_protocols(NslcdClient(constants.NSLCD_ACTION_PROTOCOL_ALL))
+        return
+    for key in keys:
+        if re.match('^\d+$', key):
+            con = NslcdClient(constants.NSLCD_ACTION_PROTOCOL_BYNUMBER)
+            con.write_int32(int(key))
+        else:
+            con = NslcdClient(constants.NSLCD_ACTION_PROTOCOL_BYNAME)
+            con.write_string(key)
+        write_protocols(con)
+
+
+def write_rpc(con):
     while con.get_response() == constants.NSLCD_RESULT_BEGIN:
         name = con.read_string()
         aliases = con.read_stringlist()
@@ -277,10 +315,34 @@ def getent_rpc(database, key=None):
         print '%-15s %d  %s' % (name, number, ' '.join(aliases))
 
 
-def getent_services(database, key=None):
-    if not key:
-        con = NslcdClient(constants.NSLCD_ACTION_SERVICE_ALL)
-    else:
+def getent_rpc(database, keys=None):
+    if not keys:
+        write_rpc(NslcdClient(constants.NSLCD_ACTION_RPC_ALL))
+        return
+    for key in keys:
+        if re.match('^\d+$', key):
+            con = NslcdClient(constants.NSLCD_ACTION_RPC_BYNUMBER)
+            con.write_int32(int(key))
+        else:
+            con = NslcdClient(constants.NSLCD_ACTION_RPC_BYNAME)
+            con.write_string(key)
+        write_rpc(con)
+
+
+def write_services(con):
+    while con.get_response() == constants.NSLCD_RESULT_BEGIN:
+        name = con.read_string()
+        aliases = con.read_stringlist()
+        number = con.read_int32()
+        protocol = con.read_string()
+        print '%-21s %d/%s %s' % (name, number, protocol, ' '.join(aliases))
+
+
+def getent_services(database, keys=None):
+    if not keys:
+        write_services(NslcdClient(constants.NSLCD_ACTION_SERVICE_ALL))
+        return
+    for key in keys:
         value = key
         protocol = ''
         if '/' in value:
@@ -293,60 +355,63 @@ def getent_services(database, key=None):
             con = NslcdClient(constants.NSLCD_ACTION_SERVICE_BYNAME)
             con.write_string(value)
             con.write_string(protocol)
-    while con.get_response() == constants.NSLCD_RESULT_BEGIN:
-        name = con.read_string()
-        aliases = con.read_stringlist()
-        number = con.read_int32()
-        protocol = con.read_string()
-        print '%-21s %d/%s %s' % (name, number, protocol, ' '.join(aliases))
+        write_services(con)
 
 
-def getent_shadow(database, key=None):
-    if not key:
-        con = NslcdClient(constants.NSLCD_ACTION_SHADOW_ALL)
-    else:
-        con = NslcdClient(constants.NSLCD_ACTION_SHADOW_BYNAME)
-        con.write_string(key)
-    value2str = lambda x: str(x) if x != -1 else ''
+def _shadow_value2str(number):
+    return str(number) if number != -1 else ''
+
+
+def write_shadow(con):
     while con.get_response() == constants.NSLCD_RESULT_BEGIN:
         print '%s:%s:%s:%s:%s:%s:%s:%s:%s' % (
                 con.read_string(),
                 con.read_string(),
-                value2str(con.read_int32()),
-                value2str(con.read_int32()),
-                value2str(con.read_int32()),
-                value2str(con.read_int32()),
-                value2str(con.read_int32()),
-                value2str(con.read_int32()),
-                value2str(con.read_int32()),
+                _shadow_value2str(con.read_int32()),
+                _shadow_value2str(con.read_int32()),
+                _shadow_value2str(con.read_int32()),
+                _shadow_value2str(con.read_int32()),
+                _shadow_value2str(con.read_int32()),
+                _shadow_value2str(con.read_int32()),
+                _shadow_value2str(con.read_int32()),
             )
 
 
+def getent_shadow(database, keys=None):
+    if not keys:
+        write_shadow(NslcdClient(constants.NSLCD_ACTION_SHADOW_ALL))
+        return
+    for key in keys:
+        con = NslcdClient(constants.NSLCD_ACTION_SHADOW_BYNAME)
+        con.write_string(key)
+        write_shadow(con)
+
+
 if __name__ == '__main__':
     args = parser.parse_args()
     try:
         if args.database == 'aliases':
-            getent_aliases(args.database, args.key)
+            getent_aliases(args.database, args.keys)
         elif args.database == 'ethers':
-            getent_ethers(args.database, args.key)
+            getent_ethers(args.database, args.keys)
         elif args.database in ('group', 'group.bymember'):
-            getent_group(args.database, args.key)
+            getent_group(args.database, args.keys)
         elif args.database in ('hosts', 'hostsv4', 'hostsv6'):
-            getent_hosts(args.database, args.key)
+            getent_hosts(args.database, args.keys)
         elif args.database in ('netgroup', 'netgroup.norec'):
-            getent_netgroup(args.database, args.key)
+            getent_netgroup(args.database, args.keys)
         elif args.database in ('networks', 'networksv4', 'networksv6'):
-            getent_networks(args.database, args.key)
+            getent_networks(args.database, args.keys)
         elif args.database == 'passwd':
-            getent_passwd(args.database, args.key)
+            getent_passwd(args.database, args.keys)
         elif args.database == 'protocols':
-            getent_protocols(args.database, args.key)
+            getent_protocols(args.database, args.keys)
         elif args.database == 'rpc':
-            getent_rpc(args.database, args.key)
+            getent_rpc(args.database, args.keys)
         elif args.database == 'services':
-            getent_services(args.database, args.key)
+            getent_services(args.database, args.keys)
         elif args.database == 'shadow':
-            getent_shadow(args.database, args.key)
+            getent_shadow(args.database, args.keys)
         else:
             parser.error('Unknown database: %s' % args.database)
     except struct.error:

-----------------------------------------------------------------------

Summary of changes:
 man/getent.ldap.1.xml                       |   6 +-
 tests/Makefile.am                           |   9 +-
 tests/{test_nsscmds.sh => test_ldapcmds.sh} | 357 +++++++++++++---------------
 tests/test_nsscmds.sh                       |  10 +-
 tests/testenv.sh                            |  18 +-
 utils/chsh.py                               |   2 +-
 utils/cmdline.py                            |   4 +-
 utils/getent.py                             | 327 +++++++++++++++----------
 utils/nslcd.py                              |  37 ++-
 utils/shells.py                             |   8 +-
 utils/users.py                              |   4 +-
 11 files changed, 426 insertions(+), 356 deletions(-)
 copy tests/{test_nsscmds.sh => test_ldapcmds.sh} (79%)


hooks/post-receive
-- 
nss-pam-ldapd
-- 
To unsubscribe send an email to
nss-pam-ldapd-commits-unsubscribe@lists.arthurdejong.org or see
https://lists.arthurdejong.org/nss-pam-ldapd-commits/