/*
 *	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.2   JRR     03-Mar-1992	Fixed to work here at Monsanto.
*       V01.3   JRR     05-Mar-1992	Fix up to error messages.
*	V01.4	JRR	26-May-1992	Added IBM conditionals.
*	V01.5	JRR	17-Jun-1992	Added header.
*	V01.6	JRR	06-Nov-1992	Added support for HPUX.
*	V01.7	JRR	07-Dec-1992	Modified for C prototpyes.
*	V01.8	JRR	06-Apr-1993	Added support for DECOSF.
*/

#include "nqs.h"
#include <pwd.h>
#include "nqsdirs.h"			/* NQS files and directories */

#ifndef __CEXTRACT__
#if __STDC__

static set_sflag ( char * optarg );

#else /* __STDC__ */

static set_sflag (/* char * optarg */);

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



#define DSP_ERR1	"-g, -u, -U, -A are mutually exclusive"
#define DSP_ERR2	" or one has been used previously in the command."
#define DSP_ERR3	"multiple uses of "
#define DSP_ERR4	"\tadministrator option '-U -u -A -G' was"
#define DSP_ERR5	"requested by an invalid NQS manager"


/*
 *	Global variables:
 */
char *Qstat_prefix = "Qstat";
int scpflag = 0;

/*** main_dsp
 *
 * set up everything for the displays
 * open needed databases, set up special
 * needs, etc.
 */
main_dsp (
	int 	argc,
	char 	*argv[],
	long	flags,
	char 	* selector,
	char	* tname,
	char	* hname)
{
	extern char	*optarg;
	extern int 	optind;

	struct confd *queuefile;	/* Queue description file */
	struct confd *qcomplexfile;	/* Queue complex definition file */
	struct confd *qmapfile;		/* Qmap description file */
	struct confd *pipeqfile;	/* Pipeqfile description file */
	char *argument;
	short daepresent;		/* Boolean non-zero if the local */
					/* NQS daemon is present and running */
	char whom[10];			/* Whom we are interested in */
	struct passwd *whompw;		/* Password entry of "whom" */
	uid_t whomuid;			/* Uid of whom we are interested in */
	Mid_t	itsmid;
	int	i;

	/* step 1. change to root directory */
	if (chdir (Nqs_root) == -1) {
		fprintf (stderr, "%s(FATAL): Unable to chdir() to the NQS ",
			 Qstat_prefix);
		fprintf (stderr, "root directory: %s\n", Nqs_root);
		return (-1);
	}

	/* step 2. opend queue, complex, map, and pipeto databases */
	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");
		return (-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 (2);
        }
        if ((qmapfile = opendb (Nqs_qmaps, O_RDONLY)) == NULL) {
                fprintf (stderr, "%s(FATAL): Unable to open the NQS queue ",
                         Qstat_prefix);
                fprintf (stderr, "complex definition database file.\n");
                exit (2);
        }
        if ((pipeqfile = opendb (Nqs_pipeto, O_RDONLY)) == NULL) {
                fprintf (stderr, "%s(FATAL): Unable to open the NQS queue ",
                         Qstat_prefix);
                fprintf (stderr, "complex definition database file.\n");
                exit (2);
        }



	/* get user id */
	whomuid = getuid();		/* Assume asking about self */
	whompw=getpwuid(whomuid);
	strcpy(whom,whompw->pw_name);
	strcat(whom,"\0");
	closepwdb();		/* Close the password file */

	/* step 7.  Now, buffer stdout for speed.  */
	bufstdout();


	/* step 8. move to correct arg */
	for(i=0; i<argc; i++)
		argv++;

	/* step 9. if HOST then send to information to host */
	if (hname != NULL) {
		if (get_host_id(  hname, &itsmid) != SUCCESS) {
			printf("host not available. \n");
			exit (0);
		}
		do {
			call_host(whomuid, flags, itsmid, *argv);
			if (*argv != NULL)
				argv++;
		} while (*argv != NULL);
		return(0);
	}


	/* step 10. if requested adminstrator flag validate adminstrator 
	 *	if not requeusting adminstrator option then set
	 *	ourself as the selector for requests to be seen
	 */
	if (selector != NULL) {
		/* #### localmid takes way to long fix!!!! ####
		*if (localmid (&Local_mid) != 0) {
		*	printf("Unable to get machine-id of local host \n");
		*	exit(2);
		*}
		*/
		if (nqspriv(whomuid,0,0) == 0) {
			printf("%s %s \n",DSP_ERR4, DSP_ERR5);
			return(-2);
		}
	}
	else
		selector = whom;



	/* step 11. print requests */
	do {
		list(queuefile, qcomplexfile, *argv, flags, selector,qmapfile,
			pipeqfile);
		if (*argv != NULL)
			argv++;
	} while (*argv != NULL);


	/* step 12.  Flush any output buffers and exit.  */
	fflush (stdout);
	fflush (stderr);
	closedb(qcomplexfile);
	closedb(queuefile);
	closedb(qmapfile);
	closedb(pipeqfile);
	return (0);
}



/*** set_sflag
 *
 * show specific queues that are in specific state
 */
static set_sflag(char *optarg)
{
	int i;
	long flags;

	for (i=0; (*optarg != NULL); i++, optarg++) {
		switch(*optarg) {
		case 'h':
			flags |= SHO_RS_HOLD;
			break;
		case 'r':
			flags |= SHO_RS_RUN;
			break;
		case 'q':
			flags |= SHO_RS_QUEUED;
			break;
		case 't':
			flags |= SHO_RS_EXIT;
			break;
		default:
			printf("error \n");
		}	/* end switch */
	}		/* end for    */
	return(flags);
}


/***parse_args
 *
 * parse args for commands
 */
long 
parse_args(
  	int  *argc,
  	char *argv[],
  	char * string,
  	char ** selector,
  	char ** tname,
  	char ** hname)
{
	extern 		char	*optarg;
	extern 		int 	optind;
	register	int	c;
	register	int	i;
	register	long	flags=0;
	register	int	state=0;

	while ((c=getopt(*argc, argv, string)) !=-1) {
		switch (c) {
		case 'b':		/* batch q */
			flags |= SHO_BATCH;
			break;
		case 'p':		/* pipe q */
			flags |= SHO_PIPE;
			break;
		case 'd':		/* device q */
			flags |= SHO_DEVICE;
			break;
		case 'f':		/* full display */
		case 'l':		/* long display */
			flags |= SHO_FULL;
			break;
		case 'L':		/* rescources */
			flags |= SHO_LIMITS;
			break;
		case 'n':		/* no header/trailer */
			flags |= SHO_NOHDR;
			break;
		case 'x':		/* extended by vendor */
			flags |= SHO_EXTEND;
			break;
		case 'h':		/* extended by vendor */
			if (flags & SHO_HOST){
				printf(" %s -h \n",DSP_ERR3);
				exit(2);
			}
			flags |= SHO_HOST;
			*hname = optarg;
			break;
		case 's':		/* extended by vendor */
			state++;
			flags |= set_sflag(optarg);
			break;
		case 'T':		/*target uname in conjunction w/ host*/
			if (flags & SHO_TARGET){
				printf(" %s -T \n",DSP_ERR3);
				exit(2);
			}
			flags |= SHO_TARGET;
			*tname = optarg;
			break;
		case 'A':		/* account list */
			if ((flags & SHO_GROUP) || (flags & SHO_ACCT)
			|| (flags & SHO_USER) || (flags & SHO_R_ALLUID)) {
				printf(" %s \n", DSP_ERR1);
				printf(" %s \n", DSP_ERR2);
				exit(2);
			}
			flags |= SHO_ACCT;
			*selector = optarg;
			break;
		case 'g':		/* group list */
			if ((flags & SHO_GROUP) || (flags & SHO_ACCT)
			|| (flags & SHO_USER) || (flags & SHO_R_ALLUID)) {
				printf(" %s \n", DSP_ERR1);
				printf(" %s \n", DSP_ERR2);
				exit(2);
			}
			flags |= SHO_GROUP;
			*selector = optarg;
			break;
		case 'u':		/* user list */
			if ((flags & SHO_GROUP) || (flags & SHO_ACCT)
			|| (flags & SHO_USER) || (flags & SHO_R_ALLUID)) {
				printf(" %s \n", DSP_ERR1);
				printf(" %s \n", DSP_ERR2);
				exit(2);
			}
			flags |= SHO_USER;
			*selector = optarg;
			break;
		case 'a':		/* show all */
		case 'U':		/* Unrestricted display */
			if ((flags & SHO_GROUP) || (flags & SHO_ACCT)
			|| (flags & SHO_USER)) {
				printf(" %s \n", DSP_ERR1);
				printf(" %s \n", DSP_ERR2);
				exit(2);
			}
			flags |= SHO_R_ALLUID;
			break;
		case 'Q':		/* queue list */
			flags |= SHO_QUE;
			flags |= SHO_BATCH;
			break;
		case '?':
			fprintf (stderr, "Invalid option flag ");
			fprintf (stderr, "specified.\n");
			fprintf (stderr, "Command format is:\n\n");
			fprintf (stderr, "    %s %s",argv[0],string);
			fprintf (stderr, "[ <list-name(s)> ]\n\n");
			exit (7);
		}
	}

	/* step 5. move argv up to where we stopped parsing */
	*argc=optind;

	/* if no specific type is mentioned then show all types */

	/* Well, on second thought, the default case will be to show */
	/* requests, and that will be taken care of by qstat.c. TS   */
        /*
	 * if ( (! (flags & SHO_BATCH)) && (! (flags & SHO_PIPE)) && 
	 *      (! (flags & SHO_DEVICE)) )
	 * {
	 *      flags |= ( SHO_BATCH | SHO_PIPE | SHO_DEVICE );
	 * }
	 */

	/* step 6. no special state so show all */
	if (state == 0)
		flags |= (SHO_RS_RUN | SHO_RS_EXIT | SHO_RS_HOLD |
			  SHO_RS_QUEUED);

	return(flags);
}
