diff options
author | Artur Grabowski <art@cvs.openbsd.org> | 2002-02-16 14:34:55 +0000 |
---|---|---|
committer | Artur Grabowski <art@cvs.openbsd.org> | 2002-02-16 14:34:55 +0000 |
commit | 1e9aa1b7e7c743eaedb8e1aa8bf66c17a3c0bc79 (patch) | |
tree | 27d4921412f575b29c659f6f127a3966e9680f7a /regress/sys/kern/sysvshm | |
parent | d64737a15b963bcb5db0423df8c460f890b77ba4 (diff) |
test sysv shared memory. From NetBSD with changes.
Diffstat (limited to 'regress/sys/kern/sysvshm')
-rw-r--r-- | regress/sys/kern/sysvshm/Makefile | 5 | ||||
-rw-r--r-- | regress/sys/kern/sysvshm/shmtest.c | 311 |
2 files changed, 316 insertions, 0 deletions
diff --git a/regress/sys/kern/sysvshm/Makefile b/regress/sys/kern/sysvshm/Makefile new file mode 100644 index 00000000000..53ad9fd3203 --- /dev/null +++ b/regress/sys/kern/sysvshm/Makefile @@ -0,0 +1,5 @@ +# $OpenBSD: Makefile,v 1.1 2002/02/16 14:34:54 art Exp $ + +PROG=shmtest + +.include <bsd.regress.mk> diff --git a/regress/sys/kern/sysvshm/shmtest.c b/regress/sys/kern/sysvshm/shmtest.c new file mode 100644 index 00000000000..7b633b9fe2e --- /dev/null +++ b/regress/sys/kern/sysvshm/shmtest.c @@ -0,0 +1,311 @@ +/* $NetBSD: shmtest.c,v 1.2 2001/02/19 22:44:41 cgd Exp $ */ + +/*- + * Copyright (c) 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Test the SVID-compatible Shared Memory facility. + */ + +#include <sys/param.h> +#include <sys/ipc.h> +#include <sys/shm.h> +#include <sys/wait.h> + +#include <err.h> +#include <errno.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +int main __P((int, char *[])); +void print_shmid_ds __P((struct shmid_ds *, mode_t)); +void sigsys_handler __P((int)); +void sigchld_handler __P((int)); +void cleanup __P((void)); +void receiver __P((void)); + +const char *m_str = "The quick brown fox jumped over the lazy dog."; + +int sender_shmid = -1; +pid_t child_pid; + +key_t shmkey; + +char keyname[] = "/tmp/msgtestXXXXXXXX"; + +int verbose; + +size_t pgsize; + +int +main(argc, argv) + int argc; + char *argv[]; +{ + struct sigaction sa; + struct shmid_ds s_ds; + sigset_t sigmask; + char *shm_buf; + int fd, ch; + + if ((fd = mkstemp(keyname)) < 0) + err(1, "mkstemp"); + + close(fd); + + while ((ch = getopt(argc, argv, "v")) != -1) { + switch (ch) { + case 'v': + verbose = 1; + break; + default: + fprintf(stderr, "Usage: shmtest [-v]\n"); + exit(1); + } + } + + /* + * Install a SIGSYS handler so that we can exit gracefully if + * System V Shared Memory support isn't in the kernel. + */ + sa.sa_handler = sigsys_handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + if (sigaction(SIGSYS, &sa, NULL) == -1) + err(1, "sigaction SIGSYS"); + + /* + * Install and SIGCHLD handler to deal with all possible exit + * conditions of the receiver. + */ + sa.sa_handler = sigchld_handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + if (sigaction(SIGCHLD, &sa, NULL) == -1) + err(1, "sigaction SIGCHLD"); + + pgsize = sysconf(_SC_PAGESIZE); + + shmkey = ftok(argv[1], 4160); + + /* + * Initialize child_pid to ourselves to that the cleanup function + * works before we create the receiver. + */ + child_pid = getpid(); + + /* + * Make sure that when the sender exits, the message queue is + * removed. + */ + if (atexit(cleanup) == -1) + err(1, "atexit"); + + if ((sender_shmid = shmget(shmkey, pgsize, IPC_CREAT | 0640)) == -1) + err(1, "shmget"); + + if (shmctl(sender_shmid, IPC_STAT, &s_ds) == -1) + err(1, "shmctl IPC_STAT"); + + if (verbose) + print_shmid_ds(&s_ds, 0640); + + s_ds.shm_perm.mode = (s_ds.shm_perm.mode & ~0777) | 0600; + + if (shmctl(sender_shmid, IPC_SET, &s_ds) == -1) + err(1, "shmctl IPC_SET"); + + memset(&s_ds, 0, sizeof(s_ds)); + + if (shmctl(sender_shmid, IPC_STAT, &s_ds) == -1) + err(1, "shmctl IPC_STAT"); + + if ((s_ds.shm_perm.mode & 0777) != 0600) + err(1, "IPC_SET of mode didn't hold"); + + if (verbose) + print_shmid_ds(&s_ds, 0600); + + if ((shm_buf = shmat(sender_shmid, NULL, 0)) == (void *) -1) + err(1, "sender: shmat"); + + /* + * Write the test pattern into the shared memory buffer. + */ + strcpy(shm_buf, m_str); + + switch ((child_pid = fork())) { + case -1: + err(1, "fork"); + /* NOTREACHED */ + + case 0: + receiver(); + break; + + default: + break; + } + + /* + * Suspend forever; when we get SIGCHLD, the handler will exit. + */ + sigemptyset(&sigmask); + (void) sigsuspend(&sigmask); + + /* + * ...and any other signal is an unexpected error. + */ + errx(1, "sender: received unexpected signal"); +} + +void +sigsys_handler(signo) + int signo; +{ + + errx(1, "System V Shared Memory support is not present in the kernel"); +} + +void +sigchld_handler(signo) + int signo; +{ + struct shmid_ds s_ds; + int cstatus; + + /* + * Reap the child; if it exited successfully, then the test passed! + */ + if (waitpid(child_pid, &cstatus, 0) != child_pid) + err(1, "waitpid"); + + if (WIFEXITED(cstatus) == 0) + errx(1, "receiver exited abnormally"); + + if (WEXITSTATUS(cstatus) != 0) + errx(1, "receiver exited with status %d\n", + WEXITSTATUS(cstatus)); + + /* + * If we get here, the child has exited normally, and thus + * we should exit normally too. First, tho, we print out + * the final stats for the message queue. + */ + + if (shmctl(sender_shmid, IPC_STAT, &s_ds) == -1) + err(1, "shmctl IPC_STAT"); + + if (verbose) + print_shmid_ds(&s_ds, 0600); + + exit(0); +} + +void +cleanup() +{ + + /* + * If we're the sender, and it exists, remove the shared memory area. + */ + if (child_pid != 0 && sender_shmid != -1) { + if (shmctl(sender_shmid, IPC_RMID, NULL) == -1) + warn("shmctl IPC_RMID"); + } + + remove(keyname); +} + +void +print_shmid_ds(sp, mode) + struct shmid_ds *sp; + mode_t mode; +{ + uid_t uid = geteuid(); + gid_t gid = getegid(); + + printf("PERM: uid %d, gid %d, cuid %d, cgid %d, mode 0%o\n", + sp->shm_perm.uid, sp->shm_perm.gid, + sp->shm_perm.cuid, sp->shm_perm.cgid, + sp->shm_perm.mode & 0777); + + printf("segsz %lu, lpid %d, cpid %d, nattch %u\n", + (u_long)sp->shm_segsz, sp->shm_lpid, sp->shm_cpid, + sp->shm_nattch); + + printf("atime: %s", ctime(&sp->shm_atime)); + printf("dtime: %s", ctime(&sp->shm_dtime)); + printf("ctime: %s", ctime(&sp->shm_ctime)); + + /* + * Sanity check a few things. + */ + + if (sp->shm_perm.uid != uid || sp->shm_perm.cuid != uid) + errx(1, "uid mismatch"); + + if (sp->shm_perm.gid != gid || sp->shm_perm.cgid != gid) + errx(1, "gid mismatch"); + + if ((sp->shm_perm.mode & 0777) != mode) + errx(1, "mode mismatch"); +} + +void +receiver() +{ + int shmid; + void *shm_buf; + + if ((shmid = shmget(shmkey, pgsize, 0)) == -1) + err(1, "receiver: shmget"); + + if ((shm_buf = shmat(shmid, NULL, 0)) == (void *) -1) + err(1, "receiver: shmat"); + + if (verbose) + printf("%s\n", (const char *)shm_buf); + if (strcmp((const char *)shm_buf, m_str) != 0) + err(1, "receiver: data isn't correct"); + + exit(0); +} |