gsasl-commit
[Top][All Lists]
Advanced

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

[SCM] GNU gsasl branch, master, updated. gsasl-1-2-49-gdfbe103


From: Simon Josefsson
Subject: [SCM] GNU gsasl branch, master, updated. gsasl-1-2-49-gdfbe103
Date: Thu, 10 Sep 2009 07:28:55 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU gsasl".

http://git.savannah.gnu.org/cgit/gsasl.git/commit/?id=dfbe103de0e51f9ed9a3ef365559e562cff054dc

The branch, master has been updated
       via  dfbe103de0e51f9ed9a3ef365559e562cff054dc (commit)
       via  e28d78fa3cbd8908c8f37266c3ca0e7b67fde52a (commit)
       via  2e53291847c0e16464ba0b86b5895deaacb83222 (commit)
       via  372d48eca332cd12a328b56037730573566978b9 (commit)
       via  4307c4b0f0e6079eebeef23aec05bd4551a5cb6b (commit)
      from  0a0978edc55f61bdda776c3122eb20846618423c (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit dfbe103de0e51f9ed9a3ef365559e562cff054dc
Author: Simon Josefsson <address@hidden>
Date:   Thu Sep 10 09:28:42 2009 +0200

    Add gnulib strchrnul module.

commit e28d78fa3cbd8908c8f37266c3ca0e7b67fde52a
Author: Simon Josefsson <address@hidden>
Date:   Thu Sep 10 09:27:17 2009 +0200

    Add gnulib strchrnul module.

commit 2e53291847c0e16464ba0b86b5895deaacb83222
Author: Simon Josefsson <address@hidden>
Date:   Thu Sep 10 09:26:15 2009 +0200

    Add gnulib strchrnul module.

commit 372d48eca332cd12a328b56037730573566978b9
Author: Simon Josefsson <address@hidden>
Date:   Thu Sep 10 09:25:47 2009 +0200

    Parse more.

commit 4307c4b0f0e6079eebeef23aec05bd4551a5cb6b
Author: Simon Josefsson <address@hidden>
Date:   Thu Sep 10 09:11:06 2009 +0200

    Make it build.

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

Summary of changes:
 gl/Makefile.am               |    3 +-
 gl/m4/string_h.m4            |    4 +-
 gl/m4/unistd_h.m4            |    3 +-
 gl/m4/wctype.m4              |   13 +++-
 gl/string.in.h               |    4 +-
 gl/unistd.in.h               |    5 +-
 gl/wctype.in.h               |   31 +++++++++
 lib/gl/Makefile.am           |   23 ++++++-
 lib/gl/m4/gnulib-cache.m4    |    3 +-
 lib/gl/m4/gnulib-comp.m4     |   12 ++++
 lib/gl/m4/rawmemchr.m4       |   21 ++++++
 lib/gl/m4/strchrnul.m4       |   21 ++++++
 lib/gl/m4/string_h.m4        |    4 +-
 lib/gl/m4/unistd_h.m4        |    3 +-
 lib/gl/rawmemchr.c           |  136 ++++++++++++++++++++++++++++++++++++++++
 lib/gl/rawmemchr.valgrind    |   12 ++++
 lib/gl/strchrnul.c           |  142 ++++++++++++++++++++++++++++++++++++++++++
 lib/gl/strchrnul.valgrind    |   12 ++++
 lib/gl/string.in.h           |    4 +-
 lib/gl/unistd.in.h           |    5 +-
 lib/gltests/Makefile.am      |   16 +++++
 lib/gltests/test-rawmemchr.c |   84 +++++++++++++++++++++++++
 lib/gltests/test-strchrnul.c |   94 ++++++++++++++++++++++++++++
 lib/scram/parser.c           |   85 ++++++++++++++++++++++++-
 tests/scram.c                |    1 +
 25 files changed, 721 insertions(+), 20 deletions(-)
 create mode 100644 lib/gl/m4/rawmemchr.m4
 create mode 100644 lib/gl/m4/strchrnul.m4
 create mode 100644 lib/gl/rawmemchr.c
 create mode 100644 lib/gl/rawmemchr.valgrind
 create mode 100644 lib/gl/strchrnul.c
 create mode 100644 lib/gl/strchrnul.valgrind
 create mode 100644 lib/gltests/test-rawmemchr.c
 create mode 100644 lib/gltests/test-strchrnul.c

diff --git a/gl/Makefile.am b/gl/Makefile.am
index d73b6a1..1f12d47 100644
--- a/gl/Makefile.am
+++ b/gl/Makefile.am
@@ -1112,7 +1112,6 @@ string.h: string.in.h
              -e 's|@''HAVE_STPNCPY''@|$(HAVE_STPNCPY)|g' \
              -e 's|@''HAVE_STRCHRNUL''@|$(HAVE_STRCHRNUL)|g' \
              -e 's|@''HAVE_DECL_STRDUP''@|$(HAVE_DECL_STRDUP)|g' \
-             -e 's|@''HAVE_STRNDUP''@|$(HAVE_STRNDUP)|g' \
              -e 's|@''HAVE_DECL_STRNDUP''@|$(HAVE_DECL_STRNDUP)|g' \
              -e 's|@''HAVE_DECL_STRNLEN''@|$(HAVE_DECL_STRNLEN)|g' \
              -e 's|@''HAVE_STRPBRK''@|$(HAVE_STRPBRK)|g' \
@@ -1128,6 +1127,7 @@ string.h: string.in.h
              -e 's|@''REPLACE_STRDUP''@|$(REPLACE_STRDUP)|g' \
              -e 's|@''REPLACE_STRSTR''@|$(REPLACE_STRSTR)|g' \
              -e 's|@''REPLACE_STRERROR''@|$(REPLACE_STRERROR)|g' \
+             -e 's|@''REPLACE_STRNDUP''@|$(REPLACE_STRNDUP)|g' \
              -e 's|@''REPLACE_STRSIGNAL''@|$(REPLACE_STRSIGNAL)|g' \
              -e 's|@''REPLACE_STRTOK_R''@|$(REPLACE_STRTOK_R)|g' \
              -e 's|@''UNDEFINE_STRTOK_R''@|$(UNDEFINE_STRTOK_R)|g' \
@@ -1314,6 +1314,7 @@ unistd.h: unistd.in.h
              -e 's|@''REPLACE_GETCWD''@|$(REPLACE_GETCWD)|g' \
              -e 's|@''REPLACE_GETPAGESIZE''@|$(REPLACE_GETPAGESIZE)|g' \
              -e 's|@''REPLACE_LCHOWN''@|$(REPLACE_LCHOWN)|g' \
+             -e 's|@''REPLACE_LINK''@|$(REPLACE_LINK)|g' \
              -e 's|@''REPLACE_LSEEK''@|$(REPLACE_LSEEK)|g' \
              -e 's|@''REPLACE_WRITE''@|$(REPLACE_WRITE)|g' \
              -e 
's|@''UNISTD_H_HAVE_WINSOCK2_H''@|$(UNISTD_H_HAVE_WINSOCK2_H)|g' \
diff --git a/gl/m4/string_h.m4 b/gl/m4/string_h.m4
index 3dbbfe1..edc5c6e 100644
--- a/gl/m4/string_h.m4
+++ b/gl/m4/string_h.m4
@@ -5,7 +5,7 @@
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 8
+# serial 9
 
 # Written by Paul Eggert.
 
@@ -74,7 +74,6 @@ AC_DEFUN([gl_HEADER_STRING_H_DEFAULTS],
   HAVE_STPNCPY=1;              AC_SUBST([HAVE_STPNCPY])
   HAVE_STRCHRNUL=1;            AC_SUBST([HAVE_STRCHRNUL])
   HAVE_DECL_STRDUP=1;          AC_SUBST([HAVE_DECL_STRDUP])
-  HAVE_STRNDUP=1;              AC_SUBST([HAVE_STRNDUP])
   HAVE_DECL_STRNDUP=1;         AC_SUBST([HAVE_DECL_STRNDUP])
   HAVE_DECL_STRNLEN=1;         AC_SUBST([HAVE_DECL_STRNLEN])
   HAVE_STRPBRK=1;              AC_SUBST([HAVE_STRPBRK])
@@ -90,6 +89,7 @@ AC_DEFUN([gl_HEADER_STRING_H_DEFAULTS],
   REPLACE_STRSTR=0;            AC_SUBST([REPLACE_STRSTR])
   REPLACE_STRCASESTR=0;                AC_SUBST([REPLACE_STRCASESTR])
   REPLACE_STRERROR=0;          AC_SUBST([REPLACE_STRERROR])
+  REPLACE_STRNDUP=0;           AC_SUBST([REPLACE_STRNDUP])
   REPLACE_STRSIGNAL=0;         AC_SUBST([REPLACE_STRSIGNAL])
   REPLACE_STRTOK_R=0;          AC_SUBST([REPLACE_STRTOK_R])
   UNDEFINE_STRTOK_R=0;         AC_SUBST([UNDEFINE_STRTOK_R])
diff --git a/gl/m4/unistd_h.m4 b/gl/m4/unistd_h.m4
index 84f0755..7347e38 100644
--- a/gl/m4/unistd_h.m4
+++ b/gl/m4/unistd_h.m4
@@ -1,4 +1,4 @@
-# unistd_h.m4 serial 24
+# unistd_h.m4 serial 25
 dnl Copyright (C) 2006-2009 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -94,6 +94,7 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS],
   REPLACE_GETCWD=0;       AC_SUBST([REPLACE_GETCWD])
   REPLACE_GETPAGESIZE=0;  AC_SUBST([REPLACE_GETPAGESIZE])
   REPLACE_LCHOWN=0;       AC_SUBST([REPLACE_LCHOWN])
+  REPLACE_LINK=0;         AC_SUBST([REPLACE_LINK])
   REPLACE_LSEEK=0;        AC_SUBST([REPLACE_LSEEK])
   REPLACE_WRITE=0;        AC_SUBST([REPLACE_WRITE])
   UNISTD_H_HAVE_WINSOCK2_H=0; AC_SUBST([UNISTD_H_HAVE_WINSOCK2_H])
diff --git a/gl/m4/wctype.m4 b/gl/m4/wctype.m4
index 6a1b6f0..1eb55a4 100644
--- a/gl/m4/wctype.m4
+++ b/gl/m4/wctype.m4
@@ -1,4 +1,4 @@
-# wctype.m4 serial 2
+# wctype.m4 serial 3
 
 dnl A placeholder for ISO C99 <wctype.h>, for platforms that lack it.
 
@@ -12,6 +12,7 @@ dnl Written by Paul Eggert.
 AC_DEFUN([gl_WCTYPE_H],
 [
   AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST])
   AC_CHECK_FUNCS_ONCE([iswcntrl])
   if test $ac_cv_func_iswcntrl = yes; then
     HAVE_ISWCNTRL=1
@@ -52,7 +53,15 @@ AC_DEFUN([gl_WCTYPE_H],
             ])
         ])
       if test $gl_cv_func_iswcntrl_works = yes; then
-        WCTYPE_H=
+        case "$host_os" in
+          mingw*)
+            dnl On mingw, towlower and towupper return random high 16 bits.
+            ;;
+          *)
+            dnl iswcntrl works. towlower and towupper work as well.
+            WCTYPE_H=
+            ;;
+        esac
       fi
     fi
     dnl Compute NEXT_WCTYPE_H even if WCTYPE_H is empty,
diff --git a/gl/string.in.h b/gl/string.in.h
index 8d48e4d..3d0c7d1 100644
--- a/gl/string.in.h
+++ b/gl/string.in.h
@@ -203,11 +203,11 @@ extern char *strdup (char const *__s);
 
 /* Return a newly allocated copy of at most N bytes of STRING.  */
 #if @GNULIB_STRNDUP@
-# if ! @HAVE_STRNDUP@
+# if @REPLACE_STRNDUP@
 #  undef strndup
 #  define strndup rpl_strndup
 # endif
-# if ! @HAVE_STRNDUP@ || ! @HAVE_DECL_STRNDUP@
+# if @REPLACE_STRNDUP@ || ! @HAVE_DECL_STRNDUP@
 extern char *strndup (char const *__string, size_t __n);
 # endif
 #elif defined GNULIB_POSIXCHECK
diff --git a/gl/unistd.in.h b/gl/unistd.in.h
index d509aaa..c749cbe 100644
--- a/gl/unistd.in.h
+++ b/gl/unistd.in.h
@@ -595,11 +595,14 @@ extern int lchown (char const *file, uid_t owner, gid_t 
group);
 
 
 #if @GNULIB_LINK@
+# if @REPLACE_LINK@
+#  define link rpl_link
+# endif
 /* Create a new hard link for an existing file.
    Return 0 if successful, otherwise -1 and errno set.
    See POSIX:2001 specification
    <http://www.opengroup.org/susv3xsh/link.html>.  */
-# if address@hidden@
+# if address@hidden@ || @REPLACE_LINK@
 extern int link (const char *path1, const char *path2);
 # endif
 #elif defined GNULIB_POSIXCHECK
diff --git a/gl/wctype.in.h b/gl/wctype.in.h
index 1106b3f..71df686 100644
--- a/gl/wctype.in.h
+++ b/gl/wctype.in.h
@@ -196,5 +196,36 @@ towupper (wint_t wc)
 
 # endif /* ! HAVE_ISWCNTRL */
 
+# if defined __MINGW32__
+
+/* On native Windows, wchar_t is uint16_t, and wint_t is uint32_t.
+   The functions towlower and towupper are implemented in the MSVCRT library
+   to take a wchar_t argument and return a wchar_t result.  mingw declares
+   these functions to take a wint_t argument and return a wint_t result.
+   This means that:
+   1. When the user passes an argument outside the range 0x0000..0xFFFF, the
+      function will look only at the lower 16 bits.  This is allowed according
+      to POSIX.
+   2. The return value is returned in the lower 16 bits of the result register.
+      The upper 16 bits are random: whatever happened to be in that part of the
+      result register.  We need to fix this by adding a zero-extend from
+      wchar_t to wint_t after the call.  */
+
+static inline wint_t
+rpl_towlower (wint_t wc)
+{
+  return (wint_t) (wchar_t) towlower (wc);
+}
+#  define towlower rpl_towlower
+
+static inline wint_t
+rpl_towupper (wint_t wc)
+{
+  return (wint_t) (wchar_t) towupper (wc);
+}
+#  define towupper rpl_towupper
+
+# endif
+
 #endif /* _GL_WCTYPE_H */
 #endif /* _GL_WCTYPE_H */
diff --git a/lib/gl/Makefile.am b/lib/gl/Makefile.am
index 84f1cdb..3f3adc1 100644
--- a/lib/gl/Makefile.am
+++ b/lib/gl/Makefile.am
@@ -9,7 +9,7 @@
 # the same distribution terms as the rest of that program.
 #
 # Generated by gnulib-tool.
-# Reproduce by: gnulib-tool --import --dir=. --local-dir=gl/override 
--lib=libgl --source-base=gl --m4-base=gl/m4 --doc-base=doc 
--tests-base=gltests --aux-dir=build-aux --with-tests 
--avoid=vc-list-files-tests --lgpl=2 --libtool --macro-prefix=gl --no-vc-files 
base64 crypto/gc crypto/gc-hmac-md5 crypto/gc-hmac-md5-tests crypto/gc-md5 
crypto/gc-md5-tests crypto/gc-random crypto/gc-tests getline gettext 
lib-msvc-compat lib-symbol-versions lib-symbol-visibility maintainer-makefile 
minmax strverscmp vasprintf
+# Reproduce by: gnulib-tool --import --dir=. --local-dir=gl/override 
--lib=libgl --source-base=gl --m4-base=gl/m4 --doc-base=doc 
--tests-base=gltests --aux-dir=build-aux --with-tests 
--avoid=vc-list-files-tests --lgpl=2 --libtool --macro-prefix=gl --no-vc-files 
base64 crypto/gc crypto/gc-hmac-md5 crypto/gc-hmac-md5-tests crypto/gc-md5 
crypto/gc-md5-tests crypto/gc-random crypto/gc-tests getline gettext 
lib-msvc-compat lib-symbol-versions lib-symbol-visibility maintainer-makefile 
minmax strchrnul strverscmp vasprintf
 
 AUTOMAKE_OPTIONS = 1.5 gnits
 
@@ -246,6 +246,15 @@ libgl_la_SOURCES += minmax.h
 
 ## end   gnulib module minmax
 
+## begin gnulib module rawmemchr
+
+
+EXTRA_DIST += rawmemchr.c rawmemchr.valgrind
+
+EXTRA_libgl_la_SOURCES += rawmemchr.c
+
+## end   gnulib module rawmemchr
+
 ## begin gnulib module realloc-posix
 
 
@@ -502,6 +511,15 @@ EXTRA_DIST += stdlib.in.h
 
 ## end   gnulib module stdlib
 
+## begin gnulib module strchrnul
+
+
+EXTRA_DIST += strchrnul.c strchrnul.valgrind
+
+EXTRA_libgl_la_SOURCES += strchrnul.c
+
+## end   gnulib module strchrnul
+
 ## begin gnulib module string
 
 BUILT_SOURCES += string.h
@@ -555,7 +573,6 @@ string.h: string.in.h
              -e 's|@''HAVE_STPNCPY''@|$(HAVE_STPNCPY)|g' \
              -e 's|@''HAVE_STRCHRNUL''@|$(HAVE_STRCHRNUL)|g' \
              -e 's|@''HAVE_DECL_STRDUP''@|$(HAVE_DECL_STRDUP)|g' \
-             -e 's|@''HAVE_STRNDUP''@|$(HAVE_STRNDUP)|g' \
              -e 's|@''HAVE_DECL_STRNDUP''@|$(HAVE_DECL_STRNDUP)|g' \
              -e 's|@''HAVE_DECL_STRNLEN''@|$(HAVE_DECL_STRNLEN)|g' \
              -e 's|@''HAVE_STRPBRK''@|$(HAVE_STRPBRK)|g' \
@@ -571,6 +588,7 @@ string.h: string.in.h
              -e 's|@''REPLACE_STRDUP''@|$(REPLACE_STRDUP)|g' \
              -e 's|@''REPLACE_STRSTR''@|$(REPLACE_STRSTR)|g' \
              -e 's|@''REPLACE_STRERROR''@|$(REPLACE_STRERROR)|g' \
+             -e 's|@''REPLACE_STRNDUP''@|$(REPLACE_STRNDUP)|g' \
              -e 's|@''REPLACE_STRSIGNAL''@|$(REPLACE_STRSIGNAL)|g' \
              -e 's|@''REPLACE_STRTOK_R''@|$(REPLACE_STRTOK_R)|g' \
              -e 's|@''UNDEFINE_STRTOK_R''@|$(UNDEFINE_STRTOK_R)|g' \
@@ -667,6 +685,7 @@ unistd.h: unistd.in.h
              -e 's|@''REPLACE_GETCWD''@|$(REPLACE_GETCWD)|g' \
              -e 's|@''REPLACE_GETPAGESIZE''@|$(REPLACE_GETPAGESIZE)|g' \
              -e 's|@''REPLACE_LCHOWN''@|$(REPLACE_LCHOWN)|g' \
+             -e 's|@''REPLACE_LINK''@|$(REPLACE_LINK)|g' \
              -e 's|@''REPLACE_LSEEK''@|$(REPLACE_LSEEK)|g' \
              -e 's|@''REPLACE_WRITE''@|$(REPLACE_WRITE)|g' \
              -e 
's|@''UNISTD_H_HAVE_WINSOCK2_H''@|$(UNISTD_H_HAVE_WINSOCK2_H)|g' \
diff --git a/lib/gl/m4/gnulib-cache.m4 b/lib/gl/m4/gnulib-cache.m4
index 4f0b2b8..da5c1a7 100644
--- a/lib/gl/m4/gnulib-cache.m4
+++ b/lib/gl/m4/gnulib-cache.m4
@@ -15,7 +15,7 @@
 
 
 # Specification in the form of a command-line invocation:
-#   gnulib-tool --import --dir=. --local-dir=gl/override --lib=libgl 
--source-base=gl --m4-base=gl/m4 --doc-base=doc --tests-base=gltests 
--aux-dir=build-aux --with-tests --avoid=vc-list-files-tests --lgpl=2 --libtool 
--macro-prefix=gl --no-vc-files base64 crypto/gc crypto/gc-hmac-md5 
crypto/gc-hmac-md5-tests crypto/gc-md5 crypto/gc-md5-tests crypto/gc-random 
crypto/gc-tests getline gettext lib-msvc-compat lib-symbol-versions 
lib-symbol-visibility maintainer-makefile minmax strverscmp vasprintf
+#   gnulib-tool --import --dir=. --local-dir=gl/override --lib=libgl 
--source-base=gl --m4-base=gl/m4 --doc-base=doc --tests-base=gltests 
--aux-dir=build-aux --with-tests --avoid=vc-list-files-tests --lgpl=2 --libtool 
--macro-prefix=gl --no-vc-files base64 crypto/gc crypto/gc-hmac-md5 
crypto/gc-hmac-md5-tests crypto/gc-md5 crypto/gc-md5-tests crypto/gc-random 
crypto/gc-tests getline gettext lib-msvc-compat lib-symbol-versions 
lib-symbol-visibility maintainer-makefile minmax strchrnul strverscmp vasprintf
 
 # Specification in the form of a few gnulib-tool.m4 macro invocations:
 gl_LOCAL_DIR([gl/override])
@@ -35,6 +35,7 @@ gl_MODULES([
   lib-symbol-visibility
   maintainer-makefile
   minmax
+  strchrnul
   strverscmp
   vasprintf
 ])
diff --git a/lib/gl/m4/gnulib-comp.m4 b/lib/gl/m4/gnulib-comp.m4
index 22501ea..ef5a819 100644
--- a/lib/gl/m4/gnulib-comp.m4
+++ b/lib/gl/m4/gnulib-comp.m4
@@ -83,6 +83,8 @@ AC_DEFUN([gl_INIT],
   gl_STRING_MODULE_INDICATOR([memchr])
   gl_MINMAX
   gl_MULTIARCH
+  gl_FUNC_RAWMEMCHR
+  gl_STRING_MODULE_INDICATOR([rawmemchr])
   gl_FUNC_REALLOC_POSIX
   gl_STDLIB_MODULE_INDICATOR([realloc-posix])
   gl_SIZE_MAX
@@ -91,6 +93,8 @@ AC_DEFUN([gl_INIT],
   gl_STDINT_H
   gl_STDIO_H
   gl_STDLIB_H
+  gl_FUNC_STRCHRNUL
+  gl_STRING_MODULE_INDICATOR([strchrnul])
   gl_HEADER_STRING_H
   gl_FUNC_STRVERSCMP
   gl_STRING_MODULE_INDICATOR([strverscmp])
@@ -267,6 +271,8 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/printf-args.h
   lib/printf-parse.c
   lib/printf-parse.h
+  lib/rawmemchr.c
+  lib/rawmemchr.valgrind
   lib/realloc.c
   lib/size_max.h
   lib/stdbool.in.h
@@ -275,6 +281,8 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/stdio-write.c
   lib/stdio.in.h
   lib/stdlib.in.h
+  lib/strchrnul.c
+  lib/strchrnul.valgrind
   lib/string.in.h
   lib/strverscmp.c
   lib/unistd.in.h
@@ -331,6 +339,7 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/po.m4
   m4/printf-posix.m4
   m4/progtest.m4
+  m4/rawmemchr.m4
   m4/realloc.m4
   m4/size_max.m4
   m4/stdbool.m4
@@ -339,6 +348,7 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/stdint_h.m4
   m4/stdio_h.m4
   m4/stdlib_h.m4
+  m4/strchrnul.m4
   m4/string_h.m4
   m4/strverscmp.m4
   m4/threadlib.m4
@@ -360,11 +370,13 @@ AC_DEFUN([gl_FILE_LIST], [
   tests/test-getdelim.c
   tests/test-getline.c
   tests/test-memchr.c
+  tests/test-rawmemchr.c
   tests/test-stdbool.c
   tests/test-stddef.c
   tests/test-stdint.c
   tests/test-stdio.c
   tests/test-stdlib.c
+  tests/test-strchrnul.c
   tests/test-string.c
   tests/test-strverscmp.c
   tests/test-unistd.c
diff --git a/lib/gl/m4/rawmemchr.m4 b/lib/gl/m4/rawmemchr.m4
new file mode 100644
index 0000000..1ac7b74
--- /dev/null
+++ b/lib/gl/m4/rawmemchr.m4
@@ -0,0 +1,21 @@
+# rawmemchr.m4 serial 1
+dnl Copyright (C) 2003, 2007, 2008 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_RAWMEMCHR],
+[
+  dnl Persuade glibc <string.h> to declare rawmemchr().
+  AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
+
+  AC_REQUIRE([gl_HEADER_STRING_H_DEFAULTS])
+  AC_REPLACE_FUNCS([rawmemchr])
+  if test $ac_cv_func_rawmemchr = no; then
+    HAVE_RAWMEMCHR=0
+    gl_PREREQ_RAWMEMCHR
+  fi
+])
+
+# Prerequisites of lib/strchrnul.c.
+AC_DEFUN([gl_PREREQ_RAWMEMCHR], [:])
diff --git a/lib/gl/m4/strchrnul.m4 b/lib/gl/m4/strchrnul.m4
new file mode 100644
index 0000000..7e270d0
--- /dev/null
+++ b/lib/gl/m4/strchrnul.m4
@@ -0,0 +1,21 @@
+# strchrnul.m4 serial 7
+dnl Copyright (C) 2003, 2007, 2009 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_STRCHRNUL],
+[
+  dnl Persuade glibc <string.h> to declare strchrnul().
+  AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
+
+  AC_REQUIRE([gl_HEADER_STRING_H_DEFAULTS])
+  AC_REPLACE_FUNCS([strchrnul])
+  if test $ac_cv_func_strchrnul = no; then
+    HAVE_STRCHRNUL=0
+    gl_PREREQ_STRCHRNUL
+  fi
+])
+
+# Prerequisites of lib/strchrnul.c.
+AC_DEFUN([gl_PREREQ_STRCHRNUL], [:])
diff --git a/lib/gl/m4/string_h.m4 b/lib/gl/m4/string_h.m4
index 3dbbfe1..edc5c6e 100644
--- a/lib/gl/m4/string_h.m4
+++ b/lib/gl/m4/string_h.m4
@@ -5,7 +5,7 @@
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 8
+# serial 9
 
 # Written by Paul Eggert.
 
@@ -74,7 +74,6 @@ AC_DEFUN([gl_HEADER_STRING_H_DEFAULTS],
   HAVE_STPNCPY=1;              AC_SUBST([HAVE_STPNCPY])
   HAVE_STRCHRNUL=1;            AC_SUBST([HAVE_STRCHRNUL])
   HAVE_DECL_STRDUP=1;          AC_SUBST([HAVE_DECL_STRDUP])
-  HAVE_STRNDUP=1;              AC_SUBST([HAVE_STRNDUP])
   HAVE_DECL_STRNDUP=1;         AC_SUBST([HAVE_DECL_STRNDUP])
   HAVE_DECL_STRNLEN=1;         AC_SUBST([HAVE_DECL_STRNLEN])
   HAVE_STRPBRK=1;              AC_SUBST([HAVE_STRPBRK])
@@ -90,6 +89,7 @@ AC_DEFUN([gl_HEADER_STRING_H_DEFAULTS],
   REPLACE_STRSTR=0;            AC_SUBST([REPLACE_STRSTR])
   REPLACE_STRCASESTR=0;                AC_SUBST([REPLACE_STRCASESTR])
   REPLACE_STRERROR=0;          AC_SUBST([REPLACE_STRERROR])
+  REPLACE_STRNDUP=0;           AC_SUBST([REPLACE_STRNDUP])
   REPLACE_STRSIGNAL=0;         AC_SUBST([REPLACE_STRSIGNAL])
   REPLACE_STRTOK_R=0;          AC_SUBST([REPLACE_STRTOK_R])
   UNDEFINE_STRTOK_R=0;         AC_SUBST([UNDEFINE_STRTOK_R])
diff --git a/lib/gl/m4/unistd_h.m4 b/lib/gl/m4/unistd_h.m4
index 84f0755..7347e38 100644
--- a/lib/gl/m4/unistd_h.m4
+++ b/lib/gl/m4/unistd_h.m4
@@ -1,4 +1,4 @@
-# unistd_h.m4 serial 24
+# unistd_h.m4 serial 25
 dnl Copyright (C) 2006-2009 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -94,6 +94,7 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS],
   REPLACE_GETCWD=0;       AC_SUBST([REPLACE_GETCWD])
   REPLACE_GETPAGESIZE=0;  AC_SUBST([REPLACE_GETPAGESIZE])
   REPLACE_LCHOWN=0;       AC_SUBST([REPLACE_LCHOWN])
+  REPLACE_LINK=0;         AC_SUBST([REPLACE_LINK])
   REPLACE_LSEEK=0;        AC_SUBST([REPLACE_LSEEK])
   REPLACE_WRITE=0;        AC_SUBST([REPLACE_WRITE])
   UNISTD_H_HAVE_WINSOCK2_H=0; AC_SUBST([UNISTD_H_HAVE_WINSOCK2_H])
diff --git a/lib/gl/rawmemchr.c b/lib/gl/rawmemchr.c
new file mode 100644
index 0000000..f749fe9
--- /dev/null
+++ b/lib/gl/rawmemchr.c
@@ -0,0 +1,136 @@
+/* Searching in a string.
+   Copyright (C) 2008 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 2.1 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <string.h>
+
+/* Find the first occurrence of C in S.  */
+void *
+rawmemchr (const void *s, int c_in)
+{
+  /* On 32-bit hardware, choosing longword to be a 32-bit unsigned
+     long instead of a 64-bit uintmax_t tends to give better
+     performance.  On 64-bit hardware, unsigned long is generally 64
+     bits already.  Change this typedef to experiment with
+     performance.  */
+  typedef unsigned long int longword;
+
+  const unsigned char *char_ptr;
+  const longword *longword_ptr;
+  longword repeated_one;
+  longword repeated_c;
+  unsigned char c;
+
+  c = (unsigned char) c_in;
+
+  /* Handle the first few bytes by reading one byte at a time.
+     Do this until CHAR_PTR is aligned on a longword boundary.  */
+  for (char_ptr = (const unsigned char *) s;
+       (size_t) char_ptr % sizeof (longword) != 0;
+       ++char_ptr)
+    if (*char_ptr == c)
+      return (void *) char_ptr;
+
+  longword_ptr = (const longword *) char_ptr;
+
+  /* All these elucidatory comments refer to 4-byte longwords,
+     but the theory applies equally well to any size longwords.  */
+
+  /* Compute auxiliary longword values:
+     repeated_one is a value which has a 1 in every byte.
+     repeated_c has c in every byte.  */
+  repeated_one = 0x01010101;
+  repeated_c = c | (c << 8);
+  repeated_c |= repeated_c << 16;
+  if (0xffffffffU < (longword) -1)
+    {
+      repeated_one |= repeated_one << 31 << 1;
+      repeated_c |= repeated_c << 31 << 1;
+      if (8 < sizeof (longword))
+        {
+          size_t i;
+
+          for (i = 64; i < sizeof (longword) * 8; i *= 2)
+            {
+              repeated_one |= repeated_one << i;
+              repeated_c |= repeated_c << i;
+            }
+        }
+    }
+
+  /* Instead of the traditional loop which tests each byte, we will
+     test a longword at a time.  The tricky part is testing if *any of
+     the four* bytes in the longword in question are equal to NUL or
+     c.  We first use an xor with repeated_c.  This reduces the task
+     to testing whether *any of the four* bytes in longword1 is zero.
+
+     We compute tmp =
+       ((longword1 - repeated_one) & ~longword1) & (repeated_one << 7).
+     That is, we perform the following operations:
+       1. Subtract repeated_one.
+       2. & ~longword1.
+       3. & a mask consisting of 0x80 in every byte.
+     Consider what happens in each byte:
+       - If a byte of longword1 is zero, step 1 and 2 transform it into 0xff,
+         and step 3 transforms it into 0x80.  A carry can also be propagated
+         to more significant bytes.
+       - If a byte of longword1 is nonzero, let its lowest 1 bit be at
+         position k (0 <= k <= 7); so the lowest k bits are 0.  After step 1,
+         the byte ends in a single bit of value 0 and k bits of value 1.
+         After step 2, the result is just k bits of value 1: 2^k - 1.  After
+         step 3, the result is 0.  And no carry is produced.
+     So, if longword1 has only non-zero bytes, tmp is zero.
+     Whereas if longword1 has a zero byte, call j the position of the least
+     significant zero byte.  Then the result has a zero at positions 0, ...,
+     j-1 and a 0x80 at position j.  We cannot predict the result at the more
+     significant bytes (positions j+1..3), but it does not matter since we
+     already have a non-zero bit at position 8*j+7.
+
+     The test whether any byte in longword1 is zero is equivalent
+     to testing whether tmp is nonzero.
+
+     This test can read beyond the end of a string, depending on where
+     C_IN is encountered.  However, this is considered safe since the
+     initialization phase ensured that the read will be aligned,
+     therefore, the read will not cross page boundaries and will not
+     cause a fault.  */
+
+  while (1)
+    {
+      longword longword1 = *longword_ptr ^ repeated_c;
+
+      if ((((longword1 - repeated_one) & ~longword1)
+           & (repeated_one << 7)) != 0)
+        break;
+      longword_ptr++;
+    }
+
+  char_ptr = (const unsigned char *) longword_ptr;
+
+  /* At this point, we know that one of the sizeof (longword) bytes
+     starting at char_ptr is == c.  On little-endian machines, we
+     could determine the first such byte without any further memory
+     accesses, just by looking at the tmp result from the last loop
+     iteration.  But this does not work on big-endian machines.
+     Choose code that works in both cases.  */
+
+  char_ptr = (unsigned char *) longword_ptr;
+  while (*char_ptr != c)
+    char_ptr++;
+  return (void *) char_ptr;
+}
diff --git a/lib/gl/rawmemchr.valgrind b/lib/gl/rawmemchr.valgrind
new file mode 100644
index 0000000..6363923
--- /dev/null
+++ b/lib/gl/rawmemchr.valgrind
@@ -0,0 +1,12 @@
+# Suppress a valgrind message about use of uninitialized memory in rawmemchr().
+# This use is OK because it provides only a speedup.
+{
+    rawmemchr-value4
+    Memcheck:Value4
+    fun:rawmemchr
+}
+{
+    rawmemchr-value8
+    Memcheck:Value8
+    fun:rawmemchr
+}
diff --git a/lib/gl/strchrnul.c b/lib/gl/strchrnul.c
new file mode 100644
index 0000000..bd68515
--- /dev/null
+++ b/lib/gl/strchrnul.c
@@ -0,0 +1,142 @@
+/* Searching in a string.
+   Copyright (C) 2003, 2007, 2008 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 2.1 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <string.h>
+
+/* Find the first occurrence of C in S or the final NUL byte.  */
+char *
+strchrnul (const char *s, int c_in)
+{
+  /* On 32-bit hardware, choosing longword to be a 32-bit unsigned
+     long instead of a 64-bit uintmax_t tends to give better
+     performance.  On 64-bit hardware, unsigned long is generally 64
+     bits already.  Change this typedef to experiment with
+     performance.  */
+  typedef unsigned long int longword;
+
+  const unsigned char *char_ptr;
+  const longword *longword_ptr;
+  longword repeated_one;
+  longword repeated_c;
+  unsigned char c;
+
+  c = (unsigned char) c_in;
+  if (!c)
+    return rawmemchr (s, 0);
+
+  /* Handle the first few bytes by reading one byte at a time.
+     Do this until CHAR_PTR is aligned on a longword boundary.  */
+  for (char_ptr = (const unsigned char *) s;
+       (size_t) char_ptr % sizeof (longword) != 0;
+       ++char_ptr)
+    if (!*char_ptr || *char_ptr == c)
+      return (char *) char_ptr;
+
+  longword_ptr = (const longword *) char_ptr;
+
+  /* All these elucidatory comments refer to 4-byte longwords,
+     but the theory applies equally well to any size longwords.  */
+
+  /* Compute auxiliary longword values:
+     repeated_one is a value which has a 1 in every byte.
+     repeated_c has c in every byte.  */
+  repeated_one = 0x01010101;
+  repeated_c = c | (c << 8);
+  repeated_c |= repeated_c << 16;
+  if (0xffffffffU < (longword) -1)
+    {
+      repeated_one |= repeated_one << 31 << 1;
+      repeated_c |= repeated_c << 31 << 1;
+      if (8 < sizeof (longword))
+        {
+          size_t i;
+
+          for (i = 64; i < sizeof (longword) * 8; i *= 2)
+            {
+              repeated_one |= repeated_one << i;
+              repeated_c |= repeated_c << i;
+            }
+        }
+    }
+
+  /* Instead of the traditional loop which tests each byte, we will
+     test a longword at a time.  The tricky part is testing if *any of
+     the four* bytes in the longword in question are equal to NUL or
+     c.  We first use an xor with repeated_c.  This reduces the task
+     to testing whether *any of the four* bytes in longword1 or
+     longword2 is zero.
+
+     Let's consider longword1.  We compute tmp =
+       ((longword1 - repeated_one) & ~longword1) & (repeated_one << 7).
+     That is, we perform the following operations:
+       1. Subtract repeated_one.
+       2. & ~longword1.
+       3. & a mask consisting of 0x80 in every byte.
+     Consider what happens in each byte:
+       - If a byte of longword1 is zero, step 1 and 2 transform it into 0xff,
+         and step 3 transforms it into 0x80.  A carry can also be propagated
+         to more significant bytes.
+       - If a byte of longword1 is nonzero, let its lowest 1 bit be at
+         position k (0 <= k <= 7); so the lowest k bits are 0.  After step 1,
+         the byte ends in a single bit of value 0 and k bits of value 1.
+         After step 2, the result is just k bits of value 1: 2^k - 1.  After
+         step 3, the result is 0.  And no carry is produced.
+     So, if longword1 has only non-zero bytes, tmp is zero.
+     Whereas if longword1 has a zero byte, call j the position of the least
+     significant zero byte.  Then the result has a zero at positions 0, ...,
+     j-1 and a 0x80 at position j.  We cannot predict the result at the more
+     significant bytes (positions j+1..3), but it does not matter since we
+     already have a non-zero bit at position 8*j+7.
+
+     The test whether any byte in longword1 or longword2 is zero is equivalent
+     to testing whether tmp1 is nonzero or tmp2 is nonzero.  We can combine
+     this into a single test, whether (tmp1 | tmp2) is nonzero.
+
+     This test can read more than one byte beyond the end of a string,
+     depending on where the terminating NUL is encountered.  However,
+     this is considered safe since the initialization phase ensured
+     that the read will be aligned, therefore, the read will not cross
+     page boundaries and will not cause a fault.  */
+
+  while (1)
+    {
+      longword longword1 = *longword_ptr ^ repeated_c;
+      longword longword2 = *longword_ptr;
+
+      if (((((longword1 - repeated_one) & ~longword1)
+            | ((longword2 - repeated_one) & ~longword2))
+           & (repeated_one << 7)) != 0)
+        break;
+      longword_ptr++;
+    }
+
+  char_ptr = (const unsigned char *) longword_ptr;
+
+  /* At this point, we know that one of the sizeof (longword) bytes
+     starting at char_ptr is == 0 or == c.  On little-endian machines,
+     we could determine the first such byte without any further memory
+     accesses, just by looking at the tmp result from the last loop
+     iteration.  But this does not work on big-endian machines.
+     Choose code that works in both cases.  */
+
+  char_ptr = (unsigned char *) longword_ptr;
+  while (*char_ptr && (*char_ptr != c))
+    char_ptr++;
+  return (char *) char_ptr;
+}
diff --git a/lib/gl/strchrnul.valgrind b/lib/gl/strchrnul.valgrind
new file mode 100644
index 0000000..b14fa13
--- /dev/null
+++ b/lib/gl/strchrnul.valgrind
@@ -0,0 +1,12 @@
+# Suppress a valgrind message about use of uninitialized memory in strchrnul().
+# This use is OK because it provides only a speedup.
+{
+    strchrnul-value4
+    Memcheck:Value4
+    fun:strchrnul
+}
+{
+    strchrnul-value8
+    Memcheck:Value8
+    fun:strchrnul
+}
diff --git a/lib/gl/string.in.h b/lib/gl/string.in.h
index 1815566..4b6d47f 100644
--- a/lib/gl/string.in.h
+++ b/lib/gl/string.in.h
@@ -203,11 +203,11 @@ extern char *strdup (char const *__s);
 
 /* Return a newly allocated copy of at most N bytes of STRING.  */
 #if @GNULIB_STRNDUP@
-# if ! @HAVE_STRNDUP@
+# if @REPLACE_STRNDUP@
 #  undef strndup
 #  define strndup rpl_strndup
 # endif
-# if ! @HAVE_STRNDUP@ || ! @HAVE_DECL_STRNDUP@
+# if @REPLACE_STRNDUP@ || ! @HAVE_DECL_STRNDUP@
 extern char *strndup (char const *__string, size_t __n);
 # endif
 #elif defined GNULIB_POSIXCHECK
diff --git a/lib/gl/unistd.in.h b/lib/gl/unistd.in.h
index 3b40310..d4519a7 100644
--- a/lib/gl/unistd.in.h
+++ b/lib/gl/unistd.in.h
@@ -595,11 +595,14 @@ extern int lchown (char const *file, uid_t owner, gid_t 
group);
 
 
 #if @GNULIB_LINK@
+# if @REPLACE_LINK@
+#  define link rpl_link
+# endif
 /* Create a new hard link for an existing file.
    Return 0 if successful, otherwise -1 and errno set.
    See POSIX:2001 specification
    <http://www.opengroup.org/susv3xsh/link.html>.  */
-# if address@hidden@
+# if address@hidden@ || @REPLACE_LINK@
 extern int link (const char *path1, const char *path2);
 # endif
 #elif defined GNULIB_POSIXCHECK
diff --git a/lib/gltests/Makefile.am b/lib/gltests/Makefile.am
index a7d6422..844a1c1 100644
--- a/lib/gltests/Makefile.am
+++ b/lib/gltests/Makefile.am
@@ -101,6 +101,14 @@ EXTRA_DIST += test-memchr.c zerosize-ptr.h
 
 ## end   gnulib module memchr-tests
 
+## begin gnulib module rawmemchr-tests
+
+TESTS += test-rawmemchr
+check_PROGRAMS += test-rawmemchr
+EXTRA_DIST += test-rawmemchr.c
+
+## end   gnulib module rawmemchr-tests
+
 ## begin gnulib module stdbool-tests
 
 TESTS += test-stdbool
@@ -146,6 +154,14 @@ EXTRA_DIST += test-stdlib.c
 
 ## end   gnulib module stdlib-tests
 
+## begin gnulib module strchrnul-tests
+
+TESTS += test-strchrnul
+check_PROGRAMS += test-strchrnul
+EXTRA_DIST += test-strchrnul.c
+
+## end   gnulib module strchrnul-tests
+
 ## begin gnulib module string-tests
 
 TESTS += test-string
diff --git a/lib/gltests/test-rawmemchr.c b/lib/gltests/test-rawmemchr.c
new file mode 100644
index 0000000..34e70ef
--- /dev/null
+++ b/lib/gltests/test-rawmemchr.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2008 Free Software Foundation
+ * Written by Eric Blake and Bruno Haible
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define ASSERT(expr) \
+  do                                                                        \
+    {                                                                       \
+      if (!(expr))                                                          \
+       {                                                                    \
+         fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \
+         fflush (stderr);                                                   \
+         abort ();                                                          \
+       }                                                                    \
+    }                                                                       \
+  while (0)
+
+/* Calculating void * + int is not portable, so this wrapper converts
+   to char * to make the tests easier to write.  */
+#define RAWMEMCHR (char *) rawmemchr
+
+int
+main ()
+{
+  size_t n = 0x100000;
+  char *input = malloc (n + 1);
+  ASSERT (input);
+
+  input[0] = 'a';
+  input[1] = 'b';
+  memset (input + 2, 'c', 1024);
+  memset (input + 1026, 'd', n - 1028);
+  input[n - 2] = 'e';
+  input[n - 1] = 'a';
+  input[n] = '\0';
+
+  /* Basic behavior tests.  */
+  ASSERT (RAWMEMCHR (input, 'a') == input);
+  ASSERT (RAWMEMCHR (input, 'b') == input + 1);
+  ASSERT (RAWMEMCHR (input, 'c') == input + 2);
+  ASSERT (RAWMEMCHR (input, 'd') == input + 1026);
+
+  ASSERT (RAWMEMCHR (input + 1, 'a') == input + n - 1);
+  ASSERT (RAWMEMCHR (input + 1, 'e') == input + n - 2);
+
+  ASSERT (RAWMEMCHR (input, '\0') == input + n);
+
+  /* Alignment tests.  */
+  {
+    int i, j;
+    for (i = 0; i < 32; i++)
+      {
+        for (j = 0; j < 256; j++)
+          input[i + j] = j;
+        for (j = 0; j < 256; j++)
+          {
+            ASSERT (RAWMEMCHR (input + i, j) == input + i + j);
+          }
+      }
+  }
+
+  free (input);
+
+  return 0;
+}
diff --git a/lib/gltests/test-strchrnul.c b/lib/gltests/test-strchrnul.c
new file mode 100644
index 0000000..dc55066
--- /dev/null
+++ b/lib/gltests/test-strchrnul.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2008 Free Software Foundation
+ * Written by Eric Blake and Bruno Haible
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define ASSERT(expr) \
+  do                                                                        \
+    {                                                                       \
+      if (!(expr))                                                      \
+        {                                                               \
+          fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \
+          fflush (stderr);                                              \
+          abort ();                                                     \
+        }                                                               \
+    }                                                                   \
+  while (0)
+
+int
+main ()
+{
+  size_t n = 0x100000;
+  char *input = malloc (n + 1);
+  ASSERT (input);
+
+  input[0] = 'a';
+  input[1] = 'b';
+  memset (input + 2, 'c', 1024);
+  memset (input + 1026, 'd', n - 1028);
+  input[n - 2] = 'e';
+  input[n - 1] = 'a';
+  input[n] = '\0';
+
+  /* Basic behavior tests.  */
+  ASSERT (strchrnul (input, 'a') == input);
+  ASSERT (strchrnul (input, 'b') == input + 1);
+  ASSERT (strchrnul (input, 'c') == input + 2);
+  ASSERT (strchrnul (input, 'd') == input + 1026);
+
+  ASSERT (strchrnul (input + 1, 'a') == input + n - 1);
+  ASSERT (strchrnul (input + 1, 'e') == input + n - 2);
+
+  ASSERT (strchrnul (input, 'f') == input + n);
+  ASSERT (strchrnul (input, '\0') == input + n);
+
+  /* Check that a very long haystack is handled quickly if the byte is
+     found near the beginning.  */
+  {
+    size_t repeat = 10000;
+    for (; repeat > 0; repeat--)
+      {
+        ASSERT (strchrnul (input, 'c') == input + 2);
+      }
+  }
+
+  /* Alignment tests.  */
+  {
+    int i, j;
+    for (i = 0; i < 32; i++)
+      {
+        for (j = 0; j < 256; j++)
+          input[i + j] = (j + 1) & 0xff;
+        for (j = 1; j < 256; j++)
+          {
+            ASSERT (strchrnul (input + i, j) == input + i + j - 1);
+            input[i + j - 1] = (j == 1 ? 2 : 1);
+            ASSERT (strchrnul (input + i, j) == input + i + 255);
+            input[i + j - 1] = j;
+          }
+      }
+  }
+
+  free (input);
+
+  return 0;
+}
diff --git a/lib/scram/parser.c b/lib/scram/parser.c
index 5b6b918..86c3922 100644
--- a/lib/scram/parser.c
+++ b/lib/scram/parser.c
@@ -30,7 +30,7 @@
 /* Get malloc, free. */
 #include <stdlib.h>
 
-/* Get memcpy, strlen. */
+/* Get memcpy, strlen, strchrnul. */
 #include <string.h>
 
 /* Get validator. */
@@ -40,5 +40,86 @@ int
 scram_parse_client_first (const char *str, size_t len,
                          struct scram_client_first *cf)
 {
-  return -1;
+  /* Minimum client first string is 'n,,n=a,r=b'. */
+  if (len < 10)
+    return -1;
+
+  if (*str != 'p' && *str != 'n' && *str != 'y')
+    return -1;
+
+  cf->cbflag = *str++;
+  if (cf->cbflag == 'p')
+    {
+      /* FIXME parse cbname */
+      return -1;
+    }
+
+  if (*str++ != ',')
+    return -1;
+
+  if (*str == 'a')
+    {
+      /* FIXME parse authzid */
+      return -1;
+    }
+
+  if (*str++ != ',')
+    return -1;
+
+  if (*str++ != 'n')
+    return -1;
+
+  if (*str++ != '=')
+    return -1;
+
+  {
+    char *p;
+    size_t len;
+
+    p = strchr (str, ',');
+    if (!p)
+      return -1;
+
+    len = p - str;
+
+    cf->username = malloc (len + 1);
+    if (!cf->username)
+      return -1;
+
+    memcpy (cf->username, str, len);
+    cf->username[len] = '\0';
+
+    str = p;
+  }
+
+  if (*str++ != ',')
+    return -1;
+
+  if (*str++ != 'r')
+    return -1;
+
+  if (*str++ != '=')
+    return -1;
+
+  {
+    char *p;
+    size_t len;
+
+    p = strchrnul (str, ',');
+    if (!p)
+      return -1;
+
+    len = p - str;
+
+    cf->username = malloc (len + 1);
+    if (!cf->username)
+      return -1;
+
+    memcpy (cf->username, str, len);
+    cf->username[len] = '\0';
+
+    str = p;
+  }
+
+  return 0;
 }
diff --git a/tests/scram.c b/tests/scram.c
index 16ca975..30cf3ac 100644
--- a/tests/scram.c
+++ b/tests/scram.c
@@ -74,6 +74,7 @@ doit (void)
   Gsasl_session *server = NULL, *client = NULL;
   char *s1, *s2;
   size_t s1len, s2len;
+  size_t i;
   int res;
 
   res = gsasl_init (&ctx);


hooks/post-receive
-- 
GNU gsasl




reply via email to

[Prev in Thread] Current Thread [Next in Thread]