nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* source: xio-stdio.c */ |
2 | /* Copyright Gerhard Rieger 2001-2009 */ |
||
3 | /* Published under the GNU General Public License V.2, see file COPYING */ |
||
4 | |||
5 | /* this file contains the source for opening addresses stdio type */ |
||
6 | |||
7 | #include "xiosysincludes.h" |
||
8 | #include "xioopen.h" |
||
9 | |||
10 | #include "xio-fdnum.h" |
||
11 | #include "xio-stdio.h" |
||
12 | |||
13 | |||
14 | #if WITH_STDIO |
||
15 | |||
16 | static int xioopen_stdio(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3); |
||
17 | static int xioopen_stdfd(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, unsigned groups, int fd, int dummy2, int dummy3); |
||
18 | |||
19 | |||
20 | /* we specify all option groups that we can imagine for a FD, becasue the |
||
21 | changed parsing mechanism does not allow us to check the type of FD before |
||
22 | applying the options */ |
||
23 | static const struct xioaddr_endpoint_desc xioaddr_stdio0 = { XIOADDR_SYS, "stdio", 0, XIOBIT_ALL, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_FILE|GROUP_SOCKET|GROUP_TERMIOS|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP, XIOSHUT_UNSPEC, XIOCLOSE_NONE, xioopen_stdio, 0, 0, 0 HELP(NULL) }; |
||
24 | static const struct xioaddr_endpoint_desc xioaddr_stdin0 = { XIOADDR_SYS, "stdin", 0, XIOBIT_RDONLY, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_FILE|GROUP_SOCKET|GROUP_TERMIOS|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP, XIOSHUT_UNSPEC, XIOCLOSE_NONE, xioopen_stdfd, 0, 0, 0 HELP(NULL) }; |
||
25 | static const struct xioaddr_endpoint_desc xioaddr_stdout0 = { XIOADDR_SYS, "stdout", 0, XIOBIT_WRONLY, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_FILE|GROUP_SOCKET|GROUP_TERMIOS|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP, XIOSHUT_UNSPEC, XIOCLOSE_NONE, xioopen_stdfd, 1, 0, 0 HELP(NULL) }; |
||
26 | static const struct xioaddr_endpoint_desc xioaddr_stderr0 = { XIOADDR_SYS, "stderr", 0, XIOBIT_WRONLY, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_FILE|GROUP_SOCKET|GROUP_TERMIOS|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP, XIOSHUT_UNSPEC, XIOCLOSE_NONE, xioopen_stdfd, 2, 0, 0 HELP(NULL) }; |
||
27 | |||
28 | const union xioaddr_desc *xioaddrs_stdio[] = { |
||
29 | (union xioaddr_desc *)&xioaddr_stdio0, NULL }; |
||
30 | const union xioaddr_desc *xioaddrs_stdin[] = { |
||
31 | (union xioaddr_desc *)&xioaddr_stdin0, NULL }; |
||
32 | const union xioaddr_desc *xioaddrs_stdout[] = { |
||
33 | (union xioaddr_desc *)&xioaddr_stdout0, NULL }; |
||
34 | const union xioaddr_desc *xioaddrs_stderr[] = { |
||
35 | (union xioaddr_desc *)&xioaddr_stderr0, NULL }; |
||
36 | |||
37 | /* process a bidirectional "stdio" or "-" argument with options. */ |
||
38 | int xioopen_stdio_bi(xiofile_t *sock) { |
||
39 | struct opt *opts1, *opts2, *optspr; |
||
40 | unsigned int groups1 = xioaddr_stdio0.groups, groups2 = xioaddr_stdio0.groups; |
||
41 | int result; |
||
42 | |||
43 | sock->stream.rfd = 0 /*stdin*/; |
||
44 | sock->stream.wfd = 1 /*stdout*/; |
||
45 | |||
46 | #if WITH_TERMIOS |
||
47 | if (Isatty(sock->stream.rfd)) { |
||
48 | if (Tcgetattr(sock->stream.rfd, |
||
49 | &sock->stream.savetty) |
||
50 | < 0) { |
||
51 | Warn2("cannot query current terminal settings on fd %d: %s", |
||
52 | sock->stream.rfd, strerror(errno)); |
||
53 | } else { |
||
54 | sock->stream.ttyvalid = true; |
||
55 | } |
||
56 | } |
||
57 | if (Isatty(sock->stream.wfd) && (sock->stream.wfd != sock->stream.rfd)) { |
||
58 | if (Tcgetattr(sock->stream.wfd, |
||
59 | &sock->stream.savetty) |
||
60 | < 0) { |
||
61 | Warn2("cannot query current terminal settings on fd %d: %s", |
||
62 | sock->stream.wfd, strerror(errno)); |
||
63 | } else { |
||
64 | sock->stream.ttyvalid = true; |
||
65 | } |
||
66 | } |
||
67 | #endif /* WITH_TERMIOS */ |
||
68 | if (applyopts_single(&sock->stream, sock->stream.opts, PH_INIT) < 0) |
||
69 | return -1; |
||
70 | applyopts(-1, sock->stream.opts, PH_INIT); |
||
71 | if (sock->stream.howtoshut == XIOSHUT_UNSPEC) |
||
72 | sock->stream.howtoshut = XIOSHUT_NONE; |
||
73 | |||
74 | /* options here are one-time and one-direction, no second use */ |
||
75 | retropt_bool(sock->stream.opts, OPT_IGNOREEOF, &sock->stream.ignoreeof); |
||
76 | |||
77 | /* extract opts that should be applied only once */ |
||
78 | if ((optspr = copyopts(sock->stream.opts, GROUP_PROCESS)) == NULL) { |
||
79 | return -1; |
||
80 | } |
||
81 | if ((result = applyopts(-1, optspr, PH_EARLY)) < 0) |
||
82 | return result; |
||
83 | if ((result = applyopts(-1, optspr, PH_PREOPEN)) < 0) |
||
84 | return result; |
||
85 | |||
86 | /* here we copy opts, because most have to be applied twice! */ |
||
87 | if ((opts1 = copyopts(sock->stream.opts, GROUP_FD|GROUP_APPL|(groups1&~GROUP_PROCESS))) == NULL) { |
||
88 | return -1; |
||
89 | } |
||
90 | |||
91 | /* apply options to first FD */ |
||
92 | if ((result = applyopts(sock->stream.rfd, opts1, PH_ALL)) < 0) { |
||
93 | return result; |
||
94 | } |
||
95 | if ((result = _xio_openlate(&sock->stream, opts1)) < 0) { |
||
96 | return result; |
||
97 | } |
||
98 | |||
99 | if ((opts2 = copyopts(sock->stream.opts, GROUP_FD|GROUP_APPL|(groups2&~GROUP_PROCESS))) == NULL) { |
||
100 | return -1; |
||
101 | } |
||
102 | /* apply options to second FD */ |
||
103 | if ((result = applyopts(sock->stream.wfd, opts2, PH_ALL)) < 0) { |
||
104 | return result; |
||
105 | } |
||
106 | if ((result = _xio_openlate(&sock->stream, opts2)) < 0) { |
||
107 | return result; |
||
108 | } |
||
109 | |||
110 | if ((result = _xio_openlate(&sock->stream, optspr)) < 0) { |
||
111 | return result; |
||
112 | } |
||
113 | |||
114 | Notice("reading from and writing to stdio"); |
||
115 | return 0; |
||
116 | } |
||
117 | |||
118 | |||
119 | /* wrap around unidirectional xioopensingle and xioopen_fd to automatically determine stdin or stdout fd depending on rw. |
||
120 | Do not set FD_CLOEXEC flag. */ |
||
121 | static int xioopen_stdio(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, unsigned groups, int dummy1, int dummy2, int dummy3) { |
||
122 | int rw = (xioflags&XIO_ACCMODE); |
||
123 | |||
124 | if (argc != 1) { |
||
125 | Error2("%s: wrong number of parameters (%d instead of 0)", argv[0], argc-1); |
||
126 | } |
||
127 | |||
128 | if (rw == XIO_RDWR) { |
||
129 | return xioopen_stdio_bi(xfd); |
||
130 | } |
||
131 | |||
132 | Notice2("using %s for %s", |
||
133 | &("stdin\0\0\0stdout"[rw<<3]), |
||
134 | ddirection[rw]); |
||
135 | return xioopen_fd(opts, rw, xfd, |
||
136 | XIOWITHRD(rw)?0:-1, |
||
137 | XIOWITHWR(rw)?1:-1, |
||
138 | dummy2, dummy3); |
||
139 | } |
||
140 | |||
141 | /* wrap around unidirectional xioopensingle and xioopen_fd to automatically determine stdin or stdout fd depending on rw. |
||
142 | Do not set FD_CLOEXEC flag. */ |
||
143 | static int xioopen_stdfd(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, unsigned groups, int fd, int dummy2, int dummy3) { |
||
144 | int rw = (xioflags&XIO_ACCMODE); |
||
145 | |||
146 | if (argc != 1) { |
||
147 | Error2("%s: wrong number of parameters (%d instead of 0)", argv[0], argc-1); |
||
148 | } |
||
149 | Notice2("using %s for %s", |
||
150 | &("stdin\0\0\0stdout\0\0stderr"[fd<<3]), |
||
151 | ddirection[rw]); |
||
152 | return xioopen_fd(opts, rw, xfd, |
||
153 | XIOWITHRD(rw)?fd:-1, |
||
154 | XIOWITHWR(rw)?fd:-1, |
||
155 | dummy2, dummy3); |
||
156 | } |
||
157 | #endif /* WITH_STDIO */ |