/*
 * axui <iface> [unproto_call]   --   send unproto packets via <iface>.
 * From TNOS by KO4KS.  Mods by K5JB.
 */
#include "global.h"
#ifdef AXUI
#include "ctype.h"
#include "commands.h"
#include "session.h"
#include "smtp.h"
#include "usock.h"
#include "mailbox.h"
#include "pktdrvr.h"

#if !defined(_lint)
static char rcsid[] OPTIONAL = "$Id: axui.c,v 1.16 1997/06/13 13:15:31 root Exp $";
#endif

int Axui_sock = -1;		/* Socket number listening for AX25 UI frames */
static struct iface *axif;
static int ui_timestamp = 1;	/* Time and etc, in displayed header - K5JB */
static int ui_verbose = 0;	/* Toggle on/off verbose headers */
static int ui_header = 1;	/* Toggle on/off use of headers */
static int ui_silent = 0;	/* Toggle on/off supression of bell characters */

static char lastsrc[AXALEN], lastdest[AXALEN];

static char help[] = "<Cmds>:\n  /c call (set new outgoing call)      /i iface (set new outgoing interface)\n  /h      (toggle use of headers)      /v       (verbose headers - use always)\n  /t      (toggle use of timestamp)    /q       (to quit)\n";
static char running[] = "%s already running\n";
static char notax25[] = "Iface %s not an AX25 type interface\n";
static char notdefined[] = "Iface %s not defined\n";
static char sessionstr[] = "%s%s session %d UI frames %s->%s on interface %s\n%s";
static char forhelp[] = "For help, type '/?'\n";
static char badiface[] = "<invalid interface>\n";
static char headersstr[] = "*** Headers %sabled\n";
static char Enstr[] = "En";
static char Disstr[] = "Dis";
static char verbosestr[] = "*** Headers displayed %s\n";
static char packetstr[] = "for each packet";
static char changestr[] = "when src or dest changes";
static char timestamp[] = "*** Timestamping in headers is %sabled\n";
static char silentstr[] = "*** Silent mode is %sabled\n";
static char sessionclosed[] = "\n%s session %u closed: EOF\n";
static char display1[] = "\n%s - %s recv: %s->%s:\n";
static char display2[] = "\n%s->%s:\n";
static char DigisUsed[] = "Illegal when digis in use.\n";


int 
doaxui (int argc, char *argv[], void *p OPTIONAL)
{
char *cp;
char name[AXBUF];
char buf[200];
int16 i;
char tmpcall[AXALEN];
char tmpcall2[AXBUF];
struct session *sp;
struct mbuf *bp;
struct iface *ifc;
int first = 1;

	/* Check if this comes from console */
	if (Curproc->input != Command->input)
		return 0;

	/* Check to see if AXUI is already running. Only one copy at a time */
	if (Axui_sock != -1) {
		tprintf (running, Sestypes[AXUITNC]);
		return 1;
	}
	if (((axif = if_lookup (argv[1])) != NULLIF) && (axif->type != CL_AX25)) {
		tprintf (notax25, argv[1]);
		return 1;
	}
	if (axif == NULLIF) {
		tprintf (notdefined, argv[1]);
		return 1;
	}
	if (argc == 2 || setcall (tmpcall, argv[2]) == -1)
		memcpy (tmpcall, Ax25multi[IDCALL], AXALEN);

	if (argc > 3)		/* digis present? */
		if (connect_filt (argc, argv, tmpcall, axif, AX_AUTO) == 0)
			return 1;

	(void) pax25 (name, AXuser);
	/* Now everything seems okay ! Get a session */
	if ((sp = newsession (name, AXUITNC, 1)) == NULLSESSION) {
		tputs (TooManySessions);
		return 0;
	}

restart:
	tprintf (sessionstr, (first) ? "" : "\n", Sestypes[sp->type], sp->index, pax25 (tmpcall2, AXuser),
		 pax25 (name, tmpcall), axif->name, (first) ? forhelp : "");
	Axui_sock = Curproc->output;
	first = 0;

	/* Process whatever's typed on the terminal */
	memset (buf, 0, MBXLINE);	/* Clear the input buffer */
	while (recvline (Curproc->input, (unsigned char *) buf, sizeof (buf) - 1) >= 0) {
		if (buf[0] == '/') {
			cp = skipnonwhite (buf);
			cp = skipwhite (cp);
			rip (cp);
			/* process commands */
			switch (tolower (buf[1])) {
				case '?':
					tputs (help);
					goto restart;
				case 'c':
					if (argc > 3) {
						tputs (DigisUsed);
						break;
					}
					if (setcall (tmpcall2, cp) == -1)
						break;
					memcpy (tmpcall, tmpcall2, AXALEN);
					goto restart;
				case 'i':
					if (argc > 3) {
						tputs (DigisUsed);
						break;
					}
					if (((ifc = if_lookup (cp)) != NULLIF) && (ifc->type == CL_AX25)) {
						axif = ifc;
						goto restart;
					} else
						tputs (badiface);
					break;
				case 'h':
					ui_header ^= 1;
					tprintf (headersstr, (ui_header) ? Enstr : Disstr);
					break;
				case 'v':
					ui_verbose ^= 1;
					tprintf (verbosestr, (ui_verbose) ? packetstr : changestr);
					break;
				case 't':
					ui_timestamp ^= 1;
					tprintf (timestamp, (ui_timestamp) ? Enstr : Disstr);
					break;
				case 's':
					ui_silent ^= 1;
					tprintf (silentstr, (ui_silent) ? Enstr : Disstr);
					break;
				case 'b':
				case 'e':
				case 'q':
					goto done;
				default:
					tputs ("Huh?\n");
					break;
			}
		} else {
			i = (int16) strlen (buf);
			buf[i - 1] = '\r';
			if ((bp = alloc_mbuf (i)) == NULLBUF)
				goto done;
			bp->cnt = i;
			memcpy (bp->data, buf, (size_t) i);

			(void) (*axif->output) (axif, tmpcall, AXuser, PID_NO_L3, bp);	/* send it */
		}
		usflush (Curproc->output);
		memset (buf, 0, MBXLINE);	/* Clear the input buffer */
	}
done:
	if (argc > 3)
		(void) ax_drop (tmpcall, axif, AX_AUTO);	/* remove digi route added by connect_filt */
	Axui_sock = -1;
	tprintf (sessionclosed, Sestypes[sp->type], sp->index);
	(void) keywait (NULLCHAR, 1);
	freesession (sp);
	return 0;
}


void
axui_input (iface, axp, src, dest, bp, mcast)
struct iface *iface;
struct ax25_cb *axp OPTIONAL;
char *src;
char *dest;
struct mbuf *bp;
int mcast OPTIONAL;
{
time_t timer;
char *cp;
char buf[256];
int16 n, nn = 0;
char thissrc[AXBUF], thisdest[AXBUF];

	if (Axui_sock != -1) {
		(void) pax25 (thissrc, src);
		(void) pax25 (thisdest, dest);
		if (ui_header && (ui_verbose || memcmp (lastsrc, src, AXALEN) || memcmp (lastdest, dest, AXALEN))) {
			memcpy (lastsrc, src, AXALEN);
			memcpy (lastdest, dest, AXALEN);
			if (ui_timestamp) {
				(void) time (&timer);
				cp = ctime (&timer);
				cp[24] = '\0';
				usprintf (Axui_sock, display1, cp, iface->name, thissrc, thisdest);
			} else
				usprintf (Axui_sock, display2, thissrc, thisdest);
		}
		while ((n = pullup (&bp, (unsigned char *) buf, sizeof (buf) - 1)) != 0) {
			buf[n] = 0;
			if (ui_silent) {
				do {
					cp = strchr (buf, 0x07);
					if (cp)
						*cp = '.';
				} while (cp);
			}
			nn = (int16) usprintf (Axui_sock, "%s", buf);
		}
		if (nn && buf[nn - 1] != '\n')
			usputc (Axui_sock, '\n');
		usflush (Axui_sock);
	}
	free_p (bp);
}


#endif /* AXUI */
