6 * io - simple library for asynchronous io handling.
8 * io provides a mechanism to write I/O servers with multiple
9 * connections. Each callback indicates what I/O they plan next
10 * (eg. read, write). It is also possible to write custom I/O
13 * When compiled with DEBUG, control flow is changed so that rather
14 * than returning to the main io_loop(), plans are executed sequentially
15 * providing a backtrace showing what has occurred on that connection.
16 * Which connection(s) do this depends on the user-specified io_debug
20 * // Given tr A-Z a-z outputs tr a-z a-z
21 * #include <ccan/io/io.h>
22 * #include <ccan/err/err.h>
26 * #include <sys/types.h>
27 * #include <sys/wait.h>
32 * size_t start, end, rlen, wlen;
36 * static void finish(struct io_conn *c, struct buffer *b)
38 * // Mark us finished.
40 * // Wake writer just in case it's asleep.
44 * static struct io_plan read_in(struct io_conn *c, struct buffer *b)
46 * // Add what we just read.
48 * assert(b->end <= sizeof(b->buf));
50 * // If we just read something, wake writer.
54 * // If buffer is empty, return to start.
55 * if (b->start == b->end)
56 * b->start = b->end = 0;
58 * // Read in some of the rest.
59 * b->rlen = sizeof(b->buf) - b->end;
61 * // No room? Wait for writer
63 * return io_wait(b, read_in, b);
65 * return io_read_partial(b->buf + b->end, &b->rlen, read_in, b);
68 * static struct io_plan write_out(struct io_conn *c, struct buffer *b)
70 * // Remove what we just wrote.
71 * b->start += b->wlen;
72 * assert(b->start <= sizeof(b->buf));
74 * // If we wrote somthing, wake writer.
78 * b->wlen = b->end - b->start;
79 * // Nothing to write? Wait for reader.
83 * return io_wait(b, write_out, b);
86 * return io_write_partial(b->buf + b->start, &b->wlen, write_out, b);
89 * // Feed a program our stdin, gather its stdout, print that at end.
90 * int main(int argc, char *argv[])
92 * int tochild[2], fromchild[2];
93 * struct buffer to, from;
95 * struct io_conn *reader;
98 * errx(1, "Usage: runner <cmdline>...");
100 * if (pipe(tochild) != 0 || pipe(fromchild) != 0)
101 * err(1, "Creating pipes");
104 * // Child runs command.
106 * close(fromchild[0]);
108 * dup2(tochild[0], STDIN_FILENO);
109 * dup2(fromchild[1], STDOUT_FILENO);
110 * execvp(argv[1], argv + 1);
115 * close(fromchild[1]);
116 * signal(SIGPIPE, SIG_IGN);
118 * // Read from stdin, write to child.
119 * memset(&to, 0, sizeof(to));
120 * reader = io_new_conn(STDIN_FILENO, read_in(NULL, &to));
121 * io_set_finish(reader, finish, &to);
122 * io_new_conn(tochild[1], write_out(NULL, &to));
124 * // Read from child, write to stdout.
125 * reader = io_new_conn(fromchild[0], read_in(NULL, &from));
126 * io_set_finish(reader, finish, &from);
127 * io_new_conn(STDOUT_FILENO, write_out(NULL, &from));
132 * return WIFEXITED(status) ? WEXITSTATUS(status) : 2;
135 * License: LGPL (v2.1 or any later version)
136 * Author: Rusty Russell <rusty@rustcorp.com.au>
138 int main(int argc, char *argv[])
143 if (strcmp(argv[1], "depends") == 0) {
144 printf("ccan/typesafe_cb\n");
145 printf("ccan/time\n");
146 printf("ccan/timer\n");