1272343Sngie/* $NetBSD: h_forkcli.c,v 1.1 2011/01/05 17:19:09 pooka Exp $ */ 2272343Sngie 3272343Sngie#include <sys/types.h> 4272343Sngie#include <sys/wait.h> 5272343Sngie 6272343Sngie#include <err.h> 7272343Sngie#include <errno.h> 8272343Sngie#include <fcntl.h> 9272343Sngie#include <stdlib.h> 10272343Sngie#include <stdio.h> 11272343Sngie#include <string.h> 12272343Sngie#include <unistd.h> 13272343Sngie 14272343Sngie#include <rump/rump_syscalls.h> 15272343Sngie#include <rump/rumpclient.h> 16272343Sngie 17272343Sngiestatic void 18272343Sngiesimple(void) 19272343Sngie{ 20272343Sngie struct rumpclient_fork *rf; 21272343Sngie pid_t pid1, pid2; 22272343Sngie int fd, status; 23272343Sngie 24272343Sngie if ((pid1 = rump_sys_getpid()) < 2) 25272343Sngie errx(1, "unexpected pid %d", pid1); 26272343Sngie 27272343Sngie fd = rump_sys_open("/dev/null", O_CREAT | O_RDWR); 28272343Sngie if (rump_sys_write(fd, &fd, sizeof(fd)) != sizeof(fd)) 29272343Sngie errx(1, "write newlyopened /dev/null"); 30272343Sngie 31272343Sngie if ((rf = rumpclient_prefork()) == NULL) 32272343Sngie err(1, "prefork"); 33272343Sngie 34272343Sngie switch (fork()) { 35272343Sngie case -1: 36272343Sngie err(1, "fork"); 37272343Sngie break; 38272343Sngie case 0: 39272343Sngie if (rumpclient_fork_init(rf) == -1) 40272343Sngie err(1, "postfork init failed"); 41272343Sngie 42272343Sngie if ((pid2 = rump_sys_getpid()) < 2) 43272343Sngie errx(1, "unexpected pid %d", pid2); 44272343Sngie if (pid1 == pid2) 45272343Sngie errx(1, "child and parent pids are equal"); 46272343Sngie 47272343Sngie /* check that we can access the fd, the close it and exit */ 48272343Sngie if (rump_sys_write(fd, &fd, sizeof(fd)) != sizeof(fd)) 49272343Sngie errx(1, "write child /dev/null"); 50272343Sngie rump_sys_close(fd); 51272343Sngie break; 52272343Sngie default: 53272343Sngie /* 54272343Sngie * check that we can access the fd, wait for the child, and 55272343Sngie * check we can still access the fd 56272343Sngie */ 57272343Sngie if (rump_sys_write(fd, &fd, sizeof(fd)) != sizeof(fd)) 58272343Sngie errx(1, "write parent /dev/null"); 59272343Sngie if (wait(&status) == -1) 60272343Sngie err(1, "wait failed"); 61272343Sngie if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) 62272343Sngie errx(1, "child exited with status %d", status); 63272343Sngie if (rump_sys_write(fd, &fd, sizeof(fd)) != sizeof(fd)) 64272343Sngie errx(1, "write parent /dev/null"); 65272343Sngie break; 66272343Sngie } 67272343Sngie} 68272343Sngie 69272343Sngiestatic void 70272343Sngiecancel(void) 71272343Sngie{ 72272343Sngie 73272343Sngie /* XXX: not implemented in client / server !!! */ 74272343Sngie} 75272343Sngie 76272343Sngie#define TESTSTR "i am your fatherrrrrrr" 77272343Sngie#define TESTSLEN (sizeof(TESTSTR)-1) 78272343Sngiestatic void 79272343Sngiepipecomm(void) 80272343Sngie{ 81272343Sngie struct rumpclient_fork *rf; 82272343Sngie char buf[TESTSLEN+1]; 83272343Sngie int pipetti[2]; 84272343Sngie int status; 85272343Sngie 86272343Sngie if (rump_sys_pipe(pipetti) == -1) 87272343Sngie errx(1, "pipe"); 88272343Sngie 89272343Sngie if ((rf = rumpclient_prefork()) == NULL) 90272343Sngie err(1, "prefork"); 91272343Sngie 92272343Sngie switch (fork()) { 93272343Sngie case -1: 94272343Sngie err(1, "fork"); 95272343Sngie break; 96272343Sngie case 0: 97272343Sngie if (rumpclient_fork_init(rf) == -1) 98272343Sngie err(1, "postfork init failed"); 99272343Sngie 100272343Sngie memset(buf, 0, sizeof(buf)); 101272343Sngie if (rump_sys_read(pipetti[0], buf, TESTSLEN) != TESTSLEN) 102272343Sngie err(1, "pipe read"); 103272343Sngie if (strcmp(TESTSTR, buf) != 0) 104272343Sngie errx(1, "teststring doesn't match, got %s", buf); 105272343Sngie break; 106272343Sngie default: 107272343Sngie if (rump_sys_write(pipetti[1], TESTSTR, TESTSLEN) != TESTSLEN) 108272343Sngie err(1, "pipe write"); 109272343Sngie if (wait(&status) == -1) 110272343Sngie err(1, "wait failed"); 111272343Sngie if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) 112272343Sngie errx(1, "child exited with status %d", status); 113272343Sngie break; 114272343Sngie } 115272343Sngie} 116272343Sngie 117272343Sngiestatic void 118272343Sngiefakeauth(void) 119272343Sngie{ 120272343Sngie struct rumpclient_fork *rf; 121272343Sngie uint32_t *auth; 122272343Sngie int rv; 123272343Sngie 124272343Sngie if ((rf = rumpclient_prefork()) == NULL) 125272343Sngie err(1, "prefork"); 126272343Sngie 127272343Sngie /* XXX: we know the internal structure of rf */ 128272343Sngie auth = (void *)rf; 129272343Sngie *(auth+3) = *(auth+3) ^ 0x1; 130272343Sngie 131272343Sngie rv = rumpclient_fork_init(rf); 132272343Sngie if (!(rv == -1 && errno == ESRCH)) 133272343Sngie exit(1); 134272343Sngie} 135272343Sngie 136272343Sngiestruct parsa { 137272343Sngie const char *arg; /* sp arg, el */ 138272343Sngie void (*spring)(void); /* spring into action */ 139272343Sngie} paragus[] = { 140272343Sngie { "simple", simple }, 141272343Sngie { "cancel", cancel }, 142272343Sngie { "pipecomm", pipecomm }, 143272343Sngie { "fakeauth", fakeauth }, 144272343Sngie}; 145272343Sngie 146272343Sngieint 147272343Sngiemain(int argc, char *argv[]) 148272343Sngie{ 149272343Sngie unsigned i; 150272343Sngie 151272343Sngie if (argc != 2) 152272343Sngie errx(1, "invalid usage"); 153272343Sngie 154272343Sngie if (rumpclient_init() == -1) 155272343Sngie err(1, "rumpclient init"); 156272343Sngie 157272343Sngie for (i = 0; i < __arraycount(paragus); i++) { 158272343Sngie if (strcmp(argv[1], paragus[i].arg) == 0) { 159272343Sngie paragus[i].spring(); 160272343Sngie break; 161272343Sngie } 162272343Sngie } 163272343Sngie if (i == __arraycount(paragus)) { 164272343Sngie printf("invalid test %s\n", argv[1]); 165272343Sngie exit(1); 166272343Sngie } 167272343Sngie 168272343Sngie exit(0); 169272343Sngie} 170