
/* Position reporting-related user commands (derived from RIP)
 *   (c) 1993 Brian A. Lantz
 */
#include <stdio.h>
#include "global.h"
#include "mbuf.h"
#include "netuser.h"
#include "internet.h"
#include "cmdparse.h"
#include "timer.h"
#include "iface.h"
#include "udp.h"
#include "rip.h"
#include "commands.h"
#include "gps.h"

static int32 PosHost = -1;
char *CurrentPos;
static struct udp_cb *GPS_cb;
static struct timer POStimer;

static int docurrent __ARGS((int argc,char *argv[],void *p));
static int doposhostname __ARGS((int argc,char *argv[],void *p));
static int dolist __ARGS((int argc,char *argv[],void *p));
static int dotimer __ARGS((int argc,char *argv[],void *p));
void POStick __ARGS((void *v));
static void gps_rx __ARGS((struct iface *iface,struct udp_cb *sock,int cnt));
static int gps_tx __ARGS((void));
static int doPOSkick __ARGS((int argc,char *argv[],void *p));


/* Start Position agent listening at local GPS UDP port */
int
POSstart()
{
struct socket lsock;

	lsock.address = INADDR_ANY;
	lsock.port = IPPORT_GPS;

	if(GPS_cb == NULLUDP)
		GPS_cb = open_udp(&lsock,gps_rx);

	return 0;
}

int
POSstop(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	del_udp(GPS_cb);
	GPS_cb = NULLUDP;
	return 0;
}


static struct cmds Positioncmds[] = {
	"current",	docurrent,	0,	0,	NULLCHAR,
	"hostname",	doposhostname,	0,	0,	NULLCHAR,
	"kick",		doPOSkick,	0,	0,	NULLCHAR,
	"list",		dolist,		0,	0,	NULLCHAR,
	"timer",	dotimer,	0,	0,	NULLCHAR,
	NULLCHAR,
};

int
doposition(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	return subcmd(Positioncmds,argc,argv,p);
}

/* Set the host that we are to report position data to */
static int
doposhostname(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	if (argc > 1)
		PosHost = resolve(argv[1]);
	tprintf ("Position reporting to: %s\n", inet_ntoa(PosHost));
	return 0;
}

/* Display current position data string */
int
docurrent(argc,argv,p)
int argc;
char *argv[];
void *p;
{
char *cp;

	if (!CurrentPos || !*CurrentPos)
		cp = "unknown!\n";
	else
		cp = CurrentPos;
	tprintf ("Current GPS Position data:\n%s\n", cp);
	return 0;
}

static int
doPOSkick(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	POStick (NULL);
	return 0;
}

static int
dolist(argc,argv,p)
int argc;
char *argv[];
void *p;
{
char buf[GPSMAXLEN + 1], *cp;
FILE *fp;

	fp = fopen (GPSfile, "r");	/* no error checking yet */
	if (fp)		{
		tprintf ("Current GPS Data:\n\n");
/*		rewind (fp);		*/
		while (!feof (fp))	{
			fread (buf, 1, GPSMAXLEN, fp);
			if (feof (fp))
				continue;
#ifdef nope
#ifdef TNOS_68K
			cp = strpbrk (buf, "\n\l");	/* no error chk */
#else
			cp = strpbrk (buf, "\r\n");	/* no error chk */
#endif
			*(++cp) = 0;
#endif
			cp = strchr (buf, '*'); /* find beginning of checksum */
			*cp = 0;
			tprintf ("%s\n", buf);
		}
		fclose (fp);
	}
	return 0;
}

static int
dotimer(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	if(argc < 2){
		tprintf("Outgoing Position timer: %lu/%lu\n",
			read_timer(&POStimer)/1000L,
			dur_timer(&POStimer)/1000L);
		return 0;
	}
	stop_timer (&POStimer);	/* just in case */
	POStimer.func = (void (*)__ARGS((void *)))POStick;/* what to call on timeout */
	POStimer.arg = NULL;		/* dummy value */
	set_timer(&POStimer,atol(argv[1])*1000L); /* set timer duration */
	start_timer(&POStimer);     /* fire it up */
	return 0;
}

void
POStick (v)
void *v;
{
#ifdef nope
	if (GPSactive != NULLIF)		{	/* GPS must be started */
		psignal (GPSactive, 0);	/* wake up the GPS daemon */
		pwait (CurrentPos);	/* wait until it's update is complete */
	}
#endif
	if (CurrentPos && *CurrentPos)	/* not if nothing there */
		gps_tx();
	start_timer(&POStimer);     /* fire it up */
}

/* Process GPS input received from 'interface'. */
static void
gps_rx(iface,sock,cnt)
struct iface *iface;
struct udp_cb *sock;
int cnt;
{
struct mbuf *bp;
struct socket fsock;
char buf[GPSMAXLEN + 1], *cp = buf;
char inbuf[GPSMAXLEN + 1];
FILE *fp;
int hostnamelen;

	/* receive the RIP packet */
	recv_udp(sock,&fsock,&bp);

	memset (buf, 0x20, GPSMAXLEN);
	while(len_p(bp))
		*cp++ = PULLCHAR(&bp);
	if (!(cp = strchr (buf, ':')))	/* not a valid gps frame */
		return;
	hostnamelen = (int) (cp - buf + 1);	/* include the ":" */
	fp = fopen (GPSfile, "a+");	/* no error checking yet */
	fseek (fp, GPSMAXLEN, 0);	/* don't touch 1st entry */
	while (!feof (fp))	{
		fread (inbuf, 1, GPSMAXLEN, fp);
		if (!strncmp (inbuf, buf, (unsigned)hostnamelen))		{ /* found it */
			fseek (fp, (long) (ftell (fp) - (long) GPSMAXLEN), 0L);
			break;
		}
	}
	fwrite (buf, 1, GPSMAXLEN, fp);
	fclose (fp);
	return;		
}

/* Send a GPS packet to the specified destination */
static int
gps_tx()
{
struct mbuf *bp;
struct socket lsock,fsock;

	lsock.address = INADDR_ANY;
	fsock.address = PosHost;
	lsock.port = fsock.port = IPPORT_GPS;

	/* Send out one GPS packet as a broadcast to 'dest'  */
	if((bp = alloc_mbuf(GPSMAXLEN)) == NULLBUF)
		return -1;

	strncpy (bp->data, CurrentPos, GPSMAXLEN);
	bp->cnt = strlen (bp->data);
	send_udp(&lsock, &fsock,0,0,bp,bp->cnt,0,0);
	return 0;
}

