/*
 * qmgr/mgr_show.c
 * 
 * DESCRIPTION:
 *
 *	NQS manager show command execution module.
 *
 *	Original Author:
 *	-------
 *	Brent A. Kingsbury, Sterling Software Incorporated.
 *	March 30, 1986.
 */

#include <libnqs/license.h>
#include <libnqs/proto.h>
#include <libnqs/nqsxvars.h>			/* NQS external vars */

#include <libsal/license.h>
#include <libsal/proto.h>
#include <libsal/defines.h>

static int putname ( char *name, int width, int col );
static void shofor ( void );
static void shoman ( void );
static void shopar ( void );
static void shoservers ( void );

extern Mid_t Local_mid;			/* Machine-id of local host */
extern int Mgr_priv;			/* Privilege bits for current */
					/* user of Qmgr as imported from */
					/* mgr_main.c */
int monsanto_header = 0;

/*** v_shoall
 *
 *
 *	void v_shoall():
 *	SHOw All command.
 */
void v_shoall()
{

	long flags;			/* Display flags */
	short daepresent;		/* Boolean non-zero if the local */
					/* NQS daemon is present and running */

	if (scan_end() == -1) return;
	/*
	 *  Determine if the local NQS daemon is still present and running,
	 *  and set the daepresent boolean flag accordingly.
	 */
#if	HAS_BSD_PIPE
	daepresent = daepres (Queuefile);
#else
	daepresent = daepres();
#endif
        flags = (SHO_R_QUEUE | SHO_R_STANDARD 
                 | SHO_RS_RUN | SHO_RS_EXIT | SHO_RS_QUEUED
                 | SHO_RS_HOLD  | SHO_RS_WAIT | SHO_RS_STAGE
		 | SHO_RS_ARRIVE | SHO_R_ALLUID );
	printf ("Queues:\n\n");
	/*
	 *  We must seek to the start of all of the database files
	 *  used by shoallque(), because this Qmgr program (or other
	 *  Qmgr programs), may have just changed the NQS configuration.
	 *
	 *  Furthermore, we use seekdb() INSTEAD of seekdbb(), since
	 *  we MUST do an unbuffered seek to get the latest copy of
	 *  the first block of each of the requisite database files.
	 */
	seekdb (Queuefile, 0L);		/* Seek (unbuffered) to file start */
	seekdb (Qmapfile, 0L);		/* Seek (unbuffered) to file start */
	seekdb (Pipeqfile, 0L);		/* Seek (unbuffered) to file start */
        seekdb (Qcomplexfile, 0L);      /* Seek (unbuffered) to file start */
	shoallque(Queuefile, flags, 
		0,		/* whomuid */
		NULL,		/* struct reqset *reqs */
		daepresent,
		Qmapfile,
		Pipeqfile,
		0,		/* not remote */
		Qcomplexfile);
	printf ("Devices:\n\n");
	/*
	 *  We must seek to the start of the device definition
	 *  file used by shoalldev(), since this Qmgr program (or
	 *  other Qmgr programs), may have just changed the NQS
	 *  configuration.
	 *
	 *  Furthermore, we use seekdb() INSTEAD of seekdbb(), since
	 *  we MUST do an unbuffered seek to get the latest copy of
	 *  the first block of the device definition file.
	 */
	seekdb (Devicefile, 0L);	/* Seek (unbuffered) to file start */
	shoalldev (Devicefile);
	printf ("Managers:\n");
	shoman();
	printf ("Forms:\n");
	shofor();
	printf ("NQS operating parameters:\n");
	shopar();
	printf ("Limits supported:\n\n");
	shoalllim ((struct confd *) 0, 0);	/* Don't show shell strategy */
	printf ("Compute server performance:\n");
	shoservers();
}


/*** v_shodev
 *
 *
 *	void v_shodev():
 *	SHOw Device command.
 */
void v_shodev()
{
	char devname [MAX_DEVNAME + 1 + MAX_MACHINENAME + 1];

	/*
	 *  We must seek to the start of the device definition
	 *  file used by shoalldev() and shodbyname(), since this
	 *  Qmgr program (or other Qmgr programs), may have just
	 *  changed the NQS configuration.
	 *
	 *  Furthermore, we use seekdb() INSTEAD of seekdbb(), since
	 *  we MUST do an unbuffered seek to get the latest copy of
	 *  the first block of the device definition file.
	 */
	seekdb (Devicefile, 0L);	/* Seek (unbuffered) to file start */
	if (scan_opdev (devname) == -1) return;	/* Scan optional device */
	if (devname [0] == '\0') {
		shoalldev (Devicefile);
	}
	else {
		if (scan_end() == -1) return;
		shodbyname (Devicefile, devname);
	}
	endmacnam();			/* Discard machine-name cache */
	endusenam();			/* Flush username cache and */
}					/* close password file opened */
					/* by shodev() */


/*** v_shofor
 *
 *
 *	void v_shofor():
 *	SHOw Forms command.
 */
void v_shofor()
{

	if (scan_end() == -1) return;
	shofor();
}


/*** shofor
 *
 *
 *	void shofor():
 *	Show the forms set.
 */
static void shofor()
{
	register struct gendescr *descr;
	register int col;

	/*
	 *  We must seek to the start of all the forms definition
	 *  file, since this Qmgr program (or other Qmgr programs),
	 *  may have just changed the NQS configuration.
	 *
	 *  Furthermore, we use seekdb() INSTEAD of seekdbb(), since
	 *  we MUST do an unbuffered seek to get the latest copy of
	 *  the first block of the forms definition file.
	 */
	seekdb (Formsfile, 0L);		/* Seek (unbuffered) to file start */
	putchar ('\n');
	descr = nextdb (Formsfile);
	col = 3;
	while (descr != (struct gendescr *) 0) {
		col = putname (descr->v.form.forms, MAX_FORMNAME, col);
		descr = nextdb (Formsfile);
	}
	if (col != 3) putchar ('\n');
	putchar ('\n');
}


/*** v_sholim
 *
 *
 *	void v_sholim():
 *	SHOw LImits_supported command.
 */
void v_sholim()
{
	if (scan_end() == -1) return;
	putchar ('\n');
	shoalllim ((struct confd *) 0, 0);	/* Don't show shell strategy */
}


/*** v_sholongque
 *
 *
 *	void v_sholongque():
 *	SHOw LOng Queue command.
 */
void v_sholongque()
{
	char quename [MAX_QUEUENAME+1+MAX_MACHINENAME+1]; /* Name of queue */
	long flags;			/* Display flags */
	short daepresent;		/* Boolean non-zero if the local */
					/* NQS daemon is present and running */
	long whomuid = 0;		/* Uid of account name */

	flags = (SHO_R_LONG | SHO_R_ALLUID );
	flags |= (SHO_RS_EXIT | SHO_RS_RUN | SHO_RS_STAGE |
               SHO_RS_QUEUED | SHO_RS_WAIT | SHO_RS_HOLD | SHO_RS_ARRIVE);
        flags |= (SHO_H_DEST | SHO_H_ACCESS | SHO_H_LIM | SHO_H_MAP |
               SHO_H_RUNL | SHO_H_SERV | SHO_H_TIME );
	if (scan_opqueue (quename) == -1) return;
#if	HAS_BSD_PIPE
	daepresent = daepres (Queuefile);
#else
	daepresent = daepres();
#endif
	/*
	 *  We must seek to the start of all of the database files
	 *  used by shoallque() or shoqbyname(), because this Qmgr
	 *  program (or other Qmgr programs), may have just changed
	 *  the NQS configuration.
	 *
	 *  Furthermore, we use seekdb() INSTEAD of seekdbb(), since
	 *  we MUST do an unbuffered seek to get the latest copy of
	 *  the first block of each of the requisite database files.
	 */
	seekdb (Queuefile, 0L);
        seekdbb (Qcomplexfile, 0L);
	seekdb (Qmapfile, 0L);
	seekdb (Pipeqfile, 0L);
	if (quename [0] == '\0') {
		/*
		 *  All queues are to be shown.
		 *  Whomuid contains garbage, OK because SHO_R_ALLUID is on.
		 *  The same is true below if whomuid == -1.
		 */
		shoallque(Queuefile, flags, whomuid,
			NULL,		/* struct reqset *reqs */
			daepresent,	/* short dae_present */
			Qmapfile,
			Pipeqfile,
			0,		/* not remote */
			Qcomplexfile);
	}
	else {
		if (scan_opaname (&whomuid) == -1) return;
		if (whomuid != -1) {
			if (scan_end() == -1) return;
			flags &= ~SHO_R_ALLUID;
		}
		shoqbyname (Queuefile, quename, flags, whomuid,
			NULL,		/* struct reqset *reqs */
			daepresent,	/* short dae_present */
			Qmapfile,
			Pipeqfile,
			Qcomplexfile);
	}
	endgrpnam();		/* Flush groupname cache and close */
				/* group file opened by a callee */
	endmacnam();		/* Discard machine-name cache */
	endusenam();		/* Flush username cache and close */
}				/* password file opened by a callee */


/*** v_shoman
 *
 *
 *	void v_shoman():
 *	SHOw Managers command.
 */
void v_shoman()
{
	if (scan_end() == -1) return;
	shoman();
}


/*** shoman
 *
 *
 *	void shoman():
 *	Show the manager set.
 */
static void shoman()
{
	register struct gendescr *descr;

	/*
	 *  We must seek to the start of all the manager definition
	 *  file, since this Qmgr program (or other Qmgr programs),
	 *  may have just changed the NQS configuration.
	 *
	 *  Furthermore, we use seekdb() INSTEAD of seekdbb(), since
	 *  we MUST do an unbuffered seek to get the latest copy of
	 *  the first block of the manager definition file.
	 */
	seekdb (Mgrfile, 0L);		/* Seek (unbuffered) to file start */
	putchar ('\n');
	descr = nextdb (Mgrfile);
	while (descr != (struct gendescr *) 0) {
		if (descr->v.mgr.manager_mid != Local_mid) {
			/*
			 *  The manager account is on a remote machine.
			 */
			printf ("  [%1d]@", (int) descr->v.mgr.manager_uid);
			fputs (getmacnam (descr->v.mgr.manager_mid), stdout);
		}
		else {
			/*
			 *  The manager account is on the local machine.
			 */
			printf ("  %s", getusenam (descr->v.mgr.manager_uid));
		}
		if (descr->v.mgr.privileges & QMGR_MGR_PRIV) {
			fputs (":m\n", stdout);
		}
		else fputs (":o\n", stdout);
		descr = nextdb (Mgrfile);
	}
	endmacnam();			/* Discard machine-name cache */
	endusenam();			/* Discard username cache and */
	putchar ('\n');			/* close the password file */
}


/*** v_shoservers
 *
 *
 *	void v_shoservers():
 *	SHOw Managers command.
 */
void v_shoservers()
{
	if (scan_end() == -1) return;
	shoservers();
}


/*** shoservers
 *
 *
 *	void shoservers():
 *	Show the compute server performance set.
 */
static void shoservers()
{
	register struct gendescr *descr;

	/*
	 *  We must seek to the start of all the server definition
	 *  file, since this Qmgr program (or other Qmgr programs),
	 *  may have just changed the NQS configuration.
	 *
	 *  Furthermore, we use seekdb() INSTEAD of seekdbb(), since
	 *  we MUST do an unbuffered seek to get the latest copy of
	 *  the first block of the manager definition file.
	 */
	seekdb (Serverfile, 0L);	/* Seek (unbuffered) to file start */
	putchar ('\n');
	descr = nextdb (Serverfile);
	while (descr != (struct gendescr *) 0) {
	    fputs (getmacnam (descr->v.cserver.server_mid), stdout);
	    printf("	%ld\n", descr->v.cserver.rel_perf);
	    descr = nextdb (Serverfile);
	}
	endmacnam();			/* Discard machine-name cache */
	putchar ('\n');	
}

/*** putname
 *
 *
 *	int putname():
 *	Display a name in formatted columns width+2 fields wide.
 */
static int putname (
	char *name,		/* Name to be displayed */
	int width,		/* Maximum name length */
	int col)		/* Current column: [1..n] */
{
	register int i;

	printf ("  %s", name);
	width += 2;
	if ((col += width) + width > 79) {
		putchar ('\n');
		col = 3;
	}
	else {
		i = width - strlen (name);
		while (i--) putchar (' ');
	}
	return (col);
}


/*** v_shopar
 *
 *
 *	void v_shopar():
 *	SHOw Parameters command.
 */
void v_shopar()
{

	if (scan_end() == -1) return;
	shopar();
}


/*** shopar
 *
 *
 *	void shopar():
 *	Show general NQS operating parameters.
 */
static void shopar()
{
	/*
	 *  We must seek to the start of all the general parameters
	 *  file, since this Qmgr program (or other Qmgr programs),
	 *  may have just changed the NQS configuration.
	 *
	 *  Furthermore, we use seekdb() INSTEAD of seekdbb(), since
	 *  we MUST do an unbuffered seek to get the latest copy of
	 *  the first block of the general parameters file.
	 */
	seekdb (Paramfile, 0L);		/* Seek (unbuffered) to file start */
	ldparam();			/* Load general NQS operating */
					/* parameters. */
	putchar ('\n');
	printf ("  Debug level =  %1d\n", sal_debug_GetLevel());
	printf ("  Global batch run limit = %d\n", Maxgblbatlimit);
	printf ("  Global pipe route limit = %d\n", Maxgblpiplimit);
	printf ("  Default batch_request priority = %1d\n", Defbatpri);
	printf ("  Default batch_request queue = ");
	if (Defbatque [0] == '\0') printf ("NONE\n");
	else printf ("%s\n", Defbatque);
	printf ("  Default destination_retry time = %1ld hours\n",
	       (long) Defdesrettim / 3600);
	printf ("  Default destination_retry wait = %1ld minutes\n",
	       (long) Defdesretwai / 60);
	printf ("  Default load interval = %ld minutes\n",  Defloadint/60);	
	printf ("  Default device_request priority = %1d\n", Defdevpri);
	if (Defprifor[0] == '\0') printf ("  No default print forms\n");
	else printf ("  Default print forms = %s\n", Defprifor);
	printf ("  Default print queue = ");
	if (Defprique [0] == '\0') printf ("NONE\n");
	else printf ("%s\n", Defprique);
	printf ("  (Pipe queue request) Lifetime = %1ld hours\n",
		Lifetime / 3600);
	printf ("  Log_file = ");
	if (Logfilename [0] == '\0') printf ("/dev/null");
	else fputs (Logfilename, stdout);
	putchar ('\n');
	printf ("  Mail account = %s\n", getusenam (Mail_uid));
	printf ("  Maximum number of print copies = %1d\n", Maxcopies);
	printf ("  Maximum failed device open retry limit = %1d\n", Maxoperet);
	printf ("  Maximum print file size = %1d bytes\n", Maxprint);
	printf ("  Netdaemon = ");
	if (Netdaemon [0] == '\0') printf ("NONE\n");
	else printf ("%s\n", Netdaemon);
	printf ("  Netclient = ");
	if (Netclient [0] == '\0') printf ("NONE\n");
	else printf ("%s\n", Netclient);
	printf ("  Netserver = ");
	if (Netserver [0] == '\0') printf ("NONE\n");
	else printf ("%s\n", Netserver);
	printf ("  Loaddaemon = ");
	if (Loaddaemon [0] == '\0') printf ("NONE\n");
	else printf ("%s\n", Loaddaemon);
	printf ("  (Failed device) Open_wait time = %1d seconds\n", Opewai);
	if (Plockdae) printf ("  NQS daemon is LOCKED in memory\n");
	else printf ("  NQS daemon is not locked in memory\n");
	Seqno_user = nextseqno();	/* Next request seq# */
	printf ("  Next available sequence number = %1ld\n", Seqno_user);
	printf ("  Batch request shell choice strategy = ");
	if (Shell_strategy == SHSTRAT_FREE) printf ("FREE\n");
	else {
		if (Shell_strategy == SHSTRAT_LOGIN) printf ("LOGIN\n");
		else {
			printf ("FIXED: %s\n", Fixed_shell);
		}
	}
	printf ("  Scheduler = ");
	if (LB_Scheduler == 0) printf ("NONE\n");
	else printf ("%s\n", fmtmidname(LB_Scheduler) );
	/* 
	 * We don't know these pids in the manager image.
	 *
	 * printf ("  Net Daemon pid = ");
	 * if (Netdaepid) printf("%d\n", Netdaepid);
	 * else printf ("NONE\n");
	 * printf ("  Load Daemon pid = ");
	 * if (Loaddaepid) printf("%d\n", Loaddaepid);
	 * else printf ("NONE\n");
	 */
	putchar ('\n');
	endusenam();			/* Discard username cache */
}


/*** v_shoque
 *
 *
 *	void v_shoque():
 *	SHOw Queue command.
 */
void v_shoque()
{
	char quename [MAX_QUEUENAME+1+MAX_MACHINENAME+1]; /* Name of queue */
	long flags;			/* Display flags */
	short daepresent;		/* Boolean non-zero if the local */
					/* NQS daemon is present and running */
	long whomuid = 0;		/* Uid of account name */

        flags = (SHO_R_QUEUE | SHO_R_STANDARD 
                 | SHO_RS_RUN | SHO_RS_EXIT | SHO_RS_QUEUED
                 | SHO_RS_HOLD  | SHO_RS_WAIT | SHO_RS_STAGE
		 | SHO_RS_ARRIVE | SHO_R_ALLUID );

	if (scan_opqueue (quename) == -1) return;
#if	HAS_BSD_PIPE
	daepresent = daepres (Queuefile);
#else
	daepresent = daepres();
#endif
	/*
	 *  We must seek to the start of all of the database files
	 *  used by shoallque() or shoqbyname(), because this Qmgr
	 *  program (or other Qmgr programs), may have just changed
	 *  the NQS configuration.
	 *
	 *  Furthermore, we use seekdb() INSTEAD of seekdbb(), since
	 *  we MUST do an unbuffered seek to get the latest copy of
	 *  the first block of each of the requisite database files.
	 */
	seekdb (Queuefile, 0L);		/* Seek (unbuffered) to file start */
        seekdbb (Qcomplexfile, 0L);
	if (quename [0] == '\0') {
		/*
		 * All queues are to be shown.
		 * Whomuid contains garbage, OK because SHO_R_ALLUID is on.
		 * The same is true below if whomuid == -1.
		 */
		shoallque(Queuefile, flags, whomuid,
			NULL,		/* struct reqset *reqs */
			daepresent,	/* short dae_present */
			Qmapfile,
			Pipeqfile,
			0,		/* not remote */
			Qcomplexfile);
	}
	else {
		if (scan_opaname (&whomuid) == -1) return;
		if (whomuid != -1) {
			if (scan_end() == -1) return;
			flags &= ~SHO_R_ALLUID;
		}
		shoqbyname (Queuefile, quename, flags, whomuid,
			NULL,		/* struct reqset *reqs */
			daepresent,	/* short dae_present */
			Qmapfile,
			Pipeqfile,
			Qcomplexfile);
	}
        printf("\n");
	endgrpnam();		/* Flush groupname cache and close */
				/* group file opened by a callee */
	endmacnam();		/* Discard machine-name cache */
	endusenam();		/* Flush username cache and close */
}				/* password file opened by a callee */
