1 /* Prototype for the setgrent functions we use here. */
2 typedef enum nss_status (*set_function
) (void);
4 /* Prototype for the endgrent functions we use here. */
5 typedef enum nss_status (*end_function
) (void);
7 /* Prototype for the setgrent functions we use here. */
8 typedef enum nss_status (*get_function
) (struct group
*, char *,
11 /* This file is also used in nscd where __libc_alloca_cutoff is not
14 # define __libc_use_alloca(size) ((size) < __MAX_ALLOCA_CUTOFF * 4)
18 static enum nss_status
19 compat_call (service_user
*nip
, const char *user
, gid_t group
, long int *start
,
20 long int *size
, gid_t
**groupsp
, long int limit
, int *errnop
)
23 size_t buflen
= __sysconf (_SC_GETGR_R_SIZE_MAX
);
24 enum nss_status status
;
25 set_function setgrent_fct
;
26 get_function getgrent_fct
;
27 end_function endgrent_fct
;
28 gid_t
*groups
= *groupsp
;
30 getgrent_fct
= __nss_lookup_function (nip
, "getgrent_r");
31 if (getgrent_fct
== NULL
)
32 return NSS_STATUS_UNAVAIL
;
34 setgrent_fct
= __nss_lookup_function (nip
, "setgrent");
37 status
= DL_CALL_FCT (setgrent_fct
, ());
38 if (status
!= NSS_STATUS_SUCCESS
)
42 endgrent_fct
= __nss_lookup_function (nip
, "endgrent");
44 char *tmpbuf
= __alloca (buflen
);
45 bool use_malloc
= false;
46 enum nss_status result
= NSS_STATUS_SUCCESS
;
50 while ((status
= DL_CALL_FCT (getgrent_fct
,
51 (&grpbuf
, tmpbuf
, buflen
, errnop
)),
52 status
== NSS_STATUS_TRYAGAIN
)
55 if (__libc_use_alloca (buflen
* 2))
56 tmpbuf
= extend_alloca (tmpbuf
, buflen
, buflen
* 2);
60 char *newbuf
= realloc (use_malloc
? tmpbuf
: NULL
, buflen
);
63 result
= NSS_STATUS_TRYAGAIN
;
71 if (status
!= NSS_STATUS_SUCCESS
)
74 if (grpbuf
.gr_gid
!= group
)
78 for (m
= grpbuf
.gr_mem
; *m
!= NULL
; ++m
)
79 if (strcmp (*m
, user
) == 0)
81 /* Check whether the group is already on the list. */
83 for (cnt
= 0; cnt
< *start
; ++cnt
)
84 if (groups
[cnt
] == grpbuf
.gr_gid
)
89 /* Matches user and not yet on the list. Insert
91 if (__builtin_expect (*start
== *size
, 0))
93 /* Need a bigger buffer. */
97 if (limit
> 0 && *size
== limit
)
98 /* We reached the maximum. */
104 newsize
= MIN (limit
, 2 * *size
);
106 newgroups
= realloc (groups
,
107 newsize
* sizeof (*groups
));
108 if (newgroups
== NULL
)
110 *groupsp
= groups
= newgroups
;
114 groups
[*start
] = grpbuf
.gr_gid
;
122 while (status
== NSS_STATUS_SUCCESS
);
129 DL_CALL_FCT (endgrent_fct
, ());