summaryrefslogtreecommitdiff
path: root/dialects/hpux/pstat/dproc.c
diff options
context:
space:
mode:
Diffstat (limited to 'dialects/hpux/pstat/dproc.c')
-rw-r--r--dialects/hpux/pstat/dproc.c904
1 files changed, 904 insertions, 0 deletions
diff --git a/dialects/hpux/pstat/dproc.c b/dialects/hpux/pstat/dproc.c
new file mode 100644
index 0000000..fb0c8e4
--- /dev/null
+++ b/dialects/hpux/pstat/dproc.c
@@ -0,0 +1,904 @@
+/*
+ * dproc.c -- pstat-based HP-UX process access functions for lsof
+ */
+
+
+/*
+ * Copyright 1999 Purdue Research Foundation, West Lafayette, Indiana
+ * 47907. All rights reserved.
+ *
+ * Written by Victor A. Abell
+ *
+ * This software is not subject to any license of the American Telephone
+ * and Telegraph Company or the Regents of the University of California.
+ *
+ * Permission is granted to anyone to use this software for any purpose on
+ * any computer system, and to alter it and redistribute it freely, subject
+ * to the following restrictions:
+ *
+ * 1. Neither the authors nor Purdue University are responsible for any
+ * consequences of the use of this software.
+ *
+ * 2. The origin of this software must not be misrepresented, either by
+ * explicit claim or by omission. Credit to the authors and Purdue
+ * University must appear in documentation and sources.
+ *
+ * 3. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ *
+ * 4. This notice may not be removed or altered.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright 1999 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id";
+#endif
+
+
+#include "lsof.h"
+
+
+/*
+ * Local definitions
+ */
+
+#define FDS_ALLOC_INCR 256 /* fds[] allocation increment */
+#define FDS_ALLOC_INIT 64 /* initial fds[] allocation */
+#define FINFOINCR 128 /* pst_fileinfo2 table allocation
+ * increment */
+#define INCLMEM(s, m) ((size_t)(offsetof(struct s, m) \
+ + sizeof(((struct s *)0)->m)))
+ /* size of struct s, including
+ * member m */
+#define PSTATINCR 512 /* pst_status table allocation
+ * increment */
+#define TXTVMINCR 64 /* text and vm info table table
+ * allocation increment */
+#define VMREGINCR 64 /* VM region table table allocation
+ * increment */
+
+
+/*
+ * Local structures
+ */
+
+struct pstatck {
+ size_t moff; /* offset of size member in pst_static
+ * -- from offsetof(...member) */
+ size_t msz; /* structure's pst_static member
+ * inclusion size -- from INCLMEM(s, m)
+ * macro */
+ size_t ssz; /* structure size -- from
+ * sizeof(struct) */
+ char *sn; /* structure name */
+} PstatCk[] = {
+ { (size_t)offsetof(struct pst_static, pst_status_size),
+ (size_t)INCLMEM(pst_static, pst_status_size),
+ sizeof(struct pst_status),
+ "pst_status" },
+ { (size_t)offsetof(struct pst_static, pst_vminfo_size),
+ (size_t)INCLMEM(pst_static, pst_vminfo_size),
+ sizeof(struct pst_vminfo),
+ "pst_vminfo" },
+ { (size_t)offsetof(struct pst_static, pst_filedetails_size),
+ (size_t)INCLMEM(pst_static, pst_filedetails_size),
+ sizeof(struct pst_filedetails),
+ "pst_filedetails" },
+ { (size_t)offsetof(struct pst_static, pst_socket_size),
+ (size_t)INCLMEM(pst_static, pst_socket_size),
+ sizeof(struct pst_socket),
+ "pst_socket" },
+ { (size_t)offsetof(struct pst_static, pst_stream_size),
+ (size_t)INCLMEM(pst_static, pst_stream_size),
+ sizeof(struct pst_stream),
+ "pst_stream" },
+ { (size_t)offsetof(struct pst_static, pst_mpathnode_size),
+ (size_t)INCLMEM(pst_static, pst_mpathnode_size),
+ sizeof(struct pst_mpathnode),
+ "pst_mpathnode" },
+ { (size_t)offsetof(struct pst_static, pst_fileinfo2_size),
+ (size_t)INCLMEM(pst_static, pst_fileinfo2_size),
+ sizeof(struct pst_fileinfo2),
+ "pst_fileinfo2" },
+};
+#define NPSTATCK (sizeof(PstatCk) /sizeof(struct pstatck))
+
+
+/*
+ * Local static variables
+ */
+
+static int HvRtPsfid = -1; /* "/" psfileid status:
+ * -1: not yet tested;
+ * 0: tested and unknown;
+ * 1: tested and known */
+static struct psfileid RtPsfid; /* "/" psfileid */
+
+
+/*
+ * Local function prototypes
+ */
+
+_PROTOTYPE(static void get_kernel_access,(void));
+_PROTOTYPE(static void process_text,(struct pst_status *p));
+_PROTOTYPE(static struct pst_fileinfo2 *read_files,(struct pst_status *p,
+ int *n));
+_PROTOTYPE(static struct pst_status *read_proc,(int *n));
+_PROTOTYPE(static struct pst_vm_status *read_vmreg,(struct pst_status *p,
+ int *n));
+
+
+/*
+ * gather_proc_info() -- gather process information
+ */
+
+void
+gather_proc_info()
+{
+ short cckreg; /* conditional status of regular file
+ * checking:
+ * 0 = unconditionally check
+ * 1 = conditionally check */
+ short ckscko; /* socket file only checking status:
+ * 0 = none
+ * 1 = check only socket files,
+ * including TCP and UDP
+ * streams with eXPORT data,
+ * where supported */
+ int cwds, fd, *fds, fdsa, i, j, l, nf, np, rtds;
+ struct pst_fileinfo2 *f;
+ long flag;
+ KA_T ka, na;
+ MALLOC_S nb;
+ struct pst_status *p;
+ struct pst_filedetails pd;
+ struct pst_socket *s;
+ short pss, sf;
+/*
+ * Compute current working and root directory statuses and the statuses of
+ * the first FDS_ALLOC_INIT FDs.
+ */
+ if (Fand && Fdl) {
+ cwds = (ck_fd_status(CWD, -1) != 2) ? 0 : 1;
+ rtds = (ck_fd_status(RTD, -1) != 2) ? 0 : 1;
+ nb = (MALLOC_S)(sizeof(int) * FDS_ALLOC_INIT);
+ if (!(fds = (int *)malloc(nb))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d FD status entries\n", Pn,
+ FDS_ALLOC_INIT);
+ Exit(1);
+ }
+ for (fdsa = 0; fdsa < FDS_ALLOC_INIT; fdsa++) {
+ if (Fand && Fdl)
+ fds[fdsa] = (ck_fd_status(NULL, fdsa) == 2) ? 1 : 0;
+ else
+ fds[fdsa] = 1;
+ }
+ } else {
+ cwds = rtds = 1;
+ fdsa = 0;
+ fds = (int *)NULL;
+ }
+/*
+ * If only socket files have been selected, or socket files have been selected
+ * ANDed with other selection options, enable the skipping of regular files.
+ *
+ * If socket files and some process options have been selected, enable
+ * conditional skipping of regular file; i.e., regular files will be skipped
+ * unless they belong to a process selected by one of the specified options.
+ */
+ if (Selflags & SELNW) {
+
+ /*
+ * Some network files selection options have been specified.
+ */
+ if (Fand || !(Selflags & ~SELNW)) {
+
+ /*
+ * Selection ANDing or only network file options have been
+ * specified, so set unconditional skipping of regular files
+ * and socket file only checking.
+ */
+ cckreg = 0;
+ ckscko = 1;
+ } else {
+
+ /*
+ * If ORed file selection options have been specified, or no ORed
+ * process selection options have been specified, enable
+ * unconditional file checking and clear socket file only checking.
+ *
+ * If only ORed process selection options have been specified,
+ * enable conditional file skipping and socket file only checking.
+ */
+ if ((Selflags & SELFILE) || !(Selflags & SELPROC))
+ cckreg = ckscko = 0;
+ else
+ cckreg = ckscko = 1;
+ }
+ } else {
+
+ /*
+ * No network file selection options were specified. Enable
+ * unconditional file checking and clear socket file only checking.
+ */
+ cckreg = ckscko = 0;
+ }
+/*
+ * Examine proc structures and their associated information.
+ */
+ for (i = 0, p = read_proc(&np); i < np; i++, p++) {
+ if (!p->pst_stat || p->pst_stat == PS_ZOMBIE)
+ continue;
+ if (is_proc_excl((int)p->pst_pid, (int)p->pst_pgrp,
+ (UID_ARG)p->pst_uid, &pss, &sf))
+ continue;
+ /*
+ * Make sure the command name is NUL-terminated.
+ */
+ p->pst_ucomm[PST_UCOMMLEN - 1] = '\0';
+ if (is_cmd_excl(p->pst_ucomm, &pss, &sf))
+ continue;
+ if (cckreg) {
+
+ /*
+ * If conditional checking of regular files is enabled, enable
+ * socket file only checking, based on the process' selection
+ * status.
+ */
+ ckscko = (sf & SELPROC) ? 0 : 1;
+ }
+ alloc_lproc((int)p->pst_pid, (int)p->pst_pgrp, (int)p->pst_ppid,
+ (UID_ARG)p->pst_uid, p->pst_ucomm, (int)pss, (int)sf);
+ Plf = (struct lfile *)NULL;
+ /*
+ * Save current working directory information.
+ */
+ if (!ckscko && cwds
+ && IS_PSFILEID(&p->pst_cdir) && (p->pst_cdir.psf_fileid > 0)
+ ) {
+ alloc_lfile(CWD, -1);
+ if ((na = read_det(&p->pst_fid_cdir, p->pst_hi_fileid_cdir,
+ p->pst_lo_fileid_cdir,
+ p->pst_hi_nodeid_cdir,
+ p->pst_lo_nodeid_cdir, &pd)))
+ (void) process_finfo(&pd, &p->pst_fid_cdir,
+ &p->pst_cdir, na);
+ else {
+ (void) snpf(Namech, Namechl,
+ "can't read %s pst_filedetails%s%s", CWD,
+ errno ? ": " : "", errno ? strerror(errno) : "");
+ enter_nm(Namech);
+ }
+ if (Lf->sf)
+ link_lfile();
+ }
+ /*
+ * Save root directory information.
+ */
+ if (!ckscko && rtds
+ && IS_PSFILEID(&p->pst_rdir) && (p->pst_rdir.psf_fileid > 0)
+ ) {
+ if (HvRtPsfid < 0)
+ (void) scanmnttab();
+ if (!HvRtPsfid
+ || memcmp((void *)&RtPsfid, (void *)&p->pst_rdir,
+ sizeof(RtPsfid)))
+ {
+ alloc_lfile(RTD, -1);
+ if ((na = read_det(&p->pst_fid_rdir,
+ p->pst_hi_fileid_rdir,
+ p->pst_lo_fileid_rdir,
+ p->pst_hi_nodeid_rdir,
+ p->pst_lo_nodeid_rdir, &pd)))
+ (void) process_finfo(&pd, &p->pst_fid_rdir,
+ &p->pst_rdir, na);
+ else {
+ (void) snpf(Namech, Namechl,
+ "can't read %s pst_filedetails%s%s", RTD,
+ errno ? ": " : "",
+ errno ? strerror(errno) : "");
+ enter_nm(Namech);
+ }
+ if (Lf->sf)
+ link_lfile();
+ }
+ }
+ /*
+ * Print information on the text files.
+ */
+ if (!ckscko)
+ (void) process_text(p);
+ /*
+ * Loop through user's files.
+ */
+ for (j = 0, f = read_files(p, &nf); j < nf; j++, f++) {
+ fd = (int)f->psf_fd;
+ /*
+ * Check FD status and allocate local file space, as required.
+ */
+ if (Fand && Fdl && fds) {
+
+ /*
+ * Check and update the FD status array.
+ */
+ if (fd >= fdsa) {
+ for (l = fdsa; l <= fd; l += FDS_ALLOC_INCR)
+ ;
+ nb = (MALLOC_S)(l * sizeof(int));
+ if (!(fds = (int *)realloc((MALLOC_P *)fds, nb))) {
+ (void) fprintf(stderr,
+ "%s: can't reallocate %d FD status entries\n",
+ Pn, l);
+ Exit(1);
+ }
+ while (fdsa < l) {
+ fds[fdsa] = (ck_fd_status(NULL, fdsa) == 2) ? 1 : 0;
+ fdsa++;
+ }
+ }
+ if (!fds[fd])
+ continue;
+ }
+ alloc_lfile(NULL, (int)f->psf_fd);
+ /*
+ * Construct access code.
+ */
+ if ((flag = (long)(f->psf_flag & ~PS_FEXCLOS))
+ == (long)PS_FRDONLY)
+ Lf->access = 'r';
+ else if (flag == (long)PS_FWRONLY)
+ Lf->access = 'w';
+ else
+ Lf->access = 'u';
+
+#if defined(HASFSTRUCT)
+ /*
+ * Save file structure values.
+ */
+ if (Fsv & FSV_CT) {
+ Lf->fct = (long)f->psf_count;
+ Lf->fsv |= FSV_CT;
+ }
+ if (Fsv & FSV_FA) {
+ ka = (((KA_T)(f->psf_hi_fileid & 0xffffffff) << 32)
+ | (KA_T)(f->psf_lo_fileid & 0xffffffff));
+ if ((Lf->fsa = ka))
+ Lf->fsv |= FSV_FA;
+ }
+ if (Fsv & FSV_FG) {
+ Lf->ffg = flag;
+ Lf->fsv |= FSV_FG;
+ }
+ Lf->pof = (long)(f->psf_flag & PS_FEXCLOS);
+#endif /* defined(HASFSTRUCT) */
+
+ /*
+ * Save file offset. _PSTAT64 should alwaus be defined, but just
+ * to be safe, check for it.
+ */
+
+#if defined(_PSTAT64)
+ Lf->off = (SZOFFTYPE)f->_PSF_OFFSET64;
+#else /* !defined(_PSTAT64) */
+ Lf->off = (SZOFFTYPE)f->psf_offset;
+#endif /* defined(_PSTAT64) */
+
+ /*
+ * Process the file by its type.
+ */
+ switch (f->psf_ftype) {
+ case PS_TYPE_VNODE:
+ if (ckscko || Selinet)
+ break;
+ if ((na = read_det(&f->psf_fid, f->psf_hi_fileid,
+ f->psf_lo_fileid, f->psf_hi_nodeid,
+ f->psf_lo_nodeid, &pd)))
+ (void) process_finfo(&pd, &f->psf_fid, &f->psf_id, na);
+ else {
+ (void) snpf(Namech, Namechl,
+ "can't read pst_filedetails%s%s",
+ errno ? ": " : "",
+ errno ? strerror(errno) : "");
+ enter_nm(Namech);
+ }
+ break;
+ case PS_TYPE_SOCKET:
+ switch (f->psf_subtype) {
+ case PS_SUBTYPE_SOCK:
+ (void) process_socket(f, (struct pst_socket *)NULL);
+ break;
+ case PS_SUBTYPE_SOCKSTR:
+ if ((s = read_sock(f)))
+ (void) process_socket(f, s);
+ else
+ (void) process_stream(f, (int)ckscko);
+ break;
+ default:
+ (void) snpf(Namech, Namechl,
+ "unknown socket sub-type: %d", (int)f->psf_subtype);
+ enter_nm(Namech);
+ }
+ break;
+ case PS_TYPE_STREAMS:
+ (void) process_stream(f, (int)ckscko);
+ break;
+ case PS_TYPE_UNKNOWN:
+ (void) snpf(Lf->type, sizeof(Lf->type), "UNKN");
+ (void) enter_nm("no more information");
+ break;
+ case PS_TYPE_UNSP:
+ (void) snpf(Lf->type, sizeof(Lf->type), "UNSP");
+ (void) enter_nm("no more information");
+ break;
+ case PS_TYPE_LLA:
+ (void) snpf(Lf->type, sizeof(Lf->type), "LLA");
+ (void) enter_nm("no more information");
+ break;
+ }
+ if (Lf->sf)
+ link_lfile();
+ }
+ /*
+ * Examine results.
+ */
+ if (examine_lproc())
+ return;
+ }
+}
+
+
+/*
+ * get_kernel_access() -- access the required information in the kernel
+ */
+
+static void
+get_kernel_access()
+{
+ int err = 0;
+ int i;
+ struct pst_static pst;
+ _T_LONG_T *szp;
+/*
+ * Check the kernel version.
+ */
+ (void) ckkv("HP-UX", LSOF_VSTR, (char *)NULL, (char *)NULL);
+/*
+ * Check PSTAT support. First make sure we can read pst_static up through
+ * its pst_static_size member. If not, quit. If we can, read the full
+ * pst_static structure.
+ */
+ if (pstat_getstatic(&pst, (size_t)INCLMEM(pst_static, pst_static_size),
+ 1, 0) != 1)
+ {
+ (void) fprintf(stderr,
+ "%s: FATAL: can't determine PSTAT static size: %s\n",
+ Pn, strerror(errno));
+ Exit(1);
+ }
+ if (pstat_getstatic(&pst, (size_t)pst.pst_static_size, 1, 0) != 1) {
+ (void) fprintf(stderr,
+ "%s: FATAL: can't read %ld bytes of pst_static\n",
+ Pn, (long)pst.pst_static_size);
+ Exit(1);
+ }
+/*
+ * Check all the pst_static members defined in PstatCk[].
+ */
+ for (i = 0; i < NPSTATCK; i++) {
+ if (pst.pst_static_size < PstatCk[i].msz) {
+ (void) fprintf(stderr,
+ "%s: FATAL: pst_static doesn't contain %s_size\n",
+ Pn, PstatCk[i].sn);
+ err = 1;
+ continue;
+ }
+ szp = (_T_LONG_T *)(((char *)&pst) + PstatCk[i].moff);
+ if (*szp < PstatCk[i].ssz) {
+ (void) fprintf(stderr,
+ "%s: FATAL: %s_size should be: %llu; is %llu\n",
+ Pn, PstatCk[i].sn, (unsigned long long)PstatCk[i].ssz,
+ (unsigned long long)*szp);
+ err = 1;
+ }
+ }
+/*
+ * Save the clone major device number, if pst_static is big enough to hold it.
+ */
+ if (pst.pst_static_size >= (size_t)INCLMEM(pst_static, clonemajor)) {
+ CloneMaj = pst.clonemajor;
+ HaveCloneMaj = 1;
+ }
+ if (!err)
+ return;
+ Exit(1);
+}
+
+
+/*
+ * initialize() -- perform all initialization
+ */
+
+void
+initialize()
+{
+ get_kernel_access();
+}
+
+
+/*
+ * process_text() -- process text access information
+ */
+
+static void
+process_text(p)
+ struct pst_status *p; /* pst_status for process */
+{
+ int i, j, nr, ntvu;
+ int meme = 0;
+ static int mems = -1;
+ KA_T na;
+ MALLOC_S nb;
+ static int ntva;
+ struct pst_vm_status *rp;
+ static int txts = -1;
+ struct txtvm {
+ char *fd;
+ struct pst_fid opfid;
+ struct psfileid psfid;
+ KA_T na;
+ struct pst_filedetails pd;
+ };
+ static struct txtvm *tv = (struct txtvm *)NULL;
+/*
+ * Get and remember "mem" and "txt" FD statuses.
+ */
+ if (mems < 0) {
+ if (Fand && Fdl)
+ mems = (ck_fd_status("mem", -1) == 2) ? 1 : 0;
+ else
+ mems = 1;
+ }
+ if (txts < 0) {
+ if (Fand && Fdl)
+ txts = (ck_fd_status("txt", -1) == 2) ? 1 : 0;
+ else
+ txts = 1;
+ }
+ if (!mems && !txts)
+ return;
+/*
+ * Pre-allocate sufficient tv[] space for text file.
+ */
+ if (!tv) {
+ ntva = TXTVMINCR;
+ nb = (MALLOC_S)(ntva * sizeof(struct txtvm));
+ if (!(tv = (struct txtvm *)malloc(nb))) {
+
+no_txtvm_space:
+
+ (void) fprintf(stderr,
+ "%s: no memory for text and VM info array; PID: %d\n",
+ Pn, (int)p->pst_pid);
+ Exit(1);
+ }
+ }
+/*
+ * Enter text file in tv[], if possible.
+ */
+ if (txts && IS_PSFILEID(&p->pst_text) && (p->pst_text.psf_fileid > 0))
+ {
+ if ((na = read_det(&p->pst_fid_text, p->pst_hi_fileid_text,
+ p->pst_lo_fileid_text, p->pst_hi_nodeid_text,
+ p->pst_lo_nodeid_text, &tv[0].pd)))
+ {
+ tv[0].fd = "txt";
+ tv[0].na = na;
+ tv[0].opfid = p->pst_fid_text;
+ tv[0].psfid = p->pst_text;
+ ntvu = 1;
+ } else {
+ alloc_lfile("txt", -1);
+ (void) snpf(Namech, Namechl,
+ "can't read txt pst_filedetails%s%s",
+ errno ? ": " : "", errno ? strerror(errno) : "");
+ enter_nm(Namech);
+ if (Lf->sf)
+ link_lfile();
+ ntvu = 0;
+ }
+ } else
+ ntvu = 0;
+/*
+ * Get unique VM regions.
+ */
+ if (mems) {
+ for (i = 0, rp = read_vmreg(p, &nr); (i < nr); i++, rp++) {
+
+ /*
+ * Skip duplicate regions.
+ */
+ for (j = 0; j < ntvu; j++) {
+ if (memcmp((void *)&rp->pst_id, (void *)&tv[j].psfid,
+ sizeof(struct psfileid))
+ == 0)
+ break;
+ }
+ if (j < ntvu)
+ continue;
+ /*
+ * Make sure there's tv[] space for this region.
+ */
+ if (ntvu >= ntva) {
+ ntva += TXTVMINCR;
+ nb = (MALLOC_S)(ntva * sizeof(struct txtvm));
+ if (!(tv = (struct txtvm *)realloc((MALLOC_P *)tv, nb)))
+ goto no_txtvm_space;
+ }
+ /*
+ * See if we can read the file details for this region.
+ */
+ if ((na = read_det(&rp->pst_fid, rp->pst_hi_fileid,
+ rp->pst_lo_fileid, rp->pst_hi_nodeid,
+ rp->pst_lo_nodeid, &tv[ntvu].pd)))
+ {
+ tv[ntvu].fd = "mem";
+ tv[ntvu].na = na;
+ tv[ntvu].opfid = rp->pst_fid;
+ tv[ntvu].psfid = rp->pst_id;
+ ntvu++;
+ } else if (!meme) {
+ alloc_lfile("mem", -1);
+ (void) snpf(Namech, Namechl,
+ "can't read mem pst_filedetails%s%s",
+ errno ? ": " : "", errno ? strerror(errno) : "");
+ enter_nm(Namech);
+ if (Lf->sf)
+ link_lfile();
+ meme = 1;
+ }
+ }
+ }
+/*
+ * Process information for unique regions.
+ */
+ for (i = 0; i < ntvu; i++) {
+ alloc_lfile(tv[i].fd, -1);
+ (void) process_finfo(&tv[i].pd, &tv[i].opfid, &tv[i].psfid,
+ tv[i].na);
+ if (Lf->sf)
+ link_lfile();
+ }
+}
+
+
+/*
+ * read_det() -- read the pst_filedetails structure
+ */
+
+KA_T
+read_det(ki, hf, lf, hn, ln, pd)
+ struct pst_fid *ki; /* kernel file ID */
+ uint32_t hf; /* high file ID bits */
+ uint32_t lf; /* low file ID bits */
+ uint32_t hn; /* high node ID bits */
+ uint32_t ln; /* low node ID bits */
+ struct pst_filedetails *pd; /* details receiver */
+{
+ KA_T na;
+
+ errno = 0;
+ na = (KA_T)(((KA_T)(hn & 0xffffffff) << 32) | (KA_T)(ln & 0xffffffff));
+ if (pstat_getfiledetails(pd, sizeof(struct pst_filedetails), ki) <= 0
+ || hf != pd->psfd_hi_fileid || lf != pd->psfd_lo_fileid
+ || hn != pd->psfd_hi_nodeid || ln != pd->psfd_lo_nodeid)
+ return((KA_T)0);
+ return(na);
+}
+
+
+/*
+ * read_files() -- read the file descriptor information for a process
+ */
+
+static struct pst_fileinfo2 *
+read_files(p, n)
+ struct pst_status *p; /* pst_status for the process */
+ int *n; /* returned fi[] entry count */
+{
+ size_t ec;
+ static struct pst_fileinfo2 *fi = (struct pst_fileinfo2 *)NULL;
+ MALLOC_S nb;
+ int nf = 0;
+ static int nfa = 0;
+ int rc;
+ static size_t sz = sizeof(struct pst_fileinfo2);
+/*
+ * Read the pst_fileinfo2 information for all files of the process
+ * into fi[].
+ */
+ do {
+ if (nf >= nfa) {
+
+ /*
+ * Increase the size of fi[].
+ */
+ nfa += FINFOINCR;
+ nb = (MALLOC_S)(nfa * sizeof(struct pst_fileinfo2));
+ if (!fi)
+ fi = (struct pst_fileinfo2 *)malloc(nb);
+ else
+ fi = (struct pst_fileinfo2 *)realloc((MALLOC_P *)fi, nb);
+ if (!fi) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d bytes for pst_filinfo\n",
+ Pn, nb);
+ Exit(1);
+ }
+ }
+ /*
+ * Read the next block of pst_fileinfo2 structures.
+ */
+ ec = (size_t)(nfa - nf);
+ if ((rc = pstat_getfile2(fi + nf, sz, ec, nf, p->pst_pid)) > 0) {
+ nf += rc;
+ if (rc < (int)ec)
+ rc = 0;
+ }
+ } while (rc > 0);
+ *n = nf;
+ return(fi);
+}
+
+
+/*
+ * read_proc() -- read process table status information
+ */
+
+static struct pst_status *
+read_proc(n)
+ int *n; /* returned ps[] entry count */
+{
+ size_t el;
+ int i = 0;
+ MALLOC_S nb;
+ int np = 0;
+ static int npa = 0;
+ static struct pst_status *ps = (struct pst_status *)NULL;
+ int rc;
+ size_t sz = sizeof(struct pst_status);
+/*
+ * Read the pst_status information for all processes into ps[].
+ */
+ do {
+ if (np >= npa) {
+
+ /*
+ * Increase the size of ps[].
+ */
+ npa += PSTATINCR;
+ nb = (MALLOC_S)(npa * sizeof(struct pst_status));
+ if (!ps)
+ ps = (struct pst_status *)malloc(nb);
+ else
+ ps = (struct pst_status *)realloc((MALLOC_P *)ps, nb);
+ if (!ps) {
+
+ps_alloc_error:
+ (void) fprintf(stderr,
+ "%s: can't allocate %d bytes for pst_status table\n",
+ Pn, nb);
+ Exit(1);
+ }
+ }
+ /*
+ * Read the next block of pst_status structures.
+ */
+ el = (size_t)(npa - np);
+ if ((rc = pstat_getproc(ps + np, sz, el, i)) > 0) {
+ np += rc;
+ i = (ps + np - 1)->pst_idx + 1;
+ if (rc < el)
+ rc = 0;
+ }
+ } while (rc > 0);
+/*
+ * Reduce ps[] to a minimum, unless repeat mode is in effect.
+ */
+ if (!RptTm && ps && np && (np < npa)) {
+ nb = (MALLOC_S)(np * sizeof(struct pst_status));
+ if (!(ps = (struct pst_status *)realloc((MALLOC_P *)ps, nb)))
+ goto ps_alloc_error;
+ }
+ *n = np;
+ return(ps);
+}
+
+
+/*
+ * read_vmreg() -- read info about the VM regions of a process
+ */
+
+static struct pst_vm_status *
+read_vmreg(p, n)
+ struct pst_status *p; /* pst_status for process */
+ int *n; /* returned region count */
+{
+ size_t ec = (size_t)p->pst_pid;
+ MALLOC_S nb;
+ int nr, rx;
+ static int nra = 0;
+ struct pst_vm_status *rp;
+ static struct pst_vm_status *reg = (struct pst_vm_status *)NULL;
+ size_t sz = sizeof(struct pst_vm_status);
+/*
+ * Read all VM region information for the process.
+ */
+ for (nr = rx = 0;; rx++) {
+ if (nr >= nra) {
+
+ /*
+ * Increase the region table size.
+ */
+ nra += VMREGINCR;
+ nb = (MALLOC_S)(nra * sizeof(struct pst_vm_status));
+ if (!reg)
+ reg = (struct pst_vm_status *)malloc(nb);
+ else
+ reg = (struct pst_vm_status *)realloc((MALLOC_P *)reg, nb);
+ if (!reg) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d bytes for pst_vm_status\n",
+ Pn, nb);
+ Exit(1);
+ }
+ }
+ /*
+ * Read the pst_vm_status structure for the next region.
+ */
+ rp = reg + nr;
+ if (pstat_getprocvm(rp, sz, ec, rx) != 1)
+ break;
+ if (IS_PSFILEID(&rp->pst_id) && (rp->pst_id.psf_fileid > 0))
+ nr++;
+ }
+ *n = nr;
+ return(reg);
+}
+
+
+/*
+ * scanmnttab() -- scan mount table
+ */
+
+extern void
+scanmnttab()
+{
+ struct mounts *mp;
+/*
+ * Scan the mount table to identify NFS file systems and form the psfileid
+ * for "/".
+ *
+ * This function allows the mount table scan to be deferred until its
+ * information is needed.
+ */
+ if ((HvRtPsfid >= 0) && (HasNFS >= 0))
+ return;
+ (void) memset((void *)&RtPsfid, 0, sizeof(RtPsfid));
+ for (HasNFS = HvRtPsfid = 0, mp = readmnt(); mp; mp = mp->next) {
+ if (mp->MOUNTS_FSTYPE
+ && (strcmp(mp->MOUNTS_FSTYPE, MNTTYPE_NFS) == 0
+ || strcmp(mp->MOUNTS_FSTYPE, MNTTYPE_NFS3) == 0)) {
+ HasNFS = 1;
+ mp->is_nfs = 1;
+ } else
+ mp->is_nfs = 0;
+ if (!HvRtPsfid && !strcmp(mp->dir, "/")) {
+ HvRtPsfid = 1;
+ RtPsfid.psf_fsid.psfs_id = mp->dev;
+ RtPsfid.psf_fsid.psfs_type = mp->MOUNTS_STAT_FSTYPE;
+ RtPsfid.psf_fileid = mp->inode;
+ }
+ }
+}