/* -----------------------------------------------------------------------------

 startup.api ©1999 Dietmar Eilert

 API plug-in. Runs a rexx macro specified by the user (as startup argument).
 Dice:

 DMAKE

 -------------------------------------------------------------------------------

*/

#include "defs.h"

/// "prototypes"

// library functions

Prototype LibCall struct APIClient *APIMountClient(__A0 struct APIMessage *, __A1 char *);
Prototype LibCall void              APICloseClient(__A0 struct APIClient  *, __A1 struct APIMessage *);
Prototype LibCall void              APIBriefClient(__A0 struct APIClient  *, __A1 struct APIMessage *);
Prototype LibCall void              APIFree       (__A0 struct APIClient  *, __A1 struct APIOrder   *);

// private

Prototype ULONG *SendRexxCommand(UBYTE *, UBYTE *, struct MessagePort *);
Prototype void   StartupHandler(void);

// globals

UWORD Handlers;

///
/// "library functions"

LibCall struct APIClient *
APIMountClient(__A0 struct APIMessage *apiMsg, __A1 char *args)
{
    static struct APIClient apiClient;

    apiClient.api_APIVersion = API_INTERFACE_VERSION;
    apiClient.api_Version    = 1;
    apiClient.api_Name       = "Startup";
    apiClient.api_Info       = "API example";
    apiClient.api_Commands   = NULL;
    apiClient.api_Serial     = 0;
    apiClient.api_Classes    = API_CLASS_SYSTEM;
    apiClient.api_Area       = NULL;

    // <args> names the macro to be executed

    if (args && *args) {

        UBYTE *command;

        if (command = AllocVec(strlen(args) + 1, MEMF_CLEAR | MEMF_PUBLIC)) {

            struct Task *task;

            Forbid();

            if (task = (struct Task *)CreateNewProcTags(NP_Entry, (APTR)StartupHandler, NP_Name, "STARTUP", NP_Priority, 1, TAG_DONE)) {

                ++Handlers;

                task->tc_UserData = (APTR)strcpy(command, args);
            }

            Permit();
        }

    }

    return(&apiClient);
}

LibCall void
APICloseClient(__A0 struct APIClient *handle, __A1 struct APIMessage *apiMsg)
{
    // wait for termination of running tasks

    while (Handlers)

        Delay(25);
}

LibCall void
APIBriefClient(__A0 struct APIClient *handle, __A1 struct APIMessage *apiMsg)
{
    // ignore notifies
}

LibCall void
APIFree(__A0 struct APIClient *handle, __A1 struct APIOrder *apiOrder)
{
    // no ressources to be freed
}

///
/// "rexx"

/* ---------------------------------- SendRexxCommand -------------------------

 Send ARexx message & wait for answer. Return pointer to result or NULL.

*/

__geta4 ULONG *
SendRexxCommand(port, cmd, replyPort)

UBYTE              *port;
UBYTE              *cmd;
struct MessagePort *replyPort;
{
    struct MsgPort *rexxport;

    Forbid();

    if (rexxport = FindPort(port)) {

        struct RexxMsg *rexxMsg, *answer;

        if (rexxMsg = CreateRexxMsg(replyPort, NULL, NULL)) {

            if (rexxMsg->rm_Args[0] = CreateArgstring(cmd, strlen(cmd))) {

                static ULONG result;

                rexxMsg->rm_Action = RXCOMM | RXFF_RESULT;

                PutMsg(rexxport, &rexxMsg->rm_Node);

                do {

                    WaitPort(replyPort);

                    if (answer = (struct RexxMsg *)GetMsg(replyPort))

                        result = answer->rm_Result1;

                } while (!answer);

                Permit();

                if (answer->rm_Result1 == RC_OK)

                    if (answer->rm_Result2)

                        DeleteArgstring((UBYTE *)answer->rm_Result2);

                DeleteArgstring((UBYTE *)ARG0(answer));

                DeleteRexxMsg(answer);

                return(&result);
            }
        }
    }

    Permit();

    return(NULL);
}

///
/// "startup handler"

/* ------------------------------ StartupHandler -------------------------------

 Send <command> to the ARexx server. This function runs as an asynchronous task
 because plug-ins are not allowed to block the host program. The command string
 is expected in the task's tc_UserData slot (it is FreeVec'ed by this function).

*/

__geta4 void
StartupHandler()
{
    UBYTE *command;

    if (command = FindTask(NULL)->tc_UserData) {

        struct MessagePort *msgPort;

        if (msgPort = CreateMsgPort()) {

            SendRexxCommand("AREXX", command, msgPort);

            DeleteMsgPort(msgPort);
        }

        FreeVec(command);

        Forbid();

        --Handlers;
    }
}

///
