home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / libexec / telnetd / state.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-20  |  31.1 KB  |  1,444 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. static char sccsid[] = "@(#)state.c    5.10 (Berkeley) 3/22/91";
  36. #endif /* not lint */
  37.  
  38. #include "telnetd.h"
  39. #if    defined(AUTHENTICATE)
  40. #include <libtelnet/auth.h>
  41. #endif
  42.  
  43. char    doopt[] = { IAC, DO, '%', 'c', 0 };
  44. char    dont[] = { IAC, DONT, '%', 'c', 0 };
  45. char    will[] = { IAC, WILL, '%', 'c', 0 };
  46. char    wont[] = { IAC, WONT, '%', 'c', 0 };
  47. int    not42 = 1;
  48.  
  49. /*
  50.  * Buffer for sub-options, and macros
  51.  * for suboptions buffer manipulations
  52.  */
  53. unsigned char subbuffer[512], *subpointer= subbuffer, *subend= subbuffer;
  54.  
  55. #define    SB_CLEAR()    subpointer = subbuffer;
  56. #define    SB_TERM()    { subend = subpointer; SB_CLEAR(); }
  57. #define    SB_ACCUM(c)    if (subpointer < (subbuffer+sizeof subbuffer)) { \
  58.                 *subpointer++ = (c); \
  59.             }
  60. #define    SB_GET()    ((*subpointer++)&0xff)
  61. #define    SB_EOF()    (subpointer >= subend)
  62. #define    SB_LEN()    (subend - subpointer)
  63.  
  64.  
  65.  
  66. /*
  67.  * State for recv fsm
  68.  */
  69. #define    TS_DATA        0    /* base state */
  70. #define    TS_IAC        1    /* look for double IAC's */
  71. #define    TS_CR        2    /* CR-LF ->'s CR */
  72. #define    TS_SB        3    /* throw away begin's... */
  73. #define    TS_SE        4    /* ...end's (suboption negotiation) */
  74. #define    TS_WILL        5    /* will option negotiation */
  75. #define    TS_WONT        6    /* wont " */
  76. #define    TS_DO        7    /* do " */
  77. #define    TS_DONT        8    /* dont " */
  78.  
  79.     void
  80. telrcv()
  81. {
  82.     register int c;
  83.     static int state = TS_DATA;
  84. #if    defined(CRAY2) && defined(UNICOS5)
  85.     char *opfrontp = pfrontp;
  86. #endif
  87.  
  88.     while (ncc > 0) {
  89.         if ((&ptyobuf[BUFSIZ] - pfrontp) < 2)
  90.             break;
  91.         c = *netip++ & 0377, ncc--;
  92. #if    defined(ENCRYPT)
  93.         if (decrypt_input)
  94.             c = (*decrypt_input)(c);
  95. #endif
  96.         switch (state) {
  97.  
  98.         case TS_CR:
  99.             state = TS_DATA;
  100.             /* Strip off \n or \0 after a \r */
  101.             if ((c == 0) || (c == '\n')) {
  102.                 break;
  103.             }
  104.             /* FALL THROUGH */
  105.  
  106.         case TS_DATA:
  107.             if (c == IAC) {
  108.                 state = TS_IAC;
  109.                 break;
  110.             }
  111.             /*
  112.              * We now map \r\n ==> \r for pragmatic reasons.
  113.              * Many client implementations send \r\n when
  114.              * the user hits the CarriageReturn key.
  115.              *
  116.              * We USED to map \r\n ==> \n, since \r\n says
  117.              * that we want to be in column 1 of the next
  118.              * printable line, and \n is the standard
  119.              * unix way of saying that (\r is only good
  120.              * if CRMOD is set, which it normally is).
  121.              */
  122.             if ((c == '\r') && his_state_is_wont(TELOPT_BINARY)) {
  123.                 int nc = *netip;
  124. #if    defined(ENCRYPT)
  125.                 if (decrypt_input)
  126.                     nc = (*decrypt_input)(nc & 0xff);
  127. #endif
  128. #ifdef    LINEMODE
  129.                 /*
  130.                  * If we are operating in linemode,
  131.                  * convert to local end-of-line.
  132.                  */
  133.                 if (linemode && (ncc > 0) && (('\n' == nc) ||
  134.                      ((0 == nc) && tty_iscrnl())) ) {
  135.                     netip++; ncc--;
  136.                     c = '\n';
  137.                 } else
  138. #endif
  139.                 {
  140. #if    defined(ENCRYPT)
  141.                     if (decrypt_input)
  142.                         (void)(*decrypt_input)(-1);
  143. #endif
  144.                     state = TS_CR;
  145.                 }
  146.             }
  147.             *pfrontp++ = c;
  148.             break;
  149.  
  150.         case TS_IAC:
  151. gotiac:            switch (c) {
  152.  
  153.             /*
  154.              * Send the process on the pty side an
  155.              * interrupt.  Do this with a NULL or
  156.              * interrupt char; depending on the tty mode.
  157.              */
  158.             case IP:
  159.                 DIAG(TD_OPTIONS,
  160.                     printoption("td: recv IAC", c));
  161.                 interrupt();
  162.                 break;
  163.  
  164.             case BREAK:
  165.                 DIAG(TD_OPTIONS,
  166.                     printoption("td: recv IAC", c));
  167.                 sendbrk();
  168.                 break;
  169.  
  170.             /*
  171.              * Are You There?
  172.              */
  173.             case AYT:
  174.                 DIAG(TD_OPTIONS,
  175.                     printoption("td: recv IAC", c));
  176.                 recv_ayt();
  177.                 break;
  178.  
  179.             /*
  180.              * Abort Output
  181.              */
  182.             case AO:
  183.                 {
  184.                 DIAG(TD_OPTIONS,
  185.                     printoption("td: recv IAC", c));
  186.                 ptyflush();    /* half-hearted */
  187.                 init_termbuf();
  188.  
  189.                 if (slctab[SLC_AO].sptr &&
  190.                     *slctab[SLC_AO].sptr != (cc_t)(_POSIX_VDISABLE)) {
  191.                     *pfrontp++ =
  192.                     (unsigned char)*slctab[SLC_AO].sptr;
  193.                 }
  194.  
  195.                 netclear();    /* clear buffer back */
  196.                 *nfrontp++ = IAC;
  197.                 *nfrontp++ = DM;
  198.                 neturg = nfrontp-1; /* off by one XXX */
  199.                 DIAG(TD_OPTIONS,
  200.                     printoption("td: send IAC", DM));
  201.                 break;
  202.                 }
  203.  
  204.             /*
  205.              * Erase Character and
  206.              * Erase Line
  207.              */
  208.             case EC:
  209.             case EL:
  210.                 {
  211.                 cc_t ch;
  212.  
  213.                 DIAG(TD_OPTIONS,
  214.                     printoption("td: recv IAC", c));
  215.                 ptyflush();    /* half-hearted */
  216.                 init_termbuf();
  217.                 if (c == EC)
  218.                     ch = *slctab[SLC_EC].sptr;
  219.                 else
  220.                     ch = *slctab[SLC_EL].sptr;
  221.                 if (ch != (cc_t)(_POSIX_VDISABLE))
  222.                     *pfrontp++ = (unsigned char)ch;
  223.                 break;
  224.                 }
  225.  
  226.             /*
  227.              * Check for urgent data...
  228.              */
  229.             case DM:
  230.                 DIAG(TD_OPTIONS,
  231.                     printoption("td: recv IAC", c));
  232.                 SYNCHing = stilloob(net);
  233.                 settimer(gotDM);
  234.                 break;
  235.  
  236.  
  237.             /*
  238.              * Begin option subnegotiation...
  239.              */
  240.             case SB:
  241.                 state = TS_SB;
  242.                 SB_CLEAR();
  243.                 continue;
  244.  
  245.             case WILL:
  246.                 state = TS_WILL;
  247.                 continue;
  248.  
  249.             case WONT:
  250.                 state = TS_WONT;
  251.                 continue;
  252.  
  253.             case DO:
  254.                 state = TS_DO;
  255.                 continue;
  256.  
  257.             case DONT:
  258.                 state = TS_DONT;
  259.                 continue;
  260.             case EOR:
  261.                 if (his_state_is_will(TELOPT_EOR))
  262.                     doeof();
  263.                 break;
  264.  
  265.             /*
  266.              * Handle RFC 10xx Telnet linemode option additions
  267.              * to command stream (EOF, SUSP, ABORT).
  268.              */
  269.             case xEOF:
  270.                 doeof();
  271.                 break;
  272.  
  273.             case SUSP:
  274.                 sendsusp();
  275.                 break;
  276.  
  277.             case ABORT:
  278.                 sendbrk();
  279.                 break;
  280.  
  281.             case IAC:
  282.                 *pfrontp++ = c;
  283.                 break;
  284.             }
  285.             state = TS_DATA;
  286.             break;
  287.  
  288.         case TS_SB:
  289.             if (c == IAC) {
  290.                 state = TS_SE;
  291.             } else {
  292.                 SB_ACCUM(c);
  293.             }
  294.             break;
  295.  
  296.         case TS_SE:
  297.             if (c != SE) {
  298.                 if (c != IAC) {
  299.                     /*
  300.                      * bad form of suboption negotiation.
  301.                      * handle it in such a way as to avoid
  302.                      * damage to local state.  Parse
  303.                      * suboption buffer found so far,
  304.                      * then treat remaining stream as
  305.                      * another command sequence.
  306.                      */
  307.  
  308.                     /* for DIAGNOSTICS */
  309.                     SB_ACCUM(IAC);
  310.                     SB_ACCUM(c);
  311.                     subpointer -= 2;
  312.  
  313.                     SB_TERM();
  314.                     suboption();
  315.                     state = TS_IAC;
  316.                     goto gotiac;
  317.                 }
  318.                 SB_ACCUM(c);
  319.                 state = TS_SB;
  320.             } else {
  321.                 /* for DIAGNOSTICS */
  322.                 SB_ACCUM(IAC);
  323.                 SB_ACCUM(SE);
  324.                 subpointer -= 2;
  325.  
  326.                 SB_TERM();
  327.                 suboption();    /* handle sub-option */
  328.                 state = TS_DATA;
  329.             }
  330.             break;
  331.  
  332.         case TS_WILL:
  333.             willoption(c);
  334.             state = TS_DATA;
  335.             continue;
  336.  
  337.         case TS_WONT:
  338.             wontoption(c);
  339.             state = TS_DATA;
  340.             continue;
  341.  
  342.         case TS_DO:
  343.             dooption(c);
  344.             state = TS_DATA;
  345.             continue;
  346.  
  347.         case TS_DONT:
  348.             dontoption(c);
  349.             state = TS_DATA;
  350.             continue;
  351.  
  352.         default:
  353.             syslog(LOG_ERR, "telnetd: panic state=%d\n", state);
  354.             printf("telnetd: panic state=%d\n", state);
  355.             exit(1);
  356.         }
  357.     }
  358. #if    defined(CRAY2) && defined(UNICOS5)
  359.     if (!linemode) {
  360.         char    xptyobuf[BUFSIZ+NETSLOP];
  361.         char    xbuf2[BUFSIZ];
  362.         register char *cp;
  363.         int n = pfrontp - opfrontp, oc;
  364.         bcopy(opfrontp, xptyobuf, n);
  365.         pfrontp = opfrontp;
  366.         pfrontp += term_input(xptyobuf, pfrontp, n, BUFSIZ+NETSLOP,
  367.                     xbuf2, &oc, BUFSIZ);
  368.         for (cp = xbuf2; oc > 0; --oc)
  369.             if ((*nfrontp++ = *cp++) == IAC)
  370.                 *nfrontp++ = IAC;
  371.     }
  372. #endif    /* defined(CRAY2) && defined(UNICOS5) */
  373. }  /* end of telrcv */
  374.  
  375. /*
  376.  * The will/wont/do/dont state machines are based on Dave Borman's
  377.  * Telnet option processing state machine.
  378.  *
  379.  * These correspond to the following states:
  380.  *    my_state = the last negotiated state
  381.  *    want_state = what I want the state to go to
  382.  *    want_resp = how many requests I have sent
  383.  * All state defaults are negative, and resp defaults to 0.
  384.  *
  385.  * When initiating a request to change state to new_state:
  386.  * 
  387.  * if ((want_resp == 0 && new_state == my_state) || want_state == new_state) {
  388.  *    do nothing;
  389.  * } else {
  390.  *    want_state = new_state;
  391.  *    send new_state;
  392.  *    want_resp++;
  393.  * }
  394.  *
  395.  * When receiving new_state:
  396.  *
  397.  * if (want_resp) {
  398.  *    want_resp--;
  399.  *    if (want_resp && (new_state == my_state))
  400.  *        want_resp--;
  401.  * }
  402.  * if ((want_resp == 0) && (new_state != want_state)) {
  403.  *    if (ok_to_switch_to new_state)
  404.  *        want_state = new_state;
  405.  *    else
  406.  *        want_resp++;
  407.  *    send want_state;
  408.  * }
  409.  * my_state = new_state;
  410.  *
  411.  * Note that new_state is implied in these functions by the function itself.
  412.  * will and do imply positive new_state, wont and dont imply negative.
  413.  *
  414.  * Finally, there is one catch.  If we send a negative response to a
  415.  * positive request, my_state will be the positive while want_state will
  416.  * remain negative.  my_state will revert to negative when the negative
  417.  * acknowlegment arrives from the peer.  Thus, my_state generally tells
  418.  * us not only the last negotiated state, but also tells us what the peer
  419.  * wants to be doing as well.  It is important to understand this difference
  420.  * as we may wish to be processing data streams based on our desired state
  421.  * (want_state) or based on what the peer thinks the state is (my_state).
  422.  *
  423.  * This all works fine because if the peer sends a positive request, the data
  424.  * that we receive prior to negative acknowlegment will probably be affected
  425.  * by the positive state, and we can process it as such (if we can; if we
  426.  * can't then it really doesn't matter).  If it is that important, then the
  427.  * peer probably should be buffering until this option state negotiation
  428.  * is complete.
  429.  *
  430.  */
  431.     void
  432. send_do(option, init)
  433.     int option, init;
  434. {
  435.     if (init) {
  436.         if ((do_dont_resp[option] == 0 && his_state_is_will(option)) ||
  437.             his_want_state_is_will(option))
  438.             return;
  439.         /*
  440.          * Special case for TELOPT_TM:  We send a DO, but pretend
  441.          * that we sent a DONT, so that we can send more DOs if
  442.          * we want to.
  443.          */
  444.         if (option == TELOPT_TM)
  445.             set_his_want_state_wont(option);
  446.         else
  447.             set_his_want_state_will(option);
  448.         do_dont_resp[option]++;
  449.     }
  450.     (void) sprintf(nfrontp, doopt, option);
  451.     nfrontp += sizeof (dont) - 2;
  452.  
  453.     DIAG(TD_OPTIONS, printoption("td: send do", option));
  454. }
  455.  
  456. #ifdef    AUTHENTICATE
  457. extern void auth_request();
  458. #endif
  459. #ifdef    LINEMODE
  460. extern void doclientstat();
  461. #endif
  462. #ifdef    ENCRYPT
  463. extern void encrypt_send_support();
  464. #endif
  465.  
  466.     void
  467. willoption(option)
  468.     int option;
  469. {
  470.     int changeok = 0;
  471.     void (*func)() = 0;
  472.  
  473.     /*
  474.      * process input from peer.
  475.      */
  476.  
  477.     DIAG(TD_OPTIONS, printoption("td: recv will", option));
  478.  
  479.     if (do_dont_resp[option]) {
  480.         do_dont_resp[option]--;
  481.         if (do_dont_resp[option] && his_state_is_will(option))
  482.             do_dont_resp[option]--;
  483.     }
  484.     if (do_dont_resp[option] == 0) {
  485.         if (his_want_state_is_wont(option)) {
  486.         switch (option) {
  487.  
  488.         case TELOPT_BINARY:
  489.             init_termbuf();
  490.             tty_binaryin(1);
  491.             set_termbuf();
  492.             changeok++;
  493.             break;
  494.  
  495.         case TELOPT_ECHO:
  496.             /*
  497.              * See comments below for more info.
  498.              */
  499.             not42 = 0;    /* looks like a 4.2 system */
  500.             break;
  501.  
  502.         case TELOPT_TM:
  503. #if    defined(LINEMODE) && defined(KLUDGELINEMODE)
  504.             /*
  505.              * This telnetd implementation does not really
  506.              * support timing marks, it just uses them to
  507.              * support the kludge linemode stuff.  If we
  508.              * receive a will or wont TM in response to our
  509.              * do TM request that may have been sent to
  510.              * determine kludge linemode support, process
  511.              * it, otherwise TM should get a negative
  512.              * response back.
  513.              */
  514.             /*
  515.              * Handle the linemode kludge stuff.
  516.              * If we are not currently supporting any
  517.              * linemode at all, then we assume that this
  518.              * is the client telling us to use kludge
  519.              * linemode in response to our query.  Set the
  520.              * linemode type that is to be supported, note
  521.              * that the client wishes to use linemode, and
  522.              * eat the will TM as though it never arrived.
  523.              */
  524.             if (lmodetype < KLUDGE_LINEMODE) {
  525.                 lmodetype = KLUDGE_LINEMODE;
  526.                 clientstat(TELOPT_LINEMODE, WILL, 0);
  527.                 send_wont(TELOPT_SGA, 1);
  528.             }
  529. #endif    /* defined(LINEMODE) && defined(KLUDGELINEMODE) */
  530.             /*
  531.              * We never respond to a WILL TM, and
  532.              * we leave the state WONT.
  533.              */
  534.             return;
  535.  
  536.         case TELOPT_LFLOW:
  537.             /*
  538.              * If we are going to support flow control
  539.              * option, then don't worry peer that we can't
  540.              * change the flow control characters.
  541.              */
  542.             slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS;
  543.             slctab[SLC_XON].defset.flag |= SLC_DEFAULT;
  544.             slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS;
  545.             slctab[SLC_XOFF].defset.flag |= SLC_DEFAULT;
  546.         case TELOPT_TTYPE:
  547.         case TELOPT_SGA:
  548.         case TELOPT_NAWS:
  549.         case TELOPT_TSPEED:
  550.         case TELOPT_XDISPLOC:
  551.         case TELOPT_ENVIRON:
  552.             changeok++;
  553.             break;
  554.  
  555. #ifdef    LINEMODE
  556.         case TELOPT_LINEMODE:
  557. # ifdef    KLUDGELINEMODE
  558.             /*
  559.              * Note client's desire to use linemode.
  560.              */
  561.             lmodetype = REAL_LINEMODE;
  562. # endif    /* KLUDGELINEMODE */
  563.             func = doclientstat;
  564.             changeok++;
  565.             break;
  566. #endif    /* LINEMODE */
  567.  
  568. #ifdef    AUTHENTICATE
  569.         case TELOPT_AUTHENTICATION:
  570.             func = auth_request;
  571.             changeok++;
  572.             break;
  573. #endif
  574.  
  575. #ifdef    ENCRYPT
  576.         case TELOPT_ENCRYPT:
  577.             func = encrypt_send_support;
  578.             changeok++;
  579.             break;
  580. #endif
  581.  
  582.         default:
  583.             break;
  584.         }
  585.         if (changeok) {
  586.             set_his_want_state_will(option);
  587.             send_do(option, 0);
  588.         } else {
  589.             do_dont_resp[option]++;
  590.             send_dont(option, 0);
  591.         }
  592.         } else {
  593.         /*
  594.          * Option processing that should happen when
  595.          * we receive conformation of a change in
  596.          * state that we had requested.
  597.          */
  598.         switch (option) {
  599.         case TELOPT_ECHO:
  600.             not42 = 0;    /* looks like a 4.2 system */
  601.             /*
  602.              * Egads, he responded "WILL ECHO".  Turn
  603.              * it off right now!
  604.              */
  605.             send_dont(option, 1);
  606.             /*
  607.              * "WILL ECHO".  Kludge upon kludge!
  608.              * A 4.2 client is now echoing user input at
  609.              * the tty.  This is probably undesireable and
  610.              * it should be stopped.  The client will
  611.              * respond WONT TM to the DO TM that we send to
  612.              * check for kludge linemode.  When the WONT TM
  613.              * arrives, linemode will be turned off and a
  614.              * change propogated to the pty.  This change
  615.              * will cause us to process the new pty state
  616.              * in localstat(), which will notice that
  617.              * linemode is off and send a WILL ECHO
  618.              * so that we are properly in character mode and
  619.              * all is well.
  620.              */
  621.             break;
  622. #ifdef    LINEMODE
  623.         case TELOPT_LINEMODE:
  624. # ifdef    KLUDGELINEMODE
  625.             /*
  626.              * Note client's desire to use linemode.
  627.              */
  628.             lmodetype = REAL_LINEMODE;
  629. # endif    /* KLUDGELINEMODE */
  630.             func = doclientstat;
  631.             break;
  632. #endif    /* LINEMODE */
  633.  
  634. #ifdef    AUTHENTICATE
  635.         case TELOPT_AUTHENTICATION:
  636.             func = auth_request;
  637.             break;
  638. #endif
  639.  
  640. #ifdef    ENCRYPT
  641.         case TELOPT_ENCRYPT:
  642.             func = encrypt_send_support;
  643.             break;
  644. #endif
  645.         }
  646.         }
  647.     }
  648.     set_his_state_will(option);
  649.     if (func)
  650.         (*func)();
  651. }  /* end of willoption */
  652.  
  653.     void
  654. send_dont(option, init)
  655.     int option, init;
  656. {
  657.     if (init) {
  658.         if ((do_dont_resp[option] == 0 && his_state_is_wont(option)) ||
  659.             his_want_state_is_wont(option))
  660.             return;
  661.         set_his_want_state_wont(option);
  662.         do_dont_resp[option]++;
  663.     }
  664.     (void) sprintf(nfrontp, dont, option);
  665.     nfrontp += sizeof (doopt) - 2;
  666.  
  667.     DIAG(TD_OPTIONS, printoption("td: send dont", option));
  668. }
  669.  
  670.     void
  671. wontoption(option)
  672.     int option;
  673. {
  674.     /*
  675.      * Process client input.
  676.      */
  677.  
  678.     DIAG(TD_OPTIONS, printoption("td: recv wont", option));
  679.  
  680.     if (do_dont_resp[option]) {
  681.         do_dont_resp[option]--;
  682.         if (do_dont_resp[option] && his_state_is_wont(option))
  683.             do_dont_resp[option]--;
  684.     }
  685.     if (do_dont_resp[option] == 0) {
  686.         if (his_want_state_is_will(option)) {
  687.         /* it is always ok to change to negative state */
  688.         switch (option) {
  689.         case TELOPT_ECHO:
  690.             not42 = 1; /* doesn't seem to be a 4.2 system */
  691.             break;
  692.  
  693.         case TELOPT_BINARY:
  694.             init_termbuf();
  695.             tty_binaryin(0);
  696.             set_termbuf();
  697.             break;
  698.  
  699. #ifdef    LINEMODE
  700.         case TELOPT_LINEMODE:
  701. # ifdef    KLUDGELINEMODE
  702.             /*
  703.              * If real linemode is supported, then client is
  704.              * asking to turn linemode off.
  705.              */
  706.             if (lmodetype != REAL_LINEMODE)
  707.                 break;
  708.             lmodetype = KLUDGE_LINEMODE;
  709. # endif    /* KLUDGELINEMODE */
  710.             clientstat(TELOPT_LINEMODE, WONT, 0);
  711.             break;
  712. #endif    /* LINEMODE */
  713.  
  714.         case TELOPT_TM:
  715.             /*
  716.              * If we get a WONT TM, and had sent a DO TM,
  717.              * don't respond with a DONT TM, just leave it
  718.              * as is.  Short circut the state machine to
  719.              * achive this.
  720.              */
  721.             set_his_want_state_wont(TELOPT_TM);
  722.             return;
  723.  
  724.         case TELOPT_LFLOW:
  725.             /*
  726.              * If we are not going to support flow control
  727.              * option, then let peer know that we can't
  728.              * change the flow control characters.
  729.              */
  730.             slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS;
  731.             slctab[SLC_XON].defset.flag |= SLC_CANTCHANGE;
  732.             slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS;
  733.             slctab[SLC_XOFF].defset.flag |= SLC_CANTCHANGE;
  734.             break;
  735.  
  736. #if    defined(AUTHENTICATE)
  737.         case TELOPT_AUTHENTICATION:
  738.             auth_finished(0, AUTH_REJECT);
  739.             break;
  740. #endif
  741.  
  742.         /*
  743.          * For options that we might spin waiting for
  744.          * sub-negotiation, if the client turns off the
  745.          * option rather than responding to the request,
  746.          * we have to treat it here as if we got a response
  747.          * to the sub-negotiation, (by updating the timers)
  748.          * so that we'll break out of the loop.
  749.          */
  750.         case TELOPT_TTYPE:
  751.             settimer(ttypesubopt);
  752.             break;
  753.  
  754.         case TELOPT_TSPEED:
  755.             settimer(tspeedsubopt);
  756.             break;
  757.  
  758.         case TELOPT_XDISPLOC:
  759.             settimer(xdisplocsubopt);
  760.             break;
  761.  
  762.         case TELOPT_ENVIRON:
  763.             settimer(environsubopt);
  764.             break;
  765.  
  766.         default:
  767.             break;
  768.         }
  769.         set_his_want_state_wont(option);
  770.         if (his_state_is_will(option))
  771.             send_dont(option, 0);
  772.         } else {
  773.         switch (option) {
  774.         case TELOPT_TM:
  775. #if    defined(LINEMODE) && defined(KLUDGELINEMODE)
  776.             if (lmodetype < REAL_LINEMODE) {
  777.                 lmodetype = NO_LINEMODE;
  778.                 clientstat(TELOPT_LINEMODE, WONT, 0);
  779.                 send_will(TELOPT_SGA, 1);
  780.                 send_will(TELOPT_ECHO, 1);
  781.             }
  782. #endif    /* defined(LINEMODE) && defined(KLUDGELINEMODE) */
  783.             break;
  784.  
  785. #if    defined(AUTHENTICATE)
  786.         case TELOPT_AUTHENTICATION:
  787.             auth_finished(0, AUTH_REJECT);
  788.             break;
  789. #endif
  790.         default:
  791.             break;
  792.         }
  793.         }
  794.     }
  795.     set_his_state_wont(option);
  796.  
  797. }  /* end of wontoption */
  798.  
  799.     void
  800. send_will(option, init)
  801.     int option, init;
  802. {
  803.     if (init) {
  804.         if ((will_wont_resp[option] == 0 && my_state_is_will(option))||
  805.             my_want_state_is_will(option))
  806.             return;
  807.         set_my_want_state_will(option);
  808.         will_wont_resp[option]++;
  809.     }
  810.     (void) sprintf(nfrontp, will, option);
  811.     nfrontp += sizeof (doopt) - 2;
  812.  
  813.     DIAG(TD_OPTIONS, printoption("td: send will", option));
  814. }
  815.  
  816. #if    !defined(LINEMODE) || !defined(KLUDGELINEMODE)
  817. /*
  818.  * When we get a DONT SGA, we will try once to turn it
  819.  * back on.  If the other side responds DONT SGA, we
  820.  * leave it at that.  This is so that when we talk to
  821.  * clients that understand KLUDGELINEMODE but not LINEMODE,
  822.  * we'll keep them in char-at-a-time mode.
  823.  */
  824. int turn_on_sga = 0;
  825. #endif
  826.  
  827.     void
  828. dooption(option)
  829.     int option;
  830. {
  831.     int changeok = 0;
  832.  
  833.     /*
  834.      * Process client input.
  835.      */
  836.  
  837.     DIAG(TD_OPTIONS, printoption("td: recv do", option));
  838.  
  839.     if (will_wont_resp[option]) {
  840.         will_wont_resp[option]--;
  841.         if (will_wont_resp[option] && my_state_is_will(option))
  842.             will_wont_resp[option]--;
  843.     }
  844.     if ((will_wont_resp[option] == 0) && (my_want_state_is_wont(option))) {
  845.         switch (option) {
  846.         case TELOPT_ECHO:
  847. #ifdef    LINEMODE
  848. # ifdef    KLUDGELINEMODE
  849.             if (lmodetype == NO_LINEMODE)
  850. # else
  851.             if (his_state_is_wont(TELOPT_LINEMODE))
  852. # endif
  853. #endif
  854.             {
  855.                 init_termbuf();
  856.                 tty_setecho(1);
  857.                 set_termbuf();
  858.             }
  859.             changeok++;
  860.             break;
  861.  
  862.         case TELOPT_BINARY:
  863.             init_termbuf();
  864.             tty_binaryout(1);
  865.             set_termbuf();
  866.             changeok++;
  867.             break;
  868.  
  869.         case TELOPT_SGA:
  870. #if    defined(LINEMODE) && defined(KLUDGELINEMODE)
  871.             /*
  872.              * If kludge linemode is in use, then we must
  873.              * process an incoming do SGA for linemode
  874.              * purposes.
  875.              */
  876.             if (lmodetype == KLUDGE_LINEMODE) {
  877.                 /*
  878.                  * Receipt of "do SGA" in kludge
  879.                  * linemode is the peer asking us to
  880.                  * turn off linemode.  Make note of
  881.                  * the request.
  882.                  */
  883.                 clientstat(TELOPT_LINEMODE, WONT, 0);
  884.                 /*
  885.                  * If linemode did not get turned off
  886.                  * then don't tell peer that we did.
  887.                  * Breaking here forces a wont SGA to
  888.                  * be returned.
  889.                  */
  890.                 if (linemode)
  891.                     break;
  892.             }
  893. #else
  894.             turn_on_sga = 0;
  895. #endif    /* defined(LINEMODE) && defined(KLUDGELINEMODE) */
  896.             changeok++;
  897.             break;
  898.  
  899.         case TELOPT_STATUS:
  900.             changeok++;
  901.             break;
  902.  
  903.         case TELOPT_TM:
  904.             /*
  905.              * Special case for TM.  We send a WILL, but
  906.              * pretend we sent a WONT.
  907.              */
  908.             send_will(option, 0);
  909.             set_my_want_state_wont(option);
  910.             set_my_state_wont(option);
  911.             return;
  912.  
  913.         case TELOPT_LOGOUT:
  914.             /*
  915.              * When we get a LOGOUT option, respond
  916.              * with a WILL LOGOUT, make sure that
  917.              * it gets written out to the network,
  918.              * and then just go away...
  919.              */
  920.             set_my_want_state_will(TELOPT_LOGOUT);
  921.             send_will(TELOPT_LOGOUT, 0);
  922.             set_my_state_will(TELOPT_LOGOUT);
  923.             (void)netflush();
  924.             cleanup(0);
  925.             /* NOT REACHED */
  926.             break;
  927.  
  928. #if    defined(ENCRYPT)
  929.         case TELOPT_ENCRYPT:
  930.             changeok++;
  931.             break;
  932. #endif
  933.         case TELOPT_LINEMODE:
  934.         case TELOPT_TTYPE:
  935.         case TELOPT_NAWS:
  936.         case TELOPT_TSPEED:
  937.         case TELOPT_LFLOW:
  938.         case TELOPT_XDISPLOC:
  939.         case TELOPT_ENVIRON:
  940.         default:
  941.             break;
  942.         }
  943.         if (changeok) {
  944.             set_my_want_state_will(option);
  945.             send_will(option, 0);
  946.         } else {
  947.             will_wont_resp[option]++;
  948.             send_wont(option, 0);
  949.         }
  950.     }
  951.     set_my_state_will(option);
  952.  
  953. }  /* end of dooption */
  954.  
  955.     void
  956. send_wont(option, init)
  957.     int option, init;
  958. {
  959.     if (init) {
  960.         if ((will_wont_resp[option] == 0 && my_state_is_wont(option)) ||
  961.             my_want_state_is_wont(option))
  962.             return;
  963.         set_my_want_state_wont(option);
  964.         will_wont_resp[option]++;
  965.     }
  966.     (void) sprintf(nfrontp, wont, option);
  967.     nfrontp += sizeof (wont) - 2;
  968.  
  969.     DIAG(TD_OPTIONS, printoption("td: send wont", option));
  970. }
  971.  
  972.     void
  973. dontoption(option)
  974.     int option;
  975. {
  976.     /*
  977.      * Process client input.
  978.      */
  979.  
  980.  
  981.     DIAG(TD_OPTIONS, printoption("td: recv dont", option));
  982.  
  983.     if (will_wont_resp[option]) {
  984.         will_wont_resp[option]--;
  985.         if (will_wont_resp[option] && my_state_is_wont(option))
  986.             will_wont_resp[option]--;
  987.     }
  988.     if ((will_wont_resp[option] == 0) && (my_want_state_is_will(option))) {
  989.         switch (option) {
  990.         case TELOPT_BINARY:
  991.             init_termbuf();
  992.             tty_binaryout(0);
  993.             set_termbuf();
  994.             break;
  995.  
  996.         case TELOPT_ECHO:    /* we should stop echoing */
  997. #ifdef    LINEMODE
  998. # ifdef    KLUDGELINEMODE
  999.             if (lmodetype == NO_LINEMODE)
  1000. # else
  1001.             if (his_state_is_wont(TELOPT_LINEMODE))
  1002. # endif
  1003. #endif
  1004.             {
  1005.                 init_termbuf();
  1006.                 tty_setecho(0);
  1007.                 set_termbuf();
  1008.             }
  1009.             break;
  1010.  
  1011.         case TELOPT_SGA:
  1012. #if    defined(LINEMODE) && defined(KLUDGELINEMODE)
  1013.             /*
  1014.              * If kludge linemode is in use, then we
  1015.              * must process an incoming do SGA for
  1016.              * linemode purposes.
  1017.              */
  1018.             if (lmodetype == KLUDGE_LINEMODE) {
  1019.                 /*
  1020.                  * The client is asking us to turn
  1021.                  * linemode on.
  1022.                  */
  1023.                 clientstat(TELOPT_LINEMODE, WILL, 0);
  1024.                 /*
  1025.                  * If we did not turn line mode on,
  1026.                  * then what do we say?  Will SGA?
  1027.                  * This violates design of telnet.
  1028.                  * Gross.  Very Gross.
  1029.                  */
  1030.             }
  1031.             break;
  1032. #else
  1033.             set_my_want_state_wont(option);
  1034.             if (my_state_is_will(option))
  1035.                 send_wont(option, 0);
  1036.             set_my_state_wont(option);
  1037.             if (turn_on_sga ^= 1)
  1038.                 send_will(option);
  1039.             return;
  1040. #endif    /* defined(LINEMODE) && defined(KLUDGELINEMODE) */
  1041.  
  1042.         default:
  1043.             break;
  1044.         }
  1045.  
  1046.         set_my_want_state_wont(option);
  1047.         if (my_state_is_will(option))
  1048.             send_wont(option, 0);
  1049.     }
  1050.     set_my_state_wont(option);
  1051.  
  1052. }  /* end of dontoption */
  1053.  
  1054. /*
  1055.  * suboption()
  1056.  *
  1057.  *    Look at the sub-option buffer, and try to be helpful to the other
  1058.  * side.
  1059.  *
  1060.  *    Currently we recognize:
  1061.  *
  1062.  *    Terminal type is
  1063.  *    Linemode
  1064.  *    Window size
  1065.  *    Terminal speed
  1066.  */
  1067.     void
  1068. suboption()
  1069. {
  1070.     register int subchar;
  1071.  
  1072.     DIAG(TD_OPTIONS, {netflush(); printsub('<', subpointer, SB_LEN()+2);});
  1073.  
  1074.     subchar = SB_GET();
  1075.     switch (subchar) {
  1076.     case TELOPT_TSPEED: {
  1077.     register int xspeed, rspeed;
  1078.  
  1079.     if (his_state_is_wont(TELOPT_TSPEED))    /* Ignore if option disabled */
  1080.         break;
  1081.  
  1082.     settimer(tspeedsubopt);
  1083.  
  1084.     if (SB_EOF() || SB_GET() != TELQUAL_IS)
  1085.         return;
  1086.  
  1087.     xspeed = atoi((char *)subpointer);
  1088.  
  1089.     while (SB_GET() != ',' && !SB_EOF());
  1090.     if (SB_EOF())
  1091.         return;
  1092.  
  1093.     rspeed = atoi((char *)subpointer);
  1094.     clientstat(TELOPT_TSPEED, xspeed, rspeed);
  1095.  
  1096.     break;
  1097.  
  1098.     }  /* end of case TELOPT_TSPEED */
  1099.  
  1100.     case TELOPT_TTYPE: {        /* Yaaaay! */
  1101.     static char terminalname[41];
  1102.  
  1103.     if (his_state_is_wont(TELOPT_TTYPE))    /* Ignore if option disabled */
  1104.         break;
  1105.     settimer(ttypesubopt);
  1106.  
  1107.     if (SB_EOF() || SB_GET() != TELQUAL_IS) {
  1108.         return;        /* ??? XXX but, this is the most robust */
  1109.     }
  1110.  
  1111.     terminaltype = terminalname;
  1112.  
  1113.     while ((terminaltype < (terminalname + sizeof terminalname-1)) &&
  1114.                                     !SB_EOF()) {
  1115.         register int c;
  1116.  
  1117.         c = SB_GET();
  1118.         if (isupper(c)) {
  1119.         c = tolower(c);
  1120.         }
  1121.         *terminaltype++ = c;    /* accumulate name */
  1122.     }
  1123.     *terminaltype = 0;
  1124.     terminaltype = terminalname;
  1125.     break;
  1126.     }  /* end of case TELOPT_TTYPE */
  1127.  
  1128.     case TELOPT_NAWS: {
  1129.     register int xwinsize, ywinsize;
  1130.  
  1131.     if (his_state_is_wont(TELOPT_NAWS))    /* Ignore if option disabled */
  1132.         break;
  1133.  
  1134.     if (SB_EOF())
  1135.         return;
  1136.     xwinsize = SB_GET() << 8;
  1137.     if (SB_EOF())
  1138.         return;
  1139.     xwinsize |= SB_GET();
  1140.     if (SB_EOF())
  1141.         return;
  1142.     ywinsize = SB_GET() << 8;
  1143.     if (SB_EOF())
  1144.         return;
  1145.     ywinsize |= SB_GET();
  1146.     clientstat(TELOPT_NAWS, xwinsize, ywinsize);
  1147.  
  1148.     break;
  1149.  
  1150.     }  /* end of case TELOPT_NAWS */
  1151.  
  1152. #ifdef    LINEMODE
  1153.     case TELOPT_LINEMODE: {
  1154.     register int request;
  1155.  
  1156.     if (his_state_is_wont(TELOPT_LINEMODE))    /* Ignore if option disabled */
  1157.         break;
  1158.     /*
  1159.      * Process linemode suboptions.
  1160.      */
  1161.     if (SB_EOF())
  1162.         break;        /* garbage was sent */
  1163.     request = SB_GET();    /* get will/wont */
  1164.  
  1165.     if (SB_EOF())
  1166.         break;        /* another garbage check */
  1167.  
  1168.     if (request == LM_SLC) {  /* SLC is not preceeded by WILL or WONT */
  1169.         /*
  1170.          * Process suboption buffer of slc's
  1171.          */
  1172.         start_slc(1);
  1173.         do_opt_slc(subpointer, subend - subpointer);
  1174.         (void) end_slc(0);
  1175.         break;
  1176.     } else if (request == LM_MODE) {
  1177.         if (SB_EOF())
  1178.             return;
  1179.         useeditmode = SB_GET();  /* get mode flag */
  1180.         clientstat(LM_MODE, 0, 0);
  1181.         break;
  1182.     }
  1183.  
  1184.     if (SB_EOF())
  1185.         break;
  1186.     switch (SB_GET()) {  /* what suboption? */
  1187.     case LM_FORWARDMASK:
  1188.         /*
  1189.          * According to spec, only server can send request for
  1190.          * forwardmask, and client can only return a positive response.
  1191.          * So don't worry about it.
  1192.          */
  1193.  
  1194.     default:
  1195.         break;
  1196.     }
  1197.     break;
  1198.     }  /* end of case TELOPT_LINEMODE */
  1199. #endif
  1200.     case TELOPT_STATUS: {
  1201.     int mode;
  1202.  
  1203.     if (SB_EOF())
  1204.         break;
  1205.     mode = SB_GET();
  1206.     switch (mode) {
  1207.     case TELQUAL_SEND:
  1208.         if (my_state_is_will(TELOPT_STATUS))
  1209.         send_status();
  1210.         break;
  1211.  
  1212.     case TELQUAL_IS:
  1213.         break;
  1214.  
  1215.     default:
  1216.         break;
  1217.     }
  1218.     break;
  1219.     }  /* end of case TELOPT_STATUS */
  1220.  
  1221.     case TELOPT_XDISPLOC: {
  1222.     if (SB_EOF() || SB_GET() != TELQUAL_IS)
  1223.         return;
  1224.     settimer(xdisplocsubopt);
  1225.     subpointer[SB_LEN()] = '\0';
  1226.     (void)setenv("DISPLAY", (char *)subpointer, 1);
  1227.     break;
  1228.     }  /* end of case TELOPT_XDISPLOC */
  1229.  
  1230.     case TELOPT_ENVIRON: {
  1231.     register int c;
  1232.     register char *cp, *varp, *valp;
  1233.  
  1234.     if (SB_EOF())
  1235.         return;
  1236.     c = SB_GET();
  1237.     if (c == TELQUAL_IS)
  1238.         settimer(environsubopt);
  1239.     else if (c != TELQUAL_INFO)
  1240.         return;
  1241.  
  1242.     while (!SB_EOF() && SB_GET() != ENV_VAR)
  1243.         ;
  1244.  
  1245.     if (SB_EOF())
  1246.         return;
  1247.  
  1248.     cp = varp = (char *)subpointer;
  1249.     valp = 0;
  1250.  
  1251.     while (!SB_EOF()) {
  1252.         switch (c = SB_GET()) {
  1253.         case ENV_VALUE:
  1254.             *cp = '\0';
  1255.             cp = valp = (char *)subpointer;
  1256.             break;
  1257.  
  1258.         case ENV_VAR:
  1259.             *cp = '\0';
  1260.             if (valp)
  1261.                 (void)setenv(varp, valp, 1);
  1262.             else
  1263.                 unsetenv(varp);
  1264.             cp = varp = (char *)subpointer;
  1265.             valp = 0;
  1266.             break;
  1267.  
  1268.         case ENV_ESC:
  1269.             if (SB_EOF())
  1270.                 break;
  1271.             c = SB_GET();
  1272.             /* FALL THROUGH */
  1273.         default:
  1274.             *cp++ = c;
  1275.             break;
  1276.         }
  1277.     }
  1278.     *cp = '\0';
  1279.     if (valp)
  1280.         (void)setenv(varp, valp, 1);
  1281.     else
  1282.         unsetenv(varp);
  1283.     break;
  1284.     }  /* end of case TELOPT_ENVIRON */
  1285. #if    defined(AUTHENTICATE)
  1286.     case TELOPT_AUTHENTICATION:
  1287.     if (SB_EOF())
  1288.         break;
  1289.     switch(SB_GET()) {
  1290.     case TELQUAL_SEND:
  1291.     case TELQUAL_REPLY:
  1292.         /*
  1293.          * These are sent by us and cannot be sent by
  1294.          * the client.
  1295.          */
  1296.         break;
  1297.     case TELQUAL_IS:
  1298.         auth_is(subpointer, SB_LEN());
  1299.         break;
  1300.     case TELQUAL_NAME:
  1301.         auth_name(subpointer, SB_LEN());
  1302.         break;
  1303.     }
  1304.     break;
  1305. #endif
  1306. #if    defined(ENCRYPT)
  1307.     case TELOPT_ENCRYPT:
  1308.     if (SB_EOF())
  1309.         break;
  1310.     switch(SB_GET()) {
  1311.     case ENCRYPT_SUPPORT:
  1312.         encrypt_support(subpointer, SB_LEN());
  1313.         break;
  1314.     case ENCRYPT_IS:
  1315.         encrypt_is(subpointer, SB_LEN());
  1316.         break;
  1317.     case ENCRYPT_REPLY:
  1318.         encrypt_reply(subpointer, SB_LEN());
  1319.         break;
  1320.     case ENCRYPT_START:
  1321.         encrypt_start(subpointer, SB_LEN());
  1322.         break;
  1323.     case ENCRYPT_END:
  1324.         encrypt_end();
  1325.         break;
  1326.     case ENCRYPT_REQSTART:
  1327.         encrypt_request_start(subpointer, SB_LEN());
  1328.         break;
  1329.     case ENCRYPT_REQEND:
  1330.         /*
  1331.          * We can always send an REQEND so that we cannot
  1332.          * get stuck encrypting.  We should only get this
  1333.          * if we have been able to get in the correct mode
  1334.          * anyhow.
  1335.          */
  1336.         encrypt_request_end();
  1337.         break;
  1338.     case ENCRYPT_ENC_KEYID:
  1339.         encrypt_enc_keyid(subpointer, SB_LEN());
  1340.         break;
  1341.     case ENCRYPT_DEC_KEYID:
  1342.         encrypt_dec_keyid(subpointer, SB_LEN());
  1343.         break;
  1344.     default:
  1345.         break;
  1346.     }
  1347.     break;
  1348. #endif
  1349.  
  1350.     default:
  1351.     break;
  1352.     }  /* end of switch */
  1353.  
  1354. }  /* end of suboption */
  1355.  
  1356.     void
  1357. doclientstat()
  1358. {
  1359.     clientstat(TELOPT_LINEMODE, WILL, 0);
  1360. }
  1361.  
  1362. #define    ADD(c)     *ncp++ = c;
  1363. #define    ADD_DATA(c) { *ncp++ = c; if (c == SE) *ncp++ = c; }
  1364.     void
  1365. send_status()
  1366. {
  1367.     unsigned char statusbuf[256];
  1368.     register unsigned char *ncp;
  1369.     register unsigned char i;
  1370.  
  1371.     ncp = statusbuf;
  1372.  
  1373.     netflush();    /* get rid of anything waiting to go out */
  1374.  
  1375.     ADD(IAC);
  1376.     ADD(SB);
  1377.     ADD(TELOPT_STATUS);
  1378.     ADD(TELQUAL_IS);
  1379.  
  1380.     /*
  1381.      * We check the want_state rather than the current state,
  1382.      * because if we received a DO/WILL for an option that we
  1383.      * don't support, and the other side didn't send a DONT/WONT
  1384.      * in response to our WONT/DONT, then the "state" will be
  1385.      * WILL/DO, and the "want_state" will be WONT/DONT.  We
  1386.      * need to go by the latter.
  1387.      */
  1388.     for (i = 0; i < NTELOPTS; i++) {
  1389.         if (my_want_state_is_will(i)) {
  1390.             ADD(WILL);
  1391.             ADD_DATA(i);
  1392.             if (i == IAC)
  1393.                 ADD(IAC);
  1394.         }
  1395.         if (his_want_state_is_will(i)) {
  1396.             ADD(DO);
  1397.             ADD_DATA(i);
  1398.             if (i == IAC)
  1399.                 ADD(IAC);
  1400.         }
  1401.     }
  1402.  
  1403.     if (his_want_state_is_will(TELOPT_LFLOW)) {
  1404.         ADD(SB);
  1405.         ADD(TELOPT_LFLOW);
  1406.         ADD(flowmode);
  1407.         ADD(SE);
  1408.     }
  1409.  
  1410. #ifdef    LINEMODE
  1411.     if (his_want_state_is_will(TELOPT_LINEMODE)) {
  1412.         unsigned char *cp, *cpe;
  1413.         int len;
  1414.  
  1415.         ADD(SB);
  1416.         ADD(TELOPT_LINEMODE);
  1417.         ADD(LM_MODE);
  1418.         ADD_DATA(editmode);
  1419.         if (editmode == IAC)
  1420.             ADD(IAC);
  1421.         ADD(SE);
  1422.  
  1423.         ADD(SB);
  1424.         ADD(TELOPT_LINEMODE);
  1425.         ADD(LM_SLC);
  1426.         start_slc(0);
  1427.         send_slc();
  1428.         len = end_slc(&cp);
  1429.         for (cpe = cp + len; cp < cpe; cp++)
  1430.             ADD_DATA(*cp);
  1431.         ADD(SE);
  1432.     }
  1433. #endif    /* LINEMODE */
  1434.  
  1435.     ADD(IAC);
  1436.     ADD(SE);
  1437.  
  1438.     writenet(statusbuf, ncp - statusbuf);
  1439.     netflush();    /* Send it on its way */
  1440.  
  1441.     DIAG(TD_OPTIONS,
  1442.         {printsub('>', statusbuf, ncp - statusbuf); netflush();});
  1443. }
  1444.