diff options
Diffstat (limited to 'dialects/hpux/pstat/dproc.c')
-rw-r--r-- | dialects/hpux/pstat/dproc.c | 904 |
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; + } + } +} |