Skip to content

Commit

Permalink
Merge pull request #5 from hackerschoice/ptyresize
Browse files Browse the repository at this point in the history
ptyresize
  • Loading branch information
SkyperTHC authored Oct 30, 2020
2 parents 593eeae + b0c119c commit e594652
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 23 deletions.
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ(2.61)
AC_INIT([gsocket], 1.4.20)
AC_INIT([gsocket], 1.4.21)
dnl AC_CONFIG_AUX_DIR(config-x86_64-apple-darwin19.6.0)
AC_CONFIG_AUX_DIR(config)
AC_CANONICAL_SYSTEM
Expand Down
2 changes: 1 addition & 1 deletion tools/4_gs-netcat.c
Original file line number Diff line number Diff line change
Expand Up @@ -666,7 +666,7 @@ cb_connect_client(GS_SELECT_CTX *ctx, int fd_notused, void *arg, int val)
DEBUGF_M("Setting tty\n");
XASSERT(p->fd_in == STDIN_FILENO, "p->fd_in = %d, not STDIN\n", p->fd_in);
stty_set_raw();
stty_set_remote_size(ctx, p);
// stty_set_remote_size(ctx, p);
}

return GS_SUCCESS;
Expand Down
25 changes: 9 additions & 16 deletions tools/run_all_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -466,11 +466,9 @@ fi
if [[ "$tests" =~ '7.3' ]]; then
test_start -n "Running: netcat #7.3 (pty shell, exit)...................."
GSPID1="$(sh -c './gs-netcat -k id_sec.txt -l -i 2>server_err.txt >server_out.dat & echo ${!}')"
if [[ "$OSTYPE" == *"BSD"* ]]; then
(sleep 3; echo "date; echo Hello World; exit") | ./gs-netcat -k id_sec.txt -w 2>client_err.txt >client_out.dat
else
(echo "date; echo Hello World; exit") | ./gs-netcat -k id_sec.txt -w 2>client_err.txt >client_out.dat
fi
PTYSIM='\033[25;80R'
# Can not start Client with -i because it's not a tty. Must 'fake' the terminal response.
(printf "${PTYSIM}date; echo Hello World; exit\n") | ./gs-netcat -k id_sec.txt -w 2>client_err.txt >client_out.dat
sleep_ct
kill $GSPID1
tail -2 client_out.dat | grep 'Hello World' &>/dev/null
Expand All @@ -481,20 +479,15 @@ fi
if [[ "$tests" =~ '7.4' ]]; then
test_start -n "Running: netcat #7.4 (multi pty shell, exit).............."
GSPID1="$(sh -c './gs-netcat -k id_sec.txt -l -i 2>server_err.txt >server_out.dat & echo ${!}')"
if [[ "$OSTYPE" == *"BSD"* ]]; then
GSPID2="$(sh -c '(sleep 3; echo "date && echo Hello World && exit") | ./gs-netcat -k id_sec.txt -iw 2>client1_err.txt >client1_out.dat & echo ${!}')"
GSPID3="$(sh -c '(sleep 3; echo "date && echo Hello World && exit") | ./gs-netcat -k id_sec.txt -iw 2>client2_err.txt >client2_out.dat & echo ${!}')"
GSPID4="$(sh -c '(sleep 3; echo "date && echo Hello World && exit") | ./gs-netcat -k id_sec.txt -iw 2>client3_err.txt >client3_out.dat & echo ${!}')"
else
GSPID2="$(sh -c '(echo "date && echo Hello World && exit") | ./gs-netcat -k id_sec.txt -iw 2>client1_err.txt >client1_out.dat & echo ${!}')"
GSPID3="$(sh -c '(echo "date && echo Hello World && exit") | ./gs-netcat -k id_sec.txt -iw 2>client2_err.txt >client2_out.dat & echo ${!}')"
GSPID4="$(sh -c '(echo "date && echo Hello World && exit") | ./gs-netcat -k id_sec.txt -iw 2>client3_err.txt >client3_out.dat & echo ${!}')"
fi
PTYSIM='\033[25;80R'
GSPID2=$(sh -c "(printf \"${PTYSIM} date && echo Hello World && exit\n\") | ./gs-netcat -k id_sec.txt -w 2>client1_err.txt >client1_out.dat & echo \${!}")
GSPID3=$(sh -c "(printf \"${PTYSIM} date && echo Hello World && exit\n\") | ./gs-netcat -k id_sec.txt -w 2>client2_err.txt >client2_out.dat & echo \${!}")
GSPID4=$(sh -c "(printf \"${PTYSIM} date && echo Hello World && exit\n\") | ./gs-netcat -k id_sec.txt -w 2>client3_err.txt >client3_out.dat & echo \${!}")
waitk $GSPID2 $GSPID3 $GSPID4
kill $GSPID1
if [ x"$(tail -2 client1_out.dat | grep 'Hello World')" == x ]; then fail 1; fi
if [ x"$(tail -2 client2_out.dat | grep 'Hello World')" == x ]; then fail 1; fi
if [ x"$(tail -2 client3_out.dat | grep 'Hello World')" == x ]; then fail 1; fi
if [ x"$(tail -2 client2_out.dat | grep 'Hello World')" == x ]; then fail 2; fi
if [ x"$(tail -2 client3_out.dat | grep 'Hello World')" == x ]; then fail 3; fi
$ECHO "${OK}"
fi

Expand Down
155 changes: 150 additions & 5 deletions tools/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ init_vars(void)
void
usage(const char *params)
{
fprintf(stderr, "%s [0x%lxL]\n", OPENSSL_VERSION_TEXT, OPENSSL_VERSION_NUMBER);
fprintf(stderr, "%s [0x%lxL] (GS v%s)\n", OPENSSL_VERSION_TEXT, OPENSSL_VERSION_NUMBER, PACKAGE_VERSION);

while (*params)
{
Expand Down Expand Up @@ -479,6 +479,134 @@ setup_cmd_child(void)
signal(SIGPIPE, SIG_DFL);
}

#define ESCAPE(string) "\033" string
#define PTY_RESIZE_STR ESCAPE("7") ESCAPE("[r") ESCAPE("[9999;9999H") ESCAPE("[6n")
#define PTY_RESTORE ESCAPE("8")
#define PTY_SIZE_STR ESCAPE("[%d;%dR")
#define UIntClr(dst,bits) dst = dst & (unsigned) ~(bits)
static int tty;
static struct termios tioorig;
static int onintr_called;

static void
onintr(int sig)
{
if (onintr_called)
return;

onintr_called = 1;
(void) tcsetattr(tty, TCSADRAIN, &tioorig);
}

static void
resize_timeout(int sig)
{
onintr(sig);
}

static int
readstring(int fd, char *buf, size_t sz, const char *str)
{
unsigned char last;
unsigned char c;
int n;
int rv = -1;
char *end = buf + sz;

signal(SIGALRM, resize_timeout);
alarm(10);
n = read(fd, &c, 1);
if (n <= 0)
goto err;

if (c == 0233)
{ /* meta-escape, CSI */
*buf++ = ESCAPE("")[0];
*buf++ = '[';
} else {
*buf++ = (char) c;
}
if (c != *str)
goto err;

last = str[strlen(str) - 1]; // R
while (1)
{
n = read(fd, &c, 1);
if (n <= 0)
goto err;
*buf++ = c;
if (c == last)
break;
if (buf >= end)
goto err;
}

alarm(0);
*buf = 0;
rv = 0;
err:
if (rv != 0)
{
signal(SIGALRM, SIG_DFL);
alarm(0); // CANCEL alarm
}
return rv;
}


static void
pty_resize(int fd)
{
int rv = -1;
struct termios tio;
int rows;
int cols;
char buf[64];
struct winsize ws;


tty = fd;
rv = tcgetattr(tty, &tioorig);
if (rv != 0)
return;
tio = tioorig;

/* FIXME: set signal here */

UIntClr(tio.c_iflag, ICRNL);
UIntClr(tio.c_lflag, (ICANON | ECHO));
tio.c_cflag |= CS8;
tio.c_cc[VMIN] = 6;
tio.c_cc[VTIME] = 1;
rv = tcsetattr(tty, TCSADRAIN, &tio);
if (rv != 0)
{
goto err;
}

rv = write(fd, PTY_RESIZE_STR PTY_RESTORE, strlen(PTY_RESIZE_STR) + strlen(PTY_RESTORE));
rv = readstring(tty, buf, sizeof buf, PTY_SIZE_STR);
if (rv != 0)
goto err;
if (sscanf(buf, PTY_SIZE_STR, &rows, &cols) != 2)
goto err;

memset(&ws, 0, sizeof ws);
ws.ws_col = cols;
ws.ws_row = rows;

ioctl(fd, TIOCSWINSZ, &ws);
onintr(0);
// fprintf(stderr, "rows %d, cols %d\n", rows, cols);
rv = 0;
err:
if (rv != 0)
{
}
/* reset terminal values. cleanup */
onintr(0);
}

#ifndef HAVE_OPENPTY
static int
Expand Down Expand Up @@ -522,12 +650,13 @@ openpty(int *amaster, int *aslave, void *a, void *b, void *c)

#ifndef HAVE_FORKPTY
static int
forkpty(int *master, void *a, void *b, void *c)
forkpty(int *fd, void *a, void *b, void *c)
{
pid_t pid;
int slave;
int master;

if (openpty(master, &slave, NULL, NULL, NULL) == -1)
if (openpty(&master, &slave, NULL, NULL, NULL) == -1)
return -1;

pid = fork();
Expand All @@ -541,14 +670,16 @@ forkpty(int *master, void *a, void *b, void *c)
ioctl(slave, TIOCNOTTY, NULL);
#endif
setsid();
close(*master);
close(master);
dup2(slave, 0);
dup2(slave, 1);
dup2(slave, 2);
*fd = slave;
return 0; // CHILD
default:
/* PARENT */
close(slave);
*fd = master;
return pid;
}

Expand All @@ -563,10 +694,24 @@ pty_cmd(const char *cmdUNUSED)
int fd;

pid = forkpty(&fd, NULL, NULL, NULL);
XASSERT(pid >= 0, "Error: fork(): %s\n", strerror(errno));
XASSERT(pid >= 0, "Error: forkpty(): %s\n", strerror(errno));

if (pid == 0)
{
/* Our own forkpty() (solaris 10) returns the actual slave TTY.
* We can not open /dev/tty on solaris10 and use the fd that
* our own forkpty() returns. Any other OS needs to open
* /dev/tty to get correct fd for child's tty.
*/
#ifdef HAVE_FORKPTY
fd = open("/dev/tty", O_NOCTTY | O_RDWR);
#endif
if (fd >= 0)
{
pty_resize(fd);
close(fd);
}

/* HERE: Child */
setup_cmd_child();

Expand Down

0 comments on commit e594652

Please sign in to comment.