mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 15:32:35 +00:00
New option chdir (cd)
This commit is contained in:
parent
e5cbf2feeb
commit
6125ed4e4e
11 changed files with 301 additions and 62 deletions
4
CHANGES
4
CHANGES
|
@ -143,6 +143,10 @@ Features:
|
||||||
Added option res-nsaddr that overrides /etc/resolv.conf nameserver
|
Added option res-nsaddr that overrides /etc/resolv.conf nameserver
|
||||||
address based on an undocumented resolver feature.
|
address based on an undocumented resolver feature.
|
||||||
|
|
||||||
|
New option chdir changes the working directory of the address to the
|
||||||
|
given path, only during the open stage.
|
||||||
|
Tests: CHDIR_ON_CREATE CHDIR_ON_SYSTEM
|
||||||
|
|
||||||
Option umask now applies only during opening of its very address, not
|
Option umask now applies only during opening of its very address, not
|
||||||
for the lifetime of the process; the original umask is restored
|
for the lifetime of the process; the original umask is restored
|
||||||
afterwards.
|
afterwards.
|
||||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
"1.7.4.5+20230721"
|
"1.7.4.5+"
|
||||||
|
|
|
@ -1990,6 +1990,10 @@ These options may be applied to all address types. They change some process
|
||||||
properties that are restored after opening the address.
|
properties that are restored after opening the address.
|
||||||
|
|
||||||
startdit()
|
startdit()
|
||||||
|
label(OPTION_CHDIR)dit(bf(tt(chdir=<filename>))) dit(bf(tt(cd=<filename>)))
|
||||||
|
Changes the working directory. After opening the address the master process
|
||||||
|
changes back to the original working directory. Sub processes inherit the
|
||||||
|
temporary setting.
|
||||||
label(OPTION_UMASK)dit(bf(tt(umask=<mode>)))
|
label(OPTION_UMASK)dit(bf(tt(umask=<mode>)))
|
||||||
Sets the umask of the process to <mode> [link(mode_t)(TYPE_MODE_T)] before
|
Sets the umask of the process to <mode> [link(mode_t)(TYPE_MODE_T)] before
|
||||||
opening the address. Useful when file system entries are created or a shell
|
opening the address. Useful when file system entries are created or a shell
|
||||||
|
|
176
test.sh
176
test.sh
|
@ -1283,7 +1283,7 @@ waitsctp4port () {
|
||||||
[ "$timeout" ] || timeout=5
|
[ "$timeout" ] || timeout=5
|
||||||
while [ $timeout -gt 0 ]; do
|
while [ $timeout -gt 0 ]; do
|
||||||
case "$UNAME" in
|
case "$UNAME" in
|
||||||
Linux) if false && [ "$SS" ]; then
|
Linux) if [ "$SS" ]; then
|
||||||
l=$($SS -4 -n 2>/dev/null |grep "^sctp.*LISTEN .*:$port\>")
|
l=$($SS -4 -n 2>/dev/null |grep "^sctp.*LISTEN .*:$port\>")
|
||||||
else
|
else
|
||||||
l=$(netstat -n -a |grep '^sctp .*[0-9*]:'$port' .* LISTEN')
|
l=$(netstat -n -a |grep '^sctp .*[0-9*]:'$port' .* LISTEN')
|
||||||
|
@ -7851,7 +7851,8 @@ if ! eval $NUMCOND; then :;
|
||||||
else
|
else
|
||||||
tf="$td/test$N.stout"
|
tf="$td/test$N.stout"
|
||||||
te="$td/test$N.stderr"
|
te="$td/test$N.stderr"
|
||||||
CMD="$TRACE $SOCAT $opts -d -d /dev/null pty,end-close"
|
# -t must be longer than 0.1 on OpenBSD
|
||||||
|
CMD="$TRACE $SOCAT $opts -d -d -t 0.5 /dev/null pty,end-close"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
# AIX reports the pty writeable for select() only when its slave side has been
|
# AIX reports the pty writeable for select() only when its slave side has been
|
||||||
# opened, therefore we run this process in background and check its NOTICE
|
# opened, therefore we run this process in background and check its NOTICE
|
||||||
|
@ -7860,7 +7861,7 @@ printf "test $F_n $TEST... " $N
|
||||||
waitfile "${te}"
|
waitfile "${te}"
|
||||||
psleep 0.1
|
psleep 0.1
|
||||||
PTY=$(grep "N PTY is " $te |sed 's/.*N PTY is //')
|
PTY=$(grep "N PTY is " $te |sed 's/.*N PTY is //')
|
||||||
[ -e "$PTY" ] && cat $PTY >/dev/null
|
[ -e "$PTY" ] && cat $PTY >/dev/null 2>/dev/null
|
||||||
rc=$(cat "$td/test$N.rc0")
|
rc=$(cat "$td/test$N.rc0")
|
||||||
if [ "$rc" = 0 ]; then
|
if [ "$rc" = 0 ]; then
|
||||||
$PRINTF "$OK\n"
|
$PRINTF "$OK\n"
|
||||||
|
@ -17355,6 +17356,171 @@ else
|
||||||
listFAIL="$listFAIL $N"
|
listFAIL="$listFAIL $N"
|
||||||
namesFAIL="$namesFAIL $NAME"
|
namesFAIL="$namesFAIL $NAME"
|
||||||
fi
|
fi
|
||||||
|
fi # NUMCOND
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
N=$((N+1))
|
||||||
|
|
||||||
|
|
||||||
|
# Some of the following tests need absolute path of Socat
|
||||||
|
case "$SOCAT" in
|
||||||
|
/*) absSOCAT="$SOCAT" ;;
|
||||||
|
*) absSOCAT="$PWD/$SOCAT" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Test the chdir option, in particular if chdir with the first address
|
||||||
|
# (CREATE) does not affect pwd of second address, i.e. original pwd is
|
||||||
|
# recovered
|
||||||
|
NAME=CHDIR_ON_CREATE
|
||||||
|
case "$TESTS" in
|
||||||
|
*%$N%*|*%functions%*|*%creat%*|*%system%*|*%chdir%*|*%$NAME%*)
|
||||||
|
TEST="$NAME: restore of pwd after CREAT with chdir option"
|
||||||
|
# Run Socat with first address CREAT with modified chdir,
|
||||||
|
# and second address SYSTEM (shell) with pwd command
|
||||||
|
# Check if the file is created with modified pwd but shell has original pwd
|
||||||
|
if ! eval $NUMCOND; then :;
|
||||||
|
elif ! F=$(testfeats CREAT SYSTEM); then
|
||||||
|
$PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not configured in $SOCAT${NORMAL}\n" $N
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
listCANT="$listCANT $N"
|
||||||
|
elif ! A=$(testaddrs - CREAT SYSTEM); then
|
||||||
|
$PRINTF "test $F_n $TEST... ${YELLOW}Address $A not available in $SOCAT${NORMAL}\n" $N
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
listCANT="$listCANT $N"
|
||||||
|
elif ! o=$(testoptions chdir) >/dev/null; then
|
||||||
|
$PRINTF "test $F_n $TEST... ${YELLOW}Option $o not available in $SOCAT${NORMAL}\n" $N
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
listCANT="$listCANT $N"
|
||||||
|
else
|
||||||
|
tf="$td/test$N.stdout"
|
||||||
|
te="$td/test$N.stderr"
|
||||||
|
tc="test$N.creat"
|
||||||
|
tdd="test$N.d"
|
||||||
|
tdiff="$td/test$N.diff"
|
||||||
|
tdebug="$td/test$N.debug"
|
||||||
|
opwd=$(pwd)
|
||||||
|
CMD0="$TRACE $absSOCAT $opts -U CREAT:$tc,chdir=$td SYSTEM:pwd"
|
||||||
|
printf "test $F_n $TEST... " $N
|
||||||
|
mkdir "$td/$tdd"
|
||||||
|
pushd "$td/$tdd" >/dev/null
|
||||||
|
$CMD0 >/dev/null 2>"${te}0"
|
||||||
|
rc0=$?
|
||||||
|
popd >/dev/null
|
||||||
|
tpwd=$(find $td -name $tc -print); tpwd=${tpwd%/*}
|
||||||
|
pwd2=$(cat $tpwd/$tc </dev/null)
|
||||||
|
echo "Original pwd: $opwd" >>$tdebug
|
||||||
|
echo "Temporary pwd: $tpwd" >>$tdebug
|
||||||
|
echo "Addr2 pwd: $pwd2" >>$tdebug
|
||||||
|
if [ "$rc0" -ne 0 ]; then
|
||||||
|
$PRINTF "$FAILED\n"
|
||||||
|
echo "$CMD0 &"
|
||||||
|
cat "${te}0" >&2
|
||||||
|
numFAIL=$((numFAIL+1))
|
||||||
|
listFAIL="$listFAIL $N"
|
||||||
|
namesFAIL="$namesFAIL $NAME"
|
||||||
|
elif [ "$tpwd" != "$td" ]; then
|
||||||
|
$PRINTF "$FAILED (chdir failed)\n"
|
||||||
|
echo "$CMD0 &"
|
||||||
|
cat "${te}0" >&2
|
||||||
|
numFAIL=$((numFAIL+1))
|
||||||
|
listFAIL="$listFAIL $N"
|
||||||
|
namesFAIL="$namesFAIL $NAME"
|
||||||
|
elif ! echo "$pwd2" |diff "$td/$tc" - >$tdiff; then
|
||||||
|
$PRINTF "$FAILED (bad pwd2)\n"
|
||||||
|
echo "$CMD0 &"
|
||||||
|
cat "${te}0" >&2
|
||||||
|
echo "// diff:" >&2
|
||||||
|
cat "$tdiff" >&2
|
||||||
|
numFAIL=$((numFAIL+1))
|
||||||
|
listFAIL="$listFAIL $N"
|
||||||
|
namesFAIL="$namesFAIL $NAME"
|
||||||
|
else
|
||||||
|
$PRINTF "$OK\n"
|
||||||
|
if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi
|
||||||
|
if [ "$DEBUG" ]; then cat "${te}0" >&2; fi
|
||||||
|
numOK=$((numOK+1))
|
||||||
|
fi
|
||||||
|
fi # NUMCOND
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
N=$((N+1))
|
||||||
|
|
||||||
|
# Test the chdir option, in particular if chdir with first address
|
||||||
|
# (SHELL) does not affect pwd of second address, i.e. original pwd is
|
||||||
|
# recovered
|
||||||
|
NAME=CHDIR_ON_SHELL
|
||||||
|
case "$TESTS" in
|
||||||
|
*%$N%*|*%functions%*|*%shell%*|*%system%*|*%chdir%*|*%$NAME%*)
|
||||||
|
TEST="$NAME: restore of pwd after SYSTEM with chdir option"
|
||||||
|
# Run Socat with first address SYSTEM:"cat >file" with chdir,
|
||||||
|
# and second address SYSTEM (shell) with pwd command.
|
||||||
|
# Check if the file is created with modified pwd but shell has original pwd
|
||||||
|
if ! eval $NUMCOND; then :;
|
||||||
|
elif ! F=$(testfeats SHELL SYSTEM); then
|
||||||
|
$PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not configured in $SOCAT${NORMAL}\n" $N
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
listCANT="$listCANT $N"
|
||||||
|
elif ! A=$(testaddrs SHELL SYSTEM); then
|
||||||
|
$PRINTF "test $F_n $TEST... ${YELLOW}Address $A not available in $SOCAT${NORMAL}\n" $N
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
listCANT="$listCANT $N"
|
||||||
|
elif ! o=$(testoptions chdir) >/dev/null; then
|
||||||
|
$PRINTF "test $F_n $TEST... ${YELLOW}Option $o not available in $SOCAT${NORMAL}\n" $N
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
listCANT="$listCANT $N"
|
||||||
|
else
|
||||||
|
tf="$td/test$N.stdout"
|
||||||
|
te="$td/test$N.stderr"
|
||||||
|
tc="test$N.creat"
|
||||||
|
tdd="test$N.d"
|
||||||
|
tdiff="$td/test$N.diff"
|
||||||
|
tdebug="$td/test$N.debug"
|
||||||
|
opwd=$(pwd)
|
||||||
|
CMD0="$TRACE $absSOCAT $opts -U SHELL:\"cat\ >$tc\",chdir=$td SYSTEM:pwd"
|
||||||
|
printf "test $F_n $TEST... " $N
|
||||||
|
mkdir "$td/$tdd"
|
||||||
|
pushd "$td/$tdd" >/dev/null
|
||||||
|
eval "$CMD0" >/dev/null 2>"${te}0"
|
||||||
|
rc0=$?
|
||||||
|
popd >/dev/null
|
||||||
|
tpwd=$(find $td -name $tc -print); tpwd=${tpwd%/*}
|
||||||
|
pwd2=$(cat $tpwd/$tc </dev/null)
|
||||||
|
echo "Original pwd: $opwd" >>$tdebug
|
||||||
|
echo "Temporary pwd: $tpwd" >>$tdebug
|
||||||
|
echo "Addr2 pwd: $pwd2" >>$tdebug
|
||||||
|
if [ "$rc0" -ne 0 ]; then
|
||||||
|
$PRINTF "$FAILED\n"
|
||||||
|
echo "$CMD0 &"
|
||||||
|
cat "${te}0" >&2
|
||||||
|
numFAIL=$((numFAIL+1))
|
||||||
|
listFAIL="$listFAIL $N"
|
||||||
|
namesFAIL="$namesFAIL $NAME"
|
||||||
|
elif [ "$tpwd" != "$td" ]; then
|
||||||
|
$PRINTF "$FAILED (chdir failed)\n"
|
||||||
|
echo "$CMD0 &"
|
||||||
|
cat "${te}0" >&2
|
||||||
|
numFAIL=$((numFAIL+1))
|
||||||
|
listFAIL="$listFAIL $N"
|
||||||
|
namesFAIL="$namesFAIL $NAME"
|
||||||
|
elif ! echo "$pwd2" |diff "$td/$tc" - >$tdiff; then
|
||||||
|
$PRINTF "$FAILED (bad pwd)\n"
|
||||||
|
echo "$CMD0 &"
|
||||||
|
cat "${te}0" >&2
|
||||||
|
echo "// diff:" >&2
|
||||||
|
cat "$tdiff" >&2
|
||||||
|
numFAIL=$((numFAIL+1))
|
||||||
|
listFAIL="$listFAIL $N"
|
||||||
|
namesFAIL="$namesFAIL $NAME"
|
||||||
|
else
|
||||||
|
$PRINTF "$OK\n"
|
||||||
|
if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi
|
||||||
|
if [ "$DEBUG" ]; then cat "${te}0" >&2; fi
|
||||||
|
numOK=$((numOK+1))
|
||||||
|
fi
|
||||||
|
fi # NUMCOND
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
N=$((N+1))
|
||||||
|
|
||||||
|
|
||||||
# Test the modified umask option, in particular if umask with first address
|
# Test the modified umask option, in particular if umask with first address
|
||||||
|
@ -17372,7 +17538,7 @@ elif ! F=$(testfeats CREAT SYSTEM); then
|
||||||
$PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not configured in $SOCAT${NORMAL}\n" $N
|
$PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not configured in $SOCAT${NORMAL}\n" $N
|
||||||
numCANT=$((numCANT+1))
|
numCANT=$((numCANT+1))
|
||||||
listCANT="$listCANT $N"
|
listCANT="$listCANT $N"
|
||||||
elif ! A=$(testaddrs - CREAT SYSTEM); then
|
elif ! A=$(testaddrs CREAT SYSTEM); then
|
||||||
$PRINTF "test $F_n $TEST... ${YELLOW}Address $A not available in $SOCAT${NORMAL}\n" $N
|
$PRINTF "test $F_n $TEST... ${YELLOW}Address $A not available in $SOCAT${NORMAL}\n" $N
|
||||||
numCANT=$((numCANT+1))
|
numCANT=$((numCANT+1))
|
||||||
listCANT="$listCANT $N"
|
listCANT="$listCANT $N"
|
||||||
|
@ -17441,7 +17607,7 @@ N=$((N+1))
|
||||||
# recovered
|
# recovered
|
||||||
NAME=UMASK_ON_SYSTEM
|
NAME=UMASK_ON_SYSTEM
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%shell%*|*%umask%*|*%socket%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%shell%*|*%system%*|*%umask%*|*%socket%*|*%$NAME%*)
|
||||||
TEST="$NAME: test restore after SHELL with umask option"
|
TEST="$NAME: test restore after SHELL with umask option"
|
||||||
# Run Socat with first address SHELL:"cat >file" with modified umask,
|
# Run Socat with first address SHELL:"cat >file" with modified umask,
|
||||||
# and second address SYSTEM (shell) with umask command.
|
# and second address SYSTEM (shell) with umask command.
|
||||||
|
|
|
@ -44,29 +44,61 @@ int xio_set_namespace(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int xio_apply_namespace(
|
||||||
|
struct opt *opts)
|
||||||
|
{
|
||||||
|
int old_netfd;
|
||||||
|
char *netns_name;
|
||||||
|
char old_nspath[PATH_MAX];
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (retropt_string(opts, OPT_SET_NETNS, &netns_name) < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Get path describing current namespace */
|
||||||
|
snprintf(old_nspath, sizeof(old_nspath)-1, "/proc/"F_pid"/ns/net",
|
||||||
|
Getpid());
|
||||||
|
|
||||||
|
/* Get a file descriptor to current ns for later reset */
|
||||||
|
old_netfd = Open(old_nspath, O_RDONLY|O_CLOEXEC, 000);
|
||||||
|
if (old_netfd < 0) {
|
||||||
|
Error2("open(%s, O_RDONLY|O_CLOEXEC): %s",
|
||||||
|
old_nspath, strerror(errno));
|
||||||
|
free(netns_name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (old_netfd == 0) {
|
||||||
|
/* 0 means not netns option, oops */
|
||||||
|
Error1("%s(): INTERNAL", __func__);
|
||||||
|
free(netns_name);
|
||||||
|
Close(old_netfd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
rc = xio_set_namespace("netns", netns_name);
|
||||||
|
free(netns_name);
|
||||||
|
if (rc < 0) {
|
||||||
|
Close(old_netfd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return old_netfd;
|
||||||
|
}
|
||||||
|
|
||||||
/* Sets the given namespace to that of process 1, this is assumed to be the
|
/* Sets the given namespace to that of process 1, this is assumed to be the
|
||||||
systems default.
|
systems default.
|
||||||
Returns 0 on success, or -1 on error. */
|
Returns 0 on success, or -1 on error. */
|
||||||
int xio_reset_namespace(
|
int xio_reset_namespace(
|
||||||
const char *nstype)
|
int saved_netfd)
|
||||||
{
|
{
|
||||||
char nspath[PATH_MAX];
|
|
||||||
int nsfd;
|
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
snprintf(nspath, sizeof(nspath)-1, "/proc/1/ns/%s", nstype);
|
rc = Setns(saved_netfd, CLONE_NEWNET);
|
||||||
Info("switching back to default namespace");
|
|
||||||
nsfd = Open(nspath, O_RDONLY|O_CLOEXEC, 000);
|
|
||||||
if (nsfd < 0) {
|
|
||||||
Error2("open(%s, O_RDONLY|O_CLOEXEC): %s", nspath, strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
rc = Setns(nsfd, CLONE_NEWNET);
|
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
Error2("setns(%d, CLONE_NEWNET): %s", nsfd, strerror(errno));
|
Error2("xio_reset_namespace(%d): %s", saved_netfd, strerror(errno));
|
||||||
Close(nsfd);
|
Close(saved_netfd);
|
||||||
|
return STAT_NORETRY;
|
||||||
}
|
}
|
||||||
Close(nsfd);
|
Close(saved_netfd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,8 @@ extern const struct optdesc opt_set_netns;
|
||||||
extern const struct optdesc opt_reset_netns;
|
extern const struct optdesc opt_reset_netns;
|
||||||
|
|
||||||
extern int xio_set_namespace(const char *nstype, const char *nsname);
|
extern int xio_set_namespace(const char *nstype, const char *nsname);
|
||||||
extern int xio_reset_namespace(const char *nstype);
|
extern int xio_apply_namespace(struct opt *opts);
|
||||||
|
extern int xio_reset_namespace(int saved_netfd);
|
||||||
|
|
||||||
#endif /* WITH_NAMESPACES */
|
#endif /* WITH_NAMESPACES */
|
||||||
|
|
||||||
|
|
35
xiolayer.c
35
xiolayer.c
|
@ -24,4 +24,39 @@ const struct optdesc opt_intervall = { "interval", NULL, OPT_INTERVALL, GROUP_R
|
||||||
const struct optdesc opt_retry = { "retry", NULL, OPT_RETRY, GROUP_RETRY, PH_INIT, TYPE_UINT, OFUNC_EXT, XIO_OFFSETOF(retry), XIO_SIZEOF(retry) };
|
const struct optdesc opt_retry = { "retry", NULL, OPT_RETRY, GROUP_RETRY, PH_INIT, TYPE_UINT, OFUNC_EXT, XIO_OFFSETOF(retry), XIO_SIZEOF(retry) };
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
const struct optdesc opt_chdir = { "chdir", "cd", OPT_CHDIR, GROUP_ADDR, PH_INIT, TYPE_FILENAME, OFUNC_SPEC };
|
||||||
const struct optdesc opt_umask = { "umask", NULL, OPT_UMASK, GROUP_ADDR, PH_INIT, TYPE_MODET, OFUNC_SPEC };
|
const struct optdesc opt_umask = { "umask", NULL, OPT_UMASK, GROUP_ADDR, PH_INIT, TYPE_MODET, OFUNC_SPEC };
|
||||||
|
|
||||||
|
|
||||||
|
int xio_chdir(
|
||||||
|
struct opt* opts,
|
||||||
|
char **orig_dir)
|
||||||
|
{
|
||||||
|
char *tmp_dir = NULL;
|
||||||
|
|
||||||
|
if (retropt_string(opts, OPT_CHDIR, &tmp_dir) < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if ((*orig_dir = Malloc(PATH_MAX)) == NULL) {
|
||||||
|
free(tmp_dir);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getcwd(*orig_dir, PATH_MAX) == NULL) {
|
||||||
|
Error1("getcwd(<ptr>, PATH_MAX): %s", strerror(errno));
|
||||||
|
free(*orig_dir);
|
||||||
|
free(tmp_dir);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*orig_dir = Realloc(*orig_dir, strlen(*orig_dir+1));
|
||||||
|
|
||||||
|
if (Chdir(tmp_dir) < 0) {
|
||||||
|
Error2("chdir(\"%s\"): %s", tmp_dir, strerror(errno));
|
||||||
|
free(*orig_dir);
|
||||||
|
free(tmp_dir);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(tmp_dir);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
|
@ -15,7 +15,9 @@ extern const struct optdesc opt_escape;
|
||||||
extern const struct optdesc opt_forever;
|
extern const struct optdesc opt_forever;
|
||||||
extern const struct optdesc opt_intervall;
|
extern const struct optdesc opt_intervall;
|
||||||
extern const struct optdesc opt_retry;
|
extern const struct optdesc opt_retry;
|
||||||
|
extern const struct optdesc opt_chdir;
|
||||||
extern const struct optdesc opt_umask;
|
extern const struct optdesc opt_umask;
|
||||||
extern const struct optdesc opt_un_umask;
|
|
||||||
|
extern int xio_chdir(struct opt* opts, char **orig_dir);
|
||||||
|
|
||||||
#endif /* !defined(__xiolayer_h_included) */
|
#endif /* !defined(__xiolayer_h_included) */
|
||||||
|
|
70
xioopen.c
70
xioopen.c
|
@ -622,6 +622,7 @@ int xioopen_single(xiofile_t *xfd, int xioflags) {
|
||||||
const struct addrdesc *addrdesc;
|
const struct addrdesc *addrdesc;
|
||||||
const char *modetext[4] = { "none", "read-only", "write-only", "read-write" } ;
|
const char *modetext[4] = { "none", "read-only", "write-only", "read-write" } ;
|
||||||
/* Values to be saved until xioopen() is finished */
|
/* Values to be saved until xioopen() is finished */
|
||||||
|
char *orig_dir = NULL;
|
||||||
bool have_umask = false;
|
bool have_umask = false;
|
||||||
mode_t orig_umask, tmp_umask;
|
mode_t orig_umask, tmp_umask;
|
||||||
int result;
|
int result;
|
||||||
|
@ -631,42 +632,10 @@ int xioopen_single(xiofile_t *xfd, int xioflags) {
|
||||||
struct __res_state save_res;
|
struct __res_state save_res;
|
||||||
#endif /* WITH_RESOLVE && HAVE_RESOLV_H */
|
#endif /* WITH_RESOLVE && HAVE_RESOLV_H */
|
||||||
#if WITH_NAMESPACES
|
#if WITH_NAMESPACES
|
||||||
char *temp_netns;
|
|
||||||
int save_netfd = -1;
|
int save_netfd = -1;
|
||||||
#endif
|
#endif
|
||||||
int rc;
|
|
||||||
|
|
||||||
/* Apply "temporary" process properties, save value for later restore */
|
|
||||||
|
|
||||||
if (applyopts_single(sfd, sfd->opts, PH_OFFSET) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
#if WITH_NAMESPACES
|
|
||||||
if (retropt_string(sfd->opts, OPT_SET_NETNS, &temp_netns) >= 0) {
|
|
||||||
char nspath[PATH_MAX];
|
|
||||||
|
|
||||||
snprintf(nspath, sizeof(nspath)-1, "/proc/"F_pid"/ns/net",
|
|
||||||
Getpid());
|
|
||||||
save_netfd = Open(nspath, O_RDONLY|O_CLOEXEC, 000);
|
|
||||||
if (save_netfd < 0) {
|
|
||||||
Error2("open(%s, O_RDONLY|O_CLOEXEC): %s", nspath, strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = xio_set_namespace("netns", temp_netns);
|
|
||||||
free(temp_netns);
|
|
||||||
if (rc < 0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#endif /* WITH_NAMESPACES */
|
|
||||||
|
|
||||||
#if WITH_RESOLVE && HAVE_RESOLV_H
|
|
||||||
if ((do_res = xio_res_init(sfd, &save_res)) < 0)
|
|
||||||
return STAT_NORETRY;
|
|
||||||
#endif /* WITH_RESOLVE && HAVE_RESOLV_H */
|
|
||||||
|
|
||||||
addrdesc = xfd->stream.addr;
|
addrdesc = xfd->stream.addr;
|
||||||
/* Check if address supports required data directions */
|
|
||||||
if (((xioflags+1)&XIO_ACCMODE) & ~(addrdesc->directions)) {
|
if (((xioflags+1)&XIO_ACCMODE) & ~(addrdesc->directions)) {
|
||||||
Warn2("address is opened in %s mode but only supports %s", modetext[(xioflags+1)&XIO_ACCMODE], modetext[addrdesc->directions]);
|
Warn2("address is opened in %s mode but only supports %s", modetext[(xioflags+1)&XIO_ACCMODE], modetext[addrdesc->directions]);
|
||||||
}
|
}
|
||||||
|
@ -682,12 +651,31 @@ int xioopen_single(xiofile_t *xfd, int xioflags) {
|
||||||
xfd->stream.flags &= (~XIO_ACCMODE);
|
xfd->stream.flags &= (~XIO_ACCMODE);
|
||||||
xfd->stream.flags |= (xioflags & XIO_ACCMODE);
|
xfd->stream.flags |= (xioflags & XIO_ACCMODE);
|
||||||
|
|
||||||
|
/* Apply "temporary" process properties, save value for later restore */
|
||||||
|
|
||||||
|
if (applyopts_single(sfd, sfd->opts, PH_OFFSET) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
#if WITH_NAMESPACES
|
||||||
|
if ((save_netfd = xio_apply_namespace(sfd->opts)) < 0)
|
||||||
|
return -1;
|
||||||
|
#endif /* WITH_NAMESPACES */
|
||||||
|
|
||||||
|
#if HAVE_RESOLV_H
|
||||||
|
if ((do_res = xio_res_init(sfd, &save_res)) < 0)
|
||||||
|
return STAT_NORETRY;
|
||||||
|
#endif /* HAVE_RESOLV_H */
|
||||||
|
|
||||||
|
if (xio_chdir(sfd->opts, &orig_dir) < 0)
|
||||||
|
return STAT_NORETRY;
|
||||||
|
|
||||||
if (retropt_mode(xfd->stream.opts, OPT_UMASK, &tmp_umask) >= 0) {
|
if (retropt_mode(xfd->stream.opts, OPT_UMASK, &tmp_umask) >= 0) {
|
||||||
Info1("changing umask to 0%3o", tmp_umask);
|
Info1("changing umask to 0%3o", tmp_umask);
|
||||||
orig_umask = Umask(tmp_umask);
|
orig_umask = Umask(tmp_umask);
|
||||||
have_umask = true;
|
have_umask = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Call the specific xioopen function */
|
||||||
result = (*addrdesc->func)(xfd->stream.argc, xfd->stream.argv,
|
result = (*addrdesc->func)(xfd->stream.argc, xfd->stream.argv,
|
||||||
xfd->stream.opts, xioflags, xfd,
|
xfd->stream.opts, xioflags, xfd,
|
||||||
addrdesc);
|
addrdesc);
|
||||||
|
@ -698,19 +686,23 @@ int xioopen_single(xiofile_t *xfd, int xioflags) {
|
||||||
Umask(orig_umask);
|
Umask(orig_umask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (orig_dir != NULL) {
|
||||||
|
if (Chdir(orig_dir) < 0) {
|
||||||
|
Error2("chdir(\"%s\"): %s", orig_dir, strerror(errno));
|
||||||
|
free(orig_dir);
|
||||||
|
return STAT_NORETRY;
|
||||||
|
}
|
||||||
|
free(orig_dir);
|
||||||
|
}
|
||||||
|
|
||||||
#if WITH_RESOLVE && HAVE_RESOLV_H
|
#if WITH_RESOLVE && HAVE_RESOLV_H
|
||||||
if (do_res)
|
if (do_res)
|
||||||
xio_res_restore(&save_res);
|
xio_res_restore(&save_res);
|
||||||
#endif /* WITH_RESOLVE && HAVE_RESOLV_H */
|
#endif /* WITH_RESOLVE && HAVE_RESOLV_H */
|
||||||
|
|
||||||
#if WITH_NAMESPACES
|
#if WITH_NAMESPACES
|
||||||
if (save_netfd >= 0) {
|
if (save_netfd > 0) {
|
||||||
rc = Setns(save_netfd, CLONE_NEWNET);
|
xio_reset_namespace(save_netfd);
|
||||||
if (rc < 0) {
|
|
||||||
Error2("setns(%d, CLONE_NEWNET): %s", save_netfd, strerror(errno));
|
|
||||||
Close(save_netfd);
|
|
||||||
return STAT_NORETRY;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif /* WITH_NAMESPACES */
|
#endif /* WITH_NAMESPACES */
|
||||||
|
|
||||||
|
|
|
@ -314,9 +314,11 @@ const struct optname optionnames[] = {
|
||||||
IF_ANY ("bytes", &opt_readbytes)
|
IF_ANY ("bytes", &opt_readbytes)
|
||||||
IF_OPENSSL("cafile", &opt_openssl_cafile)
|
IF_OPENSSL("cafile", &opt_openssl_cafile)
|
||||||
IF_OPENSSL("capath", &opt_openssl_capath)
|
IF_OPENSSL("capath", &opt_openssl_capath)
|
||||||
|
IF_ANY ("cd", &opt_chdir)
|
||||||
IF_OPENSSL("cert", &opt_openssl_certificate)
|
IF_OPENSSL("cert", &opt_openssl_certificate)
|
||||||
IF_OPENSSL("certificate", &opt_openssl_certificate)
|
IF_OPENSSL("certificate", &opt_openssl_certificate)
|
||||||
IF_TERMIOS("cfmakeraw", &opt_termios_cfmakeraw)
|
IF_TERMIOS("cfmakeraw", &opt_termios_cfmakeraw)
|
||||||
|
IF_ANY ("chdir", &opt_chdir)
|
||||||
#if WITH_LISTEN
|
#if WITH_LISTEN
|
||||||
IF_ANY ("children-shutup", &opt_children_shutup)
|
IF_ANY ("children-shutup", &opt_children_shutup)
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -263,6 +263,7 @@ enum e_optcode {
|
||||||
# endif
|
# endif
|
||||||
OPT_BSDLY, /* termios.c_oflag */
|
OPT_BSDLY, /* termios.c_oflag */
|
||||||
#endif
|
#endif
|
||||||
|
OPT_CHDIR, /* change working directory */
|
||||||
OPT_CHILDREN_SHUTUP,
|
OPT_CHILDREN_SHUTUP,
|
||||||
OPT_CHROOT, /* chroot() past file system access */
|
OPT_CHROOT, /* chroot() past file system access */
|
||||||
OPT_CHROOT_EARLY, /* chroot() before file system access */
|
OPT_CHROOT_EARLY, /* chroot() before file system access */
|
||||||
|
|
Loading…
Reference in a new issue