nexmon – Rev 1

Subversion Repositories:
Rev:
/* source: xioopts.c */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */

/* this file contains the source for address options handling */

#include "xiosysincludes.h"
#include "xioopen.h"
#include "xio-unix.h"

#include "xiomodes.h"
#include "xiolockfile.h"
#include "nestlex.h"

bool xioopts_ignoregroups;

#define IF_ANY(a,b) {a,b},

#if WITH_NAMED
#  define IF_NAMED(a,b) {a,b},
#else
#  define IF_NAMED(a,b) 
#endif

#if WITH_PIPE || WITH_GOPEN
#  define IF_OPEN(a,b) {a,b},
#else
#  define IF_OPEN(a,b) 
#endif

#if WITH_TERMIOS
#  define IF_TERMIOS(a,b) {a,b},
#else
#  define IF_TERMIOS(a,b) 
#endif

#if WITH_EXEC
#  define IF_EXEC(a,b) {a,b},
#else
#  define IF_EXEC(a,b) 
#endif

#if _WITH_SOCKET
#  define IF_SOCKET(a,b) {a,b},
#else
#  define IF_SOCKET(a,b) 
#endif

#if WITH_LISTEN
#  define IF_LISTEN(a,b) {a,b},
#else
#  define IF_LISTEN(a,b) 
#endif

#if (WITH_UDP || WITH_TCP) && WITH_LISTEN
#  define IF_RANGE(a,b) {a,b},
#else
#  define IF_RANGE(a,b)
#endif

#if WITH_IP4 || WITH_IP6
#  define IF_IP(a,b) {a,b},
#else
#  define IF_IP(a,b) 
#endif

#if WITH_IP6
#  define IF_IP6(a,b) {a,b},
#else
#  define IF_IP6(a,b) 
#endif

#if WITH_TCP|WITH_UDP
#  define IF_IPAPP(a,b) {a,b},
#else
#  define IF_IPAPP(a,b) 
#endif

#if WITH_TCP
#  define IF_TCP(a,b) {a,b},
#else
#  define IF_TCP(a,b) 
#endif

#if WITH_SCTP
#  define IF_SCTP(a,b) {a,b},
#else
#  define IF_SCTP(a,b) 
#endif

#if WITH_SOCKS4
#  define IF_SOCKS4(a,b) {a,b},
#else
#  define IF_SOCKS4(a,b) 
#endif

#if WITH_SOCKS5
#  define IF_SOCKS5(a,b) {a,b},
#else
#  define IF_SOCKS5(a,b) 
#endif

#if WITH_PROXY
#  define IF_PROXY(a,b) {a,b},
#else
#  define IF_PROXY(a,b) 
#endif

#if WITH_READLINE
#  define IF_READLINE(a,b) {a,b},
#else
#  define IF_READLINE(a,b)
#endif

#if WITH_PTY
#  define IF_PTY(a,b) {a,b},
#else
#  define IF_PTY(a,b)
#endif

#if WITH_OPENSSL
#  define IF_OPENSSL(a,b) {a,b},
#else
#  define IF_OPENSSL(a,b)
#endif

#if WITH_TUN
#  define IF_TUN(a,b) {a,b},
#else
#  define IF_TUN(a,b)
#endif

#if WITH_UNIX
#  define IF_UNIX(a,b) {a,b},
#else
#  define IF_UNIX(a,b)
#endif

#if WITH_RETRY
#  define IF_RETRY(a,b) {a,b},
#else
#  define IF_RETRY(a,b) 
#endif


static int applyopt_offset(struct single *xfd, struct opt *opt);


/* address options - keep this array strictly alphabetically sorted for
   binary search! */
/* NULL terminated */
const struct optname optionnames[] = {
#if HAVE_RESOLV_H
        IF_IP     ("aaonly",    &opt_res_aaonly)
#endif /* HAVE_RESOLV_H */
#ifdef TCP_ABORT_THRESHOLD  /* HP_UX */
        IF_TCP    ("abort-threshold",   &opt_tcp_abort_threshold)
#endif
#ifdef SO_ACCEPTCONN /* AIX433 */
        IF_SOCKET ("acceptconn",        &opt_so_acceptconn)
#endif /* SO_ACCEPTCONN */
#ifdef IP_ADD_MEMBERSHIP
        IF_IP     ("add-membership",    &opt_ip_add_membership)
#endif
        IF_TUN    ("allmulti",  &opt_iff_allmulti)
#if WITH_LIBWRAP && defined(HAVE_HOSTS_ALLOW_TABLE)
        IF_IPAPP  ("allow-table",       &opt_tcpwrap_hosts_allow_table)
#endif
        IF_ANY    ("append",    &opt_append)
#ifdef O_ASYNC
        IF_ANY    ("async",     &opt_async)
#endif
#ifdef SO_ATTACH_FILTER
        IF_SOCKET ("attach-filter",     &opt_so_attach_filter)
        IF_SOCKET ("attachfilter",      &opt_so_attach_filter)
#endif
#ifdef SO_AUDIT /* AIX 4.3.3 */
        IF_SOCKET ("audit",     &opt_so_audit)
#endif /* SO_AUDIT */
#ifdef IPV6_AUTHHDR
        IF_IP6    ("authhdr",   &opt_ipv6_authhdr)
#endif
        IF_TUN    ("automedia", &opt_iff_automedia)
#ifdef CBAUD
        IF_TERMIOS("b0",        &opt_b0)
#ifdef B1000000
        IF_TERMIOS("b1000000",  &opt_b1000000)
#endif
        IF_TERMIOS("b110",      &opt_b110)
#ifdef B115200
        IF_TERMIOS("b115200",   &opt_b115200)
#endif
#ifdef B1152000
        IF_TERMIOS("b1152000",  &opt_b1152000)
#endif
        IF_TERMIOS("b1200",     &opt_b1200)
        IF_TERMIOS("b134",      &opt_b134)
        IF_TERMIOS("b150",      &opt_b150)
#ifdef B1500000
        IF_TERMIOS("b1500000",  &opt_b1500000)
#endif
        IF_TERMIOS("b1800",     &opt_b1800)
        IF_TERMIOS("b19200",    &opt_b19200)
        IF_TERMIOS("b200",      &opt_b200)
#ifdef B2000000
        IF_TERMIOS("b2000000",  &opt_b2000000)
#endif
#ifdef B230400
        IF_TERMIOS("b230400",   &opt_b230400)
#endif
        IF_TERMIOS("b2400",     &opt_b2400)
#ifdef B2500000
        IF_TERMIOS("b2500000",  &opt_b2500000)
#endif
        IF_TERMIOS("b300",      &opt_b300)
#ifdef B3000000
        IF_TERMIOS("b3000000",  &opt_b3000000)
#endif
#ifdef B3500000
        IF_TERMIOS("b3500000",  &opt_b3500000)
#endif
#ifdef B3600    /* HP-UX */
        IF_TERMIOS("b3600",     &opt_b3600)
#endif
        IF_TERMIOS("b38400",    &opt_b38400)
#ifdef B4000000
        IF_TERMIOS("b4000000",  &opt_b4000000)
#endif
#ifdef B460800
        IF_TERMIOS("b460800",   &opt_b460800)
#endif
        IF_TERMIOS("b4800",     &opt_b4800)
        IF_TERMIOS("b50",       &opt_b50)
#ifdef B500000
        IF_TERMIOS("b500000",   &opt_b500000)
#endif
#ifdef B57600
        IF_TERMIOS("b57600",    &opt_b57600)
#endif
#ifdef B576000
        IF_TERMIOS("b576000",   &opt_b576000)
#endif
        IF_TERMIOS("b600",      &opt_b600)
#ifdef B7200    /* HP-UX */
        IF_TERMIOS("b7200",     &opt_b7200)
#endif
        IF_TERMIOS("b75",       &opt_b75)
#ifdef B900     /* HP-UX */
        IF_TERMIOS("b900",      &opt_b900)
#endif
#ifdef B921600
        IF_TERMIOS("b921600",   &opt_b921600)
#endif
        IF_TERMIOS("b9600",     &opt_b9600)
#endif /* defined(CBAUD) */
        IF_LISTEN ("backlog",   &opt_backlog)
#ifdef O_BINARY
        IF_OPEN   ("bin",               &opt_o_binary)
        IF_OPEN   ("binary",            &opt_o_binary)
#endif
        IF_SOCKET ("bind",      &opt_bind)
#ifdef SO_BINDTODEVICE
        IF_SOCKET ("bindtodevice",      &opt_so_bindtodevice)
#endif
        IF_TERMIOS("brkint",    &opt_brkint)
        IF_SOCKET ("broadcast", &opt_so_broadcast)
#ifdef BSDLY
#  ifdef BS0
        IF_TERMIOS("bs0",       &opt_bs0)
#  endif
#  ifdef BS1
        IF_TERMIOS("bs1",       &opt_bs1)
#  endif
#endif
#ifdef SO_BSDCOMPAT
        IF_SOCKET ("bsdcompat", &opt_so_bsdcompat)
#endif
#ifdef BSDLY
        IF_TERMIOS("bsdly",     &opt_bsdly)
#endif
        IF_ANY    ("bytes",     &opt_readbytes)
        IF_OPENSSL("cafile",    &opt_openssl_cafile)
        IF_OPENSSL("capath",    &opt_openssl_capath)
        IF_OPENSSL("cert",      &opt_openssl_certificate)
        IF_OPENSSL("certificate",       &opt_openssl_certificate)
        IF_TERMIOS("cfmakeraw",         &opt_termios_cfmakeraw)
        IF_ANY    ("chroot",    &opt_chroot)
        IF_ANY    ("chroot-early",      &opt_chroot_early)
        /*IF_TERMIOS("cibaud",  &opt_cibaud)*/
        IF_OPENSSL("cipher",    &opt_openssl_cipherlist)
        IF_OPENSSL("cipherlist",        &opt_openssl_cipherlist)
        IF_OPENSSL("ciphers",   &opt_openssl_cipherlist)
#ifdef SO_CKSUMRECV
        IF_SOCKET ("cksumrecv", &opt_so_cksumrecv)
#endif /* SO_CKSUMRECV */
        /*IF_NAMED  ("cleanup", &opt_cleanup)*/
        IF_TERMIOS("clocal",    &opt_clocal)
        IF_ANY    ("cloexec",   &opt_cloexec)
        IF_ANY    ("close",     &opt_end_close)
        IF_OPENSSL("cn",                &opt_openssl_commonname)
        IF_OPENSSL("commonname",        &opt_openssl_commonname)
        IF_EXEC   ("commtype",  &opt_commtype)
#if WITH_EXT2 && defined(EXT2_COMPR_FL)
        IF_ANY    ("compr",     &opt_ext2_compr)
#endif
#if OPENSSL_VERSION_NUMBER >= 0x00908000L && !defined(OPENSSL_NO_COMP)
        IF_OPENSSL("compress",  &opt_openssl_compress)
#endif
#ifdef TCP_CONN_ABORT_THRESHOLD  /* HP_UX */
        IF_TCP    ("conn-abort-threshold",      &opt_tcp_conn_abort_threshold)
#endif
        IF_SOCKET ("connect-timeout",   &opt_connect_timeout)
        IF_LISTEN ("cool-write",        &opt_cool_write)
        IF_LISTEN ("coolwrite", &opt_cool_write)
#ifdef TCP_CORK
        IF_TCP    ("cork",      &opt_tcp_cork)
#endif
        IF_ANY    ("cr",        &opt_cr)
#ifdef CRDLY
#  ifdef CR0
        IF_TERMIOS("cr0",       &opt_cr0)
#  endif
#  ifdef CR1
        IF_TERMIOS("cr1",       &opt_cr1)
#  endif
#  ifdef CR2
        IF_TERMIOS("cr2",       &opt_cr2)
#  endif
#  ifdef CR3
        IF_TERMIOS("cr3",       &opt_cr3)
#  endif
#  if CRDLY_SHIFT >= 0
        IF_TERMIOS("crdly",     &opt_crdly)
#  endif
#endif /* defined(CRDLY) */
        IF_TERMIOS("cread",     &opt_cread)
        IF_OPEN   ("creat",     &opt_o_create)
        IF_OPEN   ("create",    &opt_o_create)
        IF_ANY    ("crlf",      &opt_crnl)
        IF_ANY    ("crnl",      &opt_crnl)
        IF_TERMIOS("crterase",  &opt_echoe)
        IF_TERMIOS("crtkill",   &opt_echoke)
#ifdef CRTSCTS
        IF_TERMIOS("crtscts",   &opt_crtscts)
#endif
        IF_TERMIOS("cs5",       &opt_cs5)
        IF_TERMIOS("cs6",       &opt_cs6)
        IF_TERMIOS("cs7",       &opt_cs7)
        IF_TERMIOS("cs8",       &opt_cs8)
#if CSIZE_SHIFT >= 0
        IF_TERMIOS("csize",     &opt_csize)
#endif
        IF_TERMIOS("cstopb",    &opt_cstopb)
        IF_TERMIOS("ctlecho",   &opt_echoctl)
        IF_TERMIOS("ctty",      &opt_tiocsctty)
        IF_EXEC   ("dash",      &opt_dash)
        IF_SOCKET ("debug",     &opt_so_debug)
        /*IF_IP     ("debug",   &opt_res_debug)*/
#ifdef O_DEFER
        IF_OPEN   ("defer",     &opt_o_defer)
#endif
#ifdef TCP_DEFER_ACCEPT /* Linux 2.4.0 */
        IF_TCP    ("defer-accept",      &opt_tcp_defer_accept)
#endif
#if HAVE_RESOLV_H
        IF_IP     ("defnames",  &opt_res_defnames)
#endif /* HAVE_RESOLV_H */
#ifdef O_DELAY
        IF_OPEN   ("delay",     &opt_o_delay)
#endif
        IF_NAMED  ("delete",    &opt_unlink)
#if WITH_LIBWRAP && defined(HAVE_HOSTS_DENY_TABLE)
        IF_IPAPP  ("deny-table",        &opt_tcpwrap_hosts_deny_table)
#endif
#ifdef SO_DETACH_FILTER
        IF_SOCKET ("detach-filter", &opt_so_detach_filter)
        IF_SOCKET ("detachfilter",  &opt_so_detach_filter)
#endif
#ifdef SO_DGRAM_ERRIND
        IF_SOCKET ("dgram-errind",      &opt_so_dgram_errind)
        IF_SOCKET ("dgramerrind",       &opt_so_dgram_errind)
#endif
        IF_OPENSSL("dh",        &opt_openssl_dhparam)
        IF_OPENSSL("dhparam",   &opt_openssl_dhparam)
#ifdef O_DIRECT
        IF_OPEN   ("direct",    &opt_o_direct)
#endif
#ifdef O_DIRECTORY
        IF_OPEN   ("directory", &opt_o_directory)
#endif
#if WITH_EXT2 && defined(EXT2_DIRSYNC_FL)
        IF_ANY    ("dirsync",   &opt_ext2_dirsync)
#endif
#ifdef VDISCARD
        IF_TERMIOS("discard",   &opt_vdiscard)
#endif
#if HAVE_RESOLV_H
        IF_IP     ("dnsrch",    &opt_res_dnsrch)
#endif /* HAVE_RESOLV_H */
#ifdef SO_DONTLINGER
        IF_SOCKET ("dontlinger",        &opt_so_dontlinger)
#endif
        IF_SOCKET ("dontroute", &opt_so_dontroute)
#ifdef IPV6_DSTOPTS
        IF_IP6    ("dstopts",   &opt_ipv6_dstopts)
#endif
#ifdef VDSUSP   /* HP-UX */
        IF_TERMIOS("dsusp",     &opt_vdsusp)
#endif
#ifdef O_DSYNC
        IF_OPEN   ("dsync",     &opt_o_dsync)
#endif
        IF_TERMIOS("echo",      &opt_echo)
        IF_TERMIOS("echoctl",   &opt_echoctl)
        IF_TERMIOS("echoe",     &opt_echoe)
        IF_TERMIOS("echok",     &opt_echok)
        IF_TERMIOS("echoke",    &opt_echoke)
        IF_TERMIOS("echonl",    &opt_echonl)
#ifdef ECHOPRT
        IF_TERMIOS("echoprt",   &opt_echoprt)
#endif
        IF_OPENSSL("egd",       &opt_openssl_egd)
        IF_ANY    ("end-close", &opt_end_close)
        IF_TERMIOS("eof",       &opt_veof)
        IF_TERMIOS("eol",       &opt_veol)
        IF_TERMIOS("eol2",      &opt_veol2)
        IF_TERMIOS("erase",     &opt_verase)
        IF_SOCKET ("error",     &opt_so_error)
        IF_ANY    ("escape",    &opt_escape)
        IF_OPEN   ("excl",      &opt_o_excl)
#if WITH_EXT2 && defined(EXT2_APPEND_FL)
        IF_ANY    ("ext2-append",       &opt_ext2_append)
#endif
#if WITH_EXT2 && defined(EXT2_COMPR_FL)
        IF_ANY    ("ext2-compr",        &opt_ext2_compr)
#endif
#if WITH_EXT2 && defined(EXT2_DIRSYNC_FL)
        IF_ANY    ("ext2-dirsync",      &opt_ext2_dirsync)
#endif
#if WITH_EXT2 && defined(EXT2_IMMUTABLE_FL)
        IF_ANY    ("ext2-immutable",    &opt_ext2_immutable)
#endif
#if WITH_EXT2 && defined(EXT2_JOURNAL_DATA_FL)
        IF_ANY    ("ext2-journal-data", &opt_ext2_journal_data)
#endif
#if WITH_EXT2 && defined(EXT2_NOATIME_FL)
        IF_ANY    ("ext2-noatime",      &opt_ext2_noatime)
#endif
#if WITH_EXT2 && defined(EXT2_NODUMP_FL)
        IF_ANY    ("ext2-nodump",       &opt_ext2_nodump)
#endif
#if WITH_EXT2 && defined(EXT2_NOTAIL_FL)
        IF_ANY    ("ext2-notail",       &opt_ext2_notail)
#endif
#if WITH_EXT2 && defined(EXT2_SECRM_FL)
        IF_ANY    ("ext2-secrm",        &opt_ext2_secrm)
#endif
#if WITH_EXT2 && defined(EXT2_SYNC_FL)
        IF_ANY    ("ext2-sync",         &opt_ext2_sync)
#endif
#if WITH_EXT2 && defined(EXT2_TOPDIR_FL)
        IF_ANY    ("ext2-topdir",       &opt_ext2_topdir)
#endif
#if WITH_EXT2 && defined(EXT2_UNRM_FL)
        IF_ANY    ("ext2-unrm",         &opt_ext2_unrm)
#endif
#if WITH_EXT2 && defined(EXT2_APPEND_FL)
        IF_ANY    ("ext3-append",       &opt_ext2_append)
#endif
#if WITH_EXT2 && defined(EXT2_COMPR_FL)
        IF_ANY    ("ext3-compr",        &opt_ext2_compr)
#endif
#if WITH_EXT2 && defined(EXT2_DIRSYNC_FL)
        IF_ANY    ("ext3-dirsync",      &opt_ext2_dirsync)
#endif
#if WITH_EXT2 && defined(EXT2_IMMUTABLE_FL)
        IF_ANY    ("ext3-immutable",    &opt_ext2_immutable)
#endif
#if WITH_EXT2 && defined(EXT2_JOURNAL_DATA_FL)
        IF_ANY    ("ext3-journal-data", &opt_ext2_journal_data)
#endif
#if WITH_EXT2 && defined(EXT2_NOATIME_FL)
        IF_ANY    ("ext3-noatime",      &opt_ext2_noatime)
#endif
#if WITH_EXT2 && defined(EXT2_NODUMP_FL)
        IF_ANY    ("ext3-nodump",       &opt_ext2_nodump)
#endif
#if WITH_EXT2 && defined(EXT2_NOTAIL_FL)
        IF_ANY    ("ext3-notail",       &opt_ext2_notail)
#endif
#if WITH_EXT2 && defined(EXT2_SECRM_FL)
        IF_ANY    ("ext3-secrm",        &opt_ext2_secrm)
#endif
#if WITH_EXT2 && defined(EXT2_SYNC_FL)
        IF_ANY    ("ext3-sync",         &opt_ext2_sync)
#endif
#if WITH_EXT2 && defined(EXT2_TOPDIR_FL)
        IF_ANY    ("ext3-topdir",       &opt_ext2_topdir)
#endif
#if WITH_EXT2 && defined(EXT2_UNRM_FL)
        IF_ANY    ("ext3-unrm",         &opt_ext2_unrm)
#endif
        IF_ANY    ("f-setlk",   &opt_f_setlk_wr)
        IF_ANY    ("f-setlk-rd",        &opt_f_setlk_rd)
        IF_ANY    ("f-setlk-wr",        &opt_f_setlk_wr)
        IF_ANY    ("f-setlkw",  &opt_f_setlkw_wr)
        IF_ANY    ("f-setlkw-rd",       &opt_f_setlkw_rd)
        IF_ANY    ("f-setlkw-wr",       &opt_f_setlkw_wr)
        IF_EXEC   ("fdin",      &opt_leftinfd)
        IF_EXEC   ("fdout",     &opt_leftoutfd)
#ifdef FFDLY
#  ifdef FF0
        IF_TERMIOS("ff0",       &opt_ff0)
#  endif
#  ifdef FF1
        IF_TERMIOS("ff1",       &opt_ff1)
#  endif
        IF_TERMIOS("ffdly",     &opt_ffdly)
#endif
#ifdef FIOSETOWN
        IF_SOCKET ("fiosetown", &opt_fiosetown)
#endif
#if WITH_FIPS
        IF_OPENSSL("fips",      &opt_openssl_fips)
#endif
#if HAVE_FLOCK
        IF_ANY    ("flock",     &opt_flock_ex)
        IF_ANY    ("flock-ex",  &opt_flock_ex)
        IF_ANY    ("flock-ex-nb",       &opt_flock_ex_nb)
        IF_ANY    ("flock-nb",  &opt_flock_ex_nb)
        IF_ANY    ("flock-sh",  &opt_flock_sh)
        IF_ANY    ("flock-sh-nb",       &opt_flock_sh_nb)
#endif
#ifdef IPV4_FLOWINFO
        IF_IP6    ("flowinfo",  &opt_ipv6_flowinfo)
#endif
        IF_TERMIOS("flusho",    &opt_flusho)
        IF_RETRY  ("forever",   &opt_forever)
        IF_LISTEN ("fork",      &opt_fork)
#ifdef IP_FREEBIND
        IF_IP     ("freebind",  &opt_ip_freebind)
#endif
#if HAVE_FTRUNCATE64
        IF_ANY    ("ftruncate", &opt_ftruncate64)
#else
        IF_ANY    ("ftruncate", &opt_ftruncate32)
#endif
        IF_ANY    ("ftruncate32",       &opt_ftruncate32)
#if HAVE_FTRUNCATE64
        IF_ANY    ("ftruncate64",       &opt_ftruncate64)
#endif
        IF_ANY    ("gid",       &opt_group)
        IF_NAMED  ("gid-e",     &opt_group_early)
        IF_ANY    ("gid-l",     &opt_group_late)
        IF_ANY    ("group",     &opt_group)
        IF_NAMED  ("group-early",       &opt_group_early)
        IF_ANY    ("group-late",        &opt_group_late)
#ifdef IP_HDRINCL
        IF_IP     ("hdrincl",   &opt_ip_hdrincl)
#endif
        IF_READLINE("history",  &opt_history_file)
        IF_READLINE("history-file",     &opt_history_file)
#ifdef IPV6_HOPLIMIT
        IF_IP6    ("hoplimit",  &opt_ipv6_hoplimit)
#endif
#ifdef IPV6_HOPOPTS
        IF_IP6    ("hopopts",   &opt_ipv6_hopopts)
#endif
#if WITH_LIBWRAP && defined(HAVE_HOSTS_ALLOW_TABLE)
        IF_IPAPP  ("hosts-allow",       &opt_tcpwrap_hosts_allow_table)
#endif
#if WITH_LIBWRAP && defined(HAVE_HOSTS_DENY_TABLE)
        IF_IPAPP  ("hosts-deny",        &opt_tcpwrap_hosts_deny_table)
#endif
        IF_TERMIOS("hup",       &opt_hupcl)
        IF_TERMIOS("hupcl",     &opt_hupcl)
#ifdef I_POP
        IF_ANY    ("i-pop-all", &opt_streams_i_pop_all)
#endif
#ifdef I_PUSH
        IF_ANY    ("i-push",    &opt_streams_i_push)
#endif
        IF_TERMIOS("icanon",    &opt_icanon)
        IF_TERMIOS("icrnl",     &opt_icrnl)
        IF_TERMIOS("iexten",    &opt_iexten)
#ifdef SO_BINDTODEVICE
        IF_SOCKET ("if",        &opt_so_bindtodevice)
#endif
        IF_TUN    ("iff-allmulti",      &opt_iff_allmulti)
        IF_TUN    ("iff-automedia",     &opt_iff_automedia)
        IF_TUN    ("iff-broadcast",     &opt_iff_broadcast)
        IF_TUN    ("iff-debug", &opt_iff_debug)
        /*IF_TUN    ("iff-dynamic",     &opt_iff_dynamic)*/
        IF_TUN    ("iff-loopback",      &opt_iff_loopback)
        IF_TUN    ("iff-master",        &opt_iff_master)
        IF_TUN    ("iff-multicast",     &opt_iff_multicast)
        IF_TUN    ("iff-no-pi", &opt_iff_no_pi)
        IF_TUN    ("iff-noarp", &opt_iff_noarp)
        IF_TUN    ("iff-notrailers",    &opt_iff_notrailers)
        IF_TUN    ("iff-pointopoint",   &opt_iff_pointopoint)
        IF_TUN    ("iff-portsel",       &opt_iff_portsel)
        IF_TUN    ("iff-promisc",       &opt_iff_promisc)
        IF_TUN    ("iff-running",       &opt_iff_running)
        IF_TUN    ("iff-slave", &opt_iff_slave)
        IF_TUN    ("iff-up",    &opt_iff_up)
        IF_TERMIOS("ignbrk",    &opt_ignbrk)
        IF_TERMIOS("igncr",     &opt_igncr)
  /* you might need to terminate socat manually if you use this option: */
        IF_PROXY  ("ignorecr",  &opt_ignorecr)
        IF_ANY    ("ignoreeof", &opt_ignoreeof)
        IF_ANY    ("ignoreof",  &opt_ignoreeof)
        IF_TERMIOS("ignpar",    &opt_ignpar)
#if HAVE_RESOLV_H
        IF_IP     ("igntc",     &opt_res_igntc)
#endif /* HAVE_RESOLV_H */
        IF_TERMIOS("imaxbel",   &opt_imaxbel)
#if WITH_EXT2 && defined(EXT2_IMMUTABLE_FL)
        IF_ANY    ("immutable", &opt_ext2_immutable)
#endif
#ifdef TCP_INFO /* Linux 2.4.0 */
        IF_TCP    ("info",      &opt_tcp_info)
#endif
        IF_TERMIOS("inlcr",     &opt_inlcr)
        IF_TERMIOS("inpck",     &opt_inpck)
#ifdef SO_BINDTODEVICE
        IF_SOCKET ("interface", &opt_so_bindtodevice)
#endif
        IF_RETRY  ("interval",  &opt_intervall)
        IF_RETRY  ("intervall", &opt_intervall)
        IF_TERMIOS("intr",      &opt_vintr)
        IF_ANY    ("ioctl",     &opt_ioctl_void)
        IF_ANY    ("ioctl-bin", &opt_ioctl_bin)
        IF_ANY    ("ioctl-int", &opt_ioctl_int)
        IF_ANY    ("ioctl-intp",        &opt_ioctl_intp)
        IF_ANY    ("ioctl-string",      &opt_ioctl_string)
        IF_ANY    ("ioctl-void",        &opt_ioctl_void)
#ifdef IP_ADD_MEMBERSHIP
        IF_IP     ("ip-add-membership", &opt_ip_add_membership)
#endif
#ifdef IP_FREEBIND
        IF_IP     ("ip-freebind",       &opt_ip_freebind)
#endif
#ifdef IP_HDRINCL
        IF_IP     ("ip-hdrincl",        &opt_ip_hdrincl)
#endif
#ifdef IP_ADD_MEMBERSHIP
        IF_IP     ("ip-membership",     &opt_ip_add_membership)
#endif
#ifdef IP_MTU
        IF_IP     ("ip-mtu",    &opt_ip_mtu)
#endif
#ifdef IP_MTU_DISCOVER
        IF_IP     ("ip-mtu-discover",   &opt_ip_mtu_discover)
#endif
        IF_IP     ("ip-multicast-if",   &opt_ip_multicast_if)
        IF_IP     ("ip-multicast-loop", &opt_ip_multicast_loop)
        IF_IP     ("ip-multicast-ttl",  &opt_ip_multicast_ttl)
#ifdef IP_OPTIONS
        IF_IP     ("ip-options",        &opt_ip_options)
#endif
#ifdef IP_PKTINFO
        IF_IP     ("ip-pktinfo",        &opt_ip_pktinfo)
#endif
#ifdef IP_PKTOPTIONS
        IF_IP     ("ip-pktoptions",     &opt_ip_pktoptions)
#endif
#ifdef IP_RECVDSTADDR
        IF_IP     ("ip-recvdstaddr",    &opt_ip_recvdstaddr)
#endif
#ifdef IP_RECVERR
        IF_IP     ("ip-recverr",        &opt_ip_recverr)
#endif
#ifdef IP_RECVIF
        IF_IP     ("ip-recvif",         &opt_ip_recvif)
#endif
#ifdef IP_RECVOPTS
        IF_IP     ("ip-recvopts",       &opt_ip_recvopts)
#endif
#ifdef IP_RECVTOS
        IF_IP     ("ip-recvtos",        &opt_ip_recvtos)
#endif
#ifdef IP_RECVTTL
        IF_IP     ("ip-recvttl",        &opt_ip_recvttl)
#endif
#ifdef IP_RETOPTS
        IF_IP     ("ip-retopts",        &opt_ip_retopts)
#endif
#ifdef IP_ROUTER_ALERT
        IF_IP     ("ip-router-alert",   &opt_ip_router_alert)
#endif
        IF_IP     ("ip-tos",    &opt_ip_tos)
        IF_IP     ("ip-ttl",    &opt_ip_ttl)
#ifdef IP_FREEBIND
        IF_IP     ("ipfreebind",        &opt_ip_freebind)
#endif
#ifdef IP_HDRINCL
        IF_IP     ("iphdrincl", &opt_ip_hdrincl)
#endif
#ifdef IP_MTU
        IF_IP     ("ipmtu",     &opt_ip_mtu)
#endif
#ifdef IP_MTU_DISCOVER
        IF_IP     ("ipmtudiscover",     &opt_ip_mtu_discover)
#endif
        IF_IP     ("ipmulticastloop",   &opt_ip_multicast_loop)
        IF_IP     ("ipmulticastttl",    &opt_ip_multicast_ttl)
#ifdef IP_OPTIONS
        IF_IP     ("ipoptions", &opt_ip_options)
#endif
#ifdef IP_PKTINFO
        IF_IP     ("ippktinfo", &opt_ip_pktinfo)
#endif
#ifdef IP_PKTOPTIONS
        IF_IP     ("ippktoptions",      &opt_ip_pktoptions)
#endif
#ifdef IP_RECVDSTADDR
        IF_IP     ("iprecvdstaddr",     &opt_ip_recvdstaddr)
#endif
#ifdef IP_RECVERR
        IF_IP     ("iprecverr", &opt_ip_recverr)
#endif
#ifdef IP_RECVOPTS
        IF_IP     ("iprecvopts",        &opt_ip_recvopts)
#endif
#ifdef IP_RECVTOS
        IF_IP     ("iprecvtos", &opt_ip_recvtos)
#endif
#ifdef IP_RECVTTL
        IF_IP     ("iprecvttl", &opt_ip_recvttl)
#endif
#ifdef IP_RETOPTS
        IF_IP     ("ipretopts", &opt_ip_retopts)
#endif
#ifdef IP_ROUTER_ALERT
        IF_IP     ("iprouteralert",     &opt_ip_router_alert)
#endif
        IF_IP     ("iptos",     &opt_ip_tos)
        IF_IP     ("ipttl",     &opt_ip_ttl)
#ifdef IPV6_JOIN_GROUP
        IF_IP6    ("ipv6-add-membership",       &opt_ipv6_join_group)
#endif
#ifdef IPV6_AUTHHDR
        IF_IP6    ("ipv6-authhdr",      &opt_ipv6_authhdr)
#endif
#ifdef IPV6_DSTOPTS
        IF_IP6    ("ipv6-dstopts",      &opt_ipv6_dstopts)
#endif
#ifdef IPV4_FLOWINFO
        IF_IP6    ("ipv6-flowinfo",     &opt_ipv6_flowinfo)
#endif
#ifdef IPV6_HOPLIMIT
        IF_IP6    ("ipv6-hoplimit",     &opt_ipv6_hoplimit)
#endif
#ifdef IPV6_HOPOPTS
        IF_IP6    ("ipv6-hopopts",      &opt_ipv6_hopopts)
#endif
#ifdef IPV6_JOIN_GROUP
        IF_IP6    ("ipv6-join-group",   &opt_ipv6_join_group)
#endif
#ifdef IPV6_PKTINFO
        IF_IP6    ("ipv6-pktinfo",      &opt_ipv6_pktinfo)
#endif
#ifdef IPV6_RECVDSTOPTS
        IF_IP6    ("ipv6-recvdstopts",  &opt_ipv6_recvdstopts)
#endif
#ifdef IPV6_RECVERR
        IF_IP6    ("ipv6-recverr",      &opt_ipv6_recverr)
#endif
#ifdef IPV6_RECVHOPLIMIT
        IF_IP6    ("ipv6-recvhoplimit", &opt_ipv6_recvhoplimit)
#endif
#ifdef IPV6_RECVHOPOPTS
        IF_IP6    ("ipv6-recvhopopts",  &opt_ipv6_recvhopopts)
#endif
#ifdef IPV6_PATHMTU
        IF_IP6    ("ipv6-recvpathmtu",  &opt_ipv6_recvpathmtu)
#endif
#ifdef IPV6_RECVPKTINFO
        IF_IP6    ("ipv6-recvpktinfo",  &opt_ipv6_recvpktinfo)
#endif
#ifdef IPV6_RECVRTHDR
        IF_IP6    ("ipv6-recvrthdr",    &opt_ipv6_recvrthdr)
#endif
#ifdef IPV6_RECVTCLASS
        IF_IP6    ("ipv6-recvtclass",   &opt_ipv6_recvtclass)
#endif
#ifdef IPV6_RTHDR
        IF_IP6    ("ipv6-rthdr",        &opt_ipv6_rthdr)
#endif
#ifdef IPV6_TCLASS
        IF_IP6    ("ipv6-tclass",       &opt_ipv6_tclass)
#endif
        IF_IP6    ("ipv6-unicast-hops", &opt_ipv6_unicast_hops)
#ifdef IPV6_V6ONLY
        IF_IP6    ("ipv6-v6only",       &opt_ipv6_v6only)
        IF_IP6    ("ipv6only",  &opt_ipv6_v6only)
#endif
        IF_TERMIOS("isig",      &opt_isig)
#if defined(HAVE_TERMIOS_ISPEED) && defined(ISPEED_OFFSET) && (ISPEED_OFFSET != -1)
        IF_TERMIOS("ispeed",    &opt_ispeed)
#endif
        IF_TERMIOS("istrip",    &opt_istrip)
#ifdef IUCLC
        IF_TERMIOS("iuclc",     &opt_iuclc)
#endif
        IF_TERMIOS("ixany",     &opt_ixany)
        IF_TERMIOS("ixoff",     &opt_ixoff)
        IF_TERMIOS("ixon",      &opt_ixon)
#ifdef IPV6_JOIN_GROUP
        IF_IP6    ("join-group",        &opt_ipv6_join_group)
#endif
#if WITH_EXT2 && defined(EXT2_JOURNAL_DATA_FL)
        IF_ANY    ("journal",           &opt_ext2_journal_data)
        IF_ANY    ("journal-data",      &opt_ext2_journal_data)
#endif
        IF_SOCKET ("keepalive", &opt_so_keepalive)
#ifdef TCP_KEEPCNT      /* Linux 2.4.0 */
        IF_TCP    ("keepcnt",   &opt_tcp_keepcnt)
#endif
#ifdef TCP_KEEPIDLE     /* Linux 2.4.0 */
        IF_TCP    ("keepidle",  &opt_tcp_keepidle)
#endif
#ifdef TCP_KEEPINIT     /* OSF1 */
        IF_TCP    ("keepinit",  &opt_tcp_keepinit)
#endif
#ifdef TCP_KEEPINTVL    /* Linux 2.4.0 */
        IF_TCP    ("keepintvl", &opt_tcp_keepintvl)
#endif
#ifdef SO_KERNACCEPT    /* AIX 4.3.3 */
        IF_SOCKET ("kernaccept",        &opt_so_kernaccept)
#endif /* SO_KERNACCEPT */
        IF_OPENSSL("key",       &opt_openssl_key)
        IF_TERMIOS("kill",      &opt_vkill)
#ifdef O_LARGEFILE
        IF_OPEN   ("largefile", &opt_o_largefile)
#endif
        IF_EXEC   ("left",      &opt_leftfd)
        IF_EXEC   ("leftfd",    &opt_leftfd)
        IF_EXEC   ("leftinfd",  &opt_leftinfd)
        IF_EXEC   ("leftoutfd", &opt_leftoutfd)
#if WITH_LIBWRAP
        IF_IPAPP  ("libwrap",           &opt_tcpwrappers)
#endif
        IF_SOCKET ("linger",    &opt_so_linger)
#ifdef TCP_LINGER2      /* Linux 2.4.0 */
        IF_TCP    ("linger2",   &opt_tcp_linger2)
#endif
        IF_PTY    ("link",      &opt_symbolic_link)
        IF_TERMIOS("lnext",     &opt_vlnext)
#if defined(F_SETLKW)
        IF_ANY    ("lock",      &opt_f_setlkw_wr)       /* POSIX, first choice */
#elif defined(HAVE_FLOCK)
        IF_ANY    ("lock",      &opt_flock_ex)  /* BSD, fallback */
#endif
        IF_ANY    ("lockfile",  &opt_lockfile)
#if defined(F_SETLKW)
        IF_ANY    ("lockw",     &opt_f_setlkw_wr)       /* POSIX, first choice */
#elif defined(HAVE_FLOCK)
        IF_ANY    ("lockw",     &opt_flock_ex_nb)       /* BSD, fallback */
#endif
        IF_EXEC   ("login",     &opt_dash)
        IF_TUN    ("loopback",  &opt_iff_loopback)
        IF_IPAPP  ("lowport",   &opt_lowport)
#if HAVE_LSEEK64
        IF_ANY    ("lseek",     &opt_lseek64_set)
#else
        IF_ANY    ("lseek",     &opt_lseek32_set)
#endif
        IF_ANY    ("lseek32",           &opt_lseek32_set)
        IF_ANY    ("lseek32-cur",       &opt_lseek32_cur)
        IF_ANY    ("lseek32-end",       &opt_lseek32_end)
        IF_ANY    ("lseek32-set",       &opt_lseek32_set)
#if HAVE_LSEEK64
        IF_ANY    ("lseek64",           &opt_lseek64_set)
        IF_ANY    ("lseek64-cur",       &opt_lseek64_cur)
        IF_ANY    ("lseek64-end",       &opt_lseek64_end)
        IF_ANY    ("lseek64-set",       &opt_lseek64_set)
#endif
        IF_TUN    ("master",    &opt_iff_master)
        IF_LISTEN ("max-children",      &opt_max_children)
        IF_LISTEN ("maxchildren",       &opt_max_children)
#ifdef TCP_MAXSEG
        IF_TCP    ("maxseg",    &opt_tcp_maxseg)
        IF_TCP    ("maxseg-late",       &opt_tcp_maxseg_late)
#endif
#ifdef TCP_MD5SUM
        IF_TCP    ("md5sig",    &opt_tcp_md5sig)
#endif
#ifdef IP_ADD_MEMBERSHIP
        IF_IP     ("membership",        &opt_ip_add_membership)
#endif
        IF_OPENSSL("method",    &opt_openssl_method)
        IF_TERMIOS("min",       &opt_vmin)
        IF_ANY    ("mode",      &opt_perm)
#ifdef TCP_MAXSEG
        IF_TCP    ("mss",       &opt_tcp_maxseg)
        IF_TCP    ("mss-late",  &opt_tcp_maxseg_late)
#endif
#ifdef IP_MTU
        IF_IP     ("mtu",       &opt_ip_mtu)
#endif
#ifdef IP_MTU_DISCOVER
        IF_IP     ("mtudiscover",       &opt_ip_mtu_discover)
#endif
        IF_TUN    ("multicast", &opt_iff_multicast)
        IF_IP     ("multicast-if",      &opt_ip_multicast_if)
        IF_IP     ("multicast-loop",    &opt_ip_multicast_loop)
        IF_IP     ("multicast-ttl",     &opt_ip_multicast_ttl)
        IF_IP     ("multicastloop",     &opt_ip_multicast_loop)
        IF_IP     ("multicastttl",      &opt_ip_multicast_ttl)
#if defined(O_NDELAY) && (!defined(O_NONBLOCK) || O_NDELAY != O_NONBLOCK)
        IF_ANY    ("ndelay",    &opt_o_ndelay)
#else
        IF_ANY    ("ndelay",    &opt_nonblock)
#endif
        IF_NAMED  ("new",       &opt_unlink_early)
#ifdef NLDLY
#  ifdef NL0
        IF_TERMIOS("nl0",       &opt_nl0)
#  endif
#  ifdef NL1
        IF_TERMIOS("nl1",       &opt_nl1)
#  endif
        IF_TERMIOS("nldly",     &opt_nldly)
#endif /* defined(NLDLY) */
#ifdef SO_NO_CHECK
        IF_SOCKET ("no-check",  &opt_so_no_check)
#endif
        IF_TUN    ("no-pi",     &opt_iff_no_pi)
        IF_TUN    ("noarp",     &opt_iff_noarp)
#ifdef O_NOATIME
        IF_OPEN   ("noatime",   &opt_o_noatime)
#endif
#ifdef SO_NO_CHECK
        IF_SOCKET ("nocheck",   &opt_so_no_check)
#endif
        IF_OPEN   ("noctty",    &opt_o_noctty)
#ifdef TCP_NODELAY
        IF_TCP    ("nodelay",   &opt_tcp_nodelay)
#endif
#if WITH_EXT2 && defined(EXT2_NODUMP_FL)
        IF_ANY    ("nodump",    &opt_ext2_nodump)
#endif
#if HAVE_REGEX_H
        IF_READLINE("noecho",   &opt_noecho)
#endif /* HAVE_REGEX_H */
        IF_TERMIOS("noflsh",    &opt_noflsh)
#ifdef O_NOFOLLOW
        IF_OPEN   ("nofollow",  &opt_o_nofollow)
#endif
        IF_EXEC   ("nofork",    &opt_nofork) 
#ifdef O_NOINHERIT
        IF_ANY    ("noinherit",         &opt_o_noinherit)
#endif
        IF_ANY    ("nonblock",  &opt_nonblock)
#ifdef TCP_NOOPT
        IF_TCP    ("noopt",             &opt_tcp_noopt)
#endif
        IF_READLINE("noprompt", &opt_noprompt)
#ifdef TCP_NOPUSH
        IF_TCP    ("nopush",    &opt_tcp_nopush)
#endif
#ifdef SO_NOREUSEADDR   /* AIX 4.3.3 */
        IF_SOCKET ("noreuseaddr",       &opt_so_noreuseaddr)
#endif /* SO_NOREUSEADDR */
        IF_TUN    ("notrailers",        &opt_iff_notrailers)
#ifdef O_NSHARE
        IF_OPEN   ("nshare",    &opt_o_nshare)
#endif
        IF_SOCKET ("null-eof",          &opt_null_eof)
        IF_ANY    ("o-append",          &opt_append)
#ifdef O_ASYNC
        IF_ANY    ("o-async",           &opt_async)
#endif
#ifdef O_BINARY
        IF_OPEN   ("o-binary",          &opt_o_binary)
#endif
        IF_OPEN   ("o-creat",   &opt_o_create)
        IF_OPEN   ("o-create",  &opt_o_create)
#ifdef O_DEFER
        IF_OPEN   ("o-defer",   &opt_o_defer)
#endif
#ifdef O_DELAY
        IF_OPEN   ("o-delay",   &opt_o_delay)
#endif
#ifdef O_DIRECT
        IF_OPEN   ("o-direct",  &opt_o_direct)
#endif
#ifdef O_DIRECTORY
        IF_OPEN   ("o-directory",       &opt_o_directory)
#endif
#ifdef O_DSYNC
        IF_OPEN   ("o-dsync",   &opt_o_dsync)
#endif
        IF_OPEN   ("o-excl",    &opt_o_excl)
#ifdef O_LARGEFILE
        IF_OPEN   ("o-largefile",       &opt_o_largefile)
#endif
#if defined(O_NDELAY) && (!defined(O_NONBLOCK) || O_NDELAY != O_NONBLOCK)
        IF_ANY    ("o-ndelay",  &opt_o_ndelay)
#else
        IF_ANY    ("o-ndelay",  &opt_nonblock)
#endif
#ifdef O_NOATIME
        IF_OPEN   ("o-noatime", &opt_o_noatime)
#endif
        IF_OPEN   ("o-noctty",  &opt_o_noctty)
#ifdef O_NOFOLLOW
        IF_OPEN   ("o-nofollow",        &opt_o_nofollow)
#endif
#ifdef O_NOINHERIT
        IF_ANY    ("o-noinherit",       &opt_o_noinherit)
#endif
        IF_ANY    ("o-nonblock",        &opt_nonblock)
#ifdef O_NSHARE
        IF_OPEN   ("o-nshare",  &opt_o_nshare)
#endif
#ifdef O_PRIV
        IF_OPEN   ("o-priv",    &opt_o_priv)
#endif
        IF_OPEN   ("o-rdonly",  &opt_o_rdonly)
        IF_OPEN   ("o-rdwr",    &opt_o_rdwr)
#ifdef O_RSHARE
        IF_OPEN   ("o-rshare",  &opt_o_rshare)
#endif
#ifdef O_RSYNC
        IF_OPEN   ("o-rsync",   &opt_o_rsync)
#endif
#ifdef O_SYNC
        IF_OPEN   ("o-sync",    &opt_o_sync)
#endif
#ifdef O_TEXT
        IF_ANY    ("o-text",            &opt_o_text)
#endif
        IF_OPEN   ("o-trunc",   &opt_o_trunc)
        IF_OPEN   ("o-wronly",  &opt_o_wronly)
#ifdef OCRNL
        IF_TERMIOS("ocrnl",     &opt_ocrnl)
#endif
#ifdef OFDEL
        IF_TERMIOS("ofdel",     &opt_ofdel)
#endif
#ifdef OFILL
        IF_TERMIOS("ofill",     &opt_ofill)
#endif
#ifdef OLCUC
        IF_TERMIOS("olcuc",     &opt_olcuc)
#endif
        IF_TERMIOS("onlcr",     &opt_onlcr)
#ifdef ONLRET
        IF_TERMIOS("onlret",    &opt_onlret)
#endif
#ifdef ONOCR
        IF_TERMIOS("onocr",     &opt_onocr)
#endif
        IF_SOCKET ("oobinline", &opt_so_oobinline)
#if HAVE_OPENPTY
        IF_EXEC   ("openpty",   &opt_openpty)
#endif /* HAVE_OPENPTY */
        IF_OPENSSL("openssl-cafile",    &opt_openssl_cafile)
        IF_OPENSSL("openssl-capath",    &opt_openssl_capath)
        IF_OPENSSL("openssl-certificate",       &opt_openssl_certificate)
        IF_OPENSSL("openssl-cipherlist",        &opt_openssl_cipherlist)
        IF_OPENSSL("openssl-commonname",        &opt_openssl_commonname)
#if OPENSSL_VERSION_NUMBER >= 0x00908000L && !defined(OPENSSL_NO_COMP)
        IF_OPENSSL("openssl-compress",  &opt_openssl_compress)
#endif
        IF_OPENSSL("openssl-dhparam",   &opt_openssl_dhparam)
        IF_OPENSSL("openssl-egd",       &opt_openssl_egd)
#if WITH_FIPS
        IF_OPENSSL("openssl-fips",      &opt_openssl_fips)
#endif
        IF_OPENSSL("openssl-key",       &opt_openssl_key)
        IF_OPENSSL("openssl-method",    &opt_openssl_method)
        IF_OPENSSL("openssl-pseudo",    &opt_openssl_pseudo)
        IF_OPENSSL("openssl-verify",    &opt_openssl_verify)
        IF_TERMIOS("opost",     &opt_opost)
#if defined(HAVE_TERMIOS_ISPEED) && defined(OSPEED_OFFSET) && (OSPEED_OFFSET != -1)
        IF_TERMIOS("ospeed",    &opt_ospeed)
#endif
        IF_ANY    ("owner",     &opt_user)
        IF_TERMIOS("parenb",    &opt_parenb)
        IF_TERMIOS("parmrk",    &opt_parmrk)
        IF_TERMIOS("parodd",    &opt_parodd)
#ifdef SO_PASSCRED
        IF_SOCKET ("passcred",  &opt_so_passcred)
#endif
        IF_EXEC   ("path",      &opt_path)
#ifdef TCP_PAWS /* OSF1 */
        IF_TCP    ("paws",      &opt_tcp_paws)
#endif
#ifdef SO_PEERCRED
        IF_SOCKET ("peercred",  &opt_so_peercred)
#endif
#ifdef PENDIN
        IF_TERMIOS("pendin",    &opt_pendin)
#endif
        IF_ANY    ("perm",      &opt_perm)
        IF_NAMED  ("perm-early",        &opt_perm_early)
        IF_ANY    ("perm-late", &opt_perm_late)
        IF_SOCKET ("pf",        &opt_protocol_family)
        IF_EXEC   ("pgid",      &opt_setpgid)
        IF_EXEC   ("pipes",     &opt_pipes)
#ifdef IP_PKTINFO
        IF_IP     ("pktinfo",   &opt_ip_pktinfo)
#endif
#ifdef IP_PKTOPTIONS
        IF_IP     ("pktoptions",        &opt_ip_pktoptions)
        IF_IP     ("pktopts",   &opt_ip_pktoptions)
#endif
        IF_TUN    ("pointopoint",       &opt_iff_pointopoint)
#ifdef I_POP
        IF_ANY    ("pop-all",   &opt_streams_i_pop_all)
#endif
        /*IF_IPAPP("port",      &opt_port)*/
        IF_TUN    ("portsel",   &opt_iff_portsel)
#if HAVE_RESOLV_H
        IF_IP     ("primary",   &opt_res_primary)
#endif /* HAVE_RESOLV_H */
#ifdef SO_PRIORITY
        IF_SOCKET ("priority",  &opt_so_priority)
#endif
#ifdef O_PRIV
        IF_OPEN   ("priv",      &opt_o_priv)
#endif
        IF_TUN    ("promisc",   &opt_iff_promisc)
        IF_READLINE("prompt",   &opt_prompt)
#ifdef SO_PROTOTYPE
        IF_SOCKET ("protocol",  &opt_so_prototype)
#endif
        IF_SOCKET ("protocol-family",   &opt_protocol_family)
#ifdef SO_PROTOTYPE
        IF_SOCKET ("prototype", &opt_so_prototype)
#endif
        IF_PROXY  ("proxy-auth",        &opt_proxy_authorization)
        IF_PROXY  ("proxy-authorization",       &opt_proxy_authorization)
        IF_PROXY  ("proxy-resolve",     &opt_proxy_resolve)
        IF_PROXY  ("proxyauth", &opt_proxy_authorization)
        IF_PROXY  ("proxyport", &opt_proxyport)
#ifdef ECHOPRT
        IF_TERMIOS("prterase",  &opt_echoprt)
#endif
        IF_OPENSSL("pseudo",    &opt_openssl_pseudo)
#if HAVE_DEV_PTMX || HAVE_DEV_PTC
        IF_EXEC   ("ptmx",      &opt_ptmx)
#endif
#if HAVE_PTY
        IF_EXEC   ("pty",       &opt_pty)
#endif
#if HAVE_PTY && HAVE_POLL
        IF_PTY    ("pty-interval",      &opt_pty_intervall)
        IF_PTY    ("pty-intervall",     &opt_pty_intervall)
        IF_PTY    ("pty-wait-slave",    &opt_pty_wait_slave)
#endif /* HAVE_PTY && HAVE_POLL */
#ifdef I_PUSH
        IF_ANY    ("push",      &opt_streams_i_push)
#endif
#ifdef TCP_QUICKACK
        IF_TCP    ("quickack",  &opt_tcp_quickack)
#endif
        IF_TERMIOS("quit",      &opt_vquit)
        IF_RANGE  ("range",     &opt_range)
        IF_TERMIOS("raw",       &opt_raw)
        IF_SOCKET ("rcvbuf",    &opt_so_rcvbuf)
        IF_SOCKET ("rcvbuf-late",       &opt_so_rcvbuf_late)
#ifdef SO_RCVLOWAT
        IF_SOCKET ("rcvlowat",  &opt_so_rcvlowat)
#endif
#ifdef SO_RCVTIMEO
        IF_SOCKET ("rcvtimeo",  &opt_so_rcvtimeo)
#endif
        IF_OPEN   ("rdonly",    &opt_o_rdonly)
        IF_OPEN   ("rdwr",      &opt_o_rdwr)
        IF_ANY    ("readbytes", &opt_readbytes)
#if HAVE_RESOLV_H
        IF_IP     ("recurse",   &opt_res_recurse)
#endif /* HAVE_RESOLV_H */
#ifdef IP_RECVDSTADDR
        IF_IP     ("recvdstaddr",       &opt_ip_recvdstaddr)
#endif
#ifdef IPV6_RECVDSTOPTS
        IF_IP6    ("recvdstopts",       &opt_ipv6_recvdstopts)
#endif
#ifdef IP_RECVERR
        IF_IP     ("recverr",   &opt_ip_recverr)
#endif
#ifdef IPV6_RECVHOPLIMIT
        IF_IP6    ("recvhoplimit",      &opt_ipv6_recvhoplimit)
#endif
#ifdef IPV6_RECVHOPOPTS
        IF_IP6    ("recvhopopts",       &opt_ipv6_recvhopopts)
#endif
#ifdef IP_RECVIF
        IF_IP     ("recvif",            &opt_ip_recvif)
#endif
#ifdef IP_RECVOPTS
        IF_IP     ("recvopts",  &opt_ip_recvopts)
#endif
#ifdef IPV6_RECVPKTINFO
        IF_IP6    ("recvpktinfo",       &opt_ipv6_recvpktinfo)
#endif
#ifdef IPV6_RECVRTHDR
        IF_IP6    ("recvrthdr", &opt_ipv6_recvrthdr)
#endif
#ifdef IP_RECVTOS
        IF_IP     ("recvtos",   &opt_ip_recvtos)
#endif
#ifdef IP_RECVTTL
        IF_IP     ("recvttl",   &opt_ip_recvttl)
#endif
        IF_NAMED  ("remove",    &opt_unlink)
#ifdef VREPRINT
        IF_TERMIOS("reprint",   &opt_vreprint)
#endif
#if HAVE_RESOLV_H
        IF_IP     ("res-aaonly",        &opt_res_aaonly)
        IF_IP     ("res-debug", &opt_res_debug)
        IF_IP     ("res-defnames",      &opt_res_defnames)
        IF_IP     ("res-dnsrch",        &opt_res_dnsrch)
        IF_IP     ("res-igntc", &opt_res_igntc)
        IF_IP     ("res-primary",       &opt_res_primary)
        IF_IP     ("res-recurse",       &opt_res_recurse)
        IF_IP     ("res-stayopen",      &opt_res_stayopen)
        IF_IP     ("res-usevc", &opt_res_usevc)
#endif /* HAVE_RESOLV_H */
        IF_PROXY  ("resolv",    &opt_proxy_resolve)
        IF_PROXY  ("resolve",   &opt_proxy_resolve)
#ifdef IP_RETOPTS
        IF_IP     ("retopts",   &opt_ip_retopts)
#endif
        IF_RETRY  ("retry",     &opt_retry)
        IF_SOCKET ("reuseaddr", &opt_so_reuseaddr)
#ifdef SO_REUSEPORT     /* AIX 4.3.3 */
        IF_SOCKET ("reuseport", &opt_so_reuseport)
#endif /* defined(SO_REUSEPORT) */
#ifdef TCP_RFC1323
        IF_TCP    ("rfc1323",   &opt_tcp_rfc1323)
#endif
        IF_EXEC   ("right",     &opt_rightfd)
        IF_EXEC   ("rightfd",   &opt_rightfd)
        IF_EXEC   ("rightin",   &opt_rightinfd)
        IF_EXEC   ("rightinfd", &opt_rightinfd)
        IF_EXEC   ("rightout",  &opt_rightoutfd)
        IF_EXEC   ("rightoutfd",&opt_rightoutfd)
#ifdef IP_ROUTER_ALERT
        IF_IP     ("routeralert",       &opt_ip_router_alert)
#endif
#ifdef VREPRINT
        IF_TERMIOS("rprnt",     &opt_vreprint)
#endif
#ifdef O_RSHARE
        IF_OPEN   ("rshare",    &opt_o_rshare)
#endif
#ifdef O_RSYNC
        IF_OPEN   ("rsync",     &opt_o_rsync)
#endif
#ifdef IPV6_RTHDR
        IF_IP6    ("rthdr",     &opt_ipv6_rthdr)
#endif
        IF_TUN    ("running",   &opt_iff_running)
#ifdef TCP_SACK_DISABLE
        IF_TCP    ("sack-disable",      &opt_tcp_sack_disable)
#endif
#ifdef TCP_SACKENA      /* OSF1 */
        IF_TCP    ("sackena",   &opt_tcp_sackena)
#endif
        IF_TERMIOS("sane",      &opt_sane)
#ifdef SCTP_MAXSEG
        IF_SCTP   ("sctp-maxseg",       &opt_sctp_maxseg)
        IF_SCTP   ("sctp-maxseg-late",  &opt_sctp_maxseg_late)
#endif
#ifdef SCTP_NODELAY
        IF_SCTP   ("sctp-nodelay",      &opt_sctp_nodelay)
#endif
#if WITH_EXT2 && defined(EXT2_SECRM_FL)
        IF_ANY    ("secrm",     &opt_ext2_secrm)
#endif
#ifdef SO_SECURITY_AUTHENTICATION
        IF_SOCKET ("security-authentication",   &opt_so_security_authentication)
#endif
#ifdef SO_SECURITY_ENCRYPTION_NETWORK
        IF_SOCKET ("security-encryption-network",       &opt_so_security_encryption_network)
#endif
#ifdef SO_SECURITY_ENCRYPTION_TRANSPORT
        IF_SOCKET ("security-encryption-transport",     &opt_so_security_encryption_transport)
#endif
#ifdef SO_SECURITY_AUTHENTICATION
        IF_SOCKET ("securityauthentication",    &opt_so_security_authentication)
#endif
#ifdef SO_SECURITY_ENCRYPTION_NETWORK
        IF_SOCKET ("securityencryptionnetwork", &opt_so_security_encryption_network)
#endif
#ifdef SO_SECURITY_ENCRYPTION_TRANSPORT
        IF_SOCKET ("securityencryptiontransport",       &opt_so_security_encryption_transport)
#endif
#if HAVE_LSEEK64
        IF_ANY    ("seek",              &opt_lseek64_set)
        IF_ANY    ("seek-cur",          &opt_lseek64_cur)
        IF_ANY    ("seek-end",          &opt_lseek64_end)
        IF_ANY    ("seek-set",          &opt_lseek64_set)
#else
        IF_ANY    ("seek",              &opt_lseek32_set)
        IF_ANY    ("seek-cur",          &opt_lseek32_cur)
        IF_ANY    ("seek-end",          &opt_lseek32_end)
        IF_ANY    ("seek-set",          &opt_lseek32_set)
#endif
        IF_ANY    ("setgid",    &opt_setgid)
        IF_ANY    ("setgid-early",      &opt_setgid_early)
        IF_ANY    ("setlk",     &opt_f_setlk_wr)
        IF_ANY    ("setlk-rd",  &opt_f_setlk_rd)
        IF_ANY    ("setlk-wr",  &opt_f_setlk_wr)
        IF_ANY    ("setlkw",    &opt_f_setlkw_wr)
        IF_ANY    ("setlkw-rd", &opt_f_setlkw_rd)
        IF_ANY    ("setlkw-wr", &opt_f_setlkw_wr)
        IF_EXEC   ("setpgid",   &opt_setpgid)
#if WITH_EXEC || WITH_SYSTEM
        IF_EXEC   ("setsid",    &opt_setsid)
#endif
        IF_SOCKET ("setsockopt-bin",    &opt_setsockopt_bin)
        IF_SOCKET ("setsockopt-int",    &opt_setsockopt_int)
        IF_SOCKET ("setsockopt-string", &opt_setsockopt_string)
        IF_ANY    ("setuid",    &opt_setuid)
        IF_ANY    ("setuid-early",      &opt_setuid_early)
        IF_ANY    ("shut-close",        &opt_shut_close)
        IF_ANY    ("shut-down", &opt_shut_down)
        IF_ANY    ("shut-none", &opt_shut_none)
        IF_ANY    ("shut-null",         &opt_shut_null)
#if WITH_EXEC || WITH_SYSTEM
        IF_ANY    ("sid",       &opt_setsid)
#endif
        IF_EXEC   ("sighup",    &opt_sighup)
        IF_EXEC   ("sigint",    &opt_sigint)
#ifdef TCP_SIGNATURE_ENABLE
        IF_TCP    ("signature-enable",  &opt_tcp_signature_enable)
#endif
        IF_EXEC   ("sigquit",   &opt_sigquit)
#ifdef SIOCSPGRP
        IF_SOCKET ("siocspgrp", &opt_siocspgrp)
#endif
        IF_TUN    ("slave",     &opt_iff_slave)
        IF_SOCKET ("sndbuf",    &opt_so_sndbuf)
        IF_SOCKET ("sndbuf-late",       &opt_so_sndbuf_late)
#ifdef SO_SNDLOWAT
        IF_SOCKET ("sndlowat",  &opt_so_sndlowat)
#endif
#ifdef SO_SNDTIMEO
        IF_SOCKET ("sndtimeo",  &opt_so_sndtimeo)
#endif
#ifdef SO_ACCEPTCONN /* AIX433 */
        IF_SOCKET ("so-acceptconn",     &opt_so_acceptconn)
#endif /* SO_ACCEPTCONN */
#ifdef SO_ATTACH_FILTER
        IF_SOCKET ("so-attach-filter",  &opt_so_attach_filter)
#endif
#ifdef SO_AUDIT /* AIX 4.3.3 */
        IF_SOCKET ("so-audit",  &opt_so_audit)
#endif /* SO_AUDIT */
#ifdef SO_BINDTODEVICE
        IF_SOCKET ("so-bindtodevice",   &opt_so_bindtodevice)
#endif
        IF_SOCKET ("so-broadcast",      &opt_so_broadcast)
#ifdef SO_BSDCOMPAT
        IF_SOCKET ("so-bsdcompat",      &opt_so_bsdcompat)
#endif
#ifdef SO_CKSUMRECV
        IF_SOCKET ("so-cksumrecv",      &opt_so_cksumrecv)
#endif /* SO_CKSUMRECV */
        IF_SOCKET ("so-debug",  &opt_so_debug)
#ifdef SO_DETACH_FILTER
        IF_SOCKET ("so-detach-filter", &opt_so_detach_filter)
#endif
#ifdef SO_DGRAM_ERRIND
        IF_SOCKET ("so-dgram-errind",   &opt_so_dgram_errind)
#endif
#ifdef SO_DONTLINGER
        IF_SOCKET ("so-dontlinger",     &opt_so_dontlinger)
#endif
        IF_SOCKET ("so-dontroute",      &opt_so_dontroute)
        IF_SOCKET ("so-error",  &opt_so_error)
        IF_SOCKET ("so-keepalive",      &opt_so_keepalive)
#ifdef SO_KERNACCEPT    /* AIX 4.3.3 */
        IF_SOCKET ("so-kernaccept",     &opt_so_kernaccept)
#endif /* SO_KERNACCEPT */
        IF_SOCKET ("so-linger", &opt_so_linger)
#ifdef SO_NO_CHECK
        IF_SOCKET ("so-no-check",       &opt_so_no_check)
#endif
#ifdef SO_NOREUSEADDR   /* AIX 4.3.3 */
        IF_SOCKET ("so-noreuseaddr",    &opt_so_noreuseaddr)
#endif /* SO_NOREUSEADDR */
        IF_SOCKET ("so-oobinline",      &opt_so_oobinline)
#ifdef SO_PASSCRED
        IF_SOCKET ("so-passcred",       &opt_so_passcred)
#endif
#ifdef SO_PEERCRED
        IF_SOCKET ("so-peercred",       &opt_so_peercred)
#endif
#ifdef SO_PRIORITY
        IF_SOCKET ("so-priority",       &opt_so_priority)
#endif
#ifdef SO_PROTOTYPE
        IF_SOCKET ("so-prototype",      &opt_so_prototype)
#endif
        IF_SOCKET ("so-rcvbuf", &opt_so_rcvbuf)
        IF_SOCKET ("so-rcvbuf-late",    &opt_so_rcvbuf_late)
#ifdef SO_RCVLOWAT
        IF_SOCKET ("so-rcvlowat",       &opt_so_rcvlowat)
#endif
#ifdef SO_RCVTIMEO
        IF_SOCKET ("so-rcvtimeo",       &opt_so_rcvtimeo)
#endif
        IF_SOCKET ("so-reuseaddr",      &opt_so_reuseaddr)
#ifdef SO_REUSEPORT     /* AIX 4.3.3 */
        IF_SOCKET ("so-reuseport",      &opt_so_reuseport)
#endif /* defined(SO_REUSEPORT) */
#ifdef SO_SECURITY_AUTHENTICATION
        IF_SOCKET ("so-security-authentication",        &opt_so_security_authentication)
#endif
#ifdef SO_SECURITY_ENCRYPTION_NETWORK
        IF_SOCKET ("so-security-encryption-network",    &opt_so_security_encryption_network)
#endif
#ifdef SO_SECURITY_ENCRYPTION_TRANSPORT
        IF_SOCKET ("so-security-encryption-transport",  &opt_so_security_encryption_transport)
#endif
        IF_SOCKET ("so-sndbuf", &opt_so_sndbuf)
        IF_SOCKET ("so-sndbuf-late",    &opt_so_sndbuf_late)
#ifdef SO_SNDLOWAT
        IF_SOCKET ("so-sndlowat",       &opt_so_sndlowat)
#endif
#ifdef SO_SNDTIMEO
        IF_SOCKET ("so-sndtimeo",       &opt_so_sndtimeo)
#endif
#ifdef SO_TIMESTAMP
        IF_SOCKET ("so-timestamp",      &opt_so_timestamp)
#endif
        IF_SOCKET ("so-type",   &opt_so_type)
#ifdef SO_USE_IFBUFS
        IF_SOCKET ("so-use-ifbufs",     &opt_so_use_ifbufs)
#endif /* SO_USE_IFBUFS */
#ifdef SO_USELOOPBACK /* AIX433, Solaris */
        IF_SOCKET ("so-useloopback",    &opt_so_useloopback)
#endif /* SO_USELOOPBACK */
        IF_SOCKET ("sockopt-bin",       &opt_setsockopt_bin)
        IF_SOCKET ("sockopt-int",       &opt_setsockopt_int)
        IF_SOCKET ("sockopt-string",    &opt_setsockopt_string)
        IF_SOCKS5 ("socks5-password",   &opt_socks5_password)
        IF_SOCKS5 ("socks5-username",   &opt_socks5_username)
        IF_SOCKS4 ("socksport", &opt_socksport)
        IF_SOCKS4 ("socksuser", &opt_socksuser)
        IF_SOCKET ("socktype",  &opt_so_type)
        IF_IPAPP  ("sourceport",        &opt_sourceport)
        IF_IPAPP  ("sp",        &opt_sourceport)
        IF_TERMIOS("start",     &opt_vstart)
#if HAVE_RESOLV_H
        IF_IP     ("stayopen",  &opt_res_stayopen)
#endif /* HAVE_RESOLV_H */
        IF_EXEC   ("stderr",    &opt_stderr)
#ifdef TCP_STDURG
        IF_TCP    ("stdurg",    &opt_tcp_stdurg)
#endif
        IF_TERMIOS("stop",      &opt_vstop)
#ifdef I_POP
        IF_ANY    ("streams-i-pop-all", &opt_streams_i_pop_all)
#endif
#ifdef I_PUSH
        IF_ANY    ("streams-i-push",    &opt_streams_i_push)
#endif
        IF_ANY    ("su",        &opt_substuser)
#if defined(HAVE_SETGRENT) && defined(HAVE_GETGRENT) && defined(HAVE_ENDGRENT)
        IF_ANY    ("su-d",      &opt_substuser_delayed)
#endif
        IF_ANY    ("su-e",      &opt_substuser_early)
        IF_ANY    ("substuser", &opt_substuser)
#if defined(HAVE_SETGRENT) && defined(HAVE_GETGRENT) && defined(HAVE_ENDGRENT)
        IF_ANY    ("substuser-delayed", &opt_substuser_delayed)
#endif
        IF_ANY    ("substuser-early",   &opt_substuser_early)
        IF_TERMIOS("susp",      &opt_vsusp)
#ifdef VSWTC
        IF_TERMIOS("swtc",      &opt_vswtc)
        IF_TERMIOS("swtch",     &opt_vswtc)
#endif
        IF_PTY    ("symbolic-link",     &opt_symbolic_link)
#ifdef O_SYNC
        IF_OPEN   ("sync",      &opt_o_sync)
#elif EXT2_SYNC_FL
        IF_ANY    ("sync",      &opt_ext2_sync)
#endif
#ifdef TCP_SYNCNT
        IF_TCP    ("syncnt",    &opt_tcp_syncnt)
#endif
#ifdef TABDLY
#  ifdef TAB0
        IF_TERMIOS("tab0",      &opt_tab0)
#  endif
#  ifdef TAB1
        IF_TERMIOS("tab1",      &opt_tab1)
#  endif
#  ifdef TAB2
        IF_TERMIOS("tab2",      &opt_tab2)
#  endif
#  ifdef TAB3
        IF_TERMIOS("tab3",      &opt_tab3)
#  endif
#  if TABDLY_SHIFT >= 0
        IF_TERMIOS("tabdly",    &opt_tabdly)
#  endif
#endif
        IF_TERMIOS("tandem",    &opt_ixoff)
#ifdef TCP_ABORT_THRESHOLD  /* HP_UX */
        IF_TCP    ("tcp-abort-threshold",       &opt_tcp_abort_threshold)
#endif
#ifdef TCP_CONN_ABORT_THRESHOLD  /* HP_UX */
        IF_TCP    ("tcp-conn-abort-threshold",  &opt_tcp_conn_abort_threshold)
#endif
#ifdef TCP_CORK
        IF_TCP    ("tcp-cork",  &opt_tcp_cork)
#endif
#ifdef TCP_DEFER_ACCEPT /* Linux 2.4.0 */
        IF_TCP    ("tcp-defer-accept",  &opt_tcp_defer_accept)
#endif
#ifdef TCP_INFO /* Linux 2.4.0 */
        IF_TCP    ("tcp-info",  &opt_tcp_info)
#endif
#ifdef TCP_KEEPCNT      /* Linux 2.4.0 */
        IF_TCP    ("tcp-keepcnt",       &opt_tcp_keepcnt)
#endif
#ifdef TCP_KEEPIDLE     /* Linux 2.4.0 */
        IF_TCP    ("tcp-keepidle",      &opt_tcp_keepidle)
#endif
#ifdef TCP_KEEPINIT     /* OSF1 */
        IF_TCP    ("tcp-keepinit",      &opt_tcp_keepinit)
#endif
#ifdef TCP_KEEPINTVL    /* Linux 2.4.0 */
        IF_TCP    ("tcp-keepintvl",     &opt_tcp_keepintvl)
#endif
#ifdef TCP_LINGER2      /* Linux 2.4.0 */
        IF_TCP    ("tcp-linger2",       &opt_tcp_linger2)
#endif
#ifdef TCP_MAXSEG
        IF_TCP    ("tcp-maxseg",        &opt_tcp_maxseg)
        IF_TCP    ("tcp-maxseg-late",   &opt_tcp_maxseg_late)
#endif
#ifdef TCP_MD5SIG
        IF_TCP    ("tcp-md5sig",        &opt_tcp_md5sig)
#endif
#ifdef TCP_NODELAY
        IF_TCP    ("tcp-nodelay",       &opt_tcp_nodelay)
#endif
#ifdef TCP_NOOPT
        IF_TCP    ("tcp-noopt",         &opt_tcp_noopt)
#endif
#ifdef TCP_NOPUSH
        IF_TCP    ("tcp-nopush",        &opt_tcp_nopush)
#endif
#ifdef TCP_PAWS /* OSF1 */
        IF_TCP    ("tcp-paws",          &opt_tcp_paws)
#endif
#ifdef TCP_QUICKACK
        IF_TCP    ("tcp-quickack",      &opt_tcp_quickack)
#endif
#ifdef TCP_RFC1323
        IF_TCP    ("tcp-rfc1323",       &opt_tcp_rfc1323)
#endif
#ifdef TCP_SACK_DISABLE
        IF_TCP    ("tcp-sack-disable",  &opt_tcp_sack_disable)
#endif
#ifdef TCP_SACKENA      /* OSF1 */
        IF_TCP    ("tcp-sackena",       &opt_tcp_sackena)
#endif
#ifdef TCP_SIGNATURE_ENABLE
        IF_TCP    ("tcp-signature-enable",      &opt_tcp_signature_enable)
#endif
#ifdef TCP_STDURG
        IF_TCP    ("tcp-stdurg",        &opt_tcp_stdurg)
#endif
#ifdef TCP_SYNCNT       /* Linux 2.4.0 */
        IF_TCP    ("tcp-syncnt",        &opt_tcp_syncnt)
#endif
#ifdef TCP_TSOPTENA     /* OSF1 */
        IF_TCP    ("tcp-tsoptena",      &opt_tcp_tsoptena)
#endif
#ifdef TCP_WINDOW_CLAMP /* Linux 2.4.0 */
        IF_TCP    ("tcp-window-clamp",  &opt_tcp_window_clamp)
#endif
#if WITH_LIBWRAP
        IF_IPAPP  ("tcpwrap",           &opt_tcpwrappers)
        IF_IPAPP  ("tcpwrap-dir",       &opt_tcpwrap_etc)
        IF_IPAPP  ("tcpwrap-etc",       &opt_tcpwrap_etc)
#if WITH_LIBWRAP && defined(HAVE_HOSTS_ALLOW_TABLE)
        IF_IPAPP  ("tcpwrap-hosts-allow-table", &opt_tcpwrap_hosts_allow_table)
#endif
#if WITH_LIBWRAP && defined(HAVE_HOSTS_DENY_TABLE)
        IF_IPAPP  ("tcpwrap-hosts-deny-table",  &opt_tcpwrap_hosts_deny_table)
#endif
        IF_IPAPP  ("tcpwrapper",        &opt_tcpwrappers)
        IF_IPAPP  ("tcpwrappers",       &opt_tcpwrappers)
#endif
        IF_TERMIOS("termios-cfmakeraw", &opt_termios_cfmakeraw)
        IF_TERMIOS("termios-rawer",     &opt_termios_rawer)
#ifdef O_TEXT
        IF_ANY    ("text",      &opt_o_text)
#endif
        IF_UNIX   ("tightsocklen",      &xioopt_unix_tightsocklen)
        IF_TERMIOS("time",      &opt_vtime)
#ifdef SO_TIMESTAMP
        IF_SOCKET ("timestamp", &opt_so_timestamp)
#endif
        IF_TERMIOS("tiocsctty", &opt_tiocsctty)
#if WITH_EXT2 && defined(EXT2_TOPDIR_FL)
        IF_ANY    ("topdir",    &opt_ext2_topdir)
#endif
        IF_IP     ("tos",       &opt_ip_tos)
        IF_TERMIOS("tostop",    &opt_tostop)
        IF_OPEN   ("trunc",     &opt_o_trunc)
#if HAVE_FTRUNCATE64
        IF_ANY    ("truncate",  &opt_ftruncate64)
#else
        IF_ANY    ("truncate",  &opt_ftruncate32)
#endif
#ifdef TCP_TSOPTENA     /* OSF1 */
        IF_TCP    ("tsoptena",  &opt_tcp_tsoptena)
#endif
        IF_IP     ("ttl",       &opt_ip_ttl)
        IF_TUN    ("tun-device",        &opt_tun_device)
        IF_TUN    ("tun-name",  &opt_tun_name)
        IF_TUN    ("tun-no-pi", &opt_iff_no_pi)
        IF_TUN    ("tun-type",  &opt_tun_type)
        IF_SOCKET ("type",      &opt_so_type)
        IF_ANY    ("uid",       &opt_user)
        IF_NAMED  ("uid-e",     &opt_user_early)
        IF_ANY    ("uid-l",     &opt_user_late)
        IF_NAMED  ("umask",     &opt_umask)
        IF_IP6    ("unicast-hops",      &opt_ipv6_unicast_hops)
        IF_UNIX   ("unix-tightsocklen", &xioopt_unix_tightsocklen)
        IF_NAMED  ("unlink",    &opt_unlink)
        IF_NAMED  ("unlink-close",      &opt_unlink_close)
        IF_NAMED  ("unlink-early",      &opt_unlink_early)
        IF_NAMED  ("unlink-late",       &opt_unlink_late)
#if WITH_EXT2 && defined(EXT2_UNRM_FL)
        IF_ANY    ("unrm",              &opt_ext2_unrm)
#endif
        IF_TUN    ("up",        &opt_iff_up)
#ifdef SO_USE_IFBUFS
        IF_SOCKET ("use-ifbufs",        &opt_so_use_ifbufs)
        IF_SOCKET ("useifbufs",         &opt_so_use_ifbufs)
#endif /* SO_USE_IFBUFS */
#ifdef SO_USELOOPBACK /* AIX433, Solaris */
        IF_SOCKET ("useloopback",       &opt_so_useloopback)
#endif /* SO_USELOOPBACK */
        IF_ANY    ("user",      &opt_user)
        IF_NAMED  ("user-early",        &opt_user_early)
        IF_ANY    ("user-late", &opt_user_late)
#if HAVE_RESOLV_H
        IF_IP     ("usevc",     &opt_res_usevc)
#endif /* HAVE_RESOLV_H */
#ifdef IPV6_V6ONLY
        IF_IP6    ("v6only",    &opt_ipv6_v6only)
#endif
#ifdef VDISCARD
        IF_TERMIOS("vdiscard",  &opt_vdiscard)
#endif
#ifdef VDSUSP   /* HP-UX */
        IF_TERMIOS("vdsusp",    &opt_vdsusp)
#endif
        IF_TERMIOS("veof",      &opt_veof)
        IF_TERMIOS("veol",      &opt_veol)
        IF_TERMIOS("veol2",     &opt_veol2)
        IF_TERMIOS("verase",    &opt_verase)
        IF_OPENSSL("verify",    &opt_openssl_verify)
        IF_TERMIOS("vintr",     &opt_vintr)
        IF_TERMIOS("vkill",     &opt_vkill)
        IF_TERMIOS("vlnext",    &opt_vlnext)
        IF_TERMIOS("vmin",      &opt_vmin)
        IF_TERMIOS("vquit",     &opt_vquit)
#ifdef VREPRINT
        IF_TERMIOS("vreprint",  &opt_vreprint)
#endif
        IF_TERMIOS("vstart",    &opt_vstart)
        IF_TERMIOS("vstop",     &opt_vstop)
        IF_TERMIOS("vsusp",     &opt_vsusp)
#ifdef VSWTC
        IF_TERMIOS("vswtc",     &opt_vswtc)
#endif
#ifdef VTDLY
#  ifdef VT0
        IF_TERMIOS("vt0",       &opt_vt0)
#  endif
#  ifdef VT1
        IF_TERMIOS("vt1",       &opt_vt1)
#  endif
        IF_TERMIOS("vtdly",     &opt_vtdly)
#endif
        IF_TERMIOS("vtime",     &opt_vtime)
#ifdef VWERASE
        IF_TERMIOS("vwerase",   &opt_vwerase)
#endif
#if HAVE_PTY && HAVE_POLL
        IF_PTY    ("wait-slave",        &opt_pty_wait_slave)
#endif /* HAVE_PTY && HAVE_POLL */
        IF_ANY    ("waitlock",  &opt_waitlock)
#if HAVE_PTY && HAVE_POLL
        IF_PTY    ("waitslave", &opt_pty_wait_slave)
#endif /* HAVE_PTY && HAVE_POLL */
#ifdef VWERASE
        IF_TERMIOS("werase",    &opt_vwerase)
#endif
#ifdef TCP_WINDOW_CLAMP /* Linux 2.4.0 */
        IF_TCP    ("window-clamp",      &opt_tcp_window_clamp)
#endif
#if WITH_LIBWRAP
        IF_IPAPP  ("wrap",              &opt_tcpwrappers)
#endif
        IF_OPEN   ("wronly",    &opt_o_wronly)
#ifdef XCASE
        IF_TERMIOS("xcase",     &opt_xcase)
#endif
#if defined(TABDLY) && defined(XTABS)
        IF_TERMIOS("xtabs",     &opt_xtabs)
#endif
        { NULL }
} ;


/* walks the text argument a and writes its options that conform to groups 
   to the array opts. Uses the option table 'optionnames'.
   returns 0 on success, -1 on error, 1 on unknown/wrong option  
*/
int parseopts(const char **a, struct opt **opts) {

   return parseopts_table(a, opts, optionnames, 
                          sizeof(optionnames)/sizeof(struct optname)-1);
}


/* walks the text argument a and writes its options that conform to groups 
   to the array opts. Uses the specified option table.
   returns 0 on success, -1 on error, 1 on unknown/wrong option  
*/
int parseopts_table(const char **a, struct opt **opts,
              const struct optname optionnames[], size_t optionnum) {
   int i=0;
   struct opt *opt;
   bool assign;
   const char *a0 = *a;
   unsigned long ulongval;
   long slongval;
   long long slonglongval;
   char token[512], *tokp;  size_t len;
   int parsres;
   int result;
   char optbuf[256];  size_t optlen;
   const char *endkey[6+1];
   const char *endval[5+1];
   const char *assign_str = "=";
   const char *hquotes[] = {
      "'",
      NULL
   } ;
   const char *squotes[] = {
      "\"",
      NULL
   } ;
   const char *nests[] = {
      "(", ")",
      "[", "]",
      "{", "}",
      NULL
   } ;

   i = 0;
   endkey[i++] = xioopts.chainsep;      /* default: "|" */
   endkey[i++] = xioopts.pipesep;               /* default: "%" */
   endkey[i++] = ","/*xioopts.comma*/;          /* default: "," */
   endkey[i++] = "=";
   endkey[i++] = NULL;

   i = 0;
   endval[i++] = xioopts.chainsep;      /* default: "|" */
   endval[i++] = xioopts.pipesep;               /* default: "%" */
   endval[i++] = ","/*xioopts.comma*/;          /* default: "," */
   endval[i++] = NULL;

   i = 0;
   *opts = Malloc((i+8)*sizeof(struct opt));
   if (*opts == NULL) {
      return -1;
   }
   if (*a == NULL) {
      (*opts)[i].desc = ODESC_END;
      return 0;
   }

   while (true) {
      const struct optname *ent;

      if (a == NULL || *a == NULL || **a == '\0')
         break;

      while (!strncmp(*a, ",", strlen(",")))  { (*a) += strlen(","); }
      a0 = *a;

      len = sizeof(token);  tokp = token;
      parsres =
         nestlex(a, &tokp, &len, endkey, hquotes, squotes, nests,
                 true, true, true, false);
      if (parsres < 0) {
         Error1("option too long:  \"%s\"", *a);
         return -1;
      } else if (parsres > 0) {
         Error1("syntax error in \"%s\"", *a);
         return -1;
      }
      if (tokp == token) {
         /* no option found */
         break;
      }
      *tokp = '\0';

      ent = (struct optname *)
         keyw((struct wordent *)optionnames, token, optionnum);
      if (ent == NULL) {
         Error1("parseopts(): unknown option \"%s\"", token);
         continue;
      }

#if 0
      if (!(ent->desc->group & groups) && !(ent->desc->group & GROUP_ANY) &&
          !xioopts_ignoregroups) {
         Error1("parseopts(): option \"%s\" not supported with this address type",
                token /*a0*/);
         Info2("parseopts()  groups=%08x, ent->group=%08x",
               groups, ent->desc->group);
#if 0
         continue;
#endif
      }
#endif
      (*opts)[i].desc = ent->desc;
      
      if (!strncmp(*a, assign_str, strlen(assign_str))) {
         /* there is an assignment (mostly "=") */
         (*a) += strlen(assign_str);
         len = sizeof(token);  tokp = token;
         parsres =
            nestlex(a, &tokp, &len, endval, hquotes, squotes, nests,
                    true, true, true, false);
         if (parsres < 0) {
            Error1("option too long:  \"%s\"", *a);
            return -1;
         } else if (parsres > 0) {
            Error1("syntax error in \"%s\"", *a);
            return -1;
         }
         *tokp = '\0';
         assign = true;

      } else {
         assign = false;
      }
      opt = &(*opts)[i];

      switch (ent->desc->type) {
      case TYPE_CONST:
         if (assign) {
            Error1("no value permitted for option \"%s\"",
                   ent->desc->defname);
            continue;
         }
         Info1("setting option \"%s\"", ent->desc->defname);
         break;
      case TYPE_BIN:
         if (!assign) { Error1("option \"%s\": value required", a0);
            continue; }
         optlen = 0;
         if ((result = dalan(token, optbuf, &optlen, sizeof(optbuf))) != 0) {
            Error1("parseopts(): problem with \"%s\" data", token);
            continue;
         }
         if (((*opts)[i].value.u_bin.b_data = memdup(optbuf, optlen)) == NULL) {
            Error1("memdup(, "F_Zu"): out of memory", optlen);
            return -1;
         }
         (*opts)[i].value.u_bin.b_len = optlen;
         break;
      case TYPE_BYTE:
         if (assign) {
          unsigned long ul;
          char *rest;
          ul = strtoul(token, &rest/*!*/, 0);
          if (ul > UCHAR_MAX) {
            Error3("parseopts(%s): byte value exceeds limit (%lu vs. %u), using max",
                   a0, ul, UCHAR_MAX);
            (*opts)[i].value.u_byte = UCHAR_MAX;
          } else {
            (*opts)[i].value.u_byte = ul;
          }
         } else {
            (*opts)[i].value.u_byte = 1;
         }
         Info2("setting option \"%s\" to %d", ent->desc->defname,
               (*opts)[i].value.u_byte);
         break;
#if HAVE_BASIC_OFF_T==3
      case TYPE_OFF32:
#endif
      case TYPE_INT:
         if (assign) {
            char *rest;
            (*opts)[i].value.u_int = strtoul(token, &rest/*!*/, 0);
         } else {
            (*opts)[i].value.u_int = 1;
         }
         Info2("setting option \"%s\" to %d", ent->desc->defname,
               (*opts)[i].value.u_int);
         break;
      case TYPE_BOOL:
         if (!assign) {
            (*opts)[i].value.u_bool = 1;
         } else {
            char *rest;
            (*opts)[i].value.u_bool = strtoul(token, &rest, 0);
            if (rest && *rest) {
               Error1("error in option \"%s\": \"0\" or \"1\" required", a0);
            }
         }
         Info2("setting option \"%s\" to %d", ent->desc->defname,
               (*opts)[i].value.u_bool);
         break;

#if HAVE_BASIC_SIZE_T==4
      case TYPE_SIZE_T:
#endif
      case TYPE_UINT:
         if (!assign) {
            (*opts)[i].value.u_uint = 1;
         } else {
            char *rest;
            ulongval = strtoul(token, &rest/*!*/, 0);
            if (ulongval > UINT_MAX) {
               Error3("parseopts(%s): unsigned int value exceeds limit (%lu vs. %u), using max",
                      a0, ulongval, UINT_MAX);
            }
            (*opts)[i].value.u_uint = ulongval;
         }
         Info2("setting option \"%s\" to %u", ent->desc->defname,
               (*opts)[i].value.u_uint);
         break;

#if HAVE_BASIC_SIZE_T==2
      case TYPE_SIZE_T:
#endif
      case TYPE_USHORT:
         if (!assign) {
            (*opts)[i].value.u_ushort = 1;
         } else {
            char *rest;
            ulongval = strtoul(token, &rest/*!*/, 0);
            if (ulongval > USHRT_MAX) {
               Error3("parseopts(%s): unsigned short value exceeds limit (%lu vs. %u), using max",
                      a0, ulongval, USHRT_MAX);
            }
            (*opts)[i].value.u_ushort = ulongval;
         }
         Info2("setting option \"%s\" to %u", ent->desc->defname,
               (*opts)[i].value.u_ushort);
         break;

#if HAVE_BASIC_OFF_T==5
      case TYPE_OFF32:
#endif
#if HAVE_STAT64 && defined(HAVE_BASIC_OFF64_T) && HAVE_BASIC_OFF64_T==5
      case TYPE_OFF64:
#endif
      case TYPE_LONG:
         if (!assign) {
            (*opts)[i].value.u_long = 1;
         } else {
            char *rest;
            slongval = strtol(token, &rest, 0);
            (*opts)[i].value.u_long = slongval;
         }
         Info2("setting option \"%s\" to %lu", ent->desc->defname,
               (*opts)[i].value.u_long);
         break;

#if HAVE_BASIC_SIZE_T==6
      case TYPE_SIZE_T:
#endif
      case TYPE_ULONG:
         if (!assign) {
            (*opts)[i].value.u_ulong = 1;
         } else {
            char *rest;
            ulongval = strtoul(token, &rest, 0);
            (*opts)[i].value.u_ulong = ulongval;
         }
         Info2("setting option \"%s\" to %lu", ent->desc->defname,
               (*opts)[i].value.u_ulong);
         break;

#if HAVE_TYPE_LONGLONG
      case TYPE_LONGLONG:
#  if HAVE_STAT64 && defined(HAVE_BASIC_OFF64_T) && HAVE_BASIC_OFF64_T==7
      case TYPE_OFF64:
#  endif
         if (!assign) {
            (*opts)[i].value.u_longlong = 1;
         } else {
            char *rest;
#  if HAVE_STRTOLL
            slonglongval = strtoll(token, &rest, 0);
#  else
            /* in this case, input value range is limited */
            slonglongval = strtol(token, &rest, 0);
#  endif /* HAVE_STRTOLL */
            (*opts)[i].value.u_longlong = slonglongval;
         }
         Info2("setting option \"%s\" to %Lu", ent->desc->defname,
               (*opts)[i].value.u_longlong);
         break;
#endif /* HAVE_TYPE_LONGLONG */

      case TYPE_UIDT:
         if (!assign) {
            Error1("option \"%s\": value required", a0);
            continue;
         }
         if (isdigit((*token)&0xff)) {
            char *rest;
            (*opts)[i].value.u_uidt = strtoul(token, &rest/*!*/, 0);
         } else {
            struct passwd *pwd;
            if ((pwd = getpwnam(token)) == NULL) {
               Error1("getpwnam(\"%s\"): no such user", token);
               continue;
            }
            (*opts)[i].value.u_uidt = getpwnam(token)->pw_uid;
         }
         Info2("setting option \"%s\" to %u", ent->desc->defname,
               (*opts)[i].value.u_uidt);
         break;

      case TYPE_GIDT:
         if (!assign) { Error1("option \"%s\": value required", a0);
            continue; }
         if (isdigit((token[0])&0xff)) {
            char *rest;
            (*opts)[i].value.u_gidt = strtoul(token, &rest/*!*/, 0);
         } else {
            struct group *grp;
            grp = getgrnam(token);
            if (grp == NULL) {
               Error1("getgrnam(\"%s\"): no such group", token);
               continue;
            }
            (*opts)[i].value.u_gidt = grp->gr_gid;
         }
         Info2("setting option \"%s\" to %u", ent->desc->defname,
               (*opts)[i].value.u_gidt);
         break;

      case TYPE_MODET:
         if (!assign) { Error1("option \"%s\": value required", a0);
            continue;
         }
         {
            char *rest;
            (*opts)[i].value.u_modet = strtoul(token, &rest/*!*/, 8);
         }
         Info2("setting option \"%s\" to %u", ent->desc->defname,
               (*opts)[i].value.u_modet);
         break;

      case TYPE_STRING:
         if (!assign) {
            Error1("option \"%s\": value required", a0);
            continue;
         }
         if (((*opts)[i].value.u_string = strdup(token)) == NULL) {
            Error("out of memory"); return -1;
         }
         Info2("setting option \"%s\" to \"%s\"", ent->desc->defname,
               (*opts)[i].value.u_string);
         break;

      case TYPE_STRING_NULL:
         if (!assign) {
            (*opts)[i].value.u_string = NULL;
            Info1("setting option \"%s\" to NULL", ent->desc->defname);
         } else {
            (*opts)[i].value.u_string = strdup(token);
            Info2("setting option \"%s\" to \"%s\"", ent->desc->defname,
                  (*opts)[i].value.u_string);
         }
         break;

#if LATER
      case TYPE_INT3:
         
         break;
#endif

      case TYPE_TIMEVAL:
         if (!assign) {
            Error1("option \"%s\": value required", a0);
            continue;
         } else {
            double val;
            val = strtod(token, NULL);
            if (val == HUGE_VAL || val == -HUGE_VAL ||
                val == 0.0 && errno == ERANGE) {
               Error2("strtod(\"%s\", NULL): %s", token, strerror(errno));
               val = 0.0;
            }
            (*opts)[i].value.u_timeval.tv_sec  = val;
            (*opts)[i].value.u_timeval.tv_usec =
               (val-(*opts)[i].value.u_timeval.tv_sec) * 1000000;
         }
         break;

#if HAVE_STRUCT_TIMESPEC
      case TYPE_TIMESPEC:
         if (!assign) {
            Error1("option \"%s\": value required", a0);
            continue;
         } else {
            double val;
            val = strtod(token, NULL);
            if (val == HUGE_VAL || val == -HUGE_VAL ||
                val == 0.0 && errno == ERANGE) {
               Error2("strtod(\"%s\", NULL): %s", token, strerror(errno));
               val = 0.0;
            }
            (*opts)[i].value.u_timespec.tv_sec  = val;
            (*opts)[i].value.u_timespec.tv_nsec =
               (val-(*opts)[i].value.u_timespec.tv_sec) * 1000000000.;
         }
         break;
#endif /* HAVE_STRUCT_TIMESPEC */

#if HAVE_STRUCT_LINGER
      case TYPE_LINGER:
         if (!assign) {
            Error1("option \"%s\": value required", a0);
            continue;
         }
         (*opts)[i].value.u_linger.l_onoff = 1;
         {
            char *rest;
            (*opts)[i].value.u_linger.l_linger = strtoul(token, &rest/*!*/, 0);
         }
         Info3("setting option \"%s\" to {%d,%d}", ent->desc->defname,
               (*opts)[i].value.u_linger.l_onoff,
               (*opts)[i].value.u_linger.l_linger);
         break;
#endif /* HAVE_STRUCT_LINGER */

      case TYPE_INT_INT:
      case TYPE_INT_INTP:
         if (!assign) {
            Error1("option \"%s\": values required", a0);
            continue;
         }
         {
            char *rest;
            (*opts)[i].value.u_int = strtoul(token, &rest, 0);
            if (*rest != ':') {
               Error1("option \"%s\": 2 arguments required",
                      ent->desc->defname);
            }
            ++rest;
            (*opts)[i].value2.u_int = strtoul(rest, &rest, 0);
         }
         Info3("setting option \"%s\" to %d:%d", ent->desc->defname,
               (*opts)[i].value.u_int, (*opts)[i].value2.u_int);
         break;

      case TYPE_INT_BIN:
         if (!assign) {
            Error1("option \"%s\": values required", a0);
            continue;
         }
         {
            char *rest;
            (*opts)[i].value.u_int = strtoul(token, &rest, 0);
            if (*rest != ':') {
               Error1("option \"%s\": 2 arguments required",
                      ent->desc->defname);
            }
            ++rest;
            optlen = 0;
            if ((result = dalan(rest, optbuf, &optlen, sizeof(optbuf))) != 0) {
               Error1("parseopts(): problem with \"%s\" data", rest);
               continue;
            }
            if (((*opts)[i].value2.u_bin.b_data = memdup(optbuf, optlen)) == NULL) {
               Error1("memdup(, "F_Zu"): out of memory", optlen);
               return -1;
            }
            (*opts)[i].value2.u_bin.b_len = optlen;
         }
         Info2("setting option \"%s\" to %d:..."/*!!!*/, ent->desc->defname,
               (*opts)[i].value.u_int);
         break;

      case TYPE_INT_STRING:
         if (!assign) {
            Error1("option \"%s\": values required", a0);
            continue;
         }
         {
            char *rest;
            (*opts)[i].value.u_int = strtoul(token, &rest, 0);
            if (*rest != ':') {
               Error1("option \"%s\": 2 arguments required",
                      ent->desc->defname);
            }
            ++rest;
            if (((*opts)[i].value2.u_string = strdup(rest)) == NULL) {
               Error("out of memory"); return -1;
            }
         }
         Info3("setting option \"%s\" to %d:\"%s\"", ent->desc->defname,
               (*opts)[i].value.u_int, (*opts)[i].value2.u_string);
         break;

      case TYPE_INT_INT_INT:
         if (!assign) {
            Error1("option \"%s\": values required", a0);
            continue;
         }
         {
            char *rest;
            (*opts)[i].value.u_int = strtoul(token, &rest, 0);
            if (*rest != ':') {
               Error1("option \"%s\": 3 arguments required",
                      ent->desc->defname);
            }
            ++rest;
            (*opts)[i].value2.u_int = strtoul(rest, &rest, 0);
            if (*rest != ':') {
               Error1("option \"%s\": 3 arguments required",
                      ent->desc->defname);
            }
            ++rest;
            (*opts)[i].value3.u_int = strtoul(rest, &rest, 0);
         }
         Info4("setting option \"%s\" to %d:%d:%d", ent->desc->defname,
               (*opts)[i].value.u_int, (*opts)[i].value2.u_int, (*opts)[i].value3.u_int);
         break;

      case TYPE_INT_INT_BIN:
         if (!assign) {
            Error1("option \"%s\": values required", a0);
            continue;
         }
         {
            char *rest;
            (*opts)[i].value.u_int = strtoul(token, &rest, 0);
            if (*rest != ':') {
               Error1("option \"%s\": 3 arguments required",
                      ent->desc->defname);
            }
            ++rest;
            (*opts)[i].value2.u_int = strtoul(rest, &rest, 0);
            if (*rest != ':') {
               Error1("option \"%s\": 3 arguments required",
                      ent->desc->defname);
            }
            ++rest;
            optlen = 0;
            if ((result = dalan(rest, optbuf, &optlen, sizeof(optbuf))) != 0) {
               Error1("parseopts(): problem with \"%s\" data", rest);
               continue;
            }
            if (((*opts)[i].value3.u_bin.b_data = memdup(optbuf, optlen)) == NULL) {
               Error1("memdup(, "F_Zu"): out of memory", optlen);
               return -1;
            }
            (*opts)[i].value3.u_bin.b_len = optlen;
         }
         Info3("setting option \"%s\" to %d:%d:..."/*!!!*/, ent->desc->defname,
               (*opts)[i].value.u_int, (*opts)[i].value2.u_int);
         break;

      case TYPE_INT_INT_STRING:
         if (!assign) {
            Error1("option \"%s\": values required", a0);
            continue;
         }
         {
            char *rest;
            (*opts)[i].value.u_int = strtoul(token, &rest, 0);
            if (*rest != ':') {
               Error1("option \"%s\": 3 arguments required",
                      ent->desc->defname);
            }
            ++rest;
            (*opts)[i].value2.u_int = strtoul(rest, &rest, 0);
            if (*rest != ':') {
               Error1("option \"%s\": 3 arguments required",
                      ent->desc->defname);
            }
            ++rest;
            if (((*opts)[i].value3.u_string = strdup(rest)) == NULL) {
               Error("out of memory"); return -1;
            }
         }
         Info4("setting option \"%s\" to %d:%d:\"%s\"", ent->desc->defname,
               (*opts)[i].value.u_int, (*opts)[i].value2.u_int,
               (*opts)[i].value3.u_string);
         break;
#if defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN)

      case TYPE_IP_MREQN:
         {
            /* we do not resolve the addresses here because we do not yet know
               if we are coping with a IPv4 or IPv6 socat address */
            const char *ends[] = { ":", NULL };
            const char *nests[] = { "[","]", NULL };
            char buff[512], *buffp=buff; size_t bufspc = sizeof(buff)-1;

            /* parse first IP address, expect ':' */
            tokp = token;
            parsres =
               nestlex((const char **)&tokp, &buffp, &bufspc,
                       ends, NULL, NULL, nests,
                       true, true, false, false);
            if (parsres < 0) {
               Error1("option too long:  \"%s\"", *a);
               return -1;
            } else if (parsres > 0) {
               Error1("syntax error in \"%s\"", *a);
               return -1;
            }
            if (*tokp != ':') {
               Error1("syntax in option %s: missing ':'", token);
            }
            *buffp++ = '\0';
            (*opts)[i].value.u_ip_mreq.multiaddr = strdup(buff); /*!!! NULL */

            ++tokp;
            /* parse second IP address, expect ':' or '\0'' */
            buffp = buff;
            parsres =
               nestlex((const char **)&tokp, &buffp, &bufspc,
                       ends, NULL, NULL, nests,
                       true, true, false, false);
            if (parsres < 0) {
               Error1("option too long:  \"%s\"", *a);
               return -1;
            } else if (parsres > 0) {
               Error1("syntax error in \"%s\"", *a);
               return -1;
            }
            *buffp++ = '\0';
            (*opts)[i].value.u_ip_mreq.param2 = strdup(buff); /*!!! NULL */

#if HAVE_STRUCT_IP_MREQN            
            if (*tokp++ == ':') {
               strncpy((*opts)[i].value.u_ip_mreq.ifindex, tokp, IF_NAMESIZE);  /* ok */
               Info4("setting option \"%s\" to {\"%s\",\"%s\",\"%s\"}",
                     ent->desc->defname,
                     (*opts)[i].value.u_ip_mreq.multiaddr,
                     (*opts)[i].value.u_ip_mreq.param2,
                     (*opts)[i].value.u_ip_mreq.ifindex);
            } else {
               (*opts)[i].value.u_ip_mreq.ifindex[0] = '\0';
               Info3("setting option \"%s\" to {\"%s\",\"%s\"}",
                     ent->desc->defname,
                     (*opts)[i].value.u_ip_mreq.multiaddr,
                     (*opts)[i].value.u_ip_mreq.param2);
            }
#else /* !HAVE_STRUCT_IP_MREQN */
            Info3("setting option \"%s\" to {0x%08x,0x%08x}",
                  ent->desc->defname,
                  (*opts)[i].value.u_ip_mreq.multiaddr,
                  (*opts)[i].value.u_ip_mreq.param2);
#endif /* !HAVE_STRUCT_IP_MREQN */
         }
         break;
#endif /* defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN) */

#if WITH_IP4
      case TYPE_IP4NAME:
         {
            struct sockaddr_in sa;  socklen_t salen = sizeof(sa);
            const char *ends[] = { NULL };
            const char *nests[] = { "[","]", NULL };
            char buff[512], *buffp=buff; size_t bufspc = sizeof(buff)-1;

            tokp = token;
            parsres =
            nestlex((const char **)&tokp, &buffp, &bufspc,
                    ends, NULL, NULL, nests,
                    true, true, false, false);
            if (parsres < 0) {
               Error1("option too long:  \"%s\"", *a);
               return -1;
            } else if (parsres > 0) {
               Error1("syntax error in \"%s\"", *a);
               return -1;
            }
            if (*tokp != '\0') {
               Error1("trailing data in option \"%s\"", token);
            }
            *buffp = '\0';
            if (xiogetaddrinfo(buff, NULL, AF_INET, SOCK_DGRAM, IPPROTO_IP,
                               (union sockaddr_union *)&sa, &salen,
                               0, 0/*!!!*/) != STAT_OK) {
               opt->desc = ODESC_ERROR; continue;
            }
            opt->value.u_ip4addr = sa.sin_addr;
         }
         break;
#endif /* defined(WITH_IP4) */

      default:
         Error2("parseopts(): internal error on option \"%s\": unimplemented type %d",
                ent->desc->defname, ent->desc->type);
         continue;
      }

      ++i;
      if ((i % 8) == 0) {
         *opts = Realloc(*opts, (i+8) * sizeof(struct opt));
         if (*opts == NULL) {
            return -1;
         }
      }
   }

   /*(*opts)[i+1].desc = ODESC_END;*/
   (*opts)[i].desc = ODESC_END;
   return 0;
}


/* checks if the options conform to the group set.
   returns 0 if all options conform to the group set,
   or -1 otherwise. */
int xiocheckopts(struct opt *opts, unsigned int groups) {
   const struct opt *opt = opts;

   if (opts == NULL) {
      return 0;
   }
   while (opt->desc != ODESC_END) {

      if (!(opt->desc->group & groups) &&
          !(opt->desc->group & GROUP_ANY) &&
          !xioopts_ignoregroups) {
         Error1("option \"%s\" not supported with this address type",
                opt->desc->defname);
         Info2("parseopts()  groups=%08x, opt->group=%08x",
               groups, opt->desc->group);
         return -1;
      }
   }
   return 0;
}


/* copy the already parsed options for repeated application, but only those
   matching groups ANY and <groups> */
struct opt *copyopts(const struct opt *opts, unsigned int groups) {
   struct opt *new;
   int i, j, n;

   if (!opts)  return NULL;

   /* just count the options in the array */
   i = 0; while (opts[i].desc != ODESC_END) {
      ++i;
   }
   n = i+1;

   new = Malloc(n * sizeof(struct opt));
   if (new == NULL) {
      return NULL;
   }

   i = 0, j = 0;
   while (i < n-1) {
      if (opts[i].desc == ODESC_DONE) {
         new[j].desc = ODESC_DONE;
      } else if ((opts[i].desc->group & (GROUP_ANY&~GROUP_PROCESS)) ||
                 (opts[i].desc->group & groups)) {
         new[j++] = opts[i];
      }
      ++i;
   }
   new[j].desc = ODESC_END;
   return new;
}

/* move options to a new options list
   move only those matching <groups> */
struct opt *moveopts(struct opt *opts, unsigned int groups) {
   struct opt *new;
   int i, j, n;

   if (!opts)  return NULL;

   /* just count the options in the array */
   i = 0; j = 0; while (opts[i].desc != ODESC_END) {
      if (opts[i].desc != ODESC_DONE &&
          opts[i].desc != ODESC_ERROR)
         ++j;
      ++i;
   }
   n = i;

   new = Malloc((j+1) * sizeof(struct opt));
   if (new == NULL) {
      return NULL;
   }

   i = 0, j = 0;
   while (i < n) {
      if (opts[i].desc == ODESC_DONE ||
          opts[i].desc == ODESC_ERROR) {
         ++i; continue;
      } else if (opts[i].desc->group & groups) {
         new[j++] = opts[i];
         opts[i].desc = ODESC_DONE;
      }
      ++i;
   }
   new[j].desc = ODESC_END;
   return new;
}

/* return the number of yet unconsumed options; -1 on error */
int leftopts(const struct opt *opts) {
   const struct opt *opt = opts;
   int num = 0;

   if (!opts)  return 0;

   while (opt->desc != ODESC_END) {
      if (opt->desc != ODESC_DONE) {
         ++num;
      }
      ++opt;
   }
   return num;
}

/* show as warning which options are still unused */
int showleft(const struct opt *opts) {
   const struct opt *opt = opts;

   while (opt->desc != ODESC_END) {
      if (opt->desc != ODESC_DONE) {
         Warn1("showleft(): option \"%s\" not inquired", opt->desc->defname);
      }
      ++opt;
   }
   return 0;
}


/* determines the address group from mode_t */
/* does not set GROUP_FD; cannot determine GROUP_TERMIOS ! */
int _groupbits(mode_t mode) {
   unsigned int result = 0;
  
   switch ((mode&S_IFMT)>>12) {
   case (S_IFIFO>>12):  /* 1, FIFO */
      result = GROUP_FIFO;   break;
   case (S_IFCHR>>12):  /* 2, character device */
      result = GROUP_TERMIOS;    break;
   case (S_IFDIR>>12):  /* 4, directory !!! not supported */
      result = GROUP_NONE;   break;
   case (S_IFBLK>>12):  /* 6, block device */
      result = GROUP_BLK;    break;
   case (S_IFREG>>12):  /* 8, regular file */
      result = GROUP_REG;    break;
   case (S_IFLNK>>12):  /* 10, symbolic link !!! not supported */
      result = GROUP_NONE;   break;
#ifdef S_IFSOCK
   case (S_IFSOCK>>12): /* 12, socket */
      result = GROUP_SOCKET|GROUP_SOCK_UNIX; break;
#else
   default: /* some systems (pure POSIX.1) do not know S_IFSOCK */
      result = GROUP_SOCKET|GROUP_SOCK_UNIX; break;
#endif
   }
   Debug2("_groupbits(%d) -> %d", mode, result);
   return result;
}

/* does not set GROUP_FD */
int groupbits(int fd) {
#if HAVE_STAT64
   struct stat64 buf;
#else
   struct stat buf;
#endif /* !HAVE_STAT64 */
   int result;

   if (
#if HAVE_STAT64
       Fstat64(fd, &buf) < 0
#else
       Fstat(fd, &buf) < 0
#endif /* !HAVE_STAT64 */
      ) {
      Error4("groupbits(%d): fstat(%d, %p): %s",
             fd, fd, &buf, strerror(errno));
      return -1;
   }
   result = _groupbits(buf.st_mode&S_IFMT);
   return result;
}

#if 0   /* currently not used */
int retropt(struct opt *opts, int optcode, union integral *result) {
   struct opt *opt = opts;

   while (opt->desc != ODESC_END) {
      if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
         *result = opt->value;
         opt->desc = ODESC_DONE;
         return 0;
      }
      ++opt;
   }
   return -1;
}
#endif

static struct opt *xio_findopt(struct opt *opts, int optcode) {
   struct opt *opt = opts;

   while (opt->desc != ODESC_END) {
      if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
         return opt;
      }
      ++opt;
   }
   return NULL;
}

int retropt_timespec(struct opt *opts, int optcode, struct timespec *result) {
   struct opt *opt;

   if (!(opt = xio_findopt(opts, optcode))) {
      return -1;
   }
   *result = opt->value.u_timespec;
   opt->desc = ODESC_DONE;
   return 0;
}
      
   
/* Looks for the first option of type <optcode>. If the option is found,
   this function stores its bool value in *result, "consumes" the
   option, and returns 0.
   If the option is not found, *result is not modified, and -1 is returned. */
int retropt_bool(struct opt *opts, int optcode, bool *result) {
   struct opt *opt = opts;

   while (opt->desc != ODESC_END) {
      if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
         *result = opt->value.u_bool;
         opt->desc = ODESC_DONE;
         return 0;
      }
      ++opt;
   }
   return -1;
}

#if 0   /* currently not used */
/* Looks for the first option of type <optcode>. If the option is found,
   this function stores its short value in *result, "consumes" the
   option, and returns 0.
   If the option is not found, *result is not modified, and -1 is returned. */
int retropt_short(struct opt *opts, int optcode, short *result) {
   struct opt *opt = opts;

   while (opt->desc != ODESC_END) {
      if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
         *result = opt->value.u_short;
         opt->desc = ODESC_DONE;
         return 0;
      }
      ++opt;
   }
   return -1;
}
#endif

/* Looks for the first option of type <optcode>. If the option is found,
   this function stores its unsigned short value in *result, "consumes" the
   option, and returns 0.
   If the option is not found, *result is not modified, and -1 is returned. */
int retropt_ushort(struct opt *opts, int optcode, unsigned short *result) {
   struct opt *opt = opts;

   while (opt->desc != ODESC_END) {
      if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
         *result = opt->value.u_ushort;
         opt->desc = ODESC_DONE;
         return 0;
      }
      ++opt;
   }
   return -1;
}

/* Looks for the first option of type <optcode>. If the option is found,
   this function stores its int value in *result, "consumes" the
   option, and returns 0.
   If the option is not found, *result is not modified, and -1 is returned. */
int retropt_int(struct opt *opts, int optcode, int *result) {
   struct opt *opt = opts;

   while (opt->desc != ODESC_END) {
      if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
         switch (opt->desc->type) {
         case TYPE_INT: *result = opt->value.u_int; break;
         case TYPE_STRING: *result = strtol(opt->value.u_string, NULL, 0);
            break;
         default: Error2("cannot convert type %d of option %s to int",
                         opt->desc->type, opt->desc->defname);
            opt->desc = ODESC_ERROR;
            return -1;
         }
         opt->desc = ODESC_DONE;
         return 0;
      }
      ++opt;
   }
   return -1;
}

/* Looks for the first option of type <optcode>. If the option is found,
   this function stores its unsigned int value in *result, "consumes" the
   option, and returns 0.
   If the option is not found, *result is not modified, and -1 is returned. */
int retropt_uint(struct opt *opts, int optcode, unsigned int *result) {
   struct opt *opt = opts;

   while (opt->desc != ODESC_END) {
      if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
         *result = opt->value.u_uint;
         opt->desc = ODESC_DONE;
         return 0;
      }
      ++opt;
   }
   return -1;
}

/* Looks for the first option of type <optcode>. If the option is found,
   this function stores its long value in *result, "consumes" the option,
   and returns 0.
   If the option is not found, *result is not modified, and -1 is returned. */
int retropt_long(struct opt *opts, int optcode, long *result) {
   struct opt *opt = opts;

   while (opt->desc != ODESC_END) {
      if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
         *result = opt->value.u_long;
         opt->desc = ODESC_DONE;
         return 0;
      }
      ++opt;
   }
   return -1;
}

/* Looks for the first option of type <optcode>. If the option is found,
   this function stores its unsigned long value in *result, "consumes" the
   option, and returns 0.
   If the option is not found, *result is not modified, and -1 is returned. */
int retropt_ulong(struct opt *opts, int optcode, unsigned long *result) {
   struct opt *opt = opts;

   while (opt->desc != ODESC_END) {
      if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
         *result = opt->value.u_ulong;
         opt->desc = ODESC_DONE;
         return 0;
      }
      ++opt;
   }
   return -1;
}

#if 0   /* currently not used */
/* get the value of a FLAG typed option, and apply it to the appropriate
   bit position. Mark the option as consumed (done). return 0 if options was found and successfully applied,
   or -1 if option was not in opts */
int retropt_flag(struct opt *opts, int optcode, flags_t *result) {
   struct opt *opt = opts;

   while (opt->desc != ODESC_END) {
      if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
         if (opt->value.u_bool) {
            *result |= opt->desc->major;
         } else {
            *result &= ~opt->desc->major;
         }
         opt->desc = ODESC_DONE;
         return 0;
      }
      ++opt;
   }
   return -1;
}
#endif

/* Looks for the first option of type <optcode>. If the option is found,
   this function stores its character pointer value in *result, "consumes" the
   option, and returns 0. Note that, for options of type STRING_NULL, the
   character pointer might degenerate to NULL.
   The resulting string is malloc'ed and should be freed after use.
   If the option is not found, *result is not modified, and -1 is returned.
 */
int retropt_string(struct opt *opts, int optcode, char **result) {
   struct opt *opt = opts;

   while (opt->desc != ODESC_END) {
      if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
         if (opt->value.u_string == NULL) {
            *result = NULL;
         } else if ((*result = strdup(opt->value.u_string)) == NULL) {
            Error1("strdup("F_Zu"): out of memory",
                   strlen(opt->value.u_string));
            return -1;
         }
         opt->desc = ODESC_DONE;
         return 0;
      }
      ++opt;
   }
   return -1;
}


#if _WITH_SOCKET
/* looks for a bind option and, if found, overwrites the complete contents of
   sa with the appropriate value(s).
   returns STAT_OK if option exists and could be resolved,
   STAT_NORETRY if option exists but had error,
   or STAT_NOACTION if it does not exist */
/* currently only for IP (v4, v6) and raw (PF_UNSPEC) */
int retropt_bind(struct opt *opts,
                 int af,
                 int socktype,
                 int ipproto,
                 struct sockaddr *sa,
                 socklen_t *salen,
                 int feats,     /* TCP etc: 1..address allowed,
                                            3..address and port allowed
                                   UNIX (or'd): 1..tight
                                                2..abstract
                                */
                 unsigned long res_opts0, unsigned long res_opts1) {
   const char portsep[] = ":";
   const char *ends[] = { portsep, NULL };
   const char *nests[] = { "[", "]", NULL };
   bool portallowed;
   char *bindname, *bindp;
   char hostname[512], *hostp = hostname, *portp = NULL;
   size_t hostlen = sizeof(hostname)-1;
   int parsres;
   int result;

   if (retropt_string(opts, OPT_BIND, &bindname) < 0) {
      return STAT_NOACTION;
   }
   bindp = bindname;

   switch (af) {

   case AF_UNSPEC:
      {
         size_t p = 0;
         dalan(bindname, (char *)sa->sa_data, &p, *salen-sizeof(sa->sa_family));
         *salen = p + sizeof(sa->sa_family);
         *salen = p +
#if HAVE_STRUCT_SOCKADDR_SALEN
            sizeof(sa->sa_len) +
#endif
            sizeof(sa->sa_family);
#if HAVE_STRUCT_SOCKADDR_SALEN
         sa->sa_len = *salen;
#endif
      }
      break;

#if WITH_IP4 || WITH_IP6
#if WITH_IP4
   case AF_INET:
#endif
#if WITH_IP6
   case AF_INET6:
#endif /*WITH_IP6 */
      portallowed = (feats>=2);
      parsres =
         nestlex((const char **)&bindp, &hostp, &hostlen, ends, NULL, NULL, nests,
                 true, false, false, false);
      if (parsres < 0) {
         Error1("option too long:  \"%s\"", bindp);
         return STAT_NORETRY;
      } else if (parsres > 0) {
         Error1("syntax error in \"%s\"", bindp);
         return STAT_NORETRY;
      }
      *hostp++ = '\0';
      if (!strncmp(bindp, portsep, strlen(portsep))) {
         if (!portallowed) {
            Error("port specification not allowed in this bind option");
            return STAT_NORETRY;
         } else {
            portp = bindp + strlen(portsep);
         }
      }
      if ((result =
           xiogetaddrinfo(hostname[0]!='\0'?hostname:NULL, portp,
                          af, socktype, ipproto,
                          (union sockaddr_union *)sa, salen,
                          res_opts0, res_opts1))
          != STAT_OK) {
         Error("error resolving bind option");
         return STAT_NORETRY;
      }    
      break;
#endif /* WITH_IP4 || WITH_IP6 */

#if WITH_UNIX
   case AF_UNIX:
      {
         bool abstract = (feats&2);
         bool tight = (feats&1);
         struct sockaddr_un *s_un = (struct sockaddr_un *)sa;
         *salen = xiosetunix(af, s_un, bindname, abstract, tight);
      }
      break;
#endif /* WITH_UNIX */

   default:
      Error1("bind: unknown address family %d", af);
      return STAT_NORETRY;
   }
   return STAT_OK;
}
#endif /* _WITH_SOCKET */


/* applies to fd all options belonging to phase */
/* note: not all options can be applied this way (e.g. OFUNC_SPEC with PH_OPEN)
   implemented are: OFUNC_FCNTL, OFUNC_SOCKOPT (probably not all types),
   OFUNC_TERMIOS_FLAG, OFUNC_TERMIOS_PATTERN, and some OFUNC_SPEC */
int applyopts(int fd, struct opt *opts, enum e_phase phase) {
   struct opt *opt;

   opt = opts; while (opt && opt->desc != ODESC_END) {
      if (opt->desc == ODESC_DONE ||
          (phase != PH_ALL && opt->desc->phase != phase)) {
         ++opt; continue; }

      if (opt->desc->func == OFUNC_SEEK32) {
         if (Lseek(fd, opt->value.u_off, opt->desc->major) < 0) {
            Error4("lseek(%d, "F_off", %d): %s",
                   fd, opt->value.u_off, opt->desc->major, strerror(errno));
         }
#if HAVE_LSEEK64
      } else if (opt->desc->func == OFUNC_SEEK64) {

         /*! this depends on off64_t atomic type */
         if (Lseek64(fd, opt->value.u_off64, opt->desc->major) < 0) {
            Error4("lseek64(%d, "F_off64", %d): %s",
                   fd, opt->value.u_off64, opt->desc->major, strerror(errno));
         }
#endif /* HAVE_LSEEK64 */

      } else if (opt->desc->func == OFUNC_FCNTL) {
         int flag;

         /* retrieve existing flag setttings */
         if ((flag = Fcntl(fd, opt->desc->major-1)) < 0) {
            Error3("fcntl(%d, %d): %s",
                   fd, opt->desc->major, strerror(errno));
            opt->desc = ODESC_ERROR; ++opt; continue;
         } else {
            if (opt->value.u_bool) {
               flag |= opt->desc->minor;
            } else {
               flag &= ~opt->desc->minor;
            }
            if (Fcntl_l(fd, opt->desc->major, flag) < 0) {
               Error4("fcntl(%d, %d, %d): %s",
                      fd, opt->desc->major, flag, strerror(errno));
               opt->desc = ODESC_ERROR; ++opt; continue;
            }
         }

      } else if (opt->desc->func == OFUNC_IOCTL) {
         if (Ioctl(fd, opt->desc->major, (void *)&opt->value) < 0) {
            Error4("ioctl(%d, 0x%x, %p): %s",
                   fd, opt->desc->major, (void *)&opt->value, strerror(errno));
            opt->desc = ODESC_ERROR; ++opt; continue;
         }

      } else if (opt->desc->func == OFUNC_IOCTL_MASK_LONG) {
         long val;
         int getreq = opt->desc->major;
         int setreq = opt->desc->minor;
         long mask  = opt->desc->arg3;

         if (Ioctl(fd, getreq, (void *)&val) < 0) {
            Error5("option \"%s\": ioctl(%d, 0x%x, %p): %s",
                   opt->desc->defname,
                   fd, opt->desc->major, (void *)&val, strerror(errno));
            opt->desc = ODESC_ERROR; ++opt; continue;
         }
         val &= ~mask;
         if (opt->value.u_bool)  val |= mask;
         if (Ioctl(fd, setreq, (void *)&val) < 0) {
            Error4("ioctl(%d, 0x%x, %p): %s",
                   fd, opt->desc->major, (void *)&val, strerror(errno));
            opt->desc = ODESC_ERROR; ++opt; continue;
         }

      } else if (opt->desc->func == OFUNC_IOCTL_GENERIC) {
         switch (opt->desc->type) {
         case TYPE_INT:
            if (Ioctl(fd, opt->value.u_int, NULL) < 0) {
               Error3("ioctl(%d, 0x%x, NULL): %s",
                      fd, opt->value.u_int, strerror(errno));
               opt->desc = ODESC_ERROR; ++opt; continue;
            }
            break;
         case TYPE_INT_INT:
            if (Ioctl_int(fd, opt->value.u_int, opt->value2.u_int) < 0) {
               Error4("ioctl(%d, 0x%x, 0x%x): %s",
                      fd, opt->value.u_int, opt->value2.u_int, strerror(errno));
               opt->desc = ODESC_ERROR; ++opt; continue;
            }
            break;
         case TYPE_INT_INTP:
            if (Ioctl(fd, opt->value.u_int, (void *)&opt->value2.u_int) < 0) {
               Error4("ioctl(%d, 0x%x, %p): %s",
                      fd, opt->value.u_int, (void *)&opt->value2.u_int, strerror(errno));
               opt->desc = ODESC_ERROR; ++opt; continue;
            }
            break;
         case TYPE_INT_BIN:
            if (Ioctl(fd, opt->value.u_int, (void *)opt->value2.u_bin.b_data) < 0) {
               Error4("ioctl(%d, 0x%x, %p): %s",
                      fd, opt->value.u_int, (void *)opt->value2.u_bin.b_data, strerror(errno));
               opt->desc = ODESC_ERROR; ++opt; continue;
            }
            break;
         case TYPE_INT_STRING:
            if (Ioctl(fd, opt->value.u_int, (void *)opt->value2.u_string) < 0) {
               Error4("ioctl(%d, 0x%x, %p): %s",
                      fd, opt->value.u_int, (void *)opt->value2.u_string, strerror(errno));
               opt->desc = ODESC_ERROR; ++opt; continue;
            }
            break;
         default:
            Error1("ioctl() data type %d not implemented",
                   opt->desc->type);
         }

#if _WITH_SOCKET
      } else if (opt->desc->func == OFUNC_SOCKOPT) {
         if (0) {
            ;
#if 0 && HAVE_STRUCT_LINGER
         } else if (opt->desc->optcode == OPT_SO_LINGER) {
            struct linger lingstru;
            lingstru.l_onoff = (opt->value.u_int>=0 ? 1 : 0);
            lingstru.l_linger = opt->value.u_int;
            if (Setsockopt(fd, opt->desc->major, opt->desc->minor, &lingstru,
                           sizeof(lingstru)) < 0) {
               Error6("setsockopt(%d, %d, %d, {%d,%d}, "F_Zu,
                      fd, opt->desc->major, opt->desc->minor, lingstru.l_onoff,
                      lingstru.l_linger, sizeof(lingstru));
               opt->desc = ODESC_ERROR; ++opt; continue;
            }
#endif /* HAVE_STRUCT_LINGER */
         } else {
            switch (opt->desc->type) {
            case TYPE_BIN:
               if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
                              opt->value.u_bin.b_data, opt->value.u_bin.b_len)
                   < 0) {
                  Error6("setsockopt(%d, %d, %d, %p, "F_Zu"): %s",
                         fd, opt->desc->major, opt->desc->minor,
                         opt->value.u_bin.b_data, opt->value.u_bin.b_len,
                         strerror(errno));
                  opt->desc = ODESC_ERROR; ++opt; continue;
               }
               break;
            case TYPE_BOOL:
               if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
                              &opt->value.u_bool, sizeof(opt->value.u_bool))
                   < 0) {
                  Error6("setsockopt(%d, %d, %d, {%d}, "F_Zu"): %s", fd,
                         opt->desc->major, opt->desc->minor,
                         opt->value.u_bool, sizeof(opt->value.u_bool),
                         strerror(errno));
                  opt->desc = ODESC_ERROR; ++opt; continue;
               }
               break;
            case TYPE_BYTE:
               if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
                              &opt->value.u_byte, sizeof(uint8_t)) < 0) {
                  Error6("setsockopt(%d, %d, %d, {%u}, "F_Zu"): %s",
                         fd, opt->desc->major, opt->desc->minor,
                         opt->value.u_byte, sizeof(uint8_t), strerror(errno));
                  opt->desc = ODESC_ERROR; ++opt; continue;
               }
               break;
            case TYPE_INT:
               if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
                              &opt->value.u_int, sizeof(int)) < 0) {
                  Error6("setsockopt(%d, %d, %d, {%d}, "F_Zu"): %s",
                         fd, opt->desc->major, opt->desc->minor,
                         opt->value.u_int, sizeof(int), strerror(errno));
                  opt->desc = ODESC_ERROR; ++opt; continue;
               }
               break;
            case TYPE_LONG:
               if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
                              &opt->value.u_long, sizeof(long)) < 0) {
                  Error6("setsockopt(%d, %d, %d, {%ld}, "F_Zu"): %s",
                         fd, opt->desc->major, opt->desc->minor,
                         opt->value.u_long, sizeof(long), strerror(errno));
                  opt->desc = ODESC_ERROR; ++opt; continue;
               }
               break;
            case TYPE_STRING:
               if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
                              opt->value.u_string,
                              strlen(opt->value.u_string)+1) < 0) {
                  Error6("setsockopt(%d, %d, %d, \"%s\", "F_Zu"): %s",
                         fd, opt->desc->major, opt->desc->minor,
                         opt->value.u_string, strlen(opt->value.u_string)+1,
                         strerror(errno));
                  opt->desc = ODESC_ERROR; ++opt; continue;
               }
               break;
            case TYPE_UINT:
               if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
                              &opt->value.u_uint, sizeof(unsigned int)) < 0) {
                  Error6("setsockopt(%d, %d, %d, {%u}, "F_Zu"): %s",
                         fd, opt->desc->major, opt->desc->minor,
                         opt->value.u_uint, sizeof(unsigned int),
                         strerror(errno));
                  opt->desc = ODESC_ERROR; ++opt; continue;
               }
               break;
            case TYPE_TIMEVAL:
               if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
                              &opt->value.u_timeval, sizeof(struct timeval)) < 0) {
                  Error7("setsockopt(%d, %d, %d, {%ld,%ld}, "F_Zu"): %s",
                         fd, opt->desc->major, opt->desc->minor,
                         opt->value.u_timeval.tv_sec, opt->value.u_timeval.tv_usec,
                         sizeof(struct timeval), strerror(errno));
                  opt->desc = ODESC_ERROR; ++opt; continue;
               }
               break;
#if HAVE_STRUCT_LINGER
            case TYPE_LINGER:
               {
                  struct linger lingstru;
                  lingstru.l_onoff = (opt->value.u_linger.l_onoff>=0 ? 1 : 0);
                  lingstru.l_linger = opt->value.u_linger.l_linger;
                  if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
                                 &lingstru, sizeof(lingstru)) < 0) {
                     Error6("setsockopt(%d, %d, %d, {%d,%d}): %s",
                            fd, opt->desc->major, opt->desc->minor,
                            lingstru.l_onoff, lingstru.l_linger,
                            strerror(errno));
                     opt->desc = ODESC_ERROR; ++opt; continue;
                  }
               }
               break;
#endif /* HAVE_STRUCT_LINGER */
#if defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN)
            case TYPE_IP_MREQN:
               /* handled in applyopts_single */
               ++opt; continue;
#endif /* defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN) */

               /*! still many types missing; implement on demand */
#if WITH_IP4
            case TYPE_IP4NAME:
               if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
                              &opt->value.u_ip4addr, sizeof(opt->value.u_ip4addr)) < 0) {
                  Error6("setsockopt(%d, %d, %d, {0x%x}, "F_Zu"): %s",
                         fd, opt->desc->major, opt->desc->minor,
                         *(uint32_t *)&opt->value.u_ip4addr, sizeof(opt->value.u_ip4addr),
                         strerror(errno));
               }
               break;
#endif /* defined(WITH_IP4) */
            default:
#if !NDEBUG
               Error1("applyopts(): type %d not implemented",
                            opt->desc->type);
#else
               Warn1("applyopts(): type %d not implemented",
                            opt->desc->type);
#endif
               opt->desc = ODESC_ERROR; ++opt; continue;
            }
         }

      } else if (opt->desc->func == OFUNC_SOCKOPT_APPEND) {
         switch (opt->desc->type) {
            uint8_t data[256];
            socklen_t oldlen, newlen;
         case TYPE_BIN:
            oldlen = sizeof(data);
            if (Getsockopt(fd, opt->desc->major, opt->desc->minor,
                           data, &oldlen)
                < 0) {
               Error6("getsockopt(%d, %d, %d, %p, {"F_socklen"}): %s",
                      fd, opt->desc->major, opt->desc->minor, data, oldlen,
                      strerror(errno));
               opt->desc = ODESC_ERROR; ++opt; continue;
            }
            memcpy(&data[oldlen], opt->value.u_bin.b_data,
                   MIN(opt->value.u_bin.b_len, sizeof(data)-oldlen));
            newlen = oldlen + MIN(opt->value.u_bin.b_len, sizeof(data)-oldlen);
            if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
                           data, newlen)
                < 0) {
               Error6("setsockopt(%d, %d, %d, %p, %d): %s",
                      fd, opt->desc->major, opt->desc->minor, data, newlen,
                      strerror(errno));
               opt->desc = ODESC_ERROR; ++opt; continue;
            }
            break;
         default:
            Error2("internal: option \"%s\": unimplemented type %d",
                   opt->desc->defname, opt->desc->type);
            break;
         }
      } else if (opt->desc->func == OFUNC_SOCKOPT_GENERIC) {
         switch (opt->desc->type) {
         case TYPE_INT_INT_INT:
            if (Setsockopt(fd, opt->value.u_int, opt->value2.u_int,
                           &opt->value3.u_int, sizeof(int)) < 0) {
               Error6("setsockopt(%d, %d, %d, {%d}, "F_Zu"): %s",
                      fd, opt->value.u_int, opt->value2.u_int,
                      opt->value3.u_int, sizeof(int), strerror(errno));
            }
            break;
         case TYPE_INT_INT_BIN:
            if (Setsockopt(fd, opt->value.u_int, opt->value2.u_int,
                           opt->value3.u_bin.b_data, opt->value3.u_bin.b_len) < 0) {
               Error5("setsockopt(%d, %d, %d, {...}, "F_Zu"): %s",
                      fd, opt->value.u_int, opt->value2.u_int,
                      opt->value3.u_bin.b_len, strerror(errno));
            }
            break;
         case TYPE_INT_INT_STRING:
            if (Setsockopt(fd, opt->value.u_int, opt->value2.u_int,
                           opt->value3.u_string,
                           strlen(opt->value3.u_string)+1) < 0) {
               Error6("setsockopt(%d, %d, %d, \"%s\", "F_Zu"): %s",
                      fd, opt->value.u_int, opt->value2.u_int,
                      opt->value3.u_string, strlen(opt->value3.u_string)+1,
                      strerror(errno));
            }
            break;
         default:
            Error1("setsockopt() data type %d not implemented",
                   opt->desc->type);
         }
#endif /* _WITH_SOCKET */
         
#if HAVE_FLOCK
      } else if (opt->desc->func == OFUNC_FLOCK) {
         if (Flock(fd, opt->desc->major) < 0) {
            Error3("flock(%d, %d): %s",
                   fd, opt->desc->major, strerror(errno));
            opt->desc = ODESC_ERROR; ++opt; continue;
         }
#endif /* defined(HAVE_FLOCK) */

      } else if (opt->desc->func == OFUNC_SPEC ||
                 opt->desc->func == OFUNC_FLAG) {
         switch (opt->desc->optcode) {
         case OPT_USER:
         case OPT_USER_LATE:
            if (Fchown(fd, opt->value.u_uidt, -1) < 0) {
               Error3("fchown(%d, "F_uid", -1): %s",
                      fd, opt->value.u_uidt, strerror(errno));
               opt->desc = ODESC_ERROR; ++opt; continue;
            }
            break;
         case OPT_GROUP:
         case OPT_GROUP_LATE:
            if (Fchown(fd, -1, opt->value.u_gidt) < 0) {
               Error3("fchown(%d, -1, "F_gid"): %s",
                      fd, opt->value.u_gidt, strerror(errno));
               opt->desc = ODESC_ERROR; ++opt; continue;
            }
            break;
         case OPT_PERM:
         case OPT_PERM_LATE:
            if (Fchmod(fd, opt->value.u_modet) < 0) {
               Error3("fchmod(%d, %u): %s",
                      fd, opt->value.u_modet, strerror(errno));
               opt->desc = ODESC_ERROR; ++opt; continue;
            }
            break;
         case OPT_FTRUNCATE32:
            if (Ftruncate(fd, opt->value.u_off) < 0) {
               Error3("ftruncate(%d, "F_off"): %s",
                      fd, opt->value.u_off, strerror(errno));
               opt->desc = ODESC_ERROR; ++opt; continue;
            }
            break;
#if HAVE_FTRUNCATE64
         case OPT_FTRUNCATE64:
            if (Ftruncate64(fd, opt->value.u_off64) < 0) {
               Error3("ftruncate64(%d, "F_off64"): %s",
                      fd, opt->value.u_off64, strerror(errno));
               opt->desc = ODESC_ERROR; ++opt; continue;
            }
#endif /* HAVE_FTRUNCATE64 */
            break; 
         case OPT_F_SETLK_RD:
         case OPT_F_SETLK_WR:
         case OPT_F_SETLKW_RD:
         case OPT_F_SETLKW_WR:
            {
               struct flock l;  /* Linux: <asm/fcntl.h> */
               l.l_type   = opt->desc->minor;
               l.l_whence = SEEK_SET;
               l.l_start  = 0;
               l.l_len    = LONG_MAX;
               l.l_pid    = 0;  /* hope this uses our current process */
               if (Fcntl_lock(fd, opt->desc->major, &l) < 0) {
                  Error3("fcntl(%d, %d, {type=F_WRLCK,whence=SEEK_SET,start=0,len=LONG_MAX,pid=0}): %s", fd, opt->desc->major, strerror(errno));
                  opt->desc = ODESC_ERROR; ++opt; continue;
               }
            }
            break; 
         case OPT_SETUID_EARLY:
         case OPT_SETUID:
            if (Setuid(opt->value.u_uidt) < 0) {
               Error2("setuid("F_uid"): %s", opt->value.u_uidt,
                      strerror(errno));
               opt->desc = ODESC_ERROR; ++opt; continue;
            }
            break;
         case OPT_SETGID_EARLY:
         case OPT_SETGID:
            if (Setgid(opt->value.u_gidt) < 0) {
               Error2("setgid("F_gid"): %s", opt->value.u_gidt,
                      strerror(errno));
               opt->desc = ODESC_ERROR; ++opt; continue;
            }
            break;
         case OPT_SUBSTUSER_EARLY:
         case OPT_SUBSTUSER:
            {
               struct passwd *pwd;
               if ((pwd = getpwuid(opt->value.u_uidt)) == NULL) {
                  Error1("getpwuid("F_uid"): no such user",
                         opt->value.u_uidt);
                  opt->desc = ODESC_ERROR; ++opt; continue;
               }
               if (Initgroups(pwd->pw_name, pwd->pw_gid) < 0) {
                  Error3("initgroups(%s, "F_gid"): %s",
                         pwd->pw_name, pwd->pw_gid, strerror(errno));
                  opt->desc = ODESC_ERROR; ++opt; continue;
               }
               if (Setgid(pwd->pw_gid) < 0) {
                  Error2("setgid("F_gid"): %s", pwd->pw_gid,
                         strerror(errno));
                  opt->desc = ODESC_ERROR; ++opt; continue;
               }
               if (Setuid(opt->value.u_uidt) < 0) {
                  Error2("setuid("F_uid"): %s", opt->value.u_uidt,
                         strerror(errno));
                  opt->desc = ODESC_ERROR; ++opt; continue;
               }
#if 1
               if (setenv("USER", pwd->pw_name, 1) < 0)
                  Error1("setenv(\"USER\", \"%s\", 1): insufficient space",
                         pwd->pw_name);
               if (setenv("LOGNAME", pwd->pw_name, 1) < 0)
                  Error1("setenv(\"LOGNAME\", \"%s\", 1): insufficient space",
                         pwd->pw_name);
               if (setenv("HOME", pwd->pw_dir, 1) < 0)
                  Error1("setenv(\"HOME\", \"%s\", 1): insufficient space",
                         pwd->pw_dir);
               if (setenv("SHELL", pwd->pw_shell, 1) < 0)
                  Error1("setenv(\"SHELL\", \"%s\", 1): insufficient space",
                         pwd->pw_shell);
#endif
            }
            break;
#if defined(HAVE_SETGRENT) && defined(HAVE_GETGRENT) && defined(HAVE_ENDGRENT)
         case OPT_SUBSTUSER_DELAYED:
            {
               struct passwd *pwd;

               if ((pwd = getpwuid(opt->value.u_uidt)) == NULL) {
                  Error1("getpwuid("F_uid"): no such user",
                         opt->value.u_uidt);
                  opt->desc = ODESC_ERROR; ++opt; continue;
               }
               delayeduser_uid = opt->value.u_uidt;
               delayeduser_gid = pwd->pw_gid;
               if ((delayeduser_name = strdup(pwd->pw_name)) == NULL) {
                  Error1("strdup("F_Zu"): out of memory",
                         strlen(pwd->pw_name)+1);
                  opt->desc = ODESC_ERROR; ++opt; continue;
               }
               if ((delayeduser_dir = strdup(pwd->pw_dir)) == NULL) {
                  Error1("strdup("F_Zu"): out of memory",
                         strlen(pwd->pw_dir)+1);
                  opt->desc = ODESC_ERROR; ++opt; continue;
               }
               if ((delayeduser_shell = strdup(pwd->pw_shell)) == NULL) {
                  Error1("strdup("F_Zu"): out of memory",
                         strlen(pwd->pw_shell)+1);
                  opt->desc = ODESC_ERROR; ++opt; continue;
               }
               /* function to get all supplementary groups of user */
               delayeduser_ngids = sizeof(delayeduser_gids)/sizeof(gid_t);
               getusergroups(delayeduser_name, delayeduser_gids,
                             &delayeduser_ngids);
               delayeduser = true;
            }
            break;
#endif
         case OPT_CHROOT_EARLY:
         case OPT_CHROOT:
            if (Chroot(opt->value.u_string) < 0) {
               Error2("chroot(\"%s\"): %s", opt->value.u_string,
                      strerror(errno));
               opt->desc = ODESC_ERROR; ++opt; continue;
            }
            if (Chdir("/") < 0) {
               Error1("chdir(\"/\"): %s", strerror(errno));
            }
            break;
         case OPT_SETSID:
            if (Setsid() < 0) {
               Warn1("setsid(): %s", strerror(errno));
               if (Setpgid(getpid(), getppid()) < 0) {
                  Warn3("setpgid(%d, %d): %s",
                        getpid(), getppid(), strerror(errno));
               } else {
                  if (Setsid() < 0) {
                     Error1("setsid(): %s", strerror(errno));
                  }               
               }
            }
            break;
         case OPT_SETPGID:
            if (Setpgid(0, opt->value.u_int) < 0) {
               Warn2("setpgid(0, "F_pid"): %s",
                     opt->value.u_int, strerror(errno));
            }
            break;
         case OPT_TIOCSCTTY:
            {
               int mytty;
               /* this code idea taken from ssh/pty.c: make pty controlling term. */
               if ((mytty = Open("/dev/tty", O_NOCTTY, 0640)) < 0) {
                  Warn1("open(\"/dev/tty\", O_NOCTTY, 0640): %s", strerror(errno));
               } else {
                  /*0 Info1("open(\"/dev/tty\", O_NOCTTY, 0640) -> %d", mytty);*/
#ifdef TIOCNOTTY
                  if (Ioctl(mytty, TIOCNOTTY, NULL) < 0) {
                     Warn2("ioctl(%d, TIOCNOTTY, NULL): %s",
                           mytty, strerror(errno));
                  }
#endif
                  if (Close(mytty) < 0) {
                     Info2("close(%d): %s",
                           mytty, strerror(errno));
                  }
               }
#ifdef TIOCSCTTY
               if (Ioctl(fd, TIOCSCTTY, NULL) < 0) {
                  Warn2("ioctl(%d, TIOCSCTTY, NULL): %s", fd, strerror(errno));
               }
#endif
               if (Tcsetpgrp(0, getpid()) < 0) {
                  Warn2("tcsetpgrp("F_pid"): %s", getpid(), strerror(errno));
               }
            }
            break;

         default: Error1("applyopts(): option \"%s\" not implemented",
                         opt->desc->defname);
            opt->desc = ODESC_ERROR; ++opt; continue;
         }

#if WITH_TERMIOS
      } else if (opt->desc->func == OFUNC_TERMIOS_FLAG) {
#if 0
         union {
            struct termios termarg;
            tcflag_t flags[4];
         } tdata;
         if (Tcgetattr(fd, &tdata.termarg) < 0) {
            Error3("tcgetattr(%d, %p): %s",
                   fd, &tdata.termarg, strerror(errno));
            opt->desc = ODESC_ERROR; ++opt; continue;
         }
         if (opt->value.u_bool) {
            tdata.flags[opt->desc->major] |= opt->desc->minor;
         } else {
            tdata.flags[opt->desc->major] &= ~opt->desc->minor;
         }
         if (Tcsetattr(fd, TCSADRAIN, &tdata.termarg) < 0) {
            Error3("tcsetattr(%d, TCSADRAIN, %p): %s",
                   fd, &tdata.termarg, strerror(errno));
            opt->desc = ODESC_ERROR; ++opt; continue;
         }
#else
         if (xiotermiosflag_applyopt(fd, opt) < 0) {
            opt->desc = ODESC_ERROR; ++opt; continue;
         }
#endif

      } else if (opt->desc->func == OFUNC_TERMIOS_VALUE) {
         union {
            struct termios termarg;
            tcflag_t flags[4];
         } tdata;
         if (((opt->value.u_uint << opt->desc->arg3) & opt->desc->minor) !=
             (opt->value.u_uint << opt->desc->arg3)) {
            Error2("option %s: invalid value %u",
                   opt->desc->defname, opt->value.u_uint);
            opt->desc = ODESC_ERROR; ++opt; continue;
         }
         if (Tcgetattr(fd, &tdata.termarg) < 0) {
            Error3("tcgetattr(%d, %p): %s",
                   fd, &tdata.termarg, strerror(errno));
            opt->desc = ODESC_ERROR; ++opt; continue;
         }

         tdata.flags[opt->desc->major] &= ~opt->desc->minor;
         tdata.flags[opt->desc->major] |=
            ((opt->value.u_uint << opt->desc->arg3) & opt->desc->minor);
         if (Tcsetattr(fd, TCSADRAIN, &tdata.termarg) < 0) {
            Error3("tcsetattr(%d, TCSADRAIN, %p): %s",
                   fd, &tdata.termarg, strerror(errno));
            opt->desc = ODESC_ERROR; ++opt; continue;
         }

      } else if (opt->desc->func == OFUNC_TERMIOS_PATTERN) {
         union {
            struct termios termarg;
            tcflag_t flags[4];
         } tdata;
         if (Tcgetattr(fd, &tdata.termarg) < 0) {
            Error3("tcgetattr(%d, %p): %s",
                   fd, &tdata.termarg, strerror(errno));
            opt->desc = ODESC_ERROR; ++opt; continue;
         }
         tdata.flags[opt->desc->major] &= ~opt->desc->arg3;
         tdata.flags[opt->desc->major] |= opt->desc->minor;
         if (Tcsetattr(fd, TCSADRAIN, &tdata.termarg) < 0) {
            Error3("tcsetattr(%d, TCSADRAIN, %p): %s",
                   fd, &tdata.termarg, strerror(errno));
            opt->desc = ODESC_ERROR;++opt;  continue;
         }

      } else if (opt->desc->func == OFUNC_TERMIOS_CHAR) {
         struct termios termarg;
         if (Tcgetattr(fd, &termarg) < 0) {
            Error3("tcgetattr(%d, %p): %s",
                   fd, &termarg, strerror(errno));
            opt->desc = ODESC_ERROR; ++opt; continue;
         }
         termarg.c_cc[opt->desc->major] = opt->value.u_byte;
         if (Tcsetattr(fd, TCSADRAIN, &termarg) < 0) {
            Error3("tcsetattr(%d, TCSADRAIN, %p): %s",
                   fd, &termarg, strerror(errno));
            opt->desc = ODESC_ERROR; ++opt; continue;
         }

#ifdef HAVE_TERMIOS_ISPEED
      } else if (opt->desc->func == OFUNC_TERMIOS_SPEED) {
         union {
            struct termios termarg;
            speed_t speeds[sizeof(struct termios)/sizeof(speed_t)];
         } tdata;
         if (Tcgetattr(fd, &tdata.termarg) < 0) {
            Error3("tcgetattr(%d, %p): %s",
                   fd, &tdata.termarg, strerror(errno));
            opt->desc = ODESC_ERROR; ++opt; continue;
         }
         tdata.speeds[opt->desc->major] = opt->value.u_uint;
         if (Tcsetattr(fd, TCSADRAIN, &tdata.termarg) < 0) {
            Error3("tcsetattr(%d, TCSADRAIN, %p): %s",
                   fd, &tdata.termarg, strerror(errno));
            opt->desc = ODESC_ERROR; ++opt; continue;
         }
#endif /* HAVE_TERMIOS_ISPEED */

      } else if (opt->desc->func == OFUNC_TERMIOS_SPEC) {
         struct termios termarg;
         if (Tcgetattr(fd, &termarg) < 0) {
            Error3("tcgetattr(%d, %p): %s",
                   fd, &termarg, strerror(errno));
            opt->desc = ODESC_ERROR; ++opt; continue;
         }
         switch (opt->desc->optcode) {
         case OPT_RAW:
            termarg.c_iflag &=
              ~(IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|ISTRIP|INLCR|IGNCR|ICRNL|IXON|IXOFF
#ifdef IUCLC
                |IUCLC
#endif
                |IXANY|IMAXBEL);
            termarg.c_iflag |= (0);
            termarg.c_oflag &= ~(OPOST);
            termarg.c_oflag |= (0);
            termarg.c_cflag &= ~(0);
            termarg.c_cflag |= (0);
            termarg.c_lflag &= ~(ISIG|ICANON
#ifdef XCASE
                                 |XCASE
#endif
                                 );
            termarg.c_lflag |= (0);
            termarg.c_cc[VMIN] = 1;
            termarg.c_cc[VTIME] = 0;
            break;
         case OPT_TERMIOS_RAWER:
            termarg.c_iflag = 0;
            termarg.c_oflag = 0;
            termarg.c_lflag = 0;
            termarg.c_cflag = (CS8);
            termarg.c_cc[VMIN] = 1;
            termarg.c_cc[VTIME] = 0;
            break;
         case OPT_SANE:
            /* cread -ignbrk brkint  -inlcr  -igncr  icrnl
              -ixoff  -iuclc  -ixany  imaxbel opost -olcuc -ocrnl
              onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0
              vt0 ff0 isig icanon iexten echo echoe echok -echonl
              -noflsh -xcase -tostop -echoprt echoctl echoke, and
              also  sets  all special characters to their default
              values.
*/
            termarg.c_iflag &= ~(IGNBRK|INLCR|IGNCR|IXOFF
#ifdef IUCLC
                                 |IUCLC
#endif
                                 |IXANY);
            termarg.c_iflag |= (BRKINT|ICRNL|IMAXBEL);
            termarg.c_oflag &= ~(0      /* for canonical reasons */
#ifdef OLCUC
                                 |OLCUC
#endif
#ifdef OCRNL
                                 |OCRNL
#endif
#ifdef ONOCR
                                 |ONOCR
#endif
#ifdef ONLRET
                                 |ONLRET
#endif
#ifdef OFILL
                                 |OFILL
#endif
#ifdef OFDEL
                                 |OFDEL
#endif
#ifdef NLDLY
                                 |NLDLY
#endif
#ifdef CRDLY
                                 |CRDLY
#endif
#ifdef TABDLY
                                 |TABDLY
#endif
#ifdef BSDLY
                                 |BSDLY
#endif
#ifdef VTDLY
                                 |VTDLY
#endif
#ifdef FFDLY
                                 |FFDLY
#endif
                                 );
            termarg.c_oflag |= (OPOST|ONLCR
#ifdef NL0
                                |NL0
#endif
#ifdef CR0
                                |CR0
#endif
#ifdef TAB0
                                |TAB0
#endif
#ifdef BS0
                                |BS0
#endif
#ifdef VT0
                                |VT0
#endif
#ifdef FF0
                                |FF0
#endif
                                );
            termarg.c_cflag &= ~(0);
            termarg.c_cflag |= (CREAD);
            termarg.c_lflag &= ~(ECHONL|NOFLSH
#ifdef XCASE
                                 |XCASE
#endif
                                 |TOSTOP
#ifdef ECHOPRT
                                 |ECHOPRT
#endif
                                 );
            termarg.c_lflag |= (ISIG|ICANON|IEXTEN|ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE);
            /*! "sets characters to their default values... - which? */
            break;
         case OPT_TERMIOS_CFMAKERAW:
#if HAVE_CFMAKERAW
            cfmakeraw(&termarg);
#else
            /* these setting follow the Linux documenation of cfmakeraw */
            termarg.c_iflag &=
               ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
            termarg.c_oflag &= ~(OPOST);
            termarg.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
            termarg.c_cflag &= ~(CSIZE|PARENB);
            termarg.c_cflag |= (CS8);
#endif
            break;
         default:
            Error("TERMIOS option not handled - internal error?");
         }
         if (Tcsetattr(fd, TCSADRAIN, &termarg) < 0) {
            Error3("tcsetattr(%d, TCSADRAIN, %p): %s",
                   fd, &termarg, strerror(errno));
            opt->desc = ODESC_ERROR; ++opt; continue;
         }

#endif /* WITH_TERMIOS */

#if WITH_STREAMS
#define ENABLE_APPLYOPT
#include "xio-streams.c"
#undef ENABLE_APPLYOPT
#endif /* WITH_STREAMS */

      } else {
        /*Error1("applyopts(): function %d not implemented",
          opt->desc->func);*/
         if (opt->desc->func != OFUNC_EXT && opt->desc->func != OFUNC_SIGNAL) {
            Error1("applyopts(): option \"%s\" does not apply",
                   opt->desc->defname);
            opt->desc = ODESC_ERROR;
            ++opt;
            continue;
         }
         ++opt;
         continue;
      }
      opt->desc = ODESC_DONE;
      ++opt;
   }
   return 0;
}

/* applies to fd all options belonging to phases */
/* note: not all options can be applied this way (e.g. OFUNC_SPEC with PH_OPEN)
   implemented are: OFUNC_FCNTL, OFUNC_SOCKOPT (probably not all types),
   OFUNC_TERMIOS_FLAG, OFUNC_TERMIOS_PATTERN, and some OFUNC_SPEC */
int applyopts2(int fd, struct opt *opts, unsigned int from, unsigned int to) {
   unsigned int i;
   int stat;

   for (i = from; i <= to; ++i) {
      if ((stat = applyopts(fd, opts, i)) < 0)
         return stat;
   }
   return 0;
}

/* apply and consume all options of type FLAG and group.
   Return 0 if everything went right, or -1 if an error occurred. */
int applyopts_flags(struct opt *opts, int group, flags_t *result) {
   struct opt *opt = opts;

   if (!opts)  return 0;

   while (opt->desc != ODESC_END) {
      if (opt->desc != ODESC_DONE && 
          (opt->desc->group & group)) {
         if (opt->desc->func == OFUNC_FLAG) {
            if (opt->value.u_bool) {
               *result |= opt->desc->major;
            } else {
               *result &= ~opt->desc->major;
            }
            opt->desc = ODESC_DONE;
         } else if (opt->desc->func == OFUNC_FLAG_PATTERN) {
            *result &= ~opt->desc->minor;
            *result |= opt->desc->major;
            opt->desc = ODESC_DONE;
         }
      }
      ++opt;
   }
   return 0;
}



/* set the FD_CLOEXEC fcntl if the options do not set it to 0 */
int applyopts_cloexec(int fd, struct opt *opts) {
   bool docloexec = 1;

   if (!opts)  return 0;

   retropt_bool(opts, OPT_CLOEXEC, &docloexec);
   if (docloexec) {
      if (Fcntl_l(fd, F_SETFD, FD_CLOEXEC) < 0) {
         Warn2("fcntl(%d, F_SETFD, FD_CLOEXEC): %s", fd, strerror(errno));
      }
   }
   return 0;
}

int applyopts_fchown(int fd, struct opt *opts) {
   uid_t user = -1;
   gid_t group = -1;

   retropt_uidt(opts, OPT_USER, &user);
   retropt_gidt(opts, OPT_GROUP, &group);

   if (user != (uid_t)-1 || group != (gid_t)-1) {
      if (Fchown(fd, user, group) < 0) {
         Error4("fchown(%d, "F_uid", "F_gid"): %s", fd, user, group,
                strerror(errno));
         return STAT_RETRYLATER;
      }
   }
   return 0;
}

/* caller must make sure that option is not yet consumed */
static int applyopt_offset(struct single *xfd, struct opt *opt) {
   unsigned char *ptr;

   ptr = (unsigned char *)xfd + opt->desc->major;
   switch (opt->desc->type) {
   case TYPE_BOOL:
      *(bool *)ptr = opt->value.u_bool;  break;
   case TYPE_INT:
      *(int *)ptr = opt->value.u_int;  break;
   case TYPE_UINT:
      *(unsigned int *)ptr = opt->value.u_uint;  break;
   case TYPE_DOUBLE:
      *(double *)ptr = opt->value.u_double;  break;
   case TYPE_TIMEVAL:
      *(struct timeval *)ptr = opt->value.u_timeval;  break;
   case TYPE_STRING_NULL:
      if (opt->value.u_string == NULL) {
         *(char **)ptr = NULL;
         break;
      }
      /* PASSTHROUGH */
   case TYPE_STRING:
      if ((*(char **)ptr = strdup(opt->value.u_string)) == NULL) {
         Error1("strdup("F_Zu"): out of memory",
                strlen(opt->value.u_string)+1);
      }
      break;
   case TYPE_CONST:
      *(int *)ptr = opt->desc->minor;
      break;
   case TYPE_TIMESPEC:
      *(struct timespec *)ptr = opt->value.u_timespec; break;
   default:
      Error1("applyopt_offset(): type %d not implemented",
             opt->desc->type);
      return -1;
   }
   opt->desc = ODESC_DONE;
   return 0;
}

int applyopts_offset(struct single *xfd, struct opt *opts) {
   struct opt *opt;

   opt = opts; while (opt->desc != ODESC_END) {
      if ((opt->desc == ODESC_DONE) ||
          opt->desc->func != OFUNC_OFFSET)  {
         ++opt; continue; }

      applyopt_offset(xfd, opt);
      opt->desc = ODESC_DONE;
      ++opt;
   }
   return 0;
}

/* applies to xfd all OFUNC_EXT options belonging to phase
   returns -1 if an error occurred */
int applyopts_single(struct single *xfd, struct opt *opts, enum e_phase phase) {
   struct opt *opt;
   int lockrc;

   if (!opts)  return 0;

   opt = opts; while (opt->desc != ODESC_END) {
      if ((opt->desc == ODESC_DONE) ||
          (opt->desc->phase != phase && phase != PH_ALL)) {
         /* option not handled in this function */
         ++opt; continue;
      } else {
     switch (opt->desc->func) {

     case OFUNC_OFFSET:
        applyopt_offset(xfd, opt);
        break;

     case OFUNC_EXT:
      switch (opt->desc->optcode) {
#if 0
      case OPT_IGNOREEOF:
         xfd->ignoreeof = true;
         break;
      case OPT_CR:
         xfd->lineterm = LINETERM_CR;
         break;
      case OPT_CRNL:
         xfd->lineterm = LINETERM_CRNL;
         break;
#endif /* 0 */
      case OPT_READBYTES:
         xfd->readbytes = opt->value.u_sizet;
         xfd->actbytes  = xfd->readbytes;
         break;
      case OPT_LOCKFILE:
         if (xfd->lock.lockfile) {
            Error("only one use of options lockfile and waitlock allowed");
         }
         xfd->lock.lockfile = strdup(opt->value.u_string);
         xfd->lock.intervall.tv_sec  = 1;
         xfd->lock.intervall.tv_nsec = 0;

         if ((lockrc = xiolock(&xfd->lock)) < 0) {
            /* error message already printed */
            return -1;
         }
         if (lockrc) {
            Error1("could not obtain lock \"%s\"", xfd->lock.lockfile);
         } else {
            xfd->havelock = true;
         }
         break;
      case OPT_WAITLOCK:
         if (xfd->lock.lockfile) {
            Error("only one use of options lockfile and waitlock allowed");
         }
         xfd->lock.lockfile = strdup(opt->value.u_string);
         xfd->lock.waitlock = true;
         xfd->lock.intervall.tv_sec  = 1;
         xfd->lock.intervall.tv_nsec = 0;

         /*! this should be integrated into central select()/poll() loop */
         if (xiolock(&xfd->lock) < 0) {
            return -1;
         }
         xfd->havelock = true;
         break;
         
      default:
         /* just store the value in the correct component of struct single */
         if (opt->desc->type == TYPE_CONST) {
            /* only for integral types compatible to int */
            *(int *)(&((char *)xfd)[opt->desc->major]) = opt->desc->arg3;
         } else {
            memcpy(&((char *)xfd)[opt->desc->major], &opt->value, opt->desc->minor);
         }
      }
      break;

     case OFUNC_OFFSET_MASKS:
        {
           void *masks = (char *)xfd + opt->desc->major;
           size_t masksize = opt->desc->minor;
           unsigned long bit = opt->desc->arg3;
           switch (masksize) {
           case sizeof(uint16_t):
              if (opt->value.u_bool) {
                 ((uint16_t *)masks)[0] |= bit;
              } else {
                 ((uint16_t *)masks)[1] |= bit;
              }
              break;
           case sizeof(uint32_t):
              if (opt->value.u_bool) {
                 ((uint32_t *)masks)[0] |= bit;
              } else {
                 ((uint32_t *)masks)[1] |= bit;
              }
              break;
           default:
              Info1("sizeof(uint32_t)="F_Zu, sizeof(uint32_t));
              Error1("applyopts_single: masksize "F_Zu" not implemented",
                     masksize);
           }
        }
        break;

#if _WITH_SOCKET
     case OFUNC_SOCKOPT:
         switch (opt->desc->optcode) {
#if WITH_IP4 && (defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN))
         case OPT_IP_ADD_MEMBERSHIP:
            {
               union {
#if HAVE_STRUCT_IP_MREQN
                  struct ip_mreqn mreqn;
#endif
                  struct ip_mreq  mreq;
               } ip4_mreqn = {{{0}}};
               /* IPv6 not supported - seems to have different handling */
/*
mc:addr:ifname|ifind
mc:ifname|ifind
mc:addr
*/
               union sockaddr_union sockaddr1;
               socklen_t socklen1 = sizeof(sockaddr1.ip4);
               union sockaddr_union sockaddr2;
               socklen_t socklen2 = sizeof(sockaddr2.ip4);

               /* first parameter is alway multicast address */
               /*! result */
               xiogetaddrinfo(opt->value.u_ip_mreq.multiaddr, NULL,
                              xfd->para.socket.la.soa.sa_family,
                              SOCK_DGRAM, IPPROTO_IP,
                              &sockaddr1, &socklen1, 0, 0);
               ip4_mreqn.mreq.imr_multiaddr = sockaddr1.ip4.sin_addr;
               if (0) {
                  ;     /* for canonical reasons */
#if HAVE_STRUCT_IP_MREQN
               } else if (opt->value.u_ip_mreq.ifindex[0] != '\0') {
                  /* three parameters */
                  /* second parameter is interface address */
                  xiogetaddrinfo(opt->value.u_ip_mreq.param2, NULL,
                                 xfd->para.socket.la.soa.sa_family,
                                 SOCK_DGRAM, IPPROTO_IP,
                                 &sockaddr2, &socklen2, 0, 0);
                  ip4_mreqn.mreq.imr_interface = sockaddr2.ip4.sin_addr;
                  /* third parameter is interface */
                  if (ifindex(opt->value.u_ip_mreq.ifindex,
                              (unsigned int *)&ip4_mreqn.mreqn.imr_ifindex, -1)
                      < 0) {
                     Error1("cannot resolve interface \"%s\"", 
                            opt->value.u_ip_mreq.ifindex);
                  }
#endif /* HAVE_STRUCT_IP_MREQN */
               } else {
                  /* two parameters */
                  if (0) {
                     ;  /* for canonical reasons */
#if HAVE_STRUCT_IP_MREQN
                  /* there is a form with two parameters that uses mreqn */
                  } else if (ifindex(opt->value.u_ip_mreq.param2,
                                     (unsigned int *)&ip4_mreqn.mreqn.imr_ifindex,
                                     -1)
                             >= 0) {
                     /* yes, second param converts to interface */
                     ip4_mreqn.mreq.imr_interface.s_addr = htonl(0);
#endif /* HAVE_STRUCT_IP_MREQN */
                  } else {
                     /*! result */
                     xiogetaddrinfo(opt->value.u_ip_mreq.param2, NULL,
                                    xfd->para.socket.la.soa.sa_family,
                                    SOCK_DGRAM, IPPROTO_IP,
                                    &sockaddr2, &socklen2, 0, 0);
                     ip4_mreqn.mreq.imr_interface = sockaddr2.ip4.sin_addr;
                  }
               }
                        
#if LATER
               if (0) {
                  ; /* for canonical reasons */
               } else if (xfd->para.socket.la.soa.sa_family == PF_INET) {
               } else if (xfd->para.socket.la.soa.sa_family == PF_INET6) {
                  ip6_mreqn.mreq.imr_multiaddr = sockaddr1.ip6.sin6_addr;
                  ip6_mreqn.mreq.imr_interface = sockaddr2.ip6.sin6_addr;
               }
#endif

#if HAVE_STRUCT_IP_MREQN
               if (Setsockopt(xfd->rfd, opt->desc->major, opt->desc->minor,
                              &ip4_mreqn.mreqn, sizeof(ip4_mreqn.mreqn)) < 0) {
                  Error8("setsockopt(%d, %d, %d, {0x%08x,0x%08x,%d}, "F_Zu"): %s",
                         xfd->rfd, opt->desc->major, opt->desc->minor,
                         ip4_mreqn.mreqn.imr_multiaddr.s_addr,
                         ip4_mreqn.mreqn.imr_address.s_addr,
                         ip4_mreqn.mreqn.imr_ifindex,
                         sizeof(ip4_mreqn.mreqn),
                         strerror(errno));
                  opt->desc = ODESC_ERROR; continue;
               }
#else
               if (Setsockopt(xfd->rfd, opt->desc->major, opt->desc->minor,
                              &ip4_mreqn.mreq, sizeof(ip4_mreqn.mreq)) < 0) {
                  Error7("setsockopt(%d, %d, %d, {0x%08x,0x%08x}, "F_Zu"): %s",
                         xfd->rfd, opt->desc->major, opt->desc->minor,
                         ip4_mreqn.mreq.imr_multiaddr,
                         ip4_mreqn.mreq.imr_interface,
                         sizeof(ip4_mreqn.mreq),
                         strerror(errno));
                  opt->desc = ODESC_ERROR; continue;
               }
#endif
               break;
            }
           break;
#endif /* WITH_IP4 && (defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN)) */



#if WITH_IP6 && defined(HAVE_STRUCT_IPV6_MREQ)
         case OPT_IPV6_JOIN_GROUP:
            {
               struct ipv6_mreq ip6_mreq = {{{{0}}}};
               union sockaddr_union sockaddr1;
               socklen_t socklen1 = sizeof(sockaddr1.ip6);

               /* always two parameters */
               /* first parameter is multicast address */
               /*! result */
               xiogetaddrinfo(opt->value.u_ip_mreq.multiaddr, NULL,
                              xfd->para.socket.la.soa.sa_family,
                              SOCK_DGRAM, IPPROTO_IP,
                              &sockaddr1, &socklen1, 0, 0);
               ip6_mreq.ipv6mr_multiaddr = sockaddr1.ip6.sin6_addr;
               if (ifindex(opt->value.u_ip_mreq.param2,
                           &ip6_mreq.ipv6mr_interface, -1)
                   < 0) {
                  Error1("interface \"%s\" not found",
                         opt->value.u_ip_mreq.param2);
                  ip6_mreq.ipv6mr_interface = htonl(0);
               }

               if (Setsockopt(xfd->rfd, opt->desc->major, opt->desc->minor,
                              &ip6_mreq, sizeof(ip6_mreq)) < 0) {
                  Error6("setsockopt(%d, %d, %d, {...,0x%08x}, "F_Zu"): %s",
                         xfd->rfd, opt->desc->major, opt->desc->minor,
                         ip6_mreq.ipv6mr_interface,
                         sizeof(ip6_mreq),
                         strerror(errno));
                  opt->desc = ODESC_ERROR; continue;
               }
            }
           break;
#endif /* WITH_IP6 && defined(HAVE_STRUCT_IPV6_MREQ) */
        default:
           /* ignore here */
           ++opt; continue;
        }
        break;
#endif /* _WITH_SOCKET */

     default:
        ++opt;
        continue;
     }
     opt->desc = ODESC_DONE;
     ++opt;
      }
   }
   return 0;
}


/* xfd->para.exec.pid must be set */
int applyopts_signal(struct single *xfd, struct opt *opts) {
   struct opt *opt;

   if (!opts)  return 0;

   opt = opts; while (opt->desc != ODESC_END) {
      if (opt->desc == ODESC_DONE || opt->desc->func != OFUNC_SIGNAL) {
         ++opt; continue;
      }

      if (xio_opt_signal(xfd->child.pid, opt->desc->major) < 0) {
         opt->desc = ODESC_ERROR; continue;
      }
      opt->desc = ODESC_DONE;
      ++opt;
   }
   return 0;
}

/* apply remaining options to file descriptor, and tell us if something is
   still unused */
int _xio_openlate(struct single *xfd, struct opt *opts) {
   int fd;
   int numleft;
   int result;

   if (xfd->rfd >= 0) {
      fd = xfd->rfd;
   } else {
      fd = xfd->wfd;
   }

   _xioopen_setdelayeduser();

   if ((result = applyopts(fd, opts, PH_LATE)) < 0) {
      return result;
   }
#if 0   /*! need to copy opts before previous statement! */
   if (xfd->fdtype == FDTYPE_DOUBLE) {
      if ((result = applyopts(fd, opts, PH_LATE)) < 0) {
         return result;
      }
   }
#endif
   if ((result = applyopts_single(xfd, opts, PH_LATE)) < 0) {
      return result;
   }
   if ((result = applyopts(fd, opts, PH_LATE2)) < 0) {
      return result;
   }
   /*! need to apply to wfd too! */

   if ((numleft = leftopts(opts)) > 0) {
      showleft(opts);
      Error1("%d option(s) could not be used", numleft);
      return -1;
   }
   return 0;
}

int dropopts(struct opt *opts, unsigned int phase) {
   struct opt *opt;

   if (phase == PH_ALL) {
      opts[0].desc = ODESC_END;
      return 0;
   }
   opt = opts; while (opt && opt->desc != ODESC_END) {
      if (opt->desc != ODESC_DONE && opt->desc->phase == phase) {
         Debug1("ignoring option \"%s\"", opt->desc->defname);
         opt->desc = ODESC_DONE;
      }
      ++opt;
   }
   return 0;
}

int dropopts2(struct opt *opts, unsigned int from, unsigned int to) {
   unsigned int i;

   for (i = from; i <= to; ++i) {
      dropopts(opts, i);
   }
   return 0;
}