/* * MONPROC.C - Monitor AmigaDOS process packet activity. * * Phillip Lindsay (c) 1987 Commodore-Amiga, Inc. * You may use this source as long as this copywrite notice is left intact. * * re-organized and slightly re-worked by Davide P. Cervone, 4/25/87. */ #include #include #include #include #include #include #ifdef MANX #include #endif #define ONE 1L /* * AmigaDOS uses task signal bit 8 for message signaling */ #define DOS_SIGNAL 8 #define DOS_MASK (ONE<ln_Succ; /* while there are more */ theProc=theProc->ln_Succ,count++) /* go on to the next */ { printf("%4ld. %08lX %08lX %s\n",count, theProc->ln_Name, &(PTR(Process,theProc->ln_Name)->pr_MsgPort), PTR(Process,theProc->ln_Name)->pr_Task.tc_Node.ln_Name); } printf("\nNUMBER: "); gets(s); } while (sscanf(s,"%ld",&choice) != 1); if (choice < 1 || choice >= count) { printf("Operation Aborted.\n"); } else { for (count=1,theProc=ProcList.lh_Head; count < choice; theProc=theProc->ln_Succ,count++); ChosenProcess = PTR(Process,theProc->ln_Name); } FreeProcList(&ProcList); } return(ChosenProcess); } /* * SetupSignal() * * Allocate a signal to use for our inter-task communication, and * set up the mask for using it. */ void SetupSignal(theSignal) LONG *theSignal; { *theSignal = AllocSignal(-ONE); if (*theSignal == -ONE) { printf("Can't Allocate a Task Signal."); exit(10); } WaitMask = (ONE << (*theSignal)); } /* * SetupProcess() * * Copy the process name, and gets it Message port. Set our priority * higher than the monitored process so we will be able to react to its * signals. Then set the pr_PktWait field so that we begin monitoring * the other task. Save the old one so we can put it back. */ void SetupProcess(theProcess,name) struct Process *theProcess; char *name; { strcpy(name,theProcess->pr_Task.tc_Node.ln_Name); thePort = &theProcess->pr_MsgPort; Forbid(); SetTaskPri(myProcess,(ULONG)(theProcess->pr_Task.tc_Node.ln_Pri + 1)); OldPktWait = theProcess->pr_PktWait; theProcess->pr_PktWait = (APTR) PWait; Permit(); } /* * MonitorProcess() * * Wait for the monitored process to receive a message (our PacketWait() * function signals us via theSignal when it has received a message), then * print out the contents of the message. A semaphore is used to coordinate * this routine with the PacketWait() routine (which is run asynchonously * by the monitored process). Phillip Lindsay says "there are probably a * hundred better was of doing this. I just went with the first one [that] * came to mind." I couldn't think of a better one, so I still use it. * Since our process is running at a higher priority than the monitored one, * we should obtain the semaphore first. The other process wil block until * we release it (when we are done printing the contents). */ void MonitorProcess(name,theSignal) char *name; ULONG theSignal; { ULONG signals; struct DosPacket *thePacket; do { signals = Wait(SIGBREAKF_CTRL_C | WaitMask); ObtainSemaphore(&CanReturn); if (signals & WaitMask) { /* * PacketWait() signalled us so print the message it put in * theMessage. */ thePacket = PTR(DosPacket,theMessage->mn_Node.ln_Name); printf("\n%s: ",name); PrintPkt(thePacket); } ReleaseSemaphore(&CanReturn); } while(!(signals & SIGBREAKF_CTRL_C)); } /* * ClenUpProcess() * * Put everything back the way we found it, except that the monitored process * is still running our code... */ void CleanUpProcess(theProcess) struct Process *theProcess; { Forbid(); theProcess->pr_PktWait = OldPktWait; Permit(); SetTaskPri(myProcess,0L); } /* * WaitForLastPacket() * * Since the monitored process is still running our PacketWait() code, we * can't quit yet. Since we already put back the old pr_PktWait pointer, * our code will not be called after the next packet is received, so we have * to wait for one more packet before we can quit. Note that PacketWait() * will still signal us, so we know when it will be safe to remove the code. * Just in case we goof, let CTRL-E cancel, too. */ void WaitForLastPacket(theSignal) ULONG theSignal; { ULONG signals; printf("\nThe process must receive another message before we can safely\n"); printf("remove the packet wait code. We will wait for one more packet.\n"); printf("Press CTRL-E if you want to quit early, but that will likely\n"); printf("crash the monitored process!\n"); signals = Wait(SIGBREAKF_CTRL_E | WaitMask); if (signals & WaitMask) { ObtainSemaphore(&CanReturn); ReleaseSemaphore(&CanReturn); } } void main(argc,argv) int argc; char **argv; { struct Process *ChosenProcess; LONG TaskSignal; UBYTE ProcessName[81]; if (argc > 1) DoArguments(argc,argv); printf("\n%s - monitor AmigaDOS process packet activity.\n",*argv); myProcess = FindTask(NULL); ChosenProcess = GetProcToMonitor(); if (ChosenProcess != NULL) { #ifndef MANX onbreak(&Ctrl_C); /* Turn off CTRL-C for Lattice: we do our own */ #endif SetupSignal(&TaskSignal); InitSemaphore(&CanReturn); SetupProcess(ChosenProcess,ProcessName); printf("Monitor Installed, press CTRL-C to quit monitoring\n"); MonitorProcess(ProcessName,TaskSignal); CleanUpProcess(ChosenProcess); WaitForLastPacket(TaskSignal); FreeSignal(TaskSignal); printf("\nAll done.\n"); } } /* * This code stub has been known to save lives... */ #if MANX #asm XREF _PacketWait XDEF _PWait _PWait: movem.l a2/a3/a4,-(sp) jsr _PacketWait movem.l (sp)+,a2/a3/a4 rts #endasm #endif