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

View file

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

27
test.sh
View file

@ -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 </dev/null &
CMD2="$TRACE $SOCAT $opts TCP-LISTEN:$PORT,reuseaddr,accept-timeout=1 PIPE" &
$CMD2 >"$te2" 2>&1 </dev/null &
pid2=$!
sleep 1
if kill $pid2 2>"$tk2"; then

View file

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