1/* 2 * Test the POSIX shared-memory API. 3 * Dedicated to the public domain by Garrett A. Wollman, 2000. 4 * $FreeBSD: releng/10.2/tools/test/posixshm/shm_test.c 254604 2013-08-21 17:47:11Z kib $ 5 */ 6 7#include <sys/types.h> 8#include <sys/mman.h> 9#include <sys/wait.h> 10 11#include <err.h> 12#include <errno.h> 13#include <fcntl.h> 14#include <signal.h> 15#include <stdio.h> 16#include <stdlib.h> 17#include <string.h> 18#include <unistd.h> 19 20/* 21 * Signal handler which does nothing. 22 */ 23static void 24ignoreit(int sig __unused) 25{ 26 ; 27} 28 29int 30main(int argc, char **argv) 31{ 32 char buf[1024], *cp, c; 33 int error, desc, rv; 34 long scval; 35 sigset_t ss; 36 struct sigaction sa; 37 void *region; 38 size_t i, psize; 39 40#ifndef _POSIX_SHARED_MEMORY_OBJECTS 41 printf("_POSIX_SHARED_MEMORY_OBJECTS is undefined\n"); 42#else 43 printf("_POSIX_SHARED_MEMORY_OBJECTS is defined as %ld\n", 44 (long)_POSIX_SHARED_MEMORY_OBJECTS - 0); 45 if (_POSIX_SHARED_MEMORY_OBJECTS - 0 == -1) 46 printf("***Indicates this feature may be unsupported!\n"); 47#endif 48 errno = 0; 49 scval = sysconf(_SC_SHARED_MEMORY_OBJECTS); 50 if (scval == -1 && errno != 0) { 51 err(1, "sysconf(_SC_SHARED_MEMORY_OBJECTS)"); 52 } else { 53 printf("sysconf(_SC_SHARED_MEMORY_OBJECTS) returns %ld\n", 54 scval); 55 if (scval == -1) 56 printf("***Indicates this feature is unsupported!\n"); 57 } 58 59 errno = 0; 60 scval = sysconf(_SC_PAGESIZE); 61 if (scval == -1 && errno != 0) { 62 err(1, "sysconf(_SC_PAGESIZE)"); 63 } else if (scval <= 0 || (size_t)psize != psize) { 64 warnx("bogus return from sysconf(_SC_PAGESIZE): %ld", 65 scval); 66 psize = 4096; 67 } else { 68 printf("sysconf(_SC_PAGESIZE) returns %ld\n", scval); 69 psize = scval; 70 } 71 72 argc--, argv++; 73 74 if (*argv) { 75 strncat(buf, *argv, (sizeof buf) - 1); 76 desc = shm_open(buf, O_EXCL | O_CREAT | O_RDWR, 0600); 77 } else { 78 do { 79 /* 80 * Can't use mkstemp for obvious reasons... 81 */ 82 strcpy(buf, "/tmp/shmtest.XXXXXXXXXXXX"); 83 mktemp(buf); 84 desc = shm_open(buf, O_EXCL | O_CREAT | O_RDWR, 0600); 85 } while (desc < 0 && errno == EEXIST); 86 } 87 88 if (desc < 0) 89 err(1, "shm_open"); 90 91 if (shm_unlink(buf) < 0) 92 err(1, "shm_unlink"); 93 94 if (ftruncate(desc, (off_t)psize) < 0) 95 err(1, "ftruncate"); 96 97 region = mmap((void *)0, psize, PROT_READ | PROT_WRITE, MAP_SHARED, 98 desc, (off_t)0); 99 if (region == MAP_FAILED) 100 err(1, "mmap"); 101 memset(region, '\377', psize); 102 103 sa.sa_flags = 0; 104 sa.sa_handler = ignoreit; 105 sigemptyset(&sa.sa_mask); 106 if (sigaction(SIGUSR1, &sa, (struct sigaction *)0) < 0) 107 err(1, "sigaction"); 108 109 sigemptyset(&ss); 110 sigaddset(&ss, SIGUSR1); 111 if (sigprocmask(SIG_BLOCK, &ss, (sigset_t *)0) < 0) 112 err(1, "sigprocmask"); 113 114 rv = fork(); 115 if (rv < 0) { 116 err(1, "fork"); 117 } else if (rv == 0) { 118 sigemptyset(&ss); 119 sigsuspend(&ss); 120 121 for (cp = region; cp < (char *)region + psize; cp++) { 122 if (*cp != '\151') 123 _exit(1); 124 } 125 if (lseek(desc, 0, SEEK_SET) == -1) 126 _exit(1); 127 for (i = 0; i < psize; i++) { 128 error = read(desc, &c, 1); 129 if (c != '\151') 130 _exit(1); 131 } 132 _exit(0); 133 } else { 134 int status; 135 136 memset(region, '\151', psize - 2); 137 error = pwrite(desc, region, 2, psize - 2); 138 if (error != 2) { 139 if (error >= 0) 140 errx(1, "short write %d", error); 141 else 142 err(1, "shmfd write"); 143 } 144 kill(rv, SIGUSR1); 145 waitpid(rv, &status, 0); 146 147 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { 148 printf("Functionality test successful\n"); 149 exit(0); 150 } else if (WIFEXITED(status)) { 151 printf("Child process exited with status %d\n", 152 WEXITSTATUS(status)); 153 } else { 154 printf("Child process terminated with %s\n", 155 strsignal(WTERMSIG(status))); 156 } 157 } 158 exit(1); 159} 160