Version 1.8.0.0
[socat.git] / xio-stdio.c
blob9f8aac99ee0106f5a0f6eac29ceaccf807b63f09
1 /* source: xio-stdio.c */
2 /* Copyright Gerhard Rieger and contributors (see file CHANGES) */
3 /* Published under the GNU General Public License V.2, see file COPYING */
5 /* this file contains the source for opening addresses stdio type */
7 #include "xiosysincludes.h"
8 #include "xioopen.h"
10 #include "xio-fdnum.h"
11 #include "xio-stdio.h"
14 #if WITH_STDIO
16 static int xioopen_stdio(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, const struct addrdesc *addrdesc);
17 static int xioopen_stdfd(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
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 const struct addrdesc xioaddr_stdio = { "STDIO", 3, xioopen_stdio, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_FILE|GROUP_SOCKET|GROUP_TERMIOS|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP, 0, 0, 0 HELP(NULL) };
24 const struct addrdesc xioaddr_stdin = { "STDIN", 1, xioopen_stdfd, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_FILE|GROUP_SOCKET|GROUP_TERMIOS|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP, 0, 0, 0 HELP(NULL) };
25 const struct addrdesc xioaddr_stdout = { "STDOUT", 2, xioopen_stdfd, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_FILE|GROUP_SOCKET|GROUP_TERMIOS|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP, 1, 0, 0 HELP(NULL) };
26 const struct addrdesc xioaddr_stderr = { "STDERR", 2, xioopen_stdfd, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_FILE|GROUP_SOCKET|GROUP_TERMIOS|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP, 2, 0, 0 HELP(NULL) };
29 /* process a bidirectional "stdio" or "-" argument with options.
30 generate a dual address. */
31 int xioopen_stdio_bi(xiofile_t *sock) {
32 struct opt *optspr;
33 groups_t groups1 = xioaddr_stdio.groups;
34 int result;
36 if (xioopen_makedual(sock) < 0) {
37 return -1;
40 sock->dual.stream[0]->tag = XIO_TAG_RDONLY;
41 sock->dual.stream[0]->fd = 0 /*stdin*/;
42 sock->dual.stream[1]->tag = XIO_TAG_WRONLY;
43 sock->dual.stream[1]->fd = 1 /*stdout*/;
44 if (sock->dual.stream[0]->howtoend == END_UNSPEC)
45 sock->dual.stream[0]->howtoend = END_NONE;
46 if (sock->dual.stream[1]->howtoend == END_UNSPEC)
47 sock->dual.stream[1]->howtoend = END_NONE;
49 #if WITH_TERMIOS
50 if (Isatty(sock->dual.stream[0]->fd)) {
51 if (Tcgetattr(sock->dual.stream[0]->fd,
52 &sock->dual.stream[0]->savetty)
53 < 0) {
54 Warn2("cannot query current terminal settings on fd %d: %s",
55 sock->dual.stream[0]->fd, strerror(errno));
56 } else {
57 sock->dual.stream[0]->ttyvalid = true;
60 if (Isatty(sock->dual.stream[1]->fd)) {
61 if (Tcgetattr(sock->dual.stream[1]->fd,
62 &sock->dual.stream[1]->savetty)
63 < 0) {
64 Warn2("cannot query current terminal settings on fd %d: %s",
65 sock->dual.stream[1]->fd, strerror(errno));
66 } else {
67 sock->dual.stream[1]->ttyvalid = true;
70 #endif /* WITH_TERMIOS */
72 /* options here are one-time and one-direction, no second use */
73 retropt_bool(sock->stream.opts, OPT_IGNOREEOF, &sock->dual.stream[0]->ignoreeof);
75 /* extract opts that should be applied only once */
76 if ((optspr = copyopts(sock->stream.opts, GROUP_PROCESS)) == NULL) {
77 return -1;
79 /* here we copy opts, because most have to be applied twice! */
80 if ((sock->dual.stream[1]->opts = copyopts(sock->stream.opts, GROUP_FD|GROUP_APPL|(groups1&~GROUP_PROCESS))) == NULL) {
81 return -1;
83 sock->dual.stream[0]->opts = sock->stream.opts;
84 sock->stream.opts = NULL;
86 if (applyopts_single(sock->dual.stream[0],
87 sock->dual.stream[0]->opts, PH_INIT)
88 < 0)
89 return -1;
90 if (applyopts_single(sock->dual.stream[1],
91 sock->dual.stream[1]->opts, PH_INIT)
92 < 0)
93 return -1;
94 applyopts(sock->dual.stream[0], -1, sock->dual.stream[0]->opts, PH_INIT);
95 applyopts(sock->dual.stream[1], -1, sock->dual.stream[1]->opts, PH_INIT);
96 if ((result = applyopts(NULL, -1, optspr, PH_EARLY)) < 0)
97 return result;
98 if ((result = applyopts(NULL, -1, optspr, PH_PREOPEN)) < 0)
99 return result;
101 /* apply options to first FD */
102 if ((result =
103 applyopts(sock->dual.stream[0], -1,
104 sock->dual.stream[0]->opts, PH_ALL))
105 < 0) {
106 return result;
108 if ((result = _xio_openlate(sock->dual.stream[0],
109 sock->dual.stream[0]->opts)) < 0) {
110 return result;
112 #if 0
113 /* ignore this opt */
114 retropt_bool(sock->dual.stream[0]->opts, OPT_COOL_WRITE);
115 #endif
117 /* apply options to second FD */
118 if ((result = applyopts(sock->dual.stream[1], -1,
119 sock->dual.stream[1]->opts, PH_ALL)) < 0) {
120 return result;
122 if ((result = _xio_openlate(sock->dual.stream[1],
123 sock->dual.stream[1]->opts)) < 0) {
124 return result;
127 #if 0
128 if ((result = _xio_openlate(sock->dual.stream[1], optspr)) < 0) {
129 return result;
131 #endif
133 Notice("reading from and writing to stdio");
134 return 0;
138 /* wrap around unidirectional xioopensingle and xioopen_fd to automatically determine stdin or stdout fd depending on rw.
139 Do not set FD_CLOEXEC flag. */
140 static int xioopen_stdio(
141 int argc,
142 const char *argv[],
143 struct opt *opts,
144 int xioflags,
145 xiofile_t *fd,
146 const struct addrdesc *addrdesc)
148 int rw = (xioflags&XIO_ACCMODE);
150 if (argc != 1) {
151 Error2("%s: wrong number of parameters (%d instead of 0)", argv[0], argc-1);
154 if (rw == XIO_RDWR) {
155 return xioopen_stdio_bi(fd);
158 Notice2("using %s for %s",
159 &("stdin\0\0\0stdout"[rw<<3]),
160 ddirection[rw]);
161 return xioopen_fd(opts, rw, &fd->stream, rw);
164 /* wrap around unidirectional xioopensingle and xioopen_fd to automatically determine stdin or stdout fd depending on rw.
165 Do not set FD_CLOEXEC flag. */
166 static int xioopen_stdfd(
167 int argc,
168 const char *argv[],
169 struct opt *opts,
170 int xioflags,
171 xiofile_t *xfd,
172 const struct addrdesc *addrdesc)
174 int rw = (xioflags&XIO_ACCMODE);
175 int fd = addrdesc->arg1;
177 if (argc != 1) {
178 Error2("%s: wrong number of parameters (%d instead of 0)", argv[0], argc-1);
180 Notice2("using %s for %s",
181 &("stdin\0\0\0stdout\0\0stderr"[fd<<3]),
182 ddirection[rw]);
183 return xioopen_fd(opts, rw, &xfd->stream, fd);
185 #endif /* WITH_STDIO */