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