maint: update copyright
[gnulib.git] / m4 / strncat.m4
1 # strncat.m4 serial 2
2 dnl Copyright (C) 2002-2004, 2009-2014 Free Software Foundation, Inc.
3 dnl This file is free software; the Free Software Foundation
4 dnl gives unlimited permission to copy and/or distribute it,
5 dnl with or without modifications, as long as this notice is preserved.
6
7 AC_DEFUN_ONCE([gl_FUNC_STRNCAT],
8 [
9   AC_REQUIRE([gl_HEADER_STRING_H_DEFAULTS])
10   AC_REQUIRE([AC_PROG_CC])
11   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
12
13   dnl Check for prerequisites for memory fence checks.
14   gl_FUNC_MMAP_ANON
15   AC_CHECK_HEADERS_ONCE([sys/mman.h])
16   AC_CHECK_FUNCS_ONCE([mprotect])
17
18   dnl Detect bug in Solaris 8..10 on SPARC:
19   dnl strncat should not dereference more than n bytes, but always dereferences
20   dnl n+1 bytes if the first n bytes don't contain a NUL byte.
21   dnl Assume that strncat works on platforms that lack mprotect.
22   AC_CACHE_CHECK([whether strncat works], [gl_cv_func_strncat_works],
23     [AC_RUN_IFELSE([AC_LANG_PROGRAM([[
24 #include <string.h>
25 #if HAVE_SYS_MMAN_H
26 # include <fcntl.h>
27 # include <unistd.h>
28 # include <sys/types.h>
29 # include <sys/mman.h>
30 # ifndef MAP_FILE
31 #  define MAP_FILE 0
32 # endif
33 #endif
34 ]], [[
35   char *fence = NULL;
36 #if HAVE_SYS_MMAN_H && HAVE_MPROTECT
37 # if HAVE_MAP_ANONYMOUS
38   const int flags = MAP_ANONYMOUS | MAP_PRIVATE;
39   const int fd = -1;
40 # else /* !HAVE_MAP_ANONYMOUS */
41   const int flags = MAP_FILE | MAP_PRIVATE;
42   int fd = open ("/dev/zero", O_RDONLY, 0666);
43   if (fd >= 0)
44 # endif
45     {
46       int pagesize = getpagesize ();
47       char *two_pages =
48         (char *) mmap (NULL, 2 * pagesize, PROT_READ | PROT_WRITE,
49                        flags, fd, 0);
50       if (two_pages != (char *)(-1)
51           && mprotect (two_pages + pagesize, pagesize, PROT_NONE) == 0)
52         fence = two_pages + pagesize;
53     }
54 #endif
55   if (fence)
56     {
57       char dest[8];
58
59       dest[0] = '*';
60       dest[1] = 'a';
61       dest[2] = '\0';
62       dest[3] = 'w';
63       dest[4] = 'x';
64       dest[5] = 'y';
65       dest[6] = 'z';
66
67       *(fence - 3) = '7';
68       *(fence - 2) = '2';
69       *(fence - 1) = '9';
70
71       if (strncat (dest + 1, fence - 3, 3) != dest + 1)
72         return 1;
73       if (dest[0] != '*')
74         return 2;
75       if (dest[1] != 'a'
76           || dest[2] != '7' || dest[3] != '2' || dest[4] != '9'
77           || dest[5] != '\0')
78         return 3;
79       if (dest[6] != 'z')
80         return 4;
81     }
82   return 0;
83 ]])], [gl_cv_func_strncat_works=yes], [gl_cv_func_strncat_works=no],
84        [
85         case "$host_os" in
86                     # Guess no on Solaris.
87           solaris*) gl_cv_func_strncat_works="guessing no";;
88                     # Guess yes otherwise.
89           *)        gl_cv_func_strncat_works="guessing yes";;
90         esac
91        ])
92     ])
93   case "$gl_cv_func_strncat_works" in
94     *yes) ;;
95     *) REPLACE_STRNCAT=1 ;;
96   esac
97 ])
98
99 # Prerequisites of lib/strncat.c.
100 AC_DEFUN([gl_PREREQ_STRNCAT], [
101   :
102 ])