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
|
/*
* fdopen.c
*
* Common code between fopen(), fdopen() and the standard descriptors.
*/
#include "stdioint.h"
FILE *stdin, *stdout, *stderr;
/* Doubly-linked list of all stdio structures */
struct _IO_file_pvt __stdio_headnode =
{
.prev = &__stdio_headnode,
.next = &__stdio_headnode,
};
FILE *fopencookie(void *cookie, const char *mode, cookie_io_functions_t funcs)
{
struct _IO_file_pvt *f;
const size_t bufoffs =
(sizeof *f + 4*sizeof(void *) - 1) &
~(4*sizeof(void *) - 1);
(void)mode;
f = zalloc(bufoffs + BUFSIZ + _IO_UNGET_SLOP);
if (!f)
goto err;
f->data = f->buf = (char *)f + bufoffs;
f->funcs = funcs;
f->cookie = cookie;
f->bufsiz = BUFSIZ;
f->bufmode = _IOFBF;
/* Insert into linked list */
f->prev = &__stdio_headnode;
f->next = __stdio_headnode.next;
f->next->prev = f;
__stdio_headnode.next = f;
return &f->pub;
err:
if (f)
free(f);
errno = ENOMEM;
return NULL;
}
FILE *fdopen(int fd, const char *mode)
{
FILE *file;
/*
* Cookie operations for ordinary files. This is only safe because
* all Linux architectures pass integers <= sizeof(pointer) and
* pointers the same way, at least for non-structure arguments.
*/
const struct cookie_io_functions_t file_funcs = {
.read = (cookie_read_function_t *)read,
.write = (cookie_write_function_t *)write,
.seek = (cookie_seek_function_t *)lseek,
.close = (cookie_close_function_t *)close
};
file = fopencookie((void *)(intptr_t)fd, mode, file_funcs);
if (file) {
struct _IO_file_pvt *f = stdio_pvt(file);
f->isfile = true;
f->bufmode = isatty(fd) ? _IOLBF : _IOFBF;
}
return file;
}
void __init_stdio(void)
{
stdin = fdopen(0, NULL);
stdout = fdopen(1, NULL);
stderr = fdopen(2, NULL);
stdio_pvt(stderr)->bufmode = _IONBF;
}
|