]> git.ozlabs.org Git - ccan/blob - ccan/io/_info
rfc822: Use the memmem module
[ccan] / ccan / io / _info
1 #include <stdio.h>
2 #include <string.h>
3 #include "config.h"
4
5 /**
6  * io - simple library for asynchronous io handling.
7  *
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
11  * plans.
12  *
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
17  * function.
18  *
19  * Example:
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>
23  * #include <assert.h>
24  * #include <stdlib.h>
25  * #include <signal.h>
26  * #include <sys/types.h>
27  * #include <sys/wait.h>
28  * #include <string.h>
29  *
30  * struct buffer {
31  *      bool finished;
32  *      size_t start, end, rlen, wlen;
33  *      char buf[4096];
34  * };
35  *
36  * static void finish(struct io_conn *c, struct buffer *b)
37  * {
38  *      // Mark us finished.
39  *      b->finished = true;
40  *      // Wake writer just in case it's asleep.
41  *      io_wake(b);
42  * }
43  *
44  * static struct io_plan read_in(struct io_conn *c, struct buffer *b)
45  * {
46  *      // Add what we just read.
47  *      b->end += b->rlen;
48  *      assert(b->end <= sizeof(b->buf));
49  *
50  *      // If we just read something, wake writer.
51  *      if (b->rlen != 0)
52  *              io_wake(b);
53  *
54  *      // If buffer is empty, return to start.
55  *      if (b->start == b->end)
56  *              b->start = b->end = 0;
57  *
58  *      // Read in some of the rest.
59  *      b->rlen = sizeof(b->buf) - b->end;
60  *
61  *      // No room?  Wait for writer
62  *      if (b->rlen == 0)
63  *              return io_wait(b, read_in, b);
64  *
65  *      return io_read_partial(b->buf + b->end, &b->rlen, read_in, b);
66  * }
67  *
68  * static struct io_plan write_out(struct io_conn *c, struct buffer *b)
69  * {
70  *      // Remove what we just wrote.
71  *      b->start += b->wlen;
72  *      assert(b->start <= sizeof(b->buf));
73  *
74  *      // If we wrote somthing, wake writer.
75  *      if (b->wlen != 0)
76  *              io_wake(b);
77  *
78  *      b->wlen = b->end - b->start;
79  *      // Nothing to write?  Wait for reader.
80  *      if (b->wlen == 0) {
81  *              if (b->finished)
82  *                      return io_close();
83  *              return io_wait(b, write_out, b);
84  *      }
85  *
86  *      return io_write_partial(b->buf + b->start, &b->wlen, write_out, b);
87  * }
88  *
89  * // Feed a program our stdin, gather its stdout, print that at end.
90  * int main(int argc, char *argv[])
91  * {
92  *      int tochild[2], fromchild[2];
93  *      struct buffer to, from;
94  *      int status;
95  *      struct io_conn *reader;
96  *
97  *      if (argc == 1)
98  *              errx(1, "Usage: runner <cmdline>...");
99  *
100  *      if (pipe(tochild) != 0 || pipe(fromchild) != 0)
101  *              err(1, "Creating pipes");
102  *
103  *      if (!fork()) {
104  *              // Child runs command.
105  *              close(tochild[1]);
106  *              close(fromchild[0]);
107  *
108  *              dup2(tochild[0], STDIN_FILENO);
109  *              dup2(fromchild[1], STDOUT_FILENO);
110  *              execvp(argv[1], argv + 1);
111  *              exit(127);
112  *      }
113  *
114  *      close(tochild[0]);
115  *      close(fromchild[1]);
116  *      signal(SIGPIPE, SIG_IGN);
117  *
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));
123  *
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));
128  *
129  *      io_loop();
130  *      wait(&status);
131  *
132  *      return WIFEXITED(status) ? WEXITSTATUS(status) : 2;
133  * }
134  *
135  * License: LGPL (v2.1 or any later version)
136  * Author: Rusty Russell <rusty@rustcorp.com.au>
137  */
138 int main(int argc, char *argv[])
139 {
140         if (argc != 2)
141                 return 1;
142
143         if (strcmp(argv[1], "depends") == 0) {
144                 printf("ccan/typesafe_cb\n");
145                 printf("ccan/time\n");
146                 printf("ccan/timer\n");
147                 return 0;
148         }
149
150         return 1;
151 }