/**
 *  TapeMon:  the monitor program for the BTNtape handler.
 */
#define VERSTAG "$VER: TapeMon/RAR 2.1 "
/*
 *  (c) Copyright 1990, 1991  Robert Rethemeyer
 *   This software may be freely distributed and redistributed,
 *   for non-commercial purposes, provided this notice is included.
 *------------------------------------------------------------
 *   Run TapeMon from a CLI to receive informational messages
 *   from the BTN-Tape handler process.  To terminate the
 *   monitor program, break the CLI using control-C or BREAK.
 */
#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/ports.h>
#include <exec/tasks.h>
#include <exec/execbase.h>
#include <libraries/dos.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "/tplink.h"

#if defined AZTEC_C
  #include <functions.h>
#elif defined LATTICE
  #include <proto/exec.h>
  #include <proto/dos.h>
#endif

extern struct DosLibrary *DOSBase;

void main(int,char *[]);
void toUPPER(char *);

void main(int argc, char *argv[])
{
 struct Task    *tapeproc;
 struct Task    *monproc;
 struct tplink  *linktp;
 char *tapename;
 char *xx;
 char *ver;
 ULONG x;
 int   run = 1;
 int   fullsense = 0;
 int   ii;
 BYTE  signum;
 BYTE  oldpri;

   ver = VERSTAG "(" __DATE__ ")";
   printf("*** BTN-Tape Handler & Monitor ***\n"
          "(c) Copyright 1990,1991 R. Rethemeyer\n");

   if(argc > 1) {
      tapename = argv[1];
      toUPPER(tapename);
      xx = &tapename[strlen(tapename)-1];
      if(*xx == ':') *xx = '\0';
   }
   else tapename = "TAPE";

   if(argc > 2) fullsense = 1;

   if (!(tapeproc = FindTask(tapename)))  {
         printf("Process %s not found.\n",tapename);
         exit(30);
   }
   if (!(linktp = (struct tplink *) tapeproc->tc_UserData))  {
         printf("No linkage structure...\n wrong process, or\n handler not active yet?\n");
         exit(31);
   }
   printf("%s: Proc %X DevNode %X\n",tapename,tapeproc,linktp->devnode);

   if (strcmp(linktp->keyword,"TapeHandler"))  {
         printf("Process %s doesn't look like BTN-Tape\n",tapename);
         exit(32);
   }

   if (linktp->montask)  {
         printf("There is already a TapeMon running\n");
         exit(33);
   }

   if (!linktp->handsig) {
          printf("Handler has no signal\n");
          exit(34);
   }

   signum = AllocSignal(-1);
   if (signum == -1)  {
         printf("Unable to allocate signal for TapeMon\n");
         exit(35);
   }
   linktp->monsig  = 1UL << signum;      /* give mask to tape handler */
   monproc = linktp->montask = FindTask(0);

   printf("%s  Unit-%X  LU-%X\n",linktp->driver,*(linktp->unit),
                                                *(linktp->Lun)>>5);

   if(linktp->inquiry[8] != '\0')  printf("Drive: %s\n",linktp->inquiry+8);
   if(linktp->inquiry[0] == 0x01)
        printf("Sequential Access\n");
   else if (linktp->inquiry[0] == 0x10)
        printf("Direct Access\n");
   else if (linktp->inquiry[0] == 0x7f)
        printf("BAD LOGICAL UNIT NUMBER\n");
   else printf("Device type = %X\n",linktp->inquiry[0]);

   if(linktp->badparm) printf("ERROR(S) IN STARTUP\n");

   if(linktp->sense)
       printf("Last sense= %s, other=%02X,%02X\n",linktp->sense,linktp->xsns1,
         linktp->xsns2);
   printf("Use ^C to terminate TapeMon\n-%s\n",linktp->version+6);

   /* Set the monitor priority to the same as that of the handler */
   oldpri = SetTaskPri (monproc, (long)tapeproc->tc_Node.ln_Pri);

   /* The main loop.  Wait for a signal from the handler, then print the
      contents of dbb.  Some extra handshaking must then be done to sync
      the two processes and prevent races.  If a control-C occurs during
      a Wait, then finish whatever was in progress before ending the loop.
   */

   while(run)  {
     x=Wait(linktp->monsig | SIGBREAKF_CTRL_C);   /* Wait for req from hndlr */
     if  (x & SIGBREAKF_CTRL_C) run = 0;
     if(!(x & linktp->monsig) ) {                 /* detect control-c */
        linktp->montask = NULL;                   /* break link with handler */
        if(SetSignal(0,0) & linktp->monsig) {     /* detect terminate race */
            linktp->montask = monproc;
            SetSignal(SIGBREAKF_CTRL_C,SIGBREAKF_CTRL_C);
            run = 1;
        }
        continue;
     }

     printf(" %s",linktp->dbb);                   /* print handler's message */
     if(fullsense && linktp->sns) {               /* If sense info           */
        for(ii=0; ii<32; ii++)                    /*   print all sense info  */
            printf(" %02X",linktp->sns[ii]);
        printf("\n");
     }

     Signal(tapeproc, linktp->handsig);           /* tell it we are 'done' */

     x=Wait(linktp->monsig | SIGBREAKF_CTRL_C);   /* Wait for ack of 'done' */
     if  (x & SIGBREAKF_CTRL_C) run = 0;
     if(!(x & linktp->monsig) ) Wait(linktp->monsig);

     if(!run) linktp->montask = NULL;
     Signal(tapeproc, linktp->handsig);           /* Ack his ack */
   }

   /* Clean up and exit */

   SetTaskPri(monproc, (long) oldpri);          /* restore priority */
   linktp->monsig  = 0;
   FreeSignal((ULONG)signum);
   printf("TapeMon terminated\n");
   exit(0);
}

/**************************************************************************/
/* toUPPER: convert string to upper case */

void toUPPER(char *zz)
{
  for(; *zz != '\0'; zz++)  if(*zz >= 'a') *zz -= 0x20;
  return;
}
