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 *,
12 static enum nss_status
13 compat_call (service_user
*nip
, const char *user
, gid_t group
, long int *start
,
14 long int *size
, gid_t
**groupsp
, long int limit
, int *errnop
)
17 enum nss_status status
;
18 set_function setgrent_fct
;
19 get_function getgrent_fct
;
20 end_function endgrent_fct
;
21 gid_t
*groups
= *groupsp
;
23 getgrent_fct
= __nss_lookup_function (nip
, "getgrent_r");
24 if (getgrent_fct
== NULL
)
25 return NSS_STATUS_UNAVAIL
;
27 setgrent_fct
= __nss_lookup_function (nip
, "setgrent");
30 status
= DL_CALL_FCT (setgrent_fct
, ());
31 if (status
!= NSS_STATUS_SUCCESS
)
35 endgrent_fct
= __nss_lookup_function (nip
, "endgrent");
37 struct scratch_buffer tmpbuf
;
38 scratch_buffer_init (&tmpbuf
);
39 enum nss_status result
= NSS_STATUS_SUCCESS
;
43 while ((status
= DL_CALL_FCT (getgrent_fct
,
44 (&grpbuf
, tmpbuf
.data
, tmpbuf
.length
,
46 status
== NSS_STATUS_TRYAGAIN
)
49 if (!scratch_buffer_grow (&tmpbuf
))
51 result
= NSS_STATUS_TRYAGAIN
;
56 if (status
!= NSS_STATUS_SUCCESS
)
59 if (grpbuf
.gr_gid
!= group
)
63 for (m
= grpbuf
.gr_mem
; *m
!= NULL
; ++m
)
64 if (strcmp (*m
, user
) == 0)
66 /* Check whether the group is already on the list. */
68 for (cnt
= 0; cnt
< *start
; ++cnt
)
69 if (groups
[cnt
] == grpbuf
.gr_gid
)
74 /* Matches user and not yet on the list. Insert
76 if (__glibc_unlikely (*start
== *size
))
78 /* Need a bigger buffer. */
82 if (limit
> 0 && *size
== limit
)
83 /* We reached the maximum. */
89 newsize
= MIN (limit
, 2 * *size
);
91 newgroups
= realloc (groups
,
92 newsize
* sizeof (*groups
));
93 if (newgroups
== NULL
)
95 *groupsp
= groups
= newgroups
;
99 groups
[*start
] = grpbuf
.gr_gid
;
107 while (status
== NSS_STATUS_SUCCESS
);
110 scratch_buffer_free (&tmpbuf
);
113 DL_CALL_FCT (endgrent_fct
, ());