socat/xio-pipe.c

178 lines
5.7 KiB
C
Raw Normal View History

2008-01-27 12:00:08 +00:00
/* $Id: xio-pipe.c,v 1.24 2007/01/25 21:36:11 gerhard Exp $ */
/* Copyright Gerhard Rieger 2001-2007 */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains the source for opening addresses of pipe type */
#include "xiosysincludes.h"
#include "xioopen.h"
#include "xio-named.h"
#if WITH_PIPE
2008-02-24 10:09:01 +00:00
static int xioopen_fifo0(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3);
static int xioopen_fifo1(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3);
2008-01-27 12:00:08 +00:00
2008-02-24 10:09:01 +00:00
static const struct xioaddr_endpoint_desc xioaddr_pipe0 = { XIOADDR_SYS, "pipe", 0, XIOBIT_RDWR, GROUP_FD|GROUP_NAMED|GROUP_OPEN|GROUP_FIFO, XIOSHUT_CLOSE, XIOCLOSE_CLOSE, xioopen_fifo0, 0, 0, 0 HELP("") };
static const struct xioaddr_endpoint_desc xioaddr_pipe1 = { XIOADDR_SYS, "pipe", 1, XIOBIT_ALL, GROUP_FD|GROUP_NAMED|GROUP_OPEN|GROUP_FIFO, XIOSHUT_CLOSE, XIOCLOSE_CLOSE, xioopen_fifo1, 0, 0, 0 HELP(":<filename>") };
2008-01-27 12:00:08 +00:00
2008-02-24 10:09:01 +00:00
const union xioaddr_desc *xioaddrs_pipe[] = {
(union xioaddr_desc *)&xioaddr_pipe0,
(union xioaddr_desc *)&xioaddr_pipe1,
NULL };
2008-01-27 12:00:08 +00:00
/* process an unnamed bidirectional "pipe" or "fifo" or "echo" argument with
options */
2008-02-24 10:09:01 +00:00
static int xioopen_fifo0(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *sock, unsigned groups, int dummy1, int dummy2, int dummy3) {
2008-01-27 12:00:08 +00:00
struct opt *opts2;
int filedes[2];
int numleft;
int result;
if (applyopts_single(&sock->stream, opts, PH_INIT) < 0) return -1;
applyopts(-1, opts, PH_INIT);
if (Pipe(filedes) != 0) {
Error2("pipe(%p): %s", filedes, strerror(errno));
return -1;
}
/*0 Info2("pipe({%d,%d})", filedes[0], filedes[1]);*/
2008-02-24 10:09:01 +00:00
sock->common.tag = XIO_TAG_RDWR;
sock->stream.dtype = XIODATA_2PIPE;
sock->stream.fd1 = filedes[0];
sock->stream.fd2 = filedes[1];
sock->stream.fdtype = FDTYPE_DOUBLE;
applyopts_cloexec(sock->stream.fd1, opts);
applyopts_cloexec(sock->stream.fd2, opts);
2008-01-27 12:00:08 +00:00
/* one-time and input-direction options, no second application */
retropt_bool(opts, OPT_IGNOREEOF, &sock->stream.ignoreeof);
/* here we copy opts! */
if ((opts2 = copyopts(opts, GROUP_FIFO)) == NULL) {
return STAT_NORETRY;
}
/* apply options to first FD */
2008-02-24 10:09:01 +00:00
if ((result = applyopts(sock->stream.fd1, opts, PH_ALL)) < 0) {
2008-01-27 12:00:08 +00:00
return result;
}
if ((result = applyopts_single(&sock->stream, opts, PH_ALL)) < 0) {
return result;
}
/* apply options to second FD */
2008-02-24 10:09:01 +00:00
if ((result = applyopts(sock->stream.fd2, opts2, PH_ALL)) < 0)
2008-01-27 12:00:08 +00:00
{
return result;
}
if ((numleft = leftopts(opts)) > 0) {
Error1("%d option(s) could not be used", numleft);
showleft(opts);
}
Notice("writing to and reading from unnamed pipe");
return 0;
}
/* open a named pipe/fifo */
2008-02-24 10:09:01 +00:00
static int xioopen_fifo1(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3) {
2008-01-27 12:00:08 +00:00
const char *pipename = argv[1];
int rw = (xioflags & XIO_ACCMODE);
#if HAVE_STAT64
struct stat64 pipstat;
#else
struct stat pipstat;
#endif /* !HAVE_STAT64 */
bool opt_unlink_early = false;
bool opt_unlink_close = true;
mode_t mode = 0666;
int result;
if (applyopts_single(&fd->stream, opts, PH_INIT) < 0) return -1;
applyopts(-1, opts, PH_INIT);
retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early);
applyopts(-1, opts, PH_EARLY);
if (opt_unlink_early) {
if (Unlink(pipename) < 0) {
if (errno == ENOENT) {
Warn2("unlink(%s): %s", pipename, strerror(errno));
} else {
Error2("unlink(%s): %s", pipename, strerror(errno));
return STAT_RETRYLATER;
}
}
}
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
retropt_modet(opts, OPT_PERM, &mode);
if (applyopts_named(pipename, opts, PH_EARLY) < 0) {
return STAT_RETRYLATER;
}
if (applyopts_named(pipename, opts, PH_PREOPEN) < 0) {
return STAT_RETRYLATER;
}
if (
#if HAVE_STAT64
Stat64(pipename, &pipstat) < 0
#else
Stat(pipename, &pipstat) < 0
#endif /* !HAVE_STAT64 */
) {
if (errno != ENOENT) {
Error3("stat(\"%s\", %p): %s", pipename, &pipstat, strerror(errno));
} else {
Debug1("xioopen_fifo(\"%s\"): does not exist, creating fifo", pipename);
#if 0
result = Mknod(pipename, S_IFIFO|mode, 0);
if (result < 0) {
Error3("mknod(%s, %d, 0): %s", pipename, mode, strerror(errno));
return STAT_RETRYLATER;
}
#else
result = Mkfifo(pipename, mode);
if (result < 0) {
Error3("mkfifo(%s, %d): %s", pipename, mode, strerror(errno));
return STAT_RETRYLATER;
}
#endif
Notice2("created named pipe \"%s\" for %s", pipename, ddirection[rw]);
}
if (opt_unlink_close) {
if ((fd->stream.unlink_close = strdup(pipename)) == NULL) {
Error1("strdup(\"%s\"): out of memory", pipename);
}
fd->stream.opt_unlink_close = true;
}
} else {
/* exists */
Debug1("xioopen_fifo(\"%s\"): already exist, opening it", pipename);
Notice3("opening %s \"%s\" for %s",
filetypenames[(pipstat.st_mode&S_IFMT)>>12],
pipename, ddirection[rw]);
/*applyopts_early(pipename, opts);*/
applyopts_named(pipename, opts, PH_EARLY);
}
if ((result = _xioopen_open(pipename, rw, opts)) < 0) {
return result;
}
2008-02-24 10:09:01 +00:00
fd->stream.fd1 = result;
fd->stream.fdtype = FDTYPE_SINGLE;
fd->stream.howtoshut = XIOSHUTWR_NONE|XIOSHUTRD_CLOSE;
fd->stream.howtoclose = XIOCLOSE_CLOSE;
2008-01-27 12:00:08 +00:00
applyopts_named(pipename, opts, PH_FD);
2008-02-24 10:09:01 +00:00
applyopts(fd->stream.fd1, opts, PH_FD);
applyopts_cloexec(fd->stream.fd1, opts);
2008-01-27 12:00:08 +00:00
return _xio_openlate(&fd->stream, opts);
}
#endif /* WITH_PIPE */