/*************************************************************************

MUIEmpire Service written by Karl Bellve

   
*************************************************************************/


#include <exec/types.h>
#include <exec/memory.h>
#include <exec/ports.h>

#include <utility/tagitem.h>
#include <workbench/startup.h>

#include <dos/dostags.h>
#include <dos.h>

#include <envoy/nipc.h>
#include <envoy/services.h>

#include <pragmas/dos_pragmas.h>
#include <pragmas/exec_pragmas.h>
#include <pragmas/nipc_pragmas.h>
#include <pragmas/utility_pragmas.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <clib/nipc_protos.h>
#include <clib/alib_protos.h>
#include <clib/utility_protos.h>

#include "string.h"
#include "stdio.h"
struct Library *UtilityBase, *DOSBase;

#define ASM           __asm
//StartServiceA   (struct TagItem *);
//GetServiceAttrsA(struct TagItem *);

struct StartMsg
{
  struct WBStartup wbmsg;    
  struct PhonySegList *psl;
  struct Segment *rsl;
  struct MsgPort *parent;  
  char   name[30];
};

struct PhonySegList {
        BPTR    psl_NextSeg;            /*  BPTR to next element in list  */
        UWORD   psl_JMP;                /*  A 68000 JMP abs.l instruction  */
        LONG    (*psl_EntryPoint)();    /*  The address of the function  */
};


struct PhonySegList psltemplate = {
        NULL,                           /*  No next element.              */
        0x4EF9,                         /*  JMP abs.l                     */
        NULL                            /*  Argument for JMP instruction  */
};

int x;

VOID __saveds ASM LIBRexxReserved() { return; }


/**************************************************************************
StartService() - Starts the service.

    Services Manager calls this function to attempt to start the service.

    INPUTS: TagList passed in by Services Manager
    OUTPUT: Error Code - Non Zero Means Error
**************************************************************************/
ULONG __saveds ASM LIBStartServiceA(register __a0 struct TagItem *st_list)
{
    struct TagItem cptags[3];
    struct Process *lpdproc;
    struct MyStartMsg *startupmsg;
    struct MsgPort *parent,*child;
    struct PhonySegList *fakelist = NULL;
    char   name[20];
    BOOL   status = FALSE;
    UBYTE  sigbit;
    ULONG  MUIEmpireError = 0;
    
    
    x++;
    sprintf(&name[0],"empireserver.%d\0",x);
    parent = CreatePort(NULL, NULL);
    if (parent) {
       if (!(fakelist = (struct PhonySegList *)
           AllocMem (sizeof(struct PhonySegList), NULL)  ))
         {
         DeletePort(parent);
         return(1);
         }
         CopyMem (&psltemplate, fakelist, sizeof(PhonySegList) );
         fakelist->psl_EntryPoint = NULL;

        
        
        if (seglist = NewLoadSeg("Empire:EnvoyEmpireServer",NULL)) {
    
            cptags[0].ti_Tag  = NP_Seglist;
            cptags[0].ti_Data = seglist;
            cptags[1].ti_Tag  = NP_Name;
            cptags[1].ti_Data = (ULONG) &name[0];
            cptags[2].ti_Tag  = TAG_DONE;
            cptags[2].ti_Data = NULL;
            
            startupmsg = (struct MyStartMsg *) AllocMem(sizeof(struct MyStartMsg), NULL);
            
            if (startupmsg) {
               if (child = (struct MsgPort *)CreateProc (cname, priority, (BPTR) startupmsg->rsl, stacksize) )
                 port = (struct MsgPort *) lpdproc;
                 startupmsg->wbmsg.sm_Message.mn_Node.ln_Type = NT_MESSAGE;
                 startupmsg->wbmsg.sm_Message.mn_Node.ln_Pri  = 0;
                 startupmsg->wbmsg.sm_Message.mn_ReplyPort    = parent;
                 startupmsg->wbmsg.sm_Process = child;
                 startupmsg->wbmsg.sm_Segment = (BPTR) startupmsg->rsl;
                 startupmsg->wbmsg.sm_NumArgs = 0L;
                 startupmsg->wbmsg.sm_ToolWindow = NULL;
                 startupmsg->wbmsg.sm_ArgList = NULL;
                 startupmsg->psl = fakelist;     /** for cleanup **/
                 startupmsg->rsl = (struct Segment *)seglist;
                 startupmsg->parent = parent;
                 strcpy(startupmsg->name, name);
                 
                 PutMsg(child, (struct Message *) startupmsg);
                 Wait(1L<<parent->mp_SigBit);
                 
              }
              FreeMem(startupmsg, (long) sizeof(struct MyStartMsg));
            }
            
            if(tag=FindTagItem(SSVC_EntityName,st_list))
              {
              strcpy((char *)tag->ti_Data,name);
              } 
            else MUIEmpireError = 2;
            FreeMem (fakelist, (LONG) sizeof (struct PhonySegList));
        }
        else MUIEmpireError = 3;
        DeletePort(parent);
    }    
       
    return(MUIEmpireError);
}



/*************************************************************************
GetServiceAttrsA() - Get service attributes

    Required to return the name of the service in tag SVCAttrs_Name

    INPUTS: TagList from services manager to process/update
*************************************************************************/
VOID __saveds ASM LIBGetServiceAttrsA(register __a0 struct TagItem *tagList)
{
    struct TagItem *ti;

    if(ti=FindTagItem( SVCAttrs_Name, tagList))
    {
        strcpy((STRPTR)ti->ti_Data,"MUIEmpire_Service");
    }
}


int __saveds __UserLibInit(void) {
  
  UtilityBase = OpenLibrary("utility.library",37);
  DOSBase = OpenLibrary("dos.library",37);
  
  if (!DOSBase) return(1);
  if (!UtilityBase){
      CloseLibrary(DOSBase);
      return (1);
  }
  
  return(0);
}

int __saveds __UserLibCleanup(void) {
  
  CloseLibrary(DOSBase);
  CloseLibrary(UtilityBase);
   
  return(0);
}
