/* **************************************************************
 *								*
 *	      DISPLAY / MODIFY THE PRODUCT TYPE TABLE		*
 *		  last modified 01/26/84 dsb			*
 *								*
 ************************************************************** */

#include "libc.h"
#include "syslib.h"
#include "hardio.h"

/* #define DBUG YES  */

/* ***************** REVISION HISTORY OF THIS MODULE ***************   

    11/15/83	Works.	No Erase function yet though
    01/18/84	Turned into an overlay.  pr_entries() moved to the
		 utility module so SYSLIB2 (add/modify) and SYSLIB4
		 (verify) can use it too
    01/20/84	Fixed bug(s) in local storage & parameter passing
    01/22/84	Added "Erase"
    01/24/84	Fixed references to yorn() which now returns boolean
    01/26/84	Combined add & modify to allow for automatic operation
*/
/* *********************** MISCELLANEOUS EQUATES ******************** */


#define MAX_PROD 20	   /* consider any higher product numbers invalid */

/* **************** SPECIAL STRUCTURES FOR READING MACH TABLE ******** */


#define MTtrack   0x01		/* constants describing location and length */
#define MTsector  0x09		/* of tables on hard disk unit 0 */
#define MTlength    12

SFILE machtable = {
    MTtrack,
    MTsector,
    MTlength,
    NULL 
    };

struct MTentry {
    long sernum; 
    char product;
    char optmap[6];
    char iobyte;
    };

/* ***************** FUNCTIONS THAT DON'T RETURN INTS***************** */
struct PTentry *pr_find();

/*page*/


ovmain(junk)	     /* root uses generalized function that always passes */
int junk;	     /* an argument.  We refer to it here for consistency. */
{
    int i;

    for ever
    {
	i = pr_menu();
	if(abort_req)
	{
	    printf("\n");
	    return();
	}

	switch(i)
	{
	    case 'A':	pr_add();
			break;
	    case 'E':	pr_erase();
			break;
	    case 'L':	pr_dump();
			break;
	    case 'T':	pr_types();
			break;
	}
#ifdef DBUG
	printf("\njust outside switch");
#endif
    } /* loop until exit requested */
#ifdef DBUG
    printf("\n*DEBUG* break from loop (ERROR)");
#endif

} /* prod_fix (main product type table subprogram) */


pr_menu()
{
    char choice;
    int i;

    abort_req = FALSE;
    do
    {
    printf("\n\n\nPRODUCT TABLE MENU");
    printf("\n\n  A  -  ADD/MODIFY\tAdd or modify a Product Table entry.");
    printf("\n  E  -  ERASE     \tErase an entry from the Product Table.");
    printf("\n\n  L  -  LIST      \tDisplay the Product Table.");
    printf("\n  T  -  TYPES     \tDisplay Product Types for DMS equipment.");
    printf("\nEnter your choice (Press RETURN to go back to Main Menu) --> ");
    } while ((i=dgets(&choice,1)) > 1);
    abort_req = !i;
    return(toupper(choice));
}


pr_types()
{
    printf("\n\nProduct Type codes for various DMS computers");
    printf("\n(Press any key to stop or restart listing)");
    printf("\n\nProd. Type    Models");
    printf("\n----------    ----------------------------------------------");
    check_wait();
    printf("\n      1       DMS-3,  3/101,  3/102,  3/103,  3/4004, 3/4008,");
    printf("\n              3/501,  3/A25,  3/B,    3/F (Fox),  15, 5080");
    printf("\n      2       DMS-4");
    printf("\n      3       1280");
    check_wait();
    printf("\n      4       3/C");
    printf("\n      5       86, 5086");
    printf("\n      6       5016");
    printf("\n      7       816\n");
    waitkey();
    return();
} /* list the product types for DMS equipment */


struct PTentry *
pr_find(num)
int num;
{
    struct PTentry *entry;
    int i,max;

    entry = (struct PTentry *)prodtable.buffer;
    max = pr_entries();
    for(i=0; (i<max) && ((int)entry->type != num); i++, entry++)
	;
    if(i < max)
	return(entry);
    return(NULL);
} /* pr_find */


pr_dump()
{
    struct PTentry *entry;
    int i,max;

    printf("\n\n     PRODUCT TYPE TABLE\n");
    pr_title();
    max = pr_entries();
    entry = (struct PTentry *) prodtable.buffer;
    for(i=0; entry->type && (i < max); i++,entry++)
    {
	pr_prt(entry);
	check_wait();
    }
    printf("\n");
    waitkey();
} /* dump product table */


pr_title()	    /* print title on the screen */
{
    printf("\nProduct    Boot Loader    Login Program    OS Menu");
    printf("\n-------    -----------    -------------    -------");
}


pr_prt(ent)
struct PTentry *ent;
{
    int i,j;
    char *cp;

    printf("\n   %x  ",ent->type);
    for(i=0, cp=(char*)ent->bp2_name;  i<3;  i++)	    
    {
	printf("\t   ");
	for(j=0; j<8; j++)
	    printf("%c",*cp++);
    }
} /* print a ptt entry */


pr_add()		    /* add a product entry or modify an existing one */
{
    int  i,type;
    char adding;
    struct PTentry entry, *new_ptr;
    int  new_num;
    char *add_msg = 
	   "The Product Table entry which you have created looks like this:";
    char *mod_1_msg =
	   "You have asked to modify this Product Table entry:";
    char *mod_2_msg =
	   "The modified Product Table entry looks like this:";
    char *bp2_msg = "Loader Program";
    char *log_msg = "Login Program";
    char *osm_msg = "OS Menu Program";
    char ok;

    if(yorn("\nWould you like to see the list of possible product types"))
	pr_types();

    do
    {
	printf("\nEnter Product Type Number you want to add or modify.");
	printf("\n(Press RETURN to go back to the Product Menu) --> ");
	type = (int) gethex(1,2);
	if(abort_req)
	    return();
	if(!(ok = (type > 0) && (type < MAX_PROD)))
	    pr_types();
   } while(!ok);

    new_ptr = pr_find(type);	    /* NULL if a new product */
    adding = (new_ptr == NULL);

    if(adding)
	if((new_num = pr_entries()) >= 40)
	{
	    printf("\nThe Product Type Table is full -- you cannot make any ");
	    printf("more entries.\nThis is an unusual condition and may indi");
	    printf("\07indicate a corrupted \nControl Area or a program bug.");
	    waitkey();
	    ok = FALSE;
	}
	else
	{
	   printf("\nYou have asked to add an entry for product type %d (%s).",
		type,product[type]);
	    ok = yorn("\nIs this correct");
	}
    else
	ok = pr_ent_confirm(mod_1_msg,new_ptr);

    if(!ok)
	return();

    entry.type = type;

    printf("\nProgram names entered here should be eight characters or less.");
    printf("\nPress ESC to return to the Product Menu.");
    if(adding)
    {
	ok = (pr_refill(bp2_msg, NULL, entry.bp2_name, type)) &&
	     (pr_refill(log_msg, NULL, entry.lgn_name, type)) && 
	     (pr_refill(osm_msg, NULL, entry.osm_name, type)) &&
	     (pr_ent_confirm(add_msg,&entry));
	new_ptr = ((struct PTentry *)(prodtable.buffer)) + new_num;
    }
    else
    {
	printf("\nPress RETURN to keep current choice.");
	ok = (pr_refill(bp2_msg, new_ptr->bp2_name, entry.bp2_name, type)) &&
	     (pr_refill(log_msg, new_ptr->lgn_name, entry.lgn_name, type)) && 
	     (pr_refill(osm_msg, new_ptr->osm_name, entry.osm_name, type)) &&
	     (pr_ent_confirm(mod_2_msg,&entry));
    }
      
    if(ok)
    {
	blockmv(new_ptr,&entry,sizeof(struct PTentry));
	if(adding)
	    sort(prodtable.buffer,sizeof(struct PTentry),0,1,new_num+1);
	putfile(prodtable);
    }
    return();
} /* pr_a_m (add to or modify product table) */
       

pr_ent_confirm(msg,ent)
char *msg;
struct PTentry *ent;
{
    printf("\n%s\n",msg);
    pr_title();
    pr_prt(ent);
    return(yorn("\n\nIs this correct"));
}


pr_refill(msg,old,new,type)	   /* add or modify a file name */
char *msg,*old,*new;		   /* ESC aborts, RETURN keeps old value */
int type;			   /* return 0 if abort req, else 1 */
{
    while(!pr_fill(msg,new,type))
	if(old) 		    /* <cr> if there is an old value */
	{			    /* means keep the old value.  */
	    blockmv(new,old,8);     /* If there is no old value to keep, */
	    return(TRUE);	    /* <cr> is invalid. */
	}
	else
	    printf("\07Enter a file name (or ESC) --> ");

    if(*new == ESC)
	return(FALSE);
    return(TRUE);
}  /* pr_refill (modify existing name) */


pr_fill(msg,loc,type)		/* get a name into a location */
char *msg,*loc; 		/* return 0 if empty return */
int type;
{
    char temp[8];
    int valid = TRUE;
    int i;

    do
    {
	valid = TRUE;
	printf("\nEnter name of the %s for product %x\t --> ",msg,type);
				   
	clear(temp,8,' ');

	if(!(i=dgets(temp,8)))	  /* if count = 0, empty <cr> hit */
	    return(0);

	if(*temp == ESC)	 /* if ESC is first char, don't check name */
	{
	    *loc = ESC; 	 /* but just return an ESC in the buffer */
	    return(1);
	}

	chop_name(temp,loc);	 /* upper case and blank fill  */
	if(!(find_sd(loc)))
	{
	    valid = FALSE;
	    printf("\n\07There is no file named ");
	    for(i=0; (i<8) && (*(loc+i) != ' '); i++)
		printf("%c",*(loc+i));
	    printf(" in the Control Area Directory.");
	    printf("\nI cannot accept it into the Product Table.");
	}
    } while (!valid);
    return(i);
}   /* pr_fill (fill a name field in a product table entry) */

pr_erase()
{
    struct PTentry *ent;
    int entries;
    char type;
    char *cp;

    printf("\nEnter Product Type Number you want to delete. ");
    printf("\n(Press RETURN to go back to the Product Menu) --> ");

    type = (int) gethex(1,2);
    if(abort_req)
	return();

    if((ent=pr_find(type)) == NULL)
    {
	printf("\n\07There is no entry for that product type in the table. ");
	return();
    }

    printf("\nYou have asked to delete this product type:");
    pr_title();
    pr_prt(ent);
    printf("\n\nIf you delete this entry, machines of Product Type %d",type);
    printf("\n(i.e. %s) will not be able to log in.",product[type]);
    if(mt_pr_find(type))
	cp = "ARE";
    else
	cp = "are no";
    printf("\nCurrently there %s machines of that type in the Machine Table.",
	    cp);
    if(!yorn("\nARE YOU SURE YOU WANT TO DELETE THIS ENTRY"))
	return();
    entries = pr_entries();
    clear(ent,sizeof(struct PTentry),0xE5);  /* 0 is an illegal product code */
					     /* so this entry will be sorted */
					     /* out to the end. */
    sort(prodtable.buffer,sizeof(struct PTentry),0,1,entries);
    putfile(prodtable);
    return();
} /* pr_erase */

mt_pr_find(type)    /* see if Machine Table lists products of this type */
char type;
{
    char machbuf[128*sizeof(struct MTentry)];	   /* big but temporary! */
    struct MTentry *ent;
    char enttype;
    int i;

    machtable.buffer = machbuf;
    getfile(machtable);

    for(ent = (struct MTentry *)machbuf, i=0; i<128; ent++,i++)
    {
	if((enttype = ent->product) == type)
	    return(TRUE);
	if((enttype < 1) || (enttype == 0xE5) || (enttype > MAX_PROD))
	    break;
    }
    return(FALSE);
} /* mt_pr_find (find a Machine Table entry that mentions a given prod type) */
OD))
	    break;
    }
    re