Fixed PTYs on Solaris

This commit is contained in:
Gerhard Rieger 2022-10-29 22:32:14 +02:00
parent e0c669028d
commit 6340127060
4 changed files with 85 additions and 55 deletions

View file

@ -1,4 +1,5 @@
 
<<<<<<< HEAD
Corrections: Corrections:
In error.c msg2() there was a stack overflow on long messages: The In error.c msg2() there was a stack overflow on long messages: The
terminating \0 Byte was written behind the last position. terminating \0 Byte was written behind the last position.
@ -63,6 +64,9 @@ Porting:
Corrected message format when no strftime() is available; improved Corrected message format when no strftime() is available; improved
handling of very long host or program names handling of very long host or program names
Solaris requires that termios options are always applied to the slave
side of PTY.
Features: Features:
Filan prints target of symlink when appropriate Filan prints target of symlink when appropriate
Test: FILANSYMLINK Test: FILANSYMLINK

View file

@ -677,7 +677,10 @@ int Ioctl(int d, int request, void *argp) {
_errno = errno; _errno = errno;
if (!diag_in_handler) diag_flush(); if (!diag_in_handler) diag_flush();
#if WITH_SYCLS #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 */ #endif /* WITH_SYCLS */
errno = _errno; errno = _errno;
return retval; return retval;

27
test.sh
View file

@ -270,8 +270,8 @@ case "$UNAME" in
# PTYOPTS2= # PTYOPTS2=
# ;; # ;;
SunOS) SunOS)
PTYOPTS="echo=0,opost=0,perm=600" PTYOPTS="perm=600"
PTYOPTS2="cfmakeraw" PTYOPTS2="echo=0,opost=0"
;; ;;
*) *)
PTYOPTS="echo=0,opost=0" PTYOPTS="echo=0,opost=0"
@ -2685,7 +2685,7 @@ elif ! testfeats pty >/dev/null; then
numCANT=$((numCANT+1)) numCANT=$((numCANT+1))
listCANT="$listCANT $N" listCANT="$listCANT $N"
else else
testecho "$N" "$TEST" "" "exec:$CAT,pty,$PTYOPTS" "$opts" testecho "$N" "$TEST" "" "exec:$CAT,pty,$PTYOPTS,$PTYOPTS2" "$opts"
fi fi
esac esac
N=$((N+1)) N=$((N+1))
@ -2701,7 +2701,7 @@ elif ! testfeats pty >/dev/null; then
numCANT=$((numCANT+1)) numCANT=$((numCANT+1))
listCANT="$listCANT $N" listCANT="$listCANT $N"
else else
testecho "$N" "$TEST" "" "system:$CAT,pty,$PTYOPTS" "$opts" testecho "$N" "$TEST" "" "system:$CAT,pty,$PTYOPTS,$PTYOPTS2" "$opts"
fi fi
esac esac
N=$((N+1)) N=$((N+1))
@ -10575,7 +10575,7 @@ printf "test $F_n $TEST... " $N
eval "$CMD0 2>\"${te}0\" >\"$tf\" &" eval "$CMD0 2>\"${te}0\" >\"$tf\" &"
pid0=$! pid0=$!
wait${protov}port $tsa1 1 wait${protov}port $tsa1 1
echo |$CMD1 2>"${te}1" { echo; sleep 0.1; } |$CMD1 2>"${te}1"
rc1=$? rc1=$?
waitfile "$tf" 2 waitfile "$tf" 2
kill $pid0 2>/dev/null; wait 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\" &" eval "$CMD0 >\"$tf\" 2>\"${te}0\" &"
pid0="$!" pid0="$!"
wait${proto}port $tra 1 wait${proto}port $tra 1
echo "XYZ" |$CMD1 2>"${te}1" { echo "XYZ"; sleep 0.1; } |$CMD1 2>"${te}1"
rc1="$?" rc1="$?"
waitfile "$tf" 2 waitfile "$tf" 2
#i=0; while [ ! -s "${te}0" -a "$i" -lt 10 ]; do usleep 100000; i=$((i+1)); done #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)) 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 NAME=PTY_VOIDARG
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%bugs%*|*%pty%*|*%$NAME%*) *%$N%*|*%functions%*|*%bugs%*|*%pty%*|*%$NAME%*)
@ -13748,12 +13748,13 @@ tf="$td/test$N.stdout"
te="$td/test$N.stderr" te="$td/test$N.stderr"
tdiff="$td/test$N.diff" tdiff="$td/test$N.diff"
da="test$N $(date) $RANDOM" 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 echo "$CMD0" >$td/test$N.sh
chmod a+x $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 # 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=$? rc0=$?
if [ $rc0 -eq 0 ]; then if [ $rc0 -eq 0 ]; then
$PRINTF "$OK\n" $PRINTF "$OK\n"
@ -13762,6 +13763,8 @@ else
$PRINTF "$FAILED\n" $PRINTF "$FAILED\n"
echo "$CMD0" echo "$CMD0"
cat "${te}0" cat "${te}0"
echo "$CMD1"
cat "${te}1"
numFAIL=$((numFAIL+1)) numFAIL=$((numFAIL+1))
listFAIL="$listFAIL $N" listFAIL="$listFAIL $N"
fi fi
@ -14562,8 +14565,8 @@ if ! kill $pid1 2>"$tk1"; then
listCANT="$listCANT $N" listCANT="$listCANT $N"
else else
# Second, set accept-timeout and see if socat exits before kill # 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="$TRACE $SOCAT $opts TCP-LISTEN:$PORT,reuseaddr,accept-timeout=1 PIPE" &
$CMD2 >"$te1" 2>&1 </dev/null & $CMD2 >"$te2" 2>&1 </dev/null &
pid2=$! pid2=$!
sleep 1 sleep 1
if kill $pid2 2>"$tk2"; then if kill $pid2 2>"$tk2"; then

View file

@ -8,6 +8,7 @@
#include "xioopen.h" #include "xioopen.h"
#include "xio-process.h" #include "xio-process.h"
#include "xio-named.h"
#include "xio-progcall.h" #include "xio-progcall.h"
#include "xio-socket.h" #include "xio-socket.h"
@ -73,6 +74,8 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
bool withstderr = false; bool withstderr = false;
bool nofork = false; bool nofork = false;
bool withfork; bool withfork;
char *tn = NULL;
int trigger[2];
popts = moveopts(*copts, GROUP_ALL); popts = moveopts(*copts, GROUP_ALL);
if (applyopts_single(fd, popts, PH_INIT) < 0) return -1; 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);*/ /*0 Info2("open(\"%s\", O_RDWR|O_NOCTTY, 0620) -> %d", PTMX, ptyfd);*/
} }
if (ptyfd >= 0 && ttyfd < 0) { if (ptyfd >= 0 && ttyfd < 0) {
char *tn = NULL;
/* we used PTMX before forking */ /* we used PTMX before forking */
extern char *ptsname(int); 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 HAVE_PROTOTYPE_LIB_ptsname /* AIX, not Linux */
if ((tn = Ptsname(ptyfd)) == NULL) { if ((tn = Ptsname(ptyfd)) == NULL) {
Warn2("ptsname(%d): %s", ptyfd, strerror(errno)); 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); ptyname[0] = '\0'; strncat(ptyname, tn, MAXPTYNAMELEN-1);
if ((ttyfd = Open(tn, O_RDWR|O_NOCTTY, 0620)) < 0) { #if HAVE_GRANTPT /* AIX, not Linux */
Warn2("open(\"%s\", O_RDWR|O_NOCTTY, 0620): %s", tn, strerror(errno)); if (Grantpt(ptyfd)/*!*/ < 0) {
} else { Warn2("grantpt(%d): %s", ptyfd, strerror(errno));
/*0 Info2("open(\"%s\", O_RDWR|O_NOCTTY, 0620) -> %d", tn, ttyfd);*/
} }
#endif /* HAVE_GRANTPT */
#ifdef I_PUSH #if HAVE_UNLOCKPT
/* Linux: I_PUSH def'd; pty: ioctl(, I_FIND, ...) -> -1 EINVAL */ if (Unlockpt(ptyfd)/*!*/ < 0) {
/* AIX: I_PUSH def'd; pty: ioctl(, I_FIND, ...) -> 1 */ Warn2("unlockpt(%d): %s", ptyfd, strerror(errno));
/* 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 #endif /* HAVE_UNLOCKPT */
#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_DEV_PTMX || HAVE_DEV_PTC */ #endif /* HAVE_DEV_PTMX || HAVE_DEV_PTC */
@ -290,7 +264,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
} }
#endif /* HAVE_OPENPTY */ #endif /* HAVE_OPENPTY */
free(*copts); 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; return -1;
} }
applyopts_cloexec(ptyfd, popts);/*!*/ applyopts_cloexec(ptyfd, popts);/*!*/
@ -306,8 +280,6 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
fd->fd = ptyfd; fd->fd = ptyfd;
/* this for child, was after fork */
applyopts(ttyfd, *copts, PH_FD);
} else } else
#endif /* HAVE_PTY */ #endif /* HAVE_PTY */
if (usepipes) { if (usepipes) {
@ -411,6 +383,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
xiosetchilddied(); /* set SIGCHLD handler */ xiosetchilddied(); /* set SIGCHLD handler */
if (withfork) { if (withfork) {
Socketpair(PF_UNIX, SOCK_STREAM, 0, trigger);
pid = xio_fork(true, E_ERROR); pid = xio_fork(true, E_ERROR);
if (pid < 0) { if (pid < 0) {
return -1; 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. */ /* In particular, it's not defined whether ignoring SIGCHLD is inheritable. */
if (Signal(SIGCHLD, SIG_DFL) == SIG_ERR) { if (Signal(SIGCHLD, SIG_DFL) == SIG_ERR) {
Warn1("signal(SIGCHLD, SIG_DFL): %s", strerror(errno)); Warn1("signal(SIGCHLD, SIG_DFL): %s", strerror(errno));
Close(trigger[0]);
} }
#if HAVE_PTY #if HAVE_PTY
if (usepty) { 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); Close(ptyfd);
if (rw != XIO_RDONLY && fdi != ttyfd) { if (rw != XIO_RDONLY && fdi != ttyfd) {
/* make sure that the internal diagnostic socket pair fds do not conflict /* 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_LATE);
applyopts(ttyfd, *copts, PH_LATE2); applyopts(ttyfd, *copts, PH_LATE2);
} else } else
#endif /* HAVE_PTY */ #endif /* HAVE_PTY */
@ -539,6 +544,10 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
applyopts(fdi, *copts, PH_LATE); applyopts(fdi, *copts, PH_LATE);
applyopts(fdi, *copts, PH_LATE2); applyopts(fdi, *copts, PH_LATE2);
} }
if (withfork) {
Info("Signalling parent ready");
Close(trigger[1]);
}
} /* withfork */ } /* withfork */
else { else {
applyopts(-1, *copts, PH_LATE); applyopts(-1, *copts, PH_LATE);
@ -556,6 +565,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
/* for parent (this is our socat process) */ /* for parent (this is our socat process) */
Notice1("forked off child process "F_pid, pid); Notice1("forked off child process "F_pid, pid);
Close(trigger[1]);
#if 0 #if 0
if ((popts = copyopts(*copts, if ((popts = copyopts(*copts,
@ -565,9 +575,11 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
#if HAVE_PTY #if HAVE_PTY
if (usepty) { if (usepty) {
# if 0
if (Close(ttyfd) < 0) { if (Close(ttyfd) < 0) {
Info2("close(%d): %s", ttyfd, strerror(errno)); Info2("close(%d): %s", ttyfd, strerror(errno));
} }
# endif
} else } else
#endif /* HAVE_PTY */ #endif /* HAVE_PTY */
if (usepipes) { if (usepipes) {
@ -586,6 +598,14 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
return STAT_NORETRY; 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 */ return pid; /* indicate parent (main) process */
} }
#endif /* WITH_EXEC || WITH_SYSTEM */ #endif /* WITH_EXEC || WITH_SYSTEM */