/* monproc.c - monitor amigados process packet activity. * * Phillip Lindsay (c) 1987 Commodore-Amiga, Inc. * */ #include #include #include #include #include #include #include #include #include #include #ifdef MANX #include #else #define index stpchr /* can you say "ANSI STANDARD"...I knew you could... */ #endif #include /* constants */ #define ONE 1L /* AmigaDOS uses task signal bit 8 for message signaling */ #define DOS_SIGNAL 8 #define DOS_MASK ( ONE << DOS_SIGNAL ) /* referenced globals */ extern void getprocs(),freeprocs(),givepkt(); void memfill(); extern struct DosLibrary *DOSBase; struct Message *packetwait(); LONG pw(); /* this the asm stub that calls packetwait() */ /* global data structures */ struct MsgPort *deviceid; struct Process *memyselfNi; ULONG mymask; struct SignalSemaphore canreturn; struct Message *mymess; main() { struct List procs; struct Node *proc; register struct Process *devproc; register struct DosPacket *pkt; BYTE mypri; register ULONG waitmask,signals,oldpktwait; LONG mysignal; ULONG count,choice; UBYTE processname[81]; puts("MONPROC - monitor AmigaDOS process packet activity.\n"); memyselfNi = (struct Process *) FindTask(NULL); NewList(&procs); /* initialize list header */ getprocs(&procs); /* fill list with "active" devices */ if(procs.lh_TailPred == &procs) /* list empty (should never happen) */ { puts("No processes."); exit(0); } /* * I am assuming that process list won't change. This is for hackers only. */ do { puts("Enter NUMBER for process to monitor:"); puts("Pick# Process MsgPort Name"); for(count = 1,proc = procs.lh_Head;proc->ln_Succ;proc=proc->ln_Succ,count++) printf("%4ld. %08lx %08lx %s\n",count, ((struct Process *)proc->ln_Name), &(((struct Process *)proc->ln_Name)->pr_MsgPort), ((struct Process *)proc->ln_Name)->pr_Task.tc_Node.ln_Name); printf("\nNUMBER: "); fflush(stdout); } while( scanf("%ld",&choice) == EOF ) ; if(!choice || choice >= count) { puts("Operation aborted."); freeprocs(&procs); exit(0); } /* what did he/she pick? */ for(count = 1,proc = procs.lh_Head;proc->ln_Succ;proc=proc->ln_Succ,count++) if(choice == count) { devproc = (struct Process *) proc->ln_Name; break; } /* we don't need our process list anymore */ freeprocs(&procs); /* make a copy of the process name */ strcpy(processname,devproc->pr_Task.tc_Node.ln_Name); /* get process msgport of process we will be monitoring */ deviceid = &devproc->pr_MsgPort; /* grab a signal for task intercommunication */ mysignal = (LONG) AllocSignal(-1L); if(mysignal == -1) { puts("Can't allocate a task signal."); exit(0); } mymask = ONE << mysignal; waitmask = SIGBREAKF_CTRL_C | mymask; /* initialize our semaphore */ memfill(&canreturn,(ULONG)sizeof(canreturn),0L); InitSemaphore(&canreturn); Forbid(); mypri = devproc->pr_Task.tc_Node.ln_Pri; Permit(); /* make sure our priority is greater than the device task */ SetTaskPri(memyselfNi, (ULONG)(mypri+1) ); puts("Waiting for messages...[CTRL_C to quit monitoring...]"); /* install our packet wait function */ Forbid(); oldpktwait = (ULONG) devproc->pr_PktWait; devproc->pr_PktWait = (APTR) pw; Permit(); /* * I am using semaphores to control the monitoring of the handler's packets. * There is probably a hundred better ways of doing this. I just went with * what first came to mind. Since I am a higher priority than the handler... * Once I am awake I will obtain the semaphore before the lower priority * task has a chance...I will give it back to him once I am done with the * packet data structure. */ do { signals = (ULONG) Wait(waitmask); ObtainSemaphore(&canreturn); if(signals & mymask) /* did the packetwait code signal us? */ { /* yes, let's boogie... */ pkt = (struct DosPacket *) mymess->mn_Node.ln_Name; /* get packet address */ printf("%s: ",processname); givepkt(pkt); } ReleaseSemaphore(&canreturn); } while(!(signals & SIGBREAKF_CTRL_C)); /* remove our packet wait function and install previous value */ Forbid(); devproc->pr_PktWait = (APTR) oldpktwait; Permit(); SetTaskPri(memyselfNi,0L); puts("\nThere is no safe way to leave since the process is waiting in"); puts("our installed code. We have de-installed ourselves, but you should"); puts("be certain that the process received a packet AFTER we have been"); puts("de-installed. Press CTRL-E if you are certain this has happened."); Wait(SIGBREAKF_CTRL_E); FreeSignal(mysignal); puts("All done."); } /* end of main() */ /** ** local subroutines **/ /* * packetwait() ... Waits for a message to arrive at your port and * returns it to you. */ struct Message *packetwait() { #ifdef MANX /* if MANX make sure we can see our data */ geta4(); #endif /* wait for packet */ SetSignal(FALSE,DOS_MASK); /* clear sigbit 8 */ while( !(mymess = (struct Message *) GetMsg(deviceid)) ) Wait(DOS_MASK); Signal(memyselfNi,mymask); /* Wake up monitoring task he will grab the data */ ObtainSemaphore(&canreturn); /* we get this guy when we CAN return */ ReleaseSemaphore(&canreturn); return(mymess); } /* * memfill() - fill memory with supplied byte value for "size" bytes */ void memfill(source,size,value) UBYTE *source; ULONG size; UBYTE value; { register UBYTE *msource=source, mvalue=value; register ULONG msize=size; if(msize) { do { --msize; msource[msize] = mvalue; } while(msize); } } /* * This code stub has been known to save lives... */ #if MANX #asm XREF _packetwait XDEF _pw _pw: movem.l a2/a3/a4,-(sp) jsr _packetwait movem.l (sp)+,a2/a3/a4 rts #endasm #endif /* end of procdev.c */