1 #include <ccan/oserver/oserver.c>
2 #include <ccan/oserver/oserver.h>
3 #include <ccan/str/str.h>
4 #include <ccan/tap/tap.h>
6 #include <sys/select.h>
12 static bool write_sall(int fd, const char *str)
15 ssize_t len = write(fd, str, strlen(str));
23 static bool input_is(int fd, const char *str)
27 ssize_t len = read(fd, buffer, strlen(str));
30 if (strncmp(str, buffer, len) != 0)
37 static void run_client(int readyfd, bool die)
41 struct sockaddr_in in;
43 int sfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
46 u.in.sin_family = AF_INET;
47 u.in.sin_port = htons(OSERVER_PORT);
48 u.in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
49 if (connect(sfd, &u.addr, sizeof(u.in)) != 0)
52 if (!input_is(sfd, "Welcome. Please ask your question.\n"))
56 if (!write_sall(sfd, "Question?\n"))
59 if (!input_is(sfd, "While the Oracle ponders, please answer the following question:\nQuestion?\n"))
66 if (!write_sall(sfd, "Answer?\n"))
69 /* Since other died, oracle won't say any more. */
74 static void set_flag(struct tevent_context *ev,
75 struct tevent_signal *se,
85 static unsigned int count_clients(struct oserver *oserver)
87 unsigned int i, count = 0;
89 for (i = 0; i < ARRAY_SIZE(oserver->clients); i++) {
90 if (oserver->clients[i])
96 int main(int argc, char *argv[])
99 struct tevent_context *ev = tevent_context_init(NULL);
100 struct oserver *oserver;
104 /* This is how many tests you plan to run */
107 oserver = oserver_setup(ev, OSERVER_PORT);
109 err(1, "Failed to set up server");
111 tevent_add_signal(ev, ev, SIGCHLD, 0, set_flag, &done);
115 /* This child will exit, doesn't need fd. */
118 run_client(-1, true);
122 run_client(ready[0], false);
125 /* Wait for dead child to exit... */
127 tevent_loop_once(ev);
129 /* Wait for client to be freed. */
130 while (count_clients(oserver) == 2)
131 tevent_loop_once(ev);
133 /* One child should be dead... */
134 ok1(waitpid(-1, &status, 0) > 0);
136 /* Tell other child to write answer. */
137 write(ready[1], &status, 1);
140 tevent_loop_once(ev);
142 /* Other child should be hung... */
143 ok1(waitpid(-1, &status, WNOHANG) == 0);
146 return exit_status();