/************************************************************************
 *   Metal Sysop Routines for METAL
 *
 *	FILE: MESYSOP.C
 *
 *	Metal and Metal Message System are Trademarked and
 *	     Copyright (c) 1984, 1985, 1986 Tim Gary
 *		    All rights reserved
 *
 ************************************************************************
 *
 * 1.50xx 08/14/86 Fixed for new free_space() function..
 * 1.50xx 03/09/86 Fixed for reply stuff, and no comments file..
 * 1.40xx 01/26/86 New format of a few things..
 * 1.31a  10/13/85 Release version.  Security improved for '!' command.
 *		   Space on disk, and write error checks made during purge.
 *		   Purge function is now AT LEAST TWICE AS FAST..
 * 1.30xx 6/23/85  BAK files deleted before rename..
 * 1.30xx 3/03/85  Z3 stuff looked into for this module
 * 1.20b 01/07/85  Double purge bug corrected.
 * 1.20a 11/07/84  Purge message after effects muffled.
 * 1.20a 11/04/84  Few more safeguards added.
 * 1.10e 11/03/84  Ho hum, added info about disk reset, etc..
 * 1.10e 11/02/84  Make purge function work!.. (after yesterday)
 * 1.10e 11/01/84  Reset disk performed before purge..
 * 1.10e 10/31/84  Added sostat() and readcomm().
 *		  Fixed purge messages to allow seperate output
 *		  drive for message file.
 * 1.10c 10/12/84  Modified to use msg[] table for reply/parent
 *		  in case of conficts found earlier.
 * 1.10b  <none>
 * 1.10a  9/26/84  Fixed purge to allow messages on drives
 *		  than A:
 * 1.10a  9/01/84  Split from mutil.c for overlay Metal.
 *
 * 1.01c  8/16/84  Improved bad record handling, and patchup.
 *
 * 1.01b  8/03/84  Fixed to handle message purge cases when a
 *		  summary file is unavailable, or destroyed..
 *		  This is handled by removing or renaming the 
 *		  the destroyed summary file, and index will be
 *		  built from message file directly.
 *
 * 1.01a  6/10/84  Fixed for Aztec C 1.06.
 *
 ***********************************************************************/

#include "xpm.h"	/* CPMIO header file for i/o operations.*/
#include "megen.h"	/* general defines		*/
#include "meglob.h"	/* global variable definitions	*/
#include "meovfn.h"	/* overlay function numbers	*/
#include "mefiles.h"	/* file names			*/

#include "ctype.h"


/* Main dispatcher */

ovmain(func,parm)
int func,parm;
{

switch (func)
	{
	case PURGE:
		if (user.status!=SYSOP) return;
		return destroy(parm);
	case SOSTAT:
		return sostat(parm);
	default:
		send("\nUnknown overlay function called for.\n");
		break;
	}

return ERROR;
}	/* main */


FILE *msource,*mdest;
static int new_index,nmsg_rec;	/* index variable, last+1 rec of msg file */

destroy(parm)
 int parm;
{
int tindex,err_flag;
unsigned total;
char temp[50],msgdest[30],sumdest[30],countdest[30],*tp,newdrive[10];
msg_record *mptr;

new_index=total=0;

if (!lmsg) {
	send("\nNo messages to purge.\n");
	return;
	}

msource=open(MESSAGES,0);

printf("\nThere are %d active messages, and %d deleted messages (unpurged).\n",
	msgcount,mindex-msgcount);
if (msource)
	{
	toeof(msource);
	nmsg_rec=getrec(msource);
	total=(nmsg_rec+7)>>3;
	printf("\nMessage file now %dk",total);
	}
if (summary=open(SUMMARY))
	{
	toeof(summary);
	total+=(getrec(summary)+7)>>3;
	printf(",  Summary file is %dk\n",(getrec(summary)+7)>>3);
	close(summary);
	}

/* check if possible problem with purge to same drive */

printf("\nFree space on same drive is %uK\n",free_space(summary->_fcb.f_drive));

if ( total+2 > free_space(summary->_fcb.f_drive) )
	printf("\nWARNING: Space remaining on same drive is less than the total space used\nby the current summary, messages and counters files.");

/* make sure the person still wants to do the purge */

close(msource);		/* cause gotta close for reset disk */

ask("\n\nPurge messages (y/n) ?",temp,1,UP);
if (*temp!='Y') return;

send("\nPress any key to perform a disk reset and continue.\n(swap disks NOW if you need to!) --> ");
getchar();

reset_disk(0);
msource=open(MESSAGES,0);
mptr=bufloc(msource);

*newdrive='\0';	/* nothing */

do {
   ask("\n\nUser area/Drive to place new files on ( uu/d: )\n(RETURN=same as message source files)? ",temp,8,UP);
   if (index(temp,':') || index(temp,'/'))
	{
	sprintf(buffer,"\nNew user/drive = '%s', ok (y/n)? ",temp);
	ask(buffer,temp+10,2,UP);
	if (temp[10]=='Y')
		{
		strcpy(newdrive,temp);	/* put in place */
		break;
		}
	continue;
	}
     else if (*temp=='\0') break;
    } while (1);

send("\n\n[Purging messages]\n");

if (!*newdrive)
	{
	unlink("summary.bak");
	rename(SUMMARY,"summary.bak");	/* backup of summary file */
	summary=open(SUMMARY,1);	/* make new summary file  */
	}
  else {
       sprintf(sumdest,"%ssummary",newdrive);
       unlink(sumdest);		/* make sure no file previously */
       summary=open(sumdest,1);
       }

*msgdest='\0';
if (tp=index(MESSAGES,':'))	/* THIS = IS ON PURPOSE !!! */
	{
	strncpy(msgdest,MESSAGES,tp-MESSAGES+1);
	msgdest[tp-MESSAGES+1]='\0';	/* terminate */
	}

if (*newdrive)
	{
	sprintf(msgdest,"%smessages",newdrive);
	sprintf(countdest,"%scounters",newdrive);
	unlink(countdest);	unlink(msgdest);
	}
  else
	{
	strcat(msgdest,"messages.new");
	unlink("counters.bak");
	rename(COUNTERS,"counters.bak");	/* backup counters */
	*countdest='\0';
	}

if (*newdrive)
	printf("\nOutput message file is %s.\nOutput summary file is %s.\n\
Output counters file is %s.\n",msgdest,sumdest,countdest);

mdest=open(msgdest,1);

if (!(msource && mdest && summary))
	{
	printf("\nCan't open all files...\nMESSAGES=%s  NEWMESS=%s  SUMMARY=%s \n\n",
	msource ? "<open>" : "<Couldn't open>",
	mdest ? "<open>" : "<Couldn't open>",
	summary ? "<open>" : "<Couldn't open>");
	close(msource); close(mdest); close(summary);
	return;
	}

sprintf(bufloc(summary),"%u",msgcount);
write(summary,1);

tindex=0;
while (tindex<mindex)
	{
	setarec(msource,msg[tindex].seek);	/* fix if bad recs.. */
	read(msource,1);	/* into buffer pointed to by mptr */
	if (mptr->status!=DEADMSG)
		if ((err_flag=wrtmsg(mdest,tindex))==ERROR) /* out to file */
			break;		/* stop here.. */
	++tindex;
	}
mindex=new_index;

if (err_flag!=ERROR)
  printf("\n\nMessage file now %dk,  Summary file is %dk\n\n[Finishing up]\n",
	(getrec(mdest)+7)/8,(getrec(summary)+7)/8);

close(mdest);
close(summary);
close(msource);
if (!*newdrive)
	{
	if (err_flag!=ERROR)
		{
		unlink("messages.bak");
		rename(MESSAGES,"messages.bak");   /* backup message file */
		rename(msgdest,MESSAGES);
		}
	  else	{
		unlink(msgdest);
		rename("counters.bak",COUNTERS);
		unlink(SUMMARY);
		rename("summary.bak",SUMMARY);
		}
	}

if (err_flag!=ERROR) pcounters(*countdest ? countdest : 0);
 else send("\n\n*** ERROR encountered while writing new file.  Operation ABORTED ***\n");

send("\nPress any key to return to command mode.\n(swap disks back NOW if you need to!) --> ");
getchar();
reset_disk(0);		/* make sure buffers flushed */

if (err_flag==ERROR)
	{
	send("\n\nSince an error was encountered, tables will now be rebuilt using the\nmessage alert function....\n");
	ovovload(OVINFREQ,MSGALERT,0);	/* fix tables after a bad purge */
	}

printf("\n\n[done]\n");

} /* destroy */


wrtmsg(fil,tindex)
 FILE *fil;
 int tindex;
{
msg_record *mptr;
int len,tlen;
char *buf,*tbuf;


mptr=bufloc(msource);
sprintf(buffer,"\r[Processing %5u]",mptr->number);
send(buffer);

msg[new_index].number=mptr->number;
msg[new_index].seek=mptr->seek=getrec(fil);		/* fix seek loc      */
msg[new_index].parent=mptr->parent=msg[tindex].parent;	/* fix if bombed     */
msg[new_index++].group=mptr->group=msg[tindex].group;

movmem(bufloc(msource),bufloc(fil),128);	/* copy to output buffer   */
if (write(fil,1)!=128) return ERROR;
movmem(bufloc(msource),bufloc(summary),128);
if (write(summary,1)!=128) return ERROR;

/* if last, use global eof rec pointer to compute size.. */
if (tindex>=mindex-1) len=nmsg_rec-getrec(msource);
  else len=msg[tindex+1].seek-getrec(msource);

tlen=len;

if ( (tbuf=buf=malloc(len*128+20))==(char *)0)
	{	/* we do it the slower way if not enuf space */	
	while (len--)
		{
		if (read(msource,1)!=128) break;
		movmem(bufloc(msource),bufloc(fil),128);
		if (write(fil,1)!=128) return ERROR;
		}
	}
  else		/* we can do it the fastest way... */
	{
	while (len--)
		{
		if (read(msource,1)!=128)
			{
			tlen=tlen-len-1;  /* point to actual number read */
			break;
			}
		movmem(bufloc(msource),tbuf,128);
		tbuf+=128;
		}
	tbuf=buf;
	while (tlen--)		
		{
		movmem(tbuf,bufloc(fil),128);
		tbuf+=128;
		if (write(fil,1)!=128)
			{
			free(buf);
			return ERROR;
			}
		}
	free(buf);
	} /* most efficient way else.. */

}	/* write message */


/***********************
 * Toggle sysop status * 
 ***********************/

extern char ostat,sotries;	/* these are defined in metal.c */

sostat(n)
 register int n;
{
if (user.status==SYSOP) {
	if (ostat!=0) {
		user.status=ostat;
		user.type_ptr=get_tp(user.status);
		}  else {
			ostat=user.status=SPECIAL;
			user.type_ptr=get_tp(SPECIAL);
			}
		send("[Sysop status Off]");
#ifdef Z3
		if (O.ZCPR==3) ovovloader(OVZ3,INITZ3,TRUE);
#endif
		return;
		}
ask("Prove it! ",buffer,PASSLEN+1,UP+NOECHO);	/* why not */
if (!strcmp(buffer,O.SOPASS))
	{
	ostat=user.status;	/* save original status and type */
	user.status=SYSOP;
	user.type_ptr=get_tp(SYSOP);
	sotries=0;
	send("[Sysop status On]");
	}
    else if (++sotries>=O.MAXTRIES) hangup(0);	/* dump after x tries */
  *maxuser=user.type_ptr->maxuser;
#ifdef Z3
 if (O.ZCPR==3) ovovloader(OVZ3,INITZ3,TRUE);	/* reset environment */
#endif
}



/* End of file */

