home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / MISC / NETWORK / TEL23SRC.ZIP / INT14 / START14.C < prev   
Encoding:
C/C++ Source or Header  |  1991-07-01  |  34.0 KB  |  1,119 lines

  1. #ifdef __TURBOC__
  2. #include "turboc.h"
  3. #endif
  4. #include <stdio.h>
  5. #include <conio.h>
  6. #include <string.h>
  7. #include <stdlib.h>
  8. #include <malloc.h>
  9. #include <dos.h>
  10. #include <ctype.h>
  11. #include <process.h>
  12. #include <errno.h>
  13. #ifdef MSC
  14. #include <direct.h>
  15. #include <signal.h>
  16. #include <time.h>
  17. #endif
  18.  
  19.  
  20. #ifdef MEMORY_DEBUG
  21. #include "memdebug.h"
  22. #endif
  23. #include "netevent.h"
  24. #include "hostform.h"
  25. #include "whatami.h"
  26. #include "externs.h"
  27.  
  28. /* #define DEBUG */
  29.  
  30. /*
  31. *    Global variables
  32. */
  33. int    bypass_passwd=0;        /* whether to bypass the password check, not used */
  34. int debug = 0;              /* enable with -D option */
  35. unsigned char path_name[_MAX_DRIVE+_MAX_DIR],   /* character storage for the path name */
  36.     temp_str[100],temp_data[100];        /* temporary character storage */
  37. struct machinfo *mp;
  38. unsigned char buf[256];
  39. unsigned char myipnum[4];           /* the ip number for this machine */
  40. char *config;
  41.  
  42. #define SERIAL  0x14
  43. #define NUM_COMM_PORTS  4   /* the number of comm. ports supported, remember to change this variable in int14.asm also */
  44.  
  45. /* Definitions for telnet protocol */
  46.  
  47. #define STNORM      0
  48.  
  49. #define SE            240
  50. #define NOP            241
  51. #define DM            242
  52. #define BREAK        243
  53. #define IP            244
  54. #define AO            245
  55. #define AYT            246
  56. #define EC            247
  57. #define EL            248
  58. #define GOAHEAD     249
  59. #define SB            250
  60. #define WILLTEL     251
  61. #define WONTTEL     252
  62. #define DOTEL         253
  63. #define DONTTEL     254
  64. #define IAC             255
  65.  
  66.  
  67. /* Assigned Telnet Options */
  68. #define BINARY                 0
  69. #define ECHO                1
  70. #define RECONNECT            2
  71. #define SGA                 3
  72. #define AMSN                4
  73. #define STATUS                5
  74. #define TIMING                6
  75. #define RCTAN                7
  76. #define OLW                    8
  77. #define OPS                    9
  78. #define OCRD                10
  79. #define OHTS                11
  80. #define OHTD                12
  81. #define OFFD                13
  82. #define OVTS                14
  83. #define OVTD                15
  84. #define OLFD                16
  85. #define XASCII                17
  86. #define LOGOUT                18
  87. #define BYTEM                19
  88. #define DET                    20
  89. #define SUPDUP                21
  90. #define SUPDUPOUT            22
  91. #define SENDLOC                23
  92. #define TERMTYPE             24
  93. #define EOR                    25
  94. #define TACACSUID            26
  95. #define OUTPUTMARK            27
  96. #define TERMLOCNUM            28
  97. #define REGIME3270            29
  98. #define X3PAD                30
  99. #define NAWS                31
  100. #define TERMSPEED            32
  101. #define TFLOWCNTRL            33
  102. #define LINEMODE             34
  103.     #define MODE 1
  104.         #define EDIT     1
  105.         #define TRAPSIG  2
  106.         #define MODE_ACK 4
  107.  
  108.     #define FORWARDMASK 2
  109.  
  110.     #define SLC 3 
  111.         #define NO_SUPPORT        0
  112.         #define CANTCHANGE        1
  113.         #define SLC_VALUE        2
  114.         #define SLC_DEFAULT        3
  115.         #define SLC_LEVELBITS    3
  116.         #define SLC_AWK            128
  117.  
  118.         #define SLC_SYNCH        1
  119.         #define SLC_BRK            2
  120.         #define SLC_IP            3
  121.         #define SLC_AO            4
  122.         #define SLC_AYT            5
  123.         #define SLC_EOR            6
  124.         #define SLC_ABORT        7
  125.         #define SLC_EOF            8
  126.         #define SLC_SUSP        9
  127.         #define SLC_EC            10
  128.         #define SLC_EL           11
  129.         #define SLC_EW           12
  130.         #define SLC_RP            13
  131.         #define SLC_LNEXT        14
  132.         #define SLC_XON            15
  133.         #define SLC_XOFF        16
  134.         #define SLC_FORW1        17
  135.         #define SLC_FORW2        18
  136. #define XDISPLOC            35
  137. #define XOPTIONS            255
  138.  
  139.     
  140. #define ESCFOUND 5
  141. #define IACFOUND 6
  142. #define NEGOTIATE 1
  143.  
  144. #ifdef DEBUG
  145. char *telstates[]={
  146.     "Subnegotiation End",
  147.     "NOP",
  148.     "Data Mark",
  149.     "Break",
  150.     "Interrupt Process",
  151.     "Abort Output",
  152.     "Are You There",
  153.     "Erase Character",
  154.     "Erase Line",
  155.     "Go Ahead",
  156.     "Subnegotiate",
  157.     "Will",
  158.     "Won't",
  159.     "Do",
  160.     "Don't"
  161. };
  162.  
  163. char *teloptions[256]={
  164.     "Binary",                /* 0 */
  165.     "Echo",
  166.     "Reconnection",
  167.     "Supress Go Ahead",
  168.     "Message Size Negotiation",
  169.     "Status",                /* 5 */
  170.     "Timing Mark",
  171.     "Remote Controlled Trans and Echo",
  172.     "Output Line Width",
  173.     "Output Page Size",
  174.     "Output Carriage-Return Disposition",    /* 10 */
  175.     "Output Horizontal Tab Stops",
  176.     "Output Horizontal Tab Disposition",
  177.     "Output Formfeed Disposition",
  178.     "Output Vertical Tabstops",
  179.     "Output Vertical Tab Disposition",        /* 15 */
  180.     "Output Linefeed Disposition",
  181.     "Extended ASCII",
  182.     "Logout",
  183.     "Byte Macro",
  184.     "Data Entry Terminal",                    /* 20 */
  185.     "SUPDUP",
  186.     "SUPDUP Output",
  187.     "Send Location",
  188.     "Terminal Type",
  189.     "End of Record",                        /* 25 */
  190.     "TACACS User Identification",
  191.     "Output Marking",
  192.     "Terminal Location Number",
  193.     "3270 Regime",
  194.     "X.3 PAD",                                /* 30 */
  195.     "Negotiate About Window Size",
  196.     "Terminal Speed",
  197.     "Toggle Flow Control",
  198.     "Linemode",
  199.     "X Display Location",                    /* 35 */
  200.     "36","37","38","39",
  201.     "40","41","42","43","44","45","46","47","48","49",
  202.     "50","51","52","53","54","55","56","57","58","59",
  203.     "60","61","62","63","64","65","66","67","68","69",
  204.     "70","71","72","73","74","75","76","77","78","79",
  205.     "80","81","82","83","84","85","86","87","88","89",
  206.     "90","91","92","93","94","95","96","97","98","99",
  207.     "100","101","102","103","104","105","106","107","108","109",
  208.     "110","111","112","113","114","115","116","117","118","119",
  209.     "120","121","122","123","124","125","126","127","128","129",
  210.     "130","131","132","133","134","135","136","137","138","139",
  211.     "140","141","142","143","144","145","146","147","148","149",
  212.     "150","151","152","153","154","155","156","157","158","159",
  213.     "160","161","162","163","164","165","166","167","168","169",
  214.     "170","171","172","173","174","175","176","177","178","179",
  215.     "180","181","182","183","184","185","186","187","188","189",
  216.     "190","191","192","193","194","195","196","197","198","199",
  217.     "200","201","202","203","204","205","206","207","208","209",
  218.     "210","211","212","213","214","215","216","217","218","219",
  219.     "220","221","222","223","224","225","226","227","228","229",
  220.     "230","231","232","233","234","235","236","237","238","239",
  221.     "240","241","242","243","244","245","246","247","248","249",
  222.     "250","251","252","253","254",
  223.     "Extended Options List"        /* 255 */
  224. };
  225.  
  226. char *LMoptions[]={
  227.     "None",
  228.     "SYNCH",
  229.     "BREAK",
  230.     "IP",
  231.     "ABORT OUTPUT",
  232.     "AYT",
  233.     "EOR",
  234.     "ABORT",
  235.     "EOF",
  236.     "SUSP",
  237.     "EC",
  238.     "EL",
  239.     "EW",
  240.     "RP",
  241.     "LNEXT",
  242.     "XON",
  243.     "XOFF",
  244.     "FORW1",
  245.     "FORW2"
  246. };
  247.  
  248. char *LMflags[]={
  249.     "NOSUPPORT",
  250.     "CANTCHANGE",
  251.     "VALUE",
  252.     "DEFAULT"
  253. };
  254. #endif
  255.  
  256. extern void int14inst(void );
  257. extern void int14deinst(void );
  258. extern void timeinst(void );
  259. extern void timedeinst(void );
  260. extern int int14check(void );
  261. extern int int14receive(void );
  262. extern int go_tsr(void );
  263.  
  264. static void int14parse(int comm_port,unsigned char *st,int cnt);
  265. static void int14parsewrite(int comm_port,char *dat,int len);
  266.  
  267. extern struct config def;   /* Default settings obtained from host file */
  268. extern unsigned char initialized_flags;     /* flags indicating whether a port has been initialized */
  269. extern unsigned char connected_flags;       /* flags indicating whether a port is connected yet */
  270. extern unsigned char opening_flags;         /* flags indicating whether a port is negotiating an open connection */
  271. extern unsigned char port_buffer[NUM_COMM_PORTS][64];    /* four buffers to store the machine name to connect to */
  272. extern unsigned char buffer_offset[NUM_COMM_PORTS];      /* the offset into the buffer currently */
  273. extern int pnum[NUM_COMM_PORTS];                         /* the port number we are connected to */
  274.  
  275. #define PORT_DATA_SIZE      2048        /* this is sort of a guess, might need larger */
  276.  
  277. extern unsigned char *data_begin[NUM_COMM_PORTS];   /* pointers to the beginning of the data buffer for the comm.ports */
  278. extern unsigned char *data_max[NUM_COMM_PORTS];     /* pointers to the maximum value for the data_end pointers */
  279. extern unsigned char *data_end[NUM_COMM_PORTS];     /* pointers to the end of the data buffer for the comm. ports */
  280. extern unsigned char *data_start[NUM_COMM_PORTS];   /* pointers to the start of the data buffer for the comm. ports */
  281. unsigned char port_data[NUM_COMM_PORTS][PORT_DATA_SIZE]; /* data buffer for data read in from the comm. port */
  282.  
  283. unsigned char parsedat[32];                 /* character buffer to store network writes */
  284. int comm_port_index[NPORTS];                /* lookup table from a network port number to a comm port number */
  285. int telstate[NUM_COMM_PORTS]={STNORM,STNORM,STNORM,STNORM};  /* the telnet state for each comm. port */
  286. int substate[NUM_COMM_PORTS]={0,0,0,0};                  /* the telnet state for each comm. port */
  287. int echo[NUM_COMM_PORTS]={1,1,1,1};
  288. int igoahead[NUM_COMM_PORTS]={0,0,0,0};
  289. int ugoahead[NUM_COMM_PORTS]={0,0,0,0};
  290. int timing[NUM_COMM_PORTS]={0,0,0,0};
  291. char c;
  292. #ifdef QAK
  293. int buffer_stat=0,max_buffer_stat=0;
  294. #endif
  295.  
  296. void print_int(int num)
  297. {
  298. #ifdef QAK
  299.     printf("number: %d:%x\n",num,num);
  300. #else
  301.     printf("number: %d:%x\t",num,num);
  302. #endif
  303. }   /* end print_int() */
  304.  
  305. void print_int2(int num)
  306. {
  307.     printf("number2: %d:%x\n",num,num);
  308. }   /* end print_int() */
  309.  
  310. /*
  311. *   int14init
  312. *
  313. *   Entry :  none
  314. *
  315. */
  316. int int14init(void)
  317. {
  318. #ifdef QAK
  319.     config = (getenv("CONFIG.TEL"));    /* check for a config.tel in the environment */
  320.     if(config)                  /* set a different config.tel file */
  321.         Shostfile(config);
  322. #endif
  323.  
  324.     puts("National Center for Supercomputing Applications");    /* put the banner on the screen */
  325.     puts("Interrupt 14h driver");
  326.     puts("January 1991\n");
  327.  
  328.     if(Snetinit()) {            /* call session initialization */
  329. #ifdef QAK
  330.         errhandle();            /* Snetinit() reads config.tel file */
  331. #else
  332.         puts("Snetinit() failed");
  333. #endif
  334.         return(0);
  335.       }
  336.     netgetip(myipnum);          /* get my IP number (in case of BOOTP or RARP) */
  337.     Sgetconfig(&def);       /* get information provided in hosts file */
  338.  
  339. /*
  340. *  Display my Ethernet (or Appletelk) and IP address for the curious people
  341. */
  342.     pcgetaddr(&buf[200],def.address,def.ioaddr);
  343.     printf("My Ethernet address: %x:%x:%x:%x:%x:%x\r\n",buf[200],buf[201],buf[202],buf[203],buf[204],buf[205]);
  344.     printf("My IP address: %d.%d.%d.%d\r\n\n",myipnum[0],myipnum[1],myipnum[2],myipnum[3]);
  345.  
  346.     Stask();                    /* any packets for me? (return ARPs) */
  347.     return(1);      /* inidicate sucessful initialization */
  348. }   /* end int14init() */
  349.  
  350. /*
  351. *   int14open
  352. *
  353. *   Entry :
  354. *       int comm_port - which comm port this connection is attached to
  355. *
  356. */
  357. int int14open(int comm_port)
  358. {
  359.     int ev,what,dat;
  360.     char *errmsg;
  361.  
  362. #ifdef DEBUG
  363. printf("opening connection to: %s:%d\n",port_buffer[comm_port],comm_port);
  364. #endif
  365.     mp=gethostinfo(port_buffer[comm_port]);    /* look up in hosts cache, also checks for domain lookup */
  366. #ifdef DEBUG
  367. puts("after opening connection to the machine\n");
  368. #endif
  369.     if(!mp) {
  370.         puts("need to domain lookup!?!?\n");
  371.         return(0);          /* error return */
  372.       } /* end if */
  373.     else {
  374.         while((ev=Sgetevent(ERRCLASS,&what,&dat))!=0) { /* sift through the error events potentially generated by a domain lookup */
  375.             if(dat!=801 && dat!=805) {  /* filter out reports of using domain lookup */
  376.                 errmsg=neterrstring(dat);
  377.                 puts(errmsg);
  378.               } /* end if */
  379.           } /* end while */
  380.         if(0>(pnum[comm_port]=Snetopen(mp,23))) {
  381. #ifdef QAK
  382.             errhandle();
  383. #else
  384.             puts("Network open failed");
  385. #endif
  386.             netshut();
  387.             return(0);
  388.           }
  389.         comm_port_index[pnum[comm_port]]=comm_port;     /* assign the comm port to the TCP port number */
  390.       }
  391.     return(1);      /* indicate sucessful session opening */
  392. }   /* end int14open() */
  393.  
  394.  
  395. /*********************************************************************/
  396. /* int14process
  397. *  take incoming data and process it.  Close the connection if it
  398. *  is the end of the connection.
  399. */
  400. int int14process(int comm_port)
  401. {
  402.     int cnt;
  403.  
  404.     cnt=netread(pnum[comm_port],buf,64); /* get some from incoming queue */
  405.     if(cnt<0) {                    /* close this session, if over */
  406.         netclose(pnum[comm_port]);
  407.         return(0);
  408.       }
  409.  
  410.     if(cnt) 
  411.         int14parse(comm_port,buf,cnt);            /* display on screen, etc.*/
  412. #ifdef QAK
  413. puts("leaving int14process()");
  414. #endif
  415.     return(0);
  416. }
  417.  
  418. /*********************************************************************/
  419. /*  int14parse
  420. *   Do the telnet negotiation parsing.
  421. *
  422. *   look at the string which has just come in from outside and
  423. *   check for special sequences that we are interested in.
  424. *
  425. *   Tries to pass through routine strings immediately, waiting for special
  426. *   characters ESC and IAC to change modes.
  427. */
  428. void int14parse(int comm_port,unsigned char *st,int cnt)
  429. {
  430.     int i;
  431.     unsigned char *mark,*orig;
  432.  
  433.     orig=st;                /* remember beginning point */
  434.     mark=st+cnt;            /* set to end of input string */
  435.     netpush(pnum[comm_port]);
  436.  
  437. /*
  438. *  traverse string, looking for any special characters which indicate that
  439. *  we need to change modes.
  440. */
  441.     while(st<mark) {
  442.         switch(telstate[comm_port]) {
  443.             case ESCFOUND:
  444.                 int14parsewrite(comm_port,"\033",1);        /* send the missing ESC */
  445.                 telstate[comm_port]=STNORM;
  446.                 break;
  447.  
  448.             case IACFOUND:                 /* telnet option negotiation */
  449.                 if(*st==IAC) {            /* real data=255 */
  450.                     st++;                /* real 255 will get sent */
  451.                     telstate[comm_port]=STNORM;
  452.                     break;
  453.                   }
  454.  
  455.                 if(*st>239) {
  456.                     telstate[comm_port]=*st++; /* by what the option is */
  457.                     break;
  458.                   }
  459.  
  460. #ifdef DEBUG
  461.                 printf("strange telnet option %s\n",itoa(*st,parsedat,10));
  462. #endif
  463.                 orig=st;
  464.                 telstate[comm_port]=STNORM;
  465.                 break;
  466.  
  467.             case EL:        /* received a telnet erase line command */
  468.             case EC:        /* received a telnet erase character command */
  469.             case AYT:       /* received a telnet Are-You-There command */
  470.             case AO:        /* received a telnet Abort Output command */
  471.             case IP:        /* received a telnet Interrupt Process command */
  472.             case BREAK:     /* received a telnet Break command */
  473.             case DM:        /* received a telnet Data Mark command */
  474.             case NOP:       /* received a telnet No Operation command */
  475.             case SE:        /* received a telnet Subnegotiation End command */
  476. #ifdef DEBUG
  477.                 printf("RECV: %s\n",telstates[telstate[comm_port]-SE]);
  478. #endif
  479.                 telstate[comm_port]=STNORM;
  480.                 orig=st;
  481.                 break;
  482.  
  483.             case GOAHEAD:       /* telnet go ahead option*/
  484.                 telstate[comm_port]=STNORM;
  485.                 orig=st;
  486.                 break;
  487.  
  488.             case DOTEL:        /* received a telnet DO negotiation */
  489. #ifdef DEBUG
  490.                 printf("RECV: %s %s\n",telstates[telstate[comm_port]-SE],teloptions[*st]);
  491. #endif
  492.                 switch(*st) {
  493.                     case SGA:        /* Suppress go-ahead */
  494.                         if(igoahead[comm_port]) { /* suppress go-ahead */
  495. #ifdef DEBUG
  496.                             printf("SEND: %s %s\n",telstates[WILLTEL-SE],teloptions[*st]);
  497. #endif
  498.                             sprintf(parsedat,"%c%c%c",IAC,WILLTEL,*st);
  499.                             netwrite(pnum[comm_port],parsedat,3);  /* take it */
  500.                             igoahead[comm_port]=1;
  501.                           }
  502. #ifdef DEBUG
  503.                         else
  504.                             printf("NO REPLY NEEDED: %s %s\n",telstates[WILLTEL-SE],teloptions[SGA]);
  505. #endif
  506.                         telstate[comm_port]=STNORM;
  507.                         orig=++st;
  508.                         break;
  509.  
  510.                     default:
  511. #ifdef DEBUG
  512.                         printf("SEND: %s %s\n",telstates[WONTTEL-SE],teloptions[*st]);
  513. #endif
  514.                         sprintf(parsedat,"%c%c%c",IAC,WONTTEL,*st++);
  515.                         netwrite(pnum[comm_port],parsedat,3);  /* refuse it */
  516.                         telstate[comm_port]=STNORM;
  517.                         orig=st;
  518.                           break;
  519.  
  520.                 }
  521.                 break;
  522.  
  523.             case DONTTEL:        /* Received a telnet DONT option */
  524. #ifdef DEBUG
  525.                 printf("RECV: %s %s\n",telstates[telstate[comm_port]-SE],teloptions[*st]);
  526. #endif
  527.                 telstate[comm_port]=STNORM;
  528.                 orig=++st;
  529.                 break;
  530.  
  531.             case WILLTEL:        /* received a telnet WILL option */
  532. #ifdef DEBUG
  533.                 printf("RECV: %s %s\n",telstates[telstate[comm_port]-SE],teloptions[*st]);
  534. #endif
  535.                 telstate[comm_port]=STNORM;
  536.                 switch(*st++) {
  537.                     case SGA:                    /* suppress go-ahead */
  538.                         if(ugoahead[comm_port])
  539.                             break;
  540.  
  541.                         ugoahead[comm_port]=1;
  542. #ifdef DEBUG
  543.                         printf("SEND: %s %s\n",telstates[DOTEL-SE],teloptions[*st]);
  544. #endif
  545.                         sprintf(parsedat,"%c%c%c",IAC,DOTEL,3);    /* ack */
  546.                         netwrite(pnum[comm_port],parsedat,3);
  547.                         break;
  548.  
  549.                     case ECHO:                        /* echo */
  550.                         if(echo[comm_port])
  551.                             break;
  552.  
  553.                         echo[comm_port]=1;
  554. #ifdef DEBUG
  555.                         printf("SEND: %s %s\n",telstates[DOTEL-SE],teloptions[*st]);
  556. #endif
  557.                         sprintf(parsedat,"%c%c%c",IAC,DOTEL,1);    /* ack */
  558.                         netwrite(pnum[comm_port],parsedat,3);
  559.                         break;
  560.  
  561.                     case TIMING:        /* Timing mark */
  562.                         timing[comm_port]=0;
  563.                         break;
  564.  
  565.                     default:
  566. #ifdef DEBUG
  567.                         printf("SEND: %s %s\n",telstates[DONTTEL-SE],teloptions[*st]);
  568. #endif
  569.                         sprintf(parsedat,"%c%c%c",IAC,DONTTEL,*(st-1));
  570.                         netwrite(pnum[comm_port],parsedat,3);  /* refuse it */
  571.                         break;
  572.                   } /* end switch */
  573.                 orig=st;
  574.                 break;
  575.                             
  576.             case WONTTEL:        /* Received a telnet WONT option */
  577. #ifdef DEBUG
  578.                 printf("RECV: %s %s\n",telstates[telstate[comm_port]-SE],teloptions[*st]);
  579. #endif
  580.                 telstate[comm_port]=STNORM;
  581.                 switch(*st++) {            /* which option? */
  582.                     case ECHO:                /* echo */
  583.                         if(echo[comm_port])
  584.                             break;
  585.  
  586.                         echo[comm_port]=0;
  587.                         sprintf(parsedat,"%c%c%c",IAC,DONTTEL,ECHO);
  588.                         netwrite(pnum[comm_port],parsedat,3);  /* OK with us */
  589.                         break;
  590.  
  591.                     case TIMING:    /* Telnet timing mark option */
  592.                         timing[comm_port]=0;
  593.                         break;
  594.  
  595.                     default:
  596.                         break;
  597.                   }
  598.                 orig=st;
  599.                 break;
  600.  
  601.             case SB:        /* telnet sub-options negotiation */
  602.                 telstate[comm_port]=NEGOTIATE;
  603.                 orig=st;
  604.                 i=substate[comm_port]=0;               /* Defined for each */
  605.                 break;
  606.  
  607.             case NEGOTIATE:
  608.                 if(substate[comm_port]<200) {
  609.                     switch(*st) {
  610.                         case IAC:
  611.                             if(*(st+1)==IAC) {    /* skip over double IAC's */
  612.                                 parsedat[i++]=*st++;
  613.                                 parsedat[i++]=*st++;
  614.                               } /* end if */
  615.                             else {
  616.                                 parsedat[i]='\0';
  617.                                 substate[comm_port]=*st++;
  618.                               } /* end else */
  619.                             break;
  620.  
  621.                         default:
  622.                             parsedat[i++]=*st++;
  623.                             break;
  624.                       }    /* end switch */
  625.                   }    /* end if */
  626.                 else {
  627.                     switch(substate[comm_port]) {
  628.                         case IAC:
  629.                             substate[comm_port]=*st++;
  630.                             orig=st;
  631.                             telstate[comm_port]=STNORM;
  632.                             break;
  633.  
  634.                         default:
  635.                             orig=st;
  636.                             telstate[comm_port]=STNORM;
  637.                             break;
  638.                       }    /* end switch */
  639.                   }    /* end else */
  640.                 break;
  641.  
  642.             default:
  643.                 telstate[comm_port]=STNORM;
  644.                 break;
  645.         }
  646.  
  647. /*
  648. * quick scan of the remaining string, skip chars while they are
  649. * uninteresting
  650. */
  651.         if(telstate[comm_port]==STNORM) {
  652. /*
  653. *  skip along as fast as possible until an interesting character is found
  654. */
  655.             while(st<mark && *st!=27 && *st<IAC) {
  656. /* #ifdef EIGHT_BIT_CLEAN */
  657. /*                if(!tw->binary) */
  658.                     *st &= 127;                    /* mask off high bit */
  659. /* #endif */
  660.                 st++;
  661.               }
  662.             if(!timing[comm_port] && st>orig)
  663.                 int14parsewrite(comm_port,orig,st-orig);
  664.             orig=st;                /* forget what we have sent already */
  665.             if(st<mark)
  666.                 switch (*st) {
  667.                     case IAC:            /* telnet IAC */
  668.                         telstate[comm_port]=IACFOUND;
  669.                         st++;
  670.                         break;
  671.  
  672.                     case 27:            /* ESCape code */
  673.                         if(st==mark-1 || *(st+1)==12 || *(st+1)=='^')
  674.                             telstate[comm_port]=ESCFOUND;
  675.                         st++;            /* strip or accept ESC char */
  676.                         break;
  677.  
  678. #ifdef DEBUG
  679.                     default:
  680. #ifdef QAK
  681.                         vprint(cv," strange char>128\r\n");
  682. #else
  683.                         puts("strange char>128\n");
  684. #endif
  685.                         st++;
  686.                         break;
  687. #endif
  688.                   }    /* end switch */
  689.           }    /* end if */
  690.     }  /* end while */
  691. #ifdef QAK
  692. puts("leaving int14parse()");
  693. #endif
  694. }
  695.  
  696. /*********************************************************************/
  697. /*  int14parsewrite
  698. *   write out some chars from parse
  699. *   Has a choice of where to send the stuff
  700. */
  701. void int14parsewrite(int comm_port,char *dat,int len)
  702. {
  703.     int i;      /* local counting variable */
  704.  
  705.     for(i=0; i<len; i++) {
  706. #ifdef QAK
  707. buffer_stat++;
  708. if(buffer_stat>max_buffer_stat)
  709.     max_buffer_stat=buffer_stat;
  710. printf("buffer_stat=%d, max_buffer_stat=%d\n",buffer_stat,max_buffer_stat);
  711. #endif
  712. #ifdef DEBUG
  713. printf("data_end[%d]=%p, data_begin[%d]=%p\n",comm_port,data_end[comm_port],comm_port,data_begin[comm_port]);
  714. #endif
  715.         *data_end[comm_port]++=dat[i];    /* store the character in the appropriate character buffer */
  716.         if(data_end[comm_port]>=data_max[comm_port])    /* check if we went off the end of the buffer */
  717.             data_end[comm_port]=data_start[comm_port];  /* wrap back to the beginning */
  718.         if(data_end[comm_port]==data_begin[comm_port]) {    /* check if we are going to wrap around */
  719. #ifdef DEBUG
  720. printf("data_end[%d] pushed data_begin[%d]\n",comm_port,comm_port);
  721. #endif
  722.             data_begin[comm_port]++;    /* lose data at the beginning of the buffer */
  723.             if(data_begin[comm_port]>=data_max[comm_port])    /* check if we went off the end of the buffer */
  724.                 data_begin[comm_port]=data_start[comm_port];   /* wrap back to the beginning */
  725.           } /* end if */
  726.       } /* end for */
  727. #ifdef DEBUG
  728. printf("b:data_end[%d]=%p, data_begin[%d]=%p\n",comm_port,data_end[comm_port],comm_port,data_begin[comm_port]);
  729. #endif
  730. }
  731.  
  732. /*********************************************************************/
  733. /*  get_comm_char
  734. *   used by the interrupt service routine to get characters from the
  735. *       comm. buffers
  736. */
  737. int get_comm_char(int comm_port)
  738. {
  739.     int i;      /* local counting variable */
  740.  
  741.     while(data_end[comm_port]==data_begin[comm_port]);  /* wait for a character */
  742. #ifdef QAK
  743. buffer_stat--;
  744. #endif
  745.     i=*data_begin[comm_port]++;
  746.     if(data_begin[comm_port]>=data_max[comm_port])
  747.         data_begin[comm_port]=data_start[comm_port];
  748.     return(i);
  749. }
  750.  
  751. /*********************************************************************/
  752. /*  int14netsleep
  753. *   manage the network in the background, grabs packets from the network
  754. *   Has a choice of where to send the stuff
  755. */
  756. void int14netsleep(void)
  757. {
  758.     int ev,what,dat;
  759.     char *errmsg;
  760.  
  761. #ifdef DEBUG
  762. printf("int14netsleep().a: stackavail=%u\n",stackavail());
  763. #endif
  764. /*
  765. *  get event from network, these two classes return all of the events
  766. *  of user interest.
  767. */
  768. #ifdef QAK
  769.     ev=Sgetevent(USERCLASS | CONCLASS | ERRCLASS,&what,&dat);
  770. #else
  771.     ev=Sgetevent(CONCLASS | ERRCLASS,&what,&dat);
  772. #endif
  773.     if(!ev) {
  774. #ifdef DEBUG
  775. printf("int14netsleep().b: stackavail=%u\n",stackavail());
  776. #endif
  777.         return;
  778.       } /* end if */
  779.     if(what==ERRCLASS) {                /* error event */
  780.         errmsg=neterrstring(dat);
  781. #ifdef QAK
  782.         puts(errmsg);       /* ifdef'ed out because of messing up DOS */
  783. #endif
  784.       }
  785.     else
  786.         if(what==CONCLASS) {        /* event of user interest */
  787.             switch (ev) {
  788.                 case CONOPEN:               /* connection opened or closed */
  789. #ifdef DEBUG
  790. puts("CONOPEN received");
  791. #endif
  792.                     netpush(dat);           /* negotiation */
  793.                     netwrite(dat,"\377\375\001\377\375\003\377\374\030",9);
  794.                     break;
  795.  
  796.                 default:
  797.                     break;
  798.  
  799.                 case CONDATA:               /* data arrived for me */
  800. #ifdef OLD_WAY
  801.                     cnt=netread(dat,buf,80);
  802.                     for(i=0; i<cnt; i++)
  803.                         if(buf[i]<128)
  804.                             putchar(buf[i]);
  805. #else
  806.                     if(int14process(comm_port_index[dat]))
  807.                         c=16;       /* break out of the loop */
  808. #endif
  809.                     break;
  810.  
  811.                 case CONFAIL:
  812. #ifdef DEBUG
  813. puts("CONFAIL received");
  814. #endif
  815.                     puts("Connection attempt failed");
  816.                                         /* drop through to exit */
  817.  
  818.                 case CONCLOSE:
  819. #ifdef DEBUG
  820. puts("CONCLOSE received");
  821. #endif
  822. #ifdef QAK
  823.                     netshut();
  824.                     exit(1);
  825. #else
  826.                     c=16;
  827. #endif
  828.                 }
  829.             }
  830. #ifdef QAK
  831.         else
  832.             if(what==USERCLASS) {
  833.                 switch (ev) {
  834.                     case DOMOK:                         /* domain worked */
  835. #ifdef DEBUG
  836. puts("DOMOK received");
  837. #endif
  838.                         mp=Slooknum(dat);               /* get machine info */
  839.                         pnum[PORT]=Snetopen(mp,23);           /* open to host name */
  840.                         break;
  841.  
  842.                     case DOMFAIL:   /* domain failed */
  843. #ifdef DEBUG
  844.                         n_puts("domain failed");
  845. #endif
  846. #ifdef QAK
  847.                         netshut();
  848.                         exit(1);
  849. #else
  850.                         c=16;
  851. #endif
  852.                     default:
  853.                         break;
  854.                   }
  855.               }
  856. #endif
  857. #ifdef DEBUG
  858. printf("int14netsleep().c: stackavail=%u\n",stackavail());
  859. #endif
  860. }
  861.  
  862. /*
  863. *    main ( argc, argv )
  864. *
  865. *    Entry : 
  866. *
  867. *        parameter 1 : machine name
  868. *
  869. */
  870.  
  871. /* #define TSR
  872. #define PORT 1 */
  873.  
  874. int main(argc,argv)
  875. int argc;
  876. char *argv[];
  877. {
  878.     union REGS inregs;      /* register set going into the interrupt */
  879.     union REGS outregs;     /* register set going out of the interrupt */
  880.     int i,cnt,ev,what,dat,
  881.         exec_num;           /* the argument number which is the name of the file to execute */
  882.     unsigned int str_length;
  883.     char *errmsg,
  884.         file_name[_MAX_PATH],
  885.         *str;
  886.  
  887. #ifdef __TURBOC__
  888.     fnsplit(argv[0],path_name,buf,temp_str,temp_data);
  889. #else
  890.     _splitpath(argv[0],path_name,buf,temp_str,temp_data);   /* split the full path name of net14.exe into it's components */
  891. #endif
  892.     strcat(path_name,buf);    /* append the real path name to the drive specifier */
  893.  
  894.  
  895.     config = (getenv("CONFIG.TEL"));    /* check for a config.tel in the environment */
  896.     if(config)                  /* set a different config.tel file */
  897.         Shostfile(config);
  898.  
  899. #ifdef QAK
  900.     puts("National Center for Supercomputing Applications");    /* put the banner on the screen */
  901.     puts("Interrupt 14h driver");
  902.     puts("January 1991\n");
  903. #endif
  904.  
  905. #ifndef TSR
  906.     if(argc<2) {
  907.         puts("Usage: net14 [-h hostfile] childname [child_param]\n");
  908.         exit(1);
  909.       } /* end if */
  910. #endif
  911. /*
  912. *  work on parms
  913. */
  914.     for(i=1; i<argc; i++) {            /* look at each parm */
  915.         if(*argv[i]=='-') {     /* command line parameter */
  916.             switch(*(argv[i]+1)) {
  917.                 case 'h':
  918.                     Shostfile(argv[++i]);    /* set new name for host file */
  919.                     break;
  920.  
  921.                 case 'D':   /* turn on debugging */
  922.                     debug=1;
  923.                     break;
  924.  
  925.                 default:
  926.                     puts("Usage: net14 [-h hostfile] filename [param]\n");
  927.                     exit(1);
  928.               }
  929.           }
  930.         else {  /* must be the name of the file to execute */
  931.             exec_num=i;     /* save the argument number of the name to execute */
  932.             break;          /* break out of the loop (any further arguments must pertain to the program to execute) */
  933.           } /* end else */
  934.       }
  935.  
  936.     if(!int14init())    /* install the network stuff */
  937.         exit(1);
  938.  
  939.     for(i=0; i<NUM_COMM_PORTS; i++) {    /* initialize the port buffers */
  940.         data_begin[i]=port_data[i];     /* start at the beginning of the buffer */
  941.         data_end[i]=port_data[i];       /* set the end of the buffer at the beginning currently */
  942.         data_start[i]=port_data[i];     /* set the start of each buffer */
  943.         data_max[i]=port_data[i]+PORT_DATA_SIZE;    /* set the maximum value the buffer can use */
  944. #ifdef DEBUG
  945. printf("%d: data_begin=%p, data_max=%p, data_end=%p\n",i,data_begin[i],data_max[i],data_end[i]);
  946. #endif
  947.       } /* end for */
  948.  
  949.     for(i=0; i<NPORTS; i++)     /* initialize the comm port indices */
  950.         comm_port_index[i]=-1;
  951.  
  952. #ifdef DEBUG
  953. printf("data_begin[2]=[%x][%x]\n",(unsigned)(*((unsigned *)&data_begin[2])),(unsigned)(*(((unsigned *)&data_begin[2])+1)));
  954. #endif
  955.  
  956.     int14inst();        /* install the int 14h handler */
  957. #ifdef QAK
  958. printf("int14 =%p\n",_dos_getvect(0x14));
  959. #endif
  960.  
  961. /* #ifndef TSR */
  962.     timeinst();         /* install the timer interrupt handler */
  963. /* #endif */
  964. #ifdef QAK
  965. printf("int1C =%p\n",_dos_getvect(0x1C));
  966. #endif
  967.  
  968. #ifdef TSR
  969.     inregs.h.ah=0;          /* set to initialize the comm. port */
  970.     inregs.x.dx=PORT;          /* use port two */
  971.     int86(SERIAL,&inregs,&outregs);     /* call to initialize the interrupt */
  972.  
  973.     inregs.h.ah=1;          /* set to send a character */
  974.     inregs.h.al=2;          /* send initialization character */
  975.     inregs.x.dx=PORT;          /* use port two */
  976.     int86(SERIAL,&inregs,&outregs);     /* call to initialize the interrupt */
  977.  
  978.     str=argv[1];
  979.     str_length=strlen(str);
  980.     for(i=0; i<(int)str_length; i++,str++) {
  981.         inregs.h.ah=1;          /* set to send a character */
  982.         inregs.h.al=*str;       /* send name character */
  983.         inregs.x.dx=PORT;          /* use port two */
  984.         int86(SERIAL,&inregs,&outregs);     /* call to initialize the interrupt */
  985.       } /* end for */
  986.  
  987.     inregs.h.ah=1;          /* set to send a character */
  988.     inregs.h.al=3;          /* send initialization character */
  989.     inregs.x.dx=PORT;          /* use port two */
  990.     int86(SERIAL,&inregs,&outregs);     /* call to initialize the interrupt */
  991.  
  992. #ifdef QAK
  993.     if(!int14open(argv[1]),2)    /* open session to the specified machine */
  994.         exit(1);
  995. #endif
  996.  
  997.     c = 0;
  998.     do {
  999.         if(kbhit()) {               /* has key been pressed */
  1000.             c=(char)getch();
  1001. if(c==16)
  1002.     break;
  1003. if(c==14)
  1004. #ifdef QAK
  1005.     printf("max_buffer_stat=%d\n",max_buffer_stat);
  1006. #else
  1007.     printf("stackavail()=%u\n",stackavail());
  1008. #endif
  1009.             inregs.h.ah=1;          /* set to send a character */
  1010.             inregs.h.al=c;          /* send character */
  1011.             inregs.x.dx=PORT;          /* use port two */
  1012.             int86(SERIAL,&inregs,&outregs);     /* call to initialize the interrupt */
  1013.           }
  1014. #ifdef QAK
  1015. int14netsleep();            /* call this to maintain network */
  1016. #endif
  1017. #ifdef QAK
  1018.         inregs.h.ah=3;          /* set to check status */
  1019.         inregs.x.dx=PORT;          /* use port two */
  1020.         int86(SERIAL,&inregs,&outregs);     /* call to initialize the interrupt */
  1021.         if(outregs.h.ah&0x01) { /* check for data being ready */
  1022.             inregs.h.ah=2;          /* set to receive a character */
  1023.             inregs.x.dx=PORT;          /* use port two */
  1024.             int86(SERIAL,&inregs,&outregs);     /* call to initialize the interrupt */
  1025.             c=(int)outregs.h.al;         /* get the return value */
  1026.             putchar(c);
  1027.           } /* end if */
  1028. #else
  1029.         dat=int14check();
  1030.         if(dat&0x0100) {        /* chek for data begin ready */
  1031.             c=int14receive();
  1032.             putchar(c);
  1033.           } /* end if */
  1034. #endif
  1035.       } while(c!=16);            /* Ctrl-P, arbitrary escape */
  1036. #ifdef QAK
  1037. printf("max_buffer_stat=%d\n",max_buffer_stat);
  1038. #endif
  1039.     timedeinst();   /* remove the timer interrupt handler */
  1040.     int14deinst();  /* remove the int 14h handler */
  1041.     netclose(pnum[PORT]);
  1042.     netshut();
  1043. #else
  1044. #ifdef QAK
  1045.     go_tsr();
  1046. #else
  1047. #ifdef QAK
  1048. printf("sizeof(struct port)=%d\n",sizeof(struct port));
  1049. #endif
  1050.     str=malloc(12000);      /* malloc a large chunk of memory */
  1051.     free(str);      /* just to get it into the memory pool */
  1052.     str=malloc(_MAX_PATH);
  1053.     strupr(argv[exec_num]);
  1054.     _searchenv(argv[exec_num],"PATH",file_name);  /* get the pathname of the file to execute */
  1055.     if(file_name[0]=='\0') {  /* couldn't find the executable in the path, is must be in the current directory */
  1056.         strcpy(str,argv[exec_num]);
  1057.         strcat(str,".COM");
  1058.         _searchenv(str,"PATH",file_name);  /* get the pathname of the file to execute */
  1059.         if(file_name[0]=='\0') {  /* couldn't find the executable in the path, is must be in the current directory */
  1060.             strcpy(str,argv[exec_num]);
  1061.             strcat(str,".EXE");
  1062.             _searchenv(str,"PATH",file_name);  /* get the pathname of the file to execute */
  1063.             if(file_name[0]=='\0')  /* couldn't find the executable in the path, is must be in the current directory */
  1064.                 getcwd(file_name,_MAX_PATH);
  1065.           } /* end if */
  1066.       } /* end if */
  1067.     i=spawnvp(P_WAIT,file_name,&argv[exec_num]);   /* call the program which needs the re-direction */
  1068.     free(str);
  1069.     if(i==(-1)) {       /* check for error spawning the process */
  1070.         switch(errno) { /* find out what the problem was */
  1071.             case E2BIG:     /* argument list too long to child process */
  1072.                 puts("Error: bad argument list to child process\n");
  1073.                 break;
  1074.  
  1075.             case EINVAL:    /* the execution mode was invalid */
  1076.                 puts("Error: invalid execution mode for child process\n");
  1077.                 break;
  1078.  
  1079.             case ENOENT:    /* file not found to spawn */
  1080.                 puts("Error: child process not found\n");
  1081.                 break;
  1082.  
  1083.             case ENOEXEC:   /* not an executable file */
  1084.                 puts("Error: child process is not an executable file\n");
  1085.                 break;
  1086.  
  1087.             case ENOMEM:    /* not enough memory to spawn process */
  1088.                 puts("Error: not enough memory for child process\n");
  1089.                 break;
  1090.           } /* end switch() */
  1091.       } /* end if */
  1092.     timedeinst();   /* remove the timer interrupt handler */
  1093.     int14deinst();  /* remove the int 14h handler */
  1094.     netshut();
  1095. #endif
  1096. #endif
  1097.     exit(0);
  1098. }
  1099.  
  1100. #ifdef QAK
  1101. /*
  1102. *    errhandle ()
  1103. *
  1104. *    Write error messages to the console window
  1105. *
  1106. */
  1107. void errhandle(void )
  1108. {
  1109.     char *errmsg;
  1110.     int i,j;
  1111.  
  1112.     while(ERR1==Sgetevent(ERRCLASS,&i,&j)) {
  1113.         errmsg=neterrstring(j);
  1114.         puts(errmsg);
  1115.       }
  1116. }
  1117. #endif
  1118.  
  1119.