Version 1.8.0.0
[socat.git] / xio-gopen.c
blobec365805b2da9306f16ba2bff2b8bbe0e4f8c484
1 /* source: xio-gopen.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 of generic open type */
7 #include "xiosysincludes.h"
8 #include "xioopen.h"
10 #include "xio-named.h"
11 #include "xio-unix.h"
12 #include "xio-gopen.h"
15 #if WITH_GOPEN
17 static int xioopen_gopen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, const struct addrdesc *addrdesc);
20 const struct addrdesc xioaddr_gopen = { "GOPEN", 3, xioopen_gopen, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_REG|GROUP_NAMED|GROUP_OPEN|GROUP_FILE|GROUP_TERMIOS|GROUP_SOCKET|GROUP_SOCK_UNIX, 0, 0, 0 HELP(":<filename>") };
22 static int xioopen_gopen(
23 int argc,
24 const char *argv[],
25 struct opt *opts,
26 int xioflags,
27 xiofile_t *xxfd,
28 const struct addrdesc *addrdesc)
30 struct single *sfd = &xxfd->stream;
31 const char *filename = argv[1];
32 flags_t openflags = (xioflags & XIO_ACCMODE);
33 mode_t st_mode;
34 bool exists;
35 bool opt_unlink_close = false;
36 int result;
38 if ((result =
39 _xioopen_named_early(argc, argv, xxfd, GROUP_NAMED|addrdesc->groups, &exists,
40 opts, addrdesc->syntax))
41 < 0) {
42 return result;
44 st_mode = result;
46 if (exists) {
47 /* file (or at least named entry) exists */
48 if ((xioflags&XIO_ACCMODE) != XIO_RDONLY) {
49 openflags |= O_APPEND;
51 } else {
52 openflags |= O_CREAT;
55 /* note: when S_ISSOCK was undefined, it always gives 0 */
56 if (exists && S_ISSOCK(st_mode)) {
57 #if WITH_UNIX
58 union sockaddr_union us;
59 socklen_t uslen = sizeof(us);
60 char infobuff[256];
62 Info1("\"%s\" is a socket, connecting to it", filename);
64 result =
65 _xioopen_unix_client(sfd, xioflags, addrdesc->groups, 0, opts,
66 filename, addrdesc);
67 if (result < 0) {
68 return result;
70 applyopts_named(filename, opts, PH_PASTOPEN); /* unlink-late */
72 if (Getsockname(sfd->fd, (struct sockaddr *)&us, &uslen) < 0) {
73 Warn4("getsockname(%d, %p, {%d}): %s",
74 sfd->fd, &us, uslen, strerror(errno));
75 } else {
76 Notice1("successfully connected via %s",
77 sockaddr_unix_info(&us.un, uslen,
78 infobuff, sizeof(infobuff)));
80 #else
81 Error("\"%s\" is a socket, but UNIX socket support is not compiled in");
82 return -1;
83 #endif /* WITH_UNIX */
85 } else {
86 /* a file name */
88 Info1("\"%s\" is not a socket, open()'ing it", filename);
90 retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
91 if (opt_unlink_close) {
92 if ((sfd->unlink_close = strdup(filename)) == NULL) {
93 Error1("strdup(\"%s\"): out of memory", filename);
95 sfd->opt_unlink_close = true;
98 Notice3("opening %s \"%s\" for %s",
99 filetypenames[(st_mode&S_IFMT)>>12], filename, ddirection[(xioflags&XIO_ACCMODE)]);
100 if ((result = _xioopen_open(filename, openflags, opts)) < 0)
101 return result;
102 #ifdef I_PUSH
103 if (S_ISCHR(st_mode) && Ioctl(result, I_FIND, "ldterm\0") == 0) {
104 Ioctl(result, I_PUSH, "ptem\0\0\0"); /* pad string length ... */
105 Ioctl(result, I_PUSH, "ldterm\0"); /* ... to requirements of ... */
106 Ioctl(result, I_PUSH, "ttcompat"); /* ... AdressSanitizer */
108 #endif
109 sfd->fd = result;
111 #if WITH_TERMIOS
112 if (Isatty(sfd->fd)) {
113 if (Tcgetattr(sfd->fd, &sfd->savetty) < 0) {
114 Warn2("cannot query current terminal settings on fd %d: %s",
115 sfd->fd, strerror(errno));
116 } else {
117 sfd->ttyvalid = true;
120 #endif /* WITH_TERMIOS */
121 applyopts_named(filename, opts, PH_FD);
122 applyopts(sfd, -1, opts, PH_FD);
123 applyopts_cloexec(sfd->fd, opts);
126 if ((result = applyopts2(sfd, -1, opts, PH_PASTSOCKET, PH_CONNECTED)) < 0)
127 return result;
129 if ((result = _xio_openlate(sfd, opts)) < 0)
130 return result;
131 return 0;
134 #endif /* WITH_GOPEN */