aboutsummaryrefslogtreecommitdiff
path: root/grp/compat-initgroups.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2004-09-30 02:24:51 +0000
committerUlrich Drepper <drepper@redhat.com>2004-09-30 02:24:51 +0000
commitf7e7a396812f5e6a6ec49ad84204d334630964a0 (patch)
treed1a47d6911b5992497cc8aa30d392e7c0f175e12 /grp/compat-initgroups.c
parent04c785b27fd35c740cc9b759b324adb8d6ab9747 (diff)
downloadglibc-f7e7a396812f5e6a6ec49ad84204d334630964a0.tar
glibc-f7e7a396812f5e6a6ec49ad84204d334630964a0.tar.gz
glibc-f7e7a396812f5e6a6ec49ad84204d334630964a0.tar.bz2
glibc-f7e7a396812f5e6a6ec49ad84204d334630964a0.zip
Update.
* grp/initgroups.c: Move compat_call implementation... * grp/compat-initgroups.c: ...to here. New file. * grp/Makefile (distribute): Add compat-initgroups.c. (CFLAGS-initgroups.c): Add -DUSE_NSCD=1. * mscd/initgrcache.c: New file. * nscd/nscd_initgroups.c: New file. * nscd/Makefile (routines): Add nscd_initgroups. (nscd-modules): Add initgrcache. * nscd/cache.c (prune_cache): Add support for INITGROUPS entries. * nscd/connections.c: Handle INITGROUPS requests. * nscd/nscd-client.h: Define INITGROUPS, initgr_response_header. Add initgrdata element to struct datahead. Fix typo in comment. * nscd/nscd_proto.h: Declare __nscd_getgrouplist. Fix parameter type in __nscd_getgrgrid_r. * nscd/selinux.c (perms): Add INITGROUPS entry. * nscd/nscd_getai.c: No need to include <sys/mman.h>. * sunrpc/get_myaddr.c (get_myaddress): Account for interfaces without assigned addresses. * sunrpc/pmap_clnt.c (__get_myaddress): Likewise. * sunrpc/pmap_rmt.c (getbroadcastnets): Likewise. * sunrpc/clnt_udp.c (is_network_up): Likewise.
Diffstat (limited to 'grp/compat-initgroups.c')
-rw-r--r--grp/compat-initgroups.c98
1 files changed, 98 insertions, 0 deletions
diff --git a/grp/compat-initgroups.c b/grp/compat-initgroups.c
new file mode 100644
index 0000000000..585c4aecbb
--- /dev/null
+++ b/grp/compat-initgroups.c
@@ -0,0 +1,98 @@
+/* Prototype for the setgrent functions we use here. */
+typedef enum nss_status (*set_function) (void);
+
+/* Prototype for the endgrent functions we use here. */
+typedef enum nss_status (*end_function) (void);
+
+/* Prototype for the setgrent functions we use here. */
+typedef enum nss_status (*get_function) (struct group *, char *,
+ size_t, int *);
+
+static enum nss_status
+compat_call (service_user *nip, const char *user, gid_t group, long int *start,
+ long int *size, gid_t **groupsp, long int limit, int *errnop)
+{
+ struct group grpbuf;
+ size_t buflen = __sysconf (_SC_GETGR_R_SIZE_MAX);
+ char *tmpbuf;
+ enum nss_status status;
+ set_function setgrent_fct;
+ get_function getgrent_fct;
+ end_function endgrent_fct;
+ gid_t *groups = *groupsp;
+
+ getgrent_fct = __nss_lookup_function (nip, "getgrent_r");
+ if (getgrent_fct == NULL)
+ return NSS_STATUS_UNAVAIL;
+
+ setgrent_fct = __nss_lookup_function (nip, "setgrent");
+ if (setgrent_fct)
+ {
+ status = DL_CALL_FCT (setgrent_fct, ());
+ if (status != NSS_STATUS_SUCCESS)
+ return status;
+ }
+
+ endgrent_fct = __nss_lookup_function (nip, "endgrent");
+
+ tmpbuf = __alloca (buflen);
+
+ do
+ {
+ while ((status = DL_CALL_FCT (getgrent_fct,
+ (&grpbuf, tmpbuf, buflen, errnop)),
+ status == NSS_STATUS_TRYAGAIN)
+ && *errnop == ERANGE)
+ {
+ buflen *= 2;
+ tmpbuf = __alloca (buflen);
+ }
+
+ if (status != NSS_STATUS_SUCCESS)
+ goto done;
+
+ if (grpbuf.gr_gid != group)
+ {
+ char **m;
+
+ for (m = grpbuf.gr_mem; *m != NULL; ++m)
+ if (strcmp (*m, user) == 0)
+ {
+ /* Matches user. Insert this group. */
+ if (__builtin_expect (*start == *size, 0))
+ {
+ /* Need a bigger buffer. */
+ gid_t *newgroups;
+ long int newsize;
+
+ if (limit > 0 && *size == limit)
+ /* We reached the maximum. */
+ goto done;
+
+ if (limit <= 0)
+ newsize = 2 * *size;
+ else
+ newsize = MIN (limit, 2 * *size);
+
+ newgroups = realloc (groups, newsize * sizeof (*groups));
+ if (newgroups == NULL)
+ goto done;
+ *groupsp = groups = newgroups;
+ *size = newsize;
+ }
+
+ groups[*start] = grpbuf.gr_gid;
+ *start += 1;
+
+ break;
+ }
+ }
+ }
+ while (status == NSS_STATUS_SUCCESS);
+
+ done:
+ if (endgrent_fct)
+ DL_CALL_FCT (endgrent_fct, ());
+
+ return NSS_STATUS_SUCCESS;
+}