home *** CD-ROM | disk | FTP | other *** search
/ GRIPS 2: Government Rast…rocessing Software & Data / GRIPS_2.cdr / dos / ncsa_tel / tel_2_2_ / source / look.c < prev    next >
C/C++ Source or Header  |  1988-07-15  |  55KB  |  2,282 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. */
  21. #define WINMASTER
  22. #define USETEK 
  23. /* #define USERAS */
  24. #define HTELNET 23
  25.  
  26. #ifndef USETEK
  27. #define leavetek() 0
  28. #endif
  29.  
  30. #include "stdio.h"
  31. #include "whatami.h"
  32. #include "signal.h"
  33. #include "fcntl.h"
  34. #include "nkeys.h"
  35. #include "windat.h"
  36. #include "hostform.h"
  37.  
  38. struct twin *creatwindow(),*newin;
  39.  
  40. FILE *tekfp;
  41.  
  42. int stand=0,
  43.     basetype = VTTYPE,
  44.     ftpact=0,                    /* ftp transfer is active */
  45.     rcpact=0,                    /* rcp transfer is active */
  46.     viewmode=0,                    /* What are we looking at? */
  47.     transok=1,                    /* is file transfer enabled? */
  48.     temptek,                    /* where drawings go by default */
  49.     indev,outdev,                /* for copying tek images */
  50.     rgdevice=0,                    /* tektronix device to draw on */
  51.     vton=1,
  52.     capon=0,                    /* overall capture on or not */
  53.     foundbreak=0,                /* trap Ctrl-C */
  54.     machparm=0;
  55.  
  56. unsigned char s[550],parsedat[128],
  57.         colors[NCOLORS] = {2,1,0x70,0},        /* base colors */
  58.         myipnum[4],
  59.         *neterrstring(),
  60.         *malloc(),
  61. *blankline = {"                                                                                       "};
  62.  
  63. int breakstop(),errhandle();
  64. long int time(),n_clicks(),lastt;
  65.  
  66. struct config def;                /* Default settings obtained from host file */
  67. struct machinfo *mp=NULL;        /* Pointer to a machine information structure */
  68.  
  69. #define PSDUMP 128
  70.  
  71. main(argc,argv)
  72.     int argc;
  73.     char *argv[];
  74.     {
  75.     int i,j;
  76.  
  77.     n_clear();                        /* do you know where your BP is? */
  78.     n_cur(0,0);
  79.     n_window(0,0,23,79);            /* vt100 size */
  80.     n_color(2);
  81.     n_puts("NCSA Telnet, reading configuration file . . .");
  82.  
  83. #define  USAGE   printf("\n\nUsage: telnet [-s] [-t] [-c color] [-h hostfile] [machinename] ...")
  84.  
  85.     if (*argv[1] == '?') {
  86.         USAGE;
  87.         n_row();
  88.         n_puts("\n\n -c 172471    sets the basic color scheme for console screen");
  89.         n_puts(" -h file      full path specification of host information file");
  90.         n_puts(" -s           standalone (server) mode for rcp and ftp");
  91.         n_puts(" -t           disable direct writes to screen");
  92.         exit(1);
  93.     }
  94.  
  95.     machparm = 1000;            /* large number */
  96. /*
  97. *  work on parms
  98. */
  99.     for (i=1; i<argc; i++) {        /* look at each parm */
  100.         if (*argv[i] == '-') {
  101.             switch ( *(argv[i]+1)) {
  102.                 case 'c':                /* set foreground color */
  103.                     i++;
  104.                     for (j=0; j < NCOLORS && *(argv[i]+j*2); j++)
  105.                         colors[j] = hexbyte(argv[i]+j*2);
  106.  
  107.                     break;
  108.                 case 's':
  109.                     stand = 1;
  110.                     break;
  111.                 case 't':              /*  Disable direct writes to screen  */
  112.                     Scwritemode(0);
  113.                     break;
  114.                 case 'h':
  115.                     Shostfile(argv[++i]);    /* set new name for host file */
  116.                     break;
  117.                 default:
  118.                     USAGE;
  119.                     exit(1);
  120.             }
  121.         }
  122.         else {
  123.             if (i < machparm)
  124.                 machparm = i;            /* where first machine name is */
  125.         }
  126.  
  127.     }
  128.  
  129.     for (i=0; i < NPORTS; i++)
  130.         wins[i] = NULL;                        /* we are using no windows yet */
  131. /*
  132. * create console window for errors, informative messages, etc.
  133. */
  134.     if (0 > VSinit(30))    {                /* initialize GPs virtual screens */
  135.         n_puts("Virtual screen initialization failed.");
  136.         exit(1);
  137.     }
  138.  
  139.     if (NULL == (console = creatwindow())) {
  140.         n_puts("Console memory allocation failed");
  141.         exit(1);
  142.     }
  143.  
  144.     strcpy(console->mname,"Console");
  145.  
  146. /*
  147. * introductions on the console window
  148. */
  149.     i = console->vs;
  150.     RSvis(-1);
  151.     vprint(i,"\n\n Console messages:\r\n\nNCSA Telnet\r\n");
  152.     vhead(i);
  153.  
  154. /*
  155. * initialize network stuff
  156. */
  157.  
  158.     if (j = Snetinit()) {
  159.         wrest(console);
  160.         errhandle();
  161.         vprint(i,"Error initializing network or getting configuration file\r\n");
  162.         if (j == -2)    /* RARP failure, special case */
  163.             netshut();
  164.         exit(1);
  165.     }
  166.  
  167.     netgetip(myipnum);            /* what is my ip number? */
  168.     Sgetconfig(&def);            /* get information provided in hosts file */
  169.  
  170. #ifdef USETEK
  171. /*
  172. *  install tektronix
  173. */
  174.     if (stmode())
  175.         tekinit(def.video);
  176. #endif
  177. #ifdef USERAS
  178.     if (!VRinit()) {
  179.         vprint(i,"Error initializing raster support\r\n");
  180.     }
  181. #endif
  182.  
  183. /*
  184. *  Display my ethernet and IP address for the curious people
  185. */
  186.     pcgetaddr(&s[200],def.address,def.ioaddr);
  187.     sprintf(s,"My Ethernet address: %x:%x:%x:%x:%x:%x\r\n",s[200],s[201],
  188.     s[202],s[203],s[204],s[205]);
  189.     vprint(console->vs,s);
  190.     sprintf(s,"My IP address: %d.%d.%d.%d\r\n\n",
  191.         myipnum[0],myipnum[1],myipnum[2],myipnum[3]);
  192.     vprint(console->vs,s);
  193.  
  194.  
  195. #ifdef MSC
  196.     signal(SIGINT,&breakstop);        /* Microsoft intercept of break */
  197. #else
  198.     onbreak(&breakstop);            /* Lattice intercept of break */
  199. #endif
  200.  
  201.     Stask();                    /* any packets for me? (return ARPs) */
  202.  
  203. /*
  204. *   With the parameters left on the command line, open a connection
  205. *   to each machine named.  Start up all of the configuration on open
  206. *   connections. 
  207. */
  208.     for (i = machparm; i < argc; i++) 
  209.         addsess(argv[i]);
  210.  
  211.     if (current == NULL) {           /* special viewmode for server mode */
  212.         current = console;            /* special enter sequence avoids flicker */
  213.         viewmode = 6;
  214.     }
  215.  
  216.     wrest(current);                 /* paint the first session's screen */
  217.  
  218.     while (AF3 != dosessions())     /* serve all sessions, events */
  219.         ;
  220.  
  221.     endall();
  222. }
  223.  
  224. /************************************************************************/
  225. /* vhead
  226. *  place the header for new sessions in.
  227. */
  228. vhead(v)
  229.     int v;
  230.     {
  231.     vprint(v,"\r\nNational Center for Supercomputing Applications\r\n");
  232.     vprint(v,"NCSA Telnet for the PC version 2.2S\r\n");
  233.     vprint(v,"\nAlt-H presents a summary of special keys \r\n\n");
  234. }
  235.  
  236. /************************************************************************/
  237. /*  dosessions
  238. *   dosessions is an infinite loop serving three sources of external
  239. *   input in order of precedence:
  240. *   - changes to the video display properties
  241. *   - keyboard strokes
  242. *   - network events
  243. *
  244. *   What the user sees is top priority followed by servicing the keyboard
  245. *   and when there is time left over, looks for network events.
  246. *
  247. *   viewmode is a state variable which can determine if the screen should
  248. *   be re-drawn, etc.
  249. */
  250.  
  251. dosessions() 
  252.     {
  253.     int i,j,c,cl,dat,cvs;
  254.     unsigned int sw;
  255.     struct twin *t1;
  256.     unsigned char *p;
  257.  
  258.     i = 0;
  259.     switch (viewmode) {
  260.         case 0:                    /* no special mode, just check scroll lock */
  261.         default:
  262.             if (n_scrlck()) {    /* scroll lock prevents text from printing */
  263.                 viewmode = 1;
  264.                 i = n_row();
  265.                 j = n_col();
  266.                 c = n_color(current->colors[2]);
  267.                 n_cur(24,60);
  268.                 n_draw("* Scroll Lock *",16);    /* status in lower left */
  269.                 n_color(c);
  270.                 n_cur(i,j);
  271.             }
  272. /*
  273. *  This gives precedence to the keyboard over the network.
  274. */
  275.             while (0 <= (c = newkey(current)))    /* do all key translations */
  276.                 if (c == AF3)
  277.                     return(AF3);
  278.                     break;            /* no special viewing characterisitics */
  279.  
  280.         case 1:                        /* scrollock is active */
  281.             if (!n_scrlck()) {
  282.                 VSsetrgn(current->vs,0,0,79,23);
  283.                 viewmode = 0;        /* set back if appropriate */
  284.                 statline();
  285.             }
  286. /* 
  287. *  In scroll lock mode, take keys only for the scrollback, 
  288. *  The scrollback routine will never block, so we keep servicing events.
  289. */
  290.             scrollback();
  291.             break;
  292.         case 2:                        /* console is visible */
  293.             viewmode = 9;            /* check keypress before redrawing */
  294.             break;
  295.         case 3:                        /* help screen view1 */
  296.         case 4:                        /* help screen view2 */
  297.             while (0 <= (c = n_chkchar())) {    
  298.                 if (c == AF3)
  299.                     return(AF3);
  300.                 if (viewmode == 3 && c == 27) {
  301.                     viewmode = 4;
  302.                     help2(c);
  303.                 }
  304.                 else {                  /* restore view 0 */
  305.                     if (c > 128)
  306.                         dokey(current,c);
  307. /*    dokey might change view, if so, don't reset view 0 */
  308.                     if (viewmode >= 3 && viewmode <= 4)
  309.                         viewmode = 10;
  310.                 }
  311.             }
  312.             break;
  313.  
  314.         case 5:                        /* DOS screen view */
  315.             viewmode = 9;            /* wait for keypress */
  316.             break;
  317.  
  318.         case 6:                        /* server mode */
  319.             vprint(console->vs,
  320.         "\r\nServer mode, press ESC to exit or ALT-A to begin a session\r\n");
  321.             viewmode = 7;
  322.         case 7:                        /* server mode 2 */
  323.             j = n_chkchar();
  324.             switch (j) {
  325.                 case 27:
  326.                     vprint(console->vs,"\r\n\n Ending server mode \r\n");
  327.                     return(AF3);    /* leave the program */
  328.                     break;
  329.                 case ALTA:
  330.                     if (!addsess(NULL)) {    /* start up a new one */
  331.                         viewmode = 10;
  332.                     }
  333.                     else {
  334.                         current = console;
  335.                         viewmode = 6;
  336.                     }
  337.                     break;
  338.                 case -1:
  339.                     break;                /* no keypress */
  340.                 default:
  341.                     vprint(console->vs,
  342.                     "\r\nYou must have an open session to use other commands.\r\n");
  343.                     viewmode = 6;
  344.                     break;
  345.             }
  346.             break;
  347.  
  348.         case 8:
  349.             if (graphit())                /* graphics menu screen */
  350.                 viewmode = 10;
  351.             break;
  352.  
  353.         case 9:                            /* reset current screen on keypress */
  354.             if (0 < n_chkchar())
  355.                 viewmode = 10;    
  356.             break;
  357.  
  358.         case 10:                        /* Display current screen */
  359.             wrest(current);
  360.             viewmode = 0;                /* return to standard mode */
  361.             statline();    
  362.             break;
  363.  
  364.     }
  365.  
  366. /*
  367. *  Check for any relevant events that need to be handled by me
  368. */
  369.     if (0 < (i = Sgetevent(USERCLASS | CONCLASS | ERRCLASS, &cl, &dat))) {
  370.  
  371.         sw = cl*256 + i;                /* class and event combination */
  372.         cvs = console->vs;
  373.  
  374.         switch (sw) {
  375.             case CONCLASS*256+CONOPEN:
  376.                 /* a connection has just opened */
  377.                 t1 = wins[dat];            /* where the window pointer is stored */
  378.                 if (!t1)
  379.                     break;
  380.                 t1->sstat = '/';        /* connection status */
  381.                 netpush(dat);
  382.                 netwrite(dat,"\377\375\001\377\375\003",6);    /* telnet negotiate */
  383.                 if (current != t1) {
  384.                     current = t1;
  385.                     viewmode = 10;
  386.                 }
  387.                 break;
  388.             case CONCLASS*256+CONCLOSE:    /* connection is closing */
  389.                 if (0 < netqlen(dat))
  390.                     netputuev(CONCLASS,CONCLOSE,dat);  /* call me again */
  391.                     /* drop through, process any data */
  392.             case CONCLASS*256+CONDATA:
  393.                 if (viewmode) {            /* not ready for it */
  394.                     netputuev(CONCLASS,CONDATA,dat);
  395.                     break;
  396.                 }
  397.                 t1 = wins[dat];            /* where the window pointer is stored */
  398.                 if (!t1)
  399.                     break;
  400.                 if (inprocess(t1))
  401.                     return(AF3);
  402.                 break;
  403.             case CONCLASS*256+CONFAIL:    /* can't open connection */
  404.                 t1 = wins[dat];            /* where the window pointer is stored */
  405.                 if (!t1)
  406.                     break;                /* this don't count */
  407.                 vprint(cvs,"\r\nCan't open connection, timed out\r\n");
  408.                 netclose(dat);            /* close out attempt */
  409.                 if (!t1->next) {
  410.                     wrest(console);
  411.                     return(AF3);
  412.                 }
  413.                 if (t1 == current) {
  414.                     current = current->next;
  415.                     viewmode = 10;
  416.                 }
  417.                 delwindow(t1,1);
  418.                 statline();
  419.                 break;
  420. /*
  421. *  domain nameserver results.
  422. */
  423.             case USERCLASS*256+DOMFAIL:            /* domain failed */
  424.                 mp = Slooknum(dat);    /* get machine info */
  425.                 vprint(cvs,"\r\nDOMAIN lookup failed for: ");
  426.                 if (mp && mp->hname)
  427.                     vprint(cvs,mp->hname);
  428.                 else if (mp && mp->sname)
  429.                     vprint(cvs,mp->sname);
  430.                 vprint(cvs,"\r\n");
  431.                 break;
  432.             case USERCLASS*256+DOMOK:
  433.                 mp = Slooknum(dat);    /* get machine info */
  434.                 if (mp) {
  435.                     vprint(cvs,"\r\nDOMAIN lookup OK for: ");
  436.                     /* print session name and host name */
  437.                     if (mp->hname)
  438.                         vprint(cvs,mp->hname);
  439.                     if (mp->sname) {
  440.                         vprint(cvs," - ");
  441.                         vprint(cvs,mp->sname);
  442.                         addsess(mp->sname);
  443.                     }
  444.                     else
  445.                         addsess(mp->hname);
  446.                     vprint(cvs,"\r\n");
  447.                     viewmode = 10;
  448.                 }
  449.                 
  450.                 break;
  451. /*
  452. *  FTP status events.
  453. */
  454.             case USERCLASS*256+FTPBEGIN:        /* data connection */
  455.                 ftpact = dat;
  456.                 Sftpname(s);                    /* get name */
  457.                 vprint(cvs,"FTP transferring: ");
  458.                 vprint(cvs,s);
  459.                 vprint(cvs,"\r\n");
  460.                 ftpstart(ftpact+2,s);
  461.                 lastt = n_clicks();
  462.                 break;
  463.             case USERCLASS*256+FTPLIST:            /* LIST or NLST */
  464.                 vprint(cvs,"FTP directory beginning\r\n");
  465.                 break;
  466.             case USERCLASS*256+FTPEND:            /* data connection ending */
  467.                 ftpact = 0;
  468.                 statline();
  469.                 vprint(cvs,"FTP transfer done\r\n");
  470.                 break;
  471.             case USERCLASS*256+FTPCOPEN:        /* command connection */
  472.                 vprint(cvs,"FTP server initiated from host: ");
  473.                 Sftphost(s);
  474.                 if ((NULL == (mp = Slookip(s))) || (NULL == mp->sname)) 
  475.                     sprintf(&s[4],"%d.%d.%d.%d\r\n",s[0],s[1],s[2],s[3]);
  476.                 else
  477.                     sprintf(&s[4],"%s\r\n",mp->sname);
  478.                 vprint(cvs,&s[4]);
  479.                 break;
  480.             case USERCLASS*256+FTPUSER:            /* user name entered */
  481.                 vprint(cvs,"FTP user ");
  482.                 Sftpuser(s);
  483.                 vprint(cvs,s);
  484.                 vprint(cvs," login request\r\n");
  485.                 break;
  486.             case USERCLASS*256+FTPPWOK:            /* user password verified */
  487.                 vprint(cvs,"FTP Password verified\r\n");
  488.                 break;
  489.             case USERCLASS*256+FTPPWNO:            /* user password failed */
  490.                 vprint(cvs,"FTP Password failed verification\r\n");
  491.                 break;
  492.             case USERCLASS*256+FTPCLOSE:        /* command connection ends */
  493.                 vprint(cvs,"FTP server ending session\r\n");
  494.                 break;
  495.             case USERCLASS*256+RCPBEGIN:        /* rcp starting */
  496.                 vprint(cvs,"rcp file transfer\r\n");
  497.                 rcpact = 1;
  498.                 break;
  499.             case USERCLASS*256+RCPEND:            /* rcp ending */
  500.                 vprint(cvs,"rcp ending\r\n");
  501.                 rcpact = 0;
  502.                 break;
  503. #ifdef USETEK
  504.             case USERCLASS*256+PSDUMP:            /* dump graphics screen */
  505.                 if (VGpred(indev,outdev)) {
  506.                     if (dat) {
  507.                         endump();
  508.                         vprint(cvs,"Graphics writing finished\r\n");
  509.                         wrest(console);
  510.                         viewmode = 2;
  511.                     }
  512.                 }
  513.                 else
  514.                     netputevent(USERCLASS,PSDUMP,dat);    /* remind myself */
  515.                 break;
  516. #endif
  517.             case ERRCLASS*256+ERR1:                        /* error message */
  518.                 p = neterrstring(dat);
  519.                 VSwrite(cvs,p,strlen(p));
  520.                 VSwrite(cvs,"\r\n",2);
  521.             default:
  522.                 break;
  523.         }
  524.     }
  525. /*
  526. *   update the FTP spinner if we are in ftp
  527. */
  528.     else if (ftpact && (n_clicks() > lastt + 10)) {
  529.         ftpstart(ftpact+2,s);
  530.         lastt = n_clicks();
  531.     }
  532.  
  533.     return(c);
  534.  
  535. }
  536.  
  537. /*********************************************************************/
  538. /* inprocess
  539. *  take incoming data and process it.  Close the connection if it
  540. *  is the end of the connection.
  541. */
  542. inprocess(tw)
  543.     struct twin *tw;
  544.     {
  545.     int cnt;
  546.  
  547.     cnt = netread(tw->pnum,s,64);    /* get some from incoming queue */
  548.  
  549.     if (cnt < 0) {                    /* close this session, if over */
  550.         netclose(tw->pnum);
  551.  
  552.         if (tw->capon) {
  553.             fclose(tw->capfp);        /* close the capture file */
  554.             tw->capon = capon = 0;
  555.         }
  556.         n_color(tw->colors[0]);
  557.  
  558.         if (tw->next == NULL)         /* if this is the last one */
  559.             return(-1);                /* signal no sessions open */
  560.  
  561. #ifdef USETEK
  562.         leavetek();                    /* make Tek inactive */
  563. #endif
  564.         if (tw != current) {
  565.             wrest(tw);
  566.         }
  567.  
  568.         n_puts("\nConnection closed, press a key . . .");
  569.         if (tw == current)
  570.             current = tw->next;
  571.         delwindow(tw,1);
  572.         viewmode = 9;
  573.         return(0);
  574.     }
  575.  
  576.     if (cnt) 
  577.         parse(tw,s,cnt);            /* display on screen, etc.*/
  578.  
  579.     return(0);
  580.  
  581. }
  582.  
  583. /*********************************************************************/
  584. /* endall
  585. *  clean up and leave
  586. */
  587. endall()
  588.     {
  589.     netshut();
  590.  
  591.     n_cur(24,0);            /* go to bottom of screen */
  592.     n_color(7);
  593.     n_draw(blankline,80);    /* blank it out */
  594.     exit(0);                /* return to DOS */
  595.  
  596. }
  597.  
  598. /*********************************************************************/
  599. /*  errhandle
  600. *   write error messages to the console window
  601. */
  602. errhandle()
  603.     {
  604.     char *errmsg;
  605.     int i,j;
  606.  
  607.     while (ERR1 == Sgetevent(ERRCLASS,&i,&j)) {
  608.         errmsg = neterrstring(j);
  609.         VSwrite(console->vs,errmsg,strlen(errmsg));
  610.         VSwrite(console->vs,"\r\n",2);
  611.     }
  612.  
  613. }
  614.  
  615.  
  616. /*********************************************************************/
  617. /*  vprint
  618. *   print to a virtual screen
  619. */
  620. vprint(w,s)
  621.     int w;
  622.     char *s;
  623.     {
  624.  
  625.     VSwrite(w,s,strlen(s));
  626. }
  627.  
  628. /*********************************************************************/
  629.  
  630. helpmsg() {
  631.     int i;
  632.  
  633.     leavetek();
  634.     i = n_color(current->colors[0]); 
  635.  
  636.     n_clear();
  637.     n_cur(0,0);
  638.     n_puts("Keyboard usage for NCSA telnet: \n");
  639.     n_puts("Alt-A     add a session                    Alt-Y     Interrupt Process");
  640.     n_puts("Alt-N     next session                     Alt-O     Abort Output");
  641.     n_puts("Alt-M     message screen                   Alt-Q     Are you there?");
  642.     n_puts("Alt-E     escape to DOS shell              Alt-U     Erase line");
  643.     n_puts("Alt-G     graphics menu                    Alt-K     Erase Kharacter");
  644.     n_puts("Alt-C     toggle capture on/off            Alt-X     close connection");
  645.     n_puts("Alt-R     reset VT102 screen               HOME      exit graphics mode");
  646.     n_puts("Alt-H     this help screen                 Ctrl-HOME clear/enter graphics mode");
  647.     n_puts("ScrLock   pause/restart screen (DO NOT use Ctrl-NumLock)");
  648.     n_puts("ScrLock   enter/exit scroll-back mode");
  649.     n_puts("Alt-T     start file transfer as if typed: ftp [internet address]");
  650.     n_puts("Alt-I     send my internet address to host as if typed");
  651.     n_puts("Alt-S     skip scrolling, jump ahead");
  652.     n_puts("Alt-P     change a parameter, one of:");
  653.     n_puts("          color, capture file name, backspace, session name, screen mode");
  654.     n_puts("Alt-F3    abort program completely.  STRONGLY discouraged");
  655.  
  656.     n_puts("\n\nPress ESC for information page, space bar to return to session:");
  657.  
  658.     n_color(i);
  659. }
  660.  
  661. help2(c) 
  662.     int c;
  663.     {
  664.     int i;
  665.  
  666.     i = n_color(current->colors[0]); 
  667.  
  668.     n_clear();
  669.     n_cur(0,0);
  670.     n_puts("NCSA Telnet for the IBM PC and Macintosh version 2.2S");
  671.     n_puts("\nNational Center for Supercomputing Applications, University of Illinois");
  672.     n_puts("written by Tim Krauskopf, Gaige B. Paulsen, and Aaron Contorer\n");
  673.  
  674. #ifndef beta
  675.     n_puts("This program is in the public domain.");
  676.     n_puts("Please retain the following notice:");
  677.     n_puts("\n  Portions developed by the National Center for Supercomputing Applications");
  678.     n_puts("  at the University of Illinois, Urbana-Champaign.");
  679. #else
  680.     n_puts("Authorized beta test version - open to technical users at your own risk.");
  681.     n_puts("Please report all problems that you wish fixed before July 1");
  682.     n_puts("All rights reserved.");
  683. #endif
  684.  
  685.     n_puts("\n\nFor information or for disks and manuals (there is a handling fee),");
  686.     n_puts("contact NCSA at:");
  687.     n_puts("152 Computing Applications Building");
  688.     n_puts("605 E. Springfield Ave.");
  689.     n_puts("Champaign, IL 61820");
  690.     n_puts("\nbugs and suggestions to telbug@ncsa.uiuc.edu");
  691.     n_puts("\nPress space bar to return to session");
  692.  
  693.     n_color(i);
  694. }
  695.  
  696. /*********************************************************************/
  697. /*  parse
  698. *   Do the telnet negotiation parsing.
  699. *
  700. *   look at the string which has just come in from outside and
  701. *   check for special sequences that we are interested in.
  702. *
  703. *   Tries to pass through routine strings immediately, waiting for special
  704. *   characters ESC and 255 to change modes.
  705. */
  706.  
  707. #define STNORM    0
  708. #define GOAHEAD 249
  709. #define WILLTEL 251
  710. #define WONTTEL 252
  711. #define DOTEL    253
  712. #define DONTTEL 254
  713. #define ESCFOUND 5
  714. #define IACFOUND 6
  715.  
  716. parse(tw,st,cnt)
  717.     struct twin *tw;
  718.     int cnt;
  719.     unsigned char *st;
  720.     {
  721.     int i,cv;
  722.     unsigned char *mark,*orig;
  723.  
  724.     cv = console->vs;
  725.     orig = st;                /* remember beginning point */
  726.     mark = st + cnt;        /* set to end of input string */
  727.     netpush(tw->pnum);
  728.  
  729. /*
  730. *  traverse string, looking for any special characters which indicate that
  731. *  we need to change modes.
  732. */
  733.     while (st < mark) {
  734.  
  735.         switch (tw->telstate) {
  736.             case ESCFOUND:
  737. #ifdef USETEK
  738.                 if (*st == 12)    {        /* esc-FF */
  739.                     if (tw->termstate == VTEKTYPE) {
  740.                         vprint(cv,"\n\r Entering Tek mode \n\r");
  741.                         tw->termstate = TEKTYPE;
  742.                         VGgmode(rgdevice);
  743.                         VGuncover(temptek);
  744.                         current=tw;
  745.                     }
  746.                     VGwrite(temptek,"\033\014",2);
  747.                     orig = ++st;        /* pass by ESC-FF in data */
  748.                     tw->telstate = STNORM;
  749.                     break;
  750.                 }
  751. #endif 
  752. #ifdef USERAS
  753.                 if (*st == '^') {        /* esc-^ */
  754.                     tw->termstate = RASTYPE;
  755.                     tw->telstate = STNORM;
  756.                     current=tw;
  757.                     VRwrite("\033^",2);             /* echo ^ */
  758.                     orig = ++st;
  759.                     break;
  760.                 }
  761. #endif
  762.                 parsewrite(tw,"\033",1);        /* send the missing ESC */
  763.  
  764.                 tw->telstate = STNORM;
  765.                 break;
  766.             case IACFOUND:         /* telnet option negotiation */
  767.                 if (*st == 255) {        /* real data = 255 */
  768.                     st++;                /* real 255 will get sent */
  769.                     tw->telstate = STNORM;
  770.                     break;
  771.                 }
  772.                 if ( 248 < *st ) {
  773.                     tw->telstate = *st;        /* by what the option is */
  774.                     st++;
  775.                     break;
  776.                 }
  777.                 vprint(cv,"\n\r strange telnet option\r\n");
  778.                 orig = st;
  779.                 tw->telstate = STNORM;
  780.                 break;
  781.             case GOAHEAD:
  782.                 tw->telstate = STNORM;
  783.                 orig = st;
  784.                 break;
  785.             case DOTEL:
  786.                 sprintf(parsedat," telnet option %d %d\r\n",tw->telstate,*st);
  787.                 vprint(cv,parsedat);
  788.                 if (*st != 3) {            /* anything but suppress go-ahead */
  789.                     sprintf(parsedat,"%c%c%c",255,WONTTEL,*st++);
  790.                     netwrite(tw->pnum,parsedat,3);    /* refuse it */
  791.                 }
  792.                 else if (!tw->igoahead) {    /* suppress go-ahead */
  793.                     sprintf(parsedat,"%c%c%c",255,WILLTEL,*st++);
  794.                     netwrite(tw->pnum,parsedat,3);    /* take it */
  795.                     tw->igoahead = 1;
  796.                 }
  797.                 tw->telstate = STNORM;
  798.                 orig = st;
  799.                 break;
  800.             case DONTTEL:
  801.                 sprintf(parsedat," telnet option %d %d\r\n",tw->telstate,*st++);
  802.                 vprint(cv,parsedat);
  803.                 tw->telstate = STNORM;
  804.                 orig = st;
  805.                 break;
  806.             case WILLTEL:
  807.                 sprintf(parsedat," telnet option %d %d\r\n",tw->telstate,*st);
  808.                 vprint(cv,parsedat);
  809.                 tw->telstate = STNORM;
  810.                 switch(*st++) {
  811.                 case 3:                /* suppress go-ahead */
  812.                     if (tw->ugoahead)
  813.                         break;
  814.                     tw->ugoahead = 1;
  815.                     sprintf(parsedat,"%c%c%c",255,DOTEL,3);    /* ack */
  816.                     netwrite(tw->pnum,parsedat,3);
  817.                     break;
  818.                 case 1:                /* echo */
  819.                     if (tw->echo)
  820.                         break;
  821.                     tw->echo = 1;
  822.                     sprintf(parsedat,"%c%c%c",255,DOTEL,1);    /* ack */
  823.                     netwrite(tw->pnum,parsedat,3);
  824.                     netwrite(tw->pnum,tw->linemode,strlen(tw->linemode));
  825.                     tw->linemode[0] = '\0';
  826.                     break;
  827.                 default:
  828.                     sprintf(parsedat,"%c%c%c",255,DONTTEL,*(st-1));
  829.                     netwrite(tw->pnum,parsedat,3);    /* refuse it */
  830.                 }
  831.                 orig = st;
  832.                 break;
  833.                             
  834.             case WONTTEL:
  835.                 sprintf(parsedat," telnet option %d %d\r\n",tw->telstate,*st);
  836.                 vprint(cv,parsedat);
  837.                 tw->telstate = STNORM;
  838.                 switch(*st++) {            /* which option? */
  839.                 case 1:                /* echo */
  840.                     if (!tw->echo)
  841.                         break;
  842.                     tw->echo = 0;
  843.                     sprintf(parsedat,"%c%c%c",255,DONTTEL,1);
  844.                     netwrite(tw->pnum,parsedat,3);    /* OK with us */
  845.                     break;
  846.                 default:
  847.                     break;
  848.                 }
  849.                 orig = st;
  850.                 break;
  851.             default:
  852.                 tw->telstate = STNORM;
  853.                 break;
  854.         }
  855.  
  856. /*
  857. * quick scan of the remaining string, skip chars while they are
  858. * uninteresting
  859. */
  860.         if (tw->telstate == STNORM) {
  861. /*
  862. *  skip along as fast as possible until an interesting character is found
  863. */
  864.             while (st < mark && *st != 27 && *st < 255) {
  865.                 if (!tw->binary) 
  866.                     *st &= 127;                    /* mask off high bit */
  867.                 st++;
  868.             }
  869.  
  870.             parsewrite(tw,orig,st-orig);
  871.  
  872.             orig = st;                /* forget what we have sent already */
  873.  
  874.             if (st < mark)
  875.             switch (*st) {
  876.                 case 255:            /* telnet IAC */
  877.                     tw->telstate = IACFOUND;
  878.                     st++;
  879.                     break;
  880.  
  881.                 case 27:            /* ESCape code */
  882.                     if (st == mark-1 || *(st+1) == 12 || *(st+1) == '^') {
  883.                         tw->telstate = ESCFOUND;
  884.                     }
  885.                     st++;            /* strip or accept ESC char */
  886.             
  887.                     break;
  888.  
  889.                 default:
  890.                     vprint(cv," strange char > 128\r\n");
  891.                     st++;
  892.                     break;
  893.             }
  894.  
  895.         }
  896.  
  897.     }  /* end while */
  898.  
  899. }
  900.  
  901. /*********************************************************************/
  902. /*  parsewrite
  903. *   write out some chars from parse
  904. *   Has a choice of where to send the stuff
  905. */
  906. parsewrite(tw,dat,len)
  907.     struct twin *tw;
  908.     char *dat;
  909.     int len;
  910.     {
  911.     int i;
  912. /*
  913. *  send the string where it belongs
  914. *  1. Check for a capture file.  If so, echo a copy of the string
  915. *  2. Check for dumb terminal type, convert special chars if so
  916. *  3. Check for Tektronix mode, sending Tek stuff
  917. *  3b. check for raster color type
  918. *  4. or, send to virtual screen anyway
  919. */
  920.     if (tw->capon)                        /* capture to file? */
  921.         fwrite(dat,len,1,tw->capfp);
  922. /*
  923. * raw mode for debugging, passes through escape sequences and other
  924. * special characters as <27> symbols
  925. */
  926.     if (tw->termstate == DUMBTYPE) {
  927.         for (i=0; i < len ; i++,dat++) 
  928.             if (*dat == 27 || *dat > 126) {
  929.                 sprintf(parsedat,"<%d>",*dat);
  930.                 VSwrite(tw->vs,parsedat,strlen(parsedat));
  931.             }
  932.             else
  933.                 VSwrite(tw->vs,dat,1);
  934.     }
  935.     else {
  936. #ifdef USETEK
  937.         if (tw->termstate == TEKTYPE) {
  938.             i = VGwrite(temptek,dat,len);
  939.             if (i < len) {
  940.                 leavetek();
  941.                 viewmode=10;
  942.                 parsewrite(tw,dat+i,len-i);
  943.             }
  944.         }                
  945.         else 
  946. #endif
  947. #ifdef USERAS
  948.         if (tw->termstate == RASTYPE) {
  949.             i = VRwrite(dat,len);
  950.             if (i < len) {
  951.                 tw->termstate = VTEKTYPE;
  952.                 parsewrite(tw,dat+i,len-i);
  953.             }
  954.         }
  955.         else
  956. #endif
  957.             VSwrite(tw->vs,dat,len);    /* send to virtual VT102 */
  958.  
  959.     }
  960.  
  961. }
  962.  
  963. /*********************************************************************/
  964.  
  965. breakstop()
  966.     {
  967.     foundbreak = 1;
  968.     return(0);
  969. }
  970.  
  971. /*********************************************************************/
  972. /* newkey
  973. *  filter for command key sequences
  974. */
  975.  
  976. newkey(t1)
  977.     struct twin *t1;
  978.     {
  979.     int c;
  980.  
  981.     if (foundbreak) {
  982.         foundbreak = 0;
  983.         c = '\003';                    /* ctrl-c */
  984.     }
  985.     else {
  986.         if (t1->echo)
  987.             c = n_chkchar();        /* a char available ?*/
  988.         else if (t1->halfdup) {        /* half duplex */
  989.             c = n_chkchar();
  990.             if (c == 13) {
  991.                 parse(t1,"\r\n",2);    /* echo crlf */
  992.                 vt100key(13);
  993.                 c = 10;
  994.             } else if (c > 0 && c < 128)
  995.                 parse(t1,&c,1);        /* echo char */
  996.         }
  997.         else {                        /* line mode */
  998.             c = RSgets(t1->vs,t1->linemode,79);
  999.             if (c == 13) {            /* pressed return */
  1000.                 parse(t1,"\r\n",2);     /* echo the return */
  1001.                 strcat(t1->linemode,"\r\n");
  1002.                 netpush(t1->pnum);
  1003.                 netwrite(t1->pnum,t1->linemode,strlen(t1->linemode));
  1004.                 t1->linemode[0] = '\0';
  1005.                 c = 0;
  1006.             }
  1007.             else if (c > 0) {        /* write string, pass c to command interp */
  1008.                 if (t1->linemode[0]) {
  1009.                     netpush(t1->pnum);
  1010.                     netwrite(t1->pnum,t1->linemode,strlen(t1->linemode));
  1011.                     t1->linemode[0] = '\0';
  1012.                 }
  1013.             }
  1014.         }
  1015.     }
  1016.  
  1017.     if (c <= 0)
  1018.         return(c);
  1019.  
  1020.     return(dokey(t1,c));
  1021.  
  1022. }
  1023.  
  1024. /************************************************************************/
  1025. /*  dokey
  1026. *   translates and sends keys and filters for command keys
  1027. *
  1028. */
  1029. dokey(t1,c)
  1030.     struct twin *t1;
  1031.     int c;
  1032.     {
  1033.     int i;
  1034.  
  1035.         switch (c) {
  1036.             case 8:
  1037.                 c = t1->bksp;            /* allows auto del instead of bs */
  1038.                 break;
  1039.             case 13:                    /* different CR mappings */
  1040.                 vt100key(13);
  1041.                 vt100key(t1->crfollow);
  1042.                 c = 0;
  1043.                 break;
  1044.             case 127:
  1045.                 c = t1->del;        /* switch bs around, too */
  1046.                 break;
  1047.  
  1048.             case THENUL:            /* user wants the true NUL char */
  1049.                 c = 0;
  1050.                 netwrite(t1->pnum, &c, 1);    /* write a NUL */
  1051.                 break;
  1052.  
  1053.             case CTRLHOME:                /* tek clear screen */
  1054.                 if (current->termstate != TEKTYPE) {
  1055.                     current->termstate = TEKTYPE;
  1056.                     VGgmode(rgdevice);
  1057.                     VGuncover(temptek);
  1058.                 }
  1059.                 VGwrite(temptek,"\033\014",2);    /* clear storage and screen */
  1060.                 c = 0;
  1061.                 break;
  1062.  
  1063.             case HOME:                /* clear to text */
  1064.                 if (leavetek()) {
  1065.                     viewmode = 10;
  1066.                     c = 0;
  1067.                 }
  1068.                 break;
  1069.  
  1070.             case ALTH:                /* help display */
  1071.                 viewmode = 3;
  1072.                 helpmsg();
  1073.                 c = 0;
  1074.                 break;
  1075.  
  1076.             case ALTP:                /* change a parameter */
  1077.                 parmchange();
  1078.                 c = 0;
  1079.                 break;
  1080.  
  1081.             case ALTR:                /* reset screen values */
  1082.                 if (!leavetek()) {
  1083.                     if (current->capon) {
  1084.                         fclose(current->capfp);
  1085.                         current->capon = capon = 0;
  1086.                     }
  1087.                     VSreset(current->vs);        /* reset's emulator */
  1088.                 }
  1089.                 wrest(current);
  1090.                 c = 0;
  1091.                 break;
  1092.  
  1093. #ifdef USETEK
  1094.             case ALTG:            /* graphics manipulation */
  1095.                 c = 0;
  1096.                 leavetek();
  1097.                 dispgr();
  1098.                 break;
  1099. #endif
  1100.  
  1101.             case ALTE:
  1102.                 leavetek();
  1103.                 n_window(0,0,24,79);
  1104.                 i = n_color(current->colors[0]); 
  1105.                 dosescape();
  1106.                 viewmode = 5;
  1107.                 n_color(i);
  1108.                 c = 0;
  1109.                 break;
  1110.  
  1111.             case ALTC:                            /* toggle capture */
  1112.                 if (capon && current->capon) {    /* already on */
  1113.                     capstat("Capture off");
  1114.                     fclose(current->capfp);        /* close the capture file */
  1115.                     current->capon = capon = 0;
  1116.                 }
  1117.                 else if (!capon) {                /* I want one */
  1118.                     FILE *Sopencap();
  1119.                     if (NULL == (current->capfp = Sopencap())) {
  1120.                         vprint(console->vs,"\r\nCannot open capture file ");
  1121.                         break;
  1122.                     }
  1123.                     capstat("Capture on ");
  1124.                     current->capon = capon = 1;
  1125.                 }
  1126.                 else {
  1127.                     vprint(console->vs,"\r\nAnother session has capture file open, cannot open two at once\r\n");
  1128.                     wrest(console);
  1129.                     viewmode=2;
  1130.                 }
  1131.                     
  1132.                 c=0;
  1133.                 break;
  1134.  
  1135.             case ALTI:                            /* my internet address */
  1136.                 sprintf(s,"%d.%d.%d.%d",myipnum[0],myipnum[1],myipnum[2],myipnum[3]);
  1137.                 netwrite(t1->pnum,s,strlen(s));
  1138.                 if (!t1->echo)
  1139.                     parse(t1,s,strlen(s));         /* echo the string */
  1140.                 c = 0;
  1141.                 break;
  1142.  
  1143.             case ALTT:                            /* an ftp command */
  1144.                 if (Sneedpass())
  1145.                     strcpy(s,"ftp ");
  1146.                 else
  1147.                     strcpy(s,"ftp -n ");
  1148.                 sprintf(&s[strlen(s)],"%d.%d.%d.%d\r\n",
  1149.                 myipnum[0],myipnum[1],myipnum[2],myipnum[3]);
  1150.                 netwrite(t1->pnum,s,strlen(s));
  1151.                 if (!t1->echo)
  1152.                     parse(t1,s,strlen(s));     /* echo the string */
  1153.                 c = 0;
  1154.                 break;
  1155.  
  1156.             case ALTQ:                /* are you there? */
  1157.                 netpush(t1->pnum);
  1158.                 netwrite(t1->pnum,"\377\366",2);
  1159.                 c = 0;
  1160.                 break;
  1161.  
  1162.             case ALTO:                /* abort output */
  1163.                 netpush(t1->pnum);
  1164.                 netwrite(t1->pnum,"\377\365",2);
  1165.                 c = 0;
  1166.                 break;
  1167.                 
  1168.             case ALTY:                /* interrupt */
  1169.                 netpush(t1->pnum);
  1170.                 netwrite(t1->pnum,"\377\364",2);
  1171.                 c = 0;
  1172.                 break;
  1173.                 
  1174.             case ALTU:                /* erase line */
  1175.                 netpush(t1->pnum);
  1176.                 netwrite(t1->pnum,"\377\370",2);
  1177.                 c = 0;
  1178.                 break;
  1179.                 
  1180.             case ALTK:                /* erase char */
  1181.                 netpush(t1->pnum);
  1182.                 netwrite(t1->pnum,"\377\367",2);
  1183.                 c = 0;
  1184.                 break;
  1185.                 
  1186.             case ALTA:                /* add session */
  1187.                 c = 0;
  1188.                 if (0 > addsess(NULL)) {        /* start up a new one */
  1189.                     vprint(console->vs,"\r\nPress any key to continue . . .");
  1190.                     viewmode = 9;
  1191.                 }
  1192.                 else
  1193.                     viewmode = 10;
  1194.                 break;
  1195.  
  1196.             case ALTM:
  1197.                 c = 0;
  1198.                 leavetek();
  1199.                 wrest(console);
  1200.                 viewmode = 2;                /* console view mode */
  1201.                 break;
  1202.  
  1203.             case ALTN:                        /* session switch */
  1204.                 c = 0;
  1205.                 leavetek();
  1206.                 if (current->next == NULL)   /* are we only one ? */
  1207.                     break;
  1208.                 current = current->next;
  1209.                 viewmode = 10;
  1210.                 break;
  1211.  
  1212.             case ALTS:                        /* skip to end */
  1213.                 c = 0;
  1214.                 RSvis(0);
  1215.                 while (0 < (i = netread(t1->pnum,s,500)))
  1216.                     parse(t1,s,i);
  1217.                 viewmode = 10;
  1218.                 break;
  1219.  
  1220.             case ALTX:                        /* close the connection */
  1221.                 leavetek();
  1222.                 n_puts("\n Are you sure you want to close the connection? Y/N");
  1223.                 c = nbgetch();                /* get the answer */
  1224.                 if (tolower(c) == 'y') {
  1225.                     n_puts("\n Attempting to close . . .");
  1226.                     netclose(t1->pnum);
  1227.                     Stask();
  1228.                     netputuev(CONCLASS,CONCLOSE,t1->pnum);
  1229.                 }
  1230.                 else
  1231.                     viewmode=10;            /* redraw screen */
  1232.                 c = 0;
  1233.                 break;
  1234.  
  1235.             case AF9:
  1236.                 statcheck();
  1237.                 break;
  1238.  
  1239.             case AF3:
  1240.                 return(AF3);
  1241.                 break;
  1242.  
  1243.             default:
  1244.                 break;
  1245.  
  1246.         }
  1247.  
  1248.     if (c > 0)
  1249.         vt100key(c);            /* send it, with VT100 translation */
  1250.  
  1251.     return(c);
  1252.  
  1253. }
  1254.  
  1255. /**************************************************************************/
  1256. /*  dispgr
  1257. *   display graphics menu screen
  1258. */
  1259. dispgr()
  1260.     {
  1261.     int c,i,j,k,l;
  1262.  
  1263.     c = n_color(current->colors[0]);
  1264.     n_clear();
  1265.     n_cur(0,0);
  1266. n_puts("ALT-G                           Graphics menu");
  1267. n_puts("<            Press the appropriate function key or ESC to resume        >\n");
  1268. strcpy(s,"   F1 - Write postscript to a file called: ");
  1269. strcat(s,def.psfile);
  1270. n_puts(s);
  1271. n_puts(  "   F2 - Change postscript output file name\n");
  1272. strcpy(s,"   F3 - Write HPGL code to a file called: ");
  1273. strcat(s,def.hpfile);
  1274. n_puts(s);
  1275. n_puts(  "   F4 - Change HPGL output file name\n");
  1276. strcpy(s,"   F5 - Write Tektronix 4014 codes to a file called: ");
  1277. strcat(s,def.tekfile);
  1278. n_puts(s);
  1279. n_puts(  "   F6 - Change Tektronix output file name\n");
  1280. VGwhatzoom(temptek,&i,&j,&k,&l);
  1281. sprintf(s,"        View region is currently: %d,%d,%d,%d",i,j,k,l);
  1282. n_puts(s);
  1283. n_puts("   F7 - Set a new view region (Zoom, Pan)");
  1284. n_puts("   RETURN - draw picture on screen in current zoom factor\n");
  1285. n_puts("   Enter choice:");
  1286.     viewmode = 8;
  1287.     n_color(c);
  1288.  
  1289. }
  1290.  
  1291. /***************************************************************************/
  1292. /*  dosescape
  1293. *  escape to dos for processing
  1294. *  put the connections to automated sleep while in DOS
  1295. */
  1296. dosescape()
  1297.     {
  1298.     int i;
  1299.     n_clear();
  1300.     n_cur(0,0);
  1301.     n_puts("Warning, some programs will interfere with network communication and can");
  1302.     n_puts("cause lost connections.  Do not run any network programs from this DOS shell.");
  1303.     n_puts("Type 'EXIT' to return to NCSA Telnet");
  1304. /*
  1305. *  invoke a put-to-sleep routine which calls netsleep every 8/18ths of a sec
  1306. *  Also:  disable ftp,rcp when asleep and suppress error messages
  1307. */
  1308.     if (ftpact || rcpact) {
  1309.         n_puts("Please wait until file transfer is finished");
  1310.         n_puts("\nPress any key to continue");
  1311.         return(0);
  1312.     }
  1313.  
  1314.     tinst();
  1315.     i = system("command");        /* call DOS */
  1316.     tdeinst();
  1317.  
  1318.     if (i < 0) {
  1319.         n_puts("\n\nError loading COMMAND.COM");
  1320.         n_puts("Make sure COMMAND.COM is specified under COMSPEC.");
  1321.         n_puts("It must also be in a directory which is in your PATH statement.");
  1322.     }
  1323.  
  1324.     n_row();
  1325.     n_puts("\nPress any key to return to telnet");
  1326.     return(0);
  1327. }
  1328.  
  1329. /***********************************************************************/
  1330. /*  creatwindow
  1331. *   returns a pointer to a new window
  1332. */
  1333. struct twin *creatwindow()
  1334.     {
  1335.     struct twin *p;
  1336.     int i;
  1337.  
  1338.     p = (struct twin *)malloc(sizeof(struct twin));
  1339.     if (!p)
  1340.         return(NULL);
  1341.     p->pnum = -1;
  1342.     p->telstate = 0;
  1343.     if (vton)
  1344.         p->termstate = basetype;
  1345.     else
  1346.         p->termstate = DUMBTYPE;
  1347.     p->linemode[0] = 0;
  1348.     p->echo = 1;
  1349.     p->binary = 0;
  1350.     p->ugoahead = 0;        /* we want goahead suppressed */
  1351.     p->igoahead = 0;        /* we want goahead suppressed */
  1352.     p->capon = 0;
  1353.     p->next = NULL;
  1354.     p->prev = NULL;
  1355.     p->sstat = '*';                /* connection not opened yet */
  1356.  
  1357.     if (mp == NULL) {
  1358.         p->bksp = 127;
  1359.         p->del = 8;
  1360.         p->crfollow = 10;
  1361.         p->halfdup = 0;
  1362.  
  1363.         for (i=0; i<3; i++)                    /* start default colors */
  1364.             p->colors[i] = colors[i];
  1365.  
  1366.         i = VSnewscreen(0,0,80,0);            /* create a new virtual screen */
  1367.     }
  1368.     else {
  1369.         p->bksp = mp->bksp;
  1370.         if (p->bksp == 127)
  1371.             p->del = 8;
  1372.         else
  1373.             p->del = 127;
  1374.         p->crfollow = mp->crmap;
  1375.         p->halfdup = mp->halfdup;
  1376.  
  1377.         p->colors[0] = mp->nfcolor[0] + (mp->nbcolor[0]<<4);
  1378.         p->colors[2] = mp->bfcolor[0] + (mp->bbcolor[0]<<4);
  1379.         p->colors[1] = mp->ufcolor[0] + (mp->ubcolor[0]<<4);
  1380.  
  1381.         i = VSnewscreen(mp->bkscroll,1,80,0);    /* create a new virtual screen */
  1382.  
  1383.         if (i >= 0 && mp->vtwrap)
  1384.             VSwrite(i,"\033[?7h",5);        /* turn wrap on */
  1385.         VSscrolcontrol(i,-1,mp->clearsave);    /* set clearsave flag */
  1386.     }
  1387.  
  1388.     if (i < 0)
  1389.         return(NULL);
  1390.     p->vs = i;
  1391.     screens[i] = p;                        /* we need to know where it is */
  1392.  
  1393.     return(p);
  1394. }
  1395.  
  1396. /***********************************************************************/
  1397.  
  1398. wrest(t)
  1399.     struct twin *t;
  1400.     {
  1401.  
  1402.     RSvis(t->vs);
  1403.     statline();                        /* done before, moves cursor */
  1404.     VSredraw(t->vs,0,0,79,23);        /* redisplay, resets cursor correctly */
  1405.  
  1406. }
  1407.  
  1408. /***************************************************************************/
  1409. statline()
  1410.     {
  1411.     struct twin *t1,*t2;
  1412.     int wn,i,c,sm,rw,cl;
  1413.  
  1414.     if (current == NULL || current == console || current->termstate == TEKTYPE)
  1415.         return(0);
  1416.  
  1417.     c = n_color(current->colors[0]);            /* save current color */
  1418.     if (current->sstat != '*')
  1419.         current->sstat = 254;                    /* this is current one */
  1420.     rw = n_row();
  1421.     cl = n_col();
  1422.  
  1423.     t1 = t2 = current;
  1424.     wn = 0;
  1425.     sm = scmode();
  1426.     do {
  1427.  
  1428.         n_cur(24,wn*18);
  1429.  
  1430.         n_color(t1->colors[2]);
  1431.         if (t1->sstat == 254 && t1 != current)
  1432.             t1->sstat = 176;
  1433.         n_putchar(t1->sstat);
  1434.         n_putchar(' ');
  1435.         i = strlen(t1->mname);
  1436.         if (sm) {
  1437.             n_cheat(t1->mname,i);            /* machine name of connection */
  1438.             n_cheat(blankline,16-i);        /* fill out to 16 spaces */
  1439.         }
  1440.         else {
  1441.             n_draw(t1->mname,i);            /* machine name of connection */
  1442.             n_draw(blankline,16-i);            /* fill out to 16 spaces */
  1443.         }
  1444.  
  1445.         if (t1->next)                    /* if not the only window open */
  1446.             t1 = t1->next;
  1447.  
  1448.         wn++;
  1449.     } while (t1 != t2 && wn < 4);
  1450.  
  1451.     n_color(current->colors[0]);
  1452.     n_cur(24,wn*18);
  1453.     if (sm)
  1454.         n_cheat(blankline,80-wn*18);            /* fill to edge of screen */
  1455.     else
  1456.         n_draw(blankline,80-wn*18);                /* fill to edge of screen */
  1457.  
  1458.     n_color(c);
  1459.     n_cur(rw,cl);
  1460.  
  1461. }
  1462.  
  1463. /***********************************************************************/
  1464. /*  inswindow
  1465. *    insert a window into the circular linked list
  1466. *
  1467. *   current is used as a reference point for the new entry, the new entry
  1468. *   is put next in line past "current"
  1469. */
  1470. inswindow(t,wtype)
  1471.     struct twin *t;
  1472.     int wtype;
  1473.     {
  1474.     struct twin *p,*q;
  1475.  
  1476. /*
  1477. *   put it into the port number array
  1478. */
  1479.     if (wtype)
  1480.         wins[t->pnum] = t;
  1481.  
  1482. /*
  1483. *  check for the NULL case for current.
  1484. */
  1485.     if (current == NULL || current == console) {
  1486.         current = t; 
  1487.         statline();
  1488.         return(0);
  1489.     }
  1490.  
  1491.     p = current;                    /* find surrounding elements */
  1492.     if (p->prev == NULL) {            /* only one now, we are adding 2nd */
  1493.         t->next = p;
  1494.         t->prev = p;
  1495.         p->next = t;
  1496.         p->prev = t;
  1497.     }
  1498.     else {                            /* adding third or more */
  1499.         q = p->next;                /* find next one */
  1500.  
  1501.         t->prev = p;
  1502.         t->next = q;                /* insert it as next after current */
  1503.         q->prev = t;
  1504.         p->next = t;
  1505.     }
  1506.  
  1507. }
  1508.  
  1509. /***********************************************************************/
  1510. /*  delwindow()
  1511. *   take a window out of the linked list
  1512. */
  1513. delwindow(t,wtype)
  1514.     struct twin *t;
  1515.     int wtype;
  1516.     {
  1517.     struct twin *p,*q;
  1518.  
  1519.     if (wtype)    
  1520.         wins[t->pnum] = NULL;        /* take out of array */
  1521.  
  1522.     p = t->prev;
  1523.     q = t->next;
  1524.  
  1525.     if (p == NULL) {                /* is only node */
  1526.         freewin(t);
  1527.         current = console;
  1528.         return(0);
  1529.     }
  1530.  
  1531.     if (p == q) {                /* two in list */
  1532.         p->next = NULL;
  1533.         p->prev = NULL;
  1534.     }
  1535.     else {
  1536.         q->prev = p;
  1537.         p->next = q;            /* merge two links */
  1538.     }
  1539.  
  1540.     freewin(t);                    /* release the space */            
  1541.  
  1542.     return(0);
  1543. }
  1544.  
  1545. /************************************************************************/
  1546. /*  freewin
  1547. *   deallocate and detach all associated memory from a window
  1548. */
  1549. freewin(t)
  1550.     struct twin *t;
  1551.     {
  1552.  
  1553.     VSdetatch(t->vs);
  1554.     free(t);
  1555.     return(0);
  1556.  
  1557. }
  1558.  
  1559. /************************************************************************/
  1560. /*
  1561. *  hexbyte
  1562. *   return a byte taken from a string which contains hex digits
  1563. */
  1564. hexbyte(st)
  1565.     char *st;
  1566.     {
  1567.     int i;
  1568.  
  1569.     if (*st >= 'A')
  1570.         i = ((*st|32)-87)<<4;
  1571.     else
  1572.         i = (*st-48)<<4;
  1573.  
  1574.     st++;
  1575.  
  1576.     if (*st > 'A')
  1577.         i |= (*st | 32)-87;
  1578.     else
  1579.         i += (*st-48);
  1580.  
  1581.     return(i);
  1582.  
  1583. }
  1584.  
  1585. /***********************************************************************/
  1586. /* tekinit
  1587. *  tektronix initialization
  1588. */
  1589. #ifdef USETEK
  1590. tekinit(dev)
  1591.     char *dev;
  1592.     {
  1593.     int i;
  1594.  
  1595.     if (strlen(dev) < 1 )
  1596.         return(0);
  1597.  
  1598.     if (0 > VGinit()) {
  1599.         vprint(console->vs,"\r\nCannot initialize Tektronix driver\r\n");
  1600.         return(-1);
  1601.     }
  1602.     else
  1603.         vprint(console->vs,"\r\nTektronix initialized\r\n");
  1604.  
  1605.     if (!strcmp(dev,"no9"))
  1606.         rgdevice = 4;
  1607.     else if (!strcmp(dev,"ega"))
  1608.         rgdevice = 1;
  1609. #ifdef why
  1610.     else if (!strcmp(dev,"ps"))
  1611.         rgdevice = 2;
  1612. and the hplot is dev 6
  1613. #endif
  1614.     else if (!strcmp(dev,"hercules"))
  1615.         rgdevice = 3;
  1616.     else if (!strcmp(dev,"cga") || !strcmp(dev,"pga"))
  1617.         rgdevice = 5;
  1618.     else
  1619.         rgdevice = 0;                /* null device */
  1620.  
  1621.     basetype = VTEKTYPE;
  1622.  
  1623.     temptek = VGnewwin(rgdevice);    /* default for drawing */
  1624.  
  1625.     return(0);
  1626. }
  1627.  
  1628. /***********************************************************************/
  1629. /*  function to write to file
  1630. */
  1631. fdump(str)
  1632.     char *str;
  1633.     {
  1634.     fputs(str,tekfp);
  1635. }
  1636.  
  1637. fdumpc(c)
  1638.     char c;
  1639.     {
  1640.     fputc(c,tekfp);
  1641. }
  1642.  
  1643. endump()
  1644.     {
  1645.  
  1646.     VGclose(outdev);
  1647.  
  1648.     if (indev != temptek) {
  1649.         VGclose(indev);
  1650.         if (tekfp) {
  1651.             fclose(tekfp);
  1652.             tekfp = NULL;
  1653.         }
  1654.     }
  1655. }
  1656.  
  1657. /***********************************************************************/
  1658. /* graphit
  1659. *  Get some user choices and execute them
  1660. */
  1661. graphit()
  1662.     {
  1663.     int i,j,k,l,c;
  1664.  
  1665.     c = n_chkchar();
  1666.     if (c == 27)
  1667.         return(1);
  1668.     if (c < 0)
  1669.         return(0);
  1670.  
  1671.     switch (c) {
  1672.  
  1673.     case F2:
  1674.     case F4:
  1675.     case F6:    /* prompting for file name */
  1676.         n_puts("\nEnter new file name:");
  1677.         nbgets(s,50);
  1678.         if (s[0] && s[0] != ' ') {
  1679.             switch (c) {
  1680.             case F2:
  1681.                 Snewpsfile(s);
  1682.                 break;
  1683.             case F4:
  1684.                 Snewhpfile(s);
  1685.                 break;
  1686.             case F6:
  1687.                 Snewtekfile(s);
  1688.                 break;
  1689.             }
  1690.             Sgetconfig(&def);
  1691.         }
  1692.         dispgr();                        /* leave in graphit mode */
  1693.         return(0);
  1694.         break;
  1695.     case F1:            /* postscript dump */
  1696.         if (*def.psfile == '+') {
  1697.             if (NULL == (tekfp = fopen(&def.psfile[1],"a")))
  1698.                 return(1);
  1699.             fseek(tekfp,0L,2);      /* to end */
  1700.         }
  1701.         else if (NULL == (tekfp = fopen(def.psfile,"w"))) 
  1702.             return(1);
  1703.         RGPoutfunc(&fdump);        /* set function */
  1704.         outdev = VGnewwin(2);
  1705.         indev = temptek;
  1706.         temptek = VGnewwin(rgdevice);
  1707.         VGgmode(2);
  1708.         VGzcpy(indev,temptek);
  1709.         VGzcpy(indev,outdev);
  1710.         VGuncover(outdev);
  1711.         VGpage(outdev);
  1712.             if (VGpred(indev,outdev))
  1713.             endump();
  1714.         else
  1715.             netputevent(USERCLASS,PSDUMP,1);        /* remind myself */
  1716.         return(1);
  1717.         break;
  1718.                     
  1719.     case F3:            /* HPGL dump */
  1720.         if (*def.hpfile == '+') {            /* append feature */
  1721.             if (NULL == (tekfp = fopen(&def.hpfile[1],"a"))) 
  1722.                 return(1);
  1723.             fseek(tekfp,0L,2);
  1724.         }
  1725.         else if (NULL == (tekfp = fopen(def.hpfile,"w"))) 
  1726.             return(1);
  1727.         RGHPoutfunc(&fdump);        /* set function */
  1728.         outdev = VGnewwin(6);
  1729.         indev = temptek;
  1730.         temptek = VGnewwin(rgdevice);
  1731.             VGgmode(6);
  1732.         VGzcpy(indev,temptek);
  1733.         VGzcpy(indev,outdev);
  1734.         VGuncover(outdev);
  1735.         VGpage(outdev);
  1736.             if (VGpred(indev,outdev))
  1737.             endump();
  1738.         else
  1739.             netputevent(USERCLASS,PSDUMP,1);        /* remind myself */
  1740.         return(1);
  1741.         break;
  1742.     case F5:            /* tektronix dump */
  1743.         if (*def.tekfile == '+') {
  1744.             if (NULL == (tekfp = fopen(&def.tekfile[1],"ab"))) 
  1745.                 return(1);
  1746.             fseek(tekfp,0L,2);
  1747.         }
  1748.         else if (NULL == (tekfp = fopen(def.tekfile,"wb"))) 
  1749.             return(1);
  1750.         fputs("\033\014",tekfp);
  1751.         VGdumpstore(temptek,&fdumpc);
  1752.         fclose(tekfp);
  1753.         return(1);
  1754.         break;
  1755.  
  1756.     case F7:            /* tek view region */
  1757.         n_puts("\nEnter 0-4095 for lower left xy, upper right xy.");
  1758.         n_puts("\nExample:  0,0,4095,3119 is full view. (default if you leave it blank)");
  1759.         nbgets(s,30);
  1760.         if (4 != sscanf(s,"%d,%d,%d,%d",&i,&j,&k,&l))
  1761.             VGzoom(temptek,0,0,4096,3119);
  1762.         else
  1763.             VGzoom(temptek,i,j,k,l);
  1764.         dispgr();                        /* leave in graphit mode */
  1765.         return(0);
  1766.         break;
  1767.     case 13:
  1768.         current->termstate = TEKTYPE;
  1769.         VGgmode(rgdevice);
  1770.         VGuncover(temptek);
  1771.         outdev = temptek;                /* redraw to itself */
  1772.         indev = temptek;
  1773.         tekfp = NULL;
  1774.         if (!VGpred(indev,outdev))
  1775.             netputevent(USERCLASS,PSDUMP,0);        /* remind myself */
  1776.         viewmode = 0;                    /* normal logon state */
  1777.         break;
  1778.     default:
  1779.         break;
  1780.     }
  1781.  
  1782.     return(0);
  1783.  
  1784. }
  1785.  
  1786. #endif
  1787.  
  1788. /***********************************************************************/
  1789. /*  menu support
  1790. *   New 5/22/88 - TK
  1791. *   Provide menus with a reasonable user interface for the user to
  1792. *   select colors or other parameters.
  1793. *
  1794. *   This menu system provides two types of entries.
  1795. *   1. Up to nine static choices, 0-8.  Each static choice is encoded
  1796. *      into the data structure and automatically rotated by the user.
  1797. *      The user cannot select an illegal value.
  1798. *   2. A string choice.  A maximum string length is honored.
  1799. *   There must be at least 20 characters open for each field, longer
  1800. *   if the field is longer.  Static choices cannot be longer than 20 chars.
  1801. *
  1802. */
  1803.  
  1804. /*
  1805. *  structure for the menu entries
  1806. */
  1807. struct pt {
  1808.     int posx,posy,        /* row and col position on screen for field */
  1809.         choice,            /* which is the currently visible selection */
  1810.         replen;            /* length of reply if a string is allowed to be entered */
  1811.     char *vals[9];        /* pointers to the actual choices */
  1812. };
  1813.  
  1814. #define LO 5
  1815. struct pt pc[] = {
  1816.     /* session colors */
  1817.     {LO+0,44,0,0,"black","blue","green","cyan","red","magenta","yellow","white",NULL},
  1818.     {LO+1,44,0,0,"black","blue","green","cyan","red","magenta","yellow","white",NULL},
  1819.     {LO+2,44,0,0,"black","blue","green","cyan","red","magenta","yellow","white",NULL},
  1820.     {LO+3,44,0,0,"black","blue","green","cyan","red","magenta","yellow","white",NULL},
  1821.     {LO+4,44,0,0,"black","blue","green","cyan","red","magenta","yellow","white",NULL},
  1822.     {LO+5,44,0,0,"black","blue","green","cyan","red","magenta","yellow","white",NULL},
  1823.     /* things which also apply to this session */
  1824.     {LO+6,44,0,0,"Local echo","Remote echo",NULL},
  1825.     {LO+7,44,1,0,"Backspace","Delete",NULL},
  1826.     {LO+8,44,0,20,NULL,"                     ",NULL},
  1827.     {LO+9,44,0,0,"VT102 and Tek4014","Dumb TTY","VT102 only",NULL},
  1828.     /* things which apply over all of telnet */
  1829.     {LO+11,44,0,35,NULL,"                                      ",NULL},
  1830.     {LO+12,44,1,0,"Use BIOS","Direct to screen",NULL},
  1831.     {LO+13,44,0,0,"Disabled","Enabled",NULL},
  1832.     {LO+0,0}
  1833. };
  1834.  
  1835. /************************************************************************/
  1836. /* menuit
  1837. *  draw the current line at the required position.
  1838. *  If the field length (replen) is longer than 20 chars, fill in the
  1839. *  entire field width.  All fields are padded with spaces to their
  1840. *  length when printed, but stored without padding.
  1841. */
  1842. menuit(p,n)
  1843.     struct pt p[];
  1844.     int n;
  1845.     {
  1846.     int i;
  1847.     char fmt[12];
  1848.  
  1849.     n_cur(p[n].posx,p[n].posy);
  1850.     if ((i = p[n].replen) < 20)             /* i = larger of replen and 20 */
  1851.         i = 20;
  1852.  
  1853.     sprintf(fmt,"%%-%d.%ds",i,i);                /* create format string */
  1854.     sprintf(s,fmt,p[n].vals[p[n].choice]);        /* put out value */
  1855.     n_puts(s);
  1856. }
  1857.  
  1858. /************************************************************************/
  1859. /*  makechoice
  1860. *   Allow the user to travel between choices on the screen, selecting
  1861. *   from a list of legal options.
  1862. *   Arrow keys change the selections on the screen.  The data structure
  1863. *   must be set up before entering this procedure.
  1864. */
  1865. makechoice(p,maxp,spec)
  1866.     struct pt p[];
  1867.     int maxp,spec;
  1868.     {
  1869.     int i,oldln,ln,c;
  1870.     
  1871.     oldln = ln = 0;
  1872.     n_color(7);
  1873.  
  1874.     for (i=1; i<maxp; i++)         /* print the opening selections */
  1875.         menuit(p,i);
  1876.  
  1877. /*
  1878. *  For each keystroke, repaint the current line and travel around the
  1879. *  data structure until the exit key is hit.
  1880. */
  1881.     do {
  1882.         if (oldln != ln) {
  1883.             n_color(7);                    /* re-write old line in normal color */
  1884.             menuit(p,oldln);
  1885.         }
  1886.         n_color(0x70);
  1887.         menuit(p,ln);                    /* write the current line in reverse */
  1888.         if (spec)
  1889.             makespecial();                /* display special requirements */
  1890.         n_cur(p[ln].posx,p[ln].posy);    /* reset cursor to current entry */
  1891.         oldln = ln;
  1892.  
  1893.         c = nbgetch();
  1894.         switch (c) {                    /* act on user's key */
  1895.         case CURUP:
  1896.             if (ln)
  1897.                 ln--;
  1898.             else
  1899.                 ln = maxp-1;
  1900.             break;
  1901.         case CURDN:                        /* up and down change current field */
  1902.             if (++ln >= maxp)
  1903.                 ln = 0;
  1904.             break;
  1905.         case PGUP:
  1906.         case HOME:
  1907.             ln = 0;
  1908.             break;
  1909.         case PGDN:
  1910.         case ENDKEY:
  1911.             ln = maxp-1;
  1912.             break;
  1913.         case 32:                /* space, tab and arrows change field contents */
  1914.         case 9:
  1915.         case CURRT:
  1916.             i = ++p[ln].choice;        /* if blank or non-existant, reset to 0 */
  1917.  
  1918.             if (!p[ln].vals[i] || !(*p[ln].vals[i]) || ' ' == *p[ln].vals[i])
  1919.                 p[ln].choice = 0;
  1920.             break;
  1921.         case CURLF:
  1922.             if (p[ln].choice)
  1923.                 p[ln].choice--;
  1924.             else {                /* if at zero, search for highest valid value */
  1925.                 i = 0;
  1926.                 while (p[ln].vals[i] && *p[ln].vals[i] && ' ' != *p[ln].vals[i])
  1927.                     i++;
  1928.                 if (i)
  1929.                     p[ln].choice = i-1;
  1930.             }
  1931.             break;
  1932.         case 8:
  1933.         case 21:
  1934.         case 13:
  1935.                 /* BS, Ctrl-U, or return */
  1936. /*
  1937. *  if allowed, the user can enter a string value.
  1938. *  prepare the field, by printing in a different color to set it apart.
  1939. */
  1940.             if (p[ln].replen) {
  1941.                 p[ln].choice = 1;
  1942.                 n_color(1);                        /* underline color */
  1943.                 n_cur(p[ln].posx,p[ln].posy);
  1944.                 for (i=0; i<p[ln].replen; i++)  /* blank out field */
  1945.                     n_putchar(' '); 
  1946.                 n_cur(p[ln].posx,p[ln].posy);
  1947.                 c = nbgets(p[ln].vals[1],p[ln].replen);
  1948.             }
  1949.             break;
  1950.         default:
  1951.             break;
  1952.         }
  1953.  
  1954.     } while (c != F1 && c != F10 && c != 27);
  1955.  
  1956.     return((c == F1) || (c == 27));
  1957.  
  1958. }
  1959.  
  1960. /************************************************************************/
  1961. /*  makespecial
  1962. *  Apart from standard menuing, we want to show an example of what the
  1963. *  text is going to look like in each of the three attributes.
  1964. */
  1965. makespecial()
  1966.     {
  1967.     n_cur(LO-1,15);
  1968.     n_color(pc[0].choice + (pc[1].choice <<4));
  1969.     n_puts("normal");
  1970.     n_cur(LO-1,25);
  1971.     n_color(pc[2].choice + (pc[3].choice <<4));
  1972.     n_puts("reverse");
  1973.     n_cur(LO-1,35);
  1974.     n_color(pc[4].choice + (pc[5].choice <<4));
  1975.     n_puts("underline");
  1976.  
  1977. }
  1978.  
  1979.  
  1980. /************************************************************************/
  1981. /*  parmchange
  1982. *   ALT-P from the user calls this routine to prompt the user for
  1983. *   telnet parameter values.
  1984. *   Set up the menuing system with the current values for this session.
  1985. *   Call the menuing routines, then analyze the results when it returns.
  1986. *
  1987. *   Affects the settings of:
  1988. *   session color, name, local echo, backspace/del, terminal type
  1989. *   overall file transfer enable, capture file name, screen access method
  1990. *
  1991. */
  1992. parmchange()
  1993.     {
  1994.     int i,c,colsave;
  1995. /*
  1996. *  set up the screen for the menus
  1997. *  Positions of text interlock with fields of menu routines
  1998. */
  1999.     leavetek();
  2000.     colsave = n_color(7);
  2001.     n_clear();
  2002.     n_cur(0,0);
  2003.  
  2004. n_puts("ALT-P                         Parameter menu ");
  2005. n_puts("   <      Select parameters, F1 to accept, ESC to leave unchanged      >\n");
  2006.  
  2007. n_puts("   --------------- Color setup and session parameters ----------------- ");
  2008. n_puts(" Text: ");
  2009.  
  2010. n_puts("          Normal Foreground (nfcolor) - ");
  2011. n_puts("          Normal Background (nbcolor) - ");
  2012. n_puts("         Reverse Foreground (rfcolor) - ");
  2013. n_puts("         Reverse Background (rbcolor) - ");
  2014. n_puts("       Underline Foreground (ufcolor) - ");
  2015. n_puts("       Underline Background (ubcolor) - ");
  2016. n_puts("        Use remote echo or local echo - ");
  2017. n_puts("                  Backspace key sends - ");
  2018. n_puts("                         Session name *>");
  2019. n_puts("                        Terminal type - ");
  2020. n_puts("   -------------- Parameters which apply to all sessions -------------- ");
  2021. n_puts("                    Capture file name *>");
  2022. n_puts(" Screen mode (for BIOS compatibility) - ");
  2023. n_puts("                     File transfer is - ");
  2024.  
  2025. n_puts("\n\nUse arrow keys to select, Enter clears changeable field (*>)");
  2026.  
  2027. /*
  2028. *  set values for menus from our telnet-stored values
  2029. */
  2030.     i = current->colors[0];        /* session colors */
  2031.     pc[0].choice = i & 15;
  2032.     pc[1].choice = i >> 4;
  2033.     i = current->colors[2];
  2034.     pc[2].choice = i & 15;
  2035.     pc[3].choice = i >> 4;
  2036.     i = current->colors[1];
  2037.     pc[4].choice = i & 15;
  2038.     pc[5].choice = i >> 4;
  2039.     pc[6].choice = current->echo;
  2040.     if (current->bksp == 8)        /* backspace setting */
  2041.         pc[7].choice = 0;
  2042.     else
  2043.         pc[7].choice = 1;
  2044.     pc[8].vals[0] = current->mname;        /* session name */
  2045.     pc[9].choice = current->termstate - 1;    /* terminal type */
  2046.     pc[10].vals[0] = def.capture;        /* capture file name */
  2047.     pc[11].choice = scmode();            /* screen write mode */
  2048.     pc[12].choice = transok;            /* filetransfer enable */
  2049.  
  2050.     if (makechoice(&pc,13,1)) {            /* call it and check the results */
  2051. /*
  2052. *  Work on results, only if user pressed 'F1', if ESC, this is skipped.
  2053. *
  2054. *
  2055. *  check for new capture file name
  2056. */
  2057.         if (pc[10].choice) {
  2058.             strcpy(s,pc[10].vals[1]);
  2059.             if (s[0] && s[0] != ' ') {    /* no NULL names */
  2060.                 Snewcap(s);
  2061.                 Sgetconfig(&def);
  2062.             }
  2063.             *pc[10].vals[1] = 0;
  2064.             pc[10].choice = 0;
  2065.         }
  2066. /*
  2067. *  check for new screen mode, BIOS or not
  2068. */
  2069.         if (pc[11].choice != scmode())
  2070.             Scwritemode(pc[11].choice);    /* set to whatever choice is */
  2071. /*
  2072. *  check whether to enable or disable file transfers
  2073. */
  2074.         if (pc[12].choice != transok) {
  2075.             transok = pc[12].choice;
  2076.             Sftpmode(transok);
  2077.             Srcpmode(transok);
  2078.         }
  2079. /*
  2080. *  check remote or local echo mode
  2081. */
  2082.         if (pc[6].choice != current->echo) {
  2083.             if (current->echo = pc[6].choice) {        /* assign = is on purpose */
  2084.                 sprintf(s,"%c%c%c",255,DOTEL,1);    /* telnet negotiation */
  2085.                 netpush(current->pnum);
  2086.                 netwrite(current->pnum,s,3);
  2087.             }
  2088.             else {
  2089.                 sprintf(s,"%c%c%c",255,DONTTEL,1);
  2090.                 netpush(current->pnum);
  2091.                 netwrite(current->pnum,s,3);
  2092.             }
  2093.         }
  2094. /*
  2095. *  check function of backspace or delete
  2096. */
  2097.         if (pc[7].choice) {
  2098.             current->bksp = 127;        /* backspace/delete are swapped */
  2099.             current->del = 8;
  2100.         }
  2101.         else {
  2102.             current->bksp = 8;            /* are normal */
  2103.             current->del = 127;
  2104.         }
  2105. /*
  2106. *  check new session name
  2107. */
  2108.         if (pc[8].choice) {
  2109.             strcpy(s,pc[8].vals[1]);
  2110.             if (s[0] != ' ' && s[0]) {        /* limit of 14 chars stored */
  2111.                 strncpy(current->mname,s,15);
  2112.                 current->mname[14] = 0;
  2113.             }
  2114.             *pc[8].vals[1] = 0;
  2115.             pc[8].choice = 0;
  2116.         }
  2117. /*
  2118. *  check terminal type
  2119. */
  2120.         if (pc[6].choice != current->termstate-1) 
  2121.             current->termstate = pc[9].choice + 1;
  2122. /*
  2123. *  assign new colors
  2124. */
  2125.         i = pc[0].choice + (pc[1].choice <<4);   /* normal color */
  2126.         if (i != current->colors[0]) {
  2127.             current->colors[0] = i;
  2128.             RSsetatt(127,current->vs);        /* seed the current screen */
  2129.             n_color(current->colors[0]);    /* seed ncolor */
  2130.         }
  2131.         current->colors[1] = pc[4].choice + (pc[5].choice <<4);
  2132.         current->colors[2] = pc[2].choice + (pc[3].choice <<4);
  2133.  
  2134.     }
  2135.  
  2136.  
  2137. /*
  2138. *  go back to telnet
  2139. */
  2140.     n_color(colsave);
  2141.     wrest(current);
  2142.  
  2143. }
  2144.  
  2145. /*************************************************************************/
  2146. /*  addsess
  2147. *   Add a session to a named machine, or prompt for a machine to be named.
  2148. */
  2149. addsess(st)
  2150.     char *st;
  2151.     {
  2152.     int i,new,cv;
  2153.     struct twin *newin;
  2154.  
  2155.     leavetek();
  2156.     cv = console->vs;
  2157.  
  2158.     if (st == NULL) {            /* no machine yet */
  2159.         wrest(console);
  2160.         vprint(cv,"\n\r\nEnter new machine name/address, ESC to return: \r\n");
  2161.         s[0] = '\0';
  2162.         while (0 >= (i = RSgets(cv,s,70)))
  2163.             Stask();
  2164.         if (i == 27 || !s[0]) 
  2165.             return(1);
  2166.         vprint(cv,"\r\n\n");    /* skip down a little */
  2167.         st = s;                    /* make a copy of the pointer to s */
  2168.  
  2169.     }
  2170.  
  2171.     mp = Sgethost(st);            /* gain access to host information */
  2172.     errhandle();
  2173.  
  2174.     if (!mp) {
  2175.         if (Sdomain(st) > 0) 
  2176.             vprint(cv,"\r\nQuerying the DOMAIN name server\r\n");
  2177.         else {
  2178.             vprint(cv,"\r\nNo nameserver, cannot resolve IP address\r\n");
  2179.             return(-1);
  2180.         }
  2181.     }
  2182.     else {
  2183. /*
  2184. *   tell user about it on the console
  2185. */
  2186.         vprint(cv,"\r\nTrying to open TCP connection to: ");
  2187.         vprint(cv,st);
  2188.         vprint(cv,"\r\n");
  2189.  
  2190.     /* try to serve the request */
  2191.         if ( 0 > (new = Snetopen(mp,HTELNET))) {
  2192.             errhandle();
  2193.             vprint(cv,"\r\nCould not open new connection to: ");
  2194.             vprint(cv,st);
  2195.             vprint(cv,"\r\n");
  2196.             return(-1);
  2197.         }
  2198.  
  2199.         newin = creatwindow();
  2200.         if (!newin) {                /* mem error */
  2201.             vprint(console->vs,"\r\nMemory Allocation error for window\r\n");
  2202.             return(-1);
  2203.         }
  2204.  
  2205.         newin->pnum = new;
  2206.         strncpy(newin->mname,st,14);
  2207.         newin->mname[14] = 0;
  2208.  
  2209.         inswindow(newin,1);
  2210.         vhead(newin->vs);
  2211.     }
  2212.  
  2213.     return(0);
  2214.  
  2215. }
  2216.  
  2217. #ifdef USETEK
  2218. leavetek()
  2219.     {
  2220.     if (current->termstate == TEKTYPE) {
  2221.         VGwrite(temptek,"\037",1);            /* force to alpha */
  2222.         current->termstate = VTEKTYPE;
  2223.         VGtmode(rgdevice);
  2224.         /* clear graphics mode */
  2225.         return(1);
  2226.     }
  2227.  
  2228.     return(0);                    /* we did nothing */
  2229. }
  2230. #endif
  2231.  
  2232. /***********************************************************************/
  2233. /*  capstat
  2234. *
  2235. */
  2236. capstat(s)
  2237.     char *s;
  2238.     {
  2239.     int r,c;
  2240.  
  2241.     r = n_row();
  2242.     c = n_col();
  2243.  
  2244.     n_cur(24,54);
  2245.     n_draw(s,strlen(s));
  2246.  
  2247.     n_cur(r,c);
  2248. }
  2249.  
  2250. /***********************************************************************/
  2251. /*  scrollback
  2252. *   Take keyboard keys to manipulate the screen's scrollback
  2253. *   
  2254. */
  2255. scrollback()
  2256.     {
  2257.     int c;
  2258.  
  2259.     if (current->termstate == TEKTYPE)
  2260.         return(0);
  2261.  
  2262.     while (0 < ( c = n_chkchar())) {
  2263.         switch (c) {
  2264.             case CURUP:
  2265.                 VSscrolback(current->vs,1);
  2266.                 break;
  2267.             case CURDN:
  2268.                 VSscrolforward(current->vs,1);
  2269.                 break;
  2270.             case PGUP:
  2271.                 VSscrolback(current->vs,22);
  2272.                 break;
  2273.             case PGDN:
  2274.                 VSscrolforward(current->vs,22);
  2275.                 break;
  2276.             default:
  2277.                 break;
  2278.         }
  2279.     }
  2280.  
  2281. }
  2282.