/**
 *  TapeMon:  a monitor program for the BTNtape handler.
 *        Version 3.0   3/14/94
 */
#define VERSTAG "$VER: TapeMon/RAR 3.0 "
/*
 *  (c) Copyright 1990, 1994  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.
 *
 *   Compile with SAS/C v6.  To compile TapeMon, use "smake tapemon"
 */
#define _STRICT_ANSI
#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"

#include <proto/exec.h>
#include <proto/dos.h>
#include <pragmas/exec_pragmas.h>
#include <pragmas/dos_pragmas.h>

extern struct DosLibrary *DOSBase;

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

void main(int argc, char *argv[])
{
 struct Task    *tapeproc;
 struct Task    *monproc;
 struct MsgPort *monport;
 struct MsgPort *tapeport;
 struct Message *tmsg;
#define BTNM ((struct BTNmsg*)tmsg)
 static struct BTNmsg  mmsg;
 struct tplink  *linktp;
 char tn[32] = "BTN_";
 char mn[32] = "TMON_";
 UBYTE snsdata[64];
 UBYTE *snsflag;
 char *tapename;
 char *monname;
 char *xx;
 char *ver;
 ULONG x;
 int   run = 1;
 BOOL  fullsense = 0;
 int   ii;
 ULONG monsig;
 BYTE  oldpri;
 char  dbbcopy[80];

   ver = VERSTAG "(" __DATE__ ")";
   monproc = FindTask(NULL);

   if(argc > 1) {
      toUPPER(argv[1]);
      xx = argv[1] + strlen(argv[1])-1;
      if(*xx == ':') *xx = '\0';
      tapename = strcat(tn,argv[1]);
      monname  = strcat(mn,argv[1]);
   }
   else { tapename = "BTN_TAPE";  monname = "TMON_TAPE"; }

   if(argc > 2) fullsense = 1;

   monport = CreatePort(monname,0);
   if(!monport)  {
         printf("Unable to create tapemon port\n");
         exit(34);
   }
   monsig = 1 << monport->mp_SigBit;

   Forbid();
   tapeport = FindPort(tapename);
   Permit();
   if (!tapeport) {  /* tapemon may start before the handler */
         printf("Waiting for %s: to mount (^C to quit)...\n",tapename+4);
         x = Wait(monsig | SIGBREAKF_CTRL_C); /* Wait for wakeup from hndlr */
         if(x & monsig) {
             tmsg = GetMsg(monport);
             tapeport = tmsg->mn_ReplyPort;
             ReplyMsg(tmsg);
         }
         if(x & SIGBREAKF_CTRL_C) {
             DeletePort(monport);
             exit(0);
         }
   }
   tapeproc = tapeport->mp_SigTask;

   /* let the handler know we are here */
   mmsg.bmsg.mn_ReplyPort = monport;
   mmsg.mptr = monport;
   PutMsg(tapeport,&mmsg.bmsg);
   WaitPort(monport);       /* wait for reply */
   tmsg = GetMsg(monport);  /* which contains link to tplink block */
   if(!(linktp = BTNM->mptr)) {
         printf("Port %s refused connection...\n  TapeMon already running?\n",
                 tapename);
         DeletePort(monport);
         exit(35);
   }

   /* print informational items */
   printf("*** BTN-Tape Handler & Monitor ***\n%s\n",linktp->cpyw);
   printf("%s: Proc %X DevNode %X\n",tapeproc->tc_Node.ln_Name,
                                           tapeproc,linktp->devnode);
   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 message from the handler, copy the print
      string, reply the message, then print the string.  Escape on ctl-C.
   */

   x=0;
   for(;;) {
     if(x & SIGBREAKF_CTRL_C) run = 0;
     if(tmsg = GetMsg(monport)) {           /* check for a BTN message */
        linktp = BTNM->mptr;                    /* get link to BTN struct */
        strcpy(dbbcopy, linktp->dbb);           /* make a copy of string */
        snsflag = linktp->sns;                  /* make a copy of sense data */
        if(fullsense)  if(snsflag)
            memcpy(snsdata,snsflag,64);
        ReplyMsg(tmsg);                         /* release handler */
        printf(" %s",dbbcopy);                  /* print handler's message */
        if(fullsense && snsflag) {              /* print extra sense info */
           for(ii=0; ii<32; ii++)
               printf(" %02X",snsdata[ii]);
           printf("\n");
        }
     }
     else {
        if(run) x = Wait(monsig | SIGBREAKF_CTRL_C);  /* Wait for msg/ctl-c */
        else break;
     }
   }

   /* tell handler we are going bye-bye */
   mmsg.mptr = NULL;
   PutMsg(tapeport,&mmsg.bmsg);
   WaitPort(monport);

   /* Clean up and exit */
   SetTaskPri(monproc, (long) oldpri);          /* restore priority */
   DeletePort(monport);
   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;
}

