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