1:
2: typedef enum nss_status (*set_function) (void);
3:
4:
5: typedef enum nss_status (*end_function) (void);
6:
7:
8: typedef enum nss_status (*get_function) (struct group *, char *,
9: size_t, int *);
10:
11: static enum nss_status
12: compat_call (service_user *nip, const char *user, gid_t group, long int *start,
13: long int *size, gid_t **groupsp, long int limit, int *errnop)
14: {
15: struct group grpbuf;
16: size_t buflen = __sysconf (_SC_GETGR_R_SIZE_MAX);
17: char *tmpbuf;
18: enum nss_status status;
19: set_function setgrent_fct;
20: get_function getgrent_fct;
21: end_function endgrent_fct;
22: gid_t *groups = *groupsp;
23:
24: getgrent_fct = __nss_lookup_function (nip, "getgrent_r");
25: if (getgrent_fct == NULL)
26: return NSS_STATUS_UNAVAIL;
27:
28: setgrent_fct = __nss_lookup_function (nip, "setgrent");
29: if (setgrent_fct)
30: {
31: status = DL_CALL_FCT (setgrent_fct, ());
32: if (status != NSS_STATUS_SUCCESS)
33: return status;
34: }
35:
36: endgrent_fct = __nss_lookup_function (nip, "endgrent");
37:
38: tmpbuf = __alloca (buflen);
39:
40: do
41: {
42: while ((status = DL_CALL_FCT (getgrent_fct,
43: (&grpbuf, tmpbuf, buflen, errnop)),
44: status == NSS_STATUS_TRYAGAIN)
45: && *errnop == ERANGE)
46: {
47: buflen *= 2;
48: tmpbuf = __alloca (buflen);
49: }
50:
51: if (status != NSS_STATUS_SUCCESS)
52: goto done;
53:
54: if (grpbuf.gr_gid != group)
55: {
56: char **m;
57:
58: for (m = grpbuf.gr_mem; *m != NULL; ++m)
59: if (strcmp (*m, user) == 0)
60: {
61:
62: long int cnt;
63: for (cnt = 0; cnt < *start; ++cnt)
64: if (groups[cnt] == grpbuf.gr_gid)
65: break;
66:
67: if (cnt == *start)
68: {
69:
70:
71: if (__builtin_expect (*start == *size, 0))
72: {
73:
74: gid_t *newgroups;
75: long int newsize;
76:
77: if (limit > 0 && *size == limit)
78:
79: goto done;
80:
81: if (limit <= 0)
82: newsize = 2 * *size;
83: else
84: newsize = MIN (limit, 2 * *size);
85:
86: newgroups = realloc (groups,
87: newsize * sizeof (*groups));
88: if (newgroups == NULL)
89: goto done;
90: *groupsp = groups = newgroups;
91: *size = newsize;
92: }
93:
94: groups[*start] = grpbuf.gr_gid;
95: *start += 1;
96: }
97:
98: break;
99: }
100: }
101: }
102: while (status == NSS_STATUS_SUCCESS);
103:
104: done:
105: if (endgrent_fct)
106: DL_CALL_FCT (endgrent_fct, ());
107:
108: return NSS_STATUS_SUCCESS;
109: }