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