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