/*
 *	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     ??-Oct-1991	Fixed -od                
*       V01.30  JRR     ??-Oct-1991	Fixed the fix to -od                
*       V01.40  JRR     29-Oct-1991	Added debug flag for interactive pgms.
*       V01.50  JRR     16-Jan-1992	Added support for RS6000.
*       V01.6   JRR     05-Mar-1992	Added Cosmic V2 changes.
*					including -c switch for complexes.
*       V01.7   JRR     09-Apr-1992     Added CERN enhancements.
*	V01.8	JRR	16-Jun-1992	Added Header,  Version 3.21
*	V01.9	JRR	17-Jun-1992	It helps to have comments start properly.
*	V01.10	JRR	30-Jul-1992	Add include for nqsvars.h.
*	V01.11	JRR	08-Jan-1993	Fix to agree with documentation.
*	V01.12	JRR	05-Mar-1993	Added Boeing enhancement to files.
*	V01.13	JRR	17-Aug-1993	Fixed up usage message.
*	V01.14	JRR	01-Mar-1994	Added support for SOLARIS.
*/
/*++ qstat.c - Network Queueing System
 *
 * $Source: /usr2/jrroma/nqs/nqs-3.35.6/src/RCS/qstat.c,v $
 *
 * DESCRIPTION:
 *
 *	Display queue status information.
 *	This program must run as a setuid program.
 *
 *
 *	Author:
 *	-------
 *	Brent A. Kingsbury, Sterling Software Incorporated.
 *	August 12, 1985.
 *
 *
 * STANDARDS VIOLATIONS:
 *   None.
 *
 * REVISION HISTORY: ($Revision: 1.14 $ $Date: 1994/03/30 20:37:09 $ $State: Exp $)
 * $Log: qstat.c,v $
 * Revision 1.14  1994/03/30  20:37:09  jrroma
 * Version 3.35.6
 *
 * Revision 1.13  93/09/10  13:57:30  jrroma
 * Version 3.35
 * 
 * Revision 1.12  93/07/13  21:34:12  jrroma
 * Version 3.34
 * 
 * Revision 1.11  93/02/05  23:16:51  jrroma
 * Version 3.31
 * 
 * Revision 1.10  92/12/22  15:43:26  jrroma
 * Version 3.30
 * 
 * Revision 1.9  92/06/18  09:08:29  jrroma
 * Version 3.21a
 * 
 * Revision 1.8  92/06/16  17:26:15  jrroma
 * *** empty log message ***
 * 
 * Revision 1.7  92/05/06  10:46:34  jrroma
 *  Version 3.20
 * 
 * Revision 1.6  92/03/20  10:57:28  jrroma
 * Done.
 * 
 * Revision 1.5  92/01/17  11:29:46  jrroma
 * Added support for RS6000
 * 
 * Revision 1.4  91/10/29  10:18:54  jrroma
 * Added debug flag for interactive pgms.
 * 
 * Revision 1.3  91/10/29  09:58:58  jrroma
 * Fixed with copy from skws02
 * 
 * Revision 1.4  91/10/23  14:39:09  jrroma
 * Fixed the fix for -od.
 * If ask for version, will do nothing else.
 * Version 3.02
 * 
 * Revision 1.3  91/10/23  13:37:30  jrroma
 * Fixed problem with segmentation fault with -od switch combination.
 * 
 * Revision 1.2  91/10/23  13:18:43  jrroma
 * Done
 * 
 * Revision 1.1  91/08/23  11:11:11  jrroma
 * Initial revision
 * 
 *
 */

#include "nqs.h"
#include <stdlib.h>
#include "nqsvars.h"			/* NQS global variables */

#ifndef __CEXTRACT__
#if __STDC__

static void sho_version ( void );
static void showhow ( void );

#else /* __STDC__ */

static void sho_version (/* void */);
static void showhow (/* void */);

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


/*
 *	Global variables:
 */
int  monsanto_header = 0;
char *Qstat_prefix = "Qstat";
int DEBUG;				/* Debug flag for interactive pgms. */

/*** main
 *
 *
 *      qstat [ -a ]            all users jobs
 *            [ -d ]            jobs in the local nqs domain
 *	      [ -h ]		force header with monsanto style
 *            [ -l ]            long format
 *            [ -o ]            originating from this node
 *            [ -s ]            original standard format
 *            [ -u username ]   particular user's requests
 *            [ -v ]            version
 *            [ <queue-name(s)> ]
 *
 *      Default is monsanto standard format for only the current user
 *      on the local machine.
 *
 *  To get information about queues:
 *
 *      qstat -x
 *            [ -b ]            Brief format
 *            [ -l ]            Long format
 *
 *
 *  To get information about complexes:
 *
 *      qstat -c
 *            [ -b ]            Brief format
 *            [ -l ]            Long format
 */
main (argc, argv)
int argc;
char *argv[];
{
	struct confd *queuefile;	/* Queue description file */
	struct confd *qcomplexfile;	/* Queue complex description file */
	struct confd *qmapfile;		/* Queue/device/destination mapping */
					/* file */
	struct confd *pipeqfile;	/* Pipe queue destination file */
	long flags;
	char *argument;
	short daepresent;		/* Boolean non-zero if the local */
					/* NQS daemon is present and running */
	char *whom;			/* Whom we are interested in */
	struct passwd *whompw;		/* Password entry of "whom" */
	uid_t whomuid;			/* Uid of whom we are interested in */
	struct reqset *reqset_ptr;	/* pointer to the request set */
	struct reqset reqset;		/* request set we are interested in */
	Mid_t	mymid;
	char	*root_dir;
	int	exit_status;		/* Status at exit */

        if ( ! buildenv()) {
                fprintf (stderr, "%s(FATAL): Unable to establish directory ", 
			Qstat_prefix);
                fprintf (stderr, "independent environment.\n");
		exit(1);
        }
	root_dir = getfilnam (Nqs_root,  SPOOLDIR);
	if (root_dir == (char *) NULL) {
		fprintf (stderr, "%s(FATAL): Unable to determine the NQS ",
			 Qstat_prefix);
		fprintf (stderr, "root directory.\n");
		exit (1);
	}
	if (chdir (root_dir) == -1) {
		fprintf (stderr, "%s(FATAL): Unable to chdir() to the NQS ",
			 Qstat_prefix);
		fprintf (stderr, "root directory.\n");
		exit (1);
	}
	relfilnam (root_dir);
	if ((queuefile = opendb (Nqs_queues, O_RDONLY)) == NULL) {
		fprintf (stderr, "%s(FATAL): Unable to open the NQS queue ",
			 Qstat_prefix);
		fprintf (stderr, "definition database file.\n");
		exit (1);
	}
	if ((qmapfile = opendb (Nqs_qmaps, O_RDONLY)) == NULL) {
		fprintf (stderr, "%s(FATAL): Unable to open the NQS queue/",
			 Qstat_prefix);
		fprintf (stderr, "device/destination\n");
		fprintf (stderr, "%s(FATAL): mapping database file.\n",
			 Qstat_prefix);
		exit (1);
	}
	if ((pipeqfile = opendb (Nqs_pipeto, O_RDONLY)) == NULL) {
		fprintf (stderr, "%s(FATAL): Unable to open the NQS pipe-",
			 Qstat_prefix);
		fprintf (stderr, "queue destination database file.\n");
		exit (1);
	}
	if ((qcomplexfile = opendb (Nqs_qcomplex, O_RDONLY)) == NULL) {
		fprintf (stderr, "%s(FATAL): Unable to open the NQS queue ",
			 Qstat_prefix);
		fprintf (stderr, "complex definition database file.\n");
		exit (1);
	}
	/*
	 *  Determine if the local NQS daemon is 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
	reqset_ptr = NULL;
	reqset.v.reqid.orig_mid = 0;
	reqset.v.reqid.orig_seqno = 0;
	reqset.selecttype = 0;
	reqset.next = NULL;
	whomuid = NULL;			/* Start with no one */
	flags = SHO_R_MONSANTO;		/* Assume short request format */
	while (*++argv != NULL && **argv == '-') {
	    argument = *argv;
	    while (*++argument != '\0') {
	        switch (*argument) {
		case 'a':
		    flags |= SHO_R_ALLUID;
		    break;
                case 'b':
                    flags |= SHO_R_BRIEF;
                    break;
                case 'c':
                    flags |= SHO_R_COMPLEX;
		    flags &= ~(SHO_R_STANDARD | SHO_R_MONSANTO);
                    break;
                case 'd':
                    flags |= SHO_R_DEST;
                    break;
                case 'h':
                    flags |= SHO_R_HEADER;
                    break;
		case 'l':
		    flags |= SHO_R_LONG;
		    flags &= ~(SHO_R_STANDARD | SHO_R_MONSANTO);
		    break;
                case 'm':	/* no-op -- synonym for default */
                    break;
                case 'o':
                    flags |= SHO_R_ORIGIN;
		    localmid(&mymid);
	            reqset.v.reqid.orig_mid = mymid;
		    reqset.v.reqid.orig_seqno = 0;
		    reqset.selecttype = SEL_REQID;
		    reqset.next = NULL;
		    reqset_ptr = &reqset;
                    break;
                case 's':
                    flags |= SHO_R_STANDARD;
                    flags &= ~(SHO_R_MONSANTO);
                    break;
		case 'u':
		    whom = *++argv;
		    if (whom == NULL) {
		        fprintf (stderr, "User name required ");
		        fprintf (stderr, "after -u.\n");
		        exit (5);
		    }
		    if ((whompw = fetchpwnam (whom)) ==
				        (struct passwd *) 0) {
		        fprintf (stderr, "Unknown user %s.\n", whom);
		        exit (6);
		    }
		    whomuid = whompw->pw_uid;
		    break;
                case 'v':
                    sho_version();
		    exit(0);
                    break;
		case 'x':
		    flags |= (SHO_R_QUEUE);
		    flags &= ~(SHO_R_STANDARD | SHO_R_MONSANTO);
		    break;
	        default:
		    fprintf (stderr, "Invalid option flag ");
		    fprintf (stderr, "specified.\n");
		    showhow();
		    exit (7);
		}
	    }
	}
	if (flags & SHO_R_QUEUE ) {
		if ( (flags & SHO_R_ALLUID) || (flags & SHO_R_ORIGIN) ||
			(flags & SHO_R_STANDARD) || (flags & SHO_R_HEADER) ||
			(whomuid != NULL) ) {
			fprintf(stderr, "Incompatable switch with -x.\n");
			exit(1);
		}
	}
	if (flags & SHO_R_COMPLEX ) {
		if ( (flags & SHO_R_ALLUID) || (flags & SHO_R_ORIGIN) ||
			(flags & SHO_R_STANDARD) || (flags & SHO_R_HEADER) ||
			(whomuid != NULL) || (flags & SHO_R_QUEUE) ) {
			fprintf(stderr, "Incompatable switch with -c.\n");
			exit(1);
		}
	}
	if ( (flags & SHO_R_BRIEF) && (flags & SHO_R_LONG) ) {
		fprintf(stderr, "Cannot have -b and -l on same ");
		fprintf(stderr, "command line.\n");
		exit(1);
	}
	if (flags & SHO_R_HEADER) {
		if (!(flags & SHO_R_MONSANTO) ) {
			fprintf(stderr, "-h switch cannot be used here.\n");
			exit(1);
		}
	}
	if ( (flags & SHO_R_ALLUID) && (whomuid != NULL) ) {
		fprintf(stderr, "Cannot use -a and -u switches together.\n");
		exit(1);
	}
	if (whomuid == NULL) whomuid = getuid();
						/* Assume asking about self */
	/*
	 *  For this preliminary version of the Qstat command, show all
	 *  requests in the queue, regardless of state.
	 */
	flags |= (SHO_RS_EXIT | SHO_RS_RUN | SHO_RS_STAGE |
		  SHO_RS_QUEUED | SHO_RS_WAIT | SHO_RS_HOLD | SHO_RS_ARRIVE);

        /*
         * If we just want short queue information, we just want the
         * destination.  If we want the long, give us all.  Medium gets just
         * some.
         */
        if ( flags & SHO_R_QUEUE) {
            flags &= ~(SHO_R_MONSANTO);
            if (flags & SHO_R_BRIEF) 
				;
            else if ( flags & SHO_R_LONG)
                flags |= (SHO_H_DEST | SHO_H_ACCESS | SHO_H_LIM | SHO_H_MAP |
                            SHO_H_RUNL | SHO_H_SERV | SHO_H_TIME );
            else flags |= (SHO_H_DEST);
        }
	exit_status = 0;			/* Assume success */
	if ( flags & SHO_R_COMPLEX) {
	    if ( *argv != NULL ) {
                while (*argv != NULL) {         /* Show info on a complex */
		    exit_status += showcomplex( queuefile, *argv, flags, whomuid, 
		        reqset_ptr, daepresent, qmapfile, pipeqfile, qcomplexfile);
                    argv++;
		}
            } else {
		exit_status += showcomplex( queuefile, NULL, flags, whomuid, 
			reqset_ptr, daepresent, qmapfile, pipeqfile, qcomplexfile);
	    }
	} else {   				/* Show info on a queue */
	    if (*argv != NULL) {
	        if (flags & SHO_R_DEST) {
		    fprintf(stderr, "Incompatable Qstat switches.\n");
		    exit(0);
	        }
	        while (*argv != NULL) {		/* Show info on a queue */
		    exit_status += shoqbyname (queuefile, *argv, flags, whomuid,
				    reqset_ptr, daepresent, qmapfile,
				    pipeqfile, qcomplexfile);
		    argv++;
	        }
	    } else {
		exit_status += shoallque (queuefile, flags, whomuid, reqset_ptr,
			   daepresent, qmapfile, pipeqfile, 0, qcomplexfile);
	    }
	}
	/*
	 *  Flush any output buffers and exit.
	 */
	fflush (stdout);
	fflush (stderr);
	if (exit_status) exit(1);
	exit (0);
}
static void sho_version()
{
     fprintf(stderr, "NQS version is %s\n", NQS_VERSION);
}
static void showhow()
{
    fprintf (stderr, "Command format is:\n\n");
    fprintf (stderr, "    qstat [-a] [-d] [-h] [-l] [-m] [-o] [-s] \n");
    fprintf (stderr, "          [-u username] [-v]");
    fprintf (stderr, " [ <queue-name(s)> ]\n\n");
    fprintf (stderr, "    qstat -x [-b] [-l] [ <queue-name(s)> ]\n\n ");
    fprintf (stderr, "    qstat -c [-b] [-l] [ <complex-name(s)> ]\n");
    exit (0);
}
