/*
** UrlManager.c - Opens an ARexx port and wait for commands
** Copyright (C) 1996-97 Serge Emond
**
** 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 2
** of the License, 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

#include "UrlManager.h"

#ifdef ONE_OBJECT_ONLY
#include "UMUtilities.c"
#include "UMRexxFcts.c"
#endif

/// Globals

struct Global g;
extern struct ExecBase *SysBase;

const TEXT *version=VERSION;
///

/// Main - Entry point

LONG main()
{
    if (SysBase->LibNode.lib_Version < 37)
    {
        Write(Output(), "You need OS version 37 or more\n", 31);
        exit(20);
    }

    InitAll();
    Loop();
    EndAll(NULL);
}
///

/// InitAll
// Reads CLI arguments, creates mem pools, opens msg port

void InitAll()
{
    // Fill Global struct with NULLs
    memset((STRPTR)&g, 0L, sizeof(struct Global));

    g.opts[OPT_PORT] = (LONG) DEF_PORT;

    // Read CLI Args
    if (!(g.rdargs = ReadArgs(OPT_TEMP, g.opts, NULL)))
    {
        PrintFault(IoErr(), NULL);
        EndAll(RETURN_FAIL);
    }

    // Create Mem Pools, Init List
    if (!FlushAll())
    {
        Printf("Can't alloc mem\n");
        EndAll(RETURN_FAIL);
    }

    // Create Msg Port
    Forbid();
    g.mp = FindPort((TEXT *)g.opts[OPT_PORT]);
    Permit();

    if (g.mp) {
        Printf("Port already exists\n");
        g.mp = 0;
        EndAll(RETURN_FAIL);
    }

    if (!(g.mp = CreatePort((TEXT *)g.opts[OPT_PORT], NULL)))
    {
        Printf("Can't create message port\n");
        EndAll(RETURN_FAIL);
    }

    // Set iosize
//  g.iosize = (g.opts[OPT_IOBUF] ? *((ULONG *)g.opts[OPT_IOBUF]) : DEF_IOSIZE);
}
///

/// EndAll
// Clears remaining messages, closes msgport, free pool memory, free args

void EndAll(ULONG ret)
{
    if (g.mp)
    {
        /* Return residual messages */
        while(g.msg = GetMsg(g.mp))
        {
            if (IsRexxMsg((struct RexxMsg *)g.msg))
            {
                ((struct RexxMsg *)g.msg)->rm_Result1 = 20;
            }

            ReplyMsg(g.msg);
        }

        DeletePort(g.mp);
    }
    if (g.spool) DeletePool(g.spool);
    if (g.upool) DeletePool(g.upool);
    if (g.rdargs) FreeArgs(g.rdargs);

    exit(ret);
}
///

/// void Reply( RC, UMRES );
// Replies an ARexx message, setting RC and a special result variable.

// ULONG RC:
//     Code to return in calling-script's RC variable
//
// char *UMRES:
//     String to be copied to calling-script's variable (name def in RES_VAR).
//     RES_VAR will be a NULL string if umres==NULL.

void Reply(ULONG res, STRPTR umres)
{
    /* Set RC */
    ((struct RexxMsg *)g.msg)->rm_Result1 = res;

    /* Set a result variable */
    if (SetRexxVar(g.msg, RES_VAR, (umres?umres:NULL),
                (umres?strlen(umres):0)))
    {
        /* Failed */
        ((struct RexxMsg *)g.msg)->rm_Result1 = 15;
    }

    /* Send the message back where it came from */
    ReplyMsg(g.msg);
}
///

/// Loop()
// Checks for break & messages

void Loop()
{
    ULONG signal;

    while(1)
    {
        /* Wait for msg or CTRL-C */
        signal = Wait(1 << g.mp->mp_SigBit | SIGBREAKF_CTRL_C);

        if (signal & (1<<g.mp->mp_SigBit))
        {
            /* We may have message(s) waiting, get/reply them */
            while(g.msg = GetMsg(g.mp))
            {
                /* If RexxMsg, process it, else return it */
                if (IsRexxMsg((struct RexxMsg *)g.msg)) ProcMsg();
                else ReplyMsg(g.msg);
            }
        }

        if (signal & SIGBREAKF_CTRL_C)
        {
            Printf("***BREAK\n");
            EndAll(0L);
        }
    }
}
///

/// ProcMsg()
// Processes message pointed by g.msg.  Calls the right function.

void ProcMsg()
{
    TEXT    tok[64],        // Will contain command's name
            *p;             // Points to argument-string

    p = stptok(((struct RexxMsg *)g.msg)->rm_Args[0], tok, sizeof(tok), " ");
    p = stpblk(++p);

    /* Parse all functions to find a match */
    for (g.exenmb=0; fcts[g.exenmb].cmd != NULL; g.exenmb++)
    {
        if (!stricmp(fcts[g.exenmb].cmd, tok))
        {
            /* Matched - call the function */
            fcts[g.exenmb].function(p);
            break;
        }
    }

    // Unknown command - RC = 10
    if (fcts[g.exenmb].cmd == NULL) Reply(10, NULL);
}
///

