version 1.7.3.0
[socat.git] / xio-gopen.c
bloba4e2dec79c9dd0688949c954e55424af2049d9fc
1 /* source: xio-gopen.c */
2 /* Copyright Gerhard Rieger 2001-2010 */
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, unsigned groups, int dummy1, int dummy2, int dummy3);
20 const struct addrdesc addr_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(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3) {
23 const char *filename = argv[1];
24 flags_t openflags = (xioflags & XIO_ACCMODE);
25 mode_t st_mode;
26 bool exists;
27 bool opt_unlink_close = false;
28 int result;
30 if ((result =
31 _xioopen_named_early(argc, argv, fd, GROUP_NAMED|groups, &exists, opts)) < 0) {
32 return result;
34 st_mode = result;
36 if (exists) {
37 /* file (or at least named entry) exists */
38 if ((xioflags&XIO_ACCMODE) != XIO_RDONLY) {
39 openflags |= O_APPEND;
41 } else {
42 openflags |= O_CREAT;
45 /* note: when S_ISSOCK was undefined, it always gives 0 */
46 if (exists && S_ISSOCK(st_mode)) {
47 #if WITH_UNIX
48 union sockaddr_union us;
49 socklen_t uslen = sizeof(us);
50 char infobuff[256];
52 Info1("\"%s\" is a socket, connecting to it", filename);
54 result =
55 _xioopen_unix_client(&fd->stream, xioflags, groups, 0, opts, filename);
56 if (result < 0) {
57 return result;
59 applyopts_named(filename, opts, PH_PASTOPEN); /* unlink-late */
61 if (Getsockname(fd->stream.fd, (struct sockaddr *)&us, &uslen) < 0) {
62 Warn4("getsockname(%d, %p, {%d}): %s",
63 fd->stream.fd, &us, uslen, strerror(errno));
64 } else {
65 Notice1("successfully connected via %s",
66 sockaddr_unix_info(&us.un, uslen,
67 infobuff, sizeof(infobuff)));
69 #else
70 Error("\"%s\" is a socket, but UNIX socket support is not compiled in");
71 return -1;
72 #endif /* WITH_UNIX */
74 } else {
75 /* a file name */
77 Info1("\"%s\" is not a socket, open()'ing it", filename);
79 retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
80 if (opt_unlink_close) {
81 if ((fd->stream.unlink_close = strdup(filename)) == NULL) {
82 Error1("strdup(\"%s\"): out of memory", filename);
84 fd->stream.opt_unlink_close = true;
87 Notice3("opening %s \"%s\" for %s",
88 filetypenames[(st_mode&S_IFMT)>>12], filename, ddirection[(xioflags&XIO_ACCMODE)]);
89 if ((result = _xioopen_open(filename, openflags, opts)) < 0)
90 return result;
91 #ifdef I_PUSH
92 if (S_ISCHR(st_mode)) {
93 Ioctl(result, I_PUSH, "ptem");
94 Ioctl(result, I_PUSH, "ldterm");
95 Ioctl(result, I_PUSH, "ttcompat");
97 #endif
98 fd->stream.fd = result;
100 #if WITH_TERMIOS
101 if (Isatty(fd->stream.fd)) {
102 if (Tcgetattr(fd->stream.fd, &fd->stream.savetty) < 0) {
103 Warn2("cannot query current terminal settings on fd %d: %s",
104 fd->stream.fd, strerror(errno));
105 } else {
106 fd->stream.ttyvalid = true;
109 #endif /* WITH_TERMIOS */
110 applyopts_named(filename, opts, PH_FD);
111 applyopts(fd->stream.fd, opts, PH_FD);
112 applyopts_cloexec(fd->stream.fd, opts);
115 if ((result = applyopts2(fd->stream.fd, opts, PH_PASTSOCKET, PH_CONNECTED)) < 0)
116 return result;
118 if ((result = _xio_openlate(&fd->stream, opts)) < 0)
119 return result;
120 return 0;
123 #endif /* WITH_GOPEN */