1*e30a6200SEnji Cooper /* 2*e30a6200SEnji Cooper Copyright (C) 2004 Michael J. Silbersack. All rights reserved. 3*e30a6200SEnji Cooper 4*e30a6200SEnji Cooper Redistribution and use in source and binary forms, with or without 5*e30a6200SEnji Cooper modification, are permitted provided that the following conditions 6*e30a6200SEnji Cooper are met: 7*e30a6200SEnji Cooper 1. Redistributions of source code must retain the above copyright 8*e30a6200SEnji Cooper notice, this list of conditions and the following disclaimer. 9*e30a6200SEnji Cooper 2. Redistributions in binary form must reproduce the above copyright 10*e30a6200SEnji Cooper notice, this list of conditions and the following disclaimer in the 11*e30a6200SEnji Cooper documentation and/or other materials provided with the distribution. 12*e30a6200SEnji Cooper 13*e30a6200SEnji Cooper THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14*e30a6200SEnji Cooper ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15*e30a6200SEnji Cooper IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16*e30a6200SEnji Cooper ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 17*e30a6200SEnji Cooper FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18*e30a6200SEnji Cooper DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19*e30a6200SEnji Cooper OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20*e30a6200SEnji Cooper HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21*e30a6200SEnji Cooper LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22*e30a6200SEnji Cooper OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23*e30a6200SEnji Cooper SUCH DAMAGE. 24*e30a6200SEnji Cooper */ 25*e30a6200SEnji Cooper 26*e30a6200SEnji Cooper #include <sys/types.h> 27*e30a6200SEnji Cooper #include <sys/stat.h> 28*e30a6200SEnji Cooper #include <sys/wait.h> 29*e30a6200SEnji Cooper #include <assert.h> 30*e30a6200SEnji Cooper #include <err.h> 31*e30a6200SEnji Cooper #include <errno.h> 32*e30a6200SEnji Cooper #include <stdio.h> 33*e30a6200SEnji Cooper #include <stdlib.h> 34*e30a6200SEnji Cooper #include <string.h> 35*e30a6200SEnji Cooper #include <unistd.h> 36*e30a6200SEnji Cooper 37*e30a6200SEnji Cooper /* 38*e30a6200SEnji Cooper * $FreeBSD$ 39*e30a6200SEnji Cooper * This program simply tests writing through the reverse direction of 40*e30a6200SEnji Cooper * a pipe. Nothing too fancy, it's only needed because most pipe-using 41*e30a6200SEnji Cooper * programs never touch the reverse direction (it doesn't exist on 42*e30a6200SEnji Cooper * Linux.) 43*e30a6200SEnji Cooper */ 44*e30a6200SEnji Cooper 45*e30a6200SEnji Cooper int 46*e30a6200SEnji Cooper main(void) 47*e30a6200SEnji Cooper { 48*e30a6200SEnji Cooper char buffer[65535], buffer2[65535], go[] = "go", go2[] = "go2"; 49*e30a6200SEnji Cooper int desc[2], ipc_coord[2]; 50*e30a6200SEnji Cooper size_t i; 51*e30a6200SEnji Cooper ssize_t total; 52*e30a6200SEnji Cooper int buggy, error; 53*e30a6200SEnji Cooper pid_t new_pid; 54*e30a6200SEnji Cooper 55*e30a6200SEnji Cooper buggy = 0; 56*e30a6200SEnji Cooper total = 0; 57*e30a6200SEnji Cooper 58*e30a6200SEnji Cooper error = pipe(desc); 59*e30a6200SEnji Cooper if (error == -1) 60*e30a6200SEnji Cooper err(1, "Couldn't allocate data pipe"); 61*e30a6200SEnji Cooper 62*e30a6200SEnji Cooper error = pipe(ipc_coord); 63*e30a6200SEnji Cooper if (error == -1) 64*e30a6200SEnji Cooper err(1, "Couldn't allocate IPC coordination pipe"); 65*e30a6200SEnji Cooper 66*e30a6200SEnji Cooper buffer[0] = 'A'; 67*e30a6200SEnji Cooper 68*e30a6200SEnji Cooper for (i = 1; i < (int)sizeof(buffer); i++) { 69*e30a6200SEnji Cooper buffer[i] = buffer[i - 1] + 1; 70*e30a6200SEnji Cooper if (buffer[i] > 'Z') 71*e30a6200SEnji Cooper buffer[i] = 'A'; 72*e30a6200SEnji Cooper } 73*e30a6200SEnji Cooper 74*e30a6200SEnji Cooper new_pid = fork(); 75*e30a6200SEnji Cooper assert(new_pid != -1); 76*e30a6200SEnji Cooper 77*e30a6200SEnji Cooper #define SYNC_R(i, _buf) do { \ 78*e30a6200SEnji Cooper int _error = errno; \ 79*e30a6200SEnji Cooper warnx("%d: waiting for synchronization", __LINE__); \ 80*e30a6200SEnji Cooper if (read(ipc_coord[i], &_buf, sizeof(_buf)) != sizeof(_buf)) \ 81*e30a6200SEnji Cooper err(1, "failed to synchronize (%s)", (i == 0 ? "parent" : "child")); \ 82*e30a6200SEnji Cooper errno = _error; \ 83*e30a6200SEnji Cooper } while(0) 84*e30a6200SEnji Cooper 85*e30a6200SEnji Cooper #define SYNC_W(i, _buf) do { \ 86*e30a6200SEnji Cooper int _error = errno; \ 87*e30a6200SEnji Cooper warnx("%d: sending synchronization", __LINE__); \ 88*e30a6200SEnji Cooper if (write(ipc_coord[i], &_buf, sizeof(_buf)) != sizeof(_buf)) \ 89*e30a6200SEnji Cooper err(1, "failed to synchronize (%s)", (i == 0 ? "child" : "parent")); \ 90*e30a6200SEnji Cooper errno = _error; \ 91*e30a6200SEnji Cooper } while(0) 92*e30a6200SEnji Cooper 93*e30a6200SEnji Cooper #define WRITE(s) do { \ 94*e30a6200SEnji Cooper ssize_t _size; \ 95*e30a6200SEnji Cooper if ((_size = write(desc[1], &buffer[total], s)) != s) \ 96*e30a6200SEnji Cooper warn("short write; wrote %zd, expected %d", _size, s); \ 97*e30a6200SEnji Cooper total += _size; \ 98*e30a6200SEnji Cooper } while(0) 99*e30a6200SEnji Cooper 100*e30a6200SEnji Cooper if (new_pid == 0) { 101*e30a6200SEnji Cooper SYNC_R(0, go); 102*e30a6200SEnji Cooper for (i = 0; i < 8; i++) 103*e30a6200SEnji Cooper WRITE(4096); 104*e30a6200SEnji Cooper 105*e30a6200SEnji Cooper SYNC_W(0, go2); 106*e30a6200SEnji Cooper SYNC_R(0, go); 107*e30a6200SEnji Cooper 108*e30a6200SEnji Cooper for (i = 0; i < 2; i++) 109*e30a6200SEnji Cooper WRITE(4096); 110*e30a6200SEnji Cooper 111*e30a6200SEnji Cooper SYNC_W(0, go2); 112*e30a6200SEnji Cooper 113*e30a6200SEnji Cooper _exit(0); 114*e30a6200SEnji Cooper } 115*e30a6200SEnji Cooper 116*e30a6200SEnji Cooper SYNC_W(1, go); 117*e30a6200SEnji Cooper SYNC_R(1, go2); 118*e30a6200SEnji Cooper 119*e30a6200SEnji Cooper error = read(desc[0], &buffer2, 8 * 4096); 120*e30a6200SEnji Cooper total += error; 121*e30a6200SEnji Cooper printf("Read %d bytes\n", error); 122*e30a6200SEnji Cooper 123*e30a6200SEnji Cooper SYNC_W(1, go); 124*e30a6200SEnji Cooper SYNC_R(1, go2); 125*e30a6200SEnji Cooper 126*e30a6200SEnji Cooper error = read(desc[0], &buffer2[total], 2 * 4096); 127*e30a6200SEnji Cooper total += error; 128*e30a6200SEnji Cooper printf("Read %d bytes, done\n", error); 129*e30a6200SEnji Cooper 130*e30a6200SEnji Cooper if (memcmp(buffer, buffer2, total) != 0) { 131*e30a6200SEnji Cooper for (i = 0; i < (size_t)total; i++) { 132*e30a6200SEnji Cooper if (buffer[i] != buffer2[i]) { 133*e30a6200SEnji Cooper buggy = 1; 134*e30a6200SEnji Cooper printf("Location %zu input: %hhx " 135*e30a6200SEnji Cooper "output: %hhx\n", 136*e30a6200SEnji Cooper i, buffer[i], buffer2[i]); 137*e30a6200SEnji Cooper } 138*e30a6200SEnji Cooper } 139*e30a6200SEnji Cooper } 140*e30a6200SEnji Cooper 141*e30a6200SEnji Cooper waitpid(new_pid, NULL, 0); 142*e30a6200SEnji Cooper 143*e30a6200SEnji Cooper if ((buggy == 1) || (total != 10 * 4096)) 144*e30a6200SEnji Cooper errx(1, "FAILED"); 145*e30a6200SEnji Cooper else 146*e30a6200SEnji Cooper printf("SUCCESS\n"); 147*e30a6200SEnji Cooper 148*e30a6200SEnji Cooper exit(0); 149*e30a6200SEnji Cooper } 150