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>
30 * size_t max, off, rlen;
34 * struct stdin_buffer {
35 * struct io_conn *reader, *writer;
40 * // This reads from stdin.
41 * static struct io_plan wake_writer(struct io_conn *, struct stdin_buffer *);
42 * // This writes the stdin buffer to the child.
43 * static struct io_plan wake_reader(struct io_conn *, struct stdin_buffer *);
45 * static struct io_plan wake_writer(struct io_conn *c, struct stdin_buffer *b)
47 * assert(c == b->reader);
48 * io_wake(b->writer, io_write(b->inbuf, b->len, wake_reader, b));
52 * static void reader_exit(struct io_conn *c, struct stdin_buffer *b)
54 * assert(c == b->reader);
55 * io_wake(b->writer, io_close());
59 * static struct io_plan wake_reader(struct io_conn *c, struct stdin_buffer *b)
61 * assert(c == b->writer);
64 * b->len = sizeof(b->inbuf);
65 * io_wake(b->reader, io_read_partial(b->inbuf, &b->len, wake_writer, b));
69 * static void fail_child_write(struct io_conn *conn, struct stdin_buffer *b)
72 * err(1, "Failed writing to child.");
75 * // This reads from the child and saves it into buffer.
76 * static struct io_plan read_from_child(struct io_conn *conn,
81 * if (b->off == b->max)
82 * b->buf = realloc(b->buf, b->max *= 2);
84 * b->rlen = b->max - b->off;
85 * return io_read_partial(b->buf + b->off, &b->rlen, read_from_child, b);
88 * // Feed a program our stdin, gather its stdout, print that at end.
89 * int main(int argc, char *argv[])
91 * int tochild[2], fromchild[2];
93 * struct stdin_buffer sbuf;
97 * struct io_conn *from_child;
100 * errx(1, "Usage: runner <cmdline>...");
102 * if (pipe(tochild) != 0 || pipe(fromchild) != 0)
103 * err(1, "Creating pipes");
106 * // Child runs command.
108 * close(fromchild[0]);
110 * dup2(tochild[0], STDIN_FILENO);
111 * dup2(fromchild[1], STDOUT_FILENO);
112 * execvp(argv[1], argv + 1);
117 * close(fromchild[1]);
118 * signal(SIGPIPE, SIG_IGN);
120 * sbuf.len = sizeof(sbuf.inbuf);
121 * sbuf.reader = io_new_conn(STDIN_FILENO,
122 * io_read_partial(sbuf.inbuf, &sbuf.len,
123 * wake_writer, &sbuf));
124 * sbuf.writer = io_new_conn(tochild[1], io_idle());
129 * out.buf = malloc(out.max);
130 * from_child = io_new_conn(fromchild[0],
131 * io_read_partial(out.buf, &out.rlen,
132 * read_from_child, &out));
133 * if (!sbuf.reader || !sbuf.writer || !from_child)
134 * err(1, "Allocating connections");
136 * io_set_finish(sbuf.reader, reader_exit, &sbuf);
137 * io_set_finish(sbuf.writer, fail_child_write, &sbuf);
142 * for (off = 0; off < out.off; off += ret) {
143 * ret = write(STDOUT_FILENO, out.buf+off, out.off-off);
145 * err(1, "Writing stdout");
149 * return WIFEXITED(status) ? WEXITSTATUS(status) : 2;
152 * License: LGPL (v2.1 or any later version)
153 * Author: Rusty Russell <rusty@rustcorp.com.au>
155 int main(int argc, char *argv[])
160 if (strcmp(argv[1], "depends") == 0) {
161 printf("ccan/time\n");
162 printf("ccan/timer\n");