/*=============================================================================
			USERS		module 0
	"us0.c"
*/

/*=============================================================================
			INCLUDES
*/
/*
#define		debug0		0
*/

#include	"users.os"
#include	"standard.inc"
#include	"overlay.h"
#include	"errno.h"

#define		EXTERNal	0

#include	"users.dat"

#define	OV_PSWD		"usov1"
#define OV_MODIFY	"usov2"
#define OV_ADD		"usov3"

/*=============================================================================
			HISTORY
date		9 February  1984
person		tpl

ver	0
rev	0
mod	c
patch	6

 ver/rev
"""""""""
  0 / 0

     mod/patch
    """""""""""
	c4		6 February 1984		tpl
		.RELEASED TO SOFTWARE TEST.

	c1		3 February 1984		tpl
		.Try to save code.
		.Use data_xfer for Get/Save tables.

	c0		31 January 1984		tpl
		.Restructuring of modules, especially includes.
		.Start using includes like ALLOC.
		.Put version info in new module "USERSDOC.C".

	b11		30 January 1984		tpl
		.RELEASED TO SOFTWARE TEST.

	b1		16 December 1983	tpl
		.Too big to compile. Break up us0b.c into
		'usinit.dat','usconst.def'.
		.Take out 'Add' and associated routines and put
		into 'us1a.c' and 'us2a.c'.

	b0		16 December 1983	tpl
		.Enter code for default partitions setting, including reading
		the alloc table in.
		.Enter code for Log In Command setting and displaying.

	a15		16 December 1983	tpl
		.Add working except for default partitions and Log In string.

	a8		15 December 1983	tpl
		.Enter much of Add().
		.List, Get, Save, Zero all working.

	a1		13 December 1983	tpl
		.Read in all sectors of user/config tables.
		.Enter ZeroTable code.
		.Check for empty table.
		.0xE5 or 0 indicates end of table.

	a0		12 December 1983	tpl
		.Begin coding. Steal routines from alloc and filecopy.
		.Compiled but bombed after entering Initialize.

*/

/*page*/
/*=============================================================================
			ROUTINES
*/
/*---------------------------------------------------------------------------*/
/*				MAIN					     */
extern int	errno;

#define MANAGER	1	/* for system password routines	*/

/*---------------------------------------------------------------------------*/

#define		RESTART6	0x30
#define		RETIz80		0x4DED
#define		EIz80		0xFB

static CHAR	save_rst6[3];

/*---------------------------------------------------------------------------*/

rst6_disable()
{

    save_rst[0] = *( (CHAR *)RESTART6);
    save_rst[1] = *( (CHAR *)RESTART6+1);
    save_rst[2] = *( (CHAR *)RESTART6+2);

    *( (CHAR *)RESTART6 ) = EIz80;
    *( RESTART6+1 )	= RETIz80;
}

/*---------------------------------------------------------------------------*/

rst6_reset()
{
    *( (CHAR *)RESTART6) = save_rst[0];
    *( (CHAR *)RESTART6+1) = save_rst[1];
    *( (CHAR *)RESTART6+2) = save_rst[2];
}

/*---------------------------------------------------------------------------*/



main(arg_count,arg_vector)
int	arg_count;
char	*arg_vector[];
{

    Show_Version();	/* In "USERSDOC.C"	*/

    
    if ( !Is_Master() )
    {
	printz("%c\n\n This is not a master.\n\
 Users can only be run on a master.\n", BELL);
	zabort();
    }


/* GET PASSWORD */
/* for level 2, the operator level.	*/
    if ( ovloader( OV_PSWD, 2 ) == -1 )	/* zaborts if faliure	*/
    	ov_error (OV_PSWD);


    rst6_disable();
    Initialize();
    Get_Users_Table();
    Get_Alloc_Table();
    Main_Menu();
    Quit_Program();
    rst6_reset();

} /* main */


/*---------------------------------------------------------------------------*/
/*page*/

Main_Menu()
{
  register CHAR	not_done = TRUE;

#ifdef debugP
	putz("\np..Main_Menu\n");
#endif

    while( not_done )
    {
	switch( Do_Menu( &menuMain, RETNOTOK) )
	{
	    case 'A':
		/* overlay add routine */ 
		if ( ovloader (OV_ADD) == -1)
			ov_error (OV_ADD);
		break;

	    case 'M':
		    /* overlay modify routine */
		    if ( ovloader( OV_MODIFY) == -1 )
			ov_error (OV_MODIFY);

		break;

	    case 'D':
		Delete();
		break;

	    case 'Z':
		Zero_Users_Table();
		break;

	    case 'G':
		Get_Users_Table();
		break;

	    case 'S':
		Save_Users_Table();
		break;

	    case 'L':
		List_Users_Table();
		break;

	    case 'Q':
		if ( changes_made )
		{
		   putz("\n You have made changes to the Users Table without\n");
		   putz("saving it to the hard disk.\n");
		   printz("%c\n Do you still want to QUIT the program? --> ", BELL);

		   if ( Get_Yes_No(RETNOTOK) )	/* if yes we are done.	*/
			not_done = FALSE;
		}
		else	/* Else if no changes made just quit.	*/
		    not_done = FALSE;

		break;

	    default:
		break;

	} /*switch*/

    } /*while not done*/

} /* Main_Menu */

/*---------------------------------------------------------------------------*/
/*page*/

CHAR
Do_Menu( which_menu, accept_return )
  struct menu	*which_menu;
  int	accept_return;
{
  register CHAR	i, user_choice;
  register int num_lines;


    num_lines = which_menu->numLines;
    for ( i=0; i<num_lines; ++i)
    {
	if ( (user_choice = upgtstch()) != 0 )	/* then character input */
	    if ( index( which_menu->valid_choices, user_choice) )
		return(user_choice);	/* FOUND VALID ENTRY */
	    else
		ptch( BELL );	/* Entry not in menu so beep, no echo. */
	printz("%s", which_menu->lines[i]);  /* Print out next line of menu. */
    }

    while ( TRUE )
    {
	while ( TRUE )
	{
	    user_choice = upgtch();
	    if ( (user_choice == CR) || (user_choice == LF) )
	    {
		if ( accept_return )
		    return RETURN;
		else
		    ptch( BELL );
	    }
	    else
		break;	/* Not a CR or LF so go on to check if menu choice.  */
	}

	if ( index( which_menu->valid_choices, user_choice ) )
	{
	    ptch( user_choice );	/* echo entry.	*/
	    break;			/* FOUND VALID ENTRY.	*/
	}

	if ((user_choice < SPACE) || (user_choice >= DEL))
	    printz("%c    That", BELL);
	else
	    printz("%c       %c", BELL, user_choice);
	printz(" is not in the menu. Please try again.");
	repchar(BS,46);
	ptch( SPACE );
	ptch( BS );

    } /* while TRUE */

    repchar( SPACE, 47);
    putz("\n");
    return(user_choice);

} /* Do_Menu */

/*---------------------------------------------------------------------------*/
/*page*/

Quit_Program()
{
    putz("\n Leaving the program.\n");
    ReInitialize();
    exit( 0 );		/* Leave gracefully.	*/

} /* Quit_Program */

/*---------------------------------------------------------------------------*/

zabort()
{
    putz("\n\n Aborted.\n");
    ReInitialize();
    exit( 0 );		/* Leave gracefully.	*/

} /* zabort */

/*---------------------------------------------------------------------------*/
/*page*/

Zero_Users_Table()
{
    printz("%c\n\n    WARNING !!!!!!!\n\n", BELL );
    putz("  THIS OPTION ERASES THE ENTIRE USER TABLE.\n\n\
  However, the erased table is not saved to the\n\
 control area until the Save command is given.\n\n");
    printz("%c Do you still wish to Zero the Users Table?\n\n", BELL);
    putz("    -->                    (yes/no)");
    repchar( BS,27 );

    if ( !Get_Yes_No( RETNOTOK ) )
	return;		/* return if user responds no.	*/

    clear( &users_table[0], sizeof( struct users_entry ) * NuserTblEntries, 0);
    clear( &config_table[0], sizeof( struct config_entry ) * NuserTblEntries, 0);

} /* Zero_Users_Table */

/*---------------------------------------------------------------------------*/
/*page*/

Get_Users_Table()
{

#ifdef debugP
	putz("\np..Get_Users_Table\n");
#endif

    data_xfer( READ, USERStrack, USERSsector, users_table, USERSsizeInSectors);

    data_xfer( READ, CONFIGtrack, CONFIGsector, config_table, CONFIGsizeInSectors);

} /* Get_Users_Table */

/*---------------------------------------------------------------------------*/
/*page*/

Save_Users_Table()
{
#ifdef debugP
    putz("..Save_Users_Table\n");
#endif

/* First reset changes made flag. Saving tables saves all changes.	*/
    changes_made = FALSE;

    data_xfer( WRITE, USERStrack, USERSsector, users_table, USERSsizeInSectors);

    data_xfer( WRITE, CONFIGtrack, CONFIGsector, config_table, CONFIGsizeInSectors);


} /* Save_Users_Table */

/*---------------------------------------------------------------------------*/
/*page*/

List_Users_Table()
{
  int	i;

    putz("\n\n       List the Users Table.\n\
       Press 'ctrl-s' to pause listing, any key to start again.\n\n");

    Show_Header();
    for (i=0; (i<NuserTblEntries)
		&& ( users_table[i].name[0] != 0xE5)
		&& ( users_table[i].name[0] != 0); ++i)
	{
	Show_Entry( &users_table[i] , &config_table[i]);
	if (gtstch() == 0x1B)  break;	/* stop listing on escape */
	}

    printz("\n   %d entries used out of 128.\n", i);
    putz("\n\n  Hit any key to return to Main Menu.\n");
    gtch();

} /* List_Users_Table */

/*---------------------------------------------------------------------------*/

Show_Header()
{
putz("\
  Name   Password              Partitions                     O.S.\n\
                   A        B        C        D         Type        Kind\n\
-------- -------- ----------------------------------- -------------------\n");

} /* Show_Header */

/*---------------------------------------------------------------------------*/
/*page*/

Show_Entry( u_entry, c_entry )
struct users_entry	*u_entry;
struct config_entry	*c_entry;
{
  register CHAR j,i;

/* Show the name.	*/

    printz("%.8s ", u_entry->name );

/* Show the password.	*/

    printz("%.6s  ", u_entry->password );

/* Show the default disk assignments.	*/

    for ( j=0; j<Nassignments; ++j)
    {		/* Mask possible hibit set. */
	printz(" %c", c_entry->assignments[j][0] & 0x7f );
		/* show rest of partition name.	*/
	printz("%.7s", &(c_entry->assignments[j][1]) );
    }

/* Now the O.S. type.	*/

    repchar( SPACE,2 );
    switch( u_entry->op_sys & 0xf0 )
    {

	case CPMsys:			/* = 0x10	*/
		switch( u_entry->op_sys & 0x0f )
		{
		    case CPMeither:
				putz("CPM2 or 86");
				break;
		    case CPM2sys:
				putz("CPM2      ");
				break;
		    case CPM86sys:
				putz("CPM86     ");
				break;
		    case HIDOSsys:
				putz("HiDos     ");
				break;
		}

		break;
	case MSDOSsys:			/* = 0x20	*/
		putz("MSDOS     ");
		break;
	default:
		putz("?         ");
		break;
    }

/* Display OS kind.	*/

    repchar( SPACE,3 );
    if ( u_entry->flags == 1)	/* Then hi-tpa model.	*/
	putz("HiMEM\n");
    else
	putz("Full\n");

    if ( c_entry->size_type_ahead != 0 )
    {
	putz("    Log in command -->");
	C_listchars( c_entry->type_ahead,
		     c_entry->size_type_ahead);
	putz("\n");
    }

} /* Show_Entry */

/*---------------------------------------------------------------------------*/
/*page*/

Initialize()
{

#ifdef debugP
    putz("\np..Enter Initialize\n");
#endif

    cur_volume = 0;

    begin_disk = CurDisk();	/* Save current disk.	*/


#ifdef debugP
	putz(" ..Exit Initialize\n");
#endif

} /* Initialize */

/*---------------------------------------------------------------------------*/
/*page*/

ReInitialize()
{
#ifdef debugP
	putz("\np..Enter ReInitialize");
#endif

    DiskReset();		/* Let CP/M know of dpb change
					and select drive A.		*/

    SelDisk( begin_disk );	/* Reselect original disk.	*/

} /* ReInitialize */

/*---------------------------------------------------------------------------*/
/*page*/

Get_Alloc_Table()
{
    data_xfer( READ, ALLOCtrack, ALLOCsector, alloc_table, ALLOCsizeInRecords);

} /* Get_Alloc_Table	*/

/*---------------------------------------------------------------------------*/

ov_error (fname)
CHAR	*fname;
{
	ptch( BELL );
	switch ( errno )
	{
	    case ENOENT:
		printz("\nMissing %s.ovr file.\n", fname);
		break;
	    case E_OVSMALL:
	    case E_NOTOVLY:
		printz("\nFile %s.ovr is bad.\n", fname);
		break;
		
	    case E_NOMEM:
		printz("\nOut of memory for %s.ovr file.\n", fname);
		break;

	   default:
		printz("Error using %s.ovr file.\n", fname);
		break;
	}/* switch on errno */

	zabort();

}/* if ovloader returns error */




/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

