/* * ps.c - a program to print MiNT process statuses * * Based on the original ps by Tony Reynolds, cctony@sgisci1.ocis.olemiss.edu, * and updated by Eric Smith and Allan Pratt. * For use with MiNT release 0.9. * Compiles with my port of the MiNTlib to Sozobon 2.0, as well as the GCC. * * $Log: ps.c,v $ * Revision 0.9 1992/01/15 21:48:22 sozobon * dpg's first version. * Uses opendir rather than Fsfirst/next. * Print owner information, rather than parent process id. * */ static char *proc = "$Id: ps.c,v 0.9 1992/01/15 21:48:22 sozobon Exp sozobon $"; #include #include #include #include #include #include #include #include #include #include #define PROCDIR "u:/proc" #define ulong unsigned long #define ushort unsigned short extern int __mint; /* The following structures are taken from proc.h in the MiNT kernel. */ /* a process context consists, for now, of its registers */ typedef struct _context { long regs[15]; /* registers d0-d7, a0-a6 */ long usp; /* user stack pointer (a7) */ short sr; /* status register */ long pc; /* program counter */ long ssp; /* supervisor stack pointer */ long term_vec; /* GEMDOS terminate vector (0x102) */ char fstate[216]; /* FPU internal state */ char fregs[12*8]; /* registers fp0-fp7 */ long fctrl[3]; /* FPCR/FPSR/FPIAR */ short sfmt; /* stack frame format identifier */ long iar; /* instruction address */ short internal[4]; /* four words of internal info */ } CONTEXT; #define PROC_CTXTS 2 typedef struct proc { /* this is stuff that the public can know about */ /* NOTE: some assembly code (in intr.s and contxt.s) makes * assumptions about the offsets of sysstack, ctxt[0], systime, * and usrtime. */ long sysstack; /* must be first */ CONTEXT ctxt[PROC_CTXTS]; /* must be second */ long magic; /* validation for proc struct */ char *base; /* process base page */ short pid, ppid, pgrp; short ruid; /* process real user id */ short rgid; /* process real group id */ short euid, egid; /* effective user and group ids */ ushort memflags; /* e.g. malloc from alternate ram */ short pri; /* base process priority */ short wait_q; /* current process queue */ long wait_cond; /* condition we're waiting on */ /* (also return code from wait) */ /* (all times are in milliseconds) */ ulong systime; /* time spent in kernel */ ulong usrtime; /* time spent out of kernel */ ulong chldstime; /* children's kernel time */ ulong chldutime; /* children's user time */ ulong maxmem; /* max. amount of memory to use */ ulong maxdata; /* max. data region for process */ ulong maxcore; /* max. core memory for process */ ulong maxcpu; /* max. cpu time to use */ short domain; /* process domain (TOS or UNIX) */ short curpri; /* current process priority */ #define MIN_NICE -20 #define MAX_NICE 20 } PROC; /* different process queues */ #define CURPROC_Q 0 #define READY_Q 1 #define WAIT_Q 2 #define IO_Q 3 #define ZOMBIE_Q 4 #define TSR_Q 5 #define STOP_Q 6 #define SELECT_Q 7 #define NUM_QUEUES 8 struct status { char mint; char desc; } proc_stat[NUM_QUEUES + 1] = { CURPROC_Q, 'R', READY_Q, 'R', WAIT_Q, 'S', IO_Q, 'S', SELECT_Q, 'S', STOP_Q, 'T', ZOMBIE_Q, 'Z', TSR_Q, 'X', -1, '?' }; /* initialized from data in procfs.c */ void main(argc, argv) int argc; char **argv; { DIR *dirp; struct dirent *ent; struct stat info; int fd; int fserror; long place; short pid, ppid, pri, curpri; char *s, username[9]; struct status *statp; BASEPAGE bpage; /* process basepage read in here if possible */ PROC proc; /* process info read in here */ long ptime; long hour, min, sec, frac; struct passwd *pwent; if (chdir(PROCDIR) || !(dirp = opendir("."))) { perror(PROCDIR); return 1; } printf("USER PID PRI/CUR STAT SIZE TIME COMMAND\n"); username[8] = '\0'; while (ent = readdir(dirp)) { if ((fd = open(ent->d_name, 0)) < 0 || fstat(fd, &info)) goto next; /* Should really copy the name elsewhere. */ for (s = ent->d_name; *s && *s != '.'; s++); *s = '\0'; ioctl(fd, PPROCADDR, &place); lseek(fd, place, 0); read(fd, &proc, sizeof(proc)); if (pwent = getpwuid(proc.ruid)) strncpy(username, pwent->pw_name, 8); else strcpy(username, "??user??"); ptime = proc.systime + proc.usrtime; hour = (ptime / 1000 / 60 / 60); min = (ptime / 1000 / 60) % 60; sec = (ptime / 1000) % 60; frac = (ptime % 1000) / 10; /* (never anything in .00x digit) */ ioctl(fd, PBASEADDR, &place); lseek(fd, place, 0); read(fd, &bpage, sizeof(bpage)); if (*bpage.p_cmdlin) *bpage.p_cmdlin = ' '; close(fd); statp = proc_stat; /* hunt down string referring to process * status */ while (statp->mint != proc.wait_q && statp->mint >= 0) statp++; printf("%-8s %03d %3d/%3d %c %c ", username, proc.pid, proc.pri, proc.curpri, statp->desc, proc.pri < 0 ? 'N' : proc.pri > 0 ? '<' : ' '); if (info.st_size > 1000000L) printf("%3ldM ", info.st_size / 1000000L); else if (info.st_size > 1000L) printf("%3ldk ", info.st_size / 1000L); else printf("%3ld ", info.st_size); if (hour) printf("%02ld:%02ld:%02ld", hour, min, sec); else printf("%02ld:%02ld.%02ld", min, sec, frac); printf(" %s%s\n", ent->d_name, bpage.p_cmdlin); next: } closedir(dirp); endpwent(); return 0; }