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