Commits (3)
......@@ -78,6 +78,7 @@ typedef struct {
uint32_t options;
int listen_backlog;
int log_level;
int lowest_log_level; // highest severity from JS
uint32_t stack_size;
js_startup_t js;
js_server_props_t js_server_props;
......@@ -306,8 +307,12 @@ js_log(JSContext *cx, uintN argc, jsval *arglist)
rc=JS_SUSPENDREQUEST(cx);
if(service==NULL)
lprintf(level,"%04d %s",client->socket,str);
else if(level <= client->service->log_level)
lprintf(level,"%04d %s %s",client->socket,client->service->protocol,str);
else {
if(level < client->service->lowest_log_level)
level = client->service->lowest_log_level;
if(level <= client->service->log_level)
lprintf(level,"%04d %s %s",client->socket,client->service->protocol,str);
}
JS_RESUMEREQUEST(cx, rc);
JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(JS_NewStringCopyZ(cx, str)));
......@@ -1603,6 +1608,7 @@ static service_t* read_services_ini(const char* services_ini, service_t* service
serv.stack_size=(uint32_t)iniGetBytes(list,sec_list[i],"StackSize",1,stack_size);
serv.options=iniGetBitField(list,sec_list[i],"Options",service_options,options);
serv.log_level=iniGetLogLevel(list,sec_list[i],"LogLevel",log_level);
serv.lowest_log_level=iniGetLogLevel(list,sec_list[i],"LowestLogLevel",0);
SAFECOPY(serv.cmd,iniGetString(list,sec_list[i],"Command","",cmd));
p=iniGetString(list,sec_list[i],"Port",serv.protocol,portstr);
......
......@@ -2224,6 +2224,7 @@ struct bbslist *show_bbslist(char *current, int connected)
"Commands:\n\n"
"~ CTRL-E ~ to edit the selected entry\n"
"~ CTRL-S ~ to modify the sort order\n"
"~ TAB ~ to modify the selected entry comment or SyncTERM Settings\n"
"~ ENTER ~ to connect to the selected entry";
else {
uifc.helpbuf= "`SyncTERM Directory`\n\n"
......@@ -2232,6 +2233,7 @@ struct bbslist *show_bbslist(char *current, int connected)
"~ CTRL-E ~ to edit the selected entry\n"
"~ CTRL-S ~ to modify the sort order\n"
"~ " ALT_KEY_NAMEP "-B ~ View scrollback of last session\n"
"~ TAB ~ to modify the selected entry comment or SyncTERM Settings\n"
"~ ENTER ~ to connect to the selected entry\n\n"
"`Conio Keys` (may not work in some modes)\n\n"
"~ " ALT_KEY_NAMEP "-Left ~ Snap window size to next smaller horizontal size\n"
......
......@@ -220,7 +220,6 @@ char* connect_result(struct modem* modem)
char* connected(struct modem* modem)
{
ZERO_VAR(telnet);
modem->online = true;
modem->ringing = false;
ResetEvent(hungup_event);
......@@ -269,6 +268,164 @@ int address_family()
return PF_UNSPEC;
}
int putcom(char* buf, size_t len)
{
return send(sock, buf, len, /* flags: */0);
}
static void send_telnet_cmd(uchar cmd, uchar opt)
{
char buf[16];
if(cmd<TELNET_WILL) {
dprintf("TELNET TX: %s"
,telnet_cmd_desc(cmd));
sprintf(buf,"%c%c",TELNET_IAC,cmd);
putcom(buf,2);
} else {
dprintf("TELNET TX: %s %s"
,telnet_cmd_desc(cmd), telnet_opt_desc(opt));
sprintf(buf,"%c%c%c",TELNET_IAC,cmd,opt);
putcom(buf,3);
}
}
void request_telnet_opt(uchar cmd, uchar opt)
{
if(cmd==TELNET_DO || cmd==TELNET_DONT) { /* remote option */
if(telnet.remote_option[opt]==telnet_opt_ack(cmd))
return; /* already set in this mode, do nothing */
telnet.remote_option[opt]=telnet_opt_ack(cmd);
} else { /* local option */
if(telnet.local_option[opt]==telnet_opt_ack(cmd))
return; /* already set in this mode, do nothing */
telnet.local_option[opt]=telnet_opt_ack(cmd);
}
send_telnet_cmd(cmd,opt);
}
BYTE* telnet_interpret(BYTE* inbuf, size_t inlen, BYTE* outbuf, size_t *outlen)
{
BYTE command;
BYTE option;
BYTE* first_cr=NULL;
BYTE* first_int=NULL;
size_t i;
if(inlen<1) {
*outlen=0;
return(inbuf); /* no length? No interpretation */
}
first_int=(BYTE*)memchr(inbuf, TELNET_IAC, inlen);
if(telnet.remote_option[TELNET_BINARY_TX]!=TELNET_WILL) {
first_cr=(BYTE*)memchr(inbuf, '\r', inlen);
if(first_cr) {
if(first_int==NULL || first_cr < first_int)
first_int=first_cr;
}
}
if(telnet.cmdlen==0 && first_int==NULL) {
*outlen=inlen;
return(inbuf); /* no interpretation needed */
}
if(telnet.cmdlen==0 /* If we haven't returned and telnet.cmdlen==0 then first_int is not NULL */ ) {
*outlen=first_int-inbuf;
memcpy(outbuf, inbuf, *outlen);
} else
*outlen=0;
for(i=*outlen;i<inlen;i++) {
if(telnet.remote_option[TELNET_BINARY_TX]!=TELNET_WILL) {
if(telnet.cmdlen==1 && telnet.cmd[0]=='\r') {
outbuf[(*outlen)++]='\r';
if(inbuf[i]!=0 && inbuf[i]!=TELNET_IAC)
outbuf[(*outlen)++]=inbuf[i];
telnet.cmdlen=0;
if(inbuf[i]!=TELNET_IAC)
continue;
}
if(inbuf[i]=='\r' && telnet.cmdlen==0) {
telnet.cmd[telnet.cmdlen++]='\r';
continue;
}
}
if(inbuf[i]==TELNET_IAC && telnet.cmdlen==1) { /* escaped 255 */
telnet.cmdlen=0;
outbuf[(*outlen)++]=TELNET_IAC;
continue;
}
if(inbuf[i]==TELNET_IAC || telnet.cmdlen) {
if(telnet.cmdlen<sizeof(telnet.cmd))
telnet.cmd[telnet.cmdlen++]=inbuf[i];
command = telnet.cmd[1];
option = telnet.cmd[2];
if(telnet.cmdlen>=2 && command==TELNET_SB) {
if(inbuf[i]==TELNET_SE
&& telnet.cmd[telnet.cmdlen-2]==TELNET_IAC) {
telnet.cmdlen=0;
}
}
else if(telnet.cmdlen==2 && inbuf[i]<TELNET_WILL) {
telnet.cmdlen=0;
}
else if(telnet.cmdlen>=3) { /* telnet option negotiation */
dprintf("TELNET RX: %s %s"
,telnet_cmd_desc(command),telnet_opt_desc(option));
if(command==TELNET_DO || command==TELNET_DONT) { /* local options */
if(telnet.local_option[option]!=command) {
switch(option) {
case TELNET_BINARY_TX:
case TELNET_ECHO:
case TELNET_TERM_TYPE:
case TELNET_SUP_GA:
case TELNET_NEGOTIATE_WINDOW_SIZE:
telnet.local_option[option]=command;
send_telnet_cmd(telnet_opt_ack(command),option);
break;
default: /* unsupported local options */
if(command==TELNET_DO) /* NAK */
send_telnet_cmd(telnet_opt_nak(command),option);
break;
}
}
} else { /* WILL/WONT (remote options) */
if(telnet.remote_option[option]!=command) {
switch(option) {
case TELNET_BINARY_TX:
case TELNET_ECHO:
case TELNET_TERM_TYPE:
case TELNET_SUP_GA:
case TELNET_NEGOTIATE_WINDOW_SIZE:
telnet.remote_option[option]=command;
send_telnet_cmd(telnet_opt_ack(command),option);
break;
default: /* unsupported remote options */
if(command==TELNET_WILL) /* NAK */
send_telnet_cmd(telnet_opt_nak(command),option);
break;
}
}
}
telnet.cmdlen=0;
}
} else
outbuf[(*outlen)++]=inbuf[i];
}
return(outbuf);
}
// Significant portions copies from syncterm/conn.c
char* dial(struct modem* modem, const char* number)
{
......@@ -386,6 +543,7 @@ connected:
dprintf("%s %d connected!", __FILE__, __LINE__);
int keepalives = TRUE;
setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void*)&keepalives, sizeof(keepalives));
ZERO_VAR(telnet);
return connected(modem);
}
......@@ -409,6 +567,14 @@ char* answer(struct modem* modem)
}
char tmp[256];
dprintf("Connection accepted from TCP port %hu at %s", inet_addrport(&addr), inet_addrtop(&addr, tmp, sizeof(tmp)));
if(mode == TELNET) {
ZERO_VAR(telnet);
/* Disable Telnet Terminal Echo */
request_telnet_opt(TELNET_WILL,TELNET_ECHO);
/* Will suppress Go Ahead */
request_telnet_opt(TELNET_WILL,TELNET_SUP_GA);
}
return connected(modem);
}
......@@ -650,164 +816,6 @@ void listen_thread(void* arg)
}
}
int putcom(char* buf, size_t len)
{
return send(sock, buf, len, /* flags: */0);
}
static void send_telnet_cmd(uchar cmd, uchar opt)
{
char buf[16];
if(cmd<TELNET_WILL) {
dprintf("TELNET TX: %s"
,telnet_cmd_desc(cmd));
sprintf(buf,"%c%c",TELNET_IAC,cmd);
putcom(buf,2);
} else {
dprintf("TELNET TX: %s %s"
,telnet_cmd_desc(cmd), telnet_opt_desc(opt));
sprintf(buf,"%c%c%c",TELNET_IAC,cmd,opt);
putcom(buf,3);
}
}
void request_telnet_opt(uchar cmd, uchar opt)
{
if(cmd==TELNET_DO || cmd==TELNET_DONT) { /* remote option */
if(telnet.remote_option[opt]==telnet_opt_ack(cmd))
return; /* already set in this mode, do nothing */
telnet.remote_option[opt]=telnet_opt_ack(cmd);
} else { /* local option */
if(telnet.local_option[opt]==telnet_opt_ack(cmd))
return; /* already set in this mode, do nothing */
telnet.local_option[opt]=telnet_opt_ack(cmd);
}
send_telnet_cmd(cmd,opt);
}
BYTE* telnet_interpret(BYTE* inbuf, size_t inlen, BYTE* outbuf, size_t *outlen)
{
BYTE command;
BYTE option;
BYTE* first_cr=NULL;
BYTE* first_int=NULL;
size_t i;
if(inlen<1) {
*outlen=0;
return(inbuf); /* no length? No interpretation */
}
first_int=(BYTE*)memchr(inbuf, TELNET_IAC, inlen);
if(telnet.remote_option[TELNET_BINARY_TX]!=TELNET_WILL) {
first_cr=(BYTE*)memchr(inbuf, '\r', inlen);
if(first_cr) {
if(first_int==NULL || first_cr < first_int)
first_int=first_cr;
}
}
if(telnet.cmdlen==0 && first_int==NULL) {
*outlen=inlen;
return(inbuf); /* no interpretation needed */
}
if(telnet.cmdlen==0 /* If we haven't returned and telnet.cmdlen==0 then first_int is not NULL */ ) {
*outlen=first_int-inbuf;
memcpy(outbuf, inbuf, *outlen);
} else
*outlen=0;
for(i=*outlen;i<inlen;i++) {
if(telnet.remote_option[TELNET_BINARY_TX]!=TELNET_WILL) {
if(telnet.cmdlen==1 && telnet.cmd[0]=='\r') {
outbuf[(*outlen)++]='\r';
if(inbuf[i]!=0 && inbuf[i]!=TELNET_IAC)
outbuf[(*outlen)++]=inbuf[i];
telnet.cmdlen=0;
if(inbuf[i]!=TELNET_IAC)
continue;
}
if(inbuf[i]=='\r' && telnet.cmdlen==0) {
telnet.cmd[telnet.cmdlen++]='\r';
continue;
}
}
if(inbuf[i]==TELNET_IAC && telnet.cmdlen==1) { /* escaped 255 */
telnet.cmdlen=0;
outbuf[(*outlen)++]=TELNET_IAC;
continue;
}
if(inbuf[i]==TELNET_IAC || telnet.cmdlen) {
if(telnet.cmdlen<sizeof(telnet.cmd))
telnet.cmd[telnet.cmdlen++]=inbuf[i];
command = telnet.cmd[1];
option = telnet.cmd[2];
if(telnet.cmdlen>=2 && command==TELNET_SB) {
if(inbuf[i]==TELNET_SE
&& telnet.cmd[telnet.cmdlen-2]==TELNET_IAC) {
telnet.cmdlen=0;
}
}
else if(telnet.cmdlen==2 && inbuf[i]<TELNET_WILL) {
telnet.cmdlen=0;
}
else if(telnet.cmdlen>=3) { /* telnet option negotiation */
dprintf("TELNET RX: %s %s"
,telnet_cmd_desc(command),telnet_opt_desc(option));
if(command==TELNET_DO || command==TELNET_DONT) { /* local options */
if(telnet.local_option[option]!=command) {
switch(option) {
case TELNET_BINARY_TX:
case TELNET_ECHO:
case TELNET_TERM_TYPE:
case TELNET_SUP_GA:
case TELNET_NEGOTIATE_WINDOW_SIZE:
telnet.local_option[option]=command;
send_telnet_cmd(telnet_opt_ack(command),option);
break;
default: /* unsupported local options */
if(command==TELNET_DO) /* NAK */
send_telnet_cmd(telnet_opt_nak(command),option);
break;
}
}
} else { /* WILL/WONT (remote options) */
if(telnet.remote_option[option]!=command) {
switch(option) {
case TELNET_BINARY_TX:
case TELNET_ECHO:
case TELNET_TERM_TYPE:
case TELNET_SUP_GA:
case TELNET_NEGOTIATE_WINDOW_SIZE:
telnet.remote_option[option]=command;
send_telnet_cmd(telnet_opt_ack(command),option);
break;
default: /* unsupported remote options */
if(command==TELNET_WILL) /* NAK */
send_telnet_cmd(telnet_opt_nak(command),option);
break;
}
}
}
telnet.cmdlen=0;
}
} else
outbuf[(*outlen)++]=inbuf[i];
}
return(outbuf);
}
int main(int argc, char** argv)
{
int argn = 1;
......