]>
Commit | Line | Data |
---|---|---|
f7e7a396 UD |
1 | /* Prototype for the setgrent functions we use here. */ |
2 | typedef enum nss_status (*set_function) (void); | |
3 | ||
4 | /* Prototype for the endgrent functions we use here. */ | |
5 | typedef enum nss_status (*end_function) (void); | |
6 | ||
7 | /* Prototype for the setgrent functions we use here. */ | |
8 | typedef enum nss_status (*get_function) (struct group *, char *, | |
9 | size_t, int *); | |
10 | ||
bc16e0c4 | 11 | |
f7e7a396 UD |
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) | |
15 | { | |
16 | struct group grpbuf; | |
f7e7a396 UD |
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; | |
22 | ||
23 | getgrent_fct = __nss_lookup_function (nip, "getgrent_r"); | |
24 | if (getgrent_fct == NULL) | |
25 | return NSS_STATUS_UNAVAIL; | |
26 | ||
27 | setgrent_fct = __nss_lookup_function (nip, "setgrent"); | |
28 | if (setgrent_fct) | |
29 | { | |
30 | status = DL_CALL_FCT (setgrent_fct, ()); | |
31 | if (status != NSS_STATUS_SUCCESS) | |
32 | return status; | |
33 | } | |
34 | ||
35 | endgrent_fct = __nss_lookup_function (nip, "endgrent"); | |
36 | ||
866ba63b FW |
37 | struct scratch_buffer tmpbuf; |
38 | scratch_buffer_init (&tmpbuf); | |
1a9dd4e4 | 39 | enum nss_status result = NSS_STATUS_SUCCESS; |
f7e7a396 UD |
40 | |
41 | do | |
42 | { | |
43 | while ((status = DL_CALL_FCT (getgrent_fct, | |
866ba63b FW |
44 | (&grpbuf, tmpbuf.data, tmpbuf.length, |
45 | errnop)), | |
f7e7a396 UD |
46 | status == NSS_STATUS_TRYAGAIN) |
47 | && *errnop == ERANGE) | |
48 | { | |
866ba63b | 49 | if (!scratch_buffer_grow (&tmpbuf)) |
1a9dd4e4 | 50 | { |
866ba63b FW |
51 | result = NSS_STATUS_TRYAGAIN; |
52 | goto done; | |
1a9dd4e4 | 53 | } |
f7e7a396 UD |
54 | } |
55 | ||
56 | if (status != NSS_STATUS_SUCCESS) | |
57 | goto done; | |
58 | ||
59 | if (grpbuf.gr_gid != group) | |
60 | { | |
61 | char **m; | |
62 | ||
63 | for (m = grpbuf.gr_mem; *m != NULL; ++m) | |
64 | if (strcmp (*m, user) == 0) | |
65 | { | |
695c4370 UD |
66 | /* Check whether the group is already on the list. */ |
67 | long int cnt; | |
68 | for (cnt = 0; cnt < *start; ++cnt) | |
69 | if (groups[cnt] == grpbuf.gr_gid) | |
70 | break; | |
71 | ||
72 | if (cnt == *start) | |
73 | { | |
74 | /* Matches user and not yet on the list. Insert | |
75 | this group. */ | |
a1ffb40e | 76 | if (__glibc_unlikely (*start == *size)) |
695c4370 UD |
77 | { |
78 | /* Need a bigger buffer. */ | |
79 | gid_t *newgroups; | |
80 | long int newsize; | |
81 | ||
82 | if (limit > 0 && *size == limit) | |
83 | /* We reached the maximum. */ | |
84 | goto done; | |
85 | ||
86 | if (limit <= 0) | |
87 | newsize = 2 * *size; | |
88 | else | |
89 | newsize = MIN (limit, 2 * *size); | |
90 | ||
91 | newgroups = realloc (groups, | |
92 | newsize * sizeof (*groups)); | |
93 | if (newgroups == NULL) | |
94 | goto done; | |
95 | *groupsp = groups = newgroups; | |
96 | *size = newsize; | |
97 | } | |
98 | ||
99 | groups[*start] = grpbuf.gr_gid; | |
100 | *start += 1; | |
101 | } | |
f7e7a396 UD |
102 | |
103 | break; | |
104 | } | |
105 | } | |
106 | } | |
107 | while (status == NSS_STATUS_SUCCESS); | |
108 | ||
109 | done: | |
866ba63b | 110 | scratch_buffer_free (&tmpbuf); |
1a9dd4e4 | 111 | |
f7e7a396 UD |
112 | if (endgrent_fct) |
113 | DL_CALL_FCT (endgrent_fct, ()); | |
114 | ||
1a9dd4e4 | 115 | return result; |
f7e7a396 | 116 | } |