]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/sendmail/libsm/t-notify.c
Merge commit '850ef5ae11d69ea3381bd310f564f025fc8caea3'
[FreeBSD/FreeBSD.git] / contrib / sendmail / libsm / t-notify.c
1 /*
2  * Copyright (c) 2020 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>
11 #include <stdio.h>
12
13 #if _FFR_DMTRIGGER || _FFR_NOTIFY
14 # include <stdlib.h>
15 # include <unistd.h>
16 # include <errno.h>
17 # include <sm/heap.h>
18 # include <sm/string.h>
19 # include <sm/test.h>
20 # include <sm/notify.h>
21 # include <sm/conf.h>
22 # include "notify.h"
23
24 static int Verbose = 0;
25 #define MAX_CHILDREN    256
26 #define MAX_MSGS        1024
27 static pid_t pids[MAX_CHILDREN];
28 static char msgs[MAX_CHILDREN][MAX_MSGS];
29
30 /*
31 **  NOTIFY_WR -- test of notify write feature
32 **
33 **      Parameters:
34 **              pid -- pid of process
35 **              nmsgs -- number of messages to write
36 **
37 **      Returns:
38 **              >=0 on success
39 **              < 0 on failure
40 */
41
42 static int
43 notify_wr(pid, nmsgs)
44         pid_t pid;
45         int nmsgs;
46 {
47         int r, i;
48         size_t len;
49         char buf[64];
50 #define TSTSTR "qf0001"
51
52         r = sm_notify_start(false, 0);
53         if (r < 0)
54         {
55                 perror("sm_notify_start failed");
56                 return -1;
57         }
58
59         for (i = 0; i < nmsgs; i++)
60         {
61                 len = sm_snprintf(buf, sizeof(buf), "%s-%ld_%d", TSTSTR,
62                                 (long) pid, i);
63                 r = sm_notify_snd(buf, len);
64                 SM_TEST(r >= 0);
65         }
66         return r;
67 }
68
69 static int
70 validpid(nproc, cpid)
71         int nproc;
72         pid_t cpid;
73 {
74         int i;
75
76         for (i = 0; i < nproc; i++)
77                 if (cpid == pids[i])
78                         return i;
79         if (Verbose > 0)
80                 fprintf(stderr, "pid=%ld not found, nproc=%d\n",
81                         (long) cpid, nproc);
82         return -1;
83 }
84
85 /*
86 **  NOTIFY_RD -- test of notify read feature
87 **
88 **      Parameters:
89 **              nproc -- number of processes started
90 **              nmsgs -- number of messages to read for each process
91 **
92 **      Returns:
93 **              0 on success
94 **              < 0 on failure
95 */
96
97 static int
98 notify_rd(nproc, nmsgs)
99         int nproc;
100         int nmsgs;
101 {
102         int r, i, pidx;
103         long cpid;
104         char buf[64], *p;
105 #define TSTSTR "qf0001"
106
107         r = sm_notify_start(true, 0);
108         if (r < 0)
109         {
110                 perror("sm_notify_start failed");
111                 return -1;
112         }
113
114         for (i = 0; i < nmsgs * nproc; i++)
115         {
116                 do
117                 {
118                         r = sm_notify_rcv(buf, sizeof(buf), 5 * SM_MICROS);
119                         SM_TEST(r >= 0);
120                 } while (0 == r);
121                 if (r < 0)
122                 {
123                         fprintf(stderr, "pid=%ld, rcv=%d, i=%d\n",
124                                 (long)getpid(), r, i);
125                         return r;
126                 }
127                 if (r > 0 && r < sizeof(buf))
128                         buf[r] = '\0';
129                 buf[sizeof(buf) - 1] = '\0';
130
131                 if (Verbose > 0)
132                         fprintf(stderr, "pid=%ld, buf=\"%s\", i=%d\n",
133                                 (long)getpid(), buf, i);
134
135                 SM_TEST(strncmp(buf, TSTSTR, sizeof(TSTSTR) - 1) == 0);
136                 SM_TEST(r > sizeof(TSTSTR));
137
138                 r = sscanf(buf + sizeof(TSTSTR), "%ld", &cpid);
139                 SM_TEST(1 == r);
140                 pidx = validpid(nproc, (pid_t)cpid);
141                 SM_TEST(pidx >= 0);
142                 SM_TEST(pidx < nproc);
143
144                 p = strchr(buf, '_');
145                 SM_TEST(NULL != p);
146                 if (NULL != p && pidx < nproc && pidx >= 0)
147                 {
148                         int n;
149
150                         r = sscanf(p + 1, "%d", &n);
151                         SM_TEST(1 == r);
152                         SM_TEST(n >= 0);
153                         SM_TEST(n < nmsgs);
154                         if (1 == r && n < nmsgs && n >= 0)
155                         {
156                                 SM_TEST('\0' == msgs[pidx][n]);
157                                 msgs[pidx][n] = 'f';
158                         }
159                 }
160         }
161         return 0;
162 }
163
164 int
165 main(argc, argv)
166         int argc;
167         char *argv[];
168 {
169         int i;
170         int r = 0;
171         int nproc = 1;
172         int nmsgs = 1;
173         pid_t pid;
174
175 # define OPTIONS        "n:p:V"
176         while ((i = getopt(argc, argv, OPTIONS)) != -1)
177         {
178                 switch ((char) i)
179                 {
180                   case 'n':
181                         nmsgs = atoi(optarg);
182                         if (nmsgs < 1)
183                         {
184                                 errno = EINVAL;
185                                 fprintf(stderr, "-%c: must be >0\n", (char) i);
186                                 return 1;
187                         }
188                         if (nmsgs >= MAX_MSGS)
189                         {
190                                 errno = EINVAL;
191                                 fprintf(stderr, "-%c: must be <%d\n", (char) i, MAX_MSGS);
192                                 return 1;
193                         }
194                         break;
195                   case 'p':
196                         nproc = atoi(optarg);
197                         if (nproc < 1)
198                         {
199                                 errno = EINVAL;
200                                 fprintf(stderr, "-%c: must be >0\n", (char) i);
201                                 return 1;
202                         }
203                         if (nproc >= MAX_CHILDREN)
204                         {
205                                 errno = EINVAL;
206                                 fprintf(stderr, "-%c: must be <%d\n", (char) i, MAX_CHILDREN);
207                                 return 1;
208                         }
209                         break;
210                   case 'V':
211                         ++Verbose;
212                         break;
213                   default:
214                         break;
215                 }
216         }
217
218         memset(msgs, '\0', sizeof(msgs));
219         sm_test_begin(argc, argv, "test notify");
220         r = sm_notify_init(0);
221         SM_TEST(r >= 0);
222         if (r < 0)
223         {
224                 perror("sm_notify_init failed\n");
225                 return r;
226         }
227
228         pid = 0;
229         for (i = 0; i < nproc; i++)
230         {
231                 if ((pid = fork()) < 0)
232                 {
233                         perror("fork failed\n");
234                         return -1;
235                 }
236
237                 if (pid == 0)
238                 {
239                         /* give the parent the chance to set up data */
240                         sleep(1);
241                         r = notify_wr(getpid(), nmsgs);
242                         break;
243                 }
244                 if (pid > 0)
245                         pids[i] = pid;
246         }
247         if (pid > 0)
248                 r = notify_rd(nproc, nmsgs);
249         SM_TEST(r >= 0);
250         return sm_test_end();
251 }
252 #else /* _FFR_DMTRIGGER */
253 int
254 main(argc, argv)
255         int argc;
256         char *argv[];
257 {
258         printf("SKIPPED: no _FFR_DMTRIGGER || _FFR_NOTIFY\n");
259         return 0;
260 }
261 #endif /* _FFR_DMTRIGGER || _FFR_NOTIFY */