/******************************************************************************
 * 	This is the main METAL/Z-MSG module
 *
 *	Name: METAL.C or Z-MSG.C
 *
 *		   Copyright (c) 1984,1985, 1986 Tim Gary
 *			     All rights reserved.
 *
 *	This is a commercial product, and is for use by a single system
 *	and user.  Copies may be made for backup purposes ONLY.
 *
 ******************************************************************************
 *
 * 1.50xx 07/04/86 Commands mask check added..
 * 1.50xx 04/10/86 Moved most z3 stuff (return from alias/init env) to MEZ3..
 * 1.50xx 04/09/86 Menu-like operation for non-expert users if menu is
 *      	   found in the help file..
 * 1.50xx 03/13/86 More stack space..
 * 1.50xx 03/09/86 Groups structure allocated here..
 * 1.40xx 01/25/86 New method for date/time, etc..
 * 1.32xx 01/16/86 Fixed bug which caused lastcalr file to be read after mentr.
 * 1.32xx 01/12/86 Converted for 1.06d...  Change settop to sbrk..
 * 1.31a  10/13/85 Release version.  Includes following changes:
 *		    Now able to load ZCPR3 system Segs based on user type.
 *		    Other ZCPR3 init stuff added.
 *		    Custom init routine called (MEINIT).
 *		    Command table moved to MECMDS.H
 *		    Overlay to overlay calling supported (one level..),
 *		     calling overlay will be returned to when other done.
 * 1.30xx 7/01/85  Print and echo flags saved/restored now..
 * 1.30xx 6/19/85  G_restore, etc done here to avoid ANY memory conflicts..
 * 1.30xx 6/15/85  Apply/Comments pass diff. 'func' vals, time expired fixed.
 * 1.30xx 6/09/85  Moved memory allocation settop routine here.  Etc..
 * 1.30xx 5/26/85  Make sure non expert mode set for welcome message, etc..
 * 1.30xx 5/25/85  Modified to find highest location for msg allocation, so
 *		  extra memory won't be needed for an alias (for msg).
 * 1.30xx 5/02/85  Turned Z3BUG off, Z3MSG_OFFSET define added.
 * 1.30xx 5/01/85  Fixed for renaming of MESUMM TO MESTUFF.
 * 1.30xx 4/28/85  Slight Z3 debug stuff added..
 * 1.30xx 4/26/85  Fix for saving z3 command line..
 * 1.30xx 3/13/85  Fix for return from OS...
 * 1.30xx 3/07/85  BBSNAME stuff added..
 * 1.30xx 3/03/85  Continued with z3setup..
 * 1.30xx 2/20/85  Start changes for Z3 multi command lines, etc..
 * 1.20b 01/18/85  Showtime seperated to overlay..
 * 1.20b 01/14/85  Prompt shows time on system so far.
 * 1.20b 01/11/85  More clock support added at prompts, etc..
 * 1.20b 01/05/85  Bug fixes, add fast change to sysop stat from CP/M.
 * 1.20a 11/04/84  Alias to apply command is COMMENT.
 * 1.10e 11/03/84  Added APPLY command.
 * 1.10e 10/31/84  Functions moved out of this routine, overlays functions
 *		  added, new UNKILL command (also RESTORE=same thing).
 * 1.10c 10/12/84  Some routines moved to MEMISC overlay to conserve space.
 *
 * 1.10b 10/04/84  Chat fixed for xx columns, auto return..
 * 1.10b 10/01/84  Spelling error fixed.  Other cosmetics.
 *
 * 1.10a  9/27/84  More cosmetic changes.
 * 1.10a  9/08/84  Chat routines expanded to include user name, and if
 *		  sysop is not around, ask if they would like to leave
 *		  private comments to the sysop.
 * 1.10a  9/01/84  Continued work on overlays.
 * 1.10a  8/24/84  JUST STARTING OVERLAY VERSION.
 *
 * 1.01a  7/02/84  Multi-user lastcalr implemented.
 * 1.01a  6/27/84  Multi user OS support cont..  
 * 1.01a  6/10/84  Fixes for Aztec C 1.06.  Added Link to mutil command,
 *		  also started provisions for Multi-user OS's..
 *
 * 1.0b   4/22/84  Problem with mult commands fixed (introduced 9 days ago)
 * 1.0b   4/20/84  Fixed 'U' bug (command changed user.lastread..)
 * 1.0b   4/13/84  Added upper/lower case name ability.  3 User defined
 *		   files may be displayed.  '!' command now restores original
 *		   user status when turning off sysop status.  'Articles'
 *		   command added to allow printing of various text files.
 *
 * 1.0a	  2/15/84  Lastcalr file changed, benefit: pretty xmodem log, and
 *		   user parameters 'stick' when the user changes them and exits
 *		   to CP/M, and then returns.  NOCPM fix.
 *
 *****************************************************************************/

/* #define Z3BUG   */ /* for duration of debugging Z3 stuff in this file */

#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"

#define	MAINMENU "MAINMENUHLP"	/* main help menu in METHELP library */

char *sbrk();
extern struct cmdtype maincomtab[];	/* declared seperately like O */
char sotries=0;				/* tries attempted with '!' command */

/**********************************************************************/

/**************************
 * start the main program *
 **************************/

main(argc,argv)
 int argc;
 char *argv[];
{
char temp[40];

/* do initial stuff in another area...  Must be the VERY FIRST thing here */

init(argc,argv);


/***************************
 * main command input loop *
 ***************************/

while(1)				/* one giant endless loop.. */
	{
	/* if novice user, display menu if there is one */
	if ( !(user.flags&EXPERT) )
		{
		ltype(METHELP,MAINMENU);
		strcpy(temp,"\n(Enter '?' for help)  ");
		}
	  else strcpy(temp,"\n");
	if (user.status==SYSOP) strcat(temp,"Sysop: ");
	  else strcat(temp,"Command: ");

	if (get_cmd(temp,maincomtab)==ERROR)	/* ERROR=bad command */
		{
		send("I didn't follow that, try '?' for help!");
		strloc=0;	/* sorry, but one error aborts rest.. */
		}	/* error in command */
	}	/* main while loop */

}	/* MAIN loop */ 	 	


/*********************************************
 * Init stuff.. Sets top of program pointer
 * for overlays.  Checks to see if init
 * overaly is to be loaded.  Does g_restore if
 * return from zcpr command...
 *********************************************/

init(argc,argv)
 int argc;
 char *argv[];
{
char **m_buff;
int envok_flag=YES;

rsvstk(1400);		/* allow a little over 1k for stack */

/* if z3 stuff, make sure there's room for protection code here */
if (O.ZCPR==3) z3_hp=sbrk(sizeof(struct g_prot)+10);

group=sbrk(sizeof(struct _group)*N_GROUPS+1);
msg=sbrk((O.MAXTOTMSGS*8)+4);	/* space for the message array */
if ((int)msg==-1) msg=(char *)0;

ov_init(MAINOVRS);	/* open large overlay file */

user.flags&=(~EXPERT);	/* make sure expert toggle is off */

findbye();	/* get bye addresses.. */

#ifdef Z3
/* setup z3 pointer if being used */

if (O.ZCPR==3)
	{
	z3env=0x100;	/* point to initial 'internal' descriptor */
	if (z3env->class==1) z3env=z3env->expath; /* if ext., point there */
	if (z3env==0 || z3env->msg==0)
		{	/* appearently z3 not really installed.. */
		O.ZCPR=0;
		envok_flag=NO;	/* flag not ok, for later.. */		
		}
	  else
		{
		*(z3env->wheel)=0;	/* no wheel */
		m_buff=(z3env->msg)+O.Z3MSG;

#ifdef Z3BUG
		printf("\nZ3 is being used, and z3env is located at %xh.\n",
			(unsigned)z3env);
		printf("\nZ3 message buffer (@ %xh) has a value of %xh.\n",
			(unsigned)m_buff,(unsigned)*m_buff);
#endif

		if (*m_buff!=(char *)0 && argc>1)
			{
			argc=-1;	/* MUST do this to flag silent stuff */
			ovloader(OVZ3,RETCMD,*m_buff);
#ifdef Z3BUG
			printf("\nGlobals restored, user name=%s.\n",user.name);
#endif
			*m_buff=(char *)0;	/* clear this */
			}
		} /* env ok flag.. */
	}
	else	/* falls through */
#endif	/* Z3 */
	  if (O.ZCPR) *O.SECURELOC=0;	/* make sure system is safe */


if (argc>1) ovloader(OVMENTER,argc,argv);	/* get name/pass, etc.. */

*maxuser=user.type_ptr->maxuser;	/* is this needed here? */

if (!envok_flag)
	{
	if (user.status==SYSOP)
		send("\n\n***  ERROR: Z3 Environment is Invalid.  Use Z3INS to install!!  ***\n\n");
	 else   {
		user.status=NOCPM;	/* sorry folks */
		user.type_ptr=get_tp(user.status);
		send("\nNOTE: Operating System access has temporarily been suspended for all users.\n");
		}
	}

if (argc!=-1) ovloader(OVINFREQ,INIT,argc);	/* initialize the works.. */

/* if auto read option ON, and was first time through..., then read new msgs */
if (user.flags&READNEW && argc>1)
	{
	send("[Reading New Messages]\n");
	ovloader(OVREAD,0,READ_NEW | READ_SEL);	/* do a RP */
	}

new_page();	/* reset line count */

} /* init */


/************************************************* 
 * (Z3) Restore global variables moved to MEZ3.C * 
 *	z3_init() moved to same place...	 * 
 *************************************************/


/********************************************
 * Get a line of input, and do command if a *
 * match is found....			    *
 ********************************************/

get_cmd(str,cmdlist)
 char *str;
 struct cmdtype *cmdlist;
{
register struct cmdtype *ind;		/* index to go through list */
register char *chind;			/* character index	    */

sepstr=' ';	/* allow space seperator */
do {
   ask(str,buffer,MAXLINE,UP);	/* print prompt, and get line */
   if (*buffer=='/' && buffer[1]!='/')
	{
	strloc=0;	/* nullify rest of line */
	*buffer='\0';
	continue;
	}
   } while (*buffer=='\0');

sepstr='\0';	/* turn this off */

for (ind=cmdlist; ind->abbr && (ind->mask & user.type_ptr->flags); ind++)
	{
	if (!strncmp(buffer,ind->abbr,strlen(ind->abbr)))
		{	/* matched abbreviation */
		chind=buffer+strlen(ind->abbr);
		if (!strncmp(chind,ind->full,strlen(chind)))
			{
			if (ind->ovname==0) (*ind->func)(ind->value);
			  else ovloader(ind->ovname,ind->func,ind->value);
			break;	/* get out of all these nested tests */
			}
		} 	/* abbr. match test */
	}  /* search loop */

if (ind->abbr) return NULL;	/* NULL=command found */

#ifdef Z3
if (O.ZCPR==3)			/* if ZCPR3 is in use */
	{
	char temp[MAXLINE+1];
	strcpy(temp,buffer);
	return ovloader(OVZ3,CMD,temp);	/* do alias command if found */
	}
   else	/* 'fall' through to return ERROR */
#endif

return ERROR;	/* command not found */

}  /* get_cmd */


char ostat=0;	/* this needs to be externs here--overlays reinit statics */

/*****************************
 * Check if user matches the passed string
 *****************************/

thisis(s)
 register char *s;
{
char bs[NAMELEN+1];

strcpy(bs,s);  upcase(bs);	/* make passed string upper case only */

if (!ustrcmp(user.name,s) || (user.status==SYSOP && usindex("SYSOP",bs)))
	return TRUE;

return FALSE;
}


/****************************************
 * da..du..du..da..dat's all folks....	*
 ****************************************/

