|
|
researchv8 Dan Cross
/*
* ps; VAX 4BSD version
*/
#include <stdio.h>
#include <ctype.h>
#include <nlist.h>
#include <pwd.h>
#include <sys/param.h>
#include <sys/tty.h>
#include <sys/dir.h>
#include <sys/user.h>
#include <sys/proc.h>
#include <sys/pte.h>
#include <sys/vm.h>
#include <sys/text.h>
#include <sys/stat.h>
#include <math.h>
#include <sys/vlimit.h>
#include <sys/inode.h>
#include <sys/file.h>
#define vprintf if (vflg) printf
#define WD -1
#define TEXT -2
int pcbpf, nswap, kmem, mem, swap, uid, pid;
int uflg, fflg, inum, Mdev, mdev, special, vflg, nproc, pflg;
char *uname;
struct nlist nl[] = {
{ "_proc" },
#define X_PROC 0
{ "_Usrptmap" },
#define X_USRPTMA 1
{ "_usrpt" },
#define X_USRPT 2
{ "_nswap" },
#define X_NSWAP 3
{ "_nproc" },
#define X_NPROC 4
{ 0 },
};
struct proc proc[8], *mproc; /* 8 = a few, for less syscalls */
struct pte *Usrptma, *usrpt;
int paduser1; /* avoid hardware mem clobbering botch */
union {
struct user user;
char upages[UPAGES][NBPG];
} user;
int paduser2; /* avoid hardware mem clobbering botch */
#define u user.user
char *kmemf, *memf, *swapf, *nlistf;
extern int errno;
main(argc, argv)
char **argv;
{
register int i, j;
off_t procp;
dev_t dev;
argv++;
while (--argc > 0) {
if (strcmp(*argv, "-v") == 0) {
vflg++;
argv++;
continue;
}
if (strcmp(*argv, "-u") == 0) {
if (uflg++)
usage();
if ((uid = getuname(*(++argv))) < 0) {
fprintf(stderr, "%s: unknown user\n", *argv);
exit(1);
}
--argc;
argv++;
continue;
}
if (strcmp(*argv, "-f") == 0) {
if (fflg++)
usage();
if ((dev = getfname(*(++argv))) < 0) {
perror(*argv);
exit(1);
}
--argc;
argv++;
continue;
}
if (strcmp(*argv, "-p") == 0) {
if (pflg++ || ((pid = Atoi(*(++argv))) <= 0)) {
usage();
perror(*argv);
exit(1);
}
--argc;
argv++;
continue;
}
/* admit missing -u, -f, -p */
/* it's an expert system! */
if ((pid = Atoi(*argv)) > 0) {
if (pflg++)
usage();
continue;
}
if (fflg && uflg)
usage();
if (uflg) {
/* it must be a file */
fflg++;
if ((dev = getfname(*argv)) < 0) {
perror(*argv);
exit(1);
}
argv++;
continue;
}
if (fflg) {
/* it must be a user */
uflg++;
if ((uid = getuname(*argv)) < 0) {
fprintf(stderr,
"%s: unknown user\n", *argv);
exit(1);
}
argv++;
continue;
}
/* !uflg && !fflg -- which is it? */
if ((dev = getfname(*argv)) >= 0)
fflg++; /* could be a file */
if ((uid = getuname(*argv)) >= 0)
uflg++; /* could be a user */
if ((!uflg ^ !fflg) == 0)
usage(); /* could be either/neither */
argv++;
continue;
}
if (fflg) {
Mdev = major(dev);
mdev = minor(dev);
}
if (chdir("/dev") < 0) {
perror("/dev");
exit(1);
}
printf("user\t\t pid\t fd major minor\tinode\n");
openfiles();
getkvars();
procp = getw((off_t) nl[X_PROC].n_value);
nproc = getw((off_t) nl[X_NPROC].n_value);
for (i=0; i<nproc; i += 8) {
lseek(kmem, (long) procp, 0);
j = nproc - i;
if (j > 8)
j = 8;
j *= sizeof (struct proc);
if (read(kmem, (char *) proc, j) != j)
cantread("proc table", kmemf);
procp += j;
for (j = j / sizeof (struct proc) - 1; j >= 0; j--) {
mproc = &proc[j];
if (mproc->p_stat == 0)
continue;
doproc();
}
}
exit(0);
}
long
getw(loc)
off_t loc;
{
long word;
lseek(kmem, (long) loc, 0);
if (read(kmem, (char *) &word, sizeof (word)) != sizeof (word))
vprintf("error reading kmem at %x\n", loc);
return (word);
}
openfiles()
{
kmemf = "kmem";
kmem = open(kmemf, 0);
if (kmem < 0) {
perror(kmemf);
exit(1);
}
memf = "mem";
mem = open(memf, 0);
if (mem < 0) {
perror(memf);
exit(1);
}
swapf = "drum";
swap = open(swapf, 0);
if (swap < 0) {
perror(swapf);
exit(1);
}
}
getkvars()
{
nlistf = "/unix";
nlist(nlistf, nl);
if (nl[0].n_type == 0) {
fprintf(stderr, "%s: No namelist\n", nlistf);
exit(1);
}
Usrptma = (struct pte *) nl[X_USRPTMA].n_value;
usrpt = (struct pte *) nl[X_USRPT].n_value;
lseek(kmem, (long) nl[X_NSWAP].n_value, 0);
if (read(kmem, (char *) &nswap, sizeof (nswap)) != sizeof (nswap)) {
cantread("nswap", kmemf);
exit(1);
}
}
cantread(what, fromwhat)
char *what, *fromwhat;
{
vprintf("fstat: error reading %s from %s", what, fromwhat);
}
doproc()
{
struct passwd *getpwuid();
if (uflg && mproc->p_uid != uid)
return;
if (pflg && mproc->p_pid != pid)
return;
if (mproc->p_stat != SZOMB && getu() == 0)
return;
uname = getpwuid(u.u_uid)->pw_name;
dotext();
getf();
}
getu()
{
struct pte *pteaddr, apte;
int pad1; /* avoid hardware botch */
struct pte arguutl[UPAGES+CLSIZE];
int pad2; /* avoid hardware botch */
register int i;
int ncl, size, argaddr;
size = sizeof (struct user);
if ((mproc->p_flag & SLOAD) == 0) {
lseek(swap, (long) ctob(mproc->p_swaddr), 0);
if (read(swap, (char *) &user.user, size) != size) {
vprintf("fstat: cant read u for pid %d from %s\n",
mproc->p_pid, swapf);
return (0);
}
pcbpf = 0;
argaddr = 0;
return (1);
}
pteaddr = &Usrptma[btokmx(mproc->p_p0br) + mproc->p_szpt - 1];
lseek(kmem, (long) pteaddr, 0);
if (read(kmem, (char *) &apte, sizeof(apte)) != sizeof(apte)) {
vprintf("fstat: can't read indir pte to get u for pid %d from %s\n",
mproc->p_pid, swapf);
return (0);
}
lseek(mem,
(long) ctob(apte.pg_pfnum+1) - (UPAGES+CLSIZE) * sizeof (struct pte), 0);
if (read(mem, (char *) arguutl, sizeof(arguutl)) != sizeof(arguutl)) {
vprintf("fstat: can't read page table for u of pid %d from %s\n",
mproc->p_pid, swapf);
return (0);
}
if (arguutl[0].pg_fod == 0 && arguutl[0].pg_pfnum)
argaddr = ctob(arguutl[0].pg_pfnum);
else
argaddr = 0;
pcbpf = arguutl[CLSIZE].pg_pfnum;
ncl = (size + NBPG*CLSIZE - 1) / (NBPG*CLSIZE);
while (--ncl >= 0) {
i = ncl * CLSIZE;
lseek(mem, (long) ctob(arguutl[CLSIZE+i].pg_pfnum), 0);
if (read(mem, user.upages[i], CLSIZE*NBPG) != CLSIZE*NBPG) {
vprintf("fstat: can't read page %d of u of pid %d from %s\n",
arguutl[CLSIZE+i].pg_pfnum, mproc->p_pid, memf);
return(0);
}
}
return (1);
}
#define NMAX 8
#define NUID 2048
dotext()
{
struct text text;
lseek(kmem, (long) mproc->p_textp, 0);
if (read(kmem, (char *) &text, sizeof(text)) != sizeof(text)) {
cantread("text table", kmemf);
return;
}
if (text.x_flag == 0)
return;
itrans(text.x_iptr, TEXT);
}
itrans(i, fno)
struct inode *i;
{
struct inode inode;
dev_t idev;
lseek(kmem, (long) i, 0);
if (read(kmem, (char *) &inode, sizeof(inode))
!= sizeof(inode)) {
vprintf("error %d reading inode at %x from kmem\n", errno, i);
return;
}
if (special)
idev = inode.i_dev;
else
idev = inode.i_dev;
if (fflg && major(idev) != Mdev)
return;
if (fflg && minor(idev) != mdev)
return;
if (inum && inode.i_number != inum)
return;
printf("%-16s%5d\t", uname, mproc->p_pid);
if (fno == WD)
printf(" wd");
else if (fno == TEXT)
printf("text");
else
printf("%4d", fno);
printf("\t%2d\t%2d\t%5d\n", major(inode.i_dev), minor(inode.i_dev),
inode.i_number);
}
getf()
{
int i;
struct file file;
itrans(u.u_cdir, WD);
for (i = 0; i < NOFILE; i++) {
if (u.u_ofile[i] == 0)
continue;
lseek(kmem, (long) u.u_ofile[i], 0);
if (read(kmem, (char *) &file, sizeof(file)) != sizeof(file)) {
cantread("file", kmemf);
continue;
}
itrans(file.f_inode, i);
}
}
usage()
{
fputs("usage: fstat [-u user] [-f filename] [-p pid]\n", stderr);
exit(1);
}
getuname(uname)
char *uname;
{
struct passwd *passwd, *getpwnam();
if ((passwd = getpwnam(uname)) == NULL)
return(-1);
return(passwd->pw_uid);
}
getfname(filename)
char *filename;
{
struct stat statbuf;
if (stat(filename, &statbuf) != 0)
return(-1);
/*
* if file is block special, look for open files on it
*/
if ((statbuf.st_mode & S_IFMT) != S_IFBLK) {
inum = statbuf.st_ino;
return(statbuf.st_dev);
} else {
special++;
inum = 0;
return(statbuf.st_rdev);
}
}
Atoi(p)
register char *p;
{
register int n = 0;
while(*p >= '0' && *p <= '9')
n = n*10 + *p++ - '0';
return(*p ? -n : n);
}
/* @(#)getpwent.c 4.1 (Berkeley) 12/21/80 */
static char PASSWD[] = "/etc/passwd";
static char EMPTY[] = "";
static FILE *pwf = NULL;
static char line[BUFSIZ+1];
static struct passwd passwd;
setpwent()
{
if( pwf == NULL )
pwf = fopen( PASSWD, "r" );
else
rewind( pwf );
}
endpwent()
{
if( pwf != NULL ){
fclose( pwf );
pwf = NULL;
}
}
static char *
pwskip(p)
register char *p;
{
while( *p && *p != ':' )
++p;
if( *p ) *p++ = 0;
return(p);
}
struct passwd *
getpwent()
{
register char *p;
if (pwf == NULL) {
if( (pwf = fopen( PASSWD, "r" )) == NULL )
return(0);
}
p = fgets(line, BUFSIZ, pwf);
if (p==NULL)
return(0);
passwd.pw_name = p;
p = pwskip(p);
passwd.pw_passwd = p;
p = pwskip(p);
passwd.pw_uid = atoi(p);
p = pwskip(p);
passwd.pw_gid = atoi(p);
passwd.pw_quota = 0;
passwd.pw_comment = EMPTY;
p = pwskip(p);
passwd.pw_gecos = p;
p = pwskip(p);
passwd.pw_dir = p;
p = pwskip(p);
passwd.pw_shell = p;
while(*p && *p != '\n') p++;
*p = '\0';
return(&passwd);
}
/* @(#)getpwuid.c 4.1 (Berkeley) 12/21/80 */
struct passwd *
getpwuid(uid)
register uid;
{
register struct passwd *p;
struct passwd *getpwent();
setpwent();
while( (p = getpwent()) && p->pw_uid != uid );
endpwent();
return(p);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.