diff --git a/CHANGES b/CHANGES index 4aa4980..b1e2861 100644 --- a/CHANGES +++ b/CHANGES @@ -197,6 +197,10 @@ Features: reads info from /proc/self/stat and searches for a device with matching major and minor numbers. + Added socat-chain.sh that makes it possible to stack protocols, e.g. to + drive socks through TLS, or to use TLS over a serial line. + Tests: SOCAT_CHAIN_SOCKS4 SOCAT_CHAIN_SSL_PTY + Corrections: When a sub process (EXEC, SYSTEM) terminated with exit code other than 0, its last sent data might have been lost depending on timing of read/ diff --git a/Makefile.in b/Makefile.in index 3ecd5d2..cf9f263 100644 --- a/Makefile.in +++ b/Makefile.in @@ -76,7 +76,8 @@ HFILES = sycls.h sslcls.h error.h dalan.h procan.h filan.h hostan.h sysincludes. DOCFILES = README README.FIPS CHANGES FILES EXAMPLES PORTING SECURITY DEVELOPMENT doc/socat.yo doc/socat.1 doc/socat.html FAQ BUGREPORTS COPYING COPYING.OpenSSL doc/dest-unreach.css doc/socat-openssltunnel.html doc/socat-multicast.html doc/socat-tun.html doc/socat-genericsocket.html -SHFILES = daemon.sh mail.sh ftp.sh readline.sh \ +SHFILES = socat-chain.sh \ + daemon.sh mail.sh ftp.sh readline.sh \ socat_buildscript_for_android.sh TESTFILES = test.sh socks4echo.sh proxyecho.sh readline-test.sh \ proxy.sh socks4a-echo.sh @@ -131,6 +132,7 @@ install: progs $(srcdir)/doc/socat.1 mkdir -p $(DESTDIR)$(BINDEST) $(INSTALL) -m 755 socat $(DESTDIR)$(BINDEST)/socat1 ln -s socat1 $(DESTDIR)$(BINDEST)/socat + $(INSTALL) -m 755 socat-chain.sh $(DESTDIR)$(BINDEST) $(INSTALL) -m 755 procan $(DESTDIR)$(BINDEST) $(INSTALL) -m 755 filan $(DESTDIR)$(BINDEST) mkdir -p $(DESTDIR)$(MANDEST)/man1 @@ -140,6 +142,7 @@ install: progs $(srcdir)/doc/socat.1 uninstall: rm -f $(DESTDIR)$(BINDEST)/socat rm -f $(DESTDIR)$(BINDEST)/socat1 + rm -f $(DESTDIR)$(BINDEST)/socat-chain.sh rm -f $(DESTDIR)$(BINDEST)/procan rm -f $(DESTDIR)$(BINDEST)/filan rm -f $(DESTDIR)$(MANDEST)/man1/socat.1 diff --git a/socat-chain.sh b/socat-chain.sh new file mode 100755 index 0000000..865446d --- /dev/null +++ b/socat-chain.sh @@ -0,0 +1,264 @@ +#! /usr/bin/env bash +# Copyright Gerhard Rieger and contributors (see file CHANGES) +# Published under the GNU General Public License V.2, see file COPYING + +# Shell script to build a chain of Socat instances connected via TCP sockets. +# This allows to drive, e.g., PROXY-CONNECT over SSL, or SSL over serial. +# Currently only a chain made from 3 addresses, resulting in two instances, is +# implemented. +# The 2nd address must be one of OPENSSL (SSL), PROXY-CONNECT (PROXY), +# SOCKS4, SOCKS4A, SOCKS5 + +# This is beta! + +# Examples: + +# Drive HTTP CONNECT (PROXY) over SSL +# (establish an SSL tunnel to a proxy server, request being forwarded to a +# telnet server): +# socat-chain.sh \ +# STDIO \ +# PROXY:::23 \ +# OPENSSL::8443 + +# Accept connections that arrive on port 7777, encrypt the data, and send it +# via socks server to final target: +# socat-chain.sh \ +# TCP-L:7777,reuseaddr,fork \ +# OPENSSL,verify=0 \ +# SOCKS4:::8443 + +# Receive SSL coming from a serial lie +# socat-chain.sh \ +# /dev/ttyS0,cfmakeraw \ +# SSL-L,cafile=server.pem,verify=0 \ +# TCP4:localhost:80 + +# Formally, this is what happens: +# socat-chain.sh addr1 addr2 addr3 +# results in something like: +# socat TCP-L:RANDOM addr3 & +# socat addr1 addr2:localhost:RANDOM +# or on passive/listening addr2: +# socat addr2:RANDOM addr3 & +# socat addr1 TCP:localhost:RANDOM + +ECHO="echo -e" + +usage () { + $ECHO "Usage: $0 " + $ECHO " is typically a passive (listening) address like" + $ECHO " TCP-L:1234" + $ECHO " must be one of OPENSSL, PROXY, SOCK4, SOCKS4A, or SOCKS5," + $ECHO " or SSL-L (passive/listening)" + $ECHO " Given server hostname and port are ignored and replaced by internal" + $ECHO " communication point" + $ECHO " is typically a client address with protocol like OPENSSL" + $ECHO " :" + $ECHO " -d* -S -t -T are passed to socat" + $ECHO " -V prints the socat commands before starting them" + $ECHO "Example to drive SOCKS over TLS:" + $ECHO " $0 \\" + $ECHO " TCP4-L:1234,reuseaddr,fork \\" + $ECHO " SOCKS::: \\" + $ECHO " OPENSSL:10.2.3.4:12345,cafile=..." + $ECHO " Clients that connect to port 1234 will be forwarded to : using socks" + $ECHO " over TLS" +} + + +LOCALHOST=127.0.0.1 + +VERBOSE= QUIET= OPTS= +while [ "$1" ]; do + case "X$1" in + X-h) usage; exit ;; + X-V) VERBOSE=1 ;; + X-q) QUIET=1; OPTS="-d0" ;; + X-d*|X-l?*) OPTS="$OPTS $1" ;; + X-b|X-S|X-t|X-T|X-l) OPT=$1; shift; OPTS="$OPTS $OPT $1" ;; + X-) break ;; + X-*) echo "$0: Unknown option \"$1\"" >&2 + usage >&2 + exit 1 ;; + *) break ;; + esac + shift +done + +ARG0="$1" +ARG1="$2" +ARG2="$3" + +if [ -z "$ARG0" -o -z "$ARG1" -o -z "$ARG2" ]; then + echo "$0: Three addresses required" >&2 + usage >&2 + exit 1 +fi + + +mkprogname () { + ARG="$1" + if [[ "$ARG" =~ .*[:].* ]]; then + NAME="${ARG%%:*}" + elif [[ "$ARG" =~ .*[,].* ]]; then + NAME="${ARG%%,*}" + elif [ "X$ARG" = X- ]; then + NAME=stdio + else + NAME="$ARG" + fi + NAME="${NAME,,*}" + echo $NAME +} + + +# You may place a fork option in the first address +# in which case the following internal listeners do fork too +FORK= +case "$ARG0" in + *,fork,*|*,fork) FORK=fork ;; +esac + +# Split middle address for insertion of additional parts +if [[ "$ARG1" =~ .*,.* ]]; then + ARG1A="${ARG1%%,*}" + ARG1B="${ARG1#*,}" +else + ARG1A="$ARG1" + ARG1B= +fi + +case "$0" in + */*) SOCAT=${0%/*}/socat ;; + *) SOCAT=socat ;; +esac + +PORT=$($SOCAT -d -d TCP4-L:0,accept-timeout=0.000001 /dev/null 2>&1 |grep listening |sed 's/.*:\([1-9][0-9]*\)$/\1/') +if [ -z "$PORT" ]; then + echo "$0: Failed to determine free TCP port" >&2 + exit 1 +fi + +PASSIVE= # is the second address passive/listening/server? +case "${ARG1A^^*}" in + OPENSSL|OPENSSL:*|SSL|SSL:.*) + OPTS1A= + #if [[ $ARG1A =~ ^\([^:]*\):\([^:]*\):\([^,]*\)\(.*\) ]]; then # bash 3 + if [[ $ARG1A =~ ^([^:]*):([^:]*):([^,]*)(.*) ]]; then + OPTS1A="${BASH_REMATCH[4]}" + #elif [[ $ARG1A =~ ^\([^,]*\)\(.*\) ]]; then # bash 3 + elif [[ $ARG1A =~ ^([^,]*)(.*) ]]; then + OPTS1A="${BASH_REMATCH[2]}" + else + echo "$0: \"$ARG1A\": invalid arguments" >&2 + exit 1 + fi + PROG1="${BASH_REMATCH[1]}" + NAME1=$(mkprogname "${BASH_REMATCH[1]}") + NAME2=$(mkprogname "$ARG2") + ARG1A=$PROG1:$LOCALHOST:$PORT$OPTS1A ;; + PROXY-CONNECT:*|PROXY:*) + #if ! [[ $ARG1A =~ ^\([^:]*\):\([^:]*\):\([^:]*\):\([^,]*\)\(.*\) ]]; then # bash 3 + if ! [[ $ARG1A =~ ^([^:]*):([^:]*):([^:]*):([^,]*)(.*) ]]; then + echo "$0: \"$ARG1A\": invalid arguments" >&2 + exit 1 + fi + #echo "0:\"${BASH_REMATCH[0]}\" 1:\"${BASH_REMATCH[1]}\" 2:\"${BASH_REMATCH[2]}\" 3:\"${BASH_REMATCH[3]}\" 4:\"${BASH_REMATCH[4]}\"" + PROG1="${BASH_REMATCH[1]}" + NAME1=$(mkprogname "${PROG1,,*}") + NAME2=$(mkprogname "$ARG2") + OPTS1A="${BASH_REMATCH[5]}" + ARG1A="$PROG1:$LOCALHOST:${BASH_REMATCH[3]}:${BASH_REMATCH[4]},proxyport=$PORT,$OPTS1A" ;; + SOCKS:*|SOCKS4:*|SOCKS4A*) + #if ! [[ $ARG1A =~ ^\([^:]*\):\([^:]*\):\([^:]*\):\([^:,]*\),* ]]; then # bash 3 + if ! [[ $ARG1A =~ ^([^:]*):([^:]*):([^:]*):([^:,]*),* ]]; then + echo "$0: \"$ARG1A\": invalid arguments" >&2 + exit 1 + fi + PROG1="${BASH_REMATCH[1]}" + NAME1=$(mkprogname "${PROG1,,*}") + NAME2=$(mkprogname "$ARG2") + OPTS1A="${BASH_REMATCH[5]}" + ARG1A="$PROG1:$LOCALHOST:${BASH_REMATCH[3]}:${BASH_REMATCH[4]},socksport=$PORT,$OPTS1A" ;; + SOCKS5:*|SOCKS5-CONNECT*) + #if ! [[ $ARG1A =~ ^\([^:]*\):\([^:]*\):\([^:]*\):\([^:,]*\):\([^:,]*\),* ]]; then # bash 3 + if ! [[ $ARG1A =~ ^([^:]*):([^:]*):([^:]*):([^:,]*):([^:,]*),* ]]; then + echo "$0: \"$ARG1A\": invalid arguments" >&2 + exit 1 + fi + PROG1="${BASH_REMATCH[1]}" + NAME1=$(mkprogname "${PROG1,,*}") + NAME2=$(mkprogname "$ARG2") + OPTS1A="${BASH_REMATCH[6]}" + ARG1A="$PROG1:$LOCALHOST:$PORT:${BASH_REMATCH[4]}:${BASH_REMATCH[5]},$OPTS1A" ;; + # Passive (server) addresses + OPENSSL-LISTEN|OPENSSL-LISTEN:*|SSL-L|SSL-L:.*) + PASSIVE=1 + OPTS1A= + #if [[ $ARG1A =~ ^\([^:]*\):\([^,]*\)\(.*\) ]]; then # bash 3 + if [[ $ARG1A =~ ^([^:]*):([^,]*)(.*) ]]; then + OPTS1A="${BASH_REMATCH[3]}" + #elif [[ $ARG1A =~ ^\([^,]*\)\(.*\) ]]; then # bash 3 + elif [[ $ARG1A =~ ^([^,]*)(.*) ]]; then + OPTS1A="${BASH_REMATCH[2]}" + else + echo "$0: \"$ARG1A\": invalid arguments" >&2 + exit 1 + fi + PROG1="${BASH_REMATCH[1]}" + NAME1=$(mkprogname "$ARG0") + NAME2=$(mkprogname "${BASH_REMATCH[1]}") + ARG1A=$PROG1:$PORT$OPTS1A ;; + *) echo "$0: Unsupported address \"$ARG1A\"" >&2 + usage >&2 + exit 1 ;; +esac + +ADDR1A="$ARG0" +if [ -z "$PASSIVE" ]; then + ADDR1B="$ARG1A,bind=$LOCALHOST,$ARG1B" + ADDR2A="TCP4-L:$PORT,reuseaddr,$FORK,bind=$LOCALHOST,range=$LOCALHOST/32" +else + ADDR1B="TCP4:$LOCALHOST:$PORT,bind=$LOCALHOST" + ADDR2A="$ARG1A,reuseaddr,$FORK,bind=$LOCALHOST,range=$LOCALHOST/32,$ARG1B" +fi +ADDR2B="$ARG2" + + +pid1= pid2= +trap '[ "$pid1" ] && kill $pid1 2>/dev/null; [ "$pid2" ] && kill $pid2 2>/dev/null' EXIT + +set -bm +trap 'rc=$?; if ! kill -n 0 $pid2 2>/dev/null; then [ -z "$QUIET" -a $rc -ne 0 ] && echo "$0: socat-$NAME2 exited with rc=$rc" >&2; exit $rc; fi' SIGCHLD + +# Start instance 2 first, because instance 1 ("left") connects to 2 +if [ "$VERBOSE" ]; then + $ECHO "$SOCAT $OPTS -lp socat-$NAME2 \\ + \"$ADDR2A\" \\ + \"$ADDR2B\" &" +fi +$SOCAT $OPTS -lp socat-$NAME2 \ + "$ADDR2A" \ + "$ADDR2B" & +pid2=$! +sleep 0.1 + +#trap 'if ! kill -n 0 $pid1 2>/dev/null; then [ -z "$QUIET" ] && echo "$0: socat-$NAME1 exited with rc=$?" >&2; kill $pid2 2>/dev/null; exit 1; elif ! kill -n 0 $pid2 2>/dev/null; then [ -z "$QUIET" ] && echo "$0: socat-$NAME2 exited with rc=$?" >&2; kill $pid1 2>/dev/null; exit 1; fi' SIGCHLD + +if [ "$VERBOSE" ]; then + $ECHO "$SOCAT $OPTS -lp socat-$NAME1 \\ + \"$ADDR1A\" \\ + \"$ADDR1B\"" +fi +$SOCAT $OPTS -lp socat-$NAME1 \ + "$ADDR1A" \ + "$ADDR1B" +#pid1=$! +rc1=$? + +kill $pid2 2>/dev/null +wait 2>/dev/null +#wait -f + +exit $rc1 diff --git a/socks4echo.sh b/socks4echo.sh index 103719a..48ea536 100755 --- a/socks4echo.sh +++ b/socks4echo.sh @@ -91,7 +91,7 @@ else fi if [ "$u" != "nobody" ]; then $ECHO "$SOCKSREPLY_FAILED" - echo "wrong socks user requested" >&2 + echo "wrong socks user requested (expected \"nobody\")" >&2 exit fi diff --git a/test.sh b/test.sh index c9bc3aa..f91973e 100755 --- a/test.sh +++ b/test.sh @@ -1044,7 +1044,7 @@ checkconds() { local uname="$(echo $UNAME |tr 'A-Z' 'a-z')" for i in $unames; do if [ "$uname" = "$(echo "$i" |tr 'A-Z,' 'a-z ')" ]; then - # good, mark as passed + # good, mark as passed i= break; fi @@ -18838,6 +18838,154 @@ esac N=$((N+1)) +# Test the socat-chain.sh script with SOCKS4 over UNIX-socket +NAME=SOCAT_CHAIN_SOCKS4 +case "$TESTS" in +*%$N%*|*%functions%*|*%scripts%*|*%socat-chain%*|*%listen%*|*%fork%*|*%ip4%*|*%tcp4%*|*%unix%*|*%socks4%*|*%socket%*|*%$NAME%*) +TEST="$NAME: test socat-chain.sh with SOCKS4 over UNIX-socket" +# Run a socks4 server on UNIX-listen +# Connect with socat-chein.sh; check if data transfer is correct +if ! eval $NUMCOND; then : +# Remove unneeded checks, adapt lists of the remaining ones +elif ! cond=$(checkconds \ + "" \ + "" \ + "" \ + "IP4 TCP LISTEN STDIO UNIX" \ + "TCP4-LISTEN PIPE STDIN STDOUT TCP4 UNIX UNIX-LISTEN" \ + "so-reuseaddr" \ + "tcp4 unix" ); then + $PRINTF "test $F_n $TEST... ${YELLOW}$cond${NORMAL}\n" $N + numCANT=$((numCANT+1)) + listCANT="$listCANT $N" + namesCANT="$namesCANT $NAME" +else + ts="$td/test$N.sock" + tf="$td/test$N.stdout" + te="$td/test$N.stderr" + tdiff="$td/test$N.diff" + da="test$N $(date) $RANDOM" + CMD0="$TRACE $SOCAT $opts UNIX-LISTEN:$ts,reuseaddr EXEC:./socks4echo.sh" + CMD1="$TRACE ./socat-chain.sh $opts - SOCKS4::32.98.76.54:32109,socksuser=nobody UNIX:$ts" + printf "test $F_n $TEST... " $N + $CMD0 >/dev/null 2>"${te}0" & + pid0=$! + waitunixport $ts 1 + #relsleep 1 # if no matching wait*port function + echo "$da" |$CMD1 >"${tf}1" 2>"${te}1" + rc1=$? + kill $pid0 2>/dev/null; wait + if [ "$rc1" -ne 0 ]; then + $PRINTF "$FAILED (rc1=$rc1)\n" + echo "$CMD0 &" + cat "${te}0" >&2 + echo "$CMD1" + cat "${te}1" >&2 + numFAIL=$((numFAIL+1)) + listFAIL="$listFAIL $N" + namesFAIL="$namesFAIL $NAME" + elif ! echo "$da" |diff - "${tf}1" >$tdiff; then + $PRINTF "$FAILED (diff)\n" + echo "$CMD0 &" + cat "${te}0" >&2 + echo "$CMD1" + cat "${te}1" >&2 + echo "// diff:" >&2 + cat "$tdiff" >&2 + numFAIL=$((numFAIL+1)) + listFAIL="$listFAIL $N" + namesFAIL="$namesFAIL $NAME" + else + $PRINTF "$OK\n" + if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi + if [ "$DEBUG" ]; then cat "${te}0" >&2; fi + if [ "$VERBOSE" ]; then echo "$CMD1"; fi + if [ "$DEBUG" ]; then cat "${te}1" >&2; fi + numOK=$((numOK+1)) + fi +fi # NUMCOND + ;; +esac +N=$((N+1)) + +# Test the socat-chain.sh script by driving SSL over serial +NAME=SOCAT_CHAIN_SSL_PTY +case "$TESTS" in +*%$N%*|*%functions%*|*%scripts%*|*%socat-chain%*|*%listen%*|*%fork%*|*%ip4%*|*%tcp4%*|*%unix%*|*%socket%*|*%socket%*|*%$NAME%*) +TEST="$NAME: test socat-chain.sh with SSL over PTY" +# Run a socat-chain.sh instance with SSL listening behind a PTY; +# open the PTY with socat-chein.sh using SSL; +# check if data transfer is correct +if ! eval $NUMCOND; then : +# Remove unneeded checks, adapt lists of the remaining ones +elif ! cond=$(checkconds \ + "" \ + "" \ + "" \ + "IP4 TCP LISTEN OPENSSL STDIO PTY" \ + "TCP4-LISTEN SOCKETPAIR STDIN STDOUT TCP4 SSL SSL-L" \ + "so-reuseaddr" \ + "tcp4" ); then + $PRINTF "test $F_n $TEST... ${YELLOW}$cond${NORMAL}\n" $N + numCANT=$((numCANT+1)) + listCANT="$listCANT $N" + namesCANT="$namesCANT $NAME" +elif [[ $BASH_VERSION =~ ^[1-3]\. ]]; then + $PRINTF "test $F_n $TEST... ${YELLOW}requires bash 4 or higher${NORMAL}\n" $N + numCANT=$((numCANT+1)) + listCANT="$listCANT $N" + namesCANT="$namesCANT $NAME" +else + gentestcert testsrv + tp="$td/test$N.pty" + tf="$td/test$N.stdout" + te="$td/test$N.stderr" + tdiff="$td/test$N.diff" + da="test$N $(date) $RANDOM" + CMD0="$TRACE ./socat-chain.sh $opts PTY,link=$tp SSL-L,cert=testsrv.pem,verify=0 SOCKETPAIR" + CMD1="$TRACE ./socat-chain.sh $opts - SSL,cafile=testsrv.crt,commonname=localhost $tp,cfmakeraw" + printf "test $F_n $TEST... " $N + $CMD0 >/dev/null 2>"${te}0" & + pid0=$! + waitfile $tp 1 + echo "$da" |$CMD1 >"${tf}1" 2>"${te}1" + rc1=$? + kill $pid0 2>/dev/null + wait 2>/dev/null + if [ "$rc1" -ne 0 ]; then + $PRINTF "$FAILED (rc1=$rc1)\n" + echo "$CMD0 &" + cat "${te}0" >&2 + echo "$CMD1" + cat "${te}1" >&2 + numFAIL=$((numFAIL+1)) + listFAIL="$listFAIL $N" + namesFAIL="$namesFAIL $NAME" + elif ! echo "$da" |diff - "${tf}1" >$tdiff; then + $PRINTF "$FAILED (diff)\n" + echo "$CMD0 &" + cat "${te}0" >&2 + echo "$CMD1" + cat "${te}1" >&2 + echo "// diff:" >&2 + cat "$tdiff" >&2 + numFAIL=$((numFAIL+1)) + listFAIL="$listFAIL $N" + namesFAIL="$namesFAIL $NAME" + else + $PRINTF "$OK\n" + if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi + if [ "$DEBUG" ]; then cat "${te}0" >&2; fi + if [ "$VERBOSE" ]; then echo "$CMD1"; fi + if [ "$DEBUG" ]; then cat "${te}1" >&2; fi + numOK=$((numOK+1)) + fi +fi # NUMCOND + ;; +esac +N=$((N+1)) + + # end of common tests ################################################################################## @@ -19015,7 +19163,7 @@ else numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" namesFAIL="$namesFAIL $NAME" - elif ! echo "$da" |diff "${tf}1" - >$tdiff; then + elif ! echo "$da" |diff - "${tf}1" >$tdiff; then $PRINTF "$FAILED (diff)\n" echo "$CMD0 &" cat "${te}0" >&2 diff --git a/xio-pty.c b/xio-pty.c index 2e6f60c..585fb1f 100644 --- a/xio-pty.c +++ b/xio-pty.c @@ -38,7 +38,8 @@ static int xioopen_pty( { /* we expect the form: filename */ struct single *sfd = &xfd->stream; - int ptyfd = -1, ttyfd = -1; + int ptyfd = -1; /* master */ + int ttyfd = -1; /* slave */ #if defined(HAVE_DEV_PTMX) || defined(HAVE_DEV_PTC) bool useptmx = false; /* use /dev/ptmx or equivalent */ #endif @@ -101,6 +102,18 @@ static int xioopen_pty( if (applyopts_single(sfd, opts, PH_INIT) < 0) return -1; applyopts2(sfd, -1, opts, PH_INIT, PH_EARLY); +#if HAVE_OPENPTY + if (ptyfd < 0) { + int result; + if ((result = Openpty(&ptyfd, &ttyfd, ptyname, NULL, NULL)) < 0) { + Error4("openpty(%p, %p, %p, NULL, NULL): %s", + &ptyfd, &ttyfd, ptyname, strerror(errno)); + return -1; + } + Notice1("PTY is %s", ptyname); + } +#endif /* HAVE_OPENPTY */ + applyopts(sfd, -1, opts, PH_PREBIGEN); #if defined(HAVE_DEV_PTMX) @@ -109,7 +122,7 @@ static int xioopen_pty( # define PTMX "/dev/ptc" /* AIX 4.3.3 */ #endif #if HAVE_DEV_PTMX || HAVE_DEV_PTC - if (useptmx) { + if (useptmx || ptyfd < 0) { if ((ptyfd = Open(PTMX, O_RDWR|O_NOCTTY, 0620)) < 0) { Warn1("open(\""PTMX"\", O_RDWR|O_NOCTTY, 0620): %s", strerror(errno)); @@ -117,7 +130,7 @@ static int xioopen_pty( } else { ;/*0 Info1("open(\""PTMX"\", O_RDWR|O_NOCTTY, 0620) -> %d", ptyfd);*/ } - if (ptyfd >= 0 && ttyfd < 0) { + if (ptyfd >= 0) { /* we used PTMX before forking */ /*0 extern char *ptsname(int);*/ #if HAVE_GRANTPT /* AIX, not Linux */ @@ -146,17 +159,6 @@ static int xioopen_pty( } } #endif /* HAVE_DEV_PTMX || HAVE_DEV_PTC */ -#if HAVE_OPENPTY - if (ptyfd < 0) { - int result; - if ((result = Openpty(&ptyfd, &ttyfd, ptyname, NULL, NULL)) < 0) { - Error4("openpty(%p, %p, %p, NULL, NULL): %s", - &ptyfd, &ttyfd, ptyname, strerror(errno)); - return -1; - } - Notice1("PTY is %s", ptyname); - } -#endif /* HAVE_OPENPTY */ if (!retropt_string(opts, OPT_SYMBOLIC_LINK, &linkname)) { xio_unlink(linkname, E_ERROR); @@ -178,7 +180,7 @@ static int xioopen_pty( applyopts_cloexec(ptyfd, opts);/*!*/ sfd->dtype = XIODATA_PTY; - applyopts(sfd, ptyfd, opts, PH_FD); + applyopts(sfd, ttyfd, opts, PH_FD); { /* special handling of user-late etc.; with standard behaviour (up to diff --git a/xiohelp.c b/xiohelp.c index 4641dbd..9db54c4 100644 --- a/xiohelp.c +++ b/xiohelp.c @@ -225,8 +225,8 @@ int xiohelp_syntax( int isnum, const char *syntax) { - Error4("%s: wrong number of parameters (%d instead of %d): usage: %s", - addr, isnum, expectnum, syntax); + Error5("%s: wrong number of parameters (%d instead of %d): usage: %s%s", + addr, isnum, expectnum, addr, syntax); return -1; }