summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--testsuite/config/default-nt-names.exp17
-rw-r--r--testsuite/config/env.exp26
-rw-r--r--testsuite/config/unix.exp27
-rw-r--r--testsuite/nsswitch/bigfd.c38
-rw-r--r--testsuite/nsswitch/bigfd.exp27
-rw-r--r--testsuite/nsswitch/finger.exp27
-rw-r--r--testsuite/nsswitch/getent.exp37
-rwxr-xr-xtestsuite/nsswitch/getent_r.sh35
-rw-r--r--testsuite/nsswitch/getgrent_r.c84
-rw-r--r--testsuite/nsswitch/getgrent_r.exp42
-rw-r--r--testsuite/nsswitch/getgrgid.c57
-rw-r--r--testsuite/nsswitch/getgrgid.exp54
-rw-r--r--testsuite/nsswitch/getgrnam.c51
-rw-r--r--testsuite/nsswitch/getgrnam.exp29
-rw-r--r--testsuite/nsswitch/getpwent_r.c85
-rw-r--r--testsuite/nsswitch/getpwent_r.exp42
-rw-r--r--testsuite/nsswitch/getpwnam.c37
-rw-r--r--testsuite/nsswitch/getpwnam.exp29
-rw-r--r--testsuite/nsswitch/getpwuid.c43
-rw-r--r--testsuite/nsswitch/getpwuid.exp54
-rw-r--r--testsuite/nsswitch/nss_winbind_syms.c62
-rw-r--r--testsuite/nsswitch/nss_winbind_syms.exp51
-rw-r--r--testsuite/nsswitch/pam_winbind_syms.c55
-rw-r--r--testsuite/nsswitch/pam_winbind_syms.exp44
24 files changed, 1053 insertions, 0 deletions
diff --git a/testsuite/config/default-nt-names.exp b/testsuite/config/default-nt-names.exp
new file mode 100644
index 0000000000..4a868e71bc
--- /dev/null
+++ b/testsuite/config/default-nt-names.exp
@@ -0,0 +1,17 @@
+#
+# A list of default domain/local users/groups
+#
+
+# Domain users and groups
+
+set domain_users [list "$domain/Administrator" "$domain/Guest"]
+
+set domain_groups [list "$domain/Domain Admins" "$domain/Domain Guests" \
+ "$domain/Domain Users"]
+
+# Local groups
+
+set local_groups [list "BUILTIN/Replicator" "BUILTIN/Server Operators" \
+ "BUILTIN/Account Operators" "BUILTIN/Backup Operators" \
+ "BUILTIN/Print Operators" "BUILTIN/Guests" "BUILTIN/Users" \
+ "BUILTIN/Administrators"]
diff --git a/testsuite/config/env.exp b/testsuite/config/env.exp
new file mode 100644
index 0000000000..503d058c3f
--- /dev/null
+++ b/testsuite/config/env.exp
@@ -0,0 +1,26 @@
+#
+# Load environment variables
+#
+
+# Domain set through environment variable
+
+catch {set domain "$env(TEST_WORKGROUP)"} tmp
+
+if {[regexp "^can't read" $tmp]} {
+ error "Environment variable \$TEST_WORKGROUP not set"
+}
+
+# NT user and server
+
+catch {set ntserver "$env(TEST_NTSERVER)"} tmp
+
+if {[regexp "^can't read" $tmp]} {
+ error "Environment variable \$TEST_NTSERVER not set"
+}
+
+catch {set ntuser "$env(TEST_NTUSER)"} tmp
+
+if {[regexp "^can't read" $tmp]} {
+ error "Environment variable \$TEST_NTUSER not set"
+}
+
diff --git a/testsuite/config/unix.exp b/testsuite/config/unix.exp
new file mode 100644
index 0000000000..c8b3b28779
--- /dev/null
+++ b/testsuite/config/unix.exp
@@ -0,0 +1,27 @@
+# Copyright (C) 1988, 1990, 1991, 1992, 1994, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Rob Savoye. (rob@cygnus.com)
+
+# Set a default timeout to be used for the tests under UNIX, rather than
+# accepting whatever default dejagnu gives us (apparently 10 seconds).
+# When running the tests over NFS, under somewhat heavy load, 10 seconds
+# does not seem to be enough. Try starting with 60.
+set timeout 60
+verbose "Timeout is now $timeout seconds" 2
diff --git a/testsuite/nsswitch/bigfd.c b/testsuite/nsswitch/bigfd.c
new file mode 100644
index 0000000000..99e402e0f3
--- /dev/null
+++ b/testsuite/nsswitch/bigfd.c
@@ -0,0 +1,38 @@
+/*
+ * Test maximum number of file descriptors winbind daemon can handle
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <pwd.h>
+#include <sys/types.h>
+
+int main(int argc, char **argv)
+{
+ struct passwd *pw;
+ int i;
+
+ while(1) {
+
+ /* Start getpwent until we get an NT user. This way we know we
+ have at least opened a connection to the winbind daemon */
+
+ setpwent();
+
+ while((pw = getpwent()) != NULL) {
+ if (strchr(pw->pw_name, '/') != NULL) {
+ break;
+ }
+ }
+
+ if (pw != NULL) {
+ i++;
+ printf("got pwent handle %d\n", i);
+ } else {
+ printf("winbind daemon not running?\n");
+ exit(1);
+ }
+
+ sleep(1);
+ }
+}
diff --git a/testsuite/nsswitch/bigfd.exp b/testsuite/nsswitch/bigfd.exp
new file mode 100644
index 0000000000..bda1a6db6c
--- /dev/null
+++ b/testsuite/nsswitch/bigfd.exp
@@ -0,0 +1,27 @@
+#
+# @(#) Test maximum number of clients (file descriptors) for winbindd
+#
+
+load_lib util-defs.exp
+load_lib "$srcdir/config/env.exp"
+
+pass "bigfd"
+return
+
+# Compile bigfd.c
+
+set output [target_compile "$srcdir/$subdir/bigfd.c" \
+ "$srcdir/$subdir/bigfd" executable {additional_flags="-g"}]
+
+if {$output != ""} {
+ perror "compile bigfd"
+ puts $output
+ return
+}
+
+# Run bigfd
+
+set output [util_start "$srcdir/$subdir/bigfd" "" ""]
+puts $output
+
+pass "bigfd"
diff --git a/testsuite/nsswitch/finger.exp b/testsuite/nsswitch/finger.exp
new file mode 100644
index 0000000000..8a57f1c809
--- /dev/null
+++ b/testsuite/nsswitch/finger.exp
@@ -0,0 +1,27 @@
+#
+# @(#) Test default domain users resolve using the finger command
+#
+
+load_lib util-defs.exp
+load_lib "$srcdir/config/env.exp"
+load_lib "$srcdir/config/default-nt-names.exp"
+
+# Look up domain users using finger. This should test getpwnam()
+
+foreach { user } $domain_users {
+ if {[util_test "finger" "-m $user" "" "no such user"] < 1} {
+ fail "finger -m $user"
+ } else {
+ pass "finger -m $user"
+ }
+}
+
+# Run finger without the -m to also test set/get/endpwent()
+
+foreach { user } $domain_users {
+ if {[util_test "finger" "$user" "" "no such user"] < 1} {
+ fail "finger $user"
+ } else {
+ pass "finger $user"
+ }
+}
diff --git a/testsuite/nsswitch/getent.exp b/testsuite/nsswitch/getent.exp
new file mode 100644
index 0000000000..fcd98670b8
--- /dev/null
+++ b/testsuite/nsswitch/getent.exp
@@ -0,0 +1,37 @@
+#
+# @(#) Test the getent command returns domain/local users and groups
+#
+
+load_lib util-defs.exp
+load_lib "$srcdir/config/env.exp"
+load_lib "$srcdir/config/default-nt-names.exp"
+
+#
+# Test getent passwd
+#
+
+set output [util_start "getent" "passwd" ""]
+
+# Test output for domain users
+
+foreach {user} $domain_users {
+ if {![regexp "$user" $output]} {
+ fail "getent passwd $user"
+ } else {
+ pass "getent passwd $user"
+ }
+}
+
+#
+# Test getent group
+#
+
+set output [util_start "getent" "group" ""]
+
+foreach {group} $domain_groups {
+ if {![regexp "$group" $output]} {
+ fail "getent group $group"
+ } else {
+ pass "getent group $group"
+ }
+}
diff --git a/testsuite/nsswitch/getent_r.sh b/testsuite/nsswitch/getent_r.sh
new file mode 100755
index 0000000000..75dc603f82
--- /dev/null
+++ b/testsuite/nsswitch/getent_r.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+#
+# Verify test output. Basically we check to see if all the files generated
+# in /tmp by the get{pw,gr}ent_r.c and program are identical. If there is
+# some problem with the re-entrancy of the code then the information in the
+# two files will be different.
+#
+
+TYPE=$1
+ID=$2
+FILES="/tmp/${TYPE}_r-${ID}.out-*"
+
+# Sort files
+
+for file in $FILES; do
+ cat $file | sort > $file.sorted
+done
+
+# Diff files
+
+SORTED="/tmp/${TYPE}_r-${ID}.out-*.sorted"
+failed=0
+
+for file1 in $SORTED; do
+ for file2 in $SORTED; do
+ if [ $file1 != $file2 ]; then
+ diff $file1 $file2
+ fi
+ done
+done
+
+# Clean up
+
+rm -f $SORTED
+
diff --git a/testsuite/nsswitch/getgrent_r.c b/testsuite/nsswitch/getgrent_r.c
new file mode 100644
index 0000000000..3eac8aa218
--- /dev/null
+++ b/testsuite/nsswitch/getgrent_r.c
@@ -0,0 +1,84 @@
+/*
+ * Use set/get/endgrent calls from two processes to iterate over the
+ * password database. This checks the multithreaded stuff works.
+ */
+
+#include <stdio.h>
+#include <grp.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <wait.h>
+
+void dump_grent(char *id)
+{
+ struct group *gr;
+ char fname[255];
+ FILE *fptr;
+
+ /* Open results file */
+
+ sprintf(fname, "/tmp/getgrent_r-%s.out-%d", id, getpid());
+
+ if ((fptr = fopen(fname, "w")) < 0) {
+ fprintf(stderr, "ERROR: could not open file %s: %s\n", fname,
+ sys_errlist[errno]);
+ return;
+ }
+
+ /* Dump group database */
+
+ setgrent();
+
+ while((gr = getgrent()) != NULL) {
+ fprintf(fptr,"%s:%s:%d:%d\n", gr->gr_name, gr->gr_passwd,
+ gr->gr_gid);
+ }
+
+ endgrent();
+
+ /* Close results file */
+
+ fclose(fptr);
+}
+
+int main(int argc, char **argv)
+{
+ pid_t pid;
+
+ /* Check args */
+
+ if (argc != 2) {
+ printf("ERROR: must specify output file identifier\n");
+ return 1;
+ }
+
+ /* Fork child process */
+
+ if ((pid = fork()) == -1) {
+ printf("ERROR: unable to fork\n");
+ return 1;
+ }
+
+ /* Handle test case */
+
+ if (pid > 0) {
+ int status;
+
+ /* Parent */
+
+ dump_grent(argv[1]);
+ wait(&status);
+
+ } else {
+
+ /* Child */
+
+ dump_grent(argv[1]);
+ return 0;
+ }
+
+ printf("PASS: run getgrent_r.c\n");
+ return 0;
+}
diff --git a/testsuite/nsswitch/getgrent_r.exp b/testsuite/nsswitch/getgrent_r.exp
new file mode 100644
index 0000000000..d2dc47e252
--- /dev/null
+++ b/testsuite/nsswitch/getgrent_r.exp
@@ -0,0 +1,42 @@
+#
+# @(#) Test multiple threads can enumerate groups correctly
+#
+
+load_lib util-defs.exp
+load_lib "$srcdir/config/env.exp"
+load_lib "$srcdir/config/default-nt-names.exp"
+
+# Compile getgrent_r.c
+
+set output [target_compile "$srcdir/$subdir/getgrent_r.c" \
+ "$srcdir/$subdir/getgrent_r" executable {additional_flags="-g"}]
+
+if {$output != ""} {
+ perror "compile getgrent_r"
+ puts $output
+ return
+}
+
+# Clean up output from previous tests
+
+set pid [pid]
+file delete [glob -nocomplain "/tmp/getgrent_r-$pid.out-*"]
+
+# Run test proggy
+
+set output [util_start "$srcdir/$subdir/getgrent_r" "$pid" ""]
+if {![regexp "^PASS:" $output]} {
+ perror "run getgrent_r"
+ puts $output
+ return -1
+}
+
+# Sort and compare output
+
+set output [util_start "$srcdir/$subdir/getent_r.sh" "getgrent $pid" ""]
+if {$output == ""} {
+ pass "getgrent_r"
+} else {
+ fail "getgrent_r"
+ puts $output
+}
diff --git a/testsuite/nsswitch/getgrgid.c b/testsuite/nsswitch/getgrgid.c
new file mode 100644
index 0000000000..947dd0ac4c
--- /dev/null
+++ b/testsuite/nsswitch/getgrgid.c
@@ -0,0 +1,57 @@
+/*
+ * Lookup a group by gid.
+ */
+
+#include <stdio.h>
+#include <grp.h>
+#include <sys/types.h>
+
+int main(int argc, char **argv)
+{
+ struct group *gr;
+ gid_t gid;
+
+ /* Check args */
+
+ if (argc != 2) {
+ printf("ERROR: no arg specified\n");
+ exit(1);
+ }
+
+ if ((gid = atoi(argv[1])) == 0) {
+ printf("ERROR: invalid gid specified\n");
+ exit(1);
+ }
+
+ /* Do getgrgid() */
+
+ if ((gr = getgrgid(gid)) == NULL) {
+ printf("FAIL: gid %d does not exist\n", gid);
+ exit(1);
+ }
+
+ /* Print group info */
+
+ printf("PASS: gid %d exists\n", gid);
+ printf("gr_name = %s\n", gr->gr_name);
+ printf("gr_passwd = %s\n", gr->gr_passwd);
+ printf("gr_gid = %d\n", gr->gr_gid);
+
+ /* Group membership */
+
+ if (gr->gr_mem != NULL) {
+ int i = 0;
+
+ printf("gr_mem = ");
+ while(gr->gr_mem[i] != NULL) {
+ printf("%s", gr->gr_mem[i]);
+ i++;
+ if (gr->gr_mem != NULL) {
+ printf(",");
+ }
+ }
+ printf("\n");
+ }
+
+ exit(0);
+}
diff --git a/testsuite/nsswitch/getgrgid.exp b/testsuite/nsswitch/getgrgid.exp
new file mode 100644
index 0000000000..a6508b3cd5
--- /dev/null
+++ b/testsuite/nsswitch/getgrgid.exp
@@ -0,0 +1,54 @@
+#
+# @(#) Test reverse lookup of group ids from getent match getgrgid() output
+#
+
+load_lib util-defs.exp
+load_lib "$srcdir/config/env.exp"
+load_lib "$srcdir/config/default-nt-names.exp"
+
+# Compile getpwuid.c
+
+set output [target_compile "$srcdir/$subdir/getgrgid.c" \
+ "$srcdir/$subdir/getgrgid" executable {additional_flags="-g"}]
+
+if {$output != ""} {
+ perror "compile getgrgid"
+ puts $output
+ return
+}
+
+# Get list of uids using getent
+
+set output [util_start "getent" "group" ""]
+set got_entries 0
+
+foreach {line} [split $output "\n"] {
+
+ # Process user
+
+ set grp_entry [split $line ":"]
+ set group [lindex $grp_entry 0]
+
+ if {[regexp "^($domain)/" $group]} {
+
+ set got_entries 1
+
+ # Only lookup winbindd users
+
+ set gid [lindex $grp_entry 2]
+
+ # Test lookup of gid succeeds
+
+ set output [util_start "$srcdir/$subdir/getgrgid" "$gid" ""]
+ if {[regexp "PASS:" $output]} {
+ pass "getgrgid $gid ($group)"
+ } else {
+ fail "getgrgid $gid ($group)"
+ }
+ }
+
+}
+
+if {!$got_entries} {
+ perror "No domain groups returned from getent"
+}
diff --git a/testsuite/nsswitch/getgrnam.c b/testsuite/nsswitch/getgrnam.c
new file mode 100644
index 0000000000..8ab4046bd9
--- /dev/null
+++ b/testsuite/nsswitch/getgrnam.c
@@ -0,0 +1,51 @@
+/*
+ * Lookup a group by name
+ */
+
+#include <stdio.h>
+#include <grp.h>
+#include <sys/types.h>
+
+int main(int argc, char **argv)
+{
+ struct group *gr;
+
+ /* Check args */
+
+ if (argc != 2) {
+ printf("ERROR: no arg specified\n");
+ exit(1);
+ }
+
+ /* Do getgrnam() */
+
+ if ((gr = getgrnam(argv[1])) == NULL) {
+ printf("FAIL: group %s does not exist\n", argv[1]);
+ exit(1);
+ }
+
+ /* Print group info */
+
+ printf("PASS: group %s exists\n", argv[1]);
+ printf("gr_name = %s\n", gr->gr_name);
+ printf("gr_passwd = %s\n", gr->gr_passwd);
+ printf("gr_gid = %d\n", gr->gr_gid);
+
+ /* Group membership */
+
+ if (gr->gr_mem != NULL) {
+ int i = 0;
+
+ printf("gr_mem = ");
+ while(gr->gr_mem[i] != NULL) {
+ printf("%s", gr->gr_mem[i]);
+ i++;
+ if (gr->gr_mem != NULL) {
+ printf(",");
+ }
+ }
+ printf("\n");
+ }
+
+ exit(0);
+}
diff --git a/testsuite/nsswitch/getgrnam.exp b/testsuite/nsswitch/getgrnam.exp
new file mode 100644
index 0000000000..2ba6ba0281
--- /dev/null
+++ b/testsuite/nsswitch/getgrnam.exp
@@ -0,0 +1,29 @@
+#
+# @(#) Test domain/local groups resolve using getgrnam()
+#
+
+load_lib util-defs.exp
+load_lib "$srcdir/config/env.exp"
+load_lib "$srcdir/config/default-nt-names.exp"
+
+# Compile getgrnam.c
+
+set output [target_compile "$srcdir/$subdir/getgrnam.c" \
+ "$srcdir/$subdir/getgrnam" executable {additional_flags="-g"}]
+
+if {$output != ""} {
+ perror "compile getgrnam"
+ puts $output
+ return
+}
+
+# Test domain groups
+
+foreach {group} $domain_groups {
+ set output [util_start "$srcdir/$subdir/getgrnam" "\"$group\"" ""]
+ if {[regexp "PASS:" $output]} {
+ pass "getgrnam $group"
+ } else {
+ fail "getgrnam $group"
+ }
+}
diff --git a/testsuite/nsswitch/getpwent_r.c b/testsuite/nsswitch/getpwent_r.c
new file mode 100644
index 0000000000..2ba7ea96f1
--- /dev/null
+++ b/testsuite/nsswitch/getpwent_r.c
@@ -0,0 +1,85 @@
+/*
+ * Use set/get/endpwent calls from two processes to iterate over the
+ * password database. This checks the multithreaded stuff works.
+ */
+
+#include <stdio.h>
+#include <pwd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <wait.h>
+
+void dump_pwent(char *id)
+{
+ struct passwd *pw;
+ char fname[255];
+ FILE *fptr;
+
+ /* Open results file */
+
+ sprintf(fname, "/tmp/getpwent_r-%s.out-%d", id, getpid());
+
+ if ((fptr = fopen(fname, "w")) < 0) {
+ fprintf(stderr, "ERROR: could not open file %s: %s\n", fname,
+ sys_errlist[errno]);
+ return;
+ }
+
+ /* Dump passwd database */
+
+ setpwent();
+
+ while((pw = getpwent()) != NULL) {
+ fprintf(fptr,"%s:%s:%s:%d:%d\n", pw->pw_name, pw->pw_passwd,
+ pw->pw_gecos, pw->pw_uid, pw->pw_gid);
+ }
+
+ endpwent();
+
+ /* Close results file */
+
+ fclose(fptr);
+}
+
+#define NUM_FORKS 2
+
+int main(int argc, char **argv)
+{
+ pid_t pids[NUM_FORKS];
+ int i, status;
+
+ /* Check args */
+
+ if (argc != 2) {
+ printf("ERROR: must specify output file identifier\n");
+ return 1;
+ }
+
+ for(i = 0; i < NUM_FORKS; i++) {
+
+ /* Fork off lots */
+
+ if ((pids[i] = fork()) == -1) {
+ perror("fork");
+ return 1;
+ }
+
+ /* Child does tests */
+
+ if (pids[i] == 0) {
+ dump_pwent(argv[1]);
+ return 0;
+ }
+ }
+
+ /* Wait for everyone to finish */
+
+ for (i = 0; i < NUM_FORKS; i++) {
+ waitpid(pids[i], &status, 0);
+ }
+
+ printf("PASS: getpwent_r.c\n");
+ return 0;
+}
diff --git a/testsuite/nsswitch/getpwent_r.exp b/testsuite/nsswitch/getpwent_r.exp
new file mode 100644
index 0000000000..9e6f915113
--- /dev/null
+++ b/testsuite/nsswitch/getpwent_r.exp
@@ -0,0 +1,42 @@
+#
+# @(#) Test multiple threads can enumerate users correctly
+#
+
+load_lib util-defs.exp
+load_lib "$srcdir/config/env.exp"
+load_lib "$srcdir/config/default-nt-names.exp"
+
+# Compile getpwent_r.c
+
+set output [target_compile "$srcdir/$subdir/getpwent_r.c" \
+ "$srcdir/$subdir/getpwent_r" executable {additional_flags="-g"}]
+
+if {$output != ""} {
+ perror "compile getpwent_r"
+ puts $output
+ fail ""
+}
+
+# Clean up output from previous tests
+
+set pid [pid]
+file delete [glob -nocomplain "/tmp/getpwent_r-$pid.out-*"]
+
+# Run test proggy
+
+set output [util_start "$srcdir/$subdir/getpwent_r" "$pid" ""]
+if {![regexp "^PASS:" $output]} {
+ perror "run getpwent_r"
+ puts $output
+ return -1
+}
+
+# Sort and compare output
+
+set output [util_start "$srcdir/$subdir/getent_r.sh" "getpwent $pid" ""]
+if {$output == ""} {
+ pass "getpwent_r"
+} else {
+ fail "getpwent_r"
+ puts $output
+}
diff --git a/testsuite/nsswitch/getpwnam.c b/testsuite/nsswitch/getpwnam.c
new file mode 100644
index 0000000000..e7dd2910b6
--- /dev/null
+++ b/testsuite/nsswitch/getpwnam.c
@@ -0,0 +1,37 @@
+/*
+ * Lookup a user by name
+ */
+
+#include <stdio.h>
+#include <pwd.h>
+#include <sys/types.h>
+
+int main(int argc, char **argv)
+{
+ struct passwd *pw;
+
+ /* Check args */
+
+ if (argc != 2) {
+ printf("ERROR: no arg specified\n");
+ exit(1);
+ }
+
+ /* Do getpwnam() */
+
+ if ((pw = getpwnam(argv[1])) == NULL) {
+ printf("FAIL: user %s does not exist\n", argv[1]);
+ exit(1);
+ }
+
+ printf("PASS: user %s exists\n", argv[1]);
+ printf("pw_name = %s\n", pw->pw_name);
+ printf("pw_passwd = %s\n", pw->pw_passwd);
+ printf("pw_uid = %d\n", pw->pw_uid);
+ printf("pw_gid = %d\n", pw->pw_gid);
+ printf("pw_gecos = %s\n", pw->pw_gecos);
+ printf("pw_dir = %s\n", pw->pw_dir);
+ printf("pw_shell = %s\n", pw->pw_shell);
+
+ exit(0);
+}
diff --git a/testsuite/nsswitch/getpwnam.exp b/testsuite/nsswitch/getpwnam.exp
new file mode 100644
index 0000000000..49f61f1a5c
--- /dev/null
+++ b/testsuite/nsswitch/getpwnam.exp
@@ -0,0 +1,29 @@
+#
+# @(#) Test default domain users resolve using getpwnam()
+#
+
+load_lib util-defs.exp
+load_lib "$srcdir/config/env.exp"
+load_lib "$srcdir/config/default-nt-names.exp"
+
+# Compile getpwnam.c
+
+set output [target_compile "$srcdir/$subdir/getpwnam.c" \
+ "$srcdir/$subdir/getpwnam" executable {additional_flags="-g"}]
+
+if {$output != ""} {
+ perror "compile getpwnam"
+ puts $output
+ return
+}
+
+# Test domain users
+
+foreach {user} $domain_users {
+ set output [util_start "$srcdir/$subdir/getpwnam" "\"$user\"" ""]
+ if {[regexp "PASS:" $output]} {
+ pass "getpwnam $user"
+ } else {
+ fail "getpwnam $user"
+ }
+}
diff --git a/testsuite/nsswitch/getpwuid.c b/testsuite/nsswitch/getpwuid.c
new file mode 100644
index 0000000000..3f364df29d
--- /dev/null
+++ b/testsuite/nsswitch/getpwuid.c
@@ -0,0 +1,43 @@
+/*
+ * Lookup a user by uid.
+ */
+
+#include <stdio.h>
+#include <pwd.h>
+#include <sys/types.h>
+
+int main(int argc, char **argv)
+{
+ struct passwd *pw;
+ uid_t uid;
+
+ /* Check args */
+
+ if (argc != 2) {
+ printf("ERROR: no arg specified\n");
+ exit(1);
+ }
+
+ if ((uid = atoi(argv[1])) == 0) {
+ printf("ERROR: invalid uid specified\n");
+ exit(1);
+ }
+
+ /* Do getpwuid() */
+
+ if ((pw = getpwuid(uid)) == NULL) {
+ printf("FAIL: uid %d does not exist\n", uid);
+ exit(1);
+ }
+
+ printf("PASS: uid %d exists\n", uid);
+ printf("pw_name = %s\n", pw->pw_name);
+ printf("pw_passwd = %s\n", pw->pw_passwd);
+ printf("pw_uid = %d\n", pw->pw_uid);
+ printf("pw_gid = %d\n", pw->pw_gid);
+ printf("pw_gecos = %s\n", pw->pw_gecos);
+ printf("pw_dir = %s\n", pw->pw_dir);
+ printf("pw_shell = %s\n", pw->pw_shell);
+
+ exit(0);
+}
diff --git a/testsuite/nsswitch/getpwuid.exp b/testsuite/nsswitch/getpwuid.exp
new file mode 100644
index 0000000000..48e7dcb2be
--- /dev/null
+++ b/testsuite/nsswitch/getpwuid.exp
@@ -0,0 +1,54 @@
+#
+# @(#) Test reverse lookup of user ids from getent match getpwuid() output
+#
+
+load_lib util-defs.exp
+load_lib "$srcdir/config/env.exp"
+load_lib "$srcdir/config/default-nt-names.exp"
+
+# Compile getpwuid.c
+
+set output [target_compile "$srcdir/$subdir/getpwuid.c" \
+ "$srcdir/$subdir/getpwuid" executable {additional_flags="-g"}]
+
+if {$output != ""} {
+ perror "compile getpwuid"
+ puts $output
+ return
+}
+
+# Get list of uids using getent
+
+set output [util_start "getent" "passwd" ""]
+set got_entries 0
+
+foreach {line} [split $output "\n"] {
+
+ # Process user
+
+ set pwd_entry [split $line ":"]
+ set user [lindex $pwd_entry 0]
+
+ if {[regexp "^($domain)/" $user]} {
+
+ set got_entries 1
+
+ # Only lookup winbindd users
+
+ set uid [lindex $pwd_entry 2]
+ set gid [lindex $pwd_entry 3]
+
+ # Test lookup of uid succeeds
+
+ set output [util_start "$srcdir/$subdir/getpwuid" "$uid" ""]
+ if {[regexp "PASS:" $output]} {
+ pass "getpwuid $uid ($user)"
+ } else {
+ fail "getpwuid $uid ($user)"
+ }
+ }
+}
+
+if {!$got_entries} {
+ perror "No domain users returned from getent"
+}
diff --git a/testsuite/nsswitch/nss_winbind_syms.c b/testsuite/nsswitch/nss_winbind_syms.c
new file mode 100644
index 0000000000..3df471ed99
--- /dev/null
+++ b/testsuite/nsswitch/nss_winbind_syms.c
@@ -0,0 +1,62 @@
+/*
+ * Test required functions are exported from the libnss_winbind.so library
+ */
+
+#include <stdio.h>
+#include <dlfcn.h>
+
+/* Symbol list to check */
+
+static char *symlist[] = {
+ "_nss_winbind_getgrent_r",
+ "_nss_winbind_endgrent",
+ "_nss_winbind_endpwent",
+ "_nss_winbind_getgrgid_r",
+ "_nss_winbind_getgrnam_r",
+ "_nss_winbind_getpwent_r",
+ "_nss_winbind_getpwnam_r",
+ "_nss_winbind_getpwuid_r",
+ "_nss_winbind_setgrent",
+ "_nss_winbind_setpwent",
+ NULL
+};
+
+/* Main function */
+
+int main(int argc, char **argv)
+{
+ void *handle, *sym;
+ int i, y;
+
+ /* Open library */
+
+ if (argc != 2) {
+ printf("FAIL: usage '%s sharedlibname'\n", argv[0]);
+ return 1;
+ }
+
+ handle = dlopen(argv[1], RTLD_NOW);
+
+ if (handle == NULL) {
+ printf("FAIL: could not dlopen library: %s\n", dlerror());
+ return 1;
+ }
+
+ /* Read symbols */
+
+ for (i = 0; symlist[i] != NULL; i++) {
+ sym = dlsym(handle, symlist[i]);
+ if (sym == NULL) {
+ printf("FAIL: could not resolve symbol '%s': %s\n",
+ symlist[i], dlerror());
+ return 1;
+ } else {
+ printf("loaded symbol '%s' ok\n", symlist[i]);
+ }
+ }
+
+ /* Clean up */
+
+ dlclose(handle);
+ return 0;
+}
diff --git a/testsuite/nsswitch/nss_winbind_syms.exp b/testsuite/nsswitch/nss_winbind_syms.exp
new file mode 100644
index 0000000000..a0cf4cf7fc
--- /dev/null
+++ b/testsuite/nsswitch/nss_winbind_syms.exp
@@ -0,0 +1,51 @@
+#
+# @(#) Test nss functions are exported from the libnss_winbind.so library
+# @(#) Test there are no external dependencies in the libnss_winbind.so library
+#
+# We expect the following symbols to be exported:
+#
+# _nss_winbind_getgrent_r
+# _nss_winbind_endgrent
+# _nss_winbind_endpwent
+# _nss_winbind_getgrgid_r
+# _nss_winbind_getgrnam_r
+# _nss_winbind_getpwent_r
+# _nss_winbind_getpwnam_r
+# _nss_winbind_getpwuid_r
+# _nss_winbind_setgrent
+# _nss_winbind_setpwent
+#
+# This test also has the nice side-effect of showing any unresolved symbols
+# in the library.
+#
+
+load_lib util-defs.exp
+
+# Compile nss_winbind_syms.c
+
+set output [target_compile "$srcdir/$subdir/nss_winbind_syms.c" \
+ "$srcdir/$subdir/nss_winbind_syms" executable \
+ {"libs=-ldl" "additional_flags=-g"}]
+
+if {$output != ""} {
+ perror "compile nss_winbind_syms.c"
+ puts $output
+ return
+}
+
+# Run load-dl.c
+
+set output [util_start "$srcdir/$subdir/nss_winbind_syms" \
+ "nsswitch/libnss_winbind.so"]
+
+if {[regexp "FAIL:" $output]} {
+ fail "run nss_winbind_syms"
+ puts $output
+ return
+}
+
+pass "nss_winbind_syms"
+
+# Clean up
+
+file delete "$srcdir/$subdir/nss_winbind_syms"
diff --git a/testsuite/nsswitch/pam_winbind_syms.c b/testsuite/nsswitch/pam_winbind_syms.c
new file mode 100644
index 0000000000..1264bdb23e
--- /dev/null
+++ b/testsuite/nsswitch/pam_winbind_syms.c
@@ -0,0 +1,55 @@
+/*
+ * Test required functions are exported from the pam_winbind.so library
+ */
+
+#include <stdio.h>
+#include <dlfcn.h>
+
+/* Symbol list to check */
+
+static char *symlist[] = {
+ "pam_sm_acct_mgmt",
+ "pam_sm_authenticate",
+ "pam_sm_setcred",
+ NULL
+};
+
+/* Main function */
+
+int main(int argc, char **argv)
+{
+ void *handle, *sym;
+ int i, y;
+
+ /* Open library */
+
+ if (argc != 2) {
+ printf("FAIL: usage '%s sharedlibname'\n", argv[0]);
+ return 1;
+ }
+
+ handle = dlopen(argv[1], RTLD_NOW);
+
+ if (handle == NULL) {
+ printf("FAIL: could not dlopen library: %s\n", dlerror());
+ return 1;
+ }
+
+ /* Read symbols */
+
+ for (i = 0; symlist[i] != NULL; i++) {
+ sym = dlsym(handle, symlist[i]);
+ if (sym == NULL) {
+ printf("FAIL: could not resolve symbol '%s': %s\n",
+ symlist[i], dlerror());
+ return 1;
+ } else {
+ printf("loaded symbol '%s' ok\n", symlist[i]);
+ }
+ }
+
+ /* Clean up */
+
+ dlclose(handle);
+ return 0;
+}
diff --git a/testsuite/nsswitch/pam_winbind_syms.exp b/testsuite/nsswitch/pam_winbind_syms.exp
new file mode 100644
index 0000000000..f95274cdd9
--- /dev/null
+++ b/testsuite/nsswitch/pam_winbind_syms.exp
@@ -0,0 +1,44 @@
+#
+# @(#) Test nss functions are exported from the pam_winbind.so library
+# @(#) Test there are no external dependencies in the pam_winbind.so library
+#
+# We expect the following symbols to be exported:
+#
+# pam_sm_acct_mgmt
+# pam_sm_authenticate
+# pam_sm_setcred
+#
+# This test also has the nice side-effect of showing any unresolved symbols
+# in the library.
+#
+
+load_lib util-defs.exp
+
+# Compile pam_winbind_syms.c
+
+set output [target_compile "$srcdir/$subdir/pam_winbind_syms.c" \
+ "$srcdir/$subdir/pam_winbind_syms" executable \
+ {"libs=-ldl -lpam" "additional_flags=-g"}]
+
+if {$output != ""} {
+ perror "compile pam_winbind_syms.c"
+ puts $output
+ return
+}
+
+# Run load-dl.c
+
+set output [util_start "$srcdir/$subdir/pam_winbind_syms" \
+ "nsswitch/pam_winbind.so"]
+
+if {[regexp "FAIL:" $output]} {
+ fail "run pam_winbind_syms"
+ puts $output
+ return
+}
+
+pass "pam_winbind_syms"
+
+# Clean up
+
+file delete "$srcdir/$subdir/pam_winbind_syms"