home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <libraries/dos.h>
- #include <libraries/dosextens.h>
- #include <exec/memory.h>
- #include <exec/tasks.h>
-
- /*
- * P S : Like the UN*X command of the same name, this reports on
- * running processes in the system. The current version only
- * reports CLI processes, so you don't see the filesystem
- * tasks. Written because I got tired of seeing the question
- * marks that status spits out at every opportunity.
- * This will build OK with 16 bit integers.
- *
- * Usage: ps [-f]
- *
- * Author: Dewi Williams ..!ihnp4!druca!dewi
- * Status: Public domain.
- */
-
- /* Defines */
-
- /* Change typeless BCPL BPTR to typed C (for struct pointers). Don't
- * use this define on an APTR, that's only a badly disguised void *.
- */
- #define BPTR_TO_C(strtag, var) ((struct strtag *)(BADDR( (ULONG) var)))
-
- /* Use AmigaDOS i/o to keep executable size down */
- #define WSTR(s) (void)Write(OutLock, s, (long)strlen(s))
- #define WCHR(s) (void)Write(OutLock, s, 1L) /* char w/ d. quotes */
-
- #define TO_ASC(n) ((n) + '0') /* make it printable! */
-
- /* Casting conveniences */
- #define PROC(task) ((struct Process *)task)
- #define ROOTNODE ((struct RootNode *)DOSBase->dl_Root)
- #define CLI(proc) (BPTR_TO_C(CommandLineInterface, proc->pr_CLI))
-
- /* Externs */
- extern struct DosLibrary *DOSBase; /* dos library base pointer */
- extern struct FileLock *Output(); /* get output file handle */
-
- /* Globals */
- static struct FileLock *OutLock; /* used by WSTR define */
- static int fullopt = 0; /* set by -f command line flag */
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- register ULONG *tt; /* References TaskArray */
- register int count; /* loop variable */
- register UBYTE *port; /* msgport & ptr arith */
- register struct Task *task; /* EXEC descriptor */
- char strbuf[256]; /* scratch for btocstr() */
- char *btocstr(); /* BCPL BSTR to ASCIIZ */
- void disp_hdr(); /* display ps header */
- void display(); /* display data for one process */
-
- OutLock = Output(); /* initialize output handle */
-
- if (argc > 1 && strcmp(argv[1], "-f") == 0) fullopt = 1;
-
- tt = (unsigned long *)(BADDR(ROOTNODE->rn_TaskArray));
-
- if (fullopt) disp_hdr();
-
- Forbid(); /* need linked list consistency */
-
- /* Loop through the data for the CLI processes. */
- for (count = 1; count <= (int)tt[0] ; count++) {/* or just assume 20?*/
- if (tt[count] == 0) continue; /* nobody home */
-
- /* Start by pulling out MsgPort addresses from the TaskArray
- * area. By making unwarranted assumptions about the layout
- * of Process and Task structures, we can derive these
- * descriptors. Every task has an associated process, since
- * this loop drives off a CLI data area.
- */
-
- port = (UBYTE *)tt[count];
- task = (struct Task *)(port - sizeof(struct Task));
-
- /* Sanity check just in case */
- if (PROC(task)->pr_TaskNum == 0 || PROC(task)->pr_CLI == NULL)
- continue; /* or complain? */
-
- /* Pass the C string version of the command name to
- * the display routine.
- */
- display(count, task->tc_Node.ln_Name,
- btocstr(CLI(PROC(task))->cli_CommandName, strbuf),
- task->tc_Node.ln_Pri);
- }
- Permit(); /* outside critical region */
- exit(0);
- }
-
- /*
- * Convert a BCPL string to a C string. To avoid scrogging in-memory
- * stuff, it copies it first. Your data area better be big enough!
- */
-
- char *
- btocstr(b, buf)
- ULONG b;
- char *buf;
- {
- register char *s;
-
- s = (char *)BADDR(b); /* Shift & get length-prefixed str */
- (void)movmem(s +1, buf, s[0]); /* a.k.a memcpy */
- buf[s[0]] = '\0';
- return buf;
- }
-
- /*
- * Display the header for the output.
- */
-
- void
- disp_hdr()
- {
- WSTR("Process # CLI Type Command Name Priority\n");
- }
-
- /*
- * Display the information for a particular CLI process. Keep the format
- * string in sync with that of disp_hdr().
- */
-
- void
- display(tnum, type, name, pri)
- int tnum; /* CLI process number */
- char *type; /* Initial, Background or New CLI */
- char *name; /* Command name if CLI's running one */
- int pri; /* priority of CLI & command */
- {
- char *psitoa();
- char buf[80];
- char *ext_len();
- register char *p = buf;
-
- if (*name == '\0') name = "<Cli>"; /* Null, nothing loaded */
-
- if (fullopt) {
- p = ext_len(psitoa(tnum, p), 11);
- strcpy(p, type);
- p = ext_len(p, 17);
- strcpy(p, name);
- p = ext_len(p, 21);
- (void)psitoa(pri, p);
- } else {
- p = ext_len(psitoa(tnum, p), 2);
- *p++ = ':';
- *p++ = ' ';
- strcpy(p, name);
- }
-
- WSTR(buf);
- WCHR("\n");
- }
-
- /*
- * Everything after here is a hack to avoid dragging in printf.
- * ------------------------------------------------------------
- */
-
- /*
- * Limited itoa style function. Don't use it anywhere else! Used to keep
- * things small & avoid printf. Has a very limited range (3 digits +/- sign).
- * This hack avoids having to do the recursion & reverse of K&R itoa.
- */
-
- char *
- psitoa(num, into)
- int num; /* number to convert */
- char *into; /* write it into here */
- {
- register char *p = into;
-
- if (num < 0) {
- *p++ = '-';
- num = -num;
- }
- if (num > 99) {
- *p++ = TO_ASC(num/100);
- *p++ = TO_ASC((num%100)/10);
- *p++ = TO_ASC(num%10);
- } else if (num > 9) {
- *p++ = TO_ASC(num/10);
- *p++ = TO_ASC(num%10);
- } else
- *p++ = TO_ASC(num);
-
- *p = '\0'; /* end of the string */
- return into;
- }
-
- /*
- * Extend to length. Assumes strlen(s) never greater than len.
- */
-
- char *
- ext_len(s, len)
- char *s; /* must be large enough for extension to len */
- int len;
- {
- register int leftover;
- register int slen = strlen(s);
- register char *p = s + slen;
-
- for(leftover = len - slen; leftover > 0; leftover--)
- *p++ = ' ';
-
- *p = '\0'; /* null terminate */
- return p; /* return loc after string */
- }
-