/*
 *	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	17-Jun-1992	Added header.
*	V01.4	JRR	22-Sep-1992	Write shutdown record to acct file.
*	V01.5	JRR	08-Mar-1993	Added Boeing enhancement for files.
*	V01.6	JRR	20-Jul-1993	Added support for auto-shutdown.
*	V01.7	JRR	01-Mar-1994	Added support for SOLARIS.
*/
/*++ nqs_ups.c - Network Queueing System
 *
 * $Source: /usr2/jrroma/nqs/nqs-3.35.6/src/RCS/nqs_ups.c,v $
 *
 * DESCRIPTION:
 *
 *	NQS shutdown state update module.
 *
 *
 *	Author:
 *	-------
 *	Brent A. Kingsbury, Sterling Software Incorporated.
 *	June 16, 1986.
 *
 *
 * STANDARDS VIOLATIONS:
 *   None.
 *
 * REVISION HISTORY: ($Revision: 1.7 $ $Date: 1994/03/30 20:36:59 $ $State: Exp $)
 * $Log: nqs_ups.c,v $
 * Revision 1.7  1994/03/30  20:36:59  jrroma
 * Version 3.35.6
 *
 * Revision 1.6  93/09/10  13:57:23  jrroma
 * Version 3.35
 * 
 * Revision 1.5  93/07/13  21:34:04  jrroma
 * Version 3.34
 * 
 * Revision 1.4  92/12/22  15:41:39  jrroma
 * Version 3.30
 * 
 * Revision 1.3  92/06/18  17:31:31  jrroma
 * Added gnu header
 * 
 * Revision 1.2  92/01/17  11:19:54  jrroma
 * Added support for RS6000.
 * 
 * Revision 1.1  92/01/17  11:19:18  jrroma
 * Initial revision
 * 
 *
 */

#include "nqs.h"
#include <signal.h>
#include <errno.h>
#include "nqsxvars.h"
#include "transactcc.h"		/* Transaction completion codes */
#include "nqsacct.h"		/* NQS accounting data structures */

/*** ups_shutdown
 *
 *
 *	long ups_shutdown():
 *
 *	Prepare to shutdown.
 *
 *	Non-Berkeley based UNIX implementations must disable group and
 *	others write-access on the named-pipe used to accept message
 *	packets from other processes.  The disabling of group and other
 *	write-access is critical for NQS to shutdown properly, rebuffing
 *	new message packets from client processes (see fstat() call in
 *	../lib/inter.c).
 *
 *	Berkeley UNIX based implementations release the advisory exclusive
 *	access lock on the Queuefile to accomplish the same thing.
 *
 *
 *	Returns:
 *		TCML_COMPLETE:	if successful;
 *		TCML_SHUTERROR:	if some error has prevented
 *				the shutdown sequence from
 *				being started.
 */
long ups_shutdown (pid, ruid, grace_period)
int pid;				/* Pid of requesting process.	*/
uid_t ruid;				/* Real UID of requesting process. */
int grace_period;			/* Number of seconds warning to */
					/* each running request. */
{
	register struct nqsqueue *queue;	/* Used to queue walking */
	struct nqsacct_shutdown  acct_shutdown;
        char *fifo_file;                /* Fully qualified file name */
        int fd_acct;

	if (Shutdown == 1) return (TCML_COMPLETE);
					/* Ignore multiple shutdown */
					/* requests.  */
	if (Shutdown == 2) Shutdown = 1;
	/*
	 *  Record who asked us to stop.
	 */
	printf ("I$Received shutdown request from process %1d.\n", pid);
	printf ("I$Process real user-id is: %1d.\n", ruid);
	fflush (stdout);
	/*
	 *  Broadcast SIGTERM to all NQS shepherd processes, and to the
	 *  NQS network daemon (if one is present).  It is CRITICAL that
	 *  all NQS shepherd processes be notified of the impending
	 *  shutdown PRIOR to aborting all queues (see the loops below).
	 *  Otherwise, the shepherd processes will not know if the
	 *  signal death of the request server process or shell is
	 *  because of an NQS shutdown.
	 */
	kill (-getpid(), SIGTERM);	/* Signal process-group */
#if	HPUX | SGI | SOLARIS | SYS52 | IBMRS | ULTRIX | DECOSF | LINUX
	/*
	 *  Turn off ALL write permissions to the NQS pipe "mailbox" so
	 *  that other processes can tell that the NQS daemon is shutting
	 *  down.
	 */
        fifo_file = getfilnam (Nqs_ffifo, SPOOLDIR);
        if (fifo_file == (char *)NULL) {
                printf ("E$Shutdown request error.\n");
                printf ("I$Unable to determine name of FIFO file.\n");
                fflush (stdout);
                relfilnam (fifo_file);
                return (TCML_SHUTERROR);        /* Shutdown error */
        }
	if (chmod (fifo_file, 00600) == -1) {
		/*
		 *  We were unable to change the mode of the NQS
		 *  daemon's request pipe!
		 */
		printf ("E$Shutdown request error.\n");
		printf ("I$Unable to chmod() on the NQS request FIFO.\n");
		printf ("I$File=%s.\n", fifo_file);
		printf ("I$%s.\n", asciierrno());
		fflush (stdout);
		return (TCML_SHUTERROR);	/* Shutdown error */
	}
        relfilnam (fifo_file);
#else
#if	BSD43
#else
BAD SYSTEM TYPE
#endif
#endif

#if	BSD43 | ULTRIX | DECOSF
	/*
	 *  Release the advisory exclusive access lock on the Queuefile,
	 *  so that other NQS client processes can tell that NQS is shutdown,
	 *  or is in the process of doing so.
	 *
	 *  The advisory exclusive access lock on the Qmapfile however,
	 *  must be retained until the bloody end (see ../src/nqs_boot.c).
	 */
	flock (Queuefile->fd, LOCK_UN);	/* Release advisory exclusive lock */
#else
#if	HPUX | SGI | SOLARIS | SYS52 | IBMRS | LINUX
#else
BAD SYSTEM TYPE
#endif
#endif
	close (Write_fifo);		/* Close the file descriptor we had */
					/* open to prevent exiting when no  */
					/* req. activity was taking place.  */
					/* We do blocking reads for requests*/
					/* until ALL other processes close  */
					/* their write-descriptors on the   */
					/* mailbox request pipe.	    */
	/*
	 *  For each queue, perform the equivalent of an ABort Queue command,
	 *  with the exception that requests are to be requeued.
	 */
	Shutdown = 1;			/* Signal that no more reqs are to */
					/* be spawned.  We are shutting down*/
	queue = Nonnet_queueset;	/* Walk the non-network queues */
	while (queue != (struct nqsqueue *) 0) {
		nqs_aboque (queue, grace_period, 1);	/* Requeue req if */
		queue = queue->next;			/* possible */
	}
	queue = Net_queueset;		/* Walk the network queues */
	while (queue != (struct nqsqueue *) 0) {
		nqs_aboque (queue, grace_period, 1);	/* Requeue req if */
		queue = queue->next;			/* possible */
	}
        /*
         * Write out the shutdown record to nqs accounting file.
         */
        fd_acct = open(NQSACCT_FILE,
                        O_WRONLY|O_APPEND|O_CREAT, 0644);
        if (fd_acct < 0) {
            printf ("E$Error opening NQS account");
            printf(" file;  Errno = %d\n", errno);
            fflush (stdout);
        } else {
            bytezero((char *)&acct_shutdown, sizeof(acct_shutdown));
            acct_shutdown.h.type = NQSACCT_SHUTDOWN;
            acct_shutdown.h.length = sizeof(acct_shutdown);
            acct_shutdown.h.jobid = 0;
            acct_shutdown.down_time = time ((time_t *)0);
            write(fd_acct, (char *)&acct_shutdown, sizeof(acct_shutdown));
	    close (fd_acct);
        }

	return (TCML_COMPLETE);		/* Return successful completion */
}
