Home | History | Annotate | Line # | Download | only in h_client
      1 /*	$NetBSD: h_forkcli.c,v 1.2 2019/07/16 17:29:18 martin 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, 0600);
     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