xref: /freebsd/contrib/sendmail/libsm/t-notify.c (revision d39bd2c1)
15b0945b5SGregory Neil Shapiro /*
2*d39bd2c1SGregory Neil Shapiro  * Copyright (c) 2020 Proofpoint, Inc. and its suppliers.
35b0945b5SGregory Neil Shapiro  *      All rights reserved.
45b0945b5SGregory Neil Shapiro  *
55b0945b5SGregory Neil Shapiro  * By using this file, you agree to the terms and conditions set
65b0945b5SGregory Neil Shapiro  * forth in the LICENSE file which can be found at the top level of
75b0945b5SGregory Neil Shapiro  * the sendmail distribution.
85b0945b5SGregory Neil Shapiro  */
95b0945b5SGregory Neil Shapiro 
105b0945b5SGregory Neil Shapiro #include <sm/gen.h>
115b0945b5SGregory Neil Shapiro #include <stdio.h>
125b0945b5SGregory Neil Shapiro 
132fb4f839SGregory Neil Shapiro #if _FFR_DMTRIGGER || _FFR_NOTIFY
145b0945b5SGregory Neil Shapiro # include <stdlib.h>
155b0945b5SGregory Neil Shapiro # include <unistd.h>
162fb4f839SGregory Neil Shapiro # include <errno.h>
175b0945b5SGregory Neil Shapiro # include <sm/heap.h>
185b0945b5SGregory Neil Shapiro # include <sm/string.h>
195b0945b5SGregory Neil Shapiro # include <sm/test.h>
205b0945b5SGregory Neil Shapiro # include <sm/notify.h>
212fb4f839SGregory Neil Shapiro # include <sm/conf.h>
22*d39bd2c1SGregory Neil Shapiro # include "notify.h"
23*d39bd2c1SGregory Neil Shapiro 
24*d39bd2c1SGregory Neil Shapiro static int Verbose = 0;
25*d39bd2c1SGregory Neil Shapiro #define MAX_CHILDREN	256
26*d39bd2c1SGregory Neil Shapiro #define MAX_MSGS	1024
27*d39bd2c1SGregory Neil Shapiro static pid_t pids[MAX_CHILDREN];
28*d39bd2c1SGregory Neil Shapiro static char msgs[MAX_CHILDREN][MAX_MSGS];
295b0945b5SGregory Neil Shapiro 
305b0945b5SGregory Neil Shapiro /*
31*d39bd2c1SGregory Neil Shapiro **  NOTIFY_WR -- test of notify write feature
325b0945b5SGregory Neil Shapiro **
335b0945b5SGregory Neil Shapiro **	Parameters:
342fb4f839SGregory Neil Shapiro **		pid -- pid of process
35*d39bd2c1SGregory Neil Shapiro **		nmsgs -- number of messages to write
365b0945b5SGregory Neil Shapiro **
375b0945b5SGregory Neil Shapiro **	Returns:
38*d39bd2c1SGregory Neil Shapiro **		>=0 on success
392fb4f839SGregory Neil Shapiro **		< 0 on failure
405b0945b5SGregory Neil Shapiro */
415b0945b5SGregory Neil Shapiro 
425b0945b5SGregory Neil Shapiro static int
notify_wr(pid,nmsgs)43*d39bd2c1SGregory Neil Shapiro notify_wr(pid, nmsgs)
442fb4f839SGregory Neil Shapiro 	pid_t pid;
45*d39bd2c1SGregory Neil Shapiro 	int nmsgs;
465b0945b5SGregory Neil Shapiro {
47*d39bd2c1SGregory Neil Shapiro 	int r, i;
485b0945b5SGregory Neil Shapiro 	size_t len;
495b0945b5SGregory Neil Shapiro 	char buf[64];
505b0945b5SGregory Neil Shapiro #define TSTSTR "qf0001"
515b0945b5SGregory Neil Shapiro 
522fb4f839SGregory Neil Shapiro 	r = sm_notify_start(false, 0);
535b0945b5SGregory Neil Shapiro 	if (r < 0)
545b0945b5SGregory Neil Shapiro 	{
555b0945b5SGregory Neil Shapiro 		perror("sm_notify_start failed");
565b0945b5SGregory Neil Shapiro 		return -1;
575b0945b5SGregory Neil Shapiro 	}
585b0945b5SGregory Neil Shapiro 
59*d39bd2c1SGregory Neil Shapiro 	for (i = 0; i < nmsgs; i++)
60*d39bd2c1SGregory Neil Shapiro 	{
61*d39bd2c1SGregory Neil Shapiro 		len = sm_snprintf(buf, sizeof(buf), "%s-%ld_%d", TSTSTR,
62*d39bd2c1SGregory Neil Shapiro 				(long) pid, i);
635b0945b5SGregory Neil Shapiro 		r = sm_notify_snd(buf, len);
645b0945b5SGregory Neil Shapiro 		SM_TEST(r >= 0);
65*d39bd2c1SGregory Neil Shapiro 	}
665b0945b5SGregory Neil Shapiro 	return r;
675b0945b5SGregory Neil Shapiro }
682fb4f839SGregory Neil Shapiro 
69*d39bd2c1SGregory Neil Shapiro static int
validpid(nproc,cpid)70*d39bd2c1SGregory Neil Shapiro validpid(nproc, cpid)
71*d39bd2c1SGregory Neil Shapiro 	int nproc;
72*d39bd2c1SGregory Neil Shapiro 	pid_t cpid;
73*d39bd2c1SGregory Neil Shapiro {
74*d39bd2c1SGregory Neil Shapiro 	int i;
75*d39bd2c1SGregory Neil Shapiro 
76*d39bd2c1SGregory Neil Shapiro 	for (i = 0; i < nproc; i++)
77*d39bd2c1SGregory Neil Shapiro 		if (cpid == pids[i])
78*d39bd2c1SGregory Neil Shapiro 			return i;
79*d39bd2c1SGregory Neil Shapiro 	if (Verbose > 0)
80*d39bd2c1SGregory Neil Shapiro 		fprintf(stderr, "pid=%ld not found, nproc=%d\n",
81*d39bd2c1SGregory Neil Shapiro 			(long) cpid, nproc);
82*d39bd2c1SGregory Neil Shapiro 	return -1;
83*d39bd2c1SGregory Neil Shapiro }
84*d39bd2c1SGregory Neil Shapiro 
852fb4f839SGregory Neil Shapiro /*
86*d39bd2c1SGregory Neil Shapiro **  NOTIFY_RD -- test of notify read feature
872fb4f839SGregory Neil Shapiro **
882fb4f839SGregory Neil Shapiro **	Parameters:
89*d39bd2c1SGregory Neil Shapiro **		nproc -- number of processes started
90*d39bd2c1SGregory Neil Shapiro **		nmsgs -- number of messages to read for each process
912fb4f839SGregory Neil Shapiro **
922fb4f839SGregory Neil Shapiro **	Returns:
932fb4f839SGregory Neil Shapiro **		0 on success
942fb4f839SGregory Neil Shapiro **		< 0 on failure
952fb4f839SGregory Neil Shapiro */
962fb4f839SGregory Neil Shapiro 
972fb4f839SGregory Neil Shapiro static int
notify_rd(nproc,nmsgs)98*d39bd2c1SGregory Neil Shapiro notify_rd(nproc, nmsgs)
992fb4f839SGregory Neil Shapiro 	int nproc;
100*d39bd2c1SGregory Neil Shapiro 	int nmsgs;
1015b0945b5SGregory Neil Shapiro {
102*d39bd2c1SGregory Neil Shapiro 	int r, i, pidx;
103*d39bd2c1SGregory Neil Shapiro 	long cpid;
104*d39bd2c1SGregory Neil Shapiro 	char buf[64], *p;
1052fb4f839SGregory Neil Shapiro #define TSTSTR "qf0001"
1062fb4f839SGregory Neil Shapiro 
1072fb4f839SGregory Neil Shapiro 	r = sm_notify_start(true, 0);
1082fb4f839SGregory Neil Shapiro 	if (r < 0)
1092fb4f839SGregory Neil Shapiro 	{
1102fb4f839SGregory Neil Shapiro 		perror("sm_notify_start failed");
1112fb4f839SGregory Neil Shapiro 		return -1;
1122fb4f839SGregory Neil Shapiro 	}
1132fb4f839SGregory Neil Shapiro 
114*d39bd2c1SGregory Neil Shapiro 	for (i = 0; i < nmsgs * nproc; i++)
115*d39bd2c1SGregory Neil Shapiro 	{
116*d39bd2c1SGregory Neil Shapiro 		do
1172fb4f839SGregory Neil Shapiro 		{
1182fb4f839SGregory Neil Shapiro 			r = sm_notify_rcv(buf, sizeof(buf), 5 * SM_MICROS);
1195b0945b5SGregory Neil Shapiro 			SM_TEST(r >= 0);
120*d39bd2c1SGregory Neil Shapiro 		} while (0 == r);
1215b0945b5SGregory Neil Shapiro 		if (r < 0)
1222fb4f839SGregory Neil Shapiro 		{
123*d39bd2c1SGregory Neil Shapiro 			fprintf(stderr, "pid=%ld, rcv=%d, i=%d\n",
124*d39bd2c1SGregory Neil Shapiro 				(long)getpid(), r, i);
1255b0945b5SGregory Neil Shapiro 			return r;
1262fb4f839SGregory Neil Shapiro 		}
1275b0945b5SGregory Neil Shapiro 		if (r > 0 && r < sizeof(buf))
1285b0945b5SGregory Neil Shapiro 			buf[r] = '\0';
1295b0945b5SGregory Neil Shapiro 		buf[sizeof(buf) - 1] = '\0';
130*d39bd2c1SGregory Neil Shapiro 
131*d39bd2c1SGregory Neil Shapiro 		if (Verbose > 0)
132*d39bd2c1SGregory Neil Shapiro 			fprintf(stderr, "pid=%ld, buf=\"%s\", i=%d\n",
133*d39bd2c1SGregory Neil Shapiro 				(long)getpid(), buf, i);
134*d39bd2c1SGregory Neil Shapiro 
1352fb4f839SGregory Neil Shapiro 		SM_TEST(strncmp(buf, TSTSTR, sizeof(TSTSTR) - 1) == 0);
1362fb4f839SGregory Neil Shapiro 		SM_TEST(r > sizeof(TSTSTR));
137*d39bd2c1SGregory Neil Shapiro 
138*d39bd2c1SGregory Neil Shapiro 		r = sscanf(buf + sizeof(TSTSTR), "%ld", &cpid);
139*d39bd2c1SGregory Neil Shapiro 		SM_TEST(1 == r);
140*d39bd2c1SGregory Neil Shapiro 		pidx = validpid(nproc, (pid_t)cpid);
141*d39bd2c1SGregory Neil Shapiro 		SM_TEST(pidx >= 0);
142*d39bd2c1SGregory Neil Shapiro 		SM_TEST(pidx < nproc);
143*d39bd2c1SGregory Neil Shapiro 
144*d39bd2c1SGregory Neil Shapiro 		p = strchr(buf, '_');
145*d39bd2c1SGregory Neil Shapiro 		SM_TEST(NULL != p);
146*d39bd2c1SGregory Neil Shapiro 		if (NULL != p && pidx < nproc && pidx >= 0)
147*d39bd2c1SGregory Neil Shapiro 		{
148*d39bd2c1SGregory Neil Shapiro 			int n;
149*d39bd2c1SGregory Neil Shapiro 
150*d39bd2c1SGregory Neil Shapiro 			r = sscanf(p + 1, "%d", &n);
151*d39bd2c1SGregory Neil Shapiro 			SM_TEST(1 == r);
152*d39bd2c1SGregory Neil Shapiro 			SM_TEST(n >= 0);
153*d39bd2c1SGregory Neil Shapiro 			SM_TEST(n < nmsgs);
154*d39bd2c1SGregory Neil Shapiro 			if (1 == r && n < nmsgs && n >= 0)
155*d39bd2c1SGregory Neil Shapiro 			{
156*d39bd2c1SGregory Neil Shapiro 				SM_TEST('\0' == msgs[pidx][n]);
157*d39bd2c1SGregory Neil Shapiro 				msgs[pidx][n] = 'f';
158*d39bd2c1SGregory Neil Shapiro 			}
159*d39bd2c1SGregory Neil Shapiro 		}
1605b0945b5SGregory Neil Shapiro 	}
1615b0945b5SGregory Neil Shapiro 	return 0;
1625b0945b5SGregory Neil Shapiro }
1635b0945b5SGregory Neil Shapiro 
1645b0945b5SGregory Neil Shapiro int
main(argc,argv)1655b0945b5SGregory Neil Shapiro main(argc, argv)
1665b0945b5SGregory Neil Shapiro 	int argc;
1675b0945b5SGregory Neil Shapiro 	char *argv[];
1685b0945b5SGregory Neil Shapiro {
1692fb4f839SGregory Neil Shapiro 	int i;
1705b0945b5SGregory Neil Shapiro 	int r = 0;
1712fb4f839SGregory Neil Shapiro 	int nproc = 1;
172*d39bd2c1SGregory Neil Shapiro 	int nmsgs = 1;
1735b0945b5SGregory Neil Shapiro 	pid_t pid;
1745b0945b5SGregory Neil Shapiro 
175*d39bd2c1SGregory Neil Shapiro # define OPTIONS	"n:p:V"
1762fb4f839SGregory Neil Shapiro 	while ((i = getopt(argc, argv, OPTIONS)) != -1)
1775b0945b5SGregory Neil Shapiro 	{
1782fb4f839SGregory Neil Shapiro 		switch ((char) i)
1795b0945b5SGregory Neil Shapiro 		{
180*d39bd2c1SGregory Neil Shapiro 		  case 'n':
181*d39bd2c1SGregory Neil Shapiro 			nmsgs = atoi(optarg);
182*d39bd2c1SGregory Neil Shapiro 			if (nmsgs < 1)
183*d39bd2c1SGregory Neil Shapiro 			{
184*d39bd2c1SGregory Neil Shapiro 				errno = EINVAL;
185*d39bd2c1SGregory Neil Shapiro 				fprintf(stderr, "-%c: must be >0\n", (char) i);
186*d39bd2c1SGregory Neil Shapiro 				return 1;
187*d39bd2c1SGregory Neil Shapiro 			}
188*d39bd2c1SGregory Neil Shapiro 			if (nmsgs >= MAX_MSGS)
189*d39bd2c1SGregory Neil Shapiro 			{
190*d39bd2c1SGregory Neil Shapiro 				errno = EINVAL;
191*d39bd2c1SGregory Neil Shapiro 				fprintf(stderr, "-%c: must be <%d\n", (char) i, MAX_MSGS);
192*d39bd2c1SGregory Neil Shapiro 				return 1;
193*d39bd2c1SGregory Neil Shapiro 			}
194*d39bd2c1SGregory Neil Shapiro 			break;
1952fb4f839SGregory Neil Shapiro 		  case 'p':
1962fb4f839SGregory Neil Shapiro 			nproc = atoi(optarg);
1972fb4f839SGregory Neil Shapiro 			if (nproc < 1)
1982fb4f839SGregory Neil Shapiro 			{
1992fb4f839SGregory Neil Shapiro 				errno = EINVAL;
200*d39bd2c1SGregory Neil Shapiro 				fprintf(stderr, "-%c: must be >0\n", (char) i);
201*d39bd2c1SGregory Neil Shapiro 				return 1;
2022fb4f839SGregory Neil Shapiro 			}
203*d39bd2c1SGregory Neil Shapiro 			if (nproc >= MAX_CHILDREN)
204*d39bd2c1SGregory Neil Shapiro 			{
205*d39bd2c1SGregory Neil Shapiro 				errno = EINVAL;
206*d39bd2c1SGregory Neil Shapiro 				fprintf(stderr, "-%c: must be <%d\n", (char) i, MAX_CHILDREN);
207*d39bd2c1SGregory Neil Shapiro 				return 1;
208*d39bd2c1SGregory Neil Shapiro 			}
209*d39bd2c1SGregory Neil Shapiro 			break;
210*d39bd2c1SGregory Neil Shapiro 		  case 'V':
211*d39bd2c1SGregory Neil Shapiro 			++Verbose;
2122fb4f839SGregory Neil Shapiro 			break;
2135b0945b5SGregory Neil Shapiro 		  default:
2145b0945b5SGregory Neil Shapiro 			break;
2155b0945b5SGregory Neil Shapiro 		}
2165b0945b5SGregory Neil Shapiro 	}
2175b0945b5SGregory Neil Shapiro 
218*d39bd2c1SGregory Neil Shapiro 	memset(msgs, '\0', sizeof(msgs));
2192fb4f839SGregory Neil Shapiro 	sm_test_begin(argc, argv, "test notify");
2205b0945b5SGregory Neil Shapiro 	r = sm_notify_init(0);
2212fb4f839SGregory Neil Shapiro 	SM_TEST(r >= 0);
2225b0945b5SGregory Neil Shapiro 	if (r < 0)
2235b0945b5SGregory Neil Shapiro 	{
2245b0945b5SGregory Neil Shapiro 		perror("sm_notify_init failed\n");
2252fb4f839SGregory Neil Shapiro 		return r;
2265b0945b5SGregory Neil Shapiro 	}
2275b0945b5SGregory Neil Shapiro 
2282fb4f839SGregory Neil Shapiro 	pid = 0;
2292fb4f839SGregory Neil Shapiro 	for (i = 0; i < nproc; i++)
2302fb4f839SGregory Neil Shapiro 	{
2315b0945b5SGregory Neil Shapiro 		if ((pid = fork()) < 0)
2325b0945b5SGregory Neil Shapiro 		{
2335b0945b5SGregory Neil Shapiro 			perror("fork failed\n");
2345b0945b5SGregory Neil Shapiro 			return -1;
2355b0945b5SGregory Neil Shapiro 		}
2365b0945b5SGregory Neil Shapiro 
2375b0945b5SGregory Neil Shapiro 		if (pid == 0)
2385b0945b5SGregory Neil Shapiro 		{
2395b0945b5SGregory Neil Shapiro 			/* give the parent the chance to set up data */
2405b0945b5SGregory Neil Shapiro 			sleep(1);
241*d39bd2c1SGregory Neil Shapiro 			r = notify_wr(getpid(), nmsgs);
2422fb4f839SGregory Neil Shapiro 			break;
2435b0945b5SGregory Neil Shapiro 		}
244*d39bd2c1SGregory Neil Shapiro 		if (pid > 0)
245*d39bd2c1SGregory Neil Shapiro 			pids[i] = pid;
2465b0945b5SGregory Neil Shapiro 	}
2472fb4f839SGregory Neil Shapiro 	if (pid > 0)
248*d39bd2c1SGregory Neil Shapiro 		r = notify_rd(nproc, nmsgs);
2495b0945b5SGregory Neil Shapiro 	SM_TEST(r >= 0);
2505b0945b5SGregory Neil Shapiro 	return sm_test_end();
2515b0945b5SGregory Neil Shapiro }
2522fb4f839SGregory Neil Shapiro #else /* _FFR_DMTRIGGER */
2532fb4f839SGregory Neil Shapiro int
main(argc,argv)2542fb4f839SGregory Neil Shapiro main(argc, argv)
2552fb4f839SGregory Neil Shapiro 	int argc;
2562fb4f839SGregory Neil Shapiro 	char *argv[];
2572fb4f839SGregory Neil Shapiro {
258*d39bd2c1SGregory Neil Shapiro 	printf("SKIPPED: no _FFR_DMTRIGGER || _FFR_NOTIFY\n");
2592fb4f839SGregory Neil Shapiro 	return 0;
2602fb4f839SGregory Neil Shapiro }
261*d39bd2c1SGregory Neil Shapiro #endif /* _FFR_DMTRIGGER || _FFR_NOTIFY */
262