summaryrefslogtreecommitdiffstats
path: root/mbbsd
diff options
context:
space:
mode:
authorin2 <in2@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2005-04-08 10:27:19 +0800
committerin2 <in2@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2005-04-08 10:27:19 +0800
commit0666dd02983c5a7ad580a29d7d6deec1cbcd80b5 (patch)
tree4ad1a26d8b3bbad4afc2a8396cbd7b8651a40b73 /mbbsd
parenta0296382b6836538ae15de74b4adf96b54e8d9ad (diff)
downloadpttbbs-0666dd02983c5a7ad580a29d7d6deec1cbcd80b5.tar
pttbbs-0666dd02983c5a7ad580a29d7d6deec1cbcd80b5.tar.gz
pttbbs-0666dd02983c5a7ad580a29d7d6deec1cbcd80b5.tar.bz2
pttbbs-0666dd02983c5a7ad580a29d7d6deec1cbcd80b5.tar.lz
pttbbs-0666dd02983c5a7ad580a29d7d6deec1cbcd80b5.tar.xz
pttbbs-0666dd02983c5a7ad580a29d7d6deec1cbcd80b5.tar.zst
pttbbs-0666dd02983c5a7ad580a29d7d6deec1cbcd80b5.zip
handle telnet protocol and enable NAWS (resize terminal) capability.
SKIP_TELNET_CONTROL_SIGNAL can be disabled now. by piaip git-svn-id: http://opensvn.csie.org/pttbbs/trunk/pttbbs@2690 63ad8ddf-47c3-0310-b6dd-a9e9d9715204
Diffstat (limited to 'mbbsd')
-rw-r--r--mbbsd/io.c112
-rw-r--r--mbbsd/mbbsd.c16
-rw-r--r--mbbsd/term.c28
-rw-r--r--mbbsd/var.c1
4 files changed, 116 insertions, 41 deletions
diff --git a/mbbsd/io.c b/mbbsd/io.c
index fde21d3b..acbbe6f8 100644
--- a/mbbsd/io.c
+++ b/mbbsd/io.c
@@ -4,7 +4,7 @@
#define OBUFSIZE 2048
#define IBUFSIZE 128
-static char outbuf[OBUFSIZE], inbuf[IBUFSIZE];
+static unsigned char outbuf[OBUFSIZE], inbuf[IBUFSIZE];
static int obufsize = 0, ibufsize = 0;
static int icurrchar = 0;
@@ -187,7 +187,7 @@ dogetch(void)
}
#ifdef SKIP_TELNET_CONTROL_SIGNAL
- } while( inbuf[0] == -1 );
+ } while( inbuf[0] == IAC );
#endif
ibufsize = len;
icurrchar = 0;
@@ -204,38 +204,114 @@ dogetch(void)
currutmp->lastact = now;
lastact = now;
}
- return inbuf[icurrchar++];
+ return (unsigned char)inbuf[icurrchar++];
}
+enum IAC_STATE {
+ IAC_NONE,
+ IAC_WAIT1,
+ IAC_WAIT_NAWS,
+ IAC_WAIT_NAWS_IAC,
+ IAC_WAIT_IAC_SE_1,
+ IAC_WAIT_IAC_SE_2,
+ IAC_ERROR
+};
+
static int water_which_flag = 0;
int
igetch(void)
{
- register int ch, mode = 0, last = 0;
- while ((ch = dogetch())) {
+ register int ch, mode = 0, last = 0;
+ static int iac_state = IAC_NONE;
+ static unsigned char nawsbuf[4], inaws = 0;
+ while ((ch = dogetch()) >= 0) {
+ if(raw_connection) /* only process IAC in raw connection mode */
+ switch (iac_state) {
+ case IAC_NONE:
+ if(ch == IAC) {
+ iac_state = IAC_WAIT1;
+ continue;
+ }
+ break;
+ case IAC_WAIT1:
+ if(ch == SB)
+ iac_state = IAC_WAIT_IAC_SE_1;
+ else
+ iac_state = IAC_NONE;
+ if(ch == AYT) {
+ redoscr();
+ outmsg("我還活著喔");
+ }
+ continue;
+ case IAC_WAIT_IAC_SE_1:
+ if(ch == IAC)
+ iac_state = IAC_WAIT_IAC_SE_2;
+ if(ch == TELOPT_NAWS) {
+ iac_state = IAC_WAIT_NAWS;
+ inaws = 0;
+ }
+ continue;
+ case IAC_WAIT_IAC_SE_2:
+ if(ch == SE) {
+ iac_state = IAC_NONE;
+ continue;
+ }
+ else
+ iac_state = IAC_WAIT_IAC_SE_1;
+ continue;
+ case IAC_WAIT_NAWS_IAC:
+ // when we're waiting for NAWS and an IAC comes, orz
+ iac_state = IAC_WAIT_NAWS;
+ if (ch == IAC)
+ nawsbuf[inaws-1] = IAC;
+ // else? i don't know how to handle sich situation
+ // there shall not be any other cases
+ continue;
+ case IAC_WAIT_NAWS:
+ nawsbuf[inaws++] = (unsigned char)ch;
+ if(ch == IAC) {
+ iac_state = IAC_WAIT_NAWS_IAC;
+ continue;
+ }
+ if(inaws == 4) {
+ int w = (nawsbuf[0] << 8) + nawsbuf[1];
+ int h = (nawsbuf[2] << 8) + nawsbuf[3];
+ iac_state = IAC_WAIT_IAC_SE_1;
+ term_resize(w, h); /* term_resize is safe */
+ /* redoscr(); */ /* will not work as we want */
+#ifdef DEBUG
+ {
+ char buf[256];
+ sprintf(buf, "[%dx%d]", w, h);
+ outmsg(buf);
+ }
+#endif
+ iac_state = IAC_WAIT_IAC_SE_1;
+ }
+ continue;
+ } else if (ch == 0) /* in non-raw connection mode, ignore zero. */
+ return 0;
+
if (mode == 0 && ch == KEY_ESC) // here is state machine for 2 bytes key
- mode = 1;
+ mode = 1;
else if (mode == 1) { /* Escape sequence */
if (ch == '[' || ch == 'O')
mode = 2;
else if (ch == '1' || ch == '4')
- { mode = 3; last = ch; }
- else
- {
+ { mode = 3; last = ch; }
+ else {
KEY_ESC_arg = ch;
return KEY_ESC;
- }
+ }
} else if (mode == 2 && ch >= 'A' && ch <= 'D') /* Cursor key */
- return KEY_UP + (ch - 'A');
- else if (mode == 2 && ch >= '1' && ch <= '6')
- { mode = 3; last = ch; }
- else if (mode == 3 && ch == '~') { /* Ins Del Home End PgUp PgDn */
- return KEY_HOME + (last - '1');
+ return KEY_UP + (ch - 'A');
+ else if (mode == 2 && ch >= '1' && ch <= '6')
+ { mode = 3; last = ch; }
+ else if (mode == 3 && ch == '~') { /* Ins Del Home End PgUp PgDn */
+ return KEY_HOME + (last - '1');
}
else // here is switch for default keys
- switch (ch) {
- case IAC:
- continue;
+ switch (ch) { // XXX: indent error
#ifdef DEBUG
case Ctrl('Q'):{
struct rusage ru;
diff --git a/mbbsd/mbbsd.c b/mbbsd/mbbsd.c
index 41b77e43..e54c0139 100644
--- a/mbbsd/mbbsd.c
+++ b/mbbsd/mbbsd.c
@@ -1139,6 +1139,8 @@ telnet_init(void)
struct timeval to;
unsigned char buf[64];
fd_set ReadSet, r;
+
+ raw_connection = 1;
FD_ZERO(&ReadSet);
FD_SET(0, &ReadSet);
@@ -1168,18 +1170,8 @@ telnet_init(void)
bi += 3;
w = GETB() << 8; w |= GETB();
h = GETB() << 8; h |= GETB();
- /* safer
- // suggested by kcwu, a pity that we can't handle < 24. */
- h = MAX(24, MIN(100, h));
- w = MAX(80, MIN(200, w));
- if(buf[bi++] == IAC && buf[bi++] == SE) {
- /* copied from term.c */
- t_lines = h;
- t_columns = w;
- scr_lns = t_lines;
- b_lines = t_lines - 1;
- p_lines = t_lines - 4;
- }
+ if(buf[bi++] == IAC && buf[bi++] == SE)
+ term_resize(w, h);
}
}
}
diff --git a/mbbsd/term.c b/mbbsd/term.c
index 94067e99..782d07b8 100644
--- a/mbbsd/term.c
+++ b/mbbsd/term.c
@@ -30,21 +30,27 @@ init_tty(void)
#define TERMCOMSIZE (40)
static void
-term_resize(int sig)
+sig_term_resize(int sig)
{
struct winsize newsize;
+ Signal(SIGWINCH, SIG_IGN); /* Don't bother me! */
+ ioctl(0, TIOCGWINSZ, &newsize);
+ term_resize(newsize.ws_col, newsize.ws_row);
+}
+
+void term_resize(int w, int h)
+{
screenline_t *new_picture;
Signal(SIGWINCH, SIG_IGN); /* Don't bother me! */
- ioctl(0, TIOCGWINSZ, &newsize);
/* make sure reasonable size */
- newsize.ws_row = MAX(24, MIN(100, newsize.ws_row));
- newsize.ws_col = MAX(80, MIN(200, newsize.ws_col));
+ h = MAX(24, MIN(100, h));
+ w = MAX(80, MIN(200, w));
- if (newsize.ws_row > t_lines) {
- new_picture = (screenline_t *) calloc(newsize.ws_row,
- sizeof(screenline_t));
+ if (h > t_lines && big_picture) {
+ new_picture = (screenline_t *)
+ calloc(h, sizeof(screenline_t));
if (new_picture == NULL) {
syslog(LOG_ERR, "calloc(): %m");
return;
@@ -53,19 +59,19 @@ term_resize(int sig)
free(big_picture);
big_picture = new_picture;
}
- t_lines = newsize.ws_row;
- t_columns = newsize.ws_col;
+ t_lines = h;
+ t_columns = w;
scr_lns = t_lines; /* XXX: scr_lns 跟 t_lines 有什麼不同, 為何分成兩個 */
b_lines = t_lines - 1;
p_lines = t_lines - 4;
- Signal(SIGWINCH, term_resize);
+ Signal(SIGWINCH, sig_term_resize);
}
int
term_init(void)
{
- Signal(SIGWINCH, term_resize);
+ Signal(SIGWINCH, sig_term_resize);
return YEA;
}
diff --git a/mbbsd/var.c b/mbbsd/var.c
index 2d256aac..ee290bd3 100644
--- a/mbbsd/var.c
+++ b/mbbsd/var.c
@@ -375,6 +375,7 @@ char real_name[IDLEN + 1];
char local_article;
/* mbbsd.c */
+int raw_connection = 0;
char fromhost[STRLEN] = "\0";
char water_usies = 0;
FILE *fp_writelog = NULL;