mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 15:32:35 +00:00
Fixed PTYs on Solaris
This commit is contained in:
parent
e0c669028d
commit
6340127060
4 changed files with 85 additions and 55 deletions
4
CHANGES
4
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
|
||||
|
|
5
sycls.c
5
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;
|
||||
|
|
27
test.sh
27
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 </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
|
||||
|
|
104
xio-progcall.c
104
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 */
|
||||
|
|
Loading…
Reference in a new issue