
/* Position reporting-related user commands (derived from RIP)
 *   (c) 1993 Brian A. Lantz
 */
#include "global.h"
#ifdef GPS
#include "commands.h"
#include "mbuf.h"
#include "netuser.h"
#include "internet.h"
#include "iface.h"
#include "udp.h"
#include "gps.h"
#include "files.h"

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

static uint32 PosHost = 0xffffffffU;
char *CurrentPos;
static struct udp_cb *GPS_cb;
static struct timer POStimer;

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


/* Start Position agent listening at local GPS UDP port */
int
POSstart(argc, argv, p)
int argc OPTIONAL;
char *argv[] OPTIONAL;
void *p OPTIONAL;
{
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 OPTIONAL;
char *argv[] OPTIONAL;
void *p OPTIONAL;
{
	(void) 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,	NULL,		0,	0,	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 OPTIONAL;
{
	if (argc > 1)
		PosHost = resolve(argv[1]);
	tprintf ("Position reporting to: %s\n", inet_ntoa(PosHost));
	return 0;
}

/* Display current position data string */
static int
docurrent(argc,argv,p)
int argc OPTIONAL;
char *argv[] OPTIONAL;
void *p OPTIONAL;
{
	tprintf ("Current GPS Position data:\n%s\n", (!CurrentPos || !*CurrentPos) ? "unknown!\n" : CurrentPos);
	return 0;
}

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

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

	fp = fopen (GPSfile, "r");	/* no error checking yet */
	if (fp)		{
		tputs ("Current GPS Data:\n\n");
/*		rewind (fp);		*/
		while (!feof (fp))	{
			(void) 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 */
			if (cp != NULLCHAR)
				*cp = 0;
			tprintf ("%s\n", buf);
		}
		(void) fclose (fp);
	}
	return 0;
}

static int
dotimer(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
	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 (*)(void *))POStick;/* what to call on timeout */
	POStimer.arg = NULL;		/* dummy value */
	set_timer(&POStimer,atol(argv[1])*1000L); /* set timer duration */
	start_detached_timer(&POStimer);     /* fire it up */
	return 0;
}

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

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

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

	memset (buf, 0x20, GPSMAXLEN);
	while(len_p(bp))	{
		bpp = &bp;
		*cp++ = (char) PULLCHAR(bpp);
	}
	if ((cp = strchr (buf, ':')) == NULLCHAR)	/* not a valid gps frame */
		return;
	hostnamelen = (int) (cp - buf + 1);	/* include the ":" */
	fp = fopen (GPSfile, "a+");	/* no error checking yet */
	if (fp != NULLFILE)	{
		fseek (fp, GPSMAXLEN, 0);	/* don't touch 1st entry */
		while (!feof (fp))	{
			(void) fread (inbuff, 1, GPSMAXLEN, fp);
			if (!strncmp (inbuff, buf, (unsigned)hostnamelen))		{ /* found it */
				fseek (fp, (long) (ftell (fp) - (long) GPSMAXLEN), 0L);
				break;
			}
		}
		fwrite (buf, 1, GPSMAXLEN, fp);
		(void) 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 ((char *) bp->data, CurrentPos, GPSMAXLEN);
	bp->cnt = (int16) strlen ((char *) bp->data);
	(void) send_udp(&lsock, &fsock,0,0,bp,bp->cnt,0,0);
	return 0;
}

#endif
