/*
 *	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	05-Dec-1991	Added support for remote deletes.
*       V01.20	JRR	16-Jan-1992	Added support for RS6000.
*       V01.3 	JRR	28-Feb-1992	Added Cosmic V2 changes.
*       V01.4   JRR     13-Apr-1992     Remove bogus printf.
*	V01.5	JRR	17-Jun-1992	Added header.
*	V01.6	JRR	05-Nov-1992	Modified for C prototypes.
*	V01.7
*	V01.8	JRR	23-Feb-1993	Added Boeing enhancement for Mids.
*	V01.9	JRR	18-Aug-1993	Clean up includes.
*	V01.10	JRR	03-Mar-1994	Fix up NMAP.
*/
/*++ delreq.c - Network Queueing System
 *
 * $Source: /usr2/jrroma/nqs/nqs-3.35.6/lib/RCS/delreq.c,v $
 *
 * DESCRIPTION:
 *
 *	Delete a queued NQS request, or signal a running NQS request.
 *
 *
 *	Author:
 *	-------
 *	Brent A. Kingsbury, Sterling Software Incorporated.
 *	October 3, 1985.
 *
 *
 * STANDARDS VIOLATIONS:
 *   None.
 *
 * REVISION HISTORY: ($Revision: 1.10 $ $Date: 1994/03/30 20:32:26 $ $State: Exp $)
 * $Log: delreq.c,v $
 * Revision 1.10  1994/03/30  20:32:26  jrroma
 * Version 3.35.6
 *
 * Revision 1.9  93/09/10  13:55:08  jrroma
 * Version 3.35
 * 
 * Revision 1.8  93/07/13  21:31:00  jrroma
 * Version 3.34
 * 
 * Revision 1.7  92/11/06  11:07:30  jrroma
 * Modified for C prototypes.
 * 
 * Revision 1.6  92/06/18  13:23:38  jrroma
 * Added gnu header
 * 
 * Revision 1.5  92/05/06  10:09:19  jrroma
 * Version 3.20
 * 
 * Revision 1.4  92/02/28  13:49:22  jrroma
 * Added Cosmic V2 code.
 * 
 * Revision 1.3  92/01/16  15:23:41  jrroma
 * Added support for RS6000.
 * 
 * Revision 1.2  91/12/05  16:48:13  jrroma
 * Completed fixes for remote deletes
 * 
 * Revision 1.1  91/11/19  13:28:42  jrroma
 * Initial revision
 * 
 *
 */

#include <nqs.h>
#include "nqspacket.h"			/* NQS local message packets */
#include "netpacket.h"			/* NQS remote message packets */
#include "transactcc.h"


#ifndef __CEXTRACT__
#if __STDC__

static int diagdel ( long code, char *reqid );

#else /* __STDC__ */

static int diagdel (/* long code, char *reqid */);

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

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

/*** delreq
 *
 *
 *	long delreq():
 *	Delete a queued NQS request, or signal a running 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_REQDELETE:	 if the request was queued, and was
 *				 deleted.
 *		TCML_REQRUNNING: if the request is running, and has
 *				 not been signalled.
 *		TCML_REQSIGNAL:	 if the request was running, and
 *				 has been signalled.
 *
 *    With version 3.02 we now can do remote deletes, so the TCMP forms
 *    of the errors are possible as well.    
 */
long delreq (
	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 sig,		/* Signal to send to the processes */
				/* in the req, if running.  0 if no*/
				/* signals are to be sent to */
				/* running request processes */
	int reqquestate)	/* Request queue state */
{

        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 (orig_mid);
	    interw32i ((long) target_mid);
	    interw32i ((long) sig);
	    interw32i ((long) reqquestate);
	    return (inter (PKT_DELREQ));
	}

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

        sd = establish (NPK_DELREQ, 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 (orig_mid);
                interw32i ((long) sig);
                interw32i ((long) reqquestate);
                sd = establish (NPK_DELREQ, target_mid,
                        mapped_uid, whompw->pw_name, &transactcc);
                timeout *= 2;
            } while (sd == -2 && timeout <= 16);
        }
        return (transactcc);
}

/*** diagqdel
 *
 *
 *      diagdel():
 *      Diagnose delreq() completion code.
 */
static int diagdel (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 this NQS implementation does not support the ");
                printf ("deletion of a\n");
                printf ("request under such conditions.\n");
                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_REQDELETE:
                printf ("Request %s has been deleted.\n", reqid);
                break;
        case TCML_REQRUNNING:
                printf ("Request %s is running.\n", reqid);
                break;
        case TCML_REQSIGNAL:
                printf ("Request %s is running, and has ", reqid);
                printf ("been signalled.\n");
                break;
        default:
                printf ("Unexpected completion code from NQS daemon.\n");
                exiting();              /* Delete communication file */
                exit (-1);
        }
}

