159498Swollman/* 259498Swollman * Test the POSIX shared-memory API. 3228975Suqs * Dedicated to the public domain by Garrett A. Wollman, 2000. 459498Swollman * $FreeBSD$ 559498Swollman */ 659498Swollman 759498Swollman#include <sys/types.h> 859498Swollman#include <sys/mman.h> 959498Swollman#include <sys/wait.h> 1059498Swollman 1159498Swollman#include <err.h> 1259498Swollman#include <errno.h> 1359498Swollman#include <fcntl.h> 1459498Swollman#include <signal.h> 1559498Swollman#include <stdio.h> 1659498Swollman#include <stdlib.h> 1759498Swollman#include <string.h> 1859498Swollman#include <unistd.h> 1959498Swollman 2059498Swollman/* 2159498Swollman * Signal handler which does nothing. 2259498Swollman */ 2359498Swollmanstatic void 24254604Skibignoreit(int sig __unused) 2559498Swollman{ 2659498Swollman ; 2759498Swollman} 2859498Swollman 2959498Swollmanint 3059498Swollmanmain(int argc, char **argv) 3159498Swollman{ 32254604Skib char buf[1024], *cp, c; 33254604Skib int error, desc, rv; 3459498Swollman long scval; 3559498Swollman sigset_t ss; 3659498Swollman struct sigaction sa; 3759498Swollman void *region; 38254604Skib size_t i, psize; 3959498Swollman 4059498Swollman#ifndef _POSIX_SHARED_MEMORY_OBJECTS 4159498Swollman printf("_POSIX_SHARED_MEMORY_OBJECTS is undefined\n"); 4259498Swollman#else 4359498Swollman printf("_POSIX_SHARED_MEMORY_OBJECTS is defined as %ld\n", 4459498Swollman (long)_POSIX_SHARED_MEMORY_OBJECTS - 0); 4559498Swollman if (_POSIX_SHARED_MEMORY_OBJECTS - 0 == -1) 4659498Swollman printf("***Indicates this feature may be unsupported!\n"); 4759498Swollman#endif 4859498Swollman errno = 0; 4959498Swollman scval = sysconf(_SC_SHARED_MEMORY_OBJECTS); 5059498Swollman if (scval == -1 && errno != 0) { 5159498Swollman err(1, "sysconf(_SC_SHARED_MEMORY_OBJECTS)"); 5259498Swollman } else { 5359498Swollman printf("sysconf(_SC_SHARED_MEMORY_OBJECTS) returns %ld\n", 5459498Swollman scval); 5559498Swollman if (scval == -1) 5659498Swollman printf("***Indicates this feature is unsupported!\n"); 5759498Swollman } 5859498Swollman 5959498Swollman errno = 0; 6059498Swollman scval = sysconf(_SC_PAGESIZE); 6159498Swollman if (scval == -1 && errno != 0) { 6259498Swollman err(1, "sysconf(_SC_PAGESIZE)"); 6359498Swollman } else if (scval <= 0 || (size_t)psize != psize) { 6459498Swollman warnx("bogus return from sysconf(_SC_PAGESIZE): %ld", 6559498Swollman scval); 6659498Swollman psize = 4096; 6759498Swollman } else { 6859498Swollman printf("sysconf(_SC_PAGESIZE) returns %ld\n", scval); 6959498Swollman psize = scval; 7059498Swollman } 7159498Swollman 7259498Swollman argc--, argv++; 7359498Swollman 7459498Swollman if (*argv) { 7559498Swollman strncat(buf, *argv, (sizeof buf) - 1); 7659498Swollman desc = shm_open(buf, O_EXCL | O_CREAT | O_RDWR, 0600); 7759498Swollman } else { 7859498Swollman do { 7959498Swollman /* 8059498Swollman * Can't use mkstemp for obvious reasons... 8159498Swollman */ 8259498Swollman strcpy(buf, "/tmp/shmtest.XXXXXXXXXXXX"); 8359498Swollman mktemp(buf); 8459498Swollman desc = shm_open(buf, O_EXCL | O_CREAT | O_RDWR, 0600); 8559498Swollman } while (desc < 0 && errno == EEXIST); 8659498Swollman } 8759498Swollman 8859498Swollman if (desc < 0) 8959498Swollman err(1, "shm_open"); 9059498Swollman 9159498Swollman if (shm_unlink(buf) < 0) 9259498Swollman err(1, "shm_unlink"); 9359498Swollman 9459498Swollman if (ftruncate(desc, (off_t)psize) < 0) 9559498Swollman err(1, "ftruncate"); 9659498Swollman 9759498Swollman region = mmap((void *)0, psize, PROT_READ | PROT_WRITE, MAP_SHARED, 9859498Swollman desc, (off_t)0); 9959498Swollman if (region == MAP_FAILED) 10059498Swollman err(1, "mmap"); 10159498Swollman memset(region, '\377', psize); 10259498Swollman 10359498Swollman sa.sa_flags = 0; 10459498Swollman sa.sa_handler = ignoreit; 10559498Swollman sigemptyset(&sa.sa_mask); 10659498Swollman if (sigaction(SIGUSR1, &sa, (struct sigaction *)0) < 0) 10759498Swollman err(1, "sigaction"); 10859498Swollman 10959498Swollman sigemptyset(&ss); 11059498Swollman sigaddset(&ss, SIGUSR1); 11159498Swollman if (sigprocmask(SIG_BLOCK, &ss, (sigset_t *)0) < 0) 11259498Swollman err(1, "sigprocmask"); 11359498Swollman 11459498Swollman rv = fork(); 11559498Swollman if (rv < 0) { 11659498Swollman err(1, "fork"); 11759498Swollman } else if (rv == 0) { 11859498Swollman sigemptyset(&ss); 11959498Swollman sigsuspend(&ss); 12059498Swollman 121254604Skib for (cp = region; cp < (char *)region + psize; cp++) { 12259498Swollman if (*cp != '\151') 12359498Swollman _exit(1); 124254604Skib } 125254604Skib if (lseek(desc, 0, SEEK_SET) == -1) 126254604Skib _exit(1); 127254604Skib for (i = 0; i < psize; i++) { 128254604Skib error = read(desc, &c, 1); 129254604Skib if (c != '\151') 130254604Skib _exit(1); 131254604Skib } 13259498Swollman _exit(0); 13359498Swollman } else { 13459498Swollman int status; 13559498Swollman 136254604Skib memset(region, '\151', psize - 2); 137254604Skib error = pwrite(desc, region, 2, psize - 2); 138254604Skib if (error != 2) { 139254604Skib if (error >= 0) 140254604Skib errx(1, "short write %d", error); 141254604Skib else 142254604Skib err(1, "shmfd write"); 143254604Skib } 14459498Swollman kill(rv, SIGUSR1); 14559498Swollman waitpid(rv, &status, 0); 14659498Swollman 14759498Swollman if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { 14859498Swollman printf("Functionality test successful\n"); 14959498Swollman exit(0); 15059498Swollman } else if (WIFEXITED(status)) { 15159498Swollman printf("Child process exited with status %d\n", 15259498Swollman WEXITSTATUS(status)); 15359498Swollman } else { 15459498Swollman printf("Child process terminated with %s\n", 15559498Swollman strsignal(WTERMSIG(status))); 15659498Swollman } 15759498Swollman } 15859498Swollman exit(1); 15959498Swollman} 160