home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / libexec / telnetd / telnetd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-20  |  29.7 KB  |  1,250 lines

  1. /*
  2.  * Copyright (c) 1989 Regents of the University of California.
  3.  * 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. char copyright[] =
  36. "@(#) Copyright (c) 1989 Regents of the University of California.\n\
  37.  All rights reserved.\n";
  38. #endif /* not lint */
  39.  
  40. #ifndef lint
  41. static char sccsid[] = "@(#)telnetd.c    5.48 (Berkeley) 3/1/91";
  42. #endif /* not lint */
  43.  
  44. #include "telnetd.h"
  45. #include "pathnames.h"
  46.  
  47. #if    defined(AUTHENTICATE)
  48. #include <libtelnet/auth.h>
  49. int    auth_level = 0;
  50. #endif
  51. #if    defined(SecurID)
  52. int    require_SecurID = 0;
  53. #endif
  54.  
  55. /*
  56.  * I/O data buffers,
  57.  * pointers, and counters.
  58.  */
  59. char    ptyibuf[BUFSIZ], *ptyip = ptyibuf;
  60. char    ptyibuf2[BUFSIZ];
  61.  
  62. int    hostinfo = 1;            /* do we print login banner? */
  63.  
  64. #ifdef    CRAY
  65. extern int      newmap; /* nonzero if \n maps to ^M^J */
  66. int    lowpty = 0, highpty;    /* low, high pty numbers */
  67. #endif /* CRAY */
  68.  
  69. int debug = 0;
  70. int keepalive = 1;
  71. char *progname;
  72.  
  73. extern void usage P((void));
  74.  
  75. main(argc, argv)
  76.     char *argv[];
  77. {
  78.     struct sockaddr_in from;
  79.     int on = 1, fromlen;
  80.     register int ch;
  81.     extern char *optarg;
  82.     extern int optind;
  83. #if    defined(IPPROTO_IP) && defined(IP_TOS)
  84.     int tos = -1;
  85. #endif
  86.  
  87.     pfrontp = pbackp = ptyobuf;
  88.     netip = netibuf;
  89.     nfrontp = nbackp = netobuf;
  90. #if    defined(ENCRYPT)
  91.     nclearto = 0;
  92. #endif
  93.  
  94.     progname = *argv;
  95.  
  96. #ifdef CRAY
  97.     /*
  98.      * Get number of pty's before trying to process options,
  99.      * which may include changing pty range.
  100.      */
  101.     highpty = getnpty();
  102. #endif /* CRAY */
  103.  
  104.     while ((ch = getopt(argc, argv, "d:a:e:lhnr:I:D:B:sS:a:X:")) != EOF) {
  105.         switch(ch) {
  106.  
  107. #ifdef    AUTHENTICATE
  108.         case 'a':
  109.             /*
  110.              * Check for required authentication level
  111.              */
  112.             if (strcmp(optarg, "debug") == 0) {
  113.                 extern int auth_debug_mode;
  114.                 auth_debug_mode = 1;
  115.             } else if (strcasecmp(optarg, "none") == 0) {
  116.                 auth_level = 0;
  117.             } else if (strcasecmp(optarg, "other") == 0) {
  118.                 auth_level = AUTH_OTHER;
  119.             } else if (strcasecmp(optarg, "user") == 0) {
  120.                 auth_level = AUTH_USER;
  121.             } else if (strcasecmp(optarg, "valid") == 0) {
  122.                 auth_level = AUTH_VALID;
  123.             } else if (strcasecmp(optarg, "off") == 0) {
  124.                 /*
  125.                  * This hack turns off authentication
  126.                  */
  127.                 auth_level = -1;
  128.             } else {
  129.                 fprintf(stderr,
  130.                 "telnetd: unknown authorization level for -a\n");
  131.             }
  132.             break;
  133. #endif    /* AUTHENTICATE */
  134.  
  135. #ifdef BFTPDAEMON
  136.         case 'B':
  137.             bftpd++;
  138.             break;
  139. #endif /* BFTPDAEMON */
  140.  
  141.         case 'd':
  142.             if (strcmp(optarg, "ebug") == 0) {
  143.                 debug++;
  144.                 break;
  145.             }
  146.             usage();
  147.             /* NOTREACHED */
  148.             break;
  149.  
  150. #ifdef DIAGNOSTICS
  151.         case 'D':
  152.             /*
  153.              * Check for desired diagnostics capabilities.
  154.              */
  155.             if (!strcmp(optarg, "report")) {
  156.                 diagnostic |= TD_REPORT|TD_OPTIONS;
  157.             } else if (!strcmp(optarg, "exercise")) {
  158.                 diagnostic |= TD_EXERCISE;
  159.             } else if (!strcmp(optarg, "netdata")) {
  160.                 diagnostic |= TD_NETDATA;
  161.             } else if (!strcmp(optarg, "ptydata")) {
  162.                 diagnostic |= TD_PTYDATA;
  163.             } else if (!strcmp(optarg, "options")) {
  164.                 diagnostic |= TD_OPTIONS;
  165.             } else {
  166.                 usage();
  167.                 /* NOT REACHED */
  168.             }
  169.             break;
  170. #endif /* DIAGNOSTICS */
  171.  
  172. #ifdef    AUTHENTICATE
  173.         case 'e':
  174.             if (strcmp(optarg, "debug") == 0) {
  175.                 extern int encrypt_debug_mode;
  176.                 encrypt_debug_mode = 1;
  177.                 break;
  178.             }
  179.             usage();
  180.             /* NOTREACHED */
  181.             break;
  182. #endif    /* AUTHENTICATE */
  183.  
  184.         case 'h':
  185.             hostinfo = 0;
  186.             break;
  187.  
  188. #if    defined(CRAY) && defined(NEWINIT)
  189.         case 'I':
  190.             {
  191.             extern char *gen_id;
  192.             gen_id = optarg;
  193.             break;
  194.             }
  195. #endif    /* defined(CRAY) && defined(NEWINIT) */
  196.  
  197. #ifdef    LINEMODE
  198.         case 'l':
  199.             alwayslinemode = 1;
  200.             break;
  201. #endif    /* LINEMODE */
  202.  
  203.         case 'n':
  204.             keepalive = 0;
  205.             break;
  206.  
  207. #ifdef CRAY
  208.         case 'r':
  209.             {
  210.             char *strchr();
  211.             char *c;
  212.  
  213.             /*
  214.              * Allow the specification of alterations
  215.              * to the pty search range.  It is legal to
  216.              * specify only one, and not change the
  217.              * other from its default.
  218.              */
  219.             c = strchr(optarg, '-');
  220.             if (c) {
  221.                 *c++ = '\0';
  222.                 highpty = atoi(c);
  223.             }
  224.             if (*optarg != '\0')
  225.                 lowpty = atoi(optarg);
  226.             if ((lowpty > highpty) || (lowpty < 0) ||
  227.                             (highpty > 32767)) {
  228.                 usage();
  229.                 /* NOT REACHED */
  230.             }
  231.             break;
  232.             }
  233. #endif    /* CRAY */
  234.  
  235. #ifdef    SecurID
  236.         case 's':
  237.             /* SecurID required */
  238.             require_SecurID = 1;
  239.             break;
  240. #endif    /* SecurID */
  241.         case 'S':
  242. #ifdef    HAS_GETTOS
  243.             if ((tos = parsetos(optarg, "tcp")) < 0)
  244.                 fprintf(stderr, "%s%s%s\n",
  245.                     "telnetd: Bad TOS argument '", optarg,
  246.                     "'; will try to use default TOS");
  247. #else
  248.             fprintf(stderr, "%s%s\n", "TOS option unavailable; ",
  249.                         "-S flag not supported\n");
  250. #endif
  251.             break;
  252.  
  253. #ifdef    AUTHENTICATE
  254.         case 'X':
  255.             /*
  256.              * Check for invalid authentication types
  257.              */
  258.             auth_disable_name(optarg);
  259.             break;
  260. #endif    /* AUTHENTICATE */
  261.  
  262.         default:
  263.             fprintf(stderr, "telnetd: %s: unknown option\n", ch);
  264.             /* FALLTHROUGH */
  265.         case '?':
  266.             usage();
  267.             /* NOTREACHED */
  268.         }
  269.     }
  270.  
  271.     argc -= optind;
  272.     argv += optind;
  273.  
  274.     if (debug) {
  275.         int s, ns, foo;
  276.         struct servent *sp;
  277.         static struct sockaddr_in sin = { AF_INET };
  278.  
  279.         if (argc > 1) {
  280.         usage();
  281.         /* NOT REACHED */
  282.         } else if (argc == 1) {
  283.             if (sp = getservbyname(*argv, "tcp")) {
  284.             sin.sin_port = sp->s_port;
  285.             } else {
  286.             sin.sin_port = atoi(*argv);
  287.             if ((int)sin.sin_port <= 0) {
  288.                 fprintf(stderr, "telnetd: %s: bad port #\n", *argv);
  289.                 usage();
  290.                 /* NOT REACHED */
  291.             }
  292.             sin.sin_port = htons((u_short)sin.sin_port);
  293.            }
  294.         } else {
  295.         sp = getservbyname("telnet", "tcp");
  296.         if (sp == 0) {
  297.             fprintf(stderr, "telnetd: tcp/telnet: unknown service\n");
  298.             exit(1);
  299.         }
  300.         sin.sin_port = sp->s_port;
  301.         }
  302.  
  303.         s = socket(AF_INET, SOCK_STREAM, 0);
  304.         if (s < 0) {
  305.             perror("telnetd: socket");;
  306.             exit(1);
  307.         }
  308.         (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
  309.         if (bind(s, (struct sockaddr *)&sin, sizeof sin) < 0) {
  310.         perror("bind");
  311.         exit(1);
  312.         }
  313.         if (listen(s, 1) < 0) {
  314.         perror("listen");
  315.         exit(1);
  316.         }
  317.         foo = sizeof sin;
  318.         ns = accept(s, (struct sockaddr *)&sin, &foo);
  319.         if (ns < 0) {
  320.         perror("accept");
  321.         exit(1);
  322.         }
  323.         (void) dup2(ns, 0);
  324.         (void) close(ns);
  325.         (void) close(s);
  326. #ifdef convex
  327.     } else if (argc == 1) {
  328.         ; /* VOID*/        /* Just ignore the host/port name */
  329. #endif
  330.     } else if (argc > 0) {
  331.         usage();
  332.         /* NOT REACHED */
  333.     }
  334.  
  335.     openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON);
  336.     fromlen = sizeof (from);
  337.     if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
  338.         fprintf(stderr, "%s: ", progname);
  339.         perror("getpeername");
  340.         _exit(1);
  341.     }
  342.     if (keepalive &&
  343.         setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) {
  344.         syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
  345.     }
  346.  
  347. #if    defined(IPPROTO_IP) && defined(IP_TOS)
  348.     {
  349. # if    defined(HAS_GETTOS)
  350.         struct tosent *tp;
  351.         if (tos < 0 && (tp = gettosbyname("telnet", "tcp")))
  352.             tos = tp->t_tos;
  353. # endif
  354.         if (tos < 0)
  355.             tos = 020;    /* Low Delay bit */
  356.         if (tos
  357.            && (setsockopt(0, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0)
  358.            && (errno != ENOPROTOOPT) )
  359.             syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
  360.     }
  361. #endif    /* defined(IPPROTO_IP) && defined(IP_TOS) */
  362.     net = 0;
  363.     doit(&from);
  364.     /* NOTREACHED */
  365. }  /* end of main */
  366.  
  367.     void
  368. usage()
  369. {
  370.     fprintf(stderr, "Usage: telnetd");
  371. #ifdef    AUTHENTICATE
  372.     fprintf(stderr, " [-a (debug|other|user|valid|off)]\n\t");
  373. #endif
  374. #ifdef BFTPDAEMON
  375.     fprintf(stderr, " [-B]");
  376. #endif
  377.     fprintf(stderr, " [-debug]");
  378. #ifdef DIAGNOSTICS
  379.     fprintf(stderr, " [-D (options|report|exercise|netdata|ptydata)]\n\t");
  380. #endif
  381. #ifdef    AUTHENTICATE
  382.     fprintf(stderr, " [-edebug]");
  383. #endif
  384.     fprintf(stderr, " [-h]");
  385. #if    defined(CRAY) && defined(NEWINIT)
  386.     fprintf(stderr, " [-Iinitid]");
  387. #endif
  388. #ifdef LINEMODE
  389.     fprintf(stderr, " [-l]");
  390. #endif
  391.     fprintf(stderr, " [-n]");
  392. #ifdef    CRAY
  393.     fprintf(stderr, " [-r[lowpty]-[highpty]]");
  394. #endif
  395. #ifdef    SecurID
  396.     fprintf(stderr, " [-s]");
  397. #endif
  398. #ifdef    AUTHENTICATE
  399.     fprintf(stderr, " [-X auth-type]");
  400. #endif
  401.     fprintf(stderr, " [port]\n");
  402.     exit(1);
  403. }
  404.  
  405. /*
  406.  * getterminaltype
  407.  *
  408.  *    Ask the other end to send along its terminal type and speed.
  409.  * Output is the variable terminaltype filled in.
  410.  */
  411. static char ttytype_sbbuf[] = { IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE };
  412.  
  413.     int
  414. getterminaltype(name)
  415.     char *name;
  416. {
  417.     int retval = -1;
  418.     void _gettermname();
  419.  
  420.     settimer(baseline);
  421. #if    defined(AUTHENTICATE)
  422.     /*
  423.      * Handle the Authentication option before we do anything else.
  424.      */
  425.     send_do(TELOPT_AUTHENTICATION, 1);
  426.     while (his_will_wont_is_changing(TELOPT_AUTHENTICATION))
  427.     ttloop();
  428.     if (his_state_is_will(TELOPT_AUTHENTICATION)) {
  429.     retval = auth_wait(name);
  430.     }
  431. #endif
  432.  
  433. #if    defined(ENCRYPT)
  434.     send_will(TELOPT_ENCRYPT, 1);
  435. #endif
  436.     send_do(TELOPT_TTYPE, 1);
  437.     send_do(TELOPT_TSPEED, 1);
  438.     send_do(TELOPT_XDISPLOC, 1);
  439.     send_do(TELOPT_ENVIRON, 1);
  440.     while (
  441. #if    defined(ENCRYPT)
  442.        his_do_dont_is_changing(TELOPT_ENCRYPT) ||
  443. #endif
  444.        his_will_wont_is_changing(TELOPT_TTYPE) ||
  445.        his_will_wont_is_changing(TELOPT_TSPEED) ||
  446.        his_will_wont_is_changing(TELOPT_XDISPLOC) ||
  447.        his_will_wont_is_changing(TELOPT_ENVIRON)) {
  448.     ttloop();
  449.     }
  450. #if    defined(ENCRYPT)
  451.     /*
  452.      * Wait for the negotiation of what type of encryption we can
  453.      * send with.  If autoencrypt is not set, this will just return.
  454.      */
  455.     if (his_state_is_will(TELOPT_ENCRYPT)) {
  456.     encrypt_wait();
  457.     }
  458. #endif
  459.     if (his_state_is_will(TELOPT_TSPEED)) {
  460.     static char sbbuf[] = { IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE };
  461.  
  462.     bcopy(sbbuf, nfrontp, sizeof sbbuf);
  463.     nfrontp += sizeof sbbuf;
  464.     }
  465.     if (his_state_is_will(TELOPT_XDISPLOC)) {
  466.     static char sbbuf[] = { IAC, SB, TELOPT_XDISPLOC, TELQUAL_SEND, IAC, SE };
  467.  
  468.     bcopy(sbbuf, nfrontp, sizeof sbbuf);
  469.     nfrontp += sizeof sbbuf;
  470.     }
  471.     if (his_state_is_will(TELOPT_ENVIRON)) {
  472.     static char sbbuf[] = { IAC, SB, TELOPT_ENVIRON, TELQUAL_SEND, IAC, SE };
  473.  
  474.     bcopy(sbbuf, nfrontp, sizeof sbbuf);
  475.     nfrontp += sizeof sbbuf;
  476.     }
  477.     if (his_state_is_will(TELOPT_TTYPE)) {
  478.  
  479.     bcopy(ttytype_sbbuf, nfrontp, sizeof ttytype_sbbuf);
  480.     nfrontp += sizeof ttytype_sbbuf;
  481.     }
  482.     if (his_state_is_will(TELOPT_TSPEED)) {
  483.     while (sequenceIs(tspeedsubopt, baseline))
  484.         ttloop();
  485.     }
  486.     if (his_state_is_will(TELOPT_XDISPLOC)) {
  487.     while (sequenceIs(xdisplocsubopt, baseline))
  488.         ttloop();
  489.     }
  490.     if (his_state_is_will(TELOPT_ENVIRON)) {
  491.     while (sequenceIs(environsubopt, baseline))
  492.         ttloop();
  493.     }
  494.     if (his_state_is_will(TELOPT_TTYPE)) {
  495.     char first[256], last[256];
  496.  
  497.     while (sequenceIs(ttypesubopt, baseline))
  498.         ttloop();
  499.  
  500.     /*
  501.      * If the other side has already disabled the option, then
  502.      * we have to just go with what we (might) have already gotten.
  503.      */
  504.     if (his_state_is_will(TELOPT_TTYPE) && !terminaltypeok(terminaltype)) {
  505.         (void) strncpy(first, terminaltype, sizeof(first));
  506.         for(;;) {
  507.         /*
  508.          * Save the unknown name, and request the next name.
  509.          */
  510.         (void) strncpy(last, terminaltype, sizeof(last));
  511.         _gettermname();
  512.         if (terminaltypeok(terminaltype))
  513.             break;
  514.         if ((strncmp(last, terminaltype, sizeof(last)) == 0) ||
  515.             his_state_is_wont(TELOPT_TTYPE)) {
  516.             /*
  517.              * We've hit the end.  If this is the same as
  518.              * the first name, just go with it.
  519.              */
  520.             if (strncmp(first, terminaltype, sizeof(first)) == 0)
  521.             break;
  522.             /*
  523.              * Get the terminal name one more time, so that
  524.              * RFC1091 compliant telnets will cycle back to
  525.              * the start of the list.
  526.              */
  527.              _gettermname();
  528.             if (strncmp(first, terminaltype, sizeof(first)) != 0)
  529.             (void) strncpy(terminaltype, first, sizeof(first));
  530.             break;
  531.         }
  532.         }
  533.     }
  534.     }
  535.     return(retval);
  536. }  /* end of getterminaltype */
  537.  
  538.     void
  539. _gettermname()
  540. {
  541.     /*
  542.      * If the client turned off the option,
  543.      * we can't send another request, so we
  544.      * just return.
  545.      */
  546.     if (his_state_is_wont(TELOPT_TTYPE))
  547.     return;
  548.     settimer(baseline);
  549.     bcopy(ttytype_sbbuf, nfrontp, sizeof ttytype_sbbuf);
  550.     nfrontp += sizeof ttytype_sbbuf;
  551.     while (sequenceIs(ttypesubopt, baseline))
  552.     ttloop();
  553. }
  554.  
  555.     int
  556. terminaltypeok(s)
  557.     char *s;
  558. {
  559.     char buf[1024];
  560.  
  561.     if (terminaltype == NULL)
  562.     return(1);
  563.  
  564.     /*
  565.      * tgetent() will return 1 if the type is known, and
  566.      * 0 if it is not known.  If it returns -1, it couldn't
  567.      * open the database.  But if we can't open the database,
  568.      * it won't help to say we failed, because we won't be
  569.      * able to verify anything else.  So, we treat -1 like 1.
  570.      */
  571.     if (tgetent(buf, s) == 0)
  572.     return(0);
  573.     return(1);
  574. }
  575.  
  576. #ifndef    MAXHOSTNAMELEN
  577. #define    MAXHOSTNAMELEN 64
  578. #endif    /* MAXHOSTNAMELEN */
  579.  
  580. char *hostname;
  581. char host_name[MAXHOSTNAMELEN];
  582. char remote_host_name[MAXHOSTNAMELEN];
  583.  
  584. #ifndef    convex
  585. extern void telnet P((int, int));
  586. #else
  587. extern void telnet P((int, int, char *));
  588. #endif
  589.  
  590. /*
  591.  * Get a pty, scan input lines.
  592.  */
  593. doit(who)
  594.     struct sockaddr_in *who;
  595. {
  596.     char *host, *inet_ntoa();
  597.     int t;
  598.     struct hostent *hp;
  599.     int level;
  600.     char user_name[256];
  601.  
  602.     /*
  603.      * Find an available pty to use.
  604.      */
  605. #ifndef    convex
  606.     pty = getpty();
  607.     if (pty < 0)
  608.         fatal(net, "All network ports in use");
  609. #else
  610.     for (;;) {
  611.         char *lp;
  612.         extern char *line, *getpty();
  613.  
  614.         if ((lp = getpty()) == NULL)
  615.             fatal(net, "Out of ptys");
  616.  
  617.         if ((pty = open(lp, 2)) >= 0) {
  618.             strcpy(line,lp);
  619.             line[5] = 't';
  620.             break;
  621.         }
  622.     }
  623. #endif
  624.  
  625.     /* get name of connected client */
  626.     hp = gethostbyaddr((char *)&who->sin_addr, sizeof (struct in_addr),
  627.         who->sin_family);
  628.     if (hp)
  629.         host = hp->h_name;
  630.     else
  631.         host = inet_ntoa(who->sin_addr);
  632.     /*
  633.      * We must make a copy because Kerberos is probably going
  634.      * to also do a gethost* and overwrite the static data...
  635.      */
  636.     strncpy(remote_host_name, host, sizeof(remote_host_name)-1);
  637.     remote_host_name[sizeof(remote_host_name)-1] = 0;
  638.     host = remote_host_name;
  639.  
  640.     (void) gethostname(host_name, sizeof (host_name));
  641.     hostname = host_name;
  642.  
  643. #if    defined(AUTHENTICATE) || defined(ENCRYPT)
  644.     auth_encrypt_init(hostname, host, "TELNETD", 1);
  645. #endif
  646.  
  647.     init_env();
  648.     /*
  649.      * get terminal type.
  650.      */
  651.     *user_name = 0;
  652.     level = getterminaltype(user_name);
  653.     setenv("TERM", terminaltype ? terminaltype : "network", 1);
  654.  
  655.     /*
  656.      * Start up the login process on the slave side of the terminal
  657.      */
  658. #ifndef    convex
  659.     startslave(host, level, user_name);
  660.  
  661.     telnet(net, pty);  /* begin server processing */
  662. #else
  663.     telnet(net, pty, host);
  664. #endif
  665.     /*NOTREACHED*/
  666. }  /* end of doit */
  667.  
  668. #if    defined(CRAY2) && defined(UNICOS5) && defined(UNICOS50)
  669.     int
  670. Xterm_output(ibufp, obuf, icountp, ocount)
  671.     char **ibufp, *obuf;
  672.     int *icountp, ocount;
  673. {
  674.     int ret;
  675.     ret = term_output(*ibufp, obuf, *icountp, ocount);
  676.     *ibufp += *icountp;
  677.     *icountp = 0;
  678.     return(ret);
  679. }
  680. #define    term_output    Xterm_output
  681. #endif    /* defined(CRAY2) && defined(UNICOS5) && defined(UNICOS50) */
  682.  
  683. /*
  684.  * Main loop.  Select from pty and network, and
  685.  * hand data to telnet receiver finite state machine.
  686.  */
  687.     void
  688. #ifndef    convex
  689. telnet(f, p)
  690. #else
  691. telnet(f, p, host)
  692. #endif
  693.     int f, p;
  694. #ifdef convex
  695.     char *host;
  696. #endif
  697. {
  698.     int on = 1;
  699. #define    TABBUFSIZ    512
  700.     char    defent[TABBUFSIZ];
  701.     char    defstrs[TABBUFSIZ];
  702. #undef    TABBUFSIZ
  703.     char *HE;
  704.     char *HN;
  705.     char *IM;
  706.     void netflush();
  707.  
  708.     /*
  709.      * Initialize the slc mapping table.
  710.      */
  711.     get_slc_defaults();
  712.  
  713.     /*
  714.      * Do some tests where it is desireable to wait for a response.
  715.      * Rather than doing them slowly, one at a time, do them all
  716.      * at once.
  717.      */
  718.     if (my_state_is_wont(TELOPT_SGA))
  719.         send_will(TELOPT_SGA, 1);
  720.     /*
  721.      * Is the client side a 4.2 (NOT 4.3) system?  We need to know this
  722.      * because 4.2 clients are unable to deal with TCP urgent data.
  723.      *
  724.      * To find out, we send out a "DO ECHO".  If the remote system
  725.      * answers "WILL ECHO" it is probably a 4.2 client, and we note
  726.      * that fact ("WILL ECHO" ==> that the client will echo what
  727.      * WE, the server, sends it; it does NOT mean that the client will
  728.      * echo the terminal input).
  729.      */
  730.     send_do(TELOPT_ECHO, 1);
  731.  
  732. #ifdef    LINEMODE
  733.     if (his_state_is_wont(TELOPT_LINEMODE)) {
  734.         /* Query the peer for linemode support by trying to negotiate
  735.          * the linemode option.
  736.          */
  737.         linemode = 0;
  738.         editmode = 0;
  739.         send_do(TELOPT_LINEMODE, 1);  /* send do linemode */
  740.     }
  741. #endif    /* LINEMODE */
  742.  
  743.     /*
  744.      * Send along a couple of other options that we wish to negotiate.
  745.      */
  746.     send_do(TELOPT_NAWS, 1);
  747.     send_will(TELOPT_STATUS, 1);
  748.     flowmode = 1;  /* default flow control state */
  749.     send_do(TELOPT_LFLOW, 1);
  750.  
  751.     /*
  752.      * Spin, waiting for a response from the DO ECHO.  However,
  753.      * some REALLY DUMB telnets out there might not respond
  754.      * to the DO ECHO.  So, we spin looking for NAWS, (most dumb
  755.      * telnets so far seem to respond with WONT for a DO that
  756.      * they don't understand...) because by the time we get the
  757.      * response, it will already have processed the DO ECHO.
  758.      * Kludge upon kludge.
  759.      */
  760.     while (his_will_wont_is_changing(TELOPT_NAWS))
  761.         ttloop();
  762.  
  763.     /*
  764.      * But...
  765.      * The client might have sent a WILL NAWS as part of its
  766.      * startup code; if so, we'll be here before we get the
  767.      * response to the DO ECHO.  We'll make the assumption
  768.      * that any implementation that understands about NAWS
  769.      * is a modern enough implementation that it will respond
  770.      * to our DO ECHO request; hence we'll do another spin
  771.      * waiting for the ECHO option to settle down, which is
  772.      * what we wanted to do in the first place...
  773.      */
  774.     if (his_want_state_is_will(TELOPT_ECHO) &&
  775.         his_state_is_will(TELOPT_NAWS)) {
  776.         while (his_will_wont_is_changing(TELOPT_ECHO))
  777.             ttloop();
  778.     }
  779.     /*
  780.      * On the off chance that the telnet client is broken and does not
  781.      * respond to the DO ECHO we sent, (after all, we did send the
  782.      * DO NAWS negotiation after the DO ECHO, and we won't get here
  783.      * until a response to the DO NAWS comes back) simulate the
  784.      * receipt of a will echo.  This will also send a WONT ECHO
  785.      * to the client, since we assume that the client failed to
  786.      * respond because it believes that it is already in DO ECHO
  787.      * mode, which we do not want.
  788.      */
  789.     if (his_want_state_is_will(TELOPT_ECHO)) {
  790.         DIAG(TD_OPTIONS,
  791.             {sprintf(nfrontp, "td: simulating recv\r\n");
  792.              nfrontp += strlen(nfrontp);});
  793.         willoption(TELOPT_ECHO);
  794.     }
  795.  
  796.     /*
  797.      * Finally, to clean things up, we turn on our echo.  This
  798.      * will break stupid 4.2 telnets out of local terminal echo.
  799.      */
  800.  
  801.     if (my_state_is_wont(TELOPT_ECHO))
  802.         send_will(TELOPT_ECHO, 1);
  803.  
  804.     /*
  805.      * Turn on packet mode
  806.      */
  807.     (void) ioctl(p, TIOCPKT, (char *)&on);
  808. #if    defined(LINEMODE) && defined(KLUDGELINEMODE)
  809.     /*
  810.      * Continuing line mode support.  If client does not support
  811.      * real linemode, attempt to negotiate kludge linemode by sending
  812.      * the do timing mark sequence.
  813.      */
  814.     if (lmodetype < REAL_LINEMODE)
  815.         send_do(TELOPT_TM, 1);
  816. #endif    /* defined(LINEMODE) && defined(KLUDGELINEMODE) */
  817.  
  818.     /*
  819.      * Call telrcv() once to pick up anything received during
  820.      * terminal type negotiation, 4.2/4.3 determination, and
  821.      * linemode negotiation.
  822.      */
  823.     telrcv();
  824.  
  825.     (void) ioctl(f, FIONBIO, (char *)&on);
  826.     (void) ioctl(p, FIONBIO, (char *)&on);
  827. #if    defined(CRAY2) && defined(UNICOS5)
  828.     init_termdriver(f, p, interrupt, sendbrk);
  829. #endif
  830.  
  831. #if    defined(SO_OOBINLINE)
  832.     (void) setsockopt(net, SOL_SOCKET, SO_OOBINLINE, &on, sizeof on);
  833. #endif    /* defined(SO_OOBINLINE) */
  834.  
  835. #ifdef    SIGTSTP
  836.     (void) signal(SIGTSTP, SIG_IGN);
  837. #endif
  838. #ifdef    SIGTTOU
  839.     /*
  840.      * Ignoring SIGTTOU keeps the kernel from blocking us
  841.      * in ttioct() in /sys/tty.c.
  842.      */
  843.     (void) signal(SIGTTOU, SIG_IGN);
  844. #endif
  845.  
  846.     (void) signal(SIGCHLD, cleanup);
  847.  
  848. #if    defined(CRAY2) && defined(UNICOS5)
  849.     /*
  850.      * Cray-2 will send a signal when pty modes are changed by slave
  851.      * side.  Set up signal handler now.
  852.      */
  853.     if ((int)signal(SIGUSR1, termstat) < 0)
  854.         perror("signal");
  855.     else if (ioctl(p, TCSIGME, (char *)SIGUSR1) < 0)
  856.         perror("ioctl:TCSIGME");
  857.     /*
  858.      * Make processing loop check terminal characteristics early on.
  859.      */
  860.     termstat();
  861. #endif
  862.  
  863. #ifdef  TIOCNOTTY
  864.     {
  865.         register int t;
  866.         t = open(_PATH_TTY, O_RDWR);
  867.         if (t >= 0) {
  868.             (void) ioctl(t, TIOCNOTTY, (char *)0);
  869.             (void) close(t);
  870.         }
  871.     }
  872. #endif
  873.  
  874. #if    defined(CRAY) && defined(NEWINIT) && defined(TIOCSCTTY)
  875.     (void) setsid();
  876.     ioctl(p, TIOCSCTTY, 0);
  877. #endif
  878.  
  879.     /*
  880.      * Show banner that getty never gave.
  881.      *
  882.      * We put the banner in the pty input buffer.  This way, it
  883.      * gets carriage return null processing, etc., just like all
  884.      * other pty --> client data.
  885.      */
  886.  
  887. #if    !defined(CRAY) || !defined(NEWINIT)
  888.     if (getenv("USER"))
  889.         hostinfo = 0;
  890. #endif
  891.  
  892.     if (getent(defent, "default") == 1) {
  893.         char *getstr();
  894.         char *cp=defstrs;
  895.  
  896.         HE = getstr("he", &cp);
  897.         HN = getstr("hn", &cp);
  898.         IM = getstr("im", &cp);
  899.         if (HN && *HN)
  900.             (void) strcpy(host_name, HN);
  901.         if (IM == 0)
  902.             IM = "";
  903.     } else {
  904.         IM = DEFAULT_IM;
  905.         HE = 0;
  906.     }
  907.     edithost(HE, host_name);
  908.     if (hostinfo && *IM)
  909.         putf(IM, ptyibuf2);
  910.  
  911.     if (pcc)
  912.         (void) strncat(ptyibuf2, ptyip, pcc+1);
  913.     ptyip = ptyibuf2;
  914.     pcc = strlen(ptyip);
  915. #ifdef    LINEMODE
  916.     /*
  917.      * Last check to make sure all our states are correct.
  918.      */
  919.     init_termbuf();
  920.     localstat();
  921. #endif    /* LINEMODE */
  922.  
  923.     DIAG(TD_REPORT,
  924.         {sprintf(nfrontp, "td: Entering processing loop\r\n");
  925.          nfrontp += strlen(nfrontp);});
  926.  
  927. #ifdef    convex
  928.     startslave(host);
  929. #endif
  930.  
  931.     for (;;) {
  932.         fd_set ibits, obits, xbits;
  933.         register int c;
  934.  
  935.         if (ncc < 0 && pcc < 0)
  936.             break;
  937.  
  938. #if    defined(CRAY2) && defined(UNICOS5)
  939.         if (needtermstat)
  940.             _termstat();
  941. #endif    /* defined(CRAY2) && defined(UNICOS5) */
  942.         FD_ZERO(&ibits);
  943.         FD_ZERO(&obits);
  944.         FD_ZERO(&xbits);
  945.         /*
  946.          * Never look for input if there's still
  947.          * stuff in the corresponding output buffer
  948.          */
  949.         if (nfrontp - nbackp || pcc > 0) {
  950.             FD_SET(f, &obits);
  951.         } else {
  952.             FD_SET(p, &ibits);
  953.         }
  954.         if (pfrontp - pbackp || ncc > 0) {
  955.             FD_SET(p, &obits);
  956.         } else {
  957.             FD_SET(f, &ibits);
  958.         }
  959.         if (!SYNCHing) {
  960.             FD_SET(f, &xbits);
  961.         }
  962.         if ((c = select(16, &ibits, &obits, &xbits,
  963.                         (struct timeval *)0)) < 1) {
  964.             if (c == -1) {
  965.                 if (errno == EINTR) {
  966.                     continue;
  967.                 }
  968.             }
  969.             sleep(5);
  970.             continue;
  971.         }
  972.  
  973.         /*
  974.          * Any urgent data?
  975.          */
  976.         if (FD_ISSET(net, &xbits)) {
  977.             SYNCHing = 1;
  978.         }
  979.  
  980.         /*
  981.          * Something to read from the network...
  982.          */
  983.         if (FD_ISSET(net, &ibits)) {
  984. #if    !defined(SO_OOBINLINE)
  985.             /*
  986.              * In 4.2 (and 4.3 beta) systems, the
  987.              * OOB indication and data handling in the kernel
  988.              * is such that if two separate TCP Urgent requests
  989.              * come in, one byte of TCP data will be overlaid.
  990.              * This is fatal for Telnet, but we try to live
  991.              * with it.
  992.              *
  993.              * In addition, in 4.2 (and...), a special protocol
  994.              * is needed to pick up the TCP Urgent data in
  995.              * the correct sequence.
  996.              *
  997.              * What we do is:  if we think we are in urgent
  998.              * mode, we look to see if we are "at the mark".
  999.              * If we are, we do an OOB receive.  If we run
  1000.              * this twice, we will do the OOB receive twice,
  1001.              * but the second will fail, since the second
  1002.              * time we were "at the mark", but there wasn't
  1003.              * any data there (the kernel doesn't reset
  1004.              * "at the mark" until we do a normal read).
  1005.              * Once we've read the OOB data, we go ahead
  1006.              * and do normal reads.
  1007.              *
  1008.              * There is also another problem, which is that
  1009.              * since the OOB byte we read doesn't put us
  1010.              * out of OOB state, and since that byte is most
  1011.              * likely the TELNET DM (data mark), we would
  1012.              * stay in the TELNET SYNCH (SYNCHing) state.
  1013.              * So, clocks to the rescue.  If we've "just"
  1014.              * received a DM, then we test for the
  1015.              * presence of OOB data when the receive OOB
  1016.              * fails (and AFTER we did the normal mode read
  1017.              * to clear "at the mark").
  1018.              */
  1019.             if (SYNCHing) {
  1020.             int atmark;
  1021.  
  1022.             (void) ioctl(net, SIOCATMARK, (char *)&atmark);
  1023.             if (atmark) {
  1024.                 ncc = recv(net, netibuf, sizeof (netibuf), MSG_OOB);
  1025.                 if ((ncc == -1) && (errno == EINVAL)) {
  1026.                 ncc = read(net, netibuf, sizeof (netibuf));
  1027.                 if (sequenceIs(didnetreceive, gotDM)) {
  1028.                     SYNCHing = stilloob(net);
  1029.                 }
  1030.                 }
  1031.             } else {
  1032.                 ncc = read(net, netibuf, sizeof (netibuf));
  1033.             }
  1034.             } else {
  1035.             ncc = read(net, netibuf, sizeof (netibuf));
  1036.             }
  1037.             settimer(didnetreceive);
  1038. #else    /* !defined(SO_OOBINLINE)) */
  1039.             ncc = read(net, netibuf, sizeof (netibuf));
  1040. #endif    /* !defined(SO_OOBINLINE)) */
  1041.             if (ncc < 0 && errno == EWOULDBLOCK)
  1042.             ncc = 0;
  1043.             else {
  1044.             if (ncc <= 0) {
  1045.                 break;
  1046.             }
  1047.             netip = netibuf;
  1048.             }
  1049.             DIAG((TD_REPORT | TD_NETDATA),
  1050.                 {sprintf(nfrontp, "td: netread %d chars\r\n", ncc);
  1051.                  nfrontp += strlen(nfrontp);});
  1052.             DIAG(TD_NETDATA, printdata("nd", netip, ncc));
  1053.         }
  1054.  
  1055.         /*
  1056.          * Something to read from the pty...
  1057.          */
  1058.         if (FD_ISSET(p, &ibits)) {
  1059.             pcc = read(p, ptyibuf, BUFSIZ);
  1060.             /*
  1061.              * On some systems, if we try to read something
  1062.              * off the master side before the slave side is
  1063.              * opened, we get EIO.
  1064.              */
  1065.             if (pcc < 0 && (errno == EWOULDBLOCK || errno == EIO)) {
  1066.                 pcc = 0;
  1067.             } else {
  1068.                 if (pcc <= 0)
  1069.                     break;
  1070. #if    !defined(CRAY2) || !defined(UNICOS5)
  1071. #ifdef    LINEMODE
  1072.                 /*
  1073.                  * If ioctl from pty, pass it through net
  1074.                  */
  1075.                 if (ptyibuf[0] & TIOCPKT_IOCTL) {
  1076.                     copy_termbuf(ptyibuf+1, pcc-1);
  1077.                     localstat();
  1078.                     pcc = 1;
  1079.                 }
  1080. #endif    /* LINEMODE */
  1081.                 if (ptyibuf[0] & TIOCPKT_FLUSHWRITE) {
  1082.                     netclear();    /* clear buffer back */
  1083. #ifndef    NO_URGENT
  1084.                     /*
  1085.                      * There are client telnets on some
  1086.                      * operating systems get screwed up
  1087.                      * royally if we send them urgent
  1088.                      * mode data.
  1089.                      */
  1090.                     *nfrontp++ = IAC;
  1091.                     *nfrontp++ = DM;
  1092.                     neturg = nfrontp-1; /* off by one XXX */
  1093. #endif
  1094.                 }
  1095.                 if (his_state_is_will(TELOPT_LFLOW) &&
  1096.                     (ptyibuf[0] &
  1097.                      (TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))) {
  1098.                     (void) sprintf(nfrontp, "%c%c%c%c%c%c",
  1099.                         IAC, SB, TELOPT_LFLOW,
  1100.                         ptyibuf[0] & TIOCPKT_DOSTOP ? 1 : 0,
  1101.                         IAC, SE);
  1102.                     nfrontp += 6;
  1103.                 }
  1104.                 pcc--;
  1105.                 ptyip = ptyibuf+1;
  1106. #else    /* defined(CRAY2) && defined(UNICOS5) */
  1107.                 if (!uselinemode) {
  1108.                     unpcc = pcc;
  1109.                     unptyip = ptyibuf;
  1110.                     pcc = term_output(&unptyip, ptyibuf2,
  1111.                                 &unpcc, BUFSIZ);
  1112.                     ptyip = ptyibuf2;
  1113.                 } else
  1114.                     ptyip = ptyibuf;
  1115. #endif    /* defined(CRAY2) && defined(UNICOS5) */
  1116.             }
  1117.         }
  1118.  
  1119.         while (pcc > 0) {
  1120.             if ((&netobuf[BUFSIZ] - nfrontp) < 2)
  1121.                 break;
  1122.             c = *ptyip++ & 0377, pcc--;
  1123.             if (c == IAC)
  1124.                 *nfrontp++ = c;
  1125. #if    defined(CRAY2) && defined(UNICOS5)
  1126.             else if (c == '\n' &&
  1127.                      my_state_is_wont(TELOPT_BINARY) && newmap)
  1128.                 *nfrontp++ = '\r';
  1129. #endif    /* defined(CRAY2) && defined(UNICOS5) */
  1130.             *nfrontp++ = c;
  1131.             if ((c == '\r') && (my_state_is_wont(TELOPT_BINARY))) {
  1132.                 if (pcc > 0 && ((*ptyip & 0377) == '\n')) {
  1133.                     *nfrontp++ = *ptyip++ & 0377;
  1134.                     pcc--;
  1135.                 } else
  1136.                     *nfrontp++ = '\0';
  1137.             }
  1138.         }
  1139. #if    defined(CRAY2) && defined(UNICOS5)
  1140.         /*
  1141.          * If chars were left over from the terminal driver,
  1142.          * note their existence.
  1143.          */
  1144.         if (!uselinemode && unpcc) {
  1145.             pcc = unpcc;
  1146.             unpcc = 0;
  1147.             ptyip = unptyip;
  1148.         }
  1149. #endif    /* defined(CRAY2) && defined(UNICOS5) */
  1150.  
  1151.         if (FD_ISSET(f, &obits) && (nfrontp - nbackp) > 0)
  1152.             netflush();
  1153.         if (ncc > 0)
  1154.             telrcv();
  1155.         if (FD_ISSET(p, &obits) && (pfrontp - pbackp) > 0)
  1156.             ptyflush();
  1157.     }
  1158.     cleanup(0);
  1159. }  /* end of telnet */
  1160.     
  1161. #ifndef    TCSIG
  1162. # ifdef    TIOCSIG
  1163. #  define TCSIG TIOCSIG
  1164. # endif
  1165. #endif
  1166.  
  1167. /*
  1168.  * Send interrupt to process on other side of pty.
  1169.  * If it is in raw mode, just write NULL;
  1170.  * otherwise, write intr char.
  1171.  */
  1172.     void
  1173. interrupt()
  1174. {
  1175.     ptyflush();    /* half-hearted */
  1176.  
  1177. #ifdef    TCSIG
  1178.     (void) ioctl(pty, TCSIG, (char *)SIGINT);
  1179. #else    /* TCSIG */
  1180.     init_termbuf();
  1181.     *pfrontp++ = slctab[SLC_IP].sptr ?
  1182.             (unsigned char)*slctab[SLC_IP].sptr : '\177';
  1183. #endif    /* TCSIG */
  1184. }
  1185.  
  1186. /*
  1187.  * Send quit to process on other side of pty.
  1188.  * If it is in raw mode, just write NULL;
  1189.  * otherwise, write quit char.
  1190.  */
  1191.     void
  1192. sendbrk()
  1193. {
  1194.     ptyflush();    /* half-hearted */
  1195. #ifdef    TCSIG
  1196.     (void) ioctl(pty, TCSIG, (char *)SIGQUIT);
  1197. #else    /* TCSIG */
  1198.     init_termbuf();
  1199.     *pfrontp++ = slctab[SLC_ABORT].sptr ?
  1200.             (unsigned char)*slctab[SLC_ABORT].sptr : '\034';
  1201. #endif    /* TCSIG */
  1202. }
  1203.  
  1204.     void
  1205. sendsusp()
  1206. {
  1207. #ifdef    SIGTSTP
  1208.     ptyflush();    /* half-hearted */
  1209. # ifdef    TCSIG
  1210.     (void) ioctl(pty, TCSIG, (char *)SIGTSTP);
  1211. # else    /* TCSIG */
  1212.     *pfrontp++ = slctab[SLC_SUSP].sptr ?
  1213.             (unsigned char)*slctab[SLC_SUSP].sptr : '\032';
  1214. # endif    /* TCSIG */
  1215. #endif    /* SIGTSTP */
  1216. }
  1217.  
  1218. /*
  1219.  * When we get an AYT, if ^T is enabled, use that.  Otherwise,
  1220.  * just send back "[Yes]".
  1221.  */
  1222.     void
  1223. recv_ayt()
  1224. {
  1225. #if    defined(SIGINFO) && defined(TCSIG)
  1226.     if (slctab[SLC_AYT].sptr && *slctab[SLC_AYT].sptr != _POSIX_VDISABLE) {
  1227.         (void) ioctl(pty, TCSIG, (char *)SIGINFO);
  1228.         return;
  1229.     }
  1230. #endif
  1231.     (void) strcpy(nfrontp, "\r\n[Yes]\r\n");
  1232.     nfrontp += 9;
  1233. }
  1234.  
  1235.     void
  1236. doeof()
  1237. {
  1238.     init_termbuf();
  1239.  
  1240. #if    defined(LINEMODE) && defined(USE_TERMIO) && (VEOF == VMIN)
  1241.     if (!tty_isediting()) {
  1242.         extern char oldeofc;
  1243.         *pfrontp++ = oldeofc;
  1244.         return;
  1245.     }
  1246. #endif
  1247.     *pfrontp++ = slctab[SLC_EOF].sptr ?
  1248.             (unsigned char)*slctab[SLC_EOF].sptr : '\004';
  1249. }
  1250.