New option chdir (cd)

This commit is contained in:
Gerhard Rieger 2023-10-02 07:56:51 +02:00
parent e5cbf2feeb
commit 6125ed4e4e
11 changed files with 301 additions and 62 deletions

View file

@ -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.

View file

@ -1 +1 @@
"1.7.4.5+20230721" "1.7.4.5+"

View file

@ -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
View file

@ -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.

View file

@ -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;
} }

View file

@ -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 */

View file

@ -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;
}

View file

@ -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) */

View file

@ -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 */

View file

@ -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

View file

@ -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 */