home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / gnunet10.zip / source / telnet / commands.c < prev    next >
C/C++ Source or Header  |  1996-07-27  |  73KB  |  2,980 lines

  1. /*
  2.  * Copyright (c) 1988, 1990, 1993
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static char sccsid[] = "@(#)commands.c    8.4 (Berkeley) 5/30/95";
  36. #endif /* not lint */
  37.  
  38. #if    defined(unix)
  39. # include <sys/param.h>
  40. # if    defined(CRAY) || defined(sysV88)
  41. #  include <sys/types.h>
  42. # endif
  43. # include <sys/file.h>
  44. #else
  45. # include <sys/types.h>
  46. #endif    /* defined(unix) */
  47. #include <sys/socket.h>
  48. #include <netinet/in.h>
  49. #ifdef    CRAY
  50. # include <fcntl.h>
  51. #endif    /* CRAY */
  52.  
  53. #include <signal.h>
  54. #include <netdb.h>
  55. #include <ctype.h>
  56. #include <pwd.h>
  57. #include <varargs.h>
  58. #include <errno.h>
  59.  
  60. #ifdef HAVE_MALLOC_H
  61. #include <malloc.h>
  62. #endif
  63.  
  64. #include <arpa/telnet.h>
  65.  
  66. #include "general.h"
  67.  
  68. #include "ring.h"
  69.  
  70. #include "externs.h"
  71. #include "defines.h"
  72. #include "types.h"
  73.  
  74. #if !defined(CRAY) && !defined(sysV88)
  75. #ifdef HAVE_NETINET_IN_SYSTM_H
  76. #include <netinet/in_systm.h>
  77. #endif
  78. # if (defined(vax) || defined(tahoe) || defined(hp300)) && !defined(ultrix)
  79. # include <machine/endian.h>
  80. # endif /* vax */
  81. #endif /* !defined(CRAY) && !defined(sysV88) */
  82. #ifdef HAVE_NETINET_IP_H
  83. #include <netinet/ip.h>
  84. #endif
  85.  
  86. #if    defined(IPPROTO_IP) && defined(IP_TOS)
  87. int tos = -1;
  88. #endif    /* defined(IPPROTO_IP) && defined(IP_TOS) */
  89.  
  90. char    *hostname;
  91. static char *_hostname = 0;
  92.  
  93. extern char *getenv();
  94.  
  95. extern int isprefix();
  96. extern char **genget();
  97. extern int Ambiguous();
  98.  
  99. static call();
  100.  
  101. typedef struct {
  102.     char    *name;        /* command name */
  103.     char    *help;        /* help string (NULL for no help) */
  104.     int    (*handler)();    /* routine which executes command */
  105.     int    needconnect;    /* Do we need to be connected to execute? */
  106. } Command;
  107.  
  108. static char line[256];
  109. static char saveline[256];
  110. static int margc;
  111. static char *margv[20];
  112.  
  113.     static void
  114. makeargv()
  115. {
  116.     register char *cp, *cp2, c;
  117.     register char **argp = margv;
  118.  
  119.     margc = 0;
  120.     cp = line;
  121.     if (*cp == '!') {        /* Special case shell escape */
  122.     strcpy(saveline, line);    /* save for shell command */
  123.     *argp++ = "!";        /* No room in string to get this */
  124.     margc++;
  125.     cp++;
  126.     }
  127.     while (c = *cp) {
  128.     register int inquote = 0;
  129.     while (isspace(c))
  130.         c = *++cp;
  131.     if (c == '\0')
  132.         break;
  133.     *argp++ = cp;
  134.     margc += 1;
  135.     for (cp2 = cp; c != '\0'; c = *++cp) {
  136.         if (inquote) {
  137.         if (c == inquote) {
  138.             inquote = 0;
  139.             continue;
  140.         }
  141.         } else {
  142.         if (c == '\\') {
  143.             if ((c = *++cp) == '\0')
  144.             break;
  145.         } else if (c == '"') {
  146.             inquote = '"';
  147.             continue;
  148.         } else if (c == '\'') {
  149.             inquote = '\'';
  150.             continue;
  151.         } else if (isspace(c))
  152.             break;
  153.         }
  154.         *cp2++ = c;
  155.     }
  156.     *cp2 = '\0';
  157.     if (c == '\0')
  158.         break;
  159.     cp++;
  160.     }
  161.     *argp++ = 0;
  162. }
  163.  
  164. /*
  165.  * Make a character string into a number.
  166.  *
  167.  * Todo:  1.  Could take random integers (12, 0x12, 012, 0b1).
  168.  */
  169.  
  170.     static
  171. special(s)
  172.     register char *s;
  173. {
  174.     register char c;
  175.     char b;
  176.  
  177.     switch (*s) {
  178.     case '^':
  179.         b = *++s;
  180.         if (b == '?') {
  181.             c = b | 0x40;        /* DEL */
  182.         } else {
  183.             c = b & 0x1f;
  184.         }
  185.         break;
  186.     default:
  187.         c = *s;
  188.         break;
  189.     }
  190.     return c;
  191. }
  192.  
  193. /*
  194.  * Construct a control character sequence
  195.  * for a special character.
  196.  */
  197.     static char *
  198. control(c)
  199.     register cc_t c;
  200. {
  201.     static char buf[5];
  202.     /*
  203.      * The only way I could get the Sun 3.5 compiler
  204.      * to shut up about
  205.      *    if ((unsigned int)c >= 0x80)
  206.      * was to assign "c" to an unsigned int variable...
  207.      * Arggg....
  208.      */
  209.     register unsigned int uic = (unsigned int)c;
  210.  
  211.     if (uic == 0x7f)
  212.         return ("^?");
  213.     if (c == (cc_t)_POSIX_VDISABLE) {
  214.         return "off";
  215.     }
  216.     if (uic >= 0x80) {
  217.         buf[0] = '\\';
  218.         buf[1] = ((c>>6)&07) + '0';
  219.         buf[2] = ((c>>3)&07) + '0';
  220.         buf[3] = (c&07) + '0';
  221.         buf[4] = 0;
  222.     } else if (uic >= 0x20) {
  223.         buf[0] = c;
  224.         buf[1] = 0;
  225.     } else {
  226.         buf[0] = '^';
  227.         buf[1] = '@'+c;
  228.         buf[2] = 0;
  229.     }
  230.     return (buf);
  231. }
  232.  
  233.  
  234.  
  235. /*
  236.  *    The following are data structures and routines for
  237.  *    the "send" command.
  238.  *
  239.  */
  240.  
  241. struct sendlist {
  242.     char    *name;        /* How user refers to it (case independent) */
  243.     char    *help;        /* Help information (0 ==> no help) */
  244.     int        needconnect;    /* Need to be connected */
  245.     int        narg;        /* Number of arguments */
  246.     int        (*handler)();    /* Routine to perform (for special ops) */
  247.     int        nbyte;        /* Number of bytes to send this command */
  248.     int        what;        /* Character to be sent (<0 ==> special) */
  249. };
  250.  
  251.  
  252. static int
  253.     send_esc P((void)),
  254.     send_help P((void)),
  255.     send_docmd P((char *)),
  256.     send_dontcmd P((char *)),
  257.     send_willcmd P((char *)),
  258.     send_wontcmd P((char *));
  259.  
  260. static struct sendlist Sendlist[] = {
  261.     { "ao",    "Send Telnet Abort output",        1, 0, 0, 2, AO },
  262.     { "ayt",    "Send Telnet 'Are You There'",        1, 0, 0, 2, AYT },
  263.     { "brk",    "Send Telnet Break",            1, 0, 0, 2, BREAK },
  264.     { "break",    0,                    1, 0, 0, 2, BREAK },
  265.     { "ec",    "Send Telnet Erase Character",        1, 0, 0, 2, EC },
  266.     { "el",    "Send Telnet Erase Line",        1, 0, 0, 2, EL },
  267.     { "escape",    "Send current escape character",    1, 0, send_esc, 1, 0 },
  268.     { "ga",    "Send Telnet 'Go Ahead' sequence",    1, 0, 0, 2, GA },
  269.     { "ip",    "Send Telnet Interrupt Process",    1, 0, 0, 2, IP },
  270.     { "intp",    0,                    1, 0, 0, 2, IP },
  271.     { "interrupt", 0,                    1, 0, 0, 2, IP },
  272.     { "intr",    0,                    1, 0, 0, 2, IP },
  273.     { "nop",    "Send Telnet 'No operation'",        1, 0, 0, 2, NOP },
  274.     { "eor",    "Send Telnet 'End of Record'",        1, 0, 0, 2, EOR },
  275.     { "abort",    "Send Telnet 'Abort Process'",        1, 0, 0, 2, ABORT },
  276.     { "susp",    "Send Telnet 'Suspend Process'",    1, 0, 0, 2, SUSP },
  277.     { "eof",    "Send Telnet End of File Character",    1, 0, 0, 2, xEOF },
  278.     { "synch",    "Perform Telnet 'Synch operation'",    1, 0, dosynch, 2, 0 },
  279.     { "getstatus", "Send request for STATUS",        1, 0, get_status, 6, 0 },
  280.     { "?",    "Display send options",            0, 0, send_help, 0, 0 },
  281.     { "help",    0,                    0, 0, send_help, 0, 0 },
  282.     { "do",    0,                    0, 1, send_docmd, 3, 0 },
  283.     { "dont",    0,                    0, 1, send_dontcmd, 3, 0 },
  284.     { "will",    0,                    0, 1, send_willcmd, 3, 0 },
  285.     { "wont",    0,                    0, 1, send_wontcmd, 3, 0 },
  286.     { 0 }
  287. };
  288.  
  289. #define    GETSEND(name) ((struct sendlist *) genget(name, (char **) Sendlist, \
  290.                 sizeof(struct sendlist)))
  291.  
  292.     static int
  293. sendcmd(argc, argv)
  294.     int  argc;
  295.     char **argv;
  296. {
  297.     int count;        /* how many bytes we are going to need to send */
  298.     int i;
  299.     int question = 0;    /* was at least one argument a question */
  300.     struct sendlist *s;    /* pointer to current command */
  301.     int success = 0;
  302.     int needconnect = 0;
  303.  
  304.     if (argc < 2) {
  305.     printf("need at least one argument for 'send' command\n");
  306.     printf("'send ?' for help\n");
  307.     return 0;
  308.     }
  309.     /*
  310.      * First, validate all the send arguments.
  311.      * In addition, we see how much space we are going to need, and
  312.      * whether or not we will be doing a "SYNCH" operation (which
  313.      * flushes the network queue).
  314.      */
  315.     count = 0;
  316.     for (i = 1; i < argc; i++) {
  317.     s = GETSEND(argv[i]);
  318.     if (s == 0) {
  319.         printf("Unknown send argument '%s'\n'send ?' for help.\n",
  320.             argv[i]);
  321.         return 0;
  322.     } else if (Ambiguous(s)) {
  323.         printf("Ambiguous send argument '%s'\n'send ?' for help.\n",
  324.             argv[i]);
  325.         return 0;
  326.     }
  327.     if (i + s->narg >= argc) {
  328.         fprintf(stderr,
  329.         "Need %d argument%s to 'send %s' command.  'send %s ?' for help.\n",
  330.         s->narg, s->narg == 1 ? "" : "s", s->name, s->name);
  331.         return 0;
  332.     }
  333.     count += s->nbyte;
  334.     if (s->handler == send_help) {
  335.         send_help();
  336.         return 0;
  337.     }
  338.  
  339.     i += s->narg;
  340.     needconnect += s->needconnect;
  341.     }
  342.     if (!connected && needconnect) {
  343.     printf("?Need to be connected first.\n");
  344.     printf("'send ?' for help\n");
  345.     return 0;
  346.     }
  347.     /* Now, do we have enough room? */
  348.     if (NETROOM() < count) {
  349.     printf("There is not enough room in the buffer TO the network\n");
  350.     printf("to process your request.  Nothing will be done.\n");
  351.     printf("('send synch' will throw away most data in the network\n");
  352.     printf("buffer, if this might help.)\n");
  353.     return 0;
  354.     }
  355.     /* OK, they are all OK, now go through again and actually send */
  356.     count = 0;
  357.     for (i = 1; i < argc; i++) {
  358.     if ((s = GETSEND(argv[i])) == 0) {
  359.         fprintf(stderr, "Telnet 'send' error - argument disappeared!\n");
  360.         (void) quit();
  361.         /*NOTREACHED*/
  362.     }
  363.     if (s->handler) {
  364.         count++;
  365.         success += (*s->handler)((s->narg > 0) ? argv[i+1] : 0,
  366.                   (s->narg > 1) ? argv[i+2] : 0);
  367.         i += s->narg;
  368.     } else {
  369.         NET2ADD(IAC, s->what);
  370.         printoption("SENT", IAC, s->what);
  371.     }
  372.     }
  373.     return (count == success);
  374. }
  375.  
  376.     static int
  377. send_esc()
  378. {
  379.     NETADD(escape);
  380.     return 1;
  381. }
  382.  
  383.     static int
  384. send_docmd(name)
  385.     char *name;
  386. {
  387.     return(send_tncmd(send_do, "do", name));
  388. }
  389.  
  390.     static int
  391. send_dontcmd(name)
  392.     char *name;
  393. {
  394.     return(send_tncmd(send_dont, "dont", name));
  395. }
  396.     static int
  397. send_willcmd(name)
  398.     char *name;
  399. {
  400.     return(send_tncmd(send_will, "will", name));
  401. }
  402.     static int
  403. send_wontcmd(name)
  404.     char *name;
  405. {
  406.     return(send_tncmd(send_wont, "wont", name));
  407. }
  408.  
  409.     int
  410. send_tncmd(func, cmd, name)
  411.     void    (*func)();
  412.     char    *cmd, *name;
  413. {
  414.     char **cpp;
  415.     extern char *telopts[];
  416.     register int val = 0;
  417.  
  418.     if (isprefix(name, "help") || isprefix(name, "?")) {
  419.     register int col, len;
  420.  
  421.     printf("Usage: send %s <value|option>\n", cmd);
  422.     printf("\"value\" must be from 0 to 255\n");
  423.     printf("Valid options are:\n\t");
  424.  
  425.     col = 8;
  426.     for (cpp = telopts; *cpp; cpp++) {
  427.         len = strlen(*cpp) + 3;
  428.         if (col + len > 65) {
  429.         printf("\n\t");
  430.         col = 8;
  431.         }
  432.         printf(" \"%s\"", *cpp);
  433.         col += len;
  434.     }
  435.     printf("\n");
  436.     return 0;
  437.     }
  438.     cpp = (char **)genget(name, telopts, sizeof(char *));
  439.     if (Ambiguous(cpp)) {
  440.     fprintf(stderr,"'%s': ambiguous argument ('send %s ?' for help).\n",
  441.                     name, cmd);
  442.     return 0;
  443.     }
  444.     if (cpp) {
  445.     val = cpp - telopts;
  446.     } else {
  447.     register char *cp = name;
  448.  
  449.     while (*cp >= '0' && *cp <= '9') {
  450.         val *= 10;
  451.         val += *cp - '0';
  452.         cp++;
  453.     }
  454.     if (*cp != 0) {
  455.         fprintf(stderr, "'%s': unknown argument ('send %s ?' for help).\n",
  456.                     name, cmd);
  457.         return 0;
  458.     } else if (val < 0 || val > 255) {
  459.         fprintf(stderr, "'%s': bad value ('send %s ?' for help).\n",
  460.                     name, cmd);
  461.         return 0;
  462.     }
  463.     }
  464.     if (!connected) {
  465.     printf("?Need to be connected first.\n");
  466.     return 0;
  467.     }
  468.     (*func)(val, 1);
  469.     return 1;
  470. }
  471.  
  472.     static int
  473. send_help()
  474. {
  475.     struct sendlist *s;    /* pointer to current command */
  476.     for (s = Sendlist; s->name; s++) {
  477.     if (s->help)
  478.         printf("%-15s %s\n", s->name, s->help);
  479.     }
  480.     return(0);
  481. }
  482.  
  483. /*
  484.  * The following are the routines and data structures referred
  485.  * to by the arguments to the "toggle" command.
  486.  */
  487.  
  488.     static int
  489. lclchars()
  490. {
  491.     donelclchars = 1;
  492.     return 1;
  493. }
  494.  
  495.     static int
  496. togdebug()
  497. {
  498. #ifndef    NOT43
  499.     if (net > 0 &&
  500.     (SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) {
  501.         perror("setsockopt (SO_DEBUG)");
  502.     }
  503. #else    /* NOT43 */
  504.     if (debug) {
  505.     if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
  506.         perror("setsockopt (SO_DEBUG)");
  507.     } else
  508.     printf("Cannot turn off socket debugging\n");
  509. #endif    /* NOT43 */
  510.     return 1;
  511. }
  512.  
  513.  
  514.     static int
  515. togcrlf()
  516. {
  517.     if (crlf) {
  518.     printf("Will send carriage returns as telnet <CR><LF>.\n");
  519.     } else {
  520.     printf("Will send carriage returns as telnet <CR><NUL>.\n");
  521.     }
  522.     return 1;
  523. }
  524.  
  525. int binmode;
  526.  
  527.     static int
  528. togbinary(val)
  529.     int val;
  530. {
  531.     donebinarytoggle = 1;
  532.  
  533.     if (val >= 0) {
  534.     binmode = val;
  535.     } else {
  536.     if (my_want_state_is_will(TELOPT_BINARY) &&
  537.                 my_want_state_is_do(TELOPT_BINARY)) {
  538.         binmode = 1;
  539.     } else if (my_want_state_is_wont(TELOPT_BINARY) &&
  540.                 my_want_state_is_dont(TELOPT_BINARY)) {
  541.         binmode = 0;
  542.     }
  543.     val = binmode ? 0 : 1;
  544.     }
  545.  
  546.     if (val == 1) {
  547.     if (my_want_state_is_will(TELOPT_BINARY) &&
  548.                     my_want_state_is_do(TELOPT_BINARY)) {
  549.         printf("Already operating in binary mode with remote host.\n");
  550.     } else {
  551.         printf("Negotiating binary mode with remote host.\n");
  552.         tel_enter_binary(3);
  553.     }
  554.     } else {
  555.     if (my_want_state_is_wont(TELOPT_BINARY) &&
  556.                     my_want_state_is_dont(TELOPT_BINARY)) {
  557.         printf("Already in network ascii mode with remote host.\n");
  558.     } else {
  559.         printf("Negotiating network ascii mode with remote host.\n");
  560.         tel_leave_binary(3);
  561.     }
  562.     }
  563.     return 1;
  564. }
  565.  
  566.     static int
  567. togrbinary(val)
  568.     int val;
  569. {
  570.     donebinarytoggle = 1;
  571.  
  572.     if (val == -1)
  573.     val = my_want_state_is_do(TELOPT_BINARY) ? 0 : 1;
  574.  
  575.     if (val == 1) {
  576.     if (my_want_state_is_do(TELOPT_BINARY)) {
  577.         printf("Already receiving in binary mode.\n");
  578.     } else {
  579.         printf("Negotiating binary mode on input.\n");
  580.         tel_enter_binary(1);
  581.     }
  582.     } else {
  583.     if (my_want_state_is_dont(TELOPT_BINARY)) {
  584.         printf("Already receiving in network ascii mode.\n");
  585.     } else {
  586.         printf("Negotiating network ascii mode on input.\n");
  587.         tel_leave_binary(1);
  588.     }
  589.     }
  590.     return 1;
  591. }
  592.  
  593.     static int
  594. togxbinary(val)
  595.     int val;
  596. {
  597.     donebinarytoggle = 1;
  598.  
  599.     if (val == -1)
  600.     val = my_want_state_is_will(TELOPT_BINARY) ? 0 : 1;
  601.  
  602.     if (val == 1) {
  603.     if (my_want_state_is_will(TELOPT_BINARY)) {
  604.         printf("Already transmitting in binary mode.\n");
  605.     } else {
  606.         printf("Negotiating binary mode on output.\n");
  607.         tel_enter_binary(2);
  608.     }
  609.     } else {
  610.     if (my_want_state_is_wont(TELOPT_BINARY)) {
  611.         printf("Already transmitting in network ascii mode.\n");
  612.     } else {
  613.         printf("Negotiating network ascii mode on output.\n");
  614.         tel_leave_binary(2);
  615.     }
  616.     }
  617.     return 1;
  618. }
  619.  
  620.  
  621. static int togglehelp P((void));
  622. #if    defined(AUTHENTICATION)
  623. extern int auth_togdebug P((int));
  624. #endif
  625. #ifdef    ENCRYPTION
  626. extern int EncryptAutoEnc P((int));
  627. extern int EncryptAutoDec P((int));
  628. extern int EncryptDebug P((int));
  629. extern int EncryptVerbose P((int));
  630. #endif    /* ENCRYPTION */
  631.  
  632. struct togglelist {
  633.     char    *name;        /* name of toggle */
  634.     char    *help;        /* help message */
  635.     int        (*handler)();    /* routine to do actual setting */
  636.     int        *variable;
  637.     char    *actionexplanation;
  638. };
  639.  
  640. static struct togglelist Togglelist[] = {
  641.     { "autoflush",
  642.     "flushing of output when sending interrupt characters",
  643.         0,
  644.         &autoflush,
  645.             "flush output when sending interrupt characters" },
  646.     { "autosynch",
  647.     "automatic sending of interrupt characters in urgent mode",
  648.         0,
  649.         &autosynch,
  650.             "send interrupt characters in urgent mode" },
  651. #if    defined(AUTHENTICATION)
  652.     { "autologin",
  653.     "automatic sending of login and/or authentication info",
  654.         0,
  655.         &autologin,
  656.             "send login name and/or authentication information" },
  657.     { "authdebug",
  658.     "Toggle authentication debugging",
  659.         auth_togdebug,
  660.         0,
  661.              "print authentication debugging information" },
  662. #endif
  663. #ifdef    ENCRYPTION
  664.     { "autoencrypt",
  665.     "automatic encryption of data stream",
  666.         EncryptAutoEnc,
  667.         0,
  668.             "automatically encrypt output" },
  669.     { "autodecrypt",
  670.     "automatic decryption of data stream",
  671.         EncryptAutoDec,
  672.         0,
  673.             "automatically decrypt input" },
  674.     { "verbose_encrypt",
  675.     "Toggle verbose encryption output",
  676.         EncryptVerbose,
  677.         0,
  678.             "print verbose encryption output" },
  679.     { "encdebug",
  680.     "Toggle encryption debugging",
  681.         EncryptDebug,
  682.         0,
  683.             "print encryption debugging information" },
  684. #endif    /* ENCRYPTION */
  685.     { "skiprc",
  686.     "don't read ~/.telnetrc file",
  687.         0,
  688.         &skiprc,
  689.             "skip reading of ~/.telnetrc file" },
  690.     { "binary",
  691.     "sending and receiving of binary data",
  692.         togbinary,
  693.         0,
  694.             0 },
  695.     { "inbinary",
  696.     "receiving of binary data",
  697.         togrbinary,
  698.         0,
  699.             0 },
  700.     { "outbinary",
  701.     "sending of binary data",
  702.         togxbinary,
  703.         0,
  704.             0 },
  705.     { "crlf",
  706.     "sending carriage returns as telnet <CR><LF>",
  707.         togcrlf,
  708.         &crlf,
  709.             0 },
  710.     { "crmod",
  711.     "mapping of received carriage returns",
  712.         0,
  713.         &crmod,
  714.             "map carriage return on output" },
  715.     { "localchars",
  716.     "local recognition of certain control characters",
  717.         lclchars,
  718.         &localchars,
  719.             "recognize certain control characters" },
  720.     { " ", "", 0 },        /* empty line */
  721. #if    defined(unix) && defined(TN3270)
  722.     { "apitrace",
  723.     "(debugging) toggle tracing of API transactions",
  724.         0,
  725.         &apitrace,
  726.             "trace API transactions" },
  727.     { "cursesdata",
  728.     "(debugging) toggle printing of hexadecimal curses data",
  729.         0,
  730.         &cursesdata,
  731.             "print hexadecimal representation of curses data" },
  732. #endif    /* defined(unix) && defined(TN3270) */
  733.     { "debug",
  734.     "debugging",
  735.         togdebug,
  736.         &debug,
  737.             "turn on socket level debugging" },
  738.     { "netdata",
  739.     "printing of hexadecimal network data (debugging)",
  740.         0,
  741.         &netdata,
  742.             "print hexadecimal representation of network traffic" },
  743.     { "prettydump",
  744.     "output of \"netdata\" to user readable format (debugging)",
  745.         0,
  746.         &prettydump,
  747.             "print user readable output for \"netdata\"" },
  748.     { "options",
  749.     "viewing of options processing (debugging)",
  750.         0,
  751.         &showoptions,
  752.             "show option processing" },
  753. #if    defined(unix)
  754.     { "termdata",
  755.     "(debugging) toggle printing of hexadecimal terminal data",
  756.         0,
  757.         &termdata,
  758.             "print hexadecimal representation of terminal traffic" },
  759. #endif    /* defined(unix) */
  760.     { "?",
  761.     0,
  762.         togglehelp },
  763.     { "help",
  764.     0,
  765.         togglehelp },
  766.     { 0 }
  767. };
  768.  
  769.     static int
  770. togglehelp()
  771. {
  772.     struct togglelist *c;
  773.  
  774.     for (c = Togglelist; c->name; c++) {
  775.     if (c->help) {
  776.         if (*c->help)
  777.         printf("%-15s toggle %s\n", c->name, c->help);
  778.         else
  779.         printf("\n");
  780.     }
  781.     }
  782.     printf("\n");
  783.     printf("%-15s %s\n", "?", "display help information");
  784.     return 0;
  785. }
  786.  
  787.     static void
  788. settogglehelp(set)
  789.     int set;
  790. {
  791.     struct togglelist *c;
  792.  
  793.     for (c = Togglelist; c->name; c++) {
  794.     if (c->help) {
  795.         if (*c->help)
  796.         printf("%-15s %s %s\n", c->name, set ? "enable" : "disable",
  797.                         c->help);
  798.         else
  799.         printf("\n");
  800.     }
  801.     }
  802. }
  803.  
  804. #define    GETTOGGLE(name) (struct togglelist *) \
  805.         genget(name, (char **) Togglelist, sizeof(struct togglelist))
  806.  
  807.     static int
  808. toggle(argc, argv)
  809.     int  argc;
  810.     char *argv[];
  811. {
  812.     int retval = 1;
  813.     char *name;
  814.     struct togglelist *c;
  815.  
  816.     if (argc < 2) {
  817.     fprintf(stderr,
  818.         "Need an argument to 'toggle' command.  'toggle ?' for help.\n");
  819.     return 0;
  820.     }
  821.     argc--;
  822.     argv++;
  823.     while (argc--) {
  824.     name = *argv++;
  825.     c = GETTOGGLE(name);
  826.     if (Ambiguous(c)) {
  827.         fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n",
  828.                     name);
  829.         return 0;
  830.     } else if (c == 0) {
  831.         fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\n",
  832.                     name);
  833.         return 0;
  834.     } else {
  835.         if (c->variable) {
  836.         *c->variable = !*c->variable;        /* invert it */
  837.         if (c->actionexplanation) {
  838.             printf("%s %s.\n", *c->variable? "Will" : "Won't",
  839.                             c->actionexplanation);
  840.         }
  841.         }
  842.         if (c->handler) {
  843.         retval &= (*c->handler)(-1);
  844.         }
  845.     }
  846.     }
  847.     return retval;
  848. }
  849.  
  850. /*
  851.  * The following perform the "set" command.
  852.  */
  853.  
  854. #ifdef    USE_TERMIO
  855. struct termio new_tc = { 0 };
  856. #endif
  857.  
  858. struct setlist {
  859.     char *name;                /* name */
  860.     char *help;                /* help information */
  861.     void (*handler)();
  862.     cc_t *charp;            /* where it is located at */
  863. };
  864.  
  865. static struct setlist Setlist[] = {
  866. #ifdef    KLUDGELINEMODE
  867.     { "echo",     "character to toggle local echoing on/off", 0, &echoc },
  868. #endif
  869.     { "escape",    "character to escape back to telnet command mode", 0, &escape },
  870.     { "rlogin", "rlogin escape character", 0, &rlogin },
  871.     { "tracefile", "file to write trace information to", SetNetTrace, (cc_t *)NetTraceFile},
  872.     { " ", "" },
  873.     { " ", "The following need 'localchars' to be toggled true", 0, 0 },
  874.     { "flushoutput", "character to cause an Abort Output", 0, termFlushCharp },
  875.     { "interrupt", "character to cause an Interrupt Process", 0, termIntCharp },
  876.     { "quit",    "character to cause an Abort process", 0, termQuitCharp },
  877.     { "eof",    "character to cause an EOF ", 0, termEofCharp },
  878.     { " ", "" },
  879.     { " ", "The following are for local editing in linemode", 0, 0 },
  880.     { "erase",    "character to use to erase a character", 0, termEraseCharp },
  881.     { "kill",    "character to use to erase a line", 0, termKillCharp },
  882.     { "lnext",    "character to use for literal next", 0, termLiteralNextCharp },
  883.     { "susp",    "character to cause a Suspend Process", 0, termSuspCharp },
  884.     { "reprint", "character to use for line reprint", 0, termRprntCharp },
  885.     { "worderase", "character to use to erase a word", 0, termWerasCharp },
  886.     { "start",    "character to use for XON", 0, termStartCharp },
  887.     { "stop",    "character to use for XOFF", 0, termStopCharp },
  888.     { "forw1",    "alternate end of line character", 0, termForw1Charp },
  889.     { "forw2",    "alternate end of line character", 0, termForw2Charp },
  890.     { "ayt",    "alternate AYT character", 0, termAytCharp },
  891.     { 0 }
  892. };
  893.  
  894. #if    defined(CRAY) && !defined(__STDC__)
  895. /* Work around compiler bug in pcc 4.1.5 */
  896.     void
  897. _setlist_init()
  898. {
  899. #ifndef    KLUDGELINEMODE
  900. #define    N 5
  901. #else
  902. #define    N 6
  903. #endif
  904.     Setlist[N+0].charp = &termFlushChar;
  905.     Setlist[N+1].charp = &termIntChar;
  906.     Setlist[N+2].charp = &termQuitChar;
  907.     Setlist[N+3].charp = &termEofChar;
  908.     Setlist[N+6].charp = &termEraseChar;
  909.     Setlist[N+7].charp = &termKillChar;
  910.     Setlist[N+8].charp = &termLiteralNextChar;
  911.     Setlist[N+9].charp = &termSuspChar;
  912.     Setlist[N+10].charp = &termRprntChar;
  913.     Setlist[N+11].charp = &termWerasChar;
  914.     Setlist[N+12].charp = &termStartChar;
  915.     Setlist[N+13].charp = &termStopChar;
  916.     Setlist[N+14].charp = &termForw1Char;
  917.     Setlist[N+15].charp = &termForw2Char;
  918.     Setlist[N+16].charp = &termAytChar;
  919. #undef    N
  920. }
  921. #endif    /* defined(CRAY) && !defined(__STDC__) */
  922.  
  923.     static struct setlist *
  924. getset(name)
  925.     char *name;
  926. {
  927.     return (struct setlist *)
  928.         genget(name, (char **) Setlist, sizeof(struct setlist));
  929. }
  930.  
  931.     void
  932. set_escape_char(s)
  933.     char *s;
  934. {
  935.     if (rlogin != _POSIX_VDISABLE) {
  936.         rlogin = (s && *s) ? special(s) : _POSIX_VDISABLE;
  937.         printf("Telnet rlogin escape character is '%s'.\n",
  938.                     control(rlogin));
  939.     } else {
  940.         escape = (s && *s) ? special(s) : _POSIX_VDISABLE;
  941.         printf("Telnet escape character is '%s'.\n", control(escape));
  942.     }
  943. }
  944.  
  945.     static int
  946. setcmd(argc, argv)
  947.     int  argc;
  948.     char *argv[];
  949. {
  950.     int value;
  951.     struct setlist *ct;
  952.     struct togglelist *c;
  953.  
  954.     if (argc < 2 || argc > 3) {
  955.     printf("Format is 'set Name Value'\n'set ?' for help.\n");
  956.     return 0;
  957.     }
  958.     if ((argc == 2) && (isprefix(argv[1], "?") || isprefix(argv[1], "help"))) {
  959.     for (ct = Setlist; ct->name; ct++)
  960.         printf("%-15s %s\n", ct->name, ct->help);
  961.     printf("\n");
  962.     settogglehelp(1);
  963.     printf("%-15s %s\n", "?", "display help information");
  964.     return 0;
  965.     }
  966.  
  967.     ct = getset(argv[1]);
  968.     if (ct == 0) {
  969.     c = GETTOGGLE(argv[1]);
  970.     if (c == 0) {
  971.         fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n",
  972.             argv[1]);
  973.         return 0;
  974.     } else if (Ambiguous(c)) {
  975.         fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n",
  976.             argv[1]);
  977.         return 0;
  978.     }
  979.     if (c->variable) {
  980.         if ((argc == 2) || (strcmp("on", argv[2]) == 0))
  981.         *c->variable = 1;
  982.         else if (strcmp("off", argv[2]) == 0)
  983.         *c->variable = 0;
  984.         else {
  985.         printf("Format is 'set togglename [on|off]'\n'set ?' for help.\n");
  986.         return 0;
  987.         }
  988.         if (c->actionexplanation) {
  989.         printf("%s %s.\n", *c->variable? "Will" : "Won't",
  990.                             c->actionexplanation);
  991.         }
  992.     }
  993.     if (c->handler)
  994.         (*c->handler)(1);
  995.     } else if (argc != 3) {
  996.     printf("Format is 'set Name Value'\n'set ?' for help.\n");
  997.     return 0;
  998.     } else if (Ambiguous(ct)) {
  999.     fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n",
  1000.             argv[1]);
  1001.     return 0;
  1002.     } else if (ct->handler) {
  1003.     (*ct->handler)(argv[2]);
  1004.     printf("%s set to \"%s\".\n", ct->name, (char *)ct->charp);
  1005.     } else {
  1006.     if (strcmp("off", argv[2])) {
  1007.         value = special(argv[2]);
  1008.     } else {
  1009.         value = _POSIX_VDISABLE;
  1010.     }
  1011.     *(ct->charp) = (cc_t)value;
  1012.     printf("%s character is '%s'.\n", ct->name, control(*(ct->charp)));
  1013.     }
  1014.     slc_check();
  1015.     return 1;
  1016. }
  1017.  
  1018.     static int
  1019. unsetcmd(argc, argv)
  1020.     int  argc;
  1021.     char *argv[];
  1022. {
  1023.     struct setlist *ct;
  1024.     struct togglelist *c;
  1025.     register char *name;
  1026.  
  1027.     if (argc < 2) {
  1028.     fprintf(stderr,
  1029.         "Need an argument to 'unset' command.  'unset ?' for help.\n");
  1030.     return 0;
  1031.     }
  1032.     if (isprefix(argv[1], "?") || isprefix(argv[1], "help")) {
  1033.     for (ct = Setlist; ct->name; ct++)
  1034.         printf("%-15s %s\n", ct->name, ct->help);
  1035.     printf("\n");
  1036.     settogglehelp(0);
  1037.     printf("%-15s %s\n", "?", "display help information");
  1038.     return 0;
  1039.     }
  1040.  
  1041.     argc--;
  1042.     argv++;
  1043.     while (argc--) {
  1044.     name = *argv++;
  1045.     ct = getset(name);
  1046.     if (ct == 0) {
  1047.         c = GETTOGGLE(name);
  1048.         if (c == 0) {
  1049.         fprintf(stderr, "'%s': unknown argument ('unset ?' for help).\n",
  1050.             name);
  1051.         return 0;
  1052.         } else if (Ambiguous(c)) {
  1053.         fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n",
  1054.             name);
  1055.         return 0;
  1056.         }
  1057.         if (c->variable) {
  1058.         *c->variable = 0;
  1059.         if (c->actionexplanation) {
  1060.             printf("%s %s.\n", *c->variable? "Will" : "Won't",
  1061.                             c->actionexplanation);
  1062.         }
  1063.         }
  1064.         if (c->handler)
  1065.         (*c->handler)(0);
  1066.     } else if (Ambiguous(ct)) {
  1067.         fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n",
  1068.             name);
  1069.         return 0;
  1070.     } else if (ct->handler) {
  1071.         (*ct->handler)(0);
  1072.         printf("%s reset to \"%s\".\n", ct->name, (char *)ct->charp);
  1073.     } else {
  1074.         *(ct->charp) = _POSIX_VDISABLE;
  1075.         printf("%s character is '%s'.\n", ct->name, control(*(ct->charp)));
  1076.     }
  1077.     }
  1078.     return 1;
  1079. }
  1080.  
  1081. /*
  1082.  * The following are the data structures and routines for the
  1083.  * 'mode' command.
  1084.  */
  1085. #ifdef    KLUDGELINEMODE
  1086. extern int kludgelinemode;
  1087.  
  1088.     static int
  1089. dokludgemode()
  1090. {
  1091.     kludgelinemode = 1;
  1092.     send_wont(TELOPT_LINEMODE, 1);
  1093.     send_dont(TELOPT_SGA, 1);
  1094.     send_dont(TELOPT_ECHO, 1);
  1095. }
  1096. #endif
  1097.  
  1098.     static int
  1099. dolinemode()
  1100. {
  1101. #ifdef    KLUDGELINEMODE
  1102.     if (kludgelinemode)
  1103.     send_dont(TELOPT_SGA, 1);
  1104. #endif
  1105.     send_will(TELOPT_LINEMODE, 1);
  1106.     send_dont(TELOPT_ECHO, 1);
  1107.     return 1;
  1108. }
  1109.  
  1110.     static int
  1111. docharmode()
  1112. {
  1113. #ifdef    KLUDGELINEMODE
  1114.     if (kludgelinemode)
  1115.     send_do(TELOPT_SGA, 1);
  1116.     else
  1117. #endif
  1118.     send_wont(TELOPT_LINEMODE, 1);
  1119.     send_do(TELOPT_ECHO, 1);
  1120.     return 1;
  1121. }
  1122.  
  1123.     static int
  1124. dolmmode(bit, on)
  1125.     int bit, on;
  1126. {
  1127.     unsigned char c;
  1128.     extern int linemode;
  1129.  
  1130.     if (my_want_state_is_wont(TELOPT_LINEMODE)) {
  1131.     printf("?Need to have LINEMODE option enabled first.\n");
  1132.     printf("'mode ?' for help.\n");
  1133.     return 0;
  1134.     }
  1135.  
  1136.     if (on)
  1137.     c = (linemode | bit);
  1138.     else
  1139.     c = (linemode & ~bit);
  1140.     lm_mode(&c, 1, 1);
  1141.     return 1;
  1142. }
  1143.  
  1144.     int
  1145. setmode(bit)
  1146. {
  1147.     return dolmmode(bit, 1);
  1148. }
  1149.  
  1150.     int
  1151. clearmode(bit)
  1152. {
  1153.     return dolmmode(bit, 0);
  1154. }
  1155.  
  1156. struct modelist {
  1157.     char    *name;        /* command name */
  1158.     char    *help;        /* help string */
  1159.     int    (*handler)();    /* routine which executes command */
  1160.     int    needconnect;    /* Do we need to be connected to execute? */
  1161.     int    arg1;
  1162. };
  1163.  
  1164. extern int modehelp();
  1165.  
  1166. static struct modelist ModeList[] = {
  1167.     { "character", "Disable LINEMODE option",    docharmode, 1 },
  1168. #ifdef    KLUDGELINEMODE
  1169.     { "",    "(or disable obsolete line-by-line mode)", 0 },
  1170. #endif
  1171.     { "line",    "Enable LINEMODE option",    dolinemode, 1 },
  1172. #ifdef    KLUDGELINEMODE
  1173.     { "",    "(or enable obsolete line-by-line mode)", 0 },
  1174. #endif
  1175.     { "", "", 0 },
  1176.     { "",    "These require the LINEMODE option to be enabled", 0 },
  1177.     { "isig",    "Enable signal trapping",    setmode, 1, MODE_TRAPSIG },
  1178.     { "+isig",    0,                setmode, 1, MODE_TRAPSIG },
  1179.     { "-isig",    "Disable signal trapping",    clearmode, 1, MODE_TRAPSIG },
  1180.     { "edit",    "Enable character editing",    setmode, 1, MODE_EDIT },
  1181.     { "+edit",    0,                setmode, 1, MODE_EDIT },
  1182.     { "-edit",    "Disable character editing",    clearmode, 1, MODE_EDIT },
  1183.     { "softtabs", "Enable tab expansion",    setmode, 1, MODE_SOFT_TAB },
  1184.     { "+softtabs", 0,                setmode, 1, MODE_SOFT_TAB },
  1185.     { "-softtabs", "Disable character editing",    clearmode, 1, MODE_SOFT_TAB },
  1186.     { "litecho", "Enable literal character echo", setmode, 1, MODE_LIT_ECHO },
  1187.     { "+litecho", 0,                setmode, 1, MODE_LIT_ECHO },
  1188.     { "-litecho", "Disable literal character echo", clearmode, 1, MODE_LIT_ECHO },
  1189.     { "help",    0,                modehelp, 0 },
  1190. #ifdef    KLUDGELINEMODE
  1191.     { "kludgeline", 0,                dokludgemode, 1 },
  1192. #endif
  1193.     { "", "", 0 },
  1194.     { "?",    "Print help information",    modehelp, 0 },
  1195.     { 0 },
  1196. };
  1197.  
  1198.  
  1199.     int
  1200. modehelp()
  1201. {
  1202.     struct modelist *mt;
  1203.  
  1204.     printf("format is:  'mode Mode', where 'Mode' is one of:\n\n");
  1205.     for (mt = ModeList; mt->name; mt++) {
  1206.     if (mt->help) {
  1207.         if (*mt->help)
  1208.         printf("%-15s %s\n", mt->name, mt->help);
  1209.         else
  1210.         printf("\n");
  1211.     }
  1212.     }
  1213.     return 0;
  1214. }
  1215.  
  1216. #define    GETMODECMD(name) (struct modelist *) \
  1217.         genget(name, (char **) ModeList, sizeof(struct modelist))
  1218.  
  1219.     static int
  1220. modecmd(argc, argv)
  1221.     int  argc;
  1222.     char *argv[];
  1223. {
  1224.     struct modelist *mt;
  1225.  
  1226.     if (argc != 2) {
  1227.     printf("'mode' command requires an argument\n");
  1228.     printf("'mode ?' for help.\n");
  1229.     } else if ((mt = GETMODECMD(argv[1])) == 0) {
  1230.     fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]);
  1231.     } else if (Ambiguous(mt)) {
  1232.     fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]);
  1233.     } else if (mt->needconnect && !connected) {
  1234.     printf("?Need to be connected first.\n");
  1235.     printf("'mode ?' for help.\n");
  1236.     } else if (mt->handler) {
  1237.     return (*mt->handler)(mt->arg1);
  1238.     }
  1239.     return 0;
  1240. }
  1241.  
  1242. /*
  1243.  * The following data structures and routines implement the
  1244.  * "display" command.
  1245.  */
  1246.  
  1247.     static int
  1248. display(argc, argv)
  1249.     int  argc;
  1250.     char *argv[];
  1251. {
  1252.     struct togglelist *tl;
  1253.     struct setlist *sl;
  1254.  
  1255. #define    dotog(tl)    if (tl->variable && tl->actionexplanation) { \
  1256.                 if (*tl->variable) { \
  1257.                 printf("will"); \
  1258.                 } else { \
  1259.                 printf("won't"); \
  1260.                 } \
  1261.                 printf(" %s.\n", tl->actionexplanation); \
  1262.             }
  1263.  
  1264. #define    doset(sl)   if (sl->name && *sl->name != ' ') { \
  1265.             if (sl->handler == 0) \
  1266.                 printf("%-15s [%s]\n", sl->name, control(*sl->charp)); \
  1267.             else \
  1268.                 printf("%-15s \"%s\"\n", sl->name, (char *)sl->charp); \
  1269.             }
  1270.  
  1271.     if (argc == 1) {
  1272.     for (tl = Togglelist; tl->name; tl++) {
  1273.         dotog(tl);
  1274.     }
  1275.     printf("\n");
  1276.     for (sl = Setlist; sl->name; sl++) {
  1277.         doset(sl);
  1278.     }
  1279.     } else {
  1280.     int i;
  1281.  
  1282.     for (i = 1; i < argc; i++) {
  1283.         sl = getset(argv[i]);
  1284.         tl = GETTOGGLE(argv[i]);
  1285.         if (Ambiguous(sl) || Ambiguous(tl)) {
  1286.         printf("?Ambiguous argument '%s'.\n", argv[i]);
  1287.         return 0;
  1288.         } else if (!sl && !tl) {
  1289.         printf("?Unknown argument '%s'.\n", argv[i]);
  1290.         return 0;
  1291.         } else {
  1292.         if (tl) {
  1293.             dotog(tl);
  1294.         }
  1295.         if (sl) {
  1296.             doset(sl);
  1297.         }
  1298.         }
  1299.     }
  1300.     }
  1301. /*@*/optionstatus();
  1302. #ifdef    ENCRYPTION
  1303.     EncryptStatus();
  1304. #endif    /* ENCRYPTION */
  1305.     return 1;
  1306. #undef    doset
  1307. #undef    dotog
  1308. }
  1309.  
  1310. /*
  1311.  * The following are the data structures, and many of the routines,
  1312.  * relating to command processing.
  1313.  */
  1314.  
  1315. /*
  1316.  * Set the escape character.
  1317.  */
  1318.     static int
  1319. setescape(argc, argv)
  1320.     int argc;
  1321.     char *argv[];
  1322. {
  1323.     register char *arg;
  1324.     char buf[50];
  1325.  
  1326.     printf(
  1327.         "Deprecated usage - please use 'set escape%s%s' in the future.\n",
  1328.                 (argc > 2)? " ":"", (argc > 2)? argv[1]: "");
  1329.     if (argc > 2)
  1330.         arg = argv[1];
  1331.     else {
  1332.         printf("new escape character: ");
  1333.         (void) fgets(buf, sizeof(buf), stdin);
  1334.         arg = buf;
  1335.     }
  1336.     if (arg[0] != '\0')
  1337.         escape = arg[0];
  1338.     if (!In3270) {
  1339.         printf("Escape character is '%s'.\n", control(escape));
  1340.     }
  1341.     (void) fflush(stdout);
  1342.     return 1;
  1343. }
  1344.  
  1345.     /*VARARGS*/
  1346.     static int
  1347. togcrmod()
  1348. {
  1349.     crmod = !crmod;
  1350.     printf("Deprecated usage - please use 'toggle crmod' in the future.\n");
  1351.     printf("%s map carriage return on output.\n", crmod ? "Will" : "Won't");
  1352.     (void) fflush(stdout);
  1353.     return 1;
  1354. }
  1355.  
  1356.     /*VARARGS*/
  1357.     int
  1358. suspend()
  1359. {
  1360. #ifdef    SIGTSTP
  1361.     setcommandmode();
  1362.     {
  1363.     long oldrows, oldcols, newrows, newcols, err;
  1364.  
  1365.     err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0;
  1366.     (void) kill(0, SIGTSTP);
  1367.     /*
  1368.      * If we didn't get the window size before the SUSPEND, but we
  1369.      * can get them now (?), then send the NAWS to make sure that
  1370.      * we are set up for the right window size.
  1371.      */
  1372.     if (TerminalWindowSize(&newrows, &newcols) && connected &&
  1373.         (err || ((oldrows != newrows) || (oldcols != newcols)))) {
  1374.         sendnaws();
  1375.     }
  1376.     }
  1377.     /* reget parameters in case they were changed */
  1378.     TerminalSaveState();
  1379.     setconnmode(0);
  1380. #else
  1381.     printf("Suspend is not supported.  Try the '!' command instead\n");
  1382. #endif
  1383.     return 1;
  1384. }
  1385.  
  1386. #if    !defined(TN3270)
  1387.     /*ARGSUSED*/
  1388.     int
  1389. shell(argc, argv)
  1390.     int argc;
  1391.     char *argv[];
  1392. {
  1393. #ifdef __EMX__
  1394.     fprintf(stderr,"This port does not support shells.\n");
  1395.     return 1;
  1396. #else
  1397.     long oldrows, oldcols, newrows, newcols, err;
  1398.  
  1399.     setcommandmode();
  1400.  
  1401.     err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0;
  1402.     switch(vfork()) {
  1403.     case -1:
  1404.     perror("Fork failed\n");
  1405.     break;
  1406.  
  1407.     case 0:
  1408.     {
  1409.         /*
  1410.          * Fire up the shell in the child.
  1411.          */
  1412.         register char *shellp, *shellname;
  1413.         extern char *strrchr();
  1414.  
  1415.         shellp = getenv("SHELL");
  1416.         if (shellp == NULL)
  1417.         shellp = "/bin/sh";
  1418.         if ((shellname = strrchr(shellp, '/')) == 0)
  1419.         shellname = shellp;
  1420.         else
  1421.         shellname++;
  1422.         if (argc > 1)
  1423.         execl(shellp, shellname, "-c", &saveline[1], 0);
  1424.         else
  1425.         execl(shellp, shellname, 0);
  1426.         perror("Execl");
  1427.         _exit(1);
  1428.     }
  1429.     default:
  1430.         (void)wait((int *)0);    /* Wait for the shell to complete */
  1431.  
  1432.         if (TerminalWindowSize(&newrows, &newcols) && connected &&
  1433.         (err || ((oldrows != newrows) || (oldcols != newcols)))) {
  1434.             sendnaws();
  1435.         }
  1436.         break;
  1437.     }
  1438.     return 1;
  1439. #endif /* __EMX__ */
  1440. }
  1441. #else    /* !defined(TN3270) */
  1442. extern int shell();
  1443. #endif    /* !defined(TN3270) */
  1444.  
  1445.     /*VARARGS*/
  1446.     static
  1447. bye(argc, argv)
  1448.     int  argc;        /* Number of arguments */
  1449.     char *argv[];    /* arguments */
  1450. {
  1451.     extern int resettermname;
  1452.  
  1453.     if (connected) {
  1454.     (void) shutdown(net, 2);
  1455.     printf("Connection closed.\n");
  1456.     (void) NetClose(net);
  1457.     connected = 0;
  1458.     resettermname = 1;
  1459. #if    defined(AUTHENTICATION) || defined(ENCRYPTION)
  1460.     auth_encrypt_connect(connected);
  1461. #endif    /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
  1462.     /* reset options */
  1463.     tninit();
  1464. #if    defined(TN3270)
  1465.     SetIn3270();        /* Get out of 3270 mode */
  1466. #endif    /* defined(TN3270) */
  1467.     }
  1468.     if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) {
  1469.     longjmp(toplevel, 1);
  1470.     /* NOTREACHED */
  1471.     }
  1472.     return 1;            /* Keep lint, etc., happy */
  1473. }
  1474.  
  1475. /*VARARGS*/
  1476. quit()
  1477. {
  1478.     (void) call(bye, "bye", "fromquit", 0);
  1479.     Exit(0);
  1480.     /*NOTREACHED*/
  1481. }
  1482.  
  1483. /*VARARGS*/
  1484.     int
  1485. logout()
  1486. {
  1487.     send_do(TELOPT_LOGOUT, 1);
  1488.     (void) netflush();
  1489.     return 1;
  1490. }
  1491.  
  1492.  
  1493. /*
  1494.  * The SLC command.
  1495.  */
  1496.  
  1497. struct slclist {
  1498.     char    *name;
  1499.     char    *help;
  1500.     void    (*handler)();
  1501.     int    arg;
  1502. };
  1503.  
  1504. static void slc_help();
  1505.  
  1506. struct slclist SlcList[] = {
  1507.     { "export",    "Use local special character definitions",
  1508.                         slc_mode_export,    0 },
  1509.     { "import",    "Use remote special character definitions",
  1510.                         slc_mode_import,    1 },
  1511.     { "check",    "Verify remote special character definitions",
  1512.                         slc_mode_import,    0 },
  1513.     { "help",    0,                slc_help,        0 },
  1514.     { "?",    "Print help information",    slc_help,        0 },
  1515.     { 0 },
  1516. };
  1517.  
  1518.     static void
  1519. slc_help()
  1520. {
  1521.     struct slclist *c;
  1522.  
  1523.     for (c = SlcList; c->name; c++) {
  1524.     if (c->help) {
  1525.         if (*c->help)
  1526.         printf("%-15s %s\n", c->name, c->help);
  1527.         else
  1528.         printf("\n");
  1529.     }
  1530.     }
  1531. }
  1532.  
  1533.     static struct slclist *
  1534. getslc(name)
  1535.     char *name;
  1536. {
  1537.     return (struct slclist *)
  1538.         genget(name, (char **) SlcList, sizeof(struct slclist));
  1539. }
  1540.  
  1541.     static
  1542. slccmd(argc, argv)
  1543.     int  argc;
  1544.     char *argv[];
  1545. {
  1546.     struct slclist *c;
  1547.  
  1548.     if (argc != 2) {
  1549.     fprintf(stderr,
  1550.         "Need an argument to 'slc' command.  'slc ?' for help.\n");
  1551.     return 0;
  1552.     }
  1553.     c = getslc(argv[1]);
  1554.     if (c == 0) {
  1555.         fprintf(stderr, "'%s': unknown argument ('slc ?' for help).\n",
  1556.                     argv[1]);
  1557.         return 0;
  1558.     }
  1559.     if (Ambiguous(c)) {
  1560.         fprintf(stderr, "'%s': ambiguous argument ('slc ?' for help).\n",
  1561.                     argv[1]);
  1562.         return 0;
  1563.     }
  1564.     (*c->handler)(c->arg);
  1565.     slcstate();
  1566.     return 1;
  1567. }
  1568.  
  1569. /*
  1570.  * The ENVIRON command.
  1571.  */
  1572.  
  1573. struct envlist {
  1574.     char    *name;
  1575.     char    *help;
  1576.     void    (*handler)();
  1577.     int    narg;
  1578. };
  1579.  
  1580. extern struct env_lst *
  1581.     env_define P((unsigned char *, unsigned char *));
  1582. extern void
  1583.     env_undefine P((unsigned char *)),
  1584.     env_export P((unsigned char *)),
  1585.     env_unexport P((unsigned char *)),
  1586.     env_send P((unsigned char *)),
  1587. #if defined(OLD_ENVIRON) && defined(ENV_HACK)
  1588.     env_varval P((unsigned char *)),
  1589. #endif
  1590.     env_list P((void));
  1591. static void
  1592.     env_help P((void));
  1593.  
  1594. struct envlist EnvList[] = {
  1595.     { "define",    "Define an environment variable",
  1596.                         (void (*)())env_define,    2 },
  1597.     { "undefine", "Undefine an environment variable",
  1598.                         env_undefine,    1 },
  1599.     { "export",    "Mark an environment variable for automatic export",
  1600.                         env_export,    1 },
  1601.     { "unexport", "Don't mark an environment variable for automatic export",
  1602.                         env_unexport,    1 },
  1603.     { "send",    "Send an environment variable", env_send,    1 },
  1604.     { "list",    "List the current environment variables",
  1605.                         env_list,    0 },
  1606. #if defined(OLD_ENVIRON) && defined(ENV_HACK)
  1607.     { "varval", "Reverse VAR and VALUE (auto, right, wrong, status)",
  1608.                         env_varval,    1 },
  1609. #endif
  1610.     { "help",    0,                env_help,        0 },
  1611.     { "?",    "Print help information",    env_help,        0 },
  1612.     { 0 },
  1613. };
  1614.  
  1615.     static void
  1616. env_help()
  1617. {
  1618.     struct envlist *c;
  1619.  
  1620.     for (c = EnvList; c->name; c++) {
  1621.     if (c->help) {
  1622.         if (*c->help)
  1623.         printf("%-15s %s\n", c->name, c->help);
  1624.         else
  1625.         printf("\n");
  1626.     }
  1627.     }
  1628. }
  1629.  
  1630.     static struct envlist *
  1631. getenvcmd(name)
  1632.     char *name;
  1633. {
  1634.     return (struct envlist *)
  1635.         genget(name, (char **) EnvList, sizeof(struct envlist));
  1636. }
  1637.  
  1638. env_cmd(argc, argv)
  1639.     int  argc;
  1640.     char *argv[];
  1641. {
  1642.     struct envlist *c;
  1643.  
  1644.     if (argc < 2) {
  1645.     fprintf(stderr,
  1646.         "Need an argument to 'environ' command.  'environ ?' for help.\n");
  1647.     return 0;
  1648.     }
  1649.     c = getenvcmd(argv[1]);
  1650.     if (c == 0) {
  1651.         fprintf(stderr, "'%s': unknown argument ('environ ?' for help).\n",
  1652.                     argv[1]);
  1653.         return 0;
  1654.     }
  1655.     if (Ambiguous(c)) {
  1656.         fprintf(stderr, "'%s': ambiguous argument ('environ ?' for help).\n",
  1657.                     argv[1]);
  1658.         return 0;
  1659.     }
  1660.     if (c->narg + 2 != argc) {
  1661.     fprintf(stderr,
  1662.         "Need %s%d argument%s to 'environ %s' command.  'environ ?' for help.\n",
  1663.         c->narg < argc + 2 ? "only " : "",
  1664.         c->narg, c->narg == 1 ? "" : "s", c->name);
  1665.     return 0;
  1666.     }
  1667.     (*c->handler)(argv[2], argv[3]);
  1668.     return 1;
  1669. }
  1670.  
  1671. struct env_lst {
  1672.     struct env_lst *next;    /* pointer to next structure */
  1673.     struct env_lst *prev;    /* pointer to previous structure */
  1674.     unsigned char *var;    /* pointer to variable name */
  1675.     unsigned char *value;    /* pointer to variable value */
  1676.     int export;        /* 1 -> export with default list of variables */
  1677.     int welldefined;    /* A well defined variable */
  1678. };
  1679.  
  1680. struct env_lst envlisthead;
  1681.  
  1682.     struct env_lst *
  1683. env_find(var)
  1684.     unsigned char *var;
  1685. {
  1686.     register struct env_lst *ep;
  1687.  
  1688.     for (ep = envlisthead.next; ep; ep = ep->next) {
  1689.         if (strcmp((char *)ep->var, (char *)var) == 0)
  1690.             return(ep);
  1691.     }
  1692.     return(NULL);
  1693. }
  1694.  
  1695.     void
  1696. env_init()
  1697. {
  1698.     extern char **environ;
  1699.     register char **epp, *cp;
  1700.     register struct env_lst *ep;
  1701.     extern char *strchr();
  1702.  
  1703.     for (epp = environ; *epp; epp++) {
  1704.         if (cp = strchr(*epp, '=')) {
  1705.             *cp = '\0';
  1706.             ep = env_define((unsigned char *)*epp,
  1707.                     (unsigned char *)cp+1);
  1708.             ep->export = 0;
  1709.             *cp = '=';
  1710.         }
  1711.     }
  1712.     /*
  1713.      * Special case for DISPLAY variable.  If it is ":0.0" or
  1714.      * "unix:0.0", we have to get rid of "unix" and insert our
  1715.      * hostname.
  1716.      */
  1717.     if ((ep = env_find("DISPLAY"))
  1718.         && ((*ep->value == ':')
  1719.             || (strncmp((char *)ep->value, "unix:", 5) == 0))) {
  1720.         extern char *localhost ();
  1721.         char *hostname = localhost ();
  1722.         char *cp2 = strchr((char *)ep->value, ':');
  1723.  
  1724.         cp = (char *)malloc(strlen(hostname) + strlen(cp2) + 1);
  1725.         sprintf((char *)cp, "%s%s", localhost, cp2);
  1726.  
  1727.         free(ep->value);
  1728.         ep->value = (unsigned char *)cp;
  1729.  
  1730.         free (hostname);
  1731.     }
  1732.     /*
  1733.      * If USER is not defined, but LOGNAME is, then add
  1734.      * USER with the value from LOGNAME.  By default, we
  1735.      * don't export the USER variable.
  1736.      */
  1737.     if ((env_find("USER") == NULL) && (ep = env_find("LOGNAME"))) {
  1738.         env_define((unsigned char *)"USER", ep->value);
  1739.         env_unexport((unsigned char *)"USER");
  1740.     }
  1741.     env_export((unsigned char *)"DISPLAY");
  1742.     env_export((unsigned char *)"PRINTER");
  1743. }
  1744.  
  1745.     struct env_lst *
  1746. env_define(var, value)
  1747.     unsigned char *var, *value;
  1748. {
  1749.     register struct env_lst *ep;
  1750.  
  1751.     if (ep = env_find(var)) {
  1752.         if (ep->var)
  1753.             free(ep->var);
  1754.         if (ep->value)
  1755.             free(ep->value);
  1756.     } else {
  1757.         ep = (struct env_lst *)malloc(sizeof(struct env_lst));
  1758.         ep->next = envlisthead.next;
  1759.         envlisthead.next = ep;
  1760.         ep->prev = &envlisthead;
  1761.         if (ep->next)
  1762.             ep->next->prev = ep;
  1763.     }
  1764.     ep->welldefined = opt_welldefined(var);
  1765.     ep->export = 1;
  1766.     ep->var = (unsigned char *)strdup((char *)var);
  1767.     ep->value = (unsigned char *)strdup((char *)value);
  1768.     return(ep);
  1769. }
  1770.  
  1771.     void
  1772. env_undefine(var)
  1773.     unsigned char *var;
  1774. {
  1775.     register struct env_lst *ep;
  1776.  
  1777.     if (ep = env_find(var)) {
  1778.         ep->prev->next = ep->next;
  1779.         if (ep->next)
  1780.             ep->next->prev = ep->prev;
  1781.         if (ep->var)
  1782.             free(ep->var);
  1783.         if (ep->value)
  1784.             free(ep->value);
  1785.         free(ep);
  1786.     }
  1787. }
  1788.  
  1789.     void
  1790. env_export(var)
  1791.     unsigned char *var;
  1792. {
  1793.     register struct env_lst *ep;
  1794.  
  1795.     if (ep = env_find(var))
  1796.         ep->export = 1;
  1797. }
  1798.  
  1799.     void
  1800. env_unexport(var)
  1801.     unsigned char *var;
  1802. {
  1803.     register struct env_lst *ep;
  1804.  
  1805.     if (ep = env_find(var))
  1806.         ep->export = 0;
  1807. }
  1808.  
  1809.     void
  1810. env_send(var)
  1811.     unsigned char *var;
  1812. {
  1813.     register struct env_lst *ep;
  1814.  
  1815.         if (my_state_is_wont(TELOPT_NEW_ENVIRON)
  1816. #ifdef    OLD_ENVIRON
  1817.         && my_state_is_wont(TELOPT_OLD_ENVIRON)
  1818. #endif
  1819.         ) {
  1820.         fprintf(stderr,
  1821.             "Cannot send '%s': Telnet ENVIRON option not enabled\n",
  1822.                                     var);
  1823.         return;
  1824.     }
  1825.     ep = env_find(var);
  1826.     if (ep == 0) {
  1827.         fprintf(stderr, "Cannot send '%s': variable not defined\n",
  1828.                                     var);
  1829.         return;
  1830.     }
  1831.     env_opt_start_info();
  1832.     env_opt_add(ep->var);
  1833.     env_opt_end(0);
  1834. }
  1835.  
  1836.     void
  1837. env_list()
  1838. {
  1839.     register struct env_lst *ep;
  1840.  
  1841.     for (ep = envlisthead.next; ep; ep = ep->next) {
  1842.         printf("%c %-20s %s\n", ep->export ? '*' : ' ',
  1843.                     ep->var, ep->value);
  1844.     }
  1845. }
  1846.  
  1847.     unsigned char *
  1848. env_default(init, welldefined)
  1849.     int init;
  1850. {
  1851.     static struct env_lst *nep = NULL;
  1852.  
  1853.     if (init) {
  1854.         nep = &envlisthead;
  1855.         return;
  1856.     }
  1857.     if (nep) {
  1858.         while (nep = nep->next) {
  1859.             if (nep->export && (nep->welldefined == welldefined))
  1860.                 return(nep->var);
  1861.         }
  1862.     }
  1863.     return(NULL);
  1864. }
  1865.  
  1866.     unsigned char *
  1867. env_getvalue(var)
  1868.     unsigned char *var;
  1869. {
  1870.     register struct env_lst *ep;
  1871.  
  1872.     if (ep = env_find(var))
  1873.         return(ep->value);
  1874.     return(NULL);
  1875. }
  1876.  
  1877. #if defined(OLD_ENVIRON) && defined(ENV_HACK)
  1878.     void
  1879. env_varval(what)
  1880.     unsigned char *what;
  1881. {
  1882.     extern int old_env_var, old_env_value, env_auto;
  1883.     int len = strlen((char *)what);
  1884.  
  1885.     if (len == 0)
  1886.         goto unknown;
  1887.  
  1888.     if (strncasecmp((char *)what, "status", len) == 0) {
  1889.         if (env_auto)
  1890.             printf("%s%s", "VAR and VALUE are/will be ",
  1891.                     "determined automatically\n");
  1892.         if (old_env_var == OLD_ENV_VAR)
  1893.             printf("VAR and VALUE set to correct definitions\n");
  1894.         else
  1895.             printf("VAR and VALUE definitions are reversed\n");
  1896.     } else if (strncasecmp((char *)what, "auto", len) == 0) {
  1897.         env_auto = 1;
  1898.         old_env_var = OLD_ENV_VALUE;
  1899.         old_env_value = OLD_ENV_VAR;
  1900.     } else if (strncasecmp((char *)what, "right", len) == 0) {
  1901.         env_auto = 0;
  1902.         old_env_var = OLD_ENV_VAR;
  1903.         old_env_value = OLD_ENV_VALUE;
  1904.     } else if (strncasecmp((char *)what, "wrong", len) == 0) {
  1905.         env_auto = 0;
  1906.         old_env_var = OLD_ENV_VALUE;
  1907.         old_env_value = OLD_ENV_VAR;
  1908.     } else {
  1909. unknown:
  1910.         printf("Unknown \"varval\" command. (\"auto\", \"right\", \"wrong\", \"status\")\n");
  1911.     }
  1912. }
  1913. #endif
  1914.  
  1915. #if    defined(AUTHENTICATION)
  1916. /*
  1917.  * The AUTHENTICATE command.
  1918.  */
  1919.  
  1920. struct authlist {
  1921.     char    *name;
  1922.     char    *help;
  1923.     int    (*handler)();
  1924.     int    narg;
  1925. };
  1926.  
  1927. extern int
  1928.     auth_enable P((char *)),
  1929.     auth_disable P((char *)),
  1930.     auth_status P((void));
  1931. static int
  1932.     auth_help P((void));
  1933.  
  1934. struct authlist AuthList[] = {
  1935.     { "status",    "Display current status of authentication information",
  1936.                         auth_status,    0 },
  1937.     { "disable", "Disable an authentication type ('auth disable ?' for more)",
  1938.                         auth_disable,    1 },
  1939.     { "enable", "Enable an authentication type ('auth enable ?' for more)",
  1940.                         auth_enable,    1 },
  1941.     { "help",    0,                auth_help,        0 },
  1942.     { "?",    "Print help information",    auth_help,        0 },
  1943.     { 0 },
  1944. };
  1945.  
  1946.     static int
  1947. auth_help()
  1948. {
  1949.     struct authlist *c;
  1950.  
  1951.     for (c = AuthList; c->name; c++) {
  1952.     if (c->help) {
  1953.         if (*c->help)
  1954.         printf("%-15s %s\n", c->name, c->help);
  1955.         else
  1956.         printf("\n");
  1957.     }
  1958.     }
  1959.     return 0;
  1960. }
  1961.  
  1962. auth_cmd(argc, argv)
  1963.     int  argc;
  1964.     char *argv[];
  1965. {
  1966.     struct authlist *c;
  1967.  
  1968.     if (argc < 2) {
  1969.     fprintf(stderr,
  1970.         "Need an argument to 'auth' command.  'auth ?' for help.\n");
  1971.     return 0;
  1972.     }
  1973.  
  1974.     c = (struct authlist *)
  1975.         genget(argv[1], (char **) AuthList, sizeof(struct authlist));
  1976.     if (c == 0) {
  1977.         fprintf(stderr, "'%s': unknown argument ('auth ?' for help).\n",
  1978.                     argv[1]);
  1979.         return 0;
  1980.     }
  1981.     if (Ambiguous(c)) {
  1982.         fprintf(stderr, "'%s': ambiguous argument ('auth ?' for help).\n",
  1983.                     argv[1]);
  1984.         return 0;
  1985.     }
  1986.     if (c->narg + 2 != argc) {
  1987.     fprintf(stderr,
  1988.         "Need %s%d argument%s to 'auth %s' command.  'auth ?' for help.\n",
  1989.         c->narg < argc + 2 ? "only " : "",
  1990.         c->narg, c->narg == 1 ? "" : "s", c->name);
  1991.     return 0;
  1992.     }
  1993.     return((*c->handler)(argv[2], argv[3]));
  1994. }
  1995. #endif
  1996.  
  1997. #ifdef    ENCRYPTION
  1998. /*
  1999.  * The ENCRYPT command.
  2000.  */
  2001.  
  2002. struct encryptlist {
  2003.     char    *name;
  2004.     char    *help;
  2005.     int    (*handler)();
  2006.     int    needconnect;
  2007.     int    minarg;
  2008.     int    maxarg;
  2009. };
  2010.  
  2011. extern int
  2012.     EncryptEnable P((char *, char *)),
  2013.     EncryptDisable P((char *, char *)),
  2014.     EncryptType P((char *, char *)),
  2015.     EncryptStart P((char *)),
  2016.     EncryptStartInput P((void)),
  2017.     EncryptStartOutput P((void)),
  2018.     EncryptStop P((char *)),
  2019.     EncryptStopInput P((void)),
  2020.     EncryptStopOutput P((void)),
  2021.     EncryptStatus P((void));
  2022. static int
  2023.     EncryptHelp P((void));
  2024.  
  2025. struct encryptlist EncryptList[] = {
  2026.     { "enable", "Enable encryption. ('encrypt enable ?' for more)",
  2027.                         EncryptEnable, 1, 1, 2 },
  2028.     { "disable", "Disable encryption. ('encrypt enable ?' for more)",
  2029.                         EncryptDisable, 0, 1, 2 },
  2030.     { "type", "Set encryption type. ('encrypt type ?' for more)",
  2031.                         EncryptType, 0, 1, 1 },
  2032.     { "start", "Start encryption. ('encrypt start ?' for more)",
  2033.                         EncryptStart, 1, 0, 1 },
  2034.     { "stop", "Stop encryption. ('encrypt stop ?' for more)",
  2035.                         EncryptStop, 1, 0, 1 },
  2036.     { "input", "Start encrypting the input stream",
  2037.                         EncryptStartInput, 1, 0, 0 },
  2038.     { "-input", "Stop encrypting the input stream",
  2039.                         EncryptStopInput, 1, 0, 0 },
  2040.     { "output", "Start encrypting the output stream",
  2041.                         EncryptStartOutput, 1, 0, 0 },
  2042.     { "-output", "Stop encrypting the output stream",
  2043.                         EncryptStopOutput, 1, 0, 0 },
  2044.  
  2045.     { "status",    "Display current status of authentication information",
  2046.                         EncryptStatus,    0, 0, 0 },
  2047.     { "help",    0,                EncryptHelp,    0, 0, 0 },
  2048.     { "?",    "Print help information",    EncryptHelp,    0, 0, 0 },
  2049.     { 0 },
  2050. };
  2051.  
  2052.     static int
  2053. EncryptHelp()
  2054. {
  2055.     struct encryptlist *c;
  2056.  
  2057.     for (c = EncryptList; c->name; c++) {
  2058.     if (c->help) {
  2059.         if (*c->help)
  2060.         printf("%-15s %s\n", c->name, c->help);
  2061.         else
  2062.         printf("\n");
  2063.     }
  2064.     }
  2065.     return 0;
  2066. }
  2067.  
  2068. encrypt_cmd(argc, argv)
  2069.     int  argc;
  2070.     char *argv[];
  2071. {
  2072.     struct encryptlist *c;
  2073.  
  2074.     if (argc < 2) {
  2075.     fprintf(stderr,
  2076.         "Need an argument to 'encrypt' command.  'encrypt ?' for help.\n");
  2077.     return 0;
  2078.     }
  2079.  
  2080.     c = (struct encryptlist *)
  2081.         genget(argv[1], (char **) EncryptList, sizeof(struct encryptlist));
  2082.     if (c == 0) {
  2083.         fprintf(stderr, "'%s': unknown argument ('encrypt ?' for help).\n",
  2084.                     argv[1]);
  2085.         return 0;
  2086.     }
  2087.     if (Ambiguous(c)) {
  2088.         fprintf(stderr, "'%s': ambiguous argument ('encrypt ?' for help).\n",
  2089.                     argv[1]);
  2090.         return 0;
  2091.     }
  2092.     argc -= 2;
  2093.     if (argc < c->minarg || argc > c->maxarg) {
  2094.     if (c->minarg == c->maxarg) {
  2095.         fprintf(stderr, "Need %s%d argument%s ",
  2096.         c->minarg < argc ? "only " : "", c->minarg,
  2097.         c->minarg == 1 ? "" : "s");
  2098.     } else {
  2099.         fprintf(stderr, "Need %s%d-%d arguments ",
  2100.         c->maxarg < argc ? "only " : "", c->minarg, c->maxarg);
  2101.     }
  2102.     fprintf(stderr, "to 'encrypt %s' command.  'encrypt ?' for help.\n",
  2103.         c->name);
  2104.     return 0;
  2105.     }
  2106.     if (c->needconnect && !connected) {
  2107.     if (!(argc && (isprefix(argv[2], "help") || isprefix(argv[2], "?")))) {
  2108.         printf("?Need to be connected first.\n");
  2109.         return 0;
  2110.     }
  2111.     }
  2112.     return ((*c->handler)(argc > 0 ? argv[2] : 0,
  2113.             argc > 1 ? argv[3] : 0,
  2114.             argc > 2 ? argv[4] : 0));
  2115. }
  2116. #endif    /* ENCRYPTION */
  2117.  
  2118. #if    defined(unix) && defined(TN3270)
  2119.     static void
  2120. filestuff(fd)
  2121.     int fd;
  2122. {
  2123.     int res;
  2124.  
  2125. #ifdef    F_GETOWN
  2126.     setconnmode(0);
  2127.     res = fcntl(fd, F_GETOWN, 0);
  2128.     setcommandmode();
  2129.  
  2130.     if (res == -1) {
  2131.     perror("fcntl");
  2132.     return;
  2133.     }
  2134.     printf("\tOwner is %d.\n", res);
  2135. #endif
  2136.  
  2137.     setconnmode(0);
  2138.     res = fcntl(fd, F_GETFL, 0);
  2139.     setcommandmode();
  2140.  
  2141.     if (res == -1) {
  2142.     perror("fcntl");
  2143.     return;
  2144.     }
  2145. #ifdef notdef
  2146.     printf("\tFlags are 0x%x: %s\n", res, decodeflags(res));
  2147. #endif
  2148. }
  2149. #endif /* defined(unix) && defined(TN3270) */
  2150.  
  2151. /*
  2152.  * Print status about the connection.
  2153.  */
  2154.     /*ARGSUSED*/
  2155.     static
  2156. status(argc, argv)
  2157.     int     argc;
  2158.     char *argv[];
  2159. {
  2160.     if (connected) {
  2161.     printf("Connected to %s.\n", hostname);
  2162.     if ((argc < 2) || strcmp(argv[1], "notmuch")) {
  2163.         int mode = getconnmode();
  2164.  
  2165.         if (my_want_state_is_will(TELOPT_LINEMODE)) {
  2166.         printf("Operating with LINEMODE option\n");
  2167.         printf("%s line editing\n", (mode&MODE_EDIT) ? "Local" : "No");
  2168.         printf("%s catching of signals\n",
  2169.                     (mode&MODE_TRAPSIG) ? "Local" : "No");
  2170.         slcstate();
  2171. #ifdef    KLUDGELINEMODE
  2172.         } else if (kludgelinemode && my_want_state_is_dont(TELOPT_SGA)) {
  2173.         printf("Operating in obsolete linemode\n");
  2174. #endif
  2175.         } else {
  2176.         printf("Operating in single character mode\n");
  2177.         if (localchars)
  2178.             printf("Catching signals locally\n");
  2179.         }
  2180.         printf("%s character echo\n", (mode&MODE_ECHO) ? "Local" : "Remote");
  2181.         if (my_want_state_is_will(TELOPT_LFLOW))
  2182.         printf("%s flow control\n", (mode&MODE_FLOW) ? "Local" : "No");
  2183. #ifdef    ENCRYPTION
  2184.         encrypt_display();
  2185. #endif    /* ENCRYPTION */
  2186.     }
  2187.     } else {
  2188.     printf("No connection.\n");
  2189.     }
  2190. #   if !defined(TN3270)
  2191.     printf("Escape character is '%s'.\n", control(escape));
  2192.     (void) fflush(stdout);
  2193. #   else /* !defined(TN3270) */
  2194.     if ((!In3270) && ((argc < 2) || strcmp(argv[1], "notmuch"))) {
  2195.     printf("Escape character is '%s'.\n", control(escape));
  2196.     }
  2197. #   if defined(unix)
  2198.     if ((argc >= 2) && !strcmp(argv[1], "everything")) {
  2199.     printf("SIGIO received %d time%s.\n",
  2200.                 sigiocount, (sigiocount == 1)? "":"s");
  2201.     if (In3270) {
  2202.         printf("Process ID %d, process group %d.\n",
  2203.                         getpid(), getpgrp(getpid()));
  2204.         printf("Terminal input:\n");
  2205.         filestuff(tin);
  2206.         printf("Terminal output:\n");
  2207.         filestuff(tout);
  2208.         printf("Network socket:\n");
  2209.         filestuff(net);
  2210.     }
  2211.     }
  2212.     if (In3270 && transcom) {
  2213.        printf("Transparent mode command is '%s'.\n", transcom);
  2214.     }
  2215. #   endif /* defined(unix) */
  2216.     (void) fflush(stdout);
  2217.     if (In3270) {
  2218.     return 0;
  2219.     }
  2220. #   endif /* defined(TN3270) */
  2221.     return 1;
  2222. }
  2223.  
  2224. #ifdef    SIGINFO
  2225. /*
  2226.  * Function that gets called when SIGINFO is received.
  2227.  */
  2228. ayt_status()
  2229. {
  2230.     (void) call(status, "status", "notmuch", 0);
  2231. }
  2232. #endif
  2233.  
  2234. unsigned long inet_addr();
  2235.  
  2236.     int
  2237. tn(argc, argv)
  2238.     int argc;
  2239.     char *argv[];
  2240. {
  2241.     register struct hostent *host = 0;
  2242.     struct sockaddr_in sin;
  2243.     struct servent *sp = 0;
  2244.     unsigned long temp;
  2245.     extern char *inet_ntoa();
  2246. #if    defined(IP_OPTIONS) && defined(IPPROTO_IP)
  2247.     char *srp = 0, *strrchr();
  2248.     unsigned long sourceroute(), srlen;
  2249. #endif
  2250.     char *cmd, *hostp = 0, *portp = 0, *user = 0;
  2251.  
  2252.     /* clear the socket address prior to use */
  2253.     memset((char *)&sin, 0, sizeof(sin));
  2254.  
  2255.     if (connected) {
  2256.     printf("?Already connected to %s\n", hostname);
  2257.     setuid(getuid());
  2258.     return 0;
  2259.     }
  2260.     if (argc < 2) {
  2261.     (void) strcpy(line, "open ");
  2262.     printf("(to) ");
  2263.     (void) fgets(&line[strlen(line)], sizeof(line) - strlen(line), stdin);
  2264.     makeargv();
  2265.     argc = margc;
  2266.     argv = margv;
  2267.     }
  2268.     cmd = *argv;
  2269.     --argc; ++argv;
  2270.     while (argc) {
  2271.     if (strcmp(*argv, "help") == 0 || isprefix(*argv, "?"))
  2272.         goto usage;
  2273.     if (strcmp(*argv, "-l") == 0) {
  2274.         --argc; ++argv;
  2275.         if (argc == 0)
  2276.         goto usage;
  2277.         user = *argv++;
  2278.         --argc;
  2279.         continue;
  2280.     }
  2281.     if (strcmp(*argv, "-a") == 0) {
  2282.         --argc; ++argv;
  2283.         autologin = 1;
  2284.         continue;
  2285.     }
  2286.     if (hostp == 0) {
  2287.         hostp = *argv++;
  2288.         --argc;
  2289.         continue;
  2290.     }
  2291.     if (portp == 0) {
  2292.         portp = *argv++;
  2293.         --argc;
  2294.         continue;
  2295.     }
  2296.     usage:
  2297.     printf("usage: %s [-l user] [-a] host-name [port]\n", cmd);
  2298.     setuid(getuid());
  2299.     return 0;
  2300.     }
  2301.     if (hostp == 0)
  2302.     goto usage;
  2303.  
  2304. #if    defined(IP_OPTIONS) && defined(IPPROTO_IP)
  2305.     if (hostp[0] == '@' || hostp[0] == '!') {
  2306.     if ((hostname = strrchr(hostp, ':')) == NULL)
  2307.         hostname = strrchr(hostp, '@');
  2308.     hostname++;
  2309.     srp = 0;
  2310.     temp = sourceroute(hostp, &srp, &srlen);
  2311.     if (temp == 0) {
  2312.         herror(srp);
  2313.         setuid(getuid());
  2314.         return 0;
  2315.     } else if (temp == -1) {
  2316.         printf("Bad source route option: %s\n", hostp);
  2317.         setuid(getuid());
  2318.         return 0;
  2319.     } else {
  2320.         sin.sin_addr.s_addr = temp;
  2321.         sin.sin_family = AF_INET;
  2322.     }
  2323.     } else {
  2324. #endif
  2325.     temp = inet_addr(hostp);
  2326.     if (temp != (unsigned long) -1) {
  2327.         sin.sin_addr.s_addr = temp;
  2328.         sin.sin_family = AF_INET;
  2329.  
  2330.         if (_hostname)
  2331.         free (_hostname);
  2332.         _hostname = malloc (strlen (hostp) + 1);
  2333.         if (_hostname) {
  2334.         strcpy (_hostname, hostp);
  2335.         hostname = _hostname;
  2336.         } else {
  2337.         printf ("Can't allocate memory to copy hostname\n");
  2338.         setuid(getuid());
  2339.         return 0;
  2340.         }
  2341.     } else {
  2342.         host = gethostbyname(hostp);
  2343.         if (host) {
  2344.         sin.sin_family = host->h_addrtype;
  2345. #if    defined(h_addr)        /* In 4.3, this is a #define */
  2346.         memmove((caddr_t)&sin.sin_addr,
  2347.                 host->h_addr_list[0], host->h_length);
  2348. #else    /* defined(h_addr) */
  2349.         memmove((caddr_t)&sin.sin_addr, host->h_addr, host->h_length);
  2350. #endif    /* defined(h_addr) */
  2351.  
  2352.         if (_hostname)
  2353.             free (_hostname);
  2354.         _hostname = malloc (strlen (host->h_name) + 1);
  2355.         if (_hostname) {
  2356.             strcpy (_hostname, host->h_name);
  2357.             hostname = _hostname;
  2358.         } else {
  2359.             printf ("Can't allocate memory to copy hostname\n");
  2360.             setuid(getuid());
  2361.             return 0;
  2362.         }
  2363.         } else {
  2364.         herror(hostp);
  2365.             setuid(getuid());
  2366.         return 0;
  2367.         }
  2368.     }
  2369. #if    defined(IP_OPTIONS) && defined(IPPROTO_IP)
  2370.     }
  2371. #endif
  2372.     if (portp) {
  2373.     if (*portp == '-') {
  2374.         portp++;
  2375.         telnetport = 1;
  2376.     } else
  2377.         telnetport = 0;
  2378.     sin.sin_port = atoi(portp);
  2379.     if (sin.sin_port == 0) {
  2380.         sp = getservbyname(portp, "tcp");
  2381.         if (sp)
  2382.         sin.sin_port = sp->s_port;
  2383.         else {
  2384.         printf("%s: bad port number\n", portp);
  2385.             setuid(getuid());
  2386.         return 0;
  2387.         }
  2388.     } else {
  2389. #if    !defined(htons)
  2390.         u_short htons P((unsigned short));
  2391. #endif    /* !defined(htons) */
  2392.         sin.sin_port = htons(sin.sin_port);
  2393.     }
  2394.     } else {
  2395.     if (sp == 0) {
  2396.         sp = getservbyname("telnet", "tcp");
  2397.         if (sp == 0) {
  2398.         fprintf(stderr, "telnet: tcp/telnet: unknown service\n");
  2399.             setuid(getuid());
  2400.         return 0;
  2401.         }
  2402.         sin.sin_port = sp->s_port;
  2403.     }
  2404.     telnetport = 1;
  2405.     }
  2406.     printf("Trying %s...\n", inet_ntoa(sin.sin_addr));
  2407.     do {
  2408.     net = socket(AF_INET, SOCK_STREAM, 0);
  2409.     setuid(getuid());
  2410.     if (net < 0) {
  2411.         perror("telnet: socket");
  2412.         return 0;
  2413.     }
  2414. #if    defined(IP_OPTIONS) && defined(IPPROTO_IP)
  2415.     if (srp && setsockopt(net, IPPROTO_IP, IP_OPTIONS, (char *)srp, srlen) < 0)
  2416.         perror("setsockopt (IP_OPTIONS)");
  2417. #endif
  2418. #if    defined(IPPROTO_IP) && defined(IP_TOS)
  2419.     {
  2420. # if    defined(HAS_GETTOS) && !defined(__EMX__)
  2421.         struct tosent *tp;
  2422.         if (tos < 0 && (tp = gettosbyname("telnet", "tcp")))
  2423.         tos = tp->t_tos;
  2424. # endif
  2425.         if (tos < 0)
  2426.         tos = 020;    /* Low Delay bit */
  2427.         if (tos
  2428.         && (setsockopt(net, IPPROTO_IP, IP_TOS,
  2429.             (char *)&tos, sizeof(int)) < 0)
  2430.         && (errno != ENOPROTOOPT))
  2431.             perror("telnet: setsockopt (IP_TOS) (ignored)");
  2432.     }
  2433. #endif    /* defined(IPPROTO_IP) && defined(IP_TOS) */
  2434.  
  2435.     if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) {
  2436.         perror("setsockopt (SO_DEBUG)");
  2437.     }
  2438.  
  2439.     if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
  2440. #if    defined(h_addr)        /* In 4.3, this is a #define */
  2441.         if (host && host->h_addr_list[1]) {
  2442.         int oerrno = errno;
  2443.  
  2444.         fprintf(stderr, "telnet: connect to address %s: ",
  2445.                         inet_ntoa(sin.sin_addr));
  2446.         errno = oerrno;
  2447.         perror((char *)0);
  2448.         host->h_addr_list++;
  2449.         memmove((caddr_t)&sin.sin_addr,
  2450.             host->h_addr_list[0], host->h_length);
  2451.         (void) NetClose(net);
  2452.         continue;
  2453.         }
  2454. #endif    /* defined(h_addr) */
  2455.         perror("telnet: Unable to connect to remote host");
  2456.         return 0;
  2457.     }
  2458.     connected++;
  2459. #if    defined(AUTHENTICATION) || defined(ENCRYPTION)
  2460.     auth_encrypt_connect(connected);
  2461. #endif    /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
  2462.     } while (connected == 0);
  2463.     cmdrc(hostp, hostname);
  2464.     if (autologin && user == NULL) {
  2465.     struct passwd *pw;
  2466.  
  2467.     user = getenv("USER");
  2468.     if (user == NULL ||
  2469.         (pw = getpwnam(user)) && pw->pw_uid != getuid()) {
  2470.         if (pw = getpwuid(getuid()))
  2471.             user = pw->pw_name;
  2472.         else
  2473.             user = NULL;
  2474.     }
  2475.     }
  2476.     if (user) {
  2477.     env_define((unsigned char *)"USER", (unsigned char *)user);
  2478.     env_export((unsigned char *)"USER");
  2479.     }
  2480.     (void) call(status, "status", "notmuch", 0);
  2481.     if (setjmp(peerdied) == 0)
  2482.     telnet(user);
  2483.     (void) NetClose(net);
  2484.     ExitString("Connection closed by foreign host.\n",1);
  2485.     /*NOTREACHED*/
  2486. }
  2487.  
  2488. #define HELPINDENT (sizeof ("connect"))
  2489.  
  2490. static char
  2491.     openhelp[] =    "connect to a site",
  2492.     closehelp[] =    "close current connection",
  2493.     logouthelp[] =    "forcibly logout remote user and close the connection",
  2494.     quithelp[] =    "exit telnet",
  2495.     statushelp[] =    "print status information",
  2496.     helphelp[] =    "print help information",
  2497.     sendhelp[] =    "transmit special characters ('send ?' for more)",
  2498.     sethelp[] =     "set operating parameters ('set ?' for more)",
  2499.     unsethelp[] =     "unset operating parameters ('unset ?' for more)",
  2500.     togglestring[] ="toggle operating parameters ('toggle ?' for more)",
  2501.     slchelp[] =    "change state of special charaters ('slc ?' for more)",
  2502.     displayhelp[] =    "display operating parameters",
  2503. #if    defined(TN3270) && defined(unix)
  2504.     transcomhelp[] = "specify Unix command for transparent mode pipe",
  2505. #endif    /* defined(TN3270) && defined(unix) */
  2506. #if    defined(AUTHENTICATION)
  2507.     authhelp[] =    "turn on (off) authentication ('auth ?' for more)",
  2508. #endif
  2509. #ifdef    ENCRYPTION
  2510.     encrypthelp[] =    "turn on (off) encryption ('encrypt ?' for more)",
  2511. #endif    /* ENCRYPTION */
  2512. #if    defined(unix)
  2513.     zhelp[] =    "suspend telnet",
  2514. #endif    /* defined(unix) */
  2515.     shellhelp[] =    "invoke a subshell",
  2516.     envhelp[] =    "change environment variables ('environ ?' for more)",
  2517.     modestring[] = "try to enter line or character mode ('mode ?' for more)";
  2518.  
  2519. static int    help();
  2520.  
  2521. static Command cmdtab[] = {
  2522.     { "close",    closehelp,    bye,        1 },
  2523.     { "logout",    logouthelp,    logout,        1 },
  2524.     { "display",    displayhelp,    display,    0 },
  2525.     { "mode",    modestring,    modecmd,    0 },
  2526.     { "open",    openhelp,    tn,        0 },
  2527.     { "quit",    quithelp,    quit,        0 },
  2528.     { "send",    sendhelp,    sendcmd,    0 },
  2529.     { "set",    sethelp,    setcmd,        0 },
  2530.     { "unset",    unsethelp,    unsetcmd,    0 },
  2531.     { "status",    statushelp,    status,        0 },
  2532.     { "toggle",    togglestring,    toggle,        0 },
  2533.     { "slc",    slchelp,    slccmd,        0 },
  2534. #if    defined(TN3270) && defined(unix)
  2535.     { "transcom",    transcomhelp,    settranscom,    0 },
  2536. #endif    /* defined(TN3270) && defined(unix) */
  2537. #if    defined(AUTHENTICATION)
  2538.     { "auth",    authhelp,    auth_cmd,    0 },
  2539. #endif
  2540. #ifdef    ENCRYPTION
  2541.     { "encrypt",    encrypthelp,    encrypt_cmd,    0 },
  2542. #endif    /* ENCRYPTION */
  2543. #if    defined(unix)
  2544.     { "z",        zhelp,        suspend,    0 },
  2545. #endif    /* defined(unix) */
  2546. #if    defined(TN3270)
  2547.     { "!",        shellhelp,    shell,        1 },
  2548. #else
  2549.     { "!",        shellhelp,    shell,        0 },
  2550. #endif
  2551.     { "environ",    envhelp,    env_cmd,    0 },
  2552.     { "?",        helphelp,    help,        0 },
  2553.     0
  2554. };
  2555.  
  2556. static char    crmodhelp[] =    "deprecated command -- use 'toggle crmod' instead";
  2557. static char    escapehelp[] =    "deprecated command -- use 'set escape' instead";
  2558.  
  2559. static Command cmdtab2[] = {
  2560.     { "help",    0,        help,        0 },
  2561.     { "escape",    escapehelp,    setescape,    0 },
  2562.     { "crmod",    crmodhelp,    togcrmod,    0 },
  2563.     0
  2564. };
  2565.  
  2566.  
  2567. /*
  2568.  * Call routine with argc, argv set from args (terminated by 0).
  2569.  */
  2570.  
  2571.     /*VARARGS1*/
  2572.     static
  2573. call(va_alist)
  2574.     va_dcl
  2575. {
  2576.     va_list ap;
  2577.     typedef int (*intrtn_t)();
  2578.     intrtn_t routine;
  2579.     char *args[100];
  2580.     int argno = 0;
  2581.  
  2582.     va_start(ap);
  2583.     routine = (va_arg(ap, intrtn_t));
  2584.     while ((args[argno++] = va_arg(ap, char *)) != 0) {
  2585.     ;
  2586.     }
  2587.     va_end(ap);
  2588.     return (*routine)(argno-1, args);
  2589. }
  2590.  
  2591.  
  2592.     static Command *
  2593. getcmd(name)
  2594.     char *name;
  2595. {
  2596.     Command *cm;
  2597.  
  2598.     if (cm = (Command *) genget(name, (char **) cmdtab, sizeof(Command)))
  2599.     return cm;
  2600.     return (Command *) genget(name, (char **) cmdtab2, sizeof(Command));
  2601. }
  2602.  
  2603.     void
  2604. command(top, tbuf, cnt)
  2605.     int top;
  2606.     char *tbuf;
  2607.     int cnt;
  2608. {
  2609.     register Command *c;
  2610.  
  2611.     setcommandmode();
  2612.     if (!top) {
  2613.     putchar('\n');
  2614. #if    defined(unix)
  2615.     } else {
  2616.     (void) signal(SIGINT, SIG_DFL);
  2617.     (void) signal(SIGQUIT, SIG_DFL);
  2618. #endif    /* defined(unix) */
  2619.     }
  2620.     for (;;) {
  2621.     if (rlogin == _POSIX_VDISABLE)
  2622.         printf("%s> ", prompt);
  2623.     if (tbuf) {
  2624.         register char *cp;
  2625.         cp = line;
  2626.         while (cnt > 0 && (*cp++ = *tbuf++) != '\n')
  2627.         cnt--;
  2628.         tbuf = 0;
  2629.         if (cp == line || *--cp != '\n' || cp == line)
  2630.         goto getline;
  2631.         *cp = '\0';
  2632.         if (rlogin == _POSIX_VDISABLE)
  2633.             printf("%s\n", line);
  2634.     } else {
  2635.     getline:
  2636.         if (rlogin != _POSIX_VDISABLE)
  2637.         printf("%s> ", prompt);
  2638.         if (fgets(line, sizeof(line), stdin) == NULL) {
  2639.         if (feof(stdin) || ferror(stdin)) {
  2640.             (void) quit();
  2641.             /*NOTREACHED*/
  2642.         }
  2643.         break;
  2644.         }
  2645.     }
  2646.     if (line[0] == 0)
  2647.         break;
  2648.     makeargv();
  2649.     if (margv[0] == 0) {
  2650.         break;
  2651.     }
  2652.     c = getcmd(margv[0]);
  2653.     if (Ambiguous(c)) {
  2654.         printf("?Ambiguous command\n");
  2655.         continue;
  2656.     }
  2657.     if (c == 0) {
  2658.         printf("?Invalid command\n");
  2659.         continue;
  2660.     }
  2661.     if (c->needconnect && !connected) {
  2662.         printf("?Need to be connected first.\n");
  2663.         continue;
  2664.     }
  2665.     if ((*c->handler)(margc, margv)) {
  2666.         break;
  2667.     }
  2668.     }
  2669.     if (!top) {
  2670.     if (!connected) {
  2671.         longjmp(toplevel, 1);
  2672.         /*NOTREACHED*/
  2673.     }
  2674. #if    defined(TN3270)
  2675.     if (shell_active == 0) {
  2676.         setconnmode(0);
  2677.     }
  2678. #else    /* defined(TN3270) */
  2679.     setconnmode(0);
  2680. #endif    /* defined(TN3270) */
  2681.     }
  2682. }
  2683.  
  2684. /*
  2685.  * Help command.
  2686.  */
  2687.     static
  2688. help(argc, argv)
  2689.     int argc;
  2690.     char *argv[];
  2691. {
  2692.     register Command *c;
  2693.  
  2694.     if (argc == 1) {
  2695.         printf("Commands may be abbreviated.  Commands are:\n\n");
  2696.         for (c = cmdtab; c->name; c++)
  2697.             if (c->help) {
  2698.                 printf("%-*s\t%s\n", HELPINDENT, c->name,
  2699.                                     c->help);
  2700.             }
  2701.         return 0;
  2702.     }
  2703.     while (--argc > 0) {
  2704.         register char *arg;
  2705.         arg = *++argv;
  2706.         c = getcmd(arg);
  2707.         if (Ambiguous(c))
  2708.             printf("?Ambiguous help command %s\n", arg);
  2709.         else if (c == (Command *)0)
  2710.             printf("?Invalid help command %s\n", arg);
  2711.         else
  2712.             printf("%s\n", c->help);
  2713.     }
  2714.     return 0;
  2715. }
  2716.  
  2717. static char *rcname = 0;
  2718. static char rcbuf[128];
  2719.  
  2720. cmdrc(m1, m2)
  2721.     char *m1, *m2;
  2722. {
  2723.     register Command *c;
  2724.     FILE *rcfile;
  2725.     int gotmachine = 0;
  2726.     int l1 = strlen(m1);
  2727.     int l2 = strlen(m2);
  2728.     char m1save[64];
  2729.  
  2730.     if (skiprc)
  2731.     return;
  2732.  
  2733.     strcpy(m1save, m1);
  2734.     m1 = m1save;
  2735.  
  2736.     if (rcname == 0) {
  2737.     rcname = getenv("HOME");
  2738.     if (rcname)
  2739.         strcpy(rcbuf, rcname);
  2740.     else
  2741.         rcbuf[0] = '\0';
  2742.     strcat(rcbuf, "/.telnetrc");
  2743.     rcname = rcbuf;
  2744.     }
  2745.  
  2746.     if ((rcfile = fopen(rcname, "r")) == 0) {
  2747.     return;
  2748.     }
  2749.  
  2750.     for (;;) {
  2751.     if (fgets(line, sizeof(line), rcfile) == NULL)
  2752.         break;
  2753.     if (line[0] == 0)
  2754.         break;
  2755.     if (line[0] == '#')
  2756.         continue;
  2757.     if (gotmachine) {
  2758.         if (!isspace(line[0]))
  2759.         gotmachine = 0;
  2760.     }
  2761.     if (gotmachine == 0) {
  2762.         if (isspace(line[0]))
  2763.         continue;
  2764.         if (strncasecmp(line, m1, l1) == 0)
  2765.         strncpy(line, &line[l1], sizeof(line) - l1);
  2766.         else if (strncasecmp(line, m2, l2) == 0)
  2767.         strncpy(line, &line[l2], sizeof(line) - l2);
  2768.         else if (strncasecmp(line, "DEFAULT", 7) == 0)
  2769.         strncpy(line, &line[7], sizeof(line) - 7);
  2770.         else
  2771.         continue;
  2772.         if (line[0] != ' ' && line[0] != '\t' && line[0] != '\n')
  2773.         continue;
  2774.         gotmachine = 1;
  2775.     }
  2776.     makeargv();
  2777.     if (margv[0] == 0)
  2778.         continue;
  2779.     c = getcmd(margv[0]);
  2780.     if (Ambiguous(c)) {
  2781.         printf("?Ambiguous command: %s\n", margv[0]);
  2782.         continue;
  2783.     }
  2784.     if (c == 0) {
  2785.         printf("?Invalid command: %s\n", margv[0]);
  2786.         continue;
  2787.     }
  2788.     /*
  2789.      * This should never happen...
  2790.      */
  2791.     if (c->needconnect && !connected) {
  2792.         printf("?Need to be connected first for %s.\n", margv[0]);
  2793.         continue;
  2794.     }
  2795.     (*c->handler)(margc, margv);
  2796.     }
  2797.     fclose(rcfile);
  2798. }
  2799.  
  2800. #if    defined(IP_OPTIONS) && defined(IPPROTO_IP)
  2801.  
  2802. /*
  2803.  * Source route is handed in as
  2804.  *    [!]@hop1@hop2...[@|:]dst
  2805.  * If the leading ! is present, it is a
  2806.  * strict source route, otherwise it is
  2807.  * assmed to be a loose source route.
  2808.  *
  2809.  * We fill in the source route option as
  2810.  *    hop1,hop2,hop3...dest
  2811.  * and return a pointer to hop1, which will
  2812.  * be the address to connect() to.
  2813.  *
  2814.  * Arguments:
  2815.  *    arg:    pointer to route list to decipher
  2816.  *
  2817.  *    cpp:     If *cpp is not equal to NULL, this is a
  2818.  *        pointer to a pointer to a character array
  2819.  *        that should be filled in with the option.
  2820.  *
  2821.  *    lenp:    pointer to an integer that contains the
  2822.  *        length of *cpp if *cpp != NULL.
  2823.  *
  2824.  * Return values:
  2825.  *
  2826.  *    Returns the address of the host to connect to.  If the
  2827.  *    return value is -1, there was a syntax error in the
  2828.  *    option, either unknown characters, or too many hosts.
  2829.  *    If the return value is 0, one of the hostnames in the
  2830.  *    path is unknown, and *cpp is set to point to the bad
  2831.  *    hostname.
  2832.  *
  2833.  *    *cpp:    If *cpp was equal to NULL, it will be filled
  2834.  *        in with a pointer to our static area that has
  2835.  *        the option filled in.  This will be 32bit aligned.
  2836.  * 
  2837.  *    *lenp:    This will be filled in with how long the option
  2838.  *        pointed to by *cpp is.
  2839.  *    
  2840.  */
  2841.     unsigned long
  2842. sourceroute(arg, cpp, lenp)
  2843.     char    *arg;
  2844.     char    **cpp;
  2845.     int    *lenp;
  2846. {
  2847. #ifdef __EMX__
  2848.         fprintf(stderr,"sourceroute() not functional in this port.\n");
  2849.         return -1;
  2850. #else
  2851.     static char lsr[44];
  2852. #ifdef    sysV88
  2853.     static IOPTN ipopt;
  2854. #endif
  2855.     char *cp, *cp2, *lsrp, *lsrep;
  2856.     register int tmp;
  2857.     struct in_addr sin_addr;
  2858.     register struct hostent *host = 0;
  2859.     register char c;
  2860.  
  2861.     /*
  2862.      * Verify the arguments, and make sure we have
  2863.      * at least 7 bytes for the option.
  2864.      */
  2865.     if (cpp == NULL || lenp == NULL)
  2866.         return((unsigned long)-1);
  2867.     if (*cpp != NULL && *lenp < 7)
  2868.         return((unsigned long)-1);
  2869.     /*
  2870.      * Decide whether we have a buffer passed to us,
  2871.      * or if we need to use our own static buffer.
  2872.      */
  2873.     if (*cpp) {
  2874.         lsrp = *cpp;
  2875.         lsrep = lsrp + *lenp;
  2876.     } else {
  2877.         *cpp = lsrp = lsr;
  2878.         lsrep = lsrp + 44;
  2879.     }
  2880.  
  2881.     cp = arg;
  2882.  
  2883.     /*
  2884.      * Next, decide whether we have a loose source
  2885.      * route or a strict source route, and fill in
  2886.      * the begining of the option.
  2887.      */
  2888. #ifndef    sysV88
  2889.     if (*cp == '!') {
  2890.         cp++;
  2891.         *lsrp++ = IPOPT_SSRR;
  2892.     } else
  2893.         *lsrp++ = IPOPT_LSRR;
  2894. #else
  2895.     if (*cp == '!') {
  2896.         cp++;
  2897.         ipopt.io_type = IPOPT_SSRR;
  2898.     } else
  2899.         ipopt.io_type = IPOPT_LSRR;
  2900. #endif
  2901.  
  2902.     if (*cp != '@')
  2903.         return((unsigned long)-1);
  2904.  
  2905. #ifndef    sysV88
  2906.     lsrp++;        /* skip over length, we'll fill it in later */
  2907.     *lsrp++ = 4;
  2908. #endif
  2909.  
  2910.     cp++;
  2911.  
  2912.     sin_addr.s_addr = 0;
  2913.  
  2914.     for (c = 0;;) {
  2915.         if (c == ':')
  2916.             cp2 = 0;
  2917.         else for (cp2 = cp; c = *cp2; cp2++) {
  2918.             if (c == ',') {
  2919.                 *cp2++ = '\0';
  2920.                 if (*cp2 == '@')
  2921.                     cp2++;
  2922.             } else if (c == '@') {
  2923.                 *cp2++ = '\0';
  2924.             } else if (c == ':') {
  2925.                 *cp2++ = '\0';
  2926.             } else
  2927.                 continue;
  2928.             break;
  2929.         }
  2930.         if (!c)
  2931.             cp2 = 0;
  2932.  
  2933.         if ((tmp = inet_addr(cp)) != -1) {
  2934.             sin_addr.s_addr = tmp;
  2935.         } else if (host = gethostbyname(cp)) {
  2936. #if    defined(h_addr)
  2937.             memmove((caddr_t)&sin_addr,
  2938.                 host->h_addr_list[0], host->h_length);
  2939. #else
  2940.             memmove((caddr_t)&sin_addr, host->h_addr, host->h_length);
  2941. #endif
  2942.         } else {
  2943.             *cpp = cp;
  2944.             return(0);
  2945.         }
  2946.         memmove(lsrp, (char *)&sin_addr, 4);
  2947.         lsrp += 4;
  2948.         if (cp2)
  2949.             cp = cp2;
  2950.         else
  2951.             break;
  2952.         /*
  2953.          * Check to make sure there is space for next address
  2954.          */
  2955.         if (lsrp + 4 > lsrep)
  2956.             return((unsigned long)-1);
  2957.     }
  2958. #ifndef    sysV88
  2959.     if ((*(*cpp+IPOPT_OLEN) = lsrp - *cpp) <= 7) {
  2960.         *cpp = 0;
  2961.         *lenp = 0;
  2962.         return((unsigned long)-1);
  2963.     }
  2964.     *lsrp++ = IPOPT_NOP; /* 32 bit word align it */
  2965.     *lenp = lsrp - *cpp;
  2966. #else
  2967.     ipopt.io_len = lsrp - *cpp;
  2968.     if (ipopt.io_len <= 5) {        /* Is 3 better ? */
  2969.         *cpp = 0;
  2970.         *lenp = 0;
  2971.         return((unsigned long)-1);
  2972.     }
  2973.     *lenp = sizeof(ipopt);
  2974.     *cpp = (char *) &ipopt;
  2975. #endif
  2976.     return(sin_addr.s_addr);
  2977. #endif /* EMX */
  2978. }
  2979. #endif
  2980.