home *** CD-ROM | disk | FTP | other *** search
- /*
- * stelnet - A telnet client for the serial port
- * Version 1.00 (December 20th, 1994)
- *
- * Copyright 1994 Riku Saikkonen (riku.saikkonen@pcb.compart.fi)
- *
- * This program is free software; you can redistribute and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
- * Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program (as the file COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * The author, Riku Saikkonen, can be contacted via the following means:
- * E-mail: riku.saikkonen@pcb.compart.fi (preferred) or
- * risaikko@freenet.hut.fi
- * Paper mail: Riku Saikkonen
- * Alakartanontie 4 B 63
- * SF-02360 ESPOO
- * Finland
- */
-
- /*
- * Known bugs:
- * ZModem ZR[Q]INIT to telnet without a reply activates ZModem 8-bit clean
- * mode (ZDLE ZDLE exits it)
- *
- * Todo list:
- * user-selectable terminal types
- * don't beep on local screen in put_ser() (affects only warnings etc.)
- * debug mode (show IACs)
- * ECHO option (local echo)
- * TELNET options 5 (STATUS), 32-38?
- * non-SGA mode + send Go Ahead command
- * telnet handshaking (how?)
- * telnet/serial options in synchronisation with sob/tob
- * (difficult, not very useful)
- */
-
- #include <stdio.h>
- #include <conio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <dos.h>
- #include <time.h>
- #include <tcp.h>
-
- #define BANNER "stelnet 1.00"
- #define COPYRIGHT1 \
- "Copyright 1994 Riku Saikkonen (riku.saikkonen@pcb.compart.fi)"
- #define COPYRIGHT2 \
- "stelnet is free software, distributed under the terms of the GNU " \
- "General\r\n" \
- "Public License version 2, and comes with ABSOLUTELY NO WARRANTY; for " \
- "details,\r\n" \
- "see the documentation distributed with the program.\r\n"
-
- /* Default telnet, serial buffer sizes (override with makefile) */
- #ifndef TIBLEN
- #define TIBLEN 512
- #endif
- #ifndef SIBLEN
- #define SIBLEN 512
- #endif
- #ifndef TOBLEN
- #define TOBLEN 8192
- #endif
- #ifndef SOBLEN
- #define SOBLEN 8192
- #endif
- #ifndef SOBLIMIT
- #define SOBLIMIT 512
- #endif
-
- /* Default loopcheck value (override with makefile) */
- #ifndef LOOPCHECK
- #define LOOPCHECK 100
- #endif
-
- typedef unsigned char BYTE;
- typedef unsigned int WORD;
-
- #define SE 240
- #define BRK 243
- #define IP 244
- #define AO 245
- #define AYT 246
- #define EC 247
- #define EL 248
- #define SB 250
- #define WILL 251
- #define WONT 252
- #define DO 253
- #define DONT 254
- #define IAC 255
-
- #define IS 0
- #define SEND 1
-
- #define TELOPT_BINARY 0
- #define TELOPT_ECHO 1
- #define TELOPT_SGA 3
- #define TELOPT_TTYPE 24
-
- #define addsob(c) { if (sobp>=SOBLEN) sobp=0; /* Wrap */ \
- if (sobp==sobs && sobp!=0) \
- {sobs++;soverrun++;} /* Buffer overrun; lose first character */ \
- sob[sobp]=c;sobp++; }
-
- #define addtob(c) { if (tobp>=TOBLEN) tobp=0; /* Wrap */ \
- if (tobp==tobs && tobp!=0) \
- {tobs++;toverrun++;} /* Buffer overrun; lose first character */ \
- tob[tobp]=c;tobp++; }
-
- #define putstr(s) {fputs(s,stdout);}
-
- void syntax(void);
-
- int init_tel(void);
- void deinit_tel(void);
- #define ok_tel() tcp_tick(socket)
- #define read_tel(buf,sz) sock_fastread(socket,buf,sz)
- #define write_tel(buf,sz) sock_fastwrite(socket,buf,sz)
-
- int init_ser(void);
- int read_ser(BYTE *buf, int sz);
- int write_ser(BYTE *buf, int sz);
- int ok_ser(void);
- int put_ser(char *s);
- void deinit_ser(void);
-
- int comport;
- union REGS reg;
- struct SREGS sreg;
-
- char hostname[128];
- int port;
- unsigned long hostnum;
- tcp_Socket *socket;
- tcp_Socket socketdata;
-
- int opt_bin;
- int copt_cd,copt_localscr,copt_idle,copt_sendinit,copt_8bit;
- char copt_username[30];
-
- int main(int argc, char *argv[])
- {
- static BYTE tib[TIBLEN],tob[TOBLEN];
- static BYTE sib[SIBLEN],sob[SOBLEN];
- BYTE sibc,tibc;
- static FILE *fp;
- int sobs,sobp,tobs,tobp,sibend,tibend;
- int i,j;
- unsigned u=0;
- int sercmd,teliac,quit,timewarn,itimewarn;
- time_t stime,etime,itime,curtime;
- unsigned char sercmdkey;
- long soverrun,toverrun;
- int clean8bit,clean8bitz,zmframe;
- int loopcount,loop2count,notidle;
- static char s[256],exit8bits[11]="-\030\030stelnet";
-
- putstr(BANNER "\n" COPYRIGHT1 "\n" COPYRIGHT2 "\n");
-
- if (argc<4) syntax();
-
- comport=atoi(argv[1]);
- if (comport<1 || comport>8)
- {
- putstr("Invalid COM port!\n");
- exit(10);
- }
- comport--;
-
- itime=etime=0;
- copt_cd=copt_sendinit=1;copt_localscr=copt_idle=copt_8bit=0;
- itimewarn=timewarn=0;
- strcpy(copt_username,"Unknown");
- stime=time(NULL);
- sercmdkey=255;
-
- for (i=4;i<argc;i++)
- {
- switch (tolower(argv[i][0]))
- {
- case 'i':
- copt_idle=1;
- putstr("Idle timeout checking on.\n");
- break;
- case 't':
- timewarn=atoi(&argv[i][1]);
- etime=stime+timewarn*60;
- timewarn=300;
- putstr("Time limit set.\n");
- break;
- case '8': copt_8bit=1;putstr("8-bit clean mode.\n");break;
- case 'e':
- sercmdkey=atoi(&argv[i][1]);
- sprintf(s,"Escape character set to ASCII %d.\n",sercmdkey);
- putstr(s);
- break;
- case 'c': copt_cd=0;putstr("Carrier Detect checking off.\n");break;
- case 'l': copt_localscr=1;putstr("Local screen on.\n");break;
- case 'x':
- copt_sendinit=0;putstr("Not sending initialisation codes.\n");
- break;
- case 'd': /* Door information file */
- if ((fp=fopen(&argv[i][2],"rb"))==NULL)
- {
- putstr("Error opening door information file!\n");
- exit(9);
- }
- switch (tolower(argv[i][1]))
- {
- case 'p': /* PCBOARD.SYS */
- fseek(fp,84,SEEK_SET);
- fread(copt_username,sizeof(unsigned char),25,fp);
- copt_username[25]=0; /* Purge spaces from right !!! */
- fread(&u,sizeof(unsigned int),1,fp);
- if (u<1440) /* !!! */
- {
- etime=stime+u*60;
- timewarn=300;
- }
- putstr("PCBOARD.SYS read.\n");
- break;
- default: syntax();
- }
- fclose(fp);
- break;
- default: syntax();
- }
- }
-
- if (init_ser()<0)
- {
- putstr("Error initialising serial port!\n");
- exit(3);
- }
-
- /* VT-100: ESC c (reset), ESC [1;1f (home), ESC [2J (clear screen) */
- if (copt_sendinit) put_ser("\033c\033[1;1f\033[2J");
-
- put_ser("\r\n" BANNER "\r\n" COPYRIGHT1 "\r\n" COPYRIGHT2 "\r\n");
-
- sprintf(s,"Serial escape character is ASCII %d.\r\n",sercmdkey);
- putstr(s);
-
- if (copt_8bit)
- put_ser("In 8-bit clean mode; exit with '<255><^X><^X>stelnet'.\r\n");
-
- if (etime!=0)
- {
- sprintf(s,"Time left: %.1f min\r\n",(etime-time(NULL))/60.0);
- put_ser(s);
- }
-
- strcpy(hostname,argv[2]);
- port=atoi(argv[3]);
-
- sprintf(s,"\r\nTrying to connect to %s port %d...\r\n",hostname,port);
- put_ser(s);
-
- i=init_tel();
- if (i<0)
- {
- if (i==-1) put_ser("Connection refused.");
- else put_ser("Name resolver not working!");
- put_ser(" Exiting.\r\n");
- deinit_ser();
- if (i==-1) exit(2); else exit(4);
- }
-
- put_ser("Connected. Type <ASCII 255> ? for a list of commands.\r\n");
-
- sobs=sobp=tobs=tobp=sercmd=teliac=quit=0;
- soverrun=toverrun=0;
- zmframe=clean8bitz=0;
- clean8bit=copt_8bit;
- sibc=tibc=0;
- loopcount=loop2count=notidle=1;
- itimewarn=6;
-
- /* Telnet initialisation IACs */
- if (copt_sendinit)
- {
- tob[0]=IAC;tob[1]=DO;tob[2]=TELOPT_BINARY;
- tob[3]=IAC;tob[4]=WILL;tob[5]=TELOPT_BINARY;opt_bin=1;
- tob[6]=IAC;tob[7]=DO;tob[8]=TELOPT_ECHO;
- tob[9]=IAC;tob[10]=WILL;tob[11]=TELOPT_SGA;
- tob[12]=IAC;tob[13]=DO;tob[14]=TELOPT_SGA;
- tob[15]=IAC;tob[16]=WILL;tob[17]=TELOPT_TTYPE;
- tobp=18;
- }
-
- do
- {
- loopcount--;
-
- if (!loopcount)
- {
- if (!ok_ser())
- {
- putstr("stelnet: Serial port error (Carrier Detect lost)!\n");
- deinit_tel();deinit_ser();exit(3);
- }
- if (!ok_tel()) break;
- }
-
- #if SOBLIMIT != 0
- if ((sobs<=sobp)?(sobp-sobs<SOBLEN-SOBLIMIT):(sobs-sobp>SOBLIMIT))
- {
- #endif
- if ((tibend=read_tel(tib,TIBLEN))<0) break;
- #if SOBLIMIT != 0
- } else tibend=0;
- #endif
-
- sibend=read_ser(sib,SIBLEN);
-
- if (!loopcount && copt_localscr)
- if (kbhit())
- if (sibend<SIBLEN) {sib[sibend]=getch();sibend++;}
-
- for (i=0;i<tibend;i++)
- {
- tibc=tib[i];
- if (teliac)
- {
- switch (teliac)
- {
- case 1: /* IAC */
- switch (tibc)
- {
- case DO: teliac=2;break;
- case DONT: teliac=3;break;
- case WILL: teliac=4;break;
- case WONT: teliac=5;break;
- case SB: teliac=6;break;
- case IP:
- teliac=0;
- quit=2;
- break;
- case AYT:
- teliac=0;
- /* Send "[yes]\n" in reply */
- addtob('[');addtob('y');addtob('e');addtob('s');addtob(']');
- addtob(10);
- break;
- case EC:
- teliac=0;
- /* VT-100 destructive backspace (BS + space + BS) */
- addsob(8);addsob(32);addsob(8);
- break;
- case EL:
- teliac=0;
- /* VT-100 erase line (CR + erase to EOL) */
- addsob(13);addsob(27);addsob('K');
- break;
- case IAC: teliac=0;addsob(255);break;
- default: teliac=0;break; /* Ignore others */
- }
- break;
- case 2: /* IAC DO */
- teliac=0;
- switch (tibc)
- {
- case TELOPT_ECHO:
- /* Never echo ? !!! */
- addtob(IAC);addtob(WONT);addtob(TELOPT_ECHO);
- break;
- case TELOPT_BINARY:
- addtob(IAC);addtob(WILL);addtob(TELOPT_BINARY);
- opt_bin=1;
- break;
- case TELOPT_SGA:
- /* Never sends GA anyway */
- addtob(IAC);addtob(WILL);addtob(TELOPT_SGA);
- break;
- case TELOPT_TTYPE:
- addtob(IAC);addtob(WILL);addtob(TELOPT_TTYPE);
- break;
- default: /* Wont */
- addtob(IAC);addtob(WONT);addtob(tibc);
- break;
- }
- break;
- case 3: /* IAC DONT */
- teliac=0;
- switch (tibc)
- {
- case TELOPT_ECHO:
- addtob(IAC);addtob(WONT);addtob(TELOPT_ECHO);
- break;
- case TELOPT_BINARY:
- addtob(IAC);addtob(WONT);addtob(TELOPT_BINARY);
- put_ser("\r\nstelnet: Non-binary (7-bit) mode activated "
- "by remote request.\r\n");
- opt_bin=0;
- break;
- case TELOPT_SGA:
- /* Never sends GA anyway */
- addtob(IAC);addtob(WONT);addtob(TELOPT_SGA);
- break;
- case TELOPT_TTYPE:
- addtob(IAC);addtob(WONT);addtob(TELOPT_TTYPE);
- break;
- default: /* Wont */
- addtob(IAC);addtob(WONT);addtob(tibc);
- break;
- }
- break;
- case 4: /* IAC WILL */
- case 5: /* IAC WONT */
- /* Nothing to do; ignore */
- teliac=0;
- break;
- case 6: /* IAC SB */
- if (tibc==TELOPT_TTYPE) teliac=7;
- else if (tibc==IAC) teliac=8; /* Ignore string */
- break;
- case 7: /* IAC SB TERMINAL-TYPE */
- teliac=6;
- if (tibc==SEND)
- {
- addtob(IAC);addtob(SB);addtob(TELOPT_TTYPE);addtob(IS);
- /* VT-100: (RFC 1340) "DEC-VT100" (termcap) !!! */
- addtob('D');addtob('E');addtob('C');addtob('-');
- addtob('V');addtob('T');addtob('1');addtob('0');addtob('0');
- addtob(IAC);addtob(SE);
- break;
- }
- break;
- case 8: /* IAC SB ... IAC */
- if (tibc==SE) teliac=0; else teliac=6;
- break;
- default: break;
- }
- } else
- {
- if (tibc==IAC) teliac=1;
- else
- {
- /* Feel free to receive 8-bit even without binary mode ? !!! */
- addsob(tibc);
- if (copt_localscr && tibc!=7) putchar(tibc); /* Don't beep */
- }
- }
- }
-
- if (sibend>0) notidle=1;
- if (!loopcount && notidle) {itime=time(NULL);notidle=0;itimewarn=6;}
-
- for (i=0;i<sibend;i++)
- {
- sibc=sib[i];
- if (sibc==sercmdkey || sercmd) /* Command key */
- {
- if (!sercmd) sercmd=1; /* Skip command key */
- else if (clean8bit)
- {
- if (sibc==exit8bits[sercmd])
- {
- sercmd++;
- if (sercmd>9)
- {
- put_ser("\r\nstelnet: Exiting 8-bit clean mode.\r\n");
- clean8bit=clean8bitz=0;
- sercmd=0;
- }
- }
- else
- {
- addtob(sercmdkey);
- if (sercmdkey==IAC) addtob(IAC); /* IAC -> IAC IAC */
- for (j=1;j<sercmd;j++) addtob(exit8bits[j]);
- addtob(sibc);
- if (sibc==IAC) addtob(IAC); /* IAC -> IAC IAC */
- sercmd=0;
- }
- } else if (sercmd==2) /* <cmdkey> k */
- {
- sercmdkey=sibc;
- sprintf(s,"\r\nstelnet: Serial escape character set to ASCII "
- "%d.\r\n",sercmdkey);
- put_ser(s);
- sercmd=0;
- } else if (sibc==sercmdkey && sercmdkey!='e')
- {
- /* Send the command key */
- addtob(sercmdkey);
- if (sercmdkey==IAC) addtob(IAC); /* IAC -> IAC IAC */
- sercmd=0;
- } else { /* Process command */
- sercmd=0;
- switch (tolower(sibc))
- {
- case 'c':
- put_ser("\r\nstelnet: Close connection command\r\n");
- quit=1;
- break;
- case '8':
- if (opt_bin)
- {
- sprintf(s,"\r\nstelnet: 8-bit clean mode entered "
- "(exit with '<%d><^X><^X>stelnet').\r\n",sercmdkey);
- put_ser(s);
- clean8bit=1;clean8bitz=0;
- } else put_ser("\r\nstelnet: Not in binary mode!\r\n");
- break;
- case 'i': addtob(IAC);addtob(IP);break;
- case 'r': addtob(IAC);addtob(BRK);break;
- case 'a': addtob(IAC);addtob(AO);break;
- case 't': addtob(IAC);addtob(AYT);break;
- case 'e':
- sercmd=2; /* Wait for the character */
- break;
- case 's':
- put_ser("\r\n" BANNER "\r\nConnection status:\r\n");
- put_ser("Connected to ");
- put_ser(hostname);
- put_ser(" (");
- put_ser(itoa((hostnum&0xff000000L)>>24,s,10));
- put_ser(".");
- put_ser(itoa((hostnum&0x00ff0000L)>>16,s,10));
- put_ser(".");
- put_ser(itoa((hostnum&0x0000ff00L)>>8,s,10));
- put_ser(".");
- put_ser(itoa(hostnum&0x000000ffL,s,10));
- put_ser(") port ");
- put_ser(itoa(port,s,10));
- put_ser("\r\n");
- /* For some odd reason, this:
- * sprintf(s," (%d.%d.%d.%d) port %d\r\n",
- * ((hostnum&0xff000000L)>>24),((hostnum&0x00ff0000L)>>16),
- * ((hostnum&0x0000ff00L)>>8),((hostnum&0x000000ffL)),
- * port);
- * didn't work! (BC++ 3.0 bug?)
- */
- put_ser("Binary mode ");
- put_ser((opt_bin)?"on.\r\n":"off.\r\n");
- if (etime!=0)
- {
- sprintf(s,"Time left: %.1f min\r\n",
- (etime-time(NULL))/60.0);
- put_ser(s);
- }
- if (soverrun>0)
- {
- sprintf(s,"%ld characters lost due to serial port output "
- "overflow.\r\n",soverrun);
- put_ser(s);
- }
- if (toverrun>0)
- {
- sprintf(s,"%ld characters lost due to telnet output "
- "overflow.\r\n",toverrun);
- put_ser(s);
- }
- sprintf(s,"Connection %s on the local screen.\r\n",
- (copt_localscr)?"shown":"not shown");
- put_ser(s);
- sprintf(s,"Idle timeout checking %s.\r\n\r\n",
- (copt_idle)?"on":"off");
- put_ser(s);
- break;
- case '?': /* Help */
- put_ser("\r\n" BANNER "\r\n");
- put_ser("stelnet commands (precede with "
- "the escape character):\r\n");
- put_ser("c Forcefully close the connection and exit "
- "stelnet\r\n");
- put_ser("8 (in binary mode) Enter 8-bit clean mode\r\n");
- put_ser(" (exit with '<escchar><^X><^X>stelnet')\r\n");
- put_ser("i Send telnet Interrupt Process code (IAC IP)\r\n");
- put_ser("r Send telnet NVT BRK code (IAC BRK)\r\n");
- put_ser("a Send telnet Abort Output code (IAC AO)\r\n");
- put_ser("t Send telnet Are You There code (IAC AYT)\r\n");
- put_ser("e<key> Set the escape character to <key>\r\n");
- put_ser("s Display connection status\r\n");
- put_ser("? Display this help text\r\n");
- put_ser("<escchar> Send the escape character through "
- "telnet\r\n");
- put_ser("\r\n");
- break;
- default: break;
- }
- }
- } else
- {
- switch (zmframe)
- {
- case 0:
- if (sibc=='*') zmframe=1;
- else if (clean8bitz && sibc==24) zmframe=10;
- break;
- case 1: /* ZPAD */
- if (sibc==24) zmframe=2; else if (sibc!='*') zmframe=0;
- break;
- case 2: /* ZPAD ZDLE */
- if (sibc=='A' || sibc=='C') zmframe=3;
- else if (sibc=='B') zmframe=4;
- else zmframe=0;
- break;
- case 3: /* ZPAD ZDLE ZBIN */
- if (clean8bitz)
- {
- if (sibc==8) /* ZFIN */
- clean8bit=clean8bitz=0;
- } else
- {
- if (sibc==0 || sibc==1) /* ZRQINIT / ZRINIT */
- if (!clean8bit) clean8bit=clean8bitz=1;
- }
- zmframe=0;
- break;
- case 4: /* ZPAD ZDLE ZHEX */
- if (sibc=='0') zmframe=5; else zmframe=0;
- break;
- case 5: /* ZPAD ZDLE ZHEX '0' */
- if (clean8bitz)
- {
- if (sibc=='8') /* ZFIN (hex) */
- clean8bit=clean8bitz=0;
- } else
- {
- if (sibc=='0' || sibc=='1') /* ZRQINIT / ZRINIT (hex) */
- if (!clean8bit) clean8bit=clean8bitz=1;
- }
- zmframe=0;
- break;
- case 10: /* (clean8bitz) ZDLE */
- if (sibc==24) /* Second ZDLE */
- clean8bit=clean8bitz=0;
- zmframe=0;
- break;
- default: break;
- }
-
- if (!opt_bin) sibc&=0x7f; /* Non-binary: Remove 8th bit */
- addtob(sibc);
- if (sibc==IAC) addtob(IAC); /* IAC -> IAC IAC */
- /* Local echo !!! */
- /* if (opt_echo) {if (copt_localscr) putchar(sibc); */
- /* addsob(sibc);} */
- }
- }
-
- if (sobs<sobp)
- {
- /* sobs+=write_ser(&sob[sobs],sobp-sobs); didn't work! */
- /* (another BC++ 3.0 bug?) */
- i=write_ser(&sob[sobs],sobp-sobs);
- sobs+=i;
- } else if (sobs>=sobp && sobs!=0)
- {
- i=write_ser(&sob[sobs],SOBLEN-sobs);
- sobs+=i;
- if (sobs>=SOBLEN) sobs=0; /* Wrap */
- }
- if (sobs==sobp && i!=0) sobs=sobp=0; /* buffer empty -> both = 0 */
-
- if (tobs<tobp)
- {
- i=write_tel(&tob[tobs],tobp-tobs);
- if (i<0) break;
- tobs+=i;
- } else if (tobs>=tobp && tobs!=0)
- {
- i=write_tel(&tob[tobs],TOBLEN-tobs);
- if (i<0) break;
- tobs+=i;
- if (tobs>=TOBLEN) tobs=0; /* Wrap */
- }
- if (tobs==tobp && i!=0) tobs=tobp=0; /* buffer empty -> both = 0 */
-
- if (!loopcount)
- {
- if (etime!=0)
- {
- if (time(NULL)>(etime-timewarn))
- {
- if (timewarn<=0)
- {
- put_ser("\r\nstelnet: No time left!\007\r\n");
- break;
- } else
- {
- sprintf(s,
- "\r\nstelnet: Only %d minute%s of time left!\007\r\n",
- timewarn/60,(timewarn==60)?"":"s");
- put_ser(s);
- timewarn-=60;
- }
- }
- }
-
- if (copt_idle)
- {
- if (time(NULL)>(itime+(6-itimewarn)*10+240))
- {
- if (itimewarn<=0)
- {
- put_ser("\r\nstelnet: Idle timeout!\007\r\n");
- break;
- } else
- {
- put_ser(
- "\r\nstelnet: Idle timeout soon! Do something!\007\r\n");
- itimewarn--;
- }
- }
- }
-
- if (!copt_localscr)
- {
- loop2count--;
- if (!loop2count)
- {
- curtime=time(NULL);
- putstr(BANNER "\n");
- sprintf(s,"User %s\nConnected to %s port %d for %d min",
- copt_username,hostname,port,(curtime-stime)/60);
- putstr(s);
-
- if (etime!=0)
- {
- sprintf(s," (%d min left).\n",(etime-curtime)/60);
- putstr(s);
- } else putstr(".\n");
- sprintf(s,"Idle for %d second(s).",curtime-itime);
- putstr(s);
- if (clean8bit)
- {
- putstr(" 8-bit clean mode");
- if (copt_8bit) putstr(" (from command line)");
- if (clean8bitz) putstr(" (Zmodem)");
- putstr(".");
- }
- putstr("\n\n");
- loop2count=LOOPCHECK;
- }
- }
-
- loopcount=LOOPCHECK;
- }
- } while (!quit);
-
- if (quit>0) /* Non-error return */
- {
- /* Flush sob for 10 seconds */
-
- for (i=0;i<100;i++)
- {
- if (sobs<sobp)
- {
- sobs+=write_ser(&sob[sobs],sobp-sobs);
- } else if (sobs>=sobp && sobs!=0)
- {
- sobs+=write_ser(&sob[sobs],SOBLEN-sobs);
- if (sobs>=SOBLEN) sobs=0; /* Wrap */
- }
- if (sobs==sobp) break;
- delay(100);
- }
-
- switch (quit)
- {
- case 1: put_ser("\r\nstelnet: Local abort.");break;
- case 2: put_ser("\r\nstelnet: Aborted by remote.");break;
- default: break;
- }
- }
-
- deinit_tel();
-
- put_ser("\r\nstelnet: Connection closed, exiting.\r\n");
-
- if (soverrun>0)
- {
- sprintf(s,
- "%ld characters lost due to serial port output overflow.\r\n",
- soverrun);
- put_ser(s);
- }
- if (toverrun>0)
- {
- sprintf(s,"%ld characters lost due to telnet output overflow.\r\n",
- toverrun);
- put_ser(s);
- }
-
- deinit_ser();
-
- if (etime!=0)
- {
- if (time(NULL)>etime) exit(1); else exit(0);
- } else exit(0);
-
- return 0;
- }
-
- void syntax(void)
- {
- putstr("Syntax: stelnet <comport> <host> <port> [options]\n"
- " comport = COM port number (1-8)\n"
- " host = the host name or IP address to connect to\n"
- " port = the TCP/IP port to connect to\n"
- "Options (put as separate arguments):\n"
- " t<n> = set a n-minute time limit\n"
- " i = set a 5-minute idle timeout\n"
- " l = show the connection on the local screen and read the keyboard\n"
- " c = disable Carrier Detect detection on the serial port\n"
- " x = don't send telnet/serial initialisation codes\n"
- " 8 = enter 8-bit clean mode at start\n"
- " d<t><filename> = read a door information file (<t> = type,\n"
- " <filename> = full file name with path)\n"
- " Types: p = PCBOARD.SYS\n"
- "Example: stelnet 1 10.0.0.1 15 dpc:\\pcb\\node1\\pcboard.sys i\n"
- "Errorlevels at return:\n"
- " 0 = ok, 1 = out of time, 2 = connection refused, "
- "3 = serial error,\n"
- " 4 = network error, 9 = error in reading door information file,\n"
- " 10 = error in command line\n");
- exit(10);
- }
-
- int init_tel(void)
- {
- int i;
-
- sock_init();
- dbug_init();
-
- hostnum=resolve(hostname);
- if (hostnum==0) return -2; /* Name resolver failure */
- socket=&socketdata;
- if (!tcp_open(socket,0,hostnum,port,0)) return -1;
- sock_wait_established(socket,sock_delay,0,&i);
- sock_mode(socket,TCP_MODE_NAGLE);
-
- return 0;
-
- sock_err:
- return -1;
- }
-
- void deinit_tel(void)
- {
- int i;
-
- sock_close(socket);
- sock_wait_closed(socket,sock_delay,0,&i);
-
- return;
- sock_err:
- return;
- }
-
- int init_ser()
- {
- reg.h.ah=0x04;
- reg.x.bx=0;
- reg.x.dx=comport;
- int86(0x14,®,®);
- if (reg.x.ax!=0x1954) return -1; else return 0;
- }
-
- int read_ser(BYTE *buf, int sz)
- {
- reg.h.ah=0x18;
- sreg.es=FP_SEG(buf);
- reg.x.di=FP_OFF(buf);
- reg.x.cx=sz;
- reg.x.dx=comport;
- int86x(0x14,®,®,&sreg);
- return reg.x.ax;
- }
-
- int write_ser(BYTE *buf, int sz)
- {
- reg.h.ah=0x19;
- sreg.es=FP_SEG(buf);
- reg.x.di=FP_OFF(buf);
- reg.x.cx=sz;
- reg.x.dx=comport;
- int86x(0x14,®,®,&sreg);
- return reg.x.ax;
- }
-
- int ok_ser(void)
- {
- if (!copt_cd) return 1;
- reg.h.ah=0x03;
- reg.x.dx=comport;
- int86(0x14,®,®);
- if ((reg.h.al&0x80)==0) return 0; else return 1; /* Carrier Detect */
- }
-
- int put_ser(char *s)
- {
- char *sp,*ep;
- int err=0,i;
-
- putstr(s);
-
- sp=s;ep=s+strlen(s);
-
- while (sp<ep)
- {
- i=write_ser(sp,ep-sp);
- sp+=i;
- if (i==0)
- {
- err++;
- delay(100);
- if (err>30) return -1;
- } else err=0;
- }
- return 0;
- }
-
- void deinit_ser(void)
- {
- int i;
-
- /* Wait max. 10 s to flush output buffer */
- for (i=0;i<100;i++)
- {
- reg.h.ah=0x03;
- reg.x.dx=comport;
- int86(0x14,®,®);
- if ((reg.h.ah&0x40)!=0) break; /* Output buffer empty */
-
- delay(100);
- }
-
- /* Deinitialise FOSSIL */
- reg.h.ah=0x05;
- reg.x.dx=comport;
- int86(0x14,®,®);
- }
-
- /* End of stelnet.c */