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