summaryrefslogtreecommitdiffstats
path: root/mbbsd
diff options
context:
space:
mode:
authorkcwu <kcwu@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2009-06-07 01:55:53 +0800
committerkcwu <kcwu@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2009-06-07 01:55:53 +0800
commita810729f9c6413f0b0fd61643f9ce5d3c2553d6d (patch)
tree32e0e79f8fe4053e7d0089ea793f6e566f693319 /mbbsd
parentca8b35a1b996ba8cdecb9b231a112fc6509bcd98 (diff)
downloadpttbbs-a810729f9c6413f0b0fd61643f9ce5d3c2553d6d.tar
pttbbs-a810729f9c6413f0b0fd61643f9ce5d3c2553d6d.tar.gz
pttbbs-a810729f9c6413f0b0fd61643f9ce5d3c2553d6d.tar.bz2
pttbbs-a810729f9c6413f0b0fd61643f9ce5d3c2553d6d.tar.lz
pttbbs-a810729f9c6413f0b0fd61643f9ce5d3c2553d6d.tar.xz
pttbbs-a810729f9c6413f0b0fd61643f9ce5d3c2553d6d.tar.zst
pttbbs-a810729f9c6413f0b0fd61643f9ce5d3c2553d6d.zip
- extract telnet.c to cmsys
git-svn-id: http://opensvn.csie.org/pttbbs/trunk/pttbbs@4505 63ad8ddf-47c3-0310-b6dd-a9e9d9715204
Diffstat (limited to 'mbbsd')
-rw-r--r--mbbsd/mbbsd.c1
-rw-r--r--mbbsd/telnet.c332
-rw-r--r--mbbsd/var.c1
3 files changed, 30 insertions, 304 deletions
diff --git a/mbbsd/mbbsd.c b/mbbsd/mbbsd.c
index fd2fd73f..f7fc9dd5 100644
--- a/mbbsd/mbbsd.c
+++ b/mbbsd/mbbsd.c
@@ -705,6 +705,7 @@ login_query(void)
outs("½Ð­«·s¿é¤J¡C\n");
continue;
}
+ telnet_turnoff_client_detect();
#ifdef CONVERT
/* switch to gb mode if uid end with '.' */
diff --git a/mbbsd/telnet.c b/mbbsd/telnet.c
index 332b3f3a..45f000a7 100644
--- a/mbbsd/telnet.c
+++ b/mbbsd/telnet.c
@@ -1,68 +1,37 @@
-/*
- * piaip's simplified implementation of TELNET protocol
- */
-#ifdef DEBUG
-#define TELOPTS
-#define TELCMDS
-#endif
-
#include "bbs.h"
+static TelnetCtx telnet_ctx;
+static char raw_connection = 0;
+
#ifdef DETECT_CLIENT
-void UpdateClientCode(unsigned char c); // see mbbsd.c
-#endif
+extern void UpdateClientCode(unsigned char c);
-unsigned int telnet_handler(unsigned char c) ;
-void telnet_init(void);
-ssize_t tty_read(unsigned char *buf, size_t max);
+void telnet_cb_update_client_code(void *ccctx, unsigned char c)
+{
+ UpdateClientCode(c);
+}
+#endif
-enum TELNET_IAC_STATES {
- IAC_NONE,
- IAC_COMMAND,
- IAC_WAIT_OPT,
- IAC_WAIT_SE,
- IAC_PROCESS_OPT,
- IAC_ERROR
+const static struct TelnetCallback telnet_callback = {
+ term_resize,
+#ifdef DETECT_CLIENT
+ telnet_cb_update_client_code,
+#else
+ NULL,
+#endif
};
-static unsigned char iac_state = 0; /* as byte to reduce memory */
-
-#define TELNET_IAC_MAXLEN (16)
-/* We don't reply to most commands, so this maxlen can be minimal.
- * Warning: if you want to support ENV passing or other long commands,
- * remember to increase this value. Howver, some poorly implemented
- * terminals like xxMan may not follow the protocols and user will hang
- * on those terminals when IACs were sent.
- */
-
void
telnet_init(void)
{
- /* We are the boss. We don't respect to client.
- * It's client's responsibility to follow us.
- * Please write these codes in i-dont-care opt handlers.
- */
- const char telnet_init_cmds[] = {
- /* retrieve terminal type and throw away.
- * why? because without this, clients enter line mode.
- */
- IAC, DO, TELOPT_TTYPE,
- IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE,
-
- /* i'm a smart term with resize ability. */
- IAC, DO, TELOPT_NAWS,
-
- /* i will echo. */
- IAC, WILL, TELOPT_ECHO,
- /* supress ga. */
- IAC, WILL, TELOPT_SGA,
- /* 8 bit binary. */
- IAC, WILL, TELOPT_BINARY,
- IAC, DO, TELOPT_BINARY,
- };
-
+ int fd = 0;
+ TelnetCtx *ctx = &telnet_ctx;
raw_connection = 1;
- write(0, telnet_init_cmds, sizeof(telnet_init_cmds));
+ telnet_ctx_init(ctx, &telnet_callback, fd);
+#ifdef DETECT_CLIENT
+ telnet_ctx_set_ccctx(ctx, (void*)1);
+#endif
+ telnet_send_init_cmds(fd);
}
/* tty_read
@@ -73,6 +42,7 @@ ssize_t
tty_read(unsigned char *buf, size_t max)
{
ssize_t l = read(0, buf, max);
+ TelnetCtx *ctx = &telnet_ctx;
if(l == 0 || (l < 0 && !(errno == EINTR || errno == EAGAIN)))
abort_bbs(0);
@@ -80,259 +50,15 @@ tty_read(unsigned char *buf, size_t max)
if(!raw_connection)
return l;
- /* process buffer */
- if (l > 0) {
- unsigned char *buf2 = buf;
- size_t i = 0, i2 = 0;
-
- /* prescan. because IAC is rare,
- * this cost is worthy. */
- if (iac_state == IAC_NONE && memchr(buf, IAC, l) == NULL)
- return l;
-
- /* we have to look into the buffer. */
- for (i = 0; i < l; i++, buf++)
- if(telnet_handler(*buf) == 0)
- *(buf2++) = *buf;
- else
- i2 ++;
- l = (i2 == l) ? -1L : l - i2;
- }
+ l = telnet_process(ctx, buf, l);
return l;
}
-#ifdef DBG_OUTRPT
-extern unsigned char fakeEscape;
-#endif // DBG_OUTRPT
-
-/* input: raw character
- * output: telnet command if c was handled, otherwise zero.
- */
-unsigned int
-telnet_handler(unsigned char c)
+void
+telnet_turnoff_client_detect(void)
{
- static unsigned char iac_quote = 0; /* as byte to reduce memory */
- static unsigned char iac_opt_req = 0;
-
- static unsigned char iac_buf[TELNET_IAC_MAXLEN];
- static unsigned int iac_buflen = 0;
-
- /* we have to quote all IACs. */
- if(c == IAC && !iac_quote) {
- iac_quote = 1;
- return NOP;
- }
-
-#ifdef DETECT_CLIENT
- /* hash client telnet sequences */
- if(cuser.userid[0]==0) {
- if(iac_state == IAC_WAIT_SE) {
- // skip suboption
- } else {
- if(iac_quote)
- UpdateClientCode(IAC);
- UpdateClientCode(c);
- }
- }
-#endif
-
- /* a special case is the top level iac. otherwise, iac is just a quote. */
- if (iac_quote) {
- if(iac_state == IAC_NONE)
- iac_state = IAC_COMMAND;
- if(iac_state == IAC_WAIT_SE && c == SE)
- iac_state = IAC_PROCESS_OPT;
- iac_quote = 0;
- }
-
- /* now, let's process commands by state */
- switch(iac_state) {
-
- case IAC_NONE:
- return 0;
-
- case IAC_COMMAND:
-#if 0 // def DEBUG
- {
- int cx = c; /* to make compiler happy */
- write(0, "-", 1);
- if(TELCMD_OK(cx))
- write(0, TELCMD(c), strlen(TELCMD(c)));
- write(0, " ", 1);
- }
-#endif
- iac_state = IAC_NONE; /* by default we restore state. */
- switch(c) {
- case IAC:
- // return 0;
- // we don't want to allow IACs as input.
- return 1;
-
- /* we don't want to process these. or maybe in future. */
- case BREAK: /* break */
-#ifdef DBG_OUTRPT
- fakeEscape = !fakeEscape;
- return NOP;
-#endif
-
- case ABORT: /* Abort process */
- case SUSP: /* Suspend process */
- case AO: /* abort output--but let prog finish */
- case IP: /* interrupt process--permanently */
- case EOR: /* end of record (transparent mode) */
- case DM: /* data mark--for connect. cleaning */
- case xEOF: /* End of file: EOF is already used... */
- return NOP;
-
- case NOP: /* nop */
- return NOP;
-
- /* we should process these, but maybe in future. */
- case GA: /* you may reverse the line */
- case EL: /* erase the current line */
- case EC: /* erase the current character */
- return NOP;
-
- /* good */
- case AYT: /* are you there */
- {
- const char *alive = "I'm still alive, loading: ";
- char buf[STRLEN];
-
- /* respond as fast as we can */
- write(0, alive, strlen(alive));
- cpuload(buf);
- write(0, buf, strlen(buf));
- write(0, "\r\n", 2);
- }
- return NOP;
-
- case DONT: /* you are not to use option */
- case DO: /* please, you use option */
- case WONT: /* I won't use option */
- case WILL: /* I will use option */
- iac_opt_req = c;
- iac_state = IAC_WAIT_OPT;
- return NOP;
-
- case SB: /* interpret as subnegotiation */
- iac_state = IAC_WAIT_SE;
- iac_buflen = 0;
- return NOP;
-
- case SE: /* end sub negotiation */
- default:
- return NOP;
- }
- return 1;
-
- case IAC_WAIT_OPT:
-#if 0 // def DEBUG
- write(0, "-", 1);
- if(TELOPT_OK(c))
- write(0, TELOPT(c), strlen(TELOPT(c)));
- write(0, " ", 1);
-#endif
- iac_state = IAC_NONE;
- /*
- * According to RFC, there're some tricky steps to prevent loop.
- * However because we have a poor term which does not allow
- * most abilities, let's be a strong boss here.
- *
- * Although my old imeplementation worked, it's even better to follow this:
- * http://www.tcpipguide.com/free/t_TelnetOptionsandOptionNegotiation-3.htm
- */
- switch(c) {
- /* i-dont-care: i don't care about what client is.
- * these should be clamed in init and
- * client must follow me. */
- case TELOPT_TTYPE: /* termtype or line. */
- case TELOPT_NAWS: /* resize terminal */
- case TELOPT_SGA: /* supress GA */
- case TELOPT_ECHO: /* echo */
- case TELOPT_BINARY: /* we are CJK. */
- break;
-
- /* i-dont-agree: i don't understand/agree these.
- * according to RFC, saying NO stopped further
- * requests so there'll not be endless loop. */
- case TELOPT_RCP: /* prepare to reconnect */
- default:
- if (iac_opt_req == WILL || iac_opt_req == DO)
- {
- /* unknown option, reply with won't */
- unsigned char cmd[3] = { IAC, DONT, 0 };
- if(iac_opt_req == DO) cmd[1] = WONT;
- cmd[2] = c;
- write(0, cmd, sizeof(cmd));
- }
- break;
- }
- return 1;
-
- case IAC_WAIT_SE:
- iac_buf[iac_buflen++] = c;
- /* no need to convert state because previous quoting will do. */
-
- if(iac_buflen == TELNET_IAC_MAXLEN) {
- /* may be broken protocol?
- * whether finished or not, break for safety
- * or user may be frozen.
- */
- iac_state = IAC_NONE;
- return 0;
- }
- return 1;
-
- case IAC_PROCESS_OPT:
- iac_state = IAC_NONE;
-#if 0 // def DEBUG
- write(0, "-", 1);
- if(TELOPT_OK(iac_buf[0]))
- write(0, TELOPT(iac_buf[0]), strlen(TELOPT(iac_buf[0])));
- write(0, " ", 1);
-#endif
- switch(iac_buf[0]) {
-
- /* resize terminal */
- case TELOPT_NAWS:
- {
- int w = (iac_buf[1] << 8) + (iac_buf[2]);
- int h = (iac_buf[3] << 8) + (iac_buf[4]);
- term_resize(w, h);
-#ifdef DETECT_CLIENT
- if(cuser.userid[0]==0) {
- UpdateClientCode(iac_buf[0]);
- if(w==80 && h==24)
- UpdateClientCode(1);
- else if(w==80)
- UpdateClientCode(2);
- else if(h==24)
- UpdateClientCode(3);
- else
- UpdateClientCode(4);
- UpdateClientCode(IAC);
- UpdateClientCode(SE);
- }
-#endif
- }
- break;
-
- default:
-#ifdef DETECT_CLIENT
- if(cuser.userid[0]==0) {
- int i;
- for(i=0;i<iac_buflen;i++)
- UpdateClientCode(iac_buf[i]);
- UpdateClientCode(IAC);
- UpdateClientCode(SE);
- }
-#endif
- break;
- }
- return 1;
- }
- return 1; /* never reached */
+ TelnetCtx *ctx = &telnet_ctx;
+ telnet_ctx_set_ccctx(ctx, NULL);
}
// vim: sw=4
diff --git a/mbbsd/var.c b/mbbsd/var.c
index 7bfc785a..f2e402d2 100644
--- a/mbbsd/var.c
+++ b/mbbsd/var.c
@@ -374,7 +374,6 @@ char real_name[IDLEN + 1];
char local_article;
/* mbbsd.c */
-char raw_connection = 0;
char fromhost[STRLEN] = "\0";
char fromhost_masked[32] = "\0"; // masked 'fromhost'
char water_usies = 0;