/**************************************************************************
   CONCOM.C
***************************************************************************
   This module shows how to add console commands to NetWare.  This is
   useful in situations where an NLM needs console IO support
   (for instance, an NLM which has no screen).

   After loading CONCOM.NLM, return to the system console and notice that
   two new commands are accepted by the NetWare console - CONCOM STAT and
   CONCOM MISC.
*************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <nwtypes.h>
#include <nwthread.h>
#include <nwerrno.h>
#include <nwadv.h>
#include <nwconio.h>

#define HANDLEDCOMMAND  0
#define NOTMYCOMMAND    1

/* Prototypes */

int     InstallConsoleHandler(void);
static  void  CCRemoveConsoleHandler(void);
void    HandleStatRequest(void *dummy);
void    HandleMiscRequest(void *dummy);
void    ScheduleStatCommand(void);
void    ScheduleMiscCommand(void);
static  LONG CommandLineInterpreter(LONG screenID, BYTE *commandLine);

/* Globals */

static  LONG    StatCommandThread;
static  LONG    MiscCommandThread;

/*  Structure used to register/deregister a console handler with the OS */
static  struct  commandParserStructure ConsoleHandler = {0, CommandLineInterpreter, 0};

int main(void)
{
   if (BeginThread(HandleStatRequest,NULL,8192,NULL) == EFAILURE)
   {
      printf("ConCom: Couldn't start Handle Stat Request thread!\n");
      exit(1);
   }

   if (BeginThread(HandleMiscRequest,NULL,8192,NULL) == EFAILURE)
   {
      printf("ConCom: Couldn't start Handle Misc Request thread!\n");
      exit(1);
   }

   ThreadSwitch(); /* let them run at least once... */

   if (InstallConsoleHandler() == EFAILURE)
   {
      printf("ConCom: Couldn't install command parser!\n");
      exit(1);
   }

   ExitThread(EXIT_THREAD,0);
   return(0);
}

static LONG CommandLineInterpreter(LONG screenID, BYTE *commandLine)
{
   screenID = screenID;
   /*  All added commands begin with "CONCOM " */

   if (!strnicmp("CONCOM ", commandLine, 7))
   {
      /*
        Figure out which command it is, and then schedule the
        appropriate thread to handle the request.  It's a good
        idea to execute quickly here, and return back to the
        console handler, so all I'm doing is signalling a local
        semaphore which will wake up the appropriate function.

        If you want to do all of the work here, you MUST change
        the CLib context to that of a thread group in your NLM.
        You can use SetThreadGroupID to do this.  Remember to
        switch it back before you return.
      */

      if (!strnicmp("STAT",&commandLine[7],4))
      {
         ScheduleStatCommand();
         ConsolePrintf("ConCom: STAT request being processed!\r\n");
      }
      else if (!strnicmp("MISC",&commandLine[7],4))
      {
         ScheduleMiscCommand();
         ConsolePrintf("ConCom: MISC request being processed!\r\n");
      }
      else
      {
         ConsolePrintf("ConCom: \"%s\" is not a valid command!\r\n",
                       &commandLine[7]);
      }

      /*  Tell NetWare we handled the command */
      return HANDLEDCOMMAND;
   }

   /*  Tell NetWare that the command isn't mine */
   return NOTMYCOMMAND;
}

/*  This function is called during NLM shutdown */

static void CCRemoveConsoleHandler(void)
{
   UnRegisterConsoleCommand(&ConsoleHandler);
}

/*  This function installs the handler */

int InstallConsoleHandler(void)
{
   /*  Our command line handler interfaces the system operator
       with this NLM */

   ConsoleHandler.RTag = AllocateResourceTag(GetNLMHandle(),
                                             "Command Line Processor",
                                             ConsoleCommandSignature);
   if (!ConsoleHandler.RTag)
   {
      printf("Error on allocate resource tag\n");
      return EFAILURE;
   }

   RegisterConsoleCommand(&ConsoleHandler);

   /*  The Remove procedure unregisters the console handler */

   atexit( CCRemoveConsoleHandler );
   return ESUCCESS;
}

void ScheduleStatCommand(void)
{
   ResumeThread(StatCommandThread);
}

void HandleStatRequest(void *dummy)
{
   dummy = dummy;
   for (;;)
   {
      SuspendThread(StatCommandThread = GetThreadID());
      ConsolePrintf("ConCom: Message from the STAT command\n");
   }
}

void ScheduleMiscCommand(void)
{
   ResumeThread(MiscCommandThread);
}

void HandleMiscRequest(void *dummy)
{
   dummy = dummy;
   for (;;)
   {
      SuspendThread(MiscCommandThread = GetThreadID());
      ConsolePrintf("ConCom: Message from the MISC command\n");
   }
}

