aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog.old6
-rw-r--r--beam.c114
-rw-r--r--tcp.c28
-rw-r--r--tcp.h3
4 files changed, 111 insertions, 40 deletions
diff --git a/ChangeLog.old b/ChangeLog.old
index db6a835..c704f2c 100644
--- a/ChangeLog.old
+++ b/ChangeLog.old
@@ -1,3 +1,9 @@
+2009-01-06 dain
+
+ * beam.c, tcp.c, tcp.h: Fixed IAC handling inside MPI
+ messages. Still not done properly, but double IACs are converted
+ to one ASCII 255, and message length is correctly computed.
+
2009-01-05 dain
* cmd.c, edit.c, edit.h, powwow.help, utils.c: Added an
diff --git a/beam.c b/beam.c
index fc14b5c..891faac 100644
--- a/beam.c
+++ b/beam.c
@@ -23,6 +23,7 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include <arpa/telnet.h>
#include "defines.h"
#include "main.h"
@@ -56,8 +57,9 @@ static void write_message __P1 (char *,s)
int process_message __P2 (char *,buf, int,len)
{
int msglen, i, l, used;
- char *text;
+ char *text, *from, *to;
char msg[BUFSIZE];
+ int got_iac;
status(1);
@@ -72,52 +74,72 @@ int process_message __P2 (char *,buf, int,len)
}
l = len - ++i;
- if (msglen < l) {
- l = msglen;
- used = msglen + i;
- } else
- used = len;
-
+
text = (char *)malloc(msglen);
if (!text) {
errmsg("malloc");
return used > len ? len : used;
}
-
- memmove(text, buf + i, l);
- i = l;
- while(i < msglen) {
- /*
- * read() might block here, but it should't be long. I should also
- * process any telnet protocol commands, but I don't care right now.
- */
+
+ /* only doing trivial (IAC IAC) processing; this should all be
+ * rewritten */
+ got_iac = 0;
+ from = buf + i;
+ to = text;
+ for (i = 0; i < l && (to - text) < msglen; ++i) {
+ if (got_iac) {
+ if (*from != (char)IAC)
+ errmsg("got IAC in MPI message; treating as IAC IAC");
+ else
+ ++from;
+ got_iac = 0;
+ } else {
+ got_iac = (*to++ = *from++) == (char)IAC;
+ }
+ }
+ i = to - text;
+ used = from - buf;
+
+ while (i < msglen) {
+ /* read() might block here, but it should't be long */
while ((l = read(tcp_fd, text + i, msglen - i)) == -1 && errno == EINTR)
;
if (l == -1) {
errmsg("read message from socket");
return used > len ? len : used;
}
+ from = to = text + i;
+ for (i = 0; i < l; ++i) {
+ if (got_iac) {
+ if (*from != (char)IAC)
+ errmsg("got IAC in MPI message; treating as IAC IAC");
+ else
+ ++from;
+ got_iac = 0;
+ } else {
+ got_iac = (*to++ = *from++) == (char)IAC;
+ }
+ }
+ i = to - text;
tty_printf("\rgot %d chars out of %d", i, msglen);
tty_flush();
- i += l;
}
tty_printf("\rread all %d chars.%s\n", msglen, tty_clreoln);
- if ((msglen = tcp_unIAC(text, msglen)))
- switch(*buf) {
- case 'E':
- message_edit(text, msglen, 0, 0);
- break;
- case 'V':
- message_edit(text, msglen, 1, 0);
- break;
- default:
- sprintf(msg, "#warning: received a funny message (0x%x)\n", *buf);
- write_message(msg);
- free(text);
- break;
- }
-
+ switch(*buf) {
+ case 'E':
+ message_edit(text, msglen, 0, 0);
+ break;
+ case 'V':
+ message_edit(text, msglen, 1, 0);
+ break;
+ default:
+ sprintf(msg, "#warning: received a funny message (0x%x)\n", *buf);
+ write_message(msg);
+ free(text);
+ break;
+ }
+
return used;
}
@@ -167,6 +189,25 @@ void cancel_edit __P1 (editsess *,sp)
sp->cancel = 1;
}
+static ssize_t read_file(int fd, void *buf, size_t count)
+{
+ size_t result = 0;
+ while (count > 0) {
+ int r;
+ do {
+ r = read(fd, buf, count);
+ } while (r < 0 && errno == EINTR);
+ if (r < 0)
+ return -1;
+ if (r == 0)
+ break;
+ result += r;
+ buf += r;
+ count -= r;
+ }
+ return result;
+}
+
/*
* send back edited text to server, or cancel the editing session if the
* file was not changed.
@@ -196,17 +237,18 @@ static void finish_edit __P1 (editsess *,sp)
if (!sp->cancel && (sbuf.st_mtime > sp->ctime || txtlen != sp->oldsize)) {
/* file was changed by editor: send back result to server */
- realtext = (char *)malloc(2*txtlen + 65);
- /* *2 to protect IACs, +1 is for possible LF, +64 for header */
+ realtext = (char *)malloc(txtlen + 65);
+ /* +1 is for possible LF, +64 for header */
if (!realtext) {
errmsg("malloc");
goto cleanup_fd;
}
text = realtext + 64;
- if ((txtlen = tcp_read_addIAC(fd, text, txtlen)) == -1)
+ txtlen = read_file(fd, text, txtlen);
+ if (txtlen < 0)
goto cleanup_text;
-
+
if (txtlen && text[txtlen - 1] != '\n') {
/* If the last line isn't LF-terminated, add an LF;
* however, empty files must remain empty */
@@ -222,7 +264,7 @@ static void finish_edit __P1 (editsess *,sp)
memcpy(text, hdr, hdrlen);
/* text[hdrlen + txtlen] = '\0'; */
- tcp_raw_write(sp->fd, text, hdrlen + txtlen);
+ tcp_write_escape_iac(sp->fd, text, hdrlen + txtlen);
sprintf(buf, "#completed session %s (%u)\n", sp->descr, sp->key);
write_message(buf);
diff --git a/tcp.c b/tcp.c
index fbb5812..f4af987 100644
--- a/tcp.c
+++ b/tcp.c
@@ -538,11 +538,10 @@ int tcp_read __P3 (int,fd, char *,buffer, int,maxsize)
return (char *)p - buffer;
}
-void tcp_raw_write __P3 (int,fd, char *,data, int,len)
+static void internal_tcp_raw_write __P3 (int,fd, const char *,data, int,len)
{
- int i;
- tcp_flush();
while (len > 0) {
+ int i;
while ((i = write(fd, data, len)) < 0 && errno == EINTR)
;
if (i < 0) {
@@ -554,6 +553,29 @@ void tcp_raw_write __P3 (int,fd, char *,data, int,len)
}
}
+void tcp_raw_write __P3 (int,fd, const char *,data, int,len)
+{
+ tcp_flush();
+ internal_tcp_raw_write(fd, data, len);
+}
+
+/* write data, escape any IACs */
+void tcp_write_escape_iac __P3 (int,fd, const char *,data, int,len)
+{
+ tcp_flush();
+
+ for (;;) {
+ const char *iac = memchr(data, IAC, len);
+ size_t l = iac ? (iac - data) + 1 : len;
+ internal_tcp_raw_write(fd, data, l);
+ if (iac == NULL)
+ return;
+ internal_tcp_raw_write(fd, iac, 1);
+ len -= l;
+ data = iac + 1;
+ }
+}
+
/*
* Send current terminal size (RFC 1073)
*/
diff --git a/tcp.h b/tcp.h
index 1813980..56389b9 100644
--- a/tcp.h
+++ b/tcp.h
@@ -59,7 +59,8 @@ extern fd_set fdset; /* set of descriptors to select() on */
int tcp_connect __P ((char *addr, int port));
int tcp_read __P ((int fd, char *buffer, int maxsize));
-void tcp_raw_write __P ((int fd, char *data, int len));
+void tcp_raw_write __P ((int fd, const char *data, int len));
+void tcp_write_escape_iac __P3 (int,fd, const char *,data, int,len);
void tcp_write_tty_size __P ((void));
void tcp_write __P ((int fd, char *data));
void tcp_main_write __P ((char *data));