home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume20 / process-cwd < prev    next >
Text File  |  1989-10-22  |  21KB  |  799 lines

  1. Subject:  v20i046:  Print current directory of processes (on BSD)
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Cliff Spencer <cspencer@spdcc.com>
  7. Posting-number: Volume 20, Issue 46
  8. Archive-name: process-cwd
  9.  
  10.  
  11. Here is cwd, it performs a pwd() the hard way.  This is a program that
  12. prints out the current working directory of processes on your BSD based
  13. system. It is probably most useful for amusement purposes. Cwd won't work
  14. on NFS hosts. I welcome all bug reports.
  15.                         Cliff Spencer
  16.                         spdcc!lemming!cspencer
  17.  
  18.  
  19. # This is a shell archive.  Remove anything before this line, then
  20. # unpack it by saving it in a file and typing "sh file".  cd /u(Files
  21. # unpacked will be owned by you and have default permissions.)
  22.  
  23. echo x - README
  24. sed -e 's/^X//' > "README" << '//E*O*F README//'
  25. XTue Oct 17 21:52:01 EDT 1989
  26. XHere is cwd, a program that prints out the current working directory
  27. Xof processes on your BSD based system. It is probably most useful for 
  28. Xamusement purposes. Cwd won't work on NFS hosts. I welcome all bug 
  29. Xreports.
  30. X                        Cliff Spencer
  31. X                        spdcc!lemming!cspencer
  32. X
  33. //E*O*F README//
  34.  
  35. echo x - Makefile
  36. sed -e 's/^X//' > "Makefile" << '//E*O*F Makefile//'
  37. X#Makefile for cwd
  38. X#
  39. X# One of bsd, ultrix, or sun should be defined
  40. X# if you're using gcc or BSD4.3, you'll need to define the
  41. X# appropriate symbol in CFLAGS
  42. XCC=cc
  43. XRM=/bin/rm
  44. X
  45. XCFLAGS=-g 
  46. X
  47. Xcwd: cwd.o 
  48. X    $(CC) $(CFLAGS) -o cwd cwd.o
  49. Xclean:
  50. X    $(RM) -f cwd.o
  51. X
  52. Xclobber: clean
  53. X    $(RM) -f cwd
  54. //E*O*F Makefile//
  55.  
  56. echo x - cwd.c
  57. sed -e 's/^X//' > "cwd.c" << '//E*O*F cwd.c//'
  58. X
  59. X/*
  60. X * This program may be freely redistributed but this entire comment 
  61. X * MUST remain intact.
  62. X *
  63. X * Copyright (c) 1989 Clifford Spencer
  64. X *
  65. X * usage: cwd [usernames]
  66. X *
  67. X * for each process on the system print full path of current directory
  68. X * as found in u.u_cdir. Note that this program requires read permission
  69. X * on the raw disks
  70. X * 
  71. X *
  72. X * This program has been compiled successfully on Ultrix 3.0, SunOS 3.5, 
  73. X * and BSD4.3. It won't work for NFS mounted filesystems because of lack 
  74. X * of access to remote devices
  75. X * 
  76. X * author: Cliff Spencer (cspencer@lemming.uucp)
  77. X * Tue Oct 17 21:53:30 EDT 1989
  78. X *
  79. X */
  80. X#if !defined(ultrix) && !defined(bsd) && !defined(sun)
  81. X#define sun
  82. X#endif
  83. X#include <sys/param.h>
  84. X#if !defined(bsd)       /* user.h pulls this in on BSD */
  85. X#include <sys/time.h>
  86. X#endif
  87. X#if defined(sun)
  88. X#include <sys/vnode.h>
  89. X#endif
  90. X#if defined(bsd)
  91. X#include <sys/fs.h>
  92. X#else
  93. X#include <ufs/fs.h>
  94. X#endif
  95. X#include <sys/dir.h>
  96. X#include <sys/file.h>
  97. X#if defined(ultrix) || defined(bsd)
  98. X#include <sys/inode.h>
  99. X#include <sys/mount.h>
  100. X#endif
  101. X#if defined(ultrix)
  102. X#include <sys/gnode.h>
  103. X#endif
  104. X#if defined(sun)
  105. X#include <ufs/mount.h>
  106. X#define KERNEL  /* this is to pick up define for VTOI */
  107. X#include <ufs/inode.h>
  108. X#undef KERNEL
  109. X#endif
  110. X#include <machine/pte.h>
  111. X#include <sys/buf.h>
  112. X#include <sys/user.h>
  113. X#include <sys/proc.h>
  114. X#include <sys/stat.h>
  115. X#include <pwd.h>
  116. X#include <utmp.h>
  117. X#include <stdio.h>
  118. X#include <fstab.h>
  119. X#include <nlist.h>
  120. X#include <errno.h>
  121. X
  122. X/* 
  123. X * handy info to keep around on each mounted filesystem
  124. X */
  125. Xstruct mount_stuff {
  126. X        dev_t   dev;                    /* major/minor of fs */
  127. X        char devname[MAXPATHLEN + 1];   /* name of dev */
  128. X        char path[MAXPATHLEN + 1];      /* name of mount point */
  129. X        int fd;
  130. X        struct fs *fs;
  131. X};
  132. X
  133. X
  134. Xstruct nlist nlst[] = {
  135. X        { "_proc" },
  136. X#define X_PROC          0
  137. X        { "_nproc" },
  138. X#define X_NPROC         1
  139. X#if defined(sun)
  140. X        { "_mounttab" },
  141. X#else
  142. X        { "_mount" },
  143. X#endif
  144. X#define X_MOUNT         2
  145. X#if defined(ultrix)
  146. X        { "_nmount"},
  147. X#define X_NMOUNT        3
  148. X#endif
  149. X        {       0    },
  150. X};
  151. X
  152. Xdaddr_t bmap();
  153. Xchar *emalloc();
  154. Xvoid mread();
  155. Xint kmem;
  156. Xint mem;
  157. Xint swap;
  158. X
  159. X
  160. X#define ANY_UID -1
  161. X#define NOSUCH_USER -2
  162. X
  163. X#if defined(ultrix)
  164. X#define GTOI(g)         (&(g)->g_req)
  165. X#define inode           gnode_req
  166. X#define i_number        gr_number
  167. X#define i_dev           gr_dev
  168. X#endif
  169. X
  170. X
  171. X
  172. Xmain(argc, argv)
  173. Xint argc;
  174. Xchar **argv;
  175. X{
  176. X        unsigned nproc, i;
  177. X        struct proc *p;
  178. X
  179. X        struct mount_stuff *mount_stuff, *getmountstuff();
  180. X        
  181. X        (void)nlist("/vmunix", nlst);
  182. X        
  183. X        for (i = 0; nlst[i].n_name; i++)
  184. X                if (nlst[i].n_type == 0)
  185. X                        ecmderr(0, "vmunix: can' get symbol <%s>\n", 
  186. X                                nlst[i].n_name);
  187. X        
  188. X        mem = eopen("/dev/mem", O_RDONLY);
  189. X        kmem = eopen("/dev/kmem", O_RDONLY);
  190. X        swap = eopen("/dev/drum", O_RDONLY);
  191. X        
  192. X        
  193. X        mread(kmem,(daddr_t)nlst[X_NPROC].n_value, 
  194. X              (char *)&nproc, sizeof(nproc));
  195. X        mread(kmem, (daddr_t)nlst[X_PROC].n_value, (char *)&p, sizeof(p));
  196. X        mount_stuff = getmountstuff(nlst);
  197. X        
  198. X    printf("PID    USER       COMMAND          PATH\n");
  199. X        if (argc > 1) {
  200. X                while (--argc)
  201. X                        cwd(mount_stuff, p, nproc, name2uid(*++argv));
  202. X        }
  203. X        else
  204. X                cwd(mount_stuff, p, nproc, ANY_UID);
  205. X}
  206. X
  207. Xcwd(mount_stuff, procaddr, nproc, uid)
  208. Xstruct mount_stuff *mount_stuff;
  209. Xstruct proc *procaddr;
  210. Xunsigned nproc;
  211. Xint uid;
  212. X{
  213. X    struct inode *cdir, *getcdir();
  214. X        struct proc *p, proc;
  215. X        struct mount_stuff *m, *devtostuff();
  216. X        struct user *getu();
  217. X        char *path;
  218. X        struct user *u; 
  219. X        char *findpath();
  220. X    int proci;
  221. X        
  222. X    if (uid == NOSUCH_USER)
  223. X        return;
  224. X    for (proci = 0, p = &proc; proci < nproc; proci++) {
  225. X        mread(kmem, (daddr_t)&procaddr[proci], (char *)&proc, 
  226. X            sizeof(struct proc));
  227. X                if (p->p_stat && p->p_stat != SZOMB) {
  228. X                        if (uid != ANY_UID && p->p_uid != uid)
  229. X                                continue;
  230. X                        if (u = getu(p, mem, kmem, swap)) {
  231. X                                cdir = getcdir(kmem,(daddr_t)u->u_cdir);
  232. X                printpid(p->p_pid);
  233. X                                (void)printuser(u->u_uid);
  234. X                                printcomm(u, p->p_pid);
  235. X                                m = devtostuff(cdir->i_dev, mount_stuff);
  236. X                                if (!m)
  237. X                                        printf("<no mount info>");
  238. X                                else {
  239. X                                        path = findpath(m, cdir->i_number,
  240. X                                                        (ino_t)0);
  241. X                                        printf("%s", path);
  242. X                                }
  243. X                                printf("\n");
  244. X                        }
  245. X                }
  246. X        }
  247. X}
  248. X
  249. X/*
  250. X * recursively lookup and return the path to the inode described by "thenum"
  251. X * append path components on return
  252. X * args:
  253. X *      mount_stuff: mount info for the appropriate device
  254. X *      dirinum: i number of the current dir containing the
  255. X *              element being looked up
  256. X *      thenum: i number to look up in this dir (0 means none))
  257. X *
  258. X * returns: pathname corresponding to dirinum
  259. X */
  260. Xchar *findpath(mount_stuff, dirinum, thenum)
  261. Xstruct mount_stuff *mount_stuff;
  262. Xino_t dirinum;
  263. Xino_t thenum;
  264. X{
  265. X        DIR *open_dir(), *dir;
  266. X        struct direct *read_dir(), *dirp;
  267. X        struct dinode *ip, *readinode();
  268. X        ino_t dotdot,dot;
  269. X        int fd = mount_stuff->fd;
  270. X        struct fs *fs = mount_stuff->fs;
  271. X        static char path[MAXPATHLEN+1];
  272. X        
  273. X        
  274. X        /*
  275. X         * hit the root, prepend the mount point and return
  276. X         */
  277. X        if (dirinum == thenum) {
  278. X                strcpy(path, mount_stuff->path);
  279. X                return path;
  280. X        }
  281. X        
  282. X        
  283. X    ip = readinode(fd, fs, dirinum);
  284. X    dir = open_dir(fd, fs, ip);
  285. X    if (dir == NULL)
  286. X        return "<bogus dir>";
  287. X    
  288. X    while (dirp = read_dir(fs, ip, dir)) {
  289. X        if (strcmp(dirp->d_name, ".") == 0) {
  290. X            dot = dirp->d_ino;/* next inode # to lookup */
  291. X            continue;
  292. X        }
  293. X        /* save number of parent for next time */
  294. X        else if (strcmp(dirp->d_name, "..") == 0)
  295. X            dotdot = dirp->d_ino;
  296. X        else if (dirp->d_ino == thenum || thenum == 0) {
  297. X            char name[MAXNAMLEN+1];
  298. X            
  299. X            if (thenum) 
  300. X                sprintf(name, "/%s", dirp->d_name);
  301. X               
  302. X            (void)findpath(mount_stuff, dotdot, dot);
  303. X            if (thenum) {
  304. X                /* 
  305. X                 * remove redundant leading / for
  306. X                 * things mounted on root
  307. X                 */
  308. X                int len = strlen(path);
  309. X                if (path[len-1] == '/') 
  310. X                    len--;
  311. X                strcpy(&path[len],name);
  312. X            }
  313. X            break;
  314. X        }
  315. X    }
  316. X    close_dir(dir);
  317. X        return path;
  318. X}
  319. X
  320. X
  321. X/*
  322. X * read from a block from the disk
  323. X */  
  324. Xbread(fi, bno, buf, cnt)
  325. Xint fi;
  326. Xdaddr_t bno;
  327. Xchar *buf;
  328. Xlong cnt;
  329. X{
  330. X        mread(fi, bno * DEV_BSIZE, buf, cnt);
  331. X}
  332. X
  333. X
  334. X/*
  335. X * map logical to physical block numbers
  336. X */
  337. Xdaddr_t bmap(b, ip, fi, fs)
  338. Xdaddr_t b;
  339. Xstruct dinode *ip;
  340. Xint fi;
  341. Xstruct fs *fs;
  342. X{
  343. X        daddr_t ibuf[MAXBSIZE / sizeof (daddr_t)];
  344. X    daddr_t iblock;
  345. X    int indir;
  346. X    int nblocks;
  347. X        
  348. X        if(b < NDADDR)
  349. X                return(ip->di_db[b]);
  350. X        b -= NDADDR;
  351. X    for (nblocks = 1, indir = 0; indir < NIADDR; indir++) {
  352. X        nblocks *= NINDIR(fs);
  353. X        if (nblocks > b)
  354. X            break;
  355. X        else
  356. X            b -= nblocks;
  357. X    }
  358. X    if (indir == NIADDR)
  359. X                return((daddr_t)0);
  360. X           iblock = ip->di_ib[indir];
  361. X    for (; indir >= 0; indir--) {
  362. X        bread(fi, fsbtodb(fs, iblock), (char *)ibuf, sizeof(ibuf));
  363. X        nblocks /= NINDIR(fs);
  364. X        iblock = ibuf[(b/nblocks) % NINDIR(fs)];
  365. X    }
  366. X        return iblock;
  367. X}
  368. X
  369. XDIR *open_dir(file, fs, ip)
  370. Xint file;
  371. Xstruct fs *fs;
  372. Xstruct dinode *ip;
  373. X{
  374. X        static DIR dir;
  375. X        
  376. X        if ((ip->di_mode & IFMT) != IFDIR) {
  377. X                fprintf(stderr, "open_dir:  not a directory\n");
  378. X                return NULL;
  379. X        }
  380. X        dir.dd_loc = 0;
  381. X        dir.dd_size = ip->di_size;
  382. X#if !defined(bsd)
  383. X    if (dir.dd_buf)
  384. X        free(dir.dd_buf);
  385. X        dir.dd_buf = (char *)emalloc((unsigned)fs->fs_bsize);
  386. X#endif
  387. X        dir.dd_fd = file;
  388. X        return &dir;
  389. X}
  390. X
  391. Xclose_dir(dirp)
  392. XDIR *dirp;
  393. X{
  394. X#if !defined(bsd)
  395. X        if (dirp->dd_buf) {
  396. X                free(dirp->dd_buf);
  397. X                dirp->dd_buf = NULL;
  398. X        }
  399. X#endif
  400. X}
  401. X
  402. X
  403. X
  404. Xstruct direct *read_dir(fs,ip, dir)
  405. Xstruct fs *fs;
  406. Xstruct dinode *ip;
  407. XDIR *dir;
  408. X{
  409. X        daddr_t bn;
  410. X        static struct direct *dp;
  411. X        
  412. X        if (dir->dd_loc >= dir->dd_size)
  413. X                return NULL;
  414. X        if (blkoff(fs, dir->dd_loc) == 0) {     /* need to read a block */
  415. X                bn = lblkno(fs, dir->dd_loc);
  416. X                bn = bmap(bn, ip, dir->dd_fd, fs);
  417. X                if (bn == 0)
  418. X                        return NULL;
  419. X                bn = fsbtodb(fs, bn);
  420. X                bread(dir->dd_fd, bn, dir->dd_buf, fs->fs_bsize);
  421. X        }
  422. X        dp = (struct direct *)&dir->dd_buf[dir->dd_loc];
  423. X        dir->dd_loc += dp->d_reclen;
  424. X        return dp;
  425. X}
  426. X
  427. X/*
  428. X * error printing 
  429. X * modelled after routines written by Dan Franklin@bbn
  430. X * if e is -1 print system error message from errno
  431. X * if e is 0 don't print error message
  432. X * else use e as errno
  433. X * 
  434. X * note: using _doprnt is less than portable
  435. X */
  436. Xcmderr(e, format, args)
  437. Xint e;
  438. Xchar *format;
  439. Xchar *args;
  440. X{
  441. X        register int nl = 0;
  442. X        register int i = strlen(format) - 1;
  443. X        char fmt[BUFSIZ];
  444. X        extern int sys_nerr;
  445. X        extern char *sys_errlist[];
  446. X        extern int errno;
  447. X        
  448. X        strcpy(fmt, format);
  449. X        if ( e == -1)
  450. X                e = errno;
  451. X        if (fmt[i] == '\n') {
  452. X                fmt[i] = NULL;
  453. X                nl = 1;
  454. X        }
  455. X        _doprnt(fmt, &args, stderr);
  456. X        if (e > sys_nerr)
  457. X                fprintf(stderr," Error %d", e);
  458. X        else if (e)
  459. X                fprintf(stderr, " %s", sys_errlist[e]);
  460. X        if(nl)
  461. X                fprintf(stderr,"\n");
  462. X}
  463. X
  464. X
  465. X/*
  466. X * print error message and exit
  467. X */
  468. Xecmderr(e, fmt, args)
  469. Xint e;
  470. Xchar *fmt;
  471. Xunsigned args;
  472. X{
  473. X        cmderr(e,fmt,args);
  474. X        exit(e);
  475. X}
  476. X
  477. X/*
  478. X * read from the specified address 
  479. X */
  480. Xvoid mread(fd, addr, buf, cnt)
  481. Xint fd;
  482. Xdaddr_t addr;
  483. Xchar *buf;
  484. Xint cnt;
  485. X{
  486. X        int nread;
  487. X        extern daddr_t lseek();
  488. X        if (lseek(fd, addr, L_SET) != addr)
  489. X                ecmderr(-1, "Seek failed\n");
  490. X        if ((nread = read(fd, buf, cnt)) == 0)
  491. X                ecmderr(-1, "Read failed (wanted:%d)\n", cnt);
  492. X        if (nread > cnt) cmderr(-1,"read for %d returned %d\n", cnt, nread);
  493. X}
  494. X
  495. X/* 
  496. X * "safe" open
  497. X */
  498. Xeopen(name, mode)
  499. Xchar *name;
  500. Xunsigned mode;
  501. X{
  502. X        int fd;
  503. X        fd = open(name, mode);
  504. X        if (fd < 0)
  505. X                ecmderr(-1, "cwd: Can't open %s\n", name);
  506. X        return fd;
  507. X}
  508. X
  509. X/*
  510. X * "safe" malloc 
  511. X */
  512. Xchar *emalloc(n)
  513. Xunsigned n;
  514. X{
  515. X        char *p;
  516. X        extern char *malloc();
  517. X        p = malloc(n);
  518. X        if (p == NULL)
  519. X                ecmderr(-1, "Malloc failed\n");
  520. X        return p;
  521. X}
  522. X
  523. X
  524. X/*
  525. X * read kernel mount table and save the stuff we care about
  526. X */
  527. Xstruct mount_stuff *getmountstuff(nlst)
  528. Xstruct nlist nlst[];
  529. X{
  530. X        int  nmount, i;
  531. X        struct mount *mounttable;
  532. X        struct mount_stuff *mount_stuff;
  533. X        struct fstab *fstab, *getfsent();
  534. X        int m;
  535. X        
  536. X#if defined(ultrix)
  537. X        mread(kmem, (daddr_t)nlst[X_NMOUNT].n_value, &nmount, sizeof(nmount));
  538. X#else
  539. X        nmount = NMOUNT;
  540. X#endif
  541. X        
  542. X        mounttable = (struct mount *)emalloc(
  543. X        (unsigned)nmount * sizeof(struct mount));
  544. X        mread(kmem, (daddr_t)nlst[X_MOUNT].n_value, (char *)mounttable, 
  545. X              nmount * sizeof(struct mount));
  546. X        mount_stuff = (struct mount_stuff *)
  547. X                emalloc((nmount + 1)* sizeof(struct mount_stuff));
  548. X        
  549. X        for (m = 0; fstab = getfsent();) {
  550. X                struct stat s;
  551. X                struct buf buf;
  552. X                char *slash;
  553. X                extern char *rindex(), *index();
  554. X                
  555. X                if (*fstab->fs_file == NULL)
  556. X                        continue;
  557. X                if (index(fstab->fs_spec,'@')) {
  558. X                        fprintf(stderr,"%s: Can't handle NFS yet\n",
  559. X                                fstab->fs_spec);
  560. X                        continue;
  561. X                }
  562. X                if (stat(fstab->fs_spec, &s) != 0)
  563. X                        ecmderr(-1, "cwd: Can't stat %s\n", fstab->fs_spec);
  564. X                strcpy(mount_stuff[m].devname, fstab->fs_spec);
  565. X                slash = rindex(mount_stuff[m].devname, '/');
  566. X                if (slash) {
  567. X                        slash++;
  568. X                        bcopy(slash, slash+1, strlen(slash)+1);
  569. X                        *slash = 'r';
  570. X                }
  571. X                strcpy(mount_stuff[m].path, fstab->fs_file);
  572. X                
  573. X                mount_stuff[m].fd = -1;
  574. X                mount_stuff[m].fs = (struct fs *)emalloc(sizeof(struct fs));
  575. X                for (i = 0; i < nmount; i++) {
  576. X                        if (mounttable[i].m_dev != s.st_rdev)
  577. X                                continue;
  578. X                        mount_stuff[m].dev = s.st_rdev;
  579. X                        mread(kmem, (daddr_t)mounttable[i].m_bufp,
  580. X                              (char *)&buf,sizeof(struct buf));
  581. X                        mread(kmem, (daddr_t)buf.b_un.b_fs,(char *)mount_stuff[m].fs, 
  582. X                              sizeof(struct fs));
  583. X                        break;
  584. X                }
  585. X                m++;
  586. X                if (i >= nmount) 
  587. X                        cmderr(0, "cwd: Can't find %s in kernel mount table\n",
  588. X                               fstab->fs_spec);
  589. X        }       
  590. X        mount_stuff[m].dev = -1;
  591. X        free(mounttable);
  592. X        return mount_stuff;
  593. X}
  594. X
  595. X/*
  596. X * return a pointer to some mount information using
  597. X * device as the key
  598. X */
  599. Xstruct mount_stuff *devtostuff(dev, mount_stuff)
  600. Xdev_t dev;
  601. Xstruct mount_stuff mount_stuff[];
  602. X{
  603. X        int i;
  604. X        
  605. X        for (i = 0; mount_stuff[i].dev != -1; i++) {
  606. X                if (mount_stuff[i].dev == dev) {
  607. X                        if (mount_stuff[i].fd == -1)
  608. X                                mount_stuff[i].fd = 
  609. X                                        eopen(mount_stuff[i].devname,
  610. X                                              O_RDONLY);
  611. X                        return &mount_stuff[i];
  612. X                }
  613. X        }
  614. X        return NULL;
  615. X}
  616. X
  617. X/*
  618. X * massage the u_comm field of a user page
  619. X */
  620. Xprintcomm(u, pid)
  621. Xstruct user *u;
  622. Xint pid;
  623. X{
  624. X        char *name;
  625. X        switch (pid) {
  626. X              case 0:
  627. X                name = "swapper";
  628. X                break;
  629. X              case 2:
  630. X                name = "pagedaemon";
  631. X                break;
  632. X              default:
  633. X                name = u->u_comm;
  634. X        }
  635. X        printf("%-*s ", MAXCOMLEN, name );
  636. X}
  637. X
  638. Xprintpid(pid)
  639. Xint pid;
  640. X{
  641. X    printf("%-6d ", pid);
  642. X}
  643. X
  644. X/*
  645. X * print a username based on uid
  646. X */ 
  647. Xprintuser(uid)
  648. Xint uid;
  649. X{
  650. X        struct passwd *pw;
  651. X        pw = getpwuid(uid);
  652. X        if (pw)
  653. X                printf("%-8.8s   ", pw->pw_name);
  654. X        return (pw != NULL);
  655. X}
  656. X
  657. Xstruct dinode *readinode(fd, fs, inum)
  658. Xint fd;
  659. Xstruct fs *fs;
  660. Xino_t inum;
  661. X{
  662. X        static struct dinode itab[MAXIPG];
  663. X        
  664. X        bread(fd, fsbtodb(fs, cgimin(fs, inum/fs->fs_ipg)), (char *)itab,
  665. X              fs->fs_ipg * sizeof (struct dinode));
  666. X        
  667. X        return &itab[inum%fs->fs_ipg];
  668. X}
  669. X
  670. Xname2uid(name)
  671. Xchar *name;
  672. X{
  673. X        struct passwd *pw;
  674. X        pw = getpwnam(name);
  675. X        if (pw)
  676. X                return pw->pw_uid;
  677. X        else {
  678. X                fprintf(stderr,"%s: no such user\n",name);
  679. X                return NOSUCH_USER;
  680. X        }
  681. X}
  682. X
  683. X
  684. X/*
  685. X * return a pointer to a user page
  686. X * this routine was liberally cribbed from the "top" program
  687. X * by William Lefebvre
  688. X */
  689. Xstruct user *getu(p, mem, kmem, swap)
  690. Xstruct proc *p;
  691. X{
  692. X        /* pad reads from swap to a page */
  693. X        static union {
  694. X                struct  user u;
  695. X                char    upages[UPAGES][NBPG];
  696. X        } user;
  697. X#if !defined(bsd)
  698. X        static struct ucred ucred;
  699. X#endif
  700. X        char *up;
  701. X        struct pte *pte, uptes[UPAGES];
  702. X        int n;
  703. X#define min(a,b)        (a < b ? a : b)
  704. X        /* try in core */
  705. X        if (p->p_flag & SLOAD) {
  706. X                mread(kmem, (daddr_t)p->p_addr,(char *)uptes, 
  707. X                      UPAGES * sizeof(struct pte));
  708. X                pte = uptes;
  709. X                for(up = (char *)&user, n = sizeof(struct user); n > 0; 
  710. X                    n -= NBPG) {
  711. X                        mread(mem, (daddr_t)(pte++->pg_pfnum * NBPG),
  712. X                              up,min(n,NBPG));
  713. X                        up += NBPG;
  714. X                }
  715. X        }
  716. X        else 
  717. X                mread(swap, (daddr_t)dtob(p->p_swaddr),
  718. X                      (char *)&user,sizeof(user));
  719. X#if !defined(bsd)       
  720. X        mread(kmem, (daddr_t)user.u.u_cred, &ucred, sizeof(ucred));
  721. X        user.u.u_cred = &ucred;
  722. X#endif
  723. X        return &user.u;
  724. X}
  725. X
  726. X
  727. X/*
  728. X * get the inode corresponding to current working directory
  729. X */
  730. Xstruct inode *getcdir(kmem, addr)
  731. Xint kmem;
  732. Xdaddr_t addr;
  733. X{
  734. X        static struct inode in;
  735. X        struct inode *cdir;
  736. X        
  737. X#if defined(ultrix)
  738. X        struct gnode g;
  739. X        mread(kmem, addr, &g, sizeof(g));
  740. X        cdir = GTOI(&g);
  741. X#endif
  742. X#if defined(bsd)
  743. X        mread(kmem, addr, &in, sizeof(in));
  744. X        cdir = ∈
  745. X#endif
  746. X#if defined(sun)
  747. X        struct vnode v;
  748. X        mread(kmem, addr, &v, sizeof(v));
  749. X        mread(kmem, (daddr_t)VTOI(&v), &in, sizeof(in));
  750. X        cdir = ∈
  751. X#endif
  752. X        return cdir;
  753. X}
  754. //E*O*F cwd.c//
  755.  
  756. echo x - cwd.1
  757. sed -e 's/^X//' > "cwd.1" << '//E*O*F cwd.1//'
  758. X.TH CWD 1 "Oct 17, 1989"
  759. X.SH NAME
  760. Xcwd \- print current working directory of running processes
  761. X.SH SYNOPSIS
  762. X.B cwd
  763. X[
  764. X.B usernames...
  765. X]
  766. X.br
  767. X.SH DESCRIPTION
  768. X.B Cwd
  769. Xreads the kernel data structures from memory and
  770. Xconstructs a pathname corresponding to the 
  771. X.B u.u_cdir
  772. Xkernel variable associated with each process on the system.
  773. XIf 
  774. X.B usernames 
  775. Xare specified as arguments, only processes belonging to those users
  776. Xwill be considered, the default is to report on all processes
  777. Xon the system. For each eligible process, the user name, process name,
  778. Xprocess id, and current working directory will be displayed. This command 
  779. Xnormally requires root permission unless
  780. Xyour disks are readable (a less than good idea). 
  781. X.B Cwd 
  782. Xcurrently only works on BSD based filesystems.
  783. X
  784. X.PP
  785. X.SH "SEE ALSO"
  786. XNcheck(8)
  787. X.SH BUGS
  788. X.B Cwd
  789. Xcannot report on 
  790. X.I NFS 
  791. Xpathnames.
  792. //E*O*F cwd.1//
  793.  
  794. exit 0
  795. -- 
  796. Cliff Spencer 
  797. spdcc!lemming!cspencer             lemming!cspencer@spdcc.com
  798.  
  799.