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
|
#define _GNU_SOURCE
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
struct slow_cookie
{
int fd;
};
static ssize_t slow_read(void *vcookie, char *buf, size_t count)
{
struct slow_cookie *cookie = vcookie;
usleep(500000); // sleep for half of a second
ssize_t res;
while ((res = read(cookie->fd, buf, count)) < 0)
if (errno != EINTR && errno != EAGAIN)
break;
return res;
}
static int slow_close(void *vcookie)
{
struct slow_cookie *cookie = vcookie;
return close(cookie->fd);
}
cookie_io_functions_t slow_stdio = {
.read = slow_read,
.close = slow_close,
};
int main(void)
{
/* setup a custom stdin stream with a slow read function */
struct slow_cookie cookie = {
.fd = STDIN_FILENO,
};
FILE *input_stream = fopencookie(&cookie, "r", slow_stdio);
/* change the buffer size to the one given by stdbuf.
** it doesn't work out of the box as stdbuf only does
** this for the already existing stdin stream.
*/
char *buffer = NULL;
char *buffer_size = getenv("_STDBUF_I");
if (buffer_size)
{
size_t size = atoi(buffer_size);
buffer = malloc(size);
setvbuf(input_stream, buffer, _IOFBF, size);
}
/* forward all characters from stdin to stdout */
int c;
while ((c = fgetc(input_stream)) != EOF)
{
fputc(c, stdout);
fflush(stdout);
}
fclose(input_stream);
free(buffer);
return 0;
}
|