| 193 | } |
| 194 | |
| 195 | static int is_in_group(gid_t gid) |
| 196 | { |
| 197 | #ifdef HAVE_GETGROUPS |
| 198 | static gid_t last_in; |
| 199 | static int ngroups = -2, last_out = -1; |
| 200 | static GETGROUPS_T *gidset; |
| 201 | int n; |
| 202 | |
| 203 | if (gid == last_in && last_out >= 0) |
| 204 | return last_out; |
| 205 | if (ngroups < -1) { |
| 206 | if ((ngroups = getgroups(0, NULL)) < 0) |
| 207 | ngroups = 0; |
| 208 | gidset = new_array(GETGROUPS_T, ngroups+1); |
| 209 | if (ngroups > 0) |
| 210 | ngroups = getgroups(ngroups, gidset); |
| 211 | /* The default gid might not be in the list on some systems. */ |
| 212 | for (n = 0; n < ngroups; n++) { |
| 213 | if ((gid_t)gidset[n] == our_gid) |
| 214 | break; |
| 215 | } |
| 216 | if (n == ngroups) |
| 217 | gidset[ngroups++] = our_gid; |
| 218 | if (DEBUG_GTE(OWN, 2)) { |
| 219 | int pos; |
| 220 | char *gidbuf = new_array(char, ngroups*21+32); |
| 221 | pos = snprintf(gidbuf, 32, "process has %d gid%s: ", ngroups, ngroups == 1? "" : "s"); |
| 222 | for (n = 0; n < ngroups; n++) { |
| 223 | pos += snprintf(gidbuf+pos, 21, " %d", (int)gidset[n]); |
| 224 | } |
| 225 | rprintf(FINFO, "%s\n", gidbuf); |
| 226 | free(gidbuf); |
| 227 | } |
| 228 | } |
| 229 | |
| 230 | last_in = gid; |
| 231 | for (n = 0; n < ngroups; n++) { |
| 232 | if ((gid_t)gidset[n] == gid) |
| 233 | return last_out = 1; |
| 234 | } |
| 235 | return last_out = 0; |
| 236 | |
| 237 | #else |
| 238 | return gid == our_gid; |
| 239 | #endif |
| 240 | } |
| 241 | |
| 242 | /* Add a uid/gid to its list of ids. Only called on receiving side. */ |
| 243 | static struct idlist *recv_add_id(struct idlist **idlist_ptr, struct idlist *idmap, |
no test coverage detected