home *** CD-ROM | disk | FTP | other *** search
- Path: wuarchive!gem.mps.ohio-state.edu!tut.cis.ohio-state.edu!cs.utexas.edu!uunet!bbn.com!rsalz
- From: rsalz@uunet.uu.net (Rich Salz)
- Newsgroups: comp.sources.unix
- Subject: v20i046: Print current directory of processes (on BSD)
- Message-ID: <2053@papaya.bbn.com>
- Date: 24 Oct 89 00:20:03 GMT
- Lines: 796
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: Cliff Spencer <cspencer@spdcc.com>
- Posting-number: Volume 20, Issue 46
- Archive-name: process-cwd
-
-
- Here is cwd, it performs a pwd() the hard way. This is a program that
- prints out the current working directory of processes on your BSD based
- system. It is probably most useful for amusement purposes. Cwd won't work
- on NFS hosts. I welcome all bug reports.
- Cliff Spencer
- spdcc!lemming!cspencer
-
-
- # This is a shell archive. Remove anything before this line, then
- # unpack it by saving it in a file and typing "sh file". cd /u(Files
- # unpacked will be owned by you and have default permissions.)
-
- echo x - README
- sed -e 's/^X//' > "README" << '//E*O*F README//'
- XTue Oct 17 21:52:01 EDT 1989
- XHere is cwd, a program that prints out the current working directory
- Xof processes on your BSD based system. It is probably most useful for
- Xamusement purposes. Cwd won't work on NFS hosts. I welcome all bug
- Xreports.
- X Cliff Spencer
- X spdcc!lemming!cspencer
- X
- //E*O*F README//
-
- echo x - Makefile
- sed -e 's/^X//' > "Makefile" << '//E*O*F Makefile//'
- X#Makefile for cwd
- X#
- X# One of bsd, ultrix, or sun should be defined
- X# if you're using gcc or BSD4.3, you'll need to define the
- X# appropriate symbol in CFLAGS
- XCC=cc
- XRM=/bin/rm
- X
- XCFLAGS=-g
- X
- Xcwd: cwd.o
- X $(CC) $(CFLAGS) -o cwd cwd.o
- Xclean:
- X $(RM) -f cwd.o
- X
- Xclobber: clean
- X $(RM) -f cwd
- //E*O*F Makefile//
-
- echo x - cwd.c
- sed -e 's/^X//' > "cwd.c" << '//E*O*F cwd.c//'
- X
- X/*
- X * This program may be freely redistributed but this entire comment
- X * MUST remain intact.
- X *
- X * Copyright (c) 1989 Clifford Spencer
- X *
- X * usage: cwd [usernames]
- X *
- X * for each process on the system print full path of current directory
- X * as found in u.u_cdir. Note that this program requires read permission
- X * on the raw disks
- X *
- X *
- X * This program has been compiled successfully on Ultrix 3.0, SunOS 3.5,
- X * and BSD4.3. It won't work for NFS mounted filesystems because of lack
- X * of access to remote devices
- X *
- X * author: Cliff Spencer (cspencer@lemming.uucp)
- X * Tue Oct 17 21:53:30 EDT 1989
- X *
- X */
- X#if !defined(ultrix) && !defined(bsd) && !defined(sun)
- X#define sun
- X#endif
- X#include <sys/param.h>
- X#if !defined(bsd) /* user.h pulls this in on BSD */
- X#include <sys/time.h>
- X#endif
- X#if defined(sun)
- X#include <sys/vnode.h>
- X#endif
- X#if defined(bsd)
- X#include <sys/fs.h>
- X#else
- X#include <ufs/fs.h>
- X#endif
- X#include <sys/dir.h>
- X#include <sys/file.h>
- X#if defined(ultrix) || defined(bsd)
- X#include <sys/inode.h>
- X#include <sys/mount.h>
- X#endif
- X#if defined(ultrix)
- X#include <sys/gnode.h>
- X#endif
- X#if defined(sun)
- X#include <ufs/mount.h>
- X#define KERNEL /* this is to pick up define for VTOI */
- X#include <ufs/inode.h>
- X#undef KERNEL
- X#endif
- X#include <machine/pte.h>
- X#include <sys/buf.h>
- X#include <sys/user.h>
- X#include <sys/proc.h>
- X#include <sys/stat.h>
- X#include <pwd.h>
- X#include <utmp.h>
- X#include <stdio.h>
- X#include <fstab.h>
- X#include <nlist.h>
- X#include <errno.h>
- X
- X/*
- X * handy info to keep around on each mounted filesystem
- X */
- Xstruct mount_stuff {
- X dev_t dev; /* major/minor of fs */
- X char devname[MAXPATHLEN + 1]; /* name of dev */
- X char path[MAXPATHLEN + 1]; /* name of mount point */
- X int fd;
- X struct fs *fs;
- X};
- X
- X
- Xstruct nlist nlst[] = {
- X { "_proc" },
- X#define X_PROC 0
- X { "_nproc" },
- X#define X_NPROC 1
- X#if defined(sun)
- X { "_mounttab" },
- X#else
- X { "_mount" },
- X#endif
- X#define X_MOUNT 2
- X#if defined(ultrix)
- X { "_nmount"},
- X#define X_NMOUNT 3
- X#endif
- X { 0 },
- X};
- X
- Xdaddr_t bmap();
- Xchar *emalloc();
- Xvoid mread();
- Xint kmem;
- Xint mem;
- Xint swap;
- X
- X
- X#define ANY_UID -1
- X#define NOSUCH_USER -2
- X
- X#if defined(ultrix)
- X#define GTOI(g) (&(g)->g_req)
- X#define inode gnode_req
- X#define i_number gr_number
- X#define i_dev gr_dev
- X#endif
- X
- X
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar **argv;
- X{
- X unsigned nproc, i;
- X struct proc *p;
- X
- X struct mount_stuff *mount_stuff, *getmountstuff();
- X
- X (void)nlist("/vmunix", nlst);
- X
- X for (i = 0; nlst[i].n_name; i++)
- X if (nlst[i].n_type == 0)
- X ecmderr(0, "vmunix: can' get symbol <%s>\n",
- X nlst[i].n_name);
- X
- X mem = eopen("/dev/mem", O_RDONLY);
- X kmem = eopen("/dev/kmem", O_RDONLY);
- X swap = eopen("/dev/drum", O_RDONLY);
- X
- X
- X mread(kmem,(daddr_t)nlst[X_NPROC].n_value,
- X (char *)&nproc, sizeof(nproc));
- X mread(kmem, (daddr_t)nlst[X_PROC].n_value, (char *)&p, sizeof(p));
- X mount_stuff = getmountstuff(nlst);
- X
- X printf("PID USER COMMAND PATH\n");
- X if (argc > 1) {
- X while (--argc)
- X cwd(mount_stuff, p, nproc, name2uid(*++argv));
- X }
- X else
- X cwd(mount_stuff, p, nproc, ANY_UID);
- X}
- X
- Xcwd(mount_stuff, procaddr, nproc, uid)
- Xstruct mount_stuff *mount_stuff;
- Xstruct proc *procaddr;
- Xunsigned nproc;
- Xint uid;
- X{
- X struct inode *cdir, *getcdir();
- X struct proc *p, proc;
- X struct mount_stuff *m, *devtostuff();
- X struct user *getu();
- X char *path;
- X struct user *u;
- X char *findpath();
- X int proci;
- X
- X if (uid == NOSUCH_USER)
- X return;
- X for (proci = 0, p = &proc; proci < nproc; proci++) {
- X mread(kmem, (daddr_t)&procaddr[proci], (char *)&proc,
- X sizeof(struct proc));
- X if (p->p_stat && p->p_stat != SZOMB) {
- X if (uid != ANY_UID && p->p_uid != uid)
- X continue;
- X if (u = getu(p, mem, kmem, swap)) {
- X cdir = getcdir(kmem,(daddr_t)u->u_cdir);
- X printpid(p->p_pid);
- X (void)printuser(u->u_uid);
- X printcomm(u, p->p_pid);
- X m = devtostuff(cdir->i_dev, mount_stuff);
- X if (!m)
- X printf("<no mount info>");
- X else {
- X path = findpath(m, cdir->i_number,
- X (ino_t)0);
- X printf("%s", path);
- X }
- X printf("\n");
- X }
- X }
- X }
- X}
- X
- X/*
- X * recursively lookup and return the path to the inode described by "thenum"
- X * append path components on return
- X * args:
- X * mount_stuff: mount info for the appropriate device
- X * dirinum: i number of the current dir containing the
- X * element being looked up
- X * thenum: i number to look up in this dir (0 means none))
- X *
- X * returns: pathname corresponding to dirinum
- X */
- Xchar *findpath(mount_stuff, dirinum, thenum)
- Xstruct mount_stuff *mount_stuff;
- Xino_t dirinum;
- Xino_t thenum;
- X{
- X DIR *open_dir(), *dir;
- X struct direct *read_dir(), *dirp;
- X struct dinode *ip, *readinode();
- X ino_t dotdot,dot;
- X int fd = mount_stuff->fd;
- X struct fs *fs = mount_stuff->fs;
- X static char path[MAXPATHLEN+1];
- X
- X
- X /*
- X * hit the root, prepend the mount point and return
- X */
- X if (dirinum == thenum) {
- X strcpy(path, mount_stuff->path);
- X return path;
- X }
- X
- X
- X ip = readinode(fd, fs, dirinum);
- X dir = open_dir(fd, fs, ip);
- X if (dir == NULL)
- X return "<bogus dir>";
- X
- X while (dirp = read_dir(fs, ip, dir)) {
- X if (strcmp(dirp->d_name, ".") == 0) {
- X dot = dirp->d_ino;/* next inode # to lookup */
- X continue;
- X }
- X /* save number of parent for next time */
- X else if (strcmp(dirp->d_name, "..") == 0)
- X dotdot = dirp->d_ino;
- X else if (dirp->d_ino == thenum || thenum == 0) {
- X char name[MAXNAMLEN+1];
- X
- X if (thenum)
- X sprintf(name, "/%s", dirp->d_name);
- X
- X (void)findpath(mount_stuff, dotdot, dot);
- X if (thenum) {
- X /*
- X * remove redundant leading / for
- X * things mounted on root
- X */
- X int len = strlen(path);
- X if (path[len-1] == '/')
- X len--;
- X strcpy(&path[len],name);
- X }
- X break;
- X }
- X }
- X close_dir(dir);
- X return path;
- X}
- X
- X
- X/*
- X * read from a block from the disk
- X */
- Xbread(fi, bno, buf, cnt)
- Xint fi;
- Xdaddr_t bno;
- Xchar *buf;
- Xlong cnt;
- X{
- X mread(fi, bno * DEV_BSIZE, buf, cnt);
- X}
- X
- X
- X/*
- X * map logical to physical block numbers
- X */
- Xdaddr_t bmap(b, ip, fi, fs)
- Xdaddr_t b;
- Xstruct dinode *ip;
- Xint fi;
- Xstruct fs *fs;
- X{
- X daddr_t ibuf[MAXBSIZE / sizeof (daddr_t)];
- X daddr_t iblock;
- X int indir;
- X int nblocks;
- X
- X if(b < NDADDR)
- X return(ip->di_db[b]);
- X b -= NDADDR;
- X for (nblocks = 1, indir = 0; indir < NIADDR; indir++) {
- X nblocks *= NINDIR(fs);
- X if (nblocks > b)
- X break;
- X else
- X b -= nblocks;
- X }
- X if (indir == NIADDR)
- X return((daddr_t)0);
- X iblock = ip->di_ib[indir];
- X for (; indir >= 0; indir--) {
- X bread(fi, fsbtodb(fs, iblock), (char *)ibuf, sizeof(ibuf));
- X nblocks /= NINDIR(fs);
- X iblock = ibuf[(b/nblocks) % NINDIR(fs)];
- X }
- X return iblock;
- X}
- X
- XDIR *open_dir(file, fs, ip)
- Xint file;
- Xstruct fs *fs;
- Xstruct dinode *ip;
- X{
- X static DIR dir;
- X
- X if ((ip->di_mode & IFMT) != IFDIR) {
- X fprintf(stderr, "open_dir: not a directory\n");
- X return NULL;
- X }
- X dir.dd_loc = 0;
- X dir.dd_size = ip->di_size;
- X#if !defined(bsd)
- X if (dir.dd_buf)
- X free(dir.dd_buf);
- X dir.dd_buf = (char *)emalloc((unsigned)fs->fs_bsize);
- X#endif
- X dir.dd_fd = file;
- X return &dir;
- X}
- X
- Xclose_dir(dirp)
- XDIR *dirp;
- X{
- X#if !defined(bsd)
- X if (dirp->dd_buf) {
- X free(dirp->dd_buf);
- X dirp->dd_buf = NULL;
- X }
- X#endif
- X}
- X
- X
- X
- Xstruct direct *read_dir(fs,ip, dir)
- Xstruct fs *fs;
- Xstruct dinode *ip;
- XDIR *dir;
- X{
- X daddr_t bn;
- X static struct direct *dp;
- X
- X if (dir->dd_loc >= dir->dd_size)
- X return NULL;
- X if (blkoff(fs, dir->dd_loc) == 0) { /* need to read a block */
- X bn = lblkno(fs, dir->dd_loc);
- X bn = bmap(bn, ip, dir->dd_fd, fs);
- X if (bn == 0)
- X return NULL;
- X bn = fsbtodb(fs, bn);
- X bread(dir->dd_fd, bn, dir->dd_buf, fs->fs_bsize);
- X }
- X dp = (struct direct *)&dir->dd_buf[dir->dd_loc];
- X dir->dd_loc += dp->d_reclen;
- X return dp;
- X}
- X
- X/*
- X * error printing
- X * modelled after routines written by Dan Franklin@bbn
- X * if e is -1 print system error message from errno
- X * if e is 0 don't print error message
- X * else use e as errno
- X *
- X * note: using _doprnt is less than portable
- X */
- Xcmderr(e, format, args)
- Xint e;
- Xchar *format;
- Xchar *args;
- X{
- X register int nl = 0;
- X register int i = strlen(format) - 1;
- X char fmt[BUFSIZ];
- X extern int sys_nerr;
- X extern char *sys_errlist[];
- X extern int errno;
- X
- X strcpy(fmt, format);
- X if ( e == -1)
- X e = errno;
- X if (fmt[i] == '\n') {
- X fmt[i] = NULL;
- X nl = 1;
- X }
- X _doprnt(fmt, &args, stderr);
- X if (e > sys_nerr)
- X fprintf(stderr," Error %d", e);
- X else if (e)
- X fprintf(stderr, " %s", sys_errlist[e]);
- X if(nl)
- X fprintf(stderr,"\n");
- X}
- X
- X
- X/*
- X * print error message and exit
- X */
- Xecmderr(e, fmt, args)
- Xint e;
- Xchar *fmt;
- Xunsigned args;
- X{
- X cmderr(e,fmt,args);
- X exit(e);
- X}
- X
- X/*
- X * read from the specified address
- X */
- Xvoid mread(fd, addr, buf, cnt)
- Xint fd;
- Xdaddr_t addr;
- Xchar *buf;
- Xint cnt;
- X{
- X int nread;
- X extern daddr_t lseek();
- X if (lseek(fd, addr, L_SET) != addr)
- X ecmderr(-1, "Seek failed\n");
- X if ((nread = read(fd, buf, cnt)) == 0)
- X ecmderr(-1, "Read failed (wanted:%d)\n", cnt);
- X if (nread > cnt) cmderr(-1,"read for %d returned %d\n", cnt, nread);
- X}
- X
- X/*
- X * "safe" open
- X */
- Xeopen(name, mode)
- Xchar *name;
- Xunsigned mode;
- X{
- X int fd;
- X fd = open(name, mode);
- X if (fd < 0)
- X ecmderr(-1, "cwd: Can't open %s\n", name);
- X return fd;
- X}
- X
- X/*
- X * "safe" malloc
- X */
- Xchar *emalloc(n)
- Xunsigned n;
- X{
- X char *p;
- X extern char *malloc();
- X p = malloc(n);
- X if (p == NULL)
- X ecmderr(-1, "Malloc failed\n");
- X return p;
- X}
- X
- X
- X/*
- X * read kernel mount table and save the stuff we care about
- X */
- Xstruct mount_stuff *getmountstuff(nlst)
- Xstruct nlist nlst[];
- X{
- X int nmount, i;
- X struct mount *mounttable;
- X struct mount_stuff *mount_stuff;
- X struct fstab *fstab, *getfsent();
- X int m;
- X
- X#if defined(ultrix)
- X mread(kmem, (daddr_t)nlst[X_NMOUNT].n_value, &nmount, sizeof(nmount));
- X#else
- X nmount = NMOUNT;
- X#endif
- X
- X mounttable = (struct mount *)emalloc(
- X (unsigned)nmount * sizeof(struct mount));
- X mread(kmem, (daddr_t)nlst[X_MOUNT].n_value, (char *)mounttable,
- X nmount * sizeof(struct mount));
- X mount_stuff = (struct mount_stuff *)
- X emalloc((nmount + 1)* sizeof(struct mount_stuff));
- X
- X for (m = 0; fstab = getfsent();) {
- X struct stat s;
- X struct buf buf;
- X char *slash;
- X extern char *rindex(), *index();
- X
- X if (*fstab->fs_file == NULL)
- X continue;
- X if (index(fstab->fs_spec,'@')) {
- X fprintf(stderr,"%s: Can't handle NFS yet\n",
- X fstab->fs_spec);
- X continue;
- X }
- X if (stat(fstab->fs_spec, &s) != 0)
- X ecmderr(-1, "cwd: Can't stat %s\n", fstab->fs_spec);
- X strcpy(mount_stuff[m].devname, fstab->fs_spec);
- X slash = rindex(mount_stuff[m].devname, '/');
- X if (slash) {
- X slash++;
- X bcopy(slash, slash+1, strlen(slash)+1);
- X *slash = 'r';
- X }
- X strcpy(mount_stuff[m].path, fstab->fs_file);
- X
- X mount_stuff[m].fd = -1;
- X mount_stuff[m].fs = (struct fs *)emalloc(sizeof(struct fs));
- X for (i = 0; i < nmount; i++) {
- X if (mounttable[i].m_dev != s.st_rdev)
- X continue;
- X mount_stuff[m].dev = s.st_rdev;
- X mread(kmem, (daddr_t)mounttable[i].m_bufp,
- X (char *)&buf,sizeof(struct buf));
- X mread(kmem, (daddr_t)buf.b_un.b_fs,(char *)mount_stuff[m].fs,
- X sizeof(struct fs));
- X break;
- X }
- X m++;
- X if (i >= nmount)
- X cmderr(0, "cwd: Can't find %s in kernel mount table\n",
- X fstab->fs_spec);
- X }
- X mount_stuff[m].dev = -1;
- X free(mounttable);
- X return mount_stuff;
- X}
- X
- X/*
- X * return a pointer to some mount information using
- X * device as the key
- X */
- Xstruct mount_stuff *devtostuff(dev, mount_stuff)
- Xdev_t dev;
- Xstruct mount_stuff mount_stuff[];
- X{
- X int i;
- X
- X for (i = 0; mount_stuff[i].dev != -1; i++) {
- X if (mount_stuff[i].dev == dev) {
- X if (mount_stuff[i].fd == -1)
- X mount_stuff[i].fd =
- X eopen(mount_stuff[i].devname,
- X O_RDONLY);
- X return &mount_stuff[i];
- X }
- X }
- X return NULL;
- X}
- X
- X/*
- X * massage the u_comm field of a user page
- X */
- Xprintcomm(u, pid)
- Xstruct user *u;
- Xint pid;
- X{
- X char *name;
- X switch (pid) {
- X case 0:
- X name = "swapper";
- X break;
- X case 2:
- X name = "pagedaemon";
- X break;
- X default:
- X name = u->u_comm;
- X }
- X printf("%-*s ", MAXCOMLEN, name );
- X}
- X
- Xprintpid(pid)
- Xint pid;
- X{
- X printf("%-6d ", pid);
- X}
- X
- X/*
- X * print a username based on uid
- X */
- Xprintuser(uid)
- Xint uid;
- X{
- X struct passwd *pw;
- X pw = getpwuid(uid);
- X if (pw)
- X printf("%-8.8s ", pw->pw_name);
- X return (pw != NULL);
- X}
- X
- Xstruct dinode *readinode(fd, fs, inum)
- Xint fd;
- Xstruct fs *fs;
- Xino_t inum;
- X{
- X static struct dinode itab[MAXIPG];
- X
- X bread(fd, fsbtodb(fs, cgimin(fs, inum/fs->fs_ipg)), (char *)itab,
- X fs->fs_ipg * sizeof (struct dinode));
- X
- X return &itab[inum%fs->fs_ipg];
- X}
- X
- Xname2uid(name)
- Xchar *name;
- X{
- X struct passwd *pw;
- X pw = getpwnam(name);
- X if (pw)
- X return pw->pw_uid;
- X else {
- X fprintf(stderr,"%s: no such user\n",name);
- X return NOSUCH_USER;
- X }
- X}
- X
- X
- X/*
- X * return a pointer to a user page
- X * this routine was liberally cribbed from the "top" program
- X * by William Lefebvre
- X */
- Xstruct user *getu(p, mem, kmem, swap)
- Xstruct proc *p;
- X{
- X /* pad reads from swap to a page */
- X static union {
- X struct user u;
- X char upages[UPAGES][NBPG];
- X } user;
- X#if !defined(bsd)
- X static struct ucred ucred;
- X#endif
- X char *up;
- X struct pte *pte, uptes[UPAGES];
- X int n;
- X#define min(a,b) (a < b ? a : b)
- X /* try in core */
- X if (p->p_flag & SLOAD) {
- X mread(kmem, (daddr_t)p->p_addr,(char *)uptes,
- X UPAGES * sizeof(struct pte));
- X pte = uptes;
- X for(up = (char *)&user, n = sizeof(struct user); n > 0;
- X n -= NBPG) {
- X mread(mem, (daddr_t)(pte++->pg_pfnum * NBPG),
- X up,min(n,NBPG));
- X up += NBPG;
- X }
- X }
- X else
- X mread(swap, (daddr_t)dtob(p->p_swaddr),
- X (char *)&user,sizeof(user));
- X#if !defined(bsd)
- X mread(kmem, (daddr_t)user.u.u_cred, &ucred, sizeof(ucred));
- X user.u.u_cred = &ucred;
- X#endif
- X return &user.u;
- X}
- X
- X
- X/*
- X * get the inode corresponding to current working directory
- X */
- Xstruct inode *getcdir(kmem, addr)
- Xint kmem;
- Xdaddr_t addr;
- X{
- X static struct inode in;
- X struct inode *cdir;
- X
- X#if defined(ultrix)
- X struct gnode g;
- X mread(kmem, addr, &g, sizeof(g));
- X cdir = GTOI(&g);
- X#endif
- X#if defined(bsd)
- X mread(kmem, addr, &in, sizeof(in));
- X cdir = ∈
- X#endif
- X#if defined(sun)
- X struct vnode v;
- X mread(kmem, addr, &v, sizeof(v));
- X mread(kmem, (daddr_t)VTOI(&v), &in, sizeof(in));
- X cdir = ∈
- X#endif
- X return cdir;
- X}
- //E*O*F cwd.c//
-
- echo x - cwd.1
- sed -e 's/^X//' > "cwd.1" << '//E*O*F cwd.1//'
- X.TH CWD 1 "Oct 17, 1989"
- X.SH NAME
- Xcwd \- print current working directory of running processes
- X.SH SYNOPSIS
- X.B cwd
- X[
- X.B usernames...
- X]
- X.br
- X.SH DESCRIPTION
- X.B Cwd
- Xreads the kernel data structures from memory and
- Xconstructs a pathname corresponding to the
- X.B u.u_cdir
- Xkernel variable associated with each process on the system.
- XIf
- X.B usernames
- Xare specified as arguments, only processes belonging to those users
- Xwill be considered, the default is to report on all processes
- Xon the system. For each eligible process, the user name, process name,
- Xprocess id, and current working directory will be displayed. This command
- Xnormally requires root permission unless
- Xyour disks are readable (a less than good idea).
- X.B Cwd
- Xcurrently only works on BSD based filesystems.
- X
- X.PP
- X.SH "SEE ALSO"
- XNcheck(8)
- X.SH BUGS
- X.B Cwd
- Xcannot report on
- X.I NFS
- Xpathnames.
- //E*O*F cwd.1//
-
- exit 0
- --
- Cliff Spencer
- spdcc!lemming!cspencer lemming!cspencer@spdcc.com
-
- --
- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
- Use a domain-based address or give alternate paths, or you may lose out.
-