
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <dos/dos.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>

#include <clib/AMarquee_protos.h>
#include <pragmas/AMarquee_pragmas.h>

FILE * output                 = NULL;
struct Library * AMarqueeBase = NULL;
struct QSession * session     = NULL;

#define UNLESS(x) if(!(x))

/* Takes user input until blank line is typed */
void ProcessDebugCommands(struct QSession * session)
{
  BOOL BReturn = FALSE;
  
  while(BReturn == FALSE)
  {
   char debugline[500] = "\0\0\0\0\0\0\0\0";
   char * keyword, * data;
   ULONG dataLen = 0L;
   LONG res;
   
   fprintf(output, "Enter your debug command now: "); fflush(output);
   fgets(debugline, sizeof(debugline), output); fflush(output);
   
   keyword = &debugline[2];
   if (data = strchr(keyword,'='))
   {
     *data = '\0';  /* terminate the keyword */
     data++;
     dataLen = strlen(data)+1;
   }
   switch((int)(debugline[0]))
   {
     case '\0': case '\n': res=QGo(session,0L); BReturn=TRUE;break;
     case 's':  res=QSetOp(session, keyword, data, dataLen); break;
     case 'm':  res=QMessageOp(session, keyword, data, dataLen); break;
     case 'S':  res=QStreamOp(session, keyword, data, dataLen); break;
     case 'd':  res=QDeleteOp(session, keyword);             break;
     case 'i':  res=QInfoOp(session);                        break;
     case 'p':  res=QPingOp(session);                        break;
     default:   fprintf(output,"Command code %c was not recognized.\n",debugline[0]); break;
   }
   fprintf(output,"(Op result was %i)\n",res); fflush(output);
  }
}


void CleanExit(void)
{
  if (session)      QFreeSession(session);        /* This MUST be done before we close the library! */
  if (AMarqueeBase) CloseLibrary(AMarqueeBase);  
  if (output)       
  {
    fprintf(output,"\n\nExiting... window will close in 2 seconds.\n"); fflush(output);
    Delay(200);
    fclose(output);
  }
}

/* Main program */
int main(int argc, char ** argv)
{    
  UNLESS(output = fopen("CON:","r+")) exit(RETURN_ERROR);  

  atexit(CleanExit);

  UNLESS(AMarqueeBase = OpenLibrary("amarquee.library",37L))
  {
    fprintf(output, "Couldn't open amarquee.library v37!\n");
    exit(RETURN_ERROR);
  }
  fprintf(output,"Getting connection socket from inetd...\n"); fflush(output);
  UNLESS(session = QNewServerSession("#?", "#?"))
  {
    fprintf(output,"Couldn't accept connection from inetd.\n\n");
    fprintf(output,"Note that this program MUST be started by AmiTCP,\n");
    fprintf(output,"starting it manually from the CLI will only get you\n");
    fprintf(output,"this message.  See the AMarquee docs under example\n");
    fprintf(output,"programs for how to install and use this demo.\n");
    exit(RETURN_WARN);
  }
 
  fprintf(output, "This is a demonstration AmiTCP inetd daemon, using\n");
  fprintf(output, "amarquee.library.  You may interactively send and receive\n");
  fprintf(output, "data with any connecting AMarquee-based client.\n\n");
  fprintf(output, "Commands for this demo daemon:\n");
  fprintf(output, "\n");
  fprintf(output, "s path=value  (use QSetOp to queue data)\n");
  fprintf(output, "m hosts=value (use QMessageOp to queue data)\n");
  fprintf(output, "S path=value  (use QStreamOp to queue data)\n");
  fprintf(output, "d path        (use QDeleteOp to queue null data)\n");
  fprintf(output, "i             (use QInfoOp to queue free memory info)\n");
  fprintf(output, "p             (use QPingOp to queue ping packet\n");
  fprintf(output, "<enter>       (Send all queued transactions)\n");
  fprintf(output,"Press CTRL-F to enter commands, or CTRL-C to quit\n\n"); fflush(output);
  while(1)
  {
    struct QMessage * qMsg;
    ULONG signals = (1L << session->qMsgPort->mp_SigBit) | (SIGBREAKF_CTRL_C) | (SIGBREAKF_CTRL_F);

    /* Wait for next message from the server */
    signals = Wait(signals);
    
    if (signals & (1L << session->qMsgPort->mp_SigBit))
    {
      while(qMsg = (struct QMessage *) GetMsg(session->qMsgPort))
      {
        struct QRunInfo * inf = (qMsg->qm_DataLen == sizeof(struct QRunInfo)) ? (struct QRunInfo *) qMsg->qm_Data : NULL;

        /* Handle message */
        fprintf(output,"Message %p recieved---------\n",qMsg);
        fprintf(output,"Status:       %i\n",  qMsg->qm_Status);
        fprintf(output,"Error Line:   %i\n",  qMsg->qm_ErrorLine);
        fprintf(output,"Message ID:   %i\n",  qMsg->qm_ID);
        fprintf(output,"Path:        [%s]\n", qMsg->qm_Path?qMsg->qm_Path:"<NULL>");
        fprintf(output,"Data:        [%s](int=%i)\n", qMsg->qm_Data?qMsg->qm_Data:((UBYTE*)"<NULL>"),qMsg->qm_Data?(*((int*)qMsg->qm_Data)):0);
        fprintf(output,"DataLen:      %lu\n", qMsg->qm_DataLen);
        fprintf(output,"ActualLen:    %lu\n", qMsg->qm_ActualLen);
        if (inf) fprintf(output,"Info: alloced:%li allowed:%li avail:%li\n",inf->qr_Alloced, inf->qr_Allowed, inf->qr_Avail); 
        if (qMsg->qm_Status == QERROR_NO_CONNECTION) Signal(FindTask(NULL), SIGBREAKF_CTRL_C);  /* kill myself! */
        FreeQMessage(session, qMsg);
        fflush(output);        
      }
    }
    if (signals & SIGBREAKF_CTRL_F) ProcessDebugCommands(session);
    if (signals & SIGBREAKF_CTRL_C) break;  /* Quit if CTRL-C pressed */
  }
  /* CleanExit() called here! */
}
