aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2012-10-19 10:14:00 -0700
committerPaul Eggert2012-10-19 10:14:00 -0700
commit2c43889e841d1c4e19d876ec2c7d078b940d10d0 (patch)
treea5428cf704ba6a4eac006b80efcc7796b563ec8a
parente752e0b0a2622d8d0ba518bf81f6fa652d926e67 (diff)
downloademacs-2c43889e841d1c4e19d876ec2c7d078b940d10d0.tar.gz
emacs-2c43889e841d1c4e19d876ec2c7d078b940d10d0.zip
New files from gnulib.
Fixes: debbugs:12632
-rw-r--r--lib/at-func.c146
-rw-r--r--lib/euidaccess.c221
-rw-r--r--lib/faccessat.c45
-rw-r--r--lib/fcntl.in.h347
-rw-r--r--lib/getgroups.c116
-rw-r--r--lib/group-member.c119
-rw-r--r--lib/root-uid.h30
-rw-r--r--lib/xalloc-oversized.h38
-rw-r--r--m4/euidaccess.m452
-rw-r--r--m4/faccessat.m428
-rw-r--r--m4/fcntl_h.m450
-rw-r--r--m4/getgroups.m4107
-rw-r--r--m4/group-member.m429
13 files changed, 1328 insertions, 0 deletions
diff --git a/lib/at-func.c b/lib/at-func.c
new file mode 100644
index 00000000000..481eea475a1
--- /dev/null
+++ b/lib/at-func.c
@@ -0,0 +1,146 @@
1/* Define at-style functions like fstatat, unlinkat, fchownat, etc.
2 Copyright (C) 2006, 2009-2012 Free Software Foundation, Inc.
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
16
17/* written by Jim Meyering */
18
19#include "dosname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */
20
21#ifdef GNULIB_SUPPORT_ONLY_AT_FDCWD
22# include <errno.h>
23# ifndef ENOTSUP
24# define ENOTSUP EINVAL
25# endif
26#else
27# include "openat.h"
28# include "openat-priv.h"
29# include "save-cwd.h"
30#endif
31
32#ifdef AT_FUNC_USE_F1_COND
33# define CALL_FUNC(F) \
34 (flag == AT_FUNC_USE_F1_COND \
35 ? AT_FUNC_F1 (F AT_FUNC_POST_FILE_ARGS) \
36 : AT_FUNC_F2 (F AT_FUNC_POST_FILE_ARGS))
37# define VALIDATE_FLAG(F) \
38 if (flag & ~AT_FUNC_USE_F1_COND) \
39 { \
40 errno = EINVAL; \
41 return FUNC_FAIL; \
42 }
43#else
44# define CALL_FUNC(F) (AT_FUNC_F1 (F AT_FUNC_POST_FILE_ARGS))
45# define VALIDATE_FLAG(F) /* empty */
46#endif
47
48#ifdef AT_FUNC_RESULT
49# define FUNC_RESULT AT_FUNC_RESULT
50#else
51# define FUNC_RESULT int
52#endif
53
54#ifdef AT_FUNC_FAIL
55# define FUNC_FAIL AT_FUNC_FAIL
56#else
57# define FUNC_FAIL -1
58#endif
59
60/* Call AT_FUNC_F1 to operate on FILE, which is in the directory
61 open on descriptor FD. If AT_FUNC_USE_F1_COND is defined to a value,
62 AT_FUNC_POST_FILE_PARAM_DECLS must include a parameter named flag;
63 call AT_FUNC_F2 if FLAG is 0 or fail if FLAG contains more bits than
64 AT_FUNC_USE_F1_COND. Return int and fail with -1 unless AT_FUNC_RESULT
65 or AT_FUNC_FAIL are defined. If possible, do it without changing the
66 working directory. Otherwise, resort to using save_cwd/fchdir,
67 then AT_FUNC_F?/restore_cwd. If either the save_cwd or the restore_cwd
68 fails, then give a diagnostic and exit nonzero. */
69FUNC_RESULT
70AT_FUNC_NAME (int fd, char const *file AT_FUNC_POST_FILE_PARAM_DECLS)
71{
72 VALIDATE_FLAG (flag);
73
74 if (fd == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file))
75 return CALL_FUNC (file);
76
77#ifdef GNULIB_SUPPORT_ONLY_AT_FDCWD
78 errno = ENOTSUP;
79 return FUNC_FAIL;
80#else
81 {
82 /* Be careful to choose names unlikely to conflict with
83 AT_FUNC_POST_FILE_PARAM_DECLS. */
84 struct saved_cwd saved_cwd;
85 int saved_errno;
86 FUNC_RESULT err;
87
88 {
89 char proc_buf[OPENAT_BUFFER_SIZE];
90 char *proc_file = openat_proc_name (proc_buf, fd, file);
91 if (proc_file)
92 {
93 FUNC_RESULT proc_result = CALL_FUNC (proc_file);
94 int proc_errno = errno;
95 if (proc_file != proc_buf)
96 free (proc_file);
97 /* If the syscall succeeds, or if it fails with an unexpected
98 errno value, then return right away. Otherwise, fall through
99 and resort to using save_cwd/restore_cwd. */
100 if (FUNC_FAIL != proc_result)
101 return proc_result;
102 if (! EXPECTED_ERRNO (proc_errno))
103 {
104 errno = proc_errno;
105 return proc_result;
106 }
107 }
108 }
109
110 if (save_cwd (&saved_cwd) != 0)
111 openat_save_fail (errno);
112 if (0 <= fd && fd == saved_cwd.desc)
113 {
114 /* If saving the working directory collides with the user's
115 requested fd, then the user's fd must have been closed to
116 begin with. */
117 free_cwd (&saved_cwd);
118 errno = EBADF;
119 return FUNC_FAIL;
120 }
121
122 if (fchdir (fd) != 0)
123 {
124 saved_errno = errno;
125 free_cwd (&saved_cwd);
126 errno = saved_errno;
127 return FUNC_FAIL;
128 }
129
130 err = CALL_FUNC (file);
131 saved_errno = (err == FUNC_FAIL ? errno : 0);
132
133 if (restore_cwd (&saved_cwd) != 0)
134 openat_restore_fail (errno);
135
136 free_cwd (&saved_cwd);
137
138 if (saved_errno)
139 errno = saved_errno;
140 return err;
141 }
142#endif
143}
144#undef CALL_FUNC
145#undef FUNC_RESULT
146#undef FUNC_FAIL
diff --git a/lib/euidaccess.c b/lib/euidaccess.c
new file mode 100644
index 00000000000..ca2ceca5d22
--- /dev/null
+++ b/lib/euidaccess.c
@@ -0,0 +1,221 @@
1/* euidaccess -- check if effective user id can access file
2
3 Copyright (C) 1990-1991, 1995, 1998, 2000, 2003-2006, 2008-2012 Free
4 Software Foundation, Inc.
5
6 This file is part of the GNU C Library.
7
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20
21/* Written by David MacKenzie and Torbjorn Granlund.
22 Adapted for GNU C library by Roland McGrath. */
23
24#ifndef _LIBC
25# include <config.h>
26#endif
27
28#include <fcntl.h>
29#include <sys/types.h>
30#include <sys/stat.h>
31#include <unistd.h>
32
33#include "root-uid.h"
34
35#if HAVE_LIBGEN_H
36# include <libgen.h>
37#endif
38
39#include <errno.h>
40#ifndef __set_errno
41# define __set_errno(val) errno = (val)
42#endif
43
44#if defined EACCES && !defined EACCESS
45# define EACCESS EACCES
46#endif
47
48#ifndef F_OK
49# define F_OK 0
50# define X_OK 1
51# define W_OK 2
52# define R_OK 4
53#endif
54
55
56#ifdef _LIBC
57
58# define access __access
59# define getuid __getuid
60# define getgid __getgid
61# define geteuid __geteuid
62# define getegid __getegid
63# define group_member __group_member
64# define euidaccess __euidaccess
65# undef stat
66# define stat stat64
67
68#endif
69
70/* Return 0 if the user has permission of type MODE on FILE;
71 otherwise, return -1 and set 'errno'.
72 Like access, except that it uses the effective user and group
73 id's instead of the real ones, and it does not always check for read-only
74 file system, text busy, etc. */
75
76int
77euidaccess (const char *file, int mode)
78{
79#if HAVE_FACCESSAT /* glibc, AIX 7, Solaris 11, Cygwin 1.7 */
80 return faccessat (AT_FDCWD, file, mode, AT_EACCESS);
81#elif defined EFF_ONLY_OK /* IRIX, OSF/1, Interix */
82 return access (file, mode | EFF_ONLY_OK);
83#elif defined ACC_SELF /* AIX */
84 return accessx (file, mode, ACC_SELF);
85#elif HAVE_EACCESS /* FreeBSD */
86 return eaccess (file, mode);
87#else /* Mac OS X, NetBSD, OpenBSD, HP-UX, Solaris, Cygwin, mingw, BeOS */
88
89 uid_t uid = getuid ();
90 gid_t gid = getgid ();
91 uid_t euid = geteuid ();
92 gid_t egid = getegid ();
93 struct stat stats;
94
95# if HAVE_DECL_SETREGID && PREFER_NONREENTRANT_EUIDACCESS
96
97 /* Define PREFER_NONREENTRANT_EUIDACCESS if you prefer euidaccess to
98 return the correct result even if this would make it
99 nonreentrant. Define this only if your entire application is
100 safe even if the uid or gid might temporarily change. If your
101 application uses signal handlers or threads it is probably not
102 safe. */
103
104 if (mode == F_OK)
105 return stat (file, &stats);
106 else
107 {
108 int result;
109 int saved_errno;
110
111 if (uid != euid)
112 setreuid (euid, uid);
113 if (gid != egid)
114 setregid (egid, gid);
115
116 result = access (file, mode);
117 saved_errno = errno;
118
119 /* Restore them. */
120 if (uid != euid)
121 setreuid (uid, euid);
122 if (gid != egid)
123 setregid (gid, egid);
124
125 errno = saved_errno;
126 return result;
127 }
128
129# else
130
131 /* The following code assumes the traditional Unix model, and is not
132 correct on systems that have ACLs or the like. However, it's
133 better than nothing, and it is reentrant. */
134
135 unsigned int granted;
136 if (uid == euid && gid == egid)
137 /* If we are not set-uid or set-gid, access does the same. */
138 return access (file, mode);
139
140 if (stat (file, &stats) != 0)
141 return -1;
142
143 /* The super-user can read and write any file, and execute any file
144 that anyone can execute. */
145 if (euid == ROOT_UID
146 && ((mode & X_OK) == 0
147 || (stats.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))))
148 return 0;
149
150 /* Convert the mode to traditional form, clearing any bogus bits. */
151 if (R_OK == 4 && W_OK == 2 && X_OK == 1 && F_OK == 0)
152 mode &= 7;
153 else
154 mode = ((mode & R_OK ? 4 : 0)
155 + (mode & W_OK ? 2 : 0)
156 + (mode & X_OK ? 1 : 0));
157
158 if (mode == 0)
159 return 0; /* The file exists. */
160
161 /* Convert the file's permission bits to traditional form. */
162 if (S_IRUSR == (4 << 6) && S_IWUSR == (2 << 6) && S_IXUSR == (1 << 6)
163 && S_IRGRP == (4 << 3) && S_IWGRP == (2 << 3) && S_IXGRP == (1 << 3)
164 && S_IROTH == (4 << 0) && S_IWOTH == (2 << 0) && S_IXOTH == (1 << 0))
165 granted = stats.st_mode;
166 else
167 granted = ((stats.st_mode & S_IRUSR ? 4 << 6 : 0)
168 + (stats.st_mode & S_IWUSR ? 2 << 6 : 0)
169 + (stats.st_mode & S_IXUSR ? 1 << 6 : 0)
170 + (stats.st_mode & S_IRGRP ? 4 << 3 : 0)
171 + (stats.st_mode & S_IWGRP ? 2 << 3 : 0)
172 + (stats.st_mode & S_IXGRP ? 1 << 3 : 0)
173 + (stats.st_mode & S_IROTH ? 4 << 0 : 0)
174 + (stats.st_mode & S_IWOTH ? 2 << 0 : 0)
175 + (stats.st_mode & S_IXOTH ? 1 << 0 : 0));
176
177 if (euid == stats.st_uid)
178 granted >>= 6;
179 else if (egid == stats.st_gid || group_member (stats.st_gid))
180 granted >>= 3;
181
182 if ((mode & ~granted) == 0)
183 return 0;
184 __set_errno (EACCESS);
185 return -1;
186
187# endif
188#endif
189}
190#undef euidaccess
191#ifdef weak_alias
192weak_alias (__euidaccess, euidaccess)
193#endif
194
195#ifdef TEST
196# include <error.h>
197# include <stdio.h>
198# include <stdlib.h>
199
200char *program_name;
201
202int
203main (int argc, char **argv)
204{
205 char *file;
206 int mode;
207 int err;
208
209 program_name = argv[0];
210 if (argc < 3)
211 abort ();
212 file = argv[1];
213 mode = atoi (argv[2]);
214
215 err = euidaccess (file, mode);
216 printf ("%d\n", err);
217 if (err != 0)
218 error (0, errno, "%s", file);
219 exit (0);
220}
221#endif
diff --git a/lib/faccessat.c b/lib/faccessat.c
new file mode 100644
index 00000000000..d11a3efaad6
--- /dev/null
+++ b/lib/faccessat.c
@@ -0,0 +1,45 @@
1/* Check the access rights of a file relative to an open directory.
2 Copyright (C) 2009-2012 Free Software Foundation, Inc.
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
16
17/* written by Eric Blake */
18
19#include <config.h>
20
21#include <unistd.h>
22#include <fcntl.h>
23
24#ifndef HAVE_ACCESS
25/* Mingw lacks access, but it also lacks real vs. effective ids, so
26 the gnulib euidaccess module is good enough. */
27# undef access
28# define access euidaccess
29#endif
30
31/* Invoke access or euidaccess on file, FILE, using mode MODE, in the directory
32 open on descriptor FD. If possible, do it without changing the
33 working directory. Otherwise, resort to using save_cwd/fchdir, then
34 (access|euidaccess)/restore_cwd. If either the save_cwd or the
35 restore_cwd fails, then give a diagnostic and exit nonzero.
36 Note that this implementation only supports AT_EACCESS, although some
37 native versions also support AT_SYMLINK_NOFOLLOW. */
38
39#define AT_FUNC_NAME faccessat
40#define AT_FUNC_F1 euidaccess
41#define AT_FUNC_F2 access
42#define AT_FUNC_USE_F1_COND AT_EACCESS
43#define AT_FUNC_POST_FILE_PARAM_DECLS , int mode, int flag
44#define AT_FUNC_POST_FILE_ARGS , mode
45#include "at-func.c"
diff --git a/lib/fcntl.in.h b/lib/fcntl.in.h
new file mode 100644
index 00000000000..5fdac2313d0
--- /dev/null
+++ b/lib/fcntl.in.h
@@ -0,0 +1,347 @@
1/* Like <fcntl.h>, but with non-working flags defined to 0.
2
3 Copyright (C) 2006-2012 Free Software Foundation, Inc.
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17
18/* written by Paul Eggert */
19
20#if __GNUC__ >= 3
21@PRAGMA_SYSTEM_HEADER@
22#endif
23@PRAGMA_COLUMNS@
24
25#if defined __need_system_fcntl_h
26/* Special invocation convention. */
27
28/* Needed before <sys/stat.h>.
29 May also define off_t to a 64-bit type on native Windows. */
30#include <sys/types.h>
31/* On some systems other than glibc, <sys/stat.h> is a prerequisite of
32 <fcntl.h>. On glibc systems, we would like to avoid namespace pollution.
33 But on glibc systems, <fcntl.h> includes <sys/stat.h> inside an
34 extern "C" { ... } block, which leads to errors in C++ mode with the
35 overridden <sys/stat.h> from gnulib. These errors are known to be gone
36 with g++ version >= 4.3. */
37#if !(defined __GLIBC__ || defined __UCLIBC__) || (defined __cplusplus && defined GNULIB_NAMESPACE && !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))
38# include <sys/stat.h>
39#endif
40#@INCLUDE_NEXT@ @NEXT_FCNTL_H@
41
42#else
43/* Normal invocation convention. */
44
45#ifndef _@GUARD_PREFIX@_FCNTL_H
46
47/* Needed before <sys/stat.h>.
48 May also define off_t to a 64-bit type on native Windows. */
49#include <sys/types.h>
50/* On some systems other than glibc, <sys/stat.h> is a prerequisite of
51 <fcntl.h>. On glibc systems, we would like to avoid namespace pollution.
52 But on glibc systems, <fcntl.h> includes <sys/stat.h> inside an
53 extern "C" { ... } block, which leads to errors in C++ mode with the
54 overridden <sys/stat.h> from gnulib. These errors are known to be gone
55 with g++ version >= 4.3. */
56#if !(defined __GLIBC__ || defined __UCLIBC__) || (defined __cplusplus && defined GNULIB_NAMESPACE && !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))
57# include <sys/stat.h>
58#endif
59/* The include_next requires a split double-inclusion guard. */
60#@INCLUDE_NEXT@ @NEXT_FCNTL_H@
61
62#ifndef _@GUARD_PREFIX@_FCNTL_H
63#define _@GUARD_PREFIX@_FCNTL_H
64
65#ifndef __GLIBC__ /* Avoid namespace pollution on glibc systems. */
66# include <unistd.h>
67#endif
68
69/* Native Windows platforms declare open(), creat() in <io.h>. */
70#if (@GNULIB_OPEN@ || defined GNULIB_POSIXCHECK) \
71 && ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__)
72# include <io.h>
73#endif
74
75
76/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */
77
78/* The definition of _GL_ARG_NONNULL is copied here. */
79
80/* The definition of _GL_WARN_ON_USE is copied here. */
81
82
83/* Declare overridden functions. */
84
85#if @GNULIB_FCNTL@
86# if @REPLACE_FCNTL@
87# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
88# undef fcntl
89# define fcntl rpl_fcntl
90# endif
91_GL_FUNCDECL_RPL (fcntl, int, (int fd, int action, ...));
92_GL_CXXALIAS_RPL (fcntl, int, (int fd, int action, ...));
93# else
94# if !@HAVE_FCNTL@
95_GL_FUNCDECL_SYS (fcntl, int, (int fd, int action, ...));
96# endif
97_GL_CXXALIAS_SYS (fcntl, int, (int fd, int action, ...));
98# endif
99_GL_CXXALIASWARN (fcntl);
100#elif defined GNULIB_POSIXCHECK
101# undef fcntl
102# if HAVE_RAW_DECL_FCNTL
103_GL_WARN_ON_USE (fcntl, "fcntl is not always POSIX compliant - "
104 "use gnulib module fcntl for portability");
105# endif
106#endif
107
108#if @GNULIB_OPEN@
109# if @REPLACE_OPEN@
110# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
111# undef open
112# define open rpl_open
113# endif
114_GL_FUNCDECL_RPL (open, int, (const char *filename, int flags, ...)
115 _GL_ARG_NONNULL ((1)));
116_GL_CXXALIAS_RPL (open, int, (const char *filename, int flags, ...));
117# else
118_GL_CXXALIAS_SYS (open, int, (const char *filename, int flags, ...));
119# endif
120/* On HP-UX 11, in C++ mode, open() is defined as an inline function with a
121 default argument. _GL_CXXALIASWARN does not work in this case. */
122# if !defined __hpux
123_GL_CXXALIASWARN (open);
124# endif
125#elif defined GNULIB_POSIXCHECK
126# undef open
127/* Assume open is always declared. */
128_GL_WARN_ON_USE (open, "open is not always POSIX compliant - "
129 "use gnulib module open for portability");
130#endif
131
132#if @GNULIB_OPENAT@
133# if @REPLACE_OPENAT@
134# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
135# undef openat
136# define openat rpl_openat
137# endif
138_GL_FUNCDECL_RPL (openat, int,
139 (int fd, char const *file, int flags, /* mode_t mode */ ...)
140 _GL_ARG_NONNULL ((2)));
141_GL_CXXALIAS_RPL (openat, int,
142 (int fd, char const *file, int flags, /* mode_t mode */ ...));
143# else
144# if !@HAVE_OPENAT@
145_GL_FUNCDECL_SYS (openat, int,
146 (int fd, char const *file, int flags, /* mode_t mode */ ...)
147 _GL_ARG_NONNULL ((2)));
148# endif
149_GL_CXXALIAS_SYS (openat, int,
150 (int fd, char const *file, int flags, /* mode_t mode */ ...));
151# endif
152_GL_CXXALIASWARN (openat);
153#elif defined GNULIB_POSIXCHECK
154# undef openat
155# if HAVE_RAW_DECL_OPENAT
156_GL_WARN_ON_USE (openat, "openat is not portable - "
157 "use gnulib module openat for portability");
158# endif
159#endif
160
161
162/* Fix up the FD_* macros, only known to be missing on mingw. */
163
164#ifndef FD_CLOEXEC
165# define FD_CLOEXEC 1
166#endif
167
168/* Fix up the supported F_* macros. Intentionally leave other F_*
169 macros undefined. Only known to be missing on mingw. */
170
171#ifndef F_DUPFD_CLOEXEC
172# define F_DUPFD_CLOEXEC 0x40000000
173/* Witness variable: 1 if gnulib defined F_DUPFD_CLOEXEC, 0 otherwise. */
174# define GNULIB_defined_F_DUPFD_CLOEXEC 1
175#else
176# define GNULIB_defined_F_DUPFD_CLOEXEC 0
177#endif
178
179#ifndef F_DUPFD
180# define F_DUPFD 1
181#endif
182
183#ifndef F_GETFD
184# define F_GETFD 2
185#endif
186
187/* Fix up the O_* macros. */
188
189#if !defined O_DIRECT && defined O_DIRECTIO
190/* Tru64 spells it 'O_DIRECTIO'. */
191# define O_DIRECT O_DIRECTIO
192#endif
193
194#if !defined O_CLOEXEC && defined O_NOINHERIT
195/* Mingw spells it 'O_NOINHERIT'. */
196# define O_CLOEXEC O_NOINHERIT
197#endif
198
199#ifndef O_CLOEXEC
200# define O_CLOEXEC 0
201#endif
202
203#ifndef O_DIRECT
204# define O_DIRECT 0
205#endif
206
207#ifndef O_DIRECTORY
208# define O_DIRECTORY 0
209#endif
210
211#ifndef O_DSYNC
212# define O_DSYNC 0
213#endif
214
215#ifndef O_EXEC
216# define O_EXEC O_RDONLY /* This is often close enough in older systems. */
217#endif
218
219#ifndef O_IGNORE_CTTY
220# define O_IGNORE_CTTY 0
221#endif
222
223#ifndef O_NDELAY
224# define O_NDELAY 0
225#endif
226
227#ifndef O_NOATIME
228# define O_NOATIME 0
229#endif
230
231#ifndef O_NONBLOCK
232# define O_NONBLOCK O_NDELAY
233#endif
234
235/* If the gnulib module 'nonblocking' is in use, guarantee a working non-zero
236 value of O_NONBLOCK. Otherwise, O_NONBLOCK is defined (above) to O_NDELAY
237 or to 0 as fallback. */
238#if @GNULIB_NONBLOCKING@
239# if O_NONBLOCK
240# define GNULIB_defined_O_NONBLOCK 0
241# else
242# define GNULIB_defined_O_NONBLOCK 1
243# undef O_NONBLOCK
244# define O_NONBLOCK 0x40000000
245# endif
246#endif
247
248#ifndef O_NOCTTY
249# define O_NOCTTY 0
250#endif
251
252#ifndef O_NOFOLLOW
253# define O_NOFOLLOW 0
254#endif
255
256#ifndef O_NOLINK
257# define O_NOLINK 0
258#endif
259
260#ifndef O_NOLINKS
261# define O_NOLINKS 0
262#endif
263
264#ifndef O_NOTRANS
265# define O_NOTRANS 0
266#endif
267
268#ifndef O_RSYNC
269# define O_RSYNC 0
270#endif
271
272#ifndef O_SEARCH
273# define O_SEARCH O_RDONLY /* This is often close enough in older systems. */
274#endif
275
276#ifndef O_SYNC
277# define O_SYNC 0
278#endif
279
280#ifndef O_TTY_INIT
281# define O_TTY_INIT 0
282#endif
283
284#if O_ACCMODE != (O_RDONLY | O_WRONLY | O_RDWR | O_EXEC | O_SEARCH)
285# undef O_ACCMODE
286# define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR | O_EXEC | O_SEARCH)
287#endif
288
289/* For systems that distinguish between text and binary I/O.
290 O_BINARY is usually declared in fcntl.h */
291#if !defined O_BINARY && defined _O_BINARY
292 /* For MSC-compatible compilers. */
293# define O_BINARY _O_BINARY
294# define O_TEXT _O_TEXT
295#endif
296
297#if defined __BEOS__ || defined __HAIKU__
298 /* BeOS 5 and Haiku have O_BINARY and O_TEXT, but they have no effect. */
299# undef O_BINARY
300# undef O_TEXT
301#endif
302
303#ifndef O_BINARY
304# define O_BINARY 0
305# define O_TEXT 0
306#endif
307
308/* Fix up the AT_* macros. */
309
310/* Work around a bug in Solaris 9 and 10: AT_FDCWD is positive. Its
311 value exceeds INT_MAX, so its use as an int doesn't conform to the
312 C standard, and GCC and Sun C complain in some cases. If the bug
313 is present, undef AT_FDCWD here, so it can be redefined below. */
314#if 0 < AT_FDCWD && AT_FDCWD == 0xffd19553
315# undef AT_FDCWD
316#endif
317
318/* Use the same bit pattern as Solaris 9, but with the proper
319 signedness. The bit pattern is important, in case this actually is
320 Solaris with the above workaround. */
321#ifndef AT_FDCWD
322# define AT_FDCWD (-3041965)
323#endif
324
325/* Use the same values as Solaris 9. This shouldn't matter, but
326 there's no real reason to differ. */
327#ifndef AT_SYMLINK_NOFOLLOW
328# define AT_SYMLINK_NOFOLLOW 4096
329#endif
330
331#ifndef AT_REMOVEDIR
332# define AT_REMOVEDIR 1
333#endif
334
335/* Solaris 9 lacks these two, so just pick unique values. */
336#ifndef AT_SYMLINK_FOLLOW
337# define AT_SYMLINK_FOLLOW 2
338#endif
339
340#ifndef AT_EACCESS
341# define AT_EACCESS 4
342#endif
343
344
345#endif /* _@GUARD_PREFIX@_FCNTL_H */
346#endif /* _@GUARD_PREFIX@_FCNTL_H */
347#endif
diff --git a/lib/getgroups.c b/lib/getgroups.c
new file mode 100644
index 00000000000..f9d36236afe
--- /dev/null
+++ b/lib/getgroups.c
@@ -0,0 +1,116 @@
1/* provide consistent interface to getgroups for systems that don't allow N==0
2
3 Copyright (C) 1996, 1999, 2003, 2006-2012 Free Software Foundation, Inc.
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17
18/* written by Jim Meyering */
19
20#include <config.h>
21
22#include <unistd.h>
23
24#include <errno.h>
25#include <stdlib.h>
26#include <stdint.h>
27
28#if !HAVE_GETGROUPS
29
30/* Provide a stub that fails with ENOSYS, since there is no group
31 information available on mingw. */
32int
33getgroups (int n _GL_UNUSED, GETGROUPS_T *groups _GL_UNUSED)
34{
35 errno = ENOSYS;
36 return -1;
37}
38
39#else /* HAVE_GETGROUPS */
40
41# undef getgroups
42# ifndef GETGROUPS_ZERO_BUG
43# define GETGROUPS_ZERO_BUG 0
44# endif
45
46/* On at least Ultrix 4.3 and NextStep 3.2, getgroups (0, NULL) always
47 fails. On other systems, it returns the number of supplemental
48 groups for the process. This function handles that special case
49 and lets the system-provided function handle all others. However,
50 it can fail with ENOMEM if memory is tight. It is unspecified
51 whether the effective group id is included in the list. */
52
53int
54rpl_getgroups (int n, gid_t *group)
55{
56 int n_groups;
57 GETGROUPS_T *gbuf;
58 int saved_errno;
59
60 if (n < 0)
61 {
62 errno = EINVAL;
63 return -1;
64 }
65
66 if (n != 0 || !GETGROUPS_ZERO_BUG)
67 {
68 int result;
69 if (sizeof *group == sizeof *gbuf)
70 return getgroups (n, (GETGROUPS_T *) group);
71
72 if (SIZE_MAX / sizeof *gbuf <= n)
73 {
74 errno = ENOMEM;
75 return -1;
76 }
77 gbuf = malloc (n * sizeof *gbuf);
78 if (!gbuf)
79 return -1;
80 result = getgroups (n, gbuf);
81 if (0 <= result)
82 {
83 n = result;
84 while (n--)
85 group[n] = gbuf[n];
86 }
87 saved_errno = errno;
88 free (gbuf);
89 errno == saved_errno;
90 return result;
91 }
92
93 n = 20;
94 while (1)
95 {
96 /* No need to worry about address arithmetic overflow here,
97 since the ancient systems that we're running on have low
98 limits on the number of secondary groups. */
99 gbuf = malloc (n * sizeof *gbuf);
100 if (!gbuf)
101 return -1;
102 n_groups = getgroups (n, gbuf);
103 if (n_groups == -1 ? errno != EINVAL : n_groups < n)
104 break;
105 free (gbuf);
106 n *= 2;
107 }
108
109 saved_errno = errno;
110 free (gbuf);
111 errno = saved_errno;
112
113 return n_groups;
114}
115
116#endif /* HAVE_GETGROUPS */
diff --git a/lib/group-member.c b/lib/group-member.c
new file mode 100644
index 00000000000..5fcc7e01d0c
--- /dev/null
+++ b/lib/group-member.c
@@ -0,0 +1,119 @@
1/* group-member.c -- determine whether group id is in calling user's group list
2
3 Copyright (C) 1994, 1997-1998, 2003, 2005-2006, 2009-2012 Free Software
4 Foundation, Inc.
5
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
18
19#include <config.h>
20
21/* Specification. */
22#include <unistd.h>
23
24#include <stdio.h>
25#include <sys/types.h>
26#include <stdlib.h>
27
28#include "xalloc-oversized.h"
29
30/* Most processes have no more than this many groups, and for these
31 processes we can avoid using malloc. */
32enum { GROUPBUF_SIZE = 100 };
33
34struct group_info
35 {
36 gid_t *group;
37 gid_t groupbuf[GROUPBUF_SIZE];
38 };
39
40static void
41free_group_info (struct group_info const *g)
42{
43 if (g->group != g->groupbuf)
44 free (g->group);
45}
46
47static int
48get_group_info (struct group_info *gi)
49{
50 int n_groups = getgroups (GROUPBUF_SIZE, gi->groupbuf);
51 gi->group = gi->groupbuf;
52
53 if (n_groups < 0)
54 {
55 int n_group_slots = getgroups (0, NULL);
56 if (0 <= n_group_slots
57 && ! xalloc_oversized (n_group_slots, sizeof *gi->group))
58 {
59 gi->group = malloc (n_group_slots * sizeof *gi->group);
60 if (gi->group)
61 n_groups = getgroups (n_group_slots, gi->group);
62 }
63 }
64
65 /* In case of error, the user loses. */
66 return n_groups;
67}
68
69/* Return non-zero if GID is one that we have in our groups list.
70 Note that the groups list is not guaranteed to contain the current
71 or effective group ID, so they should generally be checked
72 separately. */
73
74int
75group_member (gid_t gid)
76{
77 int i;
78 int found;
79 struct group_info gi;
80 int n_groups = get_group_info (&gi);
81
82 /* Search through the list looking for GID. */
83 found = 0;
84 for (i = 0; i < n_groups; i++)
85 {
86 if (gid == gi.group[i])
87 {
88 found = 1;
89 break;
90 }
91 }
92
93 free_group_info (&gi);
94
95 return found;
96}
97
98#ifdef TEST
99
100char *program_name;
101
102int
103main (int argc, char **argv)
104{
105 int i;
106
107 program_name = argv[0];
108
109 for (i = 1; i < argc; i++)
110 {
111 gid_t gid;
112
113 gid = atoi (argv[i]);
114 printf ("%d: %s\n", gid, group_member (gid) ? "yes" : "no");
115 }
116 exit (0);
117}
118
119#endif /* TEST */
diff --git a/lib/root-uid.h b/lib/root-uid.h
new file mode 100644
index 00000000000..2379773c291
--- /dev/null
+++ b/lib/root-uid.h
@@ -0,0 +1,30 @@
1/* The user ID that always has appropriate privileges in the POSIX sense.
2
3 Copyright 2012 Free Software Foundation, Inc.
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 Written by Paul Eggert. */
19
20#ifndef ROOT_UID_H_
21#define ROOT_UID_H_
22
23/* The user ID that always has appropriate privileges in the POSIX sense. */
24#ifdef __TANDEM
25# define ROOT_UID 65535
26#else
27# define ROOT_UID 0
28#endif
29
30#endif
diff --git a/lib/xalloc-oversized.h b/lib/xalloc-oversized.h
new file mode 100644
index 00000000000..ad777d8dd79
--- /dev/null
+++ b/lib/xalloc-oversized.h
@@ -0,0 +1,38 @@
1/* xalloc-oversized.h -- memory allocation size checking
2
3 Copyright (C) 1990-2000, 2003-2004, 2006-2012 Free Software Foundation, Inc.
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17
18#ifndef XALLOC_OVERSIZED_H_
19# define XALLOC_OVERSIZED_H_
20
21# include <stddef.h>
22
23/* Return 1 if an array of N objects, each of size S, cannot exist due
24 to size arithmetic overflow. S must be positive and N must be
25 nonnegative. This is a macro, not a function, so that it
26 works correctly even when SIZE_MAX < N.
27
28 By gnulib convention, SIZE_MAX represents overflow in size
29 calculations, so the conservative dividend to use here is
30 SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value.
31 However, malloc (SIZE_MAX) fails on all known hosts where
32 sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for
33 exactly-SIZE_MAX allocations on such hosts; this avoids a test and
34 branch when S is known to be 1. */
35# define xalloc_oversized(n, s) \
36 ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n))
37
38#endif /* !XALLOC_OVERSIZED_H_ */
diff --git a/m4/euidaccess.m4 b/m4/euidaccess.m4
new file mode 100644
index 00000000000..2de95b88ba8
--- /dev/null
+++ b/m4/euidaccess.m4
@@ -0,0 +1,52 @@
1# euidaccess.m4 serial 15
2dnl Copyright (C) 2002-2012 Free Software Foundation, Inc.
3dnl This file is free software; the Free Software Foundation
4dnl gives unlimited permission to copy and/or distribute it,
5dnl with or without modifications, as long as this notice is preserved.
6
7AC_DEFUN([gl_FUNC_NONREENTRANT_EUIDACCESS],
8[
9 AC_REQUIRE([gl_FUNC_EUIDACCESS])
10 AC_CHECK_DECLS([setregid])
11 AC_DEFINE([PREFER_NONREENTRANT_EUIDACCESS], [1],
12 [Define this if you prefer euidaccess to return the correct result
13 even if this would make it nonreentrant. Define this only if your
14 entire application is safe even if the uid or gid might temporarily
15 change. If your application uses signal handlers or threads it
16 is probably not safe.])
17])
18
19AC_DEFUN([gl_FUNC_EUIDACCESS],
20[
21 AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
22
23 dnl Persuade glibc <unistd.h> to declare euidaccess().
24 AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
25
26 AC_CHECK_FUNCS([euidaccess])
27 if test $ac_cv_func_euidaccess = no; then
28 HAVE_EUIDACCESS=0
29 fi
30])
31
32# Prerequisites of lib/euidaccess.c.
33AC_DEFUN([gl_PREREQ_EUIDACCESS], [
34 dnl Prefer POSIX faccessat over non-standard euidaccess.
35 AC_CHECK_FUNCS_ONCE([faccessat])
36 dnl Try various other non-standard fallbacks.
37 AC_CHECK_HEADERS([libgen.h])
38 AC_FUNC_GETGROUPS
39
40 # Solaris 9 and 10 need -lgen to get the eaccess function.
41 # Save and restore LIBS so -lgen isn't added to it. Otherwise, *all*
42 # programs in the package would end up linked with that potentially-shared
43 # library, inducing unnecessary run-time overhead.
44 LIB_EACCESS=
45 AC_SUBST([LIB_EACCESS])
46 gl_saved_libs=$LIBS
47 AC_SEARCH_LIBS([eaccess], [gen],
48 [test "$ac_cv_search_eaccess" = "none required" ||
49 LIB_EACCESS=$ac_cv_search_eaccess])
50 AC_CHECK_FUNCS([eaccess])
51 LIBS=$gl_saved_libs
52])
diff --git a/m4/faccessat.m4 b/m4/faccessat.m4
new file mode 100644
index 00000000000..82f3b1f8dde
--- /dev/null
+++ b/m4/faccessat.m4
@@ -0,0 +1,28 @@
1# serial 6
2# See if we need to provide faccessat replacement.
3
4dnl Copyright (C) 2009-2012 Free Software Foundation, Inc.
5dnl This file is free software; the Free Software Foundation
6dnl gives unlimited permission to copy and/or distribute it,
7dnl with or without modifications, as long as this notice is preserved.
8
9# Written by Eric Blake.
10
11AC_DEFUN([gl_FUNC_FACCESSAT],
12[
13 AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
14
15 dnl Persuade glibc <unistd.h> to declare faccessat().
16 AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
17
18 AC_CHECK_FUNCS_ONCE([faccessat])
19 if test $ac_cv_func_faccessat = no; then
20 HAVE_FACCESSAT=0
21 fi
22])
23
24# Prerequisites of lib/faccessat.m4.
25AC_DEFUN([gl_PREREQ_FACCESSAT],
26[
27 AC_CHECK_FUNCS([access])
28])
diff --git a/m4/fcntl_h.m4 b/m4/fcntl_h.m4
new file mode 100644
index 00000000000..cac28aeb283
--- /dev/null
+++ b/m4/fcntl_h.m4
@@ -0,0 +1,50 @@
1# serial 15
2# Configure fcntl.h.
3dnl Copyright (C) 2006-2007, 2009-2012 Free Software Foundation, Inc.
4dnl This file is free software; the Free Software Foundation
5dnl gives unlimited permission to copy and/or distribute it,
6dnl with or without modifications, as long as this notice is preserved.
7
8dnl Written by Paul Eggert.
9
10AC_DEFUN([gl_FCNTL_H],
11[
12 AC_REQUIRE([gl_FCNTL_H_DEFAULTS])
13 AC_REQUIRE([gl_FCNTL_O_FLAGS])
14 gl_NEXT_HEADERS([fcntl.h])
15
16 dnl Ensure the type pid_t gets defined.
17 AC_REQUIRE([AC_TYPE_PID_T])
18
19 dnl Ensure the type mode_t gets defined.
20 AC_REQUIRE([AC_TYPE_MODE_T])
21
22 dnl Check for declarations of anything we want to poison if the
23 dnl corresponding gnulib module is not in use, if it is not common
24 dnl enough to be declared everywhere.
25 gl_WARN_ON_USE_PREPARE([[#include <fcntl.h>
26 ]], [fcntl openat])
27])
28
29AC_DEFUN([gl_FCNTL_MODULE_INDICATOR],
30[
31 dnl Use AC_REQUIRE here, so that the default settings are expanded once only.
32 AC_REQUIRE([gl_FCNTL_H_DEFAULTS])
33 gl_MODULE_INDICATOR_SET_VARIABLE([$1])
34 dnl Define it also as a C macro, for the benefit of the unit tests.
35 gl_MODULE_INDICATOR_FOR_TESTS([$1])
36])
37
38AC_DEFUN([gl_FCNTL_H_DEFAULTS],
39[
40 GNULIB_FCNTL=0; AC_SUBST([GNULIB_FCNTL])
41 GNULIB_NONBLOCKING=0; AC_SUBST([GNULIB_NONBLOCKING])
42 GNULIB_OPEN=0; AC_SUBST([GNULIB_OPEN])
43 GNULIB_OPENAT=0; AC_SUBST([GNULIB_OPENAT])
44 dnl Assume proper GNU behavior unless another module says otherwise.
45 HAVE_FCNTL=1; AC_SUBST([HAVE_FCNTL])
46 HAVE_OPENAT=1; AC_SUBST([HAVE_OPENAT])
47 REPLACE_FCNTL=0; AC_SUBST([REPLACE_FCNTL])
48 REPLACE_OPEN=0; AC_SUBST([REPLACE_OPEN])
49 REPLACE_OPENAT=0; AC_SUBST([REPLACE_OPENAT])
50])
diff --git a/m4/getgroups.m4 b/m4/getgroups.m4
new file mode 100644
index 00000000000..17473af486b
--- /dev/null
+++ b/m4/getgroups.m4
@@ -0,0 +1,107 @@
1# serial 18
2
3dnl From Jim Meyering.
4dnl A wrapper around AC_FUNC_GETGROUPS.
5
6# Copyright (C) 1996-1997, 1999-2004, 2008-2012 Free Software Foundation, Inc.
7#
8# This file is free software; the Free Software Foundation
9# gives unlimited permission to copy and/or distribute it,
10# with or without modifications, as long as this notice is preserved.
11
12m4_version_prereq([2.70], [] ,[
13
14# This is taken from the following Autoconf patch:
15# http://git.savannah.gnu.org/gitweb/?p=autoconf.git;a=commitdiff;h=7fbb553727ed7e0e689a17594b58559ecf3ea6e9
16AC_DEFUN([AC_FUNC_GETGROUPS],
17[
18 AC_REQUIRE([AC_TYPE_GETGROUPS])dnl
19 AC_REQUIRE([AC_TYPE_SIZE_T])dnl
20 AC_REQUIRE([AC_CANONICAL_HOST])dnl for cross-compiles
21 AC_CHECK_FUNC([getgroups])
22
23 # If we don't yet have getgroups, see if it's in -lbsd.
24 # This is reported to be necessary on an ITOS 3000WS running SEIUX 3.1.
25 ac_save_LIBS=$LIBS
26 if test $ac_cv_func_getgroups = no; then
27 AC_CHECK_LIB(bsd, getgroups, [GETGROUPS_LIB=-lbsd])
28 fi
29
30 # Run the program to test the functionality of the system-supplied
31 # getgroups function only if there is such a function.
32 if test $ac_cv_func_getgroups = yes; then
33 AC_CACHE_CHECK([for working getgroups], [ac_cv_func_getgroups_works],
34 [AC_RUN_IFELSE(
35 [AC_LANG_PROGRAM(
36 [AC_INCLUDES_DEFAULT],
37 [[/* On Ultrix 4.3, getgroups (0, 0) always fails. */
38 return getgroups (0, 0) == -1;]])
39 ],
40 [ac_cv_func_getgroups_works=yes],
41 [ac_cv_func_getgroups_works=no],
42 [case "$host_os" in # ((
43 # Guess yes on glibc systems.
44 *-gnu*) ac_cv_func_getgroups_works="guessing yes" ;;
45 # If we don't know, assume the worst.
46 *) ac_cv_func_getgroups_works="guessing no" ;;
47 esac
48 ])
49 ])
50 else
51 ac_cv_func_getgroups_works=no
52 fi
53 case "$ac_cv_func_getgroups_works" in
54 *yes)
55 AC_DEFINE([HAVE_GETGROUPS], [1],
56 [Define to 1 if your system has a working `getgroups' function.])
57 ;;
58 esac
59 LIBS=$ac_save_LIBS
60])# AC_FUNC_GETGROUPS
61
62])
63
64AC_DEFUN([gl_FUNC_GETGROUPS],
65[
66 AC_REQUIRE([AC_TYPE_GETGROUPS])
67 AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
68 AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
69
70 AC_FUNC_GETGROUPS
71 if test $ac_cv_func_getgroups != yes; then
72 HAVE_GETGROUPS=0
73 else
74 if test "$ac_cv_type_getgroups" != gid_t \
75 || { case "$ac_cv_func_getgroups_works" in
76 *yes) false;;
77 *) true;;
78 esac
79 }; then
80 REPLACE_GETGROUPS=1
81 AC_DEFINE([GETGROUPS_ZERO_BUG], [1], [Define this to 1 if
82 getgroups(0,NULL) does not return the number of groups.])
83 else
84 dnl Detect FreeBSD bug; POSIX requires getgroups(-1,ptr) to fail.
85 AC_CACHE_CHECK([whether getgroups handles negative values],
86 [gl_cv_func_getgroups_works],
87 [AC_RUN_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT],
88 [[int size = getgroups (0, 0);
89 gid_t *list = malloc (size * sizeof *list);
90 return getgroups (-1, list) != -1;]])],
91 [gl_cv_func_getgroups_works=yes],
92 [gl_cv_func_getgroups_works=no],
93 [case "$host_os" in
94 # Guess yes on glibc systems.
95 *-gnu*) gl_cv_func_getgroups_works="guessing yes" ;;
96 # If we don't know, assume the worst.
97 *) gl_cv_func_getgroups_works="guessing no" ;;
98 esac
99 ])])
100 case "$gl_cv_func_getgroups_works" in
101 *yes) ;;
102 *) REPLACE_GETGROUPS=1 ;;
103 esac
104 fi
105 fi
106 test -n "$GETGROUPS_LIB" && LIBS="$GETGROUPS_LIB $LIBS"
107])
diff --git a/m4/group-member.m4 b/m4/group-member.m4
new file mode 100644
index 00000000000..c393b5b1303
--- /dev/null
+++ b/m4/group-member.m4
@@ -0,0 +1,29 @@
1# serial 14
2
3# Copyright (C) 1999-2001, 2003-2007, 2009-2012 Free Software Foundation, Inc.
4
5# This file is free software; the Free Software Foundation
6# gives unlimited permission to copy and/or distribute it,
7# with or without modifications, as long as this notice is preserved.
8
9dnl Written by Jim Meyering
10
11AC_DEFUN([gl_FUNC_GROUP_MEMBER],
12[
13 AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
14
15 dnl Persuade glibc <unistd.h> to declare group_member().
16 AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
17
18 dnl Do this replacement check manually because I want the hyphen
19 dnl (not the underscore) in the filename.
20 AC_CHECK_FUNC([group_member], , [
21 HAVE_GROUP_MEMBER=0
22 ])
23])
24
25# Prerequisites of lib/group-member.c.
26AC_DEFUN([gl_PREREQ_GROUP_MEMBER],
27[
28 AC_REQUIRE([AC_FUNC_GETGROUPS])
29])