diff --git a/ChangeLog b/ChangeLog index cc59035c5b..26deea6b3d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,126 @@ +1997-09-16 02:14 Ulrich Drepper + + Implementation of Hesiod NSS module by Mark Kettenis. + * hesiod/Makefile: New file. + * hesiod/hesiod.c: New file. + * hesiod/hesiod.h: New file. + * hesiod/hesiod_p.h: New file. + * hesiod/libnss_hesiod.map: New file. + * hesiod/nss_hesiod/hesiod-grp.c: New file. + * hesiod/nss_hesiod/hesiod-pwd.c: New file. + * hesiod/nss_hesiod/hesiod-service.c: New file. + * sysdeps/unix/inet/Subdirs: Add hesiod. + + * shlib-versions: Add version number for libnss_hesiod. + + * libio/iolibio.h: Remove definition of _IO_* macros. + * libio/fileops.c: Define close, fstat, lseek, read, and write as + macros to use __ protected versions. Use those functions instead + of _IO_* functions. + * libio/iopopen.c: Define _IO_close to close. + + * manual/math.texi: Explain the use of the optimizing inline + functions. + Describe rand_r function and tell about SysV RNGs in introduction. + + * resolv/res_send.c (res_send): Use socklen_t type for `fromlen' + variable. + + * string/Makefile (tests): Add noinl-tester. + * string/noinl-tester.c: New file. + * string/tester.c: Add more stpcpy tests for constant arguments for + all short lengths. + + * string/string.h: Always declare __bzero. + Describe __NO_STRING_INLINES. + Always include . + * string/bits/string2.h: Add warning about direct use. + Change __strcpy_small and __stpcpy_small implementation to use + macros and provide alternative for platforms which cannot do + unaligned stores. + * sysdeps/i386/bits/string.h: Don't define anything is + __NO_STRING_INLINES is defined. + * sysdeps/i386/i486/bits/string.h: Change __strcpy_small and + __stpcpy_small implementation to use macros and provide + alternative for platforms which cannot do unaligned stores. + * sysdeps/alpha/bzero.S: Define bzero as weak alias of __bzero. + * sysdeps/generic/bzero.c: Likewise. + * sysdeps/i386/bzero.c: Likewise. + * sysdeps/i386/i586/bzero.S: Likewise. + * sysdeps/vax/bzero.s: Likewise. + + * sysdeps/generic/bits/select.h: Don't use ugly casts to access array. + * sysdeps/i386/bits/select.h: Likewise. + + * sysdeps/i386/fpu/bits/mathinline.c (__finite): Relax register + constraints a bit. + Don't define and test for _BITS_MATHINLINE_H. Emit warning if used + directly and not through math.h. + + * sysdeps/i386/i486/atomicity.h: Change return type of compare_and_swap + to char to get better code. Fix typo. + * sysdeps/stub/atomicity.h: Fix typo. + +1997-09-14 Andreas Schwab + + * sysdeps/generic/stpcpy.c: #undef stpcpy and __stpcpy. + +1997-09-14 Andreas Schwab + + * string/bits/string2.h: Add prototypes to avoid warning. + +1997-09-14 Andreas Schwab + + * string/bits/string2.h (strsep): Fix handling of empty REJECT. + (__strsep_1c): Handle NULL and empty string. + (__strsep_g): Likewise. + +1997-09-13 Andreas Schwab + + * catgets/Makefile (extra-objs): Set this instead of generated. + + * md5-crypt/Makefile (extra-objs): Add all object file variants of + onlymd5-entry. + +1997-09-12 Andreas Schwab + + * sysdeps/generic/sysd-stdio.c (__stdio_read): Fix typo in last + change. + +1997-09-12 Andreas Schwab + + * sysdeps/m68k/m68020/atomicity.h: New file. + +1997-09-15 05:11 Ulrich Drepper + + * posix/Makefile (distribute): Add globtest.c and globtest.sh. + Compile and run globtest if not cross-compiling. + * posix/globtest.c: New file. + * posix/globtest.sh: New file. + * posix/glob.c: Pretty print preprocessor stuff. + (glob_in_dir): If PATTERN is not really a pattern still check + whether it is a real file in the current directory and return + error if not. + Reported by Eugene Mamchits . + + * libio/fileops.c (_IO_file_sync): Acquire lock before doing the work. + * libio/ioseekoff.c (_IO_seekoff): Likewise. + * libio/ioseekpos.c (_IO_seekpos): Likewise. + +1997-09-13 18:06 Ulrich Drepper + + * configure.in: Prevent configuration for unsupported platforms. + +1997-09-13 04:07 Ulrich Drepper + + * elf/rtld.c (dl_main): Make sure we always have a file argument by + testing for < 2 arguments after recognizing the options. + +1997-09-12 11:47 Fila Kolodny + + * string/bits/string2.h (__strsep_1c): Cast out const from __retval. + (__strsep_g): Likewise. + 1997-09-11 17:32 Ulrich Drepper * sysdeps/unix/sysv/linux/sparc/bits/fcntl.h: Define O_ASYNC. diff --git a/bits/select.h b/bits/select.h index 7803335499..8487e21bb3 100644 --- a/bits/select.h +++ b/bits/select.h @@ -21,15 +21,14 @@ #endif -/* This line MUST be split! Otherwise m4 will not change it. - - We don't use `memset' because this would require a prototype and +/* We don't use `memset' because this would require a prototype and the array isn't too big. */ #define __FD_ZERO(set) \ do { \ unsigned int __i; \ + __fd_mask *__arr = (set); \ for (__i = 0; __i < sizeof (__fd_set) / sizeof (__fd_mask); ++__i) \ - ((__fd_mask *) set)[__i] = '\0'; \ + __arr->fds_bits[__i] = '\0'; \ } while (0) #define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d)) #define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d)) diff --git a/catgets/Makefile b/catgets/Makefile index 725d826249..0631599f18 100644 --- a/catgets/Makefile +++ b/catgets/Makefile @@ -26,11 +26,10 @@ distribute = catgetsinfo.h config.h routines = catgets open_catalog others = gencat install-bin = gencat +extra-objs = $(gencat-modules:=.o) gencat-modules = xmalloc -generated += xmalloc.o - # To find xmalloc.c vpath %.c ../locale/programs diff --git a/configure b/configure index c6042fc9a7..958e588dcc 100755 --- a/configure +++ b/configure @@ -785,6 +785,24 @@ gnu*) ;; esac +### +### I put this here to prevent those annoying emails from people who cannot +### read and try to compile glibc on unsupported platforms. --drepper +### +case "$host_os" in +linux* | gnu*) + ;; +*) + echo "*** The GNU C library is currently not available for this platform." + echo "*** So far nobody cared to port it and if there is no volunteer it" + echo "*** might never happen. So, if you have interest to see glibc on" + echo "*** this platform visit" + echo "*** http://www.gnu.ai.mit.edu/software/libc/porting.html" + echo "*** and join the group of porters" + exit 1 + ;; +esac + # We keep the original values in `$config_*' and never modify them, so we # can write them unchanged into config.make. Everything else uses # $machine, $vendor, and $os, and changes them whenever convenient. @@ -839,7 +857,7 @@ esac # This can take a while to compute. sysdep_dir=$srcdir/sysdeps echo $ac_n "checking sysdep dirs""... $ac_c" 1>&6 -echo "configure:843: checking sysdep dirs" >&5 +echo "configure:861: 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'`" @@ -1040,7 +1058,7 @@ echo "$ac_t""sysdeps/generic sysdeps/stub" 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:1044: checking for a BSD compatible install" >&5 +echo "configure:1062: 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 @@ -1094,7 +1112,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:1098: checking whether ln -s works" >&5 +echo "configure:1116: 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 @@ -1119,7 +1137,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:1123: checking for $ac_word" >&5 +echo "configure:1141: 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 @@ -1152,7 +1170,7 @@ test -n "$MSGFMT" || MSGFMT=":" # 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:1156: checking for $ac_word" >&5 +echo "configure:1174: 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 @@ -1181,7 +1199,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:1185: checking for $ac_word" >&5 +echo "configure:1203: 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 @@ -1229,7 +1247,7 @@ fi fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:1233: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 +echo "configure:1251: 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. @@ -1239,11 +1257,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:1265: \"$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 @@ -1266,13 +1284,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:1270: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "configure:1288: 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:1276: checking whether we are using GNU C" >&5 +echo "configure:1294: 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 @@ -1281,7 +1299,7 @@ else yes; #endif EOF -if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1285: \"$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:1303: \"$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 @@ -1298,7 +1316,7 @@ if test $ac_cv_prog_gcc = yes; then yes; #endif EOF - if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1302: \"$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:1320: \"$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 @@ -1310,7 +1328,7 @@ else fi echo $ac_n "checking build system type""... $ac_c" 1>&6 -echo "configure:1314: checking build system type" >&5 +echo "configure:1332: checking build system type" >&5 build_alias=$build case "$build_alias" in @@ -1333,7 +1351,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:1337: checking for $ac_word" >&5 +echo "configure:1355: 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 @@ -1364,7 +1382,7 @@ done fi echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 -echo "configure:1368: checking how to run the C preprocessor" >&5 +echo "configure:1386: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= @@ -1379,13 +1397,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:1389: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1407: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then : @@ -1396,13 +1414,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:1406: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1424: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then : @@ -1433,7 +1451,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:1437: checking for $ac_word" >&5 +echo "configure:1455: 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 @@ -1464,7 +1482,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:1468: checking for $ac_word" >&5 +echo "configure:1486: 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 @@ -1495,7 +1513,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:1499: checking for $ac_word" >&5 +echo "configure:1517: 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 @@ -1530,7 +1548,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:1534: checking for $ac_word" >&5 +echo "configure:1552: 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 @@ -1571,7 +1589,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:1575: checking for $ac_word" >&5 +echo "configure:1593: 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 @@ -1613,7 +1631,7 @@ fi echo $ac_n "checking for signed size_t type""... $ac_c" 1>&6 -echo "configure:1617: checking for signed size_t type" >&5 +echo "configure:1635: 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 @@ -1637,12 +1655,12 @@ EOF fi echo $ac_n "checking for libc-friendly stddef.h""... $ac_c" 1>&6 -echo "configure:1641: checking for libc-friendly stddef.h" >&5 +echo "configure:1659: 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:1679: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* libc_cv_friendly_stddef=yes else @@ -1676,7 +1694,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:1680: checking whether we need to use -P to assemble .S files" >&5 +echo "configure:1698: 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 @@ -1699,7 +1717,7 @@ asm-CPPFLAGS = -P # The assembler can't grok cpp's # line directives." fi echo $ac_n "checking for assembler global-symbol directive""... $ac_c" 1>&6 -echo "configure:1703: checking for assembler global-symbol directive" >&5 +echo "configure:1721: 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 @@ -1729,7 +1747,7 @@ EOF fi echo $ac_n "checking for .set assembler directive""... $ac_c" 1>&6 -echo "configure:1733: checking for .set assembler directive" >&5 +echo "configure:1751: 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 @@ -1763,7 +1781,7 @@ EOF fi echo $ac_n "checking for .symver assembler directive""... $ac_c" 1>&6 -echo "configure:1767: checking for .symver assembler directive" >&5 +echo "configure:1785: 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 @@ -1782,7 +1800,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:1786: checking for ld --version-script" >&5 +echo "configure:1804: 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 @@ -1801,7 +1819,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:1805: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; + 1>&5'; { (eval echo configure:1823: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then libc_cv_ld_version_script_option=yes else @@ -1831,7 +1849,7 @@ fi if test $elf = yes; then echo $ac_n "checking for .previous assembler directive""... $ac_c" 1>&6 -echo "configure:1835: checking for .previous assembler directive" >&5 +echo "configure:1853: 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 @@ -1839,7 +1857,7 @@ else .section foo_section .previous EOF - if { ac_try='${CC-cc} -c $CFLAGS conftest.s 1>&5'; { (eval echo configure:1843: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then + if { ac_try='${CC-cc} -c $CFLAGS conftest.s 1>&5'; { (eval echo configure:1861: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then libc_cv_asm_previous_directive=yes else libc_cv_asm_previous_directive=no @@ -1855,7 +1873,7 @@ EOF else echo $ac_n "checking for .popsection assembler directive""... $ac_c" 1>&6 -echo "configure:1859: checking for .popsection assembler directive" >&5 +echo "configure:1877: 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 @@ -1863,7 +1881,7 @@ else .pushsection foo_section .popsection EOF - if { ac_try='${CC-cc} -c $CFLAGS conftest.s 1>&5'; { (eval echo configure:1867: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then + if { ac_try='${CC-cc} -c $CFLAGS conftest.s 1>&5'; { (eval echo configure:1885: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then libc_cv_asm_popsection_directive=yes else libc_cv_asm_popsection_directive=no @@ -1883,12 +1901,12 @@ fi if test $elf != yes; then echo $ac_n "checking for .init and .fini sections""... $ac_c" 1>&6 -echo "configure:1887: checking for .init and .fini sections" >&5 +echo "configure:1905: 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:1919: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* libc_cv_have_initfini=yes else @@ -1925,19 +1943,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:1929: checking for _ prefix on C symbol names" >&5 +echo "configure:1947: 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:1959: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* libc_cv_asm_underscores=yes else @@ -1952,17 +1970,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:1956: checking for _ prefix on C symbol names" >&5 +echo "configure:1974: 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:1984: \"$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 @@ -1995,7 +2013,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:1999: checking for assembler .weak directive" >&5 +echo "configure:2017: 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 @@ -2018,7 +2036,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:2022: checking for assembler .weakext directive" >&5 +echo "configure:2040: 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 @@ -2055,7 +2073,7 @@ EOF fi echo $ac_n "checking for ld --no-whole-archive""... $ac_c" 1>&6 -echo "configure:2059: checking for ld --no-whole-archive" >&5 +echo "configure:2077: 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 @@ -2066,7 +2084,7 @@ __throw () {} EOF if { ac_try='${CC-cc} $CFLAGS -nostdlib -nostartfiles -Wl,--no-whole-archive - -o conftest conftest.c 1>&5'; { (eval echo configure:2070: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then + -o conftest conftest.c 1>&5'; { (eval echo configure:2088: \"$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 @@ -2077,7 +2095,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:2081: checking for gcc -fno-exceptions" >&5 +echo "configure:2099: 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 @@ -2088,7 +2106,7 @@ __throw () {} EOF if { ac_try='${CC-cc} $CFLAGS -nostdlib -nostartfiles -fno-exceptions - -o conftest conftest.c 1>&5'; { (eval echo configure:2092: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then + -o conftest conftest.c 1>&5'; { (eval echo configure:2110: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then libc_cv_gcc_no_exceptions=yes else libc_cv_gcc_no_exceptions=no @@ -2140,7 +2158,7 @@ if test "$uname" = "sysdeps/generic"; then fi echo $ac_n "checking OS release for uname""... $ac_c" 1>&6 -echo "configure:2144: checking OS release for uname" >&5 +echo "configure:2162: 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 @@ -2162,7 +2180,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:2166: checking OS version for uname" >&5 +echo "configure:2184: 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 @@ -2184,7 +2202,7 @@ else fi echo $ac_n "checking stdio selection""... $ac_c" 1>&6 -echo "configure:2188: checking stdio selection" >&5 +echo "configure:2206: checking stdio selection" >&5 case $stdio in libio) cat >> confdefs.h <<\EOF @@ -2196,7 +2214,7 @@ esac echo "$ac_t""$stdio" 1>&6 echo $ac_n "checking ldap selection""... $ac_c" 1>&6 -echo "configure:2200: checking ldap selection" >&5 +echo "configure:2218: checking ldap selection" >&5 case $add_ons in *ldap*) diff --git a/configure.in b/configure.in index 9f2c984b26..340e86774a 100644 --- a/configure.in +++ b/configure.in @@ -116,6 +116,24 @@ gnu*) ;; esac +### +### I put this here to prevent those annoying emails from people who cannot +### read and try to compile glibc on unsupported platforms. --drepper +### +case "$host_os" in +linux* | gnu*) + ;; +*) + echo "*** The GNU C library is currently not available for this platform." + echo "*** So far nobody cared to port it and if there is no volunteer it" + echo "*** might never happen. So, if you have interest to see glibc on" + echo "*** this platform visit" + echo "*** http://www.gnu.ai.mit.edu/software/libc/porting.html" + echo "*** and join the group of porters" + exit 1 + ;; +esac + # We keep the original values in `$config_*' and never modify them, so we # can write them unchanged into config.make. Everything else uses # $machine, $vendor, and $os, and changes them whenever convenient. diff --git a/elf/rtld.c b/elf/rtld.c index 60a102a85c..3e21f1a95a 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -321,21 +321,6 @@ dl_main (const ElfW(Phdr) *phdr, pay attention to its PT_INTERP command (we are the interpreter ourselves). This is an easy way to test a new ld.so before installing it. */ - if (_dl_argc < 2) - _dl_sysdep_fatal ("\ -Usage: ld.so [--list|--verify] EXECUTABLE-FILE [ARGS-FOR-PROGRAM...]\n\ -You have invoked `ld.so', the helper program for shared library executables.\n\ -This program usually lives in the file `/lib/ld.so', and special directives\n\ -in executable files using ELF shared libraries tell the system's program\n\ -loader to load the helper program from this file. This helper program loads\n\ -the shared libraries needed by the program executable, prepares the program\n\ -to run, and runs it. You may invoke this helper program directly from the\n\ -command line to load and run an ELF executable file; this is like executing\n\ -that file itself, but always uses this helper program from the file you\n\ -specified, instead of the helper program file specified in the executable\n\ -file you run. This is mostly of use for maintainers to test new versions\n\ -of this helper program; chances are you did not intend to run this program.\n", - NULL); /* Note the place where the dynamic linker actually came from. */ _dl_rtld_map.l_name = _dl_argv[0]; @@ -361,6 +346,24 @@ of this helper program; chances are you did not intend to run this program.\n", else break; + /* If we have no further argument the program was called incorrectly. + Grant the user some education. */ + if (_dl_argc < 2) + _dl_sysdep_fatal ("\ +Usage: ld.so [--list|--verify] EXECUTABLE-FILE [ARGS-FOR-PROGRAM...]\n\ +You have invoked `ld.so', the helper program for shared library executables.\n\ +This program usually lives in the file `/lib/ld.so', and special directives\n\ +in executable files using ELF shared libraries tell the system's program\n\ +loader to load the helper program from this file. This helper program loads\n\ +the shared libraries needed by the program executable, prepares the program\n\ +to run, and runs it. You may invoke this helper program directly from the\n\ +command line to load and run an ELF executable file; this is like executing\n\ +that file itself, but always uses this helper program from the file you\n\ +specified, instead of the helper program file specified in the executable\n\ +file you run. This is mostly of use for maintainers to test new versions\n\ +of this helper program; chances are you did not intend to run this program.\n", + NULL); + ++_dl_skip_args; --_dl_argc; ++_dl_argv; diff --git a/hesiod/Makefile b/hesiod/Makefile new file mode 100644 index 0000000000..8d0363b50d --- /dev/null +++ b/hesiod/Makefile @@ -0,0 +1,49 @@ +# Copyright (C) 1997 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 hesiod portion of the library. +# +subdir := hesiod + +distribute := hesiod.h hesiod_p.h + +extra-libs := libnss_hesiod +extra-libs-others = $(extra-libs) + +subdir-dirs = nss_hesiod +vpath %.c nss_hesiod + +libnss_hesiod-routines := hesiod hesiod-grp hesiod-pwd hesiod-service +libnss_hesiod-map := libnss_hesiod.map +ifneq ($(build-static-nss),yes) +libnss_hesiod-inhibit-o = $(filter-out .os,$(object-suffixes)) +endif + +include ../Rules + +CFLAGS-hesiod.c = -DSYSCONFDIR='"$(sysconfdir)"' + +# Depend on libc.so so a DT_NEEDED is generated in the shared objects. +# This ensures they will load libc.so for needed symbols if loaded by +# a statically-linked program that hasn't already loaded it. +# The Hesiod NSS modules also needs the resolver and some help from +# the file service. +$(objpfx)libnss_hesiod.so: $(common-objpfx)resolv/libresolv.so \ + $(common-objpfx)nss/libnss_files.so \ + $(common-objpfx)libc.so diff --git a/hesiod/hesiod.c b/hesiod/hesiod.c new file mode 100644 index 0000000000..8e95dfb393 --- /dev/null +++ b/hesiod/hesiod.c @@ -0,0 +1,470 @@ +/* Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* Copyright 1996 by the Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" + * without express or implied warranty. + */ + +/* This file is part of the hesiod library. It implements the core + * portion of the hesiod resolver. + * + * This file is loosely based on an interim version of hesiod.c from + * the BIND IRS library, which was in turn based on an earlier version + * of this file. Extensive changes have been made on each step of the + * path. + * + * This implementation is not truly thread-safe at the moment because + * it uses res_send() and accesses _res. + */ + +static const char rcsid[] = "$Id$"; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hesiod.h" +#include "hesiod_p.h" + +/* A few operating systems don't define these. */ +#ifndef C_HS +#define C_HS 4 +#endif +#ifndef T_TXT +#define T_TXT 16 +#endif + +static int read_config_file(struct hesiod_p *ctx, const char *filename); +static char **get_txt_records(struct hesiod_p *ctx, int class, + const char *name); +static int cistrcmp(const char *s1, const char *s2); + +/* This function is called to initialize a hesiod_p. */ +int hesiod_init(void **context) +{ + struct hesiod_p *ctx; + const char *p, *configname; + + ctx = malloc(sizeof(struct hesiod_p)); + if (ctx) + { + *context = ctx; + configname = __secure_getenv("HESIOD_CONFIG"); + if (!configname) + configname = SYSCONFDIR "/hesiod.conf"; + if (read_config_file(ctx, configname) >= 0) + { + /* The default rhs can be overridden by an environment variable. */ + p = __secure_getenv("HES_DOMAIN"); + if (p) + { + if (ctx->rhs) + free(ctx->rhs); + ctx->rhs = malloc(strlen(p) + 2); + if (ctx->rhs) + { + *ctx->rhs = '.'; + strcpy(ctx->rhs + 1, (*p == '.') ? p + 1 : p); + return 0; + } + else + __set_errno (ENOMEM); + } + else + return 0; + } + } + else + __set_errno (ENOMEM); + + if (ctx->lhs) + free(ctx->lhs); + if (ctx->rhs) + free(ctx->rhs); + if (ctx) + free(ctx); + return -1; +} + +/* This function deallocates the hesiod_p. */ +void hesiod_end(void *context) +{ + struct hesiod_p *ctx = (struct hesiod_p *) context; + + free(ctx->rhs); + if (ctx->lhs) + free(ctx->lhs); + free(ctx); +} + +/* This function takes a hesiod (name, type) and returns a DNS + * name which is to be resolved. + */ +char *hesiod_to_bind(void *context, const char *name, const char *type) +{ + struct hesiod_p *ctx = (struct hesiod_p *) context; + char bindname[MAXDNAME], *p, *ret, **rhs_list = NULL; + const char *rhs; + int len; + + strcpy(bindname, name); + + /* Find the right right hand side to use, possibly truncating bindname. */ + p = strchr(bindname, '@'); + if (p) + { + *p++ = 0; + if (strchr(p, '.')) + rhs = name + (p - bindname); + else + { + rhs_list = hesiod_resolve(context, p, "rhs-extension"); + if (rhs_list) + rhs = *rhs_list; + else + { + __set_errno (ENOENT); + return NULL; + } + } + } else + rhs = ctx->rhs; + + /* See if we have enough room. */ + len = strlen(bindname) + 1 + strlen(type); + if (ctx->lhs) + len += strlen(ctx->lhs) + ((ctx->lhs[0] != '.') ? 1 : 0); + len += strlen(rhs) + ((rhs[0] != '.') ? 1 : 0); + if (len > sizeof(bindname) - 1) + { + if (rhs_list) + hesiod_free_list(context, rhs_list); + __set_errno (EMSGSIZE); + return NULL; + } + + /* Put together the rest of the domain. */ + strcat(bindname, "."); + strcat(bindname, type); + if (ctx->lhs) + { + if (ctx->lhs[0] != '.') + strcat(bindname, "."); + strcat(bindname, ctx->lhs); + } + if (rhs[0] != '.') + strcat(bindname, "."); + strcat(bindname, rhs); + + /* rhs_list is no longer needed, since we're done with rhs. */ + if (rhs_list) + hesiod_free_list(context, rhs_list); + + /* Make a copy of the result and return it to the caller. */ + ret = malloc(strlen(bindname) + 1); + if (!ret) + { + __set_errno (ENOMEM); + return NULL; + } + strcpy(ret, bindname); + return ret; +} + +/* This is the core function. Given a hesiod name and type, it + * returns an array of strings returned by the resolver. + */ +char **hesiod_resolve(void *context, const char *name, const char *type) +{ + struct hesiod_p *ctx = (struct hesiod_p *) context; + char *bindname, **retvec; + + bindname = hesiod_to_bind(context, name, type); + if (!bindname) + return NULL; + + retvec = get_txt_records(ctx, ctx->classes[0], bindname); + if (retvec == NULL && errno == ENOENT && ctx->classes[1]) + retvec = get_txt_records(ctx, ctx->classes[1], bindname); + + free(bindname); + return retvec; +} + +void hesiod_free_list(void *context, char **list) +{ + char **p; + + for (p = list; *p; p++) + free(*p); + free(list); +} + +/* This function parses the /etc/hesiod.conf file. Returns 0 on success, + * -1 on failure. On failure, it might leave values in ctx->lhs or + * ctx->rhs which need to be freed by the caller. */ +static int read_config_file(struct hesiod_p *ctx, const char *filename) +{ + char *key, *data, *p, **which; + char buf[MAXDNAME + 7]; + int n; + FILE *fp; + + /* Set default query classes. */ + ctx->classes[0] = C_IN; + ctx->classes[1] = C_HS; + + /* Try to open the configuration file. */ + fp = fopen(filename, "r"); + if (!fp) + { + /* Use compiled in default domain names. */ + ctx->lhs = malloc(strlen(DEF_LHS) + 1); + ctx->rhs = malloc(strlen(DEF_RHS) + 1); + if (ctx->lhs && ctx->rhs) + { + strcpy(ctx->lhs, DEF_LHS); + strcpy(ctx->rhs, DEF_RHS); + return 0; + } + else + { + __set_errno (ENOMEM); + return -1; + } + } + + ctx->lhs = NULL; + ctx->rhs = NULL; + while (fgets(buf, sizeof(buf), fp) != NULL) + { + p = buf; + if (*p == '#' || *p == '\n' || *p == '\r') + continue; + while(*p == ' ' || *p == '\t') + p++; + key = p; + while(*p != ' ' && *p != '\t' && *p != '=') + p++; + *p++ = 0; + + while(isspace(*p) || *p == '=') + p++; + data = p; + while(!isspace(*p)) + p++; + *p = 0; + + if (cistrcmp(key, "lhs") == 0 || cistrcmp(key, "rhs") == 0) + { + which = (strcmp(key, "lhs") == 0) ? &ctx->lhs : &ctx->rhs; + *which = malloc(strlen(data) + 1); + if (!*which) + { + __set_errno (ENOMEM); + return -1; + } + strcpy(*which, data); + } + else if (cistrcmp(key, "classes") == 0) + { + n = 0; + while (*data && n < 2) + { + p = data; + while (*p && *p != ',') + p++; + if (*p) + *p++ = 0; + if (cistrcmp(data, "IN") == 0) + ctx->classes[n++] = C_IN; + else if (cistrcmp(data, "HS") == 0) + ctx->classes[n++] = C_HS; + data = p; + } + while (n < 2) + ctx->classes[n++] = 0; + } + } + fclose(fp); + + if (!ctx->rhs || ctx->classes[0] == 0 || ctx->classes[0] == ctx->classes[1]) + { + __set_errno (ENOEXEC); + return -1; + } + + return 0; +} + +/* Given a DNS class and a DNS name, do a lookup for TXT records, and + * return a list of them. + */ +static char **get_txt_records(struct hesiod_p *ctx, int qclass, + const char *name) +{ + HEADER *hp; + unsigned char qbuf[PACKETSZ], abuf[MAX_HESRESP], *p, *eom, *eor; + char *dst, **list; + int ancount, qdcount, i, j, n, skip, type, class, len; + + /* Make sure the resolver is initialized. */ + if ((_res.options & RES_INIT) == 0 && res_init() == -1) + return NULL; + + /* Construct the query. */ + n = res_mkquery(QUERY, name, qclass, T_TXT, NULL, 0, + NULL, qbuf, PACKETSZ); + if (n < 0) + return NULL; + + /* Send the query. */ + n = res_send(qbuf, n, abuf, MAX_HESRESP); + if (n < 0) + { + __set_errno (ECONNREFUSED); + return NULL; + } + + /* Parse the header of the result. */ + hp = (HEADER *) abuf; + ancount = ntohs(hp->ancount); + qdcount = ntohs(hp->qdcount); + p = abuf + sizeof(HEADER); + eom = abuf + n; + + /* Skip questions, trying to get to the answer section which follows. */ + for (i = 0; i < qdcount; i++) + { + skip = dn_skipname(p, eom); + if (skip < 0 || p + skip + QFIXEDSZ > eom) + { + __set_errno (EMSGSIZE); + return NULL; + } + p += skip + QFIXEDSZ; + } + + /* Allocate space for the text record answers. */ + list = malloc((ancount + 1) * sizeof(char *)); + if (!list) + { + __set_errno (ENOMEM); + return NULL; + } + + /* Parse the answers. */ + j = 0; + for (i = 0; i < ancount; i++) + { + /* Parse the header of this answer. */ + skip = dn_skipname(p, eom); + if (skip < 0 || p + skip + 10 > eom) + break; + type = p[skip + 0] << 8 | p[skip + 1]; + class = p[skip + 2] << 8 | p[skip + 3]; + len = p[skip + 8] << 8 | p[skip + 9]; + p += skip + 10; + if (p + len > eom) + { + __set_errno (EMSGSIZE); + break; + } + + /* Skip entries of the wrong class and type. */ + if (class != qclass || type != T_TXT) + { + p += len; + continue; + } + + /* Allocate space for this answer. */ + list[j] = malloc(len); + if (!list[j]) + { + __set_errno (ENOMEM); + break; + } + dst = list[j++]; + + /* Copy answer data into the allocated area. */ + eor = p + len; + while (p < eor) + { + n = (unsigned char) *p++; + if (p + n > eor) + { + __set_errno (EMSGSIZE); + break; + } + memcpy(dst, p, n); + p += n; + dst += n; + } + if (p < eor) + { + __set_errno (EMSGSIZE); + break; + } + *dst = 0; + } + + /* If we didn't terminate the loop normally, something went wrong. */ + if (i < ancount) + { + for (i = 0; i < j; i++) + free(list[i]); + free(list); + return NULL; + } + + if (j == 0) + { + __set_errno (ENOENT); + free(list); + return NULL; + } + + list[j] = NULL; + return list; +} + +static int cistrcmp(const char *s1, const char *s2) +{ + while (*s1 && tolower(*s1) == tolower(*s2)) + { + s1++; + s2++; + } + return tolower(*s1) - tolower(*s2); +} diff --git a/hesiod/hesiod.h b/hesiod/hesiod.h new file mode 100644 index 0000000000..9c3d323811 --- /dev/null +++ b/hesiod/hesiod.h @@ -0,0 +1,73 @@ +/* $Id$ */ + +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef HESIOD__INCLUDED +#define HESIOD__INCLUDED + +#include +#include +#include + +/* Application-visible define to signal that we have the new interfaces. */ +#define HESIOD_INTERFACES + +struct hesiod_postoffice { + char *hesiod_po_type; + char *hesiod_po_host; + char *hesiod_po_name; +}; + +int hesiod_init(void **context); +void hesiod_end(void *context); +char *hesiod_to_bind(void *context, const char *name, const char *type); +char **hesiod_resolve(void *context, const char *name, const char *type); +void hesiod_free_list(void *context, char **list); +struct passwd *hesiod_getpwnam(void *context, const char *name); +struct passwd *hesiod_getpwuid(void *context, uid_t uid); +void hesiod_free_passwd(void *context, struct passwd *pw); +struct servent *hesiod_getservbyname(void *context, const char *name, + const char *proto); +void hesiod_free_servent(void *context, struct servent *serv); +struct hesiod_postoffice *hesiod_getmailhost(void *context, const char *user); +void hesiod_free_postoffice(void *context, struct hesiod_postoffice *po); + +/* Compatibility stuff. */ + +#define HES_ER_UNINIT -1 /* uninitialized */ +#define HES_ER_OK 0 /* no error */ +#define HES_ER_NOTFOUND 1 /* Hesiod name not found by server */ +#define HES_ER_CONFIG 2 /* local problem (no config file?) */ +#define HES_ER_NET 3 /* network problem */ + +struct hes_postoffice { + char *po_type; + char *po_host; + char *po_name; +}; + +int hes_init(void); +char *hes_to_bind(const char *name, const char *type); +char **hes_resolve(const char *name, const char *type); +int hes_error(void); +struct passwd *hes_getpwnam(const char *name); +struct passwd *hes_getpwuid(uid_t uid); +struct servent *hes_getservbyname(const char *name, const char *proto); +struct hes_postoffice *hes_getmailhost(const char *name); + +#endif diff --git a/hesiod/hesiod_p.h b/hesiod/hesiod_p.h new file mode 100644 index 0000000000..809916ac2b --- /dev/null +++ b/hesiod/hesiod_p.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * $Id$ + */ + +/* + * hesiod_p.h -- private definitions for the hesiod library + */ + +#ifndef HESIOD_P_H_INCLUDED +#define HESIOD_P_H_INCLUDED + +/* Defaults if the configuration file is not present. */ +#define DEF_RHS ".athena.mit.edu" +#define DEF_LHS ".ns" + +struct hesiod_p { + char *lhs; /* normally ".ns" */ + char *rhs; /* AKA the default hesiod domain */ + int classes[2]; /* The class search order. */ +}; + +#define MAX_HESRESP 1024 + +#endif /*HESIOD_P_H_INCLUDED*/ diff --git a/hesiod/libnss_hesiod.map b/hesiod/libnss_hesiod.map new file mode 100644 index 0000000000..6c1fd5eba9 --- /dev/null +++ b/hesiod/libnss_hesiod.map @@ -0,0 +1,12 @@ +GLIBC_2.0 { + global: + _nss_hesiod_setpwent; _nss_hesiod_endpwent; + _nss_hesiod_getpwnam_r; _nss_hesiod_getpwuid; + _nss_hesiod_setgrent; _nss_hesiod_endgrent; + _nss_hesiod_getgrnam_r; _nss_hesiod_getgrgid; + _nss_hesiod_setservent; _nss_hesiod_endservent; + _nss_hesiod_getservbyname_r; + + local: + *; +}; diff --git a/hesiod/nss_hesiod/hesiod-grp.c b/hesiod/nss_hesiod/hesiod-grp.c new file mode 100644 index 0000000000..7b0832dbe3 --- /dev/null +++ b/hesiod/nss_hesiod/hesiod-grp.c @@ -0,0 +1,150 @@ +/* Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Mark Kettenis , 1997. + + 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 + +/* Get the declaration of the parser function. */ +#define ENTNAME grent +#define STRUCTURE group +#define EXTERN_PARSER +#include + +/* Locks the static variables in this file. */ +__libc_lock_define_initialized (static, lock); + +static void *context = NULL; + +static enum nss_status +internal_setgrent (void) +{ + if (!context) + { + if (hesiod_init (&context) == -1) + return NSS_STATUS_UNAVAIL; + } + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_hesiod_setgrent (void) +{ + enum nss_status status; + + __libc_lock_lock (lock); + + status = internal_setgrent (); + + __libc_lock_unlock (lock); + + return status; +} + +enum nss_status +_nss_hesiod_endgrent (void) +{ + __libc_lock_lock (lock); + + if (context) + { + hesiod_end (context); + context = NULL; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +static enum nss_status +lookup (const char *name, const char *type, struct group *grp, + char *buffer, size_t buflen) +{ + enum nss_status status; + struct parser_data *data = (void *) buffer; + size_t linebuflen; + char **list; + int parse_res; + + status = internal_setgrent (); + if (status != NSS_STATUS_SUCCESS) + return status; + + list = hesiod_resolve (context, name, type); + if (list == NULL) + return errno == ENOENT ? NSS_STATUS_NOTFOUND : NSS_STATUS_UNAVAIL; + + linebuflen = buffer + buflen - data->linebuffer; + if (linebuflen < strlen (*list) + 1) + { + hesiod_free_list (context, list); + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; + } + + strcpy (buffer, *list); + hesiod_free_list (context, list); + + parse_res = _nss_files_parse_grent (buffer, grp, data, buflen); + if (parse_res < 1) + return parse_res == -1 ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND; + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_hesiod_getgrnam_r (const char *name, struct group *grp, + char *buffer, size_t buflen) +{ + enum nss_status status; + + __libc_lock_lock (lock); + + status = lookup (name, "group", grp, buffer, buflen); + + __libc_lock_unlock (lock); + + return status; +} + +enum nss_status +_nss_hesiod_getgrgid_r (gid_t gid, struct group *grp, + char *buffer, size_t buflen) +{ + enum nss_status status = NSS_STATUS_UNAVAIL; + char gidstr[21]; /* We will probably never have a gid_t with more + than 64 bits. */ + + snprintf (gidstr, sizeof gidstr, "%d", gid); + + __libc_lock_lock (lock); + + status = lookup (gidstr, "gid", grp, buffer, buflen); + + __libc_lock_unlock (lock); + + return status; +} diff --git a/hesiod/nss_hesiod/hesiod-pwd.c b/hesiod/nss_hesiod/hesiod-pwd.c new file mode 100644 index 0000000000..bb2a4c8785 --- /dev/null +++ b/hesiod/nss_hesiod/hesiod-pwd.c @@ -0,0 +1,150 @@ +/* Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Mark Kettenis , 1997. + + 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 + +/* Get the declaration of the parser function. */ +#define ENTNAME pwent +#define STRUCTURE passwd +#define EXTERN_PARSER +#include + +/* Locks the static variables in this file. */ +__libc_lock_define_initialized (static, lock); + +static void *context = NULL; + +static enum nss_status +internal_setpwent (void) +{ + if (!context) + { + if (hesiod_init (&context) == -1) + return NSS_STATUS_UNAVAIL; + } + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_hesiod_setpwent (void) +{ + enum nss_status status; + + __libc_lock_lock (lock); + + status = internal_setpwent (); + + __libc_lock_unlock (lock); + + return status; +} + +enum nss_status +_nss_hesiod_endpwent (void) +{ + __libc_lock_lock (lock); + + if (context) + { + hesiod_end (context); + context = NULL; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +static enum nss_status +lookup (const char *name, const char *type, struct passwd *pwd, + char *buffer, size_t buflen) +{ + enum nss_status status; + struct parser_data *data = (void *) buffer; + size_t linebuflen; + char **list; + int parse_res; + + status = internal_setpwent (); + if (status != NSS_STATUS_SUCCESS) + return status; + + list = hesiod_resolve (context, name, type); + if (list == NULL) + return errno == ENOENT ? NSS_STATUS_NOTFOUND : NSS_STATUS_UNAVAIL; + + linebuflen = buffer + buflen - data->linebuffer; + if (linebuflen < strlen (*list) + 1) + { + hesiod_free_list (context, list); + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; + } + + strcpy (data->linebuffer, *list); + hesiod_free_list (context, list); + + parse_res = _nss_files_parse_pwent (buffer, pwd, data, buflen); + if (parse_res < 1) + return parse_res == -1 ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND; + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_hesiod_getpwnam_r (const char *name, struct passwd *pwd, + char *buffer, size_t buflen) +{ + enum nss_status status; + + __libc_lock_lock (lock); + + status = lookup (name, "passwd", pwd, buffer, buflen); + + __libc_lock_unlock (lock); + + return status; +} + +enum nss_status +_nss_hesiod_getpwuid_r (uid_t uid, struct passwd *pwd, + char *buffer, size_t buflen) +{ + enum nss_status status = NSS_STATUS_UNAVAIL; + char uidstr[21]; /* We will probably never have a gid_t with more + than 64 bits. */ + + snprintf (uidstr, sizeof uidstr, "%d", uid); + + __libc_lock_lock (lock); + + status = lookup (uidstr, "uid", pwd, buffer, buflen); + + __libc_lock_unlock (lock); + + return status; +} diff --git a/hesiod/nss_hesiod/hesiod-service.c b/hesiod/nss_hesiod/hesiod-service.c new file mode 100644 index 0000000000..f74877f748 --- /dev/null +++ b/hesiod/nss_hesiod/hesiod-service.c @@ -0,0 +1,165 @@ +/* Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Mark Kettenis , 1997. + + 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 + + +/* Hesiod uses a format for service entries that differs from the + traditional format. We therefore declare our own parser. */ + +#define ENTNAME servent + +#define ENTDATA servent_data +struct servent_data {}; + +#define TRAILING_LIST_MEMBER s_aliases +#define TRAILING_LIST_SEPARATOR_P isspace +#include +#define ISSEMICOLON(c) ((c) == ';') +LINE_PARSER +("", + (void) entdata; + STRING_FIELD (result->s_name, ISSEMICOLON, 1); + STRING_FIELD (result->s_proto, ISSEMICOLON, 1); + INT_FIELD (result->s_port, ISSEMICOLON, 10, 0, htons); + ) + + +/* Locks the static variables in this file. */ +__libc_lock_define_initialized (static, lock); + +static void *context = NULL; + +static enum nss_status +internal_setservent (void) +{ + if (!context) + { + if (hesiod_init (&context) == -1) + return NSS_STATUS_UNAVAIL; + } + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_hesiod_setservent (void) +{ + enum nss_status status; + + __libc_lock_lock (lock); + + status = internal_setservent (); + + __libc_lock_unlock (lock); + + return status; +} + +enum nss_status +_nss_hesiod_endservent (void) +{ + __libc_lock_lock (lock); + + if (context) + { + hesiod_end (context); + context = NULL; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +static enum nss_status +lookup (const char *name, const char *protocol, struct servent *serv, + char *buffer, size_t buflen) +{ + enum nss_status status; + struct parser_data *data = (void *) buffer; + size_t linebuflen; + char **list, **item; + int parse_res; + int found; + + status = internal_setservent (); + if (status != NSS_STATUS_SUCCESS) + return status; + + list = hesiod_resolve (context, name, "service"); + if (list == NULL) + return errno == ENOENT ? NSS_STATUS_NOTFOUND : NSS_STATUS_UNAVAIL; + + linebuflen = buffer + buflen - data->linebuffer; + + item = list; + found = 0; + do + { + if (linebuflen < strlen (*item) + 1) + { + hesiod_free_list (context, list); + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; + } + + strcpy (data->linebuffer, *item); + + parse_res = parse_line (buffer, serv, data, buflen); + if (parse_res == -1) + { + hesiod_free_list (context, list); + return NSS_STATUS_TRYAGAIN; + } + + if (parse_res > 0) + found = protocol == NULL || strcmp (serv->s_proto, protocol) == 0; + + ++item; + } + while (*item != NULL && !found); + + hesiod_free_list (context, list); + + return found ? NSS_STATUS_SUCCESS : NSS_STATUS_NOTFOUND; +} + +enum nss_status +_nss_hesiod_getservbyname_r (const char *name, const char *protocol, + struct servent *serv, + char *buffer, size_t buflen) +{ + enum nss_status status; + + __libc_lock_lock (lock); + + status = lookup (name, protocol, serv, buffer, buflen); + + __libc_lock_unlock (lock); + + return status; +} diff --git a/libio/fileops.c b/libio/fileops.c index 10f7567b0a..001794d05a 100644 --- a/libio/fileops.c +++ b/libio/fileops.c @@ -40,7 +40,12 @@ extern int errno; #ifdef _LIBC -# define open(Name, Flags, Prot) __open ((Name), (Flags), (Prot)) +# define open(Name, Flags, Prot) __open (Name, Flags, Prot) +# define close(FD) __close (FD) +# define fstat(FD, Statbuf) __fstat (FD, Statbuf) +# define lseek(FD, Offset, Whence) __lseek (FD, Offset, Whence) +# define read(FD, Buf, NBytes) __read (FD, Buf, NBytes) +# define write(FD, Buf, NBytes) __write (FD, Buf, NBytes) #endif /* An fstream can be in at most one of put mode, get mode, or putback mode. @@ -384,6 +389,10 @@ _IO_file_sync (fp) _IO_FILE *fp; { _IO_size_t delta; + int retval = 0; + + _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); + _IO_flockfile (fp); /* char* ptr = cur_ptr(); */ if (fp->_IO_write_ptr > fp->_IO_write_base) if (_IO_do_flush(fp)) return EOF; @@ -402,12 +411,14 @@ _IO_file_sync (fp) ; /* Ignore error from unseekable devices. */ #endif else - return EOF; + retval = EOF; } - fp->_offset = _IO_pos_BAD; + if (retval != EOF) + fp->_offset = _IO_pos_BAD; /* FIXME: Cleanup - can this be shared? */ /* setg(base(), ptr, ptr); */ - return 0; + _IO_cleanup_region_end (1); + return retval; } _IO_pos_t @@ -575,7 +586,7 @@ _IO_file_read (fp, buf, size) void *buf; _IO_ssize_t size; { - return _IO_read (fp->_fileno, buf, size); + return read (fp->_fileno, buf, size); } _IO_pos_t @@ -584,7 +595,7 @@ _IO_file_seek (fp, offset, dir) _IO_off_t offset; int dir; { - return _IO_lseek (fp->_fileno, offset, dir); + return lseek (fp->_fileno, offset, dir); } int @@ -592,14 +603,14 @@ _IO_file_stat (fp, st) _IO_FILE *fp; void *st; { - return _IO_fstat (fp->_fileno, (struct stat *) st); + return fstat (fp->_fileno, (struct stat *) st); } int _IO_file_close (fp) _IO_FILE *fp; { - return _IO_close (fp->_fileno); + return close (fp->_fileno); } _IO_ssize_t @@ -611,7 +622,7 @@ _IO_file_write (f, data, n) _IO_ssize_t to_do = n; while (to_do > 0) { - _IO_ssize_t count = _IO_write (f->_fileno, data, to_do); + _IO_ssize_t count = write (f->_fileno, data, to_do); if (count == EOF) { f->_flags |= _IO_ERR_SEEN; diff --git a/libio/iolibio.h b/libio/iolibio.h index ca863b51b3..92df6a6fd2 100644 --- a/libio/iolibio.h +++ b/libio/iolibio.h @@ -56,22 +56,3 @@ extern _IO_FILE* _IO_popen __P((const char*, const char*)); #ifdef __cplusplus } #endif - -#define _IO_open __open -#define _IO_close __close -#define _IO_fork __fork -#define _IO_fcntl __fcntl -#define _IO__exit _exit -#define _IO_read __read -#define _IO_write __write -#define _IO_lseek __lseek -#define _IO_getdtablesize __getdtablesize -#define _IO_pipe __pipe -#define _IO_dup2 __dup2 -#define _IO_execl execl -#define _IO_waitpid __waitpid -#define _IO_stat __stat -#define _IO_getpid __getpid -#define _IO_geteuid __geteuid -#define _IO_getegid __getegid -#define _IO_fstat __fstat diff --git a/libio/iopopen.c b/libio/iopopen.c index 434008609f..59d4fc3f0e 100644 --- a/libio/iopopen.c +++ b/libio/iopopen.c @@ -68,6 +68,10 @@ extern int _IO_dup2 __P ((int fd, int fd2)); #define _IO__exit _exit #endif +#ifndef _IO_close +#define _IO_close close +#endif + struct _IO_proc_file { struct _IO_FILE_plus file; diff --git a/libio/ioseekoff.c b/libio/ioseekoff.c index 8c642165f6..b1c4729b3d 100644 --- a/libio/ioseekoff.c +++ b/libio/ioseekoff.c @@ -32,9 +32,14 @@ _IO_seekoff (fp, offset, dir, mode) int dir; int mode; { + _IO_pos_t retval; + /* If we have a backup buffer, get rid of it, since the __seekoff callback may not know to do the right thing about it. This may be over-kill, but it'll do for now. TODO */ + _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); + _IO_flockfile (fp); + if (_IO_have_backup (fp)) { @@ -42,6 +47,8 @@ _IO_seekoff (fp, offset, dir, mode) offset -= fp->_IO_read_end - fp->_IO_read_ptr; _IO_free_backup_area (fp); } + retval = _IO_SEEKOFF (fp, offset, dir, mode); - return _IO_SEEKOFF (fp, offset, dir, mode); + _IO_cleanup_region_end (1); + return retval; } diff --git a/libio/ioseekpos.c b/libio/ioseekpos.c index 1ae88fb848..2ce0c2224e 100644 --- a/libio/ioseekpos.c +++ b/libio/ioseekpos.c @@ -31,12 +31,18 @@ _IO_seekpos (fp, pos, mode) _IO_pos_t pos; int mode; { + _IO_pos_t retval; + /* If we have a backup buffer, get rid of it, since the __seekoff callback may not know to do the right thing about it. This may be over-kill, but it'll do for now. TODO */ + _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); + _IO_flockfile (fp); if (_IO_have_backup (fp)) _IO_free_backup_area (fp); + retval = _IO_SEEKPOS (fp, pos, mode); - return _IO_SEEKPOS (fp, pos, mode); + _IO_cleanup_region_end (1); + return retval; } diff --git a/manual/math.texi b/manual/math.texi index 2b7cb82f5e..15a2075d33 100644 --- a/manual/math.texi +++ b/manual/math.texi @@ -54,6 +54,7 @@ in case of double using @code{double} is a good compromise. constant. * FP Comparison Functions:: Special functions to compare floating-point numbers. +* FP Function Optimizations:: Fast code or small code. * Trig Functions:: Sine, cosine, and tangent. * Inverse Trig Functions:: Arc sine, arc cosine, and arc tangent. * Exponents and Logarithms:: Also includes square root. @@ -704,6 +705,35 @@ that the comparison for equality and unequality do @emph{not} throw an exception if one of the arguments is an unordered value. +@node FP Function Optimizations +@section Is Fast Code or Small Code preferred? +@cindex Optimization + +If an application uses many floating point function it is often the case +that the costs for the function calls itseld are not neglectable. +Modern processor implementation often can execute the operation itself +very fast but the call means a disturbance of the control flow. + +For this reason the GNU C Library provides optimizations for many of the +frequently used math functions. When the GNU CC is used and the user +activates the optimizer several new inline functions and macros get +defined. These new functions and macros have the same names as the +library function and so get used instead of the later. In case of +inline functions the compiler will decide whether it is reasonable to +use the inline function and this decision is usually correct. + +For the generated code this means that no calls to the library functions +are necessary. This increases the speed significantly. But the +drawback is that the code size increases and this increase is not always +neglectable. + +In cases where the inline functions and macros are not wanted the symbol +@code{__NO_MATH_INLINES} should be defined before any system header is +included. This will make sure only library functions are used. Of +course it can be determined for each single file in the project whether +giving this option is preferred or not. + + @node Trig Functions @section Trigonometric Functions @cindex trigonometric functions @@ -1430,8 +1460,14 @@ the same seed, used in different C libraries or on different CPU types, will give you different random numbers. The GNU library supports the standard @w{ISO C} random number functions -plus another set derived from BSD. We recommend you use the standard -ones, @code{rand} and @code{srand}. +plus two other sets derived from BSD and SVID. We recommend you use the +standard ones, @code{rand} and @code{srand} if only a small number of +random bits are required. The SVID functions provide an interface which +allows better randon number generator algorithms and they return up to +48 random bits in one calls and they also return random floating-point +numbers if wanted. The SVID function might not be available on some BSD +derived systems but since they are required in the XPG they are +available on all Unix-conformant systems. @menu * ISO Random:: @code{rand} and friends. @@ -1478,6 +1514,30 @@ To produce truly random numbers (not just pseudo-random), do @code{srand (time (0))}. @end deftypefun +A completely broken interface was designed by the POSIX.1 committee to +support reproducible random numbers in multi-threaded programs. + +@comment stdlib.h +@comment POSIX.1 +@deftypefun int rand_r (unsigned int *@var{seed}) +This function returns a random number in the range 0 to @code{RAND_MAX} +just as @code{rand} does. But this function does not keep an internal +state for the RNG. Instead the @code{unsigned int} variable pointed to +by the argument @var{seed} is the only state. Before the value is +returned the state will be updated so that the next call will return a +new number. + +I.e., the state of the RNG can only have as much bits as the type +@code{unsigned int} has. This is far too few to provide a good RNG. +This interface is broken by design. + +If the program requires reproducible random numbers in multi-threaded +programs the reentrant SVID functions are probably a better choice. But +these functions are GNU extensions and therefore @code{rand_r}, as being +standardized in POSIX.1, should always be kept as a default method. +@end deftypefun + + @node BSD Random @subsection BSD Random Number Functions diff --git a/md5-crypt/Makefile b/md5-crypt/Makefile index ab054ce8a6..1737381c27 100644 --- a/md5-crypt/Makefile +++ b/md5-crypt/Makefile @@ -36,7 +36,7 @@ libcrypt-map := libcrypt.map onlymd5-routines := onlymd5-entry md5-crypt md5 distribute += onlymd5-entry.c -extra-objs := onlymd5-entry.o +extra-objs := $(patsubst %,onlymd5-entry%,$(object-suffixes)) include ../Makeconfig diff --git a/posix/Makefile b/posix/Makefile index 285f3b306c..2b14fac138 100644 --- a/posix/Makefile +++ b/posix/Makefile @@ -28,7 +28,8 @@ headers := sys/utsname.h sys/times.h sys/wait.h sys/types.h unistd.h \ bits/waitflags.h bits/waitstatus.h sys/unistd.h sched.h \ bits/sched.h re_comp.h wait.h -distribute := confstr.h TESTS TESTS2C.sed testcases.h +distribute := confstr.h TESTS TESTS2C.sed testcases.h \ + globtest.c globtest.sh routines := \ uname \ @@ -60,6 +61,11 @@ before-compile := testcases.h include ../Rules +ifeq (no,$(cross-compiling)) +tests: $(objpfx)globtest + $(SHELL) -e globtest.sh $(common-objpfx) +endif + CFLAGS-regex.c = -Wno-unused -Wno-strict-prototypes CFLAGS-getaddrinfo.c = -DRESOLVER diff --git a/posix/glob.c b/posix/glob.c index b6e087e5eb..f0cb6d377b 100644 --- a/posix/glob.c +++ b/posix/glob.c @@ -21,12 +21,12 @@ #endif #ifdef HAVE_CONFIG_H -#include +# include #endif /* Enable GNU extensions in glob.h. */ #ifndef _GNU_SOURCE -#define _GNU_SOURCE 1 +# define _GNU_SOURCE 1 #endif #include @@ -49,45 +49,45 @@ it is simpler to just do this in the source for each such file. */ #define GLOB_INTERFACE_VERSION 1 -#if !defined (_LIBC) && defined (__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1 -#include -#if _GNU_GLOB_INTERFACE_VERSION == GLOB_INTERFACE_VERSION -#define ELIDE_CODE -#endif +#if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1 +# include +# if _GNU_GLOB_INTERFACE_VERSION == GLOB_INTERFACE_VERSION +# define ELIDE_CODE +# endif #endif #ifndef ELIDE_CODE -#if defined(STDC_HEADERS) || defined(__GNU_LIBRARY__) -#include +#if defined STDC_HEADERS || defined __GNU_LIBRARY__ +# include #endif #if defined HAVE_UNISTD_H || defined _LIBC -#include -#ifndef POSIX -#ifdef _POSIX_VERSION -#define POSIX -#endif -#endif +# include +# ifndef POSIX +# ifdef _POSIX_VERSION +# define POSIX +# endif +# endif #endif -#if !defined (_AMIGA) && !defined (VMS) && !defined(WINDOWS32) -#include +#if !defined _AMIGA && !defined VMS && !defined WINDOWS32 +# include #endif -#if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS) +#if !defined __GNU_LIBRARY__ && !defined STDC_HEADERS extern int errno; #endif #ifndef __set_errno -#define __set_errno(val) errno = (val) +# define __set_errno(val) errno = (val) #endif #ifndef NULL -#define NULL 0 +# define NULL 0 #endif -#if defined (HAVE_DIRENT_H) || defined (__GNU_LIBRARY__) +#if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__ # include # define NAMLEN(dirent) strlen((dirent)->d_name) #else @@ -110,36 +110,36 @@ extern int errno; /* In GNU systems, defines this macro for us. */ #ifdef _D_NAMLEN -#undef NAMLEN -#define NAMLEN(d) _D_NAMLEN(d) +# undef NAMLEN +# define NAMLEN(d) _D_NAMLEN(d) #endif -#if (defined (POSIX) || defined (WINDOWS32)) && !defined (__GNU_LIBRARY__) +#if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__ /* Posix does not require that the d_ino field be present, and some systems do not provide it. */ -#define REAL_DIR_ENTRY(dp) 1 +# define REAL_DIR_ENTRY(dp) 1 #else -#define REAL_DIR_ENTRY(dp) (dp->d_ino != 0) +# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0) #endif /* POSIX */ -#if (defined (STDC_HEADERS) || defined (__GNU_LIBRARY__)) -#include -#include -#define ANSI_STRING +#if defined STDC_HEADERS || defined __GNU_LIBRARY__ +# include +# include +# define ANSI_STRING #else /* No standard headers. */ extern char *getenv (); -#ifdef HAVE_STRING_H -#include -#define ANSI_STRING -#else -#include -#endif -#ifdef HAVE_MEMORY_H -#include -#endif +# ifdef HAVE_STRING_H +# include +# define ANSI_STRING +# else +# include +# endif +# ifdef HAVE_MEMORY_H +# include +# endif extern char *malloc (), *realloc (); extern void free (); @@ -151,35 +151,35 @@ extern void abort (), exit (); #ifndef ANSI_STRING -#ifndef bzero +# ifndef bzero extern void bzero (); -#endif -#ifndef bcopy +# endif +# ifndef bcopy extern void bcopy (); -#endif +# endif -#define memcpy(d, s, n) bcopy ((s), (d), (n)) -#define strrchr rindex +# define memcpy(d, s, n) bcopy ((s), (d), (n)) +# define strrchr rindex /* memset is only used for zero here, but let's be paranoid. */ -#define memset(s, better_be_zero, n) \ +# define memset(s, better_be_zero, n) \ ((void) ((better_be_zero) == 0 ? (bzero((s), (n)), 0) : (abort(), 0))) #endif /* Not ANSI_STRING. */ #if !defined HAVE_STRCOLL && !defined _LIBC -#define strcoll strcmp +# define strcoll strcmp #endif #ifndef __GNU_LIBRARY__ -#ifdef __GNUC__ +# ifdef __GNUC__ __inline -#endif -#ifndef __SASC -#ifdef WINDOWS32 +# endif +# ifndef __SASC +# ifdef WINDOWS32 static void * -#else +# else static char * -#endif +# endif my_realloc (p, n) char *p; unsigned int n; @@ -190,47 +190,47 @@ my_realloc (p, n) return (char *) malloc (n); return (char *) realloc (p, n); } -#define realloc my_realloc -#endif /* __SASC */ +# define realloc my_realloc +# endif /* __SASC */ #endif /* __GNU_LIBRARY__ */ -#if !defined(__alloca) && !defined(__GNU_LIBRARY__) +#if !defined __alloca && !defined __GNU_LIBRARY__ -#ifdef __GNUC__ -#undef alloca -#define alloca(n) __builtin_alloca (n) -#else /* Not GCC. */ -#ifdef HAVE_ALLOCA_H -#include -#else /* Not HAVE_ALLOCA_H. */ -#ifndef _AIX -#ifdef WINDOWS32 -#include -#else +# ifdef __GNUC__ +# undef alloca +# define alloca(n) __builtin_alloca (n) +# else /* Not GCC. */ +# ifdef HAVE_ALLOCA_H +# include +# else /* Not HAVE_ALLOCA_H. */ +# ifndef _AIX +# ifdef WINDOWS32 +# include +# else extern char *alloca (); -#endif /* WINDOWS32 */ -#endif /* Not _AIX. */ -#endif /* sparc or HAVE_ALLOCA_H. */ -#endif /* GCC. */ +# endif /* WINDOWS32 */ +# endif /* Not _AIX. */ +# endif /* sparc or HAVE_ALLOCA_H. */ +# endif /* GCC. */ -#define __alloca alloca +# define __alloca alloca #endif #ifndef __GNU_LIBRARY__ -#define __stat stat -#ifdef STAT_MACROS_BROKEN -#undef S_ISDIR -#endif -#ifndef S_ISDIR -#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) -#endif +# define __stat stat +# ifdef STAT_MACROS_BROKEN +# undef S_ISDIR +# endif +# ifndef S_ISDIR +# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +# endif #endif -#if !(defined (STDC_HEADERS) || defined (__GNU_LIBRARY__)) -#undef size_t -#define size_t unsigned int +#if !(defined STDC_HEADERS || defined __GNU_LIBRARY__) +# undef size_t +# define size_t unsigned int #endif /* Some system header files erroneously define these. @@ -508,18 +508,18 @@ glob (pattern, flags, errfunc, pglob) { /* Look up home directory. */ char *home_dir = getenv ("HOME"); -#ifdef _AMIGA +# ifdef _AMIGA if (home_dir == NULL || home_dir[0] == '\0') home_dir = "SYS:"; -#else -#ifdef WINDOWS32 +# else +# ifdef WINDOWS32 if (home_dir == NULL || home_dir[0] == '\0') home_dir = "c:/users/default"; /* poor default */ -#else +# else if (home_dir == NULL || home_dir[0] == '\0') { int success; -#if defined HAVE_GETLOGIN_R || defined _LIBC +# if defined HAVE_GETLOGIN_R || defined _LIBC extern int getlogin_r __P ((char *, size_t)); size_t buflen = sysconf (_SC_LOGIN_NAME_MAX) + 1; char *name; @@ -531,15 +531,15 @@ glob (pattern, flags, errfunc, pglob) name = (char *) __alloca (buflen); success = getlogin_r (name, buflen) >= 0; -#else +# else extern char *getlogin __P ((void)); char *name; success = (name = getlogin ()) != NULL; -#endif +# endif if (success) { -#if defined HAVE_GETPWNAM_R || defined _LIBC +# if defined HAVE_GETPWNAM_R || defined _LIBC size_t pwbuflen = sysconf (_SC_GETPW_R_SIZE_MAX); char *pwtmpbuf; struct passwd pwbuf, *p; @@ -548,18 +548,18 @@ glob (pattern, flags, errfunc, pglob) success = (__getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p) >= 0); -#else +# else struct passwd *p = getpwnam (name); success = p != NULL; -#endif +# endif if (success) home_dir = p->pw_dir; } } if (home_dir == NULL || home_dir[0] == '\0') home_dir = (char *) "~"; /* No luck. */ -#endif /* WINDOWS32 */ -#endif +# endif /* WINDOWS32 */ +# endif /* Now construct the full directory. */ if (dirname[1] == '\0') dirname = home_dir; @@ -573,7 +573,7 @@ glob (pattern, flags, errfunc, pglob) dirname = newp; } } -#if !defined _AMIGA && !defined WINDOWS32 +# if !defined _AMIGA && !defined WINDOWS32 else { char *end_name = strchr (dirname, '/'); @@ -591,7 +591,7 @@ glob (pattern, flags, errfunc, pglob) /* Look up specific user's home directory. */ { -#if defined HAVE_GETPWNAM_R || defined _LIBC +# if defined HAVE_GETPWNAM_R || defined _LIBC size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX); char *pwtmpbuf = (char *) __alloca (buflen); struct passwd pwbuf, *p; @@ -599,13 +599,13 @@ glob (pattern, flags, errfunc, pglob) home_dir = p->pw_dir; else home_dir = NULL; -#else +# else struct passwd *p = getpwnam (user_name); if (p != NULL) home_dir = p->pw_dir; else home_dir = NULL; -#endif +# endif } /* If we found a home directory use this. */ if (home_dir != NULL) @@ -620,7 +620,7 @@ glob (pattern, flags, errfunc, pglob) dirname = newp; } } -#endif /* Not Amiga && not WINDOWS32. */ +# endif /* Not Amiga && not WINDOWS32. */ } #endif /* Not VMS. */ @@ -912,8 +912,42 @@ glob_in_dir (pattern, directory, flags, errfunc, pglob) if (!__glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE))) { - stream = NULL; - flags |= GLOB_NOCHECK; + /* We must check whether the file in this directory exists. */ + stream = ((flags & GLOB_ALTDIRFUNC) ? + (*pglob->gl_opendir) (directory) : + (__ptr_t) opendir (directory)); + if (stream == NULL) + { + if ((errfunc != NULL && (*errfunc) (directory, errno)) || + (flags & GLOB_ERR)) + return GLOB_ABORTED; + } + else + while (1) + { + struct dirent *d = ((flags & GLOB_ALTDIRFUNC) ? + (*pglob->gl_readdir) (stream) : + readdir ((DIR *) stream)); + if (d == NULL) + break; + if (! REAL_DIR_ENTRY (d)) + continue; + + if (strcmp (pattern, d->d_name) == 0) + { + size_t len = NAMLEN (d); + names = + (struct globlink *) __alloca (sizeof (struct globlink)); + names->name = (char *) malloc (len + 1); + if (names->name == NULL) + goto memory_error; + memcpy ((__ptr_t) names->name, pattern, len); + names->name[len] = '\0'; + names->next = NULL; + nfound = 1; + break; + } + } } else { @@ -984,24 +1018,27 @@ glob_in_dir (pattern, directory, flags, errfunc, pglob) names->name[len] = '\0'; } - pglob->gl_pathv - = (char **) realloc (pglob->gl_pathv, - (pglob->gl_pathc + - ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) + - nfound + 1) * - sizeof (char *)); - if (pglob->gl_pathv == NULL) - goto memory_error; + if (nfound != 0) + { + pglob->gl_pathv + = (char **) realloc (pglob->gl_pathv, + (pglob->gl_pathc + + ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) + + nfound + 1) * + sizeof (char *)); + if (pglob->gl_pathv == NULL) + goto memory_error; - if (flags & GLOB_DOOFFS) - while (pglob->gl_pathc < pglob->gl_offs) - pglob->gl_pathv[pglob->gl_pathc++] = NULL; + if (flags & GLOB_DOOFFS) + while (pglob->gl_pathc < pglob->gl_offs) + pglob->gl_pathv[pglob->gl_pathc++] = NULL; - for (; names != NULL; names = names->next) - pglob->gl_pathv[pglob->gl_pathc++] = names->name; - pglob->gl_pathv[pglob->gl_pathc] = NULL; + for (; names != NULL; names = names->next) + pglob->gl_pathv[pglob->gl_pathc++] = names->name; + pglob->gl_pathv[pglob->gl_pathc] = NULL; - pglob->gl_flags = flags; + pglob->gl_flags = flags; + } if (stream != NULL) { diff --git a/posix/globtest.c b/posix/globtest.c new file mode 100644 index 0000000000..589e91b973 --- /dev/null +++ b/posix/globtest.c @@ -0,0 +1,46 @@ +/* Copyright (C) 1997 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. */ + +#include +#include + +int +main (int argc, char *argv[]) +{ + int i; + int glob_flags = GLOB_NOSORT; + glob_t filenames; + + i = glob (argv[1], glob_flags, NULL, &filenames); + + if (i == GLOB_NOSPACE) + puts ("GLOB_NOSPACE"); + else if (i == GLOB_ABEND) + puts ("GLOB_ABEND"); + else if (i == GLOB_NOMATCH) + puts ("GLOB_NOMATCH"); + + printf ("%sNULL\n", filenames.gl_pathv ? "not " : ""); + + if (filenames.gl_pathv) + { + for (i = 0; i < filenames.gl_pathc; ++i) + printf ("`%s'\n", filenames.gl_pathv[i]); + } + return 0; +} diff --git a/posix/globtest.sh b/posix/globtest.sh new file mode 100755 index 0000000000..c51655b9b3 --- /dev/null +++ b/posix/globtest.sh @@ -0,0 +1,98 @@ +#! /bin/sh + +common_objpfx=$1; shift + +# Create the arena +: ${TMPDIR=/tmp} +testdir=$TMPDIR/globtest-dir +testout=$TMPDIR/globtest-out + +trap 'rm -fr $testdir $testout' 1 2 3 15 + +rm -fr $testdir +mkdir $testdir +echo 1 > $testdir/file1 +echo 2 > $testdir/file2 +mkdir $testdir/dir1 +mkdir $testdir/dir2 +echo 1_1 > $testdir/dir1/file1_1 +echo 1_2 > $testdir/dir1/file1_2 + +# Run some tests. +result=0 +here=`pwd` + +(cd $testdir && + LD_LIBRARY_PATH=$common_objpfx $common_objpfx/posix/globtest "*") | +sort > $testout +cat <<"EOF" | cmp - $testout || result=1 +`dir1' +`dir2' +`file1' +`file2' +not NULL +EOF + +(cd $testdir && + LD_LIBRARY_PATH=$common_objpfx $common_objpfx/posix/globtest "*/*") | +sort > $testout +cat <<"EOF" | cmp - $testout || result=1 +`dir1/file1_1' +`dir1/file1_2' +not NULL +EOF + +(cd $testdir && + LD_LIBRARY_PATH=$common_objpfx $common_objpfx/posix/globtest "*/1") | +sort > $testout +cat <<"EOF" | cmp - $testout || result=1 +GLOB_NOMATCH +NULL +EOF + +(cd $testdir && + LD_LIBRARY_PATH=$common_objpfx $common_objpfx/posix/globtest "*/*1_1") | +sort > $testout +cat <<"EOF" | cmp - $testout || result=1 +`dir1/file1_1' +not NULL +EOF + +(cd $testdir && + LD_LIBRARY_PATH=$common_objpfx $common_objpfx/posix/globtest "*/file1_1") | +sort > $testout +cat <<"EOF" | cmp - $testout || result=1 +`dir1/file1_1' +not NULL +EOF + +(cd $testdir && + LD_LIBRARY_PATH=$common_objpfx $common_objpfx/posix/globtest "*-/*") | +sort > $testout +cat <<"EOF" | cmp - $testout || result=1 +GLOB_NOMATCH +NULL +EOF + +(cd $testdir && + LD_LIBRARY_PATH=$common_objpfx $common_objpfx/posix/globtest "*-") | +sort > $testout +cat <<"EOF" | cmp - $testout || result=1 +GLOB_NOMATCH +NULL +EOF + +if test $result -eq 0; then + rm -fr $testdir $testout +fi + +exit $result + +# Preserve executable bits for this shell script. +Local Variables: +eval:(defun frobme () (set-file-modes buffer-file-name file-mode)) +eval:(make-local-variable 'file-mode) +eval:(setq file-mode (file-modes (buffer-file-name))) +eval:(make-local-variable 'after-save-hook) +eval:(add-hook 'after-save-hook 'frobme) +End: diff --git a/resolv/res_send.c b/resolv/res_send.c index a4d242e8aa..eb159be456 100644 --- a/resolv/res_send.c +++ b/resolv/res_send.c @@ -498,7 +498,7 @@ res_send(buf, buflen, ans, anssiz) struct timeval timeout; fd_set dsmask; struct sockaddr_in from; - size_t fromlen; + socklen_t fromlen; if ((s < 0) || vc) { if (vc) diff --git a/shlib-versions b/shlib-versions index 33412a4e1e..d24a4b010c 100644 --- a/shlib-versions +++ b/shlib-versions @@ -63,6 +63,7 @@ alpha-.*-linux.* libnss_compat=1.1 alpha-.*-linux.* libnss_nis=1.1 alpha-.*-linux.* libnss_nisplus=1.1 alpha-.*-linux.* libnss_ldap=1.1 +alpha-.*-linux.* libnss_hesiod=1.1 .*-.*-.* libnss_files=1 .*-.*-.* libnss_dns=1 .*-.*-.* libnss_db=1 @@ -70,6 +71,7 @@ alpha-.*-linux.* libnss_ldap=1.1 .*-.*-.* libnss_nis=1 .*-.*-.* libnss_nisplus=1 .*-.*-.* libnss_ldap=1 +.*-.*-.* libnss_hesiod=1 # Version for libnsl with YP and NIS+ functions. alpha-.*-linux.* libnsl=1.1 diff --git a/string/Makefile b/string/Makefile index 8596bc1b24..dbc41be0be 100644 --- a/string/Makefile +++ b/string/Makefile @@ -40,8 +40,8 @@ routines := strcat strchr strcmp strcoll strcpy strcspn \ envz basename \ strcoll_l strxfrm_l -tests := tester inl-tester testcopy test-ffs tst-strlen \ - stratcliff tst-svc +tests := tester inl-tester noinl-tester testcopy test-ffs \ + tst-strlen stratcliff tst-svc distribute := memcopy.h pagecopy.h tst-svc.expect diff --git a/string/bits/string2.h b/string/bits/string2.h index b943fe9aa0..b0e9cdcb8a 100644 --- a/string/bits/string2.h +++ b/string/bits/string2.h @@ -18,8 +18,11 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#ifndef _BITS_STRING2_H -#define _BITS_STRING2_H 1 +#ifndef _STRING_H +# error "Never use directly; include instead." +#endif + +#ifdef __NO_STRING_INLINES /* Unlike the definitions in the header the definitions contained here are not optimizing down to assembler @@ -30,7 +33,7 @@ trick is to use GNU CC's `__builtin_constant_p' function. Every function XXX which has a defined version in - must be accompanied by a have _HAVE_STRING_ARCH_XXX + must be accompanied by a symbol _HAVE_STRING_ARCH_XXX to make sure we don't get redefinitions. We must use here macros instead of inline functions since the @@ -42,55 +45,158 @@ # define __STRING_INLINE extern __inline #endif -/* We need some more types. */ -#include +#if _STRING_ARCH_unaligned +/* If we can do unaligned memory accesses we must know the endianess. */ +# include +# include + +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define __STRING2_SMALL_GET16(src, idx) \ + (((src)[idx + 1] << 8) | (src)[idx]) +# define __STRING2_SMALL_GET32(src, idx) \ + ((((src)[idx + 3] << 8 | (src)[idx + 2]) << 8 \ + | (src)[idx + 1]) << 8 | (src)[idx]) +# else +# define __STRING2_SMALL_GET16(src, idx) \ + (((src)[idx] << 8) | (src)[idx + 1]) +# define __STRING2_SMALL_GET32(src, idx) \ + ((((src)[idx] << 8 | (src)[idx + 1]) << 8 \ + | (src)[idx + 2]) << 8 | (src)[idx + 3]) +# endif +#else +/* These are a few types we need for the optimizations if we cannot + use unaligned memory accesses. */ +# define __STRING2_COPY_TYPE(N) \ + typedef struct { char __arr[N]; } \ + __STRING2_COPY_ARR##N __attribute__ ((packed)) +__STRING2_COPY_TYPE (2); +__STRING2_COPY_TYPE (3); +__STRING2_COPY_TYPE (4); +__STRING2_COPY_TYPE (5); +__STRING2_COPY_TYPE (6); +__STRING2_COPY_TYPE (7); +__STRING2_COPY_TYPE (8); +# undef __STRING2_COPY_TYPE +#endif + + +/* Set N bytes of S to C. */ +#ifndef _HAVE_STRING_ARCH_memset +# define memset(s, c, n) \ + (__extension__ (__builtin_constant_p (c) && (c) == '\0' \ + ? ({ void *__s = (s); __bzero (__s, n); __s; }) \ + : memset (s, c, n))) +#endif /* Copy SRC to DEST. */ #ifndef _HAVE_STRING_ARCH_strcpy # define strcpy(dest, src) \ (__extension__ (__builtin_constant_p (src) \ - ? (strlen (src) + 1 <= 8 \ + ? (sizeof ((src)[0]) == 1 && strlen (src) + 1 <= 8 \ ? __strcpy_small (dest, src, strlen (src) + 1) \ : (char *) memcpy (dest, src, strlen (src) + 1)) \ : strcpy (dest, src))) -__STRING_INLINE char * -__strcpy_small (char *__dest, __const char *__src, size_t __srclen) -{ - register char *__tmp = __dest; - switch (__srclen) - { - case 7: - *((__uint16_t *) __tmp)++ = *((__uint16_t *) __src)++; - case 5: - *((__uint32_t *) __tmp)++ = *((__uint32_t *) __src)++; - *((unsigned char *) __tmp) = '\0'; - break; - - case 8: - *((__uint32_t *) __tmp)++ = *((__uint32_t *) __src)++; - case 4: - *((__uint32_t *) __tmp) = *((__uint32_t *) __src); - break; - - case 6: - *((__uint32_t *) __tmp)++ = *((__uint32_t *) __src)++; - case 2: - *((__uint16_t *) __tmp) = *((__uint16_t *) __src); - break; - - case 3: - *((__uint16_t *) __tmp)++ = *((__uint16_t *) __src)++; - case 1: - *((unsigned char *) __tmp) = '\0'; - break; - - default: - break; - } - return __dest; -} +# if _STRING_ARCH_unaligned +# define __strcpy_small(dest, src, srclen) \ + (__extension__ ({ char *__retval = (dest); \ + char *__cp = __retval; \ + switch (srclen) \ + { \ + case 1: \ + *((unsigned char *) __cp) = '\0'; \ + break; \ + case 2: \ + *((__uint16_t *) __cp) = \ + __STRING2_SMALL_GET16 (src, 0); \ + break; \ + case 3: \ + *((__uint16_t *) __cp)++ = \ + __STRING2_SMALL_GET16 (src, 0); \ + *((unsigned char *) __cp) = '\0'; \ + break; \ + case 4: \ + *((__uint32_t *) __cp) = \ + __STRING2_SMALL_GET32 (src, 0); \ + break; \ + case 5: \ + *((__uint32_t *) __cp)++ = \ + __STRING2_SMALL_GET32 (src, 0); \ + *((unsigned char *) __cp) = '\0'; \ + break; \ + case 6: \ + *((__uint32_t *) __cp)++ = \ + __STRING2_SMALL_GET32 (src, 0); \ + *((__uint16_t *) __cp) = \ + __STRING2_SMALL_GET16 (src, 4); \ + break; \ + case 7: \ + *((__uint32_t *) __cp)++ = \ + __STRING2_SMALL_GET32 (src, 0); \ + *((__uint16_t *) __cp)++ = \ + __STRING2_SMALL_GET16 (src, 4); \ + *((unsigned char *) __cp) = '\0'; \ + break; \ + case 8: \ + *((__uint32_t *) __cp)++ = \ + __STRING2_SMALL_GET32 (src, 0); \ + *((__uint32_t *) __cp) = \ + __STRING2_SMALL_GET32 (src, 4); \ + break; \ + } \ + __retval; })) +# else +# define __strcpy_small(dest, src, srclen) \ + (__extension__ ({ char *__cp = (dest); \ + switch (srclen) \ + { \ + case 1: \ + *((unsigned char *) __cp) = '\0'; \ + break; \ + case 2: \ + *((__STRING2_COPY_ARR2 *) __cp) = \ + ((__STRING2_COPY_ARR2) { { (src)[0], '\0' } }); \ + break; \ + case 3: \ + *((__STRING2_COPY_ARR3 *) __cp) = \ + ((__STRING2_COPY_ARR3) { { (src)[0], (src)[1], \ + '\0' } }); \ + break; \ + case 4: \ + *((__STRING2_COPY_ARR4 *) __cp) = \ + ((__STRING2_COPY_ARR4) { { (src)[0], (src)[1], \ + (src)[2], '\0' } }); \ + break; \ + case 5: \ + *((__STRING2_COPY_ARR5 *) __cp) = \ + ((__STRING2_COPY_ARR5) { { (src)[0], (src)[1], \ + (src)[2], (src)[3], \ + '\0' } }); \ + break; \ + case 6: \ + *((__STRING2_COPY_ARR6 *) __cp) = \ + ((__STRING2_COPY_ARR6) { { (src)[0], (src)[1], \ + (src)[2], (src)[3], \ + (src)[4], '\0' } }); \ + break; \ + case 7: \ + *((__STRING2_COPY_ARR7 *) __cp) = \ + ((__STRING2_COPY_ARR7) { { (src)[0], (src)[1], \ + (src)[2], (src)[3], \ + (src)[4], (src)[5], \ + '\0' } }); \ + break; \ + case 8: \ + *((__STRING2_COPY_ARR8 *) __cp) = \ + ((__STRING2_COPY_ARR8) { { (src)[0], (src)[1], \ + (src)[2], (src)[3], \ + (src)[4], (src)[5], \ + (src)[6], '\0' } }); \ + break; \ + } \ + __cp; })) +# endif #endif @@ -99,7 +205,7 @@ __strcpy_small (char *__dest, __const char *__src, size_t __srclen) # ifndef _HAVE_STRING_ARCH_stpcpy # define __stpcpy(dest, src) \ (__extension__ (__builtin_constant_p (src) \ - ? (strlen (src) + 1 <= 8 \ + ? (sizeof ((src)[0]) == 1 && strlen (src) + 1 <= 8 \ ? __stpcpy_small (dest, src, strlen (src) + 1) \ : ((char *) __mempcpy (dest, src, strlen (src) + 1) - 1))\ : __stpcpy (dest, src))) @@ -107,43 +213,108 @@ __strcpy_small (char *__dest, __const char *__src, size_t __srclen) we have to use the name `__stpcpy'. */ # define stpcpy(dest, src) __stpcpy (dest, src) -__STRING_INLINE char * -__stpcpy_small (char *__dest, __const char *__src, size_t __srclen) -{ - register char *__tmp = __dest; - switch (__srclen) - { - case 7: - *((__uint16_t *) __tmp)++ = *((__uint16_t *) __src)++; - case 5: - *((__uint32_t *) __tmp)++ = *((__uint32_t *) __src)++; - *((unsigned char *) __tmp) = '\0'; - return __tmp; - - case 8: - *((__uint32_t *) __tmp)++ = *((__uint32_t *) __src)++; - case 4: - *((__uint32_t *) __tmp) = *((__uint32_t *) __src); - return __tmp + 3; - - case 6: - *((__uint32_t *) __tmp)++ = *((__uint32_t *) __src)++; - case 2: - *((__uint16_t *) __tmp) = *((__uint16_t *) __src); - return __tmp + 1; - - case 3: - *((__uint16_t *) __tmp)++ = *((__uint16_t *) __src)++; - case 1: - *((unsigned char *) __tmp) = '\0'; - return __tmp; - - default: - break; - } - /* This should never happen. */ - return NULL; -} +# if _STRING_ARCH_unaligned +# define __stpcpy_small(dest, src, srclen) \ + (__extension__ ({ char *__cp = (dest); \ + switch (srclen) \ + { \ + case 1: \ + *((unsigned char *) __cp) = '\0'; \ + break; \ + case 2: \ + *((__uint16_t *) __cp) = \ + __STRING2_SMALL_GET16 (src, 0); \ + ++__cp; \ + break; \ + case 3: \ + *((__uint16_t *) __cp)++ = \ + __STRING2_SMALL_GET16 (src, 0); \ + *((unsigned char *) __cp) = '\0'; \ + break; \ + case 4: \ + *((__uint32_t *) __cp) = \ + __STRING2_SMALL_GET32 (src, 0); \ + __cp += 3; \ + break; \ + case 5: \ + *((__uint32_t *) __cp)++ = \ + __STRING2_SMALL_GET32 (src, 0); \ + *((unsigned char *) __cp) = '\0'; \ + break; \ + case 6: \ + *((__uint32_t *) __cp)++ = \ + __STRING2_SMALL_GET32 (src, 0); \ + *((__uint16_t *) __cp) = \ + __STRING2_SMALL_GET16 (src, 4); \ + ++__cp; \ + break; \ + case 7: \ + *((__uint32_t *) __cp)++ = \ + __STRING2_SMALL_GET32 (src, 0); \ + *((__uint16_t *) __cp)++ = \ + __STRING2_SMALL_GET16 (src, 4); \ + *((unsigned char *) __cp) = '\0'; \ + break; \ + case 8: \ + *((__uint32_t *) __cp)++ = \ + __STRING2_SMALL_GET32 (src, 0); \ + *((__uint32_t *) __cp) = \ + __STRING2_SMALL_GET32 (src, 4); \ + __cp += 3; \ + break; \ + } \ + __cp; })) +# else +# define __stpcpy_small(dest, src, srclen) \ + (__extension__ ({ char *__cp = (dest); \ + switch (srclen) \ + { \ + case 1: \ + *((unsigned char *) __cp) = '\0'; \ + break; \ + case 2: \ + *((__STRING2_COPY_ARR2 *) __cp) = \ + ((__STRING2_COPY_ARR2) { { (src)[0], '\0' } }); \ + break; \ + case 3: \ + *((__STRING2_COPY_ARR3 *) __cp) = \ + ((__STRING2_COPY_ARR3) { { (src)[0], (src)[1], \ + '\0' } }); \ + break; \ + case 4: \ + *((__STRING2_COPY_ARR4 *) __cp) = \ + ((__STRING2_COPY_ARR4) { { (src)[0], (src)[1], \ + (src)[2], '\0' } }); \ + break; \ + case 5: \ + *((__STRING2_COPY_ARR5 *) __cp) = \ + ((__STRING2_COPY_ARR5) { { (src)[0], (src)[1], \ + (src)[2], (src)[3], \ + '\0' } }); \ + break; \ + case 6: \ + *((__STRING2_COPY_ARR6 *) __cp) = \ + ((__STRING2_COPY_ARR6) { { (src)[0], (src)[1], \ + (src)[2], (src)[3], \ + (src)[4], '\0' } }); \ + break; \ + case 7: \ + *((__STRING2_COPY_ARR7 *) __cp) = \ + ((__STRING2_COPY_ARR7) { { (src)[0], (src)[1], \ + (src)[2], (src)[3], \ + (src)[4], (src)[5], \ + '\0' } }); \ + break; \ + case 8: \ + *((__STRING2_COPY_ARR8 *) __cp) = \ + ((__STRING2_COPY_ARR8) { { (src)[0], (src)[1], \ + (src)[2], (src)[3], \ + (src)[4], (src)[5], \ + (src)[6], '\0' } }); \ + break; \ + } \ + __cp + ((srclen) - 1); })) +# endif # endif #endif @@ -157,7 +328,7 @@ __stpcpy_small (char *__dest, __const char *__src, size_t __srclen) ? (char *) memcpy (dest, src, n) \ : (memset (__mempcpy (dest, src, strlen (src)), '\0', \ n - strlen (src)), \ - dest)) \ + (char *) dest)) \ : strncpy (dest, src, n))) # else # define strncpy(dest, src, n) \ @@ -177,7 +348,7 @@ __stpcpy_small (char *__dest, __const char *__src, size_t __srclen) (__extension__ (__builtin_constant_p (src) && __builtin_constant_p (n) \ ? (strlen (src) < ((size_t) (n)) \ ? strcat (dest, src) \ - : (memcpy (strchr (dest, '\0'), src, n), dest)) \ + : (memcpy (strchr (dest, '\0'), src, n), (char *) dest)) \ : strncat (dest, src, n))) # else # define strncat(dest, src, n) \ @@ -205,15 +376,15 @@ __stpcpy_small (char *__dest, __const char *__src, size_t __srclen) consists entirely of characters not in REJECT. */ #ifndef _HAVE_STRING_ARCH_strcspn # define strcspn(s, reject) \ - (__extension__ (__builtin_constant_p (reject) \ - ? (((const char *) (reject))[0] == '\0' \ + (__extension__ (__builtin_constant_p (reject) && sizeof ((reject)[0]) == 1 \ + ? ((reject)[0] == '\0' \ ? strlen (s) \ - : (((const char *) (reject))[1] == '\0' \ - ? __strcspn_c1 (s, ((((const char *) (reject))[0] \ - & 0xff) << 8)) \ - : strcspn (s, reject))) \ + : ((reject)[1] == '\0' \ + ? __strcspn_c1 (s, (reject)[0]) \ + : strcspn (s, reject))) \ : strcspn (s, reject))) +__STRING_INLINE size_t __strcspn_c1 (__const char *__s, char __reject); __STRING_INLINE size_t __strcspn_c1 (__const char *__s, char __reject) { @@ -229,14 +400,15 @@ __strcspn_c1 (__const char *__s, char __reject) consists entirely of characters in ACCEPT. */ #ifndef _HAVE_STRING_ARCH_strspn # define strspn(s, accept) \ - (__extension__ (__builtin_constant_p (accept) \ - ? (((const char *) (accept))[0] == '\0' \ + (__extension__ (__builtin_constant_p (accept) && sizeof ((accept)[0]) == 1 \ + ? ((accept)[0] == '\0' \ ? 0 \ - : (((const char *) (accept))[1] == '\0' \ - ? __strspn_c1 (s, ((const char *) (accept))[0]) \ + : ((accept)[1] == '\0' \ + ? __strspn_c1 (s, (accept)[0]) \ : strspn (s, accept))) \ : strspn (s, accept))) +__STRING_INLINE size_t __strspn_c1 (__const char *__s, char __accept); __STRING_INLINE size_t __strspn_c1 (__const char *__s, char __accept) { @@ -252,11 +424,11 @@ __strspn_c1 (__const char *__s, char __accept) /* Find the first occurrence in S of any character in ACCEPT. */ #ifndef _HAVE_STRING_ARCH_strpbrk # define strpbrk(s, accept) \ - (__extension__ (__builtin_constant_p (accept) \ - ? (((const char *) (accept))[0] == '\0' \ + (__extension__ (__builtin_constant_p (accept) && sizeof ((accept)[0]) == 1 \ + ? ((accept)[0] == '\0' \ ? NULL \ - : (((const char *) (accept))[1] == '\0' \ - ? strchr (s, ((const char *) (accept))[0]) \ + : ((accept)[1] == '\0' \ + ? strchr (s, (accept)[0]) \ : strpbrk (s, accept))) \ : strpbrk (s, accept))) #endif @@ -265,11 +437,11 @@ __strspn_c1 (__const char *__s, char __accept) /* Find the first occurrence of NEEDLE in HAYSTACK. */ #ifndef _HAVE_STRING_ARCH_strstr # define strstr(haystack, needle) \ - (__extension__ (__builtin_constant_p (needle) \ - ? (((const char *) (needle))[0] == '\0' \ + (__extension__ (__builtin_constant_p (needle) && sizeof ((needle)[0]) == 1 \ + ? ((needle)[0] == '\0' \ ? haystack \ - : (((const char *) (needle))[1] == '\0' \ - ? strchr (haystack, ((const char *) (needle))[0]) \ + : ((needle)[1] == '\0' \ + ? strchr (haystack, (needle)[0]) \ : strstr (haystack, needle))) \ : strstr (haystack, needle))) #endif @@ -277,7 +449,8 @@ __strspn_c1 (__const char *__s, char __accept) #ifdef __USE_GNU # ifndef _HAVE_STRING_ARCH_strnlen -extern __inline size_t +__STRING_INLINE size_t strnlen (__const char *__string, size_t __maxlen); +__STRING_INLINE size_t strnlen (__const char *__string, size_t __maxlen) { __const char *__end = (__const char *) memchr (__string, '\0', __maxlen); @@ -287,6 +460,45 @@ strnlen (__const char *__string, size_t __maxlen) #endif +#ifdef __USE_BSD +# ifndef _HAVE_STRING_ARCH_strsep + +# define strsep(s, reject) \ + (__extension__ (__builtin_constant_p (reject) && sizeof ((reject)[0]) == 1 \ + ? ((reject)[0] != '\0' && (reject)[1] == '\0' \ + ? __strsep_1c (s, (reject)[0]) \ + : __strsep_g (s, reject)) \ + : __strsep_g (s, reject))) + +__STRING_INLINE char *__strsep_1c (char **__s, char __reject); +__STRING_INLINE char * +__strsep_1c (char **__s, char __reject) +{ + register __const char *__retval = *__s; + if (__retval == NULL || *__retval == '\0') + return NULL; + while (*__retval == __reject) + ++__retval; + if ((*__s = strchr (__retval, __reject)) != NULL) + *(*__s)++ = '\0'; + return (char *) __retval; +} + +__STRING_INLINE char *__strsep_g (char **__s, __const char *__reject); +__STRING_INLINE char * +__strsep_g (char **__s, __const char *__reject) +{ + register __const char *__retval = *__s; + if (__retval == NULL || *__retval == '\0') + return NULL; + if ((*__s = strpbrk (__retval, __reject)) != NULL) + *(*__s)++ = '\0'; + return (char *) __retval; +} +# endif +#endif + + #undef __STRING_INLINE -#endif /* bits/string2.h */ +#endif /* No string inlines. */ diff --git a/string/noinl-tester.c b/string/noinl-tester.c new file mode 100644 index 0000000000..2e994f73f9 --- /dev/null +++ b/string/noinl-tester.c @@ -0,0 +1,4 @@ +/* We don't want to test any of the inline functions here. */ + +#define __NO_STRING_INLINES 1 +#include "tester.c" diff --git a/string/string.h b/string/string.h index 560638be8e..e95d7cac96 100644 --- a/string/string.h +++ b/string/string.h @@ -200,12 +200,15 @@ extern char *__strerror_r __P ((int __errnum, char *__buf, size_t __buflen)); extern char *strerror_r __P ((int __errnum, char *__buf, size_t __buflen)); #endif +/* We define this function always since `bzero' is sometimes needed when + the namespace rules does not allow this. */ +extern void __bzero __P ((__ptr_t __s, size_t __n)); + #if defined __USE_BSD || defined __USE_XOPEN_EXTENDED /* Copy N bytes of SRC to DEST (like memmove, but args reversed). */ extern void bcopy __P ((__const __ptr_t __src, __ptr_t __dest, size_t __n)); /* Set N bytes of S to 0. */ -extern void __bzero __P ((__ptr_t __s, size_t __n)); extern void bzero __P ((__ptr_t __s, size_t __n)); /* Compare N bytes of S1 and S2 (same as memcmp). */ @@ -296,12 +299,12 @@ extern char *basename __P ((__const char *__filename)); code size significantly and which optimize mainly situations where one or more arguments are compile-time constants. These optimizations are used always when the compiler is - taught to optimized. */ + taught to optimized. -/* Get the machine-dependent optimizations if wanted. */ -# ifdef __USE_STRING_INLINES -# include -# endif + One can inhibit all optimizations by defining __NO_STRING_INLINES. */ + +/* Get the machine-dependent optimizations (if any). */ +# include /* These are generic optimizations which do not add too much inline code. */ # include diff --git a/string/tester.c b/string/tester.c index dfb1258864..ee36e12a6d 100644 --- a/string/tester.c +++ b/string/tester.c @@ -135,16 +135,64 @@ main (void) /* A closely related function is stpcpy. */ it = "stpcpy"; - check ((stpcpy (one, "abcde") - one) == 5, 1); - equal (one, "abcde", 2); + check ((stpcpy (one, "a") - one) == 1, 1); + equal (one, "a", 2); - check ((stpcpy (one, "x") - one) == 1, 3); - equal (one, "x", 4); /* Writeover. */ - equal (one+2, "cde", 5); /* Wrote too much? */ + check ((stpcpy (one, "ab") - one) == 2, 3); + equal (one, "ab", 4); - check ((stpcpy (stpcpy (stpcpy (one, "a"), "b"), "c") - one) == 3, 6); - equal (one, "abc", 7); - equal (one + 4, "e", 8); + check ((stpcpy (one, "abc") - one) == 3, 5); + equal (one, "abc", 6); + + check ((stpcpy (one, "abcd") - one) == 4, 7); + equal (one, "abcd", 8); + + check ((stpcpy (one, "abcde") - one) == 5, 9); + equal (one, "abcde", 10); + + check ((stpcpy (one, "abcdef") - one) == 6, 11); + equal (one, "abcdef", 12); + + check ((stpcpy (one, "abcdefg") - one) == 7, 13); + equal (one, "abcdefg", 14); + + check ((stpcpy (one, "abcdefgh") - one) == 8, 15); + equal (one, "abcdefgh", 16); + + check ((stpcpy (one, "abcdefghi") - one) == 9, 17); + equal (one, "abcdefghi", 18); + + check ((stpcpy (one, "x") - one) == 1, 19); + equal (one, "x", 20); /* Writeover. */ + equal (one+2, "cdefghi", 21); /* Wrote too much? */ + + check ((stpcpy (one, "xx") - one) == 2, 22); + equal (one, "xx", 23); /* Writeover. */ + equal (one+3, "defghi", 24); /* Wrote too much? */ + + check ((stpcpy (one, "xxx") - one) == 3, 25); + equal (one, "xxx", 26); /* Writeover. */ + equal (one+4, "efghi", 27); /* Wrote too much? */ + + check ((stpcpy (one, "xxxx") - one) == 4, 28); + equal (one, "xxxx", 29); /* Writeover. */ + equal (one+5, "fghi", 30); /* Wrote too much? */ + + check ((stpcpy (one, "xxxxx") - one) == 5, 31); + equal (one, "xxxxx", 32); /* Writeover. */ + equal (one+6, "ghi", 33); /* Wrote too much? */ + + check ((stpcpy (one, "xxxxxx") - one) == 6, 34); + equal (one, "xxxxxx", 35); /* Writeover. */ + equal (one+7, "hi", 36); /* Wrote too much? */ + + check ((stpcpy (one, "xxxxxxx") - one) == 7, 37); + equal (one, "xxxxxxx", 38); /* Writeover. */ + equal (one+8, "i", 39); /* Wrote too much? */ + + check ((stpcpy (stpcpy (stpcpy (one, "a"), "b"), "c") - one) == 3, 40); + equal (one, "abc", 41); + equal (one + 4, "xxx", 42); /* stpncpy. */ it = "stpncpy"; diff --git a/sysdeps/alpha/bzero.S b/sysdeps/alpha/bzero.S index b70ade6a6d..1e0792395b 100644 --- a/sysdeps/alpha/bzero.S +++ b/sysdeps/alpha/bzero.S @@ -78,7 +78,7 @@ $tail: bne t4, 1f # is there a tail to do? .end bzero_loop -ENTRY(bzero) +ENTRY(__bzero) #ifdef PROF ldgp gp, 0(pv) lda AT, _mcount @@ -117,3 +117,4 @@ $oneq: $done: ret END(bzero) +weak_alias (__bzero, bzero) diff --git a/sysdeps/generic/bits/select.h b/sysdeps/generic/bits/select.h index 7803335499..8487e21bb3 100644 --- a/sysdeps/generic/bits/select.h +++ b/sysdeps/generic/bits/select.h @@ -21,15 +21,14 @@ #endif -/* This line MUST be split! Otherwise m4 will not change it. - - We don't use `memset' because this would require a prototype and +/* We don't use `memset' because this would require a prototype and the array isn't too big. */ #define __FD_ZERO(set) \ do { \ unsigned int __i; \ + __fd_mask *__arr = (set); \ for (__i = 0; __i < sizeof (__fd_set) / sizeof (__fd_mask); ++__i) \ - ((__fd_mask *) set)[__i] = '\0'; \ + __arr->fds_bits[__i] = '\0'; \ } while (0) #define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d)) #define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d)) diff --git a/sysdeps/generic/bzero.c b/sysdeps/generic/bzero.c index 7fda7c3b5e..002af2f0a3 100644 --- a/sysdeps/generic/bzero.c +++ b/sysdeps/generic/bzero.c @@ -22,7 +22,7 @@ /* Set N bytes of S to 0. */ void -bzero (s, len) +__bzero (s, len) void *s; size_t len; { @@ -78,3 +78,4 @@ bzero (s, len) len -= 1; } } +weak_alias (__bzero, bzero) diff --git a/sysdeps/generic/stpcpy.c b/sysdeps/generic/stpcpy.c index 0bf84cc700..e9de98ea7a 100644 --- a/sysdeps/generic/stpcpy.c +++ b/sysdeps/generic/stpcpy.c @@ -22,6 +22,9 @@ #include +#undef __stpcpy +#undef stpcpy + #ifndef weak_alias # define __stpcpy stpcpy #endif diff --git a/sysdeps/generic/sysd-stdio.c b/sysdeps/generic/sysd-stdio.c index 9818f84c5c..da8ed20bed 100644 --- a/sysdeps/generic/sysd-stdio.c +++ b/sysdeps/generic/sysd-stdio.c @@ -28,10 +28,10 @@ /* Read N bytes into BUF from COOKIE. */ int -__stdio_read (void *cookie, char *buf, size_t n;) +__stdio_read (void *cookie, char *buf, size_t n) { const int fd = (int) cookie; -#if defined (EINTR) && defined (EINTR_REPEAT) +#if defined EINTR && defined EINTR_REPEAT int save = errno; int nread; @@ -70,7 +70,7 @@ __stdio_write (void *cookie, const char *buf, size_t n) n -= count; } else if (count < 0 -#if defined (EINTR) && defined (EINTR_REPEAT) +#if defined EINTR && defined EINTR_REPEAT && errno != EINTR #endif ) diff --git a/sysdeps/i386/bits/select.h b/sysdeps/i386/bits/select.h index edcb562945..34d2b0b27a 100644 --- a/sysdeps/i386/bits/select.h +++ b/sysdeps/i386/bits/select.h @@ -58,8 +58,9 @@ # define __FD_ZERO(set) \ do { \ unsigned int __i; \ + __fd_mask *__arr = (set); \ for (__i = 0; __i < sizeof (__fd_set) / sizeof (__fd_mask); ++__i) \ - ((__fd_mask *) set)[__i] = 0; \ + __arr->fds_bits[__i] = 0; \ } while (0) # define __FD_SET(d, set) ((set)->fds_bits[__FDELT (d)] |= __FDMASK (d)) # define __FD_CLR(d, set) ((set)->fds_bits[__FDELT (d)] &= ~__FDMASK (d)) diff --git a/sysdeps/i386/bits/string.h b/sysdeps/i386/bits/string.h index 2931684781..c6deb2b6a4 100644 --- a/sysdeps/i386/bits/string.h +++ b/sysdeps/i386/bits/string.h @@ -18,11 +18,17 @@ Boston, MA 02111-1307, USA. */ #ifndef _STRING_H -#error "Never use directly; include instead." +# error "Never use directly; include instead." #endif -/* We only provide optimizations for the GNU CC. */ -#if defined __GNUC__ && __GNUC__ >= 2 +/* The ix86 processors can access unaligned multi-byte variables. */ +#define _STRING_ARCH_unaligned 1 + + +/* We only provide optimizations if the user selects them and if + GNU CC is used. */ +#if !defined __NO_STRING_INLINES && defined __USE_STRING_INLINES \ + && defined __GNUC__ && __GNUC__ >= 2 #ifdef __cplusplus # define __STRING_INLINE inline @@ -741,4 +747,4 @@ strstr (__const char *__haystack, __const char *__needle) #undef __STRING_INLINE -#endif /* GNU CC */ +#endif /* use string inlines && GNU CC */ diff --git a/sysdeps/i386/bzero.c b/sysdeps/i386/bzero.c index 5cc5989f90..99f2352dc6 100644 --- a/sysdeps/i386/bzero.c +++ b/sysdeps/i386/bzero.c @@ -26,7 +26,7 @@ #ifdef __GNUC__ void -bzero (dstpp, len) +__bzero (dstpp, len) void *dstpp; size_t len; { @@ -75,6 +75,7 @@ bzero (dstpp, len) "0" (dstp), "c" (len), "a" (x) : "cx"); } +weak_alias (__bzero, bzero) #else #include diff --git a/sysdeps/i386/fpu/bits/mathinline.h b/sysdeps/i386/fpu/bits/mathinline.h index 55e9171459..edb6ee01d7 100644 --- a/sysdeps/i386/fpu/bits/mathinline.h +++ b/sysdeps/i386/fpu/bits/mathinline.h @@ -18,8 +18,9 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#ifndef _BITS_MATHINLINE_H -#define _BITS_MATHINLINE_H 1 +#ifndef _MATH_H +# error "Never use directly; include instead." +#endif #if defined __USE_ISOC9X && defined __GNUC__ && __GNUC__ >= 2 @@ -518,7 +519,7 @@ __finite (double __x) ("orl $0x800fffff, %0\n\t" "incl %0\n\t" "shrl $31, %0" - : "=q" (__result) : "0" (((int *) &__x)[1]) : "cc"); + : "=r" (__result) : "0" (((int *) &__x)[1]) : "cc"); return __result; } @@ -542,5 +543,3 @@ __inline_mathcode (__acosh1p, __x, \ #endif /* Not gcc <= 2.7. */ #endif /* __NO_MATH_INLINES */ #endif /* __GNUC__ */ - -#endif /* _BITS_MATHINLINE_H */ diff --git a/sysdeps/i386/i486/atomicity.h b/sysdeps/i386/i486/atomicity.h index 98a2531365..7157bc33d8 100644 --- a/sysdeps/i386/i486/atomicity.h +++ b/sysdeps/i386/i486/atomicity.h @@ -1,4 +1,4 @@ -/* Low-level functions for atomitc operations. ix86 version, x >= 4. +/* Low-level functions for atomic operations. ix86 version, x >= 4. Copyright (C) 1997 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -41,7 +41,7 @@ atomic_add (volatile uint32_t *mem, int val) : : "ir" (val), "m" (*mem) : "memory"); } -static inline int +static inline char __attribute__ ((unused)) compare_and_swap (volatile long int *p, long int oldval, long int newval) { diff --git a/sysdeps/i386/i486/bits/string.h b/sysdeps/i386/i486/bits/string.h index 770f5c1e15..5e4abbc3e5 100644 --- a/sysdeps/i386/i486/bits/string.h +++ b/sysdeps/i386/i486/bits/string.h @@ -18,11 +18,17 @@ Boston, MA 02111-1307, USA. */ #ifndef _STRING_H -#error "Never use directly; include instead." +# error "Never use directly; include instead." #endif -/* We only provide optimizations for the GNU CC. */ -#if defined __GNUC__ && __GNUC__ >= 2 +/* The ix86 processors can access unaligned multi-byte variables. */ +#define _STRING_ARCH_unaligned 1 + + +/* We only provide optimizations if the user selects them and if + GNU CC is used. */ +#if !defined __NO_STRING_INLINES && defined __USE_STRING_INLINES \ + && defined __GNUC__ && __GNUC__ >= 2 #ifdef __cplusplus # define __STRING_INLINE inline @@ -30,6 +36,13 @@ # define __STRING_INLINE extern __inline #endif +/* The macros are used in some of the optimized implementations below. */ +#define __STRING_SMALL_GET16(src, idx) \ + (((src)[idx + 1] << 8) | (src)[idx]) +#define __STRING_SMALL_GET32(src, idx) \ + ((((src)[idx + 3] << 8 | (src)[idx + 2]) << 8 \ + | (src)[idx + 1]) << 8 | (src)[idx]) + /* Copy N bytes of SRC to DEST. */ #define _HAVE_STRING_ARCH_memcpy 1 @@ -355,9 +368,59 @@ __strlen_g (__const char *__str) #define _HAVE_STRING_ARCH_strcpy 1 #define strcpy(dest, src) \ (__extension__ (__builtin_constant_p (src) \ - ? (char *) memcpy (dest, src, strlen (src) + 1) \ + ? (sizeof (src[0]) == 1 && strlen (src) + 1 <= 8 \ + ? __strcpy_small (dest, src, strlen (src) + 1) \ + : (char *) memcpy (dest, src, strlen (src) + 1)) \ : __strcpy_g (dest, src))) +# define __strcpy_small(dest, src, srclen) \ + (__extension__ ({ char *__retval = (dest); \ + char *__cp = __retval; \ + switch (srclen) \ + { \ + case 1: \ + *((unsigned char *) __cp) = '\0'; \ + break; \ + case 2: \ + *((__uint16_t *) __cp) = \ + __STRING_SMALL_GET16 (src, 0); \ + break; \ + case 3: \ + *((__uint16_t *) __cp)++ = \ + __STRING_SMALL_GET16 (src, 0); \ + *((unsigned char *) __cp) = '\0'; \ + break; \ + case 4: \ + *((__uint32_t *) __cp) = \ + __STRING_SMALL_GET32 (src, 0); \ + break; \ + case 5: \ + *((__uint32_t *) __cp)++ = \ + __STRING_SMALL_GET32 (src, 0); \ + *((unsigned char *) __cp) = '\0'; \ + break; \ + case 6: \ + *((__uint32_t *) __cp)++ = \ + __STRING_SMALL_GET32 (src, 0); \ + *((__uint16_t *) __cp) = \ + __STRING_SMALL_GET16 (src, 4); \ + break; \ + case 7: \ + *((__uint32_t *) __cp)++ = \ + __STRING_SMALL_GET32 (src, 0); \ + *((__uint16_t *) __cp)++ = \ + __STRING_SMALL_GET16 (src, 4); \ + *((unsigned char *) __cp) = '\0'; \ + break; \ + case 8: \ + *((__uint32_t *) __cp)++ = \ + __STRING_SMALL_GET32 (src, 0); \ + *((__uint32_t *) __cp) = \ + __STRING_SMALL_GET32 (src, 4); \ + break; \ + } \ + __retval; })) + __STRING_INLINE char * __strcpy_g (char *__dest, __const char *__src) { @@ -398,43 +461,56 @@ __strcpy_g (char *__dest, __const char *__src) /* In glibc itself we use this symbol for namespace reasons. */ # define stpcpy(dest, src) __stpcpy (dest, src) -__STRING_INLINE char * -__stpcpy_small (char *__dest, __const char __src[], size_t __srclen) -{ - register char *__tmp = __dest; - switch (__srclen) - { - case 7: - *((unsigned short int *) __tmp)++ = *((unsigned short int *) __src)++; - case 5: - *((unsigned int *) __tmp)++ = *((unsigned int *) __src)++; - *((unsigned char *) __tmp) = '\0'; - return __tmp; - - case 8: - *((unsigned int *) __tmp)++ = *((unsigned int *) __src)++; - case 4: - *((unsigned int *) __tmp) = *((unsigned int *) __src); - return __tmp + 3; - - case 6: - *((unsigned int *) __tmp)++ = *((unsigned int *) __src)++; - case 2: - *((unsigned short int *) __tmp) = *((unsigned short int *) __src); - return __tmp + 1; - - case 3: - *((unsigned short int *) __tmp)++ = *((unsigned short int *) __src)++; - case 1: - *((unsigned char *) __tmp) = '\0'; - return __tmp; - - default: - break; - } - /* This should never happen. */ - return NULL; -} +# define __stpcpy_small(dest, src, srclen) \ + (__extension__ ({ char *__cp = (dest); \ + switch (srclen) \ + { \ + case 1: \ + *((unsigned char *) __cp) = '\0'; \ + break; \ + case 2: \ + *((__uint16_t *) __cp) = \ + __STRING_SMALL_GET16 (src, 0); \ + ++cp; \ + break; \ + case 3: \ + *((__uint16_t *) __cp)++ = \ + __STRING_SMALL_GET16 (src, 0); \ + *((unsigned char *) __cp) = '\0'; \ + break; \ + case 4: \ + *((__uint32_t *) __cp) = \ + __STRING_SMALL_GET32 (src, 0); \ + cp += 3; \ + break; \ + case 5: \ + *((__uint32_t *) __cp)++ = \ + __STRING_SMALL_GET32 (src, 0); \ + *((unsigned char *) __cp) = '\0'; \ + break; \ + case 6: \ + *((__uint32_t *) __cp)++ = \ + __STRING_SMALL_GET32 (src, 0); \ + *((__uint16_t *) __cp) = \ + __STRING_SMALL_GET16 (src, 4); \ + ++cp; \ + break; \ + case 7: \ + *((__uint32_t *) __cp)++ = \ + __STRING_SMALL_GET32 (src, 0); \ + *((__uint16_t *) __cp)++ = \ + __STRING_SMALL_GET16 (src, 4); \ + *((unsigned char *) __cp) = '\0'; \ + break; \ + case 8: \ + *((__uint32_t *) __cp)++ = \ + __STRING_SMALL_GET32 (src, 0); \ + *((__uint32_t *) __cp) = \ + __STRING_SMALL_GET32 (src, 4); \ + cp += 3; \ + break; \ + } \ + __cp; })) __STRING_INLINE char * __mempcpy_by4 (char *__dest, __const char *__src, size_t __srclen) @@ -1458,4 +1534,4 @@ __strstr_g (__const char *__haystack, __const char *__needle) #undef __STRING_INLINE -#endif /* GNU CC */ +#endif /* use string inlines && GNU CC */ diff --git a/sysdeps/i386/i586/bzero.S b/sysdeps/i386/i586/bzero.S index 2c75103492..84d2f709c1 100644 --- a/sysdeps/i386/i586/bzero.S +++ b/sysdeps/i386/i586/bzero.S @@ -1,2 +1,3 @@ -#define memset bzero +#define memset __bzero #include +weak_alias (__bzero, bzero) diff --git a/sysdeps/m68k/m68020/atomicity.h b/sysdeps/m68k/m68020/atomicity.h new file mode 100644 index 0000000000..d74b8194ad --- /dev/null +++ b/sysdeps/m68k/m68020/atomicity.h @@ -0,0 +1,65 @@ +/* Low-level functions for atomic operations. m680x0 version, x >= 2. + Copyright (C) 1997 Free Software Foundation, Inc. + Contributed by Andreas Schwab . + + 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. */ + +#ifndef _ATOMICITY_H +#define _ATOMICITY_H 1 + +#include + + +static inline int +__attribute__ ((unused)) +exchange_and_add (volatile uint32_t *mem, int val) +{ + register int result = *mem; + register int temp; + __asm__ __volatile__ ("1: move%.l %0,%1;" + " add%.l %2,%1;" + " cas%.l %0,%1,%3;" + " jbne 1b" + : "=d" (result), "=&d" (temp) + : "d" (val), "m" (*mem), "0" (result) : "memory"); + return result; +} + +static inline void +__attribute__ ((unused)) +atomic_add (volatile uint32_t *mem, int val) +{ + /* XXX Use cas here as well? */ + __asm__ __volatile__ ("add%.l %0,%1" + : : "ir" (val), "m" (*mem) : "memory"); +} + +static inline int +__attribute__ ((unused)) +compare_and_swap (volatile long int *p, long int oldval, long int newval) +{ + char ret; + long int readval; + + __asm__ __volatile__ ("cas%.l %2,%3,%1; seq %0" + : "=dm" (ret), "=m" (*p), "=d" (readval) + : "d" (newval), "m" (*p), "2" (oldval)); + return ret; +} + +#endif /* atomicity.h */ diff --git a/sysdeps/stub/atomicity.h b/sysdeps/stub/atomicity.h index 3916eebbcf..e9edc83a8d 100644 --- a/sysdeps/stub/atomicity.h +++ b/sysdeps/stub/atomicity.h @@ -1,4 +1,4 @@ -/* Low-level functions for atomitc operations. ix86 version, x >= 4. +/* Low-level functions for atomitc operations. Stub version. Copyright (C) 1997 Free Software Foundation, Inc. This file is part of the GNU C Library. diff --git a/sysdeps/unix/inet/Subdirs b/sysdeps/unix/inet/Subdirs index 5043651cc5..647ec6a4a6 100644 --- a/sysdeps/unix/inet/Subdirs +++ b/sysdeps/unix/inet/Subdirs @@ -1,4 +1,5 @@ inet resolv +hesiod sunrpc nis diff --git a/sysdeps/vax/bzero.s b/sysdeps/vax/bzero.s index 5f90763d41..dff59ba667 100644 --- a/sysdeps/vax/bzero.s +++ b/sysdeps/vax/bzero.s @@ -39,7 +39,7 @@ #include "DEFS.h" -ENTRY(bzero, 0) +ENTRY(__bzero, 0) movl 4(ap),r3 jbr 2f 1: @@ -51,3 +51,4 @@ ENTRY(bzero, 0) jgtr 1b movc5 $0,(r3),$0,8(ap),(r3) ret +weak_alias (__bzero, bzero)