137Srgrimes/* $NetBSD: h_forkcli.c,v 1.1 2011/01/05 17:19:09 pooka Exp $ */ 237Srgrimes 337Srgrimes#include <sys/types.h> 437Srgrimes#include <sys/wait.h> 537Srgrimes 637Srgrimes#include <err.h> 737Srgrimes#include <errno.h> 837Srgrimes#include <fcntl.h> 937Srgrimes#include <stdlib.h> 1037Srgrimes#include <stdio.h> 1137Srgrimes#include <string.h> 1237Srgrimes#include <unistd.h> 1337Srgrimes 1437Srgrimes#include <rump/rump_syscalls.h> 1537Srgrimes#include <rump/rumpclient.h> 1637Srgrimes 1737Srgrimesstatic void 1837Srgrimessimple(void) 1937Srgrimes{ 2037Srgrimes struct rumpclient_fork *rf; 2137Srgrimes pid_t pid1, pid2; 2237Srgrimes int fd, status; 2337Srgrimes 2437Srgrimes if ((pid1 = rump_sys_getpid()) < 2) 2537Srgrimes errx(1, "unexpected pid %d", pid1); 2637Srgrimes 2737Srgrimes fd = rump_sys_open("/dev/null", O_CREAT | O_RDWR); 2837Srgrimes if (rump_sys_write(fd, &fd, sizeof(fd)) != sizeof(fd)) 2937Srgrimes errx(1, "write newlyopened /dev/null"); 3037Srgrimes 3137Srgrimes if ((rf = rumpclient_prefork()) == NULL) 3237Srgrimes err(1, "prefork"); 3337Srgrimes 3437Srgrimes switch (fork()) { 3537Srgrimes case -1: 3637Srgrimes err(1, "fork"); 3737Srgrimes break; 3837Srgrimes case 0: 3937Srgrimes if (rumpclient_fork_init(rf) == -1) 4037Srgrimes err(1, "postfork init failed"); 4137Srgrimes 4237Srgrimes if ((pid2 = rump_sys_getpid()) < 2) 4337Srgrimes errx(1, "unexpected pid %d", pid2); 4437Srgrimes if (pid1 == pid2) 4537Srgrimes errx(1, "child and parent pids are equal"); 4637Srgrimes 4737Srgrimes /* check that we can access the fd, the close it and exit */ 4837Srgrimes if (rump_sys_write(fd, &fd, sizeof(fd)) != sizeof(fd)) 4937Srgrimes errx(1, "write child /dev/null"); 5037Srgrimes rump_sys_close(fd); 5137Srgrimes break; 5237Srgrimes default: 5337Srgrimes /* 5437Srgrimes * check that we can access the fd, wait for the child, and 5537Srgrimes * check we can still access the fd 5637Srgrimes */ 5737Srgrimes if (rump_sys_write(fd, &fd, sizeof(fd)) != sizeof(fd)) 5837Srgrimes errx(1, "write parent /dev/null"); 5937Srgrimes if (wait(&status) == -1) 6037Srgrimes err(1, "wait failed"); 6137Srgrimes if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) 6237Srgrimes errx(1, "child exited with status %d", status); 6337Srgrimes if (rump_sys_write(fd, &fd, sizeof(fd)) != sizeof(fd)) 6437Srgrimes errx(1, "write parent /dev/null"); 6537Srgrimes break; 6637Srgrimes } 6737Srgrimes} 6837Srgrimes 6937Srgrimesstatic void 7037Srgrimescancel(void) 7137Srgrimes{ 7237Srgrimes 7337Srgrimes /* XXX: not implemented in client / server !!! */ 7437Srgrimes} 7537Srgrimes 7637Srgrimes#define TESTSTR "i am your fatherrrrrrr" 7737Srgrimes#define TESTSLEN (sizeof(TESTSTR)-1) 7837Srgrimesstatic void 7937Srgrimespipecomm(void) 8037Srgrimes{ 8137Srgrimes struct rumpclient_fork *rf; 8237Srgrimes char buf[TESTSLEN+1]; 8337Srgrimes int pipetti[2]; 8437Srgrimes int status; 8537Srgrimes 8637Srgrimes if (rump_sys_pipe(pipetti) == -1) 8737Srgrimes errx(1, "pipe"); 8837Srgrimes 8937Srgrimes if ((rf = rumpclient_prefork()) == NULL) 9037Srgrimes err(1, "prefork"); 9137Srgrimes 9237Srgrimes switch (fork()) { 9337Srgrimes case -1: 9437Srgrimes err(1, "fork"); 9537Srgrimes break; 9637Srgrimes case 0: 9737Srgrimes if (rumpclient_fork_init(rf) == -1) 9837Srgrimes err(1, "postfork init failed"); 9937Srgrimes 10037Srgrimes memset(buf, 0, sizeof(buf)); 10137Srgrimes if (rump_sys_read(pipetti[0], buf, TESTSLEN) != TESTSLEN) 10237Srgrimes err(1, "pipe read"); 10337Srgrimes if (strcmp(TESTSTR, buf) != 0) 10437Srgrimes errx(1, "teststring doesn't match, got %s", buf); 10537Srgrimes break; 10637Srgrimes default: 10737Srgrimes if (rump_sys_write(pipetti[1], TESTSTR, TESTSLEN) != TESTSLEN) 10837Srgrimes err(1, "pipe write"); 10937Srgrimes if (wait(&status) == -1) 11037Srgrimes err(1, "wait failed"); 11137Srgrimes if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) 11237Srgrimes errx(1, "child exited with status %d", status); 11337Srgrimes break; 11437Srgrimes } 11537Srgrimes} 11637Srgrimes 11737Srgrimesstatic void 11837Srgrimesfakeauth(void) 11937Srgrimes{ 12037Srgrimes struct rumpclient_fork *rf; 12137Srgrimes uint32_t *auth; 12237Srgrimes int rv; 12337Srgrimes 12437Srgrimes if ((rf = rumpclient_prefork()) == NULL) 12537Srgrimes err(1, "prefork"); 12637Srgrimes 12737Srgrimes /* XXX: we know the internal structure of rf */ 12837Srgrimes auth = (void *)rf; 12937Srgrimes *(auth+3) = *(auth+3) ^ 0x1; 13037Srgrimes 13137Srgrimes rv = rumpclient_fork_init(rf); 13237Srgrimes if (!(rv == -1 && errno == ESRCH)) 13337Srgrimes exit(1); 13437Srgrimes} 13537Srgrimes 13637Srgrimesstruct parsa { 13737Srgrimes const char *arg; /* sp arg, el */ 13837Srgrimes void (*spring)(void); /* spring into action */ 13937Srgrimes} paragus[] = { 14037Srgrimes { "simple", simple }, 14137Srgrimes { "cancel", cancel }, 14237Srgrimes { "pipecomm", pipecomm }, 14337Srgrimes { "fakeauth", fakeauth }, 14437Srgrimes}; 14537Srgrimes 14637Srgrimesint 14737Srgrimesmain(int argc, char *argv[]) 14837Srgrimes{ 14937Srgrimes unsigned i; 15037Srgrimes 15137Srgrimes if (argc != 2) 15237Srgrimes errx(1, "invalid usage"); 15337Srgrimes 15437Srgrimes if (rumpclient_init() == -1) 15537Srgrimes err(1, "rumpclient init"); 15637Srgrimes 15737Srgrimes for (i = 0; i < __arraycount(paragus); i++) { 15837Srgrimes if (strcmp(argv[1], paragus[i].arg) == 0) { 15937Srgrimes paragus[i].spring(); 16037Srgrimes break; 16137Srgrimes } 16237Srgrimes } 16337Srgrimes if (i == __arraycount(paragus)) { 16437Srgrimes printf("invalid test %s\n", argv[1]); 16537Srgrimes exit(1); 16637Srgrimes } 16737Srgrimes 16837Srgrimes exit(0); 16937Srgrimes} 17037Srgrimes