/*
 *	Network Queueing System (NQS)
 *  This version of NQS is Copyright (C) 1992  John Roman
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 1, or (at your option)
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
/*
*  PROJECT:     Network Queueing System
*  AUTHOR:      John Roman
*
*  Modification history:
*
*       Version Who     When            Description
*       -------+-------+---------------+-------------------------
*       V01.10  JRR                     Initial version.
*       V01.20  JRR     16-Jan-1992	Added support for RS6000.
*	V01.30  JRR	17-Jan-1992	Fix reference to SHO_R_SHORT.
*	V01.4   JRR	24-Jan-1992	Added variable monsanto_header.
*	V01.5   JRR	12-Feb-1992	Fixed declaration of static routines.
*	V01.6   JRR	02-Mar-1992	Added Cosmic V2 changes.
*       V01.7   JRR     08-Apr-1992     Added CERN enhancements.
*	V01.8	JRR	17-Jun-1992	Added header.
*	V01.9	JRR	22-Sep-1992	Fixed dash to equals.
*			20-Nov-1992	Changes related to 3.30.
*	V01.10	JRR	08-Jan-1993	Fix show queue & show long queue.
*	V01.11	JRR	06-Apr-1993	Add support for DECOSF.
*	V01.12	JRR	28-Feb-1994	Added support for SOLARIS.
*	V01.13	JRR	06-Apr-1994	Ranking compute servers.
*/
/*++ mgr_show.c - Network Queueing System
 *
 * $Source: /usr2/jrroma/nqs/nqs-3.36/src/RCS/mgr_show.c,v $
 *
 * DESCRIPTION:
 *
 *	NQS manager show command execution module.
 *
 *
 *	Author:
 *	-------
 *	Brent A. Kingsbury, Sterling Software Incorporated.
 *	March 30, 1986.
 *
 *
 * STANDARDS VIOLATIONS:
 *   None.
 *
 * REVISION HISTORY: ($Revision: 1.13 $ $Date: 1994/09/02 17:39:36 $ $State: Exp $)
 * $Log: mgr_show.c,v $
 * Revision 1.13  1994/09/02  17:39:36  jrroma
 * Version 3.36
 *
 * Revision 1.12  94/03/30  20:36:22  jrroma
 * Version 3.35.6
 * 
 * Revision 1.11  93/07/13  21:33:42  jrroma
 * Version 3.34
 * 
 * Revision 1.10  93/02/05  23:16:41  jrroma
 * Version 3.31
 * 
 * Revision 1.9  92/12/22  15:39:40  jrroma
 * Version 3.30
 * 
 * Revision 1.8  92/06/18  17:30:45  jrroma
 * Added gnu header
 * 
 * Revision 1.7  92/05/06  10:36:55  jrroma
 * Version 3.20
 * 
 * Revision 1.6  92/03/02  10:58:44  jrroma
 * Started to add Cosmic V2 changes.
 * 
 * Revision 1.5  92/02/12  15:55:22  jrroma
 * Fixed declaration of static routines.
 * 
 * Revision 1.4  92/02/12  15:54:15  jrroma
 * Added variable monsanto_header
 * 
 * Revision 1.3  92/01/17  14:55:12  jrroma
 * Fix reference to SHO_R_SHORT.
 * 
 * Revision 1.2  92/01/17  08:59:37  jrroma
 * Added support for RS6000.
 * 
 * Revision 1.1  91/10/03  16:20:19  jrroma
 * Initial revision
 * 
 *
 */

#include "nqs.h"			/* NQS types and definitions */
#include "nqsxvars.h"			/* NQS external vars */

#ifndef __CEXTRACT__
#if __STDC__

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 );

#else /* __STDC__ */

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 */);

#endif /* __STDC__ */
#endif /* __CEXTRACT__ */

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	BSD43 | ULTRIX | DECOSF
	daepresent = daepres (Queuefile);
#else
#if	HPUX | SGI  | SOLARIS | SYS52 | IBMRS | LINUX
	daepresent = daepres();
#else
BAD SYSTEM TYPE
#endif
#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;			/* 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	BSD43 | ULTRIX | DECOSF
	daepresent = daepres (Queuefile);
#else
#if	HPUX | SGI | SOLARIS | SYS52 | IBMRS | LINUX
	daepresent = daepres();
#else
BAD SYSTEM TYPE
#endif
#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("	%d\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 (name, width, col)
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", Debug);
	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 = %d 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 = %1ld 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 ("  Log Daemon pid = ");
	 * if (Logdaepid) printf("%d\n", Logdaepid);
	 * else printf ("NONE\n");
	 * 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;			/* 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	BSD43 | ULTRIX | DECOSF
	daepresent = daepres (Queuefile);
#else
#if	HPUX | SGI | SOLARIS | SYS52 | IBMRS | LINUX
	daepresent = daepres();
#else
BAD SYSTEM TYPE
#endif
#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 */
