/*
 *	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.3   JRR     28-Feb-1992	Added Cosmic V2 changes.
*	V01.4	JRR	17-Jun-1992	Added header.
*	V01.5	JRR	03-Sep-1992	Return if remote server complains.
*	V01.6	JRR	14-Apr-1993	Return 1 if queue not exist,  0 O/W.
*	V01.7	JRR	18-Aug-1993	Miniscule change to includes.
*	V01.8	JRR	05-Aug-1994	Add fflush per Bruno Wolff.
*/
/*++ shoqbyname.c - Network Queueing System
 *
 * $Source: /usr2/jrroma/nqs/nqs-3.36/lib/RCS/shoqbyname.c,v $
 *
 * DESCRIPTION:
 *
 *	Print on stdout information about a queue.
 *
 *	Author:
 *	-------
 *	Robert W. Sandstrom, Sterling Software Incorporated.
 *	December 18, 1985.
 *
 *
 * STANDARDS VIOLATIONS:
 *   None.
 *
 * REVISION HISTORY: ($Revision: 1.8 $ $Date: 1994/09/02 17:37:59 $ $State: Exp $)
 * $Log: shoqbyname.c,v $
 * Revision 1.8  1994/09/02  17:37:59  jrroma
 * Version 3.36
 *
 * Revision 1.7  1993/09/10  13:55:25  jrroma
 * Version 3.35
 *
 * Revision 1.6  93/07/13  21:31:38  jrroma
 * Version 3.34
 * 
 * Revision 1.5  92/12/22  15:46:33  jrroma
 * Version 3.30
 * 
 * Revision 1.4  92/06/18  13:24:51  jrroma
 * Added gnu header
 * 
 * Revision 1.3  92/02/28  15:33:00  jrroma
 * Added Cosmic V2 changes.
 * 
 * Revision 1.2  92/01/16  17:20:41  jrroma
 * Added support for RS6000.
 * 
 * Revision 1.1  92/01/16  17:19:49  jrroma
 * Initial revision
 * 
 *
 */

#include "nqs.h"			/* NQS types and definitions */
#include "netpacket.h"			/* NQS networking */

/*** shoqbyname
 *
 *
 *	int shoqbyname():
 *
 *	Print on stdout information about the named queue.
 *	Returns: 0 if output was produced.
 *		 1 if no output was produced.
 */
int shoqbyname (queuefile, fullname, flags, whomuid, reqs, dae_present,
		qmapfile, pipeqfile, qcomplexfile)
struct confd *queuefile;		/* NQS queue file */
char *fullname;				/* Name with possible '@' */
long flags;				/* SHO_??? */
uid_t whomuid;				/* Whom we are interested in */
struct reqset *reqs;			/* Looking for these requests only */
short dae_present;			/* NQS local daemon is present */
struct confd *qmapfile;			/* NQS queue/device/destination */
					/* mappings file */
struct confd *pipeqfile;		/* NQS pipe queue destinations file */
struct confd *qcomplexfile;             /* NQS queue complex definition file */
{
	uid_t myuid;			/* Local user-id */
	char myname [MAX_ACCOUNTNAME+1];/* Local account name */
	struct gendescr *descr;		/* Pointer to general descriptor */
	int found;			/* Boolean */
	Mid_t itsmid;			/* The machine id of the queue */
	Mid_t mymid;			/* The local machine id */
	char *localname;		/* The queue name without "@host" */
	struct passwd *passwd;		/* Password file entry */
	int sd;				/* Socket descriptor */
	int extrach;			/* Number of chs already read */
	short output;			/* Boolean */
	int timeout;			/* Timeout in between tries */
	long transactcc;		/* Transaction completion code */

	switch (machspec (fullname, &itsmid)) {
		case 0:
			break;
		case -1:
		case -2:
			fprintf (stderr, "Invalid hostname specification ");
			fprintf (stderr, "for queue %s.\n", fullname);
			return (1);
		case -3:
		case -4:
			fprintf (stderr, "Unexpected error in machspec(), ");
			fprintf (stderr, "queue = %s.\n", fullname);
			return (1);
	}
	if (localmid (&mymid) != 0) {
		fprintf (stderr, "Unexpected error in localmid().\n");
		return (0);
	}
	localname = destqueue (fullname);
	if (itsmid == mymid) {
		if (fullname[0] == '@') {
		    shoallque (queuefile,  flags, whomuid, reqs, dae_present, 
			    qmapfile, pipeqfile, 0, qcomplexfile);
		    return (0);
		}
		found = 0;
		if (telldb (queuefile) != -1) {
			/*
			 *  We are not necessarily at the start of the
			 *  database file....
			 */
			seekdb (queuefile, 0L);	/* Seek to the beginning */
		}
		descr = nextdb (queuefile);
		while (descr != NULL && !found) {
			if (strcmp (descr->v.que.namev.name, localname) == 0) {
				found = 1;
			}
			else descr = nextdb (queuefile);
		}
		if (found) {
			return (shoqbydesc (queuefile, descr, flags, whomuid,
					    reqs, dae_present, qmapfile,
					    pipeqfile, qcomplexfile));
		}
		else {
			fprintf (stderr, "Queue: %s does not exist.\n",
				 fullname);
			return (1);
		}
	}
	else {
		myuid = getuid();
		if ((passwd = fetchpwuid (myuid)) == (struct passwd *) 0) {
			fprintf (stderr, "Who are you?\n");
			return (1);
		}
		strncpy (myname, passwd->pw_name, MAX_ACCOUNTNAME+1);
					/* Save account name */
		if ((passwd = fetchpwuid (whomuid)) == (struct passwd *) 0) {
			fprintf (stderr, "Who is user %d?\n", whomuid);
			return (1);
		}
		interclear ();
		/* flags &= ~SHO_R_ALLUID; */			/* jrr	*/
		interw32i (flags);	/* SHO_??? */
		interwstr (localname);	/* Queue name without @machine */
		/*
		 *  This implementation of shoqbyname() uses "whomuid" to
		 *  determine, for local queues, whose requests should be
		 *  highlighted.  We presume that the remote implementation
		 *  does the same.  However, we do not assume that nmap is
		 *  used to come up with the remote whomuid.  Pass both the
		 *  client's whomuid and the client's "whom-username".
		 *  This lets the netserver decide how to come up with
		 *  whomuid on the server machine.
		 */
		interw32i (whomuid);
		interwstr (passwd->pw_name);
		sd = establish (NPK_QSTAT, itsmid, myuid, myname,
				&transactcc);
		/*
		 *  Establish has just told the network server
		 *  on the remote machine what it is that we want.
		 */
		if (sd < 0) {
			if (sd == -2) {
				/*
				 * Retry is in order.
				 */
				timeout = 1;
				do {
					nqssleep (timeout);
					interclear ();
					interw32i (flags);
					interwstr (localname);
					interw32i (whomuid);
					interwstr (passwd->pw_name);
					sd = establish (NPK_QSTAT, itsmid,
							myuid, myname,
							&transactcc);
					timeout *= 2;
				} while (sd == -2 && timeout <= 16);
				/*
				 *  Beyond this point, give up on retry.
				 */
				if (sd < 0) {
					analyzetcm (transactcc, stderr, "");
					return(1);
				}
			}
			else {
				/*
				 *  Retry would surely fail.
				 */
				analyzetcm (transactcc, stderr, "");
				return(1);
			}
		}
		/*
		 *  The server liked us.
		 */
		output = 1;
		/*
		 *  First, display any characters that
		 *  were already read inside establish().
		 */
		if (extrach = extrasockch ()) {
			output = 0;
			fflush (stdout);
			write (STDOUT, bufsockch (), extrach);
		}
		/*
		 *  Then display any characters that the server
		 *  may still want to send us.
		 */
		fflush (stdout);
		if (filecopyentire (sd, STDOUT)) return (0);
		else return (output);
	}
}
