/*
 * libnqs/req/delreq.c
 * 
 * DESCRIPTION:
 *
 *	Delete a queued NQS request, or signal a running NQS request.
 *
 *
 *	Original Author:
 *	-------
 *	Brent A. Kingsbury, Sterling Software Incorporated.
 *	October 3, 1985.
 */

#include <libnqs/license.h>
#include <libnqs/proto.h>
#include <libnqs/nqspacket.h>		/* NQS local message packets */
#include <libnqs/netpacket.h>		/* NQS remote message packets */
#include <libnqs/transactcc.h>
#include <libsal/license.h>
#include <libsal/proto.h>

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

extern Mid_t 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 = sal_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);
}

#if 0
/*** 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);
        }
}

#endif
