1 1.2 martin /* $NetBSD: h_forkcli.c,v 1.2 2019/07/16 17:29:18 martin Exp $ */ 2 1.1 pooka 3 1.1 pooka #include <sys/types.h> 4 1.1 pooka #include <sys/wait.h> 5 1.1 pooka 6 1.1 pooka #include <err.h> 7 1.1 pooka #include <errno.h> 8 1.1 pooka #include <fcntl.h> 9 1.1 pooka #include <stdlib.h> 10 1.1 pooka #include <stdio.h> 11 1.1 pooka #include <string.h> 12 1.1 pooka #include <unistd.h> 13 1.1 pooka 14 1.1 pooka #include <rump/rump_syscalls.h> 15 1.1 pooka #include <rump/rumpclient.h> 16 1.1 pooka 17 1.1 pooka static void 18 1.1 pooka simple(void) 19 1.1 pooka { 20 1.1 pooka struct rumpclient_fork *rf; 21 1.1 pooka pid_t pid1, pid2; 22 1.1 pooka int fd, status; 23 1.1 pooka 24 1.1 pooka if ((pid1 = rump_sys_getpid()) < 2) 25 1.1 pooka errx(1, "unexpected pid %d", pid1); 26 1.1 pooka 27 1.2 martin fd = rump_sys_open("/dev/null", O_CREAT | O_RDWR, 0600); 28 1.1 pooka if (rump_sys_write(fd, &fd, sizeof(fd)) != sizeof(fd)) 29 1.1 pooka errx(1, "write newlyopened /dev/null"); 30 1.1 pooka 31 1.1 pooka if ((rf = rumpclient_prefork()) == NULL) 32 1.1 pooka err(1, "prefork"); 33 1.1 pooka 34 1.1 pooka switch (fork()) { 35 1.1 pooka case -1: 36 1.1 pooka err(1, "fork"); 37 1.1 pooka break; 38 1.1 pooka case 0: 39 1.1 pooka if (rumpclient_fork_init(rf) == -1) 40 1.1 pooka err(1, "postfork init failed"); 41 1.1 pooka 42 1.1 pooka if ((pid2 = rump_sys_getpid()) < 2) 43 1.1 pooka errx(1, "unexpected pid %d", pid2); 44 1.1 pooka if (pid1 == pid2) 45 1.1 pooka errx(1, "child and parent pids are equal"); 46 1.1 pooka 47 1.1 pooka /* check that we can access the fd, the close it and exit */ 48 1.1 pooka if (rump_sys_write(fd, &fd, sizeof(fd)) != sizeof(fd)) 49 1.1 pooka errx(1, "write child /dev/null"); 50 1.1 pooka rump_sys_close(fd); 51 1.1 pooka break; 52 1.1 pooka default: 53 1.1 pooka /* 54 1.1 pooka * check that we can access the fd, wait for the child, and 55 1.1 pooka * check we can still access the fd 56 1.1 pooka */ 57 1.1 pooka if (rump_sys_write(fd, &fd, sizeof(fd)) != sizeof(fd)) 58 1.1 pooka errx(1, "write parent /dev/null"); 59 1.1 pooka if (wait(&status) == -1) 60 1.1 pooka err(1, "wait failed"); 61 1.1 pooka if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) 62 1.1 pooka errx(1, "child exited with status %d", status); 63 1.1 pooka if (rump_sys_write(fd, &fd, sizeof(fd)) != sizeof(fd)) 64 1.1 pooka errx(1, "write parent /dev/null"); 65 1.1 pooka break; 66 1.1 pooka } 67 1.1 pooka } 68 1.1 pooka 69 1.1 pooka static void 70 1.1 pooka cancel(void) 71 1.1 pooka { 72 1.1 pooka 73 1.1 pooka /* XXX: not implemented in client / server !!! */ 74 1.1 pooka } 75 1.1 pooka 76 1.1 pooka #define TESTSTR "i am your fatherrrrrrr" 77 1.1 pooka #define TESTSLEN (sizeof(TESTSTR)-1) 78 1.1 pooka static void 79 1.1 pooka pipecomm(void) 80 1.1 pooka { 81 1.1 pooka struct rumpclient_fork *rf; 82 1.1 pooka char buf[TESTSLEN+1]; 83 1.1 pooka int pipetti[2]; 84 1.1 pooka int status; 85 1.1 pooka 86 1.1 pooka if (rump_sys_pipe(pipetti) == -1) 87 1.1 pooka errx(1, "pipe"); 88 1.1 pooka 89 1.1 pooka if ((rf = rumpclient_prefork()) == NULL) 90 1.1 pooka err(1, "prefork"); 91 1.1 pooka 92 1.1 pooka switch (fork()) { 93 1.1 pooka case -1: 94 1.1 pooka err(1, "fork"); 95 1.1 pooka break; 96 1.1 pooka case 0: 97 1.1 pooka if (rumpclient_fork_init(rf) == -1) 98 1.1 pooka err(1, "postfork init failed"); 99 1.1 pooka 100 1.1 pooka memset(buf, 0, sizeof(buf)); 101 1.1 pooka if (rump_sys_read(pipetti[0], buf, TESTSLEN) != TESTSLEN) 102 1.1 pooka err(1, "pipe read"); 103 1.1 pooka if (strcmp(TESTSTR, buf) != 0) 104 1.1 pooka errx(1, "teststring doesn't match, got %s", buf); 105 1.1 pooka break; 106 1.1 pooka default: 107 1.1 pooka if (rump_sys_write(pipetti[1], TESTSTR, TESTSLEN) != TESTSLEN) 108 1.1 pooka err(1, "pipe write"); 109 1.1 pooka if (wait(&status) == -1) 110 1.1 pooka err(1, "wait failed"); 111 1.1 pooka if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) 112 1.1 pooka errx(1, "child exited with status %d", status); 113 1.1 pooka break; 114 1.1 pooka } 115 1.1 pooka } 116 1.1 pooka 117 1.1 pooka static void 118 1.1 pooka fakeauth(void) 119 1.1 pooka { 120 1.1 pooka struct rumpclient_fork *rf; 121 1.1 pooka uint32_t *auth; 122 1.1 pooka int rv; 123 1.1 pooka 124 1.1 pooka if ((rf = rumpclient_prefork()) == NULL) 125 1.1 pooka err(1, "prefork"); 126 1.1 pooka 127 1.1 pooka /* XXX: we know the internal structure of rf */ 128 1.1 pooka auth = (void *)rf; 129 1.1 pooka *(auth+3) = *(auth+3) ^ 0x1; 130 1.1 pooka 131 1.1 pooka rv = rumpclient_fork_init(rf); 132 1.1 pooka if (!(rv == -1 && errno == ESRCH)) 133 1.1 pooka exit(1); 134 1.1 pooka } 135 1.1 pooka 136 1.1 pooka struct parsa { 137 1.1 pooka const char *arg; /* sp arg, el */ 138 1.1 pooka void (*spring)(void); /* spring into action */ 139 1.1 pooka } paragus[] = { 140 1.1 pooka { "simple", simple }, 141 1.1 pooka { "cancel", cancel }, 142 1.1 pooka { "pipecomm", pipecomm }, 143 1.1 pooka { "fakeauth", fakeauth }, 144 1.1 pooka }; 145 1.1 pooka 146 1.1 pooka int 147 1.1 pooka main(int argc, char *argv[]) 148 1.1 pooka { 149 1.1 pooka unsigned i; 150 1.1 pooka 151 1.1 pooka if (argc != 2) 152 1.1 pooka errx(1, "invalid usage"); 153 1.1 pooka 154 1.1 pooka if (rumpclient_init() == -1) 155 1.1 pooka err(1, "rumpclient init"); 156 1.1 pooka 157 1.1 pooka for (i = 0; i < __arraycount(paragus); i++) { 158 1.1 pooka if (strcmp(argv[1], paragus[i].arg) == 0) { 159 1.1 pooka paragus[i].spring(); 160 1.1 pooka break; 161 1.1 pooka } 162 1.1 pooka } 163 1.1 pooka if (i == __arraycount(paragus)) { 164 1.1 pooka printf("invalid test %s\n", argv[1]); 165 1.1 pooka exit(1); 166 1.1 pooka } 167 1.1 pooka 168 1.1 pooka exit(0); 169 1.1 pooka } 170