1/*
2 * Copyright (c) 2000-2002, 2004, 2005 Sendmail, Inc. and its suppliers.
3 *      All rights reserved.
4 *
5 * By using this file, you agree to the terms and conditions set
6 * forth in the LICENSE file which can be found at the top level of
7 * the sendmail distribution.
8 */
9
10#pragma ident	"%Z%%M%	%I%	%E% SMI"
11
12#include <sm/gen.h>
13SM_RCSID("@(#)$Id: t-shm.c,v 1.22 2005/01/14 02:14:10 ca Exp $")
14
15#include <stdio.h>
16
17#if SM_CONF_SHM
18# include <stdlib.h>
19# include <unistd.h>
20# include <sys/wait.h>
21
22# include <sm/heap.h>
23# include <sm/string.h>
24# include <sm/test.h>
25# include <sm/shm.h>
26
27# define SHMSIZE	1024
28# define SHM_MAX	6400000
29# define T_SHMKEY	21
30
31
32/*
33**  SHMINTER -- interactive testing of shared memory
34**
35**	Parameters:
36**		owner -- create segment.
37**
38**	Returns:
39**		0 on success
40**		< 0 on failure.
41*/
42
43int shminter __P((bool));
44
45int
46shminter(owner)
47	bool owner;
48{
49	int *shm, shmid;
50	int i, t;
51
52	shm = (int *) sm_shmstart(T_SHMKEY, SHMSIZE, 0, &shmid, owner);
53	if (shm == (int *) 0)
54	{
55		perror("shminit failed");
56		return -1;
57	}
58
59	while ((t = getchar()) != EOF)
60	{
61		switch (t)
62		{
63		  case 'c':
64			*shm = 0;
65			break;
66		  case 'i':
67			++*shm;
68			break;
69		  case 'd':
70			--*shm;
71			break;
72		  case 's':
73			sleep(1);
74			break;
75		  case 'l':
76			t = *shm;
77			for (i = 0; i < SHM_MAX; i++)
78			{
79				++*shm;
80			}
81			if (*shm != SHM_MAX + t)
82				fprintf(stderr, "error: %d != %d\n",
83					*shm, SHM_MAX + t);
84			break;
85		  case 'v':
86			printf("shmval: %d\n", *shm);
87			break;
88		  case 'S':
89			i = sm_shmsetowner(shmid, getuid(), getgid(), 0644);
90			printf("sm_shmsetowner=%d\n", i);
91			break;
92		}
93	}
94	return sm_shmstop((void *) shm, shmid, owner);
95}
96
97
98/*
99**  SHMBIG -- testing of shared memory
100**
101**	Parameters:
102**		owner -- create segment.
103**		size -- size of segment.
104**
105**	Returns:
106**		0 on success
107**		< 0 on failure.
108*/
109
110int shmbig __P((bool, int));
111
112int
113shmbig(owner, size)
114	bool owner;
115	int size;
116{
117	int *shm, shmid;
118	int i;
119
120	shm = (int *) sm_shmstart(T_SHMKEY, size, 0, &shmid, owner);
121	if (shm == (int *) 0)
122	{
123		perror("shminit failed");
124		return -1;
125	}
126
127	for (i = 0; i < size / sizeof(int); i++)
128		shm[i] = i;
129	for (i = 0; i < size / sizeof(int); i++)
130	{
131		if (shm[i] != i)
132		{
133			fprintf(stderr, "failed at %d: %d", i, shm[i]);
134		}
135	}
136
137	return sm_shmstop((void *) shm, shmid, owner);
138}
139
140
141/*
142**  SHMTEST -- test of shared memory
143**
144**	Parameters:
145**		owner -- create segment.
146**
147**	Returns:
148**		0 on success
149**		< 0 on failure.
150*/
151
152# define MAX_CNT	10
153
154int shmtest __P((int));
155
156int
157shmtest(owner)
158	int owner;
159{
160	int *shm, shmid;
161	int cnt = 0;
162
163	shm = (int *) sm_shmstart(T_SHMKEY, SHMSIZE, 0, &shmid, owner);
164	if (shm == (int *) 0)
165	{
166		perror("shminit failed");
167		return -1;
168	}
169
170	if (owner)
171	{
172		int r;
173
174		r = sm_shmsetowner(shmid, getuid(), getgid(), 0660);
175		SM_TEST(r == 0);
176		*shm = 1;
177		while (*shm == 1 && cnt++ < MAX_CNT)
178			sleep(1);
179		SM_TEST(cnt <= MAX_CNT);
180
181		/* release and re-acquire the segment */
182		r = sm_shmstop((void *) shm, shmid, owner);
183		SM_TEST(r == 0);
184		shm = (int *) sm_shmstart(T_SHMKEY, SHMSIZE, 0, &shmid, owner);
185		SM_TEST(shm != (int *) 0);
186	}
187	else
188	{
189		while (*shm != 1 && cnt++ < MAX_CNT)
190			sleep(1);
191		SM_TEST(cnt <= MAX_CNT);
192		*shm = 2;
193
194		/* wait a momemt so the segment is still in use */
195		sleep(2);
196	}
197	return sm_shmstop((void *) shm, shmid, owner);
198}
199
200int
201main(argc, argv)
202	int argc;
203	char *argv[];
204{
205	bool interactive = false;
206	bool owner = false;
207	int big = -1;
208	int ch;
209	int r = 0;
210	int status;
211	extern char *optarg;
212
213# define OPTIONS	"b:io"
214	while ((ch = getopt(argc, argv, OPTIONS)) != -1)
215	{
216		switch ((char) ch)
217		{
218		  case 'b':
219			big = atoi(optarg);
220			break;
221
222		  case 'i':
223			interactive = true;
224			break;
225
226		  case 'o':
227			owner = true;
228			break;
229
230		  default:
231			break;
232		}
233	}
234
235	if (interactive)
236		r = shminter(owner);
237	else if (big > 0)
238		r = shmbig(true, big);
239	else
240	{
241		pid_t pid;
242		extern int SmTestNumErrors;
243
244		if ((pid = fork()) < 0)
245		{
246			perror("fork failed\n");
247			return -1;
248		}
249
250		sm_test_begin(argc, argv, "test shared memory");
251		if (pid == 0)
252		{
253			/* give the parent the chance to setup data */
254			sleep(1);
255			r = shmtest(false);
256		}
257		else
258		{
259			r = shmtest(true);
260			(void) wait(&status);
261		}
262		SM_TEST(r == 0);
263		if (SmTestNumErrors > 0)
264			printf("add -DSM_CONF_SHM=0 to confENVDEF in devtools/Site/site.config.m4\nand start over.\n");
265		return sm_test_end();
266	}
267	return r;
268}
269#else /* SM_CONF_SHM */
270int
271main(argc, argv)
272	int argc;
273	char *argv[];
274{
275	printf("No support for shared memory configured on this machine\n");
276	return 0;
277}
278#endif /* SM_CONF_SHM */
279