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