/* "Dumb terminal" session command for serial lines
 * Copyright 1991 Phil Karn, KA9Q
 *
 *      Feb '91 Bill Simpson
 *              rlsd control and improved dialer
 */
/* mods by PA0GRI */
#include "global.h"
#include "commands.h"
#include "mbuf.h"
#include "proc.h"
#include "iface.h"
#ifdef UNIX
#include "unixasy.h"
#else
#include "n8250.h"
#endif
#include "asy.h"
#include "tty.h"
#include "devparam.h"


#if !defined(_lint)
static char rcsid[] OPTIONAL = "$Id: tip.c,v 1.16 2001/05/06 16:32:58 brian Exp $";
#endif

static void tip_out (int dev,void *n1,void *n2);
static int tipcmd (int argc, char *argv[], void *);


/* Execute user tip command */
static int
tipcmd(argc,argv,p)
int argc OPTIONAL;
char *argv[];
void *p OPTIONAL;
{
struct session *sp = NULLSESSION;
register struct iface *ifp;
struct asy *ap;
char *ifn;
int (*rawsave) (struct iface *,struct mbuf *);
int c;
int usesession = 0;
struct proc *proc1;

	if((ifp = if_lookup(argv[1])) == NULLIF){
		tprintf(Badinterface,argv[1]);
		return 1;
	}
	ap = &Asy[ifp->dev];
	if( ifp->dev >= ASY_MAX || ap->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;
	}

	if (Curproc->input == Command->input) {
	        usesession = 1;
		/* Allocate a session descriptor */
		if ((sp = newsession (argv[1], TIP, 0)) == NULLSESSION){
			tputs (TooManySessions);
			return 1;
		}
		/* Put tty into raw mode */
		sp->ttystate.echo = 0;
		sp->ttystate.edit = 0;
		(void) sockmode(sp->output,SOCK_BINARY);
	}

	/* 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);
#ifdef POLLEDKISS
	suspend(ap->poller);
#endif

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

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

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

	while((c = get_asy(ifp->dev)) != -1)
#if 1
		tputc (uchar(c));
#else
		tputc(c & 0x7f);
#endif
	tflush();

	killproc(proc1);
	ifp->raw = rawsave;
	resume(ifp->rxproc);
#ifdef POLLEDKISS
	resume(ap->poller);
#endif
	if (usesession && sp) {
		sp->proc1 = NULLPROC;
		(void) keywait(NULLCHAR,1);
		freesession(sp);
	}
	return 0;
}


/* Execute user telnet command */
int
dotip(argc,argv,p)
int argc OPTIONAL;
char *argv[];
void *p OPTIONAL;
{
char **pargv;
int i;

	if (Curproc->input == Command->input) {
		/* Make private copy of argv and args,
		 * spawn off subprocess and return.
		 */
		pargv = (char **)callocw((size_t)argc + 1, sizeof(char *));
		for (i = 0; i < argc; i++)
			pargv[i] = strdup(argv[i]);
		pargv[i] = NULL;
		(void) newproc("tip",256,(void (*)(int,void *,void *))tipcmd,argc,(void *)pargv,p,1);
	} else
		(void) tipcmd(argc,argv,p);
	return 0;
}


/* Output process, DTE version */
static void
tip_out(dev,n1,n2)
int dev;
void *n1 OPTIONAL,*n2 OPTIONAL;
{
	struct mbuf *bp;
	int c;

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


