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