home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / MISC / NETWORK / TEL23SRC.ZIP / ENGINE / LOOK.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-08-20  |  80.7 KB  |  3,014 lines

  1. /*
  2. *    LOOK.C
  3. *    User interface code for NCSA Telnet
  4. ****************************************************************************
  5. *                                                                          *
  6. *      NCSA Telnet for the PC                                              *
  7. *      by Tim Krauskopf, VT100 by Gaige Paulsen, Tek by Aaron Contorer     *
  8. *                                                                          *
  9. *      National Center for Supercomputing Applications                     *
  10. *      152 Computing Applications Building                                 *
  11. *      605 E. Springfield Ave.                                             *
  12. *      Champaign, IL  61820                                                *
  13. *                                                                          *
  14. *      This program is in the public domain.                               *
  15. *                                                                          *
  16. ****************************************************************************
  17. *   Revisions:
  18. *   10/1/87  Initial source release, Tim Krauskopf
  19. *   7/5/88   Version 2.2 Tim Krauskopf
  20. *      5/8/89     Version 2.3 Heeren Pathak & Quincey Koziol
  21. *   1/21/91  Version 2.3 Chris Wilson & Quincey Koziol
  22. *   6/19/91  Version 2.3 - Linemode reworked - Jeff Wiedemeier
  23. */
  24.  
  25. #define UM
  26. #define WINMASTER
  27. #define REALTIME
  28.  
  29. #define NUMLMODEOPTIONS 30
  30. /* #define NEGOTIATEDEBUG /* define this to enable -d option for console file */
  31.                                                                                                         /* and hex dump of incoming data                    */
  32.  
  33. #define USETEK 
  34. /* #define USERAS */
  35. #define HTELNET 23
  36. /*#define DEBUG*/
  37.  
  38. #define LMODE        /* to compile with LINEMODE enabled */
  39.  
  40. #ifndef USETEK
  41. #define leavetek() 0
  42. #endif
  43.  
  44. #ifdef MSC
  45. #define mousecl mousecml
  46. #endif
  47.  
  48. #ifdef __TURBOC__
  49. #include "turboc.h"
  50. #endif
  51. #ifdef MOUSE
  52. #include "mouse.h"
  53. #endif
  54. #include <stdlib.h>
  55. #include <string.h>
  56. #include <stdio.h>
  57. #include <fcntl.h>
  58. #include <ctype.h>
  59. #include <direct.h>
  60. #include <time.h>
  61. #include <conio.h>
  62. #include <process.h>
  63. #include <stdarg.h>
  64. #include <bios.h>
  65. #ifdef MSC
  66. #include <malloc.h>
  67. #endif
  68. #ifdef MEMORY_DEBUG
  69. #include "memdebug.h"
  70. #endif
  71.  
  72. #include "whatami.h"
  73. #include "nkeys.h"
  74. #include "windat.h"
  75. #include "hostform.h"
  76. #include "protocol.h"
  77. #include "data.h"
  78. #include "externs.h"
  79.  
  80. FILE *tekfp, *mem_file;
  81. extern int localprint;
  82. extern int default_mapoutput;
  83. int sound_on=0;
  84.  
  85. long size,                /* size of buffer */
  86.     cstart,                /* starting location of VS copy buffer */
  87.     cend,                /* ending location of VS copy buffer */
  88.     cdist,                /* distance to base point */
  89.     temp;
  90.  
  91. int stand=0,
  92.     basetype = VTTYPE,
  93.     ftpact=0,                    /* ftp transfer is active */
  94.     rcpact=0,                    /* rcp transfer is active */
  95.     viewmode=0,                    /* What are we looking at? */
  96.     ftpok=1,                    /* is file transfer enabled? */
  97.     rcpok=1,                    /* remote copying enabled? */
  98.     scroll,                        /* which way do we scrool */
  99.     cflag=0,                    /* are we copying ? */
  100.     cbuf=0,                        /* do we have things in the buffer? */
  101.     mcflag,                        /* mouse button flag */
  102.     ginon=0,                    /* the tektronics Graphics INput (GIN) mode flag */
  103.     vsrow=0,                    /* VS row */
  104.     mighty,                        /* mouse present? */    
  105.     temptek,                    /* where drawings go by default */
  106.     indev,outdev,                /* for copying tek images */
  107.     rgdevice=0,                    /* tektronix device to draw on */
  108.     bypass_passwd=0,            /* flag whether to bypass the password check for ftp'ing back to our own machine */
  109.     vton=1,
  110.     capon=0,                    /* overall capture on or not */
  111.     foundbreak=0,                /* trap Ctrl-C */
  112.     machparm=0,
  113.     domacro=-1,
  114.     use_mouse=0,                /* use mouse for scrolling toggle */
  115.     console_file_wanted=0;            /* should console be written to file ? */
  116.  
  117. extern int beep_notify;
  118. int save_screen = TRUE;
  119.  
  120. unsigned char s[550],parsedat[256],
  121.     temp_str[128],
  122.     path_name[_MAX_DRIVE+_MAX_DIR],        /* character storage for the path name */
  123.     colors[NCOLORS] = {2,1,0x70,0},        /* base colors */
  124.     myipnum[4],
  125.     *copybuf,
  126.     *lineend = {"\r\n"},
  127.     *blankline = {"                                                                                       "};
  128.  
  129. time_t oldtime;                    /* the last time the clock was updated */
  130.  
  131.  
  132. long int lastt;
  133.  
  134. extern struct config def;        /* Default settings obtained from host file */
  135.  
  136. struct machinfo *mp=NULL;        /* Pointer to a machine information structure */
  137.  
  138. void (*attrptr)(int );            /* pointer to the routine to change the attribute of a character on the screen */
  139.  
  140. #define PSDUMP 128
  141.  
  142. /* Definitions for telnet protocol */
  143.  
  144. #define STNORM        0
  145.  
  146. #define TEL_EOF    36
  147. #define SUSP 237
  148. #define ABORT 238
  149. #define SE            240
  150. #define NOP            241
  151. #define DM            242
  152. #define BREAK        243
  153. #define IP            244
  154. #define AO            245
  155. #define AYT            246
  156. #define EC            247
  157. #define EL            248
  158. #define GOAHEAD     249
  159. #define SB            250
  160. #define WILLTEL     251
  161. #define WONTTEL     252
  162. #define DOTEL         253
  163. #define DONTTEL     254
  164. #define IAC             255
  165.  
  166.  
  167. /* Assigned Telnet Options */
  168. #define BINARY                 0
  169. #define ECHO                1
  170. #define RECONNECT            2
  171. #define SGA                 3
  172. #define AMSN                4
  173. #define STATUS                5
  174. #define TIMING                6
  175. #define RCTAN                7
  176. #define OLW                    8
  177. #define OPS                    9
  178. #define OCRD                10
  179. #define OHTS                11
  180. #define OHTD                12
  181. #define OFFD                13
  182. #define OVTS                14
  183. #define OVTD                15
  184. #define OLFD                16
  185. #define XASCII                17
  186. #define LOGOUT                18
  187. #define BYTEM                19
  188. #define DET                    20
  189. #define SUPDUP                21
  190. #define SUPDUPOUT            22
  191. #define SENDLOC                23
  192. #define TERMTYPE             24
  193. #define EOR                    25
  194. #define TACACSUID            26
  195. #define OUTPUTMARK            27
  196. #define TERMLOCNUM            28
  197. #define REGIME3270            29
  198. #define X3PAD                30
  199. #define NAWS                31
  200. #define TERMSPEED            32
  201. #define TFLOWCNTRL            33
  202. #define LINEMODE             34
  203.     #define MODE 1
  204.         #define EDIT     1
  205.         #define TRAPSIG  2
  206.         #define MODE_ACK 4
  207.         #define SOFT_TAB    8
  208.         #define LIT_ECHO    16
  209.  
  210.     #define FORWARDMASK 2
  211.  
  212.     #define SLC 3 
  213.         #define NO_SUPPORT        0
  214.         #define CANTCHANGE        1
  215.         #define SLC_VALUE        2
  216.         #define SLC_DEFAULT        3
  217.         #define SLC_LEVELBITS    3
  218.         #define SLC_ACK            128
  219.  
  220.         #define SLC_SYNCH        1
  221.         #define SLC_BRK            2
  222.         #define SLC_IP            3
  223.         #define SLC_AO            4
  224.         #define SLC_AYT            5
  225.         #define SLC_EOR            6
  226.         #define SLC_ABORT        7
  227.         #define SLC_EOF            8
  228.         #define SLC_SUSP        9
  229.         #define SLC_EC            10
  230.         #define SLC_EL           11
  231.         #define SLC_EW           12
  232.         #define SLC_RP            13
  233.         #define SLC_LNEXT        14
  234.         #define SLC_XON            15
  235.         #define SLC_XOFF        16
  236.         #define SLC_FORW1        17
  237.         #define SLC_FORW2        18
  238.         #define SLC_MCL    19
  239.         #define SLC_MCR    20
  240.         #define SLC_MCWL    21
  241.         #define SLC_MCWR    22
  242.         #define SLC_MCBOL    23
  243.         #define SLC_MCEOL    24
  244.         #define    SLC_INSRT    25
  245.         #define SLC_OVER    26
  246.         #define SLC_ECR    27
  247.         #define    SLC_EWR    28
  248.         #define SLC_EBOL    29
  249.         #define SLC_EEOL    30
  250.  
  251. #define XDISPLOC            35
  252. #define XOPTIONS            255
  253.  
  254.     
  255. #define ESCFOUND 5
  256. #define IACFOUND 6
  257. #define NEGOTIATE 1
  258.  
  259. char *telstates[]={
  260.     "Subnegotiation End",
  261.     "NOP",
  262.     "Data Mark",
  263.     "Break",
  264.     "Interrupt Process",
  265.     "Abort Output",
  266.     "Are You There",
  267.     "Erase Character",
  268.     "Erase Line",
  269.     "Go Ahead",
  270.     "Subnegotiate",
  271.     "Will",
  272.     "Won't",
  273.     "Do",
  274.     "Don't"
  275. };
  276.  
  277. char *teloptions[256]={
  278.     "Binary",                /* 0 */
  279.     "Echo",
  280.     "Reconnection",
  281.     "Supress Go Ahead",
  282.     "Message Size Negotiation",
  283.     "Status",                /* 5 */
  284.     "Timing Mark",
  285.     "Remote Controlled Trans and Echo",
  286.     "Output Line Width",
  287.     "Output Page Size",
  288.     "Output Carriage-Return Disposition",    /* 10 */
  289.     "Output Horizontal Tab Stops",
  290.     "Output Horizontal Tab Disposition",
  291.     "Output Formfeed Disposition",
  292.     "Output Vertical Tabstops",
  293.     "Output Vertical Tab Disposition",        /* 15 */
  294.     "Output Linefeed Disposition",
  295.     "Extended ASCII",
  296.     "Logout",
  297.     "Byte Macro",
  298.     "Data Entry Terminal",                    /* 20 */
  299.     "SUPDUP",
  300.     "SUPDUP Output",
  301.     "Send Location",
  302.     "Terminal Type",
  303.     "End of Record",                        /* 25 */
  304.     "TACACS User Identification",
  305.     "Output Marking",
  306.     "Terminal Location Number",
  307.     "3270 Regime",
  308.     "X.3 PAD",                                /* 30 */
  309.     "Negotiate About Window Size",
  310.     "Terminal Speed",
  311.     "Toggle Flow Control",
  312.     "Linemode",
  313.     "X Display Location",                    /* 35 */
  314.     "36","37","38","39",
  315.     "40","41","42","43","44","45","46","47","48","49",
  316.     "50","51","52","53","54","55","56","57","58","59",
  317.     "60","61","62","63","64","65","66","67","68","69",
  318.     "70","71","72","73","74","75","76","77","78","79",
  319.     "80","81","82","83","84","85","86","87","88","89",
  320.     "90","91","92","93","94","95","96","97","98","99",
  321.     "100","101","102","103","104","105","106","107","108","109",
  322.     "110","111","112","113","114","115","116","117","118","119",
  323.     "120","121","122","123","124","125","126","127","128","129",
  324.     "130","131","132","133","134","135","136","137","138","139",
  325.     "140","141","142","143","144","145","146","147","148","149",
  326.     "150","151","152","153","154","155","156","157","158","159",
  327.     "160","161","162","163","164","165","166","167","168","169",
  328.     "170","171","172","173","174","175","176","177","178","179",
  329.     "180","181","182","183","184","185","186","187","188","189",
  330.     "190","191","192","193","194","195","196","197","198","199",
  331.     "200","201","202","203","204","205","206","207","208","209",
  332.     "210","211","212","213","214","215","216","217","218","219",
  333.     "220","221","222","223","224","225","226","227","228","229",
  334.     "230","231","232","233","234","235","236","237","238","239",
  335.     "240","241","242","243","244","245","246","247","248","249",
  336.     "250","251","252","253","254",
  337.     "Extended Options List"        /* 255 */
  338. };
  339.  
  340. char *LMoptions[]={
  341.     "None",
  342.     "SYNCH",
  343.     "BREAK",
  344.     "IP",
  345.     "ABORT OUTPUT",
  346.     "AYT",
  347.     "EOR",
  348.     "ABORT",
  349.     "EOF",
  350.     "SUSP",
  351.     "EC",
  352.     "EL",
  353.     "EW",
  354.     "RP",
  355.     "LNEXT",
  356.     "XON",
  357.     "XOFF",
  358.     "FORW1",
  359.     "FORW2",
  360.     "MCL",
  361.     "MCR",
  362.     "MCWL",
  363.     "MCWR",
  364.     "MCBOL",
  365.     "MCEOL",
  366.     "INSRT",
  367.     "OVER",
  368.     "ECR",
  369.     "EWR",
  370.     "EBOL",
  371.     "EEOL"
  372. };
  373.  
  374. char *LMflags[]={
  375.     "NOSUPPORT",
  376.     "CANTCHANGE",
  377.     "VALUE",
  378.     "DEFAULT"
  379. };
  380.  
  381. #ifdef IP_ENHANCEMENTS                    /* UNFINISHED message screen enhancements */
  382. char *source_ip_num;                    /* for error messages */
  383. int port_num;                            /* for error messages */
  384. #endif
  385.  
  386. #define  USAGE   printf("\n\nUsage: telnet [-s] [-n] [-t] [-c color] [-h hostfile] [machinename] ...")
  387.  
  388. main(argc,argv)
  389. int argc;
  390. char *argv[];
  391. {
  392.     int i,j;
  393.     char *config;
  394.  
  395.     numline=23;
  396.     copybuf=NULL;
  397.     machparm = 1000;            /* large number */
  398.  
  399.     config=(getenv("CONFIG.TEL"));
  400.     if(config)
  401.         Shostfile(config);
  402.  
  403. /*
  404. *  work on parms
  405. */
  406.  
  407.     examineCommandLine(argc,argv);
  408.  
  409.     if (save_screen)
  410.         init_text();
  411.  
  412. #ifdef __TURBOC__
  413.     fnsplit(argv[0],path_name,s,temp_str,parsedat);        /* split the full path name of telbin.exe into it's components */
  414. #else
  415.     _splitpath(argv[0],path_name,s,temp_str,parsedat);    /* split the full path name of telbin.exe into it's components */
  416. #endif
  417.     strcat(path_name,s);    /* append the real path name to the drive specifier */
  418.  
  419.     install_keyboard();        /* determine what kind of keyboard this is */
  420.  
  421.     save_break();            /* preserve the status of the DOS BREAK setting */
  422.     save_cursor();            /* save the user's keyboard cursor type */
  423.     time(&oldtime);
  424. #ifndef MOUSE
  425.     mighty=initmouse();
  426. #else
  427.     mighty=nm_initmouse();
  428. #endif
  429.     n_clear();                        /* do you know where your BP is? */
  430.     n_cur(0,0);
  431.     n_window(0,0,numline,79);            /* vt100 size */
  432.     n_color(2);
  433.     n_puts("NCSA Telnet 2.3.03, reading configuration file . . .");
  434.  
  435.     if(*argv[1]=='?' || argc==1) {
  436.         USAGE;
  437.         n_row();
  438.         n_puts("\n\n -c 172471    sets the basic color scheme for console screen");
  439.         n_puts(" -h file      full path specification of host information file");
  440.         n_puts(" -s           standalone (server) mode for rcp and ftp");
  441.         n_puts(" -t           disable direct writes to screen");
  442.         n_puts(" -n           disable screen restore\n");
  443.         exit(1);
  444.       }
  445.  
  446. /*
  447. * initialize the default keyboard settings
  448. */
  449.     if((j=initkbfile())<0) {    /* check for correct keyboard initialization */
  450.         printf("Error reading default settings from telnet.key\n");
  451.         printf("Please make certain this file is in the same directory as telbin.exe\n");
  452.         getch();
  453.     } /* end if */
  454.     initoutputfile();        /* initialize the output mapping */
  455.  
  456. /*
  457. * initialize network stuff
  458. */
  459.     if(j=Snetinit()) {
  460.         wrest(console);
  461.         errhandle();
  462.         printf("Error initializing network or getting configuration file\n\r");
  463.         switch (j) {
  464.             case -1:
  465.                 printf("Cannot initialize board.\n");
  466.                 break;
  467.  
  468.             case -5:
  469.                 printf("Error in config.tel file.\n");
  470.                 break;
  471.  
  472.             case -2:
  473.                 printf("RARP failed!!\n");
  474.                 break;
  475.  
  476.             case -3:
  477.                 printf("BOOTP failed!!\n");
  478.                 break;
  479.  
  480.             case -4:
  481.                 printf("X25 Initialization Failed!!\n");
  482.                 break;
  483.  
  484.             default:
  485.                 printf("Error from Snetinit()=%d\n",j);
  486.                 break;
  487.         }
  488.         if(j<-1)    /* network initialized, special case */
  489.             netshut();
  490.         exit(1);
  491.     }
  492.  
  493.     netgetip(myipnum);        /* what is my ip number? */
  494.     Sgetconfig(&def);       /* get information provided in hosts file */
  495.  
  496.     ftpok=def.ftp;                    /* what types of files transfers are allowed?*/
  497.     rcpok=def.rcp;
  498.  
  499.     /* Check to see if we need to enter 43 or 50 line mode */
  500.     if(def.ega43==1) 
  501.         numline=41;
  502.     else  if (def.ega43==2)
  503.         numline=48;
  504.     else {
  505.         numline=23;                /***** NEED TO ADD SUPPORT FOR MODE CURRENT */
  506.         ega24();
  507.     }
  508.  
  509.     n_window(0,0,numline,79);           /* vt100 size */
  510.     if(def.ega43)
  511.         ega43();
  512.     if(def.cursortop!=-1 && def.cursorbottom!=-1)
  513.         install_cursor((unsigned int)((def.cursortop<<8) | def.cursorbottom));
  514.  
  515.     if(Scmode())
  516.         attrptr=n_attr;
  517.     else
  518.         attrptr=n_biosattr;
  519.  
  520.     n_clear();
  521.  
  522.     VSsetrgn(console->vs,0,0,79,numline);
  523.     for(i=0; i<NPORTS; i++)
  524.         wins[i]=NULL;                    /* we are using no window yet */
  525.  
  526. /*
  527. * create console window for errors, informative messages, etc.
  528. */
  529.     if(0>VSinit(30))  {                /* initialize GPs virtual screens */
  530.         n_puts("Virtual screen initialization failed.");
  531.         exit(1);
  532.     } /* end if */
  533.     if(NULL==(console=creatwindow())) {
  534.         n_puts("Console memory allocation failed");
  535.         exit(1);
  536.     }
  537.     strcpy(console->mname,"Console");
  538. /*
  539. * introductions on the console window
  540. */
  541.     i=console->vs;
  542.  RSvis(-1);
  543.     vprint(i,"\n\n Console messages:\n\r\nNCSA Telnet\r\n");
  544.     vhead(i);
  545.  
  546. #ifdef USETEK
  547. /*
  548. *  install tektronix
  549. */
  550.     if(Stmode())
  551.         tekinit(def.video);
  552. #endif
  553. #ifdef USERAS
  554.     if(!VRinit())
  555.         vprint(i,"Error initializing raster support\r\n");
  556. #endif
  557. /*
  558. *  Display my Ethernet (or Appletelk) and IP address for the curious people
  559. */
  560.     pcgetaddr(&s[200],def.address,def.ioaddr);
  561.     tprintf(console->vs,"My Ethernet address: %x:%x:%x:%x:%x:%x\r\n",s[200],s[201],s[202],s[203],s[204],s[205]);
  562.     tprintf(console->vs,"My IP address: %d.%d.%d.%d\n\r\n",myipnum[0],myipnum[1],myipnum[2],myipnum[3]);
  563.  
  564.     install_break((int *)&foundbreak);        /* install our BREAK handler */
  565.  
  566.     Stask();                    /* any packets for me? (return ARPs) */
  567. /*
  568. *   With the parameters left on the command line, open a connection
  569. *   to each machine named.  Start up all of the configuration on open
  570. *   connections. 
  571. */
  572.     for(i=machparm; i<argc; i++)
  573.         addsess(argv[i]);
  574.  
  575.     if(current==NULL) {         /* special viewmode for server mode */
  576.         current=console;        /* special enter sequence avoids flicker */
  577.         viewmode=6;
  578.     }
  579.     wrest(current);             /* paint the first session's screen */
  580.     while (EXIT_TELNET!=dosessions());    /* serve all sessions, events */
  581.     endall();
  582.     return(0);
  583. }
  584.  
  585. extern char *commandLineOveride;    /* defined in confile.h */
  586.  
  587. void examineCommandLine(int argc, char *argv[])
  588. {
  589.     int i,j,size=0;
  590.  
  591.     for(i=1; i<argc; i++) {         /* look at each parm */
  592.         if(*argv[i]=='-') {
  593.             switch(*(argv[i]+1)) {
  594.                 case 'c':            /* set foreground color */
  595.                     i++;
  596.                     for(j=0; j<NCOLORS && *(argv[i]+j*2); j++)
  597.                         colors[j]=(unsigned char)hexbyte(argv[i]+j*2);
  598.                     break;
  599.  
  600.                 case 'd':
  601.                     console_file_wanted=1;
  602.                     break;
  603.  
  604.                 case 'e':
  605.                     if (commandLineOveride)
  606.                         size = strlen(commandLineOveride);
  607.                     commandLineOveride = (char *)realloc(commandLineOveride,
  608.                       strlen(commandLineOveride)+strlen(argv[++i])+3);
  609.                     *(commandLineOveride+size)=(char)NULL;
  610.                     strcat(commandLineOveride,argv[i]);
  611.                     *(commandLineOveride+strlen(commandLineOveride)+1)=(char)NULL;
  612.                     *(commandLineOveride+strlen(commandLineOveride))=';';
  613.                     break;
  614.  
  615.                 case 'n':               /* disable screen restore */
  616.                     save_screen = FALSE;
  617.                     break;
  618.  
  619.                 case 's':
  620.                     stand=1;
  621.                     break;
  622.  
  623.                 case 't':              /*  Disable direct writes to screen  */
  624.                     Scwritemode(0);
  625.                     break;
  626.  
  627.                 case 'h':
  628.                     Shostfile(argv[++i]);    /* set new name for host file */
  629.                     break;
  630.  
  631.                 default:
  632.                     USAGE;
  633.                     exit(1);
  634.             }
  635.         }
  636.         else {
  637.             if(i<machparm)
  638.                 machparm=i;            /* where first machine name is */
  639.         }
  640.     }
  641. }
  642.  
  643. /************************************************************************/
  644. /* vhead
  645. *  place the header for new sessions in.
  646. */
  647. void vhead(v)
  648. int v;
  649. {
  650.     vprint(v,"\r\nNational Center for Supercomputing Applications\r\n");
  651.     vprint(v,"NCSA Telnet for the PC version 2.3.03\r\n");
  652.     vprint(v,"\nAlt-H presents a summary of special keys \n\r\n");
  653. }
  654.  
  655. /************************************************************************/
  656. /*  dosessions
  657. *   dosessions is an infinite loop serving three sources of external
  658. *   input in order of precedence:
  659. *   - changes to the video display properties
  660. *   - keyboard strokes
  661. *   - network events
  662. *
  663. *   What the user sees is top priority followed by servicing the keyboard
  664. *   and when there is time left over, looks for network events.
  665. *
  666. *   viewmode is a state variable which can determine if the screen should
  667. *   be re-drawn, etc.
  668. */
  669.  
  670. int dosessions(void)
  671. {
  672.     static int scroll_row,scroll_col;                 /* the row and column saved while in scroll back */
  673.     time_t newtime;                    /* variable to hold the new time for the clock */
  674.     int clock_row,clock_col,        /* the row and column saved while updating the clock */
  675.         i=0,j, ginkey=0,ch,
  676.           c,                                  /* the color saved */
  677.         cl,dat,cvs;
  678.     int m1=3,m2=0,m3=0,m4=0;        /* mouse variables */
  679.     int x1,x2,y1,y2;                /* temp variables for VSgetrgn test when exiting scrlback mode */
  680.     unsigned int sw;
  681.     char gindata[5];        /* variable to store gin data in when returning fron VGgindata */
  682.     struct twin *t1;
  683.     static char lch=-1;
  684.     char *p=NULL, *outstring=NULL;
  685.  
  686.     if (ginon && current->termstate==TEKTYPE) {    /* check for GIN mode for tektronics */
  687.         ch=n_chkchar();
  688.         mousecl(&m1,&m2,&m3,&m4);
  689.         if ((ch!= -1)||(m2&1)) {
  690.             printf("ch == %d\n",ch);
  691.             if ((ch!='\r')&&(ch!='\n')&&(ch>0)) lch=(char) ch;
  692.             printf("lch %d\n",lch);
  693.             printf("mousecl returned m2== %x\n",m2);
  694.             if ((lch!= -1)&&(m2&1)) {
  695.                 printf("sending info. lch= %c\n",lch);
  696.                 VGgindata(current->vs,m3,m4,lch,gindata);    /* send the mouse cursor */
  697.                                                     /* position to be translated */
  698.                                                     /* by VGgindata and the */
  699.                                                     /* information returned */
  700.                                                     /* in gindata */
  701.  
  702. #ifndef NOT
  703.                 RSsendstring(current->vs,gindata,5);    /* return GIN data across network */
  704. #else
  705.                 printf("netwrite returned %d\n",netwrite(screens[current->vs]->pnum,gindata,5));
  706. #endif
  707.                 lch=-1;                                    /* clear last char buffer */
  708.                 resetgin();                                /* reset GIN mode */
  709.                 }                                            /* end if */
  710.           }                                                /* end if */
  711.     }
  712.  
  713.     switch(viewmode) {
  714.         case 0:                    /* no special mode, just check scroll lock */
  715.         default:
  716.             if(n_scrlck()) {    /* scroll lock prevents text from printing */
  717.                 viewmode=1;
  718.                 vsrow=0;
  719.                 cstart=0;
  720.                 cend=0;
  721.                 cflag=0;
  722.                 cbuf=0;
  723.                 mcflag=0;
  724.                 scroll_row=n_row();
  725.                 scroll_col=n_col();
  726.                 c=n_color(current->colors[1]);
  727.                 n_cur(numline+1,61);
  728.                 n_draw("Scrl",4);    /* status in lower left */
  729.                 n_color(c);
  730.                 n_cur(scroll_row,scroll_col);
  731.               }
  732. /*
  733. *  This gives precedence to the keyboard over the network.
  734. */
  735.             if ((ginon)&&(current->termstate==TEKTYPE)) break;
  736.             while(0<=(c=newkey(current)))    /* do all key translations */
  737.                 if(c==EXIT_TELNET)
  738.                     return(EXIT_TELNET);
  739.             break;            /* no special viewing characterisitics */
  740.  
  741.         case 1:                        /* scrollock is active */
  742.             if(!n_scrlck()) {
  743.                 VSgetrgn(current->vs,&x1,&y1,&x2,&y2);
  744.                 if (y1 != 0) VSsetrgn(current->vs,0,0,79,numline);
  745.                 viewmode=0;            /* set back if appropriate */
  746.                 if (y1==0) wrest(current);
  747.                 scroll=0;
  748.                 statline();
  749.                 n_cur(scroll_row,scroll_col);
  750.               }
  751. /* 
  752. *  In scroll lock mode, take keys only for the scrollback, 
  753. *  The scrollback routine will never block, so we keep servicing events.
  754. */
  755.             scrollback(current);
  756.             break;
  757.  
  758.         case 2:                        /* console is visible */
  759.             if(n_scrlck()) {    /* scroll lock prevents text from printing */
  760.                 viewmode=13;
  761.                 vsrow=0;
  762.                 cstart=0;
  763.                 cend=0;
  764.                 cflag=0;
  765.                 cbuf=0;
  766.                 mcflag=0;
  767.                 scroll_row=n_row();
  768.                 scroll_col=n_col();
  769.                 c=n_color(console->colors[1]);
  770.                 n_cur(numline+1,61);
  771.                 n_draw("Scrl",4);    /* status in lower left */
  772.                 n_color(c);
  773.                 n_cur(scroll_row,scroll_col);
  774.               }
  775.             if(0< n_chkchar())
  776.                 viewmode=10;    
  777.             break;
  778.  
  779.         case 3:                        /* help screen view1 */
  780.         case 4:                        /* help screen view2 */
  781.             while(0<=(c=n_chkchar())) {    
  782.                 if(c==EXIT_TELNET)
  783.                     return(EXIT_TELNET);
  784.                 if(viewmode==3 && c==27) {
  785.                     viewmode=4;
  786.                     help2();
  787.                 }
  788.                 else {                  /* restore view 0 */
  789.                     if(c==' ') {
  790.                         viewmode=10;
  791.                     } else
  792.                         if(c>128)
  793.                             dokey(current,c);    /* dokey might change view, if so, don't reset view 0 */
  794.                 }
  795.             }
  796.             break;
  797.  
  798.         case 5:                        /* DOS screen view */
  799.             viewmode=9;                /* wait for keypress */
  800.             break;
  801.  
  802.         case 6:                        /* server mode */
  803.             vprint(console->vs,"\r\nServer mode, press ESC to exit or ALT-A to begin a session\r\n");
  804.             viewmode=7;
  805.         case 7:                        /* server mode 2 */
  806.             j=n_chkchar();
  807.             switch(j) {
  808.                 case 27:
  809.                     vprint(console->vs,"\n\r\n Ending server mode \r\n");
  810.                     return(EXIT_TELNET);    /* leave the program */
  811.  
  812.                 case ALTA:
  813.                     if(!addsess(NULL))         /* start up a new one */
  814.                         viewmode=10;
  815.                     else {
  816.                         current=console;
  817.                         viewmode=6;
  818.                       }
  819.                     break;
  820.  
  821.                 case ALTE:        /* shell to dos */
  822.                     leavetek();
  823.                     n_window(0,0,numline+1,79);
  824.                     i=n_color(current->colors[0]);
  825.                     dosescape();
  826.                     wrest(console);
  827.                     viewmode=7;
  828.                     n_color(i);
  829.                     break;
  830.  
  831.                 case -1:
  832.                     break;        /* no keypress */
  833.  
  834.                 default:
  835.                     vprint(console->vs,"\r\nYou must have an open session to use other commands.\r\n");
  836.                     viewmode=6;
  837.                     break;
  838.               }
  839.             break;
  840.  
  841.         case 8:
  842.             if(graphit())                /* graphics menu screen */
  843.                 viewmode=10;
  844.             break;
  845.  
  846.         case 9:                            /* reset current screen on keypress */
  847.             if(0<n_chkchar())
  848.                 viewmode=10;    
  849.             break;
  850.  
  851.         case 10:                        /* Display current screen */
  852.             wrest(current);
  853.             viewmode=0;                    /* return to standard mode */
  854.             statline();    
  855.             break;
  856.  
  857.         case 11:                        /* paste copy buffer to current session */
  858.             temp-=netwrite(current->pnum,(char *)©buf[(int)(size-temp)],(int)temp);
  859.             if(!temp)
  860.                 viewmode=0;
  861.             break;
  862.  
  863.         case 13:
  864.             if(!n_scrlck()) {
  865.                 VSsetrgn(current->vs,0,0,79,numline);
  866.                 viewmode=2;            /* set back if appropriate */
  867.                 scroll=0;
  868.                 wrest(console);
  869.                 statline();
  870.                 n_cur(scroll_row,scroll_col);
  871.               }
  872. /* 
  873. *  In scroll lock mode, take keys only for the scrollback, 
  874. *  The scrollback routine will never block, so we keep servicing events.
  875. */
  876.             scrollback(console);
  877.             break;
  878.     }
  879.  
  880. /*
  881. *  Check for any relevant events that need to be handled by me
  882. */
  883.     if(0<(i=Sgetevent(USERCLASS | CONCLASS | ERRCLASS, &cl, &dat))) {
  884.         sw=cl*256+i;                /* class and event combination */
  885.         cvs=console->vs;
  886.         switch(sw) {
  887.             case CONCLASS*256+CONOPEN:    /* a connection has just opened */
  888.                 t1=wins[dat];            /* where the window pointer is stored */
  889.                 if(!t1)
  890.                     break;
  891.  
  892.                 t1->sstat='/';            /* connection status */
  893.                 netpush(dat);
  894.  
  895.                 /* Start negotiation on network */
  896.                 sprintf(parsedat,"%c%c%c",IAC,DOTEL,ECHO);
  897.                 netwrite(dat,parsedat,3);
  898.                 sprintf(parsedat,"%c%c%c",IAC,DOTEL,SGA);
  899.                 netwrite(dat,parsedat,3);
  900.                 sprintf(parsedat,"%c%c%c",IAC,WILLTEL,NAWS);
  901.                 netwrite(dat,parsedat,3);
  902.  
  903.                 /* Print to the console what we just did */
  904.                 tprintf(cvs,"SEND: %s %s\r\n",telstates[DOTEL-SE],teloptions[ECHO]);
  905.                 tprintf(cvs,"SEND: %s %s\r\n",telstates[DOTEL-SE],teloptions[SGA]);
  906.                 tprintf(cvs,"SEND: %s %s\r\n",telstates[WILLTEL-SE],teloptions[TERMTYPE]);
  907.                 tprintf(cvs,"SEND: %s %s\r\n",telstates[WILLTEL-SE],teloptions[LINEMODE]);
  908.                 tprintf(cvs,"SEND: %s %s\r\n",telstates[WILLTEL-SE],teloptions[NAWS]);
  909.  
  910.                 if(current!=t1) {
  911.                     current=t1;
  912.                     viewmode=10;
  913.                   }
  914.                 break;
  915.  
  916.             case CONCLASS*256+CONCLOSE:    /* connection is closing */
  917.                 if(0<netqlen(dat))
  918.                     netputuev(CONCLASS,CONCLOSE,dat);  /* call me again */
  919.                     /* drop through, process any data */
  920.  
  921.             case CONCLASS*256+CONDATA:
  922.                 if(viewmode) {            /* not ready for it */
  923.                     netputuev(CONCLASS,CONDATA,dat);
  924.                     break;
  925.                   }
  926.                 t1=wins[dat];            /* where the window pointer is stored */
  927.                 if(!t1)
  928.                     break;
  929.  
  930.                 if(inprocess(t1))
  931.                     return(EXIT_TELNET);
  932.                 break;
  933.  
  934.             case CONCLASS*256+CONFAIL:    /* can't open connection */
  935.                 t1=wins[dat];            /* where the window pointer is stored */
  936.                 if(!t1)
  937.                     break;                /* this don't count */
  938.                 vprint(cvs,"\r\nCan't open connection, timed out\r\n");
  939.                 netclose(dat);            /* close out attempt */
  940.                 if(!t1->next) {
  941.                     wrest(console);
  942.                     return(EXIT_TELNET);
  943.                   }
  944.                 if(t1==current) {
  945.                     current=current->next;
  946.                     viewmode=10;
  947.                   }
  948.                 delwindow(t1,1);
  949.                 statline();
  950.                 break;
  951.  
  952. /*
  953. *  domain nameserver results.
  954. */
  955.             case USERCLASS*256+DOMFAIL:            /* domain failed */
  956.                 mp=Slooknum(dat);                /* get machine info */
  957.                 vprint(cvs,"\r\nDOMAIN lookup failed for: ");
  958.                 if(mp && mp->hname)
  959.                     vprint(cvs,mp->hname);
  960.                 else 
  961.                     if(mp && mp->sname)
  962.                         vprint(cvs,mp->sname);
  963.                 vprint(cvs,"\r\n");
  964.                 break;
  965.  
  966.             case USERCLASS*256+DOMOK:
  967.                 mp=Slooknum(dat);                /* get machine info */
  968.                 if(mp) {
  969.                     vprint(cvs,"\r\nDOMAIN lookup OK for: ");   /* print session name and host name */
  970.                     if(mp->hname)
  971.                         vprint(cvs,mp->hname);
  972.                     if(mp->sname) {
  973.                         vprint(cvs," - ");
  974.                         vprint(cvs,mp->sname);
  975.                         if(mp->port!=HTELNET) {
  976.                             char *s;
  977.  
  978.                             if((s=(char *) malloc(strlen(mp->sname) + 6))!=NULL) {
  979.                                 sprintf(s,"%s#%d",mp->sname,mp->port);
  980.                                 mp->port=HTELNET;
  981.                                 addsess(s);
  982.                                 free(s);
  983.                               }    /* end if */
  984.                           }    /* end if */
  985.                         else
  986.                             addsess(mp->sname);
  987.                       }
  988.                     else
  989.                         if(mp->port!=HTELNET) {
  990.                             char *s;
  991.  
  992.                             if((s=(char *) malloc(strlen(mp->hname) + 6))!=NULL) {
  993.                                 sprintf(s,"%s#%d",mp->hname,mp->port);
  994.                                 mp->port=HTELNET;
  995.                                 addsess(s);
  996.                                 free(s);
  997.                               }    /* end if */
  998.                           }
  999.                         else
  1000.                             addsess(mp->hname);
  1001.                     vprint(cvs,"\r\n");
  1002.                     tprintf(console->vs,"Domain Port is:%d\r\n",mp->port);
  1003.                     viewmode=10;
  1004.                   }
  1005.                 break;
  1006.  
  1007. /*
  1008. *  FTP status events.
  1009. */
  1010.             case USERCLASS*256+FTPBEGIN:        /* data connection */
  1011.                 {
  1012.                     unsigned char host[4];
  1013.  
  1014.                     ftpact=dat;
  1015.                     Sftpname(s);                    /* get name */
  1016.                     Sftphost(host);
  1017.                     if (SftpDirection())
  1018.                         tprintf(cvs,"FTP: RECEIVING %s from host ", s);
  1019.                     else
  1020.                         tprintf(cvs,"FTP: SENDING %s to host ", s);
  1021.                     if((NULL==(mp=Slookip(host))) || (NULL==mp->sname))
  1022.                         tprintf(cvs,"%d.%d.%d.%d\r\n",host[0],host[1],host[2],host[3]);
  1023.                     else
  1024.                         tprintf(cvs,"%s\r\n",mp->sname);
  1025.                     ftpstart((char)(ftpact+2),s);
  1026.                     lastt=n_clicks();
  1027.                     break;
  1028.                 }
  1029.  
  1030.             case USERCLASS*256+FTPLIST:            /* LIST or NLST */
  1031.                 vprint(cvs,"FTP directory beginning\r\n");
  1032.                 break;
  1033.  
  1034.             case USERCLASS*256+FTPEND:            /* data connection ending */
  1035.                 ftpact=0;
  1036.                 statline();
  1037.                 vprint(cvs,"FTP transfer done\r\n");
  1038.                 break;
  1039.  
  1040.             case USERCLASS*256+FTPCOPEN:        /* command connection */
  1041.                 vprint(cvs,"FTP server initiated from host: ");
  1042.                 Sftphost(s);
  1043.                 if((NULL==(mp=Slookip(s))) || (NULL==mp->sname)) 
  1044.                     sprintf(&s[4],"%d.%d.%d.%d\r\n",s[0],s[1],s[2],s[3]);
  1045.                 else
  1046.                     sprintf(&s[4],"%s\r\n",mp->sname);
  1047.                 vprint(cvs,&s[4]);
  1048.                 break;
  1049.  
  1050.             case USERCLASS*256+FTPUSER:            /* user name entered */
  1051.                 vprint(cvs,"FTP user ");
  1052.                 Sftpuser(s);
  1053.                 vprint(cvs,s);
  1054.                 vprint(cvs," login request\r\n");
  1055.                 break;
  1056.  
  1057.             case USERCLASS*256+FTPPWOK:            /* user password verified */
  1058.                 vprint(cvs,"FTP Password verified\r\n");
  1059.                 break;
  1060.  
  1061.             case USERCLASS*256+FTPPWNO:            /* user password failed */
  1062.                 vprint(cvs,"FTP Password failed verification\r\n");
  1063.                 break;
  1064.  
  1065.             case USERCLASS*256+FTPCLOSE:        /* command connection ends */
  1066.                 vprint(cvs,"FTP server ending session\r\n");
  1067.                 break;
  1068.  
  1069.             case USERCLASS*256+RCPBEGIN:        /* rcp starting */
  1070.                 vprint(cvs,"rcp file transfer\r\n");
  1071.                 rcpact=1;
  1072.                 break;
  1073.  
  1074.             case USERCLASS*256+RCPEND:            /* rcp ending */
  1075.                 vprint(cvs,"rcp ending\r\n");
  1076.                 rcpact=0;
  1077.                 break;
  1078.  
  1079. #ifdef USETEK
  1080.             case USERCLASS*256+PSDUMP:            /* dump graphics screen */
  1081.                 if(VGpred(indev,outdev)) {
  1082.                     if(dat) {
  1083.                         endump();
  1084.                         vprint(cvs,"Graphics writing finished\r\n");
  1085.                         wrest(console);
  1086.                         viewmode=2;
  1087.                       }
  1088.                   }
  1089.                 else
  1090.                     netputevent(USERCLASS,PSDUMP,dat);    /* remind myself */
  1091.                 break;
  1092.  
  1093. #endif
  1094.             case ERRCLASS*256+ERR1:                        /* error message */
  1095.                 p=neterrstring(dat);
  1096.                 VSwrite(cvs,p,strlen(p));
  1097.                 VSwrite(cvs,"\r\n",2);
  1098.                 if (dat == 407)
  1099.                     inv_port_err(0,0,NULL);
  1100.             default:
  1101.                 break;
  1102.         }
  1103.     }
  1104. /*
  1105. *    update the FTP spinner if we are in ftp, and update the clock
  1106. */
  1107.     else {
  1108.         if(ftpact && (n_clicks()>lastt + 10)) {
  1109.             ftpstart((char)(ftpact+2),s);
  1110.             lastt=n_clicks();
  1111.           }
  1112.         if(def.clock) {
  1113.             if((current->termstate<TEKTYPE) && (!ftpact)) {
  1114.                 time(&newtime);
  1115.                 if(oldtime!=newtime) {
  1116.                     strcpy(s,ctime(&newtime));
  1117.                     clock_row=n_row();
  1118.                     clock_col=n_col();
  1119.                     c=n_color(current->colors[0]);
  1120.                     n_cur(numline+1,72);
  1121.                     set_cur(0);
  1122.                     if(Scmode())      /* check which screen writing mode to use */
  1123.                         n_cheat(&s[11],9);
  1124.                     else
  1125.                         n_draw(&s[11],9);
  1126.                     n_cur(clock_row,clock_col);
  1127.                     n_color(c);
  1128.                     oldtime=newtime;
  1129.                     set_cur(1);
  1130.                   } /* end if */
  1131.               } /* end if */
  1132.           } /* end if */
  1133.       } /* end else */
  1134.     return(c);
  1135. }
  1136.  
  1137. /*********************************************************************/
  1138. /* inprocess
  1139. *  take incoming data and process it.  Close the connection if it
  1140. *  is the end of the connection.
  1141. */
  1142. int inprocess(tw)
  1143. struct twin *tw;
  1144. {
  1145.     int cnt;
  1146.  
  1147.     cnt=netread(tw->pnum,s,200);    /* get some from incoming queue */
  1148.     if(cnt<0) {                    /* close this session, if over */
  1149.         netclose(tw->pnum);
  1150.  
  1151.         if(tw->capon) {
  1152.             fclose(tw->capfp);        /* close the capture file */
  1153.             tw->capon=capon=0;
  1154.           }
  1155.         n_color(tw->colors[0]);
  1156.         if(tw->next==NULL)         /* if this is the last one */
  1157.             if(stand) {
  1158.                 wins[tw->pnum]=NULL;
  1159.                 freewin(tw);
  1160.                 current=console;
  1161.                 viewmode=6;
  1162.                 wrest(current);
  1163.                 return(0);
  1164.               }    /* end if */
  1165.             else
  1166.                 return(-1);        /* signal no sessions open */
  1167.  
  1168. #ifdef USETEK
  1169.         leavetek();                    /* make Tek inactive */
  1170. #endif
  1171.         if(tw!=current)
  1172.             wrest(tw);
  1173.  
  1174.         if(!def.wingoaway)        /* check whether the window just goes away, or sticks around for a keypress */
  1175.             n_puts("\nConnection closed, press a key . . .");
  1176.         if(tw==current)
  1177.             current=tw->next;
  1178.         delwindow(tw,1);
  1179.         if(!def.wingoaway)        /* check whether the window just goes away, or sticks around for a keypress */
  1180.             viewmode=9;
  1181.         else
  1182.             viewmode=10;
  1183.         return(0);
  1184.       }
  1185.  
  1186.     if(cnt) 
  1187.         parse(tw,s,cnt);            /* display on screen, etc.*/
  1188.     return(0);
  1189. }
  1190.  
  1191. /*********************************************************************/
  1192. /* endall
  1193. *  clean up and leave
  1194. */
  1195. void endall()
  1196. {
  1197.     netshut();
  1198.  
  1199.     n_cur(numline+1,0);            /* go to bottom of screen */
  1200.     n_color(7);
  1201.     n_draw(blankline,80);        /* blank it out */
  1202.     if(def.ega43>0)                /* restore screen */
  1203.         ega24();
  1204.     remove_break();                /* restore the previous ctrl-c interupt handler */
  1205.     restore_break();            /* restore the BREAK status */
  1206.     restore_cursor();            /* restore the keyboard cursor */
  1207.     if (save_screen)
  1208.         end_text();
  1209.     exit(0);                    /* return to DOS */
  1210. }
  1211.  
  1212. /*********************************************************************/
  1213. /*  errhandle
  1214. *   write error messages to the console window
  1215. */
  1216. void errhandle()
  1217. {
  1218.     char *errmsg;
  1219.     int i,j;
  1220.  
  1221.     while(ERR1==Sgetevent(ERRCLASS,&i,&j)) {
  1222.         errmsg=neterrstring(j);
  1223.         VSwrite(console->vs,errmsg,strlen(errmsg));
  1224.         VSwrite(console->vs,"\r\n",2);
  1225.         if (j == 407)
  1226.             inv_port_err(0,0,NULL);
  1227.         }
  1228. }
  1229.  
  1230. /*********************************************************************/
  1231. /*  vprint
  1232. *   print to a virtual screen
  1233. */
  1234. void vprint(w,str)
  1235. int w;
  1236. char *str;
  1237. {
  1238. #ifdef CONSOLEDEBUG
  1239.     VSwrite(current->vs,str,strlen(str));        /* dump all messages to the current screen */
  1240. #else
  1241.     VSwrite(w,str,strlen(str));
  1242. #endif
  1243. }
  1244.  
  1245. /*********************************************************************/
  1246. /*  tprintf
  1247. *    print a formatted string to a virtual screen
  1248. */
  1249. #ifdef __TURBOC__
  1250. void tprintf(int w,char *fmt,...)
  1251. #else
  1252. void tprintf(w,fmt,...)
  1253. int w;
  1254. char *fmt;
  1255. #endif
  1256. {
  1257.     va_list arg_ptr;
  1258.  
  1259.     va_start(arg_ptr,fmt);        /* get a pointer to the variable arguement list */
  1260.     vsprintf(temp_str,fmt,arg_ptr);    /* print the formatted string into a buffer */
  1261.     va_end(arg_ptr);
  1262. #ifdef CONSOLEDEBUG
  1263.     VSwrite(current->vs,temp_str,strlen(temp_str));        /* dump all messages to the current screen */
  1264. #else
  1265.     VSwrite(w,temp_str,strlen(temp_str));
  1266. #endif
  1267. }
  1268.  
  1269. /*********************************************************************/
  1270. /*  parse
  1271. *   Do the telnet negotiation parsing.
  1272. *
  1273. *   look at the string which has just come in from outside and
  1274. *   check for special sequences that we are interested in.
  1275. *
  1276. *   Tries to pass through routine strings immediately, waiting for special
  1277. *   characters ESC and IAC to change modes.
  1278. */
  1279. void parse(tw,st,cnt)
  1280. struct twin *tw;
  1281. int cnt;
  1282. unsigned char *st;
  1283. {
  1284.     int cv,i;
  1285.     unsigned char *mark,*orig;
  1286.  
  1287.     cv=console->vs;
  1288.  
  1289. #ifdef NEGOTIATEDEBUG
  1290.     vprint(cv,"\r\n");
  1291.     for(i = 0; i < cnt; i++) {
  1292.         int j;
  1293.         for(j=0; (j < 16) && ((i + j) < cnt); j++) {
  1294.             tprintf(cv,"%2.2X  ", *(unsigned char *) (st + i + j));
  1295.         }
  1296.         i += j - 1;
  1297.         vprint(cv,"\r\n");
  1298.     }
  1299.     vprint(cv,"\r\n");
  1300. #endif /* NEGOTIATEDEBUG */
  1301.  
  1302.     orig=st;                /* remember beginning point */
  1303.     mark=st+cnt;            /* set to end of input string */
  1304.     netpush(tw->pnum);
  1305.  
  1306. /*
  1307. *  traverse string, looking for any special characters which indicate that
  1308. *  we need to change modes.
  1309. */
  1310.     while(st<mark) {
  1311.         switch(tw->telstate) {
  1312.             case ESCFOUND:
  1313. #ifdef USETEK
  1314.                 if((*st==12)&&(def.tek))    {                /* esc-FF */
  1315.                     if(tw->termstate==VTEKTYPE) {
  1316.                         vprint(cv,"\r\n Entering Tek mode \r\n");
  1317.                         tw->termstate=TEKTYPE;
  1318.                         VGgmode(rgdevice);
  1319.                         VGuncover(temptek);
  1320.                         current=tw;
  1321.                       }
  1322.                     VGwrite(temptek,"\033\014",2);
  1323.                     orig=++st;                    /* pass by ESC-FF in data */
  1324.                     tw->telstate=STNORM;
  1325.                     break;
  1326.                   }
  1327. #endif 
  1328.  
  1329. #ifdef USERAS
  1330.                 if(*st=='^') {                    /* esc-^ */
  1331.                     tw->termstate=RASTYPE;
  1332.                     tw->telstate=STNORM;
  1333.                     current=tw;
  1334.                     VRwrite("\033^",2);             /* echo ^ */
  1335.                     orig=++st;
  1336.                     break;
  1337.                   }
  1338. #endif
  1339.  
  1340.                 parsewrite(tw,"\033",1);        /* send the missing ESC */
  1341.                 tw->telstate=STNORM;
  1342.                 break;
  1343.  
  1344.             case IACFOUND:                 /* telnet option negotiation */
  1345.                 if(*st==IAC) {            /* real data=255 */
  1346.                     st++;                /* real 255 will get sent */
  1347.                     tw->telstate=STNORM;
  1348.                     break;
  1349.                   }
  1350.  
  1351.                 if(*st>239) {
  1352.                     tw->telstate=*st++;    /* by what the option is */
  1353.                     break;
  1354.                   }
  1355.  
  1356.                 tprintf(cv,"\r\n strange telnet option %s",itoa(*st,s,10));
  1357.                 orig=st;
  1358.                 tw->telstate=STNORM;
  1359.                 break;
  1360.  
  1361.     case EL:        /* received a telnet erase line command */
  1362.     case EC:        /* received a telnet erase character command */
  1363.     case AYT:       /* received a telnet Are-You-There command */
  1364.     case AO:        /* received a telnet Abort Output command */
  1365.     case IP:        /* received a telnet Interrupt Process command */
  1366.     case BREAK:     /* received a telnet Break command */
  1367.     case DM:        /* received a telnet Data Mark command */
  1368.     case NOP:       /* received a telnet No Operation command */
  1369.     case SE:        /* received a telnet Subnegotiation End command */
  1370.         tprintf(cv,"RECV: %s\r\n",telstates[tw->telstate-SE]);
  1371.         tw->telstate=STNORM;
  1372.         orig=st;
  1373.         break;
  1374.  
  1375.     case GOAHEAD:       /* telnet go ahead option*/
  1376.                     tw->telstate=STNORM;
  1377.                     orig=st;
  1378.                     break;
  1379.  
  1380.             case DOTEL:        /* received a telnet DO negotiation */
  1381.                 tprintf(cv,"RECV: %s %s\r\n",telstates[tw->telstate-SE],teloptions[*st]);
  1382.                 switch(*st) {
  1383.                     case SGA:        /* Suppress go-ahead */
  1384.                         if(!tw->igoahead) {    /* suppress go-ahead */
  1385.                             tprintf(cv,"SEND: %s %s\r\n",telstates[WILLTEL-SE],teloptions[*st]);
  1386.                             sprintf(parsedat,"%c%c%c",IAC,WILLTEL,*st);
  1387.                             netwrite(tw->pnum,parsedat,3);    /* take it */
  1388.                             tw->igoahead=1;
  1389.                           }
  1390.                         else
  1391.                             tprintf(cv,"NO REPLY NEEDED: %s %s\r\n",telstates[WILLTEL-SE],teloptions[SGA]);
  1392.                         tw->telstate=STNORM;
  1393.                         orig=++st;
  1394.                         break;
  1395.  
  1396.                     case TERMTYPE:        /* terminal type negotiation */
  1397.                         if(!tw->termsent) {
  1398.                             tw->termsent=1;
  1399.                             tprintf(cv,"SEND: %s %s\r\n",telstates[WILLTEL-SE],teloptions[*st]);
  1400.                             sprintf(parsedat,"%c%c%c",IAC,WILLTEL,*st);
  1401.                             netwrite(tw->pnum,parsedat,3);
  1402.                           }    /* end if */
  1403.                         else
  1404.                             tprintf(cv,"NO REPLY NEEDED: %s %s\r\n",telstates[WILLTEL-SE],teloptions[TERMTYPE]);
  1405.                         tw->telstate=STNORM;
  1406.                         orig=++st;
  1407.                         break;
  1408.  
  1409. #ifdef LMODE
  1410.                     case LINEMODE:        /* linemode negotiation */
  1411.                         sprintf(parsedat,"%c%c%c",IAC,WILLTEL,LINEMODE);
  1412.                         netwrite(tw->pnum,parsedat,3);
  1413.                         vprint(cv,"SEND: SB LINEMODE SLC\r\n");
  1414.                         sprintf(parsedat,"%c%c%c%c",IAC,SB,LINEMODE,SLC);
  1415.                         netwrite(tw->pnum,parsedat,4);
  1416.  
  1417.                         for(i=1; i<NUMLMODEOPTIONS; i++) {
  1418.                             if(tw->slc[i]==-1)
  1419.                                 sprintf(parsedat,"%c%c%c",i,NO_SUPPORT,0);
  1420.                             else
  1421.                                 sprintf(parsedat,"%c%c%c",i,CANTCHANGE,(char)tw->slc[i]);
  1422.  
  1423.                             netwrite(tw->pnum,parsedat,3);
  1424.                             tprintf(cv,"     %s %s %s\r\n",LMoptions[i],(tw->slc[i]==-1) ? "NO_SUPPORT" : "CANTCHANGE",(tw->slc[i]==-1) ? "0" : itoa(tw->slc[i],s,10));
  1425.                         }    /* end for */
  1426.  
  1427.                         sprintf(parsedat,"%c%c",IAC,SE);
  1428.                         netwrite(tw->pnum,parsedat,2);
  1429.                         vprint(cv,"\r\n");
  1430.                         tw->telstate=STNORM;
  1431.                         orig=++st;
  1432.                         break;
  1433. #endif /* LMODE */
  1434.  
  1435.  
  1436.                     case NAWS:        /* Negotiate About Window Size */
  1437.                         sprintf(parsedat,"%c%c%c%c%c%c%c%c%c",IAC,SB,NAWS,(char)0,(char)tw->width,(char)0,(char)tw->rows,IAC,SE);
  1438.                         netwrite(tw->pnum,parsedat,9);
  1439.                         vprint(cv,"SEND: SB NAWS 0 ");
  1440.                         vprint(cv,itoa(tw->width,parsedat,10));
  1441.                         vprint(cv," 0 ");
  1442.                         vprint(cv,itoa(tw->rows,parsedat,10));
  1443.                         vprint(cv," IAC SE");
  1444.                         tw->telstate=STNORM;
  1445. /* new */                        orig=++st;
  1446.                         break;
  1447.  
  1448.                     default:
  1449.                         tprintf(cv,"SEND: %s %s\r\n",telstates[WONTTEL-SE],teloptions[*st]);
  1450.                         sprintf(parsedat,"%c%c%c",IAC,WONTTEL,*st++);
  1451.                         netwrite(tw->pnum,parsedat,3);    /* refuse it */
  1452.                         tw->telstate=STNORM;
  1453.                         orig=st;
  1454.                           break;
  1455.  
  1456.                 }
  1457.                 break;
  1458.  
  1459.             case DONTTEL:        /* Received a telnet DONT option */
  1460.                 tprintf(cv,"RECV: %s %s\r\n",telstates[tw->telstate-SE],teloptions[*st]);
  1461.                 tw->telstate=STNORM;
  1462.                 orig=++st;
  1463.                 break;
  1464.  
  1465.             case WILLTEL:        /* received a telnet WILL option */
  1466.                 tprintf(cv,"RECV: %s %s\r\n",telstates[tw->telstate-SE],teloptions[*st]);
  1467.                 tw->telstate=STNORM;
  1468.                 switch(*st++) {
  1469.                     case SGA:                    /* suppress go-ahead */
  1470.                         if(tw->ugoahead)
  1471.                             break;
  1472.  
  1473.                         tw->ugoahead=1;
  1474.                         tprintf(cv,"SEND: %s %s\r\n",telstates[DOTEL-SE],teloptions[*st]);
  1475.                         sprintf(parsedat,"%c%c%c",IAC,DOTEL,3);    /* ack */
  1476.                         netwrite(tw->pnum,parsedat,3);
  1477.                         break;
  1478.  
  1479.                     case ECHO:                        /* echo */
  1480.                         if(tw->echo)
  1481.                             break;
  1482.  
  1483.                         tw->echo=1;
  1484.                         tprintf(cv,"SEND: %s %s\r\n",telstates[DOTEL-SE],teloptions[*st]);
  1485.                         sprintf(parsedat,"%c%c%c",IAC,DOTEL,1);    /* ack */
  1486.                         netwrite(tw->pnum,parsedat,3);
  1487.                         netwrite(tw->pnum,tw->linemode,strlen(tw->linemode));
  1488.                         tw->linemode[0]='\0';
  1489.                         break;
  1490.  
  1491.                     case TIMING:        /* Timing mark */
  1492.                         tw->timing=0;
  1493.                         break;
  1494.  
  1495.                     default:
  1496.                         tprintf(cv,"SEND: %s %s\r\n",telstates[DONTTEL-SE],teloptions[*st]);
  1497.                         sprintf(parsedat,"%c%c%c",IAC,DONTTEL,*(st-1));
  1498.                         netwrite(tw->pnum,parsedat,3);    /* refuse it */
  1499.                         break;
  1500.                   } /* end switch */
  1501.                 orig=st;
  1502.                 break;
  1503.                             
  1504.             case WONTTEL:        /* Received a telnet WONT option */
  1505.                 tprintf(cv,"RECV: %s %s\r\n",telstates[tw->telstate-SE],teloptions[*st]);
  1506.                 tw->telstate=STNORM;
  1507.                 switch(*st++) {            /* which option? */
  1508.                     case ECHO:                /* echo */
  1509.                         if(!tw->echo)
  1510.                             break;
  1511.  
  1512.                         tw->echo=0;
  1513.                         sprintf(parsedat,"%c%c%c",IAC,DONTTEL,ECHO);
  1514.                         netwrite(tw->pnum,parsedat,3);    /* OK with us */
  1515.                         break;
  1516.  
  1517.                     case TIMING:    /* Telnet timing mark option */
  1518.                         tw->timing=0;
  1519.                         break;
  1520.  
  1521.                     default:
  1522.                         break;
  1523.                   }
  1524.                 orig=st;
  1525.                 break;
  1526.  
  1527.             case SB:        /* telnet sub-options negotiation */
  1528.                 tw->telstate=NEGOTIATE;
  1529.                 orig=st;
  1530.                 i=tw->substate=0;                /* Defined for each */
  1531.                 break;
  1532.  
  1533.             case NEGOTIATE:
  1534.                 if(tw->substate<200) {
  1535.                     switch(*st) {
  1536.                         case IAC:
  1537.                             if(*(st+1)==IAC) {    /* skip over double IAC's */
  1538.                                 parsedat[i++]=*st++;
  1539.                                 parsedat[i++]=*st++;
  1540.                               } /* end if */
  1541.                             else {
  1542.                                 parsedat[i]='\0';
  1543.                                 tw->substate=*st++;
  1544.                               } /* end else */
  1545.                             break;
  1546.  
  1547.                         default:
  1548.                             parsedat[i++]=*st++;
  1549.                             break;
  1550.                       }    /* end switch */
  1551.                   }    /* end if */
  1552.                 else {
  1553.                     switch(tw->substate) {
  1554.                         case IAC:
  1555.                             tw->substate=*st++;
  1556.                             if(tw->substate==SE) {
  1557.                                 switch(parsedat[0]) {
  1558.                                     case TERMTYPE:
  1559.                                         if(parsedat[1]==1) {
  1560.                                             char s[100];
  1561.  
  1562.                                             netwrite(tw->pnum,"\377\372\030\000",4);
  1563.                                             sprintf(s,"%s\377\360",def.termtype);
  1564.                                             netwrite(tw->pnum, s, strlen(s));
  1565.                                             tprintf(cv,"RECV: SB TERMINAL-TYPE SEND\r\nSEND: SB TERMINAL-TYPE IS %s\r\n",def.termtype);
  1566.                                           }    /* end if */
  1567.                                         break;
  1568.  
  1569.                                     case LINEMODE:
  1570.                                         switch(parsedat[1]) {
  1571.                                             char s[50];
  1572.  
  1573.                                             case MODE:
  1574.                                                 if(parsedat[2] & EDIT)
  1575.                                                     tw->lmflag=1;
  1576.                                                 else
  1577.                                                     tw->lmflag=0;
  1578.  
  1579.                                                 sprintf(s,"%c%c%c%c",IAC,SB,LINEMODE,MODE);
  1580.                                                 netwrite(tw->pnum,s,4);
  1581.                                                 sprintf(s,"%c%c%c",parsedat[2]|MODE_ACK,IAC,SE);
  1582.                                                 netwrite(tw->pnum,s,3);
  1583.                                                 vprint(cv,"RECV: LINEMODE MODE ");
  1584.                                                 vprint(cv,itoa(parsedat[2],s,10));
  1585.                                                 vprint(cv,"\r\n");
  1586.                                                 break;
  1587.  
  1588.                                             case DOTEL:
  1589.                                                 netwrite(tw->pnum,"\377\372\042",3);
  1590.                                                 sprintf(s,"%c\002\377\360",WONTTEL);
  1591.                                                 netwrite(tw->pnum,s,strlen(s));
  1592.                                                 break;
  1593.  
  1594.                                             case WILLTEL:
  1595.                                                 netwrite(tw->pnum,"\377\372\042",3);
  1596.                                                 sprintf(s,"%c\002\377\360",DONTTEL);
  1597.                                                 netwrite(tw->pnum,s,strlen(s));
  1598.                                                 break;
  1599.  
  1600.                                             case SLC:
  1601.                                                 vprint(cv,"RECV: SB LINEMODE SLC\r\n");
  1602.                                                 for(i=2;(parsedat[i]!='\0') && (parsedat[i]!=IAC); i+=3) {
  1603.                                                     if(parsedat[i+1] & SLC_ACK)
  1604.                                                         tprintf(cv,"     [%2.2X %2.2X %2.2X] (%d) %s %s|ACK %d\r\n",
  1605.                                                             parsedat[i], parsedat[i+1], parsedat[i+2], parsedat[i] ,
  1606.                                                             LMoptions[parsedat[i]],LMflags[parsedat[i+1] & SLC_LEVELBITS],
  1607.                                                             parsedat[i+2]);
  1608.                                                     else
  1609.                                                         tprintf(cv,"     [%2.2X %2.2X %2.2X] (%d) %s %s %d\r\n",
  1610.                                                             parsedat[i], parsedat[i+1], parsedat[i+2], parsedat[i] ,
  1611.                                                             LMoptions[parsedat[i]],LMflags[parsedat[i+1] & SLC_LEVELBITS],
  1612.                                                             parsedat[i+2]);
  1613.                                                     if (parsedat[i+2]==IAC) i++;
  1614.                                                 }    /* end for */
  1615.  
  1616.                                                     /* First check to see if we need to reply */
  1617.  
  1618.                                                 for(i=2; (parsedat[i]!='\0') && (parsedat[i]!=IAC); i+=3)
  1619.                                                     if(!(parsedat[i+1] & SLC_ACK))
  1620.                                                         break;
  1621.                                                         
  1622.                                                     /* if we do then send a reply */
  1623.                                                 if((parsedat[i]!=IAC) && (parsedat[i]!='\0')) {
  1624.                                                     vprint(cv,"SEND: SB LINEMODE SLC\r\n");
  1625.                                                     sprintf(s,"%c%c%c%c",IAC,SB,LINEMODE,SLC);
  1626.                                                     netwrite(tw->pnum,s,4);
  1627.  
  1628. /*--------------------------------------------------------------------*/
  1629.                                                         for (i=2; (parsedat[i]!='\0') && (parsedat[i]!=IAC); i+=3) {
  1630.                                                             
  1631.                                                                 if (!(parsedat[i+1] & SLC_ACK))    {    /* no response of ACK set */
  1632.                                                                     if (parsedat[i+1]!=NO_SUPPORT) {
  1633.                                                                         if (tw->slc[parsedat[i]]==-1) {
  1634.                                                                             sprintf(s,"%c%c%c",parsedat[i],NO_SUPPORT,0);
  1635.  
  1636.                                                                             tprintf(cv, "    [%2.2X %2.2X %2.2X] (%d) %s %s %d\r\n",
  1637.                                                                                 s[0], s[1], s[2], parsedat[i],
  1638.                                                                                 LMoptions[parsedat[i]], "NO_SUPPORT", 0);
  1639.                                                                         } else {
  1640.                                                                             sprintf(s,"%c%c%c",parsedat[i],CANTCHANGE,
  1641.                                                                                     tw->slc[parsedat[i]]);
  1642.  
  1643.                                                                             tprintf(cv, "    [%2.2X %2.2X %2.2X] (%d) %s %s %d\r\n",
  1644.                                                                                 s[0], s[1], s[2], parsedat[i],
  1645.                                                                                 LMoptions[parsedat[i]], "CANTCHANGE",tw->slc[parsedat[i]]);
  1646.                                                                         }
  1647.                                                                     } else    {    /*  No_Support case */
  1648.                                                                         if (tw->slc[parsedat[i]] != -1) { /* only need to do */
  1649.                                                                                                                                                                                                                 /* something if we support*/
  1650.                                                                             if (parsedat[i] < NUMLMODEOPTIONS)
  1651.                                                                                 tw->slc[parsedat[i]] = -1;
  1652.                                                                             sprintf(s,"%c%c%c",parsedat[i],
  1653.                                                                                     (unsigned char)(NO_SUPPORT | SLC_ACK), 0);
  1654.  
  1655.                                                                             tprintf(cv, "    [%2.2X %2.2X %2.2X] (%d) %s %s %d\r\n",
  1656.                                                                                 s[0], (unsigned char) s[1], s[2], parsedat[i],
  1657.                                                                                 LMoptions[parsedat[i]], "NO_SUPPORT|ACK", 0);
  1658.                                                                         }
  1659.                                                                     }
  1660.                                                                     netwrite(tw->pnum,s,3);
  1661.                                                                 }
  1662.                                                                     if (parsedat[i+2]==IAC) i++;
  1663.                                                         }
  1664. /*----------------------------------------------------------------------*/
  1665.  
  1666.                                                     sprintf(s,"%c%c",IAC,SE);
  1667.                                                     netwrite(tw->pnum,s,2);
  1668.                                                   }    /* end if */
  1669.  
  1670.                                                 /* otherwise just exit */
  1671.                                                 break;
  1672.  
  1673.                                             default:
  1674.                                                 break;
  1675.                                           }    /* end switch */
  1676.                                         break;
  1677.                                     
  1678.                                     default:
  1679.                                         break;
  1680.                                   }    /* end switch */
  1681.                               }    /* end if */
  1682.                             orig=st;
  1683.                             tw->telstate=STNORM;
  1684.                             break;
  1685.  
  1686.                         default:
  1687.                             orig=st;
  1688.                             tw->telstate=STNORM;
  1689.                             break;
  1690.                       }    /* end switch */
  1691.                   }    /* end else */
  1692.                 break;
  1693.  
  1694.             default:
  1695.                 tw->telstate=STNORM;
  1696.                 break;
  1697.         }
  1698.  
  1699. /*
  1700. * quick scan of the remaining string, skip chars while they are
  1701. * uninteresting
  1702. */
  1703.         if(tw->telstate==STNORM) {
  1704. /*
  1705. *  skip along as fast as possible until an interesting character is found
  1706. */
  1707.             while(st<mark && *st!=27 && *st<IAC) {
  1708.                 if((!tw->binary) && (!tw->mapoutput))
  1709.                     *st &= 127;                    /* mask off high bit */
  1710.                 st++;
  1711.               }
  1712.             if(!tw->timing) 
  1713.                 parsewrite(tw,orig,st-orig);
  1714.             orig=st;                /* forget what we have sent already */
  1715.             if(st<mark)
  1716.                 switch (*st) {
  1717.                     case IAC:            /* telnet IAC */
  1718.                         tw->telstate=IACFOUND;
  1719.                         st++;
  1720.                         break;
  1721.  
  1722.                     case 27:            /* ESCape code */
  1723.                         if(st==mark-1 || *(st+1)==12 || *(st+1)=='^')
  1724.                             tw->telstate=ESCFOUND;
  1725.                         st++;            /* strip or accept ESC char */
  1726.                         break;
  1727.  
  1728.                     default:
  1729.                         vprint(cv," strange char>128\r\n");
  1730.                         st++;
  1731.                         break;
  1732.                   }    /* end switch */
  1733.           }    /* end if */
  1734.     }  /* end while */
  1735. }
  1736.  
  1737. /*********************************************************************/
  1738. /*  parsewrite
  1739. *   write out some chars from parse
  1740. *   Has a choice of where to send the stuff
  1741. */
  1742. void parsewrite(tw,dat,len)
  1743. struct twin *tw;
  1744. char *dat;
  1745. int len;
  1746. {
  1747.     int i;
  1748. /*
  1749. *  send the string where it belongs
  1750. *  1. Check for a capture file.  If so, echo a copy of the string
  1751. *  2. Check for dumb terminal type, convert special chars if so
  1752. *  3. Check for Tektronix mode, sending Tek stuff
  1753. *  3b. check for raster color type
  1754. *  4. or, send to virtual screen anyway
  1755. */
  1756.  
  1757. #ifndef UM
  1758.     if (localprint) {
  1759.         for(i=0; i<len-3; i++) {
  1760.             if ((dat[i]==27)&&(dat[i+1]=='[')&&(dat[i+2]=='4')&&(dat[i+3]=='i')) 
  1761.                 localprint=0;
  1762.         }
  1763.         if (localprint)
  1764.             for(i=0; i<len; i++)
  1765. #ifdef MSC
  1766.                 _bios_printer(_PRINTER_WRITE,0,dat[i]);
  1767. #elif __TURBOC__
  1768.                 biosprint(0,ptr[i],0);
  1769. #endif
  1770.     }
  1771. #endif
  1772.     if(tw->capon)                        /* capture to file? */
  1773.         fwrite(dat,len,1,tw->capfp);
  1774. /*
  1775. * raw mode for debugging, passes through escape sequences and other
  1776. * special characters as <27> symbols
  1777. */
  1778.     if(tw->termstate==DUMBTYPE) {
  1779.         for (i=0; i<len; i++, dat++) 
  1780.             if(*dat==27 || *dat>126) {
  1781.                 sprintf(parsedat,"<%d>",*dat);
  1782.                 VSwrite(tw->vs,parsedat,strlen(parsedat));
  1783.               }
  1784.             else
  1785.                 VSwrite(tw->vs,dat,1);
  1786.       }
  1787.     else {
  1788. #ifdef USETEK
  1789.         if(tw->termstate==TEKTYPE) {
  1790.             i=VGwrite(temptek,dat,len);
  1791.             if(i<len) {
  1792.                 leavetek();
  1793.                 viewmode=10;
  1794.                 parsewrite(tw,dat+i,len-i);
  1795.               }
  1796.           }                
  1797.         else 
  1798. #endif
  1799. #ifdef USERAS
  1800.             if(tw->termstate==RASTYPE) {
  1801.                 i=VRwrite(dat,len);
  1802.                 if(i<len) {
  1803.                     tw->termstate=VTEKTYPE;
  1804.                     parsewrite(tw,dat+i,len-i);
  1805.                   }
  1806.               }
  1807.             else
  1808. #endif
  1809.                 VSwrite(tw->vs,dat,len);    /* send to virtual VT102 */
  1810.  
  1811.       }    /* end else */
  1812. }
  1813.  
  1814.  
  1815. /*********************************************************************/
  1816. /* newkey
  1817. *  filter for command key sequences
  1818. */
  1819. int newkey(t1)
  1820. struct twin *t1;
  1821. {
  1822.     int c;
  1823.     char s[3];
  1824.  
  1825.     if(foundbreak) {
  1826.         foundbreak=0;
  1827.         c='\003';                   /* ctrl-c */
  1828.         if(t1->lmflag) {       /* Telnet line mode is on */
  1829.             sprintf(s, "%c%c", IAC, IP);
  1830.             netwrite(t1->pnum, s, 2);
  1831.             vprint(console->vs, "SEND: IAC IP\r\n");
  1832.             c = 0; /* don't want ^C on beginning of next line */
  1833.         } /* end if */
  1834.     } else {
  1835.         if(ginon)
  1836.             c=0;
  1837.         else
  1838.             if(t1->lmflag) {       /* Telnet line mode is on */
  1839.                 c=RSgets(t1->vs,t1->linemode,79,(char)(!t1->echo));
  1840.                 if((c==13) || (c == t1->slc[SLC_SUSP])) {            /* pressed return or susp */
  1841.                     parse(t1,"\r\n",2);     /* echo the return */
  1842.                     strcat(t1->linemode,"\n"); 
  1843.                     netpush(t1->pnum);
  1844.                     netwrite(t1->pnum,t1->linemode,strlen(t1->linemode));
  1845.                     t1->linemode[0]='\0';
  1846.                     if (c == t1->slc[SLC_SUSP]) {
  1847.                         sprintf(s, "%c%c", IAC, SUSP);
  1848.                         netwrite(t1->pnum, s, 2);
  1849.                         vprint(console->vs, "SEND: IAC SUSP\r\n");
  1850.                     }
  1851.                     c=0;
  1852.                 }
  1853.                 else
  1854.                     if(c>0) {        /* write string, pass c to command interp */
  1855.                         if(t1->linemode[0]) {
  1856.                             netpush(t1->pnum);
  1857.                             netwrite(t1->pnum,t1->linemode,strlen(t1->linemode));
  1858.                             t1->linemode[0]='\0';
  1859.                         }
  1860.                     }
  1861.           }
  1862.         else
  1863.             if(t1->echo)
  1864.                 c=n_chkchar();            /* a char available ? */
  1865.             else 
  1866.                 if(t1->halfdup) {        /* half duplex */
  1867.                     c=n_chkchar();
  1868.                         if(c==13) {
  1869.                             parse(t1,"\r\n",2); /* echo crlf */
  1870.                             vt100key(13);
  1871.                             c=10;
  1872.                             } 
  1873.                         else 
  1874.                             if(c>0 && c<128)
  1875.                                 parse(t1,(char *)&c,1);        /* echo char */
  1876.                   } /* end if */
  1877.                 else {                        /* kludge linemode */
  1878.                     c=RSgets(t1->vs,t1->linemode,79,1);
  1879.                     if(c==13) {            /* pressed return */
  1880.                         parse(t1,"\r\n",2);     /* echo the return */
  1881.                         strcat(t1->linemode,"\r\n");
  1882.                         netpush(t1->pnum);
  1883.                         netwrite(t1->pnum,t1->linemode,strlen(t1->linemode));
  1884.                         t1->linemode[0]='\0';
  1885.                         c=0;
  1886.                       } /* end if */
  1887.                     else
  1888.                         if(c>0) {        /* write string, pass c to command interp */
  1889.                             if(t1->linemode[0]) {
  1890.                                 netpush(t1->pnum);
  1891.                                 netwrite(t1->pnum,t1->linemode,strlen(t1->linemode));
  1892.                                 t1->linemode[0]='\0';
  1893.                               } /* end if */
  1894.                           } /* end if */
  1895.                   } /* end else */
  1896.       } /* end else */
  1897.  
  1898.     if(c<=0)
  1899.         return(c);
  1900.     return(dokey(t1,c));
  1901. }
  1902.  
  1903. /************************************************************************/
  1904. /*  screendump
  1905. *   dump the contents of the current screen into the capture file
  1906. *
  1907. */
  1908. void screendump(struct twin *t1)
  1909. {
  1910.     int y,            /* variable to count the line of the screen we are dumping */
  1911.         len;        /* the length of the line with trailing blanks eliminated */
  1912.     unsigned char *c,*d;    /* temporary pointers into the text for a line */
  1913.  
  1914.     if(t1->capfp) {        /* make certain the file is open */
  1915.         if(VSvalids(t1->vs))    /* make certain there is a virtual screen to dump */
  1916.             return;
  1917.         capstat("Dump",1);
  1918.         for(y=0; y<numline+1; y++) {    /* dump each line */
  1919.             c=&VSIw->linest[y]->text[0];    /* get the address of the text line */
  1920.             d=c+VSIw->allwidth;            /* allwidth =79 for an 80 width window */
  1921.             while((*d==' ' || *d==0) && d>c)        /* don't print trailing blanks */
  1922.                 d--;
  1923.             len=d-c+1;
  1924.             fprintf(t1->capfp,"%*.*s\r\n",len,len,c);   /* store the line */
  1925.           }    /* end for */
  1926.         fprintf(t1->capfp,"\f");    /* print formfeed */
  1927.         statline();        /* re-print the statline */
  1928.       }    /* end if */
  1929. }    /* end screendump() */
  1930.  
  1931. /************************************************************************/
  1932. /*  dokey
  1933. *   translates and sends keys and filters for command keys
  1934. *
  1935. */
  1936. int dokey(t1,c)
  1937. struct twin *t1;
  1938. int c;
  1939. {
  1940.     int i;
  1941.  
  1942.     switch (c) {
  1943.         case BACKSPACE:        /* backspace */
  1944.             c=t1->bksp;        /* allows auto del instead of bs */
  1945.             break;
  1946.  
  1947.         case 13:            /* different CR mappings */
  1948.             vt100key(13);
  1949.             vt100key(t1->crfollow);
  1950.             c=0;
  1951.             break;
  1952.  
  1953.         case 127:
  1954.             c=t1->del;        /* switch bs around, too */
  1955.             break;
  1956.  
  1957.         case THENUL:        /* user wants the true NUL char */
  1958.             c=0;
  1959.             netwrite(t1->pnum,(char *)&c,1);    /* write a NUL */
  1960.             break;
  1961.  
  1962.         case CTRLHOME:        /* tek clear screen */
  1963.         case E_CTRLHOME:    /* tek clear screen */
  1964.             if(def.tek) {    /* check whether we are allowed to go into tek mode */
  1965.                 if(current->termstate!=TEKTYPE) {
  1966.                     current->termstate=TEKTYPE;
  1967.                     VGgmode(rgdevice);
  1968.                     VGuncover(temptek);
  1969.                 }
  1970.                 VGwrite(temptek,"\033\014",2);  /* clear storage and screen */
  1971.                 c=0;
  1972.               }    /* end if */
  1973.             break;
  1974.  
  1975.         case HOME:            /* clear to text */
  1976.         case E_HOME:        /* clear to text */
  1977.             if(def.tek) {    /* check whether tektronix is enabled */
  1978.                 if(leavetek()) {
  1979.                     viewmode=10;
  1980.                     c=0;
  1981.                   }
  1982.               }    /* end if */
  1983.             break;
  1984.  
  1985.         case ALTA:                /* add session */
  1986.             c=0;
  1987.             if(0>addsess(NULL)) {        /* start up a new one */
  1988.                 vprint(console->vs,"\r\nPress any key to continue . . .");
  1989.                 viewmode=9;
  1990.               }
  1991.             else
  1992.                 viewmode=10;
  1993.             break;
  1994.  
  1995.         case ALTB:                        /* session switch backwards */
  1996.             c=0;
  1997.             leavetek();
  1998.             if(current->prev==NULL)   /* are we only one ? */
  1999.                 break;
  2000.             current=current->prev;
  2001.             viewmode=10;
  2002.             break;
  2003.  
  2004.         case ALTC:                            /* toggle capture */
  2005.             if(capon && current->capon) {    /* already on */
  2006.                 capstat("    ",0);
  2007.                 fclose(current->capfp);        /* close the capture file */
  2008.                 current->capon=capon=0;
  2009.               }    /* end if */
  2010.             else 
  2011.                 if(!capon) {                /* I want one */
  2012.                     if(NULL==(current->capfp=Sopencap())) {
  2013.                         vprint(console->vs,"\r\nCannot open capture file ");
  2014.                         break;
  2015.                       }    /* end if */
  2016.                     capstat("Capt",1);
  2017.                     current->capon=capon=1;
  2018.                   }    /* end if */
  2019.                 else {
  2020.                     vprint(console->vs,"\r\nAnother session has capture file open, cannot open two at once\r\n");
  2021.                     wrest(console);
  2022.                     viewmode=2;
  2023.                   }    /* end else */
  2024.             c=0;
  2025.             break;
  2026.  
  2027.         case ALTD:        /* dump screen to capture file */
  2028.             c=0;
  2029.             if(!capon) {    /* if the capture file is not already open */
  2030.                 if((current->capfp=Sopencap())==NULL) {    /* try to open t he capture file */
  2031.                     vprint(console->vs,"\r\nCannot open capture file for screendump ");
  2032.                     wrest(console);
  2033.                     viewmode=2;
  2034.                     break;
  2035.                   }    /* end if */
  2036.                 screendump(current);    /* dump the current screen */
  2037.                 fclose(current->capfp);
  2038.                 current->capfp=NULL;
  2039.                 break;
  2040.               }    /* end if */
  2041.             if(current->capon && current->capfp)    /* ok, capture if on & the file is open */
  2042.                 screendump(current);    /* dump the screen */
  2043.             else {
  2044.                 vprint(console->vs,"\r\nAnother session has a capture file open, cannot screendump\r\n");
  2045.                 wrest(console);
  2046.                 viewmode=2;
  2047.               }    /* end else */
  2048.             break;
  2049.  
  2050.         case ALTE:        /* shell to commmand processor (DOS) */
  2051.             leavetek();
  2052.             n_window(0,0,numline+1,79);
  2053.             i=n_color(current->colors[0]); 
  2054.             dosescape();
  2055.             viewmode=5;
  2056.             n_color(i);
  2057.             c=0;
  2058.             break;
  2059.  
  2060.         case ALTF:                            /* an ftp command */
  2061.             strcpy(s,"ftp ");
  2062.             if((!Sneedpass())&&(current->ftpopts)) {
  2063.                 strcat(s,current->ftpopts);
  2064.                 strcat(s," ");
  2065.             }
  2066.             sprintf(&s[strlen(s)],"%d.%d.%d.%d\r\n",myipnum[0],myipnum[1],myipnum[2],myipnum[3]);
  2067.             netwrite(t1->pnum,s,strlen(s));
  2068.             if(!t1->echo)
  2069.                 parse(t1,s,strlen(s));     /* echo the string */
  2070.             c=0;
  2071.             break;
  2072.  
  2073. #ifdef USETEK
  2074.         case ALTG:            /* graphics manipulation */
  2075.             if(Stmode()) {        /* make certain that tektronix has been initialized */
  2076.                 c=0;
  2077.                 leavetek();
  2078.                 dispgr();
  2079.               } /* end if */
  2080.             break;
  2081. #endif
  2082.  
  2083.         case ALTH:                /* help display */
  2084.             if(viewmode!=3) {
  2085.                 leavetek();
  2086.                 viewmode=3;
  2087.                 helpmsg();
  2088.                 c=0;
  2089.             }
  2090.             break;
  2091.  
  2092.         case ALTI:                            /* my internet address */
  2093.             sprintf(s,"%d.%d.%d.%d",myipnum[0],myipnum[1],myipnum[2],myipnum[3]);
  2094.             netwrite(t1->pnum,s,strlen(s));
  2095.             if(!t1->echo)
  2096.                 parse(t1,s,strlen(s));         /* echo the string */
  2097.             c=0;
  2098.             break;
  2099.  
  2100. #ifdef MEMORY_DEBUG
  2101.         case ALTJ:      /* for debuggin' purposes */
  2102.             mem_file=fopen("c:\mem_dump","w");
  2103.             if (mem_file) {
  2104.                 Mem_Display(mem_file);
  2105.                 vprint(console->vs,"wrote mem_file.\r\n");
  2106.                 fclose(mem_file);
  2107.             }
  2108.             else vprint(console->vs,"failed mem_file write.\r\n");
  2109.  
  2110.             c=0;
  2111.             break;
  2112. #endif
  2113.  
  2114.         case ALTK:                /* erase char */
  2115.             netpush(t1->pnum);
  2116.             netwrite(t1->pnum,"\377\367",2);
  2117.             c=0;
  2118.             break;
  2119.  
  2120.         case ALTL:
  2121.             sound_on=!sound_on;
  2122.             c=0;
  2123.             break;
  2124.                 
  2125.         case ALTM:                  /* mouse control on/off */
  2126.             c=0;
  2127.             use_mouse=!use_mouse;
  2128.             break;
  2129.  
  2130.         case ALTN:                        /* session switch forwards */
  2131.             c=0;
  2132.             leavetek();
  2133.             if(current->next==NULL)   /* are we only one ? */
  2134.                 break;
  2135.             current=current->next;
  2136.             viewmode=10;
  2137.             break;
  2138.  
  2139.         case ALTO:                /* abort output */
  2140.             netpush(t1->pnum);
  2141.             netwrite(t1->pnum,"\377\365",2);
  2142.             c=0;
  2143.             break;
  2144.                 
  2145.         case ALTP:                /* change a parameter */
  2146.             parmchange();
  2147.             c=0;
  2148.             break;
  2149.  
  2150.         case ALTQ:                /* are you there? */
  2151.             netpush(t1->pnum);
  2152.             netwrite(t1->pnum,"\377\366",2);
  2153.             c=0;
  2154.             break;
  2155.  
  2156.         case ALTR:                /* reset screen values */
  2157.             if(!leavetek()) {
  2158.                 if(current->capon) {
  2159.                     fclose(current->capfp);
  2160.                     current->capon=capon=0;
  2161.                   }
  2162.                 VSreset(current->vs);        /* reset's emulator */
  2163.               }
  2164.             wrest(current);
  2165.             c=0;
  2166.             break;
  2167.  
  2168.         case ALTS:                        /* skip to end */
  2169.             c=0;
  2170.             RSvis(0);
  2171.             while(0<(i=netread(t1->pnum,s,500)))
  2172.                 parse(t1,s,i);
  2173.             viewmode=10;
  2174.             break;
  2175.  
  2176.         case ALTU:                /* erase line */
  2177.             netpush(t1->pnum);
  2178.             netwrite(t1->pnum,"\377\370",2);
  2179.             c=0;
  2180.             break;
  2181.                 
  2182.         case ALTV:                /* paste clipboard into buffer */
  2183.             if(copybuf!=NULL) {
  2184.                 temp=size;
  2185.                 viewmode=11;
  2186.               }
  2187.             c=0;
  2188.             break;
  2189.  
  2190.         case ALTW:                /* send our password to the machine we are connected to, for use in ftp'ing back to oneself */
  2191.             bypass_passwd=1;    /* set the flag to bypass the password check */
  2192.             c=0;
  2193.             break;
  2194.  
  2195.         case ALTX:                        /* close the connection */
  2196.             leavetek();
  2197.             n_puts("\n Are you sure you want to close the connection? Y/N");
  2198.             c=nbgetch();                /* get the answer */
  2199.             if(tolower(c)=='y') {
  2200.                 n_puts("\n Attempting to close . . .");
  2201.                 netclose(t1->pnum);
  2202.                 Stask();
  2203.                 netputuev(CONCLASS,CONCLOSE,t1->pnum);
  2204.               }
  2205.             else
  2206.                 viewmode=10;            /* redraw screen */
  2207.             c=0;
  2208.             break;
  2209.  
  2210.         case ALTY:                /* interrupt */
  2211.             netpush(t1->pnum);
  2212.             netwrite(t1->pnum,"\377\364",2);
  2213.             t1->timing=1;
  2214.             netwrite(t1->pnum,"\377\375\006",3);
  2215.             c=0;
  2216.             break;
  2217.  
  2218.         case ALTZ:                    /* view console */
  2219.             c=0;
  2220.             leavetek();
  2221.             wrest(console);
  2222.             viewmode=2;                /* console view mode */
  2223.             break;
  2224.  
  2225. #ifdef DEBUG
  2226.         case AF9:
  2227.             statcheck();
  2228.             break;
  2229. #endif
  2230.  
  2231.         case EXIT_TELNET:            /* abort Telnet */
  2232.             return(EXIT_TELNET);
  2233.  
  2234.         default:
  2235.             break;
  2236.       }    /* end switch */
  2237.  
  2238.     if(c>0)
  2239.         vt100key(c);            /* send it, with VT100 translation */
  2240.     return(c);
  2241. }
  2242.  
  2243. /***************************************************************************/
  2244. /*  dosescape
  2245. *  escape to dos for processing
  2246. *  put the connections to automated sleep while in DOS
  2247. */
  2248. void dosescape(void )
  2249. {
  2250.     int i;
  2251.     char *command_shell;        /* the command shell to shell out to */
  2252.     char oldDir[1024];
  2253.  
  2254.     if(ftpact || rcpact) {
  2255.         n_puts("Please wait until file transfer is finished");
  2256.         n_puts("\nPress any key to continue");
  2257.         return;
  2258.     }
  2259.  
  2260.     getcwd(oldDir,1023);
  2261.     n_clear();
  2262.     n_cur(0,0);
  2263.     n_puts("Warning, some programs will interfere with network communication and can");
  2264.     n_puts("cause lost connections.  Do not run any network programs from this DOS shell.");
  2265.     n_puts("Type 'EXIT' to return to NCSA Telnet");
  2266. /*
  2267. *  invoke a put-to-sleep routine which calls netsleep every 8/18ths of a sec
  2268. *  Also:  disable ftp,rcp when asleep and suppress error messages
  2269. */
  2270.     restore_break();        /* restore the break status */
  2271. /*    if(def.ega43>0)         /* if we are 43 or 50 line switch to 24 line */
  2272. /*        ega24();        */
  2273.     restore_cursor();       /* restore the user's keyboard cursor */
  2274.     remove_break();            /* restore the previous ctrl-c interupt handler */
  2275.  
  2276.     netsleep(0);
  2277.  
  2278.     tinst();
  2279.  
  2280. /*  set_mode();             /* set video mode to what it was before telnet */
  2281.  
  2282.     command_shell = getenv("COMSPEC");        /* search for the user's COMSPEC */
  2283.  
  2284.     if(command_shell!=NULL)        /* make certain that the COMSPEC exists */
  2285.         i=system(command_shell);        /* call DOS */
  2286.     else        /* tell the user if it doesn't */
  2287.         i=-1;
  2288.     tdeinst();
  2289.  
  2290.     if(i<0) {
  2291.         n_puts("\n\nError loading DOS shell");
  2292.         n_puts("Make sure DOS shell is specified under COMSPEC.");
  2293.         n_puts("It must also be in a directory which is in your PATH statement.");
  2294.     }
  2295.     chdir(oldDir);
  2296.  
  2297.     install_break((int *)&foundbreak);            /* install our ctrl-c interupt handler */
  2298.     save_cursor();                /* save the user's keyboard cursor */
  2299. /*    if(def.ega43) */
  2300. /*        ega43();                /* switch back to 43 line mode */
  2301. /*    else          */
  2302. /*        ega24();  */
  2303.     n_row();
  2304.     n_puts("\nPress any key to return to telnet");
  2305.     save_break();                /* save the break state again */
  2306. }
  2307.  
  2308. /***********************************************************************/
  2309. /*  creatwindow
  2310. *   returns a pointer to a new window
  2311. */
  2312. struct twin *creatwindow(void )
  2313. {
  2314.     struct twin *p;
  2315.     int i;
  2316.  
  2317.     p=(struct twin *)malloc(sizeof(struct twin));
  2318.     if(p==NULL)
  2319.         return(NULL);
  2320.     p->pnum=-1;
  2321.     p->telstate=0;
  2322.     p->substate=0;
  2323.     p->termsent=0;
  2324.     if(vton)
  2325.         p->termstate=basetype;
  2326.     else
  2327.         p->termstate=DUMBTYPE;
  2328.     p->linemode[0]=0;
  2329.     p->echo=1;
  2330.     p->binary=0;
  2331.     p->ugoahead=0;        /* we want goahead suppressed */
  2332.     p->igoahead=0;        /* we want goahead suppressed */
  2333.     p->timing=0;
  2334.     p->capon=0;
  2335.     p->next=NULL;
  2336.     p->prev=NULL;
  2337.     p->lmflag=0;
  2338.     p->mapoutput=default_mapoutput;        /* turn output mapping on if specified */
  2339.  for(i=1; i<NUMLMODEOPTIONS; i++)
  2340.         p->slc[i]=-1;
  2341.     p->sstat='*';                /* connection not opened yet */
  2342.  
  2343.     if(mp==NULL) {
  2344.         p->bksp=127;
  2345.         p->del=8;
  2346.         p->crfollow=10;
  2347.         p->halfdup=0;
  2348.         p->vtwrap=1;
  2349.         p->bkscroll=0;
  2350.         p->width=80;
  2351.         p->rows=numline+1;
  2352.         p->slc[SLC_IP]=3;
  2353.         p->slc[SLC_EC]=127;
  2354.         p->slc[SLC_EL]=21;
  2355.         p->slc[SLC_SUSP]=26;
  2356.         p->slc[SLC_EOF]=4;
  2357.         p->slc[SLC_ABORT]=3;
  2358.         p->ftpopts=NULL;
  2359.  
  2360.         for(i=0; i<3; i++)                    /* start default colors */
  2361.             p->colors[i]=colors[i];
  2362.  
  2363. /****!*!*!*!*!*!*!*!*!*!*!*!*****/
  2364.         i=VSnewscreen(500,1,80,0);            /* create a new virtual screen */
  2365.         VSsetlines(i,numline+1);
  2366.         VSsetrgn(i,0,0,79,numline);
  2367.       }
  2368.     else {
  2369.         p->bksp=mp->bksp;
  2370.         if(p->bksp==127)
  2371.             p->del=8;
  2372.         else
  2373.             p->del=127;
  2374.         p->crfollow=mp->crmap;
  2375.         p->halfdup=mp->halfdup;
  2376.         p->vtwrap=mp->vtwrap;
  2377.         p->bkscroll=mp->bkscroll;
  2378.         p->width=mp->vtwidth;
  2379.         p->rows=numline+1;
  2380.         p->colors[0]=mp->nfcolor + (mp->nbcolor<<4);
  2381.         p->colors[1]=mp->ufcolor + (mp->ubcolor<<4);
  2382.         p->colors[2]=mp->bfcolor + (mp->bbcolor<<4);
  2383.         p->slc[SLC_IP]=3;
  2384.         p->slc[SLC_EC]=mp->bksp;
  2385.         p->slc[SLC_EL]=21;
  2386.         p->slc[SLC_EOF]=4;
  2387.         p->slc[SLC_SUSP]=26;
  2388.         p->slc[SLC_ABORT]=3;
  2389.         p->ftpopts=mp->ftpoptions;
  2390.  
  2391.         i=VSnewscreen(mp->bkscroll,1,80,0);    /* create a new virtual screen */
  2392.         VSsetlines(i,numline+1);
  2393.         VSsetrgn(i,0,0,79,numline);
  2394.  
  2395.         if(i>=0 && mp->vtwrap)
  2396.             VSwrite(i,"\033[?7h",5);        /* turn wrap on */
  2397.         VSscrolcontrol(i,-1,mp->clearsave);    /* set clearsave flag */
  2398.       }
  2399.  
  2400.     if(i<0)
  2401.         return(NULL);
  2402.     p->vs=i;
  2403.     screens[i]=p;                        /* we need to know where it is */
  2404.     return(p);
  2405. }
  2406.  
  2407. /***********************************************************************/
  2408.  
  2409. void wrest(t)
  2410. struct twin *t;
  2411. {
  2412.     RSvis(t->vs);
  2413.     statline();                        /* done before, moves cursor */
  2414.     VSredraw(t->vs,0,0,79,numline);        /* redisplay, resets cursor correctly */
  2415. }
  2416.  
  2417. /***************************************************************************/
  2418. void statline(void )
  2419. {
  2420.     struct twin *t1,*t2;
  2421.     int wn;
  2422.     int i,c,sm,rw,cl;
  2423.  
  2424.     if(current==NULL || current==console || current->termstate==TEKTYPE)
  2425.         return;
  2426.     c=n_color(current->colors[0]);            /* save current color */
  2427.     if(current->sstat!='*')
  2428.         current->sstat=254;                    /* this is current one */
  2429.     rw=n_row();
  2430.     cl=n_col();
  2431.     t1=t2=current;
  2432.     wn=0;
  2433.     sm=Scmode();
  2434.     do {
  2435.         n_cur(numline+1,wn*15);
  2436.         n_color(t1->colors[2]);
  2437.         if(t1->sstat==254 && t1!=current)
  2438.             t1->sstat=176;
  2439.         n_putchar((char)t1->sstat);
  2440.         n_putchar(' ');
  2441.         i=strlen(t1->mname);
  2442.         if(i>=13) {        /* check for too long of a name */
  2443.             if(sm)
  2444.                 n_cheat(t1->mname,13);            /* machine name of connection */
  2445.             else
  2446.                 n_draw(t1->mname,13);            /* machine name of connection */
  2447.           }    /* end if */
  2448.         else {
  2449.             if(sm) {
  2450.                 n_cheat(t1->mname,i);            /* machine name of connection */
  2451.                 n_cheat(blankline,13-i);        /* fill out to 13 spaces */
  2452.               }
  2453.             else {
  2454.                 n_draw(t1->mname,i);            /* machine name of connection */
  2455.                 n_draw(blankline,13-i);            /* fill out to 13 spaces */
  2456.               }
  2457.           }    /* end else */
  2458.         if(t1->next)                        /* if not the only window open */
  2459.             t1=t1->next;
  2460.         wn++;
  2461.       }    while(t1!=current && wn<4);
  2462.     n_color(current->colors[0]);
  2463.     n_cur(numline+1,wn*15);
  2464.     if(def.clock)    /* if we have a clock, then only fill up to the edge of the capture indicator */
  2465.         if(sm)
  2466.             n_cheat(blankline,71-wn*15);            /* fill to edge of screen */
  2467.         else
  2468.             n_draw(blankline,71-wn*15);             /* fill to edge of screen */
  2469.     else        /* for no clock, fill all the way across the bottom of the screen */
  2470.         if(sm)
  2471.             n_cheat(blankline,80-wn*15);            /* fill to edge of screen */
  2472.         else
  2473.             n_draw(blankline,80-wn*15);                /* fill to edge of screen */
  2474.  
  2475.     if(wn>3 && (t1!=t2)) {        /* check whether to display the '\' */
  2476.         i=176;        /* display a '\' if any of the windows has data and those windows don't appear on the statline, (windows>4) */
  2477.         while(t1!=t2 && i!=14) {
  2478.             if(t1->sstat!=254 && t1->sstat!=176)    /* check for a different status character */
  2479.                 i=t1->sstat;
  2480.             if(t1->next)    /* go to the next window if there is one */
  2481.                 t1=t1->next;
  2482.           }    /* end while */
  2483.         n_color(current->colors[0]);
  2484.         n_cur(numline+1,71);
  2485.         n_putchar((char)i);
  2486.       }    /* end if */
  2487.     else {    /* just display a blank */
  2488.         n_color(current->colors[0]);
  2489.         n_cur(numline+1,71);
  2490.         n_putchar((char)' ');
  2491.       } /* end else */
  2492.  
  2493.     if(current->capon)                              /* put capture flag status */
  2494.         capstat("Capt",1);
  2495.     else
  2496.         capstat("    ",0);
  2497.  
  2498.     n_color(c);
  2499.     n_cur(rw,cl);
  2500. }
  2501.  
  2502. /***********************************************************************/
  2503. /*  inswindow
  2504. *    insert a window into the circular linked list
  2505. *
  2506. *   current is used as a reference point for the new entry, the new entry
  2507. *   is put next in line past "current"
  2508. */
  2509. void inswindow(t,wtype)
  2510. struct twin *t;
  2511. int wtype;
  2512. {
  2513.     struct twin *p,*q;
  2514.  
  2515. /*
  2516. *   put it into the port number array
  2517. */
  2518.     if(wtype)
  2519.         wins[t->pnum]=t;
  2520.  
  2521. /*
  2522. *  check for the NULL case for current.
  2523. */
  2524.     if(current==NULL || current==console) {
  2525.         current=t; 
  2526.         statline();
  2527.         return;
  2528.       }
  2529.     p=current;                    /* find surrounding elements */
  2530.     if(p->prev==NULL) {            /* only one now, we are adding 2nd */
  2531.         t->next=p;
  2532.         t->prev=p;
  2533.         p->next=t;
  2534.         p->prev=t;
  2535.       }
  2536.     else {                            /* adding third or more */
  2537.         q=p->next;                /* find next one */
  2538.         t->prev=p;
  2539.         t->next=q;                /* insert it as next after current */
  2540.         q->prev=t;
  2541.         p->next=t;
  2542.       }
  2543. }
  2544.  
  2545. /***********************************************************************/
  2546. /*  delwindow()
  2547. *   take a window out of the linked list
  2548. */
  2549. void delwindow(t,wtype)
  2550. struct twin *t;
  2551. int wtype;
  2552. {
  2553.     struct twin *p,*q;
  2554.  
  2555.     if(wtype)    
  2556.         wins[t->pnum]=NULL;        /* take out of array */
  2557.     p=t->prev;
  2558.     q=t->next;
  2559.     if(p==NULL) {                /* is only node */
  2560.         freewin(t);
  2561.         current=console;
  2562.         return;
  2563.       }    /* end if */
  2564.     if(p==q) {                /* two in list */
  2565.         p->next=NULL;
  2566.         p->prev=NULL;
  2567.       }    /* end if */
  2568.     else {
  2569.         q->prev=p;
  2570.         p->next=q;            /* merge two links */
  2571.       }    /* end else */
  2572.     freewin(t);                /* release the space */
  2573. }    /* end delwindow() */
  2574.  
  2575. /************************************************************************/
  2576. /*  freewin
  2577. *   deallocate and detach all associated memory from a window
  2578. */
  2579. void freewin(t)
  2580. struct twin *t;
  2581. {
  2582.     VSdetatch(t->vs);
  2583.     free(t);
  2584. }    /* end freewin() */
  2585.  
  2586. /************************************************************************/
  2587. /*
  2588. *  hexbyte
  2589. *   return a byte taken from a string which contains hex digits
  2590. */
  2591. int hexbyte(st)
  2592. char *st;
  2593. {
  2594.     int i;
  2595.  
  2596.     if(*st>='A')
  2597.         i=((*st|32)-87)<<4;
  2598.     else
  2599.         i=(*st-48)<<4;
  2600.     st++;
  2601.     if(*st>'A')
  2602.         i|=(*st|32)-87;
  2603.     else
  2604.         i+=(*st-48);
  2605.     return(i);
  2606. }
  2607.  
  2608. /***********************************************************************/
  2609. /* tekinit
  2610. *  tektronix initialization
  2611. */
  2612. #ifdef USETEK
  2613. int tekinit(dev)
  2614. char *dev;
  2615. {
  2616.     if(strlen(dev)<1)
  2617.         return(0);
  2618. #ifdef OLD_WAY
  2619.     if(0>VGinit()) {
  2620.         vprint(console->vs,"\r\nCannot initialize Tektronix driver\r\n");
  2621.         return(-1);
  2622.       }
  2623.     else
  2624.         vprint(console->vs,"\r\nTektronix initialized\r\n");
  2625. #else
  2626.     VGinit();
  2627.     vprint(console->vs,"\r\nTektronix initialized\r\n");
  2628. #endif
  2629.     if(!strcmp(dev,"vga")) 
  2630.         rgdevice=7;
  2631.           /* end if */
  2632.     else if(!strcmp(dev,"no9"))
  2633.         rgdevice=4;
  2634.     else if(!strcmp(dev,"ega"))
  2635.         rgdevice=1;
  2636.     else if(!strcmp(dev,"hercules"))
  2637.         rgdevice=3;
  2638.     else if(!strcmp(dev,"cga") || !strcmp(dev,"pga"))
  2639.         rgdevice=5;
  2640.     else
  2641.         rgdevice=0;                /* null device */
  2642.     basetype=VTEKTYPE;
  2643.     temptek=VGnewwin(rgdevice);    /* default for drawing */
  2644.     return(0);
  2645. }
  2646.  
  2647. /***********************************************************************/
  2648. /*  function to write to file
  2649. */
  2650. void fdump(str)
  2651. char *str;
  2652. {
  2653.     fputs(str,tekfp);
  2654. }
  2655.  
  2656. void fdumpc(c)
  2657. int c;
  2658. {
  2659.     fputc(c,tekfp);
  2660. }
  2661.  
  2662. void endump(void )
  2663. {
  2664.     VGclose(outdev);
  2665.     if(indev!=temptek) {
  2666.         VGclose(indev);
  2667.         if(tekfp) {
  2668.             fclose(tekfp);
  2669.             tekfp=NULL;
  2670.          }
  2671.       }
  2672. }
  2673.  
  2674. /***********************************************************************/
  2675. /* graphit
  2676. *  Get some user choices and execute them
  2677. */
  2678. int graphit(void )
  2679. {
  2680.     int i,j,k,l,c;
  2681.  
  2682.     c=n_chkchar();
  2683.     if(c==27)
  2684.         return(1);
  2685.     if(c<0)
  2686.         return(0);
  2687.     switch (c) {
  2688.         case F2:
  2689.         case F4:
  2690.         case F6:    /* prompting for file name */
  2691.             n_puts("\nEnter new file name:");
  2692.             nbgets(s,50);
  2693.             if(s[0] && s[0]!=' ') {
  2694.                 switch(c) {
  2695.                     case F2:
  2696.                         Snewpsfile(s);
  2697.                         break;
  2698.  
  2699.                     case F4:
  2700.                         Snewhpfile(s);
  2701.                         break;
  2702.  
  2703.                     case F6:
  2704.                         Snewtekfile(s);
  2705.                         break;
  2706.                   }
  2707.                 Sgetconfig(&def);
  2708.               }
  2709.             dispgr();                        /* leave in graphit mode */
  2710.             return(0);
  2711.  
  2712.         case F1:            /* postscript dump */
  2713.             if(*def.psfile=='+') {
  2714.                 if(NULL==(tekfp=fopen(&def.psfile[1],"a")))
  2715.                     return(1);
  2716.                 fseek(tekfp,0L,2);      /* to end */
  2717.               }
  2718.             else 
  2719.                 if(NULL==(tekfp=fopen(def.psfile,"w"))) 
  2720.                     return(1);
  2721. #ifdef MSC
  2722.             RGPoutfunc(fdump);        /* set function */
  2723. #else
  2724.             RGPoutfunc(&fdump);        /* set function */
  2725. #endif
  2726.             outdev=VGnewwin(2);
  2727.             indev=temptek;
  2728.             temptek=VGnewwin(rgdevice);
  2729.             VGgmode(2);
  2730.             VGzcpy(indev,temptek);
  2731.             VGzcpy(indev,outdev);
  2732.             VGuncover(outdev);
  2733.             VGpage(outdev);
  2734.             if(VGpred(indev,outdev))
  2735.                 endump();
  2736.             else
  2737.                 netputevent(USERCLASS,PSDUMP,1);        /* remind myself */
  2738.             return(1);
  2739.                     
  2740.         case F3:            /* HPGL dump */
  2741.             if(*def.hpfile=='+') {            /* append feature */
  2742.                 if(NULL==(tekfp=fopen(&def.hpfile[1],"a"))) 
  2743.                     return(1);
  2744.                 fseek(tekfp,0L,2);
  2745.               }
  2746.             else 
  2747.                 if(NULL==(tekfp=fopen(def.hpfile,"w"))) 
  2748.                     return(1);
  2749. #ifdef MSC
  2750.             RGHPoutfunc(fdump);        /* set function */
  2751. #else
  2752.             RGHPoutfunc(&fdump);        /* set function */
  2753. #endif
  2754.             outdev=VGnewwin(6);
  2755.             indev=temptek;
  2756.             temptek=VGnewwin(rgdevice);
  2757.             VGgmode(6);
  2758.             VGzcpy(indev,temptek);
  2759.             VGzcpy(indev,outdev);
  2760.             VGuncover(outdev);
  2761.             VGpage(outdev);
  2762.             if(VGpred(indev,outdev))
  2763.                 endump();
  2764.             else
  2765.                 netputevent(USERCLASS,PSDUMP,1);        /* remind myself */
  2766.             return(1);
  2767.  
  2768.         case F5:            /* tektronix dump */
  2769.             if(*def.tekfile=='+') {
  2770.                 if(NULL==(tekfp=fopen(&def.tekfile[1],"ab"))) 
  2771.                     return(1);
  2772.                 fseek(tekfp,0L,2);
  2773.               }
  2774.             else 
  2775.                 if(NULL==(tekfp=fopen(def.tekfile,"wb"))) 
  2776.                     return(1);
  2777.             fputs("\033\014",tekfp);
  2778. #ifdef MSC
  2779.             VGdumpstore(temptek,fdumpc);
  2780. #else
  2781.             VGdumpstore(temptek,&fdumpc);
  2782. #endif
  2783.             fclose(tekfp);
  2784.             return(1);
  2785.  
  2786.         case F7:            /* tek view region */
  2787.             n_puts("\nEnter 0-4095 for lower left xy, upper right xy.");
  2788.             n_puts("\nExample:  0,0,4095,3119 is full view. (default if you leave it blank)");
  2789.             nbgets(s,30);
  2790.             if(4!=sscanf(s,"%d,%d,%d,%d",&i,&j,&k,&l))
  2791.                 VGzoom(temptek,0,0,4096,3119);
  2792.             else
  2793.                 VGzoom(temptek,i,j,k,l);
  2794.             dispgr();                        /* leave in graphit mode */
  2795.             return(0);
  2796.  
  2797.         case 13:
  2798.             if (!def.tek) break;
  2799.             current->termstate=TEKTYPE;
  2800.             VGgmode(rgdevice);
  2801.             VGuncover(temptek);
  2802.             outdev=temptek;                /* redraw to itself */
  2803.             indev=temptek;
  2804.             tekfp=NULL;
  2805.             if(!VGpred(indev,outdev))
  2806.                 netputevent(USERCLASS,PSDUMP,0);        /* remind myself */
  2807.              viewmode=0;                    /* normal logon state */
  2808.             break;
  2809.  
  2810.         default:
  2811.             break;
  2812.     }
  2813.     return(0);
  2814. }
  2815. #endif
  2816.  
  2817. /*************************************************************************/
  2818. /*  addsess
  2819. *   Add a session to a named machine, or prompt for a machine to be named.
  2820. */
  2821. int addsess(st)
  2822. char *st;
  2823. {
  2824.     int i,new,cv,pflag=0,port=0;
  2825.     struct twin *newin;
  2826.  
  2827.     leavetek();
  2828.     cv=console->vs;
  2829.     if(st==NULL) {            /* no machine yet */
  2830.         wrest(console);
  2831.         vprint(cv,"\n\r\nEnter new machine name/address, ESC to return: \r\n");
  2832.         s[0]='\0';
  2833.         while(0>=(i=RSgets(cv,s,70,1)))
  2834.             Stask();
  2835.         if(i==27 || !s[0])
  2836.             return(1);
  2837.         vprint(cv,"\n\r\n");    /* skip down a little */
  2838.         st=s;                    /* make a copy of the pointer to s */
  2839.       }
  2840. /*
  2841. *    Find out what port to open to
  2842. */
  2843.     for (i=0; (st[i]!=' ') && (st[i]!='#') && (st[i]!='\0'); i++);
  2844.  
  2845.     if((st[i]=='#') || (st[i]==' ')) {
  2846.         st[i++]='\0';
  2847.         new=i;
  2848.         pflag=1;
  2849.         for( ; (st[i]!='\0') && isdigit(st[i]) ; i++);
  2850.          if(st[i]!='\0') 
  2851.             pflag=0;
  2852.         if(pflag) 
  2853.             port=(unsigned int)atoi(&st[new]);
  2854.       }
  2855.     mp=Sgethost(st);            /* gain access to host information */
  2856.     errhandle();
  2857.     if(!mp) {
  2858.         if(pflag)
  2859.             st[strlen(st)]='#';    /* Append port number */
  2860.         if(Sdomain(st)>0) 
  2861.             vprint(cv,"\r\nQuerying the DOMAIN name server\r\n");
  2862.         else {
  2863.             vprint(cv,"\r\nNo nameserver, cannot resolve IP address\r\n");
  2864.             return(-1);
  2865.           }
  2866.       }
  2867.     else {
  2868. /*
  2869. *   tell user about it on the console
  2870. */
  2871.         vprint(cv,"\r\nTrying to open TCP connection to: ");
  2872.         vprint(cv,st);
  2873.         vprint(cv,"\r\n");
  2874.         if(!pflag) 
  2875.             port=mp->port;
  2876.  
  2877.     
  2878.     /* try to serve the request */
  2879.         if( 0>(new=Snetopen(mp,port))) {
  2880.             errhandle();
  2881.             vprint(cv,"\r\nCould not open new connection to: ");
  2882.             vprint(cv,st);
  2883.             vprint(cv,"\r\n");
  2884.             return(-1);
  2885.           }
  2886.         newin=creatwindow();
  2887.         if(!newin) {                /* mem error */
  2888.             vprint(console->vs,"\r\nMemory Allocation error for window\r\n");
  2889.             return(-1);
  2890.           }
  2891.         newin->pnum=new;
  2892.         strncpy(newin->mname,st,14);
  2893.         newin->mname[14]='\0';
  2894.         inswindow(newin,1);
  2895.         vhead(newin->vs);
  2896.       }
  2897.     return(0);
  2898. }
  2899.  
  2900. #ifdef USETEK
  2901. int leavetek(void )
  2902. {
  2903.     if(current->termstate==TEKTYPE) {
  2904.         VGwrite(temptek,"\037",1);            /* force to alpha */
  2905.         current->termstate=VTEKTYPE;
  2906.         VGtmode(rgdevice);
  2907.         resetgin();                /* make sure to reset the GIN mode */
  2908.                                 /* clear graphics mode */
  2909.         if(def.ega43) 
  2910.             ega43();
  2911.         return(1);
  2912.     }
  2913.     return(0);                    /* we did nothing */
  2914. }
  2915. #endif
  2916.  
  2917. /***********************************************************************/
  2918. /*  capstat
  2919. *    Print the capture status on the screen
  2920. */
  2921. void capstat(str,i)
  2922. char *str;
  2923. int i;
  2924. {
  2925.     int r,c,color;
  2926.  
  2927.     r=n_row();
  2928.     c=n_col();
  2929.     color=n_color(current->colors[i]);
  2930.     n_cur(numline+1,66);
  2931.     n_draw(str,strlen(str));
  2932.     n_color(color);
  2933.     n_cur(r,c);
  2934. }
  2935.  
  2936. /***********************************************************************/
  2937. /*  set_vtwrap
  2938. *    QAK - 7/29/90
  2939. *    set the vtwrap parameter for any telnet window, added because changing
  2940. *    a virtual screen's auto-wrapping had no way to change the telnet window's
  2941. *    wrapping state
  2942. */
  2943. void set_vtwrap(vs_win,value)
  2944. int vs_win,value;
  2945. {
  2946.     struct twin *temp_window;
  2947.  
  2948.     temp_window=screens[vs_win];        /* get a pointer to the window for the virtual screen */
  2949.     if(temp_window!=NULL)
  2950.         temp_window->vtwrap=(unsigned char)value;        /* set the virtual screen's wrapping */
  2951. }    /* end set_vtwrap() */
  2952.  
  2953. #ifdef DEBUG
  2954. void heapdump(void)
  2955. {
  2956.  
  2957.     struct _heapinfo hinfo;
  2958.     long free_mem=0;
  2959.     int heapstatus;
  2960.  
  2961.     hinfo._pentry = NULL;
  2962.     while ((heapstatus = _heapwalk(&hinfo)) == _HEAPOK){
  2963.         free_mem+= (hinfo._useflag == _USEDENTRY ? 0 : hinfo._size);
  2964.         printf("%6s block at %p of size %4.4X\n",
  2965.                 (hinfo._useflag == _USEDENTRY ? "USED" : "FREE"),
  2966.                 hinfo._pentry, hinfo._size);
  2967.  
  2968.         }
  2969.     switch(heapstatus){
  2970.         case _HEAPEMPTY:
  2971.             printf("OK - empty heap\n\n");
  2972.             break;
  2973.         case _HEAPEND:
  2974.             printf("OK - end of heap \n\n");
  2975.             break;
  2976.         case _HEAPBADPTR:
  2977.             printf("ERROR - bad pointer to heap \n\n");
  2978.             break;
  2979.         case _HEAPBADBEGIN:
  2980.             printf("ERROR - bad start of heap \n\n");
  2981.             break;
  2982.         case _HEAPBADNODE:
  2983.             printf("ERROR - bad node in heap \n\n");
  2984.     }
  2985.     printf("free_mem=%ld\n",free_mem);
  2986. }
  2987.  
  2988. void print_windowlist(void )
  2989. {
  2990.  
  2991.     struct twin *p, *q;
  2992.  
  2993.     wrest(console);
  2994.     n_clear();
  2995.     p=q=current;
  2996.     printf("List of Machines following NEXT list\n");
  2997.     do{
  2998.         printf("Host is %s\n",p->mname);
  2999.         p=p->next;
  3000.         } while(p!=q);
  3001.     printf("Hit any key for prev list\n");
  3002.     getch();
  3003.     n_clear();
  3004.     p=q=current;
  3005.     printf("List of Machines following PREV list\n");
  3006.     do{
  3007.         printf("Host is %s\n",p->mname);
  3008.         p=p->prev;
  3009.         } while(p!=q);
  3010.     printf("Hit any key to return to normal\n");
  3011.     getch();
  3012. }
  3013. #endif
  3014.