/* "Dumb terminal" session command for serial lines
 * Copyright 1991 Phil Karn, KA9Q
 *
 *	Feb '91	Bill Simpson
 *		rlsd control and improved dialer
 */

/****************************************************************************
*	$Id: tip.c 1.2 93/07/16 11:51:43 ROOT_DOS Exp $
*	14 Jun 93	1.2		GT	Fix warnings.									*
*
*  ATARI Version by David Nash - dnash@chaos.demon.co.uk
*
*  	__stdargs tip_out, dotip
*		Include st_asy.h in place of 8250.h
*
****************************************************************************/

#include "config.h"
#include "global.h"
#include "mbuf.h"
#include "proc.h"
#include "iface.h"
#ifdef ATARI
#include "st_asy.h"
#else
#include "8250.h"
#endif
#include "asy.h"
#include "tty.h"
#include "session.h"
#include "socket.h"
#include "commands.h"
#include "devparam.h"
#include "ip.h"


static void __stdargs tip_out __ARGS((int dev,void *n1,void *n2));


/* Execute user telnet command */

int __stdargs dotip(int argc, char *argv[], void *p)
{
	struct session *sp;
	struct iface *ifp;
	char *ifn;
	int (*rawsave) __ARGS((struct iface *,struct mbuf *));
	int c;

	if ((ifp = if_lookup(argv[1])) == NULLIF)  {
		tprintf("Interface %s unknown\n", argv[1]);
		return 1;
	}

	if (ifp->dev >= ASY_MAX || Asy[ifp->dev].iface != ifp )  { 
		tprintf("Interface %s not asy port\n", argv[1]);
		return 1;
	}

	if (ifp->raw == bitbucket)  {
		tprintf("tip or dialer session already active on %s\n", argv[1]);
		return 1;
	}

	/* Allocate a session descriptor */
	
	if ((sp = newsession(argv[1], TIP)) == NULLSESSION)  {
		tprintf("Too many sessions\n");
		return 1;
	}

	/* Save output handler and temporarily redirect output to null */
	
	rawsave = ifp->raw;
	ifp->raw = bitbucket;

	/* Suspend the packet input driver. Note that the transmit driver
	 * is left running since we use it to send buffers to the line.
	 */

	suspend(ifp->rxproc);

	/* Put tty into raw mode */

	sp->ttystate.echo = 0;
	sp->ttystate.edit = 0;
	sockmode(sp->output, SOCK_BINARY);

	/* Now fork into two paths, one rx, one tx */
	
	ifn = if_name( ifp, " tip out" );
	sp->proc1 = newproc(ifn, 256, tip_out, ifp->dev, NULL, NULL, 0);
	free(ifn);

	ifn = if_name(ifp, " tip in" );
	chname(Curproc, ifn );
	free(ifn);

	/* bring the line up (just in case) */
	
	if ( ifp->ioctl != NULL )
		(*ifp->ioctl)( ifp, PARAM_UP, TRUE, 0L );

	while((c = get_asy(ifp->dev)) != -1)
		tputc(c & 0x7f);
	tflush();

	killproc(sp->proc1);
	sp->proc1 = NULLPROC;
	ifp->raw = rawsave;
	resume(ifp->rxproc);
	keywait(NULLCHAR, 1);
	freesession(sp);
	return 0;
}


/* Output process, DTE version */

static void __stdargs tip_out(int dev, void *n1, void *n2)
{
	struct mbuf *bp;
	int c;

	while ((c = recvchar(Curproc->input)) != EOF) {
		if (c == '\n')
			c = '\r';									/* NL => CR                      */
		bp = pushdown(NULLBUF, 1);
		bp->data[0] = c;
		asy_send(dev, bp);
		Asy[dev].iface->lastsent = secclock();
	}
}


