summaryrefslogtreecommitdiff
path: root/src/regress/lib/libc/sys/t_msgrcv.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/regress/lib/libc/sys/t_msgrcv.c')
-rw-r--r--src/regress/lib/libc/sys/t_msgrcv.c385
1 files changed, 0 insertions, 385 deletions
diff --git a/src/regress/lib/libc/sys/t_msgrcv.c b/src/regress/lib/libc/sys/t_msgrcv.c
deleted file mode 100644
index 2e73b3d5ba..0000000000
--- a/src/regress/lib/libc/sys/t_msgrcv.c
+++ /dev/null
@@ -1,385 +0,0 @@
1/* $OpenBSD: t_msgrcv.c,v 1.2 2021/12/13 16:56:48 deraadt Exp $ */
2/* $NetBSD: t_msgrcv.c,v 1.5 2017/10/08 08:31:05 kre Exp $ */
3
4/*-
5 * Copyright (c) 2011 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Jukka Ruohonen.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include "macros.h"
34
35#include <sys/msg.h>
36#include <sys/stat.h>
37#include <sys/sysctl.h>
38#include <sys/wait.h>
39
40#include "atf-c.h"
41#include <errno.h>
42#include <limits.h>
43#include <pwd.h>
44#include <signal.h>
45#include <stdio.h>
46#include <stdlib.h>
47#include <string.h>
48#include <sysexits.h>
49#include <time.h>
50#include <unistd.h>
51
52#define MSG_KEY 1234
53#define MSG_MTYPE_1 0x41
54#define MSG_MTYPE_2 0x42
55#define MSG_MTYPE_3 0x43
56#define MSG_LEN 3
57
58struct msg {
59 long mtype;
60 char buf[MSG_LEN];
61};
62
63static void clean(void);
64
65static void
66clean(void)
67{
68 int id;
69
70 if ((id = msgget(MSG_KEY, 0)) != -1)
71 (void)msgctl(id, IPC_RMID, 0);
72}
73
74ATF_TC_WITH_CLEANUP(msgrcv_basic);
75ATF_TC_HEAD(msgrcv_basic, tc)
76{
77 atf_tc_set_md_var(tc, "descr", "A basic test of msgrcv(2)");
78}
79
80ATF_TC_BODY(msgrcv_basic, tc)
81{
82 struct msg msg1 = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
83 struct msg msg2 = { MSG_MTYPE_1, { 'x', 'y', 'z' } };
84 int id;
85
86 id = msgget(MSG_KEY, IPC_CREAT | 0600);
87 ATF_REQUIRE(id != -1);
88
89 (void)msgsnd(id, &msg1, MSG_LEN, IPC_NOWAIT);
90 (void)msgrcv(id, &msg2, MSG_LEN, MSG_MTYPE_1, IPC_NOWAIT);
91
92 ATF_CHECK(msg1.buf[0] == msg2.buf[0]);
93 ATF_CHECK(msg1.buf[1] == msg2.buf[1]);
94 ATF_CHECK(msg1.buf[2] == msg2.buf[2]);
95
96 ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
97}
98
99ATF_TC_CLEANUP(msgrcv_basic, tc)
100{
101 clean();
102}
103
104ATF_TC_WITH_CLEANUP(msgrcv_block);
105ATF_TC_HEAD(msgrcv_block, tc)
106{
107 atf_tc_set_md_var(tc, "descr", "Test that msgrcv(2) blocks");
108}
109
110ATF_TC_BODY(msgrcv_block, tc)
111{
112 struct msg msg = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
113 int id, sta;
114 pid_t pid;
115
116 id = msgget(MSG_KEY, IPC_CREAT | 0600);
117 ATF_REQUIRE(id != -1);
118
119 pid = fork();
120 ATF_REQUIRE(pid >= 0);
121
122 if (pid == 0) {
123
124 if (msgrcv(id, &msg, MSG_LEN, MSG_MTYPE_1, 0) < 0)
125 _exit(EXIT_FAILURE);
126
127 _exit(EXIT_SUCCESS);
128 }
129
130 /*
131 * Below msgsnd(2) should unblock the child,
132 * and hence kill(2) should fail with ESRCH.
133 */
134 (void)sleep(1);
135 (void)msgsnd(id, &msg, MSG_LEN, IPC_NOWAIT);
136 (void)sleep(1);
137 (void)kill(pid, SIGKILL);
138 (void)wait(&sta);
139
140 if (WIFEXITED(sta) == 0 || WIFSIGNALED(sta) != 0)
141 atf_tc_fail("msgrcv(2) did not block");
142
143 ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
144}
145
146ATF_TC_CLEANUP(msgrcv_block, tc)
147{
148 clean();
149}
150
151ATF_TC_WITH_CLEANUP(msgrcv_err);
152ATF_TC_HEAD(msgrcv_err, tc)
153{
154 atf_tc_set_md_var(tc, "descr", "Test errors from msgrcv(2)");
155}
156
157ATF_TC_BODY(msgrcv_err, tc)
158{
159 struct msg msg = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
160 int id, r = 0;
161
162 id = msgget(MSG_KEY, IPC_CREAT | 0600);
163 ATF_REQUIRE(id != -1);
164
165 errno = 0;
166
167 ATF_REQUIRE_ERRNO(ENOMSG, msgrcv(id, &msg,
168 MSG_LEN, MSG_MTYPE_1, IPC_NOWAIT) == -1);
169
170 ATF_REQUIRE(msgsnd(id, &msg, MSG_LEN, IPC_NOWAIT) == 0);
171
172 errno = 0;
173
174 ATF_REQUIRE_ERRNO(EFAULT, msgrcv(id, (void *)-1,
175 MSG_LEN, MSG_MTYPE_1, IPC_NOWAIT) == -1);
176
177 errno = 0;
178
179 ATF_REQUIRE_ERRNO(EINVAL, msgrcv(-1, &msg,
180 MSG_LEN, MSG_MTYPE_1, IPC_NOWAIT) == -1);
181
182 errno = 0;
183
184 ATF_REQUIRE_ERRNO(EINVAL, msgrcv(-1, &msg,
185 SSIZE_MAX, MSG_MTYPE_1, IPC_NOWAIT) == -1);
186
187 ATF_REQUIRE(msgsnd(id, &msg, MSG_LEN, IPC_NOWAIT) == 0);
188
189 errno = 0;
190
191 ATF_REQUIRE_ERRNO(E2BIG, msgrcv(id, &r,
192 MSG_LEN - 1, MSG_MTYPE_1, IPC_NOWAIT) == -1);
193
194 ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
195}
196
197ATF_TC_CLEANUP(msgrcv_err, tc)
198{
199 clean();
200}
201
202
203ATF_TC_WITH_CLEANUP(msgrcv_mtype);
204ATF_TC_HEAD(msgrcv_mtype, tc)
205{
206 atf_tc_set_md_var(tc, "descr", "Test message types with msgrcv(2)");
207}
208
209ATF_TC_BODY(msgrcv_mtype, tc)
210{
211 struct msg msg1 = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
212 struct msg msg2 = { MSG_MTYPE_3, { 'x', 'y', 'z' } };
213 int id;
214
215 id = msgget(MSG_KEY, IPC_CREAT | 0600);
216 ATF_REQUIRE(id != -1);
217
218 (void)msgsnd(id, &msg1, MSG_LEN, IPC_NOWAIT);
219 (void)msgrcv(id, &msg2, MSG_LEN, MSG_MTYPE_2, IPC_NOWAIT);
220
221 ATF_CHECK(msg1.buf[0] != msg2.buf[0]); /* Different mtype. */
222 ATF_CHECK(msg1.buf[1] != msg2.buf[1]);
223 ATF_CHECK(msg1.buf[2] != msg2.buf[2]);
224
225 (void)msgrcv(id, &msg2, MSG_LEN, MSG_MTYPE_1, IPC_NOWAIT);
226
227 ATF_CHECK(msg1.buf[0] == msg2.buf[0]); /* Same mtype. */
228 ATF_CHECK(msg1.buf[1] == msg2.buf[1]);
229 ATF_CHECK(msg1.buf[2] == msg2.buf[2]);
230
231 ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
232}
233
234ATF_TC_CLEANUP(msgrcv_mtype, tc)
235{
236 clean();
237}
238
239ATF_TC_WITH_CLEANUP(msgrcv_nonblock);
240ATF_TC_HEAD(msgrcv_nonblock, tc)
241{
242 atf_tc_set_md_var(tc, "descr", "Test msgrcv(2) with IPC_NOWAIT");
243 atf_tc_set_md_var(tc, "timeout", "10");
244}
245
246ATF_TC_BODY(msgrcv_nonblock, tc)
247{
248 struct msg msg = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
249 const ssize_t n = 10;
250 int id, sta;
251 ssize_t i;
252 pid_t pid;
253
254 id = msgget(MSG_KEY, IPC_CREAT | 0600);
255 ATF_REQUIRE(id != -1);
256
257 for (i = 0; i < n; i++) {
258
259 ATF_REQUIRE(msgsnd(id, &msg, MSG_LEN, IPC_NOWAIT) == 0);
260 }
261
262 pid = fork();
263 ATF_REQUIRE(pid >= 0);
264
265 if (pid == 0) {
266
267 while (i != 0) {
268
269 if (msgrcv(id, &msg, MSG_LEN, MSG_MTYPE_1,
270 IPC_NOWAIT) == -1)
271 _exit(EXIT_FAILURE);
272
273 i--;
274 }
275
276 _exit(EXIT_SUCCESS);
277 }
278
279 (void)sleep(2);
280 (void)kill(pid, SIGKILL);
281 (void)wait(&sta);
282
283 if (WIFSIGNALED(sta) != 0 || WTERMSIG(sta) == SIGKILL)
284 atf_tc_fail("msgrcv(2) blocked with IPC_NOWAIT");
285
286 if (WIFEXITED(sta) == 0 && WEXITSTATUS(sta) != EXIT_SUCCESS)
287 atf_tc_fail("msgrcv(2) failed");
288
289 ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
290}
291
292ATF_TC_CLEANUP(msgrcv_nonblock, tc)
293{
294 clean();
295}
296
297ATF_TC_WITH_CLEANUP(msgrcv_truncate);
298ATF_TC_HEAD(msgrcv_truncate, tc)
299{
300 atf_tc_set_md_var(tc, "descr", "Test msgrcv(2) with MSG_NOERROR");
301}
302
303ATF_TC_BODY(msgrcv_truncate, tc)
304{
305#define MSG_SMALLLEN 2
306 struct msgsmall {
307 long mtype;
308 char buf[MSG_SMALLLEN];
309 };
310
311 struct msg msg1 = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
312 struct msgsmall msg2 = { MSG_MTYPE_1, { 'x', 'y' } };
313 int id;
314
315 id = msgget(MSG_KEY, IPC_CREAT | 0600);
316 ATF_REQUIRE(id != -1);
317
318 (void)msgsnd(id, &msg1, MSG_LEN, IPC_NOWAIT);
319 (void)msgrcv(id, &msg2, MSG_SMALLLEN,
320 MSG_MTYPE_1, IPC_NOWAIT | MSG_NOERROR);
321
322 ATF_CHECK(msg1.buf[0] == msg2.buf[0]);
323 ATF_CHECK(msg1.buf[1] == msg2.buf[1]);
324
325 ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
326}
327
328ATF_TC_CLEANUP(msgrcv_truncate, tc)
329{
330 clean();
331}
332
333static volatile int sig_caught;
334
335static void
336sigsys_handler(int signum)
337{
338
339 sig_caught = signum;
340}
341
342static int
343no_kernel_sysvmsg(void)
344{
345 int id;
346 void (*osig)(int);
347
348 sig_caught = 0;
349 osig = signal(SIGSYS, sigsys_handler);
350 id = msgget(MSG_KEY, IPC_CREAT | 0600);
351 if (sig_caught || id == -1)
352 return 1;
353
354 (void)msgctl(id, IPC_RMID, 0);
355 (void)signal(SIGSYS, osig);
356
357 return 0;
358}
359
360ATF_TC(msgrcv_query);
361ATF_TC_HEAD(msgrcv_query, tc)
362{
363 atf_tc_set_md_var(tc, "descr", "Skip msgrcv_* tests - no SYSVMSG");
364}
365ATF_TC_BODY(msgrcv_query, tc)
366{
367 atf_tc_skip("No SYSVMSG in kernel");
368}
369
370ATF_TP_ADD_TCS(tp)
371{
372
373 if (no_kernel_sysvmsg()) {
374 ATF_TP_ADD_TC(tp, msgrcv_query);
375 } else {
376 ATF_TP_ADD_TC(tp, msgrcv_basic);
377 ATF_TP_ADD_TC(tp, msgrcv_block);
378 ATF_TP_ADD_TC(tp, msgrcv_err);
379 ATF_TP_ADD_TC(tp, msgrcv_mtype);
380 ATF_TP_ADD_TC(tp, msgrcv_nonblock);
381 ATF_TP_ADD_TC(tp, msgrcv_truncate);
382 }
383
384 return atf_no_error();
385}