diff --git a/src/syncterm/GNUmakefile b/src/syncterm/GNUmakefile index cf4b542319a12fd2f6dce3b6bfe64bbad12f4d64..73d669963b34fd3626074d922ddcad96d7cd8126 100644 --- a/src/syncterm/GNUmakefile +++ b/src/syncterm/GNUmakefile @@ -6,9 +6,11 @@ ifeq ($(os),sunos) # Solaris CFLAGS += -DNEED_CFMAKERAW endif -CFLAGS += $(UIFC-MT_CFLAGS) $(CIOLIB-MT_CFLAGS) $(XPDEV-MT_CFLAGS) +CFLAGS += $(UIFC-MT_CFLAGS) $(CIOLIB-MT_CFLAGS) $(XPDEV-MT_CFLAGS) -I../sbbs3 LDFLAGS += $(UIFC-MT_LDFLAGS) $(CIOLIB-MT_LDFLAGS) $(XPDEV-MT_LDFLAGS) +vpath %.c ../sbbs3 + $(SYNCTERM): $(EXEODIR) $(OBJS) $(BUILD_DEPENDS) @echo Linking $@ ${QUIET}$(CC) $(LDFLAGS) $(MT_LDFLAGS) $(OBJS) -o $@ $(UIFC-MT_LIBS) $(CIOLIB-MT_LIBS) $(XPDEV-MT_LIBS) diff --git a/src/syncterm/Makefile b/src/syncterm/Makefile index 4f38644c9191902f0d612450e65358cc9c2347ce..0cfb3f4cea35b97b6332a486cc3d9ba5401bdaf5 100644 --- a/src/syncterm/Makefile +++ b/src/syncterm/Makefile @@ -1,9 +1,11 @@ SRC_ROOT = .. !include ${SRC_ROOT}\build\Common.bmake -CFLAGS = $(CFLAGS) $(UIFC-MT_CFLAGS) $(CIOLIB-MT_CFLAGS) $(XPDEV-MT_CFLAGS) +CFLAGS = $(CFLAGS) $(UIFC-MT_CFLAGS) $(CIOLIB-MT_CFLAGS) $(XPDEV-MT_CFLAGS) -I../sbbs3 LDFLAGS = $(LDFLAGS) $(UIFC-MT_LDFLAGS) $(CIOLIB-MT_LDFLAGS) $(XPDEV-MT_LDFLAGS) +.path.c = .;../sbbs3 + $(SYNCTERM): $(OBJS) @echo Linking $@ ${QUIET}$(CC) $(LDFLAGS) $(MT_LDFLAGS) -e$@ $(OBJS) $(UIFC-MT_LIBS) $(CIOLIB-MT_LIBS) $(XPDEV-MT_LIBS) diff --git a/src/syncterm/bbslist.c b/src/syncterm/bbslist.c index 72b8ab1ac5e75622eab4de4ccd38469035fa1c71..57bf1859b3198e81b2a2fcdc4be188f037948b5a 100644 --- a/src/syncterm/bbslist.c +++ b/src/syncterm/bbslist.c @@ -7,6 +7,7 @@ #include "bbslist.h" #include "uifcinit.h" +#include "conn.h" enum { USER_BBSLIST @@ -40,6 +41,7 @@ void read_list(char *listpath, struct bbslist **list, int *i, int type) FILE *listfile; char *bbsname; str_list_t bbses; + BOOL dumb; if((listfile=fopen(listpath,"r"))!=NULL) { bbses=iniReadSectionList(listfile,NULL); @@ -54,7 +56,10 @@ void read_list(char *listpath, struct bbslist **list, int *i, int type) list[*i]->calls=iniReadInteger(listfile,bbsname,"TotalCalls",0); iniReadString(listfile,bbsname,"UserName","",list[*i]->user); iniReadString(listfile,bbsname,"Password","",list[*i]->password); - list[*i]->dumb=iniReadBool(listfile,bbsname,"BeDumb",0); + list[*i]->conn_type=iniReadInteger(listfile,bbsname,"ConnectionType",CONN_TYPE_RLOGIN); + dumb=iniReadBool(listfile,bbsname,"BeDumb",0); + if(dumb) + list[*i]->conn_type=CONN_TYPE_RAW; list[*i]->reversed=iniReadBool(listfile,bbsname,"Reversed",0); list[*i]->type=type; list[*i]->id=*i; @@ -84,9 +89,7 @@ int edit_list(struct bbslist *item,char *listpath) if(item->type==SYSTEM_BBSLIST) { uifc.helpbuf= "`Cannot edit system BBS list`\n\n" "SyncTERM supports system-wide and per-user lists. You may only edit entries" - "in your own personal list.\n" - "\n" - "The Be Dumb option can be used to connect to BBSs which support 'dumb' telnet"; + "in your own personal list.\n"; uifc.msg("Cannot edit system BBS list"); return(0); } @@ -99,11 +102,11 @@ int edit_list(struct bbslist *item,char *listpath) return(0); for(;;) { sprintf(opt[0],"BBS Name: %s",item->name); - sprintf(opt[1],"RLogin Address: %s",item->addr); - sprintf(opt[2],"RLogin Port: %hu",item->port); + sprintf(opt[1],"Address: %s",item->addr); + sprintf(opt[2],"Port: %hu",item->port); sprintf(opt[3],"Username: %s",item->user); sprintf(opt[4],"Password"); - sprintf(opt[5],"Be Dumb: %s",item->dumb?"Yes":"No"); + sprintf(opt[5],"Connection: %s",conn_types[item->conn_type]); sprintf(opt[6],"Reversed: %s",item->reversed?"Yes":"No"); uifc.changes=0; @@ -125,23 +128,19 @@ int edit_list(struct bbslist *item,char *listpath) iniRenameSection(&inifile,tmp,item->name); break; case 1: - uifc.helpbuf= "`RLogin address`\n\n" + uifc.helpbuf= "`Address`\n\n" "Enter the domain name of the system to connect to ie:\n" "nix.synchro.net"; - uifc.input(WIN_MID|WIN_SAV,0,0,"RLogin Address",item->addr,LIST_ADDR_MAX,K_EDIT); + uifc.input(WIN_MID|WIN_SAV,0,0,"Address",item->addr,LIST_ADDR_MAX,K_EDIT); iniSetString(&inifile,item->name,"Address",item->addr,NULL); break; case 2: i=item->port; sprintf(str,"%hu",item->port?item->port:513); - uifc.helpbuf= "`RLogin port`\n\n" - "Enter the port which RLogin is listening to on the remote system\n\n" - "~ NOTE:~\n" - "Connecting to telnet ports currently appears to work... however, if an\n" - "ASCII 255 char is sent by either end, it will be handled incorreclty by\n" - "the remote system. Further, if the remote system follows the RFC, some\n" - "Terminal weirdness should be expected. This program DOES NOT do telnet."; - uifc.input(WIN_MID|WIN_SAV,0,0,"RLogin Port",str,5,K_EDIT|K_NUMBER); + uifc.helpbuf= "`Port`\n\n" + "Enter the port which the BBS is listening to on the remote system\n" + "Telnet is generally port 23 and RLogin is generally 513\n"; + uifc.input(WIN_MID|WIN_SAV,0,0,"Port",str,5,K_EDIT|K_NUMBER); j=atoi(str); if(j<1 || j>65535) j=513; @@ -165,9 +164,11 @@ int edit_list(struct bbslist *item,char *listpath) iniSetString(&inifile,item->name,"Password",item->password,NULL); break; case 5: - item->dumb=!item->dumb; + item->conn_type++; + if(item->conn_type==CONN_TYPE_TERMINATOR) + item->conn_type=CONN_TYPE_RLOGIN; changed=1; - iniSetBool(&inifile,item->name,"BeDumb",item->dumb,NULL); + iniSetInteger(&inifile,item->name,"ConnectionType",item->conn_type,NULL); break; case 6: item->reversed=!item->reversed; @@ -203,7 +204,7 @@ void add_bbs(char *listpath, struct bbslist *bbs) iniSetInteger(&inifile,bbs->name,"TotalCalls",bbs->calls,NULL); iniSetString(&inifile,bbs->name,"UserName",bbs->user,NULL); iniSetString(&inifile,bbs->name,"Password",bbs->password,NULL); - iniSetBool(&inifile,bbs->name,"BeDumb",bbs->dumb,NULL); + iniSetInteger(&inifile,bbs->name,"ConnectionType",bbs->conn_type,NULL); iniSetBool(&inifile,bbs->name,"Reversed",bbs->reversed,NULL); if((listfile=fopen(listpath,"w"))!=NULL) { iniWriteFile(listfile,inifile); @@ -314,10 +315,10 @@ struct bbslist *show_bbslist(int mode, char *path) uifc.input(WIN_MID|WIN_SAV,0,0,"BBS Name",list[listcount-1]->name,LIST_NAME_MAX,K_EDIT); if(uifc.changes) { uifc.changes=0; - uifc.helpbuf= "`RLogin address`\n\n" + uifc.helpbuf= "`Address`\n\n" "Enter the domain name of the system to connect to ie:\n" "nix.synchro.net"; - uifc.input(WIN_MID|WIN_SAV,0,0,"RLogin Address",list[listcount-1]->addr,LIST_ADDR_MAX,K_EDIT); + uifc.input(WIN_MID|WIN_SAV,0,0,"Address",list[listcount-1]->addr,LIST_ADDR_MAX,K_EDIT); } if(!uifc.changes) { free(list[listcount-1]); @@ -328,27 +329,26 @@ struct bbslist *show_bbslist(int mode, char *path) while(!list[listcount-1]->port) { list[listcount-1]->port=513; sprintf(str,"%hu",list[listcount-1]->port); - uifc.helpbuf= "`RLogin port`\n\n" - "Enter the port which RLogin is listening to on the remote system\n\n" - "~ NOTE:~\n" - "Connecting to telnet ports currently appears to work... however, if an\n" - "ASCII 255 char is sent by either end, it will be handled incorreclty by\n" - "the remote system. Further, if the remote system follows the RFC, some\n" - "Terminal weirdness should be expected. This program DOES NOT do telnet."; - uifc.input(WIN_MID|WIN_SAV,0,0,"RLogin Port",str,5,K_EDIT|K_NUMBER); + uifc.helpbuf= "`Port`\n\n" + "Enter the port which the BBS is listening to on the remote system\n" + "Telnet is generally port 23 and RLogin is generally 513\n"; + uifc.input(WIN_MID|WIN_SAV,0,0,"Port",str,5,K_EDIT|K_NUMBER); j=atoi(str); if(j<1 || j>65535) j=0; list[listcount-1]->port=j; } if(list[listcount-1]->port != 513) { - uifc.helpbuf= "`Be Dumb`\n\n" - "Select this option if attempting to connect to a dumb telnet BBS"; - list[listcount-1]->dumb=0; - uifc.list(WIN_MID|WIN_SAV,0,0,0,&list[listcount-1]->dumb,NULL,"Be Dumb",YesNo); - list[listcount-1]->dumb=!list[listcount-1]->dumb; + uifc.helpbuf= "`Connection Type`\n\n" + "Select the type of connection you wish to make:\n" + "~ RLogin:~ Auto-login with RLogin protocol\n" + "~ Telnet:~ Use more common Telnet protocol (experimental)\n" + "~ Raw: ~ Make a raw socket connection (experimental)\n"; + list[listcount-1]->conn_type=CONN_TYPE_RLOGIN; + uifc.list(WIN_MID|WIN_SAV,0,0,0,&list[listcount-1]->conn_type,NULL,"Connection Type",&conn_types[1]); + list[listcount-1]->conn_type++; } - if(!list[listcount-1]->dumb) { + if(list[listcount-1]->conn_type==CONN_TYPE_RLOGIN) { uifc.helpbuf= "`Username`\n\n" "Enter the username to attempt auto-login to the remote with."; uifc.input(WIN_MID|WIN_SAV,0,0,"User Name",list[listcount-1]->user,MAX_USER_LEN,K_EDIT); diff --git a/src/syncterm/bbslist.h b/src/syncterm/bbslist.h index 61e899864beaa85eb368faf3d7f5a98795a9a4cb..031ed1e0321a550ac3354e68a0a500788afe9d80 100644 --- a/src/syncterm/bbslist.h +++ b/src/syncterm/bbslist.h @@ -23,8 +23,8 @@ struct bbslist { char user[MAX_USER_LEN+1]; char password[MAX_PASSWD_LEN+1]; int type; + int conn_type; int id; - int dumb; int reversed; }; diff --git a/src/syncterm/conn.c b/src/syncterm/conn.c new file mode 100644 index 0000000000000000000000000000000000000000..6b317362bc06c59ea27349dbc233734b678b9719 --- /dev/null +++ b/src/syncterm/conn.c @@ -0,0 +1,84 @@ +#include "sockwrap.h" + +#include "rlogin.h" +#include "telnet_io.h" +#include "raw_io.h" +#include "conn.h" + +static int con_type=CONN_TYPE_UNKNOWN; +SOCKET conn_socket=INVALID_SOCKET; +char *conn_types[]={"Unknown","RLogin","Telnet","Raw",""}; + +int conn_recv(char *buffer, size_t buflen) +{ + int retval=-1; + + switch(con_type) { + case CONN_TYPE_RLOGIN: + retval=rlogin_recv(buffer, buflen); + break; + case CONN_TYPE_TELNET: + retval=telnet_recv(buffer, buflen); + break; + case CONN_TYPE_RAW: + retval=raw_recv(buffer, buflen); + break; + } + return(retval); +} + +int conn_send(char *buffer, size_t buflen, unsigned int timeout) +{ + int retval=-1; + + switch(con_type) { + case CONN_TYPE_RLOGIN: + retval=rlogin_send(buffer, buflen, timeout); + break; + case CONN_TYPE_TELNET: + retval=telnet_send(buffer, buflen, timeout); + break; + case CONN_TYPE_RAW: + retval=raw_send(buffer, buflen, timeout); + break; + } + return(retval); +} + +int conn_connect(char *addr, int port, char *ruser, char *passwd, int conn_type) +{ + int retval=-1; + + con_type=conn_type; + switch(con_type) { + case CONN_TYPE_RLOGIN: + retval=rlogin_connect(addr, port, ruser, passwd); + break; + case CONN_TYPE_TELNET: + retval=telnet_connect(addr, port, ruser, passwd); + break; + case CONN_TYPE_RAW: + retval=raw_connect(addr, port, ruser, passwd); + break; + } + return(retval); +} + +int conn_close(void) +{ + int retval=-1; + + switch(con_type) { + case CONN_TYPE_RLOGIN: + retval=rlogin_close(); + break; + case CONN_TYPE_TELNET: + retval=telnet_close(); + break; + case CONN_TYPE_RAW: + retval=raw_close(); + break; + } + con_type=CONN_TYPE_UNKNOWN; + return(retval); +} diff --git a/src/syncterm/conn.h b/src/syncterm/conn.h new file mode 100644 index 0000000000000000000000000000000000000000..54c1335d6fdc2971da199e10580791d94c25cbf2 --- /dev/null +++ b/src/syncterm/conn.h @@ -0,0 +1,23 @@ +#ifndef _CONN_H_ +#define _CONN_H_ + +#include "sockwrap.h" + +extern SOCKET conn_socket; +extern char *conn_types[]; + +enum { + CONN_TYPE_UNKNOWN + ,CONN_TYPE_RLOGIN + ,CONN_TYPE_TELNET + ,CONN_TYPE_RAW + ,CONN_TYPE_TERMINATOR +}; + +int conn_recv(char *buffer, size_t buflen); +int conn_send(char *buffer, size_t buflen, unsigned int timeout); +int conn_connect(char *addr, int port, char *ruser, char *passwd, int conn_type); +int conn_close(void); +void conn_settype(int type); + +#endif diff --git a/src/syncterm/objects.mk b/src/syncterm/objects.mk index 0dd7c8f7a83de90e5b69b1cb63f98ab6714ed8d3..1cc877595649088a9fde2200e67a217d32b23dc7 100644 --- a/src/syncterm/objects.mk +++ b/src/syncterm/objects.mk @@ -1,8 +1,12 @@ OBJS = \ - $(MTOBJODIR)$(DIRSEP)bbslist$(OFILE) \ + $(MTOBJODIR)$(DIRSEP)bbslist$(OFILE) \ $(MTOBJODIR)$(DIRSEP)uifcinit$(OFILE) \ + $(MTOBJODIR)$(DIRSEP)conn$(OFILE) \ + $(MTOBJODIR)$(DIRSEP)telnet$(OFILE) \ + $(MTOBJODIR)$(DIRSEP)telnet_io$(OFILE) \ + $(MTOBJODIR)$(DIRSEP)raw_io$(OFILE) \ $(MTOBJODIR)$(DIRSEP)rlogin$(OFILE) \ $(MTOBJODIR)$(DIRSEP)term$(OFILE) \ $(MTOBJODIR)$(DIRSEP)window$(OFILE) \ $(MTOBJODIR)$(DIRSEP)menu$(OFILE) \ - $(MTOBJODIR)$(DIRSEP)syncterm$(OFILE) + $(MTOBJODIR)$(DIRSEP)syncterm$(OFILE) diff --git a/src/syncterm/raw_io.c b/src/syncterm/raw_io.c new file mode 100644 index 0000000000000000000000000000000000000000..48943aaaba47b1f7f702793db6207a8d2fb1a33c --- /dev/null +++ b/src/syncterm/raw_io.c @@ -0,0 +1,110 @@ +#include <genwrap.h> +#include <sockwrap.h> + +#include "uifcinit.h" +#include "bbslist.h" +#include "conn.h" + +int raw_recv(char *buffer, size_t buflen) +{ + int r; + int avail; + int rd; + + if(!socket_check(conn_socket, NULL, NULL, 0)) + return(-1); + + if(!ioctlsocket(conn_socket,FIONREAD,(void *)&avail) && avail) + r=recv(conn_socket,buffer,avail<buflen?avail:buflen,0); + else + return(0); + + if(r==-1 && (errno==EAGAIN || errno==EINTR || errno==0)) /* WTF? */ + r=0; + return(r); +} + +int raw_send(char *buffer, size_t buflen, unsigned int timeout) +{ + int sent=0; + int ret; + int i; + + while(sent<buflen) { + if(!socket_check(conn_socket, NULL, &i, timeout)) + return(-1); + if(!i) + return(-1); + ret=send(conn_socket,buffer+sent,buflen-sent,0); + if(ret==-1) { + switch(errno) { + case EAGAIN: + case ENOBUFS: + SLEEP(1); + break; + default: + return(-1); + } + } + else + sent+=ret; + } + return(0); +} + +int raw_connect(char *addr, int port, char *ruser, char *passwd) +{ + HOSTENT *ent; + SOCKADDR_IN saddr; + char nil=0; + char *p; + unsigned int neta; + int i; + + for(p=addr;*p;p++) + if(*p!='.' && !isdigit(*p)) + break; + if(!(*p)) + neta=inet_addr(addr); + else { + if((ent=gethostbyname(addr))==NULL) { + char str[LIST_ADDR_MAX+17]; + + sprintf(str,"Cannot resolve %s!",addr); + uifcmsg(str, "`Cannot Resolve Host`\n\n" + "The system is unable to resolve the hostname... double check the spelling.\n" + "If it's not an issue with your DNS settings, the issue is probobly\n" + "with the DNS settings of the system you are trying to contact."); + return(-1); + } + neta=*((unsigned int*)ent->h_addr_list[0]); + } + conn_socket=socket(PF_INET, SOCK_STREAM, IPPROTO_IP); + if(conn_socket==INVALID_SOCKET) { + uifcmsg("Cannot create socket!", "`Unable to create socket`\n\n" + "Your system is either dangerously low on resources, or there" + "is a problem with your TCP/IP stack."); + return(-1); + } + memset(&saddr,0,sizeof(saddr)); + saddr.sin_addr.s_addr = neta; + saddr.sin_family = AF_INET; + saddr.sin_port = htons(port); + + if(connect(conn_socket, (struct sockaddr *)&saddr, sizeof(saddr))) { + char str[LIST_ADDR_MAX+20]; + + raw_close(); + sprintf(str,"Cannot connect to %s!",addr); + uifcmsg(str, "`Unable to connect`\n\n" + "Cannot connect to the remost system... it is down or unreachable."); + return(-1); + } + + return(0); +} + +int raw_close(void) +{ + return(closesocket(conn_socket)); +} diff --git a/src/syncterm/raw_io.h b/src/syncterm/raw_io.h new file mode 100644 index 0000000000000000000000000000000000000000..d351617dc76f25e590a5b2eb268f848d5c82acb2 --- /dev/null +++ b/src/syncterm/raw_io.h @@ -0,0 +1,9 @@ +#ifndef _RAW_IO_H_ +#define _RAW_IO_H_ + +int raw_recv(char *buffer, size_t buflen); +int raw_send(char *buffer, size_t buflen, unsigned int timeout); +int raw_connect(char *addr, int port, char *ruser, char *passwd); +int raw_close(void); + +#endif diff --git a/src/syncterm/rlogin.c b/src/syncterm/rlogin.c index eaca53b8d97c92c3aaa751fdcd7240d4a7fb2971..3841d05573a2e12b6320339fa124554a1286c3e5 100644 --- a/src/syncterm/rlogin.c +++ b/src/syncterm/rlogin.c @@ -3,8 +3,7 @@ #include "uifcinit.h" #include "bbslist.h" - -static SOCKET rlogin_socket=INVALID_SOCKET; +#include "conn.h" int rlogin_recv(char *buffer, size_t buflen) { @@ -12,11 +11,11 @@ int rlogin_recv(char *buffer, size_t buflen) int avail; int rd; - if(!socket_check(rlogin_socket, NULL, NULL, 0)) + if(!socket_check(conn_socket, NULL, NULL, 0)) return(-1); - if(!ioctlsocket(rlogin_socket,FIONREAD,(void *)&avail) && avail) - r=recv(rlogin_socket,buffer,avail<buflen?avail:buflen,0); + if(!ioctlsocket(conn_socket,FIONREAD,(void *)&avail) && avail) + r=recv(conn_socket,buffer,avail<buflen?avail:buflen,0); else return(0); @@ -32,11 +31,11 @@ int rlogin_send(char *buffer, size_t buflen, unsigned int timeout) int i; while(sent<buflen) { - if(!socket_check(rlogin_socket, NULL, &i, timeout)) + if(!socket_check(conn_socket, NULL, &i, timeout)) return(-1); if(!i) return(-1); - ret=send(rlogin_socket,buffer+sent,buflen-sent,0); + ret=send(conn_socket,buffer+sent,buflen-sent,0); if(ret==-1) { switch(errno) { case EAGAIN: @@ -53,7 +52,7 @@ int rlogin_send(char *buffer, size_t buflen, unsigned int timeout) return(0); } -int rlogin_connect(char *addr, int port, char *ruser, char *passwd, int bedumb) +int rlogin_connect(char *addr, int port, char *ruser, char *passwd) { HOSTENT *ent; SOCKADDR_IN saddr; @@ -80,8 +79,8 @@ int rlogin_connect(char *addr, int port, char *ruser, char *passwd, int bedumb) } neta=*((unsigned int*)ent->h_addr_list[0]); } - rlogin_socket=socket(PF_INET, SOCK_STREAM, IPPROTO_IP); - if(rlogin_socket==INVALID_SOCKET) { + conn_socket=socket(PF_INET, SOCK_STREAM, IPPROTO_IP); + if(conn_socket==INVALID_SOCKET) { uifcmsg("Cannot create socket!", "`Unable to create socket`\n\n" "Your system is either dangerously low on resources, or there" "is a problem with your TCP/IP stack."); @@ -92,7 +91,7 @@ int rlogin_connect(char *addr, int port, char *ruser, char *passwd, int bedumb) saddr.sin_family = AF_INET; saddr.sin_port = htons(port); - if(connect(rlogin_socket, (struct sockaddr *)&saddr, sizeof(saddr))) { + if(connect(conn_socket, (struct sockaddr *)&saddr, sizeof(saddr))) { char str[LIST_ADDR_MAX+20]; rlogin_close(); @@ -102,16 +101,15 @@ int rlogin_connect(char *addr, int port, char *ruser, char *passwd, int bedumb) return(-1); } - if(!bedumb) { - rlogin_send("",1,1000); - rlogin_send(passwd,strlen(passwd)+1,1000); - rlogin_send(ruser,strlen(ruser)+1,1000); - rlogin_send("ansi-bbs/9600",14,1000); - } + rlogin_send("",1,1000); + rlogin_send(passwd,strlen(passwd)+1,1000); + rlogin_send(ruser,strlen(ruser)+1,1000); + rlogin_send("ansi-bbs/9600",14,1000); + return(0); } int rlogin_close(void) { - return(closesocket(rlogin_socket)); + return(closesocket(conn_socket)); } diff --git a/src/syncterm/rlogin.h b/src/syncterm/rlogin.h index 3375654803b890e96a13f950cd6a0d4beef1af82..8f8d9940d38e3cfacae3137ff44fac2c9581dae3 100644 --- a/src/syncterm/rlogin.h +++ b/src/syncterm/rlogin.h @@ -7,7 +7,7 @@ extern SOCKET rlogin_socket; int rlogin_recv(char *buffer, size_t buflen); int rlogin_send(char *buffer, size_t buflen, unsigned int timeout); -int rlogin_connect(char *addr, int port, char *ruser, char *passwd, int dumb); +int rlogin_connect(char *addr, int port, char *ruser, char *passwd); int rlogin_close(void); #endif diff --git a/src/syncterm/syncterm.c b/src/syncterm/syncterm.c index bab8aa412073d614d17fbcc07638f4113d0042af..fe70785679ebe0d14621c908996ebddc46077f7f 100644 --- a/src/syncterm/syncterm.c +++ b/src/syncterm/syncterm.c @@ -6,7 +6,7 @@ #include <dirwrap.h> #include "bbslist.h" -#include "rlogin.h" +#include "conn.h" #include "uifcinit.h" #ifdef _WINSOCKAPI_ @@ -58,7 +58,7 @@ int main(int argc, char **argv) FULLPATH(path,drive,sizeof(path)); atexit(uifcbail); while((bbs=show_bbslist(BBSLIST_SELECT,path))!=NULL) { - if(!rlogin_connect(bbs->addr,bbs->port,bbs->reversed?bbs->password:bbs->user,bbs->reversed?bbs->user:bbs->password,bbs->dumb)) { + if(!conn_connect(bbs->addr,bbs->port,bbs->reversed?bbs->password:bbs->user,bbs->reversed?bbs->user:bbs->password,bbs->conn_type)) { /* ToDo: Update the entry with new lastconnected */ /* ToDo: Disallow duplicate entries */ str_list_t inifile; diff --git a/src/syncterm/telnet_io.c b/src/syncterm/telnet_io.c new file mode 100644 index 0000000000000000000000000000000000000000..ff9cd8d752d3a8a0fbd62eb24dcc0039086c0ae5 --- /dev/null +++ b/src/syncterm/telnet_io.c @@ -0,0 +1,323 @@ +#include <stdlib.h> +#include <string.h> + +#include "genwrap.h" +#include "sockwrap.h" +#include "telnet.h" +#include "gen_defs.h" +#include "bbslist.h" +#include "conn.h" + +#define TELNET_TERM_MAXLEN 40 + +uint telnet_cmdlen=0; +uchar telnet_cmd[64]; +char terminal[TELNET_TERM_MAXLEN+1]; +uint rows; +uint cols; +ulong telnet_mode; +uchar telnet_local_option[0x100]; +uchar telnet_remote_option[0x100]; + +#define putcom(buf,len) send(conn_socket, buf, len, 0) + +void send_telnet_cmd(uchar cmd, uchar opt); + +static BYTE* telnet_interpret(BYTE* inbuf, int inlen, BYTE* outbuf, int *outlen) +{ + BYTE* first_iac=NULL; + BYTE* first_cr=NULL; + int i; + + if(inlen<1) { + *outlen=0; + return(inbuf); // no length? No interpretation + } + + first_iac=(BYTE*)memchr(inbuf, TELNET_IAC, inlen); + + if(!telnet_cmdlen && first_iac==NULL && first_cr==NULL) { + *outlen=inlen; + return(inbuf); // no interpretation needed + } + + if(first_iac!=NULL || first_cr!=NULL) { + if(first_iac!=NULL && (first_cr==NULL || first_iac<first_cr)) + *outlen=first_iac-inbuf; + else + *outlen=first_cr-inbuf; + memcpy(outbuf, inbuf, *outlen); + } else + *outlen=0; + + for(i=*outlen;i<inlen;i++) { + 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) { + uchar command = telnet_cmd[1]; + uchar option = telnet_cmd[2]; + + if(telnet_cmdlen<sizeof(telnet_cmd)) + telnet_cmd[telnet_cmdlen++]=inbuf[i]; + + if(telnet_cmdlen>=2 && command==TELNET_SB) { + if(inbuf[i]==TELNET_SE + && telnet_cmd[telnet_cmdlen-2]==TELNET_IAC) { + /* sub-option terminated */ + if(option==TELNET_TERM_TYPE + && telnet_cmd[3]==TELNET_TERM_IS) { + sprintf(terminal,"%.*s",(int)telnet_cmdlen-6,telnet_cmd+4); + } else if(option==TELNET_TERM_SPEED + && telnet_cmd[3]==TELNET_TERM_IS) { + char speed[128]; + sprintf(speed,"%.*s",(int)telnet_cmdlen-6,telnet_cmd+4); + } else if(option==TELNET_NEGOTIATE_WINDOW_SIZE) { + long cols = (telnet_cmd[3]<<8) | telnet_cmd[4]; + long rows = (telnet_cmd[5]<<8) | telnet_cmd[6]; + if(rows) /* auto-detect rows */ + rows=rows; + if(cols) + cols=cols; + } + telnet_cmdlen=0; + } + } + else if(telnet_cmdlen==2 && inbuf[i]<TELNET_WILL) { + telnet_cmdlen=0; + } + else if(telnet_cmdlen>=3) { /* telnet option negotiation */ + if(command==TELNET_DO || command==TELNET_DONT) { /* local options */ + if(telnet_local_option[option]!=command) { + telnet_local_option[option]=command; + send_telnet_cmd(telnet_opt_ack(command),option); + } + } 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_TERM_SPEED: + 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; + } + } + + if(command==TELNET_WILL && option==TELNET_TERM_TYPE) { + char buf[64]; + sprintf(buf,"%c%c%c%c%c%c" + ,TELNET_IAC,TELNET_SB + ,TELNET_TERM_TYPE,TELNET_TERM_SEND + ,TELNET_IAC,TELNET_SE); + putcom(buf,6); + } + else if(command==TELNET_WILL && option==TELNET_TERM_SPEED) { + char buf[64]; + sprintf(buf,"%c%c%c%c%c%c" + ,TELNET_IAC,TELNET_SB + ,TELNET_TERM_SPEED,TELNET_TERM_SEND + ,TELNET_IAC,TELNET_SE); + putcom(buf,6); + } + } + + telnet_cmdlen=0; + + } + } else + outbuf[*outlen++]=inbuf[i]; + } + return(outbuf); +} + +void send_telnet_cmd(uchar cmd, uchar opt) +{ + char buf[16]; + + if(telnet_mode&TELNET_MODE_OFF) + return; + + if(cmd<TELNET_WILL) { + sprintf(buf,"%c%c",TELNET_IAC,cmd); + putcom(buf,2); + } else { + 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); +} + +int telnet_recv(char *buffer, size_t buflen) +{ + int r; + int avail; + int rd; + BYTE *inbuf; + + if(!socket_check(conn_socket, NULL, NULL, 0)) + return(-1); + + if((inbuf=(BYTE *)malloc(buflen))==NULL) + return(-1); + + if(!ioctlsocket(conn_socket,FIONREAD,(void *)&avail) && avail) + r=recv(conn_socket,inbuf,avail<buflen?avail:buflen,0); + else { + free(inbuf); + return(0); + } + + if(r==-1 && (errno==EAGAIN || errno==EINTR || errno==0)) /* WTF? */ + r=0; + if(r) { + if(telnet_interpret(inbuf, r, buffer, &r)==inbuf) + memcpy(buffer, inbuf, r); + } + + free(inbuf); + return(r); +} + +BYTE* telnet_expand(BYTE* inbuf, size_t inlen, BYTE* outbuf, size_t *newlen) +{ + BYTE* first_iac; + ulong i,outlen; + + first_iac=(BYTE*)memchr(inbuf, TELNET_IAC, inlen); + + if(first_iac==NULL) { /* Nothing to expand */ + *newlen=inlen; + return(inbuf); + } + + outlen=first_iac-inbuf; + memcpy(outbuf, inbuf, outlen); + + for(i=outlen;i<inlen;i++) { + if(inbuf[i]==TELNET_IAC) + outbuf[outlen++]=TELNET_IAC; + outbuf[outlen++]=inbuf[i]; + } + *newlen=outlen; + return(outbuf); +} + +int telnet_send(char *buffer, size_t buflen, unsigned int timeout) +{ + int sent=0; + int ret; + int i; + BYTE *outbuf; + BYTE *sendbuf; + + if((outbuf=(BYTE *)malloc(buflen*2))==NULL) + return(-1); + sendbuf=telnet_expand(buffer, buflen, outbuf, &buflen); + while(sent<buflen) { + if(!socket_check(conn_socket, NULL, &i, timeout)) { + free(outbuf); + return(-1); + } + if(!i) { + free(outbuf); + return(-1); + } + ret=send(conn_socket,sendbuf+sent,buflen-sent,0); + if(ret==-1) { + switch(errno) { + case EAGAIN: + case ENOBUFS: + SLEEP(1); + break; + default: + free(outbuf); + return(-1); + } + } + else + sent+=ret; + } + free(outbuf); + return(0); +} + +int telnet_close(void) +{ + return(closesocket(conn_socket)); +} + +int telnet_connect(char *addr, int port, char *ruser, char *passwd) +{ + HOSTENT *ent; + SOCKADDR_IN saddr; + char nil=0; + char *p; + unsigned int neta; + int i; + + for(p=addr;*p;p++) + if(*p!='.' && !isdigit(*p)) + break; + if(!(*p)) + neta=inet_addr(addr); + else { + if((ent=gethostbyname(addr))==NULL) { + char str[LIST_ADDR_MAX+17]; + + sprintf(str,"Cannot resolve %s!",addr); + uifcmsg(str, "`Cannot Resolve Host`\n\n" + "The system is unable to resolve the hostname... double check the spelling.\n" + "If it's not an issue with your DNS settings, the issue is probobly\n" + "with the DNS settings of the system you are trying to contact."); + return(-1); + } + neta=*((unsigned int*)ent->h_addr_list[0]); + } + conn_socket=socket(PF_INET, SOCK_STREAM, IPPROTO_IP); + if(conn_socket==INVALID_SOCKET) { + uifcmsg("Cannot create socket!", "`Unable to create socket`\n\n" + "Your system is either dangerously low on resources, or there" + "is a problem with your TCP/IP stack."); + return(-1); + } + memset(&saddr,0,sizeof(saddr)); + saddr.sin_addr.s_addr = neta; + saddr.sin_family = AF_INET; + saddr.sin_port = htons(port); + + if(connect(conn_socket, (struct sockaddr *)&saddr, sizeof(saddr))) { + char str[LIST_ADDR_MAX+20]; + + telnet_close(); + sprintf(str,"Cannot connect to %s!",addr); + uifcmsg(str, "`Unable to connect`\n\n" + "Cannot connect to the remost system... it is down or unreachable."); + return(-1); + } + + return(0); +} diff --git a/src/syncterm/telnet_io.h b/src/syncterm/telnet_io.h new file mode 100644 index 0000000000000000000000000000000000000000..068256abba86feb4cab8b4664fffd0e6ee447370 --- /dev/null +++ b/src/syncterm/telnet_io.h @@ -0,0 +1,9 @@ +#ifndef _TELNET_IO_H_ +#define _TELNET_IO_H_ + +int telnet_recv(char *buffer, size_t buflen); +int telnet_send(char *buffer, size_t buflen, unsigned int timeout); +int telnet_close(void); +int telnet_connect(char *addr, int port, char *ruser, char *passwd); + +#endif diff --git a/src/syncterm/term.c b/src/syncterm/term.c index 9f5ac32f203cfa136c982407027d85cfcbc891e7..5c4ca1d4f380edbb94ecd06ad24e592120d494a7 100644 --- a/src/syncterm/term.c +++ b/src/syncterm/term.c @@ -4,7 +4,7 @@ #include <mouse.h> #include <keys.h> -#include "rlogin.h" +#include "conn.h" #include "term.h" #include "uifcinit.h" #include "menu.h" @@ -32,19 +32,19 @@ void doterm(void) /* Main input loop */ for(;;) { /* Get remote input */ - i=rlogin_recv(buf,sizeof(buf)); + i=conn_recv(buf,sizeof(buf)); switch(i) { case -1: free(scrollback); cterm_end(); - rlogin_close(); + conn_close(); uifcmsg("Disconnected","`Disconnected`\n\nRemote host dropped connection"); return; case 0: break; default: cterm_write(buf,i,prn,sizeof(prn)); - rlogin_send(prn,strlen(prn),0); + conn_send(prn,strlen(prn),0); break; } @@ -62,37 +62,37 @@ void doterm(void) break; case CIO_KEY_LEFT: - rlogin_send("\033[D",3,0); + conn_send("\033[D",3,0); break; case CIO_KEY_RIGHT: - rlogin_send("\033[C",3,0); + conn_send("\033[C",3,0); break; case CIO_KEY_UP: - rlogin_send("\033[A",3,0); + conn_send("\033[A",3,0); break; case CIO_KEY_DOWN: - rlogin_send("\033[B",3,0); + conn_send("\033[B",3,0); break; case CIO_KEY_HOME: - rlogin_send("\033[H",3,0); + conn_send("\033[H",3,0); break; case CIO_KEY_END: #ifdef CIO_KEY_SELECT case CIO_KEY_SELECT: /* Some terminfo/termcap entries use KEY_SELECT as the END key! */ #endif - rlogin_send("\033[K",3,0); + conn_send("\033[K",3,0); break; case CIO_KEY_F(1): - rlogin_send("\033OP",3,0); + conn_send("\033OP",3,0); break; case CIO_KEY_F(2): - rlogin_send("\033OQ",3,0); + conn_send("\033OQ",3,0); break; case CIO_KEY_F(3): - rlogin_send("\033Ow",3,0); + conn_send("\033Ow",3,0); break; case CIO_KEY_F(4): - rlogin_send("\033Ox",3,0); + conn_send("\033Ox",3,0); break; case 0x1f00: /* ALT-S */ viewscroll(); @@ -102,7 +102,7 @@ void doterm(void) case 17: /* CTRL-Q */ cterm_end(); free(scrollback); - rlogin_close(); + conn_close(); return; case 19: /* CTRL-S */ i=wherex(); @@ -111,7 +111,7 @@ void doterm(void) case -1: cterm_end(); free(scrollback); - rlogin_close(); + conn_close(); return; } gotoxy(i,j); @@ -122,7 +122,7 @@ void doterm(void) default: if(key<256) { ch[0]=key; - rlogin_send(ch,1,0); + conn_send(ch,1,0); } }