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