From 899d423eaf3f66e59ffffefe40b2ba2137bd0050 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Fri, 19 Jun 1998 13:01:35 +0000 Subject: Update. 1998-06-10 Thorsten Kukuk * nis/Makefile: Add nis-initgroups and compat-initgroups. * nis/libnss_compat.map: Add _nss_compat_initgroups. * nis/libnss_nis.map: Add _nss_nis_initgroups. * nis/nss_compat/compat-initgroups.c: New, faster then getgrent(). * nis/nss_nis/nis-initgroups.c: Likewise. * libc-work/nss/nsswitch.c: Rename nss_lookup_function to __nss_lookup_function and make it public. * grp/initgroups.c: Rewrite, to use initgroups function from NSS module if exists, else use old method. 1998-06-19 Ulrich Drepper * nss/getXXbyYY_r.c (lookup_function): Correct return in type definition. * nss/getXXent_r.c (set_function, end_function, get_function): Likewise. Reported by Thorsten Kukuk. * sysdeps/unix/sysv/linux/sigstack.c: Mark sigstack as dangerous. 1998-06-19 Andreas Jaeger * sysdeps/unix/sysv/linux/sparc/Dist: Follow change from 1998-06-16 and distribute kernel_termios.h. * nis/Makefile (distribute): Add nis_xdr.h. 1998-06-19 Andreas Jaeger * sysdeps/unix/sysv/linux/sigstack.c (sigstack): Disable for kernels that don't have sigaltstack. --- grp/initgroups.c | 184 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 130 insertions(+), 54 deletions(-) (limited to 'grp') diff --git a/grp/initgroups.c b/grp/initgroups.c index 2ca90ab18d..2150fa968c 100644 --- a/grp/initgroups.c +++ b/grp/initgroups.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1989, 1991, 1993, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1989, 91, 93, 96, 97, 98 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -23,8 +23,102 @@ #include #include #include +#include +/* Type of the lookup function. */ +typedef enum nss_status (*initgroups_function) (const char *, gid_t, + long int *, long int *, + gid_t *, long int, int *); +/* 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 *); + +/* The lookup function for the first entry of this service. */ +extern int __nss_group_lookup (service_user **nip, const char *name, + void **fctp); +extern void *__nss_lookup_function (service_user *ni, const char *fct_name); + +extern service_user *__nss_group_database; + +static enum nss_status +compat_call (service_user *nip, const char *user, gid_t group, long int *start, + long int *size, gid_t *groups, long int limit, int *errnop) +{ + struct group grpbuf, *g; + size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX); + char *tmpbuf; + enum nss_status status; + set_function setgrent_fct; + get_function getgrent_fct; + end_function endgrent_fct; + + setgrent_fct = __nss_lookup_function (nip, "setgrent"); + status = (*setgrent_fct) (); + if (status != NSS_STATUS_SUCCESS) + return status; + + getgrent_fct = __nss_lookup_function (nip, "getgrent_r"); + endgrent_fct = __nss_lookup_function (nip, "endgrent"); + + tmpbuf = __alloca (buflen); + + do + { + while ((status = + (*getgrent_fct) (&grpbuf, tmpbuf, buflen, errnop)) == + NSS_STATUS_TRYAGAIN && *errnop == ERANGE) + { + buflen *= 2; + tmpbuf = __alloca (buflen); + } + + if (status != NSS_STATUS_SUCCESS) + goto done; + + g = &grpbuf; + if (g->gr_gid != group) + { + char **m; + + for (m = g->gr_mem; *m != NULL; ++m) + if (strcmp (*m, user) == 0) + { + /* Matches user. Insert this group. */ + if (*start == *size && limit <= 0) + { + /* Need a bigger buffer. */ + groups = realloc (groups, *size * sizeof (*groups)); + if (groups == NULL) + goto done; + *size *= 2; + } + + groups[*start] = g->gr_gid; + *start += 1; + + if (*start == limit) + /* Can't take any more groups; stop searching. */ + goto done; + + break; + } + } + } + while (status == NSS_STATUS_SUCCESS); + + done: + (*endgrent_fct) (); + + return NSS_STATUS_SUCCESS; +} + /* Initialize the group set for the current user by reading the group database and using all groups of which USER is a member. Also include GROUP. */ @@ -40,76 +134,58 @@ initgroups (user, group) #else - struct group grpbuf, *g; - size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX); - char *tmpbuf; - size_t n; - size_t ngroups; + service_user *nip = NULL; + initgroups_function fct; + enum nss_status status = NSS_STATUS_UNAVAIL; + int no_more; + /* Start is one, because we have the first group as parameter. */ + long int start = 1; + long int size; gid_t *groups; - int status; #ifdef NGROUPS_MAX # define limit NGROUPS_MAX - ngroups = limit; + size = limit; #else long int limit = sysconf (_SC_NGROUPS_MAX); if (limit > 0) - ngroups = limit; + size = limit; else /* No fixed limit on groups. Pick a starting buffer size. */ - ngroups = 16; + size = 16; #endif - groups = __alloca (ngroups * sizeof *groups); - tmpbuf = __alloca (buflen); - - setgrent (); + groups = malloc (size * sizeof (gid_t *)); - n = 0; - groups[n++] = group; + groups[0] = group; - do + if (__nss_group_database != NULL) { - while ((status = __getgrent_r (&grpbuf, tmpbuf, buflen, &g)) != 0 - && errno == ERANGE) - { - buflen *= 2; - tmpbuf = __alloca (buflen); - } - - if (status == 0 && g->gr_gid != group) - { - char **m; - - for (m = g->gr_mem; *m != NULL; ++m) - if (strcmp (*m, user) == 0) - { - /* Matches user. Insert this group. */ - if (n == ngroups && limit <= 0) - { - /* Need a bigger buffer. */ - gid_t *newgrp; - newgrp = __alloca (ngroups * 2 * sizeof *groups); - groups = memcpy (newgrp, groups, ngroups * sizeof *groups); - ngroups *= 2; - } - - groups[n++] = g->gr_gid; - - if (n == limit) - /* Can't take any more groups; stop searching. */ - goto done; - - break; - } - } + no_more = 0; + nip = __nss_group_database; } - while (status == 0); + else + no_more = __nss_database_lookup ("group", NULL, + "compat [NOTFOUND=return] files", &nip); -done: - endgrent (); + while (! no_more) + { + fct = __nss_lookup_function (nip, "initgroups"); + + if (fct == NULL) + status = compat_call (nip, user, group, &start, &size, groups, + limit, &errno); + else + status = (*fct) (user, group, &start, &size, groups, limit, + &errno); + + if (nip->next == NULL) + no_more = -1; + else + nip = nip->next; + } - return setgroups (n, groups); + return setgroups (start, groups); #endif } -- cgit 1.4.1