/*
 *	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.00	JRR	20-Mar-1992	Initial version from delreq.
*	V01.1	JRR	17-Jun-1992	Added header.
*	V01.2	JRR	06-Nov-1992	Modified for C prototypes.
*	V01.3	JRR	18-Aug-1993	Miniscule change for includes.
*			01-Sep-1993	Fix for Mids as unsigned ints.
*	V01.4	JRR			Placeholder.
*	V01.5	JRR	03-Mar-1994	Fixed up NMAP.
*/
/*++ delreq.c - Network Queueing System
 *
 *
 * DESCRIPTION:
 *
 *	Delete a queued NQS request, or signal a running NQS request.
 *
 *
 *	Author:
 *	-------
 *	John Roman, Monsanto Company.
 *	March 20, 1992.
 *
 *
 * STANDARDS VIOLATIONS:
 *   None.
 *
 */

#include "nqs.h"
#include "nqspacket.h"			/* NQS local message packets */
#include "netpacket.h"			/* NQS remote message packets */
#include "nmap.h"			/* Mid_t (all OS's) */
					/* Uid_t and gid_t (if not BSD43) */
#include "transactcc.h"

extern Mid_t Locmid;			/* mid of local machine */

/*** suspendreq
 *
 *
 *	long suspendreq():
 *	Suspend a running NQS request or resume a suspended NQS request.
 *
 *	Returns:
 *		TCML_INTERNERR:	 if maximum packet size exceeded.
 *		TCML_NOESTABLSH: if unable to establish inter-
 *				 process communication.
 *		TCML_NOLOCALDAE: if the NQS daemon is not running.
 *		TCML_NOSUCHREQ:	 if the specified request does not
 *				 exist.
 *		TCML_NOSUCHSIG:	 if the request was running or in
 *				 transit, and the specified signal
 *				 to send is not recognized by
 *				 the execution machine.
 *		TCML_NOTREQOWN:	 if the specified request is not
 *				 owned by the client.
 *		TCML_PROTOFAIL:	 if a protocol failure occurred.
 *		TCML_REQRESUMED: if the request was successfully resumed.
 *		TCML_REQSUSPENDED: 
 *				 if the request was sucessfully suspended.
 *		TCML_REQWASRUNNING: 
 *				 if requested to resume a job already running.
 *		TCML_REQWASSUSPENDED: 
 *				 if requested to resume a job already running.
 *
 *    The TCMP forms  of the errors are possible as well.    
 */
long suspendreq ( 
	uid_t mapped_uid,	/* Mapped owner user-id */
	long orig_seqno,	/* Original sequence# */
	Mid_t orig_mid,		/* Original machine-id of req */
	Mid_t target_mid,	/* Target machine-id of req */
	int privs,		/* Privs of the user */
	int action)		/* True if suspend, false if resume */
{

	/*
	 * If the orig_seqno is 0, then we want to suspend all jobs on
	 * the appropriate machine.
	 */
        struct passwd *whompw;          /* Whose request it is */
        int sd;                         /* Socket descriptor */
        short timeout;                  /* Seconds between tries */
        long transactcc;                /* Holds establish() return value */

	interclear();
        interw32i ((long) mapped_uid);  /* Client uid */
	if (target_mid == (Mid_t) 0 || target_mid == Locmid) {
	    interw32i ((long) orig_seqno);
	    interw32u ((Mid_t) orig_mid);
	    interw32u ((Mid_t) target_mid);
	    interw32i ((long) privs);
	    interw32i ((long) action);
	    return (inter (PKT_SUSPENDREQ));
	}

	whompw = fetchpwuid(mapped_uid);/* Get the passwd structure */
        interwstr (whompw->pw_name);    /* Client username */
        interw32i (orig_seqno);  	/* Original sequence number */
        interw32u ((Mid_t) orig_mid);  	/* Original machine id */
        interw32i ((long) privs);       /* Signal */
        interw32i ((long) action); 	/* Request queueing state */

        sd = establish (NPK_SUSPENDREQ, target_mid, mapped_uid, 
			whompw->pw_name, &transactcc);
        if (sd == -2) {
            /*
             * Retry is in order.
             */
		printf("Retrying...\n");
            timeout = 1;
            do {
                nqssleep (timeout);
                interclear ();
                interw32i ((long) mapped_uid);
                interwstr (whompw->pw_name);
                interw32i (orig_seqno);
                interw32u ((Mid_t) orig_mid);
                interw32i ((long) privs);
                interw32i ((long) action);
                sd = establish (NPK_SUSPENDREQ, target_mid,
                        mapped_uid, whompw->pw_name, &transactcc);
                timeout *= 2;
            } while (sd == -2 && timeout <= 16);
        }
        return (transactcc);
}

/*** diagqsuspend
 *
 *
 *      diagqsuspend():
 *      Diagnose suspendreq() completion code.
 */
int diagqsuspend (long code, char *reqid)
{
        switch (code) {
        case TCML_INTERNERR:
                printf ("Internal error.\n");
                exiting();              /* Delete communication file */
                exit (-1);
        case TCML_NOESTABLSH:
                printf ("Unable to establish inter-process communications ");
                printf ("with NQS daemon.\n");
                printf ("Seek staff support.\n");
                exiting();              /* Delete communication file */
                exit (-1);
        case TCML_NOLOCALDAE:
                printf ("The NQS daemon is not running.\n");
                printf ("Seek staff support.\n");
                exiting();              /* Delete communication file */
                exit (-1);
        case TCML_NOSUCHREQ:
                printf ("Request %s does not exist.\n", reqid);
                break;
        case TCML_NOSUCHSIG:
                printf ("Request %s is running, and the ", reqid);
                printf ("specified signal is\n");
                printf ("not recognized by the execution machine.\n");
                break;
        case TCML_NOTREQOWN:
                printf ("Not owner of request %s.\n", reqid);
                break;
        case TCML_PEERDEPART:
                printf ("Request %s is presently being routed by a ", reqid);
                 printf ("pipe queue,\n");
                printf ("and cannot be suspended / resumed ");
                break;
        case TCML_PROTOFAIL:
                printf ("Protocol failure in inter-process communications ");
                printf ("with NQS daemon.\n");
                printf ("Seek staff support.\n");
                exiting();              /* Delete communication file */
                exit (-1);
        case TCML_REQSUSPENDED:
                printf ("Request %s has been suspended.\n", reqid);
                break;
        case TCML_REQRESUMED:
                printf ("Request %s has been resumed.\n", reqid);
                break;
        case TCML_REQWASRUNNING:
                printf ("Request %s is already running.\n", reqid);
                break;
        case TCML_REQWASSUSPENDED:
                printf ("Request %s is already suspended.\n", reqid);
                break;
        default:
                printf ("Unexpected completion code from NQS daemon.\n");
        	printf("The code is %d\n",code);
                exiting();              /* Delete communication file */
                exit (-1);
        }
}

