1 /* $NetBSD: h_forkcli.c,v 1.1 2011/01/05 17:19:09 pooka 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
simple(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);
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
cancel(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
pipecomm(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
fakeauth(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
main(int argc,char * argv[])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