diff options
Diffstat (limited to 'rump/rumpkern/h_client/h_forkcli.c')
| -rw-r--r-- | rump/rumpkern/h_client/h_forkcli.c | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/rump/rumpkern/h_client/h_forkcli.c b/rump/rumpkern/h_client/h_forkcli.c new file mode 100644 index 000000000000..3b89727bedd6 --- /dev/null +++ b/rump/rumpkern/h_client/h_forkcli.c @@ -0,0 +1,169 @@ +/* $NetBSD: h_forkcli.c,v 1.1 2011/01/05 17:19:09 pooka Exp $ */ + +#include <sys/types.h> +#include <sys/wait.h> + +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include <rump/rump_syscalls.h> +#include <rump/rumpclient.h> + +static void +simple(void) +{ + struct rumpclient_fork *rf; + pid_t pid1, pid2; + int fd, status; + + if ((pid1 = rump_sys_getpid()) < 2) + errx(1, "unexpected pid %d", pid1); + + fd = rump_sys_open("/dev/null", O_CREAT | O_RDWR); + if (rump_sys_write(fd, &fd, sizeof(fd)) != sizeof(fd)) + errx(1, "write newlyopened /dev/null"); + + if ((rf = rumpclient_prefork()) == NULL) + err(1, "prefork"); + + switch (fork()) { + case -1: + err(1, "fork"); + break; + case 0: + if (rumpclient_fork_init(rf) == -1) + err(1, "postfork init failed"); + + if ((pid2 = rump_sys_getpid()) < 2) + errx(1, "unexpected pid %d", pid2); + if (pid1 == pid2) + errx(1, "child and parent pids are equal"); + + /* check that we can access the fd, the close it and exit */ + if (rump_sys_write(fd, &fd, sizeof(fd)) != sizeof(fd)) + errx(1, "write child /dev/null"); + rump_sys_close(fd); + break; + default: + /* + * check that we can access the fd, wait for the child, and + * check we can still access the fd + */ + if (rump_sys_write(fd, &fd, sizeof(fd)) != sizeof(fd)) + errx(1, "write parent /dev/null"); + if (wait(&status) == -1) + err(1, "wait failed"); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) + errx(1, "child exited with status %d", status); + if (rump_sys_write(fd, &fd, sizeof(fd)) != sizeof(fd)) + errx(1, "write parent /dev/null"); + break; + } +} + +static void +cancel(void) +{ + + /* XXX: not implemented in client / server !!! */ +} + +#define TESTSTR "i am your fatherrrrrrr" +#define TESTSLEN (sizeof(TESTSTR)-1) +static void +pipecomm(void) +{ + struct rumpclient_fork *rf; + char buf[TESTSLEN+1]; + int pipetti[2]; + int status; + + if (rump_sys_pipe(pipetti) == -1) + errx(1, "pipe"); + + if ((rf = rumpclient_prefork()) == NULL) + err(1, "prefork"); + + switch (fork()) { + case -1: + err(1, "fork"); + break; + case 0: + if (rumpclient_fork_init(rf) == -1) + err(1, "postfork init failed"); + + memset(buf, 0, sizeof(buf)); + if (rump_sys_read(pipetti[0], buf, TESTSLEN) != TESTSLEN) + err(1, "pipe read"); + if (strcmp(TESTSTR, buf) != 0) + errx(1, "teststring doesn't match, got %s", buf); + break; + default: + if (rump_sys_write(pipetti[1], TESTSTR, TESTSLEN) != TESTSLEN) + err(1, "pipe write"); + if (wait(&status) == -1) + err(1, "wait failed"); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) + errx(1, "child exited with status %d", status); + break; + } +} + +static void +fakeauth(void) +{ + struct rumpclient_fork *rf; + uint32_t *auth; + int rv; + + if ((rf = rumpclient_prefork()) == NULL) + err(1, "prefork"); + + /* XXX: we know the internal structure of rf */ + auth = (void *)rf; + *(auth+3) = *(auth+3) ^ 0x1; + + rv = rumpclient_fork_init(rf); + if (!(rv == -1 && errno == ESRCH)) + exit(1); +} + +struct parsa { + const char *arg; /* sp arg, el */ + void (*spring)(void); /* spring into action */ +} paragus[] = { + { "simple", simple }, + { "cancel", cancel }, + { "pipecomm", pipecomm }, + { "fakeauth", fakeauth }, +}; + +int +main(int argc, char *argv[]) +{ + unsigned i; + + if (argc != 2) + errx(1, "invalid usage"); + + if (rumpclient_init() == -1) + err(1, "rumpclient init"); + + for (i = 0; i < __arraycount(paragus); i++) { + if (strcmp(argv[1], paragus[i].arg) == 0) { + paragus[i].spring(); + break; + } + } + if (i == __arraycount(paragus)) { + printf("invalid test %s\n", argv[1]); + exit(1); + } + + exit(0); +} |
