mirror of
https://github.com/moparisthebest/socat
synced 2024-12-21 22:48:48 -05:00
EXEC and SYSTEM with stderr injected socat messages into the data stream
This commit is contained in:
parent
c4751d50ec
commit
ad4bd0d9db
3
CHANGES
3
CHANGES
@ -9,6 +9,9 @@ corrections:
|
|||||||
|
|
||||||
corrected a few mistakes that caused compiler warnings on 64bit hosts
|
corrected a few mistakes that caused compiler warnings on 64bit hosts
|
||||||
|
|
||||||
|
EXEC and SYSTEM with stderr injected socat messages into the data
|
||||||
|
stream. test: EXECSTDERRLOG
|
||||||
|
|
||||||
####################### V 1.6.0.1:
|
####################### V 1.6.0.1:
|
||||||
|
|
||||||
new features:
|
new features:
|
||||||
|
2
VERSION
2
VERSION
@ -1 +1 @@
|
|||||||
"1.6.0.1+ip4bind+recvfromfork+x64"
|
"1.6.0.1+ip4bind+recvfromfork+x64+execstderr"
|
||||||
|
67
error.c
67
error.c
@ -39,7 +39,6 @@ struct diag_opts {
|
|||||||
const char *progname;
|
const char *progname;
|
||||||
int msglevel;
|
int msglevel;
|
||||||
int exitlevel;
|
int exitlevel;
|
||||||
int logstderr;
|
|
||||||
int syslog;
|
int syslog;
|
||||||
FILE *logfile;
|
FILE *logfile;
|
||||||
int logfacility;
|
int logfacility;
|
||||||
@ -51,7 +50,7 @@ struct diag_opts {
|
|||||||
|
|
||||||
|
|
||||||
struct diag_opts diagopts =
|
struct diag_opts diagopts =
|
||||||
{ NULL, E_ERROR, E_ERROR, 1, 0, NULL, LOG_DAEMON, false, 0 } ;
|
{ NULL, E_ERROR, E_ERROR, 0, NULL, LOG_DAEMON, false, 0 } ;
|
||||||
|
|
||||||
static void _msg(int level, const char *buff, const char *syslp);
|
static void _msg(int level, const char *buff, const char *syslp);
|
||||||
|
|
||||||
@ -89,7 +88,21 @@ static struct wordent facilitynames[] = {
|
|||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
static int diaginitialized;
|
||||||
|
static int diag_init(void) {
|
||||||
|
if (diaginitialized) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
diaginitialized = 1;
|
||||||
|
/* gcc with GNU libc refuses to set this in the initializer */
|
||||||
|
diagopts.logfile = stderr;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#define DIAG_INIT ((void)(diaginitialized || diag_init()))
|
||||||
|
|
||||||
|
|
||||||
void diag_set(char what, const char *arg) {
|
void diag_set(char what, const char *arg) {
|
||||||
|
DIAG_INIT;
|
||||||
switch (what) {
|
switch (what) {
|
||||||
const struct wordent *keywd;
|
const struct wordent *keywd;
|
||||||
|
|
||||||
@ -104,14 +117,24 @@ void diag_set(char what, const char *arg) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
openlog(diagopts.progname, LOG_PID, diagopts.logfacility);
|
openlog(diagopts.progname, LOG_PID, diagopts.logfacility);
|
||||||
diagopts.logstderr = false; break;
|
if (diagopts.logfile != NULL && diagopts.logfile != stderr) {
|
||||||
case 'f': if ((diagopts.logfile = fopen(arg, "a")) == NULL) {
|
fclose(diagopts.logfile);
|
||||||
|
}
|
||||||
|
diagopts.logfile = NULL;
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
if (diagopts.logfile != NULL && diagopts.logfile != stderr) {
|
||||||
|
fclose(diagopts.logfile);
|
||||||
|
}
|
||||||
|
if ((diagopts.logfile = fopen(arg, "a")) == NULL) {
|
||||||
Error2("cannot open log file \"%s\": %s", arg, strerror(errno));
|
Error2("cannot open log file \"%s\": %s", arg, strerror(errno));
|
||||||
break;
|
break;
|
||||||
} else {
|
|
||||||
diagopts.logstderr = false; break;
|
|
||||||
}
|
}
|
||||||
case 's': diagopts.logstderr = true; break; /* logging to stderr is default */
|
case 's':
|
||||||
|
if (diagopts.logfile != NULL && diagopts.logfile != stderr) {
|
||||||
|
fclose(diagopts.logfile);
|
||||||
|
}
|
||||||
|
diagopts.logfile = stderr; break; /* logging to stderr is default */
|
||||||
case 'p': diagopts.progname = arg;
|
case 'p': diagopts.progname = arg;
|
||||||
openlog(diagopts.progname, LOG_PID, diagopts.logfacility);
|
openlog(diagopts.progname, LOG_PID, diagopts.logfacility);
|
||||||
break;
|
break;
|
||||||
@ -122,6 +145,7 @@ void diag_set(char what, const char *arg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void diag_set_int(char what, int arg) {
|
void diag_set_int(char what, int arg) {
|
||||||
|
DIAG_INIT;
|
||||||
switch (what) {
|
switch (what) {
|
||||||
case 'D': diagopts.msglevel = arg; break;
|
case 'D': diagopts.msglevel = arg; break;
|
||||||
case 'e': diagopts.exitlevel = arg; break;
|
case 'e': diagopts.exitlevel = arg; break;
|
||||||
@ -138,9 +162,10 @@ void diag_set_int(char what, int arg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int diag_get_int(char what) {
|
int diag_get_int(char what) {
|
||||||
|
DIAG_INIT;
|
||||||
switch (what) {
|
switch (what) {
|
||||||
case 'y': return diagopts.syslog;
|
case 'y': return diagopts.syslog;
|
||||||
case 's': return diagopts.logstderr;
|
case 's': return diagopts.logfile == stderr;
|
||||||
case 'd': case 'D': return diagopts.msglevel;
|
case 'd': case 'D': return diagopts.msglevel;
|
||||||
case 'e': return diagopts.exitlevel;
|
case 'e': return diagopts.exitlevel;
|
||||||
}
|
}
|
||||||
@ -148,6 +173,7 @@ int diag_get_int(char what) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char *diag_get_string(char what) {
|
const char *diag_get_string(char what) {
|
||||||
|
DIAG_INIT;
|
||||||
switch (what) {
|
switch (what) {
|
||||||
case 'p': return diagopts.progname;
|
case 'p': return diagopts.progname;
|
||||||
}
|
}
|
||||||
@ -170,6 +196,7 @@ void msg(int level, const char *format, ...) {
|
|||||||
size_t bytes;
|
size_t bytes;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
|
DIAG_INIT;
|
||||||
if (level < diagopts.msglevel) return;
|
if (level < diagopts.msglevel) return;
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
#if HAVE_GETTIMEOFDAY || 1
|
#if HAVE_GETTIMEOFDAY || 1
|
||||||
@ -236,9 +263,6 @@ void msg(int level, const char *format, ...) {
|
|||||||
|
|
||||||
|
|
||||||
static void _msg(int level, const char *buff, const char *syslp) {
|
static void _msg(int level, const char *buff, const char *syslp) {
|
||||||
if (diagopts.logstderr) {
|
|
||||||
fputs(buff, stderr); fflush(stderr);
|
|
||||||
}
|
|
||||||
if (diagopts.syslog) {
|
if (diagopts.syslog) {
|
||||||
/* prevent format string attacks (thanks to CoKi) */
|
/* prevent format string attacks (thanks to CoKi) */
|
||||||
syslog(syslevel[level], "%s", syslp);
|
syslog(syslevel[level], "%s", syslp);
|
||||||
@ -247,3 +271,24 @@ static void _msg(int level, const char *buff, const char *syslp) {
|
|||||||
fputs(buff, diagopts.logfile); fflush(diagopts.logfile);
|
fputs(buff, diagopts.logfile); fflush(diagopts.logfile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* use a new log output file descriptor that is dup'ed from the current one.
|
||||||
|
this is useful when socat logs to stderr but fd 2 should be redirected to
|
||||||
|
serve other purposes */
|
||||||
|
int diag_dup(void) {
|
||||||
|
int newfd;
|
||||||
|
|
||||||
|
DIAG_INIT;
|
||||||
|
if (diagopts.logfile == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
newfd = dup(fileno(diagopts.logfile));
|
||||||
|
if (diagopts.logfile != stderr) {
|
||||||
|
fclose(diagopts.logfile);
|
||||||
|
}
|
||||||
|
if (newfd >= 0) {
|
||||||
|
diagopts.logfile = fdopen(newfd, "w");
|
||||||
|
}
|
||||||
|
return newfd;
|
||||||
|
}
|
||||||
|
5
error.h
5
error.h
@ -1,5 +1,5 @@
|
|||||||
/* source: error.h */
|
/* source: error.h */
|
||||||
/* Copyright Gerhard Rieger 2001-2007 */
|
/* Copyright Gerhard Rieger 2001-2008 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
#ifndef __error_h_included
|
#ifndef __error_h_included
|
||||||
@ -202,7 +202,8 @@ extern void diag_set(char what, const char *arg);
|
|||||||
extern void diag_set_int(char what, int arg);
|
extern void diag_set_int(char what, int arg);
|
||||||
extern int diag_get_int(char what);
|
extern int diag_get_int(char what);
|
||||||
extern const char *diag_get_string(char what);
|
extern const char *diag_get_string(char what);
|
||||||
|
extern int diag_dup(void);
|
||||||
|
extern int diag_dup2(int newfd);
|
||||||
extern void msg(int level, const char *format, ...);
|
extern void msg(int level, const char *format, ...);
|
||||||
|
|
||||||
#endif /* !defined(__error_h_included) */
|
#endif /* !defined(__error_h_included) */
|
||||||
|
18
test.sh
18
test.sh
@ -5713,6 +5713,7 @@ esac
|
|||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
|
||||||
|
|
||||||
|
# there was an error in address EXEC with options pipes,stderr
|
||||||
NAME=EXECPIPESSTDERR
|
NAME=EXECPIPESSTDERR
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%functions%*|*%$NAME%*)
|
*%functions%*|*%$NAME%*)
|
||||||
@ -5721,6 +5722,23 @@ testecho "$N" "$TEST" "" "exec:$CAT,pipes,stderr" "$opts"
|
|||||||
esac
|
esac
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
|
||||||
|
# EXEC and SYSTEM with stderr injected socat messages into the data stream.
|
||||||
|
NAME=EXECSTDERRLOG
|
||||||
|
case "$TESTS" in
|
||||||
|
*%functions%*|*%$NAME%*)
|
||||||
|
TEST="$NAME: simple echo via exec of cat with pipes,stderr"
|
||||||
|
SAVE_opts="$opts"
|
||||||
|
# make sure at least two -d are there
|
||||||
|
case "$opts" in
|
||||||
|
*-d*-d*) ;;
|
||||||
|
*-d*) opts="$opts -d" ;;
|
||||||
|
*) opts="-d -d" ;;
|
||||||
|
esac
|
||||||
|
testecho "$N" "$TEST" "" "exec:$CAT,pipes,stderr" "$opts"
|
||||||
|
opts="$SAVE_opts"
|
||||||
|
esac
|
||||||
|
N=$((N+1))
|
||||||
|
|
||||||
|
|
||||||
NAME=SIMPLEPARSE
|
NAME=SIMPLEPARSE
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
|
10
xio-exec.c
10
xio-exec.c
@ -1,5 +1,5 @@
|
|||||||
/* source: xio-exec.c */
|
/* source: xio-exec.c */
|
||||||
/* Copyright Gerhard Rieger 2001-2006 */
|
/* Copyright Gerhard Rieger 2001-2008 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
/* this file contains the source for opening addresses of exec type */
|
/* this file contains the source for opening addresses of exec type */
|
||||||
@ -32,6 +32,7 @@ static int xioopen_exec(int argc, const char *argv[], struct opt *opts,
|
|||||||
) {
|
) {
|
||||||
int status;
|
int status;
|
||||||
bool dash = false;
|
bool dash = false;
|
||||||
|
int duptostderr;
|
||||||
|
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
Error3("\"%s:%s\": wrong number of parameters (%d instead of 1)", argv[0], argv[1], argc-1);
|
Error3("\"%s:%s\": wrong number of parameters (%d instead of 1)", argv[0], argv[1], argc-1);
|
||||||
@ -39,7 +40,7 @@ static int xioopen_exec(int argc, const char *argv[], struct opt *opts,
|
|||||||
|
|
||||||
retropt_bool(opts, OPT_DASH, &dash);
|
retropt_bool(opts, OPT_DASH, &dash);
|
||||||
|
|
||||||
status = _xioopen_foxec(xioflags, &fd->stream, groups, &opts);
|
status = _xioopen_foxec(xioflags, &fd->stream, groups, &opts, &duptostderr);
|
||||||
if (status < 0) return status;
|
if (status < 0) return status;
|
||||||
if (status == 0) { /* child */
|
if (status == 0) { /* child */
|
||||||
const char *ends[] = { " ", NULL };
|
const char *ends[] = { " ", NULL };
|
||||||
@ -118,6 +119,11 @@ static int xioopen_exec(int argc, const char *argv[], struct opt *opts,
|
|||||||
return STAT_NORETRY;
|
return STAT_NORETRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* only now redirect stderr */
|
||||||
|
if (duptostderr >= 0) {
|
||||||
|
diag_dup();
|
||||||
|
Dup2(duptostderr, 2);
|
||||||
|
}
|
||||||
Notice1("execvp'ing \"%s\"", token);
|
Notice1("execvp'ing \"%s\"", token);
|
||||||
result = Execvp(token, pargv);
|
result = Execvp(token, pargv);
|
||||||
/* here we come only if execvp() failed */
|
/* here we come only if execvp() failed */
|
||||||
|
@ -44,7 +44,8 @@ const struct optdesc opt_sigquit = { "sigquit", NULL, OPT_SIGQUIT, GROUP_P
|
|||||||
int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
||||||
struct single *fd,
|
struct single *fd,
|
||||||
unsigned groups,
|
unsigned groups,
|
||||||
struct opt **copts /* in: opts; out: opts for child */
|
struct opt **copts, /* in: opts; out: opts for child */
|
||||||
|
int *duptostderr /* out: redirect stderr to output fd */
|
||||||
) {
|
) {
|
||||||
struct opt *popts; /* parent process options */
|
struct opt *popts; /* parent process options */
|
||||||
int numleft;
|
int numleft;
|
||||||
@ -261,7 +262,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||||||
}
|
}
|
||||||
if (tn == NULL) {
|
if (tn == NULL) {
|
||||||
Error("could not open pty");
|
Error("could not open pty");
|
||||||
return STAT_NORETRY;
|
return -1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
Info1("opened pseudo terminal %s", tn);
|
Info1("opened pseudo terminal %s", tn);
|
||||||
@ -280,7 +281,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||||||
#endif /* HAVE_OPENPTY */
|
#endif /* HAVE_OPENPTY */
|
||||||
free(*copts);
|
free(*copts);
|
||||||
if ((*copts = moveopts(popts, GROUP_TERMIOS|GROUP_FORK|GROUP_EXEC|GROUP_PROCESS)) == NULL) {
|
if ((*copts = moveopts(popts, GROUP_TERMIOS|GROUP_FORK|GROUP_EXEC|GROUP_PROCESS)) == NULL) {
|
||||||
return STAT_RETRYLATER;
|
return -1;
|
||||||
}
|
}
|
||||||
applyopts_cloexec(ptyfd, popts);/*!*/
|
applyopts_cloexec(ptyfd, popts);/*!*/
|
||||||
/* exec:...,pty did not kill child process under some circumstances */
|
/* exec:...,pty did not kill child process under some circumstances */
|
||||||
@ -307,7 +308,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||||||
if (rw != XIO_WRONLY) {
|
if (rw != XIO_WRONLY) {
|
||||||
if (Pipe(rdpip) < 0) {
|
if (Pipe(rdpip) < 0) {
|
||||||
Error2("pipe(%p): %s", rdpip, strerror(errno));
|
Error2("pipe(%p): %s", rdpip, strerror(errno));
|
||||||
return STAT_RETRYLATER;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*0 Info2("pipe({%d,%d})", rdpip[0], rdpip[1]);*/
|
/*0 Info2("pipe({%d,%d})", rdpip[0], rdpip[1]);*/
|
||||||
@ -315,7 +316,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||||||
free(*copts);
|
free(*copts);
|
||||||
if ((*copts = moveopts(popts, GROUP_FORK|GROUP_EXEC|GROUP_PROCESS))
|
if ((*copts = moveopts(popts, GROUP_FORK|GROUP_EXEC|GROUP_PROCESS))
|
||||||
== NULL) {
|
== NULL) {
|
||||||
return STAT_RETRYLATER;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
popts2 = copyopts(popts, GROUP_ALL);
|
popts2 = copyopts(popts, GROUP_ALL);
|
||||||
@ -330,7 +331,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||||||
if (rw != XIO_RDONLY) {
|
if (rw != XIO_RDONLY) {
|
||||||
if (Pipe(wrpip) < 0) {
|
if (Pipe(wrpip) < 0) {
|
||||||
Error2("pipe(%p): %s", wrpip, strerror(errno));
|
Error2("pipe(%p): %s", wrpip, strerror(errno));
|
||||||
return STAT_RETRYLATER;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*0 Info2("pipe({%d,%d})", wrpip[0], wrpip[1]);*/
|
/*0 Info2("pipe({%d,%d})", wrpip[0], wrpip[1]);*/
|
||||||
@ -364,13 +365,13 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
Error5("socketpair(%d, %d, %d, %p): %s",
|
Error5("socketpair(%d, %d, %d, %p): %s",
|
||||||
d, type, protocol, sv, strerror(errno));
|
d, type, protocol, sv, strerror(errno));
|
||||||
return STAT_RETRYLATER;
|
return -1;
|
||||||
}
|
}
|
||||||
/*0 Info5("socketpair(%d, %d, %d, {%d,%d})",
|
/*0 Info5("socketpair(%d, %d, %d, {%d,%d})",
|
||||||
d, type, protocol, sv[0], sv[1]);*/
|
d, type, protocol, sv[0], sv[1]);*/
|
||||||
free(*copts);
|
free(*copts);
|
||||||
if ((*copts = moveopts(popts, GROUP_FORK|GROUP_EXEC|GROUP_PROCESS)) == NULL) {
|
if ((*copts = moveopts(popts, GROUP_FORK|GROUP_EXEC|GROUP_PROCESS)) == NULL) {
|
||||||
return STAT_RETRYLATER;
|
return -1;
|
||||||
}
|
}
|
||||||
applyopts(sv[0], *copts, PH_PASTSOCKET);
|
applyopts(sv[0], *copts, PH_PASTSOCKET);
|
||||||
applyopts(sv[1], popts, PH_PASTSOCKET);
|
applyopts(sv[1], popts, PH_PASTSOCKET);
|
||||||
@ -397,7 +398,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||||||
if (applyopts_single(fd, popts, PH_LATE) < 0) return -1;
|
if (applyopts_single(fd, popts, PH_LATE) < 0) return -1;
|
||||||
}
|
}
|
||||||
/*0 if ((optpr = copyopts(*copts, GROUP_PROCESS)) == NULL)
|
/*0 if ((optpr = copyopts(*copts, GROUP_PROCESS)) == NULL)
|
||||||
return STAT_RETRYLATER;*/
|
return -1;*/
|
||||||
retropt_bool(*copts, OPT_STDERR, &withstderr);
|
retropt_bool(*copts, OPT_STDERR, &withstderr);
|
||||||
|
|
||||||
xiosetchilddied(); /* set SIGCHLD handler */
|
xiosetchilddied(); /* set SIGCHLD handler */
|
||||||
@ -409,7 +410,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||||||
pid = Fork();
|
pid = Fork();
|
||||||
if (pid < 0) {
|
if (pid < 0) {
|
||||||
Error1("fork(): %s", strerror(errno));
|
Error1("fork(): %s", strerror(errno));
|
||||||
return STAT_RETRYLATER;
|
return -1;
|
||||||
}
|
}
|
||||||
/* gdb recommends to have env controlled sleep after fork */
|
/* gdb recommends to have env controlled sleep after fork */
|
||||||
if (forkwaitstring = getenv("SOCAT_FORK_WAIT")) {
|
if (forkwaitstring = getenv("SOCAT_FORK_WAIT")) {
|
||||||
@ -438,13 +439,13 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||||||
if (rw != XIO_RDONLY && fdi != ttyfd) {
|
if (rw != XIO_RDONLY && fdi != ttyfd) {
|
||||||
if (Dup2(ttyfd, fdi) < 0) {
|
if (Dup2(ttyfd, fdi) < 0) {
|
||||||
Error3("dup2(%d, %d): %s", ttyfd, fdi, strerror(errno));
|
Error3("dup2(%d, %d): %s", ttyfd, fdi, strerror(errno));
|
||||||
return STAT_RETRYLATER; }
|
return -1; }
|
||||||
/*0 Info2("dup2(%d, %d)", ttyfd, fdi);*/
|
/*0 Info2("dup2(%d, %d)", ttyfd, fdi);*/
|
||||||
}
|
}
|
||||||
if (rw != XIO_WRONLY && fdo != ttyfd) {
|
if (rw != XIO_WRONLY && fdo != ttyfd) {
|
||||||
if (Dup2(ttyfd, fdo) < 0) {
|
if (Dup2(ttyfd, fdo) < 0) {
|
||||||
Error3("dup2(%d, %d): %s", ttyfd, fdo, strerror(errno));
|
Error3("dup2(%d, %d): %s", ttyfd, fdo, strerror(errno));
|
||||||
return STAT_RETRYLATER; }
|
return -1; }
|
||||||
/*0 Info2("dup2(%d, %d)", ttyfd, fdo);*/
|
/*0 Info2("dup2(%d, %d)", ttyfd, fdo);*/
|
||||||
}
|
}
|
||||||
if ((rw == XIO_RDONLY || fdi != ttyfd) &&
|
if ((rw == XIO_RDONLY || fdi != ttyfd) &&
|
||||||
@ -466,7 +467,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||||||
if (fdi == rdpip[1]) { /* a conflict here */
|
if (fdi == rdpip[1]) { /* a conflict here */
|
||||||
if ((tmpi = Dup(wrpip[0])) < 0) {
|
if ((tmpi = Dup(wrpip[0])) < 0) {
|
||||||
Error2("dup(%d): %s", wrpip[0], strerror(errno));
|
Error2("dup(%d): %s", wrpip[0], strerror(errno));
|
||||||
return STAT_RETRYLATER;
|
return -1;
|
||||||
}
|
}
|
||||||
/*0 Info2("dup(%d) -> %d", wrpip[0], tmpi);*/
|
/*0 Info2("dup(%d) -> %d", wrpip[0], tmpi);*/
|
||||||
rdpip[1] = tmpi;
|
rdpip[1] = tmpi;
|
||||||
@ -474,7 +475,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||||||
if (fdo == wrpip[0]) { /* a conflict here */
|
if (fdo == wrpip[0]) { /* a conflict here */
|
||||||
if ((tmpo = Dup(rdpip[1])) < 0) {
|
if ((tmpo = Dup(rdpip[1])) < 0) {
|
||||||
Error2("dup(%d): %s", rdpip[1], strerror(errno));
|
Error2("dup(%d): %s", rdpip[1], strerror(errno));
|
||||||
return STAT_RETRYLATER;
|
return -1;
|
||||||
}
|
}
|
||||||
/*0 Info2("dup(%d) -> %d", rdpip[1], tmpo);*/
|
/*0 Info2("dup(%d) -> %d", rdpip[1], tmpo);*/
|
||||||
wrpip[0] = tmpo;
|
wrpip[0] = tmpo;
|
||||||
@ -483,7 +484,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||||||
if (rw != XIO_WRONLY && rdpip[1] != fdo) {
|
if (rw != XIO_WRONLY && rdpip[1] != fdo) {
|
||||||
if (Dup2(rdpip[1], fdo) < 0) {
|
if (Dup2(rdpip[1], fdo) < 0) {
|
||||||
Error3("dup2(%d, %d): %s", rdpip[1], fdo, strerror(errno));
|
Error3("dup2(%d, %d): %s", rdpip[1], fdo, strerror(errno));
|
||||||
return STAT_RETRYLATER;
|
return -1;
|
||||||
}
|
}
|
||||||
Close(rdpip[1]);
|
Close(rdpip[1]);
|
||||||
/*0 Info2("dup2(%d, %d)", rdpip[1], fdo);*/
|
/*0 Info2("dup2(%d, %d)", rdpip[1], fdo);*/
|
||||||
@ -492,7 +493,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||||||
if (rw != XIO_RDONLY && wrpip[0] != fdi) {
|
if (rw != XIO_RDONLY && wrpip[0] != fdi) {
|
||||||
if (Dup2(wrpip[0], fdi) < 0) {
|
if (Dup2(wrpip[0], fdi) < 0) {
|
||||||
Error3("dup2(%d, %d): %s", wrpip[0], fdi, strerror(errno));
|
Error3("dup2(%d, %d): %s", wrpip[0], fdi, strerror(errno));
|
||||||
return STAT_RETRYLATER;
|
return -1;
|
||||||
}
|
}
|
||||||
Close(wrpip[0]);
|
Close(wrpip[0]);
|
||||||
/*0 Info2("dup2(%d, %d)", wrpip[0], fdi);*/
|
/*0 Info2("dup2(%d, %d)", wrpip[0], fdi);*/
|
||||||
@ -509,13 +510,13 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||||||
if (rw != XIO_RDONLY && fdi != sv[1]) {
|
if (rw != XIO_RDONLY && fdi != sv[1]) {
|
||||||
if (Dup2(sv[1], fdi) < 0) {
|
if (Dup2(sv[1], fdi) < 0) {
|
||||||
Error3("dup2(%d, %d): %s", sv[1], fdi, strerror(errno));
|
Error3("dup2(%d, %d): %s", sv[1], fdi, strerror(errno));
|
||||||
return STAT_RETRYLATER; }
|
return -1; }
|
||||||
/*0 Info2("dup2(%d, %d)", sv[1], fdi);*/
|
/*0 Info2("dup2(%d, %d)", sv[1], fdi);*/
|
||||||
}
|
}
|
||||||
if (rw != XIO_WRONLY && fdo != sv[1]) {
|
if (rw != XIO_WRONLY && fdo != sv[1]) {
|
||||||
if (Dup2(sv[1], fdo) < 0) {
|
if (Dup2(sv[1], fdo) < 0) {
|
||||||
Error3("dup2(%d, %d): %s", sv[1], fdo, strerror(errno));
|
Error3("dup2(%d, %d): %s", sv[1], fdo, strerror(errno));
|
||||||
return STAT_RETRYLATER; }
|
return -1; }
|
||||||
/*0 Info2("dup2(%d, %d)", sv[1], fdo);*/
|
/*0 Info2("dup2(%d, %d)", sv[1], fdo);*/
|
||||||
}
|
}
|
||||||
if (fdi != sv[1] && fdo != sv[1]) {
|
if (fdi != sv[1] && fdo != sv[1]) {
|
||||||
@ -530,36 +531,6 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||||||
applyopts(-1, *copts, PH_LATE);
|
applyopts(-1, *copts, PH_LATE);
|
||||||
applyopts(-1, *copts, PH_LATE2);
|
applyopts(-1, *copts, PH_LATE2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* what to do with stderr? */
|
|
||||||
if (withstderr) {
|
|
||||||
/* handle it just like ordinary process output, i.e. copy output fd */
|
|
||||||
if (!withfork) {
|
|
||||||
if (Dup2(fdo, 2) < 0) {
|
|
||||||
Error2("dup2(%d, 2): %s", fdo, strerror(errno));
|
|
||||||
}
|
|
||||||
/*0 Info1("dup2(%d, 2)", fdo);*/
|
|
||||||
} else
|
|
||||||
#if HAVE_PTY
|
|
||||||
if (usepty) {
|
|
||||||
if (Dup2(ttyfd, 2) < 0) {
|
|
||||||
Error2("dup2(%d, 2): %s", ttyfd, strerror(errno));
|
|
||||||
}
|
|
||||||
/*0 Info1("dup2(%d, 2)", ttyfd);*/
|
|
||||||
} else
|
|
||||||
#endif /* HAVE_PTY */
|
|
||||||
if (usepipes) {
|
|
||||||
if (Dup2(/*rdpip[1]*/ fdo, 2) < 0) {
|
|
||||||
Error2("dup2(%d, 2): %s", /*rdpip[1]*/ fdo, strerror(errno));
|
|
||||||
}
|
|
||||||
/*0 Info1("dup2(%d, 2)", rdpip[1]);*/
|
|
||||||
} else {
|
|
||||||
if (Dup2(sv[1], 2) < 0) {
|
|
||||||
Error2("dup2(%d, 2): %s", sv[1], strerror(errno));
|
|
||||||
}
|
|
||||||
/*0 Info1("dup2(%d, 2)", sv[1]);*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_xioopen_setdelayeduser();
|
_xioopen_setdelayeduser();
|
||||||
/* set group before user - maybe you are not permitted afterwards */
|
/* set group before user - maybe you are not permitted afterwards */
|
||||||
if (retropt_gidt(*copts, OPT_SETGID, &group) >= 0) {
|
if (retropt_gidt(*copts, OPT_SETGID, &group) >= 0) {
|
||||||
@ -568,6 +539,12 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||||||
if (retropt_uidt(*copts, OPT_SETUID, &user) >= 0) {
|
if (retropt_uidt(*copts, OPT_SETUID, &user) >= 0) {
|
||||||
Setuid(user);
|
Setuid(user);
|
||||||
}
|
}
|
||||||
|
if (withstderr) {
|
||||||
|
*duptostderr = fdo;
|
||||||
|
} else {
|
||||||
|
*duptostderr = -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0; /* indicate child process */
|
return 0; /* indicate child process */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* source: xio-progcall.h */
|
/* source: xio-progcall.h */
|
||||||
/* Copyright Gerhard Rieger 2001-2006 */
|
/* Copyright Gerhard Rieger 2001-2008 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
#ifndef __xio_progcall_h_included
|
#ifndef __xio_progcall_h_included
|
||||||
@ -21,8 +21,11 @@ extern const struct optdesc opt_sigquit;
|
|||||||
extern int _xioopen_foxec(int rw, /* O_RDONLY etc. */
|
extern int _xioopen_foxec(int rw, /* O_RDONLY etc. */
|
||||||
struct single *fd,
|
struct single *fd,
|
||||||
unsigned groups,
|
unsigned groups,
|
||||||
struct opt **opts
|
struct opt **opts,
|
||||||
|
int *duptostderr
|
||||||
);
|
);
|
||||||
extern int setopt_path(struct opt *opts, char **path);
|
extern int setopt_path(struct opt *opts, char **path);
|
||||||
|
extern
|
||||||
|
int _xioopen_redir_stderr(int fdo);
|
||||||
|
|
||||||
#endif /* !defined(__xio_progcall_h_included) */
|
#endif /* !defined(__xio_progcall_h_included) */
|
||||||
|
@ -31,10 +31,11 @@ static int xioopen_system(int argc, const char *argv[], struct opt *opts,
|
|||||||
) {
|
) {
|
||||||
int status;
|
int status;
|
||||||
char *path = NULL;
|
char *path = NULL;
|
||||||
|
int duptostderr;
|
||||||
int result;
|
int result;
|
||||||
const char *string = argv[1];
|
const char *string = argv[1];
|
||||||
|
|
||||||
status = _xioopen_foxec(xioflags, &fd->stream, groups, &opts);
|
status = _xioopen_foxec(xioflags, &fd->stream, groups, &opts, &duptostderr);
|
||||||
if (status < 0) return status;
|
if (status < 0) return status;
|
||||||
if (status == 0) { /* child */
|
if (status == 0) { /* child */
|
||||||
int numleft;
|
int numleft;
|
||||||
@ -50,6 +51,11 @@ static int xioopen_system(int argc, const char *argv[], struct opt *opts,
|
|||||||
return STAT_NORETRY;
|
return STAT_NORETRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* only now redirect stderr */
|
||||||
|
if (duptostderr >= 0) {
|
||||||
|
diag_dup();
|
||||||
|
Dup2(duptostderr, 2);
|
||||||
|
}
|
||||||
Info1("executing shell command \"%s\"", string);
|
Info1("executing shell command \"%s\"", string);
|
||||||
result = System(string);
|
result = System(string);
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
|
Loading…
Reference in New Issue
Block a user