static void sigchld_handler(int signo __unused) { 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", 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"); print_shmid_ds(&s_ds, 0600); exit(0); }
int main(int argc, char *argv[]) { struct sigaction sa; struct shmid_ds s_ds; sigset_t sigmask; char *shm_buf; if (argc != 2) usage(); /* * 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"); 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"); 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"); }
ATF_TC_BODY(shm, tc) { struct sigaction sa; struct shmid_ds s_ds; sigset_t sigmask; char *shm_buf; int sender_shmid; int c_status; /* * Install a SIGSYS handler so that we can exit gracefully if * System V Shared Memory support isn't in the kernel. */ did_sigsys = 0; sa.sa_handler = sigsys_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; ATF_REQUIRE_MSG(sigaction(SIGSYS, &sa, NULL) != -1, "sigaction SIGSYS: %d", errno); /* * Install a SIGCHLD handler to deal with all possible exit * conditions of the sharer. */ did_sigchild = 0; child_count = 0; sa.sa_handler = sigchld_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; ATF_REQUIRE_MSG(sigaction(SIGCHLD, &sa, NULL) != -1, "sigaction SIGCHLD: %d", errno); pgsize = sysconf(_SC_PAGESIZE); shmkey = get_ftok(4160); ATF_REQUIRE_MSG(shmkey != (key_t)-1, "get_ftok failed"); ATF_REQUIRE_MSG((sender_shmid = shmget(shmkey, pgsize, IPC_CREAT | 0640)) != -1, "shmget: %d", errno); write_int("sender_shmid", sender_shmid); ATF_REQUIRE_MSG(shmctl(sender_shmid, IPC_STAT, &s_ds) != -1, "shmctl IPC_STAT: %d", errno); print_shmid_ds(&s_ds, 0640); s_ds.shm_perm.mode = (s_ds.shm_perm.mode & ~0777) | 0600; ATF_REQUIRE_MSG(shmctl(sender_shmid, IPC_SET, &s_ds) != -1, "shmctl IPC_SET: %d", errno); memset(&s_ds, 0, sizeof(s_ds)); ATF_REQUIRE_MSG(shmctl(sender_shmid, IPC_STAT, &s_ds) != -1, "shmctl IPC_STAT: %d", errno); ATF_REQUIRE_MSG((s_ds.shm_perm.mode & 0777) == 0600, "IPC_SET of mode didn't hold"); print_shmid_ds(&s_ds, 0600); shm_buf = shmat(sender_shmid, NULL, 0); ATF_REQUIRE_MSG(shm_buf != (void *) -1, "sender: shmat: %d", errno); /* * Write the test pattern into the shared memory buffer. */ strcpy(shm_buf, m2_str); switch ((child_pid = fork())) { case -1: atf_tc_fail("fork: %d", errno); return; case 0: sharer(); break; default: break; } /* * Wait for child to finish */ sigemptyset(&sigmask); (void) sigsuspend(&sigmask); if (did_sigchild) { c_status = child_status; if (c_status < 0) atf_tc_fail("waitpid: %d", -c_status); else if (WIFEXITED(c_status) == 0) atf_tc_fail("c abnormal exit: %d", c_status); else if (WEXITSTATUS(c_status) != 0) atf_tc_fail("c status: %d", WEXITSTATUS(c_status)); else { ATF_REQUIRE_MSG(shmctl(sender_shmid, IPC_STAT, &s_ds) != -1, "shmctl IPC_STAT: %d", errno); print_shmid_ds(&s_ds, 0600); atf_tc_pass(); } } else atf_tc_fail("sender: received unexpected signal"); }