aboutsummaryrefslogtreecommitdiffstats
path: root/ports/linux/guts/getgrouplist.c
diff options
context:
space:
mode:
Diffstat (limited to 'ports/linux/guts/getgrouplist.c')
-rw-r--r--ports/linux/guts/getgrouplist.c54
1 files changed, 39 insertions, 15 deletions
diff --git a/ports/linux/guts/getgrouplist.c b/ports/linux/guts/getgrouplist.c
index 3489ec9..8b16e47 100644
--- a/ports/linux/guts/getgrouplist.c
+++ b/ports/linux/guts/getgrouplist.c
@@ -9,23 +9,47 @@
int found = 0;
int found_group = 0;
- char buf[PSEUDO_PWD_MAX];
- struct group grp, *gbuf = &grp;
-
- setgrent();
- while ((rc = wrap_getgrent_r(gbuf, buf, PSEUDO_PWD_MAX, &gbuf)) == 0) {
- int i = 0;
- for (i = 0; gbuf->gr_mem[i]; ++i) {
- if (!strcmp(gbuf->gr_mem[i], user)) {
- if (found < *ngroups)
- groups[found] = gbuf->gr_gid;
- ++found;
- if (gbuf->gr_gid == group)
- found_group = 1;
+ size_t buflen = PSEUDO_PWD_MAX;
+ char *buf = NULL;
+ struct group grp;
+
+ rc = ERANGE;
+
+ do {
+ struct group *gbuf = &grp;
+ char *new_buf = buf;
+
+ if (rc == ERANGE)
+ new_buf = realloc(buf, buflen);
+
+ if (!new_buf) {
+ rc = ENOMEM;
+ break;
+ }
+
+ buf = new_buf;
+
+ found = 0;
+ found_group = 0;
+ setgrent();
+ while ((rc = wrap_getgrent_r(gbuf, buf, buflen, &gbuf)) == 0) {
+ int i = 0;
+ for (i = 0; gbuf->gr_mem[i]; ++i) {
+ if (!strcmp(gbuf->gr_mem[i], user)) {
+ if (found < *ngroups)
+ groups[found] = gbuf->gr_gid;
+ ++found;
+ if (gbuf->gr_gid == group)
+ found_group = 1;
+ }
}
}
- }
- endgrent();
+ endgrent();
+
+ if (rc == ERANGE)
+ buflen = buflen << 1;
+ } while (rc == ERANGE);
+ free(buf);
if (!found_group) {
if (found < *ngroups)
groups[found] = group;