char *name;
int rem = -1; /* Remote socket fd */
+int do_inband = 0;
char cmdchar = '~';
int eight = 1; /* Default to 8 bit transmission */
int no_local_escape = 0;
reached from confirm_death() */
krb5_sigtype sigwinch KRB5_PROTOTYPE((int));
+int server_message KRB5_PROTOTYPE((int));
void oob KRB5_PROTOTYPE((void));
krb5_sigtype lostpeer KRB5_PROTOTYPE((int));
#if __STDC__
int rcvstate;
int ppid;
+/* returns 1 if flush, 0 otherwise */
-void oob()
+int server_message(mark)
+ int mark;
{
#ifndef POSIX_TERMIOS
int out = FWRITE;
#endif
- int atmark, n;
+ int n;
int rcvd = 0;
- char waste[RLOGIN_BUFSIZ], mark;
#ifdef POSIX_TERMIOS
struct termios tty;
#else
struct sgttyb sb;
#endif
#endif
- mark = 0;
-
- recv(rem, &mark, 1, MSG_OOB);
-
if (mark & TIOCPKT_WINDOW) {
/*
(void) ioctl(1, TCFLSH, 1);
#endif
#endif
- for (;;) {
- if (ioctl(rem, SIOCATMARK, &atmark) < 0) {
- perror("ioctl");
- break;
- }
- if (atmark)
- break;
- n = read(rem, waste, sizeof (waste));
- printf("tossed %d bytes\n", n);
- if (n <= 0)
- break;
-return;
- }
+ return(1);
}
+
+ return(0);
+}
+
+void oob()
+{
+ char mark;
+ char waste[RLOGIN_BUFSIZ];
+ int atmark;
+
+ mark = 0;
-
+ recv(rem, &mark, 1, MSG_OOB);
+
+ if (server_message(mark)) {
+ if (ioctl(rem, SIOCATMARK, &atmark) < 0) {
+ perror("ioctl");
+ return;
+ }
+ if (!atmark)
+ read(rem, waste, sizeof (waste));
+ }
}
+/* two control messages are defined:
+
+ a double flag byte of 'o' indicates a one-byte message which is
+ identical to what was once carried out of band.
+
+ a double flag byte of 'q' indicates a zero-byte message. This
+ message is interpreted as two \377 data bytes. This is just a
+ quote rule so that binary data from the server does not confuse the
+ client. */
+int control(cp, n)
+ unsigned char *cp;
+ int n;
+{
+ if ((n >= 5) && (cp[2] == 'o') && (cp[3] == 'o')) {
+ if (server_message(cp[4]))
+ return(-5);
+ return(5);
+ } else if ((n >= 4) && (cp[2] == 'q') && (cp[3] == 'q')) {
+ /* this is somewhat of a hack */
+ cp[2] = '\377';
+ cp[3] = '\377';
+ return(2);
+ }
+
+ return(0);
+}
/*
- * reader: read from remote: line -> 1
+ * reader: read from remote: line -> 1
*/
reader(oldmask)
#ifdef POSIX_SIGNALS
int pid = -getpid();
#endif
fd_set readset, excset, writeset;
- int n, remaining;
+ int n, remaining, left;
char *bufp = rcvbuf;
+ char *cp;
#ifdef POSIX_SIGNALS
struct sigaction sa;
#endif /* POSIX_SIGNALS */
for (;;) {
- if ((remaining = rcvcnt - (bufp - rcvbuf)) > 0)
- {
+ if ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) {
FD_SET(1,&writeset);
rcvstate = WRITING;
FD_CLR(rem, &readset);
+ } else {
+ bufp = rcvbuf;
+ rcvcnt = 0;
+ rcvstate = READING;
+ FD_SET(rem,&readset);
+ FD_CLR(1,&writeset);
}
- else {
-
- bufp = rcvbuf;
- rcvcnt = 0;
- rcvstate = READING;
- FD_SET(rem,&readset);
- FD_CLR(1,&writeset);
- }
- FD_SET(rem,&excset);
+ if (!do_inband)
+ FD_SET(rem,&excset);
if (select(rem+1, &readset, &writeset, &excset, 0) > 0 ) {
- if (FD_ISSET(rem, &excset))
- oob();
+ if (!do_inband)
+ if (FD_ISSET(rem, &excset))
+ oob();
if (FD_ISSET(1,&writeset)) {
n = write(1, bufp, remaining);
if (n < 0) {
bufp += n;
}
if (FD_ISSET(rem, &readset)) {
- {
- int x;
-
- if (!ioctl(rem, FIONREAD, &x));
-
- }
-
rcvcnt = rcmd_stream_read(rem, rcvbuf, sizeof (rcvbuf));
if (rcvcnt == 0)
return (0);
if (rcvcnt < 0)
goto error;
+
+ if (do_inband) {
+ for (cp = rcvbuf; cp < rcvbuf+rcvcnt-1; cp++) {
+ if (cp[0] == '\377' &&
+ cp[1] == '\377') {
+ left = (rcvbuf+rcvcnt) - cp;
+ n = control(cp, left);
+ if (n < 0) {
+ left -= (-n);
+ rcvcnt = 0;
+ /* flush before, and (-n) bytes */
+ if (left > 0)
+ memmove(rcvbuf, cp+(-n), left);
+ cp = rcvbuf-1;
+ } else if (n) {
+ left -= n;
+ rcvcnt -= n;
+ if (left > 0)
+ memmove(cp, cp+n, left);
+ cp--;
+ }
+ }
+ }
+ }
}
} else
error:
char term[64];
char rhost_name[128];
krb5_principal client;
+int do_inband = 0;
int reapchild();
char *progname;
char oobdata[] = {0};
#endif
+int sendoob(fd, byte)
+ int fd;
+ char *byte;
+{
+ char message[5];
+ int cc;
+
+ if (do_inband) {
+ message[0] = '\377';
+ message[1] = '\377';
+ message[2] = 'o';
+ message[3] = 'o';
+ message[4] = *byte;
+
+ cc = rcmd_stream_write(fd, message, sizeof(message));
+ while (cc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
+ /* also shouldn't happen */
+ sleep(5);
+ cc = rcmd_stream_write(fd, message, sizeof(message));
+ }
+ } else {
+ send(fd, byte, 1, MSG_OOB);
+ }
+}
+
/*
* Handle a "control" request (signaled by magic being present)
* in the data stream. For now, we are only willing to handle
void protocol(f, p)
int f, p;
{
- unsigned char pibuf[BUFSIZ], fibuf[BUFSIZ], *pbp, *fbp;
+ unsigned char pibuf[BUFSIZ], qpibuf[BUFSIZ*2], fibuf[BUFSIZ], *pbp, *fbp;
register pcc = 0, fcc = 0;
int cc;
char cntl;
signal(SIGTTOU, SIG_IGN);
#endif
#ifdef TIOCSWINSZ
- send(f, oobdata, 1, MSG_OOB); /* indicate new rlogin */
+ sendoob(f, oobdata);
#endif
for (;;) {
fd_set ibits, obits, ebits;
FD_SET(f, &obits);
else
FD_SET(p, &ibits);
- FD_SET(p, &ebits);
if (select(8*sizeof(ibits), &ibits, &obits, &ebits, 0) < 0) {
if (errno == EINTR)
fatalperror(f, "select");
}
#define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))
- if (FD_ISSET(p, &ebits)) {
- cc = read(p, &cntl, 1);
- if (cc == 1 && pkcontrol(cntl)) {
- cntl |= oobdata[0];
- send(f, &cntl, 1, MSG_OOB);
- if (cntl & TIOCPKT_FLUSHWRITE) {
- pcc = 0;
- FD_CLR(p, &ibits);
- }
- }
- }
if (FD_ISSET(f, &ibits)) {
fcc = rcmd_stream_read(f, fibuf, sizeof (fibuf));
- if (fcc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN)))
- fcc = 0;
- else {
+ if (fcc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
+ fcc = 0;
+ } else {
register unsigned char *cp;
int left, n;
if (fcc <= 0)
- break;
+ break;
fbp = fibuf;
- top:
- for (cp = fibuf; cp < fibuf+fcc-1; cp++)
- if (cp[0] == magic[0] &&
- cp[1] == magic[1]) {
- left = fcc - (cp-fibuf);
- n = control(p, cp, left);
- if (n) {
- left -= n;
- if (left > 0)
- memmove(cp, cp+n, left);
- fcc -= n;
- goto top; /* n^2 */
- }
- }
+ for (cp = fibuf; cp < fibuf+fcc-1; cp++) {
+ if (cp[0] == magic[0] &&
+ cp[1] == magic[1]) {
+ left = (fibuf+fcc) - cp;
+ n = control(p, cp, left);
+ if (n) {
+ left -= n;
+ fcc -= n;
+ if (left > 0)
+ memmove(cp, cp+n, left);
+ cp--;
+ }
+ }
+ }
}
}
if (FD_ISSET(p, &ibits)) {
pcc = read(p, pibuf, sizeof (pibuf));
pbp = pibuf;
- if (pcc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN)))
- pcc = 0;
- else if (pcc <= 0)
- break;
+ if (pcc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
+ pcc = 0;
+ } else if (pcc <= 0) {
+ break;
+ }
#ifdef TIOCPKT
else if (tiocpkt_on) {
- if (pibuf[0] == 0)
- pbp++, pcc--;
- else {
- if (pkcontrol(pibuf[0])) {
- pibuf[0] |= oobdata[0];
- send(f, &pibuf[0], 1, MSG_OOB);
- }
- pcc = 0;
- }
+ if (pibuf[0] == 0) {
+ pbp++, pcc--;
+ } else {
+ if (pkcontrol(pibuf[0])) {
+ pibuf[0] |= oobdata[0];
+ sendoob(f, pibuf);
+ }
+ pcc = 0;
+ }
}
#endif
+
+ /* quote any double-\377's if necessary */
+
+ if (do_inband) {
+ unsigned char *qpbp;
+ int qpcc, i;
+
+ qpbp = qpibuf;
+ qpcc = 0;
+
+ for (i=0; i<pcc;) {
+ if (pbp[i] == 0377u && (i+1)<pcc && pbp[i+1] == 0377u) {
+ qpbp[qpcc] = '\377';
+ qpbp[qpcc+1] = '\377';
+ qpbp[qpcc+2] = 'q';
+ qpbp[qpcc+3] = 'q';
+ i += 2;
+ qpcc += 4;
+ } else {
+ qpbp[qpcc] = pbp[i];
+ i++;
+ qpcc++;
+ }
+ }
+
+ pbp = qpbp;
+ pcc = qpcc;
+ }
}
+
if (FD_ISSET(f, &obits) && pcc > 0) {
cc = rcmd_stream_write(f, pbp, pcc);
if (cc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {