blob: fb0c8e49a31385f958bc231f482cfffa1e2a617b [file] [log] [blame]
/*
* 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;
}
}
}