From: Ulrich Drepper Date: Sat, 31 Jan 1998 08:39:55 +0000 (+0000) Subject: Update. X-Git-Tag: cvs/libc-980218~30 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d67281a7eac124e2f1b498c377dde3432f711039;p=thirdparty%2Fglibc.git Update. 1998-01-31 Phil Blundell * configure.in: Add --without-cvs option to suppress automatic checkin of regenerated files. * config.make: Likewise. * Makefile: Respect with-cvs setting. * Makerules: Likewise. * configure.in: Allow the standalone ARM port to be configured. 1998-01-31 Thorsten Kukuk * grp/getgrgid_r.c: Define USE_NSCD. * grp/getgrnam_r.c: Likewise. * pwd/getpwuid_r.c: Likewise. * pwd/getpwnam_r.c: Likewise. * sysdeps/unix/inet/Subdirs: Add nscd subdir. * nss/getXXbyYY_r.c: Try at first nscd. * nscd/Makefile: New, for the Name Switch Cache Daemon (nscd). * nscd/connections.c: New file. * nscd/dbg_log.c: New file. * nscd/dbg_log.h: New file. * nscd/grpcache.c: New file. * nscd/nscd.c: New file. * nscd/nscd.h: New file. * nscd/nscd_conf.c: New file. * nscd/nscd_stat.c: New file. * nscd/pwdcache.c: New file. * nscd/nscd_getgr_r.c: New, client code, linked into libc. * nscd/nscd_getpw_r.c: Likewise. * nscd/nscd_proto.h: New, prototypes for client functions. * nscd/nscd.conf: New, example for a configuration file. * nscd/nscd.init: New, example for a startup script. * nscd/getgrgid_r.c: Old grp/getgrgid_r version, used from nscd to avoid deadlocks. * nscd/getgrnam_r.c: Likewise. * nscd/getpwnam_r.c: Likewise. * nscd/getpwuid_r.c: Likewise. * nis/nis_cache.c: New file. * nis/nis_cache2.h: New file. * nis/nis_cache2_xdr.c: New file. --- diff --git a/ChangeLog b/ChangeLog index 7bfd1af411b..ea73c1c7536 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,48 @@ +1998-01-31 Phil Blundell + + * configure.in: Add --without-cvs option to suppress automatic + checkin of regenerated files. + * config.make: Likewise. + * Makefile: Respect with-cvs setting. + * Makerules: Likewise. + + * configure.in: Allow the standalone ARM port to be configured. + +1998-01-31 Thorsten Kukuk + + * grp/getgrgid_r.c: Define USE_NSCD. + * grp/getgrnam_r.c: Likewise. + * pwd/getpwuid_r.c: Likewise. + * pwd/getpwnam_r.c: Likewise. + + * sysdeps/unix/inet/Subdirs: Add nscd subdir. + + * nss/getXXbyYY_r.c: Try at first nscd. + + * nscd/Makefile: New, for the Name Switch Cache Daemon (nscd). + * nscd/connections.c: New file. + * nscd/dbg_log.c: New file. + * nscd/dbg_log.h: New file. + * nscd/grpcache.c: New file. + * nscd/nscd.c: New file. + * nscd/nscd.h: New file. + * nscd/nscd_conf.c: New file. + * nscd/nscd_stat.c: New file. + * nscd/pwdcache.c: New file. + + * nscd/nscd_getgr_r.c: New, client code, linked into libc. + * nscd/nscd_getpw_r.c: Likewise. + * nscd/nscd_proto.h: New, prototypes for client functions. + + * nscd/nscd.conf: New, example for a configuration file. + * nscd/nscd.init: New, example for a startup script. + + * nscd/getgrgid_r.c: Old grp/getgrgid_r version, used from nscd to + avoid deadlocks. + * nscd/getgrnam_r.c: Likewise. + * nscd/getpwnam_r.c: Likewise. + * nscd/getpwuid_r.c: Likewise. + 1998-01-31 11:44 Ulrich Drepper * intl/Makefile: Use CVSOPTS in cvs invocation. @@ -520,9 +565,9 @@ * nis/Makefile: Distribute nis_cache2.h, add nis cache functions to routines. - * nis/nis_cache.c: New. - * nis/nis_cache2.h: New. - * nis/nis_cache2_xdr.c: New. + * nis/nis_cache.c: New file. + * nis/nis_cache2.h: New file. + * nis/nis_cache2_xdr.c: New file. * nis/nis_call.c: Changes for cache2_info parameter. * nis/nis_checkpoint.c: Likewise. * nis/nis_intern.h: Likewise. diff --git a/configure b/configure index 185ad96fc98..473ab075d98 100755 --- a/configure +++ b/configure @@ -30,6 +30,8 @@ ac_help="$ac_help --with-binutils=PATH specify location of binutils (as and ld)" ac_help="$ac_help --with-elf if using the ELF object format" +ac_help="$ac_help + --without-cvs if CVS should not be used" ac_help="$ac_help --enable-libio build in GNU libio instead of GNU stdio" ac_help="$ac_help @@ -618,6 +620,15 @@ else elf=no fi +# Check whether --with-cvs or --without-cvs was given. +if test "${with_cvs+set}" = set; then + withval="$with_cvs" + with_cvs=$withval +else + with_cvs=yes +fi + + # Check whether --enable-libio or --disable-libio was given. if test "${enable_libio+set}" = set; then @@ -762,7 +773,7 @@ else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } fi echo $ac_n "checking host system type""... $ac_c" 1>&6 -echo "configure:766: checking host system type" >&5 +echo "configure:777: checking host system type" >&5 host_alias=$host case "$host_alias" in @@ -805,8 +816,8 @@ esac ### platforms. ### if test -z "$enable_hacker_mode"; then - case "$host_os" in - linux* | gnu*) + case "$machine-$host_os" in + *-linux* | *-gnu* | arm*-none*) ;; *) echo "*** The GNU C library is currently not available for this platform." @@ -881,7 +892,7 @@ fi # This can take a while to compute. sysdep_dir=$srcdir/sysdeps echo $ac_n "checking sysdep dirs""... $ac_c" 1>&6 -echo "configure:885: checking sysdep dirs" >&5 +echo "configure:896: checking sysdep dirs" >&5 # Make sco3.2v4 become sco3.2.4 and sunos4.1.1_U1 become sunos4.1.1.U1. os="`echo $os | sed 's/\([0-9A-Z]\)[v_]\([0-9A-Z]\)/\1.\2/g'`" @@ -1082,7 +1093,7 @@ echo "$ac_t""sysdeps/generic" 1>&6 # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 -echo "configure:1086: checking for a BSD compatible install" >&5 +echo "configure:1097: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1136,7 +1147,7 @@ if test "$INSTALL" = "${srcdir}/install-sh -c"; then INSTALL='\$(..)./install-sh -c' fi echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6 -echo "configure:1140: checking whether ln -s works" >&5 +echo "configure:1151: checking whether ln -s works" >&5 if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1161,7 +1172,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1165: checking for $ac_word" >&5 +echo "configure:1176: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_MSGFMT'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1193,7 +1204,7 @@ test -n "$MSGFMT" || MSGFMT=":" # Extract the first word of "makeinfo", so it can be a program name with args. set dummy makeinfo; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1197: checking for $ac_word" >&5 +echo "configure:1208: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_MAKEINFO'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1233,7 +1244,7 @@ fi # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1237: checking for $ac_word" >&5 +echo "configure:1248: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1262,7 +1273,7 @@ if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1266: checking for $ac_word" >&5 +echo "configure:1277: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1310,7 +1321,7 @@ fi fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:1314: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 +echo "configure:1325: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. @@ -1320,11 +1331,11 @@ ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:1339: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then @@ -1347,13 +1358,13 @@ else cross_linkable=yes fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:1351: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "configure:1362: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:1357: checking whether we are using GNU C" >&5 +echo "configure:1368: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1362,7 +1373,7 @@ else yes; #endif EOF -if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1366: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1377: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no @@ -1379,7 +1390,7 @@ if test $ac_cv_prog_gcc = yes; then yes; #endif EOF - if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1383: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1394: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then if test -z "$CFLAGS"; then CFLAGS="-g -O2" fi @@ -1391,7 +1402,7 @@ else fi echo $ac_n "checking build system type""... $ac_c" 1>&6 -echo "configure:1395: checking build system type" >&5 +echo "configure:1406: checking build system type" >&5 build_alias=$build case "$build_alias" in @@ -1414,7 +1425,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1418: checking for $ac_word" >&5 +echo "configure:1429: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_BUILD_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1445,7 +1456,7 @@ done fi echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 -echo "configure:1449: checking how to run the C preprocessor" >&5 +echo "configure:1460: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= @@ -1460,13 +1471,13 @@ else # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1470: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1481: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then : @@ -1477,13 +1488,13 @@ else rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1487: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1498: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then : @@ -1516,7 +1527,7 @@ LD=`$CC -print-file-name=ld` # Determine whether we are using GNU binutils. echo $ac_n "checking whether $AS is GNU as""... $ac_c" 1>&6 -echo "configure:1520: checking whether $AS is GNU as" >&5 +echo "configure:1531: checking whether $AS is GNU as" >&5 if eval "test \"`echo '$''{'libc_cv_prog_as_gnu'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1534,7 +1545,7 @@ rm -f a.out gnu_as=$libc_cv_prog_as_gnu echo $ac_n "checking whether $LD is GNU ld""... $ac_c" 1>&6 -echo "configure:1538: checking whether $LD is GNU ld" >&5 +echo "configure:1549: checking whether $LD is GNU ld" >&5 if eval "test \"`echo '$''{'libc_cv_prog_ld_gnu'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1558,7 +1569,7 @@ fi # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. set dummy ${ac_tool_prefix}ar; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1562: checking for $ac_word" >&5 +echo "configure:1573: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1589,7 +1600,7 @@ fi # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1593: checking for $ac_word" >&5 +echo "configure:1604: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1620,7 +1631,7 @@ if test -n "$ac_tool_prefix"; then # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1624: checking for $ac_word" >&5 +echo "configure:1635: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1655,7 +1666,7 @@ fi # Extract the first word of "bash", so it can be a program name with args. set dummy bash; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1659: checking for $ac_word" >&5 +echo "configure:1670: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_BASH'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1697,7 +1708,7 @@ if test "$BASH" = no; then # Extract the first word of "ksh", so it can be a program name with args. set dummy ksh; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1701: checking for $ac_word" >&5 +echo "configure:1712: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_KSH'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1743,7 +1754,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1747: checking for $ac_word" >&5 +echo "configure:1758: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_PERL'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1778,7 +1789,7 @@ test -n "$PERL" || PERL="no" echo $ac_n "checking for signed size_t type""... $ac_c" 1>&6 -echo "configure:1782: checking for signed size_t type" >&5 +echo "configure:1793: checking for signed size_t type" >&5 if eval "test \"`echo '$''{'libc_cv_signed_size_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1802,12 +1813,12 @@ EOF fi echo $ac_n "checking for libc-friendly stddef.h""... $ac_c" 1>&6 -echo "configure:1806: checking for libc-friendly stddef.h" >&5 +echo "configure:1817: checking for libc-friendly stddef.h" >&5 if eval "test \"`echo '$''{'libc_cv_friendly_stddef'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1837: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* libc_cv_friendly_stddef=yes else @@ -1841,7 +1852,7 @@ override stddef.h = # The installed seems to be libc-friendly." fi echo $ac_n "checking whether we need to use -P to assemble .S files""... $ac_c" 1>&6 -echo "configure:1845: checking whether we need to use -P to assemble .S files" >&5 +echo "configure:1856: checking whether we need to use -P to assemble .S files" >&5 if eval "test \"`echo '$''{'libc_cv_need_minus_P'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1872,7 +1883,7 @@ if test $ac_cv_prog_gcc = yes; then # We must check this even if -pipe is not given here, because the user # might do `make CFLAGS=-pipe'. echo $ac_n "checking for gcc 2.7.x -pipe bug""... $ac_c" 1>&6 -echo "configure:1876: checking for gcc 2.7.x -pipe bug" >&5 +echo "configure:1887: checking for gcc 2.7.x -pipe bug" >&5 if eval "test \"`echo '$''{'libc_cv_gcc_pipe_bug'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1901,7 +1912,7 @@ else fi echo $ac_n "checking for assembler global-symbol directive""... $ac_c" 1>&6 -echo "configure:1905: checking for assembler global-symbol directive" >&5 +echo "configure:1916: checking for assembler global-symbol directive" >&5 if eval "test \"`echo '$''{'libc_cv_asm_global_directive'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1931,7 +1942,7 @@ EOF fi echo $ac_n "checking for .set assembler directive""... $ac_c" 1>&6 -echo "configure:1935: checking for .set assembler directive" >&5 +echo "configure:1946: checking for .set assembler directive" >&5 if eval "test \"`echo '$''{'libc_cv_asm_set_directive'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1965,7 +1976,7 @@ EOF fi echo $ac_n "checking for .symver assembler directive""... $ac_c" 1>&6 -echo "configure:1969: checking for .symver assembler directive" >&5 +echo "configure:1980: checking for .symver assembler directive" >&5 if eval "test \"`echo '$''{'libc_cv_asm_symver_directive'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1984,7 +1995,7 @@ fi echo "$ac_t""$libc_cv_asm_symver_directive" 1>&6 echo $ac_n "checking for ld --version-script""... $ac_c" 1>&6 -echo "configure:1988: checking for ld --version-script" >&5 +echo "configure:1999: checking for ld --version-script" >&5 if eval "test \"`echo '$''{'libc_cv_ld_version_script_option'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2007,7 +2018,7 @@ EOF if { ac_try='${CC-cc} $CFLAGS -shared -o conftest.so conftest.o -nostartfiles -nostdlib -Wl,--version-script,conftest.map - 1>&5'; { (eval echo configure:2011: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; + 1>&5'; { (eval echo configure:2022: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then libc_cv_ld_version_script_option=yes else @@ -2045,7 +2056,7 @@ if test $VERSIONING = no; then fi if test $elf = yes; then echo $ac_n "checking for .previous assembler directive""... $ac_c" 1>&6 -echo "configure:2049: checking for .previous assembler directive" >&5 +echo "configure:2060: checking for .previous assembler directive" >&5 if eval "test \"`echo '$''{'libc_cv_asm_previous_directive'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2053,7 +2064,7 @@ else .section foo_section .previous EOF - if { ac_try='${CC-cc} -c $CFLAGS conftest.s 1>&5'; { (eval echo configure:2057: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then + if { ac_try='${CC-cc} -c $CFLAGS conftest.s 1>&5'; { (eval echo configure:2068: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then libc_cv_asm_previous_directive=yes else libc_cv_asm_previous_directive=no @@ -2069,7 +2080,7 @@ EOF else echo $ac_n "checking for .popsection assembler directive""... $ac_c" 1>&6 -echo "configure:2073: checking for .popsection assembler directive" >&5 +echo "configure:2084: checking for .popsection assembler directive" >&5 if eval "test \"`echo '$''{'libc_cv_asm_popsection_directive'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2077,7 +2088,7 @@ else .pushsection foo_section .popsection EOF - if { ac_try='${CC-cc} -c $CFLAGS conftest.s 1>&5'; { (eval echo configure:2081: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then + if { ac_try='${CC-cc} -c $CFLAGS conftest.s 1>&5'; { (eval echo configure:2092: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then libc_cv_asm_popsection_directive=yes else libc_cv_asm_popsection_directive=no @@ -2097,12 +2108,12 @@ fi if test $elf != yes; then echo $ac_n "checking for .init and .fini sections""... $ac_c" 1>&6 -echo "configure:2101: checking for .init and .fini sections" >&5 +echo "configure:2112: checking for .init and .fini sections" >&5 if eval "test \"`echo '$''{'libc_cv_have_initfini'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2126: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* libc_cv_have_initfini=yes else @@ -2139,19 +2150,19 @@ if test $elf = yes; then else if test $ac_cv_prog_cc_works = yes; then echo $ac_n "checking for _ prefix on C symbol names""... $ac_c" 1>&6 -echo "configure:2143: checking for _ prefix on C symbol names" >&5 +echo "configure:2154: checking for _ prefix on C symbol names" >&5 if eval "test \"`echo '$''{'libc_cv_asm_underscores'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:2166: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* libc_cv_asm_underscores=yes else @@ -2166,17 +2177,17 @@ fi echo "$ac_t""$libc_cv_asm_underscores" 1>&6 else echo $ac_n "checking for _ prefix on C symbol names""... $ac_c" 1>&6 -echo "configure:2170: checking for _ prefix on C symbol names" >&5 +echo "configure:2181: checking for _ prefix on C symbol names" >&5 if eval "test \"`echo '$''{'libc_cv_asm_underscores'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2191: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then if grep _underscore_test conftest* >/dev/null; then rm -f conftest* libc_cv_asm_underscores=yes @@ -2209,7 +2220,7 @@ if test $elf = yes; then libc_cv_asm_weakext_directive=no else echo $ac_n "checking for assembler .weak directive""... $ac_c" 1>&6 -echo "configure:2213: checking for assembler .weak directive" >&5 +echo "configure:2224: checking for assembler .weak directive" >&5 if eval "test \"`echo '$''{'libc_cv_asm_weak_directive'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2232,7 +2243,7 @@ echo "$ac_t""$libc_cv_asm_weak_directive" 1>&6 if test $libc_cv_asm_weak_directive = no; then echo $ac_n "checking for assembler .weakext directive""... $ac_c" 1>&6 -echo "configure:2236: checking for assembler .weakext directive" >&5 +echo "configure:2247: checking for assembler .weakext directive" >&5 if eval "test \"`echo '$''{'libc_cv_asm_weakext_directive'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2269,7 +2280,7 @@ EOF fi echo $ac_n "checking for ld --no-whole-archive""... $ac_c" 1>&6 -echo "configure:2273: checking for ld --no-whole-archive" >&5 +echo "configure:2284: checking for ld --no-whole-archive" >&5 if eval "test \"`echo '$''{'libc_cv_ld_no_whole_archive'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2280,7 +2291,7 @@ __throw () {} EOF if { ac_try='${CC-cc} $CFLAGS -nostdlib -nostartfiles -Wl,--no-whole-archive - -o conftest conftest.c 1>&5'; { (eval echo configure:2284: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then + -o conftest conftest.c 1>&5'; { (eval echo configure:2295: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then libc_cv_ld_no_whole_archive=yes else libc_cv_ld_no_whole_archive=no @@ -2291,7 +2302,7 @@ fi echo "$ac_t""$libc_cv_ld_no_whole_archive" 1>&6 echo $ac_n "checking for gcc -fno-exceptions""... $ac_c" 1>&6 -echo "configure:2295: checking for gcc -fno-exceptions" >&5 +echo "configure:2306: checking for gcc -fno-exceptions" >&5 if eval "test \"`echo '$''{'libc_cv_gcc_no_exceptions'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2302,7 +2313,7 @@ __throw () {} EOF if { ac_try='${CC-cc} $CFLAGS -nostdlib -nostartfiles -fno-exceptions - -o conftest conftest.c 1>&5'; { (eval echo configure:2306: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then + -o conftest conftest.c 1>&5'; { (eval echo configure:2317: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then libc_cv_gcc_no_exceptions=yes else libc_cv_gcc_no_exceptions=no @@ -2314,14 +2325,14 @@ echo "$ac_t""$libc_cv_gcc_no_exceptions" 1>&6 if test "$base_machine" = alpha ; then echo $ac_n "checking for function ..ng prefix""... $ac_c" 1>&6 -echo "configure:2318: checking for function ..ng prefix" >&5 +echo "configure:2329: checking for function ..ng prefix" >&5 if eval "test \"`echo '$''{'libc_cv_gcc_alpha_ng_prefix'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.c <<\EOF foo () { } EOF -if { ac_try='${CC-cc} -S conftest.c -o - | fgrep "\$foo..ng" > /dev/null'; { (eval echo configure:2325: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; +if { ac_try='${CC-cc} -S conftest.c -o - | fgrep "\$foo..ng" > /dev/null'; { (eval echo configure:2336: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then libc_cv_gcc_alpha_ng_prefix=yes else @@ -2345,12 +2356,12 @@ fi fi echo $ac_n "checking for DWARF2 unwind info support""... $ac_c" 1>&6 -echo "configure:2349: checking for DWARF2 unwind info support" >&5 +echo "configure:2360: checking for DWARF2 unwind info support" >&5 if eval "test \"`echo '$''{'libc_cv_gcc_dwarf2_unwind_info'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.c <&5; (eval $ac_try) 2>&5; }; }; then + -o conftest conftest.c -lgcc >&5'; { (eval echo configure:2392: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then libc_cv_gcc_dwarf2_unwind_info=static else libc_cv_gcc_dwarf2_unwind_info=no @@ -2385,7 +2396,7 @@ fi if test $libc_cv_gcc_dwarf2_unwind_info = no; then if { ac_try='${CC-cc} $CFLAGS -DCHECK__register_frame -nostdlib -nostartfiles - -o conftest conftest.c -lgcc >&5'; { (eval echo configure:2389: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then + -o conftest conftest.c -lgcc >&5'; { (eval echo configure:2400: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then libc_cv_gcc_dwarf2_unwind_info=yes else libc_cv_gcc_dwarf2_unwind_info=no @@ -2456,7 +2467,7 @@ if test "$uname" = "sysdeps/generic"; then fi echo $ac_n "checking OS release for uname""... $ac_c" 1>&6 -echo "configure:2460: checking OS release for uname" >&5 +echo "configure:2471: checking OS release for uname" >&5 if eval "test \"`echo '$''{'libc_cv_uname_release'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2478,7 +2489,7 @@ echo "$ac_t""$libc_cv_uname_release" 1>&6 uname_release="$libc_cv_uname_release" echo $ac_n "checking OS version for uname""... $ac_c" 1>&6 -echo "configure:2482: checking OS version for uname" >&5 +echo "configure:2493: checking OS version for uname" >&5 if eval "test \"`echo '$''{'libc_cv_uname_version'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2500,7 +2511,7 @@ else fi echo $ac_n "checking stdio selection""... $ac_c" 1>&6 -echo "configure:2504: checking stdio selection" >&5 +echo "configure:2515: checking stdio selection" >&5 case $stdio in libio) cat >> confdefs.h <<\EOF @@ -2512,7 +2523,7 @@ esac echo "$ac_t""$stdio" 1>&6 echo $ac_n "checking ldap selection""... $ac_c" 1>&6 -echo "configure:2516: checking ldap selection" >&5 +echo "configure:2527: checking ldap selection" >&5 case $add_ons in *ldap*) @@ -2574,7 +2585,7 @@ if test $static = no && test $shared = yes; then fi echo $ac_n "checking whether -fPIC is default""... $ac_c" 1>&6 -echo "configure:2578: checking whether -fPIC is default" >&5 +echo "configure:2589: checking whether -fPIC is default" >&5 if eval "test \"`echo '$''{'pic_default'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2756,6 +2767,7 @@ s%@includedir@%$includedir%g s%@oldincludedir@%$oldincludedir%g s%@infodir@%$infodir%g s%@mandir@%$mandir%g +s%@with_cvs@%$with_cvs%g s%@subdirs@%$subdirs%g s%@host@%$host%g s%@host_alias@%$host_alias%g diff --git a/grp/getgrgid_r.c b/grp/getgrgid_r.c index 8f05ae50607..8d5122a2cd6 100644 --- a/grp/getgrgid_r.c +++ b/grp/getgrgid_r.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1996. @@ -26,5 +26,6 @@ #define ADD_PARAMS gid_t gid #define ADD_VARIABLES gid #define BUFLEN NSS_BUFLEN_GROUP +#define USE_NSCD 1 -#include "../nss/getXXbyYY_r.c" +#include diff --git a/grp/getgrnam_r.c b/grp/getgrnam_r.c index eb34c1f7776..ee84cfe5ece 100644 --- a/grp/getgrnam_r.c +++ b/grp/getgrnam_r.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1996. @@ -25,5 +25,6 @@ #define DATABASE_NAME group #define ADD_PARAMS const char *name #define ADD_VARIABLES name +#define USE_NSCD 1 -#include "../nss/getXXbyYY_r.c" +#include diff --git a/nscd/Makefile b/nscd/Makefile new file mode 100644 index 00000000000..4510c4d452e --- /dev/null +++ b/nscd/Makefile @@ -0,0 +1,46 @@ +# Copyright (C) 1998 Free Software Foundation, Inc. +# This file is part of the GNU C Library. + +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. + +# The GNU C Library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. + +# You should have received a copy of the GNU Library General Public +# License along with the GNU C Library; see the file COPYING.LIB. If not, +# write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +# +# Sub-makefile for nscd portion of the library. +# +subdir := nscd + +routines := nscd_getpw_r nscd_getgr_r + +# We can later add the names of other thread packages here. +ifeq (,$(findstring linuxthreads,$(add-ons))) + +others := nscd +install-sbin := nscd + +endif + +nscd-routines := nscd connections pwdcache getpwnam_r getpwuid_r grpcache\ + getgrnam_r getgrgid_r dbg_log nscd_conf nscd_stat +extra-objs := $(nscd-routines:=.o) + +distribute := nscd.h dbg_log.h + +include ../Rules + +ifeq ($(build-shared),yes) +$(objpfx)nscd: $(nscd-routines:%=$(objpfx)%.o) $(objpfx)../linuxthreads/libpthread.so$(libpthread.so-version) $(objpfx)../nis/libnsl.so$(libnsl.so-version) +else +$(objpfx)nscd: $(nscd-routines:%=$(objpfx)%.o) $(objpfx)../linuxthreads/libpthread.a $(objpfx)../nis/libnsl.a +endif diff --git a/nscd/TODO b/nscd/TODO new file mode 100644 index 00000000000..16c28354688 --- /dev/null +++ b/nscd/TODO @@ -0,0 +1,7 @@ + +* We should use readv/writev for group entries, too + +* If we have reached the max. # of process, close accept socket. + ! THIS COULD CAUSE THE KERNEL TO HANG ! BE CAREFUL ! + +* Implement cache for hosts diff --git a/nscd/connections.c b/nscd/connections.c new file mode 100644 index 00000000000..abde747a8aa --- /dev/null +++ b/nscd/connections.c @@ -0,0 +1,529 @@ +/* Copyright (c) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "nscd.h" +#include "dbg_log.h" + +/* Socket 0 in the array is named and exported into the file namespace + as a connection point for clients. */ +static int sock[MAX_NUM_CONNECTIONS]; +static int socks_active; +static fd_set read_set; +static pthread_mutex_t sock_lock = PTHREAD_MUTEX_INITIALIZER; + + +/* Cleanup. */ +void +close_sockets (void) +{ + int i; + + if (debug_flag) + dbg_log (_("close_sockets called")); + + pthread_mutex_lock (&sock_lock); + + /* Close sockets. */ + for (i = 0; i < MAX_NUM_CONNECTIONS; ++i) + if (sock[i] != 0) + { + if (close (sock[i])) + dbg_log (_("socket [%d|%d] close: %s"), strerror (errno)); + + sock[i] = 0; + --socks_active; + } + + pthread_mutex_unlock (&sock_lock); +} + +void +close_socket (int conn) +{ + if (debug_flag > 2) + dbg_log (_("close socket (%d|%d)"), conn, sock[conn]); + + pthread_mutex_lock (&sock_lock); + + close (sock[conn]); + sock[conn] = 0; + --socks_active; + + pthread_mutex_unlock (&sock_lock); +} + +/* Local rountine, assigns a socket to a new connection request. */ +static void +handle_new_connection (void) +{ + int i; + + if (debug_flag > 2) + dbg_log (_("handle_new_connection")); + + pthread_mutex_lock (&sock_lock); + + if (socks_active < MAX_NUM_CONNECTIONS) + /* Find a free socket entry to use. */ + for (i = 1; i < MAX_NUM_CONNECTIONS; ++i) + { + if (sock[i] == 0) + { + if ((sock[i] = accept (sock[0], NULL, NULL)) < 0) + { + dbg_log (_("socket accept: %s"), strerror (errno)); + return; + } + ++socks_active; + FD_SET (sock[i], &read_set); + if (debug_flag > 2) + dbg_log (_("handle_new_connection used socket %d|%d"), i, + sock[i]); + break; + } + } + else + { + int black_widow_sock; + dbg_log (_("Supported number of simultainious connections exceeded")); + dbg_log (_("Ignoring client connect request")); + /* There has to be a better way to ignore a connection request,.. + when I get my hands on a sockets wiz I'll modify this. */ + black_widow_sock = accept (sock[0], NULL, NULL); + close (black_widow_sock); + } + pthread_mutex_unlock (&sock_lock); +} + +/* Local routine, reads a request off a socket indicated by a selectset. */ +static int +handle_new_request (fd_set read_selects, int **connp, request_header **reqp, + char **key) +{ + ssize_t nbytes; + int i; + + if (debug_flag) + dbg_log ("handle_new_request"); + + /* Find the descriptor. */ + for (i = 1; i < MAX_NUM_CONNECTIONS; ++i) + if (FD_ISSET(sock[i], &read_selects)) + break; + + if (debug_flag > 2) + dbg_log (_("handle_new_request uses socket %d"), i); + + /* Read from it. */ + nbytes = read (sock[i], *reqp, sizeof (request_header)); + if (nbytes != sizeof (request_header)) + { + /* Handle non-data read cases. */ + if (nbytes == 0) + { + /* Close socket down. */ + if (debug_flag > 2) + dbg_log (_("Real close socket %d|%d"), i, sock[i]); + + pthread_mutex_lock (&sock_lock); + FD_CLR (sock[i], &read_set); + close (sock[i]); + sock[i] = 0; + --socks_active; + pthread_mutex_unlock (&sock_lock); + } + else + if (nbytes < 0) + { + dbg_log (_("Read(%d|%d) error on get request: %s"), + i, sock[i], strerror (errno)); + exit (1); + } + else + dbg_log (_("Read, data < request buf size, ignoring data")); + + return -1; + } + else + { + *key = malloc ((*reqp)->key_len + 1); + /* Read the key from it */ + nbytes = read (sock[i], *key, (*reqp)->key_len); + if (nbytes != (*reqp)->key_len) + { + /* Handle non-data read cases. */ + if (nbytes == 0) + { + /* Close socket down. */ + if (debug_flag > 2) + dbg_log (_("Real close socket %d|%d"), i, sock[i]); + + pthread_mutex_lock (&sock_lock); + FD_CLR (sock[i], &read_set); + close (sock[i]); + sock[i] = 0; + --socks_active; + pthread_mutex_unlock (&sock_lock); + } + else + if (nbytes < 0) + { + perror (_("Read() error on get request")); + return 0; + } + else + fputs (_("Read, data < request buf size, ignoring data"), + stderr); + + free (*key); + return -1; + } + else + { + /* Ok, have a live one, A real data req buf has been obtained. */ + (*key)[(*reqp)->key_len] = '\0'; + **connp = i; + return 0; + } + } +} + +void +get_request (int *conn, request_header *req, char **key) +{ + int i, nr, done = 0; + fd_set read_selects; + + if (debug_flag) + dbg_log ("get_request"); + + /* loop, processing new connection requests until a client buffer + is read in on an existing connection. */ + while (!done) + { + /* Set up the socket descriptor mask for the select. + copy read_set into the local copy. */ + + FD_ZERO (&read_selects); + pthread_mutex_lock (&sock_lock); + for (i = 0; i < MAX_NUM_CONNECTIONS; ++i) + { + if (FD_ISSET (sock[i], &read_set)) + FD_SET (sock[i], &read_selects); + } + pthread_mutex_unlock (&sock_lock); + /* Poll active connections using select(). */ + nr = select (FD_SETSIZE, &read_selects, NULL, NULL, NULL); + if (nr <= 0) + { + perror (_("Select new reads")); + exit (1); + } + if (FD_ISSET (sock[0], &read_selects)) + /* Handle the case of a new connection request on the named socket. */ + handle_new_connection (); + else + { + /* Read data from client specific descriptor. */ + if (handle_new_request (read_selects, &conn, &req, key) == 0) + { + FD_CLR (sock[*conn], &read_set); + done = 1; + } + } + } /* While not_done. */ +} + +void +init_sockets (void) +{ + struct sockaddr_un sock_addr; + + /* Initialize the connections db. */ + socks_active = 0; + FD_ZERO (&read_set); + + /* Create the socket. */ + sock[0] = socket (AF_UNIX, SOCK_STREAM, 0); + if (sock[0] < 0) + { + perror (_("cannot create socket")); + exit (1); + } + /* Bind a name to the socket. */ + sock_addr.sun_family = AF_UNIX; + strcpy (sock_addr.sun_path, _PATH_NSCDSOCKET); + if (bind (sock[0], (struct sockaddr *) &sock_addr, sizeof (sock_addr)) < 0) + { + dbg_log ("%s: %s", _PATH_NSCDSOCKET, strerror (errno)); + exit (1); + } + /* Set permissions for the socket. */ + chmod (_PATH_NSCDSOCKET, 0666); + + /* Set the socket up to accept connections. */ + if (listen (sock[0], MAX_NUM_CONNECTIONS) < 0) + { + perror (_("cannot enable socket to accept connections")); + exit (1); + } + + /* Add the socket to the server's set of active sockets. */ + FD_SET (sock[0], &read_set); + ++socks_active; +} + +void +pw_send_answer (int conn, struct passwd *pwd) +{ + pw_response_header resp; + + resp.version = NSCD_VERSION; + if (pwd != NULL) + { + resp.found = 1; + resp.pw_name_len = strlen (pwd->pw_name); + resp.pw_passwd_len = strlen (pwd->pw_passwd); + resp.pw_uid = pwd->pw_uid; + resp.pw_gid = pwd->pw_gid; + resp.pw_gecos_len = strlen (pwd->pw_gecos); + resp.pw_dir_len = strlen (pwd->pw_dir); + resp.pw_shell_len = strlen (pwd->pw_shell); + } + else + { + resp.found = 0; + resp.pw_name_len = 0; + resp.pw_passwd_len = 0; + resp.pw_uid = -1; + resp.pw_gid = -1; + resp.pw_gecos_len = 0; + resp.pw_dir_len = 0; + resp.pw_shell_len = 0; + } + if (sock[conn] == 0) + { + dbg_log (_("bad connection id on send response [%d|%d]"), + conn, sock[conn]); + return; + } + + /* Send response header. */ + if (write (sock[conn], &resp, sizeof (pw_response_header)) != + sizeof (pw_response_header)) + { + dbg_log (_("write incomplete on send response: %s"), strerror (errno)); + return; + } + + if (resp.found) + { + struct iovec vec[5]; + + /* Send pw_name. */ + vec[0].iov_base = pwd->pw_name; + vec[0].iov_len = resp.pw_name_len; + /* Send pw_passwd. */ + vec[1].iov_base = pwd->pw_passwd; + vec[1].iov_len = resp.pw_passwd_len; + /* Send pw_gecos. */ + vec[2].iov_base = pwd->pw_gecos; + vec[2].iov_len = resp.pw_gecos_len; + /* Send pw_dir. */ + vec[3].iov_base = pwd->pw_dir; + vec[3].iov_len = resp.pw_dir_len; + /* Send pw_shell. */ + vec[4].iov_base = pwd->pw_shell; + vec[4].iov_len = resp.pw_shell_len; + + if (writev (sock[conn], vec, 5) != (resp.pw_name_len + resp.pw_passwd_len + + resp.pw_gecos_len + resp.pw_dir_len + + resp.pw_shell_len)) + dbg_log (_("write incomplete on send passwd answer: %s"), + strerror (errno)); + } +} + +void +pw_send_disabled (int conn) +{ + pw_response_header resp; + + resp.version = NSCD_VERSION; + resp.found = -1; + resp.pw_name_len = 0; + resp.pw_passwd_len = 0; + resp.pw_uid = -1; + resp.pw_gid = -1; + resp.pw_gecos_len = 0; + resp.pw_dir_len = 0; + resp.pw_shell_len = 0; + + if (sock[conn] == 0) + { + dbg_log ("bad connection id on send response [%d|%d]", + conn, sock[conn]); + return; + } + + /* Send response header. */ + if (write (sock[conn], &resp, sizeof (pw_response_header)) + != sizeof (pw_response_header)) + dbg_log (_("write incomplete on send response: %s"), strerror (errno)); +} + +void +gr_send_answer (int conn, struct group *grp) +{ + gr_response_header resp; + + resp.version = NSCD_VERSION; + if (grp != NULL) + { + resp.found = 1; + resp.gr_name_len = strlen (grp->gr_name); + resp.gr_passwd_len = strlen (grp->gr_passwd); + resp.gr_gid = grp->gr_gid; + resp.gr_mem_len = 0; + while (grp->gr_mem[resp.gr_mem_len]) + ++resp.gr_mem_len; + } + else + { + resp.found = 0; + resp.gr_name_len = 0; + resp.gr_passwd_len = 0; + resp.gr_gid = -1; + resp.gr_mem_len = 0; + } + if (sock[conn] == 0) + { + dbg_log (_("bad connection id on send response [%d|%d]"), + conn, sock[conn]); + return; + } + + /* Send response header. */ + if (write (sock[conn], &resp, sizeof (gr_response_header)) + != sizeof (gr_response_header)) + { + dbg_log (_("write incomplete on send response: %s"), strerror (errno)); + return; + } + + if (resp.found) + { + unsigned int l = 0; + + /* Send gr_name. */ + if (write (sock[conn], grp->gr_name, resp.gr_name_len) + != resp.gr_name_len) + { + dbg_log (_("write incomplete on send response: %s"), + strerror (errno)); + return; + } + /* Send gr_passwd. */ + if (write (sock[conn], grp->gr_passwd, resp.gr_passwd_len) + != resp.gr_passwd_len) + { + dbg_log (_("write incomplete on send response: %s"), + strerror (errno)); + return; + } + + while (grp->gr_mem[l]) + { + size_t len = strlen (grp->gr_mem[l]); + + if (write (sock[conn], &len, sizeof (len)) != sizeof (len)) + { + dbg_log (_("write incomplete on send response: %s"), + strerror (errno)); + return; + } + if (write (sock[conn], grp->gr_mem[l], len) != len) + { + dbg_log (_("write incomplete on send response: %s"), + strerror (errno)); + return; + } + ++l; + } + } +} + +void +gr_send_disabled (int conn) +{ + gr_response_header resp; + + resp.version = NSCD_VERSION; + resp.found = -1; + resp.gr_name_len = 0; + resp.gr_passwd_len = 0; + resp.gr_gid = -1; + resp.gr_mem_len = 0; + + if (sock[conn] == 0) + { + dbg_log (_("bad connection id on send gr_disabled response [%d|%d]"), + conn, sock[conn]); + return; + } + + /* Send response header. */ + if (write (sock[conn], &resp, sizeof (gr_response_header)) + != sizeof (gr_response_header)) + dbg_log (_("write incomplete on send gr_disabled response: %s"), + strerror (errno)); +} + +void +stat_send (int conn, stat_response_header *resp) +{ + if (sock[conn] == 0) + { + dbg_log (_("bad connection id on send stat response [%d|%d]"), + conn, sock[conn]); + return; + } + + /* send response header. */ + if (write (sock[conn], resp, sizeof (stat_response_header)) + != sizeof (stat_response_header)) + dbg_log (_("write incomplete on send stat response: %s"), + strerror (errno)); +} diff --git a/nscd/dbg_log.c b/nscd/dbg_log.c new file mode 100644 index 00000000000..37065e446ec --- /dev/null +++ b/nscd/dbg_log.c @@ -0,0 +1,64 @@ +/* Copyright (c) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include "dbg_log.h" +#include "nscd.h" + +/* if in debug mode and we have a debug file, we write the messages to it, + if in debug mode and no debug file, we write the messages to stderr, + else to syslog. */ + +FILE *dbgout = NULL; +int debug_flag = 0; + +int +set_logfile (const char *logfile) +{ + dbgout = fopen (logfile, "a"); + return dbgout == NULL ? 0 : 1; +} + +void +dbg_log (const char *fmt,...) +{ + va_list ap; + char msg[512], msg2[512]; + + va_start (ap, fmt); + vsnprintf (msg2, sizeof (msg), fmt, ap); + + if (debug_flag) + { + snprintf (msg, sizeof (msg), "%d: %s\n", getpid (), msg2); + if (dbgout) + fputs (msg, dbgout); + else + fputs (msg, stderr); + } + else + { + snprintf (msg, sizeof (msg), "%d: %s", getpid (), msg2); + syslog (LOG_NOTICE, msg); + } + va_end (ap); +} diff --git a/nscd/dbg_log.h b/nscd/dbg_log.h new file mode 100644 index 00000000000..c3d1dc4559c --- /dev/null +++ b/nscd/dbg_log.h @@ -0,0 +1,27 @@ +/* Copyright (c) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _DBG_LOG_H +#define _DBG_LOG_H 1 + +extern int debug_flag; + +extern void dbg_log (const char *, ...); + +#endif diff --git a/nscd/getgrgid_r.c b/nscd/getgrgid_r.c new file mode 100644 index 00000000000..30116026715 --- /dev/null +++ b/nscd/getgrgid_r.c @@ -0,0 +1,30 @@ +/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + + +#define LOOKUP_TYPE struct group +#define FUNCTION_NAME getgrgid +#define DATABASE_NAME group +#define ADD_PARAMS gid_t gid +#define ADD_VARIABLES gid +#define BUFLEN NSS_BUFLEN_GROUP + +#include diff --git a/nscd/getgrnam_r.c b/nscd/getgrnam_r.c new file mode 100644 index 00000000000..3575e74b1fc --- /dev/null +++ b/nscd/getgrnam_r.c @@ -0,0 +1,29 @@ +/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + + +#define LOOKUP_TYPE struct group +#define FUNCTION_NAME getgrnam +#define DATABASE_NAME group +#define ADD_PARAMS const char *name +#define ADD_VARIABLES name + +#include diff --git a/nscd/getpwnam_r.c b/nscd/getpwnam_r.c new file mode 100644 index 00000000000..328c3055f80 --- /dev/null +++ b/nscd/getpwnam_r.c @@ -0,0 +1,30 @@ +/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + + +#define LOOKUP_TYPE struct passwd +#define FUNCTION_NAME getpwnam +#define DATABASE_NAME passwd +#define ADD_PARAMS const char *name +#define ADD_VARIABLES name +#define BUFLEN NSS_BUFLEN_PASSWD + +#include diff --git a/nscd/getpwuid_r.c b/nscd/getpwuid_r.c new file mode 100644 index 00000000000..91bd802d61f --- /dev/null +++ b/nscd/getpwuid_r.c @@ -0,0 +1,30 @@ +/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + + +#define LOOKUP_TYPE struct passwd +#define FUNCTION_NAME getpwuid +#define DATABASE_NAME passwd +#define ADD_PARAMS uid_t uid +#define ADD_VARIABLES uid +#define BUFLEN NSS_BUFLEN_PASSWD + +#include diff --git a/nscd/grpcache.c b/nscd/grpcache.c new file mode 100644 index 00000000000..9f6c767fd7d --- /dev/null +++ b/nscd/grpcache.c @@ -0,0 +1,589 @@ +/* Copyright (c) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include +#include +#include + +#include "dbg_log.h" +#include "nscd.h" + +static unsigned long modulo = 211; +static unsigned long postimeout = 3600; +static unsigned long negtimeout = 60; + +static unsigned long poshit = 0; +static unsigned long posmiss = 0; +static unsigned long neghit = 0; +static unsigned long negmiss = 0; + +struct grphash +{ + time_t create; + struct grphash *next; + struct group *grp; +}; +typedef struct grphash grphash; + +struct gidhash +{ + struct gidhash *next; + struct grphash *grptr; +}; +typedef struct gidhash gidhash; + +struct neghash +{ + time_t create; + struct neghash *next; + char *key; +}; +typedef struct neghash neghash; + +static grphash *grptbl; +static gidhash *gidtbl; +static neghash *negtbl; + +static pthread_rwlock_t grplock = PTHREAD_RWLOCK_INITIALIZER; +static pthread_rwlock_t neglock = PTHREAD_RWLOCK_INITIALIZER; + +static void *grptable_update (void *); +static void *negtable_update (void *); + +void +get_gr_stat (stat_response_header *stat) +{ + stat->gr_poshit = poshit; + stat->gr_posmiss = posmiss; + stat->gr_neghit = neghit; + stat->gr_negmiss = negmiss; + stat->gr_size = modulo; + stat->gr_posttl = postimeout; + stat->gr_negttl = negtimeout; +} + +void +set_grp_modulo (unsigned long mod) +{ + modulo = mod; +} + +void +set_pos_grp_ttl (unsigned long ttl) +{ + postimeout = ttl; +} + +void +set_neg_grp_ttl (unsigned long ttl) +{ + negtimeout = ttl; +} + +int +cache_grpinit () +{ + pthread_attr_t attr; + pthread_t thread; + + grptbl = calloc (1, modulo * sizeof (grphash)); + if (grptbl == NULL) + return -1; + calloc (1, modulo * sizeof (grphash)); + if (gidtbl == NULL) + return -1; + negtbl = calloc (1, modulo * sizeof (neghash)); + if (negtbl == NULL) + return -1; + + pthread_attr_init (&attr); + pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); + + pthread_create (&thread, NULL, grptable_update, &attr); + pthread_create (&thread, NULL, negtable_update, &attr); + + pthread_attr_destroy (&attr); + + return 0; +} + +static struct group * +save_grp (struct group *src) +{ + struct group *dest; + unsigned long int l; + + dest = calloc (1, sizeof (struct group)); + dest->gr_name = strdup (src->gr_name); + dest->gr_passwd = strdup (src->gr_passwd); + dest->gr_gid = src->gr_gid; + + /* How many members does this group have? */ + l = 0; + while (src->gr_mem[l]) + ++l; + + dest->gr_mem = calloc (1, sizeof (char *) * (l+1)); + l = 0; + while (src->gr_mem[l]) + { + dest->gr_mem[l] = strdup (src->gr_mem[l]); + ++l; + } + + return dest; +} + +static void +free_grp (struct group *src) +{ + unsigned long int l; + + free (src->gr_name); + free (src->gr_passwd); + + l = 0; + while (src->gr_mem[l]) + { + free (src->gr_mem[l]); + ++l; + } + free (src->gr_mem); + free (src); +} + +static int +add_cache (struct group *grp) +{ + grphash *work; + unsigned long int hash = __nis_hash (grp->gr_name, + strlen (grp->gr_name)) % modulo; + + work = &grptbl[hash]; + + if (grptbl[hash].grp == NULL) + grptbl[hash].grp = save_grp (grp); + else + { + while (work->next != NULL) + work = work->next; + + work->next = calloc (1, sizeof (grphash)); + work->next->grp = save_grp (grp); + work = work->next; + } + + time (&work->create); + gidtbl[grp->gr_gid % modulo].grptr = work; + + return 0; +} + +static struct group * +cache_search_name (const char *name) +{ + grphash *work; + unsigned long int hash = __nis_hash (name, strlen(name)) % modulo; + + work = &grptbl[hash]; + + while (work->grp != NULL) + { + if (strcmp (work->grp->gr_name, name) == 0) + return work->grp; + if (work->next != NULL) + work = work->next; + else + return NULL; + } + return NULL; +} + +static struct group * +cache_search_gid (gid_t gid) +{ + gidhash *work; + + work = &gidtbl[gid % modulo]; + + while (work->grptr != NULL) + { + if (work->grptr->grp->gr_gid == gid) + return work->grptr->grp; + if (work->next != NULL) + work = work->next; + else + return NULL; + } + return NULL; +} + +static int +add_negcache (char *key) +{ + neghash *work; + unsigned long int hash = __nis_hash (key, strlen (key)) % modulo; + + work = &negtbl[hash]; + + if (negtbl[hash].key == NULL) + negtbl[hash].key = strdup (key); + else + { + while (work->next != NULL) + work = work->next; + + work->next = calloc (1, sizeof (neghash)); + work->next->key = strdup (key); + work = work->next; + } + + time (&work->create); + return 0; +} + +static int +cache_search_neg (const char *key) +{ + neghash *work; + unsigned long int hash = __nis_hash (key, strlen (key)) % modulo; + + work = &negtbl[hash]; + + while (work->key != NULL) + { + if (strcmp (work->key, key) == 0) + return 1; + if (work->next != NULL) + work = work->next; + else + return 0; + } + return 0; +} + +void * +cache_getgrnam (void *v_param) +{ + param_t *param = (param_t *)v_param; + struct group *grp, resultbuf; + + pthread_rwlock_rdlock (&grplock); + grp = cache_search_name (param->key); + + /* I don't like it to hold the read only lock longer, but it is + necessary to avoid to much malloc/free/strcpy. */ + + if (grp) + { + if (debug_flag) + dbg_log (_("Found \"%s\" in cache !"), param->key); + + ++poshit; + gr_send_answer (param->conn, grp); + close_socket (param->conn); + + pthread_rwlock_unlock (&grplock); + } + else + { + int buflen = 1024; + char *buffer = calloc (1, buflen); + int status; + + if (debug_flag) + dbg_log (_("Doesn't found \"%s\" in cache !"), param->key); + + pthread_rwlock_unlock (&grplock); + + pthread_rwlock_rdlock (&neglock); + status = cache_search_neg (param->key); + pthread_rwlock_unlock (&neglock); + + if (status == 0) + { + while (buffer != NULL + && (getgrnam_r (param->key, &resultbuf, buffer, buflen, &grp) + != 0) + && errno == ERANGE) + { + errno = 0; + buflen += 1024; + buffer = realloc (buffer, buflen); + } + + if (buffer != NULL && grp != NULL) + { + struct group *tmp; + + ++poshit; + pthread_rwlock_wrlock (&grplock); + /* While we are waiting on the lock, somebody else could + add this entry. */ + tmp = cache_search_name (param->key); + if (tmp == NULL) + add_cache (grp); + pthread_rwlock_unlock (&grplock); + } + else + { + pthread_rwlock_wrlock (&neglock); + add_negcache (param->key); + ++negmiss; + pthread_rwlock_unlock (&neglock); + } + } + else + ++neghit; + + gr_send_answer (param->conn, grp); + close_socket (param->conn); + if (buffer != NULL) + free (buffer); + } + free (param->key); + free (param); + return NULL; +} + +void * +cache_gr_disabled (void *v_param) +{ + param_t *param = (param_t *)v_param; + + gr_send_disabled (param->conn); + return NULL; +} + +void * +cache_getgrgid (void *v_param) +{ + param_t *param = (param_t *)v_param; + struct group *grp, resultbuf; + gid_t gid = strtol (param->key, NULL, 10); + + pthread_rwlock_rdlock (&grplock); + grp = cache_search_gid (gid); + + /* I don't like it to hold the read only lock longer, but it is + necessary to avoid to much malloc/free/strcpy. */ + + if (grp != NULL) + { + if (debug_flag) + dbg_log (_("Found \"%d\" in cache !\n"), gid); + + ++poshit; + gr_send_answer (param->conn, grp); + close_socket (param->conn); + + pthread_rwlock_unlock (&grplock); + } + else + { + int buflen = 1024; + char *buffer = malloc (buflen); + int status; + + if (debug_flag) + dbg_log (_("Doesn't found \"%d\" in cache !\n"), gid); + + pthread_rwlock_unlock (&grplock); + + pthread_rwlock_rdlock (&neglock); + status = cache_search_neg (param->key); + pthread_rwlock_unlock (&neglock); + + if (status == 0) + { + while (buffer != NULL + && (getgrgid_r (gid, &resultbuf, buffer, buflen, &grp) != 0) + && errno == ERANGE) + { + errno = 0; + buflen += 1024; + buffer = realloc (buffer, buflen); + } + + if (buffer != NULL && grp != NULL) + { + struct group *tmp; + + ++posmiss; + pthread_rwlock_wrlock (&grplock); + /* While we are waiting on the lock, somebody else could + add this entry. */ + tmp = cache_search_gid (gid); + if (tmp == NULL) + add_cache (grp); + pthread_rwlock_unlock (&grplock); + } + else + { + ++negmiss; + pthread_rwlock_wrlock (&neglock); + add_negcache (param->key); + pthread_rwlock_unlock (&neglock); + } + } + else + ++neghit; + + gr_send_answer (param->conn, grp); + close_socket (param->conn); + if (buffer != NULL) + free (buffer); + } + free (param->key); + free (param); + return NULL; +} + +void * +grptable_update (void *v) +{ + time_t now; + int i; + + sleep (20); + + while (!do_shutdown) + { + if (debug_flag > 2) + dbg_log (_("(grptable_update) Wait for write lock!")); + + pthread_rwlock_wrlock (&grplock); + + if (debug_flag > 2) + dbg_log (_("(grptable_update) Have write lock")); + + time (&now); + for (i = 0; i < modulo; ++i) + { + grphash *work = &grptbl[i]; + + while (work && work->grp) + { + if ((now - work->create) >= postimeout) + { + gidhash *uh = &gidtbl[work->grp->gr_gid % modulo]; + + if (debug_flag) + dbg_log (_("Give \"%s\" free"), work->grp->gr_name); + + while (uh && uh->grptr) + { + if (uh->grptr->grp->gr_gid == work->grp->gr_gid) + { + if (debug_flag > 3) + dbg_log (_("Give gid for \"%s\" free"), + work->grp->gr_name); + if (uh->next != NULL) + { + gidhash *tmp = uh->next; + uh->grptr = tmp->grptr; + uh->next = tmp->next; + free (tmp); + } + else + uh->grptr = NULL; + } + uh = uh->next; + } + + free_grp (work->grp); + if (work->next != NULL) + { + grphash *tmp = work->next; + work->create = tmp->create; + work->next = tmp->next; + work->grp = tmp->grp; + free (tmp); + } + else + work->grp = NULL; + } + work = work->next; + } + } + if (debug_flag > 2) + dbg_log (_("(pwdtable_update) Release wait lock\n")); + pthread_rwlock_unlock (&grplock); + sleep (20); + } + return NULL; +} + +void * +negtable_update (void *v) +{ + time_t now; + int i; + + sleep (30); + + while (!do_shutdown) + { + if (debug_flag > 2) + dbg_log (_("(negtable_update) Wait for write lock!")); + + pthread_rwlock_wrlock (&neglock); + + if (debug_flag > 2) + dbg_log (_("(negtable_update) Have write lock")); + + time (&now); + for (i = 0; i < modulo; ++i) + { + neghash *work = &negtbl[i]; + + while (work && work->key) + { + if ((now - work->create) >= negtimeout) + { + if (debug_flag) + dbg_log (_("Give \"%s\" free"), work->key); + + free (work->key); + + if (work->next != NULL) + { + neghash *tmp = work->next; + work->create = tmp->create; + work->next = tmp->next; + work->key = tmp->key; + free (tmp); + } + else + work->key = NULL; + } + work = work->next; + } + } + if (debug_flag > 2) + dbg_log (_("(negtable_update) Release wait lock")); + pthread_rwlock_unlock (&neglock); + sleep (10); + } + return NULL; +} diff --git a/nscd/nscd.c b/nscd/nscd.c new file mode 100644 index 00000000000..59d4a60e020 --- /dev/null +++ b/nscd/nscd.c @@ -0,0 +1,423 @@ +/* Copyright (c) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* nscd - Name Service Cache Daemon. Caches passwd and group. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dbg_log.h" +#include "nscd.h" + +/* Get libc version number. */ +#include + +#define PACKAGE _libc_intl_domainname + +/* Structure used by main() thread to keep track of the number of + active threads. Used to limit how many threads it will create + and under a shutdown condition to wait till all in-progress + requests have finished before "turning off the lights". */ + +typedef struct +{ + int num_active; + pthread_cond_t thread_exit_cv; + pthread_mutex_t mutex; +} thread_info_t; + +thread_info_t thread_info; + +int do_shutdown = 0; +int disabled_passwd = 0; +int disabled_group = 0; + +static void termination_handler (int signum); +static int check_pid (const char *file); +static int write_pid (const char *file); +static void usage (int status) __attribute__ ((noreturn)); +static void handle_requests (void); + +int +main (int argc, char **argv) +{ + int go_background = 1; + const char *conffile = _PATH_NSCDCONF; + + /* Set locale via LC_ALL. */ + setlocale (LC_ALL, ""); + /* Set the text message domain. */ + textdomain (PACKAGE); + + while (1) + { + int c; + int option_index = 0; + static struct option long_options[] = { + { "debug", no_argument, NULL, 'd' }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'V' }, + { "shutdown", no_argument, NULL, 'K' }, + {NULL, 0, NULL, '\0'} + }; + + c = getopt_long (argc, argv, "df:ghKV", long_options, &option_index); + if (c == (-1)) + break; + switch (c) + { + case 'd': + debug_flag = 1; + go_background = 0; + break; + case 'f': + conffile = optarg; + break; + case 'h': + usage (EXIT_SUCCESS); + break; + case 'K': + if (getuid () != 0) + { + printf (_("Only root is allowed to use this option!\n\n")); + usage (EXIT_FAILURE); + } + { + int sock = __nscd_open_socket (); + request_header req; + ssize_t nbytes; + + if (sock == -1) + exit (EXIT_FAILURE); + + req.version = NSCD_VERSION; + req.type = SHUTDOWN; + req.key_len = 0; + nbytes = write (sock, &req, sizeof (request_header)); + close (sock); + if (nbytes != req.key_len) + exit (EXIT_FAILURE); + else + exit (EXIT_SUCCESS); + } + case 'g': + print_stat (); + exit (EXIT_SUCCESS); + case 'V': + printf ("nscd (GNU %s) %s\n", PACKAGE, VERSION); + printf (_("\ +Copyright (C) %s Free Software Foundation, Inc.\n\ +This is free software; see the source for copying conditions. There is NO\n\ +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ +"), "1998"); + printf (_("Written by %s.\n"), "Thorsten Kukuk"); + exit (EXIT_SUCCESS); + default: + usage (EXIT_FAILURE); + } + } + + signal (SIGINT, termination_handler); + signal (SIGQUIT, termination_handler); + signal (SIGTERM, termination_handler); + + /* Check if we are already running. */ + if (check_pid (_PATH_NSCDPID)) + { + fputs (_("already running"), stderr); + exit (EXIT_FAILURE); + } + + /* Behave like a daemon. */ + if (go_background) + { + openlog ("nscd", LOG_CONS | LOG_ODELAY, LOG_DAEMON); + + if (daemon (0, 0) < 0) + { + fprintf (stderr, _("connot auto-background: %s\n"), + strerror (errno)); + exit (EXIT_FAILURE); + } + if (write_pid (_PATH_NSCDPID) < 0) + dbg_log ("%s: %s", _PATH_NSCDPID, strerror (errno)); + + /* Ignore job control signals */ + signal (SIGTTOU, SIG_IGN); + signal (SIGTTIN, SIG_IGN); + signal (SIGTSTP, SIG_IGN); + } + /* Cleanup files created by a previous `bind' */ + unlink (_PATH_NSCDSOCKET); + + nscd_parse_file (conffile); + + /* Create first sockets */ + init_sockets (); + /* Init databases */ + cache_pwdinit (); + cache_grpinit (); + /* Handle incoming requests */ + handle_requests (); + + return 0; +} + +/* Create a socket connected to a name. */ +int +__nscd_open_socket (void) +{ + struct sockaddr_un addr; + int sock; + + sock = socket (PF_UNIX, SOCK_STREAM, 0); + if (sock < 0) + return -1; + + addr.sun_family = AF_UNIX; + strcpy (addr.sun_path, _PATH_NSCDSOCKET); + if (connect (sock, (struct sockaddr *) &addr, sizeof (addr)) < 0) + { + close (sock); + return -1; + } + + return sock; +} + +/* Cleanup. */ +static void +termination_handler (int signum) +{ + close_sockets (); + + /* Clean up the files created by `bind'. */ + unlink (_PATH_NSCDSOCKET); + + /* Clean up pid file. */ + unlink (_PATH_NSCDPID); + + exit (EXIT_SUCCESS); +} + +/* Display usage information and exit. */ +static void +usage (int status) +{ + if (status != EXIT_SUCCESS) + fprintf (stderr, _("Try `%s --help' for more information.\n"), + program_invocation_name); + else + { + printf (_("\ +Usage: %s [OPTION]...\n\ + -d, --debug do not fork and display messages on the current tty\n\ + -h, --help display this help and exit\n\ + -V, --version output version information and exit\n\ + -f configuration-file read configuration data from the specified file.\n\ + -K, --shutdown shut the server down.\n\ + -g Prints configuration and statistics to stdout.\n"), + program_invocation_name); + fputs (_("\ +Report bugs using the `glibcbug' script to .\n"), + stdout); + } + exit (status); +} + +/* Returns 1 if the process in pid file FILE is running, 0 if not. */ +static int +check_pid (const char *file) +{ + FILE *fp; + + fp = fopen (file, "r"); + if (fp) + { + pid_t pid; + + fscanf (fp, "%d", &pid); + fclose (fp); + + if (kill (pid, 0) == 0) + return 1; + } + + return 0; +} + +/* Write the current process id to the file FILE. + Returns 0 if successful, -1 if not. */ +static int +write_pid (const char *file) +{ + FILE *fp; + + fp = fopen (file, "w"); + if (fp == NULL) + return -1; + + fprintf (fp, "%d\n", getpid ()); + if (ferror (fp)) + return -1; + + fclose (fp); + + return 0; +} + +/* Type of the lookup function for netname2user. */ +typedef int (*pwbyname_function) (const char *name, struct passwd *pw, + char *buffer, size_t buflen); + +/* Hanlde incoming requests. */ +static +void handle_requests (void) +{ + request_header req; + int conn; /* Handle on which connection (client) the request came from. */ + int done = 0; + char *key; + + while (!done) + { + key = NULL; + get_request (&conn, &req, &key); + if (debug_flag) + dbg_log (_("handle_requests: request received (Version = %d)"), + req.version); + switch (req.type) + { + case GETPWBYNAME: + { + param_t *param = malloc (sizeof (param_t)); + pthread_t thread; + + if (debug_flag) + dbg_log ("\tGETPWBYNAME (%s)", key); + param->key = key; + param->conn = conn; + if (disabled_passwd) + pthread_create (&thread, NULL, cache_pw_disabled, (void *)param); + else + pthread_create (&thread, NULL, cache_getpwnam, (void *)param); + pthread_detach (thread); + } + break; + case GETPWBYUID: + { + param_t *param = malloc (sizeof (param_t)); + pthread_t thread; + + if (debug_flag) + dbg_log ("\tGETPWBYUID (%s)", key); + param->key = key; + param->conn = conn; + if (disabled_passwd) + pthread_create (&thread, NULL, cache_pw_disabled, (void *)param); + else + pthread_create (&thread, NULL, cache_getpwuid, (void *)param); + pthread_detach (thread); + } + break; + case GETGRBYNAME: + { + param_t *param = malloc (sizeof (param_t)); + pthread_t thread; + + if (debug_flag) + dbg_log ("\tGETGRBYNAME (%s)", key); + param->key = key; + param->conn = conn; + if (disabled_group) + pthread_create (&thread, NULL, cache_gr_disabled, (void *)param); + else + pthread_create (&thread, NULL, cache_getgrnam, (void *)param); + pthread_detach (thread); + } + break; + case GETGRBYGID: + { + param_t *param = malloc (sizeof (param_t)); + pthread_t thread; + + if (debug_flag) + dbg_log ("\tGETGRBYGID (%s)", key); + param->key = key; + param->conn = conn; + if (disabled_group) + pthread_create (&thread, NULL, cache_gr_disabled, (void *)param); + else + pthread_create (&thread, NULL, cache_getgrgid, (void *)param); + pthread_detach (thread); + } + break; + case GETHOSTBYNAME: + /* Not yetimplemented. */ + close_socket (conn); + break; + case GETHOSTBYADDR: + /* Not yet implemented. */ + close_socket (conn); + break; + case SHUTDOWN: + do_shutdown = 1; + close_socket (0); + close_socket (conn); + /* Clean up the files created by `bind'. */ + unlink (_PATH_NSCDSOCKET); + /* Clean up pid file. */ + unlink (_PATH_NSCDPID); + done = 1; + break; + case GETSTAT: + { + stat_response_header resp; + + if (debug_flag) + dbg_log ("\tGETSTAT"); + + get_pw_stat (&resp); + get_gr_stat (&resp); + resp.debug_level = debug_flag; + resp.pw_enabled = !disabled_passwd; + resp.gr_enabled = !disabled_group; + + stat_send (conn, &resp); + + close_socket (conn); + } + break; + default: + dbg_log (_("Unknown request (%d)"), req.type); + break; + } + } +} diff --git a/nscd/nscd.conf b/nscd/nscd.conf new file mode 100644 index 00000000000..5d8c7f31ac4 --- /dev/null +++ b/nscd/nscd.conf @@ -0,0 +1,30 @@ +# +# /etc/nscd.conf +# +# An example Name Service Cache config file. This file is needed by nscd. +# +# Legal entries are: +# +# logfile +# enable-cache +# debug-level +# positive-time-to-live