190792Sgshapiro/*
2261370Sgshapiro * Copyright (c) 2000-2002, 2004, 2005 Proofpoint, Inc. and its suppliers.
390792Sgshapiro *      All rights reserved.
490792Sgshapiro *
590792Sgshapiro * By using this file, you agree to the terms and conditions set
690792Sgshapiro * forth in the LICENSE file which can be found at the top level of
790792Sgshapiro * the sendmail distribution.
890792Sgshapiro */
990792Sgshapiro
1090792Sgshapiro#include <sm/gen.h>
11266711SgshapiroSM_RCSID("@(#)$Id: t-shm.c,v 1.23 2013-11-22 20:51:43 ca Exp $")
1290792Sgshapiro
1390792Sgshapiro#include <stdio.h>
1490792Sgshapiro
1590792Sgshapiro#if SM_CONF_SHM
1690792Sgshapiro# include <stdlib.h>
1790792Sgshapiro# include <unistd.h>
1890792Sgshapiro# include <sys/wait.h>
1990792Sgshapiro
2090792Sgshapiro# include <sm/heap.h>
2190792Sgshapiro# include <sm/string.h>
2290792Sgshapiro# include <sm/test.h>
2390792Sgshapiro# include <sm/shm.h>
2490792Sgshapiro
2590792Sgshapiro# define SHMSIZE	1024
2690792Sgshapiro# define SHM_MAX	6400000
2790792Sgshapiro# define T_SHMKEY	21
2890792Sgshapiro
2990792Sgshapiro
3090792Sgshapiro/*
3190792Sgshapiro**  SHMINTER -- interactive testing of shared memory
3290792Sgshapiro**
3390792Sgshapiro**	Parameters:
3490792Sgshapiro**		owner -- create segment.
3590792Sgshapiro**
3690792Sgshapiro**	Returns:
3790792Sgshapiro**		0 on success
3890792Sgshapiro**		< 0 on failure.
3990792Sgshapiro*/
4090792Sgshapiro
4190792Sgshapiroint shminter __P((bool));
4290792Sgshapiro
4390792Sgshapiroint
4490792Sgshapiroshminter(owner)
4590792Sgshapiro	bool owner;
4690792Sgshapiro{
4790792Sgshapiro	int *shm, shmid;
48132943Sgshapiro	int i, t;
4990792Sgshapiro
5090792Sgshapiro	shm = (int *) sm_shmstart(T_SHMKEY, SHMSIZE, 0, &shmid, owner);
5190792Sgshapiro	if (shm == (int *) 0)
5290792Sgshapiro	{
5390792Sgshapiro		perror("shminit failed");
5490792Sgshapiro		return -1;
5590792Sgshapiro	}
5690792Sgshapiro
5790792Sgshapiro	while ((t = getchar()) != EOF)
5890792Sgshapiro	{
5990792Sgshapiro		switch (t)
6090792Sgshapiro		{
6190792Sgshapiro		  case 'c':
6290792Sgshapiro			*shm = 0;
6390792Sgshapiro			break;
6490792Sgshapiro		  case 'i':
6590792Sgshapiro			++*shm;
6690792Sgshapiro			break;
6790792Sgshapiro		  case 'd':
6890792Sgshapiro			--*shm;
6990792Sgshapiro			break;
7090792Sgshapiro		  case 's':
7190792Sgshapiro			sleep(1);
7290792Sgshapiro			break;
7390792Sgshapiro		  case 'l':
7490792Sgshapiro			t = *shm;
7590792Sgshapiro			for (i = 0; i < SHM_MAX; i++)
7690792Sgshapiro			{
7790792Sgshapiro				++*shm;
7890792Sgshapiro			}
7990792Sgshapiro			if (*shm != SHM_MAX + t)
8090792Sgshapiro				fprintf(stderr, "error: %d != %d\n",
8190792Sgshapiro					*shm, SHM_MAX + t);
8290792Sgshapiro			break;
8390792Sgshapiro		  case 'v':
8490792Sgshapiro			printf("shmval: %d\n", *shm);
8590792Sgshapiro			break;
86147078Sgshapiro		  case 'S':
87147078Sgshapiro			i = sm_shmsetowner(shmid, getuid(), getgid(), 0644);
88147078Sgshapiro			printf("sm_shmsetowner=%d\n", i);
89147078Sgshapiro			break;
9090792Sgshapiro		}
9190792Sgshapiro	}
9290792Sgshapiro	return sm_shmstop((void *) shm, shmid, owner);
9390792Sgshapiro}
9490792Sgshapiro
9590792Sgshapiro
9690792Sgshapiro/*
9790792Sgshapiro**  SHMBIG -- testing of shared memory
9890792Sgshapiro**
9990792Sgshapiro**	Parameters:
10090792Sgshapiro**		owner -- create segment.
10190792Sgshapiro**		size -- size of segment.
10290792Sgshapiro**
10390792Sgshapiro**	Returns:
10490792Sgshapiro**		0 on success
10590792Sgshapiro**		< 0 on failure.
10690792Sgshapiro*/
10790792Sgshapiro
10890792Sgshapiroint shmbig __P((bool, int));
10990792Sgshapiro
11090792Sgshapiroint
11190792Sgshapiroshmbig(owner, size)
11290792Sgshapiro	bool owner;
11390792Sgshapiro	int size;
11490792Sgshapiro{
11590792Sgshapiro	int *shm, shmid;
11690792Sgshapiro	int i;
11790792Sgshapiro
11890792Sgshapiro	shm = (int *) sm_shmstart(T_SHMKEY, size, 0, &shmid, owner);
11990792Sgshapiro	if (shm == (int *) 0)
12090792Sgshapiro	{
12190792Sgshapiro		perror("shminit failed");
12290792Sgshapiro		return -1;
12390792Sgshapiro	}
12490792Sgshapiro
12590792Sgshapiro	for (i = 0; i < size / sizeof(int); i++)
12690792Sgshapiro		shm[i] = i;
12790792Sgshapiro	for (i = 0; i < size / sizeof(int); i++)
12890792Sgshapiro	{
12990792Sgshapiro		if (shm[i] != i)
13090792Sgshapiro		{
13190792Sgshapiro			fprintf(stderr, "failed at %d: %d", i, shm[i]);
13290792Sgshapiro		}
13390792Sgshapiro	}
13490792Sgshapiro
13590792Sgshapiro	return sm_shmstop((void *) shm, shmid, owner);
13690792Sgshapiro}
13790792Sgshapiro
13890792Sgshapiro
13990792Sgshapiro/*
14090792Sgshapiro**  SHMTEST -- test of shared memory
14190792Sgshapiro**
14290792Sgshapiro**	Parameters:
14390792Sgshapiro**		owner -- create segment.
14490792Sgshapiro**
14590792Sgshapiro**	Returns:
14690792Sgshapiro**		0 on success
14790792Sgshapiro**		< 0 on failure.
14890792Sgshapiro*/
14990792Sgshapiro
15090792Sgshapiro# define MAX_CNT	10
15190792Sgshapiro
152141858Sgshapiroint shmtest __P((int));
153141858Sgshapiro
15490792Sgshapiroint
15590792Sgshapiroshmtest(owner)
15690792Sgshapiro	int owner;
15790792Sgshapiro{
15890792Sgshapiro	int *shm, shmid;
15990792Sgshapiro	int cnt = 0;
16090792Sgshapiro
16190792Sgshapiro	shm = (int *) sm_shmstart(T_SHMKEY, SHMSIZE, 0, &shmid, owner);
16290792Sgshapiro	if (shm == (int *) 0)
16390792Sgshapiro	{
16490792Sgshapiro		perror("shminit failed");
16590792Sgshapiro		return -1;
16690792Sgshapiro	}
16790792Sgshapiro
16890792Sgshapiro	if (owner)
16990792Sgshapiro	{
17090792Sgshapiro		int r;
17190792Sgshapiro
172147078Sgshapiro		r = sm_shmsetowner(shmid, getuid(), getgid(), 0660);
173147078Sgshapiro		SM_TEST(r == 0);
17490792Sgshapiro		*shm = 1;
17590792Sgshapiro		while (*shm == 1 && cnt++ < MAX_CNT)
17690792Sgshapiro			sleep(1);
17790792Sgshapiro		SM_TEST(cnt <= MAX_CNT);
17890792Sgshapiro
17990792Sgshapiro		/* release and re-acquire the segment */
18090792Sgshapiro		r = sm_shmstop((void *) shm, shmid, owner);
18190792Sgshapiro		SM_TEST(r == 0);
18290792Sgshapiro		shm = (int *) sm_shmstart(T_SHMKEY, SHMSIZE, 0, &shmid, owner);
18390792Sgshapiro		SM_TEST(shm != (int *) 0);
18490792Sgshapiro	}
18590792Sgshapiro	else
18690792Sgshapiro	{
18790792Sgshapiro		while (*shm != 1 && cnt++ < MAX_CNT)
18890792Sgshapiro			sleep(1);
18990792Sgshapiro		SM_TEST(cnt <= MAX_CNT);
19090792Sgshapiro		*shm = 2;
19190792Sgshapiro
19290792Sgshapiro		/* wait a momemt so the segment is still in use */
19390792Sgshapiro		sleep(2);
19490792Sgshapiro	}
19590792Sgshapiro	return sm_shmstop((void *) shm, shmid, owner);
19690792Sgshapiro}
19790792Sgshapiro
19890792Sgshapiroint
19990792Sgshapiromain(argc, argv)
20090792Sgshapiro	int argc;
20190792Sgshapiro	char *argv[];
20290792Sgshapiro{
20390792Sgshapiro	bool interactive = false;
20490792Sgshapiro	bool owner = false;
20590792Sgshapiro	int big = -1;
20690792Sgshapiro	int ch;
20790792Sgshapiro	int r = 0;
20890792Sgshapiro	int status;
20990792Sgshapiro	extern char *optarg;
21090792Sgshapiro
21190792Sgshapiro# define OPTIONS	"b:io"
21290792Sgshapiro	while ((ch = getopt(argc, argv, OPTIONS)) != -1)
21390792Sgshapiro	{
21490792Sgshapiro		switch ((char) ch)
21590792Sgshapiro		{
21690792Sgshapiro		  case 'b':
21790792Sgshapiro			big = atoi(optarg);
21890792Sgshapiro			break;
21990792Sgshapiro
22090792Sgshapiro		  case 'i':
22190792Sgshapiro			interactive = true;
22290792Sgshapiro			break;
22390792Sgshapiro
22490792Sgshapiro		  case 'o':
22590792Sgshapiro			owner = true;
22690792Sgshapiro			break;
22790792Sgshapiro
22890792Sgshapiro		  default:
22990792Sgshapiro			break;
23090792Sgshapiro		}
23190792Sgshapiro	}
23290792Sgshapiro
23390792Sgshapiro	if (interactive)
23490792Sgshapiro		r = shminter(owner);
23590792Sgshapiro	else if (big > 0)
23690792Sgshapiro		r = shmbig(true, big);
23790792Sgshapiro	else
23890792Sgshapiro	{
23990792Sgshapiro		pid_t pid;
24094334Sgshapiro		extern int SmTestNumErrors;
24190792Sgshapiro
24290792Sgshapiro		if ((pid = fork()) < 0)
24390792Sgshapiro		{
24490792Sgshapiro			perror("fork failed\n");
24590792Sgshapiro			return -1;
24690792Sgshapiro		}
24790792Sgshapiro
24890792Sgshapiro		sm_test_begin(argc, argv, "test shared memory");
24990792Sgshapiro		if (pid == 0)
25090792Sgshapiro		{
25190792Sgshapiro			/* give the parent the chance to setup data */
25290792Sgshapiro			sleep(1);
25390792Sgshapiro			r = shmtest(false);
25490792Sgshapiro		}
25590792Sgshapiro		else
25690792Sgshapiro		{
25790792Sgshapiro			r = shmtest(true);
25890792Sgshapiro			(void) wait(&status);
25990792Sgshapiro		}
26090792Sgshapiro		SM_TEST(r == 0);
26194334Sgshapiro		if (SmTestNumErrors > 0)
26294334Sgshapiro			printf("add -DSM_CONF_SHM=0 to confENVDEF in devtools/Site/site.config.m4\nand start over.\n");
26390792Sgshapiro		return sm_test_end();
26490792Sgshapiro	}
26590792Sgshapiro	return r;
26690792Sgshapiro}
26790792Sgshapiro#else /* SM_CONF_SHM */
26890792Sgshapiroint
26990792Sgshapiromain(argc, argv)
27090792Sgshapiro	int argc;
27190792Sgshapiro	char *argv[];
27290792Sgshapiro{
27390792Sgshapiro	printf("No support for shared memory configured on this machine\n");
27490792Sgshapiro	return 0;
27590792Sgshapiro}
27690792Sgshapiro#endif /* SM_CONF_SHM */
277