version 1.7.3.0
[socat.git] / xio-pipe.c
blob3e6a11786bcff7b52be921b4b0bce122b3f1a94b
1 /* source: xio-pipe.c */
2 /* Copyright Gerhard Rieger */
3 /* Published under the GNU General Public License V.2, see file COPYING */
5 /* this file contains the source for opening addresses of pipe type */
7 #include "xiosysincludes.h"
8 #include "xioopen.h"
10 #include "xio-named.h"
13 #if WITH_PIPE
15 static int xioopen_fifo(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3);
16 static int xioopen_fifo_unnamed(xiofile_t *sock, struct opt *opts);
19 const struct addrdesc addr_pipe = { "pipe", 3, xioopen_fifo, GROUP_FD|GROUP_NAMED|GROUP_OPEN|GROUP_FIFO, 0, 0, 0 HELP(":<filename>") };
22 /* process an unnamed bidirectional "pipe" or "fifo" or "echo" argument with
23 options */
24 static int xioopen_fifo_unnamed(xiofile_t *sock, struct opt *opts) {
25 struct opt *opts2;
26 int filedes[2];
27 int numleft;
28 int result;
30 if (applyopts_single(&sock->stream, opts, PH_INIT) < 0) return -1;
31 applyopts(-1, opts, PH_INIT);
33 if (Pipe(filedes) != 0) {
34 Error2("pipe(%p): %s", filedes, strerror(errno));
35 return -1;
37 /*0 Info2("pipe({%d,%d})", filedes[0], filedes[1]);*/
39 sock->common.tag = XIO_TAG_RDWR;
40 sock->stream.dtype = XIODATA_PIPE;
41 sock->stream.fd = filedes[0];
42 sock->stream.para.bipipe.fdout = filedes[1];
43 applyopts_cloexec(sock->stream.fd, opts);
44 applyopts_cloexec(sock->stream.para.bipipe.fdout, opts);
46 /* one-time and input-direction options, no second application */
47 retropt_bool(opts, OPT_IGNOREEOF, &sock->stream.ignoreeof);
49 /* here we copy opts! */
50 if ((opts2 = copyopts(opts, GROUP_FIFO)) == NULL) {
51 return STAT_NORETRY;
54 /* apply options to first FD */
55 if ((result = applyopts(sock->stream.fd, opts, PH_ALL)) < 0) {
56 return result;
58 if ((result = applyopts_single(&sock->stream, opts, PH_ALL)) < 0) {
59 return result;
62 /* apply options to second FD */
63 if ((result = applyopts(sock->stream.para.bipipe.fdout, opts2, PH_ALL)) < 0)
65 return result;
68 if ((numleft = leftopts(opts)) > 0) {
69 Error1("%d option(s) could not be used", numleft);
70 showleft(opts);
72 Notice("writing to and reading from unnamed pipe");
73 return 0;
77 /* open a named or unnamed pipe/fifo */
78 static int xioopen_fifo(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3) {
79 const char *pipename = argv[1];
80 int rw = (xioflags & XIO_ACCMODE);
81 #if HAVE_STAT64
82 struct stat64 pipstat;
83 #else
84 struct stat pipstat;
85 #endif /* !HAVE_STAT64 */
86 bool opt_unlink_early = false;
87 bool opt_unlink_close = true;
88 mode_t mode = 0666;
89 int result;
91 if (argc == 1) {
92 return xioopen_fifo_unnamed(fd, fd->stream.opts);
95 if (argc != 2) {
96 Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1);
99 if (applyopts_single(&fd->stream, opts, PH_INIT) < 0) return -1;
100 applyopts(-1, opts, PH_INIT);
102 retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early);
103 applyopts_named(pipename, opts, PH_EARLY); /* umask! */
104 applyopts(-1, opts, PH_EARLY);
106 if (opt_unlink_early) {
107 if (Unlink(pipename) < 0) {
108 if (errno == ENOENT) {
109 Warn2("unlink(%s): %s", pipename, strerror(errno));
110 } else {
111 Error2("unlink(%s): %s", pipename, strerror(errno));
112 return STAT_RETRYLATER;
117 retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
118 retropt_modet(opts, OPT_PERM, &mode);
119 if (applyopts_named(pipename, opts, PH_EARLY) < 0) {
120 return STAT_RETRYLATER;
122 if (applyopts_named(pipename, opts, PH_PREOPEN) < 0) {
123 return STAT_RETRYLATER;
125 if (
126 #if HAVE_STAT64
127 Stat64(pipename, &pipstat) < 0
128 #else
129 Stat(pipename, &pipstat) < 0
130 #endif /* !HAVE_STAT64 */
132 if (errno != ENOENT) {
133 Error3("stat(\"%s\", %p): %s", pipename, &pipstat, strerror(errno));
134 } else {
135 Debug1("xioopen_fifo(\"%s\"): does not exist, creating fifo", pipename);
136 #if 0
137 result = Mknod(pipename, S_IFIFO|mode, 0);
138 if (result < 0) {
139 Error3("mknod(%s, %d, 0): %s", pipename, mode, strerror(errno));
140 return STAT_RETRYLATER;
142 #else
143 result = Mkfifo(pipename, mode);
144 if (result < 0) {
145 Error3("mkfifo(%s, %d): %s", pipename, mode, strerror(errno));
146 return STAT_RETRYLATER;
148 #endif
149 Notice2("created named pipe \"%s\" for %s", pipename, ddirection[rw]);
150 applyopts_named(pipename, opts, PH_ALL);
153 if (opt_unlink_close) {
154 if ((fd->stream.unlink_close = strdup(pipename)) == NULL) {
155 Error1("strdup(\"%s\"): out of memory", pipename);
157 fd->stream.opt_unlink_close = true;
159 } else {
160 /* exists */
161 Debug1("xioopen_fifo(\"%s\"): already exist, opening it", pipename);
162 Notice3("opening %s \"%s\" for %s",
163 filetypenames[(pipstat.st_mode&S_IFMT)>>12],
164 pipename, ddirection[rw]);
165 /*applyopts_early(pipename, opts);*/
166 applyopts_named(pipename, opts, PH_EARLY);
169 if ((result = _xioopen_open(pipename, rw, opts)) < 0) {
170 return result;
172 fd->stream.fd = result;
174 applyopts_named(pipename, opts, PH_FD);
175 applyopts(fd->stream.fd, opts, PH_FD);
176 applyopts_cloexec(fd->stream.fd, opts);
177 return _xio_openlate(&fd->stream, opts);
180 #endif /* WITH_PIPE */