diff --git a/CHANGES b/CHANGES index b594cbb..f09da57 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,5 @@  +<<<<<<< HEAD Corrections: In error.c msg2() there was a stack overflow on long messages: The terminating \0 Byte was written behind the last position. @@ -63,6 +64,9 @@ Porting: Corrected message format when no strftime() is available; improved handling of very long host or program names + Solaris requires that termios options are always applied to the slave + side of PTY. + Features: Filan prints target of symlink when appropriate Test: FILANSYMLINK diff --git a/sycls.c b/sycls.c index 7ecb447..27db8f0 100644 --- a/sycls.c +++ b/sycls.c @@ -677,7 +677,10 @@ int Ioctl(int d, int request, void *argp) { _errno = errno; if (!diag_in_handler) diag_flush(); #if WITH_SYCLS - Debug1("ioctl() -> %d", retval); + if (retval < 0) + Debug2("ioctl() -> %d, errno=%d", retval, _errno); + else + Debug1("ioctl() -> %d", retval); #endif /* WITH_SYCLS */ errno = _errno; return retval; diff --git a/test.sh b/test.sh index 668f64d..2b80b76 100755 --- a/test.sh +++ b/test.sh @@ -270,8 +270,8 @@ case "$UNAME" in # PTYOPTS2= # ;; SunOS) - PTYOPTS="echo=0,opost=0,perm=600" - PTYOPTS2="cfmakeraw" + PTYOPTS="perm=600" + PTYOPTS2="echo=0,opost=0" ;; *) PTYOPTS="echo=0,opost=0" @@ -2685,7 +2685,7 @@ elif ! testfeats pty >/dev/null; then numCANT=$((numCANT+1)) listCANT="$listCANT $N" else -testecho "$N" "$TEST" "" "exec:$CAT,pty,$PTYOPTS" "$opts" +testecho "$N" "$TEST" "" "exec:$CAT,pty,$PTYOPTS,$PTYOPTS2" "$opts" fi esac N=$((N+1)) @@ -2701,7 +2701,7 @@ elif ! testfeats pty >/dev/null; then numCANT=$((numCANT+1)) listCANT="$listCANT $N" else -testecho "$N" "$TEST" "" "system:$CAT,pty,$PTYOPTS" "$opts" +testecho "$N" "$TEST" "" "system:$CAT,pty,$PTYOPTS,$PTYOPTS2" "$opts" fi esac N=$((N+1)) @@ -10575,7 +10575,7 @@ printf "test $F_n $TEST... " $N eval "$CMD0 2>\"${te}0\" >\"$tf\" &" pid0=$! wait${protov}port $tsa1 1 -echo |$CMD1 2>"${te}1" +{ echo; sleep 0.1; } |$CMD1 2>"${te}1" rc1=$? waitfile "$tf" 2 kill $pid0 2>/dev/null; wait @@ -10689,7 +10689,7 @@ if $SOCAT -hhh |grep "[[:space:]]$SCM_RECV[[:space:]]" >/dev/null; then eval "$CMD0 >\"$tf\" 2>\"${te}0\" &" pid0="$!" wait${proto}port $tra 1 -echo "XYZ" |$CMD1 2>"${te}1" +{ echo "XYZ"; sleep 0.1; } |$CMD1 2>"${te}1" rc1="$?" waitfile "$tf" 2 #i=0; while [ ! -s "${te}0" -a "$i" -lt 10 ]; do usleep 100000; i=$((i+1)); done @@ -11899,7 +11899,7 @@ esac N=$((N+1)) -# PTY address allowed to sepcify address parameters but ignored them +# PTY address allowed to specify address parameters but ignored them NAME=PTY_VOIDARG case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%pty%*|*%$NAME%*) @@ -13748,12 +13748,13 @@ tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" -CMD0="$TRACE $SOCAT $opts -T 1 STDIO,echo=0 EXEC:cat" +CMD0="$TRACE $SOCAT $opts -T 1 STDIO,echo=0 EXEC:cat 2>${te}0" echo "$CMD0" >$td/test$N.sh chmod a+x $td/test$N.sh -printf "test $F_n $TEST... " $N # EXEC need not work with script (musl libc), so use SYSTEM -$SOCAT /dev/null SYSTEM:$td/test$N.sh,pty 2>"${te}0" +CMD1="$TRACE $SOCAT $opts /dev/null SYSTEM:$td/test$N.sh,pty,$PTYOPTS" +printf "test $F_n $TEST... " $N +$CMD1 2>"${te}1" rc0=$? if [ $rc0 -eq 0 ]; then $PRINTF "$OK\n" @@ -13762,6 +13763,8 @@ else $PRINTF "$FAILED\n" echo "$CMD0" cat "${te}0" + echo "$CMD1" + cat "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi @@ -14562,8 +14565,8 @@ if ! kill $pid1 2>"$tk1"; then listCANT="$listCANT $N" else # Second, set accept-timeout and see if socat exits before kill -CMD2="$TRACE $SOCAT $opts TCP-LISTEN:$PORT,reuseaddr,accept-timeout=1 PIPE" >"$te1" & -$CMD2 >"$te1" 2>&1 "$te2" 2>&1 "$tk2"; then diff --git a/xio-progcall.c b/xio-progcall.c index 65cf3b3..206636a 100644 --- a/xio-progcall.c +++ b/xio-progcall.c @@ -8,6 +8,7 @@ #include "xioopen.h" #include "xio-process.h" +#include "xio-named.h" #include "xio-progcall.h" #include "xio-socket.h" @@ -73,6 +74,8 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ bool withstderr = false; bool nofork = false; bool withfork; + char *tn = NULL; + int trigger[2]; popts = moveopts(*copts, GROUP_ALL); if (applyopts_single(fd, popts, PH_INIT) < 0) return -1; @@ -223,19 +226,9 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ /*0 Info2("open(\"%s\", O_RDWR|O_NOCTTY, 0620) -> %d", PTMX, ptyfd);*/ } if (ptyfd >= 0 && ttyfd < 0) { - char *tn = NULL; /* we used PTMX before forking */ extern char *ptsname(int); -#if HAVE_GRANTPT /* AIX, not Linux */ - if (Grantpt(ptyfd)/*!*/ < 0) { - Warn2("grantpt(%d): %s", ptyfd, strerror(errno)); - } -#endif /* HAVE_GRANTPT */ -#if HAVE_UNLOCKPT - if (Unlockpt(ptyfd)/*!*/ < 0) { - Warn2("unlockpt(%d): %s", ptyfd, strerror(errno)); - } -#endif /* HAVE_UNLOCKPT */ + #if HAVE_PROTOTYPE_LIB_ptsname /* AIX, not Linux */ if ((tn = Ptsname(ptyfd)) == NULL) { Warn2("ptsname(%d): %s", ptyfd, strerror(errno)); @@ -247,35 +240,16 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ } } ptyname[0] = '\0'; strncat(ptyname, tn, MAXPTYNAMELEN-1); - if ((ttyfd = Open(tn, O_RDWR|O_NOCTTY, 0620)) < 0) { - Warn2("open(\"%s\", O_RDWR|O_NOCTTY, 0620): %s", tn, strerror(errno)); - } else { - /*0 Info2("open(\"%s\", O_RDWR|O_NOCTTY, 0620) -> %d", tn, ttyfd);*/ +#if HAVE_GRANTPT /* AIX, not Linux */ + if (Grantpt(ptyfd)/*!*/ < 0) { + Warn2("grantpt(%d): %s", ptyfd, strerror(errno)); } - -#ifdef I_PUSH - /* Linux: I_PUSH def'd; pty: ioctl(, I_FIND, ...) -> -1 EINVAL */ - /* AIX: I_PUSH def'd; pty: ioctl(, I_FIND, ...) -> 1 */ - /* SunOS: I_PUSH def'd; pty: ioctl(, I_FIND, ...) -> 0 */ - /* HP-UX: I_PUSH def'd; pty: ioctl(, I_FIND, ...) -> 0 */ - if (Ioctl(ttyfd, I_FIND, "ldterm\0") == 0) { - Ioctl(ttyfd, I_PUSH, "ptem\0\0\0"); /* 0 */ /* padding for AdressSanitizer */ - Ioctl(ttyfd, I_PUSH, "ldterm\0"); /* 0 */ - Ioctl(ttyfd, I_PUSH, "ttcompat"); /* HP-UX: -1 */ +#endif /* HAVE_GRANTPT */ +#if HAVE_UNLOCKPT + if (Unlockpt(ptyfd)/*!*/ < 0) { + Warn2("unlockpt(%d): %s", ptyfd, strerror(errno)); } -#endif - -#if 0 /* the following block need not work */ - - if (ttyfd >= 0 && ((tn = Ttyname(ttyfd)) == NULL)) { - Warn2("ttyname(%d): %s", ttyfd, strerror(errno)); - } - if (tn == NULL) { - Error("could not open pty"); - return -1; - } -#endif - Info1("opened pseudo terminal %s", tn); +#endif /* HAVE_UNLOCKPT */ } } #endif /* HAVE_DEV_PTMX || HAVE_DEV_PTC */ @@ -290,7 +264,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ } #endif /* HAVE_OPENPTY */ free(*copts); - if ((*copts = moveopts(popts, GROUP_TERMIOS|GROUP_FORK|GROUP_EXEC|GROUP_PROCESS)) == NULL) { + if ((*copts = moveopts(popts, GROUP_TERMIOS|GROUP_FORK|GROUP_EXEC|GROUP_PROCESS|GROUP_NAMED)) == NULL) { return -1; } applyopts_cloexec(ptyfd, popts);/*!*/ @@ -306,8 +280,6 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ fd->fd = ptyfd; - /* this for child, was after fork */ - applyopts(ttyfd, *copts, PH_FD); } else #endif /* HAVE_PTY */ if (usepipes) { @@ -411,6 +383,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ xiosetchilddied(); /* set SIGCHLD handler */ if (withfork) { + Socketpair(PF_UNIX, SOCK_STREAM, 0, trigger); pid = xio_fork(true, E_ERROR); if (pid < 0) { return -1; @@ -422,10 +395,43 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ /* In particular, it's not defined whether ignoring SIGCHLD is inheritable. */ if (Signal(SIGCHLD, SIG_DFL) == SIG_ERR) { Warn1("signal(SIGCHLD, SIG_DFL): %s", strerror(errno)); + Close(trigger[0]); } #if HAVE_PTY if (usepty) { + applyopts_named(tn, *copts, PH_PREOPEN); + applyopts_named(tn, *copts, PH_EARLY); + applyopts_named(tn, *copts, PH_FD); + + if (ttyfd < 0) { + if ((ttyfd = Open(tn, O_RDWR|O_NOCTTY, 0620)) < 0) { + Warn2("open(\"%s\", O_RDWR|O_NOCTTY, 0620): %s", tn, strerror(errno)); + } else { + /*0 Info2("open(\"%s\", O_RDWR|O_NOCTTY, 0620) -> %d", tn, ttyfd);*/ + } + } else { + if ((tn = Ttyname(ttyfd)) == NULL) { + Warn2("ttyname(%d): %s", ttyfd, strerror(errno)); + } + } + +#ifdef I_PUSH + /* Linux: I_PUSH def'd; pty: ioctl(, I_FIND, ...) -> -1 EINVAL */ + /* AIX: I_PUSH def'd; pty: ioctl(, I_FIND, ...) -> 1 */ + /* SunOS: I_PUSH def'd; pty: ioctl(, I_FIND, ...) -> 0 */ + /* HP-UX: I_PUSH def'd; pty: ioctl(, I_FIND, ...) -> 0 */ + if (Ioctl(ttyfd, I_FIND, "ldterm\0") == 0) { + Ioctl(ttyfd, I_PUSH, "ptem\0\0\0"); /* 0 */ /* padding for AdressSanitizer */ + Ioctl(ttyfd, I_PUSH, "ldterm\0"); /* 0 */ + Ioctl(ttyfd, I_PUSH, "ttcompat"); /* HP-UX: -1 */ + } +#endif + + /* this for child, was after fork */ + applyopts(ttyfd, *copts, PH_FD); + + Info1("opened pseudo terminal %s", tn); Close(ptyfd); if (rw != XIO_RDONLY && fdi != ttyfd) { /* make sure that the internal diagnostic socket pair fds do not conflict @@ -451,7 +457,6 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ } applyopts(ttyfd, *copts, PH_LATE); - applyopts(ttyfd, *copts, PH_LATE2); } else #endif /* HAVE_PTY */ @@ -539,6 +544,10 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ applyopts(fdi, *copts, PH_LATE); applyopts(fdi, *copts, PH_LATE2); } + if (withfork) { + Info("Signalling parent ready"); + Close(trigger[1]); + } } /* withfork */ else { applyopts(-1, *copts, PH_LATE); @@ -556,6 +565,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ /* for parent (this is our socat process) */ Notice1("forked off child process "F_pid, pid); + Close(trigger[1]); #if 0 if ((popts = copyopts(*copts, @@ -565,9 +575,11 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ #if HAVE_PTY if (usepty) { +# if 0 if (Close(ttyfd) < 0) { Info2("close(%d): %s", ttyfd, strerror(errno)); } +# endif } else #endif /* HAVE_PTY */ if (usepipes) { @@ -586,6 +598,14 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ return STAT_NORETRY; } + { + struct pollfd fds[1]; + fds[0].fd = trigger[0]; + fds[0].events = POLLIN|POLLHUP; + Poll(fds, 1, -1); + Info("Child process signalled ready"); + } + return pid; /* indicate parent (main) process */ } #endif /* WITH_EXEC || WITH_SYSTEM */