[net.micro.amiga] stat.c

james@uw-atm.UUCP (James M Synge) (09/03/86)

I have been trying to figure out some of the dark, hidden secrets of AmigaDOS
and my poking around has lead to the following program to replace STATUS.
I like it because it tells me a lot more than STATUS.

---------------------------------------------------------------------------
James M Synge, Department of Atmospheric Sciences, University of Washington
VOX: 1 206 543 0308 (Work)   1 206 455 2025 (Home)
UUCP: uw-beaver!geops!uw-atm!james (prefered)   OR  uw-beaver!uw-june!james
ARPA: james@washington.arpa (Till September)   james@june.cs.washington.edu


#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar:    Shell Archiver
#	Run the following text with /bin/sh to create:
#	README
#	stat.c
# This archive created: Tue Sep  2 22:59:33 1986
sed 's/^X//' << \SHAR_EOF > README
XSTAT is a replacement for the AmigaDOS command STATUS.  It is far more
Xinformative about the processes then the current command.  For each AmigaDOS
Xprocess, it prints the Task number, Priority, the Address of the process in
Xmemory, the Command line being executed, and the current Directory.
X
XBelow is an example:
X
X1> run stat > ram:d
XTask Pri  Address Command			   Directory
X  1    0     97b0 run stat > ram:d                 df1:stat
X  2   -5    1af88 stat                             df1:stat
X
XGood luck, and send me a message if you find any bugs.
X
XJames M Synge    (206) 543-0308 at Work
XUUCP: uw-beaver!geops!uw-atm!james
SHAR_EOF
sed 's/^X//' << \SHAR_EOF > stat.c
X/* stat.c An enhanced version of the AmigaDOS command STATUS.
X *
X * Copyright 1986 by James M Synge. Sept. 2, 1986.
X * Permission is granted for unlimited non-commercial use.
X *
X * Compiled using Aztec C, but it shouldn't be that hard to change
X * for Lattice C ;^)
X *
X * The makefile file is very short:
X *------------------------------
X *  stat: stat.o
X *	ln -v stat.o -lc
X *------------------------------
X * UUCP: uw-beaver!geops!uw-atm!james
X */
X
X#include <exec/types.h>
X#include <exec/memory.h>
X#include <exec/tasks.h>
X
X#include <libraries/dosextens.h>
X
Xchar buf1[32], buf2[32];
X
X/* DOSBase is already set up (by _main?) */
Xextern struct DosLibrary *DOSBase;
X
X/* Need a macro to translate a BPTR to an APTR */
X#ifdef BADDR
X#undef BADDR
X#endif
X#define BADDR(bptr) (((long)bptr) << 2)
X
X/* By experimentation I determined that the command line arguments are */
X/* located at (tc_SPLower + 0x280).  This may change in the future. */
X/* If STAT starts printing garbage for the args, just comment out this: */
X#define ARGS_OFFSET 0x280
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	int i, tasknum, pri, strncmp(); char *msg, *index();
X	long process, processes, *ta;
X	struct Process *pr;
X	struct RootNode *rn;
X	struct CommandLineInterface *cli;
X	
X	/* Find the RootNode */
X	rn = (struct RootNode *)(DOSBase->dl_Root);
X
X	/* ta points to the array of tasks. The first location is the */
X	/* maximum number of processes, followed by that many pointers. */
X	/* Each pointer points to the MsgPort within the Process data */
X	/* structure of each AmigaDos process, otherwise its value is 0L. */
X	/* The AmigaDOS Technical Reference Manual calls these pointers */
X	/* process ids. */	
X
X	ta = (long *) BADDR(rn->rn_TaskArray);
X
X	/* How many AmigaDOS processes are there? */
X
X	processes = *ta++;
X
X	/* Print the title line. */
X	printf("Task Pri  Address Command\t\t\t   Directory\n");
X
X	/* Loop through each live process, printing info. */
X
X	for (process = 0; process < processes; process++ ) {
X
X		/* Get the next process id (i.e. struct MsgPort *) */
X		msg = (char *)(*ta++);
X		if (!msg) continue; /* No associated Process? */
X
X		/* Pointer to struct Process */
X 		pr = (struct Process *)(msg - sizeof(struct Task));
X
X		/* CLIs have small positive task numbers */
X		tasknum = (int)(pr->pr_TaskNum);
X
X		/* The priority of the task is in the Node structure */
X		pri = (int)(pr->pr_Task.tc_Node.ln_Pri);
X
X		cli = (struct CommandLineInterface *) BADDR(pr->pr_CLI);
X
X		if (cli) {
X		    moveBSTR(cli->cli_CommandName, buf1, 32);
X		    if (!buf1[0]) strcpy(buf1, "Waiting for a command");
X#ifdef ARGS_OFFSET
X		    else {
X			msg = (char *)(pr->pr_Task.tc_SPLower) + ARGS_OFFSET;
X			if (*msg && *msg != '\n') {
X			    strncat(buf1, " ", 32);
X			    strncat(buf1, msg, 32);
X			    msg = index(buf1, '\n');  /* Look for a \n */
X			    if (msg) *msg = '\0';
X			}
X		    }
X#endif
X		    moveBSTR(cli->cli_SetName, buf2, 32);
X		} else {
X			strcpy(buf1, "Not a CLI");
X			buf2[0] = 0;
X		}
X
X		printf("%3d %4d %8lx %-32s %s\n",
X			tasknum, pri, pr, buf1, buf2);
X	}
X	exit(0);
X}
X
X/* moveBSTR copies a BSTR to a C char string. */
XmoveBSTR(bptr, buffer, maxlen)
XBSTR bptr;
Xchar *buffer;
Xint maxlen; /* size of buffer[] */
X{
X	register char *ptr;
X	register unsigned int len, i;
X	unsigned char l;	
X
X	ptr = (char *) BADDR(bptr); /* Make a char* to the length */
X
X	l = (unsigned int) (*ptr++); /* Get the length and increment ptr */
X
X	if (!(len = l)) {
X		*buffer = '\0'; /* Mark the end of the string. */
X		return;
X	}
X	if (len > maxlen) len = maxlen;
X	for(i = 0; i < len; i++) *buffer++ = *ptr++; /* Copy it. */
X
X	if (i < maxlen) *buffer = '\0'; /* If there is room, mark the end */
X	return;
X}
X
SHAR_EOF
#	End of shell archive
exit 0