aboutsummaryrefslogtreecommitdiffstats
path: root/ports/linux/guts/getgrouplist.c
blob: 5481a3883e860d9b639761ebe5f93340aee91b12 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/* 
 * Copyright (c) 2010 Wind River Systems; see
 * guts/COPYRIGHT for information.
 *
 * SPDX-License-Identifier: LGPL-2.1-only
 *
 * static int
 * wrap_getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups) {
 *	int rc = -1;
 */

	int found = 0;
	int found_group = 0;
	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();

		if (rc == ERANGE)
			buflen = buflen << 1;
	} while (rc == ERANGE);
	free(buf);
	if (!found_group) {
		if (found < *ngroups)
			groups[found] = group;
		++found;
	}
	if (found >= *ngroups)
		rc = -1;
	else
		rc = found;
	*ngroups = found;

/*	return rc;
 * }
 */