#ifndef lint
static char *RCSid = "$Header: empdis.c,v 1.16 90/03/19 10:54:05 mr-frog Exp $";
#endif /* not lint */

/*
 * empdis.c
 *
 * empire dispatcher stuff
 *
 * from PSL Empire, 1985
 */

#include <stdio.h>
#include "misc.h"
#include "nat.h"
#include "tel.h"
#include "proto.h"
#include "com.h"
#include "deity.h"
#include "keyword.h"
#include "file.h"
#include "io.h"

#include <fcntl.h>
#include <sys/time.h>
#include <signal.h>

int
getcommand(combufp)
	char	*combufp;
{
	struct	natstr *natp;
	char	buf[512];

	natp = getnatp(cnum);
	do {
		prprompt(natp->nat_minused, natp->nat_btu);
		*buf = 0;
		if (recvclient(buf, sizeof(buf)) < 0)
			return -1;
	} while (*buf == 0);
	copy(buf, combufp);
	return (strlen(combufp));
}

init_files()
{
	extern	int commf;
	extern	char upfil[];
	extern	char commfil[];
	int	upf;
	struct	telstr tgm;
	char	buf[512];

	ef_init();
	/* open the rest of the empire files */
	ef_open(EF_NATION, O_RDONLY, EFF_MEM);
	ef_open(EF_SECTOR, O_RDWR, 0);
	ef_open(EF_NEWS, O_RDWR, 0);
	ef_open(EF_LOAN, O_RDWR, 0);
	ef_open(EF_SHIP, O_RDWR, 0);
	ef_open(EF_PLANE, O_RDWR, 0);
	ef_open(EF_TREATY, O_RDWR, 0);
	ef_open(EF_NUKE, O_RDWR, 0);
	ef_open(EF_POWER, O_RDWR, 0);
	ef_open(EF_TRADE, O_RDWR, 0);
	commf = open(commfil, O_RDWR, 0);
	if ((upf = open(upfil, O_RDONLY, 0)) < 0)
		return;
	if (read(upf, (char *) &tgm, sizeof(tgm)) != sizeof(tgm)) {
		logerror("bad header on login message (upfil)");
		return;
	}
	if (read(upf, buf, tgm.tel_length) != tgm.tel_length) {
		logerror("bad length %d on login message", tgm.tel_length);
		return;
	}
	if (tgm.tel_length >= sizeof(buf))
		tgm.tel_length = sizeof(buf)-1;
	buf[tgm.tel_length] = 0;
	pr(buf);
	(void) close(upf);
}

explain()
{
	register char *format;
	register int i;

	pr("\t\tCurrent EMPIRE Command List\n");
	pr("\t\t------- ------ ------- ----\n");
	pr("Initial number is cost in B.T.U. units.\n");
	pr("Args in [brackets] are optional.\n");
	if (nstat > 4) {
		pr("All-caps args in <angle brackets>");
		pr(" have the following meanings:\n");
		pr("  <NUM> :: a number in unspecified units\n");
		pr("  <COMM> :: a commodity such as `food', `guns', etc\n");
		pr("  <VAR> :: a commodity such as `food', `guns', etc\n");
		pr("  <TYPE> :: an item type such as `ship', `plane', etc\n");
	}
	for (i = 0; (format = coms[i].c_form) != 0; i++) {
		if ((coms[i].c_permit & ncomstat) == coms[i].c_permit)
			pr(fmt("%d %s\n", coms[i].c_cost, format));
	}
	pr("For further info on command syntax see \"info syntax\".\n");
	return RET_OK;
}

/*
 * returns true if down
 */
int
gamedown()
{
	extern	char downfil[];
	int	downf;
	struct	telstr tgm;
	char	buf[512];

	if (god)
		return 0;
	if ((downf = open(downfil, O_RDONLY, 0)) < 0)
		return 0;
	if (read(downf, (char *) &tgm, sizeof(tgm)) != sizeof(tgm)) {
		logerror("bad header on login message (downfil)");
		return 1;
	}
	if (read(downf, buf, tgm.tel_length) != tgm.tel_length) {
		logerror("bad length %d on login message", tgm.tel_length);
		return 1;
	}
	if (tgm.tel_length >= sizeof(buf))
		tgm.tel_length = sizeof(buf)-1;
	buf[tgm.tel_length] = 0;
	pr(buf);
	pr("\nThe game is down\n");
	(void) close(downf);
	return 1;
}

daychange(now)
	time_t	now;
{
	struct	natstr *natp;
	struct	tm *tm;

	natp = getnatp(cnum);
	tm = localtime(&now);
	if ((tm->tm_yday % 128) != natp->nat_dayno) {
		NAT_SET(nat_dayno, cnum, tm->tm_yday % 128);
		NAT_SET(nat_minused, cnum, 0);
	}
}

getconstants()
{
	extern	int adj_update;
	extern	int etu_per_update;
	extern	int s_p_etu;
	char	*bp;
#ifdef BLITZ
	extern	time_t	blitz_time;

	if (bp = kw_find("blitz_time"))
		kw_parse(CF_VALUE, bp, &blitz_time);
#endif /* BLITZ */
	if (bp = kw_find("adj_update"))
		kw_parse(CF_VALUE, bp, &adj_update);
	if (bp = kw_find("etu_per_update"))
		kw_parse(CF_VALUE, bp, &etu_per_update);
	if (bp = kw_find("s_p_etu"))
		kw_parse(CF_VALUE, bp, &s_p_etu);
}

int
getminleft(now, hour, mpd)
	time_t	now;
	int	*hour;
	int	*mpd;
{
	char	*bp;
	struct	tm *tm;
	int	nminleft;
	int	curtime;
	struct	natstr *natp;
	int	n;

	tm = localtime(&now);
	curtime = tm->tm_min + tm->tm_hour * 60;
	if (bp = kw_find("minutes"))
		kw_parse(CF_VALUE, bp, mpd);
	natp = getnatp(cnum);
	nminleft = *mpd - natp->nat_minused;
	if (bp = kw_find("hours")) {
		/*
		 * assume hours has already been set; just verify
		 * that it is present
		 */
		n = hour[1] - curtime;
		if (n < nminleft)
			nminleft = n;
	}
	n = 60*24 - (tm->tm_min + tm->tm_hour*60);
	if (n < nminleft)
		nminleft = n;
	return nminleft;
}

tm_exit(code)
	int	code;
{
	extern	iop_t playerio;
	extern	iop_t iop;

	/* This routine is modified ala the changed to update/main.c */
	if (iop != 0 && !io_error(iop) && !io_eof(iop)){
		NAT_SET(nat_login, cnum, 0);
		tm_close();
		io_noblocking(iop, 1);
	}

	while ((iop != 0) && !io_eof(iop) && !io_error(iop)){
		io_flush();
		io_select(0);
		io_input(iop);
		io_output(iop);
	}

	if (iop != 0)
		io_close(iop);

	(void) outid(C_EXIT);
	io_puts(playerio, "so long...\n");
	/* do what we can to flush...then bail */
	io_shutdown(playerio, IO_READ);
	io_noblocking(playerio, 0);
	while (io_output(playerio) > 0)
		;
	io_close(playerio);
	if (isatty(0)) {
		/* XXX debug only */
		close(0);
		open("/dev/tty", 0, 0);
		fcntl(0, F_SETFL, 0);
	}
	exit(code);
}
