1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-11 05:18:09 +03:00

Merge from TNG.

(This used to be commit af5ded9f17)
This commit is contained in:
Tim Potter 2000-05-12 06:55:09 +00:00
parent 053322d0ca
commit 75ebfc6f7a
24 changed files with 1053 additions and 0 deletions

View File

@ -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"]

26
testsuite/config/env.exp Normal file
View File

@ -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"
}

27
testsuite/config/unix.exp Normal file
View File

@ -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

View File

@ -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);
}
}

View File

@ -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"

View File

@ -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"
}
}

View File

@ -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"
}
}

35
testsuite/nsswitch/getent_r.sh Executable file
View File

@ -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

View File

@ -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;
}

View File

@ -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
}

View File

@ -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);
}

View File

@ -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"
}

View File

@ -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);
}

View File

@ -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"
}
}

View File

@ -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;
}

View File

@ -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
}

View File

@ -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);
}

View File

@ -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"
}
}

View File

@ -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);
}

View File

@ -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"
}

View File

@ -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;
}

View File

@ -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"

View File

@ -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;
}

View File

@ -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"