]> git.ozlabs.org Git - ccan/blob - ccan/io/_info
f494c124ead964cff335f446123fe879ad19ec4c
[ccan] / ccan / io / _info
1 #include <stdio.h>
2 #include <string.h>
3 #include "config.h"
4
5 /**
6  * io - simple library for stateful io handling.
7  *
8  * io provides a simple mechanism to write I/O servers with multiple
9  * connections.  Handling of connections is multiplexed, and function
10  * indicate what they want written or read, and what follow-on
11  * function to call on success (or failure).
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  *
23  * struct buffer {
24  *      size_t max, off, rlen;
25  *      char *buf;
26  * };
27  *
28  * struct stdin_buffer {
29  *      struct io_conn *reader, *writer;
30  *      size_t len;
31  *      char inbuf[4096];
32  * };
33  *
34  * // This reads from stdin.
35  * static struct io_op *wake_writer(struct io_conn *, struct stdin_buffer *);
36  * // This writes the stdin buffer to the child.
37  * static struct io_op *write_to_child(struct io_conn *c,
38  *                                     struct stdin_buffer *b);
39  * static struct io_op *read_stdin(struct io_conn *c, struct stdin_buffer *b)
40  * {
41  *      assert(c == b->reader);
42  *      b->len = sizeof(b->inbuf);
43  *      return io_read_partial(b->inbuf, &b->len,
44  *                             io_next(c, wake_writer, b));
45  * }
46  *
47  * static struct io_op *wake_writer(struct io_conn *c, struct stdin_buffer *b)
48  * {
49  *      assert(c == b->reader);
50  *      io_wake(b->writer, write_to_child, b);
51  *      return io_idle(c);
52  * }
53  *
54  * static void reader_exit(struct io_conn *c, struct stdin_buffer *b)
55  * {
56  *      assert(c == b->reader);
57  *      io_wake(b->writer, write_to_child, b);
58  *      b->reader = NULL;
59  * }
60  *
61  * static struct io_op *wake_reader(struct io_conn *c, struct stdin_buffer *b)
62  * {
63  *      assert(c == b->writer);
64  *      io_wake(b->reader, read_stdin, b);
65  *      return io_idle(c);
66  * }
67  *
68  * static struct io_op *write_to_child(struct io_conn *conn,
69  *                                    struct stdin_buffer *b)
70  * {
71  *      assert(conn == b->writer);
72  *      if (!b->reader)
73  *              return io_close(conn, NULL);
74  *      return io_write(b->inbuf, b->len, io_next(conn, wake_reader, b));
75  * }
76  *
77  * static struct io_op *start_writer(struct io_conn *conn,
78  *                                   struct stdin_buffer *b)
79  * {
80  *      assert(conn == b->writer);
81  *      return io_idle(conn);
82  * }
83  *
84  * static void fail_child_write(struct io_conn *conn, struct stdin_buffer *b)
85  * {
86  *      if (b->reader)
87  *              err(1, "Failed writing to child.");
88  * }
89  *
90  * // This reads from the child and saves it into buffer.
91  * static struct io_op *read_from_child(struct io_conn *conn,
92  *                                      struct buffer *b)
93  * {
94  *      b->off += b->rlen;
95  *
96  *      if (b->off == b->max) {
97  *              if (b->max == 0)
98  *                      b->max = 128;
99  *              else if (b->max >= 1024*1024)
100  *                      b->max += 1024*1024;
101  *              else
102  *                      b->max *= 2;
103  *              b->buf = realloc(b->buf, b->max);
104  *      }
105  *
106  *      b->rlen = b->max - b->off;
107  *      return io_read_partial(b->buf + b->off, &b->rlen,
108  *                             io_next(conn, read_from_child, b));
109  * }
110  *
111  * // Feed a program our stdin, gather its stdout, print that at end.
112  * int main(int argc, char *argv[])
113  * {
114  *      int tochild[2], fromchild[2];
115  *      struct buffer out = { 0, 0, 0, NULL };
116  *      struct stdin_buffer sbuf;
117  *      int status;
118  *      size_t off;
119  *      ssize_t ret;
120  *
121  *      if (argc == 1)
122  *              errx(1, "Usage: runner <cmdline>...");
123  *
124  *      if (pipe(tochild) != 0 || pipe(fromchild) != 0)
125  *              err(1, "Creating pipes");
126  *
127  *      if (!fork()) {
128  *              // Child runs command.
129  *              close(tochild[1]);
130  *              close(fromchild[0]);
131  *
132  *              dup2(tochild[0], STDIN_FILENO);
133  *              dup2(fromchild[1], STDOUT_FILENO);
134  *              execvp(argv[1], argv + 1);
135  *              exit(127);
136  *      }
137  *
138  *      close(tochild[0]);
139  *      close(fromchild[1]);
140  *      signal(SIGPIPE, SIG_IGN);
141  *
142  *      sbuf.reader = io_new_conn(STDIN_FILENO, read_stdin, reader_exit, &sbuf);
143  *      sbuf.writer = io_new_conn(tochild[1], start_writer, fail_child_write,
144  *                                &sbuf);
145  *      if (!sbuf.reader || !sbuf.writer
146  *          || !io_new_conn(fromchild[0], read_from_child, NULL, &out))
147  *              err(1, "Allocating connections");
148  *
149  *      io_loop();
150  *      wait(&status);
151  *
152  *      for (off = 0; off < out.off; off += ret) {
153  *              ret = write(STDOUT_FILENO, out.buf+off, out.off-off);
154  *              if (ret < 0)
155  *                      err(1, "Writing stdout");
156  *      }
157  *      free(out.buf);
158  *
159  *      return WIFEXITED(status) ? WEXITSTATUS(status) : 2;
160  * }
161  *
162  * License: BSD-MIT
163  */
164 int main(int argc, char *argv[])
165 {
166         if (argc != 2)
167                 return 1;
168
169         if (strcmp(argv[1], "depends") == 0) {
170                 return 0;
171         }
172
173         return 1;
174 }