home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / compsrcs / unix / volume18 / ofiles < prev    next >
Encoding:
Text File  |  1989-03-23  |  35.8 KB  |  1,531 lines

  1. Path: wugate!wucs1!uunet!bbn.com!rsalz
  2. From: rsalz@uunet.uu.net (Rich Salz)
  3. Newsgroups: comp.sources.unix
  4. Subject: v18i056:  Find who has files open on BSD, Sun, etc.
  5. Message-ID: <1604@fig.bbn.com>
  6. Date: 22 Mar 89 23:06:51 GMT
  7. Lines: 1521
  8. Approved: rsalz@uunet.UU.NET
  9.  
  10. Submitted-by: abe@mace.cc.purdue.edu (Vic Abell)
  11. Posting-number: Volume 18, Issue 56
  12. Archive-name: ofiles
  13.  
  14. [  Just the thing to see who's preventing you from unmounting that disk...
  15.    --r$  ]
  16.  
  17. Show owner of open file or network connection.  Reports owner, process ID,
  18. access type, command and inode number.  The update looks up the owner of a
  19. network connection from its Protocol Control Block address (netstat -A).
  20. The program also underwent a general cleanup and lint was removed.  The
  21. man page was redone.  Ofiles compiles and runs on 4.3BSD, DYNIX 3.0.12
  22. (Balance) and 3.0.14 (Symmetry), SunOS 4.0 and ULTRIX 2.2.
  23.  
  24. Vic Abell, Purdue University Computing Center, abe@mace.cc.purdue.edu
  25.  
  26. #!/bin/sh
  27. # shar:    Shell Archiver
  28. #    Run the following text with /bin/sh to create:
  29. #    README
  30. #    Makefile
  31. #    ofiles.c
  32. #    ofiles.8l
  33. # By:    Vic Abell (Purdue University)
  34. echo shar: extracting README '(1315 characters)'
  35. sed 's/^XX//' << \SHAR_EOF > README
  36. XXOfiles shows the owner of an open file or network connection.
  37. XX
  38. XXC. Spencer is the original author of ofiles.  Michael Ditto, Tom Dunigan,
  39. XXAlexander Dupuy, Gary Nebbett and Richard Tobin made contributions.  Mike
  40. XXSpitzer, Ray Moody and Vik Lall of the Purdue University Computing Center
  41. XX(PUCC) adapted ofiles to a number of different UNIX environments.  I added
  42. XXthe network connection option.
  43. XX
  44. XXOfiles compiles and runs on 4.3BSD, DYNIX 3.0.12 (Balance) and 3.0.14
  45. XX(Symmetry), SunOS 4.0 and ULTRIX 2.2.  It is free of lint on those systems
  46. XXaccording to the lint libraries in use at PUCC.
  47. XX
  48. XXSpecial notes:
  49. XX
  50. XX    1.  A "generic" Makefile is included.  You may have to adjust it
  51. XX        to your local conditions.
  52. XX
  53. XX    2.  SunOS 4.0 loading requires "-lkvm", so modify the Makefile
  54. XX        accordingly when you port ofiles to your Sun system.
  55. XX
  56. XX    3.  Ofiles needs permission to read /dev/drum (swap files), /dev/kmem
  57. XX        and /dev/mem.  PUCC uses a "setgid kmem" approach - i. e.,
  58. XX        /dev/{drum,kmem,mem} are in the kmem group and ofiles has mode
  59. XX        2755, group kmem.  The Makefile install rule implements this
  60. XX        convention.
  61. XX
  62. XXThe ofiles distribution includes:
  63. XX
  64. XX    README        this file
  65. XX    Makefile    a generic Makefile
  66. XX    ofiles.c    source
  67. XX    ofiles.8l    man page
  68. XX
  69. XXVic Abell, abe@mace.cc.purdue.edu
  70. XXPurdue University Computing Center
  71. XXMarch 22, 1989
  72. SHAR_EOF
  73. if test 1315 -ne "`wc -c README`"
  74. then
  75. echo shar: error transmitting README '(should have been 1315 characters)'
  76. fi
  77. echo shar: extracting Makefile '(738 characters)'
  78. sed 's/^XX//' << \SHAR_EOF > Makefile
  79. XX#
  80. XX#    Makefile for ofiles
  81. XX#
  82. XX
  83. XXPROG=    ofiles
  84. XXBIN=    ${DESTDIR}/usr/local/etc
  85. XX
  86. XXI=/usr/include
  87. XXS=/usr/include/sys
  88. XXL=/usr/include/local
  89. XX
  90. XXINCLUDE=
  91. XXDEBUG=    -O
  92. XXCDEFS=  
  93. XXCFLAGS= ${DEBUG} ${CDEFS} ${INCLUDE}
  94. XX
  95. XXHDR=    
  96. XXONEC=    ofiles.c
  97. XXOTHER=    
  98. XXSOURCE=    Makefile ${HDR} ${ONEC} ${OTHER}
  99. XX
  100. XXall: ${PROG}
  101. XX
  102. XX# SunOS 4.0 needs -lkvm in the following rule
  103. XX
  104. XX${PROG}:
  105. XX    ${CC} -o $@ ${CFLAGS} ${ONEC} 
  106. XX
  107. XXclean: FRC
  108. XX    rm -f Makefile.bak ${PROG} *.o a.out core errs tags
  109. XX
  110. XXinstall: all FRC
  111. XX    install -cs -m 2755 -g kmem ${PROG} ${BIN}
  112. XX
  113. XXlint: ${HDR} ${ONEC} FRC
  114. XX    lint ${CDEFS} ${INCLUDE} ${ONEC}
  115. XX
  116. XXprint: source FRC
  117. XX    lpr -J'${PROG} source' ${SOURCE}
  118. XX
  119. XXsource: ${SOURCE}
  120. XX
  121. XXspotless: clean
  122. XX    rcsclean ${SOURCE}
  123. XX
  124. XXtags: ${HDR} ${ONEC}
  125. XX    ctags -t ${HDR} ${ONEC}
  126. XX
  127. XX${SOURCE}:
  128. XX    co -q $@
  129. XX
  130. XXFRC:
  131. XX
  132. SHAR_EOF
  133. if test 738 -ne "`wc -c Makefile`"
  134. then
  135. echo shar: error transmitting Makefile '(should have been 738 characters)'
  136. fi
  137. echo shar: extracting ofiles.c '(24404 characters)'
  138. sed 's/^XX//' << \SHAR_EOF > ofiles.c
  139. XX/*    ofiles.c
  140. XX *
  141. XX *    ofiles [-d ] [-k nlist core] [-n] [-p] args
  142. XX *
  143. XX *    Show owner of open file or network connection.
  144. XX *
  145. XX *    Reports owner, process ID, access type, command and inode number.
  146. XX *
  147. XX *    -d        select verbose debugging output
  148. XX *
  149. XX *    -k nlist core    specifies alternative name list and core files
  150. XX *            (DYNIX only)
  151. XX *
  152. XX *    -n        interpret names as network connection, hexadecimal
  153. XX *            Protocol Control Block (PCB) addresses
  154. XX *
  155. XX *    -p          gives brief (pids only) report
  156. XX *
  157. XX *    names        file names, file system names or network connection
  158. XX *            PCB addresses
  159. XX *
  160. XX *    Stat each file or file system argument and scan the process table,
  161. XX *    looking for a match in the associated user structure's file lists.
  162. XX *
  163. XX *    Follow each PCB arg to the Internet Protocol Control Block (INPCB),
  164. XX *    thence to the socket; then scan the file table to find the file
  165. XX *    structure address associated with the socket; finally, scan the
  166. XX *    process table, looking for a nacth in the associated user structure's
  167. XX *    file lists.
  168. XX *
  169. XX *    Doesn't handlle remote NFS files.
  170. XX */
  171. XX
  172. XX/*
  173. XX *    Authors:
  174. XX *
  175. XX *    The orignal author is:
  176. XX *
  177. XX *        C. Spencer
  178. XX *
  179. XX *    Contributors include:
  180. XX *
  181. XX *        Michael Ditto
  182. XX *        Tom Dunigan
  183. XX *        Alexander Dupuy
  184. XX *        Greg Nebbett
  185. XX *        Richard Tobin
  186. XX *
  187. XX *    From the Purdue University Computing Center:
  188. XX *
  189. XX *        Mike Spitzer         converted to 4.3BSD, DYNIX 3.0.1[24]
  190. XX *        Ray Moody        SunOS 4.0 and ULTRIX 2.2
  191. XX *        Vik Lall
  192. XX *
  193. XX *        Vic Abell        added socket option and removed lint
  194. XX *                
  195. XX */
  196. XX
  197. XX#ifndef lint
  198. XXstatic char rcsid[]="$Header: /usr/src/local/etc/ofiles/RCS/ofiles.c,v 1.5 89/01/26 16:20:11 vik Exp $";
  199. XX#endif /* lint */
  200. XX
  201. XX#include <sys/param.h>
  202. XX#include <sys/dir.h>
  203. XX#include <sys/user.h>
  204. XX
  205. XX#ifdef DYNIX
  206. XX#define KERNEL
  207. XX#include <sys/file.h>
  208. XX#include <sys/vnode.h>
  209. XX#include <sys/inode.h>
  210. XX#undef KERNEL
  211. XX#else
  212. XX#define KERNEL
  213. XX#include <sys/file.h>
  214. XX#ifndef sun
  215. XX#include <sys/inode.h>
  216. XX#endif
  217. XX#undef KERNEL
  218. XX#endif
  219. XX
  220. XX#include <machine/pte.h>
  221. XX#if !defined(ultrix) && !defined(sun)
  222. XX#include <machine/machparam.h>
  223. XX#endif
  224. XX#include <sys/proc.h>
  225. XX#include <nlist.h>
  226. XX#include <sys/stat.h>
  227. XX#include <pwd.h>
  228. XX#include <fstab.h>
  229. XX#include <sys/vmmac.h>
  230. XX#include <stdio.h>
  231. XX
  232. XX#ifdef sun
  233. XX#include <sys/vnode.h>
  234. XX#include "/usr/src/sys/specfs/snode.h"
  235. XX#include <ufs/inode.h>
  236. XX#include <kvm.h>
  237. XXkvm_t    *kd;
  238. XX#endif
  239. XX
  240. XX#ifdef ultrix
  241. XX#include <sys/gnode.h>
  242. XX#include <sys/gnode_common.h>
  243. XX#include <machine/param.h>
  244. XX#endif
  245. XX
  246. XX#include <sys/socket.h>
  247. XX#include <sys/socketvar.h>
  248. XX#include <net/route.h>
  249. XX#include <netinet/in.h>
  250. XX#include <netinet/in_pcb.h>
  251. XX#include <netinet/tcp.h>
  252. XX#include <netinet/tcp_fsm.h>
  253. XX#include <netinet/tcp_timer.h>
  254. XX#include <netinet/tcp_var.h>
  255. XX
  256. XX#define CDIR    01
  257. XX#define OFILE    02
  258. XX#define RDIR    04
  259. XX#define SHFILE    010
  260. XX#define EXFILE    020
  261. XX#define SOCKET  040
  262. XX
  263. XXchar *namelist;
  264. XXchar *corefile;
  265. XXint k_opt = 0;
  266. XXint n_opt = 0;
  267. XX
  268. XX#ifdef    ultrix
  269. XX#define    ls_t    long
  270. XX#else
  271. XX#define ls_t    off_t
  272. XX#endif
  273. XX
  274. XX#ifdef    sun
  275. XXchar    *sprintf();
  276. XX#endif
  277. XX
  278. XXls_t lseek(), vtophys();
  279. XX
  280. XXvoid eread(), eseek();
  281. XX#ifdef    ultrix
  282. XXvoid exit(), nlist(), perror();
  283. XX#endif
  284. XX
  285. XXint nproc;        /* number of entries in proc table         */
  286. XXint mem;        /* fd for /dev/mem                */
  287. XXint kmem;
  288. XXint swap;        /* fd for /dev/swap                */
  289. XXlong procbase;
  290. XXint ppid = -1;        /* previously display PID */
  291. XX
  292. XXint dirinode;        /* directory (CDIR or RDIR) inode */
  293. XXint opninode;        /* save inode of open file */
  294. XXint pids_only = 0;    /* if non-zero, only output process ids    */
  295. XX
  296. XXchar *progname;
  297. XXstruct nlist nl[] = {
  298. XX#define    X_PROC        0
  299. XX    { "_proc" },
  300. XX#define X_NPROC     1
  301. XX    {"_nproc"},
  302. XX#define X_USRPTMA    2
  303. XX        {"_Usrptmap"},    
  304. XX#define X_USRPT        3
  305. XX    {"_usrpt"},
  306. XX#define X_SYSMAP    4
  307. XX    {"_Sysmap"},
  308. XX#define    SFIL        5
  309. XX    { "_file" },
  310. XX#define    SNFILE        6
  311. XX    { "_nfile" },
  312. XX    { "" },
  313. XX};
  314. XX
  315. XX#ifndef    DYNIX
  316. XXstruct pte *usrpt, *Usrptma;
  317. XX#endif
  318. XX
  319. XXint debug;
  320. XX
  321. XXmain(argc, argv)
  322. XX    int     argc;
  323. XX    char    *argv[];
  324. XX{
  325. XX
  326. XX#ifdef ultrix
  327. XX    struct gnode *i, *getinode();
  328. XX#else
  329. XX    struct inode *i, *getinode();
  330. XX#endif
  331. XX    struct stat s;
  332. XX    struct user *u, *getuser();
  333. XX    struct proc p;
  334. XX    register int filen, flags, procn;
  335. XX    register char *filename, *fsname;
  336. XX    struct fstab *fs, *getfsfile(), *getfsspec();
  337. XX    char *getsockfp(), *rindex();
  338. XX    struct file *fp;
  339. XX    int ax, err, findf, nmct;
  340. XX    char *ap;
  341. XX    int exitval = 0;
  342. XX
  343. XX#ifdef    lint
  344. XX/*
  345. XX * The following code satisfies lint for KERNEL symbols.
  346. XX * This program is lint-free under 4.3BSD, DYNIX 3.0.1[24], SunOS 4.0
  347. XX * and ULTRIX 2.2, using the lint libraries of the systems at the
  348. XX * Purdue University Computing Center.
  349. XX */
  350. XX#if    !defined(ultrix) && !defined(DYNIX) && !defined(sun)
  351. XX    long lintlong;
  352. XX#endif
  353. XX#ifdef    ultrix
  354. XX    struct nch *lintnch;
  355. XX    float lintfloat;
  356. XX#endif
  357. XX#if    !defined(DYNIX)
  358. XX    file = fileNFILE = NULL;
  359. XX    fp = file;
  360. XX    fp = fileNFILE;
  361. XX    nfile = 0;
  362. XX    filen = nfile;
  363. XX#endif
  364. XX#if    !defined(ultrix) && !defined(DYNIX) && !defined(sun)
  365. XX    inode = inodeNINODE = rootdir = NULL;
  366. XX    i = inode;
  367. XX    i = inodeNINODE;
  368. XX    i = rootdir;
  369. XX    ninode = 0;
  370. XX    nextinodeid = 0l;
  371. XX    lintlong = nextinodeid;
  372. XX    nextinodeid = lintlong;
  373. XX    filen = ninode;
  374. XX#endif
  375. XX#ifdef    sun
  376. XX    tcp_ttl = 0;
  377. XX    filen  = tcp_ttl;
  378. XX#endif
  379. XX#ifdef    ultrix
  380. XX    nch = NULL;
  381. XX    lintnch = nch;
  382. XX    nch = lintnch;
  383. XX    nchsize = 0;
  384. XX    filen = nchsize;
  385. XX    tcp_alpha = tcp_beta = 0.0;
  386. XX    lintfloat = tcp_alpha;
  387. XX    lintfloat = tcp_beta;
  388. XX    tcp_alpha = lintfloat;
  389. XX#endif
  390. XX#endif    /* lint */
  391. XX
  392. XX    if ((progname = rindex(argv[0], '/')))
  393. XX        progname++;
  394. XX    else
  395. XX        progname = argv[0];
  396. XX
  397. XX    if (argc == 1) {
  398. XX
  399. XXusage:
  400. XX
  401. XX#ifdef    DYNIX
  402. XX        (void) fprintf(stderr,
  403. XX            "usage: %s [-d ] [-k nlist core] [-n] [-p] names\n",
  404. XX            progname);
  405. XX#else
  406. XX        (void) fprintf(stderr,
  407. XX            "usage: %s [-d ] [-n] [-p] names\n", progname);
  408. XX#endif
  409. XX        (void) fprintf(stderr, "\t-d    = select verbose debugging output\n");
  410. XX#ifdef    DYNIX
  411. XX        (void) fprintf(stderr,
  412. XX            "\t-k    = use specified nlist and core files\n");
  413. XX#endif
  414. XX        (void) fprintf(stderr,
  415. XX            "\t-n    = interpret names as network connection, hexadecimal,\n");
  416. XX        (void) fprintf(stderr,
  417. XX            "\t        Protocol Control Block (PCB) addresses, as supplied\n");
  418. XX        (void) fprintf(stderr,
  419. XX            "\t        by netstat's -A option\n");
  420. XX        (void) fprintf(stderr, "\t-p    = print only process IDs\n");
  421. XX        (void) fprintf(stderr,
  422. XX            "\tnames = file names or PCB addresses\n");
  423. XX        exit(exitval);
  424. XX    }
  425. XX
  426. XX    /* check for switches */
  427. XX    for (err = 0, ax = 1; ax < argc; ax++) {
  428. XX        ap = argv[ax];
  429. XX        if (*ap++ != '-')
  430. XX            break;
  431. XX        while (*ap) {
  432. XX            switch (*ap++) {
  433. XX
  434. XX            case 'd':
  435. XX                debug = 1;
  436. XX                break;
  437. XX#ifdef    DYNIX
  438. XX            case 'k':
  439. XX                if ((ax + 2) >= argc) {
  440. XX                    (void) fprintf(stderr,
  441. XX                        "%s: no nlist/core after -k\n",
  442. XX                        progname);
  443. XX                    err++;
  444. XX                } else {
  445. XX                    namelist = argv[++ax];
  446. XX                    corefile = argv[++ax];
  447. XX                    k_opt = 1;
  448. XX                    continue;
  449. XX                }
  450. XX                break;
  451. XX#endif
  452. XX            case 'n':
  453. XX                n_opt++;
  454. XX                break;
  455. XX
  456. XX            case 'p':
  457. XX                pids_only = 1;
  458. XX                break;
  459. XX
  460. XX            default:
  461. XX                (void) fprintf(stderr,
  462. XX                    "%s: unknown switch - %c\n",
  463. XX                    progname, *(ap - 1));
  464. XX                err++;
  465. XX            }
  466. XX        }
  467. XX    }
  468. XX    if (ax >= argc) {
  469. XX        (void) fprintf(stderr, "%s: no names specified\n", progname);
  470. XX        err++;
  471. XX    }
  472. XX    if (err) {
  473. XX        exitval = 1;
  474. XX        goto usage;
  475. XX    }
  476. XX
  477. XX#ifdef sun
  478. XX        if ((kd = kvm_open (NULL, NULL, NULL, O_RDONLY)) == 0) {
  479. XX        (void) fprintf(stderr, "%s: can't access memory: ",
  480. XX            progname);
  481. XX            perror ("");
  482. XX        exit(1);
  483. XX    }
  484. XX#endif
  485. XX    if ((mem = open("/dev/mem", 0)) < 0) {
  486. XX        (void) fprintf(stderr, "%s: /dev/mem: ", progname);
  487. XX        perror("");
  488. XX        exit(1);
  489. XX    }
  490. XX    if (k_opt) {
  491. XX        if ((kmem = open(corefile, 0)) < 0) {
  492. XX            (void) fprintf(stderr, "%s: %s: ",
  493. XX                progname, corefile);
  494. XX            perror("");
  495. XX            exit(1);
  496. XX        }
  497. XX    } else {
  498. XX        if ((kmem = open("/dev/kmem", 0)) < 0) {
  499. XX            (void) fprintf(stderr, "%s: /dev/kmem: ", progname);
  500. XX            perror("");
  501. XX            exit(1);
  502. XX        }
  503. XX    }
  504. XX    if (!k_opt) 
  505. XX        if ((swap = open("/dev/drum", 0)) < 0) {
  506. XX            (void) fprintf(stderr, "%s: /dev/drum: ", progname);
  507. XX            perror("");
  508. XX            exit(1);
  509. XX        }
  510. XX
  511. XX    getsyms();
  512. XX
  513. XX    for (err = 0, nmct = argc - ax; ax < argc; ax++) {
  514. XX        /* if -n, then arg is a PCB */
  515. XX        if (n_opt) {
  516. XX            if ((filename = getsockfp(argv[ax], &fp)) == NULL) {
  517. XX                err++;
  518. XX                continue;
  519. XX            }
  520. XX            fsname = "";
  521. XX        } else {
  522. XX            /* assume arg is  a filesystem */
  523. XX            if ((fs = getfsfile(argv[ax])) != NULL) {
  524. XX                fsname = argv[ax];
  525. XX                if (strcmp(".", argv[ax]) == 0)
  526. XX                    filename = argv[ax];
  527. XX                else
  528. XX                    filename = fs->fs_spec;
  529. XX            /* maybe it's the device name for a filesystem */
  530. XX            } else if ((fs = getfsspec(argv[ax])) != NULL) {
  531. XX                filename = argv[ax];
  532. XX                fsname = fs->fs_file;
  533. XX            /* probably a regular file */
  534. XX            } else {
  535. XX                filename = argv[ax];
  536. XX                fsname = "";
  537. XX            }
  538. XX            if (stat(filename, &s)) {
  539. XX                (void) fprintf(stderr, "%s: can't stat %s: ",
  540. XX                    progname, filename);
  541. XX                perror("");
  542. XX                err++;
  543. XX                continue;
  544. XX            }
  545. XX            if (debug)
  546. XX                (void) printf(
  547. XX                    "stat dev %x ino %d mode %x rdev %x\n",
  548. XX                    s.st_dev, s.st_ino, s.st_mode,
  549. XX                    s.st_rdev);
  550. XX        }
  551. XX        if (! pids_only) {
  552. XX            (void) printf("%s\t%s", filename, fsname);
  553. XX            if (!n_opt) {
  554. XX                if ((s.st_mode & S_IFMT) == S_IFDIR)
  555. XX                    (void) printf("(directory)");
  556. XX            }
  557. XX            (void) printf("\n%-8.8s  %5s  %-6.6s  FD  %-14.14s",
  558. XX                "USER", "PID", "TYPE", "CMD");
  559. XX            if (!n_opt)
  560. XX                (void) printf("  INODE");
  561. XX            (void) printf("\n");
  562. XX        }
  563. XX        for (findf = procn = 0; procn < nproc; procn++) {
  564. XX            procslot(procn, &p);
  565. XX            flags = 0;
  566. XX            if (p.p_stat == 0 || p.p_stat == SZOMB) 
  567. XX                continue;
  568. XX#ifdef sun
  569. XX                u = kvm_getu(kd, &p);
  570. XX#else
  571. XX            u = getuser(&p);
  572. XX#endif
  573. XX
  574. XX            if ( u == (struct user *)NULL)
  575. XX                continue;
  576. XX            if (debug)
  577. XX                (void) printf("pid %d uid %d cmd %s\n", p.p_pid,
  578. XX                    p.p_uid, u->u_comm);
  579. XX            if (!n_opt) {
  580. XX                i = getinode(u->u_rdir, "rdir");
  581. XX                if (check(&s, i)) {
  582. XX                    dirinode = s.st_ino;
  583. XX                    gotone(u, &p, -1, RDIR);
  584. XX                    findf++;
  585. XX                }
  586. XX                i = getinode(u->u_cdir, "cdir");
  587. XX                if (check(&s, i)) {
  588. XX                    dirinode = s.st_ino;
  589. XX                    gotone(u, &p, -1, CDIR);
  590. XX                    findf++;
  591. XX                }
  592. XX            }
  593. XX#ifdef    DYNIX
  594. XX            for (filen = 0; filen < u->u_nofile; filen++)
  595. XX#else
  596. XX            for (filen = 0; filen < NOFILE; filen++)
  597. XX#endif    
  598. XX            {
  599. XX                struct file f;
  600. XX
  601. XX                flags = 0;
  602. XX                if (n_opt) {
  603. XX#ifdef    DYNIX
  604. XX                    if (u->u_lofile[filen].of_file != fp)
  605. XX#else
  606. XX                    if (u->u_ofile[filen] != fp)
  607. XX#endif
  608. XX                        continue;
  609. XX                } else {
  610. XX#ifdef    DYNIX
  611. XX                    if (u->u_lofile[filen].of_file == NULL)
  612. XX                        continue;
  613. XX#else
  614. XX                    if (u->u_ofile[filen] == NULL)
  615. XX                        continue;
  616. XX#endif
  617. XX                }
  618. XX
  619. XX                if (k_opt)
  620. XX#ifdef    DYNIX
  621. XX                    eseek(kmem, vtophys((ls_t)u->u_lofile[filen].of_file), 0, "file");
  622. XX#else
  623. XX                eseek(kmem, vtophys((ls_t)u->u_ofile[filen]), 0, "file");
  624. XX#endif 
  625. XX                else
  626. XX#ifdef    DYNIX
  627. XX                    eseek(kmem, (ls_t)u->u_lofile[filen].of_file, 0, "file");
  628. XX#else
  629. XX                eseek(kmem, (ls_t)u->u_ofile[filen], 0, "file");
  630. XX#endif
  631. XX                eread(kmem, (char *)&f, sizeof(f), "file");
  632. XX
  633. XX                if (f.f_count > 0) {
  634. XX                    if (n_opt && f.f_type == DTYPE_SOCKET) {
  635. XX                        gotone(u, &p, filen, SOCKET);
  636. XX                        findf++;
  637. XX                        continue;
  638. XX                    }
  639. XX#if    defined(DYNIX) || defined(sun)
  640. XX                    if (f.f_type != DTYPE_VNODE)
  641. XX#else
  642. XX                    if (f.f_type != DTYPE_INODE)
  643. XX#endif
  644. XX                        continue;
  645. XX#if    defined(DYNIX) || defined(sun)
  646. XX                    i = getinode((struct vnode *)f.f_data,
  647. XX                        "ofile");
  648. XX#else
  649. XX#ifdef    ultrix
  650. XX                    i = getinode((struct gnode *)f.f_data,
  651. XX                        "ofile");
  652. XX#else
  653. XX                    i = getinode((struct inode *)f.f_data,
  654. XX                        "ofile");
  655. XX#endif
  656. XX#endif
  657. XX                    if (check(&s, i)) {
  658. XX#if !defined(ultrix)
  659. XX                        opninode = i->i_number;
  660. XX#else
  661. XX                        opninode = (int)i->g_req.gr_number;
  662. XX#endif
  663. XX                        flags |= OFILE;
  664. XX                        if (f.f_flag & FEXLOCK) {
  665. XX                            flags |= EXFILE;
  666. XX                        }
  667. XX                        if (f.f_flag & FSHLOCK) {
  668. XX                            flags |= SHFILE;
  669. XX                        }
  670. XX                        gotone(u, &p, filen, flags);
  671. XX                        findf++;
  672. XX                    }
  673. XX                }
  674. XX            }
  675. XX        }
  676. XX        if (findf)
  677. XX            nmct--;
  678. XX        if (! pids_only) {
  679. XX                (void) printf("\n");
  680. XX            (void) fflush(stdout);
  681. XX        }
  682. XX    }
  683. XX    if (pids_only && ppid != -1) {
  684. XX        (void) printf("\n");
  685. XX        (void) fflush(stdout);
  686. XX    }
  687. XX    exitval = (err || nmct) ? 1 : 0;
  688. XX    exit(exitval);
  689. XX}        
  690. XX
  691. XX/*
  692. XX * print the name of the user owning process "p" and the pid of that process
  693. XX */
  694. XXgotone(u, p, fd, f)
  695. XX    struct user *u;
  696. XX    struct proc *p;
  697. XX    int fd;
  698. XX    int f;
  699. XX{
  700. XX    char *ty, tybuf[8], *strcat(), *strcpy();
  701. XX    struct passwd *getpwuid();
  702. XX    register struct passwd *pw;
  703. XX
  704. XX    /* only print pids and return */
  705. XX    if (pids_only) {
  706. XX        if (ppid != p->p_pid) {
  707. XX            if (ppid != -1)
  708. XX                (void) printf(" ");
  709. XX            (void) printf("%d", p->p_pid);
  710. XX            (void) fflush(stdout);
  711. XX            ppid = p->p_pid;
  712. XX        }
  713. XX        return;
  714. XX    }
  715. XX    pw = getpwuid((int)p->p_uid);
  716. XX    if (pw)
  717. XX        (void) printf("%-8.8s  ", pw->pw_name );
  718. XX    else
  719. XX        (void) printf("%-8d  ", p->p_uid);
  720. XX    (void) printf("%5d  ", p->p_pid);
  721. XX    if (f & OFILE) {
  722. XX        (void) strcpy(tybuf, "file");
  723. XX        ty = tybuf;
  724. XX        if (f & SHFILE)
  725. XX            (void) strcat(ty, "/s");
  726. XX        else if (f & EXFILE)
  727. XX            (void) strcat(ty, "/x");
  728. XX    } else if (f & CDIR)
  729. XX        ty = "cwd";
  730. XX    else if (f & RDIR)
  731. XX        ty = "rdir";
  732. XX    else if (f & SOCKET)
  733. XX        ty = "sock";
  734. XX    else
  735. XX        ty = "";
  736. XX    (void) printf("%-6.6s  ", ty);
  737. XX    if (fd >= 0)
  738. XX        (void) printf("%2d  ", fd);
  739. XX    else
  740. XX        (void) printf("    ");
  741. XX    (void) printf("%-14.14s", u->u_comm);
  742. XX    if (f & OFILE)
  743. XX        (void) printf("  %5d", opninode);
  744. XX    else if (f & (CDIR|RDIR))
  745. XX        (void) printf("  %5d", dirinode);
  746. XX    (void) printf("\n");
  747. XX    return;
  748. XX}
  749. XX
  750. XX/*
  751. XX * is inode "i" on device "s"? returns TRUE or FALSE 
  752. XX */
  753. XXcheck(s, i)
  754. XX    struct stat *s;
  755. XX#ifdef ultrix
  756. XX    struct gnode *i;
  757. XX#else
  758. XX    struct inode *i;
  759. XX#endif
  760. XX{
  761. XX    if (s == (struct stat *)NULL)
  762. XX        return 0;
  763. XX#ifdef ultrix
  764. XX    if (i == (struct gnode *)NULL)
  765. XX        return 0;
  766. XX    if ((s->st_mode & S_IFMT) == S_IFBLK && s->st_rdev == i->g_dev)
  767. XX            return 1;
  768. XX    else if ((s->st_dev == i->g_dev) && (s->st_ino == i->g_req.gr_number))
  769. XX            return 1;
  770. XX#else
  771. XX    if (i == (struct inode *)NULL) return 0;
  772. XX    if ((s->st_mode & S_IFMT) == S_IFBLK && s->st_rdev == i->i_dev)
  773. XX            return 1;
  774. XX    else if ((s->st_dev == i->i_dev) && (s->st_ino == i->i_number))
  775. XX            return 1;
  776. XX#endif
  777. XX#ifdef sun
  778. XX    else if (s->st_rdev == i->i_dev && i->i_number == 0)
  779. XX            return 1;
  780. XX#endif
  781. XX    else return 0;
  782. XX}
  783. XX
  784. XX
  785. XX/* 
  786. XX *    getinode - read an inode from from mem at address "addr"
  787. XX *           return pointer to inode struct. 
  788. XX */
  789. XX#if defined(DYNIX) || defined(sun)
  790. XXstruct inode *
  791. XXgetinode(ip, s)
  792. XX    struct vnode *ip;
  793. XX    char *s;
  794. XX{
  795. XX    static struct inode i;
  796. XX    static struct vnode v;
  797. XX#ifdef    sun
  798. XX    struct snode sn;
  799. XX#endif
  800. XX
  801. XX    if (ip == NULL)
  802. XX        return(NULL);
  803. XX    if (k_opt)
  804. XX        eseek(kmem, vtophys((ls_t)ip), 0, "vnode");
  805. XX    else
  806. XX        eseek(kmem, (ls_t)ip, 0, "vnode");
  807. XX    eread(kmem, (char *)&v, sizeof(v), "vnode");
  808. XX    if (debug)
  809. XX        (void) printf("vnode %s at %x %x dev=%x vtype=%d inode@%x\n",
  810. XX             s, ip, v.v_flag, v.v_rdev, v.v_type, v.v_data);
  811. XX    if (k_opt)
  812. XX        eseek(kmem, vtophys((ls_t)v.v_data), 0, "inode");
  813. XX    else
  814. XX        eseek(kmem, (ls_t)v.v_data, 0, "inode");
  815. XX#ifdef    sun
  816. XX    if (v.v_type == VBLK || v.v_type == VCHR || v.v_type == VFIFO) {
  817. XX        eread(kmem, (char *)&sn, sizeof(sn), "snode");
  818. XX        if (debug)
  819. XX            (void) printf(
  820. XX                "snode %s at %x %x dev=%x realvp=%x bdevvp=%x\n",
  821. XX                s, ip, sn.s_vnode.v_type, sn.s_dev,
  822. XX                sn.s_realvp, sn.s_bdevvp);
  823. XX        if (sn.s_realvp || sn.s_bdevvp) {
  824. XX            eseek(kmem,
  825. XX                (sn.s_realvp) ? (ls_t)sn.s_realvp
  826. XX                          : (ls_t)sn.s_bdevvp,
  827. XX                0, "rvnode");
  828. XX            eread(kmem, (char *)&v, sizeof(v), "rvnode");
  829. XX            eseek(kmem, (ls_t)v.v_data, 0, "rinode");
  830. XX        }
  831. XX    }
  832. XX#endif
  833. XX    eread(kmem, (char *)&i, sizeof(i), "inode");
  834. XX    if (debug)
  835. XX        (void) printf("inode %s at %x %x dev=%x inode=%d vtype=%x\n",
  836. XX            s, v.v_data, i.i_flag, i.i_dev, i.i_number,
  837. XX            i.i_vnode.v_type);
  838. XX    return &i;
  839. XX}
  840. XX
  841. XX#else
  842. XX/* ARGSUSED */
  843. XX
  844. XX#ifdef ultrix
  845. XXstruct gnode *
  846. XXgetinode(ip, s)
  847. XX    struct gnode *ip;
  848. XX#else
  849. XX
  850. XXstruct inode *
  851. XXgetinode(ip, s)
  852. XX    struct inode *ip;
  853. XX#endif
  854. XX
  855. XX    char *s;
  856. XX{
  857. XX#if defined(ultrix) 
  858. XX    static struct gnode i;
  859. XX#else
  860. XX    static struct inode i;
  861. XX#endif
  862. XX
  863. XX    eseek(kmem, (ls_t)ip, 0, "inode");
  864. XX    eread(kmem, (char *)&i, sizeof(i), "inode");
  865. XX    return &i;
  866. XX}
  867. XX#endif
  868. XX
  869. XX#if !defined(sun)
  870. XX/* 
  871. XX * get user page for proc "p" from core or swap
  872. XX * return pointer to user struct
  873. XX */
  874. XX#ifdef    DYNIX
  875. XXstruct user *
  876. XXgetuser(p)
  877. XX    struct proc *p;
  878. XX{
  879. XX    int btr;
  880. XX    ls_t sp;
  881. XX    static struct user *u = NULL;
  882. XX    char *valloc();
  883. XX
  884. XX    if (u == NULL) {
  885. XX        if ((u = (struct user *) valloc(ctob(UPAGES))) == NULL) {
  886. XX            (void) fprintf(stderr,
  887. XX                "%s: can't allocate space for user structure\n",                progname);
  888. XX            exit(1);
  889. XX        }
  890. XX    }
  891. XX    btr = ctob(UPAGES);
  892. XX    if ((p->p_flag & SLOAD) == 0) {
  893. XX        if (k_opt)
  894. XX            return (struct user *)NULL;
  895. XX        sp = (ls_t) dtob(p->p_swaddr);
  896. XX        if (lseek(swap, sp, 0) != sp) {
  897. XX            if (debug) {
  898. XX                (void) fprintf(stderr,
  899. XX                    "%s: error seeking to swap for %d: ",
  900. XX                    progname, p->p_pid);
  901. XX                perror("");
  902. XX            }
  903. XX            return (struct user *)NULL;
  904. XX        }
  905. XX        if (read(swap, (char*)u, btr) != btr) {
  906. XX            if (debug) {
  907. XX                (void) fprintf(stderr,
  908. XX                    "%s: error reading swap for %d: ",
  909. XX                    progname, p->p_pid);
  910. XX                perror("");
  911. XX            }
  912. XX            return (struct user *)NULL;
  913. XX        }
  914. XX        if (debug)
  915. XX            (void) printf("read swap\n");
  916. XX    } else {
  917. XX        if (k_opt)
  918. XX            (void) lseek(kmem, vtophys((ls_t)p->p_uarea), L_SET);
  919. XX        else
  920. XX            (void) lseek(kmem, (ls_t)p->p_uarea, L_SET);
  921. XX        if (read(kmem, (char *)u, btr) != btr)
  922. XX            return (struct user *)NULL;
  923. XX    }
  924. XX    return u;
  925. XX}
  926. XX#else
  927. XXstruct user *
  928. XXgetuser(p)
  929. XX    struct proc *p;
  930. XX{
  931. XX    struct pte *ptep, apte;
  932. XX    struct pte mypgtbl[NBPG/sizeof(struct pte)];
  933. XX    int upage;
  934. XX    char *up;
  935. XX    static struct user user;
  936. XX
  937. XX    /* easy way */
  938. XX    if ((p->p_flag & SLOAD) == 0) {
  939. XX        if (k_opt)
  940. XX            return (struct user *)NULL;
  941. XX        (void) lseek(swap, (ls_t)dtob(p->p_swaddr), 0);
  942. XX        if (read(swap, (char *)&user, sizeof(struct user))==0) {
  943. XX            (void) fprintf(stderr,
  944. XX                "%s: can't get swapped user page\n",
  945. XX                progname);
  946. XX            return (struct user *)NULL;
  947. XX        }
  948. XX        if (debug)
  949. XX            (void) printf("read swap\n");
  950. XX    } else {     /* boo */
  951. XX        ptep = &Usrptma[btokmx(p->p_p0br) + p->p_szpt - 1];
  952. XX
  953. XX        /* get the page table for the user page */
  954. XX        (void) lseek(kmem, (ls_t)ptep, 0);
  955. XX        if (read(kmem, (char *)&apte, sizeof(apte)) == 0) {
  956. XX            (void) fprintf(stderr,
  957. XX                "%s: can't get user page table\n",
  958. XX                progname);
  959. XX            return (struct user *)NULL;
  960. XX        }
  961. XX
  962. XX        /* now get this user's page table */
  963. XX        eseek(mem, (ls_t)ctob(apte.pg_pfnum) ,0, "page tbl");
  964. XX        if (read(mem, (char *)mypgtbl, sizeof(mypgtbl)) == 0) {
  965. XX            (void) fprintf(stderr,
  966. XX                "%s: can't get mypgtbl.\n", progname);
  967. XX            return (struct user *)NULL;
  968. XX        }
  969. XX        /* now collect various pages of u area */
  970. XX        for (upage = 0, up = (char *)&user; upage < sizeof(struct user)/NBPG; upage++) {
  971. XX            eseek(mem, (ls_t)ctob(mypgtbl[NPTEPG-UPAGES+upage].pg_pfnum), 0, "u page");
  972. XX            if (read(mem, up, NBPG) == 0) {
  973. XX                (void) fprintf(stderr,
  974. XX                    "%s: can't get page %d of user area.\n",
  975. XX                    progname, upage);
  976. XX                return(NULL);
  977. XX            }
  978. XX            up += NBPG;
  979. XX        }
  980. XX    }
  981. XX    return &user;
  982. XX}
  983. XX#endif
  984. XX
  985. XX#endif
  986. XX/*
  987. XX * read with error checking
  988. XX */
  989. XXvoid
  990. XXeread(fd, p, size, s)
  991. XX    int fd;
  992. XX    char *p;
  993. XX    int size;
  994. XX    char *s;
  995. XX{
  996. XX    char buf[100];
  997. XX    if (read(fd, p, size) != size) {
  998. XX        if (!k_opt) {
  999. XX            (void) fprintf(stderr, "%s: eread ", progname);
  1000. XX            perror("");
  1001. XX        }
  1002. XX        (void) sprintf(buf, "read error for %s\n", s);
  1003. XX        error(buf);
  1004. XX    }
  1005. XX}
  1006. XX
  1007. XX/*
  1008. XX * seek with error checking
  1009. XX */
  1010. XXvoid
  1011. XXeseek(fd, off, whence, s)
  1012. XX    int fd;
  1013. XX    ls_t off;
  1014. XX    int whence;
  1015. XX    char *s;
  1016. XX{
  1017. XX    ls_t ret;
  1018. XX    char buf[100];
  1019. XX
  1020. XX    if (( ret = lseek(fd, off, whence)) != off) {
  1021. XX        (void) sprintf(buf, "seek for %s failed, wanted %o, got %o.\n",
  1022. XX            s, off, ret);
  1023. XX        error(buf);
  1024. XX    }
  1025. XX}
  1026. XX
  1027. XX/*
  1028. XX * print mesg "s", don't exit if we are processing a core, 
  1029. XX * so that corrupt entries don't prevent further uncorrupted
  1030. XX * entries from showing up.
  1031. XX */
  1032. XXerror(s)
  1033. XX    char *s;
  1034. XX{
  1035. XX    if (s && !k_opt)
  1036. XX        (void) fprintf(stderr, "%s: %s", progname, s);
  1037. XX    if (!k_opt)
  1038. XX        exit(1);
  1039. XX}
  1040. XX
  1041. XX/*
  1042. XX * get some symbols form the kernel
  1043. XX */
  1044. XXgetsyms()
  1045. XX{
  1046. XX    register i;
  1047. XX
  1048. XX    if (k_opt) {
  1049. XX#ifdef    ultrix
  1050. XX        (void) nlist(namelist, nl);
  1051. XX#else    /* not ultrix */
  1052. XX        if (nlist(namelist, nl) == -1) {
  1053. XX            (void) fprintf(stderr,
  1054. XX                "%s: can't get name list from %s\n",
  1055. XX                progname, namelist);
  1056. XX            exit(1);
  1057. XX        }
  1058. XX#endif    /* ultrix */
  1059. XX    } else {
  1060. XX#ifdef    ultrix
  1061. XX        (void) nlist("/vmunix", nl);
  1062. XX#else    /* not ultrix */
  1063. XX#ifdef    DYNIX
  1064. XX        if (nlist("/dynix", nl) == -1)
  1065. XX#else    /* not DYNIX */
  1066. XX        if (nlist("/vmunix", nl) == -1)
  1067. XX#endif    /* DYNIX */
  1068. XX        {
  1069. XX            (void) fprintf(stderr,
  1070. XX                "%s: can't get name list from %s\n",
  1071. XX#ifdef    DYNIX
  1072. XX                progname, "/dynix");
  1073. XX#else    /* not DYNIX */
  1074. XX                progname, "/vmunix");
  1075. XX#endif    /* DYNIX */
  1076. XX            exit(1);
  1077. XX        }
  1078. XX#endif    /* ultrix */
  1079. XX    }
  1080. XX
  1081. XX    for (i = 0; i < (sizeof(nl)/sizeof(nl[0]))-1; i++)
  1082. XX        if (nl[i].n_value == 0) {
  1083. XX            (void) fprintf(stderr, "%s: can't nlist symbol %s\n",
  1084. XX                progname, nl[i].n_name);
  1085. XX            exit(1);
  1086. XX        }
  1087. XX
  1088. XX        eseek(kmem, (ls_t)(nl[X_PROC].n_value), 0, "procbase 1");
  1089. XX        eread(kmem, (char *)&procbase, sizeof(procbase), "procbase 1");
  1090. XX        eseek(kmem, (ls_t)(nl[X_NPROC].n_value), 0, "nproc");
  1091. XX        eread(kmem, (char *)&nproc, sizeof(nproc), "nproc");
  1092. XX
  1093. XX#ifndef    DYNIX
  1094. XX    Usrptma = (struct pte *)nl[X_USRPTMA].n_value;
  1095. XX    usrpt = (struct pte *)nl[X_USRPT].n_value;    /* used by <vmmac.h>*/
  1096. XX#endif
  1097. XX    return;
  1098. XX}
  1099. XX
  1100. XX/*
  1101. XX * read proc table entry "n" into buffer "p"
  1102. XX */
  1103. XXprocslot(n, p)
  1104. XX    int n;
  1105. XX    struct proc *p;
  1106. XX{
  1107. XX    if (k_opt)
  1108. XX        eseek(kmem, vtophys((ls_t)(procbase + (long)(n * sizeof(struct proc)))), 0, "proc");
  1109. XX    else
  1110. XX        eseek(kmem, (ls_t)(procbase + (long)(n * sizeof(struct proc))), 0, "proc");
  1111. XX    eread(kmem, (char *)p, sizeof(struct proc), "proc");
  1112. XX    return;
  1113. XX}
  1114. XX
  1115. XX/*
  1116. XX * When looking at kernel data space through /dev/mem or
  1117. XX * with a core file, do virtual memory mapping.
  1118. XX */
  1119. XXls_t
  1120. XXvtophys(vaddr)
  1121. XX    ls_t vaddr;
  1122. XX{
  1123. XX    u_int paddr;
  1124. XX    
  1125. XX#ifdef    i386
  1126. XX    if (vaddr < 8192)
  1127. XX        return vaddr;
  1128. XX#endif
  1129. XX    paddr = nl[X_SYSMAP].n_value;
  1130. XX    (void) lseek(kmem, (ls_t)paddr, 0);
  1131. XX    (void) read(kmem, (char *)&paddr, sizeof paddr);
  1132. XX    paddr = (int)((int *)paddr + (vaddr / NBPG));
  1133. XX    (void) lseek(kmem, (ls_t)paddr, 0);
  1134. XX    (void) read(kmem, (char *)&paddr, sizeof paddr);
  1135. XX#ifndef    i386
  1136. XX# define    PTBITS    0x1ff    /* 512 byte pages */
  1137. XX#else
  1138. XX# define    PTBITS    0xfff    /* 4096 byte pages */
  1139. XX#endif
  1140. XX
  1141. XX    return ((ls_t)(paddr & ~PTBITS) | (vaddr & PTBITS));
  1142. XX}
  1143. XX
  1144. XX/*
  1145. XX * get file pointer for socket
  1146. XX */
  1147. XXchar *
  1148. XXgetsockfp(cba, pfp)
  1149. XX    char *cba;
  1150. XX    struct file **pfp;
  1151. XX{
  1152. XX    register char *cp;
  1153. XX    struct file *socktofile();
  1154. XX    struct inpcb inpcb;
  1155. XX    static char nmbuf[128];
  1156. XX    struct socket sock;
  1157. XX    struct tcpcb tcpcb;
  1158. XX    long x;
  1159. XX
  1160. XX/*
  1161. XX * Convert PCB address from ASCII to hex.
  1162. XX */
  1163. XX    for (cp = cba, x = 0l; *cp; cp++) {
  1164. XX        x <<= 4;
  1165. XX        if (*cp >= '0' && *cp <= '9')
  1166. XX            x += *cp - '0';
  1167. XX        else if (*cp >= 'a' && *cp <= 'f')
  1168. XX            x += *cp - 'a' + 10;
  1169. XX        else if (*cp >= 'A' && *cp <= 'F')
  1170. XX            x += *cp - 'A' + 10;
  1171. XX        else {
  1172. XX            (void) fprintf(stderr,
  1173. XX                "%s: non-hex address, %s\n", progname, cba);
  1174. XX            return(NULL);
  1175. XX        }
  1176. XX    }
  1177. XX/*
  1178. XX * Read PCB and make sure it is in LISTEN or ESTABLISHED state.
  1179. XX */
  1180. XX    eseek(kmem, (ls_t)x, 0, "tcpcb");
  1181. XX    eread(kmem, (char *)&tcpcb, sizeof(tcpcb), "tcpcb");
  1182. XX    if (tcpcb.t_state < TCPS_LISTEN || tcpcb.t_state > TCPS_ESTABLISHED) {
  1183. XX        (void) fprintf(stderr,
  1184. XX            "%s: PCB %x not in LISTEN to ESTABLISHED state\n",
  1185. XX            progname, x);
  1186. XX        return(NULL);
  1187. XX    }
  1188. XX    if (tcpcb.t_inpcb == (struct inpcb *)0) {
  1189. XX        (void) fprintf(stderr,
  1190. XX            "%s: PCB %x has no INPCB\n",
  1191. XX            progname, x);
  1192. XX        return(NULL);
  1193. XX    }
  1194. XX/*
  1195. XX * Read INPCB for PCB and make sure it points back to the PCB.
  1196. XX */
  1197. XX    eseek(kmem, (ls_t)tcpcb.t_inpcb, 0, "inpcb");
  1198. XX    eread(kmem, (char *)&inpcb, sizeof(inpcb), "inpcb");
  1199. XX    if ((caddr_t)x != inpcb.inp_ppcb) {
  1200. XX        (void) fprintf(stderr,
  1201. XX            "%s: INPCB for PCB %x not linked to it\n",
  1202. XX            progname, x);
  1203. XX        return(NULL);
  1204. XX    }
  1205. XX/*
  1206. XX * Read the socket and make sure it points back to the INPCB.
  1207. XX */
  1208. XX    eseek(kmem, (ls_t)inpcb.inp_socket, 0, "socket");
  1209. XX    eread(kmem, (char *)&sock, sizeof(sock), "socket");
  1210. XX    if (sock.so_pcb != (caddr_t)tcpcb.t_inpcb) {
  1211. XX        (void) fprintf(stderr,
  1212. XX            "%s: socket not linked to INPCB for PCB %x\n",
  1213. XX            progname, x);
  1214. XX        return(NULL);
  1215. XX    }
  1216. XX/*
  1217. XX * Find the file structure that is linked to the socket.
  1218. XX */
  1219. XX    if ((*pfp = socktofile((caddr_t)inpcb.inp_socket)) == NULL) {
  1220. XX        (void) fprintf(stderr,
  1221. XX            "%s: no file structure for socket of PCB %x\n",
  1222. XX            progname, x);
  1223. XX        return(NULL);
  1224. XX    }
  1225. XX/*
  1226. XX * Construct a pseudo file name and return it.
  1227. XX */
  1228. XX    (void) sprintf(nmbuf,
  1229. XX        "file %lx of socket %lx of INPCB %lx of PCB %lx",
  1230. XX        (long)*pfp, (long)inpcb.inp_socket, (long)tcpcb.t_inpcb, x);
  1231. XX    return(nmbuf);
  1232. XX}
  1233. XX
  1234. XX/*
  1235. XX * Convert a socket address to a file address.
  1236. XX */
  1237. XXstruct file *
  1238. XXsocktofile(s)
  1239. XX    caddr_t s;
  1240. XX{
  1241. XX    register struct file *afile;
  1242. XX    char *calloc();
  1243. XX    register struct file *fp;
  1244. XX    static struct file *ftp;
  1245. XX    static int nfile = -1;
  1246. XX    static struct file *xfile = NULL;
  1247. XX
  1248. XX/*
  1249. XX * Read the size of file table, allocate space
  1250. XX * for it, and read the file table pointer (once).
  1251. XX */
  1252. XX    if (nfile < 0) {
  1253. XX        eseek(kmem, (ls_t)(nl[SNFILE].n_value), 0, "_nfile");
  1254. XX        eread(kmem, (char *)&nfile, sizeof(nfile), "_nfile");
  1255. XX        xfile = (struct file *) calloc((unsigned)nfile, sizeof (struct file));
  1256. XX        eseek(kmem, (ls_t)(nl[SFIL].n_value), 0, "_file");
  1257. XX        eread(kmem, (char *)&ftp, sizeof(ftp), "_file");
  1258. XX    }
  1259. XX/*
  1260. XX * Read the file table and search for an in-use
  1261. XX * socket file with a matching data address.
  1262. XX */
  1263. XX    eseek(kmem, (ls_t)ftp, 0, "_file");
  1264. XX    eread(kmem, (char *)xfile, nfile * sizeof(struct file), "_file");
  1265. XX    for (fp = xfile, afile = ftp; fp < &xfile[nfile]; fp++, afile++) {
  1266. XX        if (fp->f_count && fp->f_type == DTYPE_SOCKET
  1267. XX        &&  s == fp->f_data)
  1268. XX            return(afile);
  1269. XX    }
  1270. XX    return(NULL);
  1271. XX}
  1272. SHAR_EOF
  1273. if test 24404 -ne "`wc -c ofiles.c`"
  1274. then
  1275. echo shar: error transmitting ofiles.c '(should have been 24404 characters)'
  1276. fi
  1277. echo shar: extracting ofiles.8l '(5223 characters)'
  1278. sed 's/^XX//' << \SHAR_EOF > ofiles.8l
  1279. XX.TH OFILES 8L LOCAL
  1280. XX.SH NAME
  1281. XXofiles \- show owner of open file or network connection
  1282. XX.SH SYNOPSIS
  1283. XX.B ofiles
  1284. XX[
  1285. XX.B \-d
  1286. XX] [
  1287. XX.B \-k
  1288. XX.I nlist
  1289. XX.I core
  1290. XX] [
  1291. XX.B \-n
  1292. XX] [
  1293. XX.B \-p
  1294. XX]
  1295. XX.I names
  1296. XX.SH DESCRIPTION
  1297. XX.I Ofiles
  1298. XXdisplays the owner, process identification (PID), type, command and
  1299. XXthe number of the inode associated with an open instance of a file
  1300. XXor a network connection.
  1301. XX.PP
  1302. XXAn open file may be a regular file, a file system or a directory;
  1303. XXit is specified by its path name.
  1304. XXWhen the path name refers to a file system,
  1305. XX.I ofiles
  1306. XXwill display the owners of all open instances of files in the system.
  1307. XX.PP
  1308. XXAn open network connection is specified by the kernel address of its
  1309. XXProtocol Control Block (PCB), as displayed by
  1310. XX.IR netstat (8),
  1311. XXwhen its
  1312. XX.B \-A
  1313. XXoption is specified.
  1314. XX.SH OPTIONS
  1315. XX.I Ofiles
  1316. XXdisplays information about its usage if no options are specified.
  1317. XX.TP \w'-kXnlistXcore'u+4
  1318. XX.BI \-d
  1319. XXThis option selects verbose, debugging output.
  1320. XX.TP
  1321. XX.BI \-k \ nlist\ core
  1322. XXThis option may be used only on DYNIX hosts.
  1323. XXIt sets optional name list and core file paths.
  1324. XX.IP
  1325. XX.I Nlist
  1326. XXis the path to the file from which
  1327. XX.I ofiles
  1328. XXshould obtain the addresses of kernel symbols,
  1329. XXinstead of from
  1330. XX.IR /dynix .
  1331. XX.IP
  1332. XX.I Core
  1333. XXis the path to the file from which
  1334. XX.I ofiles
  1335. XXshould obtain the value of kernel symbols,
  1336. XXinstead of from
  1337. XX.IR /dev/mem .
  1338. XX.IP
  1339. XXThis option is useful for debugging system crash dumps.
  1340. XX.TP
  1341. XX.B \-n
  1342. XXThis option specifies that the
  1343. XX.I name
  1344. XXarguments identify network connections by their hexadecimal, Protocol
  1345. XXControl Block (PCB) addresses.
  1346. XXPCB addresses can be obtained via the
  1347. XX.B \-A
  1348. XXoption of
  1349. XX.IR netstat (1).
  1350. XX.IP
  1351. XXThis option makes it possible to determine the local processes that
  1352. XXare using network connections in the LISTEN through ESTABLISHED states.
  1353. XX.TP
  1354. XX.B \-p 
  1355. XXThis option specifies that
  1356. XX.I ofiles
  1357. XXshould print process identifiers only \- e. g., so that the output may
  1358. XXbe piped to
  1359. XX.IR kill (1).
  1360. XX.TP
  1361. XX.I names
  1362. XXThese are path names of files, directories and file systems;
  1363. XXor, if the
  1364. XX.B \-n
  1365. XXoption has been specified, network connections, identified by their
  1366. XXhexadecimal Protocol Control Block (PCB) addresses.
  1367. XX.SH OUTPUT
  1368. XX.I Ofiles
  1369. XXdisplays for each
  1370. XX.IR name :
  1371. XX.TP \w'name/linkages'u+4
  1372. XX.I name/linkages
  1373. XXfor file paths, an interpretation of the type of name \- file, directory
  1374. XXor file system;
  1375. XXfor network connections, the kernel address linkages, starting with the file
  1376. XXstructure and proceeding through the socket structure and the Internet
  1377. XXProtocol Control Block (INPCB) structure to the PCB
  1378. XX.TP
  1379. XX.B USER
  1380. XXthe login name of the user of the process that has
  1381. XX.I name
  1382. XXopen
  1383. XX.TP
  1384. XX.B PID
  1385. XXthe identifier of the process that has
  1386. XX.I name
  1387. XXopen
  1388. XX.TP
  1389. XX.B TYPE
  1390. XXa file type explanation:
  1391. XX.RS
  1392. XX.TP \w'file'u+4
  1393. XX.B cwd 
  1394. XXif
  1395. XX.I name
  1396. XXis the current working directory of the process
  1397. XX.TP
  1398. XX.B file
  1399. XXif
  1400. XX.I name
  1401. XXis being used as a regular file by the process, optionally followed by:
  1402. XX.RS
  1403. XX.TP
  1404. XX.B /s
  1405. XXif the process has a shared lock on the file
  1406. XX.TP
  1407. XX.B /x
  1408. XXif the process has an exclusive lock on the file
  1409. XX.RE
  1410. XX.TP
  1411. XX.B rdir
  1412. XXif 
  1413. XX.I name
  1414. XXis the root directory of the process
  1415. XX.TP
  1416. XX.B sock
  1417. XXif
  1418. XX.I name
  1419. XXis a socket
  1420. XX.RE
  1421. XX.TP
  1422. XX.B FD
  1423. XXthe file descriptor number, local to the process
  1424. XX.TP
  1425. XX.B CMD
  1426. XXthe user command that opened
  1427. XX.I name
  1428. XX.TP
  1429. XX.B INODE
  1430. XXthe inode number of the file
  1431. XX.SH EXAMPLES
  1432. XXThis example shows the use of
  1433. XX.I ofiles
  1434. XXto discover the owner of the open, regular file,
  1435. XX.IR /usr/spool/lpd/lock .
  1436. XX.PP
  1437. XX.RS
  1438. XX.nf
  1439. XX% ofiles /usr/spool/lpd/lock
  1440. XX.br
  1441. XX/usr/spool/lpd/lock    
  1442. XX.br
  1443. XXUSER    PID    TYPE      FD    CMD    INODE
  1444. XX.br
  1445. XXroot    110    file/x     3    lpd    26683
  1446. XX.fi
  1447. XX.RE
  1448. XX.PP
  1449. XXThis example shows the use of
  1450. XX.IR netstat (1),
  1451. XX.IR grep (1)
  1452. XXand
  1453. XX.I ofiles
  1454. XXto identify the local endpoint of the ``smtp'' network connection.
  1455. XXThe first column of output from
  1456. XX.I netstat
  1457. XXis the PCB address; it is used as the
  1458. XX.I name
  1459. XXargument to
  1460. XX.IR ofiles ,
  1461. XXalong with the
  1462. XX.B \-n
  1463. XXoption.
  1464. XX.PP
  1465. XX.RS
  1466. XX.nf
  1467. XX% netstat -aA | grep smtp
  1468. XX.br
  1469. XX80f6770c    tcp    0    0    *.smtp    *.*    LISTEN
  1470. XX.br
  1471. XX% ofiles -n 80f6770c
  1472. XX.br
  1473. XXfile 80102b64 of socket 80f6758c of INPCB 80f6780c of PCB 80f6770c    
  1474. XX.br
  1475. XXUSER    PID    TYPE    FD    CMD
  1476. XX.br
  1477. XXroot    105    sock     5    sendmail 
  1478. XX.fi
  1479. XX.RE
  1480. XX.SH DIAGNOSTICS
  1481. XXErrors are identified with messages on the standard error file.
  1482. XX.PP
  1483. XX.I Ofiles
  1484. XXreturns a one (1) if any error was detected, including the failure to
  1485. XXlocate any
  1486. XX.IR names .
  1487. XXIt returns a zero (0) if no errors were detected and if it was able to
  1488. XXdisplay owner information about all the specified
  1489. XX.IR names .
  1490. XX.SH BUGS
  1491. XX.I Ofiles
  1492. XXcan't identify SunOS 4.0 stream files, so it doesn't follow their file
  1493. XXstructure pointers correctly when reading their inodes.
  1494. XXThat results in the display of erroneous inode numbers for stream files.
  1495. XX.PP
  1496. XXThe
  1497. XX.B \-n
  1498. XXoption limits its search to network connections in the LISTEN through
  1499. XXESTABLISHED states.
  1500. XX.PP
  1501. XXSince
  1502. XX.I ofiles
  1503. XXreads kernel memory in its search for open files and network connections,
  1504. XXrapid changes in kernel memory may produce unsatisfactory results.
  1505. XX.SH AUTHORS
  1506. XXC. Spencer is the original author.
  1507. XXMichael Ditto, Tom Dunigan, Alexander Dupuy, Gary Nebbett and Richard Tobin
  1508. XXcontributed.
  1509. XX.PP
  1510. XXMichael Spitzer, Ray Moody, and Vik Lall of the Purdue University Computing
  1511. XXCenter converted the program to a variety of UNIX environments.
  1512. XX.PP
  1513. XXVic Abell of the Purdue University Computing Center added the
  1514. XX.B \-n
  1515. XXoption.
  1516. XX.SH SEE ALSO
  1517. XXinode(5),
  1518. XXmount(1),
  1519. XXkill(1),
  1520. XXtcp(4).
  1521. SHAR_EOF
  1522. if test 5223 -ne "`wc -c ofiles.8l`"
  1523. then
  1524. echo shar: error transmitting ofiles.8l '(should have been 5223 characters)'
  1525. fi
  1526. #    End of shell archive
  1527. exit 0
  1528.  
  1529. -- 
  1530. Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
  1531.