xref: /openbsd/regress/lib/libpthread/group/group.c (revision 2badd5e3)
1*2badd5e3Sfgsch /*	$OpenBSD: group.c,v 1.2 2001/08/23 04:26:05 fgsch Exp $	*/
2b2ea75c1Sfgsch /* David Leonard <d@openbsd.org>, 2001. Public Domain. */
3b2ea75c1Sfgsch 
4b2ea75c1Sfgsch /*
5b2ea75c1Sfgsch  * Test getgrgid_r() across multiple threads to see if the members list changes.
6b2ea75c1Sfgsch  */
7b2ea75c1Sfgsch 
8b2ea75c1Sfgsch #include <pthread.h>
9b2ea75c1Sfgsch #include <unistd.h>
10b2ea75c1Sfgsch #include <stdio.h>
11b2ea75c1Sfgsch #include <grp.h>
12b2ea75c1Sfgsch #include <sys/types.h>
13b2ea75c1Sfgsch #include "test.h"
14b2ea75c1Sfgsch 
15b2ea75c1Sfgsch struct group * getgrgid_r(gid_t, struct group *);
16b2ea75c1Sfgsch 
17b2ea75c1Sfgsch char fail[] = "fail";
18b2ea75c1Sfgsch 
19b2ea75c1Sfgsch pthread_cond_t done;
20b2ea75c1Sfgsch volatile int done_count;
21b2ea75c1Sfgsch 
22b2ea75c1Sfgsch pthread_mutex_t display;
23b2ea75c1Sfgsch pthread_mutex_t display2;
24b2ea75c1Sfgsch 
25b2ea75c1Sfgsch void*
26b2ea75c1Sfgsch test(void* arg)
27b2ea75c1Sfgsch {
28*2badd5e3Sfgsch 	gid_t gid = *(gid_t *)arg;
29b2ea75c1Sfgsch 	gid_t ogid;
30b2ea75c1Sfgsch 	struct group grpbuf;
31b2ea75c1Sfgsch 	struct group *grp;
32b2ea75c1Sfgsch 	char **p;
33b2ea75c1Sfgsch 	char buf[2048];
34b2ea75c1Sfgsch 	char *cpy[128];
35b2ea75c1Sfgsch 	int i;
36b2ea75c1Sfgsch 	int count1, count2;
37b2ea75c1Sfgsch 	char *s;
38b2ea75c1Sfgsch 	char *oname;
39b2ea75c1Sfgsch 	char *opasswd;
40b2ea75c1Sfgsch 
41b2ea75c1Sfgsch 	/* Acquire lock for running first part. */
42b2ea75c1Sfgsch 	CHECKr(pthread_mutex_lock(&display));
43b2ea75c1Sfgsch 
44b2ea75c1Sfgsch 	/* Store magic name to test for non-alteration */
45b2ea75c1Sfgsch 	grpbuf.gr_name = fail;
46b2ea75c1Sfgsch 
47b2ea75c1Sfgsch 	/* Call getgrgid_r() */
48b2ea75c1Sfgsch 	printf("gid %d\n", gid);
49b2ea75c1Sfgsch 	CHECKn(grp = getgrgid_r(gid, &grpbuf));
50b2ea75c1Sfgsch 
51b2ea75c1Sfgsch 	/* Test for non-alteration of group structure */
52b2ea75c1Sfgsch 	ASSERT(grp->gr_name != fail);
53b2ea75c1Sfgsch 
54b2ea75c1Sfgsch 	/* We must get the right group */
55b2ea75c1Sfgsch 	ASSERT(grp->gr_gid == gid);
56b2ea75c1Sfgsch 
57b2ea75c1Sfgsch 	s = buf;	/* Keep our private buffer on the stack */
58b2ea75c1Sfgsch 
59b2ea75c1Sfgsch 	/* copy gr_name */
60b2ea75c1Sfgsch 	strcpy(oname = s, grp->gr_name);
61b2ea75c1Sfgsch 	s += 1 + strlen(s);
62b2ea75c1Sfgsch 
63b2ea75c1Sfgsch 	/* copy gr_passwd */
64b2ea75c1Sfgsch 	strcpy(opasswd = s, grp->gr_passwd);
65b2ea75c1Sfgsch 	s += 1 + strlen(s);
66b2ea75c1Sfgsch 
67b2ea75c1Sfgsch 	/* copy gr_gid */
68b2ea75c1Sfgsch 	ogid = grp->gr_gid;
69b2ea75c1Sfgsch 
70b2ea75c1Sfgsch 	/* copy gr_mem */
71b2ea75c1Sfgsch 	for (i = 0, p = grp->gr_mem; *p; p++) {
72b2ea75c1Sfgsch 		strcpy(cpy[i] = s, *p); i++;
73b2ea75c1Sfgsch 		s += 1 + strlen(s);
74b2ea75c1Sfgsch 	}
75b2ea75c1Sfgsch 	cpy[i] = NULL;
76b2ea75c1Sfgsch 
77b2ea75c1Sfgsch #if 0
78b2ea75c1Sfgsch 	printf("now:    %s:%s:%d:", grp->gr_name, grp->gr_passwd, grp->gr_gid);
79b2ea75c1Sfgsch 	for (p = grp->gr_mem; *p; p++)
80b2ea75c1Sfgsch 		printf("%s%s", *p, *(p+1) == NULL ? "": ",");
81b2ea75c1Sfgsch 	printf("\n");
82b2ea75c1Sfgsch #endif
83b2ea75c1Sfgsch 
84b2ea75c1Sfgsch #ifdef DEBUG /* debugging this program */
85b2ea75c1Sfgsch 	printf("buf = \"");
86b2ea75c1Sfgsch 	for (i = 0; i < s - buf; i++)
87b2ea75c1Sfgsch 		if (buf[i] == '\0')	printf("\\0");
88b2ea75c1Sfgsch 		else printf("%c", buf[i]);
89b2ea75c1Sfgsch 	printf("\"\n");
90b2ea75c1Sfgsch #endif
91b2ea75c1Sfgsch 
92b2ea75c1Sfgsch 	/* Inform main that we have finished */
93b2ea75c1Sfgsch 	done_count++;
94b2ea75c1Sfgsch 	CHECKr(pthread_cond_signal(&done));
95b2ea75c1Sfgsch 
96b2ea75c1Sfgsch 	/* Allow other threads to run first part */
97b2ea75c1Sfgsch 	CHECKr(pthread_mutex_unlock(&display));
98b2ea75c1Sfgsch 
99b2ea75c1Sfgsch 	/* Acquire lock for the second part */
100b2ea75c1Sfgsch 	CHECKr(pthread_mutex_lock(&display2));
101b2ea75c1Sfgsch 
102b2ea75c1Sfgsch 	count1 = 0;
103b2ea75c1Sfgsch 	printf("before: %s:%s:%d:", oname, opasswd, ogid);
104b2ea75c1Sfgsch 	for (p = cpy; *p; p++)  {
105b2ea75c1Sfgsch 		count1++;
106b2ea75c1Sfgsch 		printf("%s%s", *p, *(p+1) == NULL ? "": ",");
107b2ea75c1Sfgsch 	}
108b2ea75c1Sfgsch 	printf("\n");
109b2ea75c1Sfgsch 
110b2ea75c1Sfgsch 	count2 = 0;
111b2ea75c1Sfgsch 	printf("after:  %s:%s:%d:", grp->gr_name, grp->gr_passwd, grp->gr_gid);
112b2ea75c1Sfgsch 	for (p = grp->gr_mem; *p; p++)  {
113b2ea75c1Sfgsch 		count2++;
114b2ea75c1Sfgsch 		printf("%s%s", *p, *(p+1) == NULL ? "": ",");
115b2ea75c1Sfgsch 	}
116b2ea75c1Sfgsch 	printf("\n");
117b2ea75c1Sfgsch 
118b2ea75c1Sfgsch 	CHECKr(pthread_mutex_unlock(&display2));
119b2ea75c1Sfgsch 
120b2ea75c1Sfgsch 	if (count1 != count2)
121b2ea75c1Sfgsch 		return "gr_mem length changed";
122b2ea75c1Sfgsch 	for (i = 0; i < count1; i++)
123b2ea75c1Sfgsch 		if (strcmp(cpy[i], grp->gr_mem[i]) != 0)
124b2ea75c1Sfgsch 			return "gr_mem list changed";
125b2ea75c1Sfgsch 	if (strcmp(grp->gr_name, oname) != 0)
126b2ea75c1Sfgsch 		return "gr_name changed";
127b2ea75c1Sfgsch 	if (strcmp(grp->gr_passwd, opasswd) != 0)
128b2ea75c1Sfgsch 		return "gr_passwd changed";
129b2ea75c1Sfgsch 	if (grp->gr_gid != ogid)
130b2ea75c1Sfgsch 		return "gr_gid changed";
131b2ea75c1Sfgsch 	return NULL;
132b2ea75c1Sfgsch }
133b2ea75c1Sfgsch 
134b2ea75c1Sfgsch 
135b2ea75c1Sfgsch #define NGRPS	5
136b2ea75c1Sfgsch int
137b2ea75c1Sfgsch main()
138b2ea75c1Sfgsch {
139b2ea75c1Sfgsch 	pthread_t thread[NGRPS];
140b2ea75c1Sfgsch 	int gid;
141b2ea75c1Sfgsch 	int failed;
142b2ea75c1Sfgsch 	void *result;
143b2ea75c1Sfgsch 
144b2ea75c1Sfgsch 	CHECKr(pthread_mutex_init(&display, NULL));
145b2ea75c1Sfgsch 	CHECKr(pthread_mutex_init(&display2, NULL));
146b2ea75c1Sfgsch 
147b2ea75c1Sfgsch 	CHECKr(pthread_cond_init(&done, NULL));
148b2ea75c1Sfgsch 	done_count = 0;
149b2ea75c1Sfgsch 
150b2ea75c1Sfgsch 	pthread_mutex_lock(&display);
151b2ea75c1Sfgsch 	pthread_mutex_lock(&display2);
152b2ea75c1Sfgsch 
153b2ea75c1Sfgsch 	/* Get separate threads to do a group open separately */
154b2ea75c1Sfgsch 	for (gid = 0; gid < NGRPS; gid++) {
155*2badd5e3Sfgsch 		CHECKr(pthread_create(&thread[gid], NULL, test, (void *)&gid));
156b2ea75c1Sfgsch 	}
157b2ea75c1Sfgsch 
158b2ea75c1Sfgsch 	/* Allow all threads to run their first part */
159b2ea75c1Sfgsch 	while (done_count < NGRPS)
160b2ea75c1Sfgsch 		pthread_cond_wait(&done, &display);
161b2ea75c1Sfgsch 
162b2ea75c1Sfgsch 	/* Allow each thread to run the 2nd part of its test */
163b2ea75c1Sfgsch 	CHECKr(pthread_mutex_unlock(&display2));
164b2ea75c1Sfgsch 
165b2ea75c1Sfgsch 	/* Wait for each thread to terminate, collecting results. */
166b2ea75c1Sfgsch 	failed = 0;
167b2ea75c1Sfgsch 	for (gid = 0; gid < NGRPS; gid++) {
168b2ea75c1Sfgsch 		CHECKr(pthread_join(thread[gid], &result));
169b2ea75c1Sfgsch 		if (result != NULL) {
170b2ea75c1Sfgsch 			fprintf(stderr, "gid %d: %s\n", gid, (char *)result);
171b2ea75c1Sfgsch 			failed++;
172b2ea75c1Sfgsch 		}
173b2ea75c1Sfgsch 	}
174b2ea75c1Sfgsch 
175b2ea75c1Sfgsch 	if (!failed) {
176b2ea75c1Sfgsch 		SUCCEED;
177b2ea75c1Sfgsch 	} else {
178b2ea75c1Sfgsch 		exit(1);
179b2ea75c1Sfgsch 	}
180b2ea75c1Sfgsch }
181