Exemple #1
0
/*
 * end_slc
 *
 * Finish up the slc negotiation.  If something to send, then send it.
 */
int end_slc(unsigned char **bufp) {
    int len;
    /*
     * If a change has occured, store the new terminal control
     * structures back to the terminal driver.
     */
    if (slcchange) {
	set_termbuf();
    }

    /*
     * If the pty state has not yet been fully processed and there is a
     * deferred slc request from the client, then do not send any
     * sort of slc negotiation now.  We will respond to the client's
     * request very soon.
     */
    if (def_slcbuf && (terminit() == 0)) {
	return 0;
    }

    if (slcptr > (slcbuf + 4)) {
	if (bufp) {
	    *bufp = &slcbuf[4];
	    return(slcptr - slcbuf - 4);
	} 
	else {
	    sprintf(slcptr, "%c%c", IAC, SE);
	    slcptr += 2;
	    len = slcptr - slcbuf;
	    writenet(slcbuf, len);
	    netflush();  /* force it out immediately */
	}
    }
    return 0;
}
void
tty_setlinemode(int on)
{
	set_termbuf();
	(void) ioctl(pty, TIOCEXT, (char *)&on);
	init_termbuf();
}
Exemple #3
0
/*
 * clientstat
 *
 * Process linemode related requests from the client.
 * Client can request a change to only one of linemode, editmode or slc's
 * at a time, and if using kludge linemode, then only linemode may be
 * affected.
 */
void
clientstat(int code, int parm1, int parm2)
{
    /*
     * Get a copy of terminal characteristics.
     */
    init_termbuf();

    /*
     * Process request from client. code tells what it is.
     */
    switch (code) {
    case TELOPT_NAWS:
#ifdef	TIOCSWINSZ
	{
	    struct winsize ws;

	    def_col = parm1;
	    def_row = parm2;

	    /*
	     * Change window size as requested by client.
	     */

	    ws.ws_col = parm1;
	    ws.ws_row = parm2;
	    ioctl(ourpty, TIOCSWINSZ, (char *)&ws);
	}
#endif	/* TIOCSWINSZ */

    break;

    case TELOPT_TSPEED:
	{
	    def_tspeed = parm1;
	    def_rspeed = parm2;
	    /*
	     * Change terminal speed as requested by client.
	     * We set the receive speed first, so that if we can't
	     * store seperate receive and transmit speeds, the transmit
	     * speed will take precedence.
	     */
	    tty_rspeed(parm2);
	    tty_tspeed(parm1);
	    set_termbuf();

	    break;

	}  /* end of case TELOPT_TSPEED */

    default:
	/* What? */
	break;
    }  /* end of switch */

    netflush();

}
Exemple #4
0
void tty_setlinemode(int on) {
#ifdef TIOCEXT
    set_termbuf();
    ioctl(pty, TIOCEXT, (char *)&on);
    init_termbuf();
#else	/* !TIOCEXT */
# ifdef	EXTPROC
    if (on) termbuf.c_lflag |= EXTPROC;
    else termbuf.c_lflag &= ~EXTPROC;
# endif
#endif	/* TIOCEXT */
}
Exemple #5
0
/*
 * end_slc
 *
 * Finish up the slc negotiation.  If something to send, then send it.
 */
int
end_slc (register unsigned char **bufp)
{
  register int len;
  void netflush ();

  /*
   * If a change has occured, store the new terminal control
   * structures back to the terminal driver.
   */
  if (slcchange)
    {
      set_termbuf ();
    }

  /*
   * If the pty state has not yet been fully processed and there is a
   * deferred slc request from the client, then do not send any
   * sort of slc negotiation now.  We will respond to the client's
   * request very soon.
   */
  if (def_slcbuf && (terminit () == 0))
    {
      return (0);
    }

  if (slcptr > (slcbuf + 4))
    {
      if (bufp)
	{
	  *bufp = &slcbuf[4];
	  return (slcptr - slcbuf - 4);
	}
      else
	{
	  sprintf ((char *) slcptr, "%c%c", IAC, SE);
	  slcptr += 2;
	  len = slcptr - slcbuf;
	  net_output_datalen (slcbuf, len);
	  netflush ();		/* force it out immediately */
	  DEBUG (debug_options, 1, printsub ('>', slcbuf + 2, len - 2));
	}
    }
  return (0);

}				/* end of end_slc */
Exemple #6
0
/*
 * clientstat
 *
 * Process linemode related requests from the client.
 * Client can request a change to only one of linemode, editmode or slc's
 * at a time, and if using kludge linemode, then only linemode may be
 * affected.
 */
void
clientstat(int code, int parm1, int parm2)
{

	/*
	 * Get a copy of terminal characteristics.
	 */
	init_termbuf();

	/*
	 * Process request from client. code tells what it is.
	 */
	switch (code) {
#ifdef	LINEMODE
	case TELOPT_LINEMODE:
		/*
		 * Don't do anything unless client is asking us to change
		 * modes.
		 */
		uselinemode = (parm1 == WILL);
		if (uselinemode != linemode) {
# ifdef	KLUDGELINEMODE
			/*
			 * If using kludge linemode, make sure that
			 * we can do what the client asks.
			 * We can not turn off linemode if alwayslinemode
			 * and the ICANON bit is set.
			 */
			if (lmodetype == KLUDGE_LINEMODE) {
				if (alwayslinemode && tty_isediting()) {
					uselinemode = 1;
				}
			}

			/*
			 * Quit now if we can't do it.
			 */
			if (uselinemode == linemode)
				return;

			/*
			 * If using real linemode and linemode is being
			 * turned on, send along the edit mode mask.
			 */
			if (lmodetype == REAL_LINEMODE && uselinemode)
# else	/* KLUDGELINEMODE */
			if (uselinemode)
# endif	/* KLUDGELINEMODE */
			{
				useeditmode = 0;
				if (tty_isediting())
					useeditmode |= MODE_EDIT;
				if (tty_istrapsig())
					useeditmode |= MODE_TRAPSIG;
				if (tty_issofttab())
					useeditmode |= MODE_SOFT_TAB;
				if (tty_islitecho())
					useeditmode |= MODE_LIT_ECHO;
				output_data("%c%c%c%c%c%c%c", IAC,
					SB, TELOPT_LINEMODE, LM_MODE,
							useeditmode, IAC, SE);
				editmode = useeditmode;
			}


			tty_setlinemode(uselinemode);

			linemode = uselinemode;

			if (!linemode)
				send_will(TELOPT_ECHO, 1);
		}
		break;

	case LM_MODE:
	    {
		int ack, changed;

		/*
		 * Client has sent along a mode mask.  If it agrees with
		 * what we are currently doing, ignore it; if not, it could
		 * be viewed as a request to change.  Note that the server
		 * will change to the modes in an ack if it is different from
		 * what we currently have, but we will not ack the ack.
		 */
		 useeditmode &= MODE_MASK;
		 ack = (useeditmode & MODE_ACK);
		 useeditmode &= ~MODE_ACK;

		 if ((changed = (useeditmode ^ editmode))) {
			/*
			 * This check is for a timing problem.  If the
			 * state of the tty has changed (due to the user
			 * application) we need to process that info
			 * before we write in the state contained in the
			 * ack!!!  This gets out the new MODE request,
			 * and when the ack to that command comes back
			 * we'll set it and be in the right mode.
			 */
			if (ack)
				localstat();
			if (changed & MODE_EDIT)
				tty_setedit(useeditmode & MODE_EDIT);

			if (changed & MODE_TRAPSIG)
				tty_setsig(useeditmode & MODE_TRAPSIG);

			if (changed & MODE_SOFT_TAB)
				tty_setsofttab(useeditmode & MODE_SOFT_TAB);

			if (changed & MODE_LIT_ECHO)
				tty_setlitecho(useeditmode & MODE_LIT_ECHO);

			set_termbuf();

 			if (!ack) {
				output_data("%c%c%c%c%c%c%c", IAC,
					SB, TELOPT_LINEMODE, LM_MODE,
 					useeditmode|MODE_ACK,
 					IAC, SE);
 			}

			editmode = useeditmode;
		}

		break;

	    }  /* end of case LM_MODE */
#endif	/* LINEMODE */

	case TELOPT_NAWS:
#ifdef	TIOCSWINSZ
	    {
		struct winsize ws;

		def_col = parm1;
		def_row = parm2;
#ifdef	LINEMODE
		/*
		 * Defer changing window size until after terminal is
		 * initialized.
		 */
		if (terminit() == 0)
			return;
#endif	/* LINEMODE */

		/*
		 * Change window size as requested by client.
		 */

		ws.ws_col = parm1;
		ws.ws_row = parm2;
		(void) ioctl(spty, TIOCSWINSZ, (char *)&ws);
	    }
#endif	/* TIOCSWINSZ */

		break;

	case TELOPT_TSPEED:
	    {
		def_tspeed = parm1;
		def_rspeed = parm2;
#ifdef	LINEMODE
		/*
		 * Defer changing the terminal speed.
		 */
		if (terminit() == 0)
			return;
#endif	/* LINEMODE */
		/*
		 * Change terminal speed as requested by client.
		 * We set the receive speed first, so that if we can't
		 * store separate receive and transmit speeds, the transmit
		 * speed will take precedence.
		 */
		tty_rspeed(parm2);
		tty_tspeed(parm1);
		set_termbuf();

		break;

	    }  /* end of case TELOPT_TSPEED */

	default:
		/* What? */
		break;
	}  /* end of switch */

	netflush();

}  /* end of clientstat */
Exemple #7
0
/*
 * localstat
 *
 * This function handles all management of linemode.
 *
 * Linemode allows the client to do the local editing of data
 * and send only complete lines to the server.  Linemode state is
 * based on the state of the pty driver.  If the pty is set for
 * external processing, then we can use linemode.  Further, if we
 * can use real linemode, then we can look at the edit control bits
 * in the pty to determine what editing the client should do.
 *
 * Linemode support uses the following state flags to keep track of
 * current and desired linemode state.
 *	alwayslinemode : true if -l was specified on the telnetd
 * 	command line.  It means to have linemode on as much as
 *	possible.
 *
 * 	lmodetype: signifies whether the client can
 *	handle real linemode, or if use of kludgeomatic linemode
 *	is preferred.  It will be set to one of the following:
 *		REAL_LINEMODE : use linemode option
 *		NO_KLUDGE : don't initiate kludge linemode.
 *		KLUDGE_LINEMODE : use kludge linemode
 *		NO_LINEMODE : client is ignorant of linemode
 *
 *	linemode, uselinemode : linemode is true if linemode
 *	is currently on, uselinemode is the state that we wish
 *	to be in.  If another function wishes to turn linemode
 *	on or off, it sets or clears uselinemode.
 *
 *	editmode, useeditmode : like linemode/uselinemode, but
 *	these contain the edit mode states (edit and trapsig).
 *
 * The state variables correspond to some of the state information
 * in the pty.
 *	linemode:
 *		In real linemode, this corresponds to whether the pty
 *		expects external processing of incoming data.
 *		In kludge linemode, this more closely corresponds to the
 *		whether normal processing is on or not.  (ICANON in
 *		system V, or COOKED mode in BSD.)
 *		If the -l option was specified (alwayslinemode), then
 *		an attempt is made to force external processing on at
 *		all times.
 *
 * The following heuristics are applied to determine linemode
 * handling within the server.
 *	1) Early on in starting up the server, an attempt is made
 *	   to negotiate the linemode option.  If this succeeds
 *	   then lmodetype is set to REAL_LINEMODE and all linemode
 *	   processing occurs in the context of the linemode option.
 *	2) If the attempt to negotiate the linemode option failed,
 *	   and the "-k" (don't initiate kludge linemode) isn't set,
 *	   then we try to use kludge linemode.  We test for this
 *	   capability by sending "do Timing Mark".  If a positive
 *	   response comes back, then we assume that the client
 *	   understands kludge linemode (ech!) and the
 *	   lmodetype flag is set to KLUDGE_LINEMODE.
 *	3) Otherwise, linemode is not supported at all and
 *	   lmodetype remains set to NO_LINEMODE (which happens
 *	   to be 0 for convenience).
 *	4) At any time a command arrives that implies a higher
 *	   state of linemode support in the client, we move to that
 *	   linemode support.
 *
 * A short explanation of kludge linemode is in order here.
 *	1) The heuristic to determine support for kludge linemode
 *	   is to send a do timing mark.  We assume that a client
 *	   that supports timing marks also supports kludge linemode.
 *	   A risky proposition at best.
 *	2) Further negotiation of linemode is done by changing the
 *	   the server's state regarding SGA.  If server will SGA,
 *	   then linemode is off, if server won't SGA, then linemode
 *	   is on.
 */
void
localstat(void)
{
	int need_will_echo = 0;

	/*
	 * Check for changes to flow control if client supports it.
	 */
	flowstat();

	/*
	 * Check linemode on/off state
	 */
	uselinemode = tty_linemode();

	/*
	 * If alwayslinemode is on, and pty is changing to turn it off, then
	 * force linemode back on.
	 */
	if (alwayslinemode && linemode && !uselinemode) {
		uselinemode = 1;
		tty_setlinemode(uselinemode);
	}

	if (uselinemode) {
		/*
		 * Check for state of BINARY options.
		 *
		 * We only need to do the binary dance if we are actually going
		 * to use linemode.  As this confuses some telnet clients
		 * that don't support linemode, and doesn't gain us
		 * anything, we don't do it unless we're doing linemode.
		 * -Crh ([email protected])
		 */

		if (tty_isbinaryin()) {
			if (his_want_state_is_wont(TELOPT_BINARY))
				send_do(TELOPT_BINARY, 1);
		} else {
			if (his_want_state_is_will(TELOPT_BINARY))
				send_dont(TELOPT_BINARY, 1);
		}

		if (tty_isbinaryout()) {
			if (my_want_state_is_wont(TELOPT_BINARY))
				send_will(TELOPT_BINARY, 1);
		} else {
			if (my_want_state_is_will(TELOPT_BINARY))
				send_wont(TELOPT_BINARY, 1);
		}
	}

#ifdef	ENCRYPTION
	/*
	 * If the terminal is not echoing, but editing is enabled,
	 * something like password input is going to happen, so
	 * if we the other side is not currently sending encrypted
	 * data, ask the other side to start encrypting.
	 */
	if (his_state_is_will(TELOPT_ENCRYPT)) {
		static int enc_passwd = 0;
		if (uselinemode && !tty_isecho() && tty_isediting()
		    && (enc_passwd == 0) && !decrypt_input) {
			encrypt_send_request_start();
			enc_passwd = 1;
		} else if (enc_passwd) {
			encrypt_send_request_end();
			enc_passwd = 0;
		}
	}
#endif	/* ENCRYPTION */

	/*
	 * Do echo mode handling as soon as we know what the
	 * linemode is going to be.
	 * If the pty has echo turned off, then tell the client that
	 * the server will echo.  If echo is on, then the server
	 * will echo if in character mode, but in linemode the
	 * client should do local echoing.  The state machine will
	 * not send anything if it is unnecessary, so don't worry
	 * about that here.
	 *
	 * If we need to send the WILL ECHO (because echo is off),
	 * then delay that until after we have changed the MODE.
	 * This way, when the user is turning off both editing
	 * and echo, the client will get editing turned off first.
	 * This keeps the client from going into encryption mode
	 * and then right back out if it is doing auto-encryption
	 * when passwords are being typed.
	 */
	if (uselinemode) {
		if (tty_isecho())
			send_wont(TELOPT_ECHO, 1);
		else
			need_will_echo = 1;
#ifdef	KLUDGELINEMODE
		if (lmodetype == KLUDGE_OK)
			lmodetype = KLUDGE_LINEMODE;
#endif
	}

	/*
	 * If linemode is being turned off, send appropriate
	 * command and then we're all done.
	 */
	 if (!uselinemode && linemode) {
# ifdef	KLUDGELINEMODE
		if (lmodetype == REAL_LINEMODE) {
# endif	/* KLUDGELINEMODE */
			send_dont(TELOPT_LINEMODE, 1);
# ifdef	KLUDGELINEMODE
		} else if (lmodetype == KLUDGE_LINEMODE)
			send_will(TELOPT_SGA, 1);
# endif	/* KLUDGELINEMODE */
		send_will(TELOPT_ECHO, 1);
		linemode = uselinemode;
		goto done;
	}

# ifdef	KLUDGELINEMODE
	/*
	 * If using real linemode check edit modes for possible later use.
	 * If we are in kludge linemode, do the SGA negotiation.
	 */
	if (lmodetype == REAL_LINEMODE) {
# endif	/* KLUDGELINEMODE */
		useeditmode = 0;
		if (tty_isediting())
			useeditmode |= MODE_EDIT;
		if (tty_istrapsig())
			useeditmode |= MODE_TRAPSIG;
		if (tty_issofttab())
			useeditmode |= MODE_SOFT_TAB;
		if (tty_islitecho())
			useeditmode |= MODE_LIT_ECHO;
# ifdef	KLUDGELINEMODE
	} else if (lmodetype == KLUDGE_LINEMODE) {
		if (tty_isediting() && uselinemode)
			send_wont(TELOPT_SGA, 1);
		else
			send_will(TELOPT_SGA, 1);
	}
# endif	/* KLUDGELINEMODE */

	/*
	 * Negotiate linemode on if pty state has changed to turn it on.
	 * Send appropriate command and send along edit mode, then all done.
	 */
	if (uselinemode && !linemode) {
# ifdef	KLUDGELINEMODE
		if (lmodetype == KLUDGE_LINEMODE) {
			send_wont(TELOPT_SGA, 1);
		} else if (lmodetype == REAL_LINEMODE) {
# endif	/* KLUDGELINEMODE */
			send_do(TELOPT_LINEMODE, 1);
			/* send along edit modes */
			output_data("%c%c%c%c%c%c%c", IAC, SB,
				TELOPT_LINEMODE, LM_MODE, useeditmode,
				IAC, SE);
			editmode = useeditmode;
# ifdef	KLUDGELINEMODE
		}
# endif	/* KLUDGELINEMODE */
		linemode = uselinemode;
		goto done;
	}

# ifdef	KLUDGELINEMODE
	/*
	 * None of what follows is of any value if not using
	 * real linemode.
	 */
	if (lmodetype < REAL_LINEMODE)
		goto done;
# endif	/* KLUDGELINEMODE */

	if (linemode && his_state_is_will(TELOPT_LINEMODE)) {
		/*
		 * If edit mode changed, send edit mode.
		 */
		 if (useeditmode != editmode) {
			/*
			 * Send along appropriate edit mode mask.
			 */
			output_data("%c%c%c%c%c%c%c", IAC, SB,
				TELOPT_LINEMODE, LM_MODE, useeditmode,
				IAC, SE);
			editmode = useeditmode;
		}


		/*
		 * Check for changes to special characters in use.
		 */
		start_slc(0);
		check_slc();
		(void) end_slc(0);
	}

done:
	if (need_will_echo)
		send_will(TELOPT_ECHO, 1);
	/*
	 * Some things should be deferred until after the pty state has
	 * been set by the local process.  Do those things that have been
	 * deferred now.  This only happens once.
	 */
	if (_terminit == 0) {
		_terminit = 1;
		defer_terminit();
	}

	netflush();
	set_termbuf();
	return;

}  /* end of localstat */
void dontoption(int option) {
    /*
     * Process client input.
     */
    DIAG(TD_OPTIONS, printoption("td: recv dont", option));

    if (will_wont_resp[option]) {
        will_wont_resp[option]--;
        if (will_wont_resp[option] && my_state_is_wont(option))
            will_wont_resp[option]--;
    }
    if ((will_wont_resp[option] == 0) && (my_want_state_is_will(option))) {
        switch (option) {
        case TELOPT_BINARY:
            init_termbuf();
            tty_binaryout(0);
            set_termbuf();
            break;

        case TELOPT_ECHO:	/* we should stop echoing */
#ifdef	LINEMODE
#ifdef	KLUDGELINEMODE
            if (lmodetype == NO_LINEMODE)
#else
            if (his_state_is_wont(TELOPT_LINEMODE))
#endif
#endif
            {
                init_termbuf();
                tty_setecho(0);
                set_termbuf();
            }
            break;

        case TELOPT_SGA:
#if defined(LINEMODE) && defined(KLUDGELINEMODE)
            /*
             * If kludge linemode is in use, then we
             * must process an incoming do SGA for
             * linemode purposes.
             */
            if (lmodetype == KLUDGE_LINEMODE) {
                /*
                 * The client is asking us to turn
                 * linemode on.
                 */
                clientstat(TELOPT_LINEMODE, WILL, 0);
                /*
                 * If we did not turn line mode on,
                 * then what do we say?  Will SGA?
                 * This violates design of telnet.
                 * Gross.  Very Gross.
                 */
            }
            break;
#else
            set_my_want_state_wont(option);
            if (my_state_is_will(option))
                send_wont(option, 0);
            set_my_state_wont(option);
            if (turn_on_sga ^= 1) send_will(option,1);
            return;
#endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */

        default:
            break;
        }

        set_my_want_state_wont(option);
        if (my_state_is_will(option))
            send_wont(option, 0);
    }
    set_my_state_wont(option);
}
void dooption(int option) {
    int changeok = 0;

    /*
     * Process client input.
     */

    DIAG(TD_OPTIONS, printoption("td: recv do", option));

    if (will_wont_resp[option]) {
        will_wont_resp[option]--;
        if (will_wont_resp[option] && my_state_is_will(option))
            will_wont_resp[option]--;
    }
    if ((will_wont_resp[option] == 0) && (my_want_state_is_wont(option))) {
        switch (option) {
        case TELOPT_ECHO:
#ifdef	LINEMODE
#ifdef	KLUDGELINEMODE
            if (lmodetype == NO_LINEMODE)
#else
            if (his_state_is_wont(TELOPT_LINEMODE))
#endif
#endif
            {
                init_termbuf();
                tty_setecho(1);
                set_termbuf();
            }
            changeok++;
            break;

        case TELOPT_BINARY:
            init_termbuf();
            tty_binaryout(1);
            set_termbuf();
            changeok++;
            break;

        case TELOPT_SGA:
#if defined(LINEMODE) && defined(KLUDGELINEMODE)
            /*
             * If kludge linemode is in use, then we must
             * process an incoming do SGA for linemode
             * purposes.
             */
            if (lmodetype == KLUDGE_LINEMODE) {
                /*
                 * Receipt of "do SGA" in kludge
                 * linemode is the peer asking us to
                 * turn off linemode.  Make note of
                 * the request.
                 */
                clientstat(TELOPT_LINEMODE, WONT, 0);
                /*
                 * If linemode did not get turned off
                 * then don't tell peer that we did.
                 * Breaking here forces a wont SGA to
                 * be returned.
                 */
                if (linemode)  break;
            }
#else
            turn_on_sga = 0;
#endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
            changeok++;
            break;

        case TELOPT_STATUS:
            changeok++;
            break;

        case TELOPT_TM:
            /*
             * Special case for TM.  We send a WILL, but
             * pretend we sent a WONT.
             */
            send_will(option, 0);
            set_my_want_state_wont(option);
            set_my_state_wont(option);
            return;

        case TELOPT_LOGOUT:
            /*
             * When we get a LOGOUT option, respond
             * with a WILL LOGOUT, make sure that
             * it gets written out to the network,
             * and then just go away...
             */
            set_my_want_state_will(TELOPT_LOGOUT);
            send_will(TELOPT_LOGOUT, 0);
            set_my_state_will(TELOPT_LOGOUT);
            (void)netflush();
            cleanup(0);
            /* NOT REACHED */
            break;

#if defined(ENCRYPT)
        case TELOPT_ENCRYPT:
            changeok++;
            break;
#endif
        case TELOPT_LINEMODE:
        case TELOPT_TTYPE:
        case TELOPT_NAWS:
        case TELOPT_TSPEED:
        case TELOPT_LFLOW:
        case TELOPT_XDISPLOC:
        case TELOPT_ENVIRON:
        default:
            break;
        }
        if (changeok) {
            set_my_want_state_will(option);
            send_will(option, 0);
        }
        else {
            will_wont_resp[option]++;
            send_wont(option, 0);
        }
    }
    set_my_state_will(option);
}
Exemple #10
0
void wontoption(int option) {
    /*
     * Process client input.
     */

    DIAG(TD_OPTIONS, printoption("td: recv wont", option));

    if (do_dont_resp[option]) {
        do_dont_resp[option]--;
        if (do_dont_resp[option] && his_state_is_wont(option))
            do_dont_resp[option]--;
    }
    if (do_dont_resp[option] == 0) {
        if (his_want_state_is_will(option)) {
            /* it is always ok to change to negative state */
            switch (option) {
            case TELOPT_ECHO:
                not42 = 1; /* doesn't seem to be a 4.2 system */
                break;

            case TELOPT_BINARY:
                init_termbuf();
                tty_binaryin(0);
                set_termbuf();
                break;

#ifdef LINEMODE
            case TELOPT_LINEMODE:
#ifdef KLUDGELINEMODE
                /*
                 * If real linemode is supported, then client is
                 * asking to turn linemode off.
                 */
                if (lmodetype != REAL_LINEMODE)
                    break;
                lmodetype = KLUDGE_LINEMODE;
# endif	/* KLUDGELINEMODE */
                clientstat(TELOPT_LINEMODE, WONT, 0);
                break;
#endif	/* LINEMODE */

            case TELOPT_TM:
                /*
                 * If we get a WONT TM, and had sent a DO TM,
                 * don't respond with a DONT TM, just leave it
                 * as is.  Short circut the state machine to
                 * achive this.
                 */
                set_his_want_state_wont(TELOPT_TM);
                return;

            case TELOPT_LFLOW:
                /*
                 * If we are not going to support flow control
                 * option, then let peer know that we can't
                 * change the flow control characters.
                 */
                slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS;
                slctab[SLC_XON].defset.flag |= SLC_CANTCHANGE;
                slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS;
                slctab[SLC_XOFF].defset.flag |= SLC_CANTCHANGE;
                break;

#if defined(AUTHENTICATE)
            case TELOPT_AUTHENTICATION:
                auth_finished(0, AUTH_REJECT);
                break;
#endif

            /*
             * For options that we might spin waiting for
             * sub-negotiation, if the client turns off the
             * option rather than responding to the request,
             * we have to treat it here as if we got a response
             * to the sub-negotiation, (by updating the timers)
             * so that we'll break out of the loop.
             */
            case TELOPT_TTYPE:
                settimer(ttypesubopt);
                break;

            case TELOPT_TSPEED:
                settimer(tspeedsubopt);
                break;

            case TELOPT_XDISPLOC:
                settimer(xdisplocsubopt);
                break;

            case TELOPT_ENVIRON:
                settimer(environsubopt);
                break;

            default:
                break;
            }
            set_his_want_state_wont(option);
            if (his_state_is_will(option)) send_dont(option, 0);
        }
        else {
            switch (option) {
            case TELOPT_TM:
#if defined(LINEMODE) && defined(KLUDGELINEMODE)
                if (lmodetype < REAL_LINEMODE) {
                    lmodetype = NO_LINEMODE;
                    clientstat(TELOPT_LINEMODE, WONT, 0);
                    send_will(TELOPT_SGA, 1);
                    send_will(TELOPT_ECHO, 1);
                }
#endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
                break;

#if	defined(AUTHENTICATE)
            case TELOPT_AUTHENTICATION:
                auth_finished(0, AUTH_REJECT);
                break;
#endif
            default:
                break;
            }
        }
    }
}  /* end of wontoption */
Exemple #11
0
void willoption(int option) {
    int changeok = 0;
    void (*func)(void) = 0;

    /*
     * process input from peer.
     */

    DIAG(TD_OPTIONS, printoption("td: recv will", option));

    if (do_dont_resp[option]) {
        do_dont_resp[option]--;
        if (do_dont_resp[option] && his_state_is_will(option))
            do_dont_resp[option]--;
    }
    if (do_dont_resp[option] == 0) {
        if (his_want_state_is_wont(option)) {
            switch (option) {

            case TELOPT_BINARY:
                init_termbuf();
                tty_binaryin(1);
                set_termbuf();
                changeok++;
                break;

            case TELOPT_ECHO:
                /*
                 * See comments below for more info.
                 */
                not42 = 0;	/* looks like a 4.2 system */
                break;

            case TELOPT_TM:
#if defined(LINEMODE) && defined(KLUDGELINEMODE)
                /*
                 * This telnetd implementation does not really
                 * support timing marks, it just uses them to
                 * support the kludge linemode stuff.  If we
                 * receive a will or wont TM in response to our
                 * do TM request that may have been sent to
                 * determine kludge linemode support, process
                 * it, otherwise TM should get a negative
                 * response back.
                 */
                /*
                 * Handle the linemode kludge stuff.
                 * If we are not currently supporting any
                 * linemode at all, then we assume that this
                 * is the client telling us to use kludge
                 * linemode in response to our query.  Set the
                 * linemode type that is to be supported, note
                 * that the client wishes to use linemode, and
                 * eat the will TM as though it never arrived.
                 */
                if (lmodetype < KLUDGE_LINEMODE) {
                    lmodetype = KLUDGE_LINEMODE;
                    clientstat(TELOPT_LINEMODE, WILL, 0);
                    send_wont(TELOPT_SGA, 1);
                }
#endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
                /*
                 * We never respond to a WILL TM, and
                 * we leave the state WONT.
                 */
                return;

            case TELOPT_LFLOW:
                /*
                 * If we are going to support flow control
                 * option, then don't worry peer that we can't
                 * change the flow control characters.
                 */
                slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS;
                slctab[SLC_XON].defset.flag |= SLC_DEFAULT;
                slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS;
                slctab[SLC_XOFF].defset.flag |= SLC_DEFAULT;
            case TELOPT_TTYPE:
            case TELOPT_SGA:
            case TELOPT_NAWS:
            case TELOPT_TSPEED:
            case TELOPT_XDISPLOC:
            case TELOPT_ENVIRON:
                changeok++;
                break;

#ifdef LINEMODE
            case TELOPT_LINEMODE:
#ifdef KLUDGELINEMODE
                /*
                 * Note client's desire to use linemode.
                 */
                lmodetype = REAL_LINEMODE;
#endif	/* KLUDGELINEMODE */
                func = doclientstat;
                changeok++;
                break;
#endif	/* LINEMODE */

#ifdef	AUTHENTICATE
            case TELOPT_AUTHENTICATION:
                func = auth_request;
                changeok++;
                break;
#endif

#ifdef ENCRYPT
            case TELOPT_ENCRYPT:
                func = encrypt_send_support;
                changeok++;
                break;
#endif

            default:
                break;
            }
            if (changeok) {
                set_his_want_state_will(option);
                send_do(option, 0);
            }
            else {
                do_dont_resp[option]++;
                send_dont(option, 0);
            }
        }
        else {
            /*
             * Option processing that should happen when
             * we receive conformation of a change in
             * state that we had requested.
             */
            switch (option) {
            case TELOPT_ECHO:
                not42 = 0;	/* looks like a 4.2 system */
                /*
                 * Egads, he responded "WILL ECHO".  Turn
                 * it off right now!
                 */
                send_dont(option, 1);
                /*
                 * "WILL ECHO".  Kludge upon kludge!
                 * A 4.2 client is now echoing user input at
                 * the tty.  This is probably undesireable and
                 * it should be stopped.  The client will
                 * respond WONT TM to the DO TM that we send to
                 * check for kludge linemode.  When the WONT TM
                 * arrives, linemode will be turned off and a
                 * change propogated to the pty.  This change
                 * will cause us to process the new pty state
                 * in localstat(), which will notice that
                 * linemode is off and send a WILL ECHO
                 * so that we are properly in character mode and
                 * all is well.
                 */
                break;
#ifdef	LINEMODE
            case TELOPT_LINEMODE:
# ifdef	KLUDGELINEMODE
                /*
                 * Note client's desire to use linemode.
                 */
                lmodetype = REAL_LINEMODE;
# endif	/* KLUDGELINEMODE */
                func = doclientstat;
                break;
#endif	/* LINEMODE */

#ifdef	AUTHENTICATE
            case TELOPT_AUTHENTICATION:
                func = auth_request;
                break;
#endif

#ifdef	ENCRYPT
            case TELOPT_ENCRYPT:
                func = encrypt_send_support;
                break;
#endif
            }
        }
    }
    set_his_state_will(option);
    if (func) (*func)();
}
Exemple #12
0
static int getptyslave(void) {
#if 0
    register int t = -1;

# ifdef	LINEMODE
    int waslm;
# endif
# ifdef	TIOCGWINSZ
    struct winsize ws;
# endif
    /*
     * Opening the slave side may cause initilization of the
     * kernel tty structure.  We need remember the state of
     * 	if linemode was turned on
     *	terminal window size
     *	terminal speed
     * so that we can re-set them if we need to.
     */
# ifdef	LINEMODE
    waslm = tty_linemode();
# endif


    /*
     * Make sure that we don't have a controlling tty, and
     * that we are the session (process group) leader.
     */
    t = open(_PATH_TTY, O_RDWR);
    if (t >= 0) {
	ioctl(t, TIOCNOTTY, (char *)0);
	close(t);
    }

    t = cleanopen(line);
    if (t < 0) fatalperror(net, line);
#endif /* 0 */

    struct winsize ws;
    int t = ptyslavefd;

    /*
     * set up the tty modes as we like them to be.
     */
    init_termbuf();
# ifdef	TIOCGWINSZ
    if (def_row || def_col) {
	bzero((char *)&ws, sizeof(ws));
	ws.ws_col = def_col;
	ws.ws_row = def_row;
	ioctl(t, TIOCSWINSZ, (char *)&ws);
    }
# endif

    /*
     * Settings for all other termios/termio based
     * systems, other than 4.4BSD.  In 4.4BSD the
     * kernel does the initial terminal setup.
     *
     * XXX what about linux?
     */
#  ifndef	OXTABS
#   define OXTABS	0
#  endif
    termbuf.c_lflag |= ECHO;
    termbuf.c_oflag |= OPOST|ONLCR|OXTABS;
    termbuf.c_iflag |= ICRNL;
    termbuf.c_iflag &= ~IXOFF;

    tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600);
    tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600);
# ifdef	LINEMODE
    if (waslm) tty_setlinemode(1);
# endif	/* LINEMODE */

    /*
     * Set the tty modes, and make this our controlling tty.
     */
    set_termbuf();
    if (login_tty(t) == -1) fatalperror(net, "login_tty");

    if (net > 2) close(net);
    if (pty > 2) close(pty);
    return t;
}
Exemple #13
0
/*
 * localstat
 *
 * This function handles all management of linemode.
 *
 * Linemode allows the client to do the local editing of data
 * and send only complete lines to the server.  Linemode state is
 * based on the state of the pty driver.  If the pty is set for
 * external processing, then we can use linemode.  Further, if we
 * can use real linemode, then we can look at the edit control bits
 * in the pty to determine what editing the client should do.
 *
 * Linemode support uses the following state flags to keep track of
 * current and desired linemode state.
 *	alwayslinemode : true if -l was specified on the telnetd
 * 	command line.  It means to have linemode on as much as
 *	possible.
 *
 * 	lmodetype: signifies whether the client can
 *	handle real linemode, or if use of kludgeomatic linemode
 *	is preferred.  It will be set to one of the following:
 *		REAL_LINEMODE : use linemode option
 *		NO_KLUDGE : don't initiate kludge linemode.
 *		KLUDGE_LINEMODE : use kludge linemode
 *		NO_LINEMODE : client is ignorant of linemode
 *
 *	linemode, uselinemode : linemode is true if linemode
 *	is currently on, uselinemode is the state that we wish
 *	to be in.  If another function wishes to turn linemode
 *	on or off, it sets or clears uselinemode.
 *
 *	editmode, useeditmode : like linemode/uselinemode, but
 *	these contain the edit mode states (edit and trapsig).
 *
 * The state variables correspond to some of the state information
 * in the pty.
 *	linemode:
 *		In real linemode, this corresponds to whether the pty
 *		expects external processing of incoming data.
 *		In kludge linemode, this more closely corresponds to the
 *		whether normal processing is on or not.  (ICANON in
 *		system V, or COOKED mode in BSD.)
 *		If the -l option was specified (alwayslinemode), then
 *		an attempt is made to force external processing on at
 *		all times.
 *
 * The following heuristics are applied to determine linemode
 * handling within the server.
 *	1) Early on in starting up the server, an attempt is made
 *	   to negotiate the linemode option.  If this succeeds
 *	   then lmodetype is set to REAL_LINEMODE and all linemode
 *	   processing occurs in the context of the linemode option.
 *	2) If the attempt to negotiate the linemode option failed,
 *	   and the "-k" (don't initiate kludge linemode) isn't set,
 *	   then we try to use kludge linemode.  We test for this
 *	   capability by sending "do Timing Mark".  If a positive
 *	   response comes back, then we assume that the client
 *	   understands kludge linemode (ech!) and the
 *	   lmodetype flag is set to KLUDGE_LINEMODE.
 *	3) Otherwise, linemode is not supported at all and
 *	   lmodetype remains set to NO_LINEMODE (which happens
 *	   to be 0 for convenience).
 *	4) At any time a command arrives that implies a higher
 *	   state of linemode support in the client, we move to that
 *	   linemode support.
 *
 * A short explanation of kludge linemode is in order here.
 *	1) The heuristic to determine support for kludge linemode
 *	   is to send a do timing mark.  We assume that a client
 *	   that supports timing marks also supports kludge linemode.
 *	   A risky proposition at best.
 *	2) Further negotiation of linemode is done by changing the
 *	   the server's state regarding SGA.  If server will SGA,
 *	   then linemode is off, if server won't SGA, then linemode
 *	   is on.
 */
	void
localstat()
{
	int need_will_echo = 0;

#if	defined(CRAY2) && defined(UNICOS5)
	/*
	 * Keep track of that ol' CR/NL mapping while we're in the
	 * neighborhood.
	 */
	newmap = tty_isnewmap();
#endif	/* defined(CRAY2) && defined(UNICOS5) */

	/*
	 * Check for state of BINARY options.
	 */
	if (tty_isbinaryin()) {
		if (his_want_state_is_wont(TELOPT_BINARY))
			send_do(TELOPT_BINARY, 1);
	} else {
		if (his_want_state_is_will(TELOPT_BINARY))
			send_dont(TELOPT_BINARY, 1);
	}

	if (tty_isbinaryout()) {
		if (my_want_state_is_wont(TELOPT_BINARY))
			send_will(TELOPT_BINARY, 1);
	} else {
		if (my_want_state_is_will(TELOPT_BINARY))
			send_wont(TELOPT_BINARY, 1);
	}

	/*
	 * Check for changes to flow control if client supports it.
	 */
	flowstat();

	/*
	 * Check linemode on/off state
	 */
	uselinemode = tty_linemode();

	/*
	 * If alwayslinemode is on, and pty is changing to turn it off, then
	 * force linemode back on.
	 */
	if (alwayslinemode && linemode && !uselinemode) {
		uselinemode = 1;
		tty_setlinemode(uselinemode);
	}


	/*
	 * Do echo mode handling as soon as we know what the
	 * linemode is going to be.
	 * If the pty has echo turned off, then tell the client that
	 * the server will echo.  If echo is on, then the server
	 * will echo if in character mode, but in linemode the
	 * client should do local echoing.  The state machine will
	 * not send anything if it is unnecessary, so don't worry
	 * about that here.
	 *
	 * If we need to send the WILL ECHO (because echo is off),
	 * then delay that until after we have changed the MODE.
	 * This way, when the user is turning off both editing
	 * and echo, the client will get editing turned off first.
	 * This keeps the client from going into encryption mode
	 * and then right back out if it is doing auto-encryption
	 * when passwords are being typed.
	 */
	if (uselinemode) {
		if (tty_isecho())
			send_wont(TELOPT_ECHO, 1);
		else
			need_will_echo = 1;
#ifdef	KLUDGELINEMODE
		if (lmodetype == KLUDGE_OK)
			lmodetype = KLUDGE_LINEMODE;
#endif
	}

	/*
	 * If linemode is being turned off, send appropriate
	 * command and then we're all done.
	 */
	 if (!uselinemode && linemode) {
# ifdef	KLUDGELINEMODE
		if (lmodetype == REAL_LINEMODE) {
# endif	/* KLUDGELINEMODE */
			send_dont(TELOPT_LINEMODE, 1);
# ifdef	KLUDGELINEMODE
		} else if (lmodetype == KLUDGE_LINEMODE)
			send_will(TELOPT_SGA, 1);
# endif	/* KLUDGELINEMODE */
		send_will(TELOPT_ECHO, 1);
		linemode = uselinemode;
		goto done;
	}

# ifdef	KLUDGELINEMODE
	/*
	 * If using real linemode check edit modes for possible later use.
	 * If we are in kludge linemode, do the SGA negotiation.
	 */
	if (lmodetype == REAL_LINEMODE) {
# endif	/* KLUDGELINEMODE */
		useeditmode = 0;
		if (tty_isediting())
			useeditmode |= MODE_EDIT;
		if (tty_istrapsig())
			useeditmode |= MODE_TRAPSIG;
		if (tty_issofttab())
			useeditmode |= MODE_SOFT_TAB;
		if (tty_islitecho())
			useeditmode |= MODE_LIT_ECHO;
# ifdef	KLUDGELINEMODE
	} else if (lmodetype == KLUDGE_LINEMODE) {
		if (tty_isediting() && uselinemode)
			send_wont(TELOPT_SGA, 1);
		else
			send_will(TELOPT_SGA, 1);
	}
# endif	/* KLUDGELINEMODE */

	/*
	 * Negotiate linemode on if pty state has changed to turn it on.
	 * Send appropriate command and send along edit mode, then all done.
	 */
	if (uselinemode && !linemode) {
# ifdef	KLUDGELINEMODE
		if (lmodetype == KLUDGE_LINEMODE) {
			send_wont(TELOPT_SGA, 1);
		} else if (lmodetype == REAL_LINEMODE) {
# endif	/* KLUDGELINEMODE */
			send_do(TELOPT_LINEMODE, 1);
			/* send along edit modes */
			(void) sprintf(nfrontp, "%c%c%c%c%c%c%c", IAC, SB,
				TELOPT_LINEMODE, LM_MODE, useeditmode,
				IAC, SE);
			nfrontp += 7;
			editmode = useeditmode;
# ifdef	KLUDGELINEMODE
		}
# endif	/* KLUDGELINEMODE */
		linemode = uselinemode;
		goto done;
	}

# ifdef	KLUDGELINEMODE
	/*
	 * None of what follows is of any value if not using
	 * real linemode.
	 */
	if (lmodetype < REAL_LINEMODE)
		goto done;
# endif	/* KLUDGELINEMODE */

	if (linemode && his_state_is_will(TELOPT_LINEMODE)) {
		/*
		 * If edit mode changed, send edit mode.
		 */
		 if (useeditmode != editmode) {
			/*
			 * Send along appropriate edit mode mask.
			 */
			(void) sprintf(nfrontp, "%c%c%c%c%c%c%c", IAC, SB,
				TELOPT_LINEMODE, LM_MODE, useeditmode,
				IAC, SE);
			nfrontp += 7;
			editmode = useeditmode;
		}


		/*
		 * Check for changes to special characters in use.
		 */
		start_slc(0);
		check_slc();
		(void) end_slc(0);
	}

done:
	if (need_will_echo)
		send_will(TELOPT_ECHO, 1);
	/*
	 * Some things should be deferred until after the pty state has
	 * been set by the local process.  Do those things that have been
	 * deferred now.  This only happens once.
	 */
	if (_terminit == 0) {
		_terminit = 1;
		defer_terminit();
	}

	netflush();
	set_termbuf();
	return;

}  /* end of localstat */
void
getptyslave(void)
{
	int t = -1;

#ifdef	LINEMODE
	int waslm;
#endif
	struct winsize ws;
	/*
	 * Opening the slave side may cause initilization of the
	 * kernel tty structure.  We need remember the state of
	 * 	if linemode was turned on
	 *	terminal window size
	 *	terminal speed
	 * so that we can re-set them if we need to.
	 */
#ifdef	LINEMODE
	waslm = tty_linemode();
#endif

	/*
	 * Make sure that we don't have a controlling tty, and
	 * that we are the session (process group) leader.
	 */
	t = open(_PATH_TTY, O_RDWR);
	if (t >= 0) {
		(void) ioctl(t, TIOCNOTTY, (char *)0);
		(void) close(t);
	}



	t = cleanopen(line);
	if (t < 0)
		fatalperror(net, line);


	/*
	 * set up the tty modes as we like them to be.
	 */
	init_termbuf();
	if (def_row || def_col) {
		memset((char *)&ws, 0, sizeof(ws));
		ws.ws_col = def_col;
		ws.ws_row = def_row;
		(void)ioctl(t, TIOCSWINSZ, (char *)&ws);
	}

	/*
	 * Settings for sgtty based systems
	 */

	/*
	 * Settings for all other termios/termio based
	 * systems, other than 4.4BSD.  In 4.4BSD the
	 * kernel does the initial terminal setup.
	 */
	tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600);
	tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600);
#ifdef	LINEMODE
	if (waslm)
		tty_setlinemode(1);
#endif	/* LINEMODE */

	/*
	 * Set the tty modes, and make this our controlling tty.
	 */
	set_termbuf();
	if (login_tty(t) == -1)
		fatalperror(net, "login_tty");
	if (net > 2)
		(void) close(net);
	if (pty > 2) {
		(void) close(pty);
		pty = -1;
	}
}
Exemple #15
0
/*
 * getptyslave()
 *
 * Open the slave side of the pty, and do any initialization
 * that is necessary.  The return value is a file descriptor
 * for the slave side.
 */
void getptyslave(void)
{
    int t = -1;

    struct winsize ws;
    /*
     * Opening the slave side may cause initilization of the
     * kernel tty structure.  We need remember the state of
     * 	if linemode was turned on
     *	terminal window size
     *	terminal speed
     * so that we can re-set them if we need to.
     */


    /*
     * Make sure that we don't have a controlling tty, and
     * that we are the session (process group) leader.
     */

#ifdef HAVE_SETSID
    if(setsid()<0)
	fatalperror(net, "setsid()");
#else
# ifdef	TIOCNOTTY
    t = open(_PATH_TTY, O_RDWR);
    if (t >= 0) {
	ioctl(t, TIOCNOTTY, (char *)0);
	close(t);
    }
# endif
#endif

# ifdef PARENT_DOES_UTMP
    /*
     * Wait for our parent to get the utmp stuff to get done.
     */
    utmp_sig_wait();
# endif

    t = cleanopen(line);
    if (t < 0)
	fatalperror(net, line);

#ifdef  STREAMSPTY
    ttyfd = t;


    /*
     * Not all systems have (or need) modules ttcompat and pckt so
     * don't flag it as a fatal error if they don't exist.
     */

    if (really_stream)
	{
	    /* these are the streams modules that we want pushed. note
	       that they are in reverse order, ptem will be pushed
	       first. maybe_push_modules() will try to push all modules
	       before the first one that isn't already pushed. i.e if
	       ldterm is pushed, only ttcompat will be attempted.

	       all this is because we don't know which modules are
	       available, and we don't know which modules are already
	       pushed (via autopush, for instance).

	       */

	    char *ttymodules[] = { "ttcompat", "ldterm", "ptem", NULL };
	    char *ptymodules[] = { "pckt", NULL };

	    maybe_push_modules(t, ttymodules);
	    maybe_push_modules(ourpty, ptymodules);
	}
#endif
    /*
     * set up the tty modes as we like them to be.
     */
    init_termbuf();
# ifdef	TIOCSWINSZ
    if (def_row || def_col) {
	memset(&ws, 0, sizeof(ws));
	ws.ws_col = def_col;
	ws.ws_row = def_row;
	ioctl(t, TIOCSWINSZ, (char *)&ws);
    }
# endif

    /*
     * Settings for sgtty based systems
     */

    /*
     * Settings for UNICOS (and HPUX)
     */
# if defined(_CRAY) || defined(__hpux)
    termbuf.c_oflag = OPOST|ONLCR|TAB3;
    termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
    termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
    termbuf.c_cflag = EXTB|HUPCL|CS8;
# endif

    /*
     * Settings for all other termios/termio based
     * systems, other than 4.4BSD.  In 4.4BSD the
     * kernel does the initial terminal setup.
     */
# if !(defined(_CRAY) || defined(__hpux)) && (BSD <= 43)
#  ifndef	OXTABS
#   define OXTABS	0
#  endif
    termbuf.c_lflag |= ECHO;
    termbuf.c_oflag |= ONLCR|OXTABS;
    termbuf.c_iflag |= ICRNL;
    termbuf.c_iflag &= ~IXOFF;
# endif
    tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600);
    tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600);

    /*
     * Set the tty modes, and make this our controlling tty.
     */
    set_termbuf();
    if (login_tty(t) == -1)
	fatalperror(net, "login_tty");
    if (net > 2)
	close(net);
    if (ourpty > 2) {
	close(ourpty);
	ourpty = -1;
    }
}