#
/*
*       SCCS File Type - 
*
* 	What identification string
*/
static char *_S_tpeutilc =       "@(#)tpe_util.c	1.21";

#include "TPE.epl"
#include "emuniv.h"
#include "EDI.h"
#include "NKSRdefs.h"
#include "NKedit.h"
#include "KSOSpaths.h"

#define IO_EOF         0
#define IO_FAIL       -1
#define LPD_EVENT     '\151'
#define NON_KCALL     " "
#define NO_ERR        XOK
#define PRTMODE        0666
/*#define XOK            0*/
#define XpostEh        10601

openDescriptor prt_od;
seid           prt_seid;
K_err_num      error;
ioStatus       errs;
seid           lpd_seid;
int            devfun_read;
p_block        null_Pblk;

char *yesorno();
char gettyid();
char notvalid = INVALID;

/*****************************************************************************

CPCI:  KSOS NKSR
CP:
TAG:  TPE
MODULE NAME:
				TERMINAL PROFILE EDITOR
REFERENCES:
  A SPECS:  None
  B5 SPECS: None

HISTORY:
  AUTHOR:  Nanette E. Harter (with modifications by Tom Perrine)
  VERSION:  1.21 of 3/11/86
  MODULE TYPE: 

******************************************************************************

PURPOSE
		The editor is a record editor which
		will edit a specific file of records, termpdb--
		terminal profile database, modifying
		the records or fields in the records.
		The purpose of the editor is:
		a) To have an editor that runs on KSOS without an Emulator.
		b) To have a field editor that does not allow the entry of
		   incorrect records.
		c) To have a editor that provides a nice user interface.
		   Such as using a name for a security compartment rather than
		   using the bits representation as input.


DESCRIPTION
		The main procedure of the editor will
		create a temporary file to be used in editing,
		accept the the commands from the user,
		and call the correct procedure for action.

ASSERT
		Tpe is invoked by the secure server and assumes
		security checks have already been performed

CALLED BY       None

CALLS           tpefiles, add, change, delete, find, print, view, quit
		printf

*****************************************************************************/

main (argc, argv)
    int   argc;
    char *argv[];
{
	extern  char      *Tempfile;
	extern  tpstruct  Tprecord;
	extern  char      Termlist[];
	extern  int       Numofterm;
	extern  char      Edtor_comds[];
	char 	command[20];

	/*
	 *	Announce version
	 */
	printf("TPE version 1.21\n");

	/*
	 * open tpfile and create tempfile
	 * read in first set of blocks and
	 * create lists
	 */
	Tempfile = "/sys/tmp/tpdbtemp";
	tpefiles();
	mkseclist();

	while (FOREVER)
	{
		/* print prompt and receive command */
		printf ("> ");
		scaner(command);

		switch (command[0])
		{
			case 'a': tpeadd();    break;
			case 'c': tpechange(); break;
			case 'p': tpeprint();  break;
			case 'v': tpeview();   break;
			case 'd': tpedelete(Termlist,Numofterm); break;
			case 'f': tpefind(Termlist,Numofterm);   break;
			case 'n': tpenext(Termlist,Numofterm);   break;
			case 'q': tpequit(Termlist,Numofterm,tpdbPath,&Tprecord,sizeof(Tprecord));
			default:  printf("%s", Edtor_comds);
		}
	}
}

/*****************************************************************************

PURPOSE
		Add is a module to handle the addition of a new
		record to the tpdb file

DESCRIPTION
		The add command will prompt the user for
		the info to complete the new record,
		check the info for feasibility,
		and append new record to end of file.

CALLED BY       main

CALLS           gettyid, getbaud, getprty, wrtnewrec
		getscreen, yesorno, getaccesslev,

*****************************************************************************/
tpeadd()
{
	extern  tpstruct  Tprecord;
	extern  char   	  Termlist[];
	extern  int       Numofterm;
	extern  int       Index;
	extern  int       Changed_flag;
	char	pattern[LINELENGTH];		/* input parity type */
	int     i;

	Tprecord.ttyid = gettyid();

	for (i=0; i<Numofterm; i++)
		if (Termlist[i] == Tprecord.ttyid)
		{       printf ("Terminal id must be a unique number.\n\n");
			Tprecord.ttyid = notvalid;
			return;
		}

	Index = Numofterm++;
	Termlist[Index] = Tprecord.ttyid;


	printf("\nIs the terminal configured ? (y or n) : ");
	Tprecord.config = yesorno();

	printf("\nIs the terminal to be treated as a console ? (y or n) : ");
	Tprecord.console = yesorno();

	Tprecord.xmitBaud = getbaud("transmission");

	Tprecord.recBaud = getbaud("receiving");

	Tprecord.parity = getprty();

	printf("`\nEnter clear screen sequence (max 8 chars) : '");
	scaner(pattern);
	strcopy(Tprecord.clrScreen,pattern,8);

	printf("\nENTER MAXIMUM ACCESS LEVEL\n");
	getaccesslev(&Tprecord.maxLevel);

	wrtnewrec(&Tprecord,sizeof(Tprecord));

	Changed_flag = ON;

	return;
}

/*****************************************************************************

PURPOSE
		Print is a module which will cause printing of the
		information in tpdb records to the lineprinter.

CALLED BY       main

CALLS           none

*****************************************************************************/
tpeprint()
{
	printf("Printing Terminal Profile Data Base\n");
	find_LPD();
	printf("Calling print_tpdb\n");
	print_tpdb();
	printf("Completed printing\n");
}

/*****************************************************************************

PURPOSE
		View is a module which will cause printing of the
		information in database records to the standard output.

DESCRIPTION     Check for empty database,read in the desired record,
		print it

CALLED BY       main

CALLS           tview

*****************************************************************************/
tpeview()
{
	extern  tpstruct Tprecord;
	extern  int       Index;

	if (Index == ERROR)
	{
		printf ("No record.\n");
		return;
	}

	/* read record from file */
	readarec(&Tprecord,sizeof(Tprecord));

	/* print the record */
	tview();
}
tview()
{
	extern  tpstruct Tprecord;
	int	indx;

	printf("tty id: %d\n",Tprecord.ttyid);
	printf("Terminal is configured: %c\n", Tprecord.config);
	printf("Terminal is console: %c\n", Tprecord.console);
	printf("Default transmission baud rate: %d\n", Tprecord.xmitBaud);
	printf("Default receiving baud rate: %d\n", Tprecord.recBaud);
	printf("Default parity: ");
	switch(Tprecord.parity)
	{
		case 0: printf("even\n"); break;
		case 1: printf("odd\n");  break;
		case 2: printf("none\n");
	}
	printclearscreen();
	printf("Maximum access level:\n");
	prtlevel(&Tprecord.maxLevel);
}

/*****************************************************************************


PURPOSE
		Change is a module to allow a record from the tpdb file
		to be modified.

DESCRIPTION
		The terminal id currently pointed to will be echoed,
		The user is prompted for the field to edit,
		The data is asked for, and
		The changes made.

CALLED BY       main

CALLS           readarec, wrtarec, prtlevel, gettyid, tview
		getbaud, getprty, getscreen, getaccesslev,
		printf,scaner

*****************************************************************************/
tpechange()
{
	extern  tpstruct Tprecord;
	extern  char     Tpchang_comds[];
	extern	char     Termlist[];
	extern  int      Numofterm;
	extern	int	 Index;
	extern  int	 Changed_flag;
	char    command[LINELENGTH];

	if (Index == ERROR)
	{
		printf ("No record.\n");
		return;
	}

	readarec(&Tprecord,sizeof(Tprecord));

	printf ("x will terminate change\n\n");
	printf ("Changing tty %d\n\n", Tprecord.ttyid);

	while(FOREVER)
	{
		printf ("\nEnter field name to change : ");
		scaner(command);

		switch (command[0])
		{
			case 'x':              /* carriage return */
				wrtarec(&Tprecord,sizeof(Tprecord));
				Changed_flag = ON;
				return;

			case 'v':
				tview();
				break;

			case 'i':
				printf("tty id: %d\n",Tprecord.ttyid);
				Termlist[Index] = notvalid;
				Tprecord.ttyid = Termlist[Index] = gettyid();
				break;

			case 'f':
				printf("Terminal is configured: %c\n", Tprecord.config);
				printf("\nIs the terminal configured ? (y or n) : ");
				Tprecord.config = yesorno();
				break;

			case 'c':
				printf("Terminal is console: %c\n", Tprecord.console);
				printf("\nIs the terminal to be treated as a console ? (y or n) : ");
				Tprecord.console = yesorno();
				break;

			case 't':
				printf("Default transmission baud rate: %d\n", Tprecord.xmitBaud);
				Tprecord.xmitBaud = getbaud("transmission");
				break;

			case 'r':
				printf("Default receiving baud rate: %d\n", Tprecord.recBaud);
				Tprecord.recBaud = getbaud("receiving");
				break;

			case 'p':
				printf("Default parity: ");
				switch(Tprecord.parity)
				{
					case 0: printf("even\n"); break;
					case 1: printf("odd\n");  break;
					case 2: printf("none\n");
				}
				Tprecord.parity = getprty();
				break;

			case 's':
				printclearscreen();
				printf("\nEnter clear screen sequence (max 8 chars) : ");
				scaner(command);
				blankout(Tprecord.clrScreen,8);
				strcopy(Tprecord.clrScreen,command,8);
				break;

			case 'm':
				printf("Maximum access level:\n");
				prtlevel(&Tprecord.maxLevel);
				getaccesslev(&Tprecord.maxLevel);
				break;
			
			default: printf ("%s", Tpchang_comds);
		}
	}

}

/*****************************************************************************

PURPOSE
	display the clear screen character sequence
DESCRIPTION
	display the clear screen sequence, translating non-printing
	characters to a printable form
CALLED BY
	tpeview, tpechange
CALLS
	printf
******************************************************************************/
printclearscreen()
{
	extern	tpstruct	Tprecord;
	int	indx;
	char	tempch;

	printf("Clear screen sequence: ");
	indx = 0;
	while ( indx < 8 & Tprecord.clrScreen[indx] != '\0')
	{
		tempch = Tprecord.clrScreen[indx];
		if ( (tempch>040) && (tempch<0177) )
			printf("%c",tempch);
		else			/* print octal equiv '\nnn' */
			printf("\\%o%o%o",
				(tempch&0100)>>6,(tempch&070)>>3,tempch&007);

		indx++;
	}
	printf("\n");
}

/*****************************************************************************

PURPOSE
		Set up tpfile and temp dp file

DESCRIPTION
		open tpdb, create a tempfile and create a termlist of
		terminal ids, read in first buffer.

CALLED BY       main

CALLS           
		printf

*****************************************************************************/
tpefiles()
{
/*	extern  char      yesorno();*/
	extern  char     *Tempfile;
	extern  tpstruct  Tprecord;     /* stores a tpdb record */
	extern  int       Index;        /* offset into input buffer */
	extern  char      Termlist[];
	extern  int       Numofterm;    /* number of entry in the devicelist */
	extern  int       F1, F2;       /* file descriptors */
	int     n;
	int     lindex;                 /* local index */

	/*
	 * open tpdb */
	if ((F1 = N_open(tpdbPath, READ)) == -1)
	{
		printf("Can't open terminal profile data base.\n");
		printf("Do you wish to create it (y or n) ?");
		if ( yesorno() == YES )
		{
			if ((F1 = N_create (tpdbPath, READ, PMODE)) == -1)
			{
				printf("Can't create terminal data base.\n");
				tpeexit();
			}
		}
		else    /* NO - don't create data base */
			tpeexit();
	}

	/* create temporary file of tpdb which is to be used for editing */
	if ((F2 = N_create (Tempfile, RW, PMODE)) == -1)
	{
		printf("can't create tpdbtemp\n");
		printf("Do you wish to proceed anyway (y or n) ?");
		if ( yesorno() == YES )
		{
			tpdbrm();	/* remove it, or die trying */
			if ((F2 = N_create (Tempfile, RW, PMODE)) == -1)
			{
				printf("Can't recreate terminal data base.\n");
				tpeexit();
			}
		}
		else    /* NO - don't create data base */
			tpeexit();
	}


	if ( F2 == -1 || F1 == -1 )
		tpeexit();

	/* copy file */
	lindex = 0;
	while((n = N_read(F1,&Tprecord,sizeof(Tprecord))) > 0)
		if(N_write(F2,&Tprecord,n) != n)
			printf("write error while writing temp file\n");
                else
		/* as long as null records are getting written at the end
		 * of the file and config is still a char (y or n)
		 * make a check for null records */
		if (Tprecord.config != ENDSTRING)
		{
			Termlist[lindex++] = Tprecord.ttyid;
		}
	if ((Numofterm = lindex) == ZERO)
		Index = -1;
	else
		Index = 0;
	N_flush(F2);
	N_close(F1);
}

/*****************************************************************************

PURPOSE
		Gettyid returns the unique tty id of a terminal

CALLED BY       add, change

CALLS           printf, scaner

*****************************************************************************/
char gettyid(list,num)
char list[];
register int num;
{
	char    name;                   /* user input */
	char	id;			/* input id */
	unsigned int    tempid;         /* temporary id */
	int     anumber;

	while (FOREVER)
	{
		printf ("\nEnter tty id: ");

		do
			anumber = getdec (&tempid, &name);
		while ((anumber != FOUND) && (name != NEWLINE));

		if (name != NEWLINE)
			while ((name = getchar()) != NEWLINE);

		if ((anumber != FOUND)  || (tempid < 0) || (tempid > 254))
			printf ("Id must be between 0 and 254.\n");

		else
			break;
	}
	id = tempid;

	return(id);
}
/*****************************************************************************

PURPOSE
		Getbaud asks for the default baud rate of a terminal

CALLED BY       add, change

CALLS           printf, scaner

*****************************************************************************/

getbaud(type)
char	 *type;
{
	register int     anumber;       /* if a number read, returned as ON */
	register int     i;             /* index */
	int     again = ON;             /* continue flag */
	int     id;                     /* input  id */
	char    c;                      /* nondigit read from input */

	while(again)
	{
		/* read standard in for number or carriage return */
		printf ("\nEnter default %s baud rate: ",type);
		do
			anumber = getdec(&id,&c);
		while ((anumber != FOUND) && (c != NEWLINE));

		/* number entered */
		if ((c == NEWLINE) && (anumber == FOUND))
		{
		     /* check if number out of range */
		     if (id < ZERO)
			    printf ("Number too large.\n\n");
		     else
			    again = OFF;
		}
		/* non numeric value entered */
		else
			printf("Numeric value needed.\n");
	}
	return(id);
}
/*****************************************************************************

PURPOSE
		Getprty ask for the default parity of a terminal and
		check for its validity

CALLED BY       add, change

CALLS           printf, scaner

*****************************************************************************/

getprty()
{
	char	parity[LINELENGTH];	/* input parity type */

	while(FOREVER)
	{
		printf ("\nEnter default parity (even, odd, or none): ");
		scaner(parity);

		switch ( parity[0] )
		{
			case 'e': return(0);
			case 'E': return(0);

			case 'o': return(1);
			case 'O': return(1);

			case 'n': return(2);
			case 'N': return(2);

		}
	}
}
/*****************************************************************************

PURPOSE
		Find is a module to search the file for the name
		passed as an argument of the command.

DESCRIPTION
		Find will search the file for the requested record and
		will set a pointer to the beginning of that record
		if it is found. A message will be printed if not found.

CALLED BY
		main

CALLS
		printf, scaner

*****************************************************************************/
tpefind(list,num)
char list[];
register int num;
{
	extern  int     Index;          /* index into tpdb */
	char    name[LINELENGTH];       /* user input */
	char	id;			/* input id */
	register int     start_index;   /* begining position in tpdb */

	if (Index == ERROR)
	{
		printf ("No record.\n");
		return;
	}

	/* get a tty id */
	id = gettyid (list, num);

	/* save current position */
	start_index = Index;

	/* search through list */
	while ( id != list[Index] )
	{
		Index++;

		if(Index == num)       /* go to top when end reached */
			Index = 0;

		if(Index == start_index)        /* name not found */
		{
			printf ("Record not found.\n\n");
			return;
		}
	}
	return;
}




/*****************************************************************************

PURPOSE
		Next is a module to set the Index to the
		tpenext valid record in the database file.

DESCRIPTION
		Next will add one to the Index, looping until
		it has reached a valid field in namelist.

CALLED BY
		main

CALLS
		printf, scaner

*****************************************************************************/
tpenext(list,num)
char list[];
register int num;
{
	extern  int     Index;          /* index into list */
	register int     start_index;   /* begining position in list */

	if (Index == ERROR)
	{
		printf ("No record.\n");
		return;
	}

	/* save current position in the database */
	start_index = Index;

	/* search through list */
	while (FOREVER)
	{
		Index++;

		if(Index == num)       /* go to top when end reached */
			Index = 0;

		if (list[Index] != notvalid)
			return;                 /* valid name found */

		if(Index == start_index)        /* no valid records found */
		{
			printf ("No other records.\n\n");
			return(ERROR);
		}
	}
}


/*****************************************************************************

PURPOSE
		Delete is a module to handle the deletion of a
		record from the file

DESCRIPTION
		The first fieldname of the record currently pointed to
		will be echoed and verifiction ask for to delete,
		A "y" will cause deletion of the entire record,
		anything else will be considered as no and procedure exited.

CALLED BY       main

CALLS		
		printf

*****************************************************************************/
tpedelete(list,num)
char list[];
register int num;
{
/*	extern char     yesorno();*/
	extern int      Changed_flag;
	extern int      Index;
	register int     start_index;   /* beginning position in list */

	if (Index == ERROR)
	{
		printf ("No record.\n");
		return;
	}

	printf("Do you want to delete tty %d (y or n) : ",list[Index]);

	if ( yesorno() == YES )
	{
		/* delete record from temp tpfile by blanking name field */
		list[Index] = notvalid;

		printf ("Record deleted.\n\n");
		Changed_flag = ON;

		/* move Index to tpenext record */
		if (tpenext(list,num) == ERROR)
			Index = -1;
	}
	else
		printf("Record not deleted.\n\n");

}



/*****************************************************************************

PURPOSE
		Quit is the module which ends execution of the
		editor.

DESCRIPTION
		When ending execution, the user has the option to
		save the editing session updates. The files are 
		closed and execution of the editor teminated.

ASSERT
		Assume a temp file is open for read

CALLED BY       main

CALLS           yesorno,
		close, open, read, write, printf

*****************************************************************************/
tpequit(list,num,filepath,record,size)
char list[];
register int num;
char	 *filepath;
char     *record;
register int size;
{
/*	extern char   yesorno();*/
	extern int    F1,F2;            /* file descriptors */
	extern int    Index;            /* offset into input buffer */
	extern int    Changed_flag;     /* flag set if changes made */
	register int    file_read;      /* number of bytes received by read */

	if (Changed_flag == ON)
	{
		printf("Do you want to save the updates? ");

		if (yesorno() == YES)
		{
			creatdb(filepath);

			if (Index != ERROR)
				writetdb(list,num,record,size);
		}
	}

	N_close (F1);
	N_close (F2);

	tpdbrm();			/* remove the temp file */

	tpeexit();			/* print msg and exit */

}

writetdb(list,num,record,size)
char list[];
register int num;
char     *record;
register int size;
{
	extern int    F1,F2;            /* file descriptors */
	extern int    Index;            /* offset into input buffer */
	int  file_read;                 /* number of bytes received by read */


	for (Index = 0; Index < num; Index++)
		if (list[Index] != notvalid)
		{
			N_seek (F2,(long) Index * size,0);
			file_read = N_read (F2,record,size);
			if (file_read != size)
			{
				printf ("error writing database file\n");
				tpeexit();
			}
			N_write (F1,record,file_read);
		}
}

/*****************************************************************************

PURPOSE:
		tpdbrm() - removes the tpdbtemp file

DESCRIPTION
		This routine is used to encapsulate the fcn so it may be done
		when the editor exits, or when the user wishes to
		ignore the existance of the temp/locl file

ASSERT
		The temp file exists

CALLED BY
		tpequit, tpefiles

WRITTEN BY
		Tom Perrine (Jan 16, 1986)
*****************************************************************************/
tpdbrm()
{
	extern char   *Tempfile;        /* pointer to temp file */
	seid parent;
	seid fseid;
	char entry_name[SIZE_NAME];

	if (UDM_find (ROOT, Tempfile, po_REMOVE, &parent, &fseid, &entry_name)
	    != UDM_no_error)
	{
	    printf ("Can't remove %s\n", Tempfile);
	    tpeexit();
	}

	if (UDM_rm (parent, &entry_name, TRUE) != UDM_no_error)
	    printf ("Removal of %s failed\n", Tempfile);
}



/*****************************************************************************

PURPOSE:
		tpeexit() - print message and kill current process

DESCRIPTION
		This routine is used to encapsulate the fcn so it may be done
		for all exits, normal and otherwise

CALLED BY
		tpequit, various other places

WRITTEN BY
		Tom Perrine (Jan 16, 1986)
*****************************************************************************/
tpeexit()
{
	printf ("TPE exit . . .\n");
	K_release_process (null_seid);
}



/************************************************************************
	The following routines are in support of the tpeprint
	module and cause the Terminal Profile Data Base to be
	written to the file /sys/tmp/prttp and the seid of that
	file to be sent via an IPC message to the Printer Daemon.
************************************************************************/

find_LPD()
{
	int     result;                 /* result returned by kernel */
	seid    lpd_file[128];      /* contents of /lpdseid */
	openDescriptor lpd_od;      /* open descriptor to /lpdseid */
	char *lpd_path = "/lpdseid";
	
	if ((lpd_od = N_open(lpd_path, READ)) == IO_FAIL)
		abort("Cannot open LPD seid file", NON_KCALL, NO_ERR);
	printf("Found /lpdseid\n");
	if ((result = N_read(lpd_od, &lpd_file, 512)) == IO_FAIL)
		abort("Cannot read LPD seid file", NON_KCALL, NO_ERR);
	lpd_seid = lpd_file[0];
	if ((result = N_close(lpd_od)) == IO_FAIL)
		abort("Cannot close LPD seid file", NON_KCALL, NO_ERR);
}

print_tpdb()
{
	tpstruct entry;              /* entry in the tp data base */
	openDescriptor tp_opendes;     /* open descriptor to tpdbtmp */
	int     result;                 /* value returned by buffered io */
	char *tp_path = "/sys/tmp/tpdbtemp";
	
	zero_prt();                     /* clear print file, get prt_od */
	buffString("The Terminal Profile Data Base\n\n");
	if ((tp_opendes = N_open(tp_path, READ)) == IO_FAIL)
		abort("Cannot open the tp data base", NON_KCALL, NO_ERR);
	while(TRUE)
	{
		if ((result = N_read(tp_opendes, &entry, sizeof(entry))) == IO_FAIL)
			abort("Cannot read from the tp data base", NON_KCALL, NO_ERR);
		if (result == IO_EOF)
			break;
		put_tp_entry(&entry);
	}
	if ((result = N_flush(prt_od)) == IO_FAIL)
		abort("Cannot write to print file", NON_KCALL, NO_ERR);
	if ((result = N_close(tp_opendes)) == IO_FAIL)
		abort("Cannot close the tp data base", NON_KCALL, NO_ERR);
	if ((result = N_close(prt_od)) == IO_FAIL)
		abort("Cannot close the print file", NON_KCALL, NO_ERR);
	send_to_LPD();  /* dispatch IPC message to Printer Daemon */
}


put_tp_entry (record)
tpstruct *record;
{
	buffString("Tty Id :  ");
	buffDecC((*record).ttyid);
	buffString(",   Configured ?  ");
	buffChar((*record).config);
	buffString(",   Console ?  ");
	buffChar((*record).console);
	buffString(",   Default Baud Rates -  Tx :  ");
	buffDecC((*record).xmitBaud);
	buffString(",  Rx :  ");
	buffDecC((*record).recBaud);
	buffString("\n    Default Parity :  ");
	switch((*record).parity)
	{
		case 0: buffString("even"); break;
		case 1: buffString("odd "); break;
		case 2: buffString("none"); break;
	}
	buffString(",   Clear Screen Sequence :  ");
	buffString((*record).clrScreen);
	buffString("\n    Maximum Access Level :  ");
	buffLevel(&(*record).maxLevel);
}

send_to_LPD()
{
	msg_struct  ipc;                /* IPC message buffer */
	
	ipc[0] = LPD_EVENT;
	ipc[1] = '\0';
	ipc[2] = prt_seid.nsp & 0377;
	ipc[3] = prt_seid.uniq_id0;
	ipc[4] = prt_seid.uniq_id1 % 256;
	ipc[5] = prt_seid.uniq_id1 / 256;
	printf("Sending msg to LPD\n");
	error = K_post(lpd_seid, FALSE, &ipc);
	if (error != XOK)
		if (error == XpostEh)
			abort("LPD queue is full", "K_post", error);
		else
			abort("Printer Daemon not running", "K_post", error);
}

zero_prt()
{
	cardinal32 size;                /* size for K_devfun call */
	int  result;
	char *prt_file_path = "/sys/tmp/prttp";
	
	size = 0;
	if ((prt_od = N_open(prt_file_path, RW)) != IO_FAIL)
	{
		printf("Erasing print file\n");
		error = K_device_function(prt_od, ERASEFILE, size,
			      &null_Pblk, &null_Pblk, 0, &errs, &devfun_read);
		if (error != NO_ERR)
			abort("Cannot erase print file", "K_device_function", error);
	}
	else
	{
		if ((prt_od = N_create(prt_file_path, RW, PRTMODE)) == IO_FAIL)
			abort("Cannot create print file", NON_KCALL, NO_ERR);
	}
	if ((result = N_tell_seid(prt_od, &prt_seid)) == IO_FAIL)
		abort("Cannot get seid of print file", NON_KCALL, NO_ERR);
}

buffLevel(level)
access_level_type *level;
{
	extern secarray seclist[];
	int    i;
	
	buffString(" Security Category :  ");
	i = (*level).security_category;
	buffString(seclist[i].shortname);
	buffString(",   Integrity Category :  ");
	i = (*level).integrity_category;
	buffString(seclist[NUMSECCAT+(i)].shortname);
	buffString("\n    Security Compartments :\n        ");
	buffComp(&level->security_compart);
	buffString("\n\n");
}

buffComp(comp)
int *comp;
{
	int compartment[2];
	extern secarray seclist[];
	int any=OFF;
	int mask;
	int j;
	int order;
	
	compartment[0] = *comp;
	compartment[1] = *(comp+1);
	for (mask=1,j=COMPLOW,order=0; j<COMPHIGH; mask <<= 1, j++)
	{
		if (j == HALFWAY)
		{
			order = 1;
			mask = 1;
		}
		if ((compartment[order] & mask) && (seclist[j].activ == ACTIVE))
		{
			buffString(seclist[j].shortname);
			buffString(" = ");
			buffDecC(j-NUMCAT);
			buffString("  ");
			any = ON;
		}
	}
	if (any == OFF)
	buffString("NULL");
}

buffChar (bchar)
char bchar;
{
	char str[2];

	str[0] = bchar;
	str[1] = '\0';
	buffString(str);
}

buffDecC (num)
int num;                          /* decimal integer to be printed */
{
	char    *str;
	
	itoa(num, &str, 10);
	buffString(&str);
}

buffC32 (num)
cardinal32 num;                   /* double word to be printed */
{
	char    *str;
	int     num1;
	
	num1 = num / 65536;
	itoa(num1, &str, 10);
	buffString(&str);
	buffString("/");
	num1 = num % 65536;
	itoa(num1, &str, 10);
	buffString(&str);
}

itoa (num, str, base)
int num;                          /* number to be converted */
char str[];                        /* ascii string */
int base;                         /* base for conversion */
{
	int     i, j, val;
	char    str1[6];
	char *digits = "0123456789";
	
	val = num;
	for (i=0; i<=5; i++)
		str[i] = '\0';
	for (i=0; i<=5; i++)
	{
		j = val % base;
		str1[i] = digits[j];
		val = val / base;
		if (val == 0)
			break;
	}
	for (j=0; j<=5; j++)
	{
		str[i--] = str1[j];
		if (i < 0)
			break;
	}
}


buffString (string)
char *string;                     /* string to be printed */
{
	int     n, result;
	
	n = strlen(string);
	if ((result = N_write(prt_od, string, n)) == IO_FAIL)
		abort("Cannot write to print file", NON_KCALL, NO_ERR);
}

abort(err_msg, call_name, exception)
char *err_msg;                        /* error message to print */
char *call_name;                      /* kernel call, if any */
int exception;                        /* error returned from kernel call */
{
	printf("%s\n", err_msg);
	if (exception != NO_ERR)
		printf("%s returns %d\n", call_name, exception);
	printf("Aborting TPE\n");
	K_release_process(null_seid);
}


strlen(s)
char s[];                             /* string to be sized */
{
	int i;
	
	i = 0;
	while (s[i] != '\0')
		++i;
	return(i);
}
