1132524Ssilby/* 2132524SsilbyCopyright (C) 2004 Michael J. Silbersack. All rights reserved. 3132524Ssilby 4132524SsilbyRedistribution and use in source and binary forms, with or without 5132524Ssilbymodification, are permitted provided that the following conditions 6132524Ssilbyare met: 7132524Ssilby1. Redistributions of source code must retain the above copyright 8132524Ssilby notice, this list of conditions and the following disclaimer. 9132524Ssilby2. Redistributions in binary form must reproduce the above copyright 10132524Ssilby notice, this list of conditions and the following disclaimer in the 11132524Ssilby documentation and/or other materials provided with the distribution. 12132524Ssilby 13132524SsilbyTHIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14132524SsilbyANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15132524SsilbyIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16132524SsilbyARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 17132524SsilbyFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18132524SsilbyDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19132524SsilbyOR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20132524SsilbyHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21132524SsilbyLIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22132524SsilbyOUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23132524SsilbySUCH DAMAGE. 24132524Ssilby*/ 25132524Ssilby 26290914Sngie#include <sys/types.h> 27290914Sngie#include <sys/stat.h> 28290914Sngie#include <sys/wait.h> 29290914Sngie#include <assert.h> 30290914Sngie#include <err.h> 31290914Sngie#include <errno.h> 32132524Ssilby#include <stdio.h> 33290914Sngie#include <stdlib.h> 34290914Sngie#include <string.h> 35132524Ssilby#include <unistd.h> 36132524Ssilby 37132524Ssilby/* 38132524Ssilby * $FreeBSD$ 39132524Ssilby * This program simply tests writing through the reverse direction of 40132524Ssilby * a pipe. Nothing too fancy, it's only needed because most pipe-using 41132524Ssilby * programs never touch the reverse direction (it doesn't exist on 42132524Ssilby * Linux.) 43132524Ssilby */ 44132524Ssilby 45290914Sngieint 46290914Sngiemain(void) 47132524Ssilby{ 48290914Sngie char buffer[65535], buffer2[65535], go[] = "go", go2[] = "go2"; 49290914Sngie int desc[2], ipc_coord[2]; 50290914Sngie size_t i; 51290914Sngie ssize_t total; 52290914Sngie int buggy, error; 53290914Sngie pid_t new_pid; 54132524Ssilby 55290914Sngie buggy = 0; 56290914Sngie total = 0; 57132524Ssilby 58290914Sngie error = pipe(desc); 59290914Sngie if (error == -1) 60290914Sngie err(1, "Couldn't allocate data pipe"); 61132524Ssilby 62290914Sngie error = pipe(ipc_coord); 63290914Sngie if (error == -1) 64290914Sngie err(1, "Couldn't allocate IPC coordination pipe"); 65132524Ssilby 66290914Sngie buffer[0] = 'A'; 67132524Ssilby 68290914Sngie for (i = 1; i < (int)sizeof(buffer); i++) { 69290914Sngie buffer[i] = buffer[i - 1] + 1; 70290914Sngie if (buffer[i] > 'Z') 71290914Sngie buffer[i] = 'A'; 72132524Ssilby } 73132524Ssilby 74290914Sngie new_pid = fork(); 75290914Sngie assert(new_pid != -1); 76132524Ssilby 77290914Sngie#define SYNC_R(i, _buf) do { \ 78290914Sngie int _error = errno; \ 79290914Sngie warnx("%d: waiting for synchronization", __LINE__); \ 80290914Sngie if (read(ipc_coord[i], &_buf, sizeof(_buf)) != sizeof(_buf)) \ 81290914Sngie err(1, "failed to synchronize (%s)", (i == 0 ? "parent" : "child")); \ 82290914Sngie errno = _error; \ 83290914Sngie } while(0) 84290914Sngie 85290914Sngie#define SYNC_W(i, _buf) do { \ 86290914Sngie int _error = errno; \ 87290914Sngie warnx("%d: sending synchronization", __LINE__); \ 88290914Sngie if (write(ipc_coord[i], &_buf, sizeof(_buf)) != sizeof(_buf)) \ 89290914Sngie err(1, "failed to synchronize (%s)", (i == 0 ? "child" : "parent")); \ 90290914Sngie errno = _error; \ 91290914Sngie } while(0) 92290914Sngie 93290914Sngie#define WRITE(s) do { \ 94290914Sngie ssize_t _size; \ 95290914Sngie if ((_size = write(desc[1], &buffer[total], s)) != s) \ 96290914Sngie warn("short write; wrote %zd, expected %d", _size, s); \ 97290914Sngie total += _size; \ 98290914Sngie } while(0) 99290914Sngie 100290914Sngie if (new_pid == 0) { 101290914Sngie SYNC_R(0, go); 102290914Sngie for (i = 0; i < 8; i++) 103290914Sngie WRITE(4096); 104290914Sngie 105290914Sngie SYNC_W(0, go2); 106290914Sngie SYNC_R(0, go); 107290914Sngie 108290914Sngie for (i = 0; i < 2; i++) 109290914Sngie WRITE(4096); 110290914Sngie 111290914Sngie SYNC_W(0, go2); 112290914Sngie 113290914Sngie _exit(0); 114290914Sngie } 115290914Sngie 116290914Sngie SYNC_W(1, go); 117290914Sngie SYNC_R(1, go2); 118290914Sngie 119290914Sngie error = read(desc[0], &buffer2, 8 * 4096); 120132524Ssilby total += error; 121290914Sngie printf("Read %d bytes\n", error); 122290914Sngie 123290914Sngie SYNC_W(1, go); 124290914Sngie SYNC_R(1, go2); 125290914Sngie 126290914Sngie error = read(desc[0], &buffer2[total], 2 * 4096); 127132524Ssilby total += error; 128132524Ssilby printf("Read %d bytes, done\n", error); 129132524Ssilby 130290914Sngie if (memcmp(buffer, buffer2, total) != 0) { 131290914Sngie for (i = 0; i < (size_t)total; i++) { 132290914Sngie if (buffer[i] != buffer2[i]) { 133290914Sngie buggy = 1; 134290914Sngie printf("Location %zu input: %hhx " 135290914Sngie "output: %hhx\n", 136290914Sngie i, buffer[i], buffer2[i]); 137290914Sngie } 138132524Ssilby } 139132524Ssilby } 140132524Ssilby 141290914Sngie waitpid(new_pid, NULL, 0); 142132524Ssilby 143290914Sngie if ((buggy == 1) || (total != 10 * 4096)) 144290914Sngie errx(1, "FAILED"); 145290914Sngie else 146290914Sngie printf("SUCCESS\n"); 147132524Ssilby 148290914Sngie exit(0); 149132524Ssilby} 150