#include "fido.h"
#include <ascii.h>
#include "fidomem.h"
#include "proto.h"

/* This function is to let the main pre-load this overlay for caller
performance. It does nothing except reside in the proper overlay. */

void fido_ov_load() {
}

/* Main function for Fido. Handles one caller, then returns to the
main section. */

int do_fido() {
int time,i,n;
int ev,to_mail;
long x;
char *cp,c;

	cd_flag= 0;				/* enable carrier-loss detection */
	terminate= 0;				/* no terminate-after */
	clr_clk();				/* start counting */
	*ovpath= NUL;				/* no path override */
	n= -1;					/* (if carrier is lost) */
	fido.caller= -1;			/* no caller is on */

	crashmail= 1;				/* process fidonet sync chars */
	crashcode= 0;				/* during signon process */
	set_abort(0);				/* set carrier loss trap */
	if (was_abort()) {			/* return to main */
exit:		close_node();			/* close node files */
		close_up();			/* close aborted files */
		close_clr();			/* caller logoff/G-Errorlevel */
		write_lastuser();		/* generate communication files */
		getsys();			/* reload default stuff */
		rept_stack();
		cprintf(FM+1);
		return(crashcode);
	}
	open_node();				/* open node files */
	mconflush();				/* flush interrupt buffers */
	cmdflush();				/* flush command buffers */
	gtod(date);				/* get signon date, */
	loadlang(0);				/* get system default language */
	switch (signon()) {			/* login, see what happened */
		case 1: break;			/* connected OK -- proceed */
		case 0: goto exit;		/* special login -- no disconnect */
		default: logoff(0,1);		/* bad signon -- disconnect */
	}
	crashmail= 0;				/* no longer process sync chars */
	if (! localout) cprintf(SM+124,caller.name,caller.city,datarate,caller.times,minutes,seconds,user_limit);
	maketid(text,"MSG.BUF");
	delete(text);				/* kill the message buffer */
	if (!test && fbit(FBIT_TLG)) timelog(0);/* keep statistics, */
	line= 0;				/* sync up "more" stuff, */
	quote("quotes.bbs");			/* quote for the day, needs SYSTEM.bbs */
	main_menu();
}

/* Logoff the caller. Set the GoodBye-ErrorLevel code. If this is a normal 
exit (G command, time limit exceeded, carrier lost, etc) and not an error 
or special occasion (error, incoming FidoNet) re-enable the RUSH events and 
set the G-errorlevel code. */

void close_clr() {
int f;
long p;

	if (! doscode) {			/* if no errorlevel specified */
		doscode= fido.byecode;		/* use G-ErrorLevel code */
		clrrevts();			/* clear RUSH events */
		clrcevts();			/* clear CONT events */
	}
	fido.autolog= -1;			/* dont autolog again */
	if (fido.caller != -1) {		/* if a caller logged in */
		if (! test) {
			++fido.callers;		/* count another call, */
			caller.time += minutes;	/* accumulate time on, */
		}
		strcpy(caller.date,date);	/* last time called */
		if (minutes > user_limit) caller.tleft= 0;
		else caller.tleft= user_limit - minutes;
		write_clr();			/* update caller record */
		lprintf(LM+33,caller.times,minutes);
	}
	putsys();				/* update system file, */
}

/* Try a number of times to open the caller file  */

int openclr() {
int i,f;
char buff[SS];

	makesname(buff,"caller.sys");		/* open CALLER.SYS */
	for (i= 10; i--;) {
		f= open(buff,2);		/* make a few tries */
		if (f != -1) return(f);
		delay(5);
	}
	return(-1);
}

/* Write the caller record to disk. */

int write_clr() {
int f;
long p;

	f= openclr();				/* open CALLER.SYS */
	if (f == -1) return(-1);
	p= 0L + fido.caller; p *= sizeof(struct _clr);
	lseek(f,p,0);				/* proper place, */
	write(f,&caller,sizeof(struct _clr));
	close(f);				/* update caller, */
	return(0);
}