/*
 *	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     02-Mar-1992	Added Cosmic V2 changes.
*       V01.3   JRR     09-Apr-1992     Added CERN enhancements.
*	V01.4	JRR	17-Jun-1992	Added header.
*	V01.5	JRR	19-Nov-1992	Modified for C prototypes.
*	V01.6	JRR	01-Mar-1994	Added support for SOLARIS.
*/
/*++ nqs_upp.c - Network Queueing System
 *
 * $Source: /usr2/jrroma/nqs/nqs-3.35.6/src/RCS/nqs_upp.c,v $
 *
 * DESCRIPTION:
 *
 *	NQS general parameters state update module.
 *
 *
 *	Author:
 *	-------
 *	Brent A. Kingsbury, Sterling Software Incorporated.
 *	June 16, 1986.
 *
 *
 * STANDARDS VIOLATIONS:
 *   None.
 *
 * REVISION HISTORY: ($Revision: 1.6 $ $Date: 1994/03/30 20:36:56 $ $State: Exp $)
 * $Log: nqs_upp.c,v $
 * Revision 1.6  1994/03/30  20:36:56  jrroma
 * Version 3.35.6
 *
 * Revision 1.5  92/12/22  15:41:37  jrroma
 * Version 3.30
 * 
 * Revision 1.4  92/06/18  17:31:29  jrroma
 * Added gnu header
 * 
 * Revision 1.3  92/05/06  10:44:26  jrroma
 * 
 *  Version 3.20
 * 
 * Revision 1.2  92/03/02  16:26:45  jrroma
 * Added Cosmic V2 changes.
 * 
 * Revision 1.1  92/03/02  16:24:45  jrroma
 * Initial revision
 * 
 *
 */

#include <signal.h>
#include <errno.h>
#include <string.h>
#include "nqs.h"
#include "nqsxvars.h"
#include "transactcc.h"		/* Transaction completion codes */


#ifndef __CEXTRACT__
#if __STDC__

static void upp_brokenpipe ( void );

#else /* __STDC__ */

static void upp_brokenpipe (/* void */);

#endif /* __STDC__ */
#endif /* __CEXTRACT__ */
/*** upp_setdefbatque
 *
 *
 *	long upp_setdefbatque():
 *	Set the default batch-request queue.
 *
 *	Returns:
 *		TCML_COMPLETE:	if successful;
 *		TCML_NOSUCHQUE:	if the named queue does not exist.
 */
long upp_setdefbatque (defbatque)
char *defbatque;		/* Name of the new default batch-req queue */
{
	register struct nqsqueue *queue;

	if (defbatque [0] != '\0') {		/* Setting a default */
		queue = nqs_fndnnq (defbatque);
		if (queue == (struct nqsqueue *)0) {
			return (TCML_NOSUCHQUE);/* No such queue */
		}
	}
	strcpy (Defbatque, defbatque);		/* Save new batch queue name */
	udb_genparams();			/* Update NQS database */
	return (TCML_COMPLETE);			/* Success */
}


/*** upp_setdefprifor
 *
 *
 *	long upp_setdefprifor():
 *	Set the default print-forms value.
 *
 *	Returns:
 *		TCML_COMPLETE:	 if successful;
 *		TCML_NOSUCHFORM: if the named form is not defined in the
 *				 local NQS forms set.
 */
long upp_setdefprifor (defprifor)
char *defprifor;			/* Name of default print-forms */
{
	if (defprifor [0] != '\0') {	/* Setting a default */
		if (!upf_valfor (defprifor)) {
			return (TCML_NOSUCHFORM);	/* No such form */
		}
	}
	strcpy (Defprifor, defprifor);	/* Save default print-form */
	udb_genparams();		/* Update NQS database */
	return (TCML_COMPLETE);		/* Success */
}


/*** upp_setdefprique
 *
 *
 *	long upp_setdefprique():
 *	Set the default print-request queue.
 *
 *	Returns:
 *		TCML_COMPLETE:	if successful;
 *		TCML_NOSUCHQUE:	if the named queue does not exist.
 */
long upp_setdefprique (defprique)
char *defprique;		/* Name of the new default print-req queue */
{
	register struct nqsqueue *queue;

	if (defprique [0] != '\0') {	/* Setting a default */
		queue = nqs_fndnnq (defprique);
		if (queue == (struct nqsqueue *)0) {
			return (TCML_NOSUCHQUE);	/* No such queue */
		}
	}
	strcpy (Defprique, defprique);	/* Save new print-queue name */
	udb_genparams();		/* Update NQS database */
	return (TCML_COMPLETE);		/* Success */
}


/*** upp_setlogfil
 *
 *
 *	long upp_setlogfil():
 *
 *	Switch error and message logging to a new logfile.
 *	If the new logfile cannot be opened for writing, then
 *	do not switch!
 *
 *	A message is left on the old logfile if the switch is
 *	successful (or unsuccessful).
 *
 *	Returns:
 *		TCML_COMPLETE:	if successful;
 *		TCML_LOGFILERR:	if unsuccessful.
 */
long upp_setlogfil (newlogname)
register char *newlogname;		/* Name of new logfile. */
{
	void (*sigpipe_sav)();		/* Save old SIGPIPE handler */
	char buffer [1];		/* Status buffer */

	sigpipe_sav = signal (SIGPIPE, upp_brokenpipe);
					/* Save caller's SIGPIPE handler */
					/* and instate our own */
	errno = 0;			/* Clear system call error */
	/*
	 * If we make SURE that "$$" comes immediately after a new line,
	 * then we can safely do a blocking read on the pipe, for
	 * the log daemon is sure to write something to us.
	 */
	printf ("\n$$%s\n", newlogname);
	fflush (stdout);
        if (errno && errno != ENOTTY && errno != 45) {
		signal (SIGPIPE, sigpipe_sav); /* Restore SIGPIPE handler */
		return (TCML_LOGFILERR);
	}
	/*
	 *  Successful write to the NQS log process.
	 */
	if (read (Fromlog, buffer, 1) != 1) {	/* Blocking read on pipe */
		/*
		 *  Status readback from log process failed.
		 */
		signal (SIGPIPE, sigpipe_sav); /* Restore SIGPIPE handler */
		return (TCML_LOGFILERR);
	}
	signal (SIGPIPE, sigpipe_sav);	/* Restore SIGPIPE handler */
	if (buffer [0]) {
		/*
		 *  Success!  The new logfile has been opened.
		 */
		strcpy (Logfilename, newlogname);
					/* Remember new logfile name */
		udb_setlogfil();	/* Update log file name in */
					/* NQS database */
		return (TCML_COMPLETE);
	}
	return (TCML_LOGFILERR);	/* Failure */
}


/*** upp_brokenpipe
 *
 *
 *	void upp_brokenpipe ():
 *
 *	This function serves as the signal catcher for SIGPIPE signals
 *	sent in case the NQS log process is not running anymore.
 *
 *	This function sets errno = EPIPE
 */
static void upp_brokenpipe ()
{
	signal (SIGPIPE, upp_brokenpipe);
	errno = EPIPE;
}

/*** upp_setgblrunlim
 *
 *
 *	int upp_setgblrunlim():
 *
 *	Set the global run limit for all requests.  This may require us to
 *	allocate memory for a bigger Runvars structure.
 *
 *	Returns:
 *		 0:	if successful.
 *		-1:	if unable to allocate memory for the Runvars structure.
 */
int upp_setgblrunlim ()
{
	int i;
	int newgblrunlimit;
	struct running *runvars;

	newgblrunlimit = Maxgblbatlimit + Maxgblpiplimit + Maxgblnetlimit
		 /* + Maxnoofdevices */;
	if (newgblrunlimit > Runvars_size) {
		if (Runvars_size == 0) {
			/*
			 *  Create Runvars structure for the first time.
			 */
			Runvars = (struct running *) malloc (newgblrunlimit *
				sizeof (struct running));
			if (Runvars ==  (struct running *) 0) {
				printf ("E$upp_setgblrunlim(): Can't malloc Runvars\n");
				return (-1);
			}
		} else {
			/*
			 *  Increase the number of entries in the existing
			 *  Runvars structure.
			 */
			runvars = (struct running *) realloc ((char *) Runvars,
				newgblrunlimit * sizeof (struct running));
			if (runvars ==  (struct running *) 0) {
				/*
				 *  We're assuming that realloc won't damage
				 *  the original Runvars structure.
				 */
				printf ("E$upp_setgblrunlim(): Can't realloc Runvars\n");
				return (-1);
			}
			Runvars = runvars;
		}
		/*
		 *  Clear the allocated flag in all of the newly created
		 *  Runvars entries.
		 */
		for (i = Runvars_size; i < newgblrunlimit; i++)
			(Runvars + i)->allocated = 0;
		Runvars_size = newgblrunlimit;
	}
	Maxgblrunlimit = newgblrunlimit;
	return (0);
}


/*** upp_setgblbatlim
 *
 *
 *	long upp_setgblbatlim():
 *
 *	Set the global runlimit for batch requests.
 *
 *	Returns:
 *		TCML_COMPLETE:	if successful.
 *		TCML_NOMOREMEM:	if unable to allocate more memory for the
 *				Runvars structure.
 */
long upp_setgblbatlim (limit)
long limit;
{
	long prevlim;	 		/* Previous batch request runlimit */

	/*
	 *  Set the new global batch run limit which in turn affects the global
	 *  run limit, so set it too.  Call the spawning routine to possibly
	 *  spawn new batch requests if the limit has increased.
	 */
	prevlim = Maxgblbatlimit;
	Maxgblbatlimit = limit;
	if (upp_setgblrunlim () == -1) {
		/*
		 *  We were unable to set the global run limit due to an
		 *  inability to allocate more memory for the Runvars structure,
		 *  so we'll put the global batch limit back the way it was.
		 */
		Maxgblbatlimit = prevlim;
		return (TCML_NOMOREMEM);
	}
	if (Booted) {
		udb_genparams ();
	}
	if (limit > prevlim) {
		bsc_spawn ();
	}
	return (TCML_COMPLETE);		/* Successful completion */
}


/*** upp_setgblpiplim
 *
 *
 *	long upp_setgblpiplim():
 *
 *	Set the global route limit for pipe requests.
 *
 *	Returns:
 *		TCML_COMPLETE:	if successful.
 *		TCML_NOMOREMEM:	if unable to allocate more memory for the
 *				Runvars structure.
 */
long upp_setgblpiplim (limit)
long limit;
{
	long prevlim;			/* Previous pipe request route limit */

	/*
	 *  Set the new global pipe route limit which in turn affects the global
	 *  run limit, so set it too.  Call the spawning routine to possibly
	 *  spawn new pipe requests if the limit has increased.
	 */
	prevlim = Maxgblpiplimit;
	Maxgblpiplimit = limit;
	if (upp_setgblrunlim () == -1) {
		/*
		 *  We were unable to set the global run limit due to an
		 *  inability to allocate more memory for the Runvars structure,
		 *  so we'll put the global pipe limit back the way it was.
		 */
		Maxgblpiplimit = prevlim;
		return (TCML_NOMOREMEM);
	}
	if (Booted) {
		udb_genparams ();
	}
	if (limit > prevlim) {
		psc_spawn ();
	}
	return (TCML_COMPLETE);		/* Successful completion */
}


