xref: /dflybsd-src/test/testcases/sysv/sysvshm/shmtest.c (revision 938e74dcd560a0eea89fcf09db1435c6d5f94fcb)
1*a563ca70SAlex Hornung /*-
2*a563ca70SAlex Hornung  * Copyright (c) 1999 The NetBSD Foundation, Inc.
3*a563ca70SAlex Hornung  * All rights reserved.
4*a563ca70SAlex Hornung  *
5*a563ca70SAlex Hornung  * This code is derived from software contributed to The NetBSD Foundation
6*a563ca70SAlex Hornung  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
7*a563ca70SAlex Hornung  * NASA Ames Research Center.
8*a563ca70SAlex Hornung  *
9*a563ca70SAlex Hornung  * Redistribution and use in source and binary forms, with or without
10*a563ca70SAlex Hornung  * modification, are permitted provided that the following conditions
11*a563ca70SAlex Hornung  * are met:
12*a563ca70SAlex Hornung  * 1. Redistributions of source code must retain the above copyright
13*a563ca70SAlex Hornung  *    notice, this list of conditions and the following disclaimer.
14*a563ca70SAlex Hornung  * 2. Redistributions in binary form must reproduce the above copyright
15*a563ca70SAlex Hornung  *    notice, this list of conditions and the following disclaimer in the
16*a563ca70SAlex Hornung  *    documentation and/or other materials provided with the distribution.
17*a563ca70SAlex Hornung  * 3. All advertising materials mentioning features or use of this software
18*a563ca70SAlex Hornung  *    must display the following acknowledgement:
19*a563ca70SAlex Hornung  *	This product includes software developed by the NetBSD
20*a563ca70SAlex Hornung  *	Foundation, Inc. and its contributors.
21*a563ca70SAlex Hornung  * 4. Neither the name of The NetBSD Foundation nor the names of its
22*a563ca70SAlex Hornung  *    contributors may be used to endorse or promote products derived
23*a563ca70SAlex Hornung  *    from this software without specific prior written permission.
24*a563ca70SAlex Hornung  *
25*a563ca70SAlex Hornung  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
26*a563ca70SAlex Hornung  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27*a563ca70SAlex Hornung  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28*a563ca70SAlex Hornung  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
29*a563ca70SAlex Hornung  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30*a563ca70SAlex Hornung  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31*a563ca70SAlex Hornung  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32*a563ca70SAlex Hornung  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33*a563ca70SAlex Hornung  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34*a563ca70SAlex Hornung  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35*a563ca70SAlex Hornung  * POSSIBILITY OF SUCH DAMAGE.
36*a563ca70SAlex Hornung  *
37*a563ca70SAlex Hornung  * Obtained from: $NetBSD: shmtest.c,v 1.3 2002/07/20 08:36:26 grant Exp $
38*a563ca70SAlex Hornung  */
39*a563ca70SAlex Hornung 
40*a563ca70SAlex Hornung /*
41*a563ca70SAlex Hornung  * Test the SVID-compatible Shared Memory facility.
42*a563ca70SAlex Hornung  */
43*a563ca70SAlex Hornung 
44*a563ca70SAlex Hornung #include <sys/param.h>
45*a563ca70SAlex Hornung #include <sys/ipc.h>
46*a563ca70SAlex Hornung #include <sys/shm.h>
47*a563ca70SAlex Hornung #include <sys/wait.h>
48*a563ca70SAlex Hornung 
49*a563ca70SAlex Hornung #include <err.h>
50*a563ca70SAlex Hornung #include <errno.h>
51*a563ca70SAlex Hornung #include <signal.h>
52*a563ca70SAlex Hornung #include <stdio.h>
53*a563ca70SAlex Hornung #include <stdlib.h>
54*a563ca70SAlex Hornung #include <string.h>
55*a563ca70SAlex Hornung #include <time.h>
56*a563ca70SAlex Hornung #include <unistd.h>
57*a563ca70SAlex Hornung 
58*a563ca70SAlex Hornung void	print_shmid_ds (struct shmid_ds *, mode_t);
59*a563ca70SAlex Hornung void	sigsys_handler (int);
60*a563ca70SAlex Hornung void	sigchld_handler (int);
61*a563ca70SAlex Hornung void	cleanup (void);
62*a563ca70SAlex Hornung void	receiver (void);
63*a563ca70SAlex Hornung void	usage (void);
64*a563ca70SAlex Hornung 
65*a563ca70SAlex Hornung const char *m_str = "The quick brown fox jumped over the lazy dog.";
66*a563ca70SAlex Hornung 
67*a563ca70SAlex Hornung int	sender_shmid = -1;
68*a563ca70SAlex Hornung pid_t	child_pid;
69*a563ca70SAlex Hornung 
70*a563ca70SAlex Hornung key_t	shmkey;
71*a563ca70SAlex Hornung 
72*a563ca70SAlex Hornung size_t	pgsize;
73*a563ca70SAlex Hornung 
74*a563ca70SAlex Hornung int
main(argc,argv)75*a563ca70SAlex Hornung main(argc, argv)
76*a563ca70SAlex Hornung 	int argc;
77*a563ca70SAlex Hornung 	char *argv[];
78*a563ca70SAlex Hornung {
79*a563ca70SAlex Hornung 	struct sigaction sa;
80*a563ca70SAlex Hornung 	struct shmid_ds s_ds;
81*a563ca70SAlex Hornung 	sigset_t sigmask;
82*a563ca70SAlex Hornung 	char *shm_buf;
83*a563ca70SAlex Hornung 
84*a563ca70SAlex Hornung 	if (argc != 2)
85*a563ca70SAlex Hornung 		usage();
86*a563ca70SAlex Hornung 
87*a563ca70SAlex Hornung 	/*
88*a563ca70SAlex Hornung 	 * Install a SIGSYS handler so that we can exit gracefully if
89*a563ca70SAlex Hornung 	 * System V Shared Memory support isn't in the kernel.
90*a563ca70SAlex Hornung 	 */
91*a563ca70SAlex Hornung 	sa.sa_handler = sigsys_handler;
92*a563ca70SAlex Hornung 	sigemptyset(&sa.sa_mask);
93*a563ca70SAlex Hornung 	sa.sa_flags = 0;
94*a563ca70SAlex Hornung 	if (sigaction(SIGSYS, &sa, NULL) == -1)
95*a563ca70SAlex Hornung 		err(1, "sigaction SIGSYS");
96*a563ca70SAlex Hornung 
97*a563ca70SAlex Hornung 	/*
98*a563ca70SAlex Hornung 	 * Install and SIGCHLD handler to deal with all possible exit
99*a563ca70SAlex Hornung 	 * conditions of the receiver.
100*a563ca70SAlex Hornung 	 */
101*a563ca70SAlex Hornung 	sa.sa_handler = sigchld_handler;
102*a563ca70SAlex Hornung 	sigemptyset(&sa.sa_mask);
103*a563ca70SAlex Hornung 	sa.sa_flags = 0;
104*a563ca70SAlex Hornung 	if (sigaction(SIGCHLD, &sa, NULL) == -1)
105*a563ca70SAlex Hornung 		err(1, "sigaction SIGCHLD");
106*a563ca70SAlex Hornung 
107*a563ca70SAlex Hornung 	pgsize = sysconf(_SC_PAGESIZE);
108*a563ca70SAlex Hornung 
109*a563ca70SAlex Hornung 	shmkey = ftok(argv[1], 4160);
110*a563ca70SAlex Hornung 
111*a563ca70SAlex Hornung 	/*
112*a563ca70SAlex Hornung 	 * Initialize child_pid to ourselves to that the cleanup function
113*a563ca70SAlex Hornung 	 * works before we create the receiver.
114*a563ca70SAlex Hornung 	 */
115*a563ca70SAlex Hornung 	child_pid = getpid();
116*a563ca70SAlex Hornung 
117*a563ca70SAlex Hornung 	/*
118*a563ca70SAlex Hornung 	 * Make sure that when the sender exits, the message queue is
119*a563ca70SAlex Hornung 	 * removed.
120*a563ca70SAlex Hornung 	 */
121*a563ca70SAlex Hornung 	if (atexit(cleanup) == -1)
122*a563ca70SAlex Hornung 		err(1, "atexit");
123*a563ca70SAlex Hornung 
124*a563ca70SAlex Hornung 	if ((sender_shmid = shmget(shmkey, pgsize, IPC_CREAT | 0640)) == -1)
125*a563ca70SAlex Hornung 		err(1, "shmget");
126*a563ca70SAlex Hornung 
127*a563ca70SAlex Hornung 	if (shmctl(sender_shmid, IPC_STAT, &s_ds) == -1)
128*a563ca70SAlex Hornung 		err(1, "shmctl IPC_STAT");
129*a563ca70SAlex Hornung 
130*a563ca70SAlex Hornung 	print_shmid_ds(&s_ds, 0640);
131*a563ca70SAlex Hornung 
132*a563ca70SAlex Hornung 	s_ds.shm_perm.mode = (s_ds.shm_perm.mode & ~0777) | 0600;
133*a563ca70SAlex Hornung 
134*a563ca70SAlex Hornung 	if (shmctl(sender_shmid, IPC_SET, &s_ds) == -1)
135*a563ca70SAlex Hornung 		err(1, "shmctl IPC_SET");
136*a563ca70SAlex Hornung 
137*a563ca70SAlex Hornung 	memset(&s_ds, 0, sizeof(s_ds));
138*a563ca70SAlex Hornung 
139*a563ca70SAlex Hornung 	if (shmctl(sender_shmid, IPC_STAT, &s_ds) == -1)
140*a563ca70SAlex Hornung 		err(1, "shmctl IPC_STAT");
141*a563ca70SAlex Hornung 
142*a563ca70SAlex Hornung 	if ((s_ds.shm_perm.mode & 0777) != 0600)
143*a563ca70SAlex Hornung 		err(1, "IPC_SET of mode didn't hold");
144*a563ca70SAlex Hornung 
145*a563ca70SAlex Hornung 	print_shmid_ds(&s_ds, 0600);
146*a563ca70SAlex Hornung 
147*a563ca70SAlex Hornung 	if ((shm_buf = shmat(sender_shmid, NULL, 0)) == (void *) -1)
148*a563ca70SAlex Hornung 		err(1, "sender: shmat");
149*a563ca70SAlex Hornung 
150*a563ca70SAlex Hornung 	/*
151*a563ca70SAlex Hornung 	 * Write the test pattern into the shared memory buffer.
152*a563ca70SAlex Hornung 	 */
153*a563ca70SAlex Hornung 	strcpy(shm_buf, m_str);
154*a563ca70SAlex Hornung 
155*a563ca70SAlex Hornung 	switch ((child_pid = fork())) {
156*a563ca70SAlex Hornung 	case -1:
157*a563ca70SAlex Hornung 		err(1, "fork");
158*a563ca70SAlex Hornung 		/* NOTREACHED */
159*a563ca70SAlex Hornung 
160*a563ca70SAlex Hornung 	case 0:
161*a563ca70SAlex Hornung 		receiver();
162*a563ca70SAlex Hornung 		break;
163*a563ca70SAlex Hornung 
164*a563ca70SAlex Hornung 	default:
165*a563ca70SAlex Hornung 		break;
166*a563ca70SAlex Hornung 	}
167*a563ca70SAlex Hornung 
168*a563ca70SAlex Hornung 	/*
169*a563ca70SAlex Hornung 	 * Suspend forever; when we get SIGCHLD, the handler will exit.
170*a563ca70SAlex Hornung 	 */
171*a563ca70SAlex Hornung 	sigemptyset(&sigmask);
172*a563ca70SAlex Hornung 	(void) sigsuspend(&sigmask);
173*a563ca70SAlex Hornung 
174*a563ca70SAlex Hornung 	/*
175*a563ca70SAlex Hornung 	 * ...and any other signal is an unexpected error.
176*a563ca70SAlex Hornung 	 */
177*a563ca70SAlex Hornung 	errx(1, "sender: received unexpected signal");
178*a563ca70SAlex Hornung }
179*a563ca70SAlex Hornung 
180*a563ca70SAlex Hornung void
sigsys_handler(signo)181*a563ca70SAlex Hornung sigsys_handler(signo)
182*a563ca70SAlex Hornung 	int signo;
183*a563ca70SAlex Hornung {
184*a563ca70SAlex Hornung 
185*a563ca70SAlex Hornung 	errx(1, "System V Shared Memory support is not present in the kernel");
186*a563ca70SAlex Hornung }
187*a563ca70SAlex Hornung 
188*a563ca70SAlex Hornung void
sigchld_handler(signo)189*a563ca70SAlex Hornung sigchld_handler(signo)
190*a563ca70SAlex Hornung 	int signo;
191*a563ca70SAlex Hornung {
192*a563ca70SAlex Hornung 	struct shmid_ds s_ds;
193*a563ca70SAlex Hornung 	int cstatus;
194*a563ca70SAlex Hornung 
195*a563ca70SAlex Hornung 	/*
196*a563ca70SAlex Hornung 	 * Reap the child; if it exited successfully, then the test passed!
197*a563ca70SAlex Hornung 	 */
198*a563ca70SAlex Hornung 	if (waitpid(child_pid, &cstatus, 0) != child_pid)
199*a563ca70SAlex Hornung 		err(1, "waitpid");
200*a563ca70SAlex Hornung 
201*a563ca70SAlex Hornung 	if (WIFEXITED(cstatus) == 0)
202*a563ca70SAlex Hornung 		errx(1, "receiver exited abnormally");
203*a563ca70SAlex Hornung 
204*a563ca70SAlex Hornung 	if (WEXITSTATUS(cstatus) != 0)
205*a563ca70SAlex Hornung 		errx(1, "receiver exited with status %d",
206*a563ca70SAlex Hornung 		    WEXITSTATUS(cstatus));
207*a563ca70SAlex Hornung 
208*a563ca70SAlex Hornung 	/*
209*a563ca70SAlex Hornung 	 * If we get here, the child has exited normally, and thus
210*a563ca70SAlex Hornung 	 * we should exit normally too.  First, tho, we print out
211*a563ca70SAlex Hornung 	 * the final stats for the message queue.
212*a563ca70SAlex Hornung 	 */
213*a563ca70SAlex Hornung 
214*a563ca70SAlex Hornung 	if (shmctl(sender_shmid, IPC_STAT, &s_ds) == -1)
215*a563ca70SAlex Hornung 		err(1, "shmctl IPC_STAT");
216*a563ca70SAlex Hornung 
217*a563ca70SAlex Hornung 	print_shmid_ds(&s_ds, 0600);
218*a563ca70SAlex Hornung 
219*a563ca70SAlex Hornung 	exit(0);
220*a563ca70SAlex Hornung }
221*a563ca70SAlex Hornung 
222*a563ca70SAlex Hornung void
cleanup()223*a563ca70SAlex Hornung cleanup()
224*a563ca70SAlex Hornung {
225*a563ca70SAlex Hornung 
226*a563ca70SAlex Hornung 	/*
227*a563ca70SAlex Hornung 	 * If we're the sender, and it exists, remove the shared memory area.
228*a563ca70SAlex Hornung 	 */
229*a563ca70SAlex Hornung 	if (child_pid != 0 && sender_shmid != -1) {
230*a563ca70SAlex Hornung 		if (shmctl(sender_shmid, IPC_RMID, NULL) == -1)
231*a563ca70SAlex Hornung 			warn("shmctl IPC_RMID");
232*a563ca70SAlex Hornung 	}
233*a563ca70SAlex Hornung }
234*a563ca70SAlex Hornung 
235*a563ca70SAlex Hornung void
print_shmid_ds(sp,mode)236*a563ca70SAlex Hornung print_shmid_ds(sp, mode)
237*a563ca70SAlex Hornung 	struct shmid_ds *sp;
238*a563ca70SAlex Hornung 	mode_t mode;
239*a563ca70SAlex Hornung {
240*a563ca70SAlex Hornung 	uid_t uid = geteuid();
241*a563ca70SAlex Hornung 	gid_t gid = getegid();
242*a563ca70SAlex Hornung 
243*a563ca70SAlex Hornung 	printf("PERM: uid %d, gid %d, cuid %d, cgid %d, mode 0%o\n",
244*a563ca70SAlex Hornung 	    sp->shm_perm.uid, sp->shm_perm.gid,
245*a563ca70SAlex Hornung 	    sp->shm_perm.cuid, sp->shm_perm.cgid,
246*a563ca70SAlex Hornung 	    sp->shm_perm.mode & 0777);
247*a563ca70SAlex Hornung 
248*a563ca70SAlex Hornung 	printf("segsz %lu, lpid %d, cpid %d, nattch %u\n",
249*a563ca70SAlex Hornung 	    (u_long)sp->shm_segsz, sp->shm_lpid, sp->shm_cpid,
250*a563ca70SAlex Hornung 	    sp->shm_nattch);
251*a563ca70SAlex Hornung 
252*a563ca70SAlex Hornung 	printf("atime: %s", ctime(&sp->shm_atime));
253*a563ca70SAlex Hornung 	printf("dtime: %s", ctime(&sp->shm_dtime));
254*a563ca70SAlex Hornung 	printf("ctime: %s", ctime(&sp->shm_ctime));
255*a563ca70SAlex Hornung 
256*a563ca70SAlex Hornung 	/*
257*a563ca70SAlex Hornung 	 * Sanity check a few things.
258*a563ca70SAlex Hornung 	 */
259*a563ca70SAlex Hornung 
260*a563ca70SAlex Hornung 	if (sp->shm_perm.uid != uid || sp->shm_perm.cuid != uid)
261*a563ca70SAlex Hornung 		errx(1, "uid mismatch");
262*a563ca70SAlex Hornung 
263*a563ca70SAlex Hornung 	if (sp->shm_perm.gid != gid || sp->shm_perm.cgid != gid)
264*a563ca70SAlex Hornung 		errx(1, "gid mismatch");
265*a563ca70SAlex Hornung 
266*a563ca70SAlex Hornung 	if ((sp->shm_perm.mode & 0777) != mode)
267*a563ca70SAlex Hornung 		errx(1, "mode mismatch");
268*a563ca70SAlex Hornung }
269*a563ca70SAlex Hornung 
270*a563ca70SAlex Hornung void
usage()271*a563ca70SAlex Hornung usage()
272*a563ca70SAlex Hornung {
273*a563ca70SAlex Hornung 
274*a563ca70SAlex Hornung 	fprintf(stderr, "usage: %s keypath\n", getprogname());
275*a563ca70SAlex Hornung 	exit(1);
276*a563ca70SAlex Hornung }
277*a563ca70SAlex Hornung 
278*a563ca70SAlex Hornung void
receiver()279*a563ca70SAlex Hornung receiver()
280*a563ca70SAlex Hornung {
281*a563ca70SAlex Hornung 	int shmid;
282*a563ca70SAlex Hornung 	void *shm_buf;
283*a563ca70SAlex Hornung 
284*a563ca70SAlex Hornung 	if ((shmid = shmget(shmkey, pgsize, 0)) == -1)
285*a563ca70SAlex Hornung 		err(1, "receiver: shmget");
286*a563ca70SAlex Hornung 
287*a563ca70SAlex Hornung 	if ((shm_buf = shmat(shmid, NULL, 0)) == (void *) -1)
288*a563ca70SAlex Hornung 		err(1, "receiver: shmat");
289*a563ca70SAlex Hornung 
290*a563ca70SAlex Hornung 	printf("%s\n", (const char *)shm_buf);
291*a563ca70SAlex Hornung 	if (strcmp((const char *)shm_buf, m_str) != 0)
292*a563ca70SAlex Hornung 		err(1, "receiver: data isn't correct");
293*a563ca70SAlex Hornung 
294*a563ca70SAlex Hornung 	exit(0);
295*a563ca70SAlex Hornung }
296