home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / compsrcs / unix / volume20 / process.cwd < prev    next >
Encoding:
Text File  |  1989-10-23  |  20.7 KB  |  806 lines

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