Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!utgpu!water!watnot!watmath!clyde!rutgers!cbmvax!phillip From: phillip@cbmvax.UUCP Newsgroups: comp.sys.amiga Subject: A program to monitor AmigaDOS packet activity. Message-ID: <1599@cbmvax.cbmvax.cbm.UUCP> Date: Mon, 30-Mar-87 11:24:33 EST Article-I.D.: cbmvax.1599 Posted: Mon Mar 30 11:24:33 1987 Date-Received: Tue, 31-Mar-87 06:34:35 EST Distribution: comp Organization: Commodore Technology, West Chester, PA Lines: 717 [yeah, bugs come and go, but COBOL insists on staying...] In the process structure you will find a field labeled "pr_PktWait." This is a pointer for a alternate wait routine for AmigaDOS message handling. Everytime the AmigaDOS taskwait() routine is called a check is made to see if the process PktWait field is non-zero...if non-zero a subroutine call is made to that address. The requirement of the subroutine is to wait for a message to arrive at the process port (pr_MsgPort) and to return the address of the message (NOT PACKET!) in D0. Anyway, what follows is a simple program that will allow you to monitor any process for packet activity. A binary is available for the asking. (uuencoded) BTW, When you call a AmigaDOS routine [like Read()] that talks to a AmigaDOS handler you can monitor a process receiving packets. -phil [ I promise this time no two signatures ] ============================================================================== Phillip Lindsay - Commodore Business Machines - Amiga Technical Support UUCP: {ihnp4|seismo|caip}!cbmvax!phillip - Phone: (215) 431-9180 No warranty is implied or otherwise given in the form of suggestion or example. Any opinions found here are of my making. /* eof */ --------------ok...SA take out your blade and slice here---------------------- #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # makefile # monproc.c # getprocs.c # givepkt.c # This archive created: Mon Mar 30 10:11:06 1987 export PATH; PATH=/bin:$PATH echo shar: extracting "'makefile'" '(220 characters)' if test -f 'makefile' then echo shar: will not over-write existing file "'makefile'" else sed 's/^ X//' << \SHAR_EOF > 'makefile' X# monproc - mointor process packet activity X# X# X XCFLAGS = +l -dMANX X XOBJS = monproc.o getprocs.o givepkt.o X Xall: $(OBJS) X ln -o monproc $(OBJS) -lc32 X Xmonproc: monproc.o X Xgetprocs: getprocs.o X Xgivepkt: givepkt.o X X# eof SHAR_EOF if test 220 -ne "`wc -c < 'makefile'`" then echo shar: error transmitting "'makefile'" '(should have been 220 characters)' fi fi # end of overwriting check echo shar: extracting "'monproc.c'" '(6161 characters)' if test -f 'monproc.c' then echo shar: will not over-write existing file "'monproc.c'" else sed 's/^ X//' << \SHAR_EOF > 'monproc.c' X/* monproc.c - monitor amigados process packet activity. X * X * Phillip Lindsay (c) 1987 Commodore-Amiga, Inc. X * X */ X X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X X#ifdef MANX X#include X#include X#else X#define index stpchr /* can you say "ANSI STANDARD"...I knew you could... */ X#include X#endif X X/* constants */ X X#define ONE 1L X X/* AmigaDOS uses task signal bit 8 for message signaling */ X#define DOS_SIGNAL 8 X#define DOS_MASK ( ONE << DOS_SIGNAL ) X X/* referenced globals */ Xextern void getprocs(),freeprocs(),givepkt(); Xvoid memfill(); Xextern struct DosLibrary *DOSBase; Xstruct Message *packetwait(); XLONG pw(); /* this the asm stub that calls packetwait() */ X X/* global data structures */ Xstruct MsgPort *deviceid; Xstruct Process *memyselfNi; XULONG mymask; Xstruct SignalSemaphore canreturn; Xstruct Message *mymess; X X Xmain() X{ X struct List procs; X struct Node *proc; X register struct Process *devproc; X register struct DosPacket *pkt; X BYTE mypri; X register ULONG waitmask,signals,oldpktwait; X LONG mysignal; X ULONG count,choice; X UBYTE processname[81]; X X puts("MONPROC - monitor AmigaDOS process packet activity.\n"); X X memyselfNi = (struct Process *) FindTask(NULL); X NewList(&procs); /* initialize list header */ X getprocs(&procs); /* fill list with "active" devices */ X X if(procs.lh_TailPred == &procs) /* list empty (should never happen) */ X { X puts("No processes."); X exit(0); X } X X/* X * I am assuming that process list won't change. This is for hackers only. X */ X do X { X puts("Enter NUMBER for process to monitor:"); X puts("Pick# Process MsgPort Name"); X for(count = 1,proc = procs.lh_Head;proc->ln_Succ;proc=proc->ln_Succ,count++) X printf("%4ld. %08lx %08lx %s\n",count, X ((struct Process *)proc->ln_Name), X &(((struct Process *)proc->ln_Name)->pr_MsgPort), X ((struct Process *)proc->ln_Name)->pr_Task.tc_Node.ln_Name); X printf("\nNUMBER: "); X fflush(stdout); X } while( scanf("%ld",&choice) == EOF ) ; X X X if(!choice || choice >= count) X { X puts("Operation aborted."); X freeprocs(&procs); X exit(0); X } X X/* what did he/she pick? */ X for(count = 1,proc = procs.lh_Head;proc->ln_Succ;proc=proc->ln_Succ,count++) X if(choice == count) X { X devproc = (struct Process *) proc->ln_Name; X break; X } X X/* we don't need our process list anymore */ X freeprocs(&procs); X X/* make a copy of the process name */ X strcpy(processname,devproc->pr_Task.tc_Node.ln_Name); X X/* get process msgport of process we will be monitoring */ X deviceid = &devproc->pr_MsgPort; X X/* grab a signal for task intercommunication */ X mysignal = (LONG) AllocSignal(-1L); X if(mysignal == -1) X { X puts("Can't allocate a task signal."); X exit(0); X } X X mymask = ONE << mysignal; X X waitmask = SIGBREAKF_CTRL_C | mymask; X X/* initialize our semaphore */ X memfill(&canreturn,(ULONG)sizeof(canreturn),0L); X InitSemaphore(&canreturn); X X Forbid(); X mypri = devproc->pr_Task.tc_Node.ln_Pri; X Permit(); X X/* make sure our priority is greater than the device task */ X SetTaskPri(memyselfNi, (ULONG)(mypri+1) ); X X puts("Waiting for messages...[CTRL_C to quit monitoring...]"); X X /* install our packet wait function */ X Forbid(); X oldpktwait = (ULONG) devproc->pr_PktWait; X devproc->pr_PktWait = (APTR) pw; X Permit(); X X/* X * I am using semaphores to control the monitoring of the handler's packets. X * There is probably a hundred better ways of doing this. I just went with X * what first came to mind. Since I am a higher priority than the handler... X * Once I am awake I will obtain the semaphore before the lower priority X * task has a chance...I will give it back to him once I am done with the X * packet data structure. X */ Xdo X { X X signals = (ULONG) Wait(waitmask); X ObtainSemaphore(&canreturn); X X if(signals & mymask) /* did the packetwait code signal us? */ X { /* yes, let's boogie... */ X pkt = (struct DosPacket *) mymess->mn_Node.ln_Name; /* get packet address */ X printf("%s: ",processname); X givepkt(pkt); X } X X ReleaseSemaphore(&canreturn); X X } while(!(signals & SIGBREAKF_CTRL_C)); X X /* remove our packet wait function and install previous value */ X Forbid(); X devproc->pr_PktWait = (APTR) oldpktwait; X Permit(); X SetTaskPri(memyselfNi,0L); X puts("\nThere is no safe way to leave since the process is waiting in"); X puts("our installed code. We have de-installed ourselves, but you should"); X puts("be certain that the process received a packet AFTER we have been"); X puts("de-installed. Press CTRL-E if you are certain this has happened."); X Wait(SIGBREAKF_CTRL_E); X FreeSignal(mysignal); X puts("All done."); X X} /* end of main() */ X X X/** X ** local subroutines X **/ X X/* X * packetwait() ... Waits for a message to arrive at your port and X * returns it to you. X */ Xstruct Message *packetwait() X{ X#ifdef MANX /* if MANX make sure we can see our data */ X geta4(); X#endif X /* wait for packet */ X SetSignal(FALSE,DOS_MASK); /* clear sigbit 8 */ X while( !(mymess = (struct Message *) GetMsg(deviceid)) ) Wait(DOS_MASK); X Signal(memyselfNi,mymask); /* Wake up monitoring task he will grab the data */ X ObtainSemaphore(&canreturn); /* we get this guy when we CAN return */ X ReleaseSemaphore(&canreturn); X X return(mymess); X} X X/* X * memfill() - fill memory with supplied byte value for "size" bytes X */ Xvoid memfill(source,size,value) XUBYTE *source; XULONG size; XUBYTE value; X{ X register UBYTE *msource=source, X mvalue=value; X register ULONG msize=size; X X if(msize) X { X do X { X --msize; X msource[msize] = mvalue; X } while(msize); X X } X} X X/* X * This code stub has been known to save lives... X */ X X#if MANX X#asm X XREF _packetwait X X XDEF _pw X_pw: X movem.l a2/a3/a4,-(sp) X jsr _packetwait X movem.l (sp)+,a2/a3/a4 X rts X#endasm X#endif X X/* end of procdev.c */ SHAR_EOF if test 6161 -ne "`wc -c < 'monproc.c'`" then echo shar: error transmitting "'monproc.c'" '(should have been 6161 characters)' fi fi # end of overwriting check echo shar: extracting "'getprocs.c'" '(3659 characters)' if test -f 'getprocs.c' then echo shar: will not over-write existing file "'getprocs.c'" else sed 's/^ X//' << \SHAR_EOF > 'getprocs.c' X/* getprocs.c - Grab all available processes and return them to you in a X * simple exec list. The list is made up of nodes--the "name" X * fields pointing to the process structure. X * X * Phillip Lindsay (c) 1987 Commodore-Amiga Inc. X * You may use this source as long as the copyright notice is left intact. X */ X X#include X#include X#include X#include X#include X#include X#include X#include X#include X X#ifdef MANX X#include X#include X#else X#include X#endif X X/* getnode() will allocate a node structure for you. And initialize the node X * structure with the given values. X */ Xstruct Node *getnode(name,type,pri) Xchar *name; XUBYTE type,pri; X{ X register struct Node *mynode; X X mynode = (struct Node *) X AllocMem((ULONG)sizeof(*mynode),MEMF_PUBLIC | MEMF_CLEAR); X X if(!mynode) return((struct Node *)NULL); X X mynode->ln_Name = name; X mynode->ln_Type = type; X mynode->ln_Pri = pri; X X return(mynode); X} X X/* freenode() frees a given Exec node. X * Make sure you remove node from any list. X */ Xvoid freenode(mynode) Xstruct Node *mynode; X{ X FreeMem(mynode,(ULONG)sizeof(*mynode)); X} X X X/* getprocs() will grab all processes in the system task's list and X * append an exec node to a given list. The node name field filled X * with a pointer to the process strcuture. X * WARNING: This isn't a casual subroutine. The returned list is valid as X * long as a process is not ended or added after this subroutine is X * called. To be real safe you should probably check to see if the X * process is still around before trying to look at the data structure. X */ Xvoid getprocs(plist) Xstruct List *plist; /* passed a pointer to a initialized exec list */ X{ X extern struct ExecBase *SysBase; X register struct ExecBase *execbase=SysBase; X register struct List *proclist; X register struct Node *aproc,*bproc; X register USHORT count=0; X X/* I haven't clocked this code, but you shouldn't as a rule stay disabled for X * no more than 250ms. I'm have no doubt I'm illegal, but you can't be X * too safe when dealing with something that changes with a blink of a X * interrupt. X */ X X Disable(); X X/* first we deal with ourselves... */ X if(execbase->ThisTask->tc_Node.ln_Type == NT_PROCESS) X { X if((bproc=getnode(execbase->ThisTask,0,0))) X { X AddTail(plist,bproc); X } X } X X/* hopefully the added braces make the flow clear */ X for(;count <= 1;count++) X { X if(!count) X proclist = &execbase->TaskReady; X else X proclist = &execbase->TaskWait; X X if(proclist->lh_TailPred != proclist) X { X for(aproc = proclist->lh_Head;aproc->ln_Succ;aproc=aproc->ln_Succ) X { X if(aproc->ln_Type == NT_PROCESS) X { X if((bproc=getnode(aproc,0,0))) X { X AddTail(plist,bproc); X } X } X } X } X } X X Enable(); X X} /* end of getprocs() */ X X X/* freeprocs() will free all nodes in a given list. Function assumes nodes where X * initialized with getnode(). X */ Xvoid freeprocs(plist) Xstruct List *plist; X{ X register struct Node *proc; X X while((proc=RemTail(plist))) X freenode(proc); X} X X/* Xmain() X { X struct List procs; X struct Node *proc; X X NewList(&procs); ** Initialize list header ** X getprocs(&procs); ** Fill list ** X X ** print any processess in list.... if any ** X if(procs.lh_TailPred != &procs) X for(proc = procs.lh_Head;proc->ln_Succ;proc=proc->ln_Succ) X puts( ((struct Process *)proc->ln_Name)->pr_Task.tc_Node.ln_Name ); X X freeprocs(&procs); X } X X*/ X SHAR_EOF if test 3659 -ne "`wc -c < 'getprocs.c'`" then echo shar: error transmitting "'getprocs.c'" '(should have been 3659 characters)' fi fi # end of overwriting check echo shar: extracting "'givepkt.c'" '(4342 characters)' if test -f 'givepkt.c' then echo shar: will not over-write existing file "'givepkt.c'" else sed 's/^ X//' << \SHAR_EOF > 'givepkt.c' X/* givepkt.c - This doesn't do much, it takes a packet type (number) and X * gives you something more readable on stdout. X * X * Phillip Lindsay (c) 1987 Commodore-Amiga Inc. X * You may use this source as long as the copyright notice is left intact. X * X */ X X#include X#include X X/* packet types */ X#define _ACTION_NIL 0L X#define _ACTION_GET_BLOCK 2L X#define _ACTION_SET_MAP 4L X#define _ACTION_DIE 5L X#define _ACTION_EVENT 6L X#define _ACTION_CURRENT_VOLUME 7L X#define _ACTION_LOCATE_OBJECT 8L X#define _ACTION_RENAME_DISK 9L X#define _ACTION_FREE_LOCK 15L X#define _ACTION_DELETE_OBJECT 16L X#define _ACTION_RENAME_OBJECT 17L X#define _ACTION_MORE_CACHE 18L X#define _ACTION_COPY_DIR 19L X#define _ACTION_WAIT_CHAR 20L X#define _ACTION_SET_PROTECT 21L X#define _ACTION_CREATE_DIR 22L X#define _ACTION_EXAMINE_OBJECT 23L X#define _ACTION_EXAMINE_NEXT 24L X#define _ACTION_DISK_INFO 25L X#define _ACTION_INFO 26L X#define _ACTION_FLUSH 27L X#define _ACTION_SET_COMMENT 28L X#define _ACTION_PARENT 29L X X/* This is normally a returning timer device request. (internal) */ X#define _ACTION_TIMER 30L X X#define _ACTION_INHIBIT 31L X#define _ACTION_DISK_TYPE 32L X#define _ACTION_DISK_CHANGE 33L X#define _ACTION_SET_FILE_DATE 34L X#define _ACTION_READ 82L X#define _ACTION_WRITE 87L X#define _ACTION_SET_SCREEN_MODE 994L X/* X * When a handler internally sends a device i/o request they are sent using X * their process port and in the form of a "packet" the packet types below: X * (ACTION_TIMER above also falls into this catagory) X */ X#define _ACTION_READ_INTERNAL 1001L X#define _ACTION_WRITE_INTERNAL 1002L X X#define _ACTION_FIND_INPUT 1005L X#define _ACTION_FIND_OUTPUT 1006L X#define _ACTION_CLOSE 1007L X#define _ACTION_SEEK 1008L X Xvoid givepkt(pkt) Xstruct DosPacket *pkt; X{ X switch(pkt->dp_Type) X { X case _ACTION_NIL: X puts("ACTION_NIL"); X break; X X case _ACTION_GET_BLOCK: X puts("ACTION_GET_BLOCK"); X break; X X case _ACTION_SET_MAP: X puts("ACTION_SET_MAP"); X break; X X case _ACTION_DIE: X puts("ACTION_DIE"); X break; X X case _ACTION_EVENT: X puts("ACTION_EVENT"); X break; X X case _ACTION_CURRENT_VOLUME: X puts("ACTION_CURRENT_VOLUME"); X break; X X case _ACTION_LOCATE_OBJECT: X puts("ACTION_LOCATE_OBJECT"); X break; X X case _ACTION_RENAME_DISK: X puts("ACTION_RENAME_DISK"); X break; X X case _ACTION_FREE_LOCK: X puts("ACTION_FREE_LOCK"); X break; X X case _ACTION_DELETE_OBJECT: X puts("ACTION_DELETE_OBJECT"); X break; X X case _ACTION_RENAME_OBJECT: X puts("ACTION_RENAME_OBJECT"); X break; X X case _ACTION_MORE_CACHE: X puts("ACTION_MORE_CACHE"); X break; X X case _ACTION_COPY_DIR: X puts("ACTION_COPY_DIR"); X break; X X case _ACTION_WAIT_CHAR: X puts("ACTION_WAIT_CHAR"); X break; X X case _ACTION_SET_PROTECT: X puts("ACTION_SET_PROTECT"); X break; X X case _ACTION_CREATE_DIR: X puts("ACTION_CREATE_DIR"); X break; X X case _ACTION_EXAMINE_OBJECT: X puts("ACTION_EXAMINE_OBJECT"); X break; X X case _ACTION_EXAMINE_NEXT: X puts("ACTION_EXAMINE_NEXT"); X break; X X case _ACTION_DISK_INFO: X puts("ACTION_DISK_INFO"); X break; X X case _ACTION_INFO: X puts("ACTION_INFO"); X break; X X case _ACTION_FLUSH: X puts("ACTION_FLUSH"); X break; X X case _ACTION_SET_COMMENT: X puts("ACTION_SET_COMMENT"); X break; X X case _ACTION_PARENT: X puts("ACTION_PARENT"); X break; X X case _ACTION_TIMER: X puts("ACTION_TIMER"); X break; X X case _ACTION_INHIBIT: X puts("ACTION_INHIBIT"); X break; X X case _ACTION_DISK_TYPE: X puts("ACTION_DISK_TYPE"); X break; X X case _ACTION_DISK_CHANGE: X puts("ACTION_DISK_CHANGE"); X break; X X case _ACTION_SET_FILE_DATE: X puts("ACTION_SET_FILE_DATE"); X break; X X case _ACTION_READ: X puts("ACTION_READ"); X break; X X case _ACTION_WRITE: X puts("ACTION_WRITE"); X break; X X case _ACTION_SET_SCREEN_MODE: X puts("ACTION_SET_SCREEN_MODE"); X break; X X case _ACTION_READ_INTERNAL: X puts("ACTION_READ_INTERNAL"); X break; X X case _ACTION_WRITE_INTERNAL: X puts("ACTION_WRITE_INTERNAL"); X break; X X case _ACTION_FIND_INPUT: X puts("ACTION_FIND_INPUT"); X break; X X case _ACTION_FIND_OUTPUT: X puts("ACTION_FIND_OUTPUT"); X break; X X case _ACTION_CLOSE: X puts("ACTION_CLOSE"); X break; X X case _ACTION_SEEK: X puts("ACTION_SEEK"); X break; X X default: X printf("Unknown packet: %ld\n",pkt->dp_Type); X break; X } X} X X/* end of givepkt.c */ SHAR_EOF if test 4342 -ne "`wc -c < 'givepkt.c'`" then echo shar: error transmitting "'givepkt.c'" '(should have been 4342 characters)' fi fi # end of overwriting check # End of shell archive exit 0