summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJinWang An <jinwang.an@samsung.com>2021-12-28 10:01:55 +0900
committerJinWang An <jinwang.an@samsung.com>2021-12-28 10:01:55 +0900
commitfbf25342d5b67bf9e9776f4dcd011cf63c581cc2 (patch)
tree4814a6c1a5267b5dc11ab1efc26af70381c15fc8
parent9bb81f8a90ecc8b70c955bff72ec59dd3d9e5ae7 (diff)
downloadlsof-fbf25342d5b67bf9e9776f4dcd011cf63c581cc2.tar.gz
lsof-fbf25342d5b67bf9e9776f4dcd011cf63c581cc2.tar.bz2
lsof-fbf25342d5b67bf9e9776f4dcd011cf63c581cc2.zip
Imported Upstream version 4.88upstream/4.88
-rw-r--r--00.README.FIRST_4.8729
-rw-r--r--00CREDITS5
-rw-r--r--00DCACHE4
-rw-r--r--00DIALECTS3
-rw-r--r--00DIST54
-rw-r--r--00FAQ9
-rw-r--r--00PORTING18
-rw-r--r--00QUICKSTART5
-rw-r--r--00TEST7
-rw-r--r--00XCONFIG40
-rwxr-xr-xConfigure72
-rw-r--r--README.lsof_4.87128
-rw-r--r--arg.c2
-rw-r--r--dialects/aix/Makefile169
-rwxr-xr-xdialects/aix/Mksrc24
-rw-r--r--dialects/aix/aix5/README7
-rw-r--r--dialects/aix/aix5/j2/j2_lock.h19
-rw-r--r--dialects/aix/aix5/j2/private_j2_snapshot.h17
-rw-r--r--dialects/aix/ddev.c728
-rw-r--r--dialects/aix/dfile.c600
-rw-r--r--dialects/aix/dlsof.h442
-rw-r--r--dialects/aix/dmnt.c302
-rw-r--r--dialects/aix/dnode.c1307
-rw-r--r--dialects/aix/dnode1.c313
-rw-r--r--dialects/aix/dnode2.c81
-rw-r--r--dialects/aix/dproc.c1481
-rw-r--r--dialects/aix/dproto.h68
-rw-r--r--dialects/aix/dsock.c443
-rw-r--r--dialects/aix/dstore.c405
-rw-r--r--dialects/aix/machine.h691
-rwxr-xr-xdialects/darwin/get-hdr-loc.sh119
-rw-r--r--dialects/darwin/kmem/Makefile171
-rwxr-xr-xdialects/darwin/kmem/Mksrc24
-rw-r--r--dialects/darwin/kmem/ddev.c479
-rw-r--r--dialects/darwin/kmem/dfile.c390
-rw-r--r--dialects/darwin/kmem/dlsof.h337
-rw-r--r--dialects/darwin/kmem/dmnt.c229
-rw-r--r--dialects/darwin/kmem/dnode.c1038
-rw-r--r--dialects/darwin/kmem/dnode1.c107
-rw-r--r--dialects/darwin/kmem/dproc.c763
-rw-r--r--dialects/darwin/kmem/dproto.h62
-rw-r--r--dialects/darwin/kmem/dsock.c478
-rw-r--r--dialects/darwin/kmem/dstore.c105
-rw-r--r--dialects/darwin/kmem/machine.h647
-rw-r--r--dialects/darwin/libproc/Makefile171
-rwxr-xr-xdialects/darwin/libproc/Mksrc24
-rw-r--r--dialects/darwin/libproc/ddev.c549
-rw-r--r--dialects/darwin/libproc/dfile.c682
-rw-r--r--dialects/darwin/libproc/dlsof.h136
-rw-r--r--dialects/darwin/libproc/dmnt.c201
-rw-r--r--dialects/darwin/libproc/dproc.c839
-rw-r--r--dialects/darwin/libproc/dproto.h61
-rw-r--r--dialects/darwin/libproc/dsock.c449
-rw-r--r--dialects/darwin/libproc/dstore.c91
-rw-r--r--dialects/darwin/libproc/machine.h629
-rw-r--r--dialects/du/Makefile156
-rwxr-xr-xdialects/du/Mksrc24
-rw-r--r--dialects/du/ddev.c759
-rw-r--r--dialects/du/dfile.c118
-rw-r--r--dialects/du/dlsof.h400
-rw-r--r--dialects/du/dmnt.c320
-rw-r--r--dialects/du/dnode.c992
-rw-r--r--dialects/du/dproc.c1606
-rw-r--r--dialects/du/dproto.h61
-rw-r--r--dialects/du/dsock.c325
-rw-r--r--dialects/du/dstore.c162
-rw-r--r--dialects/du/machine.h647
-rw-r--r--dialects/freebsd/Makefile162
-rw-r--r--dialects/freebsd/Makefile.zfs17
-rwxr-xr-xdialects/freebsd/Mksrc29
-rw-r--r--dialects/freebsd/dlsof.h672
-rw-r--r--dialects/freebsd/dmnt.c462
-rw-r--r--dialects/freebsd/dnode.c1578
-rw-r--r--dialects/freebsd/dnode1.c144
-rw-r--r--dialects/freebsd/dnode2.c153
-rw-r--r--dialects/freebsd/dproc.c700
-rw-r--r--dialects/freebsd/dproto.h66
-rw-r--r--dialects/freebsd/dsock.c535
-rw-r--r--dialects/freebsd/dstore.c131
-rw-r--r--dialects/freebsd/dzfs.h112
-rw-r--r--dialects/freebsd/include/procfs/pfsnode.h217
-rw-r--r--dialects/freebsd/machine.h662
-rw-r--r--dialects/hpux/kmem/Makefile161
-rwxr-xr-xdialects/hpux/kmem/Mksrc24
-rw-r--r--dialects/hpux/kmem/dfile.c266
-rw-r--r--dialects/hpux/kmem/dlsof.h441
-rw-r--r--dialects/hpux/kmem/dmnt.c252
-rw-r--r--dialects/hpux/kmem/dnode.c1097
-rw-r--r--dialects/hpux/kmem/dnode1.c157
-rw-r--r--dialects/hpux/kmem/dnode2.c371
-rw-r--r--dialects/hpux/kmem/dproc.c842
-rw-r--r--dialects/hpux/kmem/dproto.h69
-rw-r--r--dialects/hpux/kmem/dsock.c1170
-rw-r--r--dialects/hpux/kmem/dstore.c241
-rw-r--r--dialects/hpux/kmem/hpux11/ipc_s.h98
-rw-r--r--dialects/hpux/kmem/hpux11/kernbits.h22
-rw-r--r--dialects/hpux/kmem/hpux11/lla.h91
-rw-r--r--dialects/hpux/kmem/hpux11/nfs_clnt.h76
-rw-r--r--dialects/hpux/kmem/hpux11/proc.h245
-rw-r--r--dialects/hpux/kmem/hpux11/rnode.h94
-rw-r--r--dialects/hpux/kmem/hpux11/sth.h84
-rw-r--r--dialects/hpux/kmem/hpux11/tcp_s.h227
-rw-r--r--dialects/hpux/kmem/hpux11/udp_s.h79
-rw-r--r--dialects/hpux/kmem/hpux11/vnode.h131
-rw-r--r--dialects/hpux/kmem/machine.h671
-rw-r--r--dialects/hpux/pstat/Makefile150
-rwxr-xr-xdialects/hpux/pstat/Mksrc24
-rw-r--r--dialects/hpux/pstat/dfile.c806
-rw-r--r--dialects/hpux/pstat/dlsof.h206
-rw-r--r--dialects/hpux/pstat/dproc.c904
-rw-r--r--dialects/hpux/pstat/dproto.h59
-rw-r--r--dialects/hpux/pstat/dsock.c1647
-rw-r--r--dialects/hpux/pstat/dstore.c80
-rw-r--r--dialects/hpux/pstat/machine.h648
-rw-r--r--dialects/linux/dnode.c147
-rw-r--r--dialects/linux/dproc.c163
-rw-r--r--dialects/linux/dsock.c133
-rw-r--r--dialects/linux/machine.h9
-rw-r--r--dialects/n+obsd/Makefile159
-rwxr-xr-xdialects/n+obsd/Mksrc24
-rw-r--r--dialects/n+obsd/dlsof.h584
-rw-r--r--dialects/n+obsd/dmnt.c256
-rw-r--r--dialects/n+obsd/dnode.c1459
-rw-r--r--dialects/n+obsd/dnode1.c95
-rw-r--r--dialects/n+obsd/dproc.c584
-rw-r--r--dialects/n+obsd/dproto.h55
-rw-r--r--dialects/n+obsd/dsock.c425
-rw-r--r--dialects/n+obsd/dstore.c132
-rw-r--r--dialects/n+obsd/machine.h623
-rw-r--r--dialects/n+os/Makefile169
-rwxr-xr-xdialects/n+os/Mksrc24
-rw-r--r--dialects/n+os/dlsof.h272
-rw-r--r--dialects/n+os/dnode.c711
-rw-r--r--dialects/n+os/dnode1.c401
-rw-r--r--dialects/n+os/dproc.c767
-rw-r--r--dialects/n+os/dproto.h53
-rw-r--r--dialects/n+os/dsock.c306
-rw-r--r--dialects/n+os/dstore.c133
-rw-r--r--dialects/n+os/machine.h615
-rw-r--r--dialects/osr/Makefile165
-rwxr-xr-xdialects/osr/Mksrc25
-rw-r--r--dialects/osr/dfile.c161
-rw-r--r--dialects/osr/dlsof.h255
-rw-r--r--dialects/osr/dmnt.c219
-rw-r--r--dialects/osr/dnode.c739
-rw-r--r--dialects/osr/dproc.c2003
-rw-r--r--dialects/osr/dproto.h62
-rw-r--r--dialects/osr/dsock.c422
-rw-r--r--dialects/osr/dstore.c154
-rw-r--r--dialects/osr/include/netdb.h121
-rw-r--r--dialects/osr/include/sys/cdefs.h98
-rw-r--r--dialects/osr/machine.h614
-rw-r--r--dialects/sun/Makefile160
-rwxr-xr-xdialects/sun/Mksrc57
-rw-r--r--dialects/sun/ddev.c1143
-rw-r--r--dialects/sun/dfile.c669
-rw-r--r--dialects/sun/dlsof.h690
-rw-r--r--dialects/sun/dmnt.c417
-rw-r--r--dialects/sun/dnode.c5509
-rw-r--r--dialects/sun/dnode1.c441
-rw-r--r--dialects/sun/dnode2.c518
-rw-r--r--dialects/sun/dproc.c2239
-rw-r--r--dialects/sun/dproto.h109
-rw-r--r--dialects/sun/dsock.c2089
-rw-r--r--dialects/sun/dstore.c234
-rw-r--r--dialects/sun/machine.h749
-rw-r--r--dialects/sun/solaris_kaddr_filters239
-rw-r--r--dialects/uw/Makefile159
-rwxr-xr-xdialects/uw/Mksrc23
-rw-r--r--dialects/uw/dfile.c216
-rw-r--r--dialects/uw/dlsof.h358
-rw-r--r--dialects/uw/dmnt.c227
-rw-r--r--dialects/uw/dnode.c1574
-rw-r--r--dialects/uw/dnode1.c94
-rw-r--r--dialects/uw/dnode2.c114
-rw-r--r--dialects/uw/dnode3.c271
-rw-r--r--dialects/uw/dproc.c650
-rw-r--r--dialects/uw/dproto.h49
-rw-r--r--dialects/uw/dsock.c1197
-rw-r--r--dialects/uw/dstore.c134
-rw-r--r--dialects/uw/machine.h630
-rw-r--r--dialects/uw/uw7/README6
-rw-r--r--dialects/uw/uw7/fs/nsc_cfs/cnode.h78
-rw-r--r--dialects/uw/uw7/fs/procfs/README4
-rw-r--r--dialects/uw/uw7/fs/procfs/prdata.h228
-rw-r--r--dialects/uw/uw7/sys/fs/README6
-rw-r--r--dialects/uw/uw7/sys/fs/fifonode.h143
-rw-r--r--dialects/uw/uw7/sys/fs/namenode.h100
-rw-r--r--lsof.832
-rw-r--r--lsof.h32
-rw-r--r--lsof.man1448
-rw-r--r--lsof_fields.h4
-rw-r--r--main.c78
-rw-r--r--misc.c28
-rw-r--r--proc.c150
-rw-r--r--proto.h10
-rw-r--r--store.c7
-rw-r--r--tests/TestDB7
-rw-r--r--usage.c43
-rw-r--r--version2
200 files changed, 74523 insertions, 1076 deletions
diff --git a/00.README.FIRST_4.87 b/00.README.FIRST_4.87
deleted file mode 100644
index 14e0b17..0000000
--- a/00.README.FIRST_4.87
+++ /dev/null
@@ -1,29 +0,0 @@
-A tour of the lsof_4.87 distribution:
-
- 00.README.FIRST_4.87 is this file.
-
- README.lsof_4.87 contains distribution and security information.
-
- RELEASE.SUMMARY_4.87 contains a summary of the lsof 4.87
- distribution.
-
- lsof_4.87_src.tar is the lsof 4.87 source tar archive.
-
- lsof_4.87_src.tar.sig is a detached GPG certificate for
- lsof_4.87_src.tar.
-
-I suggest you follow these steps:
-
-1. Read 00.README.FIRST_4.87.
-
-2. Read README.lsof_4.87 and follow its instructions to verify
- the authenticity of lsof_4.87_src.tar.
-
-3. Unpack lsof_4.87_src.tar -- use `tar xf lsof_4.87_src.tar`.
- That will produce an lsof_4.87_src sub-directory.
-
-4. Change to the lsof_4.87_src sub-directory and read its
- 00.README.FIRST file.
-
-Vic Abell <abe@purdue.edu>
-Wed Jan 2 12:52:08 EST 2013
diff --git a/00CREDITS b/00CREDITS
index 9c7688a..e86a151 100644
--- a/00CREDITS
+++ b/00CREDITS
@@ -82,6 +82,7 @@ provided test systems where I was able to do development work.
John Caruso
Jon Champlin
Kris Chandrasekhar
+ Stephane Chazelas
Albert Chin-A-Young
Bernt Christandl
Marc Christensen
@@ -375,6 +376,7 @@ provided test systems where I was able to do development work.
Hung Pham
Ray Phillips
Francois Pinard
+ Gary Plewa
Alex Podlecki
Lutz Poetschulat,
John Polstra
@@ -406,6 +408,7 @@ provided test systems where I was able to do development work.
Kevin Ruderman
Wolfgang Rupprecht
Pavol Rusnak
+ Eygene Ryabinkin
Conrad J. Sabatier
Klaus Saggerer
Chris Schanzle
@@ -530,4 +533,4 @@ and I apologize for the error.
Vic Abell <abe@purdue.edu>
-January 2, 2013
+October 13, 2014
diff --git a/00DCACHE b/00DCACHE
index 58747b2..4382376 100644
--- a/00DCACHE
+++ b/00DCACHE
@@ -727,7 +727,7 @@ machine.h header files.
AIX 5.[12] and 5.3-ML1
FreeBSD 4.x, 4.1x, 5.x and [6789].x for x86-based systems
- FreeBSD 5.x, [6789].x fnd 10.xor Alpha, AMD64 and Sparc64-a
+ FreeBSD 5.x, [6789].x and 10 for Alpha, AMD64 and Sparc64-a
based systems
HP-UX 11.00
NetBSD 1.[456], 2.x and 3.x for Alpha, x86, and SPARC-based
@@ -742,4 +742,4 @@ machine.h header files.
Vic Abell <abe@purdue.edu>
-April 10, 2012
+October 13, 2014
diff --git a/00DIALECTS b/00DIALECTS
index 16652de..33364be 100644
--- a/00DIALECTS
+++ b/00DIALECTS
@@ -1,5 +1,4 @@
Apple Darwin 9 and Mac OS X 10.[567]
- FreeBSD 4.9 and 6.4 for x86-based systems
- FreeBSD 8.2, 9.0 and 10.0 for AMD64-based systems
+ FreeBSD 8.[234], 9.0, 10.0 and 11.0 for AMD64-based systems
Linux 2.1.72 and above for x86-based systems
Solaris 9, 10 and 11
diff --git a/00DIST b/00DIST
index c1dcdbb..bd1d700 100644
--- a/00DIST
+++ b/00DIST
@@ -116,6 +116,7 @@
4.85, September 27, 2011
4.86, April 10, 2012
4.87, January 2, 2013
+ 4.88, October 13, 2014
Dialects Supported
@@ -127,8 +128,7 @@ version 3, itself a major revision of version 2. Version 4 has
been tested on:
Apple Darwin 9 and Mac OS X 10.[567]
- FreeBSD 4.9 and 6.4 for x86-based systems
- FreeBSD 8.2, 9.0 and 10.0 for AMD64-based systems
+ FreeBSD 8.[234], 9.0, 10.0 and 11.0 for AMD64-based systems
Linux 2.1.72 and above for x86-based systems
Solaris 9, 10 and 11
@@ -4692,5 +4692,53 @@ Supplement Regenerated the 4.04 distribution to correct a non-
<yamato@redhat.com> developed the kernel patch to getxattr()
and supplied the lsof patch.
+4.88 October 13, 2014
+ Reduced to 50 the number of open file descriptors lsof
+ attempts to close while trying to protect itself from a
+ file descriptor exec() attack. This limits the overhead
+ lsof incurs on systems that have large file descriptor
+ limits, yet provides sufficient open descriptors for the
+ library functions lsof calls.
+
+ Updated for changes in FreeBSD 10 with advice from Eygene
+ Ryabinkin <rea@freebsd.org>. Taught Configure to recognize
+ FreeBSD 8.4.
+
+ Herein am noting that lsof for Solaris 10 or 11 is no longer
+ supported. I no longer have test systems. Some support is
+ still available from Casper Dik <Casper.Dik@oracle.com> and a
+ Solaris 11 patch he provided is included in this revision.
+
+ Initialized local variables in the Linux process_id() function.
+ Jia He <jiakernel@gmail.com> reported the problem.
+
+ Added support for FreeBSD 11.
+
+ Updated FreeBSD ZFS Configure stanza to supply a dummy
+ opt_kdtrace.h when needed.
+
+ Added tmpfs file system support for FreeBSD.
+
+ Since a test system is no longer available, dropped the
+ claim of FreeBSD 4.9 support.
+
+ Added the +|-E options for Linux. -E displays endpoint info;
+ +E displays endpoint info and endpopint files. Masatake YAMATO
+ <yamato@redhat.com> requested this support and suggested code
+ to implement it.
+
+ Fixed a Linux bug handling processes whose command includes a
+ non-printing character, particularly a NEWLINE character, and
+ clarified printing of single '\\' characters in command and
+ file names. Stephane Chazelas <stephane.chazelas@gmail.com>
+ reported the problem.
+
+ Added support for Linux RDMA and CRYPTO protocal names and UNIX
+ socket type with code from Masatake YAMATO <yamato@redhat.com>.
+
+ Fixed field output to insure that the field descriptor field is
+ always selected, since it identifies the file set. The bug was
+ reported by Gary Plewa <gary.m.plewa-1@lowes.com>.
+
Vic Abell <abe@purdue.edu>
-January 2, 2013
+October 13, 2014
diff --git a/00FAQ b/00FAQ
index c75ae9f..2937ff8 100644
--- a/00FAQ
+++ b/00FAQ
@@ -13,7 +13,7 @@ This file contains frequently asked questions about lsof and answers
to them.
Vic Abell <abe@purdue.edu>
-January 3, 2013
+October 13, 2014
______________________________________________________________________
Table of Contents:
@@ -549,11 +549,14 @@ ______________________________________________________________________
1.2.1 Are there mirror sites?
- On April 28, 2009 these sites appeared to have the lastest
+ On March 21, 2013 these sites appeared to have the lastest
lsof revision:
ftp://ftp.fu-berlin.de/pub/unix/tools/lsof
ftp://sunsite.ualberta.ca/pub/Mirror/lsof
+ http://www.mirrorservice.org/sites/lsof.itap.purdue.edu/pub/tools/unix/lsof/
+ ftp://ftp.mirrorservice.org/sites/lsof.itap.purdue.edu/pub/tools/unix/lsof/
+ rsync://rsync.mirrorservice.org/lsof.itap.purdue.edu/pub/tools/unix/lsof/
1.2.2 Are lsof executables available?
@@ -939,7 +942,7 @@ ______________________________________________________________________
AIX 5.[23] and 5.3
FreeBSD 4.9 and 6.4 for x86-based systems
- FreeBSD 8.2, 9.0 and 10.0 for AMD64-based systems
+ FreeBSD 8.[234], 9.0, 10.0 and 11.0 for AMD64-based systems
Linux 2.1.72 and above for x86-based systems
Solaris 9, 10 and 11
diff --git a/00PORTING b/00PORTING
index 2683946..e4dc550 100644
--- a/00PORTING
+++ b/00PORTING
@@ -778,6 +778,9 @@ possibilities
HASEOPT indicates the dialect supports the -e option to
eliminate kernel blocks on a named file system.
+ HASEPTOPTS indicates the dialect supports the +|-E end point
+ options.
+
HASEXT2FS is defined for BSD dialects for which ext2fs
file system support can be provided. A value
of 1 indicates that the i_e2din member does not
@@ -786,6 +789,9 @@ possibilities
HASF_VNODE indicates the dialect's file structure has an
f_vnode member in it.
+ HAS_FILEDESCENT indicates the FreeBSD system has the filedescent
+ definition in the <sys/filedesc.h> header file.
+
HASFDESCFS enables file descriptor file system support
for the dialect. A value of 1 indicates
<miscfs/fdesc.h> has a Fctty definition; 2,
@@ -815,8 +821,6 @@ possibilities
name cache. See dialects/osr/dproc.c for
an example.
- HAS_JFS2 The AIX >= 5.0 dialect has jfs2 support.
-
HASFSTRUCT indicates the dialect has a file structure
the listing of whose element values can be
enabled with +f[cfn]. FSV_DEFAULT defines
@@ -891,6 +895,8 @@ possibilities
HASIPv6 indicates the dialect supports the IPv6
Internet address family.
+ HAS_JFS2 The AIX >= 5.0 dialect has jfs2 support.
+
HASKERNELKEYT indicates the Linux version has a
__kernel_key_t typedef in <linux/types.h>.
@@ -904,6 +910,9 @@ possibilities
kernel's name list from a file -- e.g., from
a crash dump file.
+ HAS_PAUSE_SBT indicates the FreeBSD system's systm.h has the
+ pause to pause_sbt definition.
+
HASKQUEUE indicates the dialect supports the kqueue
file type.
@@ -1236,6 +1245,9 @@ possibilities
Tru64 UNIX dialect has a libmsfs.so,
containing tag_to_path().
+ HAS_TMPFS indicates the FreeBSD system has the <fs/tmpfs.h>
+ header file.
+
HASTMPNODE enables/disables readtnode() in node.c.
HASTCPOPT indicates the dialect has TCP option
@@ -1835,4 +1847,4 @@ keep in mind the private, one-man nature of current lsof support.
Vic Abell <abe@purdue.edu>
-January 2, 2013
+October 13, 2014
diff --git a/00QUICKSTART b/00QUICKSTART
index 697734e..48bebd1 100644
--- a/00QUICKSTART
+++ b/00QUICKSTART
@@ -265,12 +265,11 @@
Address Type Vnode Conn Local Addr Remote Addr
ffffff0084253b68 stream-ord 0000000 0000000
- Using lsof's -U opetion and its output piped to a grep on the address
+ Using lsof's -U option and its output piped to a grep on the address
yields:
$ lsof -U | grep ffffff0084253b68
squid 1638 nobody 12u unix 18,98 0t10 9437188 /devices/pseudo/tl@0:ticots->0xffffff0084253b68 stream-ord
- $ lsof -U |
8. Finding Files Open to a Named Command
@@ -1020,4 +1019,4 @@ D. Miscellaneous Lsof Options
Vic Abell <abe@purdue.edu>
-January 18, 2010
+October 13, 2014
diff --git a/00TEST b/00TEST
index 624d0a4..5162be1 100644
--- a/00TEST
+++ b/00TEST
@@ -903,8 +903,11 @@ base, footprints, and the scripts that support them.
8.0 Amd64, gcc
8.2 Amd64, gcc
8.3 Amd64, gcc
+ 8.4 Amd64, gcc
9.0 Amd64, gcc
10.0 Amd64, gcc
+ 10.0 Amd64, clang
+ 11.0 Amd64, clang
DEC OSF/1 4.0, cc
HP-UX 10.20, cc LTbigf
10.20, gcc (1) LTbigf
@@ -945,6 +948,8 @@ base, footprints, and the scripts that support them.
supplies file offsets to
lsof.)
2.6.38-686
+ 3.10.004
+ 3.10.08
NEXTSTEP 3.1, gcc LTnfs
NetBSD 1.4.1, Alpha, gcc LTnfs
1.5x, x86, gcc LTnfs
@@ -1023,4 +1028,4 @@ I was unable to make the test suite run on the following dialects.
Vic Abell <abe@purdue.edu>
-April 10, 2012
+October 13, 2014
diff --git a/00XCONFIG b/00XCONFIG
index c89ae8e..6db0db0 100644
--- a/00XCONFIG
+++ b/00XCONFIG
@@ -150,11 +150,26 @@ LSOF_HOST may be used to specify a value in lsof's -v output
default: the dialect's host name application -- e.g.,
hostname or uname -n
-LSOF_INCLUDE is the path to the standard header files. You may
- need to specify it if you want Configure to test
- header files in a tree different from /usr/include,
- and you want to compile lsof from the header files
- in that different tree.
+LSOF_INCLUDE is the path to a tree of header files that is an exact
+ image of the the standard header file tree for the
+ target dialect. You may need to specify it if you
+ want Configure to test header files in a tree different
+ from /usr/include and compile its test programs with
+ header files from that tree, then you want to compile
+ lsof from the header files in that different, duplicate
+ image tree.
+
+ Note: LSOF_INCLUDE should contain a single path
+ without any option flags, such as -I. It is always
+ supplied to the compiler in CFLAGS following the -I
+ option flag. If you want to specify other include
+ paths, use LSOF_OPINC.
+
+ ADDITIONAL NOTE: all the header files that lsof's
+ Configure tests for optional features and uses to
+ compile test programs must be in LSOF_CONFIGURE.
+ They can't be scattered in the other include path
+ that LSOF_OPINC names.
LSOF_LOGNAME may be used to specify a value in lsof's -v output
other than the one in the LOGNAME environment
@@ -175,6 +190,19 @@ LSOF_MKC may be used to specify an alternate method of
default: ln -s
+LSOF_OPINC may be used to specify other include file search
+ paths. Each must be preceded by the compiler's -I
+ option file and, if there are muliple paths, they
+ must be separated by spaces and the entire set must
+ be enclosed in double quote marks -- e.g.,
+
+ LSOF_OPINC="-I/path1 -I/path2 ..."
+
+ The optional include paths thus specified will be
+ appended to LSOF_INCLUDE and whatever special
+ include paths the lsof Configure script finds
+ necessary.
+
LSOF_RANLIB may be used to specify an alternate command for the
randomizing of the lsof library.
@@ -700,4 +728,4 @@ UW_HAS_NSC If this environment variable has a value of "Y" or "y",
default: tested via /bin/node_self
Vic Abell <abe@purdue.edu>
-September 27, 2011
+October 13, 2014
diff --git a/Configure b/Configure
index 005d05b..aba0f2d 100755
--- a/Configure
+++ b/Configure
@@ -14,7 +14,7 @@
# shell script, named $LSOF_MK, that places its source modules in this
# directory.
#
-# $Id: Configure,v 1.162 2013/01/02 17:13:48 abe Exp $
+# $Id: Configure,v 1.163 2014/10/13 22:31:08 abe Exp $
# LSOF_CFLAGS_OVERRIDE=1 may be introduced through the environment to cause
# the library Makefile's CFLAGS definition to override any in the
@@ -104,6 +104,8 @@ LSOF_VF=version
# $LSOF_NBSD_BUFQH NetBSD <sys/bufq.h> copy status
# $LSOF_NBSD_PTYFS NetBSD ${NETBSD_SYS}/sys/fs/ptyfs/ copy status
# $LSOF_N_UNIXV *BSD system's kernel file
+# $LSOF_OPINC supplies additional -I/path arguments for the
+# Makefile's CFLAGS.
# $LSOF_PL patch level
# $LSOF_RANLIB randomizing command for the lsof library
# $LSOF_RANLIB_SUP if non-NULL $LSOF_RANLIB was supplied
@@ -132,6 +134,7 @@ LSOF_VF=version
# $LSOF_TSTXO test extra objects (for $LSOF_TSTXOC)
# $LSOF_TSTXOC test extra objects file
# $LSOF_UNSUP Lsof is unsupported on this dialect
+# $LSOF_UNSUP2 Second message about lack of support
# $LSOF_VERS Unix dialect version as a decimal number (may
# be supplied externally)
# $LSOF_VSTR Unix dialect version as a string -- may be supplied
@@ -199,6 +202,7 @@ LSOF_TSTVPATH=0
LSOF_TSTXO=""
LSOF_TSTXOC="${LSOF_TSTSUBD}/config.xobj"
LSOF_UNSUP="WARNING: unsupported dialect or version"
+LSOF_UNSUP2=""
if test "X$LSOF_VERS" = "X" # {
then
LSOF_VERS=""
@@ -289,6 +293,8 @@ do
echo "rm -rf AFSHeaders AFSVersion solaris11 version.h vnode_if.h"
rm -f ${LSOF_HLP_BASE}* cd9660_node.h lockf_owner.h fbsd_minor.h
echo "rm -f ${LSOF_HLP_BASE}* cd9660_node.h lockf_owner.h fbsd_minor.h"
+ rm -f opt_kdtrace.h
+ echo "rm -f opt_kdtrace.h"
rm -f dialects/aix/aix5/j2/j2_snapshot.h
echo "rm -f dialects/aix/aix5/j2/j2_snapshot.h"
rm -f dialects/sun/solaris10 # DEBUG -- for s10_44
@@ -1595,6 +1601,10 @@ kernel generation process.
LSOF_TSTBIGF=" "
LSOF_VERS=8030
;;
+ 8.4*)
+ LSOF_TSTBIGF=" "
+ LSOF_VERS=8040
+ ;;
9*)
LSOF_TSTBIGF=" "
LSOF_VERS=9000
@@ -1603,6 +1613,10 @@ kernel generation process.
LSOF_TSTBIGF=" "
LSOF_VERS=10000
;;
+ 11*)
+ LSOF_TSTBIGF=" "
+ LSOF_VERS=11000
+ ;;
*)
echo Unknown FreeBSD release: `uname -r`
rm -f $LSOF_HLP
@@ -1614,7 +1628,7 @@ kernel generation process.
# Clear LSOF_UNSUP message for supported versions of FreeBSD.
case $LSOF_VERS in # {
- 4090|8020|8030|9000|10000)
+ 4090|8020|8030|8040|9000|10000|11000)
LSOF_UNSUP=""
;;
esac # }
@@ -1680,6 +1694,17 @@ kernel generation process.
exit 1
fi # }
+ # Test pause() status in system.h.
+
+ if test -r ${FREEBSD_SYS}/sys/systm.h # {
+ then
+ grep -q pause_sbt ${FREEBSD_SYS}/sys/systm.h
+ if test $? -eq 0 # {
+ then
+ LSOF_CFGF="$LSOF_CFGF -DHAS_PAUSE_SBT"
+ fi # }
+ fi # }
+
# Do FreeBSD version-specific stuff.
case $LSOF_VERS in # {
@@ -1771,6 +1796,18 @@ kernel generation process.
fi # }
fi # }
fi # }
+ if test -r ${FREEBSD_SYS}/sys/filedesc.h # {
+ then
+ grep -q filedescent ${FREEBSD_SYS}/sys/filedesc.h
+ if test $? -eq 0 # {
+ then
+ LSOF_CFGF="$LSOF_CFGF -DHAS_FILEDESCENT"
+ fi # }
+ fi # }
+ if test -r ${FREEBSD_SYS}/fs/tmpfs/tmpfs.h # {
+ then
+ LSOF_CFGF="$LSOF_CFGF -DHAS_TMPFS"
+ fi #}
# Do FreeBSD 5.2 and higher version-specific stuff.
@@ -1943,6 +1980,23 @@ FBSD_MINOR3
then
LSOF_FBSD_ZFS_CFGF="$LSOF_FBSD_ZFS_CFGF -DHAS_Z_PHYS"
fi # }
+ if test -r ${LSOF_FBSD_ZFS_SYS}/compat/opensolaris/sys/sdt.h #{
+ then
+ grep -q opt_kdtrace.h ${LSOF_FBSD_ZFS_SYS}/compat/opensolaris/sys/sdt.h
+ if test $? -eq 0 # {
+ then
+ rm -f opt_kdtrace.h
+ touch opt_kdtrace.h
+ fi # }
+ fi # }
+ if test -r ${LSOF_FBSD_ZFS_SYS}/compat/opensolaris/sys/kcondvar.h #{
+ then
+ grep -q cv_timedwait_sbt ${LSOF_FBSD_ZFS_SYS}/compat/opensolaris/sys/kcondvar.h
+ if test $? -eq 0 # {
+ then
+ LSOF_FBSD_ZFS_CFGF="$LSOF_FBSD_ZFS_CFGF -DHAS_CV_TIMEDWAIT_SBT"
+ fi # }
+ fi #}
fi # }
if test -r ${LSOF_INCLUDE}/sys/vnode.h # {
then
@@ -4952,6 +5006,10 @@ return(0); }
if test $LSOF_TMP1 -eq 1 # {
then
+ # Warn that VxFS is unsupported.
+
+ LSOF_UNSUP2="WARNING: VxFS is no longer supported by Solaris lsof."
+
# The VxFS header files are for VxFS version 3.4 or above. Enable VxFS
# for those versions.
@@ -5438,6 +5496,10 @@ else
fi # }
fi # }
echo "DEBUG= $LSOF_DEBUG" >> $LSOF_MKFC
+if test "X$LSOF_OPINC" != "X" # {
+then
+ LSOF_DINC="$LSOF_DINC $LSOF_OPINC"
+fi # }
if test "X$LSOF_DINC" != "X" # {
then
echo "" >> $LSOF_MKFC
@@ -5594,10 +5656,14 @@ then
./Customize $LSOF_DIALECT_DIR
fi # }
-# Issue unsupported warning, as appropriate.
+# Issue unsupported warnings, as appropriate.
if test "X$LSOF_UNSUP" != "X" # {
then
echo "$LSOF_UNSUP"
fi #}
+if test "X$LSOF_UNSUP2" != "X" # {
+then
+ echo "$LSOF_UNSUP2"
+fi #}
exit 0
diff --git a/README.lsof_4.87 b/README.lsof_4.87
deleted file mode 100644
index fe906c4..0000000
--- a/README.lsof_4.87
+++ /dev/null
@@ -1,128 +0,0 @@
-
- Information About This Lsof Distribution
-
-
-What You Have
-=============
-
-If you got this far without being confused, then you are probably
-familiar with the construction of the lsof distribution or you have
-read RELEASE.SUMMARY_4.87. If either is the case, please skip to
-the Inventory section. If you haven't read RELEASE.SUMMARY_4.87,
-I suggest you do it now, because it explains how the lsof distribution
-is constructed and other useful things about lsof, including a
-summary of changes for the past few lsof revisions.
-
-Even though you may have thought you were getting lsof.tar.bz2,
-lsof.tar.gz or lsof.tar.Z with ftp, you really got lsof_4.87.tar.bz2,
-lsof_4.87.tar.gz or lsof_4.87.tar.Z. That's because the triplet of
-lsof.tar.* files are symbolic links to their longer-named counterparts.
-
-The bzip2'd, gzip'd or compressed tar files with lsof_, followed by a
-number, are wrapper archives, designed to package the lsof source
-archive, this file, other documentation files, and a GPG authentication
-certificate together.
-
-The number, 4.87, is the lsof revision number. When you bunzip2'd,
-gunzip'd or uncompressed lsof_4.87.tar.* and used tar to unpack
-lsof_4.87.tar, you got: 00.README.FIRST_4.87, describing the contents
-of lsof_4.87; README.lsof_4.87; lsof_4.87_src.tar; and
-lsof_4.87_src.tar.sig. All are identified with the revision number.
-You're reading README.lsof_4.87. lsof_4.87_src.tar.sig is a GPG
-certificate that authenticates the lsof source archive,
-lsof_4.87_src.tar.
-
-After you read the Inventory and Security sections, and hopefully
-after you check the GPG certificate, unpack the lsof_4.87_src.tar
-source archive and you will get a sub-directory, named lsof_4.87_src,
-that contains the lsof 4.87 source distribution.
-
-
-Inventory
-=========
-
-Once you have unpacked lsof_4.87_src.tar.tar, you can check
-lsof_4.87_src for completeness by changing to that sub-directory
-and running the Inventory script. The lsof_4.87_src/Configure
-script runs the Inventory script, too. The Configure script also
-calls a customization script, called Customize. You can direct
-Configure to avoid calling Inventory and Customize with the -n
-option.
-
-See the Distribution Contents section of the 00DIST file and The
-Inventory Script section of the 00README file for more information
-on the contents of the lsof distribution, and the Configure,
-Customize and Inventory scripts. The 00DIST and 00README files
-will be found in the lsof_4.87_src sub-directory you just created.
-
-
-Security
-========
-
-The md5 checksum for lsof_4.87_src.tar is:
-
- MD5 (lsof_4.87_src.tar) = d451291231fcfeec92b5a9a2b7fff4e5
-
-A good source for an MD5 checksum computation tool is the OpenSSL
-project whose work may be found at:
-
- www.openssl.org
-
-You can use the openssl "dgst" operator to compute an MD5 checksum --
-e.g.,
-
- $ openssl dgst -md5 lsof_4.87_src
-
-The old-style sum(1) checksum for lsof_4.87_src.tar (Please read
-the next paragraph if you don't get this value.) is:
-
- 45946 8490 lsof_4.87/lsof_4.87_src.tar
-
-If your dialect's sum(1) program defaults to the new style algorithm
-(e.g., Solaris), you may have to use its -r option (or use the
-Solaris /usr/ucb/sum). If your Unix dialect doesn't have a sum(1)
-program (e.g., FreeBSD, or NetBSD), use its cksum(1) program with
-the -o1 option to get an old-style checksum. You may also need to
-ignore the block count, depending on the block size used on your
-your system (i.e., 512 or 1,024). The sum(1) that produced the
-above checksum considers block size to be 512; in contrast the BSD
-cksum(1) programs' -o1 option considers block size to be 1,024.
-
-lsof_4.87_src.tar.sig is a GPG certificate file, using my public
-key. My key may be available on some public key servers under the
-names:
-
- Victor A. Abell <abe@cc.purdue.edu>
- or
- Victor A. Abell <abe@purdue.edu>
-
-You will also find it at:
-
- ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/Victor_A_Abell.gpg
-
-Get my key and install it in your public key ring.
-
-Once my key is installed, use this command to check the certificate
-of lsof_4.87_src.tar:
-
- gpg --verify lsof_4.87_src.tar.sig lsof_4.87_src.tar
-
-If the certificate check isn't good, lsof_4.87_src.tar is suspect.
-Report the problem to me via e-mail at <abe@purdue.edu>.
-
-If you don't have GPG, you can compare the md5 checksum of
-lsof_4.87_src.tar to the value listed in this file. However, that
-is a less reliable authentication method, since it can't detect
-changes to both lsof_4.87_src.tar and the md5 checksum value listed
-in this tile.
-
-Other Security
-==============
-
-Signature information for the distribution file that contains
-this file may be found in the CHECKSUMS file that is located
-where the distribution file was found.
-
-
-Victor A. Abell <abe@purdue.edu>
-Wed Jan 2 12:52:06 EST 2013
diff --git a/arg.c b/arg.c
index 59d4acb..5371927 100644
--- a/arg.c
+++ b/arg.c
@@ -32,7 +32,7 @@
#ifndef lint
static char copyright[] =
"@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n";
-static char *rcsid = "$Id: arg.c,v 1.51 2012/04/10 16:30:06 abe Exp $";
+static char *rcsid = "$Id: arg.c,v 1.51 2012/04/10 16:30:06 abe Exp abe $";
#endif
diff --git a/dialects/aix/Makefile b/dialects/aix/Makefile
new file mode 100644
index 0000000..830a25f
--- /dev/null
+++ b/dialects/aix/Makefile
@@ -0,0 +1,169 @@
+
+# AIX Makefile
+#
+# $Id: Makefile,v 1.14 2008/04/15 13:28:12 abe Exp $
+
+PROG= lsof
+
+BIN= ${DESTDIR}
+
+DOC= ${DESTDIR}
+
+I=/usr/include
+S=/usr/include/sys
+L=/usr/include/local
+P=
+
+CDEF=
+CDEFS= ${CDEF} ${CFGF}
+INCL= ${DINC}
+CFLAGS= ${CDEFS} ${INCL} ${DEBUG}
+
+GRP=
+
+HDR= lsof.h lsof_fields.h dlsof.h machine.h proto.h dproto.h
+
+SRC= ddev.c dfile.c dmnt.c dnode.c dnode1.c dnode2.c dproc.c dsock.c \
+ dstore.c arg.c main.c misc.c node.c print.c proc.c store.c usage.c \
+ util.o
+
+OBJ= ddev.o dfile.o dmnt.o dnode.o dnode1.o dnode2.o dproc.o dsock.o \
+ dstore.o arg.o main.o misc.o node.o print.o proc.o store.o usage.o \
+ util.o
+
+MAN= lsof.8
+
+OTHER=
+
+SHELL= /bin/sh
+
+SOURCE= Makefile ${OTHER} ${MAN} ${HDR} ${SRC}
+
+all: ${PROG}
+
+${PROG}: ${LIB} ${P} ${OBJ}
+ ${CC} -o $@ ${CFLAGS} ${OBJ} ${CFGL}
+
+clean: FRC
+ rm -f Makefile.bak ${PROG} a.out core errs lint.out tags *.o version.h
+ rm -f machine.h.old new_machine.h
+ (cd lib; ${MAKE} -f Makefile.skel clean)
+
+install: all FRC
+ @echo ''
+ @echo 'Please write your own install rule. Lsof Needs to be able to'
+ @echo 'read /dev/kmem and /dev/mem'. Installing it segid to the group'
+ @echo 'that can read those devices is one way to allow it to read them.'
+ @echo 'normally that group is the system group and your install rule'
+ @echo 'might look something like this:'
+ @echo ''
+ @echo ' install -f $${BIN} -S -M 2755 -G $${GRP} $${PROG}'
+ @echo ' install -f $${DOC} -M 444 $${MAN}'
+ @echo ''
+ @echo 'You will have to complete the skeletons for the BIN, DOC, and'
+ @echo 'GRP strings given at the beginning of this Makefile, e.g.,'
+ @echo ''
+ @echo ' BIN= $${DESTDIR}/usr/local/etc'
+ @echo ' DOC= $${DESTDIR}/usr/man/man8'
+ @echo ' GRP= system'
+ @echo ''
+ @echo 'You might also consider giving lsof permission to read /dev/kmem'
+ @echo 'and /dev/mem via ACLs. First, establish a new group to which'
+ @echo 'you will setgid lsof -- e.g., group kmem. Next, change the ACLs'
+ @echo 'for /dev/kmem and /dev/mem to permit group kmem members to read'
+ @echo 'them. Finally, install lsof setgid the kmem group with:
+ @echo ''
+ @echo ' GRP= kmem'
+
+${LIB}: FRC
+ (cd lib; ${MAKE} DEBUG="${DEBUG}" CFGF="${CFGF}")
+
+version.h: FRC
+ @echo Constructing version.h
+ @rm -f version.h
+ @echo '#define LSOF_BLDCMT "${LSOF_BLDCMT}"' > version.h;
+ @echo '#define LSOF_CC "${CC}"' >> version.h
+ @echo '#define LSOF_CCV "${CCV}"' >> version.h
+ @echo '#define LSOF_CCDATE "'`date`'"' >> version.h
+ @echo '#define LSOF_CCFLAGS "'`echo ${CFLAGS} | sed 's/\\\\(/\\(/g' | sed 's/\\\\)/\\)/g' | sed 's/"/\\\\"/g'`'"' >> version.h
+ @echo '#define LSOF_CINFO "${CINFO}"' >> version.h
+ @if [ "X${LSOF_HOST}" = "X" ]; then \
+ echo '#define LSOF_HOST "'`uname -n`'"' >> version.h; \
+ else \
+ if [ "${LSOF_HOST}" = "none" ]; then \
+ echo '#define LSOF_HOST ""' >> version.h; \
+ else \
+ echo '#define LSOF_HOST "${LSOF_HOST}"' >> version.h; \
+ fi \
+ fi
+ @echo '#define LSOF_LDFLAGS "${CFGL}"' >> version.h
+ @if [ "X${LSOF_LOGNAME}" = "X" ]; then \
+ echo '#define LSOF_LOGNAME "${LOGNAME}"' >> version.h; \
+ else \
+ if [ "${LSOF_LOGNAME}" = "none" ]; then \
+ echo '#define LSOF_LOGNAME ""' >> version.h; \
+ else \
+ echo '#define LSOF_LOGNAME "${LSOF_LOGNAME}"' >> version.h; \
+ fi; \
+ fi
+ @if [ "X${LSOF_SYSINFO}" = "X" ]; then \
+ echo '#define LSOF_SYSINFO "'`uname -a`'"' >> version.h; \
+ else \
+ if [ "${LSOF_SYSINFO}" = "none" ]; then \
+ echo '#define LSOF_SYSINFO ""' >> version.h; \
+ else \
+ echo '#define LSOF_SYSINFO "${LSOF_SYSINFO}"' >> version.h; \
+ fi \
+ fi
+ @if [ "X${LSOF_USER}" = "X" ]; then \
+ echo '#define LSOF_USER "${USER}"' >> version.h; \
+ else \
+ if [ "${LSOF_USER}" = "none" ]; then \
+ echo '#define LSOF_USER ""' >> version.h; \
+ else \
+ echo '#define LSOF_USER "${LSOF_USER}"' >> version.h; \
+ fi \
+ fi
+ @sed '/VN/s/.ds VN \(.*\)/#define LSOF_VERSION "\1"/' < version >> version.h
+
+FRC:
+
+# DO NOT DELETE THIS LINE - make depend DEPENDS ON IT
+
+ddev.o: ${HDR} ddev.c
+
+dfile.o: ${HDR} dfile.c
+
+dmnt.o: ${HDR} dmnt.c
+
+dnode.o: ${HDR} dnode.c
+
+dnode1.o: ${HDR} dnode1.c
+
+dproc.o: ${HDR} dproc.c
+
+dnode2.o: ${HDR} dnode2.c
+
+dsock.o: ${HDR} dsock.c
+
+dstore.o: ${HDR} dstore.c
+
+arg.o: ${HDR} arg.c
+
+main.o: ${HDR} main.c
+
+misc.o: ${HDR} misc.c
+
+node.o: ${HDR} node.c
+
+print.o: ${HDR} print.c
+
+proc.o: ${HDR} proc.c
+
+store.o: ${HDR} store.c
+
+usage.o: ${HDR} version.h usage.c
+
+util.o: ${HDR} util.c
+
+# *** Do not add anything here - It will go away. ***
diff --git a/dialects/aix/Mksrc b/dialects/aix/Mksrc
new file mode 100755
index 0000000..397b61e
--- /dev/null
+++ b/dialects/aix/Mksrc
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Mksrc - make AIX source files
+#
+# WARNING: This script assumes it is running from the main directory
+# of the lsof, version 4 distribution.
+#
+# One environment variable applies:
+#
+# LSOF_MKC is the method for creating the source files.
+# It defaults to "ln -s". A common alternative is "cp".
+#
+# $Id: Mksrc,v 1.3 2003/03/21 17:39:46 abe Exp $
+
+
+D=dialects/aix
+L="dlsof.h ddev.c dfile.c dmnt.c dnode.c dnode1.c dnode2.c dproc.c dproto.h dsock.c dstore.c machine.h"
+
+for i in $L
+do
+ rm -f $i
+ $LSOF_MKC $D/$i $i
+ echo "$LSOF_MKC $D/$i $i"
+done
diff --git a/dialects/aix/aix5/README b/dialects/aix/aix5/README
new file mode 100644
index 0000000..28adc0c
--- /dev/null
+++ b/dialects/aix/aix5/README
@@ -0,0 +1,7 @@
+This directory exists to supply missing /usr/include/j2 header
+files for AIX 5 and above, or to supply alternatives that can be
+#include'd when distributed AIX 5 and above header files can't be
+used -- e.g., they #include missing header files.
+
+Vic Abell
+March 2, 2003
diff --git a/dialects/aix/aix5/j2/j2_lock.h b/dialects/aix/aix5/j2/j2_lock.h
new file mode 100644
index 0000000..9bfc511
--- /dev/null
+++ b/dialects/aix/aix5/j2/j2_lock.h
@@ -0,0 +1,19 @@
+/*
+ * j2_lock.h -- lsof private copy
+ *
+ * Needed for:
+ *
+ * AIX 5L, because it's missing there;
+ * AIX 5.2, because it includes <proc/proc_public.h> and that header
+ * file is missing from AIX 5.2.
+ *
+ * V. Abell <abe@purdue.edu>
+ * Purdue University
+ */
+
+#if !defined(LSOF_J2_LOCK_H)
+#define LSOF_J2_LOCK_H
+typedef long event_t;
+#define MUTEXLOCK_T Simple_lock
+#define RDWRLOCK_T Complex_lock
+#endif /* !defined(LSOF_J2_LOCK_H) */
diff --git a/dialects/aix/aix5/j2/private_j2_snapshot.h b/dialects/aix/aix5/j2/private_j2_snapshot.h
new file mode 100644
index 0000000..0760c0a
--- /dev/null
+++ b/dialects/aix/aix5/j2/private_j2_snapshot.h
@@ -0,0 +1,17 @@
+/*
+ * j2_snapshot.h -- lsof private copy
+ *
+ * Needed for:
+ *
+ * AIX 5.2, because this header file is missing and j2_inode.h #includes
+ * it. The dummy snapshotObject structure definition is needed by
+ * some releases of AIX 5.2 and above, but the structure's size does
+ * not affect lsof's use of the JFS2 inode structure.
+ */
+
+#if !defined(_H_J2_SNAPSHOT)
+#define _H_J2_SNAPSHOT
+struct snapshotObject {
+ uint64 d1;
+};
+#endif /* !defined(_H_J2_SNAPSHOT) */
diff --git a/dialects/aix/ddev.c b/dialects/aix/ddev.c
new file mode 100644
index 0000000..4150aa6
--- /dev/null
+++ b/dialects/aix/ddev.c
@@ -0,0 +1,728 @@
+/*
+ * ddev.c - AIX device support functions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: ddev.c,v 1.14 2005/08/08 19:46:38 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+/*
+ * Local definitions
+ */
+
+#define LIKE_BLK_SPEC "like block special"
+#define LIKE_CHR_SPEC "like character special"
+
+
+/*
+ * Local function prototypes
+ */
+
+_PROTOTYPE(static int rmdupdev,(struct l_dev ***dp, int n, char *nm));
+
+
+#if defined(HASDCACHE) && AIXV>=4140
+
+
+/*
+ * clr_sect() - clear cached clone and pseudo sections
+ */
+
+void
+clr_sect()
+{
+ struct clone *c, *c1;
+
+ if (Clone) {
+ for (c = Clone; c; c = c1) {
+ c1 = c->next;
+ if (c->cd.name)
+ (void) free((FREE_P *)c->cd.name);
+ (void) free((FREE_P *)c);
+ }
+ Clone = (struct clone *)NULL;
+ }
+}
+#endif /* defined(HASDCACHE) && AIXV>=4140 */
+
+
+/*
+ * getchan() - get channel from file path name
+ */
+
+int
+getchan(p)
+ char *p; /* file path name */
+{
+ int ch;
+ char *s;
+
+ if (!(s = strrchr(p, '/')))
+ return(-1);
+ if (*(++s) == '\0')
+ return(-1);
+ for (ch = 0; *s; s++) {
+
+#if defined(__STDC__)
+ if ( ! isdigit(*s))
+#else
+ if ( ! isascii(*s) || ! isdigit(*s))
+#endif /* __STDC__ */
+
+ return(-1);
+ ch = (ch * 10) + *s - '0';
+ }
+ return(ch);
+}
+
+
+/*
+ * printdevname() - print device name
+ */
+
+int
+printdevname(dev, rdev, f, nty)
+ dev_t *dev; /* device */
+ dev_t *rdev; /* raw device */
+ int f; /* 1 = follow with '\n' */
+ int nty; /* node type: N_BLK or N_CHR */
+{
+ struct l_dev *dp;
+/*
+ * Search device table for a full match.
+ */
+ if ((dp = lkupdev(dev, rdev, 1, 1))) {
+ if (Lf->ch < 0)
+ safestrprt(dp->name, stdout, f);
+ else {
+ safestrprt(dp->name, stdout, 0);
+ (void) printf("/%d%s", Lf->ch, f ? "\n" : "");
+ }
+ return(1);
+ }
+/*
+ * Search device table for a match without inode number and dev.
+ */
+ if ((dp = lkupdev(&DevDev, rdev, 0, 1))) {
+
+ /*
+ * A raw device match was found. Record it as a name column addition.
+ */
+ char *cp, *ttl;
+ int len;
+
+ ttl = (nty == N_BLK) ? LIKE_BLK_SPEC : LIKE_CHR_SPEC;
+ len = (int)(1 + strlen(ttl) + 1 + strlen(dp->name) + 1);
+ if (!(cp = (char *)malloc((MALLOC_S)(len + 1)))) {
+ (void) fprintf(stderr, "%s: no nma space for: (%s %s)\n",
+ Pn, ttl, dp->name);
+ Exit(1);
+ }
+ (void) snpf(cp, len + 1, "(%s %s)", ttl, dp->name);
+ (void) add_nma(cp, len);
+ (void) free((MALLOC_P *)cp);
+ return(0);
+ }
+ return(0);
+}
+
+
+/*
+ * readdev() - read device names, modes and types
+ */
+
+void
+readdev(skip)
+ int skip; /* skip device cache read if 1 */
+{
+
+#if defined(HASDCACHE)
+ int dcrd;
+#endif /* defined(HASDCACHE) */
+
+ DIR *dfp;
+ struct dirent *dp;
+ char *fp = (char *)NULL;
+ int i = 0;
+
+#if defined(HASBLKDEV)
+ int j = 0;
+#endif /* defined(HASBLKDEV) */
+
+ char *path = (char *)NULL;
+ MALLOC_S pl;
+ struct stat sb;
+
+#if AIXV>=4140
+ struct clone *c;
+ dev_t cd;
+#endif /* AIXV >=4140 */
+
+ if (Sdev)
+ return;
+
+#if defined(HASDCACHE)
+/*
+ * Read device cache, as directed.
+ */
+ if (!skip) {
+ if (DCstate == 2 || DCstate == 3) {
+ if ((dcrd = read_dcache()) == 0)
+ return;
+ }
+ } else
+ dcrd = 1;
+#endif /* defined(HASDCACHE) */
+
+#if AIXV>=4140
+/*
+ * Establish the clone major device for AIX 4.1.4 and above.
+ */
+ if (stat("/dev/clone", &sb) == 0) {
+ cd = sb.st_rdev;
+ CloneMaj = GET_MAJ_DEV(cd);
+ }
+#endif /* AIXV >=4140 */
+
+ Dstk = (char **)NULL;
+ Dstkn = Dstkx = 0;
+ (void) stkdir("/dev");
+/*
+ * Unstack the next /dev or /dev/<subdirectory> directory.
+ */
+ while (--Dstkx >= 0) {
+ if (!(dfp = opendir(Dstk[Dstkx]))) {
+
+#if defined(WARNDEVACCESS)
+ if (!Fwarn) {
+ (void) fprintf(stderr, "%s: WARNING: can't open: ", Pn);
+ safestrprt(Dstk[Dstkx], stderr, 1);
+ }
+#endif /* defined(WARNDEVACCESS) */
+
+ (void) free((FREE_P *)Dstk[Dstkx]);
+ Dstk[Dstkx] = (char *)NULL;
+ continue;
+ }
+ if (path) {
+ (void) free((FREE_P *)path);
+ path = (char *)NULL;
+ }
+ if (!(path = mkstrcat(Dstk[Dstkx], -1, "/", 1, (char *)NULL,
+ -1, &pl)))
+ {
+ (void) fprintf(stderr, "%s: no space for: ", Pn);
+ safestrprt(Dstk[Dstkx], stderr, 1);
+ Exit(1);
+ }
+ (void) free((FREE_P *)Dstk[Dstkx]);
+ Dstk[Dstkx] = (char *)NULL;
+ /*
+ * Scan the directory.
+ */
+ for (dp = readdir(dfp); dp; dp = readdir(dfp)) {
+ if (!dp->d_ino || (dp->d_name[0] == '.'))
+ continue;
+ /*
+ * Form the full path name and get its status.
+ */
+ if (fp) {
+ (void) free((FREE_P *)fp);
+ fp = (char *)NULL;
+ }
+ if (!(fp = mkstrcat(path, (int)pl, dp->d_name, dp->d_namlen,
+ (char *)NULL, -1, (MALLOC_S *)NULL))) {
+ (void) fprintf(stderr, "%s: no space for: ", Pn);
+ safestrprt(path, stderr, 0);
+ safestrprt(dp->d_name, stderr, 1);
+ Exit(1);
+ }
+
+#if defined(USE_STAT)
+ if (stat(fp, &sb) != 0)
+#else /* !defined(USE_STAT) */
+ if (lstat(fp, &sb) != 0)
+#endif /* defined(USE_STAT) */
+
+ {
+ if (errno == ENOENT) /* symbolic link to nowhere? */
+ continue;
+
+#if defined(WARNDEVACCESS)
+ if (!Fwarn) {
+ int errno_save = errno;
+
+ (void) fprintf(stderr, "%s: can't stat: ", Pn);
+ safestrprt(fp, stderr, 0);
+ (void) fprintf(stderr, ": %s\n", strerror(errno_save));
+ }
+#endif /* defined(WARNDEVACCESS) */
+
+ continue;
+ }
+ /*
+ * If it's a subdirectory, stack its name for later processing.
+ */
+ if ((sb.st_mode & S_IFMT) == S_IFDIR) {
+ (void) stkdir(fp);
+ continue;
+ }
+ if ((sb.st_mode & S_IFMT) == S_IFCHR) {
+
+ /*
+ * Save character device information.
+ */
+ if (i >= Ndev) {
+ Ndev += DEVINCR;
+ if (!Devtp)
+ Devtp = (struct l_dev *)malloc(
+ (MALLOC_S)(sizeof(struct l_dev)*Ndev));
+ else
+ Devtp = (struct l_dev *)realloc( (MALLOC_P *)Devtp,
+ (MALLOC_S)(sizeof(struct l_dev)*Ndev));
+ if (!Devtp) {
+ (void) fprintf(stderr,
+ "%s: no space for character device\n", Pn);
+ Exit(1);
+ }
+ }
+ Devtp[i].rdev = sb.st_rdev;
+ Devtp[i].inode = (INODETYPE)sb.st_ino;
+ if (!(Devtp[i].name = mkstrcpy(fp, (MALLOC_S *)NULL))) {
+ (void) fprintf(stderr, "%s: no space for: ", Pn);
+ safestrprt(fp, stderr, 1);
+ Exit(1);
+ }
+ Devtp[i].v = 0;
+ i++;
+
+#if AIXV>=4140
+ /*
+ * Save information on AIX 4.1.4 and above clone devices.
+ */
+ if (CloneMaj >= 0 && CloneMaj == GET_MAJ_DEV(sb.st_rdev)) {
+ if (!(c = (struct clone *)malloc(
+ (MALLOC_S)sizeof(struct clone))))
+ {
+ (void) fprintf(stderr,
+ "%s: no space for clone device: ", Pn);
+ safestrprt(fp, stderr, 1);
+ exit(1);
+ }
+ if (!(c->cd.name = mkstrcpy(fp, (MALLOC_S)NULL))) {
+ (void) fprintf(stderr,
+ "%s: no space for clone name: ", Pn);
+ safestrprt(fp, stderr, 1);
+ exit(1);
+ }
+ c->cd.inode = (INODETYPE)sb.st_ino;
+ c->cd.rdev = sb.st_rdev;
+ c->cd.v = 0;
+ c->next = Clone;
+ Clone = c;
+ if (ClonePtc < 0 && strcmp(path, "/dev/ptc") == 0)
+ ClonePtc = GET_MIN_DEV(sb.st_rdev);
+ }
+#endif /* AIXV >=4140 */
+
+ }
+
+#if defined(HASBLKDEV)
+ if ((sb.st_mode & S_IFMT) == S_IFBLK) {
+
+ /*
+ * Save block device information in BDevtp[].
+ */
+ if (j >= BNdev) {
+ BNdev += DEVINCR;
+ if (!BDevtp)
+ BDevtp = (struct l_dev *)malloc(
+ (MALLOC_S)(sizeof(struct l_dev)*BNdev));
+ else
+ BDevtp = (struct l_dev *)realloc(
+ (MALLOC_P *)BDevtp,
+ (MALLOC_S)(sizeof(struct l_dev)*BNdev));
+ if (!BDevtp) {
+ (void) fprintf(stderr,
+ "%s: no space for block device\n", Pn);
+ Exit(1);
+ }
+ }
+ BDevtp[j].rdev = sb.st_rdev;
+ BDevtp[j].inode = (INODETYPE)sb.st_ino;
+ BDevtp[j].name = fp;
+ fp = (char *)NULL;
+ BDevtp[j].v = 0;
+ j++;
+ }
+#endif /* defined(HASBLKDEV) */
+
+ }
+ (void) closedir(dfp);
+ }
+/*
+ * Free any allocated space.
+ */
+ if (Dstk) {
+ (void) free((FREE_P *)Dstk);
+ Dstk = (char **)NULL;
+ Dstkn = Dstkx = 0;
+ }
+ if (fp)
+ (void) free((FREE_P *)fp);
+ if (path)
+ (void) free((FREE_P *)path);
+/*
+ * Reduce the BDevtp[] (optional) and Devtp[] tables to their minimum
+ * sizes; allocate and build sort pointer lists; and sort the tables by
+ * device number.
+ */
+
+#if defined(HASBLKDEV)
+ if (BNdev) {
+ if (BNdev > j) {
+ BNdev = j;
+ BDevtp = (struct l_dev *)realloc((MALLOC_P *)BDevtp,
+ (MALLOC_S)(sizeof(struct l_dev) * BNdev));
+ }
+ if (!(BSdev = (struct l_dev **)malloc(
+ (MALLOC_S)(sizeof(struct l_dev *) * BNdev))))
+ {
+ (void) fprintf(stderr,
+ "%s: no space for block device sort pointers\n", Pn);
+ Exit(1);
+ }
+ for (j = 0; j < BNdev; j++) {
+ BSdev[j] = &BDevtp[j];
+ }
+ (void) qsort((QSORT_P *)BSdev, (size_t)BNdev,
+ (size_t)sizeof(struct l_dev *), compdev);
+ BNdev = rmdupdev(&BSdev, BNdev, "block");
+ } else {
+ if (!Fwarn)
+ (void) fprintf(stderr,
+ "%s: WARNING: no block devices found\n", Pn);
+ }
+#endif /* defined(HASBLKDEV) */
+
+ if (Ndev) {
+ if (Ndev > i) {
+ Ndev = i;
+ Devtp = (struct l_dev *)realloc((MALLOC_P *)Devtp,
+ (MALLOC_S)(sizeof(struct l_dev) * Ndev));
+ }
+ if (!(Sdev = (struct l_dev **)malloc(
+ (MALLOC_S)(sizeof(struct l_dev *) * Ndev))))
+ {
+ (void) fprintf(stderr,
+ "%s: no space for character device sort pointers\n", Pn);
+ Exit(1);
+ }
+ for (i = 0; i < Ndev; i++) {
+ Sdev[i] = &Devtp[i];
+ }
+ (void) qsort((QSORT_P *)Sdev, (size_t)Ndev,
+ (size_t)sizeof(struct l_dev *), compdev);
+ Ndev = rmdupdev(&Sdev, Ndev, "char");
+ } else {
+ (void) fprintf(stderr, "%s: no character devices found\n", Pn);
+ Exit(1);
+ }
+
+#if defined(HASDCACHE)
+/*
+ * Write device cache file, as required.
+ */
+ if (DCstate == 1 || (DCstate == 3 && dcrd))
+ write_dcache();
+#endif /* defined(HASDCACHE) */
+
+}
+
+
+#if defined(HASDCACHE)
+/*
+ * rereaddev() - reread device names, modes and types
+ */
+
+void
+rereaddev()
+{
+ (void) clr_devtab();
+
+# if defined(DCACHE_CLR)
+ (void) DCACHE_CLR();
+# endif /* defined(DCACHE_CLR) */
+
+ readdev(1);
+ DCunsafe = 0;
+}
+#endif /* defined(HASDCACHE) */
+
+
+/*
+ * rmdupdev() - remove duplicate (major/minor/inode) devices
+ */
+
+static int
+rmdupdev(dp, n, nm)
+ struct l_dev ***dp; /* device table pointers address */
+ int n; /* number of pointers */
+ char *nm; /* device table name for error message */
+{
+
+#if AIXV>=4140
+ struct clone *c, *cp;
+#endif /* AIXV>=4140 */
+
+ int i, j, k;
+ struct l_dev **p;
+
+ for (i = j = 0, p = *dp; i < n ;) {
+ for (k = i + 1; k < n; k++) {
+ if (p[i]->rdev != p[k]->rdev || p[i]->inode != p[k]->inode)
+ break;
+
+#if AIXV>=4140
+ /*
+ * See if we're deleting a duplicate clone device. If so,
+ * delete its clone table entry.
+ */
+ for (c = Clone, cp = (struct clone *)NULL;
+ c;
+ cp = c, c = c->next)
+ {
+ if (c->cd.rdev != p[k]->rdev
+ || c->cd.inode != p[k]->inode
+ || strcmp(c->cd.name, p[k]->name))
+ continue;
+ if (!cp)
+ Clone = c->next;
+ else
+ cp->next = c->next;
+ if (c->cd.name)
+ (void) free((FREE_P *)c->cd.name);
+ (void) free((FREE_P *)c);
+ break;
+ }
+#endif /* AIXV>=4140 */
+
+ }
+ if (i != j)
+ p[j] = p[i];
+ j++;
+ i = k;
+ }
+ if (n == j)
+ return(n);
+ if (!(*dp = (struct l_dev **)realloc((MALLOC_P *)*dp,
+ (MALLOC_S)(j * sizeof(struct l_dev *)))))
+ {
+ (void) fprintf(stderr, "%s: can't realloc %s device pointers\n",
+ Pn, nm);
+ Exit(1);
+ }
+ return(j);
+}
+
+
+#if defined(HASDCACHE) && AIXV>=4140
+/*
+ * rw_clone_sect() - read/write the device cache file clone section
+ */
+
+int
+rw_clone_sect(m)
+ int m; /* mode: 1 = read; 2 = write */
+{
+ char buf[MAXPATHLEN*2], *cp;
+ struct clone *c;
+ int i, len, n;
+
+ if (m == 1) {
+
+ /*
+ * Read the clone section header and validate it.
+ */
+ if (!fgets(buf, sizeof(buf), DCfs)) {
+
+bad_clone_sect:
+
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ "%s: bad clone section header in %s: ",
+ Pn, DCpath[DCpathX]);
+ safestrprt(buf, stderr, 1);
+ }
+ return(1);
+ }
+ (void) crc(buf, strlen(buf), &DCcksum);
+ len = strlen("clone section: ");
+ if (strncmp(buf, "clone section: ", len) != 0)
+ goto bad_clone_sect;
+ if ((n = atoi(&buf[len])) < 0)
+ goto bad_clone_sect;
+ /*
+ * Read the clone section lines and create the Clone list.
+ */
+ for (i = 0; i < n; i++) {
+ if (!fgets(buf, sizeof(buf), DCfs)) {
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ "%s: bad clone line in %s: ", Pn, DCpath[DCpathX]);
+ safestrprt(buf, stderr, 1);
+ }
+ return(1);
+ }
+ (void) crc(buf, strlen(buf), &DCcksum);
+ /*
+ * Allocate a clone structure.
+ */
+ if (!(c = (struct clone *)calloc(1, sizeof(struct clone)))) {
+ (void) fprintf(stderr,
+ "%s: no space for cached clone: ", Pn);
+ safestrprt(buf, stderr, 1);
+ Exit(1);
+ }
+ /*
+ * Enter the clone device number.
+ */
+ if (!(cp = x2dev(buf, &c->cd.rdev)) || *cp++ != ' ') {
+
+bad_cached_clone:
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ "%s: bad cached clone device: ", Pn);
+ safestrprt(buf, stderr, 1);
+ }
+ return(1);
+ }
+ CloneMaj = GET_MAJ_DEV(c->cd.rdev);
+ /*
+ * Enter the clone inode number.
+ */
+ for (c->cd.inode = (INODETYPE)0; *cp != ' '; cp++) {
+ if (*cp < '0' || *cp > '9')
+ goto bad_cached_clone;
+ c->cd.inode = (INODETYPE)((c->cd.inode * 10) + (*cp - '0'));
+ }
+ /*
+ * Enter the clone path name.
+ */
+ if ((len = strlen(++cp)) < 2 || *(cp + len - 1) != '\n') {
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ "%s: bad cached clone path: ", Pn);
+ safestrprt(buf, stderr, 1);
+ }
+ return(1);
+ }
+ *(cp + len - 1) = '\0';
+ if (!(c->cd.name = mkstrcpy(cp, (MALLOC_S *)NULL))) {
+ (void) fprintf(stderr,
+ "%s: no space for cached clone path: ", Pn);
+ safestrprt(buf, stderr, 1);
+ Exit(1);
+ }
+ c->cd.v = 0;
+ c->next = Clone;
+ Clone = c;
+ if (ClonePtc < 0 && strcmp(c->cd.name, "/dev/ptc") == 0)
+ ClonePtc = GET_MIN_DEV(c->cd.rdev);
+ }
+ return(0);
+ } else if (m == 2) {
+
+ /*
+ * Write the clone section header.
+ */
+ for (c = Clone, n = 0; c; c = c->next, n++)
+ ;
+ (void) snpf(buf, sizeof(buf), "clone section: %d\n", n);
+ if (wr2DCfd(buf, &DCcksum))
+ return(1);
+ /*
+ * Write the clone section lines.
+ */
+ for (c = Clone; c; c = c->next) {
+ (void) snpf(buf, sizeof(buf), "%x %ld %s\n",
+ c->cd.rdev, (long)c->cd.inode, c->cd.name);
+ if (wr2DCfd(buf, &DCcksum))
+ return(1);
+ }
+ return(0);
+ }
+/*
+ * A shouldn't-happen case: mode neither 1 nor 2.
+ */
+ (void) fprintf(stderr, "%s: internal rw_clone_sect error: %d\n",
+ Pn, m);
+ Exit(1);
+}
+#endif /* defined(HASDCACHE) && AIXV>=4140 */
+
+
+#if defined(HASDCACHE)
+/*
+ * vfy_dev() - verify a device table entry (usually when DCunsafe == 1)
+ *
+ * Note: rereads entire device table when an entry can't be verified.
+ */
+
+int
+vfy_dev(dp)
+ struct l_dev *dp; /* device table pointer */
+{
+ struct stat sb;
+
+ if (!DCunsafe || dp->v)
+ return(1);
+
+#if defined(USE_STAT)
+ if (stat(dp->name, &sb) != 0
+#else /* !defined(USE_STAT) */
+ if (lstat(dp->name, &sb) != 0
+#endif /* defined(USE_STAT) */
+
+ || dp->rdev != sb.st_rdev
+ || dp->inode != (INODETYPE)sb.st_ino) {
+ (void) rereaddev();
+ return(0);
+ }
+ dp->v = 1;
+ return(1);
+}
+#endif /* defined(HASDCACHE) */
diff --git a/dialects/aix/dfile.c b/dialects/aix/dfile.c
new file mode 100644
index 0000000..74b30c8
--- /dev/null
+++ b/dialects/aix/dfile.c
@@ -0,0 +1,600 @@
+/*
+ * dfile.c - AIX file processing functions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dfile.c,v 1.13 2005/08/08 19:46:38 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+/*
+ * Local structures
+ */
+
+struct hsfile {
+ struct sfile *s; /* the Sfile table address */
+ struct hsfile *next; /* the next hash bucket entry */
+};
+
+
+/*
+ * Local static variables
+ */
+
+static struct hsfile *HbyFdi = /* hash by file buckets */
+ (struct hsfile *)NULL;
+static int HbyFdiCt = 0; /* HbyFdi entry count */
+static struct hsfile *HbyFrd = /* hash by file raw device buckets */
+ (struct hsfile *)NULL;
+static int HbyFrdCt = 0; /* HbyFrd entry count */
+static struct hsfile *HbyFsd = /* hash by file system buckets */
+ (struct hsfile *)NULL;
+static int HbyFsdCt = 0; /* HbyFsd entry count */
+static struct hsfile *HbyMPC = /* hash by MPC file buckets */
+ (struct hsfile *)NULL;
+static int HbyMPCCt = 0; /* HbyMPC entry count */
+static struct hsfile *HbyNm = /* hash by name buckets */
+ (struct hsfile *)NULL;
+static int HbyNmCt = 0; /* HbyNm entry count */
+
+
+/*
+ * Local definitions
+ */
+
+#define SFDIHASH 4094 /* Sfile hash by (device,inode) number
+ * pair bucket count (power of 2!) */
+#define SFFSHASH 128 /* Sfile hash by file system device
+ * number bucket count (power of 2!) */
+#define SFHASHDEVINO(maj, min, ino, mod) ((int)(((int)((((int)(maj+1))*((int)((min+1))))+ino)*31415)&(mod-1)))
+ /* hash for Sfile by major device,
+ * minor device, and inode, modulo m
+ * (m must be a power of 2) */
+#define SFMPCHASH 1024 /* Sfile hash by MPC device number */
+#define SFNMHASH 4096 /* Sfile hash by name bucket count
+ (power of 2!) */
+#define SFRDHASH 1024 /* Sfile hash by raw device number
+ * bucket count (power of 2!) */
+#define SFHASHRDEVI(maj, min, rmaj, rmin, ino, mod) ((int)(((int)((((int)(maj+1))*((int)((min+1))))+((int)(rmaj+1)*(int)(rmin+1))+ino)*31415)&(mod-1)))
+ /* hash for Sfile by major device,
+ * minor device, major raw device,
+ * minor raw device, and inode, modulo
+ * mod (mod must be a power of 2) */
+
+
+/*
+ * hashSfile() - hash Sfile entries for use in is_file_named() searches
+ */
+
+void
+hashSfile()
+{
+ static int hs = 0;
+ int i;
+ struct sfile *s;
+ struct hsfile *sh, *sn;
+/*
+ * Do nothing if there are no file search arguments cached or if the
+ * hashes have already been constructed.
+ */
+ if (!Sfile || hs)
+ return;
+/*
+ * Allocate hash buckets by (device,inode), file system device, MPC device,
+ * and file name.
+ */
+ if (!(HbyFdi = (struct hsfile *)calloc((MALLOC_S)SFDIHASH,
+ sizeof(struct hsfile))))
+ {
+ (void) fprintf(stderr,
+ "%s: can't allocate space for %d (dev,ino) hash buckets\n",
+ Pn, SFDIHASH);
+ Exit(1);
+ }
+ if (!(HbyFrd = (struct hsfile *)calloc((MALLOC_S)SFRDHASH,
+ sizeof(struct hsfile))))
+ {
+ (void) fprintf(stderr,
+ "%s: can't allocate space for %d rdev hash buckets\n",
+ Pn, SFRDHASH);
+ Exit(1);
+ }
+ if (!(HbyFsd = (struct hsfile *)calloc((MALLOC_S)SFFSHASH,
+ sizeof(struct hsfile))))
+ {
+ (void) fprintf(stderr,
+ "%s: can't allocate space for %d file sys hash buckets\n",
+ Pn, SFFSHASH);
+ Exit(1);
+ }
+ if (!(HbyMPC = (struct hsfile *)calloc((MALLOC_S)SFMPCHASH,
+ sizeof(struct hsfile))))
+ {
+ (void) fprintf(stderr,
+ "%s: can't allocate space for %d MPC file hash buckets\n",
+ Pn, SFMPCHASH);
+ Exit(1);
+ }
+ if (!(HbyNm = (struct hsfile *)calloc((MALLOC_S)SFNMHASH,
+ sizeof(struct hsfile))))
+ {
+ (void) fprintf(stderr,
+ "%s: can't allocate space for %d name hash buckets\n",
+ Pn, SFNMHASH);
+ Exit(1);
+ }
+ hs++;
+/*
+ * Scan the Sfile chain, building file, file system, MPC file, and file
+ * name hash bucket chains.
+ */
+ for (s = Sfile; s; s = s->next) {
+ for (i = 0; i < 4; i++) {
+ if (i == 0) {
+ if (!s->aname)
+ continue;
+ sh = &HbyNm[hashbyname(s->aname, SFNMHASH)];
+ HbyNmCt++;
+ } else if (i == 1) {
+ if (s->type) {
+ sh = &HbyFdi[SFHASHDEVINO(GET_MAJ_DEV(s->dev),
+ GET_MIN_DEV(s->dev),
+ s->i,
+ SFDIHASH)];
+ HbyFdiCt++;
+ } else {
+ sh = &HbyFsd[SFHASHDEVINO(GET_MAJ_DEV(s->dev),
+ GET_MIN_DEV(s->dev),
+ 0,
+ SFFSHASH)];
+ HbyFsdCt++;
+ }
+ } else if (i == 2) {
+ if (s->type && (s->ch < 0) && (s->mode == S_IFCHR))
+ {
+ sh = &HbyMPC[SFHASHDEVINO(GET_MAJ_DEV(s->dev),
+ GET_MIN_DEV(s->dev),
+ 0,
+ SFMPCHASH)];
+ HbyMPCCt++;
+ } else
+ continue;
+ } else if (i == 3) {
+ if (s->type
+ && (((s->mode == S_IFCHR) && (s->ch < 0))
+ || ((s->mode == S_IFBLK))))
+ {
+ sh = &HbyFrd[SFHASHRDEVI(GET_MAJ_DEV(s->dev),
+ GET_MIN_DEV(s->dev),
+ GET_MAJ_DEV(s->rdev),
+ GET_MIN_DEV(s->rdev),
+ s->i,
+ SFRDHASH)];
+ HbyFrdCt++;
+ } else
+ continue;
+ }
+ if (!sh->s) {
+ sh->s = s;
+ sh->next = (struct hsfile *)NULL;
+ continue;
+ } else {
+ if (!(sn = (struct hsfile *)malloc(
+ (MALLOC_S)sizeof(struct hsfile))))
+ {
+ (void) fprintf(stderr,
+ "%s: can't allocate hsfile bucket for: %s\n",
+ Pn, s->aname);
+ Exit(1);
+ }
+ sn->s = s;
+ sn->next = sh->next;
+ sh->next = sn;
+ }
+ }
+ }
+}
+
+
+/*
+ * is_file_named() - is file named?
+ */
+
+int
+is_file_named(p, ty, ch, ic)
+ char *p; /* path name; NULL = search by device
+ * and inode (from *Lf) */
+ enum vtype ty; /* vnode type */
+ chan_t ch; /* gnode channel */
+ int ic; /* is clone file (4.1.4 and above) */
+{
+ int dmaj, dmin, maj, min, rmaj, rmin;
+ static int dsplit = 0;
+ char *ep;
+ int f = 0;
+ struct sfile *s;
+ struct hsfile *sh;
+ size_t sz;
+/*
+ * Split the device numbers into their major and minor numbers.
+ *
+ * THis is necessitated by 64 bit AIX architectures, which store two different
+ * types of device numbers in 64 bit dev_t's. The two types can't be compared
+ * directly, but must be compared by extracting their major and minor numbers
+ * and comparing them.
+ */
+ readdev(0);
+ if (!dsplit) {
+ dmaj = GET_MAJ_DEV(DevDev);
+ dmin = GET_MIN_DEV(DevDev);
+ dsplit = 1;
+ }
+ if (Lf->dev_def) {
+ maj = GET_MAJ_DEV(Lf->dev);
+ min = GET_MIN_DEV(Lf->dev);
+ }
+ if (Lf->rdev_def) {
+ rmaj = GET_MAJ_DEV(Lf->rdev);
+ rmin = GET_MIN_DEV(Lf->rdev);
+ }
+
+#if AIXV>=4140
+/*
+ * Check for a clone match.
+ */
+ if (ic
+ && HbyFdiCt
+ && CloneMaj >= 0
+ && (Lf->dev_def && (maj = dmaj) && (min == dmin))
+ && Lf->rdev_def
+ && (Lf->inp_ty == 1 || Lf->inp_ty == 3))
+ {
+ for (sh=&HbyFdi[SFHASHDEVINO(CloneMaj, rmaj, Lf->inode, SFDIHASH)];
+ sh;
+ sh = sh->next)
+ {
+ if ((s = sh->s)
+ && (GET_MAJ_DEV(s->rdev) == CloneMaj)
+ && (GET_MIN_DEV(s->rdev) == rmaj)
+ && (s->i == Lf->inode))
+ {
+ f = 3;
+ break;
+ }
+ }
+ }
+#endif /* AIXV>=4140 */
+
+/*
+ * Check for a path name match, as requested.
+ */
+ if (!f && p && HbyNmCt) {
+ for (sh = &HbyNm[hashbyname(p, SFNMHASH)]; sh; sh = sh->next) {
+ if ((s = sh->s) && strcmp(p, s->aname) == 0) {
+ f = 2;
+ break;
+ }
+ }
+ }
+/*
+ * Check for a regular AIX multiplexed file, matching the channel if
+ * it was supplied by the caller.
+ */
+ if (!f && HbyMPCCt && ty == VMPC
+ && (Lf->dev_def && (maj == dmaj) && (min == dmin))
+ && Lf->rdev_def)
+ {
+ for (sh = &HbyMPC[SFHASHDEVINO(rmaj, rmin, 0, SFMPCHASH)];
+ sh;
+ sh = sh->next)
+ {
+ if ((s = sh->s)
+ && (GET_MAJ_DEV(s->dev) == rmaj)
+ && (GET_MIN_DEV(s->dev) == rmin)
+ && (s->ch < 0 || ch == s->ch)) {
+ f = 1;
+ break;
+ }
+ }
+ }
+/*
+ * Check for a regular file.
+ */
+ if (!f && HbyFdiCt && Lf->dev_def
+ && (Lf->inp_ty == 1 || Lf->inp_ty == 3))
+ {
+ for (sh = &HbyFdi[SFHASHDEVINO(maj, min, Lf->inode, SFDIHASH)];
+ sh;
+ sh = sh->next)
+ {
+ if ((s = sh->s)
+ && (maj == GET_MAJ_DEV(s->dev))
+ && (min == GET_MIN_DEV(s->dev))
+ && (Lf->inode == s->i))
+ {
+ f = 1;
+ break;
+ }
+ }
+ }
+/*
+ * Check for a file system.
+ */
+ if (!f && HbyFsdCt && Lf->dev_def) {
+ for (sh = &HbyFsd[SFHASHDEVINO(maj, min, 0, SFFSHASH)];
+ sh;
+ sh = sh->next)
+ {
+ if ((s = sh->s)
+ && (maj == GET_MAJ_DEV(s->dev))
+ && (min == GET_MIN_DEV(s->dev))
+ ) {
+ f = 1;
+ break;
+ }
+ }
+ }
+/*
+ * Check for a character or block device file.
+ */
+ if (!f && HbyFrdCt
+ && ((ty == VCHR) || (ty == VBLK))
+ && (Lf->dev_def && (maj == dmaj) && (min == dmin))
+ && Lf->rdev_def
+ && (Lf->inp_ty == 1 || Lf->inp_ty == 3))
+ {
+ for (sh = &HbyFrd[SFHASHRDEVI(maj, min, rmaj, rmin,
+ Lf->inode, SFRDHASH)];
+ sh;
+ sh = sh->next)
+ {
+ if ((s = sh->s)
+ && (GET_MAJ_DEV(s->rdev) == rmaj)
+ && (GET_MIN_DEV(s->rdev) == rmin)
+ && (((ty == VCHR) && (s->mode == S_IFCHR) && (s->ch < 0))
+ || ((ty == VBLK) && (s->mode == S_IFBLK))))
+ {
+ f = 1;
+ break;
+ }
+ }
+ }
+/*
+ * Convert the name if a match occurred.
+ */
+ if (f) {
+ if (f == 2) {
+ (void) snpf(Namech, Namechl, "%s", p);
+
+#if AIXV>=4140
+ } else if (f == 3 && ClonePtc >= 0 && (maj == ClonePtc)) {
+ (void) snpf(Namech, Namechl, "%s/%d", s->name, min);
+
+#endif /* AIXV>=4140 */
+
+ } else if (s->type) {
+
+ /*
+ * If the search argument isn't a file system, propagate it
+ * to Namech[]; otherwise, let printname() compose the name.
+ */
+ (void) snpf(Namech, Namechl, "%s", s->name);
+ if (ty == VMPC && s->ch < 0) {
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "/%d", ch);
+ }
+ if (s->devnm) {
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, " (%s)", s->devnm);
+ }
+ }
+ s->f = 1;
+ return(1);
+ }
+ return(0);
+}
+
+
+/*
+ * print_dev() - print device
+ */
+
+char *
+print_dev(lf, dev)
+ struct lfile *lf; /* file whose device to be printed */
+ dev_t *dev; /* pointer to device to be printed */
+
+{
+ static char buf[128];
+ int maj = GET_MAJ_DEV(*dev);
+ int min = GET_MIN_DEV(*dev);
+
+#if AIXV>=3200
+ if (*dev & SDEV_REMOTE) {
+ (void) snpf(buf, sizeof(buf), "NFS,%d", (min & ~SDEV_REMOTE));
+ return(buf);
+ }
+#endif /* AIXV>=3200 */
+
+ (void) snpf(buf, sizeof(buf), "%d,%d", maj, min);
+ return(buf);
+}
+
+
+/*
+ * readvfs() - read vfs structure
+ */
+
+struct l_vfs *
+readvfs(vn)
+ struct vnode *vn; /* vnode */
+{
+ struct gfs g;
+ void *mp;
+ char *s1, *s2;
+ uint ul;
+ struct vfs v;
+ struct vmount *vm;
+ struct l_vfs *vp;
+
+
+ if (!vn->v_vfsp)
+ return((struct l_vfs *)NULL);
+ for (vp = Lvfs; vp; vp = vp->next) {
+ if ((KA_T)vn->v_vfsp == vp->addr)
+ return(vp);
+ }
+ if (!(vp = (struct l_vfs *)malloc((MALLOC_S)sizeof(struct l_vfs)))) {
+ (void) fprintf(stderr, "%s: PID %d, no space for vfs\n",
+ Pn, Lp->pid);
+ Exit(1);
+ }
+ vp->dir = (char *)NULL;
+ vp->fsname = (char *)NULL;
+/*
+ * Read the vfs structure.
+ */
+ if (kread((KA_T)vn->v_vfsp, (char *)&v, sizeof(v))) {
+
+vfs_exit:
+ (void) free((FREE_P *)vp);
+ return((struct l_vfs *)NULL);
+ }
+/*
+ * Locate AIX mount information.
+ */
+ if (!v.vfs_gfs || kread((KA_T)v.vfs_gfs, (char *)&g, sizeof(g)))
+ goto vfs_exit;
+ if (!v.vfs_mdata
+ || kread((KA_T)((char *)v.vfs_mdata
+ + offsetof(struct vmount, vmt_length)),
+ (char *)&ul, sizeof(ul)))
+ goto vfs_exit;
+ if (!(mp = (void *)malloc((MALLOC_S)ul))) {
+ (void) fprintf(stderr, "%s: PID %d, no space for mount data\n",
+ Pn, Lp->pid);
+ Exit(1);
+ }
+ if (kread((KA_T)v.vfs_mdata, (char *)mp, (int)ul)) {
+ (void) free((FREE_P *)mp);
+ goto vfs_exit;
+ }
+ vm = (struct vmount *)mp;
+ vp->vmt_flags = vm->vmt_flags;
+ vp->vmt_gfstype = vm->vmt_gfstype;
+
+#if AIXV>=3200
+ if ((vp->vmt_flags & MNT_REMOTE)
+
+# if defined(HAS_SANFS) && defined(MNT_SANFS)
+ && (vp->vmt_gfstype != MNT_SANFS)
+# endif /* defined(HAS_SANFS) && defined(MNT_SANFS) */
+
+ ) {
+ vp->dev = 0x80000000 | vm->vmt_vfsnumber;
+# if AIXA>=1
+ vp->dev |= 0x8000000000000000;
+# endif /* AIXA>=1 */
+ } else
+#endif /* AIXV>=3200 */
+
+#if defined(HAS_AFS)
+ if (vm->vmt_gfstype == MNT_AFS)
+ vp->dev = AFSDEV;
+ else
+#endif /* defined(HAS_AFS) */
+
+#if AIXA>1
+ if (vm->vmt_gfstype == MNT_PROCFS) {
+
+ /*
+ * !!!DEBUG!!! !!!DEBUG!!! !!!DEBUG!!! !!!DEBUG!!! !!!DEBUG!!!
+ *
+ * The following *hack* is required to make the vmount structure's
+ * device number match what stat(2) errnoneously returns in ia64
+ * AIX >= 5.
+ *
+ * REMOVE THIS CODE WHEN STAT(2) IS FIXED!!!
+ */
+ vp->dev = (dev_t)(vm->vmt_fsid.fsid_dev & 0x7fffffffffffffff);
+ /*
+ * !!!DEBUG!!! !!!DEBUG!!! !!!DEBUG!!! !!!DEBUG!!! !!!DEBUG!!!
+ */
+
+ }
+ else
+#endif /* AIXA>1 */
+
+ vp->dev = (dev_t)vm->vmt_fsid.fsid_dev;
+ if ((s1 = vmt2dataptr(vm, VMT_STUB))) {
+ if (!(vp->dir = mkstrcpy(s1, (MALLOC_S *)NULL))) {
+
+readvfs_aix1:
+ (void) fprintf(stderr, "%s: PID %d, readvfs, no space\n",
+ Pn, Lp->pid);
+ Exit(1);
+ }
+ } else
+ vp->dir = (char *)NULL;
+ s1 = vmt2dataptr(vm, VMT_HOST);
+ if (!(s2 = vmt2dataptr(vm, VMT_OBJECT)) || *s1 == '\0')
+ s2 = g.gfs_name;
+ if (!s1 && !s2)
+ vp->fsname = (char *)NULL;
+ else {
+ if (vm->vmt_flags & MNT_REMOTE) {
+ if (!(vp->fsname = mkstrcat(s1 ? s1 : "",
+ -1,
+ (s1 && *s1) ? ":" : "",
+ -1, s2, -1,
+ (MALLOC_S *)NULL)))
+ goto readvfs_aix1;
+ } else {
+ if (!(vp->fsname = mkstrcpy(s2, (MALLOC_S *)NULL)))
+ goto readvfs_aix1;
+ }
+ }
+ (void) free((FREE_P *)mp);
+ vp->next = Lvfs;
+ vp->addr = (KA_T)vn->v_vfsp;
+
+#if defined(HAS_AFS)
+ if (!AFSVfsp && vm->vmt_gfstype == MNT_AFS)
+ AFSVfsp = (KA_T)vn->v_vfsp;
+#endif /* defined(HAS_AFS) */
+
+ Lvfs = vp;
+ return(vp);
+}
diff --git a/dialects/aix/dlsof.h b/dialects/aix/dlsof.h
new file mode 100644
index 0000000..287b4c5
--- /dev/null
+++ b/dialects/aix/dlsof.h
@@ -0,0 +1,442 @@
+/*
+ * dlsof.h - AIX header file for lsof
+ */
+
+
+/*
+ * Copyright 1994 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.
+ */
+
+
+/*
+ * $Id: dlsof.h,v 1.32 2006/03/27 23:09:21 abe Exp $
+ */
+
+
+#if !defined(AIX_LSOF_H)
+#define AIX_LSOF_H 1
+
+/*
+ * AIXA stands for AIX architecure. It is given these values in the
+ * aix stanza of the lsof Configure script:
+ *
+ * 0 The AIX version is < 5, or the AIX architecture is power and
+ * the kernel bit size is 32.
+ *
+ * 1 The AIX version is >= 5, the AIX architecture is Power, and
+ * the kernel bit size is 64.
+ *
+ * 2 The AIX version is > 5 and the architecture is IA64.
+ */
+
+# if AIXA>1
+#include <nlist.h>
+# endif /* AIXA>1 */
+
+#include <stdlib.h>
+#include <string.h>
+#include <dirent.h>
+#include <setjmp.h>
+#include <unistd.h>
+
+# if !defined(_KERNEL)
+#define _KERNEL 1
+# endif /* !defined(_KERNEL) */
+
+#include <sys/vnode.h>
+#include <sys/file.h>
+#include <procinfo.h> /* <procinfo.h> #includes <sys/user.h> */
+#define p_pid pi_pid
+#define p_pgid pi_pgrp
+#define p_ppid pi_ppid
+
+# if AIXV<4300
+#define p_stat pi_stat
+# else /* AIXV>=4300 */
+#define p_stat pi_state
+#include <sys/systemcfg.h>
+# endif /* AIXV<4300 */
+
+#define p_uid pi_uid
+#undef sleep
+#undef _KERNEL
+
+# if AIXA>1
+#define _NET_NET_MALLOC /* to keep <sys/mbuf.h> from #include'ing
+ * <sys/ppda.h>, which is missing from
+ * ia64 AIX 5L */
+# endif /* AIXA>1 */
+
+#include <sys/mbuf.h>
+#include <sys/mntctl.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+
+# if AIXV>=4140
+#include <sys/stream.h>
+# endif /* AIXV>=4140 */
+
+#include <sys/sysmacros.h>
+#include <sys/un.h>
+#include <sys/unpcb.h>
+
+# if defined(HASKERNIDCK) && AIXV>=5000
+#include <sys/utsname.h>
+# endif /* defined(HASKERNIDCK) && AIXV>=5000 */
+
+#include <netinet/in.h>
+#include <net/route.h>
+#include <net/raw_cb.h>
+
+# if AIXV>=4100
+#include <netinet/ip.h>
+# endif /* AIXV>=4100 */
+
+#include <netinet/in_pcb.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+#include <netinet/tcp_fsm.h>
+#include <netinet/tcp_timer.h>
+#include <netinet/tcp_var.h>
+#include <sys/vattr.h>
+#include <sys/statfs.h>
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+
+# if defined(HAS_AFS)
+#define __XDR_INCLUDE__
+# endif /* defined(HAS_AFS) */
+
+#include <sys/vfs.h>
+#include <sys/vmount.h>
+
+# if defined(HAS_SANFS) && !defined(MNT_SANFS)
+#define MNT_SANFS 20
+# endif /* defined(HAS_SANFS) && !defined(MNT_SANFS) */
+
+# if AIXV>=4100
+# if AIXV>=4110
+#undef u
+#undef u_comm
+#undef u_cdir
+#undef u_rdir
+#undef u_maxofile
+#undef u_ufd
+#undef u_loader
+# endif /* AIXV>=4110 */
+
+#define u_comm U_comm
+#define u_cdir U_cdir
+#define u_rdir U_rdir
+#define u_maxofile U_maxofile
+#define u_ufd U_ufd
+#define u_loader U_loader
+# endif /* AIXV>=4100 */
+
+# if AIXV>=3200
+#include <sys/specnode.h>
+# endif /* AIXV>=3200 */
+
+/*
+ * AIX doesn't supply cdrnode.h.
+ */
+
+struct cdrnode {
+ caddr_t f1[4];
+ struct gnode f2;
+ dev_t f3;
+ ino_t cn_inumber; /* inode number */
+ caddr_t f4;
+ cnt_t f5[2];
+ u_short f6;
+ uint f7[2];
+ uchar f8[3];
+ off_t cn_size; /* size of file in bytes */
+};
+
+# if defined(HAS_AFS)
+
+/*
+ * Avoid typdef conflicts in <afs/stds.h>.
+ */
+
+# if defined(HASINT16TYPE)
+#define int16 AFS_int16
+# endif /* defined(HASINT16TYPE */
+# if defined(HASUINT16TYPE)
+#define u_int16 AFS_u_int16
+# endif /* defined(HASUINT16TYPE */
+# if defined(HASINT32TYPE)
+#define int32 AFS_int32
+# endif /* defined(HASINT32TYPE) */
+
+#include <afs/stds.h>
+#include <afs/param.h>
+#include <afs/afsint.h>
+#include <afs/vldbint.h>
+# endif /* defined(HAS_AFS) */
+
+
+/*
+ * Miscellaneous definitions.
+ */
+
+# if defined(HAS_AFS)
+#define AFSAPATHDEF "/usr/vice/etc/dkload/???"
+#define AFSDEV 1 /* AFS "fake" device number */
+
+# if !defined(MNT_AFS)
+#define MNT_AFS AFS_MOUNT_AFS
+# endif /* !defined(MNT_AFS) */
+# endif /* defined(HAS_AFS) */
+
+#define COMP_P const void
+#define DEVINCR 1024 /* device table malloc() increment */
+
+# if AIXV<4200
+typedef off_t KA_T;
+# else /* AIXV>=4200 */
+# if AIXA<1
+typedef unsigned int KA_T;
+# else /* AIXA>=1 */
+typedef u_longlong_t KA_T;
+#define GET_MAJ_DEV(d) (ISDEVNO64(d) ? major64(d) : major(d & ~SDEV_REMOTE))
+#define GET_MIN_DEV(d) (ISDEVNO64(d) ? (minor64(d) & ~SDEV_REMOTE) : minor(d))
+#define KA_T_FMT_X "%#llx"
+# endif /* AIXA<1 */
+# endif /* AIXV<4200 */
+
+#define KMEM "/dev/kmem"
+
+# if defined(HASSTAT64)
+#define fstat fstat64
+#define lstat lstat64
+#define stat stat64
+# endif /* defined(HASSTAT64) */
+
+#define MALLOC_P char
+#define FREE_P MALLOC_P
+#define MALLOC_S size_t
+#define MAXSYSCMDL MAXCOMLEN /* max system command name length */
+#define N_UNIX "/unix"
+#define QSORT_P void
+#define READLEN_T size_t
+#define STRNCPY_L size_t
+
+# if AIXV>=4200
+#define SZOFFTYPE unsigned long long
+ /* size and offset type definition */
+#define SZOFFPSPEC "ll" /* SZOFFTYPE print specification modifier */
+# endif /* AIXV>=4200 */
+
+#define U_SIZE sizeof(struct user)
+
+
+/*
+ * Name list (Nl[]) indexes
+ */
+
+#define X_UADDR 0
+#define X_NL_NUM 1
+
+
+/*
+ * Definition for ckfa.c
+ */
+
+#define CKFA_MPXCHAN 1
+
+
+/*
+ * Definitions for dvch.c
+ */
+
+# if AIXV>=4140
+#define DCACHE_CLONE rw_clone_sect /* clone function for read_dcache */
+#define DCACHE_CLR clr_sect /* function to clear clone and
+ * pseudo caches when reading the
+ * device cache file fails */
+# endif /* AIXV>=4140 */
+
+
+/*
+ * Definitions for enter_dir()
+ */
+
+#define DIRTYPE dirent
+#define HASDNAMLEN 1
+
+
+# if defined(HAS_AFS)
+/*
+ * AFS name list (AFSnl[]) indexes
+ */
+
+#define X_AFS_FID 0
+#define X_AFS_VOL 1
+#define X_AFSNL_NUM 2
+# endif /* defined(HAS_AFS) */
+
+
+# if AIXV>=4140
+/*
+ * Local clone information
+ */
+
+struct clone {
+ struct l_dev cd; /* device, inode, name, verify status */
+ struct clone *next; /* next entry */
+};
+extern struct clone *Clone;
+extern int CloneMaj;
+extern int ClonePtc;
+#endif /* AIXV>=4140 */
+
+
+/*
+ * Local inode information
+ */
+
+struct l_ino {
+ dev_t dev; /* device */
+ long nlink; /* link count */
+ INODETYPE number; /* inode number */
+ SZOFFTYPE size; /* file size */
+ unsigned char dev_def; /* link count is defined */
+ unsigned char nlink_def; /* link count is defined */
+ unsigned char number_def; /* number is defined */
+ unsigned char size_def; /* size is defined */
+};
+
+
+/*
+ * Local vfs information
+ */
+
+struct l_vfs {
+ KA_T addr; /* kernel address */
+ dev_t dev; /* device */
+ char *dir; /* mounted directory */
+ char *fsname; /* file system name */
+ int vmt_flags; /* vmount flags */
+ int vmt_gfstype; /* vmount gfs type */
+ struct l_vfs *next; /* forward link */
+};
+extern struct l_vfs *Lvfs;
+
+
+/*
+ * Local mount information
+ */
+
+struct mounts {
+ char *dir; /* directory (mounted on) */
+ char *fsname; /* file system
+ * (symbolic links unresolved) */
+ char *fsnmres; /* file system
+ * (symbolic links resolved) */
+ dev_t dev; /* directory st_dev */
+ dev_t rdev; /* directory st_rdev */
+ INODETYPE inode; /* directory st_ino */
+ u_short mode; /* directory st_mode */
+ u_short fs_mode; /* file system st_mode */
+
+# if defined(HASFSTYPE)
+ int fstype; /* fs type */
+# endif /* defined(HASFSTYPE) */
+
+ struct mounts *next; /* forward link */
+};
+extern struct mounts *Mtab;
+
+
+/*
+ * Search file information
+ */
+
+struct sfile {
+ char *aname; /* file name argument */
+ char *name; /* file name (after readlink()) */
+ char *devnm; /* device name (optional) */
+ dev_t dev; /* device */
+ dev_t rdev; /* raw device */
+ chan_t ch; /* channel (last path component,
+ * (if numeric) */
+ u_short mode; /* S_IFMT mode bits from stat() */
+ int type; /* file type: 0 = file system
+ * 1 = regular file */
+ INODETYPE i; /* inode number */
+ int f; /* file found flag */
+ struct sfile *next; /* forward link */
+};
+
+
+/*
+ * Miscellaneous external definitions
+ */
+
+# if defined(HAS_AFS)
+extern struct nlist AFSnl[]; /* AFS kernel symbol name list table */
+
+# if defined(HASAOPT)
+extern char *AFSApath; /* alternate AFS name list path (from -a) */
+# endif /* defined(HASAOPT) */
+
+extern KA_T AFSVfsp; /* AFS struct vfs kernel pointer */
+# endif /* defined(HAS_AFS) */
+
+extern int Kd;
+extern int Km;
+extern struct nlist Nl[];
+
+# if defined(TCPSTATES) && AIXV<=3250
+/*
+ * For AIX 3.2.5 and below, there is no header file with the definition
+ * of tcpstates[], needed by ptti.c's print_tcptpi() function.
+ */
+
+static char *tcpstates[] = {
+ "CLOSED", "LISTEN", "SYN_SENT", "SYN_RCVD",
+ "ESTABLISHED", "CLOSE_WAIT", "FIN_WAIT_1", "CLOSING",
+ "LAST_ACK", "FIN_WAIT_2", "TIME_WAIT"
+};
+# endif /* defined(TCPSTATES) && AIXV<=3250 */
+
+
+# if AIXA>1
+/*
+ * This AIX 5 or above ia64 hack prevents the loader from linking lsof's
+ * kread() in preference to the kread() that read() uses. The very existence
+ * of a system kread() is an unwarrranted invasion of user name space!
+ */
+
+#define kread lsof_kread /* avoid conflict with the kread()
+ * in libc.so */
+# endif /* AIXA>1 */
+
+#endif /* AIX_LSOF_H */
diff --git a/dialects/aix/dmnt.c b/dialects/aix/dmnt.c
new file mode 100644
index 0000000..ef1d61c
--- /dev/null
+++ b/dialects/aix/dmnt.c
@@ -0,0 +1,302 @@
+/*
+ * dmnt.c - AIX mount support functions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dmnt.c,v 1.13 2005/08/08 19:46:38 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+/*
+ * Local static definitions
+ */
+
+static struct mounts *Lmi = (struct mounts *)NULL; /* local mount info */
+static int Lmist = 0; /* Lmi status */
+
+
+/*
+ * readmnt() - read mount table
+ */
+
+struct mounts *
+readmnt()
+{
+ char *dir, *fs, *h, *ln, *ty;
+ char *dn = (char *)NULL;
+ struct mounts *mtp;
+ int nm;
+ struct stat sb;
+ MALLOC_S sz;
+ struct vmount *v;
+ struct vmount *vt = (struct vmount *)NULL;
+
+ if (Lmi || Lmist)
+ return(Lmi);
+/*
+ * Read the table of vmount structures.
+ */
+ for (sz = sizeof(struct vmount);;) {
+ if (!(vt = (struct vmount *)malloc(sz))) {
+ (void) fprintf(stderr, "%s: no space for vmount table\n", Pn);
+ return(0);
+ }
+ nm = mntctl(MCTL_QUERY, sz, (unsigned char *)vt);
+ if (nm > 0) {
+ if (vt->vmt_revision != VMT_REVISION) {
+ (void) fprintf(stderr,
+ "%s: stale file system, rev %d != %d\n",
+ Pn, vt->vmt_revision, VMT_REVISION);
+ return(0);
+ }
+ break;
+ }
+ if (nm == 0) {
+ sz = (unsigned)vt->vmt_revision;
+ (void) free((FREE_P *)vt);
+ } else {
+ (void) fprintf(stderr, "%s: mntctl error: %s\n",
+ Pn, strerror(errno));
+ return(0);
+ }
+ }
+/*
+ * Scan the vmount structures and build Lmi.
+ */
+ for (v = vt; nm--; v = (struct vmount *)((char *)v + v->vmt_length)) {
+ dir = (char *)vmt2dataptr(v, VMT_STUB);
+ fs = (char *)vmt2dataptr(v, VMT_OBJECT);
+ h = (char *)vmt2dataptr(v, VMT_HOST);
+ if (statsafely(dir, &sb)) {
+ if (!Fwarn) {
+
+ /*
+ * Issue stat() failure warning.
+ */
+ switch(v->vmt_gfstype) {
+
+#if defined(HAS_AFS)
+ case MNT_AFS:
+ ty = "afs";
+ break;
+#endif /* defined(HAS_AFS) */
+
+#if defined(MNT_AIX) && defined(MNT_J2) && MNT_AIX==MNT_J2
+ case MNT_AIX:
+ ty = "jfs2";
+ break;
+#else /* !defined(MNT_AIX) || !defined(MNT_J2) || MNT_AIX!=MNT_J2 */
+# if defined(MNT_AIX)
+ case MNT_AIX:
+ ty = "oaix";
+ break;
+# endif /* defined(MNT_AIX) */
+# if defined(MNT_J2)
+ case MNT_J2:
+ ty = "jfs2";
+ break;
+# endif /* defined(MNT_J2) */
+#endif /* defined(MNT_AIX) && defined(MNT_H2) && MNT_AIX==MNT_J2 */
+
+ case MNT_CDROM:
+ ty = "cdrom";
+ break;
+ case MNT_JFS:
+ ty = "jfs";
+ break;
+ case MNT_NFS:
+ ty = "nfs";
+ break;
+
+#if defined(MNT_NFS3)
+ case MNT_NFS3:
+ ty = "nfs3";
+ break;
+#endif /* defined(MNT_NFS3) */
+
+#if defined(HASPROCFS)
+ case MNT_PROCFS:
+ ty = HASPROCFS;
+ break;
+#endif /* defined(HASPROCFS) */
+
+#if defined(MNT_SANFS)
+ case MNT_SANFS:
+ ty = "sanfs";
+ break;
+#endif /* defined(MNT_SANFS) */
+
+ default:
+ ty = "unknown";
+ }
+ (void) fprintf(stderr,
+ "%s: WARNING: can't stat() %s file system %s\n",
+ Pn, ty, dir);
+ (void) fprintf(stderr,
+ " Output information may be incomplete.\n");
+ }
+ /*
+ * Assemble alternate device number and mode flags.
+ */
+ (void) bzero((char *)&sb, sizeof(sb));
+ if (v->vmt_flags & MNT_REMOTE) {
+
+#if AIXA<2
+ sb.st_dev = (dev_t)(SDEV_REMOTE | v->vmt_vfsnumber);
+#else /* AIXA>=2 */
+ sb.st_dev = (dev_t)(SDEV_REMOTE | (SDEV_REMOTE << 32)
+ | v->vmt_vfsnumber);
+#endif /* AIXA<2 */
+
+ } else {
+
+#if defined(HAS_AFS)
+ if (v->vmt_gfstype == MNT_AFS)
+ sb.st_dev = AFSDEV;
+ else
+#endif /* defined(HAS_AFS) */
+
+#if AIXA>=2 && defined(HASPROCFS)
+ if (v->vmt_gfstype == MNT_PROCFS) {
+
+ /*
+ * !!!DEBUG!!! !!!DEBUG!!! !!!DEBUG!!! !!!DEBUG!!!
+ *
+ * The following *hack* is required to make the vmount
+ * structure's device number match what stat(2)
+ * errnoneously returns on ia64 AIX 5L.
+ *
+ * REMOVE THIS CODE WHEN STAT(2) IS FIXED!!!
+ */
+ sb.st_dev = (dev_t)(v->vmt_fsid.val[0]
+ & 0x7fffffffffffffff);
+ /*
+ * !!!DEBUG!!! !!!DEBUG!!! !!!DEBUG!!! !!!DEBUG!!!
+ */
+
+ }
+ else
+#endif /* AIXA>=2 && defined(HASPROCFS) */
+
+ sb.st_dev = (dev_t)v->vmt_fsid.val[0];
+ }
+ if (!Fwarn)
+ (void) fprintf(stderr,
+ " assuming \"dev=%#lx\" from mount table\n",
+ sb.st_dev);
+ sb.st_mode = S_IFDIR | 0777;
+ }
+ /*
+ * Allocate space for the directory (mounted on) and resolve
+ * any symbolic links.
+ */
+ if (dn)
+ (void) free((FREE_P *)dn);
+ if (!(dn = mkstrcpy(dir, (MALLOC_S *)NULL))) {
+
+no_space_for_mount:
+
+ (void) fprintf(stderr, "%s: no space for mount at %s (%s)\n",
+ Pn, fs, dir);
+ Exit(1);
+ }
+ if (!(ln = Readlink(dn))) {
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ " Output information may be incomplete.\n");
+ }
+ continue;
+ }
+ if (ln != dn) {
+ (void) free((FREE_P *)dn);
+ dn = ln;
+ }
+ if (*dn != '/')
+ continue;
+ /*
+ * Allocate a local mounts structure and fill the directory information.
+ */
+ if (!(mtp = (struct mounts *)malloc(
+ (MALLOC_S)sizeof(struct mounts))))
+ goto no_space_for_mount;
+ mtp->dir = dn;
+ dn = (char *)NULL;
+ mtp->dev = sb.st_dev;
+ mtp->inode = (INODETYPE)sb.st_ino;
+ mtp->mode = sb.st_mode;
+ mtp->rdev = sb.st_rdev;
+
+#if defined(HASFSTYPE)
+ mtp->fstype = sb.st_vfstype;
+#endif /* defined(HASFSTYPE) */
+
+ mtp->next = Lmi;
+ /*
+ * Form the file system (mounted-on) device name. Resolve any
+ * symbolic links. Allocate space for the result and store it in
+ * the local mounts structure.
+ */
+ if (h && (v->vmt_flags & MNT_REMOTE)) {
+ if (!(dn = mkstrcat(h, -1, *h ? ":" : "", 1, fs, -1,
+ (MALLOC_S *)NULL)))
+ goto no_space_for_mount;
+ } else {
+ if (!(dn = mkstrcpy(fs, (MALLOC_S *)NULL)))
+ goto no_space_for_mount;
+ }
+ mtp->fsname = dn;
+ ln = Readlink(dn);
+ dn = (char *)NULL;
+ /*
+ * Stat the file system (mounted-on) device name to get its modes.
+ * Set the modes to zero if the stat fails. Add file system
+ * (mounted-on) device information to the local mountsstructure.
+ */
+ if (!ln || statsafely(ln, &sb))
+ sb.st_mode = 0;
+ mtp->fsnmres = ln;
+ mtp->fs_mode = sb.st_mode;
+ Lmi = mtp;
+ }
+/*
+ * Clean up and return local mount info table address.
+ */
+ if (dn)
+ (void) free((FREE_P *)dn);
+ if (vt)
+ (void) free((FREE_P *)vt);
+ Lmist = 1;
+ return(Lmi);
+}
diff --git a/dialects/aix/dnode.c b/dialects/aix/dnode.c
new file mode 100644
index 0000000..10a07bb
--- /dev/null
+++ b/dialects/aix/dnode.c
@@ -0,0 +1,1307 @@
+/*
+ * dnode.c - AIX node reading functions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dnode.c,v 1.25 2008/10/21 16:14:18 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+/*
+ * Local definitions
+ */
+
+#if AIXV<5000
+#define FL_NEXT next
+#else /* AIXV>=5000 */
+#define FL_NEXT fl_next
+# if !defined(ISVDEV)
+#define ISVDEV(t) (((t)==VBLK)||((t)==VCHR)||((t)==VFIFO)||((t)==VMPC))
+# endif /* !defined(ISVDEV) */
+#endif /* AIXV<5000 */
+
+
+# if defined(HAS_NFS)
+# if AIXV<4210
+#include <nfs/rnode.h>
+# else /* AIXV>=4210 */
+# if AIXA<2
+/*
+ * Private rnode struct definitions for AIX 4.2.1 and above
+ *
+ * The rnode struct IBM ships in <nfs/rnode.h> doesn't match the one
+ * the kernel uses. The kernel's rnode struct definition comes from
+ * <oncplus/nfs/rnode.h>, a header file IBM does not ship with AIX.
+ *
+ * The rnode64 struct is for AIX above 4.3.3 whose "width" is 64.
+ * (See dnode.c for the method used to determine width.)
+ */
+
+struct rnode {
+ caddr_t r_d1[11]; /* dummies; links? */
+ struct vnode r_vnode; /* vnode for remote file */
+ struct gnode r_gnode; /* gnode for remote file */
+ caddr_t r_d2[29]; /* dummies; rnode elements? */
+ off_t r_size; /* client's view of file size (long)*/
+ struct vattr r_attr; /* cached vnode attributes */
+};
+
+# if AIXV>4330
+struct rnode64 {
+
+# if AIXV<5200
+ caddr_t r_d1[11]; /* dummies; links? */
+# else /* AIXV>=5200 */
+# if AIXV<5300
+ caddr_t r_d1[12]; /* dummies; links? */
+# else /* AIXV>=5300 */
+ caddr_t r_d1[7]; /* dummies; links? */
+# endif /* AIXV<5300 */
+# endif /* AIXV<5200 */
+
+ struct vnode r_vnode; /* vnode for remote file */
+ struct gnode r_gnode; /* gnode for remote file */
+
+# if AIXV<5300
+ caddr_t r_d2[15]; /* dummies; rnode elements? */
+# else /* AIXV>=5300 */
+ caddr_t r_d2[11]; /* dummies; rnode elements? */
+# endif /* AIXV<5300 */
+
+ off_t r_size; /* client's view of file size (long)*/
+ struct vattr r_attr; /* cached vnode attributes */
+};
+# endif /* AIXV>4330 */
+# else /* AIXA>=2 */
+struct rnode {
+ KA_T d1[7]; /* dummies */
+ struct vnode r_vnode; /* vnode for remote file */
+ struct gnode r_gnode; /* gnode for remote file */
+ KA_T d2[19]; /* dummies */
+ off_t r_size; /* client's view of file size (long)*/
+ struct vattr r_attr; /* cached vnode attributes */
+};
+# endif /* AIXA<2 */
+# endif /* AIXV<4210 */
+# endif /* defined(HAS_NFS) */
+
+
+/*
+ * isglocked() - is a gnode locked
+ */
+
+char
+isglocked(ga)
+ struct gnode *ga; /* local gnode address */
+{
+
+ struct filock *cfp, f, *ffp;
+ int l;
+
+ if (!(ffp = ga->gn_filocks))
+ return(' ');
+ cfp = ffp;
+
+#if AIXV>=4140
+ do {
+#endif /* AIXV>=4140 */
+
+ if (kread((KA_T)cfp, (char *)&f, sizeof(f)))
+ return(' ');
+
+#if AIXV>=4140
+ if (f.set.l_sysid || f.set.l_pid != (pid_t)Lp->pid)
+ continue;
+#endif /* AIXV>=4140 */
+
+ if (f.set.l_whence == 0 && f.set.l_start == 0
+
+#if AIXV>=4200
+ && f.set.l_end == 0x7fffffffffffffffLL
+#else /* AIXV<4200 */
+ && f.set.l_end == 0x7fffffff
+#endif /* AIXV>=4200 */
+
+ )
+ l = 1;
+ else
+ l = 0;
+ switch (f.set.l_type & (F_RDLCK | F_WRLCK)) {
+
+ case F_RDLCK:
+ return((l) ? 'R' : 'r');
+ case F_WRLCK:
+ return((l) ? 'W' : 'w');
+ case (F_RDLCK + F_WRLCK):
+ return('u');
+ }
+ return(' ');
+
+#if AIXV>=4140
+ } while ((cfp = f.FL_NEXT) && cfp != ffp);
+ return(' ');
+#endif /* AIXV>=4140 */
+
+}
+
+
+/*
+ * process_node() - process vnode
+ */
+
+void
+process_node(va)
+ KA_T va; /* vnode kernel space address */
+{
+ struct cdrnode c;
+ dev_t dev, rdev;
+ int devs = 0;
+ struct gnode g;
+ struct l_ino i;
+ int ic = 0;
+ int ins = 0;
+ struct vfs *la = NULL;
+ int rdevs = 0;
+ size_t sz;
+ char tbuf[32], *ty;
+ enum vtype type;
+ struct l_vfs *vfs;
+ static struct vnode *v = (struct vnode *)NULL;
+
+#if AIXV>=3200
+ struct devnode dn;
+ struct gnode pg;
+ struct specnode sn;
+ struct fifonode f;
+#endif /* AIXV>=3200 */
+
+#if defined(HAS_AFS)
+ static int afs = 0; /* AFS test status: -1 = no AFS
+ * 0 = not tested
+ * 1 = AFS present */
+ struct afsnode an;
+#endif /* defined(HAS_AFS) */
+
+#if defined(HAS_NFS)
+ struct vattr nfs_attr;
+ int nfss = 0;
+ static struct rnode r;
+ static char *rp = (char *)&r;
+ static int rsz = sizeof(r);
+
+# if AIXV>4330 && AIXA<2
+ static struct rnode64 r64;
+# endif /* AIXV>4330 && AIXA<2 */
+
+# if AIXA<2
+ static int width = -1;
+# else /* AIXA>=2 */
+ static width = 64;
+# endif /* AIXA<2 */
+#endif /* defined(HAS_NFS) */
+
+#if defined(HAS_SANFS)
+ struct sanfs_node { /* DEBUG */
+
+ /*
+ * This is a DEBUG version of the SANFS node structure. When IBM makes
+ * the SANFS header files available in /usr/include, this definition
+ * will be removed.
+ */
+ u_long san_d1[20]; /* DEBUG */
+ struct gnode san_gnode; /* DEBUG */
+ u_long san_d2[128]; /* DEBUG */
+ } san;
+ int sans = 0;
+#endif /* defined(HAS_SANFS) */
+
+#if AIXV>=4140
+ struct clone *cl;
+ KA_T ka;
+ struct module_info mi;
+ int ml, nx;
+ char mn[32];
+ struct queue q;
+ struct qinit qi;
+ KA_T qp, xp;
+ int ql;
+ struct sth_s { /* stream head */
+ KA_T *dummy; /* dummy */
+ KA_T *sth_wq; /* write queue */
+ } sh;
+ struct xticb { /* XTI control block */
+ int d1;
+ long d2;
+ int d3;
+ struct socket *xti_so; /* socket pointer */
+ } xt;
+#endif /* AIXV>=4140 */
+
+
+/*
+ * Read the vnode.
+ */
+ if (!va) {
+ enter_nm("no vnode address");
+ return;
+ }
+ if (!v) {
+
+ /*
+ * Allocate space for the vnode or AFS vcache structure.
+ */
+
+#if defined(HAS_AFS)
+ v = alloc_vcache();
+#else /* !defined(HAS_AFS) */
+ v = (struct vnode *)malloc((MALLOC_S)sizeof(struct vnode));
+#endif /* defined(HAS_AFS) */
+
+ if (!v) {
+ (void) fprintf(stderr, "%s: can't allocate %s space\n", Pn,
+
+#if defined(HAS_AFS)
+ "vcache"
+#else /* !defined(HAS_AFS) */
+ "vnode"
+#endif /* defined(HAS_AFS) */
+
+ );
+ Exit(1);
+ }
+ }
+/*
+ * Read the vnode.
+ */
+ if (readvnode(va, v)) {
+ enter_nm(Namech);
+ return;
+ }
+
+#if defined(HASFSTRUCT)
+ Lf->fsv |= FSV_NI;
+ Lf->fna = va;
+#endif /* defined(HASFSTRUCT) */
+
+/*
+ * Read the gnode.
+ */
+ if (!v->v_gnode || readgnode((KA_T)v->v_gnode, &g)) {
+ if (Selinet) {
+ Lf->sf = SELEXCLF;
+ return;
+ }
+ (void) snpf(Namech, Namechl, "vnode at %s has no gnode\n",
+ print_kptr(va, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+
+#if AIXV>=3200
+
+/*
+ * Under AIX 3.2 and above, if the vnode type is ISVDEV, then there is a
+ * special node and a fifonode or devnode. Behind them are the "real"
+ * gnode, inode and vnode.
+ */
+ if (ISVDEV(g.gn_type)) {
+ switch (g.gn_type) {
+ case VBLK:
+ Ntype = N_BLK;
+ break;
+ case VCHR:
+ Ntype = N_CHR;
+ break;
+ case VFIFO:
+ Ntype = N_FIFO;
+ break;
+ case VMPC:
+ Ntype = N_MPC;
+ break;
+ default:
+ (void) snpf(Namech, Namechl, "vnode at %s: unknown ISVDEV(%#x)",
+ print_kptr(va, (char *)NULL, 0), g.gn_type);
+ enter_nm(Namech);
+ return;
+ }
+ /*
+ * Read the special node.
+ */
+ if (!g.gn_data || kread((KA_T)g.gn_data, (char *)&sn, sizeof(sn))) {
+ if (Selinet) {
+ Lf->sf = SELEXCLF;
+ return;
+ }
+ (void) snpf(Namech, Namechl,
+ "vnode at %s: can't read specnode (%s)",
+ print_kptr(va, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)g.gn_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ /*
+ * Read the PFS gnode and its inode and vnode.
+ */
+ if (sn.sn_pfsgnode) {
+ if (Selinet) {
+ Lf->sf = SELEXCLF;
+ return;
+ }
+ if (readgnode((KA_T)sn.sn_pfsgnode, &g)) {
+ (void) snpf(Namech, Namechl,
+ "vnode at %s: can't read pfsgnode (%s)",
+ print_kptr(va, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)sn.sn_pfsgnode, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ if (!g.gn_data || readlino(&g, &i)) {
+ (void) snpf(Namech, Namechl,
+ "pfsgnode at %s: can't read inode (%s)",
+ print_kptr((KA_T)sn.sn_pfsgnode, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)g.gn_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ ins = 1;
+ if (!g.gn_vnode || readvnode((KA_T)g.gn_vnode, v)) {
+ (void) snpf(Namech, Namechl,
+ "pfsgnode at %s: can't read vnode (%s)",
+ print_kptr((KA_T)sn.sn_pfsgnode, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)g.gn_vnode, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ } else {
+ (void) zeromem((char *)&i, sizeof(i));
+
+#if AIXV>=4140
+ /*
+ * See if this is a clone device, connected to a stream.
+ *
+ * the clone major device number must be known;
+ * the specnode must have a devnode pointer;
+ * and the devnode must have a stream head pointer.
+ */
+ if (CloneMaj >= 0
+ && sn.sn_devnode
+ && kread((KA_T)sn.sn_devnode, (char *)&dn, sizeof(dn)) == 0
+ && (ka = (KA_T)dn.dv_pdata))
+ {
+
+# if defined(HASDCACHE)
+
+process_clone_again:
+
+# endif /* defined(HASDCACHE) */
+
+ for (cl = Clone; cl; cl = cl->next) {
+ if (GET_MAJ_DEV(g.gn_rdev) == GET_MIN_DEV(cl->cd.rdev))
+ {
+
+# if defined(HASDCACHE)
+ if (DCunsafe && !cl->cd.v && !vfy_dev(&cl->cd))
+ goto process_clone_again;
+# endif /* defined(HASDCACHE) */
+
+ /*
+ * Identify this file as a clone. Save the clone
+ * device inode number as the file's inode number.
+ */
+ ic = 1;
+ Lf->inode = cl->cd.inode;
+ Lf->inp_ty = 1;
+ if (ClonePtc >= 0
+ && GET_MAJ_DEV(g.gn_rdev) == ClonePtc) {
+ if (Selinet) {
+ Lf->sf = SELEXCLF;
+ return;
+ }
+ /*
+ * If this is a /dev/ptc stream, enter the device
+ * name and the channel.
+ */
+ (void) snpf(Namech, Namechl, "%s/%d",
+ cl->cd.name, (int)GET_MIN_DEV(g.gn_rdev));
+ break;
+ }
+ /*
+ * If this isn't a /dev/ptc stream, collect the names
+ * of the modules on the stream. Ignore the stream
+ * head and look for an "xtiso" module. Limit the
+ * module depth to 25.
+ */
+ (void) snpf(Namech, Namechl, "STR:%s", cl->cd.name);
+ nx = (int) strlen(Namech);
+ if (!kread(ka, (char *)&sh, sizeof(sh)))
+ qp = (KA_T)sh.sth_wq;
+ else
+ qp = (KA_T)NULL;
+ for (mn[sizeof(mn) - 1] = '\0', ql = 0;
+ qp && (ql < 25);
+ ql++, qp = (KA_T)q.q_next)
+ {
+
+ /*
+ * Read the queue structure. If it can't be read,
+ * end module name collection.
+ *
+ * The queue structure should lead to a qinfo
+ * structure, and the qinfo structure should lead
+ * to a module_info structure, where the module
+ * name should be found. If there's no queue
+ * structure.
+ *
+ * If the qinfo or module_info structures can't be
+ * read, skip to the next queue structure.
+ */
+ if (kread(qp, (char *)&q, sizeof(q)))
+ break;
+ if (!(ka = (KA_T)q.q_qinfo)
+ || kread(ka, (char *)&qi, sizeof(qi)))
+ continue;
+ if (!(ka = (KA_T)qi.qi_minfo)
+ || kread(ka, (char *)&mi, sizeof(mi)))
+ continue;
+ if (!(ka = (KA_T)mi.mi_idname)
+ || kread(ka, mn, sizeof(mn) - 1)
+ || !(ml = (int) strlen(mn))
+ || !strcmp(mn, "sth"))
+ continue;
+ if (!strcmp(mn, "xtiso")
+ && (xp = (KA_T)q.q_ptr)
+ && !kread(xp, (char *)&xt, sizeof(xt))
+ && (ka = (KA_T)xt.xti_so)) {
+
+ /*
+ * The xtiso module's private queue pointer
+ * leads to an xticb with a non-NULL socket
+ * pointer. Process the stream as a socket.
+ */
+ Namech[0] = '\0';
+ Lf->inp_ty = 0;
+ (void) process_socket(ka);
+ return;
+ }
+ /*
+ * Save the module name in Mamech[] as a "->"
+ * prefixed chain, beginning with "STR:<device>".
+ */
+ if ((nx + ml + 2) > (Namechl - 1))
+ continue;
+ (void) snpf(&Namech[nx], Namechl, "->%s", mn);
+ nx += (ml + 2);
+ }
+ break;
+ }
+ }
+ }
+#endif /* AIXV>=4140 */
+
+ if (Selinet) {
+ Lf->sf = SELEXCLF;
+ return;
+ }
+ }
+ /*
+ * If it's a FIFO, read its fifonode.
+ */
+ if (Ntype == N_FIFO) {
+ if (!sn.sn_fifonode ||readfifonode((KA_T)sn.sn_fifonode, &f)) {
+ (void) snpf(Namech, Namechl,
+ "vnode at %s: can't read fifonode (%s)",
+ print_kptr(va, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)sn.sn_fifonode, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ /*
+ * Otherwise, read the devnode and its gnode.
+ */
+ } else {
+ if (!sn.sn_devnode
+ || kread((KA_T)sn.sn_devnode,(char *)&dn,sizeof(dn))) {
+ (void) snpf(Namech, Namechl,
+ "vnode at %s: can't read devnode (%s)",
+ print_kptr(va, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)sn.sn_devnode, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ g = dn.dv_gnode;
+ }
+ }
+#endif /* AIXV>=3200 */
+
+/*
+ * Read the AIX virtual file system structure.
+ */
+ if (Ntype != N_AFS && g.gn_rdev == NODEVICE) {
+ vfs = (struct l_vfs *)NULL;
+ enter_dev_ch(print_kptr(va, (char *)NULL, 0));
+ } else {
+ if (!(vfs = readvfs(v))) {
+ (void) snpf(Namech, Namechl, "can't read vfs for %s at %s",
+ print_kptr(va, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)v->v_vfsp, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ }
+/*
+ * Set special node types: NFS, PROC or SANFS.
+ */
+
+#if defined(MNT_REMOTE)
+ if (vfs && vfs->vmt_flags & MNT_REMOTE) {
+ switch(vfs->vmt_gfstype) {
+
+# if defined(HAS_NFS)
+ case MNT_NFS:
+
+# if defined(MNT_NFS3)
+ case MNT_NFS3:
+# endif /* defined(MNT_NFS3) */
+
+# if defined(MNT_NFS4)
+ case MNT_NFS4:
+# endif /* defined(MNT_NFS4) */
+
+# if defined(HAS_AFS)
+ if (!AFSVfsp || (KA_T)v->v_vfsp != AFSVfsp)
+# endif /* defined(HAS_AFS) && defined(HAS_NFS) */
+
+ Ntype = N_NFS;
+# endif /* defined(HAS_NFS) */
+ break;
+
+# if defined(HAS_SANFS) && defined(MNT_SANFS)
+ case MNT_SANFS:
+ Ntype = N_SANFS;
+ break;
+# endif /* defined(HAS_SANFS) && defined(MNT_SANFS) */
+
+ }
+ }
+#endif /* defined(MNT_REMOTE) */
+
+#if defined(HASPROCFS)
+ if (vfs && (vfs->vmt_gfstype == MNT_PROCFS))
+ Ntype = N_PROC;
+#endif /* defined(HASPROCFS) */
+
+/*
+ * Get the lock status.
+ */
+ Lf->lock = isglocked(&g);
+ switch (Ntype) {
+
+#if defined(HAS_NFS)
+/*
+ * Read an NFS rnode.
+ */
+ case N_NFS:
+
+# if AIXA<2
+ if (width == -1) {
+
+ /*
+ * Establish the architecture's bit width and set NFS rnode
+ * access parameters accordingly.
+ */
+
+# if AIXV<=4330
+ width = 32;
+# else /* AIXV>4330 */
+ if (__KERNEL_64()) {
+ width = 64;
+ rp = (char *)&r64;
+ rsz = sizeof(r64);
+ } else if (__KERNEL_32()) {
+ width = 32;
+ } else {
+ if (!Fwarn)
+ (void) fprintf(stderr,
+ "%s: WARNING: unknown kernel bit size\n", Pn);
+ width = -2;
+ }
+# endif /* AIXV<-4330 */
+
+ }
+# endif /* AIXA<2 */
+
+ if (width > 0) {
+ if (!g.gn_data || kread((KA_T)g.gn_data, rp, rsz)) {
+ (void) snpf(Namech, Namechl,
+ "remote gnode at %s has no rnode",
+ print_kptr((KA_T)v->v_gnode, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+
+# if AIXV<=4330 || AIXA>=2
+ nfs_attr = r.r_attr;
+ nfss = 1;
+# else /* AIXV>4330 && AIXA<2 */
+ switch (width) {
+ case 32:
+ nfs_attr = r.r_attr;
+ nfss = 1;
+ break;
+ case 64:
+ nfs_attr = r64.r_attr;
+ nfss = 1;
+ break;
+ }
+# endif /* AIXV<=4330 || AIXA>=2 */
+
+ }
+ break;
+#endif /* defined(HAS_NFS) */
+
+#if defined(HAS_SANFS)
+/*
+ * Read SANFS node and associated structures.
+ */
+ case N_SANFS:
+ if (!g.gn_data
+ || kread((KA_T)g.gn_data, &san, sizeof(san))
+ ) {
+ (void) snpf(Namech, Namechl, "gnode at %s has no SANFS node",
+ print_kptr((KA_T)v->v_gnode, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ /*
+ * DEBUG: this code is insufficient. It can't be completed until IBM
+ * makes the SANFS header files available in /usr/include. There are
+ * apparently two node structures following the SANFS node and file
+ * attributes (size, etc.) are in the second structure.
+ */
+ sans = 1;
+ break;
+#endif /* defined(HAS_SANFS) */
+
+/*
+ * Read N_REGLR nodes.
+ */
+ case N_REGLR:
+ if (vfs && vfs->vmt_gfstype == MNT_CDROM) {
+
+ /*
+ * Read a CD-ROM cdrnode.
+ */
+ if (!g.gn_data || readcdrnode((KA_T)g.gn_data, &c)) {
+ (void) snpf(Namech, Namechl, "gnode at %s has no cdrnode",
+ print_kptr((KA_T)v->v_gnode, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ (void) zeromem((char *)&i, sizeof(i));
+ i.number = (INODETYPE)c.cn_inumber;
+ i.size = (off_t)c.cn_size;
+ i.number_def = i.size_def = 1;
+ /*
+ * Otherwise, read the inode.
+ */
+
+ } else if (g.gn_data) {
+ if (readlino(&g, &i)) {
+ (void) snpf(Namech, Namechl,
+ "gnode at %s can't read inode: %s",
+ print_kptr((KA_T)v->v_gnode, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)g.gn_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ ins = 1;
+ }
+
+#if defined(HAS_AFS)
+ else {
+
+ /*
+ * See if this is an AFS node.
+ */
+ if (AFSVfsp && (KA_T)v->v_vfsp == AFSVfsp)
+ Ntype = N_AFS;
+ else if (v->v_vfsp) {
+ switch (afs) {
+ case -1:
+ break;
+ case 0:
+ if (!hasAFS(v)) {
+ afs = 1;
+ break;
+ }
+ afs = 1;
+ Ntype = N_AFS;
+ break;
+ case 1:
+ if ((KA_T)v->v_vfsp == AFSVfsp)
+ Ntype = N_AFS;
+ }
+ }
+ /*
+ * If this is an AFS node, read the afsnode.
+ */
+ if (Ntype == N_AFS) {
+ if (readafsnode(va, v, &an))
+ return;
+ } else {
+ (void) snpf(Namech, Namechl, "gnode at %s has no inode",
+ print_kptr((KA_T)v->v_gnode, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ }
+#else /* !defined(HAS_AFS) */
+
+ else {
+ (void) snpf(Namech, Namechl, "gnode at %s has no inode",
+ print_kptr((KA_T)v->v_gnode, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+#endif /* defined(HAS_AFS) */
+
+ }
+/*
+ * Get device and type for printing.
+ */
+
+#if defined(HAS_NFS)
+ if (Ntype == N_NFS) {
+ if (vfs) {
+ dev = vfs->dev;
+ devs = 1;
+ }
+ } else
+#endif /* defined(HAS_NFS) */
+
+#if defined(HAS_AFS)
+ if (Ntype == N_AFS) {
+ dev = an.dev;
+ devs = 1;
+ } else
+#endif /* defined(HAS_AFS) */
+
+#if defined(HASPROCFS)
+ if (Ntype == N_PROC) {
+
+/* WARNING!!! WARNING!!! The following hack should be removed ASAP!!! */
+ dev = vfs ? (vfs->dev & 0x7fffffffffffffff) : 0;
+/* WARNING!!! WARNING!!! The above hack should be removed ASAP!!! */
+
+ devs = 1;
+ }
+ else
+#endif /* defined(HASPROCFS) */
+
+#if defined(HAS_SANFS)
+ if ((Ntype == N_SANFS) && vfs) {
+ dev = vfs->dev;
+ devs = 1;
+ }
+ else
+#endif /* defined(HAS_SANFS) */
+
+ {
+ if (vfs) {
+ dev = vfs->dev;
+ devs = 1;
+ }
+ rdev = g.gn_rdev;
+ rdevs = 1;
+ }
+
+#if AIXV>=3200
+ if (Ntype == N_MPC)
+ type = VMPC;
+ else
+#endif /* AIXV>=3200 */
+
+ type = g.gn_type;
+/*
+ * Obtain the inode number.
+ */
+ switch (Ntype) {
+
+#if defined(HAS_AFS)
+ case N_AFS:
+ if (an.ino_st) {
+ Lf->inode = (INODETYPE)an.inode;
+ Lf->inp_ty = 1;
+ }
+ break;
+#endif /* defined(HAS_AFS) */
+
+#if defined(HAS_NFS)
+ case N_NFS:
+ if (nfss) {
+ Lf->inode = (INODETYPE)nfs_attr.va_serialno;
+ Lf->inp_ty = 1;
+ }
+ break;
+#endif /* defined(HAS_NFS) */
+
+#if defined(HAS_SANFS)
+ case N_SANFS:
+ if (sans) {
+
+ /*
+ * DEBUG: this code is insufficient. It can't be completed until
+ * IBM makes the SANFS header files available in /usr/include.
+ */
+ /* Lf->inode = ??? DEBUG */
+ Lf->inp_ty = 1;
+ }
+ break;
+#endif /* defined(HAS_SANFS) */
+
+# if AIXV>=3200
+ case N_BLK:
+ case N_CHR:
+ case N_FIFO:
+ case N_MPC:
+# endif /* AIXV>=3200 */
+
+ case N_REGLR:
+ if (ins) {
+ Lf->inode = (INODETYPE)i.number;
+ Lf->inp_ty = i.number_def;
+ }
+ }
+/*
+ * Obtain the file size.
+ */
+ if (Foffset)
+ Lf->off_def = 1;
+ else {
+ switch (Ntype) {
+
+#if defined(HAS_AFS)
+ case N_AFS:
+ Lf->sz = (SZOFFTYPE)an.size;
+ Lf->sz_def = 1;
+ break;
+#endif /* defined(HAS_AFS) */
+
+#if AIXV>=3200
+ case N_FIFO:
+ Lf->sz = (SZOFFTYPE)f.ff_size;
+ Lf->sz_def = 1;
+ break;
+#endif /* AIXV>=3200 */
+
+#if defined(HAS_NFS)
+ case N_NFS:
+ if (nfss) {
+ Lf->sz = (SZOFFTYPE)nfs_attr.va_size;
+ Lf->sz_def = 1;
+ }
+ break;
+#endif /* defined(HAS_NFS) */
+
+#if defined(HAS_SANFS)
+ case N_SANFS:
+ if (sans) {
+
+ /*
+ * DEBUG: this code is insufficient. It can't be completed
+ * until IBM makes the SANFS header files available in
+ * /usr/include.
+ */
+ /* Lf->sz = (SZOFFTYPE)??? DEBUG */
+ Lf->sz_def = 1;
+ }
+ break;
+#endif /* defined(HAS_SANFS) */
+
+#if AIXV>=3200
+ case N_BLK:
+ if (!Fsize)
+ Lf->off_def = 1;
+ break;
+ case N_CHR:
+ case N_MPC:
+ if (!Fsize)
+ Lf->off_def = 1;
+ break;
+#endif /* AIXV>=3200 */
+
+ case N_REGLR:
+ if (type == VREG || type == VDIR) {
+ if (ins) {
+ Lf->sz = (SZOFFTYPE)i.size;
+ Lf->sz_def = i.size_def;
+ }
+ } else if (((type == VBLK) || (type == VCHR) || (type == VMPC))
+ && !Fsize)
+ Lf->off_def = 1;
+ break;
+ }
+ }
+/*
+ * Record link count.
+ */
+ if (Fnlink) {
+ switch(Ntype) {
+
+#if defined(HAS_AFS)
+ case N_AFS:
+ Lf->nlink = an.nlink;
+ Lf->nlink_def = an.nlink_st;
+ break;
+#endif /* defined(HAS_AFS) */
+
+#if defined(HAS_NFS)
+ case N_NFS:
+ if (nfss) {
+ Lf->nlink = (long)nfs_attr.va_nlink;
+ Lf->nlink_def = 1;
+ }
+ break;
+#endif /* defined(HAS_NFS) */
+
+#if defined(HAS_SANFS)
+ case N_SANFS:
+ if (sans) {
+
+ /*
+ * DEBUG: this code is insufficient. It can't be completed
+ * until IBM makes the SANFS header files available in
+ * /usr/include.
+ */
+ /* Lf->nlink = (long)??? DEBUG */
+ Lf->nlink_def = 1;
+ }
+ break;
+#endif /* defined(HAS_SANFS) */
+
+#if AIXV>=3200
+ case N_BLK:
+ case N_CHR:
+ case N_FIFO:
+ case N_MPC:
+#endif /* AIXV>=3200 */
+
+ case N_REGLR:
+ if (ins) {
+ Lf->nlink = (long)i.nlink;
+ Lf->nlink_def = i.nlink_def;
+ }
+ break;
+ }
+ if (Nlink && Lf->nlink_def && (Lf->nlink < Nlink))
+ Lf->sf |= SELNLINK;
+ }
+
+#if defined(HAS_NFS)
+/*
+ * Record an NFS file selection.
+ */
+ if (Ntype == N_NFS && Fnfs)
+ Lf->sf |= SELNFS;
+#endif /* defined(HAS_NFS) */
+
+/*
+ * Save the file system names.
+ */
+ if (vfs) {
+ Lf->fsdir = vfs->dir;
+ Lf->fsdev = vfs->fsname;
+ }
+/*
+ * Save the device numbers and their states.
+ *
+ * Format the vnode type.
+ */
+ switch (type) {
+
+ case VNON:
+ ty ="VNON";
+ Lf->dev = dev;
+ Lf->dev_def = devs;
+ Lf->rdev = rdev;
+ Lf->rdev_def = rdevs;
+ break;
+ case VREG:
+ case VDIR:
+ ty = (type == VREG) ? "VREG" : "VDIR";
+ Lf->dev = dev;
+ Lf->dev_def = devs;
+ Lf->rdev = rdev;
+ Lf->rdev_def = rdevs;
+ break;
+ case VBLK:
+ ty = "VBLK";
+ Lf->dev = dev;
+ Lf->dev_def = devs;
+ Lf->rdev = rdev;
+ Lf->rdev_def = rdevs;
+ Ntype = N_BLK;
+ break;
+ case VCHR:
+ ty = "VCHR";
+ Lf->dev = dev;
+ Lf->dev_def = devs;
+ Lf->rdev = rdev;
+ Lf->rdev_def = rdevs;
+ Ntype = N_CHR;
+ break;
+ case VLNK:
+ ty = "VLNK";
+ Lf->dev = dev;
+ Lf->dev_def = devs;
+ Lf->rdev = rdev;
+ Lf->rdev_def = rdevs;
+ break;
+
+#if defined(VSOCK)
+ case VSOCK:
+ ty = "SOCK";
+ Lf->dev = dev;
+ Lf->dev_def = devs;
+ Lf->rdev = rdev;
+ Lf->rdev_def = rdevs;
+ break;
+#endif
+
+ case VBAD:
+ ty = "VBAD";
+ Lf->dev = dev;
+ Lf->dev_def = devs;
+ Lf->rdev = rdev;
+ Lf->rdev_def = rdevs;
+ break;
+ case VFIFO:
+ if (!Lf->dev_ch || Lf->dev_ch[0] == '\0') {
+ Lf->dev = dev;
+ Lf->dev_def = devs;
+ Lf->rdev = rdev;
+ Lf->rdev_def = rdevs;
+ }
+ ty = "FIFO";
+ break;
+ case VMPC:
+ Lf->rdev = g.gn_rdev;
+ Lf->rdev_def = 1;
+ if (vfs) {
+ Lf->dev = vfs->dev;
+ Lf->dev_def = 1;
+ }
+ Lf->ch = g.gn_chan;
+
+#if AIXV<3200
+ Lf->inp_ty = 0;
+#endif /* AIXV<3200 */
+
+ Ntype = N_CHR;
+ ty = "VMPC";
+ break;
+ default:
+ Lf->dev = dev;
+ Lf->dev_def = devs;
+ Lf->rdev = rdev;
+ Lf->rdev_def = rdevs;
+ (void) snpf(Lf->type, sizeof(Lf->type), "%04o", (type & 0xfff));
+ ty = (char *)NULL;
+ }
+ if (ty)
+ (void) snpf(Lf->type, sizeof(Lf->type), "%s", ty);
+ Lf->ntype = Ntype;
+
+#if defined(HASBLKDEV)
+/*
+ * If this is a VBLK file and it's missing an inode number, try to
+ * supply one.
+ */
+ if ((Lf->inp_ty == 0) && (type == VBLK))
+ find_bl_ino();
+#endif /* defined(HASBLKDEV) */
+
+/*
+ * If this is a VCHR file and it's missing an inode number, try to
+ * supply one.
+ */
+ if ((Lf->inp_ty == 0) && (type == VCHR))
+ find_ch_ino();
+/*
+ * Test for specified file.
+ */
+ if (Sfile && is_file_named(NULL, type, g.gn_chan, ic))
+ Lf->sf |= SELNM;
+/*
+ * Enter name characters.
+ */
+ if (Namech[0])
+ enter_nm(Namech);
+}
+
+
+#if defined(HASPRIVFILETYPE)
+/*
+ * process_shmt() -- process shared memory transport file
+ */
+
+void
+process_shmt(sa)
+ KA_T sa; /* shared memory transport node struct
+ * address ??? */
+{
+ struct shmtnode { /* shared memory transport node
+ * struct ??? */
+
+ struct shmtnode *peer; /* peer shmtnode struct */
+ caddr_t d1[2]; /* dummy to fill space */
+ int sz; /* buffer size */
+ caddr_t d2[3]; /* dyummy to fill space */
+ int free; /* free bytes in buffer */
+ caddr_t d3[17]; /* dummy to fill space */
+ pid_t pid; /* process ID */
+ } mn, pn;
+/*
+ * Ignore this file if only Internet files are selected.
+ */
+ if (Selinet) {
+ Lf->sf |= SELEXCLF;
+ return;
+ }
+/*
+ * Set type to " SMT" and put shmtnode structure address in device column.
+ */
+ (void) snpf(Lf->type, sizeof(Lf->type), " SMT");
+ if (!sa || kread((KA_T)sa, (char *)&mn, sizeof(mn))) {
+ (void) snpf(Namech, Namechl, "can't read shmtnode: %s",
+ print_kptr(sa, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ enter_dev_ch(print_kptr(sa, (char *)NULL, 0));
+/*
+ * If offset display has been requested or if buffer size less free bytes is
+ * negative, enable offset display. Otherwise set the file size as buffer
+ * size less free bytes.
+ */
+ if (Foffset || mn.free > mn.sz)
+ Lf->off_def = 1;
+ else {
+ Lf->sz = (SZOFFTYPE)(mn.sz - mn.free);
+ Lf->sz_def = 1;
+ }
+/*
+ * If there is a peer, read its shmtnode structure.
+ */
+ if (!mn.peer)
+ (void) snpf(Namech, Namechl, "->(unknown)");
+ else {
+ if (kread((KA_T)mn.peer, (char *)&pn, sizeof(pn)))
+ (void) snpf(Namech, Namechl, "can't read peer shmtnode: %s",
+ print_kptr((KA_T)mn.peer, (char *)NULL, 0));
+ else {
+ if (pn.pid)
+ (void) snpf(Namech, Namechl, "->%s (PID %d)",
+ print_kptr((KA_T)mn.peer, (char *)NULL, 0), pn.pid);
+ else
+ (void) snpf(Namech, Namechl, "->%s",
+ print_kptr((KA_T)mn.peer, (char *)NULL, 0));
+ }
+ }
+ enter_nm(Namech);
+}
+#endif /* AIXV>=4200 */
+
+
+/*
+ * readlino() -- read local inode
+ */
+
+int
+readlino(ga, li)
+ struct gnode *ga; /* gnode address */
+ struct l_ino *li; /* local inode receiver */
+{
+ struct inode i; /* "regular" inode */
+
+#if defined(HAS_JFS2)
+ static struct vnodeops *j2va = (struct vnodeops *)NULL;
+ /* j2_vnops address */
+ static int j2vas = 0; /* j2nl[] status */
+#endif /* defined(HAS_JFS2) */
+
+ zeromem((char *)li, sizeof(struct l_ino));
+ if (!ga || !ga->gn_data)
+ return(0);
+
+#if defined(HAS_JFS2)
+ if (!j2vas) {
+
+ /*
+ * Get the j2_vnops address once.
+ */
+ struct nlist j2nl[] = {
+ { "j2_vnops" },
+ { (char *)NULL }
+ };
+
+ if (nlist(N_UNIX, j2nl) == 0)
+ j2va = (struct vnodeops *)j2nl[0].n_value;
+ if (!j2va && !Fwarn) {
+ (void) fprintf(stderr,
+ "%s: WARNING: can't identify jfs2 files\n", Pn);
+ }
+ j2vas = 1;
+ }
+/*
+ * If this system has jfs2, see if this gnode's operation structure pointer
+ * references j2_vnops.
+ */
+ if (ga->gn_ops && j2va && (ga->gn_ops == j2va))
+ return(readj2lino(ga, li));
+#endif /* defined(HAS_JFS2) */
+
+/*
+ * Read a "standard" inode.
+ */
+ if (readinode((KA_T)ga->gn_data, &i))
+ return(1);
+ li->dev = i.i_dev;
+ li->nlink = i.i_nlink;
+ li->number = (INODETYPE)i.i_number;
+ li->size = i.i_size;
+ li->dev_def = li->nlink_def = li->number_def = li->size_def = 1;
+ return(0);
+}
diff --git a/dialects/aix/dnode1.c b/dialects/aix/dnode1.c
new file mode 100644
index 0000000..e0f781f
--- /dev/null
+++ b/dialects/aix/dnode1.c
@@ -0,0 +1,313 @@
+/*
+ * dnode1.c - AIX AFS support
+ */
+
+
+/*
+ * Copyright 1996 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 1996 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dnode1.c,v 1.10 2005/08/08 19:46:38 abe Exp $";
+#endif
+
+
+#if defined(HAS_AFS)
+#include "lsof.h"
+
+
+/*
+ * This is an emulation of the afs_rwlock_t definition that appears in
+ * the AFS sources in afs/lock.h.
+ */
+
+struct afs_lock {
+
+# if HAS_AFS<304
+ unsigned long d1[4];
+# else /* HAS_AFS>=304 */
+ unsigned char d1[2];
+ unsigned short d2[3];
+ struct timeval d3;
+ unsigned int d4[3];
+# endif /* HAS_AFS<304 */
+
+};
+typedef struct afs_lock afs_lock_t;
+typedef struct afs_lock afs_rwlock_t;
+
+#define KERNEL
+#include <afs/afs.h>
+#undef KERNEL
+
+
+/*
+ * Local function prototypes
+ */
+
+_PROTOTYPE(static struct volume *getvolume,(struct VenusFid *f, int *vols));
+_PROTOTYPE(static int is_rootFid,(struct vcache *vc, int *rfid));
+
+
+/*
+ * alloc_vcache() - allocate space for vcache structure
+ */
+
+struct vnode *
+alloc_vcache()
+{
+ return((struct vnode *)malloc((MALLOC_S)sizeof(struct vcache)));
+}
+
+
+/*
+ * getvolume() - get volume structure
+ */
+
+static struct volume *
+getvolume(f, vols)
+ struct VenusFid *f; /* file ID pointer */
+ int *vols; /* afs_volumes status return */
+{
+ int i;
+ static KA_T ka = 0;
+ KA_T kh;
+ static struct volume v;
+ struct volume *vp;
+ static int w = 0;
+
+ if (!ka) {
+ if ((ka = (KA_T)AFSnl[X_AFS_VOL].n_value) == (KA_T)0) {
+ if (!w && !Fwarn) {
+ (void) fprintf(stderr,
+ "%s: WARNING: no kernel address for: %s\n",
+ Pn, AFSnl[X_AFS_VOL]._n._n_name);
+ (void) fprintf(stderr,
+ " This may hamper AFS node number reporting.\n");
+ w = 1;
+ }
+ *vols = 0;
+ return((struct volume *)NULL);
+ }
+ }
+ *vols = 1;
+ i = (NVOLS - 1) & f->Fid.Volume;
+ kh = (KA_T)((char *)ka + (i * sizeof(struct volume *)));
+ if (kread(kh, (char *)&vp, sizeof(vp)))
+ return((struct volume *)NULL);
+ while (vp) {
+ if (kread((KA_T)vp, (char *)&v, sizeof(v)))
+ return((struct volume *)NULL);
+ if (v.volume == f->Fid.Volume && v.cell == f->Cell)
+ return(&v);
+ vp = v.next;
+ }
+ return((struct volume *)NULL);
+}
+
+
+/*
+ * hasAFS() - test for AFS presence via vfs structure
+ */
+
+int
+hasAFS(vp)
+ struct vnode *vp; /* vnode pointer */
+{
+ struct vmount vm;
+ struct vfs v;
+/*
+ * If this vnode has a v_data pointer, then it probably isn't an AFS vnode;
+ * return FALSE.
+ *
+ * If the vfs struct address of /afs is known and this vnode's v_vfsp matches
+ * it, return TRUE.
+ *
+ * Read this vnode's vfs structure and its mount data. If the gfs type isn't
+ * AFS, return FALSE. If it is, save the vnode's v_vfsp as AFSVfsp and return
+ * TRUE.
+ */
+ if (AFSVfsp && !vp->v_data && (KA_T)vp->v_vfsp == AFSVfsp)
+ return(1);
+ if (vp->v_data || !vp->v_vfsp)
+ return(0);
+ if (kread((KA_T)vp->v_vfsp, (char *)&v, sizeof(v)))
+ return(0);
+ if (!v.vfs_mdata
+ || kread((KA_T)v.vfs_mdata, (char *)&vm, sizeof(vm)))
+ return(0);
+ if (vm.vmt_gfstype != MNT_AFS)
+ return(0);
+ AFSVfsp = (KA_T)vp->v_vfsp;
+ return(1);
+}
+
+
+/*
+ * is_rootFid() - is the file ID the root file ID
+ *
+ * return: 0 = is not root file ID
+ * 1 = is root file ID
+ * rfid = 0 if root file ID structure address not available
+ * 1 if root file ID structure address available
+ */
+
+static int
+is_rootFid(vc, rfid)
+ struct vcache *vc; /* vcache entry */
+ int *rfid; /* root file ID pointer status return */
+{
+ int err;
+ static int f = 0; /* rootFID structure status:
+ * -1 = unavailable
+ * 0 = not yet accessed
+ * 1 = available */
+ static struct VenusFid r;
+ static int w = 0;
+
+ switch (f) {
+ case -1:
+ if (vc->v.v_flag & V_ROOT) {
+ *rfid = 1;
+ return(1);
+ }
+ *rfid = 0;
+ return(0);
+ case 0:
+ if (!AFSnl[X_AFS_FID].n_value) {
+ err = 1;
+
+rfid_unavailable:
+
+ if (!w && !Fwarn) {
+ (void) fprintf(stderr,
+ "%s: WARNING: %s: %s\n", Pn,
+ err ? "no kernel address" : "can't read from kernel",
+ AFSnl[X_AFS_VOL]._n._n_name);
+ (void) fprintf(stderr,
+ " This may hamper AFS node number reporting.\n");
+ w = 1;
+ }
+ f = -1;
+ if (vc->v.v_flag & V_ROOT) {
+ *rfid = 1;
+ return(1);
+ }
+ *rfid = 0;
+ return(0);
+ }
+ if (kread((KA_T)AFSnl[X_AFS_FID].n_value, (char *)&r, sizeof(r))) {
+ err = 0;
+ goto rfid_unavailable;
+ }
+ f = 1;
+ /* fall through */
+ case 1:
+ *rfid = 1;
+ if (vc->fid.Fid.Unique == r.Fid.Unique
+ && vc->fid.Fid.Vnode == r.Fid.Vnode
+ && vc->fid.Fid.Volume == r.Fid.Volume
+ && vc->fid.Cell == r.Cell)
+ return(1);
+ }
+ *rfid = 0;
+ return(0);
+}
+
+
+/*
+ * readafsnode() - read AFS node
+ */
+
+int
+readafsnode(va, v, an)
+ KA_T va; /* kernel vnode address */
+ struct vnode *v; /* vnode buffer pointer */
+ struct afsnode *an; /* afsnode recipient */
+{
+ char *cp, tbuf[32];
+ KA_T ka;
+ int len, rfid, vols;
+ struct vcache *vc;
+ struct volume *vp;
+
+ cp = ((char *)v + sizeof(struct vnode));
+ ka = (KA_T)((char *)va + sizeof(struct vnode));
+ len = sizeof(struct vcache) - sizeof(struct vnode);
+ if (kread(ka, cp, len)) {
+ (void) snpf(Namech, Namechl,
+ "vnode at %s: can't read vcache remainder from %s",
+ print_kptr(va, tbuf, sizeof(tbuf)),
+ print_kptr(ka, (char *)NULL, 0));
+ enter_nm(Namech);
+ return(1);
+ }
+ vc = (struct vcache *)v;
+ an->dev = AFSDEV;
+ an->size = (unsigned long)vc->m.Length;
+ an->nlink = (long)vc->m.LinkCount;
+ an->nlink_st = 1;
+/*
+ * Manufacture the "inode" number.
+ */
+ if (vc->mvstat == 2) {
+ if ((vp = getvolume(&vc->fid, &vols))) {
+ an->inode = (INODETYPE)((vp->mtpoint.Fid.Vnode
+ + (vp->mtpoint.Fid.Volume << 16))
+ & 0x7fffffff);
+ if (an->inode == (INODETYPE)0) {
+ if (is_rootFid(vc, &rfid))
+ an->ino_st = 1;
+ else if (rfid) {
+ an->inode = (INODETYPE)2;
+ an->ino_st = 1;
+ } else
+ an->ino_st = 0;
+ } else
+ an->ino_st = 1;
+ } else {
+ if (vols) {
+ an->inode = (INODETYPE)2;
+ an->ino_st = 1;
+ } else {
+ if (v->v_flag & V_ROOT) {
+ an->inode = (INODETYPE)0;
+ an->ino_st = 1;
+ } else
+ an->ino_st = 0;
+ }
+ }
+ } else {
+ an->inode = (INODETYPE)((vc->fid.Fid.Vnode
+ + (vc->fid.Fid.Volume << 16))
+ & 0x7fffffff);
+ an->ino_st = 1;
+ }
+ return(0);
+}
+#endif /* defined(HAS_AFS) */
diff --git a/dialects/aix/dnode2.c b/dialects/aix/dnode2.c
new file mode 100644
index 0000000..f7a8ce9
--- /dev/null
+++ b/dialects/aix/dnode2.c
@@ -0,0 +1,81 @@
+/*
+ * dnode2.c - AIX jfs2 support
+ *
+ * V. Abell
+ * Purdue University
+ */
+
+
+/*
+ * Copyright 2003 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 2003 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dnode2.c,v 1.4 2005/08/08 19:46:38 abe Exp $";
+#endif
+
+
+#if defined(HAS_JFS2)
+#define _H_JFS_INO /* prevent <jfs_ino.h> */
+#define _H_JFS_INODE /* prevent <jfs_inode.h> */
+#define PROTO_H /* prevent "proto.h" and
+ * "dproto.h" until struct
+ * inode is available from
+ * <j2/j2_inode.h> */
+#define DPROTO_H
+#include "lsof.h"
+#define _KERNEL
+#include <j2/j2_inode.h>
+#undef PROTO_H /* enable "proto.h" */
+#undef DPROTO_H /* enable "dproto.h" */
+#include "proto.h"
+#include "dproto.h"
+
+int
+readj2lino(ga, li)
+ struct gnode *ga; /* gnode address */
+ struct l_ino *li; /* local inode receiver */
+{
+ struct inode i; /* jfs2 inode */
+/*
+ * Read the jfs2 inode and fill in the local inode receiver.
+ *
+ * Note: the caller is responsible for initializing *li to zeroes.
+ */
+ if (!ga
+ || !ga->gn_data
+ || kread((KA_T)ga->gn_data, (char *)&i, sizeof(i)))
+ return(1);
+ li->dev = i.i_dev;
+ li->nlink = i.i_nlink;
+ li->number = (INODETYPE)i.i_number;
+ li->size = i.i_size;
+ li->dev_def = li->nlink_def = li->number_def = li->size_def = 1;
+ return(0);
+}
+#endif /* defined(HAS_JFS2) */
diff --git a/dialects/aix/dproc.c b/dialects/aix/dproc.c
new file mode 100644
index 0000000..c951717
--- /dev/null
+++ b/dialects/aix/dproc.c
@@ -0,0 +1,1481 @@
+/*
+ * dproc.c - AIX process access functions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dproc.c,v 1.26 2008/10/21 16:14:18 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+_PROTOTYPE(static void get_kernel_access,(void));
+
+#if AIXA<2
+_PROTOTYPE(static struct le *getle,(KA_T a, KA_T sid, char **err));
+#endif /* AIXA<2 */
+
+#if AIXV>=4110
+_PROTOTYPE(static void getlenm,(struct le *le, KA_T sid));
+#endif /* AIXV>=4110 */
+
+_PROTOTYPE(static int kreadx,(KA_T addr, char *buf, int len, KA_T sid));
+
+#if AIXA<2
+_PROTOTYPE(static void process_text,(KA_T sid));
+#else /* AIXA>=2 */
+_PROTOTYPE(static void getsoinfo,(void));
+_PROTOTYPE(static void process_text,(pid_t pid));
+#endif /* AIXA<2 */
+
+#if defined(SIGDANGER)
+# if defined(HASINTSIGNAL)
+_PROTOTYPE(static int lowpgsp,(int sig));
+# else /* !defined(HASINTSIGNAL) */
+_PROTOTYPE(static void lowpgsp,(int sig));
+# endif /* defined(HASINTSIGNAL) */
+#endif /* defined(SIGDANGER) */
+
+
+/*
+ * Local definitions
+ */
+
+#if AIXV<4300
+#define PROCINFO procinfo
+#else /* AIXV>=4300 */
+#define PROCINFO_INCR 256
+# if AIXA<1
+#define FDSINFO fdsinfo
+#define GETPROCS getprocs
+#define PROCINFO procsinfo
+# else /* AIXA>=1 */
+#define FDSINFO fdsinfo64
+#define GETPROCS getprocs64
+#define PROCINFO procentry64
+
+# if AIXA>1
+/*
+ * AIX 5 and greater ia64 loader definitions
+ */
+
+#include <sys/ldr.h>
+
+#define SOHASHBUCKS 128 /* SoHash[] bucket count
+ * MUST BE A POWER OF 2!!! */
+#define SOHASH(d, n) ((((int)(((GET_MIN_DEV(d) & 0x7fffffff) * SOHASHBUCKS) \
+ + n) * 31415) >> 7) & (SOHASHBUCKS - 1))
+
+typedef struct so_hash {
+ dev_t dev; /* device (st_dev) */
+ int nlink; /* link count (st_nlink) */
+ char *nm; /* name (mi_name) */
+ INODETYPE node; /* node number (st_ino) */
+ struct so_hash *next; /* next entry in hash bucket */
+ SZOFFTYPE sz; /* size (st_size) */
+} so_hash_t;
+
+so_hash_t **SoHash = (so_hash_t **)NULL;
+# endif /* AIXA>1 */
+# endif /* AIXA<1 */
+#endif /* AIXV<4300 */
+
+#define PROCSIZE sizeof(struct PROCINFO)
+
+/*
+ * Create the FDSINFOSIZE definition for allocating FDSINFO space. (This
+ * isn't as straightforward as it might seem, because someone made a bad
+ * decision to change the struct fdsinfo* family at AIX 5.2.)
+ */
+
+#define FDSINFOSIZE sizeof(struct FDSINFO) /* (If we're lucky.) */
+
+#if defined(OPEN_SHRT_MAX)
+# if OPEN_SHRT_MAX<OPEN_MAX
+#undef FDSINFOSIZE /* (We weren't lucky.) */
+#define FDSELEMSIZE (sizeof(struct FDSINFO)/OPEN_SHRT_MAX)
+#define FDSINFOSIZE (OPEN_MAX * FDSELEMSIZE)
+# endif /* OPEN_SHRT_MAX<OPEN_MAX */
+#endif /* defined(OPEN_SHRT_MAX) */
+
+
+#if AIXV>=4110
+/*
+ * Loader access definitions for AIX 4.1.1 and above.
+ */
+
+#define LIBNMLN 40 /* maximum library table name
+ * length */
+
+#define LIBMASK 0xf0000000 /* library table mask */
+#define LIBNMCOMP 0xd0000000 /* library table name has
+ * multiple components */
+# if AIXA<1
+#define RDXMASK 0x0fffffff /* kreadx() address mask */
+# else /* AIXA>=1 */
+#define RDXMASK 0x0fffffffffffffff /* kreadx() address mask */
+#define URDXMASK 0x0fffffff00000000 /* upper part of RDXMASK */
+# endif /* AIXA<1 */
+#endif /* AIXV>=4110 */
+
+
+/*
+ * Loader structure definitions. (AIX doesn't supply ld_data.h.)
+ */
+
+struct le { /* loader entry */
+
+ struct le *next; /* next entry pointer */
+
+#if AIXV<4300
+ ushort dummy1;
+ ushort dummy2;
+ uint dummy3;
+ struct file *fp; /* file table entry pointer */
+
+# if AIXV>=4110
+ int ft; /* file type indicator */
+ unsigned dummy4;
+ char *dummy5;
+ unsigned dummy6;
+ char *dummy7[3];
+ char *nm; /* name */
+# endif /* AIXV>=4110 */
+#else /* AIXV>=4300 */
+# if AIXA<2
+ uint flags;
+ struct file *fp; /* file table entry pointer */
+ char *nm; /* name */
+# else /* AIXA>=2 */
+ KA_T d1[2];
+ KA_T nm; /* name */
+ KA_T d2[10];
+ struct file *fp; /* file table entry pointer */
+# endif /* AIXA<2 */
+#endif /* AIXV<4300 */
+
+};
+
+
+#if AIXV>=4300
+/*
+ * The elements of interest from the AIX >= 4.3 loader anchor structure.
+ */
+struct la { /* loader anchor */
+
+# if AIXA<2
+ struct le *list;
+ struct le *exec;
+# else /* AIXA>=2 */
+ KA_T exec;
+ KA_T list;
+# endif /* AIXA<2 */
+};
+#endif /* AIXV>=4300 */
+
+
+/*
+ * Local static values
+ */
+
+static int Np = 0; /* number of processes */
+static struct PROCINFO *P = (struct PROCINFO *)NULL;
+ /* the process table */
+static struct user *Up; /* user structure */
+
+#if AIXV>=4110
+# if AIXA<2
+static KA_T Soff; /* shared library VM offset */
+int Soff_stat = 0; /* Soff-available status */
+# endif /* AIXA<2 */
+static KA_T Uo; /* user area VM offset */
+#endif /* AIXV>=4110 */
+
+
+/*
+ * ckkv() - check kernel version
+ */
+
+void
+ckkv(d, er, ev, ea)
+ char *d; /* dialect */
+ char *er; /* expected release */
+ char *ev; /* expected version */
+ char *ea; /* expected architecture */
+{
+
+#if defined(HASKERNIDCK)
+# if AIXV<5000
+
+/*
+ * Use oslevel below AIX 5.
+ */
+ int br, p[2], pid;
+ char buf[128], *cp;
+ struct stat sb;
+
+ if (Fwarn)
+ return;
+/*
+ * Make sure we can execute OSLEVEL. If OSLEVEL doesn't exist and the AIX
+ * version is below 4.1, return quietly.
+ */
+
+#define OSLEVEL "oslevel"
+#define OSLEVELPATH "/usr/bin/oslevel"
+
+ if (stat(OSLEVELPATH, &sb)) {
+
+# if AIXV<4100
+ if (errno == ENOENT)
+ return;
+# endif /* AIXV<4100 */
+
+ (void) fprintf(stderr, "%s: can't execute %s: %s\n",
+ Pn, OSLEVELPATH, strerror(errno));
+ Exit(1);
+ }
+ if ((sb.st_mode & (S_IROTH | S_IXOTH)) != (S_IROTH | S_IXOTH)) {
+ (void) fprintf(stderr, "%s: can't execute %s, modes: %o\n",
+ Pn, OSLEVELPATH, sb.st_mode);
+ Exit(1);
+ }
+/*
+ * Open a pipe for receiving the version number from OSLEVEL. Fork a
+ * child to run OSLEVEL. Retrieve the OSLEVEL output.
+ */
+ if (pipe(p)) {
+ (void) fprintf(stderr, "%s: can't create pipe to: %s\n",
+ Pn, OSLEVELPATH);
+ Exit(1);
+ }
+ if ((pid = fork()) == 0) {
+ (void) close(1);
+ (void) close(2);
+ (void) close(p[0]);
+ dup2(p[1], 1);
+ dup2(p[1], 2);
+ (void) close(p[1]);
+ execl(OSLEVELPATH, OSLEVEL, NULL);
+ _exit(0);
+ }
+ if (pid < 0) {
+ (void) fprintf(stderr, "%s: can't fork a child for %s: %s\n",
+ Pn, OSLEVELPATH, strerror(errno));
+ Exit(1);
+ }
+ (void) close(p[1]);
+ br = read(p[0], buf, sizeof(buf) - 1);
+ (void) close(p[0]);
+ (void) wait(NULL);
+/*
+ * Warn if the actual and expected versions don't match.
+ */
+ if (br > 0) {
+ buf[br] = '\0';
+ if ((cp = strrchr(buf, '\n')))
+ *cp = '\0';
+ } else
+ (void) snpf(buf, sizeof(buf), "UNKNOWN");
+# else /* AIXV>=5000 */
+
+/*
+ * Use uname() for AIX 5 and above.
+ */
+ char buf[64];
+ struct utsname u;
+
+ (void) memset((void *)&u, 0, sizeof(u));
+ (void) uname(&u);
+ (void) snpf(buf, sizeof(buf) - 1, "%s.%s.0.0", u.version, u.release);
+ buf[sizeof(buf) - 1] = '\0';
+# endif /* AIXV<5000 */
+ if (!ev || strcmp(buf, ev))
+ (void) fprintf(stderr,
+ "%s: WARNING: compiled for %s version %s; this is %s.\n",
+ Pn, d, ev ? ev : "UNKNOWN", buf);
+#endif /* defined(HASKERNIDCK) */
+
+}
+
+
+/*
+ * 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 */
+ KA_T cdir, fp, pdir, rdir;
+ char *cmd;
+ int hl, i, nf, np;
+ struct PROCINFO *p;
+ short pss, sf;
+ struct user us;
+
+#if AIXV>=4300
+ static struct FDSINFO *fds = (struct FDSINFO *)NULL;
+ MALLOC_S msz;
+# if AIXA==1
+ pid32_t pid; /* Since we're operating with types defined
+ * under _KERNEL (see machine.), but
+ * getprocs64() expects application types
+ * (where pid_t is 32 bits), the pid variable
+ * must be cast in an application-compatible
+ * manner.
+ */
+# else /* AIXA!=1 */
+ pid_t pid;
+# endif /* AIXA==1 */
+# if AIXV==4330
+ static int trx = 0;
+ unsigned int mxof;
+ static int uo = 0;
+# endif /* AIXV==4330 */
+#endif /* AIXV>=4300 */
+
+/*
+ * Define socket and regular file conditional processing flags.
+ *
+ * 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;
+ }
+/*
+ * Read the process table.
+ */
+
+#if AIXV<4300
+ if (!P) {
+ if (!(P = (struct PROCINFO *)malloc((MALLOC_S)PROCSIZE))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate space for 1 proc\n", Pn);
+ Exit(1);
+ }
+ Np = 1;
+ }
+ while (((np = getproc(P, Np, PROCSIZE)) == -1) && errno == ENOSPC) {
+ Np = P->p_pid + 10;
+ if (!(P = (struct PROCINFO *)realloc((MALLOC_P *)P,
+ (size_t)(Np * PROCSIZE))))
+ {
+ (void) fprintf(stderr, "%s: no space for %d procinfo's\n",
+ Pn, Np);
+ Exit(1);
+ }
+ }
+#else /* AIXV>=4300 */
+ if (!P) {
+ msz = (MALLOC_S)(PROCSIZE * PROCINFO_INCR);
+ if (!(P = (struct PROCINFO *)malloc(msz))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate space for %d procs\n",
+ Pn, PROCINFO_INCR);
+ Exit(1);
+ }
+ Np = PROCINFO_INCR;
+ }
+ np = pid = 0;
+ p = P;
+ while ((i = GETPROCS(p, PROCSIZE, (struct FDSINFO *)NULL, 0, &pid,
+ PROCINFO_INCR))
+ == PROCINFO_INCR) {
+ np += PROCINFO_INCR;
+ if (np >= Np) {
+ msz = (MALLOC_S)(PROCSIZE * (Np + PROCINFO_INCR));
+ if (!(P = (struct PROCINFO *)realloc((MALLOC_P *)P, msz))) {
+ (void) fprintf(stderr,
+ "%s: no more space for proc storage\n", Pn);
+ Exit(1);
+ }
+ Np += PROCINFO_INCR;
+ }
+ p = (struct PROCINFO *)((char *)P + (np * PROCSIZE));
+ }
+ if (i > 0)
+ np += i;
+#endif /* AIXV<4300 */
+
+/*
+ * Loop through processes.
+ */
+ for (p = P, Up = &us; np > 0; np--, p++) {
+ if (p->p_stat == 0 || p->p_stat == SZOMB)
+ continue;
+ if (is_proc_excl(p->p_pid, (int)p->p_pgid, (UID_ARG)p->p_uid,
+ &pss, &sf))
+ continue;
+
+#if AIXV<4300
+ /*
+ * Get user structure for AIX < 4.3.
+ *
+ * If AIX version is below 4.1.1, use getuser().
+ *
+ * If AIX version is 4.1.1 or above: if readx() is disabled (no -X
+ * option, use getuser(); if readx() is enabled (-X), use readx().
+ */
+
+# if AIXV>=4110
+ if (Fxopt
+ && kreadx(Uo, (char *)Up, U_SIZE, (KA_T)p->pi_adspace) == 0)
+ i = 1;
+ else
+ i = 0;
+ if (i == 0) {
+ if (getuser(p, PROCSIZE, Up, U_SIZE) != 0)
+ continue;
+ }
+ hl = i;
+# else /* AIXV<4110 */
+ if (getuser(p, PROCSIZE, Up, U_SIZE) != 0)
+ continue;
+ hl = 1;
+# endif /* AIXV>=4110 */
+ /*
+ * Save directory vnode addresses, command name address, and open file
+ * count from user structure.
+ *
+ * Skip processes excluded by the user structure command name.
+ */
+ cdir = (KA_T)Up->u_cdir;
+
+# if AIXV<4100
+ pdir = (KA_T)Up->u_pdir;
+# endif /* AIXV<4100 */
+
+ rdir = (KA_T)Up->u_rdir;
+ cmd = Up->u_comm;
+ nf = Up->u_maxofile;
+ if (is_cmd_excl(cmd, &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;
+ }
+
+#else /* AIXV>=4300 */
+ /*
+ * For AIX 4.3 and above, skip processes excluded by the procsinfo
+ * command name. Use getprocs() to get the file descriptors for
+ * included processes.
+ *
+ * If readx is enabled (-X), use it to get the loader_anchor structure.
+ */
+ if (is_cmd_excl(p->pi_comm, &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;
+ }
+ if (!fds) {
+ if (!(fds = (struct FDSINFO *)malloc((MALLOC_S)FDSINFOSIZE)))
+ {
+ (void) fprintf(stderr,
+ "%s: can't allocate fdsinfo struct for PID %d\n",
+ Pn, pid);
+ Exit(1);
+ }
+ }
+ pid = p->p_pid;
+ if (GETPROCS((struct PROCINFO *)NULL, PROCSIZE, fds, FDSINFOSIZE,
+ &pid, 1)
+ != 1)
+ continue;
+ hl = 0;
+
+# if AIXV==4330
+ /*
+ * Handle readx() for AIX 4.3.3 specially, because 4.3.3 was released
+ * with two different user struct definitions in <sys/user.h> and
+ * their form affects using readx() to get the loader table pointers
+ * from U_loader of the user structure (when -X is specified).
+ */
+ if (Fxopt) {
+ for (;;) {
+
+ /*
+ * Read the AIX 4.3.3 U_loader pointers.
+ */
+ if (kreadx((KA_T)((char *)Uo
+ + offsetof(struct user, U_loader) + uo),
+ (char *)&Up->U_loader, sizeof(struct la),
+ (KA_T)p->pi_adspace))
+ break;
+ if (trx) {
+ hl = 1;
+ break;
+ }
+ /*
+ * Until the correct size of the U_loader offset in lo has been
+ * established, read U_maxofile and match it to pi_maxofile
+ * from the PROCINFO structure. Try the offsets 0, 48, and
+ * -48. Note: these offsets are heuristic attempts to adjust
+ * to differences in the user struct as observed on two systems
+ * whose <sys/user.h> header files differed. U_maxofile
+ * follows U_loader by the same number of elements in both
+ * user structs, so the U_loader offset should be the same as
+ * the U_maxofile offset.
+ */
+ if (!kreadx((KA_T)((char *)Uo
+ + offsetof(struct user,U_maxofile) + uo),
+ (char *)&mxof, sizeof(mxof),
+ (KA_T)p->pi_adspace)
+ && (mxof == p->pi_maxofile))
+ {
+ hl = trx = 1;
+ break;
+ }
+ if (uo == 0)
+ uo = 48;
+ else if (uo == 48)
+ uo = -48;
+ else {
+ Fxopt = hl = 0;
+ trx = 1;
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ "%s: WARNING: user struct mismatch;", Pn);
+ (void) fprintf(stderr, " -X option disabled.\n");
+ }
+ break;
+ }
+ }
+ }
+# else /* AIXV!=4330 */
+ if (Fxopt
+ && kreadx((KA_T)((char *)Uo + offsetof(struct user, U_loader)),
+ (char *)&Up->U_loader, sizeof(struct la),
+ (KA_T)p->pi_adspace)
+ == 0)
+ hl = 1;
+# endif /* AIXV==4330 */
+
+ /*
+ * Save directory vnode addresses, command name, and open file count
+ * from procinfo structure.
+ */
+ cdir = (KA_T)p->pi_cdir;
+ pdir = (KA_T)NULL;
+ rdir = (KA_T)p->pi_rdir;
+ cmd = p->pi_comm;
+ nf = p->pi_maxofile;
+#endif /* AIXV<4300 */
+
+ /*
+ * Allocate a local process structure and start filling it.
+ */
+ alloc_lproc(p->p_pid, (int)p->p_pgid, (int)p->p_ppid,
+ (UID_ARG)p->p_uid, cmd, (int)pss, (int)sf);
+ Plf = (struct lfile *)NULL;
+ /*
+ * Save current working directory information.
+ */
+ if (!ckscko && cdir) {
+ alloc_lfile(CWD, -1);
+ process_node(cdir);
+ if (Lf->sf)
+ link_lfile();
+ }
+ /*
+ * Save root directory information.
+ */
+ if (!ckscko && rdir) {
+ alloc_lfile(RTD, -1);
+ process_node(rdir);
+ if (Lf->sf)
+ link_lfile();
+ }
+
+#if AIXV<4100
+ /*
+ * Save parent directory information.
+ */
+ if (!ckscko && pdir) {
+ alloc_lfile(" pd", -1);
+ process_node(pdir);
+ if (Lf->sf)
+ link_lfile();
+ }
+#endif /* AIXV<4100 */
+
+ /*
+ * Save information on text files.
+ */
+ if (!ckscko && hl) {
+
+#if AIXA<2
+# if AIXA<1
+ process_text((KA_T)p->pi_adspace);
+# else /* AIXA==1 */
+ {
+ int ck = 1;
+ KA_T sid = (KA_T)p->pi_adspace;
+
+ if ((Up->U_loader[0] & URDXMASK)
+ || (Up->U_loader[1] & URDXMASK))
+ {
+
+ /*
+ * If the upper part of either loader map address is
+ * non-zero and this is not the lsof process, skip the
+ * processing of text files. If this is the lsof process,
+ * set the segment address to zero, forcing text file
+ * information to come from kmem rather than mem.
+ */
+ if (Mypid == p->p_pid)
+ sid = (KA_T)0;
+ else
+ ck = 0;
+ }
+ if (ck)
+ process_text(sid);
+ }
+# endif /* AIXA<1 */
+#else /* AIXA>=2 */
+ process_text(p->p_pid);
+#endif /* AIXA<2 */
+
+ }
+ /*
+ * Save information on file descriptors.
+ */
+ for (i = 0; i < nf; i++) {
+
+#if AIXV<4300
+ fp = (KA_T)Up->u_ufd[i].fp;
+#else /* AIXV>=4300 */
+ fp = (KA_T)fds->pi_ufd[i].fp;
+#endif /* AIXV<4300 */
+
+ if (fp) {
+ alloc_lfile((char *)NULL, i);
+ process_file(fp);
+ if (Lf->sf) {
+
+#if defined(HASFSTRUCT)
+ if (Fsv & FSV_FG)
+
+# if AIXV<4300
+ Lf->pof = (long)(Up->u_ufd[i].flags & 0x7f);
+#else /* AIXV>=4300 */
+ Lf->pof = (long)(fds->pi_ufd[i].flags & 0x7f);
+#endif /* AIXV<4300 */
+#endif /* defined(HASFSTRUCT) */
+
+ link_lfile();
+ }
+ }
+ }
+ /*
+ * Examine results.
+ */
+ if (examine_lproc())
+ return;
+ }
+}
+
+
+/*
+ * get_kernel_access() - get access to kernel memory
+ */
+
+static void
+get_kernel_access()
+{
+ int oe = 0;
+
+#if defined(AIX_KERNBITS)
+ int kb;
+ char *kbb, *kbr;
+/*
+ * Check the kernel bit size against the size for which this executable was
+ * configured.
+ */
+ if (__KERNEL_32()) {
+ kb = 32;
+ kbr = "32";
+ } else if (__KERNEL_64()) {
+ kb = 64;
+ kbr = "64";
+ } else {
+ kb = 0;
+ kbr = "unknown";
+ }
+ if ((AIX_KERNBITS == 0) || !kb || (kb != AIX_KERNBITS)) {
+ if (AIX_KERNBITS == 32)
+ kbb = "32";
+ else if (AIX_KERNBITS == 64)
+ kbb = "64";
+ else
+ kbb = "unknown";
+ (void) fprintf(stderr,
+ "%s: FATAL: compiled for a kernel of %s bit size.\n", Pn, kbb);
+ (void) fprintf(stderr,
+ " The bit size of this kernel is %s.\n", kbr);
+ Exit(1);
+ }
+#endif /* defined(AIX_KERNBITS) */
+
+/*
+ * Access /dev/mem.
+ */
+ if ((Km = open("/dev/mem", O_RDONLY, 0)) < 0) {
+ (void) fprintf(stderr, "%s: can't open /dev/mem: %s\n",
+ Pn, strerror(errno));
+ oe++;
+ }
+
+#if defined(WILLDROPGID)
+/*
+ * If kernel memory isn't coming from KMEM, drop setgid permission
+ * before attempting to open the (Memory) file.
+ */
+ if (Memory)
+ (void) dropgid();
+#else /* !defined(WILLDROPGID) */
+/*
+ * See if the non-KMEM memory file is readable.
+ */
+ if (Memory && !is_readable(Memory, 1))
+ Exit(1);
+#endif /* defined(WILLDROPGID) */
+
+/*
+ * Access kernel memory file.
+ */
+ if ((Kd = open(Memory ? Memory : KMEM, O_RDONLY, 0)) < 0) {
+ (void) fprintf(stderr, "%s: can't open %s: %s\n", Pn,
+ Memory ? Memory : KMEM, strerror(errno));
+ oe++;
+ }
+ if (oe)
+ Exit(1);
+
+#if defined(WILLDROPGID)
+/*
+ * Drop setgid permission, if necessary.
+ */
+ if (!Memory)
+ (void) dropgid();
+#endif /* defined(WILLDROPGID) */
+
+/*
+ * Get kernel symbols.
+ */
+ if (knlist(Nl, X_NL_NUM, sizeof(struct nlist)) || !Nl[X_UADDR].n_value)
+ {
+ (void) fprintf(stderr, "%s: can't get kernel's %s address\n",
+ Pn, Nl[X_UADDR].n_name);
+ Exit(1);
+ }
+
+#if defined(HAS_AFS)
+ (void) knlist(AFSnl, X_AFSNL_NUM, sizeof(struct nlist));
+#endif /* defined(HAS_AFS) */
+
+#if AIXV>=4110
+/*
+ * Get user area and shared library VM offsets for AIX 4.1.1 and above.
+ */
+ if (Fxopt) {
+ struct ublock *ub;
+
+# if AIXA<2
+ struct nlist ll[] = {
+ { "library_anchor" },
+
+# if AIXV>=4330
+ { "library_le_handle" },
+# else /* AIXV<4330 */
+ { "library_data_handle" },
+# endif /* AIXV>=4330 */
+
+ { (char *)NULL }
+ };
+
+ if (nlist(N_UNIX, ll) == 0
+ && ll[0].n_value != (long)0 && ll[1].n_value != (long)0
+ && kreadx((KA_T)(ll[1].n_value & RDXMASK), (char *)&Soff,
+ sizeof(Soff), (KA_T)0)
+ == 0)
+ Soff_stat++;
+# endif /* AIXA<2 */
+
+ ub = (struct ublock *)Nl[X_UADDR].n_value;
+ Uo = (KA_T)((KA_T)&ub->ub_user & RDXMASK);
+ }
+#endif /* AIXV>=4110 */
+
+/*
+ * Check the kernel version number.
+ */
+ (void) ckkv("AIX", (char *)NULL, LSOF_VSTR, (char *)NULL);
+
+#if defined(SIGDANGER)
+/*
+ * If SIGDANGER is defined, enable its handler.
+ */
+ (void) signal(SIGDANGER, lowpgsp);
+#endif /* defined(SIGDANGER) */
+
+}
+
+
+#if AIXA<2
+/*
+ * getle() - get loader entry structure
+ */
+
+static struct le *
+getle(a, sid, err)
+ KA_T a; /* loader entry kernel address */
+ KA_T sid; /* user structure segment ID */
+ char **err; /* error message (if return is NULL) */
+{
+ static struct le le;
+
+#if AIXV<4110
+ if (a < Nl[X_UADDR].n_value) {
+ *err = "address too small";
+ return((struct le *)NULL);
+ }
+ if (((char *)a + sizeof(le)) <= ((char *)Nl[X_UADDR].n_value + U_SIZE))
+ return((struct le *)((char *)Up + a - Nl[X_UADDR].n_value));
+#endif /* AIXV<4110 */
+
+ if (!Fxopt) {
+ *err = "readx() disabled for Stale Segment ID bug (see -X)";
+ return((struct le *)NULL);
+ }
+
+#if AIXV>=4110
+ if (!sid) {
+ if (!kread(a, (char *)&le, sizeof(le)))
+ return(&le);
+ } else {
+ if (!kreadx((KA_T)(a & RDXMASK),(char *)&le,sizeof(le),(KA_T)sid))
+ return(&le);
+ }
+#else /* AIXV<4110 */
+ if (!kreadx((KA_T)a, (char *)&le, sizeof(le), (KA_T)sid))
+ return(&le);
+#endif /* AIXV>=4110 */
+
+getle_err:
+
+ *err = "can't readx()";
+ return((struct le *)NULL);
+}
+#endif /* AIXA<2 */
+
+
+#if AIXV>=4110
+/*
+ * getlenm() - get loader entry file name for AIX >= 4.1.1
+ */
+
+static void
+getlenm(le, sid)
+ struct le *le; /* loader entry structure */
+ KA_T sid; /* segment ID */
+{
+ char buf[LIBNMLN];
+ int i;
+
+# if AIXV<4300
+ if ((le->ft & LIBMASK) != LIBNMCOMP)
+ return;
+#else /* AIXV>=4300 */
+# if AIXA<2
+ if (!sid) {
+ if (kread((KA_T)le->nm, buf, LIBNMLN))
+ return;
+ } else {
+ if (!Soff_stat || !le->nm
+ || kreadx((KA_T)le->nm & (KA_T)RDXMASK, buf, LIBNMLN, (KA_T)Soff))
+ return;
+ }
+ buf[LIBNMLN - 1] = '\0';
+ i = strlen(buf);
+ if (i < (LIBNMLN - 3) && buf[i+1])
+ enter_nm(&buf[i+1]);
+ else if (buf[0])
+ enter_nm(buf);
+# else /* AIXA>=2 */
+ if (!le->nm || kread(le->nm, buf, sizeof(buf)))
+ return;
+ buf[LIBNMLN - 1] = '\0';
+ if (!strlen(buf))
+ return;
+ enter_nm(buf);
+# endif /* AIXA<2 */
+#endif /* AIXV<4300 */
+
+}
+#endif /* AIXV>=4110 */
+
+
+#if AIXA>1
+/*
+ * getsoinfo() - get *.so information for ia64 AIX >= 5
+ */
+
+static void
+getsoinfo()
+{
+ char buf[65536];
+ uint bufsz = (uint) sizeof(buf);
+ int ct, h;
+ char *ln = (char *)NULL;
+ char *rn = (char *)NULL;
+ LDR_Mod_info_t *lp;
+ struct stat sb;
+ so_hash_t *sp;
+/*
+ * See if loader information is needed. Warn if this process has insufficient
+ * permission to acquire it from all processes.
+ */
+ if (!Fxopt)
+ return;
+ if ((Myuid != 0) && !Setuidroot && !Fwarn) {
+ (void) fprintf(stderr,
+ "%s: WARNING: insufficient permission to access all", Pn);
+ (void) fprintf(stderr, " /%s/object sub-\n", HASPROCFS);
+ (void) fprintf(stderr,
+ " directories; some loader information may", Pn);
+ (void) fprintf(stderr, " be unavailable.\n");
+ }
+/*
+ * Get the loader module table. Allocate hash space for it.
+ */
+ if ((ct = ldr_get_modules(SOL_GLOBAL, (void *)buf, &bufsz)) < 1)
+ return;
+ if (!(SoHash = (so_hash_t **)calloc((MALLOC_S)SOHASHBUCKS,
+ sizeof(so_hash_t *))))
+ {
+ (void) fprintf(stderr, "%s: no space for *.so hash buckets\n", Pn);
+ Exit(1);
+ }
+/*
+ * Cache the loader module information, complete with stat(2) results.
+ */
+ for (lp = (LDR_Mod_info_t *)buf; ct; ct--, lp++) {
+
+ /*
+ * Release previous name space allocations.
+ */
+ if (ln) {
+ (void) free((MALLOC_P *)ln);
+ ln = (char *)NULL;
+ }
+ if (rn) {
+ (void) free((MALLOC_P *)rn);
+ rn = (char *)NULL;
+ }
+ /*
+ * Make a copy of the loader module name.
+ */
+ if (!(rn = mkstrcpy(lp->mi_name, (MALLOC_S *)NULL))) {
+ (void) fprintf(stderr, "%s: no space for name: %s\n", Pn,
+ lp->mi_name);
+ Exit(1);
+ }
+ /*
+ * Resolve symbolic links.
+ */
+ ln = Readlink(rn);
+ if (ln == rn)
+ rn = (char *)NULL;
+ /*
+ * Get stat(2) information.
+ */
+ if (statsafely(ln, &sb)) {
+ if (!Fwarn)
+ (void) fprintf(stderr, "%s: WARNING: can't stat: %s\n",
+ Pn, ln);
+ continue;
+ }
+ /*
+ * Allocate and fill a loader information hash structure.
+ */
+ if (!(sp = (so_hash_t *)malloc((MALLOC_S)sizeof(so_hash_t)))) {
+ (void) fprintf(stderr, "%s: no space for *.so hash entry: %s\n",
+ Pn, ln);
+ Exit(1);
+ }
+ sp->dev = sb.st_dev;
+ sp->nlink = (int)sb.st_nlink;
+ sp->nm = ln;
+ ln = (char *)NULL;
+ sp->node = (INODETYPE)sb.st_ino;
+ sp->sz = (SZOFFTYPE)sb.st_size;
+ /*
+ * Link the structure to the appropriate hash bucket.
+ */
+ h = SOHASH(sb.st_dev, (INODETYPE)sb.st_ino);
+ if (SoHash[h])
+ sp->next = SoHash[h];
+ else
+ sp->next = (so_hash_t *)NULL;
+ SoHash[h] = sp;
+ }
+/*
+ * Free any unused name space that was allocated.
+ */
+ if (ln)
+ (void) free((MALLOC_P *)ln);
+ if (rn)
+ (void) free((MALLOC_P *)rn);
+}
+#endif /* AIXA>1 */
+
+
+/*
+ * initialize() - perform all initialization
+ */
+
+void
+initialize()
+{
+ get_kernel_access();
+
+#if AIXA>1
+ (void) getsoinfo();
+#endif /* AIXA>1 */
+
+}
+
+
+/*
+ * kread() - read from kernel memory
+ */
+
+int
+kread(addr, buf, len)
+ KA_T addr; /* kernel memory address */
+ char *buf; /* buffer to receive data */
+ READLEN_T len; /* length to read */
+{
+ int br;
+
+#if AIXV<4200
+ if (lseek(Kd, (off_t)addr, L_SET) == (off_t)-1)
+#else /* AIXV>=4200 */
+ if (lseek64(Kd, (off64_t)addr, L_SET) == (off64_t)-1)
+#endif /* AIXV<4200 */
+
+ return(1);
+ br = read(Kd, buf, len);
+ return((br == len) ? 0 : 1);
+}
+
+
+/*
+ * kreadx() - read kernel segmented memory
+ */
+
+int
+kreadx(addr, buf, len, sid)
+ KA_T addr; /* kernel address */
+ char *buf; /* destination buffer */
+ int len; /* length */
+ KA_T sid; /* segment ID */
+{
+ int br;
+
+#if AIXV<4200
+ if (lseek(Km, addr, L_SET) == (off_t)-1)
+#else /* AIXV>=4200 */
+ if (lseek64(Km, (off64_t)addr, L_SET) == (off64_t)-1)
+#endif /* AIXV<4200 */
+
+ return(1);
+ br = readx(Km, buf, len, sid);
+ return (br == len ? 0 : 1);
+}
+
+
+#if defined(SIGDANGER)
+/*
+ * lowpgsp() - hangle a SIGDANGER signal about low paging space
+*/
+
+# if defined(HASINTSIGNAL)
+static int
+# else /* !defined(HASINTSIGNAL) */
+static void
+# endif /* defined(HASINTSIGNAL) */
+
+lowpgsp(sig)
+ int sig;
+{
+ (void) fprintf(stderr, "%s: FATAL: system paging space is low.\n", Pn);
+ Exit(1);
+}
+#endif /* defined(SIGDANGER) */
+
+
+#if AIXA<2
+/*
+ * process_text() - process text file information for non-ia64 AIX
+ */
+
+static void
+process_text(sid)
+ KA_T sid; /* user area segment ID */
+{
+ char *err, fd[8];
+ static struct file **f = (struct file **)NULL;
+ int i, j, n;
+ struct le *le;
+ KA_T ll;
+ MALLOC_S msz;
+ static MALLOC_S nf = 0;
+ struct file *xf = (struct file *)NULL;
+
+#if AIXV>=4300
+ struct la *la = (struct la *)&Up->U_loader;
+#endif /* AIXV>=4300 */
+
+/*
+ * Display information on the exec'd entry.
+ */
+
+#if AIXV<4300
+ if ((ll = (KA_T)Up->u_loader[1]))
+#else /* AIXV>=4300 */
+ if ((ll = (KA_T)la->exec))
+#endif /* AIXV<4300 */
+
+ {
+ alloc_lfile(" txt", -1);
+ if ((le = getle(ll, sid, &err))) {
+ if ((xf = le->fp)) {
+ process_file((KA_T)xf);
+ if (Lf->sf) {
+
+#if AIXV>=4110 && AIXV<4300
+ if (!Lf->nm || !Lf->nm[0])
+ getlenm(le, sid);
+#endif /* AIXV>=4110 && AIXV<4300 */
+
+ link_lfile();
+ }
+ }
+ } else {
+ (void) snpf(Namech, Namechl, "text entry at %s: %s",
+ print_kptr((KA_T)ll, (char *)NULL, 0), err);
+ enter_nm(Namech);
+ if (Lf->sf)
+ link_lfile();
+ }
+ }
+/*
+ * Display the loader list.
+ */
+ for (i = n = 0,
+
+#if AIXV<4300
+ ll = (KA_T)Up->u_loader[0];
+#else /* AIXV>=4300 */
+ ll = (KA_T)la->list;
+#endif /* AIXV<4300 */
+
+ ll;
+ ll = (KA_T)le->next)
+ {
+ (void) snpf(fd, sizeof(fd), " L%02d", i);
+ alloc_lfile(fd, -1);
+ if (!(le = getle(ll, sid, &err))) {
+ (void) snpf(Namech, Namechl, "loader entry at %s: %s",
+ print_kptr((KA_T)ll, (char *)NULL, 0), err);
+ enter_nm(Namech);
+ if (Lf->sf)
+ link_lfile();
+ return;
+ }
+ /*
+ * Skip entries with no file pointers, the exec'd file, and entries
+ * that have already been processed.
+ */
+ if (!le->fp || (le->fp == xf))
+ continue;
+ for (j = 0; j < n; j++) {
+ if (f[j] == le->fp)
+ break;
+ }
+ if (j < n)
+ continue;
+ if (n >= nf) {
+
+ /*
+ * Allocate file structure address cache space.
+ */
+ nf += 10;
+ msz = (MALLOC_S)(nf * sizeof(struct file *));
+ if (f)
+ f = (struct file **)realloc((MALLOC_P *)f, msz);
+ else
+ f = (struct file **)malloc(msz);
+ if (!f) {
+ (void) fprintf(stderr,
+ "%s: no space for text file pointers\n", Pn);
+ Exit(1);
+ }
+ }
+ f[n++] = le->fp;
+ /*
+ * Save the loader entry.
+ */
+ process_file((KA_T)le->fp);
+ if (Lf->sf) {
+
+#if AIXV>=4110
+ if (!Lf->nm || !Lf->nm[0])
+ getlenm(le, sid);
+#endif /* AIXV>=4110 */
+
+ link_lfile();
+ i++;
+ }
+ }
+}
+#else /* AIXA>=2 */
+/*
+ * process_text() - process text file information for ia64 AIX >= 5
+ */
+
+static void
+process_text(pid)
+ pid_t pid; /* process PID */
+{
+ char buf[MAXPATHLEN+1], fd[8], *nm, *pp;
+ size_t bufl = sizeof(buf);
+ DIR *dfp;
+ struct dirent *dp;
+ int i;
+ struct la *la = (struct la *)&Up->U_loader;
+ struct le le;
+ struct lfile *lf;
+ struct stat sb;
+ so_hash_t *sp;
+ size_t sz;
+ dev_t xdev;
+ INODETYPE xnode;
+ int xs = 0;
+/*
+ * Display information on the exec'd entry.
+ */
+ if (la->exec && !kread((KA_T)la->exec, (char *)&le, sizeof(le))
+ && le.fp) {
+ alloc_lfile(" txt", -1);
+ process_file((KA_T)le.fp);
+ if (Lf->dev_def && (Lf->inp_ty == 1)) {
+ xdev = Lf->dev;
+ xnode = Lf->inode;
+ xs = 1;
+ }
+ if (Lf->sf) {
+ if (!Lf->nm || !Lf->nm[0])
+ getlenm(&le, (KA_T)0);
+ link_lfile();
+ }
+ }
+/*
+ * Collect devices and names for the entries in /HASPROCFS/PID/object -- the
+ * AIX 5 loader list equivalent. When things fail in this processing -- most
+ * likely for insufficient permissions -- be silent; a warning was issued by
+ * getsoinfo().
+ */
+ (void) snpf(buf, bufl, "/%s/%ld/object", HASPROCFS, (long)pid);
+ if (!(dfp = opendir(buf)))
+ return;
+ if ((sz = strlen(buf)) >= bufl)
+ return;
+ buf[sz++] = '/';
+ pp = &buf[sz];
+ sz = bufl - sz;
+/*
+ * Read the entries in the /HASPROCFS/PID/object subdirectory.
+ */
+ for (dp = readdir(dfp), i = 0; dp; dp = readdir(dfp)) {
+
+ /*
+ * Skip '.', "..", entries with no node number, and entries whose
+ * names are too long.
+ */
+ if (!dp->d_ino || (dp->d_name[0] == '.'))
+ continue;
+ if ((dp->d_namlen + 1) >= sz)
+ continue;
+ (void) strncpy(pp, dp->d_name, dp->d_namlen);
+ pp[dp->d_namlen] = '\0';
+ /*
+ * Get stat(2) information.
+ */
+ if (statsafely(buf, &sb))
+ continue;
+ /*
+ * Ignore the exec'd and non-regular files.
+ */
+ if (xs && (xdev == sb.st_dev) && (xnode == (INODETYPE)sb.st_ino))
+ continue;
+ if (!S_ISREG(sb.st_mode))
+ continue;
+ /*
+ * Allocate space for a file entry. Set its basic characteristics.
+ */
+ (void) snpf(fd, sizeof(fd), "L%02d", i++);
+ alloc_lfile(fd, -1);
+ Lf->dev_def = Lf->inp_ty = Lf->nlink_def = Lf->sz_def = 1;
+ Lf->dev = sb.st_dev;
+ Lf->inode = (INODETYPE)sb.st_ino;
+ (void) snpf(Lf->type, sizeof(Lf->type), "VREG");
+ /*
+ * Look for a match on device and node numbers in the *.so cache.
+ */
+ for (sp = SoHash[SOHASH(sb.st_dev, (INODETYPE)sb.st_ino)];
+ sp;
+ sp = sp->next)
+ {
+ if ((sp->dev == sb.st_dev)
+ && (sp->node == (INODETYPE)sb.st_ino))
+ {
+
+ /*
+ * A match was found; use its name, link count, and size.
+ */
+ nm = sp->nm;
+ Lf->nlink = sp->nlink;
+ Lf->sz = sp->sz;
+ break;
+ }
+ }
+ if (!sp) {
+
+ /*
+ * No match was found; use the /HASPROCFS/object name, its link
+ * count, and its size.
+ */
+ nm = pp;
+ Lf->nlink_def = sb.st_nlink;
+ Lf->sz = sb.st_size;
+ }
+ /*
+ * Do selection tests: NFS; link count; file name; and file system.
+ */
+
+# if defined(HAS_NFS)
+ if (Fnfs && (GET_MIN_DEV(Lf->dev_def) & SDEV_REMOTE))
+ Lf->sf |= SELNFS;
+# endif /* defined(HAS_NFS) */
+
+ if (Nlink && (Lf->nlink < Nlink))
+ Lf->sf |= SELNLINK;
+ if (Sfile && is_file_named(NULL, VREG, 0, 0))
+ Lf->sf |= SELNM;
+ if (Lf->sf) {
+
+ /*
+ * If the file was selected, enter its name and link it to the
+ * other files of the process.
+ */
+ enter_nm(nm);
+ link_lfile();
+ }
+ }
+ (void) closedir(dfp);
+}
+#endif /* AIXA<2 */
diff --git a/dialects/aix/dproto.h b/dialects/aix/dproto.h
new file mode 100644
index 0000000..a844342
--- /dev/null
+++ b/dialects/aix/dproto.h
@@ -0,0 +1,68 @@
+/*
+ * dproto.h - AIX function prototypes for lsof
+ *
+ * The _PROTOTYPE macro is defined in the common proto.h.
+ */
+
+
+/*
+ * Copyright 1994 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.
+ */
+
+
+/*
+ * $Id: dproto.h,v 1.4 2004/03/10 23:49:13 abe Exp $
+ */
+
+
+#if !defined(DPROTO_H)
+#define DPROTO_H
+
+# if defined(HAS_AFS)
+_PROTOTYPE(extern struct vnode *alloc_vcache,(void));
+_PROTOTYPE(extern int hasAFS,(struct vnode *vp));
+_PROTOTYPE(extern int readafsnode,(KA_T va, struct vnode *v, struct afsnode *an));
+# endif /* defined(HAS_AFS) */
+
+# if defined(HAS_JFS2)
+_PROTOTYPE(extern int readj2lino,(struct gnode *ga, struct l_ino *li));
+# endif /* defined(HAS_JFS2) */
+
+_PROTOTYPE(extern int getchan,(char *p));
+_PROTOTYPE(extern int is_file_named,(char *p, enum vtype ty, chan_t ch, int ic));
+_PROTOTYPE(extern char isglocked,(struct gnode *ga));
+_PROTOTYPE(extern int readlino,(struct gnode *ga, struct l_ino *li));
+_PROTOTYPE(extern struct l_vfs *readvfs,(struct vnode *vn));
+
+# if AIXV>=4200
+_PROTOTYPE(extern void process_shmt,(KA_T sa));
+# endif /* AIV>=4200 */
+
+# if defined(HASDCACHE) && AIXV>=4140
+_PROTOTYPE(extern void clr_sect,(void));
+_PROTOTYPE(extern int rw_clone_sect,(int m));
+# endif /* defined(HASDCACHE) && AIXV>=4140 */
+
+#endif /* !defined(DPROTO_H) */
diff --git a/dialects/aix/dsock.c b/dialects/aix/dsock.c
new file mode 100644
index 0000000..bd1756d
--- /dev/null
+++ b/dialects/aix/dsock.c
@@ -0,0 +1,443 @@
+/*
+ * dsock.c - AIX socket processing functions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dsock.c,v 1.24 2008/10/21 16:14:18 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+/*
+ * We include <sys/domain.h> here instead of "dlsof.h" for gcc's benefit.
+ * Its loader can't handle the multiple CONST u_char arrays declared in
+ * <net/net_globals.h> -- e.g., etherbroadcastaddr[]. (<sys/domain.h>
+ * #include's <net/net_globals.h>.)
+ */
+
+#include <net/netopt.h>
+#include <sys/domain.h>
+
+
+/*
+ * process_socket() - process socket file
+ */
+
+void
+process_socket(sa)
+ KA_T sa; /* socket address in kernel */
+{
+ struct domain d;
+ unsigned char *fa = (unsigned char *)NULL;
+ int fam;
+ int fp, lp, uo;
+ struct gnode g;
+ struct l_ino i;
+ struct inpcb inp;
+ int is = 0;
+ unsigned char *la = (unsigned char *)NULL;
+ struct protosw p;
+ struct socket s;
+ struct tcpcb t;
+ int ts = 0;
+ int tsn, tsnx;
+ struct unpcb uc, unp;
+ struct sockaddr_un *ua = (struct sockaddr_un *)NULL;
+ struct sockaddr_un un;
+ struct vnode v;
+ struct mbuf mb;
+/*
+ * Set socket file variables.
+ */
+ (void) snpf(Lf->type, sizeof(Lf->type), "sock");
+ Lf->inp_ty = 2;
+/*
+ * Read socket and protocol switch structures.
+ */
+ if (!sa) {
+ enter_nm("no socket address");
+ return;
+ }
+ if (kread(sa, (char *) &s, sizeof(s))) {
+ (void) snpf(Namech, Namechl, "can't read socket struct from %s",
+ print_kptr(sa, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ if (!s.so_type) {
+ enter_nm("no socket type");
+ return;
+ }
+ if (!s.so_proto
+ || kread((KA_T)s.so_proto, (char *)&p, sizeof(p))) {
+ (void) snpf(Namech, Namechl, "can't read protocol switch from %s",
+ print_kptr((KA_T)s.so_proto, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+/*
+ * Save size information.
+ */
+ if (Fsize) {
+ if (Lf->access == 'r')
+ Lf->sz = (SZOFFTYPE)s.so_rcv.sb_cc;
+ else if (Lf->access == 'w')
+ Lf->sz = (SZOFFTYPE)s.so_snd.sb_cc;
+ else
+ Lf->sz = (SZOFFTYPE)(s.so_rcv.sb_cc + s.so_snd.sb_cc);
+ Lf->sz_def = 1;
+ } else
+ Lf->off_def = 1;
+
+#if defined(HASTCPTPIQ)
+ Lf->lts.rq = s.so_rcv.sb_cc;
+ Lf->lts.sq = s.so_snd.sb_cc;
+ Lf->lts.rqs = Lf->lts.sqs = 1;
+#endif /* defined(HASTCPTPIQ) */
+
+#if defined(HASSOOPT)
+ Lf->lts.ltm = (unsigned int)s.so_linger;
+ Lf->lts.opt = (unsigned int)s.so_options;
+ Lf->lts.pqlen = (unsigned int)s.so_q0len;
+ Lf->lts.qlen = (unsigned int)s.so_qlen;
+ Lf->lts.qlim = (unsigned int)s.so_qlimit;
+ Lf->lts.rbsz = (unsigned long)s.so_rcv.sb_mbmax;
+ Lf->lts.sbsz = (unsigned long)s.so_snd.sb_mbmax;
+ Lf->lts.pqlens = Lf->lts.qlens = Lf->lts.qlims = Lf->lts.rbszs
+ = Lf->lts.sbszs = (unsigned char)1;
+#endif /* defined(HASSOOPT) */
+
+#if defined(HASSOSTATE)
+ Lf->lts.ss = (unsigned int)s.so_state;
+#endif /* defined(HASSOSTATE) */
+
+/*
+ * Process socket by the associated domain family.
+ */
+ if (!p.pr_domain
+ || kread((KA_T)p.pr_domain, (char *)&d, sizeof(d))) {
+ (void) snpf(Namech, Namechl, "can't read domain struct from %s",
+ print_kptr((KA_T)p.pr_domain, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ switch ((fam = d.dom_family)) {
+/*
+ * Process an Internet domain socket.
+ */
+ case AF_INET:
+
+#if defined(HASIPv6)
+ case AF_INET6:
+#endif /* defined(HASIPv6) */
+
+ /*
+ * Read protocol control block.
+ */
+ if (!s.so_pcb
+ || kread((KA_T) s.so_pcb, (char *) &inp, sizeof(inp))) {
+ if (!s.so_pcb) {
+ (void) snpf(Namech, Namechl, "no PCB%s%s",
+ (s.so_state & SS_CANTSENDMORE) ? ", CANTSENDMORE" : "",
+ (s.so_state & SS_CANTRCVMORE) ? ", CANTRCVMORE" : "");
+ } else {
+ (void) snpf(Namech, Namechl, "can't read inpcb at %s",
+ print_kptr((KA_T)s.so_pcb, (char *)NULL, 0));
+ }
+ enter_nm(Namech);
+ return;
+ }
+ if (p.pr_protocol == IPPROTO_TCP) {
+
+ /*
+ * If this is a TCP socket, read its control block.
+ */
+ if (inp.inp_ppcb
+ && !kread((KA_T)inp.inp_ppcb, (char *)&t, sizeof(t)))
+ {
+ ts = 1;
+ tsn = (int)t.t_state;
+ tsnx = tsn + TcpStOff;
+ }
+ }
+ if (ts
+ && (TcpStIn || TcpStXn)
+ && (tsnx >= 0) && (tsnx < TcpNstates)
+ ) {
+
+ /*
+ * Check TCP state name inclusion and exclusions.
+ */
+ if (TcpStXn) {
+ if (TcpStX[tsnx]) {
+ Lf->sf |= SELEXCLF;
+ return;
+ }
+ }
+ if (TcpStIn) {
+ if (TcpStI[tsnx])
+ TcpStI[tsnx] = 2;
+ else {
+ Lf->sf |= SELEXCLF;
+ return;
+ }
+ }
+ }
+ if (Fnet) {
+
+ /*
+ * Set SELNET flag for the file, as requested.
+ */
+ if (!FnetTy
+ || ((FnetTy == 4) && (fam == AF_INET))
+
+#if defined(HASIPv6)
+ || ((FnetTy == 6) && (fam == AF_INET6))
+#endif /* defined(HASIPv6) */
+ )
+
+ Lf->sf |= SELNET;
+ }
+ printiproto(p.pr_protocol);
+
+#if defined(HASIPv6)
+ (void) snpf(Lf->type, sizeof(Lf->type),
+ fam == AF_INET ? "IPv4" : "IPv6");
+#else /* !defined(HASIPv6) */
+ (void) snpf(Lf->type, sizeof(Lf->type), "inet");
+#endif /* defined(HASIPv6) */
+
+ /*
+ * Save Internet socket information.
+ */
+ enter_dev_ch(print_kptr((KA_T)(inp.inp_ppcb ? inp.inp_ppcb
+ : s.so_pcb),
+ (char *)NULL, 0));
+
+#if defined(HASIPv6)
+ /*
+ * If this is an IPv6 (AF_INET6) socket and IPv4 compatibility
+ * mode is enabled, use the IPv4 address, change the family
+ * indicator from AF_INET6 to AF_INET. Otherwise, use the IPv6
+ * address. Don't ignore empty addresses.
+ */
+ if (fam == AF_INET6) {
+ if (inp.inp_flags & INP_COMPATV4) {
+ fam = AF_INET;
+ la = (unsigned char *)&inp.inp_laddr;
+ } else
+ la = (unsigned char *)&inp.inp_laddr6;
+ } else
+#endif /* defined(HASIPv6) */
+
+ la = (unsigned char *)&inp.inp_laddr;
+ lp = (int)ntohs(inp.inp_lport);
+ if (fam == AF_INET
+ && (inp.inp_faddr.s_addr != INADDR_ANY || inp.inp_fport != 0)) {
+ fa = (unsigned char *)&inp.inp_faddr;
+ fp = (int)ntohs(inp.inp_fport);
+ }
+
+#if defined(HASIPv6)
+ else if (fam == AF_INET6) {
+
+ /*
+ * If this is an IPv6 (AF_INET6) socket and IPv4 compatibility
+ * mode is enabled, use the IPv4 address, change the family
+ * indicator from AF_INET6 to AF_INET. Otherwise, use the IPv6
+ * address. Ignore empty addresses.
+ */
+ if (inp.inp_flags & INP_COMPATV4) {
+ fam = AF_INET;
+ if (inp.inp_faddr.s_addr != INADDR_ANY
+ || inp.inp_fport != 0)
+ {
+ fa = (unsigned char *)&inp.inp_faddr;
+ fp = (int)ntohs(inp.inp_fport);
+ }
+ } else {
+ if (!IN6_IS_ADDR_UNSPECIFIED(&inp.inp_faddr6)) {
+ fa = (unsigned char *)&inp.inp_faddr6;
+ fp = (int)ntohs(inp.inp_fport);
+ }
+ }
+ }
+#endif /* defined(HASIPv6) */
+
+ if (fa || la)
+ (void) ent_inaddr(la, lp, fa, fp, fam);
+ if (ts) {
+ Lf->lts.type = 0;
+ Lf->lts.state.i = tsn;
+
+#if defined(HASSOOPT)
+ Lf->lts.kai = (unsigned int)t.t_timer[TCPT_KEEP];
+#endif /* defined(HASSOOPT) */
+
+#if defined(HASTCPOPT)
+ Lf->lts.mss = (unsigned long)t.t_maxseg;
+ Lf->lts.msss = (unsigned char)1;
+ Lf->lts.topt = (unsigned int)t.t_flags;
+#endif /* defined(HASTCPOPT) */
+
+ }
+ break;
+/*
+ * Process a ROUTE domain socket.
+ */
+ case AF_ROUTE:
+ (void) snpf(Lf->type, sizeof(Lf->type), "rte");
+ if (s.so_pcb)
+ enter_dev_ch(print_kptr((KA_T)(s.so_pcb), (char *)NULL, 0));
+ else
+ (void) snpf(Namech, Namechl, "no protocol control block");
+ if (!Fsize)
+ Lf->off_def = 1;
+ break;
+/*
+ * Process a Unix domain socket.
+ */
+ case AF_UNIX:
+ if (Funix)
+ Lf->sf |= SELUNX;
+ (void) snpf(Lf->type, sizeof(Lf->type), "unix");
+ /*
+ * Read Unix protocol control block and the Unix address structure.
+ */
+ enter_dev_ch(print_kptr(sa, (char *)NULL, 0));
+ if (kread((KA_T) s.so_pcb, (char *)&unp, sizeof(unp))) {
+ (void) snpf(Namech, Namechl, "can't read unpcb at %s",
+ print_kptr((KA_T)s.so_pcb, (char *)NULL, 0));
+ break;
+ }
+ if ((struct socket *)sa != unp.unp_socket) {
+ (void) snpf(Namech, Namechl, "unp_socket (%s) mismatch",
+ print_kptr((KA_T)unp.unp_socket, (char *)NULL, 0));
+ break;
+ }
+ if (unp.unp_addr) {
+ if (kread((KA_T) unp.unp_addr, (char *)&mb, sizeof(mb))) {
+ (void) snpf(Namech, Namechl, "can't read unp_addr at %s",
+ print_kptr((KA_T)unp.unp_addr, (char *)NULL, 0));
+ break;
+ }
+
+#if AIXV>=3200
+ uo = (int)(mb.m_hdr.mh_data - (caddr_t)unp.unp_addr);
+ if ((uo + sizeof(struct sockaddr)) <= sizeof(mb))
+ ua = (struct sockaddr_un *)((char *)&mb + uo);
+ else {
+ if (mb.m_hdr.mh_data
+ && !kread((KA_T)mb.m_hdr.mh_data, (char *)&un, sizeof(un))
+ ) {
+ ua = &un;
+ }
+ }
+#else /* AIXV<3200 */
+ ua = (struct sockaddr_un *)(((char *)&mb) + mb.m_off);
+#endif /* AIXV>=3200 */
+
+ }
+ if (!ua) {
+ ua = &un;
+ (void) bzero((char *)ua, sizeof(un));
+ ua->sun_family = AF_UNSPEC;
+ }
+ /*
+ * Print information on Unix socket that has no address bound
+ * to it, although it may be connected to another Unix domain
+ * socket as a pipe.
+ */
+ if (ua->sun_family != AF_UNIX) {
+ if (ua->sun_family == AF_UNSPEC) {
+ if (unp.unp_conn) {
+ if (kread((KA_T)unp.unp_conn, (char *)&uc, sizeof(uc)))
+ (void) snpf(Namech, Namechl,
+ "can't read unp_conn at %s",
+ print_kptr((KA_T)unp.unp_conn,(char *)NULL,0));
+ else
+ (void) snpf(Namech, Namechl, "->%s",
+ print_kptr((KA_T)uc.unp_socket,(char *)NULL,0));
+ } else
+ (void) snpf(Namech, Namechl, "->(none)");
+ } else
+ (void) snpf(Namech, Namechl, "unknown sun_family (%d)",
+ ua->sun_family);
+ break;
+ }
+ /*
+ * Read any associated vnode and then read its gnode and inode.
+ */
+ g.gn_type = VSOCK;
+ if (unp.unp_vnode
+ && !readvnode((KA_T)unp.unp_vnode, &v)) {
+ if (v.v_gnode
+ && !readgnode((KA_T)v.v_gnode, &g)) {
+ Lf->lock = isglocked(&g);
+ if (g.gn_type == VSOCK && g.gn_data
+ && !readlino(&g, &i))
+ is = 1;
+ }
+ }
+ /*
+ * Print Unix socket information.
+ */
+ if (is) {
+ Lf->dev = i.dev;
+ Lf->dev_def = i.dev_def;
+ if (Lf->dev_ch) {
+ (void) free((FREE_P *)Lf->dev_ch);
+ Lf->dev_ch = (char *)NULL;
+ }
+ Lf->inode = (INODETYPE)i.number;
+ Lf->inp_ty = i.number_def;
+ }
+ if (ua->sun_path[0]) {
+ if (mb.m_len > sizeof(struct sockaddr_un))
+ mb.m_len = sizeof(struct sockaddr_un);
+ *((char *)ua + mb.m_len - 1) = '\0';
+ if (Sfile && is_file_named(ua->sun_path, VSOCK, 0, 0))
+ Lf->sf |= SELNM;
+ if (!Namech[0])
+ (void) snpf(Namech, Namechl, "%s", ua->sun_path);
+ } else
+ (void) snpf(Namech, Namechl, "no address");
+ break;
+
+ default:
+ printunkaf(fam, 1);
+ }
+ if (Namech[0])
+ enter_nm(Namech);
+}
diff --git a/dialects/aix/dstore.c b/dialects/aix/dstore.c
new file mode 100644
index 0000000..c4e3ed9
--- /dev/null
+++ b/dialects/aix/dstore.c
@@ -0,0 +1,405 @@
+/*
+ * dstore.c - AIX global storage for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dstore.c,v 1.12 2004/12/30 18:40:59 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+/*
+ * Global storage definitions
+ */
+
+#if defined(HAS_AFS)
+struct nlist AFSnl[] = {
+ { "afs_rootFid", 0, 0, 0, 0, 0 },
+ { "afs_volumes", 0, 0, 0, 0, 0 },
+};
+
+# if defined(HASAOPT)
+char *AFSApath = (char *)NULL; /* alternate AFS name list path
+ * (from -a) */
+# endif /* defined(HASAOPT) */
+
+KA_T AFSVfsp = (KA_T)NULL; /* AFS vfs struct kernel address */
+#endif /* defined(HAS_AFS) */
+
+# if AIXV>=4140
+struct clone *Clone = (struct clone *)NULL;
+ /* local clone information */
+int CloneMaj = -1; /* clone major device number */
+int ClonePtc = -1; /* /dev/ptc minor device number */
+# endif /* AIXV>=4140 */
+
+int Kd = -1; /* /dev/kmem file descriptor */
+struct l_vfs *Lvfs = NULL; /* local vfs structure table */
+int Km = -1; /* /dev/mem file descriptor */
+
+struct nlist Nl[] = {
+
+#if AIXV<4100
+ { "u", 0, 0, 0, 0, 0 },
+#else /* AIXV>=4100 */
+ { "__ublock", 0, 0, 0, 0, 0 },
+#endif /* AIXV<4100 */
+
+};
+
+#if defined(HASFSTRUCT)
+/*
+ * Pff_tab[] - table for printing file flags
+ */
+
+struct pff_tab Pff_tab[] = {
+
+# if defined(FREAD)
+ { (long)FREAD, FF_READ },
+# else /* !defined(FREAD) */
+# if defined(_FREAD)
+ { (long)_FREAD, FF_READ },
+# endif /* defined(_FREAD) */
+# endif /* defined(FREAD) */
+
+# if defined(FWRITE)
+ { (long)FWRITE, FF_WRITE },
+# else /* !defined(FWRITE) */
+# if defined(_FWRITE)
+ { (long)_FWRITE, FF_WRITE },
+# endif /* defined(_FWRITE) */
+# endif /* defined(FWRITE) */
+
+# if defined(FNONBLOCK)
+ { (long)FNONBLOCK, FF_NBLOCK },
+# else /* !defined(FNONBLOCK) */
+# if defined(_FNONBLOCK)
+ { (long)_FNONBLOCK, FF_NBLOCK },
+# endif /* defined(_FNONBLOCK) */
+# endif /* defined(FNONBLOCK) */
+
+# if defined(FAPPEND)
+ { (long)FAPPEND, FF_APPEND },
+# else /* !defined(FAPPEND) */
+# if defined(_FAPPEND)
+ { (long)_FAPPEND, FF_APPEND },
+# endif /* defined(_FAPPEND) */
+# endif /* defined(FAPPEND) */
+
+# if defined(FSYNC)
+ { (long)FSYNC, FF_SYNC },
+# else /* !defined(FSYNC) */
+# if defined(_FSYNC)
+ { (long)_FSYNC, FF_SYNC },
+# endif /* defined(_FSYNC) */
+# endif /* defined(FSYNC) */
+
+# if defined(FEXEC)
+ { (long)FEXEC, FF_EXEC },
+# else /* !defined(FEXEC) */
+# if defined(_FEXEC)
+ { (long)_FEXEC, FF_EXEC },
+# endif /* defined(_FEXEC) */
+# endif /* defined(FEXEC) */
+
+# if defined(FCREAT)
+ { (long)FCREAT, FF_CREAT },
+# else /* !defined(FCREAT) */
+# if defined(_FCREAT)
+ { (long)_FCREAT, FF_CREAT },
+# endif /* defined(_FCREAT) */
+# endif /* defined(FCREAT) */
+
+# if defined(FTRUNC)
+ { (long)FTRUNC, FF_TRUNC },
+# else /* !defined(FTRUNC) */
+# if defined(_FTRUNC)
+ { (long)_FTRUNC, FF_TRUNC },
+# endif /* defined(_FTRUNC) */
+# endif /* defined(FTRUNC) */
+
+# if defined(FEXCL)
+ { (long)FEXCL, FF_EXCL },
+# else /* !defined(FEXCL) */
+# if defined(_FEXCL)
+ { (long)_EXCL, FF_EXCL },
+# endif /* defined(_FEXCL) */
+# endif /* defined(FEXCL) */
+
+# if defined(FNOCTTY)
+ { (long)FNOCTTY, FF_NOCTTY },
+# else /* !defined(FNOCTTY) */
+# if defined(_FNOCTTY)
+ { (long)_FNOCTTY, FF_NOCTTY },
+# endif /* defined(_FNOCTTY) */
+# endif /* defined(FNOCTTY) */
+
+# if defined(FRSHARE)
+ { (long)FRSHARE, FF_RSHARE },
+# else /* !defined(FRSHARE) */
+# if defined(_FRSHARE)
+ { (long)_FRSHARE, FF_RSHARE },
+# endif /* defined(_FRSHARE) */
+# endif /* defined(FRSHARE) */
+
+# if defined(FDEFER)
+ { (long)FDEFER, FF_DEFER },
+# else /* !defined(FDEFER) */
+# if defined(_FDEFER)
+ { (long)_FDEFER, FF_DEFER },
+# endif /* defined(_FDEFER) */
+# endif /* defined(FDEFER) */
+
+# if defined(FDELAY)
+ { (long)FDELAY, FF_DELAY },
+# else /* !defined(FDELAY) */
+# if defined(_FDELAY)
+ { (long)_FDELAY, FF_DELAY },
+# endif /* defined(_FDELAY) */
+# endif /* defined(FDELAY) */
+
+# if defined(FNDELAY)
+ { (long)FNDELAY, FF_NDELAY },
+# else /* !defined(FNDELAY) */
+# if defined(_FNDELAY)
+ { (long)_FNDELAY, FF_NDELAY },
+# endif /* defined(_FNDELAY) */
+# endif /* defined(FNDELAY) */
+
+# if defined(FNSHARE)
+ { (long)FNSHARE, FF_NSHARE },
+# else /* !defined(FNSHARE) */
+# if defined(_FNSHARE)
+ { (long)_FNSHARE, FF_NSHARE },
+# endif /* defined(_FNSHARE) */
+# endif /* defined(FNSHARE) */
+
+# if defined(FASYNC)
+ { (long)FASYNC, FF_ASYNC },
+# else /* !defined(FASYNC) */
+# if defined(_FASYNC)
+ { (long)_FASYNC, FF_ASYNC },
+# endif /* defined(_FASYNC) */
+# endif /* defined(FASYNC) */
+
+# if defined(FAIO)
+ { (long)FAIO, FF_AIO },
+# else /* !defined(FAIO) */
+# if defined(_FAIO)
+ { (long)_FAIO, FF_AIO },
+# endif /* defined(_FAIO) */
+# endif /* defined(FAIO) */
+
+# if defined(FCIO)
+ { (long)FCIO, FF_CIO },
+# else /* !defined(FCIO) */
+# if defined(_FCIO)
+ { (long)_FCIO, FF_CIO },
+# endif /* defined(_FCIO) */
+# endif /* defined(FCIO) */
+
+# if defined(FMOUNT)
+ { (long)FMOUNT, FF_MOUNT },
+# else /* !defined(FMOUNT) */
+# if defined(_FMOUNT)
+ { (long)_FMOUNT, FF_MOUNT },
+# endif /* defined(_FMOUNT) */
+# endif /* defined(FMOUNT) */
+
+# if defined(FSYNCALL)
+ { (long)FSYNCALL, FF_SYNC },
+# else /* !defined(FSYNCALL) */
+# if defined(_FSYNCALL)
+ { (long)_FSYNCALL, FF_SYNC },
+# endif /* defined(_FSYNCALL) */
+# endif /* defined(FSYNCALL) */
+
+# if defined(FNOCACHE)
+ { (long)FNOCACHE, FF_NOCACHE },
+# else /* defined(FNOCACHE) */
+# if defined(_FNOCACHE)
+ { (long)_FNOCACHE, FF_NOCACHE },
+# endif /* defined(_FNOCACHE) */
+# endif /* defined(FNOCACHE) */
+
+# if defined(FREADSYNC)
+ { (long)FREADSYNC, FF_RSYNC },
+# else /* !defined(FREADSYNC) */
+# if defined(_FREADSYNC)
+ { (long)_FREADSYNC, FF_RSYNC },
+# endif /* defined(_FREADSYNC) */
+# endif /* defined(FREADSYNC) */
+
+# if defined(FDATASYNC)
+ { (long)FDATASYNC, FF_DSYNC },
+# else /* !defined(FDATASYNC) */
+# if defined(_FDATASYNC)
+ { (long)_FDATASYNC, FF_DSYNC },
+# endif /* defined(_FDATASYNC) */
+# endif /* defined(FDATASYNC) */
+
+# if defined(FDEFERIND)
+ { (long)FDEFERIND, FF_DEFERIND },
+# else /* !defined(FDEFERIND) */
+# if defined(_FDEFERIND)
+ { (long)_FDEFERIND, FF_DEFERIND },
+# endif /* defined(_FDEFERIND) */
+# endif /* defined(FDEFERIND) */
+
+# if defined(FDATAFLUSH)
+ { (long)FDATAFLUSH, FF_DATAFLUSH },
+# else /* !defined(FDATAFLUSH) */
+# if defined(_FDATAFLUSH)
+ { (long)_FDATAFLUSH, FF_DATAFLUSH },
+# endif /* defined(_FDATAFLUSH) */
+# endif /* defined(FDATAFLUSH) */
+
+# if defined(FCLREAD)
+ { (long)FCLREAD, FF_CLREAD },
+# else /* !defined(FCLREAD) */
+# if defined(_FCLREAD)
+ { (long)_FCLREAD, FF_CLREAD },
+# endif /* defined(_FCLREAD) */
+# endif /* defined(FCLREAD) */
+
+# if defined(FLARGEFILE)
+ { (long)FLARGEFILE, FF_LARGEFILE },
+# else /* !defined(FLARGEFILE) */
+# if defined(_FLARGEFILE)
+ { (long)_FLARGEFILE, FF_LARGEFILE },
+# endif /* defined(_FLARGEFILE) */
+# endif /* defined(FLARGEFILE) */
+
+# if defined(FDIRECT)
+ { (long)FDIRECT, FF_DIRECT },
+# else /* !defined(FDIRECT) */
+# if defined(_FDIRECT)
+ { (long)_FDIRECT, FF_DIRECT },
+# endif /* defined(_FDIRECT) */
+# endif /* defined(FDIRECT) */
+
+# if defined(FSNAPSHOT)
+ { (long)FSNAPSHOT, FF_SNAP },
+# else /* !defined(FSNAPSHOT) */
+# if defined(_FSNAPSHOT)
+ { (long)_FSNAPSHOT, FF_SNAP },
+# endif /* defined(_FSNAPSHOT) */
+# endif /* defined(FAIO) */
+
+# if defined(FDOCLONE)
+ { (long)FDOCLONE, FF_DOCLONE },
+# else /* !defined(FDOCLONE) */
+# if defined(_FDOCLONE)
+ { (long)_FDOCLONE, FF_DOCLONE },
+# endif /* defined(_FDOCLONE) */
+# endif /* defined(FDOCLONE) */
+
+# if defined(FKERNEL)
+ { (long)FKERNEL, FF_KERNEL },
+# else /* !defined(FKERNEL) */
+# if defined(_FKERNEL)
+ { (long)_FKERNEL, FF_KERNEL },
+# endif /* defined(_FKERNEL) */
+# endif /* defined(FKERNEL) */
+
+# if defined(FMSYNC)
+ { (long)FMSYNC, FF_MSYNC },
+# else /* !defined(FMSYNC) */
+# if defined(_FMSYNC)
+ { (long)_FMSYNC, FF_MSYNC },
+# endif /* defined(_FMSYNC) */
+# endif /* defined(FMSYNC) */
+
+# if defined(GCFDEFER)
+ { (long)GCFDEFER, FF_GCFDEFER },
+# endif /* defined(GCFDEFER) */
+
+# if defined(GCFMARK)
+ { (long)GCFMARK, FF_GCFMARK },
+# endif /* defined(GCFMARK) */
+
+ { (long)0, NULL }
+};
+
+
+/*
+ * Pof_tab[] - table for print process open file flags
+ */
+
+struct pff_tab Pof_tab[] = {
+
+# if defined(UF_EXCLOSE)
+ { (long)UF_EXCLOSE, POF_CLOEXEC },
+# endif /* defined(UF_EXCLOSE) */
+
+# if defined(UF_MAPPED)
+ { (long)UF_MAPPED, POF_MAPPED },
+# endif /* defined(UF_MAPPED) */
+
+# if defined(UF_FDLOCK)
+ { (long)UF_FDLOCK, POF_FDLOCK },
+# endif /* defined(UF_FDLOCK) */
+
+# if defined(UF_AUD_READ)
+ { (long)UF_AUD_READ, POF_BNRD },
+# endif /* defined(UF_AUD_READ) */
+
+# if defined(UF_AUD_WRITE)
+ { (long)UF_AUD_WRITE, POF_BNWR },
+# endif /* defined(UF_AUD_WRITE) */
+
+# if defined(UF_FSHMAT)
+ { (long)UF_FSHMAT, POF_FSHMAT },
+# endif /* defined(UF_FSHMAT) */
+
+# if defined(UF_CLOSING)
+ { (long)UF_CLOSING, POF_CLOSING },
+# endif /* defined(UF_CLOSING) */
+
+# if defined(UF_ALLOCATED)
+ { (long)UF_ALLOCATED, POF_ALLOCATED },
+# endif /* defined(UF_ALLOCATED) */
+
+ { (long)0, NULL }
+};
+#endif /* defined(HASFSTRUCT) */
+
+#if AIXV>=4110
+struct ublock __ublock; /* dummy so we can define _KERNEL
+ * for <sys/user.h> */
+
+# if AIXA>2
+void aix_dstore_dummy_function() {} /* for ia64 idebug */
+# endif /* AIXA>2 */
+#endif /* AIXV>=4110 */
diff --git a/dialects/aix/machine.h b/dialects/aix/machine.h
new file mode 100644
index 0000000..d8f4a46
--- /dev/null
+++ b/dialects/aix/machine.h
@@ -0,0 +1,691 @@
+/*
+ * machine.h - AIX definitions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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.
+ */
+
+
+/*
+ * $Id: machine.h,v 1.43 2010/07/29 16:02:44 abe Exp $
+ */
+
+
+#if !defined(LSOF_MACHINE_H)
+#define LSOF_MACHINE_H 1
+
+
+# if AIXV<=3250
+/*
+ * The AIX 3.2.5 and below <netdb.h> requires that _SUN be defined to
+ * be able to get the rpcent structure definition.
+ */
+
+#define _SUN
+#include <netdb.h>
+#undef _SUN
+# endif /* AIXV<=3250 */
+
+
+# if AIXV>=4200
+/*
+ * AIX 4.2 requires that <sys/mstsave.h> be #include'd early. It needs
+ * <sys/types.h> and _KERNEL.
+ *
+ * AIX 4.3 requires that _KERNEL be defined before the #include of
+ * <sys/types.h>
+ *
+ * For gcc's sake, some redefinitions after including <sys/types.h> insure
+ * the off64_t and offset_t types are aligned on an 8 byte boundary.
+ */
+
+# if AIXV>=4300
+#define _KERNEL 1
+# endif /* AIXV>=4300 */
+
+#include <sys/types.h>
+
+# if AIXA>0
+#include <sys/resource.h>
+# endif /* AIXA>0 */
+
+# if defined(__GNUC__)
+typedef long long aligned_off64_t __attribute__ ((aligned (8)));
+typedef long long aligned_offset_t __attribute__ ((aligned (8)));
+#define off64_t aligned_off64_t
+#define offset_t aligned_offset_t
+# endif /* defined(__GNUC__) */
+
+# if AIXV<4300
+#define _KERNEL 1
+# endif /* AIXV<4300 */
+
+#include <sys/mstsave.h>
+#undef _KERNEL
+# endif /* AIXV>=4200 */
+
+
+/*
+ * CAN_USE_CLNT_CREATE is defined for those dialects where RPC clnt_create()
+ * can be used to obtain a CLIENT handle in lieu of clnttcp_create().
+ */
+
+# if AIXV>=4200
+#define CAN_USE_CLNT_CREATE 1
+# endif /* AIXV>=4200 */
+
+
+/*
+ * DEVDEV_PATH defines the path to the directory that contains device
+ * nodes.
+ */
+
+#define DEVDEV_PATH "/dev"
+
+
+/*
+ * GET_MAX_FD is defined for those dialects that provide a function other than
+ * getdtablesize() to obtain the maximum file descriptor number plus one.
+ */
+
+/* #define GET_MAX_FD ? */
+
+
+/*
+ * HASAOPT is defined for those dialects that have AFS support; it specifies
+ * that the default path to an alternate AFS kernel name list file may be
+ * supplied with the -A <path> option.
+ */
+
+/* #define HASAOPT 1 */
+
+
+/*
+ * HASBLKDEV is defined for those dialects that want block device information
+ * recorded in BDevtp[].
+ */
+
+#define HASBLKDEV 1
+
+
+/*
+ * HASDCACHE is defined for those dialects that support a device cache
+ * file.
+ *
+ * HASENVDC defined the name of an environment variable that contains the
+ * device cache file path. The HASENVDC environment variable is ignored when
+ * the lsof process is setuid(root) or its real UID is 0.
+ *
+ * HASPERSDC defines the format for the last component of a personal device
+ * cache file path. The first will be the home directory of the real UID that
+ * executes lsof.
+ *
+ * HASPERSDCPATH defines the environment variable whose value is the middle
+ * component of the personal device cache file path. The middle component
+ * follows the home directory and precedes the results of applying HASPERSDC.
+ * The HASPERSDCPATH environment variable is ignored when the lsof process is
+ * setuid(root) or its real UID is 0.
+ *
+ * HASSYSDC defines a public device cache file path. When it's defined, it's
+ * used as the path from which to read the device cache.
+ *
+ * Consult the 00DCACHE and 00FAQ files of the lsof distribution for more
+ * information on device cache file path construction.
+ */
+
+#define HASDCACHE 1
+#define HASENVDC "LSOFDEVCACHE"
+#define HASPERSDC "%h/%p.lsof_%L"
+#define HASPERSDCPATH "LSOFPERSDCPATH"
+/* #define HASSYSDC "/your/choice/of/path" */
+
+
+/*
+ * HASCDRNODE is defined for those dialects that have CD-ROM nodes.
+ */
+
+#define HASCDRNODE 1
+
+
+/*
+ * HASFIFONODE is defined for those dialects that have FIFO nodes.
+ */
+
+# if AIXV>=3200
+#define HASFIFONODE 1
+# endif /* AIXV>=3200 */
+
+
+/*
+ * HASFSINO is defined for those dialects that have the file system
+ * inode element, fs_ino, in the lfile structure definition in lsof.h.
+ */
+
+/* #define HASFSINO 1 */
+
+
+/*
+ * HASFSTRUCT is defined if the dialect has a file structure.
+ *
+ * FSV_DEFAULT defines the default set of file structure values to list.
+ * It defaults to zero (0), but may be made up of a combination of the
+ * FSV_* symbols from lsof.h.
+ *
+ * HASNOFSADDR -- has no file structure address
+ * HASNOFSFLAGS -- has no file structure flags
+ * HASNOFSCOUNT -- has no file structure count
+ * HASNOFSNADDR -- has no file structure node address
+ */
+
+#define HASFSTRUCT 1
+/* #define FSV_DEFAULT FSV_? | FSV_? | FSV_? */
+/* #define HASNOFSADDR 1 has no file structure address */
+/* #define HASNOFSFLAGS 1 has no file structure flags */
+/* #define HASNOFSCOUNT 1 has no file structure count */
+/* #define HASNOFSNADDR 1 has no file structure node address */
+
+
+/*
+ * HASGNODE is defined for those dialects that have gnodes.
+ */
+
+#define HASGNODE 1
+
+
+/*
+ * HASHSNODE is defined for those dialects that have High Sierra nodes.
+ */
+
+/* #define HASHSNODE 1 */
+
+
+/*
+ * HASINODE is defined for those dialects that have inodes and wish to
+ * use readinode() from node.c.
+ */
+
+#define HASINODE 1
+
+
+/*
+ * HASINTSIGNAL is defined for those dialects whose signal function returns
+ * an int.
+ */
+
+/* #define HASINTSIGNAL 1 */
+
+
+/*
+ * HASKERNIDCK is defined for those dialects that support the comparison of
+ * the build to running kernel identity.
+ */
+
+#define HASKERNIDCK 1
+
+
+/*
+ * HASKOPT is defined for those dialects that support the -k option of
+ * reading the kernel's name list from an optional file.
+ */
+
+/* #define HASKOPT 1 */
+
+
+/*
+ * HASLFILEADD is defined for those dialects that need additional elements
+ * in struct lfile. The HASLFILEADD definition is a macro that defines
+ * them. If any of the additional elements need to be preset in the
+ * alloc_lfile() function of proc.c, the SETLFILEADD macro may be defined
+ * to do that.
+ *
+ * If any additional elements need to be cleared in alloc_lfile() or in the
+ * free_proc() function of proc.c, the CLRLFILEADD macro may be defined to
+ * do that. Note that CLRLFILEADD takes one argument, the pointer to the
+ * lfile struct. The CLRLFILEADD macro is expected to expand to statements
+ * that are complete -- i.e., have terminating semi-colons -- so the macro is
+ * called without a terminating semicolon by proc.c.
+ *
+ * The HASXOPT definition may be used to select the conditions under which
+ * private lfile elements are used.
+ */
+
+/* #define HASLFILEADD int ... */
+/* #define CLRLFILEADD(lf) (lf)->... = (type)NULL; */
+/* #define SETLFILEADD Lf->... */
+
+
+/*
+ * HASMNTSTAT indicates the dialect supports the mount stat(2) result option
+ * in its l_vfs and mounts structures.
+ */
+
+/* #define HASMNTSTAT 1 */
+
+
+/*
+ * HASMNTSUP is defined for those dialects that support the mount supplement
+ * option.
+ */
+
+/* #define HASMNTSUP 1 */
+
+
+/*
+ * HASMOPT is defined for those dialects that support the reading of
+ * kernel memory from an alternate file.
+ */
+
+#define HASMOPT 1
+
+
+/*
+ * HASNCACHE is defined for those dialects that have a kernel name cache
+ * that lsof can search. A value of 1 directs printname() to prefix the
+ * cache value with the file system directory name; 2, avoid the prefix.
+ *
+ * NCACHELDPFX is a set of C commands to execute before calling ncache_load().
+ *
+ * NCACHELDSFX is a set of C commands to execute after calling ncache_load().
+ */
+
+/* #define HASNCACHE 1 */
+/* #define NCACHELDPFX ??? */
+/* #define NCACHELDSFX ??? */
+
+
+/*
+ * HASNLIST is defined for those dialects that use nlist() to acccess
+ * kernel symbols. (AIX lsof doesn't use nlist, it uses knlist.)
+ */
+
+/* #define HASNLIST 1 */
+
+
+/*
+ * HASPIPEFN is defined for those dialects that have a special function to
+ * process DTYPE_PIPE file structure entries. Its value is the name of the
+ * function.
+ *
+ * NOTE: don't forget to define a prototype for this function in dproto.h.
+ */
+
+/* #define HASPIPEFN process_pipe? */
+
+
+/*
+ * HASPIPENODE is defined for those dialects that have pipe nodes.
+ */
+
+/* #define HASPIPENODE 1 */
+
+
+/*
+ * HASPMAPENABLED is defined when the reporting of portmapper registration
+ * info is enabled by default.
+ */
+
+/* #define HASPMAPENABLED 1 */
+
+
+/*
+ * HASPPID is defined for those dialects that support identification of
+ * the parent process IDentifier (PPID) of a process.
+ */
+
+#define HASPPID 1
+
+
+/*
+ * HASPRINTDEV, HASPRINTINO, HASPRINTNM, HASPRINTOFF, and HASPRINTSZ
+ * define private dialect-specific functions for printing DEVice numbers,
+ * INOde numbers, NaMes, file OFFsets, and file SiZes. The functions are
+ * called from print_file().
+ */
+
+#define HASPRINTDEV print_dev
+/* #define HASPRINTINO print_ino? */
+/* #define HASPRINTNM print_nm? */
+/* #define HASPRINTOFF print_off? */
+/* #define HASPRINTSZ print_sz? */
+
+
+/*
+ * HASPRIVFILETYPE and PRIVFILETYPE are defined for dialects that have a
+ * file structure type that isn't defined by a DTYPE_* symbol. They are
+ * used in lib/prfp.c to select the type's processing.
+ *
+ * PRIVFILETYPE is the definition of the f_type value in the file struct.
+ *
+ * HASPRIVFILETYPE is the name of the processing function.
+ */
+
+# if AIXV>=4140
+#define HASPRIVFILETYPE process_shmt
+#define PRIVFILETYPE 15
+# endif /* AIXV>=4140 */
+
+
+/*
+ * HASPRIVNMCACHE is defined for dialects that have a private method for
+ * printing cached NAME column values for some files. HASPRIVNAMECACHE
+ * is defined to be the name of the function.
+ *
+ * The function takes one argument, a struct lfile pointer to the file, and
+ * returns non-zero if it prints a name to stdout.
+ */
+
+/* #define HASPRIVNMCACHE <function name> */
+
+
+/*
+ * HASPRIVPRIPP is defined for dialects that have a private function for
+ * printing IP protocol names. When HASPRIVPRIPP isn't defined, the
+ * IP protocol name printing function defaults to printiprto().
+ */
+
+/* #define HASPRIVPRIPP 1 */
+
+
+/*
+ * HASPROCFS is defined for those dialects that have a proc file system --
+ * usually /proc and usually in SYSV4 derivatives.
+ *
+ * HASFSTYPE is defined as 1 for those systems that have a file system type
+ * string, st_fstype, in the stat() buffer; 2, for those systems that have a
+ * file system type integer in the stat() buffer, named MOUNTS_STAT_FSTYPE;
+ * 0, for systems whose stat(2) structure has no file system type member. The
+ * additional symbols MOUNTS_FSTYPE, RMNT_FSTYPE, and RMNT_STAT_FSTYPE may be
+ * defined in dlsof.h to direct how the readmnt() function in lib/rmnt.c
+ * preserves these stat(2) and getmntent(3) buffer values in the local mounts
+ * structure.
+ *
+ * The defined value is the string that names the file system type.
+ *
+ * The HASPROCFS definition usually must be accompanied by the HASFSTYPE
+ * definition and the providing of an fstype element in the local mounts
+ * structure (defined in dlsof.h).
+ *
+ * The HASPROCFS definition may be accompanied by the HASPINODEN definition.
+ * HASPINODEN specifies that searching for files in HASPROCFS is to be done
+ * by inode number.
+ */
+
+# if AIXA<1
+/* #define HASPROCFS "proc?" */
+/* #define HASFSTYPE 1 */
+/* #define HASPINODEN 1 */
+# else /* AIXA>=1 */
+#define HASPROCFS "proc"
+#define HASFSTYPE 2
+#define HASPINODEN 1
+# endif /* AIXA<1 */
+
+
+/*
+ * HASRNODE is defined for those dialects that have rnodes.
+ *
+ * Note: while AIX has rnodes, they are processed privately, so this
+ * definition should be disabled.
+ */
+
+/* #define HASRNODE 1 */
+
+
+/*
+ * Define HASSECURITY to restrict the listing of all open files to the
+ * root user. When HASSECURITY is defined, the non-root user may list
+ * only files whose processes have the same user ID as the real user ID
+ * (the one that its user logged on with) of the lsof process.
+ */
+
+/* #define HASSECURITY 1 */
+
+
+/*
+ * If HASSECURITY is defined, define HASNOSOCKSECURITY to allow users
+ * restricted by HASSECURITY to list any open socket files, provide their
+ * listing is selected by the "-i" option.
+ */
+
+/* #define HASNOSOCKSECURITY 1 */
+
+
+/*
+ * HASSETLOCALE is defined for those dialects that have <locale.h> and
+ * setlocale().
+ *
+ * If the dialect also has wide character support for language locales,
+ * HASWIDECHAR activates lsof's wide character support and WIDECHARINCL
+ * defines the header file (if any) that must be #include'd to use the
+ * mblen() and mbtowc() functions.
+ */
+
+#define HASSETLOCALE 1
+
+# if AIXV>=4320
+#define HASWIDECHAR 1
+# endif /* AIXV>=4320 */
+
+/* #define WIDECHARINCL <wchar.h> */
+
+
+/*
+ * HASSNODE is defined for those dialects that have snodes.
+ */
+
+/* #define HASSNODE 1 */
+
+
+/*
+ * HASTASKS is defined for those dialects that have task reporting support.
+ */
+
+/* #define HASTASKS 1 */
+
+
+/*
+ * HASSOOPT, HASSOSTATE and HASTCPOPT define the availability of information
+ * on socket options (SO_* symbols), socket states (SS_* symbols) and TCP
+ * options.
+ */
+
+#define HASSOOPT 1 /* has socket option information */
+#define HASSOSTATE 1 /* has socket state information */
+#define HASTCPOPT 1 /* has TCP options or flags */
+
+
+/*
+ * Define HASSPECDEVD to be the name of a function that handles the results
+ * of a successful stat(2) of a file name argument.
+ *
+ * For example, HASSPECDEVD() for Darwin makes sure that st_dev is set to
+ * what stat("/dev") returns -- i.e., what's in DevDev.
+ *
+ * The function takes two arguments:
+ *
+ * 1: pointer to the full path name of file
+ * 2: pointer to the stat(2) result
+ *
+ * The function returns void.
+ */
+
+/* #define HASSPECDEVD process_dev_stat */
+
+
+/*
+ * HASSTREAMS is defined for those dialects that support streams.
+ */
+
+/* #define HASSTREAMS 1 */
+
+
+/*
+ * HASTCPTPIQ is defined for dialects where it is possible to report the
+ * TCP/TPI Recv-Q and Send-Q values produced by netstat.
+ */
+
+#define HASTCPTPIQ 1
+
+
+/*
+ * HASTCPTPIW is defined for dialects where it is possible to report the
+ * TCP/TPI send and receive window sizes produced by netstat.
+ */
+
+/* #define HASTCPTPIW 1 */
+
+
+/*
+ * HASTCPUDPSTATE is defined for dialects that have TCP and UDP state
+ * support -- i.e., for the "-stcp|udp:state" option and its associated
+ * speed improvements.
+ */
+
+#define HASTCPUDPSTATE 1
+
+
+/*
+ * HASTMPNODE is defined for those dialects that have tmpnodes.
+ */
+
+/* #define HASTMPNODE 1 */
+
+
+/*
+ * HASVNODE is defined for those dialects that use the Sun virtual file
+ * system node, the vnode. BSD derivatives usually do; System V derivatives
+ * prior to R4 usually don't.
+ */
+
+#define HASVNODE 1
+
+
+/*
+ * HASXOPT is defined for those dialects that have an X option. It
+ * defines the text for the usage display. HASXOPT_VALUE defines the
+ * option's default binary value -- 0 or 1.
+ *
+ * AIX uses the X option to disable the use of the readx() kernel function
+ * on request.
+ *
+ * If you want to disable the use of readx() permanently, leave HASXOPT
+ * undefined and set HASXOPT_VALUE to 0. To enable readx() permanently,
+ * leave HASXOPT undefined and set HASXOPT_VALUE to 1.
+ *
+ * Define HASXOPT_ROOT if you want to restrict the use of the X option to
+ * processes whose real UID is root.
+ */
+
+#define HASXOPT "use readx() *RISKY*"
+/* #define HASXOPT_ROOT 1 */
+#define HASXOPT_VALUE 0
+
+
+/*
+ * INODETYPE and INODEPSPEC define the internal node number type and its
+ * printf specification modifier. These need not be defined and lsof.h
+ * can be allowed to define defaults.
+ *
+ * These are defined here, because they must be used in dlsof.h.
+ */
+
+# if AIXV>=4200
+#define INODETYPE unsigned long long
+ /* inode number internal storage type */
+#define INODEPSPEC "ll" /* INODETYPE printf specification
+ * modifier */
+# endif /* AIXV>=4200 */
+
+
+/*
+ * UID_ARG defines the size of a User ID number when it is passed
+ * as a function argument.
+ */
+
+#define UID_ARG uid_t
+
+
+/*
+ * Each USE_LIB_<function_name> is defined for dialects that use the
+ * <function_name> in the lsof library.
+ *
+ * Note: other definitions and operations may be required to condition the
+ * library function source code. They may be found in the dialect dlsof.h
+ * header files.
+ */
+
+/* #define USE_LIB_CKKV 1 ckkv.c */
+/* #define USE_LIB_COMPLETEVFS 1 cvfs.c */
+#define USE_LIB_FIND_CH_INO 1 /* fino.c */
+/* #define USE_LIB_IS_FILE_NAMED 1 isfn.c */
+#define USE_LIB_LKUPDEV 1 /* lkud.c */
+/* #define USE_LIB_PRINTDEVNAME 1 pdvn.c */
+#define USE_LIB_PROCESS_FILE 1 /* prfp.c */
+#define USE_LIB_PRINT_TCPTPI 1 /* ptti.c */
+/* #define USE_LIB_READDEV 1 rdev.c */
+/* #define USE_LIB_READMNT 1 rmnt.c */
+/* #define USE_LIB_REGEX 1 regex.c */
+/* #define USE_LIB_RNAM 1 rnam.c */
+/* #define USE_LIB_RNCH 1 rnch.c */
+/* #define USE_LIB_RNMH 1 rnmh.c */
+/* #define USE_LIB_SNPF 1 snpf.c */
+#define snpf snprintf /* use the system's snprintf() */
+
+
+/*
+ * WARNDEVACCESS is defined for those dialects that should issue a warning
+ * when lsof can't access /dev (or /device) or one of its sub-directories.
+ * The warning can be inhibited by the lsof caller with the -w option.
+ */
+
+#define WARNDEVACCESS 1
+
+
+/*
+ * WARNINGSTATE is defined for those dialects that want to suppress all lsof
+ * warning messages.
+ */
+
+/* #define WARNINGSTATE 1 warnings are enabled by default */
+
+
+/*
+ * WILLDROPGID is defined for those dialects whose lsof executable runs
+ * setgid(not_real_GID) and whose setgid power can be relinquished after
+ * the dialect's initialize() function has been executed.
+ */
+
+#define WILLDROPGID 1
+
+
+/*
+ * zeromem is a macro that uses bzero or memset.
+ */
+
+#define zeromem(a, l) bzero(a, l)
+
+#endif /* !defined(LSOF_MACHINE_H) */
diff --git a/dialects/darwin/get-hdr-loc.sh b/dialects/darwin/get-hdr-loc.sh
new file mode 100755
index 0000000..c0d9880
--- /dev/null
+++ b/dialects/darwin/get-hdr-loc.sh
@@ -0,0 +1,119 @@
+#!/bin/sh
+#
+# get-hdr-loc.sh -- get Darwin XNU kernel header file location
+#
+# Interactively requests the specification of the path to the host's Darwin
+# XNU kernel header files. Checks that path and returns it to the caller.
+#
+# Usage: file1 file2 ... fileN
+#
+# Where: file1 first header file needed
+# file2 second header file needed
+# ...
+# fileN last header file needed
+#
+# Exit:
+#
+# Exit code: 0 if path found; path returned on STDOUT
+#
+# 1 if path not found: error message returned
+# on STDOUT
+#
+#set -x # for DEBUGging
+
+# Check argument count. There must be at least one argument.
+
+if test $# -lt 1 # {
+then
+ echo "insufficient arguments: $#"
+ exit 1
+fi # }
+lst=$*
+
+# Request the path to the Darwin XNU kernel header files.
+
+trap 'stty echo; echo interrupted; exit 1' 1 2 3 15
+FOREVER=1
+while test $FOREVER -ge 1 # {
+do
+ if test $FOREVER -eq 1 # {
+ then
+ echo "---------------------------------------------------------------" 1>&2
+ echo "" 1>&2
+ echo "Lsof cannot find some Darwin XNU kernel header files it needs." 1>&2
+ echo "They should have already been downloaded from:" 1>&2
+ echo "" 1>&2
+ echo " http://www.opensource.apple.com/darwinsource/index.html" 1>&2
+ echo "" 1>&2
+ echo "and then installed. (See 00FAQ for download and installation" 1>&2
+ echo "instructions.)" 1>&2
+ echo "" 1>&2
+ echo "Please specify the path to the place where they were installed." 1>&2
+ echo "" 1>&2
+ echo "---------------------------------------------------------------" 1>&2
+ fi # }
+
+ END=0
+ while test $END = 0 # {
+ do
+ echo "" 1>&2
+ echo -n "What is the path? " 1>&2
+ read HP EXCESS
+ HP=`echo echo $HP | /bin/csh -fs`
+ if test $? -eq 0 # {
+ then
+ if test "X$HP" = "X" # {
+ then
+ echo "" 1>&2
+ echo "+================================+" 1>&2
+ echo "| Please enter a non-empty path. |" 1>&2
+ echo "+================================+" 1>&2
+ echo "" 1>&2
+ else
+ END=1
+ fi # }
+ else
+ echo "" 1>&2
+ echo "+============================+" 1>&2
+ echo "| Please enter a legal path. |" 1>&2
+ echo "+============================+" 1>&2
+ echo "" 1>&2
+ fi # }
+ done # }
+
+ # See if the header files are available in the specified path.
+
+ MH=""
+ for i in $lst # {
+ do
+ if test ! -f ${HP}/bsd/$i -a ! -f ${HP}/osfmk/$i # {
+ then
+ if test "X$MH" = "X" # {
+ then
+ MH=$i
+ else
+ MH="$MH $i"
+ fi # }
+ fi # }
+ done # }
+ if test "X$MH" = "X" # {
+ then
+
+ # All header files are available, so return the path and exit cleanly.
+
+ echo $HP
+ exit 0
+ else
+ echo "" 1>&2
+ echo "ERROR: not all header files are in:" 1>&2
+ echo "" 1>&2
+ echo " ${HP}" 1>&2
+ echo "" 1>&2
+ echo " These are missing:" 1>&2
+ echo "" 1>&2
+ echo " $MH" 1>&2
+ FOREVER=2
+ fi # }
+done # }
+echo "unknown error"
+exit 1
diff --git a/dialects/darwin/kmem/Makefile b/dialects/darwin/kmem/Makefile
new file mode 100644
index 0000000..47ebfee
--- /dev/null
+++ b/dialects/darwin/kmem/Makefile
@@ -0,0 +1,171 @@
+
+# Darwin /dev/kmem-based lsof Makefile
+#
+# $Id: Makefile,v 1.8 2008/10/21 16:15:34 abe Exp $
+
+PROG= lsof
+
+BIN= ${DSTROOT}/usr/sbin
+
+DOC= ${DSTROOT}/usr/share/man/man8
+
+I=/usr/include
+S=/usr/include/sys
+L=/usr/include/local
+P=
+
+CDEF= ${RC_CFLAGS}
+CDEFS= ${CDEF} ${CFGF}
+INCL= ${DINC}
+override CFLAGS= ${CDEFS} ${INCL} ${DEBUG}
+
+GRP=
+
+HDR= lsof.h lsof_fields.h dlsof.h machine.h proto.h dproto.h
+
+SRC= ddev.c dfile.c dmnt.c dnode.c dnode1.c dproc.c dsock.c dstore.c \
+ arg.c main.c misc.c node.c print.c proc.c store.c usage.c util.c
+
+OBJ= ddev.o dfile.o dmnt.o dnode.o dnode1.o dproc.o dsock.o dstore.o \
+ arg.o main.o misc.o node.o print.o proc.o store.o usage.o util.o
+
+MAN= lsof.8
+
+OTHER=
+
+SHELL= /bin/sh
+
+SOURCE= Makefile ${OTHER} ${MAN} ${HDR} ${SRC}
+
+all: ${PROG}
+
+${PROG}: ${LIB} ${P} ${OBJ}
+ ${CC} -o $@ ${CFLAGS} ${OBJ} ${CFGL}
+
+clean: FRC
+ rm -f Makefile.bak ${PROG} a.out core errs lint.out tags *.o version.h
+ rm -f machine.h.old new_machine.h
+ (cd lib; ${MAKE} -f Makefile.skel clean)
+
+install-strip: all FRC
+ mkdir -p ${BIN}
+ install -c -s -m 2755 -g kmem ${PROG} ${BIN}
+ mkdir -p ${DOC}
+ install -c -m 444 ${MAN} ${DOC}
+
+install: all FRC
+ @echo ''
+ @echo 'Please write your own install rule. Lsof for Darwin below 8'
+ @echo 'should be installed setgid to the group that has permission'
+ @echo 'to read /dev/kmem, often kmem or sys. Lsof for Darwin 8 and'
+ @echo 'above should be installed setuid-root. Your install rule'
+ @echo 'actions for Darwin below 8 might look something like this:'
+ @echo ''
+ @echo ' install -m 2xxx -g $${GRP} $${PROG} $${BIN}'
+ @echo ' install -m 444 $${MAN} $${DOC}'
+ @echo ''
+ @echo 'Your install rule actions for Darwin 8 and above might look'
+ @echo 'something like this:'
+ @echo ''
+ @echo ' install -m 4xxx -o root $${PROG} $${BIN}'
+ @echo ' install -m 444 $${MAN} $${DOC}'
+ @echo ''
+ @echo 'You will have to complete the xxx modes, the GRP value, and'
+ @echo 'the skeletons for the BIN and DOC strings, given at the'
+ @echo 'beginning of this Makefile, e.g.,'
+ @echo ''
+ @echo ' BIN= $${DESTDIR}/usr/local/etc'
+ @echo ' DOC= $${DESTDIR}/usr/man/man8'
+ @echo ' GRP= kmem'
+ @echo ''
+
+${LIB}: FRC
+ (cd lib; ${MAKE} DEBUG="${DEBUG}" CFGF="${CFGF}")
+
+version.h: FRC
+ @echo Constructing version.h
+ @rm -f version.h
+ @echo '#define LSOF_BLDCMT "${LSOF_BLDCMT}"' > version.h;
+ @echo '#define LSOF_CC "${CC}"' >> version.h
+ @echo '#define LSOF_CCV "${CCV}"' >> version.h
+ @echo '#define LSOF_CCDATE "'`date`'"' >> version.h
+ @echo '#define LSOF_CCFLAGS "'`echo ${CFLAGS} | sed 's/\\\\(/\\(/g' | sed 's/\\\\)/\\)/g' | sed 's/"/\\\\"/g'`'"' >> version.h
+ @echo '#define LSOF_CINFO "${CINFO}"' >> version.h
+ @if [ "X${LSOF_HOST}" = "X" ]; then \
+ echo '#define LSOF_HOST "'`uname -n`'"' >> version.h; \
+ else \
+ if [ "${LSOF_HOST}" = "none" ]; then \
+ echo '#define LSOF_HOST ""' >> version.h; \
+ else \
+ echo '#define LSOF_HOST "${LSOF_HOST}"' >> version.h; \
+ fi \
+ fi
+ @echo '#define LSOF_LDFLAGS "${CFGL}"' >> version.h
+ @if [ "X${LSOF_LOGNAME}" = "X" ]; then \
+ echo '#define LSOF_LOGNAME "${LOGNAME}"' >> version.h; \
+ else \
+ if [ "${LSOF_LOGNAME}" = "none" ]; then \
+ echo '#define LSOF_LOGNAME ""' >> version.h; \
+ else \
+ echo '#define LSOF_LOGNAME "${LSOF_LOGNAME}"' >> version.h; \
+ fi; \
+ fi
+ @if [ "X${LSOF_SYSINFO}" = "X" ]; then \
+ echo '#define LSOF_SYSINFO "'`uname -a`'"' >> version.h; \
+ else \
+ if [ "${LSOF_SYSINFO}" = "none" ]; then \
+ echo '#define LSOF_SYSINFO ""' >> version.h; \
+ else \
+ echo '#define LSOF_SYSINFO "${LSOF_SYSINFO}"' >> version.h; \
+ fi \
+ fi
+ @if [ "X${LSOF_USER}" = "X" ]; then \
+ echo '#define LSOF_USER "${USER}"' >> version.h; \
+ else \
+ if [ "${LSOF_USER}" = "none" ]; then \
+ echo '#define LSOF_USER ""' >> version.h; \
+ else \
+ echo '#define LSOF_USER "${LSOF_USER}"' >> version.h; \
+ fi \
+ fi
+ @sed '/VN/s/.ds VN \(.*\)/#define LSOF_VERSION "\1"/' < version >> version.h
+
+FRC:
+
+# DO NOT DELETE THIS LINE - make depend DEPENDS ON IT
+
+ddev.o: ${HDR} ddev.c
+
+dfile.o: ${HDR} dfile.c
+
+dmnt.o: ${HDR} dmnt.c
+
+dnode.o: ${HDR} dnode.c
+
+dnode1.o: ${HDR} dnode1.c
+
+dproc.o: ${HDR} dproc.c
+
+dsock.o: ${HDR} dsock.c
+
+dstore.o: ${HDR} dstore.c
+
+arg.o: ${HDR} arg.c
+
+main.o: ${HDR} main.c
+
+misc.o: ${HDR} misc.c
+
+node.o: ${HDR} node.c
+
+print.o: ${HDR} print.c
+
+proc.o: ${HDR} proc.c
+
+store.o: ${HDR} store.c
+
+usage.o: ${HDR} version.h usage.c
+
+util.o: ${HDR} util.c
+
+# *** Do not add anything here - It will go away. ***
diff --git a/dialects/darwin/kmem/Mksrc b/dialects/darwin/kmem/Mksrc
new file mode 100755
index 0000000..e576427
--- /dev/null
+++ b/dialects/darwin/kmem/Mksrc
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Mksrc - make Darwin /dev/kmem-based lsof source files
+#
+# WARNING: This script assumes it is running from the main directory
+# of the lsof, version 4 distribution.
+#
+# One environment variable applies:
+#
+# LSOF_MKC is the method for creating the source files.
+# It defaults to "ln -s". A common alternative is "cp".
+#
+# $Id: Mksrc,v 1.5 2006/03/27 23:24:50 abe Exp $
+
+
+D=dialects/darwin/kmem
+L="dlsof.h ddev.c dfile.c dmnt.c dnode.c dnode1.c dproc.c dproto.h dsock.c dstore.c machine.h"
+
+for i in $L
+do
+ rm -f $i
+ $LSOF_MKC $D/$i $i
+ echo "$LSOF_MKC $D/$i $i"
+done
diff --git a/dialects/darwin/kmem/ddev.c b/dialects/darwin/kmem/ddev.c
new file mode 100644
index 0000000..fc6ce28
--- /dev/null
+++ b/dialects/darwin/kmem/ddev.c
@@ -0,0 +1,479 @@
+/*
+ * ddev.c - Darwin device support functions for /dev/kmem-based lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: ddev.c,v 1.5 2006/03/27 23:24:50 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+/*
+ * Local definitions
+ */
+
+#if defined(DVCH_DEVPATH)
+#define DDEV_DEVPATH DVCH_DEVPATH
+#else /* !defined(DVCH_DEVPATH) */
+#define DDEV_DEVPATH "/dev"
+#endif /* defined(DVCH_DEVPATH) */
+
+#if defined(USE_STAT)
+#define STATFN stat
+#else /* !defined(USE_STAT) */
+#define STATFN lstat
+#endif /* defined(USE_STAT) */
+
+
+/*
+ * Local static variables.
+ */
+
+static dev_t *ADev = (dev_t *) NULL; /* device numbers besides DevDev found
+ * inside DDEV_DEVPATH */
+static int ADevA = 0; /* entries allocated to ADev[] */
+static int ADevU = 0; /* entries used in ADev[] */
+
+
+/*
+ * Local function prototypes
+ */
+
+_PROTOTYPE(static int rmdupdev,(struct l_dev ***dp, int n, char *nm));
+_PROTOTYPE(static void saveADev,(struct stat *s));
+
+
+#if defined(HASSPECDEVD)
+/*
+ * HASSPECDEVD() -- process stat(2) result to see if the device number is
+ * inside DDEV_DEVPATH "/"
+ *
+ * exit: s->st_dev changed to DevDev, as required
+ */
+
+void
+HASSPECDEVD(p, s)
+ char *p; /* file path */
+ struct stat *s; /* stat(2) result for file */
+{
+ int i;
+
+ switch (s->st_mode & S_IFMT) {
+ case S_IFCHR:
+ case S_IFBLK:
+ if (s->st_dev == DevDev)
+ return;
+ (void) readdev(0);
+ if (!ADev)
+ return;
+ for (i = 0; i < ADevU; i++) {
+ if (s->st_dev == ADev[i]) {
+ s->st_dev = DevDev;
+ return;
+ }
+ }
+ }
+}
+#endif /* defined(HASSPECDEVD) */
+
+
+/*
+ * readdev() - read device names, modes and types
+ */
+
+void
+readdev(skip)
+ int skip; /* skip device cache read if 1 --
+ * ignored since device cache not
+ * used */
+{
+ DIR *dfp;
+ int dnamlen;
+ struct dirent *dp;
+ char *fp = (char *)NULL;
+ char *path = (char *)NULL;
+ int i = 0;
+ int j = 0;
+ MALLOC_S pl, sz;
+ struct stat sb;
+/*
+ * Read device names but once.
+ */
+ if (Sdev)
+ return;
+/*
+ * Prepare to scan DDEV_DEVPATH.
+ */
+ Dstkn = Dstkx = 0;
+ Dstk = (char **)NULL;
+ (void) stkdir(DDEV_DEVPATH);
+/*
+ * Unstack the next directory.
+ */
+ while (--Dstkx >= 0) {
+ if (!(dfp = OpenDir(Dstk[Dstkx]))) {
+
+# if defined(WARNDEVACCESS)
+ if (!Fwarn) {
+ (void) fprintf(stderr, "%s: WARNING: can't open: ", Pn);
+ safestrprt(Dstk[Dstkx], stderr, 1);
+ }
+# endif /* defined(WARNDEVACCESS) */
+
+ (void) free((FREE_P *)Dstk[Dstkx]);
+ Dstk[Dstkx] = (char *)NULL;
+ continue;
+ }
+ if (path) {
+ (void) free((FREE_P *)path);
+ path = (char *)NULL;
+ }
+ if (!(path = mkstrcat(Dstk[Dstkx], -1, "/", 1, (char *)NULL, -1,
+ &pl)))
+ {
+ (void) fprintf(stderr, "%s: no space for: ", Pn);
+ safestrprt(Dstk[Dstkx], stderr, 1);
+ Exit(1);
+ }
+ (void) free((FREE_P *)Dstk[Dstkx]);
+ Dstk[Dstkx] = (char *)NULL;
+ /*
+ * Scan the directory.
+ */
+ for (dp = ReadDir(dfp); dp; dp = ReadDir(dfp)) {
+ if (dp->d_ino == 0 || dp->d_name[0] == '.')
+ continue;
+ /*
+ * Form the full path name and get its status.
+ */
+ dnamlen = (int)dp->d_namlen;
+ if (fp) {
+ (void) free((FREE_P *)fp);
+ fp = (char *)NULL;
+ }
+ if (!(fp = mkstrcat(path, pl, dp->d_name, dnamlen,
+ (char *)NULL, -1, (MALLOC_S *)NULL)))
+ {
+ (void) fprintf(stderr, "%s: no space for: ", Pn);
+ safestrprt(path, stderr, 0);
+ safestrprtn(dp->d_name, dnamlen, stderr, 1);
+ Exit(1);
+ }
+ if (STATFN(fp, &sb) != 0) {
+ if (errno == ENOENT) /* a sym link to nowhere? */
+ continue;
+
+# if defined(WARNDEVACCESS)
+ if (!Fwarn) {
+ int errno_save = errno;
+
+ (void) fprintf(stderr, "%s: can't stat ", Pn);
+ safestrprt(fp, stderr, 0);
+ (void) fprintf(stderr, ": %s\n", strerror(errno_save));
+ }
+# endif /* defined(WARNDEVACCESS) */
+
+ continue;
+ }
+ /*
+ * If it's a subdirectory, stack its name for later
+ * processing.
+ */
+ if ((sb.st_mode & S_IFMT) == S_IFDIR) {
+
+ /*
+ * Skip /dev/fd.
+ */
+ if (strcmp(fp, "/dev/fd"))
+ (void) stkdir(fp);
+ continue;
+ }
+ if ((sb.st_mode & S_IFMT) == S_IFLNK) {
+
+ /*
+ * Ignore symbolic links.
+ */
+ continue;
+ }
+ if ((sb.st_mode & S_IFMT) == S_IFCHR) {
+
+ /*
+ * Save character device information in Devtp[].
+ */
+ if (i >= Ndev) {
+ Ndev += DEVINCR;
+ if (!Devtp)
+ Devtp = (struct l_dev *)malloc(
+ (MALLOC_S)(sizeof(struct l_dev)*Ndev));
+ else
+ Devtp = (struct l_dev *)realloc((MALLOC_P *)Devtp,
+ (MALLOC_S)(sizeof(struct l_dev)*Ndev));
+ if (!Devtp) {
+ (void) fprintf(stderr,
+ "%s: no space for character device\n", Pn);
+ Exit(1);
+ }
+ }
+ Devtp[i].rdev = sb.st_rdev;
+ Devtp[i].inode = (INODETYPE)sb.st_ino;
+ if (!(Devtp[i].name = mkstrcpy(fp, (MALLOC_S *)NULL))) {
+ (void) fprintf(stderr,
+ "%s: no space for device name: ", Pn);
+ safestrprt(fp, stderr, 1);
+ Exit(1);
+ }
+ Devtp[i].v = 0;
+ i++;
+ }
+
+# if defined(HASBLKDEV)
+ if ((sb.st_mode & S_IFMT) == S_IFBLK) {
+
+ /*
+ * Save block device information in BDevtp[].
+ */
+ if (j >= BNdev) {
+ BNdev += DEVINCR;
+ if (!BDevtp)
+ BDevtp = (struct l_dev *)malloc(
+ (MALLOC_S)(sizeof(struct l_dev)*BNdev));
+ else
+ BDevtp = (struct l_dev *)realloc((MALLOC_P *)BDevtp,
+ (MALLOC_S)(sizeof(struct l_dev)*BNdev));
+ if (!BDevtp) {
+ (void) fprintf(stderr,
+ "%s: no space for block device\n", Pn);
+ Exit(1);
+ }
+ }
+ BDevtp[j].name = fp;
+ fp = (char *)NULL;
+ BDevtp[j].inode = (INODETYPE)sb.st_ino;
+ BDevtp[j].rdev = sb.st_rdev;
+ BDevtp[j].v = 0;
+ j++;
+ }
+# endif /* defined(HASBLKDEV) */
+
+ /*
+ * Save a possible new st_dev number within DDEV_DEVPATH.
+ */
+ if (sb.st_dev != DevDev)
+ (void) saveADev(&sb);
+ }
+ (void) CloseDir(dfp);
+ }
+/*
+ * Free any unneeded space that was allocated.
+ */
+ if (ADev && (ADevU < ADevA)) {
+
+ /*
+ * Reduce space allocated to additional DDEV_DEVPATH device numbers.
+ */
+ if (!ADevU) {
+
+ /*
+ * If no space was used, free the entire allocation.
+ */
+ (void) free((FREE_P *)ADev);
+ ADev = (dev_t *)NULL;
+ ADevA = 0;
+ } else {
+
+ /*
+ * Reduce the allocation to what was used.
+ */
+ sz = (MALLOC_S)(ADevU * sizeof(dev_t));
+ if (!(ADev = (dev_t *)realloc((MALLOC_P *)ADev, sz))) {
+ (void) fprintf(stderr, "%s: can't reduce ADev[]\n", Pn);
+ Exit(1);
+ }
+ }
+ }
+ if (!Dstk) {
+ (void) free((FREE_P *)Dstk);
+ Dstk = (char **)NULL;
+ }
+ if (fp)
+ (void) free((FREE_P *)fp);
+ if (path)
+ (void) free((FREE_P *)path);
+
+# if defined(HASBLKDEV)
+/*
+ * Reduce the BDevtp[] (optional) and Devtp[] tables to their minimum
+ * sizes; allocate and build sort pointer lists; and sort the tables by
+ * device number.
+ */
+ if (BNdev) {
+ if (BNdev > j) {
+ BNdev = j;
+ BDevtp = (struct l_dev *)realloc((MALLOC_P *)BDevtp,
+ (MALLOC_S)(sizeof(struct l_dev) * BNdev));
+ }
+ if (!(BSdev = (struct l_dev **)malloc(
+ (MALLOC_S)(sizeof(struct l_dev *) * BNdev))))
+ {
+ (void) fprintf(stderr,
+ "%s: no space for block device sort pointers\n", Pn);
+ Exit(1);
+ }
+ for (j = 0; j < BNdev; j++) {
+ BSdev[j] = &BDevtp[j];
+ }
+ (void) qsort((QSORT_P *)BSdev, (size_t)BNdev,
+ (size_t)sizeof(struct l_dev *), compdev);
+ BNdev = rmdupdev(&BSdev, BNdev, "block");
+ }
+
+# if !defined(NOWARNBLKDEV)
+ else {
+ if (!Fwarn)
+ (void) fprintf(stderr,
+ "%s: WARNING: no block devices found\n", Pn);
+ }
+# endif /* !defined(NOWARNBLKDEV) */
+# endif /* defined(HASBLKDEV) */
+
+ if (Ndev) {
+ if (Ndev > i) {
+ Ndev = i;
+ Devtp = (struct l_dev *)realloc((MALLOC_P *)Devtp,
+ (MALLOC_S)(sizeof(struct l_dev) * Ndev));
+ }
+ if (!(Sdev = (struct l_dev **)malloc(
+ (MALLOC_S)(sizeof(struct l_dev *) * Ndev))))
+ {
+ (void) fprintf(stderr,
+ "%s: no space for character device sort pointers\n", Pn);
+ Exit(1);
+ }
+ for (i = 0; i < Ndev; i++) {
+ Sdev[i] = &Devtp[i];
+ }
+ (void) qsort((QSORT_P *)Sdev, (size_t)Ndev,
+ (size_t)sizeof(struct l_dev *), compdev);
+ Ndev = rmdupdev(&Sdev, Ndev, "char");
+ } else {
+ (void) fprintf(stderr, "%s: no character devices found\n", Pn);
+ Exit(1);
+ }
+}
+
+
+/*
+ * rmdupdev() - remove duplicate (major/minor/inode) devices
+ */
+
+static int
+rmdupdev(dp, n, nm)
+ struct l_dev ***dp; /* device table pointers address */
+ int n; /* number of pointers */
+ char *nm; /* device table name for error message */
+{
+ int i, j, k;
+ struct l_dev **p;
+
+ for (i = j = 0, p = *dp; i < n ;) {
+ for (k = i + 1; k < n; k++) {
+ if (p[i]->rdev != p[k]->rdev || p[i]->inode != p[k]->inode)
+ break;
+ }
+ if (i != j)
+ p[j] = p[i];
+ j++;
+ i = k;
+ }
+ if (n == j)
+ return(n);
+ if (!(*dp = (struct l_dev **)realloc((MALLOC_P *)*dp,
+ (MALLOC_S)(j * sizeof(struct l_dev *)))))
+ {
+ (void) fprintf(stderr, "%s: can't realloc %s device pointers\n",
+ Pn, nm);
+ Exit(1);
+ }
+ return(j);
+}
+
+
+/*
+ * saveADev() - save additional device number appearing inside DDEV_DEVPATH
+ */
+
+static void
+saveADev(s)
+ struct stat *s; /* stat(2) buffer for file */
+{
+ int i;
+ MALLOC_S sz;
+/*
+ * Process VCHR files.
+ *
+ * Optionally process VBLK files.
+ */
+
+#if defined(HASBLKDEV)
+ if (((s->st_mode & S_IFMT) != S_IFBLK)
+ && ((s->st_mode & S_IFMT) != S_IFCHR))
+#else /* !defined(HASBLKDEV) */
+ if ((s->st_mode & S_IFCHR) != S_IFCHR)
+#endif /* defined(HASBLKDEV) */
+
+ return;
+/*
+ * See if this is a new VBLK or VCHR st_dev value for ADev[].
+ */
+ for (i = 0; i < ADevU; i++) {
+ if (s->st_dev == ADev[i])
+ return;
+ }
+/*
+ * This is a new device number to add to ADev[].
+ */
+ if (ADevU >= ADevA) {
+ ADevA += 16;
+ sz = (MALLOC_S)(ADevA * sizeof(dev_t));
+ if (ADev)
+ ADev = (dev_t *)realloc((MALLOC_P *)ADev, sz);
+ else
+ ADev = (dev_t *)malloc(sz);
+ if (!ADev) {
+ (void) fprintf(stderr, "%s: no space for ADev[]\n", Pn);
+ Exit(1);
+ }
+ }
+ ADev[ADevU++] = s->st_dev;
+}
diff --git a/dialects/darwin/kmem/dfile.c b/dialects/darwin/kmem/dfile.c
new file mode 100644
index 0000000..e1b23a7
--- /dev/null
+++ b/dialects/darwin/kmem/dfile.c
@@ -0,0 +1,390 @@
+/*
+ * dfile.c - Darwin file processing functions for /dev/kmem-based lsof
+ */
+
+
+/*
+ * Copyright 2005 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 2005 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id$";
+#endif
+
+
+#include "lsof.h"
+
+
+/*
+ * Local definitions
+ */
+
+#if DARWINV>=800
+#define file fileglob
+#define f_flag fg_flag
+#define f_type fg_type
+#define f_count fg_count
+#define f_ops fg_ops
+#define f_offset fg_offset
+#define f_data fg_data
+#endif /* DARWINV>=800 */
+
+#if defined(HASPSXSEM)
+#define PSEMNAMLEN 31 /* from kern/posix_sem.c */
+#endif /* defined(HASPSXSEM) */
+
+#if defined(HASPSXSHM)
+#define PSHMNAMLEN 31 /* from kern/posix_shm.c */
+#endif /* defined(HASPSXSHM) */
+
+
+/*
+ * Local structure definitions
+ */
+
+#if defined(HASPSXSEM)
+struct pseminfo { /* from kern/posix_sem.c */
+ unsigned int psem_flags;
+ unsigned int psem_usecount;
+ mode_t psem_mode;
+ uid_t psem_uid;
+ gid_t psem_gid;
+ char psem_name[PSEMNAMLEN + 1];
+ void *psem_semobject;
+ struct proc *sem_proc;
+};
+
+struct psemnode {
+ struct pseminfo *pinfo;
+};
+#endif /* defined(HASPSXSEM) */
+
+#if defined(HASPSXSHM) /* from kern/posix_shm.c */
+struct pshminfo {
+ unsigned int pshm_flags;
+ unsigned int pshm_usecount;
+ off_t pshm_length;
+ mode_t pshm_mode;
+ uid_t pshm_uid;
+ gid_t pshm_gid;
+ char pshm_name[PSHMNAMLEN + 1];
+ void *pshm_memobject;
+};
+
+struct pshmnode {
+ off_t mapp_addr;
+
+# if DARWINV<800
+ size_t map_size;
+# else /* DARWINV>=800 */
+ user_size_t map_size;
+# endif /* DARWINV>=800 */
+
+ struct pshminfo *pinfo;
+};
+#endif /* defined(HASPSXSHM) */
+
+
+#if DARWINV>=800
+/*
+ * print_v_path() - print vnode's path
+ */
+
+int
+print_v_path(lf)
+ struct lfile *lf;
+{
+ if (lf->V_path) {
+ safestrprt(lf->V_path, stdout, 0);
+ return(1);
+ }
+ return(0);
+}
+#endif /* DARWINV>=800 */
+
+
+#if defined(HASKQUEUE)
+/*
+ * process_kqueue() -- process kqueue file
+ */
+
+void
+process_kqueue(ka)
+ KA_T ka; /* kqueue file structure address */
+{
+ struct kqueue kq; /* kqueue structure */
+
+ (void) snpf(Lf->type, sizeof(Lf->type), "KQUEUE");
+ enter_dev_ch(print_kptr(ka, (char *)NULL, 0));
+ if (!ka || kread(ka, (char *)&kq, sizeof(kq)))
+ return;
+ (void) snpf(Namech, Namechl, "count=%d, state=%#x", kq.kq_count,
+ kq.kq_state);
+ enter_nm(Namech);
+}
+#endif /* defined(HASKQUEUE) */
+
+
+#if DARWINV>=800
+/*
+ * process_pipe() - process a file structure whose type is DTYPE_PIPE
+ */
+
+void
+process_pipe(pa)
+ KA_T pa; /* pipe structure address */
+{
+ (void) snpf(Lf->type, sizeof(Lf->type), "PIPE");
+ enter_dev_ch(print_kptr(pa, (char *)NULL, 0));
+ Namech[0] = '\0';
+}
+#endif /* DARWINV>=800 */
+
+
+#if defined(HASPSXSEM)
+/*
+ * process_psxsem() -- process POSIX semaphore file
+ */
+
+void
+process_psxsem(pa)
+ KA_T pa; /* psxsem file structure address */
+{
+ struct pseminfo pi;
+ struct psemnode pn;
+
+ (void) snpf(Lf->type, sizeof(Lf->type), "PSXSEM");
+ enter_dev_ch(print_kptr(pa, (char *)NULL, 0));
+ if (!Fsize)
+ Lf->off_def = 1;
+ if (pa && !kread(pa, (char *)&pn, sizeof(pn))) {
+ if (pn.pinfo && !kread((KA_T)pn.pinfo, (char *)&pi, sizeof(pi))) {
+ if (pi.psem_name[0]) {
+ pi.psem_name[PSEMNAMLEN] = '\0';
+ (void) snpf(Namech, Namechl, "%s", pi.psem_name);
+ enter_nm(Namech);
+ }
+ }
+ }
+}
+#endif /* defined(HASPSXSEM) */
+
+
+#if defined(HASPSXSHM)
+/*
+ * process_psxshm() -- process POSIX shared memory file
+ */
+
+void
+process_psxshm(pa)
+ KA_T pa; /* psxshm file structure address */
+{
+ struct pshminfo pi;
+ struct pshmnode pn;
+ int pns = 0;
+
+ (void) snpf(Lf->type, sizeof(Lf->type), "PSXSHM");
+ enter_dev_ch(print_kptr(pa, (char *)NULL, 0));
+ if (pa && !kread(pa, (char *)&pn, sizeof(pn))) {
+ pns = 1;
+ if (pn.pinfo && !kread((KA_T)pn.pinfo, (char *)&pi, sizeof(pi))) {
+ if (pi.pshm_name[0]) {
+ pi.pshm_name[PSEMNAMLEN] = '\0';
+ (void) snpf(Namech, Namechl, "%s", pi.pshm_name);
+ enter_nm(Namech);
+ } else if (pi.pshm_memobject) {
+ (void) snpf(Namech, Namechl, "obj=%s",
+ print_kptr((KA_T)pi.pshm_memobject, (char *)NULL, 0));
+ enter_nm(Namech);
+ }
+ }
+ }
+ if (Foffset)
+ Lf->off_def = 1;
+ else if (pns) {
+ Lf->sz = (SZOFFTYPE)pn.map_size;
+ Lf->sz_def = 1;
+ }
+}
+#endif /* defined(HASPSXSHM) */
+
+
+/*
+ * process_file() - process file
+ */
+
+/*
+ * The caller may define:
+ *
+ * FILEPTR as the name of the location to store a pointer
+ * to the current file struct -- e.g.,
+ *
+ * struct file *foobar;
+ * #define FILEPTR foobar
+ */
+
+void
+process_file(fp)
+ KA_T fp; /* kernel file structure address */
+{
+
+#if DARWINV<800
+ struct file f;
+#else /* DARWINV>=800 */
+ struct fileglob f;
+ struct fileproc fileproc;
+#endif /* DARWINV>=800 */
+
+ int flag;
+
+#if defined(FILEPTR)
+/*
+ * Save file structure address for process_node().
+ */
+ FILEPTR = &f;
+#endif /* defined(FILEPTR) */
+
+/*
+ * Read file structure.
+ */
+
+#if DARWINV<800
+ if (kread((KA_T)fp, (char *)&f, sizeof(f))) {
+ (void) snpf(Namech, Namechl, "can't read file struct from %s",
+ print_kptr(fp, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+#else /* DARWINV>=800 */
+ if (kread((KA_T)fp, (char *)&fileproc, sizeof(fileproc))) {
+ (void) snpf(Namech, Namechl, "can't read fileproc struct from %s",
+ print_kptr(fp, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ if (kread((KA_T)fileproc.f_fglob, (char *)&f, sizeof(f))) {
+ (void) snpf(Namech, Namechl, "can't read fileglob struct from %s",
+ print_kptr((KA_T)fileproc.f_fglob, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+#endif /* DARWINV>=800 */
+
+ Lf->off = (SZOFFTYPE)f.f_offset;
+ if (f.f_count) {
+
+ /*
+ * Construct access code.
+ */
+ if ((flag = (f.f_flag & (FREAD | FWRITE))) == FREAD)
+ Lf->access = 'r';
+ else if (flag == FWRITE)
+ Lf->access = 'w';
+ else if (flag == (FREAD | FWRITE))
+ Lf->access = 'u';
+
+#if defined(HASFSTRUCT)
+ /*
+ * Save file structure values.
+ */
+ if (Fsv & FSV_CT) {
+ Lf->fct = (long)f.f_count;
+ Lf->fsv |= FSV_CT;
+ }
+ if (Fsv & FSV_FA) {
+ Lf->fsa = fp;
+ Lf->fsv |= FSV_FA;
+ }
+ if (Fsv & FSV_FG) {
+ Lf->ffg = (long)f.f_flag;
+ Lf->fsv |= FSV_FG;
+ }
+ if (Fsv & FSV_NI) {
+ Lf->fna = (KA_T)f.f_data;
+ Lf->fsv |= FSV_NI;
+ }
+#endif /* defined(HASFSTRUCT) */
+
+ /*
+ * Process structure by its type.
+ */
+ switch (f.f_type) {
+
+
+#if defined(DTYPE_PIPE)
+ case DTYPE_PIPE:
+# if defined(HASPIPEFN)
+ if (!Selinet)
+ HASPIPEFN((KA_T)f.f_data);
+# endif /* defined(HASPIPEFN) */
+ return;
+#endif /* defined(DTYPE_PIPE) */
+
+ case DTYPE_VNODE:
+ if (!Selinet)
+ process_node((KA_T)f.f_data);
+ return;
+ case DTYPE_SOCKET:
+ process_socket((KA_T)f.f_data);
+ return;
+
+#if defined(HASKQUEUE)
+ case DTYPE_KQUEUE:
+ process_kqueue((KA_T)f.f_data);
+ return;
+#endif /* defined(HASKQUEUE) */
+
+#if defined(HASPSXSEM)
+ case DTYPE_PSXSEM:
+ process_psxsem((KA_T)f.f_data);
+ return;
+#endif /* defined(HASPSXSEM) */
+
+#if defined(HASPSXSHM)
+ case DTYPE_PSXSHM:
+ process_psxshm((KA_T)f.f_data);
+ return;
+#endif /* defined(HASPSXSHM) */
+
+#if defined(HASPRIVFILETYPE)
+ case PRIVFILETYPE:
+ HASPRIVFILETYPE((KA_T)f.f_data);
+ return;
+#endif /* defined(HASPRIVFILETYPE) */
+
+ default:
+ if (f.f_type || f.f_ops) {
+ (void) snpf(Namech, Namechl,
+ "%s file struct, ty=%#x, op=%p",
+ print_kptr(fp, (char *)NULL, 0), f.f_type, f.f_ops);
+ enter_nm(Namech);
+ return;
+ }
+ }
+ }
+ enter_nm("no more information");
+}
diff --git a/dialects/darwin/kmem/dlsof.h b/dialects/darwin/kmem/dlsof.h
new file mode 100644
index 0000000..f5e50eb
--- /dev/null
+++ b/dialects/darwin/kmem/dlsof.h
@@ -0,0 +1,337 @@
+/*
+ * dlsof.h - Darwin header file for /dev/kmem-based lsof
+ */
+
+
+/*
+ * Copyright 1994 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.
+ */
+
+
+/*
+ * $Id: dlsof.h,v 1.11 2005/11/01 20:24:51 abe Exp $
+ */
+
+
+#if !defined(DARWIN_LSOF_H)
+#define DARWIN_LSOF_H 1
+
+#include <stdlib.h>
+#include <dirent.h>
+#include <nlist.h>
+#include <setjmp.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/conf.h>
+#include <sys/filedesc.h>
+#include <sys/ucred.h>
+
+#if DARWINV<800
+#include <sys/mount.h>
+#define m_stat mnt_stat
+#else /* DARWINV>=800 */
+#include <sys/mount_internal.h>
+#define m_stat mnt_vfsstat
+#endif /* DARWINV>=800 */
+
+#if DARWINV<800
+#include <sys/uio.h>
+#include <sys/vnode.h>
+#else /* DARWINV>=800 */
+#include <sys/vnode.h>
+#define _SYS_SYSTM_H_
+struct nameidata { int dummy; }; /* to satisfy function prototypes */
+#include <sys/vnode_internal.h>
+#endif /* DARWINV>=800 */
+
+#include <rpc/types.h>
+#define KERNEL_PRIVATE
+#include <sys/socketvar.h>
+#undef KERNEL_PRIVATE
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/unpcb.h>
+
+# if defined(AF_NDRV)
+#include <net/if_var.h>
+#define KERNEL
+#include <sys/kern_event.h>
+#undef KERNEL
+#include <net/ndrv.h>
+# if DARWINV>=530
+#define KERNEL 1
+#include <net/ndrv_var.h>
+#undef KERNEL
+# endif /* DARWINV>=530 */
+# endif /* defined(AF_NDRV) */
+
+# if defined(AF_SYSTEM)
+#include <sys/queue.h>
+#define KERNEL
+#include <sys/kern_event.h>
+#undef KERNEL
+# endif /* defined(AF_SYSTEM) */
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <net/route.h>
+#include <netinet6/ipsec.h>
+#include <netinet/in_pcb.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+#include <netinet/tcp_fsm.h>
+#include <netinet/tcp_timer.h>
+#include <netinet/tcp_var.h>
+#include <arpa/inet.h>
+#include <net/raw_cb.h>
+#include <sys/domain.h>
+#define pmap RPC_pmap
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#undef pmap
+
+#include <sys/quota.h>
+#include <sys/event.h>
+
+# if DARWINV<800
+#include <paths.h>
+#undef MAXNAMLEN
+#include <ufs/ufs/quota.h>
+#include <paths.h>
+#include <ufs/ufs/quota.h>
+#include <ufs/ufs/inode.h>
+#include <nfs/rpcv2.h>
+#include <nfs/nfs.h>
+#include <nfs/nfsproto.h>
+#include <nfs/nfsnode.h>
+
+# if DARWINV<600
+#include <hfs/hfs.h>
+#undef offsetof
+# else /* DARWINV>=600 */
+#define KERNEL
+#include <hfs/hfs_cnode.h>
+#undef KERNEL
+# endif /* DARWINV<600 */
+# endif /* DARWINV<800 */
+
+# if DARWINV<800
+#define time t1 /* hack to make dn_times() happy */
+#include <miscfs/devfs/devfsdefs.h>
+#undef time
+# endif /* DARWINV<800 */
+
+# if DARWINV<800
+#define KERNEL
+#include <miscfs/fdesc/fdesc.h>
+#undef KERNEL
+# endif /* DARWINV<800 */
+
+# if DARWINV<800
+#include <sys/proc.h>
+# else /* DARWINV>=800 */
+#define PROC_DEF_ENABLED
+#define sleep kernel_sleep
+#include <sys/proc_internal.h>
+#undef sleep
+# endif /* DARWINV<800 */
+
+#include <kvm.h>
+#undef TRUE
+#undef FALSE
+
+# if DARWINV<800
+#include <sys/sysctl.h>
+# else /* DARWINV>=800 */
+#include "/usr/include/sys/sysctl.h"
+# endif /* DARWINV<800 */
+
+# if DARWINV<800
+#define KERNEL
+#include <sys/fcntl.h>
+#include <sys/file.h>
+#undef KERNEL
+# else /* DARWINV>=800 */
+#include <sys/fcntl.h>
+#include <sys/file_internal.h>
+# endif /* DARWINV<800 */
+
+# if defined(HASKQUEUE)
+#include <sys/eventvar.h>
+# endif /* defined(HASKQUEUE) */
+
+# if defined(DTYPE_PSXSEM)
+#define HASPSXSEM /* has the POSIX semaphore file
+ * type */
+# endif /* defined(DTYPE_PSXSEM) */
+
+# if defined(DTYPE_PSXSHM)
+#define HASPSXSHM /* has the POSIX shared memory
+ * file type */
+# endif /* defined(DTYPE_PSXSHM) */
+
+struct vop_advlock_args { int dummy; }; /* to satisfy lf_advlock() prototype */
+#include <sys/lockf.h>
+#include <sys/lock.h>
+
+/*
+ * Compensate for removal of MAP_ENTRY_IS_A_MAP from <vm/vm_map.h>,
+ * This work-around was supplied by John Polstra <jdp@polstra.com>.
+ */
+
+# if defined(MAP_ENTRY_IS_SUB_MAP) && !defined(MAP_ENTRY_IS_A_MAP)
+#define MAP_ENTRY_IS_A_MAP 0
+# endif /* defined(MAP_ENTRY_IS_SUB_MAP) && !defined(MAP_ENTRY_IS_A_MAP) */
+
+#undef B_NEEDCOMMIT
+#include <sys/buf.h>
+#include <sys/signal.h>
+#define user_sigaltstack sigaltstack
+#include <sys/user.h>
+
+#define COMP_P const void
+#define DEVINCR 1024 /* device table malloc() increment */
+#define DIRTYPE dirent /* directory entry type */
+
+typedef u_long KA_T;
+
+#define KMEM "/dev/kmem"
+#define LOGINML MAXLOGNAME
+#define MALLOC_P void
+#define FREE_P MALLOC_P
+#define MALLOC_S size_t
+
+#define N_UNIX "/mach_kernel"
+
+#define QSORT_P void
+#define READLEN_T int
+#define STRNCPY_L size_t
+#define SWAP "/dev/drum"
+
+# if DARWINV>=800
+#define SZOFFTYPE unsigned long long
+ /* size and offset internal storage
+ * type */
+#define SZOFFPSPEC "ll" /* SZOFFTYPE printf specification
+ * modifier */
+# endif /* DARWINV>=800 */
+
+
+/*
+ * Global storage definitions (including their structure definitions)
+ */
+
+struct file * Cfp;
+
+extern int Kd; /* KMEM descriptor */
+extern KA_T Kpa;
+
+struct l_vfs {
+ KA_T addr; /* kernel address */
+ fsid_t fsid; /* file system ID */
+
+# if defined(MOUNT_NONE)
+ short type; /* type of file system */
+# else /* !defined(MOUNT_NONE) */
+ char *typnm; /* file system type name */
+# endif /* defined(MOUNT_NONE) */
+
+ char *dir; /* mounted directory */
+ char *fsname; /* file system name */
+ struct l_vfs *next; /* forward link */
+};
+extern struct l_vfs *Lvfs;
+
+struct mounts {
+ char *dir; /* directory (mounted on) */
+ char *fsname; /* file system
+ * (symbolic links unresolved) */
+ char *fsnmres; /* file system
+ * (symbolic links resolved) */
+ dev_t dev; /* directory st_dev */
+ dev_t rdev; /* directory st_rdev */
+ INODETYPE inode; /* directory st_ino */
+ mode_t mode; /* directory st_mode */
+ mode_t fs_mode; /* file system st_mode */
+ struct mounts *next; /* forward link */
+};
+
+#define X_NCACHE "ncache"
+#define X_NCSIZE "ncsize"
+#define NL_NAME n_name
+
+struct sfile {
+ char *aname; /* argument file name */
+ char *name; /* file name (after readlink()) */
+ char *devnm; /* device name (optional) */
+ dev_t dev; /* device */
+ dev_t rdev; /* raw device */
+ u_short mode; /* S_IFMT mode bits from stat() */
+ int type; /* file type: 0 = file system
+ * 1 = regular file */
+ INODETYPE i; /* inode number */
+ int f; /* file found flag */
+ struct sfile *next; /* forward link */
+
+};
+
+#define XDR_VOID (const xdrproc_t)xdr_void
+#define XDR_PMAPLIST (const xdrproc_t)xdr_pmaplist
+
+
+/*
+ * Definitions for rnmh.c
+ */
+
+# if defined(HASNCACHE)
+#include <sys/uio.h>
+#include <sys/namei.h>
+
+# if !defined(offsetof)
+#define offsetof(type, member) ((size_t)(&((type *)0)->member))
+# endif /* !defined(offsetof) */
+
+#define NCACHE namecache /* kernel's structure name */
+
+#define NCACHE_NM nc_name /* name in NCACHE */
+
+# if DARWINV<700
+#define NCACHE_NMLEN nc_nlen /* name length in NCACHE */
+# endif /* DARWINV<700 */
+
+#define NCACHE_NXT nc_hash.le_next /* link in NCACHE */
+#define NCACHE_NODEADDR nc_vp /* node address in NCACHE */
+#define NCACHE_PARADDR nc_dvp /* parent node address in NCACHE */
+
+# if defined(HASNCVPID)
+#define NCACHE_NODEID nc_vpid /* node ID in NCACHE */
+#define NCACHE_PARID nc_dvpid /* parent node ID in NCACHE */
+# endif /* defined(HASNCVPID) */
+# endif /* defined(HASNCACHE) */
+
+#endif /* DARWIN_LSOF_H */
diff --git a/dialects/darwin/kmem/dmnt.c b/dialects/darwin/kmem/dmnt.c
new file mode 100644
index 0000000..7ba9453
--- /dev/null
+++ b/dialects/darwin/kmem/dmnt.c
@@ -0,0 +1,229 @@
+/*
+ * dmnt.c - Darwin mount support functions for /dev/kmem-based lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dmnt.c,v 1.4 2005/11/01 20:24:51 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+/*
+ * Local static information
+ */
+
+static struct mounts *Lmi = (struct mounts *)NULL; /* local mount info */
+static int Lmist = 0; /* Lmi status */
+
+/*
+ * readmnt() - read mount table
+ */
+
+struct mounts *
+readmnt()
+{
+ char *dn = (char *)NULL;
+ char *ln;
+ struct statfs *mb = (struct statfs *)NULL;
+ struct mounts *mtp;
+ int n;
+ struct stat sb;
+
+ if (Lmi || Lmist)
+ return(Lmi);
+/*
+ * Access mount information.
+ */
+ if ((n = getmntinfo(&mb, MNT_NOWAIT)) <= 0) {
+ (void) fprintf(stderr, "%s: no mount information\n", Pn);
+ return(0);
+ }
+/*
+ * Read mount information.
+ */
+ for (; n; n--, mb++) {
+
+ if (!mb->f_type)
+ continue;
+ /*
+ * Interpolate a possible symbolic directory link.
+ */
+ if (dn)
+ (void) free((FREE_P *)dn);
+ if (!(dn = mkstrcpy(mb->f_mntonname, (MALLOC_S *)NULL))) {
+
+no_space_for_mount:
+
+ (void) fprintf(stderr, "%s: no space for mount at ", Pn);
+ safestrprt(mb->f_mntonname, stderr, 0);
+ (void) fprintf(stderr, " (");
+ safestrprt(mb->f_mntfromname, stderr, 0);
+ (void) fprintf(stderr, ")\n");
+ Exit(1);
+ }
+ if (!(ln = Readlink(dn))) {
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ " Output information may be incomplete.\n");
+ }
+ continue;
+ }
+ if (ln != dn) {
+ (void) free((FREE_P *)dn);
+ dn = ln;
+ }
+ if (*dn != '/')
+ continue;
+ /*
+ * Stat() the directory.
+ */
+ if (statsafely(dn, &sb)) {
+ if (!Fwarn) {
+ (void) fprintf(stderr, "%s: WARNING: can't stat() ", Pn);
+
+ safestrprt(mb->f_fstypename, stderr, 0);
+
+ (void) fprintf(stderr, " file system ");
+ safestrprt(mb->f_mntonname, stderr, 1);
+ (void) fprintf(stderr,
+ " Output information may be incomplete.\n");
+ }
+ (void) bzero((char *)&sb, sizeof(sb));
+ sb.st_dev = (dev_t)mb->f_fsid.val[0];
+ sb.st_mode = S_IFDIR | 0777;
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ " assuming \"dev=%x\" from mount table\n",
+ sb.st_dev);
+ }
+ }
+ /*
+ * Allocate and fill a local mount structure.
+ */
+ if (!(mtp = (struct mounts *)malloc(sizeof(struct mounts))))
+ goto no_space_for_mount;
+ mtp->dir = dn;
+ dn = (char *)NULL;
+
+ mtp->next = Lmi;
+ mtp->dev = sb.st_dev;
+ mtp->rdev = sb.st_rdev;
+ mtp->inode = (INODETYPE)sb.st_ino;
+ mtp->mode = sb.st_mode;
+ /*
+ * Interpolate a possible file system (mounted-on) device name link.
+ */
+ if (!(dn = mkstrcpy(mb->f_mntfromname, (MALLOC_S *)NULL)))
+ goto no_space_for_mount;
+ mtp->fsname = dn;
+ ln = Readlink(dn);
+ dn = (char *)NULL;
+ /*
+ * Stat() the file system (mounted-on) name and add file system
+ * information to the local mount table entry.
+ */
+ if (!ln || statsafely(ln, &sb))
+ sb.st_mode = 0;
+ mtp->fsnmres = ln;
+ mtp->fs_mode = sb.st_mode;
+ Lmi = mtp;
+ }
+/*
+ * Clean up and return the local mount info table address.
+ */
+ if (dn)
+ (void) free((FREE_P *)dn);
+ Lmist = 1;
+ return(Lmi);
+}
+
+
+/*
+ * readvfs() - read vfs structure
+ */
+
+struct l_vfs *
+readvfs(vm)
+ KA_T vm; /* kernel mount address from vnode */
+{
+ struct mount m;
+ struct l_vfs *vp;
+/*
+ * Search for match on existing entry.
+ */
+ for (vp = Lvfs; vp; vp = vp->next) {
+ if (vm == vp->addr)
+ return(vp);
+ }
+/*
+ * Read the (new) mount structure, allocate a local entry, and fill it.
+ */
+ if (kread((KA_T)vm, (char *)&m, sizeof(m)) != 0)
+ return((struct l_vfs *)NULL);
+ if (!(vp = (struct l_vfs *)malloc(sizeof(struct l_vfs)))) {
+ (void) fprintf(stderr, "%s: PID %d, no space for vfs\n",
+ Pn, Lp->pid);
+ Exit(1);
+ }
+ if (!(vp->dir = mkstrcpy(m.m_stat.f_mntonname, (MALLOC_S *)NULL))
+ || !(vp->fsname = mkstrcpy(m.m_stat.f_mntfromname, (MALLOC_S *)NULL)))
+ {
+ (void) fprintf(stderr, "%s: PID %d, no space for mount names\n",
+ Pn, Lp->pid);
+ Exit(1);
+ }
+ vp->addr = vm;
+ vp->fsid = m.m_stat.f_fsid;
+ {
+ int len;
+
+ if ((len = strlen(m.m_stat.f_fstypename))) {
+ if (len > (MFSNAMELEN - 1))
+ len = MFSNAMELEN - 1;
+ if (!(vp->typnm = mkstrcat(m.m_stat.f_fstypename, len,
+ (char *)NULL, -1, (char *)NULL, -1,
+ (MALLOC_S *)NULL)))
+ {
+ (void) fprintf(stderr,
+ "%s: no space for fs type name: ", Pn);
+ safestrprt(m.m_stat.f_fstypename, stderr, 1);
+ Exit(1);
+ }
+ } else
+ vp->typnm = "";
+ }
+ vp->next = Lvfs;
+ Lvfs = vp;
+ return(vp);
+}
diff --git a/dialects/darwin/kmem/dnode.c b/dialects/darwin/kmem/dnode.c
new file mode 100644
index 0000000..d634c62
--- /dev/null
+++ b/dialects/darwin/kmem/dnode.c
@@ -0,0 +1,1038 @@
+/*
+ * dnode.c - Darwin node functions for /dev/kmem-based lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dnode.c,v 1.11 2006/03/27 23:24:50 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+/*
+ * Local function prototypes
+ */
+
+#if DARWINV<600
+_PROTOTYPE(static int lkup_dev_tty,(dev_t *dr, dev_t *rdr, INODETYPE *ir));
+#endif /* DARWINV<600 */
+
+#if DARWINV>=800
+_PROTOTYPE(static char *getvpath,(KA_T va, struct vnode *rv));
+_PROTOTYPE(static int readvname,(KA_T addr, char *buf, int buflen));
+#endif /* DARWINV>=800 */
+
+
+#if DARWINV>=800
+/*
+ * getvpath() - get vnode path
+ * adapted from build_path() (.../bsd/vfs/vfs_subr.c)
+ */
+
+static char *
+getvpath(va, rv)
+ KA_T va; /* kernel address of the rightmost
+ * vnode in the path */
+ struct vnode *rv; /* pointer to rightmost vnode */
+{
+ char *ap;
+ static char *bp = (char *)NULL;
+ static size_t bl = (size_t)(MAXPATHLEN + MAXPATHLEN + 1);
+ static char *cb = (char *)NULL;
+ static size_t cbl = (size_t)0;
+ static int ce = 0;
+ struct mount mb;
+ int pl, vnl;
+ char *pp, vn[MAXPATHLEN+1];
+ struct vnode vb;
+ KA_T vas = va;
+/*
+ * Initialize the path assembly.
+ */
+ if (!bp) {
+ if (!(bp = (char *)malloc((MALLOC_S)bl))) {
+ (void) fprintf(stderr, "%s: no space (%d) for path assembly\n",
+ Pn, (int)bl);
+ Exit(1);
+ }
+ }
+ pp = bp + bl - 1;
+ *pp = '\0';
+ pl = 0;
+/*
+ * Process the starting vnode.
+ */
+ if (!va)
+ return(0);
+ if ((rv->v_flag & VROOT) && rv->v_mount) {
+
+ /*
+ * This is the root of a file system and it has a mount structure.
+ * Read the mount structure.
+ */
+ if (kread((KA_T)rv->v_mount, (char *)&mb, sizeof(mb)))
+ return(0);
+ if (mb.mnt_flag & MNT_ROOTFS) {
+
+ /*
+ * This is the root file system, so the path is "/".
+ */
+ pp--;
+ *pp = '/';
+ pl = 1;
+ goto getvpath_alloc;
+ } else {
+
+ /*
+ * Get the covered vnode's pointer and read it. Use it to
+ * form the path.
+ */
+ if ((va = (KA_T)mb.mnt_vnodecovered)) {
+ if (readvnode(va, &vb))
+ return(0);
+ }
+ }
+ } else {
+
+ /*
+ * Use the supplied vnode.
+ */
+ vb = *rv;
+ }
+/*
+ * Accumulate the path from the vnode chain.
+ */
+ while (va && ((KA_T)vb.v_parent != va)) {
+ if (!vb.v_name) {
+
+ /*
+ * If there is no name pointer or parent, the assembly is complete.
+ */
+ if (vb.v_parent) {
+
+ /*
+ * It is an error if there is a parent but no name.
+ */
+ return((char *)NULL);
+ }
+ break;
+ }
+ /*
+ * Read the name and add it to the assembly.
+ */
+ if ((vnl = readvname((KA_T)vb.v_name, vn, sizeof(vn))) <= 0)
+ return((char *)NULL);
+ if ((vnl + 1 + pl + 1) > bl)
+ return((char *)NULL);
+ memmove((void *)(pp - vnl), (void *)vn, vnl);
+ pp -= (vnl + 1);
+ *pp = '/';
+ pl += vnl + 1;
+ if ((va == vas) && (vb.v_flag & VROOT)) {
+
+ /*
+ * This is the starting vnode and it is a root vnode. Read its
+ * mount structure.
+ */
+ if (vb.v_mount) {
+ if (kread((KA_T)vb.v_mount, (char *)&mb, sizeof(mb)))
+ return((char *)NULL);
+ if (mb.mnt_vnodecovered) {
+
+ /*
+ * If there's a covered vnode, read it and use it's parent
+ * vnode pointer.
+ */
+ if ((va = (KA_T)mb.mnt_vnodecovered)) {
+ if (readvnode(va, &vb))
+ return((char *)NULL);
+ va = (KA_T)vb.v_parent;
+ }
+ } else
+ va = (KA_T)NULL;
+ } else
+ va = (KA_T)NULL;
+ } else
+ va = (KA_T)vb.v_parent;
+ /*
+ * If there's a parent vnode, read it.
+ */
+ if (va) {
+ if (readvnode(va, &vb))
+ return((char *)NULL);
+ if ((vb.v_flag & VROOT) && vb.v_mount) {
+
+ /*
+ * The mount point has been reached. Read the mount structure
+ * and use its covered vnode pointer.
+ */
+ if (kread((KA_T)vb.v_mount, (char *)&mb, sizeof(mb)))
+ return((char *)NULL);
+ if ((va = (KA_T)mb.mnt_vnodecovered)) {
+ if (readvnode(va, &vb))
+ return((char *)NULL);
+ }
+ }
+ }
+ }
+/*
+ * As a special case the following code attempts to trim a path that is
+ * larger than MAXPATHLEN by seeing if the lsof process CWD can be removed
+ * from the start of the path to make it MAXPATHLEN characters or less.
+ */
+ if (pl > MAXPATHLEN) {
+
+ /*
+ * Get the cwd. If that can't be done, return an error.
+ */
+ if (ce)
+ return((char *)NULL);
+ if (!cb) {
+ if (!(cb = (char *)malloc((MALLOC_S)(MAXPATHLEN + 1)))) {
+ (void) fprintf(stderr, "%s: no space (%d) for CWD\n",
+ Pn, (int)bl);
+ Exit(1);
+ }
+ if (!getcwd(cb, (size_t)(MAXPATHLEN + 1))) {
+ if (!Fwarn) {
+ (void) fprintf(stderr, "%s: WARNING: can't get CWD\n",
+ Pn);
+ }
+ ce = 1;
+ return((char *)NULL);
+ }
+ cb[MAXPATHLEN - 1] = '\0';
+ if (!(cbl = (size_t)strlen(cb))) {
+ if (!Fwarn) {
+ (void) fprintf(stderr, "%s: WARNING: CWD is NULL\n",
+ Pn);
+ }
+ ce = 1;
+ return((char *)NULL);
+ }
+ }
+ /*
+ * See if trimming the CWD shortens the path to MAXPATHLEN or less.
+ */
+ if ((pl <= cbl) || strncmp(cb, pp, cbl))
+ return((char *)NULL);
+ pp += cbl;
+ pl -= cbl;
+ if (cb[cbl - 1] == '/') {
+
+ /*
+ * The CWD ends in a '/', so the path must not begin with one. If
+ * it does, no trimming can be done.
+ */
+ if (*pp == '/')
+ return((char *)NULL);
+ } else {
+
+ /*
+ * The CWD doesn't end in a '/', so the path must begin with one.
+ * If it doesn't, no trimming can be done.
+ */
+ if (*pp != '/')
+ return((char *)NULL);
+ /*
+ * Skip all leading path '/' characters. Some characters must
+ * remain.
+ */
+ while ((pl > 0) && (*pp == '/')) {
+ pp++;
+ pl--;
+ }
+ if (!pl)
+ return((char *)NULL);
+ }
+ }
+/*
+ * Allocate space for the assembled path, including terminator, and return its
+ * pointer.
+ */
+
+getvpath_alloc:
+
+ if (!(ap = (char *)malloc(pl + 1))) {
+ (void) fprintf(stderr, "%s: no getvpath space (%d)\n",
+ Pn, pl + 1);
+ Exit(1);
+ }
+ (void) memmove(ap, pp, pl + 1);
+ return(ap);
+}
+#endif /* DARWINV>=800 */
+
+
+#if DARWINV<600
+/*
+ * lkup_dev_tty() - look up /dev/tty
+ */
+
+static int
+lkup_dev_tty(dr, rdr, ir)
+ dev_t *dr; /* place to return device number */
+ dev_t *rdr; /* place to return raw device number */
+ INODETYPE *ir; /* place to return inode number */
+{
+ int i;
+
+ readdev(0);
+ for (i = 0; i < Ndev; i++) {
+ if (strcmp(Devtp[i].name, "/dev/tty") == 0) {
+ *dr = DevDev;
+ *rdr = Devtp[i].rdev;
+ *ir = (INODETYPE)Devtp[i].inode;
+ return(1);
+ }
+ }
+ return(-1);
+}
+#endif /* DARWINV<600 */
+
+
+/*
+ * process_node() - process vnode
+ */
+
+void
+process_node(va)
+ KA_T va; /* vnode kernel space address */
+{
+ dev_t dev = (dev_t)0;
+ dev_t rdev = (dev_t)0;
+ unsigned char devs = 0;
+ unsigned char rdevs = 0;
+
+#if DARWINV<800
+ struct devnode *d = (struct devnode *)NULL;
+ struct devnode db;
+ unsigned char lt;
+ char dev_ch[32];
+
+# if defined(HASFDESCFS)
+ struct fdescnode *f = (struct fdescnode *)NULL;
+ struct fdescnode fb;
+# endif /* defined(HASFDESCFS) */
+
+ static INODETYPE fi;
+ static dev_t fdev, frdev;
+ static int fs = 0;
+ struct inode *i = (struct inode *)NULL;
+ struct inode ib;
+ struct lockf lf, *lff, *lfp;
+ struct nfsnode *n = (struct nfsnode *)NULL;
+ struct nfsnode nb;
+#else /* DARWINV>=800 */
+ struct stat sb;
+ char *vn;
+#endif /* DARWINV<800 */
+
+ char *ty;
+ enum vtype type;
+ struct vnode *v, vb;
+ struct l_vfs *vfs;
+
+#if DARWINV<600
+ struct hfsnode *h = (struct hfsnode *)NULL;
+ struct hfsnode hb;
+ struct hfsfilemeta *hm = (struct hfsfilemeta *)NULL;
+ struct hfsfilemeta hmb;
+#else /* DARWINV>=600 */
+# if DARWINV<800
+ struct cnode *h = (struct cnode *)NULL;
+ struct cnode hb;
+ struct filefork *hf = (struct filefork *)NULL;
+ struct filefork hfb;
+# endif /* DARWINV<800 */
+#endif /* DARWINV<600 */
+
+#if defined(HAS9660FS)
+ dev_t iso_dev;
+ int iso_dev_def = 0;
+ INODETYPE iso_ino;
+ long iso_links;
+ int iso_stat = 0;
+ SZOFFTYPE iso_sz;
+#endif /* defined(HAS9660FS) */
+
+/*
+ * Read the vnode.
+ */
+ if ( ! va) {
+ enter_nm("no vnode address");
+ return;
+ }
+ v = &vb;
+ if (readvnode(va, v)) {
+ enter_nm(Namech);
+ return;
+ }
+ type = v->v_type;
+
+#if defined(HASNCACHE)
+ Lf->na = va;
+# if defined(HASNCVPID)
+ Lf->id = v->v_id;
+# endif /* defined(HASNCVPID) */
+#endif /* defined(HASNCACHE) */
+
+#if defined(HASFSTRUCT)
+ Lf->fna = va;
+ Lf->fsv |= FSV_NI;
+#endif /* defined(HASFSTRUCT) */
+
+/*
+ * Get the vnode type.
+ */
+ if (!v->v_mount)
+ vfs = (struct l_vfs *)NULL;
+ else {
+ vfs = readvfs((KA_T)v->v_mount);
+ if (vfs) {
+ if (strcasecmp(vfs->typnm, "nfs") == 0)
+ Ntype = N_NFS;
+
+#if DARWINV<130
+ else if (strcasecmp(vfs->typnm, "afpfs") == 0)
+ Ntype = N_AFPFS;
+#endif /* DARWINV<130 */
+
+ }
+ }
+ if (Ntype == N_REGLR) {
+ switch (v->v_type) {
+ case VFIFO:
+ Ntype = N_FIFO;
+ break;
+ default:
+ break;
+ }
+ }
+
+#if DARWINV<800
+/*
+ * Define the specific node pointer.
+ */
+ switch (v->v_tag) {
+
+# if DARWINV>120
+ case VT_AFP:
+ break;
+# endif /* DARWINV>120 */
+
+# if DARWINV>120
+ case VT_CDDA:
+ break;
+# endif /* DARWINV>120 */
+
+# if DARWINV>120
+ case VT_CIFS:
+ break;
+# endif /* DARWINV>120 */
+
+ case VT_DEVFS:
+ if (!v->v_data
+ || kread((KA_T)v->v_data, (char *)&db, sizeof(db))) {
+ (void) snpf(Namech, Namechl, "no devfs node: %#x", v->v_data);
+ enter_nm(Namech);
+ return;
+ }
+ d = &db;
+ break;
+
+# if defined(HASFDESCFS)
+ case VT_FDESC:
+ if (!v->v_data
+ || kread((KA_T)v->v_data, (char *)&fb, sizeof(fb))) {
+ (void) snpf(Namech, Namechl, "no fdesc node: %s",
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ f = &fb;
+ break;
+# endif /* defined(HASFDESCFS) */
+
+ case VT_HFS:
+
+# if DARWINV<130
+ if (Ntype != N_AFPFS) {
+# endif /* DARWINV<130 */
+
+ if (!v->v_data
+ || kread((KA_T)v->v_data, (char *)&hb, sizeof(hb))) {
+ (void) snpf(Namech, Namechl, "no hfs node: %s",
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ h = &hb;
+
+# if DARWINV<600
+ if (!h->h_meta
+ || kread((KA_T)h->h_meta, (char *)&hmb, sizeof(hmb))) {
+ (void) snpf(Namech, Namechl, "no hfs node metadata: %s",
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ hm = &hmb;
+# else /* DARWINV>=600 */
+ if (v->v_type == VDIR)
+ break;
+ if (h->c_rsrc_vp == v)
+ hf = h->c_rsrcfork;
+ else
+ hf = h->c_datafork;
+ if (!hf
+ || kread((KA_T)hf, (char *)&hfb, sizeof(hfb))) {
+ (void) snpf(Namech, Namechl, "no hfs node fork: %s",
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ hf = &hfb;
+# endif /* DARWINV<600 */
+
+# if DARWINV<130
+ }
+# endif /* DARWINV<130 */
+
+ break;
+
+# if defined(HAS9660FS)
+ case VT_ISOFS:
+ if (read_iso_node(v, &iso_dev, &iso_dev_def, &iso_ino, &iso_links,
+ &iso_sz))
+ {
+ (void) snpf(Namech, Namechl, "no iso node: %s",
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ iso_stat = 1;
+ break;
+# endif /* defined(HAS9660FS) */
+
+ case VT_NFS:
+ if (!v->v_data
+ || kread((KA_T)v->v_data, (char *)&nb, sizeof(nb))) {
+ (void) snpf(Namech, Namechl, "no nfs node: %s",
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ n = &nb;
+ break;
+
+# if DARWINV>120
+ case VT_UDF:
+ break;
+# endif /* DARWINV>120 */
+
+ case VT_UFS:
+ if (!v->v_data
+ || kread((KA_T)v->v_data, (char *)&ib, sizeof(ib))) {
+ (void) snpf(Namech, Namechl, "no ufs node: %s",
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ i = &ib;
+ if ((lff = i->i_lockf)) {
+
+ /*
+ * Determine the lock state.
+ */
+ lfp = lff;
+ do {
+ if (kread((KA_T)lfp, (char *)&lf, sizeof(lf)))
+ break;
+ lt = 0;
+ switch (lf.lf_flags & (F_FLOCK|F_POSIX)) {
+ case F_FLOCK:
+ if (Cfp && (struct file *)lf.lf_id == Cfp)
+ lt = 1;
+ break;
+ case F_POSIX:
+ if ((KA_T)lf.lf_id == Kpa)
+ lt = 1;
+ break;
+ }
+ if (!lt)
+ continue;
+ if (lf.lf_start == (off_t)0
+ && lf.lf_end == 0xffffffffffffffffLL)
+ lt = 1;
+ else
+ lt = 0;
+ if (lf.lf_type == F_RDLCK)
+ Lf->lock = lt ? 'R' : 'r';
+ else if (lf.lf_type == F_WRLCK)
+ Lf->lock = lt ? 'W' : 'w';
+ else if (lf.lf_type == (F_RDLCK | F_WRLCK))
+ Lf->lock = 'u';
+ break;
+ } while ((lfp = lf.lf_next) && lfp != lff);
+ }
+ break;
+
+# if DARWINV>120
+ case VT_WEBDAV:
+ break;
+# endif /* DARWINV>120 */
+
+ default:
+ if (v->v_type == VBAD || v->v_type == VNON)
+ break;
+ (void) snpf(Namech, Namechl, "unknown file system type: %d",
+ v->v_tag);
+ enter_nm(Namech);
+ return;
+ }
+/*
+ * Get device and type for printing.
+ */
+ if (n) {
+ dev = n->n_vattr.va_fsid;
+ devs = 1;
+ } else if (i) {
+ dev = i->i_dev;
+ devs = 1;
+ if ((type == VCHR) || (type == VBLK)) {
+ rdev = i->i_rdev ;
+ rdevs = 1;
+ }
+ }
+
+# if defined(HASFDESCFS)
+ else if (f) {
+ if (f->fd_link
+ && !kread((KA_T)f->fd_link, Namech, Namechl -1))
+ Namech[Namechl - 1] = '\0';
+
+# if DARWINV<600
+ else if (f->fd_type == Fctty) {
+ if (fs == 0)
+ fs = lkup_dev_tty(&fdev, &frdev, &fi);
+ if (fs == 1) {
+ dev = fdev;
+ rdev = frdev;
+ devs = Lf->inp_ty = rdevs = 1;
+ Lf->inode = fi;
+ }
+ }
+ }
+# endif /* DARWINV<600 */
+# endif /* defined(HASFDESCFS) */
+
+ else if (h) {
+
+# if DARWINV<600
+ dev = hm->h_dev;
+# else /* DARWINV>=600 */
+ dev = h->c_dev;
+# endif /* DARWINV<600 */
+
+ devs = 1;
+ if ((type == VCHR) || (type == VBLK)) {
+
+# if DARWINV<600
+ rdev = hm->h_rdev;
+# else /* DARWINV>=600 */
+ rdev = h->c_rdev;
+# endif /* DARWINV<600 */
+
+ rdevs = 1;
+ }
+ } else if (d) {
+ dev = DevDev;
+ devs = 1;
+ rdev = d->dn_typeinfo.dev;
+ rdevs = 1;
+ }
+
+# if defined(HAS9660FS)
+ else if (iso_stat && iso_dev_def) {
+ dev = iso_dev;
+ devs = Lf->inp_ty = 1;
+ }
+# endif /* defined(HAS9660FS) */
+
+
+/*
+ * Obtain the inode number.
+ */
+ if (i) {
+ Lf->inode = (INODETYPE)i->i_number;
+ Lf->inp_ty = 1;
+ } else if (n) {
+ Lf->inode = (INODETYPE)n->n_vattr.va_fileid;
+ Lf->inp_ty = 1;
+ } else if (h) {
+
+# if DARWINV<600
+ Lf->inode = (INODETYPE)hm->h_nodeID;
+# else /* DARWINV>=600 */
+ Lf->inode = (INODETYPE)h->c_fileid;
+# endif /* DARWINV<600 */
+
+ Lf->inp_ty = 1;
+ }
+
+# if defined(HAS9660FS)
+ else if (iso_stat) {
+ Lf->inode = iso_ino;
+ Lf->inp_ty = 1;
+ }
+# endif /* defined(HAS9660FS) */
+
+/*
+ * Obtain the file size.
+ */
+ if (Foffset)
+ Lf->off_def = 1;
+ else {
+ switch (Ntype) {
+ case N_FIFO:
+ if (!Fsize)
+ Lf->off_def = 1;
+ break;
+ case N_NFS:
+ if (n) {
+ Lf->sz = (SZOFFTYPE)n->n_vattr.va_size;
+ Lf->sz_def = 1;
+ }
+ break;
+
+# if DARWINV<130
+ case N_AFPFS:
+ break;
+# endif /* DARWINV<130 */
+
+ case N_REGLR:
+ if (type == VREG || type == VDIR) {
+ if (i) {
+ Lf->sz = (SZOFFTYPE)i->i_size;
+ Lf->sz_def = 1;
+ } else if (h) {
+
+# if DARWINV<600
+ Lf->sz = (type == VDIR) ? (SZOFFTYPE)hm->h_size
+ : (SZOFFTYPE)h->fcbEOF;
+# else /* DARWINV>=600 */
+ if (type == VDIR)
+ Lf->sz = (SZOFFTYPE)h->c_nlink * 128;
+ else
+ Lf->sz = (SZOFFTYPE)hf->ff_size;
+# endif /* DARWINV<600 */
+
+ Lf->sz_def = 1;
+ }
+
+# if defined(HAS9660FS)
+ else if (iso_stat) {
+ Lf->sz = (SZOFFTYPE)iso_sz;
+ Lf->sz_def = 1;
+ }
+# endif /* defined(HAS9660FS) */
+
+ }
+ else if ((type == VCHR || type == VBLK) && !Fsize)
+ Lf->off_def = 1;
+ break;
+ }
+ }
+/*
+ * Record the link count.
+ */
+ if (Fnlink) {
+ switch(Ntype) {
+ case N_NFS:
+ if (n) {
+ Lf->nlink = (long)n->n_vattr.va_nlink;
+ Lf->nlink_def = 1;
+ }
+ break;
+
+# if DARWINV<130
+ case N_AFPFS:
+ break;
+# endif /* DARWINV<130 */
+
+ case N_REGLR:
+ if (i) {
+ Lf->nlink = (long)i->i_nlink;
+ Lf->nlink_def = 1;
+ } else if (h) {
+
+# if DARWINV<600
+ Lf->nlink = (long)hm->h_nlink;
+# else /* DARWINV>=600 */
+ Lf->nlink = (long)h->c_nlink;
+# endif /* DARWINV<600 */
+
+ Lf->nlink_def = 1;
+ }
+
+# if defined(HAS9660FS)
+ else if (iso_stat) {
+ Lf->nlink = iso_links;
+ Lf->nlink_def = 1;
+ }
+# endif /* defined(HAS9660FS) */
+
+ break;
+ }
+ if (Lf->nlink_def && Nlink && (Lf->nlink < Nlink))
+ Lf->sf |= SELNLINK;
+ }
+#else /* DARWINV>=800 */
+
+/*
+ * Process a vnode for Darwin >= 8.0.
+ */
+ if ((vn = getvpath(va, v))) {
+
+ /*
+ * If the vnode yields a path, get the file's information by doing
+ * a "safe" stat(2) of the path.
+ */
+ if (!statsafely(vn, &sb)) {
+
+ /*
+ * Save file size or offset.
+ */
+ if (Foffset) {
+ Lf->off_def = 1;
+ } else {
+ switch (Ntype) {
+ case N_FIFO:
+ if (!Fsize)
+ Lf->off_def = 1;
+ break;
+ case N_NFS:
+ case N_REGLR:
+ if (type == VREG || type == VDIR) {
+ Lf->sz = sb.st_size;
+ Lf->sz_def = 1;
+ } else if ((type == VCHR || type == VBLK) && !Fsize)
+ Lf->off_def = 1;
+ break;
+ }
+ }
+ /*
+ * Save node number.
+ */
+ Lf->inode = (INODETYPE)sb.st_ino;
+ Lf->inp_ty = 1;
+ /*
+ * Optionally save link count.
+ */
+ if (Fnlink) {
+ Lf->nlink = sb.st_nlink;
+ Lf->nlink_def = 1;
+ }
+ /*
+ * Save device number and path.
+ */
+ switch (v->v_tag) {
+ case VT_DEVFS:
+ if (vn)
+ (void) free((FREE_P *)vn);
+ dev = DevDev;
+ devs = 1;
+ break;
+ default :
+ Lf->V_path = vn;
+ dev = sb.st_dev;
+ devs = 1;
+ break;
+ }
+ /*
+ * Save character and block device number.
+ */
+ if ((type == VCHR) || (type == VBLK)) {
+ rdev = sb.st_rdev;
+ rdevs = 1;
+ }
+ } else {
+
+ /*
+ * Indicate a stat(2) failure in Namech[].
+ */
+ (void) snpf(Namech, Namechl, "stat(%s): %s", vn,
+ strerror(errno));
+ (void) free((FREE_P *)vn);
+ }
+ /*
+ * Record an NFS file.
+ */
+ if (vfs && !strcmp(vfs->typnm, "nfs"))
+ Ntype = N_NFS;
+ }
+#endif /* DARWINV>=800 */
+
+/*
+ * Record an NFS file selection.
+ */
+ if (Ntype == N_NFS && Fnfs)
+ Lf->sf |= SELNFS;
+/*
+ * Save the file system names.
+ */
+ if (vfs) {
+ Lf->fsdir = vfs->dir;
+ Lf->fsdev = vfs->fsname;
+ }
+/*
+ * Save the device numbers and their states.
+ *
+ * Format the vnode type, and possibly the device name.
+ */
+ Lf->dev = dev;
+ Lf->dev_def = devs;
+ Lf->rdev = rdev;
+ Lf->rdev_def = rdevs;
+ switch (type) {
+ case VNON:
+ ty ="VNON";
+ break;
+ case VREG:
+ ty = "VREG";
+ break;
+ case VDIR:
+ ty = "VDIR";
+ break;
+ case VBLK:
+ ty = "VBLK";
+ Ntype = N_BLK;
+ break;
+ case VCHR:
+ ty = "VCHR";
+ Ntype = N_CHR;
+ break;
+ case VLNK:
+ ty = "VLNK";
+ break;
+
+#if defined(VSOCK)
+ case VSOCK:
+ ty = "SOCK";
+ break;
+#endif /* defined(VSOCK) */
+
+ case VBAD:
+ ty = "VBAD";
+ break;
+ case VFIFO:
+ ty = "FIFO";
+ break;
+ default:
+ (void) snpf(Lf->type, sizeof(Lf->type), "%04o", (type & 0xfff));
+ ty = (char *)NULL;
+ }
+ if (ty)
+ (void) snpf(Lf->type, sizeof(Lf->type), "%s", ty);
+ Lf->ntype = Ntype;
+/*
+ * Handle some special cases:
+ *
+ * ioctl(fd, TIOCNOTTY) files;
+ * memory node files;
+ * /proc files.
+ */
+ if (type == VBAD)
+ (void) snpf(Namech, Namechl, "(revoked)");
+
+#if defined(HASBLKDEV)
+/*
+ * If this is a VBLK file and it's missing an inode number, try to
+ * supply one.
+ */
+ if ((Lf->inp_ty == 0) && (type == VBLK))
+ find_bl_ino();
+#endif /* defined(HASBLKDEV) */
+
+/*
+ * If this is a VCHR file and it's missing an inode number, try to
+ * supply one.
+ */
+ if ((Lf->inp_ty == 0) && (type == VCHR))
+ find_ch_ino();
+/*
+ * Test for specified file.
+ */
+ if (Sfile && is_file_named((char *)NULL,
+ ((type == VCHR) || (type == VBLK) ? 1
+ : 0)))
+ Lf->sf |= SELNM;
+/*
+ * Enter name characters.
+ */
+ if (Namech[0])
+ enter_nm(Namech);
+}
+
+
+#if DARWINV>=800
+/*
+ * readvname() - read vnode's path name
+ */
+
+static int
+readvname(addr, buf, buflen)
+ KA_T addr; /* kernel v_path address */
+ char *buf; /* receiving buffer */
+ int buflen; /* sizeof(buf) */
+{
+ int n, rl;
+/*
+ * Read the name 32 characters at a time, until a NUL character
+ * has been read or the buffer has been filled.
+ */
+ for (n = 0; n < buflen; addr += 32, n += 32) {
+ rl = buflen - n;
+ if (rl > 32)
+ rl = 32;
+ if (kread(addr, &buf[n], rl))
+ return(0);
+ buf[n + rl] = '\0';
+ if ((rl = (int)strlen(&buf[n])) < 32) {
+ return(n + rl);
+ }
+ }
+ return(0);
+}
+#endif /* DARWINV>=800 */
diff --git a/dialects/darwin/kmem/dnode1.c b/dialects/darwin/kmem/dnode1.c
new file mode 100644
index 0000000..20a76c1
--- /dev/null
+++ b/dialects/darwin/kmem/dnode1.c
@@ -0,0 +1,107 @@
+/*
+ * dnode1.c - Darwin node functions for /dev/kmem-based lsof
+ *
+ * This module must be separate to keep separate the multiple kernel inode
+ * structure definitions.
+ */
+
+
+/*
+ * Copyright 1995 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dnode1.c,v 1.3 2005/11/01 20:24:51 abe Exp $";
+#endif
+
+#include "lsof.h"
+
+#if defined(HAS9660FS)
+
+/*
+ * Do a little preparation for #include'ing cd9660_node.h, then #include it.
+ */
+
+#undef i_size;
+#undef doff_t
+#undef IN_ACCESS
+
+struct vop_abortop_args { int dummy; };
+struct vop_access_args { int dummy; };
+struct vop_blkatoff_args { int dummy; };
+struct vop_bmap_args { int dummy; };
+struct vop_close_args { int dummy; };
+struct vop_getattr_args { int dummy; };
+struct vop_inactive_args { int dummy; };
+struct vop_ioctl_args { int dummy; };
+struct vop_islocked_args { int dummy; };
+struct vop_lock_args { int dummy; };
+struct vop_lookup_args { int dummy; };
+struct vop_mmap_args { int dummy; };
+struct vop_open_args { int dummy; };
+struct vop_pathconf_args { int dummy; };
+struct vop_print_args { int dummy; };
+struct vop_read_args { int dummy; };
+struct vop_readdir_args { int dummy; };
+struct vop_readlink_args { int dummy; };
+struct vop_reclaim_args { int dummy; };
+struct vop_seek_args { int dummy; };
+struct vop_select_args { int dummy; };
+struct vop_strategy_args { int dummy; };
+struct vop_unlock_args { int dummy; };
+
+#include <isofs/cd9660/cd9660_node.h>
+
+/*
+ * read_iso_node() -- read CD 9660 iso_node
+ */
+
+int
+read_iso_node(v, d, dd, ino, nl, sz)
+ struct vnode *v; /* containing vnode */
+ dev_t *d; /* returned device number */
+ int *dd; /* returned device-defined flag */
+ INODETYPE *ino; /* returned inode number */
+ long *nl; /* returned number of links */
+ SZOFFTYPE *sz; /* returned size */
+{
+
+ struct iso_node i;
+
+ if (!v->v_data
+ || kread((KA_T)v->v_data, (char *)&i, sizeof(i)))
+ return(1);
+
+ *d = i.i_dev;
+ *dd = 1;
+ *ino = (INODETYPE)i.i_number;
+ *nl = (long)i.inode.iso_links;
+ *sz = (SZOFFTYPE)i.i_size;
+
+ return(0);
+}
+#endif /* defined(HAS9660FS) */
diff --git a/dialects/darwin/kmem/dproc.c b/dialects/darwin/kmem/dproc.c
new file mode 100644
index 0000000..6fb0dd6
--- /dev/null
+++ b/dialects/darwin/kmem/dproc.c
@@ -0,0 +1,763 @@
+/*
+ * dproc.c - Darwin process access functions for /dev/kmem-based lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dproc.c,v 1.8 2005/11/01 20:24:51 abe Exp $";
+#endif
+
+#include "lsof.h"
+
+#include <mach/mach_traps.h>
+#include <mach/mach_init.h>
+#include <mach/message.h>
+#include <mach/vm_map.h>
+
+
+/*
+ * Local definitions
+ */
+
+#define NPHASH 1024 /* Phash bucket count --
+ * MUST BE A POWER OF 2!!! */
+#define PHASH(a) (((int)((a * 31415) >> 3)) & (NPHASH - 1))
+#define PINCRSZ 256 /* Proc[] size inrement */
+
+
+/*
+ * Local structures
+ */
+
+struct phash {
+ KA_T ka; /* kernel proc struct address */
+ struct proc *la; /* local proc struct address */
+ struct phash *next; /* next phash entry */
+};
+
+
+/*
+ * Local function prototypes
+ */
+
+_PROTOTYPE(static pid_t get_parent_pid,(KA_T kpa));
+_PROTOTYPE(static int read_procs,());
+_PROTOTYPE(static void process_map,(pid_t pid));
+_PROTOTYPE(static void enter_vn_text,(KA_T va, int *n));
+
+#if DARWINV>=700
+_PROTOTYPE(static char *getcmdnm,(pid_t pid));
+#endif /* DARWINV>=700 */
+
+_PROTOTYPE(static void get_kernel_access,(void));
+
+
+/*
+ * Local static values
+ */
+
+static KA_T Akp = (KA_T)NULL; /* kernel allproc chain address */
+static int Np = 0; /* PA[] and Proc[] entry count */
+static int Npa = 0; /* Proc[] structure allocation count */
+static MALLOC_S Nv = 0; /* allocated Vp[] entries */
+static KA_T *Pa = (KA_T *)NULL; /* Proc[] addresses */
+struct phash **Phash = (struct phash **)NULL;
+ /* kernel proc address hash pointers */
+static struct proc *Proc = (struct proc *)NULL;
+ /* local copy of prc struct chain */
+static KA_T *Vp = NULL; /* vnode address cache */
+
+
+/*
+ * enter_vn_text() - enter a vnode text reference
+ */
+
+static void
+enter_vn_text(va, n)
+ KA_T va; /* vnode address */
+ int *n; /* Vp[] entries in use */
+{
+ int i;
+/*
+ * Ignore the request if the vnode has already been entered.
+ */
+ for (i = 0; i < *n; i++) {
+ if (va == Vp[i])
+ return;
+ }
+/*
+ * Save the text file information.
+ */
+ alloc_lfile(" txt", -1);
+ Cfp = (struct file *)NULL;
+ process_node(va);
+ if (Lf->sf)
+ link_lfile();
+ if (i >= Nv) {
+
+ /*
+ * Allocate space for remembering the vnode.
+ */
+ Nv += 10;
+ if (!Vp)
+ Vp=(KA_T *)malloc((MALLOC_S)(sizeof(struct vnode *)*10));
+ else
+ Vp=(KA_T *)realloc((MALLOC_P *)Vp,(MALLOC_S)(Nv*sizeof(KA_T)));
+ if (!Vp) {
+ (void) fprintf(stderr, "%s: no txt ptr space, PID %d\n",
+ Pn, Lp->pid);
+ Exit(1);
+ }
+ }
+/*
+ * Remember the vnode.
+ */
+ Vp[*n] = va;
+ (*n)++;
+}
+
+
+/*
+ * gather_proc_info() -- gather process information
+ */
+
+void
+gather_proc_info()
+{
+ char *cmd;
+ struct filedesc fd;
+ int i, nf;
+ MALLOC_S nb;
+ static struct file **ofb = NULL;
+ static int ofbb = 0;
+ struct proc *p;
+ int pgid;
+ int ppid = 0;
+ static char *pof = (char *)NULL;
+ static int pofb = 0;
+ short pss, sf;
+ int px;
+ uid_t uid;
+
+#if DARWINV<800
+ struct pcred pc;
+#else /* DARWINV>=800 */
+ struct ucred uc;
+#endif /* DARWINV<800 */
+
+/*
+ * Read the process table.
+ */
+ if (read_procs()) {
+ (void) fprintf(stderr, "%s: can't read process table\n", Pn);
+ Exit(1);
+ }
+/*
+ * Examine proc structures and their associated information.
+ */
+ for (p = Proc, px = 0; px < Np; p++, px++)
+ {
+
+#if DARWINV<800
+ if (!p->p_cred || kread((KA_T)p->p_cred, (char *)&pc, sizeof(pc)))
+ continue;
+ pgid = pc.p_rgid;
+ uid = pc.p_ruid;
+#else /* DARWINV>=800 */
+ if (!p->p_ucred || kread((KA_T)p->p_ucred, (char *)&uc, sizeof(uc)))
+ continue;
+ pgid = uc.cr_rgid;
+ uid = uc.cr_uid;
+#endif /* DARWINV<800 */
+
+#if defined(HASPPID)
+ ppid = get_parent_pid((KA_T)p->p_pptr);
+#endif /* defined(HASPPID) */
+
+ /*
+ * Get the command name.
+ */
+
+#if DARWINV<700
+ cmd = p->P_COMM;
+#else /* DARWINV>=700 */
+ if (!strcmp(p->p_comm, "LaunchCFMApp")) {
+ if (!(cmd = getcmdnm(p->p_pid)))
+ cmd = p->p_comm;
+ } else
+ cmd = p->p_comm;
+#endif /* DARWINV<700 */
+
+ /*
+ * See if process is excluded.
+ *
+ * Read file structure pointers.
+ */
+ if (is_proc_excl(p->p_pid, pgid, (UID_ARG)uid, &pss, &sf))
+ continue;
+ if (!p->p_fd || kread((KA_T)p->p_fd, (char *)&fd, sizeof(fd)))
+ continue;
+ if (!fd.fd_refcnt || fd.fd_lastfile > fd.fd_nfiles)
+ continue;
+ /*
+ * Allocate a local process structure.
+ *
+ * Set kernel's proc structure address.
+ */
+ if (is_cmd_excl(cmd, &pss, &sf))
+ continue;
+ alloc_lproc(p->p_pid, pgid, ppid, (UID_ARG)uid, cmd, (int)pss,
+ (int)sf);
+ Plf = (struct lfile *)NULL;
+ Kpa = Pa[px];
+ /*
+ * Save current working directory information.
+ */
+ if (fd.fd_cdir) {
+ alloc_lfile(CWD, -1);
+ Cfp = (struct file *)NULL;
+ process_node((KA_T)fd.fd_cdir);
+ if (Lf->sf)
+ link_lfile();
+ }
+ /*
+ * Save root directory information.
+ */
+ if (fd.fd_rdir) {
+ alloc_lfile(RTD, -1);
+ Cfp = (struct file *)NULL;
+ process_node((KA_T)fd.fd_rdir);
+ if (Lf->sf)
+ link_lfile();
+ }
+ /*
+ * Process the VM map.
+ */
+ process_map(p->p_pid);
+ /*
+ * Read open file structure pointers.
+ */
+ if (!fd.fd_ofiles || (nf = fd.fd_nfiles) <= 0)
+ continue;
+ nb = (MALLOC_S)(sizeof(struct file *) * nf);
+ if (nb > ofbb) {
+ if (!ofb)
+ ofb = (struct file **)malloc(nb);
+ else
+ ofb = (struct file **)realloc((MALLOC_P *)ofb, nb);
+ if (!ofb) {
+ (void) fprintf(stderr, "%s: PID %d, no file * space\n",
+ Pn, p->p_pid);
+ Exit(1);
+ }
+ ofbb = nb;
+ }
+ if (kread((KA_T)fd.fd_ofiles, (char *)ofb, nb))
+ continue;
+
+ nb = (MALLOC_S)(sizeof(char) * nf);
+ if (nb > pofb) {
+ if (!pof)
+ pof = (char *)malloc(nb);
+ else
+ pof = (char *)realloc((MALLOC_P *)pof, nb);
+ if (!pof) {
+ (void) fprintf(stderr, "%s: PID %d, no file flag space\n",
+ Pn, p->p_pid);
+ Exit(1);
+ }
+ pofb = nb;
+ }
+ if (!fd.fd_ofileflags || kread((KA_T)fd.fd_ofileflags, pof, nb))
+ zeromem(pof, nb);
+
+ /*
+ * Save information on file descriptors.
+ */
+ for (i = 0; i < nf; i++) {
+ if (ofb[i] && !(pof[i] & UF_RESERVED)) {
+ alloc_lfile(NULL, i);
+ process_file((KA_T)(Cfp = ofb[i]));
+ if (Lf->sf) {
+
+#if defined(HASFSTRUCT)
+ if (Fsv & FSV_FG)
+ Lf->pof = (long)pof[i];
+#endif /* defined(HASFSTRUCT) */
+
+ link_lfile();
+ }
+ }
+ }
+ /*
+ * Examine results.
+ */
+ if (examine_lproc())
+ return;
+ }
+}
+
+
+#if DARWINV>=700
+static char *
+getcmdnm(pid)
+ pid_t pid; /* process ID */
+{
+ static int am;
+ static char *ap = (char *)NULL;
+ char *cp, *ep, *sp;
+ int mib[3];
+ size_t sz;
+
+ if (!ap) {
+
+ /*
+ * Allocate space for the maximum argument size.
+ */
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_ARGMAX;
+ sz = sizeof(am);
+ if (sysctl(mib, 2, &am, &sz, NULL, 0) == -1) {
+ (void) fprintf(stderr, "%s: can't get arg max, PID %d\n",
+ Pn, pid);
+ Exit(1);
+ }
+ if (!(ap = (char *)malloc((MALLOC_S)am))) {
+ (void) fprintf(stderr, "%s: no arg ptr (%d) space, PID %d\n",
+ Pn, am, pid);
+ Exit(1);
+ }
+ }
+/*
+ * Get the arguments for the process.
+ */
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROCARGS;
+ mib[2] = pid;
+ sz = (size_t)am;
+ if (sysctl(mib, 3, ap, &sz, NULL, 0) == -1)
+ return((char *)NULL);
+/*
+ * Skip to the first NUL character, which should end the saved exec path.
+ */
+ for (cp = ap; *cp && (cp < (ap + sz)); cp++) {
+ ;
+ }
+ if (cp >= (ap + sz))
+ return((char *)NULL);
+/*
+ * Skip trailing NULs, which should find the beginning of the command.
+ */
+ while (!*cp && (cp < (ap + sz))) {
+ cp++;
+ }
+ if (cp >= (ap + sz))
+ return((char *)NULL);
+/*
+ * Make sure that the command is NUL-terminated.
+ */
+ for (sp = cp; *cp && (cp < (ap + sz)); cp++) {
+ ;
+ }
+ if (cp >= (ap + sz))
+ return((char *)NULL);
+ ep = cp;
+/*
+ * Locate the start of the command's base name and return it.
+ */
+ for (ep = cp, cp--; cp >= sp; cp--) {
+ if (*cp == '/') {
+ return(cp + 1);
+ }
+ }
+ return(sp);
+}
+#endif /* DARWINV>=700 */
+
+
+/*
+ * get_kernel_access() - get access to kernel memory
+ */
+
+static void
+get_kernel_access()
+{
+
+/*
+ * Check kernel version.
+ */
+ (void) ckkv("Darwin", LSOF_VSTR, (char *)NULL, (char *)NULL);
+/*
+ * Set name list file path.
+ */
+ if (!Nmlst)
+ Nmlst = N_UNIX;
+
+#if defined(WILLDROPGID)
+/*
+ * If kernel memory isn't coming from KMEM, drop setgid permission
+ * before attempting to open the (Memory) file.
+ */
+ if (Memory)
+ (void) dropgid();
+#else /* !defined(WILLDROPGID) */
+/*
+ * See if the non-KMEM memory and the name list files are readable.
+ */
+ if ((Memory && !is_readable(Memory, 1))
+ || (Nmlst && !is_readable(Nmlst, 1)))
+ Exit(1);
+#endif /* defined(WILLDROPGID) */
+
+/*
+ * Open kernel memory access.
+ */
+ if ((Kd = open(Memory ? Memory : KMEM, O_RDONLY, 0)) < 0)
+ {
+ (void) fprintf(stderr, "%s: open(%s): %s\n", Pn,
+ Memory ? Memory : KMEM,
+ strerror(errno));
+ Exit(1);
+ }
+ (void) build_Nl(Drive_Nl);
+ if (nlist(Nmlst, Nl) < 0) {
+ (void) fprintf(stderr, "%s: can't read namelist from %s\n",
+ Pn, Nmlst);
+ Exit(1);
+ }
+
+#if defined(WILLDROPGID)
+/*
+ * Drop setgid permission, if necessary.
+ */
+ if (!Memory)
+ (void) dropgid();
+#endif /* defined(WILLDROPGID) */
+
+}
+
+
+/*
+ * get_parent_pid() - get parent process PID
+ */
+
+static pid_t
+get_parent_pid(kpa)
+ KA_T kpa; /* kernel parent process address */
+{
+ struct phash *ph;
+
+ if (kpa) {
+ for (ph = Phash[PHASH(kpa)]; ph; ph = ph->next) {
+ if (ph->ka == kpa)
+ return((pid_t)ph->la->p_pid);
+ }
+ }
+ return((pid_t)0);
+}
+
+
+/*
+ * initialize() - perform all initialization
+ */
+
+void
+initialize()
+{
+ get_kernel_access();
+}
+
+
+/*
+ * kread() - read from kernel memory
+ */
+
+int
+kread(addr, buf, len)
+ KA_T addr; /* kernel memory address */
+ char *buf; /* buffer to receive data */
+ READLEN_T len; /* length to read */
+{
+ int br;
+
+ if ((off_t)addr & (off_t)0x3) {
+
+ /*
+ * No read is possible if the address is not aligned on a word
+ * boundary.
+ */
+ return(1);
+ }
+ if (lseek(Kd, (off_t)addr, SEEK_SET) == (off_t)-1)
+ return(1);
+ br = read(Kd, buf, len);
+ return((br == len) ? 0 : 1);
+}
+
+
+/*
+ * prcess_map() - process VM map
+ */
+
+static void
+process_map(pid)
+ pid_t pid; /* process id */
+{
+ vm_address_t address = 0;
+ mach_msg_type_number_t count;
+ vm_region_extended_info_data_t e_info;
+ int n = 0;
+ mach_port_t object_name;
+ vm_size_t size = 0;
+ vm_map_t task;
+ vm_region_top_info_data_t t_info;
+
+ struct vm_object { /* should come from <vm/vm_object.h> */
+
+#if DARWINV<800
+ KA_T Dummy1[15];
+#else /* DARWINV>=800 */
+ KA_T Dummy1[14];
+#endif /* DARWINV>=800 */
+
+ memory_object_t pager;
+ } vmo;
+
+ struct vnode_pager { /* from <osfmk/vm/bsd_vm.c> */
+ KA_T Dummy1[4];
+ struct vnode *vnode;
+ } vp;
+
+/*
+ * Get the task port associated with the process
+ */
+ if (task_for_pid((mach_port_name_t)mach_task_self(), pid,
+ (mach_port_name_t *)&task)
+ != KERN_SUCCESS) {
+ return;
+ }
+/*
+ * Go through the task's address space, looking for blocks of memory
+ * backed by an external pager (i.e, a "vnode")
+ */
+ for (address = 0;; address += size) {
+ count = VM_REGION_EXTENDED_INFO_COUNT;
+ if (vm_region(task, &address, &size, VM_REGION_EXTENDED_INFO,
+ (vm_region_info_t)&e_info, &count, &object_name)
+ != KERN_SUCCESS) {
+ break;
+ }
+ if (!e_info.external_pager)
+ continue;
+ count = VM_REGION_TOP_INFO_COUNT;
+ if (vm_region(task, &address, &size, VM_REGION_TOP_INFO,
+ (vm_region_info_t)&t_info, &count, &object_name)
+ != KERN_SUCCESS) {
+ break;
+ }
+ /*
+ * The returned "obj_id" is the "vm_object_t" address.
+ */
+ if (!t_info.obj_id)
+ continue;
+ if (kread(t_info.obj_id, (char *)&vmo, sizeof(vmo)))
+ break;
+ /*
+ * If the "pager" is backed by a vnode then the "vm_object_t"
+ * "memory_object_t" address is actually a "struct vnode_pager *".
+ */
+ if (!vmo.pager)
+ continue;
+ if (kread((KA_T)vmo.pager, (char *)&vp, sizeof(vp)))
+ break;
+ (void) enter_vn_text((KA_T)vp.vnode, &n);
+ }
+ return;
+}
+
+
+/*
+ * read_procs() - read proc structures
+ */
+
+static int
+read_procs()
+{
+ int h, i, np, pe;
+ KA_T kp, kpn;
+ MALLOC_S msz;
+ struct proc *p;
+ struct phash *ph, *phn;
+
+ if (!Akp) {
+
+ /*
+ * Get kernel allproc structure pointer once.
+ */
+ if (get_Nl_value("aproc", Drive_Nl, &Akp) < 0 || !Akp) {
+ (void) fprintf(stderr, "%s: can't get proc table address\n",
+ Pn);
+ Exit(1);
+ }
+ }
+/*
+ * Get the current number of processes and calculate PA and Proc[] allocation
+ * sizes large enough to handle it.
+ */
+ if (get_Nl_value("nproc", Drive_Nl, &kp) < 0 || !kp) {
+ (void) fprintf(stderr, "%s: can't get nproc address\n", Pn);
+ Exit(1);
+ }
+ if (kread(kp, (char *)&np, sizeof(np))) {
+ (void) fprintf(stderr, "%s: can't read process count from %s\n",
+ Pn, print_kptr(kp, (char *)NULL, 0));
+ Exit(1);
+ }
+ for (np += np, pe = PINCRSZ; pe < np; pe += PINCRSZ)
+ ;
+/*
+ * Allocate or reallocate the Pa[] and Proc[] tables.
+ */
+ msz = (MALLOC_S)(pe * sizeof(struct proc));
+ if (!Proc)
+ Proc = (struct proc *)malloc(msz);
+ else if (pe > Npa)
+ Proc = (struct proc *)realloc((MALLOC_P *)Proc, msz);
+ if (!Proc) {
+ (void) fprintf(stderr, "%s: no space for proc table\n", Pn);
+ Exit(1);
+ }
+ msz = (MALLOC_S)(pe * sizeof(KA_T));
+ if (!Pa)
+ Pa = (KA_T *)malloc(msz);
+ else if (pe > Npa)
+ Pa = (KA_T *)realloc((MALLOC_P *)Pa, msz);
+ if (!Pa) {
+ (void) fprintf(stderr, "%s: no space for proc addr table\n", Pn);
+ Exit(1);
+ }
+ Npa = pe;
+/*
+ * Allocate or reset the Phash[] table.
+ */
+ if (!Phash) {
+ Phash = (struct phash **)calloc(NPHASH, sizeof(struct phash *));
+ } else {
+ for (h = 0; h < NPHASH; h++) {
+ for (ph = Phash[h]; ph; ph = phn) {
+ phn = ph->next;
+ (void) free((MALLOC_P *)ph);
+ }
+ Phash[h] = (struct phash *)NULL;
+ }
+ }
+ if (!Phash) {
+ (void) fprintf(stderr, "%s: no space for proc address hash\n", Pn);
+ Exit(1);
+ }
+/*
+ * Read the proc structures on the kernel's chain.
+ */
+ for (i = Np = 0, kp = Akp, p = Proc, pe += pe;
+ kp && i < pe;
+ i++, kp = kpn)
+ {
+ if (kread(kp, (char *)p, sizeof(struct proc)))
+ break;
+ kpn = (KA_T)(((KA_T)p->p_list.le_next == Akp) ? NULL
+ : p->p_list.le_next);
+ if (p->p_stat == 0 || p->p_stat == SZOMB)
+ continue;
+ /*
+ * Cache the proc structure's addresses.
+ */
+ h = PHASH(kp);
+ if (!(ph = (struct phash *)malloc((MALLOC_S)sizeof(struct phash))))
+ {
+ (void) fprintf(stderr, "%s: no space for phash struct\n", Pn);
+ Exit(1);
+ }
+ ph->ka = kp;
+ ph->la = p;
+ ph->next = Phash[h];
+ Phash[h] = ph;
+ p++;
+ Pa[Np++] = kp;
+ if (Np >= Npa) {
+
+ /*
+ * Enlarge Pa[] and Proc[].
+ */
+ msz = (int)((Npa + PINCRSZ) * sizeof(struct proc));
+ if (!(Proc = (struct proc *)realloc((MALLOC_P *)Proc, msz))) {
+ (void) fprintf(stderr, "%s: no additional proc space\n",
+ Pn);
+ Exit(1);
+ }
+ msz = (int)((Npa + PINCRSZ) * sizeof(KA_T));
+ if (!(Pa = (KA_T *)realloc((MALLOC_P *)Pa, msz))) {
+ (void) fprintf(stderr,
+ "%s: no additional proc addr space\n", Pn);
+ Exit(1);
+ }
+ Npa += PINCRSZ;
+ }
+ }
+/*
+ * If too many processes were read, the chain following probably failed;
+ * report that and exit.
+ */
+ if (i >= pe) {
+ (void) fprintf(stderr, "%s: can't follow kernel proc chain\n", Pn);
+ Exit(1);
+ }
+/*
+ * If not in repeat mode, reduce Pa[] and Proc[] to their minimums.
+ */
+ if (Np < Npa && !RptTm) {
+ msz = (MALLOC_S)(Np * sizeof(struct proc));
+ if (!(Proc = (struct proc *)realloc((MALLOC_P *)Proc, msz))) {
+ (void) fprintf(stderr, "%s: can't reduce proc table\n", Pn);
+ Exit(1);
+ }
+ msz = (MALLOC_S)(Np * sizeof(KA_T));
+ if (!(Pa = (KA_T *)realloc((MALLOC_P *)Pa, msz))) {
+ (void) fprintf(stderr, "%s: can't reduce proc addr table\n",
+ Pn);
+ Exit(1);
+ }
+ Npa = Np;
+ }
+/*
+ * Return 0 if any processes were loaded; 1 if none were.
+ */
+ return((Np > 0) ? 0 : 1);
+}
diff --git a/dialects/darwin/kmem/dproto.h b/dialects/darwin/kmem/dproto.h
new file mode 100644
index 0000000..15ddb64
--- /dev/null
+++ b/dialects/darwin/kmem/dproto.h
@@ -0,0 +1,62 @@
+/*
+ * dproto.h - Darwin function prototypes for /dev/kmem-based lsof
+ *
+ * The _PROTOTYPE macro is defined in the common proto.h.
+ */
+
+
+/*
+ * Copyright 1994 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.
+ */
+
+
+/*
+ * $Id: dproto.h,v 1.4 2005/11/01 20:24:51 abe Exp $
+ */
+
+_PROTOTYPE(extern int is_file_named,(char *p, int cd));
+_PROTOTYPE(extern struct l_vfs *readvfs,(KA_T vm));
+
+#if defined(HASKQUEUE)
+_PROTOTYPE(extern void process_kqueue,(KA_T ka));
+#endif /* defined(HASKQUEUE) */
+
+#if defined(HASPIPEFN)
+_PROTOTYPE(extern void process_pipe,(KA_T pa));
+#endif /* defined(HASPIPEFN) */
+
+#if defined(HASPSXSEM)
+_PROTOTYPE(extern void process_psxsem,(KA_T pa));
+#endif /* defined(HASPSXSEM) */
+
+#if defined(HASPSXSHM)
+_PROTOTYPE(extern void process_psxshm,(KA_T pa));
+#endif /* defined(HASPSXSHM) */
+
+#if defined(HAS9660FS)
+_PROTOTYPE(extern int read_iso_node,(struct vnode *v, dev_t *d, int *dd, INODETYPE *ino, long *nl, SZOFFTYPE *sz));
+#endif /* defined(HAS9660FS) */
+
+_PROTOTYPE(extern void process_socket,(KA_T sa));
diff --git a/dialects/darwin/kmem/dsock.c b/dialects/darwin/kmem/dsock.c
new file mode 100644
index 0000000..a5a993b
--- /dev/null
+++ b/dialects/darwin/kmem/dsock.c
@@ -0,0 +1,478 @@
+/*
+ * dsock.c - Darwin socket processing functions for /dev/kmem-based lsof
+ */
+
+/*
+ * Special Darwin socket info: Justin Walker, 000927
+ */
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dsock.c,v 1.11 2005/11/01 20:24:51 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+#if defined(HASIPv6)
+/*
+ * IPv6_2_IPv4() -- macro to define the address of an IPv4 address contained
+ * in an IPv6 address
+ */
+
+#define IPv6_2_IPv4(v6) (((uint8_t *)((struct in6_addr *)v6)->s6_addr)+12)
+#endif /* defined(HASIPv6) */
+
+
+/*
+ * process_socket() - process socket
+ */
+
+void
+process_socket(sa)
+ KA_T sa; /* socket address in kernel */
+{
+ struct domain d;
+ unsigned char *fa = (unsigned char *)NULL;
+ int fam, lp;
+ int fp = 0;
+ struct inpcb inp;
+ unsigned char *la = (unsigned char *)NULL;
+ struct protosw p;
+ struct socket s;
+ struct tcpcb t;
+ KA_T ta = (KA_T)NULL;
+ struct unpcb uc, unp;
+ struct sockaddr_un *ua = NULL;
+ struct sockaddr_un un;
+ int unl;
+
+#if defined(HASIPv6)
+ struct in6pcb in6p;
+#endif /* defined(HASIPv6) */
+
+#if defined(AF_SYSTEM)
+ struct kern_event_pcb kev_cb;
+#endif /* defined(AF_SYSTEM) */
+
+#if defined(AF_NDRV)
+ char buf[IFNAMSIZ];
+ struct ndrv_cb ndrv_cb;
+ struct ifnet ifnet;
+#endif /* defined(AF_NDRV) */
+
+ (void) snpf(Lf->type, sizeof(Lf->type), "sock");
+ Lf->inp_ty = 2;
+/*
+ * Read the socket, protocol, and domain structures.
+ */
+ if (!sa) {
+ enter_nm("no socket address");
+ return;
+ }
+ if (kread(sa, (char *)&s, sizeof(s))) {
+ (void) snpf(Namech, Namechl, "can't read socket struct from %s",
+ print_kptr(sa, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ if (!s.so_type) {
+ enter_nm("no socket type");
+ return;
+ }
+ if (!s.so_proto
+ || kread((KA_T)s.so_proto, (char *)&p, sizeof(p))) {
+ (void) snpf(Namech, Namechl, "can't read protocol switch from %s",
+ print_kptr((KA_T)s.so_proto, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ if (!p.pr_domain
+ || kread((KA_T)p.pr_domain, (char *)&d, sizeof(d))) {
+ (void) snpf(Namech, Namechl, "can't read domain struct from %s",
+ print_kptr((KA_T)p.pr_domain, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+/*
+ * Save size information.
+ */
+ if (Fsize) {
+ if (Lf->access == 'r')
+ Lf->sz = (SZOFFTYPE)s.so_rcv.sb_cc;
+ else if (Lf->access == 'w')
+ Lf->sz = (SZOFFTYPE)s.so_snd.sb_cc;
+ else
+ Lf->sz = (SZOFFTYPE)(s.so_rcv.sb_cc + s.so_snd.sb_cc);
+ Lf->sz_def = 1;
+ } else
+ Lf->off_def = 1;
+
+#if defined(HASTCPTPIQ)
+ Lf->lts.rq = s.so_rcv.sb_cc;
+ Lf->lts.sq = s.so_snd.sb_cc;
+ Lf->lts.rqs = Lf->lts.sqs = 1;
+#endif /* defined(HASTCPTPIQ) */
+
+#if defined(HASSOOPT)
+ Lf->lts.ltm = (unsigned int)(s.so_linger & 0xffff);
+ Lf->lts.opt = (unsigned int)(s.so_options & 0xffff);
+ Lf->lts.pqlen = (unsigned int)s.so_incqlen;
+ Lf->lts.qlen = (unsigned int)s.so_qlen;
+ Lf->lts.qlim = (unsigned int)s.so_qlimit;
+ Lf->lts.rbsz = (unsigned long)s.so_rcv.sb_mbmax;
+ Lf->lts.sbsz = (unsigned long)s.so_snd.sb_mbmax;
+ Lf->lts.pqlens = Lf->lts.qlens = Lf->lts.qlims = Lf->lts.rbszs
+ = Lf->lts.sbszs = (unsigned char)1;
+#endif /* defined(HASSOOPT) */
+
+#if defined(HASSOSTATE)
+ Lf->lts.ss = (unsigned int)s.so_state;
+#endif /* defined(HASSOSTATE) */
+
+/*
+ * Process socket by the associated domain family.
+ */
+ switch ((fam = d.dom_family)) {
+/*
+ * Process an Internet domain socket.
+ */
+ case AF_INET:
+
+#if defined(HASIPv6)
+ case AF_INET6:
+#endif /* defined(HASIPv6) */
+
+ if (Fnet) {
+ if (!FnetTy
+ || ((FnetTy == 4) && (fam == AF_INET))
+
+#if defined(HASIPv6)
+ || ((FnetTy == 6) && (fam == AF_INET6))
+#endif /* defined(HASIPv6) */
+
+ )
+ Lf->sf |= SELNET;
+ }
+ printiproto(p.pr_protocol);
+
+#if defined(HASIPv6)
+ (void) snpf(Lf->type, sizeof(Lf->type),
+ (fam == AF_INET) ? "IPv4" : "IPv6");
+#else /* !defined(HASIPv6) */
+ (void) snpf(Lf->type, sizeof(Lf->type), "inet");
+#endif /* defined(HASIPv6) */
+
+#if defined(HASIPv6)
+ if (fam == AF_INET6) {
+
+ /*
+ * Read IPv6 protocol control block.
+ */
+ if (!s.so_pcb
+ || kread((KA_T)s.so_pcb, (char *)&in6p, sizeof(in6p)))
+ {
+ (void) snpf(Namech, Namechl, "can't read in6pcb at %s",
+ print_kptr((KA_T)s.so_pcb, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ /*
+ * Save IPv6 address information.
+ */
+ enter_dev_ch(print_kptr((KA_T)(in6p.in6p_ppcb ? in6p.in6p_ppcb
+ : s.so_pcb),
+ (char *)NULL, 0));
+ if (p.pr_protocol == IPPROTO_TCP)
+ ta = (KA_T)in6p.in6p_ppcb;
+ la = (unsigned char *)&in6p.in6p_laddr;
+ lp = (int)ntohs(in6p.in6p_lport);
+ if (!IN6_IS_ADDR_UNSPECIFIED(&in6p.in6p_faddr)
+ || in6p.in6p_fport)
+ {
+ fa = (unsigned char *)&in6p.in6p_faddr;
+ fp = (int)ntohs(in6p.in6p_fport);
+ }
+ } else
+#endif /* defined(HASIPv6) */
+
+ {
+
+ /*
+ * Read IPv4 protocol control block.
+ */
+ if (!s.so_pcb
+ || kread((KA_T)s.so_pcb, (char *)&inp, sizeof(inp))) {
+ if (!s.so_pcb) {
+ (void) snpf(Namech, Namechl, "no PCB%s%s",
+ (s.so_state & SS_CANTSENDMORE) ? ", CANTSENDMORE"
+ : "",
+ (s.so_state & SS_CANTRCVMORE) ? ", CANTRCVMORE"
+ : "");
+ } else {
+ (void) snpf(Namech, Namechl, "can't read inpcb at %s",
+ print_kptr((KA_T)s.so_pcb, (char *)NULL, 0));
+ }
+ enter_nm(Namech);
+ return;
+ }
+ /*
+ * Print Internet socket information.
+ */
+ enter_dev_ch(print_kptr((KA_T)(inp.inp_ppcb ? inp.inp_ppcb
+ : s.so_pcb),
+ (char *)NULL, 0));
+ /*
+ * Save IPv4 address information.
+ */
+ if (p.pr_protocol == IPPROTO_TCP)
+ ta = (KA_T)inp.inp_ppcb;
+ la = (unsigned char *)&inp.inp_laddr;
+ lp = (int)ntohs(inp.inp_lport);
+ if (inp.inp_faddr.s_addr != INADDR_ANY || inp.inp_fport) {
+ fa = (unsigned char *)&inp.inp_faddr;
+ fp = (int)ntohs(inp.inp_fport);
+ }
+ }
+
+#if defined(HASIPv6)
+ if ((fam == AF_INET6)
+ && ((la && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)la))
+ || ((fa && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)fa))))) {
+
+ /*
+ * Adjust for IPv4 addresses mapped in IPv6 addresses.
+ */
+ if (la)
+ la = (unsigned char *)IPv6_2_IPv4(la);
+ if (fa)
+ fa = (unsigned char *)IPv6_2_IPv4(fa);
+ fam = AF_INET;
+ }
+#endif /* defined(HASIPv6) */
+
+ /*
+ * Enter local and remote addresses by address family.
+ */
+ if (fa || la)
+ (void) ent_inaddr(la, lp, fa, fp, fam);
+ if (ta && !kread(ta, (char *)&t, sizeof(t))) {
+ Lf->lts.type = 0;
+ Lf->lts.state.i = (int)t.t_state;
+
+#if defined(HASSOOPT)
+ Lf->lts.kai = (unsigned int)t.t_timer[TCPT_KEEP];
+#endif /* defined(HASSOOPT) */
+
+#if defined(HASTCPOPT)
+ Lf->lts.mss = (unsigned long)t.t_maxseg;
+ Lf->lts.msss = (unsigned char)1;
+ Lf->lts.topt = (unsigned int)t.t_flags;
+#endif /* defined(HASTCPOPT) */
+
+ }
+ break;
+
+#if defined(AF_NDRV)
+/*
+ * Process an NDRV domain socket.
+ */
+ case AF_NDRV:
+ {
+ (void) snpf(Lf->type, sizeof(Lf->type), "ndrv");
+ /*
+ * Read protocol control block.
+ */
+ if (!s.so_pcb
+ || kread((KA_T)s.so_pcb, (char *)&ndrv_cb, sizeof(ndrv_cb))) {
+ (void) snpf(Namech, Namechl, "can't read ndrv_cb at %s",
+ print_kptr((KA_T)s.so_pcb, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ /*
+ * Print NDRV socket information.
+ */
+ enter_dev_ch(print_kptr((KA_T)(s.so_pcb), (char *)NULL, 0));
+ /*
+ * Print device name, if bound
+ */
+ if (!ndrv_cb.nd_if
+ || kread((KA_T)ndrv_cb.nd_if, (char *)&ifnet, sizeof(ifnet))) {
+ (void) snpf(Namech, Namechl, "can't read ifnet at %s",
+ print_kptr((KA_T)ndrv_cb.nd_if, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ if (!ifnet.if_name
+ || kread((KA_T)ifnet.if_name, buf, sizeof(buf))) {
+ (void) snpf(Namech, Namechl, "can't read ifnet.if_name at %s",
+ print_kptr((KA_T)ifnet.if_name, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ (void) snpf(Namech, Namechl, "-> %s%d", buf, ifnet.if_unit);
+ }
+ break;
+#endif /* defined(AF_NDRV) */
+
+#if defined(pseudo_AF_KEY)
+/*
+ * Process an [internal] key-management function socket
+ */
+ case pseudo_AF_KEY:
+ (void) snpf(Lf->type, sizeof(Lf->type), "key");
+ break;
+#endif /* defined(pseudo_AF_KEY) */
+
+#if defined(AF_SYSTEM)
+/*
+ * Process a SYSTEM domain socket
+ */
+ case AF_SYSTEM:
+ (void) snpf(Lf->type, sizeof(Lf->type), "systm");
+ /*
+ * Read protocol control block.
+ */
+ if (!s.so_pcb
+ || kread((KA_T)s.so_pcb, (char *)&kev_cb, sizeof(kev_cb))) {
+ (void) snpf(Namech, Namechl, "can't read kev_cb at %s",
+ print_kptr((KA_T)s.so_pcb, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ /*
+ * Print SYSTEM socket information.
+ */
+ enter_dev_ch(print_kptr((KA_T)(s.so_pcb), (char *)NULL, 0));
+ (void) snpf(Namech, Namechl, "[%lx:%lx:%lx]",
+ kev_cb.vendor_code_filter,
+ kev_cb.class_filter, kev_cb.subclass_filter);
+ break;
+#endif /* defined(AF_SYSTEM) */
+
+#if defined(AF_PPP)
+/*
+ * Process a PPP domain socket
+ */
+ case AF_PPP:
+ (void) snpf(Lf->type, sizeof(Lf->type), "ppp");
+ break;
+#endif /* defined(AF_PPP) */
+
+/*
+ * Process a ROUTE domain socket.
+ */
+ case AF_ROUTE:
+ (void) snpf(Lf->type, sizeof(Lf->type), "rte");
+ if (s.so_pcb)
+ enter_dev_ch(print_kptr((KA_T)(s.so_pcb), (char *)NULL, 0));
+ else
+ (void) snpf(Namech, Namechl, "no protocol control block");
+ if (!Fsize)
+ Lf->off_def = 1;
+ break;
+/*
+ * Process a Unix domain socket.
+ */
+ case AF_UNIX:
+ if (Funix)
+ Lf->sf |= SELUNX;
+ (void) snpf(Lf->type, sizeof(Lf->type), "unix");
+ /*
+ * Read Unix protocol control block and the Unix address structure.
+ */
+
+ enter_dev_ch(print_kptr(sa, (char *)NULL, 0));
+ if (!s.so_pcb
+ || kread((KA_T)s.so_pcb, (char *)&unp, sizeof(unp))) {
+ (void) snpf(Namech, Namechl, "can't read unpcb at %s",
+ print_kptr((KA_T)s.so_pcb, (char *)NULL, 0));
+ break;
+ }
+ if ((struct socket *)sa != unp.unp_socket) {
+ (void) snpf(Namech, Namechl, "unp_socket (%s) mismatch",
+ print_kptr((KA_T)unp.unp_socket, (char *)NULL, 0));
+ break;
+ }
+ if (unp.unp_addr) {
+ if (kread((KA_T)unp.unp_addr, (char *)&un, sizeof(un))) {
+ (void) snpf(Namech, Namechl, "can't read unp_addr at %s",
+ print_kptr((KA_T)unp.unp_addr, (char *)NULL, 0));
+ break;
+ }
+ ua = &un;
+ }
+ if (!ua) {
+ ua = &un;
+ (void) bzero((char *)ua, sizeof(un));
+ ua->sun_family = AF_UNSPEC;
+ }
+ /*
+ * Print information on Unix socket that has no address bound
+ * to it, although it may be connected to another Unix domain
+ * socket as a pipe.
+ */
+ if (ua->sun_family != AF_UNIX) {
+ if (ua->sun_family == AF_UNSPEC) {
+ if (unp.unp_conn) {
+ if (kread((KA_T)unp.unp_conn, (char *)&uc, sizeof(uc)))
+ (void) snpf(Namech, Namechl,
+ "can't read unp_conn at %s",
+ print_kptr((KA_T)unp.unp_conn,(char *)NULL,0));
+ else
+ (void) snpf(Namech, Namechl, "->%s",
+ print_kptr((KA_T)uc.unp_socket,(char *)NULL,0));
+ } else
+ (void) snpf(Namech, Namechl, "->(none)");
+ } else
+ (void) snpf(Namech, Namechl, "unknown sun_family (%d)",
+ ua->sun_family);
+ break;
+ }
+ if (ua->sun_path[0]) {
+ unl = ua->sun_len - offsetof(struct sockaddr_un, sun_path);
+ if ((unl < 0) || (unl >= sizeof(ua->sun_path)))
+ unl = sizeof(ua->sun_path) - 1;
+ ua->sun_path[unl] = '\0';
+ if (ua->sun_path[0] && Sfile && is_file_named(ua->sun_path, 0))
+ Lf->sf |= SELNM;
+ if (ua->sun_path[0] && !Namech[0])
+ (void) snpf(Namech, Namechl, "%s", ua->sun_path);
+ } else
+ (void) snpf(Namech, Namechl, "no address");
+ break;
+ default:
+ printunkaf(fam, 1);
+ }
+ if (Namech[0])
+ enter_nm(Namech);
+}
diff --git a/dialects/darwin/kmem/dstore.c b/dialects/darwin/kmem/dstore.c
new file mode 100644
index 0000000..06a91f7
--- /dev/null
+++ b/dialects/darwin/kmem/dstore.c
@@ -0,0 +1,105 @@
+/*
+ * dstore.c - Darwin global storage for /dev/kmem-based lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dstore.c,v 1.5 2005/11/01 20:24:51 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+struct file *Cfp; /* curent file's file struct pointer */
+
+
+/*
+ * Drive_Nl -- table to drive the building of Nl[] via build_Nl()
+ * (See lsof.h and misc.c.)
+ */
+
+struct drive_Nl Drive_Nl[] = {
+
+ { "aproc", "_allproc" },
+ { "nproc", "_nprocs" },
+ { X_NCACHE, "_nchashtbl" },
+ { X_NCSIZE, "_nchash" },
+ { "", "" },
+ { NULL, NULL }
+};
+
+int Kd = -1; /* KMEM descriptor */
+KA_T Kpa; /* kernel proc struct address */
+struct l_vfs *Lvfs = NULL; /* local vfs structure table */
+
+int Np = 0; /* number of kernel processes */
+
+struct kinfo_proc *P = NULL; /* local process table copy */
+
+#if defined(HASFSTRUCT)
+/*
+ * Pff_tab[] - table for printing file flags
+ */
+
+struct pff_tab Pff_tab[] = {
+ { (long)FREAD, FF_READ },
+ { (long)FWRITE, FF_WRITE },
+ { (long)FNONBLOCK, FF_NBLOCK },
+ { (long)FNDELAY, FF_NDELAY },
+ { (long)FAPPEND, FF_APPEND },
+ { (long)FASYNC, FF_ASYNC },
+ { (long)FFSYNC, FF_FSYNC },
+ { (long)FMARK, FF_MARK },
+ { (long)FDEFER, FF_DEFER },
+ { (long)FHASLOCK, FF_HASLOCK },
+ { (long)O_NOCTTY, FF_NOCTTY },
+ { (long)O_EVTONLY, FF_EVTONLY },
+ { (long)0, NULL }
+};
+
+
+/*
+ * Pof_tab[] - table for print process open file flags
+ */
+
+struct pff_tab Pof_tab[] = {
+
+# if defined(UF_EXCLOSE)
+ { (long)UF_EXCLOSE, POF_CLOEXEC },
+# endif /* defined(UF_EXCLOSE) */
+
+# if defined(UF_MAPPED)
+ { (long)UF_MAPPED, POF_MAPPED },
+# endif /* defined(UF_MAPPED) */
+
+ { (long)0, NULL }
+};
+#endif /* defined(HASFSTRUCT) */
diff --git a/dialects/darwin/kmem/machine.h b/dialects/darwin/kmem/machine.h
new file mode 100644
index 0000000..ebb2490
--- /dev/null
+++ b/dialects/darwin/kmem/machine.h
@@ -0,0 +1,647 @@
+/*
+ * machine.h - Darwin definitions for /dev/kmem-based lsof
+ */
+
+
+/*
+ * Copyright 1994 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.
+ */
+
+
+/*
+ * $Id: machine.h,v 1.16 2010/07/29 16:03:04 abe Exp $
+ */
+
+
+#if !defined(LSOF_MACHINE_H)
+#define LSOF_MACHINE_H 1
+
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+# if DARWINV>=800
+#include "/usr/include/string.h"
+# endif /* DARWINV>=800 */
+
+
+/*
+ * CAN_USE_CLNT_CREATE is defined for those dialects where RPC clnt_create()
+ * can be used to obtain a CLIENT handle in lieu of clnttcp_create().
+ */
+
+#define CAN_USE_CLNT_CREATE 1
+
+
+/*
+ * DEVDEV_PATH defines the path to the directory that contains device
+ * nodes.
+ */
+
+#define DEVDEV_PATH "/dev"
+
+
+/*
+ * GET_MAX_FD is defined for those dialects that provide a function other than
+ * getdtablesize() to obtain the maximum file descriptor number plus one.
+ */
+
+/* #define GET_MAX_FD ? */
+
+
+/*
+ * HASAOPT is defined for those dialects that have AFS support; it specifies
+ * that the default path to an alternate AFS kernel name list file may be
+ * supplied with the -A <path> option.
+ */
+
+/* #define HASAOPT 1 */
+
+
+/*
+ * HASBLKDEV is defined for those dialects that want block device information
+ * recorded in BDevtp[].
+ */
+
+#define HASBLKDEV 1
+
+
+/*
+ * HASDCACHE is defined for those dialects that support a device cache
+ * file.
+ *
+ * HASENVDC defined the name of an environment variable that contains the
+ * device cache file path. The HASENVDC environment variable is ignored when
+ * the lsof process is setuid(root) or its real UID is 0.
+ *
+ * HASPERSDC defines the format for the last component of a personal device
+ * cache file path. The first will be the home directory of the real UID that
+ * executes lsof.
+ *
+ * HASPERSDCPATH defines the environment variable whose value is the middle
+ * component of the personal device cache file path. The middle component
+ * follows the home directory and precedes the results of applying HASPERSDC.
+ * The HASPERSDCPATH environment variable is ignored when the lsof process is
+ * setuid(root) or its real UID is 0.
+ *
+ * HASSYSDC defines a public device cache file path. When it's defined, it's
+ * used as the path from which to read the device cache.
+ *
+ * Consult the 00DCACHE and 00FAQ files of the lsof distribution for more
+ * information on device cache file path construction.
+ */
+
+/* #define HASDCACHE 1 */
+/* #define HASENVDC "LSOFDEVCACHE" */
+/* #define HASPERSDC "%h/%p.lsof_%L" */
+/* #define HASPERSDCPATH "LSOFPERSDCPATH" */
+/* #define HASSYSDC "/your/choice/of/path" */
+
+
+/*
+ * HASCDRNODE is defined for those dialects that have CD-ROM nodes.
+ */
+
+/* #define HASCDRNODE 1 */
+
+
+/*
+ * HASFIFONODE is defined for those dialects that have FIFO nodes.
+ */
+
+/* #define HASFIFONODE 1 */
+
+
+/*
+ * HASFSINO is defined for those dialects that have the file system
+ * inode element, fs_ino, in the lfile structure definition in lsof.h.
+ */
+
+/* #define HASFSINO 1 */
+
+
+/*
+ * HASFSTRUCT is defined if the dialect has a file structure.
+ *
+ * FSV_DEFAULT defines the default set of file structure values to list.
+ * It defaults to zero (0), but may be made up of a combination of the
+ * FSV_* symbols from lsof.h.
+ *
+ * HASNOFSADDR -- has no file structure address
+ * HASNOFSFLAGS -- has no file structure flags
+ * HASNOFSCOUNT -- has no file structure count
+ * HASNOFSNADDR -- has no file structure node address
+ */
+
+#define HASFSTRUCT 1
+/* #define FSV_DEFAULT FSV_? | FSV_? | FSV_? */
+/* #define HASNOFSADDR 1 has no file structure address */
+/* #define HASNOFSFLAGS 1 has no file structure flags */
+/* #define HASNOFSCOUNT 1 has no file structure count */
+/* #define HASNOFSNADDR 1 has no file structure node address */
+
+
+/*
+ * HASGNODE is defined for those dialects that have gnodes.
+ */
+
+/* #define HASGNODE 1 */
+
+
+/*
+ * HASHSNODE is defined for those dialects that have High Sierra nodes.
+ */
+
+/* #define HASHSNODE 1 */
+
+
+/*
+ * HASINODE is defined for those dialects that have inodes and wish to
+ * use readinode() from node.c.
+ */
+
+# if DARWINV<800
+#define HASINODE 1
+# endif /* DARWINV<800 */
+
+
+/*
+ * HASINTSIGNAL is defined for those dialects whose signal function returns
+ * an int.
+ */
+
+/* #define HASINTSIGNAL 1 */
+
+
+/*
+ * HASKERNIDCK is defined for those dialects that support the comparison of
+ * the build to running kernel identity.
+ */
+
+#define HASKERNIDCK 1
+
+
+/*
+ * HASKOPT is defined for those dialects that support the -k option of
+ * reading the kernel's name list from an optional file.
+ */
+
+#define HASKOPT 1
+
+
+/*
+ * HASLFILEADD is defined for those dialects that need additional elements
+ * in struct lfile. The HASLFILEADD definition is a macro that defines
+ * them. If any of the additional elements need to be preset in the
+ * alloc_lfile() function of proc.c, the SETLFILEADD macro may be defined
+ * to do that.
+ *
+ * If any additional elements need to be cleared in alloc_lfile() or in the
+ * free_proc() function of proc.c, the CLRLFILEADD macro may be defined to
+ * do that. Note that CLRLFILEADD takes one argument, the pointer to the
+ * lfile struct. The CLRLFILEADD macro is expected to expand to statements
+ * that are complete -- i.e., have terminating semi-colons -- so the macro is
+ * called without a terminating semicolon by proc.c.
+ *
+ * The HASXOPT definition may be used to select the conditions under which
+ * private lfile elements are used.
+ */
+
+# if DARWINV>=800
+#define HASLFILEADD char *V_path;
+#define CLRLFILEADD(lf) if (lf->V_path) { \
+ (void) free((FREE_P *)lf->V_path); \
+ lf->V_path = (char *)NULL; \
+ }
+#define SETLFILEADD Lf->V_path = (char *)NULL;
+# endif /* DARWINV>=800 */
+
+
+/*
+ * HASMNTSTAT indicates the dialect supports the mount stat(2) result option
+ * in its l_vfs and mounts structures.
+ */
+
+/* #define HASMNTSTAT 1 */
+
+
+/*
+ * HASMNTSUP is defined for those dialects that support the mount supplement
+ * option.
+ */
+
+/* #define HASMNTSUP 1 */
+
+
+/*
+ * HASMOPT is defined for those dialects that support the reading of
+ * kernel memory from an alternate file.
+ */
+
+#define HASMOPT 1
+
+
+/*
+ * HASNCACHE is defined for those dialects that have a kernel name cache
+ * that lsof can search. A value of 1 directs printname() to prefix the
+ * cache value with the file system directory name; 2, avoid the prefix.
+ *
+ * NCACHELDPFX is a set of C commands to execute before calling ncache_load().
+ *
+ * NCACHELDSFX is a set of C commands to execute after calling ncache_load().
+ */
+
+# if DARWINV<800
+#define HASNCACHE 1
+/* #define NCACHELDPFX ??? */
+/* #define NCACHELDSFX ??? */
+# else /* DARWINV>=800 */
+/* #define HASNCACHE 1 */
+/* #define NCACHELDPFX ??? */
+/* #define NCACHELDSFX ??? */
+# endif /* DARWINV<800 */
+
+
+/*
+ * HASNLIST is defined for those dialects that use nlist() to acccess
+ * kernel symbols.
+ */
+
+#define HASNLIST 1
+
+
+/*
+ * HASPIPEFN is defined for those dialects that have a special function to
+ * process DTYPE_PIPE file structure entries. Its value is the name of the
+ * function.
+ *
+ * NOTE: don't forget to define a prototype for this function in dproto.h.
+ */
+
+# if DARWINV<800
+/* #define HASPIPEFN process_pipe? */
+# else /* DARWINV>=800 */
+#define HASPIPEFN process_pipe
+# endif /* DARWINV<800 */
+
+
+/*
+ * HASPIPENODE is defined for those dialects that have pipe nodes.
+ */
+
+/* #define HASPIPENODE 1 */
+
+
+/*
+ * HASPMAPENABLED is defined when the reporting of portmapper registration
+ * info is enabled by default.
+ */
+
+/* #define HASPMAPENABLED 1 */
+
+
+/*
+ * HASPPID is defined for those dialects that support identification of
+ * the parent process IDentifier (PPID) of a process.
+ */
+#define HASPPID 1
+
+
+/*
+ * HASPRINTDEV, HASPRINTINO, HASPRINTNM, HASPRINTOFF, and HASPRINTSZ
+ * define private dialect-specific functions for printing DEVice numbers,
+ * INOde numbers, NaMes, file OFFsets, and file SiZes. The functions are
+ * called from print_file().
+ */
+
+/* #define HASPRINTDEV print_dev? */
+/* #define HASPRINTINO print_ino? */
+/* #define HASPRINTNM print_nm? */
+/* #define HASPRINTOFF print_off? */
+/* #define HASPRINTSZ print_sz? */
+
+
+/*
+ * HASPRIVFILETYPE and PRIVFILETYPE are defined for dialects that have a
+ * file structure type that isn't defined by a DTYPE_* symbol. They are
+ * used in lib/prfp.c to select the type's processing.
+ *
+ * PRIVFILETYPE is the definition of the f_type value in the file struct.
+ *
+ * HASPRIVFILETYPE is the name of the processing function.
+ */
+
+/* #define HASPRIVFILETYPE process_shmf? */
+/* #define PRIVFILETYPE ?? */
+
+
+/*
+ * HASPRIVNMCACHE is defined for dialects that have a private method for
+ * printing cached NAME column values for some files. HASPRIVNAMECACHE
+ * is defined to be the name of the function.
+ *
+ * The function takes one argument, a struct lfile pointer to the file, and
+ * returns non-zero if it prints a name to stdout.
+ */
+
+# if DARWINV<800
+/* #define HASPRIVNMCACHE <function name> */
+# else /* DARWINV>=800 */
+#define HASPRIVNMCACHE print_v_path
+# endif /* DARWINV<800 */
+
+
+/*
+ * HASPRIVPRIPP is defined for dialects that have a private function for
+ * printing IP protocol names. When HASPRIVPRIPP isn't defined, the
+ * IP protocol name printing function defaults to printiprto().
+ */
+
+/* #define HASPRIVPRIPP 1 */
+
+
+/*
+ * HASPROCFS is defined for those dialects that have a proc file system --
+ * usually /proc and usually in SYSV4 derivatives.
+ *
+ * HASFSTYPE is defined as 1 for those systems that have a file system type
+ * string, st_fstype, in the stat() buffer; 2, for those systems that have a
+ * file system type integer in the stat() buffer, named MOUNTS_STAT_FSTYPE;
+ * 0, for systems whose stat(2) structure has no file system type member. The
+ * additional symbols MOUNTS_FSTYPE, RMNT_FSTYPE, and RMNT_STAT_FSTYPE may be
+ * defined in dlsof.h to direct how the readmnt() function in lib/rmnt.c
+ * preserves these stat(2) and getmntent(3) buffer values in the local mounts
+ * structure.
+ *
+ * The defined value is the string that names the file system type.
+ *
+ * The HASPROCFS definition usually must be accompanied by the HASFSTYPE
+ * definition and the providing of an fstype element in the local mounts
+ * structure (defined in dlsof.h).
+ *
+ * The HASPROCFS definition may be accompanied by the HASPINODEN definition.
+ * HASPINODEN specifies that searching for files in HASPROCFS is to be done
+ * by inode number.
+ */
+
+# if defined(HASPROCFS)
+#undef HASPROCFS
+#define HASPROCFS "proc"
+# endif /* defined(HASPROCFS) */
+
+/* #define HASPROCFS "proc?" */
+/* #define HASFSTYPE 1 */
+
+#define HASPINODEN 1
+
+
+/*
+ * HASRNODE is defined for those dialects that have rnodes.
+ */
+
+/* #define HASRNODE 1 */
+
+
+/*
+ * Define HASSECURITY to restrict the listing of all open files to the
+ * root user. When HASSECURITY is defined, the non-root user may list
+ * only files whose processes have the same user ID as the real user ID
+ * (the one that its user logged on with) of the lsof process.
+ */
+
+/* #define HASSECURITY 1 */
+
+
+/*
+ * If HASSECURITY is defined, define HASNOSOCKSECURITY to allow users
+ * restricted by HASSECURITY to list any open socket files, provide their
+ * listing is selected by the "-i" option.
+ */
+
+/* #define HASNOSOCKSECURITY 1 */
+
+
+/*
+ * HASSETLOCALE is defined for those dialects that have <locale.h> and
+ * setlocale().
+ *
+ * If the dialect also has wide character support for language locales,
+ * HASWIDECHAR activates lsof's wide character support and WIDECHARINCL
+ * defines the header file (if any) that must be #include'd to use the
+ * mblen() and mbtowc() functions.
+ */
+
+#define HASSETLOCALE 1
+
+# if DARWINV>=700
+#define HASWIDECHAR 1
+# endif /* DARWINV>=700 */
+
+/* #define WIDECHARINCL <wchar.h> */
+
+
+/*
+ * HASSNODE is defined for those dialects that have snodes.
+ */
+
+/* #define HASSNODE 1 */
+
+
+/*
+ * HASTASKS is defined for those dialects that have task reporting support.
+ */
+
+/* #define HASTASKS 1 */
+
+
+/*
+ * HASSOOPT, HASSOSTATE and HASTCPOPT define the availability of information
+ * on socket options (SO_* symbols), socket states (SS_* symbols) and TCP
+ * options.
+ */
+
+#define HASSOOPT 1 /* has socket option information */
+#define HASSOSTATE 1 /* has socket state information */
+#define HASTCPOPT 1 /* has TCP options or flags */
+
+
+/*
+ * Define HASSPECDEVD to be the name of a function that handles the results
+ * of a successful stat(2) of a file name argument.
+ *
+ * For example, HASSPECDEVD() for Darwin makes sure that st_dev is set to
+ * what stat("/dev") returns -- i.e., what's in DevDev.
+ *
+ * The function takes two arguments:
+ *
+ * 1: pointer to the full path name of file
+ * 2: pointer to the stat(2) result
+ *
+ * The function returns void.
+ */
+
+#define HASSPECDEVD process_dev_stat
+
+
+/*
+ * HASSTREAMS is defined for those dialects that support streams.
+ */
+
+/* #define HASSTREAMS 1 */
+
+
+/*
+ * HASTCPTPIQ is defined for dialects where it is possible to report the
+ * TCP/TPI Recv-Q and Send-Q values produced by netstat.
+ */
+
+#define HASTCPTPIQ 1
+
+
+/*
+ * HASTCPTPIW is defined for dialects where it is possible to report the
+ * TCP/TPI send and receive window sizes produced by netstat.
+ */
+
+/* #define HASTCPTPIW 1 */
+
+
+/*
+ * HASTMPNODE is defined for those dialects that have tmpnodes.
+ */
+
+/* #define HASTMPNODE 1 */
+
+
+/*
+ * HASVNODE is defined for those dialects that use the Sun virtual file system
+ * node, the vnode. BSD derivatives usually do; System V derivatives prior
+ * to R4 usually don't.
+ * doesn't.
+ */
+
+#define HASVNODE 1
+
+
+/*
+ * HASXOPT is defined for those dialects that have an X option. It
+ * defines the text for the usage display. HASXOPT_VALUE defines the
+ * option's default binary value -- 0 or 1.
+ */
+
+/* #define HASXOPT "help text for X option" */
+/* #define HASXOPT_VALUE 1 */
+
+
+/*
+ * INODETYPE and INODEPSPEC define the internal node number type and its
+ * printf specification modifier. These need not be defined and lsof.h
+ * can be allowed to define defaults.
+ *
+ * These are defined here, because they must be used in dlsof.h.
+ */
+
+# if DARWINV>=800
+#define INODETYPE unsigned long long
+ /* inode number internal storage type */
+#define INODEPSPEC "ll" /* INODETYPE printf specification
+ * modifier */
+# endif /* DARWINV>=800 */
+
+
+/*
+ * UID_ARG defines the size of a User ID number when it is passed
+ * as a function argument.
+ */
+
+#define UID_ARG int
+
+
+/*
+ * Each USE_LIB_<function_name> is defined for dialects that use the
+ * <function_name> in the lsof library.
+ *
+ * Note: other definitions and operations may be required to condition the
+ * library function source code. They may be found in the dialect dlsof.h
+ * header files.
+ */
+
+#define USE_LIB_CKKV 1 /* ckkv.c */
+/* #define USE_LIB_COMPLETEVFS 1 cvfs.c */
+#define USE_LIB_FIND_CH_INO 1 /* fino.c */
+#define USE_LIB_IS_FILE_NAMED 1 /* isfn.c */
+#define USE_LIB_LKUPDEV 1 /* lkud.c */
+#define USE_LIB_PRINTDEVNAME 1 /* pdvn.c */
+/* #define USE_LIB_PROCESS_FILE 1 prfp.c */
+#define USE_LIB_PRINT_TCPTPI 1 /* ptti.c */
+/* #define USE_LIB_READDEV 1 rdev.c */
+/* #define USE_LIB_READMNT 1 rmnt.c */
+/* #define USE_LIB_REGEX 1 regex.c */
+/* #define USE_LIB_RNAM 1 rnam.c */
+
+#if DARWINV<800
+#define USE_LIB_RNMH 1 /* rnmh.c */
+#else /* DARWINV>800 */
+/* #define USE_LIB_RNMH 1 rnmh.c */
+#endif /* DARWINV<800 */
+
+/* #define USE_LIB_RNCH 1 rnch.c */
+/* #define USE_LIB_SNPF 1 snpf.c */
+#define snpf snprintf /* use the system's snprintf() */
+
+
+/*
+ * WARNDEVACCESS is defined for those dialects that should issue a warning
+ * when lsof can't access /dev (or /device) or one of its sub-directories.
+ * The warning can be inhibited by the lsof caller with the -w option.
+ */
+
+#define WARNDEVACCESS 1
+
+
+/*
+ * WARNINGSTATE is defined for those dialects that want to suppress all lsof
+ * warning messages.
+ */
+
+/* #define WARNINGSTATE 1 warnings are enabled by default */
+
+
+/*
+ * WILLDROPGID is defined for those dialects whose lsof executable runs
+ * setgid(not_real_GID) and whose setgid power can be relinquished after
+ * the dialect's initialize() function has been executed.
+ */
+
+#define WILLDROPGID 1
+
+
+/*
+ * zeromem is a macro that uses bzero or memset.
+ */
+
+#define zeromem(a, l) memset(a, 0, l)
+
+#endif /* !defined(LSOF_MACHINE_H) */
diff --git a/dialects/darwin/libproc/Makefile b/dialects/darwin/libproc/Makefile
new file mode 100644
index 0000000..bda2623
--- /dev/null
+++ b/dialects/darwin/libproc/Makefile
@@ -0,0 +1,171 @@
+
+# Darwin libproc-based lsof Makefile
+#
+# $Id: Makefile,v 1.7 2009/03/25 19:21:37 abe Exp $
+
+PROG= lsof
+
+BIN= ${DSTROOT}/usr/sbin
+
+DOC= ${DSTROOT}/usr/share/man/man8
+
+I=/usr/include
+S=/usr/include/sys
+L=/usr/include/local
+P=
+
+CDEF= ${RC_CFLAGS}
+CDEFS= ${CDEF} ${CFGF}
+INCL= ${DINC}
+override CFLAGS= ${CDEFS} ${INCL} ${DEBUG}
+
+GRP= wheel
+
+HDR= lsof.h lsof_fields.h dlsof.h machine.h proto.h dproto.h
+
+SRC= ddev.c dfile.c dmnt.c dproc.c dsock.c dstore.c \
+ arg.c main.c misc.c node.c print.c proc.c store.c usage.c util.c
+
+OBJ= ddev.o dfile.o dmnt.o dproc.o dsock.o dstore.o \
+ arg.o main.o misc.o node.o print.o proc.o store.o usage.o util.o
+
+MAN= lsof.8
+
+OTHER=
+
+SHELL= /bin/sh
+
+SOURCE= Makefile ${OTHER} ${MAN} ${HDR} ${SRC}
+
+all: ${PROG}
+
+${PROG}: ${LIB} ${P} ${OBJ}
+ ${CC} -o $@ ${CFLAGS} ${OBJ} ${CFGL}
+
+clean: FRC
+ rm -f Makefile.bak ${PROG} a.out core errs lint.out tags *.o version.h
+ rm -f machine.h.old new_machine.h
+ (cd lib; ${MAKE} -f Makefile.skel clean)
+
+install-strip: all FRC
+ @if [ -n "${SYMROOT}" ]; then \
+ mkdir -p ${SYMROOT}; \
+ cp -p ${PROG} ${SYMROOT}/${PROG}; \
+ fi
+ mkdir -p ${BIN}
+ install -c -s -m 755 -g ${GRP} ${PROG} ${BIN}
+ mkdir -p ${DOC}
+ install -c -m 444 ${MAN} ${DOC}
+
+install: all FRC
+ @echo ''
+ @echo 'Please write your own install rule. Lsof for Darwin below 8'
+ @echo 'should be installed setgid to the group that has permission'
+ @echo 'to read /dev/kmem, often kmem or sys. Lsof for Darwin 8 and'
+ @echo 'above should be installed setuid-root. Your install rule'
+ @echo 'actions for Darwin below 8 might look something like this:'
+ @echo ''
+ @echo ' install -m 2xxx -g $${GRP} $${PROG} $${BIN}'
+ @echo ' install -m 444 $${MAN} $${DOC}'
+ @echo ''
+ @echo 'Your install rule actions for Darwin 8 and above might look'
+ @echo 'something like this:'
+ @echo ''
+ @echo ' install -m 4xxx -o root $${PROG} $${BIN}'
+ @echo ' install -m 444 $${MAN} $${DOC}'
+ @echo ''
+ @echo 'You will have to complete the xxx modes, the GRP value, and'
+ @echo 'the skeletons for the BIN and DOC strings, given at the'
+ @echo 'beginning of this Makefile, e.g.,'
+ @echo ''
+ @echo ' BIN= $${DESTDIR}/usr/local/etc'
+ @echo ' DOC= $${DESTDIR}/usr/man/man8'
+ @echo ' GRP= kmem'
+ @echo ''
+
+${LIB}: FRC
+ (cd lib; ${MAKE} DEBUG="${DEBUG}" CFGF="${CFGF}")
+
+version.h: FRC
+ @echo Constructing version.h
+ @rm -f version.h
+ @echo '#define LSOF_BLDCMT "${LSOF_BLDCMT}"' > version.h;
+ @echo '#define LSOF_CC "${CC}"' >> version.h
+ @echo '#define LSOF_CCV "${CCV}"' >> version.h
+ @echo '#define LSOF_CCDATE "'`date`'"' >> version.h
+ @echo '#define LSOF_CCFLAGS "'`echo ${CFLAGS} | sed 's/\\\\(/\\(/g' | sed 's/\\\\)/\\)/g' | sed 's/"/\\\\"/g'`'"' >> version.h
+ @echo '#define LSOF_CINFO "${CINFO}"' >> version.h
+ @if [ "X${LSOF_HOST}" = "X" ]; then \
+ echo '#define LSOF_HOST "'`uname -n`'"' >> version.h; \
+ else \
+ if [ "${LSOF_HOST}" = "none" ]; then \
+ echo '#define LSOF_HOST ""' >> version.h; \
+ else \
+ echo '#define LSOF_HOST "${LSOF_HOST}"' >> version.h; \
+ fi \
+ fi
+ @echo '#define LSOF_LDFLAGS "${CFGL}"' >> version.h
+ @if [ "X${LSOF_LOGNAME}" = "X" ]; then \
+ echo '#define LSOF_LOGNAME "${LOGNAME}"' >> version.h; \
+ else \
+ if [ "${LSOF_LOGNAME}" = "none" ]; then \
+ echo '#define LSOF_LOGNAME ""' >> version.h; \
+ else \
+ echo '#define LSOF_LOGNAME "${LSOF_LOGNAME}"' >> version.h; \
+ fi; \
+ fi
+ @if [ "X${LSOF_SYSINFO}" = "X" ]; then \
+ echo '#define LSOF_SYSINFO "'`uname -a`'"' >> version.h; \
+ else \
+ if [ "${LSOF_SYSINFO}" = "none" ]; then \
+ echo '#define LSOF_SYSINFO ""' >> version.h; \
+ else \
+ echo '#define LSOF_SYSINFO "${LSOF_SYSINFO}"' >> version.h; \
+ fi \
+ fi
+ @if [ "X${LSOF_USER}" = "X" ]; then \
+ echo '#define LSOF_USER "${USER}"' >> version.h; \
+ else \
+ if [ "${LSOF_USER}" = "none" ]; then \
+ echo '#define LSOF_USER ""' >> version.h; \
+ else \
+ echo '#define LSOF_USER "${LSOF_USER}"' >> version.h; \
+ fi \
+ fi
+ @sed '/VN/s/.ds VN \(.*\)/#define LSOF_VERSION "\1"/' < version >> version.h
+
+FRC:
+
+# DO NOT DELETE THIS LINE - make depend DEPENDS ON IT
+
+ddev.o: ${HDR} ddev.c
+
+dfile.o: ${HDR} dfile.c
+
+dmnt.o: ${HDR} dmnt.c
+
+dproc.o: ${HDR} dproc.c
+
+dsock.o: ${HDR} dsock.c
+
+dstore.o: ${HDR} dstore.c
+
+arg.o: ${HDR} arg.c
+
+main.o: ${HDR} main.c
+
+misc.o: ${HDR} misc.c
+
+node.o: ${HDR} node.c
+
+print.o: ${HDR} print.c
+
+proc.o: ${HDR} proc.c
+
+store.o: ${HDR} store.c
+
+usage.o: ${HDR} version.h usage.c
+
+util.o: ${HDR} util.c
+
+# *** Do not add anything here - It will go away. ***
diff --git a/dialects/darwin/libproc/Mksrc b/dialects/darwin/libproc/Mksrc
new file mode 100755
index 0000000..870d6ca
--- /dev/null
+++ b/dialects/darwin/libproc/Mksrc
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Mksrc -- make Darwin libproc-based lsof source files
+#
+# WARNING: This script assumes it is running from the main directory
+# of the lsof, version 4 distribution.
+#
+# One environment variable applies:
+#
+# LSOF_MKC is the method for creating the source files.
+# It defaults to "ln -s". A common alternative is "cp".
+#
+# $Id: Mksrc,v 1.5 2005/11/06 12:50:09 abe Exp $
+
+
+D=dialects/darwin/libproc
+L="dlsof.h ddev.c dfile.c dmnt.c dproc.c dproto.h dsock.c dstore.c machine.h"
+
+for i in $L
+do
+ rm -f $i
+ $LSOF_MKC $D/$i $i
+ echo "$LSOF_MKC $D/$i $i"
+done
diff --git a/dialects/darwin/libproc/ddev.c b/dialects/darwin/libproc/ddev.c
new file mode 100644
index 0000000..2240501
--- /dev/null
+++ b/dialects/darwin/libproc/ddev.c
@@ -0,0 +1,549 @@
+/*
+ * ddev.c -- Darwin device support functions for libproc-based lsof
+ */
+
+
+/*
+ * Portions Copyright 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * Copyright 2005 Purdue Research Foundation, West Lafayette, Indiana
+ * 47907. All rights reserved.
+ *
+ * Written by Allan Nathanson, Apple Computer, Inc., and Victor A.
+ * Abell, Purdue University.
+ *
+ * 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 Apple Computer, Inc. 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, Apple
+ * Computer, Inc. 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 2005 Apple Computer, Inc. and Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: ddev.c,v 1.2 2006/03/27 23:23:13 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+/*
+ * Local definitions
+ */
+
+#if defined(DVCH_DEVPATH)
+#define DDEV_DEVPATH DVCH_DEVPATH
+#else /* !defined(DVCH_DEVPATH) */
+#define DDEV_DEVPATH "/dev"
+#endif /* defined(DVCH_DEVPATH) */
+
+#define LIKE_BLK_SPEC "like block special"
+#define LIKE_CHR_SPEC "like character special"
+
+#if defined(USE_STAT)
+#define STATFN stat
+#else /* !defined(USE_STAT) */
+#define STATFN lstat
+#endif /* defined(USE_STAT) */
+
+
+/*
+ * Local static variables.
+ */
+
+static dev_t *ADev = (dev_t *) NULL; /* device numbers besides DevDev found
+ * inside DDEV_DEVPATH */
+static int ADevA = 0; /* entries allocated to ADev[] */
+static int ADevU = 0; /* entries used in ADev[] */
+
+
+/*
+ * Local function prototypes
+ */
+
+_PROTOTYPE(static int rmdupdev,(struct l_dev ***dp, int n, char *nm));
+_PROTOTYPE(static void saveADev,(struct stat *s));
+
+
+#if defined(HASSPECDEVD)
+/*
+ * HASSPECDEVD() -- process stat(2) result to see if the device number is
+ * inside DDEV_DEVPATH "/"
+ *
+ * exit: s->st_dev changed to DevDev, as required
+ */
+
+void
+HASSPECDEVD(p, s)
+ char *p; /* file path */
+ struct stat *s; /* stat(2) result for file */
+{
+ int i;
+
+ switch (s->st_mode & S_IFMT) {
+ case S_IFCHR:
+ case S_IFBLK:
+ if (s->st_dev == DevDev)
+ return;
+ (void) readdev(0);
+ if (!ADev)
+ return;
+ for (i = 0; i < ADevU; i++) {
+ if (s->st_dev == ADev[i]) {
+ s->st_dev = DevDev;
+ return;
+ }
+ }
+ }
+}
+#endif /* defined(HASSPECDEVD) */
+
+
+/*
+ * printdevname() -- print character device name
+ */
+
+int
+printdevname(dev, rdev, f, nty)
+ dev_t *dev; /* device */
+ dev_t *rdev; /* raw device */
+ int f; /* 1 = follow with '\n' */
+ int nty; /* node type: N_BLK or N_chr */
+{
+ char *cp, *ttl;
+ struct l_dev *dp;
+ int i, len;
+/*
+ * See if the device node resides in DDEV_DEVPATH. If it does, return zero
+ * to indicate the vnode path is to be used for the NAME column.
+ */
+ if (*dev == DevDev)
+ return(0);
+ readdev(0);
+ for (i = 0; i < ADevU; i++) {
+ if (*dev == ADev[i])
+ return(0);
+ }
+/*
+ * This device is not in DDEV_DEVPATH.
+ *
+ * See if it has a DDEV_DEVPATH analogue by searching the device table for a
+ * match without inode number and dev.
+ */
+
+#if defined(HASBLKDEV)
+ if (nty == N_BLK)
+ dp = lkupbdev(&DevDev, rdev, 0, 1);
+ else
+#endif /* defined(HASBLKDEV) */
+
+ dp = lkupdev(&DevDev, rdev, 0, 1);
+ if (dp) {
+
+ /*
+ * A match was found. Record it as a name column addition.
+ */
+ ttl = (nty == N_BLK) ? LIKE_BLK_SPEC : LIKE_CHR_SPEC;
+ len = (int)(1 + strlen(ttl) + 1 + strlen(dp->name) + 1);
+ if (!(cp = (char *)malloc((MALLOC_S)(len + 1)))) {
+ (void) fprintf(stderr, "%s: no nma space for: (%s %s)\n",
+ Pn, ttl, dp->name);
+ Exit(1);
+ }
+ (void) snpf(cp, len + 1, "(%s %s)", ttl, dp->name);
+ (void) add_nma(cp, len);
+ (void) free((MALLOC_P *)cp);
+ }
+/*
+ * Return zero to indicate the vnode path is to be used for the NAME column.
+ */
+ return(0);
+}
+
+
+/*
+ * readdev() -- read device names, modes and types
+ */
+
+void
+readdev(skip)
+ int skip; /* skip device cache read if 1 --
+ * ignored since device cache not
+ * used */
+{
+ DIR *dfp;
+ int dnamlen;
+ struct dirent *dp;
+ char *fp = (char *)NULL;
+ char *path = (char *)NULL;
+ int i = 0;
+ int j = 0;
+ MALLOC_S pl, sz;
+ struct stat sb;
+/*
+ * Read device names but once.
+ */
+ if (Sdev)
+ return;
+/*
+ * Prepare to scan DDEV_DEVPATH.
+ */
+ Dstkn = Dstkx = 0;
+ Dstk = (char **)NULL;
+ (void) stkdir(DDEV_DEVPATH);
+/*
+ * Unstack the next directory.
+ */
+ while (--Dstkx >= 0) {
+ if (!(dfp = OpenDir(Dstk[Dstkx]))) {
+
+# if defined(WARNDEVACCESS)
+ if (!Fwarn) {
+ (void) fprintf(stderr, "%s: WARNING: can't open: ", Pn);
+ safestrprt(Dstk[Dstkx], stderr, 1);
+ }
+# endif /* defined(WARNDEVACCESS) */
+
+ (void) free((FREE_P *)Dstk[Dstkx]);
+ Dstk[Dstkx] = (char *)NULL;
+ continue;
+ }
+ if (path) {
+ (void) free((FREE_P *)path);
+ path = (char *)NULL;
+ }
+ if (!(path = mkstrcat(Dstk[Dstkx], -1, "/", 1, (char *)NULL, -1,
+ &pl)))
+ {
+ (void) fprintf(stderr, "%s: no space for: ", Pn);
+ safestrprt(Dstk[Dstkx], stderr, 1);
+ Exit(1);
+ }
+ (void) free((FREE_P *)Dstk[Dstkx]);
+ Dstk[Dstkx] = (char *)NULL;
+ /*
+ * Scan the directory.
+ */
+ for (dp = ReadDir(dfp); dp; dp = ReadDir(dfp)) {
+ if (dp->d_ino == 0 || dp->d_name[0] == '.')
+ continue;
+ /*
+ * Form the full path name and get its status.
+ */
+ dnamlen = (int)dp->d_namlen;
+ if (fp) {
+ (void) free((FREE_P *)fp);
+ fp = (char *)NULL;
+ }
+ if (!(fp = mkstrcat(path, pl, dp->d_name, dnamlen,
+ (char *)NULL, -1, (MALLOC_S *)NULL)))
+ {
+ (void) fprintf(stderr, "%s: no space for: ", Pn);
+ safestrprt(path, stderr, 0);
+ safestrprtn(dp->d_name, dnamlen, stderr, 1);
+ Exit(1);
+ }
+ if (STATFN(fp, &sb) != 0) {
+ if (errno == ENOENT) /* a sym link to nowhere? */
+ continue;
+
+# if defined(WARNDEVACCESS)
+ if (!Fwarn) {
+ int errno_save = errno;
+
+ (void) fprintf(stderr, "%s: can't stat ", Pn);
+ safestrprt(fp, stderr, 0);
+ (void) fprintf(stderr, ": %s\n", strerror(errno_save));
+ }
+# endif /* defined(WARNDEVACCESS) */
+
+ continue;
+ }
+ /*
+ * If it's a subdirectory, stack its name for later
+ * processing.
+ */
+ if ((sb.st_mode & S_IFMT) == S_IFDIR) {
+
+ /*
+ * Skip /dev/fd.
+ */
+ if (strcmp(fp, "/dev/fd"))
+ (void) stkdir(fp);
+ continue;
+ }
+ if ((sb.st_mode & S_IFMT) == S_IFLNK) {
+
+ /*
+ * Ignore symbolic links.
+ */
+ continue;
+ }
+ if ((sb.st_mode & S_IFMT) == S_IFCHR) {
+
+ /*
+ * Save character device information in Devtp[].
+ */
+ if (i >= Ndev) {
+ Ndev += DEVINCR;
+ if (!Devtp)
+ Devtp = (struct l_dev *)malloc(
+ (MALLOC_S)(sizeof(struct l_dev)*Ndev));
+ else
+ Devtp = (struct l_dev *)realloc((MALLOC_P *)Devtp,
+ (MALLOC_S)(sizeof(struct l_dev)*Ndev));
+ if (!Devtp) {
+ (void) fprintf(stderr,
+ "%s: no space for character device\n", Pn);
+ Exit(1);
+ }
+ }
+ Devtp[i].rdev = sb.st_rdev;
+ Devtp[i].inode = (INODETYPE)sb.st_ino;
+ if (!(Devtp[i].name = mkstrcpy(fp, (MALLOC_S *)NULL))) {
+ (void) fprintf(stderr,
+ "%s: no space for device name: ", Pn);
+ safestrprt(fp, stderr, 1);
+ Exit(1);
+ }
+ Devtp[i].v = 0;
+ i++;
+ }
+
+# if defined(HASBLKDEV)
+ if ((sb.st_mode & S_IFMT) == S_IFBLK) {
+
+ /*
+ * Save block device information in BDevtp[].
+ */
+ if (j >= BNdev) {
+ BNdev += DEVINCR;
+ if (!BDevtp)
+ BDevtp = (struct l_dev *)malloc(
+ (MALLOC_S)(sizeof(struct l_dev)*BNdev));
+ else
+ BDevtp = (struct l_dev *)realloc((MALLOC_P *)BDevtp,
+ (MALLOC_S)(sizeof(struct l_dev)*BNdev));
+ if (!BDevtp) {
+ (void) fprintf(stderr,
+ "%s: no space for block device\n", Pn);
+ Exit(1);
+ }
+ }
+ BDevtp[j].name = fp;
+ fp = (char *)NULL;
+ BDevtp[j].inode = (INODETYPE)sb.st_ino;
+ BDevtp[j].rdev = sb.st_rdev;
+ BDevtp[j].v = 0;
+ j++;
+ }
+# endif /* defined(HASBLKDEV) */
+
+ /*
+ * Save a possible new st_dev number within DDEV_DEVPATH.
+ */
+ if (sb.st_dev != DevDev)
+ (void) saveADev(&sb);
+ }
+ (void) CloseDir(dfp);
+ }
+/*
+ * Free any unneeded space that was allocated.
+ */
+ if (ADev && (ADevU < ADevA)) {
+
+ /*
+ * Reduce space allocated to additional DDEV_DEVPATH device numbers.
+ */
+ if (!ADevU) {
+
+ /*
+ * If no space was used, free the entire allocation.
+ */
+ (void) free((FREE_P *)ADev);
+ ADev = (dev_t *)NULL;
+ ADevA = 0;
+ } else {
+
+ /*
+ * Reduce the allocation to what was used.
+ */
+ sz = (MALLOC_S)(ADevU * sizeof(dev_t));
+ if (!(ADev = (dev_t *)realloc((MALLOC_P *)ADev, sz))) {
+ (void) fprintf(stderr, "%s: can't reduce ADev[]\n", Pn);
+ Exit(1);
+ }
+ }
+ }
+ if (!Dstk) {
+ (void) free((FREE_P *)Dstk);
+ Dstk = (char **)NULL;
+ }
+ if (fp)
+ (void) free((FREE_P *)fp);
+ if (path)
+ (void) free((FREE_P *)path);
+
+# if defined(HASBLKDEV)
+/*
+ * Reduce the BDevtp[] (optional) and Devtp[] tables to their minimum
+ * sizes; allocate and build sort pointer lists; and sort the tables by
+ * device number.
+ */
+ if (BNdev) {
+ if (BNdev > j) {
+ BNdev = j;
+ BDevtp = (struct l_dev *)realloc((MALLOC_P *)BDevtp,
+ (MALLOC_S)(sizeof(struct l_dev) * BNdev));
+ }
+ if (!(BSdev = (struct l_dev **)malloc(
+ (MALLOC_S)(sizeof(struct l_dev *) * BNdev))))
+ {
+ (void) fprintf(stderr,
+ "%s: no space for block device sort pointers\n", Pn);
+ Exit(1);
+ }
+ for (j = 0; j < BNdev; j++) {
+ BSdev[j] = &BDevtp[j];
+ }
+ (void) qsort((QSORT_P *)BSdev, (size_t)BNdev,
+ (size_t)sizeof(struct l_dev *), compdev);
+ BNdev = rmdupdev(&BSdev, BNdev, "block");
+ }
+
+# if !defined(NOWARNBLKDEV)
+ else {
+ if (!Fwarn)
+ (void) fprintf(stderr,
+ "%s: WARNING: no block devices found\n", Pn);
+ }
+# endif /* !defined(NOWARNBLKDEV) */
+# endif /* defined(HASBLKDEV) */
+
+ if (Ndev) {
+ if (Ndev > i) {
+ Ndev = i;
+ Devtp = (struct l_dev *)realloc((MALLOC_P *)Devtp,
+ (MALLOC_S)(sizeof(struct l_dev) * Ndev));
+ }
+ if (!(Sdev = (struct l_dev **)malloc(
+ (MALLOC_S)(sizeof(struct l_dev *) * Ndev))))
+ {
+ (void) fprintf(stderr,
+ "%s: no space for character device sort pointers\n", Pn);
+ Exit(1);
+ }
+ for (i = 0; i < Ndev; i++) {
+ Sdev[i] = &Devtp[i];
+ }
+ (void) qsort((QSORT_P *)Sdev, (size_t)Ndev,
+ (size_t)sizeof(struct l_dev *), compdev);
+ Ndev = rmdupdev(&Sdev, Ndev, "char");
+ } else {
+ (void) fprintf(stderr, "%s: no character devices found\n", Pn);
+ Exit(1);
+ }
+}
+
+
+/*
+ * rmdupdev() - remove duplicate (major/minor/inode) devices
+ */
+
+static int
+rmdupdev(dp, n, nm)
+ struct l_dev ***dp; /* device table pointers address */
+ int n; /* number of pointers */
+ char *nm; /* device table name for error message */
+{
+ int i, j, k;
+ struct l_dev **p;
+
+ for (i = j = 0, p = *dp; i < n ;) {
+ for (k = i + 1; k < n; k++) {
+ if (p[i]->rdev != p[k]->rdev || p[i]->inode != p[k]->inode)
+ break;
+ }
+ if (i != j)
+ p[j] = p[i];
+ j++;
+ i = k;
+ }
+ if (n == j)
+ return(n);
+ if (!(*dp = (struct l_dev **)realloc((MALLOC_P *)*dp,
+ (MALLOC_S)(j * sizeof(struct l_dev *)))))
+ {
+ (void) fprintf(stderr, "%s: can't realloc %s device pointers\n",
+ Pn, nm);
+ Exit(1);
+ }
+ return(j);
+}
+
+
+/*
+ * saveADev() - save additional device number appearing inside DDEV_DEVPATH
+ */
+
+static void
+saveADev(s)
+ struct stat *s; /* stat(2) buffer for file */
+{
+ int i;
+ MALLOC_S sz;
+/*
+ * Process VCHR files.
+ *
+ * Optionally process VBLK files.
+ */
+
+#if defined(HASBLKDEV)
+ if (((s->st_mode & S_IFMT) != S_IFBLK)
+ && ((s->st_mode & S_IFMT) != S_IFCHR))
+#else /* !defined(HASBLKDEV) */
+ if ((s->st_mode & S_IFCHR) != S_IFCHR)
+#endif /* defined(HASBLKDEV) */
+
+ return;
+/*
+ * See if this is a new VBLK or VCHR st_dev value for ADev[].
+ */
+ for (i = 0; i < ADevU; i++) {
+ if (s->st_dev == ADev[i])
+ return;
+ }
+/*
+ * This is a new device number to add to ADev[].
+ */
+ if (ADevU >= ADevA) {
+ ADevA += 16;
+ sz = (MALLOC_S)(ADevA * sizeof(dev_t));
+ if (ADev)
+ ADev = (dev_t *)realloc((MALLOC_P *)ADev, sz);
+ else
+ ADev = (dev_t *)malloc(sz);
+ if (!ADev) {
+ (void) fprintf(stderr, "%s: no space for ADev[]\n", Pn);
+ Exit(1);
+ }
+ }
+ ADev[ADevU++] = s->st_dev;
+}
diff --git a/dialects/darwin/libproc/dfile.c b/dialects/darwin/libproc/dfile.c
new file mode 100644
index 0000000..bd8d81a
--- /dev/null
+++ b/dialects/darwin/libproc/dfile.c
@@ -0,0 +1,682 @@
+/*
+ * dfile.c -- Darwin file processing functions for libproc-based lsof
+ */
+
+
+/*
+ * Portions Copyright 2005-2007 Apple Inc. All rights reserved.
+ *
+ * Copyright 2005 Purdue Research Foundation, West Lafayette, Indiana
+ * 47907. All rights reserved.
+ *
+ * Written by Allan Nathanson, Apple Inc., and Victor A. Abell, Purdue
+ * University.
+ *
+ * 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 Apple Inc. 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, Apple
+ * Inc. 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 2005-2007 Apple Inc. and Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dfile.c,v 1.8 2012/04/10 16:41:04 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+/*
+ * enter_file_info() -- enter file information
+ */
+
+void
+enter_file_info(pfi)
+ struct proc_fileinfo *pfi; /* pointer to process file info */
+{
+ int f;
+/*
+ * Construct access code
+ */
+ f = pfi->fi_openflags & (FREAD | FWRITE);
+ if (f == FREAD)
+ Lf->access = 'r';
+ else if (f == FWRITE)
+ Lf->access = 'w';
+ else if (f == (FREAD | FWRITE))
+ Lf->access = 'u';
+/*
+ * Save the offset / size
+ */
+ Lf->off = (SZOFFTYPE)pfi->fi_offset;
+ if (Foffset)
+ Lf->off_def = 1;
+/*
+ * Save file structure information as requested.
+ */
+ if (Fsv & FSV_FG) {
+ Lf->ffg = (long)pfi->fi_openflags;
+ Lf->fsv |= FSV_FG;
+ }
+}
+
+
+/*
+ * enter_vnode_info() -- enter vnode information
+ */
+
+void
+enter_vnode_info(vip)
+ struct vnode_info_path *vip; /* pointer to vnode info with path */
+{
+ char buf[32], *cp;
+ dev_t dev = 0;
+ int devs = 0;
+ struct mounts *mp;
+/*
+ * Derive file type.
+ */
+ switch ((int)(vip->vip_vi.vi_stat.vst_mode & S_IFMT)) {
+ case S_IFIFO:
+ cp = "FIFO";
+ Ntype = N_FIFO;
+ break;
+ case S_IFCHR:
+ cp = "CHR";
+ Ntype = N_CHR;
+ break;
+ case S_IFDIR:
+ cp = "DIR";
+ Ntype = N_REGLR;
+ break;
+ case S_IFBLK:
+ cp = "BLK";
+ Ntype = N_BLK;
+ break;
+ case S_IFREG:
+ cp = "REG";
+ Ntype = N_REGLR;
+ break;
+ default:
+ (void) snpf(buf, sizeof(buf), "%04o",
+ (((vip->vip_vi.vi_stat.vst_mode & S_IFMT) >> 12) & 0xfff));
+ cp = buf;
+ Ntype = N_REGLR;
+ }
+ if (!Lf->type[0])
+ (void) snpf(Lf->type, sizeof(Lf->type), "%s", cp);
+ Lf->ntype = Ntype;
+/*
+ * Save device number and path
+ */
+ switch (Ntype) {
+ case N_FIFO:
+ break;
+ case N_CHR:
+ case N_BLK:
+ Lf->rdev = vip->vip_vi.vi_stat.vst_rdev;
+ Lf->rdev_def = 1;
+ /* fall through */
+ default:
+ Lf->dev = dev = vip->vip_vi.vi_stat.vst_dev;
+ Lf->dev_def = devs = 1;
+ }
+/*
+ * Save path name.
+ */
+ vip->vip_path[sizeof(vip->vip_path) - 1] = '\0';
+ if (vip->vip_path[0] != '\0') {
+ Lf->V_path = mkstrcpy(vip->vip_path, (MALLOC_S *)NULL);
+ }
+/*
+ * Save node number.
+ */
+ Lf->inode = (INODETYPE)vip->vip_vi.vi_stat.vst_ino;
+ Lf->inp_ty = 1;
+/*
+ * Save link count, as requested.
+ */
+ if (Fnlink) {
+ Lf->nlink = vip->vip_vi.vi_stat.vst_nlink;
+ Lf->nlink_def = 1;
+ if (Nlink && (Lf->nlink < Nlink))
+ Lf->sf |= SELNLINK;
+ }
+/*
+ * If a device number is defined, locate file system and save its identity.
+ */
+ if (devs) {
+ for (mp = readmnt(); mp; mp = mp->next) {
+ if (dev == mp->dev) {
+ Lf->fsdir = mp->dir;
+ Lf->fsdev = mp->fsname;
+ if (mp->is_nfs && Fnfs)
+ Lf->sf |= SELNFS;
+ break;
+ }
+ }
+ }
+/*
+ * Save the file size.
+ */
+ switch (Ntype) {
+ case N_CHR:
+ case N_FIFO:
+ Lf->off_def = 1;
+ break;
+ default:
+ Lf->sz = (SZOFFTYPE)vip->vip_vi.vi_stat.vst_size;
+ Lf->sz_def = 1;
+ }
+/*
+ * Test for specified file.
+ */
+ if (Sfile && is_file_named(NULL,
+ ((Ntype == N_CHR) || (Ntype == N_BLK) ? 1
+ : 0)))
+ {
+ Lf->sf |= SELNM;
+ }
+/*
+ * Enter name characters.
+ */
+ if (!Lf->nm && Namech[0])
+ enter_nm(Namech);
+}
+
+
+/*
+ * err2nm() -- convert errno to a message in Namech
+ */
+
+void
+err2nm(pfx)
+ char *pfx; /* Namech message prefix */
+{
+ char *sfx;
+
+ switch (errno) {
+ case EBADF:
+
+ /*
+ * The file descriptor is no longer available.
+ */
+ sfx = "FD unavailable";
+ break;
+ case ESRCH:
+
+ /*
+ * The process is no longer available.
+ */
+ sfx = "process unavailable";
+ break;
+ default:
+
+ /*
+ * All other errors are reported with strerror() information.
+ */
+ sfx = strerror(errno);
+ }
+ (void) snpf(Namech, Namechl, "%s: %s", pfx, sfx);
+ enter_nm(Namech);
+}
+
+
+/*
+ * print_nm() -- print Name column
+ */
+void
+print_nm(lf)
+ struct lfile *lf;
+{
+ printname(0);
+#ifdef PROC_PIDLISTFILEPORTS
+ if (lf->fileport) {
+ (void) printf(" (fileport=0x%04x)", lf->fileport);
+ }
+#endif /* PROC_PIDLISTFILEPORTS */
+ putchar('\n');
+}
+
+
+/*
+ * print_v_path() -- print vnode's path
+ */
+
+int
+print_v_path(lf)
+ struct lfile *lf;
+{
+ if (lf->V_path) {
+ safestrprt(lf->V_path, stdout, 0);
+ return(1);
+ }
+ return(0);
+}
+
+
+/*
+ * process_atalk() -- process an Apple Talk file
+ */
+
+void
+process_atalk(pid, fd)
+ int pid; /* PID */
+ int32_t fd; /* FD */
+{
+ (void) snpf(Lf->type, sizeof(Lf->type), "ATALK");
+ return;
+}
+
+
+/*
+ * process_fsevents() -- process a file system events file
+ */
+
+void
+process_fsevents(pid, fd)
+ int pid; /* PID */
+ int32_t fd; /* FD */
+{
+ (void) snpf(Lf->type, sizeof(Lf->type), "FSEVENTS");
+}
+
+
+/*
+ * process_kqueue() -- process a kernel queue file
+ */
+
+void
+process_kqueue(pid, fd)
+ int pid; /* PID */
+ int32_t fd; /* FD */
+{
+ struct kqueue_fdinfo kq;
+ int nb;
+/*
+ * Get the kernel queue file information.
+ */
+ (void) snpf(Lf->type, sizeof(Lf->type), "KQUEUE");
+ nb = proc_pidfdinfo(pid, fd, PROC_PIDFDKQUEUEINFO, &kq, sizeof(kq));
+ if (nb <= 0) {
+ (void) err2nm("kqueue");
+ return;
+ } else if (nb < sizeof(kq)) {
+ (void) fprintf(stderr,
+ "%s: PID %d, FD %d; proc_pidfdinfo(PROC_PIDFDKQUEUEINFO);\n",
+ Pn, pid, fd);
+ (void) fprintf(stderr,
+ " too few bytes; expected %ld, got %d\n",
+ sizeof(kq), nb);
+ Exit(1);
+ }
+/*
+ * Enter the kernel queue file information.
+ */
+ enter_file_info(&kq.pfi);
+/*
+ * Enter queue counts as NAME column information.
+ */
+ (void) snpf(Namech, Namechl,
+ "count=%" SZOFFPSPEC "u, state=%#x",
+ (SZOFFTYPE)kq.kqueueinfo.kq_stat.vst_size,
+ kq.kqueueinfo.kq_state);
+ enter_nm(Namech);
+}
+
+
+/*
+ * process_pipe() -- process pipe file
+ */
+
+static void
+process_pipe_common(pi)
+ struct pipe_fdinfo *pi;
+{
+ char dev_ch[32], *ep;
+ size_t sz;
+
+ (void) snpf(Lf->type, sizeof(Lf->type), "PIPE");
+/*
+ * Enter the pipe handle as the device.
+ */
+ (void) snpf(dev_ch, sizeof(dev_ch), "%s",
+ print_kptr((KA_T)pi->pipeinfo.pipe_handle, (char *)NULL, 0));
+ enter_dev_ch(dev_ch);
+/*
+ * Enable offset or size reporting.
+ */
+ if (Foffset)
+ Lf->off_def = 1;
+ else {
+ Lf->sz = (SZOFFTYPE)pi->pipeinfo.pipe_stat.vst_blksize;
+ Lf->sz_def = 1;
+ }
+/*
+ * If there is a peer handle, enter it in as NAME column information.
+ */
+ if (pi->pipeinfo.pipe_peerhandle) {
+ (void) snpf(Namech, Namechl, "->%s",
+ print_kptr((KA_T)pi->pipeinfo.pipe_peerhandle, (char *)NULL, 0));
+ enter_nm(Namech);
+ } else
+ Namech[0] = '\0';
+/*
+ * If the pipe has a count, add it to the NAME column.
+ */
+ if (pi->pipeinfo.pipe_stat.vst_size) {
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, ", cnt=%" SZOFFPSPEC "u",
+ (SZOFFTYPE)pi->pipeinfo.pipe_stat.vst_size);
+ }
+}
+
+
+void
+process_pipe(pid, fd)
+ int pid; /* PID */
+ int32_t fd; /* FD */
+{
+ int nb;
+ struct pipe_fdinfo pi;
+/*
+ * Get pipe file information.
+ */
+ nb = proc_pidfdinfo(pid, fd, PROC_PIDFDPIPEINFO, &pi, sizeof(pi));
+ if (nb <= 0) {
+ (void) err2nm("pipe");
+ return;
+ } else if (nb < sizeof(pi)) {
+ (void) fprintf(stderr,
+ "%s: PID %d, FD %d; proc_pidfdinfo(PROC_PIDFDPIPEINFO);\n",
+ Pn, pid, fd);
+ (void) fprintf(stderr,
+ " too few bytes; expected %ld, got %d\n",
+ sizeof(pi), nb);
+ Exit(1);
+ }
+
+ process_pipe_common(&pi);
+}
+
+
+#ifdef PROC_PIDLISTFILEPORTS
+void
+process_fileport_pipe(pid, fp)
+ int pid; /* PID */
+ uint32_t fp; /* FILEPORT */
+{
+ int nb;
+ struct pipe_fdinfo pi;
+/*
+ * Get pipe file information.
+ */
+ nb = proc_pidfileportinfo(pid, fp, PROC_PIDFILEPORTPIPEINFO, &pi, sizeof(pi));
+ if (nb <= 0) {
+ (void) err2nm("pipe");
+ return;
+ } else if (nb < sizeof(pi)) {
+ (void) fprintf(stderr,
+ "%s: PID %d, FILEPORT %u; proc_pidfileportinfo(PROC_PIDFILEPORTPIPEINFO);\n",
+ Pn, pid, fp);
+ (void) fprintf(stderr,
+ " too few bytes; expected %ld, got %d\n",
+ sizeof(pi), nb);
+ Exit(1);
+ }
+
+ process_pipe_common(&pi);
+}
+#endif /* PROC_PIDLISTFILEPORTS */
+
+
+/*
+ * process_psem() -- process a POSIX semaphore file
+ */
+
+void
+process_psem(pid, fd)
+ int pid; /* PID */
+ int32_t fd; /* FD */
+{
+ int nb;
+ struct psem_fdinfo ps;
+/*
+ * Get the sempaphore file information.
+ */
+ (void) snpf(Lf->type, sizeof(Lf->type), "PSXSEM");
+ nb = proc_pidfdinfo(pid, fd, PROC_PIDFDPSEMINFO, &ps, sizeof(ps));
+ if (nb <= 0) {
+ (void) err2nm("semaphore");
+ return;
+ } else if (nb < sizeof(ps)) {
+ (void) fprintf(stderr,
+ "%s: PID %d, FD %d; proc_pidfdinfo(PROC_PIDFDPSEMINFO);\n",
+ Pn, pid, fd);
+ (void) fprintf(stderr,
+ " too few bytes; expected %ld, got %d\n",
+ sizeof(ps), nb);
+ Exit(1);
+ }
+/*
+ * Enter the semaphore file information.
+ */
+ enter_file_info(&ps.pfi);
+/*
+ * If there is a semaphore file name, enter it.
+ */
+ if (ps.pseminfo.psem_name[0]) {
+ ps.pseminfo.psem_name[sizeof(ps.pseminfo.psem_name) - 1] = '\0';
+ (void) snpf(Namech, Namechl, "%s", ps.pseminfo.psem_name);
+ enter_nm(Namech);
+ }
+/*
+ * Unless file size has been specifically requested, enable the printing of
+ * file offset.
+ */
+ if (!Fsize)
+ Lf->off_def = 1;
+}
+
+
+/*
+ * process_pshm() -- process POSIX shared memory file
+ */
+
+static void
+process_pshm_common(ps)
+ struct pshm_fdinfo *ps;
+{
+ (void) snpf(Lf->type, sizeof(Lf->type), "PSXSHM");
+/*
+ * Enter the POSIX shared memory file information.
+ */
+ enter_file_info(&ps->pfi);
+/*
+ * If the POSIX shared memory file has a path name, enter it; otherwise, if it
+ * has a mapping address, enter that.
+ */
+ if (ps->pshminfo.pshm_name[0]) {
+ ps->pshminfo.pshm_name[sizeof(ps->pshminfo.pshm_name) - 1] = '\0';
+ (void) snpf(Namech, Namechl, "%s", ps->pshminfo.pshm_name);
+ enter_nm(Namech);
+ } else if (ps->pshminfo.pshm_mappaddr) {
+ (void) snpf(Namech, Namechl, "obj=%s",
+ print_kptr((KA_T)ps->pshminfo.pshm_mappaddr, (char *)NULL, 0));
+ enter_nm(Namech);
+ }
+/*
+ * Enable offset or size reporting.
+ */
+ if (Foffset)
+ Lf->off_def = 1;
+ else {
+ Lf->sz = (SZOFFTYPE)ps->pshminfo.pshm_stat.vst_size;
+ Lf->sz_def = 1;
+ }
+}
+
+
+void
+process_pshm(pid, fd)
+ int pid; /* PID */
+ int32_t fd; /* FD */
+{
+ int nb;
+ struct pshm_fdinfo ps;
+/*
+ * Get the POSIX shared memory file information.
+ */
+ nb = proc_pidfdinfo(pid, fd, PROC_PIDFDPSHMINFO, &ps, sizeof(ps));
+ if (nb <= 0) {
+ (void) err2nm("POSIX shared memory");
+ return;
+ } else if (nb < sizeof(ps)) {
+ (void) fprintf(stderr,
+ "%s: PID %d, FD %d; proc_pidfdinfo(PROC_PIDFDPSHMINFO);\n",
+ Pn, pid, fd);
+ (void) fprintf(stderr,
+ " too few bytes; expected %ld, got %d\n",
+ sizeof(ps), nb);
+ Exit(1);
+ }
+
+ process_pshm_common(&ps);
+}
+
+
+#ifdef PROC_PIDLISTFILEPORTS
+void
+process_fileport_pshm(pid, fp)
+ int pid; /* PID */
+ uint32_t fp; /* FILEPORT */
+{
+ int nb;
+ struct pshm_fdinfo ps;
+/*
+ * Get the POSIX shared memory file information.
+ */
+ nb = proc_pidfileportinfo(pid, fp, PROC_PIDFILEPORTPSHMINFO, &ps, sizeof(ps));
+ if (nb <= 0) {
+ (void) err2nm("POSIX shared memory");
+ return;
+ } else if (nb < sizeof(ps)) {
+ (void) fprintf(stderr,
+ "%s: PID %d, FILEPORT %u; proc_pidfileportinfo(PROC_PIDFILEPORTPSHMINFO);\n",
+ Pn, pid, fp);
+ (void) fprintf(stderr,
+ " too few bytes; expected %ld, got %d\n",
+ sizeof(ps), nb);
+ Exit(1);
+ }
+
+ process_pshm_common(&ps);
+}
+#endif /* PROC_PIDLISTFILEPORTS */
+
+
+/*
+ * process_vnode() -- process a vnode file
+ */
+
+static void
+process_vnode_common(vi)
+ struct vnode_fdinfowithpath *vi;
+{
+/*
+ * Enter the file and vnode information.
+ */
+ enter_file_info(&vi->pfi);
+ enter_vnode_info(&vi->pvip);
+}
+
+
+void
+process_vnode(pid, fd)
+ int pid; /* PID */
+ int32_t fd; /* FD */
+{
+ int nb;
+ struct vnode_fdinfowithpath vi;
+
+ nb = proc_pidfdinfo(pid, fd, PROC_PIDFDVNODEPATHINFO, &vi, sizeof(vi));
+ if (nb <= 0) {
+ if (errno == ENOENT) {
+
+ /*
+ * The file descriptor's vnode may have been revoked. This is a
+ * bit of a hack, since an ENOENT error might not always mean the
+ * descriptor's vnode has been revoked. As the libproc API
+ * matures, this code may need to be revisited.
+ */
+ enter_nm("(revoked)");
+ } else
+ (void) err2nm("vnode");
+ return;
+ } else if (nb < sizeof(vi)) {
+ (void) fprintf(stderr,
+ "%s: PID %d, FD %d: proc_pidfdinfo(PROC_PIDFDVNODEPATHINFO);\n",
+ Pn, pid, fd);
+ (void) fprintf(stderr,
+ " too few bytes; expected %ld, got %d\n",
+ sizeof(vi), nb);
+ Exit(1);
+ }
+
+ process_vnode_common(&vi);
+}
+
+
+#ifdef PROC_PIDLISTFILEPORTS
+void
+process_fileport_vnode(pid, fp)
+ int pid; /* PID */
+ uint32_t fp; /* FILEPORT */
+{
+ int nb;
+ struct vnode_fdinfowithpath vi;
+
+ nb = proc_pidfileportinfo(pid, fp, PROC_PIDFILEPORTVNODEPATHINFO, &vi, sizeof(vi));
+ if (nb <= 0) {
+ if (errno == ENOENT) {
+
+ /*
+ * The file descriptor's vnode may have been revoked. This is a
+ * bit of a hack, since an ENOENT error might not always mean the
+ * descriptor's vnode has been revoked. As the libproc API
+ * matures, this code may need to be revisited.
+ */
+ enter_nm("(revoked)");
+ } else
+ (void) err2nm("vnode");
+ return;
+ } else if (nb < sizeof(vi)) {
+ (void) fprintf(stderr,
+ "%s: PID %d, FILEPORT %u: proc_pidfdinfo(PROC_PIDFDVNODEPATHINFO);\n",
+ Pn, pid, fp);
+ (void) fprintf(stderr,
+ " too few bytes; expected %ld, got %d\n",
+ sizeof(vi), nb);
+ Exit(1);
+ }
+
+ process_vnode_common(&vi);
+}
+#endif /* PROC_PIDLISTFILEPORTS */
diff --git a/dialects/darwin/libproc/dlsof.h b/dialects/darwin/libproc/dlsof.h
new file mode 100644
index 0000000..142a073
--- /dev/null
+++ b/dialects/darwin/libproc/dlsof.h
@@ -0,0 +1,136 @@
+/*
+ * dlsof.h -- Darwin header file for libproc-based lsof
+ */
+
+
+/*
+ * Portions Copyright 2005-2007 Apple Inc. All rights reserved.
+ *
+ * Copyright 2005 Purdue Research Foundation, West Lafayette, Indiana
+ * 47907. All rights reserved.
+ *
+ * Written by Allan Nathanson, Apple Inc., and Victor A. Abell, Purdue
+ * University.
+ *
+ * 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 Apple Inc. 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, Apple
+ * Inc. 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.
+ */
+
+
+/*
+ * $Id: dlsof.h,v 1.8 2012/04/10 16:41:04 abe Exp $
+ */
+
+
+#if !defined(DARWIN_LSOF_H)
+#define DARWIN_LSOF_H 1
+
+#include <stdlib.h>
+#include <dirent.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+#include <wctype.h>
+#include <arpa/inet.h>
+#include <sys/attr.h>
+#include <sys/fcntl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp_fsm.h>
+#include <netinet/tcp_timer.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <libproc.h>
+
+# if DARWINV<900
+#define vst_blksize st_blksize
+#define vst_dev st_dev
+#define vst_ino st_ino
+#define vst_mode st_mode
+#define vst_nlink st_nlink
+#define vst_rdev st_rdev
+#define vst_size st_size
+# endif /* DARWINV<=900 */
+
+#define COMP_P const void
+#define DEVINCR 1024 /* device table malloc() increment */
+#define DIRTYPE dirent /* directory entry type */
+typedef uintptr_t KA_T;
+#define KA_T_FMT_X "0x%08lx"
+#define LOGINML MAXLOGNAME
+#define MALLOC_P void
+#define FREE_P MALLOC_P
+#define MALLOC_S size_t
+#define MAXSYSCMDL (MAXCOMLEN - 1) /* max system command name length */
+#define MOUNTED MNT_MNTTAB
+#define QSORT_P void
+#define READLEN_T int
+#define STRNCPY_L size_t
+#define SZOFFTYPE unsigned long long
+ /* size and offset internal storage
+ * type */
+#define SZOFFPSPEC "ll" /* SZOFFTYPE printf specification
+ * modifier */
+
+
+/*
+ * Global storage definitions (including their structure definitions)
+ */
+
+struct file *Cfp;
+
+struct mounts {
+ char *dir; /* directory (mounted on) */
+ char *fsname; /* file system
+ * (symbolic links unresolved) */
+ char *fsnmres; /* file system
+ * (symbolic links resolved) */
+ dev_t dev; /* directory st_dev */
+ dev_t rdev; /* directory st_rdev */
+ INODETYPE inode; /* directory st_ino */
+ mode_t mode; /* directory st_mode */
+ mode_t fs_mode; /* file system st_mode */
+ int is_nfs; /* 1 if NFS file system, 0 if not */
+ struct mounts *next; /* forward link */
+};
+
+struct sfile {
+ char *aname; /* argument file name */
+ char *name; /* file name (after readlink()) */
+ char *devnm; /* device name (optional) */
+ dev_t dev; /* device */
+ dev_t rdev; /* raw device */
+ u_short mode; /* S_IFMT mode bits from stat() */
+ int type; /* file type: 0 = file system
+ * 1 = regular file */
+ INODETYPE i; /* inode number */
+ int f; /* file found flag */
+ struct sfile *next; /* forward link */
+
+};
+
+#define XDR_VOID (const xdrproc_t)xdr_void
+#define XDR_PMAPLIST (const xdrproc_t)xdr_pmaplist
+
+# if !defined(offsetof)
+#define offsetof(type, member) ((size_t)(&((type *)0)->member))
+# endif /* !defined(offsetof) */
+
+#endif /* DARWIN_LSOF_H */
diff --git a/dialects/darwin/libproc/dmnt.c b/dialects/darwin/libproc/dmnt.c
new file mode 100644
index 0000000..576f432
--- /dev/null
+++ b/dialects/darwin/libproc/dmnt.c
@@ -0,0 +1,201 @@
+/*
+ * dmnt.c -- Darwin mount support functions for libproc-based lsof
+ */
+
+
+/*
+ * Portions Copyright 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * Copyright 2005 Purdue Research Foundation, West Lafayette, Indiana
+ * 47907. All rights reserved.
+ *
+ * Written by Allan Nathanson, Apple Computer, Inc., and Victor A.
+ * Abell, Purdue University.
+ *
+ * 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 Apple Computer, Inc. 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, Apple
+ * Computer, Inc. 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 2005 Apple Computer, Inc. and Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dmnt.c,v 1.6 2012/04/10 16:41:04 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+/*
+ * Local static information
+ */
+
+static struct mounts *Lmi = (struct mounts *)NULL; /* local mount info */
+static int Lmist = 0; /* Lmi status */
+
+/*
+ * readmnt() -- read mount table
+ */
+
+struct mounts *
+readmnt()
+{
+#if defined(DIR_MNTSTATUS_TRIGGER)
+ struct {
+ uint32_t length;
+ uint32_t mount_flags;
+ } ab;
+ struct attrlist al;
+#endif /* defined(DIR_MNTSTATUS_TRIGGER) */
+ char *dn = (char *)NULL;
+ char *ln;
+ struct statfs *mb = (struct statfs *)NULL;
+ struct mounts *mtp;
+ int n;
+ struct stat sb;
+
+ if (Lmi || Lmist)
+ return(Lmi);
+/*
+ * Access mount information.
+ */
+ if ((n = getmntinfo(&mb, MNT_NOWAIT)) <= 0) {
+ (void) fprintf(stderr, "%s: no mount information\n", Pn);
+ return(0);
+ }
+/*
+ * Read mount information.
+ */
+ for (; n; n--, mb++) {
+
+ if (!mb->f_type)
+ continue;
+ /*
+ * Avoid file systems that are not appropriate paths to
+ * user data (e.g. automount maps, triggers).
+ */
+#if defined(DIR_MNTSTATUS_TRIGGER)
+ (void) bzero((char *)&al, sizeof(al));
+ al.bitmapcount = ATTR_BIT_MAP_COUNT;
+ al.dirattr = ATTR_DIR_MOUNTSTATUS;
+ if (getattrlist(mb->f_mntonname, &al, &ab, sizeof(ab), 0) == 0) {
+ if (ab.mount_flags & DIR_MNTSTATUS_TRIGGER)
+ continue; // if mount trigger
+ }
+#else /* !defined(DIR_MNTSTATUS_TRIGGER) */
+ if (mb->f_flags & MNT_AUTOMOUNTED) {
+ if (!strncmp(mb->f_mntfromname, "map ", 4)
+ || !strcmp(mb->f_mntfromname, "trigger"))
+ continue;
+ }
+#endif /* defined(DIR_MNTSTATUS_TRIGGER) */
+
+ /*
+ * Interpolate a possible symbolic directory link.
+ */
+ if (dn)
+ (void) free((FREE_P *)dn);
+ if (!(dn = mkstrcpy(mb->f_mntonname, (MALLOC_S *)NULL))) {
+
+no_space_for_mount:
+
+ (void) fprintf(stderr, "%s: no space for mount at ", Pn);
+ safestrprt(mb->f_mntonname, stderr, 0);
+ (void) fprintf(stderr, " (");
+ safestrprt(mb->f_mntfromname, stderr, 0);
+ (void) fprintf(stderr, ")\n");
+ Exit(1);
+ }
+ if (!(ln = Readlink(dn))) {
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ " Output information may be incomplete.\n");
+ }
+ continue;
+ }
+ if (ln != dn) {
+ (void) free((FREE_P *)dn);
+ dn = ln;
+ }
+ if (*dn != '/')
+ continue;
+ /*
+ * Stat() the directory.
+ */
+ if (statsafely(dn, &sb)) {
+ if (!Fwarn) {
+ (void) fprintf(stderr, "%s: WARNING: can't stat() ", Pn);
+
+ safestrprt(mb->f_fstypename, stderr, 0);
+
+ (void) fprintf(stderr, " file system ");
+ safestrprt(mb->f_mntonname, stderr, 1);
+ (void) fprintf(stderr,
+ " Output information may be incomplete.\n");
+ }
+ (void) bzero((char *)&sb, sizeof(sb));
+ sb.st_dev = (dev_t)mb->f_fsid.val[0];
+ sb.st_mode = S_IFDIR | 0777;
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ " assuming \"dev=%x\" from mount table\n",
+ sb.st_dev);
+ }
+ }
+ /*
+ * Allocate and fill a local mount structure.
+ */
+ if (!(mtp = (struct mounts *)malloc(sizeof(struct mounts))))
+ goto no_space_for_mount;
+ mtp->dir = dn;
+ dn = (char *)NULL;
+ mtp->next = Lmi;
+ mtp->dev = sb.st_dev;
+ mtp->rdev = sb.st_rdev;
+ mtp->inode = (INODETYPE)sb.st_ino;
+ mtp->mode = sb.st_mode;
+ mtp->is_nfs = strcasecmp(mb->f_fstypename, "nfs") ? 0 : 1;
+ /*
+ * Interpolate a possible file system (mounted-on) device name link.
+ */
+ if (!(dn = mkstrcpy(mb->f_mntfromname, (MALLOC_S *)NULL)))
+ goto no_space_for_mount;
+ mtp->fsname = dn;
+ ln = Readlink(dn);
+ dn = (char *)NULL;
+ /*
+ * Stat() the file system (mounted-on) name and add file system
+ * information to the local mount table entry.
+ */
+ if (!ln || statsafely(ln, &sb))
+ sb.st_mode = 0;
+ mtp->fsnmres = ln;
+ mtp->fs_mode = sb.st_mode;
+ Lmi = mtp;
+ }
+/*
+ * Clean up and return the local mount info table address.
+ */
+ if (dn)
+ (void) free((FREE_P *)dn);
+ Lmist = 1;
+ return(Lmi);
+}
diff --git a/dialects/darwin/libproc/dproc.c b/dialects/darwin/libproc/dproc.c
new file mode 100644
index 0000000..e4a2f00
--- /dev/null
+++ b/dialects/darwin/libproc/dproc.c
@@ -0,0 +1,839 @@
+/*
+ * dproc.c -- Darwin process access functions for libproc-based lsof
+ */
+
+
+/*
+ * Portions Copyright 2005-2007 Apple Inc. All rights reserved.
+ *
+ * Copyright 2005 Purdue Research Foundation, West Lafayette, Indiana
+ * 47907. All rights reserved.
+ *
+ * Written by Allan Nathanson, Apple Inc., and Victor A. Abell, Purdue
+ * University.
+ *
+ * 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 Apple Inc. 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, Apple
+ * Inc. and Purdue University must appear in documentation and sources.
+ * 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 2005-2007 Apple Inc. and Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dproc.c,v 1.9 2013/01/02 17:03:05 abe Exp $";
+#endif
+
+#include "lsof.h"
+
+
+/*
+ * Local definitions
+ */
+
+#define PIDS_INCR (sizeof(int) * 32) /* PID space increment */
+#define VIPS_INCR 16 /* Vips space increment */
+
+#if DARWINV>=900
+#define THREADS_INCR (sizeof(uint64_t) * 32) /* Threads space increment */
+#endif /* DARWINV>=900 */
+
+#ifdef PROC_PIDLISTFILEPORTS
+#define FILEPORTS_INCR (sizeof(struct proc_fileportinfo) * 32) /* Fileports space increment */
+#endif /* PROC_PIDLISTFILEPORTS */
+
+/*
+ * Local static variables
+ */
+
+static struct proc_fdinfo *Fds = (struct proc_fdinfo *)NULL;
+ /* FD buffer */
+static int NbPids = 0; /* bytes allocated to Pids */
+static int NbFds = 0; /* bytes allocated to FDs */
+static int *Pids = (int *)NULL; /* PID buffer */
+
+#if DARWINV>=900
+static int NbThreads = 0; /* Threads bytes allocated */
+static uint64_t *Threads = (uint64_t *)NULL; /* Thread buffer */
+#endif /* DARWINV>=900 */
+
+#ifdef PROC_PIDLISTFILEPORTS
+static struct proc_fileportinfo *Fps = (struct proc_fileportinfo *)NULL;
+ /* fileport buffer */
+static int NbFps = 0; /* bytes allocated to fileports */
+#endif /* PROC_PIDLISTFILEPORTS */
+
+/*
+ * Local structure definitions
+ */
+
+static struct vips_info {
+ dev_t dev;
+ ino_t ino;
+} *Vips = (struct vips_info *)NULL; /* recorded vnodes */
+static int NbVips = 0; /* bytes allocated to Vips */
+static int NVips = 0; /* entries allocated to Vips */
+
+
+/*
+ * Local function prototypes
+ */
+_PROTOTYPE(static void enter_vn_text,(struct vnode_info_path *vip, int *n));
+_PROTOTYPE(static void process_fds,(int pid, uint32_t n, int ckscko));
+_PROTOTYPE(static void process_text,(int pid));
+
+#if DARWINV>=900
+_PROTOTYPE(static void process_threads,(int pid, uint32_t n));
+#endif /* DARWINV>=900 */
+
+#ifdef PROC_PIDLISTFILEPORTS
+_PROTOTYPE(static void process_fileports,(int pid, int ckscko));
+#endif /* PROC_PIDLISTFILEPORTS */
+
+/*
+ * enter_vn_text() -- enter vnode information text reference
+ */
+
+static void
+enter_vn_text(vip, n)
+ struct vnode_info_path *vip; /* vnode info */
+ int *n; /* number of vips[] entries in use */
+{
+ int i;
+/*
+ * Ignore the request if the vnode information has already been entered.
+ */
+ for (i = 0; i < *n; i++) {
+ if ((vip->vip_vi.vi_stat.vst_dev == Vips[i].dev)
+ && (vip->vip_vi.vi_stat.vst_ino == Vips[i].ino))
+ {
+ return;
+ }
+ }
+/*
+ * Save the text file information.
+ */
+ alloc_lfile(" txt", -1);
+ Cfp = (struct file *)NULL;
+ (void) enter_vnode_info(vip);
+ if (Lf->sf)
+ link_lfile();
+/*
+ * Record the entry of the vnode information.
+ */
+ if (i >= NVips) {
+
+ /*
+ * Allocate space for recording the vnode information.
+ */
+ NVips += VIPS_INCR;
+ NbVips += (int)(VIPS_INCR * sizeof(struct vips_info));
+ if (!Vips)
+ Vips = (struct vips_info *)malloc((MALLOC_S)NbVips);
+ else
+ Vips = (struct vips_info *)realloc((MALLOC_P *)Vips,
+ (MALLOC_S)NbVips);
+ if (!Vips) {
+ (void) fprintf(stderr, "%s: PID %d: no text recording space\n",
+ Pn, Lp->pid);
+ Exit(1);
+ }
+ }
+/*
+ * Record the vnode information.
+ */
+ Vips[*n].dev = vip->vip_vi.vi_stat.vst_dev;
+ Vips[*n].ino = vip->vip_vi.vi_stat.vst_ino;
+ (*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 cre, cres, ef, i, nb, np, pid;
+ short pss, sf;
+ struct proc_taskallinfo tai;
+ struct proc_vnodepathinfo vpi;
+/*
+ * Define socket and regular file conditional processing flags.
+ *
+ * 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;
+ }
+/*
+ * Determine how many bytes are needed to contain the PIDs on the system;
+ * make sure sufficient buffer space is allocated to hold them (and a few
+ * extra); then read the list of PIDs.
+ */
+ if ((nb = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0)) <= 0) {
+ (void) fprintf(stderr, "%s: can't get PID byte count: %s\n",
+ Pn, strerror(errno));
+ Exit(1);
+ }
+ if (nb > NbPids) {
+ while (nb > NbPids) {
+ NbPids += PIDS_INCR;
+ }
+ if (!Pids)
+ Pids = (int *)malloc((MALLOC_S)NbPids);
+ else
+ Pids = (int *)realloc((MALLOC_P *)Pids, (MALLOC_S)NbPids);
+ if (!Pids) {
+ (void) fprintf(stderr,
+ "%s: can't allocate space for %d PIDs\n", Pn,
+ (int)(NbPids / sizeof(int *)));
+ Exit(1);
+ }
+ }
+/*
+ * Get the list of PIDs.
+ */
+ for (ef = 0; !ef;) {
+ if ((nb = proc_listpids(PROC_ALL_PIDS, 0, Pids, NbPids)) <= 0) {
+ (void) fprintf(stderr, "%s: can't get list of PIDs: %s\n",
+ Pn, strerror(errno));
+ Exit(1);
+ }
+
+ if ((nb + sizeof(int)) < NbPids) {
+
+ /*
+ * There is room in the buffer for at least one more PID.
+ */
+ np = nb / sizeof(int);
+ ef = 1;
+ } else {
+
+ /*
+ * The PID buffer must be enlarged.
+ */
+ NbPids += PIDS_INCR;
+ Pids = (int *)realloc((MALLOC_P *)Pids, (MALLOC_S)NbPids);
+ if (!Pids) {
+ (void) fprintf(stderr,
+ "%s: can't allocate space for %d PIDs\n", Pn,
+ (int)(NbPids / sizeof(int *)));
+ Exit(1);
+ }
+ }
+ }
+/*
+ * Loop through the identified processes.
+ */
+ for (i = 0; i < np; i++) {
+ if (!(pid = Pids[i]))
+ continue;
+ nb = proc_pidinfo(pid, PROC_PIDTASKALLINFO, 0, &tai, sizeof(tai));
+ if (nb <= 0) {
+ if ((errno == EPERM) || (errno == ESRCH))
+ continue;
+ if (!Fwarn) {
+ (void) fprintf(stderr, "%s: PID %d information error: %s\n",
+ Pn, pid, strerror(errno));
+ }
+ continue;
+ } else if (nb < sizeof(tai)) {
+ (void) fprintf(stderr,
+ "%s: PID %d: proc_pidinfo(PROC_PIDTASKALLINFO);\n",
+ Pn, pid);
+ (void) fprintf(stderr,
+ " too few bytes; expected %ld, got %d\n",
+ sizeof(tai), nb);
+ Exit(1);
+ }
+ /*
+ * Check for process or command exclusion.
+ */
+ if (is_proc_excl((int)pid, (int)tai.pbsd.pbi_pgid,
+ (UID_ARG)tai.pbsd.pbi_uid, &pss, &sf))
+ {
+ continue;
+ }
+ tai.pbsd.pbi_comm[sizeof(tai.pbsd.pbi_comm) - 1] = '\0';
+ if (is_cmd_excl(tai.pbsd.pbi_comm, &pss, &sf))
+ continue;
+ if (tai.pbsd.pbi_name[0]) {
+ tai.pbsd.pbi_name[sizeof(tai.pbsd.pbi_name) - 1] = '\0';
+ if (is_cmd_excl(tai.pbsd.pbi_name, &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;
+ }
+ /*
+ * Get root and current directory information.
+ */
+ if (!ckscko) {
+ nb = proc_pidinfo(pid, PROC_PIDVNODEPATHINFO, 0, &vpi,
+ sizeof(vpi));
+ if (nb <= 0) {
+ cre = errno;
+ cres = 1;
+ } else if (nb < sizeof(vpi)) {
+ (void) fprintf(stderr,
+ "%s: PID %d: proc_pidinfo(PROC_PIDVNODEPATHINFO);\n",
+ Pn, pid);
+ (void) fprintf(stderr,
+ " too few bytes; expected %ld, got %d\n",
+ sizeof(vpi), nb);
+ Exit(1);
+ } else
+ cres = 0;
+ }
+ /*
+ * Allocate local process space.
+ */
+ alloc_lproc((int)pid, (int)tai.pbsd.pbi_pgid,
+ (int)tai.pbsd.pbi_ppid, (UID_ARG)tai.pbsd.pbi_uid,
+ (tai.pbsd.pbi_name[0] != '\0') ? tai.pbsd.pbi_name
+ : tai.pbsd.pbi_comm,
+ (int)pss, (int)sf);
+ Plf = (struct lfile *)NULL;
+ /*
+ * Save current working directory information.
+ */
+ if (!ckscko) {
+ if (cres || vpi.pvi_cdir.vip_path[0]) {
+ alloc_lfile(CWD, -1);
+ Cfp = (struct file *)NULL;
+ if (cres) {
+
+ /*
+ * If the CWD|RTD information access error is ESRCH,
+ * ignore it; otherwise report the error's message in the
+ * CWD's NAME column.
+ */
+ if (cre != ESRCH) {
+ (void) snpf(Namech, Namechl, "%s|%s info error: %s",
+ CWD + 1, RTD + 1, strerror(cre));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ if (Lf->sf)
+ link_lfile();
+ }
+ } else {
+ (void) enter_vnode_info(&vpi.pvi_cdir);
+ if (Lf->sf)
+ link_lfile();
+ }
+ }
+ }
+ /*
+ * Save root directory information.
+ */
+ if (!ckscko) {
+ if (!cres && vpi.pvi_rdir.vip_path[0]) {
+ alloc_lfile(RTD, -1);
+ Cfp = (struct file *)NULL;
+ (void) enter_vnode_info(&vpi.pvi_rdir);
+ if (Lf->sf)
+ link_lfile();
+ }
+ }
+
+#if DARWINV>=900
+ /*
+ * Check for per-thread current working directories
+ */
+ if (!ckscko) {
+ if (tai.pbsd.pbi_flags & PROC_FLAG_THCWD) {
+ (void) process_threads(pid, tai.ptinfo.pti_threadnum);
+ }
+ }
+#endif /* DARWINV>=900 */
+
+ /*
+ * Print text file information.
+ */
+ if (!ckscko)
+ (void) process_text(pid);
+
+#ifdef PROC_PIDLISTFILEPORTS
+ /*
+ * Loop through the fileports
+ */
+ (void) process_fileports(pid, ckscko);
+#endif /* PROC_PIDLISTFILEPORTS */
+
+ /*
+ * Loop through the file descriptors.
+ */
+ (void) process_fds(pid, tai.pbsd.pbi_nfiles, ckscko);
+ /*
+ * Examine results.
+ */
+ if (examine_lproc())
+ return;
+ }
+}
+
+
+/*
+ * initialize() -- perform all initialization
+ */
+
+void
+initialize()
+{
+}
+
+
+/*
+ * process_fds() -- process file descriptors
+ */
+
+static void
+process_fds(pid, n, ckscko)
+ int pid; /* PID of interest */
+ uint32_t n; /* max FDs */
+ int ckscko; /* check socket files only */
+{
+ int i, isock, nb, nf;
+ struct proc_fdinfo *fdp;
+/*
+ * Make sure an FD buffer has been allocated.
+ */
+ if (!Fds) {
+ NbFds = sizeof(struct proc_fdinfo) * n;
+ Fds = (struct proc_fdinfo *)malloc((MALLOC_S)NbFds);
+ } else if (NbFds < sizeof(struct proc_fdinfo) * n) {
+
+ /*
+ * More proc_fdinfo space is required. Allocate it.
+ */
+ NbFds = sizeof(struct proc_fdinfo) * n;
+ Fds = (struct proc_fdinfo *)realloc((MALLOC_P *)Fds,
+ (MALLOC_S)NbFds);
+ }
+ if (!Fds) {
+ (void) fprintf(stderr,
+ "%s: PID %d: can't allocate space for %d FDs\n",
+ Pn, pid, (int)(NbFds / sizeof(struct proc_fdinfo)));
+ Exit(1);
+ }
+/*
+ * Get FD information for the process.
+ */
+ nb = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, Fds, NbFds);
+ if (nb <= 0) {
+ if (errno == ESRCH) {
+
+ /*
+ * Quit if no FD information is available for the process.
+ */
+ return;
+ }
+ /*
+ * Make a dummy file entry with an error message in its NAME column.
+ */
+ alloc_lfile(" err", -1);
+ (void) snpf(Namech, Namechl, "FD info error: %s", strerror(errno));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ if (Lf->sf)
+ link_lfile();
+ return;
+ }
+ nf = (int)(nb / sizeof(struct proc_fdinfo));
+/*
+ * Loop through the file descriptors.
+ */
+ for (i = 0; i < nf; i++) {
+ fdp = &Fds[i];
+ alloc_lfile(NULL, (int)fdp->proc_fd);
+ /*
+ * Process the file by its type.
+ */
+ isock = 0;
+ switch (fdp->proc_fdtype) {
+ case PROX_FDTYPE_ATALK:
+ if (!ckscko)
+ (void) process_atalk(pid, fdp->proc_fd);
+ break;
+ case PROX_FDTYPE_FSEVENTS:
+ if (!ckscko)
+ (void) process_fsevents(pid, fdp->proc_fd);
+ break;
+ case PROX_FDTYPE_KQUEUE:
+ if (!ckscko)
+ (void) process_kqueue(pid, fdp->proc_fd);
+ break;
+ case PROX_FDTYPE_PIPE:
+ if (!ckscko)
+ (void) process_pipe(pid, fdp->proc_fd);
+ break;
+ case PROX_FDTYPE_PSEM:
+ if (!ckscko)
+ (void) process_psem(pid, fdp->proc_fd);
+ break;
+ case PROX_FDTYPE_SOCKET:
+ (void) process_socket(pid, fdp->proc_fd);
+ isock = 1;
+ break;
+ case PROX_FDTYPE_PSHM:
+ (void) process_pshm(pid, fdp->proc_fd);
+ break;
+ case PROX_FDTYPE_VNODE:
+ (void) process_vnode(pid, fdp->proc_fd);
+ break;
+ default:
+ (void) snpf(Namech, Namechl - 1, "unknown file type: %d",
+ fdp->proc_fdtype);
+ Namech[Namechl - 1] = '\0';
+ (void) enter_nm(Namech);
+ break;
+ }
+ if (Lf->sf) {
+ if (!ckscko || isock)
+ link_lfile();
+ }
+ }
+}
+
+
+#ifdef PROC_PIDLISTFILEPORTS
+/*
+ * process_fileports() -- process fileports
+ */
+
+static void
+process_fileports(pid, ckscko)
+ int pid; /* PID of interest */
+ int ckscko; /* check socket files only */
+{
+ int ef, i, isock, nb = 0, nf;
+ struct proc_fileportinfo *fpi;
+
+/*
+ * Get fileport information for the process.
+ */
+ for (ef = 0; !ef;) {
+ nb = proc_pidinfo(pid, PROC_PIDLISTFILEPORTS, 0, Fps, NbFps);
+ if (nb == 0) {
+
+ /*
+ * Quit if no fileport information
+ */
+ return;
+ } else if (nb < 0) {
+ if (errno == ESRCH) {
+
+ /*
+ * Quit if no fileport information is available for the process.
+ */
+ return;
+ }
+ /*
+ * Make a dummy file entry with an error message in its NAME column.
+ */
+ alloc_lfile(" err", -1);
+ (void) snpf(Namech, Namechl, "FILEPORT info error: %s", strerror(errno));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ if (Lf->sf)
+ link_lfile();
+ }
+
+ if ((nb + sizeof(struct proc_fileportinfo)) < NbFps) {
+
+ /*
+ * There is room in the buffer for at least one more fileport.
+ */
+ ef = 1;
+ } else {
+ if (Fps && ((nb = proc_pidinfo(pid, PROC_PIDLISTFILEPORTS, 0, NULL, 0)) <= 0)) {
+ (void) fprintf(stderr, "%s: can't get fileport byte count: %s\n",
+ Pn, strerror(errno));
+ Exit(1);
+ }
+
+ /*
+ * The fileport buffer must be enlarged.
+ */
+ while (nb > NbFps) {
+ NbFps += FILEPORTS_INCR;
+ }
+ if (!Fps)
+ Fps = (struct proc_fileportinfo *)malloc((MALLOC_S)NbFps);
+ else
+ Fps = (struct proc_fileportinfo *)realloc((MALLOC_P *)Fps, (MALLOC_S)NbFps);
+ }
+ }
+
+/*
+ * Loop through the fileports.
+ */
+ nf = (int)(nb / sizeof(struct proc_fileportinfo));
+ for (i = 0; i < nf; i++) {
+ fpi = &Fps[i];
+ /*
+ * fileport reported as "fp." with "(fileport=0xXXXX)" in the Name column
+ */
+ alloc_lfile(" fp.", -1);
+ Lf->fileport = fpi->proc_fileport;
+ /*
+ * Process the file by its type.
+ */
+ isock = 0;
+ switch (fpi->proc_fdtype) {
+ case PROX_FDTYPE_PIPE:
+ if (!ckscko)
+ (void) process_fileport_pipe(pid, fpi->proc_fileport);
+ break;
+ case PROX_FDTYPE_SOCKET:
+ (void) process_fileport_socket(pid, fpi->proc_fileport);
+ isock = 1;
+ break;
+ case PROX_FDTYPE_PSHM:
+ (void) process_fileport_pshm(pid, fpi->proc_fileport);
+ break;
+ case PROX_FDTYPE_VNODE:
+ (void) process_fileport_vnode(pid, fpi->proc_fileport);
+ break;
+ default:
+ (void) snpf(Namech, Namechl - 1, "unknown file type: %d",
+ fpi->proc_fileport);
+ Namech[Namechl - 1] = '\0';
+ (void) enter_nm(Namech);
+ break;
+ }
+ if (Lf->sf) {
+ if (!ckscko || isock)
+ link_lfile();
+ }
+ }
+}
+#endif /* PROC_PIDLISTFILEPORTS */
+
+
+/*
+ * process_text() -- process text information
+ */
+
+static void
+process_text(pid)
+ int pid; /* PID */
+{
+ uint64_t a;
+ int i, n, nb;
+ struct proc_regionwithpathinfo rwpi;
+
+ for (a = (uint64_t)0, i = n = 0; i < 10000; i++) {
+ nb = proc_pidinfo(pid, PROC_PIDREGIONPATHINFO, a, &rwpi,
+ sizeof(rwpi));
+ if (nb <= 0) {
+ if ((errno == ESRCH) || (errno == EINVAL)) {
+
+ /*
+ * Quit if no more text information is available for the
+ * process.
+ */
+ return;
+ }
+ /*
+ * Warn about all other errors via a NAME column message.
+ */
+ alloc_lfile(" txt", -1);
+ Cfp = (struct file *)NULL;
+ (void) snpf(Namech, Namechl,
+ "region info error: %s", strerror(errno));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ if (Lf->sf)
+ link_lfile();
+ return;
+ } else if (nb < sizeof(rwpi)) {
+ (void) fprintf(stderr,
+ "%s: PID %d: proc_pidinfo(PROC_PIDREGIONPATHINFO);\n",
+ Pn, pid);
+ (void) fprintf(stderr,
+ " too few bytes; expected %ld, got %d\n",
+ sizeof(rwpi), nb);
+ Exit(1);
+ }
+ if (rwpi.prp_vip.vip_path[0])
+ enter_vn_text(&rwpi.prp_vip, &n);
+ a = rwpi.prp_prinfo.pri_address + rwpi.prp_prinfo.pri_size;
+ }
+}
+
+
+#if DARWINV>=900
+/*
+ * process_threads() -- process thread information
+ */
+
+#define TWD " twd" /* per-thread current working directory
+ * fd name */
+
+static void
+process_threads(pid, n)
+ int pid; /* PID */
+ uint32_t n; /* number of threads */
+{
+ int i, nb, nt;
+/*
+ * Make sure a thread buffer has been allocated.
+ */
+ n += 10;
+ if (n > NbThreads) {
+ while (n > NbThreads) {
+ NbThreads += THREADS_INCR;
+ }
+ if (!Threads)
+ Threads = (uint64_t *)malloc((MALLOC_S)NbThreads);
+ else
+ Threads = (uint64_t *)realloc((MALLOC_P *)Threads,
+ (MALLOC_S)NbThreads);
+ if (!Threads) {
+ (void) fprintf(stderr,
+ "%s: can't allocate space for %d Threads\n", Pn,
+ (int)(NbThreads / sizeof(int *)));
+ Exit(1);
+ }
+ }
+/*
+ * Get thread information for the process.
+ */
+ nb = proc_pidinfo(pid, PROC_PIDLISTTHREADS, 0, Threads, NbThreads);
+ if (nb <= 0) {
+ if (errno == ESRCH) {
+
+ /*
+ * Quit if no thread information is available for the
+ * process.
+ */
+ return;
+ }
+ }
+ nt = (int)(nb / sizeof(uint64_t));
+/*
+ * Loop through the threads.
+ */
+ for (i = 0; i < nt; i++) {
+ uint64_t t;
+ struct proc_threadwithpathinfo tpi;
+
+ t = Threads[i];
+ nb = proc_pidinfo(pid, PROC_PIDTHREADPATHINFO, t, &tpi,
+ sizeof(tpi));
+ if (nb <= 0) {
+ if ((errno == ESRCH) || (errno == EINVAL)) {
+
+ /*
+ * Quit if no more thread information is available for the
+ * process.
+ */
+ return;
+ }
+ /*
+ * Warn about all other errors via a NAME column message.
+ */
+ alloc_lfile(TWD, -1);
+ Cfp = (struct file *)NULL;
+ (void) snpf(Namech, Namechl,
+ "thread info error: %s", strerror(errno));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ if (Lf->sf)
+ link_lfile();
+ return;
+ } else if (nb < sizeof(tpi)) {
+ (void) fprintf(stderr,
+ "%s: PID %d: proc_pidinfo(PROC_PIDTHREADPATHINFO);\n",
+ Pn, pid);
+ (void) fprintf(stderr,
+ " too few bytes; expected %ld, got %d\n",
+ sizeof(tpi), nb);
+ Exit(1);
+ }
+ if (tpi.pvip.vip_path[0]) {
+ alloc_lfile(TWD, -1);
+ Cfp = (struct file *)NULL;
+ (void) enter_vnode_info(&tpi.pvip);
+ if (Lf->sf)
+ link_lfile();
+ }
+ }
+}
+#endif /* DARWINV>=900 */
diff --git a/dialects/darwin/libproc/dproto.h b/dialects/darwin/libproc/dproto.h
new file mode 100644
index 0000000..7f20f7d
--- /dev/null
+++ b/dialects/darwin/libproc/dproto.h
@@ -0,0 +1,61 @@
+/*
+ * dproto.h -- Darwin function prototypes for libproc-based lsof
+ *
+ * The _PROTOTYPE macro is defined in the common proto.h.
+ */
+
+
+/*
+ * Portions Copyright 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * Copyright 2005 Purdue Research Foundation, West Lafayette, Indiana
+ * 47907. All rights reserved.
+ *
+ * Written by Allan Nathanson, Apple Computer, Inc., and Victor A.
+ * Abell, Purdue University.
+ *
+ * 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 Apple Computer, Inc. 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, Apple
+ * Computer, Inc. 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.
+ */
+
+
+/*
+ * $Id: dproto.h,v 1.6 2012/04/10 16:41:04 abe Exp $
+ */
+
+_PROTOTYPE(extern void enter_file_info,(struct proc_fileinfo *pfi));
+_PROTOTYPE(extern void enter_vnode_info,(struct vnode_info_path *vip));
+_PROTOTYPE(extern void err2nm,(char *pfx));
+_PROTOTYPE(extern int is_file_named,(char *p, int cd));
+_PROTOTYPE(extern void process_atalk,(int pid, int32_t fd));
+_PROTOTYPE(extern void process_fsevents,(int pid, int32_t fd));
+_PROTOTYPE(extern void process_kqueue,(int pid, int32_t fd));
+_PROTOTYPE(extern void process_pipe,(int pid, int32_t fd));
+_PROTOTYPE(extern void process_psem,(int pid, int32_t fd));
+_PROTOTYPE(extern void process_pshm,(int pid, int32_t fd));
+_PROTOTYPE(extern void process_socket,(int pid, int32_t fd));
+_PROTOTYPE(extern void process_vnode,(int pid, int32_t fd));
+#ifdef PROC_PIDLISTFILEPORTS
+_PROTOTYPE(extern void process_fileport_pipe,(int pid, uint32_t fileport));
+_PROTOTYPE(extern void process_fileport_pshm,(int pid, uint32_t fileport));
+_PROTOTYPE(extern void process_fileport_socket,(int pid, uint32_t fileport));
+_PROTOTYPE(extern void process_fileport_vnode,(int pid, uint32_t fileport));
+#endif /* PROC_PIDLISTFILEPORTS */
+
diff --git a/dialects/darwin/libproc/dsock.c b/dialects/darwin/libproc/dsock.c
new file mode 100644
index 0000000..175ca21
--- /dev/null
+++ b/dialects/darwin/libproc/dsock.c
@@ -0,0 +1,449 @@
+/*
+ * dsock.c -- Darwin socket processing functions for libproc-based lsof
+ */
+
+
+/*
+ * Portions Copyright 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * Copyright 2005 Purdue Research Foundation, West Lafayette, Indiana
+ * 47907. All rights reserved.
+ *
+ * Written by Allan Nathanson, Apple Computer, Inc., and Victor A.
+ * Abell, Purdue University.
+ *
+ * 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 Apple Computer, Inc. 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, Apple
+ * Computer, Inc. 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 2005 Apple Computer, Inc. and Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dsock.c,v 1.7 2012/04/10 16:41:04 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+/*
+ * IPv6_2_IPv4() -- macro to define the address of an IPv4 address contained
+ * in an IPv6 address
+ */
+
+#define IPv6_2_IPv4(v6) (((uint8_t *)((struct in6_addr *)v6)->s6_addr)+12)
+
+
+/*
+ * process_socket() -- process socket file
+ */
+
+static void
+process_socket_common(si)
+ struct socket_fdinfo *si;
+{
+ unsigned char *fa = (unsigned char *)NULL;
+ int fam, fp, lp, unl;
+ unsigned char *la = (unsigned char *)NULL;
+
+/*
+ * Enter basic socket values.
+ */
+ (void) snpf(Lf->type, sizeof(Lf->type), "sock");
+ Lf->inp_ty = 2;
+/*
+ * Enter basic file information.
+ */
+ enter_file_info(&si->pfi);
+/*
+ * Enable size or offset display.
+ */
+ if (Fsize) {
+ if (Lf->access == 'r')
+ Lf->sz = (SZOFFTYPE)si->psi.soi_rcv.sbi_cc;
+ else if (Lf->access == 'w')
+ Lf->sz = (SZOFFTYPE)si->psi.soi_snd.sbi_cc;
+ else
+ Lf->sz = (SZOFFTYPE)(si->psi.soi_rcv.sbi_cc
+ + si->psi.soi_snd.sbi_cc);
+ Lf->sz_def = 1;
+ } else
+ Lf->off_def = 1;
+
+#if defined(HASTCPTPIQ)
+/*
+ * Enter send and receive queue sizes.
+ */
+ Lf->lts.rq = si->psi.soi_rcv.sbi_cc;
+ Lf->lts.sq = si->psi.soi_snd.sbi_cc;
+ Lf->lts.rqs = Lf->lts.sqs = (unsigned char)1;
+#endif /* defined(HASTCPTPIQ) */
+
+#if defined(HASSOOPT)
+/*
+ * Enter socket options.
+ */
+ Lf->lts.ltm = (unsigned int)(si->psi.soi_linger & 0xffff);
+ Lf->lts.opt = (unsigned int)(si->psi.soi_options & 0xffff);
+ Lf->lts.pqlen = (unsigned int)si->psi.soi_incqlen;
+ Lf->lts.qlen = (unsigned int)si->psi.soi_qlen;
+ Lf->lts.qlim = (unsigned int)si->psi.soi_qlimit;
+ Lf->lts.rbsz = (unsigned long)si->psi.soi_rcv.sbi_mbmax;
+ Lf->lts.sbsz = (unsigned long)si->psi.soi_snd.sbi_mbmax;
+ Lf->lts.pqlens = Lf->lts.qlens = Lf->lts.qlims = Lf->lts.rbszs
+ = Lf->lts.sbszs = (unsigned char)1;
+#endif /* defined(HASSOOPT) */
+
+#if defined(HASSOSTATE)
+/*
+ * Enter socket state.
+ */
+ Lf->lts.ss = (unsigned int)si->psi.soi_state;
+#endif /* defined(HASSOSTATE) */
+
+/*
+ * Process socket by its associated domain family.
+ */
+ switch ((fam = si->psi.soi_family)) {
+ case AF_INET:
+ case AF_INET6:
+
+ /*
+ * Process IPv[46] sockets.
+ */
+ (void) snpf(Lf->type, sizeof(Lf->type),
+ (fam == AF_INET) ? "IPv4" : "IPv6");
+ if ((si->psi.soi_kind != SOCKINFO_IN) &&
+ (si->psi.soi_kind != SOCKINFO_TCP))
+ {
+ break;
+ }
+ /*
+ * Process TCP state inclusions and exclusions, as required.
+ */
+ if ((si->psi.soi_kind == SOCKINFO_TCP) && (TcpStXn || TcpStIn)) {
+ int tsnx = (int)si->psi.soi_proto.pri_tcp.tcpsi_state
+ + TcpStOff;
+
+ if ((tsnx >= 0) && (tsnx < TcpNstates)) {
+ if (TcpStXn) {
+ if (TcpStX[tsnx]) {
+ Lf->sf |= SELEXCLF;
+ return;
+ }
+ }
+ if (TcpStIn) {
+ if (TcpStI[tsnx])
+ TcpStI[tsnx] = 2;
+ else {
+ Lf->sf |= SELEXCLF;
+ return;
+ }
+ }
+ }
+ }
+ /*
+ * Process an Internet domain socket.
+ */
+ if (Fnet) {
+ if (!FnetTy
+ || ((FnetTy == 4) && (fam == AF_INET))
+ || ((FnetTy == 6) && (fam == AF_INET6))
+ )
+ Lf->sf |= SELNET;
+ }
+ printiproto(si->psi.soi_protocol);
+ if ((si->psi.soi_kind == SOCKINFO_TCP)
+ && si->psi.soi_proto.pri_tcp.tcpsi_tp)
+ {
+ enter_dev_ch(print_kptr((KA_T)si->psi.soi_proto.pri_tcp.tcpsi_tp,
+ (char *)NULL, 0));
+ } else
+ enter_dev_ch(print_kptr((KA_T)si->psi.soi_pcb, (char *)NULL, 0));
+ if (fam == AF_INET) {
+
+ /*
+ * Enter IPv4 address information.
+ */
+ if (si->psi.soi_kind == SOCKINFO_TCP) {
+
+ /*
+ * Enter information for a TCP socket.
+ */
+ la = (unsigned char *)&si->psi.soi_proto.pri_tcp.tcpsi_ini.insi_laddr.ina_46.i46a_addr4;
+ lp = (int)ntohs(si->psi.soi_proto.pri_tcp.tcpsi_ini.insi_lport);
+ fa = (unsigned char *)&si->psi.soi_proto.pri_tcp.tcpsi_ini.insi_faddr.ina_46.i46a_addr4;
+ fp = (int)ntohs(si->psi.soi_proto.pri_tcp.tcpsi_ini.insi_fport);
+ } else {
+
+ /*
+ * Enter information for a non-TCP socket.
+ */
+ la = (unsigned char *)&si->psi.soi_proto.pri_in.insi_laddr.ina_46.i46a_addr4;
+ lp = (int)ntohs(si->psi.soi_proto.pri_in.insi_lport);
+ fa = (unsigned char *)&si->psi.soi_proto.pri_in.insi_faddr.ina_46.i46a_addr4;
+ fp = (int)ntohs(si->psi.soi_proto.pri_in.insi_fport);
+ }
+ if ((fa && (*fa == INADDR_ANY)) && !fp) {
+ fa = (unsigned char *)NULL;
+ fp = 0;
+ }
+ } else {
+
+ /*
+ * Enter IPv6 address information
+ */
+ int v4mapped = 0;
+
+ if (si->psi.soi_kind == SOCKINFO_TCP)
+ {
+
+ /*
+ * Enter TCP socket information.
+ */
+ la = (unsigned char *)&si->psi.soi_proto.pri_tcp.tcpsi_ini.insi_laddr.ina_6;
+ lp = (int)ntohs(si->psi.soi_proto.pri_tcp.tcpsi_ini.insi_lport);
+ fa = (unsigned char *)&si->psi.soi_proto.pri_tcp.tcpsi_ini.insi_faddr.ina_6;
+ fp = (int)ntohs(si->psi.soi_proto.pri_tcp.tcpsi_ini.insi_fport);
+ if ((si->psi.soi_proto.pri_tcp.tcpsi_ini.insi_vflag & INI_IPV4) != 0)
+ v4mapped = 1;
+ } else {
+
+ /*
+ * Enter non-TCP socket information.
+ */
+ la = (unsigned char *)&si->psi.soi_proto.pri_in.insi_laddr.ina_6;
+ lp = (int)ntohs(si->psi.soi_proto.pri_in.insi_lport);
+ fa = (unsigned char *)&si->psi.soi_proto.pri_in.insi_faddr.ina_6;
+ fp = (int)ntohs(si->psi.soi_proto.pri_in.insi_fport);
+ if ((si->psi.soi_proto.pri_in.insi_vflag & INI_IPV4) != 0)
+ v4mapped = 1;
+ }
+ if (IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *)fa) && !fp) {
+ fa = (unsigned char *)NULL;
+ fp = 0;
+ }
+ if (v4mapped) {
+
+ /*
+ * Adjust IPv4 addresses mapped in IPv6 addresses.
+ */
+ fam = AF_INET;
+ if (la)
+ la = (unsigned char *)IPv6_2_IPv4(la);
+ if (fa)
+ fa = (unsigned char *)IPv6_2_IPv4(fa);
+ }
+ }
+ /*
+ * Enter local and remote addresses by address family.
+ */
+ if (fa || la)
+ (void) ent_inaddr(la, lp, fa, fp, fam);
+ if (si->psi.soi_kind == SOCKINFO_TCP) {
+
+ /*
+ * Enter a TCP socket definition and its state.
+ */
+ Lf->lts.type = 0;
+ Lf->lts.state.i = (int)si->psi.soi_proto.pri_tcp.tcpsi_state;
+ /*
+ * Enter TCP options.
+ */
+
+#if defined(HASSOOPT)
+ Lf->lts.kai = (unsigned int)si->psi.soi_proto.pri_tcp.tcpsi_timer[TCPT_KEEP];
+#endif /* defined(HASSOOPT) */
+
+#if defined(HASTCPOPT)
+ Lf->lts.mss = (unsigned long)si->psi.soi_proto.pri_tcp.tcpsi_mss;
+ Lf->lts.msss = (unsigned char)1;
+ Lf->lts.topt = (unsigned int)si->psi.soi_proto.pri_tcp.tcpsi_flags;
+#endif /* defined(HASTCPOPT) */
+
+ }
+ break;
+ case AF_UNIX:
+
+ /*
+ * Process a UNIX domain socket.
+ */
+ (void) snpf(Lf->type, sizeof(Lf->type), "unix");
+ if (si->psi.soi_kind != SOCKINFO_UN)
+ break;
+ if (Funix)
+ Lf->sf |= SELUNX;
+ enter_dev_ch(print_kptr((KA_T)si->psi.soi_pcb, (char *)NULL, 0));
+ /*
+ * Enter information on a UNIX domain socket that has no address bound
+ * to it, although it may be connected to another UNIX domain socket
+ * as a pipe.
+ */
+ if (si->psi.soi_proto.pri_un.unsi_addr.ua_sun.sun_family != AF_UNIX)
+ {
+ if (si->psi.soi_proto.pri_un.unsi_addr.ua_sun.sun_family
+ == AF_UNSPEC)
+ {
+ if (si->psi.soi_proto.pri_un.unsi_conn_pcb) {
+ (void) snpf(Namech, Namechl, "->%s",
+ print_kptr((KA_T)si->psi.soi_proto.pri_un.unsi_conn_pcb, (char *)NULL, 0));
+ } else
+ (void) snpf(Namech, Namechl, "->(none)");
+ } else
+ (void) snpf(Namech, Namechl, "unknown sun_family (%d)",
+ si->psi.soi_proto.pri_un.unsi_addr.ua_sun.sun_family);
+ break;
+ }
+ if (si->psi.soi_proto.pri_un.unsi_addr.ua_sun.sun_path[0]) {
+ unl = si->psi.soi_proto.pri_un.unsi_addr.ua_sun.sun_len - offsetof(struct sockaddr_un, sun_path);
+ if ((unl < 0) || (unl >= sizeof(si->psi.soi_proto.pri_un.unsi_addr.ua_sun.sun_path)))
+ unl = sizeof(si->psi.soi_proto.pri_un.unsi_addr.ua_sun.sun_path) - 1;
+ si->psi.soi_proto.pri_un.unsi_addr.ua_sun.sun_path[unl] = '\0';
+ if (si->psi.soi_proto.pri_un.unsi_addr.ua_sun.sun_path[0]
+ && Sfile
+ && is_file_named(si->psi.soi_proto.pri_un.unsi_addr.ua_sun.sun_path, 0))
+ Lf->sf |= SELNM;
+ if (si->psi.soi_proto.pri_un.unsi_addr.ua_sun.sun_path[0]
+ && !Namech[0])
+ (void) snpf(Namech, Namechl, "%s", si->psi.soi_proto.pri_un.unsi_addr.ua_sun.sun_path);
+ } else
+ (void) snpf(Namech, Namechl, "no address");
+ break;
+ case AF_ROUTE:
+
+ /*
+ * Process a ROUTE domain socket.
+ */
+ (void) snpf(Lf->type, sizeof(Lf->type), "rte");
+ if (!Fsize)
+ Lf->off_def = 1;
+ break;
+ case AF_NDRV:
+
+ /*
+ * Process an NDRV domain socket.
+ */
+ (void) snpf(Lf->type, sizeof(Lf->type), "ndrv");
+ if (si->psi.soi_kind != SOCKINFO_NDRV)
+ break;
+ enter_dev_ch(print_kptr((KA_T)si->psi.soi_pcb, (char *)NULL, 0));
+ si->psi.soi_proto.pri_ndrv.ndrvsi_if_name[sizeof(si->psi.soi_proto.pri_ndrv.ndrvsi_if_name) - 1] = '\0';
+ (void) snpf(Namech, Namechl, "-> %s%d",
+ si->psi.soi_proto.pri_ndrv.ndrvsi_if_name,
+ si->psi.soi_proto.pri_ndrv.ndrvsi_if_unit);
+ break;
+ case pseudo_AF_KEY:
+
+ /*
+ * Process an [internal] key-management function socket.
+ */
+ (void) snpf(Lf->type, sizeof(Lf->type), "key");
+ enter_dev_ch(print_kptr((KA_T)si->psi.soi_pcb, (char *)NULL, 0));
+ break;
+ case AF_SYSTEM:
+
+ /*
+ * Process a SYSTEM domain socket.
+ */
+ (void) snpf(Lf->type, sizeof(Lf->type), "systm");
+ if (si->psi.soi_kind != SOCKINFO_KERN_EVENT)
+ break;
+ enter_dev_ch(print_kptr((KA_T)si->psi.soi_pcb, (char *)NULL, 0));
+ (void) snpf(Namech, Namechl, "[%x:%x:%x]",
+ si->psi.soi_proto.pri_kern_event.kesi_vendor_code_filter,
+ si->psi.soi_proto.pri_kern_event.kesi_class_filter,
+ si->psi.soi_proto.pri_kern_event.kesi_subclass_filter);
+ break;
+ case AF_PPP:
+
+ /*
+ * Process a PPP domain socket.
+ */
+ (void) snpf(Lf->type, sizeof(Lf->type), "ppp");
+ enter_dev_ch(print_kptr((KA_T)si->psi.soi_pcb, (char *)NULL, 0));
+ break;
+ default:
+ printunkaf(fam, 1);
+ }
+/*
+ * If there are NAME column characters, enter them.
+ */
+ if (Namech[0])
+ enter_nm(Namech);
+}
+
+
+void
+process_socket(pid, fd)
+ int pid; /* PID */
+ int32_t fd; /* FD */
+{
+ int nb;
+ struct socket_fdinfo si;
+/*
+ * Get socket information.
+ */
+ nb = proc_pidfdinfo(pid, fd, PROC_PIDFDSOCKETINFO, &si, sizeof(si));
+ if (nb <= 0) {
+ (void) err2nm("socket");
+ return;
+ } else if (nb < sizeof(si)) {
+ (void) fprintf(stderr,
+ "%s: PID %d, FD %d: proc_pidfdinfo(PROC_PIDFDSOCKETINFO);\n",
+ Pn, pid, fd);
+ (void) fprintf(stderr,
+ " too few bytes; expected %ld, got %d\n",
+ sizeof(si), nb);
+ Exit(1);
+ }
+
+ process_socket_common(&si);
+}
+
+
+#ifdef PROC_PIDLISTFILEPORTS
+void
+process_fileport_socket(pid, fp)
+ int pid; /* PID */
+ uint32_t fp; /* FILEPORT */
+{
+ int nb;
+ struct socket_fdinfo si;
+/*
+ * Get socket information.
+ */
+ nb = proc_pidfileportinfo(pid, fp, PROC_PIDFILEPORTSOCKETINFO, &si, sizeof(si));
+ if (nb <= 0) {
+ (void) err2nm("socket");
+ return;
+ } else if (nb < sizeof(si)) {
+ (void) fprintf(stderr,
+ "%s: PID %d, FILEPORT %u: proc_pidfileportinfo(PROC_PIDFILEPORTSOCKETINFO);\n",
+ Pn, pid, fp);
+ (void) fprintf(stderr,
+ " too few bytes; expected %ld, got %d\n",
+ sizeof(si), nb);
+ Exit(1);
+ }
+
+ process_socket_common(&si);
+}
+#endif /* PROC_PIDLISTFILEPORTS */
diff --git a/dialects/darwin/libproc/dstore.c b/dialects/darwin/libproc/dstore.c
new file mode 100644
index 0000000..b538881
--- /dev/null
+++ b/dialects/darwin/libproc/dstore.c
@@ -0,0 +1,91 @@
+/*
+ * dstore.c -- Darwin global storage for libproc-based lsof
+ */
+
+
+/*
+ * Portions Copyright 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * Copyright 2005 Purdue Research Foundation, West Lafayette, Indiana
+ * 47907. All rights reserved.
+ *
+ * Written by Allan Nathanson, Apple Computer, Inc., and Victor A.
+ * Abell, Purdue University.
+ *
+ * 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 Apple Computer, Inc. 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, Apple
+ * Computer, Inc. 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 2005 Apple Computer, Inc. and Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dstore.c,v 1.4 2008/10/21 16:15:16 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+#if defined(HASFSTRUCT)
+/*
+ * Pff_tab[] - table for printing file flags
+ */
+
+struct pff_tab Pff_tab[] = {
+ { (long)FREAD, FF_READ },
+ { (long)FWRITE, FF_WRITE },
+ { (long)FNONBLOCK, FF_NBLOCK },
+ { (long)FNDELAY, FF_NDELAY },
+ { (long)FAPPEND, FF_APPEND },
+ { (long)FASYNC, FF_ASYNC },
+ { (long)FFSYNC, FF_FSYNC },
+
+# if defined(FHASLOCK)
+ { (long)FHASLOCK, FF_HASLOCK },
+# endif /* defined(FHASLOCK) */
+
+ { (long)O_NOCTTY, FF_NOCTTY },
+ { (long)O_EVTONLY, FF_EVTONLY },
+ { (long)0, NULL }
+};
+
+
+/*
+ * Pof_tab[] - table for print process open file flags
+ */
+
+struct pff_tab Pof_tab[] = {
+
+# if defined(UF_CLOSING)
+ { (long)UF_CLOSING, POF_CLOSING },
+# endif /* defined(UF_CLOSING) */
+
+# if defined(UF_EXCLOSE)
+ { (long)UF_EXCLOSE, POF_CLOEXEC },
+# endif /* defined(UF_EXCLOSE) */
+
+# if defined(UF_RESERVED)
+ { (long)UF_RESERVED, POF_RESERVED },
+# endif /* defined(UF_RESERVED) */
+
+ { (long)0, NULL }
+};
+#endif /* defined(HASFSTRUCT) */
diff --git a/dialects/darwin/libproc/machine.h b/dialects/darwin/libproc/machine.h
new file mode 100644
index 0000000..2bfa213
--- /dev/null
+++ b/dialects/darwin/libproc/machine.h
@@ -0,0 +1,629 @@
+/*
+ * machine.h -- Darwin definitions for libproc-based lsof
+ */
+
+
+/*
+ * Portions Copyright 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * Copyright 2005 Purdue Research Foundation, West Lafayette, Indiana
+ * 47907. All rights reserved.
+ *
+ * Written by Allan Nathanson, Apple Computer, Inc., and Victor A.
+ * Abell, Purdue University.
+ *
+ * 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 Apple Computer, Inc. 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, Apple
+ * Computer, Inc. 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.
+ */
+
+
+/*
+ * $Id: machine.h,v 1.10 2013/01/02 17:03:05 abe Exp $
+ */
+
+
+#if !defined(LSOF_MACHINE_H)
+#define LSOF_MACHINE_H 1
+
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+# if defined(NEEDS_MACH_PORT_T)
+# include <device/device_types.h>
+# endif /* NEED_MACH_PORT_T */
+
+#include "/usr/include/string.h"
+
+
+/*
+ * CAN_USE_CLNT_CREATE is defined for those dialects where RPC clnt_create()
+ * can be used to obtain a CLIENT handle in lieu of clnttcp_create().
+ */
+
+#define CAN_USE_CLNT_CREATE 1
+
+
+/*
+ * DEVDEV_PATH defines the path to the directory that contains device
+ * nodes.
+ */
+
+#define DEVDEV_PATH "/dev"
+
+
+/*
+ * GET_MAX_FD is defined for those dialects that provide a function other than
+ * getdtablesize() to obtain the maximum file descriptor number plus one.
+ */
+
+/* #define GET_MAX_FD ? */
+
+
+/*
+ * HASAOPT is defined for those dialects that have AFS support; it specifies
+ * that the default path to an alternate AFS kernel name list file may be
+ * supplied with the -A <path> option.
+ */
+
+/* #define HASAOPT 1 */
+
+
+/*
+ * HASBLKDEV is defined for those dialects that want block device information
+ * recorded in BDevtp[].
+ */
+
+#define HASBLKDEV 1
+
+
+/*
+ * HASDCACHE is defined for those dialects that support a device cache
+ * file.
+ *
+ * HASENVDC defined the name of an environment variable that contains the
+ * device cache file path. The HASENVDC environment variable is ignored when
+ * the lsof process is setuid(root) or its real UID is 0.
+ *
+ * HASPERSDC defines the format for the last component of a personal device
+ * cache file path. The first will be the home directory of the real UID that
+ * executes lsof.
+ *
+ * HASPERSDCPATH defines the environment variable whose value is the middle
+ * component of the personal device cache file path. The middle component
+ * follows the home directory and precedes the results of applying HASPERSDC.
+ * The HASPERSDCPATH environment variable is ignored when the lsof process is
+ * setuid(root) or its real UID is 0.
+ *
+ * HASSYSDC defines a public device cache file path. When it's defined, it's
+ * used as the path from which to read the device cache.
+ *
+ * Consult the 00DCACHE and 00FAQ files of the lsof distribution for more
+ * information on device cache file path construction.
+ */
+
+/* #define HASDCACHE 1 */
+/* #define HASENVDC "LSOFDEVCACHE" */
+/* #define HASPERSDC "%h/%p.lsof_%L" */
+/* #define HASPERSDCPATH "LSOFPERSDCPATH" */
+/* #define HASSYSDC "/your/choice/of/path" */
+
+
+/*
+ * HASCDRNODE is defined for those dialects that have CD-ROM nodes.
+ */
+
+/* #define HASCDRNODE 1 */
+
+
+/*
+ * HASFIFONODE is defined for those dialects that have FIFO nodes.
+ */
+
+/* #define HASFIFONODE 1 */
+
+
+/*
+ * HASFSINO is defined for those dialects that have the file system
+ * inode element, fs_ino, in the lfile structure definition in lsof.h.
+ */
+
+#define HASFSINO 1
+
+
+/*
+ * HASFSTRUCT is defined if the dialect has a file structure.
+ *
+ * FSV_DEFAULT defines the default set of file structure values to list.
+ * It defaults to zero (0), but may be made up of a combination of the
+ * FSV_* symbols from lsof.h.
+ *
+ * HASNOFSADDR -- has no file structure address
+ * HASNOFSFLAGS -- has no file structure flags
+ * HASNOFSCOUNT -- has no file structure count
+ * HASNOFSNADDR -- has no file structure node address
+ */
+
+#define HASFSTRUCT 1
+/* #define FSV_DEFAULT FSV_? | FSV_? | FSV_? */
+#define HASNOFSADDR 1 /* has no file structure address */
+/* #define HASNOFSFLAGS 1 has no file structure flags */
+/* #define HASNOFSCOUNT 1 has no file structure count */
+#define HASNOFSNADDR 1 /* has no file structure node address */
+
+
+/*
+ * HASGNODE is defined for those dialects that have gnodes.
+ */
+
+/* #define HASGNODE 1 */
+
+
+/*
+ * HASHSNODE is defined for those dialects that have High Sierra nodes.
+ */
+
+/* #define HASHSNODE 1 */
+
+
+/*
+ * HASINODE is defined for those dialects that have inodes and wish to
+ * use readinode() from node.c.
+ */
+
+/* #define HASINODE 1 */
+
+
+/*
+ * HASINTSIGNAL is defined for those dialects whose signal function returns
+ * an int.
+ */
+
+/* #define HASINTSIGNAL 1 */
+
+
+/*
+ * HASKERNIDCK is defined for those dialects that support the comparison of
+ * the build to running kernel identity.
+ */
+
+#define HASKERNIDCK 1
+
+
+/*
+ * HASKOPT is defined for those dialects that support the -k option of
+ * reading the kernel's name list from an optional file.
+ */
+
+/* #define HASKOPT 1 */
+
+
+/*
+ * HASLFILEADD is defined for those dialects that need additional elements
+ * in struct lfile. The HASLFILEADD definition is a macro that defines
+ * them. If any of the additional elements need to be preset in the
+ * alloc_lfile() function of proc.c, the SETLFILEADD macro may be defined
+ * to do that.
+ *
+ * If any additional elements need to be cleared in alloc_lfile() or in the
+ * free_proc() function of proc.c, the CLRLFILEADD macro may be defined to
+ * do that. Note that CLRLFILEADD takes one argument, the pointer to the
+ * lfile struct. The CLRLFILEADD macro is expected to expand to statements
+ * that are complete -- i.e., have terminating semi-colons -- so the macro is
+ * called without a terminating semicolon by proc.c.
+ *
+ * The HASXOPT definition may be used to select the conditions under which
+ * private lfile elements are used.
+ */
+
+#define HASLFILEADD char *V_path; \
+ mach_port_t fileport;
+#define CLRLFILEADD(lf) if (lf->V_path) { \
+ (void) free((FREE_P *)lf->V_path); \
+ lf->V_path = (char *)NULL; \
+ } \
+ lf->fileport = MACH_PORT_NULL;
+#define SETLFILEADD Lf->V_path = (char *)NULL; \
+ Lf->fileport = MACH_PORT_NULL;
+
+
+/*
+ * HASMNTSTAT indicates the dialect supports the mount stat(2) result option
+ * in its l_vfs and mounts structures.
+ */
+
+/* #define HASMNTSTAT 1 */
+
+
+/*
+ * HASMNTSUP is defined for those dialects that support the mount supplement
+ * option.
+ */
+
+/* #define HASMNTSUP 1 */
+
+
+/*
+ * HASMOPT is defined for those dialects that support the reading of
+ * kernel memory from an alternate file.
+ */
+
+/* #define HASMOPT 1 */
+
+
+/*
+ * HASNCACHE is defined for those dialects that have a kernel name cache
+ * that lsof can search. A value of 1 directs printname() to prefix the
+ * cache value with the file system directory name; 2, avoid the prefix.
+ *
+ * NCACHELDPFX is a set of C commands to execute before calling ncache_load().
+ *
+ * NCACHELDSFX is a set of C commands to execute after calling ncache_load().
+ */
+
+/* #define HASNCACHE 1 */
+/* #define NCACHELDPFX ??? */
+/* #define NCACHELDSFX ??? */
+
+
+/*
+ * HASNLIST is defined for those dialects that use nlist() to acccess
+ * kernel symbols.
+ */
+
+/* #define HASNLIST 1 */
+
+
+/*
+ * HASPIPEFN is defined for those dialects that have a special function to
+ * process DTYPE_PIPE file structure entries. Its value is the name of the
+ * function.
+ *
+ * NOTE: don't forget to define a prototype for this function in dproto.h.
+ */
+
+/* #define HASPIPEFN process_pipe? */
+
+
+/*
+ * HASPIPENODE is defined for those dialects that have pipe nodes.
+ */
+
+/* #define HASPIPENODE 1 */
+
+
+/*
+ * HASPMAPENABLED is defined when the reporting of portmapper registration
+ * info is enabled by default.
+ */
+
+/* #define HASPMAPENABLED 1 */
+
+
+/*
+ * HASPPID is defined for those dialects that support identification of
+ * the parent process IDentifier (PPID) of a process.
+ */
+
+#define HASPPID 1
+
+
+/*
+ * HASPRINTDEV, HASPRINTINO, HASPRINTNM, HASPRINTOFF, and HASPRINTSZ
+ * define private dialect-specific functions for printing DEVice numbers,
+ * INOde numbers, NaMes, file OFFsets, and file SiZes. The functions are
+ * called from print_file().
+ */
+
+/* #define HASPRINTDEV print_dev */
+/* #define HASPRINTINO print_ino? */
+#define HASPRINTNM print_nm
+/* #define HASPRINTOFF print_off? */
+/* #define HASPRINTSZ print_sz? */
+
+
+/*
+ * HASPRIVFILETYPE and PRIVFILETYPE are defined for dialects that have a
+ * file structure type that isn't defined by a DTYPE_* symbol. They are
+ * used in lib/prfp.c to select the type's processing.
+ *
+ * PRIVFILETYPE is the definition of the f_type value in the file struct.
+ *
+ * HASPRIVFILETYPE is the name of the processing function.
+ */
+
+/* #define HASPRIVFILETYPE process_shmf? */
+/* #define PRIVFILETYPE ?? */
+
+
+/*
+ * HASPRIVNMCACHE is defined for dialects that have a private method for
+ * printing cached NAME column values for some files. HASPRIVNAMECACHE
+ * is defined to be the name of the function.
+ *
+ * The function takes one argument, a struct lfile pointer to the file, and
+ * returns non-zero if it prints a name to stdout.
+ */
+
+#define HASPRIVNMCACHE print_v_path
+
+
+/*
+ * HASPRIVPRIPP is defined for dialects that have a private function for
+ * printing IP protocol names. When HASPRIVPRIPP isn't defined, the
+ * IP protocol name printing function defaults to printiprto().
+ */
+
+/* #define HASPRIVPRIPP 1 */
+
+
+/*
+ * HASPROCFS is defined for those dialects that have a proc file system --
+ * usually /proc and usually in SYSV4 derivatives.
+ *
+ * HASFSTYPE is defined as 1 for those systems that have a file system type
+ * string, st_fstype, in the stat() buffer; 2, for those systems that have a
+ * file system type integer in the stat() buffer, named MOUNTS_STAT_FSTYPE;
+ * 0, for systems whose stat(2) structure has no file system type member. The
+ * additional symbols MOUNTS_FSTYPE, RMNT_FSTYPE, and RMNT_STAT_FSTYPE may be
+ * defined in dlsof.h to direct how the readmnt() function in lib/rmnt.c
+ * preserves these stat(2) and getmntent(3) buffer values in the local mounts
+ * structure.
+ *
+ * The defined value is the string that names the file system type.
+ *
+ * The HASPROCFS definition usually must be accompanied by the HASFSTYPE
+ * definition and the providing of an fstype element in the local mounts
+ * structure (defined in dlsof.h).
+ *
+ * The HASPROCFS definition may be accompanied by the HASPINODEN definition.
+ * HASPINODEN specifies that searching for files in HASPROCFS is to be done
+ * by inode number.
+ */
+
+/* #define HASPROCFS "proc?" */
+/* #define HASFSTYPE 1 */
+/* #define HASPINODEN 1 */
+
+
+/*
+ * HASRNODE is defined for those dialects that have rnodes.
+ */
+
+/* #define HASRNODE 1 */
+
+
+/*
+ * Define HASSECURITY to restrict the listing of all open files to the
+ * root user. When HASSECURITY is defined, the non-root user may list
+ * only files whose processes have the same user ID as the real user ID
+ * (the one that its user logged on with) of the lsof process.
+ */
+
+/* #define HASSECURITY 1 */
+
+
+/*
+ * If HASSECURITY is defined, define HASNOSOCKSECURITY to allow users
+ * restricted by HASSECURITY to list any open socket files, provide their
+ * listing is selected by the "-i" option.
+ */
+
+/* #define HASNOSOCKSECURITY 1 */
+
+
+/*
+ * HASSETLOCALE is defined for those dialects that have <locale.h> and
+ * setlocale().
+ *
+ * If the dialect also has wide character support for language locales,
+ * HASWIDECHAR activates lsof's wide character support and WIDECHARINCL
+ * defines the header file (if any) that must be #include'd to use the
+ * mblen() and mbtowc() functions.
+ */
+
+#define HASSETLOCALE 1
+#define HASWIDECHAR 1
+/* #define WIDECHARINCL <wchar.h> */
+
+
+/*
+ * HASSNODE is defined for those dialects that have snodes.
+ */
+
+/* #define HASSNODE 1 */
+
+
+/*
+ * HASTASKS is defined for those dialects that have task reporting support.
+ */
+
+/* #define HASTASKS 1 */
+
+
+/*
+ * HASSOOPT, HASSOSTATE and HASTCPOPT define the availability of information
+ * on socket options (SO_* symbols), socket states (SS_* symbols) and TCP
+ * options.
+ */
+
+#define HASSOOPT 1 /* has socket option information */
+#define HASSOSTATE 1 /* has socket state information */
+#define HASTCPOPT 1 /* has TCP options or flags */
+
+
+/*
+ * Define HASSPECDEVD to be the name of a function that handles the results
+ * of a successful stat(2) of a file name argument.
+ *
+ * For example, HASSPECDEVD() for Darwin makes sure that st_dev is set to
+ * what stat("/dev") returns -- i.e., what's in DevDev.
+ *
+ * The function takes two arguments:
+ *
+ * 1: pointer to the full path name of file
+ * 2: pointer to the stat(2) result
+ *
+ * The function returns void.
+ */
+
+#define HASSPECDEVD process_dev_stat
+
+
+/*
+ * HASSTREAMS is defined for those dialects that support streams.
+ */
+
+/* #define HASSTREAMS 1 */
+
+
+/*
+ * HASTCPTPIQ is defined for dialects where it is possible to report the
+ * TCP/TPI Recv-Q and Send-Q values produced by netstat.
+ */
+
+#define HASTCPTPIQ 1
+
+
+/*
+ * HASTCPTPIW is defined for dialects where it is possible to report the
+ * TCP/TPI send and receive window sizes produced by netstat.
+ */
+
+/* #define HASTCPTPIW 1 */
+
+
+/*
+ * HASTCPUDPSTATE is defined for dialects that have TCP and UDP state
+ * support -- i.e., for the "-stcp|udp:state" option and its associated
+ * speed improvements.
+ */
+
+#define HASTCPUDPSTATE 1
+
+
+/*
+ * HASTMPNODE is defined for those dialects that have tmpnodes.
+ */
+
+/* #define HASTMPNODE 1 */
+
+
+/*
+ * HASVNODE is defined for those dialects that use the Sun virtual file system
+ * node, the vnode. BSD derivatives usually do; System V derivatives prior to
+ * R4 usually don't.
+ */
+
+/* #define HASVNODE 1 */
+
+
+/*
+ * HASXOPT is defined for those dialects that have an X option. It
+ * defines the text for the usage display. HASXOPT_VALUE defines the
+ * option's default binary value -- 0 or 1.
+ */
+
+/* #define HASXOPT "help text for X option" */
+/* #define HASXOPT_VALUE 1 */
+
+
+/*
+ * INODETYPE and INODEPSPEC define the internal node number type and its
+ * printf specification modifier. These need not be defined and lsof.h
+ * can be allowed to define defaults.
+ *
+ * These are defined here, because they must be used in dlsof.h.
+ */
+
+#define INODETYPE unsigned long long
+ /* inode number internal storage type */
+#define INODEPSPEC "ll" /* INODETYPE printf specification
+ * modifier */
+
+
+/*
+ * UID_ARG defines the size of a User ID number when it is passed
+ * as a function argument.
+ */
+
+#define UID_ARG int
+
+
+/*
+ * Each USE_LIB_<function_name> is defined for dialects that use the
+ * <function_name> in the lsof library.
+ *
+ * Note: other definitions and operations may be required to condition the
+ * library function source code. They may be found in the dialect dlsof.h
+ * header files.
+ */
+
+#define USE_LIB_CKKV 1 /* ckkv.c */
+/* #define USE_LIB_COMPLETEVFS 1 cvfs.c */
+#define USE_LIB_FIND_CH_INO 1 /* fino.c */
+#define USE_LIB_IS_FILE_NAMED 1 /* isfn.c */
+#define USE_LIB_LKUPDEV 1 /* lkud.c */
+/* #define USE_LIB_PRINTDEVNAME 1 pdvn.c */
+/* #define USE_LIB_PROCESS_FILE 1 prfp.c */
+#define USE_LIB_PRINT_TCPTPI 1 /* ptti.c */
+/* #define USE_LIB_READDEV 1 rdev.c */
+/* #define USE_LIB_READMNT 1 rmnt.c */
+/* #define USE_LIB_REGEX 1 regex.c */
+/* #define USE_LIB_RNAM 1 rnam.c */
+/* #define USE_LIB_RNCH 1 rnch.c */
+/* #define USE_LIB_RNMH 1 rnmh.c */
+/* #define USE_LIB_SNPF 1 snpf.c */
+#define snpf snprintf /* use the system's snprintf() */
+
+
+/*
+ * WARNDEVACCESS is defined for those dialects that should issue a warning
+ * when lsof can't access /dev (or /device) or one of its sub-directories.
+ * The warning can be inhibited by the lsof caller with the -w option.
+ */
+
+/* #define WARNDEVACCESS 1 */
+
+
+/*
+ * WARNINGSTATE is defined for those dialects that want to suppress all lsof
+ * warning messages.
+ */
+
+/* #define WARNINGSTATE 1 warnings are enabled by default */
+
+
+/*
+ * WILLDROPGID is defined for those dialects whose lsof executable runs
+ * setgid(not_real_GID) and whose setgid power can be relinquished after
+ * the dialect's initialize() function has been executed.
+ */
+
+#define WILLDROPGID 1
+
+
+/*
+ * zeromem is a macro that uses bzero or memset.
+ */
+
+#define zeromem(a, l) memset(a, 0, l)
+
+#endif /* !defined(LSOF_MACHINE_H) */
diff --git a/dialects/du/Makefile b/dialects/du/Makefile
new file mode 100644
index 0000000..3da0c04
--- /dev/null
+++ b/dialects/du/Makefile
@@ -0,0 +1,156 @@
+
+# DU Makefile
+#
+# $Id: Makefile,v 1.13 2008/04/15 13:29:11 abe Exp $
+
+PROG= lsof
+
+BIN= ${DESTDIR}
+
+DOC= ${DESTDIR}
+
+I=/usr/include
+S=/usr/include/sys
+L=/usr/include/local
+P=
+
+CDEF=
+CDEFS= ${CDEF} ${CFGF}
+INCL= ${DINC}
+CFLAGS= ${CDEFS} ${INCL} ${DEBUG}
+
+GRP=
+
+HDR= lsof.h lsof_fields.h dlsof.h machine.h proto.h dproto.h
+
+SRC= ddev.c dfile.c dmnt.c dnode.c dproc.c dsock.c dstore.c \
+ arg.c main.c misc.c node.c print.c proc.c store.c usage.c \
+ util.c
+
+OBJ= ddev.o dfile.o dmnt.o dnode.o dproc.o dsock.o dstore.o \
+ arg.o main.o misc.o node.o print.o proc.o store.o usage.o \
+ util.o
+
+MAN= lsof.8
+
+OTHER=
+
+SHELL= /bin/sh
+
+SOURCE= Makefile ${OTHER} ${MAN} ${HDR} ${SRC}
+
+all: ${PROG}
+
+${PROG}:${LIB} ${P} ${OBJ}
+ ${CC} -o $@ ${CFLAGS} ${OBJ} ${CFGL}
+
+clean: FRC
+ rm -f Makefile.bak ${PROG} a.out core errs lint.out tags *.o version.h
+ rm -f machine.h.old new_machine.h
+ (cd lib; ${MAKE} -f Makefile.skel clean)
+
+install: all FRC
+ @echo ''
+ @echo 'Please write your own install rule. Lsof should be installed'
+ @echo 'setgid to the group that can can read /dev/kmem. Normally'
+ @echo 'that is the mem group. Your install rule actions might look'
+ @echo 'something like this:'
+ @echo ''
+ @echo ' installbsd -c -s -m 2755 -g $${GRP} $${PROG} $${BIN}/$${PROG}'
+ @echo ' installbsd -c -m 444 $${MAN} $${DOC}/$${MAN}'
+ @echo ''
+ @echo 'You will have to complete the skeletons for the BIN, DOC, and'
+ @echo 'GRP strings given at the beginning of this Makefile, e.g.,'
+ @echo ''
+ @echo ' BIN= $${DESTDIR}/usr/local/etc'
+ @echo ' DOC= $${DESTDIR}/usr/man/man8'
+ @echo ' GRP= mem'
+ @echo ''
+
+${LIB}: FRC
+ (cd lib; ${MAKE} DEBUG="${DEBUG}" CFGF="${CFGF}")
+
+version.h: FRC
+ @echo Constructing version.h
+ @rm -f version.h
+ @echo '#define LSOF_BLDCMT "${LSOF_BLDCMT}"' > version.h;
+ @echo '#define LSOF_CC "${CC}"' >> version.h
+ @echo '#define LSOF_CCV "${CCV}"' >> version.h
+ @echo '#define LSOF_CCDATE "'`date`'"' >> version.h
+ @echo '#define LSOF_CCFLAGS "'`echo ${CFLAGS} | sed 's/\\\\(/\\(/g' | sed 's/\\\\)/\\)/g' | sed 's/"/\\\\"/g'`'"' >> version.h
+ @if [ "X${LSOF_HOST}" = "X" ]; then \
+ echo '#define LSOF_HOST "'`uname -n`'"' >> version.h; \
+ else \
+ if [ "${LSOF_HOST}" = "none" ]; then \
+ echo '#define LSOF_HOST ""' >> version.h; \
+ else \
+ echo '#define LSOF_HOST "${LSOF_HOST}"' >> version.h; \
+ fi \
+ fi
+ @echo '#define LSOF_LDFLAGS "${CFGL}"' >> version.h
+ @if [ "X${LSOF_LOGNAME}" = "X" ]; then \
+ echo '#define LSOF_LOGNAME "${LOGNAME}"' >> version.h; \
+ else \
+ if [ "${LSOF_LOGNAME}" = "none" ]; then \
+ echo '#define LSOF_LOGNAME ""' >> version.h; \
+ else \
+ echo '#define LSOF_LOGNAME "${LSOF_LOGNAME}"' >> version.h; \
+ fi; \
+ fi
+ @if [ "X${LSOF_SYSINFO}" = "X" ]; then \
+ echo '#define LSOF_SYSINFO "'`uname -a`'"' >> version.h; \
+ else \
+ if [ "${LSOF_SYSINFO}" = "none" ]; then \
+ echo '#define LSOF_SYSINFO ""' >> version.h; \
+ else \
+ echo '#define LSOF_SYSINFO "${LSOF_SYSINFO}"' >> version.h; \
+ fi \
+ fi
+ @if [ "X${LSOF_USER}" = "X" ]; then \
+ echo '#define LSOF_USER "${USER}"' >> version.h; \
+ else \
+ if [ "${LSOF_USER}" = "none" ]; then \
+ echo '#define LSOF_USER ""' >> version.h; \
+ else \
+ echo '#define LSOF_USER "${LSOF_USER}"' >> version.h; \
+ fi \
+ fi
+ @sed '/VN/s/.ds VN \(.*\)/#define LSOF_VERSION "\1"/' < version >> version.h
+
+FRC:
+
+# DO NOT DELETE THIS LINE - make depend DEPENDS ON IT
+
+ddev.o: ${HDR} ddev.c
+
+dfile.o: ${HDR} dfile.c
+
+dmnt.o: ${HDR} dmnt.c
+
+dnode.o: ${HDR} dnode.c
+
+dproc.o: ${HDR} dproc.c
+
+dsock.o: ${HDR} dsock.c
+
+dstore.o: ${HDR} dstore.c
+
+arg.o: ${HDR} arg.c
+
+main.o: ${HDR} main.c
+
+misc.o: ${HDR} misc.c
+
+node.o: ${HDR} node.c
+
+print.o: ${HDR} print.c
+
+proc.o: ${HDR} proc.c
+
+store.o: ${HDR} store.c
+
+usage.o: ${HDR} version.h usage.c
+
+util.o: ${HDR} util.c
+
+# *** Do not add anything here - It will go away. ***
diff --git a/dialects/du/Mksrc b/dialects/du/Mksrc
new file mode 100755
index 0000000..05ee4b1
--- /dev/null
+++ b/dialects/du/Mksrc
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Mksrc - make DEC OSF/1, Digital UNIX, Tru64 UNIX source files
+#
+# WARNING: This script assumes it is running from the main directory
+# of the lsof, version 4 distribution.
+#
+# One environment variable applies:
+#
+# LSOF_MKC is the method for creating the source files.
+# It defaults to "ln -s". A common alternative is "cp".
+#
+# $Id: Mksrc,v 1.3 99/04/15 06:40:21 abe Exp $
+
+
+D=dialects/du
+L="ddev.c dfile.c dlsof.h dmnt.c dnode.c dproc.c dproto.h dsock.c dstore.c machine.h"
+
+for i in $L
+do
+ rm -f $i
+ $LSOF_MKC $D/$i $i
+ echo "$LSOF_MKC $D/$i $i"
+done
diff --git a/dialects/du/ddev.c b/dialects/du/ddev.c
new file mode 100644
index 0000000..bbc4c9c
--- /dev/null
+++ b/dialects/du/ddev.c
@@ -0,0 +1,759 @@
+/*
+ * ddev.c - DEC OSF/1, Digital UNIX, Tru64 UNIX device support functions for
+ * lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: ddev.c,v 1.17 2005/08/12 15:35:14 abe Exp $";
+#endif
+
+#include "lsof.h"
+
+
+/*
+ * Local static values
+ */
+
+#if defined(USELOCALREADDIR)
+static struct stat Dirsb;
+#endif /* defined(USELOCALREADDIR) */
+
+
+/*
+ * Local definitions
+ */
+
+#define LIKE_BLK_SPEC "like block special"
+#define LIKE_CHR_SPEC "like character special"
+
+
+/*
+ * Local function prototypes
+ */
+
+_PROTOTYPE(static int rmdupdev,(struct l_dev ***dp, int n, char *nm));
+
+
+#if defined(HASDCACHE)
+/*
+ * clr_sect() - clear cached clone and pseudo sections
+ */
+
+void
+clr_sect()
+{
+ struct clone *c, *c1;
+
+ if (Clone) {
+ for (c = Clone; c; c = c1) {
+ c1 = c->next;
+ (void) free((FREE_P *)c);
+ }
+ Clone = (struct clone *)NULL;
+ }
+}
+#endif /* defined(HASDCACHE) */
+
+
+/*
+ * printdevname() - print block and character device names
+ */
+
+int
+printdevname(dev, rdev, f, nty)
+ dev_t *dev; /* device */
+ dev_t *rdev; /* raw device */
+ int f; /* 1 = follow with '\n' */
+ int nty; /* node type: N_BLK or N_CHR */
+{
+ struct clone *c;
+ struct l_dev *dp;
+
+ readdev(0);
+/*
+ * Search for clone.
+ */
+
+#if defined(HASDCACHE)
+
+printdevname_again:
+
+#endif /* defined(HASDCACHE) */
+
+ if ((nty == N_CHR) && Clone && HAVECLONEMAJ && (*dev == DevDev)
+ && (GET_MAJ_DEV(*rdev) == CLONEMAJ))
+ {
+ for (c = Clone; c; c = c->next) {
+ if (Devtp[c->dx].rdev == *rdev) {
+
+#if defined(HASDCACHE)
+ if (DCunsafe && !Devtp[c->dx].v && !vfy_dev(&Devtp[c->dx]))
+ goto printdevname_again;
+#endif /* defined(HASDCACHE) */
+
+ safestrprt(Devtp[c->dx].name, stdout, f);
+ return(1);
+ }
+ }
+ }
+/*
+ * Search device table for a full match.
+ */
+
+#if defined(HASBLKDEV)
+ if (nty == N_BLK)
+ dp = lkupbdev(dev, rdev, 1, 0);
+ else
+#endif /* defined(HASBLKDEV) */
+
+ dp = lkupdev(dev, rdev, 1, 0);
+ if (dp) {
+ safestrprt(dp->name, stdout, f);
+ return(1);
+ }
+/*
+ * Search device table for a match without inode number and dev.
+ */
+
+#if defined(HASBLKDEV)
+ if (nty == N_BLK)
+ dp = lkupbdev(&DevDev, rdev, 0, 0);
+ else
+#endif /* defined(HASBLKDEV) */
+
+ dp = lkupdev(&DevDev, rdev, 0, 0);
+ if (dp) {
+
+ /*
+ * A raw device match was found. Record it as a name column addition.
+ */
+ char *cp, *ttl;
+ int len;
+
+ ttl = (nty == N_BLK) ? LIKE_BLK_SPEC : LIKE_CHR_SPEC;
+ len = (int)(1 + strlen(ttl) + 1 + strlen(dp->name) + 1);
+ if (!(cp = (char *)malloc((MALLOC_S)(len + 1)))) {
+ (void) fprintf(stderr, "%s: no nma space for: (%s %s)\n",
+ Pn, ttl, dp->name);
+ Exit(1);
+ }
+ (void) snpf(cp, len + 1, "(%s %s)", ttl, dp->name);
+ (void) add_nma(cp, len);
+ (void) free((FREE_P *)cp);
+ return(0);
+ }
+
+#if defined(HASDCACHE)
+/*
+ * If the device cache is "unsafe" and we haven't found any match, reload
+ * the device cache.
+ */
+ if (DCunsafe) {
+ (void) rereaddev();
+ goto printdevname_again;
+ }
+#endif /* defined(HASDCACHE) */
+
+ return(0);
+}
+
+
+/*
+ * readdev() - read names, modes and device types of everything in /dev
+ */
+
+void
+readdev(skip)
+ int skip; /* skip device cache read if 1 */
+{
+#if defined(HASDCACHE)
+ int dcrd;
+#endif /* defined(HASDCACHE) */
+
+ struct clone *c;
+ DIR *dfp;
+ struct DIRTYPE *dp;
+ char *fp = (char *)NULL;
+ int i = 0;
+
+#if defined(HASBLKDEV)
+ int j = 0;
+#endif /* defined(HASBLKDEV) */
+
+ MALLOC_S nl;
+ char *path = (char *)NULL;
+ MALLOC_S pl;
+ struct stat sb;
+
+ if (Sdev)
+ return;
+
+#if defined(HASDCACHE)
+/*
+ * Read device cache, as directed.
+ */
+ if (!skip) {
+ if (DCstate == 2 || DCstate == 3) {
+ if ((dcrd = read_dcache()) == 0)
+ return;
+ }
+ } else
+ dcrd = 1;
+#endif /* defined(HASDCACHE) */
+
+ Dstk = (char **)NULL;
+ Dstkn = Dstkx = 0;
+ (void) stkdir("/dev");
+/*
+ * Unstack the next /dev or /dev/<subdirectory> directory.
+ */
+ while (--Dstkx >= 0) {
+ if (!(dfp = OpenDir(Dstk[Dstkx]))) {
+
+#if defined(WARNDEVACCESS)
+ if (!Fwarn) {
+ (void) fprintf(stderr, "%s: WARNING: can't open: ", Pn);
+ safestrprt(Dstk[Dstkx], stderr, 1);
+ }
+#endif /* defined(WARNDEVACCESS) */
+
+ (void) free((FREE_P *)Dstk[Dstkx]);
+ Dstk[Dstkx] = (char *)NULL;
+ continue;
+ }
+ if (path) {
+ (void) free((FREE_P *)path);
+ path = (char *)NULL;
+ }
+ if (!(path = mkstrcat(Dstk[Dstkx], -1, "/", 1, (char *)NULL, -1,
+ &pl)))
+ {
+ (void) fprintf(stderr, "%s: no space for: ", Pn);
+ safestrprt(Dstk[Dstkx], stderr, 1);
+ Exit(1);
+ }
+ (void) free((FREE_P *)Dstk[Dstkx]);
+ Dstk[Dstkx] = (char *)NULL;
+ /*
+ * Scan the directory.
+ */
+ for (dp = ReadDir(dfp); dp; dp = ReadDir(dfp)) {
+ if (dp->d_ino == 0 || dp->d_name[0] == '.')
+ continue;
+ /*
+ * Form the full path name and get its status.
+ */
+ if (fp) {
+ (void) free((FREE_P *)fp);
+ fp = (char *)NULL;
+ }
+ if (!(fp = mkstrcat(path, (int)pl, dp->d_name, dp->d_namlen,
+ (char *)NULL, -1, (MALLOC_S *)NULL)))
+ {
+ (void) fprintf(stderr, "%s: no space for: ", Pn);
+ safestrprt(path, stderr, 0);
+ safestrprt(dp->d_name, stderr, 1);
+ Exit(1);
+ }
+
+#if defined(USE_STAT)
+ if (stat(fp, &sb) != 0)
+#else /* !defined(USE_STAT) */
+ if (lstat(fp, &sb) != 0)
+#endif /* defined(USE_STAT) */
+
+ {
+ if (errno == ENOENT) /* symbolic link to nowhere? */
+ continue;
+
+#if defined(WARNDEVACCESS)
+ if (!Fwarn) {
+ int errno_save = errno;
+
+ (void) fprintf(stderr, "%s: can't stat ", Pn);
+ safestrprt(fp, stderr, 0);
+ (void) fprintf(stderr, ": %s\n", strerror(errno_save));
+ }
+#endif /* defined(WARNDEVACCESS) */
+
+ continue;
+ }
+ /*
+ * If it's a subdirectory, stack its name for later processing.
+ */
+ if ((sb.st_mode & S_IFMT) == S_IFDIR) {
+ (void) stkdir(fp);
+ continue;
+ }
+ if ((sb.st_mode & S_IFMT) == S_IFCHR) {
+
+ /*
+ * Save character device information in Devtp[].
+ */
+ if (i >= Ndev) {
+ Ndev += DEVINCR;
+ if (!Devtp)
+ Devtp = (struct l_dev *)malloc(
+ (MALLOC_S)(sizeof(struct l_dev)*Ndev));
+ else
+ Devtp = (struct l_dev *)realloc(
+ (MALLOC_P *)Devtp,
+ (MALLOC_S)(sizeof(struct l_dev)*Ndev));
+ if (!Devtp) {
+ (void) fprintf(stderr,
+ "%s: no space for character device\n", Pn);
+ Exit(1);
+ }
+ }
+ Devtp[i].inode = (INODETYPE)sb.st_ino;
+ if (!(Devtp[i].name = mkstrcpy(fp, (MALLOC_S *)NULL))) {
+ (void) fprintf(stderr, "%s: no space for: ", Pn);
+ safestrprt(fp, stderr, 1);
+ Exit(1);
+ }
+ Devtp[i].rdev = sb.st_rdev;
+ Devtp[i].v = 0;
+ /*
+ * Save clone device location.
+ */
+ if (HAVECLONEMAJ
+ && GET_MAJ_DEV(Devtp[i].rdev) == CLONEMAJ)
+ {
+ if (!(c = (struct clone *)malloc(sizeof(struct clone))))
+ {
+ (void) fprintf(stderr,
+ "%s: no space for clone device: ", Pn);
+ safestrprt(fp, stderr, 1);
+ Exit(1);
+ }
+ c->dx = i;
+ c->next = Clone;
+ Clone = c;
+ }
+ i++;
+ }
+
+#if defined(HASBLKDEV)
+ if ((sb.st_mode & S_IFMT) == S_IFBLK) {
+
+ /*
+ * Save block device information in BDevtp[].
+ */
+ if (j >= BNdev) {
+ BNdev += DEVINCR;
+ if (!BDevtp)
+ BDevtp = (struct l_dev *)malloc(
+ (MALLOC_S)(sizeof(struct l_dev)*BNdev));
+ else
+ BDevtp = (struct l_dev *)realloc(
+ (MALLOC_P *)BDevtp,
+ (MALLOC_S)(sizeof(struct l_dev)*BNdev));
+ if (!BDevtp) {
+ (void) fprintf(stderr,
+ "%s: no space for block device\n", Pn);
+ Exit(1);
+ }
+ }
+ BDevtp[j].inode = (INODETYPE)sb.st_ino;
+ BDevtp[j].name = fp;
+ fp = (char *)NULL;
+ BDevtp[j].rdev = sb.st_rdev;
+ BDevtp[j].v = 0;
+ j++;
+ }
+#endif /* defined(HASBLKDEV) */
+
+ }
+ (void) CloseDir(dfp);
+ }
+/*
+ * Free any allocated space.
+ */
+ if (Dstk) {
+ (void) free((FREE_P *)Dstk);
+ Dstk = (char **)NULL;
+ Dstkn = Dstkx = 0;
+ }
+ if (fp)
+ (void) free((FREE_P *)fp);
+ if (path)
+ (void) free((FREE_P *)path);
+/*
+ * Reduce the BDevtp[] (optional) and Devtp[] tables to their minimum
+ * sizes; allocate and build sort pointer lists; and sort the tables by
+ * device number.
+ */
+
+#if defined(HASBLKDEV)
+ if (BNdev) {
+ if (BNdev > j) {
+ BNdev = j;
+ BDevtp = (struct l_dev *)realloc((MALLOC_P *)BDevtp,
+ (MALLOC_S)(sizeof(struct l_dev) * BNdev));
+ }
+ if (!(BSdev = (struct l_dev **)malloc(
+ (MALLOC_S)(sizeof(struct l_dev *) * BNdev))))
+ {
+ (void) fprintf(stderr,
+ "%s: no space for block device sort pointers\n", Pn);
+ Exit(1);
+ }
+ for (j = 0; j < BNdev; j++) {
+ BSdev[j] = &BDevtp[j];
+ }
+ (void) qsort((QSORT_P *)BSdev, (size_t)BNdev,
+ (size_t)sizeof(struct l_dev *), compdev);
+ BNdev = rmdupdev(&BSdev, BNdev, "block");
+ }
+
+# if !defined(NOWARNBLKDEV)
+ else {
+ if (!Fwarn)
+ (void) fprintf(stderr,
+ "%s: WARNING: no block devices found\n", Pn);
+ }
+# endif /* !defined(NOWARNBLKDEV) */
+#endif /* defined(HASBLKDEV) */
+
+ if (Ndev) {
+ if (Ndev > i) {
+ Ndev = i;
+ Devtp = (struct l_dev *)realloc((MALLOC_P *)Devtp,
+ (MALLOC_S)(sizeof(struct l_dev) * Ndev));
+ }
+ if (!(Sdev = (struct l_dev **)malloc(
+ (MALLOC_S)(sizeof(struct l_dev *) * Ndev))))
+ {
+ (void) fprintf(stderr,
+ "%s: no space for character device sort pointers\n", Pn);
+ Exit(1);
+ }
+ for (i = 0; i < Ndev; i++) {
+ Sdev[i] = &Devtp[i];
+ }
+ (void) qsort((QSORT_P *)Sdev, (size_t)Ndev,
+ (size_t)sizeof(struct l_dev *), compdev);
+ Ndev = rmdupdev(&Sdev, Ndev, "char");
+ } else {
+ (void) fprintf(stderr, "%s: no character devices found\n", Pn);
+ Exit(1);
+ }
+
+#if defined(HASDCACHE)
+/*
+ * Write device cache file, as required.
+ */
+ if (DCstate == 1 || (DCstate == 3 && dcrd))
+ write_dcache();
+#endif /* defined(HASDCACHE) */
+
+}
+
+
+#if defined(USELOCALREADDIR)
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * This is a hacked version of NetBSD's readdir() function written to work
+ * around an apparent bug in the Digital UNIX 3.0 getdirentries() system call
+ * and/or their "/dev/fd" filesystem. The problem is that when applied to
+ * "/dev/fs", getdirentries() returns the wrong size, which can cause readdir()
+ * to run off the end of it's internal buffer and return bogus file names.
+ *
+ * The changes from the original NetBSD file are:
+ *
+ * - uses of the field dd_flags in the DIR structure have been removed since
+ * Digital UNIX doesn't have this field (it seems to be mostly used for
+ * dealing with whiteout's in NetBSD's union filesystem).
+ *
+ * - uses of the dd_len field were replaced with dd_bufsiz, since this appears
+ * to be where the Digital UNIX opendir() call stashes the size of the buffer
+ * it mallocs. Why does Digital UNIX have both? No idea -- as far as I
+ * could tell dd_len was always 0.
+ *
+ * - code within "#ifdef BROKEN_GETDIRENTRIES ... #endif" has been added to
+ * workaround the bug. Note: this code uses the (apparently) unused field,
+ * dd_len, in the Digital UNIX DIR structure. This is pretty nasty, but
+ * then, this whole routine *is* just a hack to get around a (hopefully)
+ * temporary problem in Digital UNIX.
+ *
+ * This routine has only been tested on a couple of Digital UNIX 3.0 systems.
+ * I make no guarantees that it will work for you...!
+ *
+ * Duncan McEwan (duncan@comp.vuw.ac.nz)
+ */
+
+/*
+ * Additional changes by Vic Abell <abe@cc.purdue.edu>:
+ *
+ * - The BROKEN_GETDIRENTRIES symbol was deleted. Use of this function
+ * is controlled in the lsof distribution by the HASLOCALREADDIR
+ * definition.
+ */
+
+
+/*
+ * CloseDir() - close directory
+ */
+
+int
+CloseDir(dirp)
+ register DIR *dirp;
+{
+ return(closedir(dirp));
+}
+
+
+/*
+ * OpenDir() - open directory
+ */
+
+DIR *
+OpenDir(dir)
+ char *dir;
+{
+ DIR *dirp;
+
+ if ((dirp = opendir(dir))) {
+
+ /*
+ * Get a stat(2) buffer for the directory.
+ *
+ * Warn if the stat(2) buffer operation fails, close the directory,
+ * and respond that the open failed.
+ */
+ if (statsafely(dir, &Dirsb)) {
+ int en = errno;
+
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ "%s: WARNING: can't statsafely(", Pn);
+ safestrprt(dir, stderr, 0);
+ (void) fprintf(stderr, "): %s\n", strerror(en));
+ }
+ (void) CloseDir(dirp);
+ dirp = (DIR *)NULL;
+ errno = en;
+ }
+ }
+ return(dirp);
+}
+
+
+/*
+ * ReadDir() - read next directory entry
+ */
+
+extern struct DIRTYPE *
+ReadDir(dirp)
+ register DIR *dirp;
+{
+ register struct DIRTYPE *dp;
+
+/*
+ * Loop through the directory.
+ */
+ for (;;) {
+ if (dirp->dd_loc >= dirp->dd_size) {
+ dirp->dd_loc = 0;
+ }
+ if (dirp->dd_loc == 0) {
+ dirp->dd_size = getdirentries(dirp->dd_fd,
+ dirp->dd_buf, dirp->dd_bufsiz, &dirp->dd_seek);
+
+ if (dirp->dd_size <= 0)
+ return((struct DIRTYPE *)NULL);
+ /*
+ * If the size returned by getdirentries() exceeds what it
+ * should be (as determined by a stat(2) of the directory),
+ * set it to the proper value. This is an adjustment for an
+ * apparent bug in the Digital UNIX 3.[02] getdirentries()
+ * function, when applied to a /dev/fd mount point.
+ *
+ * This check was conceived by Duncan McEwan and modified by
+ * Vic Abell.
+ */
+ if (dirp->dd_size > (long)Dirsb.st_size)
+ dirp->dd_size = (long)Dirsb.st_size;
+ Dirsb.st_size -= (off_t)dirp->dd_size;
+ }
+ dp = (struct DIRTYPE *)(dirp->dd_buf + dirp->dd_loc);
+ if ((long)dp & 03) /* bogus pointer check */
+ return((struct DIRTYPE *)NULL);
+ if (dp->d_reclen <= 0
+ || dp->d_reclen > dirp->dd_bufsiz + 1 - dirp->dd_loc)
+ return((struct DIRTYPE *)NULL);
+ dirp->dd_loc += dp->d_reclen;
+ if (dp->d_ino == 0)
+ continue;
+ return (dp);
+ }
+}
+#endif /* defined(USELOCALREADDIR) */
+
+
+#if defined(HASDCACHE)
+/*
+ * rereaddev() - reread device names, modes and types
+ */
+
+void
+rereaddev()
+{
+ (void) clr_devtab();
+
+# if defined(DCACHE_CLR)
+ (void) DCACHE_CLR();
+# endif /* defined(DCACHE_CLR) */
+
+ readdev(1);
+ DCunsafe = 0;
+}
+#endif /* defined(HASDCACHE) */
+
+
+/*
+ * rmdupdev() - remove duplicate (major/minor/inode) devices
+ */
+
+static int
+rmdupdev(dp, n, nm)
+ struct l_dev ***dp; /* device table pointers address */
+ int n; /* number of pointers */
+ char *nm; /* device table name for error message */
+{
+ struct clone *c, *cp;
+ int i, j, k;
+ struct l_dev **p;
+
+ for (i = j = 0, p = *dp; i < n ;) {
+ for (k = i + 1; k < n; k++) {
+ if (p[i]->rdev != p[k]->rdev || p[i]->inode != p[k]->inode)
+ break;
+ /*
+ * See if we're deleting a duplicate clone device. If so,
+ * delete its clone table entry.
+ */
+ for (c = Clone, cp = (struct clone *)NULL;
+ c;
+ cp = c, c = c->next)
+ {
+ if (&Devtp[c->dx] != p[k])
+ continue;
+ if (!cp)
+ Clone = c->next;
+ else
+ cp->next = c->next;
+ (void) free((FREE_P *)c);
+ break;
+ }
+ }
+ if (i != j)
+ p[j] = p[i];
+ j++;
+ i = k;
+ }
+ if (n == j)
+ return(n);
+ if (!(*dp = (struct l_dev **)realloc((MALLOC_P *)*dp,
+ (MALLOC_S)(j * sizeof(struct l_dev *)))))
+ {
+ (void) fprintf(stderr, "%s: can't realloc %s device pointers\n",
+ Pn, nm);
+ Exit(1);
+ }
+ return(j);
+}
+
+
+#if defined(HASDCACHE)
+/*
+ * vfy_dev() - verify a device table entry (usually when DCunsafe == 1)
+ *
+ * Note: rereads entire device table when an entry can't be verified.
+ */
+
+int
+vfy_dev(dp)
+ struct l_dev *dp; /* device table pointer */
+{
+ struct stat sb;
+
+ if (!DCunsafe || dp->v)
+ return(1);
+
+#if defined(USE_STAT)
+ if (stat(dp->name, &sb) != 0
+#else /* !defined(USE_STAT) */
+ if (lstat(dp->name, &sb) != 0
+#endif /* defined(USE_STAT) */
+
+ || dp->rdev != sb.st_rdev
+ || dp->inode != (INODETYPE)sb.st_ino) {
+ (void) rereaddev();
+ return(0);
+ }
+ dp->v = 1;
+ return(1);
+}
+#endif /* defined(HASDCACHE) */
diff --git a/dialects/du/dfile.c b/dialects/du/dfile.c
new file mode 100644
index 0000000..f96a455
--- /dev/null
+++ b/dialects/du/dfile.c
@@ -0,0 +1,118 @@
+/*
+ * dfile.c - DEC OSF/1, Digital UNIX, Tru64 UNIX file processing functions for
+ * lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dfile.c,v 1.12 2001/08/14 12:40:12 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+#if defined(HASIPv6)
+/*
+ * gethostbyname2() -- an RFC2133-compatible get-host-by-name-two function
+ * to get AF_INET and AF_INET6 addresses from host names,
+ * using the RFC2553-compatible getipnodebyname() function
+ */
+
+extern struct hostent *
+gethostbyname2(nm, prot)
+ char *nm; /* host name */
+ int prot; /* protocol -- AF_INET or AF_INET6 */
+{
+ int err;
+ static struct hostent *hep = (struct hostent *)NULL;
+
+ if (hep)
+ (void) freehostent(hep);
+ hep = getipnodebyname(nm, prot, 0, &err);
+ return(hep);
+}
+#endif /* defined(HASIPv6) */
+
+
+#if defined(HASPRIVNMCACHE)
+/*
+ * print_advfs_path() - print an ADVFS file path
+ *
+ * return: 1 if path printed
+ *
+ * This code was provided by Dean Brock <brock@cs.unca.edu>.
+ *
+ * This function is called by the name HASPRIVNMCACHE from printname().
+ */
+
+int
+print_advfs_path(lf)
+ struct lfile *lf; /* file whose name is to be printed */
+{
+ char buf[MAXPATHLEN+1];
+ mlBfTagT t2pb;
+/*
+ * Print any non-NULL path returned by tag_to_path() for ADVFS files that
+ * have sequence and inode numbers.
+ */
+ if (!lf->advfs_seq_stat || lf->inp_ty != 1 || !lf->fsdir || !*lf->fsdir)
+ return(0);
+ t2pb.ml_ino = (int)lf->inode;
+ t2pb.ml_seq = lf->advfs_seq;
+ if (tag_to_path(lf->fsdir, t2pb, MAXPATHLEN, buf) || !*buf)
+ return(0);
+ buf[MAXPATHLEN] = '\0';
+ safestrprt((buf[0] == '/' && buf[1] == '/') ? &buf[1] : buf, stdout, 0);
+ return(1);
+}
+#endif /* defined(HASPRIVNMCACHE) */
+
+
+/*
+ * print_dev() - print device
+ */
+
+char *
+print_dev(lf, dev)
+ struct lfile *lf; /* file whose device is to be printed */
+ dev_t *dev; /* device to be printed */
+{
+ static char buf[128];
+
+ if (GET_MIN_DEV(*dev) > 9999999)
+ (void) snpf(buf, sizeof(buf), "%d,%#x", GET_MAJ_DEV(*dev),
+ GET_MIN_DEV(*dev));
+ else
+ (void) snpf(buf, sizeof(buf), "%d,%d", GET_MAJ_DEV(*dev),
+ GET_MIN_DEV(*dev));
+ return(buf);
+}
diff --git a/dialects/du/dlsof.h b/dialects/du/dlsof.h
new file mode 100644
index 0000000..98fbb27
--- /dev/null
+++ b/dialects/du/dlsof.h
@@ -0,0 +1,400 @@
+/*
+ * dlsof.h - DEC OSF/1, Digital UNIX, Tru64 UNIX header file for lsof
+ */
+
+
+/*
+ * Copyright 1994 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.
+ */
+
+
+/*
+ * $Id: dlsof.h,v 1.27 2006/03/27 20:40:59 abe Exp $
+ */
+
+
+#if !defined(DU_LSOF_H)
+#define DU_LSOF_H 1
+
+#include <fcntl.h>
+#include <fstab.h>
+
+# if DUV<30000 || DUV>=50000
+#include <sys/mount.h>
+# endif /* DUV<30000 || DUV>=50000 */
+
+#include <dirent.h>
+#include <nlist.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+#include <cdfs/cdfsnode.h>
+#include <machine/hal_sysinfo.h>
+#include <rpc/types.h>
+#include <sys/mbuf.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/table.h>
+#include <sys/un.h>
+#include <sys/unpcb.h>
+#include <sys/domain.h>
+#include <netinet/in.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <net/route.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/in_pcb.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+#include <netinet/tcp_fsm.h>
+#include <netinet/tcp_timer.h>
+#include <netinet/tcp_var.h>
+#include <net/raw_cb.h>
+#undef queue
+#undef queue_t
+#define queue ___queue
+#define queue_t ___queue_t
+#include <sys/stream.h>
+#undef ___queue
+#undef ___queue_t
+#define ___queue queue
+#define ___queue_t queue_t
+
+# if DUV<30000
+#include <nfs/nfs.h>
+#define KERNEL_FILE
+#include <sys/file.h>
+# endif /* DUV<30000 */
+
+#include <ufs/inode.h>
+
+# if DUV>=50100
+#include <sys/systm.h>
+#define _SYS_USER_H_
+#include <machine/pcb.h>
+#undef _SYS_USER_H_
+# endif /* DUV>=50100 */
+
+/*
+ * The following header files need _KERNEL and KERNEL defined. Some
+ * ugly #undef preparation is necessary.
+ */
+
+#define _KERNEL 1
+#define KERNEL 1
+#undef MACRO_END
+#undef PIPSIZ
+#undef i_forw
+#undef i_gen
+#undef i_gid
+#undef i_lock
+#undef i_mode
+#undef i_nlink
+#undef i_rdev
+#undef i_size
+#undef i_uid
+
+# if DUV>=30000
+#undef m_data
+#undef m_next
+#include <sys/file.h>
+#include <sys/fifonode.h>
+# if DUV<50000
+#include <sys/mount.h>
+# endif /* DUV<50000 */
+# endif /* DUV>=30000 */
+
+#undef calloc
+#define calloc ___calloc
+#undef exit
+#define exit ___exit
+#define pmap ___pmap
+#undef pt_entry_t
+#define pt_entry_t ___pt_entry_t
+#undef timer_t
+#define timer_t ___timer_t
+
+# if DUV>=50000
+#include "du5_sys_malloc.h"
+#undef _SYS_WAIT_H_ /* allow <sys/user.h> to
+ * #include <sys/wait.h> while
+ * _KERNEL is defined */
+# endif /* DUV>=50000 */
+
+# if DUV<40000
+#include <kern/task.h>
+#undef ___calloc
+#define ___calloc calloc
+#undef ___exit
+#define ___exit exit
+#undef ___pt_entry_t
+#undef ___timer_t
+# endif /* DUV<40000 */
+
+#include <s5fs/s5param.h>
+#include <s5fs/s5inode.h>
+#include <sys/procfs.h>
+#include <sys/proc.h>
+
+# if DUV>=40000
+#undef ___calloc
+#define ___calloc calloc
+#undef ___exit
+#define ___exit exit
+# endif /* DUV>=40000 */
+
+#include <sys/user.h>
+#undef u_comm
+#define u_comm uu_comm
+#include <sys/flock.h>
+
+# if DUV>=30000
+#undef u
+#endif /* DUV>=30000 */
+
+#include <sys/specdev.h>
+#include <sys/vnode.h>
+
+# if DUV>=30000
+#define quotactl __quotactl
+#include <nfs/nfs.h>
+#undef quotactl
+# endif /* DUV>=30000 */
+
+#include <nfs/rnode.h>
+#include <ufs/mfsnode.h>
+#include <vm/vm_anon.h>
+#include <vm/u_mape_seg.h>
+
+# if DUV>=40000
+#include <vm/vm_ubc.h>
+# else /* DUV<40000 */
+#include <vm/vm_vp.h>
+# endif /* DUV>=40000 */
+
+
+# if !defined(HASSPECNODE)
+/*
+ * The spec_node is not defined in a distributed header file, but in
+ * a kernel source file.
+ */
+
+struct spec_node {
+ struct vnode *sn_vnode;
+ struct vattr sn_vattr;
+};
+# endif /* !defined(HASSPECNODE) */
+
+
+# if ADVFSV<500
+/*
+ * This is an educated guess at an ADVFS/MSFS node for AdvFS versions below 5.
+ *
+ * Information that became available to me for AdvFS 5.0 and higher indicates
+ * multiple adjacent structures are involved. Those definitions may be found
+ * in dnode.c inside an ADVFSV #if|#endif block.
+ */
+
+struct advfsnode {
+
+# if ADVFSV<200
+ unsigned long d1[19];
+# else /* ADVFSV>=200 */
+# if ADVFSV<300
+ unsigned long d1[20];
+# else /* ADVFSV>=300 */
+# if ADVFSV<400
+ unsigned long d1[21];
+# else /* ADVFSV>=400 */
+ unsigned long d1[17];
+# endif /* ADVFSV>=400 */
+# endif /* ADVFSV<300 */
+# endif /* ADVFSV<200 */
+
+ ino_t a_number;
+ int a_seq;
+ unsigned long d3;
+ int d4;
+ dev_t a_rdev;
+ unsigned long a_size;
+
+# if ADVFSV>=400
+ unsigned long d5[5];
+ int d6;
+ int a_nlink;
+# endif /* ADVFSV>=400 */
+
+};
+# endif /* ADVFSV<500 */
+
+
+# if defined(HASTAGTOPATH)
+/*
+ * Define the structure used for passing inode and sequence numbers to the
+ * ADVFS 4.0 and greater tag_to_path() -lmsfs function.
+ *
+ * This structure definition was provided by Dean Brock <brock@cs.unca.edu>.
+ */
+ typedef struct {
+ int ml_ino;
+ int ml_seq;
+ } mlBfTagT;
+# endif /* defined(HASTAGTOPATH) */
+
+
+# if DUV<50000
+#define COMP_P void
+typedef unsigned long KA_T;
+# else /* DUV>=50000 */
+#define COMP_P const void
+typedef off_t KA_T;
+#endif /* DUV<50000 */
+
+#define DEVINCR 1024 /* device table malloc() increment */
+#define DIRTYPE dirent
+#define KMEM "/dev/kmem"
+#define MALLOC_P char
+#define FREE_P MALLOC_P
+#define MALLOC_S size_t
+#define MAXSYSCMDL MAXCOMLEN /* max system command name length */
+#define PNSIZ 5 /* /proc PID name component length */
+#define PR_INOBIAS 64 /* /proc inode number bias */
+#define PR_ROOTINO 2 /* /proc root inode number */
+#define PROCMIN 3 /* processes that make a "good" scan */
+#define PROCTRYLM 5 /* times to try to read proc table */
+#define QSORT_P char
+#define READLEN_T int
+#define STRNCPY_L int
+#define U_SIZE sizeof(struct user)
+
+
+/*
+ * Global storage definitions (including their structure definitions)
+ */
+
+extern int CloneMaj;
+extern struct file *Fileptr;
+#define FILEPTR Fileptr /* for process_file() in lib/prfp.c */
+extern int HaveCloneMaj;
+extern int Kd;
+
+struct l_vfs {
+ KA_T addr; /* kernel address */
+ fsid_t fsid; /* file system ID */
+ short type; /* type of file system */
+ char *dir; /* mounted directory */
+ char *fsname; /* file system name */
+
+# if defined(HASFSINO)
+ INODETYPE fs_ino; /* file system inode number */
+# endif /* defined(HASFSINO) */
+
+ dev_t dev; /* device number */
+ dev_t rdev; /* raw device number */
+ struct l_vfs *next; /* forward link */
+};
+extern struct l_vfs *Lvfs;
+
+struct mounts {
+ char *dir; /* directory (mounted on) */
+ char *fsname; /* file system
+ * (symbolic links unresolved) */
+ char *fsnmres; /* file system
+ * (symbolic links resolved) */
+ dev_t dev; /* directory st_dev */
+ dev_t rdev; /* directory st_rdev */
+ INODETYPE inode; /* directory st_ino */
+ mode_t mode; /* directory st_mode */
+ mode_t fs_mode; /* file system st_mode */
+ struct mounts *next; /* forward link */
+ fsid_t fsid; /* directory file system ID */
+};
+extern struct mounts *Mtab;
+
+#define X_NCACHE "ncache"
+#define X_NCSIZE "ncsize"
+#define NL_NAME n_name
+
+struct sfile {
+ char *aname; /* argument file name */
+ char *name; /* file name (after readlink()) */
+ char *devnm; /* device name (optional) */
+ dev_t dev; /* device */
+ dev_t rdev; /* raw device */
+ u_short mode; /* S_IFMT mode bits from stat() */
+ int type; /* file type: 0 = file system
+ * 1 = regular file */
+ INODETYPE i; /* inode number */
+ int f; /* file found flag */
+ struct sfile *next; /* forward link */
+
+};
+
+# if DUV>=30000
+extern KA_T *Pa; /* kernel proc structure addresses */
+# endif /* DUV>=30000 */
+
+extern struct proc *Ps; /* local proc structures */
+extern int Psn; /* entries in Pa[] and Ps[] */
+
+extern int Vnmxp;
+
+
+/*
+ * Definitions for dvch.c, isfn.c, and rdev.c
+ */
+
+#define CLONEMAJ CloneMaj /* clone major variable name */
+#define DCACHE_CLR clr_sect /* function to clear clone cache
+ * when reading the device cache
+ * file fails */
+#define HASDNAMLEN 1 /* DIRTYPE has d_namlen element */
+#define HAS_STD_CLONE 1 /* has standard clone structure */
+#define HAVECLONEMAJ HaveCloneMaj /* clone major variable status name */
+
+
+/*
+ * Definitions for rnam.c
+ */
+
+# if defined(HASNCACHE) && DUV<50100
+#include <sys/namei.h>
+#define NCACHE namecache /* kernel's structure name */
+#define NCACHE_NM nc_name /* name in NCACHE */
+#define NCACHE_NMLEN nc_nlen /* name length in NCACHE */
+#define NCACHE_NODEADDR nc_vp /* node address in NCACHE */
+#define NCACHE_PARADDR nc_dvp /* parent node address in NCACHE */
+
+# if defined(HASNCVPID)
+#define NCACHE_NODEID nc_vpid /* node ID in NCACHE */
+#define NCACHE_PARID nc_dvpid /* parent node ID in NCACHE */
+# endif /* defined(HASNCVPID) */
+# endif /* defined(HASNCACHE) && DUV<50100 */
+
+#endif /* !DU_LSOF_H */
diff --git a/dialects/du/dmnt.c b/dialects/du/dmnt.c
new file mode 100644
index 0000000..962f7b2
--- /dev/null
+++ b/dialects/du/dmnt.c
@@ -0,0 +1,320 @@
+/*
+ * dmnt.c - DEC OSF/1, Digital UNIX, Tru64 UNIX mount support functions for
+ * lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dmnt.c,v 1.11 2005/08/08 19:56:44 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+#undef KERNEL
+#include <sys/fs_types.h> /* this defines char *mnt_names[] */
+
+
+/*
+ * Local static definitions
+ */
+
+static struct mounts *Lmi = (struct mounts *)NULL; /* local mount info */
+static int Lmist = 0; /* Lmi status */
+
+
+/*
+ * readmnt() - read mount table
+ */
+
+struct mounts *
+readmnt()
+{
+ char *dn = (char *)NULL;
+ char *ln;
+ struct statfs *mb;
+ struct mounts *mtp;
+ int n;
+ int procfs = 0;
+ struct stat sb;
+
+ if (Lmi || Lmist)
+ return(Lmi);
+/*
+ * Access mount information.
+ */
+ if ((n = getmntinfo(&mb, MNT_NOWAIT)) <= 0) {
+ (void) fprintf(stderr, "%s: no mount information\n", Pn);
+ return(0);
+ }
+/*
+ * Read mount information.
+ */
+ for (; n; n--, mb++) {
+ if (mb->f_type == MOUNT_NONE || mb->f_type >= MOUNT_MAXTYPE)
+ continue;
+ /*
+ * Avoid file systems under automounter control if they're not
+ * currently mounted.
+ */
+ if (mb->f_type == MOUNT_NFS) {
+
+ /*
+ * The mount-from name of some unmounted file systems under
+ * automounter control end with ``:(pid<n>):'' -- where <n>
+ * is the PID of the automounter process.
+ */
+ if ((ln = strchr(mb->f_mntfromname, ':'))) {
+ if (strncmp(ln+1, "(pid", 4) == 0 && isdigit(*(ln+5))) {
+ for (ln += 6; *ln && isdigit(*ln); ln++) {
+ ;
+ }
+ if (*ln == ')' && *(ln+1) == '\0')
+ continue;
+ }
+ }
+ /*
+ * Another automounter mount-from name form is "amd:<n>" --
+ * where <n> is the PID of the automounter process.
+ */
+ if (strncmp(mb->f_mntfromname, "amd:", 4) == 0
+ && isdigit(mb->f_mntfromname[4])) {
+ ln = &mb->f_mntfromname[5];
+ while (*ln && isdigit(*ln)) {
+ ln++;
+ }
+ if (!*ln || (*ln == ':' && *(ln+1) == '\0'))
+ continue;
+ }
+ }
+ /*
+ * Interpolate a possible symbolic directory link.
+ */
+ if (dn)
+ (void) free((FREE_P *)dn);
+ if (!(dn = mkstrcpy(mb->f_mntonname, (MALLOC_S *)NULL))) {
+
+no_space_for_mount:
+
+ (void) fprintf(stderr, "%s: no space for mount at ", Pn);
+ safestrprt(mb->f_mntonname, stderr, 0);
+ (void) fprintf(stderr, " (");
+ safestrprt(mb->f_mntfromname, stderr, 0);
+ (void) fprintf(stderr, ")\n");
+ Exit(1);
+ }
+ if (!(ln = Readlink(dn))) {
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ " Output information may be incomplete.\n");
+ }
+ continue;
+ }
+ if (ln != dn) {
+ (void) free((FREE_P *)dn);
+ dn = ln;
+ }
+ if (*dn != '/')
+ continue;
+ /*
+ * Stat() the directory.
+ */
+ if (statsafely(dn, &sb)) {
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ "%s: WARNING: can't stat() %s file system: ",
+ Pn, mnt_names[mb->f_type]);
+ safestrprt(mb->f_mntonname, stderr, 1);
+ (void) fprintf(stderr,
+ " Output information may be incomplete.\n");
+ }
+ if (mb->f_type != MOUNT_PROCFS
+
+#if !defined(ADVFSV) || ADVFSV<400
+ && mb->f_type != MOUNT_MSFS
+#endif /* !defined(ADVFSV) || ADVFSV<400 */
+
+ ) {
+ memset((char *)&sb, 0, sizeof(sb));
+ sb.st_dev = (dev_t)mb->f_fsid.val[0];
+ sb.st_mode = S_IFDIR | 0777;
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ " assuming dev=%x from mount table\n",
+ sb.st_dev);
+ }
+ } else
+ continue;
+ }
+ /*
+ * Allocate and fill a local mount structure.
+ */
+ if (!(mtp = (struct mounts *)malloc(sizeof(struct mounts))))
+ goto no_space_for_mount;
+ mtp->dir = dn;
+ dn = (char *)NULL;
+ mtp->dev = sb.st_dev;
+ mtp->fsid = mb->f_fsid;
+ mtp->inode = (INODETYPE)sb.st_ino;
+ mtp->mode = sb.st_mode;
+ mtp->next = Lmi;
+ mtp->rdev = sb.st_rdev;
+ /*
+ * Interpolate a possible file system (mounted-on) device path.
+ */
+ if (!(dn = mkstrcpy(mb->f_mntfromname, (MALLOC_S *)NULL)))
+ goto no_space_for_mount;
+ mtp->fsname = dn;
+ ln = Readlink(dn);
+ dn = (char *)NULL;
+ /*
+ * Stat the file system (mounted-on) name and add file sysem
+ * information to the local mount table.
+ */
+ if (!ln || statsafely(ln, &sb))
+ sb.st_mode = 0;
+ mtp->fsnmres = ln;
+ mtp->fs_mode = sb.st_mode;
+ Lmi = mtp;
+ if (mb->f_type == MOUNT_PROCFS) {
+
+ /*
+ * Save information on exactly one procfs file system.
+ */
+ if (procfs)
+ Mtprocfs = (struct mounts *)NULL;
+ else {
+ procfs = 1;
+ Mtprocfs = mtp;
+ }
+ }
+ }
+/*
+ * Clean up and return the local mount info table address.
+ */
+ if (dn)
+ (void) free((FREE_P *)dn);
+ Lmist = 1;
+ return(Lmi);
+}
+
+
+/*
+ * readvfs() - read vfs structure
+ */
+
+struct l_vfs *
+readvfs(vm)
+ KA_T vm; /* mount address in vnode */
+{
+ struct mount m;
+ struct l_vfs *vp;
+ fsid_t f;
+ struct mounts *mp;
+
+#if DUV>=40000
+ int bl;
+ char fb[MAX_MNT_PATHLEN+1];
+ char ob[MAX_MNT_PATHLEN+1];
+#endif /* DUV>=40000 */
+
+/*
+ * Search for match on existing entry.
+ */
+ for (vp = Lvfs; vp; vp = vp->next) {
+ if (vm == vp->addr)
+ return(vp);
+ }
+/*
+ * Read the (new) mount structure, allocate a local entry, and fill it.
+ */
+ if (kread((KA_T)vm, (char *)&m, sizeof(m)) != 0)
+ return((struct l_vfs *)NULL);
+ if (!(vp = (struct l_vfs *)malloc(sizeof(struct l_vfs)))) {
+ (void) fprintf(stderr, "%s: PID %d, no space for vfs\n",
+ Pn, Lp->pid);
+ Exit(1);
+ }
+
+#if DUV<40000
+ if (!(vp->dir = mkstrcpy(m.m_stat.f_mntonname, (MALLOC_S *)NULL))
+ || !(vp->fsname = mkstrcpy(m.m_stat.f_mntfromname, (MALLOC_S *)NULL)))
+#else /* DUV>=40000 */
+ bl = sizeof(ob) - 1;
+ if (!m.m_stat.f_mntonname
+ || kread((KA_T)m.m_stat.f_mntonname, ob, bl))
+ bl = 0;
+ ob[bl] = '\0';
+ bl = sizeof(fb) - 1;
+ if (!m.m_stat.f_mntfromname
+ || kread((KA_T)m.m_stat.f_mntfromname, fb, bl))
+ bl = 0;
+ fb[bl] = '\0';
+ if (!(vp->dir = mkstrcpy(ob, (MALLOC_S *)NULL))
+ || !(vp->fsname = mkstrcpy(fb, (MALLOC_S *)NULL)))
+#endif /* DUV<40000 */
+
+ {
+ (void) fprintf(stderr, "%s: PID %d, no space for mount names\n",
+ Pn, Lp->pid);
+ Exit(1);
+ }
+ vp->addr = vm;
+ vp->fsid = m.m_stat.f_fsid;
+ vp->type = m.m_stat.f_type;
+
+#if defined(HASFSINO)
+ vp->fs_ino = 0;
+#endif /* defined(HASFSINO) */
+
+ vp->next = Lvfs;
+ Lvfs = vp;
+/*
+ * Derive the device and raw device numbers from a search for the
+ * file system ID in the local mount table.
+ */
+ vp->dev = vp->rdev = 0;
+ for (f = vp->fsid, mp = readmnt(); mp; mp = mp->next) {
+ if (f.val[0] == mp->fsid.val[0]
+ && f.val[1] == mp->fsid.val[1])
+ {
+ vp->dev = mp->dev;
+ vp->rdev = mp->rdev;
+
+#if defined(HASFSINO)
+ vp->fs_ino = mp->inode;
+#endif /* defined(HASFSINO) */
+
+ break;
+ }
+ }
+ return(vp);
+}
diff --git a/dialects/du/dnode.c b/dialects/du/dnode.c
new file mode 100644
index 0000000..19a8827
--- /dev/null
+++ b/dialects/du/dnode.c
@@ -0,0 +1,992 @@
+/*
+ * dnode.c - DEC OSF/1, Digital UNIX, Tru64 UNIX node functions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dnode.c,v 1.23 2006/03/27 20:40:59 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+/*
+ * Local definitions
+ */
+
+#if ADVFSV>=500
+/*
+ * AdvFS (MSFS) definitions for AdvFS version 5.0 and above.
+ */
+
+struct fs_stat { /* file system stat(2) info structure
+ * for AdvFS 5.0 and above */
+ unsigned int num; /* node number */
+ unsigned int d1;
+ mode_t d2;
+ uid_t d3;
+ gid_t d4;
+ dev_t rdev; /* character or block device number */
+ off_t size; /* file size */
+
+# if defined(__arch32__)
+ unsigned int d5;
+# endif /* defined(__arch32__) */
+
+ time_t d6;
+ int d7;
+ time_t d8;
+ int d9;
+ time_t d10;
+ int d11;
+ unsigned int d12[5];
+ unsigned short nlink; /* link count */
+};
+
+struct fsContext { /* file system context for AdvFS 5.0
+ * and above */
+ short d1[2];
+ unsigned int d2[2];
+ long d3;
+ int d4[2];
+ lock_data_t d5;
+ long d6;
+ simple_lock_data_t d7;
+ unsigned int d8[2];
+ long d9;
+ struct fs_stat st; /* file stats */
+};
+
+struct advfsnode { /* AdvFS (MSFS) node definition for
+ * AdvFS 5.0 and above */
+ unsigned long d1;
+ struct fsContext *a_con; /* context pointer */
+};
+#endif /* ADVFSV>=500 */
+
+#if DUV>=50000
+typedef struct cnode { /* CFS node structure definition for
+ * Tru64 UNIX 5.0 and above */
+ udecl_simple_lock_data(, d1)
+ unsigned int d2;
+ time_t d3;
+ unsigned long d4[3];
+
+# if DUV<50100
+ int d5[2];
+ off_t d6;
+# endif /* DUV<50100 */
+
+ unsigned long d7;
+ vattr_t c_attr; /* 96:Cached vnode attributes */
+} cnode_t;
+#endif /* DUV>=50000 */
+
+struct l_lock { /* local lock info */
+ struct eflock set; /* lock data */
+ struct l_lock *next;
+};
+
+struct l_flinfo { /* local file lock info */
+ struct vnode *vp; /* identity of locked vnode */
+ struct l_lock *lp; /* lock information */
+ struct l_flinfo *next;
+};
+
+#define L_FLINFO_HSZ 256 /* local file lock information hash
+ * table size (must be a power of 2) */
+#define L_FLINFO_HASH(va) (((int)((long)(va) * 31415L) >> 5) & (L_FLINFO_HSZ - 1))
+
+
+/*
+ * Local static variables
+ */
+
+static struct l_flinfo **Flinfo = (struct l_flinfo **)NULL;
+ /* local file lock hash buckets */
+static int FlinfoSt = 0; /* Flinfo[] load status */
+
+
+/*
+ * Local function prototypes
+ */
+
+_PROTOTYPE(static char isvlocked,(struct vnode *vp));
+_PROTOTYPE(static int load_flinfo,(void));
+_PROTOTYPE(static int readvnode,(KA_T va, struct vnode *v));
+_PROTOTYPE(static void get_proc_sz,(struct procnode *pn));
+
+
+/*
+ * clr_flinfo() - clear local file lock table information
+ */
+
+void
+clr_flinfo()
+{
+ struct l_lock *lf, *lfn;
+ int i;
+ struct l_flinfo *fi, *fin;
+
+ if (!Flinfo && !FlinfoSt)
+ return;
+ for (i = 0; i < L_FLINFO_HSZ; i++) {
+ if (!(fi = Flinfo[i]))
+ continue;
+ do {
+ if ((lf = fi->lp)) {
+ do {
+ lfn = lf->next;
+ (void) free((FREE_P *)lf);
+ } while ((lf = lfn));
+ }
+ fin = fi->next;
+ (void) free((FREE_P *)fi);
+ } while ((fi = fin));
+ Flinfo[i] = (struct l_flinfo *)NULL;
+ }
+ FlinfoSt = 0;
+}
+
+
+/*
+ * get_proc_sz() - get size of /proc file system file
+ */
+
+static void
+get_proc_sz(pn)
+ struct procnode *pn; /* pointer to procnode */
+{
+ struct vm_map m;
+ struct proc *p;
+ KA_T pa;
+ int px;
+ struct task t;
+/*
+ * Search for procnode's process by PID.
+ */
+ for (p = Ps, px = 0; px < Psn; p++, px++) {
+ if (p->p_pid == pn->prc_pid)
+ break;
+ }
+ if (px >= Psn)
+ return;
+/*
+ * Get the task structure address, then read the task structure. Set
+ * the procnode's file size from the memory map information in the task
+ * structure.
+ */
+
+# if DUV<30000
+ if (!(pa = (KA_T)p->task))
+ return;
+# else /* DUV>=30000 */
+ if (!(pa = Pa[px]))
+ return;
+ pa = (KA_T)((char *)pa - sizeof(t));
+# endif /* DUV<30000 */
+
+ if (kread(pa, (char *)&t, sizeof(t)))
+ return;
+ if (!t.map || kread((KA_T)t.map, (char *)&m, sizeof(m)))
+ return;
+ Lf->sz = (SZOFFTYPE)m.vm_size;
+ Lf->sz_def = 1;
+}
+
+
+/*
+ * isvlocked() - is vnode locked?
+ */
+
+static char
+isvlocked(vp)
+ struct vnode *vp; /* vnode's kernel address */
+{
+ struct l_flinfo *fp;
+ int i, l;
+ struct l_lock *lp;
+
+ if (!Flinfo || !FlinfoSt) {
+ if (!load_flinfo())
+ return(' ');
+ }
+/*
+ * Hash the vnode address and see if there's a local file lock information
+ * structure for it.
+ */
+ i = L_FLINFO_HASH(vp);
+ for (fp = Flinfo[i]; fp; fp = fp->next) {
+ if (fp->vp == vp)
+ break;
+ }
+ if (!fp)
+ return(' ');
+/*
+ * Search the vnode's lock list for one held by this process.
+ */
+ for (lp = fp->lp; lp; lp = lp->next) {
+ if (lp->set.l_rsys || lp->set.l_pid != (pid_t)Lp->pid)
+ continue;
+ if (lp->set.l_whence == 0 && lp->set.l_start == 0
+ && ((lp->set.l_len == 0x8000000000000000)
+ || (lp->set.l_len == 0x7fffffffffffffff)))
+ l = 1;
+ else
+ l = 0;
+ if (lp->set.l_type == F_WRLCK)
+ return(l ? 'W' : 'w');
+ else if (lp->set.l_type == F_RDLCK)
+ return(l ? 'R' : 'r');
+ return(' ');
+ }
+ return(' ');
+}
+
+
+/*
+ * load_flinfo() - load local file lock information
+ */
+
+static int
+load_flinfo()
+{
+ struct flino fi;
+ struct filock fl;
+ KA_T fif, fip, flf, flp;
+ int i;
+ struct l_flinfo *lfi;
+ struct l_lock *ll;
+ KA_T v;
+
+ if (Flinfo && FlinfoSt)
+ return(1);
+/*
+ * Get kernel fids chain pointer.
+ */
+ if (get_Nl_value("fids", Drive_Nl, &v) < 0 || !v
+ || kread((KA_T)v, (char *)&fip, sizeof(fip)))
+ return(0);
+/*
+ * Define local hash buckets, if necessary.
+ */
+ if (!Flinfo) {
+ if (!(Flinfo = (struct l_flinfo **)calloc(sizeof(struct flinfo *),
+ L_FLINFO_HSZ)))
+ {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d byte local lock hash buckets\n",
+ Pn, L_FLINFO_HSZ * sizeof(struct l_flinfo *));
+ Exit(1);
+ }
+ }
+/*
+ * Follow the fids chain.
+ */
+ if (!(fif = fip))
+ return(1);
+ /*
+ * Follow the filock chain for this fid entry.
+ * Duplicate it via the lock file lock information hash buckets.
+ */
+ do {
+ if (kread(fip, (char *)&fi, sizeof(fi)))
+ return(0);
+ if (!(flf = (KA_T)fi.fl_flck))
+ continue;
+ /*
+ * Allocate a local file lock information structure for this fid.
+ */
+ if (!(lfi = (struct l_flinfo *)malloc(sizeof(struct l_flinfo)))) {
+ (void) fprintf(stderr,
+ "%s: no space for local vnode lock info struct\n", Pn);
+ Exit(1);
+ }
+ lfi->vp = fi.vp;
+ lfi->lp = (struct l_lock *)NULL;
+ lfi->next = (struct l_flinfo *)NULL;
+ /*
+ * Follow the flino's filock chain, duplicating it locally.
+ */
+ flp = flf;
+ do {
+ if (kread(flp, (char *)&fl, sizeof(fl)))
+ break;
+ /*
+ * Allocate a local lock information structure and link it
+ * to the chain for its vnode.
+ */
+ if (!(ll = (struct l_lock *)malloc(sizeof(struct l_lock)))) {
+ (void) fprintf(stderr,
+ "%s: no space for local lock struct\n", Pn);
+ Exit(1);
+ }
+ ll->next = lfi->lp;
+ lfi->lp = ll;
+ ll->set = fl.set;
+ } while ((flp = (KA_T)fl.next) && flp != flf);
+ /*
+ * Link the file lock information structure to its hash bucket.
+ */
+ i = L_FLINFO_HASH(lfi->vp);
+ lfi->next = Flinfo[i];
+ Flinfo[i] = lfi;
+ } while ((fip = (KA_T)fi.next) && fip != fif);
+ FlinfoSt = 1;
+ return(1);
+}
+
+
+/*
+ * process_node() - process vnode
+ */
+
+void
+process_node(va)
+ KA_T va; /* vnode kernel space address */
+{
+ struct advfsnode *a = (struct advfsnode *)NULL;
+ struct cdnode *c = (struct cdnode *)NULL;
+ dev_t dev, rdev;
+ unsigned char devs = 0;
+ unsigned char rdevs = 0;
+ struct inode *i = (struct inode *)NULL;
+ struct mfsnode *m = (struct mfsnode *)NULL;
+ struct procnode *p = (struct procnode *)NULL;
+ struct procfsid *pfi;
+ struct rnode *r = (struct rnode *)NULL;
+ struct spec_node *s = (struct spec_node *)NULL;
+ struct spec_node sn;
+ struct s5inode *s5 = (struct s5inode *)NULL;
+ char *ty;
+ enum vtype type;
+ unsigned long ul;
+ static struct vnode *v = (struct vnode *)NULL;
+ struct l_vfs *vfs;
+
+#if DUV>=30000
+ struct fifonode *f = (struct fifonode *)NULL;
+ struct fifonode fn;
+ static struct vnode *fv = (struct vnode *)NULL;
+#endif /* DUV>=30000 */
+
+#if DUV>=50000
+ cnode_t *cn = (cnode_t *)NULL;
+ struct fsContext fsc;
+ int fscs = 0;
+#endif /* DUV>=50000 */
+
+/*
+ * Read the vnode.
+ */
+ if (!va) {
+ enter_nm("no vnode address");
+ return;
+ }
+ if (!v) {
+
+ /*
+ * Allocate space for the Digital UNIX vnode.
+ */
+ if (!(v = (struct vnode *)malloc(sizeof(struct vnode)-1+Vnmxp))) {
+ (void) fprintf(stderr, "%s: no space for vnode buffer\n", Pn);
+ Exit(1);
+ }
+
+#if DUV>=30000
+ if (!(fv = (struct vnode *)malloc(sizeof(struct vnode)-1+Vnmxp))) {
+ (void) fprintf(stderr, "%s: no space for fvnode buffer\n", Pn);
+ Exit(1);
+ }
+#endif /* DUV>=30000 */
+
+ }
+ if (readvnode(va, v)) {
+ enter_nm(Namech);
+ return;
+ }
+
+#if defined(HASNCACHE)
+ Lf->na = va;
+# if defined(HASNCVPID)
+ Lf->id = (unsigned long)v->v_id;
+# endif /* defined(HASNCVPID) */
+#endif /* defined(HASNCACHE) */
+
+#if defined(HASFSTRUCT)
+ Lf->fsv |= FSV_NI;
+ Lf->fna = va;
+#endif /* defined(HASFSTRUCT) */
+
+/*
+ * Get the mount structure and determine the vnode type.
+ */
+ if (!v->v_mount)
+ vfs = (struct l_vfs *)NULL;
+ else
+ vfs = readvfs((KA_T)v->v_mount);
+ if (vfs) {
+ switch (vfs->type) {
+ case MOUNT_NFS:
+
+#if defined(MOUNT_NFS3)
+ case MOUNT_NFS3:
+#endif /* defined(MOUNT_NFS3) */
+
+ Ntype = N_NFS;
+ break;
+ }
+ if (Ntype == N_REGLR) {
+ switch (v->v_type) {
+ case VFIFO:
+ Ntype = N_FIFO;
+ break;
+ }
+ }
+ }
+/*
+ * Determine the lock type.
+ */
+ if (FILEPTR && (FILEPTR->f_flag & FSHLOCK))
+ Lf->lock = 'R';
+ else if (FILEPTR && (FILEPTR->f_flag & FEXLOCK))
+ Lf->lock = 'W';
+ else
+ Lf->lock = isvlocked((struct vnode *)va);
+/*
+ * Define the specific Digital UNIX node pointer.
+ */
+
+#if DUV>=30000
+ if (Ntype == N_FIFO) {
+ if (v->v_fifonode
+ && !kread((KA_T)v->v_fifonode, (char *)&fn, sizeof(fn)))
+ f = &fn;
+ }
+#endif /* DUV>=30000 */
+
+ switch (v->v_tag) {
+ case VT_CDFS:
+ c = (struct cdnode *)v->v_data;
+ break;
+
+#if DUV>=50000
+ case VT_CFS:
+ cn = (cnode_t *)v->v_data;
+ break;
+#endif /* DUV>=50000 */
+
+ case VT_MFS:
+ m = (struct mfsnode *)v->v_data;
+ break;
+ case VT_NFS:
+ r = (struct rnode *)v->v_data;
+ break;
+ case VT_NON:
+
+#if DUV<20000
+ if (v->v_specinfo
+ && !kread((KA_T)v->v_specinfo, (char *)&sn, sizeof(sn)))
+ s = &sn;
+ else
+#else /* DUV>=20000 */
+# if DUV>=30000
+ if (!f)
+# endif /* DUV>=30000 */
+#endif /* DUV<20000 */
+
+ s = (struct spec_node *)v->v_data;
+ break;
+ case VT_PRFS:
+ p = (struct procnode *)v->v_data;
+ break;
+ case VT_S5FS:
+ s5 = (struct s5inode *)v->v_data;
+ break;
+ case VT_MSFS:
+ a = (struct advfsnode *)v->v_data;
+
+#if ADVFSV>=500
+ if (a->a_con
+ && !kread((KA_T)a->a_con, (char *)&fsc, sizeof(fsc)))
+ fscs = 1;
+#endif /* ADVFSV>=500 */
+
+ break;
+ case VT_UFS:
+ i = (struct inode *)v->v_data;
+ break;
+ default:
+ (void) snpf(Namech, Namechl, "unknown node type, v_tag=%d",
+ v->v_tag);
+ enter_nm(Namech);
+ return;
+ }
+/*
+ * Get device and type for printing.
+ */
+ type = v->v_type;
+ if (a) {
+ if (vfs && vfs->dev) {
+ dev = vfs->dev;
+ devs = 1;
+ }
+ if ((type == VCHR) || (type == VBLK)) {
+
+#if ADVFSV>=500
+ if (fscs) {
+ rdev = fsc.st.rdev;
+ rdevs = 1;
+ }
+#else /* ADVFSV<500 */
+ rdev = a->a_rdev;
+ rdevs = 1;
+#endif /* ADVFSV>=500 */
+
+ }
+ } else if (c) {
+ dev = c->cd_dev;
+ devs = 1;
+ }
+
+#if DUV>=50000
+ else if (cn) {
+ if (vfs && vfs->dev) {
+ dev = vfs->dev;
+ devs = 1;
+ }
+ if ((type == VCHR) || (type == VBLK)) {
+ if (cn->c_attr.va_mask & AT_RDEV) {
+ rdev = cn->c_attr.va_rdev;
+ rdevs = 1;
+ }
+ }
+ }
+#endif /* DUV>=50000 */
+
+ else if (i) {
+ if (i->i_dev) {
+ dev = i->i_dev;
+ devs = 1;
+ } else if (vfs && vfs->dev) {
+ dev = vfs->dev;
+ devs = 1;
+ }
+ if ((type == VCHR) || (type == VBLK)) {
+ rdev = i->i_din.di_db[0];
+ rdevs = 1;
+ }
+ } else if (r) {
+ dev = r->r_attr.va_fsid;
+ devs = 1;
+ if ((type == VCHR) || (type == VBLK)) {
+ rdev = r->r_attr.va_rdev;
+ rdevs = 1;
+ }
+ } else if (s) {
+ if (vfs && vfs->dev)
+ dev = vfs->dev;
+ else
+ dev = DevDev;
+ devs = 1;
+ rdev = s->sn_vattr.va_rdev;
+ rdevs = 1;
+ if (!lkupdev(&dev, &rdev, 0, 0) && HaveCloneMaj)
+ rdev = makedev(CloneMaj, GET_MAJ_DEV(rdev));
+ } else if (s5) {
+ dev = s5->i_dev;
+ devs = 1;
+ } else if (f) {
+ if (vfs && vfs->dev) {
+ dev = vfs->dev;
+ devs = 1;
+ }
+ }
+/*
+ * Obtain the inode number.
+ */
+ if (a) {
+
+#if ADVFSV>=500
+ if (fscs) {
+ Lf->inode = (INODETYPE)fsc.st.num;
+ Lf->inp_ty = 1;
+ }
+#else /* ADVFSV<500 */
+ Lf->inode = (INODETYPE)a->a_number;
+ Lf->inp_ty = 1;
+#endif /* ADVFSV>=500 */
+
+
+#if defined(HASTAGTOPATH)
+ /*
+ * Record the Digital UNIX 4.0 or greater, ADVFS 4.0 or greater
+ * ADVFS sequence number for later use with tag_to_path().
+ */
+ Lf->advfs_seq = a->a_seq;
+ Lf->advfs_seq_stat = 1;
+#endif /* defined(HASTAGTOPATH) */
+
+ } else if (c) {
+ Lf->inode = (INODETYPE)c->cd_number;
+ Lf->inp_ty = 1;
+ }
+
+#if DUV>=50000
+ else if (cn) {
+ if (cn->c_attr.va_mask & AT_NODEID) {
+ Lf->inode = (INODETYPE)cn->c_attr.va_fileid;
+ Lf->inp_ty = 1;
+ }
+ }
+#endif /* DUV>=50000 */
+
+ else if (i) {
+ Lf->inode = (INODETYPE)i->i_number;
+ Lf->inp_ty = 1;
+ } else if (p) {
+ Lf->inode = (INODETYPE)((type == VDIR) ? PR_ROOTINO
+ : p->prc_pid + PR_INOBIAS);
+ Lf->inp_ty = 1;
+ } else if (r) {
+ Lf->inode = (INODETYPE)r->r_attr.va_fileid;
+ Lf->inp_ty = 1;
+ } else if (s5) {
+ Lf->inode = (INODETYPE)s5->i_number;
+ Lf->inp_ty = 1;
+ }
+
+#if DUV>=30000
+ else if (f) {
+ Lf->inode = (INODETYPE)f->fn_fileid;
+ Lf->inp_ty = 1;
+ }
+#endif /* DUV>=30000 */
+
+/*
+ * Obtain the file size.
+ */
+ if (Foffset) {
+ Lf->off_def = 1;
+
+#if DUV>=30000
+ if (Ntype == N_FIFO && f)
+ Lf->off = (unsigned long)
+ (Lf->access == 'r') ? f->fn_rptr : f->fn_wptr;
+#endif /* DUV>=30000 */
+
+ } else {
+ switch (Ntype) {
+ case N_FIFO:
+
+#if DUV>=30000
+ if (f) {
+ Lf->sz = (SZOFFTYPE)f->fn_size;
+ Lf->sz_def = 1;
+ } else if (!Fsize)
+ Lf->off_def = 1;
+#else /* DUV<30000 */
+ if (!Fsize)
+ Lf->off_def = 1;
+#endif /* DUV>=30000 */
+
+ break;
+ case N_NFS:
+ if (r) {
+ Lf->sz = (SZOFFTYPE)r->r_attr.va_qsize;
+ Lf->sz_def = 1;
+ }
+ break;
+ case N_REGLR:
+ if (type == VREG || type == VDIR) {
+ if (a) {
+
+#if ADVFSV>=500
+ if (fscs) {
+ Lf->sz = (SZOFFTYPE)fsc.st.size;
+ Lf->sz_def = 1;
+ }
+#else /* ADVFSV<500 */
+ Lf->sz = (SZOFFTYPE)a->a_size;
+ Lf->sz_def = 1;
+#endif /* ADVFSV>=500 */
+
+ } else if (c) {
+ Lf->sz = (SZOFFTYPE)c->cd_size;
+ Lf->sz_def = 1;
+ }
+
+#if DUV>=50000
+ else if (cn) {
+ if (cn->c_attr.va_mask & AT_SIZE) {
+ Lf->sz = (SZOFFTYPE)cn->c_attr.va_qsize;
+ Lf->sz_def = 1;
+ }
+ }
+#endif /* DUV>=50000 */
+
+ else if (i) {
+ Lf->sz = (SZOFFTYPE)i->i_din.di_qsize;
+ Lf->sz_def = 1;
+ } else if (m) {
+ Lf->sz = (SZOFFTYPE)m->mfs_size;
+ Lf->sz_def = 1;
+ } else if (p) {
+ if (type != VDIR)
+ get_proc_sz(p);
+ } else if (s5) {
+ Lf->sz = (SZOFFTYPE)s5->i_size;
+ Lf->sz_def = 1;
+ }
+ } else if ((type == VBLK) || (type == VCHR) && !Fsize)
+ Lf->off_def = 1;
+ }
+ }
+ if (Fnlink) {
+ switch(Ntype) {
+ case N_FIFO: /* no link count */
+ break;
+ case N_NFS:
+ Lf->nlink = (long)r->r_attr.va_nlink;
+ Lf->nlink_def = 1;
+ break;
+ case N_REGLR:
+
+# if ADVFSV>=400
+ if (a) {
+
+#if ADVFSV>=500
+ if (fscs) {
+ Lf->nlink = (long)fsc.st.nlink;
+ Lf->nlink_def = 1;
+ }
+#else /* ADVFSV<500 */
+ Lf->nlink = (long)a->a_nlink;
+ Lf->nlink_def = 1;
+#endif /* ADVFSV>=500 */
+
+ break;
+ }
+# endif /* ADVFSV>=400 */
+
+ if (c) {
+ Lf->nlink = (long)c->cd_nlink;
+ Lf->nlink_def = 1;
+ }
+
+#if DUV>=50000
+ else if (cn) {
+ if (cn->c_attr.va_mask & AT_NLINK) {
+ Lf->nlink = (long)cn->c_attr.va_nlink;
+ Lf->nlink_def = 1;
+ }
+ }
+#endif /* DUV>=50000 */
+
+ else if (i) {
+ Lf->nlink = (long)i->i_din.di_nlink;
+ Lf->nlink_def = 1;
+ } else if (s5) {
+ Lf->nlink = (long)s5->i_nlink;
+ Lf->nlink_def = 1;
+ }
+ }
+ if (Nlink && Lf->nlink_def && (Lf->nlink < Nlink))
+ Lf->sf |= SELNLINK;
+ }
+/*
+ * Record an NFS file selection.
+ */
+ if (Ntype == N_NFS && Fnfs)
+ Lf->sf |= SELNFS;
+/*
+ * Save the device numbers and their states.
+ *
+ * Format the vnode type, and possibly the device name.
+ */
+ Lf->dev = dev;
+ Lf->dev_def = devs;
+ Lf->rdev = rdev;
+ Lf->rdev_def = rdevs;
+ switch (type) {
+ case VNON:
+ ty ="VNON";
+ break;
+ case VREG:
+ case VDIR:
+ ty = (type == VREG) ? "VREG" : "VDIR";
+ break;
+ case VBLK:
+ ty = "VBLK";
+ Ntype = N_BLK;
+ break;
+ case VCHR:
+ ty = "VCHR";
+ Ntype = N_CHR;
+ break;
+ case VLNK:
+ ty = "VLNK";
+ break;
+
+#if defined(VSOCK)
+ case VSOCK:
+ ty = "SOCK";
+ break;
+#endif /* defined(VSOCK) */
+
+ case VBAD:
+ ty = "VBAD";
+ break;
+ case VFIFO:
+ ty = "FIFO";
+
+#if DUV>=30000
+ if ((!devs || !dev) && f) {
+ vfs = (struct l_vfs *)NULL;
+ devs = Lf->dev_def = 0;
+ ul = (unsigned long)v->v_fifonode;
+ enter_dev_ch(print_kptr((KA_T)(ul&0xffffffff),(char *)NULL,0));
+ }
+#endif /* DUV>=30000 */
+
+ break;
+ default:
+ (void) snpf(Lf->type, sizeof(Lf->type), "%04o", (type & 0xfff));
+ ty = (char *)NULL;
+ }
+ if (ty)
+ (void) snpf(Lf->type, sizeof(Lf->type), "%s", ty);
+ Lf->ntype = Ntype;
+/*
+ * Save the file system names.
+ */
+ if (vfs) {
+ if (vfs->dir && *vfs->dir)
+ Lf->fsdir = vfs->dir;
+ if (vfs->fsname && *vfs->fsname)
+ Lf->fsdev = vfs->fsname;
+
+#if defined(HASFSINO)
+ if (vfs->fs_ino)
+ Lf->fs_ino = vfs->fs_ino;
+#endif /* defined(HASFSINO) */
+
+ }
+/*
+ * Handle some special cases:
+ *
+ * ioctl(fd, TIOCNOTTY) files;
+ * FIFOs (Digital UNIX V3.0 and higher);
+ * memory node files;
+ * /proc files.
+ */
+
+ if (type == VBAD)
+ (void) snpf(Namech, Namechl, "(revoked)");
+ if (m) {
+ devs = Lf->dev_def = Lf->rdev_def = rdevs = 0;
+ (void) snpf(Namech, Namechl, "%#x", m->mfs_baseoff);
+ (void) enter_dev_ch("memory");
+ } else if (p) {
+ devs = Lf->dev_def = Lf->rdev_def = rdevs = 0;
+ if (type != VDIR)
+ (void) snpf(Namech, Namechl, "/proc/%d", p->prc_pid);
+ else
+ (void) snpf(Namech, Namechl, "/proc");
+ }
+
+#if defined(HASBLKDEV)
+/*
+ * If this is a VBLK file and it's missing an inode number, try to
+ * supply one.
+ */
+ if ((Lf->inp_ty == 0) && (type == VBLK))
+ find_bl_ino();
+#endif /* defined(HASBLKDEV) */
+
+/*
+ * If this is a VCHR file and it's missing an inode number, try to
+ * supply one.
+ */
+ if ((Lf->inp_ty == 0) && (type == VCHR))
+ find_ch_ino();
+/*
+ * Test for specified file.
+ */
+ if (p) {
+ if (Procsrch) {
+ Procfind = 1;
+ Lf->sf |= SELNM;
+ } else {
+ for (pfi = Procfsid; pfi; pfi = pfi->next) {
+ if ((pfi->pid && pfi->pid == p->prc_pid)
+
+#if defined(HASPINODEN)
+ || (Lf->inp_ty == 1 && pfi->inode == Lf->inode)
+#endif /* defined(HASPINODEN) */
+
+ ) {
+ pfi->f = 1;
+ Lf->sf |= SELNM;
+ break;
+ }
+ }
+ }
+ } else {
+ if (Sfile && is_file_named((char *)NULL, (type == VCHR) ? 1 : 0))
+ Lf->sf |= SELNM;
+ }
+/*
+ * Enter name characters.
+ */
+ if (Namech[0])
+ enter_nm(Namech);
+}
+
+
+/*
+ * readvnode() - read vnode
+ */
+
+static int
+readvnode(va, v)
+ KA_T va; /* vnode kernel space address */
+ struct vnode *v; /* vnode buffer pointer */
+{
+
+ if (kread((KA_T)va, (char *)v, sizeof(struct vnode) - 1 + Vnmxp)) {
+ (void) snpf(Namech, Namechl, "can't read vnode at %s",
+ print_kptr(va, (char *)NULL, 0));
+ return(1);
+ }
+ return(0);
+}
diff --git a/dialects/du/dproc.c b/dialects/du/dproc.c
new file mode 100644
index 0000000..2b141c0
--- /dev/null
+++ b/dialects/du/dproc.c
@@ -0,0 +1,1606 @@
+/*
+ * dproc.c - DEC OSF/1, Digital UNIX, Tru64 UNIX process access functions for
+ * lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dproc.c,v 1.23 2005/08/08 19:56:44 abe Exp $";
+#endif
+
+#include "lsof.h"
+
+
+#if DUV>=50000
+# if DUV>=50100 && defined(HASNCACHE)
+#include <stddef.h>
+#include <sys/namei.h>
+#define _KERNEL 1
+#include <kern/processor.h>
+#include <nfs/nfs_clnt.h>
+#undef _KERNEL
+#include <cdfs/cdfsmount.h>
+#include <dvdfs/dvdfsmount.h>
+#include <ufs/ufsmount.h>
+# endif /* DUV>=50100 && defined(HASNCACHE) */
+_PROTOTYPE(static KA_T vpo2vp,(struct vm_ubc_object *vpo));
+#endif /* DUV>=50000 */
+
+_PROTOTYPE(static void enter_vn_text,(KA_T va, int *n));
+_PROTOTYPE(static void get_kernel_access,(void));
+
+#if DUV<30000
+_PROTOTYPE(static void process_text,(KA_T tp, KA_T utp));
+#else /* DUV>=30000 */
+_PROTOTYPE(static void process_text,(KA_T tp));
+#endif /* DUV<30000 */
+
+_PROTOTYPE(static void read_proc,(void));
+
+
+/*
+ * Local defintions
+ */
+
+#define PAPSINCR 1024 /* Pa and Ps table increment */
+#define PAPSINIT 512 /* Pa and Ps table initial size */
+
+
+/*
+ * Local static values
+ */
+
+#if DUV<30000
+static KA_T Kp; /* kernel proc[] address */
+#endif /* DUV<30000 */
+
+static int Np = 0; /* number of processes */
+static MALLOC_S Nv = 0; /* allocateed Vp[] entries */
+
+#if DUV>=30000
+static KA_T Pidtab; /* kernel pidtab[] address */
+#endif /* DUV>=30000 */
+
+static KA_T *Vp = NULL; /* vnode address cache */
+
+
+/*
+ * enter_vn_text() - enter a vnode text reference
+ */
+
+static void
+enter_vn_text(va, n)
+ KA_T va; /* vnode address */
+ int *n; /* number of vnodes in vp[] */
+{
+ int i;
+
+/*
+ * Ignore the request if the vnode has already been printed.
+ */
+ for (i = 0; i < *n; i++) {
+ if (va == Vp[i])
+ return;
+ }
+/*
+ * Print the vnode.
+ */
+ alloc_lfile(" txt", -1);
+ FILEPTR = (struct file *)NULL;
+ process_node(va);
+ if (Lf->sf)
+ link_lfile();
+ if (i >= Nv) {
+
+ /*
+ * Allocate space for remembering the vnode.
+ */
+ Nv += 10;
+ if (!Vp)
+ Vp=(KA_T *)malloc((MALLOC_S)(sizeof(KA_T) * 10));
+ else
+ Vp=(KA_T *)realloc((MALLOC_P *)Vp,(MALLOC_S)(Nv*sizeof(KA_T)));
+ if (!Vp) {
+ (void) fprintf(stderr, "%s: no txt ptr space, PID %d\n",
+ Pn, Lp->pid);
+ Exit(1);
+ }
+ }
+/*
+ * Remember the vnode.
+ */
+ Vp[*n] = va;
+ (*n)++;
+}
+
+
+/*
+ * gather_proc_info() -- gather process information
+ */
+
+void
+gather_proc_info()
+{
+ MALLOC_S b;
+ struct file *fp;
+ int i, j;
+ struct pgrp pg;
+ int pgid, px;
+ struct proc *p;
+ short pss, sf;
+ struct ucred pcred;
+ uid_t uid;
+ struct utask ut, *utp;
+
+#if DUV>=30000
+ struct pid_entry pe;
+#endif /* DUV>=30000 */
+
+#if DUV<50000
+ static int nufb = 0;
+ static struct file **ufb = (struct file **)NULL;
+#else /* DUV>=50000 */
+ int k, l;
+ KA_T ka;
+ struct ufile_entry *ofb[U_FE_OF_ALLOC_SIZE];
+ struct ufile_entry ufe[U_FE_ALLOC_SIZE];
+ struct ufile_entry ufeo[U_FE_OF_ALLOC_SIZE];
+#endif /* DUV<50000 */
+
+#if defined(HASFSTRUCT) && DUV>=40000
+ static char *pof = (char *)NULL;
+ static int pofb = 0;
+ long pv;
+#endif /* defined(HASFSTRUCT) && DUV>=40000 */
+
+/*
+ * Clear file lock information.
+ */
+ (void) clr_flinfo();
+/*
+ * Read process table entries.
+ */
+ read_proc();
+/*
+ * Examine proc structures and their associated information.
+ */
+ for (p = Ps, px = 0, utp = &ut; px < Psn; p++, px++) {
+ if (p->p_stat == 0 || p->p_stat == SZOMB)
+ continue;
+ if (Fpgid) {
+ if (!p->p_pgrp
+ || kread((KA_T)p->p_pgrp, (char *)&pg, sizeof(pg)))
+ continue;
+ pgid = pg.pg_id;
+ } else
+ pgid = 0;
+ if (p->p_rcred == NULL
+ || kread((KA_T)p->p_rcred, (char *)&pcred, sizeof(pcred)))
+ continue;
+ uid = (uid_t)pcred.cr_uid;
+ if (is_proc_excl(p->p_pid, pgid, (UID_ARG)uid, &pss, &sf))
+ continue;
+
+#if DUV<30000
+ if (!p->utask
+ || kread((KA_T)p->utask, (char *)&ut, sizeof(ut)))
+#else /* DUV>=30000 */
+ if (kread((KA_T)((char *)Pa[px] + sizeof(struct proc)),
+ (char *)&ut, sizeof(ut)))
+#endif /* DUV<30000 */
+
+ continue;
+ /*
+ * Allocate a local process structure.
+ */
+ if (is_cmd_excl(utp->u_comm, &pss, &sf))
+ continue;
+ alloc_lproc((int)p->p_pid, pgid, (int)p->p_ppid, (UID_ARG)uid,
+ utp->u_comm, (int)pss, (int)sf);
+ Plf = (struct lfile *)NULL;
+ /*
+ * Save current working directory information.
+ */
+ if (utp->uu_utnd.utnd_cdir) {
+ alloc_lfile(CWD, -1);
+ FILEPTR = (struct file *)NULL;
+ process_node((KA_T)utp->uu_utnd.utnd_cdir);
+ if (Lf->sf)
+ link_lfile();
+ }
+ /*
+ * Save root directory information.
+ */
+ if (utp->uu_utnd.utnd_rdir) {
+ alloc_lfile(RTD, -1);
+ FILEPTR = (struct file *)NULL;
+ process_node((KA_T)utp->uu_utnd.utnd_rdir);
+ if (Lf->sf)
+ link_lfile();
+ }
+ /*
+ * Print information on the text file.
+ */
+
+#if DUV<30000
+ if (p->task)
+ process_text((KA_T)p->task, (KA_T)p->utask);
+#else /* DUV>=30000 */
+ process_text((KA_T)((char *)Pa[px] - sizeof(struct task)));
+#endif /* DUV<30000 */
+
+ /*
+ * Save information on file descriptors.
+ */
+
+#if DUV<50000
+ for (i = j = 0; i <= utp->uu_file_state.uf_lastfile; i++) {
+ if (i < NOFILE_IN_U) {
+ fp = utp->uu_file_state.uf_ofile[i];
+
+# if defined(HASFSTRUCT) && DUV>=40000
+ if (Fsv & FSV_FG)
+ pv = (long)utp->uu_file_state.uf_pofile[i];
+# endif /* defined(HASFSTRUCT) && DUV>=40000 */
+
+ } else {
+ if (!j) {
+ b = (MALLOC_S)(utp->uu_file_state.uf_of_count
+ * sizeof(struct file *));
+ if (b > nufb) {
+ if (!ufb)
+ ufb = (struct file **)malloc(b);
+ else
+ ufb = (struct file **)realloc((MALLOC_P *)ufb,
+ b);
+ if (!ufb) {
+ (void) fprintf(stderr,
+ "%s: PID %d, no file * space\n",
+ Pn, Lp->pid);
+ Exit(1);
+ }
+ nufb = b;
+ }
+ if (kread((KA_T)utp->uu_file_state.uf_ofile_of,
+ (char *)ufb, b))
+ break;
+
+# if defined(HASFSTRUCT) && DUV>=40000
+ if (Fsv & FSV_FG) {
+ b = (MALLOC_S)(utp->uu_file_state.uf_of_count
+ * sizeof(char));
+ if (b > pofb) {
+ if (!pof)
+ pof = (char *)malloc(b);
+ else
+ pof = (char *)realloc((MALLOC_P *)pof, b);
+ if (!pof) {
+ (void) fprintf(stderr,
+ "%s: PID %d: no file flags space\n",
+ Pn, Lp->pid);
+ Exit(1);
+ }
+ pofb = b;
+ }
+ if (kread((KA_T)utp->uu_file_state.uf_pofile_of,
+ pof, b))
+ zeromem(pof, b);
+ }
+# endif /* defined(HASFSTRUCT) && DUV>=40000 */
+
+ }
+ fp = ufb[j];
+
+# if defined(HASFSTRUCT) && DUV>=40000
+ if (Fsv & FSV_FG)
+ pv = pof[j];
+# endif /* defined(HASFSTRUCT) && DUV>=40000 */
+
+ j++;
+ }
+ if (fp && (ulong)fp != 0xffffffffffffffff) {
+ alloc_lfile(NULL, i);
+ process_file((KA_T)fp);
+ if (Lf->sf) {
+
+# if defined(HASFSTRUCT) && DUV>=40000
+ if (Fsv & FSV_FG) {
+ if ((Lf->pof = pv))
+ Lf->fsv |= FSV_FG;
+ }
+# endif /* defined(HASFSTRUCT) && DUV>=40000 */
+
+ link_lfile();
+ }
+ }
+ }
+#else /* DUV>=50000 */
+ for (i = j = k = 0; i <= utp->uu_file_state.uf_lastfile; i++) {
+ if (i < NOFILE_IN_U) {
+ if (!k) {
+ l = i/U_FE_ALLOC_SIZE;
+ if (!(ka = (KA_T)utp->uu_file_state.uf_entry[l])) {
+ i += U_FE_ALLOC_SIZE - 1;
+ continue;
+ }
+ }
+ } else {
+ if (!j) {
+ ka = (KA_T)utp->uu_file_state.uf_of_entry;
+ if (!ka || kread(ka, (char *)&ofb, sizeof(ofb)))
+ break;
+ k = 0;
+ }
+ if (!k) {
+ l = j/U_FE_OF_ALLOC_SIZE;
+ if (!(ka = (KA_T)ofb[l])) {
+ j += U_FE_OF_ALLOC_SIZE;
+ i += U_FE_OF_ALLOC_SIZE - 1;
+ continue;
+ }
+ if (kread(ka, (char *)&ufeo, sizeof(ufeo)))
+ break;
+ }
+ fp = ufeo[k].ufe_ofile;
+
+# if defined(HASFSTRUCT) && DUV>=40000
+ if (Fsv & FSV_FG)
+ pv = ufeo[k].ufe_oflags;
+# endif /* defined(HASFSTRUCT) && DUV>=40000 */
+
+ if (++k >= U_FE_OF_ALLOC_SIZE)
+ k = 0;
+ j++;
+ }
+ if (!j) {
+ if (!k) {
+ if (kread(ka, (char *)&ufe, sizeof(ufe)))
+ break;
+ }
+ fp = ufe[k].ufe_ofile;
+
+# if defined(HASFSTRUCT) && DUV>=40000
+ if (Fsv & FSV_FG)
+ pv = ufe[k].ufe_oflags;
+# endif /* defined(HASFSTRUCT) && DUV>=40000 */
+
+ if (++k >= U_FE_ALLOC_SIZE)
+ k = 0;
+ }
+ if (fp && (ulong)fp != 0xffffffffffffffff) {
+ alloc_lfile(NULL, i);
+ process_file((KA_T)fp);
+ if (Lf->sf) {
+
+# if defined(HASFSTRUCT) && DUV>=40000
+ if (Fsv & FSV_FG) {
+ if ((Lf->pof = pv))
+ Lf->fsv |= FSV_FG;
+ }
+# endif /* defined(HASFSTRUCT) && DUV>=40000 */
+
+ link_lfile();
+ }
+ }
+ }
+#endif /* DUV>=50000 */
+
+ /*
+ * Examine results.
+ */
+ if (examine_lproc())
+ return;
+ }
+}
+
+
+/*
+ * get_kernel_access() - get access to kernel memory
+ */
+
+static void
+get_kernel_access()
+{
+ dev_t dev;
+ int rv;
+ KA_T v;
+/*
+ * Check kernel version.
+ */
+ (void) ckkv("DU", LSOF_VSTR, (char *)NULL, (char *)NULL);
+/*
+ * Set name list file path.
+ */
+
+#if DUV<40000
+ if (!Nmlst) {
+ if (!(Nmlst = get_nlist_path(1))) {
+ (void) fprintf(stderr, "%s: can't get kernel name list path\n",
+ Pn);
+ Exit(1);
+ }
+ }
+#endif /* DUV<40000 */
+
+#if defined(WILLDROPGID)
+/*
+ * If kernel memory isn't coming from KMEM, drop setgid permission
+ * before attempting to open the (Memory) file.
+ */
+ if (Memory)
+ (void) dropgid();
+#else /* !defined(WILLDROPGID) */
+/*
+ * See if the non-KMEM memory file is readable.
+ */
+ if (Memory && !is_readable(Memory, 1))
+ Exit(1);
+#endif /* defined(WILLDROPGID) */
+
+/*
+ * Open kernel memory access.
+ */
+ if ((Kd = open(Memory ? Memory : KMEM, O_RDONLY, 0)) < 0) {
+ (void) fprintf(stderr, "%s: can't open %s: %s\n", Pn,
+ Memory ? Memory : KMEM, sys_errlist[errno]);
+ Exit(1);
+ }
+
+#if defined(WILLDROPGID)
+/*
+ * Drop setgid permission, if necessary.
+ */
+ if (!Memory)
+ (void) dropgid();
+#else /* !defined(WILLDROPGID) */
+/*
+ * See if the name list file is readable.
+ */
+ if (Nmlst && !is_readable(Nmlst, 1))
+ Exit(1);
+#endif /* defined(WILLDROPGID) */
+
+/*
+ * Access kernel symbols.
+ */
+ (void) build_Nl(Drive_Nl);
+
+#if DUV>=40000
+ if (!Nmlst)
+ rv = knlist(Nl);
+ else
+#endif /* DUV>=40000 */
+
+ rv = nlist(Nmlst, Nl);
+ if (rv == -1) {
+ (void) fprintf(stderr,
+ "%s: can't read kernel name list from %s: %s\n",
+ Pn, Nmlst ? Nmlst : "knlist(3)", strerror(errno));
+ Exit(1);
+ }
+
+#if DUV<30000
+ if (get_Nl_value("proc", Drive_Nl, &v) < 0 || !v
+ || kread(v, (char *)&Kp, sizeof(Kp))
+ || get_Nl_value("nproc", Drive_Nl, &v) < 0 || !v
+ || kread(v, (char *)&Np, sizeof(Np)))
+#else /* DUV>=30000 */
+ if (get_Nl_value("npid", Drive_Nl, &v) < 0 || !v
+ || kread(v, (char *)&Np, sizeof(Np))
+ || get_Nl_value("pidt", Drive_Nl, &v) < 0 || !v
+ || kread(v, (char *)&Pidtab, sizeof(Pidtab)))
+#endif /* DUV<30000 */
+
+ {
+ (void) fprintf(stderr, "%s: can't read proc table info\n", Pn);
+ Exit(1);
+ }
+ if (get_Nl_value("vnmaxp", Drive_Nl, &v) < 0 || !v
+ || kread(v, (char *)&Vnmxp, sizeof(Vnmxp))) {
+ (void) fprintf(stderr, "%s: can't determine vnode length\n", Pn);
+ Exit(1);
+ }
+ if (get_Nl_value("cldev", Drive_Nl, &v) < 0 || !v
+ || kread(v, (char *)&dev, sizeof(dev))) {
+ if (!Fwarn)
+ (void) fprintf(stderr, "%s: can't read clone device number\n",
+ Pn);
+ HaveCloneMaj = 0;
+ } else {
+ CloneMaj = GET_MAJ_DEV(dev);
+ HaveCloneMaj = 1;
+ }
+}
+
+
+/*
+ * get_nlist_path() - get kernel name list path
+ */
+
+char *
+get_nlist_path(ap)
+ int ap; /* on success, return an allocated path
+ * string pointer if 1; return a
+ * constant character pointer if 0;
+ * return NULL if failure */
+{
+ char *ba, buf[MAXPATHLEN+2], *ps;
+ int len, rv;
+/*
+ * Get bootfile name.
+ */
+ len = 0;
+ if ((rv = getsysinfo(GSI_BOOTEDFILE, &buf[1], sizeof(buf) - 1, &len,
+ (char *)NULL))
+ != 1)
+ {
+ if (rv < 0) {
+ (void) fprintf(stderr, "%s: can't get booted file name: %s\n",
+ Pn, strerror(errno));
+ Exit(1);
+ }
+ return((char *)NULL);
+ }
+/*
+ * Check for a non-NULL path.
+ */
+ buf[sizeof(buf) - 2] = '\0';
+ len = strlen(&buf[1]);
+ if (len < 1)
+ return((char *)NULL);
+/*
+ * If no path return is requested by the value of ap, return a NULL string
+ * pointer.
+ */
+ if (!ap)
+ return("");
+/*
+ * Make sure the path has a leading '/'.
+ */
+ if (buf[1] != '/') {
+ buf[0] = '/';
+ ba = buf;
+ len++;
+ } else
+ ba = &buf[1];
+/*
+ * Allocate permanent space for the path, copy it to the space, and return
+ * a pointer to the space.
+ */
+ len++;
+ if (!(ps = (char *)malloc(len))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d bytes for boot file path: %s\n",
+ Pn, len, ba);
+ Exit(1);
+ }
+ (void) snpf(ps, len, "%s", ba);
+ return(ps);
+}
+
+
+/*
+ * initialize() - perform all initialization
+ */
+
+void
+initialize()
+{
+ get_kernel_access();
+}
+
+
+/*
+ * kread() - read from kernel memory
+ */
+
+int
+kread(addr, buf, len)
+ KA_T addr; /* kernel memory address */
+ char *buf; /* buffer to receive data */
+ READLEN_T len; /* length to read */
+{
+ int br;
+
+ if (lseek(Kd, addr, L_SET) == (off_t)-1L)
+ return(-1);
+ br = read(Kd, buf, len);
+ return((br == len) ? 0 : 1);
+}
+
+
+/*
+ * process_text() - print text information
+ */
+static void
+
+#if DUV<30000
+process_text(tp, utp)
+#else /* DUV>=30000 */
+process_text(tp)
+#endif /* DUV<30000 */
+
+ KA_T tp; /* kernel task structure */
+
+#if DUV<30000
+ KA_T utp; /* user task structure address for
+ * the task */
+#endif /* DUV<30000 */
+
+{
+ int i;
+ KA_T ka, kb;
+ int n = 0;
+ struct task t;
+ struct vm_anon_object vmao;
+ struct vm_map_entry vmme;
+ struct vm_map vmm;
+ struct vm_object vmo;
+ struct vm_seg vms;
+
+#if DUV<40000
+ struct vm_vp_object vpo;
+#else /* DUV>=40000 */
+ struct vm_ubc_object vpo;
+#endif /* DUV<40000 */
+
+/*
+ * Read task structure from kernel.
+ */
+ if (kread(tp, (char *)&t, sizeof(t))
+
+#if DUV<30000
+ || (KA_T)t.u_address != utp
+#endif /* DUV<30000 */
+
+ )
+ return;
+/*
+ * Print information about the text vnode referenced in the procfs
+ * structure inside the task structure.
+ */
+ if (t.procfs.pr_exvp)
+ enter_vn_text((KA_T)t.procfs.pr_exvp, &n);
+/*
+ * Read the vm_map structure. Search its vm_map_entry structure list.
+ */
+ if (!t.map
+ || kread((KA_T)t.map, (char *)&vmm, sizeof(vmm)))
+ return;
+ if (!vmm.vm_is_mainmap)
+ return;
+
+#if defined(VM_SKIPLIST)
+ for (i = 0, ka = (KA_T)vmm.vm_links.vml_sl_next[0];
+ i < vmm.vm_nentries && ka != (KA_T)t.map;
+ i++, ka = (KA_T)vmme.vme_links.vml_sl_next[0])
+#else /* !defined(VM_SKIPLIST) */
+ for (i = 0, ka = (KA_T)vmm.vm_links.next;
+ i < vmm.vm_nentries && ka != (KA_T)t.map;
+ i++, ka = (KA_T)vmme.vme_links.next)
+#endif /* defined(VM_SKIPLIST) */
+
+ {
+
+ /*
+ * Read the next vm_map_entry structure and its object.
+ */
+ if (kread(ka, (char *)&vmme, sizeof(vmme)))
+ return;
+ if (!(kb = (KA_T)vmme.vme_uobject.vm_object)
+ || kread(kb, (char *)&vmo, sizeof(vmo)))
+ continue;
+ /*
+ * Process by object type.
+ */
+ switch (vmo.ob_type) {
+ case OT_ANON:
+
+ /*
+ * If an anonymous object is backed by an OT_UBC or OT_VP object,
+ * read its vm_ubc_object or vm_vp_object to find a vnode pointer.
+ */
+ if (kread(kb, (char *)&vmao, sizeof(vmao)))
+ break;
+ if (!vmao.ao_bobject
+ || kread((KA_T)vmao.ao_bobject, (char *)&vmo, sizeof(vmo)))
+ break;
+
+#if DUV<40000
+ if (vmo.ob_type != OT_VP
+ || kread((KA_T)vmao.ao_bobject, (char *)&vpo, sizeof(vpo)))
+ break;
+ enter_vn_text((KA_T)vpo.vo_vp, &n);
+#else /* DUV>=40000 */
+ if (vmo.ob_type != OT_UBC
+ || kread((KA_T)vmao.ao_bobject, (char *)&vpo, sizeof(vpo)))
+ break;
+# if DUV>=50000
+ enter_vn_text(vpo2vp(&vpo), &n);
+# else /* DUV<50000 */
+ enter_vn_text((KA_T)vpo.vu_vfp.vp, &n);
+#endif /* DUV>=50000 */
+#endif /* DUV<40000 */
+ break;
+ /*
+ * If this is a segment object, read the segment map, and search
+ * for backing objects whose object type is OT_UBC or OT_VP.
+ */
+
+ case OT_SEG:
+ for (kb=(KA_T)vmme.vme_seg; kb; kb=(KA_T)vms.seg_vnext) {
+ if (kread(kb, (char *)&vms, sizeof(vms)))
+ break;
+ if (!vms.seg_vop
+ || kread((KA_T)vms.seg_vop, (char *)&vmo, sizeof(vmo)))
+ continue;
+
+#if DUV<40000
+ if (vmo.ob_type != OT_VP)
+#else /* DUV>=40000 */
+ if (vmo.ob_type != OT_UBC)
+#endif /* DUV<40000 */
+
+ continue;
+ if (kread((KA_T)vms.seg_vop, (char *)&vpo, sizeof(vpo)))
+ break;
+
+#if DUV<40000
+ enter_vn_text((KA_T)vpo.vo_vp, &n);
+#else /* DUV>=40000 */
+# if DUV>=50000
+ enter_vn_text(vpo2vp(&vpo), &n);
+# else /* DUV<50000 */
+ enter_vn_text((KA_T)vpo.vu_vfp.vp, &n);
+#endif /* DUV<40000 */
+#endif /* DUV>=50000 */
+
+ }
+ }
+ }
+}
+
+
+/*
+ * read_proc() - read process table entries
+ */
+
+static void
+read_proc()
+{
+ static int ap = 0;
+ MALLOC_S len;
+ struct proc *p;
+ KA_T pa;
+ int px, try;
+
+#if DUV>=30000
+ struct pid_entry pe;
+#endif /* DUV>=30000 */
+
+ if (!Ps) {
+
+ /*
+ * Allocate local proc table space.
+ */
+ if (Np < 1) {
+ (void) fprintf(stderr, "%s: proc table has no entries\n", Pn);
+ Exit(1);
+ }
+ len = (MALLOC_S)(PAPSINIT * sizeof(struct proc));
+ if (!(Ps = (struct proc *)malloc(len))) {
+ (void) fprintf(stderr, "%s: no proc table space (%d bytes)\n",
+ Pn, len);
+ Exit(1);
+ }
+
+#if DUV>=30000
+ /*
+ * Allocate kernel proc address table space.
+ */
+ len = (MALLOC_S)(PAPSINIT * sizeof(KA_T));
+ if (!(Pa = (KA_T *)malloc(len))) {
+ (void) fprintf(stderr,
+ "%s: no proc address table space (%d bytes)\n", Pn, len);
+ Exit(1);
+ }
+#endif /* DUV>=30000 */
+
+ ap = PAPSINIT;
+ }
+/*
+ * Try to read the proc structure table PROCTRYLM times.
+ * The operation must yield PROCMIN structures.
+ */
+ for (try = 0; try < PROCTRYLM; try++) {
+ for (p = Ps, Psn = px = 0; px < Np; px++) {
+
+ /*
+ * Insure Ps and Psa space.
+ */
+ if (Psn >= ap) {
+ ap += PAPSINCR;
+ len = (MALLOC_S)(ap * sizeof(struct proc));
+ if (!(Ps = (struct proc *)realloc((MALLOC_P *)Ps, len))) {
+ (void) fprintf(stderr,
+ "%s: no more proc table space (%d bytes)\n",
+ Pn, len);
+ Exit(1);
+ }
+ p = &Ps[Psn];
+
+#if DUV>=30000
+ len = (MALLOC_S)(ap * sizeof(KA_T));
+ if (!(Pa = (KA_T *)realloc((MALLOC_P *)Pa, len))) {
+ (void) fprintf(stderr,
+ "%s: no more proc address table space (%d bytes)\n",
+ Pn, len);
+ Exit(1);
+ }
+#endif /* DUV>=30000 */
+
+ }
+
+#if DUV<30000
+ pa = Kp + (KA_T)(px * sizeof(struct proc));
+ if (kread(pa, (char *)p, sizeof(struct proc)))
+ continue;
+#else /* DUV>=30000 */
+ pa = Pidtab + (KA_T)(px * sizeof(struct pid_entry));
+ if (kread(pa, (char *)&pe, sizeof(struct pid_entry)))
+ continue;
+ if ((pa = (KA_T)pe.pe_proc) == NULL
+ || kread(pa, (char *)p, sizeof(struct proc)))
+ continue;
+ if (pe.pe_pid != p->p_pid)
+ continue;
+ Pa[Psn] = pa;
+#endif /* DUV<30000 */
+
+ Psn++;
+ p++;
+ }
+ /*
+ * Check the results of the scan.
+ */
+ if (Psn >= PROCMIN)
+ break;
+ }
+/*
+ * Quit if not enough proc structures could be accumulated.
+ */
+ if (try >= PROCTRYLM) {
+ (void) fprintf(stderr, "%s: can't read proc table\n", Pn);
+ Exit(1);
+ }
+ if (Psn < Np && !RptTm) {
+
+ /*
+ * Reduce the local proc structure tables to their minimum if
+ * not in repeat mode.
+ */
+ ap = Psn;
+ len = (MALLOC_S)(Psn * sizeof(struct proc));
+ if (!(Ps = (struct proc *)realloc((MALLOC_P *)Ps, len))) {
+ (void) fprintf(stderr,
+ "%s: can't reduce proc table to %d bytes\n",
+ Pn, len);
+ Exit(1);
+ }
+
+#if DUV>=30000
+ len = (MALLOC_S)(Psn * sizeof(KA_T));
+ if (!(Pa = (KA_T *)realloc((MALLOC_P *)Pa, len))) {
+ (void) fprintf(stderr,
+ "%s: can't reduce proc address table to %d bytes\n",
+ Pn, len);
+ Exit(1);
+ }
+#endif /* DUV>=30000 */
+
+ }
+}
+
+
+#if DUV>=50000
+/*
+ * vfp2vp() -- convert VM object's vu_vfp to a vnode pointer
+ */
+
+static KA_T
+vpo2vp(vpo)
+ struct vm_ubc_object *vpo; /* pointer to local vm_ubc_object */
+{
+ struct advfsbfs { /* This structure is referenced in
+ * vm_ubc.h (as msfsbfs), but never
+ * defined in a distributed header
+ * file, so we make a hack definition
+ * here. */
+ unsigned long d1[18]; /* dummies */
+ struct vnode *vp; /* vnode */
+ } bfa;
+ static int ft = 1;
+ KA_T ka;
+ static KA_T ops = (KA_T)0;
+/*
+ * If this is the first time, get the msfs (AdvFS) UBC operation switch
+ * address.
+ */
+ if (ft) {
+ ft = 0;
+
+#if defined(ADVFSV)
+ if (get_Nl_value("msfsubc", Drive_Nl, &ops) < 0)
+#endif /* defined(ADVFSV) */
+
+ ops = (KA_T)0;
+
+ }
+ ka = (KA_T)vpo->vu_vfp.vp;
+ if (!ops || ((KA_T)vpo->vu_ops != ops))
+ return(ka);
+ if (!ka || kread(ka, (char *)&bfa, sizeof(bfa)))
+ return(ka);
+ return((KA_T)bfa.vp);
+}
+#endif /* DUV>=50000 */
+
+
+#if DUV>=50100 && defined(HASNCACHE)
+/*
+ * Kernel name cache functions and associate definiitions for Tru64 UNIX
+ * 5.1 and above.
+ */
+
+
+/*
+ * Definitions
+ */
+
+
+/*
+ * Structures
+ */
+
+struct l_nch {
+ struct namecache *nc; /* namecache entry */
+ struct l_nch *nxt; /* next hashed entry */
+};
+
+
+/*
+ * Static variables
+ */
+
+static int Hmsk = 0; /* Nchash[] mask -- (size - 1), where
+ * size is a power of two */
+static int Nc; /* number of cached namecache structs */
+static struct l_nch **Nchash = (struct l_nch **)NULL;
+ /* hash pointers buckets */
+static int Ncfirst = 1; /* first-call status */
+
+/*
+ * Definitions
+ */
+
+#define ncachehash(i) (((int)(i*31415)>>3)&Hmsk)
+
+
+/*
+ * Prototypes
+ */
+
+_PROTOTYPE(static struct l_nch *ncache_addr,(unsigned long id));
+_PROTOTYPE(static int ncache_ckrootid,(KA_T na, unsigned long id));
+_PROTOTYPE(static int ncache_isroot,(KA_T na, char *cp));
+
+
+/*
+ * ncache_addr() -- look up a node's local ncache address
+ */
+
+static struct l_nch *
+ncache_addr(id)
+ unsigned long id; /* node's capability ID */
+{
+ register struct l_nch *hp;
+
+ for (hp = Nchash[ncachehash(id)]; hp; hp = hp->nxt) {
+ if ((hp->nc)->nc_vpid == id)
+ return(hp);
+ }
+ return((struct l_nch *)NULL);
+}
+
+
+/*
+ * ncache_ckrootid() - check for a root node ID
+ */
+
+static int
+ncache_ckrootid(na, id)
+ KA_T na; /* vnode address */
+ unsigned long id; /* root ID to check */
+{
+
+#if defined(ADVFSV)
+ struct advfsmount { /* This structure should be defined in
+ * a distributed header file, but it
+ * isn't, so we make a hack definition
+ * here. */
+ u_long d1[10]; /* dummies */
+ struct vnode *am_rootvp; /* root vnode pointer */
+ } am;
+ static KA_T aops = (KA_T)0;
+#endif /* defined(ADVFSV) */
+
+ struct cdfsmount cm;
+ static KA_T cops = (KA_T)0;
+ struct dvdfsmount dm;
+ static KA_T dops = (KA_T)0;
+ static KA_T fops = (KA_T)0;
+ static KA_T frvp = (KA_T)0;
+ static int ft = 1;
+ register int i;
+ static unsigned long *ic = (unsigned long *)NULL;
+ MALLOC_S len;
+ struct mount m;
+ static int nia = 0;
+ static int niu = 0;
+ struct mntinfo nm;
+ static KA_T nops = (KA_T)0;
+ static KA_T n3ops = (KA_T)0;
+ KA_T rv;
+ struct ufsmount um;
+ static KA_T uops = (KA_T)0;
+ struct vnode v;
+/*
+ * Check the cache.
+ */
+ if (ic && niu) {
+ for (i = 0; i < niu; i++) {
+ if (id == ic[i])
+ return(1);
+ }
+ }
+/*
+ * Read the vnode and the associated mount structure.
+ */
+ if (!na || kread(na, (char *)&v, sizeof(v)))
+ return(0);
+ if (!v.v_mount || kread((KA_T)v.v_mount, (char *)&m, sizeof(m)))
+ return(0);
+/*
+ * If this is the first time this function has been used, get the necessary
+ * kernel addresses.
+ */
+ if (ft) {
+ ft = 0;
+
+#if defined(ADVFSV)
+ if (get_Nl_value("advfsvfs", (struct drive_Nl *)NULL, &aops) < 0)
+ aops = (KA_T)0;
+#endif /* defined(ADVFSV) */
+
+ if (get_Nl_value("cdfsvfs", (struct drive_Nl *)NULL, &cops) < 0)
+ cops = (KA_T)0;
+ if (get_Nl_value("dvdfsvfs", (struct drive_Nl *)NULL, &dops) < 0)
+ dops = (KA_T)0;
+ if (get_Nl_value("fdfsvfs", (struct drive_Nl *)NULL, &fops) < 0)
+ fops = (KA_T)0;
+ if (get_Nl_value("fsfsrvp", (struct drive_Nl *)NULL, &frvp) < 0)
+ frvp = (KA_T)0;
+ if (get_Nl_value("nfsvfs", (struct drive_Nl *)NULL, &nops) < 0)
+ nops = (KA_T)0;
+ if (get_Nl_value("nfs3vfs", (struct drive_Nl *)NULL, &n3ops) < 0)
+ n3ops = (KA_T)0;
+ if (get_Nl_value("ufsvfs", (struct drive_Nl *)NULL, &uops) < 0)
+ uops = (KA_T)0;
+ }
+/*
+ * See if we know how to find the root vnode pointer for this file system
+ * type.
+ */
+
+#if defined(ADVFSV)
+ if (aops && (aops == (KA_T)m.m_op)) {
+
+ /*
+ * Set AdvFS (MSFS) root vnode address.
+ */
+ if (!m.m_info || kread((KA_T)m.m_info, (char *)&am, sizeof(am)))
+ return(0);
+ rv = (KA_T)am.am_rootvp;
+ } else
+#endif /* defined(ADVFSV) */
+
+ if (cops && (cops == (KA_T)m.m_op)) {
+
+ /*
+ * Set CDFS root vnode address.
+ */
+ if (!m.m_info || kread((KA_T)m.m_info, (char *)&cm, sizeof(cm)))
+ return(0);
+ rv = (KA_T)cm.um_rootvp;
+ } else if (dops && (dops == (KA_T)m.m_op)) {
+
+ /*
+ * Set DVDFS root vnode address.
+ */
+ if (!m.m_info || kread((KA_T)m.m_info, (char *)&dm, sizeof(dm)))
+ return(0);
+ rv = (KA_T)dm.dm_rootvp;
+ } else if (fops && (fops == (KA_T)m.m_op)) {
+
+ /*
+ * Set FDFS root vnode address.
+ */
+ rv = frvp;
+ } else if ((nops && (nops == (KA_T)m.m_op))
+ || (n3ops && (n3ops == (KA_T)m.m_op)))
+ {
+
+ /*
+ * Set NFS[3] root vnode address.
+ */
+ if (!m.m_info || kread((KA_T)m.m_info, (char *)&nm, sizeof(nm)))
+ return(0);
+ rv = (KA_T)nm.mi_rootvp;
+ } else if (uops && (uops == (KA_T)m.m_op)) {
+
+ /*
+ * Set UFS root vnode address.
+ */
+ if (!m.m_info || kread((KA_T)m.m_info, (char *)&um, sizeof(um)))
+ return(0);
+ rv = (KA_T)um.um_rootvp;
+ } else
+ return(0);
+/*
+ * Read the root vnode.
+ */
+ if (!rv || kread(rv, (char *)&v, sizeof(v)))
+ return(0);
+ if (id != v.v_id)
+ return(0);
+/*
+ * A new root vnode has been located. Cache it.
+ */
+ if (niu >= nia) {
+ if (!nia) {
+ len = (MALLOC_S)(10 * sizeof(unsigned long));
+ ic = (unsigned long *)malloc(len);
+ } else {
+ len = (MALLOC_S)((nia + 10) * sizeof(unsigned long));
+ ic = (unsigned long *)realloc((MALLOC_P *)ic, len);
+ }
+ if (!ic) {
+ (void) fprintf(stderr,
+ "%s: no space for root node VPID table\n", Pn);
+ Exit(1);
+ }
+ nia += 10;
+ }
+ ic[niu++] = id;
+ return(1);
+}
+
+
+/*
+ * ncache_isroot() - is head of name cache path a file system root?
+ */
+
+static int
+ncache_isroot(na, cp)
+ KA_T na; /* vnode address */
+ char *cp; /* partial path */
+{
+ char buf[MAXPATHLEN];
+ int i;
+ MALLOC_S len;
+ struct mounts *mtp;
+ static KA_T *nc = (KA_T *)NULL;
+ static int nca = 0;
+ static int ncn = 0;
+ struct stat sb;
+ struct vnode v;
+
+ if (!na)
+ return(0);
+/*
+ * Search the root capability node address cache.
+ */
+ for (i = 0; i < ncn; i++) {
+ if (na == nc[i])
+ return(1);
+ }
+/*
+ * Read the vnode and see if it's a VDIR node with the VROOT flag set. If
+ * it is, then the path is complete.
+ *
+ * If it isn't, and if the file has an inode number, search the mount table
+ * and see if the file system's inode number is known. If it is, form the
+ * possible full path, safely stat() it, and see if it's inode number matches
+ * the one we have for this file. If it does, then the path is complete.
+ */
+ if (kread((KA_T)na, (char *)&v, sizeof(v))
+ || v.v_type != VDIR || !(v.v_flag & VROOT)) {
+
+ /*
+ * The vnode tests failed. Try the inode tests.
+ */
+ if (Lf->inp_ty != 1 || !Lf->inode
+ || !Lf->fsdir || (len = strlen(Lf->fsdir)) < 1)
+ return(0);
+ if ((len + 1 + strlen(cp) + 1) > sizeof(buf))
+ return(0);
+ for (mtp = readmnt(); mtp; mtp = mtp->next) {
+ if (!mtp->dir || !mtp->inode)
+ continue;
+ if (strcmp(Lf->fsdir, mtp->dir) == 0)
+ break;
+ }
+ if (!mtp)
+ return(0);
+ (void) strcpy(buf, Lf->fsdir);
+ if (buf[len - 1] != '/')
+ buf[len++] = '/';
+ (void) strcpy(&buf[len], cp);
+ if (statsafely(buf, &sb) != 0
+ || (INODETYPE)sb.st_ino != Lf->inode)
+ return(0);
+ }
+/*
+ * Add the capability ID to the root capability ID cache.
+ */
+ if (ncn >= nca) {
+ if (!nca) {
+ len = (MALLOC_S)(10 * sizeof(KA_T));
+ nc = (KA_T *)malloc(len);
+ } else {
+ len = (MALLOC_S)((nca + 10) * sizeof(KA_T));
+ nc = (KA_T *)realloc((MALLOC_P *)nc, len);
+ }
+ if (!nc) {
+ (void) fprintf(stderr,
+ "%s: no space for root node address table\n", Pn);
+ Exit(1);
+ }
+ nca += 10;
+ }
+ nc[ncn++] = na;
+ return(1);
+}
+
+
+/*
+ * ncache_load() - load the kernel's name cache
+ */
+
+void
+ncache_load()
+{
+ register int h, i, n;
+ KA_T ka, ncp;
+ int len;
+ register struct l_nch *lp;
+ struct l_nch *lpnxt;
+ static struct namecache *nc = (struct namecache *)NULL;
+ static int ncl = 0;
+ static int nchsz = 0;
+ static int ncpc = 0;
+ static int ncpus = 0;
+ register struct namecache *np;
+ static KA_T *pp = (KA_T *)NULL;
+
+ if (!Fncache)
+ return;
+ if (Ncfirst) {
+
+ /*
+ * Do startup (first-time) functions.
+ */
+ Ncfirst = 0;
+ /*
+ * Get CPU count.
+ */
+ ka = (KA_T)0;
+ if (get_Nl_value("ncpus", (struct drive_Nl *)NULL, &ka) < 0
+ || !ka
+ || kread(ka, (char *)&ncpus, sizeof(ncpus)))
+ {
+ if (!Fwarn)
+ (void) fprintf(stderr,
+ "%s: WARNING: can't read processor count: %s\n",
+ Pn, print_kptr(ka, (char *)NULL, 0));
+ ncl = nchsz = ncpc = ncpus = 0;
+ return;
+ }
+ if (ncpus < 1) {
+ if (!Fwarn)
+ (void) fprintf(stderr,
+ "%s: WARNING: processor count: %d\n", Pn, ncpus);
+ ncl = nchsz = ncpc = ncpus = 0;
+ return;
+ }
+ /*
+ * Get the per-processor table address.
+ */
+ ka = (KA_T)0;
+ if (get_Nl_value("procptr", (struct drive_Nl *)NULL, &ka) < 0
+ || !ka
+ || kread(ka, (char *)&ka, sizeof(ka))
+ || !ka)
+ {
+ if (!Fwarn)
+ (void) fprintf(stderr,
+ "%s: WARNING: per processor table address: %s\n",
+ Pn, print_kptr(ka, (char *)NULL, 0));
+ ncl = nchsz = ncpc = ncpus = 0;
+ return;
+ }
+ /*
+ * Allocate space for the processor structure addresses and read them.
+ */
+ len = (int)(ncpus * sizeof(KA_T));
+ if (!(pp = (KA_T *)malloc((MALLOC_S)len))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d bytes for processor addresses\n",
+ Pn, len);
+ Exit(1);
+ }
+ if (kread(ka, (char *)pp, len)) {
+ if (!Fwarn)
+ (void) fprintf(stderr,
+ "%s: WARNING: can't read processor addresses: %s\n",
+ Pn, print_kptr(ka, (char *)NULL, 0));
+ ncl = nchsz = ncpc = ncpus = 0;
+ return;
+ }
+ for (i = 0; i < ncpus; i++) {
+ if (pp[i])
+ pp[i] = (KA_T)((char *)pp[i]
+ + offsetof(struct processor, namecache));
+ }
+ /*
+ * Get the per-processor nchash size.
+ */
+ ka = (KA_T)0;
+ if (get_Nl_value("nchsz", (struct drive_Nl *)NULL, &ka) < 0
+ || !ka
+ || kread((KA_T)ka, (char *)&nchsz, sizeof(nchsz)))
+ {
+ if (!Fwarn)
+ (void) fprintf(stderr,
+ "%s: WARNING: processor nchash count address: %s\n",
+ Pn, print_kptr(ka, (char *)NULL, 0));
+ ncl = nchsz = ncpc = ncpus = 0;
+ return;
+ }
+ if (nchsz < 1) {
+ if (!Fwarn)
+ (void) fprintf(stderr,
+ "%s: WARNING: bad per processor nchash count: %d\n",
+ Pn, nchsz);
+ nchsz = ncpus = 1;
+ return;
+ }
+ /*
+ * Allocate space for nchsz * NCHSIZE * ncpus namecache structures.
+ */
+ ncpc = (int)(nchsz * NCHSIZE);
+ ncl = (int)(ncpc * sizeof(struct namecache));
+ len = (int)(ncl * ncpus);
+ if (!(nc = (struct namecache *)malloc((MALLOC_S)len))) {
+ (void) fprintf(stderr,
+ "%s: no space for %d namecache entries (%d bytes)\n",
+ Pn, ncpc * ncpus, len);
+ Exit(1);
+ }
+ } else {
+
+ /*
+ * Do setup for repeat calls.
+ */
+ if (Nchash) {
+ for (i = 0; i <= Hmsk; i++) {
+ for (lp = Nchash[i]; lp; lp = lpnxt) {
+ lpnxt = lp->nxt;
+ (void) free((MALLOC_P *)lp);
+ }
+ }
+ (void) free((MALLOC_P *)Nchash);
+ Nchash = (struct l_nch **)NULL;
+ Nc = 0;
+ }
+ }
+/*
+ * Loop through the processors, reading the processor structure pointer
+ * for the processor, then its name cache. Build a local name cache
+ * table of struct namecache entries for all processors.
+ */
+ for (i = n = 0; i < ncpus; i++) {
+ if (!pp[i])
+ continue;
+ if (kread(pp[i], (char *)&ncp, sizeof(ncp)) || !ncp)
+ continue;
+ if (kread(ncp, (char *)&nc[n], ncl))
+ continue;
+ n += ncpc;
+ }
+/*
+ * Compute a hash table size and allocate it.
+ */
+ if (!n)
+ return;
+ for (i = 1; i < n; i <<= 1)
+ ;
+ i += i;
+ Hmsk = i - 1;
+ if (!(Nchash = (struct l_nch **)calloc(i, sizeof(struct l_nch *)))) {
+ if (!Fwarn)
+ (void) fprintf(stderr,
+ "%s: no space for %d byte name cache hash buckets\n",
+ Pn, (int)(i * sizeof(struct l_nch *)));
+ Exit(1);
+ }
+/*
+ * Assign hash pointers to the accumulated namecache entries.
+ */
+ for (i = Nc = 0; i < n; i++) {
+ if (!nc[i].nc_vpid)
+ continue;
+ if (((len = nc[i].nc_nlen) < 1) || (len > NCHNAMLEN))
+ continue;
+ if (len < 3 && nc[i].nc_name[0] == '.') {
+ if ((len == 1) || ((len == 2) && (nc[i].nc_name[1] == '.')))
+ continue;
+ }
+ h = ncachehash(nc[i].nc_vpid);
+ /*
+ * Look for an existing hash entry. Choose among duplicates the one
+ * with the largest nc_dvpid.
+ */
+ for (lp = Nchash[h]; lp; lp = lp->nxt) {
+ if ((np = lp->nc) && (np->nc_vpid == nc[i].nc_vpid)) {
+ if (nc[i].nc_dvpid > np->nc_dvpid)
+ lp->nc = &nc[i];
+ break;
+ }
+ }
+ if (lp)
+ continue;
+ /*
+ * Allocate and fill a new local name cache entry.
+ */
+ if (!(lp = (struct l_nch *)malloc(sizeof(struct l_nch)))) {
+ (void) fprintf(stderr, "%s: can't allocate l_nch entry\n", Pn);
+ Exit(1);
+ }
+ lp->nc = &nc[i];
+ lp->nxt = Nchash[h];
+ Nchash[h] = lp;
+ Nc++;
+ }
+}
+
+
+/*
+ * ncache_lookup() - look up a node's name in the kernel's name cache
+ */
+
+char *
+ncache_lookup(buf, blen, fp)
+ char *buf; /* receiving name buffer */
+ int blen; /* receiving buffer length */
+ int *fp; /* full path reply */
+{
+ char *cp = buf;
+ struct l_nch *lc;
+ struct mounts *mtp;
+ struct namecache *nc;
+ int nl, rlen;
+
+ *cp = '\0';
+ *fp = 0;
+
+# if defined(HASFSINO)
+/*
+ * If the entry has an inode number that matches the inode number of the
+ * file system mount point, return an empty path reply. That tells the
+ * caller to print the file system mount point name only.
+ */
+ if (Lf->inp_ty == 1 && Lf->fs_ino && Lf->inode == Lf->fs_ino)
+ return(cp);
+# endif /* defined(HASFSINO) */
+
+/*
+ * Look up the name cache entry for the node address.
+ */
+ if (Nc == 0 || !(lc = ncache_addr(Lf->id)) || !(nc = lc->nc)) {
+
+ /*
+ * If the node has no cache entry, see if it's the mount
+ * point of a known file system.
+ */
+ if (!Lf->fsdir || !Lf->dev_def || Lf->inp_ty != 1)
+ return((char *)NULL);
+ for (mtp = readmnt(); mtp; mtp = mtp->next) {
+ if (!mtp->dir || !mtp->inode)
+ continue;
+ if ((Lf->dev == mtp->dev)
+ && (mtp->inode == Lf->inode)
+ && (strcmp(mtp->dir, Lf->fsdir) == 0))
+ return(cp);
+ }
+ return((char *)NULL);
+ }
+/*
+ * Start the path assembly.
+ */
+ if ((nl = nc->nc_nlen) > (blen - 1))
+ return((char *)NULL);
+ cp = buf + blen - nl - 1;
+ rlen = blen - nl - 1;
+ (void) strncpy(cp, nc->nc_name, nl);
+ cp[nl] = '\0';
+/*
+ * Look up the name cache entries that are parents of the node address.
+ * Quit when:
+ *
+ * there's no parent;
+ * the name length is too large to fit in the receiving buffer.
+ */
+ for (;;) {
+ if (!nc->nc_dvpid) {
+ if (ncache_isroot((KA_T)nc->nc_vp, cp))
+ *fp = 1;
+ break;
+ }
+ if (!(lc = ncache_addr(nc->nc_dvpid))) {
+ if (ncache_ckrootid((KA_T)nc->nc_vp, nc->nc_dvpid))
+ *fp = 1;
+ break;
+ }
+ if (!(nc = lc->nc))
+ break;
+ if (((nl = nc->nc_nlen) + 1) > rlen)
+ break;
+ *(cp - 1) = '/';
+ cp--;
+ rlen--;
+ (void) strncpy(cp - nl, nc->nc_name, nl);
+ cp -= nl;
+ rlen -= nl;
+ }
+ return(cp);
+}
+#endif /* DUV>=50100 && defined(HASNCACHE) */
diff --git a/dialects/du/dproto.h b/dialects/du/dproto.h
new file mode 100644
index 0000000..ebc1d8d
--- /dev/null
+++ b/dialects/du/dproto.h
@@ -0,0 +1,61 @@
+/*
+ * dproto.h - DEC OSF/1, Digital UNIX, Tru64 UNIX function prototypes for lsof
+ *
+ * The _PROTOTYPE macro is defined in the common proto.h.
+ */
+
+
+/*
+ * Copyright 1994 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.
+ */
+
+
+/*
+ * $Id: dproto.h,v 1.8 99/06/22 08:15:18 abe Exp $
+ */
+
+
+_PROTOTYPE(extern void clr_flinfo,(void));
+_PROTOTYPE(extern char *get_nlist_path,(int ap));
+_PROTOTYPE(extern int is_file_named,(char *p, int cd));
+_PROTOTYPE(extern struct l_vfs *readvfs,(KA_T vm));
+
+#if defined(HASDCACHE)
+_PROTOTYPE(extern void clr_sect,(void));
+#endif /* defined(HASDCACHE) */
+
+#if defined(HASIPv6)
+_PROTOTYPE(extern struct hostent *gethostbyname2,(char *nm, int prot));
+#endif /* defined(HASIPv6) */
+
+#if defined(HASPRIVNMCACHE)
+_PROTOTYPE(extern int tag_to_path,(char *fs, mlBfTagT t2pb, int nl, char *nlb));
+#endif /* defined(HASPRIVNMCACHE) */
+
+#if defined(USELOCALREADDIR)
+_PROTOTYPE(extern int CloseDir,(DIR *dirp));
+_PROTOTYPE(extern DIR *OpenDir,(char *dir));
+_PROTOTYPE(extern struct DIRTYPE *ReadDir,(DIR *dirp));
+#endif /* defined(USELOCALREADDIR) */
diff --git a/dialects/du/dsock.c b/dialects/du/dsock.c
new file mode 100644
index 0000000..94f4589
--- /dev/null
+++ b/dialects/du/dsock.c
@@ -0,0 +1,325 @@
+/*
+ * dsock.c - DEC OSF/1, Digital UNIX, Tru64 UNIX socket processing functions
+ * for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dsock.c,v 1.19 2005/08/08 19:56:44 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+/*
+ * process_socket() - process socket
+ */
+
+void
+process_socket(sa)
+ KA_T sa; /* socket address in kernel */
+{
+ struct domain d;
+ unsigned char *fa = (unsigned char *)NULL;
+ int fam;
+ int fp, lp;
+ struct inpcb inp;
+ KA_T ka;
+ unsigned char *la = (unsigned char *)NULL;
+ struct mbuf mb;
+ struct protosw p;
+ struct socket s;
+ struct tcpcb t;
+ struct unpcb uc, unp;
+ struct sockaddr_un *ua = NULL;
+ struct sockaddr_un un;
+
+ (void) snpf(Lf->type, sizeof(Lf->type), "sock");
+ Lf->inp_ty = 2;
+/*
+ * Read the socket, protocol, and domain structures.
+ */
+ if (!sa) {
+ enter_nm("no socket address");
+ return;
+ }
+ if (kread(sa, (char *) &s, sizeof(s))) {
+ (void) snpf(Namech, Namechl, "can't read socket struct from %s",
+ print_kptr(sa, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ if (!s.so_type) {
+ enter_nm("no socket type");
+ return;
+ }
+ if (!s.so_proto
+ || kread((KA_T)s.so_proto, (char *)&p, sizeof(p))) {
+ (void) snpf(Namech, Namechl, "can't read protocol switch from %s",
+ print_kptr((KA_T)s.so_proto, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ if (!p.pr_domain
+ || kread((KA_T)p.pr_domain, (char *)&d, sizeof(d))) {
+ (void) snpf(Namech, Namechl, "can't read domain struct from %s",
+ print_kptr((KA_T)p.pr_domain, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+/*
+ * Save size information.
+ */
+ if (Fsize) {
+ if (Lf->access == 'r')
+ Lf->sz = (SZOFFTYPE)s.so_rcv.sb_cc;
+ else if (Lf->access == 'w')
+ Lf->sz = (SZOFFTYPE)s.so_snd.sb_cc;
+ else
+ Lf->sz = (SZOFFTYPE)(s.so_rcv.sb_cc + s.so_snd.sb_cc);
+ Lf->sz_def = 1;
+ } else
+ Lf->off_def = 1;
+
+#if defined(HASTCPTPIQ)
+ Lf->lts.rq = s.so_rcv.sb_cc;
+ Lf->lts.sq = s.so_snd.sb_cc;
+ Lf->lts.rqs = Lf->lts.sqs = 1;
+#endif /* defined(HASTCPTPIQ) */
+
+#if defined(HASSOOPT)
+ Lf->lts.ltm = (unsigned int)s.so_linger;
+ Lf->lts.opt = (unsigned int)s.so_options;
+ Lf->lts.pqlen = (unsigned int)s.so_q0len;
+ Lf->lts.qlen = (unsigned int)s.so_qlen;
+ Lf->lts.qlim = (unsigned int)s.so_qlimit;
+ Lf->lts.rbsz = (unsigned long)s.so_rcv.sb_mbmax;
+ Lf->lts.sbsz = (unsigned long)s.so_snd.sb_mbmax;
+ Lf->lts.pqlens = Lf->lts.qlens = Lf->lts.qlims = Lf->lts.rbszs
+ = Lf->lts.sbszs = (unsigned char)1;
+#endif /* defined(HASSOOPT) */
+
+#if defined(HASSOSTATE)
+ Lf->lts.ss = (unsigned int)s.so_state;
+#endif /* defined(HASSOSTATE) */
+
+/*
+ * Process socket by the associated domain family.
+ */
+ switch ((fam = d.dom_family)) {
+/*
+ * Process an Internet domain socket.
+ */
+ case AF_INET:
+
+#if defined(HASIPv6)
+ case AF_INET6:
+ (void) snpf(Lf->type, sizeof(Lf->type),
+ (fam == AF_INET) ? "IPv4" : "IPv6");
+#else /* !defined(HASIPv6) */
+ (void) snpf(Lf->type, sizeof(Lf->type), "inet");
+#endif /* defined(HASIPv6) */
+
+ if (Fnet) {
+ if (!FnetTy
+ || ((FnetTy == 4) && (fam == AF_INET))
+
+#if defined(HASIPv6)
+ || ((FnetTy == 6) && (fam == AF_INET6))
+#endif /* defined(HASIPv6) */
+ )
+
+ Lf->sf |= SELNET;
+ }
+ printiproto(p.pr_protocol);
+ /*
+ * Read protocol control block.
+ */
+ if (!s.so_pcb
+ || kread((KA_T)s.so_pcb, (char *)&inp, sizeof(inp))) {
+ (void) snpf(Namech, Namechl, "can't read inpcb at %s",
+ print_kptr((KA_T)s.so_pcb, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ /*
+ * Print Internet socket information.
+ */
+ ka = (KA_T)(inp.inp_ppcb ? inp.inp_ppcb : s.so_pcb);
+ enter_dev_ch(print_kptr((ka & 0xffffffff), (char *)NULL, 0));
+
+#if defined(HASIPv6)
+ if ((fam == AF_INET && IN6_IS_ADDR_UNSPECIFIED(&inp.inp_laddr))
+ || IN6_IS_ADDR_V4MAPPED(&inp.inp_laddr)) {
+ la = (unsigned char *)&IN6_EXTRACT_V4ADDR(&inp.inp_laddr);
+ fam = AF_INET;
+ } else {
+ la = (unsigned char *)&inp.inp_laddr;
+ fam = AF_INET6;
+ }
+#else /* !defined(HASIPv6) */
+ la = (unsigned char *)&inp.inp_laddr;
+#endif /* defined(HASIPv6) */
+
+ lp = (int)ntohs(inp.inp_lport);
+
+#if defined(HASIPv6)
+ if (fam == AF_INET) {
+ if (inp.inp_fport
+ || IN6_EXTRACT_V4ADDR(&inp.inp_faddr) != INADDR_ANY)
+ {
+ fa = (unsigned char *)&IN6_EXTRACT_V4ADDR(&inp.inp_faddr);
+ fp = (int)ntohs(inp.inp_fport);
+ }
+ } else {
+ if (inp.inp_fport || !IN6_IS_ADDR_UNSPECIFIED(&inp.inp_faddr))
+ {
+ fa = (unsigned char *)&inp.inp_faddr;
+ fp = (int)ntohs(inp.inp_fport);
+ }
+ }
+#else /* !defined(HASIPv6) */
+ if (inp.inp_faddr.s_addr != INADDR_ANY || inp.inp_fport != 0) {
+ fa = (unsigned char *)&inp.inp_faddr;
+ fp = (int)ntohs(inp.inp_fport);
+ }
+#endif /* defined(HASIPv6) */
+
+ if (fa || la)
+ (void) ent_inaddr(la, lp, fa, fp, fam);
+ if (p.pr_protocol == IPPROTO_TCP && inp.inp_ppcb
+ && !kread((KA_T)inp.inp_ppcb, (char *)&t, sizeof(t))) {
+ Lf->lts.type = 0;
+ Lf->lts.state.i = (int)t.t_state;
+
+#if defined(HASSOOPT)
+ Lf->lts.kai = (unsigned int)t.t_timer[TCPT_KEEP];
+#endif /* defined(HASSOOPT) */
+
+#if defined(HASTCPOPT)
+ Lf->lts.mss = (unsigned long)t.t_maxseg;
+ Lf->lts.msss = (unsigned char)1;
+ Lf->lts.topt = (unsigned int)t.t_flags;
+#endif /* defined(HASTCPOPT) */
+
+ }
+ break;
+/*
+ * Process a ROUTE domain socket.
+ */
+ case AF_ROUTE:
+ (void) snpf(Lf->type, sizeof(Lf->type), "rte");
+ if (s.so_pcb) {
+ ka = (KA_T)(s.so_pcb);
+ enter_dev_ch(print_kptr((ka & 0xffffffff), (char *)NULL, 0));
+ } else
+ (void) snpf(Namech, Namechl, "no protocol control block");
+ if (!Fsize)
+ Lf->off_def = 1;
+ break;
+/*
+ * Process a Unix domain socket.
+ */
+ case AF_UNIX:
+ if (Funix)
+ Lf->sf |= SELUNX;
+ (void) snpf(Lf->type, sizeof(Lf->type), "unix");
+ /*
+ * Read Unix protocol control block and the Unix address structure.
+ */
+ enter_dev_ch(print_kptr((sa & 0xffffffff), (char *)NULL, 0));
+ if (kread((KA_T) s.so_pcb, (char *) &unp, sizeof(unp))) {
+ (void) snpf(Namech, Namechl, "can't read unpcb at %s",
+ print_kptr((KA_T)s.so_pcb, (char *)NULL, 0));
+ break;
+ }
+ if ((struct socket *)sa != unp.unp_socket) {
+ (void) snpf(Namech, Namechl, "unp_socket (%s) mismatch",
+ print_kptr((KA_T)unp.unp_socket, (char *)NULL, 0));
+ break;
+ }
+ if (unp.unp_addr) {
+ if (kread((KA_T) unp.unp_addr, (char *) &mb, sizeof(mb))) {
+ (void) snpf(Namech, Namechl, "can't read unp_addr at %s",
+ print_kptr((KA_T)unp.unp_addr, (char *)NULL, 0));
+ break;
+ }
+ ua = (struct sockaddr_un *)((char *)&mb
+ + (mb.m_hdr.mh_data - (caddr_t)unp.unp_addr));
+ ua->sun_family = AF_UNIX;
+ }
+ if (!ua) {
+ ua = &un;
+ (void) zeromem((char *)ua, sizeof(un));
+ ua->sun_family = AF_UNSPEC;
+ }
+ /*
+ * Print information on Unix socket that has no address bound
+ * to it, although it may be connected to another Unix domain
+ * socket as a pipe.
+ */
+ if (ua->sun_family != AF_UNIX) {
+ if (ua->sun_family == AF_UNSPEC) {
+ if (unp.unp_conn) {
+ if (kread((KA_T)unp.unp_conn, (char *)&uc, sizeof(uc)))
+ (void) snpf(Namech, Namechl,
+ "can't read unp_conn at %s",
+ print_kptr((KA_T)unp.unp_conn,(char *)NULL,0));
+ else {
+ ka = (KA_T)uc.unp_socket;
+ (void) snpf(Namech, Namechl, "->%s",
+ print_kptr((ka & 0xffffffff), (char *)NULL, 0));
+ }
+ } else
+ (void) snpf(Namech, Namechl, "->(none)");
+ } else
+ (void) snpf(Namech, Namechl, "unknown sun_family (%d)",
+ ua->sun_family);
+ break;
+ }
+ if (ua->sun_path[0]) {
+ if (mb.m_len >= sizeof(struct sockaddr_un))
+ mb.m_len = sizeof(struct sockaddr_un) - 1;
+ *((char *)ua + mb.m_len) = '\0';
+ if (Sfile && is_file_named(ua->sun_path, 0))
+ Lf->sf |= SELNM;
+ if (!Namech[0])
+ (void) snpf(Namech, Namechl, "%s", ua->sun_path);
+ } else
+ (void) snpf(Namech, Namechl, "no address");
+ break;
+ default:
+ printunkaf(fam, 1);
+ }
+ if (Namech[0])
+ enter_nm(Namech);
+}
diff --git a/dialects/du/dstore.c b/dialects/du/dstore.c
new file mode 100644
index 0000000..7edea3b
--- /dev/null
+++ b/dialects/du/dstore.c
@@ -0,0 +1,162 @@
+/*
+ * dstore.c - DEC OSF/1, Digital UNIX, Tru64 UNIX global storage for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dstore.c,v 1.10 2000/08/09 20:06:50 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+int CloneMaj; /* clone major device number */
+
+
+/*
+ * Drive_Nl -- table to drive the building of Nl[] via build_Nl()
+ * (See lsof.h and misc.c.)
+ */
+
+struct drive_Nl Drive_Nl[] = {
+ { "cldev", "clonedev" },
+ { "fids", "fids" },
+ { "msfsubc", "msfs_ubcops" },
+
+#if DUV>=50100
+ { "advfsvfs", "msfs_vfsops" },
+ { "cdfsvfs", "cdfs_vfsops" },
+ { "dvdfsvfs", "dvdfs_vfsops" },
+ { "fdfsvfs", "fdfs_vfsops" },
+ { "fsfsrvp", "fdfs_root_directory" },
+ { "nchsz", "nchsz" },
+ { "ncpus", "ncpus" },
+ { "nfsvfs", "nfs_vfsops" },
+ { "nfs3vfs", "nfs3_vfsops" },
+ { "procptr", "processor_ptr" },
+ { "ufsvfs", "ufs_vfsops" },
+#else /* DUV<50100 */
+ { X_NCACHE, "namecache" },
+ { X_NCSIZE, "nchsize" },
+#endif /* DUV>=50100 */
+
+ { "vnmaxp", "vn_maxprivate" },
+
+#if DUV<30000
+ { "proc", "proc" },
+ { "nproc", "nproc" },
+#else /* DUV>=30000 */
+ { "npid", "npid" },
+ { "pidt", "pidtab" },
+#endif /* DUV<30000 */
+
+ { "", "", },
+ { NULL, NULL, }
+};
+
+struct file *Fileptr; /* for process_file() in lib/prfp.c */
+int HaveCloneMaj = 0; /* status of CloneMaj */
+int Kd = -1;
+struct l_vfs *Lvfs = NULL;
+
+# if DUV>=30000
+KA_T *Pa = NULL; /* kernel proc structure addresses */
+# endif /* DUV>=30000 */
+
+#if defined(HASFSTRUCT)
+/*
+ * Pff_tab[] - table for printing file flags
+ */
+
+struct pff_tab Pff_tab[] = {
+ { (long)FREAD, FF_READ },
+ { (long)FWRITE, FF_WRITE },
+ { (long)FNONBLOCK, FF_NBLOCK },
+ { (long)FNDELAY, FF_NDELAY },
+ { (long)FAPPEND, FF_APPEND },
+ { (long)FASYNC, FF_ASYNC },
+ { (long)FMARK, FF_MARK },
+ { (long)FDEFER, FF_DEFER },
+ { (long)FSHLOCK, FF_SHLOCK },
+ { (long)FEXLOCK, FF_EXLOCK },
+
+# if defined(FKERNEL)
+ { (long)FKERNEL, FF_KERNEL },
+# endif /* defined(FKERNEL) */
+
+# if defined(FKERNEL)
+ { (long)FVTEXT, FF_VTEXT },
+# endif /* defined(FVTEXT) */
+
+# if defined(FSYNC)
+ { (long)FSYNC, FF_SYNC },
+# endif /* defined(FSYNC) */
+
+# if defined(FDSYNC)
+ { (long)FDSYNC, FF_DSYNC },
+# endif /* defined(FDSYNC) */
+
+# if defined(FRSYNC)
+ { (long)FRSYNC, FF_RSYNC },
+# endif /* defined(FRSYNC) */
+
+ { (long)0, NULL }
+};
+
+
+/*
+ * Pof_tab[] - table for print process open file flags
+ */
+
+struct pff_tab Pof_tab[] = {
+
+# if defined(UF_EXCLOSE)
+ { (long)UF_EXCLOSE, POF_CLOEXEC },
+# else /* !defined(UF_EXCLOSE) */
+ { (long)1, POF_CLOEXEC },
+# endif /* defined(UF_EXCLOSE) */
+
+# if defined(UF_MAPPED)
+ { (long)UF_MAPPED, POF_MAPPED },
+# endif /* defined(UF_MAPPED) */
+
+# if defined(UF_RESERVED_WAIT)
+ { (long)UF_RESERVED_WAIT, POF_RSVWT },
+# endif /* defined(UF_RESERVED_WAIT) */
+
+ { (long)0, NULL }
+};
+#endif /* defined(HASFSTRUCT) */
+
+struct proc *Ps = NULL; /* local proc structures */
+int Psn = 0; /* entries in Paddr[] and Ps[] */
+int Vnmxp; /* vnode's max private area length */
diff --git a/dialects/du/machine.h b/dialects/du/machine.h
new file mode 100644
index 0000000..a7f92ac
--- /dev/null
+++ b/dialects/du/machine.h
@@ -0,0 +1,647 @@
+/*
+ * machine.h - DEC OSF/1, Digital UNIX, Tru64 UNIX definitions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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.
+ */
+
+
+/*
+ * $Id: machine.h,v 1.42 2010/07/29 16:02:47 abe Exp $
+ */
+
+
+#if !defined(LSOF_MACHINE_H)
+#define LSOF_MACHINE_H 1
+
+
+#include <sys/types.h>
+
+#define _KERNEL 1
+#include <sys/signal.h>
+
+#if DUV>=50000
+#include <sys/resource.h>
+#include <sys/time.h>
+#endif /* DUV>=50000 */
+
+#undef _KERNEL
+
+#include <sys/param.h>
+
+
+/*
+ * CAN_USE_CLNT_CREATE is defined for those dialects where RPC clnt_create()
+ * can be used to obtain a CLIENT handle in lieu of clnttcp_create().
+ */
+
+#if DUV>=40000
+#define CAN_USE_CLNT_CREATE 1
+#endif /* DUV>=40000 */
+
+
+/*
+ * DEVDEV_PATH defines the path to the directory that contains device
+ * nodes.
+ */
+
+#define DEVDEV_PATH "/dev"
+
+
+/*
+ * GET_MAX_FD is defined for those dialects that provide a function other than
+ * getdtablesize() to obtain the maximum file descriptor number plus one.
+ */
+
+/* #define GET_MAX_FD ? */
+
+
+/*
+ * HASAOPT is defined for those dialects that have AFS support; it specifies
+ * that the default path to an alternate AFS kernel name list file may be
+ * supplied with the -A <path> option.
+ */
+
+/* #define HASAOPT 1 */
+
+
+/*
+ * HASBLKDEV is defined for those dialects that want block device information
+ * recorded in BDevtp[].
+ *
+ * NOWARNBLKDEV suppresses warnings about no block devices for Tru64 UNIX 5.0
+ * and above.
+ */
+
+#define HASBLKDEV 1
+
+#if DUV>=50000
+#define NOWARNBLKDEV 1
+#endif /* DUV>=50000 */
+
+
+/*
+ * HASDCACHE is defined for those dialects that support a device cache
+ * file.
+ *
+ * HASENVDC defined the name of an environment variable that contains the
+ * device cache file path. The HASENVDC environment variable is ignored when
+ * the lsof process is setuid(root) or its real UID is 0.
+ *
+ * HASPERSDC defines the format for the last component of a personal device
+ * cache file path. The first will be the home directory of the real UID that
+ * executes lsof.
+ *
+ * HASPERSDCPATH defines the environment variable whose value is the middle
+ * component of the personal device cache file path. The middle component
+ * follows the home directory and precedes the results of applying HASPERSDC.
+ * The HASPERSDCPATH environment variable is ignored when the lsof process is
+ * setuid(root) or its real UID is 0.
+ *
+ * HASSYSDC defines a public device cache file path. When it's defined, it's
+ * used as the path from which to read the device cache.
+ *
+ * Consult the 00DCACHE and 00FAQ files of the lsof distribution for more
+ * information on device cache file path construction.
+ */
+
+#define HASDCACHE 1
+#define HASENVDC "LSOFDEVCACHE"
+#define HASPERSDC "%h/%p.lsof_%L"
+#define HASPERSDCPATH "LSOFPERSDCPATH"
+/* #define HASSYSDC "/your/choice/of/path" */
+
+
+/*
+ * HASCDRNODE is defined for those dialects that have CD-ROM nodes.
+ */
+
+/* #define HASCDRNODE 1 */
+
+
+/*
+ * HASFIFONODE is defined for those dialects that have FIFO nodes.
+ */
+
+/* #define HASFIFONODE 1 */
+
+
+/*
+ * HASFSINO is defined for those dialects that have the file system
+ * inode element, fs_ino, in the lfile structure definition in lsof.h.
+ */
+
+#define HASFSINO 1
+
+
+/*
+ * HASFSTRUCT is defined if the dialect has a file structure.
+ *
+ * FSV_DEFAULT defines the default set of file structure values to list.
+ * It defaults to zero (0), but may be made up of a combination of the
+ * FSV_* symbols from lsof.h.
+ *
+ * HASNOFSADDR -- has no file structure address
+ * HASNOFSFLAGS -- has no file structure flags
+ * HASNOFSCOUNT -- has no file structure count
+ * HASNOFSNADDR -- has no file structure node address
+ */
+
+#define HASFSTRUCT 1
+/* #define FSV_DEFAULT FSV_? | FSV_? | FSV_? */
+/* #define HASNOFSADDR 1 has no file structure address */
+/* #define HASNOFSFLAGS 1 has no file structure flags */
+/* #define HASNOFSCOUNT 1 has no file structure count */
+/* #define HASNOFSNADDR 1 has no file structure node address */
+
+
+/*
+ * HASGNODE is defined for those dialects that have gnodes.
+ */
+
+/* #define HASGNODE 1 */
+
+
+/*
+ * HASHSNODE is defined for those dialects that have High Sierra nodes.
+ */
+
+/* #define HASHSNODE 1 */
+
+
+/*
+ * HASINODE is defined for those dialects that have inodes and wish to
+ * use readinode() from node.c.
+ */
+
+#define HASINODE 1
+
+
+/*
+ * HASINTSIGNAL is defined for those dialects whose signal function returns
+ * an int.
+ */
+
+/* #define HASINTSIGNAL 1 */
+
+
+/*
+ * HASKERNIDCK is defined for those dialects that support the comparison of
+ * the build to running kernel identity.
+ */
+
+#define HASKERNIDCK 1
+
+
+/*
+ * HASKOPT is defined for those dialects that support the -k option of
+ * reading the kernel's name list from an optional file.
+ */
+
+#define HASKOPT 1
+
+
+/*
+ * HASLFILEADD is defined for those dialects that need additional elements
+ * in struct lfile. The HASLFILEADD definition is a macro that defines
+ * them. If any of the additional elements need to be preset in the
+ * alloc_lfile() function of proc.c, the SETLFILEADD macro may be defined
+ * to do that.
+ *
+ * If any additional elements need to be cleared in alloc_lfile() or in the
+ * free_proc() function of proc.c, the CLRLFILEADD macro may be defined to
+ * do that. Note that CLRLFILEADD takes one argument, the pointer to the
+ * lfile struct. The CLRLFILEADD macro is expected to expand to statements
+ * that are complete -- i.e., have terminating semi-colons -- so the macro is
+ * called without a terminating semicolon by proc.c.
+ *
+ * The HASXOPT definition may be used to select the conditions under which
+ * private lfile elements are used.
+ */
+
+#if defined(HASTAGTOPATH)
+#define HASLFILEADD int advfs_seq; unsigned char advfs_seq_stat;
+/* #define CLRLFILEADD(lf) (lf)->... = (type)NULL; */
+#define SETLFILEADD Lf->advfs_seq_stat = 0;
+#endif /* defined(HASTAGTOPATH) */
+
+
+/*
+ * HASMNTSTAT indicates the dialect supports the mount stat(2) result option
+ * in its l_vfs and mounts structures.
+ */
+
+/* #define HASMNTSTAT 1 */
+
+
+/*
+ * HASMNTSUP is defined for those dialects that support the mount supplement
+ * option.
+ */
+
+/* #define HASMNTSUP 1 */
+
+
+/*
+ * HASMOPT is defined for those dialects that support the reading of
+ * kernel memory from an alternate file.
+ */
+
+#define HASMOPT 1
+
+
+/*
+ * HASNCACHE is defined for those dialects that have a kernel name cache
+ * that lsof can search. A value of 1 directs printname() to prefix the
+ * cache value with the file system directory name; 2, avoid the prefix.
+ *
+ * NCACHELDPFX is a set of C commands to execute before calling ncache_load().
+ *
+ * NCACHELDSFX is a set of C commands to execute after calling ncache_load().
+ */
+
+#define HASNCACHE 1
+/* #define NCACHELDPFX ??? */
+/* #define NCACHELDSFX ??? */
+
+
+/*
+ * HASNLIST is defined for those dialects that use nlist() to acccess
+ kernel symbols.
+ */
+
+#define HASNLIST 1
+
+
+/*
+ * HASPIPEFN is defined for those dialects that have a special function to
+ * process DTYPE_PIPE file structure entries. Its value is the name of the
+ * function.
+ *
+ * NOTE: don't forget to define a prototype for this function in dproto.h.
+ */
+
+/* #define HASPIPEFN process_pipe? */
+
+
+/*
+ * HASPIPENODE is defined for those dialects that have pipe nodes.
+ */
+
+/* #define HASPIPENODE 1 */
+
+
+/*
+ * HASPMAPENABLED is defined when the reporting of portmapper registration
+ * info is enabled by default.
+ */
+
+/* #define HASPMAPENABLED 1 */
+
+
+/*
+ * HASPPID is defined for those dialects that support identification of
+ * the parent process IDentifier (PPID) of a process.
+ */
+
+#define HASPPID 1
+
+
+/*
+ * HASPRINTDEV, HASPRINTINO, HASPRINTNM, HASPRINTOFF, and HASPRINTSZ
+ * define private dialect-specific functions for printing DEVice numbers,
+ * INOde numbers, NaMes, file OFFsets, and file SiZes. The functions are
+ * called from print_file().
+ */
+
+#define HASPRINTDEV print_dev
+/* #define HASPRINTINO print_ino? */
+/* #define HASPRINTNM print_nm? */
+/* #define HASPRINTOFF print_off? */
+/* #define HASPRINTSZ print_sz? */
+
+
+/*
+ * HASPRIVFILETYPE and PRIVFILETYPE are defined for dialects that have a
+ * file structure type that isn't defined by a DTYPE_* symbol. They are
+ * used in lib/prfp.c to select the type's processing.
+ *
+ * PRIVFILETYPE is the definition of the f_type value in the file struct.
+ *
+ * HASPRIVFILETYPE is the name of the processing function.
+ */
+
+/* #define HASPRIVFILETYPE process_shmf? */
+/* #define PRIVFILETYPE ?? */
+
+
+/*
+ * HASPRIVNMCACHE is defined for dialects that have a private method for
+ * printing cached NAME column values for some files. HASPRIVNAMECACHE
+ * is defined to be the name of the function.
+ *
+ * The function takes one argument, a struct lfile pointer to the file, and
+ * returns non-zero if it prints a name to stdout.
+ */
+
+#if defined(HASTAGTOPATH)
+#define HASPRIVNMCACHE print_advfs_path
+#endif /* defined(HASTAGTOPATH) */
+
+
+/*
+ * HASPRIVPRIPP is defined for dialects that have a private function for
+ * printing IP protocol names. When HASPRIVPRIPP isn't defined, the
+ * IP protocol name printing function defaults to printiprto().
+ */
+
+/* #define HASPRIVPRIPP 1 */
+
+
+/*
+ * HASPROCFS is defined for those dialects that have a proc file system --
+ * usually /proc and usually in SYSV4 derivatives.
+ *
+ * HASFSTYPE is defined as 1 for those systems that have a file system type
+ * string, st_fstype, in the stat() buffer; 2, for those systems that have a
+ * file system type integer in the stat() buffer, named MOUNTS_STAT_FSTYPE;
+ * 0, for systems whose stat(2) structure has no file system type member. The
+ * additional symbols MOUNTS_FSTYPE, RMNT_FSTYPE, and RMNT_STAT_FSTYPE may be
+ * defined in dlsof.h to direct how the readmnt() function in lib/rmnt.c
+ * preserves these stat(2) and getmntent(3) buffer values in the local mounts
+ * structure.
+ *
+ * The defined value is the string that names the file system type.
+ *
+ * The HASPROCFS definition usually must be accompanied by the HASFSTYPE
+ * definition and the providing of an fstype element in the local mounts
+ * structure (defined in dlsof.h).
+ *
+ * The HASPROCFS definition may be accompanied by the HASPINODEN definition.
+ * HASPINODEN specifies that searching for files in HASPROCFS is to be done
+ * by inode number.
+ */
+
+#define HASPROCFS "proc"
+/* #define HASFSTYPE 1 */
+#define HASPINODEN 1
+
+
+/*
+ * HASRNODE is defined for those dialects that have rnodes.
+ */
+
+/* #define HASRNODE 1 */
+
+
+/*
+ * Define HASSECURITY to restrict the listing of all open files to the
+ * root user. When HASSECURITY is defined, the non-root user may list
+ * only files whose processes have the same user ID as the real user ID
+ * (the one that its user logged on with) of the lsof process.
+ */
+
+/* #define HASSECURITY 1 */
+
+
+/*
+ * If HASSECURITY is defined, define HASNOSOCKSECURITY to allow users
+ * restricted by HASSECURITY to list any open socket files, provide their
+ * listing is selected by the "-i" option.
+ */
+
+/* #define HASNOSOCKSECURITY 1 */
+
+
+/*
+ * HASSETLOCALE is defined for those dialects that have <locale.h> and
+ * setlocale().
+ *
+ * If the dialect also has wide character support for language locales,
+ * HASWIDECHAR activates lsof's wide character support and WIDECHARINCL
+ * defines the header file (if any) that must be #include'd to use the
+ * mblen() and mbtowc() functions.
+ */
+
+#define HASSETLOCALE 1
+
+# if DUV>=40000
+#define HASWIDECHAR 1
+# endif /* DUV>=40000 */
+
+/* #define WIDECHARINCL <wchar.h> */
+
+
+/*
+ * HASSNODE is defined for those dialects that have snodes.
+ */
+
+/* #define HASSNODE 1 */
+
+
+/*
+ * HASTASKS is defined for those dialects that have task reporting support.
+ */
+
+/* #define HASTASKS 1 */
+
+
+/*
+ * HASSOOPT, HASSOSTATE and HASTCPOPT define the availability of information
+ * on socket options (SO_* symbols), socket states (SS_* symbols) and TCP
+ * options.
+ */
+
+#define HASSOOPT 1 /* has socket option information */
+#define HASSOSTATE 1 /* has socket state information */
+#define HASTCPOPT 1 /* has TCP options or flags */
+
+
+/*
+ * Define HASSPECDEVD to be the name of a function that handles the results
+ * of a successful stat(2) of a file name argument.
+ *
+ * For example, HASSPECDEVD() for Darwin makes sure that st_dev is set to
+ * what stat("/dev") returns -- i.e., what's in DevDev.
+ *
+ * The function takes two arguments:
+ *
+ * 1: pointer to the full path name of file
+ * 2: pointer to the stat(2) result
+ *
+ * The function returns void.
+ */
+
+/* #define HASSPECDEVD process_dev_stat */
+
+
+/*
+ * HASSTREAMS is defined for those dialects that support streams.
+ */
+
+/* #define HASSTREAMS 1 */
+
+
+/*
+ * HASTCPTPIQ is defined for dialects where it is possible to report the
+ * TCP/TPI Recv-Q and Send-Q values produced by netstat.
+ */
+
+#define HASTCPTPIQ 1
+
+
+/*
+ * HASTCPTPIW is defined for dialects where it is possible to report the
+ * TCP/TPI send and receive window sizes produced by netstat.
+ */
+
+/* #define HASTCPTPIW 1 */
+
+
+/*
+ * HASTMPNODE is defined for those dialects that have tmpnodes.
+ */
+
+/* #define HASTMPNODE 1 */
+
+
+/*
+ * HASVNODE is defined for those dialects that use the Sun virtual file system
+ * node, the vnode. BSD derivatives usually do; System V derivatives prior to
+ * R4 usually don't.
+ *
+ * Even though Digital UNIX has vnodes, we don't define HASVNODE, because
+ * private vnode processing is required. (See the readvnode() function
+ * in dnode.c.)
+ */
+
+/* #define HASVNODE 1 */
+
+
+/*
+ * HASXOPT is defined for those dialects that have an X option. It
+ * defines the text for the usage display. HASXOPT_VALUE defines the
+ * option's default binary value -- 0 or 1.
+ */
+
+/* #define HASXOPT "help text for X option" */
+/* #define HASXOPT_VALUE 1 */
+
+
+/*
+ * INODETYPE and INODEPSPEC define the internal node number type and its
+ * printf specification modifier. These need not be defined and lsof.h
+ * can be allowed to define defaults.
+ *
+ * These are defined here, because they must be used in dlsof.h.
+ */
+
+/* #define INODETYPE unsigned long long */
+ /* inode number internal storage type */
+/* #define INODEPSPEC "ll" * INODETYPE printf specification
+ * modifier */
+
+
+/*
+ * UID_ARG defines the size of a User ID number when it is passed
+ * as a function argument.
+ */
+
+#define UID_ARG uid_t
+
+
+/*
+ * Each USE_LIB_<function_name> is defined for dialects that use the
+ * <function_name> in the lsof library.
+ *
+ * Note: other definitions and operations may be required to condition the
+ * library function source code. They may be found in the dialect dlsof.h
+ * header files.
+ */
+
+#define USE_LIB_CKKV 1 /* ckkv.c */
+/* #define USE_LIB_COMPLETEVFS 1 cvfs.c */
+#define USE_LIB_FIND_CH_INO 1 /* fino.c */
+#define USE_LIB_IS_FILE_NAMED 1 /* isfn.c */
+#define USE_LIB_LKUPDEV 1 /* lkud.c */
+/* #define USE_LIB_PRINTDEVNAME 1 pdvn.c */
+#define USE_LIB_PROCESS_FILE 1 /* prfp.c */
+#define USE_LIB_PRINT_TCPTPI 1 /* ptti.c */
+/* #define USE_LIB_READDEV 1 rdev.c */
+/* #define USE_LIB_READMNT 1 rmnt.c */
+/* #define USE_LIB_REGEX 1 regex.c */
+
+# if DUV<50100
+#define USE_LIB_RNAM 1 /* rnam.c */
+# else /* DUV>=50100 */
+/* Tru64 UNIX 5.1 and above have private name cache functions -- see
+ * ./dproc.c */
+# endif /* DUV<50100 */
+
+/* #define USE_LIB_RNCH 1 rnch.c */
+/* #define USE_LIB_RNMH 1 rnmh.c */
+
+# if DUV<50000
+#define USE_LIB_SNPF 1 /* snpf.c */
+# else /* DUV>=50000 */
+#define snpf snprintf /* use the system's snprintf() */
+# endif /* DUV<50000 */
+
+
+/*
+ * WARNDEVACCESS is defined for those dialects that should issue a warning
+ * when lsof can't access /dev (or /device) or one of its sub-directories.
+ * The warning can be inhibited by the lsof caller with the -w option.
+ */
+
+#define WARNDEVACCESS 1
+
+
+/*
+ * WARNINGSTATE is defined for those dialects that want to suppress all lsof
+ * warning messages.
+ */
+
+/* #define WARNINGSTATE 1 warnings are enabled by default */
+
+
+/*
+ * WILLDROPGID is defined for those dialects whose lsof executable runs
+ * setgid(not_real_GID) and whose setgid power can be relinquished after
+ * the dialect's initialize() function has been executed.
+ */
+
+#define WILLDROPGID 1
+
+
+/*
+ * zeromem is a macro that uses bzero or memset.
+ */
+
+#define zeromem(a, l) bzero(a, l)
+
+#endif /* !defined(LSOF_MACHINE_H) */
diff --git a/dialects/freebsd/Makefile b/dialects/freebsd/Makefile
new file mode 100644
index 0000000..632bc06
--- /dev/null
+++ b/dialects/freebsd/Makefile
@@ -0,0 +1,162 @@
+
+# FreeBSD Makefile remainder
+#
+# $Id: Makefile,v 1.12 2009/03/25 19:23:06 abe Exp $
+
+PROG= lsof
+
+BIN= ${DESTDIR}
+
+DOC= ${DESTDIR}
+
+I=/usr/include
+S=/usr/include/sys
+L=/usr/include/local
+P=
+
+CDEF=
+CDEFS= ${CDEF} ${CFGF}
+INCL= ${DINC}
+CFLAGS= ${CDEFS} ${INCL} ${DEBUG}
+
+GRP=
+
+HDR= lsof.h lsof_fields.h dlsof.h machine.h proto.h dproto.h dzfs.h
+
+SRC= dmnt.c dnode.c dnode1.c dnode2.c dproc.c dsock.c dstore.c \
+ arg.c main.c misc.c node.c print.c proc.c store.c usage.c \
+ util.c
+
+OBJ= dmnt.o dnode.o dnode1.o dnode2.o dproc.o dsock.o dstore.o \
+ arg.o main.o misc.o node.o print.o proc.o store.o usage.o \
+ util.o
+
+MAN= lsof.8
+
+OTHER=
+
+SHELL= /bin/sh
+
+SOURCE= Makefile ${OTHER} ${MAN} ${HDR} ${SRC}
+
+all: ${PROG}
+
+${PROG}: ${LIB} ${P} ${OBJ}
+ ${CC} -o $@ ${CFLAGS} ${OBJ} ${CFGL}
+
+clean: FRC
+ rm -f Makefile.bak ${PROG} a.out core errs lint.out tags *.o version.h
+ rm -f machine.h.old new_machine.h
+ (cd lib; ${MAKE} -f Makefile.skel clean)
+
+install: all FRC
+ @echo ''
+ @echo 'Please write your own install rule. Lsof should be installed'
+ @echo 'setgid to the group that can can read /dev/kmem. Normally'
+ @echo 'that is the kmem group. Your install rule actions might look'
+ @echo 'something like this:'
+ @echo ''
+ @echo ' install -cs -m 2755 -g $${GRP} $${PROG} $${BIN}/$${PROG}'
+ @echo ' install -c -m 444 $${MAN} $${DOC}/$${MAN}'
+ @echo ''
+ @echo 'You will have to complete the skeletons for the BIN, DOC, and'
+ @echo 'GRP strings given at the beginning of this Makefile, e.g.,'
+ @echo ''
+ @echo ' BIN= $${DESTDIR}/usr/local/etc'
+ @echo ' DOC= $${DESTDIR}/usr/local/man/man8'
+ @echo ' GRP= kmem'
+ @echo ''
+
+${LIB}: FRC
+ (cd lib; ${MAKE} DEBUG="${DEBUG}" CFGF="${CFGF}")
+
+version.h: FRC
+ @echo Constructing version.h
+ @rm -f version.h
+ @echo '#define LSOF_BLDCMT "${LSOF_BLDCMT}"' > version.h;
+ @echo '#define LSOF_CC "${CC}"' >> version.h
+ @echo '#define LSOF_CCV "${CCV}"' >> version.h
+ @echo '#define LSOF_CCDATE "'`date`'"' >> version.h
+ @echo '#define LSOF_CCFLAGS "'`echo ${CFLAGS} | sed 's/\\\\(/\\(/g' | sed 's/\\\\)/\\)/g' | sed 's/"/\\\\"/g'`'"' >> version.h
+ @if [ "X${LSOF_HOST}" = "X" ]; then \
+ echo '#define LSOF_HOST "'`uname -n`'"' >> version.h; \
+ else \
+ if [ "${LSOF_HOST}" = "none" ]; then \
+ echo '#define LSOF_HOST ""' >> version.h; \
+ else \
+ echo '#define LSOF_HOST "${LSOF_HOST}"' >> version.h; \
+ fi \
+ fi
+ @echo '#define LSOF_LDFLAGS "${CFGL}"' >> version.h
+ @if [ "X${LSOF_LOGNAME}" = "X" ]; then \
+ echo '#define LSOF_LOGNAME "${LOGNAME}"' >> version.h; \
+ else \
+ if [ "${LSOF_LOGNAME}" = "none" ]; then \
+ echo '#define LSOF_LOGNAME ""' >> version.h; \
+ else \
+ echo '#define LSOF_LOGNAME "${LSOF_LOGNAME}"' >> version.h; \
+ fi; \
+ fi
+ @if [ "X${LSOF_SYSINFO}" = "X" ]; then \
+ echo '#define LSOF_SYSINFO "'`uname -a`'"' >> version.h; \
+ else \
+ if [ "${LSOF_SYSINFO}" = "none" ]; then \
+ echo '#define LSOF_SYSINFO ""' >> version.h; \
+ else \
+ echo '#define LSOF_SYSINFO "${LSOF_SYSINFO}"' >> version.h; \
+ fi \
+ fi
+ @if [ "X${LSOF_USER}" = "X" ]; then \
+ echo '#define LSOF_USER "${USER}"' >> version.h; \
+ else \
+ if [ "${LSOF_USER}" = "none" ]; then \
+ echo '#define LSOF_USER ""' >> version.h; \
+ else \
+ echo '#define LSOF_USER "${LSOF_USER}"' >> version.h; \
+ fi \
+ fi
+ @sed '/VN/s/.ds VN \(.*\)/#define LSOF_VERSION "\1"/' < version >> version.h
+
+FRC:
+
+# DO NOT DELETE THIS LINE - make depend DEPENDS ON IT
+
+dmnt.o: ${HDR} dmnt.c
+
+dnode.o: ${HDR} dnode.c
+
+dnode1.o: ${HDR} dnode1.c
+
+dnode2.o: dzfs.h dnode2.c
+ @if [ -f ./Makefile.zfs ]; then \
+ ${MAKE} -f Makefile.zfs dnode2.o; \
+ else \
+ echo "${CC} ${CFLAGS} -c dnode2.c"; \
+ ${CC} ${CFLAGS} -c dnode2.c; \
+ fi;
+
+dproc.o: ${HDR} dproc.c
+
+dsock.o: ${HDR} dsock.c
+
+dstore.o: ${HDR} dstore.c
+
+arg.o: ${HDR} arg.c
+
+main.o: ${HDR} main.c
+
+misc.o: ${HDR} misc.c
+
+node.o: ${HDR} node.c
+
+print.o: ${HDR} print.c
+
+proc.o: ${HDR} proc.c
+
+store.o: ${HDR} store.c
+
+usage.o: ${HDR} version.h usage.c
+
+util.o: ${HDR} util.c
+
+# *** Do not add anything here - It will go away. ***
diff --git a/dialects/freebsd/Makefile.zfs b/dialects/freebsd/Makefile.zfs
new file mode 100644
index 0000000..bc473e9
--- /dev/null
+++ b/dialects/freebsd/Makefile.zfs
@@ -0,0 +1,17 @@
+
+# Makefile.zfs -- FreeBSD Makefile remainder for ZFS modules
+#
+# $Id: Makefile.zfs,v 1.3 2011/08/07 22:51:28 abe Exp $
+
+CFLAGS+=-D_SOLARIS_C_SOURCE
+CFLAGS+=${DEBUG}
+CFLAGS+=-I${OPENSOLARIS}/compat/opensolaris
+CFLAGS+=-I${OPENSOLARIS}/contrib/opensolaris/uts/common/fs/zfs
+CFLAGS+=-I${OPENSOLARIS}/contrib/opensolaris/uts/common/zmod
+CFLAGS+=-I${OPENSOLARIS}/contrib/opensolaris/uts/common
+CFLAGS+=-I${OPENSOLARIS}/contrib/opensolaris/common/zfs
+CFLAGS+=-I${OPENSOLARIS}/contrib/opensolaris/common
+CFLAGS+=-I${.CURDIR}/usr/src/include
+CFLAGS+=-I`pwd`
+
+dnode2.o: dzfs.h dnode2.c
diff --git a/dialects/freebsd/Mksrc b/dialects/freebsd/Mksrc
new file mode 100755
index 0000000..c0745ae
--- /dev/null
+++ b/dialects/freebsd/Mksrc
@@ -0,0 +1,29 @@
+#!/bin/sh
+#
+# Mksrc - make FreeBSD source files
+#
+# WARNING: This script assumes it is running from the main directory
+# of the lsof, version 4 distribution.
+#
+# One environment variable applies:
+#
+# LSOF_MKC is the method for creating the source files.
+# It defaults to "ln -s". A common alternative is "cp".
+#
+# $Id: Mksrc,v 1.5 2008/04/15 13:31:47 abe Exp $
+
+
+D=dialects/freebsd
+L="dlsof.h dmnt.c dnode.c dnode1.c dnode2.c dproc.c dproto.h dsock.c dstore.c dzfs.h machine.h"
+
+for i in $L
+do
+ rm -f $i
+ $LSOF_MKC $D/$i $i
+ echo "$LSOF_MKC $D/$i $i"
+done
+
+# For ZFS
+
+rm -f vnode_if.h
+touch vnode_if.h
diff --git a/dialects/freebsd/dlsof.h b/dialects/freebsd/dlsof.h
new file mode 100644
index 0000000..2c9afe1
--- /dev/null
+++ b/dialects/freebsd/dlsof.h
@@ -0,0 +1,672 @@
+/*
+ * dlsof.h - FreeBSD header file for lsof
+ */
+
+
+/*
+ * Copyright 1994 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.
+ */
+
+
+/*
+ * $Id: dlsof.h,v 1.46 2014/10/13 22:25:07 abe Exp $
+ */
+
+
+#if !defined(FREEBSD_LSOF_H)
+#define FREEBSD_LSOF_H 1
+
+#include <stdlib.h>
+#include <dirent.h>
+#include <nlist.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <unistd.h>
+
+# if FREEBSDV>=4000
+# if FREEBSDV>=5000
+# if FREEBSDV<6020
+# if defined(__alpha__)
+/*
+ * For Alpha below 6.2, #include <machine/pcpu.h> before #define'ing _KERNEL.
+ * Then #define PCPU_MD_FIELDS independently. This hack avoids a compiler
+ * complaint about register use.
+ */
+
+#include <machine/pcpu.h>
+#define PCPU_MD_FIELDS \
+ struct alpha_pcb pc_idlepcb; /* pcb for idling */ \
+ u_int64_t pc_idlepcbphys; /* pa of pc_idlepcb */ \
+ u_int64_t pc_pending_ipis; /* pending IPI's */ \
+ u_int32_t pc_next_asn; /* next ASN to alloc */ \
+ u_int32_t pc_current_asngen /* ASN rollover check */
+# endif /* defined(__alpha__) */
+# endif /* FREEBSDV<6020 */
+#define _KERNEL 1
+# endif /* FREEBSDV>=5000 */
+
+# if defined(HAS_VM_MEMATTR_T)
+/*
+ * The d_mmap2_t function typedef in <sys/conf.h> may need the definition
+ * of vm_memattr_t for a pointer, but that definition is only available
+ * under _KERNEL in <sys/types.h>. Defining _KERNEL before including
+ * <sys/types.h> causes many compilation problems, so this expediency
+ * (hack) is used when the vm_memattr_t definition is needed.
+ */
+#define vm_memattr_t void
+# endif /* defined(HAS_VM_MEMATTR_T) */
+
+# if defined(NEEDS_BOOLEAN_T)
+/*
+ * In FreeBSD 9 and above the boolean_t typedef is also needed and is also
+ * under _KERNEL in <sys/types.h>.
+ */
+
+#define boolean_t int
+# endif /* defined(NEEDS_BOOLEAN_T) */
+
+#include <sys/conf.h>
+
+# if defined(HAS_VM_MEMATTR_T)
+#undef vm_memattr_t
+# endif /* defined(HAS_VM_MEMATTR_T) */
+
+# if defined(NEEDS_BOOLEAN_T)
+#undef boolean_t
+# endif /* defined(NEEDS_BOOLEAN_T) */
+
+# if defined(HAS_CONF_MINOR)
+#undef minor
+#include "fbsd_minor.h"
+# endif /* defined(HAS_CONF_MINOR) */
+
+# if FREEBSDV>=5000
+#undef _KERNEL
+# endif /* FREEBSDV>=5000 */
+# endif /* FREEBSDV>=4000 */
+
+#include <sys/filedesc.h>
+#include <sys/mbuf.h>
+#define NFS
+#define m_stat mnt_stat
+
+# if FREEBSDV>=3020
+#define _KERNEL
+# endif /* FREEBSDV>=3020 */
+
+#include <sys/mount.h>
+
+# if FREEBSDV>=3020
+# if defined(__clang__)
+/*
+ * This definition is needed when clang is used, because <sys/mount.h> must
+ * be #include'd when _KERNEL is defined and that causes the getmntinfo()
+ * function prototype to be skipped.
+ */
+int getmntinfo(struct statfs **, int);
+# endif /* defined(__clang__) */
+
+#undef _KERNEL
+# endif /* FREEBSDV>=3020 */
+
+#include <rpc/types.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/un.h>
+#include <sys/unpcb.h>
+
+# if FREEBSDV>=3000
+#undef INADDR_LOOPBACK
+# endif /* FREEBSDV>=3000 */
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <net/route.h>
+#include <netinet/in_pcb.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+#include <netinet/tcp_fsm.h>
+#include <netinet/tcp_timer.h>
+#include <netinet/tcp_var.h>
+#include <sys/ucred.h>
+#include <sys/uio.h>
+
+# if defined(HAS_KVM_VNODE)
+#define _KVM_VNODE
+# endif /* defined(HAS_KVM_VNODE) */
+#include <sys/vnode.h>
+# if defined(HAS_KVM_VNODE)
+#undef _KVM_VNODE
+# endif /* defined(HAS_KVM_VNODE) */
+
+#include <net/raw_cb.h>
+#include <sys/domain.h>
+#define pmap RPC_pmap
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#undef pmap
+
+# if FREEBSDV<2000
+#include <ufs/quota.h>
+#include <ufs/inode.h>
+#include <ufs/ufsmount.h>
+#include <ufs/mfsnode.h>
+# else /* FREEBSDV>=2000 */
+#include <paths.h>
+#include <ufs/ufs/quota.h>
+
+# if FREEBSDV>=4000 && FREEBSDV<5000
+# if defined(__alpha__) || defined(__sparc64__)
+#define dev_t void *
+# endif /* defined(__alpha__) || defined(__sparc64__) */
+# endif /* FREEBSDV>=4000 && FREEBSDV<5000 */
+
+#include <ufs/ufs/inode.h>
+
+# if defined(HAS_UFS1_2)
+#define _KERNEL
+struct vop_getextattr_args;
+struct vop_deleteextattr_args;
+struct vop_setextattr_args;
+#include <ufs/ufs/extattr.h>
+#define psignal LSOF_psignal
+#define panicstr bp
+
+# if defined(__clang__)
+/*
+ * Two clang work-arounds...
+ */
+#define KASSERT(exp,msg) do {} while (0)
+#include <arpa/inet.h>
+# endif /* defined(__clang__) */
+
+#include <ufs/ufs/ufsmount.h>
+
+# if defined(__clang__)
+/*
+ * Undo the clang work-arounds.
+ */
+#undef KASSERT
+# endif /* defined(__clang__) */
+
+#undef psignal
+#undef panicstr
+#undef _KERNEL
+# endif /* defined(HAS_UFS1_2) */
+
+# if FREEBSDV>=5010
+#undef i_devvp
+# endif /* FREEBSDV>=5010 */
+
+# if FREEBSDV>=4000 && FREEBSDV<5000
+# if defined(__alpha__) || defined(__sparc64__)
+#undef dev_t
+# endif /* defined(__alpha__) || defined(__sparc64__) */
+# endif /* FREEBSDV>=4000 && FREEBSDV<5000 */
+
+# if FREEBSDV<2020
+#include <ufs/mfs/mfsnode.h>
+# endif /* FREEBSDV<2020 */
+
+# endif /* FREEBSDV<2000 */
+
+# if FREEBSDV<5000
+#include <nfs/nfsv2.h>
+# else /* FREEBSDV>=5000 */
+#include <nfs/nfsproto.h>
+# endif /* FREEBSDV<5000 */
+
+# if defined(HASRPCV2H)
+#include <nfs/rpcv2.h>
+# endif /* defined(HASRPCV2H) */
+
+# if FREEBSDV>=5000
+#include <nfsclient/nfs.h>
+#include <nfsclient/nfsnode.h>
+# else /* FREEBSDV<5000 */
+#include <nfs/nfs.h>
+#include <nfs/nfsnode.h>
+# endif /* FREEBSDV>=5000 */
+
+#include <sys/proc.h>
+#include <kvm.h>
+#undef TRUE
+#undef FALSE
+
+# if FREEBSDV<2000
+#include <sys/kinfo.h>
+# else /* FREEBSDV>=2000 */
+#include <sys/sysctl.h>
+# endif /* FREEBSDV<2000 */
+
+# if defined(HASFDESCFS)
+#define _KERNEL
+#define KERNEL
+# if FREEBSDV>=5000
+#include <fs/fdescfs/fdesc.h>
+# else /* FREEBSDV<5000 */
+#include <miscfs/fdesc/fdesc.h>
+# endif /* FREEBSDV>=5000 */
+#undef _KERNEL
+#undef KERNEL
+# endif /* defined(HASFDESCFS) */
+
+# if defined(HASNULLFS)
+#define _KERNEL
+#define KERNEL
+struct vop_generic_args;
+# if FREEBSDV>=5000
+#include <fs/nullfs/null.h>
+# else /* FREEBSDV<5000 */
+#include <miscfs/nullfs/null.h>
+# endif /* FREEBSDV>=5000 */
+#undef _KERNEL
+#undef KERNEL
+# endif /* defined(HASNULLFS) */
+
+# if defined(HASPROCFS)
+# if FREEBSDV<2000
+#include <procfs/pfsnode.h>
+# else /* FREEBSDV>=2000 */
+# if FREEBSDV<5000
+#include <miscfs/procfs/procfs.h>
+# endif /* FREEBSDV<5000 */
+#include <machine/reg.h>
+# endif /* FREEBSDV<2000 */
+
+#define PNSIZ 5
+# endif /* defined(HASPROCFS) */
+
+# if defined(HASPSEUDOFS)
+#include <fs/pseudofs/pseudofs.h>
+# endif /* defined(HASPSEUDOFS) */
+
+# if defined(HAS_ZFS)
+#include "dzfs.h"
+# endif /* defined(HAS_ZFS) */
+
+
+# if FREEBSDV<2000
+#define P_COMM p_comm
+#define P_FD p_fd
+#define P_PID p_pid
+#define P_PGID p_pgrp
+#define P_STAT p_stat
+#define P_VMSPACE p_vmspace
+# else /* FREEBSDV>=2000 */
+# if FREEBSDV<5000
+#define P_ADDR kp_eproc.e_paddr
+#define P_COMM kp_proc.p_comm
+#define P_FD kp_proc.p_fd
+#define P_PID kp_proc.p_pid
+#define P_PGID kp_eproc.e_pgid
+#define P_PPID kp_eproc.e_ppid
+#define P_STAT kp_proc.p_stat
+#define P_VMSPACE kp_proc.p_vmspace
+# else /* FREEBSDV>=5000 */
+#define P_ADDR ki_paddr
+#define P_COMM ki_comm
+#define P_FD ki_fd
+#define P_PID ki_pid
+#define P_PGID ki_pgid
+#define P_PPID ki_ppid
+#define P_STAT ki_stat
+#define P_VMSPACE ki_vmspace
+# endif /* FREEBSDV<5000 */
+# endif /* FREEBSDV<2000 */
+
+#define _KERNEL
+#define KERNEL
+#include <sys/fcntl.h>
+
+/*
+ * The following circumventions were first needed in FreeBSD 8.0-CURRENT some
+ * time in August 2008 to avoid conflicts in /usr/src/sys/sys/libkern.h> and
+ * /usr/src/sys/sys/systm.h, called by <sys/file.h> or the header files it
+ * #include's when KERNEL or _KERNEL is #define'd.
+ *
+ * The circumventions may be needed or may be erroneous for earlier FreeBSD
+ * versions where testing was not possible.
+ */
+
+# if defined(__clang__)
+/*
+ * This work-around is needed when using clang, because <sys/fcntl.h> must
+ * be #include'd under KERNEL and that causes the open() function prototype
+ * definition to be skipped.
+ */
+int open(const char *, int, ...);
+# endif /* defined(__clang__) */
+
+#define intrmask_t int
+#define log log_kernel_lsof
+
+# if !defined(HAS_PAUSE_SBT)
+#define pause pause_kernel_lsof
+# endif /* !defined(HAS_PAUSE_SBT) */
+
+#define setenv setenv_kernel_lsof
+#define uintfptr_t int
+#define _SYS_LIBKERN_H_
+#include <sys/file.h>
+
+/*
+ * Attempt to remove the circumventions.
+ */
+
+#undef _SYS_LIBKERN_H_
+#undef intrmask_t_lsof
+#undef log_kernel_lsof
+
+# if !defined(HAS_PAUSE_SBT)
+#undef pause_kernel_lsof
+# endif /* !defined(HAS_PAUSE_SBT) */
+
+#undef setenv_kernel_lsof
+#undef uintfptr_t
+#undef _KERNEL
+#undef KERNEL
+
+# if defined(DTYPE_KQUEUE)
+#define HASKQUEUE /* has the kqueue file type */
+# if FREEBSDV>=4090
+#define _KERNEL
+# endif /* FREEBSDV>=4090 */
+#include <sys/eventvar.h>
+# if FREEBSDV>=4090
+#undef _KERNEL
+# endif /* FREEBSDV>=4090 */
+# endif /* defined(DTYPE_KQUEUE) */
+
+# if FREEBSDV<2000
+#include <ufs/lockf.h>
+# else /* FREEBSDV>=2000 */
+struct vop_advlock_args { int dummy; }; /* to pacify lf_advlock() prototype */
+# if FREEBSDV>=5000
+#undef MALLOC_DECLARE
+#define MALLOC_DECLARE(type) extern struct malloc_type type[1]
+ /* to pacify <sys/lockf.h> */
+#define _KERNEL
+
+# if defined(HAS_SYS_SX_H)
+#include <sys/sx.h>
+# endif /* defined(HAS_SYS_SX_H) */
+
+# if defined(HAS_SI_PRIV) || defined(HAS_CONF_MINOR) || defined(HAS_CDEV2PRIV)
+#include <fs/devfs/devfs_int.h>
+# endif /* defined(SI_PRIV) || defined(HAS_CONF_MINOR) || defined(HAS_CDEV2PRIV) */
+
+#include <fs/devfs/devfs.h>
+#undef _KERNEL
+# endif /* FREEBSDV>=5000 */
+#include <sys/lockf.h>
+# endif /* FREEBSDV<2000 */
+
+#include <vm/vm.h>
+
+# if FREEBSDV>=2020
+# if FREEBSDV>=4090
+#define _KERNEL
+# endif /* FREEBSDV>=4090 */
+#include <sys/pipe.h>
+# if FREEBSDV>=4090
+#undef _KERNEL
+# endif /* FREEBSDV>=4090 */
+# if defined(HASVMLOCKH)
+#include <vm/lock.h>
+# endif /* defined(HASVMLOCKH) */
+#include <vm/pmap.h>
+# endif /* FREEBSDV>=2020 */
+
+#include <vm/vm_map.h>
+
+/*
+ * Compensate for removal of MAP_ENTRY_IS_A_MAP from <vm/vm_map.h>,
+ * This work-around was supplied by John Polstra <jdp@polstra.com>.
+ */
+
+# if defined(MAP_ENTRY_IS_SUB_MAP) && !defined(MAP_ENTRY_IS_A_MAP)
+#define MAP_ENTRY_IS_A_MAP 0
+# endif /* defined(MAP_ENTRY_IS_SUB_MAP) && !defined(MAP_ENTRY_IS_A_MAP) */
+
+#include <vm/vm_object.h>
+#include <vm/vm_pager.h>
+
+# if FREEBSDV>=2020
+#undef B_NEEDCOMMIT
+
+# if FREEBSDV>=5000
+#include <sys/bio.h>
+# endif /* FREEBSDV>=5000 */
+
+#include <sys/buf.h>
+#include <sys/user.h>
+
+# if FREEBSDV<5000
+#include <ufs/mfs/mfsnode.h>
+# endif /* FREEBSDV<5000 */
+# endif /* FREEBSDV>=2020 */
+
+#include <string.h>
+
+
+#define COMP_P const void
+#define DEVINCR 1024 /* device table malloc() increment */
+
+# if !defined(FREEBSD_KA_T)
+# if FREEBSDV<2000
+typedef off_t KA_T;
+# else /* FREEBSDV>=2000 */
+typedef u_long KA_T;
+# endif /* FREEBSDV<2000 */
+# endif /* !defined(FREEBSD_KA_T) */
+
+#define KMEM "/dev/kmem"
+#define MALLOC_P void
+#define FREE_P MALLOC_P
+#define MALLOC_S size_t
+#define MAXSYSCMDL MAXCOMLEN /* max system command name length */
+
+# if defined(N_UNIXV)
+#define N_UNIX_TMP(x) #x
+#define N_UNIX_STR(x) N_UNIX_TMP(x)
+#define N_UNIX N_UNIX_STR(N_UNIXV)
+# endif /* defined(N_UNIXV) */
+
+#define QSORT_P void
+
+# if !defined(READLEN_T)
+#define READLEN_T int
+# endif /* !defined(READLEN_T) */
+
+#define STRNCPY_L size_t
+#define SWAP "/dev/drum"
+#define SZOFFTYPE unsigned long long
+ /* size and offset internal storage
+ * type */
+#define SZOFFPSPEC "ll" /* SZOFFTYPE print specification
+ * modifier */
+
+
+/*
+ * Global storage definitions (including their structure definitions)
+ */
+
+struct file * Cfp;
+
+# if FREEBSDV>=2000
+extern kvm_t *Kd;
+# endif /* FREEBSDV>=2000 */
+
+# if defined(P_ADDR)
+extern KA_T Kpa;
+# endif /* defined(P_ADDR) */
+
+struct l_vfs {
+ KA_T addr; /* kernel address */
+ fsid_t fsid; /* file system ID */
+
+# if defined(MOUNT_NONE)
+ short type; /* type of file system */
+# else /* !defined(MOUNT_NONE) */
+ char *typnm; /* file system type name */
+# endif /* defined(MOUNT_NONE) */
+
+ char *dir; /* mounted directory */
+ char *fsname; /* file system name */
+ struct l_vfs *next; /* forward link */
+};
+extern struct l_vfs *Lvfs;
+
+struct mounts {
+ char *dir; /* directory (mounted on) */
+ char *fsname; /* file system
+ * (symbolic links unresolved) */
+ char *fsnmres; /* file system
+ * (symbolic links resolved) */
+ dev_t dev; /* directory st_dev */
+ dev_t rdev; /* directory st_rdev */
+ INODETYPE inode; /* directory st_ino */
+ mode_t mode; /* directory st_mode */
+ mode_t fs_mode; /* file system st_mode */
+ struct mounts *next; /* forward link */
+};
+
+#define X_NCACHE "ncache"
+#define X_NCSIZE "ncsize"
+#define NL_NAME n_name
+
+extern int Np; /* number of kernel processes */
+
+# if FREEBSDV>=2000
+extern struct kinfo_proc *P; /* local process table copy */
+# endif /* FREEBSDV>=2000 */
+
+struct sfile {
+ char *aname; /* argument file name */
+ char *name; /* file name (after readlink()) */
+ char *devnm; /* device name (optional) */
+ dev_t dev; /* device */
+ dev_t rdev; /* raw device */
+ u_short mode; /* S_IFMT mode bits from stat() */
+ int type; /* file type: 0 = file system
+ * 1 = regular file */
+ INODETYPE i; /* inode number */
+ int f; /* file found flag */
+ struct sfile *next; /* forward link */
+
+};
+
+# if FREEBSDV==4100 || FREEBSDV==4110
+#define XDR_VOID (xdrproc_t)xdr_void
+#define XDR_PMAPLIST (xdrproc_t)xdr_pmaplist
+# endif /* FREEBSDV==4100 || FREEBSDV==4110 */
+
+# if FREEBSDV>=5000
+#define XDR_VOID (const xdrproc_t)xdr_void
+#define XDR_PMAPLIST (const xdrproc_t)xdr_pmaplist
+# endif /* FREEBSDV>=5000 */
+
+
+/*
+ * Definitions for rdev.c
+ */
+
+#define DIRTYPE dirent
+#define HASDNAMLEN 1 /* struct DIRTYPE has d_namlen element */
+
+
+/*
+ * Definitions for rnam.c and rnmh.c
+ */
+
+# if defined(HASNCACHE)
+#include <sys/uio.h>
+# if FREEBSDV<4000 || (FREEBSDV>=4000 && defined(HASNAMECACHE))
+#include <sys/namei.h>
+# else /* FREEBSDV>=4000 && !defined(HASNAMECACHE) */
+/*
+ * The namecache struct definition should come from a header file that
+ * can be #include'd, but it has been moved to a kernel source file in
+ * 4.0-current for some reason unclear to me.
+ *
+ * So we must take the risk of defining it here. !!!! DANGER !!!!
+ */
+
+struct namecache {
+ LIST_ENTRY(namecache) nc_hash; /* hash chain */
+ LIST_ENTRY(namecache) nc_src; /* source vnode list */
+ TAILQ_ENTRY(namecache) nc_dst; /* destination vnode list */
+ struct vnode *nc_dvp; /* vnode of parent of name */
+ struct vnode *nc_vp; /* vnode the name refers to */
+ u_char nc_flag; /* flag bits */
+ u_char nc_nlen; /* length of name */
+ char nc_name[16]; /* segment name -- Strictly composed,
+ * the size of nc_name[] should be zero
+ * and rnmh.c in lsof/lib should read
+ * the name with a separate call to
+ * kvm_read(). Since that causes extra
+ * (and slow) calls to kvm_read(), the
+ * size is set here to an experimentally
+ * derived guess. The same experiment
+ * didn't reveal any extra kvm_read()
+ * suggesting the guess is a safe one.
+ * (VAA, 10 Apr 2002) */
+};
+# endif /* FREEBSDV<4000 || (FREEBSDV>=4000 && defined(HASNAMECACHE)) */
+
+#define NCACHE namecache /* kernel's structure name */
+#define NCACHE_NM nc_name /* name in NCACHE */
+#define NCACHE_NMLEN nc_nlen /* name length in NCACHE */
+
+# if FREEBSDV<2005
+#define NCACHE_NXT nc_nxt /* link in NCACHE */
+# else /* FREEBSDV>=2005 */
+# if FREEBSDV<2010
+#define NCACHE_NXT nc_lru.tqe_next /* link in NCACHE */
+# else /* FREEBSDV>=2010 */
+#include <stddef.h>
+#define NCACHE_NXT nc_hash.le_next /* link in NCACHE */
+# endif /* FREEBSDV<2010 */
+# endif /* FREEBSDV<2005 */
+
+#define NCACHE_NODEADDR nc_vp /* node address in NCACHE */
+#define NCACHE_PARADDR nc_dvp /* parent node address in NCACHE */
+
+# if defined(HASNCVPID)
+#define NCACHE_NODEID nc_vpid /* node ID in NCACHE */
+#define NCACHE_PARID nc_dvpid /* parent node ID in NCACHE */
+# endif /* DEFINED(HASNCVPID) */
+# endif /* defined(HASNCACHE) */
+
+# if FREEBSDV>=5000
+#define VNODE_VFLAG v_iflag
+#define NCACHE_VROOT VV_ROOT
+# endif /* FREEBSDV>=5000 */
+
+#endif /* defined(FREEBSD_LSOF_H) */
diff --git a/dialects/freebsd/dmnt.c b/dialects/freebsd/dmnt.c
new file mode 100644
index 0000000..b4db313
--- /dev/null
+++ b/dialects/freebsd/dmnt.c
@@ -0,0 +1,462 @@
+/*
+ * dmnt.c - FreeBSD mount support functions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dmnt.c,v 1.17 2013/01/02 17:01:43 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+/*
+ * Local static information
+ */
+
+static struct mounts *Lmi = (struct mounts *)NULL; /* local mount info */
+static int Lmist = 0; /* Lmi status */
+
+#undef HAS_MNT_NAMES
+
+#if FREEBSDV<2000
+static char *mnt_names[] = { "none", "ufs", "nfs", "mfs", "pc", "iso9600",
+ "procfs", "devfs" };
+#define HAS_MNT_NAMES 1
+#else /* FREEBSDV>=2000 */
+# if defined(MOUNT_NONE)
+static char *mnt_names[] = INITMOUNTNAMES;
+#define HAS_MNT_NAMES 1
+# endif /* defined(MOUNT_NONE)) */
+#endif /* FREEBSDV<2000 */
+
+
+#if FREEBSDV>=5000 && defined(HAS_NO_SI_UDEV)
+/*
+ * Dev2Udev() -- convert a kernel device number to a user device number
+ */
+
+dev_t
+Dev2Udev(c)
+
+# if defined(HAS_CONF_MINOR) || defined(HAS_CDEV2PRIV)
+ KA_T c;
+# else /* !defined(HAS_CONF_MINOR) && !defined(HAS_CDEV2PRIV) */
+ struct cdev *c;
+# endif /* defined(HAS_CONF_MINOR) || defined(HAS_CDEV2PRIV) */
+
+{
+
+# if !defined(HAS_CONF_MINOR) && !defined(HAS_CDEV2PRIV)
+ char *cp;
+ char *dn = (char *)NULL;
+ char *ln = (char *)NULL;
+ struct statfs *mb;
+ int n, sr;
+ static u_int s;
+ struct stat sb;
+ static int ss = 0;
+# endif /* !defined(HAS_CONF_MINOR) && !defined(HAS_CDEV2PRIV) */
+
+# if defined(HAS_CONF_MINOR) || defined(HAS_CDEV2PRIV)
+ KA_T ca;
+ struct cdev_priv cp;
+
+ if (!c)
+ return(NODEV);
+
+# if defined(HAS_CDEV2PRIV)
+ ca = (KA_T)cdev2priv((struct cdev *)c);
+# else /* !defined(HAS_CDEV2PRIV) */
+ ca = (KA_T)member2struct(cdev_priv, cdp_c, c);
+# endif /* defined(HAS_CDEV2PRIV) */
+
+ if (kread((KA_T)ca, (char *)&cp, sizeof(cp)))
+ return(NODEV);
+ return((dev_t)cp.cdp_inode);
+# else /* !defined(HAS_CONF_MINOR) && !defined(HAS_CDEV2PRIV) */
+# if defined(HAS_SI_PRIV)
+/*
+ * If the cdev structure has a private sub-structure, read it.
+ */
+ struct cdev_priv sp;
+
+ if (!c->si_priv || kread((KA_T)c->si_priv, (char *)&sp, sizeof(sp)))
+ return(0);
+# endif /* defined(HAS_SI_PRIV) */
+
+ if (ss) {
+
+# if defined(HAS_SI_PRIV)
+ return(sp.cdp_inode ^ s);
+# else /* !defined(HAS_SI_PRIV) */
+ return(c->si_inode ^ s);
+# endif /* defined(HAS_SI_PRIV) */
+
+ }
+
+/*
+ * Determine the random udev seed from stat(2) operations on "/" and
+ * its device.
+ */
+ if ((n = getmntinfo(&mb, MNT_NOWAIT)) <= 0) {
+ (void) fprintf(stderr, "%s: no mount information\n", Pn);
+ Exit(1);
+ }
+ for (; n; n--, mb++) {
+
+# if defined(MOUNT_NONE)
+ if (mb->f_type == MOUNT_NONE || mb->f_type >= MOUNT_MAXTYPE)
+# else /* !defined(MOUNT_NONE) */
+ if (!mb->f_type)
+# endif /* defined(MOUNT_NONE) */
+
+ continue;
+ /*
+ * Get the real directory name. Ignore all but the root directory;
+ * safely stat("/").
+ */
+ if (dn)
+ (void) free((FREE_P *)dn);
+ if (!(dn = mkstrcpy(mb->f_mntonname, (MALLOC_S *)NULL))) {
+
+Dev2Udev_no_space:
+
+ (void) fprintf(stderr, "%s: no space for mount at ", Pn);
+ safestrprt(mb->f_mntonname, stderr, 0);
+ (void) fprintf(stderr, " (");
+ safestrprt(mb->f_mntfromname, stderr, 0);
+ (void) fprintf(stderr, ")\n");
+ Exit(1);
+ }
+ if (!(ln = Readlink(dn))) {
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ " Output information may be incomplete.\n");
+ }
+ continue;
+ }
+ if (ln != dn) {
+ (void) free((FREE_P *)dn);
+ dn = ln;
+ }
+ ln = (char *)NULL;
+ if (strcmp(dn, "/"))
+ continue;
+ if (statsafely(dn, &sb))
+ continue;
+ /*
+ * Get the real device name and safely stat(2) it.
+ */
+ (void) free((FREE_P *)dn);
+ if (!(dn = mkstrcpy(mb->f_mntfromname, (MALLOC_S *)NULL)))
+ goto Dev2Udev_no_space;
+ ln = Readlink(dn);
+ if ((sr = statsafely(ln, &sb))) {
+
+ /*
+ * If the device stat(2) failed, see if the device name indicates
+ * an NFS mount, a cd9660 device, or a ZFS mount. If any condition
+ * is true, set the user device number seed to zero.
+ */
+ if (((cp = strrchr(ln, ':')) && (*(cp + 1) == '/'))
+ || !strcasecmp(mb->f_fstypename, "cd9660")
+ || !strcasecmp(mb->f_fstypename, "zfs")
+ ) {
+ ss = 1;
+ s = (u_int)0;
+ }
+ }
+ if (ln != dn)
+ (void) free((FREE_P *)ln);
+ ln = (char *)NULL;
+ (void) free((FREE_P *)dn);
+ dn = (char *)NULL;
+ if (sr && !ss)
+ continue;
+ if (!ss) {
+ ss = 1;
+ s = (u_int)sb.st_ino ^ (u_int)sb.st_rdev;
+ }
+ break;
+ }
+/*
+ * Free string copies, as required.
+ */
+ if (dn)
+ (void) free((FREE_P *)dn);
+ if (ln)
+ (void) free((FREE_P *)ln);
+/*
+ * If the device seed is known, return its application to the cdev structure's
+ * inode.
+ */
+ if (ss) {
+
+# if defined(HAS_SI_PRIV)
+ return(sp.cdp_inode ^ s);
+# else /* !defined(HAS_SI_PRIV) */
+ return(c->si_inode ^ s);
+# endif /* defined(HAS_SI_PRIV) */
+
+ }
+ (void) fprintf(stderr, "%s: can't determine user device random seed.\n", Pn);
+ Exit(1);
+
+# endif /* !defined(HAS_CONF_MINOR) */
+
+}
+#endif /* FREEBSDV>=5000 && defined(HAS_NO_SI_UDEV) */
+
+
+/*
+ * readmnt() - read mount table
+ */
+
+struct mounts *
+readmnt()
+{
+ char *dn = (char *)NULL;
+ char *ln;
+ struct statfs *mb;
+ struct mounts *mtp;
+ int n;
+ struct stat sb;
+
+#if defined(HASPROCFS)
+ unsigned char procfs = 0;
+#endif /* defined(HASPROCFS) */
+
+ if (Lmi || Lmist)
+ return(Lmi);
+/*
+ * Access mount information.
+ */
+ if ((n = getmntinfo(&mb, MNT_NOWAIT)) <= 0) {
+ (void) fprintf(stderr, "%s: no mount information\n", Pn);
+ return(0);
+ }
+/*
+ * Read mount information.
+ */
+ for (; n; n--, mb++) {
+
+#if defined(MOUNT_NONE)
+ if (mb->f_type == MOUNT_NONE || mb->f_type >= MOUNT_MAXTYPE)
+#else /* !defined(MOUNT_NONE) */
+ if (!mb->f_type)
+#endif /* defined(MOUNT_NONE) */
+
+ continue;
+ /*
+ * Interpolate a possible symbolic directory link.
+ */
+ if (dn)
+ (void) free((FREE_P *)dn);
+ if (!(dn = mkstrcpy(mb->f_mntonname, (MALLOC_S *)NULL))) {
+
+no_space_for_mount:
+
+ (void) fprintf(stderr, "%s: no space for mount at ", Pn);
+ safestrprt(mb->f_mntonname, stderr, 0);
+ (void) fprintf(stderr, " (");
+ safestrprt(mb->f_mntfromname, stderr, 0);
+ (void) fprintf(stderr, ")\n");
+ Exit(1);
+ }
+ if (!(ln = Readlink(dn))) {
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ " Output information may be incomplete.\n");
+ }
+ continue;
+ }
+ if (ln != dn) {
+ (void) free((FREE_P *)dn);
+ dn = ln;
+ }
+ if (*dn != '/')
+ continue;
+ /*
+ * Stat() the directory.
+ */
+ if (statsafely(dn, &sb)) {
+ if (!Fwarn) {
+ (void) fprintf(stderr, "%s: WARNING: can't stat() ", Pn);
+
+#if defined(HAS_MNT_NAMES)
+ safestrprt(mnt_names[mb->f_type], stderr, 0);
+#else /* !defined(HAS_MNT_NAMES) */
+ safestrprt(mb->f_fstypename, stderr, 0);
+#endif /* defined(HAS_MNT_NAMES) */
+
+ (void) fprintf(stderr, " file system ");
+ safestrprt(mb->f_mntonname, stderr, 1);
+ (void) fprintf(stderr,
+ " Output information may be incomplete.\n");
+ }
+ (void) bzero((char *)&sb, sizeof(sb));
+ sb.st_dev = (dev_t)mb->f_fsid.val[0];
+ sb.st_mode = S_IFDIR | 0777;
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ " assuming \"dev=%x\" from mount table\n",
+ sb.st_dev);
+ }
+ }
+ /*
+ * Allocate and fill a local mount structure.
+ */
+ if (!(mtp = (struct mounts *)malloc(sizeof(struct mounts))))
+ goto no_space_for_mount;
+ mtp->dir = dn;
+ dn = (char *)NULL;
+
+#if defined(HASPROCFS)
+
+#if defined(MOUNT_NONE)
+ if (mb->f_type == MOUNT_PROCFS)
+#else /* !defined(MOUNT_NONE) */
+ if (strcasecmp(mb->f_fstypename, "procfs") == 0)
+#endif /* defined(MOUNT_NONE) */
+
+ {
+
+ /*
+ * Save information on exactly one procfs file system.
+ */
+ if (procfs)
+ Mtprocfs = (struct mounts *)NULL;
+ else {
+ procfs = 1;
+ Mtprocfs = mtp;
+ }
+ }
+#endif /* defined(HASPROCFS) */
+
+ mtp->next = Lmi;
+ mtp->dev = sb.st_dev;
+ mtp->rdev = sb.st_rdev;
+ mtp->inode = (INODETYPE)sb.st_ino;
+ mtp->mode = sb.st_mode;
+ /*
+ * Interpolate a possible file system (mounted-on) device name link.
+ */
+ if (!(dn = mkstrcpy(mb->f_mntfromname, (MALLOC_S *)NULL)))
+ goto no_space_for_mount;
+ mtp->fsname = dn;
+ ln = Readlink(dn);
+ dn = (char *)NULL;
+ /*
+ * Stat() the file system (mounted-on) name and add file system
+ * information to the local mount table entry.
+ */
+ if (!ln || statsafely(ln, &sb))
+ sb.st_mode = 0;
+ mtp->fsnmres = ln;
+ mtp->fs_mode = sb.st_mode;
+ Lmi = mtp;
+ }
+/*
+ * Clean up and return the local mount info table address.
+ */
+ if (dn)
+ (void) free((FREE_P *)dn);
+ Lmist = 1;
+ return(Lmi);
+}
+
+
+/*
+ * readvfs() - read vfs structure
+ */
+
+struct l_vfs *
+readvfs(vm)
+ KA_T vm; /* kernel mount address from vnode */
+{
+ struct mount m;
+ struct l_vfs *vp;
+/*
+ * Search for match on existing entry.
+ */
+ for (vp = Lvfs; vp; vp = vp->next) {
+ if (vm == vp->addr)
+ return(vp);
+ }
+/*
+ * Read the (new) mount structure, allocate a local entry, and fill it.
+ */
+ if (kread((KA_T)vm, (char *)&m, sizeof(m)) != 0)
+ return((struct l_vfs *)NULL);
+ if (!(vp = (struct l_vfs *)malloc(sizeof(struct l_vfs)))) {
+ (void) fprintf(stderr, "%s: PID %d, no space for vfs\n",
+ Pn, Lp->pid);
+ Exit(1);
+ }
+ if (!(vp->dir = mkstrcpy(m.m_stat.f_mntonname, (MALLOC_S *)NULL))
+ || !(vp->fsname = mkstrcpy(m.m_stat.f_mntfromname, (MALLOC_S *)NULL)))
+ {
+ (void) fprintf(stderr, "%s: PID %d, no space for mount names\n",
+ Pn, Lp->pid);
+ Exit(1);
+ }
+ vp->addr = vm;
+ vp->fsid = m.m_stat.f_fsid;
+
+#if defined(MOUNT_NONE)
+ vp->type = m.m_stat.f_type;
+#else /* !defined(MOUNT_NONE) */
+ {
+ int len;
+
+ if ((len = strlen(m.m_stat.f_fstypename))) {
+ if (len > (MFSNAMELEN - 1))
+ len = MFSNAMELEN - 1;
+ if (!(vp->typnm = mkstrcat(m.m_stat.f_fstypename, len,
+ (char *)NULL, -1, (char *)NULL, -1,
+ (MALLOC_S *)NULL)))
+ {
+ (void) fprintf(stderr,
+ "%s: no space for fs type name: ", Pn);
+ safestrprt(m.m_stat.f_fstypename, stderr, 1);
+ Exit(1);
+ }
+ } else
+ vp->typnm = "";
+ }
+#endif /* defined(MOUNT_NONE) */
+
+ vp->next = Lvfs;
+ Lvfs = vp;
+ return(vp);
+}
diff --git a/dialects/freebsd/dnode.c b/dialects/freebsd/dnode.c
new file mode 100644
index 0000000..77682a4
--- /dev/null
+++ b/dialects/freebsd/dnode.c
@@ -0,0 +1,1578 @@
+/*
+ * dnode.c - FreeBSD node functions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dnode.c,v 1.43 2014/10/13 22:25:07 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+#if defined(HAS_LOCKF_ENTRY)
+#include "./lockf_owner.h"
+#endif /* defined(HAS_LOCKF_ENTRY) */
+
+#if defined(HAS_ZFS)
+#include "dzfs.h"
+#endif /* defined(HAS_ZFS) */
+
+
+#if defined(HASFDESCFS) && HASFDESCFS==1
+_PROTOTYPE(static int lkup_dev_tty,(dev_t *dr, INODETYPE *ir));
+#endif /* defined(HASFDESCFS) && HASFDESCFS==1 */
+
+
+#if defined(HAS_TMPFS)
+#define _KERNEL
+#include <fs/tmpfs/tmpfs.h>
+#undef _KERNEL
+#endif /* defined(HAS_TMPFS) */
+
+_PROTOTYPE(static void get_lock_state,(KA_T f));
+
+
+/*
+ * get_lock_state() -- get the lock state
+ */
+
+static void
+get_lock_state(f)
+ KA_T f; /* inode's lock pointer */
+{
+ struct lockf lf; /* lockf structure */
+ int lt; /* lock type */
+
+#if defined(HAS_LOCKF_ENTRY)
+ struct lockf_entry le; /* lock_entry structure */
+ KA_T lef, lep; /* lock_entry pointers */
+ struct lock_owner lo; /* lock owner structure */
+
+ if (!f || kread(f, (char *)&lf, sizeof(lf)))
+ return;
+ if (!(lef = (KA_T)lf.ls_active.lh_first))
+ return;
+ lep = lef;
+ do {
+ if (kread(lep, (char *)&le, sizeof(le)))
+ return;
+ if (!le.lf_owner
+ || kread((KA_T)le.lf_owner, (char *)&lo, sizeof(lo)))
+ continue;
+ if (lo.lo_pid == (pid_t)Lp->pid) {
+ if (le.lf_start == (off_t)0
+ && le.lf_end == 0x7fffffffffffffffLL)
+ lt = 1;
+ else
+ lt = 0;
+ if (le.lf_type == F_RDLCK)
+ Lf->lock = lt ? 'R' : 'r';
+ else if (le.lf_type == F_WRLCK)
+ Lf->lock = lt ? 'W' : 'w';
+ else if (le.lf_type == (F_RDLCK | F_WRLCK))
+ Lf->lock = 'u';
+ return;
+ }
+ } while ((lep = (KA_T)le.lf_link.le_next) && (lep != lef));
+#else /* !defined(HAS_LOCKF_ENTRY) */
+
+ unsigned char l; /* lock status */
+ KA_T lfp; /* lockf structure pointer */
+
+ if ((lfp = f)) {
+
+ /*
+ * Determine the lock state.
+ */
+ do {
+ if (kread(lfp, (char *)&lf, sizeof(lf)))
+ break;
+ l = 0;
+ switch (lf.lf_flags & (F_FLOCK|F_POSIX)) {
+ case F_FLOCK:
+ if (Cfp && (struct file *)lf.lf_id == Cfp)
+ l = 1;
+ break;
+ case F_POSIX:
+
+# if defined(P_ADDR)
+ if ((KA_T)lf.lf_id == Kpa)
+ l = 1;
+# endif /* defined(P_ADDR) */
+
+ break;
+ }
+ if (!l)
+ continue;
+ if (lf.lf_start == (off_t)0
+ && lf.lf_end == 0xffffffffffffffffLL)
+ lt = 1;
+ else
+ lt = 0;
+ if (lf.lf_type == F_RDLCK)
+ Lf->lock = lt ? 'R' : 'r';
+ else if (lf.lf_type == F_WRLCK)
+ Lf->lock = lt ? 'W' : 'w';
+ else if (lf.lf_type == (F_RDLCK | F_WRLCK))
+ Lf->lock = 'u';
+ break;
+ } while ((lfp = (KA_T)lf.lf_next) && (lfp != f));
+ }
+#endif /* defined(HAS_LOCKF_ENTRY) */
+
+}
+
+
+#if FREEBSDV>=2000
+# if defined(HASPROCFS)
+_PROTOTYPE(static void getmemsz,(pid_t pid));
+
+
+/*
+ * getmemsz() - get memory size of a /proc/<n>/mem entry
+ */
+
+static void
+getmemsz(pid)
+ pid_t pid;
+{
+ int n;
+ struct kinfo_proc *p;
+ struct vmspace vm;
+
+ for (n = 0, p = P; n < Np; n++, p++) {
+ if (p->P_PID == pid) {
+ if (!p->P_VMSPACE
+ || kread((KA_T)p->P_VMSPACE, (char *)&vm, sizeof(vm)))
+ return;
+ Lf->sz = (SZOFFTYPE)ctob(vm.vm_tsize+vm.vm_dsize+vm.vm_ssize);
+ Lf->sz_def = 1;
+ return;
+ }
+ }
+}
+# endif /* defined(HASPROCFS) */
+#endif /* FREEBSDV>=2000 */
+
+
+#if defined(HASFDESCFS) && HASFDESCFS==1
+/*
+ * lkup_dev_tty() - look up /dev/tty
+ */
+
+static int
+lkup_dev_tty(dr, ir)
+ dev_t *dr; /* place to return device number */
+ INODETYPE *ir; /* place to return inode number */
+{
+ int i;
+
+ readdev(0);
+
+# if defined(HASDCACHE)
+
+lkup_dev_tty_again:
+
+# endif /* defined(HASDCACHE) */
+
+ for (i = 0; i < Ndev; i++) {
+ if (strcmp(Devtp[i].name, "/dev/tty") == 0) {
+
+# if defined(HASDCACHE)
+ if (DCunsafe && !Devtp[i].v && !vfy_dev(&Devtp[i]))
+ goto lkup_dev_tty_again;
+# endif /* defined(HASDCACHE) */
+
+ *dr = Devtp[i].rdev;
+ *ir = Devtp[i].inode;
+ return(1);
+ }
+ }
+
+# if defined(HASDCACHE)
+ if (DCunsafe) {
+ (void) rereaddev();
+ goto lkup_dev_tty_again;
+ }
+# endif /* defined(HASDCACHE) */
+
+ return(-1);
+}
+#endif /* defined(HASFDESCFS) && HASFDESCFS==1 */
+
+
+#if defined(HASKQUEUE)
+/*
+ * process_kqueue() -- process kqueue file
+ *
+ * Strictly speaking this function should appear in dfile.c, because it is
+ * a file processing function. However, the Net and Open BSD sources don't
+ * require a dfile.c, so this is the next best location for the function.
+ */
+
+void
+process_kqueue(ka)
+ KA_T ka; /* kqueue file structure address */
+{
+ struct kqueue kq; /* kqueue structure */
+
+ (void) snpf(Lf->type, sizeof(Lf->type), "KQUEUE");
+ enter_dev_ch(print_kptr(ka, (char *)NULL, 0));
+ if (!ka || kread(ka, (char *)&kq, sizeof(kq)))
+ return;
+ (void) snpf(Namech, Namechl, "count=%d, state=%#x", kq.kq_count,
+ kq.kq_state);
+ enter_nm(Namech);
+}
+#endif /* defined(HASKQUEUE) */
+
+
+/*
+ * process_node() - process vnode
+ */
+
+void
+process_node(va)
+ KA_T va; /* vnode kernel space address */
+{
+ dev_t dev, rdev;
+ unsigned char devs;
+ unsigned char rdevs;
+ char dev_ch[32], *ep;
+ struct inode *i;
+ struct nfsnode *n;
+ size_t sz;
+ char *ty;
+ enum vtype type;
+ struct vnode *v, vb;
+ struct l_vfs *vfs;
+
+#if FREEBSDV>=2000
+ struct inode ib;
+ struct nfsnode nb;
+# if FREEBSDV>=4000
+# if FREEBSDV<5000
+ struct specinfo si;
+# else /* FREEBSDV>=5000 */
+# if !defined(HAS_CONF_MINOR) && !defined(HAS_CDEV2PRIV)
+ struct cdev si;
+# endif /* !defined(HAS_CONF_MINOR) && !defined(HAS_CDEV2PRIV) */
+# endif /* FREEBSDV<5000 */
+# endif /* FREEBSDV>=4000 */
+#endif /* FREEBSDV>=2000 */
+
+#if FREEBSDV<5000
+ struct mfsnode *m;
+# if FREEBSDV>=2000
+ struct mfsnode mb;
+# endif /* FREEBSDV>=2000 */
+#endif /* FREEBSDV<5000 */
+
+#if defined(HAS9660FS)
+ dev_t iso_dev;
+ int iso_dev_def, iso_stat;
+ INODETYPE iso_ino;
+ long iso_links;
+ SZOFFTYPE iso_sz;
+#endif /* defined(HAS9660FS) */
+
+#if defined(HASFDESCFS)
+ struct fdescnode *f;
+
+# if HASFDESCFS==1
+ static dev_t f_tty_dev;
+ static INODETYPE f_tty_ino;
+ static int f_tty_s = 0;
+# endif /* HASFDESCFS==1 */
+
+# if FREEBSDV>=2000
+ struct fdescnode fb;
+# endif /* FREEBSDV>=2000 */
+
+#endif /* defined(HASFDESCFS) */
+
+#if FREEBSDV>=5000
+# if defined(HAS_UFS1_2)
+ int ufst;
+ struct ufsmount um;
+ struct ufs1_dinode d1;
+ struct ufs2_dinode d2;
+# endif /* !defined(HAS_UFS1_2) */
+
+# if !defined(HAS_CONF_MINOR) && !defined(HAS_CDEV2PRIV)
+ struct cdev cd;
+# endif /* !defined(HAS_CONF_MINOR) && !defined(HAS_CDEV2PRIV) */
+
+ int cds;
+ struct devfs_dirent de;
+ struct devfs_dirent *d;
+ char vtbuf[32];
+ char *vtbp;
+ enum vtagtype { VT_DEVFS, VT_FDESC, VT_ISOFS, VT_PSEUDOFS, VT_NFS,
+ VT_NULL, VT_TMPFS, VT_UFS, VT_ZFS, VT_UNKNOWN
+ };
+
+# if defined(HAS_TMPFS)
+ struct tmpfs_node tn;
+ struct tmpfs_node *tnp;
+# endif /* defined(HAS_TMPFS) */
+#endif /* FREEBSDV>=5000 */
+
+#if defined(HASNULLFS)
+# if !defined(HASPRINTDEV)
+ char dbuf[32];
+# endif /* !defined(HASPRINTDEV) */
+ char *dp, *np, tbuf[1024];
+ struct null_node nu;
+ int sc = 0;
+#endif /* defined(HASNULLFS) */
+
+#if defined(HASPROCFS)
+ struct pfsnode *p;
+ struct procfsid *pfi;
+ static int pgsz = -1;
+ struct vmspace vm;
+
+# if FREEBSDV>=2000
+ struct pfsnode pb;
+# endif /* FREEBSDV>=2000 */
+#endif /* defined(HASPROCFS) */
+
+#if defined(HASPSEUDOFS)
+ struct pfs_node pn;
+ struct pfs_node *pnp;
+#endif /* defined(HASPSEUDOFS) */
+
+#if defined(HAS_ZFS)
+ zfs_info_t *z = (zfs_info_t *)NULL;
+ zfs_info_t zi;
+ char *zm = (char *)NULL;
+#else /* !defined(HAS_ZFS) */
+ static unsigned char zw = 0;
+#endif /* HAS_VFS */
+
+ enum vtagtype vtag; /* placed here to use the
+ * artificial vtagtype
+ * definition required for
+ * FREEBSDV>=5000 */
+
+#if defined(HASNULLFS)
+
+process_overlaid_node:
+
+ if (++sc > 1024) {
+ (void) snpf(Namech, Namechl, "too many overlaid nodes");
+ enter_nm(Namech);
+ return;
+ }
+#endif /* defined(HASNULLFS) */
+
+/*
+ * Initialize miscellaneous variables. This is done so that processing an
+ * overlaid node will be a fresh start.
+ */
+ devs = rdevs = 0;
+ i = (struct inode *)NULL;
+ n = (struct nfsnode *)NULL;
+ Namech[0] = '\0';
+
+#if defined(HAS9660FS)
+ iso_dev_def = iso_stat = 0;
+#endif /* defined(HAS9660FS) */
+
+#if defined(HASFDESCFS)
+ f = (struct fdescnode *)NULL;
+#endif /* defined(HASFDESCFS) */
+
+#if FREEBSDV<5000
+ m = (struct mfsnode *)NULL;
+#else /* FREEBSDV>=5000 */
+ cds = 0;
+ d = (struct devfs_dirent *)NULL;
+# if defined(HAS_UFS1_2)
+ ufst = 0;
+# endif /* !defined(HAS_UFS1_2) */
+#endif /* FREEBSDV<5000 */
+
+#if defined(HASPROCFS)
+ p = (struct pfsnode *)NULL;
+#endif /* defined(HASPROCFS) */
+
+#if defined(HASPSEUDOFS)
+ pnp = (struct pfs_node *)NULL;
+#endif /* defined(HASPSEUDOFS) */
+
+# if defined(HAS_TMPFS)
+ tnp = (struct tmpfs_node *)NULL;
+# endif /* defined(HAS_TMPFS) */
+
+
+#if defined(HAS_ZFS)
+ z = (zfs_info_t *)NULL;
+ zm = (char *)NULL;
+#endif /* defined(HAS_ZFS) */
+
+/*
+ * Read the vnode.
+ */
+ if ( ! va) {
+ enter_nm("no vnode address");
+ return;
+ }
+ v = &vb;
+ if (readvnode(va, v)) {
+ enter_nm(Namech);
+ return;
+ }
+
+#if defined(HASNCACHE)
+ Lf->na = va;
+# if defined(HASNCVPID)
+ Lf->id = v->v_id;
+# endif /* defined(HASNCVPID) */
+#endif /* defined(HASNCACHE) */
+
+#if defined(HASFSTRUCT)
+ Lf->fna = va;
+ Lf->fsv |= FSV_NI;
+#endif /* defined(HASFSTRUCT) */
+
+/*
+ * Get the vnode type.
+ */
+ if (!v->v_mount)
+ vfs = (struct l_vfs *)NULL;
+ else {
+ vfs = readvfs((KA_T)v->v_mount);
+ if (vfs) {
+
+#if defined(MOUNT_NONE)
+ switch (vfs->type) {
+ case MOUNT_NFS:
+ Ntype = N_NFS;
+ break;
+
+# if defined(HASPROCFS)
+ case MOUNT_PROCFS:
+ Ntype = N_PROC;
+ break;
+# endif /* defined(HASPROCFS) */
+ }
+#else /* !defined(MOUNT_NONE) */
+ if (strcasecmp(vfs->typnm, "nfs") == 0)
+ Ntype = N_NFS;
+
+# if defined(HASPROCFS)
+ else if (strcasecmp(vfs->typnm, "procfs") == 0)
+ Ntype = N_PROC;
+# endif /* defined(HASPROCFS) */
+
+# if defined(HASPSEUDOFS)
+ else if (strcasecmp(vfs->typnm, "pseudofs") == 0)
+ Ntype = N_PSEU;
+# endif /* defined(HASPSEUDOFS) */
+
+# if defined(HAS_TMPFS)
+ else if (strcasecmp(vfs->typnm, "tmpfs") == 0)
+ Ntype = N_TMP;
+# endif /* defined(HAS_TMPFS) */
+#endif /* defined(MOUNT_NONE) */
+
+ }
+ }
+ if (Ntype == N_REGLR) {
+ switch (v->v_type) {
+ case VFIFO:
+ Ntype = N_FIFO;
+ break;
+ default:
+ break;
+ }
+ }
+
+#if FREEBSDV>=5000
+/*
+ * For FreeBSD 5 and above VCHR and VBLK vnodes get the v_rdev structure.
+ */
+ if (((v->v_type == VCHR) || (v->v_type == VBLK))
+ && v->v_rdev
+
+# if !defined(HAS_CONF_MINOR) && !defined(HAS_CDEV2PRIV)
+ && !kread((KA_T)v->v_rdev, (char *)&cd, sizeof(cd))
+# endif /* !defined(HAS_CONF_MINOR) && !defined(HAS_CDEV2PRIV) */
+
+ ) {
+ cds = 1;
+ }
+#endif /* FREEBSDV>=5000 */
+
+/*
+ * Define the specific node pointer.
+ */
+
+#if FREEBSDV>=5000
+/*
+ * Get the pseudo vnode tag type for FreeBSD >= 5.
+ */
+ vtag = VT_UNKNOWN;
+ if (v->v_tag && !kread((KA_T)v->v_tag, (char *)&vtbuf, sizeof(vtbuf)))
+ {
+ vtbuf[sizeof(vtbuf) - 1] = '\0';
+ vtbp = vtbuf;
+ if (!strcmp(vtbuf, "ufs"))
+ vtag = VT_UFS;
+ else if (!strcmp(vtbuf, "zfs")) {
+
+#if !defined(HAS_ZFS)
+ if (!Fwarn && !zw) {
+ (void) fprintf(stderr,
+ "%s: WARNING: no ZFS support has been defined.\n",
+ Pn);
+ (void) fprintf(stderr,
+ " See 00FAQ for more information.\n");
+ zw = 1;
+ }
+#else /* defined(HAS_ZFS) */
+ vtag = VT_ZFS;
+#endif /* !defined(HAS_ZFS) */
+
+ } else if (!strcmp(vtbuf, "devfs"))
+ vtag = VT_DEVFS;
+ else if (!strcmp(vtbuf, "nfs"))
+ vtag = VT_NFS;
+ else if (!strcmp(vtbuf, "newnfs"))
+ vtag = VT_NFS;
+ else if (!strcmp(vtbuf, "oldnfs"))
+ vtag = VT_NFS;
+ else if (!strcmp(vtbuf, "isofs"))
+ vtag = VT_ISOFS;
+ else if (!strcmp(vtbuf, "pseudofs"))
+ vtag = VT_PSEUDOFS;
+ else if (!strcmp(vtbuf, "null"))
+ vtag = VT_NULL;
+ else if (!strcmp(vtbuf, "fdesc"))
+ vtag = VT_FDESC;
+ else if (!strcmp(vtbuf, "tmpfs"))
+ vtag = VT_TMPFS;
+ } else
+ vtbp = "(unknown)";
+#else /* FREEBSDV<5000 */
+ vtag = v->v_tag;
+#endif /* FREEBSDV>=5000 */
+
+ switch (vtag) {
+
+#if FREEBSDV>=5000
+ case VT_DEVFS:
+ if (!v->v_data
+ || kread((KA_T)v->v_data, (char *)&de, sizeof(de)))
+ {
+ (void) snpf(Namech, Namechl, "no devfs node: %s",
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ d = &de;
+ if (v->v_type == VDIR) {
+ if (!d->de_dir
+ || kread((KA_T)d->de_dir, (char *)&de, sizeof(de))) {
+ (void) snpf(Namech, Namechl, "no devfs dir node: %s",
+ print_kptr((KA_T)d->de_dir, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ }
+ break;
+#endif /* FREEBSDV>=5000 */
+
+#if defined(HASFDESCFS)
+ case VT_FDESC:
+
+# if FREEBSDV<2000
+ f = (struct fdescnode *)v->v_data;
+# else /* FREEBSDV>=2000 */
+ if (kread((KA_T)v->v_data, (char *)&fb, sizeof(fb)) != 0) {
+ (void) snpf(Namech, Namechl, "can't read fdescnode at: %s",
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ f = &fb;
+ break;
+# endif /* FREEBSDV<2000 */
+#endif /* defined(HASFDESCFS) */
+
+#if defined(HAS9660FS)
+ case VT_ISOFS:
+ if (read_iso_node(v, &iso_dev, &iso_dev_def, &iso_ino, &iso_links,
+ &iso_sz))
+ {
+ (void) snpf(Namech, Namechl, "no iso node: %s",
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ iso_stat = 1;
+ break;
+#endif /* defined(HAS9660FS) */
+
+#if FREEBSDV<5000
+ case VT_MFS:
+
+# if FREEBSDV<2000
+ m = (struct mfsnode *)v->v_data;
+# else /* FREEBSDV>=2000 */
+ if (!v->v_data
+ || kread((KA_T)v->v_data, (char *)&mb, sizeof(mb))) {
+ (void) snpf(Namech, Namechl, "no mfs node: %s",
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ m = &mb;
+# endif /* FREEBSDV<2000 */
+#endif /* FREEBSDV<5000 */
+
+ break;
+ case VT_NFS:
+
+#if FREEBSDV<2000
+ n = (struct nfsnode *)v->v_data;
+#else /* FREEBSDV>=2000 */
+ if (!v->v_data
+ || kread((KA_T)v->v_data, (char *)&nb, sizeof(nb))) {
+ (void) snpf(Namech, Namechl, "no nfs node: %s",
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ n = &nb;
+#endif /* FREEBSDV<2000 */
+
+ break;
+
+#if defined(HASNULLFS)
+ case VT_NULL:
+ if (sc == 1) {
+
+ /*
+ * If this is the first null_node, enter a name addition containing
+ * the mounted-on directory, the file system name, and the device
+ * number.
+ */
+ if (vfs && (vfs->dir || vfs->fsname || vfs->fsid.val[0])) {
+ if (vfs->fsid.val[0]) {
+
+#if defined(HASPRINTDEV)
+ dp = HASPRINTDEV(Lf, &dev);
+#else /* !defined(HASPRINTDEV) */
+ (void) snpf(dbuf, sizeof(dbuf) - 1, "%d,%d",
+ GET_MAJ_DEV(dev), GET_MIN_DEV(dev));
+ dbuf[sizeof(dbuf) - 1] = '\0';
+ dp = dbuf;
+#endif /* defined(HASPRINTDEV) */
+
+ } else
+ dp = (char *)NULL;
+ (void) snpf(tbuf, sizeof(tbuf) - 1,
+ "(nullfs%s%s%s%s%s%s%s)",
+ (vfs && vfs->fsname) ? " " : "",
+ (vfs && vfs->fsname) ? vfs->fsname : "",
+ (vfs && vfs->dir) ? " on " : "",
+ (vfs && vfs->dir) ? vfs->dir : "",
+ (dp && vfs && vfs->dir) ? " (" : "",
+ (dp && vfs && vfs->dir) ? dp : "",
+ (dp && vfs && vfs->dir) ? ")" : "");
+ tbuf[sizeof(tbuf) - 1] = '\0';
+ np = tbuf;
+ } else
+ np = "(nullfs)";
+ (void) add_nma(np, (int)strlen(np));
+ }
+ if (!v->v_data
+ || kread((KA_T)v->v_data, (char *)&nu, sizeof(nu))) {
+ (void) snpf(Namech, Namechl, "can't read null_node at: %s",
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ if (!nu.null_lowervp) {
+ (void) snpf(Namech, Namechl, "null_node overlays nothing");
+ enter_nm(Namech);
+ return;
+ }
+ va = (KA_T)nu.null_lowervp;
+ goto process_overlaid_node;
+#endif /* defined(HASNULLFS) */
+
+#if defined(HASPROCFS)
+ case VT_PROCFS:
+
+# if FREEBSDV<2000
+ p = (struct pfsnode *)v->v_data;
+# else /* FREEBSDV>=2000 */
+ if (!v->v_data
+ || kread((KA_T)v->v_data, (char *)&pb, sizeof(pb))) {
+ (void) snpf(Namech, Namechl, "no pfs node: %s",
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ p = &pb;
+# endif /* FREEBSDV<2000 */
+
+ break;
+#endif /* defined(HASPROCFS) */
+
+#if defined(HASPSEUDOFS)
+ case VT_PSEUDOFS:
+ if (!v->v_data
+ || kread((KA_T)v->v_data, (char *)&pn, sizeof(pn))) {
+ (void) snpf(Namech, Namechl, "no pfs_node: %s",
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ pnp = &pn;
+ break;
+#endif /* defined(HASPSEUDOFS) */
+
+# if defined(HAS_TMPFS)
+ case VT_TMPFS:
+ if (!v->v_data
+ || kread((KA_T)v->v_data, (char *)&tn, sizeof(tn))) {
+ (void) snpf(Namech, Namechl, "no tmpfs_node: %s",
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ tnp = &tn;
+ break;
+# endif /* defined(HAS_TMPFS) */
+
+ case VT_UFS:
+
+#if FREEBSDV<2000
+ i = (struct inode *)v->v_data;
+#else /* FREEBSDV>=2000 */
+ if (!v->v_data
+ || kread((KA_T)v->v_data, (char *)&ib, sizeof(ib))) {
+ (void) snpf(Namech, Namechl, "no ufs node: %s",
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ i = &ib;
+
+# if defined(HAS_UFS1_2)
+ if (i->i_ump && !kread((KA_T)i->i_ump, (char *)&um, sizeof(um))) {
+ if (um.um_fstype == UFS1) {
+ if (i->i_din1
+ && !kread((KA_T)i->i_din1, (char *)&d1, sizeof(d1)))
+ ufst = 1;
+ } else {
+ if (i->i_din2
+ && !kread((KA_T)i->i_din2, (char *)&d2, sizeof(d2)))
+ ufst = 2;
+ }
+ }
+# endif /* defined(HAS_UFS1_2) */
+#endif /* FREEBSDV<2000 */
+
+#if defined(HAS_V_LOCKF)
+ if (v->v_lockf)
+ (void) get_lock_state((KA_T)v->v_lockf);
+#else /* !defined(HAS_V_LOCKF) */
+ if (i->i_lockf)
+ (void) get_lock_state((KA_T)i->i_lockf);
+#endif /* defined(HAS_V_LOCKF) */
+
+ break;
+
+#if defined(HAS_ZFS)
+ case VT_ZFS:
+ if (!v->v_data
+ || (zm = readzfsnode((KA_T)v->v_data, &zi,
+ ((v->v_vflag & VV_ROOT) ? 1 : 0)))
+ ) {
+ (void) snpf(Namech, Namechl, "%s: %s", zm,
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ z = &zi;
+
+#if defined(HAS_V_LOCKF)
+ if (v->v_lockf)
+ (void) get_lock_state((KA_T)v->v_lockf);
+#else /* !defined(HAS_V_LOCKF) */
+ if (z->lockf)
+ (void) get_lock_state((KA_T)z->lockf);
+#endif /* defined(HAS_V_LOCKF) */
+
+ break;
+#endif /* defined(HAS_ZFS) */
+
+ default:
+ if (v->v_type == VBAD || v->v_type == VNON)
+ break;
+
+#if FREEBSDV<5000
+ (void) snpf(Namech,Namechl,"unknown file system type: %d",v->v_tag);
+#else /* FREEBSDV>=5000 */
+ (void) snpf(Namech, Namechl, "unknown file system type: %s", vtbp);
+#endif /* FREEBSDV<5000 */
+
+ enter_nm(Namech);
+ return;
+ }
+/*
+ * Get device and type for printing.
+ */
+ type = v->v_type;
+ if (n) {
+ dev = n->n_vattr.va_fsid;
+ devs = 1;
+ if ((type == VCHR) || (type == VBLK)) {
+ rdev = n->n_vattr.va_rdev;
+ rdevs = 1;
+ }
+ } else if (i) {
+
+#if FREEBSDV>=4000
+ if (i->i_dev
+
+# if !defined(HAS_CONF_MINOR) && !defined(HAS_CDEV2PRIV)
+ && !kread((KA_T)i->i_dev, (char *)&si, sizeof(si))
+# endif /* !defined(HAS_CONF_MINOR) && !defined(HAS_CDEV2PRIV) */
+
+ ) {
+
+# if defined(HAS_NO_SI_UDEV)
+# if defined(HAS_CONF_MINOR) || defined(HAS_CDEV2PRIV)
+ dev = Dev2Udev((KA_T)i->i_dev);
+# else /* !defined(HAS_CONF_MINOR) && !defined(HAS_CDEV2PRIV) */
+ dev = Dev2Udev(&si);
+# endif /* defined(HAS_CONF_MINOR) || defined(HAS_CDEV2PRIV) */
+# else /* !defined(HAS_NO_SI_UDEV) */
+ dev = si.si_udev;
+# endif /* defined(HAS_NO_SI_UDEV) */
+
+ devs = 1;
+ }
+#else /* FREEBSDV<4000 */
+ dev = i->i_dev;
+ devs = 1;
+#endif /* FREEBSDV>=4000 */
+
+ if ((type == VCHR) || (type == VBLK)) {
+
+#if FREEBSDV>=5000
+# if defined(HAS_UFS1_2)
+ if (ufst == 1) {
+ rdev = d1.di_rdev;
+ rdevs = 1;
+ } else if (ufst == 2) {
+ rdev = d2.di_rdev;
+ rdevs = 1;
+ } else
+# endif /* defined(HAS_UFS1_2) */
+
+ if (cds) {
+
+# if defined(HAS_NO_SI_UDEV)
+# if defined(HAS_CONF_MINOR) || defined(HAS_CDEV2PRIV)
+ rdev = Dev2Udev((KA_T)v->v_rdev);
+# else /* !defined(HAS_CONF_MINOR) && !defined(HAS_CDEV2PRIV) */
+ rdev = Dev2Udev(&cd);
+# endif /* defined(HAS_CONF_MINOR) || defined(HAS_CDEV2PRIV) */
+# else /* !defined(HAS_NO_SI_UDEV) */
+ rdev = cd.si_udev;
+# endif /* defined(HAS_NO_SI_UDEV) */
+
+ rdevs = 1;
+ }
+#else /* FREEBSDV<5000 */
+ rdev = i->i_rdev;
+ rdevs = 1;
+#endif /* FREEBSDV>=5000 */
+
+ }
+ }
+
+#if defined(HAS_ZFS)
+ else if (z) {
+
+ /*
+ * Record information returned by readzfsnode().
+ */
+ if (vfs) {
+ dev = vfs->fsid.val[0];
+ devs = 1;
+ }
+ if ((type == VCHR) || (type == VBLK)) {
+ if (z->rdev_def) {
+ rdev = z->rdev;
+ rdevs = 1;
+ }
+ }
+ }
+#endif /* defined(HAS_ZFS) */
+
+#if defined(HASFDESCFS) && (defined(HASFDLINK) || HASFDESCFS==1)
+ else if (f) {
+
+# if defined(HASFDLINK)
+ if (f->fd_link
+ && kread((KA_T)f->fd_link, Namech, Namechl - 1) == 0)
+ Namech[Namechl - 1] = '\0';
+
+# if HASFDESCFS==1
+ else
+# endif /* HASFDESFS==1 */
+# endif /* defined(HASFDLINK) */
+
+# if HASFDESCFS==1
+ if (f->fd_type == Fctty) {
+ if (f_tty_s == 0)
+ f_tty_s = lkup_dev_tty(&f_tty_dev, &f_tty_ino);
+ if (f_tty_s == 1) {
+ dev = f_tty_dev;
+ Lf->inode = f_tty_ino;
+ devs = Lf->inp_ty = 1;
+ }
+ }
+# endif /* HASFDESFS==1 */
+
+ }
+#endif /* defined(HASFDESCFS) && (defined(HASFDLINK) || HASFDESCFS==1) */
+
+#if defined(HAS9660FS)
+ else if (iso_stat && iso_dev_def) {
+ dev = iso_dev;
+ devs = Lf->inp_ty = 1;
+ }
+#endif /* defined(HAS9660FS) */
+
+#if FREEBSDV>=5000
+ else if (d) {
+ if (vfs) {
+ dev = vfs->fsid.val[0];
+ devs = 1;
+ } else {
+ dev = DevDev;
+ devs = 1;
+ }
+ if (type == VCHR) {
+
+# if defined(HAS_UFS1_2)
+ if (ufst == 1) {
+ rdev = d1.di_rdev;
+ rdevs = 1;
+ } else if (ufst == 2) {
+ rdev = d2.di_rdev;
+ rdevs = 1;
+ } else
+# endif /* defined(HAS_UFS1_2) */
+
+ if (cds) {
+
+# if defined(HAS_NO_SI_UDEV)
+# if defined(HAS_CONF_MINOR) || defined(HAS_CDEV2PRIV)
+ rdev = Dev2Udev((KA_T)v->v_rdev);
+# else /* !defined(HAS_CONF_MINOR) && !defined(HAS_CDEV2PRIV) */
+ rdev = Dev2Udev(&cd);
+# endif /* defined(HAS_CONF_MINOR) || defined(HAS_CDEV2PRIV) */
+# else /* !defined(HAS_NO_SI_UDEV) */
+ rdev = cd.si_udev;
+# endif /* defined(HAS_NO_SI_UDEV) */
+
+ rdevs = 1;
+ }
+ }
+ }
+#endif /* FREEBSDV>=5000 */
+
+#if defined(HASPSEUDOFS)
+ else if (pnp) {
+ if (vfs) {
+ dev = vfs->fsid.val[0];
+ devs = 1;
+ }
+ }
+#endif /* defined(HASPSEUDOFS) */
+
+# if defined(HAS_TMPFS)
+ else if (tnp) {
+ if (vfs) {
+ dev = vfs->fsid.val[0];
+ devs = 1;
+ }
+ if (tnp->tn_type == VBLK || tnp->tn_type == VCHR) {
+ rdev = tnp->tn_rdev;
+ rdevs = 1;
+ }
+ }
+# endif /* defined(HAS_TMPFS) */
+
+/*
+ * Obtain the inode number.
+ */
+ if (i) {
+ Lf->inode = (INODETYPE)i->i_number;
+ Lf->inp_ty = 1;
+ }
+
+#if defined(HAS_ZFS)
+ else if (z) {
+ if (z->ino_def) {
+ Lf->inode = z->ino;
+ Lf->inp_ty = 1;
+ }
+ }
+#endif /* defined(HAS_ZFS) */
+
+ else if (n) {
+ Lf->inode = (INODETYPE)n->n_vattr.va_fileid;
+ Lf->inp_ty = 1;
+ }
+
+#if defined(HAS9660FS)
+ else if (iso_stat) {
+ Lf->inode = iso_ino;
+ Lf->inp_ty = 1;
+ }
+#endif /* defined(HAS9660FS) */
+
+#if defined(HASPROCFS)
+# if FREEBSDV>=2000
+ else if (p) {
+ Lf->inode = (INODETYPE)p->pfs_fileno;
+ Lf->inp_ty = 1;
+ }
+# endif /* FREEBSDV>=2000 */
+#endif /* defined(HASPROCFS) */
+
+#if defined(HASPSEUDOFS)
+ else if (pnp) {
+ Lf->inode = (INODETYPE)pnp->pn_fileno;
+ Lf->inp_ty = 1;
+ }
+#endif /* defined(HASPSEUDOFS) */
+
+#if FREEBSDV>=5000
+ else if (d) {
+ Lf->inode = (INODETYPE)d->de_inode;
+ Lf->inp_ty = 1;
+ }
+#endif /* FREEBSDV>=5000 */
+
+# if defined(HAS_TMPFS)
+ else if (tnp) {
+ Lf->inode = (INODETYPE)tnp->tn_id;
+ Lf->inp_ty = 1;
+ }
+# endif /* defined(HAS_TMPFS) */
+
+/*
+ * Obtain the file size.
+ */
+ if (Foffset)
+ Lf->off_def = 1;
+ else {
+ switch (Ntype) {
+ case N_FIFO:
+ if (!Fsize)
+ Lf->off_def = 1;
+ break;
+ case N_NFS:
+ if (n) {
+ Lf->sz = (SZOFFTYPE)n->n_vattr.va_size;
+ Lf->sz_def = 1;
+ }
+ break;
+
+#if defined(HASPROCFS)
+ case N_PROC:
+
+# if FREEBSDV<2000
+ if (type == VDIR || !p || !p->pfs_vs
+ || kread((KA_T)p->pfs_vs, (char *)&vm, sizeof(vm)))
+ break;
+ if (pgsz < 0)
+ pgsz = getpagesize();
+ Lf->sz = (SZOFFTYPE)((pgsz * vm.vm_tsize)
+ + (pgsz * vm.vm_dsize)
+ + (pgsz * vm.vm_ssize));
+ Lf->sz_def = 1;
+ break;
+# else /* FREEBSDV>=2000 */
+ if (p) {
+ switch(p->pfs_type) {
+ case Proot:
+ case Pproc:
+ Lf->sz = (SZOFFTYPE)DEV_BSIZE;
+ Lf->sz_def = 1;
+ break;
+ case Pmem:
+ (void) getmemsz(p->pfs_pid);
+ break;
+ case Pregs:
+ Lf->sz = (SZOFFTYPE)sizeof(struct reg);
+ Lf->sz_def = 1;
+ break;
+ case Pfpregs:
+ Lf->sz = (SZOFFTYPE)sizeof(struct fpreg);
+ Lf->sz_def = 1;
+ break;
+ }
+ }
+# endif /* FREEBSDV<2000 */
+#endif /* defined(HASPROCFS) */
+
+#if defined(HASPSEUDOFS)
+ case N_PSEU:
+ Lf->sz = 0;
+ Lf->sz_def = 1;
+ break;
+#endif /* defined(PSEUDOFS) */
+
+ case N_REGLR:
+ if (type == VREG || type == VDIR) {
+ if (i) {
+
+#if defined(HAS_UFS1_2)
+ if (ufst == 1)
+ Lf->sz = (SZOFFTYPE)d1.di_size;
+ else if (ufst == 2)
+ Lf->sz = (SZOFFTYPE)d2.di_size;
+ else
+#endif /* defined(HAS_UFS1_2) */
+
+ Lf->sz = (SZOFFTYPE)i->i_size;
+ Lf->sz_def = 1;
+ }
+
+
+#if defined(HAS_ZFS)
+ else if (z) {
+ if (z->sz_def) {
+ Lf->sz = z->sz;
+ Lf->sz_def = 1;
+ }
+ }
+#endif /* defined(HAS_ZFS) */
+
+#if FREEBSDV<5000
+ else if (m) {
+ Lf->sz = (SZOFFTYPE)m->mfs_size;
+ Lf->sz_def = 1;
+ }
+#endif /* FREEBSDV<5000 */
+
+#if defined(HAS9660FS)
+ else if (iso_stat) {
+ Lf->sz = (SZOFFTYPE)iso_sz;
+ Lf->sz_def = 1;
+ }
+#endif /* defined(HAS9660FS) */
+
+ }
+ else if ((type == VCHR || type == VBLK) && !Fsize)
+ Lf->off_def = 1;
+ break;
+
+# if defined(HAS_TMPFS)
+ case N_TMP:
+ if ((tnp->tn_type == VBLK || tnp->tn_type == VCHR)
+ && !Fsize) {
+ Lf->off_def = 1;
+ } else {
+ Lf->sz = (SZOFFTYPE)tnp->tn_size;
+ Lf->sz_def = 1;
+ }
+ break;
+# endif /* defined(HAS_TMPFS) */
+
+ }
+ }
+/*
+ * Record the link count.
+ */
+ if (Fnlink) {
+ switch(Ntype) {
+ case N_NFS:
+ if (n) {
+ Lf->nlink = (long)n->n_vattr.va_nlink;
+ Lf->nlink_def = 1;
+ }
+ break;
+ case N_REGLR:
+ if (i) {
+
+#if defined(HASEFFNLINK)
+ Lf->nlink = (long)i->HASEFFNLINK;
+#else /* !defined(HASEFFNLINK) */
+ Lf->nlink = (long)i->i_nlink;
+#endif /* defined(HASEFFNLINK) */
+
+ Lf->nlink_def = 1;
+ }
+
+#if defined(HAS_ZFS)
+ else if (z) {
+ if (z->nl_def) {
+ Lf->nlink = z->nl;
+ Lf->nlink_def = 1;
+ }
+ }
+#endif /* defined(HAS_ZFS) */
+
+#if defined(HAS9660FS)
+ else if (iso_stat) {
+ Lf->nlink = iso_links;
+ Lf->nlink_def = 1;
+ }
+#endif /* defined(HAS9660FS) */
+
+#if FREEBSDV>=5000
+ else if (d) {
+ Lf->nlink = d->de_links;
+ Lf->nlink_def = 1;
+ }
+#endif /* FREEBSDV>=5000 */
+
+ break;
+
+#if defined(HASPSEUODOFS)
+ case N_PSEU:
+ if (pnp) {
+ Lf->nlink = 1L;
+ Lf->nlink_def = 1;
+ }
+ break;
+#endif /* defined(HASPSEUODOFS) */
+
+# if defined(HAS_TMPFS)
+ case N_TMP:
+ if (tnp) {
+ Lf->nlink = (long)tnp->tn_links;
+ Lf->nlink_def = 1;
+ }
+ break;
+# endif /* defined(HAS_TMPFS) */
+
+ }
+ if (Lf->nlink_def && Nlink && (Lf->nlink < Nlink))
+ Lf->sf |= SELNLINK;
+ }
+/*
+ * Record an NFS file selection.
+ */
+ if (Ntype == N_NFS && Fnfs)
+ Lf->sf |= SELNFS;
+/*
+ * Save the file system names.
+ */
+ if (vfs) {
+ Lf->fsdir = vfs->dir;
+ Lf->fsdev = vfs->fsname;
+ }
+/*
+ * Save the device numbers and their states.
+ *
+ * Format the vnode type, and possibly the device name.
+ */
+ Lf->dev = dev;
+ Lf->dev_def = devs;
+ Lf->rdev = rdev;
+ Lf->rdev_def = rdevs;
+ switch (type) {
+ case VNON:
+ ty ="VNON";
+ break;
+ case VREG:
+ case VDIR:
+ ty = (type == VREG) ? "VREG" : "VDIR";
+ break;
+ case VBLK:
+ ty = "VBLK";
+ Ntype = N_BLK;
+ break;
+ case VCHR:
+ ty = "VCHR";
+ Ntype = N_CHR;
+ break;
+ case VLNK:
+ ty = "VLNK";
+ break;
+
+#if defined(VSOCK)
+ case VSOCK:
+ ty = "SOCK";
+ break;
+#endif /* defined(VSOCK) */
+
+ case VBAD:
+ ty = "VBAD";
+ break;
+ case VFIFO:
+ ty = "FIFO";
+ break;
+ default:
+ (void) snpf(Lf->type, sizeof(Lf->type), "%04o", (type & 0xfff));
+ ty = (char *)NULL;
+ }
+ if (ty)
+ (void) snpf(Lf->type, sizeof(Lf->type), "%s", ty);
+ Lf->ntype = Ntype;
+/*
+ * Handle some special cases:
+ *
+ * ioctl(fd, TIOCNOTTY) files;
+ * memory node files;
+ * /proc files.
+ */
+
+ if (type == VBAD)
+ (void) snpf(Namech, Namechl, "(revoked)");
+
+#if FREEBSDV<5000
+ else if (m) {
+ Lf->dev_def = Lf->rdev_def = 0;
+ (void) snpf(Namech, Namechl, "%#x", m->mfs_baseoff);
+ (void) snpf(dev_ch, sizeof(dev_ch), " memory");
+ enter_dev_ch(dev_ch);
+ }
+#endif /* FREEBSDV<5000 */
+
+
+#if defined(HASPROCFS)
+ else if (p) {
+ Lf->dev_def = Lf->rdev_def = 0;
+
+# if FREEBSDV<2000
+ if (type == VDIR)
+ (void) snpf(Namech, Namechl, "/%s", HASPROCFS);
+ else
+ (void) snpf(Namech, Namechl, "/%s/%0*d", HASPROCFS, PNSIZ,
+ p->pfs_pid);
+ enter_nm(Namech);
+# else /* FREEBSDV>=2000 */
+ ty = (char *)NULL;
+ (void) snpf(Namech, Namechl, "/%s", HASPROCFS);
+ switch (p->pfs_type) {
+ case Proot:
+ ty = "PDIR";
+ break;
+ case Pproc:
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "/%d", p->pfs_pid);
+ ty = "PDIR";
+ break;
+ case Pfile:
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "/%d/file", p->pfs_pid);
+ ty = "PFIL";
+ break;
+ case Pmem:
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "/%d/mem", p->pfs_pid);
+ ty = "PMEM";
+ break;
+ case Pregs:
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "/%d/regs", p->pfs_pid);
+ ty = "PREG";
+ break;
+ case Pfpregs:
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "/%d/fpregs", p->pfs_pid);
+ ty = "PFPR";
+ break;
+ case Pctl:
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "/%d/ctl", p->pfs_pid);
+ ty = "PCTL";
+ break;
+ case Pstatus:
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "/%d/status", p->pfs_pid);
+ ty = "PSTA";
+ break;
+ case Pnote:
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "/%d/note", p->pfs_pid);
+ ty = "PNTF";
+ break;
+ case Pnotepg:
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "/%d/notepg", p->pfs_pid);
+ ty = "PGID";
+ break;
+
+# if FREEBSDV>=3000
+ case Pmap:
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "/%d/map", p->pfs_pid);
+ ty = "PMAP";
+ break;
+ case Ptype:
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "/%d/etype", p->pfs_pid);
+ ty = "PETY";
+ break;
+# endif /* FREEBSDV>=3000 */
+
+ }
+ if (ty)
+ (void) snpf(Lf->type, sizeof(Lf->type), "%s", ty);
+ enter_nm(Namech);
+
+# endif /* FREEBSDV<2000 */
+ }
+#endif /* defined(HASPROCFS) */
+
+#if defined(HASBLKDEV)
+/*
+ * If this is a VBLK file and it's missing an inode number, try to
+ * supply one.
+ */
+ if ((Lf->inp_ty == 0) && (type == VBLK))
+ find_bl_ino();
+#endif /* defined(HASBLKDEV) */
+
+/*
+ * If this is a VCHR file and it's missing an inode number, try to
+ * supply one.
+ */
+ if ((Lf->inp_ty == 0) && (type == VCHR))
+ find_ch_ino();
+/*
+ * Test for specified file.
+ */
+
+#if defined(HASPROCFS)
+ if (Ntype == N_PROC) {
+ if (Procsrch) {
+ Procfind = 1;
+ Lf->sf |= SELNM;
+ } else {
+ for (pfi = Procfsid; pfi; pfi = pfi->next) {
+ if ((pfi->pid && pfi->pid == p->pfs_pid)
+
+# if defined(HASPINODEN)
+ || (Lf->inp_ty == 1 && Lf->inode == pfi->inode)
+# else /* !defined(HASPINODEN) */
+ if (pfi->pid == p->pfs_pid)
+# endif /* defined(HASPINODEN) */
+
+ ) {
+ pfi->f = 1;
+ if (!Namech[0])
+ (void) snpf(Namech, Namechl, "%s", pfi->nm);
+ Lf->sf |= SELNM;
+ break;
+ }
+ }
+ }
+ } else
+#endif /* defined(HASPROCFS) */
+
+ {
+ if (Sfile && is_file_named((char *)NULL,
+ ((type == VCHR) || (type == VBLK)) ? 1
+ : 0))
+ Lf->sf |= SELNM;
+ }
+/*
+ * Enter name characters.
+ */
+ if (Namech[0])
+ enter_nm(Namech);
+}
+
+
+#if FREEBSDV>=2020
+/*
+ * process_pipe() - process a file structure whose type is DTYPE_PIPE
+ */
+
+void
+process_pipe(pa)
+ KA_T pa; /* pipe structure address */
+{
+ char dev_ch[32], *ep;
+ struct pipe p;
+ size_t sz;
+
+ if (!pa || kread(pa, (char *)&p, sizeof(p))) {
+ (void) snpf(Namech, Namechl,
+ "can't read DTYPE_PIPE pipe struct: %s",
+ print_kptr((KA_T)pa, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ (void) snpf(Lf->type, sizeof(Lf->type), "PIPE");
+ (void) snpf(dev_ch, sizeof(dev_ch), "%s",
+ print_kptr(pa, (char *)NULL, 0));
+ enter_dev_ch(dev_ch);
+ if (Foffset)
+ Lf->off_def = 1;
+ else {
+ Lf->sz = (SZOFFTYPE)p.pipe_buffer.size;
+ Lf->sz_def = 1;
+ }
+ if (p.pipe_peer)
+ (void) snpf(Namech, Namechl, "->%s",
+ print_kptr((KA_T)p.pipe_peer, (char *)NULL, 0));
+ else
+ Namech[0] = '\0';
+ if (p.pipe_buffer.cnt) {
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, ", cnt=%d", p.pipe_buffer.cnt);
+ }
+ if (p.pipe_buffer.in) {
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, ", in=%d", p.pipe_buffer.in);
+ }
+ if (p.pipe_buffer.out) {
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, ", out=%d", p.pipe_buffer.out);
+ }
+/*
+ * Enter name characters.
+ */
+ if (Namech[0])
+ enter_nm(Namech);
+}
+#endif /* FREEBSDV>=2020 */
diff --git a/dialects/freebsd/dnode1.c b/dialects/freebsd/dnode1.c
new file mode 100644
index 0000000..a5fa225
--- /dev/null
+++ b/dialects/freebsd/dnode1.c
@@ -0,0 +1,144 @@
+/*
+ * dnode1.c - FreeBSD node functions for lsof
+ *
+ * This module must be separate to keep separate the multiple kernel inode
+ * structure definitions.
+ */
+
+
+/*
+ * Copyright 1995 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dnode1.c,v 1.10 2008/10/21 16:16:06 abe Exp abe $";
+#endif
+
+
+#include "lsof.h"
+
+#if defined(HAS9660FS)
+
+/*
+ * Do a little preparation for #include'ing cd9660_node.h, then #include it.
+ */
+
+#undef i_size
+#undef doff_t
+#undef IN_ACCESS
+
+# if FREEBSDV>=4000 && defined(__alpha__)
+#define dev_t void *
+# endif /* FREEBSDV>=4000 && defined(__alpha__) */
+
+#include "cd9660_node.h"
+
+# if defined(HAS_NO_ISO_DEV)
+#define _KERNEL
+#include <isofs/cd9660/iso.h>
+#undef _KERNEL
+# endif /* defined(HAS_NO_ISO_DEV) */
+
+# if FREEBSDV>=4000 && defined(__alpha__)
+#undef dev_t
+# endif /* FREEBSDV>=4000 && defined(__alpha__) */
+
+
+/*
+ * read_iso_node() -- read CD 9660 iso_node
+ */
+
+int
+read_iso_node(v, d, dd, ino, nl, sz)
+ struct vnode *v; /* containing vnode */
+ dev_t *d; /* returned device number */
+ int *dd; /* returned device-defined flag */
+ INODETYPE *ino; /* returned inode number */
+ long *nl; /* returned number of links */
+ SZOFFTYPE *sz; /* returned size */
+{
+
+# if FREEBSDV<2000
+ struct iso_node *ip;
+# else /* FREEBSDV>=2000 */
+ struct iso_node i;
+# endif /* FREEBSDV<2000 */
+
+# if FREEBSDV>=4000
+# if FREEBSDV<5000
+ struct specinfo udev;
+# else /* FREEBSDV>=5000 */
+ struct cdev udev;
+# if defined(HAS_NO_ISO_DEV)
+ struct iso_mnt im;
+# endif /* defined(HAS_NO_ISO_DEV) */
+# endif /* FREEBSDV<5000 */
+# endif /* FREEBSDV>=4000 */
+
+# if FREEBSDV<2000
+ ip = (struct iso_node *)v->v_data;
+ *d = ip->i_dev;
+ *dd = 1;
+ *ino = (INODETYPE)ip->i_number;
+ *nl = (long)ip->inode.iso_links;
+ *sz = (SZOFFTYPE)ip->i_size;
+# else /* FREEBSDV>=2000 */
+ if (!v->v_data
+ || kread((KA_T)v->v_data, (char *)&i, sizeof(i)))
+ return(1);
+
+# if FREEBSDV>=4000
+# if defined(HAS_NO_ISO_DEV)
+ if (i.i_mnt && !kread((KA_T)i.i_mnt, (char *)&im, sizeof(im))
+ && im.im_dev && !kread((KA_T)im.im_dev, (char *)&udev, sizeof(udev)))
+# else /* !defined(HAS_NO_ISO_DEV) */
+ if (i.i_dev && !kread((KA_T)i.i_dev, (char *)&udev, sizeof(udev)))
+# endif /* defined(HAS_NO_ISO_DEV) */
+
+ {
+
+# if defined(HAS_NO_SI_UDEV)
+ *d = Dev2Udev(&udev);
+# else /* !defined(HAS_NO_SI_UDEV) */
+ *d = udev.si_udev;
+# endif /* defined(HAS_NO_SI_UDEV) */
+
+ *dd = 1;
+ }
+# else /* FREEBSDV<4000 */
+ *d = i.i_dev;
+ *dd = 1;
+# endif /* FREEBSDV>=4000 */
+
+ *ino = (INODETYPE)i.i_number;
+ *nl = (long)i.inode.iso_links;
+ *sz = (SZOFFTYPE)i.i_size;
+# endif /* FREEBSDV<2000 */
+
+ return(0);
+}
+#endif /* defined(HAS9660FS) */
diff --git a/dialects/freebsd/dnode2.c b/dialects/freebsd/dnode2.c
new file mode 100644
index 0000000..2ea9d24
--- /dev/null
+++ b/dialects/freebsd/dnode2.c
@@ -0,0 +1,153 @@
+/*
+ * dnode2.c - FreeBSD ZFS node functions for lsof
+ *
+ * This module must be separate to permit use of the OpenSolaris ZFS header
+ * files.
+ */
+
+
+/*
+ * Copyright 2008 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 2008 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dnode2.c,v 1.5 2014/10/13 22:25:07 abe Exp $";
+#endif
+
+
+#if defined(HAS_ZFS)
+
+#define _KERNEL
+
+# if defined(__clang__)
+/*
+ * A clang workaround...
+ *
+ * Note: clang's complaint about VOP_FSYNC can't be avoided.
+ */
+#define VOP_UNLOCK(vp, f) ((void)0)
+# endif /* defined(__clang__) */
+
+#include <sys/zfs_znode.h>
+#undef _KERNEL
+
+#include "dzfs.h"
+
+
+/*
+ * readzfsnode() -- read the ZFS node
+ */
+
+char *
+readzfsnode(za, zi, vr)
+ KA_T za; /* ZFS node address */
+ zfs_info_t *zi; /* return ZFS info structure pointer */
+ int vr; /* vnode's (v_flag & VROOT) */
+{
+ struct znode zn; /* ZFS node */
+
+# if defined(HAS_Z_PHYS)
+ znode_phys_t zp; /* ZFS physical node */
+# else /* !defined(HAS_Z_PHYS) */
+ KA_T ka; /* temporary kernel address */
+ zfsvfs_t zv; /* znode's zfsvfs structure */
+# endif /* defined(HAS_Z_PHYS) */
+
+ memset((void *)zi, 0, sizeof(zfs_info_t));
+ if (!za
+ || kread(za, (char *)&zn, sizeof(zn))
+ ) {
+ if (!za)
+ return("No ZFS node address");
+ return("Can't read znode");
+ }
+/*
+ * Return items contained in the znode.
+ */
+ zi->ino = (INODETYPE)zn.z_id;
+ zi->ino_def = 1;
+
+# if !defined(HAS_V_LOCKF)
+ zi->lockf = (KA_T)zn.z_lockf;
+# endif /* !defined(HAS_V_LOCKF) */
+
+# if defined(HAS_Z_PHYS)
+/*
+ * If the physical znode exists in this ZFS implementation, read it.
+ */
+ if (!zn.z_phys
+ || kread((KA_T)zn.z_phys, (char *)&zp, sizeof(zp))
+ ) {
+ if (!zn.z_phys)
+ return("No physical znode address");
+ return("Can't read physical znode");
+ }
+/*
+ * Return items contained in the physical znode.
+ */
+ zi->nl = (long)zp.zp_links;
+ zi->rdev = zp.zp_rdev;
+ zi->sz = (SZOFFTYPE)zp.zp_size;
+ zi->nl_def = zi->rdev_def = zi->sz_def = 1;
+# else /* !defined(HAS_Z_PHYS) */
+/*
+ * If this implementation has no physical znode, return items now contained
+ * in the znode.
+ */
+ zi->nl = (long)zn.z_links;
+ if (vr && (ka = (KA_T)zn.z_zfsvfs)) {
+ if (!kread(ka, (char *)&zv, sizeof(zv))) {
+ if ((zn.z_id == zv.z_root)
+ && (zv.z_ctldir != NULL)
+ && (zv.z_show_ctldir)
+ ) {
+ zi->nl++;
+ }
+ }
+ }
+ zi->sz = (SZOFFTYPE)zn.z_size;
+ zi->nl_def = zi->sz_def = 1;
+# endif /* defined(HAS_Z_PHYS) */
+
+ return((char *)NULL);
+}
+
+
+
+
+# if defined(__GNUC__) && defined(HAS_CV_TIMEDWAIT_SBT)
+/*
+ * A gcc work-around
+ */
+
+int _cv_timedwait_sbt(struct cv *cvp, struct lock_object *lock,
+ sbintime_t sbt, sbintime_t pr, int flags)
+{
+ return(0);
+}
+# endif /* defined(__GNUC__) && HAS_CV_TIMEDWAIT_SBT */
+#endif /* defined(HAS_ZFS) */
diff --git a/dialects/freebsd/dproc.c b/dialects/freebsd/dproc.c
new file mode 100644
index 0000000..c9eb92c
--- /dev/null
+++ b/dialects/freebsd/dproc.c
@@ -0,0 +1,700 @@
+/*
+ * dproc.c - FreeBSD process access functions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dproc.c,v 1.18 2014/10/13 22:25:07 abe Exp $";
+#endif
+
+#include "lsof.h"
+
+
+_PROTOTYPE(static void enter_vn_text,(KA_T va, int *n));
+_PROTOTYPE(static void get_kernel_access,(void));
+_PROTOTYPE(static void process_text,(KA_T vm));
+
+
+/*
+ * Local static values
+ */
+
+static MALLOC_S Nv = 0; /* allocated Vp[] entries */
+static KA_T *Vp = NULL; /* vnode address cache */
+
+
+/*
+ * enter_vn_text() - enter a vnode text reference
+ */
+
+static void
+enter_vn_text(va, n)
+ KA_T va; /* vnode address */
+ int *n; /* Vp[] entries in use */
+{
+ int i;
+/*
+ * Ignore the request if the vnode has already been entered.
+ */
+ for (i = 0; i < *n; i++) {
+ if (va == Vp[i])
+ return;
+ }
+/*
+ * Save the text file information.
+ */
+ alloc_lfile(" txt", -1);
+ Cfp = (struct file *)NULL;
+ process_node(va);
+ if (Lf->sf)
+ link_lfile();
+ if (i >= Nv) {
+
+ /*
+ * Allocate space for remembering the vnode.
+ */
+ Nv += 10;
+ if (!Vp)
+ Vp=(KA_T *)malloc((MALLOC_S)(sizeof(struct vnode *)*10));
+ else
+ Vp=(KA_T *)realloc((MALLOC_P *)Vp,(MALLOC_S)(Nv*sizeof(KA_T)));
+ if (!Vp) {
+ (void) fprintf(stderr, "%s: no txt ptr space, PID %d\n",
+ Pn, Lp->pid);
+ Exit(1);
+ }
+ }
+/*
+ * Remember the vnode.
+ */
+ Vp[*n] = va;
+ (*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 */
+ struct filedesc fd;
+ int i, nf;
+ MALLOC_S nb;
+
+#if defined(HAS_FILEDESCENT)
+ typedef struct filedescent ofb_t;
+#else /* !defined(HAS_FILEDESCENT) */
+ typedef struct file* ofb_t;
+#endif /* defined(HAS_FILEDESCENT) */
+
+ static ofb_t *ofb = NULL;
+ static int ofbb = 0;
+ int pgid, pid;
+ int ppid = 0;
+ short pss, sf;
+ int px;
+ int tid; /* thread (task) ID */
+ uid_t uid;
+
+#if FREEBSDV<2000
+ struct proc *p;
+ struct pcred pc;
+ struct pgrp pg;
+#else /* FREEBSDV>=2000 */
+ struct kinfo_proc *p;
+#endif /* FREEBSDV<2000 */
+
+#if defined(HASFSTRUCT) && !defined(HAS_FILEDESCENT)
+ static char *pof = (char *)NULL;
+ static int pofb = 0;
+#endif /* defined(HASFSTRUCT) && !defiled(HAS_FILEDESCENT) */
+
+/*
+ * Define socket and regular file conditional processing flags.
+ *
+ * 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;
+ }
+/*
+ * Read the process table.
+ */
+
+#if FREEBSDV<2000
+ if ((Np = kvm_getprocs(KINFO_PROC_ALL, 0)) < 0)
+#else /* FREEBSDV>=2000 */
+
+# if !defined(KERN_PROC_PROC)
+#define KERN_PROC_PROC KERN_PROC_ALL
+# endif /* !defined(KERN_PROC_PROC) */
+
+ if ((P = kvm_getprocs(Kd, Ftask ? KERN_PROC_ALL : KERN_PROC_PROC,
+ 0, &Np))
+ == NULL)
+#endif /* FREEBSDV<2000 */
+
+ {
+ (void) fprintf(stderr, "%s: can't read process table: %s\n",
+ Pn,
+
+#if FREEBSDV<2000
+ kvm_geterr()
+#else /* FREEBSDV>=2000 */
+ kvm_geterr(Kd)
+#endif /* FREEBSDV<2000 */
+
+ );
+ Exit(1);
+ }
+/*
+ * Examine proc structures and their associated information.
+ */
+
+#if FREEBSDV<2000
+ for (px = 0; px < Np; px++)
+#else /* FREEBSDV>=2000 */
+ for (p = P, px = 0; px < Np; p++, px++)
+#endif /* FREEBSDV<2000 */
+
+ {
+
+#if FREEBSDV<2000
+ /*
+ * Read process information, process group structure (if
+ * necessary), and User ID (if necessary).
+ */
+ if (!(p = kvm_nextproc()))
+ continue;
+ if (p->P_STAT == 0 || p->P_STAT == SZOMB)
+ continue;
+ pg.pg_id = 0;
+ if (Fpgid && p->P_PGID) {
+ if (kread((KA_T)p->P_PGID, (char *)&pg, sizeof(pg)))
+ continue;
+ }
+ pgid = pg.pg_id;
+ if (!p->p_cred
+ || kread((KA_T)p->p_cred, (char *)&pc, sizeof(pc)))
+ continue;
+ uid = pc.p_ruid;
+#else /* FREEBSDV>=2000 */
+ if (p->P_STAT == 0 || p->P_STAT == SZOMB)
+ continue;
+ pgid = p->P_PGID;
+# if FREEBSDV<5000
+ uid = p->kp_eproc.e_ucred.cr_uid;
+# else /* FREEBSDV>=5000 */
+ uid = p->ki_uid;
+# endif /* FREEBSDV<5000 */
+#endif /* FREEBSDV<2000 */
+
+#if defined(HASPPID)
+ ppid = p->P_PPID;
+#endif /* defined(HASPPID) */
+
+#if defined(HASTASKS)
+ /*
+ * See if process,including its tasks, is excluded.
+ */
+ tid = Ftask ? (int)p->ki_tid : 0;
+ if (is_proc_excl(p->P_PID, pgid, (UID_ARG)uid, &pss, &sf, tid))
+ continue;
+#else /* !defined(HASTASKS) */
+ /*
+ * See if process is excluded.
+ */
+ if (is_proc_excl(p->P_PID, pgid, (UID_ARG)uid, &pss, &sf))
+ continue;
+#endif /* defined(HASTASKS) */
+
+ /*
+ * Read file structure pointers.
+ */
+ if (!p->P_FD
+ || kread((KA_T)p->P_FD, (char *)&fd, sizeof(fd)))
+ continue;
+ if (!fd.fd_refcnt || fd.fd_lastfile > fd.fd_nfiles)
+ continue;
+ /*
+ * Allocate a local process structure.
+ */
+ if (is_cmd_excl(p->P_COMM, &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(p->P_PID, pgid, ppid, (UID_ARG)uid, p->P_COMM,
+ (int)pss, (int)sf);
+ Plf = (struct lfile *)NULL;
+
+#if defined(HASTASKS)
+ /*
+ * Save the task (thread) ID.
+ */
+ Lp->tid = tid;
+#endif /* defined(HASTASKS) */
+
+#if defined(P_ADDR)
+ /*
+ * Save the kernel proc struct address, if P_ADDR is defined.
+ */
+ Kpa = (KA_T)p->P_ADDR;
+#endif /* defined(P_ADDR) */
+
+ /*
+ * Save current working directory information.
+ */
+ if (!ckscko && fd.fd_cdir) {
+ alloc_lfile(CWD, -1);
+ Cfp = (struct file *)NULL;
+ process_node((KA_T)fd.fd_cdir);
+ if (Lf->sf)
+ link_lfile();
+ }
+ /*
+ * Save root directory information.
+ */
+ if (!ckscko && fd.fd_rdir) {
+ alloc_lfile(RTD, -1);
+ Cfp = (struct file *)NULL;
+ process_node((KA_T)fd.fd_rdir);
+ if (Lf->sf)
+ link_lfile();
+ }
+
+#if FREEBSDV>=5000
+ /*
+ * Save jail directory information.
+ */
+ if (!ckscko && fd.fd_jdir) {
+ alloc_lfile("jld", -1);
+ Cfp = (struct file *)NULL;
+ process_node((KA_T)fd.fd_jdir);
+ if (Lf->sf)
+ link_lfile();
+ }
+#endif /* FREEBSDV>=5000 */
+
+ /*
+ * Save information on the text file.
+ */
+ if (!ckscko && p->P_VMSPACE)
+ process_text((KA_T)p->P_VMSPACE);
+ /*
+ * Read open file structure pointers.
+ */
+ if (!fd.fd_ofiles || (nf = fd.fd_nfiles) <= 0)
+ continue;
+ nb = (MALLOC_S)(sizeof(ofb_t) * nf);
+ if (nb > ofbb) {
+ if (!ofb)
+ ofb = (ofb_t *)malloc(nb);
+ else
+ ofb = (ofb_t *)realloc((MALLOC_P *)ofb, nb);
+ if (!ofb) {
+ (void) fprintf(stderr, "%s: PID %d, no file * space\n",
+ Pn, p->P_PID);
+ Exit(1);
+ }
+ ofbb = nb;
+ }
+ if (kread((KA_T)fd.fd_ofiles, (char *)ofb, nb))
+ continue;
+
+#if defined(HASFSTRUCT) && !defined(HAS_FILEDESCENT)
+ if (Fsv & FSV_FG) {
+ nb = (MALLOC_S)(sizeof(char) * nf);
+ if (nb > pofb) {
+ if (!pof)
+ pof = (char *)malloc(nb);
+ else
+ pof = (char *)realloc((MALLOC_P *)pof, nb);
+ if (!pof) {
+ (void) fprintf(stderr,
+ "%s: PID %d, no file flag space\n", Pn, p->P_PID);
+ Exit(1);
+ }
+ pofb = nb;
+ }
+ if (!fd.fd_ofileflags || kread((KA_T)fd.fd_ofileflags, pof, nb))
+ zeromem(pof, nb);
+ }
+#endif /* defined(HASFSTRUCT) && !defined(HAS_FILEDESCENT) */
+
+ /*
+ * Save information on file descriptors.
+ */
+ for (i = 0; i < nf; i++) {
+
+#if defined(HAS_FILEDESCENT)
+ if ((Cfp = ofb[i].fde_file))
+#else /* !defined(HAS_FILEDESCENT) */
+ if ((Cfp = ofb[i]))
+#endif /* defined(HAS_FILEDESCENT) */
+
+ {
+ alloc_lfile(NULL, i);
+ process_file((KA_T)Cfp);
+ if (Lf->sf) {
+
+#if defined(HASFSTRUCT)
+ if (Fsv & FSV_FG)
+# if defined(HAS_FILEDESCENT)
+ Lf->pof = (long)ofb[i].fde_flags;
+# else /* !defined(HAS_FILEDESCENT) */
+ Lf->pof = (long)pof[i];
+# endif /* defined(HAS_FILEDESCENT) */
+#endif /* defined(HASFSTRUCT) */
+
+ link_lfile();
+ }
+ }
+ }
+ /*
+ * Unless threads (tasks) are being processed, examine results.
+ */
+ if (!Ftask) {
+ if (examine_lproc())
+ return;
+ }
+ }
+}
+
+
+/*
+ * get_kernel_access() - get access to kernel memory
+ */
+
+static void
+get_kernel_access()
+{
+
+/*
+ * Check kernel version.
+ */
+ (void) ckkv("FreeBSD", LSOF_VSTR, (char *)NULL, (char *)NULL);
+/*
+ * Set name list file path.
+ */
+ if (!Nmlst)
+
+#if defined(N_UNIX)
+ Nmlst = N_UNIX;
+#else /* !defined(N_UNIX) */
+ {
+ if (!(Nmlst = get_nlist_path(1))) {
+ (void) fprintf(stderr,
+ "%s: can't get kernel name list path\n", Pn);
+ Exit(1);
+ }
+ }
+#endif /* defined(N_UNIX) */
+
+#if defined(WILLDROPGID)
+/*
+ * If kernel memory isn't coming from KMEM, drop setgid permission
+ * before attempting to open the (Memory) file.
+ */
+ if (Memory)
+ (void) dropgid();
+#else /* !defined(WILLDROPGID) */
+/*
+ * See if the non-KMEM memory and the name list files are readable.
+ */
+ if ((Memory && !is_readable(Memory, 1))
+ || (Nmlst && !is_readable(Nmlst, 1)))
+ Exit(1);
+#endif /* defined(WILLDROPGID) */
+
+/*
+ * Open kernel memory access.
+ */
+
+#if FREEBSDV<2000
+ if (kvm_openfiles(Nmlst, Memory, NULL) == -1)
+#else /* FREEBSDV>=2000 */
+ if ((Kd = kvm_open(Nmlst, Memory, NULL, O_RDONLY, NULL)) == NULL)
+#endif /* FREEBSDV<2000 */
+
+ {
+ (void) fprintf(stderr,
+ "%s: kvm_open%s(execfile=%s, corefile=%s): %s\n",
+ Pn,
+
+#if FREEBSDV<2000
+ "files",
+#else /* FREEBSDV>=2000 */
+ "",
+#endif /* FREEBSDV<2000 */
+
+ Nmlst ? Nmlst : "default",
+ Memory ? Memory :
+
+#if defined(_PATH_MEM)
+ _PATH_MEM,
+#else /* !defined(_PATH_MEM) */
+ "default",
+#endif /* defined(_PATH_MEM) */
+
+ strerror(errno));
+ Exit(1);
+ }
+ (void) build_Nl(Drive_Nl);
+ if (kvm_nlist(Kd, Nl) < 0) {
+ (void) fprintf(stderr, "%s: can't read namelist from %s\n",
+ Pn, Nmlst);
+ Exit(1);
+ }
+
+#if defined(WILLDROPGID)
+/*
+ * Drop setgid permission, if necessary.
+ */
+ if (!Memory)
+ (void) dropgid();
+#endif /* defined(WILLDROPGID) */
+
+}
+
+
+#if !defined(N_UNIX)
+/*
+ * get_nlist_path() - get kernel name list path
+ */
+
+char *
+get_nlist_path(ap)
+ int ap; /* on success, return an allocated path
+ * string pointer if 1; return a
+ * constant character pointer if 0;
+ * return NULL if failure */
+{
+ const char *bf;
+ static char *bfc;
+ MALLOC_S bfl;
+/*
+ * Get bootfile name.
+ */
+ if ((bf = getbootfile())) {
+ if (!ap)
+ return("");
+ bfl = (MALLOC_S)(strlen(bf) + 1);
+ if (!(bfc = (char *)malloc(bfl))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d bytes for boot file path: %s\n",
+ Pn, (int)bfl, bf);
+ Exit(1);
+ }
+ (void) snpf(bfc, bfl, "%s", bf);
+ return(bfc);
+ }
+ return((char *)NULL);
+}
+#endif /* !defined(N_UNIX) */
+
+
+/*
+ * initialize() - perform all initialization
+ */
+
+void
+initialize()
+{
+ get_kernel_access();
+}
+
+
+/*
+ * kread() - read from kernel memory
+ */
+
+int
+kread(addr, buf, len)
+ KA_T addr; /* kernel memory address */
+ char *buf; /* buffer to receive data */
+ READLEN_T len; /* length to read */
+{
+ int br;
+
+#if FREEBSDV<2000
+ br = kvm_read((void *)addr, (void *)buf, len);
+#else /* FREEBSDV>=2000 */
+ br = kvm_read(Kd, (u_long)addr, buf, len);
+#endif /* FREEBSDV<2000 */
+
+ return((br == len) ? 0 : 1);
+}
+
+
+/*
+ * process_text() - process text information
+ */
+void
+process_text(vm)
+ KA_T vm; /* vm space pointer */
+{
+ int i, j;
+ KA_T ka;
+ int n = 0;
+ struct vm_map_entry vmme, *e;
+ struct vm_object vmo;
+ struct vmspace vmsp;
+
+#if FREEBSDV<2020
+ struct pager_struct pg;
+#endif /* FREEBSDV<2020 */
+
+/*
+ * Read the vmspace structure for the process.
+ */
+ if (kread(vm, (char *)&vmsp, sizeof(vmsp)))
+ return;
+/*
+ * Read the vm_map structure. Search its vm_map_entry structure list.
+ */
+ for (i = 0; i < vmsp.vm_map.nentries; i++) {
+
+ /*
+ * Read the next vm_map_entry.
+ */
+ if (i == 0)
+ e = &vmsp.vm_map.header;
+ else {
+ if (!(ka = (KA_T)e->next))
+ return;
+ e = &vmme;
+ if (kread(ka, (char *)e, sizeof(vmme)))
+ return;
+ }
+
+#if defined(MAP_ENTRY_IS_A_MAP)
+ if (e->eflags & (MAP_ENTRY_IS_A_MAP|MAP_ENTRY_IS_SUB_MAP))
+#else /* !defined(MAP_ENTRY_IS_A_MAP) */
+ if (e->is_a_map || e->is_sub_map)
+#endif /* defined(MAP_ENTRY_IS_A_MAP) */
+
+ continue;
+ /*
+ * Read the map entry's object and the object's shadow.
+ * Look for: a PG_VNODE pager handle (FreeBSD < 2.2);
+ * an OBJT_VNODE object type (FreeBSD >= 2.2).
+ */
+ for (j = 0, ka = (KA_T)e->object.vm_object;
+ j < 2 && ka;
+ j++,
+
+#if FREEBSDV<2020
+ ka = (KA_T)vmo.shadow
+#else /* FREEBSDV>=2020 */
+ ka = (KA_T)vmo.backing_object
+#endif /* FREEBSDV<2020 */
+ )
+ {
+ if (kread(ka, (char *)&vmo, sizeof(vmo)))
+ break;
+
+#if FREEBSDV<2020
+ if ((ka = (KA_T)vmo.pager) == NULL
+ || kread(ka, (char *)&pg, sizeof(pg)))
+ continue;
+ if (pg.pg_handle == NULL || pg.pg_type != PG_VNODE)
+ continue;
+ (void) (enter_vn_text((KA_T)pg.pg_handle, &n));
+#else /* FREEBSDV>=2020 */
+ if (vmo.type != OBJT_VNODE
+ || vmo.handle == (void *)NULL)
+ continue;
+ (void) (enter_vn_text((KA_T)vmo.handle, &n));
+#endif /* FREEBSDV<2020 */
+
+ }
+ }
+}
diff --git a/dialects/freebsd/dproto.h b/dialects/freebsd/dproto.h
new file mode 100644
index 0000000..cc23cf7
--- /dev/null
+++ b/dialects/freebsd/dproto.h
@@ -0,0 +1,66 @@
+/*
+ * dproto.h - FreeBSD function prototypes for lsof
+ *
+ * The _PROTOTYPE macro is defined in the common proto.h.
+ */
+
+
+/*
+ * Copyright 1994 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.
+ */
+
+
+/*
+ * $Id: dproto.h,v 1.14 2009/03/25 19:23:06 abe Exp $
+ */
+
+
+#if FREEBSDV>=5000 && defined(HAS_NO_SI_UDEV)
+# if defined(HAS_CONF_MINOR)|| defined(HAS_CDEV2PRIV)
+_PROTOTYPE(extern dev_t Dev2Udev,(KA_T c));
+# else /* !defined(HAS_CONF_MINOR) && !defined(HAS_CDEV2PRIV) */
+_PROTOTYPE(extern dev_t Dev2Udev,(struct cdev *c));
+# endif /* defined(HAS_CONF_MINOR) || defined(HAS_CDEV2PRIV) */
+#endif /* FREEBSDV>=5000 && defined(HAS_NO_SI_UDEV) */
+
+#if !defined(N_UNIX)
+_PROTOTYPE(extern char *get_nlist_path,(int ap));
+#endif /* !defined(N_UNIX) */
+
+_PROTOTYPE(extern int is_file_named,(char *p, int cd));
+_PROTOTYPE(extern void process_socket,(KA_T sa));
+_PROTOTYPE(extern struct l_vfs *readvfs,(KA_T vm));
+
+#if defined(HASKQUEUE)
+_PROTOTYPE(extern void process_kqueue,(KA_T ka));
+#endif /* defined(HASKQUEUE) */
+
+#if FREEBSDV>=2020
+_PROTOTYPE(extern void process_pipe,(KA_T pa));
+#endif /* FREEBSDV>=2020 */
+
+#if defined(HAS9660FS)
+_PROTOTYPE(extern int read_iso_node,(struct vnode *v, dev_t *d, int *dd, INODETYPE *ino, long *nl, SZOFFTYPE *sz));
+#endif /* defined(HAS9660FS) */
diff --git a/dialects/freebsd/dsock.c b/dialects/freebsd/dsock.c
new file mode 100644
index 0000000..6f8dd96
--- /dev/null
+++ b/dialects/freebsd/dsock.c
@@ -0,0 +1,535 @@
+/*
+ * dsock.c - FreeBSD socket processing functions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dsock.c,v 1.29 2013/01/02 17:01:43 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+#if defined(HASIPv6)
+
+/*
+ * IPv6_2_IPv4() -- macro to define the address of an IPv4 address contained
+ * in an IPv6 address
+ */
+
+#define IPv6_2_IPv4(v6) (((uint8_t *)((struct in6_addr *)v6)->s6_addr)+12)
+
+# if defined(HAS_NO_6PORT)
+/*
+ * If the in_pcb structure no longer has the KAME accommodations of
+ * in6p_[fl]port, redefine them to inp_[fl]port.
+ */
+
+#define in6p_fport inp_fport
+#define in6p_lport inp_lport
+# endif /* defined(HAS_NO_6PORT) */
+
+# if defined(HAS_NO_6PPCB)
+/*
+ * If the in_pcb structure no longer has the KAME accommodation of in6p_pcb,
+ * redefine it to inp_ppcb.
+ */
+
+#define in6p_ppcb inp_ppcb
+# endif /* defined(HAS_NO_6PPCB) */
+#endif /* defined(HASIPv6) */
+
+
+/*
+ * Local function prototypes
+ */
+
+_PROTOTYPE(static int ckstate,(KA_T ta, struct tcpcb *t, int fam));
+
+
+/*
+ * ckstate() -- read TCP control block and check TCP state for inclusion
+ * or exclusion
+ * return: -1 == no TCP CB available
+ * 0 == TCP DB available; continue processing file
+ * 1 == stop processing file
+ */
+
+static int
+ckstate(ta, t, fam)
+ KA_T ta; /* TCP control block address */
+ struct tcpcb *t; /* TCP control block receptor */
+ int fam; /* protocol family */
+{
+ int tsnx;
+/*
+ * Read TCP control block.
+ */
+ if (kread(ta, (char *)t, sizeof(struct tcpcb)))
+ return(-1);
+ if (TcpStXn || TcpStIn) {
+
+ /*
+ * If there are TCP state inclusions or exclusions, check them.
+ */
+ tsnx = (int)t->t_state + TcpStOff;
+ if (TcpStXn) {
+ if (TcpStX[tsnx]) {
+ Lf->sf &= ~SELNET;
+ Lf->sf |= SELEXCLF;
+ return(1);
+ }
+ }
+ if (TcpStIn) {
+ if (TcpStI[tsnx]) {
+ TcpStI[tsnx] = 2;
+ Lf->sf |= SELNET;
+ } else {
+ Lf->sf &= ~SELNET;
+ Lf->sf |= SELEXCLF;
+ return(1);
+ }
+ }
+ }
+ if (!(Lf->sf & SELNET) && !TcpStIn) {
+
+ /*
+ * See if this TCP file should be selected.
+ */
+ if (Fnet) {
+ if (!FnetTy
+ || ((FnetTy == 4) && (fam == AF_INET))
+
+#if defined(HASIPv6)
+ || ((FnetTy == 6) && (fam == AF_INET6))
+#endif /* defined(HASIPv6) */
+
+ ) {
+ Lf->sf |= SELNET;
+ }
+ }
+ }
+ return(0);
+}
+
+
+/*
+ * process_socket() - process socket
+ */
+
+void
+process_socket(sa)
+ KA_T sa; /* socket address in kernel */
+{
+ struct domain d;
+ unsigned char *fa = (unsigned char *)NULL;
+ int fam;
+ int fp, lp;
+ struct inpcb inp;
+ unsigned char *la = (unsigned char *)NULL;
+ struct protosw p;
+ struct socket s;
+ struct tcpcb t;
+ int ts = -1;
+ struct unpcb uc, unp;
+ struct sockaddr_un *ua = NULL;
+ struct sockaddr_un un;
+
+#if FREEBSDV<4050
+ struct mbuf mb;
+#else /* FREEBSDV>=4050 */
+ int unl;
+#endif /* FREEBSDV<4050 */
+
+#if defined(HASIPv6) && !defined(HASINRIAIPv6)
+ struct in6pcb in6p;
+#endif /* defined(HASIPv6) && !defined(HASINRIAIPv6) */
+
+ (void) snpf(Lf->type, sizeof(Lf->type), "sock");
+ Lf->inp_ty = 2;
+/*
+ * Read the socket, protocol, and domain structures.
+ */
+ if (!sa) {
+ enter_nm("no socket address");
+ return;
+ }
+ if (kread(sa, (char *) &s, sizeof(s))) {
+ (void) snpf(Namech, Namechl, "can't read socket struct from %s",
+ print_kptr(sa, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ if (!s.so_type) {
+ enter_nm("no socket type");
+ return;
+ }
+ if (!s.so_proto
+ || kread((KA_T)s.so_proto, (char *)&p, sizeof(p))) {
+ (void) snpf(Namech, Namechl, "can't read protocol switch from %s",
+ print_kptr((KA_T)s.so_proto, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ if (!p.pr_domain
+ || kread((KA_T)p.pr_domain, (char *)&d, sizeof(d))) {
+ (void) snpf(Namech, Namechl, "can't read domain struct from %s",
+ print_kptr((KA_T)p.pr_domain, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+/*
+ * Save size information.
+ */
+ if (Fsize) {
+ if (Lf->access == 'r')
+ Lf->sz = (SZOFFTYPE)s.so_rcv.sb_cc;
+ else if (Lf->access == 'w')
+ Lf->sz = (SZOFFTYPE)s.so_snd.sb_cc;
+ else
+ Lf->sz = (SZOFFTYPE)(s.so_rcv.sb_cc + s.so_snd.sb_cc);
+ Lf->sz_def = 1;
+ } else
+ Lf->off_def = 1;
+
+#if defined(HASTCPTPIQ)
+ Lf->lts.rq = s.so_rcv.sb_cc;
+ Lf->lts.sq = s.so_snd.sb_cc;
+ Lf->lts.rqs = Lf->lts.sqs = 1;
+#endif /* defined(HASTCPTPIQ) */
+
+#if defined(HASSOOPT)
+ Lf->lts.ltm = (unsigned int)s.so_linger;
+ Lf->lts.opt = (unsigned int)s.so_options;
+ Lf->lts.pqlen = (unsigned int)s.so_incqlen;
+ Lf->lts.qlen = (unsigned int)s.so_qlen;
+ Lf->lts.qlim = (unsigned int)s.so_qlimit;
+ Lf->lts.rbsz = (unsigned long)s.so_rcv.sb_mbmax;
+ Lf->lts.sbsz = (unsigned long)s.so_snd.sb_mbmax;
+ Lf->lts.pqlens = Lf->lts.qlens = Lf->lts.qlims = Lf->lts.rbszs
+ = Lf->lts.sbszs = (unsigned char)1;
+#endif /* defined(HASSOOPT) */
+
+#if defined(HASSOSTATE)
+ Lf->lts.ss = (unsigned int)s.so_state;
+# if defined(HASSBSTATE)
+ Lf->lts.sbs_rcv = s.so_rcv.sb_state;
+ Lf->lts.sbs_snd = s.so_snd.sb_state;
+# endif /* defined(HASSBSTATE) */
+#endif /* defined(HASSOSTATE) */
+
+/*
+ * Process socket by the associated domain family.
+ */
+ switch ((fam = d.dom_family)) {
+/*
+ * Process an Internet domain socket.
+ */
+ case AF_INET:
+
+#if defined(HASIPv6)
+ case AF_INET6:
+#endif /* defined(HASIPv6) */
+
+ if (Fnet) {
+ if (!FnetTy
+ || ((FnetTy == 4) && (fam == AF_INET))
+
+#if defined(HASIPv6)
+ || ((FnetTy == 6) && (fam == AF_INET6))
+#endif /* defined(HASIPv6) */
+
+ ) {
+ if (!TcpStIn && !UdpStIn)
+ Lf->sf |= SELNET;
+ }
+ }
+ printiproto(p.pr_protocol);
+
+#if defined(HASIPv6)
+ (void) snpf(Lf->type, sizeof(Lf->type),
+ (fam == AF_INET) ? "IPv4" : "IPv6");
+#else /* !defined(HASIPv6) */
+ (void) snpf(Lf->type, sizeof(Lf->type), "inet");
+#endif /* defined(HASIPv6) */
+
+#if defined(HASIPv6) && !defined(HASINRIAIPv6)
+ if (fam == AF_INET6) {
+
+ /*
+ * Read IPv6 protocol control block.
+ */
+ if (!s.so_pcb
+ || kread((KA_T)s.so_pcb, (char *)&in6p, sizeof(in6p))) {
+ (void) snpf(Namech, Namechl, "can't read in6pcb at %s",
+ print_kptr((KA_T)s.so_pcb, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ /*
+ * Save IPv6 address information.
+ */
+ if (p.pr_protocol == IPPROTO_TCP) {
+ if (in6p.in6p_ppcb) {
+ if ((ts = ckstate((KA_T)in6p.in6p_ppcb, &t, fam)) == 1)
+ return;
+ }
+ }
+ enter_dev_ch(print_kptr((KA_T)(in6p.in6p_ppcb ? in6p.in6p_ppcb
+ : s.so_pcb),
+ (char *)NULL, 0));
+ la = (unsigned char *)&in6p.in6p_laddr;
+ lp = (int)ntohs(in6p.in6p_lport);
+ if (!IN6_IS_ADDR_UNSPECIFIED(&in6p.in6p_faddr)
+ || in6p.in6p_fport)
+ {
+ fa = (unsigned char *)&in6p.in6p_faddr;
+ fp = (int)ntohs(in6p.in6p_fport);
+ }
+ } else
+#endif /* defined(HASIPv6) && !defined(HASINRIAIPv6) */
+
+ {
+
+ /*
+ * Read Ipv4 or IPv6 (INRIA) protocol control block.
+ */
+ if (!s.so_pcb
+ || kread((KA_T) s.so_pcb, (char *) &inp, sizeof(inp))) {
+ if (!s.so_pcb) {
+ (void) snpf(Namech, Namechl, "no PCB%s%s",
+
+#if defined(HASSBSTATE)
+ (s.so_snd.sb_state & SBS_CANTSENDMORE) ?
+#else /* !defined(HASSBSTATE) */
+ (s.so_state & SS_CANTSENDMORE) ?
+#endif /* defined(HASSBSTATE) */
+
+ ", CANTSENDMORE" : "",
+#if defined(HASSBSTATE)
+ (s.so_rcv.sb_state & SBS_CANTRCVMORE) ?
+#else /* !defined(HASSBSTATE) */
+ (s.so_state & SS_CANTRCVMORE) ?
+#endif /* defined(HASSBSTATE) */
+
+ ", CANTRCVMORE" : "");
+ } else {
+ (void) snpf(Namech, Namechl, "can't read inpcb at %s",
+ print_kptr((KA_T)s.so_pcb, (char *)NULL, 0));
+ }
+ enter_nm(Namech);
+ return;
+ }
+ if (p.pr_protocol == IPPROTO_TCP) {
+ if (inp.inp_ppcb) {
+ if ((ts = ckstate((KA_T)inp.inp_ppcb, &t, fam)) == 1)
+ return;
+ }
+ }
+ enter_dev_ch(print_kptr((KA_T)(inp.inp_ppcb ? inp.inp_ppcb
+ : s.so_pcb),
+ (char *)NULL, 0));
+ lp = (int)ntohs(inp.inp_lport);
+ if (fam == AF_INET) {
+
+ /*
+ * Save IPv4 address information.
+ */
+ la = (unsigned char *)&inp.inp_laddr;
+ if (inp.inp_faddr.s_addr != INADDR_ANY || inp.inp_fport) {
+ fa = (unsigned char *)&inp.inp_faddr;
+ fp = (int)ntohs(inp.inp_fport);
+ }
+ }
+
+#if defined(HASIPv6) && defined(HASINRIAIPv6)
+ else {
+ la = (unsigned char *)&inp.inp_laddr6;
+ if (!IN6_IS_ADDR_UNSPECIFIED(&inp.inp_faddr6)
+ || inp.inp_fport)
+ {
+ fa = (unsigned char *)&inp.inp_faddr6;
+ fp = (int)ntohs(inp.inp_fport);
+ }
+ }
+#endif /* defined(HASIPv6) && defined(HASINRIAIPv6) */
+
+ }
+
+
+#if defined(HASIPv6)
+ if ((fam == AF_INET6)
+ && ((la && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)la))
+ || ((fa && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)fa))))) {
+
+ /*
+ * Adjust for IPv4 addresses mapped in IPv6 addresses.
+ */
+ if (la)
+ la = (unsigned char *)IPv6_2_IPv4(la);
+ if (fa)
+ fa = (unsigned char *)IPv6_2_IPv4(fa);
+ fam = AF_INET;
+ }
+#endif /* defined(HASIPv6) */
+
+ /*
+ * Enter local and remote addresses by address family.
+ */
+ if (fa || la)
+ (void) ent_inaddr(la, lp, fa, fp, fam);
+ if (ts == 0) {
+ Lf->lts.type = 0;
+ Lf->lts.state.i = (int)t.t_state;
+
+#if defined(HASTCPOPT)
+ Lf->lts.mss = (unsigned long)t.t_maxseg;
+ Lf->lts.msss = (unsigned char)1;
+ Lf->lts.topt = (unsigned int)t.t_flags;
+#endif /* defined(HASTCPOPT) */
+
+ }
+ break;
+/*
+ * Process a ROUTE domain socket.
+ */
+ case AF_ROUTE:
+ (void) snpf(Lf->type, sizeof(Lf->type), "rte");
+ if (s.so_pcb)
+ enter_dev_ch(print_kptr((KA_T)(s.so_pcb), (char *)NULL, 0));
+ else
+ (void) snpf(Namech, Namechl, "no protocol control block");
+ if (!Fsize)
+ Lf->off_def = 1;
+ break;
+/*
+ * Process a Unix domain socket.
+ */
+ case AF_UNIX:
+ if (Funix)
+ Lf->sf |= SELUNX;
+ (void) snpf(Lf->type, sizeof(Lf->type), "unix");
+ /*
+ * Read Unix protocol control block and the Unix address structure.
+ */
+
+ enter_dev_ch(print_kptr(sa, (char *)NULL, 0));
+ if (kread((KA_T) s.so_pcb, (char *) &unp, sizeof(unp))) {
+ (void) snpf(Namech, Namechl, "can't read unpcb at %s",
+ print_kptr((KA_T)s.so_pcb, (char *)NULL, 0));
+ break;
+ }
+ if ((struct socket *)sa != unp.unp_socket) {
+ (void) snpf(Namech, Namechl, "unp_socket (%s) mismatch",
+ print_kptr((KA_T)unp.unp_socket, (char *)NULL, 0));
+ break;
+ }
+ if (unp.unp_addr) {
+
+#if FREEBSDV<4050
+ if (kread((KA_T)unp.unp_addr, (char *)&mb, sizeof(mb)))
+#else /* FREEBSDV>=4050 */
+ if (kread((KA_T)unp.unp_addr, (char *)&un, sizeof(un)))
+#endif /* FREEBSDV<4050 */
+
+ {
+ (void) snpf(Namech, Namechl, "can't read unp_addr at %s",
+ print_kptr((KA_T)unp.unp_addr, (char *)NULL, 0));
+ break;
+ }
+
+#if FREEBSDV<4050
+ if (mb.m_hdr.mh_len == sizeof(struct sockaddr_un))
+ ua = (struct sockaddr_un *) ((char *) &mb
+ + (mb.m_hdr.mh_data - (caddr_t) unp.unp_addr));
+#else /* FREEBSDV>=4050 */
+ ua = &un;
+#endif /* FREEBSDV<4050 */
+
+ }
+ if (!ua) {
+ ua = &un;
+ (void) bzero((char *)ua, sizeof(un));
+ ua->sun_family = AF_UNSPEC;
+ }
+ /*
+ * Print information on Unix socket that has no address bound
+ * to it, although it may be connected to another Unix domain
+ * socket as a pipe.
+ */
+ if (ua->sun_family != AF_UNIX) {
+ if (ua->sun_family == AF_UNSPEC) {
+ if (unp.unp_conn) {
+ if (kread((KA_T)unp.unp_conn, (char *)&uc, sizeof(uc)))
+ (void) snpf(Namech, Namechl,
+ "can't read unp_conn at %s",
+ print_kptr((KA_T)unp.unp_conn,(char *)NULL,0));
+ else
+ (void) snpf(Namech, Namechl, "->%s",
+ print_kptr((KA_T)uc.unp_socket,(char *)NULL,0));
+ } else
+ (void) snpf(Namech, Namechl, "->(none)");
+ } else
+ (void) snpf(Namech, Namechl, "unknown sun_family (%d)",
+ ua->sun_family);
+ break;
+ }
+ if (ua->sun_path[0]) {
+
+#if FREEBSDV<4050
+ if (mb.m_len >= sizeof(struct sockaddr_un))
+ mb.m_len = sizeof(struct sockaddr_un) - 1;
+ *((char *)ua + mb.m_len) = '\0';
+#else /* FREEBSDV>=4050 */
+# if FREEBSDV>4060
+ unl = ua->sun_len - offsetof(struct sockaddr_un, sun_path);
+# else /* FREEBSDV<4060 */
+ unl = sizeof(ua->sun_path) - 1;
+# endif /* FREEBSDV>4060 */
+ if ((unl < 0) || (unl >= sizeof(ua->sun_path)))
+ unl = sizeof(ua->sun_path) - 1;
+ ua->sun_path[unl] = '\0';
+#endif /* FREEBSDV<4050 */
+
+ if (ua->sun_path[0] && Sfile && is_file_named(ua->sun_path, 0))
+ Lf->sf |= SELNM;
+ if (ua->sun_path[0] && !Namech[0])
+ (void) snpf(Namech, Namechl, "%s", ua->sun_path);
+ } else
+ (void) snpf(Namech, Namechl, "no address");
+ break;
+ default:
+ printunkaf(fam, 1);
+ }
+ if (Namech[0])
+ enter_nm(Namech);
+}
diff --git a/dialects/freebsd/dstore.c b/dialects/freebsd/dstore.c
new file mode 100644
index 0000000..99239bd
--- /dev/null
+++ b/dialects/freebsd/dstore.c
@@ -0,0 +1,131 @@
+/*
+ * dstore.c - FreeBSD global storage for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dstore.c,v 1.8 2008/04/15 13:31:47 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+struct file *Cfp; /* curent file's file struct pointer */
+
+
+/*
+ * Drive_Nl -- table to drive the building of Nl[] via build_Nl()
+ * (See lsof.h and misc.c.)
+ */
+
+struct drive_Nl Drive_Nl[] = {
+
+#if FREEBSDV<2005
+ { X_NCACHE, "_nchhead" },
+#else /* FREEBSDV>=2005 */
+# if FREEBSDV<2010
+ { X_NCACHE, "_nclruhead" },
+# else /* FREEBSDV>=2010 */
+ { X_NCACHE, "_nchashtbl" },
+# endif /* FREEBSDV<2010 */
+#endif /* FREEBSDV<2005 */
+
+#if FREEBSDV<2010
+ { X_NCSIZE, "_numcache" },
+#else /* FREEBSDV>=2010 */
+ { X_NCSIZE, "_nchash" },
+#endif /* FREEBSDV<2010 */
+
+ { "", "" },
+ { NULL, NULL }
+};
+
+#if FREEBSDV>=2000
+kvm_t *Kd = NULL; /* kvm descriptor */
+#endif /* FREEBSDV>=2000 */
+
+#if defined(P_ADDR)
+KA_T Kpa; /* kernel proc struct address */
+#endif /* defined(P_ADDR) */
+
+struct l_vfs *Lvfs = NULL; /* local vfs structure table */
+
+int Np = 0; /* number of kernel processes */
+
+#if FREEBSDV>=2000
+struct kinfo_proc *P = NULL; /* local process table copy */
+#endif /* FREEBSDV>=2000 */
+
+#if defined(HASFSTRUCT)
+/*
+ * Pff_tab[] - table for printing file flags
+ */
+
+struct pff_tab Pff_tab[] = {
+ { (long)FREAD, FF_READ },
+ { (long)FWRITE, FF_WRITE },
+ { (long)FNONBLOCK, FF_NBLOCK },
+ { (long)FNDELAY, FF_NDELAY },
+ { (long)FAPPEND, FF_APPEND },
+ { (long)FASYNC, FF_ASYNC },
+ { (long)FFSYNC, FF_FSYNC },
+
+# if defined(FMARK)
+ { (long)FMARK, FF_MARK },
+# endif /* defined(FMARK) */
+
+# if defined(FDEFER)
+ { (long)FDEFER, FF_DEFER },
+# endif /* defined(FDEFER) */
+
+ { (long)FHASLOCK, FF_HASLOCK },
+ { (long)O_NOCTTY, FF_NOCTTY },
+ { (long)0, NULL }
+};
+
+
+/*
+ * Pof_tab[] - table for print process open file flags
+ */
+
+struct pff_tab Pof_tab[] = {
+
+# if defined(UF_EXCLOSE)
+ { (long)UF_EXCLOSE, POF_CLOEXEC },
+# endif /* defined(UF_EXCLOSE) */
+
+# if defined(UF_MAPPED)
+ { (long)UF_MAPPED, POF_MAPPED },
+# endif /* defined(UF_MAPPED) */
+
+ { (long)0, NULL }
+};
+#endif /* defined(HASFSTRUCT) */
diff --git a/dialects/freebsd/dzfs.h b/dialects/freebsd/dzfs.h
new file mode 100644
index 0000000..6ffe7de
--- /dev/null
+++ b/dialects/freebsd/dzfs.h
@@ -0,0 +1,112 @@
+/*
+ * dzfs.h - FreeBSD header file for ZFS
+ */
+
+
+/*
+ * Copyright 2008 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.
+ */
+
+
+/*
+ * $Id: dzfs.h,v 1.3 2011/08/07 22:51:28 abe Exp $
+ */
+
+
+#if !defined(FREEBSD_ZFS_H)
+#define FREEBSD_ZFS_H 1
+# if defined(HAS_ZFS)
+
+
+/*
+ * The _PROTOTYPE macro provides strict ANSI C prototypes if __STDC__
+ * is defined, and old-style K&R prototypes otherwise.
+ *
+ * (With thanks to Andy Tanenbaum)
+ */
+
+# if defined(__STDC__)
+#define _PROTOTYPE(function, params) function params
+# else /* !defined(__STDC__) */
+#define _PROTOTYPE(function, params) function()
+# endif /* defined(__STDC__) */
+
+
+/*
+ * The following define keeps gcc>=2.7 from complaining about the failure
+ * of the Exit() function to return.
+ *
+ * Paul Eggert supplied it.
+ */
+
+# if defined(__GNUC__) && !(__GNUC__<2 || (__GNUC__==2 && __GNUC_MINOR__<7))
+#define exiting __attribute__((__noreturn__))
+# else /* !gcc || gcc<2.7 */
+#define exiting
+# endif /* gcc && gcc>=2.7 */
+
+# if !defined(INODETYPE)
+#define INODETYPE unsigned long long
+# endif /* !defined(INODETYPE) */
+
+# if !defined(FREEBSD_KA_T)
+# if FREEBSDV<2000
+typedef off_t KA_T;
+# else /* FREEBSDV>=2000 */
+typedef u_long KA_T;
+# endif /* FREEBSDV<2000 */
+#define FREEBSD_KA_T 1 /* for dlsof.h */
+# endif /* !defined(FREEBSD_KA_T) */
+
+# if !defined(READLEN_T)
+#define READLEN_T int
+# endif /* !defined(READLEN_T) */
+
+# if !defined(SZOFFTYPE)
+#define SZOFFTYPE unsigned long long
+# endif /* !defined(SZOFFTYPE) */
+
+
+/*
+ * Structure for passing znode info
+ */
+
+typedef struct zfs_info {
+ INODETYPE ino; /* inode number */
+ KA_T lockf; /* znode's z_lockf pointer */
+ long nl; /* number of links */
+ dev_t rdev; /* "raw" device number */
+ SZOFFTYPE sz; /* size */
+ unsigned char ino_def; /* ino defined status */
+ unsigned char nl_def; /* nl defined status */
+ unsigned char rdev_def; /* rdev defined status */
+ unsigned char sz_def; /* sz defined status */
+} zfs_info_t;
+
+_PROTOTYPE(extern int kread,(KA_T addr, char *buf, READLEN_T len));
+_PROTOTYPE(extern char *readzfsnode,(KA_T va, zfs_info_t *zi, int vr));
+
+# endif /* defined(HAS_ZFS) */
+#endif /* defined(FREEBSD_DZFS_H) */
diff --git a/dialects/freebsd/include/procfs/pfsnode.h b/dialects/freebsd/include/procfs/pfsnode.h
new file mode 100644
index 0000000..6979e49
--- /dev/null
+++ b/dialects/freebsd/include/procfs/pfsnode.h
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 1993 Paul Kranenburg
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Paul Kranenburg.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: pfsnode.h,v 1.1 1993/12/12 12:26:39 davidg Exp $
+ */
+
+/*
+ * This structure defines the control data for the proc file system.
+ */
+
+struct pfsnode {
+ struct pfsnode *pfs_next; /* next on list */
+ struct vnode *pfs_vnode; /* vnode associated with this pfsnode */
+ pid_t pfs_pid; /* associated process */
+ u_short pfs_mode; /* mode bits for stat() */
+ uid_t pfs_uid; /* process' owner */
+ gid_t pfs_gid; /* process' group */
+ u_long pfs_vflags; /* chflags() flags */
+ u_long pfs_flags; /* open flags */
+ struct vmspace *pfs_vs;
+};
+
+struct pfsnode *pfshead;
+
+/*
+ * Format of a directory entry in /proc
+ */
+struct pfsdent {
+ unsigned long d_fileno;
+ unsigned short d_reclen;
+ unsigned short d_namlen;
+ char d_nam[8];
+};
+#define PFSDENTSIZE (sizeof(struct direct) - MAXNAMELEN + 8)
+
+#ifndef DIRBLKSIZ
+#define DIRBLKSIZ DEV_BSIZE
+#endif
+
+#ifdef DEBUG
+int pfs_debug;
+#endif
+
+/*
+ * Convert between pfsnode pointers and vnode pointers
+ */
+#define VTOPFS(vp) ((struct pfsnode *)(vp)->v_data)
+#define PFSTOV(pfsp) ((pfsp)->pfs_vnode)
+
+/*
+ * Prototypes for PFS operations on vnodes.
+ */
+int pfs_badop();
+int pfs_doio();
+int pfs_lookup __P(( \
+ struct vnode *vp, \
+ struct nameidata *ndp, \
+ struct proc *p));
+#define pfs_create ((int (*) __P(( \
+ struct nameidata *ndp, \
+ struct vattr *vap, \
+ struct proc *p))) pfs_badop)
+#define pfs_mknod ((int (*) __P(( \
+ struct nameidata *ndp, \
+ struct vattr *vap, \
+ struct ucred *cred, \
+ struct proc *p))) pfs_badop)
+int pfs_open __P((
+ struct vnode *vp,
+ int mode,
+ struct ucred *cred,
+ struct proc *p));
+int pfs_close __P((
+ struct vnode *vp,
+ int fflag,
+ struct ucred *cred,
+ struct proc *p));
+int pfs_access __P((
+ struct vnode *vp,
+ int mode,
+ struct ucred *cred,
+ struct proc *p));
+int pfs_getattr __P((
+ struct vnode *vp,
+ struct vattr *vap,
+ struct ucred *cred,
+ struct proc *p));
+int pfs_setattr __P((
+ struct vnode *vp,
+ struct vattr *vap,
+ struct ucred *cred,
+ struct proc *p));
+#define pfs_read ((int (*) __P(( \
+ struct vnode *vp, \
+ struct uio *uio, \
+ int ioflag, \
+ struct ucred *cred))) pfs_doio)
+#define pfs_write ((int (*) __P(( \
+ struct vnode *vp, \
+ struct uio *uio, \
+ int ioflag, \
+ struct ucred *cred))) pfs_doio)
+int pfs_ioctl __P((
+ struct vnode *vp,
+ int command,
+ caddr_t data,
+ int fflag,
+ struct ucred *cred,
+ struct proc *p));
+#define pfs_select ((int (*) __P(( \
+ struct vnode *vp, \
+ int which, \
+ int fflags, \
+ struct ucred *cred, \
+ struct proc *p))) pfs_badop)
+#define pfs_mmap ((int (*) __P(( \
+ struct vnode *vp, \
+ int fflags, \
+ struct ucred *cred, \
+ struct proc *p))) pfs_badop)
+#define pfs_fsync ((int (*) __P(( \
+ struct vnode *vp, \
+ int fflags, \
+ struct ucred *cred, \
+ int waitfor, \
+ struct proc *p))) pfs_badop)
+#define pfs_seek ((int (*) __P(( \
+ struct vnode *vp, \
+ off_t oldoff, \
+ off_t newoff, \
+ struct ucred *cred))) pfs_badop)
+#define pfs_remove ((int (*) __P(( \
+ struct nameidata *ndp, \
+ struct proc *p))) pfs_badop)
+#define pfs_link ((int (*) __P(( \
+ struct vnode *vp, \
+ struct nameidata *ndp, \
+ struct proc *p))) pfs_badop)
+#define pfs_rename ((int (*) __P(( \
+ struct nameidata *fndp, \
+ struct nameidata *tdnp, \
+ struct proc *p))) pfs_badop)
+#define pfs_mkdir ((int (*) __P(( \
+ struct nameidata *ndp, \
+ struct vattr *vap, \
+ struct proc *p))) pfs_badop)
+#define pfs_rmdir ((int (*) __P(( \
+ struct nameidata *ndp, \
+ struct proc *p))) pfs_badop)
+#define pfs_symlink ((int (*) __P(( \
+ struct nameidata *ndp, \
+ struct vattr *vap, \
+ char *target, \
+ struct proc *p))) pfs_badop)
+int pfs_readdir __P((
+ struct vnode *vp,
+ struct uio *uio,
+ struct ucred *cred,
+ int *eofflagp));
+#define pfs_readlink ((int (*) __P(( \
+ struct vnode *vp, \
+ struct uio *uio, \
+ struct ucred *cred))) pfs_badop)
+#define pfs_abortop ((int (*) __P(( \
+ struct nameidata *ndp))) pfs_badop)
+int pfs_inactive __P((
+ struct vnode *vp,
+ struct proc *p));
+int pfs_reclaim __P((
+ struct vnode *vp));
+#define pfs_lock ((int (*) __P(( \
+ struct vnode *vp))) nullop)
+#define pfs_unlock ((int (*) __P(( \
+ struct vnode *vp))) nullop)
+int pfs_bmap __P((
+ struct vnode *vp,
+ daddr_t bn,
+ struct vnode **vpp,
+ daddr_t *bnp));
+int pfs_strategy __P((
+ struct buf *bp));
+void pfs_print __P((
+ struct vnode *vp));
+#define pfs_islocked ((int (*) __P(( \
+ struct vnode *vp))) nullop)
+#define pfs_advlock ((int (*) __P(( \
+ struct vnode *vp, \
+ caddr_t id, \
+ int op, \
+ struct flock *fl, \
+ int flags))) pfs_badop)
diff --git a/dialects/freebsd/machine.h b/dialects/freebsd/machine.h
new file mode 100644
index 0000000..3089ef7
--- /dev/null
+++ b/dialects/freebsd/machine.h
@@ -0,0 +1,662 @@
+/*
+ * machine.h - FreeBSD definitions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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.
+ */
+
+
+/*
+ * $Id: machine.h,v 1.38 2010/07/29 16:04:28 abe Exp $
+ */
+
+
+#if !defined(LSOF_MACHINE_H)
+#define LSOF_MACHINE_H 1
+
+#include <sys/types.h>
+
+# if defined(HAS_CONF_MINOR)
+#undef minor
+# endif /* defined(HAS_CONF_MINOR) */
+
+#if defined(HASCPUMASK_T)
+/*
+ * In FreeBSD >= 5.2 when the cpumask_t typedef is present, it may be defined
+ * in <sys/types.h> only if _KERNEL is predefined. However, predefining
+ * _KERNEL before #include'ing <sys/types.h> causes redefinition errors for
+ * boolean_t and vm_page_t when <vm/vm.h> is #include'd with _KERNEL
+ * predefined. Since lsof must have _KERNEL predefined when <vm/vm.h> is
+ * #include'd, the expedient choice is made to duplicate the cpumask_t typedef
+ * here.
+ *
+ * Note: the Configure script defines HASCPUMASK_T if <sys/types.h> and
+ * <machine/_types.h> both have cpumask_t references and if the reference in
+ * <sys/types.h> is valid only when _KERNEL is defined.
+ */
+
+typedef __cpumask_t cpumask_t;
+#endif /* defined(HASCPUMASK_T) */
+
+#include <sys/param.h>
+
+
+/*
+ * CAN_USE_CLNT_CREATE is defined for those dialects where RPC clnt_create()
+ * can be used to obtain a CLIENT handle in lieu of clnttcp_create().
+ */
+
+#define CAN_USE_CLNT_CREATE 1
+
+
+/*
+ * DEVDEV_PATH defines the path to the directory that contains device
+ * nodes.
+ */
+
+#define DEVDEV_PATH "/dev"
+
+
+/*
+ * GET_MAX_FD is defined for those dialects that provide a function other than
+ * getdtablesize() to obtain the maximum file descriptor number plus one.
+ */
+
+/* #define GET_MAX_FD ? */
+
+
+/*
+ * HASAOPT is defined for those dialects that have AFS support; it specifies
+ * that the default path to an alternate AFS kernel name list file may be
+ * supplied with the -A <path> option.
+ */
+
+/* #define HASAOPT 1 */
+
+
+/*
+ * HASBLKDEV is defined for those dialects that want block device information
+ * recorded in BDevtp[].
+ */
+
+# if FREEBSDV<4000
+#define HASBLKDEV 1
+# endif /* FREEBSDV<4000 */
+
+
+/*
+ * HASDCACHE is defined for those dialects that support a device cache
+ * file.
+ *
+ * HASENVDC defined the name of an environment variable that contains the
+ * device cache file path. The HASENVDC environment variable is ignored when
+ * the lsof process is setuid(root) or its real UID is 0.
+ *
+ * HASPERSDC defines the format for the last component of a personal device
+ * cache file path. The first will be the home directory of the real UID that
+ * executes lsof.
+ *
+ * HASPERSDCPATH defines the environment variable whose value is the middle
+ * component of the personal device cache file path. The middle component
+ * follows the home directory and precedes the results of applying HASPERSDC.
+ * The HASPERSDCPATH environment variable is ignored when the lsof process is
+ * setuid(root) or its real UID is 0.
+ *
+ * HASSYSDC defines a public device cache file path. When it's defined, it's
+ * used as the path from which to read the device cache.
+ *
+ * Consult the 00DCACHE and 00FAQ files of the lsof distribution for more
+ * information on device cache file path construction.
+ */
+
+#define HASDCACHE 1
+#define HASENVDC "LSOFDEVCACHE"
+#define HASPERSDC "%h/%p.lsof_%L"
+#define HASPERSDCPATH "LSOFPERSDCPATH"
+/* #define HASSYSDC "/your/choice/of/path" */
+
+
+/*
+ * HASCDRNODE is defined for those dialects that have CD-ROM nodes.
+ */
+
+/* #define HASCDRNODE 1 */
+
+
+/*
+ * HASFIFONODE is defined for those dialects that have FIFO nodes.
+ */
+
+/* #define HASFIFONODE 1 */
+
+
+/*
+ * HASFSINO is defined for those dialects that have the file system
+ * inode element, fs_ino, in the lfile structure definition in lsof.h.
+ */
+
+/* #define HASFSINO 1 */
+
+
+/*
+ * HASFSTRUCT is defined if the dialect has a file structure.
+ *
+ * FSV_DEFAULT defines the default set of file structure values to list.
+ * It defaults to zero (0), but may be made up of a combination of the
+ * FSV_* symbols from lsof.h.
+ *
+ * HASNOFSADDR -- has no file structure address
+ * HASNOFSFLAGS -- has no file structure flags
+ * HASNOFSCOUNT -- has no file structure count
+ * HASNOFSNADDR -- has no file structure node address
+ */
+
+#define HASFSTRUCT 1
+/* #define FSV_DEFAULT FSV_? | FSV_? | FSV_? */
+/* #define HASNOFSADDR 1 has no file structure address */
+/* #define HASNOFSFLAGS 1 has no file structure flags */
+/* #define HASNOFSCOUNT 1 has no file structure count */
+/* #define HASNOFSNADDR 1 has no file structure node address */
+
+
+/*
+ * HASGNODE is defined for those dialects that have gnodes.
+ */
+
+/* #define HASGNODE 1 */
+
+
+/*
+ * HASHSNODE is defined for those dialects that have High Sierra nodes.
+ */
+
+/* #define HASHSNODE 1 */
+
+
+/*
+ * HASINODE is defined for those dialects that have inodes and wish to
+ * use readinode() from node.c.
+ */
+
+#define HASINODE 1
+
+
+/*
+ * HASINTSIGNAL is defined for those dialects whose signal function returns
+ * an int.
+ */
+
+/* #define HASINTSIGNAL 1 */
+
+
+/*
+ * HASKERNIDCK is defined for those dialects that support the comparison of
+ * the build to running kernel identity.
+ */
+
+#define HASKERNIDCK 1
+
+
+/*
+ * HASKOPT is defined for those dialects that support the -k option of
+ * reading the kernel's name list from an optional file.
+ */
+
+#define HASKOPT 1
+
+
+/*
+ * HASLFILEADD is defined for those dialects that need additional elements
+ * in struct lfile. The HASLFILEADD definition is a macro that defines
+ * them. If any of the additional elements need to be preset in the
+ * alloc_lfile() function of proc.c, the SETLFILEADD macro may be defined
+ * to do that.
+ *
+ * If any additional elements need to be cleared in alloc_lfile() or in the
+ * free_proc() function of proc.c, the CLRLFILEADD macro may be defined to
+ * do that. Note that CLRLFILEADD takes one argument, the pointer to the
+ * lfile struct. The CLRLFILEADD macro is expected to expand to statements
+ * that are complete -- i.e., have terminating semi-colons -- so the macro is
+ * called without a terminating semicolon by proc.c.
+ *
+ * The HASXOPT definition may be used to select the conditions under which
+ * private lfile elements are used.
+ */
+
+/* #define HASLFILEADD int ... */
+/* #define CLRLFILEADD(lf) (lf)->... = (type)NULL; */
+/* #define SETLFILEADD Lf->... */
+
+
+/*
+ * HASMNTSTAT indicates the dialect supports the mount stat(2) result option
+ * in its l_vfs and mounts structures.
+ */
+
+/* #define HASMNTSTAT 1 */
+
+
+/*
+ * HASMNTSUP is defined for those dialects that support the mount supplement
+ * option.
+ */
+
+/* #define HASMNTSUP 1 */
+
+
+/*
+ * HASMOPT is defined for those dialects that support the reading of
+ * kernel memory from an alternate file.
+ */
+
+#define HASMOPT 1
+
+
+/*
+ * HASNCACHE is defined for those dialects that have a kernel name cache
+ * that lsof can search. A value of 1 directs printname() to prefix the
+ * cache value with the file system directory name; 2, avoid the prefix.
+ *
+ * NCACHELDPFX is a set of C commands to execute before calling ncache_load().
+ *
+ * NCACHELDSFX is a set of C commands to execute after calling ncache_load().
+ */
+
+#define HASNCACHE 1
+/* #define NCACHELDPFX ??? */
+/* #define NCACHELDSFX ??? */
+
+
+/*
+ * HASNLIST is defined for those dialects that use nlist() to acccess
+ * kernel symbols.
+ */
+
+#define HASNLIST 1
+
+
+/*
+ * HASPIPEFN is defined for those dialects that have a special function to
+ * process DTYPE_PIPE file structure entries. Its value is the name of the
+ * function.
+ *
+ * NOTE: don't forget to define a prototype for this function in dproto.h.
+ */
+
+# if FREEBSDV>=2020
+#define HASPIPEFN process_pipe
+# endif /* FREEBSDV>=2020 */
+
+
+/*
+ * HASPIPENODE is defined for those dialects that have pipe nodes.
+ */
+
+/* #define HASPIPENODE 1 */
+
+
+/*
+ * HASPMAPENABLED is defined when the reporting of portmapper registration
+ * info is enabled by default.
+ */
+
+/* #define HASPMAPENABLED 1 */
+
+
+/*
+ * HASPPID is defined for those dialects that support identification of
+ * the parent process IDentifier (PPID) of a process.
+ */
+
+# if FREEBSDV>=2000
+#define HASPPID 1
+# endif /* FREEBSDV>=2000 */
+
+
+/*
+ * HASPRINTDEV, HASPRINTINO, HASPRINTNM, HASPRINTOFF, and HASPRINTSZ
+ * define private dialect-specific functions for printing DEVice numbers,
+ * INOde numbers, NaMes, file OFFsets, and file SiZes. The functions are
+ * called from print_file().
+ */
+
+/* #define HASPRINTDEV print_dev? */
+/* #define HASPRINTINO print_ino? */
+/* #define HASPRINTNM print_nm? */
+/* #define HASPRINTOFF print_off? */
+/* #define HASPRINTSZ print_sz? */
+
+
+/*
+ * HASPRIVFILETYPE and PRIVFILETYPE are defined for dialects that have a
+ * file structure type that isn't defined by a DTYPE_* symbol. They are
+ * used in lib/prfp.c to select the type's processing.
+ *
+ * PRIVFILETYPE is the definition of the f_type value in the file struct.
+ *
+ * HASPRIVFILETYPE is the name of the processing function.
+ */
+
+/* #define HASPRIVFILETYPE process_shmf? */
+/* #define PRIVFILETYPE ?? */
+
+
+/*
+ * HASPRIVNMCACHE is defined for dialects that have a private method for
+ * printing cached NAME column values for some files. HASPRIVNAMECACHE
+ * is defined to be the name of the function.
+ *
+ * The function takes one argument, a struct lfile pointer to the file, and
+ * returns non-zero if it prints a name to stdout.
+ */
+
+/* #define HASPRIVNMCACHE <function name> */
+
+
+/*
+ * HASPRIVPRIPP is defined for dialects that have a private function for
+ * printing IP protocol names. When HASPRIVPRIPP isn't defined, the
+ * IP protocol name printing function defaults to printiprto().
+ */
+
+/* #define HASPRIVPRIPP 1 */
+
+
+/*
+ * HASPROCFS is defined for those dialects that have a proc file system --
+ * usually /proc and usually in SYSV4 derivatives. For FreeBSD 2.0 and
+ * above the Configure script defines HASPROCFS when it can find
+ * /usr/src/sys/miscfs/procfs/procfs.h; below 2.0, Configure always defines
+ * HASPROCFS.
+ *
+ * HASFSTYPE is defined as 1 for those systems that have a file system type
+ * string, st_fstype, in the stat() buffer; 2, for those systems that have a
+ * file system type integer in the stat() buffer, named MOUNTS_STAT_FSTYPE;
+ * 0, for systems whose stat(2) structure has no file system type member. The
+ * additional symbols MOUNTS_FSTYPE, RMNT_FSTYPE, and RMNT_STAT_FSTYPE may be
+ * defined in dlsof.h to direct how the readmnt() function in lib/rmnt.c
+ * preserves these stat(2) and getmntent(3) buffer values in the local mounts
+ * structure.
+ *
+ * The defined value is the string that names the file system type.
+ *
+ * The HASPROCFS definition usually must be accompanied by the HASFSTYPE
+ * definition and the providing of an fstype element in the local mounts
+ * structure (defined in dlsof.h).
+ *
+ * The HASPROCFS definition may be accompanied by the HASPINODEN definition.
+ * HASPINODEN specifies that searching for files in HASPROCFS is to be done
+ * by inode number.
+ */
+
+# if defined(HASPROCFS)
+#undef HASPROCFS
+#define HASPROCFS "proc"
+# endif /* defined(HASPROCFS) */
+
+/* #define HASPROCFS "proc?" */
+/* #define HASFSTYPE 1 */
+
+# if FREEBSDV>=2000
+#define HASPINODEN 1
+# endif /* FREEBSDV>=2000 */
+
+
+/*
+ * HASRNODE is defined for those dialects that have rnodes.
+ */
+
+/* #define HASRNODE 1 */
+
+
+/*
+ * Define HASSECURITY to restrict the listing of all open files to the
+ * root user. When HASSECURITY is defined, the non-root user may list
+ * only files whose processes have the same user ID as the real user ID
+ * (the one that its user logged on with) of the lsof process.
+ */
+
+/* #define HASSECURITY 1 */
+
+
+/*
+ * If HASSECURITY is defined, define HASNOSOCKSECURITY to allow users
+ * restricted by HASSECURITY to list any open socket files, provide their
+ * listing is selected by the "-i" option.
+ */
+
+/* #define HASNOSOCKSECURITY 1 */
+
+
+/*
+ * HASSETLOCALE is defined for those dialects that have <locale.h> and
+ * setlocale().
+ *
+ * If the dialect also has wide character support for language locales,
+ * HASWIDECHAR activates lsof's wide character support and WIDECHARINCL
+ * defines the header file (if any) that must be #include'd to use the
+ * mblen() and mbtowc() functions.
+ */
+
+#define HASSETLOCALE 1
+
+# if FREEBSDV>=5200
+#define HASWIDECHAR 1
+# endif /* FREEBSDV>=5020 */
+
+/* #define WIDECHARINCL <wchar.h> */
+
+
+/*
+ * HASSNODE is defined for those dialects that have snodes.
+ */
+
+/* #define HASSNODE 1 */
+
+
+/*
+ * HASTASKS is defined for those dialects that have task reporting support.
+ */
+
+/* #define HASTASKS 1 */
+
+
+/*
+ * HASSOOPT, HASSOSTATE and HASTCPOPT define the availability of information
+ * on socket options (SO_* symbols), socket states (SS_* symbols) and TCP
+ * options.
+ */
+
+#define HASSOOPT 1 /* has socket option information */
+#define HASSOSTATE 1 /* has socket state information */
+#define HASTCPOPT 1 /* has TCP options or flags */
+
+
+/*
+ * Define HASSPECDEVD to be the name of a function that handles the results
+ * of a successful stat(2) of a file name argument.
+ *
+ * For example, HASSPECDEVD() for Darwin makes sure that st_dev is set to
+ * what stat("/dev") returns -- i.e., what's in DevDev.
+ *
+ * The function takes two arguments:
+ *
+ * 1: pointer to the full path name of file
+ * 2: pointer to the stat(2) result
+ *
+ * The function returns void.
+ */
+
+/* #define HASSPECDEVD process_dev_stat */
+
+
+/*
+ * HASSTREAMS is defined for those dialects that support streams.
+ */
+
+/* #define HASSTREAMS 1 */
+
+
+/*
+ * HASTCPTPIQ is defined for dialects where it is possible to report the
+ * TCP/TPI Recv-Q and Send-Q values produced by netstat.
+ */
+
+#define HASTCPTPIQ 1
+
+
+/*
+ * HASTCPTPIW is defined for dialects where it is possible to report the
+ * TCP/TPI send and receive window sizes produced by netstat.
+ */
+
+/* #define HASTCPTPIW 1 */
+
+
+/*
+ * HASTCPUDPSTATE is defined for dialects that have TCP and UDP state
+ * support -- i.e., for the "-stcp|udp:state" option and its associated
+ * speed improvements.
+ */
+
+#define HASTCPUDPSTATE 1
+
+
+/*
+ * HASTMPNODE is defined for those dialects that have tmpnodes.
+ */
+
+/* #define HASTMPNODE 1 */
+
+
+/*
+ * HASVNODE is defined for those dialects that use the Sun virtual file system
+ * node, the vnode. BSD derivatives usually do; System V derivatives prior
+ * to R4 usually don't.
+ * doesn't.
+ */
+
+#define HASVNODE 1
+
+
+/*
+ * HASXOPT is defined for those dialects that have an X option. It
+ * defines the text for the usage display. HASXOPT_VALUE defines the
+ * option's default binary value -- 0 or 1.
+ */
+
+/* #define HASXOPT "help text for X option" */
+/* #define HASXOPT_VALUE 1 */
+
+
+/*
+ * INODETYPE and INODEPSPEC define the internal node number type and its
+ * printf specification modifier. These need not be defined and lsof.h
+ * can be allowed to define defaults.
+ *
+ * These are defined here, because they must be used in dlsof.h.
+ */
+
+#define INODETYPE unsigned long long
+ /* inode number internal storage type */
+#define INODEPSPEC "ll" /* INODETYPE printf specification
+ * modifier */
+
+
+/*
+ * UID_ARG defines the size of a User ID number when it is passed
+ * as a function argument.
+ */
+
+#define UID_ARG int
+
+
+/*
+ * Each USE_LIB_<function_name> is defined for dialects that use the
+ * <function_name> in the lsof library.
+ *
+ * Note: other definitions and operations may be required to condition the
+ * library function source code. They may be found in the dialect dlsof.h
+ * header files.
+ */
+
+#define USE_LIB_CKKV 1 /* ckkv.c */
+/* #define USE_LIB_COMPLETEVFS 1 cvfs.c */
+#define USE_LIB_FIND_CH_INO 1 /* fino.c */
+#define USE_LIB_IS_FILE_NAMED 1 /* isfn.c */
+#define USE_LIB_LKUPDEV 1 /* lkud.c */
+#define USE_LIB_PRINTDEVNAME 1 /* pdvn.c */
+#define USE_LIB_PROCESS_FILE 1 /* prfp.c */
+#define USE_LIB_PRINT_TCPTPI 1 /* ptti.c */
+#define USE_LIB_READDEV 1 /* rdev.c */
+/* #define USE_LIB_READMNT 1 rmnt.c */
+/* #define USE_LIB_REGEX 1 regex.c */
+
+# if FREEBSDV<2010
+#define USE_LIB_RNAM 1 /* rnam.c */
+# else /* FREEBSDV>=2010 */
+#define USE_LIB_RNMH 1 /* rnmh.c */
+# endif /* FREEBSDV<2010 */
+
+/* #define USE_LIB_RNCH 1 rnch.c */
+/* #define USE_LIB_SNPF 1 snpf.c */
+#define snpf snprintf /* use the system's snprintf() */
+
+
+/*
+ * WARNDEVACCESS is defined for those dialects that should issue a warning
+ * when lsof can't access /dev (or /device) or one of its sub-directories.
+ * The warning can be inhibited by the lsof caller with the -w option.
+ */
+
+#define WARNDEVACCESS 1
+
+
+/*
+ * WARNINGSTATE is defined for those dialects that want to suppress all lsof
+ * warning messages.
+ */
+
+/* #define WARNINGSTATE 1 warnings are enabled by default */
+
+
+/*
+ * WILLDROPGID is defined for those dialects whose lsof executable runs
+ * setgid(not_real_GID) and whose setgid power can be relinquished after
+ * the dialect's initialize() function has been executed.
+ */
+
+#define WILLDROPGID 1
+
+
+/*
+ * zeromem is a macro that uses bzero or memset.
+ */
+
+#define zeromem(a, l) memset(a, 0, l)
+
+#endif /* !defined(LSOF_MACHINE_H) */
diff --git a/dialects/hpux/kmem/Makefile b/dialects/hpux/kmem/Makefile
new file mode 100644
index 0000000..e71696b
--- /dev/null
+++ b/dialects/hpux/kmem/Makefile
@@ -0,0 +1,161 @@
+
+# HP-UX /dev/kmem-based Makefile
+#
+# $Id: Makefile,v 1.15 2008/04/15 13:29:43 abe Exp $
+
+PROG= lsof
+
+BIN= ${DESTDIR}
+
+DOC= ${DESTDIR}
+
+I=/usr/include
+S=/usr/include/sys
+L=/usr/include/local
+P=
+
+CDEF=
+CDEFS= ${CDEF} ${CFGF}
+INCL= ${DINC}
+CFLAGS= ${CDEFS} ${INCL} ${DEBUG}
+
+GRP=
+
+HDR= lsof.h lsof_fields.h dlsof.h machine.h proto.h dproto.h
+
+SRC= dfile.c dmnt.c dnode.c dnode1.c dnode2.c dproc.c dsock.c \
+ dstore.c \
+ arg.c main.c misc.c node.c print.c proc.c store.c usage.c util.c
+
+OBJ= dfile.o dmnt.o dnode.o dnode1.o dnode2.o dproc.o dsock.o \
+ dstore.o \
+ arg.o main.o misc.o node.o print.o proc.o store.o usage.o util.o
+
+MAN= lsof.8
+
+OTHER=
+
+SHELL= /bin/sh
+
+SOURCE= Makefile ${OTHER} ${MAN} ${HDR} ${SRC}
+
+all: ${PROG}
+
+${PROG}: ${LIB} ${P} ${OBJ}
+ ${CC} -o $@ ${CFLAGS} ${OBJ} ${CFGL}
+
+clean: FRC
+ rm -f Makefile.bak ${PROG} a.out core errs lint.out tags *.o version.h
+ rm -f machine.h.old new_machine.h
+ (cd lib; ${MAKE} -f Makefile.skel clean)
+
+install: all FRC
+ @echo ''
+ @echo 'Please write your own install rule. Lsof should be installed'
+ @echo 'setgid to the group that can read /dev/kmem. Normally that is'
+ @echo 'the sys group. Your install rule actions might look something'
+ @echo 'like this:'
+ @echo ''
+ @echo ' install -i -g $${GRP} $${PROG} $${BIN}'
+ @echo ' chmod 2755 $${BIN}/$${PROG}'
+ @echo ' install -i $${MAN} $${DOC}'
+ @echo ' chmod 444 $${DOC}/$${MAN}'
+ @echo ''
+ @echo 'You will have to complete the skeletons for the BIN, DOC, and'
+ @echo 'GRP strings given at the beginning of this Makefile, e.g.,'
+ @echo ''
+ @echo ' BIN= $${DESTDIR}/usr/local/etc'
+ @echo ' DOC= $${DESTDIR}/usr/man/man8'
+ @echo ' GRP= sys'
+ @echo ''
+
+${LIB}: FRC
+ (cd lib; ${MAKE} DEBUG="${DEBUG}" CFGF="${CFGF}")
+
+version.h: FRC
+ @echo Constructing version.h
+ @rm -f version.h
+ @echo '#define LSOF_BLDCMT "${LSOF_BLDCMT}"' > version.h;
+ @echo '#define LSOF_CC "${CC}"' >> version.h
+ @echo '#define LSOF_CCV "${CCV}"' >> version.h
+ @echo '#define LSOF_CCDATE "'`date`'"' >> version.h
+ @echo '#define LSOF_CCFLAGS "'`echo ${CFLAGS} | sed 's/\\\\(/\\(/g' | sed 's/\\\\)/\\)/g' | sed 's/"/\\\\"/g'`'"' >> version.h
+ @echo '#define LSOF_CINFO "${CINFO}"' >> version.h
+ @if [ "X${LSOF_HOST}" = "X" ]; then \
+ echo '#define LSOF_HOST "'`uname -n`'"' >> version.h; \
+ else \
+ if [ "${LSOF_HOST}" = "none" ]; then \
+ echo '#define LSOF_HOST ""' >> version.h; \
+ else \
+ echo '#define LSOF_HOST "${LSOF_HOST}"' >> version.h; \
+ fi \
+ fi
+ @echo '#define LSOF_LDFLAGS "${CFGL}"' >> version.h
+ @if [ "X${LSOF_LOGNAME}" = "X" ]; then \
+ echo '#define LSOF_LOGNAME "${LOGNAME}"' >> version.h; \
+ else \
+ if [ "${LSOF_LOGNAME}" = "none" ]; then \
+ echo '#define LSOF_LOGNAME ""' >> version.h; \
+ else \
+ echo '#define LSOF_LOGNAME "${LSOF_LOGNAME}"' >> version.h; \
+ fi; \
+ fi
+ @if [ "X${LSOF_SYSINFO}" = "X" ]; then \
+ echo '#define LSOF_SYSINFO "'`uname -a`'"' >> version.h; \
+ else \
+ if [ "${LSOF_SYSINFO}" = "none" ]; then \
+ echo '#define LSOF_SYSINFO ""' >> version.h; \
+ else \
+ echo '#define LSOF_SYSINFO "${LSOF_SYSINFO}"' >> version.h; \
+ fi \
+ fi
+ @if [ "X${LSOF_USER}" = "X" ]; then \
+ echo '#define LSOF_USER "${USER}"' >> version.h; \
+ else \
+ if [ "${LSOF_USER}" = "none" ]; then \
+ echo '#define LSOF_USER ""' >> version.h; \
+ else \
+ echo '#define LSOF_USER "${LSOF_USER}"' >> version.h; \
+ fi \
+ fi
+ @sed '/VN/s/.ds VN \(.*\)/#define LSOF_VERSION "\1"/' < version >> version.h
+
+FRC:
+
+# DO NOT DELETE THIS LINE - make depend DEPENDS ON IT
+
+dfile.o: ${HDR} dfile.c
+
+dmnt.o: ${HDR} dmnt.c
+
+dnode.o: ${HDR} dnode.c
+
+dnode1.o: ${HDR} dnode1.c
+
+dnode2.o: ${HDR} dnode2.c
+
+dproc.o: ${HDR} dproc.c
+
+dsock.o: ${HDR} dsock.c
+
+dstore.o: ${HDR} dstore.c
+
+arg.o: ${HDR} arg.c
+
+main.o: ${HDR} main.c
+
+misc.o: ${HDR} misc.c
+
+node.o: ${HDR} node.c
+
+print.o: ${HDR} print.c
+
+proc.o: ${HDR} proc.c
+
+store.o: ${HDR} store.c
+
+usage.o: ${HDR} version.h usage.c
+
+util.o: ${HDR} util.c
+
+# *** Do not add anything here - It will go away. ***
diff --git a/dialects/hpux/kmem/Mksrc b/dialects/hpux/kmem/Mksrc
new file mode 100755
index 0000000..f94d164
--- /dev/null
+++ b/dialects/hpux/kmem/Mksrc
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Mksrc - make /dev/kmem-based HP-UX source files
+#
+# WARNING: This script assumes it is running from the main directory
+# of the lsof, version 4 distribution.
+#
+# One environment variable applies:
+#
+# LSOF_MKC is the method for creating the source files.
+# It defaults to "ln -s". A common alternative is "cp".
+#
+# $Id: Mksrc,v 1.3 99/04/27 15:54:00 abe Exp $
+
+
+D=dialects/hpux/kmem
+L="dfile.c dlsof.h dmnt.c dnode.c dnode1.c dnode2.c dproc.c dproto.h dsock.c dstore.c machine.h"
+
+for i in $L
+do
+ rm -f $i
+ $LSOF_MKC $D/$i $i
+ echo "$LSOF_MKC $D/$i $i"
+done
diff --git a/dialects/hpux/kmem/dfile.c b/dialects/hpux/kmem/dfile.c
new file mode 100644
index 0000000..f6c866b
--- /dev/null
+++ b/dialects/hpux/kmem/dfile.c
@@ -0,0 +1,266 @@
+/*
+ * dfile.c - /dev/kmem-based HP-UX file processing functions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dfile.c,v 1.14 2001/08/14 13:27:16 abe Exp $";
+#endif
+
+#if defined(HPUXKERNBITS) && HPUXKERNBITS>=64
+#define _TIME_T
+typedef int time_t;
+/*
+ * CAUTION!!! CAUTION!!! CAUTION!!! CAUTION!!! CAUTION!!! CAUTION!!!
+ *
+ * Do NOT:
+ *
+ * #define INO_T
+ * typedef int ino_t;
+ *
+ * in this source file for HP-UX >= 10.30. Doing so will cause the kernel's
+ * ino_t type to be erroneously used instead of the application's.
+ *
+ * CAUTION!!! CAUTION!!! CAUTION!!! CAUTION!!! CAUTION!!! CAUTION!!!
+ */
+#endif /* defined(HPUXKERNBITS) && HPUXKERNBITS>=64 */
+
+#include "lsof.h"
+
+
+/*
+ * get_max_fd() - get maximum file descriptor plus one
+ */
+
+int
+get_max_fd()
+{
+ struct rlimit r;
+
+ if (getrlimit(RLIMIT_NOFILE, &r))
+ return(-1);
+ return(r.rlim_cur);
+}
+
+
+/*
+ * print_dev() - print device
+ */
+
+char *
+print_dev(lf, dev)
+ struct lfile *lf; /* file whose device is to be printed */
+ dev_t *dev; /* device to be printed */
+{
+ static char buf[128];
+
+ (void) snpf(buf, sizeof(buf), "%d,%#x", GET_MAJ_DEV(*dev),
+ GET_MIN_DEV(*dev));
+ return(buf);
+}
+
+
+/*
+ * process_file() - process file
+ */
+
+void
+process_file(fp)
+ KA_T fp; /* kernel file structure address */
+{
+ struct file f;
+ int flag;
+
+ if (kread((KA_T)fp, (char *)&f, sizeof(f))) {
+ (void) snpf(Namech, Namechl, "can't read file struct from %s",
+ print_kptr(fp, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ Lf->off = (SZOFFTYPE)f.f_offset;
+
+ if (f.f_count) {
+
+#if defined(HASFSTRUCT)
+ /*
+ * Save file structure values.
+ */
+ if (Fsv & FSV_CT) {
+ Lf->fct = (long)f.f_count;
+ Lf->fsv |= FSV_CT;
+ }
+ if (Fsv & FSV_FA) {
+ Lf->fsa = fp;
+ Lf->fsv |= FSV_FA;
+ }
+ if (Fsv & FSV_FG) {
+ Lf->ffg = (long)f.f_flag;
+ Lf->fsv |= FSV_FG;
+ }
+ if (Fsv & FSV_NI) {
+ Lf->fna = (KA_T)f.f_data;
+ Lf->fsv |= FSV_NI;
+ }
+#endif /* defined(HASFSTRUCT) */
+
+ /*
+ * Construct access code.
+ */
+ if ((flag = (f.f_flag & (FREAD | FWRITE))) == FREAD)
+ Lf->access = 'r';
+ else if (flag == FWRITE)
+ Lf->access = 'w';
+ else if (flag == (FREAD | FWRITE))
+ Lf->access = 'u';
+ /*
+ * Process structure by its type.
+ */
+ switch (f.f_type) {
+
+#if defined(DTYPE_LLA)
+ case DTYPE_LLA:
+ process_lla((KA_T)f.f_data);
+ return;
+#endif /* DTYPE_LLA */
+
+ case DTYPE_VNODE:
+ process_node((KA_T)f.f_data);
+ return;
+ case DTYPE_SOCKET:
+ process_socket((KA_T)f.f_data);
+ return;
+ default:
+ if (!f.f_type || (f.f_ops && (KA_T)f.f_ops != Vnfops)) {
+ (void) snpf(Namech, Namechl,
+ "%s file struct, ty=%#x, op=%#x",
+ print_kptr(fp, (char *)NULL, 0), f.f_type, f.f_ops);
+ enter_nm(Namech);
+ return;
+ }
+ }
+ }
+ enter_nm("no more information");
+}
+
+
+#if HPUXV>=1030
+/*
+ * read_mi() - read stream's module information
+ *
+ * Note: this function is included in this module, because ino_t is not
+ * redfined to the kernel's type, but is left at the application's type.
+ * See the CAUTION statement inside the HPUXKERNBITS>=64 #if/#endif
+ * block at the beginning of this file.
+ */
+
+int
+read_mi(sh, ip, pcb, pn)
+ KA_T sh; /* stream head address */
+ KA_T *ip; /* returned IP q_ptr */
+ KA_T *pcb; /* returned TCP or UDP q_ptr */
+ char **pn; /* returned protocol name */
+{
+ struct l_dev *dp;
+ char *ep = Namech;
+ struct sth_s hd;
+ int i;
+ size_t len, ml;
+ char mn[32];
+ KA_T ka, qa;
+ struct module_info mi;
+ struct queue q;
+ struct qinit qi;
+ size_t sz = Namechl;
+
+ if (!sh
+ || kread(sh, (char *)&hd, sizeof(hd))) {
+ (void) snpf(Namech, Namechl, "can't read stream head: %s",
+ print_kptr(sh, (char *)NULL, 0));
+ return(1);
+ }
+ if (!Lf->rdev_def)
+ dp = (struct l_dev *)NULL;
+ else
+ dp = lkupdev(&DevDev, &Lf->rdev, 1, 0);
+ if (dp)
+ (void) snpf(ep, sz, "%s", dp->name);
+ else
+ *ep = '\0';
+/*
+ * Follow the stream head to each of its queue structures, retrieving the
+ * module names for each queue's q_info->qi_minfo->mi_idname chain of
+ * structures. Separate each additional name from the previous one with
+ * "->".
+ *
+ * Ignore failures to read all but queue structure chain entries.
+ *
+ * Ignore module names that end in "head".
+ *
+ * Save the q_ptr value for "tcp" and "udp" modules.
+ */
+ ml = sizeof(mn) - 1;
+ mn[ml] = '\0';
+ *ip = *pcb = (KA_T)NULL;
+ qa = (KA_T)hd.sth_wq;
+ for (i = 0; i < 20; i++, qa = (KA_T)q.q_next) {
+ if (!qa || kread(qa, (char *)&q, sizeof(q)))
+ break;
+ if (!(ka = (KA_T)q.q_qinfo) || kread(ka, (char *)&qi, sizeof(qi)))
+ continue;
+ if (!(ka = (KA_T)qi.qi_minfo) || kread(ka, (char *)&mi, sizeof(mi)))
+ continue;
+ if (!(ka = (KA_T)mi.mi_idname) || kread(ka, mn, ml))
+ continue;
+ if ((len = strlen(mn)) < 1)
+ continue;
+ if (len >= 3 && !strcmp(&mn[len - 3], "sth"))
+ continue;
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "%s%s", (ep == Namech) ? "" : "->", mn);
+ if (!q.q_ptr)
+ continue;
+ if (!*ip && !strcmp(mn, "ip")) {
+ *ip = (KA_T)q.q_ptr;
+ continue;
+ }
+ if (!*pcb && !strcmp(mn, "tcpm")) {
+ *pcb = (KA_T)q.q_ptr;
+ *pn = "TCP";
+ continue;
+ }
+ if (!*pcb && !strcmp(mn, "udpm")) {
+ *pcb = (KA_T)q.q_ptr;
+ *pn = "UDP";
+ }
+ }
+ return(0);
+}
+#endif /* HPUXV>=1030 */
diff --git a/dialects/hpux/kmem/dlsof.h b/dialects/hpux/kmem/dlsof.h
new file mode 100644
index 0000000..984074b
--- /dev/null
+++ b/dialects/hpux/kmem/dlsof.h
@@ -0,0 +1,441 @@
+/*
+ * dlsof.h - /dev/kmem-based HP-UX header file for lsof
+ */
+
+
+/*
+ * Copyright 1994 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.
+ */
+
+
+/*
+ * $Id: dlsof.h,v 1.19 2007/04/24 16:25:30 abe Exp $
+ */
+
+
+#if !defined(HPUX_LSOF_H)
+#define HPUX_LSOF_H 1
+
+# if HPUXV>=1030
+#include <fcntl.h>
+# endif /* HPUXV>=1030 */
+
+#include <stdlib.h>
+#include <dirent.h>
+#include <mntent.h>
+#include <setjmp.h>
+#include <string.h>
+#include <nlist.h>
+#include <unistd.h>
+
+# if HPUXV<1020
+#include <sys/vnode.h>
+# endif /* HPUXV<1020 */
+
+# if HPUXV>=1030
+/*
+ * Include header files for HP-UX 10.30 and up that have been
+ * manufactured with q4 and hand edited.
+ */
+
+#include "lla.h"
+#include "proc.h"
+#include "rnode.h"
+#include "nfs_clnt.h"
+#include "vnode.h"
+# endif /* HPUXV>=1030 */
+
+#include <sys/domain.h>
+
+# if HPUXV>=1020
+#define _INCLUDE_STRUCT_FILE
+# endif /* HPUXV>=1020 */
+
+# if HPUXV>=1030
+struct uio { /* to satisfy function prototypes in <sys/file.h> */
+ int dummy;
+};
+# endif /* HPUXV>=1030 */
+
+#include <sys/file.h>
+
+# if HPUXV>=1020
+#undef _INCLUDE_STRUCT_FILE
+# endif /* HPUXV>=1020 */
+
+# if HPUXV>=1030
+#include <sys/stream.h>
+#include "sth.h"
+# endif /* HPUXV>=1030 */
+
+#include <sys/mbuf.h>
+
+# if HPUXV>=800
+#undef _PROTOTYPES
+#include <sys/pstat.h>
+# endif /* HPUXV>=800 */
+
+#include <sys/resource.h>
+
+# if HPUXV<1010
+#include <sys/proc.h>
+# endif /* HPUXV<1010 */
+
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <netinet/in.h>
+#include <net/route.h>
+
+# if HPUXV<1030
+#include <net/raw_cb.h>
+#include <netinet/in_pcb.h>
+# endif /* HPUXV<1030 */
+
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+
+# if HPUXV<1030
+#include <netinet/tcp_fsm.h>
+#include <netinet/tcp_timer.h>
+#include <netinet/tcp_var.h>
+# else /* HPUXV>=1030 */
+#include <sys/tihdr.h>
+/*
+ * Include header files for HP-UX 10.30 and up that have been
+ * manufactured with q4 and hand editing.
+ */
+
+#include "ipc_s.h"
+#include "tcp_s.h"
+#include "udp_s.h"
+# endif /* HPUXV<1030 */
+
+# if HPUXV>=1030
+#undef TCP_NODELAY
+#undef TCP_MAXSEG
+# endif /* HPUXV>=1030 */
+
+#include <rpc/types.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+
+# if HPUXV>=1030
+#include <rpc/clnt_soc.h>
+# endif /* HPUXV>=1030 */
+
+# if HPUXV>=1000
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+#include <rpc/clnt.h>
+#include <sys/cdfsdir.h>
+#include <sys/cdfs.h>
+#include <sys/cdnode.h>
+# endif /* HPUXV>=1000 */
+
+#include <nfs/nfs.h>
+
+/*
+ * Structure for Atria's MVFS node (ancestry: lsof 3.61 or older)
+ */
+
+struct mvfsnode {
+ unsigned long d1[6];
+ unsigned long m_ino; /* node number */
+};
+
+# if HPUXV<1030
+#include <nfs/nfs_clnt.h>
+# if defined(HASRNODE3)
+/*
+ * This rnode structure definition should come from <nfs/rnode.h>, but HP-UX
+ * patched the kernel structures of NFS3 at PHNE_18173, PHNE_19426, PHNE_19937,
+ * and PHNE_20091 and didn't supply an updated <nfs/rnode.h>.
+ *
+ * This definition of rnode was derived via /usr/contrib/binq4.
+ */
+
+struct rnode {
+ struct rnode *r_next;
+ struct vnode r_vnode;
+ u_int r_fh3;
+ fhandle_t r_fh;
+ u_short r_flags;
+ short r_error;
+ daddr_t r_lastr;
+ k_off_t r_size;
+ k_off_t r_cachedsize;
+ struct ucred *r_rcred;
+ struct ucred *r_wcred;
+ struct ucred *r_unlcred;
+ int *r_unlname;
+ struct vnode *r_unldvp;
+ struct nfsfattr r_nfsattr;
+};
+# else /* !defined(HASRNODE3) */
+#include <nfs/rnode.h>
+# endif /* defined(HASRNODE3) */
+# endif /* HPUXV<1030 */
+
+#include <nfs/snode.h>
+
+# if HPUXV>=1000
+#define _KERNEL
+#include <nfs/fifonode.h>
+#undef _KERNEL
+# endif /* HPUXV>=1000 */
+
+# if defined(DTYPE_LLA) && HPUXV<1030
+#define _KERNEL 1
+#include <sio/lla.h>
+#undef _KERNEL
+# endif /* defined(DTYPE_LLA) && HPUXV<1030 */
+
+#include <sys/un.h>
+#include <sys/unpcb.h>
+#include <sys/vfs.h>
+#include <sys/vmmac.h>
+#include <sys/user.h>
+
+/*
+ * The hpux_mount.h header file is manufactured from <sys/mount.h> by the
+ * Configure script to get the mount structure without needing to define
+ * _KERNEL when including <sys/mount.h>. Defining _KERNEL causes unresolvable
+ * header file complications.
+ */
+
+#include "hpux_mount.h"
+
+# if HPUXV>=800
+/*
+ * These definitions are from <sys/vfs.h>, defined under the _KERNEL symbol.
+ * Unfortunately, defining _KERNEL causes <sys/vfs.h> to include other
+ * header files not in <sys>.
+ */
+#define MOUNT_UFS 0
+#define MOUNT_NFS 1
+#define MOUNT_CDFS 2
+# endif /* HPUXV>=800 */
+
+# if defined(HAS_CONST)
+#define COMP_P const void
+# else /* !defined(HAS_CONST) */
+#define COMP_P void
+# endif /* defined(HAS_CONST) */
+
+# if HPUXV>=800
+#define CURDIR p->p_cdir
+#define ROOTDIR p->p_rdir
+# else /* HPUXV<800 */
+#define CURDIR u->u_cdir
+#define ROOTDIR u->u_rdir
+# endif /* HPUXV>=800 */
+
+#define DEVINCR 1024 /* device table malloc() increment */
+
+# if HPUXV<1030
+/*
+ * KA_T is defined in dialects/hpux/kmem/hpux11/kernbits.h for HP-UX 10.30
+ * and above.
+ */
+typedef off_t KA_T;
+# endif /* HPUXV<1030 */
+
+#define KMEM "/dev/kmem"
+#define MALLOC_P void
+#define FREE_P void
+#define MALLOC_S unsigned
+#define MOUNTED MNT_MNTTAB
+
+# if HPUXV<1000
+#define N_UNIX "/hp-ux"
+# else /* HPUXV>=1000 */
+#define N_UNIX "/stand/vmunix"
+# endif /* HPUXV<1000 */
+
+#define QSORT_P void
+#define READLEN_T int
+#define STRNCPY_L size_t
+
+# if HPUXV>=1000
+#define SZOFFTYPE unsigned long long
+ /* type for size and offset */
+#define SZOFFPSPEC "ll" /* SZOFFTYPE printf specification modifier */
+# endif /* HPUXV>=1000 */
+
+#define SWAP "/dev/swap"
+
+# if HPUXV<800
+#define unp_addr unp_locaddr
+/*
+ * HP-UX <8 SWAP must be read in DEV_BSIZE chunks.
+ */
+#define U_SIZE (((DEV_BSIZE+sizeof(struct user))/DEV_BSIZE)*DEV_BSIZE)
+# endif /* HPUXV<800 */
+
+# if HPUXV>=800
+#define U_SIZE sizeof(struct user)
+# endif /* HPUXV>=800 */
+
+# if HPUXV>=1030
+#define XDR_PMAPLIST (xdrproc_t)xdr_pmaplist
+#define XDR_VOID (xdrproc_t)xdr_void
+# endif /* HPUXV>=1030 */
+
+
+# if defined(HAS_AFS)
+/*
+ * AFS definitions
+ */
+
+#define AFSAPATHDEF "/usr/adm/afs/kload"
+#define AFSDEV 1 /* AFS "fake" device number */
+
+# if defined(HASAOPT)
+extern char *AFSApath; /* alternate AFS name list path
+ * (from -A) */
+# endif /* defined(HASAOPT) */
+
+extern struct vfs *AFSVfsp; /* AFS struct vfs kernel pointer */
+# endif /* defined(HAS_AFS) */
+
+
+/*
+ * Global storage definitions (including their structure definitions)
+ */
+
+extern int CloneMaj;
+extern int HaveCloneMaj;
+extern int Kd;
+extern KA_T Kpa;
+
+# if HPUXV>=1010
+extern KA_T Ktp;
+#endif /* HPUXV>=1010 */
+
+struct l_vfs {
+ KA_T addr; /* kernel address */
+ dev_t dev; /* device */
+ char *dir; /* mounted directory */
+ char *fsname; /* file system name */
+
+# if defined(HASFSINO)
+ INODETYPE fs_ino; /* file system inode number */
+# endif /* defined(HASFSINO) */
+
+ struct l_vfs *next; /* forward link */
+};
+extern struct l_vfs *Lvfs;
+
+# if HPUXV<800
+extern int Mem;
+# endif /* HPUXV<800 */
+
+struct mounts {
+ char *dir; /* directory (mounted on) */
+ char *fsname; /* file system
+ * (symbolic links unresolved) */
+ char *fsnmres; /* file system
+ * (symbolic links resolved) */
+ dev_t dev; /* directory st_dev */
+ dev_t rdev; /* directory st_rdev */
+ INODETYPE inode; /* directory st_ino */
+ mode_t mode; /* directory st_mode */
+ mode_t fs_mode; /* file system st_mode */
+ struct mounts *next; /* forward link */
+};
+
+#define X_NCACHE "ncache"
+#define X_NCSIZE "ncsize"
+#define NL_NAME n_name
+
+# if HPUXV<800 && defined(hp9000s800)
+extern int npids;
+extern struct proc *proc;
+# endif /* HPUXV<800 && defined(hp9000s800) */
+
+struct sfile {
+ char *aname; /* argument file name */
+ char *name; /* file name (after readlink()) */
+ char *devnm; /* device name (optional) */
+ dev_t dev; /* device */
+ dev_t rdev; /* raw device */
+ u_short mode; /* S_IFMT mode bits from stat() */
+ int type; /* file type: 0 = file system
+ * 1 = regular file */
+ INODETYPE i; /* inode number */
+ int f; /* file found flag */
+ struct sfile *next; /* forward link */
+};
+
+# if HPUXV<800
+extern int Swap;
+# endif /* HPUXV<800 */
+
+# if HPUXV<800 && defined(hp9000s800)
+extern struct user *ubase;
+# endif /* HPUXV<800 && defined(hp9000s800) */
+
+# if HPUXV<800 && defined(hp9000s300)
+extern struct pte *Usrptmap;
+extern struct pte *usrpt;
+# endif /* HPUXV<800 && defined(hp9000s300) */
+
+extern KA_T Vnfops;
+
+
+/*
+ * Definitions for dvch.c, isfn.c, and rdev.c
+ */
+
+#define CLONEMAJ CloneMaj /* clone major variable name */
+#define DIRTYPE dirent /* directory structure type */
+#define HASDNAMLEN 1 /* DIRTYPE has d_namlen element */
+#define HAS_STD_CLONE 1 /* uses standard clone structure */
+#define HAVECLONEMAJ HaveCloneMaj /* clone major status variable name */
+#define MAXSYSCMDL (PST_CLEN - 1)
+
+
+/*
+ * Definition for rmnt.c
+ */
+
+#define MNTSKIP \
+ { if (strcmp(mp->mnt_type, MNTTYPE_IGNORE) == 0) \
+ continue; }
+
+/*
+ * Definitions for rnch.c
+ */
+
+# if defined(HASNCACHE)
+#include <sys/dnlc.h>
+# if HPUXV<1000
+#define ADDR_NCACHE 1
+# endif /* HPUXV<1000 */
+# endif /* defined(HASNCACHE) */
+
+#endif /* HPUX_LSOF_H */
diff --git a/dialects/hpux/kmem/dmnt.c b/dialects/hpux/kmem/dmnt.c
new file mode 100644
index 0000000..d02acd4
--- /dev/null
+++ b/dialects/hpux/kmem/dmnt.c
@@ -0,0 +1,252 @@
+/*
+ * dmnt.c - /dev/kmem-based HP-UX mount support functions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dmnt.c,v 1.8 2005/08/08 19:50:23 abe Exp $";
+#endif
+
+#if defined(HPUXKERNBITS) && HPUXKERNBITS>=64
+#define _TIME_T
+typedef int time_t;
+#endif /* defined(HPUXKERNBITS) && HPUXKERNBITS>=64 */
+
+#include "lsof.h"
+
+
+/*
+ * Local static definitions
+ */
+
+static struct mounts *Lmi = (struct mounts *)NULL; /* local mount info */
+
+
+/*
+ * completevfs() - complete local vfs structure
+ */
+void
+
+#if HPUXV>=800
+completevfs(vfs, dev, v)
+ struct l_vfs *vfs; /* local vfs structure pointer */
+ dev_t *dev; /* device */
+ struct vfs *v; /* kernel vfs structure */
+#else /* HPUXV<800 */
+completevfs(vfs, dev)
+ struct l_vfs *vfs; /* local vfs structure pointer */
+ dev_t *dev; /* device */
+#endif /* HPUXV>=800 */
+
+{
+ struct mounts *mp;
+/*
+ * If only Internet socket files are selected, don't bother completing the
+ * local vfs structure.
+ */
+ if (Selinet)
+ return;
+
+#if HPUXV>=800
+/*
+ * On HP-UX 8 and above, first search the local mount table for a match on
+ * the file system name from the vfs structure.
+ */
+ if (v) {
+ for (mp = readmnt(); mp; mp = mp->next) {
+ if (strcmp(mp->fsname, v->vfs_name) == 0) {
+ vfs->dev = mp->dev;
+ vfs->dir = mp->dir;
+ vfs->fsname = mp->fsname;
+
+# if defined(HASFSINO)
+ vfs->fs_ino = mp->inode;
+# endif /* defined(HASFSINO) */
+
+ return;
+ }
+ }
+ }
+#endif /* HPUXV>=800 */
+
+/*
+ * Search for a match on device number.
+ */
+ for (mp = readmnt(); mp; mp = mp->next) {
+ if (mp->dev == *dev) {
+ vfs->dev = mp->dev;
+ vfs->dir = mp->dir;
+ vfs->fsname = mp->fsname;
+
+#if defined(HASFSINO)
+ vfs->fs_ino = mp->inode;
+#endif /* defined(HASFSINO) */
+
+ return;
+ }
+ }
+
+#if HPUXV>=800
+/*
+ * If the file system name and device number searches fail, use the
+ * vfs structure name, if there is one. Determine the device number
+ * with statsafely().
+ */
+ if (v && v->vfs_name[0]) {
+
+ struct stat sb;
+
+ if (!(vfs->dir = mkstrcpy(v->vfs_name, (MALLOC_S *)NULL))) {
+ (void) fprintf(stderr, "%s: no space for vfs name: ", Pn);
+ safestrprt(v->vfs_name, stderr, 1);
+ Exit(1);
+ }
+ if (statsafely(v->vfs_name, &sb) == 0)
+ vfs->dev = sb.st_dev;
+ else
+ vfs->dev = (dev_t)0;
+
+# if defined(HASFSINO)
+ vfs->fs_ino = (INODETYPE)0;
+# endif /* defined(HASFSINO) */
+
+ }
+#endif /* HPUXV>=800 */
+
+}
+
+
+/*
+ * readvfs() - read vfs structure
+ */
+
+struct l_vfs *
+readvfs(lv)
+ struct vnode *lv; /* local vnode */
+{
+ struct mount m;
+ struct mntinfo mi;
+ int ms;
+ dev_t td;
+ struct vfs v;
+ struct l_vfs *vp;
+
+ if (!lv->v_vfsp)
+ return((struct l_vfs *)NULL);
+ for (vp = Lvfs; vp; vp = vp->next) {
+ if ((KA_T)lv->v_vfsp == vp->addr)
+ return(vp);
+ }
+ if ((vp = (struct l_vfs *)malloc(sizeof(struct l_vfs))) == NULL) {
+ (void) fprintf(stderr, "%s: PID %d, no space for vfs\n",
+ Pn, Lp->pid);
+ Exit(1);
+ }
+ vp->dev = 0;
+ vp->dir = (char *)NULL;
+ vp->fsname = (char *)NULL;
+
+#if defined(HASFSINO)
+ vp->fs_ino = 0;
+#endif /* defined(HASFSINO) */
+
+ if (lv->v_vfsp && kread((KA_T)lv->v_vfsp, (char *)&v, sizeof(v))) {
+ (void) free((FREE_P *)vp);
+ return((struct l_vfs *)NULL);
+ }
+/*
+ * Complete the mount information.
+ */
+ if (Ntype == N_NFS) {
+
+ /*
+ * The device number for an NFS file is found by following the vfs
+ * private data pointer to an mntinfo structure.
+ */
+ if (v.vfs_data
+ && kread((KA_T)v.vfs_data, (char *)&mi, sizeof(mi)) == 0) {
+
+#if HPUXV<1020
+ td = (dev_t)makedev(255, (int)mi.mi_mntno);
+#else /* HPUXV>=1020 */
+ td = mi.mi_mntno;
+#endif /* HPUXV<1020 */
+
+#if HPUXV>=800
+ (void) completevfs(vp, &td, (struct vfs *)NULL);
+#else /* HPUXV<800 */
+ (void) completevfs(vp, &td);
+#endif /* HPUXV>=800 */
+
+ }
+ } else {
+ if (v.vfs_data) {
+ if (kread((KA_T)v.vfs_data, (char *)&m, sizeof(m)) == 0)
+ ms = 1;
+ else
+ ms = 0;
+ }
+
+#if defined(HAS_AFS)
+ /*
+ * Fake the device number for an AFS device.
+ */
+ else if (Ntype == N_AFS) {
+ m.m_dev = AFSDEV;
+ ms = 1;
+ }
+#endif /* defined(HAS_AFS) */
+
+ else
+ ms = 0;
+ if (ms)
+
+#if HPUXV>=800
+# if HPUXV<1000
+ (void) completevfs(vp, (dev_t *)&m.m_dev, &v);
+# else /* HPUXV>=1000 */
+ (void) completevfs(vp, v.vfs_dev ? (dev_t *)&v.vfs_dev
+ : (dev_t *)&m.m_dev,
+ &v);
+# endif /* HPUXV<1000 */
+#else /* HPUXV<800 */
+ (void) completevfs(vp, (dev_t *)&m.m_dev);
+#endif /* HPUXV>=800 */
+
+ }
+/*
+ * Complete local vfs structure and link to the others.
+ */
+ vp->next = Lvfs;
+ vp->addr = (KA_T)lv->v_vfsp;
+ Lvfs = vp;
+ return(vp);
+}
diff --git a/dialects/hpux/kmem/dnode.c b/dialects/hpux/kmem/dnode.c
new file mode 100644
index 0000000..132b41a
--- /dev/null
+++ b/dialects/hpux/kmem/dnode.c
@@ -0,0 +1,1097 @@
+/*
+ * dnode.c - /dev/kmem-based HP-UX node functions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dnode.c,v 1.21 2007/04/24 16:25:30 abe Exp $";
+#endif
+
+#if defined(HPUXKERNBITS) && HPUXKERNBITS>=64
+#define _INO_T
+typedef int ino_t;
+#define _TIME_T
+typedef int time_t;
+#endif /* defined(HPUXKERNBITS) && HPUXKERNBITS>=64 */
+
+#include "lsof.h"
+#include <sys/inode.h>
+
+#if HPUXV>=900
+_PROTOTYPE(static void enter_nma,(char *b));
+_PROTOTYPE(static int islocked,(KA_T lp));
+#endif /* HPUXV>=900 */
+
+_PROTOTYPE(static int getnodety,(struct vnode *v));
+_PROTOTYPE(static int readinode,(KA_T ia, struct inode *i));
+_PROTOTYPE(static int read_nmn,(KA_T na, KA_T ia, struct mvfsnode *m));
+
+
+#if HPUXV>=900
+/*
+ * enter_nma() - enter NAME column addition
+ */
+
+static void
+enter_nma(b)
+ char *b; /* addition buffer */
+{
+ if (Lf->nma)
+ return;
+ if (strlen(b) < 1)
+ return;
+ Lf->nma = mkstrcpy(b, (MALLOC_S *)NULL);
+}
+
+
+/*
+ * islocked() - is node locked?
+ */
+
+static int
+islocked(lp)
+ KA_T lp; /* local locklist struct pointer */
+{
+ static int ety = -1;
+ static unsigned int ei = 0;
+ static SZOFFTYPE el = 0;
+ int l;
+ struct locklist ll;
+ KA_T llf, llp;
+
+ if (!(llf = (KA_T)lp))
+ return((int)' ');
+ llp = llf;
+/*
+ * Compute the end test value the first time through.
+ */
+
+ if (ety == -1) {
+
+# if HPUXV<1020
+ ety = 0;
+ ei = 0x7fffffff;
+# else /* HPUXV>=1020 */
+ if (sizeof(ll.ll_end) == 4) {
+ ety = 0;
+ ei = 0x80000000;
+ } else {
+ ety = 1;
+ el = 0x10000000000ll;
+ }
+# endif /* HPUXV<1020 */
+
+ }
+
+/*
+ * Search the locklist chain for this process.
+ */
+ do {
+ if (kread(llp, (char *)&ll, sizeof(ll)))
+ return((int)' ');
+
+#if !defined(L_REMOTE)
+#define L_REMOTE 0x1 /* from HP-UX 9.01 */
+#endif /* !defined(L_REMOTE) */
+
+# if HPUXV<1010
+ if (ll.ll_flags & L_REMOTE || ll.ll_proc != (KA_T)Kpa)
+# else /* HPUXV>=1010 */
+ if (ll.ll_flags & L_REMOTE || (KA_T)ll.ll_kthreadp != Ktp)
+# endif /* HPUXV<1010 */
+
+ continue;
+ l = 0;
+ if (ll.ll_start == 0) {
+ switch (ety) {
+ case 0:
+ if (ll.ll_end == ei)
+ l = 1;
+ break;
+ case 1:
+ if (ll.ll_end == el)
+ l = 1;
+ break;
+ }
+ }
+ if (ll.ll_type == F_WRLCK)
+ return((int)(l ? 'W' : 'w'));
+ else if (ll.ll_type == F_RDLCK)
+ return((int)(l ? 'R' : 'r'));
+ return((int)' ');
+ }
+
+# if HPUXV<1010
+ while ((llp = (KA_T)ll.ll_link) && llp != llf);
+# else /* HPUXV>=1010 */
+ while ((llp = (KA_T)ll.ll_fwd) && llp != llf);
+# endif /* HPUXV<1010 */
+
+ return((int)' ');
+}
+#endif /* HPUXV>=900 */
+
+
+/*
+ * getnodety() - get node type
+ */
+
+static int
+getnodety(v)
+ struct vnode *v; /* local vnode copy */
+{
+
+#if defined(HAS_AFS)
+ static int afs = 0; /* AFS test status: -1 = no AFS
+ * 0 = not tested
+ * 1 = AFS present */
+ struct afsnode an;
+#endif /* defined(HAS_AFS) */
+
+ static int ft = 1;
+ static KA_T avops;
+ static KA_T cvops;
+ static KA_T fvops;
+ static KA_T mvops;
+ static KA_T nvops;
+ static KA_T nvops3;
+ static KA_T nv3ops;
+ static KA_T pvops;
+ static KA_T svops;
+ static KA_T uvops;
+ static KA_T vvops;
+/*
+ * Do first-time only operations.
+ */
+ if (ft) {
+ if (get_Nl_value("avops", Drive_Nl, &avops) < 0)
+ avops = (unsigned long)0;
+ if (get_Nl_value("cvops", Drive_Nl, &cvops) < 0)
+ cvops = (unsigned long)0;
+ if (get_Nl_value("fvops", Drive_Nl, &fvops) < 0)
+ fvops = (unsigned long)0;
+ if (get_Nl_value("mvops", Drive_Nl, &mvops) < 0)
+ mvops = (unsigned long)0;
+ if (get_Nl_value("nvops", Drive_Nl, &nvops) < 0)
+ nvops = (unsigned long)0;
+ if (get_Nl_value("nvops3", Drive_Nl, &nvops3) < 0)
+ nvops3 = (unsigned long)0;
+ if (get_Nl_value("nv3ops", Drive_Nl, &nv3ops) < 0)
+ nv3ops = (unsigned long)0;
+ if (get_Nl_value("pvops", Drive_Nl, &pvops) < 0)
+ pvops = (unsigned long)0;
+ if (get_Nl_value("svops", Drive_Nl, &svops) < 0)
+ svops = (unsigned long)0;
+ if (get_Nl_value("uvops", Drive_Nl, &uvops) < 0)
+ uvops = (unsigned long)0;
+ if (get_Nl_value("vvops", Drive_Nl, &vvops) < 0)
+ vvops = (unsigned long)0;
+ ft = 0;
+ }
+/*
+ * Determine the vnode type.
+ */
+ if (uvops && uvops == (unsigned long)v->v_op)
+ return(N_REGLR);
+ else if (nvops && nvops == (unsigned long)v->v_op)
+ return(N_NFS);
+ else if (nvops3 && nvops3 == (unsigned long)v->v_op)
+ return(N_NFS);
+ else if (nv3ops && nv3ops == (unsigned long)v->v_op)
+ return(N_NFS);
+ else if (mvops && mvops == (unsigned long)v->v_op)
+ return(N_MVFS);
+
+#if defined(HASVXFS)
+ else if (vvops && vvops == (unsigned long)v->v_op)
+ return(N_VXFS);
+#endif /* defined(HASVXFS) */
+
+#if HPUXV>=1000
+ else if (cvops && cvops == (unsigned long)v->v_op)
+ return(N_CDFS);
+ else if (fvops && fvops == (unsigned long)v->v_op)
+ return(N_FIFO);
+ else if (pvops && pvops == (unsigned long)v->v_op)
+ return(N_PIPE);
+ else if (svops && svops == (unsigned long)v->v_op)
+ return(N_SPEC);
+#else /* HPUXV<1000 */
+ else if (v->v_type == VFIFO)
+ return(N_FIFO);
+#endif /* HPUXV<1000 */
+
+#if defined(HAS_AFS)
+ /*
+ * Caution: this AFS test should be the last one.
+ */
+
+ else if (avops) {
+ if (avops == (unsigned long)v->v_op)
+ return(N_AFS);
+ else {
+
+unknown_v_op:
+ (void) snpf(Namech, Namechl,
+ "unknown file system type; v_op: %s",
+ print_kptr((KA_T)v->v_op, (char *)NULL, 0));
+ enter_nm(Namech);
+ return(-1);
+ }
+ } else if (v->v_data || !v->v_vfsp)
+ goto unknown_v_op;
+ else {
+ switch (afs) {
+ case -1:
+ goto unknown_v_op;
+ case 0:
+ if (!hasAFS(v)) {
+ afs = -1;
+ goto unknown_v_op;
+ }
+ afs = 1;
+ return(N_AFS);
+ break;
+ case 1:
+ if (v->v_vfsp == AFSVfsp)
+ return(N_AFS);
+ else
+ goto unknown_v_op;
+ }
+ }
+#else /* !defined(HAS_AFS) */
+ else {
+ (void) snpf(Namech, Namechl,
+ "unknown file system type; v_op: %s",
+ print_kptr((KA_T)v->v_op, (char *)NULL, 0));
+ enter_nm(Namech);
+ return(-1);
+ }
+#endif /* defined(HAS_AFS) */
+
+}
+
+
+/*
+ * process_node() - process vnode
+ */
+
+void
+process_node(va)
+ KA_T va; /* vnode kernel space address */
+
+{
+
+#if defined(HAS_AFS)
+ struct afsnode an;
+#endif /* defined(HAS_AFS) */
+
+ dev_t dev, rdev;
+ int devs = 0;
+ struct inode i;
+ int ins = 0;
+ struct mvfsnode m;
+ struct rnode r;
+ int rdevs = 0;
+ int rns = 0;
+ char tbuf[32], *ty;
+ enum vtype type;
+ static struct vnode *v = (struct vnode *)NULL;
+ struct l_vfs *vfs;
+ int vty;
+
+#if HPUXV>=900
+ char fb[128];
+ int fns = 0;
+ int rp, sz, wp;
+ struct vnode rv;
+ struct snode s;
+#endif /* HPUXV>=900 */
+
+#if HPUXV>=1000
+ struct cdnode c;
+ struct fifonode f;
+ struct vattr vat;
+ int vats = 0;
+#endif /* HPUXV>=1000 */
+
+/*
+ * Read the vnode.
+ */
+ if ( ! va) {
+ enter_nm("no vnode address");
+ return;
+ }
+ if (!v) {
+
+ /*
+ * Allocate space for the vnode or AFS vcache structure.
+ */
+
+#if defined(HAS_AFS)
+ v = alloc_vcache();
+#else /* !defined(HAS_AFS) */
+ v = (struct vnode *)malloc(sizeof(struct vnode));
+#endif /* defined(HAS_AFS) */
+
+ if (!v) {
+ (void) fprintf(stderr, "%s: can't allocate %s space\n", Pn,
+
+#if defined(HAS_AFS)
+ "vcache"
+#else /* !defined(HAS_AFS) */
+ "vnode"
+#endif /* defined(HAS_AFS) */
+
+ );
+ Exit(1);
+ }
+ }
+ if (readvnode(va, v)) {
+ enter_nm(Namech);
+ return;
+ }
+
+#if defined(HASNCACHE)
+ Lf->na = va;
+#endif /* defined(HASNCACHE) */
+
+#if defined(HASFSTRUCT)
+ Lf->fna = va;
+ Lf->fsv |= FSV_NI;
+#endif /* defined(HASFSTRUCT) */
+
+/*
+ * Get the primary vnode type.
+ */
+ vty = getnodety(v);
+ if (vty == -1)
+ return;
+ Ntype = vty;
+/*
+ * Determine lock type.
+ */
+
+#if HPUXV<900
+ if (v->v_shlockc || v->v_exlockc) {
+ if (v->v_shlockc && v->v_exlockc)
+ Lf->lock = 'u';
+ else if (v->v_shlockc)
+ Lf->lock = 'R';
+ else
+ Lf->lock = 'W';
+ }
+#else /* HPUXV>900 */
+# if HPUXV>=1000
+ Lf->lock = (char)islocked((KA_T)v->v_locklist);
+# endif /* HPUXV>=1000 */
+#endif /* HPUXV<900 */
+
+/*
+ * Establish the local virtual file system structure.
+ */
+ if (!v->v_vfsp)
+ vfs = (struct l_vfs *)NULL;
+ else if (!(vfs = readvfs(v))) {
+ (void) snpf(Namech, Namechl, "can't read vfs for %s at %s",
+ print_kptr(va, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)v->v_vfsp, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+/*
+ * Read the cdnode, fifonode, inode, rnode, snode, or vache struct.
+ */
+ switch (Ntype) {
+
+#if defined(HAS_AFS)
+ case N_AFS:
+ if (readafsnode(va, v, &an))
+ return;
+ break;
+#endif /* defined(HAS_AFS) */
+
+#if defined(HASVXFS)
+ case N_VXFS:
+ if (!v->v_data || read_vxnode(v, vfs, &dev, &devs, &rdev, &rdevs)) {
+ (void) snpf(Namech, Namechl,
+ "vnode at %s: can't read vx_inode (%s)",
+ print_kptr(va, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ break;
+#endif /* defined(HASVXFS) */
+
+#if HPUXV>=1000
+ case N_CDFS:
+ if (!v->v_data
+ || kread((KA_T)v->v_data, (char *)&c, sizeof(c))) {
+ (void) snpf(Namech, Namechl,
+ "vnode at %s: can't read cdnode (%s)",
+ print_kptr(va, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ break;
+ case N_FIFO:
+ case N_PIPE:
+ if (!v->v_data
+ || kread((KA_T)v->v_data, (char *)&f, sizeof(f))) {
+ (void) snpf(Namech, Namechl,
+ "vnode at %s: can't read fifonode (%s)",
+ print_kptr(va, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ fns = 1;
+ if (f.fn_vap
+ && kread((KA_T)f.fn_vap, (char *)&vat, sizeof(vat)) == 0)
+ vats = 1;
+ break;
+#endif /* HPUXV>=1000 */
+
+ case N_MVFS:
+ if (read_nmn(va, (KA_T)v->v_data, &m))
+ return;
+ break;
+ case N_NFS:
+ if (!v->v_data || readrnode((KA_T)v->v_data, &r)) {
+ (void) snpf(Namech, Namechl,
+ "vnode at %s: can't read rnode (%s)",
+ print_kptr(va, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ rns = 1;
+ break;
+
+#if HPUXV>=1000
+ case N_SPEC:
+ if ((v->v_type == VBLK) || (v->v_type == VCHR)) {
+ if (!v->v_data || readsnode((KA_T)v->v_data, &s)) {
+ (void) snpf(Namech, Namechl,
+ "vnode at %s: can't read snode(%s)",
+ print_kptr(va, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ if (!s.s_realvp
+ || readvnode((KA_T)s.s_realvp, &rv)) {
+ (void) snpf(Namech, Namechl,
+ "snode at %s: can't read real vnode (%s)",
+ print_kptr((KA_T)v->v_data, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)s.s_realvp, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+
+#if defined(HASVXFS)
+ if (getnodety(&rv) == N_VXFS) {
+ if (!rv.v_data
+ || read_vxnode(&rv, vfs, &dev, &devs, &rdev, &rdevs)) {
+ (void) snpf(Namech, Namechl,
+ "vnode at %s: can't read vx_inode (%s)",
+ print_kptr(va, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)rv.v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ Ntype = N_VXFS;
+ break;
+ }
+#endif /* defined(HASVXFS) */
+
+ if (!rv.v_data || readinode((KA_T)rv.v_data, &i)) {
+ (void) snpf(Namech, Namechl,
+ "snode at %s: can't read inode (%s)",
+ print_kptr((KA_T)v->v_data, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)rv.v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ ins = 1;
+ break;
+ }
+ if (!v->v_data || readinode((KA_T)v->v_data, &i)) {
+ (void) snpf(Namech, Namechl,
+ "vnode at %s: can't read inode (%s)",
+ print_kptr(va, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ ins = 1;
+ break;
+#endif /* HPUXV>=1000 */
+
+#if HPUXV>=900 && HPUXV<1000
+ case N_FIFO:
+ if (v->v_fstype == VNFS_FIFO) {
+ if (!v->v_data || readsnode((KA_T)v->v_data, &s)) {
+ (void) snpf(Namech, Namechl,
+ "vnode at %s: can't read snode (%s)",
+ print_kptr(va, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ if (!s.s_realvp || readvnode((KA_T)s.s_realvp, &rv)) {
+ (void) snpf(Namech, Namechl,
+ "snode at %s: can't read real vnode (%s)",
+ print_kptr((KA_T)v->v_data, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)s.s_realvp, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ if (!rv.v_data || readrnode((KA_T)rv.v_data, &r)) {
+ (void) snpf(Namech, Namechl,
+ "snode at %s: can't read real rnode (%s)",
+ print_kptr((KA_T)v->v_data, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)s.s_realvp, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ rns = 1;
+ break;
+ }
+ /* fall through */
+#endif /* HPUXV>=900 && HPUXV<1000 */
+
+ case N_REGLR:
+ default:
+ if (!v->v_data || readinode((KA_T)v->v_data, &i)) {
+ (void) snpf(Namech, Namechl,
+ "vnode at %s: can't read inode (%s)",
+ print_kptr(va, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ ins = 1;
+
+#if HPUXV>=900 && HPUXV<1000
+ if (v->v_type == VFIFO)
+ Ntype = N_FIFO;
+#endif /* HPUXV>=900 && HPUXV<1000 */
+
+ }
+
+#if HPUXV>=900 && HPUXV<1000
+ Lf->lock = (char)islocked((KA_T)i.i_locklist);
+#endif /* HPUXV>=900 && HPUXV<1000 */
+
+/*
+ * Get device and type for printing.
+ */
+ switch (Ntype) {
+
+#if defined(HAS_AFS)
+ case N_AFS:
+ dev = an.dev;
+ devs = 1;
+ break;
+#endif /* defined(HAS_AFS) */
+
+ case N_MVFS:
+ if (vfs) {
+ dev = vfs->dev;
+ devs = 1;
+ }
+ break;
+ case N_NFS:
+ dev = vfs ? vfs->dev : 0;
+ devs = 1;
+ break;
+
+#if HPUXV>=1000
+ case N_CDFS:
+ dev = c.cd_dev;
+ devs = 1;
+ break;
+ case N_FIFO:
+ case N_PIPE:
+ if (vfs && vfs->fsname) {
+ dev = vfs->dev;
+ devs = 1;
+ } else if (vats && (dev_t)vat.va_fsid != NODEV) {
+ dev = (dev_t)vat.va_fsid;
+ devs = 1;
+ } else
+ enter_dev_ch(print_kptr(va, (char *)NULL, 0));
+ break;
+#endif /* _HPUX>=1000 */
+
+#if defined(HASVXFS)
+ case N_VXFS:
+ /* obtained via read_vxnode */
+ break;
+#endif /* defined(HASVXFS) */
+
+ case N_SPEC:
+ default:
+
+#if HPUXV>=800
+ if (vfs && vfs->fsname) {
+ dev = vfs->dev;
+ devs = 1;
+ } else if (ins) {
+ dev = i.i_dev;
+ devs = 1;
+ }
+ if ((v->v_type == VBLK) || (v->v_type == VCHR)) {
+ rdev = v->v_rdev;
+ rdevs = 1;
+ }
+#else /* HPUXV<800 */
+ if (ins) {
+ dev = i.i_dev;
+ devs = 1;
+ }
+ if ((v->v_type == VCHR) || (v->v_type == VBLK)) {
+ rdev = v->v_rdev;
+ rdevs = 1;
+ }
+#endif /* HPUXV>=800 */
+
+ }
+ type = v->v_type;
+/*
+ * Obtain the inode number.
+ */
+ switch (Ntype) {
+
+#if defined(HAS_AFS)
+ case N_AFS:
+ if (an.ino_st) {
+ Lf->inode = (INODETYPE)an.inode;
+ Lf->inp_ty = 1;
+ }
+ break;
+#endif /* defined(HAS_AFS) */
+
+ case N_MVFS:
+ Lf->inode = (INODETYPE)m.m_ino;
+ Lf->inp_ty = 1;
+ break;
+ case N_NFS:
+
+#if HPUXV<1030
+ Lf->inode = (INODETYPE)r.r_nfsattr.na_nodeid;
+#else /* HPUXV>=1030 */
+ Lf->inode = (INODETYPE)r.r_attr.va_nodeid;
+#endif /* HPUXV<1030 */
+
+ Lf->inp_ty = 1;
+ break;
+
+#if HPUXV>=1000
+ case N_CDFS:
+ Lf->inode = (INODETYPE)c.cd_num;
+ Lf->inp_ty = 1;
+ break;
+ case N_FIFO:
+ case N_PIPE:
+ if (vats) {
+ Lf->inode = (INODETYPE)vat.va_nodeid;
+ Lf->inp_ty = 1;
+ } else {
+ Lf->inode = (INODETYPE)v->v_nodeid;
+ Lf->inp_ty = 1;
+ }
+ break;
+#endif /* HPUXV>=1000 */
+
+#if defined(HASVXFS)
+ case N_VXFS:
+ /* set in read_vxnode() */
+ break;
+#endif /* defined(HASVXFS) */
+
+#if HPUXV<1000
+ case N_FIFO:
+
+# if HPUXV>=900
+ if (rns) {
+ Lf->inode = (INODETYPE)r.r_nfsattr.na_nodeid;
+ Lf->inp_ty = 1;
+ break;
+ }
+# endif /* HPUXV>=900 */
+ /* fall through */
+
+#endif /* HPUXV<1000 */
+
+ case N_BLK:
+ case N_REGLR:
+ case N_SPEC:
+ if (ins) {
+ Lf->inode = (INODETYPE)i.i_number;
+ Lf->inp_ty = 1;
+ }
+ }
+
+#if HPUXV>=1030
+/*
+ * Check for an HP-UX 10.30 and above stream.
+ */
+ if (v->v_stream) {
+ KA_T ip, pcb;
+ char *pn = (char *)NULL;
+
+ Lf->dev = dev;
+ Lf->dev_def = devs;
+ Lf->rdev = rdev;
+ Lf->rdev_def = rdevs;
+ if (read_mi((KA_T)v->v_stream, &ip, &pcb, &pn))
+ return;
+ if (ip && pcb) {
+ process_stream_sock(ip, pcb, pn, type);
+ return;
+ }
+ Lf->is_stream = 1;
+ }
+#endif /* HPUXV>=1030 */
+
+/*
+ * Obtain the file size.
+ */
+ if (Foffset)
+ Lf->off_def = 1;
+ else {
+ switch (Ntype) {
+
+#if defined(HAS_AFS)
+ case N_AFS:
+ Lf->sz = (SZOFFTYPE)an.size;
+ Lf->sz_def = 1;
+ break;
+#endif /* defined(HAS_AFS) */
+
+#if HPUXV>=1000
+ case N_CDFS:
+ Lf->sz = (SZOFFTYPE)c.cd_cdc.cdc_size;
+ Lf->sz_def = 1;
+ break;
+ case N_PIPE:
+ if (vats) {
+ Lf->sz = (SZOFFTYPE)vat.va_size;
+ Lf->sz_def = 1;
+ }
+ break;
+#endif /* HPUXV>=1000 */
+
+#if HPUXV>=900
+ case N_FIFO:
+
+# if HPUXV<1000
+ if (ins) {
+ rp = i.i_frptr;
+ sz = (int)i.i_fifosize;
+ wp = i.i_fwptr;
+ } else if (rns)
+ Lf->sz = (SZOFFTYPE)r.r_nfsattr.na_size;
+# else /* HPUXV>=1000 */
+ if (fns) {
+ rp = f.fn_rptr;
+ sz = f.fn_size;
+ wp = f.fn_wptr;
+ }
+# endif /* HPUXV<1000 */
+
+ if (Fsize || (Lf->access != 'r' && Lf->access != 'w')) {
+ if (fns || ins) {
+ (void) snpf(fb, sizeof(fb), "rd=%#x; wr=%#x", rp, wp);
+ (void) enter_nma(fb);
+ }
+ if (fns || ins || rns) {
+ Lf->sz = (SZOFFTYPE)sz;
+ Lf->sz_def = 1;
+ }
+ break;
+ }
+ if (fns || ins) {
+ Lf->off = (unsigned long)((Lf->access == 'r') ? rp
+ : wp);
+ (void) snpf(fb, sizeof(fb), "%s=%#x",
+ (Lf->access == 'r') ? "rd" : "wr",
+ (Lf->access == 'r') ? rp : wp);
+ (void) enter_nma(fb);
+ }
+ Lf->off_def = 1;
+ break;
+#endif /* HPUXV>=900 */
+
+ case N_MVFS:
+ /* The location of the file size isn't known. */
+ break;
+ case N_NFS:
+
+#if HPUXV<1030
+ Lf->sz = (SZOFFTYPE)r.r_nfsattr.na_size;
+#else /* HPUXV>=1030 */
+ Lf->sz = (SZOFFTYPE)r.r_attr.va_size;
+#endif /* HPUXV<1030 */
+
+ Lf->sz_def = 1;
+ break;
+
+#if defined(HASVXFS)
+ case N_VXFS:
+ /* set in read_vxnode() */
+ break;
+#endif /* defined(HASVXFS) */
+
+ case N_SPEC:
+ case N_REGLR:
+ if ((type == VCHR || type == VBLK) && !Fsize)
+ Lf->off_def = 1;
+ else if (ins) {
+ Lf->sz = (SZOFFTYPE)i.i_size;
+ Lf->sz_def = 1;
+ }
+ break;
+ }
+ }
+/*
+ * Record link count.
+ */
+ if (Fnlink) {
+ switch(Ntype) {
+
+# if defined(HAS_AFS)
+ case N_AFS:
+ Lf->nlink = an.nlink;
+ Lf->nlink_def = an.nlink_st;
+ break;
+# endif /* defined(HAS_AFS) */
+
+ case N_MVFS:
+ /* The location of the link count isn't known. */
+ break;
+ case N_NFS:
+
+#if HPUXV<1030
+ Lf->nlink = r.r_nfsattr.na_nlink;
+#else /* HPUXV>=1030 */
+ Lf->nlink = r.r_attr.va_nlink;
+#endif /* HPUXV<1030 */
+
+ Lf->nlink_def = 1;
+ break;
+
+# if HPUXV>=1000
+ case N_CDFS: /* no link count? */
+ break;
+# endif /* HPUXV>=1000 */
+
+ case N_FIFO:
+ case N_PIPE:
+
+# if HPUXV>=1000
+ if (vats) {
+ Lf->nlink = (long)vat.va_nlink;
+ Lf->nlink_def = 1;
+ }
+# endif /* HPUXV>=1000 */
+
+ break;
+
+# if defined(HASVXFS)
+ case N_VXFS:
+ /* set in read_vxnode() */
+ break;
+# endif /* defined(HASVXFS) */
+
+ case N_SPEC:
+ default:
+ if (ins) {
+ Lf->nlink = (long)i.i_nlink;
+ Lf->nlink_def = 1;
+ }
+ break;
+ }
+ if (Nlink && Lf->nlink_def && (Lf->nlink < Nlink))
+ Lf->sf |= SELNLINK;
+ }
+/*
+ * Record an NFS file selection.
+ */
+ if (Ntype == N_NFS && Fnfs)
+ Lf->sf |= SELNFS;
+/*
+ * Save the file system names.
+ */
+ if (vfs) {
+ Lf->fsdir = vfs->dir;
+ Lf->fsdev = vfs->fsname;
+
+#if defined(HASFSINO)
+ Lf->fs_ino = vfs->fs_ino;
+#endif /* defined(HASFSINO) */
+
+ }
+/*
+ * Save the device numbers and their states.
+ *
+ * Format the vnode type, and possibly the device name.
+ */
+ Lf->dev = dev;
+ Lf->dev_def = devs;
+ Lf->rdev = rdev;
+ Lf->rdev_def = rdevs;
+ switch (type) {
+ case VNON:
+ ty ="VNON";
+ break;
+ case VREG:
+ case VDIR:
+ ty = (type == VREG) ? "VREG" : "VDIR";
+ break;
+ case VBLK:
+ ty = "VBLK";
+ Ntype = N_BLK;
+ break;
+ case VCHR:
+ ty = "VCHR";
+ Ntype = N_CHR;
+ break;
+ case VLNK:
+ ty = "VLNK";
+ break;
+
+#if defined(VSOCK)
+ case VSOCK:
+ ty = "SOCK";
+ break;
+#endif /* defined(VSOCK) */
+
+ case VBAD:
+ ty = "VBAD";
+ break;
+ case VFIFO:
+ switch (Ntype) {
+
+#if HPUXV>=1000
+ case N_FIFO:
+ ty = "FIFO";
+ break;
+ case N_PIPE:
+ ty = "PIPE";
+ break;
+#endif /* HPUXV>=1000 */
+
+ default:
+ ty = "FIFO";
+ }
+ break;
+ default:
+ (void) snpf(Lf->type, sizeof(Lf->type), "%04o", (type & 0xfff));
+ ty = (char *)NULL;
+ }
+ if (ty)
+ (void) snpf(Lf->type, sizeof(Lf->type), "%s", ty);
+ Lf->ntype = Ntype;
+
+#if defined(HASBLKDEV)
+/*
+ * If this is a VBLK file and it's missing an inode number, try to
+ * supply one.
+ */
+ if ((Lf->inp_ty == 0) && (type == VBLK))
+ find_bl_ino();
+#endif /* defined(HASBLKDEV) */
+
+/*
+ * If this is a VCHR file and it's missing an inode number, try to
+ * supply one.
+ */
+ if ((Lf->inp_ty == 0) && (type == VCHR))
+ find_ch_ino();
+/*
+ * Test for specified file.
+ */
+ if (Sfile && is_file_named((char *)NULL,
+ ((type == VCHR) || (type == VBLK) ? 1 : 0)))
+ Lf->sf |= SELNM;
+/*
+ * Enter name characters.
+ */
+ if (Namech[0])
+ enter_nm(Namech);
+}
+
+
+
+/*
+ * readinode() - read inode
+ */
+
+static int
+readinode(ia, i)
+ KA_T ia; /* inode kernel address */
+ struct inode *i; /* inode buffer */
+{
+ if (kread((KA_T)ia, (char *)i, sizeof(struct inode))) {
+ (void) snpf(Namech, Namechl, "can't read inode at %s",
+ print_kptr(ia, (char *)NULL, 0));
+ return(1);
+ }
+ return(0);
+}
+
+
+/*
+ * read_nmn() - read node's mvfsnode
+ */
+
+static int
+read_nmn(na, ma, m)
+ KA_T na; /* containing node's address */
+ KA_T ma; /* kernel mvfsnode address */
+ struct mvfsnode *m; /* mvfsnode receiver */
+{
+ char tbuf[32];
+
+ if (!ma || kread((KA_T)ma, (char *)m, sizeof(struct mvfsnode))) {
+ (void) snpf(Namech, Namechl, "node at %s: can't read mvfsnode: %s",
+ print_kptr(na, tbuf, sizeof(tbuf)),
+ print_kptr(ma, (char *)NULL, 0));
+ enter_nm(Namech);
+ return(1);
+ }
+ return(0);
+}
diff --git a/dialects/hpux/kmem/dnode1.c b/dialects/hpux/kmem/dnode1.c
new file mode 100644
index 0000000..d6af239
--- /dev/null
+++ b/dialects/hpux/kmem/dnode1.c
@@ -0,0 +1,157 @@
+/*
+ * dnode1.c - /dev/kmem-based HP-UX node functions for lsof
+ *
+ * This module must be separate to keep separate the multiple kernel inode
+ * structure definitions.
+ */
+
+
+/*
+ * Copyright 1995 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dnode1.c,v 1.11 2005/08/08 19:50:23 abe Exp $";
+#endif
+
+
+#if defined(HASVXFS)
+
+# if defined(HPUXKERNBITS) && HPUXKERNBITS>=64
+#define _INO_T
+typedef int ino_t;
+#define _TIME_T
+typedef int time_t;
+# endif /* defined(HPUXKERNBITS) && HPUXKERNBITS>=64 */
+
+#include "lsof.h"
+
+
+/*
+ * HP-UX versions below 10.20:
+ *
+ * The pool_id_t type does not seem to be defined in the header files
+ * distributed by HP. However, <sys/fs/vx_hpux.h> requires it when
+ * _KERNEL is defined. So we fake the pool_id_t definition.
+ *
+ * <sys/fs/vx_hpux.h> also requires sv_sema_t. It's defined in
+ * <sys/sem_alpha.h> when _KERNEL is defined, but some other header file has
+ * already included <sys/sem_alpha.h> with _KERNEL undefined. So we fake the
+ * sv_sema_t definition.
+ *
+ * HP-UX version 10.20 and above:
+ *
+ * The pool_id_t type is used by other header files for other purposes.
+ * Redefine it for VXFS. Delete some other conflicting definitions.
+ * Don't #define _KERNEL. Include a different set of VXFS header files.
+ */
+
+
+# if HPUXV>=1020
+#undef te_offset
+#undef i_size
+#undef di_size
+#define pool_id_t vx_pool_id_t
+
+# if HPUXV>=1030
+#define ulong vx_ulong /* avoid <sys/stream.h> conflict */
+# endif /* HPUXV>=1030 */
+
+#include <sys/fs/vx_hpux.h>
+#include <sys/fs/vx_port.h>
+#include <sys/fs/vx_inode.h>
+
+# if HPUXV>=1030
+#undef ulong
+# endif /* HPUXV>=1030 */
+
+# else /* HPUXV<1020 */
+
+#define pool_id_t caddr_t
+#define sv_sema_t caddr_t
+#define _KERNEL
+#include <sys/fs/vx_hpux.h>
+#include <sys/fs/vx_inode.h>
+#undef _KERNEL
+# endif /* HPUXV>=1020 */
+
+
+/*
+ * read_vxnode() - read Veritas file system inode information
+ */
+
+int
+read_vxnode(v, vfs, dev, devs, rdev, rdevs)
+ struct vnode *v; /* local containing vnode */
+ struct l_vfs *vfs; /* local vfs structure */
+ dev_t *dev; /* device number receiver */
+ int *devs; /* device status receiver */
+ dev_t *rdev; /* raw device number receiver */
+ int *rdevs; /* raw device status receiver */
+{
+ struct vx_inode i;
+
+ if (!v->v_data || kread((KA_T)v->v_data, (char *)&i, sizeof(i)))
+ return(1);
+/*
+ * Return device numbers.
+ */
+ if (vfs && vfs->fsname)
+ *dev = vfs->dev;
+ else
+ *dev = i.i_dev;
+ *devs = 1;
+ if ((v->v_type == VCHR) || (v->v_type == VBLK)) {
+ *rdev = v->v_rdev;
+ *rdevs = 1;
+ }
+/*
+ * Record inode number.
+ */
+ Lf->inode = (INODETYPE)i.i_number;
+ Lf->inp_ty = 1;
+/*
+ * Record size.
+ */
+ if (Foffset || ((v->v_type == VCHR || v->v_type == VBLK) && !Fsize))
+ Lf->off_def = 1;
+ else {
+ Lf->sz = (SZOFFTYPE)i.i_size;
+ Lf->sz_def = 1;
+ }
+/*
+ * Record link count.
+ */
+ if (Fnlink) {
+ Lf->nlink = (long)i.i_nlink;
+ Lf->nlink_def = 1;
+ if (Nlink && (Lf->nlink < Nlink))
+ Lf->sf |= SELNLINK;
+ }
+ return(0);
+}
+#endif /* defined(HASVXFS) */
diff --git a/dialects/hpux/kmem/dnode2.c b/dialects/hpux/kmem/dnode2.c
new file mode 100644
index 0000000..3429831
--- /dev/null
+++ b/dialects/hpux/kmem/dnode2.c
@@ -0,0 +1,371 @@
+/*
+ * dnode2.c - /dev/kmem-based HP-UX AFS support
+ */
+
+
+/*
+ * Copyright 1996 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 1996 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dnode2.c,v 1.7 2005/08/08 19:50:23 abe Exp $";
+#endif
+
+#if defined(HAS_AFS)
+
+# if defined(HPUXKERNBITS) && HPUXKERNBITS>=64
+#define _INO_T
+typedef int ino_t;
+#define _TIME_T
+typedef int time_t;
+# endif /* defined(HPUXKERNBITS) && HPUXKERNBITS>=64 */
+
+#include "lsof.h"
+#include <afs/stds.h>
+#include <afs/param.h>
+#undef __dontcare__
+#include <afs/afsint.h>
+#include <afs/vldbint.h>
+
+
+/*
+ * This is an emulation of the afs_rwlock_t definition that appears in
+ * the AFS sources in afs/lock.h.
+ */
+
+struct afs_lock {
+
+# if HAS_AFS<304
+ unsigned long d1[1];
+# else /* HAS_AFS>=304 */
+ unsigned long d1[6];
+# endif /* HAS_AFS<304 */
+
+};
+typedef struct afs_lock afs_lock_t;
+typedef struct afs_lock afs_rwlock_t;
+
+#define KERNEL
+#include <afs/afs.h>
+#undef KERNEL
+
+
+/*
+ * Local function prototypes
+ */
+
+_PROTOTYPE(static struct volume *getvolume,(struct VenusFid *f, int *vols));
+_PROTOTYPE(static int is_rootFid,(struct vcache *vc, int *rfid));
+
+
+/*
+ * alloc_vcache() - allocate space for vcache structure
+ */
+
+struct vnode *
+alloc_vcache()
+{
+ return((struct vnode *)malloc(sizeof(struct vcache)));
+}
+
+
+/*
+ * ckAFSsym() - check for missing X_AFS_* symbols in AFS name list file
+ */
+
+void
+ckAFSsym(nl)
+ struct nlist *nl; /* copy of Nl[] when empty */
+{
+ char *path = AFSAPATHDEF;
+ int i;
+
+# if defined(HASAOPT)
+ if (AFSApath)
+ path = AFSApath;
+# endif /* defined(HASAOPT) */
+
+/*
+ * See if the alternate AFS name list file can be read.
+ */
+ if (!is_readable(path, 0)) {
+ if (!Fwarn)
+ (void) fprintf(stderr,
+ "%s: WARNING: can't access AFS name list file: %s\n",
+ Pn, path);
+ return;
+ }
+
+/*
+ * Read the AFS modload symbols and compare its non-zero values with
+ * the non-zero values in Nl[]. Quit if there is any mis-match.
+ */
+ if (nlist(path, nl) < 0)
+ return;
+ for (i = 0; Nl[i].n_name && Nl[i].n_name[0]; i++) {
+ if (!nl[i].n_value || !Nl[i].n_value)
+ continue;
+ if (nl[i].n_value != Nl[i].n_value)
+ return;
+ }
+/*
+ * If any X_AFS_* symbol that doesn't have a value in Nl[] has one from
+ * the AFS modload file, copy its modload value to Nl[].
+ */
+ if (((i = get_Nl_value("arFid", Drive_Nl, NULL)) >= 0)
+ && !Nl[i].n_value && nl[i].n_value)
+ Nl[i].n_value = nl[i].n_value;
+ if (((i = get_Nl_value("avops", Drive_Nl, NULL)) >= 0)
+ && !Nl[i].n_value && nl[i].n_value)
+ Nl[i].n_value = nl[i].n_value;
+ if (((i = get_Nl_value("avol", Drive_Nl, NULL)) >= 0)
+ && !Nl[i].n_value && nl[i].n_value)
+ Nl[i].n_value = nl[i].n_value;
+}
+
+
+/*
+ * getvolume() - get volume structure
+ */
+
+static struct volume *
+getvolume(f, vols)
+ struct VenusFid *f; /* file ID pointer */
+ int *vols; /* afs_volumes status return */
+{
+ int i;
+ static KA_T ka = 0;
+ KA_T kh;
+ static struct volume v;
+ struct volume *vp;
+ static int w = 0;
+
+ if (!ka) {
+ if (get_Nl_value("avol", Drive_Nl, (unsigned long *)&ka) < 0
+ || !ka) {
+ if (!w && !Fwarn) {
+ (void) fprintf(stderr,
+ "%s: WARNING: no afs_volumes kernel address\n", Pn);
+ (void) fprintf(stderr,
+ " This may hamper AFS node number reporting.\n");
+ w = 1;
+ }
+ *vols = 0;
+ return((struct volume *)NULL);
+ }
+ }
+ *vols = 1;
+ i = (NVOLS - 1) & f->Fid.Volume;
+ kh = (KA_T)((char *)ka + (i * sizeof(struct volume *)));
+ if (kread(kh, (char *)&vp, sizeof(vp)))
+ return((struct volume *)NULL);
+ while (vp) {
+ if (kread((KA_T)vp, (char *)&v, sizeof(v)))
+ return((struct volume *)NULL);
+ if (v.volume == f->Fid.Volume && v.cell == f->Cell)
+ return(&v);
+ vp = v.next;
+ }
+ return((struct volume *)NULL);
+}
+
+
+/*
+ * hasAFS() - test for AFS presence via vfs structure
+ */
+
+int
+hasAFS(vp)
+ struct vnode *vp; /* vnode pointer */
+{
+ struct vfs v;
+/*
+ * If this vnode has a v_data pointer, then it probably isn't an AFS vnode;
+ * return FALSE.
+ *
+ * If the vfs struct address of /afs is known and this vnode's v_vfsp matches
+ * it, return TRUE.
+ *
+ * Read this vnode's vfs structure and its mount structure. See if the file
+ * system name is AFS. If it isn't, return FALSE. If it is, save the vnode's
+ * v_vfsp as AFSVfsp and return TRUE.
+ */
+ if (AFSVfsp && !vp->v_data && vp->v_vfsp == AFSVfsp)
+ return(1);
+ if (vp->v_data
+ || !vp->v_vfsp
+ || kread((KA_T)vp->v_vfsp, (char *)&v, sizeof(v))
+ || v.vfs_data
+ || strcmp(v.vfs_name, "AFS") != 0)
+ return(0);
+ AFSVfsp = vp->v_vfsp;
+ return(1);
+}
+
+
+/*
+ * is_rootFid() - is the file ID the root file ID
+ *
+ * return: 0 = is not root file ID
+ * 1 = is root file ID
+ * rfid = 0 if root file ID structure address not available
+ * 1 if root file ID structure address available
+ */
+
+static int
+is_rootFid(vc, rfid)
+ struct vcache *vc; /* vcache structure */
+ int *rfid; /* root file ID pointer status return */
+{
+ char *err;
+ static int f = 0; /* rootFID structure status:
+ * -1 = unavailable
+ * 0 = not yet accessed
+ * 1 = available */
+ static struct VenusFid r;
+ unsigned long v;
+ static int w = 0;
+
+ switch (f) {
+ case -1:
+ if (vc->v.v_flag & VROOT) {
+ *rfid = 1;
+ return(1);
+ }
+ *rfid = 0;
+ return(0);
+ case 0:
+ if (get_Nl_value("arFid", Drive_Nl, &v) < 0 || !v) {
+ err = "no kernel address";
+
+rfid_unavailable:
+
+ if (!w && !Fwarn) {
+ (void) fprintf(stderr,
+ "%s: WARNING: AFS root Fid: %s\n", Pn, err);
+ (void) fprintf(stderr,
+ " This may hamper AFS node number reporting.\n");
+ w = 1;
+ }
+ f = -1;
+ if (vc->v.v_flag & VROOT) {
+ *rfid = 1;
+ return(1);
+ }
+ *rfid = 0;
+ return(0);
+ }
+ if (kread((KA_T)v, (char *)&r, sizeof(r))) {
+ err = "can't read from kernel";
+ goto rfid_unavailable;
+ }
+ f = 1;
+ /* fall through */
+ case 1:
+ *rfid = 1;
+ if (vc->fid.Fid.Unique == r.Fid.Unique
+ && vc->fid.Fid.Vnode == r.Fid.Vnode
+ && vc->fid.Fid.Volume == r.Fid.Volume
+ && vc->fid.Cell == r.Cell)
+ return(1);
+ }
+ *rfid = 0;
+ return(0);
+}
+
+
+/*
+ * readafsnode() - read AFS node
+ */
+
+int
+readafsnode(va, v, an)
+ KA_T va; /* kernel vnode address */
+ struct vnode *v; /* vnode buffer pointer */
+ struct afsnode *an; /* afsnode recipient */
+{
+ char *cp, tbuf[32];
+ KA_T ka;
+ int len, rfid, vols;
+ struct vcache *vc;
+ struct volume *vp;
+
+ cp = ((char *)v + sizeof(struct vnode));
+ ka = (KA_T)((char *)va + sizeof(struct vnode));
+ len = sizeof(struct vcache) - sizeof(struct vnode);
+ if (kread(ka, cp, len)) {
+ (void) snpf(Namech, Namechl,
+ "vnode at %s: can't read vcache remainder from %s",
+ print_kptr(va, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)ka, (char *)NULL, 0));
+ enter_nm(Namech);
+ return(1);
+ }
+ vc = (struct vcache *)v;
+ an->dev = AFSDEV;
+ an->size = (unsigned long)vc->m.Length;
+ an->nlink = (long)vc->m.LinkCount;
+ an->nlink_st = 1;
+/*
+ * Manufacture the "inode" number.
+ */
+ if (vc->mvstat == 2) {
+ if ((vp = getvolume(&vc->fid, &vols))) {
+ an->inode = (INODETYPE)(vp->mtpoint.Fid.Vnode +
+ (vp->mtpoint.Fid.Volume << 16));
+ if (an->inode == (INODETYPE)0) {
+ if (is_rootFid(vc, &rfid))
+ an->ino_st = 1;
+ else if (rfid) {
+ an->inode = (INODETYPE)2;
+ an->ino_st = 1;
+ } else
+ an->ino_st = 0;
+ } else
+ an->ino_st = 1;
+ } else {
+ if (vols) {
+ an->inode = (INODETYPE)2;
+ an->ino_st = 1;
+ } else {
+ if (v->v_flag & VROOT) {
+ an->inode = (INODETYPE)0;
+ an->ino_st = 1;
+ } else
+ an->ino_st = 0;
+ }
+ }
+ } else {
+ an->inode = (INODETYPE)((vc->fid.Fid.Vnode
+ + (vc->fid.Fid.Volume << 16))
+ & 0x7fffffff);
+ an->ino_st = 1;
+ }
+ return(0);
+}
+#endif /* defined(HAS_AFS) */
diff --git a/dialects/hpux/kmem/dproc.c b/dialects/hpux/kmem/dproc.c
new file mode 100644
index 0000000..62ad048
--- /dev/null
+++ b/dialects/hpux/kmem/dproc.c
@@ -0,0 +1,842 @@
+/*
+ * dproc.c - /dev/kmem-based HP-UX process access functions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dproc.c,v 1.18 2008/10/08 13:24:36 abe Exp $";
+#endif
+
+#if defined(HPUXKERNBITS)
+# if HPUXKERNBITS>=64
+#define _INO_T
+typedef int ino_t;
+#define _TIME_T
+typedef int time_t;
+# else /* HPUXKERNBITS<64 */
+#define _RLIM_T
+# if !defined(__STDC_32_MODE__)
+typedef unsigned long long rlim_t;
+# else /* defined(__STDC_32_MODE__) */
+typedef unsigned long rlim_t;
+# endif /* !defined(__STDC_32_MODE__) */
+# endif /* HPUXKERNBITS>=64 */
+#endif /* defined(HPUXKERNBITS) */
+
+#include "lsof.h"
+
+#if defined(HASNCACHE)
+#include <sys/dnlc.h>
+#endif /* defined(HASNCACHE) */
+
+
+#if HPUXV>=1010
+/*
+ * HP doesn't include a definition for the proc structure in HP-UX 10.10
+ * or above in an attempt to force use of pstat(2). Unfortunately, pstat(2)
+ * doesn't return the information lsof needs. Hence, this private proc
+ * structure definition.
+ */
+
+#include <sys/vas.h>
+
+#define SZOMB 3
+
+# if HPUXV<1020
+struct proc {
+ caddr_t d1[2]; /* dummy to occupy space */
+ caddr_t p_firstthreadp; /* thread pointer */
+ caddr_t d2[4]; /* dummy to occupy space */
+ int p_stat; /* process status */
+ caddr_t d3[9]; /* dummy to occupy space */
+ uid_t p_uid; /* UID */
+ caddr_t d4[2]; /* dummy to occupy space */
+ gid_t p_pgid; /* process group ID */
+ pid_t p_pid; /* PID */
+ pid_t p_ppid; /* parent PID */
+ caddr_t d5[9]; /* dummy to occupy space */
+ vas_t *p_vas; /* virtual address space */
+ caddr_t d6[16]; /* dummy to occupy space */
+ int p_maxof; /* max open files allowed */
+ struct vnode *p_cdir; /* current directory */
+ struct vnode *p_rdir; /* root directory */
+ struct ofile_t **p_ofilep; /* file descriptor chunks */
+ caddr_t d7[43]; /* dummy to occupy space */
+};
+# endif /* HPUXV<1020 */
+
+# if HPUXV>=1020 && HPUXV<1030
+struct proc {
+ caddr_t d1[2]; /* dummy to occupy space */
+ caddr_t p_firstthreadp; /* thread pointer */
+ caddr_t d2[6]; /* dummy to occupy space */
+ int p_stat; /* process status */
+ caddr_t d3[14]; /* dummy to occupy space */
+ uid_t p_uid; /* real UID */
+ uid_t p_suid; /* effective UID */
+ caddr_t d4; /* dummy to occupy space */
+ gid_t p_pgid; /* process group ID */
+ pid_t p_pid; /* PID */
+ pid_t p_ppid; /* parent PID */
+ caddr_t d5[9]; /* dummy to occupy space */
+ vas_t *p_vas; /* virtual address space */
+ caddr_t d6[16]; /* dummy to occupy space */
+ int p_maxof; /* max open files allowed */
+ struct vnode *p_cdir; /* current directory */
+ struct vnode *p_rdir; /* root directory */
+ struct ofile_t **p_ofilep; /* file descriptor chunks */
+ caddr_t d7[84]; /* dummy to occupy space */
+};
+# endif /* HPUXV>=1020 && HPUXV<1030 */
+#endif /* HPUXV<1010 */
+
+
+/*
+ * Local static values
+ */
+
+static KA_T Kp; /* kernel's process table address */
+static int Np; /* number of kernel processes */
+
+#if HPUXV>=800
+static MALLOC_S Nva = 0; /* number of entries allocated to
+ * vnode address cache */
+static KA_T *Vp = (KA_T *)NULL; /* vnode address cache */
+#endif /* HPUXV>=800 */
+
+
+_PROTOTYPE(static void get_kernel_access,(void));
+
+#if HPUXV>=800
+_PROTOTYPE(static void process_text,(KA_T vasp));
+#endif /* HPUXV>=800 */
+
+
+/*
+ * gather_proc_info() -- gather process information
+ */
+
+void
+gather_proc_info()
+{
+ KA_T fp;
+ int err, i, j;
+
+#if HPUXV>=1020 && HPUXV<1100
+ struct ofile_t {
+ struct ofa {
+ KA_T ofile;
+ int d1;
+ int pofile;
+ } ofa[SFDCHUNK];
+ };
+ struct ofa *ofap;
+ int ofasz = (int)sizeof(struct ofa);
+ struct ofile_t oft;
+ char *oftp = (char *)&oft;
+ int oftsz = (int)sizeof(struct ofile_t);
+#else /* HPUXV<1020 || HPUXV>=1100 */
+# if HPUXV>=1100
+ struct ofa {
+ KA_T ofile;
+ int d1;
+ short d2;
+ char d3;
+ char pofile;
+ };
+ struct ofa *ofap;
+ int ofasz = (int)sizeof(struct ofa);
+ char *oftp = (char *)NULL;
+ int oftsz = (int)(sizeof(struct ofa) * SFDCHUNK);
+ KA_T v;
+# endif /* HPUXV>=1100 */
+#endif /* HPUXV>=1020 && HPUXV<1100 */
+
+#if HPUXV>=800
+ char *c, *s;
+ KA_T pfp, ofp;
+
+#if HPUXV<1020
+ struct ofile_t oft;
+ char *oftp = (char *)&oft;
+ int oftsz = (int)sizeof(struct ofile_t);
+#endif /* HPUXV<1020 */
+
+ struct pst_status ps;
+
+# if HPUXV<1010
+ struct user us;
+# else /* HPUXV>=1010 */
+ struct user {
+ char u_comm[PST_CLEN];
+ } us;
+# endif /* HPUXV<1010 */
+#else /* HPUXV<800 */
+ int k;
+ long sw;
+ char us[U_SIZE]; /* must read HP-UX SWAP in DEV_BSIZE chunks */
+
+# if defined(hp9000s300)
+ struct pte pte1, pte2;
+ KA_T pte_off, pte_addr;
+# endif /* defined(hp9000s300) */
+#endif /* HPUXV>=800 */
+
+ struct proc *p;
+ struct proc pbuf;
+ short pss, sf;
+ int px;
+ struct user *u;
+
+#if defined(HASFSTRUCT)
+# if HPUXV>=1020 || (HPUXV>=900 && HPUXV<1000)
+#define USESPOFILE 1
+ long pof;
+# endif /* HPUXV>=1020 || (HPUXV>=900 && HPUXV<1000) */
+#endif /* defined(HASFSTRUCT) */
+
+#if HPUXV>=1100
+/*
+ * Define FD chunk size and pointer for HP-UX >= 11.
+ */
+ if (!oftp) {
+ if ((get_Nl_value("chunksz", Drive_Nl, &v) >= 0) && v) {
+ if (kread(v, (char *)&oftsz, sizeof(oftsz))) {
+ (void) fprintf(stderr, "%s: can't get FD chunk size\n",
+ Pn);
+ Exit(1);
+ }
+ if (!oftsz) {
+ (void) fprintf(stderr, "%s: bad FD chunk size: %d\n",
+ Pn, oftsz);
+ Exit(1);
+ }
+ }
+ ofasz = (int)(oftsz / SFDCHUNK);
+ if (oftsz != (ofasz * SFDCHUNK)) {
+ (void) fprintf(stderr,
+ "%s: FD chunk size (%d) not exact multiple of %d\n",
+ Pn, oftsz, SFDCHUNK);
+ Exit(1);
+ }
+ if (!(oftp = (char *)malloc((MALLOC_S)oftsz))) {
+ (void) fprintf(stderr, "%s: no space for %d FD bytes\n",
+ Pn, oftsz);
+ Exit(1);
+ }
+ }
+#endif /* HPUXV>=1100 */
+
+/*
+ * Examine proc structures and their associated information.
+ */
+
+#if HPUXV>=800
+ u = &us;
+ (void) zeromem((char *)u, U_SIZE);
+ for (p = &pbuf, px = 0; px < Np; px++)
+#else /* HPUXV<800 */
+ for (p = &pbuf, px = 0, u = (struct user *)us; px < Np; px++)
+#endif /* HPUXV>=800 */
+
+ {
+ Kpa = Kp + (KA_T)(px * sizeof(struct proc));
+ if (kread(Kpa, (char *)&pbuf, sizeof(pbuf)))
+ continue;
+ if (p->p_stat == 0 || p->p_stat == SZOMB)
+ continue;
+ /*
+ * See if process is excluded.
+ */
+ if (is_proc_excl(p->p_pid, (int)p->p_pgid, (UID_ARG)p->p_uid,
+ &pss, &sf))
+ continue;
+
+#if HPUXV>=1010
+ /*
+ * Save the kernel thread pointer.
+ */
+ Ktp = (KA_T)p->p_firstthreadp;
+#endif /* HPUXV>=1010 */
+
+ /*
+ * Read the user area.
+ */
+
+#if HPUXV>=800
+ /*
+ * Use the pstat() syscall to read process status.
+ */
+
+ if (pstat(PSTAT_PROC, &ps, sizeof(ps), 0, p->p_pid) != 1) {
+ if (!Fwarn)
+ (void) fprintf(stderr, "%s: can't pstat process %d: %s\n",
+ Pn, p->p_pid, strerror(errno));
+ continue;
+ }
+ /*
+ * Use the pst_cmd command buffer.
+ */
+ c = ps.pst_cmd;
+ ps.pst_cmd[PST_CLEN - 1] = '\0'; /* paranoia */
+ /*
+ * Skip to the last component of the first path name. Also skip any
+ * leading `-', signifying a login shell. Copy the result to u_comm[].
+ */
+ if (*c == '-')
+ c++;
+ for (s = c; *c && (*c != ' '); c++) {
+ if (*c == '/')
+ s = c + 1;
+ }
+ for (i = 0; i < MAXCOMLEN; i++) {
+ if (*s == '\0' || *s == ' ' || *s == '/')
+ break;
+ u->u_comm[i] = *s++;
+ }
+ u->u_comm[i] = '\0';
+#else /* HPUXV<800 */
+ /*
+ * Read the user area from the swap file or memory.
+ */
+ if ((p->p_flag & SLOAD) == 0) {
+
+ /*
+ * If the process is not loaded, read the user area from the swap
+ * file.
+ */
+ if (Swap < 0)
+ continue;
+ sw = (long)p->p_swaddr;
+
+# if defined(hp9000s800)
+ sw += (long)ctod(btoc(STACKSIZE * NBPG));
+# endif /* defined(hp9000s800) */
+
+ if (lseek(Swap, (off_t)dtob(sw), L_SET) == (off_t)-1
+ || read(Swap, u, U_SIZE) != U_SIZE)
+ continue;
+ } else {
+
+ /*
+ * Read the user area via the page table.
+ */
+
+# if defined(hp9000s300)
+ pte_off = (KA_T) &Usrptmap[btokmx(p->p_p0br) + p->p_szpt - 1];
+ if (kread(pte_off, (char *)&pte1, sizeof(pte1)))
+ continue;
+ pte_addr = (KA_T)(ctob(pte1.pg_pfnum + 1)
+ - ((UPAGES + FLOAT) * sizeof(pte2)));
+ if (mread(pte_addr, (char *)&pte2, sizeof(pte2)))
+ continue;
+ if (mread((KA_T)ctob(pte2.pg_pfnum), (char *)u,
+ sizeof(struct user)))
+ continue;
+# endif /* defined(hp9000s300) */
+
+# if defined(hp9000s800)
+ if (kread((KA_T)uvadd((struct proc *)Kpa), (char *)u,
+ sizeof(struct user)))
+ continue;
+ }
+# endif /* defined(hp9000s800) */
+#endif /* HPUXV>=800 */
+
+ /*
+ * Allocate a local process structure.
+ */
+ if (is_cmd_excl(u->u_comm, &pss, &sf))
+ continue;
+ alloc_lproc(p->p_pid, (int)p->p_pgid, (int)p->p_ppid,
+ (UID_ARG)p->p_uid, u->u_comm, (int)pss, (int)sf);
+ Plf = (struct lfile *)NULL;
+ /*
+ * Save current working directory information.
+ */
+ if (CURDIR) {
+ alloc_lfile(CWD, -1);
+ process_node((KA_T)CURDIR);
+ if (Lf->sf)
+ link_lfile();
+ }
+ /*
+ * Save root directory information.
+ */
+ if (ROOTDIR) {
+ alloc_lfile(RTD, -1);
+ process_node((KA_T)ROOTDIR);
+ if (Lf->sf)
+ link_lfile();
+ }
+
+#if HPUXV>=800
+ /*
+ * Print information on the text file.
+ */
+ if (p->p_vas)
+ process_text((KA_T)p->p_vas);
+#endif /* HPUXV>=800 */
+
+ /*
+ * Loop through user's files.
+ */
+
+#if HPUXV>=800
+ for (i = 0, j = SFDCHUNK, pfp = (KA_T)p->p_ofilep;
+ i < p->p_maxof;
+ i++)
+#else /* HPUXV<800 */
+ for (i = j = k = 0;; i++)
+#endif /* HPUXV>=800 */
+
+ {
+
+#if HPUXV>=800
+ if (j >= SFDCHUNK) {
+ if (!pfp || kread((KA_T)pfp, (char *)&ofp, sizeof(ofp))
+ || !ofp || kread((KA_T)ofp, oftp, oftsz))
+ break;
+ j = 0;
+ pfp += sizeof(KA_T);
+
+# if HPUXV>=1020
+ ofap = (struct ofa *)oftp;
+# endif /* HPUXV>=1020 */
+
+ }
+ j++;
+
+# if HPUXV>=1020
+# if defined(USESPOFILE)
+ pof = (long)ofap->pofile;
+# endif /* defined(USESPOFILE) */
+
+ fp = (KA_T)ofap->ofile;
+ ofap = (struct ofa *)((char *)ofap + ofasz);
+ if (fp)
+# else /* HPUXV<1020 */
+# if defined(USESPOFILE)
+ pof = (long)oft.pofile[j - 1];
+# endif /* defined(USESPOFILE) */
+
+ if ((fp = (KA_T)oft.ofile[j - 1]))
+# endif /* HPUXV>=1020 */
+#else /* HPUXV<800 */
+ if (j >= SFDCHUNK) {
+
+ /*
+ * Get next file pointer "chunk".
+ */
+ while (++k < NFDCHUNKS && !u->u_ofilep[k])
+ ;
+ if (k >= NFDCHUNKS)
+ break;
+ if (kread((KA_T)u->u_ofilep[k], (char *)&u->u_ofile,
+ sizeof(struct ofile_t)))
+ {
+ break;
+ }
+ j = 0;
+ }
+ j++;
+ if ((fp = (KA_T)u->u_ofile.ofile[j - 1]))
+#endif /* HPUXV>=800 */
+
+ /*
+ * Process the file pointer.
+ */
+
+ {
+ alloc_lfile(NULL, i);
+ process_file(fp);
+ if (Lf->sf) {
+
+#if defined(USESPOFILE)
+ if (Fsv & FSV_FG)
+ Lf->pof = pof;
+#endif /* defined(USESPOFILE) */
+
+ link_lfile();
+ }
+ }
+ }
+ /*
+ * Examine results.
+ */
+ if (examine_lproc())
+ return;
+ }
+}
+
+
+/*
+ * get_kernel_access() - access the required information in the kernel
+ */
+
+static void
+get_kernel_access()
+{
+ KA_T v;
+/*
+ * Check the kernel version.
+ */
+ (void) ckkv("HP-UX", LSOF_VSTR, (char *)NULL, (char *)NULL);
+
+#if HPUXV>=1030
+/*
+ * See if build and run bit sizes match. Exit if they don't.
+ */
+ {
+ long rv;
+
+ if ((rv = sysconf(_SC_KERNEL_BITS)) < 0) {
+ (void) fprintf(stderr,
+ "%s: sysconf(_SC_KERNEL_BITS) returns: %s\n",
+ Pn, strerror(errno));
+ Exit(1);
+ }
+ if (rv != (long)HPUXKERNBITS) {
+ (void) fprintf(stderr,
+ "%s: FATAL: %s was built for a %d bit kernel, but this\n",
+ Pn, Pn, HPUXKERNBITS);
+ (void) fprintf(stderr, " is a %ld bit kernel.\n", rv);
+ Exit(1);
+ }
+ }
+#endif /* HPUXV>=1030 */
+
+#if defined(HAS_AFS)
+ struct NLIST_TYPE *nl = (struct NLIST_TYPE *)NULL;
+#endif /* defined(HAS_AFS) */
+
+#if HPUXV<800
+/*
+ * Open access to /dev/mem and SWAP.
+ */
+ if ((Mem = open("/dev/mem", O_RDONLY, 0)) < 0) {
+ (void) fprintf(stderr, "%s: can't open /dev/mem: %s\n",
+ Pn, strerror(errno));
+ err = 1;
+ }
+ if (!Memory || strcmp(Memory, KMEM) == 0) {
+ if ((Swap = open(SWAP, O_RDONLY, 0)) < 0) {
+ (void) fprintf(stderr, "%s: %s: %s\n",
+ Pn, SWAP, strerror(errno));
+ err = 1;
+ }
+ }
+#endif /* HPUXV<800 */
+
+#if defined(WILLDROPGID)
+/*
+ * If kernel memory isn't coming from KMEM, drop setgid permission
+ * before attempting to open the (Memory) file.
+ */
+ if (Memory)
+ (void) dropgid();
+#else /* !defined(WILLDROPGID) */
+/*
+ * See if the non-KMEM memory file is readable.
+ */
+ if (Memory && !is_readable(Memory, 1))
+ Exit(1);
+#endif /* defined(WILLDROPGID) */
+
+/*
+ * Open kernel memory access.
+ */
+ if ((Kd = open(Memory ? Memory : KMEM, O_RDONLY, 0)) < 0) {
+ int errno_save = errno;
+
+ (void) fprintf(stderr, "%s: can't open ", Pn);
+ safestrprt(Memory ? Memory : KMEM, stderr, 0);
+ (void) fprintf(stderr, ": %s\n", strerror(errno_save));
+ Exit(1);
+ }
+
+#if defined(WILLDROPGID)
+/*
+ * Drop setgid permission, if necessary.
+ */
+ if (!Memory)
+ (void) dropgid();
+#else /* !defined(WILLDROPGID) */
+/*
+ * See if the name list file is readable.
+ */
+ if (Nmlst && !is_readable(Nmlst, 1))
+ Exit(1);
+#endif /* defined(WILLDROPGID) */
+
+ (void) build_Nl(Drive_Nl);
+
+#if defined(HAS_AFS)
+ if (!Nmlst) {
+
+ /*
+ * If AFS is defined and we're getting kernel symbol values from
+ * from N_UNIX, make a copy of Nl[] for possible use with the AFS
+ * module name list file.
+ */
+ if (!(nl = (struct NLIST_TYPE *)malloc(Nll))) {
+ (void) fprintf(stderr,
+ "%s: no space (%d) for Nl[] copy\n", Pn, Nll);
+ Exit(1);
+ }
+ (void) memcpy((void *)nl, (void *)Nl, (size_t)Nll);
+ }
+#endif /* defined(HAS_AFS) */
+
+/*
+ * Access kernel symbols.
+ */
+ if (NLIST_TYPE(Nmlst ? Nmlst : N_UNIX, Nl) < 0) {
+ (void) fprintf(stderr, "%s: can't read namelist from: ", Pn);
+ safestrprt(Nmlst ? Nmlst : N_UNIX, stderr, 1);
+ Exit(1);
+ }
+ if (get_Nl_value("proc", Drive_Nl, &v) < 0 || !v
+ || kread((KA_T)v, (char *)&Kp, sizeof(Kp))
+ || get_Nl_value("nproc", Drive_Nl, &v) < 0 || !v
+ || kread((KA_T)v, (char *)&Np, sizeof(Np))
+ || !Kp || Np < 1) {
+ (void) fprintf(stderr, "%s: can't read proc table info\n", Pn);
+ Exit(1);
+ }
+ if (get_Nl_value("vfops", Drive_Nl, (KA_T *)&Vnfops) < 0)
+ Vnfops = (KA_T)NULL;
+
+#if HPUXV<800 && defined(hp9000s300)
+ if (get_Nl_value("upmap", Drive_Nl, (unsigned long *)&Usrptmap) < 0) {
+ (void) fprintf(stderr, "%s: can't get kernel's Usrptmap\n", Pn);
+ Exit(1);
+ }
+ if (get_Nl_value("upt", Drive_Nl, (unsigned long *)&usrpt) < 0) {
+ (void) fprintf(stderr, "%s: can't get kernel's usrpt\n", Pn);
+ Exit(1);
+ }
+#endif /* HPUXV<800 && defined(hp9000s300) */
+
+#if HPUXV<800 && defined(hp9000s800)
+ proc = (struct proc *)Kp;
+ if (get_Nl_value("ubase", Drive_Nl, (unsigned long *)&ubase) < 0) {
+ (void) fprintf(stderr, "%s: can't get kernel's ubase\n", Pn);
+ Exit(1);
+ }
+ if (get_Nl_value("npids", Drive_Nl, &v) < 0 || !v
+ || kread((KA_T)v, (char *)&npids, sizeof(npids))) {
+ (void) fprintf(stderr, "%s: can't get kernel's npids\n", Pn);
+ Exit(1);
+ }
+#endif /* HPUXV<800 && defined(hp9000s800) */
+
+#if HPUXV>=1030
+ if (get_Nl_value("clmaj", Drive_Nl, &v) < 0 || !v
+ || kread((KA_T)v, (char *)&CloneMaj, sizeof(CloneMaj)))
+ HaveCloneMaj = 0;
+ else
+ HaveCloneMaj = 1;
+#endif /* HPUXV>=1030 */
+
+#if defined(HAS_AFS)
+ if (nl) {
+
+ /*
+ * If AFS is defined and we're getting kernel symbol values from
+ * N_UNIX, and if any X_AFS_* symbols isn't there, see if it is in the
+ * the AFS module name list file. Make sure that other symbols that
+ * appear in both name list files have the same values.
+ */
+ if ((get_Nl_value("arFid", Drive_Nl, &v) >= 0 && !v)
+ || (get_Nl_value("avops", Drive_Nl, &v) >= 0 && !v)
+ || (get_Nl_value("avol", Drive_Nl, &v) >= 0 && !v))
+ (void) ckAFSsym(nl);
+ (void) free((FREE_P *)nl);
+ }
+#endif /* defined(HAS_AFS) */
+
+}
+
+
+/*
+ * initialize() - perform all initialization
+ */
+
+void
+initialize()
+{
+ get_kernel_access();
+}
+
+
+/*
+ * kread() - read from kernel memory
+ */
+
+int
+kread(addr, buf, len)
+ KA_T addr; /* kernel memory address */
+ char *buf; /* buffer to receive data */
+ READLEN_T len; /* length to read */
+{
+ int br;
+
+ if (lseek(Kd, (off_t)addr, L_SET) == (off_t)-1L)
+ return(-1);
+ br = read(Kd, buf, len);
+ return((br == len) ? 0 : 1);
+}
+
+
+#if HPUXV<800
+/*
+ * mread() -- read from /dev/mem
+ */
+
+static int
+mread(addr, buf, len)
+ KA_T addr; /* /dev/mem address */
+ char *buf; /* buffer to receive data */
+ READLEN_T len; /* length to read */
+{
+ int br;
+
+ if (lseek(Mem, addr, L_SET) == (off_t)-1L)
+ return(1);
+ br = read(Mem, buf, len);
+ return((br == len) ? 0 : 1);
+}
+#endif /* HPUXV<800 */
+
+
+#if HPUXV>=800
+/*
+ * process_text() - process text access information
+ */
+
+static void
+process_text(vasp)
+ KA_T vasp; /* kernel's virtual address space
+ * pointer */
+{
+ char fd[FDLEN];
+ int i, j, lm;
+ MALLOC_S len;
+ struct pregion p;
+ KA_T prp;
+ struct region r;
+ struct vas v;
+ KA_T va;
+/*
+ * Read virtual address space pointer.
+ */
+ if (kread(vasp, (char *)&v, sizeof(v)))
+ return;
+/*
+ * Follow the virtual address space pregion structure chain.
+ */
+ for (i = lm = 0, prp = (KA_T)v.va_next;
+ prp != vasp;
+ prp = (KA_T)p.p_next, lm++)
+ {
+
+ /*
+ * Avoid infinite loop.
+ */
+ if (lm > 1000) {
+ if (!Fwarn)
+ (void) fprintf(stderr,
+ "%s: too many virtual address regions for PID %d\n",
+ Pn, Lp->pid);
+ return;
+ }
+ /*
+ * Read the pregion and region.
+ */
+ if (kread(prp, (char *)&p, sizeof(p)))
+ return;
+ if (kread((KA_T)p.p_reg, (char *)&r, sizeof(r)))
+ return;
+ /*
+ * Skip file entries with no file pointers.
+ */
+ if (!(va = (KA_T)r.r_fstore))
+ continue;
+ /*
+ * Skip entries whose vnodes have already been displayed.
+ *
+ * Record new, unique vnode pointers.
+ */
+ for (j = 0; j < i; j++) {
+ if (Vp[j] == va)
+ break;
+ }
+ if (j < i)
+ continue;
+ if (i >= Nva) {
+ Nva += 10;
+ len = (MALLOC_S)(Nva * sizeof(KA_T));
+ if (!Vp)
+ Vp = (KA_T *)malloc(len);
+ else
+ Vp = (KA_T *)realloc((MALLOC_P *)Vp, len);
+ if (!Vp) {
+ (void) fprintf(stderr,
+ "%s: no more space for text vnode pointers\n", Pn);
+ Exit(1);
+ }
+ }
+ Vp[i++] = va;
+ /*
+ * Allocate local file structure.
+ */
+ switch (p.p_type) {
+ case PT_DATA:
+ case PT_TEXT:
+ alloc_lfile(" txt", -1);
+ break;
+ case PT_MMAP:
+ alloc_lfile(" mem", -1);
+ break;
+ default:
+ (void) snpf(fd, sizeof(fd), "R%02d", p.p_type);
+ alloc_lfile(fd, -1);
+ }
+ /*
+ * Save vnode information.
+ */
+ process_node(va);
+ if (Lf->sf)
+ link_lfile();
+ }
+}
+#endif /* HPUXV>=800 */
diff --git a/dialects/hpux/kmem/dproto.h b/dialects/hpux/kmem/dproto.h
new file mode 100644
index 0000000..097ea23
--- /dev/null
+++ b/dialects/hpux/kmem/dproto.h
@@ -0,0 +1,69 @@
+/*
+ * dproto.h - /dev/kmem-based HP-UX function prototypes for lsof
+ *
+ * The _PROTOTYPE macro is defined in the common proto.h.
+ */
+
+
+/*
+ * Copyright 1994 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.
+ */
+
+
+/*
+ * $Id: dproto.h,v 1.7 2000/12/04 14:26:14 abe Exp $
+ */
+
+
+#if HPUXV>=800
+_PROTOTYPE(extern void completevfs,(struct l_vfs *vfs, dev_t *dev, struct vfs *v));
+#else
+_PROTOTYPE(extern void completevfs,(struct l_vfs *vfs, dev_t *dev));
+#endif /* HPUXV>=800 */
+
+_PROTOTYPE(extern int is_file_named,(char *p, int cd));
+_PROTOTYPE(extern int get_max_fd,(void));
+
+#if defined(DTYPE_LLA)
+_PROTOTYPE(extern void process_lla,(KA_T la));
+#endif
+
+_PROTOTYPE(extern struct l_vfs *readvfs,(struct vnode *lv));
+
+#if HPUXV>=1030
+_PROTOTYPE(extern void process_stream_sock,(KA_T ip, KA_T pcb, char *pn, enum vtype vt));
+_PROTOTYPE(extern int read_mi,(KA_T sh, KA_T *ip, KA_T *pcb, char **pn));
+#endif /* HPUXV>=1030 */
+
+#if defined(HAS_AFS)
+_PROTOTYPE(extern struct vnode *alloc_vcache,(void));
+_PROTOTYPE(extern void ckAFSsym,(struct nlist *nl));
+_PROTOTYPE(extern int hasAFS,(struct vnode *vp));
+_PROTOTYPE(extern int readafsnode,(KA_T va, struct vnode *v, struct afsnode *an));
+#endif /* defined(HAS_AFS) */
+
+#if defined(HASVXFS)
+_PROTOTYPE(extern int read_vxnode,(struct vnode *v, struct l_vfs *vfs, dev_t *dev, int *devs, dev_t *rdev, int *rdevs));
+#endif /* defined(HASVXFS) */
diff --git a/dialects/hpux/kmem/dsock.c b/dialects/hpux/kmem/dsock.c
new file mode 100644
index 0000000..fc54f83
--- /dev/null
+++ b/dialects/hpux/kmem/dsock.c
@@ -0,0 +1,1170 @@
+/*
+ * dsock.c - /dev/kmem-based HP-UX socket processing functions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dsock.c,v 1.20 2005/08/08 19:50:23 abe Exp $";
+#endif
+
+#if defined(HPUXKERNBITS) && HPUXKERNBITS>=64
+#define _INO_T
+typedef int ino_t;
+#define _TIME_T
+typedef int time_t;
+#endif /* defined(HPUXKERNBITS) && HPUXKERNBITS>=64 */
+
+#include "lsof.h"
+
+#if HPUXV>=800 && defined(HPUX_CCITT)
+#include <x25/x25addrstr.h>
+#include <x25/x25stat.h>
+#include <x25/x25str.h>
+#include <x25/x25config.h>
+#include <x25/x25L3.h>
+#endif /* HPUXV>=800 && defined(HPUX_CCITT) */
+
+
+/*
+ * Local definitions
+ */
+
+#if defined(HASTCPOPT)
+#define TF_NODELAY 0x1 /* TCP_NODELAY (Nagle algorithm) */
+#endif /* defined(HASTCPOPT) */
+
+
+#if HPUXV>=1030
+/*
+ * print_tcptpi() - print TCP/TPI info
+ */
+
+void
+print_tcptpi(nl)
+ int nl; /* 1 == '\n' required */
+{
+ char *cp = (char *)NULL;
+ char sbuf[128];
+ int i, t;
+ int ps = 0;
+ unsigned int u;
+
+ if (Ftcptpi & TCPTPI_STATE) {
+ switch ((t = Lf->lts.type)) {
+ case 0: /* TCP */
+ switch ((i = Lf->lts.state.i)) {
+ case TCPS_CLOSED:
+ cp = "CLOSED";
+ break;
+ case TCPS_IDLE:
+ cp = "IDLE";
+ break;
+ case TCPS_BOUND:
+ cp = "BOUND";
+ break;
+ case TCPS_LISTEN:
+ cp = "LISTEN";
+ break;
+ case TCPS_SYN_SENT:
+ cp = "SYN_SENT";
+ break;
+ case TCPS_SYN_RCVD:
+ cp = "SYN_RCVD";
+ break;
+ case TCPS_ESTABLISHED:
+ cp = "ESTABLISHED";
+ break;
+ case TCPS_CLOSE_WAIT:
+ cp = "CLOSE_WAIT";
+ break;
+ case TCPS_FIN_WAIT_1:
+ cp = "FIN_WAIT_1";
+ break;
+ case TCPS_CLOSING:
+ cp = "CLOSING";
+ break;
+ case TCPS_LAST_ACK:
+ cp = "LAST_ACK";
+ break;
+ case TCPS_FIN_WAIT_2:
+ cp = "FIN_WAIT_2";
+ break;
+ case TCPS_TIME_WAIT:
+ cp = "TIME_WAIT";
+ break;
+ default:
+ (void) snpf(sbuf, sizeof(sbuf), "UknownState_%d", i);
+ cp = sbuf;
+ }
+ break;
+ case 1: /* TPI */
+ switch ((u = Lf->lts.state.ui)) {
+ case TS_UNINIT:
+ cp = "Uninitialized";
+ break;
+ case TS_UNBND:
+ cp = "Unbound";
+ break;
+ case TS_WACK_BREQ:
+ cp = "Wait_BIND_REQ_Ack";
+ break;
+ case TS_WACK_UREQ:
+ cp = "Wait_UNBIND_REQ_Ack";
+ break;
+ case TS_IDLE:
+ cp = "Idle";
+ break;
+ case TS_WACK_OPTREQ:
+ cp = "Wait_OPT_REQ_Ack";
+ break;
+ case TS_WACK_CREQ:
+ cp = "Wait_CONN_REQ_Ack";
+ break;
+ case TS_WCON_CREQ:
+ cp = "Wait_CONN_REQ_Confirm";
+ break;
+ case TS_WRES_CIND:
+ cp = "Wait_CONN_IND_Response";
+ break;
+ case TS_WACK_CRES:
+ cp = "Wait_CONN_RES_Ack";
+ break;
+ case TS_DATA_XFER:
+ cp = "Wait_Data_Xfr";
+ break;
+ case TS_WIND_ORDREL:
+ cp = "Wait_Read_Release";
+ break;
+ case TS_WREQ_ORDREL:
+ cp = "Wait_Write_Release";
+ break;
+ case TS_WACK_DREQ6:
+ case TS_WACK_DREQ7:
+ case TS_WACK_DREQ9:
+ case TS_WACK_DREQ10:
+ case TS_WACK_DREQ11:
+ cp = "Wait_DISCON_REQ_Ack";
+ break;
+ case TS_WACK_ORDREL:
+ cp = "Internal";
+ break;
+ default:
+ (void) snpf(sbuf, sizeof(sbuf), "UNKNOWN_TPI_STATE_%u", u);
+ cp = sbuf;
+ }
+ }
+ if (Ffield)
+ (void) printf("%cST=%s%c", LSOF_FID_TCPTPI, cp, Terminator);
+ else {
+ putchar('(');
+ (void) fputs(cp, stdout);
+ }
+ ps++;
+ }
+
+# if defined(HASTCPTPIQ)
+ if (Ftcptpi & TCPTPI_QUEUES) {
+ if (Lf->lts.rqs) {
+ if (Ffield)
+ putchar(LSOF_FID_TCPTPI);
+ else {
+ if (ps)
+ putchar(' ');
+ else
+ putchar('(');
+ }
+ (void) printf("QR=%lu", Lf->lts.rq);
+ if (Ffield)
+ putchar(Terminator);
+ ps++;
+ }
+ if (Lf->lts.sqs) {
+ if (Ffield)
+ putchar(LSOF_FID_TCPTPI);
+ else {
+ if (ps)
+ putchar(' ');
+ else
+ putchar('(');
+ }
+ (void) printf("QS=%lu", Lf->lts.sq);
+ if (Ffield)
+ putchar(Terminator);
+ ps++;
+ }
+ }
+# endif /* defined(HASTCPTPIQ) */
+
+#if defined(HASSOOPT)
+ if (Ftcptpi & TCPTPI_FLAGS) {
+ int opt;
+
+ if ((opt = Lf->lts.opt)
+ || Lf->lts.qlens || Lf->lts.qlims || Lf->lts.rbszs || Lf->lts.sbsz
+ ) {
+ char sep = ' ';
+
+ if (Ffield)
+ sep = LSOF_FID_TCPTPI;
+ else if (!ps)
+ sep = '(';
+ (void) printf("%cSO", sep);
+ ps++;
+ sep = '=';
+
+# if defined(SO_BROADCAST)
+ if (opt & SO_BROADCAST) {
+ (void) printf("%cBROADCAST", sep);
+ opt &= ~SO_BROADCAST;
+ sep = ',';
+ }
+# endif /* defined(SO_BROADCAST) */
+
+# if defined(SO_DEBUG)
+ if (opt & SO_DEBUG) {
+ (void) printf("%cDEBUG", sep);
+ opt &= ~ SO_DEBUG;
+ sep = ',';
+ }
+# endif /* defined(SO_DEBUG) */
+
+# if defined(SO_DONTROUTE)
+ if (opt & SO_DONTROUTE) {
+ (void) printf("%cDONTROUTE", sep);
+ opt &= ~SO_DONTROUTE;
+ sep = ',';
+ }
+# endif /* defined(SO_DONTROUTE) */
+
+# if defined(SO_KEEPALIVE)
+ if (opt & SO_KEEPALIVE) {
+ (void) printf("%cKEEPALIVE", sep);
+ if (Lf->lts.kai)
+ (void) printf("=%d", Lf->lts.kai);
+ opt &= ~SO_KEEPALIVE;
+ sep = ',';
+ }
+# endif /* defined(SO_KEEPALIVE) */
+
+# if defined(SO_LINGER)
+ if (opt & SO_LINGER) {
+ (void) printf("%cLINGER", sep);
+ if (Lf->lts.ltm)
+ (void) printf("=%d", Lf->lts.ltm);
+ opt &= ~SO_LINGER;
+ sep = ',';
+ }
+# endif /* defined(SO_LINGER) */
+
+# if defined(SO_OOBINLINE)
+ if (opt & SO_OOBINLINE) {
+ (void) printf("%cOOBINLINE", sep);
+ opt &= ~SO_OOBINLINE;
+ sep = ',';
+ }
+# endif /* defined(SO_OOBINLINE) */
+
+ if (Lf->lts.qlens) {
+ (void) printf("%cQLEN=%u", sep, Lf->lts.qlen);
+ sep = ',';
+ }
+ if (Lf->lts.qlims) {
+ (void) printf("%cQLIM=%u", sep, Lf->lts.qlim);
+ sep = ',';
+ }
+
+# if defined(SO_REUSEADDR)
+ if (opt & SO_REUSEADDR) {
+ (void) printf("%cREUSEADDR", sep);
+ opt &= ~SO_REUSEADDR;
+ sep = ',';
+ }
+# endif /* defined(SO_REUSEADDR) */
+
+# if defined(SO_REUSEPORT)
+ if (opt & SO_REUSEPORT) {
+ (void) printf("%cREUSEPORT", sep);
+ opt &= ~SO_REUSEPORT;
+ sep = ',';
+ }
+# endif /* defined(SO_REUSEPORT) */
+
+# if defined(SO_USELOOPBACK)
+ if (opt & SO_USELOOPBACK) {
+ (void) printf("%cUSELOOPBACK", sep);
+ opt &= ~SO_USELOOPBACK;
+ sep = ',';
+ }
+# endif /* defined(SO_USELOOPBACK) */
+
+ if (opt)
+ (void) printf("%cUNKNOWN=%#x", sep, opt);
+ if (Ffield)
+ putchar(Terminator);
+ }
+ }
+#endif /* defined(HASSOOPT) */
+
+#if defined(HASTCPOPT)
+ if (Ftcptpi & TCPTPI_FLAGS) {
+ int topt;
+
+ if ((topt = Lf->lts.topt) || Lf->lts.msss) {
+ char sep = ' ';
+
+ if (Ffield)
+ sep = LSOF_FID_TCPTPI;
+ else if (!ps)
+ sep = '(';
+ (void) printf("%cTF", sep);
+ ps++;
+ sep = '=';
+
+ if (Lf->lts.msss) {
+ (void) printf("%cMSS=%lu", sep, Lf->lts.mss);
+ sep = ',';
+ }
+
+# if defined(TF_NODELAY)
+ if (topt & TF_NODELAY) {
+ (void) printf("%cNODELAY", sep);
+ topt &= ~TF_NODELAY;
+ sep = ',';
+ }
+# endif /* defined(TF_NODELAY) */
+
+ if (topt)
+ (void) printf("%cUNKNOWN=%#x", sep, topt);
+ if (Ffield)
+ putchar(Terminator);
+ }
+ }
+# endif /* defined(HASTCPOPT) */
+
+# if defined(HASTCPTPIW)
+ if (Ftcptpi & TCPTPI_WINDOWS) {
+ if (Lf->lts.rws) {
+ if (Ffield)
+ putchar(LSOF_FID_TCPTPI);
+ else {
+ if (ps)
+ putchar(' ');
+ else
+ putchar('(');
+ }
+ (void) printf("WR=%lu", Lf->lts.rw);
+ if (Ffield)
+ putchar(Terminator);
+ ps++;
+ }
+ if (Lf->lts.wws) {
+ if (Ffield)
+ putchar(LSOF_FID_TCPTPI);
+ else {
+ if (ps)
+ putchar(' ');
+ else
+ putchar('(');
+ }
+ (void) printf("WW=%lu", Lf->lts.ww);
+ if (Ffield)
+ putchar(Terminator);
+ ps++;
+ }
+ }
+# endif /* defined(HASTCPTPIW) */
+
+ if (Ftcptpi && !Ffield && ps)
+ putchar(')');
+ if (nl)
+ putchar('\n');
+}
+#endif /* HPUXV>=1030 */
+
+
+#if defined(DTYPE_LLA)
+/*
+ * process_lla() - process link level access socket file
+ */
+
+void
+process_lla(la)
+ KA_T la; /* link level CB address in kernel */
+{
+ char *ep;
+ struct lla_cb lcb;
+ size_t sz;
+
+ (void) snpf(Lf->type, sizeof(Lf->type), "lla");
+ Lf->inp_ty = 2;
+ enter_dev_ch(print_kptr(la, (char *)NULL, 0));
+/*
+ * Read link level access control block.
+ */
+ if (!la || kread((KA_T)la, (char *)&lcb, sizeof(lcb))) {
+ (void) snpf(Namech, Namechl, "can't read LLA CB (%s)",
+ print_kptr(la, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+/*
+ * Determine access mode.
+ */
+ if ((lcb.lla_flags & LLA_FWRITE | LLA_FREAD) == LLA_FWRITE)
+ Lf->access = 'w';
+ else if ((lcb.lla_flags & LLA_FWRITE | LLA_FREAD) == LLA_FREAD)
+ Lf->access = 'r';
+ else if (lcb.lla_flags & LLA_FWRITE | LLA_FREAD)
+ Lf->access = 'u';
+/*
+ * Determine the open mode, if possible.
+ */
+ if (lcb.lla_flags & LLA_IS_ETHER)
+ (void) snpf(Lf->iproto, sizeof(Lf->iproto), "Ether");
+ else if (lcb.lla_flags & (LLA_IS_8025|LLA_IS_SNAP8025|LLA_IS_FA8025)) {
+ (void) snpf(Lf->iproto, sizeof(Lf->iproto), "802.5");
+ if (lcb.lla_flags & LLA_IS_SNAP8025)
+ (void) snpf(Namech, Namechl, "SNAP");
+ else if (lcb.lla_flags & LLA_IS_FA8025)
+ (void) snpf(Namech, Namechl, "function address");
+ }
+/*
+ * Add any significant flags.
+ */
+ if (lcb.lla_flags & ~(LLA_FWRITE | LLA_FREAD)) {
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "%s(flags = %#x)",
+ (ep == Namech) ? "" : " ",
+ lcb.lla_flags);
+ }
+ if (Namech[0])
+ enter_nm(Namech);
+}
+#endif /* DTYPE_LLA */
+
+
+/*
+ * process_socket() - process socket
+ */
+
+void
+process_socket(sa)
+ KA_T sa; /* socket address in kernel */
+{
+ unsigned char *fa = (unsigned char *)NULL;
+ char *ep, tbuf[32];
+ int fam;
+ int fp, mbl, lp;
+ unsigned char *la = (unsigned char *)NULL;
+ struct protosw p;
+ struct socket s;
+ size_t sz;
+ struct unpcb uc, unp;
+ struct sockaddr_un *ua = (struct sockaddr_un *)NULL;
+ struct sockaddr_un un;
+
+#if HPUXV>=800
+ struct domain d;
+
+# if defined(HPUX_CCITT)
+ int i;
+ struct x25pcb xp;
+ struct x25pcb_extension xpe;
+# endif /* defined(HPUX_CCITT) */
+
+# if HPUXV<1030
+ struct mbuf mb;
+ struct inpcb inp;
+ struct rawcb raw;
+ struct tcpcb t;
+# else /* HPUXV>=1030 */
+ struct datab db;
+ static char *dbf = (char *)NULL;
+ static int dbl = 0;
+ struct msgb mb;
+ struct sockbuf rb, sb;
+# endif /* HPUXV<1030 */
+#endif /* HPUXV>=800 */
+
+ (void) snpf(Lf->type, sizeof(Lf->type), "sock");
+ Lf->inp_ty = 2;
+/*
+ * Read socket structure.
+ */
+ if (!sa) {
+ enter_nm("no socket address");
+ return;
+ }
+ if (kread((KA_T) sa, (char *) &s, sizeof(s))) {
+ (void) snpf(Namech, Namechl, "can't read socket struct from %s",
+ print_kptr(sa, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+/*
+ * Read protocol switch and domain structure (HP-UX 8 and above).
+ */
+ if (!s.so_type) {
+ (void) snpf(Namech, Namechl, "no socket type");
+ enter_nm(Namech);
+ return;
+ }
+ if (!s.so_proto
+ || kread((KA_T) s.so_proto, (char *) &p, sizeof(p))) {
+ (void) snpf(Namech, Namechl, "no protocol switch");
+ enter_nm(Namech);
+ return;
+ }
+
+#if HPUXV>=800
+ if (kread((KA_T) p.pr_domain, (char *) &d, sizeof(d))) {
+ (void) snpf(Namech, Namechl, "can't read domain struct from %s",
+ print_kptr((KA_T)p.pr_domain, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+#endif /* HPUXV>=800 */
+
+#if HPUXV<1030
+/*
+ * Save size information for HP-UX < 10.30.
+ */
+ if (Fsize) {
+ if (Lf->access == 'r')
+ Lf->sz = (SZOFFTYPE)s.so_rcv.sb_cc;
+ else if (Lf->access == 'w')
+ Lf->sz = (SZOFFTYPE)s.so_snd.sb_cc;
+ else
+ Lf->sz = (SZOFFTYPE)(s.so_rcv.sb_cc + s.so_snd.sb_cc);
+ Lf->sz_def = 1;
+ } else
+ Lf->off_def = 1;
+
+# if defined(HASTCPTPIQ)
+ Lf->lts.rq = s.so_rcv.sb_cc;
+ Lf->lts.sq = s.so_snd.sb_cc;
+ Lf->lts.rqs = Lf->lts.sqs = 1;
+# endif /* defined(HASTCPTPIQ) */
+#endif /* HPUXV<1030 */
+
+/*
+ * Process socket by the associated domain family.
+ */
+
+#if HPUXV>=800
+ switch ((fam = d.dom_family))
+#else /* HPUXV<800 */
+ switch ((fam = p.pr_family))
+#endif /* HPUXV>=800 */
+
+ {
+
+#if HPUXV>=800 && HPUXV<1030 && defined(HPUX_CCITT)
+/*
+ * Process an HP-UX [89].x CCITT X25 domain socket.
+ */
+ case AF_CCITT:
+ if (Fnet)
+ Lf->sf |= SELNET;
+ (void) snpf(Lf->type, sizeof(Lf->type), "x.25");
+ (void) snpf(Lf->iproto, sizeof(Lf->iproto), "%.*s", IPROTOL,
+ "CCITT");
+ /*
+ * Get the X25 PCB and its extension.
+ */
+ if (!s.so_pcb
+ || kread((KA_T)s.so_pcb, (char *)&xp, sizeof(xp))) {
+ (void) snpf(Namech, Namechl, "can't read x.25 pcb at %s",
+ print_kptr((KA_T)s.so_pcb, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ enter_dev_ch(print_kptr((KA_T)s.so_pcb, (char *)NULL, 0));
+ if (!xp.x25pcb_extend
+ || kread((KA_T)xp.x25pcb_extend, (char *)&xpe, sizeof(xpe))) {
+ (void) snpf(Namech, Namechl,
+ "can't read x.25 pcb (%s) extension at %s",
+ print_kptr((KA_T)s.so_pcb, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)xp.x25pcb_extend, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ /*
+ * Format local address.
+ */
+ for (i = 0; i < xpe.x25pcbx_local_addr.x25hostlen/2; i++) {
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "%02x", xpe.x25pcbx_local_addr.x25_host[i]);
+ }
+ if (i*2 != xpe.x25pcbx_local_addr.x25hostlen) {
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "%01x",
+ xpe.x25pcbx_local_addr.x25_host[i] >> 4);
+ }
+ /*
+ * Display the virtual connection number, if it's defined.
+ */
+ if (xp.x25pcb_vcn >= 0) {
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, ":%d", xp.x25pcb_vcn + 1);
+ }
+ /*
+ * Format peer address, if there is one.
+ */
+ if (xpe.x25pcbx_peer_addr.x25hostlen > 0) {
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "->");
+ for (i = 0; i < xpe.x25pcbx_peer_addr.x25hostlen/2; i++) {
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "%02x",
+ xpe.x25pcbx_peer_addr.x25_host[i]);
+ }
+ if (i*2 != xpe.x25pcbx_peer_addr.x25hostlen) {
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "%01x",
+ xpe.x25pcbx_peer_addr.x25_host[i] >> 4);
+ }
+ }
+ enter_nm(Namech);
+ break;
+#endif /* HPUXV>=800 && HPUXV<1030 && defined(HPUX_CCITT) */
+
+/*
+ * Process an Internet domain socket.
+ */
+ case AF_INET:
+ if (Fnet)
+ Lf->sf |= SELNET;
+ (void) snpf(Lf->type, sizeof(Lf->type), "inet");
+ printiproto(p.pr_protocol);
+
+#if HPUXV>=1030
+ /*
+ * Handle HP-UX 10.30 and above socket streams.
+ */
+ if (s.so_sth) {
+
+ KA_T ip, pcb;
+ char *pn = (char *)NULL;
+ /*
+ * Read module information.
+ */
+ if (read_mi((KA_T)s.so_sth, &ip, &pcb, &pn))
+ return;
+ if (ip && pcb) {
+
+ /*
+ * If IP and TCP or UDP modules are present, process as a
+ * stream socket.
+ */
+ process_stream_sock(ip, pcb, pn, VNON);
+ return;
+ }
+ /*
+ * If an IP module's PCB address is present, print it as the
+ * device characters.
+ */
+
+ if (ip && !Lf->dev_def)
+ enter_dev_ch(print_kptr(ip, (char *)NULL, 0));
+ if (!strlen(Namech)) {
+
+ /*
+ * If there are no NAME field characters, enter an error
+ * message.
+ */
+ if (!ip) {
+ (void) snpf(Namech, Namechl,
+ "no IP module for stream socket");
+ } else {
+ (void) snpf(Namech, Namechl,
+ "no TCP/UDP module for stream socket");
+ }
+ }
+ enter_nm(Namech);
+ return;
+ }
+#else /* HPUXV<1030 */
+
+ /*
+ * Read protocol control block.
+ */
+ if (!s.so_pcb) {
+ enter_nm("no protocol control block");
+ return;
+ }
+ if (s.so_type == SOCK_RAW) {
+
+ /*
+ * Print raw socket information.
+ */
+ if (kread((KA_T)s.so_pcb, (char *)&raw, sizeof(raw))
+ || (struct socket *)sa != (struct socket *)raw.rcb_socket) {
+ (void) snpf(Namech, Namechl, "can't read rawcb at %s",
+ print_kptr((KA_T)s.so_pcb, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ enter_dev_ch(print_kptr((KA_T)(raw.rcb_pcb ? raw.rcb_pcb
+ : s.so_pcb),
+ (char *)NULL, 0));
+ if (raw.rcb_laddr.sa_family == AF_INET)
+ la = (unsigned char *)&raw.rcb_laddr.sa_data[2];
+ else if (raw.rcb_laddr.sa_family)
+ printrawaddr(&raw.rcb_laddr);
+ if (raw.rcb_faddr.sa_family == AF_INET)
+ fa = (unsigned char *)&raw.rcb_faddr.sa_data[2];
+ else if (raw.rcb_faddr.sa_family) {
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "->");
+ printrawaddr(&raw.rcb_faddr);
+ }
+ if (fa || la)
+ (void) ent_inaddr(la, -1, fa, -1, AF_INET);
+ } else {
+
+ /*
+ * Print Internet socket information.
+ */
+ if (kread((KA_T)s.so_pcb, (char *)&inp, sizeof(inp))) {
+ (void) snpf(Namech, Namechl, "can't read inpcb at %s",
+ print_kptr((KA_T)s.so_pcb, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ enter_dev_ch(print_kptr((KA_T)(inp.inp_ppcb ? inp.inp_ppcb
+ : s.so_pcb),
+ (char *)NULL, 0));
+ la = (unsigned char *)&inp.inp_laddr;
+ lp = (int)ntohs(inp.inp_lport);
+ if (inp.inp_faddr.s_addr != INADDR_ANY || inp.inp_fport != 0) {
+ fa = (unsigned char *)&inp.inp_faddr;
+ fp = (int)ntohs(inp.inp_fport);
+ }
+ if (fa || la)
+ (void) ent_inaddr(la, lp, fa, fp, AF_INET);
+ if (p.pr_protocol == IPPROTO_TCP && inp.inp_ppcb
+ && kread((KA_T)inp.inp_ppcb, (char *)&t, sizeof(t)) == 0) {
+ Lf->lts.type = 0;
+ Lf->lts.state.i = (int)t.t_state;
+ }
+ }
+ break;
+#endif /* HPUXV>=1030 */
+
+/*
+ * Process a Unix domain socket.
+ */
+ case AF_UNIX:
+ if (Funix)
+ Lf->sf |= SELUNX;
+ (void) snpf(Lf->type, sizeof(Lf->type), "unix");
+
+#if HPUXV>=1030
+/*
+ * Save size information for HP-UX 10.30 and above.
+ */
+ if (Fsize) {
+ if (!s.so_rcv
+ || kread((KA_T)s.so_rcv, (char *)&rb, sizeof(rb)))
+ rb.sb_cc = 0;
+ if (!s.so_snd
+ || kread((KA_T)s.so_snd, (char *)&sb, sizeof(sb)))
+ sb.sb_cc = 0;
+ if (Lf->access == 'r')
+ Lf->sz = (SZOFFTYPE)rb.sb_cc;
+ else if (Lf->access == 'w')
+ Lf->sz = (SZOFFTYPE)sb.sb_cc;
+ else
+ Lf->sz = (SZOFFTYPE)(rb.sb_cc + sb.sb_cc);
+ Lf->sz_def = 1;
+ } else
+ Lf->off_def = 1;
+#endif /* HPUXV>=1030 */
+
+ /*
+ * Read Unix protocol control block and the Unix address structure.
+ */
+ enter_dev_ch(print_kptr(sa, (char *)NULL, 0));
+ if (kread((KA_T) s.so_pcb, (char *) &unp, sizeof(unp))) {
+ (void) snpf(Namech, Namechl, "can't read unpcb at %s",
+ print_kptr((KA_T)s.so_pcb, (char *)NULL, 0));
+ break;
+ }
+ if ((struct socket *)sa != unp.unp_socket) {
+ (void) snpf(Namech, Namechl, "unp_socket (%s) mismatch",
+ print_kptr((KA_T)unp.unp_socket, (char *)NULL, 0));
+ break;
+ }
+
+#if HPUXV<1030
+ /*
+ * Read UNIX domain socket address information for HP-UX below 10.30.
+ */
+ if (unp.unp_addr) {
+ if (kread((KA_T) unp.unp_addr, (char *) &mb, sizeof(mb))) {
+ (void) snpf(Namech, Namechl, "can't read unp_addr at %s",
+ print_kptr((KA_T)unp.unp_addr, (char *)NULL, 0));
+ break;
+ }
+ ua = (struct sockaddr_un *)(((char *)&mb) + mb.m_off);
+ mbl = mb.m_len;
+ }
+#else /* HPUXV>=1030 */
+ /*
+ * Obtain UNIX domain socket address information for HP-UX 10.30 and
+ * above.
+ */
+ if (unp.unp_ino) {
+ Lf->inode = (INODETYPE)unp.unp_ino;
+ Lf->inp_ty = 1;
+ }
+ ua = (struct sockaddr_un *)NULL;
+ mbl = 0;
+ if (unp.unp_addr
+ && kread((KA_T)unp.unp_addr, (char *)&mb, sizeof(mb)) == 0
+ && mb.b_datap
+ && kread((KA_T)mb.b_datap, (char *)&db, sizeof(db)) == 0) {
+ if (db.db_base) {
+ if (dbl < (db.db_size + 1)) {
+ dbl = db.db_size + 1;
+ if (dbf)
+ dbf = (char *)realloc((MALLOC_P *)dbf,
+ (MALLOC_S) dbl);
+ else
+ dbf = (char *)malloc((MALLOC_S)dbl);
+ if (!dbf) {
+ (void) fprintf(stderr,
+ "%s: no space (%d) for UNIX socket address\n",
+ Pn, dbl);
+ Exit(1);
+ }
+ }
+ if (kread((KA_T)db.db_base, dbf, db.db_size) == 0) {
+ mbl = db.db_size;
+ dbf[mbl] = '\0';
+ ua = (struct sockaddr_un *)dbf;
+ }
+ }
+ }
+#endif /* HPUXV>=1030 */
+
+ if (!ua) {
+ ua = &un;
+ (void) bzero((char *)ua, sizeof(un));
+ ua->sun_family = AF_UNSPEC;
+ }
+ /*
+ * Print information on Unix socket that has no address bound
+ * to it, although it may be connected to another Unix domain
+ * socket as a pipe.
+ */
+ if (ua->sun_family != AF_UNIX) {
+ if (ua->sun_family == AF_UNSPEC) {
+ if (unp.unp_conn) {
+ if (kread((KA_T)unp.unp_conn, (char *) &uc, sizeof(uc)))
+ (void) snpf(Namech, Namechl,
+ "can't read unp_conn at %s",
+ print_kptr((KA_T)unp.unp_conn,(char *)NULL,0));
+ else
+ (void) snpf(Namech, Namechl, "->%s",
+ print_kptr((KA_T)uc.unp_socket,(char *)NULL,0));
+ } else
+ (void) snpf(Namech, Namechl, "->(none)");
+ } else
+ (void) snpf(Namech, Namechl, "unknown sun_family (%d)",
+ ua->sun_family);
+ break;
+ }
+ if (ua->sun_path[0]) {
+ if (mbl >= sizeof(struct sockaddr_un))
+ mbl = sizeof(struct sockaddr_un) - 1;
+ *((char *)ua + mbl) = '\0';
+ if (Sfile && is_file_named(ua->sun_path, 0))
+ Lf->sf |= SELNM;
+ if (!Namech[0])
+ (void) snpf(Namech, Namechl, "%s", ua->sun_path);
+ } else
+ (void) snpf(Namech, Namechl, "no address");
+ break;
+ default:
+ printunkaf(fam, 1);
+ }
+ if (Namech[0])
+ enter_nm(Namech);
+}
+
+
+#if HPUXV>=1030
+/*
+ * process_stream_sock() - process stream socket
+ */
+
+void
+process_stream_sock(ip, pcb, pn, vt)
+ KA_T ip; /* IP module's q_ptr */
+ KA_T pcb; /* protocol's q_ptr */
+ char *pn; /* protocol name */
+ enum vtype vt; /* vnode type */
+{
+ unsigned char *fa = (unsigned char *)NULL;
+ char *ep;
+ int fp, lp, rq, sq;
+ struct ipc_s ic;
+ unsigned char *la = (unsigned char *)NULL;
+ size_t sz;
+ u_short pt;
+ struct tcp_s tc;
+ tcph_t th;
+ struct udp_s ud;
+/*
+ * Set file type and protocol. If AF_INET selection is in effect, set its flag.
+ */
+ if (Fnet)
+ Lf->sf |= SELNET;
+ (void) snpf(Lf->type, sizeof(Lf->type), "inet");
+ if (pn) {
+ (void) snpf(Lf->iproto, sizeof(Lf->iproto), pn);
+ Lf->inp_ty = 2;
+ } else if (Sfile && (vt != VNON) && Lf->dev_def && (Lf->inp_ty == 1)) {
+
+ /*
+ * If the protocol name isn't known and this stream socket's vnode type
+ * isn't VNON, the stream socket will be handled mostly as a stream.
+ * Thus, a named file check is appropriate.
+ */
+ if (is_file_named((char *)NULL, (vt == VCHR) ? 1 : 0))
+ Lf->sf |= SELNM;
+ }
+/*
+ * Get IP structure.
+ */
+ *Namech = '\0';
+ if (!ip || kread(ip, (char *)&ic, sizeof(ic))) {
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "%scan't read IP control structure from %s",
+ sz ? " " : "", print_kptr(ip, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ if (!Lf->dev_def)
+ enter_dev_ch(print_kptr(ip, (char *)NULL, 0));
+/*
+ * Check for protocol control block address. Enter if non-NULL and clear
+ * device definition flag.
+ */
+ if (!pcb) {
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "%ssocket stream has no TCP or UDP module",
+ sz ? " " : "");
+ enter_nm(Namech);
+ return;
+ }
+/*
+ * Select processing by protocol name.
+ */
+ if (pn && !strcmp(pn, "TCP")) {
+
+ /*
+ * Process TCP socket.
+ */
+ if (kread(pcb, (char *)&tc, sizeof(tc))) {
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "%scan't read TCP PCB from %s",
+ sz ? " " : "", print_kptr(pcb, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ /*
+ * Save TCP address.
+ */
+ la = (unsigned char *)&ic.ipc_tcp_laddr;
+ pt = (u_short)ic.ipc_tcp_lport;
+ if (((struct in_addr *)la)->s_addr == INADDR_ANY && pt == 0) {
+
+ /*
+ * If the ipc_s structure has no local address, use the local
+ * address in its tcp_iph structure, and the port number in its
+ * tcph structure.
+ */
+ la = (unsigned char *)&tc.tcp_u.tcp_u_iph.iph_src[0];
+ if (tc.tcp_hdr_len && tc.tcp_tcph
+ && kread((KA_T)tc.tcp_tcph, (char *)&th, sizeof(th))
+ == 0)
+ pt = (u_short)th.th_lport;
+ }
+ lp = (int)ntohs(pt);
+ if ((int)ic.ipc_tcp_faddr != INADDR_ANY
+ || (u_short)ic.ipc_tcp_fport != 0)
+ {
+ fa = (unsigned char *)&ic.ipc_tcp_faddr;
+ fp = (int)ntohs((u_short)ic.ipc_tcp_fport);
+ }
+ if (fa || la)
+ (void) ent_inaddr(la, lp, fa, fp, AF_INET);
+ /*
+ * Save TCP state and size information.
+ */
+ Lf->lts.type = 0;
+ Lf->lts.state.i = (int)tc.tcp_state;
+
+# if defined(HASTCPTPIQ) || defined(HASTCPTPIW)
+# if defined(HASTCPTPIW)
+ Lf->lts.rw = (int)tc.tcp_rwnd;
+ Lf->lts.ww = (int)tc.tcp_swnd;
+ Lf->lts.rws = Lf->lts.wws = 1;
+# endif /* defined(HASTCPTPIW) */
+
+ if ((rq = (int)tc.tcp_rnxt - (int)tc.tcp_rack - 1) < 0)
+ rq = 0;
+ if ((sq = (int)tc.tcp_snxt - (int)tc.tcp_suna - 1) < 0)
+ sq = 0;
+
+# if defined(HASTCPTPIQ)
+ Lf->lts.rq = (unsigned long)rq;
+ Lf->lts.sq = (unsigned long)sq;
+ Lf->lts.rqs = Lf->lts.sqs = 1;
+# endif /* defined(HASTCPTPIQ) */
+
+ if (Fsize) {
+ if (Lf->access == 'r')
+ Lf->sz = (SZOFFTYPE)rq;
+ else if (Lf->access == 'w')
+ Lf->sz = (SZOFFTYPE)sq;
+ else
+ Lf->sz = (SZOFFTYPE)(rq + sq);
+ Lf->sz_def = 1;
+ } else
+ Lf->off_def = 1;
+
+# else /* !defined(HASTCPTPIQ) && !defined(HASTCPTPIW) */
+ if (!Fsize)
+ Lf->off_def = 1;
+# endif /* defined(HASTCPTPIQ) || defined(HASTCPTPIW) */
+
+# if defined(HASTCPOPT)
+ if (Ftcptpi & TCPTPI_FLAGS) {
+
+ /*
+ * Save TCP options and values..
+ */
+ if (tc.tcp_naglim == (uint)1)
+ Lf->lts.topt |= TF_NODELAY;
+ Lf->lts.mss = (unsigned long)tc.tcp_mss;
+ Lf->lts.msss = (unsigned char)1;
+ }
+# endif /* defined(HASTCPOPT) */
+
+# if defined(HASSOOPT)
+ if (Ftcptpi & TCPTPI_FLAGS) {
+
+ /*
+ * Save socket options.
+ */
+ if (tc.tcp_broadcast)
+ Lf->lts.opt |= SO_BROADCAST;
+ if (tc.tcp_so_debug)
+ Lf->lts.opt |= SO_DEBUG;
+ if (tc.tcp_dontroute)
+ Lf->lts.opt |= SO_DONTROUTE;
+ if (tc.tcp_keepalive_intrvl
+ && (tc.tcp_keepalive_intrvl != 7200000)
+ ) {
+ Lf->lts.opt |= SO_KEEPALIVE;
+ Lf->lts.kai = (unsigned int)tc.tcp_keepalive_intrvl;
+ }
+ if (tc.tcp_lingering) {
+ Lf->lts.opt |= SO_LINGER;
+ Lf->lts.ltm = (unsigned int)tc.tcp_linger;
+ }
+ if (tc.tcp_oobinline)
+ Lf->lts.opt |= SO_OOBINLINE;
+ if (tc.tcp_reuseaddr)
+ Lf->lts.opt |= SO_REUSEADDR;
+ if (tc.tcp_reuseport)
+ Lf->lts.opt |= SO_REUSEPORT;
+ if (tc.tcp_useloopback)
+ Lf->lts.opt |= SO_USELOOPBACK;
+ Lf->lts.qlen = (unsigned int)tc.tcp_conn_ind_cnt;
+ Lf->lts.qlim = (unsigned int)tc.tcp_conn_ind_max;
+ if (Lf->lts.qlen || Lf->lts.qlim)
+ Lf->lts.qlens = Lf->lts.qlims = (unsigned char)1;
+ }
+# endif /* defined(HASSOOPT) */
+
+ Namech[0] = '\0';
+ return;
+ } else if (pn && !strcmp(pn, "UDP")) {
+
+ /*
+ * Process UDP socket.
+ */
+ if (kread(pcb, (char *)&ud, sizeof(ud))) {
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "%scan't read UDP PCB from %s",
+ sz ? " " : "", print_kptr(pcb, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ /*
+ * Save UDP address and TPI state.
+ */
+ la = (unsigned char *)&ic.ipc_udp_addr;
+ pt = (u_short)ic.ipc_udp_port;
+ if (((struct in_addr *)la)->s_addr == INADDR_ANY && pt == 0) {
+
+ /*
+ * If the ipc_s structure has no local address, use the one in the
+ * udp_s structure.
+ */
+ pt = (u_short)ud.udp_port[0];
+ }
+ (void) ent_inaddr(la, (int)ntohs(pt), (unsigned char *)NULL,
+ -1, AF_INET);
+ if (!Fsize)
+ Lf->off_def = 1;
+ Lf->lts.type = 1;
+ Lf->lts.state.ui = (unsigned int)ud.udp_state;
+ Namech[0] = '\0';
+ return;
+ } else {
+
+ /*
+ * Record an unknown protocol.
+ */
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "%sunknown stream protocol: %s",
+ sz ? " " : "", pn ? pn : "NUll");
+ }
+ if (Namech[0])
+ enter_nm(Namech);
+}
+#endif /* HPUXV>=1030 */
diff --git a/dialects/hpux/kmem/dstore.c b/dialects/hpux/kmem/dstore.c
new file mode 100644
index 0000000..bbf18f1
--- /dev/null
+++ b/dialects/hpux/kmem/dstore.c
@@ -0,0 +1,241 @@
+/*
+ * dstore.c - /dev/kmem-based HP-UX global storage for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dstore.c,v 1.12 2007/04/24 16:25:30 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+/*
+ * Global storage definitions
+ */
+
+#if defined(HAS_AFS)
+
+# if defined(HASAOPT)
+char *AFSApath = (char *)NULL; /* alternate AFS name list path
+ * (from -A) */
+# endif /* defined(HASAOPT) */
+
+struct vfs *AFSVfsp = (struct vfs *)NULL;
+ /* AFS vfs struct kernel address */
+#endif /* defined(HAS_AFS) */
+
+int CloneMaj; /* clone major device number */
+
+
+/*
+ * Drive_Nl -- table to drive the building of Nl[] via build_Nl()
+ * (See lsof.h and misc.c.)
+ */
+
+struct drive_Nl Drive_Nl[] = {
+
+# if defined(hp9000s300) || defined(__hp9000s300)
+ { "arFid", "_afs_rootFid" },
+ { "avops", "_afs_vnodeops" },
+ { "avol", "_afs_volumes" },
+ { X_NCACHE, "_ncache" },
+ { X_NCSIZE, "_ncsize" },
+ { "proc", "_proc" },
+ { "nvops", "_nfs_vnodeops" },
+ { "nvops3", "_nfs_vnodeops3" },
+ { "nv3ops", "_nfs3_vnodeops" },
+ { "nproc", "_nproc" },
+ { "uvops", "_ufs_vnodeops" },
+ { "vfops", "_vnodefops" },
+
+# if HPUXV<800
+ { "upmap", "_Usrptmap" },
+ { "upt", "_usrpt" },
+# endif /* HPUXV<800 */
+# endif /* defined(hp9000s300) || defined(__hp9000s300) */
+
+# if defined(hp9000s800) || defined(__hp9000s800)
+ { "arFid", "afs_rootFid" },
+ { "avops", "afs_vnodeops" },
+ { "avol", "afs_volumes" },
+ { X_NCACHE, "ncache" },
+ { X_NCSIZE, "ncsize" },
+ { "proc", "proc" },
+ { "nvops", "nfs_vnodeops" },
+ { "nvops3", "nfs_vnodeops3" },
+ { "nv3ops", "nfs3_vnodeops" },
+ { "nproc", "nproc" },
+ { "uvops", "ufs_vnodeops" },
+ { "vfops", "vnodefops" },
+
+# if HPUXV<800
+ { "ubase", "ubase" },
+ { "npids", "npids" },
+# else /* HPUXV>=800 */
+# if HPUXV>=1000
+# if HPUXV>=1030
+ { "clmaj", "clonemajor" },
+# endif /* HPUXV>=1030 */
+ { "cvops", "cdfs_vnodeops" },
+ { "fvops", "fifo_vnodeops" },
+ { "pvops", "pipe_vnodeops" },
+ { "svops", "spec_vnodeops" },
+ { "vvops", "vx_vnodeops" },
+# endif /* HPUXV>=1000 */
+# endif /* HPUXV<800 */
+# endif /* defined(hp9000s800) || defined(__hp9000s800) */
+
+ { "mvops", "mvfs_vnodeops" },
+
+# if HPUXV>=1100
+ { "chunksz", "sizeof_fd_chunk_t" },
+# endif /* HPUXV>=1100 */
+
+ { "", "" },
+ { NULL, NULL }
+};
+
+
+int HaveCloneMaj = 0; /* CloneMaj status */
+int Kd = -1; /* /dev/kmem file descriptor */
+KA_T Kpa; /* kernel proc structure address */
+
+#if HPUXV>=1010
+KA_T Ktp; /* kernel thread pointer from proc
+ * struct */
+#endif /* HPUXV>=1010 */
+
+struct l_vfs *Lvfs = NULL; /* local vfs structure table */
+
+#if HPUXV<800
+int Mem = -1; /* /dev/mem file descriptor */
+#endif /* HPUXV<800 */
+
+#if HPUXV<800 && defined(hp9000s800)
+int npids; /* number of PIDs (for uvadd()) */
+struct proc *proc; /* process table address (for uvadd()) */
+#endif /* HPUXV<800 && defined(hp9000s300) */
+
+#if defined(HASFSTRUCT)
+/*
+ * Pff_tab[] - table for printing file flags
+ */
+
+struct pff_tab Pff_tab[] = {
+ { (long)FREAD, FF_READ },
+ { (long)FWRITE, FF_WRITE },
+ { (long)FNDELAY, FF_NDELAY },
+ { (long)FAPPEND, FF_APPEND },
+ { (long)FMARK, FF_MARK },
+ { (long)FDEFER, FF_DEFER },
+ { (long)FNBLOCK, FF_NBLOCK },
+ { (long)FNOCTTY, FF_NOCTTY },
+
+# if defined(FSYNC)
+ { (long)FSYNC, FF_SYNC },
+# else /* !defined(FSYNC) */
+# if defined(O_SYNC)
+ { (long)O_SYNC, FF_SYNC },
+# endif /* defined(O_SYNC) */
+# endif /* defined(FSYNC) */
+
+# if defined(FCOPYAVOID)
+ { (long)FCOPYAVOID, FF_COPYAVOID },
+# endif /* defined(FCOPYAVOID) */
+
+# if defined(FPOSIX_AIO)
+ { (long)FPOSIX_AIO, FF_POSIX_AIO },
+# endif /* defined(FPOSIX_AIO) */
+
+# if defined(FLARGEFILE)
+ { (long)FLARGEFILE, FF_LARGEFILE },
+# else /* !defined(FLARGEFILE) */
+# if HPUXV>=1100
+ { (long)0x800, FF_LARGEFILE },
+# endif /* HPUXV>=1100 */
+# endif /* defined(FLARGEFILE) */
+
+ { (long)0x100, FF_KERNEL },
+ { (long)0, NULL }
+};
+
+
+/*
+ * Pof_tab[] - table for print process open file flags
+ */
+
+# if HPUXV>=1020
+#define UF_EXCLOSE 0x1
+#define UF_MAPPED 0x2
+#define UF_FDLOCK 0x4
+#define UF_INUSE 0x8
+# endif /* HPUXV>=1020 */
+
+struct pff_tab Pof_tab[] = {
+
+# if defined(UF_EXCLOSE)
+ { (long)UF_EXCLOSE, POF_CLOEXEC },
+# endif /* defined(UF_EXCLOSE) */
+
+# if defined(UF_MAPPED)
+ { (long)UF_MAPPED, POF_MAPPED },
+# endif /* defined(UF_MAPPED) */
+
+# if defined(UF_FDLOCK)
+ { (long)UF_FDLOCK, POF_FDLOCK },
+# endif /* defined(UF_FDLOCK) */
+
+# if defined(UF_INUSE)
+ { (long)UF_INUSE, POF_INUSE },
+# endif /* defined(UF_INUSE) */
+
+ { (long)0, NULL }
+};
+#endif /* defined(HASFSTRUCT) */
+
+#if HPUXV<800
+int Swap = -1; /* swap device file descriptor */
+#endif /* HPUXV<800 */
+
+#if HPUXV<800 && defined(hp9000s800)
+struct user *ubase; /* user area base (for uvadd()) */
+#endif /* HPUXV<800 && defined(hp9000s800) */
+
+#if HPUXV<800 && defined(hp9000s300)
+struct user *ubase; /* user area base (for uvadd()) */
+struct pte *Usrptmap; /* user page table map pointer */
+struct pte *usrpt; /* user page table pointer
+ * (for bktomx from vmmac.h) */
+#endif /* HPUXV<800 && defined(hp9000s300) */
+
+KA_T Vnfops; /* vnodefops switch address */
diff --git a/dialects/hpux/kmem/hpux11/ipc_s.h b/dialects/hpux/kmem/hpux11/ipc_s.h
new file mode 100644
index 0000000..4945c98
--- /dev/null
+++ b/dialects/hpux/kmem/hpux11/ipc_s.h
@@ -0,0 +1,98 @@
+/*
+ * ipc_s.h for HP-UX 10.30 and above
+ *
+ * This header file defines the ipc_s structure for lsof. The ipc_s structure
+ * is the streams equivalent of a Berkeley-style inpcb (Internet Protocol
+ * Control Block). The ipc_s holds the TCP/IP address for a stream.
+ *
+ * The original HP-UX 11 distribution has a flat ipc_s structure, with hash
+ * links to other ipc_s structures, and direct links to the the read and write
+ * sections of the stream.
+ *
+ * After patch bundle B11.00.43 the ipc_s structure definition requires
+ * two other Q4-derived structures, mirg_s and ipis_s. The ipis_s structure
+ * contains the hash and stream links formerly contained in ipc_s.
+ *
+ * V. Abell <abe@purdue.edu>
+ * February, 1998
+ *
+ * Patch bundle update supplied by: Kevin Vajk <kvajk@cup.hp.com>
+ * February, 1999
+ */
+
+#if !defined(LSOF_IPC_S_H)
+#define LSOF_IPC_S_H
+
+#include "kernbits.h"
+#include <sys/types.h>
+
+typedef struct mirg_s {
+ uint mirg_gen;
+} mirg_t;
+
+# if defined(HAS_IPC_S_PATCH)
+typedef struct ipis_s {
+ union {
+ KA_T u_ipc_hash_next;
+ KA_T u_ill_hash_next;
+ KA_T u_ipis_hash_next;
+ } ipis_hash_next_u;
+ union {
+ KA_T u_ipc_ptphn;
+ KA_T u_ill_ptphn;
+ KA_T u_ipis_ptphn;
+ } ipis_ptphn_u;
+ KA_T ipis_readers_next;
+ KA_T ipis_readers_ptpn;
+ KA_T ipis_ptr_hash_next;
+ KA_T ipis_ptr_ptphn;
+ KA_T ipis_rq;
+ KA_T ipis_wq;
+ mirg_t ipis_mirg;
+# if HAS_IPC_S_PATCH==2
+ uint ipis_msgsqueued;
+# endif /* HAS_IPC_S_PATCH==2 */
+} ipis_t;
+# endif /* defined(HAS_IPC_S_PATCH) */
+
+typedef struct ipc_s {
+
+# if defined(HAS_IPC_S_PATCH)
+ ipis_t ipc_ipis;
+# else /* !defined(HAS_IPC_S_PATCH) */
+ KA_T ipc_hash_next; /* hash link -- ipc_s
+ * structures are hashed in
+ * ipc_tcp_conn[] and
+ * ipc_udp_conn[] */
+ mirg_t ipc_mirg;
+ KA_T ipc_readers_next;
+ KA_T ipc_readers_ptpn;
+ KA_T ipc_ptphn;
+ KA_T ipc_rq; /* stream's read queue */
+ KA_T ipc_wq; /* stream's write queue */
+# endif /* defined(HAS_IPC_S_PATCH) */
+
+ int ipc_ioctl_pended;
+ union {
+ struct {
+ uint32_t ipcu_lcl_addr; /* local IP address */
+ uint32_t ipcu_rem_addr; /* remote IP address */
+ uint16_t ipcu_rem_port; /* remote port */
+ uint16_t ipcu_lcl_port; /* local port */
+ } ipcu_addrs;
+ uint16_t ipcu_tcp_addr[6];
+ } ipc_ipcu;
+/*
+ * The rest of the q4 elements are ignored.
+ */
+
+} ipc_s_t;
+
+#define ipc_udp_port ipc_ipcu.ipcu_addrs.ipcu_lcl_port
+#define ipc_udp_addr ipc_ipcu.ipcu_addrs.ipcu_lcl_addr
+#define ipc_tcp_lport ipc_ipcu.ipcu_addrs.ipcu_lcl_port
+#define ipc_tcp_laddr ipc_ipcu.ipcu_addrs.ipcu_lcl_addr
+#define ipc_tcp_fport ipc_ipcu.ipcu_addrs.ipcu_rem_port
+#define ipc_tcp_faddr ipc_ipcu.ipcu_addrs.ipcu_rem_addr
+
+#endif /* !defined(LSOF_IPC_S_H) */
diff --git a/dialects/hpux/kmem/hpux11/kernbits.h b/dialects/hpux/kmem/hpux11/kernbits.h
new file mode 100644
index 0000000..a0fd166
--- /dev/null
+++ b/dialects/hpux/kmem/hpux11/kernbits.h
@@ -0,0 +1,22 @@
+/*
+ * kernbits.h for HP-UX 10.30 and above
+ *
+ * This header file defines the basic kernel word size type for lsof, using
+ * the Configure-generated -DHPUXKERNBITS=<32|64> definition.
+ *
+ * V. Abell
+ * February, 1998
+ */
+
+#if !defined(LSOF_KERNBITS_H)
+#define LSOF_KERNBITS_H
+
+# if !defined(HPUXKERNBITS) || HPUXKERNBITS<64
+typedef uint32_t KA_T;
+#define KA_T_FMT_X "%#lx"
+# else /* defined(HPUXKERNBITS) && HPUXKERNBITS>=64 */
+typedef uint64_t KA_T;
+#define KA_T_FMT_X "%#llx"
+# endif /* !defined(HPUXKERNBITS) || HPUXKERNBITS<64 */
+
+#endif /* !defined(LSOF_KERNBITS_H) */
diff --git a/dialects/hpux/kmem/hpux11/lla.h b/dialects/hpux/kmem/hpux11/lla.h
new file mode 100644
index 0000000..36ec882
--- /dev/null
+++ b/dialects/hpux/kmem/hpux11/lla.h
@@ -0,0 +1,91 @@
+/*
+ * lla.h for HP-UX 10.30 and above
+ *
+ * This header file defines the lla_cb structure for lsof. Lsof uses it to
+ * to read the Link Level Access (LLA) control block. Link level access means
+ * access to the network link layer access protocol -- e.g., Ethernet 802.5.
+ *
+ * V. Abell <abe@purdue.edu>
+ * February, 1998
+ */
+
+#if !defined(LSOF_LLA_H)
+#define LSOF_LLA_H
+
+#include "kernbits.h"
+#include <sys/types.h>
+
+#define LLA_IS_ETHER 0x1
+#define LLA_FWRITE 0x100
+#define LLA_FREAD 0x200
+#define LLA_IS_8025 0x800
+#define LLA_IS_SNAP8025 0x1000
+#define LLA_IS_FA8025 0x4000
+
+typedef struct lla_hdr {
+ union {
+ struct {
+ u_char destaddr[6];
+ u_char sourceaddr[6];
+ u_short length;
+ u_char dsap;
+ u_char ssap;
+ u_char ctrl;
+ u_char pad[3];
+ u_short dxsap;
+ u_short sxsap;
+ } ieee;
+ struct {
+ u_char destaddr[6];
+ u_char sourceaddr[6];
+ u_short log_type;
+ u_short dxsap;
+ u_short sxsap;
+ } ether;
+ struct {
+ u_char access_ctl;
+ u_char frame_ctl;
+ u_char destaddr[6];
+ u_char sourceaddr[6];
+ u_char rif_plus[26];
+ u_char dsap;
+ u_char ssap;
+ u_char ctrl;
+ u_char orgid[3];
+ u_short etype;
+ } snap8025;
+ struct {
+ u_char access_ctl;
+ u_char frame_ctl;
+ u_char destaddr[6];
+ u_char sourceaddr[6];
+ u_char rif_plus[26];
+ u_char dsap;
+ u_char ssap;
+ u_char ctrl;
+ } ieee8025;
+ } proto;
+} lla_hdr_t;
+
+typedef struct lla_cb {
+ KA_T so_pcb;
+ KA_T pktheader;
+ KA_T head_packet;
+ KA_T last_packet;
+ KA_T lla_ifp;
+ u_int lan_signal_mask;
+ u_int lan_signal_pid;
+ int lan_pkt_size;
+ int lla_timeo;
+ KA_T lla_rsel;
+ struct lla_hdr packet_header;
+ short lla_msgsqd;
+ short lla_maxmsgs;
+ u_short lla_flags; /* flags, including type -- i.e.,
+ * the LLA_* symbols defined above */
+ short hdr_size;
+ int func_addr;
+ KA_T lla_lock;
+} lla_cb_t;
+
+#endif
diff --git a/dialects/hpux/kmem/hpux11/nfs_clnt.h b/dialects/hpux/kmem/hpux11/nfs_clnt.h
new file mode 100644
index 0000000..6b2df97
--- /dev/null
+++ b/dialects/hpux/kmem/hpux11/nfs_clnt.h
@@ -0,0 +1,76 @@
+/*
+ * nfs_clnt.h for HP-UX 10.30 and above
+ *
+ * This header file defines the mntinfo structure for lsof. Lsof uses it to
+ * obtain the device number of an NFS mount point.
+ *
+ * V. Abell
+ * February, 1998
+ */
+
+#if !defined(LSOF_NFS_CLNT_H)
+#define LSOF_NFS_CLNT_H
+
+#include "kernbits.h"
+#include "rnode.h"
+#include <rpc/types.h>
+#undef TCP_NODELAY
+#undef TCP_MAXSEG
+#include <rpc/rpc.h>
+#include <rpc/clnt.h>
+#include <sys/xti.h>
+#undef TCP_NODELAY
+#undef TCP_MAXSEG
+
+typedef struct kcondvar {
+ uint32_t _dummy1[6];
+} kcondvar_t;
+
+typedef struct mntinfo {
+ kmutex_t mi_lock;
+ KA_T mi_knetconfig;
+ struct netbuf mi_addr;
+ struct netbuf mi_syncaddr;
+ KA_T mi_rootvp;
+ uint32_t mi_flags;
+ int32_t mi_tsize;
+ int32_t mi_stsize;
+ int32_t mi_timeo;
+ int32_t mi_retrans;
+ char mi_hostname[32];
+ KA_T mi_netname;
+ int mi_netnamelen;
+ int mi_authflavor;
+ int32_t mi_acregmin;
+ int32_t mi_acregmax;
+ int32_t mi_acdirmin;
+ int32_t mi_acdirmax;
+ struct rpc_timers mi_timers[4];
+ int32_t mi_curread;
+ int32_t mi_curwrite;
+ KA_T mi_async_reqs;
+ KA_T mi_async_tail;
+ kcondvar_t mi_async_reqs_cv;
+ uint16_t mi_threads;
+ uint16_t mi_max_threads;
+ kcondvar_t mi_async_cv;
+ uint32_t mi_async_count;
+ kmutex_t mi_async_lock;
+ KA_T mi_pathconf;
+ u_long mi_prog;
+ u_long mi_vers;
+ KA_T mi_rfsnames;
+ KA_T mi_reqs;
+ KA_T mi_call_type;
+ KA_T mi_timer_type;
+ clock_t mi_printftime;
+ KA_T mi_aclnames;
+ KA_T mi_aclreqs;
+ KA_T mi_acl_call_type;
+ KA_T mi_acl_timer_type;
+ char mi_fsmnt[512];
+ uint64_t mi_maxfilesize;
+ dev_t mi_mntno; /* mounted device number */
+} mntinfo_t;
+
+#endif /* !defined(LSOF_NFS_CLNT_H) */
diff --git a/dialects/hpux/kmem/hpux11/proc.h b/dialects/hpux/kmem/hpux11/proc.h
new file mode 100644
index 0000000..e922bd4
--- /dev/null
+++ b/dialects/hpux/kmem/hpux11/proc.h
@@ -0,0 +1,245 @@
+/*
+ * proc.h for Hp-UX 10.30 and above
+ *
+ * This header file defines the proc structure for lsof. Lsof uses it to
+ * get process information, including PGID, PID, PPID, UID, CWD, and open
+ * file pointers.
+ *
+ * V. Abell <abe@purdue.edu>
+ * February, 1998
+ */
+
+#if !defined(LSOF_PROC_H)
+#define LSOF_PROC_H
+
+#include "kernbits.h"
+#include <sys/types.h>
+#include <sys/resource.h>
+#include <sys/user.h>
+
+struct pprof {
+ KA_T pr_base;
+ u_long pr_size;
+ u_long pr_off;
+ u_int pr_scale;
+};
+
+typedef enum proc_flag {
+ SLOAD = 0x1,
+ SSYS = 0x2,
+ SDONTTRC = 0x4,
+ STRC = 0x8,
+ SWTED_PARENT = 0x10,
+ SDEACTSELF = 0x20,
+ SPVFORK = 0x40,
+ SWEXIT = 0x80,
+ SPGID_EXIT_ADJUSTED = 0x100,
+ SVFORK = 0x200,
+ SWANTS_ALLCPU = 0x400,
+ SSERIAL = 0x800,
+ SDEACT = 0x1000,
+ SWAITIO = 0x2000,
+ SWTED_DEBUGGER = 0x4000,
+ SWCONT = 0x8000,
+ SDBG_CREATING = 0x10000,
+ SDBG_WAITING = 0x20000,
+ SDBG_ACTIVE = 0x40000,
+ SDBG_LIMBO = 0x80000,
+ SDBG_ATTACHING = 0x100000,
+ SDBG_EXITING = 0x200000,
+ SDBG_KILLED = 0x400000,
+ SDBG_INEXEC = 0x800000,
+ SDBG_TRACESELF = 0x1000000,
+ SDBG_STOPPED = 0x2000000,
+ SDBG_EXITREQ = 0x4000000,
+ SREAPING = 0x10000000
+} proc_flag_t;
+
+typedef enum proc_flag2 {
+ S2CLDSTOP = 0x1,
+ S2EXEC = 0x2,
+ SGRAPHICS = 0x4,
+ SADOPTIVE = 0x8,
+ SADOPTIVE_WAIT = 0x10,
+ SPMT = 0x40,
+ S2SENDDILSIG = 0x100,
+ SLKDONE = 0x200,
+ SISNFSLM = 0x400,
+ S2POSIX_NO_TRUNC = 0x800,
+ S2SYSCALL_BYPID = 0x1000,
+ S2ADOPTEE = 0x2000,
+ SCRITICAL = 0x4000,
+ SMULTITHREADED = 0x8000,
+ S2NOCLDWAIT = 0x10000,
+ S_USE_THRD_CACHE = 0x20000,
+ S2PASS_VIOREF = 0x40000,
+ S2VIOREF_NPROC = 0x80000,
+ SUSRMULTITHREADED = 0x100000
+} proc_flag2_t;
+
+typedef enum proc_state {
+ SUNUSED = 0,
+ SWAIT = 0x1,
+ SIDL = 0x2,
+ SZOMB = 0x3,
+ SSTOP = 0x4,
+ SINUSE = 0x5
+} proc_state_t;
+
+typedef enum proc_sync_flag {
+ P_OP_PENDING_READER = 0x1,
+ P_OP_PENDING_WRITER = 0x2
+} proc_sync_flag_t;
+
+typedef enum proc_sync_reason {
+ P_OP_NONE = 0,
+ P_OP_THREAD_MGMT = 0x1,
+ P_OP_EXIT = 0x2,
+ P_OP_EXEC = 0x3,
+ P_OP_SUSPEND = 0x4,
+ P_OP_CONTINUE = 0x5,
+ P_OP_SIGTRAP = 0x6,
+ P_OP_FORK = 0x7,
+ P_OP_VFORK = 0x8,
+ P_OP_CORE = 0x9,
+ KT_OP_SUSPEND = 0xa,
+ KT_OP_RESUME = 0xb,
+ KT_OP_CREATE = 0xc,
+ KT_OP_TERMINATE = 0xd,
+ KT_OP_LWPEXIT = 0xe,
+ KT_OP_ABORT_SYSCALL = 0xf
+} proc_sync_reason_t;
+
+typedef struct proc {
+ short p_fandx;
+ short p_pandx;
+ int p_created_threads;
+ KA_T p_firstthreadp; /* thread pointer (for locks) */
+ KA_T p_lastthreadp;
+ proc_flag_t p_flag;
+ KA_T thread_lock;
+ KA_T p_lock;
+ KA_T p_detached_zombie;
+ KA_T p_fss;
+ proc_state_t p_stat; /* process state */
+ char p_nice;
+ u_short p_pri;
+ int p_livethreads;
+ int p_cached_threads_count;
+ int p_cached_threads_max;
+ KA_T p_cached_threads;
+ KA_T p_cache_next;
+ KA_T p_cache_prev;
+ ksigset_t p_sig;
+ ksigset_t p_ksi_avail;
+ ksigset_t p_ksifl_alloced;
+ KA_T p_ksiactive;
+ KA_T p_ksifree;
+ KA_T p_sigcountp;
+ KA_T p_sigwaiters;
+ int p_cursig;
+ proc_flag2_t p_flag2;
+ int p_coreflags;
+ uid_t p_uid; /* user ID (UID) of process owner */
+ uid_t p_suid;
+ KA_T p_pgid_p;
+ gid_t p_pgid;
+ pid_t p_pid; /* process ID (PID) */
+ pid_t p_ppid; /* parent process ID (PPID) */
+ size_t p_maxrss;
+ short p_idhash;
+ short p_ridhash;
+ short p_pgidhx;
+ short p_rpgidhx;
+ short p_uidhx;
+ short p_ruidhx;
+ KA_T p_pptr;
+ KA_T p_cptr;
+ KA_T p_osptr;
+ KA_T p_ysptr;
+ KA_T p_dptr;
+ KA_T p_vas; /* pointer to VM for process */
+ short p_memresv;
+ short p_swpresv;
+ short p_sysmemresv;
+ short p_sysswpresv;
+ u_short p_xstat;
+ time_t p_deactime;
+ short p_ndx;
+ sid_t p_sid;
+ short p_sidhx;
+ short p_rsidhx;
+ short p_idwrite;
+ KA_T p_semundo;
+ KA_T p_dbipcp;
+ u_char p_cookie;
+ u_char p_reglocks;
+ int p_no_swap_count;
+ dev_t p_ttyd;
+ KA_T p_ttyp;
+ KA_T p_nextdeact;
+ time_t p_start;
+ KA_T p_shadproc;
+ KA_T p_bor_lock;
+ int p_maxof; /* maximum open files */
+ KA_T p_cdir; /* pointer to CWD vnode */
+ KA_T p_rdir; /* pointer to root directory vnode */
+ KA_T p_ofilep; /* pointer to ofile_t chain */
+ KA_T p_vforkbuf;
+ u_int p_schedpolicy;
+ u_short p_pindx;
+ KA_T p_krusagep;
+ KA_T p_timers;
+ KA_T p_clic;
+ proc_sync_reason_t p_sync_reason;
+ void (*p_wide_action_hdlr)();
+ proc_sync_flag_t p_sync_flag;
+ ushort p_sync_readers;
+ ushort p_sync_writers;
+ u_int p_sync_thread_cnt;
+ int p_suspended_threads;
+ int p_captr;
+ union {
+ struct {
+ u_int zombies_exist:1,
+ recalc_privgrps:1,
+ unused:30;
+ } bits;
+ u_int all;
+ } p_pl_flags;
+ u_int p_seqnum;
+ spu_t p_spu_group;
+ u_char p_spu_mandatory;
+ KA_T p_cred;
+ caddr_t p_ki_bitmap;
+ KA_T p_aioqp;
+ KA_T p_shared;
+ KA_T p_nseminfop;
+ KA_T p_mqpinfop;
+ KA_T p_dbgctltp;
+ KA_T p_dbgp;
+ KA_T p_trcp;
+ KA_T p_p2p;
+ KA_T p_gang;
+ u_int p_pmon_timer_mask;
+ u_int p_pmon_inherit;
+ u_long p_pmon_state_flag;
+ u_long p_pmon_state_value;
+ KA_T p_cnx_features;
+ char p_comm[15];
+ aid_t p_aid;
+ short p_audproc;
+ short p_audsusp;
+ gid_t p_sgid;
+ u_int p_priv[2];
+ int p_highestfd;
+ short p_cmask;
+ time_t p_ticks;
+ short p_acflag;
+ struct rlimit p_rlimit[11];
+ KA_T p_auditperproc;
+ struct pprof p_prof;
+ char p_spare[48];
+} proc_t;
+
+#endif /* !defined(LSOF_PROC_H) */
diff --git a/dialects/hpux/kmem/hpux11/rnode.h b/dialects/hpux/kmem/hpux11/rnode.h
new file mode 100644
index 0000000..f61ec8a
--- /dev/null
+++ b/dialects/hpux/kmem/hpux11/rnode.h
@@ -0,0 +1,94 @@
+/*
+ * rnode.h for HP-UX 10.30 and above
+ *
+ * This header file defines the rnode structure for lsof. Lsof uses it to get
+ * infomation about remote (NFS) nodes -- e.g., node number and size.
+ *
+ * V. Abell <abe@purdue.edu>
+ * February, 1998
+ */
+
+#if !defined(LSOF_RNODE_H)
+#define LSOF_RNODE_H
+
+#include "kernbits.h"
+
+#define _KERNEL
+#include <sys/spinlock.h>
+#undef _KERNEL
+
+#include "vnode.h"
+
+typedef struct krwlock {
+ lock_t *interlock;
+ u_int delay;
+ int read_count;
+ char want_write;
+ char want_upgrade;
+ char waiting;
+ char no_swap;
+} krwlock_t;
+
+typedef struct kmutex {
+ lock_t *spin_lockp;
+ int lockp_type;
+} kmutex_t;
+
+typedef struct nfs_fhandle {
+ int fh_len;
+ char fh_buf[64];
+} nfs_fhandle_t;
+
+typedef struct rnode {
+ KA_T r_freef;
+ KA_T r_freeb;
+ KA_T r_hash;
+ vnode_t r_vnode; /* the vnode that contains this rnode */
+ krwlock_t r_rwlock;
+ kmutex_t r_statelock;
+ nfs_fhandle_t r_fh;
+ uint16_t r_flags;
+ int16_t r_error;
+ KA_T r_rcred;
+ KA_T r_wcred;
+ KA_T r_unlcred;
+ KA_T r_unlname;
+ KA_T r_unldvp;
+ int64_t r_size; /* This should be an off_t, but there's an
+ * unresolvable conflict between the kernel
+ * and application off_t sizes. */
+ struct vattr r_attr; /* the vnode attributes -- e.g., node number,
+ * size, etc. (See ./vnode.h.) */
+
+/*
+ * These q4 elements are ignored.
+
+ time_t r_attrtime;
+ time_t r_mtime;
+ int32_t r_mapcnt;
+ uint32_t r_count;
+ int32_t r_seq;
+ int *r_acc;
+ int *r_dir;
+ int *r_direof;
+ symlink_cache r_symlink;
+ u_char r_verf;
+ commit_t r_commit;
+ recover_t r_recover;
+ uint32_t r_truncaddr;
+ uint32_t r_iocnt;
+ kcondvar_t r_trunccv;
+ kmutex_t r_serialize;
+ u_char r_cookieverf;
+ int *r_lmpl;
+ daddr_t r_lastr;
+ kcondvar_t r_cv;
+ int *r_owner;
+ short r_ownercount;
+
+ * Those q4 elements were ignored.
+ */
+
+} rnode_t;
+
+#endif /* !defined(LSOF_RNODE_H) */
diff --git a/dialects/hpux/kmem/hpux11/sth.h b/dialects/hpux/kmem/hpux11/sth.h
new file mode 100644
index 0000000..a47d07d
--- /dev/null
+++ b/dialects/hpux/kmem/hpux11/sth.h
@@ -0,0 +1,84 @@
+/*
+ * sth_h for HP-UX 10.30 and above
+ *
+ * This header file defines the stream head structure, sth_t, for lsof. Lsof
+ * uses the stream head structure to obtain the stream's read and write queue
+ * structure pointers.
+ *
+ * V. Abell
+ * February, 1998
+ */
+
+#if !defined(LSOF_STH_H)
+#define LSOF_STH_H
+
+#include "kernbits.h"
+#include <sys/types.h>
+
+typedef struct streams_queue {
+ KA_T q_qinfo; /* queue info pointer */
+ KA_T q_first;
+ KA_T q_last;
+ KA_T q_next;
+ KA_T q_link;
+ KA_T q_ptr; /* queue private data pointer */
+ ulong q_count;
+ ulong q_flag;
+ int q_minpsz;
+ int q_maxpsz;
+ ulong q_hiwat;
+ ulong q_lowat;
+ KA_T q_bandp;
+ u_char q_nband;
+ u_char q_pad1[3];
+ KA_T q_other;
+ KA_T queue_sth;
+} streams_queue_t;
+
+typedef struct sth_s {
+ streams_queue_t *sth_rq; /* pointer to stream's read queue
+ * structure chain */
+ streams_queue_t *sth_wq; /* pointer to stream's write queue
+ * structure chain */
+/*
+ * These q4 elements are ignored.
+
+ dev_t sth_dev;
+ ulong sth_read_mode;
+ ulong sth_write_mode;
+ int sth_close_wait_timeout;
+ u_char sth_read_error;
+ u_char sth_write_error;
+ short sth_prim_ack;
+ short sth_prim_nak;
+ short sth_ext_flags;
+ ulong sth_flags;
+ int sth_ioc_id;
+ KA_T sth_ioc_mp;
+ OSRQ sth_ioctl_osrq;
+ OSRQ sth_read_osrq;
+ OSRQ sth_write_osrq;
+ ulong sth_wroff;
+ int sth_muxid;
+ KA_T sth_mux_link;
+ KA_T sth_mux_top;
+ gid_t sth_pgid;
+ KA_T sth_session;
+ KA_T sth_next;
+ POLLQ sth_pollq;
+ SIGSQ sth_sigsq;
+ KA_T sth_ttyp;
+ int sth_push_cnt;
+ OSR sth_osr;
+ KA_T sth_pipestatp;
+ KA_T sth_ext_flags_lock;
+ uint qlen;
+ struct sth_func_reg sth_f_reg;
+ spu_t sth_bindspu;
+
+* Those q4 elements were ignored.
+*/
+
+} sth_s_t;
+
+#endif /* !defined(LSOF_STH_H) */
diff --git a/dialects/hpux/kmem/hpux11/tcp_s.h b/dialects/hpux/kmem/hpux11/tcp_s.h
new file mode 100644
index 0000000..41f21f6
--- /dev/null
+++ b/dialects/hpux/kmem/hpux11/tcp_s.h
@@ -0,0 +1,227 @@
+/*
+ * tcp_s.h for HP-UX 10.30 and above
+ *
+ * This header file defines the TCP connection structure, tpc_s, for lsof.
+ * Lsof gets the parameters of a TCP connection from tcp_s. Lsof locates a
+ * tcp_s structure by scanning the queue structure chain of a TCP stream,
+ * looking for a queue structure whose module name begins with TCP; that queue
+ * structure's private data pointer, q_ptr, addresses its associated tcp_s
+ * structure.
+ *
+ * V. Abell
+ * February, 1998
+ */
+
+#if !defined(LSOF_TCP_S_H)
+#define LSOF_TCP_S_H
+
+#include "kernbits.h"
+#include <sys/types.h>
+
+#define TCPS_CLOSED -6
+#define TCPS_IDLE -5
+#define TCPS_BOUND -4
+#define TCPS_LISTEN -3
+#define TCPS_SYN_SENT -2
+#define TCPS_SYN_RCVD -1
+#define TCPS_ESTABLISHED 0
+#define TCPS_CLOSE_WAIT 1
+#define TCPS_FIN_WAIT_1 2
+#define TCPS_CLOSING 3
+#define TCPS_LAST_ACK 4
+#define TCPS_FIN_WAIT_2 5
+#define TCPS_TIME_WAIT 6
+
+typedef struct iph_s { /* IP header */
+ u_char iph_version_and_hdr_length;
+ u_char iph_type_of_service;
+ u_char iph_length[2];
+ u_char iph_ident[2];
+ u_char iph_fragment_offset_and_flags[2];
+ u_char iph_ttl;
+ u_char iph_protocol;
+ u_char iph_hdr_checksum[2];
+ u_char iph_src[4]; /* source IP address */
+ u_char iph_dst[4]; /* destination IP address */
+} iph_t;
+
+typedef struct ipha_s {
+ u_char ipha_version_and_hdr_length;
+ u_char ipha_type_of_service;
+ uint16_t ipha_length;
+ uint16_t ipha_ident;
+ uint16_t ipha_fragment_offset_and_flags;
+ u_char ipha_ttl;
+ u_char ipha_protocol;
+ uint16_t ipha_hdr_checksum;
+ uint32_t ipha_src;
+ uint32_t ipha_dst;
+} ipha_t;
+
+typedef struct tcphdr_s {
+ uint16_t th_lport; /* local port */
+ uint16_t th_fport; /* foreign port */
+ u_char th_seq[4];
+ u_char th_ack[4];
+ u_char th_offset_and_rsrvd[1];
+ u_char th_flags[1];
+ u_char th_win[2];
+ u_char th_sum[2];
+ u_char th_urp[2];
+} tcph_t;
+
+typedef struct tcpsb {
+ uint32_t tcpsb_start;
+ uint32_t tcpsb_end;
+} tcpsb_t;
+
+typedef struct tcp_s {
+ int tcp_state; /* connection state */
+ KA_T tcp_rq;
+ KA_T tcp_wq;
+ KA_T tcp_xmit_head;
+ KA_T tcp_xmit_last;
+ uint tcp_unsent;
+ KA_T tcp_xmit_tail;
+ uint tcp_xmit_tail_unsent;
+ uint32_t tcp_snxt; /* send: next sequence number */
+ uint32_t tcp_suna; /* send: unacknowledged sequence nr */
+ uint tcp_swnd; /* send: window size */
+ uint tcp_swnd_shift;
+ uint tcp_cwnd;
+ u_long tcp_ibsegs;
+ u_long tcp_obsegs;
+ uint tcp_mss;
+ uint tcp_naglim;
+ int tcp_hdr_len; /* TCP header length */
+ int tcp_wroff_extra;
+ KA_T tcp_tcph; /* pointer to TCP header structure */
+ int tcp_tcp_hdr_len;
+ uint tcp_valid_bits;
+ int tcp_xmit_hiwater;
+ KA_T tcp_flow_mp;
+ int tcp_ms_we_have_waited;
+ KA_T tcp_timer_mp;
+ uint tcp_timer_interval;
+ uint32_t
+ tcp_urp_old : 1,
+ tcp_urp_sig_sent : 1,
+ tcp_hard_binding : 1,
+ tcp_hard_bound : 1,
+ tcp_priv_stream : 1,
+ tcp_fin_acked : 1,
+ tcp_fin_rcvd : 1,
+ tcp_fin_sent : 1,
+ tcp_ordrel_done : 1,
+ tcp_flow_stopped : 1,
+ tcp_detached : 1,
+ tcp_bind_pending : 1,
+ tcp_unbind_pending : 1,
+ tcp_use_ts_opts : 1,
+ tcp_reader_active : 1,
+ tcp_lingering : 1, /* SO_LINGER */
+ tcp_no_bind : 1,
+ tcp_sack_permitted : 1,
+ tcp_rexmitting : 1,
+ tcp_fast_rexmitting : 1,
+ tcp_ooofin_seen : 1,
+ tcp_smooth_rtt : 1,
+ tcp_main_flags_fill : 10;
+ uint32_t
+ tcp_so_debug : 1, /* SO_DEBUG */
+ tcp_dontroute : 1, /* SO_DONTROUTE */
+ tcp_broadcast : 1, /* SO_BROADCAST */
+ tcp_useloopback : 1, /* SO_USELOOPBACK */
+ tcp_reuseaddr : 1, /* SO_REUSEADDR */
+ tcp_reuseport : 1, /* SO_REUSEPORT */
+ tcp_oobinline : 1, /* SO_OOBONLINE */
+ tcp_xmit_hiwater_set : 1,
+ tcp_xmit_lowater_set : 1,
+ tcp_recv_hiwater_set : 1,
+ tcp_no_window_shift : 1,
+ tcp_window_shift_set : 1,
+ tcp_keepalive_kills : 1,
+ tcp_option_flags_fill : 19;
+ uint tcp_dupack_cnt;
+ uint32_t tcp_smax;
+ uint32_t tcp_rnxt;
+ uint tcp_rwnd; /* read: window size */
+ uint tcp_rwnd_shift;
+ uint tcp_rwnd_max;
+ int tcp_credit;
+ int tcp_credit_init;
+ KA_T tcp_reass_head;
+ KA_T tcp_reass_tail;
+ KA_T tcp_rcv_head;
+ KA_T tcp_rcv_tail;
+ uint tcp_rcv_cnt;
+ uint tcp_rcv_threshold;
+ uint tcp_cwnd_ssthresh;
+ uint tcp_cwnd_bytes_acked;
+ uint tcp_cwnd_max;
+ uint tcp_cwnd_init;
+ int tcp_rto;
+ int tcp_rtt_sa;
+ int tcp_rtt_sd;
+ uint tcp_swl1;
+ uint tcp_swl2;
+ uint32_t tcp_rack; /* read: acknowledged sequent number */
+ uint tcp_rack_cnt;
+ uint tcp_rack_cur_max;
+ uint tcp_rack_abs_max;
+ KA_T tcp_ts_ptr;
+ uint32_t tcp_ts_updated;
+ uint tcp_max_swnd;
+ uint tcp_sack_cnt;
+ tcpsb_t tcp_sack_blocks[4];
+ KA_T tcp_listener;
+ int tcp_xmit_lowater;
+ uint32_t tcp_irs;
+ uint32_t tcp_iss;
+ uint32_t tcp_fss;
+ uint32_t tcp_urg;
+ uint32_t tcp_ooofin_seq;
+ int tcp_ip_hdr_len;
+ int tcp_first_timer_threshold;
+ int tcp_second_timer_threshold;
+ uint32_t tcp_zero_win_suna;
+ int tcp_first_ctimer_threshold;
+ int tcp_second_ctimer_threshold;
+ int tcp_linger; /* SO_LINGER interval */
+ KA_T tcp_urp_mp;
+ KA_T tcp_eager_next;
+ KA_T tcp_eager_prev;
+ KA_T tcp_eager_data;
+ KA_T tcp_conn_ind_mp;
+ uint tcp_conn_ind_cnt;
+ uint tcp_conn_ind_max;
+ uint tcp_conn_ind_seqnum;
+ KA_T tcp_conn_ind_list;
+ KA_T tcp_pre_conn_ind_list;
+ int tcp_keepalive_intrvl; /* SO_KEEPALIVE interval */
+ int tcp_keepalive_detached_intrvl;
+ KA_T tcp_keepalive_mp;
+ int tcp_client_errno;
+ union {
+ iph_t tcp_u_iph; /* IP header */
+ ipha_t tcp_u_ipha;
+ char tcp_u_buf[128];
+ double tcp_u_aligner;
+ } tcp_u;
+ uint32_t tcp_sum;
+ uint32_t tcp_remote;
+ uint32_t tcp_bound_source;
+ uint tcp_last_sent_len;
+ KA_T tcp_cookie;
+ KA_T tcp_hnext_port;
+ KA_T tcp_ptphn_port;
+ KA_T tcp_hnext_listener;
+ KA_T tcp_ptphn_listener;
+ KA_T tcp_hnext_established;
+ KA_T tcp_ptphn_established;
+ uint tcp_mirg;
+ KA_T tcp_readers_next;
+ KA_T tcp_readers_ptpn;
+} tcp_s_t;
+
+#endif /* !defined(LSOF_TCP_S_H) */
diff --git a/dialects/hpux/kmem/hpux11/udp_s.h b/dialects/hpux/kmem/hpux11/udp_s.h
new file mode 100644
index 0000000..111c8db
--- /dev/null
+++ b/dialects/hpux/kmem/hpux11/udp_s.h
@@ -0,0 +1,79 @@
+/*
+ * udp_s.h for HP-UX 10.30 and above
+ *
+ * This header file defines the UDP connection structure, udp_s, for lsof.
+ * Lsof gets the parameters of a UDP connection from tcp_s. Lsof locates a
+ * tcp_s structure by scanning the queue structure chain of a UDP stream,
+ * looking for a queue structure whose module name begins with UDP; that queue
+ * structure's private data pointer, q_ptr, addresses its associated tcp_s
+ * structure.
+ *
+ * V. Abell
+ * February, 1998
+ */
+
+#if !defined(LSOF_UDP_S_H)
+#define LSOF_UDP_S_H
+
+#include "kernbits.h"
+
+typedef struct udp_s {
+ int udp_state; /* connection state */
+ KA_T udp_hash_next;
+ KA_T udp_ptphn;
+ uint16_t udp_checksum;
+ uint16_t udp_port[2]; /* source and destination ports */
+ uint32_t udp_src; /* source IP address */
+ uint32_t udp_dst; /* destination IP address */
+
+/*
+ * These q4 elements are ignored.
+
+ uint udp_hdr_length;
+ int udp_wroff_xtra;
+ uint udp_family;
+ uint udp_ip_snd_options_len;
+ KA_T udp_ip_snd_options;
+ int udp_linger;
+ union {
+ uchar udpu1_multicast_ttl;
+ u32 udpu1_pad;
+ } udp_u1;
+ NET32 udp_multicast_if_addr;
+ KA_T udp_udph;
+ uint udp_priv_stream;
+ uint udp_calc_checksum;
+ uint udp_debug;
+ uint udp_dontroute;
+ uint udp_broadcast;
+ uint udp_useloopback;
+ uint udp_reuseaddr;
+ uint udp_reuseport;
+ uint udp_multicast_loop;
+ uint udp_rx_icmp;
+ uint udp_rx_icmp_set;
+ uint udp_distribute;
+ uint udp_link_status;
+ uint udp_copyavoid;
+ uint udp_pad_to_bit_31;
+ union {
+ uint udpu2_wants_opts;
+ struct udpu2_flags_s udpu2_flags;
+ } udp_u2;
+ union {
+ char udpu3_iphc[72];
+ iph_t udpu3_iph;
+ u32 udpu3_ipharr[6];
+ uble udpu3_aligner;
+ } udp_u3;
+ u8 udp_pad2[2];
+ u8 udp_type_of_service;
+ u8 udp_ttl;
+ u8 udp_bound_ip[4];
+
+ * Those q4 elements were ignored.
+ */
+
+} udp_s_t;
+
+#endif /* !defined(LSOF_UDP_S_H) */
diff --git a/dialects/hpux/kmem/hpux11/vnode.h b/dialects/hpux/kmem/hpux11/vnode.h
new file mode 100644
index 0000000..5a386a1
--- /dev/null
+++ b/dialects/hpux/kmem/hpux11/vnode.h
@@ -0,0 +1,131 @@
+/*
+ * vnode.h for HP-UX 10.30 and above
+ *
+ * This header file defines the locklist, vnode and vattr structures for lsof
+ * in a manner that can be compiled at the application level.
+ *
+ * V. Abell <abe@purdue.edu>
+ * February, 1998
+ */
+
+#if !defined(LSOF_VNODE_H)
+#define LSOF_VNODE_H
+#define _SYS_VNODE_INCLUDED /* prevent inclusion of <sys/vnode.h> */
+
+#include "kernbits.h"
+#include <sys/types.h>
+#include <sys/sem_beta.h>
+#include <sys/time.h>
+
+#define VROOT 0x01
+
+typedef struct locklist { /* lock list */
+ KA_T ll_link;
+ short ll_count;
+ short ll_flags; /* flags */
+ KA_T ll_proc; /* proc structure address (unused) */
+ KA_T ll_kthreadp; /* thread structure address */
+
+ /* ll_start and ll_end should be typed off_t, but there's an
+ * unresolvable conflict between the size of the kernel's off_t
+ * and the 32 and 64 bit application off_t sizes.
+ */
+
+ int64_t ll_start; /* lock start */
+ int64_t ll_end; /* lock end */
+ short ll_type; /* lock type -- e.g., F_RDLCK or
+ * F_WRLCK */
+ KA_T ll_vp;
+ KA_T ll_waitq;
+ KA_T ll_fwd; /* forward link */
+ KA_T ll_rev;
+ KA_T ll_sib_fwd;
+ KA_T ll_sib_rev;
+} locklist_t;
+
+enum vtype {
+ VNON = 0,
+ VREG = 0x1,
+ VDIR = 0x2,
+ VBLK = 0x3,
+ VCHR = 0x4,
+ VLNK = 0x5,
+ VSOCK = 0x6,
+ VBAD = 0x7,
+ VFIFO = 0x8,
+ VFNWK = 0x9,
+ VEMPTYDIR = 0xa
+};
+
+enum vfstype {
+ VDUMMY = 0,
+ VNFS = 0x1,
+ VUFS = 0x2,
+ VDEV_VN = 0x3,
+ VNFS_SPEC = 0x4,
+ VNFS_BDEV = 0x5,
+ VNFS_FIFO = 0x6,
+ VCDFS = 0x7,
+ VVXFS = 0x8,
+ VDFS = 0x9,
+ VEFS = 0xa,
+ VLOFS = 0xb
+};
+
+typedef struct vnode {
+ u_short v_flag; /* flags -- e.g., VROOT */
+ u_short v_shlockc; /* shared lock count */
+ u_short v_exlockc; /* exclusive lock count */
+ u_short v_tcount;
+ int v_count;
+ KA_T v_vfsmountedhere;
+ KA_T v_op; /* operations switch */
+ KA_T v_socket;
+ KA_T v_stream; /* associated stream */
+ KA_T v_vfsp; /* pointer to virtual file system
+ * structure */
+ enum vtype v_type; /* vnode type */
+ dev_t v_rdev; /* device -- for VCHR and VBLK
+ * vnodes */
+ caddr_t v_data; /* private data -- i.e., pointer to
+ * successor node structure */
+ enum vfstype v_fstype;
+ KA_T v_vas;
+ vm_sema_t v_lock;
+ KA_T v_cleanblkhd;
+ KA_T v_dirtyblkhd;
+ int v_writecount;
+ KA_T v_locklist; /* locklist structure chain pointer */
+ int v_scount;
+ int32_t v_nodeid;
+ KA_T v_ncachedhd;
+ KA_T v_ncachevhd;
+ KA_T v_pfdathd;
+ u_int v_last_fsync;
+} vnode_t;
+
+typedef struct vattr {
+ enum vtype va_type;
+ u_short va_mode;
+ short va_nlink;
+ uid_t va_uid;
+ gid_t va_gid;
+ int32_t va_fsid;
+ int32_t va_nodeid; /* node ID number (e.g., inode
+ * number) */
+ off64_t va_size; /* file size */
+ int32_t va_blocksize;
+ struct timeval va_atime;
+ struct timeval va_mtime;
+ struct timeval va_ctime;
+ dev_t va_rdev;
+ blkcnt64_t va_blocks;
+ dev_t va_realdev;
+ u_short va_basemode;
+ u_short va_acl;
+ u_short va_sysVacl;
+ u_short va_dummy;
+ short va_fstype;
+} vattr_t;
+
+#endif /* !defined(LSOF_VNODE_H) */
diff --git a/dialects/hpux/kmem/machine.h b/dialects/hpux/kmem/machine.h
new file mode 100644
index 0000000..f98934d
--- /dev/null
+++ b/dialects/hpux/kmem/machine.h
@@ -0,0 +1,671 @@
+/*
+ * machine.h - /dev/kmem-based HP-UX definitions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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.
+ */
+
+
+/*
+ * $Id: machine.h,v 1.42 2010/07/29 16:03:09 abe Exp $
+ */
+
+
+#if !defined(LSOF_MACHINE_H)
+#define LSOF_MACHINE_H 1
+
+
+/*
+ * Do HP-UX 11 64 bit preparation.
+ */
+
+#if defined(HPUXKERNBITS) && HPUXKERNBITS>=64
+#define NLIST_TYPE nlist64
+#endif /* defined(HPUXKERNBITS) && HPUXKERNBITS>=64 */
+
+
+# if HPUXV>=1030
+#include <sys/types.h>
+#include "kernbits.h"
+# else /* HPUXV<1030 */
+# if HPUXV>=1020
+/*
+ * Since we need kernel structures from the HP-UX 10.20 <sys/vnode.h>, and
+ * since defining _KERNEL before #include'ing it causes a conflict between
+ * its FILE enum and the FILE struct definition in <stdio.h>, redefine FILE,
+ * #include <stdio.h>, revoke the FILE redefinition, define _KERNEL,
+ * #include <sys/vnode.h>, revoke the _KERNEL definition, and restore the
+ * FILE redefinition.
+ */
+
+# if defined(__GNUC__)
+/*
+ * Do gcc preparation.
+ */
+
+# if !defined(__STDC_EXT__)
+#define __STDC_EXT__
+# endif /* !defined(__STDC_EXT__) */
+#include <sys/_inttypes.h>
+# endif /* defined(__GNUC__) */
+
+#define FILE STDIO_FILE
+#include <stdio.h>
+#undef FILE
+#define _KERNEL 1
+#include <sys/vnode.h>
+#define FILE STDIO_FILE
+#undef _KERNEL
+# endif /* HPUXV>=1020 */
+# endif /* HPUXV>=1030 */
+
+
+/*
+ * CAN_USE_CLNT_CREATE is defined for those dialects where RPC clnt_create()
+ * can be used to obtain a CLIENT handle in lieu of clnttcp_create().
+ */
+
+#if HPUXV>=1020
+#define CAN_USE_CLNT_CREATE 1
+#endif /* HPUXV>=1020 */
+
+
+/*
+ * DEVDEV_PATH defines the path to the directory that contains device
+ * nodes.
+ */
+
+#define DEVDEV_PATH "/dev"
+
+
+/*
+ * GET_MAX_FD is defined for those dialects that provide a function other than
+ * getdtablesize() to obtain the maximum file descriptor number plus one.
+ */
+
+#define GET_MAX_FD get_max_fd
+
+
+/*
+ * HASAOPT is defined for those dialects that have AFS support; it specifies
+ * that the default path to an alternate AFS kernel name list file may be
+ * supplied with the -A <path> option.
+ */
+
+#define HASAOPT 1
+
+
+/*
+ * HASBLKDEV is defined for those dialects that want block device information
+ * recorded in BDevtp[].
+ */
+
+#define HASBLKDEV 1
+
+
+/*
+ * HASDCACHE is defined for those dialects that support a device cache
+ * file.
+ *
+ * HASENVDC defined the name of an environment variable that contains the
+ * device cache file path. The HASENVDC environment variable is ignored when
+ * the lsof process is setuid(root) or its real UID is 0.
+ *
+ * HASPERSDC defines the format for the last component of a personal device
+ * cache file path. The first will be the home directory of the real UID that
+ * executes lsof.
+ *
+ * HASPERSDCPATH defines the environment variable whose value is the middle
+ * component of the personal device cache file path. The middle component
+ * follows the home directory and precedes the results of applying HASPERSDC.
+ * The HASPERSDCPATH environment variable is ignored when the lsof process is
+ * setuid(root) or its real UID is 0.
+ *
+ * HASSYSDC defines a public device cache file path. When it's defined, it's
+ * used as the path from which to read the device cache.
+ *
+ * Consult the 00DCACHE and 00FAQ files of the lsof distribution for more
+ * information on device cache file path construction.
+ */
+
+#define HASDCACHE 1
+#define HASENVDC "LSOFDEVCACHE"
+#define HASPERSDC "%h/%p.lsof_%L"
+#define HASPERSDCPATH "LSOFPERSDCPATH"
+/* #define HASSYSDC "/your/choice/of/path" */
+
+
+/*
+ * HASCDRNODE is defined for those dialects that have CD-ROM nodes.
+ */
+
+/* #define HASCDRNODE 1 */
+
+
+/*
+ * HASFIFONODE is defined for those dialects that have FIFO nodes.
+ */
+
+/* #define HASFIFONODE 1 */
+
+
+/*
+ * HASFSINO is defined for those dialects that have the file system
+ * inode element, fs_ino, in the lfile structure definition in lsof.h.
+ */
+
+#define HASFSINO 1
+
+
+/*
+ * HASFSTRUCT is defined if the dialect has a file structure.
+ *
+ * FSV_DEFAULT defines the default set of file structure values to list.
+ * It defaults to zero (0), but may be made up of a combination of the
+ * FSV_* symbols from lsof.h.
+ *
+ * HASNOFSADDR -- has no file structure address
+ * HASNOFSFLAGS -- has no file structure flags
+ * HASNOFSCOUNT -- has no file structure count
+ * HASNOFSNADDR -- has no file structure node address
+ */
+
+#define HASFSTRUCT 1
+/* #define FSV_DEFAULT FSV_? | FSV_? | FSV_? */
+/* #define HASNOFSADDR 1 has no file structure address */
+/* #define HASNOFSFLAGS 1 has no file structure flags */
+/* #define HASNOFSCOUNT 1 has no file structure count */
+/* #define HASNOFSNADDR 1 has no file structure node address */
+
+
+/*
+ * HASGNODE is defined for those dialects that have gnodes.
+ */
+
+/* #define HASGNODE 1 */
+
+
+/*
+ * HASHSNODE is defined for those dialects that have High Sierra nodes.
+ */
+
+/* #define HASHSNODE 1 */
+
+
+/*
+ * HASINODE is defined for those dialects that have inodes and wish to
+ * use readinode() from node.c.
+ */
+
+/* #define HASINODE 1 */
+
+
+/*
+ * HASINTSIGNAL is defined for those dialects whose signal function returns
+ * an int.
+ */
+
+/* #define HASINTSIGNAL 1 */
+
+
+/*
+ * HASKERNIDCK is defined for those dialects that support the comparison of
+ * the build to running kernel identity.
+ */
+
+#define HASKERNIDCK 1
+
+
+/*
+ * HASKOPT is defined for those dialects that support the -k option of
+ * reading the kernel's name list from an optional file.
+ */
+
+#define HASKOPT 1
+
+
+/*
+ * HASLFILEADD is defined for those dialects that need additional elements
+ * in struct lfile. The HASLFILEADD definition is a macro that defines
+ * them. If any of the additional elements need to be preset in the
+ * alloc_lfile() function of proc.c, the SETLFILEADD macro may be defined
+ * to do that.
+ *
+ * If any additional elements need to be cleared in alloc_lfile() or in the
+ * free_proc() function of proc.c, the CLRLFILEADD macro may be defined to
+ * do that. Note that CLRLFILEADD takes one argument, the pointer to the
+ * lfile struct. The CLRLFILEADD macro is expected to expand to statements
+ * that are complete -- i.e., have terminating semi-colons -- so the macro is
+ * called without a terminating semicolon by proc.c.
+ *
+ * The HASXOPT definition may be used to select the conditions under which
+ * private lfile elements are used.
+ */
+
+/* #define HASLFILEADD int ... */
+/* #define CLRLFILEADD(lf) (lf)->... = (type)NULL; */
+/* #define SETLFILEADD Lf->... */
+
+
+/*
+ * HASMNTSTAT indicates the dialect supports the mount stat(2) result option
+ * in its l_vfs and mounts structures.
+ */
+
+/* #define HASMNTSTAT 1 */
+
+
+/*
+ * HASMNTSUP is defined for those dialects that support the mount supplement
+ * option.
+ */
+
+/* #define HASMNTSUP 1 */
+
+
+/*
+ * HASMOPT is defined for those dialects that support the reading of
+ * kernel memory from an alternate file.
+ */
+
+#define HASMOPT 1
+
+
+/*
+ * HASNCACHE is defined for those dialects that have a kernel name cache
+ * that lsof can search.
+ *
+ * NCACHELDPFX is a set of C commands to execute before calling ncache_load().
+ *
+ * NCACHELDSFX is a set of C commands to execute after calling ncache_load().
+ */
+
+#define HASNCACHE 1
+/* #define NCACHELDPFX ??? */
+/* #define NCACHELDSFX ??? */
+
+
+/*
+ * HASNCACHE is defined for those dialects that have a kernel name cache
+ * that lsof can search. A value of 1 directs printname() to prefix the
+ * cache value with the file system directory name; 2, avoid the prefix.
+ */
+
+#define HASNLIST 1
+
+
+/*
+ * HASPIPEFN is defined for those dialects that have a special function to
+ * process DTYPE_PIPE file structure entries. Its value is the name of the
+ * function.
+ *
+ * NOTE: don't forget to define a prototype for this function in dproto.h.
+ */
+
+/* #define HASPIPEFN process_pipe? */
+
+
+/*
+ * HASPIPENODE is defined for those dialects that have pipe nodes.
+ */
+
+/* #define HASPIPENODE 1 */
+
+
+/*
+ * HASPMAPENABLED is defined when the reporting of portmapper registration
+ * info is enabled by default.
+ */
+
+/* #define HASPMAPENABLED 1 */
+
+
+/*
+ * HASPPID is defined for those dialects that support identification of
+ * the parent process IDentifier (PPID) of a process.
+ */
+
+#define HASPPID 1
+
+
+/*
+ * HASPRINTDEV, HASPRINTINO, HASPRINTNM, HASPRINTOFF, and HASPRINTSZ
+ * define private dialect-specific functions for printing DEVice numbers,
+ * INOde numbers, NaMes, file OFFsets, and file SiZes. The functions are
+ * called from print_file().
+ */
+
+#define HASPRINTDEV print_dev
+/* #define HASPRINTINO print_ino? */
+/* #define HASPRINTNM print_nm? */
+/* #define HASPRINTOFF print_off? */
+/* #define HASPRINTSZ print_sz? */
+
+
+/*
+ * HASPRIVFILETYPE and PRIVFILETYPE are defined for dialects that have a
+ * file structure type that isn't defined by a DTYPE_* symbol. They are
+ * used in lib/prfp.c to select the type's processing.
+ *
+ * PRIVFILETYPE is the definition of the f_type value in the file struct.
+ *
+ * HASPRIVFILETYPE is the name of the processing function.
+ */
+
+/* #define HASPRIVFILETYPE process_shmf? */
+/* #define PRIVFILETYPE ?? */
+
+
+/*
+ * HASPRIVNMCACHE is defined for dialects that have a private method for
+ * printing cached NAME column values for some files. HASPRIVNAMECACHE
+ * is defined to be the name of the function.
+ *
+ * The function takes one argument, a struct lfile pointer to the file, and
+ * returns non-zero if it prints a name to stdout.
+ */
+
+/* #define HASPRIVNMCACHE <function name> */
+
+
+/*
+ * HASPRIVPRIPP is defined for dialects that have a private function for
+ * printing IP protocol names. When HASPRIVPRIPP isn't defined, the
+ * IP protocol name printing function defaults to printiprto().
+ */
+
+/* #define HASPRIVPRIPP 1 */
+
+
+/*
+ * HASPROCFS is defined for those dialects that have a proc file system --
+ * usually /proc and usually in SYSV4 derivatives.
+ *
+ * HASFSTYPE is defined as 1 for those systems that have a file system type
+ * string, st_fstype, in the stat() buffer; 2, for those systems that have a
+ * file system type integer in the stat() buffer, named MOUNTS_STAT_FSTYPE;
+ * 0, for systems whose stat(2) structure has no file system type member. The
+ * additional symbols MOUNTS_FSTYPE, RMNT_FSTYPE, and RMNT_STAT_FSTYPE may be
+ * defined in dlsof.h to direct how the readmnt() function in lib/rmnt.c
+ * preserves these stat(2) and getmntent(3) buffer values in the local mounts
+ * structure.
+ *
+ * The defined value is the string that names the file system type.
+ *
+ * The HASPROCFS definition usually must be accompanied by the HASFSTYPE
+ * definition and the providing of an fstype element in the local mounts
+ * structure (defined in dlsof.h).
+ *
+ * The HASPROCFS definition may be accompanied by the HASPINODEN definition.
+ * HASPINODEN specifies that searching for files in HASPROCFS is to be done
+ * by inode number.
+ */
+
+/* #define HASPROCFS "proc?" */
+/* #define HASFSTYPE 1 */
+/* #define HASPINODEN 1 */
+
+
+/*
+ * HASRNODE is defined for those dialects that have rnodes.
+ */
+
+#define HASRNODE 1
+
+
+/*
+ * Define HASSECURITY to restrict the listing of all open files to the
+ * root user. When HASSECURITY is defined, the non-root user may list
+ * only files whose processes have the same user ID as the real user ID
+ * (the one that its user logged on with) of the lsof process.
+ */
+
+/* #define HASSECURITY 1 */
+
+
+/*
+ * If HASSECURITY is defined, define HASNOSOCKSECURITY to allow users
+ * restricted by HASSECURITY to list any open socket files, provide their
+ * listing is selected by the "-i" option.
+ */
+
+/* #define HASNOSOCKSECURITY 1 */
+
+
+/*
+ * HASSETLOCALE is defined for those dialects that have <locale.h> and
+ * setlocale().
+ *
+ * If the dialect also has wide character support for language locales,
+ * HASWIDECHAR activates lsof's wide character support and WIDECHARINCL
+ * defines the header file (if any) that must be #include'd to use the
+ * mblen() and mbtowc() functions.
+ */
+
+#define HASSETLOCALE 1
+
+# if HPUXV>=1100
+#define HASWIDECHAR 1
+#endif /* HPUXV>=1100 */
+
+/* #define WIDECHARINCL <wchar.h> */
+
+
+/*
+ * HASSNODE is defined for those dialects that have snodes.
+ */
+
+# if HPUXV>=900
+#define HASSNODE 1
+# endif /* HPUXV>=900 */
+
+
+/*
+ * HASTASKS is defined for those dialects that have task reporting support.
+ */
+
+/* #define HASTASKS 1 */
+
+
+/*
+ * HASSOOPT, HASSOSTATE and HASTCPOPT define the availability of information
+ * on socket options (SO_* symbols), socket states (SS_* symbols) and TCP
+ * options.
+ */
+
+#if HPUXV>=1030
+# if HPUXV>=1100
+#define HASSOOPT 1 /* has socket option information */
+# endif /* HPUXV>=1100 */
+/* #define HASSOSTATE 1 has socket state information */
+#define HASTCPOPT 1 /* has TCP options or flags */
+#endif /* HPUXV>=1030 */
+
+
+/*
+ * Define HASSPECDEVD to be the name of a function that handles the results
+ * of a successful stat(2) of a file name argument.
+ *
+ * For example, HASSPECDEVD() for Darwin makes sure that st_dev is set to
+ * what stat("/dev") returns -- i.e., what's in DevDev.
+ *
+ * The function takes two arguments:
+ *
+ * 1: pointer to the full path name of file
+ * 2: pointer to the stat(2) result
+ *
+ * The function returns void.
+ */
+
+/* #define HASSPECDEVD process_dev_stat */
+
+
+/*
+ * HASSTREAMS is defined for those dialects that support streams.
+ */
+
+/* #define HASSTREAMS 1 */
+
+
+/*
+ * HASTCPTPIQ is defined for dialects where it is possible to report the
+ * TCP/TPI Recv-Q and Send-Q values produced by netstat.
+ */
+
+#define HASTCPTPIQ 1
+
+
+/*
+ * HASTCPTPIW is defined for dialects where it is possible to report the
+ * TCP/TPI send and receive window sizes produced by netstat.
+ */
+
+# if HPUXV>=1030
+#define HASTCPTPIW 1
+# endif /* HPUXV>=1030 */
+
+
+/*
+ * HASTMPNODE is defined for those dialects that have tmpnodes.
+ */
+
+/* #define HASTMPNODE 1 */
+
+
+/*
+ * HASVNODE is defined for those dialects that use the Sun virtual file system
+ * node, the vnode. BSD derivatives usually do; System V derivatives prior to
+ * R4 usually don't.
+ */
+
+#define HASVNODE 1
+
+
+/*
+ * HASXOPT is defined for those dialects that have an X option. It
+ * defines the text for the usage display. HASXOPT_VALUE defines the
+ * option's default binary value -- 0 or 1.
+ */
+
+/* #define HASXOPT "help text for X option" */
+/* #define HASXOPT_VALUE 1 */
+
+
+/*
+ * INODETYPE and INODEPSPEC define the internal node number type and its
+ * printf specification modifier. These need not be defined and lsof.h
+ * can be allowed to define defaults.
+ *
+ * These are defined here, because they must be used in dlsof.h.
+ */
+
+# if HPUXV>=1000
+#define INODETYPE unsigned long long
+ /* inode number internal storage type */
+#define INODEPSPEC "ll" /* INODETYPE printf specification
+ * modifier */
+# endif /* HPUXV>=1000 */
+
+
+/*
+ * UID_ARG defines the size of a User ID number when it is passed
+ * as a function argument.
+ */
+
+#define UID_ARG uid_t
+
+
+/*
+ * Each USE_LIB_<function_name> is defined for dialects that use the
+ * <function_name> in the lsof library.
+ *
+ * Note: other definitions and operations may be required to condition the
+ * library function source code. They may be found in the dialect dlsof.h
+ * header files.
+ */
+
+#define USE_LIB_CKKV 1 /* ckkv.c */
+/* #define USE_LIB_COMPLETEVFS 1 cvfs.c */
+#define USE_LIB_FIND_CH_INO 1 /* fino.c */
+#define USE_LIB_IS_FILE_NAMED 1 /* isfn.c */
+#define USE_LIB_LKUPDEV 1 /* lkud.c */
+#define USE_LIB_PRINTDEVNAME 1 /* pdvn.c */
+/* #define USE_LIB_PROCESS_FILE 1 prfp.c */
+
+# if HPUXV<1030
+#define USE_LIB_PRINT_TCPTPI 1 /* ptti.c */
+# else /* HPUXV>=1030 */
+/* #define USE_LIB_PRINT_TCPTPI 1 ptti.c */
+# endif /* HPUXV<1030 */
+
+#define USE_LIB_READDEV 1 /* rdev.c */
+#define USE_LIB_READMNT 1 /* rmnt.c */
+/* #define USE_LIB_REGEX 1 regex.c */
+/* #define USE_LIB_RNAM 1 rnam.c */
+#define USE_LIB_RNCH 1 /* rnch.c */
+/* #define USE_LIB_RNMH 1 rnmh.c */
+
+# if HPUXV<1030
+#define USE_LIB_SNPF 1 /* snpf.c */
+# else /* HPUXV>=1030 */
+#define snpf snprintf /* use the system's snprintf() */
+# endif /* HPUXV<1030 */
+
+
+/*
+ * WARNDEVACCESS is defined for those dialects that should issue a warning
+ * when lsof can't access /dev (or /device) or one of its sub-directories.
+ * The warning can be inhibited by the lsof caller with the -w option.
+ */
+
+/* #define WARNDEVACCESS 1 */
+
+
+/*
+ * WARNINGSTATE is defined for those dialects that want to suppress all lsof
+ * warning messages.
+ */
+
+/* #define WARNINGSTATE 1 warnings are enabled by default */
+
+
+/*
+ * WILLDROPGID is defined for those dialects whose lsof executable runs
+ * setgid(not_real_GID) and whose setgid power can be relinquished after
+ * the dialect's initialize() function has been executed.
+ */
+
+#define WILLDROPGID 1
+
+
+/*
+ * zeromem is a macro that uses bzero or memset.
+ */
+
+#define zeromem(a, l) bzero(a, l)
+
+#endif /* !defined(LSOF_MACHINE_H) */
diff --git a/dialects/hpux/pstat/Makefile b/dialects/hpux/pstat/Makefile
new file mode 100644
index 0000000..a5fea79
--- /dev/null
+++ b/dialects/hpux/pstat/Makefile
@@ -0,0 +1,150 @@
+
+# HP-UX PSTAT-based Makefile
+#
+# $Id: Makefile,v 1.6 2008/05/09 12:51:46 abe Exp $
+
+PROG= lsof
+
+BIN= ${DESTDIR}
+
+DOC= ${DESTDIR}
+
+I=/usr/include
+S=/usr/include/sys
+L=/usr/include/local
+P=
+
+CDEF=
+CDEFS= ${CDEF} ${CFGF}
+INCL= ${DINC}
+CFLAGS= ${CDEFS} ${INCL} ${DEBUG}
+
+GRP=
+
+HDR= lsof.h lsof_fields.h dlsof.h machine.h proto.h dproto.h
+
+SRC= dfile.c dproc.c dsock.c dstore.c \
+ arg.c main.c misc.c node.c print.c proc.c store.c usage.c util.c
+
+OBJ= dfile.o dproc.o dsock.o dstore.o \
+ arg.o main.o misc.o node.o print.o proc.o store.o usage.o util.o
+
+MAN= lsof.8
+
+OTHER=
+
+SHELL= /bin/sh
+
+SOURCE= Makefile ${OTHER} ${MAN} ${HDR} ${SRC}
+
+all: ${PROG}
+
+${PROG}: ${LIB} ${P} ${OBJ}
+ ${CC} -o $@ ${CFLAGS} ${OBJ} ${CFGL}
+
+clean: FRC
+ rm -f Makefile.bak ${PROG} a.out core errs lint.out tags *.o version.h
+ rm -f machine.h.old new_machine.h
+ (cd lib; ${MAKE} -f Makefile.skel clean)
+
+install: all FRC
+ @echo ''
+ @echo 'Please write your own install rule. Lsof should be installed'
+ @echo 'setuid to root if you wish any lsof user to be able to examine'
+ @echo 'all open files. Your install rule actions might look something'
+ @echo 'like this:'
+ @echo ''
+ @echo ' install -m 4xxx -o root -g <group> $${PROG} $${BIN}'
+ @echo ' install -m 444 $${MAN} $${DOC}'
+ @echo ''
+ @echo 'You will have to complete the 4xxx modes, the <group> value,'
+ @echo 'and the skeletons for the BIN and DOC strings, given at the'
+ @echo 'beginning of this Makefile, e.g.,'
+ @echo ''
+ @echo ' BIN= $${DESTDIR}/usr/local/etc'
+ @echo ' DOC= $${DESTDIR}/usr/man/man8'
+ @echo ' GRP= sys'
+ @echo ''
+
+${LIB}: FRC
+ (cd lib; ${MAKE} DEBUG="${DEBUG}" CFGF="${CFGF}")
+
+version.h: FRC
+ @echo Constructing version.h
+ @rm -f version.h
+ @echo '#define LSOF_BLDCMT "${LSOF_BLDCMT}"' > version.h;
+ @echo '#define LSOF_CC "${CC}"' >> version.h
+ @echo '#define LSOF_CCV "${CCV}"' >> version.h
+ @echo '#define LSOF_CCDATE "'`date`'"' >> version.h
+ @echo '#define LSOF_CCFLAGS "'`echo ${CFLAGS} | sed 's/\\\\(/\\(/g' | sed 's/\\\\)/\\)/g' | sed 's/"/\\\\"/g'`'"' >> version.h
+ @echo '#define LSOF_CINFO "${CINFO}"' >> version.h
+ @if [ "X${LSOF_HOST}" = "X" ]; then \
+ echo '#define LSOF_HOST "'`uname -n`'"' >> version.h; \
+ else \
+ if [ "${LSOF_HOST}" = "none" ]; then \
+ echo '#define LSOF_HOST ""' >> version.h; \
+ else \
+ echo '#define LSOF_HOST "${LSOF_HOST}"' >> version.h; \
+ fi \
+ fi
+ @echo '#define LSOF_LDFLAGS "${CFGL}"' >> version.h
+ @if [ "X${LSOF_LOGNAME}" = "X" ]; then \
+ echo '#define LSOF_LOGNAME "${LOGNAME}"' >> version.h; \
+ else \
+ if [ "${LSOF_LOGNAME}" = "none" ]; then \
+ echo '#define LSOF_LOGNAME ""' >> version.h; \
+ else \
+ echo '#define LSOF_LOGNAME "${LSOF_LOGNAME}"' >> version.h; \
+ fi; \
+ fi
+ @if [ "X${LSOF_SYSINFO}" = "X" ]; then \
+ echo '#define LSOF_SYSINFO "'`uname -a`'"' >> version.h; \
+ else \
+ if [ "${LSOF_SYSINFO}" = "none" ]; then \
+ echo '#define LSOF_SYSINFO ""' >> version.h; \
+ else \
+ echo '#define LSOF_SYSINFO "${LSOF_SYSINFO}"' >> version.h; \
+ fi \
+ fi
+ @if [ "X${LSOF_USER}" = "X" ]; then \
+ echo '#define LSOF_USER "${USER}"' >> version.h; \
+ else \
+ if [ "${LSOF_USER}" = "none" ]; then \
+ echo '#define LSOF_USER ""' >> version.h; \
+ else \
+ echo '#define LSOF_USER "${LSOF_USER}"' >> version.h; \
+ fi \
+ fi
+ @@sed '/VN/s/.ds VN \(.*\)/#define LSOF_VERSION "\1"/' < version >> version.h
+
+FRC:
+
+# DO NOT DELETE THIS LINE - make depend DEPENDS ON IT
+
+dfile.o: ${HDR} dfile.c
+
+dproc.o: ${HDR} dproc.c
+
+dsock.o: ${HDR} dsock.c
+
+dstore.o: ${HDR} dstore.c
+
+arg.o: ${HDR} arg.c
+
+main.o: ${HDR} main.c
+
+misc.o: ${HDR} misc.c
+
+node.o: ${HDR} node.c
+
+print.o: ${HDR} print.c
+
+proc.o: ${HDR} proc.c
+
+store.o: ${HDR} store.c
+
+usage.o: ${HDR} version.h usage.c
+
+util.o: ${HDR} util.c
+
+# *** Do not add anything here - It will go away. ***
diff --git a/dialects/hpux/pstat/Mksrc b/dialects/hpux/pstat/Mksrc
new file mode 100755
index 0000000..0840e1a
--- /dev/null
+++ b/dialects/hpux/pstat/Mksrc
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Mksrc - make pstat-based HP-UX source files
+#
+# WARNING: This script assumes it is running from the main directory
+# of the lsof, version 4 distribution.
+#
+# One environment variable applies:
+#
+# LSOF_MKC is the method for creating the source files.
+# It defaults to "ln -s". A common alternative is "cp".
+#
+# $Id: Mksrc,v 1.1 99/05/25 13:04:50 abe Exp $
+
+
+D=dialects/hpux/pstat
+L="dfile.c dlsof.h dfile.c dproc.c dproto.h dsock.c dstore.c machine.h"
+
+for i in $L
+do
+ rm -f $i
+ $LSOF_MKC $D/$i $i
+ echo "$LSOF_MKC $D/$i $i"
+done
diff --git a/dialects/hpux/pstat/dfile.c b/dialects/hpux/pstat/dfile.c
new file mode 100644
index 0000000..b68ffdf
--- /dev/null
+++ b/dialects/hpux/pstat/dfile.c
@@ -0,0 +1,806 @@
+/*
+ * dfile.c -- pstat-based HP-UX file 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"
+
+
+#if defined(HASNCACHE)
+/*
+ * Local definitions
+ */
+
+#define DNLCINCR 2048 /* DNLC read increment */
+
+#define NFSIDH 256 /* file system ID hash count
+ * -- MUST BE A POWER OF TWO!!! */
+#define NFSID sizeof(struct psfsid)
+ /* size of psfsid structure */
+#define NL_NC sizeof(struct l_nc)
+ /* size of l_nc structure */
+#define NPSTM sizeof(struct pst_mpathnode)
+ /* size of pst_mpathnode */
+
+
+/*
+ * Local structure definitions
+ */
+
+struct l_nc { /* local name cache */
+ struct psfileid id; /* node's PSTAT ID */
+ struct psfileid par; /* parent's PSTAT ID */
+ struct l_nc *pl; /* local parent name cache entry --
+ * NULL if not found or not yet
+ * accessed (see pls) */
+ int pls; /* status of pl: 0 = not accessed
+ * 1 = accessed */
+ int nl; /* name length */
+ char *nm; /* name */
+ struct l_nc *next; /* next hash bucket link */
+};
+
+struct l_fic { /* file system ID cache */
+ struct psfsid fsid; /* file system ID */
+ int nc; /* files cached for file system */
+ struct l_fic *next; /* next hash bucket link */
+};
+
+
+/*
+ * Local static variables
+ */
+
+static int Nceh; /* number of Nchash entries allocated */
+static struct l_nc **Nchash = (struct l_nc **)NULL;
+ /* the name cache hash buckets */
+static int Ncmask; /* power of two mask for the name
+ * cache -- sized from Nc */
+static int Ndnlc; /* number of DNLC entries via
+ * pst_dynamic.psd_dnlc_size */
+static struct l_fic **Ncfsid = (struct l_fic **)NULL;
+ /* the file system hash buckets */
+static struct pst_fid Nzpf; /* zeroed pst_fid (for memcmp()) */
+static struct psfileid Nzps; /* zeroed psfilid (for memcmp()) */
+static int Nzpfs = 0; /* Nzpf status: 1 = zeroed */
+static int Nzpss = 0; /* Nzps status: 1 = zeroed */
+
+
+/*
+ * Local macros
+ */
+
+#define HASHFSID(i) (Ncfsid + \
+ (((int)(((((struct psfsid *)i)->psfs_id * 31415) << 3)&0xfffffff) \
+ + (int)((((((struct psfsid *)i)->psfs_type * 31415) << 5)&0xfffffff))) \
+ & (NFSIDH - 1)))
+#define HASHPSFILEID(p) (Nchash + \
+ (((int)(((int)((((struct psfileid *)p)->psf_fsid.psfs_id * 31415) << 3)\
+ & 0xfffffff) \
+ + (int)(((((struct psfileid *)p)->psf_fsid.psfs_type * 31415) << 5) \
+ & 0xfffffff) \
+ + (int)(((((struct psfileid *)p)->psf_fileid * 31415) << 7) \
+ & 0xfffffff))) \
+ & Ncmask))
+
+
+/*
+ * Local function prototypes
+ */
+
+_PROTOTYPE(static struct l_nc *ncache_addr,(struct psfileid *ps));
+_PROTOTYPE(static void ncache_free,(void));
+_PROTOTYPE(static int ncache_isroot,(struct psfileid *ps));
+_PROTOTYPE(static void ncache_size,(void));
+#endif /* defined(HASNCACHE) */
+
+
+#if defined(HASIPv6)
+/*
+ * gethostbyname2() -- an RFC2133-compatible get-host-by-name-two function
+ * to get AF_INET and AF_INET6 addresses from host names,
+ * using the gethostbyname() and RFC2553-compatible
+ * getipnodebyname() functions
+ */
+
+extern struct hostent *
+gethostbyname2(nm, prot)
+ char *nm; /* host name */
+ int prot; /* protocol -- AF_INET or AF_INET6 */
+{
+ int err;
+
+ if (prot == AF_INET) {
+
+ /*
+ * This shouldn't be necessary if /etc/nsswitch.conf is correct, but
+ * it's a good fail-safe in case /etc/nsswitch.conf is missing or
+ * incorrect.
+ */
+ return(gethostbyname(nm));
+ }
+ return(getipnodebyname(nm, prot, 0, &err));
+}
+#endif /* defined(HASIPv6) */
+
+
+/*
+ * get_max_fd() -- get maximum file descriptor plus one
+ */
+
+int
+get_max_fd()
+{
+ struct rlimit r;
+
+ if (getrlimit(RLIMIT_NOFILE, &r))
+ return(-1);
+ return(r.rlim_cur);
+}
+
+
+#if defined(HASNCACHE)
+
+
+/*
+ * ncache_addr() -- get ncache entry address
+ */
+
+static struct l_nc *
+ncache_addr(ps)
+ struct psfileid *ps; /* parent's psfileid */
+{
+ struct l_nc **hp, *lc;
+
+ for (hp = HASHPSFILEID(ps), lc = *hp; lc; lc = lc->next) {
+ if (!memcmp((void *)ps, (void *)&lc->id, sizeof(struct psfileid)))
+ return(lc);
+ }
+ return((struct l_nc *)NULL);
+}
+
+
+/*
+ * ncache_alloc() -- allocate name cache space
+ */
+
+static void
+ncache_alloc()
+{
+ if (Nchash || Ncfsid)
+ ncache_free();
+ (void) ncache_size();
+ if (!(Nchash = (struct l_nc **)calloc(Nceh, sizeof(struct l_nc *))))
+ {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d local name cache entries\n", Pn, Nceh);
+ Exit(1);
+ }
+ if (Ncfsid)
+ return;
+ if (!(Ncfsid = (struct l_fic **)calloc(NFSIDH, sizeof(struct l_fic *))))
+ {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d local file system cache entries\n",
+ Pn, NFSIDH);
+ Exit(1);
+ }
+}
+
+
+/*
+ * ncache_free() -- free previous ncache allocations
+ */
+
+static void
+ncache_free()
+{
+ int i;
+ struct l_fic **fh, *fp, *fx;
+ struct l_nc **nh, *np, *nx;
+
+ if (Ncfsid) {
+
+ /*
+ * Free file system ID hash bucket contents.
+ */
+ for (fh = Ncfsid, i = 0; i < NFSIDH; fh++, i++) {
+ for (fp = *fh; fp; fp = fx) {
+ fx = fp->next;
+ (void) free((MALLOC_P *)fp);
+ }
+ Ncfsid[i] = (struct l_fic *)NULL;
+ }
+ }
+ if (Nchash) {
+
+ /*
+ * Free name cache.
+ */
+ for (i = 0, nh = Nchash; i < Nceh; i++, nh++) {
+ for (np = *nh; np; np = nx) {
+ nx = np->next;
+ if (np->nm)
+ (void) free((MALLOC_P *)np->nm);
+ (void) free((MALLOC_P *)np);
+ }
+ }
+ (void) free((MALLOC_P *)Nchash);
+ Nchash = (struct l_nc **)NULL;
+ }
+}
+
+
+/*
+ * ncache_isroot() -- does psfileid represent the root of a file system?
+ */
+
+static int
+ncache_isroot(ps)
+ struct psfileid *ps; /* psfileid */
+{
+ if (!ps->psf_fsid.psfs_id && !ps->psf_fsid.psfs_type
+ && ps->psf_fileid == -1)
+ return(1);
+
+# if defined(HASFSINO)
+ if (!Lf->fs_ino || (Lf->inp_ty != 1) || !Lf->dev_def)
+ return(0);
+ if ((Lf->dev == (dev_t)ps->psf_fsid.psfs_id)
+ && (Lf->fs_ino == (unsigned long)ps->psf_fileid))
+ return(1);
+# endif /* defined(HASFSINO) */
+
+ return(0);
+}
+
+
+/*
+ * ncache_load() -- load name cache
+ */
+
+void
+ncache_load()
+{
+ if (!Fncache)
+ return;
+ (void) ncache_alloc();
+ if (!Nzpfs) {
+ (void)memset((void *)&Nzpf, 0, sizeof(Nzpf));
+ Nzpfs = 1;
+ }
+ if (!Nzpss) {
+ (void)memset((void *)&Nzps, 0, sizeof(Nzps));
+ Nzpss = 1;
+ }
+}
+
+
+/*
+ * ncache_loadfs() -- load the name cache for a file system
+ */
+
+struct l_fic *
+ncache_loadfs(fsid, fh)
+ struct psfsid *fsid; /* ID of file system to add */
+ struct l_fic **fh; /* Ncfsid hash bucket */
+{
+ char *cp;
+ struct l_fic *f;
+ int i, nl, nr;
+ struct pst_mpathnode mp[DNLCINCR];
+ struct l_nc **nh, *nn, *nt, *ntp;
+ int x = 0;
+/*
+ * Allocate a new file system pointer structure and link it to its bucket.
+ */
+ if (!(f = (struct l_fic *)malloc(sizeof(struct l_fic)))) {
+ (void) fprintf(stderr, "%s: no fsid structure space\n", Pn);
+ Exit(1);
+ }
+ f->fsid = *fsid;
+ f->nc = 0;
+ f->next = *fh;
+ *fh = f;
+ while ((nr = pstat_getmpathname(&mp[0], NPSTM, DNLCINCR, x, fsid)) > 0)
+ {
+ x = mp[nr - 1].psr_idx + 1;
+ for (i = 0; i < nr; i++) {
+
+ /*
+ * Ignore NUL names, ".", and "..".
+ */
+ if (!(nl = (int)strlen(mp[i].psr_name)))
+ continue;
+ if ((nl < 3) && (mp[i].psr_name[0] == '.')) {
+ if ((nl == 1) || (mp[i].psr_name[1] == '.'))
+ continue;
+ }
+ /*
+ * Allocate name and name cache structure space.
+ */
+ if (!(cp = (char *)malloc((MALLOC_S)(nl + 1)))) {
+ (void) fprintf(stderr,
+ "%s: no name entry space (%d) for:%s\n",
+ Pn, nl + 1, mp[i].psr_name);
+ Exit(1);
+ }
+ if (!(nn = (struct l_nc *)malloc(sizeof(struct l_nc)))) {
+ (void) fprintf(stderr,
+ "%s: no name cache entry space (%d) for: %s\n",
+ Pn, (int)sizeof(struct l_nc), mp[i].psr_name);
+ Exit(1);
+ }
+ /*
+ * Fill in name cache entry, complete with name and name length.
+ */
+ (void) snpf(cp, nl + 1, "%s", mp[i].psr_name);
+ nn->id = mp[i].psr_file;
+ nn->par = mp[i].psr_parent;
+ nn->nm = cp;
+ nn->nl = nl;
+ nn->pl = nn->next = (struct l_nc *)NULL;
+ nn->pls = 0;
+ nh = HASHPSFILEID(&mp[i].psr_file);
+ /*
+ * Skip to the end of the hash bucket chain, looking for
+ * duplicates along the way.
+ */
+ for (nt = *nh, ntp = (struct l_nc *)NULL;
+ nt;
+ ntp = nt, nt = nt->next)
+ {
+ if (memcmp((void *)&nt->id, (void *)&nn->id, NL_NC) == 0)
+ break;
+ }
+ if (nt) {
+
+ /*
+ * Remove a duplicate.
+ */
+ if (ntp)
+ ntp = nt->next;
+ else
+ *nh = nt->next;
+ (void) free((MALLOC_P *)nt->nm);
+ (void) free((MALLOC_P *)nt);
+ (void) free((MALLOC_P *)nn->nm);
+ (void) free((MALLOC_P *)nn);
+ } else {
+
+ /*
+ * Link a new entry.
+ */
+ if (ntp)
+ ntp->next = nn;
+ else
+ *nh = nn;
+ f->nc++;
+ }
+ }
+ if (nr < DNLCINCR)
+ break;
+ }
+ return(f);
+}
+
+
+/*
+ * ncache_lookup() -- look up a node's name in the kernel's name cache
+ */
+
+char *
+ncache_lookup(buf, blen, fp)
+ char *buf; /* receiving name buffer */
+ int blen; /* receiving buffer length */
+ int *fp; /* full path reply */
+{
+ char *cp = buf;
+ int ef;
+ struct l_fic **fh, *fs;
+ struct l_nc *lc;
+ int nl, rlen;
+ char *pc;
+
+ *cp = '\0';
+ *fp = 0;
+
+# if defined(HASFSINO)
+/*
+ * If the entry has an inode number that matches the inode number of the
+ * file system mount point, return an empty path reply. That tells the
+ * caller that the already-printed system mount point name is sufficient.
+ */
+ if (Lf->inp_ty == 1 && Lf->fs_ino && Lf->inode == Lf->fs_ino)
+ return(cp);
+# endif /* defined(HASFSINO) */
+
+/*
+ * See if cache has been loaded for this pfsid. Don't try to load if cache
+ * loading has been inhibited with -C, or unless the real or effective UID of
+ * this process is root.
+ */
+ if ((!Myuid || Setuidroot) && Fncache) {
+ for (fh = HASHFSID(&Lf->psfid.psf_fsid), fs = *fh;
+ fs;
+ fs = fs->next)
+ {
+ if (memcmp((void *)&fs->fsid, (void *)&Lf->psfid.psf_fsid,
+ NFSID)
+ == 0)
+ break;
+ }
+ if (!fs)
+ fs = ncache_loadfs(&Lf->psfid.psf_fsid, fh);
+ } else
+ fs = (struct l_fic *)NULL;
+/*
+ * Search the cache for an entry whose psfileid matches.
+ */
+ if (!fs || !fs->nc || !(lc = ncache_addr(&Lf->psfid))) {
+
+ /*
+ * If the node has no cache entry, see if it's the root of the file
+ * system.
+ */
+
+# if defined(HASFSINO)
+ if (Lf->fs_ino && (Lf->inp_ty == 1) && (Lf->fs_ino == Lf->inode))
+ return(cp);
+# endif /* defined(HASFSINO) */
+
+ /*
+ * If the file system's cache couldn't be loaded -- e.g., this lsof
+ * process lacks permission to load it or cache lookup is inhibited
+ * with -C -- but the UID of the file's process matches the UID of the
+ * lsof process, see if it's possible to read the single path name for
+ * this particular file. (The file must have a non-zero opaque ID.)
+ */
+ if (!fs) {
+ if (Fncache
+ && (Myuid == Lp->uid)
+ && memcmp((void *)&Lf->opfid, (void *)&Nzpf, sizeof(Nzpf))
+ && (nl = pstat_getpathname(buf, (blen - 1), &Lf->opfid)) > 0)
+ {
+ buf[nl] = '\0';
+ if (*buf == '/')
+ *fp = 1;
+ return(buf);
+ }
+ }
+ return((char *)NULL);
+ }
+ if (ncache_isroot(&lc->id)) {
+
+ /*
+ * If the node is the root of the file system, return a response
+ * that will cause the root directory to be displayed.
+ */
+ return(cp);
+ }
+/*
+ * Start the path assembly.
+ */
+ if ((nl = lc->nl) > (blen - 1))
+ return((char *)NULL);
+ cp = buf + blen - nl - 1;
+ rlen = blen - nl - 1;
+ (void) snpf(cp, nl + 1, "%s", lc->nm);
+/*
+ * Look up the name cache entries that are parents of the node address.
+ * Quit when:
+ *
+ * there's no parent;
+ * the file system root is reached;
+ * the name length is too large to fit in the receiving buffer.
+ */
+ for (ef = 0; !ef;) {
+ if (!lc->pl) {
+ if (!lc->pls) {
+
+ /*
+ * If there is a parent, look up its Ncache address;
+ * otherwise quit on an incomplete path assembly.
+ */
+ if (memcmp((void *)&lc->par, (void *)&Nzps, sizeof(Nzps))) {
+ lc->pl = ncache_addr(&lc->par);
+ lc->pls = 1;
+ } else
+ break;
+ }
+ }
+ if (ncache_isroot(&lc->par)) {
+
+ /*
+ * If the parent entry is the file system root, enter the file
+ * system root directory, and indicate that the assembly should
+ * stop after this entry.
+ */
+ if (!(pc = Lf->fsdir))
+ break;
+ nl = (int)strlen(pc);
+ ef = 1;
+ } else {
+
+ /*
+ * Use the parent link if it exists; otherwise exit on an
+ * incomplete path assembly.
+ */
+ if (!(lc = lc->pl))
+ break;
+ pc = lc->nm;
+ nl = lc->nl;
+ }
+ /*
+ * Prefix the next path component. Intersperse a '/' if the
+ * component doesn't end in one.
+ */
+ if (!nl)
+ break;
+ if (pc[nl - 1] != '/') {
+ if (1 > rlen)
+ break;
+ *(cp - 1) = '/';
+ cp--;
+ rlen--;
+ }
+ if (nl > rlen)
+ break;
+ (void) strncpy((cp - nl), pc, nl);
+ cp -= nl;
+ rlen -= nl;
+ if (ef) {
+
+ /*
+ * If the file system root directory was just prefixed, return
+ * a full-path indication.
+ */
+ *fp = 1;
+ break;
+ }
+ }
+ return(cp);
+}
+
+
+/*
+ * ncache_size() -- get DNLC size
+ */
+
+static void
+ncache_size()
+{
+ struct pst_dynamic pd;
+
+ if (pstat_getdynamic(&pd, sizeof(pd), 1, 0) != 1) {
+ (void) fprintf(stderr, "%s: can't get dynamic status\n", Pn);
+ Exit(1);
+ }
+ Ndnlc = (int)pd.psd_dnlc_size;
+ for (Nceh = 1; Nceh < (Ndnlc + Ndnlc); Nceh <<= 1)
+ ;
+ Ncmask = Nceh - 1;
+}
+#endif /* defined(HASNCACHE) */
+
+
+/*
+ * print_dev() -- print device
+ */
+
+char *
+print_dev(lf, dev)
+ struct lfile *lf; /* file whose device is to be printed */
+ dev_t *dev; /* device to be printed */
+{
+ static char buf[128];
+
+ (void) snpf(buf, sizeof(buf), "%d,%#x", GET_MAJ_DEV(*dev),
+ GET_MIN_DEV(*dev));
+ return(buf);
+}
+
+
+/*
+ * process_finfo() -- process file information
+ */
+
+void
+process_finfo(pd, opfid, psfid, na)
+ struct pst_filedetails *pd; /* file details */
+ struct pst_fid *opfid; /* opaque file ID for this file */
+ struct psfileid *psfid; /* PSTAT file ID for this file */
+ KA_T na; /* node address */
+{
+ char *cp, buf[32];
+ dev_t dev;
+ int devs = 0;
+ int32_t lk;
+ struct mounts *mp;
+/*
+ * Save file IDs for later use in name lookup.
+ */
+ Lf->opfid = *opfid;
+ Lf->psfid = *psfid;
+
+#if defined(HASFSTRUCT)
+/*
+ * Save node ID.
+ */
+ if (na && (Fsv & FSV_NI)) {
+ Lf->fna = na;
+ Lf->fsv |= FSV_NI;
+ }
+#endif /* defined(HASFSTRUCT) */
+
+/*
+ * Construct lock code.
+ */
+ if ((lk = pd->psfd_lckflag) & PS_FPARTRDLCK)
+ Lf->lock = 'r';
+ else if (lk & PS_FPARTWRLCK)
+ Lf->lock = 'w';
+ else if (lk & PS_FFULLRDLCK)
+ Lf->lock = 'R';
+ else if (lk & PS_FFULLWRLCK)
+ Lf->lock = 'W';
+ else
+ Lf->lock = ' ';
+/*
+ * Derive type from modes.
+ */
+ switch ((int)(pd->psfd_mode & PS_IFMT)) {
+ case PS_IFREG:
+ cp = "REG";
+ Ntype = N_REGLR;
+ break;
+ case PS_IFBLK:
+ cp = "BLK";
+ Ntype = N_BLK;
+ break;
+ case PS_IFDIR:
+ cp = "DIR";
+ Ntype = N_REGLR;
+ break;
+ case PS_IFCHR:
+ cp = "CHR";
+ Ntype = N_CHR;
+ break;
+ case PS_IFIFO:
+ cp = "FIFO";
+ Ntype = N_FIFO;
+ break;
+ default:
+ (void) snpf(buf, sizeof(buf), "%04o",
+ (unsigned int)(((pd->psfd_mode & PS_IFMT) >> 12) & 0xfff));
+ cp = buf;
+ Ntype = N_REGLR;
+ }
+ if (!Lf->type[0])
+ (void) snpf(Lf->type, sizeof(Lf->type), "%s", cp);
+ Lf->ntype = Ntype;
+/*
+ * Save device number.
+ */
+ switch (Ntype) {
+ case N_FIFO:
+ (void) enter_dev_ch(print_kptr(na, (char *)NULL, 0));
+ break;
+ default:
+ dev = Lf->dev = (dev_t)pd->psfd_dev;
+ devs = Lf->dev_def = 1;
+ if ((Ntype == N_CHR) || (Ntype == N_BLK)) {
+ Lf->rdev = (dev_t)pd->psfd_rdev;
+ Lf->rdev_def = 1;
+ }
+ }
+/*
+ * Save node number.
+ */
+ Lf->inode = (INODETYPE)pd->psfd_ino;
+ Lf->inp_ty = 1;
+/*
+ * Save link count.
+ */
+ if (Fnlink) {
+
+ /*
+ * Ignore a zero link count only if the file is a FIFO.
+ */
+ if ((Lf->nlink = (long)pd->psfd_nlink) || (Ntype != N_FIFO))
+ Lf->nlink_def = 1;
+ if (Lf->nlink_def && Nlink && (Lf->nlink < Nlink))
+ Lf->sf |= SELNLINK;
+ }
+/*
+ * Save file system identity.
+ */
+ if (devs) {
+ for (mp = readmnt(); mp; mp = mp->next) {
+ if (dev == mp->dev) {
+ Lf->fsdir = mp->dir;
+ Lf->fsdev = mp->fsname;
+
+#if defined(HASFSINO)
+ Lf->fs_ino = (unsigned long)mp->inode;
+#endif /* defined(HASFSINO) */
+
+ break;
+ }
+ }
+ } else
+ mp = (struct mounts *)NULL;
+/*
+ * If no offset has been activated and no size saved, activate the offset or
+ * save the size.
+ */
+ if (!Lf->off_def && !Lf->sz_def) {
+ if (Foffset)
+ Lf->off_def = 1;
+ else {
+ switch (Ntype) {
+ case N_CHR:
+ case N_FIFO:
+ Lf->off_def = 1;
+ break;
+ default:
+ Lf->sz = (SZOFFTYPE)pd->psfd_size;
+ Lf->sz_def = 1;
+ }
+ }
+ }
+/*
+ * See if this is an NFS file.
+ */
+ if (Fnfs) {
+ if (HasNFS < 0)
+ (void) scanmnttab();
+ if (HasNFS && mp && mp->is_nfs)
+ Lf->sf |= SELNFS;
+ }
+/*
+ * Test for specified file.
+ */
+ if (Sfile && is_file_named(NULL,
+ ((Ntype == N_CHR) || (Ntype == N_BLK) ? 1
+ : 0)))
+ Lf->sf |= SELNM;
+/*
+ * Enter name characters.
+ */
+ if (!Lf->nm && Namech[0])
+ enter_nm(Namech);
+}
diff --git a/dialects/hpux/pstat/dlsof.h b/dialects/hpux/pstat/dlsof.h
new file mode 100644
index 0000000..dff34e5
--- /dev/null
+++ b/dialects/hpux/pstat/dlsof.h
@@ -0,0 +1,206 @@
+/*
+ * dlsof.h - pstat-based HP-UX header file 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.
+ */
+
+
+/*
+ * $Id: dlsof.h,v 1.8 2008/10/21 16:17:50 abe Exp $
+ */
+
+
+#if !defined(HPUX_LSOF_H)
+#define HPUX_LSOF_H 1
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <mntent.h>
+#include <setjmp.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+# if defined(HASIPv6)
+#include <netinet/in6.h>
+# endif /* defined(HASIPv6) */
+
+#include <rpc/types.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+
+#include <sys/fstyp.h>
+#include <sys/mount.h>
+#include <sys/param.h>
+#include <sys/pstat.h>
+
+# if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS==64 && defined(_APP32_64BIT_OFF_T)
+#define TMP_APP32_64BIT_OFF_T _APP32_64BIT_OFF_T
+#undef _APP32_64BIT_OFF_T
+# endif
+
+# if !defined(__LP64__) && defined(_LARGEFILE64_SOURCE) && HPUXV>=1123
+/*
+ * Make sure a 32 bit lsof for HPUX>=1123 uses [l]stat64 when
+ * _LARGEFILE64_SOURCE is defined.
+ */
+
+#define stat stat64
+#define lstat lstat64
+# endif /* !defined(__LP64__) && defined(_LARGEFILE64_SOURCE) && HPUXV>=1123 */
+
+#include <sys/socket.h>
+
+# if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS==64 && defined(_APP32_64BIT_OFF_T)
+#define _APP32_64BIT_OFF_T TMP_APP32_64BIT_OFF_T
+#undef TMP_APP32_64BIT_OFF_T
+# endif
+
+#include <sys/tihdr.h>
+#include <sys/un.h>
+
+
+/*
+ * This definition is needed for the common function prototype definitions
+ * in "proto.h". The /proc-based lsof also uses it to make sure its
+ * manufactured node ID number has 64 bits.
+ */
+
+typedef unsigned long long KA_T;
+#define KA_T_FMT_X "%#llx"
+
+
+/*
+ * Local definitions
+ */
+
+# if defined(HAS_CONST)
+#define COMP_P const void
+# else /* !defined(HAS_CONST) */
+#define COMP_P void
+# endif /* defined(HAS_CONST) */
+
+#define DEVINCR 1024 /* device table malloc() increment */
+#define MALLOC_P void
+#define FREE_P void
+#define MALLOC_S unsigned
+#define MOUNTED MNT_MNTTAB
+#define QSORT_P void
+#define READLEN_T int
+#define STRNCPY_L size_t
+#define SZOFFTYPE unsigned long long
+#define SZOFFPSPEC "ll" /* SZOFFTYPE printf specification modifier */
+#define XDR_PMAPLIST (xdrproc_t)xdr_pmaplist
+#define XDR_VOID (xdrproc_t)xdr_void
+
+
+/*
+ * Local macros
+ */
+
+#define IS_PSFILEID(p) ((p)->psf_fsid.psfs_id || (p)->psf_fsid.psfs_type)
+ /* is psfiled active? */
+
+
+/*
+ * Global storage definitions (including their structure definitions)
+ */
+
+extern _T_LONG_T CloneMaj; /* clone major device number */
+extern int HaveCloneMaj; /* clone major status */
+
+struct mounts {
+ char *dir; /* directory (mounted on) */
+ char *fsname; /* file system
+ * (symbolic links unresolved) */
+ char *fsnmres; /* file system
+ * (symbolic links resolved) */
+ char *mnt_fstype; /* file system type -- e.g.,
+ * MNTTYPE_NFS */
+ int stat_fstype; /* st_fstype */
+ dev_t dev; /* directory st_dev */
+ dev_t rdev; /* directory st_rdev */
+ INODETYPE inode; /* directory st_ino */
+ mode_t mode; /* directory st_mode */
+ mode_t fs_mode; /* file system st_mode */
+ u_char is_nfs; /* file system type is MNTTYPE_NFS or
+ * MNTTYPE_NFS3 */
+ struct mounts *next; /* forward link */
+};
+
+struct sfile {
+ char *aname; /* argument file name */
+ char *name; /* file name (after readlink()) */
+ char *devnm; /* device name (optional) */
+ dev_t dev; /* device */
+ dev_t rdev; /* raw device */
+ u_short mode; /* S_IFMT mode bits from stat() */
+ int type; /* file type: 0 = file system
+ * 1 = regular file */
+ INODETYPE i; /* inode number */
+ int f; /* file found flag */
+ struct sfile *next; /* forward link */
+};
+
+extern char **Fsinfo;
+extern int Fsinfomax;
+extern int HasNFS;
+
+
+/*
+ * Definitions for dvch.c, isfn.c, and rdev.c
+ */
+
+#define CLONEMAJ CloneMaj /* clone major variable name */
+#define DIRTYPE dirent
+#define HASDNAMLEN 1 /* DIRTYPE has d_namlen element */
+#define HAS_STD_CLONE 1 /* uses standard clone structure */
+#define HAVECLONEMAJ HaveCloneMaj /* clone major status variable name */
+#define MAXSYSCMDL (PST_UCOMMLEN - 1)
+ /* max system command name length */
+
+
+/*
+ * Definition for rmnt.c
+ */
+
+#define MNTSKIP \
+ { if (strcmp(mp->mnt_type, MNTTYPE_IGNORE) == 0) \
+ continue; }
+#define RMNT_FSTYPE mnt_type
+#define MOUNTS_FSTYPE mnt_fstype
+
+# if defined(HASFSTYPE) && HASFSTYPE==2
+#define RMNT_STAT_FSTYPE st_fstype
+#define MOUNTS_STAT_FSTYPE stat_fstype
+# endif /* defined(HASFSTYPE) && HASFSTYPE==2 */
+
+#endif /* HPUX_LSOF_H */
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;
+ }
+ }
+}
diff --git a/dialects/hpux/pstat/dproto.h b/dialects/hpux/pstat/dproto.h
new file mode 100644
index 0000000..66e61ac
--- /dev/null
+++ b/dialects/hpux/pstat/dproto.h
@@ -0,0 +1,59 @@
+/*
+ * dproto.h - pstat-based HP-UX function prototypes for lsof
+ *
+ * The _PROTOTYPE macro is defined in the common proto.h.
+ */
+
+
+/*
+ * 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.
+ */
+
+
+/*
+ * $Id: dproto.h,v 1.5 2008/10/21 16:17:50 abe Exp $
+ */
+
+
+_PROTOTYPE(extern int get_max_fd,(void));
+_PROTOTYPE(extern int is_file_named,(char *p, int cd));
+_PROTOTYPE(extern void process_finfo,(struct pst_filedetails *pd, struct pst_fid *opfid, struct psfileid *psfid, KA_T na));
+_PROTOTYPE(extern void process_socket,(struct pst_fileinfo2 *f,
+ struct pst_socket *s));
+_PROTOTYPE(extern void process_stream,(struct pst_fileinfo2 *f, int ckscko));
+_PROTOTYPE(extern KA_T read_det,(struct pst_fid *ki, uint32_t hf, uint32_t lf,
+ uint32_t hn, uint32_t ln,
+ struct pst_filedetails *pd));
+_PROTOTYPE(extern struct pst_socket *read_sock,(struct pst_fileinfo2 *f));
+
+#if defined(HASIPv6)
+_PROTOTYPE(extern struct hostent *gethostbyname2,(char *nm, int proto));
+#endif /* defined(HASIPv6) */
+
+#if defined(HASVXFS)
+_PROTOTYPE(extern int read_vxnode,(struct vnode *v, struct l_vfs *vfs, dev_t *dev));
+#endif /* defined(HASVXFS) */
+
+_PROTOTYPE(extern void scanmnttab,(void));
diff --git a/dialects/hpux/pstat/dsock.c b/dialects/hpux/pstat/dsock.c
new file mode 100644
index 0000000..461ba58
--- /dev/null
+++ b/dialects/hpux/pstat/dsock.c
@@ -0,0 +1,1647 @@
+/*
+ * dsock.c -- pstat-based HP-UX socket and stream processing 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 function prototypes
+ */
+
+#if defined(PS_STR_XPORT_DATA)
+_PROTOTYPE(static void make_sock,(struct pst_fileinfo2 *f,
+ struct pst_stream *sh,
+ struct pst_socket *s));
+#endif /* defined(PS_STR_XPORT_DATA) */
+
+_PROTOTYPE(static void printpsproto,(uint32_t p));
+
+
+/*
+ * Local macros
+ */
+
+#if defined(HASIPv6)
+
+/*
+ * IPv6_2_IPv4() -- macro to define the address of an IPv4 address contained
+ * in an IPv6 address
+ */
+
+#define IPv6_2_IPv4(v6) (((uint8_t *)((struct in6_addr *)v6)->s6_addr)+12)
+#endif /* defined(HASIPv6) */
+
+
+/*
+ * build_IPstates() -- build the TCP and UDP state tables
+ */
+
+void
+build_IPstates()
+{
+ if (!TcpSt) {
+ (void) enter_IPstate("TCP", "CLOSED", PS_TCPS_CLOSED);
+ (void) enter_IPstate("TCP", "IDLE", PS_TCPS_IDLE);
+ (void) enter_IPstate("TCP", "BOUND", PS_TCPS_BOUND);
+ (void) enter_IPstate("TCP", "LISTEN", PS_TCPS_LISTEN);
+ (void) enter_IPstate("TCP", "SYN_SENT", PS_TCPS_SYN_SENT);
+ (void) enter_IPstate("TCP", "SYN_RCVD", PS_TCPS_SYN_RCVD);
+ (void) enter_IPstate("TCP", "ESTABLISHED", PS_TCPS_ESTABLISHED);
+ (void) enter_IPstate("TCP", "CLOSE_WAIT", PS_TCPS_CLOSE_WAIT);
+ (void) enter_IPstate("TCP", "FIN_WAIT_1", PS_TCPS_FIN_WAIT_1);
+ (void) enter_IPstate("TCP", "CLOSING", PS_TCPS_CLOSING);
+ (void) enter_IPstate("TCP", "LAST_ACK", PS_TCPS_LAST_ACK);
+ (void) enter_IPstate("TCP", "FIN_WAIT_2", PS_TCPS_FIN_WAIT_2);
+ (void) enter_IPstate("TCP", "TIME_WAIT", PS_TCPS_TIME_WAIT);
+ (void) enter_IPstate("TCP", (char *)NULL, 0);
+ }
+ if (!UdpSt) {
+ (void) enter_IPstate("UDP", "Uninitialized", PS_TS_UNINIT);
+ (void) enter_IPstate("UDP", "Unbound", PS_TS_UNBND);
+ (void) enter_IPstate("UDP", "Wait_BIND_REQ_Ack", PS_TS_WACK_BREQ);
+ (void) enter_IPstate("UDP", "Wait_UNBIND_REQ_Ack", PS_TS_WACK_UREQ);
+ (void) enter_IPstate("UDP", "Idle", PS_TS_IDLE);
+ (void) enter_IPstate("UDP", "Wait_OPT_REQ_Ack", PS_TS_WACK_OPTREQ);
+ (void) enter_IPstate("UDP", "Wait_CONN_REQ_Ack", PS_TS_WACK_CREQ);
+ (void) enter_IPstate("UDP", "Wait_CONN_REQ_Confirm",
+ PS_TS_WCON_CREQ);
+ (void) enter_IPstate("UDP", "Wait_CONN_IND_Response",
+ PS_TS_WRES_CIND);
+ (void) enter_IPstate("UDP", "Wait_CONN_RES_Ack", PS_TS_WACK_CRES);
+ (void) enter_IPstate("UDP", "Wait_Data_Xfr", PS_TS_DATA_XFER);
+ (void) enter_IPstate("UDP", "Wait_Read_Release", PS_TS_WIND_ORDREL);
+ (void) enter_IPstate("UDP", "Wait_Write_Release",
+ PS_TS_WREQ_ORDREL);
+ (void) enter_IPstate("UDP", "Wait_DISCON_REQ_Ack",
+ PS_TS_WACK_DREQ6);
+ (void) enter_IPstate("UDP", "Wait_DISCON_REQ_Ack",
+ PS_TS_WACK_DREQ7);
+ (void) enter_IPstate("UDP", "Wait_DISCON_REQ_Ack",
+ PS_TS_WACK_DREQ9);
+ (void) enter_IPstate("UDP", "Wait_DISCON_REQ_Ack",
+ PS_TS_WACK_DREQ10);
+ (void) enter_IPstate("UDP", "Wait_DISCON_REQ_Ack",
+ PS_TS_WACK_DREQ11);
+ (void) enter_IPstate("UDP", "Internal", PS_TS_WACK_ORDREL);
+ (void) enter_IPstate("UDP", (char *)NULL, 0);
+ }
+}
+
+
+#if defined(PS_STR_XPORT_DATA)
+/*
+ * make_sock() -- make a socket from the eXPORT data in a stream's head
+ */
+
+static void
+make_sock(f, sh, s)
+ struct pst_fileinfo2 *f; /* pst_fileinfo2 */
+ struct pst_stream *sh; /* stream head */
+ struct pst_socket *s; /* constructed socket */
+{
+ size_t sz;
+/*
+ * Zero the destination pst_socket structure and propagate its file and node
+ * IDs from the stream head. Also propagate the linger time.
+ */
+ (void)memset((void *)s, 0, sizeof(struct pst_socket));
+ s->pst_hi_fileid = sh->val.head.pst_hi_fileid;
+ s->pst_lo_fileid = sh->val.head.pst_lo_fileid;
+ s->pst_hi_nodeid = sh->val.head.pst_hi_nodeid;
+ s->pst_lo_nodeid = sh->val.head.pst_lo_nodeid;
+ s->pst_linger = sh->pst_str_xport_linger;
+/*
+ * Convert stream family to socket family and stream protocol to socket
+ * protocol.
+ *
+ * This could be avoided if PSTAT were to use a common set of family and
+ * protocol symbols.
+ */
+ switch (sh->pst_str_xport_family) {
+ case PS_STR_XPORT_AFINET:
+ s->pst_family = PS_AF_INET;
+ break;
+ case PS_STR_XPORT_AFINET6:
+ s->pst_family = PS_AF_INET6;
+ break;
+ default:
+ s->pst_family = sh->pst_str_xport_family;
+ }
+ switch (sh->pst_str_xport_protocol) {
+ case PS_STR_XPORT_TCP_PROTO:
+ s->pst_protocol = PS_PROTO_TCP;
+ break;
+ case PS_STR_XPORT_UDP_PROTO:
+ s->pst_protocol = PS_PROTO_UDP;
+ break;
+ default:
+ s->pst_protocol = sh->pst_str_xport_protocol;
+ }
+/*
+ * Copy stream size information.
+ */
+ s->pst_qlimit = sh->pst_str_xport_qlimit;
+ s->pst_qlen = sh->pst_str_xport_qlen;
+ s->pst_idata = sh->pst_str_xport_idata;
+ s->pst_ibufsz = sh->pst_str_xport_ibufsz;
+ s->pst_rwnd = sh->pst_str_xport_rwnd;
+ s->pst_swnd = sh->pst_str_xport_swnd;
+ s->pst_odata = sh->pst_str_xport_odata;
+ s->pst_obufsz = sh->pst_str_xport_obufsz;
+/*
+ * Propagate protocol state from stream symbol values to socket ones.
+ *
+ * This could be avoided if PSTAT were to use a common set of protocol
+ * state symbols.
+ */
+ if (s->pst_protocol == PS_PROTO_TCP) {
+ switch (sh->pst_str_xport_pstate) {
+
+#if defined(PS_STR_XPORT_TCPS_CLOSED) && defined(PS_TCPS_CLOSED) \
+ && (PS_STR_XPORT_TCPS_CLOSED != PS_TCPS_CLOSED)
+ case PS_STR_XPORT_TCPS_CLOSED:
+ s->pst_pstate = PS_TCPS_CLOSED;
+ break;
+#endif
+
+#if defined(PS_STR_XPORT_TCPS_IDLE) && defined(PS_TCPS_IDLE) \
+ && (PS_STR_XPORT_TCPS_IDLE != PS_TCPS_IDLE)
+ case PS_STR_XPORT_TCPS_IDLE:
+ s->pst_pstate = PS_TCPS_IDLE;
+ break;
+#endif
+
+#if defined(PS_STR_XPORT_TCPS_BOUND) && defined(PS_TCPS_BOUND) \
+ && (PS_STR_XPORT_TCPS_BOUND != PS_TCPS_BOUND)
+ case PS_STR_XPORT_TCPS_BOUND:
+ s->pst_pstate = PS_TCPS_BOUND;
+ break;
+#endif
+
+#if defined(PS_STR_XPORT_TCPS_LISTEN) && defined(PS_TCPS_LISTEN) \
+ && (PS_STR_XPORT_TCPS_LISTEN != PS_TCPS_LISTEN)
+ case PS_STR_XPORT_TCPS_LISTEN:
+ s->pst_pstate = PS_TCPS_LISTEN;
+ break;
+#endif
+
+#if defined(PS_STR_XPORT_TCPS_SYN_SENT) && defined(PS_TCPS_SYN_SENT) \
+ && (PS_STR_XPORT_TCPS_SYN_SENT != PS_TCPS_SYN_SENT)
+ case PS_STR_XPORT_TCPS_SYN_SENT:
+ s->pst_pstate = PS_TCPS_SYN_SENT;
+ break;
+#endif
+
+#if defined(PS_STR_XPORT_TCPS_SYN_RCVD) && defined(PS_TCPS_SYN_RCVD) \
+ && (PS_STR_XPORT_TCPS_SYN_RCVD != PS_TCPS_SYN_RCVD)
+ case PS_STR_XPORT_TCPS_SYN_RCVD:
+ s->pst_pstate = PS_TCPS_SYN_RCVD;
+ break;
+#endif
+
+#if defined(PS_STR_XPORT_TCPS_ESTABLISHED) && defined(PS_TCPS_ESTABLISHED) \
+ && (PS_STR_XPORT_TCPS_ESTABLISHED != PS_TCPS_ESTABLISHED)
+ case PS_STR_XPORT_TCPS_ESTABLISHED:
+ s->pst_pstate = PS_TCPS_ESTABLISHED;
+ break;
+#endif
+
+#if defined(PS_STR_XPORT_TCPS_CLOSE_WAIT) && defined(PS_TCPS_CLOSE_WAIT) \
+ && (PS_STR_XPORT_TCPS_CLOSE_WAIT != PS_TCPS_CLOSE_WAIT)
+ case PS_STR_XPORT_TCPS_CLOSE_WAIT:
+ s->pst_pstate = PS_TCPS_CLOSE_WAIT;
+ break;
+#endif
+
+#if defined(PS_STR_XPORT_TCPS_FIN_WAIT_1) && defined(PS_TCPS_FIN_WAIT_1) \
+ && (PS_STR_XPORT_TCPS_FIN_WAIT_1 != PS_TCPS_FIN_WAIT_1)
+ case PS_STR_XPORT_TCPS_FIN_WAIT_1:
+ s->pst_pstate = PS_TCPS_FIN_WAIT_1;
+ break;
+#endif
+
+#if defined(PS_STR_XPORT_TCPS_CLOSING) && defined(PS_TCPS_CLOSING) \
+ && (PS_STR_XPORT_TCPS_CLOSING != PS_TCPS_CLOSING)
+ case PS_STR_XPORT_TCPS_CLOSING:
+ s->pst_pstate = PS_TCPS_CLOSING;
+ break;
+#endif
+
+#if defined(PS_STR_XPORT_TCPS_LAST_ACK) && defined(PS_TCPS_LAST_ACK) \
+ && (PS_STR_XPORT_TCPS_LAST_ACK != PS_TCPS_LAST_ACK)
+ case PS_STR_XPORT_TCPS_LAST_ACK:
+ s->pst_pstate = PS_TCPS_LAST_ACK;
+ break;
+#endif
+
+#if defined(PS_STR_XPORT_TCPS_FIN_WAIT_2) && defined(PS_TCPS_FIN_WAIT_2) \
+ && (PS_STR_XPORT_TCPS_FIN_WAIT_2 != PS_TCPS_FIN_WAIT_2)
+ case PS_STR_XPORT_TCPS_FIN_WAIT_2:
+ s->pst_pstate = PS_TCPS_FIN_WAIT_2;
+ break;
+#endif
+
+#if defined(PS_STR_XPORT_TCPS_TIME_WAIT) && defined(PS_TCPS_TIME_WAIT) \
+ && (PS_STR_XPORT_TCPS_TIME_WAIT != PS_TCPS_TIME_WAIT)
+ case PS_STR_XPORT_TCPS_TIME_WAIT:
+ s->pst_pstate = PS_TCPS_TIME_WAIT;
+ break;
+#endif
+
+ default:
+ s->pst_pstate = sh->pst_str_xport_pstate;
+ }
+ } else if (s->pst_protocol == PS_PROTO_UDP) {
+ switch (sh->pst_str_xport_pstate) {
+
+#if defined(PS_STR_XPORT_TS_UNINIT) && defined(PS_TS_UNINIT) \
+ && (PS_STR_XPORT_TS_UNINIT != PS_TS_UNINIT)
+ case PS_STR_XPORT_TS_UNINIT:
+ s->pst_pstate = PS_TS_UNINIT;
+ break;
+#endif
+
+#if defined(PS_STR_XPORT_TS_UNBND) && defined(PS_TS_UNBND) \
+ && (PS_STR_XPORT_TS_UNBND != PS_TS_UNBND)
+ case PS_STR_XPORT_TS_UNBND:
+ s->pst_pstate = PS_TS_UNBND;
+ break;
+#endif
+
+#if defined(PS_STR_XPORT_TS_WACK_BREQ) && defined(PS_TS_WACK_BREQ) \
+ && (PS_STR_XPORT_TS_WACK_BREQ != PS_TS_WACK_BREQ)
+ case PS_STR_XPORT_TS_WACK_BREQ:
+ s->pst_pstate = PS_TS_WACK_BREQ;
+ break;
+#endif
+
+#if defined(PS_STR_XPORT_TS_WACK_UREQ) && defined(PS_TS_WACK_UREQ) \
+ && (PS_STR_XPORT_TS_WACK_UREQ != PS_TS_WACK_UREQ)
+ case PS_STR_XPORT_TS_WACK_UREQ:
+ s->pst_pstate = PS_TS_WACK_UREQ;
+ break;
+#endif
+
+#if defined(PS_STR_XPORT_TS_IDLE) && defined(PS_TS_IDLE) \
+ && (PS_STR_XPORT_TS_IDLE != PS_TS_IDLE)
+ case PS_STR_XPORT_TS_IDLE:
+ s->pst_pstate = PS_TS_IDLE;
+ break;
+#endif
+
+#if defined(PS_STR_XPORT_TS_WACK_OPTREQ) && defined(PS_TS_WACK_OPTREQ) \
+ && (PS_STR_XPORT_TS_WACK_OPTREQ != PS_TS_WACK_OPTREQ)
+ case PS_STR_XPORT_TS_WACK_OPTREQ:
+ s->pst_pstate = PS_TS_WACK_OPTREQ;
+ break;
+#endif
+
+#if defined(PS_STR_XPORT_TS_WACK_CREQ) && defined(PS_TS_WACK_CREQ) \
+ && (PS_STR_XPORT_TS_WACK_CREQ != PS_TS_WACK_CREQ)
+ case PS_STR_XPORT_TS_WACK_CREQ:
+ s->pst_pstate = PS_TS_WACK_CREQ;
+ break;
+#endif
+
+#if defined(PS_STR_XPORT_TS_WCON_CREQ) && defined(PS_TS_WCON_CREQ) \
+ && (PS_STR_XPORT_TS_WCON_CREQ != PS_TS_WCON_CREQ)
+ case PS_STR_XPORT_TS_WCON_CREQ:
+ s->pst_pstate = PS_TS_WCON_CREQ;
+ break;
+#endif
+
+#if defined(PS_STR_XPORT_TS_WRES_CIND) && defined(PS_TS_WRES_CIND) \
+ && (PS_STR_XPORT_TS_WRES_CIND != PS_TS_WRES_CIND)
+ case PS_STR_XPORT_TS_WRES_CIND:
+ s->pst_pstate = PS_TS_WRES_CIND;
+ break;
+#endif
+
+#if defined(PS_STR_XPORT_TS_WACK_CRES) && defined(PS_TS_WACK_CRES) \
+ && (PS_STR_XPORT_TS_WACK_CRES != PS_TS_WACK_CRES)
+ case PS_STR_XPORT_TS_WACK_CRES:
+ s->pst_pstate = PS_TS_WACK_CRES;
+ break;
+#endif
+
+#if defined(PS_STR_XPORT_TS_DATA_XFER) && defined(PS_TS_DATA_XFER) \
+ && (PS_STR_XPORT_TS_DATA_XFER != PS_TS_DATA_XFER)
+ case PS_STR_XPORT_TS_DATA_XFER:
+ s->pst_pstate = PS_TS_DATA_XFER;
+ break;
+#endif
+
+#if defined(PS_STR_XPORT_TS_WIND_ORDREL) && defined(PS_TS_WIND_ORDREL) \
+ && (PS_STR_XPORT_TS_WIND_ORDREL != PS_TS_WIND_ORDREL)
+ case PS_STR_XPORT_TS_WIND_ORDREL:
+ s->pst_pstate = PS_TS_WIND_ORDREL;
+ break;
+#endif
+
+#if defined(PS_STR_XPORT_TS_WREQ_ORDREL) && defined(PS_TS_WREQ_ORDREL) \
+ && (PS_STR_XPORT_TS_WREQ_ORDREL != PS_TS_WREQ_ORDREL)
+ case PS_STR_XPORT_TS_WREQ_ORDREL:
+ s->pst_pstate = PS_TS_WREQ_ORDREL;
+ break;
+#endif
+
+#if defined(PS_STR_XPORT_TS_WACK_DREQ6) && defined(PS_TS_WACK_DREQ6) \
+ && (PS_STR_XPORT_TS_WACK_DREQ6 != PS_TS_WACK_DREQ6)
+ case PS_STR_XPORT_TS_WACK_DREQ6:
+ s->pst_pstate = PS_TS_WACK_DREQ6;
+ break;
+#endif
+
+#if defined(PS_STR_XPORT_TS_WACK_DREQ7) && defined(PS_TS_WACK_DREQ7) \
+ && (PS_STR_XPORT_TS_WACK_DREQ7 != PS_TS_WACK_DREQ7)
+ case PS_STR_XPORT_TS_WACK_DREQ7:
+ s->pst_pstate = PS_TS_WACK_DREQ7;
+ break;
+#endif
+
+#if defined(PS_STR_XPORT_TS_WACK_DREQ9) && defined(PS_TS_WACK_DREQ9) \
+ && (PS_STR_XPORT_TS_WACK_DREQ9 != PS_TS_WACK_DREQ9)
+ case PS_STR_XPORT_TS_WACK_DREQ9:
+ s->pst_pstate = PS_TS_WACK_DREQ9;
+ break;
+#endif
+
+#if defined(PS_STR_XPORT_TS_WACK_DREQ10) && defined(PS_TS_WACK_DREQ10) \
+ && (PS_STR_XPORT_TS_WACK_DREQ10 != PS_TS_WACK_DREQ10)
+ case PS_STR_XPORT_TS_WACK_DREQ10:
+ s->pst_pstate = PS_TS_WACK_DREQ10;
+ break;
+#endif
+
+#if defined(PS_STR_XPORT_TS_WACK_DREQ11) && defined(PS_TS_WACK_DREQ11) \
+ && (PS_STR_XPORT_TS_WACK_DREQ11 != PS_TS_WACK_DREQ11)
+ case PS_STR_XPORT_TS_WACK_DREQ11:
+ s->pst_pstate = PS_TS_WACK_DREQ11;
+ break;
+#endif
+
+#if defined(PS_STR_XPORT_TS_WACK_ORDREL) && defined(PS_TS_WACK_ORDREL) \
+ && (PS_STR_XPORT_TS_WACK_ORDREL != PS_TS_WACK_ORDREL)
+ case PS_STR_XPORT_TS_WACK_ORDREL:
+ s->pst_pstate = PS_TS_WACK_ORDREL;
+ break;
+#endif
+
+#if defined(PS_STR_XPORT_TS_NOSTATES) && defined(PS_TS_NOSTATES) \
+ && (PS_STR_XPORT_TS_NOSTATES != PS_TS_NOSTATES)
+ case PS_STR_XPORT_TS_NOSTATES:
+ s->pst_pstate = PS_TS_NOSTATES;
+ break;
+#endif
+
+ default:
+ s->pst_pstate = sh->pst_str_xport_pstate;
+ }
+ } else
+ s->pst_pstate = sh->pst_str_xport_pstate;
+/*
+ * Now propagate the bound and remote address information from pst_stream
+ * to the pst_socket structure. Validate the copy lengths.
+ */
+ sz = (size_t)sh->pst_str_xport_boundaddr_len;
+ if (sz > sizeof(s->pst_boundaddr))
+ sz = sizeof(s->pst_boundaddr);
+ if ((s->pst_boundaddr_len = sz)) {
+ (void) memcpy((void *)s->pst_boundaddr,
+ (const void *)sh->pst_str_xport_boundaddr, sz);
+ }
+ sz = (size_t)sh->pst_str_xport_remaddr_len;
+ if (sz > sizeof(s->pst_remaddr))
+ sz = sizeof(s->pst_remaddr);
+ if ((s->pst_remaddr_len = sz)) {
+ (void) memcpy((void *)s->pst_remaddr,
+ (const void *)sh->pst_str_xport_remaddr, sz);
+ }
+}
+#endif /* defined(PS_STR_XPORT_DATA) */
+
+
+/*
+ * printpsproto() -- print PSTAT protocol name
+ */
+
+static void
+printpsproto(p)
+ uint32_t p; /* protocol number */
+{
+ int i;
+ static int m = -1;
+ char *s;
+
+ switch (p) {
+ case PS_PROTO_IP:
+ s = "IP";
+ break;
+ case PS_PROTO_ICMP:
+ s = "ICMP";
+ break;
+ case PS_PROTO_IGMP:
+ s = "IGMP";
+ break;
+ case PS_PROTO_GGP:
+ s = "GGP";
+ break;
+ case PS_PROTO_IPIP:
+ s = "IPIP";
+ break;
+ case PS_PROTO_TCP:
+ s = "TCP";
+ break;
+ case PS_PROTO_EGP:
+ s = "EGP";
+ break;
+ case PS_PROTO_IGP:
+ s = "IGP";
+ break;
+ case PS_PROTO_PUP:
+ s = "PUP";
+ break;
+ case PS_PROTO_UDP:
+ s = "UDP";
+ break;
+ case PS_PROTO_IDP:
+ s = "IDP";
+ break;
+ case PS_PROTO_XTP:
+ s = "XTP";
+ break;
+ case PS_PROTO_ESP:
+ s = "ESP";
+ break;
+ case PS_PROTO_AH:
+ s = "AH";
+ break;
+ case PS_PROTO_OSPF:
+ s = "OSPF";
+ break;
+ case PS_PROTO_IPENCAP:
+ s = "IPENCAP";
+ break;
+ case PS_PROTO_ENCAP:
+ s = "ENCAP";
+ break;
+ case PS_PROTO_PXP:
+ s = "PXP";
+ break;
+ case PS_PROTO_RAW:
+ s = "RAW";
+ break;
+ default:
+ s = (char *)NULL;
+ }
+ if (s)
+ (void) snpf(Lf->iproto, sizeof(Lf->iproto), "%.*s", IPROTOL-1, s);
+ else {
+ if (m < 0) {
+ for (i = 0, m = 1; i < IPROTOL-2; i++)
+ m *= 10;
+ }
+ if (m > p)
+ (void) snpf(Lf->iproto, sizeof(Lf->iproto), "%d?", p);
+ else
+ (void) snpf(Lf->iproto, sizeof(Lf->iproto), "*%d?",
+ p % (m/10));
+ }
+}
+
+
+/*
+ * print_tcptpi() -- print TCP/TPI info
+ */
+
+void
+print_tcptpi(nl)
+ int nl; /* 1 == '\n' required */
+{
+ char *cp = (char *)NULL;
+ char sbuf[128];
+ int i;
+ int ps = 0;
+ unsigned int u;
+
+ if (Ftcptpi & TCPTPI_STATE) {
+ switch (Lf->lts.type) {
+ case 0: /* TCP */
+ if (!TcpSt)
+ (void) build_IPstates();
+ if ((i = Lf->lts.state.i + TcpStOff) < 0 || i >= TcpNstates) {
+ (void) snpf(sbuf, sizeof(sbuf), "UknownState_%d",
+ Lf->lts.state.i);
+ cp = sbuf;
+ } else
+ cp = TcpSt[i];
+ break;
+ case 1: /* UDP */
+ if (!UdpSt)
+ (void) build_IPstates();
+ if ((u = Lf->lts.state.ui + UdpStOff) > UdpNstates) {
+ (void) snpf(sbuf, sizeof(sbuf), "UNKNOWN_TPI_STATE_%u",
+ Lf->lts.state.ui);
+ cp = sbuf;
+ } else
+ cp = UdpSt[u];
+ }
+ if (cp) {
+ if (Ffield)
+ (void) printf("%cST=%s%c", LSOF_FID_TCPTPI, cp, Terminator);
+ else {
+ putchar('(');
+ (void) fputs(cp, stdout);
+ }
+ ps++;
+ }
+ }
+
+#if defined(HASTCPTPIQ)
+ if (Ftcptpi & TCPTPI_QUEUES) {
+ if (Lf->lts.rqs) {
+ if (Ffield)
+ putchar(LSOF_FID_TCPTPI);
+ else {
+ if (ps)
+ putchar(' ');
+ else
+ putchar('(');
+ }
+ (void) printf("QR=%lu", Lf->lts.rq);
+ if (Ffield)
+ putchar(Terminator);
+ ps++;
+ }
+ if (Lf->lts.sqs) {
+ if (Ffield)
+ putchar(LSOF_FID_TCPTPI);
+ else {
+ if (ps)
+ putchar(' ');
+ else
+ putchar('(');
+ }
+ (void) printf("QS=%lu", Lf->lts.sq);
+ if (Ffield)
+ putchar(Terminator);
+ ps++;
+ }
+ }
+#endif /* defined(HASTCPTPIQ) */
+
+#if defined(HASSOOPT)
+ if (Ftcptpi & TCPTPI_FLAGS) {
+ int opt;
+
+ if ((opt = Lf->lts.opt) || Lf->lts.qlens || Lf->lts.qlims) {
+ char sep = ' ';
+
+ if (Ffield)
+ sep = LSOF_FID_TCPTPI;
+ else if (!ps)
+ sep = '(';
+ (void) printf("%cSO", sep);
+ ps++;
+ sep = '=';
+
+# if defined(PS_SO_ACCEPTCONN)
+ if (opt & PS_SO_ACCEPTCONN) {
+ (void) printf("%cACCEPTCONN", sep);
+ opt &= ~PS_SO_ACCEPTCONN;
+ sep = ',';
+ }
+# endif /* defined(PS_SO_ACCEPTCONN) */
+
+# if defined(PS_SO_BROADCAST)
+ if (opt & PS_SO_BROADCAST) {
+ (void) printf("%cBROADCAST", sep);
+ opt &= ~PS_SO_BROADCAST;
+ sep = ',';
+ }
+# endif /* defined(PS_SO_BROADCAST) */
+
+# if defined(PS_SO_DEBUG)
+ if (opt & PS_SO_DEBUG) {
+ (void) printf("%cDEBUG", sep);
+ opt &= ~PS_SO_DEBUG;
+ sep = ',';
+ }
+# endif /* defined(PS_SO_DEBUG) */
+
+# if defined(PS_SO_DONTROUTE)
+ if (opt & PS_SO_DONTROUTE) {
+ (void) printf("%cDONTROUTE", sep);
+ opt &= ~PS_SO_DONTROUTE;
+ sep = ',';
+ }
+# endif /* defined(PS_SO_DONTROUTE) */
+
+# if defined(PS_SO_GETIFADDR)
+ if (opt & PS_SO_GETIFADDR) {
+ (void) printf("%cGETIFADDR", sep);
+ opt &= ~PS_SO_GETIFADDR;
+ sep = ',';
+ }
+# endif /* defined(PS_SO_GETIFADDR) */
+
+# if defined(PS_SO_INPCB_COPY)
+ if (opt & PS_SO_INPCB_COPY) {
+ (void) printf("%cINPCB_COPY", sep);
+ opt &= ~PS_SO_INPCB_COPY;
+ sep = ',';
+ }
+# endif /* defined(PS_SO_INPCB_COPY) */
+
+# if defined(PS_SO_KEEPALIVE)
+ if (opt & PS_SO_KEEPALIVE) {
+ (void) printf("%cKEEPALIVE", sep);
+ if (Lf->lts.kai)
+ (void) printf("=%d", Lf->lts.kai);
+ opt &= ~PS_SO_KEEPALIVE;
+ sep = ',';
+ }
+# endif /* defined(PS_SO_KEEPALIVE) */
+
+# if defined(PS_SO_LINGER)
+ if (opt & PS_SO_LINGER) {
+ (void) printf("%cLINGER", sep);
+ if (Lf->lts.ltm)
+ (void) printf("=%d", Lf->lts.ltm);
+ opt &= ~PS_SO_LINGER;
+ sep = ',';
+ }
+# endif /* defined(PS_SO_LINGER) */
+
+# if defined(PS_SO_OOBINLINE)
+ if (opt & PS_SO_OOBINLINE) {
+ (void) printf("%cOOBINLINE", sep);
+ opt &= ~PS_SO_OOBINLINE;
+ sep = ',';
+ }
+# endif /* defined(PS_SO_OOBINLINE) */
+
+# if defined(PS_SO_PMTU)
+ if (opt & PS_SO_PMTU) {
+ (void) printf("%cPMTU", sep);
+ opt &= ~PS_SO_PMTU;
+ sep = ',';
+ }
+# endif /* defined(PS_SO_PMTU) */
+
+ if (Lf->lts.qlens) {
+ (void) printf("%cQLEN=%u", sep, Lf->lts.qlen);
+ sep = ',';
+ }
+ if (Lf->lts.qlims) {
+ (void) printf("%cQLIM=%u", sep, Lf->lts.qlim);
+ sep = ',';
+ }
+
+# if defined(PS_SO_REUSEADDR)
+ if (opt & PS_SO_REUSEADDR) {
+ (void) printf("%cREUSEADDR", sep);
+ opt &= ~PS_SO_REUSEADDR;
+ sep = ',';
+ }
+# endif /* defined(PS_SO_REUSEADDR) */
+
+# if defined(PS_SO_REUSEPORT)
+ if (opt & PS_SO_REUSEPORT) {
+ (void) printf("%cREUSEPORT", sep);
+ opt &= ~PS_SO_REUSEPORT;
+ sep = ',';
+ }
+# endif /* defined(PS_SO_REUSEPORT) */
+
+# if defined(PS_SO_USELOOPBACK)
+ if (opt & PS_SO_USELOOPBACK) {
+ (void) printf("%cUSELOOPBACK", sep);
+ opt &= ~PS_SO_USELOOPBACK;
+ sep = ',';
+ }
+# endif /* defined(PS_SO_USELOOPBACK) */
+
+ if (opt)
+ (void) printf("%cUNKNOWN=%#x", sep, opt);
+ if (Ffield)
+ putchar(Terminator);
+ }
+ }
+#endif /* defined(HASSOOPT) */
+
+#if defined(HASSOSTATE)
+ if (Ftcptpi & TCPTPI_FLAGS) {
+ int ss;
+
+ if ((ss = Lf->lts.ss)) {
+ char sep = ' ';
+
+ if (Ffield)
+ sep = LSOF_FID_TCPTPI;
+ else if (!ps)
+ sep = '(';
+ (void) printf("%cSS", sep);
+ ps++;
+ sep = '=';
+
+# if defined(PS_SS_ASYNC)
+ if (ss & PS_SS_ASYNC) {
+ (void) printf("%cASYNC", sep);
+ ss &= ~PS_SS_ASYNC;
+ sep = ',';
+ }
+# endif /* defined(PS_SS_ASYNC) */
+
+# if defined(PS_SS_BOUND)
+ if (ss & PS_SS_BOUND) {
+ (void) printf("%cBOUND", sep);
+ ss &= ~PS_SS_BOUND;
+ sep = ',';
+ }
+# endif /* defined(PS_SS_BOUND) */
+
+# if defined(PS_SS_CANTRCVMORE)
+ if (ss & PS_SS_CANTRCVMORE) {
+ (void) printf("%cCANTRCVMORE", sep);
+ ss &= ~PS_SS_CANTRCVMORE;
+ sep = ',';
+ }
+# endif /* defined(PS_SS_CANTRCVMORE) */
+
+# if defined(PS_SS_CANTSENDMORE)
+ if (ss & PS_SS_CANTSENDMORE) {
+ (void) printf("%cCANTSENDMORE", sep);
+ ss &= ~PS_SS_CANTSENDMORE;
+ sep = ',';
+ }
+# endif /* defined(PS_SS_CANTSENDMORE) */
+
+# if defined(PS_SS_ISCONNECTED)
+ if (ss & PS_SS_ISCONNECTED) {
+ (void) printf("%cISCONNECTED", sep);
+ ss &= ~PS_SS_ISCONNECTED;
+ sep = ',';
+ }
+# endif /* defined(PS_SS_ISCONNECTED) */
+
+# if defined(PS_SS_ISCONNECTING)
+ if (ss & PS_SS_ISCONNECTING) {
+ (void) printf("%cISCONNECTING", sep);
+ ss &= ~PS_SS_ISCONNECTING;
+ sep = ',';
+ }
+# endif /* defined(PS_SS_ISCONNECTING) */
+
+# if defined(PS_SS_ISDISCONNECTI)
+ if (ss & PS_SS_ISDISCONNECTI) {
+ (void) printf("%cISDISCONNECTI", sep);
+ ss &= ~PS_SS_ISDISCONNECTI;
+ sep = ',';
+ }
+# endif /* defined(PS_SS_ISDISCONNECTI) */
+
+# if defined(PS_SS_INTERRUPTED)
+ if (ss & PS_SS_INTERRUPTED) {
+ (void) printf("%cINTERRUPTED", sep);
+ ss &= ~PS_SS_INTERRUPTED;
+ sep = ',';
+ }
+# endif /* defined(PS_SS_INTERRUPTED) */
+
+# if defined(PS_SS_NBIO)
+ if (ss & PS_SS_NBIO) {
+ (void) printf("%cNBIO", sep);
+ ss &= ~PS_SS_NBIO;
+ sep = ',';
+ }
+# endif /* defined(PS_SS_NBIO) */
+
+# if defined(PS_SS_NOFDREF)
+ if (ss & PS_SS_NOFDREF) {
+ (void) printf("%cNOFDREF", sep);
+ ss &= ~PS_SS_NOFDREF;
+ sep = ',';
+ }
+# endif /* defined(PS_SS_NOFDREF) */
+
+# if defined(PS_SS_NOUSER)
+ if (ss & PS_SS_NOUSER) {
+ (void) printf("%cNOUSER", sep);
+ ss &= ~PS_SS_NOUSER;
+ sep = ',';
+ }
+# endif /* defined(PS_SS_NOUSER) */
+
+# if defined(PS_SS_NOWAIT)
+ if (ss & PS_SS_NOWAIT) {
+ (void) printf("%cNOWAIT", sep);
+ ss &= ~PS_SS_NOWAIT;
+ sep = ',';
+ }
+# endif /* defined(PS_SS_NOWAIT) */
+
+# if defined(PS_SS_PRIV)
+ if (ss & PS_SS_PRIV) {
+ (void) printf("%cPRIV", sep);
+ ss &= ~PS_SS_PRIV;
+ sep = ',';
+ }
+# endif /* defined(PS_SS_PRIV) */
+
+# if defined(PS_SS_RCVATMARK)
+ if (ss & PS_SS_RCVATMARK) {
+ (void) printf("%cRCVATMARK", sep);
+ ss &= ~PS_SS_RCVATMARK;
+ sep = ',';
+ }
+# endif /* defined(PS_SS_RCVATMARK) */
+
+# if defined(PS_SS_XOPEN_EXT1)
+ if (ss & PS_SS_XOPEN_EXT1) {
+ (void) printf("%cXOPEN_EXT1", sep);
+ ss &= ~PS_SS_XOPEN_EXT1;
+ sep = ',';
+ }
+# endif /* defined(PS_SS_XOPEN_EXT1) */
+
+ if (ss)
+ (void) printf("%cUNKNOWN=%#x", sep, ss);
+ if (Ffield)
+ putchar(Terminator);
+ }
+ }
+#endif /* defined(HASSOSTATE) */
+
+#if defined(HASTCPTPIW)
+ if (Ftcptpi & TCPTPI_WINDOWS) {
+ if (Lf->lts.rws) {
+ if (Ffield)
+ putchar(LSOF_FID_TCPTPI);
+ else {
+ if (ps)
+ putchar(' ');
+ else
+ putchar('(');
+ }
+ (void) printf("WR=%lu", Lf->lts.rw);
+ if (Ffield)
+ putchar(Terminator);
+ ps++;
+ }
+ if (Lf->lts.wws) {
+ if (Ffield)
+ putchar(LSOF_FID_TCPTPI);
+ else {
+ if (ps)
+ putchar(' ');
+ else
+ putchar('(');
+ }
+ (void) printf("WW=%lu", Lf->lts.ww);
+ if (Ffield)
+ putchar(Terminator);
+ ps++;
+ }
+ }
+#endif /* defined(HASTCPTPIW) */
+
+ if (Ftcptpi && !Ffield && ps)
+ putchar(')');
+ if (nl)
+ putchar('\n');
+}
+
+
+/*
+ * process_socket() -- process socket
+ */
+
+void
+process_socket(f, s)
+ struct pst_fileinfo2 *f; /* file information */
+ struct pst_socket *s; /* optional socket information
+ * NULL == none */
+{
+ int af, err, fp, lp, tx;
+ char buf[1024], tbuf[32];
+ unsigned char *fa = (unsigned char *)NULL;
+ unsigned char *la = (unsigned char *)NULL;
+ size_t len;
+ KA_T na, nau;
+ char *nma = (char *)NULL;
+ struct pst_filedetails pd;
+ struct sockaddr_in *sa;
+ int sx;
+
+#if defined(HASIPv6)
+ struct sockaddr_in6 *sa6;
+#endif /* defined(HASIPv6) */
+
+ struct sockaddr_un *ua;
+/*
+ * Read socket info, as required, so that the protocol state names can be
+ * tested as soon as possible.
+ */
+ if (!s) {
+ if (!(s = read_sock(f))) {
+ (void) snpf(Namech, Namechl,
+ "can't read pst_socket%s%s", errno ? ": " : "",
+ errno ? strerror(errno) : "");
+ (void) enter_nm(Namech);
+ return;
+ }
+ }
+/*
+ * Collect protocol details so the protocol state name might be tested,
+ * as requested by options.
+ */
+ switch (s->pst_family) {
+ case PS_AF_INET:
+ af = 4;
+ break;
+
+#if defined(HASIPv6)
+ case PS_AF_INET6:
+ af = 6;
+ break;
+#endif /* defined(HASIPv6) */
+
+ default:
+ af = -1;
+ }
+ switch (s->pst_protocol) {
+ case PS_PROTO_TCP:
+ sx = (int)s->pst_pstate + TcpStOff;
+ tx = 0;
+ break;
+ case PS_PROTO_UDP:
+ sx = (unsigned int)s->pst_pstate + UdpStOff;
+ tx = 1;
+ break;
+ default:
+ sx = tx = -1;
+ }
+/*
+ * Test the protocol state and name, setting the SELNET flag where possible.
+ */
+ switch (tx) {
+ case 0: /* TCP */
+ if (TcpStXn) {
+
+ /*
+ * Check for TCP state exclusion.
+ */
+ if (sx >= 0 && sx < TcpNstates) {
+ if (TcpStX[sx]) {
+ Lf->sf |= SELEXCLF;
+ return;
+ }
+ }
+ }
+ if (TcpStIn) {
+ if (sx >= 0 && sx < TcpNstates) {
+ if (TcpStI[sx])
+ TcpStI[sx] = 2;
+ else {
+ Lf->sf |= SELEXCLF;
+ return;
+ }
+ }
+ }
+ break;
+ case 1: /* UDP */
+ if (UdpStXn) {
+
+ /*
+ * Check for UDP state exclusion.
+ */
+ if (sx >= 0 && sx < UdpNstates) {
+ if (UdpStX[sx]) {
+ Lf->sf |= SELEXCLF;
+ return;
+ }
+ }
+ }
+ if (UdpStIn) {
+ if (sx >= 0 && sx < UdpNstates) {
+ if (UdpStI[sx])
+ UdpStI[sx] = 2;
+ else {
+ Lf->sf |= SELEXCLF;
+ return;
+ }
+ }
+ }
+ break;
+ }
+/*
+ * Set default type.
+ */
+ (void) snpf(Lf->type, sizeof(Lf->type), "sock");
+ Lf->inp_ty = 2;
+/*
+ * Generate and save node ID.
+ */
+ na = (KA_T)(((KA_T)(f->psf_hi_nodeid & 0xffffffff) << 32)
+ | (KA_T)(f->psf_lo_nodeid & 0xffffffff));
+
+#if defined(HASFSTRUCT)
+ if (na && (Fsv & FSV_NI)) {
+ if (na) {
+ Lf->fna = na;
+ Lf->fsv |= FSV_NI;
+ }
+ }
+#endif /* defined(HASFSTRUCT) */
+
+/*
+ * Save size information, as requested.
+ */
+ if (Fsize) {
+ if (Lf->access == 'r')
+ Lf->sz = (SZOFFTYPE)s->pst_idata;
+ else if (Lf->access == 'w')
+ Lf->sz = (SZOFFTYPE)s->pst_odata;
+ else
+ Lf->sz = (SZOFFTYPE)(s->pst_idata + s->pst_odata);
+ Lf->sz_def = 1;
+ } else
+ Lf->off_def = 1;
+
+#if defined(HASTCPTPIQ)
+/*
+ * Enter queue sizes.
+ */
+ switch (s->pst_family) {
+ case PS_AF_INET:
+ case PS_AF_INET6:
+ Lf->lts.rq = (unsigned long)s->pst_idata;
+ Lf->lts.sq = (unsigned long)s->pst_odata;
+ Lf->lts.rqs = Lf->lts.sqs = (unsigned char)1;
+ }
+#endif /* defined(HASTCPTPIQ) */
+
+#if defined(HASSOOPT)
+/*
+ * Enter socket options.
+ */
+ Lf->lts.opt = (unsigned int)s->pst_options;
+ Lf->lts.ltm = (unsigned int)s->pst_linger;
+ Lf->lts.qlen = (unsigned int)s->pst_qlen;
+ Lf->lts.qlim = (unsigned int)s->pst_qlimit;
+ Lf->lts.qlens = Lf->lts.qlims = (unsigned char)1;
+#endif /* defined(HASSOOPT) */
+
+#if defined(HASSOSTATE)
+/*
+ * Enter socket state flags.
+ */
+ Lf->lts.ss = (unsigned int)s->pst_state;
+#endif /* defined(HASSOSTATE) */
+
+#if defined(HASTCPTPIW)
+/*
+ * Enter window sizes.
+ */
+ switch (s->pst_family) {
+ case PS_AF_INET:
+ case PS_AF_INET6:
+ Lf->lts.rw = (unsigned long)s->pst_rwnd;
+ Lf->lts.ww = (unsigned long)s->pst_swnd;
+ Lf->lts.rws = Lf->lts.wws = (unsigned char)1;
+ }
+#endif /* defined(HASTCPTPIW) */
+
+/*
+ * Process socket by the associated domain family.
+ */
+ switch (s->pst_family) {
+ case PS_AF_INET:
+ if (Fnet && (!FnetTy || (FnetTy != 6)))
+ Lf->sf |= SELNET;
+ (void) snpf(Lf->type, sizeof(Lf->type),
+
+#if defined(HASIPv6)
+ "IPv4"
+#else /* !defined(HASIPv6) */
+ "inet"
+#endif /* defined(HASIPv6) */
+
+ );
+ printpsproto(s->pst_protocol);
+ enter_dev_ch(print_kptr(na, (char *)NULL, 0));
+ switch (s->pst_protocol) {
+ case PS_PROTO_TCP:
+ Lf->lts.type = 0;
+ Lf->lts.state.i = (int)s->pst_pstate;
+ break;
+ case PS_PROTO_UDP:
+ Lf->lts.type = 1;
+ Lf->lts.state.ui = (unsigned int)s->pst_pstate;
+ }
+ /*
+ * Enter local and remote addresses, being careful to generate
+ * proper IPv4 address alignment by copying, since IPv4 addresses
+ * may not be properly aligned in pst_boundaddr[] and pst_remaddr[].
+ */
+ if ((size_t)s->pst_boundaddr_len == sizeof(struct sockaddr_in)) {
+ sa = (struct sockaddr_in *)s->pst_boundaddr;
+ la = (unsigned char *)&sa->sin_addr;
+ lp = (int)htons(sa->sin_port);
+ }
+ if ((size_t)s->pst_remaddr_len == sizeof(struct sockaddr_in)) {
+ sa = (struct sockaddr_in *)s->pst_remaddr;
+ fp = (int)htons(sa->sin_port);
+ if ((sa->sin_addr.s_addr != INADDR_ANY) || fp)
+ fa = (unsigned char *)&sa->sin_addr;
+ }
+ if (fa || la)
+ (void) ent_inaddr(la, lp, fa, fp, AF_INET);
+ break;
+
+#if defined(HASIPv6)
+ case PS_AF_INET6:
+ af = AF_INET6;
+ if (Fnet && (!FnetTy || (FnetTy != 4)))
+ Lf->sf |= SELNET;
+ (void) snpf(Lf->type, sizeof(Lf->type), "IPv6");
+ printpsproto(s->pst_protocol);
+ enter_dev_ch(print_kptr(na, (char *)NULL, 0));
+ switch (s->pst_protocol) {
+ case PS_PROTO_TCP:
+ Lf->lts.type = 0;
+ Lf->lts.state.i = (int)s->pst_pstate;
+ break;
+ case PS_PROTO_UDP:
+ Lf->lts.type = 1;
+ Lf->lts.state.ui = (unsigned int)s->pst_pstate;
+ }
+ /*
+ * Enter local and remote addresses, being careful to generate
+ * proper IPv6 address alignment by copying, since IPv6 addresses
+ * may not be properly aligned in pst_boundaddr[] and pst_remaddr[].
+ */
+ if ((size_t)s->pst_boundaddr_len == sizeof(struct sockaddr_in6)) {
+ sa6 = (struct sockaddr_in6 *)s->pst_boundaddr;
+ la = (unsigned char *)&sa6->sin6_addr;
+ lp = (int)htons(sa6->sin6_port);
+ }
+ if ((size_t)s->pst_remaddr_len == sizeof(struct sockaddr_in6)) {
+ sa6 = (struct sockaddr_in6 *)s->pst_remaddr;
+ if ((fp = (int)htons(sa6->sin6_port))
+ || !IN6_IS_ADDR_UNSPECIFIED(&sa6->sin6_addr))
+ fa = (unsigned char *)&sa6->sin6_addr;
+ }
+ if (la || fa) {
+ if ((la && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)la))
+ || (fa && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)fa)))
+ {
+ if (la)
+ la = (unsigned char *)IPv6_2_IPv4(la);
+ if (fa)
+ fa = (unsigned char *)IPv6_2_IPv4(fa);
+ af = AF_INET;
+ }
+ }
+ if (fa || la)
+ (void) ent_inaddr(la, lp, fa, fp, af);
+ break;
+#endif /* defined(HASIPv6) */
+
+ case PS_AF_UNIX:
+ if (Funix)
+ Lf->sf |= SELUNX;
+ (void) snpf(Lf->type, sizeof(Lf->type), "unix");
+ if (((len = (size_t)s->pst_boundaddr_len) > 0)
+ && (len <= sizeof(struct sockaddr_un)))
+ {
+ ua = (struct sockaddr_un *)s->pst_boundaddr;
+ if (ua->sun_path[0]) {
+
+ /*
+ * The AF_UNIX socket has a bound address (file path).
+ *
+ * Save it. If there is a low nodeid, put that in
+ * parentheses after the name. If there is a low peer
+ * nodeid, put that in the parentheses, too.
+ */
+ s->pst_boundaddr[PS_ADDR_SZ - 1] = '\0';
+ if (s->pst_lo_nodeid) {
+ (void) snpf(buf, sizeof(buf), "(%s%s%s)",
+ print_kptr((KA_T)s->pst_lo_nodeid,
+ tbuf, sizeof(tbuf)),
+ s->pst_peer_lo_nodeid ? "->" : "",
+ s->pst_peer_lo_nodeid ?
+ print_kptr((KA_T)s->pst_peer_lo_nodeid,
+ (char *)NULL, 0)
+ : ""
+ );
+ len = strlen(buf) + 1;
+ if (!(nma = (char *)malloc((MALLOC_S)len))) {
+ (void) fprintf(stderr,
+ "%s: no unix nma space(1): PID %ld, FD %s",
+ Pn, (long)Lp->pid, Lf->fd);
+ }
+ (void) snpf(nma, len, "%s", buf);
+ Lf->nma = nma;
+ }
+ /*
+ * Read the pst_filedetails for the bound address and process
+ * them as for a regular file. The already-entered file type,
+ * file name, size or offset, and name appendix will be
+ * preserved.
+ */
+ if ((nau = read_det(&f->psf_fid, f->psf_hi_fileid,
+ f->psf_lo_fileid, f->psf_hi_nodeid,
+ f->psf_lo_nodeid, &pd)))
+ {
+ enter_nm(ua->sun_path);
+ (void) process_finfo(&pd, &f->psf_fid, &f->psf_id, nau);
+ return;
+ } else {
+
+ /*
+ * Couldn't read file details. Erase any name appendix.
+ * Put the socket nodeid in the DEVICE column, put the
+ * bound address (path) in the NAME column, and build
+ * a new name appendix with the peer address. Add an
+ * error message if pstat_getfiledetails() set errno to
+ * something other than ENOENT.
+ */
+ if ((err = errno) == ENOENT)
+ err = 0;
+ if (nma) {
+ (void) free((MALLOC_P *)nma);
+ Lf->nma = (char *)NULL;
+ }
+ if (s->pst_lo_nodeid) {
+ enter_dev_ch(print_kptr((KA_T)s->pst_lo_nodeid,
+ (char *)NULL, 0));
+ }
+ (void) snpf(Namech, Namechl, "%s", ua->sun_path);
+ if (err || s->pst_peer_lo_nodeid) {
+ (void) snpf(buf, sizeof(buf),
+ "%s%s%s%s%s%s%s",
+ err ? "(Error: " : "",
+ err ? strerror(err) : "",
+ err ? ")" : "",
+ (err && s->pst_peer_lo_nodeid) ? " " : "",
+ s->pst_peer_lo_nodeid ? "(->" : "",
+ s->pst_peer_lo_nodeid ?
+ print_kptr((KA_T)s->pst_peer_lo_nodeid,
+ (char *)NULL, 0)
+ : "",
+ s->pst_peer_lo_nodeid ? ")" : ""
+ );
+ len = strlen(buf) + 1;
+ if (!(nma = (char *)malloc((MALLOC_S)len))) {
+ (void) fprintf(stderr,
+ "%s: no unix nma space(2): PID %ld, FD %s",
+ Pn, (long)Lp->pid, Lf->fd);
+ }
+ (void) snpf(nma, len, "%s", buf);
+ Lf->nma = nma;
+ }
+ if (Sfile && is_file_named(ua->sun_path, 0))
+ Lf->sf |= SELNM;
+ break;
+ }
+ }
+ }
+ /*
+ * If the UNIX socket has no bound address (file path), display the
+ * low nodeid in the DEVICE column and the peer's low nodeid in the
+ * NAME column.
+ */
+ if (s->pst_peer_lo_nodeid) {
+ (void) snpf(Namech, Namechl, "->%s",
+ print_kptr((KA_T)s->pst_peer_lo_nodeid, (char *)NULL, 0));
+ }
+ if (s->pst_lo_nodeid)
+ enter_dev_ch(print_kptr((KA_T)s->pst_lo_nodeid,(char *)NULL,0));
+ break;
+ default:
+ (void) snpf(Namech, Namechl, "unsupported family: AF_%d",
+ s->pst_family);
+ }
+ if (Namech[0])
+ enter_nm(Namech);
+}
+
+
+/*
+ * process_stream() -- process stream
+ */
+
+void
+process_stream(f, ckscko)
+ struct pst_fileinfo2 *f; /* pst_fileinfo2 */
+ int ckscko; /* socket file only checking
+ * if 1 */
+{
+ struct clone *cl;
+ char *cp;
+ struct l_dev *dp = (struct l_dev *)NULL;
+ int hx, i, ncx, nsn, nsr;
+ size_t nb, nl;
+ KA_T na;
+ static int nsa = 0;
+ dev_t rdev;
+ static struct pst_stream *s = (struct pst_stream *)NULL;
+ struct pst_socket sck;
+ static size_t sz = sizeof(struct pst_stream);
+
+#if !defined(PS_STR_XPORT_DATA)
+/*
+ * If socket file only checking is enabled and this HP-UX PSTAT instance
+ * doesn't support TCP or UDP stream eXPORT data, return without further
+ * action.
+ */
+ if (ckscko == 1)
+ return;
+#endif /* !defined(PS_STR_XPORT_DATA) */
+
+/*
+ * Generate and save node ID.
+ */
+ na = (KA_T)(((KA_T)(f->psf_hi_nodeid & 0xffffffff) << 32)
+ | (KA_T)(f->psf_lo_nodeid & 0xffffffff));
+
+#if defined(HASFSTRUCT)
+ if (na && (Fsv & FSV_NI)) {
+ Lf->fna = na;
+ Lf->fsv |= FSV_NI;
+ }
+#endif /* defined(HASFSTRUCT) */
+
+/*
+ * Enter type.
+ */
+ switch (f->psf_ftype) {
+ case PS_TYPE_STREAMS:
+ cp = "STR";
+ break;
+ case PS_TYPE_SOCKET:
+ if (f->psf_subtype == PS_SUBTYPE_SOCKSTR) {
+ cp = "STSO";
+ break;
+ }
+ /* fall through */
+ default:
+ cp = "unkn";
+ }
+ (void) snpf(Lf->type, sizeof(Lf->type), "%s", cp);
+/*
+ * Allocate sufficient space for stream structures, then read them.
+ */
+ if ((nsn = f->psf_nstrentt) && (nsn >= nsa)) {
+ nb = (size_t)(nsn * sizeof(struct pst_stream));
+ if (s)
+ s = (struct pst_stream *)realloc((MALLOC_P *)s, nb);
+ else
+ s = (struct pst_stream *)malloc(nb);
+ if (!s) {
+ (void) fprintf(stderr,
+ "%s: no space for %ld pst_stream bytes\n", Pn, (long)nb);
+ Exit(1);
+ }
+ nsa = nsn;
+ }
+ errno = 0;
+ if ((nsr = pstat_getstream(s, sz, (size_t)nsn, 0, &f->psf_fid)) < 1) {
+ if (nsn) {
+ (void) snpf(Namech, Namechl,
+ "can't read %d stream structures%s%s", nsn,
+ errno ? ": " : "", errno ? strerror(errno) : "");
+ enter_nm(Namech);
+ } else
+ enter_nm("no stream structures present");
+ return;
+ }
+/*
+ * Find the stream head.
+ */
+ for (hx = 0; hx < nsn; hx++) {
+ if (s[hx].type == PS_STR_HEAD)
+ break;
+ }
+ if (hx >= nsn) {
+ enter_nm("no stream head located");
+ return;
+ }
+/*
+ * Make sure the stream head's fileid and nodeid match the ones in the
+ * pst_fileino2 structure.
+ */
+ if ((f->psf_hi_fileid != s[hx].val.head.pst_hi_fileid)
+ | (f->psf_lo_fileid != s[hx].val.head.pst_lo_fileid)
+ | (f->psf_hi_nodeid != s[hx].val.head.pst_hi_nodeid)
+ | (f->psf_lo_nodeid != s[hx].val.head.pst_lo_nodeid)) {
+ enter_nm("no matching stream data available");
+ return;
+ }
+
+#if defined(PS_STR_XPORT_DATA)
+/*
+ * See if this stream has eXPORT data available and is a TCP or
+ * UDP stream.
+ */
+ if ((s[hx].pst_extn_flags & PS_STR_XPORT_DATA)
+ && ((s[hx].pst_str_xport_protocol == PS_STR_XPORT_TCP_PROTO)
+ || (s[hx].pst_str_xport_protocol == PS_STR_XPORT_UDP_PROTO))
+ ) {
+
+ /*
+ * Make a socket from the eXPORT data and process it.
+ */
+ (void) make_sock(f, &s[hx], &sck);
+ (void) process_socket(f, &sck);
+ return;
+ } else if (ckscko || Selinet) {
+
+ /*
+ * If socket file or Internet file only processing is enabled, return.
+ */
+ return;
+ }
+#endif /* defined(PS_STR_XPORT_DATA) */
+
+/*
+ * Enter size from stream head's structure, if requested.
+ */
+ if (Fsize) {
+ if (Lf->access == 'r') {
+ Lf->sz = (SZOFFTYPE)s[hx].val.head.pst_rbytes;
+ Lf->sz_def = 1;
+ } else if (Lf->access == 'w') {
+ Lf->sz = (SZOFFTYPE)s[hx].val.head.pst_wbytes;
+ Lf->sz_def = 1;
+ } else if (Lf->access == 'u') {
+ Lf->sz = (SZOFFTYPE)s[hx].val.head.pst_rbytes
+ + (SZOFFTYPE)s[hx].val.head.pst_wbytes;
+ Lf->sz_def = 1;
+ }
+ }
+/*
+ * Get the the device number from the stream head.
+ *
+ * If the stream is a clone:
+ *
+ * if there's a clone list, search it for the device, based on the stream
+ * head's minor device number only;
+ * if there's no clone list, search Devtp[], using a device number made
+ * from the stream head's major and minor device numbers;
+ * set the printable clone device number to one whose major device number
+ * is the stream head's minor device number, and whose minor device
+ * number is the stream head's device sequence number.
+ *
+ * If the stream isn't a clone, make the device number from the stream head's
+ * major and minor numbers, and look up the non-clone device number in Devtp[].
+ */
+ if (!Sdev)
+ readdev(0);
+ if (s[hx].val.head.pst_flag & PS_STR_ISACLONE) {
+ if (HaveCloneMaj && (CloneMaj == s[hx].val.head.pst_dev_major)) {
+ for (cl = Clone; cl; cl = cl->next) {
+ if (GET_MIN_DEV(Devtp[cl->dx].rdev)
+ == s[hx].val.head.pst_dev_minor)
+ {
+ dp = &Devtp[cl->dx];
+ break;
+ }
+ }
+ } else {
+ rdev = makedev(s[hx].val.head.pst_dev_major,
+ s[hx].val.head.pst_dev_minor);
+ dp = lkupdev(&DevDev, &rdev, 0, 1);
+ }
+ rdev = makedev(s[hx].val.head.pst_dev_minor,
+ s[hx].val.head.pst_dev_seq);
+ } else {
+ rdev = makedev(s[hx].val.head.pst_dev_major,
+ s[hx].val.head.pst_dev_minor);
+ dp = lkupdev(&DevDev, &rdev, 0, 1);
+ }
+ Lf->dev = DevDev;
+ Lf->rdev = rdev;
+ Lf->dev_def = Lf->rdev_def = 1;
+/*
+ * If the device was located, enter the device name and save the node number.
+ *
+ * If the device wasn't located, save a positive file ID number from the
+ * pst_fileinfo as a node number.
+ */
+ if (dp) {
+ (void) snpf(Namech, Namechl, "%s", dp->name);
+ ncx = strlen(Namech);
+ Lf->inode = (INODETYPE)dp->inode;
+ Lf->inp_ty = 1;
+ } else {
+ ncx = (size_t)0;
+ if (f->psf_id.psf_fileid > 0) {
+ Lf->inode = (INODETYPE)f->psf_id.psf_fileid;
+ Lf->inp_ty = 1;
+ }
+ }
+/*
+ * Enter stream module names.
+ */
+ for (i = 1; i < nsr; i++) {
+ if (!(nl = strlen(s[i].val.module.pst_name)))
+ continue;
+ if (ncx) {
+ if ((ncx + 2) > (Namechl - 1))
+ break;
+ (void) snpf(&Namech[ncx], Namechl - ncx, "->");
+ ncx += 2;
+ }
+ if ((ncx + nl) > (Namechl - 1))
+ break;
+ (void) snpf(Namech+ncx,Namechl-ncx,"%s",s[i].val.module.pst_name);
+ ncx += nl;
+ }
+/*
+ * Set node type.
+ *
+ * Set offset defined if file size not requested or if no size was
+ * obtained from the stream head.
+ */
+ Lf->ntype = N_STREAM;
+ Lf->is_stream = 1;
+ if (!Fsize || (Fsize && !Lf->sz_def))
+ Lf->off_def = 1;
+/*
+ * Test for specified file.
+ */
+ if ((f->psf_subtype == PS_SUBTYPE_CHARDEV)
+ || (f->psf_subtype == PS_SUBTYPE_BLKDEV))
+ i = 1;
+ else
+ i = 0;
+ if (Sfile && is_file_named((char *)NULL, i))
+ Lf->sf |= SELNM;
+/*
+ * Enter any name characters.
+ */
+ if (Namech[0])
+ enter_nm(Namech);
+}
+
+
+/*
+ * read_sock() -- read pst_socket info for file
+ */
+
+struct pst_socket *
+read_sock(f)
+ struct pst_fileinfo2 *f; /* file information */
+{
+ static struct pst_socket s;
+
+ errno = 0;
+ if (f) {
+ if (pstat_getsocket(&s, sizeof(s), &f->psf_fid) > 0
+ && f->psf_hi_fileid == s.pst_hi_fileid
+ && f->psf_lo_fileid == s.pst_lo_fileid
+ && f->psf_hi_nodeid == s.pst_hi_nodeid
+ && f->psf_lo_nodeid == s.pst_lo_nodeid)
+ return(&s);
+ }
+ return((struct pst_socket *)NULL);
+}
diff --git a/dialects/hpux/pstat/dstore.c b/dialects/hpux/pstat/dstore.c
new file mode 100644
index 0000000..d0a87f5
--- /dev/null
+++ b/dialects/hpux/pstat/dstore.c
@@ -0,0 +1,80 @@
+/*
+ * dstore.c - pstat-based HP-UX global storage 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"
+
+
+/*
+ * Global storage definitions
+ */
+
+_T_LONG_T CloneMaj; /* clone major device number */
+int HasNFS = -1; /* NFS-mounted file system status:
+ * -1: not yet tested;
+ * 0: tested and none mounted;
+ * 1: tested and some mounted */
+int HaveCloneMaj = 0; /* CloneMaj status */
+
+#if defined(HASFSTRUCT)
+/*
+ * Pff_tab[] - table for printing file flags
+ */
+
+struct pff_tab Pff_tab[] = {
+ { (long)PS_FRDONLY, FF_READ },
+ { (long)PS_FWRONLY, FF_WRITE },
+ { (long)PS_FAPPEND, FF_APPEND },
+ { (long)PS_FNODELY, FF_NDELAY },
+ { (long)PS_FNBLOCK, FF_NBLOCK },
+ { (long)PS_FSYNC, FF_SYNC },
+ { (long)PS_FDSYNC, FF_DSYNC },
+ { (long)PS_FRSYNC, FF_RSYNC },
+ { (long)PS_FLGFILE, FF_LARGEFILE },
+ { (long)0, NULL }
+};
+
+
+/*
+ * Pof_tab[] - table for print process open file flags
+ */
+
+struct pff_tab Pof_tab[] = {
+ { (long)PS_FEXCLOS, POF_CLOEXEC },
+ { (long)0, NULL }
+};
+#endif /* defined(HASFSTRUCT) */
diff --git a/dialects/hpux/pstat/machine.h b/dialects/hpux/pstat/machine.h
new file mode 100644
index 0000000..2555e80
--- /dev/null
+++ b/dialects/hpux/pstat/machine.h
@@ -0,0 +1,648 @@
+/*
+ * machine.h - pstat-based HP-UX definitions 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.
+ */
+
+
+/*
+ * $Id: machine.h,v 1.22 2010/07/29 16:03:12 abe Exp $
+ */
+
+
+#if !defined(LSOF_MACHINE_H)
+#define LSOF_MACHINE_H 1
+
+
+# if defined(__GNUC__)
+/*
+ * Do gcc preparation.
+ */
+
+# if !defined( __STDC_EXT__)
+#define __STDC_EXT__
+# endif /* !defined( __STDC_EXT__) */
+
+#include <sys/_inttypes.h>
+
+# if HPUXV>=1123
+#undef LSOF_XOPEN_SOURCE_EXTENDED
+# if defined(_XOPEN_SOURCE_EXTENDED)
+#define LSOF_XOPEN_SOURCE_EXTENDED _XOPEN_SOURCE_EXTENDED
+#undef _XOPEN_SOURCE_EXTENDED
+# endif /* defined(_XOPEN_SOURCE_EXTENDED) */
+#include <netdb.h>
+# if defined(LSOF_XOPEN_SOURCE_EXTENDED)
+#define _XOPEN_SOURCE_EXTENDED LSOF_XOPEN_SOURCE_EXTENDED
+#undef LSOF_XOPEN_SOURCE_EXTENDED
+# endif /* defined(_XOPEN_SOURCE_EXTENDED) */
+# endif /* HPUXV>=1123 */
+# endif /* defined(__GNUC__) */
+
+
+/*
+ * Make sure a 32 bit lsof for HP-UX<1123 uses [l]stat64()
+ */
+
+#if !defined(__LP64__) && HPUXV<1123
+#define lstat lstat64
+#define stat stat64
+#endif /* !defined(__LP64__) && HPUXV<1123 */
+
+
+/*
+ * CAN_USE_CLNT_CREATE is defined for those dialects where RPC clnt_create()
+ * can be used to obtain a CLIENT handle in lieu of clnttcp_create().
+ */
+
+#define CAN_USE_CLNT_CREATE 1
+
+
+/*
+ * DEVDEV_PATH defines the path to the directory that contains device
+ * nodes.
+ */
+
+#define DEVDEV_PATH "/dev"
+
+
+/*
+ * GET_MAX_FD is defined for those dialects that provide a function other than
+ * getdtablesize() to obtain the maximum file descriptor number plus one.
+ */
+
+#define GET_MAX_FD get_max_fd
+
+
+/*
+ * HASAOPT is defined for those dialects that have AFS support; it specifies
+ * that the default path to an alternate AFS kernel name list file may be
+ * supplied with the -A <path> option.
+ */
+
+/* #define HASAOPT 1 */
+
+
+/*
+ * HASBLKDEV is defined for those dialects that want block device information
+ * recorded in BDevtp[].
+ */
+
+#define HASBLKDEV 1
+
+
+/*
+ * HASCDRNODE is defined for those dialects that have CD-ROM nodes.
+ */
+
+/* #define HASCDRNODE 1 */
+
+
+/*
+ * HASDCACHE is defined for those dialects that support a device cache
+ * file.
+ *
+ * HASENVDC defined the name of an environment variable that contains the
+ * device cache file path. The HASENVDC environment variable is ignored when
+ * the lsof process is setuid(root) or its real UID is 0.
+ *
+ * HASPERSDC defines the format for the last component of a personal device
+ * cache file path. The first will be the home directory of the real UID that
+ * executes lsof.
+ *
+ * HASPERSDCPATH defines the environment variable whose value is the middle
+ * component of the personal device cache file path. The middle component
+ * follows the home directory and precedes the results of applying HASPERSDC.
+ * The HASPERSDCPATH environment variable is ignored when the lsof process is
+ * setuid(root) or its real UID is 0.
+ *
+ * HASSYSDC defines a public device cache file path. When it's defined, it's
+ * used as the path from which to read the device cache.
+ *
+ * Consult the 00DCACHE and 00FAQ files of the lsof distribution for more
+ * information on device cache file path construction.
+ */
+
+#define HASDCACHE 1
+#define HASENVDC "LSOFDEVCACHE"
+#define HASPERSDC "%h/%p.lsof_%L"
+#define HASPERSDCPATH "LSOFPERSDCPATH"
+/* #define HASSYSDC "/your/choice/of/path" */
+
+
+/*
+ * HASFIFONODE is defined for those dialects that have FIFO nodes.
+ */
+
+/* #define HASFIFONODE 1 */
+
+
+/*
+ * HASFSINO is defined for those dialects that have the file system
+ * inode element, fs_ino, in the lfile structure definition in lsof.h.
+ */
+
+#define HASFSINO 1
+
+
+/*
+ * HASFSTRUCT is defined if the dialect has a file structure.
+ *
+ * FSV_DEFAULT defines the default set of file structure values to list.
+ * It defaults to zero (0), but may be made up of a combination of the
+ * FSV_* symbols from lsof.h.
+ *
+ * HASNOFSADDR -- has no file structure address
+ * HASNOFSFLAGS -- has no file structure flags
+ * HASNOFSCOUNT -- has no file structure count
+ * HASNOFSNADDR -- has no file structure node address
+ */
+
+#define HASFSTRUCT 1
+/* #define FSV_DEFAULT FSV_? | FSV_? | FSV_? */
+/* #define HASNOFSADDR 1 has no file structure address */
+/* #define HASNOFSFLAGS 1 has no file structure flags */
+/* #define HASNOFSCOUNT 1 has no file structure count */
+/* #define HASNOFSNADDR 1 has no file structure node address */
+
+
+/*
+ * HASGNODE is defined for those dialects that have gnodes.
+ */
+
+/* #define HASGNODE 1 */
+
+
+/*
+ * HASHSNODE is defined for those dialects that have High Sierra nodes.
+ */
+
+/* #define HASHSNODE 1 */
+
+
+/*
+ * HASINODE is defined for those dialects that have inodes and wish to
+ * use readinode() from node.c.
+ */
+
+/* #define HASINODE 1 */
+
+
+/*
+ * HASINTSIGNAL is defined for those dialects whose signal function returns
+ * an int.
+ */
+
+/* #define HASINTSIGNAL 1 */
+
+
+/*
+ * HASKERNIDCK is defined for those dialects that support the comparison of
+ * the build to running kernel identity.
+ */
+
+#define HASKERNIDCK 1
+
+
+/*
+ * HASKOPT is defined for those dialects that support the -k option of
+ * reading the kernel's name list from an optional file.
+ */
+
+/* #define HASKOPT 1 */
+
+
+/*
+ * HASLFILEADD is defined for those dialects that need additional elements
+ * in struct lfile. The HASLFILEADD definition is a macro that defines
+ * them. If any of the additional elements need to be preset in the
+ * alloc_lfile() function of proc.c, the SETLFILEADD macro may be defined
+ * to do that.
+ *
+ * If any additional elements need to be cleared in alloc_lfile() or in the
+ * free_proc() function of proc.c, the CLRLFILEADD macro may be defined to
+ * do that. Note that CLRLFILEADD takes one argument, the pointer to the
+ * lfile struct. The CLRLFILEADD macro is expected to expand to statements
+ * that are complete -- i.e., have terminating semi-colons -- so the macro is
+ * called without a terminating semicolon by proc.c.
+ *
+ * The HASXOPT definition may be used to select the conditions under which
+ * private lfile elements are used.
+ */
+
+#define HASLFILEADD struct pst_fid opfid; \
+ struct psfileid psfid;
+/* #define CLRLFILEADD(lf) (lf)->... = (type)NULL; */
+#define SETLFILEADD memset((void *)&Lf->opfid, 0, sizeof(struct pst_fid)); \
+ memset((void *)&Lf->psfid, 0, sizeof(struct psfileid));
+
+
+/*
+ * HASMNTSTAT indicates the dialect supports the mount stat(2) result option
+ * in its l_vfs and mounts structures.
+ */
+
+/* #define HASMNTSTAT 1 */
+
+
+/*
+ * HASMNTSUP is defined for those dialects that support the mount supplement
+ * option.
+ */
+
+/* #define HASMNTSUP 1 */
+
+
+/*
+ * HASMOPT is defined for those dialects that support the reading of
+ * kernel memory from an alternate file.
+ */
+
+/* #define HASMOPT 1 */
+
+
+/*
+ * HASNCACHE is defined for those dialects that have a kernel name cache
+ * that lsof can search. A value of 1 directs printname() to prefix the
+ * cache value with the file system directory name; 2, avoid the prefix.
+ *
+ * NCACHELDPFX is a set of C commands to execute before calling ncache_load().
+ *
+ * NCACHELDSFX is a set of C commands to execute after calling ncache_load().
+ */
+
+#define HASNCACHE 2
+/* #define NCACHELDPFX ??? */
+/* #define NCACHELDSFX ??? */
+
+
+/*
+ * HASNLIST is defined for those dialects that use nlist() to acccess
+ * kernel symbols.
+ */
+
+/* #define HASNLIST 1 */
+
+
+/*
+ * HASPIPEFN is defined for those dialects that have a special function to
+ * process DTYPE_PIPE file structure entries. Its value is the name of the
+ * function.
+ *
+ * NOTE: don't forget to define a prototype for this function in dproto.h.
+ */
+
+/* #define HASPIPEFN process_pipe? */
+
+
+/*
+ * HASPIPENODE is defined for those dialects that have pipe nodes.
+ */
+
+/* #define HASPIPENODE 1 */
+
+
+/*
+ * HASPMAPENABLED is defined when the reporting of portmapper registration
+ * info is enabled by default.
+ */
+
+/* #define HASPMAPENABLED 1 */
+
+
+/*
+ * HASPPID is defined for those dialects that support identification of
+ * the parent process IDentifier (PPID) of a process.
+ */
+
+#define HASPPID 1
+
+
+/*
+ * HASPRINTDEV, HASPRINTINO, HASPRINTNM, HASPRINTOFF, and HASPRINTSZ
+ * define private dialect-specific functions for printing DEVice numbers,
+ * INOde numbers, NaMes, file OFFsets, and file SiZes. The functions are
+ * called from print_file().
+ */
+
+#define HASPRINTDEV print_dev
+/* #define HASPRINTINO print_ino? */
+/* #define HASPRINTNM print_nm? */
+/* #define HASPRINTOFF print_off? */
+/* #define HASPRINTSZ print_sz? */
+
+
+/*
+ * HASPRIVFILETYPE and PRIVFILETYPE are defined for dialects that have a
+ * file structure type that isn't defined by a DTYPE_* symbol. They are
+ * used in lib/prfp.c to select the type's processing.
+ *
+ * PRIVFILETYPE is the definition of the f_type value in the file struct.
+ *
+ * HASPRIVFILETYPE is the name of the processing function.
+ */
+
+/* #define HASPRIVFILETYPE process_shmf? */
+/* #define PRIVFILETYPE ?? */
+
+
+/*
+ * HASPRIVNMCACHE is defined for dialects that have a private method for
+ * printing cached NAME column values for some files. HASPRIVNAMECACHE
+ * is defined to be the name of the function.
+ *
+ * The function takes one argument, a struct lfile pointer to the file, and
+ * returns non-zero if it prints a name to stdout.
+ */
+
+/* #define HASPRIVNMCACHE <function name> */
+
+
+/*
+ * HASPRIVPRIPP is defined for dialects that have a private function for
+ * printing IP protocol names. When HASPRIVPRIPP isn't defined, the
+ * IP protocol name printing function defaults to printiprto().
+ */
+
+#define HASPRIVPRIPP 1
+
+
+/*
+ * HASPROCFS is defined for those dialects that have a proc file system --
+ * usually /proc and usually in SYSV4 derivatives.
+ *
+ * HASFSTYPE is defined as 1 for those systems that have a file system type
+ * string, st_fstype, in the stat() buffer; 2, for those systems that have a
+ * file system type integer in the stat() buffer, named MOUNTS_STAT_FSTYPE;
+ * 0, for systems whose stat(2) structure has no file system type member. The
+ * additional symbols MOUNTS_FSTYPE, RMNT_FSTYPE, and RMNT_STAT_FSTYPE may be
+ * defined in dlsof.h to direct how the readmnt() function in lib/rmnt.c
+ * preserves these stat(2) and getmntent(3) buffer values in the local mounts
+ * structure.
+ *
+ * The defined value is the string that names the file system type.
+ *
+ * The HASPROCFS definition usually must be accompanied by the HASFSTYPE
+ * definition and the providing of an fstype element in the local mounts
+ * structure (defined in dlsof.h).
+ *
+ * The HASPROCFS definition may be accompanied by the HASPINODEN definition.
+ * HASPINODEN specifies that searching for files in HASPROCFS is to be done
+ * by inode number.
+ */
+
+/* #define HASPROCFS "proc?" */
+#define HASFSTYPE 2 /* see also dlsof.h */
+/* #define HASPINODEN 1 */
+
+
+/*
+ * HASRNODE is defined for those dialects that have rnodes.
+ */
+
+/* #define HASRNODE 1 */
+
+
+/*
+ * Define HASSECURITY to restrict the listing of all open files to the
+ * root user. When HASSECURITY is defined, the non-root user may list
+ * only files whose processes have the same user ID as the real user ID
+ * (the one that its user logged on with) of the lsof process.
+ */
+
+/* #define HASSECURITY 1 */
+
+
+/*
+ * If HASSECURITY is defined, define HASNOSOCKSECURITY to allow users
+ * restricted by HASSECURITY to list any open socket files, provide their
+ * listing is selected by the "-i" option.
+ */
+
+/* #define HASNOSOCKSECURITY 1 */
+
+
+/*
+ * HASSETLOCALE is defined for those dialects that have <locale.h> and
+ * setlocale().
+ *
+ * If the dialect also has wide character support for language locales,
+ * HASWIDECHAR activates lsof's wide character support and WIDECHARINCL
+ * defines the header file (if any) that must be #include'd to use the
+ * mblen() and mbtowc() functions.
+ */
+
+#define HASSETLOCALE 1
+#define HASWIDECHAR 1
+#define WIDECHARINCL <wctype.h>
+
+
+/*
+ * HASSNODE is defined for those dialects that have snodes.
+ */
+
+/* #define HASSNODE 1 */
+
+
+/*
+ * HASTASKS is defined for those dialects that have task reporting support.
+ */
+
+/* #define HASTASKS 1 */
+
+
+/*
+ * HASSOOPT, HASSOSTATE and HASTCPOPT define the availability of information
+ * on socket options (SO_* symbols), socket states (SS_* symbols) and TCP
+ * options.
+ */
+
+#define HASSOOPT 1 /* has socket option information */
+#define HASSOSTATE 1 /* has socket state information */
+/* #define HASTCPOPT 1 has TCP options or flags */
+
+
+/*
+ * Define HASSPECDEVD to be the name of a function that handles the results
+ * of a successful stat(2) of a file name argument.
+ *
+ * For example, HASSPECDEVD() for Darwin makes sure that st_dev is set to
+ * what stat("/dev") returns -- i.e., what's in DevDev.
+ *
+ * The function takes two arguments:
+ *
+ * 1: pointer to the full path name of file
+ * 2: pointer to the stat(2) result
+ *
+ * The function returns void.
+ */
+
+/* #define HASSPECDEVD process_dev_stat */
+
+
+/*
+ * HASSTREAMS is defined for those dialects that support streams.
+ */
+
+/* #define HASSTREAMS 1 */
+
+
+/*
+ * HASTCPTPIQ is defined for dialects where it is possible to report the
+ * TCP/TPI Recv-Q and Send-Q values produced by netstat.
+ */
+
+#define HASTCPTPIQ 1
+
+
+/*
+ * HASTCPTPIW is defined for dialects where it is possible to report the
+ * TCP/TPI send and receive window sizes produced by netstat.
+ */
+
+#define HASTCPTPIW 1
+
+
+/*
+ * HASTCPUDPSTATE is defined for dialects that have TCP and UDP state
+ * support -- i.e., for the "-stcp|udp:state" option and its associated
+ * speed improvements.
+ */
+
+#define HASTCPUDPSTATE 1
+
+
+/*
+ * HASTMPNODE is defined for those dialects that have tmpnodes.
+ */
+
+/* #define HASTMPNODE 1 */
+
+
+/*
+ * HASVNODE is defined for those dialects that use the Sun virtual file system
+ * node, the vnode. BSD derivatives usually do; System V derivatives prior to
+ * R4 usually don't.
+ */
+
+/* #define HASVNODE 1 */
+
+
+/*
+ * HASXOPT is defined for those dialects that have an X option. It
+ * defines the text for the usage display. HASXOPT_VALUE defines the
+ * option's default binary value -- 0 or 1.
+ */
+
+/* #define HASXOPT "help text for X option" */
+/* #define HASXOPT_VALUE 1 */
+
+
+/*
+ * INODETYPE and INODEPSPEC define the internal node number type and its
+ * printf specification modifier. These need not be defined and lsof.h
+ * can be allowed to define defaults.
+ *
+ * These are defined here, because they must be used in dlsof.h.
+ */
+
+#define INODETYPE unsigned long long
+ /* inode number internal storage type */
+#define INODEPSPEC "ll" /* INODETYPE printf specification
+ * modifier */
+
+
+/*
+ * UID_ARG defines the size of a User ID number when it is passed
+ * as a function argument.
+ */
+
+#define UID_ARG uid_t
+
+
+/*
+ * Each USE_LIB_<function_name> is defined for dialects that use the
+ * <function_name> in the lsof library.
+ *
+ * Note: other definitions and operations may be required to condition the
+ * library function source code. They may be found in the dialect dlsof.h
+ * header files.
+ */
+
+#define USE_LIB_CKKV 1 /* ckkv.c */
+/* #define USE_LIB_COMPLETEVFS 1 cvfs.c */
+/* #define USE_LIB_FIND_CH_INO 1 fino.c */
+#define USE_LIB_IS_FILE_NAMED 1 /* isfn.c */
+#define USE_LIB_LKUPDEV 1 /* lkud.c */
+#define USE_LIB_PRINTDEVNAME 1 /* pdvn.c */
+/* #define USE_LIB_PROCESS_FILE 1 prfp.c */
+/* #define USE_LIB_PRINT_TCPTPI 1 ptti.c */
+/* #define USE_LIB_PRINT_TCPTPI 1 ptti.c */
+#define USE_LIB_READDEV 1 /* rdev.c */
+#define USE_LIB_READMNT 1 /* rmnt.c */
+/* #define USE_LIB_REGEX 1 regex.c */
+/* #define USE_LIB_RNAM 1 rnam.c */
+/* #define USE_LIB_RNCH 1 rnch.c */
+/* #define USE_LIB_RNMH 1 rnmh.c */
+/* #define USE_LIB_SNPF 1 snpf.c */
+#define snpf snprintf /* use the system's snprintf() */
+
+
+/*
+ * WARNDEVACCESS is defined for those dialects that should issue a warning
+ * when lsof can't access /dev (or /device) or one of its sub-directories.
+ * The warning can be inhibited by the lsof caller with the -w option.
+ */
+
+/* #define WARNDEVACCESS 1 */
+
+
+/*
+ * WARNINGSTATE is defined for those dialects that want to suppress all lsof
+ * warning messages.
+ */
+
+/* #define WARNINGSTATE 1 warnings are enabled by default */
+
+
+/*
+ * WILLDROPGID is defined for those dialects whose lsof executable runs
+ * setgid(not_real_GID) and whose setgid power can be relinquished after
+ * the dialect's initialize() function has been executed.
+ */
+
+/* #define WILLDROPGID 1 */
+
+
+/*
+ * zeromem is a macro that uses bzero or memset.
+ */
+
+#define zeromem(a, l) memset((void *)a, 0, l)
+
+#endif /* !defined(LSOF_MACHINE_H) */
diff --git a/dialects/linux/dnode.c b/dialects/linux/dnode.c
index 8a9bc73..5cf9223 100644
--- a/dialects/linux/dnode.c
+++ b/dialects/linux/dnode.c
@@ -32,7 +32,7 @@
#ifndef lint
static char copyright[] =
"@(#) Copyright 1997 Purdue Research Foundation.\nAll rights reserved.\n";
-static char *rcsid = "$Id: dnode.c,v 1.23 2013/01/02 17:02:36 abe Exp $";
+static char *rcsid = "$Id: dnode.c,v 1.24 2014/10/13 22:25:58 abe Exp $";
#endif
@@ -47,7 +47,9 @@ static char *rcsid = "$Id: dnode.c,v 1.23 2013/01/02 17:02:36 abe Exp $";
* .../src/fs/locks.c and not
* in a header file */
#define PIDBUCKS 64 /* PID hash buckets */
+#define PINFOBUCKS 512 /* pipe info hash buckets */
#define HASHPID(pid) (((int)((pid * 31415) >> 3)) & (PIDBUCKS - 1))
+#define HASHPINFO(ino) (((int)((ino * 31415) >> 3)) & (PINFOBUCKS - 1))
/*
@@ -76,6 +78,19 @@ struct llock **LckH = (struct llock **)NULL; /* PID-hashed locks */
_PROTOTYPE(static void check_lock,(void));
+#if defined(HASEPTOPTS)
+_PROTOTYPE(static void enter_pinfo,(void));
+#endif /* defined(HASEPTOPTS) */
+
+
+/*
+ * Locals storage
+ */
+
+#if defined(HASEPTOPTS)
+static pinfo_t **Pinfo = (pinfo_t **)NULL;
+#endif /* defined(HASEPTOPTS) */
+
/*
* check_lock() - check lock for file *Lf, process *Lp
@@ -100,6 +115,128 @@ check_lock()
}
+#if defined(HASEPTOPTS)
+/*
+ * clear_pinfo() -- clear allocated pipe info
+ */
+
+void
+clear_pinfo()
+{
+ int h; /* hash index */
+ pinfo_t *pi, *pp; /* temporary pointers */
+
+ if (!Pinfo)
+ return;
+ for (h = 0; h < PINFOBUCKS; h++) {
+ if ((pi = Pinfo[h])) {
+ do {
+ pp = pi->next;
+ (void) free((FREE_P *)pi);
+ pi = pp;
+ } while (pi);
+ Pinfo[h] = (pinfo_t *)NULL;
+ }
+ }
+}
+
+
+/*
+ * enter_pinfo() -- enter pipe info
+ *
+ * entry Lf = local file structure pointer
+ * Lp = local process structure pointer
+ */
+
+static void
+enter_pinfo()
+{
+ int h; /* hash result */
+ struct lfile *lf; /* local file structure pointer */
+ struct lproc *lp; /* local proc structure pointer */
+ pinfo_t *np, *pi, *pe; /* pipe info pointers */
+
+ if (!Pinfo) {
+ /*
+ * Allocate pipe info hash buckets.
+ */
+ if (!(Pinfo = (pinfo_t **)calloc(PINFOBUCKS, sizeof(pinfo_t *)))) {
+ (void) fprintf(stderr,
+ "%s: no space for %d pipe info buckets\n", Pn, PINFOBUCKS);
+ Exit(1);
+ }
+ }
+ /*
+ * Make sure this is a unique entry.
+ */
+ for (h = HASHPINFO(Lf->inode), pi = Pinfo[h], pe = (pinfo_t *)NULL;
+ pi;
+ pe = pi, pi = pi->next
+ ) {
+ lf = pi->lf;
+ lp = &Lproc[pi->lpx];
+ if (pi->ino == Lf->inode) {
+ if ((lp->pid == Lp->pid) && !strcmp(lf->fd, Lf->fd))
+ return;
+ }
+ }
+ /*
+ * Allocate, fill and link a new pipe info structure to the end of
+ * the pipe inode hash chain.
+ */
+ if (!(np = (pinfo_t *)malloc(sizeof(pinfo_t)))) {
+ (void) fprintf(stderr,
+ "%s: no space for pipeinfo, PID %d, FD %s\n",
+ Pn, Lp->pid, Lf->fd);
+ Exit(1);
+ }
+ np->ino = Lf->inode;
+ np->lf = Lf;
+ np->lpx = Lp - Lproc;
+ np->next = (pinfo_t *)NULL;
+ if (pe)
+ pe->next = np;
+ else
+ Pinfo[h] = np;
+}
+
+
+/*
+ * find_pendinfo() -- find pipe end info
+ */
+
+pinfo_t *
+find_pendinfo(lf, pp)
+ struct lfile *lf; /* pipe's lfile */
+ pinfo_t *pp; /* previous pinfo (NULL == none) */
+{
+ struct lfile *ef; /* pipe end local file structure */
+ int h; /* hash result */
+ pinfo_t *pi; /* pipe info pointer */
+
+ if (Pinfo) {
+ if (pp)
+ pi = pp;
+ else {
+ h = HASHPINFO(lf->inode);
+ pi = Pinfo[h];
+ }
+ while (pi) {
+ if (pi->ino == lf->inode) {
+ ef = pi->lf;
+ if (strcmp(lf->fd, ef->fd))
+ return(pi);
+ }
+ pi = pi->next;
+ }
+ }
+ return((pinfo_t *)NULL);
+
+}
+#endif /* defined(HASEPTOPTS) */
+
+
+
/*
* get_fields() - separate a line into fields
*/
@@ -441,6 +578,14 @@ process_proc_node(p, pbr, s, ss, l, ls)
if (ss & SB_INO) {
Lf->inode = (INODETYPE)s->st_ino;
Lf->inp_ty = 1;
+
+#if defined(HASEPTOPTS)
+ if (Lf->ntype == N_FIFO) {
+ (void) enter_pinfo();
+ Lf->sf |= SELPINFO;
+ }
+#endif /* defined(HASEPTOPTS) */
+
}
/*
* Check for a lock.
diff --git a/dialects/linux/dproc.c b/dialects/linux/dproc.c
index c3045a2..b01b287 100644
--- a/dialects/linux/dproc.c
+++ b/dialects/linux/dproc.c
@@ -32,7 +32,7 @@
#ifndef lint
static char copyright[] =
"@(#) Copyright 1997 Purdue Research Foundation.\nAll rights reserved.\n";
-static char *rcsid = "$Id: dproc.c,v 1.27 2013/01/02 17:02:36 abe Exp $";
+static char *rcsid = "$Id: dproc.c,v 1.28 2014/10/13 22:25:58 abe Exp $";
#endif
#include "lsof.h"
@@ -80,13 +80,14 @@ static short Ckscko; /* socket file only checking status:
* Local function prototypes
*/
+_PROTOTYPE(static MALLOC_S alloc_cbf,(MALLOC_S len, char **cbf, MALLOC_S cbfa));
_PROTOTYPE(static int get_fdinfo,(char *p, struct l_fdinfo *fi));
_PROTOTYPE(static int getlinksrc,(char *ln, char *src, int srcl, char **rest));
_PROTOTYPE(static int isefsys,(char *path, char *type, int l,
efsys_list_t **rep, struct lfile **lfr));
_PROTOTYPE(static int nm2id,(char *nm, int *id, int *idl));
-_PROTOTYPE(static int read_id_stat,(int ty, char *p, int id, char **cmd,
- int *ppid, int *pgid));
+_PROTOTYPE(static int read_id_stat,(char *p, int id, char **cmd, int *ppid,
+ int *pgid));
_PROTOTYPE(static void process_proc_map,(char *p, struct stat *s, int ss));
_PROTOTYPE(static int process_id,(char *idp, int idpl, char *cmd, UID_ARG uid,
int pid, int ppid, int pgid, int tid));
@@ -151,6 +152,29 @@ enter_cntx_arg(cntx)
/*
+ * alloc_cbf() -- allocate a command buffer
+ */
+
+static MALLOC_S
+alloc_cbf(len, cbf, cbfa)
+ MALLOC_S len; /* required length */
+ char **cbf; /* current buffer */
+ MALLOC_S cbfa; /* current buffer allocation */
+{
+ if (*cbf)
+ *cbf = (char *)realloc((MALLOC_P *)*cbf, len);
+ else
+ *cbf = (char *)malloc(len);
+ if (!*cbf) {
+ (void) fprintf(stderr,
+ "%s: can't allocate command %d bytes\n", Pn, (int)len);
+ Exit(1);
+ }
+ return(len);
+}
+
+
+/*
* gather_proc_info() -- gather process information
*/
@@ -330,7 +354,7 @@ gather_proc_info()
/*
* Check the task state.
*/
- rv = read_id_stat(1, tidpath, tid, &tcmd, &tppid,
+ rv = read_id_stat(tidpath, tid, &tcmd, &tppid,
&tpgid);
if ((rv < 0) || (rv == 1))
continue;
@@ -355,7 +379,7 @@ gather_proc_info()
* with its tasks.
*/
(void) make_proc_path(pidpath, n, &path, &pathl, "stat");
- if (((rv = read_id_stat(0, path, pid, &cmd, &ppid, &pgid)) >= 0)
+ if (((rv = read_id_stat(path, pid, &cmd, &ppid, &pgid)) >= 0)
&& (rv != 1))
{
tid = (Fand && ht && pidts && (Selflags & SELTASK)) ? pid : 0;
@@ -813,8 +837,17 @@ process_id(idp, idpl, cmd, uid, pid, ppid, pgid, tid)
*/
if (is_proc_excl(pid, pgid, uid, &pss, &sf, tid)
|| is_cmd_excl(cmd, &pss, &sf))
+ {
+
+#if defined(HASEPTOPTS)
+ if (!FpipeE)
+ return(1);
+#else /* !defined(HASEPTOPTS) */
return(1);
- if (Cckreg) {
+#endif /* defined(HASEPTOPTS) */
+
+ }
+ if (Cckreg && !FpipeE) {
/*
* If conditional checking of regular files is enabled, enable
@@ -829,10 +862,10 @@ process_id(idp, idpl, cmd, uid, pid, ppid, pgid, tid)
/*
* Process the ID's current working directory info.
*/
+ efs = 0;
if (!Ckscko) {
(void) make_proc_path(idp, idpl, &path, &pathl, "cwd");
alloc_lfile(CWD, -1);
- efs = 0;
if (getlinksrc(path, pbuf, sizeof(pbuf), (char **)NULL) < 1) {
if (!Fwarn) {
(void) memset((void *)&sb, 0, sizeof(sb));
@@ -878,13 +911,13 @@ process_id(idp, idpl, cmd, uid, pid, ppid, pgid, tid)
/*
* Process the ID's root directory info.
*/
+ lnk = ss = 0;
if (!Ckscko) {
(void) make_proc_path(idp, idpl, &path, &pathl, "root");
alloc_lfile(RTD, -1);
if (getlinksrc(path, pbuf, sizeof(pbuf), (char **)NULL) < 1) {
if (!Fwarn) {
(void) memset((void *)&sb, 0, sizeof(sb));
- lnk = ss = 0;
(void) snpf(nmabuf, sizeof(nmabuf), "(readlink: %s)",
strerror(errno));
nmabuf[sizeof(nmabuf) - 1] = '\0';
@@ -925,13 +958,12 @@ process_id(idp, idpl, cmd, uid, pid, ppid, pgid, tid)
/*
* Process the ID's execution info.
*/
+ lnk = ss = txts = 0;
if (!Ckscko) {
- txts = 0;
(void) make_proc_path(idp, idpl, &path, &pathl, "exe");
alloc_lfile("txt", -1);
if (getlinksrc(path, pbuf, sizeof(pbuf), (char **)NULL) < 1) {
(void) memset((void *)&sb, 0, sizeof(sb));
- lnk = ss = 0;
if (!Fwarn) {
if ((errno != ENOENT) || uid) {
(void) snpf(nmabuf, sizeof(nmabuf), "(readlink: %s)",
@@ -1393,8 +1425,7 @@ process_proc_map(p, s, ss)
*/
static int
-read_id_stat(ty, p, id, cmd, ppid, pgid)
- int ty; /* type: 0 == PID, 1 == LWP */
+read_id_stat(p, id, cmd, ppid, pgid)
char *p; /* path to status file */
int id; /* ID: PID or LWP */
char **cmd; /* malloc'd command name */
@@ -1403,11 +1434,11 @@ read_id_stat(ty, p, id, cmd, ppid, pgid)
* type */
{
char buf[MAXPATHLEN], *cp, *cp1, **fp;
+ int ch, cx, es, nf;
static char *cbf = (char *)NULL;
static MALLOC_S cbfa = 0;
FILE *fs;
- MALLOC_S len;
- int nf;
+ MALLOC_S nl;
static char *vbuf = (char *)NULL;
static size_t vsz = (size_t)0;
/*
@@ -1416,69 +1447,89 @@ read_id_stat(ty, p, id, cmd, ppid, pgid)
*/
if (!(fs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
return(-1);
- cp = fgets(buf, sizeof(buf), fs);
- (void) fclose(fs);
- if (!cp)
+ if (!(cp = fgets(buf, sizeof(buf), fs))) {
+
+read_id_stat_exit:
+
+ (void) fclose(fs);
return(-1);
+ }
/*
- * Separate the line into fields on white space separators. Expect five fields
- * for a PID type and three for an LWP type.
+ * Skip to the first field, and make sure it is a matching ID.
*/
- if ((nf = get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0))
- < (ty ? 5 : 3))
- {
- return(-1);
- }
+ cp1 = cp;
+ while (*cp && (*cp != ' ') && (*cp != '\t'))
+ cp++;
+ if (*cp)
+ *cp = '\0';
+ if (atoi(cp1) != id)
+ goto read_id_stat_exit;
/*
- * Convert the first field to an integer; its conversion must match the
- * ID argument.
+ * The second field should contain the command, enclosed in parentheses.
+ * If it also has embedded '\n' characters, replace them with '?' characters,
+ * accumulating command characters until a closing parentheses appears.
+ *
*/
- if (!fp[0] || (atoi(fp[0]) != id))
- return(-1);
+ for (++cp; *cp && (*cp == ' '); cp++)
+ ;
+ if (!cp || (*cp != '('))
+ goto read_id_stat_exit;
+ cp++;
/*
- * Get the command name from the second field. Strip a starting '(' and
- * an ending ')'. Allocate space to hold the result and return the space
- * pointer.
+ * Enter the command characters safely. Supply them from the initial read
+ * of the stat file line, a '\n' if the initial read didn't yield a ')'
+ * command closure, or by reading the rest of the command a character at
+ * a time from the stat file.
*/
- if (!(cp = fp[1]))
- return(-1);
- if (cp && *cp == '(')
- cp++;
- if ((cp1 = strrchr(cp, ')')))
- *cp1 = '\0';
- if ((len = strlen(cp) + 1) > cbfa) {
- cbfa = len;
- if (cbf)
- cbf = (char *)realloc((MALLOC_P *)cbf, cbfa);
- else
- cbf = (char *)malloc(cbfa);
- if (!cbf) {
- (void) fprintf(stderr,
- "%s: can't allocate %d bytes for command \"%s\"\n",
- Pn, (int)cbfa, cp);
- Exit(1);
- }
+ for (cx = es = 0;;) {
+ if (!es)
+ ch = *cp++;
+ else {
+ if ((ch = fgetc(fs)) == EOF)
+ goto read_id_stat_exit;
+ }
+ if (ch == ')') /* ')' closes the command */
+ break;
+ if ((cx + 2) > cbfa)
+ cbfa = alloc_cbf((cx + 2), &cbf, cbfa);
+ cbf[cx] = ch;
+ cx++;
+ cbf[cx] = '\0';
+ if (!es && !*cp)
+ es = 1; /* Switch to fgetc() when a '\0' appears. */
}
- (void) snpf(cbf, len, "%s", cp);
*cmd = cbf;
/*
+ * Read the remainder of the stat line if it was necessary to read command
+ * characters individually from the stat file.
+ *
+ * Separate the reminder into fields.
+ */
+ if (es)
+ cp = fgets(buf, sizeof(buf), fs);
+ (void) fclose(fs);
+ if (!cp || !*cp)
+ return(-1);
+ if ((nf = get_fields(cp, (char *)NULL, &fp, (int *)NULL, 0)) < 3)
+ return(-1);
+/*
* Convert and return parent process (fourth field) and process group (fifth
* field) IDs.
*/
- if (fp[3] && *fp[3])
- *ppid = atoi(fp[3]);
+ if (fp[1] && *fp[1])
+ *ppid = atoi(fp[1]);
else
return(-1);
- if (fp[4] && *fp[4])
- *pgid = atoi(fp[4]);
+ if (fp[2] && *fp[2])
+ *pgid = atoi(fp[2]);
else
return(-1);
/*
* Check the state in the third field. If it is 'Z', return that indication.
*/
- if (fp[2] && !strcmp(fp[2], "Z"))
+ if (fp[0] && !strcmp(fp[0], "Z"))
return(1);
- else if (fp[2] && !strcmp(fp[2], "T"))
+ else if (fp[0] && !strcmp(fp[0], "T"))
return(2);
return(0);
}
diff --git a/dialects/linux/dsock.c b/dialects/linux/dsock.c
index 9109b2f..5a7cd50 100644
--- a/dialects/linux/dsock.c
+++ b/dialects/linux/dsock.c
@@ -32,7 +32,7 @@
#ifndef lint
static char copyright[] =
"@(#) Copyright 1997 Purdue Research Foundation.\nAll rights reserved.\n";
-static char *rcsid = "$Id: dsock.c,v 1.39 2013/01/02 17:02:36 abe Exp $";
+static char *rcsid = "$Id: dsock.c,v 1.40 2014/10/13 22:25:58 abe Exp $";
#endif
@@ -154,6 +154,7 @@ struct uxsin { /* UNIX socket information */
dev_t sb_dev; /* stat(2) buffer device */
INODETYPE sb_ino; /* stat(2) buffer node number */
dev_t sb_rdev; /* stat(2) raw device number */
+ uint32_t ty; /* socket type */
struct uxsin *next;
};
@@ -266,6 +267,7 @@ _PROTOTYPE(static void get_unix,(char *p));
_PROTOTYPE(static int isainb,(char *a, char *b));
_PROTOTYPE(static void print_ax25info,(struct ax25sin *ap));
_PROTOTYPE(static void print_ipxinfo,(struct ipxsin *ip));
+_PROTOTYPE(static char *sockty2str,(uint32_t ty, int *rf));
#if defined(HASIPv6)
_PROTOTYPE(static struct rawsin *check_raw6,(INODETYPE i));
@@ -2281,6 +2283,7 @@ get_unix(p)
MALLOC_S len;
struct uxsin *np, *up;
FILE *us;
+ uint32_t ty;
static char *vbuf = (char *)NULL;
static size_t vsz = (size_t)0;
/*
@@ -2378,6 +2381,16 @@ get_unix(p)
} else
path = (char *)NULL;
/*
+ * Assemble socket type.
+ */
+ ep = (char *)NULL;
+ if (!fp[4] || !*fp[4]
+ || (ty = (uint32_t)strtoul(fp[4], &ep, 16)) == (uint32_t)UINT32_MAX
+ || !ep || *ep)
+ {
+ ty = (uint32_t)UINT_MAX;
+ }
+ /*
* Allocate and fill a Unix socket info structure; link it to its
* hash bucket.
*/
@@ -2390,6 +2403,7 @@ get_unix(p)
up->inode = inode;
up->pcb = pcb;
up->sb_def = 0;
+ up->ty = ty;
if ((up->path = path) && (*path == '/')) {
/*
@@ -2693,7 +2707,7 @@ process_proc_sock(p, pbr, s, ss, l, lss)
struct in_addr fs, ls;
struct icmpin *icmpp;
struct ipxsin *ip;
- int i, len, nl;
+ int i, len, nl, rf;
struct nlksin *np;
struct packin *pp;
char *pr;
@@ -3033,50 +3047,8 @@ process_proc_sock(p, pbr, s, ss, l, lss)
* number in the DEVICE column.
*/
(void) snpf(Lf->type, sizeof(Lf->type), "pack");
- switch(pp->ty) {
-
-#if defined(SOCK_STREAM)
- case SOCK_STREAM:
- cp = "STREAM";
- break;
-#endif /* defined(SOCK_STREAM) */
-
-#if defined(SOCK_DGRAM)
- case SOCK_DGRAM:
- cp = "DGRAM";
- break;
-#endif /* defined(SOCK_DGRAM) */
-
-#if defined(SOCK_RAW)
- case SOCK_RAW:
- cp = "RAW";
- break;
-#endif /* defined(SOCK_RAW) */
-
-#if defined(SOCK_RDM)
- case SOCK_RDM:
- cp = "RDM";
- break;
-#endif /* defined(SOCK_RDM) */
-
-#if defined(SOCK_SEQPACKET)
- case SOCK_SEQPACKET:
- cp = "SEQPACKET";
- break;
-#endif /* defined(SOCK_SEQPACKET) */
-
-#if defined(SOCK_PACKET)
- case SOCK_PACKET:
- cp = "PACKET";
- break;
-#endif /* defined(SOCK_PACKET) */
-
- default:
- (void) snpf(Namech, Namechl, "unknown type: %d", pp->ty);
- cp = (char *)NULL;
- }
- if (cp)
- (void) snpf(Namech, Namechl, "type=SOCK_%s", cp);
+ cp = sockty2str(pp->ty, &rf);
+ (void) snpf(Namech, Namechl, "type=%s%s", rf ? "" : "SOCK_", cp);
switch (pp->pr) {
#if defined(ETH_P_LOOP)
@@ -3420,8 +3392,13 @@ process_proc_sock(p, pbr, s, ss, l, lss)
Lf->inode = (INODETYPE)s->st_ino;
Lf->inp_ty = 1;
}
- path = up->path ? up->path : p;
- (void) enter_nm(path);
+ cp = sockty2str(up->ty, &rf);
+ (void) snpf(Namech, Namechl - 1, "%s%stype=%s",
+ up->path ? up->path : "",
+ up->path ? " " : "",
+ cp);
+ Namech[Namechl - 1] = '\0';
+ (void) enter_nm(Namech);
if (Sfile) {
/*
@@ -3944,3 +3921,63 @@ set_net_paths(p, pl)
pathl = 0;
(void) make_proc_path(p, pl, &UNIXpath, &pathl, "unix");
}
+
+
+/*
+ * Sockty2str() -- convert socket type number to a string
+ */
+
+static char *
+sockty2str(ty, rf)
+ uint32_t ty; /* socket type number */
+ int *rf; /* result flag: 0 == known
+ * 1 = unknown */
+{
+ int f = 0; /* result flag */
+ char *sr; /*string result */
+
+ switch (ty) {
+
+#if defined(SOCK_STREAM)
+ case SOCK_STREAM:
+ sr = "STREAM";
+ break;
+#endif /* defined(SOCK_STREAM) */
+
+#if defined(SOCK_DGRAM)
+ case SOCK_DGRAM:
+ sr = "DGRAM";
+ break;
+#endif /* defined(SOCK_DGRAM) */
+
+#if defined(SOCK_RAW)
+ case SOCK_RAW:
+ sr = "RAW";
+ break;
+#endif /* defined(SOCK_RAW) */
+
+#if defined(SOCK_RDM)
+ case SOCK_RDM:
+ sr = "RDM";
+ break;
+#endif /* defined(SOCK_RDM) */
+
+#if defined(SOCK_SEQPACKET)
+ case SOCK_SEQPACKET:
+ sr = "SEQPACKET";
+ break;
+#endif /* defined(SOCK_SEQPACKET) */
+
+#if defined(SOCK_PACKET)
+ case SOCK_PACKET:
+ sr = "PACKET";
+ break;
+#endif /* defined(SOCK_PACKET) */
+
+ default:
+ f = 1;
+ sr = "unknown";
+ }
+ *rf = f;
+ return(sr);
+}
diff --git a/dialects/linux/machine.h b/dialects/linux/machine.h
index 2b33128..2f17ae0 100644
--- a/dialects/linux/machine.h
+++ b/dialects/linux/machine.h
@@ -31,7 +31,7 @@
/*
- * $Id: machine.h,v 1.36 2012/04/10 16:39:50 abe Exp $
+ * $Id: machine.h,v 1.37 2014/10/13 22:25:58 abe Exp $
*/
@@ -318,6 +318,13 @@
/*
+ * HASEPTOPTS is defined for dialects that support the +|-E options.
+ */
+
+#define HASEPTOPTS 1
+
+
+/*
* HASPMAPENABLED is defined when the reporting of portmapper registration
* info is enabled by default.
*/
diff --git a/dialects/n+obsd/Makefile b/dialects/n+obsd/Makefile
new file mode 100644
index 0000000..29f88a6
--- /dev/null
+++ b/dialects/n+obsd/Makefile
@@ -0,0 +1,159 @@
+
+# N+OBSD Makefile
+#
+# $Id: Makefile,v 1.12 2008/04/15 13:30:14 abe Exp $
+
+PROG= lsof
+
+BIN= ${DESTDIR}
+
+DOC= ${DESTDIR}
+
+I=/usr/include
+S=/usr/include/sys
+L=/usr/include/local
+P=
+
+CDEF=
+CDEFS= ${CDEF} ${CFGF}
+INCL= ${DINC}
+CFLAGS= ${CDEFS} ${INCL} ${DEBUG}
+
+GRP=
+
+HDR= lsof.h lsof_fields.h dlsof.h machine.h proto.h dproto.h
+
+SRC= dmnt.c dnode.c dnode1.c dproc.c dsock.c dstore.c \
+ arg.c main.c misc.c node.c print.c proc.c store.c usage.c \
+ util.c
+
+OBJ= dmnt.o dnode.o dnode1.o dproc.o dsock.o dstore.o \
+ arg.o main.o misc.o node.o print.o proc.o store.o usage.o \
+ util.o
+
+MAN= lsof.8
+MANLCL= lsof.0
+
+OTHER=
+
+SHELL= /bin/sh
+
+SOURCE= Makefile ${OTHER} ${MAN} ${HDR} ${SRC}
+
+all: ${PROG}
+
+${MANLCL}: ${MAN}
+ rm -f ${MANLCL}
+ nroff -mandoc -Tlp ${MAN} > ${MANLCL}
+
+${PROG}: ${LIB} ${P} ${OBJ}
+ ${CC} -o $@ ${CFLAGS} ${OBJ} ${CFGL}
+
+clean: FRC
+ rm -f Makefile.bak ${PROG} a.out core *.core errs lint.out tags *.o
+ rm -f machine.h.old new_machine.h version.h
+ (cd lib; ${MAKE} -f Makefile.skel clean)
+
+install: all ${MANLCL} FRC
+ @echo ''
+ @echo 'Please write your own install rule. Lsof should be installed'
+ @echo 'setgid to the group that can can read /dev/kmem. Normally'
+ @echo 'that is the kmem group. Your install rule actions might look'
+ @echo 'something like this:'
+ @echo ''
+ @echo ' install -cs -m 2755 -g $${GRP} $${PROG} $${BIN}/$${PROG}'
+ @echo ' install -c -m 444 $${MANLCL} $${DOC}/$${MANLCL}'
+ @echo ''
+ @echo 'You will have to complete the skeletons for the BIN, DOC, and'
+ @echo 'GRP strings given at the beginning of this Makefile, e.g.,'
+ @echo ''
+ @echo ' BIN= $${DESTDIR}/usr/local/etc'
+ @echo ' DOC= $${DESTDIR}/usr/local/man/man8'
+ @echo ' GRP= kmem'
+ @echo ''
+
+${LIB}: FRC
+ (cd lib; ${MAKE} DEBUG="${DEBUG}" CFGF="${CFGF}")
+
+version.h: FRC
+ @echo Constructing version.h
+ @rm -f version.h
+ @echo '#define LSOF_BLDCMT "${LSOF_BLDCMT}"' > version.h;
+ @echo '#define LSOF_CC "${CC}"' >> version.h
+ @echo '#define LSOF_CCV "${CCV}"' >> version.h
+ @echo '#define LSOF_CCDATE "'`date`'"' >> version.h
+ @echo '#define LSOF_CCFLAGS "'`echo ${CFLAGS} | sed 's/\\\\(/\\(/g' | sed 's/\\\\)/\\)/g' | sed 's/"/\\\\"/g'`'"' >> version.h
+ @if [ "X${LSOF_HOST}" = "X" ]; then \
+ echo '#define LSOF_HOST "'`uname -n`'"' >> version.h; \
+ else \
+ if [ "${LSOF_HOST}" = "none" ]; then \
+ echo '#define LSOF_HOST ""' >> version.h; \
+ else \
+ echo '#define LSOF_HOST "${LSOF_HOST}"' >> version.h; \
+ fi \
+ fi
+ @echo '#define LSOF_LDFLAGS "${CFGL}"' >> version.h
+ @if [ "X${LSOF_LOGNAME}" = "X" ]; then \
+ echo '#define LSOF_LOGNAME "${LOGNAME}"' >> version.h; \
+ else \
+ if [ "${LSOF_LOGNAME}" = "none" ]; then \
+ echo '#define LSOF_LOGNAME ""' >> version.h; \
+ else \
+ echo '#define LSOF_LOGNAME "${LSOF_LOGNAME}"' >> version.h; \
+ fi; \
+ fi
+ @if [ "X${LSOF_SYSINFO}" = "X" ]; then \
+ echo '#define LSOF_SYSINFO "'`uname -a`'"' >> version.h; \
+ else \
+ if [ "${LSOF_SYSINFO}" = "none" ]; then \
+ echo '#define LSOF_SYSINFO ""' >> version.h; \
+ else \
+ echo '#define LSOF_SYSINFO "${LSOF_SYSINFO}"' >> version.h; \
+ fi \
+ fi
+ @if [ "X${LSOF_USER}" = "X" ]; then \
+ echo '#define LSOF_USER "${USER}"' >> version.h; \
+ else \
+ if [ "${LSOF_USER}" = "none" ]; then \
+ echo '#define LSOF_USER ""' >> version.h; \
+ else \
+ echo '#define LSOF_USER "${LSOF_USER}"' >> version.h; \
+ fi \
+ fi
+ @sed '/VN/s/.ds VN \(.*\)/#define LSOF_VERSION "\1"/' < version >> version.h
+
+FRC:
+
+# DO NOT DELETE THIS LINE - make depend DEPENDS ON IT
+
+dmnt.o: ${HDR} dmnt.c
+
+dnode.o: ${HDR} dnode.c
+
+dnode1.o: ${HDR} dnode1.c
+
+dproc.o: ${HDR} dproc.c
+
+dsock.o: ${HDR} dsock.c
+
+dstore.o: ${HDR} dstore.c
+
+arg.o: ${HDR} arg.c
+
+main.o: ${HDR} main.c
+
+misc.o: ${HDR} misc.c
+
+node.o: ${HDR} node.c
+
+print.o: ${HDR} print.c
+
+proc.o: ${HDR} proc.c
+
+store.o: ${HDR} store.c
+
+usage.o: ${HDR} version.h usage.c
+
+util.o: ${HDR} util.c
+
+# *** Do not add anything here - It will go away. ***
diff --git a/dialects/n+obsd/Mksrc b/dialects/n+obsd/Mksrc
new file mode 100755
index 0000000..a6a19b5
--- /dev/null
+++ b/dialects/n+obsd/Mksrc
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Mksrc - make NetBSD and OpenBSD source files
+#
+# WARNING: This script assumes it is running from the main directory
+# of the lsof, version 4 distribution.
+#
+# One environment variable applies:
+#
+# LSOF_MKC is the method for creating the source files.
+# It defaults to "ln -s". A common alternative is "cp".
+#
+# $Id: Mksrc,v 1.5 99/04/15 06:40:37 abe Exp $
+
+
+D=dialects/n+obsd
+L="dlsof.h dmnt.c dnode.c dnode1.c dproc.c dproto.h dsock.c dstore.c machine.h"
+
+for i in $L
+do
+ rm -f $i
+ $LSOF_MKC $D/$i $i
+ echo "$LSOF_MKC $D/$i $i"
+done
diff --git a/dialects/n+obsd/dlsof.h b/dialects/n+obsd/dlsof.h
new file mode 100644
index 0000000..2aa2169
--- /dev/null
+++ b/dialects/n+obsd/dlsof.h
@@ -0,0 +1,584 @@
+/*
+ * dlsof.h - NetBSD and OpenBSD header file for lsof
+ */
+
+
+/*
+ * Copyright 1994 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.
+ */
+
+
+/*
+ * $Id: dlsof.h,v 1.38 2006/03/28 21:54:08 abe Exp $
+ */
+
+
+#if !defined(NETBSD_LSOF_H)
+#define NETBSD_LSOF_H 1
+
+#include <stdlib.h>
+#include <dirent.h>
+#include <nlist.h>
+#include <paths.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+
+# if defined(HASGETBOOTFILE)
+#include <util.h>
+# endif /* defined(HASGETBOOTFILE) */
+
+#include <sys/filedesc.h>
+#include <sys/mbuf.h>
+
+# if defined(HAS_LWP_H)
+#include <sys/lwp.h>
+# endif /* defined(HAS_LWP_H) */
+
+# if (defined(OPENBSDV) && OPENBSDV>=3030) \
+ || (defined(NETBSDV) && __NetBSD_Version__>=106060000)
+
+# if defined(OPENBSDV) || __NetBSD_Version__<399001100
+#define _KERNEL
+# endif /* defined(OPENBSDV) || __NetBSD_Version__<399001100 */
+
+# if defined(NETBSDV) && __NetBSD_Version__<399001100
+struct buf; /* dummy for function prototype in <sys/buf.h> */
+struct uio; /* dummy for function prototype in <sys/buf.h> */
+# endif /* defined(NETBSDV && __NetBSD_Version__<399001100) */
+
+#include <sys/ucred.h>
+# endif /* (defined(OPENBSDV) && OPENBSDV>=3030)
+ || (defined(NETBSDV) && __NetBSD_Version__>=106060000) */
+
+# if defined(NETBSDV) && __NetBSD_Version__<399001100
+#include <sys/buf.h>
+# endif /* defined(NETBSDV) && __NetBSD_Version__<399001100 */
+
+# if (defined(OPENBSDV) && OPENBSDV>=3030) \
+ || (defined(NETBSDV) && __NetBSD_Version__>=106060000 \
+ && __NetBSD_Version__<399001100)
+#undef _KERNEL
+# endif /* (defined(OPENBSDV) && OPENBSDV>=3030) \
+ || (defined(NETBSDV) && __NetBSD_Version__>=106060000 \
+ && __NetBSD_Version__<399001100) */
+
+#define NFS
+#define m_stat mnt_stat
+
+# if (defined(OPENBSDV) && OPENBSDV>=3030) \
+ || (defined(NETBSDV) && __NetBSD_Version__>=106060000)
+#define _KERNEL
+# endif /* (defined(OPENBSDV) && OPENBSDV<3030)
+ || (defined(NETBSDV) && __NetBSD_Version__>=106060000) */
+
+#include <sys/mount.h>
+
+# if (defined(OPENBSDV) && OPENBSDV>=3030) \
+ || (defined(NETBSDV) && __NetBSD_Version__>=106060000)
+#undef _KERNEL
+# endif /* (defined(OPENBSDV) && OPENBSDV>=3030)
+ || (defined(NETBSDV) && __NetBSD_Version__>=106060000) */
+
+#include <rpc/types.h>
+#include <sys/protosw.h>
+
+# if defined(NETBSDV) && NETBSDV>=1003000
+#define sockproto NETBSD_sockproto
+# endif /* defined(NETBSDV) && NETBSDV>=1003000 */
+
+#include <sys/socket.h>
+
+# if defined(HASMSDOSFS)
+# if HASMSDOSFS==1
+#include <msdosfs/bpb.h>
+#include <msdosfs/fat.h>
+# else /* HASMSDOSFS!=1 */
+#include <fs/msdosfs/bpb.h>
+#include <fs/msdosfs/fat.h>
+# endif /* HASMSDOSFS==1 */
+
+# if (defined(OPENBSDV) && OPENBSDV<3030) \
+ || (defined(NETBSDV) && __NetBSD_Version__<106060000)
+/*
+ * The netcred and netexport structures may be needed in the msdosfsmount
+ * structure, defined in <msdosfs/msdosfsmount.h>. So as a terrible hack,
+ * the lsof Configure script extracts the netcred and netexport structure
+ * definitions from <sys/mount.h> and places them in "netexport.h".
+ *
+ * When needed, the netcred and netexport structures netcred should really
+ * be obtained from <sys/mount.h>. However they are hidden in <sys/mount.h>
+ * under _KERNEL, and that sometimes can't be defined when including
+ * <sys/mount.h> without causing other seemingly insurmountable #include
+ * problems.
+ *
+ * THIS IS A TERRIBLE AND FRAGILE HACK!!! It might break if the netexport or
+ * netcred definitions change radically in <sys/mount.h>.
+ *
+ * It is no longer needed for NetBSD Versions 1.6F and above, or for OpenBSD
+ * versions 3.3 and above.
+ */
+
+#include "netexport.h"
+# endif /* (defined(OPENBSDV) && OPENBSDV<3030)
+ || (defined(NETBSDV) && __NetBSD_Version__<106060000) */
+
+#define _KERNEL
+struct nameidata; /* to satisfy a function prototype in msdosfsmount.h */
+#include <msdosfs/msdosfsmount.h>
+#undef _KERNEL
+#include <msdosfs/direntry.h>
+#include <msdosfs/denode.h>
+# endif /* defined(HASMSDOSFS) */
+
+# if defined(NETBSDV) && NETBSDV>=1003000
+#undef sockproto
+# endif /* defined(NETBSDV) && NETBSDV>=1003000 */
+
+#include <sys/socketvar.h>
+#include <sys/un.h>
+#include <sys/unpcb.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+# if defined(HASIPv6) && defined(NETBSDV) && !defined(HASINRIAIPv6)
+#include <netinet/ip6.h>
+#include <netinet6/in6_pcb.h>
+# endif /* defined(HASIPv6) && defined(NETBSDV) && !defined(HASINRIAIPv6) */
+
+#include <net/route.h>
+#include <netinet/in_pcb.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+#include <netinet/tcp_fsm.h>
+#include <netinet/tcp_timer.h>
+#include <netinet/tcp_var.h>
+
+# if defined(OPENBSDV)
+# if !defined(TF_ECN_PERMIT)
+#define TF_ECN_PERMIT 0x00008000 /* other side said I could ECN */
+# endif /* !defined(TF_ECN_PERMIT) */
+
+# if !defined(TF_RCVD_CE)
+#define TF_RCVD_CE 0x00010000 /* send ECE in subsequent segs */
+# endif /* !defined(TF_RCVD_CE) */
+
+# if !defined(TF_SEND_CWR)
+#define TF_SEND_CWR 0x00020000 /* send CWR in next seg */
+# endif /* !defined(TF_SEND_CWR) */
+
+# if !defined(TF_DISABLE_ECN)
+#define TF_DISABLE_ECN 0x00040000 /* disable ECN for this connection */
+# endif /* !defined(TF_DISABLE_ECN) */
+
+# endif /* defined(OPENBSDV) */
+
+#include <sys/ucred.h>
+
+# if defined(UVM)
+/*
+ * Avoid conflicts with definitions in <vm/vm_param.h>.
+ */
+
+#undef FALSE
+#undef TRUE
+# endif /* defined(UVM) */
+
+#include <sys/vnode.h>
+
+# if defined(NETBSDV) && NETBSDV>=1003000
+/*
+ * Because late in the 1.3I NetBSD development cycle the sockproto structure
+ * was placed under _KERNEL in <sys/socket.h>, and because defining _KERNEL
+ * before #include'ing <sys/socket.h> causes other #include problems, the
+ * sockproto structure definition that might have been in <sys/socket.h> is
+ * renamed NETBSD_sockproto, and the following definition is used instead.
+ *
+ * Ugly, isn't it?
+ */
+
+struct sockproto {
+ u_short sp_family;
+ u_short sp_protocol;
+};
+# endif /* defined(NETBSDV) && NETBSDV>=1003000 */
+
+#include <net/raw_cb.h>
+#include <sys/domain.h>
+#define pmap RPC_pmap
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#undef pmap
+#define KERNEL
+#include <ufs/ufs/quota.h>
+# if defined(DIRBLKSIZ)
+#define DIRENT_DIRBLKSIZ DIRBLKSIZ
+#undef DIRBLKSIZ
+# endif /* defined(DIRBLKSIZ) */
+
+# if defined(HASI_FFS1)
+#define _KERNEL
+#include <ufs/ufs/ufsmount.h>
+#undef _KERNEL
+# endif /* defined(HASI_FFS1) */
+
+#include <ufs/ufs/inode.h>
+
+# if defined(DIRENT_BLKSIZ)
+#define DIRBLKSIZ DIRENT_DIRBLKSIZ
+#undef DIRENT_DIRBLKSIZ
+# endif /*defined(DIRENT_BLKSIZ) */
+
+# if defined(HASBUFQ_H)
+# if defined(NETBSDV) && NETBSDV>=2099010
+#define _KERNEL
+#include <sys/bufq.h>
+#undef _KERNEL
+# endif /* defined(NETBSDV) && NETBSDV>=2099010 */
+#endif /* defined(HASBUFQ_H) */
+
+#undef KERNEL
+#include <ufs/mfs/mfsnode.h>
+
+# if defined(HASNFSPROTO)
+#include <nfs/rpcv2.h>
+#include <nfs/nfsproto.h>
+# else /* !defined(HASNFSPROTO) */
+#include <nfs/nfsv2.h>
+# endif /* defined(HASNFSPROTO) */
+
+#include <nfs/nfs.h>
+#include <nfs/nfsnode.h>
+#include <sys/proc.h>
+#include <kvm.h>
+#include <sys/sysctl.h>
+# if defined(HASKVMGETPROC2)
+#define P_ADDR p_paddr
+#define P_COMM p_comm
+#define P_CWDI p_cwdi
+#define P_FD p_fd
+#define P_PID p_pid
+#define P_PGID p__pgid
+#define P_PPID p_ppid
+#define P_STAT p_stat
+#define P_TRACEP p_tracep
+#define P_UID p_uid
+#define P_VMSPACE p_vmspace
+# else /* !defined(HASKVMGETPROC2) */
+#define P_ADDR kp_eproc.e_paddr
+#define P_COMM kp_proc.p_comm
+#define P_CWDI kp_proc.p_cwdi
+#define P_FD kp_proc.p_fd
+#define P_PID kp_proc.p_pid
+#define P_PGID kp_eproc.e_pgid
+#define P_PPID kp_eproc.e_ppid
+#define P_STAT kp_proc.p_stat
+#define P_TRACEP kp_proc.p_tracep
+#define P_UID kp_eproc.e_ucred.cr_uid
+#define P_VMSPACE kp_proc.p_vmspace
+# endif /* defined(HASKVMGETPROC2) */
+
+# if defined(HASFDESCFS)
+#define _KERNEL
+#include <miscfs/fdesc/fdesc.h>
+#undef _KERNEL
+# endif /* defined(HASFDESCFS) */
+
+# if defined(HASKERNFS)
+#define _KERNEL
+#define Pkern __Pkern
+#define Proot __Proot
+#define Pnull __Pnull
+#define Ptime __Ptime
+#define Pint __Pint
+#define Pstring __Pstring
+#define Phostname __Phostname
+#define Pavenrun __Pavenrun
+#define Pdevice __Pdevice
+#define Pmsgbuf __Pmsgbuf
+#define Pipsecsadir __Pipsecsadir
+#define Pipsecspdir __Pipsecspdir
+#define Pipsecsa __Pipseca
+#define Pipsecsp __Pipsecsp
+#include <miscfs/kernfs/kernfs.h>
+#undef _KERNEL
+#undef Pkern
+#undef Proot
+#undef Pnull
+#undef Ptime
+#undef Pint
+#undef Pstring
+#undef Phostname
+#undef Pavenrun
+#undef Pdevice
+#undef Pmsgbuf
+#undef Pipsecsadir
+#undef Pipsecspdir
+#undef Pipseca
+#undef Pipsecsp
+# if defined(HASKERNFS_KFS_KT)
+#define kf_kt kfs_kt
+# endif /* defined(HASKERNFS_KFS_KT) */
+# endif /* defined(HASKERNFS) */
+
+# if defined(HASNULLFS)
+#define _KERNEL
+# if defined(NETBSDV) && NETBSDV>=1005000 && __NetBSD_Version__<106060000
+#include "netexport.h"
+# endif /* defined(NETBSDV) && NETBSDV>=1005000
+ && __NetBSD_Version__<106060000 */
+#include <miscfs/nullfs/null.h>
+#undef _KERNEL
+# endif /* defined(HASNULLFS) */
+
+# if defined(HASPROCFS)
+# if defined(HASPROCFS_PFSROOT)
+#define _KERNEL
+# endif /* defined(HASPROCFS_PFSROOT) */
+#include <miscfs/procfs/procfs.h>
+# if defined(HASPROCFS_PFSROOT)
+#undef _KERNEL
+#define Proot PFSroot
+#define Pproc PFSproc
+#define Pcurproc PFScurproc
+#define Pmem PFSmem
+#define Pregs PFSregs
+#define Pfile PFSfile
+#define Pfpregs PFSfpregs
+#define Pctl PFSctl
+#define Pstatus PFSstatus
+#define Pnote PFSnote
+#define Pnotepg PFSnotepg
+# if defined(NetBSDV)
+# if NETBSDV>=2000000
+#define Pfd PFSfd
+# endif /* NETBSDV>=2000000 */
+# if NETBSDV>=1006000
+#define Pmap PFSmap
+#define Pmaps PFSmaps
+# endif /* NETBSDV>=1006000 */
+# endif /* defined(NetBSDV) */
+# endif /* defined(HASPROCFS_PFSROOT) */
+#include <machine/reg.h>
+# endif /* defined(HASPROCFS) */
+
+# if defined(HASPTYFS)
+#define _KERNEL
+#include <fs/ptyfs/ptyfs.h>
+#include <miscfs/specfs/specdev.h>
+#undef _KERNEL
+# endif /* defined(HASPTYFS) */
+
+#define KERNEL
+#define _KERNEL
+#include <sys/file.h>
+#include <sys/fcntl.h>
+
+# if defined(HAS_ADVLOCK_ARGS)
+struct vop_advlock_args;
+# endif /* defined(HAS_ADVLOCK_ARGS) */
+
+# if defined(DTYPE_KQUEUE)
+#define HASKQUEUE /* has the kqueue file type */
+# if defined(OPENBSDV)
+#include <sys/eventvar.h>
+# endif /* defined(OPENBSDV) */
+# endif /* defined(DTYPE_KQUEUE) */
+
+#include <sys/lockf.h>
+#undef KERNEL
+#undef _KERNEL
+
+# if defined(UVM)
+# if defined(OPENBSDV)
+#define _UVM_UVM_FAULT_I_H_ 1 /* avoid OpenBSD's
+ /* <uvm/uvm_fault_i.h */
+# endif /* defined(OPENBSDV) */
+#define FALSE 0
+#define TRUE 1
+#include <uvm/uvm.h>
+# endif /* defined(UVM) */
+
+# if defined(HAS_UVM_INCL)
+#include <uvm/uvm.h>
+#include <uvm/uvm_map.h>
+#include <uvm/uvm_object.h>
+#include <uvm/uvm_pager.h>
+# else /* !defined(HAS_UVM_INCL) */
+#include <vm/vm.h>
+#include <vm/vm_map.h>
+#include <vm/vm_object.h>
+#include <vm/vm_pager.h>
+# endif /* defined(HAS_UVM_INCL) */
+
+# if defined(HAS_SYS_PIPEH)
+# if OPENBSDV==2030 && defined(__sparc__)
+# if defined(nbpg)
+#undef nbpg
+# endif /* defined(nbpg) */
+#define nbpg 4096 /* WARNING!!! This should be 8192 for sun4,
+ * but there's not much chance this value will
+ * ever be used by any lsof code. (See the
+ * use of PIPE_NODIRECT in <sys/pipe.h>. */
+# endif /* OPENBSDV==2030 && defined(__sparc__) */
+#include <sys/pipe.h>
+#endif /* defined(HAS_SYS_PIPEH) */
+
+#define COMP_P const void
+#define DEVINCR 1024 /* device table malloc() increment */
+typedef u_long KA_T;
+#define KMEM "/dev/kmem"
+#define MALLOC_P void
+#define FREE_P MALLOC_P
+#define MALLOC_S size_t
+
+# if !defined(MAXSYSCMDL)
+#define MAXSYSCMDL MAXCOMLEN /* max system command name length */
+# endif /* !defined(MAXSYSCMDL) */
+
+# if defined(N_UNIXV)
+#define N_UNIX_TMP(x) #x
+#define N_UNIX_STR(x) N_UNIX_TMP(x)
+#define N_UNIX N_UNIX_STR(N_UNIXV)
+# endif /* defined(N_UNIXV) */
+
+#define QSORT_P void
+#define READLEN_T int
+#define STRNCPY_L size_t
+#define SWAP "/dev/drum"
+#define SZOFFTYPE unsigned long long
+ /* size and offset internal storage
+ * type */
+#define SZOFFPSPEC "ll" /* SZOFFTYPE print specification
+ * modifier */
+
+
+/*
+ * Global storage definitions (including their structure definitions)
+ */
+
+extern struct file *Cfp;
+extern kvm_t *Kd;
+extern KA_T Kpa;
+
+struct l_vfs {
+ KA_T addr; /* kernel address */
+ fsid_t fsid; /* file system ID */
+ char type[MFSNAMELEN]; /* type of file system */
+ char *dir; /* mounted directory */
+ char *fsname; /* file system name */
+ struct l_vfs *next; /* forward link */
+};
+extern struct l_vfs *Lvfs;
+
+struct mounts {
+ char *dir; /* directory (mounted on) */
+ char *fsname; /* file system
+ * (symbolic links unresolved) */
+ char *fsnmres; /* file system
+ * (symbolic links resolved) */
+ dev_t dev; /* directory st_dev */
+ dev_t rdev; /* directory st_rdev */
+ INODETYPE inode; /* directory st_ino */
+ mode_t mode; /* directory st_mode */
+ mode_t fs_mode; /* file_system st_mode */
+ struct mounts *next; /* forward link */
+};
+
+#define X_NCACHE "ncache"
+#define X_NCSIZE "ncsize"
+#define NL_NAME n_name
+
+extern int Np; /* number of kernel processes */
+
+# if defined(HASKVMGETPROC2)
+struct kinfo_proc2 *P; /* local process table copy */
+# else /* ! defined(HASKVMGETPROC2) */
+struct kinfo_proc *P; /* local process table copy */
+# endif /* defined(HASKVMGETPROC2) */
+
+extern int pgshift; /* kernel's page shift */
+
+struct sfile {
+ char *aname; /* argument file name */
+ char *name; /* file name (after readlink()) */
+ char *devnm; /* device name (optional) */
+ dev_t dev; /* device */
+ dev_t rdev; /* raw device */
+ u_short mode; /* S_IFMT mode bits from stat() */
+ int type; /* file type: 0 = file system
+ * 1 = regular file */
+ INODETYPE i; /* inode number */
+ int f; /* file found flag */
+ struct sfile *next; /* forward link */
+
+};
+
+
+/*
+ * Definitions for rdev.c
+ */
+
+#define DIRTYPE dirent
+#define HASDNAMLEN 1 /* struct DIRTYPE has d_namlen element */
+
+
+/*
+ * Definitions for rnam.c and rnmh.c
+ */
+
+# if defined(HASNCACHE)
+# if (defined(OPENBSDV) && OPENBSDV>=2010) || (defined(NETBSDV) && NETBSDV>=1002000)
+#include <stddef.h>
+#endif /* (defined(OPENBSDV) && OPENBSDV>=2010) || (defined(NETBSDV) && NETBSDV>=1002000) */
+
+#include <sys/uio.h>
+#include <sys/namei.h>
+#define NCACHE namecache /* kernel's structure name */
+#define NCACHE_NM nc_name /* name in NCACHE */
+#define NCACHE_NMLEN nc_nlen /* name length in NCACHE */
+#define NCACHE_NODEADDR nc_vp /* node address in NCACHE */
+#define NCACHE_PARADDR nc_dvp /* parent node address in NCACHE */
+
+# if (defined(OPENBSDV) && OPENBSDV>=2010) || (defined(NETBSDV) && NETBSDV>=1002000)
+#define NCACHE_NXT nc_hash.le_next /* link in NCACHE */
+# else /* (defined(OPENBSDV) && OPENBSDV>=2010) || (defined(NETBSDV) && NETBSDV>=1002000) */
+# if defined(NetBSD1_0) && NetBSD<1994101
+#define NCACHE_NXT nc_nxt /* link in NCACHE */
+# else /* !defined(NetBSD1_0) || NetBSD>=1994101 */
+#define NCACHE_NXT nc_lru.tqe_next /* link in NCACHE */
+# endif /* defined(NetBSD1_0) && NetBSD<1994101 */
+# endif /* (defined(OPENBSDV) && OPENBSDV>=2010) || (defined(NETBSDV) && NETBSDV>=1002000) */
+
+# if defined(HASNCVPID)
+#define NCACHE_PARID nc_dvpid /* parent node ID in NCACHE */
+#define NCACHE_NODEID nc_vpid /* node ID in NCACHE */
+# endif /* defined(HASNCVPID) */
+# endif /* defined(HASNCACHE) */
+
+#endif /* NETBSD_LSOF_H */
diff --git a/dialects/n+obsd/dmnt.c b/dialects/n+obsd/dmnt.c
new file mode 100644
index 0000000..51aa4b0
--- /dev/null
+++ b/dialects/n+obsd/dmnt.c
@@ -0,0 +1,256 @@
+/*
+ * dmnt.c - NetBSD and OpenBSD mount support functions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dmnt.c,v 1.12 2005/08/08 19:53:24 abe Exp $";
+#endif
+
+
+#if defined(NETBSDV) && defined(HASSTATVFS)
+/*
+ * NetBSD needs the statvfs structure to be defined without the
+ * pre-definition of _KERNEL.
+ */
+
+#include <sys/statvfs.h>
+#endif /* defined(NETBSDV) && defined(HASSTATVFS) */
+
+#include "lsof.h"
+
+
+/*
+ * Local static definitions
+ */
+
+static struct mounts *Lmi = (struct mounts *)NULL; /* local mount info */
+static int Lmist = 0; /* Lmi status */
+
+
+/*
+ * readmnt() - read mount table
+ */
+
+struct mounts *
+readmnt()
+{
+ char *dn = (char *)NULL;
+ char *ln;
+ struct mounts *mtp;
+ int n;
+ struct stat sb;
+
+#if defined(HASPROCFS)
+ unsigned char procfs = 0;
+#endif /* defined(HASPROCFS) */
+
+#if defined(HASSTATVFS)
+ struct statvfs *mb = (struct statvfs *)NULL;
+#else /* !defined(HASSTATVFS) */
+ struct statfs *mb = (struct statfs *)NULL;
+#endif /* defined(HASSTATVFS) */
+
+ if (Lmi || Lmist)
+ return(Lmi);
+/*
+ * Access mount information.
+ */
+ if ((n = getmntinfo(&mb, MNT_NOWAIT)) <= 0) {
+ (void) fprintf(stderr, "%s: no mount information\n", Pn);
+ return(0);
+ }
+/*
+ * Read mount information.
+ */
+ for (; n; n--, mb++) {
+ if (mb->f_fstypename[0] == '\0')
+ continue;
+ mb->f_fstypename[MFSNAMELEN - 1] = '\0';
+ /*
+ * Interpolate a possible symbolic directory link.
+ */
+ if (dn)
+ (void) free((FREE_P *)dn);
+ if (!(dn = mkstrcpy(mb->f_mntonname, (MALLOC_S *)NULL))) {
+
+no_space_for_mount:
+
+ (void) fprintf(stderr, "%s: no space for mount at ", Pn);
+ safestrprt(mb->f_mntonname, stderr, 0);
+ (void) fprintf(stderr, " (");
+ safestrprt(mb->f_mntfromname, stderr, 0);
+ (void) fprintf(stderr, ")\n");
+ Exit(1);
+ }
+ if ((ln = Readlink(dn)) == NULL) {
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ " Output information may be incomplete.\n");
+ }
+ continue;
+ }
+ if (ln != dn) {
+ (void) free((FREE_P *)dn);
+ dn = ln;
+ }
+ if (*dn != '/')
+ continue;
+ /*
+ * Stat() the directory.
+ */
+ if (statsafely(dn, &sb)) {
+ if (!Fwarn) {
+ (void) fprintf(stderr, "%s: WARNING: can't stat() ", Pn);
+ safestrprt(mb->f_fstypename, stderr, 0);
+ (void) fprintf(stderr, " file system ");
+ safestrprt(mb->f_mntonname, stderr, 1);
+ (void) fprintf(stderr,
+ " Output information may be incomplete.\n");
+ }
+ (void) bzero((char *)&sb, sizeof(sb));
+
+#if defined(HASSTATVFS)
+ sb.st_dev = (dev_t)mb->f_fsid;
+#else /* !defined(HASSTATVFS) */
+ sb.st_dev = (dev_t)mb->f_fsid.val[0];
+#endif /* defined(HASSTATVFS) */
+
+ sb.st_mode = S_IFDIR | 0777;
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ " assuming \"dev=%x\" from mount table\n",
+ sb.st_dev);
+ }
+ }
+ /*
+ * Allocate and fill a local mount structure.
+ */
+ if (!(mtp = (struct mounts *)malloc(sizeof(struct mounts))))
+ goto no_space_for_mount;
+ mtp->dir = dn;
+ dn = (char *)NULL;
+
+#if defined(HASPROCFS)
+ if (strcmp(mb->f_fstypename, MOUNT_PROCFS) == 0) {
+
+ /*
+ * Save information on exactly one procfs file system.
+ */
+ if (procfs)
+ Mtprocfs = (struct mounts *)NULL;
+ else {
+ procfs = 1;
+ Mtprocfs = mtp;
+ }
+ }
+#endif /* defined(HASPROCFS) */
+
+ mtp->next = Lmi;
+ mtp->dev = sb.st_dev;
+ mtp->rdev = sb.st_rdev;
+ mtp->inode = (INODETYPE)sb.st_ino;
+ mtp->mode = sb.st_mode;
+ /*
+ * Interpolate a possible file system (mounted-on) device name link.
+ */
+ if (!(dn = mkstrcpy(mb->f_mntfromname, (MALLOC_S *)NULL)))
+ goto no_space_for_mount;
+ mtp->fsname = dn;
+ ln = Readlink(dn);
+ dn = (char *)NULL;
+ /*
+ * Stat() the file system (mounted-on) name and add file system
+ * information to the local mount table entry.
+ */
+ if (!ln || statsafely(ln, &sb))
+ sb.st_mode = 0;
+ mtp->fsnmres = ln;
+ mtp->fs_mode = sb.st_mode;
+ Lmi = mtp;
+ }
+/*
+ * Clean up and return local mount info table address.
+ */
+ if (dn)
+ (void) free((FREE_P *)dn);
+ Lmist = 1;
+ return(Lmi);
+}
+
+
+/*
+ * readvfs() - read vfs structure
+ */
+
+struct l_vfs *
+readvfs(vm)
+ KA_T vm; /* kernel mount address from vnode */
+{
+ struct mount m;
+ struct l_vfs *vp;
+/*
+ * Search for match on existing entry.
+ */
+ for (vp = Lvfs; vp; vp = vp->next) {
+ if (vm == vp->addr)
+ return(vp);
+ }
+/*
+ * Read the (new) mount structure, allocate a local entry, and fill it.
+ */
+ if (kread(vm, (char *)&m, sizeof(m)) != 0)
+ return((struct l_vfs *)NULL);
+ if (!(vp = (struct l_vfs *)malloc(sizeof(struct l_vfs)))) {
+ (void) fprintf(stderr, "%s: PID %d, no space for vfs\n",
+ Pn, Lp->pid);
+ Exit(1);
+ }
+ if (!(vp->dir = mkstrcpy(m.m_stat.f_mntonname, (MALLOC_S *)NULL))
+ || !(vp->fsname = mkstrcpy(m.m_stat.f_mntfromname, (MALLOC_S *)NULL)))
+ {
+ (void) fprintf(stderr, "%s: PID %d, no space for mount names\n",
+ Pn, Lp->pid);
+ Exit(1);
+ }
+ vp->addr = vm;
+
+#if defined(HASSTATVFS)
+ vp->fsid = m.m_stat.f_fsidx;
+#else /* !defined(HASSTATVFS) */
+ vp->fsid = m.m_stat.f_fsid;
+#endif /* defined(HASSTATVFS) */
+
+ (void) snpf(vp->type, sizeof(vp->type), "%s", m.m_stat.f_fstypename);
+ vp->next = Lvfs;
+ Lvfs = vp;
+ return(vp);
+}
diff --git a/dialects/n+obsd/dnode.c b/dialects/n+obsd/dnode.c
new file mode 100644
index 0000000..79d7795
--- /dev/null
+++ b/dialects/n+obsd/dnode.c
@@ -0,0 +1,1459 @@
+/*
+ * dnode.c - NetBSD and OpenBSD node functions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dnode.c,v 1.38 2007/04/24 16:22:02 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+#if defined(HAS_DINODE_U)
+#define DINODE_U dinode_u
+#else /* !defined(HAS_DINODE_U) */
+#define DINODE_U i_din
+#endif /* defined(HAS_DINODE_U) */
+
+#if defined(HASFDESCFS) && HASFDESCFS==1
+_PROTOTYPE(static int lkup_dev_tty,(dev_t *dr, INODETYPE *ir));
+#endif /* defined(HASFDESCFS) && HASFDESCFS==1 */
+
+#if defined(HAS_UM_UFS)
+#define UFS1 UM_UFS1
+#define UFS2 UM_UFS2
+#endif /* defined(HAS_UM_UFS) */
+
+#if defined(HASPROCFS)
+_PROTOTYPE(static void getmemsz,(pid_t pid));
+
+# if !defined(PGSHIFT)
+#define PGSHIFT pgshift
+# endif /* !defined(PGSHIFT) */
+
+
+/*
+ * getmemsz() - get memory size of a /proc/<n>/mem entry
+ */
+
+static void
+getmemsz(pid)
+ pid_t pid;
+{
+ int n;
+ struct vmspace vm;
+
+#if defined(HASKVMGETPROC2)
+ struct kinfo_proc2 *p;
+#else /* !defined(HASKVMGETPROC2) */
+ struct kinfo_proc *p;
+#endif /* defined(HASKVMGETPROC2) */
+
+ for (n = 0, p = P; n < Np; n++, p++) {
+ if (p->P_PID == pid) {
+ if (!p->P_VMSPACE
+ || kread((KA_T)p->P_VMSPACE, (char *)&vm, sizeof(vm)))
+ return;
+# if defined(OPENBSDV)
+ Lf->sz = (SZOFFTYPE)((vm.vm_tsize + vm.vm_dsize
+ + vm.vm_ssize) * sysconf(_SC_PAGESIZE));
+# else /* !defined(OPENBSDV */
+ Lf->sz = (SZOFFTYPE)ctob(vm.vm_tsize + vm.vm_dsize
+ + vm.vm_ssize);
+# endif /* defined(OPENBSDV) */
+
+ Lf->sz_def = 1;
+ return;
+ }
+ }
+}
+#undef PGSHIFT
+#endif /* defined(HASPROCFS) */
+
+
+#if defined(HASFDESCFS) && HASFDESCFS==1
+/*
+ * lkup_dev_tty() - look up /dev/tty
+ */
+
+static int
+lkup_dev_tty(dr, ir)
+ dev_t *dr; /* place to return device number */
+ INODETYPE *ir; /* place to return inode number */
+{
+ int i;
+
+ readdev(0);
+
+# if defined(HASDCACHE)
+
+lkup_dev_tty_again:
+
+# endif /* defined(HASDCACHE) */
+
+ for (i = 0; i < Ndev; i++) {
+ if (strcmp(Devtp[i].name, "/dev/tty") == 0) {
+
+# if defined(HASDCACHE)
+ if (DCunsafe && !Devtp[i].v && !vfy_dev(&Devtp[i]))
+ goto lkup_dev_tty_again;
+# endif /* defined(HASDCACHE) */
+
+ *dr = Devtp[i].rdev;
+ *ir = Devtp[i].inode;
+ return(1);
+ }
+ }
+
+# if defined(HASDCACHE)
+ if (DCunsafe) {
+ (void) rereaddev();
+ goto lkup_dev_tty_again;
+ }
+# endif /* defined(HASDCACHE) */
+
+ return(-1);
+}
+#endif /* defined(HASFDESCFS) && HASFDESCFS==1 */
+
+
+#if defined(HASKQUEUE)
+/*
+ * process_kqueue() -- process kqueue file
+ *
+ * Strictly speaking this function should appear in dfile.c, because it is
+ * a file processing function. However, the Net and Open BSD sources don't
+ * require a dfile.c, so this is the next best location for the function.
+ */
+
+void
+process_kqueue(ka)
+ KA_T ka; /* kqueue file structure address */
+{
+
+# if defined(OPENBSDV)
+ struct kqueue kq; /* kqueue structure */
+# endif /* defined(OPENBSDV) */
+
+ (void) snpf(Lf->type, sizeof(Lf->type), "KQUEUE");
+ enter_dev_ch(print_kptr(ka, (char *)NULL, 0));
+
+# if defined(OPENBSDV)
+ if (!ka || kread(ka, (char *)&kq, sizeof(kq)))
+ return;
+ (void) snpf(Namech, Namechl, "count=%d, state=%#x", kq.kq_count,
+ kq.kq_state);
+ enter_nm(Namech);
+# endif /* defined(OPENBSDV) */
+
+}
+#endif /* defined(HASKQUEUE) */
+
+
+/*
+ * process_node() - process vnode
+ */
+
+void
+process_node(va)
+ KA_T va; /* vnode kernel space address */
+{
+ dev_t dev, rdev;
+ unsigned char devs;
+ unsigned char lt;
+ unsigned char ns;
+ unsigned char rdevs;
+ char *ep, *ty;
+ struct lockf lf, *lff, *lfp;
+ struct inode i;
+ struct mfsnode m;
+ struct nfsnode n;
+ enum nodetype {NONODE, CDFSNODE, DOSNODE, EXT2NODE, FDESCNODE, INODE,
+ KERNFSNODE, MFSNODE, NFSNODE, PFSNODE, PTYFSNODE} nty;
+ enum vtype type;
+ struct vnode *v, vb;
+ struct l_vfs *vfs;
+
+#if defined(HAS9660FS)
+ dev_t iso_dev;
+ INODETYPE iso_ino;
+ long iso_nlink;
+ int iso_stat;
+ SZOFFTYPE iso_sz;
+#endif /* defined(HAS9660FS) */
+
+#if defined(HASFDESCFS)
+ struct fdescnode f;
+
+# if HASFDESCFS==1
+ static dev_t f_tty_dev;
+ static INODETYPE f_tty_ino;
+ static int f_tty_s = 0;
+# endif /* HASFDESCFS==1 */
+
+#endif /* defined(HASFDESCFS) */
+
+#if defined(HASEXT2FS)
+# if defined(HASI_E2FS_PTR)
+ struct ext2fs_dinode ed;
+# endif /* defined(HASI_E2FS_PTR) */
+ struct ext2fs_dinode *edp = (struct ext2fs_dinode *)NULL;
+#endif /* defined(HASEXT2FS) */
+
+#if defined(HASI_FFS1)
+ unsigned char ffs = 0;
+ unsigned char u1s = 0;
+ unsigned char u2s = 0;
+ struct ufs1_dinode u1;
+ struct ufs2_dinode u2;
+ struct ufsmount um;
+#endif /* defined(HASI_FFS1) */
+
+#if defined(HASKERNFS)
+ struct kernfs_node kn;
+ struct stat ksb;
+ int ksbs;
+ struct kern_target kt;
+ int ktnl;
+ char ktnm[MAXPATHLEN+1];
+#endif /* defined(HASKERNFS) */
+
+#if defined(HASMSDOSFS)
+ struct denode d;
+ u_long dpb;
+ INODETYPE nn;
+ struct msdosfsmount pm;
+#endif /* defined(HASMSDOSFS) */
+
+#if defined(HASNFSVATTRP)
+ struct vattr nv;
+#define NVATTR nv
+#else /* !defined(HASNFSVATTRP) */
+#define NVATTR n.n_vattr
+#endif /* defined(HASNFSVATTRP) */
+
+#if defined(HASNULLFS)
+ struct null_node nu;
+ int sc = 0;
+ struct l_vfs *nvfs = (struct l_vfs *)NULL;
+#endif /* defined(HASNULLFS) */
+
+#if defined(HASPROCFS)
+ struct pfsnode p;
+ struct procfsid *pfi;
+ size_t sz;
+#endif /* defined(HASPROCFS) */
+
+#if defined(HASPTYFS)
+ struct ptyfsnode pt;
+ struct specinfo si;
+#endif /* defined(HASPTYFS) */
+
+#if defined(HASNULLFS)
+
+process_overlaid_node:
+
+ if (++sc > 1024) {
+ (void) snpf(Namech, Namechl, "too many overlaid nodes");
+ enter_nm(Namech);
+ return;
+ }
+#endif /* defined(HASNULLFS) */
+
+/*
+ * Initialize miscellaneous variables. This is done so that processing an
+ * overlaid node will be a fresh start.
+ */
+ devs = rdevs = 0;
+ nty = NONODE;
+ Namech[0] = '\0';
+
+#if defined(HAS9660FS)
+ iso_stat = 0;
+#endif /* defined(HAS9660FS) */
+
+#if defined(HASKERNFS)
+ ksbs = 0;
+#endif /* defined(HASKERNFS) */
+
+#if defined(HASEXT2FS)
+ edp = (struct ext2fs_dinode *)NULL;
+#endif /* defined(HASEXT2FS) */
+
+#if defined(HASI_FFS1)
+ ffs = u1s = u2s = 0;
+#endif /* defined(HASI_FFS1) */
+
+/*
+ * Read the vnode.
+ */
+ if (!va) {
+ enter_nm("no vnode address");
+ return;
+ }
+ v = &vb;
+ if (readvnode(va, v)) {
+ enter_nm(Namech);
+ return;
+ }
+
+#if defined(HASNCACHE)
+ Lf->na = va;
+# if defined(HASNCVPID)
+ Lf->id = v->v_id;
+# endif /* defined(HASNCVPID) */
+#endif /* defined(HASNCACHE) */
+
+#if defined(HASFSTRUCT)
+ Lf->fna = va;
+ Lf->fsv |= FSV_NI;
+#endif /* defined(HASFSTRUCT) */
+
+/*
+ * Get the vnode type.
+ */
+ if (!v->v_mount)
+ vfs = (struct l_vfs *)NULL;
+ else {
+ vfs = readvfs((KA_T)v->v_mount);
+ if (vfs) {
+ if (strcmp(vfs->type, MOUNT_NFS) == 0)
+ Ntype = N_NFS;
+
+#if defined(HASKERNFS)
+ else if (strcmp(vfs->type, MOUNT_KERNFS) == 0)
+ Ntype = N_KERN;
+#endif /* defined(HASKERNFS) */
+
+#if defined(HASPROCFS)
+ else if (strcmp(vfs->type, MOUNT_PROCFS) == 0)
+ Ntype = N_PROC;
+#endif /* defined(HASPROCFS) */
+
+#if defined(HAS9660FS)
+ else if (strcmp(vfs->type, MOUNT_CD9660) == 0)
+ Ntype = N_CDFS;
+#endif /* defined(HAS9660FS) */
+
+ }
+ }
+ if (Ntype == N_REGLR) {
+ switch (v->v_type) {
+ case VFIFO:
+ Ntype = N_FIFO;
+ break;
+ }
+ }
+/*
+ * Read the successor node.
+ */
+ switch (v->v_tag) {
+
+#if defined(HAS9660FS)
+ case VT_ISOFS:
+ if (read_iso_node(v, &iso_dev, &iso_ino, &iso_nlink, &iso_sz))
+ {
+ (void) snpf(Namech, Namechl, "can't read iso_node at: %s",
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ iso_stat = 1;
+ nty = CDFSNODE;
+ break;
+#endif /* defined(HAS9660FS) */
+
+#if defined(HASFDESCFS)
+ case VT_FDESC:
+ if (!v->v_data
+ || kread((KA_T)v->v_data, (char *)&f, sizeof(f))) {
+ (void) snpf(Namech, Namechl, "can't read fdescnode at: %x",
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ nty = FDESCNODE;
+ break;
+#endif /* defined(HASFDESCFS) */
+
+#if defined(HASKERNFS)
+ case VT_KERNFS:
+
+ /*
+ * Read the kernfs_node.
+ */
+ if (!v->v_data
+ || kread((KA_T)v->v_data, (char *)&kn, sizeof(kn))) {
+ if (v->v_type != VDIR || !(v->v_flag && VROOT)) {
+ (void) snpf(Namech, Namechl,
+ "can't read kernfs_node at: %s",
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ } else
+ kn.kf_kt = (struct kern_target *)NULL;
+ }
+ /*
+ * Generate the /kern file name by reading the kern_target to which
+ * the kernfs_node points.
+ */
+ if (kn.kf_kt
+ && kread((KA_T)kn.kf_kt, (char *)&kt, sizeof(kt)) == 0
+ && (ktnl = (int)kt.kt_namlen) > 0
+ && kt.kt_name)
+ {
+ if (ktnl > (sizeof(ktnm) - 1))
+ ktnl = sizeof(ktnm) - 1;
+ if (!kread((KA_T)kt.kt_name, ktnm, ktnl)) {
+ ktnm[ktnl] = 0;
+ ktnl = strlen(ktnm);
+ if (ktnl > (MAXPATHLEN - strlen(_PATH_KERNFS) - 2)) {
+ ktnl = MAXPATHLEN - strlen(_PATH_KERNFS) - 2;
+ ktnm[ktnl] = '\0';
+ }
+ (void) snpf(Namech, Namechl, "%s/%s", _PATH_KERNFS, ktnm);
+ }
+ }
+ /*
+ * If this is the /kern root directory, its name, inode number and
+ * size are fixed; otherwise, safely stat() the file to get the
+ * inode number and size.
+ */
+ if (v->v_type == VDIR && (v->v_flag & VROOT)) {
+ (void) snpf(Namech, Namechl, "%s", _PATH_KERNFS);
+ ksb.st_ino = (ino_t)2;
+ ksb.st_size = DEV_BSIZE;
+ ksbs = 1;
+ } else if (Namech[0] && statsafely(Namech, &ksb) == 0)
+ ksbs = 1;
+ nty = KERNFSNODE;
+ break;
+#endif /* defined(HASKERNFS) */
+
+ case VT_MFS:
+ if (!v->v_data
+ || kread((KA_T)v->v_data, (char *)&m, sizeof(m))) {
+ (void) snpf(Namech, Namechl, "can't read mfsnode at: %s",
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ nty = MFSNODE;
+ break;
+
+#if defined(HASMSDOSFS)
+ case VT_MSDOSFS:
+ if (!v->v_data
+ || kread((KA_T)v->v_data, (char *)&d, sizeof(d))) {
+ (void) snpf(Namech, Namechl, "can't read denode at: %s",
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ nty = DOSNODE;
+ break;
+#endif /* defined(HASMSDOSFS) */
+
+ case VT_NFS:
+ if (!v->v_data
+ || kread((KA_T)v->v_data, (char *)&n, sizeof(n))) {
+ (void) snpf(Namech, Namechl, "can't read nfsnode at: %s",
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+
+#if defined(HASNFSVATTRP)
+ if (!n.n_vattr
+ || kread((KA_T)n.n_vattr, (char *)&nv, sizeof(nv))) {
+ (void) snpf(Namech, Namechl, "can't read n_vattr at: %x",
+ print_kptr((KA_T)n.n_vattr, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+#endif /* defined(HASNFSVATTRP) */
+
+ nty = NFSNODE;
+ break;
+
+#if defined(HASNULLFS)
+ case VT_NULL:
+ if ((sc == 1) && vfs)
+ nvfs = vfs;
+ if (!v->v_data
+ || kread((KA_T)v->v_data, (char *)&nu, sizeof(nu))) {
+ (void) snpf(Namech, Namechl, "can't read null_node at: %s",
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ if (!nu.null_lowervp) {
+ (void) snpf(Namech, Namechl, "null_node overlays nothing");
+ enter_nm(Namech);
+ return;
+ }
+ va = (KA_T)nu.null_lowervp;
+ goto process_overlaid_node;
+#endif /* defined(HASNULLFS) */
+
+#if defined(HASPROCFS)
+ case VT_PROCFS:
+ if (!v->v_data
+ || kread((KA_T)v->v_data, (char *)&p, sizeof(p))) {
+ (void) snpf(Namech, Namechl, "can't read pfsnode at: %s",
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ nty = PFSNODE;
+ break;
+#endif /* defined(HASPROCFS) */
+
+#if defined(HASPTYFS)
+ case VT_PTYFS:
+ if (!v->v_data
+ || kread((KA_T)v->v_data, (char *)&pt, sizeof(pt))) {
+ (void) snpf(Namech, Namechl, "can't read ptyfsnode at: %s",
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ nty = PTYFSNODE;
+ break;
+#endif /* defined(HASPTYFS) */
+
+#if defined(HASEXT2FS)
+ case VT_EXT2FS:
+#endif /* defined(HASEXT2FS) */
+
+#if defined(HASLFS)
+ case VT_LFS:
+#endif /* defined(HASLFS) */
+
+ case VT_UFS:
+ if (!v->v_data
+ || kread((KA_T)v->v_data, (char *)&i, sizeof(i))) {
+ (void) snpf(Namech, Namechl, "can't read inode at: %s",
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+
+#if defined(HASEXT2FS)
+ if (v->v_tag == VT_EXT2FS) {
+ nty = EXT2NODE;
+
+# if defined(HASI_E2FS_PTR)
+ if (i.DINODE_U.e2fs_din
+ && !kread((KA_T)i.DINODE_U.e2fs_din, (char *)&ed, sizeof(ed)))
+ edp = &ed;
+# else /* !defined(HASI_E2FS_PTR) */
+# if HASEXT2FS<2
+ edp = &i.DINODE_U.e2fs_din;
+# else /* HASEXT2FS>=2 */
+ edp = &i.i_e2din;
+# endif /* HASEXT2FS>=2 */
+# endif /* defined(HASI_E2FS_PTR) */
+
+ } else
+#endif /* defined(HASEXT2FS) */
+
+ {
+ nty = INODE;
+
+#if defined(HASI_FFS1)
+ /*
+ * If there are multiple FFS's, read the relevant structures.
+ */
+ if (i.i_ump
+ && !kread((KA_T)i.i_ump, (char *)&um, sizeof(um))) {
+ if (um.um_fstype == UFS1) {
+ ffs = 1;
+ if (i.DINODE_U.ffs1_din
+ && !kread((KA_T)i.DINODE_U.ffs1_din, (char *)&u1,
+ sizeof(u1)))
+ {
+ u1s = 1;
+ }
+ } else if (um.um_fstype == UFS2) {
+ ffs = 2;
+ if (i.DINODE_U.ffs2_din
+ && !kread((KA_T)i.DINODE_U.ffs2_din, (char *)&u2,
+ sizeof(u2)))
+ {
+ u2s = 1;
+ }
+ }
+ }
+#endif /* defined(HASI_FFS1) */
+
+ }
+
+ if ((lff = i.i_lockf)) {
+
+ /*
+ * Determine the lock state.
+ */
+ lfp = lff;
+ do {
+ if (kread((KA_T)lfp, (char *)&lf, sizeof(lf)))
+ break;
+ lt = 0;
+ switch(lf.lf_flags & (F_FLOCK|F_POSIX)) {
+ case F_FLOCK:
+ if (Cfp && (struct file *)lf.lf_id == Cfp)
+ lt = 1;
+ break;
+ case F_POSIX:
+ if ((KA_T)lf.lf_id == Kpa)
+ lt = 1;
+
+#if defined(HAS_LWP_H) && !defined(HAS_LF_LWP)
+ else {
+
+ struct lwp lw;
+
+ if (!kread((KA_T)lf.lf_id, (char *)&lw, sizeof(lw))
+ && (KA_T)lw.l_proc == Kpa)
+ lt = 1;
+ }
+#endif /* defined(HAS_LWP_H) && !defined(HAS_LF_LWP) */
+
+ break;
+ }
+ if (!lt)
+ continue;
+ if (lf.lf_start == (off_t)0
+ && lf.lf_end == 0xffffffffffffffffLL)
+ lt = 1;
+ else
+ lt = 0;
+ if (lf.lf_type == F_RDLCK)
+ Lf->lock = lt ? 'R' : 'r';
+ else if (lf.lf_type == F_WRLCK)
+ Lf->lock = lt ? 'W' : 'w';
+ else if (lf.lf_type == (F_RDLCK | F_WRLCK))
+ Lf->lock = 'u';
+ break;
+ } while ((lfp = lf.lf_next) && lfp != lff);
+ }
+ break;
+ default:
+ if (v->v_type == VBAD || v->v_type == VNON)
+ break;
+ (void) snpf(Namech, Namechl, "unknown file system type: %d",
+ v->v_tag);
+ enter_nm(Namech);
+ return;
+ }
+/*
+ * Get device and type for printing.
+ */
+ type = v->v_type;
+ switch (nty) {
+
+
+#if defined(HASMSDOSFS)
+ case DOSNODE:
+ dev = d.de_dev;
+ devs = 1;
+ break;
+#endif /* defined(HASMSDOSFS) */
+
+#if defined(HASFDESCFS)
+ case FDESCNODE:
+
+# if defined(HASFDLINK)
+ if (f.fd_link
+ && !kread((KA_T)f.fd_link, Namech, Namechl - 1)) {
+ Namech[Namechl - 1] = '\0';
+ break;
+ }
+# endif /* defined(HASFDLINK) */
+
+# if HASFDESCFS==1
+ if (f.fd_type == Fctty) {
+ if (f_tty_s == 0)
+ f_tty_s = lkup_dev_tty(&f_tty_dev, &f_tty_ino);
+ if (f_tty_s == 1) {
+ dev = DevDev;
+ rdev = f_tty_dev;
+ Lf->inode = f_tty_ino;
+ devs = Lf->inp_ty = rdevs = 1;
+ }
+ }
+ break;
+# endif /* HASFDESCFS==1 */
+#endif /* defined(HASFDESCFS) */
+
+#if defined(HASEXT2FS)
+ case EXT2NODE:
+
+ dev = i.i_dev;
+ devs = 1;
+ if ((type == VCHR) || (type == VBLK)) {
+
+# if defined(HASI_E2FS_PTR)
+ if (edp) {
+ rdev = edp->e2di_rdev;
+ rdevs = 1;
+ }
+# else /* !defined(HASI_E2FS_PTR) */
+# if HASEXT2FS<2
+ rdev = i.DINODE_U.e2fs_din.e2di_rdev;
+# else /* HASEXT2FS>=2 */
+ rdev = i.i_e2din.e2di_rdev;
+# endif /* HASEXT2FS>=2 */
+ rdevs = 1;
+# endif /* defined(HASI_E2FS_PTR) */
+
+ }
+ break;
+#endif /* defined(HASEXT2FS) */
+
+ case INODE:
+ dev = i.i_dev;
+ devs = 1;
+ if ((type == VCHR) || (type == VBLK)) {
+
+#if defined(HASI_FFS)
+ rdev = i.i_ffs_rdev;
+ rdevs = 1;
+#else /* !defined(HASI_FFS) */
+# if defined(HASI_FFS1)
+ if (ffs == 1) {
+ if (u1s) {
+ rdev = u1.di_rdev;
+ rdevs = 1;
+ }
+ } else if (ffs == 2) {
+ if (u2s) {
+ rdev = u2.di_rdev;
+ rdevs = 1;
+ }
+ }
+# else /* !defined(HASI_FFS1) */
+ rdev = i.i_rdev;
+ rdevs = 1;
+# endif /* defined(HASI_FFS1) */
+#endif /* defined(HASI_FFS) */
+
+ }
+ break;
+
+#if defined(HASKERNFS)
+ case KERNFSNODE:
+ if (vfs) {
+
+# if defined(HASSTATVFS)
+ dev = (dev_t)vfs->fsid.__fsid_val[0];
+# else /* !defined(HASSTATVFS) */
+ dev = (dev_t)vfs->fsid.val[0];
+# endif /* defined(HASSTATVFS) */
+
+ devs = 1;
+ }
+ break;
+#endif /* defined(HASKERNFS) */
+
+#if defined(HAS9660FS)
+ case CDFSNODE:
+ if (iso_stat) {
+ dev = iso_dev;
+ devs = 1;
+ }
+ break;
+#endif /* defined(HAS9660FS) */
+
+ case NFSNODE:
+ dev = NVATTR.va_fsid;
+ devs = 1;
+ break;
+
+#if defined(HASPTYFS)
+ case PTYFSNODE:
+ if (v->v_un.vu_specinfo
+ && !kread((KA_T)v->v_un.vu_specinfo, (char *)&si, sizeof(si))) {
+ rdev = si.si_rdev;
+ rdevs = 1;
+ }
+ if (vfs) {
+
+# if defined(HASSTATVFS)
+ dev = (dev_t)vfs->fsid.__fsid_val[0];
+# else /* !defined(HASSTATVFS) */
+ dev = (dev_t)vfs->fsid.val[0];
+# endif /* defined(HASSTATVFS) */
+
+ devs = 1;
+ }
+ break;
+#endif /* defined(HASPTYFS) */
+
+ }
+/*
+ * Obtain the inode number.
+ */
+ switch (nty) {
+
+#if defined(HASMSDOSFS)
+ case DOSNODE:
+ if (d.de_pmp && !kread((KA_T)d.de_pmp, (char *)&pm, sizeof(pm))) {
+ dpb = (u_long)(pm.pm_BytesPerSec / sizeof(struct direntry));
+ if (d.de_Attributes & ATTR_DIRECTORY) {
+ if (d.de_StartCluster == MSDOSFSROOT)
+ nn = (INODETYPE)1;
+ else
+ nn = (INODETYPE)(cntobn(&pm, d.de_StartCluster) * dpb);
+ } else {
+ if (d.de_dirclust == MSDOSFSROOT)
+ nn = (INODETYPE)(roottobn(&pm, 0) * dpb);
+ else
+ nn = (INODETYPE)(cntobn(&pm, d.de_dirclust) * dpb);
+ nn += (INODETYPE)(d.de_diroffset / sizeof(struct direntry));
+ }
+ Lf->inode = nn;
+ Lf->inp_ty = 1;
+ }
+ break;
+#endif /* defined(HASMSDOSFS) */
+
+#if defined(HASEXT2FS)
+ case EXT2NODE:
+#endif /* defined(HASEXT2FS) */
+
+ case INODE:
+ Lf->inode = (INODETYPE)i.i_number;
+ Lf->inp_ty = 1;
+ break;
+
+#if defined(HASKERNFS)
+ case KERNFSNODE:
+ if (ksbs) {
+ Lf->inode = (INODETYPE)ksb.st_ino;
+ Lf->inp_ty = 1;
+ }
+ break;
+#endif /* defined(HASKERNFS) */
+
+#if defined(HAS9660FS)
+ case CDFSNODE:
+ if (iso_stat) {
+ Lf->inode = iso_ino;
+ Lf->inp_ty = 1;
+ }
+ break;
+#endif /* defined(HAS9660FS) */
+
+ case NFSNODE:
+ Lf->inode = (INODETYPE)NVATTR.va_fileid;
+ Lf->inp_ty = 1;
+ break;
+
+#if defined(HASPROCFS)
+ case PFSNODE:
+ Lf->inode = (INODETYPE)p.pfs_fileno;
+ Lf->inp_ty = 1;
+ break;
+#endif /* defined(HASPROCFS) */
+
+#if defined(HASPTYFS)
+ case PTYFSNODE:
+ if (pt.ptyfs_type == PTYFSptc) {
+ if (pt.ptyfs_fileno > 0x3fffffff)
+ Lf->inode = (INODETYPE)(pt.ptyfs_fileno & 0x3fffffff);
+ else
+ Lf->inode = (INODETYPE)(pt.ptyfs_fileno - 1);
+ } else
+ Lf->inode = (INODETYPE)pt.ptyfs_fileno;
+ Lf->inp_ty = 1;
+ break;
+#endif /* defined(HASPTYFS) */
+
+ }
+
+/*
+ * Obtain the file size.
+ */
+ if (Foffset)
+ Lf->off_def = 1;
+ else {
+ switch (Ntype) {
+
+#if defined(HAS9660FS)
+ case N_CDFS:
+ if (iso_stat) {
+ Lf->sz = (SZOFFTYPE)iso_sz;
+ Lf->sz_def = 1;
+ }
+ break;
+#endif /* defined(HAS9660FS) */
+
+ case N_FIFO:
+ if (!Fsize)
+ Lf->off_def = 1;
+ break;
+
+#if defined(HASKERNFS)
+ case N_KERN:
+ if (ksbs) {
+ Lf->sz = (SZOFFTYPE)ksb.st_size;
+ Lf->sz_def = 1;
+ }
+ break;
+#endif /* defined(HASKERNFS) */
+
+ case N_NFS:
+ if (nty == NFSNODE) {
+ Lf->sz = (SZOFFTYPE)NVATTR.va_size;
+ Lf->sz_def = 1;
+ }
+ break;
+
+#if defined(HASPROCFS)
+ case N_PROC:
+ if (nty == PFSNODE) {
+ switch (p.pfs_type) {
+ case Proot:
+ case Pproc:
+ Lf->sz = (SZOFFTYPE)DEV_BSIZE;
+ Lf->sz_def = 1;
+ break;
+ case Pcurproc:
+ Lf->sz = (SZOFFTYPE)DEV_BSIZE;
+ Lf->sz_def = 1;
+ break;
+ case Pmem:
+ (void) getmemsz(p.pfs_pid);
+ break;
+ case Pregs:
+ Lf->sz = (SZOFFTYPE)sizeof(struct reg);
+ Lf->sz_def = 1;
+ break;
+
+# if defined(FP_QSIZE)
+ case Pfpregs:
+ Lf->sz = (SZOFFTYPE)sizeof(struct fpreg);
+ Lf->sz_def = 1;
+ break;
+# endif /* defined(FP_QSIZE) */
+
+ }
+ }
+ break;
+#endif /* defined(HASPROCFS) */
+
+ case N_REGLR:
+ if (type == VREG || type == VDIR) {
+ switch (nty) {
+ case INODE:
+
+#if defined(HASI_FFS)
+
+ Lf->sz = (SZOFFTYPE)i.i_ffs_size;
+ Lf->sz_def = 1;
+ break;
+#else /* !defined(HASI_FFS) */
+# if defined(HASI_FFS1)
+
+ if (ffs == 1) {
+ if (u1s) {
+ Lf->sz = (SZOFFTYPE)u1.di_size;
+ Lf->sz_def = 1;
+ }
+ } else if (ffs == 2) {
+ if (u2s) {
+ Lf->sz = (SZOFFTYPE)u2.di_size;
+ Lf->sz_def = 1;
+ }
+ }
+ break;
+# else /* !defined(HASI_FFS1) */
+ Lf->sz = (SZOFFTYPE)i.i_size;
+ Lf->sz_def = 1;
+# endif /* defined(HASI_FFS1) */
+#endif /* defined(HASI_FFS) */
+
+ break;
+
+
+#if defined(HASMSDOSFS)
+ case DOSNODE:
+ Lf->sz = (SZOFFTYPE)d.de_FileSize;
+ Lf->sz_def = 1;
+ break;
+#endif /* defined(HASMSDOSFS) */
+
+ case MFSNODE:
+ Lf->sz = (SZOFFTYPE)m.mfs_size;
+ Lf->sz_def = 1;
+ break;
+
+#if defined(HASEXT2FS)
+ case EXT2NODE:
+# if defined(HASI_E2FS_PTR)
+ if (edp) {
+ Lf->sz = (SZOFFTYPE)edp->e2di_size;
+ Lf->sz_def = 1;
+ }
+# else /* !defined(HASI_E2FS_PTR) */
+ Lf->sz = (SZOFFTYPE)i.i_e2fs_size;
+ Lf->sz_def = 1;
+# endif /* defined(HASI_E2FS_PTR) */
+ break;
+#endif /* defined(HASEXT2FS) */
+
+ }
+ } else if ((type == VCHR || type == VBLK) && !Fsize)
+ Lf->off_def = 1;
+ break;
+ }
+ }
+/*
+ * Record the link count.
+ */
+ if (Fnlink) {
+ switch(Ntype) {
+
+#if defined(HAS9660FS)
+ case N_CDFS:
+ if (iso_stat) {
+ Lf->nlink = iso_nlink;
+ Lf->nlink_def = 1;
+ }
+ break;
+#endif /* defined(HAS9660FS) */
+
+#if defined(HASKERNFS)
+ case N_KERN:
+ if (ksbs) {
+ Lf->nlink = (long)ksb.st_nlink;
+ Lf->nlink_def = 1;
+ }
+ break;
+#endif /* defined(HASKERNFS) */
+
+ case N_NFS:
+ if (nty == NFSNODE) {
+ Lf->nlink = (long)NVATTR.va_nlink;
+ Lf->nlink_def = 1;
+ }
+ break;
+ case N_REGLR:
+ switch (nty) {
+ case INODE:
+
+#if defined(HASEFFNLINK)
+ Lf->nlink = (long)i.HASEFFNLINK;
+#else /* !defined(HASEFFNLINK) */
+# if defined(HASI_FFS)
+ Lf->nlink = (long)i.i_ffs_nlink;
+# else /* !defined(HASI_FFS) */
+# if defined(HASI_FFS1)
+ if (ffs == 1) {
+ if (u1s)
+ Lf->nlink = (long)u1.di_nlink;
+ } else if (ffs == 2) {
+ if (u2s)
+ Lf->nlink = (long)u2.di_nlink;
+ }
+# else /* !defined(HASI_FFS1) */
+
+ Lf->nlink = (long)i.i_nlink;
+# endif /* defined(HASI_FFS1) */
+# endif /* defined(HASI_FFS) */
+#endif /* defined(HASEFFNLINK) */
+
+ Lf->nlink_def = 1;
+ break;
+
+#if defined(HASMSDOSFS)
+ case DOSNODE:
+ Lf->nlink = (long)d.de_refcnt;
+ Lf->nlink_def = 1;
+ break;
+#endif /* defined(HASMSDOSFS) */
+
+#if defined(HASEXT2FS)
+ case EXT2NODE:
+# if defined(HASI_E2FS_PTR)
+ if (edp) {
+ Lf->nlink = (long)edp->e2di_nlink;
+ Lf->nlink_def = 1;
+ }
+# else /* !defined(HASI_E2FS_PTR) */
+ Lf->nlink = (long)i.i_e2fs_nlink;
+ Lf->nlink_def = 1;
+# endif /* defined(HASI_E2FS_PTR) */
+
+ break;
+
+#endif /* defined(HASEXT2FS) */
+
+ }
+ break;
+ }
+ if (Lf->nlink_def && Nlink && (Lf->nlink < Nlink))
+ Lf->sf |= SELNLINK;
+ }
+/*
+ * Record an NFS file selection.
+ */
+ if (Ntype == N_NFS && Fnfs)
+ Lf->sf |= SELNFS;
+
+#if defined(HASNULLFS)
+/*
+ * If there is a saved nullfs vfs pointer, propagate its device number.
+ */
+ if (nvfs) {
+
+# if defined(HASSTATVFS)
+ dev = nvfs->fsid.__fsid_val[0];
+# else /* !defined(HASSTATVFS) */
+ dev = nvfs->fsid.val[0];
+# endif /* defined(HASSTATVFS) */
+
+ devs = 1;
+ }
+#endif /* defined(HASNULLFS) */
+
+/*
+ * Save the file system names.
+ */
+ if (vfs) {
+ Lf->fsdir = vfs->dir;
+ Lf->fsdev = vfs->fsname;
+ }
+/*
+ * Save the device numbers and their states.
+ *
+ * Format the vnode type, and possibly the device name.
+ */
+ Lf->dev = dev;
+ Lf->dev_def = devs;
+ Lf->rdev = rdev;
+ Lf->rdev_def = rdevs;
+ switch (type) {
+ case VNON:
+ ty ="VNON";
+ break;
+ case VREG:
+ ty = "VREG";
+ break;
+ case VDIR:
+ ty = "VDIR";
+ break;
+ case VBLK:
+ ty = "VBLK";
+ Ntype = N_BLK;
+ break;
+ case VCHR:
+ ty = "VCHR";
+ Ntype = N_CHR;
+ break;
+ case VLNK:
+ ty = "VLNK";
+ break;
+
+#if defined(VSOCK)
+ case VSOCK:
+ ty = "SOCK";
+ break;
+#endif /* defined(VSOCK) */
+
+ case VBAD:
+ ty = "VBAD";
+ break;
+ case VFIFO:
+ ty = "FIFO";
+ break;
+ default:
+ (void) snpf(Lf->type, sizeof(Lf->type), "%04o", (type & 0xfff));
+ ty = NULL;
+ }
+ if (ty)
+ (void) snpf(Lf->type, sizeof(Lf->type), "%s", ty);
+ Lf->ntype = Ntype;
+/*
+ * Handle some special cases:
+ *
+ * ioctl(fd, TIOCNOTTY) files;
+ * /kern files
+ * memory node files;
+ * /proc files;
+ * ptyfs files.
+ */
+
+ if (type == VBAD)
+ (void) snpf(Namech, Namechl, "(revoked)");
+ else if (nty == MFSNODE) {
+ Lf->dev_def = Lf->rdev_def = 0;
+ (void) snpf(Namech, Namechl, "%#x", m.mfs_baseoff);
+ enter_dev_ch("memory");
+ }
+
+#if defined(HASPROCFS)
+ else if (nty == PFSNODE) {
+ Lf->dev_def= Lf->rdev_def = 0;
+ ty = NULL;
+ (void) snpf(Namech, Namechl, "/%s", HASPROCFS);
+ switch (p.pfs_type) {
+ case Proot:
+ ty = "PDIR";
+ break;
+ case Pcurproc:
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "/curproc");
+ ty = "PCUR";
+ break;
+ case Pproc:
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "/%d", p.pfs_pid);
+ ty = "PDIR";
+ break;
+ case Pfile:
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "/%d/file", p.pfs_pid);
+ ty = "PFIL";
+ break;
+ case Pmem:
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "/%d/mem", p.pfs_pid);
+ ty = "PMEM";
+ break;
+ case Pregs:
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "/%d/regs", p.pfs_pid);
+ ty = "PREG";
+ break;
+ case Pfpregs:
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "/%d/fpregs", p.pfs_pid);
+ ty = "PFPR";
+ break;
+ case Pctl:
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "/%d/ctl", p.pfs_pid);
+ ty = "PCTL";
+ break;
+ case Pstatus:
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "/%d/status", p.pfs_pid);
+ ty = "PSTA";
+ break;
+ case Pnote:
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "/%d/note", p.pfs_pid);
+ ty = "PNTF";
+ break;
+ case Pnotepg:
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "/%d/notepg", p.pfs_pid);
+ ty = "PGID";
+ break;
+
+# if defined(Pfd)
+ case Pfd:
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "/%d/fd", p.pfs_pid);
+ ty = "PFD";
+ break;
+# endif /* defined(Pfd) */
+
+# if defined(Pmap)
+ case Pmap:
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "/%d/map", p.pfs_pid);
+ ty = "PMAP";
+ break;
+# endif /* defined(Pmap) */
+
+# if defined(Pmaps)
+ case Pmaps:
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "/%d/maps", p.pfs_pid);
+ ty = "PMPS";
+ break;
+# endif /* defined(Pmaps) */
+
+ }
+ if (ty)
+ (void) snpf(Lf->type, sizeof(Lf->type), ty);
+ }
+#endif /* defined(HASPROCFS) */
+
+#if defined(HASPTYFS)
+ else if (nty == PTYFSNODE) {
+ (void) snpf(Namech, Namechl, "%s", Lf->fsdir);
+ Lf->nlink = 1;
+ Lf->nlink_def = 1;
+ switch (pt.ptyfs_type) {
+ case PTYFSpts:
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "/%lu", (unsigned long)pt.ptyfs_pty);
+ break;
+ case PTYFSptc:
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "/%lu (master)",
+ (unsigned long)pt.ptyfs_pty);
+ break;
+ case PTYFSroot:
+ Lf->sz = 512;
+ Lf->sz_def = 1;
+ break;
+ }
+ if (ty)
+ (void) snpf(Lf->type, sizeof(Lf->type), ty);
+ }
+#endif /* defined(HASPTYFS) */
+
+#if defined(HASBLKDEV)
+/*
+ * If this is a VBLK file and it's missing an inode number, try to
+ * supply one.
+ */
+ if ((Lf->inp_ty == 0) && (type == VBLK))
+ find_bl_ino();
+#endif /* defined(HASBLKDEV) */
+
+/*
+ * If this is a VCHR file and it's missing an inode number, try to
+ * supply one.
+ */
+ if ((Lf->inp_ty == 0) && (type == VCHR))
+ find_ch_ino();
+/*
+ * Test for specified file.
+ */
+
+#if defined(HASPROCFS)
+ if (Ntype == N_PROC) {
+ if (Procsrch) {
+ Procfind = 1;
+ Lf->sf |= SELNM;
+ } else if (nty == PFSNODE) {
+ for (pfi = Procfsid; pfi; pfi = pfi->next) {
+ if ((pfi->pid && pfi->pid == p.pfs_pid)
+
+# if defined(HASPINODEN)
+ || ((Lf->inp_ty == 1) && (pfi->inode == Lf->inode))
+# endif /* defined(HASPINODEN) */
+
+ ) {
+ pfi->f = 1;
+ if (Namech[0] && pfi->nm)
+ (void) snpf(Namech, Namechl, "%s", pfi->nm);
+ Lf->sf |= SELNM;
+ break;
+ }
+ }
+ }
+ } else
+#endif /* defined(HASPROCFS) */
+
+ {
+ if (Namech[0]) {
+ enter_nm(Namech);
+ ns = 1;
+ } else
+ ns = 0;
+ if (Sfile && is_file_named((char *)NULL,
+ ((type == VCHR) || (type == VBLK)) ? 1
+ : 0))
+ {
+ Lf->sf |= SELNM;
+ }
+ if (ns)
+ Namech[0] = '\0';
+ }
+/*
+ * Enter name characters.
+ */
+ if (Namech[0])
+ enter_nm(Namech);
+}
+
+
+#if defined(HAS_SYS_PIPEH)
+/*
+ * process_pipe() - process a file structure whose type is DTYPE_PIPE
+ */
+
+void
+process_pipe(pa)
+ KA_T pa; /* pipe structure kernel address */
+{
+ char *ep;
+ struct pipe p;
+ size_t sz;
+
+ if (!pa || kread((KA_T)pa, (char *)&p, sizeof(p))) {
+ (void) snpf(Namech, Namechl,
+ "can't read DTYPE_PIPE pipe struct: %#s",
+ print_kptr(pa, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ (void) snpf(Lf->type, sizeof(Lf->type), "PIPE");
+ enter_dev_ch(print_kptr(pa, (char *)NULL, 0));
+ if (Foffset)
+ Lf->off_def = 1;
+ else {
+ Lf->sz = (SZOFFTYPE)p.pipe_buffer.size;
+ Lf->sz_def = 1;
+ }
+ if (p.pipe_peer)
+ (void) snpf(Namech, Namechl, "->%s",
+ print_kptr((KA_T)p.pipe_peer, (char *)NULL, 0));
+ else
+ Namech[0] = '\0';
+ if (p.pipe_buffer.cnt) {
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, ", cnt=%d", p.pipe_buffer.cnt);
+ }
+ if (p.pipe_buffer.in) {
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, ", in=%d", p.pipe_buffer.in);
+ }
+ if (p.pipe_buffer.out) {
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, ", out=%d", p.pipe_buffer.out);
+ }
+/*
+ * Enter name characters.
+ */
+ if (Namech[0])
+ enter_nm(Namech);
+}
+#endif /* defined(HAS_SYS_PIPEH) */
diff --git a/dialects/n+obsd/dnode1.c b/dialects/n+obsd/dnode1.c
new file mode 100644
index 0000000..55a1c30
--- /dev/null
+++ b/dialects/n+obsd/dnode1.c
@@ -0,0 +1,95 @@
+/*
+ * dnode1.c - NetBSD and OpenBSD node functions for lsof
+ *
+ * This module must be separate to keep separate the multiple kernel inode
+ * structure definitions.
+ */
+
+
+/*
+ * Copyright 1995 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dnode1.c,v 1.8 2005/08/08 19:53:24 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+#if defined(HAS9660FS)
+/*
+ * Undo some conflicting node header file definitions.
+ */
+
+#undef doff_t
+#undef i_dev
+#undef i_devvp
+#undef i_number
+#undef IN_ACCESS
+#undef IN_LOCKED
+#undef i_size
+#undef IN_WANTED
+
+
+/*
+ * At last, #include the desired header files.
+ */
+
+# if HAS9660FS==1
+#include <isofs/cd9660/iso.h>
+#include <isofs/cd9660/cd9660_node.h>
+# else /* HAS9660FS!=1 */
+#include <fs/cd9660/iso.h>
+#include <fs/cd9660/cd9660_node.h>
+# endif /* HAS9660FS==1 */
+
+
+/*
+ * read_iso_node() -- read CD 9660 iso_node
+ */
+
+int
+read_iso_node(v, d, ino, nl, sz)
+ struct vnode *v; /* containing vnode */
+ dev_t *d; /* returned device number */
+ INODETYPE *ino; /* returned inode number */
+ long *nl; /* returned link count */
+ SZOFFTYPE *sz; /* returned size */
+{
+ struct iso_node i;
+
+ if (!v->v_data
+ || kread((KA_T)v->v_data, (char *)&i, sizeof(i)))
+ return(1);
+ *d = i.i_dev;
+ *ino = (INODETYPE)i.i_number;
+ *nl = i.inode.iso_links;
+ *sz = (SZOFFTYPE)i.i_size;
+ return(0);
+}
+#endif /* defined(HAS9660FS) */
diff --git a/dialects/n+obsd/dproc.c b/dialects/n+obsd/dproc.c
new file mode 100644
index 0000000..2cf532b
--- /dev/null
+++ b/dialects/n+obsd/dproc.c
@@ -0,0 +1,584 @@
+/*
+ * dproc.c - NetBSD and OpenBSD process access functions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dproc.c,v 1.17 2005/05/11 12:53:54 abe Exp $";
+#endif
+
+#include "lsof.h"
+
+
+_PROTOTYPE(static void enter_vn_text,(KA_T va, int *n));
+_PROTOTYPE(static void get_kernel_access,(void));
+_PROTOTYPE(static void process_text,(KA_T vm));
+
+
+/*
+ * Local static values
+ */
+
+static MALLOC_S Nv = 0; /* allocated Vp[] entries */
+static KA_T *Vp = NULL; /* vnode address cache */
+
+
+/*
+ * ckkv - check kernel version
+ */
+
+void
+ckkv(d, er, ev, ea)
+ char *d; /* dialect */
+ char *er; /* expected release */
+ char *ev; /* expected version */
+ char *ea; /* expected architecture */
+{
+
+#if defined(HASKERNIDCK)
+ size_t l;
+ int m[2];
+ char v[64];
+
+ if (Fwarn)
+ return;
+/*
+ * Read kernel version.
+ */
+ m[0] = CTL_KERN;
+ m[1] = KERN_OSRELEASE;
+ l = sizeof(v);
+ if (sysctl(m, 2, v, &l, NULL, 0) < 0) {
+ (void) fprintf(stderr, "%s: CTL_KERN, KERN_OSRELEASE: %s\n",
+ Pn, strerror(errno));
+ Exit(1);
+ }
+/*
+ * Warn if the actual and expected releases don't match.
+ */
+ if (!er || strcmp(v, er))
+ (void) fprintf(stderr,
+ "%s: WARNING: compiled for %s release %s; this is %s.\n",
+ Pn, d, er ? er : "UNKNOWN", v);
+#endif /* defined(HASKERNIDCK) */
+
+}
+
+
+/*
+ * enter_vn_text() - enter a vnode text reference
+ */
+
+static void
+enter_vn_text(va, n)
+ KA_T va; /* vnode address */
+ int *n; /* Vp[] entries in use */
+{
+ int i;
+/*
+ * Ignore the request if the vnode has already been entered.
+ */
+ for (i = 0; i < *n; i++) {
+ if (va == Vp[i])
+ return;
+ }
+/*
+ * Save the text file information.
+ */
+ alloc_lfile(" txt", -1);
+ Cfp = (struct file *)NULL;
+ process_node((KA_T)va);
+ if (Lf->sf)
+ link_lfile();
+ if (i >= Nv) {
+
+ /*
+ * Allocate space for remembering the vnode.
+ */
+ Nv += 10;
+ if (!Vp)
+ Vp=(KA_T *)malloc((MALLOC_S)(sizeof(struct vnode *) * 10));
+ else
+ Vp=(KA_T *)realloc((MALLOC_P *)Vp,(MALLOC_S)(Nv*sizeof(KA_T)));
+ if (!Vp) {
+ (void) fprintf(stderr, "%s: no txt ptr space, PID %d\n",
+ Pn, Lp->pid);
+ Exit(1);
+ }
+ }
+/*
+ * Remember the vnode.
+ */
+ Vp[*n] = va;
+ (*n)++;
+}
+
+
+/*
+ * gather_proc_info() -- gather process information
+ */
+
+void
+gather_proc_info()
+{
+ struct filedesc fd;
+ int i, nf;
+ MALLOC_S nb;
+ static struct file **ofb = NULL;
+ static int ofbb = 0;
+ short pss, sf;
+ int px;
+ uid_t uid;
+
+#if defined(HASCWDINFO)
+ struct cwdinfo cw;
+#define CDIR cw.cwdi_cdir
+#define RDIR cw.cwdi_rdir
+#else /* !defined(HASCWDINFO) */
+#define CDIR fd.fd_cdir
+#define RDIR fd.fd_rdir
+#endif /* defined(HASCWDINFO) */
+
+#if defined(HASFSTRUCT)
+ static char *pof = (char *)NULL;
+ static int pofb = 0;
+#endif /* defined(HASFSTRUCT) */
+
+#if defined(HASKVMGETPROC2)
+ struct kinfo_proc2 *p;
+#define KVMPROCSZ2 sizeof(struct kinfo_proc2)
+#else /* !defined(HASKVMGETPROC2) */
+ struct kinfo_proc *p;
+#endif /* defined(HASKVMGETPROC2) */
+
+/*
+ * Read the process table.
+ */
+
+#if defined(HASKVMGETPROC2)
+ P = kvm_getproc2(Kd, KERN_PROC_ALL, 0, KVMPROCSZ2, &Np);
+#else /* !defined(HASKVMGETPROC2) */
+ P = kvm_getprocs(Kd, KERN_PROC_ALL, 0, &Np);
+#endif /* defined(HASKVMGETPROC2) &/
+
+ if (!P) {
+ (void) fprintf(stderr, "%s: can't read process table: %s\n",
+ Pn, kvm_geterr(Kd));
+ Exit(1);
+ }
+/*
+ * Examine proc structures and their associated information.
+ */
+
+ for (p = P, px = 0; px < Np; px++, p++) {
+ if (p->P_STAT == 0 || p->P_STAT == SZOMB)
+ continue;
+ /*
+ * Read process information, process group structure (if
+ * necessary), and User ID (if necessary).
+ *
+ * See if process is excluded.
+ *
+ * Read file structure pointers.
+ */
+ uid = p->P_UID;
+ if (is_proc_excl((int)p->P_PID, (int)p->P_PGID, (UID_ARG)uid,
+ &pss, &sf))
+ {
+ continue;
+ }
+ if (!p->P_FD
+ || kread((KA_T)p->P_FD, (char *)&fd, sizeof(fd)))
+ continue;
+ if (!fd.fd_refcnt || fd.fd_lastfile > fd.fd_nfiles)
+ continue;
+
+#if defined(HASCWDINFO)
+ if (!p->P_CWDI
+ || kread((KA_T)p->P_CWDI, (char *)&cw, sizeof(cw)))
+ CDIR = RDIR = (struct vnode *)NULL;
+#endif /* defined(HASCWDINFO) */
+
+ /*
+ * Allocate a local process structure.
+ */
+ if (is_cmd_excl(p->P_COMM, &pss, &sf))
+ continue;
+ alloc_lproc((int)p->P_PID, (int)p->P_PGID, (int)p->P_PPID,
+ (UID_ARG)uid, p->P_COMM, (int)pss, (int)sf);
+ Plf = (struct lfile *)NULL;
+ Kpa = (KA_T)p->P_ADDR;
+ /*
+ * Save current working directory information.
+ */
+ if (CDIR) {
+ alloc_lfile(CWD, -1);
+ Cfp = (struct file *)NULL;
+ process_node((KA_T)CDIR);
+ if (Lf->sf)
+ link_lfile();
+ }
+ /*
+ * Save root directory information.
+ */
+ if (RDIR) {
+ alloc_lfile(RTD, -1);
+ Cfp = (struct file *)NULL;
+ process_node((KA_T)RDIR);
+ if (Lf->sf)
+ link_lfile();
+ }
+
+#if defined(OPENBSDV) && OPENBSDV>=3020
+ /*
+ * Save trace node information.
+ */
+ if (p->P_TRACEP) {
+ alloc_lfile("tr", -1);
+ Cfp = (struct file *)NULL;
+ process_node((KA_T)p->P_TRACEP);
+ if (Lf->sf)
+ link_lfile();
+ }
+#endif /* defined(OPENBSDV) && OPENBSDV>=3020 */
+
+ /*
+ * Save information on the text file.
+ */
+ if (p->P_VMSPACE)
+ process_text((KA_T)p->P_VMSPACE);
+ /*
+ * Read open file structure pointers.
+ */
+ if (!fd.fd_ofiles || (nf = fd.fd_nfiles) <= 0)
+ continue;
+ nb = (MALLOC_S)(sizeof(struct file *) * nf);
+ if (nb > ofbb) {
+ if (!ofb)
+ ofb = (struct file **)malloc(nb);
+ else
+ ofb = (struct file **)realloc((MALLOC_P *)ofb, nb);
+ if (!ofb) {
+ (void) fprintf(stderr, "%s: PID %d, no file * space\n",
+ Pn, p->P_PID);
+ Exit(1);
+ }
+ ofbb = nb;
+ }
+ if (kread((KA_T)fd.fd_ofiles, (char *)ofb, nb))
+ continue;
+
+#if defined(HASFSTRUCT)
+ if (Fsv & FSV_FG) {
+ nb = (MALLOC_S)(sizeof(char) * nf);
+ if (nb > pofb) {
+ if (!pof)
+ pof = (char *)malloc(nb);
+ else
+ pof = (char *)realloc((MALLOC_P *)pof, nb);
+ if (!pof) {
+ (void) fprintf(stderr,
+ "%s: PID %d, no file flag space\n", Pn, p->P_PID);
+ Exit(1);
+ }
+ pofb = nb;
+ }
+ if (!fd.fd_ofileflags || kread((KA_T)fd.fd_ofileflags, pof, nb))
+ zeromem(pof, nb);
+ }
+#endif /* defined(HASFSTRUCT) */
+
+ /*
+ * Save information on file descriptors.
+ */
+ for (i = 0; i < nf; i++) {
+ if (ofb[i]) {
+ alloc_lfile(NULL, i);
+ process_file((KA_T)(Cfp = ofb[i]));
+ if (Lf->sf) {
+
+#if defined(HASFSTRUCT)
+ if (Fsv & FSV_FG)
+ Lf->pof = (long)pof[i];
+#endif /* defined(HASFSTRUCT) */
+
+ link_lfile();
+ }
+ }
+ }
+ /*
+ * Examine results.
+ */
+ if (examine_lproc())
+ return;
+ }
+}
+
+
+/*
+ * get_kernel_access() - get access to kernel memory
+ */
+
+static void
+get_kernel_access()
+{
+ KA_T v;
+/*
+ * Check kernel version.
+ */
+ (void) ckkv(
+
+#if defined(NETBSDV)
+ "NetBSD",
+#else /* !defined(NETBSDV) */
+# if defined(OPENBSDV)
+ "OpenBSD",
+# endif /* defined(OPENBSDV) */
+#endif /* defined(NETBSDV) */
+
+ LSOF_VSTR, (char *)NULL, (char *)NULL);
+/*
+ * Set name list file path.
+ */
+ if (!Nmlst)
+
+#if defined(N_UNIX)
+ Nmlst = N_UNIX;
+#else /* !defined(N_UNIX) */
+ {
+ if (!(Nmlst = get_nlist_path(1))) {
+ (void) fprintf(stderr,
+ "%s: can't get kernel name list path\n", Pn);
+ Exit(1);
+ }
+ }
+#endif /* defined(N_UNIX) */
+
+#if defined(WILLDROPGID)
+/*
+ * If kernel memory isn't coming from KMEM, drop setgid permission
+ * before attempting to open the (Memory) file.
+ */
+ if (Memory)
+ (void) dropgid();
+#else /* !defined(WILLDROPGID) */
+/*
+ * See if the non-KMEM memory and name list files are readable.
+ */
+ if ((Memory && !is_readable(Memory, 1))
+ || (Nmlst && !is_readable(Nmlst, 1)))
+ Exit(1);
+#endif /* defined(WILLDROPGID) */
+
+/*
+ * Open kernel memory access.
+ */
+ if ((Kd = kvm_openfiles(Nmlst, Memory, NULL, O_RDONLY, NULL)) == NULL) {
+ (void) fprintf(stderr,
+ "%s: kvm_openfiles(execfile=%s, corefile=%s): %s\n",
+ Pn, Nmlst,
+ Memory ? Memory :
+
+#if defined(_PATH_MEM)
+ _PATH_MEM,
+#else /* !defined(_PATH_MEM) */
+ "default",
+#endif /* defined(_PATH_MEM) */
+
+ strerror(errno));
+ Exit(1);
+ }
+ (void) build_Nl(Drive_Nl);
+ if (kvm_nlist(Kd, Nl) < 0) {
+ (void) fprintf(stderr, "%s: can't read namelist from %s\n",
+ Pn, Nmlst);
+ Exit(1);
+ }
+
+#if defined(WILLDROPGID)
+/*
+ * Drop setgid permission, if necessary.
+ */
+ if (!Memory)
+ (void) dropgid();
+#endif /* defined(WILLDROPGID) */
+
+/*
+ * Read the kernel's page shift amount, if possible.
+ */
+ if (get_Nl_value("pgshift", Drive_Nl, &v) < 0 || !v
+ || kread((KA_T)v, (char *)&pgshift, sizeof(pgshift)))
+ pgshift = 0;
+}
+
+
+#if !defined(N_UNIX)
+/*
+ * get_nlist_path() - get kernel name list path
+ */
+
+char *
+get_nlist_path(ap)
+ int ap; /* on success, return an allocated path
+ * string pointer if 1; return a
+ * constant character pointer if 0;
+ * return NULL if failure */
+{
+ const char *bf;
+ static char *bfc;
+ MALLOC_S bfl;
+/*
+ * Get bootfile name.
+ */
+ if ((bf = getbootfile())) {
+ if (!ap)
+ return("");
+ bfl = (MALLOC_S)(strlen(bf) + 1);
+ if (!(bfc = (char *)malloc(bfl))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d bytes for boot file path: %s\n",
+ Pn, bfl, bf);
+ Exit(1);
+ }
+ (void) snpf(bfc, bfl, "%s", bf);
+ return(bfc);
+ }
+ return((char *)NULL);
+}
+#endif /* !defined(N_UNIX) */
+
+
+/*
+ * initialize() - perform all initialization
+ */
+
+void
+initialize()
+{
+ get_kernel_access();
+}
+
+
+/*
+ * kread() - read from kernel memory
+ */
+
+int
+kread(addr, buf, len)
+ KA_T addr; /* kernel memory address */
+ char *buf; /* buffer to receive data */
+ READLEN_T len; /* length to read */
+{
+ int br;
+
+ br = kvm_read(Kd, (u_long)addr, buf, len);
+ return((br == len) ? 0 : 1);
+}
+
+
+/*
+ * process_text() - process text information
+ */
+void
+process_text(vm)
+ KA_T vm; /* kernel vm space pointer */
+{
+ int i, j;
+ KA_T ka;
+ int n = 0;
+ struct vm_map_entry vmme, *e;
+ struct vmspace vmsp;
+
+#if !defined(UVM)
+ struct pager_struct pg;
+ struct vm_object vmo;
+#endif /* !defined(UVM) */
+
+/*
+ * Read the vmspace structure for the process.
+ */
+ if (kread(vm, (char *)&vmsp, sizeof(vmsp)))
+ return;
+/*
+ * Read the vm_map structure. Search its vm_map_entry structure list.
+ */
+
+#if !defined(UVM)
+ if (!vmsp.vm_map.is_main_map)
+ return;
+#endif /* !defined(UVM) */
+
+ for (i = 0; i < vmsp.vm_map.nentries; i++) {
+
+ /*
+ * Read the next vm_map_entry.
+ */
+ if (!i)
+ e = &vmsp.vm_map.header;
+ else {
+ if (!(ka = (KA_T)e->next))
+ return;
+ e = &vmme;
+ if (kread(ka, (char *)e, sizeof(vmme)))
+ return;
+ }
+
+#if defined(UVM)
+ /*
+ * Process the uvm_obj pointer of a UVM map entry with a UVM_ET_OBJ
+ * type as a vnode pointer.
+ */
+ if ((e->etype > UVM_ET_OBJ) && e->object.uvm_obj)
+ (void) enter_vn_text((KA_T)e->object.uvm_obj, &n);
+#else /* !defined(UVM) */
+ /*
+ * Read the map entry's object and the object's shadow.
+ * Look for a PG_VNODE pager handle.
+ */
+ if (e->is_a_map || e->is_sub_map)
+ continue;
+ for (j = 0, ka = (KA_T)e->object.vm_object;
+ j < 2 && ka;
+ j++, ka = (KA_T)vmo.shadow)
+ {
+ if (kread(ka, (char *)&vmo, sizeof(vmo)))
+ break;
+ if (!(ka = (KA_T)vmo.pager)
+ || kread(ka, (char *)&pg, sizeof(pg)))
+ continue;
+ if (!pg.pg_handle || pg.pg_type != PG_VNODE)
+ continue;
+ (void) enter_vn_text((KA_T)pg.pg_handle, &n);
+ }
+#endif /* defined(UVM) */
+
+ }
+}
diff --git a/dialects/n+obsd/dproto.h b/dialects/n+obsd/dproto.h
new file mode 100644
index 0000000..d94627f
--- /dev/null
+++ b/dialects/n+obsd/dproto.h
@@ -0,0 +1,55 @@
+/*
+ * dproto.h - NetBSD and OpenBSD function prototypes for lsof
+ *
+ * The _PROTOTYPE macro is defined in the common proto.h.
+ */
+
+
+/*
+ * Copyright 1994 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.
+ */
+
+
+/*
+ * $Id: dproto.h,v 1.11 2005/08/08 19:53:24 abe Exp $
+ */
+
+
+#if !defined(N_UNIX)
+_PROTOTYPE(extern char *get_nlist_path,(int ap));
+#endif /* !defined(N_UNIX) */
+
+_PROTOTYPE(extern int is_file_named,(char *p, int cd));
+_PROTOTYPE(extern struct l_vfs *readvfs,(KA_T vm));
+
+#if defined(HAS_SYS_PIPE_H)
+_PROTOTYPE(extern void process_pipe,(KA_T pa));
+#endif /* defined(HAS_SYS_PIPEH) */
+
+#if defined(HAS9660FS)
+_PROTOTYPE(extern int read_iso_node,(struct vnode *v, dev_t *d, INODETYPE *ino, long *nl, SZOFFTYPE *sz));
+#endif /* defined(HAS9660FS) */
+
+_PROTOTYPE(extern void process_socket,(KA_T sa));
diff --git a/dialects/n+obsd/dsock.c b/dialects/n+obsd/dsock.c
new file mode 100644
index 0000000..0e10971
--- /dev/null
+++ b/dialects/n+obsd/dsock.c
@@ -0,0 +1,425 @@
+/*
+ * dsock.c - NetBSD and OpenBSD socket processing functions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dsock.c,v 1.25 2005/08/08 19:53:24 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+#if defined(HASIPv6)
+
+/*
+ * IPv6_2_IPv4() -- macro to define the address of an IPv4 address contained
+ * in an IPv6 address
+ */
+
+#define IPv6_2_IPv4(v6) (((uint8_t *)((struct in6_addr *)v6)->s6_addr)+12)
+#endif /* defined(HASIPv6) */
+
+
+/*
+ * process_socket() - process socket
+ */
+
+void
+process_socket(sa)
+ KA_T sa; /* socket address in kernel */
+{
+ struct domain d;
+ unsigned char *fa = (unsigned char *)NULL;
+ int fam;
+ int fp, lp;
+ struct inpcb inp;
+ unsigned char *la = (unsigned char *)NULL;
+ struct protosw p;
+ struct socket s;
+ struct tcpcb t;
+ KA_T ta = (KA_T)NULL;
+ struct unpcb uc, unp;
+ struct sockaddr_un *ua = NULL;
+ struct sockaddr_un un;
+
+#if defined(HASIPv6) && defined(NETBSDV) && !defined(HASINRIAIPv6)
+ struct in6pcb in6p;
+#endif /* defined(HASIPv6) && defined(NETBSDV) && !defined(HASINRIAIPv6) */
+
+#define UNPADDR_IN_MBUF
+
+#if defined(NETBSDV)
+# if NETBSDV>=1004000
+#undef UNPADDR_IN_MBUF
+# endif /* NETBSDV>=1004000 */
+#endif /* defined(NETBSDV) */
+
+#if defined(UNPADDR_IN_MBUF)
+ struct mbuf mb;
+#endif /* defined(UNPADDR_IN_MBUF) */
+
+ (void) snpf(Lf->type, sizeof(Lf->type), "sock");
+ Lf->inp_ty = 2;
+/*
+ * Read the socket, protocol, and domain structures.
+ */
+ if (!sa) {
+ enter_nm("no socket address");
+ return;
+ }
+ if (kread(sa, (char *) &s, sizeof(s))) {
+ (void) snpf(Namech, Namechl, "can't read socket struct from %s",
+ print_kptr(sa, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ if (!s.so_type) {
+ enter_nm("no socket type");
+ return;
+ }
+ if (!s.so_proto
+ || kread((KA_T)s.so_proto, (char *)&p, sizeof(p))) {
+ (void) snpf(Namech, Namechl, "can't read protocol switch from %s",
+ print_kptr((KA_T)s.so_proto, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ if (!p.pr_domain
+ || kread((KA_T)p.pr_domain, (char *)&d, sizeof(d))) {
+ (void) snpf(Namech, Namechl, "can't read domain struct from %s",
+ print_kptr((KA_T)p.pr_domain, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+/*
+ * Save size information.
+ */
+ if (Fsize) {
+ if (Lf->access == 'r')
+ Lf->sz = (SZOFFTYPE)s.so_rcv.sb_cc;
+ else if (Lf->access == 'w')
+ Lf->sz = (SZOFFTYPE)s.so_snd.sb_cc;
+ else
+ Lf->sz = (SZOFFTYPE)(s.so_rcv.sb_cc + s.so_snd.sb_cc);
+ Lf->sz_def = 1;
+ } else
+ Lf->off_def = 1;
+
+#if defined(HASTCPTPIQ)
+ Lf->lts.rq = s.so_rcv.sb_cc;
+ Lf->lts.sq = s.so_snd.sb_cc;
+ Lf->lts.rqs = Lf->lts.sqs = 1;
+#endif /* defined(HASTCPTPIQ) */
+
+#if defined(HASSOOPT)
+ Lf->lts.ltm = (unsigned int)s.so_linger;
+ Lf->lts.opt = (unsigned int)s.so_options;
+ Lf->lts.pqlen = (unsigned int)s.so_q0len;
+ Lf->lts.qlen = (unsigned int)s.so_qlen;
+ Lf->lts.qlim = (unsigned int)s.so_qlimit;
+ Lf->lts.rbsz = (unsigned long)s.so_rcv.sb_mbmax;
+ Lf->lts.sbsz = (unsigned long)s.so_snd.sb_mbmax;
+ Lf->lts.pqlens = Lf->lts.qlens = Lf->lts.qlims = Lf->lts.rbszs
+ = Lf->lts.sbszs = (unsigned char)1;
+#endif /* defined(HASSOOPT) */
+
+#if defined(HASSOSTATE)
+ Lf->lts.ss = (unsigned int)s.so_state;
+#endif /* defined(HASSOSTATE) */
+
+/*
+ * Process socket by the associated domain family.
+ */
+ switch ((fam = d.dom_family)) {
+/*
+ * Process an Internet domain socket.
+ */
+ case AF_INET:
+
+#if defined(HASIPv6)
+ case AF_INET6:
+#endif /* defined(HASIPv6) */
+
+ if (Fnet) {
+ if (!FnetTy
+ || ((FnetTy == 4) && (fam == AF_INET))
+
+#if defined(HASIPv6)
+ || ((FnetTy == 6) && (fam == AF_INET6))
+#endif /* defined(HASIPv6) */
+ )
+
+ Lf->sf |= SELNET;
+ }
+ printiproto(p.pr_protocol);
+
+#if defined(HASIPv6)
+ (void) snpf(Lf->type, sizeof(Lf->type),
+ (fam == AF_INET) ? "IPv4" : "IPv6");
+#else /* !defined(HASIPv6) */
+ (void) snpf(Lf->type, sizeof(Lf->type), "inet");
+#endif /* defined(HASIPv6) */
+
+#if defined(HASIPv6) && defined(NETBSDV) && !defined(HASINRIAIPv6)
+ if (fam == AF_INET6) {
+
+ /*
+ * Read IPv6 protocol control block.
+ */
+ if (!s.so_pcb
+ || kread((KA_T)s.so_pcb, (char *)&in6p, sizeof(in6p))) {
+ (void) snpf(Namech, Namechl, "can't read in6pcb at %s",
+ print_kptr((KA_T)s.so_pcb, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ /*
+ * Save IPv6 address information.
+ */
+ enter_dev_ch(print_kptr((KA_T)(in6p.in6p_ppcb ? in6p.in6p_ppcb
+ : s.so_pcb),
+ (char *)NULL, 0));
+ if (p.pr_protocol == IPPROTO_TCP)
+ ta = (KA_T)in6p.in6p_ppcb;
+ la = (unsigned char *)&in6p.in6p_laddr;
+ lp = (int)ntohs(in6p.in6p_lport);
+ if (!IN6_IS_ADDR_UNSPECIFIED(&in6p.in6p_faddr)
+ || in6p.in6p_fport)
+ {
+ fa = (unsigned char *)&in6p.in6p_faddr;
+ fp = (int)ntohs(in6p.in6p_fport);
+ }
+ } else
+#endif /* defined(HASIPv6) && defined(NETBSDV) && !defined(HASINRIAIPv6) */
+
+ {
+
+ /*
+ * Read IPv4 or IPv6 (OpenBSD) protocol control block.
+ */
+ if (!s.so_pcb
+ || kread((KA_T)s.so_pcb, (char *)&inp, sizeof(inp))) {
+ if (!s.so_pcb) {
+ (void) snpf(Namech, Namechl, "no PCB%s%s",
+ (s.so_state & SS_CANTSENDMORE) ? ", CANTSENDMORE"
+ : "",
+ (s.so_state & SS_CANTRCVMORE) ? ", CANTRCVMORE"
+ : "");
+ } else {
+ (void) snpf(Namech, Namechl, "can't read inpcb at %s",
+ print_kptr((KA_T)s.so_pcb, (char *)NULL, 0));
+ }
+ enter_nm(Namech);
+ return;
+ }
+ enter_dev_ch(print_kptr((KA_T)(inp.inp_ppcb ? inp.inp_ppcb
+ : s.so_pcb),
+ (char *)NULL, 0));
+ if (p.pr_protocol == IPPROTO_TCP)
+ ta = (KA_T)inp.inp_ppcb;
+ lp = (int)ntohs(inp.inp_lport);
+ if (fam == AF_INET) {
+
+ /*
+ * Save IPv4 address information.
+ */
+ la = (unsigned char *)&inp.inp_laddr;
+ if (inp.inp_faddr.s_addr != INADDR_ANY || inp.inp_fport) {
+ fa = (unsigned char *)&inp.inp_faddr;
+ fp = (int)ntohs(inp.inp_fport);
+ }
+ }
+
+#if defined(HASIPv6) && (defined(OPENBSDV) || defined(HASINRIAIPv6))
+ else {
+ la = (unsigned char *)&inp.inp_laddr6;
+ if (!IN6_IS_ADDR_UNSPECIFIED(&inp.inp_faddr6)
+ || inp.inp_fport)
+ {
+ fa = (unsigned char *)&inp.inp_faddr6;
+ fp = (int)ntohs(inp.inp_fport);
+ }
+ }
+#endif /* defined(HASIPv6) && (defined(OPENBSDV) || defined(HASINRIAIPv6)) */
+
+ }
+
+#if defined(HASIPv6)
+ if ((fam == AF_INET6)
+ && ((la && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)la))
+ || ((fa && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)fa))))) {
+
+ /*
+ * Adjust for IPv4 addresses mapped in IPv6 addresses.
+ */
+ if (la)
+ la = (unsigned char *)IPv6_2_IPv4(la);
+ if (fa)
+ fa = (unsigned char *)IPv6_2_IPv4(fa);
+ fam = AF_INET;
+ }
+#endif /* defined(HASIPv6) */
+
+ /*
+ * Enter local and remote addresses by address family.
+ */
+ if (fa || la)
+ (void) ent_inaddr(la, lp, fa, fp, fam);
+ /*
+ * If the protocol is TCP, and its address is available, read the
+ * TCP protocol control block and save its state.
+ */
+ if (ta && !kread(ta, (char *)&t, sizeof(t))) {
+ Lf->lts.type = 0;
+ Lf->lts.state.i = (int)t.t_state;
+
+#if defined(HASTCPOPT)
+# if defined(OPENBSDV)
+ Lf->lts.mss = (unsigned long)t.t_maxseg;
+# else /* !defined(OPENSDV) */
+ Lf->lts.mss = (unsigned long)t.t_ourmss;
+# endif /* defined(OPENSDV) */
+
+ Lf->lts.msss = (unsigned char)1;
+ Lf->lts.topt = (unsigned int)t.t_flags;
+#endif /* defined(HASTCPOPT) */
+
+ }
+ break;
+/*
+ * Process a ROUTE domain socket.
+ */
+ case AF_ROUTE:
+ (void) snpf(Lf->type, sizeof(Lf->type), "rte");
+ if (s.so_pcb)
+ enter_dev_ch(print_kptr((KA_T)(s.so_pcb), (char *)NULL, 0));
+ else
+ (void) snpf(Namech, Namechl, "no protocol control block");
+ if (!Fsize)
+ Lf->off_def = 1;
+ break;
+/*
+ * Process a Unix domain socket.
+ */
+ case AF_UNIX:
+ if (Funix)
+ Lf->sf |= SELUNX;
+ (void) snpf(Lf->type, sizeof(Lf->type), "unix");
+ /*
+ * Read Unix protocol control block and the Unix address structure.
+ */
+
+ enter_dev_ch(print_kptr(sa, (char *)NULL, 0));
+ if (kread((KA_T) s.so_pcb, (char *) &unp, sizeof(unp))) {
+ (void) snpf(Namech, Namechl, "can't read unpcb at %s",
+ print_kptr((KA_T)s.so_pcb, (char *)NULL, 0));
+ break;
+ }
+ if ((struct socket *)sa != unp.unp_socket) {
+ (void) snpf(Namech, Namechl, "unp_socket (%s) mismatch",
+ print_kptr((KA_T)unp.unp_socket, (char *)NULL, 0));
+ break;
+ }
+ if (unp.unp_addr) {
+
+#if defined(UNPADDR_IN_MBUF)
+ if (kread((KA_T)unp.unp_addr, (char *)&mb, sizeof(mb)))
+#else /* !defined(UNPADDR_IN_MBUF) */
+ if (kread((KA_T)unp.unp_addr, (char *)&un, sizeof(un)))
+#endif /* defined(UNPADDR_IN_MBUF) */
+
+ {
+ (void) snpf(Namech, Namechl, "can't read unp_addr at %s",
+ print_kptr((KA_T)unp.unp_addr, (char *)NULL, 0));
+ break;
+ }
+
+#if defined(UNPADDR_IN_MBUF)
+ if (mb.m_hdr.mh_len == sizeof(struct sockaddr_un))
+ ua = (struct sockaddr_un *) ((char *) &mb
+ + (mb.m_hdr.mh_data - (caddr_t) unp.unp_addr));
+#else /* !defined(UNPADDR_IN_MBUF) */
+ ua = &un;
+#endif /* defined(UNPADDR_IN_MBUF) */
+
+ }
+ if (!ua) {
+ ua = &un;
+ (void) bzero((char *)ua, sizeof(un));
+ ua->sun_family = AF_UNSPEC;
+ }
+ /*
+ * Print information on Unix socket that has no address bound
+ * to it, although it may be connected to another Unix domain
+ * socket as a pipe.
+ */
+ if (ua->sun_family != AF_UNIX) {
+ if (ua->sun_family == AF_UNSPEC) {
+ if (unp.unp_conn) {
+ if (kread((KA_T)unp.unp_conn, (char *)&uc, sizeof(uc)))
+ (void) snpf(Namech, Namechl,
+ "can't read unp_conn at %s",
+ print_kptr((KA_T)unp.unp_conn,(char *)NULL,0));
+ else
+ (void) snpf(Namech, Namechl, "->%s",
+ print_kptr((KA_T)uc.unp_socket,(char *)NULL,0));
+ } else
+ (void) snpf(Namech, Namechl, "->(none)");
+ } else
+ (void) snpf(Namech, Namechl, "unknown sun_family (%d)",
+ ua->sun_family);
+ break;
+ }
+ if (ua->sun_path[0]) {
+
+#if defined(UNPADDR_IN_MBUF)
+ if (mb.m_len >= sizeof(struct sockaddr_un))
+ mb.m_len = sizeof(struct sockaddr_un) - 1;
+ *((char *)ua + mb.m_len) = '\0';
+#else /* !defined(UNPADDR_IN_MBUF) */
+ ua->sun_path[sizeof(ua->sun_path) - 1] = '\0';
+#endif /* defined(UNPADDR_IN_MBUF) */
+
+ if (Sfile && is_file_named(ua->sun_path, 0))
+ Lf->sf |= SELNM;
+ if (!Namech[0])
+ (void) snpf(Namech, Namechl, "%s", ua->sun_path);
+ } else
+ (void) snpf(Namech, Namechl, "no address");
+ break;
+ default:
+ printunkaf(fam, 1);
+ }
+ if (Namech[0])
+ enter_nm(Namech);
+}
diff --git a/dialects/n+obsd/dstore.c b/dialects/n+obsd/dstore.c
new file mode 100644
index 0000000..3205c79
--- /dev/null
+++ b/dialects/n+obsd/dstore.c
@@ -0,0 +1,132 @@
+/*
+ * dstore.c - NetBSD and OpenBSD global storage for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dstore.c,v 1.9 2004/12/30 18:42:24 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+struct file *Cfp; /* current file's file struct pointer */
+
+
+/*
+ * Drive_Nl -- table to drive the building of Nl[] via build_Nl()
+ * (See lsof.h and misc.c.)
+ */
+
+struct drive_Nl Drive_Nl[] = {
+
+#if (defined(OPENBSDV) && OPENBSDV>=2010) || (defined(NETBSDV) && NETBSDV>=1002000)
+ { X_NCACHE, "_nchashtbl", },
+ { X_NCSIZE, "_nchash" },
+#else /* (defined(OPENBSDV) && OPENBSDV>=2010) || (defined(NETBSDV) && NETBSDV>=1002000) */
+# if defined(NetBSD1_0) && NetBSD<1994101
+ { X_NCACHE, "_nchhead", },
+# else /* !defined(NetBSD1_0) || NetBSD>=1994101 */
+ { X_NCACHE, "_nclruhead" },
+# endif /* defined(NetBSD1_0) && NetBSD<1994101 */
+
+ { X_NCSIZE, "_numcache" },
+#endif /* (defined(OPENBSDV) && OPENBSDV>=2010) || (defined(NETBSDV) && NETBSDV>=1002000) */
+
+ { "pgshift", "_pgshift" },
+ { "", "" },
+ { NULL, NULL }
+};
+
+kvm_t *Kd; /* kvm descriptor */
+KA_T Kpa; /* kernel proc struct address */
+
+struct l_vfs *Lvfs = NULL; /* local vfs structure table */
+
+int Np = 0; /* number of kernel processes */
+
+#if defined(HASKVMGETPROC2)
+struct kinfo_proc2 *P = NULL; /* local process table copy */
+#else /* !defined(HASKVMGETPROC2) */
+struct kinfo_proc *P = NULL; /* local process table copy */
+#endif /* defined(HASKVMGETPROC2) */
+
+#if defined(HASFSTRUCT)
+/*
+ * Pff_tab[] - table for printing file flags
+ */
+
+struct pff_tab Pff_tab[] = {
+ { (long)FREAD, FF_READ },
+ { (long)FWRITE, FF_WRITE },
+ { (long)FNONBLOCK, FF_NBLOCK },
+ { (long)FNDELAY, FF_NDELAY },
+ { (long)FAPPEND, FF_APPEND },
+ { (long)FASYNC, FF_ASYNC },
+
+# if defined(FDSYNC)
+ { (long)FDSYNC, FF_DSYNC },
+# endif /* defined*FDSYNC) */
+
+ { (long)FFSYNC, FF_FSYNC },
+
+# if defined(FRSYNC)
+ { (long)FRSYNC, FF_RSYNC },
+# endif /* defined(FRSYNC( */
+
+ { (long)FMARK, FF_MARK },
+ { (long)FDEFER, FF_DEFER },
+ { (long)FHASLOCK, FF_HASLOCK },
+ { (long)O_NOCTTY, FF_NOCTTY },
+ { (long)0, NULL }
+};
+
+
+/*
+ * Pof_tab[] - table for print process open file flags
+ */
+
+struct pff_tab Pof_tab[] = {
+
+# if defined(UF_EXCLOSE)
+ { (long)UF_EXCLOSE, POF_CLOEXEC },
+# endif /* defined(UF_EXCLOSE) */
+
+# if defined(UF_MAPPED)
+ { (long)UF_MAPPED, POF_MAPPED },
+# endif /* defined(UF_MAPPED) */
+
+ { (long)0, NULL }
+};
+#endif /* defined(HASFSTRUCT) */
+
+int pgshift = 0; /* kernel's page shift */
diff --git a/dialects/n+obsd/machine.h b/dialects/n+obsd/machine.h
new file mode 100644
index 0000000..20e2ce9
--- /dev/null
+++ b/dialects/n+obsd/machine.h
@@ -0,0 +1,623 @@
+/*
+ * machine.h - NetBSD and OpenBSD definitions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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.
+ */
+
+
+/*
+ * $Id: machine.h,v 1.39 2010/07/29 16:02:52 abe Exp $
+ */
+
+
+#if !defined(LSOF_MACHINE_H)
+#define LSOF_MACHINE_H 1
+
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+
+/*
+ * CAN_USE_CLNT_CREATE is defined for those dialects where RPC clnt_create()
+ * can be used to obtain a CLIENT handle in lieu of clnttcp_create().
+ */
+
+#define CAN_USE_CLNT_CREATE 1
+
+
+/*
+ * DEVDEV_PATH defines the path to the directory that contains device
+ * nodes.
+ */
+
+#define DEVDEV_PATH "/dev"
+
+
+/*
+ * GET_MAX_FD is defined for those dialects that provide a function other than
+ * getdtablesize() to obtain the maximum file descriptor number plus one.
+ */
+
+/* #define GET_MAX_FD ? */
+
+
+/*
+ * HASAOPT is defined for those dialects that have AFS support; it specifies
+ * that the default path to an alternate AFS kernel name list file may be
+ * supplied with the -A <path> option.
+ */
+
+/* #define HASAOPT 1 */
+
+
+/*
+ * HASBLKDEV is defined for those dialects that want block device information
+ * recorded in BDevtp[].
+ */
+
+#define HASBLKDEV 1
+
+
+/*
+ * HASDCACHE is defined for those dialects that support a device cache
+ * file.
+ *
+ * HASENVDC defined the name of an environment variable that contains the
+ * device cache file path. The HASENVDC environment variable is ignored when
+ * the lsof process is setuid(root) or its real UID is 0.
+ *
+ * HASPERSDC defines the format for the last component of a personal device
+ * cache file path. The first will be the home directory of the real UID that
+ * executes lsof.
+ *
+ * HASPERSDCPATH defines the environment variable whose value is the middle
+ * component of the personal device cache file path. The middle component
+ * follows the home directory and precedes the results of applying HASPERSDC.
+ * The HASPERSDCPATH environment variable is ignored when the lsof process is
+ * setuid(root) or its real UID is 0.
+ *
+ * HASSYSDC defines a public device cache file path. When it's defined, it's
+ * used as the path from which to read the device cache.
+ *
+ * Consult the 00DCACHE and 00FAQ files of the lsof distribution for more
+ * information on device cache file path construction.
+ */
+
+#define HASDCACHE 1
+#define HASENVDC "LSOFDEVCACHE"
+#define HASPERSDC "%h/%p.lsof_%L"
+#define HASPERSDCPATH "LSOFPERSDCPATH"
+/* #define HASSYSDC "/your/choice/of/path" */
+
+
+/*
+ * HASCDRNODE is defined for those dialects that have CD-ROM nodes.
+ */
+
+/* #define HASCDRNODE 1 */
+
+
+/*
+ * HASFIFONODE is defined for those dialects that have FIFO nodes.
+ */
+
+/* #define HASFIFONODE 1 */
+
+
+/*
+ * HASFSINO is defined for those dialects that have the file system
+ * inode element, fs_ino, in the lfile structure definition in lsof.h.
+ */
+
+/* #define HASFSINO 1 */
+
+
+/*
+ * HASFSTRUCT is defined if the dialect has a file structure.
+ *
+ * FSV_DEFAULT defines the default set of file structure values to list.
+ * It defaults to zero (0), but may be made up of a combination of the
+ * FSV_* symbols from lsof.h.
+ *
+ * HASNOFSADDR -- has no file structure address
+ * HASNOFSFLAGS -- has no file structure flags
+ * HASNOFSCOUNT -- has no file structure count
+ * HASNOFSNADDR -- has no file structure node address
+ */
+
+#define HASFSTRUCT 1
+/* #define FSV_DEFAULT FSV_? | FSV_? | FSV_? */
+/* #define HASNOFSADDR 1 has no file structure address */
+/* #define HASNOFSFLAGS 1 has no file structure flags */
+/* #define HASNOFSCOUNT 1 has no file structure count */
+/* #define HASNOFSNADDR 1 has no file structure node address */
+
+
+/*
+ * HASGNODE is defined for those dialects that have gnodes.
+ */
+
+/* #define HASGNODE 1 */
+
+
+/*
+ * HASHSNODE is defined for those dialects that have High Sierra nodes.
+ */
+
+/* #define HASHSNODE 1 */
+
+
+/*
+ * HASINODE is defined for those dialects that have inodes and wish to
+ * use readinode() from node.c.
+ */
+
+#define HASINODE 1
+
+
+/*
+ * HASINTSIGNAL is defined for those dialects whose signal function returns
+ * an int.
+ */
+
+/* #define HASINTSIGNAL 1 */
+
+
+/*
+ * HASKERNIDCK is defined for those dialects that support the comparison of
+ * the build to running kernel identity.
+ */
+
+#define HASKERNIDCK 1
+
+
+/*
+ * HASKOPT is defined for those dialects that support the -k option of
+ * reading the kernel's name list from an optional file.
+ */
+
+#define HASKOPT 1
+
+
+/*
+ * HASLFILEADD is defined for those dialects that need additional elements
+ * in struct lfile. The HASLFILEADD definition is a macro that defines
+ * them. If any of the additional elements need to be preset in the
+ * alloc_lfile() function of proc.c, the SETLFILEADD macro may be defined
+ * to do that.
+ *
+ * If any additional elements need to be cleared in alloc_lfile() or in the
+ * free_proc() function of proc.c, the CLRLFILEADD macro may be defined to
+ * do that. Note that CLRLFILEADD takes one argument, the pointer to the
+ * lfile struct. The CLRLFILEADD macro is expected to expand to statements
+ * that are complete -- i.e., have terminating semi-colons -- so the macro is
+ * called without a terminating semicolon by proc.c.
+ *
+ * The HASXOPT definition may be used to select the conditions under which
+ * private lfile elements are used.
+ */
+
+/* #define HASLFILEADD int ... */
+/* #define CLRLFILEADD(lf) (lf)->... = (type)NULL; */
+/* #define SETLFILEADD Lf->... */
+
+
+/*
+ * HASMNTSTAT indicates the dialect supports the mount stat(2) result option
+ * in its l_vfs and mounts structures.
+ */
+
+/* #define HASMNTSTAT 1 */
+
+
+/*
+ * HASMNTSUP is defined for those dialects that support the mount supplement
+ * option.
+ */
+
+/* #define HASMNTSUP 1 */
+
+
+/*
+ * HASMOPT is defined for those dialects that support the reading of
+ * kernel memory from an alternate file.
+ */
+
+#define HASMOPT 1
+
+
+/*
+ * HASNCACHE is defined for those dialects that have a kernel name cache
+ * that lsof can search. A value of 1 directs printname() to prefix the
+ * cache value with the file system directory name; 2, avoid the prefix.
+ *
+ * NCACHELDPFX is a set of C commands to execute before calling ncache_load().
+ *
+ * NCACHELDSFX is a set of C commands to execute after calling ncache_load().
+ */
+
+#define HASNCACHE 1
+/* #define NCACHELDPFX ??? */
+/* #define NCACHELDSFX ??? */
+
+
+/*
+ * HASNLIST is defined for those dialects that use nlist() to acccess
+ * kernel symbols.
+ */
+
+#define HASNLIST 1
+
+
+/*
+ * HASPIPEFN is defined for those dialects that have a special function to
+ * process DTYPE_PIPE file structure entries. Its value is the name of the
+ * function.
+ *
+ * NOTE: don't forget to define a prototype for this function in dproto.h.
+ */
+
+# if defined(HAS_SYS_PIPEH)
+#define HASPIPEFN process_pipe
+# endif /* defined(HAS_SYS_PIPEH) */
+
+
+/*
+ * HASPIPENODE is defined for those dialects that have pipe nodes.
+ */
+
+/* #define HASPIPENODE 1 */
+
+
+/*
+ * HASPMAPENABLED is defined when the reporting of portmapper registration
+ * info is enabled by default.
+ */
+
+/* #define HASPMAPENABLED 1 */
+
+
+/*
+ * HASPPID is defined for those dialects that support identification of
+ * the parent process IDentifier (PPID) of a process.
+ */
+
+#define HASPPID 1
+
+
+/*
+ * HASPRINTDEV, HASPRINTINO, HASPRINTNM, HASPRINTOFF, and HASPRINTSZ
+ * define private dialect-specific functions for printing DEVice numbers,
+ * INOde numbers, NaMes, file OFFsets, and file SiZes. The functions are
+ * called from print_file().
+ */
+
+/* #define HASPRINTDEV print_dev? */
+/* #define HASPRINTINO print_ino? */
+/* #define HASPRINTNM print_nm? */
+/* #define HASPRINTOFF print_off? */
+/* #define HASPRINTSZ print_sz? */
+
+
+/*
+ * HASPRIVFILETYPE and PRIVFILETYPE are defined for dialects that have a
+ * file structure type that isn't defined by a DTYPE_* symbol. They are
+ * used in lib/prfp.c to select the type's processing.
+ *
+ * PRIVFILETYPE is the definition of the f_type value in the file struct.
+ *
+ * HASPRIVFILETYPE is the name of the processing function.
+ */
+
+/* #define HASPRIVFILETYPE process_shmf? */
+/* #define PRIVFILETYPE ?? */
+
+
+/*
+ * HASPRIVNMCACHE is defined for dialects that have a private method for
+ * printing cached NAME column values for some files. HASPRIVNAMECACHE
+ * is defined to be the name of the function.
+ *
+ * The function takes one argument, a struct lfile pointer to the file, and
+ * returns non-zero if it prints a name to stdout.
+ */
+
+/* #define HASPRIVNMCACHE <function name> */
+
+
+/*
+ * HASPRIVPRIPP is defined for dialects that have a private function for
+ * printing IP protocol names. When HASPRIVPRIPP isn't defined, the
+ * IP protocol name printing function defaults to printiprto().
+ */
+
+/* #define HASPRIVPRIPP 1 */
+
+
+/*
+ * HASPROCFS is defined for those dialects that have a proc file system --
+ * usually /proc and usually in SYSV4 derivatives. For FreeBSD, NetBSD,
+ * and OpenBSD the lsof Configure script defines HASPROCFS, based on the
+ * presence of /usr/src/sys/miscfs/procfs/procfs.h header file.
+ *
+ * HASFSTYPE is defined as 1 for those systems that have a file system type
+ * string, st_fstype, in the stat() buffer; 2, for those systems that have a
+ * file system type integer in the stat() buffer, named MOUNTS_STAT_FSTYPE;
+ * 0, for systems whose stat(2) structure has no file system type member. The
+ * additional symbols MOUNTS_FSTYPE, RMNT_FSTYPE, and RMNT_STAT_FSTYPE may be
+ * defined in dlsof.h to direct how the readmnt() function in lib/rmnt.c
+ * preserves these stat(2) and getmntent(3) buffer values in the local mounts
+ * structure.
+ *
+ * The defined value is the string that names the file system type.
+ *
+ * The HASPROCFS definition usually must be accompanied by the HASFSTYPE
+ * definition and the providing of an fstype element in the local mounts
+ * structure (defined in dlsof.h).
+ *
+ * The HASPROCFS definition may be accompanied by the HASPINODEN definition.
+ * HASPINODEN specifies that searching for files in HASPROCFS is to be done
+ * by inode number.
+ */
+
+# if defined(HASPROCFS)
+#undef HASPROCFS
+#define HASPROCFS "proc"
+# endif /* defined(HASPROCFS) */
+
+/* #define HASPROCFS "proc?" */
+/* #define HASFSTYPE 1 */
+#define HASPINODEN 1
+
+
+/*
+ * HASRNODE is defined for those dialects that have rnodes.
+ */
+
+/* #define HASRNODE 1 */
+
+
+/*
+ * Define HASSECURITY to restrict the listing of all open files to the
+ * root user. When HASSECURITY is defined, the non-root user may list
+ * only files whose processes have the same user ID as the real user ID
+ * (the one that its user logged on with) of the lsof process.
+ */
+
+/* #define HASSECURITY 1 */
+
+
+/*
+ * If HASSECURITY is defined, define HASNOSOCKSECURITY to allow users
+ * restricted by HASSECURITY to list any open socket files, provide their
+ * listing is selected by the "-i" option.
+ */
+
+/* #define HASNOSOCKSECURITY 1 */
+
+
+/*
+ * HASSETLOCALE is defined for those dialects that have <locale.h> and
+ * setlocale().
+ *
+ * If the dialect also has wide character support for language locales,
+ * HASWIDECHAR activates lsof's wide character support and WIDECHARINCL
+ * defines the header file (if any) that must be #include'd to use the
+ * mblen() and mbtowc() functions.
+ */
+
+#define HASSETLOCALE 1
+
+# if defined(NETBSDV) && NETBSDV>=1006000
+#define HASWIDECHAR 1
+# endif /* defined(NETBSDV) && NETBSDV>=1006000 */
+
+/* #define WIDECHARINCL <wchar.h> */
+
+
+/*
+ * HASSNODE is defined for those dialects that have snodes.
+ */
+
+/* #define HASSNODE 1 */
+
+
+/*
+ * HASTASKS is defined for those dialects that have task reporting support.
+ */
+
+/* #define HASTASKS 1 */
+
+
+/*
+ * HASSOOPT, HASSOSTATE and HASTCPOPT define the availability of information
+ * on socket options (SO_* symbols), socket states (SS_* symbols) and TCP
+ * options.
+ */
+
+#define HASSOOPT 1 /* has socket option information */
+#define HASSOSTATE 1 /* has socket state information */
+#define HASTCPOPT 1 /* has TCP options or flags */
+
+
+/*
+ * Define HASSPECDEVD to be the name of a function that handles the results
+ * of a successful stat(2) of a file name argument.
+ *
+ * For example, HASSPECDEVD() for Darwin makes sure that st_dev is set to
+ * what stat("/dev") returns -- i.e., what's in DevDev.
+ *
+ * The function takes two arguments:
+ *
+ * 1: pointer to the full path name of file
+ * 2: pointer to the stat(2) result
+ *
+ * The function returns void.
+ */
+
+/* #define HASSPECDEVD process_dev_stat */
+
+
+/*
+ * HASSTREAMS is defined for those dialects that support streams.
+ */
+
+/* #define HASSTREAMS 1 */
+
+
+/*
+ * HASTCPTPIQ is defined for dialects where it is possible to report the
+ * TCP/TPI Recv-Q and Send-Q values produced by netstat.
+ */
+
+#define HASTCPTPIQ 1
+
+
+/*
+ * HASTCPTPIW is defined for dialects where it is possible to report the
+ * TCP/TPI send and receive window sizes produced by netstat.
+ */
+
+/* #define HASTCPTPIW 1 */
+
+
+/*
+ * HASTMPNODE is defined for those dialects that have tmpnodes.
+ */
+
+/* #define HASTMPNODE 1 */
+
+
+/*
+ * HASVNODE is defined for those dialects that use the Sun virtual file system
+ * node, the vnode. BSD derivatives usually do; System V derivatives prior
+ * to R4 usually don't.
+ * doesn't.
+ */
+
+#define HASVNODE 1
+
+
+/*
+ * HASXOPT is defined for those dialects that have an X option. It
+ * defines the text for the usage display. HASXOPT_VALUE defines the
+ * option's default binary value -- 0 or 1.
+ */
+
+/* #define HASXOPT "help text for X option" */
+/* #define HASXOPT_VALUE 1 */
+
+
+/*
+ * INODETYPE and INODEPSPEC define the internal node number type and its
+ * printf specification modifier. These need not be defined and lsof.h
+ * can be allowed to define defaults.
+ *
+ * These are defined here, because they must be used in dlsof.h.
+ */
+
+#define INODETYPE unsigned long long
+ /* inode number internal storage type */
+#define INODEPSPEC "ll" /* INODETYPE printf specification
+ * modifier */
+
+
+/*
+ * UID_ARG defines the size of a User ID number when it is passed
+ * as a function argument.
+ */
+
+#define UID_ARG int
+
+
+/*
+ * Each USE_LIB_<function_name> is defined for dialects that use the
+ * <function_name> in the lsof library.
+ *
+ * Note: other definitions and operations may be required to condition the
+ * library function source code. They may be found in the dialect dlsof.h
+ * header files.
+ */
+
+/* #define USE_LIB_CKKV 1 ckkv.c */
+/* #define USE_LIB_COMPLETEVFS 1 cvfs.c */
+#define USE_LIB_FIND_CH_INO 1 /* fino.c */
+#define USE_LIB_IS_FILE_NAMED 1 /* isfn.c */
+#define USE_LIB_LKUPDEV 1 /* lkud.c */
+#define USE_LIB_PRINTDEVNAME 1 /* pdvn.c */
+#define USE_LIB_PROCESS_FILE 1 /* prfp.c */
+#define USE_LIB_PRINT_TCPTPI 1 /* ptti.c */
+#define USE_LIB_READDEV 1 /* rdev.c */
+/* #define USE_LIB_READMNT 1 rmnt.c */
+/* #define USE_LIB_REGEX 1 regex.c */
+
+# if (defined(OPENBSDV) && OPENBSDV>=2010) || (defined(NETBSDV) && NETBSDV>=1002000)
+#define USE_LIB_RNMH 1 /* rnmh.c */
+# else /* (defined(OPENBSDV) && OPENBSDV<2010) && (defined(NETBSDV) && NETBSDV<1002000) */
+#define USE_LIB_RNAM 1 /* rnam.c */
+# endif /* (defined(OPENBSDV) && OPENBSDV>=2010) || (defined(NETBSDV) && NETBSDV>=1002000) */
+
+/* #define USE_LIB_RNCH 1 rnch.c */
+/* #define USE_LIB_SNPF 1 snpf.c */
+#define snpf snprintf /* use the system's snprintf() */
+
+
+/*
+ * WARNDEVACCESS is defined for those dialects that should issue a warning
+ * when lsof can't access /dev (or /device) or one of its sub-directories.
+ * The warning can be inhibited by the lsof caller with the -w option.
+ */
+
+/* #define WARNDEVACCESS 1 */
+
+
+/*
+ * WARNINGSTATE is defined for those dialects that want to suppress all lsof
+ * warning messages.
+ */
+
+/* #define WARNINGSTATE 1 warnings are enabled by default */
+
+
+/*
+ * WILLDROPGID is defined for those dialects whose lsof executable runs
+ * setgid(not_real_GID) and whose setgid power can be relinquished after
+ * the dialect's initialize() function has been executed.
+ */
+
+#define WILLDROPGID 1
+
+
+/*
+ * zeromem is a macro that uses bzero or memset.
+ */
+
+#define zeromem(a, l) memset(a, 0, l)
+
+#endif /* !defined(LSOF_MACHINE_H) */
diff --git a/dialects/n+os/Makefile b/dialects/n+os/Makefile
new file mode 100644
index 0000000..8049a88
--- /dev/null
+++ b/dialects/n+os/Makefile
@@ -0,0 +1,169 @@
+
+# N+OS Makefile
+#
+# $Id: Makefile,v 1.14 2008/04/15 13:30:27 abe Exp $
+
+PROG= lsof
+
+BIN= ${DESTDIR}
+
+DOC= ${DESTDIR}
+
+I=/usr/include
+S=/usr/include/sys
+L=/usr/include/local
+P=
+
+# Use the RC_CFLAGS environment variable to define architecture types.
+# To create a "fat" executable, supporting more than one architecture,
+# set RC_CFLAGS before executing make -- e.g., to build a "fat" executable
+# for m68k, i486, hppa, and SPARC, using /bin/sh:
+#
+# $ cd <lsof_source_directory>
+# $ ./Configure ns
+# $ RC_CFLAGS="-arch m68k -arch i486 -arch hppa -arch sparc"
+# $ export RC_CFLAGS
+# $ make
+
+CDEF= ${RC_CFLAGS}
+CDEFS= ${CDEF} ${CFGF}
+INCL= ${DINC}
+CFLAGS= ${CDEFS} ${INCL} ${DEBUG}
+
+GRP=
+
+HDR= lsof.h lsof_fields.h dlsof.h machine.h proto.h dproto.h
+
+SRC= dnode.c denode1.c dproc.c dsock.c dstore.c \
+ arg.c main.c misc.c node.c print.c proc.c store.c usage.c \
+ util.c
+
+OBJ= dnode.o dnode1.o dproc.o dsock.o dstore.o \
+ arg.o main.o misc.o node.o print.o proc.o store.o usage.o \
+ util.o
+
+MAN= lsof.8
+
+OTHER=
+
+SHELL= /bin/sh
+
+SOURCE= Makefile ${OTHER} ${MAN} ${HDR} ${SRC}
+
+all: ${PROG}
+
+${PROG}: ${LIB} ${P} ${OBJ}
+ ${CC} -o $@ ${CFLAGS} ${OBJ} ${CFGL}
+
+clean: FRC
+ rm -f Makefile.bak ${PROG} a.out core errs lint.out tags *.o version.h
+ rm -f machine.h.old new_machine.h
+ (cd lib; ${MAKE} -f Makefile.skel clean)
+
+install: all FRC
+ @echo ''
+ @echo 'Please write your own install rule. Lsof should be installed'
+ @echo 'setgid to the group that can can read /dev/kmem. Normally'
+ @echo 'that is the kmem group. Your install rule actions might look'
+ @echo 'something like this:'
+ @echo ''
+ @echo ' install -cs -m 2755 -g $${GRP} $${PROG} $${BIN}/$${PROG}'
+ @echo ' install -c -m 444 $${MAN} $${DOC}/$${MAN}'
+ @echo ''
+ @echo 'You will have to complete the skeletons for the BIN, DOC, and'
+ @echo 'GRP strings given at the beginning of this Makefile, e.g.,'
+ @echo ''
+ @echo ' BIN= $${DESTDIR}/usr/local/etc'
+ @echo ' DOC= $${DESTDIR}/usr/man/man8'
+ @echo ' GRP= kmem'
+ @echo ''
+
+${LIB}: FRC
+ (cd lib; ${MAKE} DEBUG="${DEBUG}" CFGF="${CFGF}")
+
+version.h: FRC
+ @echo Constructing version.h
+ @rm -f version.h
+ @echo '#define LSOF_BLDCMT "${LSOF_BLDCMT}"' > version.h;
+ @echo '#define LSOF_CC "${CC}"' >> version.h
+ @echo '#define LSOF_CCV "${CCV}"' >> version.h
+ @echo '#define LSOF_CCDATE "'`date`'"' >> version.h
+ @echo '#define LSOF_CCFLAGS "'`echo ${CFLAGS} | sed 's/\\\\(/\\(/g' | sed 's/\\\\)/\\)/g' | sed 's/"/\\\\"/g'`'"' >> version.h
+ @echo '#define LSOF_LDFLAGS "${CFGL}"' >> version.h
+ @if [ "X${LSOF_LOGNAME}" = "X" ]; then \
+ echo '#define LSOF_LOGNAME "${LOGNAME}"' >> version.h; \
+ else \
+ if [ "${LSOF_LOGNAME}" = "none" ]; then \
+ echo '#define LSOF_LOGNAME ""' >> version.h; \
+ else \
+ echo '#define LSOF_LOGNAME "${LSOF_LOGNAME}"' >> version.h; \
+ fi; \
+ fi
+ @if [ "X${LSOF_HOST}" = "X" ]; then \
+ echo '#define LSOF_HOST "'`hostname`'"' >> version.h; \
+ else \
+ if [ "${LSOF_HOST}" = "none" ]; then \
+ echo '#define LSOF_HOST ""' >> version.h; \
+ else \
+ echo '#define LSOF_HOST "${LSOF_HOST}"' >> version.h; \
+ fi \
+ fi
+ @if [ "X${LSOF_SYSINFO}" = "X" ]; then \
+ echo '#define LSOF_SYSINFO "'`hostinfo | head -2 | tail -1`'"' >> version.h; \
+ else \
+ if [ "${LSOF_SYSINFO}" = "none" ]; then \
+ echo '#define LSOF_SYSINFO ""' >> version.h; \
+ else \
+ echo '#define LSOF_SYSINFO "${LSOF_SYSINFO}"' >> version.h; \
+ fi \
+ fi
+ @if [ "X${LSOF_USER}" = "X" ]; then \
+ echo '#define LSOF_USER "${USER}"' >> version.h; \
+ else \
+ if [ "${LSOF_USER}" = "none" ]; then \
+ echo '#define LSOF_USER ""' >> version.h; \
+ else \
+ echo '#define LSOF_USER "${LSOF_USER}"' >> version.h; \
+ fi \
+ fi
+ @sed '/VN/s/.ds VN \(.*\)/#define LSOF_VERSION "\1"/' < version >> version.h
+
+FRC:
+
+# DO NOT DELETE THIS LINE - make depend DEPENDS ON IT
+
+ddev.o: ${HDR} ddev.c
+
+dfile.o: ${HDR} dfile.c
+
+dmnt.o: ${HDR} dmnt.c
+
+dnode.o: ${HDR} dnode.c
+
+dnode1.o: ${HDR} dnode1.c
+
+dproc.o: ${HDR} dproc.c
+
+dsock.o: ${HDR} dsock.c
+
+dstore.o: ${HDR} dstore.c
+
+arg.o: ${HDR} arg.c
+
+main.o: ${HDR} main.c
+
+misc.o: ${HDR} misc.c
+
+node.o: ${HDR} node.c
+
+print.o: ${HDR} print.c
+
+proc.o: ${HDR} proc.c
+
+store.o: ${HDR} store.c
+
+usage.o: ${HDR} version.h usage.c
+
+util.o: ${HDR} util.c
+
+# *** Do not add anything here - It will go away. ***
diff --git a/dialects/n+os/Mksrc b/dialects/n+os/Mksrc
new file mode 100755
index 0000000..9abc4be
--- /dev/null
+++ b/dialects/n+os/Mksrc
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Mksrc - make NEXTSTEP and OPENSTEP source files
+#
+# WARNING: This script assumes it is running from the main directory
+# of the lsof, version 4 distribution.
+#
+# One environment variable is supplied:
+#
+# LSOF_MKC is the method for creating the source files.
+# It defaults to "ln -s". A common alternative is "cp".
+#
+# $Id: Mksrc,v 1.6 2001/08/09 11:44:07 abe Exp $
+
+
+D=dialects/n+os
+L="dlsof.h dnode.c dnode1.c dproc.c dproto.h dsock.c dstore.c machine.h"
+
+for i in $L
+do
+ rm -f $i
+ $LSOF_MKC $D/$i $i
+ echo "$LSOF_MKC $D/$i $i"
+done
diff --git a/dialects/n+os/dlsof.h b/dialects/n+os/dlsof.h
new file mode 100644
index 0000000..afd5d9d
--- /dev/null
+++ b/dialects/n+os/dlsof.h
@@ -0,0 +1,272 @@
+/*
+ * dlsof.h - NEXTSTEP and OPENSTEP header file for lsof
+ */
+
+
+/*
+ * Copyright 1994 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.
+ */
+
+
+/*
+ * $Id: dlsof.h,v 1.14 2006/03/28 22:08:17 abe Exp $
+ */
+
+
+#if !defined(LSOF_NEXT_H)
+#define LSOF_NEXT_H 1
+
+#include <c.h>
+#include <stdlib.h>
+#include <string.h>
+#include <mntent.h>
+#include <nlist.h>
+#include <signal.h>
+#include <setjmp.h>
+
+# if !defined(NCPUS)
+#define NCPUS 1
+# endif
+
+#include <mach/mach.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/xdr.h>
+#include <nfs/nfs.h>
+#include <nfs/nfs_clnt.h>
+#include <sys/vnode.h>
+#include <sys/wait.h>
+#include <nfs/rnode.h>
+#include <sys/dir.h>
+#include <sys/domain.h>
+
+# if !defined(KERNEL)
+#define KERNEL
+# endif
+
+#include <sys/file.h>
+#undef KERNEL
+#include <sys/mbuf.h>
+#include <ufs/mount.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/stat.h>
+#include <sys/ucred.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <net/route.h>
+#include <net/raw_cb.h>
+#include <netinet/in_pcb.h>
+#include <netinet/tcp.h>
+#include <netinet/tcp_fsm.h>
+#include <netinet/tcp_timer.h>
+#include <netinet/tcp_var.h>
+#include <sys/un.h>
+#include <sys/unpcb.h>
+
+# if !defined(SHOW_UTT)
+#define SHOW_UTT
+# endif
+
+/*
+ * Define simple_lock_t size.
+ */
+
+# if STEPV>=40 && defined(m68k)
+#define SIMPLE_LOCK_SIZE 0
+# elif defined(hppa) /* && (STEPV<40 || !defined(m68k)) */
+#define SIMPLE_LOCK_SIZE 4
+# else /* (STEPV<40 || !defined(m68k)) && !defined(hppa) */
+#define SIMPLE_LOCK_SIZE 1
+# endif /* STEPV>=40 && defined(m68k) */
+
+# if !defined(SIMPLE_LOCK_SIZE)
+#define SIMPLE_LOCK_SIZE 1
+# endif /* !defined(SIMPLE_LOCK_SIZE) */
+
+# if STEPV>=40
+/*
+ * Define lock_data_t that was removed from OPENSTEP 4.x's <kernserv/lock.h>.
+ */
+
+typedef struct lock {
+ char *thread;
+ unsigned int read_count:16,
+ want_upgrade:1,
+ want_write:1,
+ waiting:1,
+ can_sleep:1,
+ recursion_depth:12;
+
+# if SIMPLE_LOCK_SIZE>0
+ caddr_t interlock[SIMPLE_LOCK_SIZE];
+# endif /* SIMPLE_LOCK_SIZE>0 */
+
+} lock_data_t;
+# endif /* STEPV>=40 */
+
+#include <sys/user.h>
+#define u_comm uu_comm
+#define u_cdir uu_cdir
+#define u_rdir uu_rdir
+#undef SHOW_UTT
+#include <sys/proc.h>
+#include <sys/vfs.h>
+#include <ufs/inode.h>
+
+typedef int pid_t;
+
+
+/*
+ * The following substitution compensates for the snode.h that NeXT does
+ * not supply in NEXTSTEP 2.0 and above. The value of interest is s_realvp.
+ */
+
+struct snode {
+ struct snode *s_next; /* must be first */
+ struct vnode s_vnode; /* vnode associated with this snode */
+ struct vnode *s_realvp; /* vnode for the fs entry (if any) */
+};
+
+
+/*
+ * Miscellaneous definitions.
+ */
+
+#define COMP_P const void
+#define DEVINCR 1024 /* device table malloc() increment */
+typedef off_t KA_T;
+#define KMEM "/dev/kmem"
+#define MALLOC_P void
+#define FREE_P MALLOC_P
+#define MALLOC_S size_t
+#define MAXSYSCMDL MAXCOMLEN /* max system command name length */
+#define PROCDFLT 256 /* default size of local proc table */
+#define PROCMIN 5 /* processes that make a "good" scan */
+#define PROCSIZE sizeof(struct proc)
+#define PROCTRYLM 5 /* times to try to read proc table */
+#define QSORT_P void
+#define READLEN_T int
+#define STRNCPY_L int
+#define U_SIZE sizeof(struct user)
+
+# if !defined(VMUNIX)
+#define VMUNIX "/mach"
+# endif
+
+#define N_UNIX VMUNIX
+
+
+# if defined(HAS_AFS)
+/*
+ * AFS definitions
+ */
+
+#define AFSAPATHDEF "/usr/vice/etc/afs_loadable"
+#define AFSDEV 1 /* AFS "fake" device number */
+
+# if defined(HASAOPT)
+extern char *AFSApath; /* alternate AFS name list path
+ * (from -A) */
+# endif /* defined(HASAOPT) */
+
+extern struct vfs *AFSVfsp; /* AFS struct vfs kernel pointer */
+# endif /* defined(HAS_AFS) */
+
+
+/*
+ * Local mount information
+ */
+
+struct mounts {
+ char *dir; /* directory (mounted on) */
+ char *fsname; /* file system
+ * (symbolic links unresolved) */
+ char *fsnmres; /* file system
+ * (symbolic links resolved) */
+ dev_t dev; /* directory st_dev */
+ dev_t rdev; /* directory st_rdev */
+ INODETYPE inode; /* directory inode number */
+ u_short mode; /* directory st_mode */
+ u_short fs_mode; /* file system st_mode */
+ struct mounts *next; /* forward link */
+};
+
+
+/*
+ * Defines for kernel name list
+ */
+
+#define NL_NAME n_un.n_name
+
+
+/*
+ * For kernel name cache processing
+ */
+
+# if defined(HASNCACHE)
+#include <sys/dnlc.h>
+#define X_NCACHE "nch"
+#define X_NCSIZE "ncsz"
+# endif /* defined(HASNCACHE) */
+
+
+/*
+ * Defines for library readdev() function
+ */
+
+#define DIRTYPE direct
+#define HASDNAMLEN 1
+
+
+/*
+ * Search file information
+ */
+
+struct sfile {
+ char *aname; /* file name argument */
+ char *name; /* file name (after readlink()) */
+ char *devnm; /* device name (optional) */
+ dev_t dev; /* device */
+ dev_t rdev; /* raw device */
+ u_short mode; /* S_IFMT mode bits from stat() */
+ int type; /* file type: 0 = file system
+ * 1 = regular file */
+ INODETYPE i; /* inode number */
+ int f; /* file found flag */
+ struct sfile *next; /* forward link */
+};
+
+
+/*
+ * Miscellaneous external definitions
+ */
+
+extern struct file *Fileptr;
+#define FILEPTR Fileptr /* for process_file() in lib/prfp.c */
+extern int Kd;
+
+#endif /* LSOF_NEXT_H */
diff --git a/dialects/n+os/dnode.c b/dialects/n+os/dnode.c
new file mode 100644
index 0000000..6747942
--- /dev/null
+++ b/dialects/n+os/dnode.c
@@ -0,0 +1,711 @@
+/*
+ * dnode.c - NEXTSTEP and OPENSTEP node functions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dnode.c,v 1.17 2006/03/28 22:08:17 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+#if STEPV>=31
+/*
+ * Local definitions
+ */
+
+struct l_lockf { /* local lock info */
+ short type; /* lock type */
+ off_t start, end; /* lock start and end */
+ pid_t pid; /* owning process ID */
+ struct l_lockf *next;
+};
+
+struct l_svn { /* shadow vnode */
+ KA_T vp; /* associated vnode */
+ struct l_lockf *lp; /* local lock chain */
+ struct l_svn *next;
+};
+
+struct posix_proc {
+ pid_t p_pid;
+};
+#define POSIX_KERN 1
+#include <ufs/lockf.h>
+
+#define SVNHASH(n) (((int)((long)(n) * 31415l) >> 5) & (LF_SVNODE_HSZ - 1))
+
+
+/*
+ * Local static variables
+ */
+
+static struct l_svn **Svnc = (struct l_svn **)NULL;
+ /* local shadow vnode cache */
+static int SvncSt = 0; /* Svnc[] load status */
+
+
+/*
+ * Local function prototypes
+ */
+
+_PROTOTYPE(static char isvlocked,(KA_T vp));
+_PROTOTYPE(static int load_svnc,(void));
+
+
+/*
+ * clr_svnc() - clear shadow vnode cache
+ */
+
+void
+clr_svnc()
+{
+ struct l_lockf *lf, *lfn;
+ int i;
+ struct l_svn *sv, *svn;
+
+ if (!Svnc || !SvncSt)
+ return;
+ for (i = 0; i < LF_SVNODE_HSZ; i++) {
+ if (!(sv = Svnc[i]))
+ continue;
+ do {
+ if ((lf = sv->lp)) {
+ do {
+ lfn = lf->next;
+ (void) free((FREE_P *)lf);
+ } while ((lf = lfn));
+ }
+ svn = sv->next;
+ (void) free((FREE_P *)sv);
+ } while ((sv = svn));
+ Svnc[i] = (struct l_svn *)NULL;
+ }
+ SvncSt = 0;
+}
+
+
+/*
+ * isvlocked() - is vnode locked?
+ */
+
+static char
+isvlocked(vp)
+ KA_T vp; /* vnode's kernel address */
+{
+ int i;
+ struct l_lockf *lp;
+ struct l_svn *sv;
+
+ if (!Svnc || !SvncSt) {
+ if (!load_svnc())
+ return(' ');
+ }
+/*
+ * Hash the vnode address and see if there's a shadow (lock) vnode structure
+ * assigned to it.
+ */
+ i = SVNHASH(vp);
+ for (sv = Svnc[i]; sv; sv = sv->next) {
+ if ((KA_T)sv->vp == vp)
+ break;
+ }
+ if (!sv)
+ return(' ');
+/*
+ * Search the lock owners represented by the shadow vnode's lock chain
+ * for this process.
+ */
+ for (lp = sv->lp; lp; lp = lp->next) {
+ if (lp->pid == (pid_t)Lp->pid) {
+ if (lp->start == 0 && lp->end == 0x7fffffff)
+ i = 1;
+ else
+ i = 0;
+ if (lp->type == F_RDLCK)
+ return(i ? 'R' : 'r');
+ else if (lp->type == F_WRLCK)
+ return(i ? 'W' : 'w');
+ return(' ');
+ }
+ }
+ return(' ');
+}
+
+
+/*
+ * load_svnc() - load the shadow vnode cache
+ */
+
+int
+load_svnc()
+{
+ int i, j;
+ static KA_T kp = (KA_T)NULL;
+ struct lockf lf, *lp;
+ struct l_lockf *lsf;
+ struct l_svn *lsv;
+ struct posix_proc p;
+ struct lf_svnode *sn, *sp[LF_SVNODE_HSZ], sv;
+
+ if (Svnc && SvncSt)
+ return(1);
+/*
+ * Get the shadow vnode hash table address from the kernel.
+ */
+ if (!kp) {
+ if (get_Nl_value("lfsvh", Drive_Nl, &kp) < 0 || !kp)
+ return(0);
+ }
+/*
+ * Define local hash buckets, if necessary.
+ */
+ if (!Svnc) {
+ if (!(Svnc = (struct l_svn **)calloc(sizeof(struct l_svn *),
+ LF_SVNODE_HSZ)))
+ {
+ (void) fprintf(stderr,
+ "%s: no space for %d local shadow vnode hash buckets\n",
+ Pn, LF_SVNODE_HSZ);
+ Exit(1);
+ }
+ }
+/*
+ * Search the hash buckets of the shadow vnode table.
+ */
+ if (kread(kp, (char *)&sp, sizeof(sp)))
+ return(0);
+ for (i = 0; i < LF_SVNODE_HSZ; i++) {
+ if (!(sn = sp[i]))
+ continue;
+ do {
+
+ /*
+ * Duplicate the chain of shadow vnodes in the bucket.
+ */
+ if (kread((KA_T)sn, (char *)&sv, sizeof(sv))
+ || !sv.lf_vnodep
+ || !sv.lf_lockfp)
+ break;
+ /*
+ * Allocate and initialize a local shadow vnode structure.
+ */
+ if (!(lsv = (struct l_svn *)malloc(sizeof(struct l_svn)))) {
+ (void) fprintf(stderr,
+ "%s: no space for local shadow vnode -- PID: %ld\n",
+ Pn, Lp->pid);
+ Exit(1);
+ }
+ lsv->vp = (KA_T)sv.lf_vnodep;
+ lsv->lp = (struct l_lockf *)NULL;
+ lsv->next = (struct l_svn *)NULL;
+ lp = sv.lf_lockfp;
+ do {
+
+ /*
+ * Duplicate the lock chain for this shadow vnode.
+ */
+ if (kread((KA_T)lp, (char *)&lf, sizeof(lf)))
+ break;
+ if (!lf.lf_posix_procp
+ || kread((KA_T)lf.lf_posix_procp, (char *)&p, sizeof(p))
+ || !p.p_pid)
+ continue;
+ if (!(lsf=(struct l_lockf *)malloc(sizeof(struct l_lockf))))
+ {
+ (void) fprintf(stderr,
+ "%s: no space for local lock struct -- PID: %ld\n",
+ Pn, Lp->pid);
+ Exit(1);
+ }
+ lsf->type = lf.lf_type;
+ lsf->start = lf.lf_start;
+ lsf->end = lf.lf_end;
+ lsf->pid = (pid_t)p.p_pid;
+ lsf->next = lsv->lp;
+ lsv->lp = lsf;
+ } while ((lp = lf.lf_next));
+ /*
+ * Link the shadow vnode to its local hash bucket.
+ */
+ j = SVNHASH(lsv->vp);
+ lsv->next = Svnc[j];
+ Svnc[j] = lsv;
+ } while ((sn = sv.lf_next));
+ }
+ SvncSt = 1;
+ return(1);
+}
+#endif /* STEPV>=31 */
+
+
+/*
+ * process_node() - process vnode
+ */
+
+void
+process_node(va)
+ KA_T va; /* vnode kernel space address */
+{
+ dev_t dev, rdev;
+ int devs = 0;
+ static int ft = 1;
+ static KA_T fvops = (KA_T)0;
+ struct inode i;
+ int ins = 0;
+ static KA_T nvops = (KA_T)0;
+ struct rnode r;
+ int rdevs = 0;
+ struct vnode rv;
+ struct snode s;
+ static KA_T svops = (KA_T)0;
+ char tbuf[32], *ty;
+ static KA_T uvops = (KA_T)0;
+ enum vtype type;
+ static struct vnode *v = (struct vnode *)NULL;
+
+#if defined(HAS_AFS)
+ static int afs = 0; /* AFS test status: -1 = no AFS
+ * 0 = not tested
+ * 1 = AFS present */
+ struct afsnode an;
+ static KA_T avops = (KA_T)0;
+#endif /* defined(HAS_AFS) */
+
+/*
+ * Read the vnode.
+ */
+ if (!va) {
+ enter_nm("no vnode address");
+ return;
+ }
+/*
+ * Read the vnode.
+ */
+ if (!v) {
+
+ /*
+ * Allocate space for the vnode or AFS vcache structure.
+ */
+
+#if defined(HAS_AFS)
+ v = alloc_vcache();
+#else /* !defined(HAS_AFS) */
+ v = (struct vnode *)malloc(sizeof(struct vnode));
+#endif /* defined(HAS_AFS) */
+
+ if (!v) {
+ (void) fprintf(stderr, "%s: can't allocate %s space\n", Pn,
+
+#if defined(HAS_AFS)
+ "vcache"
+#else /* !defined(HAS_AFS) */
+ "vnode"
+#endif /* defined(HAS_AFS) */
+
+ );
+ Exit(1);
+ }
+ }
+ if (readvnode(va, v)) {
+ enter_nm(Namech);
+ return;
+ }
+
+# if defined(HASNCACHE)
+ Lf->na = va;
+# endif /* defined(HASNCACHE) */
+
+# if defined(HASFSTRUCT)
+ Lf->fna = va;
+ Lf->fsv |= FSV_NI;
+# endif /* defined(HASFSTRUCT) */
+
+/*
+ * Get vnode operations addresses, as required.
+ */
+ if (ft) {
+
+#if defined(HAS_AFS)
+ (void) get_Nl_value("avops", Drive_Nl, &avops);
+#endif /* defined(HAS_AFS) */
+
+ (void) get_Nl_value("fvops", Drive_Nl, &fvops);
+ (void) get_Nl_value("nvops", Drive_Nl, &nvops);
+ (void) get_Nl_value("svops", Drive_Nl, &svops);
+ (void) get_Nl_value("uvops", Drive_Nl, &uvops);
+ ft = 0;
+ }
+/*
+ * Determine the vnode type.
+ */
+ if ((uvops && (KA_T)v->v_op == uvops)
+ || (svops && (KA_T)v->v_op == svops))
+ Ntype = N_REGLR;
+ else if (nvops && (KA_T)v->v_op == nvops)
+ Ntype = N_NFS;
+ else if (fvops && (KA_T)v->v_op == fvops)
+ Ntype = N_FIFO;
+
+#if defined(HAS_AFS)
+ /*
+ * Caution: this AFS test should be the last one.
+ */
+
+ else if (avops) {
+ if ((KA_T)v->v_op == avops)
+ Ntype = N_AFS;
+ else {
+
+unknown_v_op:
+ (void) snpf(Namech, Namechl,
+ "unknown file system type; v_op: %s",
+ print_kptr((KA_T)v->v_op, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ } else if (v->v_data || !v->v_vfsp)
+ goto unknown_v_op;
+ else {
+ switch (afs) {
+ case -1:
+ goto unknown_v_op;
+ case 0:
+ if (!hasAFS(v)) {
+ afs = -1;
+ goto unknown_v_op;
+ }
+ afs = 1;
+ Ntype = N_AFS;
+ AFSVfsp = (KA_T)v->v_vfsp;
+ break;
+ case 1:
+ if ((KA_T)v->v_vfsp == AFSVfsp)
+ Ntype = N_AFS;
+ else
+ goto unknown_v_op;
+ }
+ }
+#else /* !defined(HAS_AFS) */
+ else {
+ (void) snpf(Namech, Namechl, "unknown file system type; v_op: %s",
+ print_kptr((KA_T)v->v_op, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+#endif /* defined(HAS_AFS) */
+
+/*
+ * Determine the lock type.
+ */
+ if (v->v_shlockc || v->v_exlockc) {
+ if (FILEPTR && (FILEPTR->f_flag & FSHLOCK))
+ Lf->lock = 'R';
+ else if (FILEPTR && (FILEPTR->f_flag & FEXLOCK))
+ Lf->lock = 'W';
+ else
+
+#if STEPV>=31
+ Lf->lock = isvlocked(va);
+#else /* STEPV<31 */
+ Lf->lock = ' ';
+#endif /* STEPV>=31 */
+
+ }
+/*
+ * Read the inode, rnode, snode, or vcache struct.
+ */
+ switch (Ntype) {
+
+#if defined(HAS_AFS)
+ case N_AFS:
+ if (readafsnode(va, v, &an))
+ return;
+ break;
+#endif /* defined(HAS_AFS) */
+
+ case N_NFS:
+ if (!v->v_data || readrnode((KA_T)v->v_data, &r)) {
+ (void) snpf(Namech, Namechl,
+ "vnode at %s: can't read rnode (%s)",
+ print_kptr(va, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ break;
+ case N_REGLR:
+ default:
+
+ /*
+ * VBLK, VCHR and VFIFO vnodes point to an snode. The snode's s_realvp
+ * usually points to a real vnode, which points to an inode.
+ */
+ if (v->v_type == VBLK || v->v_type == VCHR || v->v_type == VFIFO) {
+ if (!v->v_data || readsnode((KA_T)v->v_data, &s)) {
+ (void) snpf(Namech, Namechl,
+ "vnode at %s: can't read snode(%s)",
+ print_kptr(va, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ if (s.s_realvp) {
+ if (readvnode((KA_T)s.s_realvp, &rv)) {
+ (void) snpf(Namech, Namechl,
+ "snode at %s: can't read real vnode (%s)",
+ print_kptr((KA_T)v->v_data, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)s.s_realvp, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ if (!rv.v_data || readinode((KA_T)rv.v_data, &i)) {
+ (void) snpf(Namech, Namechl,
+ "snode at %s: can't read inode (%s)",
+ print_kptr((KA_T)v->v_data, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)rv.v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ ins = 1;
+ }
+ break;
+ } else {
+ if (!v->v_data || readinode((KA_T)v->v_data, &i)) {
+ (void) snpf(Namech, Namechl,
+ "vnode at %s: can't read inode (%s)",
+ print_kptr(va, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ ins = 1;
+ }
+ }
+/*
+ * Get device and type for printing.
+ */
+ switch (Ntype) {
+
+#if defined(HAS_AFS)
+ case N_AFS:
+ dev = an.dev;
+ devs = 1;
+ break;
+#endif /* defined(HAS_AFS) */
+
+ case N_NFS:
+ dev = r.r_attr.va_fsid;
+ devs = 1;
+ if (dev & 0x8000)
+ dev |= 0xff00;
+ break;
+ case N_FIFO:
+ case N_REGLR:
+ if (ins) {
+ dev = i.i_dev;
+ devs = 1;
+ }
+ if ((v->v_type == VBLK) || (v->v_type == VCHR)) {
+ rdev = v->v_rdev;
+ rdevs = 1;
+ }
+ }
+ type = v->v_type;
+/*
+ * Obtain the inode number.
+ */
+ switch(Ntype) {
+
+#if defined(HAS_AFS)
+ case N_AFS:
+ if (an.ino_st) {
+ Lf->inode = (INODETYPE)an.inode;
+ Lf->inp_ty = 1;
+ }
+ break;
+#endif /* defined(HAS_AFS) */
+
+ case N_NFS:
+ Lf->inode = (INODETYPE)r.r_attr.va_nodeid;
+ Lf->inp_ty = 1;
+ break;
+ case N_FIFO:
+ case N_REGLR:
+ if (ins) {
+ Lf->inode = (INODETYPE)i.i_number;
+ Lf->inp_ty = 1;
+ }
+ }
+/*
+ * Obtain the file size.
+ */
+ if (Foffset)
+ Lf->off_def = 1;
+ else {
+ switch (Ntype) {
+
+#if defined(HAS_AFS)
+ case N_AFS:
+ Lf->sz = (SZOFFTYPE)an.size;
+ Lf->sz_def = 1;
+ break;
+#endif /* defined(HAS_AFS) */
+
+ case N_NFS:
+ Lf->sz = (SZOFFTYPE)r.r_attr.va_size;
+ Lf->sz_def = 1;
+ break;
+ case N_FIFO:
+ Lf->off_def = 1;
+ break;
+ case N_REGLR:
+ if (type == VREG || type == VDIR) {
+ if (ins) {
+ Lf->sz = (SZOFFTYPE)i.i_size;
+ Lf->sz_def = 1;
+ }
+ }
+ else if ((type == VCHR || type == VBLK) && !Fsize)
+ Lf->off_def = 1;
+ break;
+ }
+ }
+/*
+ * Record the link count.
+ */
+ if (Fnlink) {
+
+#if defined(HAS_AFS)
+ case N_AFS:
+ Lf->nlink = an.nlink;
+ Lf->nlink_def = an.nlink_st;
+ break;
+#endif /* defined(HAS_AFS) */
+
+ switch (Ntype) {
+ case N_NFS:
+ Lf->nlink = (long)r.r_attr.va_nlink;
+ Lf->nlink_def = 1;
+ break;
+ case N_REGLR:
+ if (ins) {
+ Lf->nlink = (long)i.i_nlink;
+ Lf->nlink_def = 1;
+ }
+ break;
+ }
+ if (Lf->nlink_def && Nlink && (Lf->nlink < Nlink))
+ Lf->sf |= SELNLINK;
+ }
+/*
+ * Record an NFS file selection.
+ */
+ if (Ntype == N_NFS && Fnfs)
+ Lf->sf |= SELNFS;
+/*
+ * Defer file system info lookup until printname().
+ */
+ Lf->lmi_srch = 1;
+/*
+ * Save the device numbers and their states.
+ *
+ * Format the vnode type.
+ */
+ Lf->dev = dev;
+ Lf->dev_def = devs;
+ Lf->rdev = rdev;
+ Lf->rdev_def = rdevs;
+ switch (type) {
+ case VNON:
+ ty ="VNON";
+ break;
+ case VREG:
+ case VDIR:
+ ty = (type == VREG) ? "VREG" : "VDIR";
+ break;
+ case VBLK:
+ ty = "VBLK";
+ Ntype = N_BLK;
+ break;
+ case VCHR:
+ ty = "VCHR";
+ Ntype = N_CHR;
+ break;
+ case VLNK:
+ ty = "VLNK";
+ break;
+
+#if defined(VSOCK)
+ case VSOCK:
+ ty = "SOCK";
+ break;
+#endif
+
+ case VBAD:
+ ty = "VBAD";
+ break;
+ case VFIFO:
+ ty = "FIFO";
+ break;
+ default:
+ (void) snpf(Lf->type, sizeof(Lf->type), "%04o", (type & 0xfff));
+ ty = NULL;
+ }
+ if (ty)
+ (void) snpf(Lf->type, sizeof(Lf->type), ty);
+ Lf->ntype = Ntype;
+/*
+ * If this is a VBLK file and it's missing an inode number, try to
+ * supply one.
+ */
+ if ((Lf->inp_ty == 0) && (Lf->ntype == N_BLK))
+ find_bl_ino();
+/*
+ * If this is a VCHR file and it's missing an inode number, try to
+ * supply one.
+ */
+ if ((Lf->inp_ty == 0) && (Lf->ntype == N_CHR))
+ find_ch_ino();
+/*
+ * Test for specified file.
+ */
+ if (Sfile && is_file_named((char *)NULL,
+ ((type == VCHR) || (type == VBLK)) ? 1 : 0))
+ Lf->sf |= SELNM;
+/*
+ * Enter name characters.
+ */
+ if (Namech[0])
+ enter_nm(Namech);
+}
diff --git a/dialects/n+os/dnode1.c b/dialects/n+os/dnode1.c
new file mode 100644
index 0000000..a18c482
--- /dev/null
+++ b/dialects/n+os/dnode1.c
@@ -0,0 +1,401 @@
+/*
+ * dnode1.h - NEXTSTEP and OPENSTEP AFS support
+ */
+
+
+/*
+ * Copyright 1996 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 1996 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dnode1.c,v 1.7 2005/08/08 19:54:03 abe Exp $";
+#endif
+
+
+#if defined(HAS_AFS)
+#include "lsof.h"
+
+#include <rpc/xdr.h>
+#define __XDR_INCLUDE__
+
+#include <afs/stds.h>
+#include <afs/param.h>
+#include <afs/afsint.h>
+#include <afs/vldbint.h>
+
+
+/*
+ * This is an emulation of the afs_rwlock_t definition that appears in
+ * the AFS sources in afs/lock.h.
+ */
+
+struct afs_lock {
+
+# if HAS_AFS<304
+ unsigned char d1[4];
+# else /* HAS_AFS>=304 */
+ unsigned char d1[6];
+# endif /* HAS_AFS<304 */
+
+};
+typedef struct afs_lock afs_lock_t;
+typedef struct afs_lock afs_rwlock_t;
+
+
+/*
+ * This is an emulation of the afs_bozoLock_t definition that appears in
+ * the AFS sources in afs/lock.h.
+ */
+
+struct afs_bozoLock {
+ short d1;
+ char d2[2];
+ char *d3;
+};
+typedef struct afs_bozoLock afs_bozoLock_t;
+
+#define KERNEL
+#include <afs/afs.h>
+#undef KERNEL
+
+
+/*
+ * Local function prototypes
+ */
+
+_PROTOTYPE(static struct volume *getvolume,(struct VenusFid *f, int *vols));
+_PROTOTYPE(static int is_rootFid,(struct vcache *vc, int *rfid));
+
+
+/*
+ * alloc_vcache() - allocate space for vcache structure
+ */
+
+struct vnode *
+alloc_vcache()
+{
+ return((struct vnode *)malloc(sizeof(struct vcache)));
+}
+
+
+/*
+ * ckAFSsym() - check for missing X_AFS_* symbols in AFS name list file
+ */
+
+void
+ckAFSsym(nl)
+ struct nlist *nl; /* copy of Nl[] when empty */
+{
+ char *path = AFSAPATHDEF;
+ int i;
+
+# if defined(HASAOPT)
+ if (AFSApath)
+ path = AFSApath;
+# endif /* defined(HASAOPT) */
+
+/*
+ * See if the alternate AFS name list file can be read.
+ */
+ if (!is_readable(path, 0)) {
+ if (!Fwarn)
+ (void) fprintf(stderr,
+ "%s: WARNING: can't access AFS name list file: %s\n",
+ Pn, path);
+ return;
+ }
+/*
+ * Read the AFS modload symbols and compare its non-zero values with
+ * the non-zero values in Nl[]. Quit if there is any mis-match.
+ */
+ if (nlist(path, nl) < 0)
+ return;
+ for (i = 0; Nl[i].n_un.n_name && Nl[i].n_un.n_name[0]; i++) {
+ if (!nl[i].n_value || !Nl[i].n_value)
+ continue;
+ if (nl[i].n_value != Nl[i].n_value)
+ return;
+ }
+/*
+ * If any AFS kernel name list symbol that doesn't have a value in Nl[] has
+ * one from the AFS modload file, copy its modload value to Nl[].
+ */
+ if ((i = get_Nl_value("arFid", Drive_Nl, NULL)) >= 0
+ && !Nl[i].n_value && nl[i].n_value)
+ Nl[i].n_value = nl[i].n_value;
+ if ((i = get_Nl_value("avops", Drive_Nl, NULL)) >= 0
+ && !Nl[i].n_value && nl[i].n_value)
+ Nl[i].n_value = nl[i].n_value;
+ if ((i = get_Nl_value("avol", Drive_Nl, NULL)) >= 0
+ && !Nl[i].n_value && nl[i].n_value)
+ Nl[i].n_value = nl[i].n_value;
+}
+
+
+/*
+ * getvolume() - get volume structure
+ */
+
+static struct volume *
+getvolume(f, vols)
+ struct VenusFid *f; /* file ID pointer */
+ int *vols; /* afs_volumes status return */
+{
+ int i;
+ static KA_T ka = 0;
+ KA_T kh;
+ static struct volume v;
+ struct volume *vp;
+ static int w = 0;
+
+ if (!ka) {
+ if (get_Nl_value("avol", Drive_Nl, (unsigned long *)&ka) < 0 || !ka)
+ {
+ if (!w && !Fwarn) {
+ (void) fprintf(stderr,
+ "%s: WARNING: no kernel address for afs_volumes\n", Pn);
+ (void) fprintf(stderr,
+ " This may hamper AFS node number reporting.\n");
+ w = 1;
+ }
+ *vols = 0;
+ return((struct volume *)NULL);
+ }
+ }
+ *vols = 1;
+ i = (NVOLS - 1) & f->Fid.Volume;
+ kh = (KA_T)((char *)ka + (i * sizeof(struct volume *)));
+ if (kread(kh, (char *)&vp, sizeof(vp)))
+ return((struct volume *)NULL);
+ while (vp) {
+ if (kread((KA_T)vp, (char *)&v, sizeof(v)))
+ return((struct volume *)NULL);
+ if (v.volume == f->Fid.Volume && v.cell == f->Cell)
+ return(&v);
+ vp = v.next;
+ }
+ return((struct volume *)NULL);
+}
+
+
+/*
+ * hasAFS() - test for AFS presence via vfs structure
+ */
+
+int
+hasAFS(vp)
+ struct vnode *vp; /* vnode pointer */
+{
+ struct mounts *mp;
+ int n;
+ struct vfs v;
+/*
+ * If this vnode has a v_data pointer, then it probably isn't an AFS vnode;
+ * return FALSE.
+ *
+ * If the vfs struct address of /afs is known and this vnode's v_vfsp matches
+ * it, return TRUE.
+ *
+ * Read this vnode's vfs structure and see if it's device (fsid.val[0]) is
+ * AFSDEV. If it is, record the AFS vfs struct address and return TRUE.
+ */
+ if (AFSVfsp && !vp->v_data && vp->v_vfsp == AFSVfsp)
+ return(1);
+ if (vp->v_data
+ || !vp->v_vfsp
+ || kread((KA_T)vp->v_vfsp, (char *)&v, sizeof(v))
+ || v.vfs_data)
+ return(0);
+ if (v.vfs_fsid.val[0] == AFSDEV) {
+ AFSVfsp = vp->v_vfsp;
+ return(1);
+ }
+/*
+ * Search the local mount table for /afs devices or a match on device number.
+ * Count /afs devices and skip a device number test for them. A match on
+ * device number for non-AFS devices produces a FALSE return.
+ */
+ for (mp = readmnt(), n = 0; mp; mp = mp->next) {
+ if (mp->dev == AFSDEV
+ && mp->dir && strcmp(mp->dir, "/afs") == 0
+ && mp->fsname && strcmp(mp->fsname, "AFS") == 0)
+ n++;
+ else if (mp->dev == (dev_t)v.vfs_fsid.val[0])
+ return(0);
+ }
+/*
+ * If there is exactly one /afs device, assume its vfs struct address is
+ * the one for this vnode, record it, and return TRUE.
+ */
+ if (n == 1) {
+ AFSVfsp = vp->v_vfsp;
+ return(1);
+ }
+ return(0);
+}
+
+
+/*
+ * is_rootFid() - is the file ID the root file ID
+ *
+ * return: 0 = is not root file ID
+ * 1 = is root file ID
+ * rfid = 0 if root file ID structure address not available
+ * 1 if root file ID structure address available
+ */
+
+static int
+is_rootFid(vc, rfid)
+ struct vcache *vc; /* vcache structure */
+ int *rfid; /* root file ID pointer status return */
+{
+ unsigned long arFid;
+ char *err;
+ static int f = 0; /* rootFid structure status:
+ * -1 = unavailable
+ * 0 = not yet accessed
+ * 1 = available */
+ static struct VenusFid r;
+ static int w = 0;
+
+ switch (f) {
+ case -1:
+ if (vc->v.v_flag & VROOT) {
+ *rfid = 1;
+ return(1);
+ }
+ *rfid = 0;
+ return(0);
+ case 0:
+ if (get_Nl_value("arFid", Drive_Nl, &arFid) < 0 || !arFid) {
+ err = "no _afs_rootFid kernel address";
+
+rfid_unavailable:
+
+ if (!w && !Fwarn) {
+ (void) fprintf(stderr,
+ "%s: WARNING: AFS root Fid error: %s\n", Pn, err);
+ (void) fprintf(stderr,
+ " This may hamper AFS node number reporting.\n");
+ w = 1;
+ }
+ f = -1;
+ if (vc->v.v_flag & VROOT) {
+ *rfid = 1;
+ return(1);
+ }
+ *rfid = 0;
+ return(0);
+ }
+ if (kread((KA_T)arFid, (char *)&r, sizeof(r))) {
+ err = "can't read _afs_rootFid from kernel";
+ goto rfid_unavailable;
+ }
+ f = 1;
+ /* fall through */
+ case 1:
+ *rfid = 1;
+ if (vc->fid.Fid.Unique == r.Fid.Unique
+ && vc->fid.Fid.Vnode == r.Fid.Vnode
+ && vc->fid.Fid.Volume == r.Fid.Volume
+ && vc->fid.Cell == r.Cell)
+ return(1);
+ }
+ *rfid = 0;
+ return(0);
+}
+
+
+/*
+ * readafsnode() - read AFS node
+ */
+
+int
+readafsnode(va, v, an)
+ caddr_t va; /* kernel vnode address */
+ struct vnode *v; /* vnode buffer pointer */
+ struct afsnode *an; /* afsnode recipient */
+{
+ char *cp;
+ KA_T ka;
+ int len, rfid, vols;
+ struct vcache *vc;
+ struct volume *vp;
+
+ cp = ((char *)v + sizeof(struct vnode));
+ ka = (KA_T)((char *)va + sizeof(struct vnode));
+ len = sizeof(struct vcache) - sizeof(struct vnode);
+ if (kread(ka, cp, len)) {
+ (void) snpf(Namech, Namechl,
+ "vnode at %#x: can't read vcache remainder from %#x", va, ka);
+ enter_nm(Namech);
+ return(1);
+ }
+ vc = (struct vcache *)v;
+ an->dev = AFSDEV;
+ an->size = (unsigned long)vc->m.Length;
+ an->nlink = (long)vc->m.LinkCount;
+ an->nlink_st = 1;
+/*
+ * Manufacture the "inode" number.
+ */
+ if (vc->mvstat == 2) {
+ if ((vp = getvolume(&vc->fid, &vols))) {
+ an->inode = (INODETYPE)(vp->mtpoint.Fid.Vnode
+ + (vp->mtpoint.Fid.Volume << 16));
+ if (an->inode == (INODETYPE)0) {
+ if (is_rootFid(vc, &rfid))
+ an->ino_st = 1;
+ else if (rfid) {
+ an->inode = (INODETYPE)2;
+ an->ino_st = 1;
+ } else
+ an->ino_st = 0;
+ } else
+ an->ino_st = 1;
+ } else {
+ if (vols) {
+ an->inode = (INODETYPE)2;
+ an->ino_st = 1;
+ } else {
+ if (v->v_flag & VROOT) {
+ an->inode = (INODETYPE)0;
+ an->ino_st = 1;
+ } else
+ an->ino_st = 0;
+ }
+ }
+ } else {
+ an->inode = (INODETYPE)((vc->fid.Fid.Vnode
+ + (vc->fid.Fid.Volume << 16))
+ & 0x7fffffff);
+ an->ino_st = 1;
+ }
+ return(0);
+}
+#endif /* defined(HAS_AFS) */
diff --git a/dialects/n+os/dproc.c b/dialects/n+os/dproc.c
new file mode 100644
index 0000000..cb625b9
--- /dev/null
+++ b/dialects/n+os/dproc.c
@@ -0,0 +1,767 @@
+/*
+ * dproc.c - NEXTSTEP and OPENSTEP process access functions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dproc.c,v 1.12 2001/08/09 11:44:07 abe Exp $";
+#endif
+
+#include "lsof.h"
+
+
+/*
+ * Local static values
+ */
+
+static int Mxp = 0; /* maximum number of processes */
+static int Np; /* number of entries in P[] */
+static int Nv = 0; /* allocated Vp[] entries */
+static struct proc *P = (struct proc *)NULL;
+ /* local proc structure table */
+static KA_T *Pa = (KA_T *)NULL; /* kernel address for each P[] entry */
+static KA_T Kp; /* kernel process table pointer */
+static KA_T *Vp = (KA_T *)NULL; /* vnode address cache */
+
+
+_PROTOTYPE(static void get_kernel_access,(void));
+_PROTOTYPE(static void process_map,(caddr_t map));
+_PROTOTYPE(static void read_proc,(void));
+
+
+/*
+ * ckkv - check kernel version
+ */
+
+void
+ckkv(d, er, ev, ea)
+ char *d; /* dialect */
+ char *er; /* expected release */
+ char *ev; /* expected version */
+ char *ea; /* expected architecture */
+{
+
+#if defined(HASKERNIDCK)
+ char m[128], *t;
+ kernel_version_t kv;
+ kern_return_t kr;
+ char *vt = (char *)NULL;
+
+ if (Fwarn)
+ return;
+/*
+ * Read Mach kernel version.
+ */
+ if ((kr = host_kernel_version(host_self(), kv)) != KERN_SUCCESS) {
+ (void) snpf(m, sizeof(m), "%s: can't get kernel version:", Pn);
+ mach_error(m, kr);
+ Exit(1);
+ }
+/*
+ * Skip blank-separated tokens until reaching "Mach". The kernel version
+ * string follows. Eliminate anything but decimal digits and periods from
+ * the kernel version string.
+ */
+ if ((t = strtok(kv, " "))) {
+ do {
+ if (strcmp(t, "Mach") == 0)
+ break;
+ } while ((t = strtok((char *)NULL, " ")));
+ if (t)
+ vt = strtok((char *)NULL, " ");
+ }
+ if (vt) {
+ for (t = vt; *t; t++) {
+ if (*t == '.' || (*t >= '0' && *t <= '9'))
+ continue;
+ *t = '\0';
+ break;
+ }
+ }
+/*
+ * Warn if the actual and expected versions don't match.
+ */
+ if (!ev || !vt || strcmp(ev, vt))
+ (void) fprintf(stderr,
+ "%s: WARNING: compiled for %s version %s; this is %s\n",
+ Pn, d, ev ? ev : "UNKNOWN", vt ? vt : "UNKNOWN");
+#endif /* defined(HASKERNIDCK) */
+
+}
+
+
+/*
+ * gather_proc_info() -- gather process information
+ */
+
+void
+gather_proc_info()
+{
+ int i, nf, px;
+ MALLOC_S nb;
+ short pss, sf;
+ struct task { /* (Should come from <kern/task.h>.) */
+ caddr_t d1[SIMPLE_LOCK_SIZE + 2];
+ caddr_t map;
+ caddr_t d2[SIMPLE_LOCK_SIZE + 9];
+ struct utask *u_address;
+ struct proc *proc;
+ } t;
+ struct utask *u;
+ static struct file **uf = (struct file **)NULL;
+ static MALLOC_S ufb = 0;
+ struct utask ut;
+
+#if defined(HASFSTRUCT)
+ static char *pof = (char *)NULL;
+ static MALLOC_S pofb = 0;
+#endif /* defined(HASFSTRUCT) */
+
+
+/*
+ * Clear previously loaded tables and read the process table.
+ */
+
+#if STEPV>=31
+ (void) clr_svnc();
+#endif /* STEPV>=31 */
+
+ (void) read_proc();
+/*
+ * Process proc structures pre-loaded in initialize().
+ */
+ for (px = 0, u = &ut; px < Np; px++) {
+ if (is_proc_excl(P[px].p_pid, (int)P[px].p_pgrp,
+ (UID_ARG)P[px].p_uid, &pss, &sf))
+ continue;
+ /*
+ * Read the task associated with the process, and the user
+ * area assocated with the task.
+ */
+ if (kread((KA_T)P[px].task, (char *)&t, sizeof(t)))
+ continue;
+ if ((KA_T)t.proc != Pa[px])
+ continue;
+ if (kread((KA_T)t.u_address, (char *)&ut, sizeof(ut)))
+ continue;
+ if ((KA_T)ut.uu_procp != Pa[px])
+ continue;
+ /*
+ * Allocate a local process structure and start filling it.
+ */
+ if (is_cmd_excl(u->u_comm, &pss, &sf))
+ continue;
+ alloc_lproc(P[px].p_pid, (int)P[px].p_pgrp, (int)P[px].p_ppid,
+ (UID_ARG)P[px].p_uid, u->u_comm, (int)pss, (int)sf);
+ Plf = (struct lfile *)NULL;
+ /*
+ * Save current working directory information.
+ */
+ if (u->u_cdir) {
+ alloc_lfile(CWD, -1);
+ FILEPTR = (struct file *)NULL;
+ process_node((KA_T)u->u_cdir);
+ if (Lf->sf)
+ link_lfile();
+ }
+ /*
+ * Save root directory information.
+ */
+ if (u->u_rdir) {
+ alloc_lfile(RTD, -1);
+ FILEPTR = (struct file *)NULL;
+ process_node((KA_T)u->u_rdir);
+ if (Lf->sf)
+ link_lfile();
+ }
+ /*
+ * Print information on the text files of the virtual memory
+ * address map.
+ */
+ if (t.map)
+ process_map(t.map);
+ /*
+ * Save information on file descriptors.
+ *
+ * NEXTSTEP file pointers come from a structure whose pointer is
+ * in the user task area.
+ */
+ nf = ut.uu_ofile_cnt;
+ nb = (MALLOC_S)(sizeof(struct file *) * nf);
+ if (nb > ufb) {
+ if (!uf)
+ uf = (struct file **)malloc(nb);
+ else
+ uf = (struct file **)realloc((MALLOC_P *)uf, nb);
+ if (!uf) {
+ (void) fprintf(stderr, "%s: no uu_ofile space\n", Pn);
+ Exit(1);
+ }
+ ufb = nb;
+ }
+ if (kread((KA_T)ut.uu_ofile, (char *)uf, nb))
+ continue;
+
+#if defined(HASFSTRUCT)
+ if (Fsv & FSV_FG) {
+ nb = (MALLOC_S)(sizeof(char) * nf);
+ if (nb > pofb) {
+ if (!pof)
+ pof = (char *)malloc(nb);
+ else
+ pof = (char *)realloc((MALLOC_P *)pof, nb);
+ if (!pof) {
+ (void) fprintf(stderr, "%s: no uu_pofile space\n", Pn);
+ Exit(1);
+ }
+ pofb = nb;
+ }
+ if (kread((KA_T)ut.uu_pofile, (char *)pof, nb))
+ zeromem(pof, nb);
+ }
+#endif /* defined(HASFSTRUCT) */
+
+ for (i = 0; i < nf; i++) {
+ if (uf[i]) {
+ alloc_lfile((char *)NULL, i);
+ process_file((KA_T)uf[i]);
+ if (Lf->sf) {
+
+#if defined(HASFSTRUCT)
+ if (Fsv & FSV_FG)
+ Lf->pof = (long)pof[i];
+#endif /* defined(HASFSTRUCT) */
+
+ link_lfile();
+ }
+ }
+ }
+ /*
+ * Examine results.
+ */
+ if (examine_lproc())
+ return;
+ }
+}
+
+
+/*
+ * get_kernel_access() - access the required information in the kernel
+ */
+
+static void
+get_kernel_access()
+{
+ int i;
+ KA_T lv;
+
+#if defined(HAS_AFS)
+ struct nlist *nl = (struct nlist *)NULL;
+ unsigned long v[3];
+#endif /* defined(HAS_AFS) */
+
+/*
+ * Check kernel version against compiled version.
+ */
+ ckkv("NEXTSTEP", (char *)NULL, LSOF_VSTR, (char *)NULL);
+
+#if defined(WILLDROPGID)
+/*
+ * If kernel memory isn't coming from KMEM, drop setgid permission
+ * before attempting to open the (Memory) file.
+ */
+ if (Memory)
+ (void) dropgid();
+#else /* !defined(WILLDROPGID) */
+/*
+ * See if the non-KMEM memory file is readable.
+ */
+ if (Memory && !is_readable(Memory, 1))
+ Exit(1);
+#endif /* defined(WILLDROPGID) */
+
+/*
+ * Access the kernel memory file.
+ */
+ if ((Kd = open(Memory ? Memory : KMEM, O_RDONLY, 0)) < 0) {
+ (void) fprintf(stderr, "%s: can't open %s: %s\n", Pn,
+ Memory ? Memory : KMEM, strerror(errno));
+ Exit(1);
+ }
+
+#if defined(WILLDROPGID)
+/*
+ * Drop setgid permission, if necessary.
+ */
+ if (!Memory)
+ (void) dropgid();
+#else /* !defined(WILLDROPGID) */
+/*
+ * See if the name list file is readable. Build Nl.
+ */
+ if (Nmlst && !is_readable(Nmlst, 1))
+ Exit(1);
+#endif /* defined(WILLDROPGID) */
+
+ (void) build_Nl(Drive_Nl);
+
+#if defined(HAS_AFS)
+ if (!Nmlst) {
+
+ /*
+ * If AFS is defined and we're getting kernel symbol values from
+ * from N_UNIX, make a copy of Nl[] for possible use with the AFS
+ * module name list file.
+ */
+ if (!(nl = (struct nlist *)malloc(Nll))) {
+ (void) fprintf(stderr,
+ "%s: no space (%d) for Nl[] copy\n", Pn, Nll);
+ Exit(1);
+ }
+ (void) bcopy((char *)Nl, (char *)nl, Nll);
+ }
+#endif /* defined(HAS_AFS) */
+
+/*
+ * Access the name list file.
+ */
+ if (nlist(Nmlst ? Nmlst : VMUNIX, Nl) < 0) {
+ (void) fprintf(stderr, "%s: can't read namelist from %s\n",
+ Pn, Nmlst ? Nmlst : VMUNIX);
+ Exit(1);
+ }
+ if (get_Nl_value("aproc", Drive_Nl, &lv) < 0 || !lv) {
+ (void) fprintf(stderr, "%s: can't get proc table address\n",
+ Pn);
+ Exit(1);
+ }
+
+#if defined(HAS_AFS)
+ if (nl) {
+
+ /*
+ * If AFS is defined and we're getting kernel symbol values from
+ * N_UNIX, and if any X_AFS_* symbols isn't there, see if it is in the
+ * the AFS module name list file. Make sure that other symbols that
+ * appear in both name list files have the same values.
+ */
+ if (get_Nl_value("arFID", Drive_Nl, &v[0]) >= 0
+ && get_Nl_value("avol", Drive_Nl, &v[1]) >= 0
+ && get_Nl_value("avol", Drive_Nl, &v[2]) >= 0
+ && (!vo[0] || !v[1] || !v[2]))
+ (void) ckAFSsym(nl);
+ (void) free((MALLOC_P *)nl);
+ }
+#endif /* defined(HAS_AFS) */
+
+/*
+ * Establish a maximum process count estimate.
+ */
+ if (get_Nl_value("mxproc", Drive_Nl, &lv) < 0
+ || kread((KA_T)lv, (char *)&Mxp, sizeof(Mxp))
+ || Mxp < 1)
+ Mxp = PROCDFLT;
+}
+
+
+/*
+ * initialize() - perform all initialization
+ */
+
+void
+initialize()
+{
+ get_kernel_access();
+}
+
+
+/*
+ * kread() - read from kernel memory
+ */
+
+int
+kread(addr, buf, len)
+ KA_T addr; /* kernel memory address */
+ char *buf; /* buffer to receive data */
+ READLEN_T len; /* length to read */
+{
+ int br;
+
+ if (lseek(Kd, (off_t)addr, L_SET) == (off_t)-1L)
+ return(-1);
+ br = read(Kd, buf, len);
+ return((br == len) ? 0 : 1);
+}
+
+
+/*
+ * process_map() - process vm map for vnode references
+ */
+
+static void
+process_map(map)
+ caddr_t map;
+{
+ int i, j, n, ne;
+
+#if STEPV<40
+/*
+ * Structures for NeXTSTEP and OPENSTEP < 4.0.
+ */
+ struct vm_map_entry { /* (Should come from <vm/vm_map.h>). */
+ struct vm_map_entry *prev;
+ struct vm_map_entry *next;
+ unsigned int start;
+ unsigned int end;
+ caddr_t object;
+ unsigned int offset;
+ unsigned int
+ is_a_map:1,
+ is_sub_map:1,
+ copy_on_write:1,
+ needs_copy:1;
+ int protection;
+ int max_protection;
+ int inheritance;
+ int wired_count;
+ } vme, *vmep;
+
+#define VME_NEXT(entry) entry.next
+
+ struct vm_map { /* (Should come from <vm/vm_map.h>.) */
+ caddr_t d1[SIMPLE_LOCK_SIZE + 2];
+ struct vm_map_entry header;
+ int nentries;
+ caddr_t pmap;
+ unsigned int size;
+ boolean_t is_main_map;
+ } vmm;
+ struct vm_object { /* (Should come from <vm/vm_object.h>.) */
+ caddr_t d1[SIMPLE_LOCK_SIZE + 4];
+ unsigned int size;
+ short ref_count, resident_page_count;
+ caddr_t copy;
+ caddr_t pager;
+ int pager_request, pager_name;
+ unsigned int paging_offset;
+ caddr_t shadow;
+ } vmo, vmso;
+#else /* STEPV>=40 */
+/*
+ * Structures for OPENSTEP >= 4.0.
+ */
+ struct vm_map_links { /* (Should come from <vm/vm_map.h>). */
+ struct vm_map_entry *prev;
+ struct vm_map_entry *next;
+ unsigned int start;
+ unsigned int end;
+ };
+ struct vm_map_entry { /* (Should come from <vm/vm_map.h>). */
+ struct vm_map_links links;
+ caddr_t object;
+ unsigned int offset;
+ unsigned int
+ is_shared:1,
+ is_sub_map:1,
+ in_transition:1,
+ needs_wakeup:1,
+ behavior:2,
+ needs_copy:1,
+ protection:3,
+ max_protection:3,
+ inheritance:2,
+ pad1:1,
+ alias:8;
+ unsigned short wired_count;
+ unsigned short user_wired_count;
+ } vme, *vmep;
+
+#define VME_NEXT(entry) entry.links.next
+
+ struct vm_map_header { /* (Should come from <vm/vm_map.h>.) */
+ struct vm_map_links links;
+ int nentries;
+ int entries_pageable;
+ };
+ struct vm_map { /* (Should come from <vm/vm_map.h>.) */
+ caddr_t d1[SIMPLE_LOCK_SIZE + 2];
+ struct vm_map_header hdr;
+ caddr_t pmap;
+ unsigned int size;
+ boolean_t is_main_map; /* Darwin header has this as ref_count,
+ * but we'll take some liberties ... */
+ } vmm;
+ struct vm_object { /* (Should come from <vm/vm_object.h>.) */
+ caddr_t d1[SIMPLE_LOCK_SIZE + 4];
+ unsigned int size;
+ short ref_count, resident_page_count;
+ caddr_t copy;
+ caddr_t shadow;
+ unsigned int shadow_offset;
+ caddr_t pager;
+ unsigned int paging_offset;
+ int pager_request;
+ } vmo, vmso;
+#endif /* STEPV<40 */
+
+ struct vstruct { /* (Should come from <vm/vnode_pager.h>.) */
+ boolean_t is_device;
+ caddr_t vs_pf;
+ caddr_t pfMapEntry;
+ unsigned int vs_swapfile:1;
+ short vs_count;
+ int vs_size;
+ caddr_t vs_vp;
+ } vmp;
+/*
+ * Read the vm map.
+ */
+ if (!map
+ || kread((KA_T)map, (char *)&vmm, sizeof(vmm)))
+ return;
+ if (!vmm.is_main_map)
+ return;
+/*
+ * Look for non-map and non-sub-map vm map entries that have an object
+ * with a shadow whose pager pointer addresses a non-swap-file istruct
+ * that has a vnode pointer. Process the unique vnodes found.
+ */
+#if STEPV<40
+ vme = vmm.header;
+ ne = vmm.nentries;
+#else /* STEPV>=40 */
+ if (!vmm.hdr.links.next
+ || kread((KA_T)vmm.hdr.links.next, (char *)&vme, sizeof(vme)))
+ return;
+ ne = vmm.hdr.nentries;
+#endif /* STEPV<40 */
+
+ if (ne > 1000)
+ ne = 1000;
+ for (i = n = 0; i < ne; i++) {
+ if (i) {
+ if (!VME_NEXT(vme)
+ || kread((KA_T)VME_NEXT(vme), (char *)&vme, sizeof(vme)))
+ continue;
+ }
+
+#if STEPV<40
+ if (vme.is_a_map || vme.is_sub_map)
+#else /* STEPV>=40 */
+ if (vme.is_sub_map)
+#endif /* STEPV<40 */
+
+ continue;
+ if (!vme.object
+ || kread((KA_T)vme.object, (char *)&vmo, sizeof(vmo)))
+ continue;
+ if (!vmo.shadow
+ || kread((KA_T)vmo.shadow, (char *)&vmso, sizeof(vmso)))
+ continue;
+ if (!vmso.pager
+ || kread((KA_T)vmso.pager, (char *)&vmp, sizeof(vmp)))
+ continue;
+ if (vmp.is_device || vmp.vs_swapfile || !vmp.vs_vp)
+ continue;
+ /*
+ * See if the vnode has been processed before.
+ */
+ for (j = 0; j < n; j++) {
+ if ((KA_T)vmp.vs_vp == Vp[j])
+ break;
+ }
+ if (j < n)
+ continue;
+ /*
+ * Process a new vnode.
+ */
+ alloc_lfile("txt", -1);
+ FILEPTR = (struct file *)NULL;
+ process_node((KA_T)vmp.vs_vp);
+ if (Lf->sf)
+ link_lfile();
+ /*
+ * Allocate space for remembering the vnode.
+ */
+ if (!Vp) {
+ if (!(Vp = (KA_T *)malloc((MALLOC_S)
+ (sizeof(struct vnode *) * 10))))
+ {
+ (void) fprintf(stderr, "%s: no txt ptr space, PID %d\n",
+ Pn, Lp->pid);
+ Exit(1);
+ }
+ Nv = 10;
+ } else if (n >= Nv) {
+ Nv += 10;
+ if (!(Vp = (KA_T *)realloc((MALLOC_P *)Vp,
+ (MALLOC_S)(Nv * sizeof(struct vnode *)))))
+ {
+ (void) fprintf(stderr,
+ "%s: no more txt ptr space, PID %d\n", Pn, Lp->pid);
+ Exit(1);
+ }
+ }
+ Vp[n++] = (KA_T)vmp.vs_vp;
+ }
+}
+
+
+/*
+ * read_proc() - read proc structures
+ */
+
+static void
+read_proc()
+{
+ static KA_T apav = (KA_T)0;
+ static int apax = -1;
+ int i, try;
+ static int sz = 0;
+ KA_T kp;
+ struct proc *p;
+/*
+ * Try PROCTRYLM times to read a valid proc table.
+ */
+ for (try = 0; try < PROCTRYLM; try++) {
+
+ /*
+ * Read kernel's process list pointer. This needs to be done each
+ * time lsof rereads the process list.
+ */
+ if (apax < 0) {
+ if ((apax = get_Nl_value("aproc", Drive_Nl, &apav)) < 0) {
+ (void) fprintf(stderr,
+ "%s: can't get process table address pointer\n", Pn);
+ Exit(1);
+ }
+ }
+ if (kread((KA_T)apav, (char *)&Kp, sizeof(Kp))) {
+ if (!Fwarn)
+ (void) fprintf(stderr,
+ "%s: WARNING: can't read %s from %#x\n",
+ Pn, Nl[apax].n_un.n_name, apav);
+ continue;
+ }
+
+ /*
+ * Pre-allocate proc structure space.
+ */
+ if (sz == 0) {
+ sz = Mxp;
+ if (!(P = (struct proc *)malloc((MALLOC_S)
+ (sz * sizeof(struct proc)))))
+ {
+ (void) fprintf(stderr, "%s: no proc table space\n",
+ Pn);
+ Exit(1);
+ }
+ if (!(Pa = (KA_T *)malloc((MALLOC_S)(sz * sizeof(KA_T)))))
+ {
+ (void) fprintf(stderr, "%s: no proc pointer space\n",
+ Pn);
+ Exit(1);
+ }
+ }
+ /*
+ * Accumulate proc structures.
+ */
+ for (kp = Kp, Np = 0; kp; ) {
+ if (kread(kp, (char *)&P[Np], sizeof(struct proc))) {
+ Np = 0;
+ break;
+ }
+ Pa[Np] = kp;
+ kp = (KA_T)P[Np].p_nxt;
+ if (P[Np].p_stat == 0 || P[Np].p_stat == SZOMB)
+ continue;
+ Np++;
+ if (Np >= sz) {
+
+ /*
+ * Expand the local proc table.
+ */
+ sz += PROCDFLT/2;
+ if (!(P = (struct proc *)realloc((MALLOC_P *)P,
+ (MALLOC_S)(sizeof(struct proc) * sz))))
+ {
+ (void) fprintf(stderr,
+ "%s: no more (%d) proc space\n",
+ Pn, sz);
+ Exit(1);
+ }
+ if (!(Pa = (KA_T *)realloc((MALLOC_P *)Pa,
+ (MALLOC_S)(sizeof(KA_T) * sz))))
+ {
+ (void) fprintf(stderr,
+ "%s: no more (%d) proc ptr space\n",
+ Pn, sz);
+ Exit(1);
+ }
+ }
+ }
+ /*
+ * If not enough processes were saved in the local table, try again.
+ */
+ if (Np >= PROCMIN)
+ break;
+ }
+/*
+ * Quit if no proc structures were stored in the local table.
+ */
+ if (try >= PROCTRYLM) {
+ (void) fprintf(stderr, "%s: can't read proc table\n", Pn);
+ Exit(1);
+ }
+ if (Np < sz && !RptTm) {
+
+ /*
+ * Reduce the local proc structure table size to a minimum if
+ * not in repeat mode.
+ */
+ if (!(P = (struct proc *)realloc((MALLOC_P *)P,
+ (MALLOC_S)(sizeof(struct proc) * Np))))
+ {
+ (void) fprintf(stderr,
+ "%s: can't reduce proc table to %d\n",
+ Pn, Np);
+ Exit(1);
+ }
+ if (!(Pa = (KA_T *)realloc((MALLOC_P *)Pa,
+ (MALLOC_S)(sizeof(KA_T) * Np))))
+ {
+ (void) fprintf(stderr,
+ "%s: can't reduce proc ptrs to %d\n",
+ Pn, Np);
+ Exit(1);
+ }
+ }
+}
diff --git a/dialects/n+os/dproto.h b/dialects/n+os/dproto.h
new file mode 100644
index 0000000..19c1042
--- /dev/null
+++ b/dialects/n+os/dproto.h
@@ -0,0 +1,53 @@
+/*
+ * dproto.h - NEXTSTEP and OPENSTEP function prototypes for lsof
+ *
+ * The _PROTOTYPE macro is defined in the common proto.h.
+ */
+
+
+/*
+ * Copyright 1994 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.
+ */
+
+
+/*
+ * $Id: dproto.h,v 1.6 2001/08/09 11:44:07 abe Exp $
+ */
+
+
+#if STEPV>=31
+_PROTOTYPE(extern void clr_svnc,(void));
+#endif /* STEPV>=31 */
+
+_PROTOTYPE(extern int is_file_named,(char *p, int cd));
+
+#if defined(HAS_AFS)
+_PROTOTYPE(extern struct vnode *alloc_vcache,(void));
+_PROTOTYPE(extern void ckAFSsym,(struct nlist *nl));
+_PROTOTYPE(extern int hasAFS,(struct vnode *vp));
+_PROTOTYPE(extern void process_socket,(KA_T vp));
+_PROTOTYPE(extern int readafsnode,(caddr_t va, struct vnode *v, struct afsnode *
+an));
+#endif /* defined(HAS_AFS) */
diff --git a/dialects/n+os/dsock.c b/dialects/n+os/dsock.c
new file mode 100644
index 0000000..77d3b8a
--- /dev/null
+++ b/dialects/n+os/dsock.c
@@ -0,0 +1,306 @@
+/*
+ * dsock.c - NEXTSTEP and OPENSTEP socket processing functions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dsock.c,v 1.17 2005/08/08 19:54:03 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+/*
+ * process_socket() - process socket
+ */
+
+void
+process_socket(sa)
+ KA_T sa; /* socket address in kernel */
+{
+ struct domain d;
+ char *ep;
+ unsigned char *fa = (unsigned char *)NULL;
+ int fam;
+ int fp, lp;
+ struct inpcb inp;
+ unsigned char *la = (unsigned char *)NULL;
+ struct mbuf mb;
+ struct protosw p;
+ struct rawcb raw;
+ struct socket s;
+ size_t sz;
+ struct tcpcb t;
+ struct unpcb uc, unp;
+ struct sockaddr_un *ua = NULL;
+ struct sockaddr_un un;
+
+ (void) snpf(Lf->type, sizeof(Lf->type), "sock");
+ Lf->inp_ty = 2;
+/*
+ * Read socket structure.
+ */
+ if (!sa) {
+ enter_nm("no socket address");
+ return;
+ }
+ if (kread((KA_T) sa, (char *) &s, sizeof(s))) {
+ (void) snpf(Namech,Namechl,"can't read socket struct from %#x",sa);
+ enter_nm(Namech);
+ return;
+ }
+ if (!s.so_type) {
+ enter_nm("no socket type");
+ return;
+ }
+/*
+ * Read protocol switch and domain structures.
+ */
+ if (!s.so_proto
+ || kread((KA_T) s.so_proto, (char *) &p, sizeof(p))) {
+ (void) snpf(Namech, Namechl, "no protocol switch");
+ enter_nm(Namech);
+ return;
+ }
+ if (kread((KA_T) p.pr_domain, (char *) &d, sizeof(d))) {
+ (void) snpf(Namech, Namechl, "can't read domain struct from %s",
+ print_kptr((KA_T)p.pr_domain, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+/*
+ * Save size information.
+ */
+ if (Fsize) {
+ if (Lf->access == 'r')
+ Lf->sz = (SZOFFTYPE)s.so_rcv.sb_cc;
+ else if (Lf->access == 'w')
+ Lf->sz = (SZOFFTYPE)s.so_snd.sb_cc;
+ else
+ Lf->sz = (SZOFFTYPE)(s.so_rcv.sb_cc + s.so_snd.sb_cc);
+ Lf->sz_def = 1;
+ } else
+ Lf->off_def = 1;
+
+#if defined(HASTCPTPIQ)
+ Lf->lts.rq = (unsigned long)s.so_rcv.sb_cc;
+ Lf->lts.sq = (unsigned long)s.so_snd.sb_cc;
+ Lf->lts.rqs = Lf->lts.sqs = 1;
+#endif /* defined(HASTCPTPIQ) */
+
+#if defined(HASSOOPT)
+ Lf->lts.ltm = (unsigned int)s.so_linger;
+ Lf->lts.opt = (unsigned int)s.so_options;
+ Lf->lts.pqlen = (unsigned int)s.so_q0len;
+ Lf->lts.qlen = (unsigned int)s.so_qlen;
+ Lf->lts.qlim = (unsigned int)s.so_qlimit;
+ Lf->lts.rbsz = (unsigned long)s.so_rcv.sb_mbmax;
+ Lf->lts.sbsz = (unsigned long)s.so_snd.sb_mbmax;
+ Lf->lts.pqlens = Lf->lts.qlens = Lf->lts.qlims = Lf->lts.rbszs
+ = Lf->lts.sbszs = (unsigned char)1;
+#endif /* defined(HASSOOPT) */
+
+#if defined(HASSOSTATE)
+ Lf->lts.ss = (unsigned int)s.so_state;
+#endif /* defined(HASSOSTATE) */
+
+/*
+ * Process socket by the associated domain family.
+ */
+ switch ((fam = d.dom_family)) {
+/*
+ * Process an Internet domain socket.
+ */
+ case AF_INET:
+ if (Fnet)
+ Lf->sf |= SELNET;
+ (void) snpf(Lf->type, sizeof(Lf->type), "inet");
+ printiproto(p.pr_protocol);
+ /*
+ * Read protocol control block.
+ */
+ if (!s.so_pcb) {
+ (void) snpf(Namech, Namechl, "no PCB%s%s",
+ (s.so_state & SS_CANTSENDMORE) ? ", CANTSENDMORE" : "",
+ (s.so_state & SS_CANTRCVMORE) ? ", CANTRCVMORE" : "");
+ enter_nm(Namech);
+ return;
+ }
+ if (s.so_type == SOCK_RAW) {
+
+ /*
+ * Print raw socket information.
+ */
+ if (kread((KA_T) s.so_pcb, (char *)&raw, sizeof(raw))
+ || (struct socket *)sa != raw.rcb_socket) {
+ (void) snpf(Namech, Namechl, "can't read rawcb at %s",
+ print_kptr((KA_T)s.so_pcb, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ enter_dev_ch(print_kptr((KA_T)(raw.rcb_pcb ? raw.rcb_pcb
+ : s.so_pcb),
+ (char *)NULL, 0));
+ if (raw.rcb_laddr.sa_family == AF_INET)
+ la = (unsigned char *)&raw.rcb_laddr.sa_data[2];
+ else if (raw.rcb_laddr.sa_family)
+ printrawaddr(&raw.rcb_laddr);
+ if (raw.rcb_faddr.sa_family == AF_INET)
+ fa = (unsigned char *)&raw.rcb_faddr.sa_data[2];
+ else if (raw.rcb_faddr.sa_family) {
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "->");
+ printrawaddr(&raw.rcb_faddr);
+ }
+ if (fa || la)
+ (void) ent_inaddr(la, -1, fa, -1, AF_INET);
+ } else {
+
+ /*
+ * Print Internet socket information.
+ */
+ if (kread((KA_T)s.so_pcb, (char *) &inp, sizeof(inp))
+ || (struct socket *)sa != inp.inp_socket) {
+ (void) snpf(Namech, Namechl, "can't read inpcb at %s",
+ print_kptr((KA_T)s.so_pcb, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ enter_dev_ch(print_kptr((KA_T)(inp.inp_ppcb ? inp.inp_ppcb
+ : s.so_pcb),
+ (char *)NULL, 0));
+ /*
+ * If the protocol is TCP, try to read the TCP protocol
+ * control block to record its state.
+ */
+ if (p.pr_protocol == IPPROTO_TCP
+ && inp.inp_ppcb
+ && kread((KA_T)inp.inp_ppcb, (char *)&t, sizeof(t)) == 0) {
+ Lf->lts.type = 0;
+ Lf->lts.state.i = (int)t.t_state;
+
+#if defined(HASTCPOPT)
+ Lf->lts.mss = (unsigned long)t.t_maxseg;
+ Lf->lts.msss = (unsigned char)1;
+ Lf->lts.topt = (unsigned int)t.t_flags;
+#endif /* defined(HASTCPOPT) */
+
+ }
+ /*
+ * Process the local and foreign addresses from the Internet
+ * control block.
+ */
+ la = (unsigned char *)&inp.inp_laddr;
+ lp = (int)ntohs(inp.inp_lport);
+ if (inp.inp_faddr.s_addr != INADDR_ANY || inp.inp_fport != 0) {
+ fa = (unsigned char *)&inp.inp_faddr;
+ fp = (int)ntohs(inp.inp_fport);
+ }
+ if (fa || la)
+ (void) ent_inaddr(la, lp, fa, fp, AF_INET);
+ }
+ break;
+/*
+ * Process a Unix domain socket.
+ */
+ case AF_UNIX:
+ if (Funix)
+ Lf->sf |= SELUNX;
+ (void) snpf(Lf->type, sizeof(Lf->type), "unix");
+ /*
+ * Read Unix protocol control block and the Unix address structure.
+ */
+ enter_dev_ch(print_kptr(sa, (char *)NULL, 0));
+ if (kread((KA_T) s.so_pcb, (char *) &unp, sizeof(unp))) {
+ (void) snpf(Namech, Namechl, "can't read unpcb at %s",
+ print_kptr((KA_T)s.so_pcb, (char *)NULL, 0));
+ break;
+ }
+ if ((struct socket *)sa != unp.unp_socket) {
+ (void) snpf(Namech, Namechl, "unp_socket (%s) mismatch",
+ print_kptr((KA_T)unp.unp_socket, (char *)NULL, 0));
+ break;
+ }
+ if (unp.unp_addr) {
+ if (kread((KA_T) unp.unp_addr, (char *) &mb, sizeof(mb))) {
+ (void) snpf(Namech, Namechl, "can't read unp_addr at %s",
+ print_kptr((KA_T)unp.unp_addr, (char *)NULL, 0));
+ break;
+ }
+ ua = (struct sockaddr_un *)(((char *)&mb) + mb.m_off);
+ }
+ if (!ua) {
+ ua = &un;
+ (void) bzero((char *)ua, sizeof(un));
+ ua->sun_family = AF_UNSPEC;
+ }
+ /*
+ * Print information on Unix socket that has no address bound
+ * to it, although it may be connected to another Unix domain
+ * socket as a pipe.
+ */
+ if (ua->sun_family != AF_UNIX) {
+ if (ua->sun_family == AF_UNSPEC) {
+ if (unp.unp_conn) {
+ if (kread((KA_T)unp.unp_conn, (char *) &uc, sizeof(uc)))
+ {
+ (void) snpf(Namech, Namechl,
+ "can't read unp_conn at %s",
+ print_kptr((KA_T)unp.unp_conn,(char *)NULL,0));
+ } else {
+ (void) snpf(Namech, Namechl, "->%s",
+ print_kptr((KA_T)uc.unp_socket,(char *)NULL,0));
+ }
+ } else
+ (void) snpf(Namech, Namechl, "->(none)");
+ } else
+ (void) snpf(Namech, Namechl, "unknown sun_family (%d)",
+ ua->sun_family);
+ break;
+ }
+ if (ua->sun_path[0]) {
+ if (mb.m_len >= sizeof(struct sockaddr_un))
+ mb.m_len = sizeof(struct sockaddr_un) - 1;
+ *((char *)ua + mb.m_len) = '\0';
+ if (Sfile && is_file_named(ua->sun_path, 0))
+ Lf->sf |= SELNM;
+ if (!Namech[0])
+ (void) snpf(Namech, Namechl, "%s", ua->sun_path);
+ } else
+ (void) snpf(Namech, Namechl, "no address");
+ break;
+ default:
+ printunkaf(fam, 1);
+ }
+ if (Namech[0])
+ enter_nm(Namech);
+}
diff --git a/dialects/n+os/dstore.c b/dialects/n+os/dstore.c
new file mode 100644
index 0000000..b250fde
--- /dev/null
+++ b/dialects/n+os/dstore.c
@@ -0,0 +1,133 @@
+/*
+ * dstore.c - NEXTSTEP and OPENSTEP global storage for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dstore.c,v 1.10 2001/08/09 11:44:07 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+/*
+ * Global storage definitions
+ */
+
+#if defined(HAS_AFS)
+
+# if defined(HASAOPT)
+char *AFSApath = (char *)NULL; /* alternate AFS name list path
+ * (from -a) */
+# endif /* defined(HASAOPT) */
+
+struct vfs *AFSVfsp = (struct vfs *)NULL;
+ /* AFS vfs struct kernel address */
+#endif /* defined(HAS_AFS) */
+
+/*
+ * Drive_Nl -- table to drive the building of Nl[] via build_Nl()
+ * (See lsof.h and misc.c.)
+ */
+
+struct drive_Nl Drive_Nl[] = {
+ { "arFid", "_afs_rootFid" },
+ { "avops", "_afs_vnodeops" },
+ { "avol", "_afs_volumes" },
+ { "aproc", "_allproc" },
+ { "fvops", "_fifo_vnodeops" },
+ { "lfsvh", "_lf_svnode_hash" },
+ { "mxproc", "_max_proc" },
+
+#if defined(X_NCACHE)
+ { X_NCACHE, "_ncache" },
+#endif /* defined(X_NCACHE) */
+
+#if defined(X_NCSIZE)
+ { X_NCSIZE, "_ncsize" },
+#endif /* defined(X_NCSIZE) */
+
+ { "nvops", "_nfs_vnodeops" },
+ { "svops", "_spec_vnodeops" },
+ { "uvops", "_ufs_vnodeops" },
+ { "", "", },
+ { NULL, NULL },
+};
+
+struct file *Fileptr; /* for process_file() in lib/prfp.c */
+int Kd = -1; /* /dev/kmem file descriptor */
+
+#if defined(HASFSTRUCT)
+/*
+ * Pff_tab[] - table for printing file flags
+ */
+
+struct pff_tab Pff_tab[] = {
+ { (long)FREAD, FF_READ },
+ { (long)FWRITE, FF_WRITE },
+ { (long)FNDELAY, FF_NDELAY },
+ { (long)FAPPEND, FF_APPEND },
+ { (long)FASYNC, FF_ASYNC },
+ { (long)FMARK, FF_MARK },
+ { (long)FDEFER, FF_DEFER },
+ { (long)FSHLOCK, FF_SHLOCK },
+ { (long)FEXLOCK, FF_EXLOCK },
+
+#if defined(POSIX_KERN)
+ { (long)FPOSIX_PIPE, FF_POSIX_PIPE },
+#endif /* defined(POSIX_KERN) */
+
+ { (long)0, NULL }
+};
+
+
+/*
+ * Pof_tab[] - table for print process open file flags
+ */
+
+struct pff_tab Pof_tab[] = {
+
+# if defined(UF_EXCLOSE)
+ { (long)UF_EXCLOSE, POF_CLOEXEC },
+# endif /* defined(UF_EXCLOSE) */
+
+# if defined(UF_MAPPED)
+ { (long)UF_MAPPED, POF_MAPPED },
+# endif /* defined(UF_MAPPED) */
+
+# if defined(UF_FDLOCK)
+ { (long)UF_FDLOCK, POF_FDLOCK },
+# endif /* defined(UF_FDLOCK) */
+
+ { (long)0, NULL }
+};
+#endif /* defined(HASFSTRUCT) */
diff --git a/dialects/n+os/machine.h b/dialects/n+os/machine.h
new file mode 100644
index 0000000..9119ab6
--- /dev/null
+++ b/dialects/n+os/machine.h
@@ -0,0 +1,615 @@
+/*
+ * machine.h - NEXTSTEP and OPENSTEP definitions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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.
+ */
+
+
+/*
+ * $Id: machine.h,v 1.37 2010/07/29 16:02:55 abe Exp $
+ */
+
+
+#if !defined(LSOF_MACHINE_H)
+#define LSOF_MACHINE_H 1
+
+
+#include <sys/types.h>
+
+
+/*
+ * CAN_USE_CLNT_CREATE is defined for those dialects where RPC clnt_create()
+ * can be used to obtain a CLIENT handle in lieu of clnttcp_create().
+ */
+
+#define CAN_USE_CLNT_CREATE 1
+
+
+/*
+ * DEVDEV_PATH defines the path to the directory that contains device
+ * nodes.
+ */
+
+#define DEVDEV_PATH "/dev"
+
+
+/*
+ * GET_MAX_FD is defined for those dialects that provide a function other than
+ * getdtablesize() to obtain the maximum file descriptor number plus one.
+ */
+
+/* #define GET_MAX_FD ? */
+
+
+/*
+ * HASAOPT is defined for those dialects that have AFS support; it specifies
+ * that the default path to an alternate AFS kernel name list file may be
+ * supplied with the -A <path> option.
+ */
+
+#define HASAOPT 1
+
+
+/*
+ * HASBLKDEV is defined for those dialects that want block device information
+ * recorded in BDevtp[].
+ */
+
+#define HASBLKDEV 1
+
+
+/*
+ * HASDCACHE is defined for those dialects that support a device cache
+ * file.
+ *
+ * HASENVDC defined the name of an environment variable that contains the
+ * device cache file path. The HASENVDC environment variable is ignored when
+ * the lsof process is setuid(root) or its real UID is 0.
+ *
+ * HASPERSDC defines the format for the last component of a personal device
+ * cache file path. The first will be the home directory of the real UID that
+ * executes lsof.
+ *
+ * HASPERSDCPATH defines the environment variable whose value is the middle
+ * component of the personal device cache file path. The middle component
+ * follows the home directory and precedes the results of applying HASPERSDC.
+ * The HASPERSDCPATH environment variable is ignored when the lsof process is
+ * setuid(root) or its real UID is 0.
+ *
+ * HASSYSDC defines a public device cache file path. When it's defined, it's
+ * used as the path from which to read the device cache.
+ *
+ * Consult the 00DCACHE and 00FAQ files of the lsof distribution for more
+ * information on device cache file path construction.
+ */
+
+#define HASDCACHE 1
+#define HASENVDC "LSOFDEVCACHE"
+#define HASPERSDC "%h/%p.lsof_%L"
+#define HASPERSDCPATH "LSOFPERSDCPATH"
+/* #define HASSYSDC "/your/choice/of/path" */
+
+
+/*
+ * HASCDRNODE is defined for those dialects that have CD-ROM nodes.
+ */
+
+/* #define HASCDRNODE 1 */
+
+
+/*
+ * HASFIFONODE is defined for those dialects that have FIFO nodes.
+ */
+
+/* #define HASFIFONODE 1 */
+
+
+/*
+ * HASFSINO is defined for those dialects that have the file system
+ * inode element, fs_ino, in the lfile structure definition in lsof.h.
+ */
+
+#define HASFSINO 1
+
+
+/*
+ * HASFSTRUCT is defined if the dialect has a file structure.
+ *
+ * FSV_DEFAULT defines the default set of file structure values to list.
+ * It defaults to zero (0), but may be made up of a combination of the
+ * FSV_* symbols from lsof.h.
+ *
+ * HASNOFSADDR -- has no file structure address
+ * HASNOFSFLAGS -- has no file structure flags
+ * HASNOFSCOUNT -- has no file structure count
+ * HASNOFSNADDR -- has no file structure node address
+ */
+
+#define HASFSTRUCT 1
+/* #define FSV_DEFAULT FSV_? | FSV_? | FSV_? */
+/* #define HASNOFSADDR 1 has no file structure address */
+/* #define HASNOFSFLAGS 1 has no file structure flags */
+/* #define HASNOFSCOUNT 1 has no file structure count */
+/* #define HASNOFSNADDR 1 has no file structure node address */
+
+
+/*
+ * HASGNODE is defined for those dialects that have gnodes.
+ */
+
+/* #define HASGNODE 1 */
+
+
+/*
+ * HASHSNODE is defined for those dialects that have High Sierra nodes.
+ */
+
+/* #define HASHSNODE 1 */
+
+
+/*
+ * HASINODE is defined for those dialects that have inodes and wish to
+ * use readinode() from node.c.
+ */
+
+#define HASINODE 1
+
+
+/*
+ * HASINTSIGNAL is defined for those dialects whose signal function returns
+ * an int.
+ */
+
+/* #define HASINTSIGNAL 1 */
+
+
+/*
+ * HASKERNIDCK is defined for those dialects that support the comparison of
+ * the build to running kernel identity.
+ */
+
+#define HASKERNIDCK 1
+
+
+/*
+ * HASKOPT is defined for those dialects that support the -k option of
+ * reading the kernel's name list from an optional file.
+ */
+
+#define HASKOPT 1
+
+
+/*
+ * HASLFILEADD is defined for those dialects that need additional elements
+ * in struct lfile. The HASLFILEADD definition is a macro that defines
+ * them. If any of the additional elements need to be preset in the
+ * alloc_lfile() function of proc.c, the SETLFILEADD macro may be defined
+ * to do that.
+ *
+ * If any additional elements need to be cleared in alloc_lfile() or in the
+ * free_proc() function of proc.c, the CLRLFILEADD macro may be defined to
+ * do that. Note that CLRLFILEADD takes one argument, the pointer to the
+ * lfile struct. The CLRLFILEADD macro is expected to expand to statements
+ * that are complete -- i.e., have terminating semi-colons -- so the macro is
+ * called without a terminating semicolon by proc.c.
+ *
+ * The HASXOPT definition may be used to select the conditions under which
+ * private lfile elements are used.
+ */
+
+/* #define HASLFILEADD int ... */
+/* #define CLRLFILEADD(lf) (lf)->... = (type)NULL; */
+/* #define SETLFILEADD Lf->... */
+
+
+/*
+ * HASMNTSTAT indicates the dialect supports the mount stat(2) result option
+ * in its l_vfs and mounts structures.
+ */
+
+/* #define HASMNTSTAT 1 */
+
+
+/*
+ * HASMNTSUP is defined for those dialects that support the mount supplement
+ * option.
+ */
+
+/* #define HASMNTSUP 1 */
+
+
+/*
+ * HASMOPT is defined for those dialects that support the reading of
+ * kernel memory from an alternate file.
+ */
+
+#define HASMOPT 1
+
+
+/*
+ * HASNCACHE is defined for those dialects that have a kernel name cache
+ * that lsof can search. A value of 1 directs printname() to prefix the
+ * cache value with the file system directory name; 2, avoid the prefix.
+ *
+ * NCACHELDPFX is a set of C commands to execute before calling ncache_load().
+ *
+ * NCACHELDSFX is a set of C commands to execute after calling ncache_load().
+ */
+
+#define HASNCACHE 1
+/* #define NCACHELDPFX ??? */
+/* #define NCACHELDSFX ??? */
+
+
+/*
+ * HASNLIST is defined for those dialects that use nlist() to acccess
+ * kernel symbols.
+ */
+
+#define HASNLIST 1
+
+
+/*
+ * HASPIPEFN is defined for those dialects that have a special function to
+ * process DTYPE_PIPE file structure entries. Its value is the name of the
+ * function.
+ *
+ * NOTE: don't forget to define a prototype for this function in dproto.h.
+ */
+
+/* #define HASPIPEFN process_pipe? */
+
+
+/*
+ * HASPIPENODE is defined for those dialects that have pipe nodes.
+ */
+
+/* #define HASPIPENODE 1 */
+
+
+/*
+ * HASPMAPENABLED is defined when the reporting of portmapper registration
+ * info is enabled by default.
+ */
+
+/* #define HASPMAPENABLED 1 */
+
+
+/*
+ * HASPPID is defined for those dialects that support identification of
+ * the parent process IDentifier (PPID) of a process.
+ */
+
+#define HASPPID 1
+
+
+/*
+ * HASPRINTDEV, HASPRINTINO, HASPRINTNM, HASPRINTOFF, and HASPRINTSZ
+ * define private dialect-specific functions for printing DEVice numbers,
+ * INOde numbers, NaMes, file OFFsets, and file SiZes. The functions are
+ * called from print_file().
+ */
+
+/* #define HASPRINTDEV print_dev? */
+/* #define HASPRINTINO print_ino? */
+/* #define HASPRINTNM print_nm? */
+/* #define HASPRINTOFF print_off? */
+/* #define HASPRINTSZ print_sz? */
+
+
+/*
+ * HASPRIVFILETYPE and PRIVFILETYPE are defined for dialects that have a
+ * file structure type that isn't defined by a DTYPE_* symbol. They are
+ * used in lib/prfp.c to select the type's processing.
+ *
+ * PRIVFILETYPE is the definition of the f_type value in the file struct.
+ *
+ * HASPRIVFILETYPE is the name of the processing function.
+ */
+
+/* #define HASPRIVFILETYPE process_shmf? */
+/* #define PRIVFILETYPE ?? */
+
+
+/*
+ * HASPRIVNMCACHE is defined for dialects that have a private method for
+ * printing cached NAME column values for some files. HASPRIVNAMECACHE
+ * is defined to be the name of the function.
+ *
+ * The function takes one argument, a struct lfile pointer to the file, and
+ * returns non-zero if it prints a name to stdout.
+ */
+
+/* #define HASPRIVNMCACHE <function name> */
+
+
+/*
+ * HASPRIVPRIPP is defined for dialects that have a private function for
+ * printing IP protocol names. When HASPRIVPRIPP isn't defined, the
+ * IP protocol name printing function defaults to printiprto().
+ */
+
+/* #define HASPRIVPRIPP 1 */
+
+
+/*
+ * HASPROCFS is defined for those dialects that have a proc file system --
+ * usually /proc and usually in SYSV4 derivatives.
+ *
+ * HASFSTYPE is defined as 1 for those systems that have a file system type
+ * string, st_fstype, in the stat() buffer; 2, for those systems that have a
+ * file system type integer in the stat() buffer, named MOUNTS_STAT_FSTYPE;
+ * 0, for systems whose stat(2) structure has no file system type member. The
+ * additional symbols MOUNTS_FSTYPE, RMNT_FSTYPE, and RMNT_STAT_FSTYPE may be
+ * defined in dlsof.h to direct how the readmnt() function in lib/rmnt.c
+ * preserves these stat(2) and getmntent(3) buffer values in the local mounts
+ * structure.
+ *
+ * The defined value is the string that names the file system type.
+ *
+ * The HASPROCFS definition usually must be accompanied by the HASFSTYPE
+ * definition and the providing of an fstype element in the local mounts
+ * structure (defined in dlsof.h).
+ *
+ * The HASPROCFS definition may be accompanied by the HASPINODEN definition.
+ * HASPINODEN specifies that searching for files in HASPROCFS is to be done
+ * by inode number.
+ */
+
+/* #define HASPROCFS "proc?" */
+/* #define HASFSTYPE 1 */
+/* #define HASPINODEN 1 */
+
+
+/*
+ * HASRNODE is defined for those dialects that have rnodes.
+ */
+
+#define HASRNODE 1
+
+
+/*
+ * Define HASSECURITY to restrict the listing of all open files to the
+ * root user. When HASSECURITY is defined, the non-root user may list
+ * only files whose processes have the same user ID as the real user ID
+ * (the one that its user logged on with) of the lsof process.
+ */
+
+/* #define HASSECURITY 1 */
+
+
+/*
+ * If HASSECURITY is defined, define HASNOSOCKSECURITY to allow users
+ * restricted by HASSECURITY to list any open socket files, provide their
+ * listing is selected by the "-i" option.
+ */
+
+/* #define HASNOSOCKSECURITY 1 */
+
+
+/*
+ * HASSETLOCALE is defined for those dialects that have <locale.h> and
+ * setlocale().
+ *
+ * If the dialect also has wide character support for language locales,
+ * HASWIDECHAR activates lsof's wide character support and WIDECHARINCL
+ * defines the header file (if any) that must be #include'd to use the
+ * mblen() and mbtowc() functions.
+ */
+
+#define HASSETLOCALE 1
+/* #define HASWIDECHAR 1 */
+/* #define WIDECHARINCL <wchar.h> */
+
+
+/*
+ * HASSNODE is defined for those dialects that have snodes.
+ */
+
+#define HASSNODE 1
+
+
+/*
+ * HASTASKS is defined for those dialects that have task reporting support.
+ */
+
+/* #define HASTASKS 1 */
+
+
+/*
+ * HASSOOPT, HASSOSTATE and HASTCPOPT define the availability of information
+ * on socket options (SO_* symbols), socket states (SS_* symbols) and TCP
+ * options.
+ */
+
+#define HASSOOPT 1 /* has socket option information */
+#define HASSOSTATE 1 /* has socket state information */
+#define HASTCPOPT 1 /* has TCP options or flags */
+
+
+/*
+ * Define HASSPECDEVD to be the name of a function that handles the results
+ * of a successful stat(2) of a file name argument.
+ *
+ * For example, HASSPECDEVD() for Darwin makes sure that st_dev is set to
+ * what stat("/dev") returns -- i.e., what's in DevDev.
+ *
+ * The function takes two arguments:
+ *
+ * 1: pointer to the full path name of file
+ * 2: pointer to the stat(2) result
+ *
+ * The function returns void.
+ */
+
+/* #define HASSPECDEVD process_dev_stat */
+
+
+/*
+ * HASSTREAMS is defined for those dialects that support streams.
+ */
+
+/* #define HASSTREAMS 1 */
+
+
+/*
+ * HASTCPTPIQ is defined for dialects where it is possible to report the
+ * TCP/TPI Recv-Q and Send-Q values produced by netstat.
+ */
+
+#define HASTCPTPIQ 1
+
+
+/*
+ * HASTCPTPIW is defined for dialects where it is possible to report the
+ * TCP/TPI send and receive window sizes produced by netstat.
+ */
+
+/* #define HASTCPTPIW 1 */
+
+
+/*
+ * HASTMPNODE is defined for those dialects that have tmpnodes.
+ */
+
+/* #define HASTMPNODE 1 */
+
+
+/*
+ * HASVNODE is defined for those dialects that use the Sun virtual file
+ * system node, the vnode. BSD derivatives usually do; System V derivatives
+ * prior to R4 usually don't.
+ */
+
+#define HASVNODE 1
+
+
+/*
+ * HASXOPT is defined for those dialects that have an X option. It
+ * defines the text for the usage display. HASXOPT_VALUE defines the
+ * option's default binary value -- 0 or 1.
+ */
+
+/* #define HASXOPT "help text for X option" */
+/* #define HASXOPT_VALUE 1 */
+
+
+/*
+ * INODETYPE and INODEPSPEC define the internal node number type and its
+ * printf specification modifier. These need not be defined and lsof.h
+ * can be allowed to define defaults.
+ *
+ * These are defined here, because they must be used in dlsof.h.
+ */
+
+/* #define INODETYPE unsigned long long */
+ /* inode number internal storage type */
+/* #define INODEPSPEC "ll" * INODETYPE printf specification
+ * modifier */
+
+
+# if !defined(MACH)
+/*
+ * The definition of MACH for NEXTSTEP is required for proper header
+ * file configuration -- i. e., some header files have ``#ifdef MACH''
+ * statements that affect the size of kernel structures.
+ */
+
+#define MACH 1
+# endif
+
+
+/*
+ * UID_ARG defines the size of a User ID number when it is passed
+ * as a function argument.
+ */
+
+#define UID_ARG int
+
+
+/*
+ * Each USE_LIB_<function_name> is defined for dialects that use the
+ * <function_name> in the lsof library.
+ *
+ * Note: other definitions and operations may be required to condition the
+ * library function source code. They may be found in the dialect dlsof.h
+ * header files.
+ */
+
+/* #define USE_LIB_CKKV 1 ckkv.c */
+/* #define USE_LIB_COMPLETEVFS 1 cvfs.c */
+#define USE_LIB_FIND_CH_INO 1 /* fino.c */
+#define USE_LIB_IS_FILE_NAMED 1 /* isfn.c */
+#define USE_LIB_LKUPDEV 1 /* lkud.c */
+#define USE_LIB_PRINTDEVNAME 1 /* pdvn.c */
+#define USE_LIB_PROCESS_FILE 1 /* prfp.c */
+#define USE_LIB_PRINT_TCPTPI 1 /* ptti.c */
+#define USE_LIB_READDEV 1 /* rdev.c */
+#define USE_LIB_READMNT 1 /* rmnt.c */
+#define USE_LIB_REGEX 1 /* regex.c */
+/* #define USE_LIB_RNAM 1 rnam.c */
+#define USE_LIB_RNCH 1 /* rnch.c */
+/* #define USE_LIB_RNMH 1 rnmh.c */
+#define HAS_NO_LONG_LONG 1 /* disable snpf()'s
+ * long long support */
+#define USE_LIB_SNPF 1 /* snpf.c */
+
+
+/*
+ * WARNDEVACCESS is defined for those dialects that should issue a warning
+ * when lsof can't access /dev (or /device) or one of its sub-directories.
+ * The warning can be inhibited by the lsof caller with the -w option.
+ */
+
+#define WARNDEVACCESS 1
+
+
+/*
+ * WARNINGSTATE is defined for those dialects that want to suppress all lsof
+ * warning messages.
+ */
+
+/* #define WARNINGSTATE 1 warnings are enabled by default */
+
+
+/*
+ * WILLDROPGID is defined for those dialects whose lsof executable runs
+ * setgid(not_real_GID) and whose setgid power can be relinquished after
+ * the dialect's initialize() function has been executed.
+ */
+
+#define WILLDROPGID 1
+
+
+/*
+ * zeromem is a macro that uses bzero or memset.
+ */
+
+#define zeromem(a, l) bzero(a, l)
+
+#endif /* !defined(LSOF_MACHINE_H) */
diff --git a/dialects/osr/Makefile b/dialects/osr/Makefile
new file mode 100644
index 0000000..d9e1591
--- /dev/null
+++ b/dialects/osr/Makefile
@@ -0,0 +1,165 @@
+
+# OSR Makefile
+#
+# $Id: Makefile,v 1.12 2008/04/15 13:30:40 abe Exp $
+
+PROG= lsof
+
+BIN= ${DESTDIR}
+
+DOC= ${DESTDIR}
+
+I=/usr/include
+S=/usr/include/sys
+L=/usr/include/local
+P=
+
+CDEF=
+CDEFS= ${CDEF} ${CFGF}
+INCL= ${DINC}
+CFLAGS= ${CDEFS} ${INCL} ${DEBUG}
+
+GRP=
+
+HDR= lsof.h lsof_fields.h dlsof.h machine.h proto.h dproto.h
+
+MODE= 2755
+
+OWN= bin
+
+SRC= dfile.c dmnt.c dnode.c dproc.c dsock.c dstore.c \
+ arg.c main.c misc.c node.c print.c proc.c store.c usage.c \
+ util.c
+
+OBJ= dfile.o dmnt.o dnode.o dproc.o dsock.o dstore.o \
+ arg.o main.o misc.o node.o print.o proc.o store.o usage.o \
+ util.o
+
+MAN= lsof.man
+MANLCL= lsof.LOCAL
+
+OTHER=
+
+SHELL= /bin/sh
+
+SOURCE= Makefile ${OTHER} ${MAN} ${HDR} ${SRC}
+
+all: ${PROG}
+
+${MANLCL}: ${MAN}
+ rm -f ${MANLCL}
+ cp ${MAN} ${MANLCL}
+
+${PROG}: ${LIB} ${P} ${OBJ}
+ ${CC} -o $@ ${CFLAGS} ${OBJ} ${CFGL}
+
+clean: FRC
+ rm -f Makefile.bak ${PROG} a.out core errs lint.out tags *.o version.h ${MANLCL}
+ rm -f machine.h.old new_machine.h
+ (cd lib; ${MAKE} -f Makefile.skel clean)
+
+install: all ${MANLCL} FRC
+ @echo ''
+ @echo 'Please write your own install rule. Lsof should be installed'
+ @echo 'setgid to the group that can can read /dev/kmem. Normally'
+ @echo 'that is the mem group. Your install rule actions might look'
+ @echo 'something like this:'
+ @echo ''
+ @echo ' strip $${PROG}'
+ @echo ' mcs -d $${PROG}'
+ @echo ' /etc/install -o -m <modes> -u <owner> -g <group> -f $${BIN} $${PROG}'
+ @echo ' /etc/install -o -m 444 -f $${DOC} $${MANLCL}'
+ @echo ''
+ @echo 'You will have to set values for <modes>, <owner> and <group>,'
+ @echo 'and complete the skeletons for the BIN and DOC strings given'
+ @echo 'at the beginning of this Makefile, e.g.,'
+ @echo ''
+ @echo ' BIN= $${DESTDIR}/usr/local/etc'
+ @echo ' DOC= $${DESTDIR}/usr/man/man8'
+ @echo ''
+
+${LIB}: FRC
+ (cd lib; ${MAKE} DEBUG="${DEBUG}" CFGF="${CFGF}")
+
+version.h: FRC
+ @echo Constructing version.h
+ @rm -f version.h
+ @echo '#define LSOF_BLDCMT "${LSOF_BLDCMT}"' > version.h;
+ @echo '#define LSOF_CC "${CC}"' >> version.h
+ @echo '#define LSOF_CCV "${CCV}"' >> version.h
+ @echo '#define LSOF_CCDATE "'`date`'"' >> version.h
+ @echo '#define LSOF_CCFLAGS "'`echo ${CFLAGS} | sed 's/\\\\(/\\(/g' | sed 's/\\\\)/\\)/g' | sed 's/"/\\\\"/g'`'"' >> version.h
+ @echo '#define LSOF_LDFLAGS "${CFGL}"' >> version.h
+ @if [ "X${LSOF_LOGNAME}" = "X" ]; then \
+ echo '#define LSOF_LOGNAME "${LOGNAME}"' >> version.h; \
+ else \
+ if [ "${LSOF_LOGNAME}" = "none" ]; then \
+ echo '#define LSOF_LOGNAME ""' >> version.h; \
+ else \
+ echo '#define LSOF_LOGNAME "${LSOF_LOGNAME}"' >> version.h; \
+ fi; \
+ fi
+ @if [ "X${LSOF_HOST}" = "X" ]; then \
+ echo '#define LSOF_HOST "'`uname -n`'"' >> version.h; \
+ else \
+ if [ "${LSOF_HOST}" = "none" ]; then \
+ echo '#define LSOF_HOST ""' >> version.h; \
+ else \
+ echo '#define LSOF_HOST "${LSOF_HOST}"' >> version.h; \
+ fi \
+ fi
+ @if [ "X${LSOF_SYSINFO}" = "X" ]; then \
+ echo '#define LSOF_SYSINFO "${LSOF_SYSINFO}"' >> version.h; \
+ else \
+ if [ "${LSOF_SYSINFO}" = "none" ]; then \
+ echo '#define LSOF_SYSINFO ""' >> version.h; \
+ else \
+ echo '#define LSOF_SYSINFO "'`uname -X`'"' >> version.h; \
+ fi \
+ fi
+ @if [ "X${LSOF_USER}" = "X" ]; then \
+ echo '#define LSOF_USER "${USER}"' >> version.h; \
+ else \
+ if [ "${LSOF_USER}" = "none" ]; then \
+ echo '#define LSOF_USER ""' >> version.h; \
+ else \
+ echo '#define LSOF_USER "${LSOF_USER}"' >> version.h; \
+ fi \
+ fi
+ @sed '/VN/s/.ds VN \(.*\)/#define LSOF_VERSION "\1"/' < version >> version.h
+
+FRC:
+
+# DO NOT DELETE THIS LINE - make depend DEPENDS ON IT
+
+dfile.o: ${HDR} dfile.c
+
+dmnt.o: ${HDR} dmnt.c
+
+dnode.o: ${HDR} dnode.c
+
+dproc.o: ${HDR} dproc.c
+
+dsock.o: ${HDR} dsock.c
+
+dstore.o: ${HDR} dstore.c
+
+arg.o: ${HDR} arg.c
+
+main.o: ${HDR} main.c
+
+misc.o: ${HDR} misc.c
+
+node.o: ${HDR} node.c
+
+print.o: ${HDR} print.c
+
+proc.o: ${HDR} proc.c
+
+store.o: ${HDR} store.c
+
+usage.o: ${HDR} version.h usage.c
+
+util.o: ${HDR} util.c
+
+# *** Do not add anything here - It will go away. ***
diff --git a/dialects/osr/Mksrc b/dialects/osr/Mksrc
new file mode 100755
index 0000000..535b69c
--- /dev/null
+++ b/dialects/osr/Mksrc
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+# Mksrc - make SCO OpenServer source files
+#
+# WARNING: This script assumes it is running from the main directory
+# of the lsof, version 4 distribution.
+#
+# One environment variable applies:
+#
+# LSOF_MKC is the method for creating the source files.
+# It defaults to "ln -s". A common alternative is "cp".
+#
+# $Id: Mksrc,v 1.4 99/06/22 08:21:19 abe Exp $
+
+
+D=dialects/osr
+F=dialects/common
+L="dfile.c dlsof.h dmnt.c dnode.c dproc.c dproto.h dsock.c dstore.c machine.h"
+
+for i in $L
+do
+ rm -f $i
+ $LSOF_MKC $D/$i $i
+ echo "$LSOF_MKC $D/$i $i"
+done
diff --git a/dialects/osr/dfile.c b/dialects/osr/dfile.c
new file mode 100644
index 0000000..1e9933a
--- /dev/null
+++ b/dialects/osr/dfile.c
@@ -0,0 +1,161 @@
+/*
+ * dfile.c - SCO OpenServer file processing functions for lsof
+ */
+
+
+/*
+ * Copyright 1995 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 1995 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dfile.c,v 1.11 2000/12/04 14:32:49 abe Exp abe $";
+#endif
+
+#include "lsof.h"
+
+
+/*
+ * get_max_fd() - get maximum file descriptor plus one
+ */
+
+int
+get_max_fd()
+{
+
+#if defined(F_GETHFDO) || defined(_SC_OPEN_MAX)
+ int nd;
+#endif /* defined(F_GETHFDO) || defined(_SC_OPEN_MAX) */
+
+#if defined(F_GETHFDO)
+ if ((nd = fcntl(-1, F_GETHFDO, 0)) >= 0)
+ return(nd);
+#endif /* defined(F_GETHFDO) */
+
+#if defined(_SC_OPEN_MAX)
+ if ((nd = sysconf(_SC_OPEN_MAX)) >= 0)
+ return(nd);
+#endif /* defined(_SC_OPEN_MAX) */
+
+ return(getdtablesize());
+}
+
+
+/*
+ * print_dev() - print dev
+ */
+
+char *
+print_dev(lf, dev)
+ struct lfile *lf; /* file whose device is to be printed */
+ dev_t *dev; /* device to be printed */
+{
+ static char buf[128];
+
+ (void) snpf(buf, sizeof(buf), "%d,%d",
+ lf->is_nfs ? ((~(*dev >> 8)) & 0xff) : emajor(*dev),
+ eminor(*dev));
+ return(buf);
+}
+
+
+/*
+ * print_ino() - print inode
+ */
+
+char *
+print_ino(lf)
+ struct lfile *lf; /* file whose device is to be printed */
+{
+ static char buf[128];
+
+ (void) snpf(buf, sizeof(buf), (lf->inode & 0x80000000) ? "%#x" : "%lu",
+ lf->inode);
+ return(buf);
+}
+
+
+/*
+ * process_file() - process file
+ */
+
+void
+process_file(fp)
+ KA_T fp; /* kernel file structure address */
+{
+ struct file f;
+ int flag;
+
+ if (kread(fp, (char *)&f, sizeof(f))) {
+ (void) snpf(Namech, Namechl, "can't read file struct from %s",
+ print_kptr(fp, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ Lf->off = (SZOFFTYPE)f.f_offset;
+
+ if (f.f_count) {
+
+ /*
+ * Construct access code.
+ */
+ if ((flag = (f.f_flag & (FREAD | FWRITE))) == FREAD)
+ Lf->access = 'r';
+ else if (flag == FWRITE)
+ Lf->access = 'w';
+ else if (flag == (FREAD | FWRITE))
+ Lf->access = 'u';
+ /*
+ * Process structure.
+ */
+
+#if defined(HASFSTRUCT)
+ /*
+ * Save file structure values.
+ */
+ if (Fsv & FSV_CT) {
+ Lf->fct = (long)f.f_count;
+ Lf->fsv |= FSV_CT;
+ }
+ if (Fsv & FSV_FA) {
+ Lf->fsa = fp;
+ Lf->fsv |= FSV_FA;
+ }
+ if (Fsv & FSV_FG) {
+ Lf->ffg = (long)f.f_flag;
+ Lf->fsv |= FSV_FG;
+ }
+ if (Fsv & FSV_NI) {
+ Lf->fna = (KA_T)f.f_inode;
+ Lf->fsv |= FSV_NI;
+ }
+#endif /* defined(HASFSTRUCT) */
+
+ process_node((KA_T)f.f_inode);
+ return;
+ }
+ enter_nm("no more information");
+}
diff --git a/dialects/osr/dlsof.h b/dialects/osr/dlsof.h
new file mode 100644
index 0000000..ebca8f2
--- /dev/null
+++ b/dialects/osr/dlsof.h
@@ -0,0 +1,255 @@
+/*
+ * dlsof.h - SCO OpenServer header file for lsof
+ */
+
+
+/*
+ * Copyright 1995 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.
+ */
+
+
+/*
+ * $Id: dlsof.h,v 1.14 2007/04/24 16:22:40 abe Exp $
+ */
+
+
+#if !defined(OSR_LSOF_H)
+#define OSR_LSOF_H 1
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <mnttab.h>
+#include <nlist.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <string.h>
+
+# if OSRV>=500
+#include <strings.h>
+# endif /* OSRV>=500 */
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/flock.h>
+#include <sys/fstyp.h>
+#include <sys/immu.h>
+#include <sys/inode.h>
+#include <sys/region.h>
+#include <sys/proc.h>
+#include <sys/sysi86.h>
+
+/*
+ * This confusing sequence of redefinitions of xdevmap allows lsof to size
+ * its copy of the kernel's xdevmap[] table dynamically, based on the
+ * kernel's nxdevmaps value.
+ *
+ * The net result is that there is a dummy struct XDEVMAP[1], defined in
+ * dstore.c, that is never used. The copy of the kernel's xdevmap[] table
+ * is stored in the space malloc()'d in dproc.c and addressed by Xdevmap.
+ * The last redefinition of xdevmap to Xdevmap causes the macros of
+ * <sys/sysmacros.h> to use Xdevmap.
+ *
+ * All this is done: 1) to avoid having to allocate a large amount of fixed
+ * space in advance to a copy of the kernel's xdevmap; and 2) to keep CC from
+ * complaining about the absence of a "struct xdevmap xdevmap[]," matching
+ * the "extern struct xdevmap xdevmap[]" declaration in <sys/sysmacros.h>,
+ * while still allowing lsof to use the equivalent of a "struct xdevmap *"
+ * construct instead, particularly with the kernel forms of the major() and
+ * minor() macros.
+ */
+
+#define xdevmap XDEVMAP
+#define _INKERNEL
+#include <sys/sysmacros.h>
+#undef _INKERNEL
+extern struct XDEVMAP *Xdevmap;
+#undef xdevmap
+#define xdevmap Xdevmap
+
+#include <sys/stream.h>
+#include <sys/time.h>
+#include <sys/dir.h>
+#include <sys/user.h>
+#include <sys/var.h>
+
+# if defined(HAS_NFS)
+#define multiple_groups 1
+#include <sys/fs/nfs/types.h>
+#include <sys/fs/nfs/nfs.h>
+#include <sys/fs/nfs/ucred.h>
+#include <sys/fs/nfs/rnode.h>
+# endif /* defined(HAS_NFS) */
+
+#include <sys/socket.h>
+#include <sys/net/domain.h>
+#undef NOGROUP
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+
+# if OSRV<500
+#include <sys/net/protosw.h>
+#include <sys/net/socketvar.h>
+# else /* OSRV>=500 */
+#include <sys/protosw.h>
+#include <sys/socketvar.h>
+#include <sys/un.h>
+#include <sys/fs/hpps.h>
+# endif /* OSRV<500 */
+
+#include <sys/netinet/in.h>
+#include <sys/net/route.h>
+#include <sys/netinet/in_pcb.h>
+#include <sys/netinet/ip_var.h>
+#include <sys/netinet/tcp.h>
+#include <sys/netinet/tcp_fsm.h>
+#include <sys/netinet/tcp_timer.h>
+#include <sys/netinet/tcp_var.h>
+#include <sys/netinet/udp.h>
+#include <sys/utsname.h>
+
+#define INKERNEL
+#include <sys/netinet/udp_var.h>
+#undef INKERNEL
+
+
+/*
+ * Adjust for the availability of symbolic links.
+ */
+
+# if defined(HAS_STATLSTAT)
+#define lstat statlstat
+# else /* !defined(HAS_STATLSTAT) */
+#define lstat stat
+#define readlink(path, buf, len) (-1)
+# endif /* defined(HAS_STATLSTAT) */
+
+
+
+#define COMP_P const void
+#define DEVINCR 1024 /* device table malloc() increment */
+#define DIRTYPE dirent
+typedef off_t KA_T;
+#define KMEM "/dev/kmem"
+#define MALLOC_P void
+#define MNTTAB "/etc/mnttab"
+#define FREE_P MALLOC_P
+#define MALLOC_S size_t
+
+# if !defined(MAXPATHLEN)
+#define MAXPATHLEN 1024
+# endif /* !defined(MAXPATHLEN) */
+
+#define MAXSEGS 100 /* maximum text segments */
+#define MAXSYSCMDL (PSCOMSIZ - 1) /* max system command name length */
+
+# if OSRV<500
+#define N_UNIX "/unix"
+# endif /* OSRV<500 */
+
+#define PROCBFRD 16 /* count of proc structures buffered */
+#define PROCSIZE sizeof(struct proc)
+#define QSORT_P void
+#define READLEN_T unsigned
+#define STRNCPY_L size_t
+#define STRNML 32
+#define U_SIZE sizeof(struct user)
+
+
+/*
+ * Global storage definitions (including their structure definitions)
+ */
+
+extern char **Cdevsw;
+extern int Cdevcnt;
+extern int CloneMajor;
+extern int EventMajor;
+extern char **Fsinfo;
+extern int Fsinfomax;
+extern int HaveCloneMajor;
+extern int HaveEventMajor;
+extern int HaveSockdev;
+extern int Hz;
+extern int Kd;
+extern KA_T Lbolt;
+
+extern int nxdevmaps; /* maximum kernel xdevmap[] index */
+
+struct mounts {
+ char *dir; /* directory (mounted on) */
+ char *fsname; /* file system
+ * (symbolic links unresolved) */
+ char *fsnmres; /* file system
+ * (symbolic links resolved) */
+ dev_t dev; /* directory st_dev */
+ dev_t rdev; /* directory st_rdev */
+ INODETYPE inode; /* directory st_ino */
+ mode_t mode; /* directory st_mode */
+ mode_t fs_mode; /* file system st_mode */
+ struct mounts *next; /* forward link */
+
+# if defined(HASFSTYPE)
+ char *fstype; /* st_fstype */
+# endif
+
+};
+
+#define NL_NAME n_name /* name element in struct nlist */
+
+struct sfile {
+ char *aname; /* argument file name */
+ char *name; /* file name (after readlink()) */
+ char *devnm; /* device name (optional) */
+ dev_t dev; /* device */
+ dev_t rdev; /* raw device */
+ mode_t mode; /* S_IFMT mode bits from stat() */
+ int type; /* file type: 0 = file system
+ * 1 = regular file */
+ INODETYPE i; /* inode number */
+ int f; /* file found flag */
+ struct sfile *next; /* forward link */
+};
+
+extern int Sockdev;
+extern KA_T Socktab;
+
+/*
+ * Definitions for dvch.c, isfn.c, and rdev.c
+ */
+
+#define CLONEMAJ CloneMajor /* clone major variable name */
+
+# if defined(HASDCACHE)
+# if OSRV<500
+#define DVCH_CHOWN 1 /* no fchown() below release 5.0 */
+# endif /* OSRV<500 */
+# endif /* defined(HASDCACHE) */
+
+#define HAS_STD_CLONE 1 /* has standard clone structure */
+#define HAVECLONEMAJ HaveCloneMajor /* clone major status variable name */
+
+#endif /* OSR_LSOF_H */
diff --git a/dialects/osr/dmnt.c b/dialects/osr/dmnt.c
new file mode 100644
index 0000000..47e33f4
--- /dev/null
+++ b/dialects/osr/dmnt.c
@@ -0,0 +1,219 @@
+/*
+ * dmnt.c - SCO OpenServer mount support functions for lsof
+ */
+
+
+/*
+ * Copyright 1995 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 1995 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dmnt.c,v 1.8 2005/08/08 19:54:32 abe Exp $";
+#endif
+
+#include "lsof.h"
+
+
+/*
+ * Local static definitions
+ */
+
+static struct mounts *Lmi = (struct mounts *)NULL; /* local mount info */
+static int Lmist = 0; /* Lmi status */
+
+
+/*
+ * readmnt() - read mount table
+ */
+
+struct mounts *
+readmnt()
+{
+ int br, fd;
+ int bx = sizeof(struct mnttab);
+ char *cp;
+ char dvnm[MAXPATHLEN], fsnm[MAXPATHLEN];
+ MALLOC_S dvnml, fsnml;
+ MALLOC_S len;
+ char *ln = (char *)NULL;
+ struct mnttab m;
+ struct mounts *mtp;
+ struct stat sb;
+
+ if (Lmi || Lmist)
+ return(Lmi);
+/*
+ * Open access to the mount table.
+ */
+ if ((fd = open(MNTTAB, O_RDONLY, 0)) < 0) {
+ (void) fprintf(stderr, "%s: can't open %s\n", Pn, MNTTAB);
+ Exit(1);
+ }
+/*
+ * Read the first mount table entry.
+ */
+ br = read(fd, (char *)&m, bx);
+ dvnml = fsnml = 0;
+/*
+ * Process the next complete mount table entry.
+ */
+ while (br == bx) {
+ if (!dvnml) {
+
+ /*
+ * Start the device and file system name assemblies.
+ */
+ dvnml = strlen(m.mt_dev);
+ if (dvnml >= MAXPATHLEN)
+ dvnml = MAXPATHLEN - 1;
+ (void) strncpy(dvnm, m.mt_dev, dvnml);
+ dvnm[dvnml] = '\0';
+ fsnml = strlen(m.mt_filsys);
+ if (fsnml >= MAXPATHLEN)
+ fsnml = MAXPATHLEN - 1;
+ (void) strncpy(fsnm, m.mt_filsys, fsnml);
+ fsnm[fsnml] = '\0';
+ }
+ while ((br = read(fd, (char *)&m, bx)) == bx
+ && strcmp(m.mt_filsys, "nothing") == 0
+ && strcmp(m.mt_dev, "nowhere") == 0) {
+
+ /*
+ * Add the "nothing/nowhere" extensions to the assemblies.
+ */
+ len = strlen(&m.mt_dev[8]);
+ if (len >= (MAXPATHLEN - dvnml))
+ len = MAXPATHLEN - dvnml - 1;
+ if (len) {
+ (void) strncpy(&dvnm[dvnml], &m.mt_dev[8], len);
+ dvnml += len;
+ dvnm[dvnml] = '\0';
+ }
+ len = strlen(&m.mt_filsys[8]);
+ if (len >= (MAXPATHLEN - fsnml))
+ len = MAXPATHLEN - fsnml - 1;
+ if (len) {
+ (void) strncpy(&fsnm[fsnml], &m.mt_filsys[8], len);
+ fsnml += len;
+ fsnm[fsnml] = '\0';
+ }
+ }
+ /*
+ * Skip automount place markers.
+ */
+ if ((cp = strrchr(dvnm, ':')) && strncmp(cp, ":(pid", 5) == 0) {
+ dvnml = fsnml = 0;
+ continue;
+ }
+ /*
+ * Interpolate a possible symbolic directory link.
+ */
+ if (ln) {
+ (void) free((FREE_P *)ln);
+ ln = (char *)NULL;
+ }
+ if (!(ln = Readlink(fsnm))) {
+ if (!Fwarn){
+ (void) fprintf(stderr,
+ " Output information may be incomplete.\n");
+ }
+ dvnml = fsnml = 0;
+ continue;
+ }
+ if (*ln != '/')
+ continue;
+ if (ln == fsnm) {
+
+ /*
+ * Allocate space for a copy of the file system name.
+ */
+ if (!(ln = mkstrcpy(fsnm, (MALLOC_S *)NULL))) {
+
+no_space_for_mount:
+
+ (void) fprintf(stderr, "%s: no space for mount at ", Pn);
+ safestrprt(fsnm, stderr, 0);
+ (void) fprintf(stderr, " (");
+ safestrprt(dvnm, stderr, 0);
+ (void) fprintf(stderr, ")\n");
+ Exit(1);
+ }
+ }
+ /*
+ * Stat() the directory.
+ */
+ if (statsafely(ln, &sb)) {
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ "%s: WARNING: can't stat() file system: ", Pn);
+ safestrprt(fsnm, stderr, 1);
+ (void) fprintf(stderr,
+ " Output information may be incomplete.\n");
+ }
+ dvnml = fsnml = 0;
+ continue;
+ }
+ /*
+ * Allocate and fill a local mount structure.
+ */
+ if (!(mtp = (struct mounts *)malloc(sizeof(struct mounts))))
+ goto no_space_for_mount;
+ mtp->dir = ln;
+ ln = (char *)NULL;
+ mtp->next = Lmi;
+ mtp->dev = sb.st_dev;
+ mtp->rdev = sb.st_rdev;
+ mtp->inode = (INODETYPE)sb.st_ino;
+ mtp->mode = sb.st_mode;
+ /*
+ * Interpolate a possible file system (mounted-on) device name link
+ */
+ if (!(cp = mkstrcpy(dvnm, (MALLOC_S *)NULL)))
+ goto no_space_for_mount;
+ mtp->fsname = cp;
+ ln = Readlink(cp);
+ /*
+ * Stat() the file system (mounted-on) name and add file system
+ * information to the local mount table entry.
+ */
+ if (statsafely(ln, &sb))
+ sb.st_mode = 0;
+ mtp->fsnmres = ln;
+ ln = (char *)NULL;
+ mtp->fs_mode = sb.st_mode;
+ Lmi = mtp;
+ dvnml = fsnml = 0;
+ }
+ (void) close(fd);
+/*
+ * Clean up and return the local mount information table address.
+ */
+ if (ln)
+ (void) free((FREE_P *)ln);
+ Lmist = 1;
+ return(Lmi);
+}
diff --git a/dialects/osr/dnode.c b/dialects/osr/dnode.c
new file mode 100644
index 0000000..755c82f
--- /dev/null
+++ b/dialects/osr/dnode.c
@@ -0,0 +1,739 @@
+/*
+ * dnode.c - SCO OpenServer node functions for lsof
+ */
+
+
+/*
+ * Copyright 1995 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 1995 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dnode.c,v 1.21 2006/03/28 22:09:23 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+_PROTOTYPE(static struct l_dev * finddev,(dev_t *dev, dev_t *rdev, int stream));
+
+
+/*
+ * finddev() - look up device by device number
+ */
+
+static struct l_dev *
+finddev(dev, rdev, stream)
+ dev_t *dev; /* device */
+ dev_t *rdev; /* raw device */
+ int stream; /* stream if 1 */
+{
+ struct clone *c;
+ struct l_dev *dp;
+/*
+ * Search device table for match.
+ */
+
+#if defined(HASDCACHE)
+
+finddev_again:
+
+#endif /* defined(HASDCACHE) */
+
+ if ((dp = lkupdev(dev, rdev, 0, 0)))
+ return(dp);
+/*
+ * Search for clone.
+ */
+ if (stream && Clone) {
+ for (c = Clone; c; c = c->next) {
+ if (GET_MAJ_DEV(*rdev) == GET_MIN_DEV(Devtp[c->dx].rdev)) {
+
+#if defined(HASDCACHE)
+ if (DCunsafe && !Devtp[c->dx].v && !vfy_dev(&Devtp[c->dx]))
+ goto finddev_again;
+#endif /* defined(HASDCACHE) */
+
+ return(&Devtp[c->dx]);
+ }
+ }
+ }
+ return((struct l_dev *)NULL);
+}
+
+
+/*
+ * process_node() - process node
+ */
+
+void
+process_node(na)
+ KA_T na; /* inode kernel space address */
+{
+ char *cp, tbuf[32];
+ short dl;
+ struct l_dev *dp;
+ unsigned char *fa = (unsigned char *)NULL;
+ struct filock fl;
+ KA_T flf, flp;
+ int fp, lp;
+ struct inode i;
+ short ity, udpsf, udpsl;
+ int j, k, l;
+ KA_T ka, qp;
+ unsigned char *la = (unsigned char *)NULL;
+ struct mounts *lm;
+ struct module_info mi;
+ unsigned short *n;
+ KA_T p;
+ struct inpcb pcb;
+ int port;
+ int pt = -1;
+ struct queue q;
+ struct qinit qi;
+ struct stdata sd;
+ char *tn;
+ int type;
+ struct udpdev udp;
+ short udptm = 0;
+
+#if defined(HAS_NFS)
+ struct rnode r;
+#endif /* defined(HAS_NFS) */
+
+#if OSRV>=500
+ short hpps = 0;
+ unsigned short *n1;
+ struct pipeinode pi;
+#endif /* OSRV>=500 */
+
+/*
+ * Read the inode.
+ */
+ if ( ! na) {
+ enter_nm("no inode address");
+ return;
+ }
+ if (readinode(na, &i)) {
+ enter_nm(Namech);
+ return;
+ }
+
+#if defined(HASNCACHE)
+ Lf->na = na;
+#endif /* defined(HASNCACHE) */
+
+#if defined(HASFSTRUCT)
+ Lf->fna = na;
+ Lf->fsv |= FSV_NI;
+#endif /* defined(HASFSTRUCT) */
+
+/*
+ * Identify the node type.
+ */
+ if (HaveSockdev && (i.i_ftype & IFMT) == IFCHR
+ && GET_MAJ_DEV(i.i_rdev) == Sockdev)
+ {
+
+ /*
+ * Process a socket.
+ */
+ process_socket(&i);
+ return;
+ }
+ if (Selinet)
+ return;
+ ity = i.i_fstyp;
+ type = i.i_ftype & IFMT;
+ if (ity < 1 || ity > Fsinfomax || !Fsinfo[ity-1]) {
+
+#if OSRV>=500
+ if (ity) {
+#endif /* OSRV>=500 */
+
+ (void) snpf(Namech,Namechl,"unknown fstyp (%d) in inode",ity);
+ enter_nm(Namech);
+ return;
+
+#if OSRV>=500
+ }
+#endif /* OSRV>=500 */
+
+ }
+ if (ity && strcasecmp(Fsinfo[ity-1], "HS") == 0)
+ Ntype = N_HSFS;
+
+#if defined(HAS_NFS)
+ else if (ity && strcasecmp(Fsinfo[ity-1], "NFS") == 0) {
+
+ /*
+ * Get information on NFS file.
+ */
+ Ntype = N_NFS;
+ Lf->is_nfs = 1;
+ if (Fnfs)
+ Lf->sf |= SELNFS;
+ if (!i.i_fsptr || readrnode((KA_T)i.i_fsptr, &r)) {
+ (void) snpf(Namech, Namechl, "can't read rnode (%s)",
+ print_kptr((KA_T)i.i_fsptr, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+
+# if defined(HASNCACHE)
+ Lf->na = (KA_T)i.i_fsptr;
+# endif /* defined(HASNCACHE) */
+
+ }
+#endif /* defined(HAS_NFS) */
+
+ else {
+
+ /*
+ * Determine the node type from the inode file type.
+ */
+ switch (type) {
+ case IFBLK:
+ Ntype = N_BLK;
+ break;
+ case IFCHR:
+ Ntype = N_CHR;
+ break;
+ case IFIFO:
+ Ntype = N_FIFO;
+ break;
+ case IFMPB:
+ case IFMPC:
+ Ntype = N_MPC;
+ break;
+ case IFNAM:
+ Ntype = N_NM;
+ break;
+ }
+ }
+/*
+ * Obtain lock information.
+ */
+ if ((flf = (KA_T)i.i_filocks)) {
+ flp = flf;
+ do {
+ if ((kread(flp, (char *)&fl, sizeof(fl))))
+ break;
+ if (fl.set.l_pid != (pid_t)Lp->pid)
+ continue;
+ if (fl.set.l_whence == (short)0 && fl.set.l_start == (off_t)0
+ && fl.set.l_len == 0x7fffffff)
+ l = 1;
+ else
+ l = 0;
+
+#if OSRV<500
+ if (i.i_flag & IXLOCKED)
+#else /* OSRV>=500 */
+ if (fl.flags & F_XOUT)
+#endif /* OSRV<500 */
+
+ Lf->lock = l ? 'X' : 'x';
+ else if (fl.set.l_type == F_RDLCK)
+ Lf->lock = l ? 'R' : 'r';
+ else if (fl.set.l_type == F_WRLCK)
+ Lf->lock = l ? 'W' : 'w';
+ else if (fl.set.l_type == (F_RDLCK | F_WRLCK))
+ Lf->lock = 'u';
+ break;
+ } while ((flp = (KA_T)fl.next) && flp != flf);
+ }
+
+#if OSRV>=500
+/*
+ * See if a FIFO node is an HPPS node -- 3.2v5.0.0 and higher.
+ */
+ if (Ntype == N_FIFO && ity && strcasecmp(Fsinfo[ity-1], "HPPS") == 0)
+ {
+ hpps = 1;
+ if (i.i_fsptr) {
+ enter_dev_ch(print_kptr((KA_T)i.i_fsptr, (char )NULL, 0));
+ if (kread((KA_T)i.i_fsptr, (char *)&pi, sizeof(pi)) == 0)
+ hpps = 2;
+ }
+ }
+#endif /* OSRV>=500 */
+
+/*
+ * Determine the device.
+ */
+ switch (Ntype) {
+ case N_BLK:
+ Lf->dev = i.i_dev;
+ Lf->rdev = i.i_rdev;
+ Lf->dev_def = Lf->rdev_def = 1;
+ break;
+ case N_FIFO:
+ case N_HSFS:
+ case N_NM:
+ case N_REGLR:
+
+#if OSRV>=500
+ if (hpps)
+ break;
+#endif /* OSRV>=500 */
+
+ Lf->dev = i.i_dev;
+ Lf->dev_def = 1;
+ break;
+ case N_CHR:
+ Lf->dev = i.i_dev;
+ Lf->rdev = i.i_rdev;
+ Lf->dev_def = Lf->rdev_def = 1;
+ if (i.i_sptr) {
+
+ /*
+ * Namech may be:
+ * /dev/* name if it exists for i.i_rdev;
+ * cdevsw[].d_name if it exists for GET_MAJ_DEV(i.i_rdev);
+ * "STR:" otherwise.
+ */
+ (void) snpf(Namech, Namechl, "STR:");
+ Lf->is_stream = 1;
+ k = strlen(Namech);
+ cp = (char *)NULL;
+ if ((dp = finddev(&Lf->dev, &Lf->rdev, 1))) {
+ (void) snpf(&Namech[k], Namechl - k, dp->name);
+ k += strlen(dp->name);
+ if ((cp = strrchr(dp->name, '/')))
+ cp++;
+ } else if ((j = GET_MAJ_DEV(i.i_rdev))
+ < Cdevcnt && (cp = Cdevsw[j]))
+ {
+ (void) snpf(Namech, Namechl, "%s", cp);
+ k += strlen(cp);
+ }
+ /*
+ * Get the module names of all queue elements of the stream's
+ * sd_wrq queue. Skip module names that end in "head",
+ * match the last component of the /dev name, or match the
+ * cdevsw[].d_name.
+ */
+ p = (KA_T)NULL;
+ if (!kread((KA_T)i.i_sptr, (char *)&sd, sizeof(sd))) {
+ dl = sizeof(tbuf) - 1;
+ tbuf[dl] = '\0';
+ qp = (KA_T)sd.sd_wrq;
+ for (j = 0; qp && j < 20; j++, qp = (KA_T)q.q_next) {
+ if (kread(qp, (char *)&q, sizeof(q)))
+ break;
+ if (!(ka = (KA_T)q.q_qinfo)
+ || kread(ka, (char *)&qi, sizeof(qi)))
+ continue;
+ if (!(ka = (KA_T)qi.qi_minfo)
+ || kread(ka, (char *)&mi, sizeof(mi)))
+ continue;
+ if (!(ka = (KA_T)mi.mi_idname)
+ || kread(ka, tbuf, dl))
+ continue;
+ if ((l = strlen(tbuf)) < 1)
+ continue;
+ if (l >= 4 && strcmp(&tbuf[l - 4], "head") == 0)
+ continue;
+ if (cp && strcmp(cp, tbuf) == 0) {
+ if (q.q_ptr && pt < 0) {
+
+ /*
+ * If this is a TCP or UDP module and the
+ * queue structure has a private pointer in
+ * q_ptr, save it as a PCB address.
+ */
+ if (strcasecmp(cp, "tcp") == 0) {
+ pt = 0;
+ (void) snpf(Lf->iproto,
+ sizeof(Lf->iproto), "TCP");
+ } else if (strcasecmp(cp, "udp") == 0) {
+ pt = 1;
+ (void) snpf(Lf->iproto,
+ sizeof(Lf->iproto), "UDP");
+ }
+ if (pt >= 0)
+ p = (KA_T)q.q_ptr;
+ else
+ pt = -1;
+ }
+ continue;
+ }
+ if (k) {
+ if ((k + 2) > (Namechl - 1))
+ break;
+ (void) snpf(&Namech[k], Namechl - k, "->");
+ k += 2;
+ }
+ if ((k + l) > (Namechl - 1))
+ break;
+ (void) snpf(&Namech[k], Namechl - k, tbuf);
+ k += l;
+ }
+ }
+ if (p && pt >= 0) {
+
+ /*
+ * If the stream has a TCP or UDP module with a PCB pointer,
+ * print any associated local and foreign Internet addresses.
+ */
+ if (kread(p, (char *)&pcb, sizeof(pcb)))
+ break;
+ if (Fnet)
+ Lf->sf |= SELNET;
+ if ((k + 1) > (Namechl - 1))
+ break;
+ if (pt == 1 && pcb.inp_ppcb) {
+
+ /*
+ * If this is a UDP stream, get the udpdev structure at the
+ * PCB's per-protocol address. It may contain addresses.
+ */
+ if (kread((KA_T)pcb.inp_ppcb, (char *)&udp, sizeof(udp))
+ == 0) {
+
+#if OSRV>=500
+ if (udp.ud_lsin.sin_addr.s_addr != INADDR_ANY
+ || udp.ud_lsin.sin_port != 0)
+ udpsl = 1;
+ else
+ udpsl = 0;
+#endif /* OSRV>=500 */
+
+ if (udp.ud_fsin.sin_addr.s_addr != INADDR_ANY
+ || udp.ud_fsin.sin_port != 0)
+ udpsf = 1;
+ else
+ udpsf = 0;
+ }
+ } else
+ udpsf = udpsl = 0;
+ /*
+ * Enter the local address from the PCB. If there is none,
+ * and if this is a 5.0.0 or greater UDP stream, and if it
+ * has a local address set, use it.
+ */
+ la = (unsigned char *)&pcb.inp_laddr;
+ lp = (int)ntohs(pcb.inp_lport);
+
+#if OSRV>=500
+ if (((struct in_addr *)la)->s_addr == INADDR_ANY
+ && lp == 0 && udpsl) {
+ la = (unsigned char *)&udp.ud_lsin.sin_addr;
+ lp = (int)ntohs(udp.ud_lsin.sin_port);
+ }
+
+#endif /* OSRV>=500 */
+
+ /*
+ * Enter the foreign address from the PCB. If there is
+ * none, and if this is a 5.0.0 or greater UDP stream, and
+ * if it has a local address set, use it.
+ */
+ if (pcb.inp_faddr.s_addr!=INADDR_ANY || pcb.inp_fport!=0) {
+ fa = (unsigned char *)&pcb.inp_faddr;
+ fp = (int)ntohs(pcb.inp_fport);
+ } else if (udpsf) {
+ fa = (unsigned char *)&udp.ud_fsin.sin_addr;
+ fp = (int)ntohs(udp.ud_fsin.sin_port);
+ udptm = 1;
+ }
+ if (fa || la) {
+ (void) ent_inaddr(la, lp, fa, fp, AF_INET);
+ if (udptm && !Lf->nma)
+ (void) udp_tm(udp.ud_ftime);
+ }
+ if (!i.i_number)
+ Lf->inp_ty = 2;
+ }
+ } else {
+ if (ity) {
+ if (strcasecmp(Fsinfo[ity-1], "COM") == 0)
+ Ntype = N_COM;
+ else
+ Ntype = N_CHR;
+ } else {
+ Ntype = N_CHR;
+ if (!finddev(&i.i_dev, &i.i_rdev, 0)
+ && HaveEventMajor
+ && GET_MAJ_DEV(i.i_rdev) == EventMajor)
+ (void) snpf(Namech, Namechl,
+ "clone %d:/dev/event", GET_MIN_DEV(i.i_rdev));
+ }
+ }
+ break;
+
+#if defined(HAS_NFS)
+ case N_NFS:
+
+#if OSRV<500
+ Lf->dev = (dev_t)_makedev(~GET_MAJ_DEV(i.i_dev),
+ GET_MIN_DEV(i.i_dev));
+ Lf->rdev = (dev_t)_makedev(~GET_MAJ_DEV(i.i_rdev),
+ GET_MIN_DEV(i.i_rdev));
+#else /* OSRV>=500 */
+ Lf->dev = i.i_dev;
+ Lf->rdev = i.i_rdev;
+#endif /* OSRV<500 */
+
+ Lf->dev_def = Lf->rdev_def = 1;
+ break;
+#endif /* defined(HAS_NFS) */
+
+ }
+/*
+ * Determine the inode number.
+ */
+ switch (Ntype) {
+ case N_HSFS:
+
+#if OSRV<500
+ /*
+ * High Sierra inode numbers for versions below 5.0.0, as reported
+ * by "ls -i" and stat(2), are the lower 16 bits of i_number.
+ */
+ if ((Lf->inode = (unsigned long)(i.i_number & 0xffff)))
+#else /* OSRV>=500 */
+ if ((Lf->inode = (unsigned long)i.i_number))
+#endif /* OSRV<500 */
+
+ Lf->inp_ty = 1;
+ break;
+
+#if defined(HAS_NFS)
+ case N_NFS:
+
+#if OSRV<500
+ n = (unsigned short *)&r.r_fh.fh_pad[14];
+ if ((Lf->inode = (unsigned long)ntohs(*n)))
+ Lf->inp_ty = 1;
+ else if ((Lf->inode = (unsigned long)r.r_fh.fh_u.fh_fgen_u))
+#else /* OSRV>=500 */
+ n = (unsigned short *)&r.r_fh.fh_u.fh_fid_u[4];
+ n1 = (unsigned short *)&r.r_fh.fh_u.fh_fid_u[2];
+ if ((Lf->inode = (unsigned long)*n))
+ Lf->inp_ty = 1;
+ else if ((Lf->inode = (unsigned long)*n1))
+#endif /* OSRV<500 */
+
+ Lf->inp_ty = 1;
+ break;
+#endif /* defined(HAS_NFS) */
+
+ case N_BLK:
+ case N_CHR:
+ case N_COM:
+ case N_FIFO:
+ case N_NM:
+ case N_REGLR:
+
+#if OSRV>=500
+ /*
+ * Inodes for some 5.0.x HPPS FIFOs have an i_number that is the same
+ * as i_fsptr. If it is, ignore it, because i_fsptr has already been
+ * recorded for the DEVICE column.
+ */
+ if (hpps && i.i_fsptr && i.i_number
+ && (unsigned long)i.i_fsptr == (unsigned long)i.i_number)
+ break;
+#endif /* OSRV>=500 */
+
+ if (i.i_number) {
+ Lf->inode = (unsigned long)i.i_number;
+ Lf->inp_ty = 1;
+ }
+ break;
+ }
+/*
+ * Determine the file size.
+ */
+ if (Foffset)
+ Lf->off_def = 1;
+ else {
+ switch (Ntype) {
+ case N_BLK:
+ if (!Fsize)
+ Lf->off_def = 1;
+ break;
+ case N_CHR:
+ case N_COM:
+ if (!Fsize)
+ Lf->off_def = 1;
+ break;
+ case N_FIFO:
+
+#if OSRV>=500
+ if (hpps == 2) {
+ Lf->sz = (SZOFFTYPE)pi.count;
+ Lf->sz_def = 1;
+ break;
+ }
+#endif /* OSRV>=500 */
+
+ if (!Fsize)
+ Lf->off_def = 1;
+ break;
+ case N_HSFS:
+
+#if defined(HAS_NFS)
+ case N_NFS:
+ Lf->sz = (SZOFFTYPE)i.i_size;
+ Lf->sz_def = 1;
+ break;
+#endif /* defined(HAS_NFS) */
+
+ case N_REGLR:
+ if (type == IFREG || type == IFDIR) {
+ Lf->sz = (SZOFFTYPE)i.i_size;
+ Lf->sz_def = 1;
+ }
+ break;
+ }
+ }
+/*
+ * Record link count.
+ */
+ if (Fnlink) {
+ Lf->nlink = (long)i.i_nlink;
+ Lf->nlink_def = 1;
+ if (Nlink && (Lf->nlink < Nlink))
+ Lf->sf |= SELNLINK;
+ }
+/*
+ * Format the type name.
+ */
+ switch (type) {
+ case IFDIR:
+ tn = "DIR";
+ break;
+ case IFBLK:
+ tn = "BLK";
+ break;
+ case IFCHR:
+ tn = "CHR";
+ break;
+ case IFREG:
+ tn = "REG";
+ break;
+ case IFMPC:
+ tn = "MPC";
+ break;
+ case IFMPB:
+ tn = "MPB";
+ break;
+ case IFNAM:
+ if (i.i_rdev == S_INSEM)
+ tn = "XSEM";
+ else if (i.i_rdev == S_INSHD)
+ tn = "XSD";
+ else {
+ tn = "XNAM";
+ (void) snpf(Namech, Namechl,
+ "unknown Xenix special file type: %x", i.i_rdev);
+ }
+ break;
+ case IFIFO:
+ tn = "FIFO";
+ break;
+
+#if defined(IFLNK)
+ case IFLNK:
+ tn = "LINK";
+ break;
+#endif /* defined(IFLNK) */
+
+ default:
+ (void) snpf(Lf->type, sizeof(Lf->type), "%04o",
+ ((type >> 12) & 0xfff));
+ tn = NULL;
+ }
+ if (tn)
+ (void) snpf(Lf->type, sizeof(Lf->type), "%s", tn);
+/*
+ * Save the file system names.
+ */
+ switch (Ntype) {
+ case N_BLK:
+ case N_CHR:
+ case N_FIFO:
+ case N_HSFS:
+
+#if defined(HAS_NFS)
+ case N_NFS:
+#endif /* defined(HAS_NFS) */
+
+ case N_NM:
+ case N_REGLR:
+ if (Lf->dev_def) {
+
+ /*
+ * Defer the local mount info table search until printname().
+ */
+ Lf->lmi_srch = 1;
+ }
+ break;
+ }
+ Lf->ntype = Ntype;
+
+#if defined(HASBLKDEV)
+/*
+ * If this is a IFBLK file and it's missing an inode number, try to
+ * supply one.
+ */
+ if ((Lf->inp_ty == 0) && (type == IFBLK))
+ find_bl_ino();
+#endif /* defined(HASBLKDEV) */
+
+/*
+ * If this is a IFCHR file and it's missing an inode number, try to
+ * supply one.
+ */
+ if ((Lf->inp_ty == 0) && (type == IFCHR))
+ find_ch_ino();
+/*
+ * Test for specified file.
+ */
+ if (Sfile && is_file_named((char *)NULL,
+ ((type == IFCHR) || (type == IFBLK) || (type == IFNAM)) ? 1
+ : 0))
+ Lf->sf |= SELNM;
+
+#if OSRV>=500
+/*
+ * If this is an HPPS node and no other name characters have been
+ * entered, enter HPPS as the name.
+ */
+ if (hpps && Namech[0] == '\0')
+ (void) snpf(Namech, Namechl, "HPPS");
+#endif /* OSRV>=500 */
+
+/*
+ * Enter name characters.
+ */
+ if (Namech[0])
+ enter_nm(Namech);
+}
diff --git a/dialects/osr/dproc.c b/dialects/osr/dproc.c
new file mode 100644
index 0000000..facdb42
--- /dev/null
+++ b/dialects/osr/dproc.c
@@ -0,0 +1,2003 @@
+/*
+ * dproc.c - SCO OpenServer process access functions for lsof
+ */
+
+
+/*
+ * Copyright 1995 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 1995 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dproc.c,v 1.18 2007/04/24 16:22:40 abe Exp $";
+#endif
+
+#include "lsof.h"
+
+
+/*
+ * Local static values
+ */
+
+static KA_T Kp; /* kernel process table address */
+static KA_T *Nc = (KA_T *)NULL; /* node cache */
+static int Nn = 0; /* number of Nc[] entries allocated */
+
+#if OSRV<500
+static int Npp = 0; /* number of pregions per process */
+static struct pregion *Pr = (struct pregion *)NULL;
+ /* pregion buffer */
+static int Prsz = 0; /* size of Pr */
+#endif /* OSRV<500 */
+
+
+static struct var Var; /* kernel variables */
+
+
+_PROTOTYPE(static void get_cdevsw,(void));
+_PROTOTYPE(static void get_kernel_access,(void));
+
+#if !defined(N_UNIX)
+_PROTOTYPE(static int is_boot,(char *p));
+#endif /* !defined(N_UNIX) */
+
+_PROTOTYPE(static int open_kmem,(int nx));
+_PROTOTYPE(static void process_text,(KA_T prp));
+_PROTOTYPE(static void readfsinfo,(void));
+
+
+/*
+ * Ckkv - check kernel version
+ */
+
+static void
+Ckkv(d, er, ev, ea)
+ char *d; /* dialect */
+ char *er; /* expected release */
+ char *ev; /* expected version */
+ char *ea; /* expected architecture */
+{
+
+#if defined(HASKERNIDCK)
+ struct scoutsname s;
+
+ if (Fwarn)
+ return;
+/*
+ * Read OSR kernel information.
+ */
+ if (__scoinfo(&s, sizeof(s)) < 0) {
+ (void) fprintf(stderr, "%s: can't get __scoinfo: %s\n",
+ Pn, strerror(errno));
+ Exit(1);
+ }
+/*
+ * Warn if the actual and expected releases don't match.
+ */
+ if (!er || strcmp(er, s.release))
+ (void) fprintf(stderr,
+ "%s: WARNING: compiled for %s release %s; this is %s.\n",
+ Pn, d, er ? er : "UNKNOWN", s.release);
+#endif /* defined(HASKERNIDCK) */
+
+}
+
+
+/*
+ * gather_proc_info() -- gather process information
+ */
+
+void
+gather_proc_info()
+{
+ int i, j, nf, pbc, px;
+ struct proc *p;
+ static char *pb = (char *)NULL;
+ int pid, pgrp;
+ short pss, sf;
+ static struct user *u;
+ static char *ua = (char *)NULL;
+ static MALLOC_S ual = 0;
+ unsigned int uid;
+
+#if defined(HASFSTRUCT)
+ static MALLOC_S npofb = 0;
+ char *pof;
+ static char *pofb = (char *)NULL;
+#endif /* defined(HASFSTRUCT) */
+
+/*
+ * Allocate user structure buffer.
+ */
+ if (!ua) {
+ ual = (MALLOC_S)(MAXUSIZE * NBPC);
+ if (!(ua = (char *)malloc(ual))) {
+ (void) fprintf(stderr,
+ "%s: no space for %d byte user structure buffer\n",
+ Pn, ual);
+ Exit(1);
+ }
+ u = (struct user *)ua;
+ }
+/*
+ * Allocate proc structure buffer.
+ */
+ if (!pb) {
+ if (!(pb = (char *)malloc(sizeof(struct proc) * PROCBFRD))) {
+ (void) fprintf(stderr, "%s: no space for %d proc structures\n",
+ Pn, PROCBFRD);
+ Exit(1);
+ }
+ }
+/*
+ * Examine proc structures and their associated information.
+ */
+ for (pbc = px = 0; px < Var.v_proc; px++) {
+ if (px >= pbc) {
+
+ /*
+ * Refill proc buffer.
+ */
+ i = Var.v_proc - px;
+ if (i > PROCBFRD)
+ i = PROCBFRD;
+ j = kread((KA_T)(Kp + (px * sizeof(struct proc))), pb,
+ sizeof(struct proc) * i);
+ pbc = px + i;
+ p = (struct proc *)pb;
+ if (j) {
+ px += i;
+ continue;
+ }
+ } else
+ p++;
+ if (p->p_stat == 0 || p->p_stat == SZOMB)
+ continue;
+ /*
+ * Get Process ID, Process group ID, and User ID.
+ */
+ pid = (int)p->p_pid;
+ pgrp = (int)p->p_pgrp;
+ uid = (unsigned int)p->p_uid;
+ if (is_proc_excl(pid, pgrp, (UID_ARG)uid, &pss, &sf))
+ continue;
+ /*
+ * Get the user area associated with the process.
+ */
+ if (sysi86(RDUBLK, pid, ua, MAXUSIZE * NBPC) == -1)
+ continue;
+ /*
+ * Allocate a local process structure.
+ */
+ if (is_cmd_excl(u->u_comm, &pss, &sf))
+ continue;
+ alloc_lproc(pid, pgrp, (int)p->p_ppid, (UID_ARG)uid, u->u_comm,
+ (int)pss, (int)sf);
+ Plf = (struct lfile *)NULL;
+ /*
+ * Save current working directory information.
+ */
+ if (u->u_cdir) {
+ alloc_lfile(CWD, -1);
+ process_node((KA_T)u->u_cdir);
+ if (Lf->sf)
+ link_lfile();
+ }
+ /*
+ * Save root directory information.
+ */
+ if (u->u_rdir) {
+ alloc_lfile(RTD, -1);
+ process_node((KA_T)u->u_rdir);
+ if (Lf->sf)
+ link_lfile();
+ }
+ /*
+ * Print information on the text file.
+ */
+ if (p->p_region)
+ process_text((KA_T)p->p_region);
+ /*
+ * Save information on file descriptors.
+ */
+
+#if OSRV<42
+ nf = Var.v_nofiles;
+#else /* OSRV>=42 */
+ nf = u->u_nofiles ? u->u_nofiles : Var.v_nofiles;
+#endif /* OSRV<42 */
+
+#if defined(HASFSTRUCT)
+ if (Fsv & FSV_FG) {
+
+ /*
+ * If u_pofile is in the u block, set its address.
+ */
+ if (nf && u->u_pofile
+ && ((unsigned)u->u_pofile >= UVUBLK)
+ && ((MALLOC_S)((unsigned)u->u_pofile - UVUBLK + nf) <= ual))
+ {
+ pof = ua + (unsigned)u->u_pofile - UVUBLK;
+ } else if (nf && u->u_pofile) {
+
+ /*
+ * Allocate space for u_pofile and read it from kernel memory.
+ */
+ if (nf > npofb) {
+ if (!pofb)
+ pofb = (char *)malloc((MALLOC_S)nf);
+ else
+ pofb = (char *)realloc((MALLOC_P *)pofb,
+ (MALLOC_S)nf);
+ if (!pofb) {
+ (void) fprintf(stderr, "%s: no pofile space\n", Pn);
+ Exit(1);
+ }
+ npofb = nf;
+ }
+ if (kread((KA_T)u->u_pofile, pofb, nf))
+ pof = (char *)NULL;
+ else
+ pof = pofb;
+ } else
+ pof = (char *)NULL;
+ }
+#endif /* defined(HASFSTRUCT) */
+
+ for (i = 0; i < nf; i++) {
+ if (u->u_ofile[i]) {
+ alloc_lfile((char *)NULL, i);
+ process_file((KA_T)u->u_ofile[i]);
+ if (Lf->sf) {
+
+#if defined(HASFSTRUCT)
+ if (Fsv & FSV_FG && pof)
+ Lf->pof = (long)pof[i];
+#endif /* defined(HASFSTRUCT) */
+
+ link_lfile();
+ }
+ }
+ }
+ /*
+ * Examine results.
+ */
+ if (examine_lproc())
+ return;
+ }
+}
+
+
+/*
+ * get_cdevsw() - get cdevsw[] names and record clone major device number
+ */
+
+void
+get_cdevsw()
+{
+ char buf[16];
+ struct cdevsw *c, *tmp;
+ int i, j, len;
+ struct stat sb;
+ KA_T v[2];
+/*
+ * Check cdevsw[] kernel addresses.
+ * Read cdevsw[] count from kernel's cdevcnt.
+ */
+ if (get_Nl_value("cdev", Drive_Nl, &v[0]) < 0
+ || get_Nl_value("ncdev", Drive_Nl, &v[1]) < 0
+ || !v[0] || !v[1]
+ || kread(v[1], (char *)&Cdevcnt, sizeof(Cdevcnt))
+ || Cdevcnt < 1)
+ return;
+/*
+ * Allocate cache space.
+ */
+ if (!(Cdevsw = (char **)malloc(Cdevcnt * sizeof(char *)))) {
+ (void) fprintf(stderr, "%s: no space for %d cdevsw[] names\n",
+ Pn, Cdevcnt);
+ Exit(1);
+ }
+/*
+ * Allocate temporary space for a copy of cdevsw[] and read it.
+ */
+ i = Cdevcnt * sizeof(struct cdevsw);
+ if (!(tmp = (struct cdevsw *)malloc(i))) {
+ (void) fprintf(stderr, "%s: no space for %d cdevsw[] entries\n",
+ Pn, Cdevcnt);
+ Exit(1);
+ }
+ if (kread((KA_T)v[0], (char *)tmp, i)) {
+ (void) free((FREE_P *)Cdevsw);
+ Cdevsw = (char **)NULL;
+ Cdevcnt = 0;
+ (void) free((FREE_P *)tmp);
+ return;
+ }
+/*
+ * Cache the names from cdevsw[].d_name.
+ * Record the number of the "clone" device.
+ */
+ j = sizeof(buf) - 1;
+ buf[j] = '\0';
+ for (c = tmp, i = 0; i < Cdevcnt; c++, i++) {
+ Cdevsw[i] = (char *)NULL;
+ if (!c->d_name)
+ continue;
+ if (kread((KA_T)c->d_name, buf, j)) {
+ (void) fprintf(stderr,
+ "%s: WARNING: can't read name for cdevsw[%d]: %#x\n",
+ Pn, i, c->d_name);
+ continue;
+ }
+ if (!buf[0])
+ continue;
+ len = strlen(buf) + 1;
+ if (!(Cdevsw[i] = (char *)malloc(len))) {
+ (void) fprintf(stderr, "%s: no space for cdevsw[%d] name: %s\n",
+ Pn, i, buf);
+ Exit(1);
+ }
+ (void) snpf(Cdevsw[i], len, "%s", buf);
+ if (!HaveCloneMajor && strcmp(buf, "clone") == 0) {
+ CloneMajor = i;
+ HaveCloneMajor = 1;
+ continue;
+ }
+ if (!HaveEventMajor && strcmp(buf, "ev") == 0) {
+ if (stat("/dev/event", &sb) == 0
+ && GET_MAJ_DEV(sb.st_rdev) == i) {
+ EventMajor = i;
+ HaveEventMajor = 1;
+ }
+ }
+ }
+ (void) free((FREE_P *)tmp);
+}
+
+
+/*
+ * get_kernel_access() - get access to kernel memory
+ */
+
+static void
+get_kernel_access()
+{
+ time_t lbolt;
+ MALLOC_S len;
+ KA_T v;
+/*
+ * Check kernel version.
+ */
+ (void) Ckkv("OSR", LSOF_VSTR, (char *)NULL, (char *)NULL);
+/*
+ * See if the name list file is readable.
+ */
+ if (Nmlst && !is_readable(Nmlst, 1))
+ Exit(1);
+/*
+ * Access kernel symbols.
+ */
+
+#if defined(N_UNIX)
+ (void) build_Nl(Drive_Nl);
+ if (nlist(Nmlst ? Nmlst : N_UNIX, Nl) < 0)
+#else /* !defined(N_UNIX) */
+ if (!get_nlist_path(0))
+#endif /* defined(N_UNIX) */
+
+ {
+ (void) fprintf(stderr, "%s: can't read kernel name list.\n", Pn);
+ Exit(1);
+ }
+/*
+ * Open access to kernel memory.
+ */
+ (void) open_kmem(0);
+
+#if defined(WILLDROPGID)
+/*
+ * Drop setgid permission.
+ */
+ (void) dropgid();
+#endif /* defined(WILLDROPGID) */
+
+/*
+ * Check proc table pointer.
+ */
+ if (get_Nl_value("proc", Drive_Nl, &Kp) < 0 || !Kp) {
+ (void) fprintf(stderr, "%s: no proc table pointer\n", Pn);
+ Exit(1);
+ }
+
+#if OSRV<500
+/*
+ * Read pregion information.
+ */
+ v = (KA_T)0;
+ if (get_Nl_value("pregpp", Drive_Nl, &v) < 0 || !v
+ || kread(v, (char *)&Npp, sizeof(Npp))
+ || Npp < 1) {
+ (void) fprintf(stderr,
+ "%s: can't read pregion count (%d) from %s\n", Pn, Npp,
+ print_kptr(v, (char *)NULL, 0));
+ Exit(1);
+ }
+ Prsz = (MALLOC_S)(Npp * sizeof(struct pregion));
+ if (!(Pr = (struct pregion *)malloc(Prsz))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate space for %d pregions\n",
+ Pn, Npp);
+ Exit(1);
+ }
+#endif /* OSRV< 500 */
+
+/*
+ * Read system configuration information.
+ */
+ if (get_Nl_value("var", Drive_Nl, &v) < 0 || !v
+ || kread((KA_T)v, (char *)&Var, sizeof(Var)))
+ {
+ (void) fprintf(stderr,
+ "%s: can't read system configuration info\n", Pn);
+ Exit(1);
+ }
+/*
+ * Read system clock values -- Hz and lightning bolt timer.
+ */
+ v = (KA_T)0;
+ if (get_Nl_value("hz", Drive_Nl, &v) < 0 || !v
+ || kread(v, (char *)&Hz, sizeof(Hz)))
+ {
+ if (!Fwarn)
+ (void) fprintf(stderr, "%s: WARNING: can't read Hz from %s\n",
+ Pn, print_kptr(v, (char *)NULL, 0));
+ Hz = -1;
+ }
+ if (get_Nl_value("lbolt", Drive_Nl, &Lbolt) < 0 || !v
+ || kread((KA_T)v, (char *)&lbolt, sizeof(lbolt)))
+ {
+ if (!Fwarn)
+ (void) fprintf(stderr,
+ "%s: WARNING: can't read lightning bolt timer from %s\n",
+ Pn, print_kptr(v, (char *)NULL, 0));
+ Lbolt = (KA_T)0;
+ }
+/*
+ * Get socket device number and socket table address.
+ */
+ if (get_Nl_value("sockd", Drive_Nl, &v) < 0 || !v
+ || kread(v, (char *)&Sockdev, sizeof(Sockdev)))
+ {
+ (void) fprintf(stderr,
+ "%s: WARNING: can't identify socket device.\n", Pn);
+ (void) fprintf(stderr,
+ " Socket output may be incomplete.\n");
+ return;
+ }
+ if (get_Nl_value("sockt", Drive_Nl, &Socktab) < 0 || !Socktab) {
+ (void) fprintf(stderr,
+ "%s: WARNING: socket table address is NULL.\n", Pn);
+ (void) fprintf(stderr,
+ " Socket output may be incomplete.\n");
+ return;
+ }
+
+#if OSRV>=40
+/*
+ * Get extended device table parameters. These are needed by the kernel
+ * versions of the major() and minor() device number macros; they also
+ * identify socket devices and assist in the conversion of socket device
+ * numbers to socket table addresses.
+ */
+ v = (KA_T)0;
+ if (get_Nl_value("nxdm", Drive_Nl, &v) < 0 || !v
+ || kread(v, (char *)&nxdevmaps, sizeof(nxdevmaps))
+ || nxdevmaps < 0)
+ {
+ (void) fprintf(stderr,
+ "%s: bad extended device table size (%d) at %s.\n",
+ Pn, nxdevmaps, print_kptr(v, (char *)NULL, 0));
+ Exit(1);
+ }
+ len = (MALLOC_S)((nxdevmaps + 1) * sizeof(struct XDEVMAP));
+ if (!(Xdevmap = (struct XDEVMAP *)malloc(len))) {
+ (void) fprintf(stderr, "%s: no space for %d byte xdevmap table\n",
+ Pn, len);
+ Exit(1);
+ }
+ v = (KA_T)0;
+ if (get_Nl_value("xdm", Drive_Nl, &v) < 0 || !v
+ || kread((KA_T)v, (char *)Xdevmap, len))
+ {
+ (void) fprintf(stderr,
+ "%s: can't read %d byte xdevmap table at #x\n", Pn, len, v);
+ Exit(1);
+ }
+#endif /* OSRV>=40 */
+
+ HaveSockdev = 1;
+}
+
+
+#if !defined(N_UNIX)
+/*
+ * get_nlist_path() - get kernel nlist() path
+ *
+ * As a side effect on a successful return (non-NULL character pointer), the
+ * boot path's name list will have been loaded into Nl[].
+ */
+
+char *
+get_nlist_path(ap)
+ int ap; /* on success, return an allocated path
+ * string pointer if 1; return a
+ * constant character pointer if 0;
+ * return NULL if failure */
+{
+ FILE *bf;
+ char *bfp, b1[MAXPATHLEN+1], b2[MAXPATHLEN+1], *pp, *tp;
+ struct dirent *de;
+ char *dir[] = { "/", "/stand/", NULL };
+ DIR *dp;
+ int i;
+ MALLOC_S len;
+/*
+ * If a kernel name list file was specified, use it.
+ */
+ if (Nmlst) {
+ if (is_boot(Nmlst))
+ return(Nmlst);
+ return((char *)NULL);
+ }
+/*
+ * If it's possible to open /etc/ps/booted system, search it for a preferred
+ * boot path, defined by the value of a line that begins with "KERNEL=".
+ */
+ bfp = pp = (char *)NULL;
+ if ((bf = fopen("/etc/ps/booted.system", "r"))) {
+ len = strlen("KERNEL=");
+ while (fgets(b1, sizeof(b1), bf)) {
+ if (strncmp(b1, "KERNEL=", len) != 0)
+ continue;
+ if ((tp = strrchr(&b1[len], '\n'))) {
+ *tp = '\0';
+ if (b1[len]) {
+ bfp = &b1[len];
+ if (is_boot(bfp)) {
+ pp = bfp;
+ (void) fclose(bf);
+ goto get_nlist_return_path;
+ }
+ break;
+ }
+ }
+ }
+ (void) fclose(bf);
+ }
+/*
+ * Look for possible unix* boot paths.
+ */
+ for (i = 0; dir[i]; i++) {
+ if (!(dp = opendir(dir[i])))
+ continue;
+ while ((de = readdir(dp))) {
+
+ /*
+ * Use the next entry that begins with "unix".
+ */
+ if (strncmp("unix", de->d_name, 4) != 0)
+ continue;
+ /*
+ * Construct a temporary copy of the path name,
+ * If it matches the preferred boot name, skip it.
+ */
+ len = strlen(dir[i]) + strlen(de->d_name) + 1;
+ if (len >= sizeof(b2))
+ continue;
+ (void) snpf(b2, sizeof(b2), "%s%s", dir[i], de->d_name);
+ if (bfp && strcmp(b2, bfp) == 0)
+ continue;
+ /*
+ * See if it's the booted kernel.
+ */
+ if (is_boot(b2)) {
+ (void) closedir(dp);
+ pp = b2;
+
+get_nlist_return_path:
+
+ /*
+ * A boot path has been located. As requested return a
+ * malloc'd pointer to it.
+ */
+ if (!ap)
+ return("");
+ len = (MALLOC_S)(strlen(pp) + 1);
+ if (!(tp = (char *)malloc(len))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d bytes for: %s\n",
+ Pn, len , pp);
+ Exit(1);
+ }
+ (void) snpf(tp, len, "%s", pp);
+ return(tp);
+ }
+ }
+ if (dp)
+ (void) closedir(dp);
+ }
+ return((char *)NULL);
+}
+#endif /* !defined(N_UNIX) */
+
+
+/*
+ * initialize() - perform all initialization
+ */
+
+void
+initialize()
+{
+ get_kernel_access();
+ get_cdevsw();
+ readfsinfo();
+ if (Fsv & FSV_NI)
+ NiTtl = "INODE-ADDR";
+}
+
+
+#if !defined(N_UNIX)
+/*
+ * is_boot() - does the specified path lead to a booted kernel
+ */
+
+is_boot(p)
+ char *p; /* specified path */
+{
+ int i;
+ KA_T ka;
+ union {
+ struct scoutsname s;
+ unsigned char sc[sizeof(struct scoutsname)];
+ } s1, s2;
+/*
+ * Get the scoutsname structure via __scoinfo() to use as a reference against
+ * the one obtained via kread()'ing from the nlist(<possible_kernel>) address.
+ * If __scoinfo() fails, return the default boot path.
+ */
+ if (__scoinfo(&s1.s, sizeof(s1.s)) < 0)
+ return 0;
+/*
+ * Get the name list for this boot path. Using the scoutsname address, read
+ * the scoutsname structure and compare it to the _s_scoinfo() one. If the
+ * two match, this is the boot path.
+ */
+ if (Nl) {
+ (void) free((FREE_P *)Nl);
+ Nl = (struct NLIST_TYPE *)NULL;
+ }
+ (void) build_Nl(Drive_Nl);
+ if (nlist(p, Nl) < 0)
+ return(0);
+ if (get_Nl_value("scouts", Drive_Nl, &ka) < 0 || !ka)
+ return(0);
+ if (Kd < 0) {
+ if (open_kmem(1))
+ return(0);
+ }
+ if (kread(ka, (char *)&s2.s, sizeof(s2.s)))
+ return(0);
+ for (i = 0; i < sizeof(struct scoutsname); i++) {
+ if (s1.sc[i] != s2.sc[i])
+ return(0);
+ }
+ return(1);
+}
+#endif /* !defined(N_UNIX) */
+
+
+/*
+ * kread() - read from kernel memory
+ */
+
+int
+kread(addr, buf, len)
+ KA_T addr; /* kernel memory address */
+ char *buf; /* buffer to receive data */
+ READLEN_T len; /* length to read */
+{
+ int br;
+
+ if (lseek(Kd, (off_t)addr, SEEK_SET) == (off_t)-1L)
+ return(1);
+ if ((br = read(Kd, buf, len)) < 0)
+ return(1);
+ return(((READLEN_T)br == len) ? 0 : 1);
+}
+
+
+/*
+ * open_kmem() - open kernel memory access
+ */
+
+static int
+open_kmem(nx)
+ int nx; /* no Exit(1) if 1 */
+{
+ if (Kd >= 0)
+ return(0);
+/*
+ * See if the non-KMEM memory file is readable.
+ */
+ if (Memory && !is_readable(Memory, 1)) {
+ if (nx)
+ return(1);
+ Exit(1);
+ }
+/*
+ * Open kernel memory access.
+ */
+ if ((Kd = open(Memory ? Memory : KMEM, O_RDONLY, 0)) < 0) {
+ if (nx)
+ return(1);
+ (void) fprintf(stderr, "%s: can't open %s: %s\n", Pn,
+ Memory ? Memory : KMEM, strerror(errno));
+ Exit(1);
+ }
+ return(0);
+}
+
+
+/*
+ * process_text() - process text access information
+ */
+
+static void
+process_text(prp)
+ KA_T prp; /* process region pointer */
+{
+ int i, j, k;
+ struct pregion *p;
+ struct region r;
+ KA_T na;
+ char *ty, tyb[8];
+
+#if OSRV>=500
+ KA_T pc;
+ struct pregion ps;
+#endif /* OSRV>=500 */
+
+/*
+ * Read and process the pregions.
+ */
+
+#if OSRV<500
+ if (kread(prp, (char *)Pr, Prsz))
+ return;
+ for (i = j = 0, p = Pr; i < Npp; i++, p++)
+#else /* OSRV>=500 */
+ for (i = j = 0, p = &ps, pc = prp; pc; pc = (KA_T)p->p_next, i++)
+#endif /* OSRV<500 */
+
+ {
+
+#if OSRV>=500
+ /*
+ * Avoid infinite loop.
+ */
+ if (i > 1000) {
+ if (!Fwarn)
+ (void) fprintf(stderr,
+ "%s: too many virtual address regions for PID %d\n",
+ Pn, Lp->pid);
+ return;
+ }
+ if ((i && pc == prp)
+ || kread((KA_T)pc, (char *)p, sizeof(ps)))
+ return;
+#endif /* OSRV>=500 */
+
+ if (!p->p_reg)
+ continue;
+ /*
+ * Read the region.
+ * Skip entries with no node pointers and duplicate node addresses.
+ */
+ if (kread((KA_T)p->p_reg, (char *)&r, sizeof(r)))
+ continue;
+ if (!(na = (KA_T)r.r_iptr))
+ continue;
+ for (k = 0; k < j; k++) {
+ if (Nc[k] == na)
+ break;
+ }
+ if (k < j)
+ continue;
+ /*
+ * Cache the node address for duplicate checking.
+ */
+ if (!Nc) {
+ if (!(Nc = (KA_T *)malloc((MALLOC_S)(sizeof(KA_T) * 10)))) {
+ (void) fprintf(stderr, "%s: no txt ptr space, PID %d\n",
+ Pn, Lp->pid);
+ Exit(1);
+ }
+ Nn = 10;
+ } else if (j >= Nn) {
+ Nn += 10;
+ if (!(Nc = (KA_T *)realloc((MALLOC_P *)Nc,
+ (MALLOC_S)(Nn * sizeof(KA_T)))))
+ {
+ (void) fprintf(stderr,
+ "%s: no more txt ptr space, PID %d\n", Pn, Lp->pid);
+ Exit(1);
+ }
+ }
+ Nc[j++] = na;
+ /*
+ * Save text node and mapped region information.
+ */
+ switch (p->p_type) {
+ case PT_DATA: /* data and text of */
+ case PT_TEXT: /* executing binaries */
+ ty = " txt";
+ break;
+ case PT_LIBDAT: /* shared library data and */
+ case PT_LIBTXT: /* COFF format text */
+ ty = " ltx";
+ break;
+ case PT_SHFIL: /* memory mapped file */
+ ty = " mem";
+ break;
+ case PT_V86: /* virtual 8086 mode */
+ ty = " v86";
+ break;
+ case PT_VM86: /* MERGE386 vm86 region */
+ ty = " m86";
+ break;
+ default: /* all others as a hex number */
+ (void) snpf(tyb, sizeof(tyb), " M%02x", p->p_type & 0xff);
+ ty = tyb;
+ }
+ if (ty) {
+ alloc_lfile(ty, -1);
+ process_node(na);
+ if (Lf->sf)
+ link_lfile();
+ }
+ }
+}
+
+
+/*
+ * readfsinfo() - read file system information
+ */
+
+static void
+readfsinfo()
+{
+ char buf[FSTYPSZ+1];
+ int i, len;
+
+ if ((Fsinfomax = sysfs(GETNFSTYP)) == -1) {
+ (void) fprintf(stderr, "%s: sysfs(GETNFSTYP) error: %s\n",
+ Pn, strerror(errno));
+ Exit(1);
+ }
+ if (Fsinfomax == 0)
+ return;
+ if (!(Fsinfo = (char **)malloc((MALLOC_S)(Fsinfomax * sizeof(char *)))))
+ {
+ (void) fprintf(stderr, "%s: no space for sysfs info\n", Pn);
+ Exit(1);
+ }
+ for (i = 1; i <= Fsinfomax; i++) {
+ if (sysfs(GETFSTYP, i, buf) == -1) {
+ (void) fprintf(stderr, "%s: sysfs(GETFSTYP) error: %s\n",
+ Pn, strerror(errno));
+ Exit(1);
+ }
+ buf[FSTYPSZ] = '\0';
+ len = strlen(buf) + 1;
+ if (!(Fsinfo[i-1] = (char *)malloc((MALLOC_S)len))) {
+ (void) fprintf(stderr,
+ "%s: no space for file system entry %s\n", Pn, buf);
+ Exit(1);
+ }
+ (void) snpf(Fsinfo[i-1], len, "%s", buf);
+ }
+}
+
+
+#if defined(HASNCACHE)
+
+/*
+ * Prepare for and #include the appropriate header files.
+ */
+
+# if OSRV>=500
+#undef IFIR
+#undef IFIW
+#undef IRCOLL
+#undef IWCOLL
+# endif /* OSRV>=500 */
+
+#include <sys/fs/s5inode.h>
+
+# if defined(HAS_NFS)
+#include <sys/fs/nfs/dnlc.h>
+# endif /* defined(HAS_NFS) */
+
+# if OSRV>=500
+# if OSRV<504
+#include <sys/fs/dtdnlc.h>
+#undef IFIR
+#undef IFIW
+#undef IRCOLL
+#undef IWCOLL
+#define _INKERNEL
+#include <sys/fs/htinode.h>
+#undef _INKERNEL
+# else /* OSRV>=504 */
+#include <sys/fs/dnlc.h>
+# endif /* OSRV<504 */
+# endif /* OSRV>=500 */
+
+
+/*
+ * Determine the maximum size of the cache name character array.
+ */
+
+# if OSRV<504
+#define MAXNSZ DIRSIZ
+# if OSRV>=500 && DTNCMAX>MAXNSZ
+#undef MAXNSZ
+#define MAXNSZ DTNCMAX
+# endif /* OSRV>=500 && DTNCMAX>MAXNSZ */
+# else /* OSRV>=504 */
+#define MAXNSZ DNLC_NAMELEN
+# endif /* OSRV<504 */
+
+# if defined(HAS_NFS) && NC_NAMLEN>MAXNSZ
+#undef MAXNSZ
+#define MAXNSZ NC_NAMLEN
+# endif /* defined(HAS_NFS) && NC_NAMLEN>MAXNSZ */
+
+
+/*
+ * Define the local name cache structures.
+ */
+
+struct lnch { /* local name cache structure */
+ union {
+ struct ldev { /* device-inode info */
+ dev_t dev; /* device */
+ unsigned long inum; /* inode number */
+ unsigned long pa_inum; /* parent inode number */
+ } ld;
+ struct lnfs { /* NFS info */
+ KA_T rp; /* rnode address */
+ KA_T dp; /* parent rnode address */
+ } ln;
+ } u;
+ char nm[MAXNSZ+1]; /* name */
+ unsigned char nl; /* name length */
+ unsigned char dup; /* duplicate if 1 */
+ unsigned char type; /* type: 0 = device-inode; 1 = NFS */
+ struct lnch *pa; /* parent address */
+ struct lnch *next; /* link to next same-type structure */
+};
+
+struct lnch_hh { /* device-inode and NFS hash head */
+ struct lnch *hp[2]; /* [0] = device-inode; [1] = NFS*/
+};
+
+
+/*
+ * Local name cache (LNC) definitions, macros, and static values
+ */
+
+#define LCHUNKSZ 256 /* local "chunk" size for reading the
+ * kernel DNLC -- used for OSRV>=504 */
+static int LNC_asz = 0; /* LNC cache allocated size */
+static int LNC_csz = 0; /* LNC cache current size */
+#define LNCHHLEN 64 /* hash head length (must be a
+ * power of 2) */
+#define LNCINCR 256 /* LNC size increment */
+#define LNCINIT 1024 /* LNC initial size */
+
+#define DIN_hash(d, i) &LNC_hh[((((int)(d + i)>>2)*31415)&(LNCHHLEN-1))]
+
+# if defined(HAS_NFS)
+#define NFS_hash(r) &LNC_hh[((((int)(r)>>2)*31415)&(LNCHHLEN-1))]
+# endif /* defined(HAS_NFS) */
+
+static struct lnch_hh *LNC_hh = (struct lnch_hh *)NULL;
+ /* LNC hash head pointers */
+static struct lnch *LNC_nc = (struct lnch *)NULL;
+ /* the linear LNC */
+
+
+/*
+ * Local function prototypes
+ */
+
+_PROTOTYPE(static struct lnch *DIN_addr,(dev_t *d, unsigned long i));
+
+# if OSRV>=500
+# if OSRV>=504
+_PROTOTYPE(static void DNLC_load,());
+# else /* OSRV<504 */
+_PROTOTYPE(static void DTFS_load,());
+_PROTOTYPE(static void HTFS_load,());
+# endif /* OSRV>=504 */
+# endif /* OSRV>=500 */
+
+_PROTOTYPE(static int LNC_enter,(struct lnch *le, char *nm, int nl, char *fs));
+_PROTOTYPE(static void LNC_nosp,(int len));
+
+# if defined(HAS_NFS)
+_PROTOTYPE(static struct lnch *NFS_addr,(KA_T r));
+_PROTOTYPE(static void NFS_load,(void));
+_PROTOTYPE(static int NFS_root,(KA_T r));
+# endif /* defined(HAS_NFS) */
+
+# if OSRV<504
+_PROTOTYPE(static void SYSV_load,());
+# endif /* OSRV<504 */
+
+
+/*
+ * DIN_addr() - look up a node's local device-inode address
+ */
+
+static struct lnch *
+DIN_addr(d, i)
+ dev_t *d; /* device number */
+ unsigned long i; /* inode number */
+{
+ struct lnch_hh *hh = DIN_hash(*d, i);
+ struct lnch *lc = hh->hp[0];
+
+ while (lc) {
+ if (lc->u.ld.dev == *d && lc->u.ld.inum == i)
+ return(lc);
+ lc = lc->next;
+ }
+ return((struct lnch *)NULL);
+}
+
+
+# if OSRV>=504
+/*
+ * DNLC_load() - load DNLC cache
+ */
+
+static void
+DNLC_load()
+{
+ int ccl; /* current "chunk" length */
+ int ccs; /* current "chunk" size */
+ int ccx; /* current "chunk" index */
+ static int cha = 0; /* "chunk" allocation size */
+ static int chl = 0; /* "chunk" allocation length */
+ struct dnlc__cachent *cp;
+ static struct dnlc__cachent *dnlc = (struct dnlc__cachent *)NULL;
+ static int dnlce = 0;
+ int i, len;
+ static KA_T ka = (KA_T)0;
+ struct lnch lc;
+ char nm[DNLC_NAMELEN+1];
+ KA_T v;
+ char *wa; /* "working" kernel DNLC
+ * address */
+/*
+ * Do first-time setup, as required.
+ */
+ if (dnlce == 0) {
+
+ /*
+ * Quit if the DNLC name cache address is unknown.
+ */
+ if (get_Nl_value("dnlc", Drive_Nl, &ka) < 0 || !ka)
+ return;
+ /*
+ * Determine of the DNLC name cache address is that of an array or a
+ * pointer to the array.
+ */
+ v = (KA_T)NULL;
+ if (get_Nl_value("pdnlc", Drive_Nl, &v) >= 0 && v) {
+
+ /*
+ * If the DNLC name cache address is that of a pointer to an array,
+ * get the array's address. If that fails, return without comment
+ * and without further action.
+ */
+ if (kread(ka, (char *)&ka, sizeof(ka)))
+ return;
+ }
+ /*
+ * Get the kernel's DNLC name cache size.
+ */
+ if (get_Nl_value("ndnlc", Drive_Nl, &v) < 0 || !v
+ || kread(v, (char *)&dnlce, sizeof(dnlce))
+ || dnlce < 1)
+ return;
+ /*
+ * Allocate space for a copy of a portion ("chunk") of the kernel's
+ * DNLC name cache.
+ */
+ cha = (dnlce <= LCHUNKSZ) ? dnlce : LCHUNKSZ;
+ chl = sizeof(struct dnlc__cachent) * cha;
+ if (!(dnlc = (struct dnlc__cachent *)malloc(chl))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d bytes for DNLC chunk\n",
+ Pn, chl);
+ cha = 0;
+ Exit(1);
+ }
+ }
+/*
+ * Prepare to read the kernel's DNLC name cache.
+ */
+ if (!cha || !chl || !dnlc || !ka)
+ return;
+/*
+ * Build a local copy of the kernel's DNLC name cache, reading the kernel data
+ * a "chunk" at a time.
+ */
+ nm[DNLC_NAMELEN] = '\0';
+ lc.type = 0;
+ for (ccl = ccs = i = 0, wa = (char *)ka; i < dnlce; i += ccs, wa += ccl)
+ {
+
+ /*
+ * Read the next "chunk".
+ */
+ ccs = ((dnlce - i) < cha) ? (dnlce - i) : cha;
+ ccl = sizeof(struct dnlc__cachent) * ccs;
+ if (kread((KA_T)wa, (char *)dnlc, ccl))
+ break;
+ /*
+ * Process the "chunk".
+ */
+ for (ccx = 0, cp = dnlc; ccx < ccs; cp++, ccx++) {
+ if (!cp->dev && !cp->newinum)
+ continue;
+ (void) strncpy(nm, cp->name, DNLC_NAMELEN);
+ if ((len = strlen(nm)) < 1)
+ continue;
+ if (len < 3 && nm[0] == '.') {
+ if (len == 1 || (len == 2 && nm[1] == '.'))
+ continue;
+ }
+ lc.u.ld.dev = cp->dev;
+ lc.u.ld.inum = (unsigned long)cp->newinum;
+ lc.u.ld.pa_inum = (unsigned long)cp->inum;
+ if (LNC_enter(&lc, nm, len, "DNLC"))
+ break;
+ }
+ }
+/*
+ * If not repeating, free kernel DNLC name cache buffer space.
+ */
+ if (dnlc && !RptTm) {
+ (void) free((MALLOC_P *)dnlc);
+ dnlc = (struct dnlc__cachent *)NULL;
+ dnlce = cha = chl = 0;
+ }
+}
+# endif /* OSRV>=504 */
+
+
+# if OSRV>=500 && OSRV<504
+/*
+ * DTFS_load() - load DTFS cache
+ */
+
+static void
+DTFS_load()
+{
+ struct dtcachent *cp;
+ static struct dtcachent *dtnc = (struct dtcachent *)NULL;
+ static int dtnce = 0;
+ int i, len;
+ static KA_T ka = (KA_T)NULL;
+ static int kcl = 0;
+ struct lnch lc;
+ char nm[DTNCMAX+1];
+ KA_T v;
+/*
+ * Do first-time setup, as required.
+ */
+ if (dtnce == 0) {
+
+ /*
+ * Quit if the DTFS name cache address is unknown.
+ */
+ if (get_Nl_value("dtnc", Drive_Nl, &ka) < 0 || !ka)
+ return;
+ /*
+ * Get the kernel's DTFS name cache size.
+ */
+ if (get_Nl_value("ndtnc", Drive_Nl, &v) < 0 || !v
+ || kread(v, (char *)&dtnce, sizeof(dtnce))
+ || dtnce < 1)
+ return;
+ /*
+ * Allocate space for a copy of the kernel's DTFS name cache.
+ */
+ kcl = sizeof(struct dtcachent) * dtnce;
+ if (!(dtnc = (struct dtcachent *)malloc(kcl))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d bytes for DTFS name cache\n",
+ Pn, kcl);
+ Exit(1);
+ }
+ }
+/*
+ * Read the kernel's DTFS name cache.
+ */
+ if (!dtnc || !kcl || !ka || kread(ka, (char *)dtnc, kcl))
+ return;
+/*
+ * Build a local copy of the kernel's DTFS name cache.
+ */
+ lc.type = 0;
+ nm[DTNCMAX] = '\0';
+ for (cp = dtnc, i = 0; i < dtnce; cp++, i++) {
+ if (!cp->dn_dev && !cp->dn_newinum)
+ continue;
+ (void) strncpy(nm, cp->dn_name, DTNCMAX);
+ if ((len = strlen(nm)) < 1)
+ continue;
+ if (len < 3 && cp->dn_name[0] == '.') {
+ if (len == 1 || (len == 2 && cp->dn_name[1] == '.'))
+ continue;
+ }
+ lc.u.ld.dev = cp->dn_dev;
+ lc.u.ld.inum = (unsigned long)cp->dn_newinum;
+ lc.u.ld.pa_inum = (unsigned long)cp->dn_inum;
+ if (LNC_enter(&lc, nm, len, "DTFS"))
+ break;
+ }
+/*
+ * If not repeating, free kernel DTFS name cache buffer space.
+ */
+ if (dtnc && !RptTm) {
+ (void) free((MALLOC_P *)dtnc);
+ dtnc = (struct dtcachent *)NULL;
+ dtnce = kcl = 0;
+ }
+}
+
+
+/*
+ * HTFS_load() - load HTFS cache
+ */
+
+static void
+HTFS_load()
+{
+ struct htcachent *cp;
+ static struct htcachent *htnc = (struct htcachent *)NULL;
+ static int htnce = 0;
+ int i, len;
+ static KA_T ka = (KA_T)NULL;
+ static int kcl = 0;
+ struct lnch lc;
+ char nm[DIRSIZ+1];
+ KA_T v;
+/*
+ * Do first-time setup, as required.
+ */
+ if (htnce == 0) {
+
+ /*
+ * Quit if the HTFS name cache address is unknown.
+ */
+ if (get_Nl_value("htnc", Drive_Nl, &ka) < 0 || !ka)
+ return;
+ /*
+ * Get the kernel's HTFS name cache size.
+ */
+ if (get_Nl_value("nhtnc", Drive_Nl, &v) < 0 || !v
+ || kread(v, (char *)&htnce, sizeof(htnce))
+ || htnce < 1)
+ return;
+ /*
+ * Allocate space for a copy of the kernel's HTFS name cache.
+ */
+ kcl = sizeof(struct htcachent) * htnce;
+ if (!(htnc = (struct htcachent *)malloc(kcl))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d bytes for HTFS name cache\n",
+ Pn, kcl);
+ Exit(1);
+ }
+ }
+/*
+ * Read the kernel's HTFS name cache.
+ */
+ if (!htnc || !kcl || !ka || kread(ka, (char *)htnc, kcl))
+ return;
+/*
+ * Build a local copy of the kernel's HTFS name cache.
+ */
+ lc.type = 0;
+ nm[DIRSIZ] = '\0';
+ for (cp = htnc, i = 0; i < htnce; cp++, i++) {
+ if (!cp->dev && !cp->newinum)
+ continue;
+ (void) strncpy(nm, cp->name, DIRSIZ);
+ if ((len = strlen(nm)) < 1)
+ continue;
+ if (len < 3 && cp->name[0] == '.') {
+ if (len == 1 || (len == 2 && cp->name[1] == '.'))
+ continue;
+ }
+ lc.u.ld.dev = (dev_t)cp->dev;
+ lc.u.ld.inum = (unsigned long)cp->newinum;
+ lc.u.ld.pa_inum = (unsigned long)cp->inum;
+ if (LNC_enter(&lc, nm, len, "HTFS"))
+ break;
+ }
+/*
+ * If not repeating, free kernel HTFS name cache buffer space.
+ */
+ if (htnc && !RptTm) {
+ (void) free((MALLOC_P *)htnc);
+ htnc = (struct htcachent *)NULL;
+ htnce = kcl = 0;
+ }
+}
+# endif /* OSRV>=500 && OSRV<504 */
+
+
+/*
+ * LNC_enter() - make a local name cache entry
+ */
+
+static int
+LNC_enter(le, nm, nl, fs)
+ struct lnch *le; /* skeleton local entry */
+ char *nm; /* name */
+ int nl; /* name length */
+ char *fs; /* file system name */
+{
+ struct lnch *lc;
+ MALLOC_S len;
+
+ if (LNC_csz >= LNC_asz) {
+ LNC_asz += LNCINCR;
+ len = (MALLOC_S)(LNC_asz * sizeof(struct lnch));
+ if (!(LNC_nc = (struct lnch *)realloc(LNC_nc, len))) {
+ (void) fprintf(stderr,
+ "%s: no more space for %d byte local name cache: %s\n",
+ Pn, len, fs);
+ Exit(1);
+ }
+ }
+ lc = &LNC_nc[LNC_csz];
+ if ((lc->type = le->type) == 1) {
+
+ /*
+ * Make an NFS entry.
+ */
+ lc->u.ln.rp = le->u.ln.rp;
+ lc->u.ln.dp = le->u.ln.dp;
+ } else {
+
+ /*
+ * Make a device-inode entry.
+ */
+ lc->u.ld.dev = le->u.ld.dev;
+ lc->u.ld.inum = le->u.ld.inum;
+ lc->u.ld.pa_inum = le->u.ld.pa_inum;
+ }
+/*
+ * Enter the name and its size, clear the duplicate flag,
+ * and advance the linear cache entry count.
+ */
+ if (nl > MAXNSZ) {
+ if (!Fwarn)
+ (void) fprintf(stderr,
+ "%s: WARNING: length for \"%s\" too large: %d\n",
+ Pn, nm, nl);
+ nl = MAXNSZ;
+ }
+ (void) strncpy(lc->nm, nm, nl);
+ lc->nm[nl] = '\0';
+ lc->nl = (unsigned char)nl;
+ lc->dup = 0;
+ lc->next = lc->pa = (struct lnch *)NULL;
+ LNC_csz++;
+ return(0);
+}
+
+
+/*
+ * LNC_nosp() - notify that we're out of space for the local name cache
+ */
+
+static void
+LNC_nosp(len)
+ int len; /* attempted length */
+{
+ if (!Fwarn)
+ (void) fprintf(stderr,
+ "%s: no space for %d byte local name cache\n",
+ Pn, len);
+ Exit(1);
+}
+
+
+/*
+ * ncache_load() - load the kernel's NFS and DEV name caches
+ */
+
+void
+ncache_load()
+{
+ struct lnch_hh *hh;
+ struct lnch *hl, *hlp, *lc;
+ int f, i, len;
+
+ if (!Fncache)
+ return;
+/*
+ * Initialize local name cache, as required.
+ */
+ if (LNC_asz == 0) {
+ LNC_asz = LNCINIT;
+ len = LNCINIT * sizeof(struct lnch);
+ if (!(LNC_nc = (struct lnch *)malloc((MALLOC_S)len)))
+ (void) LNC_nosp(len);
+ }
+ LNC_csz = 0;
+
+# if defined(HAS_NFS)
+/*
+ * Load NFS cache.
+ */
+ (void) NFS_load();
+# endif /* defined(HAS_NFS) */
+
+# if OSRV<504
+/*
+ * Load the device-inode SYSV file system cache.
+ */
+ (void) SYSV_load();
+
+# if OSRV>=500
+/*
+ * Load the device-inode DT and HT file system caches.
+ */
+ (void) DTFS_load();
+ (void) HTFS_load();
+# endif /* OSRV>=500 */
+# else /* OSRV>=504 */
+/*
+ * Load the device-inode combined file system cache.
+ */
+ (void) DNLC_load();
+# endif /* OSRV<504 */
+
+/*
+ * Reduce local name cache memory usage, as required.
+ */
+ if (LNC_csz < 1) {
+ LNC_csz = 0;
+ if (!RptTm) {
+ (void) free((FREE_P *)LNC_nc);
+ LNC_nc = (struct lnch *)NULL;
+ }
+ return;
+ }
+ if (LNC_csz < LNC_asz && !RptTm) {
+ len = LNC_csz * sizeof(struct lnch);
+ if (!(LNC_nc = (struct lnch *)realloc(LNC_nc, len)))
+ (void)LNC_nosp(len);
+ LNC_asz = LNC_csz;
+ }
+/*
+ * Initialize hash head pointers.
+ */
+ if (!LNC_hh) {
+ LNC_hh = (struct lnch_hh *)calloc(LNCHHLEN, sizeof(struct lnch_hh));
+ if (!LNC_hh) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d bytes for name cache hash table\n",
+ Pn, LNCHHLEN * sizeof(struct lnch_hh));
+ Exit(1);
+ }
+ } else
+ (void) zeromem((void *)LNC_hh, (LNCHHLEN * sizeof(struct lnch_hh)));
+/*
+ * Enter local name cache pointers in the hash table. Look for entries with
+ * the same identifications that have different names.
+ */
+ for (i = 0, lc = LNC_nc; i < LNC_csz; i++, lc++) {
+
+# if defined(HAS_NFS)
+ if (lc->type)
+ hh = NFS_hash(lc->u.ln.rp);
+ else
+# endif /* defined(HAS_NFS) */
+
+ hh = DIN_hash(lc->u.ld.dev, lc->u.ld.inum);
+ if (!(hl = hh->hp[lc->type])) {
+ hh->hp[lc->type] = lc;
+ continue;
+ }
+ for (f = 0, hlp = hl; hl; hlp = hl, hl = hl->next) {
+
+# if defined(HAS_NFS)
+ if (lc->type == 1) {
+ if (lc->u.ln.rp != hl->u.ln.rp)
+ continue;
+ } else
+# endif /* defined(HAS_NFS) */
+
+ {
+ if (lc->u.ld.dev != hl->u.ld.dev
+ || lc->u.ld.inum != hl->u.ld.inum)
+ continue;
+ }
+ if (strcmp(lc->nm, hl->nm) == 0)
+ f = 1;
+ else {
+ f = 2; /* same identifiers, different names */
+ break;
+ }
+ }
+ if (!f)
+ hlp->next = lc;
+ else if (f == 2) {
+
+ /*
+ * Since entries with the same identification but different names
+ * were located, mark entries with the same identification as
+ * duplicates.
+ */
+ for (hl = hh->hp[lc->type]; hl; hl = hl->next) {
+
+# if defined(HAS_NFS)
+ if (lc->type == 1) {
+ if (lc->u.ln.rp == hl->u.ln.rp)
+ hl->dup = 1;
+ continue;
+ }
+# endif /* defined(HAS_NFS) */
+
+ if (hl->u.ld.dev == lc->u.ld.dev
+ && hl->u.ld.inum == lc->u.ld.inum)
+ hl->dup = 1;
+ }
+ }
+ }
+/*
+ * Make a final pass through the local name cache and convert parent
+ * identifications to local name cache pointers. Ignore duplicates.
+ */
+ for (i = 0, lc = LNC_nc; i < LNC_csz; i++, lc++) {
+ if (lc->dup)
+ continue;
+
+# if defined(HAS_NFS)
+ if (lc->type == 1) {
+ if (lc->u.ln.dp)
+ lc->pa = NFS_addr(lc->u.ln.dp);
+ continue;
+ }
+# endif /* defined(HAS_NFS) */
+
+ if (lc->u.ld.dev && lc->u.ld.pa_inum)
+ lc->pa = DIN_addr(&lc->u.ld.dev, lc->u.ld.pa_inum);
+ }
+}
+
+
+/*
+ * ncache_lookup() - look up a node's name in the kernel's name caches
+ */
+
+char *
+ncache_lookup(buf, blen, fp)
+ char *buf; /* receiving name buffer */
+ int blen; /* receiving buffer length */
+ int *fp; /* full path reply */
+{
+ char *cp = buf;
+ int nl, rlen;
+ struct lnch *lc;
+
+ *cp = '\0';
+ *fp = 0;
+/*
+ * If the entry has an inode number that matches the inode number of the
+ * file system mount point, return an empty path reply. That tells the
+ * caller to print the file system mount point name only.
+ */
+ if (Lf->inp_ty == 1 && Lf->fs_ino && Lf->inode == Lf->fs_ino)
+ return(cp);
+ if (!LNC_nc)
+ return((char *)NULL);
+
+#if defined(HAS_NFS)
+/*
+ * Look up the NFS name cache entry.
+ */
+ if (Lf->is_nfs) {
+ if ((lc = NFS_addr(Lf->na)) && !lc->dup) {
+ if ((nl = (int)lc->nl) > (blen - 1))
+ return(*cp ? cp : (char *)NULL);
+ cp = buf + blen - nl - 1;
+ rlen = blen - nl - 1;
+ (void) snpf(cp, nl + 1, "%s", lc->nm);
+ /*
+ * Look up the NFS name cache entries that are parents of the
+ * rnode address. Quit when:
+ *
+ * there's no parent;
+ * the parent is a duplicate;
+ * the name is too large to fit in the receiving buffer.
+ */
+ for (;;) {
+ if (!lc->pa) {
+ if (NFS_root(lc->u.ln.dp))
+ *fp = 1;
+ break;
+ }
+ lc = lc->pa;
+ if (lc->dup)
+ break;
+ if (((nl = (int)lc->nl) + 1) > rlen)
+ break;
+ *(cp - 1) = '/';
+ cp--;
+ rlen--;
+ (void) strncpy((cp - nl), lc->nm, nl);
+ cp -= nl;
+ rlen -= nl;
+ }
+ return(*cp ? cp : (char *)NULL);
+ }
+ return((char *)NULL);
+ }
+# endif /* defined(HAS_NFS) */
+
+/*
+ * Look up the device-inode name cache entry.
+ */
+ if (Lf->dev_def && Lf->inp_ty == 1
+ && (lc = DIN_addr(&Lf->dev, Lf->inode)) && !lc->dup) {
+ if ((nl = (int)lc->nl) > (blen - 1))
+ return(*cp ? cp : (char *)NULL);
+ cp = buf + blen - nl - 1;
+ rlen = blen - nl - 1;
+ (void) snpf(cp, nl + 1, "%s", lc->nm);
+ /*
+ * Look up the LNC name cache entries that are parents of the
+ * device and inode number. Quit when:
+ *
+ * there's no parent;
+ * the parent is a duplicate cache entry;
+ * the name is too large to fit in the receiving buffer.
+ */
+ for (;;) {
+ if (!lc->pa) {
+ if (lc->u.ld.pa_inum && Lf->fs_ino
+ && lc->u.ld.pa_inum == Lf->fs_ino)
+ *fp = 1;
+ break;
+ }
+ lc = lc->pa;
+ if (lc->dup)
+ break;
+ if (lc->u.ld.inum && Lf->fs_ino
+ && lc->u.ld.inum == Lf->fs_ino) {
+ *fp = 1;
+ break;
+ }
+ if (((nl = (int)lc->nl) + 1) > rlen)
+ break;
+ *(cp - 1) = '/';
+ cp--;
+ rlen--;
+ (void) strncpy((cp - nl), lc->nm, nl);
+ cp -= nl;
+ rlen -= nl;
+ }
+ return(*cp ? cp : (char *)NULL);
+ }
+ return((char *)NULL);
+}
+
+
+# if defined(HAS_NFS)
+/*
+ * NFS_addr() - look up a node's local NFS_nc address
+ */
+
+static struct lnch *
+NFS_addr(r)
+ KA_T r; /* rnode's address */
+{
+ struct lnch_hh *hh = NFS_hash(r);
+ struct lnch *lc = hh->hp[1];
+
+ while (lc) {
+ if (lc->u.ln.rp == r)
+ return(lc);
+ lc = lc->next;
+ }
+ return((struct lnch *)NULL);
+}
+
+
+/*
+ * NFS_load() -- load kernel's NFS name cache
+ */
+
+static void
+NFS_load()
+{
+ struct ncache *cp;
+ int i, len;
+ struct lnch lc;
+ static KA_T ka = (KA_T)NULL;
+ static int kcl = 0;
+ static struct ncache *nfnc = (struct ncache *)NULL;
+ static int nfnce = 0;
+ char nm[NC_NAMLEN+1];
+ KA_T v;
+/*
+ * Do first-time setup, as required.
+ */
+ if (nfnce == 0) {
+
+ /*
+ * Quit if the NFS name cache address is unknown.
+ */
+ if (get_Nl_value("nfnc", Drive_Nl, &ka) < 0 || !ka)
+ return;
+ /*
+ * Get the kernel's NFS name cache size.
+ */
+ if (get_Nl_value("nnfnc", Drive_Nl, &v) < 0 || !v
+ || kread(v, (char *)&nfnce, sizeof(nfnce))
+ || nfnce < 1)
+ return;
+ /*
+ * Allocate space for a copy of the kernel's NFS name cache.
+ */
+ kcl = nfnce * sizeof(struct ncache);
+ if (!(nfnc = (struct ncache *)malloc(kcl))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d bytes for NFS name cache\n",
+ Pn, kcl);
+ Exit(1);
+ }
+ }
+/*
+ * Read the kernel's NFS name cache.
+ */
+ if (!nfnc || !kcl || !ka || kread(ka, (char *)nfnc, kcl))
+ return;
+/*
+ * Build a local copy of the kernel's NFS name cache.
+ */
+ lc.type = 1;
+ for (cp = nfnc, i = 0; i < nfnce; cp++, i++) {
+ if (!cp->rp)
+ continue;
+ if ((len = cp->namlen) < 0 || len > NC_NAMLEN)
+ continue;
+ (void) strncpy(nm, cp->name, len);
+ nm[len] = '\0';
+ if ((len = strlen(nm)) < 1)
+ continue;
+ if (len < 3 && nm[0] == '.') {
+ if (len == 1 || (len == 2 && nm[1] == '.'))
+ continue;
+ }
+ lc.u.ln.rp = (KA_T)cp->rp;
+ lc.u.ln.dp = (KA_T)cp->dp;
+ if (LNC_enter(&lc, nm, len, "NFS"))
+ break;
+ }
+/*
+ * If not repeating, free kernel NFS name cache buffer space.
+ */
+ if (nfnc && !RptTm) {
+ (void) free((MALLOC_P *)nfnc);
+ nfnc = (struct ncache *)NULL;
+ kcl = nfnce = 0;
+ }
+}
+
+
+static int
+NFS_root(r)
+ KA_T r; /* node's rnode address */
+{
+ int i;
+ MALLOC_S len;
+ static int rnc = 0;
+ static int rnca = 0;
+ static KA_T *rc = (KA_T *)NULL;
+ struct rnode rn;
+ unsigned short *n;
+ unsigned long nnum;
+
+# if OSRV>=500
+ unsigned short *n1;
+# endif /* OSRV>=500 */
+
+ if (!Lf->fs_ino || !r)
+ return(0);
+/*
+ * Search NFS root rnode cache.
+ */
+ for (i = 0; i < rnc; i++) {
+ if (rc[i] == r)
+ return(1);
+ }
+/*
+ * Read rnode and get the node number.
+ */
+ if (kread(r, (char *)&rn, sizeof(rn)))
+ return(0);
+
+# if OSRV<500
+ n = (unsigned short *)&rn.r_fh.fh_pad[14];
+ if (!(nnum = (unsigned long)ntohs(*n)))
+ nnum = (unsigned long)rn.r_fh.fh_u.fh_fgen_u;
+# else /* OSRV>=500 */
+ n = (unsigned short *)&rn.r_fh.fh_u.fh_fid_u[4];
+ n1 = (unsigned short *)&rn.r_fh.fh_u.fh_fid_u[2];
+ if (!(nnum = (unsigned long)*n))
+ nnum = (unsigned long)*n1;
+# endif /* OSRV<500 */
+
+ if (!nnum || nnum != Lf->fs_ino)
+ return(0);
+/*
+ * Add the rnode address to the NFS root rnode cache.
+ */
+ if (rnc >= rnca) {
+ if (rnca == 0) {
+ len = (MALLOC_S)(10 * sizeof(KA_T));
+ if ((rc = (KA_T *)malloc(len)))
+ rnca = 10;
+ } else {
+ len = (MALLOC_S)((rnca + 10) * sizeof(KA_T));
+ if ((rc = (KA_T *)realloc(rc, len)))
+ rnca += 10;
+ }
+ if (!rc) {
+ (void) fprintf(stderr, "%s: no space for root rnode table\n",
+ Pn);
+ Exit(1);
+ }
+ }
+ rc[rnc++] = r;
+ return(1);
+}
+# endif /* defined(HAS_NFS) */
+
+
+# if OSRV<504
+/*
+ * SYSV_load() - load SYSV cache
+ */
+
+static void
+SYSV_load()
+{
+ struct s5cachent *cp;
+ int i, len;
+ static KA_T ka = (KA_T)NULL;
+ static int kcl = 0;
+ struct lnch lc;
+ char nm[DIRSIZ+1];
+ static struct s5cachent *s5nc = (struct s5cachent *)NULL;
+ static int s5nce = 0;
+ KA_T v;
+/*
+ * Do first-time setup, as required.
+ */
+ if (s5nce == 0) {
+
+ /*
+ * Quit if the SYSV name cache address is unknown.
+ */
+ if (get_Nl_value("s5nc", Drive_Nl, &ka) < 0 || !ka)
+ return;
+ /*
+ * Get the kernel's SYSV name cache size.
+ */
+
+# if OSRV<500
+ s5nce = Var.v_s5cacheents;
+# else /* OSRV>=500 */
+ if (get_Nl_value("nsfnc", Drive_Nl, &v) < 0 || !v
+ || kread(v, (char *)&s5nce, sizeof(s5nce)))
+ return;
+# endif /* OSRV<500 */
+
+ if (s5nce < 1)
+ return;
+ /*
+ * Allocate space for a copy of the kernel's SYSV name cache.
+ */
+ kcl = sizeof(struct s5cachent) * s5nce;
+ if (!(s5nc = (struct s5cachent *)malloc(kcl))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d bytes for SYSV name cache\n",
+ Pn, kcl);
+ Exit(1);
+ }
+ }
+/*
+ * Read the kernel's SYSV name cache.
+ */
+ if (!s5nc || !kcl || !ka || kread(ka, (char *)s5nc, kcl))
+ return;
+/*
+ * Build a local copy of the kernel's SYSV name cache.
+ */
+ nm[DIRSIZ] = '\0';
+ lc.type = 0;
+ for (cp = s5nc, i = 0; i < s5nce; cp++, i++) {
+ if (!cp->dev && !cp->newinum)
+ continue;
+ (void) strncpy(nm, cp->name, DIRSIZ);
+ if ((len = strlen(nm)) < 1)
+ continue;
+ if (len < 3 && cp->name[0] == '.') {
+ if (len == 1 || (len == 2 && cp->name[1] == '.'))
+ continue;
+ }
+ lc.u.ld.dev = (dev_t)cp->dev;
+ lc.u.ld.inum = (unsigned long)cp->newinum;
+ lc.u.ld.pa_inum = (unsigned long)cp->inum;
+ if (LNC_enter(&lc, nm, len, "SYSV"))
+ break;
+ }
+/*
+ * If not repeating, free kernel SYSV name cache buffer space.
+ */
+ if (s5nc && !RptTm) {
+ (void) free((MALLOC_P *)s5nc);
+ s5nc = (struct s5cachent *)NULL;
+ kcl = s5nce = 0;
+ }
+}
+# endif /* OSRV<504 */
+#endif /* defined(HASNCACHE) */
diff --git a/dialects/osr/dproto.h b/dialects/osr/dproto.h
new file mode 100644
index 0000000..77e029c
--- /dev/null
+++ b/dialects/osr/dproto.h
@@ -0,0 +1,62 @@
+/*
+ * dproto.h - SCO OpenServer function prototypes for lsof
+ *
+ * The _PROTOTYPE macro is defined in the common proto.h.
+ */
+
+
+/*
+ * Copyright 1995 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.
+ */
+
+
+/*
+ * $Id: dproto.h,v 1.5 99/06/22 08:22:28 abe Exp $
+ */
+
+_PROTOTYPE(extern int is_file_named,(char *p, int cd));
+_PROTOTYPE(extern void process_socket,(struct inode *i));
+_PROTOTYPE(extern int get_max_fd,(void));
+
+#if OSRV<500
+_PROTOTYPE(extern int endservent,(void));
+_PROTOTYPE(extern int setservent,(int));
+
+# if defined(HASSTATLSTAT)
+_PROTOTYPE(extern int statlstat,(const char *, struct stat *));
+# endif /* defined(HASTSTATLSTAT) */
+
+_PROTOTYPE(extern int strcasecmp,(char *, char *));
+_PROTOTYPE(extern int strncasecmp,(char *, char *, unsigned int));
+_PROTOTYPE(extern pid_t wait,());
+#endif /* OSRV<500 */
+
+_PROTOTYPE(extern int sysi86,());
+_PROTOTYPE(extern int sysfs,());
+_PROTOTYPE(extern void udp_tm,(time_t tm));
+
+#if !defined(N_UNIX)
+_PROTOTYPE(extern char *get_nlist_path,(int pd));
+#endif /* !defined(N_UNIX) */
diff --git a/dialects/osr/dsock.c b/dialects/osr/dsock.c
new file mode 100644
index 0000000..80684d1
--- /dev/null
+++ b/dialects/osr/dsock.c
@@ -0,0 +1,422 @@
+/*
+ * dsock.c - SCO OpenServer socket processing functions for lsof
+ */
+
+
+/*
+ * Copyright 1995 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 1995 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dsock.c,v 1.15 2004/03/10 23:52:12 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+/*
+ * process_socket() - process socket
+ */
+
+void
+process_socket(i)
+ struct inode *i; /* inode pointer */
+{
+ char *cp;
+ struct domain d;
+ unsigned char *fa = (unsigned char *)NULL;
+ int fam, j, k;
+ int fp, lp;
+ unsigned char *la = (unsigned char *)NULL;
+ int p;
+ struct inpcb pcb;
+ short pcbs = 0;
+ short udpsf, udpsl;
+ struct socket s;
+ KA_T sa, spa;
+ struct stdata sd;
+ struct queue sh;
+ short shs = 0;
+ struct tcpcb t;
+ short ts = 0;
+ struct udpdev udp;
+ short udptm = 0;
+
+#if OSRV<500
+ struct sockaddr_in *si;
+#else /* OSRV>=500 */
+ struct sockaddr_in si;
+ struct un_dev ud;
+#endif /* OSRV<500 */
+
+ (void) snpf(Lf->type, sizeof(Lf->type), "sock");
+/*
+ * Read socket.
+ */
+ if (!Socktab) {
+ (void) enter_nm("No kernel socket table");
+ return;
+ }
+ spa = Socktab + (GET_MIN_DEV(i->i_rdev) * sizeof(struct socket *));
+ if (kread(spa, (char *)&sa, sizeof(sa))) {
+ (void) snpf(Namech, Namechl, "can't read socket pointer at %s",
+ print_kptr(spa, (char *)NULL, 0));
+ enter_nm(Namech);
+ }
+ if (kread(sa, (char *)&s, sizeof(s))) {
+ (void) snpf(Namech, Namechl, "can't read socket structure at %s",
+ print_kptr(sa, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+/*
+ * Read domain structure.
+ */
+ if (!s.so_proto.pr_domain
+ || kread((KA_T)s.so_proto.pr_domain, (char *)&d, sizeof(d))) {
+ (void) snpf(Namech, Namechl, "can't read protocol domain from %s",
+ print_kptr((KA_T)s.so_proto.pr_domain, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+/*
+ * Process by protocol domain.
+ */
+ switch ((fam = d.dom_family)) {
+ case AF_INET:
+ if (Fnet)
+ Lf->sf |= SELNET;
+ (void) snpf(Lf->type, sizeof(Lf->type), "inet");
+ printiproto((int)s.so_proto.pr_protocol);
+ Lf->inp_ty = 2;
+ /*
+ * Get protocol control block address from stream head queue structure.
+ */
+ if (s.so_stp
+ && !readstdata((KA_T)s.so_stp, &sd)
+ && !readsthead((KA_T)sd.sd_wrq, &sh))
+ shs = 1;
+ if (shs && sh.q_ptr) {
+ enter_dev_ch(print_kptr((KA_T)sh.q_ptr, (char *)NULL, 0));
+ if (kread((KA_T)sh.q_ptr, (char *)&pcb, sizeof(pcb)) == 0)
+ pcbs = 1;
+ }
+ /*
+ * Print local and remote addresses.
+ */
+ if (pcbs) {
+ if (pcb.inp_ppcb && strcasecmp(Lf->iproto, "udp") == 0) {
+
+ /*
+ * If this is a UDP socket file, get the udpdev structure
+ * at the PCB's per-protocol control block address. It
+ * may contain a foreign address.
+ */
+ if (!kread((KA_T)pcb.inp_ppcb, (char *)&udp, sizeof(udp))) {
+
+#if OSRV>=500
+ if (udp.ud_lsin.sin_addr.s_addr != INADDR_ANY
+ || udp.ud_lsin.sin_port != 0)
+ udpsl = 1;
+ else
+ udpsl = 0;
+#endif /* OSRV>=500 */
+
+ if (udp.ud_fsin.sin_addr.s_addr != INADDR_ANY
+ || udp.ud_fsin.sin_port != 0)
+ udpsf = 1;
+ else
+ udpsf = 0;
+ }
+ } else
+ udpsf = udpsl = 0;
+ /*
+ * Print the local address from the PCB. If there is none, and if
+ * this is a 5.0.0 or greater UDP stream, and if it has a local
+ * address set, use it.
+ */
+ la = (unsigned char *)&pcb.inp_laddr;
+ lp = (int)ntohs(pcb.inp_lport);
+
+#if OSRV>=500
+ if (((struct in_addr *)la)->s_addr == INADDR_ANY
+ && lp == 0 && udpsl) {
+ la = (unsigned char *)&udp.ud_lsin.sin_addr;
+ lp = (int)ntohs(udp.ud_lsin.sin_port);
+ }
+
+#endif /* OSRV>=500 */
+
+ /*
+ * Use the PCB's foreign address if it is set. If not, and if this
+ * is a UDP socket file, use the udpdev structure's foreign address
+ * if it's set.
+ */
+ if (pcb.inp_faddr.s_addr != INADDR_ANY || pcb.inp_fport != 0) {
+ fa = (unsigned char *)&pcb.inp_faddr;
+ fp = (int)ntohs(pcb.inp_fport);
+ } else if (udpsf) {
+ fa = (unsigned char *)&udp.ud_fsin.sin_addr;
+ fp = (int)ntohs(udp.ud_fsin.sin_port);
+ udptm = 1;
+ }
+ if (la || fa) {
+ (void) ent_inaddr(la, lp, fa, fp, AF_INET);
+ if (udptm && !Lf->nma)
+ (void)udp_tm(udp.ud_ftime);
+ }
+ if (pcb.inp_ppcb && strcasecmp(Lf->iproto, "tcp") == 0
+ && kread((KA_T)pcb.inp_ppcb, (char *)&t, sizeof(t)) == 0) {
+ ts = 1;
+ /*
+ * Save the TCP state from its control block.
+ */
+ Lf->lts.type = 0;
+ Lf->lts.state.i = (int)t.t_state;
+ }
+ } else {
+
+#if OSRV<500
+ if ((si = (struct sockaddr_in *)&s.so_name)) {
+ la = (unsigned char *)&si->sin_addr;
+ lp = (int)ntohs(si->sin_port);
+ }
+ if ((si = (struct sockaddr_in *)&s.so_peer)) {
+ if (si->sin_addr.s_addr != INADDR_ANY || si->sin_port != 0)
+ {
+ fa = (unsigned char *)&si->sin_addr;
+ fp = (int)ntohs(si->sin_port);
+ }
+ }
+#else /* OSRV>=500 */
+ if (s.so_name
+ && !kread((KA_T)s.so_name, (char *)&si, sizeof(si))) {
+ la = (unsigned char *)&si.sin_addr;
+ lp = (int)ntohs(si.sin_port);
+ }
+ if (s.so_peer
+ && !kread((KA_T)s.so_peer, (char *)&si, sizeof(si))) {
+ if (si.sin_addr.s_addr != INADDR_ANY || si.sin_port != 0) {
+ fa = (unsigned char *)&si.sin_addr;
+ fp = (int)ntohs(si.sin_port);
+ }
+ }
+#endif /* OSRV<500 */
+
+ if (la || fa)
+ (void) ent_inaddr(la, lp, fa, fp, AF_INET);
+ }
+ /*
+ * Save options, sizes, states and values.
+ */
+
+#if defined(HASSOOPT)
+ Lf->lts.ltm = (unsigned int)s.so_linger;
+ Lf->lts.opt = (unsigned int)s.so_options;
+ Lf->lts.qlen = (unsigned int)s.so_qlen;
+ Lf->lts.qlim = (unsigned int)s.so_qlimit;
+ Lf->lts.qlens = Lf->lts.qlims = (unsigned char)1;
+ if (ts && t.t_timer[TCPT_KEEP]) {
+ Lf->lts.opt |= SO_KEEPALIVE;
+ Lf->lts.kai = (unsigned long)t.t_timer[TCPT_KEEP];
+ }
+#endif /* defined(HASSOOPT) */
+
+#if defined(HASSOSTATE)
+ Lf->lts.ss = s.so_state;
+#endif /* defined(HASSOSTATE) */
+
+
+ if (ts) {
+
+#if defined(HASTCPOPT)
+ Lf->lts.topt = (unsigned int)t.t_flags;
+ Lf->lts.mss = (unsigned long)t.t_maxseg;
+ Lf->lts.msss = (unsigned char)1;
+#endif /* defined(HASTCPOPT) */
+
+#if defined(HASTCPTPIQ)
+ Lf->lts.rq = (unsigned long)t.t_iqsize;
+ Lf->lts.sq = (unsigned long)t.t_qsize;
+ Lf->lts.rqs = Lf->lts.sqs = 1;
+#endif /* defined(HASTCPTPIQ) */
+
+ if (Fsize) {
+ if (Lf->access == 'r')
+ Lf->sz = (SZOFFTYPE)t.t_iqsize;
+ else if (Lf->access == 'w')
+ Lf->sz = (SZOFFTYPE)t.t_qsize;
+ else
+ Lf->sz = (SZOFFTYPE)(t.t_iqsize + t.t_qsize);
+ Lf->sz_def = 1;
+ } else
+ Lf->off_def = 1;
+ } else if (shs) {
+ if (Fsize) {
+ Lf->sz = (SZOFFTYPE)sh.q_count;
+ Lf->sz_def = 1;
+ } else
+ Lf->off_def = 1;
+ } else
+ Lf->off_def = 1;
+ break;
+
+#if OSRV>=500
+ case AF_UNIX:
+ if (Funix)
+ Lf->sf |= SELUNX;
+ (void) snpf(Lf->type, sizeof(Lf->type), "unix");
+ /*
+ * Read Unix protocol control block and the Unix address structure.
+ */
+ enter_dev_ch(print_kptr(sa, (char *)NULL, 0));
+ Lf->off_def = 1;
+ if (s.so_stp
+ && !readstdata((KA_T)s.so_stp, &sd)
+ && !readsthead((KA_T)sd.sd_wrq, &sh)) {
+ if (!sh.q_ptr
+ || kread((KA_T)sh.q_ptr, (char *)&ud, sizeof(ud)))
+ {
+ (void) snpf(Namech, Namechl, "can't read un_dev from %s",
+ print_kptr((KA_T)sh.q_ptr, (char *)NULL, 0));
+ break;
+ }
+ if (ud.so_rq)
+ enter_dev_ch(print_kptr((KA_T)ud.so_rq, (char *)NULL, 0));
+ if (ud.local_addr.sun_family == AF_UNIX) {
+ Lf->inode = (unsigned long)ud.bnd_param.user_addr.inode_no;
+ Lf->inp_ty = 1;
+ ud.local_addr.sun_path[sizeof(ud.local_addr.sun_path) - 1]
+ = '\0';
+ if (Sfile && is_file_named(ud.local_addr.sun_path, 0))
+ Lf->sf |= SELNM;
+ if (!Namech[0])
+ (void) snpf(Namech,Namechl,"%s",ud.local_addr.sun_path);
+ } else if (ud.for_addr.sun_family == AF_UNIX) {
+ Lf->inode = (unsigned long)ud.bnd_param.user_addr.inode_no;
+ Lf->inp_ty = 1;
+ ud.for_addr.sun_path[sizeof(ud.for_addr.sun_path) - 1]
+ = '\0';
+ if (Sfile && is_file_named(ud.for_addr.sun_path, 0))
+ Lf->sf |= SELNM;
+ else
+ (void) snpf(Namech,Namechl,"%s",ud.for_addr.sun_path);
+ } else if (ud.other_q)
+ (void) snpf(Namech, Namechl, "->%s",
+ print_kptr((KA_T)ud.other_q, (char *)NULL, 0));
+ } else
+ (void) snpf(Namech, Namechl, "can't get un_dev");
+ break;
+#endif /* OSRV>=500 */
+
+ default:
+ printunkaf(fam, 1);
+ }
+ enter_nm(Namech);
+}
+
+
+/*
+ * udp_tm() - compute time since UDP packet was last sent
+ */
+
+void
+udp_tm(tm)
+ time_t tm; /* time when packet was sent */
+{
+ static char buf[32], *cp;
+ time_t et, lbolt;
+ MALLOC_S len;
+ short hr, min, sec;
+/*
+ * Read the lightning bolt timer and compute the elapsed time.
+ * No elapsed time is returned if:
+ * the global clock frequency variable, Hz, is negative;
+ * the lightning bolt timer is unavailable;
+ * the lightning bolt time is less than the UDP send time;
+ * the elapsed time is zero.
+ */
+ if (!Lbolt)
+ return;
+ if (Hz < 0
+ || kread((KA_T)Lbolt, (char *)&lbolt, sizeof(lbolt))
+ || tm >= lbolt
+ || (et = (time_t)((lbolt - tm) / Hz)) == 0)
+ return;
+/*
+ * If the time is 100 hours or greater, return the elapsed time as seconds.
+ */
+ if (et >= (100 * 60 * 60)) {
+ (void) snpf(buf, sizeof(buf), "%lds", et);
+ cp = &buf[strlen(buf)];
+ } else {
+
+ /*
+ * Convert seconds to hours, minutes and seconds.
+ */
+ hr = (short)(et / (60 * 60));
+ et %= (60 * 60);
+ min = (short)(et / 60);
+ sec = (short)(et % 60);
+ cp = buf;
+ /*
+ * Format the elapsed time and attach single character suffixes to
+ * represent the units:
+ *
+ * `h' = hours
+ * `m' = minutes
+ * `s' = seconds
+ */
+ if (hr) {
+ (void) snpf(cp, sizeof(buf) - (cp - buf), "%dh", hr);
+ cp += 2 + ((hr > 9) ? 1 : 0);
+ }
+ if (min) {
+ (void) snpf(cp, sizeof(buf) - (cp - buf), "%dm", min);
+ cp += 2 + ((min > 9) ? 1 : 0);
+ }
+ if (sec) {
+ (void) snpf(cp, sizeof(buf) - (cp - buf), "%ds", sec);
+ cp += 2 + ((sec > 9) ? 1 : 0);
+ }
+ }
+/*
+ * Add the `` ago'' trailer. Return the string's address and length.
+ */
+ (void) snpf(cp, sizeof(buf) - (cp - buf), " ago");
+ len = (MALLOC_S)(strlen(buf) + 1);
+ if (len < 2)
+ return;
+ if (!(cp = (char *)malloc(len))) {
+ (void) fprintf(stderr, "%s: no space for %d character UDP time\n",
+ Pn, len);
+ Exit(1);
+ }
+ (void) snpf(cp, len, "%s", buf);
+ Lf->nma = cp;
+}
diff --git a/dialects/osr/dstore.c b/dialects/osr/dstore.c
new file mode 100644
index 0000000..c7a2636
--- /dev/null
+++ b/dialects/osr/dstore.c
@@ -0,0 +1,154 @@
+/*
+ * dstore.c - SCO OpenServer global storage for lsof
+ */
+
+
+/*
+ * Copyright 1995 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 1995 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dstore.c,v 1.9 2002/12/03 18:23:08 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+char **Cdevsw = NULL; /* names from kernel's cdevsw[].d_name */
+int Cdevcnt = 0; /* Cdevsw[] count */
+int CloneMajor; /* clone major device */
+
+
+/*
+ * Drive_Nl -- table to drive the building of Nl[] via build_Nl()
+ * (See lsof.h and misc.c.)
+ */
+
+struct drive_Nl Drive_Nl[] = {
+ { "ncdev", "cdevcnt" },
+ { "cdev", "cdevsw" },
+ { "dnlc", "dnlc__cache" }, /* OSRV>=504 */
+ { "ndnlc", "dnlc__cacheents" }, /* OSRV>=504 */
+ { "pdnlc", "dnlc__cache_is_ptr" }, /* OSRV>=507 */
+ { "dtnc", "dtcache" }, /* 500<=OSRV<504 */
+ { "htnc", "htcache" }, /* 500<=OSRV<504 */
+ { "hz", "Hz" },
+ { "lbolt", "lbolt" },
+ { "nfnc", "ncache" }, /* HAS_NFS */
+ { "nnfnc", "nc_size" }, /* HAS_NFS */
+ { "nxdm", "nxdevmaps" }, /* OSRV>=40 */
+ { "pregpp", "pregpp" }, /* OSRV<500 */
+ { "proc", "proc" },
+ { "scouts", "scoutsname" }, /* OSRV>=500 */
+ { "sockd", "sockdev" },
+ { "sockt", "socktab" },
+ { "s5nc", "s5cache" }, /* OSRV<504 */
+ { "var", "v" },
+ { "ndtnc", "v_dtcacheents" }, /* 500<=OSRV<504 */
+ { "nhtnc", "v_htcacheents" }, /* 500<=OSRV<504 */
+ { "ns5nc", "v_s5cacheents" }, /* 500<=OSRV<504 */
+ { "xdm", "xdevmap" }, /* OSRV>=40 */
+ { NULL, NULL }
+};
+
+int EventMajor; /* event major device number */
+char **Fsinfo = NULL; /* file system information */
+int Fsinfomax = 0; /* maximum file system type */
+int HaveCloneMajor = 0; /* have clone major device number = 1 */
+int HaveEventMajor = 0; /* have event major device number */
+int HaveSockdev = 0; /* socket device number status: 1 = available */
+int Hz = -1; /* system clock frequency */
+int Kd = -1; /* /dev/kmem file descriptor */
+KA_T Lbolt = (KA_T)0; /* kernel's lbolt variable address */
+int Sockdev; /* socket device number */
+KA_T Socktab = (KA_T)0; /* address of socket pointer table */
+
+#if defined(HASFSTRUCT)
+/*
+ * Pff_tab[] - table for printing file flags
+ */
+
+struct pff_tab Pff_tab[] = {
+ { (long)FREAD, FF_READ },
+ { (long)FWRITE, FF_WRITE },
+ { (long)FNDELAY, FF_NDELAY },
+ { (long)FAPPEND, FF_APPEND },
+ { (long)FNONBLOCK, FF_NBLOCK },
+ { (long)FRCACH, FF_RCACH },
+ { (long)FSTOPIO, FF_STOPIO },
+
+# if defined(FASYNC)
+ { (long)FASYNC, FF_ASYNC },
+# endif /* defined(FASYNC`) */
+
+# if defined(FNET)
+ { (long)FNET, FF_NET },
+# endif /* defined(FNET) */
+
+# if defined(FSYNC)
+ { (long)FSYNC, FF_SYNC },
+# endif /* defined(FSYNC) */
+
+ { (long)0, NULL }
+};
+
+
+/*
+ * Pof_tab[] - table for print process open file flags
+ */
+
+struct pff_tab Pof_tab[] = {
+
+ { (long)EXCLOSE, POF_CLOEXEC },
+
+# if defined(AUD_READ)
+ { (long)AUD_READ, POF_BNRD },
+# endif /* defined(AUD_READ) */
+
+# if defined(AUD_WRITE)
+ { (long)AUD_WRITE, POF_BNWR },
+# endif /* defined(AUDWRITE) */
+
+# if defined(SEC_SIGHUPPED)
+ { (long)SEC_SIGHUPPED, POF_BNHUP },
+# endif /* defined(SEC_SIGHUPPED) */
+
+ { (long)0, NULL }
+};
+#endif /* defined(HASFSTRUCT) */
+
+
+#if OSRV>=40
+/*
+ * The following items are needed by the internal kernel major()
+ * and minor() macros for mapping extended minor numbers.
+ */
+
+int nxdevmaps = -1; /* maximum kernel xdevmap[] index */
+struct XDEVMAP *Xdevmap; /* dynamically allocated xdevmap[] */
+#endif /* OSRV>=40 */
diff --git a/dialects/osr/include/netdb.h b/dialects/osr/include/netdb.h
new file mode 100644
index 0000000..3d2e3d7
--- /dev/null
+++ b/dialects/osr/include/netdb.h
@@ -0,0 +1,121 @@
+/*-
+ * Copyright (c) 1980, 1983, 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)netdb.h 5.15 (Berkeley) 4/3/91
+ */
+
+#ifndef _NETDB_H_
+#define _NETDB_H_
+
+#define _PATH_HEQUIV "/etc/hosts.equiv"
+#define _PATH_HOSTS "/etc/hosts"
+#define _PATH_NETWORKS "/etc/networks"
+#define _PATH_PROTOCOLS "/etc/protocols"
+#define _PATH_SERVICES "/etc/services"
+
+/*
+ * Structures returned by network data base library. All addresses are
+ * supplied in host order, and returned in network order (suitable for
+ * use in system calls).
+ */
+struct hostent {
+ char *h_name; /* official name of host */
+ char **h_aliases; /* alias list */
+ int h_addrtype; /* host address type */
+ int h_length; /* length of address */
+ char **h_addr_list; /* list of addresses from name server */
+#define h_addr h_addr_list[0] /* address, for backward compatiblity */
+};
+
+/*
+ * Assumption here is that a network number
+ * fits in 32 bits -- probably a poor one.
+ */
+struct netent {
+ char *n_name; /* official name of net */
+ char **n_aliases; /* alias list */
+ int n_addrtype; /* net address type */
+ unsigned long n_net; /* network # */
+};
+
+struct servent {
+ char *s_name; /* official service name */
+ char **s_aliases; /* alias list */
+ int s_port; /* port # */
+ char *s_proto; /* protocol to use */
+};
+
+struct protoent {
+ char *p_name; /* official protocol name */
+ char **p_aliases; /* alias list */
+ int p_proto; /* protocol # */
+};
+
+/*
+ * Error return codes from gethostbyname() and gethostbyaddr()
+ * (left in extern int h_errno).
+ */
+
+#define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found */
+#define TRY_AGAIN 2 /* Non-Authoritive Host not found, or SERVERFAIL */
+#define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
+#define NO_DATA 4 /* Valid name, no data record of requested type */
+#define NO_ADDRESS NO_DATA /* no address, look for MX record */
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+void endhostent __P((void));
+void endnetent __P((void));
+void endprotoent __P((void));
+/* void endservent __P((void)); */
+struct hostent *gethostbyaddr __P((const char *, int, int));
+struct hostent *gethostbyname __P((char *));
+struct hostent *gethostent __P((void));
+struct netent *getnetbyaddr __P((long, int)); /* u_long? */
+struct netent *getnetbyname __P((const char *));
+struct netent *getnetent __P((void));
+struct protoent *getprotobyname __P((const char *));
+struct protoent *getprotobynumber __P((int));
+struct protoent *getprotoent __P((void));
+struct servent *getservbyname __P((const char *, const char *));
+struct servent *getservbyport __P((int, const char *));
+struct servent *getservent __P((void));
+void herror __P((const char *));
+void sethostent __P((int));
+/* void sethostfile __P((const char *)); */
+void setnetent __P((int));
+void setprotoent __P((int));
+/* void setservent __P((int)); */
+__END_DECLS
+
+#endif /* !_NETDB_H_ */
diff --git a/dialects/osr/include/sys/cdefs.h b/dialects/osr/include/sys/cdefs.h
new file mode 100644
index 0000000..c4157bc
--- /dev/null
+++ b/dialects/osr/include/sys/cdefs.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)cdefs.h 8.2 (Berkeley) 10/4/93
+ */
+
+#ifndef _CDEFS_H_
+#define _CDEFS_H_
+
+#if defined(__cplusplus)
+#define __BEGIN_DECLS extern "C" {
+#define __END_DECLS };
+#else
+#define __BEGIN_DECLS
+#define __END_DECLS
+#endif
+
+/*
+ * The __CONCAT macro is used to concatenate parts of symbol names, e.g.
+ * with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo.
+ * The __CONCAT macro is a bit tricky -- make sure you don't put spaces
+ * in between its arguments. __CONCAT can also concatenate double-quoted
+ * strings produced by the __STRING macro, but this only works with ANSI C.
+ */
+#if defined(__STDC__) || defined(__cplusplus)
+#define __P(protos) protos /* full-blown ANSI C */
+#define __CONCAT(x,y) x ## y
+#define __STRING(x) #x
+
+#if !defined(__GNUC__) && !defined(__cplusplus)
+#define inline
+#endif
+
+#else /* !(__STDC__ || __cplusplus) */
+#define __P(protos) () /* traditional C preprocessor */
+#define __CONCAT(x,y) x/**/y
+#define __STRING(x) "x"
+
+#ifdef __GNUC__
+#define const __const /* GCC: ANSI C with -traditional */
+#define inline __inline
+#define signed __signed
+#define volatile __volatile
+
+#else /* !__GNUC__ */
+#define const /* delete ANSI C keywords */
+#define inline
+#define signed
+#define volatile
+#endif /* !__GNUC__ */
+#endif /* !(__STDC__ || __cplusplus) */
+
+/*
+ * GCC has extensions for declaring functions as `pure' (always returns
+ * the same value given the same inputs, i.e., has no external state and
+ * no side effects) and `dead' (nonreturning). These mainly affect
+ * optimization and warnings. Unfortunately, GCC complains if these are
+ * used under strict ANSI mode (`gcc -ansi -pedantic'), hence we need to
+ * define them only if compiling without this.
+ */
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+#define __dead __volatile
+#define __pure __const
+#else
+#define __dead
+#define __pure
+#endif
+
+#endif /* !_CDEFS_H_ */
diff --git a/dialects/osr/machine.h b/dialects/osr/machine.h
new file mode 100644
index 0000000..d4f7cb6
--- /dev/null
+++ b/dialects/osr/machine.h
@@ -0,0 +1,614 @@
+/*
+ * machine.h - SCO OpenServer definitions for lsof
+ */
+
+
+/*
+ * Copyright 1995 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.
+ */
+
+
+/*
+ * $Id: machine.h,v 1.36 2010/07/29 16:02:57 abe Exp $
+ */
+
+#if !defined(LSOF_MACHINE_H)
+#define LSOF_MACHINE_H 1
+
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+
+/*
+ * CAN_USE_CLNT_CREATE is defined for those dialects where RPC clnt_create()
+ * can be used to obtain a CLIENT handle in lieu of clnttcp_create().
+ */
+
+#if OSRV>=42
+#define CAN_USE_CLNT_CREATE 1
+#endif /* OSRV>=42 */
+
+
+/*
+ * DEVDEV_PATH defines the path to the directory that contains device
+ * nodes.
+ */
+
+#define DEVDEV_PATH "/dev"
+
+
+/*
+ * GET_MAX_FD is defined for those dialects that provide a function other than
+ * getdtablesize() to obtain the maximum file descriptor number plus one.
+ */
+
+#define GET_MAX_FD get_max_fd
+
+
+/*
+ * HASAOPT is defined for those dialects that have AFS support; it specifies
+ * that the default path to an alternate AFS kernel name list file may be
+ * supplied with the -A <path> option.
+ */
+
+/* #define HASAOPT 1 */
+
+
+/*
+ * HASBLKDEV is defined for those dialects that want block device information
+ * recorded in BDevtp[].
+ */
+
+#define HASBLKDEV 1
+
+
+/*
+ * HASDCACHE is defined for those dialects that support a device cache
+ * file.
+ *
+ * HASENVDC defined the name of an environment variable that contains the
+ * device cache file path. The HASENVDC environment variable is ignored when
+ * the lsof process is setuid(root) or its real UID is 0.
+ *
+ * HASPERSDC defines the format for the last component of a personal device
+ * cache file path. The first will be the home directory of the real UID that
+ * executes lsof.
+ *
+ * HASPERSDCPATH defines the environment variable whose value is the middle
+ * component of the personal device cache file path. The middle component
+ * follows the home directory and precedes the results of applying HASPERSDC.
+ * The HASPERSDCPATH environment variable is ignored when the lsof process is
+ * setuid(root) or its real UID is 0.
+ *
+ * HASSYSDC defines a public device cache file path. When it's defined, it's
+ * used as the path from which to read the device cache.
+ *
+ * Consult the 00DCACHE and 00FAQ files of the lsof distribution for more
+ * information on device cache file path construction.
+ */
+
+#define HASDCACHE 1
+#define HASENVDC "LSOFDEVCACHE"
+#define HASPERSDC "%h/%p.lsof_%L"
+#define HASPERSDCPATH "LSOFPERSDCPATH"
+/* #define HASSYSDC "/your/choice/of/path" */
+
+
+/*
+ * HASCDRNODE is defined for those dialects that have CD-ROM nodes.
+ */
+
+/* #define HASCDRNODE 1 */
+
+
+/*
+ * HASFIFONODE is defined for those dialects that have FIFO nodes.
+ */
+
+/* #define HASFIFONODE 1 */
+
+
+/*
+ * HASFSINO is defined for those dialects that have the file system
+ * inode element, fs_ino, in the lfile structure definition in lsof.h.
+ */
+
+#define HASFSINO 1
+
+
+/*
+ * HASFSTRUCT is defined if the dialect has a file structure.
+ *
+ * FSV_DEFAULT defines the default set of file structure values to list.
+ * It defaults to zero (0), but may be made up of a combination of the
+ * FSV_* symbols from lsof.h.
+ *
+ * HASNOFSADDR -- has no file structure address
+ * HASNOFSFLAGS -- has no file structure flags
+ * HASNOFSCOUNT -- has no file structure count
+ * HASNOFSNADDR -- has no file structure node address
+ */
+
+#define HASFSTRUCT 1
+/* #define FSV_DEFAULT FSV_? | FSV_? | FSV_? */
+/* #define HASNOFSADDR 1 has no file structure address */
+/* #define HASNOFSFLAGS 1 has no file structure flags */
+/* #define HASNOFSCOUNT 1 has no file structure count */
+/* #define HASNOFSNADDR 1 has no file structure node address */
+
+
+/*
+ * HASGNODE is defined for those dialects that have gnodes.
+ */
+
+/* #define HASGNODE 1 */
+
+
+/*
+ * HASHSNODE is defined for those dialects that have High Sierra nodes.
+ */
+
+/* #define HASHSNODE 1 */
+
+
+/*
+ * HASINODE is defined for those dialects that have inodes and wish to
+ * use readinode() from node.c.
+ */
+
+#define HASINODE 1
+
+
+/*
+ * HASINTSIGNAL is defined for those dialects whose signal function returns
+ * an int.
+ */
+
+/* #define HASINTSIGNAL 1 */
+
+
+/*
+ * HASKERNIDCK is defined for those dialects that support the comparison of
+ * the build to running kernel identity.
+ */
+
+#define HASKERNIDCK 1
+
+
+/*
+ * HASKOPT is defined for those systems that support the -k option of
+ * reading the kernel's name list from an optional file.
+ */
+
+#define HASKOPT 1
+
+
+/*
+ * HASLFILEADD is defined for those dialects that need additional elements
+ * in struct lfile. The HASLFILEADD definition is a macro that defines
+ * them. If any of the additional elements need to be preset in the
+ * alloc_lfile() function of proc.c, the SETLFILEADD macro may be defined
+ * to do that.
+ *
+ * If any additional elements need to be cleared in alloc_lfile() or in the
+ * free_proc() function of proc.c, the CLRLFILEADD macro may be defined to
+ * do that. Note that CLRLFILEADD takes one argument, the pointer to the
+ * lfile struct. The CLRLFILEADD macro is expected to expand to statements
+ * that are complete -- i.e., have terminating semi-colons -- so the macro is
+ * called without a terminating semicolon by proc.c.
+ *
+ * The HASXOPT definition may be used to select the conditions under which
+ * private lfile elements are used.
+ */
+
+/* #define HASLFILEADD int ... */
+/* #define CLRLFILEADD(lf) (lf)->... = (type)NULL; */
+/* #define SETLFILEADD Lf->... */
+
+
+/*
+ * HASMNTSTAT indicates the dialect supports the mount stat(2) result option
+ * in its l_vfs and mounts structures.
+ */
+
+/* #define HASMNTSTAT 1 */
+
+
+/*
+ * HASMNTSUP is defined for those dialects that support the mount supplement
+ * option.
+ */
+
+/* #define HASMNTSUP 1 */
+
+
+/*
+ * HASMOPT is defined for those dialects that support the reading of
+ * kernel memory from an alternate file.
+ */
+
+#define HASMOPT 1
+
+
+/*
+ * HASNCACHE is defined for those dialects that have a kernel name cache
+ * that lsof can search. A value of 1 directs printname() to prefix the
+ * cache value with the file system directory name; 2, avoid the prefix.
+ *
+ * NCACHELDPFX is a set of C commands to execute before calling ncache_load().
+ *
+ * NCACHELDSFX is a set of C commands to execute after calling ncache_load().
+ */
+
+#define HASNCACHE 1
+/* #define NCACHELDPFX ??? */
+/* #define NCACHELDSFX ??? */
+
+
+/*
+ * HASNLIST is defined for those systems that use nlist() to acccess
+ * kernel symbols.
+ */
+
+#define HASNLIST 1
+
+
+/*
+ * HASPIPEFN is defined for those dialects that have a special function to
+ * process DTYPE_PIPE file structure entries. Its value is the name of the
+ * function.
+ *
+ * NOTE: don't forget to define a prototype for this function in dproto.h.
+ */
+
+/* #define HASPIPEFN process_pipe? */
+
+
+/*
+ * HASPIPENODE is defined for those dialects that have pipe nodes.
+ */
+
+/* #define HASPIPENODE 1 */
+
+
+/*
+ * HASPMAPENABLED is defined when the reporting of portmapper registration
+ * info is enabled by default.
+ */
+
+/* #define HASPMAPENABLED 1 */
+
+
+/*
+ * HASPPID is defined for those dialects that support identification of
+ * the parent process IDentifier (PPID) of a process.
+ */
+
+#define HASPPID 1
+
+
+/*
+ * HASPRINTDEV, HASPRINTINO, HASPRINTNM, HASPRINTOFF, and HASPRINTSZ
+ * define private dialect-specific functions for printing DEVice numbers,
+ * INOde numbers, NaMes, file OFFsets, and file SiZes. The functions are
+ * called from print_file().
+ */
+
+#define HASPRINTDEV print_dev
+#define HASPRINTINO print_ino
+/* #define HASPRINTNM print_nm? */
+/* #define HASPRINTOFF print_off? */
+/* #define HASPRINTSZ print_sz? */
+
+
+/*
+ * HASPRIVFILETYPE and PRIVFILETYPE are defined for dialects that have a
+ * file structure type that isn't defined by a DTYPE_* symbol. They are
+ * used in lib/prfp.c to select the type's processing.
+ *
+ * PRIVFILETYPE is the definition of the f_type value in the file struct.
+ *
+ * HASPRIVFILETYPE is the name of the processing function.
+ */
+
+/* #define HASPRIVFILETYPE process_shmf? */
+/* #define PRIVFILETYPE ?? */
+
+
+/*
+ * HASPRIVNMCACHE is defined for dialects that have a private method for
+ * printing cached NAME column values for some files. HASPRIVNAMECACHE
+ * is defined to be the name of the function.
+ *
+ * The function takes one argument, a struct lfile pointer to the file, and
+ * returns non-zero if it prints a name to stdout.
+ */
+
+/* #define HASPRIVNMCACHE <function name> */
+
+
+/*
+ * HASPRIVPRIPP is defined for dialects that have a private function for
+ * printing IP protocol names. When HASPRIVPRIPP isn't defined, the
+ * IP protocol name printing function defaults to printiprto().
+ */
+
+/* #define HASPRIVPRIPP 1 */
+
+
+/*
+ * HASPROCFS is defined for those dialects that have a proc file system --
+ * usually /proc and usually in SYSV4 derivatives.
+ *
+ * HASFSTYPE is defined as 1 for those systems that have a file system type
+ * string, st_fstype, in the stat() buffer; 2, for those systems that have a
+ * file system type integer in the stat() buffer, named MOUNTS_STAT_FSTYPE;
+ * 0, for systems whose stat(2) structure has no file system type member. The
+ * additional symbols MOUNTS_FSTYPE, RMNT_FSTYPE, and RMNT_STAT_FSTYPE may be
+ * defined in dlsof.h to direct how the readmnt() function in lib/rmnt.c
+ * preserves these stat(2) and getmntent(3) buffer values in the local mounts
+ * structure.
+ *
+ * The defined value is the string that names the file system type.
+ *
+ * The HASPROCFS definition usually must be accompanied by the HASFSTYPE
+ * definition and the providing of an fstype element in the local mounts
+ * structure (defined in dlsof.h).
+ *
+ * The HASPROCFS definition may be accompanied by the HASPINODEN definition.
+ * HASPINODEN specifies that searching for files in HASPROCFS is to be done
+ * by inode number.
+ */
+
+/* #define HASPROCFS "proc?" */
+/* #define HASFSTYPE 1 */
+/* #define HASPINODEN 1 */
+
+
+/*
+ * HASRNODE is defined for those dialects that have rnodes.
+ */
+
+# if defined(HAS_NFS)
+#define HASRNODE 1
+# endif /* defined(HAS_NFS) */
+
+
+/*
+ * Define HASSECURITY to restrict the listing of all open files to the
+ * root user. When HASSECURITY is defined, the non-root user may list
+ * only files whose processes have the same user ID as the real user ID
+ * (the one that its user logged on with) of the lsof process.
+ */
+
+/* #define HASSECURITY 1 */
+
+
+/*
+ * If HASSECURITY is defined, define HASNOSOCKSECURITY to allow users
+ * restricted by HASSECURITY to list any open socket files, provide their
+ * listing is selected by the "-i" option.
+ */
+
+/* #define HASNOSOCKSECURITY 1 */
+
+
+/*
+ * HASSETLOCALE is defined for those dialects that have <locale.h> and
+ * setlocale().
+ *
+ * If the dialect also has wide character support for language locales,
+ * HASWIDECHAR activates lsof's wide character support and WIDECHARINCL
+ * defines the header file (if any) that must be #include'd to use the
+ * mblen() and mbtowc() functions.
+ */
+
+#define HASSETLOCALE 1
+
+# if OSRV>=506
+#define HASWIDECHAR 1
+# endif /* OSRV>=506 */
+
+/* #define WIDECHARINCL <wchar.h> */
+
+
+/*
+ * HASSNODE is defined for those dialects that have snodes.
+ */
+
+/* #define HASSNODE 1 */
+
+
+/*
+ * HASTASKS is defined for those dialects that have task reporting support.
+ */
+
+/* #define HASTASKS 1 */
+
+
+/*
+ * HASSOOPT, HASSOSTATE and HASTCPOPT define the availability of information
+ * on socket options (SO_* symbols), socket states (SS_* symbols) and TCP
+ * options.
+ */
+
+#define HASSOOPT 1 /* has socket option information */
+#define HASSOSTATE 1 /* has socket state information */
+#define HASTCPOPT 1 /* has TCP options or flags */
+
+
+/*
+ * Define HASSPECDEVD to be the name of a function that handles the results
+ * of a successful stat(2) of a file name argument.
+ *
+ * For example, HASSPECDEVD() for Darwin makes sure that st_dev is set to
+ * what stat("/dev") returns -- i.e., what's in DevDev.
+ *
+ * The function takes two arguments:
+ *
+ * 1: pointer to the full path name of file
+ * 2: pointer to the stat(2) result
+ *
+ * The function returns void.
+ */
+
+/* #define HASSPECDEVD process_dev_stat */
+
+
+/*
+ * HASSTREAMS is defined for those systems that support streams.
+ */
+
+#define HASSTREAMS 1
+
+
+/*
+ * HASTCPTPIQ is defined for dialects where it is possible to report the
+ * TCP/TPI Recv-Q and Send-Q values produced by netstat.
+ */
+
+#define HASTCPTPIQ 1
+
+
+/*
+ * HASTCPTPIW is defined for dialects where it is possible to report the
+ * TCP/TPI send and receive window sizes produced by netstat.
+ */
+
+/* #define HASTCPTPIW 1 */
+
+
+/*
+ * HASTMPNODE is defined for those dialects that have tmpnodes.
+ */
+
+/* #define HASTMPNODE 1 */
+
+
+/*
+ * HASVNODE is defined for those dialects that use the Sun virtual file
+ * system node, the vnode. BSD derivatives usually do; System V derivatives
+ * prior to R4 usually don't.
+ */
+
+/* #define HASVNODE 1 */
+
+
+/*
+ * HASXOPT is defined for those dialects that have an X option. It
+ * defines the text for the usage display. HASXOPT_VALUE defines the
+ * option's default binary value -- 0 or 1.
+ */
+
+/* #define HASXOPT "help text for X option" */
+/* #define HASXOPT_VALUE 1 */
+
+
+/*
+ * INODETYPE and INODEPSPEC define the internal node number type and its
+ * printf specification modifier. These need not be defined and lsof.h
+ * can be allowed to define defaults.
+ *
+ * These are defined here, because they must be used in dlsof.h.
+ */
+
+/* #define INODETYPE unsigned long long */
+ /* inode number internal storage type */
+/* #define INODEPSPEC "ll" * INODETYPE printf specification
+ * modifier */
+
+
+/*
+ * UID_ARG defines the size of a User ID number when it is passed
+ * as a function argument.
+ */
+
+#define UID_ARG int
+
+
+/*
+ * Each USE_LIB_<function_name> is defined for dialects that use the
+ * <function_name> in the lsof library.
+ *
+ * Note: other definitions and operations may be required to condition the
+ * library function source code. They may be found in the dialect dlsof.h
+ * header files.
+ */
+
+/* #define USE_LIB_CKKV 1 ckkv.c */
+/* #define USE_LIB_COMPLETEVFS 1 cvfs.c */
+#define USE_LIB_FIND_CH_INO 1 /* fino.c */
+#define USE_LIB_IS_FILE_NAMED 1 /* isfn.c */
+#define USE_LIB_LKUPDEV 1 /* lkud.c */
+#define USE_LIB_PRINTDEVNAME 1 /* pdvn.c */
+/* #define USE_LIB_PROCESS_FILE 1 prfp.c */
+#define USE_LIB_PRINT_TCPTPI 1 /* ptti.c */
+#define USE_LIB_READDEV 1 /* rdev.c */
+/* #define USE_LIB_READMNT 1 rmnt.c */
+/* #define USE_LIB_REGEX 1 regex.c */
+/* #define USE_LIB_RNAM 1 rnam.c */
+/* #define USE_LIB_RNCH 1 rnch.c */
+/* #define USE_LIB_RNMH 1 rnmh.c */
+
+# if OSRV<500
+#define USE_LIB_SNPF 1 /* snpf.c */
+# else /* OSRV>=500 */
+#define snpf snprintf /* use the system's snprintf() */
+# endif /* OSRV<500 */
+
+
+/*
+ * WARNDEVACCESS is defined for those dialects that should issue a warning
+ * when lsof can't access /dev (or /device) or one of its sub-directories.
+ * The warning can be inhibited by the lsof caller with the -w option.
+ */
+
+/* #define WARNDEVACCESS 1 */
+
+
+/*
+ * WARNINGSTATE is defined for those dialects that want to suppress all lsof
+ * warning messages.
+ */
+
+/* #define WARNINGSTATE 1 warnings are enabled by default */
+
+
+/*
+ * WILLDROPGID is defined for those dialects whose lsof executable runs
+ * setgid(not_real_GID) and whose setgid power can be relinquished after
+ * the dialect's initialize() function has been executed.
+ */
+
+#define WILLDROPGID 1
+
+
+/*
+ * zeromem is a macro that uses bzero or memset.
+ */
+
+#define zeromem(a, l) memset(a, 0, l)
+#endif /* !defined(LSOF_MACHINE_H) */
diff --git a/dialects/sun/Makefile b/dialects/sun/Makefile
new file mode 100644
index 0000000..49dac14
--- /dev/null
+++ b/dialects/sun/Makefile
@@ -0,0 +1,160 @@
+
+# Sun Makefile
+#
+# $Id: Makefile,v 1.13 2008/04/15 13:30:50 abe Exp $
+
+PROG= lsof
+
+I=/usr/include
+S=/usr/include/sys
+L=/usr/include/local
+P=
+
+CDEF=
+CDEFS= ${CDEF} ${CFGF}
+INCL= ${DINC}
+CFLAGS= ${CDEFS} ${INCL} ${DEBUG}
+
+HDR= lsof.h lsof_fields.h dlsof.h machine.h proto.h dproto.h
+
+SRC= ddev.c dfile.c dmnt.c dnode.c dnode1.c dnode2.c dproc.c dsock.c \
+ dstore.c \
+ arg.c main.c misc.c node.c print.c proc.c store.c usage.c util.c
+
+OBJ= ddev.o dfile.o dmnt.o dnode.o dnode1.o dnode2.o dproc.o dsock.o \
+ dstore.o \
+ arg.o main.o misc.o node.o print.o proc.o store.o usage.o util.o
+
+MAN= lsof.8
+
+OTHER=
+
+SHELL= /bin/sh
+
+SOURCE= Makefile ${OTHER} ${MAN} ${HDR} ${SRC}
+
+all: ${PROG}
+
+${PROG}: ${LIB} ${P} ${OBJ}
+ ${CC} -o $@ ${CFLAGS} ${OBJ} ${CFGL}
+
+clean: FRC
+ rm -f Makefile.bak ${PROG} a.out core errs lint.out tags *.o version.h
+ rm -f machine.h.old new_machine.h
+ (cd lib; ${MAKE} -f Makefile.skel clean)
+
+install: all FRC
+ @echo ''
+ @echo 'Please write your own install rule. Lsof should be installed'
+ @echo 'setgid to the group that can can read /dev/kmem. Normally'
+ @echo 'that is the kmem (SunOS) or sys (Solaris) group. Your SunOS'
+ @echo 'install rule actions might look something like this:'
+ @echo ''
+ @echo ' install <options> -m 2755 -g kmem ${PROG} <bin_dest>'
+ @echo ' install <options> -m 444 ${MAN} <man_dest>'
+ @echo ''
+ @echo 'Your Solaris install rule actions might look something like
+ @echo 'this:'
+ @echo ''
+ @echo ' install -[cf] <bin_dest> <options> -m 2755 -g sys ${PROG}'
+ @echo ' install -[cf] <man_dest> <options> -m 444 ${MAN}'
+ @echo ''
+ @echo 'You may have to put additional values in <options>, as required'
+ @echo 'by the install application in your version of SunOS or Solaris.'
+ @echo 'You will have to set the appropriate destination for the lsof'
+ @echo 'executable in <bin_dest>; the appropriate destination for the'
+ @echo 'man page in <man_dest>.'
+ @echo ''
+
+${LIB}: FRC
+ (cd lib; ${MAKE} DEBUG="${DEBUG}" CFGF="${CFGF}")
+
+version.h: FRC
+ @echo Constructing version.h
+ @rm -f version.h
+ @echo '#define LSOF_BLDCMT "${LSOF_BLDCMT}"' > version.h;
+ @echo '#define LSOF_CC "${CC}"' >> version.h
+ @echo '#define LSOF_CCV "${CCV}"' >> version.h
+ @echo '#define LSOF_CCDATE "'`date`'"' >> version.h
+ @echo '#define LSOF_CCFLAGS "'`echo ${CFLAGS} | sed 's/\\\\(/\\(/g' | sed 's/\\\\)/\\)/g' | sed 's/"/\\\\"/g'`'"' >> version.h
+ @echo '#define LSOF_CINFO "${CINFO}"' >> version.h
+ @if [ "X${LSOF_HOST}" = "X" ]; then \
+ echo '#define LSOF_HOST "'`uname -n`'"' >> version.h; \
+ else \
+ if [ "${LSOF_HOST}" = "none" ]; then \
+ echo '#define LSOF_HOST ""' >> version.h; \
+ else \
+ echo '#define LSOF_HOST "${LSOF_HOST}"' >> version.h; \
+ fi \
+ fi
+ @echo '#define LSOF_LDFLAGS "${CFGL}"' >> version.h
+ @if [ "X${LSOF_LOGNAME}" = "X" ]; then \
+ echo '#define LSOF_LOGNAME "${LOGNAME}"' >> version.h; \
+ else \
+ if [ "${LSOF_LOGNAME}" = "none" ]; then \
+ echo '#define LSOF_LOGNAME ""' >> version.h; \
+ else \
+ echo '#define LSOF_LOGNAME "${LSOF_LOGNAME}"' >> version.h; \
+ fi; \
+ fi
+ @if [ "X${LSOF_SYSINFO}" = "X" ]; then \
+ echo '#define LSOF_SYSINFO "'`uname -a`'"' >> version.h; \
+ else \
+ if [ "${LSOF_SYSINFO}" = "none" ]; then \
+ echo '#define LSOF_SYSINFO ""' >> version.h; \
+ else \
+ echo '#define LSOF_SYSINFO "${LSOF_SYSINFO}"' >> version.h; \
+ fi \
+ fi
+ @if [ "X${LSOF_USER}" = "X" ]; then \
+ echo '#define LSOF_USER "${USER}"' >> version.h; \
+ else \
+ if [ "${LSOF_USER}" = "none" ]; then \
+ echo '#define LSOF_USER ""' >> version.h; \
+ else \
+ echo '#define LSOF_USER "${LSOF_USER}"' >> version.h; \
+ fi \
+ fi
+ @sed '/VN/s/.ds VN \(.*\)/#define LSOF_VERSION "\1"/' < version >> version.h
+
+FRC:
+
+# DO NOT DELETE THIS LINE - make depend DEPENDS ON IT
+
+ddev.o: ${HDR} ddev.c
+
+dfile.o: ${HDR} dfile.c
+
+dmnt.o: ${HDR} dmnt.c
+
+dnode.o: ${HDR} dnode.c
+
+dnode1.o: ${HDR} dnode1.c
+
+dnode2.o: ${HDR} dnode2.c
+
+dproc.o: ${HDR} kernelbase.h dproc.c
+
+dsock.o: ${HDR} dsock.c
+
+dstore.o: ${HDR} dstore.c
+
+arg.o: ${HDR} arg.c
+
+main.o: ${HDR} main.c
+
+misc.o: ${HDR} misc.c
+
+node.o: ${HDR} node.c
+
+print.o: ${HDR} print.c
+
+proc.o: ${HDR} proc.c
+
+store.o: ${HDR} store.c
+
+usage.o: ${HDR} version.h usage.c
+
+util.o: ${HDR} util.c
+
+# *** Do not add anything here - It will go away. ***
diff --git a/dialects/sun/Mksrc b/dialects/sun/Mksrc
new file mode 100755
index 0000000..4641bb5
--- /dev/null
+++ b/dialects/sun/Mksrc
@@ -0,0 +1,57 @@
+#!/bin/sh
+#
+# Mksrc - make Solaris source files
+#
+# WARNING: This script assumes it is running from the main directory
+# of the lsof, version 4 distribution.
+#
+# One environment variable applies:
+#
+# LSOF_MKC is the method for creating the source files.
+# It defaults to "ln -s". A common alternative is "cp".
+#
+# $Id: Mksrc,v 1.4 2000/12/04 14:35:13 abe Exp $
+
+
+D=dialects/sun
+L="ddev.c dfile.c dlsof.h dmnt.c dnode.c dnode1.c dnode2.c dproc.c dproto.h dsock.c dstore.c machine.h"
+
+for i in $L
+do
+ rm -f $i
+ $LSOF_MKC $D/$i $i
+ echo "$LSOF_MKC $D/$i $i"
+done
+
+# Assemble kernelbase.h for SunOS and Solaris < 2.5 (5.5)
+
+NM=kernelbase.h
+rm -f $NM
+if test "X$1" != "Xsolaris" -o $2 -lt 20500
+then
+ if test "X$1" = "Xsolaris"
+ then
+ A=`uname -m`
+ if test "$A" = "i86pc"
+ then
+ H=/usr/include/sys/machparam.h
+ else
+ H=/usr/src/uts/$A/sys/machparam.h
+ fi
+ else
+ H=/usr/include/machine/param.h
+ fi
+ echo "#if !defined(KERNELSIZE)" > $NM
+ grep "^#define[ ]*KERNELSIZE" $H >> $NM
+ echo "#endif" >> $NM
+ echo "#if !defined(KERNELBASE)" >> $NM
+ grep "^#define[ ]*KERNELBASE" $H >> $NM
+ echo "#endif" >> $NM
+else
+
+# To keep the dependency list for dproc.o simple in the Makefile,
+# create an empty kernelbase.h for Solaris 2.5 (5.5) and above.
+
+ touch $NM
+fi
+echo "$NM assembled."
diff --git a/dialects/sun/ddev.c b/dialects/sun/ddev.c
new file mode 100644
index 0000000..83bd2ce
--- /dev/null
+++ b/dialects/sun/ddev.c
@@ -0,0 +1,1143 @@
+/*
+ * ddev.c - Solaris device support functions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: ddev.c,v 1.20 2005/08/08 19:55:41 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+/*
+ * Local definitions
+ */
+
+#define LIKE_BLK_SPEC "like block special"
+#define LIKE_CHR_SPEC "like character special"
+
+
+/*
+ * Local static values
+ */
+
+static int Devx = 0; /* current Devtp[] index */
+
+
+/*
+ * Local function prototypes
+ */
+
+_PROTOTYPE(static void make_devtp,(struct stat *s, char *p));
+_PROTOTYPE(static int rmdupdev,(struct l_dev ***dp, int n, int ty));
+
+
+/*
+ * make_devtp() - make Devtp[] entry
+ */
+
+static void
+make_devtp(s, p)
+ struct stat *s; /* device lstat() buffer */
+ char *p; /* device path name */
+{
+
+/*
+ * Make room for another Devtp[] entry.
+ */
+ if (Devx >= Ndev) {
+ Ndev += DEVINCR;
+ if (!Devtp)
+ Devtp = (struct l_dev *)malloc(
+ (MALLOC_S)(sizeof(struct l_dev) * Ndev));
+ else
+ Devtp = (struct l_dev *)realloc((MALLOC_P *)Devtp,
+ (MALLOC_S)(sizeof(struct l_dev) * Ndev));
+ if (!Devtp) {
+ (void) fprintf(stderr, "%s: no space for character device\n",
+ Pn);
+ Exit(1);
+ }
+ }
+/*
+ * Store the device number, inode number, and name in the Devtp[] entry.
+ */
+ Devtp[Devx].inode = (INODETYPE)s->st_ino;
+ if (!(Devtp[Devx].name = mkstrcpy(p, (MALLOC_S *)NULL))) {
+ (void) fprintf(stderr, "%s: no space for /dev/", Pn);
+ safestrprt(p, stderr, 1);
+ Exit(1);
+ }
+ Devtp[Devx].rdev = s->st_rdev;
+ Devtp[Devx].v = 0;
+ Devx++;
+}
+
+
+/*
+ * printdevname() - print block or character device name
+ */
+
+int
+printdevname(dev, rdev, f, nty)
+ dev_t *dev; /* device */
+ dev_t *rdev; /* raw device */
+ int f; /* 1 = print trailing '\n' */
+ int nty; /* node type: N_BLK or N_CHR */
+{
+ struct clone *c;
+ struct l_dev *dp;
+ struct pseudo *p;
+
+ readdev(0);
+/*
+ * Search device table for a full match.
+ */
+
+#if defined(HASDCACHE)
+
+printchdevname_again:
+
+#endif /* defined(HASDCACHE) */
+
+#if defined(HASBLKDEV)
+ if (nty == N_BLK)
+ dp = lkupbdev(dev, rdev, 1, 0);
+ else
+#endif /* defined(HASBLKDEV) */
+
+ dp = lkupdev(dev, rdev, 1, 0);
+ if (dp) {
+ safestrprt(dp->name, stdout, f);
+ return(1);
+ }
+/*
+ * Search device table for a match without inode number and dev.
+ */
+
+#if defined(HASBLKDEV)
+ if (nty == N_BLK)
+ dp = lkupbdev(&DevDev, rdev, 0, 0);
+ else
+#endif /* defined(HASBLKDEV) */
+
+ dp = lkupdev(&DevDev, rdev, 0, 0);
+ if (dp) {
+
+ /*
+ * A match was found. Record it as a name column addition.
+ */
+ char *cp, *ttl;
+ int len;
+
+ ttl = (nty == N_BLK) ? LIKE_BLK_SPEC : LIKE_CHR_SPEC;
+ len = (int)(1 + strlen(ttl) + 1 + strlen(dp->name) + 1);
+ if (!(cp = (char *)malloc((MALLOC_S)(len + 1)))) {
+ (void) fprintf(stderr, "%s: no nma space for: (%s %s)\n",
+ Pn, ttl, dp->name);
+ Exit(1);
+ }
+ (void) snpf(cp, len + 1, "(%s %s)", ttl, dp->name);
+ (void) add_nma(cp, len);
+ (void) free((MALLOC_P *)cp);
+ return(0);
+ }
+/*
+ * Search for clone parent.
+ */
+ if ((nty == N_CHR) && Lf->is_stream && Clone && (*dev == DevDev)) {
+ for (c = Clone; c; c = c->next) {
+ if (GET_MAJ_DEV(*rdev) == GET_MIN_DEV(c->cd.rdev)) {
+
+#if defined(HASDCACHE)
+ if (DCunsafe && !c->cd.v && !vfy_dev(&c->cd))
+ goto printchdevname_again;
+#endif /* defined(HASDCACHE) */
+
+ safestrprt(c->cd.name, stdout, f);
+ return(1);
+ }
+ }
+ }
+/*
+ * Search for pseudo device match on major device only.
+ */
+ if ((nty == N_CHR) && *dev == DevDev) {
+ for (p = Pseudo; p; p = p->next) {
+ if (GET_MAJ_DEV(*rdev) == GET_MAJ_DEV(p->pd.rdev)) {
+
+# if defined(HASDCACHE)
+ if (DCunsafe && !p->pd.v && vfy_dev(&p->pd))
+ goto printchdevname_again;
+# endif /* defined(HASDCACHE) */
+
+ safestrprt(p->pd.name, stdout, f);
+ return(1);
+ }
+ }
+ }
+
+#if defined(HASDCACHE)
+/*
+ * If the device cache is "unsafe" and we haven't found any match, reload
+ * the device cache.
+ */
+ if (DCunsafe) {
+ (void) rereaddev();
+ goto printchdevname_again;
+ }
+#endif /* defined(HASDCACHE) */
+
+ return(0);
+}
+
+
+/*
+ * read_clone() - read Solaris clone device information
+ */
+
+void
+read_clone()
+{
+ struct clone *c;
+ char *cn;
+ DIR *dfp;
+ struct DIRTYPE *dp;
+ char *fp = (char *)NULL;
+ MALLOC_S fpl;
+ char *path;
+ MALLOC_S pl;
+ struct pseudo *p;
+ struct stat sb;
+
+ if (Clone || Pseudo)
+ return;
+/*
+ * Open the /DVCH_DEVPATH/pseudo directory.
+ */
+ if (!(path = mkstrcat(DVCH_DEVPATH, -1, "/", 1, "pseudo ", -1, &pl))) {
+ (void) fprintf(stderr, "%s: no space for %s/pseudo\n",
+ DVCH_DEVPATH, Pn);
+ Exit(1);
+ }
+ path[pl - 1] = '\0';
+ if (!(dfp = OpenDir(path))) {
+
+#if defined(WARNDEVACCESS)
+ if (!Fwarn) {
+ (void) fprintf(stderr, "%s: WARNING: can't open: ", Pn);
+ safestrprt(path, stderr, 1);
+ }
+#endif /* defined(WARNDEVACCESS) */
+
+ (void) free((FREE_P *)path);
+ return;
+ }
+ path[pl - 1] = '/';
+/*
+ * Scan the directory.
+ */
+ for (dp = ReadDir(dfp); dp; dp = ReadDir(dfp)) {
+ if (dp->d_ino == 0 || dp->d_name[0] == '.')
+ continue;
+ /*
+ * Form the full path name and stat() it.
+ */
+ if (fp) {
+ (void) free((FREE_P *)fp);
+ fp = (char *)NULL;
+ }
+ if (!(fp = mkstrcat(path, pl, dp->d_name, -1, (char *)NULL, -1,
+ &fpl)))
+ {
+ (void) fprintf(stderr, "%s: no space for: ", Pn);
+ safestrprt(path, stderr, 0);
+ safestrprt(dp->d_name, stderr, 1);
+ Exit(1);
+ }
+
+#if defined(USE_STAT)
+ if (stat(fp, &sb) != 0)
+#else /* !defined(USE_STAT) */
+ if (lstat(fp, &sb) != 0)
+#endif /* defined(USE_STAT) */
+
+ {
+ if (!Fwarn) {
+ int errno_save = errno;
+
+ (void) fprintf(stderr, "%s: can't stat: ", Pn);
+ safestrprt(fp, stderr, 0);
+ (void) fprintf(stderr, ": %s\n", strerror(errno_save));
+ }
+ continue;
+ }
+ /*
+ * Skip subdirectories and all but character devices.
+ */
+ if ((sb.st_mode & S_IFMT) == S_IFDIR
+ || (sb.st_mode & S_IFMT) != S_IFCHR)
+ continue;
+ /*
+ * Make Devtp[] entry.
+ */
+ make_devtp(&sb, fp);
+ /*
+ * Create a clone structure entry for "clone*:" devices.
+ *
+ * Make special note of network clones -- tcp, and udp.
+ */
+ if (strncmp(&fp[pl], "clone", 5) == 0) {
+ if (!(cn = strrchr(&fp[pl], ':')))
+ continue;
+ /*
+ * Allocate a clone structure.
+ */
+ if (!(c = (struct clone *)malloc(sizeof(struct clone)))) {
+ (void) fprintf(stderr,
+ "%s: no space for network clone device: ", Pn);
+ safestrprt(fp, stderr, 1);
+ Exit(1);
+ }
+ /*
+ * Allocate space for the path name.
+ */
+ if (!(c->cd.name = mkstrcpy(fp, (MALLOC_S *)NULL))) {
+ (void) fprintf(stderr, "%s: no space for clone name: ", Pn);
+ safestrprt(fp, stderr, 1);
+ Exit(1);
+ }
+ /*
+ * Save the inode and device numbers. Clear the verify flag.
+ */
+ c->cd.inode = (INODETYPE)sb.st_ino;
+ c->cd.rdev = sb.st_rdev;
+ c->cd.v = 0;
+ /*
+ * Make special note of a network clone device.
+ */
+ if (!strcmp(++cn, "tcp") || !strcmp(cn, "udp"))
+ c->n = cn - fp;
+ else
+ c->n = 0;
+ /*
+ * Link the new clone entry to the rest.
+ */
+ c->next = Clone;
+ Clone = c;
+ continue;
+ }
+ /*
+ * Save pseudo device information.
+ */
+ if (GET_MIN_DEV(sb.st_rdev) == 0) {
+
+ /*
+ * Allocate space for the pseduo device entry.
+ */
+ if (!(p = (struct pseudo *) malloc(sizeof(struct pseudo)))) {
+ (void) fprintf(stderr,
+ "%s: no space for pseudo device: ", Pn);
+ safestrprt(fp, stderr, 1);
+ Exit(1);
+ }
+ /*
+ * Save the path name, and inode and device numbers. Clear the
+ * verify flag. Link the entry to the pseudo chain.
+ */
+ p->pd.inode = (INODETYPE)sb.st_ino;
+ p->pd.name = fp;
+ fp = (char *)NULL;
+ p->pd.rdev = sb.st_rdev;
+ p->pd.v = 0;
+ p->next = Pseudo;
+ Pseudo = p;
+ }
+ }
+ (void) CloseDir(dfp);
+ if (fp)
+ (void) free((FREE_P *)fp);
+ if (path)
+ (void) free((FREE_P *)path);
+}
+
+
+/*
+ * readdev() - read names, modes and device types of everything in /dev
+ * or /device (Solaris)
+ */
+
+void
+readdev(skip)
+ int skip; /* skip device cache read if 1 */
+{
+
+#if defined(HASDCACHE)
+ int dcrd = 0;
+#endif /* defined(HASDCACHE) */
+
+ DIR *dfp;
+ struct DIRTYPE *dp;
+ char *fp = (char *)NULL;
+ MALLOC_S fpl;
+ int i;
+
+#if defined(HASBLKDEV)
+ int j = 0;
+#endif /* defined(HASBLKDEV) */
+
+ char *path = (char *)NULL;
+ char *ppath = (char *)NULL;
+ MALLOC_S pl;
+ struct stat sb;
+
+ if (Sdev)
+ return;
+
+#if defined(HASDCACHE)
+/*
+ * Read device cache, as directed.
+ */
+ if (!skip) {
+ if (DCstate == 2 || DCstate == 3) {
+ if ((dcrd = read_dcache()) == 0)
+ return;
+ }
+ } else
+ dcrd = 1;
+#endif /* defined(HASDCACHE) */
+
+ if (!(ppath = mkstrcat(DVCH_DEVPATH, -1, "/", 1, "pseudo", -1,
+ (MALLOC_S *)NULL)))
+ {
+ (void) fprintf(stderr, "%s: no space for: %s/pseudo\n",
+ Pn, DVCH_DEVPATH);
+ Exit(1);
+ }
+ read_clone();
+ Dstk = (char **)NULL;
+ Dstkn = Dstkx = 0;
+ (void) stkdir(DVCH_DEVPATH);
+/*
+ * Unstack the next directory.
+ */
+ while (--Dstkx >= 0) {
+ if (!(dfp = OpenDir(Dstk[Dstkx]))) {
+
+#if defined(WARNDEVACCESS)
+ if (!Fwarn) {
+ (void) fprintf(stderr, "%s: WARNING: can't open: ", Pn);
+ safestrprt(Dstk[Dstkx], stderr, 1);
+ }
+#endif /* defined(WARNDEVACCESS) */
+
+ (void) free((FREE_P *)Dstk[Dstkx]);
+ Dstk[Dstkx] = (char *)NULL;
+ continue;
+ }
+ /*
+ * Create a directory name buffer with a trailing slash.
+ */
+ if (path) {
+ (void) free((FREE_P *)path);
+ path = (char *)NULL;
+ }
+ if (!(path = mkstrcat(Dstk[Dstkx], -1, "/", 1, (char *)NULL, -1,
+ &pl)))
+ {
+ (void) fprintf(stderr, "%s: no space for: ", Pn);
+ safestrprt(Dstk[Dstkx], stderr, 1);
+ Exit(1);
+ }
+ (void) free((FREE_P *)Dstk[Dstkx]);
+ Dstk[Dstkx] = (char *)NULL;
+ /*
+ * Scan the directory.
+ */
+ for (dp = ReadDir(dfp); dp; dp = ReadDir(dfp)) {
+ if (dp->d_ino == 0 || dp->d_name[0] == '.')
+ continue;
+ /*
+ * Form the full path name and get its status.
+ */
+ if (fp) {
+ (void) free((FREE_P *)fp);
+ fp = (char *)NULL;
+ }
+ if (!(fp = mkstrcat(path, pl, dp->d_name, -1, (char *)NULL, -1,
+ &fpl)))
+ {
+ (void) fprintf(stderr, "%s: no space for: ", Pn);
+ safestrprt(path, stderr, 0);
+ safestrprt(dp->d_name, stderr, 1);
+ Exit(1);
+ }
+
+#if defined(USE_STAT)
+ if (stat(fp, &sb) != 0)
+#else /* !defined(USE_STAT) */
+ if (lstat(fp, &sb) != 0)
+#endif /* defined(USE_STAT) */
+
+ {
+ if (errno == ENOENT) /* symbolic link to nowhere? */
+ continue;
+
+#if defined(WARNDEVACCESS)
+ if (!Fwarn) {
+ int errno_save = errno;
+
+ (void) fprintf(stderr, "%s: can't stat ", Pn);
+ safestrprt(fp, stderr, 0);
+ (void) fprintf(stderr, ": %s\n", strerror(errno_save));
+ }
+#endif /* defined(WARNDEVACCESS) */
+
+ continue;
+ }
+ /*
+ * If it's a subdirectory, stack its name for later processing.
+ */
+ if ((sb.st_mode & S_IFMT) == S_IFDIR) {
+
+ /*
+ * Skip Solaris /DVCH_DEV_PATH/pseudo sub-directory;
+ * it has been examined in read_clone().
+ */
+ if (strcmp(fp, ppath) == 0)
+ continue;
+ (void) stkdir(fp);
+ continue;
+ }
+ if ((sb.st_mode & S_IFMT) == S_IFCHR) {
+
+ /*
+ * Make Devtp[] entry.
+ */
+ make_devtp(&sb, fp);
+ }
+
+#if defined(HASBLKDEV)
+ if ((sb.st_mode & S_IFMT) == S_IFBLK) {
+
+ /*
+ * Save block device information in BDevtp[].
+ */
+ if (j >= BNdev) {
+ BNdev += DEVINCR;
+ if (!BDevtp)
+ BDevtp = (struct l_dev *)malloc(
+ (MALLOC_S)(sizeof(struct l_dev)*BNdev));
+ else
+ BDevtp = (struct l_dev *)realloc((MALLOC_P *)BDevtp,
+ (MALLOC_S)(sizeof(struct l_dev)*BNdev));
+ if (!BDevtp) {
+ (void) fprintf(stderr,
+ "%s: no space for block device\n", Pn);
+ Exit(1);
+ }
+ }
+ BDevtp[j].rdev = sb.st_rdev;
+ BDevtp[j].inode = (INODETYPE)sb.st_ino;
+ BDevtp[j].name = fp;
+ fp = (char *)NULL;
+ BDevtp[j].v = 0;
+ j++;
+ }
+#endif /* defined(HASBLKDEV) */
+
+ }
+ (void) CloseDir(dfp);
+ }
+/*
+ * Free any allocated space.
+ */
+ if (Dstk) {
+ (void) free((FREE_P *)Dstk);
+ Dstk = (char **)NULL;
+ Dstkn = Dstkx = 0;
+ }
+ if (fp)
+ (void) free((FREE_P *)fp);
+ if (path)
+ (void) free((FREE_P *)path);
+ if (ppath)
+ (void) free((FREE_P *)ppath);
+/*
+ * Reduce the BDevtp[] (optional) and Devtp[] tables to their minimum
+ * sizes; allocate and build sort pointer lists; and sort the tables by
+ * device number.
+ */
+
+#if defined(HASBLKDEV)
+ if (BNdev) {
+ if (BNdev > j) {
+ BNdev = j;
+ BDevtp = (struct l_dev *)realloc((MALLOC_P *)BDevtp,
+ (MALLOC_S)(sizeof(struct l_dev) * BNdev));
+ }
+ if (!(BSdev = (struct l_dev **)malloc(
+ (MALLOC_S)(sizeof(struct l_dev *) * BNdev))))
+ {
+ (void) fprintf(stderr,
+ "%s: no space for block device sort pointers\n", Pn);
+ Exit(1);
+ }
+ for (j = 0; j < BNdev; j++) {
+ BSdev[j] = &BDevtp[j];
+ }
+ (void) qsort((QSORT_P *)BSdev, (size_t)BNdev,
+ (size_t)sizeof(struct l_dev *), compdev);
+ BNdev = rmdupdev(&BSdev, BNdev, 0);
+ } else {
+ if (!Fwarn)
+ (void) fprintf(stderr,
+ "%s: WARNING: no block devices found\n", Pn);
+ }
+#endif /* defined(HASBLKDEV) */
+
+ if (Ndev) {
+ if (Ndev > Devx) {
+ Ndev = Devx;
+ Devtp = (struct l_dev *)realloc((MALLOC_P *)Devtp,
+ (MALLOC_S)(sizeof(struct l_dev) * Ndev));
+ }
+ if (!(Sdev = (struct l_dev **)malloc(
+ (MALLOC_S)(sizeof(struct l_dev *) * Ndev))))
+ {
+ (void) fprintf(stderr,
+ "%s: no space for character device sort pointers\n", Pn);
+ Exit(1);
+ }
+ for (i = 0; i < Ndev; i++) {
+ Sdev[i] = &Devtp[i];
+ }
+ (void) qsort((QSORT_P *)Sdev, (size_t)Ndev,
+ (size_t)sizeof(struct l_dev *), compdev);
+ Ndev = rmdupdev(&Sdev, Ndev, 1);
+ } else {
+ (void) fprintf(stderr, "%s: no character devices found\n", Pn);
+ Exit(1);
+ }
+
+#if defined(HASDCACHE)
+/*
+ * Write device cache file, as required.
+ */
+ if (DCstate == 1 || (DCstate == 3 && dcrd))
+ write_dcache();
+#endif /* defined(HASDCACHE) */
+
+}
+
+
+/*
+ * clr_sect() - clear cached clone and pseudo sections
+ */
+
+void
+clr_sect()
+{
+ if (Clone) {
+ struct clone *c, *c1;
+
+ for (c = Clone; c; c = c1) {
+ c1 = c->next;
+ if (c->cd.name)
+ (void) free((FREE_P *)c->cd.name);
+ (void) free((FREE_P *)c);
+ }
+ Clone = (struct clone *)NULL;
+ }
+ if (Pseudo) {
+ struct pseudo *p, *p1;
+
+ for (p = Pseudo; p; p = p1) {
+ p1 = p->next;
+ if (p->pd.name)
+ (void) free((FREE_P *)p->pd.name);
+ (void) free((FREE_P *)p);
+ }
+ Pseudo = (struct pseudo *)NULL;
+ }
+}
+
+
+#if defined(HASDCACHE)
+/*
+ * rw_clone_sect() - read/write the device cache file clone section
+ */
+
+int
+rw_clone_sect(m)
+ int m; /* mode: 1 = read; 2 = write */
+{
+ char buf[MAXPATHLEN*2], *cp;
+ struct clone *c;
+ int i, len, n;
+
+ if (m == 1) {
+
+ /*
+ * Read the clone section header and validate it.
+ */
+ if (!fgets(buf, sizeof(buf), DCfs)) {
+
+bad_clone_sect:
+
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ "%s: bad clone section header in %s: ",
+ Pn, DCpath[DCpathX]);
+ safestrprt(buf, stderr, 1);
+ }
+ return(1);
+ }
+ (void) crc(buf, strlen(buf), &DCcksum);
+ len = strlen("clone section: ");
+ if (strncmp(buf, "clone section: ", len) != 0)
+ goto bad_clone_sect;
+ if ((n = atoi(&buf[len])) < 0)
+ goto bad_clone_sect;
+ /*
+ * Read the clone section lines and create the Clone list.
+ */
+ for (i = 0; i < n; i++) {
+ if (!fgets(buf, sizeof(buf), DCfs)) {
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ "%s: bad clone line in %s: ", Pn, DCpath[DCpathX]);
+ safestrprt(buf, stderr, 1);
+ }
+ return(1);
+ }
+ (void) crc(buf, strlen(buf), &DCcksum);
+ /*
+ * Allocate a clone structure.
+ */
+ if (!(c = (struct clone *)calloc(1, sizeof(struct clone)))) {
+ (void) fprintf(stderr,
+ "%s: no space for cached clone: ", Pn);
+ safestrprt(buf, stderr, 1);
+ Exit(1);
+ }
+ /*
+ * Enter the clone device number.
+ *
+ * New format clone lines (with an inode number) have a leading
+ * space, so that older lsof versions, not expecting them, will
+ * not use the new format lines.
+ */
+ if (buf[0] != ' '
+ || !(cp = x2dev(&buf[1], &c->cd.rdev)) || *cp++ != ' ')
+ {
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ "%s: bad cached clone device: ", Pn);
+ safestrprt(buf, stderr, 1);
+ }
+ return(1);
+ }
+ /*
+ * Enter the clone network value.
+ */
+ for (c->n = 0; *cp != ' '; cp++) {
+ if (*cp < '0' || *cp > '9') {
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ "%s: bad cached clone network flag: ", Pn);
+ safestrprt(buf, stderr, 1);
+ }
+ return(1);
+ }
+ c->n = (c->n * 10) + (int)(*cp - '0');
+ }
+ /*
+ * Enter the clone device inode number.
+ */
+ for (c->cd.inode = (INODETYPE)0, ++cp; *cp != ' '; cp++) {
+ if (*cp < '0' || *cp > '9') {
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ "%s: bad cached clone inode number: ", Pn);
+ safestrprt(buf, stderr, 1);
+ }
+ return(1);
+ }
+ c->cd.inode = (INODETYPE)((c->cd.inode * 10)
+ + (int)(*cp - '0'));
+ }
+ /*
+ * Enter the clone path name.
+ */
+ if ((len = strlen(++cp)) < 2 || *(cp + len - 1) != '\n') {
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ "%s: bad cached clone path: ", Pn);
+ safestrprt(buf, stderr, 1);
+ }
+ return(1);
+ }
+ *(cp + len - 1) = '\0';
+ if (!(c->cd.name = mkstrcpy(cp, (MALLOC_S *)NULL))) {
+ (void) fprintf(stderr,
+ "%s: no space for cached clone path: ", Pn);
+ safestrprt(buf, stderr, 1);
+ Exit(1);
+ }
+ c->cd.v = 0;
+ c->next = Clone;
+ Clone = c;
+ }
+ return(0);
+ } else if (m == 2) {
+
+ /*
+ * Write the clone section header.
+ */
+ for (c = Clone, n = 0; c; c = c->next, n++)
+ ;
+ (void) snpf(buf, sizeof(buf), "clone section: %d\n", n);
+ if (wr2DCfd(buf, &DCcksum))
+ return(1);
+ /*
+ * Write the clone section lines.
+ *
+ *
+ * New format clone lines (with an inode number) have a leading
+ * space, so that older lsof versions, not expecting them, will
+ * not use the new format lines.
+ */
+ for (c = Clone; c; c = c->next) {
+ (void) snpf(buf, sizeof(buf), " %lx %d %ld %s\n",
+ (long)c->cd.rdev, c->n, (long)c->cd.inode, c->cd.name);
+ if (wr2DCfd(buf, &DCcksum))
+ return(1);
+ }
+ return(0);
+ }
+/*
+ * A shouldn't-happen case: mode neither 1 nor 2.
+ */
+ (void) fprintf(stderr, "%s: internal rw_clone_sect error: %d\n",
+ Pn, m);
+ Exit(1);
+ return(1); /* to make code analyzers happy */
+}
+
+
+/*
+ * rereaddev() - reread device names, modes and types
+ */
+
+void
+rereaddev()
+{
+ (void) clr_devtab();
+ (void) clr_sect();
+ Devx = 0;
+
+# if defined(DCACHE_CLR)
+ (void) DCACHE_CLR();
+# endif /* defined(DCACHE_CLR) */
+
+ readdev(1);
+ DCunsafe = 0;
+}
+
+
+/*
+ * rw_pseudo_sect() - read/write the device cache pseudo section
+ */
+
+int
+rw_pseudo_sect(m)
+ int m; /* mode: 1 = read; 2 = write */
+{
+ char buf[MAXPATHLEN*2], *cp;
+ struct pseudo *p;
+ int i, len, n;
+
+ if (m == 1) {
+
+ /*
+ * Read the pseudo section header and validate it.
+ */
+ if (!fgets(buf, sizeof(buf), DCfs)) {
+
+bad_pseudo_sect:
+
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ "%s: bad pseudo section header in %s: ",
+ Pn, DCpath[DCpathX]);
+ safestrprt(buf, stderr, 1);
+ }
+ return(1);
+ }
+ (void) crc(buf, strlen(buf), &DCcksum);
+ len = strlen("pseudo section: ");
+ if (strncmp(buf, "pseudo section: ", len) != 0)
+ goto bad_pseudo_sect;
+ if ((n = atoi(&buf[len])) < 0)
+ goto bad_pseudo_sect;
+ /*
+ * Read the pseudo section lines and create the Pseudo list.
+ */
+ for (i = 0; i < n; i++) {
+ if (!fgets(buf, sizeof(buf), DCfs)) {
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ "%s: bad pseudo line in %s: ", Pn, DCpath[DCpathX]);
+ safestrprt(buf, stderr, 1);
+ }
+ return(1);
+ }
+ (void) crc(buf, strlen(buf), &DCcksum);
+ /*
+ * Allocate a pseudo structure.
+ */
+ if (!(p = (struct pseudo *)calloc(1, sizeof(struct pseudo)))) {
+ (void) fprintf(stderr,
+ "%s: no space for cached pseudo: ", Pn);
+ safestrprt(buf, stderr, 1);
+ Exit(1);
+ }
+ /*
+ * Enter the pseudo device number.
+ *
+ * New format pseudo lines (with an inode number) have a leading
+ * space, so that older lsof versions, not expecting them, will
+ * not use the new format lines.
+ */
+ if (buf[0] != ' '
+ || !(cp = x2dev(&buf[1], &p->pd.rdev)) || *cp++ != ' ')
+ {
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ "%s: bad cached pseudo device: ", Pn);
+ safestrprt(buf, stderr, 1);
+ }
+ return(1);
+ }
+ /*
+ * Enter the pseudo inode number.
+ */
+ for (p->pd.inode = (INODETYPE)0; *cp != ' '; cp++) {
+ if (*cp < '0' || *cp > '9') {
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ "%s: bad cached pseudo inode number: ", Pn);
+ safestrprt(buf, stderr, 1);
+ }
+ return(1);
+ }
+ p->pd.inode = (INODETYPE)((p->pd.inode * 10)
+ + (int)(*cp - '0'));
+ }
+ /*
+ * Enter the pseudo path name.
+ *
+ *
+ * New format clone lines (with an inode number) have a leading
+ * space, so that older lsof versions, not expecting them, will
+ * not use the new format lines.
+ */
+ if ((len = strlen(++cp)) < 2 || *(cp + len - 1) != '\n') {
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ "%s: bad cached pseudo path: ", Pn);
+ safestrprt(buf, stderr, 1);
+ }
+ return(1);
+ }
+ if (!(p->pd.name = (char *)malloc(len))) {
+ (void) fprintf(stderr,
+ "%s: no space for cached pseudo path: ", Pn);
+ safestrprt(buf, stderr, 1);
+ Exit(1);
+ }
+ *(cp + len - 1) = '\0';
+ (void) snpf(p->pd.name, len, "%s", cp);
+ p->pd.v = 0;
+ p->next = Pseudo;
+ Pseudo = p;
+ }
+ return(0);
+ } else if (m == 2) {
+
+ /*
+ * Write the pseudo section header.
+ */
+ for (p = Pseudo, n = 0; p; p = p->next, n++)
+ ;
+ (void) snpf(buf, sizeof(buf), "pseudo section: %d\n", n);
+ if (wr2DCfd(buf, &DCcksum))
+ return(1);
+ /*
+ * Write the pseudo section lines.
+ *
+ *
+ * New format pseudo lines (with an inode number) have a leading
+ * space, so that older lsof versions, not expecting them, will
+ * not use the new format lines.
+ */
+ for (p = Pseudo; p; p = p->next) {
+ (void) snpf(buf, sizeof(buf), " %lx %ld %s\n", (long)p->pd.rdev,
+ (long)p->pd.inode, p->pd.name);
+ if (wr2DCfd(buf, &DCcksum))
+ return(1);
+ }
+ return(0);
+ }
+/*
+ * A shouldn't-happen case: mode neither 1 nor 2.
+ */
+ (void) fprintf(stderr, "%s: internal rw_pseudo_sect error: %d\n",
+ Pn, m);
+ return(1);
+}
+
+
+/*
+ * vfy_dev() - verify a device table entry (usually when DCunsafe == 1)
+ *
+ * Note: rereads entire device table when an entry can't be verified.
+ */
+
+int
+vfy_dev(dp)
+ struct l_dev *dp; /* device table pointer */
+{
+ struct stat sb;
+
+ if (!DCunsafe || dp->v)
+ return(1);
+
+#if defined(USE_STAT)
+ if (stat(dp->name, &sb) != 0
+#else /* !defined(USE_STAT) */
+ if (lstat(dp->name, &sb) != 0
+#endif /* defined(USE_STAT) */
+
+ || dp->rdev != sb.st_rdev
+ || dp->inode != (INODETYPE)sb.st_ino) {
+ (void) rereaddev();
+ return(0);
+ }
+ dp->v = 1;
+ return(1);
+}
+#endif /* defined(HASDCACHE) */
+
+
+/*
+ * rmdupdev() - remove duplicate (major/minor/inode) devices
+ */
+
+static int
+rmdupdev(dp, n, ty)
+ struct l_dev ***dp; /* device table pointers address */
+ int n; /* number of pointers */
+ int ty; /* type: 0 = block, 1 = char */
+{
+ struct clone *c, *cp;
+ struct l_dev **d;
+ int i, j, k;
+ struct pseudo *p, *pp;
+
+ for (i = j = 0, d = *dp; i < n ;) {
+ for (k = i + 1; k < n; k++) {
+ if (d[i]->rdev != d[k]->rdev || d[i]->inode != d[k]->inode)
+ break;
+ if (ty == 0)
+ continue;
+ /*
+ * See if we're deleting a duplicate clone device. If so,
+ * delete its clone table entry.
+ */
+ for (c = Clone, cp = (struct clone *)NULL;
+ c;
+ cp = c, c = c->next)
+ {
+ if (c->cd.rdev != d[k]->rdev
+ || c->cd.inode != d[k]->inode
+ || strcmp(c->cd.name, d[k]->name))
+ continue;
+ if (!cp)
+ Clone = c->next;
+ else
+ cp->next = c->next;
+ if (c->cd.name)
+ (void) free((FREE_P *)c->cd.name);
+ (void) free((FREE_P *)c);
+ break;
+ }
+ /*
+ * See if we're deleting a duplicate pseudo device. If so,
+ * delete its pseudo table entry.
+ */
+ for (p = Pseudo, pp = (struct pseudo *)NULL;
+ p;
+ pp = p, p = p->next)
+ {
+ if (p->pd.rdev != d[k]->rdev
+ || p->pd.inode != d[k]->inode
+ || strcmp(p->pd.name, d[k]->name))
+ continue;
+ if (!pp)
+ Pseudo = p->next;
+ else
+ pp->next = p->next;
+ if (p->pd.name)
+ (void) free((FREE_P *)p->pd.name);
+ (void) free((FREE_P *)p);
+ break;
+ }
+ }
+ if (i != j)
+ d[j] = d[i];
+ j++;
+ i = k;
+ }
+ if (n == j)
+ return(n);
+ if (!(*dp = (struct l_dev **)realloc((MALLOC_P *)*dp,
+ (MALLOC_S)(j * sizeof(struct l_dev *)))))
+ {
+ (void) fprintf(stderr, "%s: can't realloc %s device pointers\n",
+ Pn, ty ? "char" : "block");
+ Exit(1);
+ }
+ return(j);
+}
diff --git a/dialects/sun/dfile.c b/dialects/sun/dfile.c
new file mode 100644
index 0000000..bb09306
--- /dev/null
+++ b/dialects/sun/dfile.c
@@ -0,0 +1,669 @@
+/*
+ * dfile.c - Solaris file processing functions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dfile.c,v 1.21 2009/03/25 19:22:16 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+/*
+ * Local structures
+ */
+
+struct hsfile {
+ struct sfile *s; /* the Sfile table address */
+ struct hsfile *next; /* the next hash bucket entry */
+};
+
+
+/*
+ * Local static variables
+ */
+
+static struct hsfile *HbyCd = /* hash by clone buckets */
+ (struct hsfile *)NULL;
+static int HbyCdCt = 0; /* HbyCd entry count */
+static struct hsfile *HbyFdi = /* hash by file buckets */
+ (struct hsfile *)NULL;
+static int HbyFdiCt = 0; /* HbyFdi entry count */
+static struct hsfile *HbyFrd = /* hash by file raw device buckets */
+ (struct hsfile *)NULL;
+static int HbyFrdCt = 0; /* HbyFrd entry count */
+static struct hsfile *HbyFsd = /* hash by file system buckets */
+ (struct hsfile *)NULL;
+static int HbyFsdCt = 0; /* HbyFsd entry count */
+static struct hsfile *HbyNm = /* hash by name buckets */
+ (struct hsfile *)NULL;
+static int HbyNmCt = 0; /* HbyNm entry count */
+
+
+/*
+ * Local definitions
+ */
+
+#define SFCDHASH 1024 /* Sfile hash by clone device */
+#define SFDIHASH 4094 /* Sfile hash by (device,inode) number
+ * pair bucket count (power of 2!) */
+#define SFFSHASH 128 /* Sfile hash by file system device
+ * number bucket count (power of 2!) */
+#define SFHASHDEVINO(maj, min, ino, mod) ((int)(((int)((((int)(maj+1))*((int)((min+1))))+ino)*31415)&(mod-1)))
+ /* hash for Sfile by major device,
+ * minor device, and inode, modulo m
+ * (m must be a power of 2) */
+#define SFNMHASH 4096 /* Sfile hash by name bucket count
+ (power of 2!) */
+#define SFRDHASH 1024 /* Sfile hash by raw device number
+ * bucket count (power of 2!) */
+#define SFHASHRDEVI(maj, min, rmaj, rmin, ino, mod) ((int)(((int)((((int)(maj+1))*((int)((min+1))))+((int)(rmaj+1)*(int)(rmin+1))+ino)*31415)&(mod-1)))
+ /* hash for Sfile by major device,
+ * minor device, major raw device,
+ * minor raw device, and inode, modulo
+ * mod (mod must be a power of 2) */
+
+
+#if solaris<20500
+/*
+ * get_max_fd() - get maximum file descriptor plus one
+ */
+
+int
+get_max_fd()
+{
+ struct rlimit r;
+
+ if (getrlimit(RLIMIT_NOFILE, &r))
+ return(-1);
+ return(r.rlim_cur);
+}
+#endif /* solaris<20500 */
+
+
+/*
+ * hashSfile() - hash Sfile entries for use in is_file_named() searches
+ */
+
+void
+hashSfile()
+{
+ int cmaj, hvc, i;
+ static int hs = 0;
+ struct sfile *s;
+ struct hsfile *sh, *sn;
+/*
+ * Do nothing if there are no file search arguments cached or if the
+ * hashes have already been constructed.
+ */
+ if (!Sfile || hs)
+ return;
+/*
+ * Preset the clone major device for Solaris.
+ */
+ if (HaveCloneMaj) {
+ cmaj = CloneMaj;
+ hvc = 1;
+ } else
+ hvc = 0;
+/*
+ * Allocate hash buckets by clone device, (device,inode), file system device,
+ * and file name.
+ */
+ if (hvc) {
+ if (!(HbyCd = (struct hsfile *)calloc((MALLOC_S)SFCDHASH,
+ sizeof(struct hsfile))))
+ {
+ (void) fprintf(stderr,
+ "%s: can't allocate space for %d clone hash buckets\n",
+ Pn, SFCDHASH);
+ Exit(1);
+ }
+ }
+ if (!(HbyFdi = (struct hsfile *)calloc((MALLOC_S)SFDIHASH,
+ sizeof(struct hsfile))))
+ {
+ (void) fprintf(stderr,
+ "%s: can't allocate space for %d (dev,ino) hash buckets\n",
+ Pn, SFDIHASH);
+ Exit(1);
+ }
+ if (!(HbyFrd = (struct hsfile *)calloc((MALLOC_S)SFRDHASH,
+ sizeof(struct hsfile))))
+ {
+ (void) fprintf(stderr,
+ "%s: can't allocate space for %d rdev hash buckets\n",
+ Pn, SFRDHASH);
+ Exit(1);
+ }
+ if (!(HbyFsd = (struct hsfile *)calloc((MALLOC_S)SFFSHASH,
+ sizeof(struct hsfile))))
+ {
+ (void) fprintf(stderr,
+ "%s: can't allocate space for %d file sys hash buckets\n",
+ Pn, SFFSHASH);
+ Exit(1);
+ }
+ if (!(HbyNm = (struct hsfile *)calloc((MALLOC_S)SFNMHASH,
+ sizeof(struct hsfile))))
+ {
+ (void) fprintf(stderr,
+ "%s: can't allocate space for %d name hash buckets\n",
+ Pn, SFNMHASH);
+ Exit(1);
+ }
+ hs++;
+/*
+ * Scan the Sfile chain, building file, file system, and file name hash
+ * bucket chains.
+ */
+ for (s = Sfile; s; s = s->next) {
+ for (i = 0; i < 4; i++) {
+ if (i == 0) {
+ if (!s->aname)
+ continue;
+ sh = &HbyNm[hashbyname(s->aname, SFNMHASH)];
+ HbyNmCt++;
+ } else if (i == 1) {
+ if (s->type) {
+ sh = &HbyFdi[SFHASHDEVINO(GET_MAJ_DEV(s->dev),
+ GET_MIN_DEV(s->dev),
+ s->i,
+ SFDIHASH)];
+ HbyFdiCt++;
+ } else {
+ sh = &HbyFsd[SFHASHDEVINO(GET_MAJ_DEV(s->dev),
+ GET_MIN_DEV(s->dev),
+ 0,
+ SFFSHASH)];
+ HbyFsdCt++;
+ }
+ } else if (i == 2) {
+ if (s->type
+ && ((s->mode == S_IFCHR) || (s->mode == S_IFBLK)))
+ {
+ sh = &HbyFrd[SFHASHRDEVI(GET_MAJ_DEV(s->dev),
+ GET_MIN_DEV(s->dev),
+ GET_MAJ_DEV(s->rdev),
+ GET_MIN_DEV(s->rdev),
+ s->i,
+ SFRDHASH)];
+ HbyFrdCt++;
+ } else
+ continue;
+ } else {
+ if (!hvc || (GET_MAJ_DEV(s->rdev) != cmaj))
+ continue;
+ sh = &HbyCd[SFHASHDEVINO(0, GET_MIN_DEV(s->rdev), 0,
+ SFCDHASH)];
+ HbyCdCt++;
+ }
+ if (!sh->s) {
+ sh->s = s;
+ sh->next = (struct hsfile *)NULL;
+ continue;
+ } else {
+ if (!(sn = (struct hsfile *)malloc(
+ (MALLOC_S)sizeof(struct hsfile))))
+ {
+ (void) fprintf(stderr,
+ "%s: can't allocate hsfile bucket for: %s\n",
+ Pn, s->aname);
+ Exit(1);
+ }
+ sn->s = s;
+ sn->next = sh->next;
+ sh->next = sn;
+ }
+ }
+ }
+}
+
+
+/*
+ * is_file_named() - is this file named?
+ */
+
+int
+is_file_named(p, nt, vt, ps)
+ char *p; /* path name; NULL = search by device
+ * and inode (from *Lf) */
+ int nt; /* node type -- e.g., N_* */
+ enum vtype vt; /* vnode type */
+ int ps; /* print status: 0 = don't copy name
+ * to Namech */
+{
+ char *ep;
+ int f = 0;
+ struct sfile *s;
+ struct hsfile *sh;
+ size_t sz;
+/*
+ * Check for a path name match, as requested.
+ */
+ if (p && HbyNmCt) {
+ for (sh = &HbyNm[hashbyname(p, SFNMHASH)]; sh; sh = sh->next) {
+ if ((s = sh->s) && strcmp(p, s->aname) == 0) {
+ f = 2;
+ break;
+ }
+ }
+ }
+/*
+ * Check for a Solaris clone file.
+ */
+ if (!f && HbyCdCt && nt == N_STREAM && Lf->dev_def && Lf->rdev_def
+ && (Lf->dev == DevDev))
+ {
+ for (sh = &HbyCd[SFHASHDEVINO(0, GET_MAJ_DEV(Lf->rdev), 0,
+ SFCDHASH)];
+ sh;
+ sh = sh->next)
+ {
+ if ((s = sh->s) && (GET_MAJ_DEV(Lf->rdev)
+ == GET_MIN_DEV(s->rdev)))
+ {
+ f = 1;
+ break;
+ }
+ }
+ }
+/*
+ * Check for a regular file.
+ */
+ if (!f && HbyFdiCt && Lf->dev_def
+ && (Lf->inp_ty == 1 || Lf->inp_ty == 3))
+ {
+ for (sh = &HbyFdi[SFHASHDEVINO(GET_MAJ_DEV(Lf->dev),
+ GET_MIN_DEV(Lf->dev),
+ Lf->inode,
+ SFDIHASH)];
+ sh;
+ sh = sh->next)
+ {
+ if ((s = sh->s) && (Lf->dev == s->dev)
+ && (Lf->inode == s->i)) {
+ f = 1;
+ break;
+ }
+ }
+ }
+/*
+ * Check for a file system match.
+ */
+ if (!f && HbyFsdCt && Lf->dev_def) {
+ for (sh = &HbyFsd[SFHASHDEVINO(GET_MAJ_DEV(Lf->dev),
+ GET_MIN_DEV(Lf->dev), 0, SFFSHASH)];
+ sh;
+ sh = sh->next)
+ {
+ if ((s = sh->s) && Lf->dev == s->dev) {
+ f = 1;
+ break;
+ }
+ }
+ }
+/*
+ * Check for a character or block device match.
+ */
+ if (!f && HbyFrdCt
+ && ((vt = VCHR) || (vt = VBLK))
+ && Lf->dev_def && (Lf->dev == DevDev)
+ && Lf->rdev_def
+ && (Lf->inp_ty == 1 || Lf->inp_ty == 3))
+ {
+ for (sh = &HbyFrd[SFHASHRDEVI(GET_MAJ_DEV(Lf->dev),
+ GET_MIN_DEV(Lf->dev),
+ GET_MAJ_DEV(Lf->rdev),
+ GET_MIN_DEV(Lf->rdev),
+ Lf->inode, SFRDHASH)];
+ sh;
+ sh = sh->next)
+ {
+ if ((s = sh->s) && (s->dev == Lf->dev)
+ && (s->rdev == Lf->rdev) && (s->i == Lf->inode))
+ {
+ f = 1;
+ break;
+ }
+ }
+ }
+/*
+ * Convert the name if a match occurred.
+ */
+ if (f) {
+ if (f == 2) {
+ if (ps)
+ (void) snpf(Namech, Namechl, "%s", p);
+ } else {
+ if (ps && s->type) {
+
+ /*
+ * If the search argument isn't a file system, propagate it
+ * to Namech[]; otherwise, let printname() compose the name.
+ */
+ (void) snpf(Namech, Namechl, "%s", s->name);
+ if (s->devnm) {
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, " (%s)", s->devnm);
+ }
+ }
+ }
+ s->f = 1;
+ return(1);
+ }
+ return(0);
+}
+
+
+#if defined(HASPRINTDEV)
+/*
+ * print_dev() - print device
+ */
+
+char *
+print_dev(lf, dev)
+ struct lfile *lf; /* file whose device is to be printed */
+ dev_t *dev; /* device to be printed */
+{
+ static char buf[128];
+/*
+ * Avoid the Solaris major() and minor() functions from makedev(3C) to get
+ * printable major/minor numbers.
+ *
+ * We would like to use the L_MAXMAJ definition from <sys/sysmacros.h> all
+ * the time, but it's not always correct in all versions of Solaris.
+ */
+ (void) snpf(buf, sizeof(buf), "%d,%d", (int)((*dev >> L_BITSMINOR) &
+
+#if solaris>=20501
+ L_MAXMAJ
+#else /* solaris<20501 */
+ 0x3fff
+#endif /* solaris>=20501 */
+
+ ), (int)(*dev & L_MAXMIN));
+ return(buf);
+}
+#endif /* defined(HASPRINTDEV) */
+
+
+#if defined(HAS_V_PATH)
+
+/*
+ * Local definitions
+ */
+
+#define VPRDLEN ((MAXPATHLEN + 7)/8) /* v_path read length increment */
+
+
+/*
+ * print_v_path() - print path name from vnode's v_path pointer
+ */
+
+extern int
+print_v_path(lf)
+ struct lfile *lf; /* local file structure */
+{
+ char buf[MAXPATHLEN+1];
+ unsigned char del = 0;
+ unsigned char aperr = 0;
+
+# if defined(HASMNTSTAT)
+ struct stat sb;
+# endif /* defined(HASMNTSTAT) */
+
+# if defined(HASVXFS) && defined(HASVXFSRNL)
+ if (lf->is_vxfs && (lf->inp_ty == 1) && lf->fsdir) {
+ if (print_vxfs_rnl_path(lf))
+ return(1);
+ }
+# endif /* defined(HASVXFS) && defined(HASVXFSRNL) */
+
+ (void) read_v_path((KA_T)lf->V_path, buf, (size_t)sizeof(buf));
+ if (buf[0]) {
+
+# if defined(HASMNTSTAT)
+ if (!lf->mnt_stat && lf->dev_def && (lf->inp_ty == 1)) {
+
+ /*
+ * No problem was detected in applying stat(2) to this mount point.
+ * If the device and inode for the file are known, it is probably
+ * safe and worthwhile to apply stat(2) to the v_path.
+ */
+ if (!statsafely(buf, &sb)) {
+
+ /*
+ * The stat(2) succeeded. See if the device and inode match.
+ * If they both don't match, ignore the v_path.
+ */
+ if ((lf->dev != sb.st_dev)
+ || (lf->inode != (INODETYPE)sb.st_ino)
+ ) {
+ return(0);
+ }
+ } else {
+
+ /*
+ * The stat(2) failed.
+ *
+ * If the error reply is ENOENT and the -X option hasn't been
+ * specified, ignore the v_path.
+ *
+ * If the error reply is ENOENT, the -X option has been
+ * specified and the file's link count is zero, report the
+ * v_path with the "(deleted)" notation.
+ *
+ * If the error reply is EACCES or EPERM, report the v_path,
+ * followed by "(?)", because lsof probably lacks permission
+ * to apply stat(2) to v_path.
+ */
+ switch (errno) {
+ case EACCES:
+ case EPERM:
+ aperr = 1;
+ break;
+ case ENOENT:
+
+# if defined(HASXOPT)
+ if (Fxopt && lf->nlink_def && !lf->nlink) {
+ del = 1;
+ break;
+ }
+# endif /* defined(HASXOPT) */
+
+ return(0);
+ default:
+ return(0);
+ }
+ }
+ }
+# endif /* defined(HASMNTSTAT) */
+
+ /*
+ * Print the v_path.
+ */
+ safestrprt(buf, stdout, 0);
+ if (del)
+ safestrprt(" (deleted)", stdout, 0);
+ else if (aperr)
+ safestrprt(" (?)", stdout, 0);
+ return(1);
+ }
+ return(0);
+}
+
+
+/*
+ * read_v_path() - read path name from vnode's v_path pointer
+ */
+
+extern void
+read_v_path(ka, rb, rbl)
+ KA_T ka; /* kernel path address */
+ char *rb; /* receiving buffer */
+ size_t rbl; /* receiving buffer length */
+{
+ char *ba;
+ size_t rl, tl;
+
+ *rb = '\0';
+ if (!ka)
+ return;
+ for (ba = rb, tl = 0;
+ tl < (rbl - 1);
+ ba += rl, ka += (KA_T)((char *)ka + rl), tl += rl
+ ) {
+
+ /*
+ * Read v_path VPRDLEN bytes at a time until the local buffer is full
+ * or a NUL byte is reached.
+ */
+ if ((rl = rbl - 1 - tl) > VPRDLEN)
+ rl = VPRDLEN;
+ else if (rl < 1) {
+ *(rb + rbl - 1) = '\0';
+ break;
+ }
+ if (!kread(ka, ba, rl)) {
+ *(ba + rl) = '\0';
+ if (strchr(ba, '\0') < (ba + rl))
+ break;
+ } else {
+
+ /*
+ * Can't read a full buffer load; try reducing the length one
+ * byte at a time until it reaches zero. Stop here, since it
+ * has been established that no more bytes can be read.
+ */
+ for (rl--; rl > 0; rl--) {
+ if (!kread(ka, ba, rl)) {
+ *(ba + rl) = '\0';
+ break;
+ }
+ }
+ if (rl <= 0)
+ *ba = '\0';
+ break;
+ }
+ }
+}
+#endif /* defined(HAS_V_PATH) */
+
+
+/*
+ * process_file() - process file
+ */
+
+void
+process_file(fp)
+ KA_T fp; /* kernel file structure address */
+{
+ struct file f;
+ int flag;
+
+#if defined(FILEPTR)
+ FILEPTR = &f;
+#endif /* defined(FILEPTR) */
+
+ if (kread(fp, (char *)&f, sizeof(f))) {
+ (void) snpf(Namech, Namechl, "can't read file struct from %s",
+ print_kptr(fp, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ Lf->off = (SZOFFTYPE)f.f_offset;
+
+ if (f.f_count) {
+
+ /*
+ * Construct access code.
+ */
+ if ((flag = (f.f_flag & (FREAD | FWRITE))) == FREAD)
+ Lf->access = 'r';
+ else if (flag == FWRITE)
+ Lf->access = 'w';
+ else if (flag == (FREAD | FWRITE))
+ Lf->access = 'u';
+
+#if defined(HASFSTRUCT)
+ /*
+ * Save file structure values.
+ */
+ if (Fsv & FSV_CT) {
+ Lf->fct = (long)f.f_count;
+ Lf->fsv |= FSV_CT;
+ }
+ if (Fsv & FSV_FA) {
+ Lf->fsa = fp;
+ Lf->fsv |= FSV_FA;
+ }
+ if (Fsv & FSV_FG) {
+ Lf->ffg = (long)f.f_flag;
+ Lf->fsv |= FSV_FG;
+ }
+ if (Fsv & FSV_NI) {
+ Lf->fna = (KA_T)f.f_vnode;
+ Lf->fsv |= FSV_NI;
+ }
+#endif /* defined(HASFSTRUCT) */
+
+ /*
+ * Solaris file structures contain a vnode pointer. Process it.
+ */
+ process_node((KA_T)f.f_vnode);
+ return;
+ }
+ enter_nm("no more information"); }
+
+
+#if defined(HASIPv6)
+/*
+ * gethostbyname2() -- an RFC2133-compatible get-host-by-name-two function
+ * to get AF_INET and AF_INET6 addresses from host names,
+ * using the RFC2553-compatible getipnodebyname() function
+ */
+
+extern struct hostent *
+gethostbyname2(nm, prot)
+ const char *nm; /* host name */
+ int prot; /* protocol -- AF_INET or AF_INET6 */
+{
+ int err;
+ static struct hostent *hep = (struct hostent *)NULL;
+
+ if (hep)
+ (void) freehostent(hep);
+ return((hep = getipnodebyname(nm, prot, 0, &err)));
+}
+#endif /* defined(HASIPv6) */
diff --git a/dialects/sun/dlsof.h b/dialects/sun/dlsof.h
new file mode 100644
index 0000000..1b74eb6
--- /dev/null
+++ b/dialects/sun/dlsof.h
@@ -0,0 +1,690 @@
+/*
+ * dlsof.h - Solaris header file for lsof
+ */
+
+
+/*
+ * Copyright 1994 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.
+ */
+
+
+/*
+ * $Id: dlsof.h,v 1.48 2012/04/10 16:40:23 abe Exp $
+ */
+
+
+#if !defined(SOLARIS_LSOF_H)
+#define SOLARIS_LSOF_H 1
+
+#include <fcntl.h>
+#include <sys/mntent.h>
+#include <sys/mnttab.h>
+
+# if solaris<20600
+#define _KMEMUSER 1
+# else /* solaris>=20600 */
+#include <stddef.h>
+# endif /* solaris<20600 */
+
+#include <stdlib.h>
+#include <dirent.h>
+
+# if defined(HASZONES)
+#define _KERNEL
+#include<sys/zone.h>
+#undef _KERNEL
+# endif /* defined(HASZONES) */
+
+#include <kvm.h>
+#include <nlist.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <string.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <rpc/types.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+
+# if solaris>=110000
+#define _KERNEL
+# endif /* solaris>=110000 */
+
+#include <netinet/in.h>
+
+# if solaris>=110000
+#undef _KERNEL
+# endif /* solaris>=110000 */
+
+
+# if solaris>=70000
+#include <sys/conf.h>
+#include <sys/systeminfo.h>
+# endif /* solaris>=70000 */
+
+#define _KERNEL
+#define MI_HRTIMING
+#include <inet/led.h>
+
+# if solaris<20600
+#undef staticf
+# endif /* solaris<20600 */
+
+#include <inet/common.h>
+
+# if solaris>=70000
+#include <sys/stropts.h>
+# endif /* solaris>=70000 */
+
+# if solaris<20600
+#include <inet/mi.h>
+# endif /* solaris<20600 */
+
+# if solaris>=80000
+#include <netinet/igmp.h>
+#include <netinet/ip6.h>
+# endif /* solaris>=80000 */
+
+# if defined(HAS_IPCLASSIFIER_H)
+#define ffs __kernel_ffs
+#define inet_ntop __inet_ntop
+#define inet_pton __inet_pton
+#define longjmp __kernel_longjmp
+#define setjmp __kernel_setjmp
+# if solaris>=110000
+#define printf __kernel_printf
+#define snprintf __kernel_snprintf
+#define sprintf __kernel_sprintf
+#define strsignal __kernel_strsignal
+#define swab __kernel_swab
+#define vprintf __kernel_vprintf
+#define vsprintf __kernel_vsprintf
+#define vsnprintf __kernel_vsnprintf
+# endif /* solaris>=110000 */
+#include <inet/ipclassifier.h>
+#undef ffs
+#undef inet_ntop
+#undef inet_pton
+#undef longjmp
+#undef setjmp
+# if solaris>=110000
+#undef printf
+#undef snprintf
+#undef sprintf
+#undef strsignal
+#undef swab
+#undef vprintf
+#undef vsprintf
+#undef vsnprintf
+# endif /* solaris>=110000 */
+# endif /* defined(HAS_IPCLASSIFIER_H) */
+
+#include <inet/ip.h>
+#undef _KERNEL
+#undef MI_HRTIMING
+#define exit kernel_exit
+#define rval_t char
+#define strsignal kernel_strsignal
+#include <sys/strsubr.h>
+
+# if defined(HAS_SOCKET_PROTO_H)
+#define _KERNEL 1 /* DEBUG */
+# endif /* HAS_SOCKET_PROTO_H */
+
+#include <sys/socketvar.h>
+
+# if defined(HAS_SOCKET_PROTO_H)
+#undef _KERNEL /* DEBUG */
+# endif /* HAS_SOCKET_PROTO_H */
+
+#undef exit
+#undef rval_t
+#undef strsignal
+
+# if solaris>=80000
+#define _KERNEL 1
+# endif /* solaris>=80000 */
+
+#include <inet/tcp.h>
+
+# if solaris>=80000
+#undef _KERNEL
+# endif /* solaris>=80000 */
+
+#include <net/route.h>
+#include <netinet/in_pcb.h>
+#include <sys/stream.h>
+
+# if solaris<20600
+#undef MAX
+#undef MIN
+# endif /* solaris<20600 */
+
+#include <sys/sysmacros.h>
+#include <sys/vfs.h>
+#include <sys/vnode.h>
+#include <sys/fs/hsfs_spec.h>
+#include <sys/fs/hsfs_node.h>
+#include <sys/fs/lofs_node.h>
+
+# if solaris>=20600
+#define _KERNEL
+# endif /* solaris>=20600 */
+
+#include <sys/fs/namenode.h>
+
+# if solaris>=20600
+#undef _KERNEL
+# endif /* solaris>=20600 */
+
+#include <sys/tihdr.h>
+
+# if solaris>=20500
+#include <sys/tiuser.h>
+#include <rpc/auth.h>
+#include <rpc/clnt.h>
+
+# if solaris>=110000
+#define _KERNEL
+#include <rpc/rpc.h>
+#undef _KERNEL
+# endif /* solaris>=110000 */
+
+#include <rpc/clnt_soc.h>
+#include <rpc/pmap_prot.h>
+#define _KERNEL
+#include <sys/fs/autofs.h>
+
+# if solaris>=100000
+#define printf lsof_printf
+#define snprintf lsof_snprintf
+#define sprintf lsof_sprintf
+#define swab lsof_swab
+#define vprintf lsof_vprintf
+#define vsnprintf lsof_vsnprintf
+#define vsprintf lsof_vsprintf
+#include <sys/fs/dv_node.h>
+#undef printf
+#undef snprintf
+#undef sprintf
+#undef swab
+#undef vprintf
+#undef vsnprintf
+#undef vsprintf
+#include <sys/contract_impl.h>
+#include <sys/ctfs_impl.h>
+#include <sys/port_impl.h>
+# endif /* solaris>=100000 */
+
+#include <sys/door.h>
+#undef _KERNEL
+# endif /* solaris>=20500 */
+
+# if !defined(_NETDB_H_)
+#include <rpc/rpcent.h>
+# endif /* !defined(_NETDB_H_) */
+
+#include <sys/t_lock.h>
+#include <sys/flock.h>
+
+# if solaris>=20300
+# if solaris<20400
+/*
+ * The lock_descriptor structure definition is missing from Solaris 2.3.
+ */
+
+struct lock_descriptor {
+ struct lock_descriptor *prev;
+ struct lock_descriptor *next;
+ struct vnode *vnode;
+ struct owner {
+ pid_t pid;
+ long sysid;
+ } owner;
+ int flags;
+ short type;
+ off_t start;
+ off_t end;
+ struct lock_info {
+ struct active_lock_info {
+ struct lock_descriptor *ali_stack;
+ } li_active;
+ struct sleep_lock_info {
+ struct flock sli_flock;
+ /* Ignore the rest. */
+ } li_sleep;
+ } info;
+};
+#define ACTIVE_LOCK 0x008 /* lock is active */
+# else /* solaris>=20400 */
+#include <sys/flock_impl.h>
+# endif /* solaris<20400 */
+# endif /* solaris>=20300 */
+
+#include <sys/fstyp.h>
+#include <sys/dditypes.h>
+#include <sys/ddidmareq.h>
+#include <sys/ddi_impldefs.h>
+#include <sys/mkdev.h>
+
+# if defined(HASCACHEFS)
+#include <sys/fs/cachefs_fs.h>
+# endif /* defined(HACACHEFS) */
+
+#include <sys/fs/fifonode.h>
+#include <sys/fs/pc_fs.h>
+#include <sys/fs/pc_dir.h>
+#include <sys/fs/pc_label.h>
+#include <sys/fs/pc_node.h>
+
+# if solaris>=20600
+#undef SLOCKED
+# endif /* solaris>=20600 */
+
+#include <sys/fs/snode.h>
+#include <sys/fs/tmpnode.h>
+
+# if solaris>=110000
+#define _KERNEL
+# endif /* solaris>=110000 */
+
+#include <nfs/nfs.h>
+
+# if solaris>=110000
+#undef _KERNEL
+# endif /* solaris>=110000 */
+
+# if solaris>=100000
+#define _KERNEL
+# endif /* solaris >= 100000 */
+
+#include <nfs/rnode.h>
+
+# if solaris>=100000
+#include <nfs/mount.h>
+#include <nfs/nfs4.h>
+#include <nfs/rnode4.h>
+# endif /* solaris>=100000 */
+
+# if solaris>=100000
+#undef _KERNEL
+# endif /* solaris >= 100000 */
+
+#include <sys/proc.h>
+#include <sys/user.h>
+
+# if defined(HASPROCFS)
+#include <sys/proc/prdata.h>
+# endif /* defined(HASPROCFS) */
+
+#include <sys/file.h>
+#include <vm/hat.h>
+#include <vm/as.h>
+#include <vm/seg.h>
+#include <vm/seg_dev.h>
+#include <vm/seg_map.h>
+#include <vm/seg_vn.h>
+#include <sys/tiuser.h>
+#include <sys/t_kuser.h>
+
+# if solaris<100000
+#include <sys/sockmod.h>
+# endif /* solaris<100000 */
+
+/*
+ * Structure for Atria's MVFS nodes
+ */
+
+struct mvfsnode {
+ unsigned long d1[6];
+ unsigned long m_ino; /* node number */
+};
+
+extern int nlist();
+
+# if defined(HAS_AFS) && !defined(AFSAPATHDEF)
+#define AFSAPATHDEF "/usr/vice/etc/modload/libafs"
+# endif /* defined(HAS_AFS) && !defined(AFSAPATHDEF) */
+
+#define ALLKMEM "/dev/allkmem"
+#define COMP_P const void
+#define CWDLEN (MAXPATHLEN+1)
+#define DEVINCR 1024 /* device table malloc() increment */
+#define DINAMEL 32
+#define DIRTYPE dirent
+
+# if solaris>=100000
+#define GET_MAJ_DEV(d) ((major_t)(d >> L_BITSMINOR & L_MAXMAJ))
+#define GET_MIN_DEV(d) ((minor_t)(d & L_MAXMIN))
+# endif /* solaris >= 100000 */
+
+# if solaris>=70000
+typedef uintptr_t KA_T;
+# else /* solaris<70000 */
+typedef void * KA_T;
+# endif /* solaris>=70000 */
+
+# if solaris>=70000
+#define KA_T_FMT_X "0x%p"
+# endif /* solaris>=70000 */
+
+# if solaris>=20501
+#define KMEM "/dev/mem"
+# else /* solaris<20501 */
+#define KMEM "/dev/kmem"
+# endif /* solaris>=20501 */
+
+#define MALLOC_P char
+#define FREE_P MALLOC_P
+#define MALLOC_S unsigned
+
+# if !defined(MAXEND)
+#define MAXEND 0x7fffffff
+# endif /* !defined(MAXEND) */
+
+#define MAXSEGS 100 /* maximum text segments */
+#define MAXSYSCMDL MAXCOMLEN /* max system command name length */
+#define NETCLNML 8
+#define N_UNIX "/dev/ksyms"
+#define PROCMIN 5 /* processes that make a "good" scan */
+
+# if defined(HASPROCFS)
+#define PR_ROOTINO 2 /* root inode for proc file system */
+# endif /* defined(HASPROCFS) */
+
+#define PROCDFLT 256 /* default size for local proc table --
+ * MUST BE > 4!!! */
+#define PROCSIZE sizeof(struct proc)
+#define PROCTRYLM 5 /* times to try to read proc table */
+#define QSORT_P char
+#define READLEN_T int
+#define STRNCPY_L int
+#define STRNML 32 /* stream name length (maximum) */
+
+# if solaris>=20501
+/*
+ * Enable large file support.
+ */
+
+# if solaris>=20600
+#define fstat fstat64
+#define lstat lstat64
+#define stat stat64
+# endif /* solaris>=20600 */
+
+#define SZOFFTYPE unsigned long long
+ /* size and offset internal storage
+ * type */
+#define SZOFFPSPEC "ll" /* SZOFFTYPE printf specification
+ * modifier */
+# endif /* solaris>=20501 */
+
+#define U_SIZE sizeof(struct user)
+
+
+/*
+ * Global storage definitions (including their structure definitions)
+ */
+
+# if defined(HAS_AFS)
+
+# if defined(HASAOPT)
+extern char *AFSApath; /* alternate AFS name list path
+ * (from -a) */
+# endif /* defined(HASAOPT) */
+
+extern dev_t AFSdev; /* AFS file system device number */
+extern int AFSdevStat; /* AFS file system device number
+ * status: 0 = unknown; 1 = known */
+extern int AFSfstype; /* AFS file system type index */
+extern KA_T AFSVfsp; /* AFS struct vfs kernel pointer */
+# endif /* defined(HAS_AFS) */
+
+struct clone {
+ struct l_dev cd; /* device, inode, name, and verify */
+ int n; /* network flag */
+ struct clone *next; /* forward link */
+};
+extern struct clone *Clone;
+
+extern major_t CloneMaj;
+
+# if defined(HAS_LIBCTF)
+/*
+ * Definitions for using the CTF library, libctf.
+ */
+
+#include <libctf.h>
+
+#define CTF_MEMBER_UNDEF ~0UL /* undefined member type */
+ /* CTF_member_t element definition */
+
+/*
+ * Member structure definition, initialized by CTF_MEMBER() macro calls
+ */
+
+typedef struct CTF_member {
+ char *m_name; /* Member name. */
+ ulong_t m_offset; /* Member offset, initially in bits,
+ * later bytes */
+} CTF_member_t;
+
+
+/*
+ * CTF request structure
+ */
+
+typedef struct CTF_request {
+ char *name; /* structure name */
+ CTF_member_t *mem; /* member table */
+} CTF_request_t;
+
+
+/*
+ * CTF macroes
+ */
+
+#define CTF_MEMBER(name) { #name, CTF_MEMBER_UNDEF }
+#define CTF_MEMBER_READ(ka, s, members, member) \
+ kread((KA_T)(ka) + members[MX_ ## member].m_offset, \
+ (char *)&s->member, sizeof(s->member))
+# endif /* defined(HAS_LIBCTF) */
+
+extern char **Fsinfo;
+extern int Fsinfomax;
+extern int HasALLKMEM;
+extern int HaveCloneMaj;
+extern kvm_t *Kd;
+
+struct l_ino {
+ unsigned char dev_def; /* dev member is defined */
+ unsigned char ino_def; /* ino member is defined */
+ unsigned char nl_def; /* nl member is defined */
+ unsigned char rdev_def; /* rdev member is defined */
+ unsigned char sz_def; /* sz member is defined */
+ dev_t dev; /* device */
+ long ino; /* node number */
+ long nl; /* link count */
+ dev_t rdev; /* "raw" device */
+ SZOFFTYPE sz; /* size */
+};
+
+struct l_vfs {
+ KA_T addr; /* kernel address */
+ char *dir; /* mounted directory */
+ char *fsname; /* file system name */
+ dev_t dev; /* device */
+
+# if defined(HASFSINO)
+ INODETYPE fs_ino; /* file system inode number */
+# endif /* defined(HASFSINO) */
+
+# if defined(HASMNTSTAT)
+ unsigned char mnt_stat; /* mount point stat() status:
+ * 0 = succeeded
+ * 1 = failed */
+# endif /* defined(HASMNTSTAT) */
+
+
+# if solaris>=80000
+ nlink_t nlink; /* directory link count */
+ off_t size; /* directory size */
+# endif /* solaris>=80000 */
+
+ struct l_vfs *next; /* forward link */
+};
+extern struct l_vfs *Lvfs;
+
+struct mounts {
+ char *dir; /* directory (mounted on) */
+ char *fsname; /* file system
+ * (symbolic links unresolved) */
+ char *fsnmres; /* file system
+ * (symbolic links resolved) */
+ dev_t dev; /* directory st_dev */
+ dev_t rdev; /* directory st_rdev */
+ INODETYPE inode; /* directory st_ino */
+ mode_t mode; /* directory st_mode */
+ mode_t fs_mode; /* file system st_mode */
+ struct mounts *next; /* forward link */
+
+# if defined(HASFSTYPE)
+ char *fstype; /* file system type */
+# endif /* defined(HASFSTYPE) */
+
+# if solaris>=80000
+ nlink_t nlink; /* directory st_nlink */
+ off_t size; /* directory st_size */
+# endif /* solaris>=80000 */
+
+# if defined(HASMNTSTAT)
+ unsigned char stat; /* mount point stat() status:
+ * 0 = succeeded
+ * 1 = failed */
+# endif /* defined(HASMNTSTAT) */
+
+};
+
+struct pseudo {
+ struct l_dev pd; /* device, inode, path, verify */
+ struct pseudo *next; /* forward link */
+};
+extern struct pseudo *Pseudo;
+
+
+/*
+ * Solaris 11 sdev definitions
+ */
+
+#define SDVOP_IP 0 /* Sdev[] devipnet_vnodeops index */
+#define SDVOP_NET 1 /* Sdev[] devnet_vnodeops index */
+#define SDVOP_PTS 2 /* Sdev[] devpts_vnodeops index */
+#define SDVOP_VT 3 /* Sdev[] devvt_vnodeops index */
+#define SDVOP_NUM 4 /* number of Sdev[] entries */
+
+
+struct sfile {
+ char *aname; /* file name argument */
+ char *name; /* file name (after readlink()) */
+ char *devnm; /* device name (optional) */
+ dev_t dev; /* device */
+ dev_t rdev; /* raw device */
+ u_short mode; /* S_IFMT mode bits from stat() */
+ int type; /* file type: 0 = file system
+ * 1 = regular file */
+ INODETYPE i; /* inode number */
+ int f; /* file found flag */
+ struct sfile *next; /* forward link */
+};
+extern int Unof; /* u_nofiles value */
+
+
+/*
+ * VxFS definitions
+ */
+
+#define VXVOP_FCL 0 /* Vvops[] vx_fcl_vnodeops_p index */
+#define VXVOP_FDD 1 /* Vvops[] fdd_vnops index */
+#define VXVOP_FDDCH 2 /* Vvops[] fdd_chain_vnops index */
+#define VXVOP_REG 3 /* Vvops[] vx_vnodeops index */
+#define VXVOP_REG_P 4 /* Vvops[] vx_vnodeops_p index */
+#define VXVOP_NUM 5 /* number of Vvops[] entries */
+
+
+/*
+ * Kernel name list definitions
+ */
+
+#define NL_NAME n_name
+#define X_NCACHE "ncache"
+#define X_NCSIZE "ncsize"
+
+
+/*
+ * Definitions for dvch.c
+ */
+
+# if defined(HASDCACHE)
+#define DCACHE_CLONE rw_clone_sect /* clone function for read_dcache */
+#define DCACHE_CLR clr_sect /* function to clear clone and
+ * pseudo caches when reading the
+ * device cache file fails */
+#define DCACHE_PSEUDO rw_pseudo_sect /* pseudo function for read_dcache */
+# endif /* defined(HASDCACHE) */
+
+#define DVCH_DEVPATH "/devices"
+
+
+/*
+ * Definition for cvfs.c
+ */
+
+#define CVFS_DEVSAVE 1
+
+# if solaris>=80000
+#define CVFS_NLKSAVE 1
+#define CVFS_SZSAVE 1
+# endif /* solaris>=80000 */
+
+
+/*
+ * Definitions for rnch.c
+ */
+
+# if defined(HASNCACHE)
+#include <sys/dnlc.h>
+
+# if !defined(NC_NAMLEN)
+#define HASDNLCPTR 1
+# endif /* !defined(NC_NAMLEN) */
+
+# if solaris>=80000
+#define NCACHE_NEGVN "negative_cache_vnode"
+# endif /* solaris>=80000 */
+# endif /* defined(HASNCACHE) */
+
+#endif /* SOLARIS_LSOF_H */
diff --git a/dialects/sun/dmnt.c b/dialects/sun/dmnt.c
new file mode 100644
index 0000000..c9c023c
--- /dev/null
+++ b/dialects/sun/dmnt.c
@@ -0,0 +1,417 @@
+/*
+ * dmnt.c - Solaris mount support functions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dmnt.c,v 1.15 2005/08/29 10:24:25 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+/*
+ * Local static definitions
+ */
+
+static struct mounts *Lmi = (struct mounts *)NULL; /* local mount info */
+static int Lmist = 0; /* Lmi status */
+
+
+_PROTOTYPE(static char *getmntdev,(char *o, int l, struct stat *s, char *f));
+
+
+/*
+ * getmntdev() - get mount entry's device number
+ */
+
+static char *
+getmntdev(o, l, s, f)
+ char *o; /* start of device option */
+ int l; /* length of device keyword (not
+ * including `=') */
+ struct stat *s; /* pointer to stat buffer to create */
+ char *f; /* file system type */
+{
+ char *opte;
+
+ memset((char *)s, 0, sizeof(struct stat));
+ if (!(opte = x2dev(o + l + 1, &s->st_dev)))
+ return((char *)NULL);
+
+#if solaris>=70000 && L_BITSMAJOR!=L_BITSMAJOR32
+/*
+ * If this is a Solaris 7 system with a 64 bit kernel, convert the 32 bit
+ * device number to a 64 bit device number.
+ */
+ s->st_dev = (((s->st_dev >> L_BITSMINOR32) & L_MAXMAJ32) << L_BITSMINOR)
+ | (s->st_dev & L_MAXMIN32);
+#endif /* solaris>=70000 && L_BITSMAJOR!=L_BITSMAJOR32 */
+
+ s->st_mode = S_IFDIR | 0777;
+
+#if defined(HASFSTYPE)
+ if (f) {
+ (void) strncpy(s->st_fstype, f, sizeof(s->st_fstype));
+ s->st_fstype[sizeof(s->st_fstype) - 1] = '\0';
+ }
+#endif /* defined(HASFSTYPE) */
+
+ return(opte);
+}
+
+
+/*
+ * readmnt() - read mount table
+ */
+
+struct mounts *
+readmnt()
+{
+ int devl, ignore;
+ char *cp, *dir, *fs;
+ char *dn = (char *)NULL;
+ char *ln;
+ FILE *mfp;
+ struct mounts *mtp;
+ char *dopt, *dopte;
+ struct stat sb;
+ struct mnttab me;
+ struct mnttab *mp;
+
+#if defined(HASPROCFS)
+ int procfs = 0;
+#endif /* defined(HASPROCFS) */
+
+ unsigned char stat;
+ char *zopt;
+
+#if defined(HASZONES)
+ int zwarn = 0;
+#endif /* definesd(HASZONES) */
+
+ if (Lmi || Lmist)
+ return(Lmi);
+ devl = strlen(MNTOPT_DEV);
+/*
+ * Open access to the mount table and read mount table entries.
+ */
+ if (!(mfp = fopen(MNTTAB, "r"))) {
+ (void) fprintf(stderr, "%s: can't access %s\n", Pn, MNTTAB);
+ return(0);
+ }
+ for (mp = &me; getmntent(mfp, mp) == 0;) {
+
+ /*
+ * Skip loop-back mounts, since they are aliases for legitimate file
+ * systems and there is no way to determine that a vnode refers to a
+ * loop-back alias.
+ */
+ if (strcmp(mp->mnt_fstype, MNTTYPE_LO) == 0)
+ continue;
+ /*
+ * Save pointers to the directory and file system names for later use.
+ *
+ * Check the file system name. If it doesn't begin with a `/'
+ * but contains a `:' not followed by a '/', ignore this entry.
+ */
+ dir = mp->mnt_mountp;
+ fs = mp->mnt_special;
+ if (*fs != '/' && (cp = strchr(fs, ':')) && *(cp+1) != '/')
+ continue;
+ /*
+ * Check for a "ignore" type (SunOS) or "ignore" option (Solaris).
+ */
+ if (hasmntopt(mp, MNTOPT_IGNORE))
+ ignore = 1;
+ else
+ ignore = 0;
+ /*
+ * Interpolate a possible symbolic directory link.
+ */
+ if (dn)
+ (void) free((FREE_P *)dn);
+ if (!(dn = mkstrcpy(dir, (MALLOC_S *)NULL))) {
+
+no_space_for_mount:
+
+ (void) fprintf(stderr, "%s: no space for mount ", Pn);
+ safestrprt(fs, stderr, 0);
+ (void) fprintf(stderr, " (");
+ safestrprt(dir, stderr, 0);
+ (void) fprintf(stderr, ")\n");
+ Exit(1);
+ }
+ if (!(ln = Readlink(dn))) {
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ " Output information may be incomplete.\n");
+ }
+ continue;
+ }
+ if (ln != dn) {
+ (void) free((FREE_P *)dn);
+ dn = ln;
+ }
+ if (*dn != '/')
+ continue;
+ /*
+ * Stat() the directory.
+ *
+ * Avoid the stat() if the mount entry has an "ignore" option and
+ * try to use the mount entry's device number instead.
+ */
+ dopt = hasmntopt(mp, MNTOPT_DEV);
+ if (ignore) {
+ if (!dopt
+ || !(dopte = getmntdev(dopt, devl, &sb,
+
+#if defined(HASFSTYPE)
+ mp->mnt_fstype
+#else /* !defined(HASFSTYPE) */
+ (char *)NULL
+#endif /* defined(HASFSTYPE) */
+
+ ))
+ )
+ continue;
+ stat = 1;
+ } else if (statsafely(dn, &sb)) {
+ if (dopt) {
+ if (!(dopte = getmntdev(dopt, devl, &sb,
+
+#if defined(HASFSTYPE)
+ mp->mnt_fstype
+#else /* !defined(HASFSTYPE) */
+ (char *)NULL
+#endif /* defined(HASFSTYPE) */
+
+ ))
+ )
+ dopt = (char *)NULL;
+ } else
+ dopte = (char *)NULL;
+ if (!Fwarn) {
+
+#if defined(HASZONES)
+ if ((zopt = hasmntopt(mp, "zone")) && dopte)
+ zwarn++;
+#else /* !defined(HASZONES) */
+ zopt = (char *)NULL;
+#endif /* defined(HASZONES) */
+
+ if (!zopt || !dopte) {
+ (void) fprintf(stderr,
+ "%s: WARNING: can't stat() ", Pn);
+ safestrprt(mp->mnt_fstype, stderr, 0);
+ (void) fprintf(stderr, " file system ");
+ safestrprt(dir, stderr, 1);
+ (void) fprintf(stderr,
+ " Output information may be incomplete.\n");
+ if (dopte) {
+ (void) fprintf(stderr,
+ " assuming \"%.*s\" from %s\n",
+ (int)(dopte - dopt), dopt, MNTTAB);
+ }
+ }
+ }
+ if (!dopt)
+ continue;
+ stat = 1;
+ } else
+ stat = 0;
+ /*
+ * Allocate and fill a local mount structure.
+ */
+ if (!(mtp = (struct mounts *)malloc(sizeof(struct mounts))))
+ goto no_space_for_mount;
+
+#if defined(HASFSTYPE)
+ if (!(mtp->fstype = mkstrcpy(sb.st_fstype, (MALLOC_S *)NULL)))
+ goto no_space_for_mount;
+#endif /* defined(HASFSTYPE) */
+
+ mtp->dir = dn;
+ dn = (char *)NULL;
+ mtp->next = Lmi;
+ mtp->dev = sb.st_dev;
+ mtp->rdev = sb.st_rdev;
+ mtp->inode = (INODETYPE)sb.st_ino;
+ mtp->mode = sb.st_mode;
+
+#if solaris>=80000
+ mtp->nlink = sb.st_nlink;
+ mtp->size = sb.st_size;
+#endif /* solaris>=80000 */
+
+#if defined(HASMNTSTAT)
+ mtp->stat = stat;
+#endif /* defined(HASMNTSTAT) */
+
+#if defined(HASPROCFS)
+ if (strcmp(sb.st_fstype, HASPROCFS) == 0) {
+
+ /*
+ * Save information on exactly one proc file system.
+ */
+ if (procfs)
+ Mtprocfs = (struct mounts *)NULL;
+ else {
+ procfs = 1;
+ Mtprocfs = mtp;
+ }
+ }
+#endif /* defined(HASPROCFS) */
+
+ /*
+ * Interpolate a possible file system (mounted-on) device name link.
+ */
+ if (!(dn = mkstrcpy(fs, (MALLOC_S *)NULL)))
+ goto no_space_for_mount;
+ mtp->fsname = dn;
+ ln = Readlink(dn);
+ dn = (char *)NULL;
+ /*
+ * Stat() the file system (mounted-on) name and add file system
+ * information to the local mount table entry.
+ */
+ if (!ln || statsafely(ln, &sb))
+ sb.st_mode = 0;
+ mtp->fsnmres = ln;
+ mtp->fs_mode = sb.st_mode;
+ Lmi = mtp;
+
+#if defined(HAS_AFS)
+ /*
+ * If an AFS device number hasn't yet been defined, look for it.
+ */
+ if (!AFSdevStat
+ && mtp->dir && strcmp(mtp->dir, "/afs") == 0
+ && mtp->fsname && strcmp(mtp->fsname, "AFS") == 0) {
+ AFSdev = mtp->dev;
+ AFSdevStat = 1;
+ }
+#endif /* defined(HAS_AFS) && solaris>=20600 */
+
+ }
+ (void) fclose(mfp);
+
+#if defined(HASZONES)
+/*
+ * If some zone file systems were encountered, issue a warning.
+ */
+ if (!Fwarn && zwarn) {
+ (void) fprintf(stderr,
+ "%s: WARNING: can't stat() %d zone file system%s", Pn, zwarn,
+ (zwarn == 1) ? "" : "s");
+ (void) fprintf(stderr, "; using dev= option%s\n",
+ (zwarn == 1) ? "" : "s");
+ }
+#endif /* defined(HASZONES) */
+
+/*
+ * Clean up and return local mount info table address.
+ */
+ if (dn)
+ (void) free((FREE_P *)dn);
+ Lmist = 1;
+ return(Lmi);
+}
+
+
+/*
+ * readvfs() - read vfs structure
+ */
+
+struct l_vfs *
+readvfs(ka, la, lv)
+ KA_T ka; /* vfs structure kernel address, if
+ * must be read from kernel */
+ struct vfs *la; /* local vfs structure address, non-
+ * NULL if already read from kernel */
+ struct vnode *lv; /* local vnode */
+{
+ struct vfs *v, tv;
+ struct l_vfs *vp;
+
+ if (!ka && !la)
+ return((struct l_vfs *)NULL);
+ for (vp = Lvfs; vp; vp = vp->next) {
+ if (ka == vp->addr)
+ return(vp);
+ }
+ if (!(vp = (struct l_vfs *)malloc(sizeof(struct l_vfs)))) {
+ (void) fprintf(stderr, "%s: PID %d, no space for vfs\n",
+ Pn, Lp->pid);
+ Exit(1);
+ }
+ vp->dir = (char *)NULL;
+ vp->fsname = (char *)NULL;
+
+#if defined(HASFSINO)
+ vp->fs_ino = 0;
+#endif /* defined(HASFSINO) */
+
+/*
+ * Read vfs structure from kernel, if necessary.
+ */
+ if (la)
+ v = la;
+ else {
+ v = &tv;
+ if (kread((KA_T)ka, (char *)v, sizeof(tv))) {
+ (void) free((FREE_P *)vp);
+ return((struct l_vfs *)NULL);
+ }
+ }
+
+#if defined(HAS_AFS)
+/*
+ * Fake the device number for an AFS device.
+ */
+ if (v->vfs_fstype == AFSfstype) {
+ if (!AFSdevStat)
+ (void) readmnt();
+ v->vfs_dev = AFSdevStat ? AFSdev : 0;
+ }
+#endif /* defined(HAS_AFS) */
+
+/*
+ * Complete mount information.
+ */
+
+ (void) completevfs(vp, (dev_t *)&v->vfs_dev);
+ vp->next = Lvfs;
+ vp->addr = ka;
+ Lvfs = vp;
+ return(vp);
+}
diff --git a/dialects/sun/dnode.c b/dialects/sun/dnode.c
new file mode 100644
index 0000000..0b98e88
--- /dev/null
+++ b/dialects/sun/dnode.c
@@ -0,0 +1,5509 @@
+/*
+ * dnode.c - Solaris node reading functions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dnode.c,v 1.60 2014/10/13 22:24:09 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+#if solaris>=110000
+#include <sys/fs/sdev_impl.h>
+#endif /* solaris>=110000 */
+
+#undef fs_bsize
+#include <sys/fs/ufs_inode.h>
+
+
+#if solaris>=110000 && defined(HAS_LIBCTF)
+/*
+ * Sockfs support for Solaris 11 via libctf
+ */
+
+
+/*
+ * Sockfs internal structure definitions
+ *
+ * The structure definitions may look like kernel structures, but they are
+ * not. They have been defined to have member names that duplicate those
+ * used by the kernel that are of interest to lsof. Member values are
+ * obtained via the CTF library, libctf.
+ *
+ * Robert Byrnes developed the CTF library access code and contributed it
+ * to lsof.
+ */
+
+struct soaddr { /* sadly, CTF doesn't grok this
+ * structure */
+ struct sockaddr *soa_sa; /* address */
+ t_uscalar_t soa_len; /* length in bytes */
+ t_uscalar_t soa_maxlen; /* maximum length */
+};
+
+typedef struct sotpi_info {
+ dev_t sti_dev; /* sonode device */
+ struct soaddr sti_laddr; /* local address */
+ struct soaddr sti_faddr; /* peer address */
+ struct so_ux_addr sti_ux_laddr; /* bound local address */
+ struct so_ux_addr sti_ux_faddr; /* bound peer address */
+ t_scalar_t sti_serv_type; /* service type */
+} sotpi_info_t;
+
+
+/*
+ * CTF definitions for sockfs
+ */
+
+static int Sockfs_ctfs = 0; /* CTF initialization status for
+ * sockfs */
+
+# if defined(_LP64)
+#define SOCKFS_MOD_FORMAT "/kernel/fs/%s/sockfs"
+# else /* !defined(_LP64) */
+#define SOCKFS_MOD_FORMAT "/kernel/fs/sockfs"
+# endif /* defined(_LP64) */
+
+ /* sockfs module pathname template to
+ * which the kernel's instruction type
+ * set is added for CTF access */
+
+
+/*
+ * Sockfs access definitions and structures
+ */
+
+#define SOADDR_TYPE_NAME "soaddr"
+
+static CTF_member_t soaddr_members[] = {
+ CTF_MEMBER(soa_sa),
+#define MX_soa_sa 0
+
+ CTF_MEMBER(soa_len),
+#define MX_soa_len 1
+
+ CTF_MEMBER(soa_maxlen),
+#define MX_soa_maxlen 2
+
+ { NULL, 0 }
+};
+
+
+#define SOTPI_INFO_TYPE_NAME "sotpi_info_t"
+
+static CTF_member_t sotpi_info_members[] = {
+ CTF_MEMBER(sti_dev),
+#define MX_sti_dev 0
+
+ CTF_MEMBER(sti_laddr),
+#define MX_sti_laddr 1
+
+ CTF_MEMBER(sti_faddr),
+#define MX_sti_faddr 2
+
+ CTF_MEMBER(sti_ux_laddr),
+#define MX_sti_ux_laddr 3
+
+ CTF_MEMBER(sti_ux_faddr),
+#define MX_sti_ux_faddr 4
+
+ CTF_MEMBER(sti_serv_type),
+#define MX_sti_serv_type 5
+
+ { NULL, 0 }
+};
+
+
+/*
+ * CTF sockfs request table
+ */
+
+static CTF_request_t Sockfs_requests[] = {
+ { SOTPI_INFO_TYPE_NAME, sotpi_info_members },
+ { NULL, NULL }
+};
+
+
+/*
+ * Sockfs function prototypes
+ */
+
+_PROTOTYPE(static int read_nsti,(struct sonode *so, sotpi_info_t *stpi));
+#endif /* solaris>=110000 && defined(HAS_LIBCTF) */
+
+
+#if defined(HAS_ZFS) && defined(HAS_LIBCTF)
+/*
+ * ZFS support via libctf
+ */
+
+
+/*
+ * ZFS internal structure definitions
+ *
+ * The structure definitions may look like kernel structures, but they are
+ * not. They have been defined to have member names that duplicate those
+ * used by the kernel that are of interest to lsof. Member values are
+ * obtained via the CTF library, libctf.
+ *
+ * Robert Byrnes developed the CTF library access code and contributed it
+ * to lsof.
+ */
+
+typedef struct zfsvfs {
+ vfs_t *z_vfs; /* pointer to VFS */
+} zfsvfs_t;
+
+typedef struct znode_phys {
+ uint64_t zp_size; /* file size (ZFS below 5) */
+ uint64_t zp_links; /* links (ZFS below 5) */
+} znode_phys_t;
+
+typedef struct znode {
+ zfsvfs_t *z_zfsvfs; /* pointer to associated vfs */
+ vnode_t *z_vnode; /* pointer to associated vnode */
+ uint64_t z_id; /* node ID */
+ znode_phys_t *z_phys; /* pointer to persistent znode (ZFS
+ * below 5) */
+ uint64_t z_links; /* links (ZFS 5 and above) */
+ uint64_t z_size; /* file size (ZFS 5 and above) */
+} znode_t;
+
+
+/*
+ * CTF definitions for ZFS
+ */
+
+static int ZFS_ctfs = 0; /* CTF initialization status for ZFS */
+
+# if defined(_LP64)
+#define ZFS_MOD_FORMAT "/kernel/fs/%s/zfs"
+# else /* !defined(_LP64) */
+#define ZFS_MOD_FORMAT "/kernel/fs/zfs"
+# endif /* defined(_LP64) */
+
+ /* ZFS module pathname template to
+ * which the kernel's instruction type
+ * set is added for CTF access */
+
+/*
+ * ZFS access definitions and structures
+ */
+
+#define ZNODE_TYPE_NAME "znode_t"
+
+static CTF_member_t znode_members[] = {
+ CTF_MEMBER(z_zfsvfs),
+#define MX_z_zfsvfs 0
+
+ CTF_MEMBER(z_vnode),
+#define MX_z_vnode 1
+
+ CTF_MEMBER(z_id),
+#define MX_z_id 2
+
+ CTF_MEMBER(z_link_node),
+#define MX_z_link_node 3
+
+ CTF_MEMBER(z_phys),
+#define MX_z_phys 4
+
+ CTF_MEMBER(z_links),
+#define MX_z_links 5
+
+ CTF_MEMBER(z_size),
+#define MX_z_size 6
+
+ { NULL, 0 }
+};
+
+
+#define ZNODE_PHYS_TYPE_NAME "znode_phys_t"
+
+static CTF_member_t znode_phys_members[] = {
+ CTF_MEMBER(zp_size),
+#define MX_zp_size 0
+
+ CTF_MEMBER(zp_links),
+#define MX_zp_links 1
+
+ { NULL, 0 }
+};
+
+
+#define ZFSVFS_TYPE_NAME "zfsvfs_t"
+
+static CTF_member_t zfsvfs_members[] = {
+ CTF_MEMBER(z_vfs),
+#define MX_z_vfs 0
+
+ { NULL, 0 }
+};
+
+
+/*
+ * CTF ZFS request table
+ */
+
+static CTF_request_t ZFS_requests[] = {
+ { ZNODE_TYPE_NAME, znode_members },
+ { ZNODE_PHYS_TYPE_NAME, znode_phys_members },
+ { ZFSVFS_TYPE_NAME, zfsvfs_members },
+ { NULL, NULL }
+};
+
+
+/*
+ * Missing members exceptions -- i.e., CTF_getmem won't consider it
+ * an error if any of these members are undefined.
+ */
+
+typedef struct CTF_exception {
+ char *tynm; /* type name */
+ char *memnm; /* member name */
+} CTF_exception_t;
+
+static CTF_exception_t CTF_exceptions[] = {
+ { ZNODE_TYPE_NAME, "z_phys" },
+ { ZNODE_TYPE_NAME, "z_links" },
+ { ZNODE_TYPE_NAME, "z_size" },
+ { NULL, NULL }
+};
+
+
+/*
+ * ZFS function prototypes
+ */
+
+_PROTOTYPE(static int read_nzn,(KA_T na, KA_T nza, znode_t *z));
+_PROTOTYPE(static int read_nznp,(KA_T nza, KA_T nzpa, znode_phys_t *zp));
+_PROTOTYPE(static int read_nzvfs,(KA_T nza, KA_T nzva, zfsvfs_t *zv));
+#endif /* defined(HAS_ZFS) && defined(HAS_LIBCTF) */
+
+
+_PROTOTYPE(static struct l_dev *finddev,(dev_t *dev, dev_t *rdev, int flags));
+
+
+/*
+ * Finddev() "look-in " flags
+ */
+
+#define LOOKDEV_TAB 0x01 /* look in device table */
+#define LOOKDEV_CLONE 0x02 /* look in Clone table */
+#define LOOKDEV_PSEUDO 0x04 /* look in Pseudo table */
+#define LOOKDEV_ALL (LOOKDEV_TAB | LOOKDEV_CLONE | LOOKDEV_PSEUDO)
+ /* look all places */
+
+
+/*
+ * SAM-FS definitions
+ */
+
+#define SAMFS_NMA_MSG "(limited SAM-FS info)"
+
+
+/*
+ * Voptab definitions
+ */
+
+typedef struct build_v_optab {
+ char *dnm; /* drive_NL name */
+ char *fsys; /* file system type name */
+ int nty; /* node type index (i.e., N_*) */
+} build_v_optab_t;
+
+static build_v_optab_t Build_v_optab[] = {
+ { "auvops", "autofs", N_AUTO },
+ { "avops", "afs", N_AFS },
+ { "afsops", "afs", N_AFS },
+ { "ctfsadir", NULL, N_CTFSADIR },
+ { "ctfsbund", NULL, N_CTFSBUND },
+ { "ctfscdir", NULL, N_CTFSCDIR },
+ { "ctfsctl", NULL, N_CTFSCTL },
+ { "ctfsevt", NULL, N_CTFSEVT },
+ { "ctfslate", NULL, N_CTFSLATE },
+ { "ctfsroot", NULL, N_CTFSROOT },
+ { "ctfsstat", NULL, N_CTFSSTAT },
+ { "ctfssym", NULL, N_CTFSSYM },
+ { "ctfstdir", NULL, N_CTFSTDIR },
+ { "ctfstmpl", NULL, N_CTFSTMPL },
+
+#if defined(HASCACHEFS)
+ { "cvops", NULL, N_CACHE },
+#endif /* defined(HASCACHEFS) */
+
+ { "devops", "devfs", N_DEV },
+ { "doorops", NULL, N_DOOR },
+ { "fdops", "fd", N_FD },
+ { "fd_ops", "fd", N_FD },
+ { "fvops", "fifofs", N_FIFO },
+ { "hvops", "hsfs", N_HSFS },
+ { "lvops", "lofs", N_LOFS },
+ { "mntops", "mntfs", N_MNT },
+ { "mvops", "mvfs", N_MVFS },
+ { "n3vops", NULL, N_NFS },
+
+#if solaris>=100000
+ { "n4vops", NULL, N_NFS4 },
+#else /* solaris<100000 */
+ { "n4vops", NULL, N_NFS },
+#endif /* solaris>=100000 */
+
+ { "nmvops", "namefs", N_NM },
+ { "nvops", NULL, N_NFS },
+ { "pdvops", "pcfs", N_PCFS },
+ { "pfvops", "pcfs", N_PCFS },
+ { "portvops", NULL, N_PORT },
+ { "prvops", "proc", N_PROC },
+ { "sam1vops", NULL, N_SAMFS },
+ { "sam2vops", NULL, N_SAMFS },
+ { "sam3vops", NULL, N_SAMFS },
+ { "sam4vops", NULL, N_SAMFS },
+ { "sckvops", "sockfs", N_SOCK },
+ { "devipnetops", "sdevfs", N_SDEV },
+ { "devnetops", "sdevfs", N_SDEV },
+ { "devptsops", "sdevfs", N_SDEV },
+ { "devvtops", "sdevfs", N_SDEV },
+ { "socketvops", "sockfs", N_SOCK },
+ { "sdevops", "sdevfs", N_SDEV },
+ { "shvops", "sharedfs", N_SHARED },
+ { "sncavops", "sockfs", N_SOCK },
+ { "stpivops", "sockfs", N_SOCK },
+ { "spvops", "specfs", N_REGLR },
+ { "tvops", "tmpfs", N_TMP },
+ { "uvops", "ufs", N_REGLR },
+ { "vvfclops", "vxfs", N_VXFS },
+ { "vvfops", "vxfs", N_VXFS },
+ { "vvfcops", "vxfs", N_VXFS },
+ { "vvops", "vxfs", N_VXFS },
+ { "vvops_p", "vxfs", N_VXFS },
+ { "zfsdops", "zfs", N_ZFS },
+ { "zfseops", "zfs", N_ZFS },
+ { "zfsfops", "zfs", N_ZFS },
+ { "zfsshops", "zfs", N_ZFS },
+ { "zfssymops", "zfs", N_ZFS },
+ { "zfsxdops", "zfs", N_ZFS },
+ { NULL, NULL, 0 } /* table end */
+};
+
+typedef struct v_optab {
+ char *fsys; /* file system type name */
+ int fx; /* Fsinfo[] index (-1 if none) */
+ int nty; /* node type index (i.e., N_*) */
+ KA_T v_op; /* vnodeops address */
+ struct v_optab *next; /* next entry */
+} v_optab_t;
+
+static v_optab_t **FxToVoptab = (v_optab_t **)NULL;
+ /* table to convert file system index
+ * to Voptab address[] -- built by
+ * build_Voptab() */
+static v_optab_t **Voptab = (v_optab_t **)NULL;
+ /* table to convert vnode v_op
+ * addresses to file system name and
+ * node type -- built by build_Voptab()
+ * and addressed through the HASHVOP()
+ * macro */
+
+#define VOPHASHBINS 256 /* number of Voptab[] hash bins --
+ * MUST BE A POWER OF TWO! */
+
+
+/*
+ * Local function prototypes
+ */
+
+_PROTOTYPE(static void build_Voptab,(void));
+_PROTOTYPE(static char isvlocked,(struct vnode *va));
+_PROTOTYPE(static int readinode,(KA_T ia, struct inode *i));
+_PROTOTYPE(static void read_mi,(KA_T s, dev_t *dev, caddr_t so, int *so_st, KA_T *so_ad, struct l_dev **sdp));
+
+
+#if solaris>=20500
+# if solaris>=20600
+_PROTOTYPE(static int read_nan,(KA_T na, KA_T aa, struct fnnode *rn));
+_PROTOTYPE(static int read_nson,(KA_T na, KA_T sa, struct sonode *sn));
+_PROTOTYPE(static int read_nusa,(struct soaddr *so, struct sockaddr_un *ua));
+# else /* solaris<20600 */
+_PROTOTYPE(static int read_nan,(KA_T na, KA_T aa, struct autonode *a));
+# endif /* solaris>=20600 */
+_PROTOTYPE(static int idoorkeep,(struct door_node *d));
+_PROTOTYPE(static int read_ndn,(KA_T na, KA_T da, struct door_node *d));
+#endif /* solaris>=20500 */
+
+#if solaris>=110000
+_PROTOTYPE(static int read_nsdn,(KA_T na, KA_T sa, struct sdev_node *sdn, struct vattr *sdva));
+#endif /* solaris>=110000 */
+
+_PROTOTYPE(static int read_nfn,(KA_T na, KA_T fa, struct fifonode *f));
+_PROTOTYPE(static int read_nhn,(KA_T na, KA_T ha, struct hsnode *h));
+_PROTOTYPE(static int read_nin,(KA_T na, KA_T ia, struct inode *i));
+_PROTOTYPE(static int read_nmn,(KA_T na, KA_T ia, struct mvfsnode *m));
+_PROTOTYPE(static int read_npn,(KA_T na, KA_T pa, struct pcnode *p));
+_PROTOTYPE(static int read_nrn,(KA_T na, KA_T ra, struct rnode *r));
+
+#if solaris>=100000
+_PROTOTYPE(static int read_nctfsn,(int ty, KA_T na, KA_T ca, char *cn));
+_PROTOTYPE(static int read_nprtn,(KA_T na, KA_T ra, port_t *p));
+_PROTOTYPE(static int read_nrn4,(KA_T na, KA_T ra, struct rnode4 *r));
+#endif /* solaris>=100000 */
+
+_PROTOTYPE(static int read_nsn,(KA_T na, KA_T sa, struct snode *s));
+_PROTOTYPE(static int read_ntn,(KA_T na, KA_T ta, struct tmpnode *t));
+_PROTOTYPE(static int read_nvn,(KA_T na, KA_T va, struct vnode *v));
+
+#if defined(HASPROCFS)
+_PROTOTYPE(static int read_npi,(KA_T na, struct vnode *v, struct pid *pids));
+#endif /* defined(HASPROCFS) */
+
+_PROTOTYPE(static char *ent_fa,(KA_T *a1, KA_T *a2, char *d, int *len));
+_PROTOTYPE(static int is_socket,(struct vnode *v));
+_PROTOTYPE(static int read_cni,(struct snode *s, struct vnode *rv,
+ struct vnode *v, struct snode *rs, struct dev_info *di, char *din,
+ int dinl));
+
+#if defined(HASCACHEFS)
+_PROTOTYPE(static int read_ncn,(KA_T na, KA_T ca, struct cnode *cn));
+#endif /* defined(HASCACHEFS) */
+
+_PROTOTYPE(static int read_nln,(KA_T na, KA_T la, struct lnode *ln));
+_PROTOTYPE(static int read_nnn,(KA_T na, KA_T nna, struct namenode *n));
+
+#if solaris<100000
+_PROTOTYPE(static void savesockmod,(struct so_so *so, struct so_so *sop, int *so_st));
+#else /* solaris>=100000 */
+_PROTOTYPE(static int read_ndvn,(KA_T na, KA_T da, struct dv_node *dv,
+ dev_t *dev, unsigned char *devs));
+#endif /* solaris<100000 */
+
+
+/*
+ * Local static values
+ */
+
+static KA_T Spvops = (KA_T)0; /* specfs vnodeops address -- saved
+ * by build_Voptab() */
+static KA_T Vvops[VXVOP_NUM]; /* addresses of:
+ * vx_fcl_dnodeops_p (VXVOP_FCL)
+ * fdd_vnops (VXVOP_FDD)
+ * fdd_chain_vnops (VXVOP_FDDCH),
+ * vx_vnodeops (VXVOP_REG)
+ * vx_vnodeops_p (VXVOP_REG_P)
+ * -- saved by build_Voptab() */
+
+/*
+ * Local macros
+ *
+ * GETVOPS() -- get direct or indirect *vnodeops address
+ *
+ * HASHVOP() -- hash the vnode's v_op address
+ */
+
+#if defined(VOPNAME_OPEN) && solaris>=100000
+#define GETVOPS(name, nl, ops) \
+ if (get_Nl_value(name, nl, &ops) < 0) \
+ ops = (KA_T)0; \
+ else if (kread(ops, (char *)&ops, sizeof(ops))) \
+ ops = (KA_T)0
+#else /* !defined(VOPNAME_OPEN) || solaris<100000 */
+#define GETVOPS(name, nl, ops) \
+ if (get_Nl_value(name, nl, &ops) < 0) \
+ ops = (KA_T)0
+#endif /* defined(VOPNAME_OPEN) && solaris>=100000 */
+
+#define HASHVOP(ka) ((int)((((ka &0x1fffffff) * 31415) >> 3) & \
+ (VOPHASHBINS - 1)))
+
+
+/*
+ * build_Voptab() -- build Voptab[]
+ */
+
+static void
+build_Voptab()
+{
+ build_v_optab_t *bp; /* Build_v_optab[] pointer */
+ int fx; /* temporary file system type index */
+ int h; /* hash index */
+ int i, j; /* temporary indexes */
+ KA_T ka; /* temporary kernel address */
+ v_optab_t *nv, *vp, *vpp; /* Voptab[] working pointers */
+ int vv = 0; /* number of Vvops[] addresses that
+ * have been located */
+/*
+ * If Voptab[] is allocated, return; otherwise allocate space for Voptab[]
+ * and FxToVoptab[] amd fill them.
+ */
+ if (Voptab)
+ return;
+/*
+ * During first call, allocate space for Voptab[] and FxToVoptab[].
+ */
+
+ if (!(Voptab = (v_optab_t **)calloc((MALLOC_S)VOPHASHBINS,
+ sizeof(v_optab_t)))
+ ) {
+ (void) fprintf(stderr, "%s: no space for Voptab\n", Pn);
+ Exit(1);
+ }
+ if (!(FxToVoptab = (v_optab_t **)calloc((MALLOC_S)Fsinfomax,
+ sizeof(v_optab_t *)))
+ ) {
+ (void) fprintf(stderr, "%s: no space for FxToVoptab\n", Pn);
+ Exit(1);
+ }
+ for (i = 0; i < VXVOP_NUM; i++) {
+ Vvops[i] = (KA_T)NULL;
+ }
+/*
+ * Use Build_v_optab[] to build Voptab[].
+ */
+ for (bp = Build_v_optab; bp->dnm; bp++) {
+
+ /*
+ * Get the kernel address for the symbol. Do nothing if it can't
+ * be determined.
+ */
+ GETVOPS(bp->dnm, Drive_Nl, ka);
+ if (!ka)
+ continue;
+ /*
+ * Check the Voptab[] for the address.
+ */
+ h = HASHVOP(ka);
+ for (vp = Voptab[h], vpp = (v_optab_t *)NULL; vp; vp = vp->next) {
+ if (vp->v_op == ka)
+ break;
+ vpp = vp;
+ }
+ if (vp) {
+
+ /*
+ * Ignore duplicates.
+ */
+ continue;
+ }
+ /*
+ * No Voptab[] entry was found, so allocate space for a new
+ * v_optab_t structure, determine its file system type index,
+ * fill it and link it to the Voptab[].
+ */
+ if (!(nv = (v_optab_t *)malloc((MALLOC_S)sizeof(v_optab_t)))) {
+ (void) fprintf(stderr, "%s: out of Voptab space at: %s\n",
+ Pn, bp->dnm);
+ Exit(1);
+ }
+ nv->fsys = bp->fsys;
+ nv->fx = -1;
+ nv->nty = bp->nty;
+ nv->next = (v_optab_t *)NULL;
+ nv->v_op = ka;
+ if (bp->fsys) {
+ for (i = 0; i < Fsinfomax; i++) {
+ if (!strcmp(bp->fsys, Fsinfo[i])) {
+ nv->fx = i;
+ break;
+ }
+ }
+ }
+ if (!Voptab[h])
+ Voptab[h] = nv;
+ else
+ vpp->next = nv;
+ /*
+ * Handle special v_op addresses:
+ *
+ * special vnode ops;
+ * VxFS ops.
+ */
+ if (!Spvops) {
+ if (!strcmp(bp->dnm, "spvops"))
+ Spvops = ka;
+ }
+ for (i = 0; (i < VXVOP_NUM) && (vv < VXVOP_NUM); i++) {
+ if (Vvops[i])
+ continue;
+ switch (i) {
+ case VXVOP_FCL:
+ if (!strcmp(bp->dnm, "vvfclops")) {
+ Vvops[i] = ka;
+ vv++;
+ }
+ break;
+ case VXVOP_FDD:
+ if (!strcmp(bp->dnm, "vvfops")) {
+ Vvops[i] = ka;
+ vv++;
+ }
+ break;
+ case VXVOP_FDDCH:
+ if (!strcmp(bp->dnm, "vvfcops")) {
+ Vvops[i] = ka;
+ vv++;
+ }
+ break;
+ case VXVOP_REG:
+ if (!strcmp(bp->dnm, "vvops")) {
+ Vvops[i] = ka;
+ vv++;
+ }
+ break;
+ case VXVOP_REG_P:
+ if (!strcmp(bp->dnm, "vvops_p")) {
+ Vvops[i] = ka;
+ vv++;
+ }
+ break;
+ }
+ }
+ }
+/*
+ * Link Voptab[] entries to FxToVoptab[] entries.
+ */
+ for (h = 0; h < VOPHASHBINS; h++) {
+ for (vp = Voptab[h]; vp; vp = vp->next) {
+ if (!vp->fsys)
+ continue;
+ if (((fx = vp->fx) >= 0) && (fx < Fsinfomax)) {
+ if (!FxToVoptab[fx])
+ FxToVoptab[fx] = vp;
+ continue;
+ }
+ for (i = 0; i < Fsinfomax; i++) {
+ if (!strcmp(Fsinfo[i], vp->fsys)) {
+ vp->fx = i;
+ if (!FxToVoptab[i])
+ FxToVoptab[i] = vp;
+ break;
+ }
+ }
+ }
+ }
+}
+
+
+#if defined(HAS_LIBCTF)
+/*
+ * CTF_getmem() -- get CTF members
+ */
+
+int
+CTF_getmem(f, mod, ty, mem)
+ ctf_file_t *f; /* CTF file handle */
+ const char *mod; /* module name */
+ const char *ty; /* type */
+ CTF_member_t *mem; /* member table */
+{
+ int err; /* error flag */
+ ctf_id_t id; /* CTF ID */
+ CTF_member_t *mp; /* member pointer */
+ CTF_exception_t *xp; /* exception table pointer */
+ int xs; /* exception status */
+/*
+ * Look up the type.
+ */
+ if ((id = ctf_lookup_by_name(f, ty)) == CTF_ERR) {
+ (void) fprintf(stderr, "%s: ctf_lookup_by_name: %s: %s: %s\n",
+ Pn, mod, ty, ctf_errmsg(ctf_errno(f)));
+ return(1);
+ }
+/*
+ * Get member offsets.
+ */
+ if (ctf_member_iter(f, id, CTF_memCB, mem) == CTF_ERR) {
+ (void) fprintf(stderr, "%s: ctf_member_iter: %s: %s: %s\n",
+ Pn, mod, ty, ctf_errmsg(ctf_errno(f)));
+ return(1);
+ }
+/*
+ * Examine members.
+ */
+ for (err = 0, mp = mem; mp->m_name; mp++) {
+ if (mp->m_offset == CTF_MEMBER_UNDEF) {
+
+ /*
+ * Check for an undefined member exception. Report an error if
+ * no exception is found.
+ */
+ for (xp = CTF_exceptions, xs = 0; xp->tynm; xp++) {
+ if (!strcmp(xp->tynm, ty) && !strcmp(xp->memnm, mp->m_name)) {
+ xs = 1;
+ break;
+ }
+ }
+ if (!xs) {
+ (void) fprintf(stderr,
+ "%s: getmembers: %s: %s: %s: struct member undefined\n",
+ Pn, mod, ty, mp->m_name);
+ err = 1;
+ }
+ } else {
+
+ /*
+ * Convert bit offsets to byte offsets.
+ */
+ if ((mp->m_offset % NBBY) != 0) {
+ (void) fprintf(stderr,
+ "%s: getmembers: %s: %s: %s: struct member is bit field\n",
+ Pn, mod, ty, mp->m_name);
+ err = 1;
+ } else
+ mp->m_offset /= NBBY;
+ }
+ }
+ return(err);
+}
+
+
+/*
+ * CTF_init - initialize CTF library access
+ */
+
+void
+CTF_init(i, t, r)
+ int *i; /* initialization status */
+ char *t; /* kernel module template */
+ CTF_request_t *r; /* CTF requests */
+{
+ int err; /* error status */
+ ctf_file_t *f; /* CTF file info handle */
+
+# if defined(_LP64)
+ static char isa[256+1]; /* kernel instruction set name */
+ static int isas = 0; /* isa[] status */
+# endif /* defined(_LP64) */
+
+ char kernmod[MAXPATHLEN]; /* kernel module pathname */
+ char *kmp; /* kernel module path name pointer */
+ static char pfn[256+1]; /* system platform name */
+ static int pfns = 0; /* pfn[] status: -1 = request failed
+ * 0 = none requested
+ * >0 = available */
+ char pfxkernmod[MAXPATHLEN]; /* prefixed kernel module name */
+ struct stat sb; /* stat(2) buffer */
+
+ if (*i)
+ return;
+
+# if defined(_LP64)
+/*
+ * If CTF access hasn't been initialized and a 64 bit kernel is in use,
+ * determine the name of the kernel's instruction set, and construct the
+ * pathname of the kernel module, using the supplied template.
+ */
+ if (!isas) {
+ if (sysinfo(SI_ARCHITECTURE_K, isa, sizeof(isa) - 1) == -1) {
+ (void) fprintf(stderr, "%s: sysinfo: %s\n", Pn, strerror(errno));
+ Exit(1);
+ }
+ isas = 1;
+ isa[sizeof(isa) - 1] = '\0';
+ }
+ (void) snprintf(kernmod, sizeof(kernmod) - 1, t, isa);
+ kernmod[sizeof(kernmod) - 1] = '\0';
+# else /* !defined(_LP64) */
+/*
+ * If CTF access hasn't been initialized and a 32 bit kernel is in use, the
+ * supplied template is the module path name.
+ */
+ (void) strncpy(kernmod, t, sizeof(kernmod) - 1);
+# endif /* defined(_LP64) */
+
+ kernmod[sizeof(kernmod) - 1] = '\0';
+ kmp = kernmod;
+ if (statsafely(kmp, &sb)) {
+
+ /*
+ * The module at the specified path does not exist or is inaccessible.
+ *
+ * Get the platform name and construct a prefix from it for module path
+ * name and see if that exists and is accessible.
+ *
+ * If it is, let CTF_init() use it; otherwise let CTF_init() fail on
+ * the specified path.
+ */
+ if (pfns >= 0) {
+ if (!pfns)
+ pfns = sysinfo(SI_MACHINE, pfn, sizeof(pfn) - 1);
+ if (pfns > 0) {
+ pfn[sizeof(pfn) - 1] = '\0';
+ (void) snprintf(pfxkernmod, sizeof(pfxkernmod) - 1,
+ "/platform/%s/%s", pfn,
+ (kernmod[0] == '/') ? &kernmod[1] : kernmod);
+ pfxkernmod[sizeof(pfxkernmod) - 1] = '\0';
+ if (!stat(pfxkernmod, &sb))
+ kmp = pfxkernmod;
+ }
+ }
+ }
+/*
+ * Open the module file and read its CTF info.
+ */
+ if ((f = ctf_open(kmp, &err)) == NULL) {
+ (void) fprintf(stderr, "%s: ctf_open: %s: %s\n",
+ Pn, kmp, ctf_errmsg(err));
+ Exit(1);
+ }
+ for (err = 0; r->name; r++) {
+ if (CTF_getmem(f, kmp, r->name, r->mem))
+ err = 1;
+ }
+ (void) ctf_close(f);
+ if (err)
+ Exit(1);
+ *i = 1;
+}
+
+
+/*
+ * CTF_memCB() - Callback function for ctf_member_iter()
+ */
+
+int
+CTF_memCB(name, id, offset, arg)
+ const char *name; /* structure member name */
+ ctf_id_t id; /* CTF ID */
+ ulong_t offset; /* member offset */
+ void *arg; /* member table */
+{
+ CTF_member_t *mp;
+/*
+ * Check for members of interest and record their offsets.
+ */
+ for (mp = (CTF_member_t *)arg; mp->m_name; mp++) {
+ if (!strcmp(name, mp->m_name)) {
+ mp->m_offset = offset;
+ break;
+ }
+ }
+ return(0);
+}
+#endif /* defined(HAS_LIBCTF) */
+
+
+/*
+ * ent_fa() - enter fattach addresses in NAME column addition
+ */
+
+static char *
+ent_fa(a1, a2, d, len)
+ KA_T *a1; /* first fattach address (NULL OK) */
+ KA_T *a2; /* second fattach address */
+ char *d; /* direction ("->" or "<-") */
+ int *len; /* returned description length */
+{
+ static char buf[1024];
+ size_t bufl = sizeof(buf);
+ char tbuf[32];
+/*
+ * Form the fattach description.
+ */
+ if (!a1)
+
+#if solaris<20600
+ (void) snpf(buf, bufl, "(FA:%s%s)", d,
+ print_kptr(*a2, (char *)NULL, 0));
+#else /* solaris>=20600 */
+ (void) snpf(buf, bufl, "(FA:%s%s)", d,
+ print_kptr(*a2, (char *)NULL, 0));
+#endif /* solaris<20600 */
+
+ else
+
+#if solaris<20600
+ (void) snpf(buf, bufl, "(FA:%s%s%s)",
+ print_kptr(*a1, tbuf, sizeof(tbuf)), d,
+ print_kptr(*a2, (char *)NULL, 0));
+#else /* solaris>=20600 */
+ (void) snpf(buf, bufl, "(FA:%s%s%s)",
+ print_kptr(*a1, tbuf, sizeof(tbuf)), d,
+ print_kptr(*a2, (char *)NULL, 0));
+#endif /* solaris<20600 */
+
+ *len = (int)strlen(buf);
+ return(buf);
+}
+
+
+/*
+ * is_socket() - is the stream a socket?
+ */
+
+static int
+is_socket(v)
+ struct vnode *v; /* vnode pointer */
+{
+ char *cp, *ep, *pf;
+ int i, j, len, n, pfl;
+ major_t maj;
+ minor_t min;
+ static struct tcpudp {
+ int ds;
+ major_t maj;
+ minor_t min;
+ char *proto;
+ } tcpudp[] = {
+ { 0, 0, 0, "tcp" },
+ { 0, 0, 0, "udp" },
+
+#if defined(HASIPv6)
+ { 0, 0, 0, "tcp6" },
+ { 0, 0, 0, "udp6" },
+#endif /* defined(HASIPv6) */
+
+ };
+#define NTCPUDP (sizeof(tcpudp) / sizeof(struct tcpudp))
+
+ static int tcpudps = 0;
+
+ if (!v->v_stream)
+ return(0);
+ maj = (major_t) GET_MAJ_DEV(v->v_rdev);
+ min = (minor_t) GET_MIN_DEV(v->v_rdev);
+/*
+ * Fill in tcpudp[], as required.
+ */
+ if (!tcpudps) {
+
+#if solaris<80000
+ pf = "/devices/pseudo/clone";
+#else /* solaris>=80000 */
+ pf = "/devices/pseudo/";
+#endif /* solaris<80000 */
+
+ for (i = n = 0, pfl = (int)strlen(pf); (i < Ndev) && (n < NTCPUDP); i++)
+ {
+ if (strncmp(Devtp[i].name, pf, pfl)
+ || !(ep = strrchr((cp = &Devtp[i].name[pfl]), ':'))
+ || (strncmp(++ep, "tcp", 3) && strncmp(ep, "udp", 3)))
+ continue;
+
+#if solaris<80000
+ if (*(ep + 3))
+#else /* solaris>=80000 */
+ len = (*(ep + 3) == '6') ? 4 : 3;
+ if (*(ep + len) || ((cp + len) >= ep) || strncmp(cp, ep, len))
+#endif /* solaris<80000 */
+
+ continue;
+ for (j = 0; j < NTCPUDP; j++) {
+ if (!tcpudp[j].ds && !strcmp(ep, tcpudp[j].proto)) {
+ tcpudp[j].ds = 1;
+ tcpudp[j].maj = (major_t) GET_MAJ_DEV(Devtp[i].rdev);
+ tcpudp[j].min = (minor_t) GET_MIN_DEV(Devtp[i].rdev);
+ n++;
+ break;
+ }
+ }
+ }
+ tcpudps = n ? 1 : -1;
+ }
+/*
+ * Check for known IPv[46] TCP or UDP device.
+ */
+ for (i = 0; (i < NTCPUDP) && (tcpudps > 0); i++) {
+ if (tcpudp[i].ds
+
+#if solaris<80000
+ && (maj == tcpudp[i].min)
+#else /* solaris>=80000 */
+ && (maj == tcpudp[i].maj)
+#endif /* solaris<80000 */
+
+ ) {
+ process_socket((KA_T)v->v_stream, tcpudp[i].proto);
+ return(1);
+ }
+ }
+ return(0);
+}
+
+
+/*
+ * isvlocked() - is Solaris vnode locked?
+ */
+
+static char
+isvlocked(va)
+ struct vnode *va; /* local vnode address */
+{
+
+#if solaris<20500
+ struct filock f;
+ KA_T ff;
+ KA_T fp;
+#endif /* solaris<20500 */
+
+ int i, l;
+
+#if solaris>=20300
+ struct lock_descriptor ld;
+ KA_T lf;
+ KA_T lp;
+# if solaris<20500
+#define LOCK_END ld.info.li_sleep.sli_flock.l_len
+#define LOCK_FLAGS ld.flags
+#define LOCK_NEXT ld.next
+#define LOCK_OWNER ld.owner.pid
+#define LOCK_START ld.start
+#define LOCK_TYPE ld.type
+# else /* solaris>=20500 */
+#define LOCK_END ld.l_flock.l_len
+#define LOCK_FLAGS ld.l_state
+#define LOCK_NEXT ld.l_next
+#define LOCK_OWNER ld.l_flock.l_pid
+#define LOCK_START ld.l_start
+#define LOCK_TYPE ld.l_type
+# endif /* solaris<20500 */
+#endif /* solaris>=20300 */
+
+ if (va->v_filocks == NULL)
+ return(' ');
+
+#if solaris<20500
+# if solaris>20300 || (solaris==20300 && defined(P101318) && P101318>=45)
+ if (Ntype == N_NFS)
+# endif /* solaris>20300 || (solaris==20300 && defined(P101318) && P101318>=45) */
+
+ {
+ ff = fp = (KA_T)va->v_filocks;
+ i = 0;
+ do {
+ if (kread(fp, (char *)&f, sizeof(f)))
+ return(' ');
+ i++;
+ if (f.set.l_pid != (pid_t)Lp->pid)
+ continue;
+ if (f.set.l_whence == 0 && f.set.l_start == 0
+ && f.set.l_len == MAXEND)
+ l = 1;
+ else
+ l = 0;
+ switch (f.set.l_type & (F_RDLCK | F_WRLCK)) {
+ case F_RDLCK:
+ return(l ? 'R' : 'r');
+ case F_WRLCK:
+ return(l ? 'W' : 'w');
+ case F_RDLCK|F_WRLCK:
+ return('u');
+ default:
+ return('N');
+ }
+ } while ((fp = (KA_T)f.next) && (fp != ff) && (i < 10000));
+ }
+#endif /* solaris<20500 */
+
+#if solaris>=20300
+ lf = lp = (KA_T)va->v_filocks;
+ i = 0;
+ do {
+ if (kread(lp, (char *)&ld, sizeof(ld)))
+ return(' ');
+ i++;
+ if (!(LOCK_FLAGS & ACTIVE_LOCK) || LOCK_OWNER != (pid_t)Lp->pid)
+ continue;
+ if (LOCK_START == 0
+ && (LOCK_END == 0
+
+# if solaris<20500
+ || LOCK_END == MAXEND
+# else /* solaris>=20500 */
+ || LOCK_END == MAXEND
+# endif /* solaris<20500 */
+
+ ))
+ l = 1;
+ else
+ l = 0;
+ switch (LOCK_TYPE) {
+ case F_RDLCK:
+ return(l ? 'R' : 'r');
+ case F_WRLCK:
+ return(l ? 'W' : 'w');
+ case (F_RDLCK | F_WRLCK):
+ return('u');
+ default:
+ return('L');
+ }
+ } while ((lp = (KA_T)LOCK_NEXT) && (lp != lf) && (i < 10000));
+ return(' ');
+#endif /* solaris>=20300 */
+
+}
+
+
+/*
+ * finddev() - look up device by device number
+ */
+
+static struct l_dev *
+finddev(dev, rdev, flags)
+ dev_t *dev; /* device */
+ dev_t *rdev; /* raw device */
+ int flags; /* look flags -- see LOOKDEV_* symbol
+ * definitions */
+{
+ struct clone *c;
+ struct l_dev *dp;
+ struct pseudo *p;
+
+ if (!Sdev)
+ readdev(0);
+/*
+ * Search device table for match.
+ */
+
+#if defined(HASDCACHE)
+
+finddev_again:
+
+#endif /* defined(HASDCACHE) */
+
+ if (flags & LOOKDEV_TAB) {
+ if ((dp = lkupdev(dev, rdev, 0, 0)))
+ return(dp);
+ }
+/*
+ * Search for clone.
+ */
+ if ((flags & LOOKDEV_CLONE) && Clone) {
+ for (c = Clone; c; c = c->next) {
+ if (GET_MAJ_DEV(*rdev) == GET_MIN_DEV(c->cd.rdev)) {
+
+#if defined(HASDCACHE)
+ if (DCunsafe && !c->cd.v && !vfy_dev(&c->cd))
+ goto finddev_again;
+#endif /* defined(HASDCACHE) */
+
+ return(&c->cd);
+ }
+ }
+ }
+/*
+ * Search for pseudo device match on major device only.
+ */
+ if ((flags & LOOKDEV_PSEUDO) && Pseudo) {
+ for (p = Pseudo; p; p = p->next) {
+ if (GET_MAJ_DEV(*rdev) == GET_MAJ_DEV(p->pd.rdev)) {
+
+#if defined(HASDCACHE)
+ if (DCunsafe && !p->pd.v && !vfy_dev(&p->pd))
+ goto finddev_again;
+#endif /* defined(HASDCACHE) */
+
+ return(&p->pd);
+ }
+ }
+ }
+ return((struct l_dev *)NULL);
+}
+
+
+#if solaris>=20500
+/*
+ * idoorkeep() -- identify door keeper process
+ */
+
+static int
+idoorkeep(d)
+ struct door_node *d; /* door's node */
+{
+ char buf[1024];
+ size_t bufl = sizeof(buf);
+ struct proc dp;
+ struct pid dpid;
+/*
+ * Get the proc structure and its pid structure for the door target.
+ */
+ if (!d->door_target
+ || kread((KA_T)d->door_target, (char *)&dp, sizeof(dp)))
+ return(0);
+ if (!dp.p_pidp
+ || kread((KA_T)dp.p_pidp, (char *)&dpid, sizeof(dpid)))
+ return(0);
+/*
+ * Form a description of the door.
+ *
+ * Put the description in the NAME column addition field. If there's already
+ * something there, allocate more space and add the door description to it.
+ */
+ if (Lp->pid == (int)dpid.pid_id)
+ (void) snpf(buf, bufl, "(this PID's door)");
+ else {
+ (void) snpf(buf, bufl, "(door to %.64s[%ld])", dp.p_user.u_comm,
+ (long)dpid.pid_id);
+ }
+ (void) add_nma(buf, (int)strlen(buf));
+ return(1);
+}
+#endif /* solaris>=20500 */
+
+
+/*
+ * process_node() - process vnode
+ */
+
+void
+process_node(va)
+ KA_T va; /* vnode kernel space address */
+{
+
+#if defined(HASCACHEFS)
+ struct cnode cn;
+#endif /* defined(HASCACHEFS) */
+
+ dev_t dev, rdev, trdev;
+ unsigned char devs = 0;
+ unsigned char fxs = 0;
+ unsigned char ins = 0;
+ unsigned char kvs = 0;
+ unsigned char nns = 0;
+ unsigned char pnl = 0;
+ unsigned char rdevs = 0;
+ unsigned char rvs = 0;
+ unsigned char rfxs = 0;
+ unsigned char sdns = 0;
+ unsigned char tdef;
+ unsigned char trdevs = 0;
+ unsigned char unix_sock = 0;
+ struct dev_info di;
+ char din[DINAMEL];
+ char *ep;
+ struct fifonode f;
+ char *fa = (char *)NULL;
+ int fal;
+ static int ft = 1;
+ struct vnode fv, rv;
+ int fx, rfx;
+ struct hsnode h;
+ struct inode i;
+ int j;
+ KA_T ka, vka;
+ struct lnode lo;
+ struct vfs kv, rkv;
+ int len, llc, nl, snl, sepl;
+ struct mvfsnode m;
+ struct namenode nn;
+ struct l_vfs *nvfs, *vfs;
+ struct pcnode pc;
+ struct pcfs pcfs;
+ struct rnode r;
+ KA_T realvp = (KA_T)NULL;
+ struct snode rs;
+ struct snode s;
+
+#if solaris>=110000
+ char *nm, *sep;
+ size_t nmrl, tl;
+ struct sdev_node sdn;
+ struct vattr sdva;
+ sotpi_info_t sti;
+ int stis = 0;
+#endif /* solaris>=110000 */
+
+ struct l_dev *sdp = (struct l_dev *)NULL;
+ size_t sz;
+ struct tmpnode t;
+ char tbuf[128], *ty, ubuf[128];
+ int tbufx;
+ enum vtype type;
+ struct sockaddr_un ua;
+ static struct vnode *v = (struct vnode *)NULL;
+ KA_T vs;
+ int vty = 0;
+ int vty_tmp;
+
+#if solaris>=20500
+# if solaris>=20600
+ struct fnnode fnn;
+ struct pairaddr {
+ short f;
+ unsigned short p;
+ } *pa;
+ KA_T peer;
+ struct sonode so;
+ KA_T soa, sona;
+# else /* solaris<20600 */
+ struct autonode au;
+# endif /* solaris>=20600 */
+
+ struct door_node dn;
+ int dns = 0;
+#endif /* solaris >=20500 */
+
+#if solaris<100000
+ KA_T so_ad[2];
+ struct so_so soso;
+ int so_st = 0;
+#else /* solaris>=100000 */
+ union {
+ ctfs_adirnode_t adir;
+ ctfs_bunode_t bun;
+ ctfs_cdirnode_t cdir;
+ ctfs_ctlnode_t ctl;
+ ctfs_evnode_t ev;
+ ctfs_latenode_t late;
+ ctfs_rootnode_t root;
+ ctfs_symnode_t sym;
+ ctfs_tdirnode_t tdir;
+ ctfs_tmplnode_t tmpl;
+ } ctfs;
+ dev_t dv_dev;
+ struct dv_node dv;
+ unsigned char dv_devs = 0;
+ unsigned char dvs = 0;
+ port_t pn;
+ struct rnode4 r4;
+#endif /* solaris<100000 */
+
+
+#if defined(HASPROCFS)
+ struct procfsid *pfi;
+ struct pid pids;
+#endif /* defined(HASPROCFS) */
+
+#if defined(HAS_AFS)
+ struct afsnode an;
+#endif /* defined(HAS_AFS) */
+
+#if defined(HASVXFS)
+ struct l_ino vx;
+#endif /* defined(HASVXFS) */
+
+#if defined(HAS_ZFS)
+ vfs_t zgvfs;
+ unsigned char zns = 0;
+ znode_t zn;
+ zfsvfs_t zvfs;
+#endif /* defined(HAS_ZFS) */
+
+/*
+ * Do first-time only operations.
+ */
+
+#if solaris<100000
+ so_ad[0] = so_ad[1] = (KA_T)0;
+#endif /* solaris<100000 */
+
+ if (ft) {
+ (void) build_Voptab();
+ ft = 0;
+ }
+/*
+ * Read the vnode.
+ */
+ if (!va) {
+ enter_nm("no vnode address");
+ return;
+ }
+ if (!v) {
+
+ /*
+ * Allocate space for the vnode or AFS vcache structure.
+ */
+
+#if defined(HAS_AFS)
+ v = alloc_vcache();
+#else /* !defined(HAS_AFS) */
+ v = (struct vnode *) malloc(sizeof(struct vnode));
+#endif /* defined(HAS_AFS) */
+
+ if (!v) {
+ (void) fprintf(stderr, "%s: can't allocate %s space\n", Pn,
+
+#if defined(HAS_AFS)
+ "vcache"
+#else /* !defined(HAS_AFS) */
+ "vnode"
+#endif /* defined(HAS_AFS) */
+
+ );
+ Exit(1);
+ }
+ }
+ if (readvnode(va, v)) {
+ enter_nm(Namech);
+ return;
+ }
+
+#if defined(HASNCACHE)
+ Lf->na = va;
+#endif /* defined(HASNCACHE) */
+
+#if defined(HASFSTRUCT)
+ Lf->fna = va;
+ Lf->fsv |= FSV_NI;
+#endif /* defined(HASFSTRUCT) */
+
+#if defined(HASLFILEADD) && defined(HAS_V_PATH)
+ Lf->V_path = (KA_T)v->v_path;
+#endif /* defined(HASLFILEADD) && defined(HAS_V_PATH) */
+
+ vs = (KA_T)v->v_stream;
+/*
+ * Check for a Solaris socket.
+ */
+ if (is_socket(v))
+ return;
+/*
+ * Obtain the Solaris virtual file system structure.
+ */
+ if ((ka = (KA_T)v->v_vfsp)) {
+ if (kread(ka, (char *)&kv, sizeof(kv))) {
+ vka = va;
+
+vfs_read_error:
+
+ (void) snpf(Namech, Namechl - 1,
+ "vnode at %s: can't read vfs: %s",
+ print_kptr(vka, tbuf, sizeof(tbuf)),
+ print_kptr(ka, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return;
+ }
+ kvs = 1;
+ } else
+ kvs = 0;
+/*
+ * Derive the virtual file system structure's device number from
+ * its file system ID for NFS and High Sierra file systems.
+ */
+ if (kvs && ((fx = kv.vfs_fstype - 1) >= 0) && (fx < Fsinfomax)) {
+ fxs = 1;
+ if (strcmp(Fsinfo[fx], "nfs") == 0
+ || strcmp(Fsinfo[fx], "nfs3") == 0
+ || strcmp(Fsinfo[fx], "hsfs") == 0)
+ kv.vfs_dev = (dev_t)kv.vfs_fsid.val[0];
+ } else {
+ fx = -1;
+ fxs = 0;
+ }
+/*
+ * Determine the Solaris vnode type.
+ */
+ if ((Ntype = vop2ty(v, fx)) < 0) {
+ if (v->v_type == VFIFO) {
+ vty = N_REGLR;
+ Ntype = N_FIFO;
+ } else if (vs) {
+ Ntype = vty = N_STREAM;
+ Lf->is_stream = 1;
+ }
+ if (Ntype < 0) {
+ (void) snpf(Namech, Namechl - 1,
+ "unknown file system type%s%s%s, v_op: %s",
+ fxs ? " (" : "",
+ fxs ? Fsinfo[fx] : "",
+ fxs ? ")" : "",
+ print_kptr((KA_T)v->v_op, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return;
+ }
+ } else {
+ vty = Ntype;
+ if (v->v_type == VFIFO)
+ Ntype = N_FIFO;
+ else if (vs && Ntype != N_SOCK) {
+ Ntype = vty = N_STREAM;
+ Lf->is_stream = 1;
+ }
+ }
+/*
+ * See if this Solaris node has been fattach'ed to another node.
+ * If it has, read the namenode, and enter the node addresses in
+ * the NAME column addition.
+ *
+ * See if it's covering a socket as well and process accordingly.
+ */
+ if (vty == N_NM) {
+ if (read_nnn(va, (KA_T)v->v_data, &nn))
+ return;
+ nns = 1;
+ if (nn.nm_mountpt)
+
+#if solaris>=20500
+ fa = ent_fa((KA_T *)((Ntype == N_FIFO || v->v_type == VDOOR)
+ ? NULL : &va),
+ (KA_T *)&nn.nm_mountpt, "->", &fal);
+#else /* solaris<20500 */
+ fa = ent_fa((KA_T *)((Ntype == N_FIFO)
+ ? NULL : &va),
+ (KA_T *)&nn.nm_mountpt, "->", &fal);
+#endif /* solaris>=20500 */
+
+ if (Ntype != N_FIFO
+ && nn.nm_filevp
+ && !kread((KA_T)nn.nm_filevp, (char *)&rv, sizeof(rv))) {
+ rvs = 1;
+ if ((ka = (KA_T)rv.v_vfsp)
+ && !kread(ka, (char *)&rkv, sizeof(rkv))
+ && ((rfx = rkv.vfs_fstype - 1) >= 0)
+ && (rfx < Fsinfomax)
+ ) {
+ rfxs = 1;
+ } else {
+ rfx = fx;
+ rfxs = fxs;
+ }
+
+#if defined(HASNCACHE)
+ Lf->na = (KA_T)nn.nm_filevp;
+#endif /* defined(HASNCACHE) */
+
+ if (is_socket(&rv))
+ return;
+ }
+ }
+ if (Selinet && Ntype != N_SOCK)
+ return;
+/*
+ * See if this Solaris node is served by spec_vnodeops.
+ */
+ if (Spvops && Spvops == (KA_T)v->v_op)
+ Ntype = N_SPEC;
+/*
+ * Determine the Solaris lock state.
+ */
+ Lf->lock = isvlocked(v);
+/*
+ * Establish the Solaris local virtual file system structure.
+ */
+ if (!(ka = (KA_T)v->v_vfsp) || !kvs)
+ vfs = (struct l_vfs *)NULL;
+ else if (!(vfs = readvfs(ka, &kv, v))) {
+ vka = va;
+ goto vfs_read_error;
+ }
+/*
+ * Read the afsnode, autonode, cnode, door_node, fifonode, fnnode, lnode,
+ * inode, pcnode, rnode, snode, tmpnode, znode, etc.
+ */
+ switch (Ntype) {
+ case N_SPEC:
+
+ /*
+ * A N_SPEC node is a node that resides in in an underlying file system
+ * type -- e.g. NFS, HSFS. Its vnode points to an snode. Subsequent
+ * node structures are implied by the underlying node type.
+ */
+ if (read_nsn(va, (KA_T)v->v_data, &s))
+ return;
+ realvp = (KA_T)s.s_realvp;
+ if (!realvp && s.s_commonvp) {
+ if (read_cni(&s, &rv, v, &rs, &di, din, sizeof(din)) == 1)
+ return;
+ if (!rv.v_stream) {
+ if (din[0]) {
+ (void) snpf(Namech, Namechl, "COMMON: %s", din);
+ Namech[Namechl - 1] = '\0';
+ Lf->is_com = 1;
+ }
+ break;
+ }
+ }
+ if (!realvp) {
+
+ /*
+ * If the snode lacks a real vnode (and also lacks a common vnode),
+ * it's original type is N_STREAM or N_REGLR, and it has a stream
+ * pointer, get the module names.
+ */
+ if ((vty == N_STREAM || vty == N_REGLR) && vs) {
+ Lf->is_stream = 1;
+ vty = N_STREAM;
+
+#if solaris<100000
+ read_mi(vs, (dev_t *)&s.s_dev, (caddr_t)&soso, &so_st,
+ so_ad, &sdp);
+#else /* solaris>=100000 */
+ read_mi(vs, (dev_t *)&s.s_dev, NULL, NULL, NULL, &sdp);
+#endif /* solaris<100000 */
+
+ vs = (KA_T)NULL;
+ }
+ }
+ break;
+
+#if defined(HAS_AFS)
+ case N_AFS:
+ if (readafsnode(va, v, &an))
+ return;
+ break;
+#endif /* defined(HAS_AFS) */
+
+#if solaris>=20500
+ case N_AUTO:
+
+# if solaris<20600
+ if (read_nan(va, (KA_T)v->v_data, &au))
+# else /* solaris>=20600 */
+ if (read_nan(va, (KA_T)v->v_data, &fnn))
+# endif /* solaris<20600 */
+
+ return;
+ break;
+
+# if solaris>=100000
+ case N_DEV:
+ if (read_ndvn(va, (KA_T)v->v_data, &dv, &dv_dev, &dv_devs))
+ return;
+ dvs = 1;
+ break;
+# endif /* solaris>=100000 */
+
+ case N_DOOR:
+ if (read_ndn(va, (KA_T)v->v_data, &dn))
+ return;
+ dns = 1;
+ break;
+#endif /* solaris>=20500 */
+
+#if defined(HASCACHEFS)
+ case N_CACHE:
+ if (read_ncn(va, (KA_T)v->v_data, &cn))
+ return;
+ break;
+#endif /* defined(HASCACHEFS) */
+
+#if solaris>=100000
+ case N_CTFSADIR:
+ case N_CTFSBUND:
+ case N_CTFSCDIR:
+ case N_CTFSCTL:
+ case N_CTFSEVT:
+ case N_CTFSLATE:
+ case N_CTFSROOT:
+ case N_CTFSSTAT:
+ case N_CTFSSYM:
+ case N_CTFSTDIR:
+ case N_CTFSTMPL:
+ if (read_nctfsn(Ntype, va, (KA_T)v->v_data, (char *)&ctfs))
+ return;
+ break;
+#endif /* solaris>=100000 */
+
+#if solaris>=20600
+ case N_SOCK:
+ sona = (KA_T)v->v_data;
+ if (read_nson(va, sona, &so))
+ return;
+ break;
+#endif /* solaris>=20600 */
+
+ case N_MNT:
+ /* Information comes from the l_vfs structure. */
+ break;
+ case N_MVFS:
+ if (read_nmn(va, (KA_T)v->v_data, &m))
+ return;
+ break;
+ case N_NFS:
+ if (read_nrn(va, (KA_T)v->v_data, &r))
+ return;
+ break;
+
+#if solaris>=100000
+ case N_NFS4:
+ if (read_nrn4(va, (KA_T)v->v_data, &r4))
+ return;
+ break;
+#endif /* solaris>=100000 */
+
+ case N_NM:
+ if (nns)
+ realvp = (KA_T)nn.nm_filevp;
+
+#if defined(HASNCACHE)
+ Lf->na = (KA_T)nn.nm_filevp;
+#endif /* defined(HASNCACHE) */
+
+ break;
+ case N_FD:
+ break; /* no successor node */
+ case N_FIFO:
+
+ /*
+ * Solaris FIFO vnodes are usually linked to a fifonode. One
+ * exception is a FIFO vnode served by nm_vnodeops; it is linked
+ * to a namenode, and the namenode points to the fifonode.
+ *
+ * Non-pipe fifonodes are linked to a vnode thorough fn_realvp.
+ */
+ if (vty == N_NM && nns) {
+ if (nn.nm_filevp) {
+ if (read_nfn(va, (KA_T)nn.nm_filevp, &f))
+ return;
+ realvp = (KA_T)NULL;
+ vty = N_FIFO;
+ } else {
+ (void) snpf(Namech, Namechl - 1,
+ "FIFO namenode at %s: no fifonode pointer",
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ return;
+ }
+ } else {
+ if (read_nfn(va, (KA_T)v->v_data, &f))
+ return;
+ realvp = (KA_T)f.fn_realvp;
+ }
+ if (!realvp) {
+ Lf->inode = (INODETYPE)(nns ? nn.nm_vattr.va_nodeid : f.fn_ino);
+
+#if solaris>=80000 /* Solaris 8 and above hack! */
+# if defined(_LP64)
+ if (Lf->inode >= (unsigned long)0xbaddcafebaddcafe)
+# else /* !defined(_LP64) */
+ if (Lf->inode >= (unsigned long)0xbaddcafe)
+# endif /* defined(_LP64) */
+
+ Lf->inp_ty = 0;
+ else
+#endif /* solaris>=80000 Solaris 8 and above hack! */
+
+ Lf->inp_ty = 1;
+ enter_dev_ch(print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ if (f.fn_flag & ISPIPE) {
+ (void) snpf(tbuf, sizeof(tbuf), "PIPE");
+ tbufx = (int)strlen(tbuf);
+ } else
+ tbufx = 0;
+
+#if solaris<20500
+ if (f.fn_mate) {
+ (void) snpf(&tbuf[tbufx], sizeof(tbuf) - tbufx, "->%s",
+ print_kptr((KA_T)f.fn_mate, (char *)NULL, 0));
+ tbufx = (int)strlen(tbuf);
+ }
+#else /* solaris>=20500 */
+ if (f.fn_dest) {
+ (void) snpf(&tbuf[tbufx], sizeof(tbuf) - tbufx, "->%s",
+ print_kptr((KA_T)f.fn_dest, (char *)NULL, 0));
+ tbufx = (int)strlen(tbuf);
+ }
+#endif /* solaris<20500 */
+
+ if (tbufx)
+ (void) add_nma(tbuf, tbufx);
+ break;
+ }
+ break;
+
+ case N_HSFS:
+ if (read_nhn(va, (KA_T)v->v_data, &h))
+ return;
+ break;
+ case N_LOFS:
+ llc = 0;
+ do {
+ rvs = 0;
+ if (read_nln(va,
+ llc ? (KA_T)rv.v_data : (KA_T)v->v_data,
+ &lo))
+ {
+ return;
+ }
+ if (!(realvp = (KA_T)lo.lo_vp)) {
+ (void) snpf(Namech, Namechl - 1,
+ "lnode at %s: no real vnode",
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return;
+ }
+ if (read_nvn((KA_T)v->v_data, (KA_T)realvp, &rv))
+ return;
+ rvs = 1;
+ llc++;
+ if ((ka = (KA_T)rv.v_vfsp)
+ && !kread(ka, (char *)&rkv, sizeof(rkv))
+ && ((rfx = rkv.vfs_fstype - 1) >= 0)
+ && (rfx < Fsinfomax)
+ ) {
+ rfxs = 1;
+ } else {
+ rfx = fx;
+ rfxs = fxs;
+ }
+ if (((vty_tmp = vop2ty(&rv, rfx)) == N_LOFS) && (llc > 1000)) {
+ (void) snpf(Namech, Namechl - 1,
+ "lnode at %s: loop > 1000",
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return;
+ }
+ } while (vty_tmp == N_LOFS);
+ break;
+ case N_PCFS:
+ if (read_npn(va, (KA_T)v->v_data, &pc))
+ return;
+ break;
+
+#if solaris>=100000
+ case N_PORT:
+ if (read_nprtn(va, (KA_T)v->v_data, &pn))
+ return;
+ break;
+#endif /* solaris>=100000 */
+
+#if defined(HASPROCFS)
+ case N_PROC:
+ if (read_npi(va, v, &pids))
+ return;
+ break;
+#endif /* defined(HASPROCFS) */
+
+#if solaris>=110000
+ case N_SDEV:
+ if (read_nsdn(va, (KA_T)v->v_data, &sdn, &sdva))
+ return;
+ sdns = 1;
+ break;
+#endif /* solaris>=110000 */
+
+ case N_SAMFS:
+ (void) add_nma(SAMFS_NMA_MSG, (int)strlen(SAMFS_NMA_MSG));
+ break;
+ case N_SHARED:
+ break; /* No more sharedfs information is available. */
+ case N_STREAM:
+ if (read_nsn(va, (KA_T)v->v_data, &s))
+ return;
+ if (vs) {
+ Lf->is_stream = 1;
+
+#if solaris<100000
+ read_mi(vs, (dev_t *)&s.s_dev, (caddr_t)&soso, &so_st, so_ad,
+ &sdp);
+#else /* solaris>=100000 */
+ read_mi(vs, (dev_t *)&s.s_dev, NULL, NULL, NULL, &sdp);
+#endif /* solaris<100000 */
+
+ vs = (KA_T)NULL;
+ }
+ break;
+ case N_TMP:
+ if (read_ntn(va, (KA_T)v->v_data, &t))
+ return;
+ break;
+
+#if defined(HASVXFS)
+ case N_VXFS:
+ if (read_vxnode(va, v, vfs, fx, &vx, Vvops))
+ return;
+ break;
+#endif /* defined(HASVXFS) */
+
+#if defined(HAS_ZFS)
+ case N_ZFS:
+ if (read_nzn(va, (KA_T)v->v_data, &zn))
+ return;
+ zns = 1;
+ break;
+#endif /* defined(HAS_ZFS) */
+
+ case N_REGLR:
+ default:
+ if (read_nin(va, (KA_T)v->v_data, &i))
+ return;
+ ins = 1;
+ }
+/*
+ * If the node has a real vnode pointer, follow it.
+ */
+ if (realvp) {
+ if (rvs) {
+ *v = rv;
+ fx = rfx;
+ fxs = rfxs;
+ }
+ else {
+ if (read_nvn((KA_T)v->v_data, (KA_T)realvp, v))
+ return;
+ else {
+
+#if defined(HASNCACHE)
+ Lf->na = (KA_T)realvp;
+#endif /* defined(HASNCACHE) */
+
+ if ((ka = (KA_T)v->v_vfsp)
+ && !kread(ka, (char *)&kv, sizeof(kv)))
+ {
+ kvs = 1;
+ }
+ if (kvs
+ && ((fx = kv.vfs_fstype - 1) >= 0)
+ && (fx < Fsinfomax)
+ ) {
+ fxs = 1;
+ }
+ }
+ }
+ /*
+ * If the original vnode type is N_STREAM, if there is a stream
+ * pointer and if there is no sdev_node, get the module names.
+ */
+ if (vty == N_STREAM && vs && !sdns) {
+ Lf->is_stream = 1;
+
+#if solaris<100000
+ read_mi(vs, (dev_t *)&s.s_dev, (caddr_t)&soso, &so_st, so_ad,
+ &sdp);
+#else /* solaris>=100000 */
+ read_mi(vs, (dev_t *)&s.s_dev, NULL, NULL, NULL, &sdp);
+#endif /* solaris<100000 */
+
+ vs = (KA_T)NULL;
+ }
+ /*
+ * Get the real vnode's type.
+ */
+ if ((vty = vop2ty(v, fx)) < 0) {
+ if (Ntype != N_FIFO && vs)
+ vty = N_STREAM;
+ else {
+
+#if solaris<100000
+ (void) snpf(Namech, Namechl - 1,
+ "unknown file system type, v_op: %s",
+ print_kptr((KA_T)v->v_op, (char *)NULL, 0));
+#else /* solaris>=100000 */
+ (void) snpf(Namech, Namechl - 1,
+ "unknown file system type (%s), v_op: %s",
+ fxs ? Fsinfo[fx] : "unknown",
+ print_kptr((KA_T)v->v_op, (char *)NULL, 0));
+#endif /* solaris<100000 */
+
+ Namech[Namechl - 1] = '\0';
+ }
+ }
+ if (Ntype == N_NM || Ntype == N_AFS)
+ Ntype = vty;
+ /*
+ * Base further processing on the "real" vnode.
+ */
+ Lf->lock = isvlocked(v);
+ switch (vty) {
+
+#if defined(HAS_AFS)
+ case N_AFS:
+ if (readafsnode(va, v, &an))
+ return;
+ break;
+#endif /* defined(HAS_AFS) */
+
+#if solaris>=20500
+ case N_AUTO:
+
+# if solaris<20600
+ if (read_nan(va, (KA_T)v->v_data, &au))
+# else /* solaris>=20600 */
+ if (read_nan(va, (KA_T)v->v_data, &fnn))
+# endif /* solaris<20600 */
+
+ return;
+ break;
+
+# if solaris>=100000
+ case N_DEV:
+ if (read_ndvn(va, (KA_T)v->v_data, &dv, &dv_dev, &dv_devs))
+ return;
+ dvs = 1;
+ break;
+# endif /* solaris>=100000 */
+
+ case N_DOOR:
+
+# if solaris<20600
+ if (read_ndn(realvp, (KA_T)v->v_data, &dn))
+# else /* solaris>=20600 */
+ if (read_ndn(va, (KA_T)v->v_data, &dn))
+# endif /* solaris<20500 */
+
+ return;
+ dns = 1;
+ break;
+#endif /* solaris>=20500 */
+
+#if defined(HASCACHEFS)
+ case N_CACHE:
+ if (read_ncn(va, (KA_T)v->v_data, &cn))
+ return;
+ break;
+#endif /* defined(HASCACHEFS) */
+
+#if solaris>=100000
+ case N_CTFSADIR:
+ case N_CTFSBUND:
+ case N_CTFSCDIR:
+ case N_CTFSCTL:
+ case N_CTFSEVT:
+ case N_CTFSLATE:
+ case N_CTFSROOT:
+ case N_CTFSSTAT:
+ case N_CTFSSYM:
+ case N_CTFSTDIR:
+ case N_CTFSTMPL:
+ if (read_nctfsn(vty, va, (KA_T)v->v_data, (char *)&ctfs))
+ return;
+ break;
+#endif /* solaris>=100000 */
+
+ case N_HSFS:
+ if (read_nhn(va, (KA_T)v->v_data, &h))
+ return;
+ break;
+ case N_MNT:
+ /* Information comes from the l_vfs structure. */
+ break;
+ case N_MVFS:
+ if (read_nmn(va, (KA_T)v->v_data, &m))
+ return;
+ break;
+ case N_NFS:
+ if (read_nrn(va, (KA_T)v->v_data, &r))
+ return;
+ break;
+
+#if solaris>=100000
+ case N_NFS4:
+ if (read_nrn4(va, (KA_T)v->v_data, &r4))
+ return;
+ break;
+#endif /* solaris>=100000 */
+
+ case N_NM:
+ if (read_nnn(va, (KA_T)v->v_data, &nn))
+ return;
+ nns = 1;
+ break;
+
+#if solaris>=100000
+ case N_PORT:
+ if (read_nprtn(va, (KA_T)v->v_data, &pn))
+ return;
+ break;
+#endif /* solaris>=100000 */
+
+ case N_PCFS:
+ if (read_npn(va, (KA_T)v->v_data, &pc))
+ return;
+ break;
+ case N_SAMFS:
+ (void) add_nma(SAMFS_NMA_MSG, (int)strlen(SAMFS_NMA_MSG));
+
+#if solaris>=110000
+ case N_SDEV:
+ if (read_nsdn(va, (KA_T)v->v_data, &sdn, &sdva))
+ return;
+ if (Lf->is_stream) {
+
+ /*
+ * This stream's real node is an sdev_node, so it's not really
+ * a stream. Reverse prior stream settings.
+ */
+ Lf->is_stream = 0;
+ Namech[0] = '\0';
+ }
+ sdns = 1;
+ break;
+#endif /* solaris>=110000 */
+
+ break;
+
+#if solaris>=20600
+ case N_SOCK:
+ sona = (KA_T)v->v_data;
+ if (read_nson(va, sona, &so))
+ return;
+ break;
+#endif /* solaris>=20600 */
+
+ case N_STREAM:
+ if (vs) {
+ Lf->is_stream = 1;
+
+#if solaris<100000
+ read_mi(vs, (dev_t *)&s.s_dev, (caddr_t)&soso, &so_st, so_ad,
+ &sdp);
+#else /* solaris>=100000 */
+ read_mi(vs, (dev_t *)&s.s_dev, NULL, NULL, NULL, &sdp);
+#endif /* solaris<100000 */
+
+ vs = (KA_T)NULL;
+ }
+ break;
+ case N_TMP:
+ if (read_ntn(va, (KA_T)v->v_data, &t))
+ return;
+ break;
+
+#if defined(HASVXFS)
+ case N_VXFS:
+ if (read_vxnode(va, v, vfs, fx, &vx, Vvops))
+ return;
+ break;
+#endif /* defined(HASVXFS) */
+
+#if defined(HAS_ZFS)
+ case N_ZFS:
+ if (read_nzn(va, (KA_T)v->v_data, &zn))
+ return;
+ zns = 1;
+ break;
+#endif /* defined(HAS_ZFS) */
+
+ case N_REGLR:
+ default:
+ if (read_nin(va, (KA_T)v->v_data, &i))
+ return;
+ ins = 1;
+ }
+ /*
+ * If this is a Solaris loopback node, use the "real" node type.
+ */
+ if (Ntype == N_LOFS)
+ Ntype = vty;
+ }
+/*
+ * Get device and type for printing.
+ */
+ switch (((Ntype == N_FIFO) || (vty == N_SDEV)) ? vty : Ntype) {
+
+#if defined(HAS_AFS)
+ case N_AFS:
+ dev = an.dev;
+ devs = 1;
+ break;
+#endif /* defined(HAS_AFS) */
+
+#if solaris>=20500
+ case N_AUTO:
+ if (kvs) {
+ dev = (dev_t)kv.vfs_fsid.val[0];
+ devs = 1;
+ }
+ break;
+
+# if solaris>=100000
+ case N_DEV:
+ if (dv_devs) {
+ dev = dv_dev;
+ devs = 1;
+ } else if (vfs) {
+ dev = vfs->dev;
+ devs = 1;
+ }
+ rdev = v->v_rdev;
+ rdevs = 1;
+ break;
+# endif /* solaris>=100000 */
+
+ case N_DOOR:
+
+# if solaris<20600
+ if (kvs) {
+ dev = (dev_t)kv.vfs_fsid.val[0];
+ devs = 1;
+ }
+# else /* solaris>=20600 */
+ if (nns) {
+ dev = (dev_t)nn.nm_vattr.va_fsid;
+ devs = 1;
+ } else if (dns) {
+ dev = (dev_t)dn.door_index;
+ devs = 1;
+ }
+# endif /* solaris<20600 */
+
+ break;
+#endif /* solaris>=20500 */
+
+#if defined(HASCACHEFS)
+ case N_CACHE:
+#endif /* defined(HASCACHEFS) */
+
+ case N_HSFS:
+ case N_PCFS:
+ if (kvs) {
+ dev = kv.vfs_dev;
+ devs = 1;
+ }
+ break;
+
+#if solaris>=100000
+ case N_CTFSADIR:
+ case N_CTFSBUND:
+ case N_CTFSCDIR:
+ case N_CTFSCTL:
+ case N_CTFSEVT:
+ case N_CTFSLATE:
+ case N_CTFSROOT:
+ case N_CTFSSTAT:
+ case N_CTFSSYM:
+ case N_CTFSTDIR:
+ case N_CTFSTMPL:
+ if (kvs) {
+ dev = kv.vfs_dev;
+ devs = 1;
+ }
+ break;
+#endif /* solaris>=100000 */
+
+
+ case N_FD:
+ if (kvs) {
+ dev = kv.vfs_dev;
+ devs = 1;
+ }
+ if ((v->v_type == VCHR) || (v->v_type == VBLK)) {
+ rdev = v->v_rdev;
+ rdevs = 1;
+ }
+ break;
+
+ case N_MNT:
+
+#if defined(CVFS_DEVSAVE)
+ if (vfs) {
+ dev = vfs->dev;
+ devs = 1;
+ }
+#endif /* defined(CVFS_DEVSAVE) */
+
+ break;
+ case N_MVFS:
+
+#if defined(CVFS_DEVSAVE)
+ if (vfs) {
+ dev = vfs->dev;
+ devs = 1;
+ }
+#endif /* defined(CVFS_DEVSAVE) */
+
+ break;
+ case N_NFS:
+ dev = r.r_attr.va_fsid;
+ devs = 1;
+ break;
+
+#if solaris>=100000
+ case N_NFS4:
+ dev = r4.r_attr.va_fsid;
+ devs = 1;
+ break;
+#endif /* solaris>=100000 */
+
+ case N_NM:
+ if (nns) {
+ dev = (dev_t)nn.nm_vattr.va_fsid;
+ devs = 1;
+ } else
+ enter_dev_ch(" NMFS");
+ break;
+
+#if solaris>=100000
+ case N_PORT:
+ if (kvs) {
+ dev = kv.vfs_dev;
+ devs = 1;
+ }
+ break;
+#endif /* solaris>=100000 */
+
+
+#if defined(HASPROCFS)
+ case N_PROC:
+ if (kvs) {
+ dev = kv.vfs_dev;
+ devs = 1;
+ }
+ break;
+#endif /* defined(HASPROCFS) */
+
+ case N_SAMFS:
+ if ((v->v_type == VCHR) || (v->v_type == VBLK)) {
+ rdev = v->v_rdev;
+ rdevs = 1;
+ } else if (vfs) {
+ dev = vfs->dev;
+ devs = 1;
+ }
+ break;
+
+#if solaris>=110000
+ case N_SDEV:
+ if (sdns) {
+ dev = sdva.va_fsid;
+ rdev = sdva.va_rdev;
+ devs = rdevs = 1;
+ }
+ if (v->v_type == VDIR) {
+ dev = v->v_rdev;
+ devs = 1;
+ } else {
+ rdev = v->v_rdev;
+ rdevs = 1;
+ }
+ break;
+#endif /* solaris>=110000 */
+
+ case N_SHARED:
+ if (vfs) {
+ dev = vfs->dev;
+ devs = 1;
+ }
+ break;
+
+#if solaris>=20600
+ case N_SOCK:
+ if (so.so_family == AF_UNIX)
+
+ /*
+ * Process an AF_UNIX socket node.
+ */
+
+# if solaris>=110000
+ {
+
+ /*
+ * Process a Solaris >= 11 AF_UNIX socket node:
+ *
+ * Get its sotpi_info_t structure;
+ */
+ if (read_nsti(&so, &sti))
+ return;
+ /*
+ * Get its device numbers. If they are located, start the NAME
+ * column with the device name, followed by "->".
+ */
+ nm = Namech;
+ nmrl = Namechl - 1;
+ Namech[Namechl - 1] = '\0';
+ if (!sdp)
+ sdp = finddev(&DevDev, &sti.sti_dev, LOOKDEV_ALL);
+ if (sdp) {
+ dev = DevDev;
+ rdev = v->v_rdev;
+ trdev = sdp->rdev;
+ devs = rdevs = trdevs = 1;
+ Lf->inode = (INODETYPE)sdp->inode;
+ Lf->inp_ty = 1;
+ (void) snpf(nm, nmrl, "%s", sdp->name);
+ tl = strlen(nm);
+ nm += tl;
+ nmrl -= tl;
+ sep = "->";
+ } else {
+ devs = rdevs = trdevs = 0;
+ sep = "";
+ }
+ /*
+ * Add the socket node's address to the NAME column.
+ */
+ sepl = strlen(sep);
+ if (sona && ((nmrl - sepl) > 0)) {
+ (void) snpf(nm, nmrl, "%s%s", sep,
+ print_kptr(sona, (char *)NULL, 0));
+ tl = strlen(nm);
+ nm += tl;
+ nmrl -= tl;
+ }
+ /*
+ * Add the service type to the NAME column.
+ */
+ switch (sti.sti_serv_type) {
+ case T_CLTS:
+ ty = "dgram";
+ break;
+ case T_COTS:
+ ty = "stream";
+ break;
+ case T_COTS_ORD:
+ ty = "stream-ord";
+ break;
+ default:
+ ty = (char *)NULL;
+ }
+ if (ty && (nmrl > 1)) {
+ (void) snpf(nm, nmrl, " %s", ty);
+ tl = strlen(nm);
+ nm += tl;
+ nmrl -= tl;
+ }
+ /*
+ * Add the vnode and connected addresses to the NAME column,
+ * as indicated by the socket node state.
+ */
+ if ((so.so_state & SS_ISBOUND)
+ && (nmrl > 36)
+ && (sti.sti_ux_laddr.soua_magic == SOU_MAGIC_EXPLICIT)
+ ) {
+ (void) snpf(nm, nmrl, " Vn=%s",
+ print_kptr((KA_T)sti.sti_ux_laddr.soua_vp,
+ (char *)NULL, 0)
+ );
+ tl = strlen(nm);
+ nm += tl;
+ nmrl -= tl;
+ }
+ if ((so.so_state & SS_ISCONNECTED)
+ && (nmrl > 38)
+ && (sti.sti_ux_faddr.soua_magic == SOU_MAGIC_EXPLICIT)
+ ) {
+ (void) snpf(nm, nmrl, " Conn=%s ",
+ print_kptr((KA_T)sti.sti_ux_faddr.soua_vp,
+ (char *)NULL, 0)
+ );
+ tl = strlen(nm);
+ nm += tl;
+ nmrl -= tl;
+ }
+ /*
+ * Put local and connected UNIX addresses in the NAME column, if
+ * they exist and as indicated by the socket node's state.
+ */
+ if ((so.so_state & SS_ISBOUND)
+ && ((len = read_nusa(&sti.sti_laddr, &ua)) > 0)
+ && (nmrl > (len + 5))
+ ) {
+ if (Sfile
+ && is_file_named(ua.sun_path, Ntype, VSOCK, 0))
+ Lf->sf |= SELNM;
+ if (len > nmrl)
+ len = nmrl;
+ if (len > 0) {
+ ua.sun_path[len] = '\0';
+ (void) snpf(nm, nmrl, " Lcl=%s", ua.sun_path);
+ tl = strlen(nm);
+ nm += tl;
+ nmrl -= tl;
+ }
+ }
+ if ((so.so_state & SS_ISCONNECTED)
+ && ((len = read_nusa(&sti.sti_faddr, &ua)) > 0)
+ && (nmrl > (len + 5))
+ ) {
+ if (Sfile
+ && is_file_named(ua.sun_path, Ntype, VSOCK, 0))
+ Lf->sf |= SELNM;
+ if (len > nmrl)
+ len = nmrl;
+ if (len > 0) {
+ ua.sun_path[len] = '\0';
+ (void) snpf(nm, nmrl, " Rem=%s", ua.sun_path);
+ tl = strlen(nm);
+ nm += tl;
+ nmrl -= tl;
+ }
+ }
+ } else {
+
+ /*
+ * Process Solaris >= 11 AF_INET, AF_INET6 and AF_ROUTE VSOCK
+ * nodes.
+ */
+ switch (so.so_family) {
+ case AF_INET:
+ case AF_INET6:
+ case AF_ROUTE:
+ if (process_VSOCK((KA_T)va, v, &so))
+ return;
+ }
+ }
+# else /* solaris<110000 */
+ {
+
+ /*
+ * Process an AF_UNIX socket node for Solaris < 11:
+ * Locate its device numbers;
+ * Enter the sonode address as the device (netstat's local
+ * address);
+ * Get a non-NULL local sockaddr_un and enter it in Namech;
+ * Get a non-NULL foreign sockaddr_un and enter it in Namech;
+ * Check for matches on sockaddr_un.sun_path names.
+ */
+
+ if (!sdp)
+ sdp = finddev(&DevDev,
+
+# if solaris<100000
+ &so.so_vnode.v_rdev,
+# else /* solaris>=100000 */
+ &so.so_dev,
+# endif /* solaris<100000 */
+
+ LOOKDEV_ALL);
+
+ if (sdp) {
+ dev = DevDev;
+
+# if solaris<100000
+ rdev = so.so_vnode.v_rdev;
+# else /* solaris>=100000 */
+ rdev = so.so_dev;
+# endif /* solaris<100000 */
+
+ trdev = sdp->rdev;
+ devs = rdevs = trdevs = 1;
+ Lf->inode = (INODETYPE)sdp->inode;
+ Lf->inp_ty = 1;
+ (void) snpf(Namech, Namechl - 1, "%s", sdp->name);
+ Namech[Namechl - 1] = '\0';
+ } else
+ devs = 0;
+ nl = snl = (int)strlen(Namech);
+
+ if ((len = read_nusa(&so.so_laddr, &ua)))
+ {
+ if (Sfile
+ && is_file_named(ua.sun_path, Ntype, VSOCK, 0))
+ Lf->sf |= SELNM;
+ sepl = Namech[0] ? 2 : 0;
+ if (len > (Namechl - nl - sepl - 1))
+ len = Namechl - nl - sepl - 1;
+ if (len > 0) {
+ ua.sun_path[len] = '\0';
+ (void) snpf(&Namech[nl], Namechl - nl, "%s%s",
+ sepl ? "->" : "", ua.sun_path);
+ nl += (len + sepl);
+ }
+ }
+ if ((len = read_nusa(&so.so_faddr, &ua)))
+ {
+ if (Sfile
+ && is_file_named(ua.sun_path, Ntype, VSOCK, 0))
+ Lf->sf |= SELNM;
+ sepl = Namech[0] ? 2 : 0;
+ if (len > (Namechl - nl - sepl - 1))
+ len = Namechl - nl - sepl - 1;
+ if (len > 0) {
+ ua.sun_path[len] = 0;
+ (void) snpf(&Namech[nl], Namechl - nl, "%s%s",
+ sepl ? "->" : "", ua.sun_path);
+ nl += (len + sepl);
+ }
+ }
+ if ((nl == snl)
+
+# if defined(HASSOUXSOUA)
+ && so.so_ux_laddr.soua_magic == SOU_MAGIC_IMPLICIT
+# else /* !defined(HASSOUXSOUA) */
+ && so.so_ux_laddr.sou_magic == SOU_MAGIC_IMPLICIT
+# endif /* defined(HASSOUXSOUA) */
+
+ ) {
+
+ /*
+ * There are no addresses; this must be a socket pair.
+ * Print its identity.
+ */
+ pa = (struct pairaddr *)&ua;
+ if (!(peer = (KA_T)((int)pa->p)))
+
+# if defined(HASSOUXSOUA)
+ peer = (KA_T)so.so_ux_laddr.soua_vp;
+# else /* !defined(HASSOUXSOUA) */
+ peer = (KA_T)so.so_ux_laddr.sou_vp;
+# endif /* defined(HASSOUXSOUA) */
+
+ if (peer)
+ (void) snpf(ubuf, sizeof(ubuf), "(socketpair: %s)",
+ print_kptr(peer, (char *)NULL, 0));
+ else
+ (void) snpf(ubuf, sizeof(ubuf), "(socketpair)");
+ len = (int)strlen(ubuf);
+ sepl = Namech[0] ? 2 : 0;
+ if (len > (Namechl - nl - sepl - 1))
+ len = Namechl - nl - sepl - 1;
+ if (len > 0) {
+ (void) snpf(&Namech[nl], Namechl - nl, "%s%s",
+ sepl ? "->" : "", ubuf);
+ nl += (len + sepl);
+ }
+ }
+ /*
+ * Add the local and foreign addresses, ala `netstat -f unix` to
+ * the name.
+ */
+
+# if defined(HASSOUXSOUA)
+ soa = (KA_T)so.so_ux_faddr.soua_vp;
+# else /* !defined(HASSOUXSOUA) */
+ soa = (KA_T)so.so_ux_faddr.sou_vp;
+# endif /* defined(HASSOUXSOUA) */
+
+ (void) snpf(ubuf, sizeof(ubuf), "%s(%s%s%s)",
+ Namech[0] ? " " : "",
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0),
+ soa ? "->" : "",
+ soa ? print_kptr(soa, tbuf, sizeof(tbuf)) : "");
+ len = (int)strlen(ubuf);
+ if (len <= (Namechl - nl - 1)) {
+ (void) snpf(&Namech[nl], Namechl - nl, "%s", ubuf);
+ nl += len;
+ }
+ /*
+ * If there is a bound vnode, add its address to the name.
+ */
+
+ if (so.so_ux_bound_vp) {
+ (void) snpf(ubuf, sizeof(ubuf), "%s(Vnode=%s)",
+ Namech[0] ? " " : "",
+ print_kptr((KA_T)so.so_ux_bound_vp, (char *)NULL, 0));
+ len = (int)strlen(ubuf);
+ if (len <= (Namechl - nl - 1)) {
+ (void) snpf(&Namech[nl], Namechl - nl, "%s", ubuf);
+ nl += len;
+ }
+ }
+ }
+# endif /* solaris>=110000 */
+
+ break;
+
+#endif /* solaris>=20600 */
+
+ case N_SPEC:
+
+#if solaris<100000
+ if (((Ntype = vty) == N_STREAM) && so_st) {
+ if (Funix)
+ Lf->sf |= SELUNX;
+ unix_sock = 1;
+ if (so_ad[0]) {
+ if (sdp) {
+ if (vfs) {
+ dev = vfs->dev;
+ devs = 1;
+ }
+ rdev = sdp->rdev;
+ rdevs = 1;
+ Lf->inode = (INODETYPE)sdp->inode;
+ Lf->inp_ty = 1;
+ (void) snpf(ubuf, sizeof(ubuf), "(%s%s%s)",
+ print_kptr(so_ad[0], (char *)NULL, 0),
+ so_ad[1] ? "->" : "",
+ so_ad[1] ? print_kptr(so_ad[1], tbuf, sizeof(tbuf))
+ : "");
+ } else {
+ enter_dev_ch(print_kptr(so_ad[0], (char *)NULL, 0));
+ if (so_ad[1])
+ (void) snpf(ubuf, sizeof(ubuf), "(->%s)",
+ print_kptr(so_ad[1], (char *)NULL, 0));
+ }
+ if (!Lf->nma && (Lf->nma = (char *)
+ malloc((int)strlen(ubuf) + 1)))
+ {
+ (void) snpf(Lf->nma, (int)strlen(ubuf) + 1, "%s", ubuf);
+ }
+ } else if (soso.lux_dev.addr.tu_addr.ino) {
+ if (vfs) {
+ dev = vfs->dev;
+ devs = 1;
+ }
+ rdev = soso.lux_dev.addr.tu_addr.dev;
+ rdevs = 1;
+ } else {
+ int dc, dl, dr;
+
+#if solaris<20400
+ dl = (soso.lux_dev.addr.tu_addr.dev >> 16) & 0xffff;
+ dr = (soso.rux_dev.addr.tu_addr.dev >> 16) & 0xffff;
+#else /* solaris>=20400 */
+ dl = soso.lux_dev.addr.tu_addr.dev & 0xffff;
+ dr = soso.rux_dev.addr.tu_addr.dev & 0xffff;
+#endif /* solaris<20400 */
+
+ dc = (dl << 16) | dr;
+ enter_dev_ch(print_kptr((KA_T)dc, (char *)NULL, 0));
+ devs = 0;
+ }
+ if (soso.laddr.buf && soso.laddr.len == sizeof(ua)) {
+ if (kread((KA_T)soso.laddr.buf, (char *)&ua, sizeof(ua))
+ == 0) {
+ ua.sun_path[sizeof(ua.sun_path) - 1] = '\0';
+ if (ua.sun_path[0]) {
+ if (Sfile
+ && is_file_named(ua.sun_path, Ntype, type, 0))
+ Lf->sf |= SELNM;
+ len = (int)strlen(ua.sun_path);
+ nl = (int)strlen(Namech);
+ sepl = Namech[0] ? 2 : 0;
+ if (len > (Namechl - nl - sepl - 1))
+ len = Namechl - nl - sepl - 1;
+ if (len > 0) {
+ ua.sun_path[len] = '\0';
+ (void) snpf(&Namech[nl], Namechl - nl, "%s%s",
+ sepl ? "->" : "", ua.sun_path);
+ }
+ }
+ }
+ }
+ } else
+#endif /* solaris<100000 */
+
+ {
+ if (vfs) {
+ dev = vfs->dev;
+ devs = 1;
+ }
+ rdev = s.s_dev;
+ rdevs = 1;
+ }
+ break;
+ case N_STREAM:
+ if (vfs) {
+ dev = vfs->dev;
+ devs = 1;
+ }
+ rdev = s.s_dev;
+ rdevs = 1;
+ break;
+ case N_TMP:
+ dev = t.tn_attr.va_fsid;
+ devs = 1;
+ break;
+
+#if defined(HASVXFS)
+ case N_VXFS:
+ dev = vx.dev;
+ devs = vx.dev_def;
+ if ((v->v_type == VCHR) || (v->v_type == VBLK)) {
+ rdev = vx.rdev;
+ rdevs = vx.rdev_def;
+ }
+ break;
+#endif /* defined(HASVXFS) */
+
+#if defined(HAS_ZFS)
+ case N_ZFS:
+ if (zns) {
+ if (!read_nzvfs((KA_T)v->v_data, (KA_T)zn.z_zfsvfs, &zvfs)
+ && zvfs.z_vfs
+ && !kread((KA_T)zvfs.z_vfs, (char *)&zgvfs, sizeof(zgvfs))
+ ) {
+ dev = zgvfs.vfs_dev;
+ devs = 1;
+ }
+ }
+ if ((v->v_type == VCHR) || (v->v_type == VBLK)) {
+ rdev = v->v_rdev;
+ rdevs = 1;
+ }
+ break;
+#endif /* defined(HAS_ZFS) */
+
+ default:
+ if (ins) {
+ dev = i.i_dev;
+ devs = 1;
+ } else if (nns) {
+ dev = nn.nm_vattr.va_fsid;
+ devs = 1;
+ } else if (vfs) {
+ dev = vfs->dev;
+ devs = 1;
+ }
+ if ((v->v_type == VCHR) || (v->v_type == VBLK)) {
+ rdev = v->v_rdev;
+ rdevs = 1;
+ }
+ }
+ type = v->v_type;
+ if (devs && vfs && !vfs->dir) {
+ (void) completevfs(vfs, &dev);
+
+#if defined(HAS_AFS)
+ if (vfs->dir && (Ntype == N_AFS || vty == N_AFS) && !AFSVfsp)
+ AFSVfsp = (KA_T)v->v_vfsp;
+#endif /* defined(HAS_AFS) */
+
+ }
+/*
+ * Obtain the inode number.
+ */
+ switch (vty) {
+
+#if defined(HAS_AFS)
+ case N_AFS:
+ if (an.ino_st) {
+ Lf->inode = (INODETYPE)an.inode;
+ Lf->inp_ty = 1;
+ }
+ break;
+#endif /* defined(HAS_AFS) */
+
+#if solaris>=20500
+ case N_AUTO:
+
+# if solaris<20600
+ Lf->inode = (INODETYPE)au.an_nodeid;
+# else /* solaris>=20600 */
+ Lf->inode = (INODETYPE)fnn.fn_nodeid;
+# endif /* solaris<20600 */
+
+ Lf->inp_ty = 1;
+ break;
+
+# if solaris>=100000
+ case N_DEV:
+ if (dvs) {
+ Lf->inode = (INODETYPE)dv.dv_ino;
+ Lf->inp_ty = 1;
+ }
+ break;
+# endif /* solaris>=100000 */
+
+ case N_DOOR:
+ if (nns && (Lf->inode = (INODETYPE)nn.nm_vattr.va_nodeid)) {
+ Lf->inp_ty = 1;
+ break;
+ }
+ if (dns) {
+ if ((Lf->inode = (INODETYPE)dn.door_index))
+ Lf->inp_ty = 1;
+ }
+ break;
+#endif /* solaris>=20500 */
+
+#if defined(HASCACHEFS)
+ case N_CACHE:
+ Lf->inode = (INODETYPE)cn.c_fileno;
+ Lf->inp_ty = 1;
+ break;
+#endif /* defined(HASCACHEFS) */
+
+#if solaris>=100000
+ case N_CTFSADIR:
+ case N_CTFSBUND:
+ case N_CTFSCDIR:
+ case N_CTFSCTL:
+ case N_CTFSEVT:
+ case N_CTFSLATE:
+ case N_CTFSROOT:
+ case N_CTFSSTAT:
+ case N_CTFSSYM:
+ case N_CTFSTDIR:
+ case N_CTFSTMPL:
+ /* Method of computing CTFS inode not known. */
+ break;
+#endif /* solaris>=10000 */
+
+ case N_FD:
+ if (v->v_type == VDIR)
+ Lf->inode = (INODETYPE)2;
+ else
+ Lf->inode = (INODETYPE)(GET_MIN_DEV(v->v_rdev) * 100);
+ Lf->inp_ty = 1;
+ break;
+ case N_HSFS:
+ Lf->inode = (INODETYPE)h.hs_nodeid;
+ Lf->inp_ty = 1;
+ break;
+
+ case N_MNT:
+
+#if defined(HASFSINO)
+ if (vfs) {
+ Lf->inode = vfs->fs_ino;
+ Lf->inp_ty = 1;
+ }
+#endif /* defined(HASFSINO) */
+
+ break;
+ case N_MVFS:
+ Lf->inode = (INODETYPE)m.m_ino;
+ Lf->inp_ty = 1;
+ break;
+ case N_NFS:
+ Lf->inode = (INODETYPE)r.r_attr.va_nodeid;
+ Lf->inp_ty = 1;
+ break;
+
+#if solaris>=100000
+ case N_NFS4:
+ Lf->inode = (INODETYPE)r4.r_attr.va_nodeid;
+ Lf->inp_ty = 1;
+ break;
+#endif /* solaris>=100000 */
+
+ case N_NM:
+ Lf->inode = (INODETYPE)nn.nm_vattr.va_nodeid;
+ Lf->inp_ty = 1;
+ break;
+
+#if defined(HASPROCFS)
+ case N_PROC:
+
+ /*
+ * The proc file system inode number is defined when the
+ * prnode is read.
+ */
+ break;
+#endif /* defined(HASPROCFS) */
+
+ case N_PCFS:
+ if (kvs && kv.vfs_data
+ && !kread((KA_T)kv.vfs_data, (char *)&pcfs, sizeof(pcfs))) {
+
+#if solaris>=70000
+# if defined(HAS_PC_DIRENTPERSEC)
+ Lf->inode = (INODETYPE)pc_makenodeid(pc.pc_eblkno,
+ pc.pc_eoffset,
+ pc.pc_entry.pcd_attr,
+ IS_FAT32(&pcfs)
+ ? ltohs(pc.pc_entry.pcd_scluster_lo) |
+ (ltohs(pc.pc_entry.un.pcd_scluster_hi) << 16)
+ : ltohs(pc.pc_entry.pcd_scluster_lo),
+ pc_direntpersec(&pcfs));
+# else /* !defined(HAS_PC_DIRENTPERSEC) */
+ Lf->inode = (INODETYPE)pc_makenodeid(pc.pc_eblkno,
+ pc.pc_eoffset,
+ pc.pc_entry.pcd_attr,
+ IS_FAT32(&pcfs)
+ ? ltohs(pc.pc_entry.pcd_scluster_lo) |
+ (ltohs(pc.pc_entry.un.pcd_scluster_hi) << 16)
+ : ltohs(pc.pc_entry.pcd_scluster_lo),
+ pcfs.pcfs_entps);
+# endif /* defined(HAS_PC_DIRENTPERSEC) */
+#else /* solaris<70000 */
+ Lf->inode = (INODETYPE)pc_makenodeid(pc.pc_eblkno,
+ pc.pc_eoffset,
+ &pc.pc_entry,
+ pcfs.pcfs_entps);
+#endif /* solaris>=70000 */
+
+ Lf->inp_ty = 1;
+ }
+ break;
+
+ case N_REGLR:
+ if (nns) {
+ if ((Lf->inode = (INODETYPE)nn.nm_vattr.va_nodeid))
+ Lf->inp_ty = 1;
+ } else if (ins) {
+ if ((Lf->inode = (INODETYPE)i.i_number))
+ Lf->inp_ty = 1;
+ }
+ break;
+ case N_SAMFS:
+ break; /* No more SAM-FS information is available. */
+
+#if solaris>=110000
+ case N_SDEV:
+ if (sdns) {
+ Lf->inode = (INODETYPE)sdva.va_nodeid;
+ Lf->inp_ty = 1;
+ }
+ break;
+#endif /* solaris>=110000 */
+
+ case N_SHARED:
+ (void) snpf(Lf->iproto, sizeof(Lf->iproto), "SHARED");
+ Lf->inp_ty = 2;
+ break;
+ case N_STREAM:
+
+#if solaris<100000
+ if (so_st && soso.lux_dev.addr.tu_addr.ino) {
+ if (Lf->inp_ty) {
+ nl = Lf->nma ? (int)strlen(Lf->nma) : 0;
+ (void) snpf(ubuf, sizeof(ubuf),
+ "%s(Inode=%lu)", nl ? " " : "",
+ (unsigned long)soso.lux_dev.addr.tu_addr.ino);
+ len = nl + (int)strlen(ubuf) + 1;
+ if (Lf->nma)
+ Lf->nma = (char *) realloc(Lf->nma, len);
+ else
+ Lf->nma = (char *) malloc(len);
+ if (Lf->nma)
+ (void) snpf(&Lf->nma[nl], len - nl, "%s", ubuf);
+ } else {
+ Lf->inode = (INODETYPE)soso.lux_dev.addr.tu_addr.ino;
+ Lf->inp_ty = 1;
+ }
+ }
+#endif /* solaris<100000 */
+
+ break;
+ case N_TMP:
+ Lf->inode = (INODETYPE)t.tn_attr.va_nodeid;
+ Lf->inp_ty = 1;
+ break;
+
+#if defined(HASVXFS)
+ case N_VXFS:
+ if (vx.ino_def) {
+ Lf->inode = (INODETYPE)vx.ino;
+ Lf->inp_ty = 1;
+ } else if (type == VCHR)
+ pnl = 1;
+ break;
+#endif /* defined(HASVXFS) */
+
+#if defined(HAS_ZFS)
+ case N_ZFS:
+ if (zns) {
+ Lf->inode = (INODETYPE)zn.z_id;
+ Lf->inp_ty = 1;
+ }
+ break;
+#endif /* defined(HAS_ZFS) */
+
+ }
+/*
+ * Obtain the file size.
+ */
+ if (Foffset)
+ Lf->off_def = 1;
+ else {
+ switch (Ntype) {
+
+#if defined(HAS_AFS)
+ case N_AFS:
+ Lf->sz = (SZOFFTYPE)an.size;
+ Lf->sz_def = 1;
+ break;
+#endif /* defined(HAS_AFS) */
+
+#if solaris>=20500
+ case N_AUTO:
+
+# if solaris<20600
+ Lf->sz = (SZOFFTYPE)au.an_size;
+# else /* solaris >=20600 */
+ Lf->sz = (SZOFFTYPE)fnn.fn_size;
+# endif /* solaris < 20600 */
+
+ Lf->sz_def = 1;
+ break;
+#endif /* solaris>=20500 */
+
+#if defined(HASCACHEFS)
+ case N_CACHE:
+ Lf->sz = (SZOFFTYPE)cn.c_size;
+ Lf->sz_def = 1;
+ break;
+#endif /* defined(HASCACHEFS) */
+
+#if solaris>=100000
+ case N_CTFSADIR:
+ case N_CTFSBUND:
+ case N_CTFSCDIR:
+ case N_CTFSCTL:
+ case N_CTFSEVT:
+ case N_CTFSLATE:
+ case N_CTFSROOT:
+ case N_CTFSSTAT:
+ case N_CTFSSYM:
+ case N_CTFSTDIR:
+ case N_CTFSTMPL:
+ /* Method of computing CTFS size not known. */
+ break;
+#endif /* solaris>=100000 */
+
+ case N_FD:
+ if (v->v_type == VDIR)
+ Lf->sz = (Unof + 2) * 16;
+ else
+ Lf->sz = (unsigned long)0;
+ Lf->sz_def = 1;
+ break;
+
+#if solaris>=20600
+ case N_SOCK:
+ Lf->off_def = 1;
+ break;
+#endif /* solaris>=20600 */
+
+ case N_HSFS:
+ Lf->sz = (SZOFFTYPE)h.hs_dirent.ext_size;
+ Lf->sz_def = 1;
+ break;
+ case N_NM:
+ Lf->sz = (SZOFFTYPE)nn.nm_vattr.va_size;
+ Lf->sz_def = 1;
+ break;
+
+# if solaris>=100000
+ case N_DEV:
+ if (!Fsize)
+ Lf->off_def = 1;
+ break;
+# endif /* solaris>=100000 */
+
+ case N_DOOR:
+ case N_FIFO:
+ if (!Fsize)
+ Lf->off_def = 1;
+ break;
+ case N_MNT:
+
+#if defined(CVFS_SZSAVE)
+ if (vfs) {
+ Lf->sz = (SZOFFTYPE)vfs->size;
+ Lf->sz_def = 1;
+ } else
+#endif /* defined(CVFS_SZSAVE) */
+
+ Lf->off_def = 1;
+ break;
+ case N_MVFS:
+ /* The location of file size isn't known. */
+ break;
+ case N_NFS:
+ if ((type == VCHR || type == VBLK) && !Fsize)
+ Lf->off_def = 1;
+ else {
+ Lf->sz = (SZOFFTYPE)r.r_size;
+ Lf->sz_def = 1;
+ }
+ break;
+
+#if solaris>=100000
+ case N_NFS4:
+ if ((type == VCHR || type == VBLK) && !Fsize)
+ Lf->off_def = 1;
+ else {
+ Lf->sz = (SZOFFTYPE)r4.r_size;
+ Lf->sz_def = 1;
+ }
+ break;
+#endif /* solaris>=100000 */
+
+ case N_PCFS:
+ Lf->sz = (SZOFFTYPE)pc.pc_size;
+ Lf->sz_def = 1;
+ break;
+
+#if solaris>=100000
+ case N_PORT:
+ Lf->sz = (SZOFFTYPE)pn.port_curr;
+ Lf->sz_def = 1;
+ break;
+#endif /* solaris>=100000 */
+
+
+#if defined(HASPROCFS)
+ case N_PROC:
+
+ /*
+ * The proc file system size is defined when the
+ * prnode is read.
+ */
+ break;
+#endif /* defined(HASPROCFS) */
+
+ case N_REGLR:
+ if (type == VREG || type == VDIR) {
+ if (ins | nns) {
+ Lf->sz = (SZOFFTYPE)(nns ? nn.nm_vattr.va_size
+ : i.i_size);
+ Lf->sz_def = 1;
+ }
+ } else if ((type == VCHR || type == VBLK) && !Fsize)
+ Lf->off_def = 1;
+ break;
+
+#if solaris>=110000
+ case N_SDEV:
+ if (sdns) {
+ if (type == VREG || type == VDIR) {
+ Lf->sz = (SZOFFTYPE)sdva.va_size;
+ Lf->sz_def = 1;
+ } else if ((type == VCHR || type == VBLK) && !Fsize)
+ Lf->off_def = 1;
+ }
+ break;
+#endif /* solaris>=110000 */
+
+ case N_SAMFS:
+ break; /* No more SAM-FS information is available. */
+ case N_SHARED:
+ break; /* No more sharedfs information is available. */
+ case N_STREAM:
+ if (!Fsize)
+ Lf->off_def = 1;
+ break;
+ case N_TMP:
+ Lf->sz = (SZOFFTYPE)t.tn_attr.va_size;
+ Lf->sz_def = 1;
+ break;
+
+#if defined(HASVXFS)
+ case N_VXFS:
+ if (type == VREG || type == VDIR) {
+ Lf->sz = (SZOFFTYPE)vx.sz;
+ Lf->sz_def = vx.sz_def;
+ } else if ((type == VCHR || type == VBLK) && !Fsize)
+ Lf->off_def = 1;
+ break;
+#endif /* defined(HASVXFS) */
+
+#if defined(HAS_ZFS)
+ case N_ZFS:
+ if (zns) {
+ if (type == VREG || type == VDIR) {
+ Lf->sz = (SZOFFTYPE)zn.z_size;
+ Lf->sz_def = 1;
+ } else if ((type == VCHR || type == VBLK) && !Fsize)
+ Lf->off_def = 1;
+ }
+ break;
+#endif /* defined(HAS_ZFS) */
+
+ }
+ }
+/*
+ * Record link count.
+ */
+
+#if !defined(HASXOPT)
+ if (Fnlink)
+#endif /* !defined(HASXOPT) */
+
+ {
+ switch (Ntype) {
+
+#if defined(HAS_AFS)
+ case N_AFS:
+ Lf->nlink = an.nlink;
+ Lf->nlink_def = an.nlink_st;
+ break;
+#endif /* defined(HAS_AFS) */
+
+#if solaris>=20500
+ case N_AUTO:
+ break;
+
+# if defined(HASCACHEFS)
+ case N_CACHE:
+ Lf->nlink = (long)cn.c_attr.va_nlink;
+ Lf->nlink_def = 1;
+ break;
+# endif /* defined(HASCACHEFS) */
+
+#endif /* solaris>=20500 */
+
+#if solaris>=100000
+ case N_CTFSADIR:
+ case N_CTFSBUND:
+ case N_CTFSCDIR:
+ case N_CTFSCTL:
+ case N_CTFSEVT:
+ case N_CTFSLATE:
+ case N_CTFSROOT:
+ case N_CTFSSTAT:
+ case N_CTFSSYM:
+ case N_CTFSTDIR:
+ case N_CTFSTMPL:
+ /* Method of computing CTFS link count not known. */
+ break;
+#endif /* solaris>=100000 */
+
+ case N_FD:
+ Lf->nlink = (v->v_type == VDIR) ? 2 : 1;
+ Lf->nlink_def = 1;
+ break;
+
+#if solaris>=20600
+ case N_SOCK: /* no link count */
+ break;
+#endif /* solaris>=20600 */
+
+ case N_HSFS:
+ Lf->nlink = (long)h.hs_dirent.nlink;
+ Lf->nlink_def = 1;
+ break;
+ case N_NM:
+ Lf->nlink = (long)nn.nm_vattr.va_nlink;
+ Lf->nlink_def = 1;
+ break;
+
+# if solaris>=100000
+ case N_DEV:
+ if (dvs) {
+ Lf->nlink = (long)dv.dv_nlink;
+ Lf->nlink_def = 1;
+ }
+ break;
+# endif /* solaris>=100000 */
+
+ case N_DOOR:
+ Lf->nlink = (long)v->v_count;
+ Lf->nlink_def = 1;
+ break;
+ case N_FIFO:
+ break;
+ case N_MNT:
+
+#if defined(CVFS_NLKSAVE)
+ if (vfs) {
+ Lf->nlink = (long)vfs->nlink;
+ Lf->nlink_def = 1;
+ }
+#endif /* defined(CVFS_NLKSAVE) */
+
+ break;
+ case N_MVFS: /* no link count */
+ break;
+ case N_NFS:
+ Lf->nlink = (long)r.r_attr.va_nlink;
+ Lf->nlink_def = 1;
+ break;
+
+#if solaris>=100000
+ case N_NFS4:
+ Lf->nlink = (long)r4.r_attr.va_nlink;
+ Lf->nlink_def = 1;
+ break;
+#endif /* solaris>=100000 */
+
+ case N_PCFS:
+ break;
+
+#if defined(HASPROCFS)
+ case N_PROC:
+ break;
+#endif /* defined(HASPROCFS) */
+
+ case N_REGLR:
+ if (ins) {
+ Lf->nlink = (long)i.i_nlink;
+ Lf->nlink_def = 1;
+ }
+ break;
+ case N_SAMFS:
+ break; /* No more SAM-FS information is available. */
+
+#if solaris>=110000
+ case N_SDEV:
+ if (sdns) {
+ Lf->nlink = (long)sdva.va_nlink;
+ Lf->nlink_def = 1;
+ }
+ break;
+#endif /* solaris>=110000 */
+
+ case N_SHARED:
+ break; /* No more sharedfs information is available. */
+ case N_STREAM:
+ break;
+ case N_TMP:
+ Lf->nlink = (long)t.tn_attr.va_nlink;
+ Lf->nlink_def = 1;
+ break;
+
+#if defined(HASVXFS)
+ case N_VXFS:
+ Lf->nlink = vx.nl;
+ Lf->nlink_def = vx.nl_def;
+ break;
+#endif /* defined(HASVXFS) */
+
+#if defined(HAS_ZFS)
+ case N_ZFS:
+ if (zns) {
+ Lf->nlink = (long)MIN(zn.z_links, UINT32_MAX);
+ Lf->nlink_def = 1;
+ }
+ break;
+#endif /* defined(HAS_ZFS) */
+
+ }
+ if (Nlink && Lf->nlink_def && (Lf->nlink < Nlink))
+ Lf->sf |= SELNLINK;
+ }
+
+#if defined(HASVXFS)
+/*
+ * Record a VxFS file.
+ */
+
+# if defined(HASVXFSDNLC)
+ Lf->is_vxfs = (Ntype == N_VXFS) ? 1 : 0;
+# endif /* defined(HASVXFSDNLC) */
+#endif /* defined(HASVXFS) */
+
+/*
+ * Record an NFS selection.
+ */
+ if (Fnfs) {
+ if ((Ntype == N_NFS) || (Ntype == N_NFS4))
+ Lf->sf |= SELNFS;
+ }
+
+#if solaris>=20500
+/*
+ * If this is a Solaris 2.5 and greater autofs entry, save the autonode name
+ * (less than Solaris 2.6) or fnnode name (Solaris 2.6 and greater).
+ */
+ if (Ntype == N_AUTO && !Namech[0]) {
+
+# if solaris<20600
+ if (au.an_name[0])
+ (void) snpf(Namech, Namechl - 1, "%s", au.an_name);
+ Namech[Namechl - 1] = '\0';
+# else /* solaris>=20600 */
+ if (fnn.fn_name
+ && (len = fnn.fn_namelen) > 0
+ && len < (Namechl - 1))
+ {
+ if (kread((KA_T)fnn.fn_name, Namech, len))
+ Namech[0] = '\0';
+ else
+ Namech[len] = '\0';
+ }
+# endif /* solaris<20600 */
+
+ }
+/*
+ * If there is no local virtual file system pointer, or if its directory and
+ * file system names are NULL, and if there is a namenode, and if we're using
+ * the device number from it, see if its nm_mountpt vnode pointer leads to a
+ * local virtual file system structure with non-NULL directory and file system
+ * names. If it does, switch to that local virtual file system pointer.
+ */
+ if (nns && (!vfs || (!vfs->dir && !vfs->fsname))
+ && devs && (dev == nn.nm_vattr.va_fsid)
+ && nn.nm_mountpt)
+ {
+ if (!readvnode((KA_T)nn.nm_mountpt, &fv) && fv.v_vfsp) {
+ if ((nvfs = readvfs((KA_T)fv.v_vfsp, (struct vfs *)NULL,
+ nn.nm_filevp))
+ && !nvfs->dir)
+ {
+ (void) completevfs(nvfs, &dev);
+ }
+
+# if defined(HASNCACHE)
+ if (nvfs && nvfs->dir && nvfs->fsname) {
+ fa = (char *)NULL;
+ vfs = nvfs;
+ }
+# endif /* defined(HASNCACHE) */
+
+ }
+ }
+
+# if defined(HASNCACHE)
+/*
+ * If there's a namenode and its device and node number match this one,
+ * use the nm_mountpt's address for name cache lookups.
+ */
+ if (nns && devs && (dev == nn.nm_vattr.va_fsid) && (Lf->inp_ty == 1)
+ && (Lf->inode == (INODETYPE)nn.nm_vattr.va_nodeid))
+ Lf->na = (KA_T)nn.nm_mountpt;
+# endif /* defined(HASNCACHE) */
+#endif /* solaris>=20500 */
+
+/*
+ * Save the file system names.
+ */
+ if (vfs) {
+ Lf->fsdir = vfs->dir;
+ Lf->fsdev = vfs->fsname;
+
+#if defined(HASMNTSTAT)
+ Lf->mnt_stat = vfs->mnt_stat;
+#endif /* defined(HASMNTSTAT) */
+
+ if (!Lf->fsdir && !Lf->fsdev && kvs && fxs) {
+
+ /*
+ * The file system names are unknown.
+ *
+ * Set the file system device to the file system type and clear
+ * the doubtful device numbers.
+ */
+ Lf->fsdev = Fsinfo[fx];
+ devs = 0;
+ rdevs = 0;
+ }
+
+#if defined(HASFSINO)
+ else
+ Lf->fs_ino = vfs->fs_ino;
+#endif /* defined(HASFSINO) */
+
+ }
+/*
+ * Save the device numbers, and their states.
+ *
+ * Format the vnode type, and possibly the device name.
+ */
+ switch (type) {
+
+ case VNON:
+ ty ="VNON";
+ Lf->dev = dev;
+ Lf->dev_def = devs;
+ Lf->rdev = rdev;
+ Lf->rdev_def = rdevs;
+ break;
+ case VREG:
+ case VDIR:
+ ty = (type == VREG) ? "VREG" : "VDIR";
+ Lf->dev = dev;
+ Lf->dev_def = devs;
+ Lf->rdev = rdev;
+ Lf->rdev_def = rdevs;
+ break;
+ case VBLK:
+ ty = "VBLK";
+ Lf->dev = dev;
+ Lf->dev_def = devs;
+ Lf->rdev = rdev;
+ Lf->rdev_def = rdevs;
+ Ntype = N_BLK;
+ break;
+ case VCHR:
+ Lf->dev = dev;
+ Lf->dev_def = devs;
+ Lf->rdev = rdev;
+ Lf->rdev_def = rdevs;
+ if (unix_sock) {
+ ty = "unix";
+ break;
+ }
+ ty = "VCHR";
+ if (Lf->is_stream == 0 && Lf->is_com == 0)
+ Ntype = N_CHR;
+ break;
+
+#if solaris>=20500
+ case VDOOR:
+ Lf->dev = dev;
+ Lf->dev_def = devs;
+ Lf->rdev = rdev;
+ Lf->rdev_def = rdevs;
+ ty = "DOOR";
+ if (dns)
+ (void) idoorkeep(&dn);
+ break;
+#endif /* solaris>=20500 */
+
+ case VLNK:
+ ty = "VLNK";
+ Lf->dev = dev;
+ Lf->dev_def = devs;
+ Lf->rdev = rdev;
+ Lf->rdev_def = rdevs;
+ break;
+
+#if solaris>=100000
+ case VPORT:
+ ty = "PORT";
+ Lf->dev = dev;
+ Lf->dev_def = devs;
+ Lf->rdev = rdev;
+ Lf->rdev_def = rdevs;
+ break;
+#endif /* solaris>=100000 */
+
+#if solaris>=20600
+ case VPROC:
+
+ /*
+ * The proc file system type is defined when the prnode is read.
+ */
+ Lf->dev = dev;
+ Lf->dev_def = devs;
+ Lf->rdev = rdev;
+ Lf->rdev_def = rdevs;
+ ty = (char *)NULL;
+ break;
+#endif /* solaris>=20600 */
+
+#if defined(HAS_VSOCK)
+ case VSOCK:
+
+# if solaris>=20600
+ if (so.so_family == AF_UNIX) {
+ ty = "unix";
+ if (Funix)
+ Lf->sf |= SELUNX;
+ } else {
+ if (so.so_family == AF_INET) {
+
+# if defined(HASIPv6)
+ ty = "IPv4";
+# else /* !defined(HASIPv6) */
+ ty = "inet";
+# endif /* defined(HASIPv6) */
+
+ (void) snpf(Namech, Namechl - 1, printsockty(so.so_type));
+ Namech[Namechl - 1] = '\0';
+ if (TcpStIn || UdpStIn || TcpStXn || UdpStXn)
+ Lf->sf |= SELEXCLF;
+ else if (Fnet && (FnetTy != 6))
+ Lf->sf |= SELNET;
+ }
+
+# if defined(HASIPv6)
+ else if (so.so_family == AF_INET6) {
+ ty = "IPv6";
+ (void) snpf(Namech, Namechl - 1, printsockty(so.so_type));
+ Namech[Namechl - 1] = '\0';
+ if (TcpStIn || UdpStIn || TcpStXn || UdpStXn)
+ Lf->sf |= SELEXCLF;
+ else if (Fnet && (FnetTy != 4))
+ Lf->sf |= SELNET;
+ }
+# endif /* defined(HASIPv6) */
+
+ else {
+ ty = "sock";
+ (void) printunkaf(so.so_family, 0);
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, ", %s", printsockty(so.so_type));
+ }
+ }
+# endif /* solaris>=20600 */
+
+ Lf->dev = dev;
+ Lf->dev_def = devs;
+ Lf->rdev = rdev;
+ Lf->rdev_def = rdevs;
+ break;
+#endif /* defined(HAS_VSOCK) */
+
+ case VBAD:
+ ty = "VBAD";
+ Lf->dev = dev;
+ Lf->dev_def = devs;
+ Lf->rdev = rdev;
+ Lf->rdev_def = rdevs;
+ break;
+ case VFIFO:
+ ty = "FIFO";
+ if (!Lf->dev_ch || Lf->dev_ch[0] == '\0') {
+ Lf->dev = dev;
+ Lf->dev_def = devs;
+ Lf->rdev = rdev;
+ Lf->rdev_def = rdevs;
+ }
+ break;
+ default:
+ Lf->dev = dev;
+ Lf->dev_def = devs;
+ Lf->rdev = rdev;
+ Lf->rdev_def = rdevs;
+ (void) snpf(Lf->type, sizeof(Lf->type), "%04o", (type & 0xfff));
+ ty = (char *)NULL;
+ }
+ if (ty)
+ (void) snpf(Lf->type, sizeof(Lf->type), "%s", ty);
+ Lf->ntype = Ntype;
+/*
+ * If this a Solaris common vnode/snode void some information.
+ */
+ if (Lf->is_com)
+ Lf->sz_def = Lf->inp_ty = 0;
+/*
+ * If a file attach description remains, put it in the NAME column addition.
+ */
+ if (fa)
+ (void) add_nma(fa, fal);
+
+#if defined(HASBLKDEV)
+/*
+ * If this is a VBLK file and it's missing an inode number, try to
+ * supply one.
+ */
+ if ((Lf->inp_ty == 0) && (type == VBLK))
+ find_bl_ino();
+#endif /* defined(HASBLKDEV) */
+
+/*
+ * If this is a VCHR file and it's missing an inode number, try to
+ * supply one.
+ */
+ if ((Lf->inp_ty == 0) && (type == VCHR)) {
+ find_ch_ino();
+ /*
+ * If the VCHR inode number still isn't known and this is a COMMON
+ * vnode file or a stream, or if a pseudo node ID lookup has been
+ * requested, see if an inode number can be derived from a pseudo
+ * or clone device node.
+ *
+ * If it can, save the pseudo or clone device for temporary
+ * use when searching for a match with a named file argument.
+ */
+ if ((Lf->inp_ty == 0) && (Lf->is_com || Lf->is_stream || pnl)
+ && (Clone || Pseudo))
+ {
+ if (!sdp) {
+ if (rdevs || devs) {
+ if (Lf->is_stream && !pnl)
+ sdp = finddev(devs ? &dev : &DevDev,
+ rdevs ? &rdev : &Lf->dev,
+ LOOKDEV_CLONE);
+ else
+ sdp = finddev(devs ? &dev : &DevDev,
+ rdevs ? &rdev : &Lf->dev,
+ LOOKDEV_PSEUDO);
+ if (!sdp)
+ sdp = finddev(devs ? &dev : &DevDev,
+ rdevs ? &rdev : &Lf->dev,
+ LOOKDEV_ALL);
+ if (sdp) {
+ if (!rdevs) {
+ Lf->rdev = Lf->dev;
+ Lf->rdev_def = rdevs = 1;
+ }
+ if (!devs) {
+ Lf->dev = DevDev;
+ devs = Lf->dev_def = 1;
+ }
+ }
+ }
+ } else {
+
+ /*
+ * A local device structure has been located. Make sure
+ * that it's accompanied by device settings.
+ */
+ if (!devs && vfs) {
+ dev = Lf->dev = vfs->dev;
+ devs = Lf->dev_def = 1;
+ }
+ if (!rdevs) {
+ Lf->rdev = rdev = sdp->rdev;
+ Lf->rdev_def = rdevs = 1;
+ }
+ }
+ if (sdp) {
+
+ /*
+ * Process the local device information.
+ */
+ trdev = sdp->rdev;
+ Lf->inode = sdp->inode;
+ Lf->inp_ty = trdevs = 1;
+ if (!Namech[0] || Lf->is_com) {
+ (void) snpf(Namech, Namechl - 1, "%s", sdp->name);
+ Namech[Namechl - 1] = '\0';
+ }
+ if (Lf->is_com && !Lf->nma) {
+ len = (int)strlen("(COMMON)") + 1;
+ if (!(Lf->nma = (char *) malloc(len))) {
+ (void) fprintf(stderr,
+ "%s: no space for (COMMON): PID %d; FD %s\n",
+ Pn, Lp->pid, Lf->fd);
+ Exit(1);
+ }
+ (void) snpf(Lf->nma, len, "(COMMON)");
+ }
+ }
+ }
+ }
+/*
+ * Record stream status.
+ */
+ if (Lf->inp_ty == 0 && Lf->is_stream && strcmp(Lf->iproto, "STR") == 0)
+ Lf->inp_ty = 2;
+/*
+ * Test for specified file.
+ */
+
+#if defined(HASPROCFS)
+ if (Ntype == N_PROC) {
+ if (Procsrch) {
+ Procfind = 1;
+ Lf->sf |= SELNM;
+ } else {
+ for (pfi = Procfsid; pfi; pfi = pfi->next) {
+ if ((pfi->pid && pfi->pid == pids.pid_id)
+
+# if defined(HASPINODEN)
+ || (Lf->inp_ty == 1 && Lf->inode == pfi->inode)
+# endif /* defined(HASPINODEN) */
+
+ ) {
+ pfi->f = 1;
+ if (!Namech[0]) {
+ (void) snpf(Namech, Namechl - 1, "%s", pfi->nm);
+ Namech[Namechl - 1] = '\0';
+ }
+ Lf->sf |= SELNM;
+ break;
+ }
+ }
+ }
+ } else
+#endif /* defined(HASPROCFS) */
+
+ {
+ if (Sfile) {
+ if (trdevs) {
+ rdev = Lf->rdev;
+ Lf->rdev = trdev;
+ tdef = Lf->rdev_def;
+ Lf->rdev_def = 1;
+ }
+ if (is_file_named(NULL, Ntype, type, 1))
+ Lf->sf |= SELNM;
+ if (trdevs) {
+ Lf->rdev = rdev;
+ Lf->rdev_def = tdef;
+ }
+ }
+ }
+/*
+ * Enter name characters.
+ */
+ if (Namech[0])
+ enter_nm(Namech);
+}
+
+
+/*
+ * read_cni() - read common snode information
+ */
+
+static int
+read_cni(s, rv, v, rs, di, din, dinl)
+ struct snode *s; /* starting snode */
+ struct vnode *rv; /* "real" vnode receiver */
+ struct vnode *v; /* starting vnode */
+ struct snode *rs; /* "real" snode receiver */
+ struct dev_info *di; /* dev_info structure receiver */
+ char *din; /* device info name receiver */
+ int dinl; /* sizeof(*din) */
+{
+ char tbuf[32];
+
+ if (read_nvn((KA_T)v->v_data, (KA_T)s->s_commonvp, rv))
+ return(1);
+ if (read_nsn((KA_T)s->s_commonvp, (KA_T)rv->v_data, rs))
+ return(1);
+ *din = '\0';
+ if (rs->s_dip) {
+ if (kread((KA_T)rs->s_dip, (char *)di, sizeof(struct dev_info))) {
+ (void) snpf(Namech, Namechl - 1,
+ "common snode at %s: no dev info: %s",
+ print_kptr((KA_T)rv->v_data, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)rs->s_dip, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+ if (di->devi_name
+ && kread((KA_T)di->devi_name, din, dinl-1) == 0)
+ din[dinl-1] = '\0';
+ }
+ return(0);
+}
+
+
+/*
+ * readinode() - read inode
+ */
+
+static int
+readinode(ia, i)
+ KA_T ia; /* inode kernel address */
+ struct inode *i; /* inode buffer */
+{
+ if (kread((KA_T)ia, (char *)i, sizeof(struct inode))) {
+ (void) snpf(Namech, Namechl - 1, "can't read inode at %s",
+ print_kptr((KA_T)ia, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+ return(0);
+}
+
+
+#if solaris>=20500
+/*
+ * read_ndn() - read node's door node
+ */
+
+static int
+read_ndn(na, da, dn)
+ KA_T na; /* containing vnode's address */
+ KA_T da; /* door node's address */
+ struct door_node *dn; /* door node receiver */
+{
+ char tbuf[32];
+
+ if (!da || kread((KA_T)da, (char *)dn, sizeof(struct door_node))) {
+ (void) snpf(Namech, Namechl - 1,
+ "vnode at %s: can't read door_node: %s",
+ print_kptr(na, tbuf, sizeof(tbuf)),
+ print_kptr(da, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+ return(0);
+}
+#endif /* solaris>=20500 */
+
+
+
+/*
+ * read_mi() - read stream's module information
+ */
+
+static void
+read_mi(s, rdev, so, so_st, so_ad, sdp)
+ KA_T s; /* kernel stream pointer address */
+ dev_t *rdev; /* raw device pointer */
+ caddr_t so; /* so_so return (Solaris) */
+ int *so_st; /* so_so status */
+ KA_T *so_ad; /* so_so addresses */
+ struct l_dev **sdp; /* returned device pointer */
+{
+ struct l_dev *dp;
+ int i, j, k, nl;
+ KA_T ka;
+ struct module_info mi;
+ char mn[STRNML];
+ struct stdata sd;
+ struct queue q;
+ struct qinit qi;
+ KA_T qp;
+/*
+ * If there is no stream pointer, or we can't read the stream head,
+ * return.
+ */
+ if (!s)
+ return;
+ if (kread((KA_T)s, (char *)&sd, sizeof(sd))) {
+ (void) snpf(Namech, Namechl - 1, "can't read stream head: %s",
+ print_kptr(s, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return;
+ }
+/*
+ * Follow the stream head to each of its queue structures, retrieving the
+ * module names from each queue's q_info->qi_minfo->mi_idname chain of
+ * structures. Separate each additional name from the previous one with
+ * "->".
+ *
+ * Ignore failures to read all but queue structure chain entries.
+ *
+ * Ignore module names that end in "head".
+ */
+ k = 0;
+ Namech[0] = '\0';
+ if (!(dp = finddev(&DevDev, rdev, LOOKDEV_CLONE)))
+ dp = finddev(&DevDev, rdev, LOOKDEV_ALL);
+ if (dp) {
+ (void) snpf(Namech, Namechl - 1, "%s", dp->name);
+ Namech[Namechl - 1] = '\0';
+ k = (int)strlen(Namech);
+ *sdp = dp;
+ } else
+ (void) snpf(Lf->iproto, sizeof(Lf->iproto), "STR");
+ nl = sizeof(mn) - 1;
+ mn[nl] = '\0';
+ qp = (KA_T)sd.sd_wrq;
+ for (i = 0; qp && i < 20; i++, qp = (KA_T)q.q_next) {
+ if (!qp || kread(qp, (char *)&q, sizeof(q)))
+ break;
+ if ((ka = (KA_T)q.q_qinfo) == (KA_T)NULL
+ || kread(ka, (char *)&qi, sizeof(qi)))
+ continue;
+ if ((ka = (KA_T)qi.qi_minfo) == (KA_T)NULL
+ || kread(ka, (char *)&mi, sizeof(mi)))
+ continue;
+ if ((ka = (KA_T)mi.mi_idname) == (KA_T)NULL
+ || kread(ka, mn, nl))
+ continue;
+ if ((j = (int)strlen(mn)) < 1)
+ continue;
+ if (j >= 4 && strcmp(&mn[j - 4], "head") == 0)
+ continue;
+
+#if solaris<100000
+ if (strcmp(mn, "sockmod") == 0) {
+
+ /*
+ * Save the Solaris sockmod device and inode numbers.
+ */
+ if (so) {
+
+ struct so_so s;
+
+ if (!kread((KA_T)q.q_ptr, (char *)&s, sizeof(s))) {
+ if (!(*so_st))
+ so_ad[0] = (KA_T)q.q_ptr;
+ else
+ so_ad[1] = (KA_T)q.q_ptr;
+ (void) savesockmod(&s, (struct so_so *)so, so_st);
+ }
+ }
+ }
+#endif /* solaris<100000 */
+
+ if (k) {
+ if ((k + 2) > (Namechl - 1))
+ break;
+ (void) snpf(&Namech[k], Namechl - k, "->");
+ k += 2;
+ }
+ if ((k + j) > (Namechl - 1))
+ break;
+ (void) snpf(&Namech[k], Namechl - k, "%s", mn);
+ k += j;
+ }
+}
+
+
+#if solaris>=20500
+
+/*
+ * read_nan(na, ca, cn) - read node's autofs node
+ */
+
+static int
+read_nan(na, aa, rn)
+ KA_T na; /* containing node's address */
+ KA_T aa; /* autofs node address */
+
+# if solaris<20600
+ struct autonode *rn; /* autofs node receiver */
+# else /* solaris>=20600 */
+ struct fnnode *rn; /* autofs node receiver */
+# endif /* solaris<20600 */
+
+{
+ char tbuf[32];
+
+# if solaris<20600
+ if (!aa || kread((KA_T)aa, (char *)rn, sizeof(struct autonode)))
+# else /* solaris>=20600 */
+ if (!aa || kread((KA_T)aa, (char *)rn, sizeof(struct fnnode)))
+# endif /* solaris<20600 */
+
+ {
+ (void) snpf(Namech, Namechl - 1,
+
+# if solaris<20600
+ "node at %s: can't read autonode: %s",
+# else /* solaris>=20600 */
+ "node at %s: can't read fnnode: %s",
+# endif /* solaris<20600 */
+
+ print_kptr(na, tbuf, sizeof(tbuf)),
+ print_kptr(aa, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+ return(0);
+}
+#endif /* solaris>=20500 */
+
+
+#if defined(HASCACHEFS)
+/*
+ * read_ncn(na, ca, cn) - read node's cache node
+ */
+
+static int
+read_ncn(na, ca, cn)
+ KA_T na; /* containing node's address */
+ KA_T ca; /* cache node address */
+ struct cnode *cn; /* cache node receiver */
+{
+ char tbuf[32];
+
+ if (!ca || kread((KA_T)ca, (char *)cn, sizeof(struct cnode))) {
+ (void) snpf(Namech, Namechl - 1,
+ "node at %s: can't read cnode: %s",
+ print_kptr(na, tbuf, sizeof(tbuf)),
+ print_kptr(ca, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+ return(0);
+}
+#endif /* defined(HASCACHEFS) */
+
+
+#if solaris>=100000
+/*
+ * read_nctfsn(ty, na, ca, cn) - read node's cache node
+ */
+
+static int
+read_nctfsn(ty, na, ca, cn)
+ int ty; /* node type -- i.e., N_CTFS* */
+ KA_T na; /* containing node's address */
+ KA_T ca; /* cache node address */
+ char *cn; /* CTFS node receiver */
+{
+ char *cp, *nm, tbuf[32];
+ READLEN_T sz;
+
+ switch (ty) {
+ case N_CTFSADIR:
+ nm = "ADIR";
+ sz = (READLEN_T)sizeof(ctfs_adirnode_t);
+ break;
+ case N_CTFSBUND:
+ nm = "BUND";
+ sz = (READLEN_T)sizeof(ctfs_bunode_t);
+ break;
+ case N_CTFSCDIR:
+ nm = "CDIR";
+ sz = (READLEN_T)sizeof(ctfs_cdirnode_t);
+ break;
+ case N_CTFSCTL:
+ nm = "CTL";
+ sz = (READLEN_T)sizeof(ctfs_ctlnode_t);
+ break;
+ case N_CTFSEVT:
+ nm = "EVT";
+ sz = (READLEN_T)sizeof(ctfs_evnode_t);
+ break;
+ case N_CTFSLATE:
+ nm = "LATE";
+ sz = (READLEN_T)sizeof(ctfs_latenode_t);
+ break;
+ case N_CTFSROOT:
+ nm = "ROOT";
+ sz = (READLEN_T)sizeof(ctfs_rootnode_t);
+ break;
+ case N_CTFSSTAT:
+ nm = "STAT";
+ sz = (READLEN_T)sizeof(ctfs_ctlnode_t);
+ break;
+ case N_CTFSSYM:
+ nm = "SYM";
+ sz = (READLEN_T)sizeof(ctfs_symnode_t);
+ break;
+ case N_CTFSTDIR:
+ nm = "TDIR";
+ sz = (READLEN_T)sizeof(ctfs_tdirnode_t);
+ break;
+ case N_CTFSTMPL:
+ nm = "TMPL";
+ sz = (READLEN_T)sizeof(ctfs_tmplnode_t);
+ break;
+ default:
+ (void) snpf(Namech, Namechl - 1, "unknown CTFS node type: %d", ty);
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+ if (!ca || kread((KA_T)ca, cn, sz)) {
+ (void) snpf(Namech, Namechl - 1,
+ "node at %s: can't read CTFS %s node: %s",
+ print_kptr(na, tbuf, sizeof(tbuf)),
+ nm,
+ print_kptr(ca, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+ return(0);
+}
+#endif /* solaris>=100000 */
+
+
+/*
+ * read_nfn() - read node's fifonode
+ */
+
+static int
+read_nfn(na, fa, f)
+ KA_T na; /* containing node's address */
+ KA_T fa; /* fifonode address */
+ struct fifonode *f; /* fifonode receiver */
+{
+ char tbuf[32];
+
+ if (!fa || readfifonode(fa, f)) {
+ (void) snpf(Namech, Namechl - 1,
+ "node at %s: can't read fifonode: %s",
+ print_kptr(na, tbuf, sizeof(tbuf)),
+ print_kptr(fa, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+ return(0);
+}
+
+
+/*
+ * read_nhn() - read node's High Sierra node
+ */
+
+static int
+read_nhn(na, ha, h)
+ KA_T na; /* containing node's address */
+ KA_T ha; /* hsnode address */
+ struct hsnode *h; /* hsnode receiver */
+{
+ char tbuf[32];
+
+ if (!ha || readhsnode(ha, h)) {
+ (void) snpf(Namech, Namechl - 1,
+ "node at %s: can't read hsnode: %s",
+ print_kptr(na, tbuf, sizeof(tbuf)),
+ print_kptr(ha, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+ return(0);
+}
+
+
+/*
+ * read_nin() - read node's inode
+ */
+
+static int
+read_nin(na, ia, i)
+ KA_T na; /* containing node's address */
+ KA_T ia; /* kernel inode address */
+ struct inode *i; /* inode receiver */
+{
+ char tbuf[32];
+
+ if (!ia || readinode(ia, i)) {
+ (void) snpf(Namech, Namechl - 1,
+ "node at %s: can't read inode: %s",
+ print_kptr(na, tbuf, sizeof(tbuf)),
+ print_kptr(ia, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+ return(0);
+}
+
+
+/*
+ * read_nln(na, la, ln) - read node's loopback node
+ */
+
+static int
+read_nln(na, la, ln)
+ KA_T na; /* containing node's address */
+ KA_T la; /* loopback node address */
+ struct lnode *ln; /* loopback node receiver */
+{
+ char tbuf[32];
+
+ if (!la || kread((KA_T)la, (char *)ln, sizeof(struct lnode))) {
+ (void) snpf(Namech, Namechl - 1,
+ "node at %s: can't read lnode: %s",
+ print_kptr(na, tbuf, sizeof(tbuf)),
+ print_kptr(la, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+ return(0);
+}
+
+
+/*
+ * read_nnn() - read node's namenode
+ */
+
+static int
+read_nnn(na, nna, nn)
+ KA_T na; /* containing node's address */
+ KA_T nna; /* namenode address */
+ struct namenode *nn; /* namenode receiver */
+{
+ char tbuf[32];
+
+ if (!nna || kread((KA_T)nna, (char *)nn, sizeof(struct namenode))) {
+ (void) snpf(Namech, Namechl - 1,
+ "node at %s: can't read namenode: %s",
+ print_kptr(na, tbuf, sizeof(tbuf)),
+ print_kptr(nna, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+ return(0);
+}
+
+
+/*
+ * read_nmn() - read node's mvfsnode
+ */
+
+static int
+read_nmn(na, ma, m)
+ KA_T na; /* containing node's address */
+ KA_T ma; /* kernel mvfsnode address */
+ struct mvfsnode *m; /* mvfsnode receiver */
+{
+ char tbuf[32];
+
+ if (!ma || kread((KA_T)ma, (char *)m, sizeof(struct mvfsnode))) {
+ (void) snpf(Namech, Namechl - 1,
+ "node at %s: can't read mvfsnode: %s",
+ print_kptr(na, tbuf, sizeof(tbuf)),
+ print_kptr(ma, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+ return(0);
+}
+
+
+#if defined(HASPROCFS)
+/*
+ * read_npi() - read node's /proc file system information
+ */
+
+static int
+read_npi(na, v, pids)
+ KA_T na; /* containing node's address */
+ struct vnode *v; /* containing vnode */
+ struct pid *pids; /* pid structure receiver */
+{
+ struct as as;
+ struct proc p;
+ struct prnode pr;
+ char tbuf[32];
+
+#if solaris>=20600
+ prcommon_t pc, ppc;
+ int pcs, ppcs, prpcs, prppcs;
+ struct proc pp;
+ pid_t prpid;
+ id_t prtid;
+ char *ty = (char *)NULL;
+#endif /* solaris>=20600 */
+
+ if (!v->v_data || kread((KA_T)v->v_data, (char *)&pr, sizeof(pr))) {
+ (void) snpf(Namech, Namechl - 1,
+ "node at %s: can't read prnode: %s",
+ print_kptr(na, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+
+#if solaris<20600
+/*
+ * For Solaris < 2.6:
+ * * Read the proc structure, get the process size and PID;
+ * * Return the PID;
+ * * Enter a name, constructed from the file system and PID;
+ * * Enter an inode number, constructed from the PID.
+ */
+ if (!pr.pr_proc) {
+ if (v->v_type == VDIR) {
+ (void) snpf(Namech, Namechl - 1, "/%s", HASPROCFS);
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ Lf->inode = (INODETYPE)PR_ROOTINO;
+ Lf->inp_ty = 1;
+ } else {
+ (void) snpf(Namech, Namechl - 1, "/%s/", HASPROCFS);
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ Lf->inp_ty = 0;
+ }
+ return(0);
+ }
+ if (kread((KA_T)pr.pr_proc, (char *)&p, sizeof(p))) {
+ (void) snpf(Namech, Namechl - 1,
+ "prnode at %s: can't read proc: %s",
+ print_kptr((KA_T)v->v_data, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)pr.pr_proc, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+ if (p.p_as && !kread((KA_T)p.p_as, (char *)&as, sizeof(as))) {
+ Lf->sz = (SZOFFTYPE)as.a_size;
+ Lf->sz_def = 1;
+ }
+ if (!p.p_pidp
+ || kread((KA_T)p.p_pidp, (char *)pids, sizeof(struct pid))) {
+ (void) snpf(Namech, Namechl - 1,
+ "proc struct at %s: can't read pid: %s",
+ print_kptr((KA_T)pr.pr_proc, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)p.p_pidp, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+ (void) snpf(Namech, Namechl, "/%s/%d", HASPROCFS, (int)pids->pid_id);
+ Namech[Namechl - 1] = '\0';
+ Lf->inode = (INODETYPE)ptoi(pids->pid_id);
+ Lf->inp_ty = 1;
+#else /* solaris>=20600 */
+/*
+ * Enter the >= Solaris 2.6 inode number.
+ */
+ Lf->inode = (INODETYPE)pr.pr_ino;
+ Lf->inp_ty = 1;
+/*
+ * Read the >= Solaris 2.6 prnode common structures.
+ *
+ * Return the PID number.
+ *
+ * Identify the lwp PID (the thread ID).
+ */
+ if (pr.pr_common
+ && kread((KA_T)pr.pr_common, (char *)&pc, sizeof(pc)) == 0) {
+ pcs = 1;
+ if (pc.prc_proc
+ && kread((KA_T)pc.prc_proc, (char *)&p, sizeof(p)) == 0)
+ prpcs = 1;
+ else
+ prpcs = 0;
+ } else
+ pcs = prpcs = 0;
+ if (pr.pr_pcommon
+ && kread((KA_T)pr.pr_pcommon, (char *)&ppc, sizeof(ppc)) == 0) {
+ ppcs = 1;
+ if (ppc.prc_proc
+ && kread((KA_T)ppc.prc_proc, (char *)&pp, sizeof(pp)) == 0)
+ prppcs = 1;
+ else
+ prppcs = 0;
+ } else
+ ppcs = prppcs = 0;
+ if (pcs && pc.prc_pid)
+ pids->pid_id = prpid = pc.prc_pid;
+ else if (ppcs && ppc.prc_pid)
+ pids->pid_id = prpid = ppc.prc_pid;
+ else
+ pids->pid_id = prpid = (pid_t)0;
+ if (pcs && pc.prc_tid)
+ prtid = pc.prc_tid;
+ else if (ppcs && ppc.prc_tid)
+ prtid = ppc.prc_tid;
+ else
+ prtid = (id_t)0;
+/*
+ * Identify the Solaris 2.6 /proc file system name, file size, and file type.
+ */
+ switch (pr.pr_type) {
+ case PR_PROCDIR:
+ (void) snpf(Namech, Namechl - 1, "/%s", HASPROCFS);
+ ty = "PDIR";
+ break;
+ case PR_PIDDIR:
+ (void) snpf(Namech, Namechl - 1, "/%s/%d", HASPROCFS, (int)prpid);
+ ty = "PDIR";
+ break;
+ case PR_AS:
+ (void) snpf(Namech, Namechl - 1,
+ "/%s/%d/as", HASPROCFS, (int)prpid);
+ ty = "PAS";
+ if (prpcs
+ && kread((KA_T)pc.prc_proc, (char *)&p, sizeof(p)) == 0
+ && p.p_as
+ && kread((KA_T)p.p_as, (char *)&as, sizeof(as)) == 0) {
+ Lf->sz = (SZOFFTYPE)as.a_size;
+ Lf->sz_def = 1;
+ }
+ break;
+ case PR_CTL:
+ (void) snpf(Namech, Namechl - 1,
+ "/%s/%d/ctl", HASPROCFS, (int)prpid);
+ ty = "PCTL";
+ break;
+ case PR_STATUS:
+ (void) snpf(Namech, Namechl - 1,
+ "/%s/%d/status", HASPROCFS, (int)prpid);
+ ty = "PSTA";
+ break;
+ case PR_LSTATUS:
+ (void) snpf(Namech, Namechl - 1,
+ "/%s/%d/lstatus", HASPROCFS, (int)prpid);
+ ty = "PLST";
+ break;
+ case PR_PSINFO:
+ (void) snpf(Namech, Namechl - 1,
+ "/%s/%d/psinfo", HASPROCFS, (int)prpid);
+ ty = "PSIN";
+ break;
+ case PR_LPSINFO:
+ (void) snpf(Namech, Namechl - 1,
+ "/%s/%d/lpsinfo", HASPROCFS, (int)prpid);
+ ty = "PLPI";
+ break;
+ case PR_MAP:
+ (void) snpf(Namech, Namechl - 1,
+ "/%s/%d/map", HASPROCFS, (int)prpid);
+ ty = "PMAP";
+ break;
+ case PR_RMAP:
+ (void) snpf(Namech, Namechl - 1,
+ "/%s/%d/rmap", HASPROCFS, (int)prpid);
+ ty = "PRMP";
+ break;
+ case PR_XMAP:
+ (void) snpf(Namech, Namechl - 1,
+ "/%s/%d/xmap", HASPROCFS, (int)prpid);
+ ty = "PXMP";
+ break;
+ case PR_CRED:
+ (void) snpf(Namech, Namechl - 1,
+ "/%s/%d/cred", HASPROCFS, (int)prpid);
+ ty = "PCRE";
+ break;
+ case PR_SIGACT:
+ (void) snpf(Namech, Namechl - 1,
+ "/%s/%d/sigact", HASPROCFS, (int)prpid);
+ ty = "PSGA";
+ break;
+ case PR_AUXV:
+ (void) snpf(Namech, Namechl - 1,
+ "/%s/%d/auxv", HASPROCFS, (int)prpid);
+ ty = "PAXV";
+ break;
+
+# if defined(HASPR_LDT)
+ case PR_LDT:
+ (void) snpf(Namech, Namechl - 1,
+ "/%s/%d/ldt", HASPROCFS, (int)prpid);
+ ty = "PLDT";
+ break;
+# endif /* defined(HASPR_LDT) */
+
+ case PR_USAGE:
+ (void) snpf(Namech, Namechl - 1,
+ "/%s/%d/usage", HASPROCFS, (int)prpid);
+ ty = "PUSG";
+ break;
+ case PR_LUSAGE:
+ (void) snpf(Namech, Namechl - 1,
+ "/%s/%d/lusage", HASPROCFS, (int)prpid);
+ ty = "PLU";
+ break;
+ case PR_PAGEDATA:
+ (void) snpf(Namech, Namechl - 1,
+ "/%s/%d/pagedata", HASPROCFS, (int)prpid);
+ ty = "PGD";
+ break;
+ case PR_WATCH:
+ (void) snpf(Namech, Namechl - 1,
+ "/%s/%d/watch", HASPROCFS, (int)prpid);
+ ty = "PW";
+ break;
+ case PR_CURDIR:
+ (void) snpf(Namech, Namechl - 1,
+ "/%s/%d/cwd", HASPROCFS, (int)prpid);
+ ty = "PCWD";
+ break;
+ case PR_ROOTDIR:
+ (void) snpf(Namech, Namechl - 1,
+ "/%s/%d/root", HASPROCFS, (int)prpid);
+ ty = "PRTD";
+ break;
+ case PR_FDDIR:
+ (void) snpf(Namech, Namechl - 1,
+ "/%s/%d/fd", HASPROCFS, (int)prpid);
+ ty = "PFDR";
+ break;
+ case PR_FD:
+ (void) snpf(Namech, Namechl - 1,
+ "/%s/%d/fd/%d", HASPROCFS, (int)prpid,
+ pr.pr_index);
+ ty = "PFD";
+ break;
+ case PR_OBJECTDIR:
+ (void) snpf(Namech, Namechl - 1,
+ "/%s/%d/object", HASPROCFS, (int)prpid);
+ ty = "PODR";
+ break;
+ case PR_OBJECT:
+ (void) snpf(Namech, Namechl - 1,
+ "/%s/%d/object/", HASPROCFS, (int)prpid);
+ ty = "POBJ";
+ break;
+ case PR_LWPDIR:
+ (void) snpf(Namech, Namechl - 1,
+ "/%s/%d/lpw", HASPROCFS, (int)prpid);
+ ty = "PLDR";
+ break;
+ case PR_LWPIDDIR:
+ (void) snpf(Namech, Namechl,
+ "/%s/%d/lwp/%d", HASPROCFS, (int)prpid, (int)prtid);
+ ty = "PLDR";
+ break;
+ case PR_LWPCTL:
+ (void) snpf(Namech, Namechl - 1, "/%s/%d/lwp/%d/lwpctl", HASPROCFS,
+ (int)prpid, (int)prtid);
+ ty = "PLC";
+ break;
+ case PR_LWPSTATUS:
+ (void) snpf(Namech, Namechl - 1,
+ "/%s/%d/lwp/%d/lwpstatus", HASPROCFS,
+ (int)prpid, (int)prtid);
+ ty = "PLWS";
+ break;
+ case PR_LWPSINFO:
+ (void) snpf(Namech, Namechl - 1,
+ "/%s/%d/lwp/%d/lwpsinfo", HASPROCFS,
+ (int)prpid, (int)prtid);
+ ty = "PLWI";
+ break;
+ case PR_LWPUSAGE:
+ (void) snpf(Namech, Namechl - 1,
+ "/%s/%d/lwp/%d/lwpusage", HASPROCFS,
+ (int)prpid, (int)prtid);
+ ty = "PLWU";
+ break;
+ case PR_XREGS:
+ (void) snpf(Namech, Namechl - 1, "/%s/%d/lwp/%d/xregs", HASPROCFS,
+ (int)prpid, (int)prtid);
+ ty = "PLWX";
+ break;
+
+# if defined(HASPR_GWINDOWS)
+ case PR_GWINDOWS:
+ (void) snpf(Namech, Namechl - 1,
+ "/%s/%d/lwp/%d/gwindows", HASPROCFS,
+ (int)prpid, (int)prtid);
+ ty = "PLWG";
+ break;
+# endif /* defined(HASPR_GWINDOWS) */
+
+ case PR_PIDFILE:
+ (void) snpf(Namech, Namechl - 1, "/%s/%d", HASPROCFS, (int)prpid);
+ ty = "POPF";
+ break;
+ case PR_LWPIDFILE:
+ (void) snpf(Namech, Namechl - 1, "/%s/%d", HASPROCFS, (int)prpid);
+ ty = "POLP";
+ break;
+ case PR_OPAGEDATA:
+ (void) snpf(Namech, Namechl - 1, "/%s/%d", HASPROCFS, (int)prpid);
+ ty = "POPG";
+ break;
+ default:
+ ty = (char *)NULL;
+ }
+ if (ty)
+ (void) snpf(Lf->type, sizeof(Lf->type), "%s", ty);
+ else
+ (void) snpf(Lf->type, sizeof(Lf->type), "%04o",
+ (pr.pr_type & 0xfff));
+/*
+ * Record the Solaris 2.6 /proc file system inode number.
+ */
+ Lf->inode = (INODETYPE)pr.pr_ino;
+ Lf->inp_ty = 1;
+# endif /* solaris<20600 */
+
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(0);
+}
+#endif /* defined(HASPROCFS) */
+
+
+/*
+ * read_npn() - read node's pcnode
+ */
+
+static int
+read_npn(na, pa, p)
+ KA_T na; /* containing node's address */
+ KA_T pa; /* pcnode address */
+ struct pcnode *p; /* pcnode receiver */
+{
+ char tbuf[32];
+
+ if (!pa || kread(pa, (char *)p, sizeof(struct pcnode))) {
+ (void) snpf(Namech, Namechl - 1,
+ "node at %s: can't read pcnode: %s",
+ print_kptr(na, tbuf, sizeof(tbuf)),
+ print_kptr(pa, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+ return(0);
+}
+
+
+#if solaris>=100000
+/*
+ * read_nprtn() - read node's port node
+ */
+
+static int
+read_nprtn(na, pa, p)
+ KA_T na; /* containing node's address */
+ KA_T pa; /* port node address */
+ port_t *p; /* port node receiver */
+{
+ char tbuf[32];
+
+ if (!pa || kread(pa, (char *)p, sizeof(port_t))) {
+ (void) snpf(Namech, Namechl - 1,
+ "node at %s: can't read port node: %s",
+ print_kptr(na, tbuf, sizeof(tbuf)),
+ print_kptr(pa, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+ return(0);
+}
+#endif /* solaris>=100000 */
+
+
+/*
+ * read_nrn() - read node's rnode
+ */
+
+static int
+read_nrn(na, ra, r)
+ KA_T na; /* containing node's address */
+ KA_T ra; /* rnode address */
+ struct rnode *r; /* rnode receiver */
+{
+ char tbuf[32];
+
+ if (!ra || readrnode(ra, r)) {
+ (void) snpf(Namech, Namechl - 1, "node at %s: can't read rnode: %s",
+ print_kptr(na, tbuf, sizeof(tbuf)),
+ print_kptr(ra, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+ return(0);
+}
+
+
+#if solaris>=100000
+/*
+ * read_nrn4() - read node's rnode4
+ */
+
+static int
+read_nrn4(na, ra, r)
+ KA_T na; /* containing node's address */
+ KA_T ra; /* rnode address */
+ struct rnode4 *r; /* rnode receiver */
+{
+ char tbuf[32];
+
+ if (!ra ||
+ kread((KA_T)ra, (char *)r, sizeof(struct rnode4))
+ ) {
+ (void) snpf(Namech, Namechl - 1,
+ "node at %s: can't read rnode4: %s",
+ print_kptr(na, tbuf, sizeof(tbuf)),
+ print_kptr(ra, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+ return(0);
+}
+#endif /* solaris>=100000 */
+
+
+#if solaris>=110000
+/*
+ * read_nsdn() - read node's sdev_node
+ */
+
+static int
+read_nsdn(na, sa, sdn, sdva)
+ KA_T na; /* containing node's adress */
+ KA_T sa; /* sdev_node address */
+ struct sdev_node *sdn; /* sdev_node receiver */
+ struct vattr *sdva; /* sdev_node's vattr receiver */
+{
+ KA_T va;
+ char tbuf[32], tbuf1[32];
+
+ if (!sa || kread((KA_T)sa, (char *)sdn, sizeof(struct sdev_node))) {
+ (void) snpf(Namech, Namechl - 1,
+ "node at %s: can't read sdev_node: %s",
+ print_kptr(na, tbuf, sizeof(tbuf)),
+ print_kptr(sa, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+ if (!(va = (KA_T)sdn->sdev_attr)
+ || kread(va, (char *)sdva, sizeof(struct vattr))
+ ) {
+ (void) snpf(Namech, Namechl - 1,
+ "node at %s; sdev_node at %s: can't read vattr: %s",
+ print_kptr(na, tbuf, sizeof(tbuf)),
+ print_kptr(sa, tbuf1, sizeof(tbuf1)),
+ print_kptr(va, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+ return(0);
+}
+#endif /* solaris>=110000 */
+
+
+#if solaris>=20600
+/*
+ * read_nson() - read node's sonode
+ */
+
+static int
+read_nson(na, sa, sn)
+ KA_T na; /* containing node's address */
+ KA_T sa; /* sonode address */
+ struct sonode *sn; /* sonode receiver */
+
+{
+ char tbuf[32];
+
+ if (!sa || kread((KA_T)sa, (char *)sn, sizeof(struct sonode))) {
+ (void) snpf(Namech, Namechl - 1,
+ "node at %s: can't read sonode: %s",
+ print_kptr(na, tbuf, sizeof(tbuf)),
+ print_kptr(sa, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+ return(0);
+}
+#endif /* solaris>=20600 */
+
+
+/*
+ * read_nsn() - read node's snode
+ */
+
+static int
+read_nsn(na, sa, s)
+ KA_T na; /* containing node's address */
+ KA_T sa; /* snode address */
+ struct snode *s; /* snode receiver */
+{
+ char tbuf[32];
+
+ if (!sa || readsnode(sa, s)) {
+ (void) snpf(Namech, Namechl - 1,
+ "node at %s: can't read snode: %s",
+ print_kptr(na, tbuf, sizeof(tbuf)),
+ print_kptr(sa, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+ return(0);
+}
+
+
+#if solaris>=110000
+/*
+ * read_nsti() - read socket node's info
+ */
+
+static int
+read_nsti(so, stpi)
+ struct sonode *so; /* socket's sonode */
+ sotpi_info_t *stpi; /* local socket info receiver */
+{
+ char tbuf[32];
+
+ (void) CTF_init(&Sockfs_ctfs, SOCKFS_MOD_FORMAT, Sockfs_requests);
+ if (!so
+ || !so->so_priv
+ || CTF_MEMBER_READ(so->so_priv,stpi,sotpi_info_members, sti_dev)
+ || CTF_MEMBER_READ(so->so_priv,stpi,sotpi_info_members, sti_laddr)
+ || CTF_MEMBER_READ(so->so_priv,stpi,sotpi_info_members, sti_faddr)
+ || CTF_MEMBER_READ(so->so_priv,stpi,sotpi_info_members, sti_ux_laddr)
+ || CTF_MEMBER_READ(so->so_priv,stpi,sotpi_info_members, sti_ux_faddr)
+ || CTF_MEMBER_READ(so->so_priv,stpi,sotpi_info_members, sti_serv_type)
+ ) {
+ (void) snpf(Namech, Namechl - 1,
+ "sonode at %s: can't read so_priv: %s",
+ print_kptr((KA_T)so, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)so->so_priv, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+ return(0);
+}
+#endif /* solaris>=110000 */
+
+
+/*
+ * read_ntn() - read node's tmpnode
+ */
+
+static int
+read_ntn(na, ta, t)
+ KA_T na; /* containing node's address */
+ KA_T ta; /* tmpnode address */
+ struct tmpnode *t; /* tmpnode receiver */
+{
+ char tbuf[32];
+
+ if (!ta || readtnode(ta, t)) {
+ (void) snpf(Namech, Namechl - 1,
+ "node at %s: can't read tnode: %s",
+ print_kptr(na, tbuf, sizeof(tbuf)),
+ print_kptr(ta, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+ return(0);
+}
+
+
+#if solaris>=20600
+/*
+ * read_nusa() - read sondode's UNIX socket address
+ */
+
+static int
+read_nusa(so, ua)
+ struct soaddr *so; /* kernel socket info structure */
+ struct sockaddr_un *ua; /* local sockaddr_un address */
+{
+ KA_T a;
+ int len;
+ int min = offsetof(struct sockaddr_un, sun_path);
+
+ ua->sun_path[0] = '\0';
+
+ if (!(a = (KA_T)so->soa_sa)
+ || (len = so->soa_len) < (min + 2)
+ || len > (int)sizeof(struct sockaddr_un)
+ || kread(a, (char *)ua, len)
+ || ua->sun_family != AF_UNIX)
+ return(0);
+ len -= min;
+ if (len >= sizeof(ua->sun_path))
+ len = sizeof(ua->sun_path) - 1;
+ ua->sun_path[len] = '\0';
+ return((int)strlen(ua->sun_path));
+}
+#endif /* solaris>=20600 */
+
+
+/*
+ * read_nvn() - read node's vnode
+ */
+
+static int
+read_nvn(na, va, v)
+ KA_T na; /* node's address */
+ KA_T va; /* vnode address */
+ struct vnode *v; /* vnode receiver */
+{
+ char tbuf[32];
+
+ if (readvnode(va, v)) {
+ (void) snpf(Namech, Namechl - 1,
+ "node at %s: can't read real vnode: %s",
+ print_kptr(na, tbuf, sizeof(tbuf)),
+ print_kptr(va, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+ return(0);
+}
+
+
+#if defined(HAS_ZFS)
+/*
+ * read_nzn() - read node's ZFS node
+ */
+
+static int
+read_nzn(na, nza, zn)
+ KA_T na; /* containing node's address */
+ KA_T nza; /* znode address */
+ znode_t *zn; /* znode receiver */
+{
+ int err = 0; /* error flag */
+ CTF_member_t *mp; /* member pointer */
+ char tbuf[32]; /* temporary buffer */
+ znode_phys_t zp; /* physical znode */
+
+ (void) CTF_init(&ZFS_ctfs, ZFS_MOD_FORMAT, ZFS_requests);
+ if (!nza
+ || CTF_MEMBER_READ(nza, zn, znode_members, z_zfsvfs)
+ || CTF_MEMBER_READ(nza, zn, znode_members, z_vnode)
+ || CTF_MEMBER_READ(nza, zn, znode_members, z_id)
+ || CTF_MEMBER_READ(nza, zn, znode_members, z_phys)
+ || CTF_MEMBER_READ(nza, zn, znode_members, z_links)
+ || CTF_MEMBER_READ(nza, zn, znode_members, z_size)
+ ) {
+ (void) snpf(Namech, Namechl - 1,
+ "node at %s: can't read znode: %s",
+ print_kptr(na, tbuf, sizeof(tbuf)),
+ print_kptr(nza, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+/*
+ * If the physical znode pointer is defined, read the physizal znode
+ * and propagate its values to the znode.
+ */
+ if (znode_members[MX_z_phys].m_offset != CTF_MEMBER_UNDEF) {
+ err = read_nznp(nza, (KA_T)zn->z_phys, &zp);
+ if (!err) {
+ zn->z_links = zp.zp_links;
+ zn->z_size = zp.zp_size;
+ }
+ } else {
+
+ /*
+ * Make sure z_link and z_size are defined when z_phys isn't.
+ */
+ if (znode_members[MX_z_links].m_offset == CTF_MEMBER_UNDEF) {
+ (void) snpf(Namech, Namechl - 1,
+ "node at %s: can't read z_links: %s",
+ print_kptr(na, tbuf, sizeof(tbuf)),
+ print_kptr(nza, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ err = 1;
+ }
+ if (znode_members[MX_z_size].m_offset == CTF_MEMBER_UNDEF) {
+ (void) snpf(Namech, Namechl - 1,
+ "node at %s: can't read z_size: %s",
+ print_kptr(na, tbuf, sizeof(tbuf)),
+ print_kptr(nza, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ err = 1;
+ }
+ }
+ return(err);
+}
+
+
+/*
+ * read_nznp() - read znode's persistent znode
+ */
+
+static int
+read_nznp(nza, nzpa, zp)
+ KA_T nza; /* containing znode's address */
+ KA_T nzpa; /* persistent znode address */
+ znode_phys_t *zp; /* persistent znode receiver */
+{
+ char tbuf[32];
+
+ (void) CTF_init(&ZFS_ctfs, ZFS_MOD_FORMAT, ZFS_requests);
+ if (!nzpa
+ || CTF_MEMBER_READ(nzpa, zp, znode_phys_members, zp_size)
+ || CTF_MEMBER_READ(nzpa, zp, znode_phys_members, zp_links)
+ ) {
+ (void) snpf(Namech, Namechl - 1, "znode at %s: "
+ "can't read znode_phys: %s",
+ print_kptr(nza, tbuf, sizeof(tbuf)),
+ print_kptr(nzpa, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+ return(0);
+}
+
+
+/*
+ * read_nzvfs() - read znode's associated vfs
+ */
+
+static int
+read_nzvfs(nza, nzva, zv)
+ KA_T nza; /* containing znode's address */
+ KA_T nzva; /* associated vfs address */
+ zfsvfs_t *zv; /* associated vfs receiver */
+{
+ char tbuf[32];
+
+ (void) CTF_init(&ZFS_ctfs, ZFS_MOD_FORMAT, ZFS_requests);
+ if (!nzva
+ || CTF_MEMBER_READ(nzva, zv, zfsvfs_members, z_vfs)
+ ) {
+ (void) snpf(Namech, Namechl - 1,
+ "znode at %s: can't read zfsvfs: %s",
+ print_kptr(nza, tbuf, sizeof(tbuf)),
+ print_kptr(nzva, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+ return(0);
+}
+#endif /* defined(HAS_ZFS) */
+
+
+#if solaris<100000
+/*
+ * savesockmod() - save addresses from sockmod so_so structure
+ */
+
+static void
+savesockmod(so, sop, so_st)
+ struct so_so *so; /* new so_so structure pointer */
+ struct so_so *sop; /* previous so_so structure pointer */
+ int *so_st; /* status of *sop (0 if not loaded) */
+{
+
+#if solaris<20500
+ dev_t d1, d2, d3;
+#endif /* solaris<20500 */
+
+#define luxadr lux_dev.addr.tu_addr
+#define luxdev lux_dev.addr.tu_addr.dev
+#define luxino lux_dev.addr.tu_addr.ino
+#define ruxadr rux_dev.addr.tu_addr
+#define ruxdev rux_dev.addr.tu_addr.dev
+#define ruxino rux_dev.addr.tu_addr.ino
+
+#if solaris<20500
+/*
+ * If either address in the new structure is missing a device number, clear
+ * its corresponding inode number. Then sort the inode-less device numbers.
+ */
+ if (!so->luxdev)
+ so->luxino = (ino_t)0;
+ if (!so->ruxdev)
+ so->ruxino = (ino_t)0;
+ if (!so->luxino && !so->ruxino) {
+ if (so->luxdev > so->ruxdev) {
+ d2 = so->luxdev;
+ d1 = so->luxdev = so->ruxdev;
+ so->ruxdev = d2;
+ } else {
+ d1 = so->luxdev;
+ d2 = so->ruxdev;
+ }
+ } else
+ d1 = d2 = (dev_t)0;
+/*
+ * If the previous structure hasn't been loaded, save the new one in it with
+ * adjusted or sorted addresses.
+ */
+ if (!*so_st) {
+ if (so->luxdev && so->luxino) {
+ *sop = *so;
+ sop->ruxdev = (dev_t)0;
+ sop->ruxino = (ino_t)0;
+ *so_st = 1;
+ return;
+ }
+ if (so->ruxdev && so->ruxino) {
+ *sop = *so;
+ sop->luxadr = sop->ruxadr;
+ sop->ruxdev = (dev_t)0;
+ sop->ruxino = (ino_t)0;
+ *so_st = 1;
+ return;
+ }
+ *sop = *so;
+ *so_st = 1;
+ return;
+ }
+/*
+ * See if the new sockmod addresses need to be merged with the previous
+ * ones:
+ *
+ * * Don't merge if the previous so_so structure's lux_dev has a non-
+ * zero device and a non-zero inode number.
+ *
+ * * If either of the device/inode pairs in the new structure is non-
+ * zero, propagate them to the previous so_so structure.
+ *
+ * * Don't merge if the both device numbers in the new structure are
+ * zero.
+ */
+ if (sop->luxdev && sop->luxino)
+ return;
+ if (so->luxdev && so->luxino) {
+ sop->luxadr = so->luxadr;
+ sop->ruxdev = (dev_t)0;
+ sop->ruxino = (ino_t)0;
+ return;
+ }
+ if (so->ruxdev && so->ruxino) {
+ sop->luxadr = so->ruxadr;
+ sop->ruxdev = (dev_t)0;
+ sop->ruxino = (ino_t)0;
+ return;
+ }
+ if (!so->luxdev && !so->ruxdev)
+ return;
+/*
+ * Check the previous structure's device numbers:
+ *
+ * * If both are zero, replace the previous structure with the new one.
+ *
+ * * Choose the minimum and maximum non-zero device numbers contained in
+ * either structure.
+ */
+ if (!sop->luxdev && !sop->ruxdev) {
+ *sop = *so;
+ return;
+ }
+ if (!sop->luxdev && (d1 || d2)) {
+ if (d1) {
+ sop->luxdev = d1;
+ d1 = (dev_t)0;
+ } else {
+ sop->luxdev = d2;
+ d2 = (dev_t)0;
+ }
+ if (sop->luxdev > sop->ruxdev) {
+ d3 = sop->luxdev;
+ sop->luxdev = sop->ruxdev;
+ sop->ruxdev = d3;
+ }
+ }
+ if (!sop->ruxdev && (d1 || d2)) {
+ if (d1) {
+ sop->ruxdev = d1;
+ d1 = (dev_t)0;
+ } else {
+ sop->ruxdev = d2;
+ d2 = (dev_t)0;
+ }
+ if (sop->luxdev > sop->ruxdev) {
+ d3 = sop->luxdev;
+ sop->luxdev = sop->ruxdev;
+ sop->ruxdev = d3;
+ }
+ }
+ if (sop->luxdev && sop->ruxdev) {
+ if (d1) {
+ if (d1 < sop->luxdev)
+ sop->luxdev = d1;
+ else if (d1 > sop->ruxdev)
+ sop->ruxdev = d1;
+ }
+ if (d2) {
+ if (d2 < sop->luxdev)
+ sop->luxdev = d2;
+ else if (d2 > sop->ruxdev)
+ sop->ruxdev = d2;
+ }
+ }
+#else /* solaris>=20500 */
+/*
+ * Save the first sockmod structure.
+ */
+ if (!*so_st) {
+ *so_st = 1;
+ *sop = *so;
+ }
+#endif /* solaris<20500 */
+
+}
+#endif /* solaris<100000 */
+
+
+
+/*
+ * vop2ty() - convert vnode operation switch address to internal type
+ */
+
+int
+vop2ty(vp, fx)
+ struct vnode *vp; /* local vnode pointer */
+ int fx; /* file system index (-1 if none) */
+{
+ int h;
+ register int i;
+ KA_T ka;
+ int nty;
+ v_optab_t *nv, *v, *vt;
+
+#if defined(HAS_AFS)
+ static int afs = 0; /* afs test status: -1 = no AFS
+ * 0 = not tested
+ * 1 = AFS */
+#endif /* defined(HAS_AFS) */
+
+/*
+ * Locate the node type by hashing the vnode's v_op address into the Voptab[].
+ */
+ if (!(ka = (KA_T)vp->v_op))
+ return(-1);
+ h = HASHVOP(ka);
+ for (v = Voptab[h]; v; v = v->next) {
+ if (ka == v->v_op)
+ break;
+ }
+ if (!v) {
+
+ /*
+ * If there's no entry in the Voptab[] for the v_op address, see if
+ * an entry can be found via the file system type and FxToVoptab[].
+ */
+ if ((fx >= 0) && (fx < Fsinfomax) && (v = FxToVoptab[fx])) {
+
+ /*
+ * There's an FxToVoptab[] mapping, so add an entry to Voptab[]
+ * for the v_op address.
+ */
+ if (!(nv = (v_optab_t *)malloc((MALLOC_S)sizeof(v_optab_t)))) {
+ (void) fprintf(stderr, "%s: can't add \"%s\" to Voptab\n",
+ Pn, Fsinfo[fx]);
+ Exit(1);
+ }
+ *nv = *v;
+ nv->v_op = ka;
+ h = HASHVOP(ka);
+ nv->next = Voptab[h];
+ Voptab[h] = v = nv;
+ }
+ }
+ if (!v)
+ return(-1);
+
+#if defined(HAS_AFS)
+/*
+ * Do special AFS checks.
+ */
+ if (v->nty == N_AFS) {
+ if (vp->v_data || !vp->v_vfsp)
+ return(-1);
+ switch (afs) {
+ case -1:
+ return(-1);
+ case 0:
+ if (!hasAFS(vp)) {
+ afs = -1;
+ return(-1);
+ }
+ afs = 1;
+ return(N_AFS);
+ case 1:
+ if ((KA_T)vp->v_vfsp == AFSVfsp)
+ return(N_AFS);
+ }
+ return(-1);
+ }
+#endif /* defined(HAS_AFS) */
+
+ return(v->nty);
+}
+
+
+#if solaris>=100000
+/*
+ * read_ndvn() -- read node's dv_node
+ */
+
+static int
+read_ndvn(na, da, dv, dev, devs)
+ KA_T na; /* containing vnode's address */
+ KA_T da; /* containing vnode's v_data */
+ struct dv_node *dv; /* dv_node receiver */
+ dev_t *dev; /* underlying file system device
+ * number receptor */
+ unsigned char *devs; /* status of *dev */
+{
+ struct vnode rv;
+ struct snode s;
+ char tbuf[32];
+ struct vfs v;
+/*
+ * Read the snode.
+ */
+ if (!da || kread((KA_T)da, (char *)&s, sizeof(s))) {
+ (void) snpf(Namech, Namechl - 1,
+ "dv_node vnode at %s: can't read snode: %s",
+ print_kptr(na, tbuf, sizeof(tbuf)),
+ print_kptr(da, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+/*
+ * Read the snode's real vnode.
+ */
+ if (!s.s_realvp
+ || kread((KA_T)s.s_realvp, (char *)&rv, sizeof(struct dv_node)))
+ {
+ (void) snpf(Namech, Namechl - 1,
+ "dv_node snode at %s: can't read real vnode: %s",
+ print_kptr(da, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)s.s_realvp, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+/*
+ * Read the real vnode's dv_node.
+ */
+ if (!rv.v_data || kread((KA_T)rv.v_data, (char *)dv, sizeof(rv))) {
+ (void) snpf(Namech, Namechl - 1,
+ "dv_node real vnode at %s: can't read dv_node: %s",
+ print_kptr((KA_T)s.s_realvp, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)rv.v_data, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+/*
+ * Return the device number of the underlying file system, if possible.
+ */
+ if (rv.v_vfsp && !kread((KA_T)rv.v_vfsp, (char *)&v, sizeof(v))) {
+ *dev = v.vfs_dev;
+ *devs = 1;
+ }
+ return(0);
+}
+#endif /* solaris<100000 */
diff --git a/dialects/sun/dnode1.c b/dialects/sun/dnode1.c
new file mode 100644
index 0000000..ac279e5
--- /dev/null
+++ b/dialects/sun/dnode1.c
@@ -0,0 +1,441 @@
+/*
+ * dnode1.h - Solaris AFS support
+ */
+
+
+/*
+ * Copyright 1996 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 1996 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dnode1.c,v 1.9 2005/08/08 19:55:41 abe Exp $";
+#endif
+
+
+#if defined(HAS_AFS)
+#include "lsof.h"
+
+#include <rpc/xdr.h>
+#define __XDR_INCLUDE__
+#define int32 old_solaris_int32
+
+# if solaris>=20600
+#undef SHARED
+#undef PRIVATE
+# endif /* solaris>=20600 */
+
+#include <afs/param.h>
+#include <afs/afsint.h>
+#include <afs/vldbint.h>
+
+
+/*
+ * This is an emulation of the afs_rwlock_t definition that appears in
+ * the AFS sources in afs/lock.h.
+ */
+
+# if defined(AFS_SUN5_ENV)
+#define AFS_NOBOZO_LOCK
+# endif /* defined(AFS_SUN5_ENV) */
+
+#define INSTRUMENT_LOCKS
+
+# if defined(AFS_FINEGR_SUNLOCK)
+typedef kmutex_ afs_lock_t;
+typedef krwlock_t afs_rwlock_t;
+# endif /* !defined(AFS_FINEGR_SUNLOCK) */
+
+struct afs_lock {
+
+# if solaris>=20500
+ unsigned char d1[2];
+ unsigned short d1_5[3];
+# else /* solaris < 20500 */
+ unsigned char d1[4];
+# endif /* solaris>=20500 */
+
+ struct timeval d2;
+
+# if defined(INSTRUMENT_LOCKS)
+ unsigned int d3[3];
+# endif /* defined(INSTRUMENT_LOCKS) */
+
+};
+typedef struct afs_lock afs_lock_t;
+typedef struct afs_lock afs_rwlock_t;
+
+
+/*
+ * This is an emulation of the afs_bozoLock_t definition that appears in
+ * the AFS sources in afs/lock.h.
+ */
+
+struct afs_bozoLock {
+ short d1;
+ char d2[2];
+ char *d3;
+};
+
+# if !defined(AFS_NOBOZO_LOCK)
+typedef struct afs_bozoLock afs_bozoLock_t;
+# else /* defined(AFS_NOBOZO_LOCK) */
+# if defined(AFS_SUN5_ENV)
+typedef kmutex_t afs_bozoLock_t;
+# else /* !defined(AFS_SUN5_ENV) */
+typedef struct afs_bozoLock afs_bozoLock_t;
+# endif /* defined(AFS_SUN5_ENV) */
+# endif /* !defined(AFS_NOBOZO_LOCK) */
+
+#define KERNEL
+#include <afs/afs.h>
+#undef KERNEL
+
+
+/*
+ * Local function prototypes
+ */
+
+_PROTOTYPE(static struct volume *getvolume,(struct VenusFid *f, int *vols));
+_PROTOTYPE(static int is_rootFid,(struct vcache *vc, int *rfid));
+
+
+/*
+ * alloc_vcache() - allocate space for vcache structure
+ */
+
+struct vnode *
+alloc_vcache()
+{
+ return((struct vnode *)malloc(sizeof(struct vcache)));
+}
+
+
+/*
+ * ckAFSsym() - check for missing X_AFS_* symbols in AFS name list file
+ */
+
+void
+ckAFSsym(nl)
+ struct nlist *nl; /* copy of Nl[] when empty */
+{
+ char *path = AFSAPATHDEF;
+ int i;
+ KA_T v;
+
+# if defined(HASAOPT)
+ if (AFSApath)
+ path = AFSApath;
+# endif /* defined(HASAOPT) */
+
+/*
+ * If an alternate AFS name list file was specified, see if it can be read.
+ */
+ if (!is_readable(path, 0)) {
+ if (!Fwarn)
+ (void) fprintf(stderr,
+ "%s: WARNING: can't access AFS name list file: %s\n",
+ Pn, path);
+ return;
+ }
+/*
+ * Read the AFS modload symbols and compare its non-zero values with
+ * the non-zero values in Nl[]. Quit if there is any mis-match.
+ */
+ if (nlist(path, nl) < 0)
+ return;
+ for (i = 0; Nl[i].n_name && Nl[i].n_name[0]; i++) {
+ if (!nl[i].n_value || !Nl[i].n_value)
+ continue;
+ if (nl[i].n_value != Nl[i].n_value)
+ return;
+ }
+/*
+ * If any AFS symbol that doesn't have a value in Nl[] has one from
+ * the AFS modload file, copy its modload value to Nl[].
+ */
+ if ((i = get_Nl_value("arFid", Drive_Nl, &v)) >= 0
+ && !Nl[i].n_value && nl[i].n_value)
+ Nl[i].n_value = nl[i].n_value;
+ if ((i = get_Nl_value("avops", Drive_Nl, &v)) >= 0
+ && !Nl[i].n_value && nl[i].n_value)
+ Nl[i].n_value = nl[i].n_value;
+ if ((i = get_Nl_value("avol", Drive_Nl, &v)) >= 0
+ && !Nl[i].n_value && nl[i].n_value)
+ Nl[i].n_value = nl[i].n_value;
+}
+
+
+/*
+ * getvolume() - get volume structure
+ */
+
+static struct volume *
+getvolume(f, vols)
+ struct VenusFid *f; /* file ID pointer */
+ int *vols; /* afs_volumes status return */
+{
+ int i;
+ static KA_T ka = 0;
+ KA_T kh;
+ static struct volume v;
+ KA_T vp;
+ static int w = 0;
+
+ if (!ka) {
+ if (get_Nl_value("avol", Drive_Nl, &ka) < 0 || !ka) {
+ if (!w && !Fwarn) {
+ (void) fprintf(stderr,
+ "%s: WARNING: no kernel address for afs_volumes\n", Pn);
+ (void) fprintf(stderr,
+ " This may hamper AFS node number reporting.\n");
+ w = 1;
+ }
+ *vols = 0;
+ return((struct volume *)NULL);
+ }
+ }
+ *vols = 1;
+ i = (NVOLS - 1) & f->Fid.Volume;
+ kh = (KA_T)((char *)ka + (i * sizeof(struct volume *)));
+ if (kread(kh, (char *)&vp, sizeof(vp)))
+ return((struct volume *)NULL);
+ while (vp) {
+ if (kread((KA_T)vp, (char *)&v, sizeof(v)))
+ return((struct volume *)NULL);
+ if (v.volume == f->Fid.Volume && v.cell == f->Cell)
+ return(&v);
+ vp = (KA_T)v.next;
+ }
+ return((struct volume *)NULL);
+}
+
+
+/*
+ * hasAFS() - test for AFS presence via vfs structure
+ */
+
+int
+hasAFS(vp)
+ struct vnode *vp; /* vnode pointer */
+{
+ struct mounts *mp;
+ int n;
+ struct vfs v;
+/*
+ * If this vnode has a v_data pointer, then it probably isn't an AFS vnode;
+ * return FALSE.
+ *
+ * If the vfs struct address of /afs is known and this vnode's v_vfsp matches
+ * it, return TRUE.
+ *
+ * Read this vnode's vfs structure and see if it's device (fsid.val[0]) is
+ * AFSdev. If it is, record the AFS vfs struct address and return TRUE.
+ */
+ if (AFSVfsp && !vp->v_data && (KA_T)vp->v_vfsp == AFSVfsp)
+ return(1);
+ if (!AFSdevStat)
+ (void) readmnt();
+ if (!AFSdevStat
+ || vp->v_data
+ || !vp->v_vfsp
+ || kread((KA_T)vp->v_vfsp, (char *)&v, sizeof(v))
+ || v.vfs_data)
+ return(0);
+ if ((dev_t)v.vfs_fsid.val[0] == AFSdev) {
+ AFSVfsp = (KA_T)vp->v_vfsp;
+ return(1);
+ }
+/*
+ * Search the local mount table for /afs devices. Count /afs devices,
+ * and skip a device number test for them. A match on device number for
+ * non-AFS devices produces a FALSE return.
+ */
+ for (mp = readmnt(), n = 0; mp; mp = mp->next) {
+ if (AFSdevStat && mp->dev == AFSdev
+ && mp->dir && strcmp(mp->dir, "/afs") == 0
+ && mp->fsname && strcmp(mp->fsname, "AFS") == 0)
+ n++;
+ else if (mp->dev == (dev_t)v.vfs_fsid.val[0])
+ return(0);
+ }
+/*
+ * If there is exactly one /afs device, assume its vfs struct address is
+ * the one for this vnode, record it, and return TRUE.
+ */
+ if (n == 1) {
+ AFSVfsp = (KA_T)vp->v_vfsp;
+ return(1);
+ }
+ return(0);
+}
+
+
+/*
+ * is_rootFid() - is the file ID the root file ID
+ *
+ * return: 0 = is not root file ID
+ * 1 = is root file ID
+ * rfid = 0 if root file ID structure address not available
+ * 1 if root file ID structure address available
+ */
+
+static int
+is_rootFid(vc, rfid)
+ struct vcache *vc; /* vcache structure */
+ int *rfid; /* root file ID pointer status return */
+{
+ KA_T arFid;
+ char *err;
+ static int f = 0; /* rootFid structure status:
+ * -1 = unavailable
+ * 0 = not yet accessed
+ * 1 = available */
+ static struct VenusFid r;
+ static int w = 0;
+
+ switch (f) {
+ case -1:
+ if (vc->v.v_flag & VROOT) {
+ *rfid = 1;
+ return(1);
+ }
+ *rfid = 0;
+ return(0);
+ case 0:
+ if (get_Nl_value("arFid", Drive_Nl, &arFid) < 0 || !arFid) {
+ err = "no afs_rootFid kernel address";
+
+rfid_unavailable:
+
+ if (!w && !Fwarn) {
+ (void) fprintf(stderr,
+ "%s: WARNING: AFS root Fid error: %s\n", Pn, err);
+ (void) fprintf(stderr,
+ " This may hamper AFS node number reporting.\n");
+ w = 1;
+ }
+ f = -1;
+ if (vc->v.v_flag & VROOT) {
+ *rfid = 1;
+ return(1);
+ }
+ *rfid = 0;
+ return(0);
+ }
+ if (kread(arFid, (char *)&r, sizeof(r))) {
+ err = "can't read afs_rootFid from kernel";
+ goto rfid_unavailable;
+ }
+ f = 1;
+ /* fall through */
+ case 1:
+ *rfid = 1;
+ if (vc->fid.Fid.Unique == r.Fid.Unique
+ && vc->fid.Fid.Vnode == r.Fid.Vnode
+ && vc->fid.Fid.Volume == r.Fid.Volume
+ && vc->fid.Cell == r.Cell)
+ return(1);
+ }
+ *rfid = 0;
+ return(0);
+}
+
+
+/*
+ * readafsnode() - read AFS node
+ */
+
+int
+readafsnode(va, v, an)
+ KA_T va; /* kernel vnode address */
+ struct vnode *v; /* vnode buffer pointer */
+ struct afsnode *an; /* afsnode recipient */
+{
+ char *cp, tbuf[32];
+ KA_T ka;
+ int len, rfid, vols;
+ struct vcache *vc;
+ struct volume *vp;
+
+ cp = ((char *)v + sizeof(struct vnode));
+ ka = (KA_T)((char *)va + sizeof(struct vnode));
+ len = sizeof(struct vcache) - sizeof(struct vnode);
+ if (kread(ka, cp, len)) {
+ (void) snpf(Namech, Namechl,
+ "vnode at %s: can't read vcache remainder from %s",
+ print_kptr(va, tbuf, sizeof(tbuf)),
+ print_kptr(ka, (char *)NULL, 0));
+ enter_nm(Namech);
+ return(1);
+ }
+ vc = (struct vcache *)v;
+ if (!AFSdevStat)
+ (void) readmnt();
+ an->dev = AFSdevStat ? AFSdev: 0;
+ an->size = (unsigned long)vc->m.Length;
+ an->nlink = (long)vc->m.LinkCount;
+ an->nlink_st = 1;
+/*
+ * Manufacture the "inode" number.
+ */
+ if (vc->mvstat == 2) {
+ if ((vp = getvolume(&vc->fid, &vols))) {
+ an->inode = (INODETYPE)((vp->mtpoint.Fid.Vnode
+ + (vp->mtpoint.Fid.Volume << 16))
+ & 0x7fffffff);
+ if (an->inode == (INODETYPE)0) {
+ if (is_rootFid(vc, &rfid))
+ an->ino_st = 1;
+ else if (rfid) {
+ an->inode = (INODETYPE)2;
+ an->ino_st = 1;
+ } else
+ an->ino_st = 0;
+ } else
+ an->ino_st = 1;
+ } else {
+ if (vols) {
+ an->inode = (INODETYPE)2;
+ an->ino_st = 1;
+ } else {
+ if (v->v_flag & VROOT) {
+ an->inode = (INODETYPE)0;
+ an->ino_st = 1;
+ } else
+ an->ino_st = 0;
+ }
+ }
+ } else {
+ an->inode = (INODETYPE)((vc->fid.Fid.Vnode
+ + (vc->fid.Fid.Volume << 16))
+ & 0x7fffffff);
+ an->ino_st = 1;
+ }
+ return(0);
+}
+#endif /* defined(HAS_AFS) */
diff --git a/dialects/sun/dnode2.c b/dialects/sun/dnode2.c
new file mode 100644
index 0000000..9d6a94f
--- /dev/null
+++ b/dialects/sun/dnode2.c
@@ -0,0 +1,518 @@
+/*
+ * dnode2.c - Solaris node functions for lsof
+ *
+ * This module must be separate to keep separate the multiple kernel inode
+ * structure definitions.
+ */
+
+
+/*
+ * Copyright 1997 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dnode2.c,v 1.23 2010/01/18 19:03:54 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+#if defined(HASVXFS)
+
+# if defined(HASVXFSUTIL)
+#include <vxfsutil.h>
+#define EMSGPFX "vx_inode: "
+
+_PROTOTYPE(static char *add2em,(char * em, char *fmt, char *arg));
+_PROTOTYPE(static char *ckptr,(char * em, char *ptr, int len, int slen,
+ char *nm));
+_PROTOTYPE(static char *getioffs,(char **vx, int *vxl,
+ char **dev, int *devl,
+ char **ino, int *inol,
+ char **nl, int *nll,
+ char **sz, int *szl));
+# else /* !defined(HASVXFSUTIL) */
+# if defined(HASVXFS_FS_H) && !defined(HASVXFS_VX_INODE)
+#undef fs_bsize
+#include <sys/fs/vx_fs.h>
+# endif /* defined(HASVXFS_FS_H) && !defined(HASVXFS_VX_INODE) */
+
+# if HASVXFS_SOL_H
+#include <sys/fs/vx_sol.h>
+# endif /* defined(HSVXFS_SOL_H) */
+
+# if defined(HASVXFS_SOLARIS_H) && defined(HASVXFS_U64_T)
+#include <sys/fs/vx_solaris.h>
+# endif /* defined(HASVXFS_SOLARIS_H) && defined(HASVXFS_U64_T) */
+
+# if defined(HASVXFS_MACHDEP_H)
+# if defined(HASVXFS_OFF32_T) && solaris>=70000
+#define off32_t VXFS_off32_t
+# endif /* defined(HASVXFS_OFF32_T) && solaris>=70000 */
+#include <sys/fs/vx_machdep.h>
+# endif /* defined(HASVXFS_MACHDEP_H) */
+
+# if defined(HASVXFS_SOLARIS_H)
+struct kdm_vnode { /* dummy for <sys/fs/vx_inode.h> */
+ int d1;
+};
+#undef fs_bsize
+#define uint16_t VXFS_uint16_t
+
+# if defined(HASVXFS_OFF64_T)
+#define off64_t VXFS_off64_t
+# endif /* defined(HASVXFS_OFF64_T) */
+
+# if defined(HASVXFS_SOLARIS_H) && !defined(HASVXFS_U64_T)
+#include <sys/fs/vx_solaris.h>
+# endif /* defined(HASVXFS_SOLARIS_H) && !defined(HASVXFS_U64_T) */
+
+#include <sys/fs/vx_layout.h>
+#include <sys/fs/vx_const.h>
+#include <sys/fs/vx_mlink.h>
+# endif /* defined(HASVXFS_SOLARIS_H) */
+
+#include <sys/fs/vx_inode.h>
+# endif /* defined(HASVXFSUTIL) */
+
+
+# if defined(HASVXFSUTIL)
+static struct vx_ioffsets Ioffsets; /* VXFS inode offsets */
+static int Ioffs_state = -1; /* Ioffsets state:
+ * -1 = uninitialized
+ * 0 = initialized
+ * >0 = initialization error */
+
+
+/*
+ * access_vxfs_ioffsets() - access the VXFS inode offsets
+ */
+
+extern int
+access_vxfs_ioffsets()
+{
+
+/*
+ * This operation is done in an external function, so it can be done before
+ * GID permission has been surrendered.
+ */
+ Ioffs_state = vxfsu_get_ioffsets(&Ioffsets, sizeof(Ioffsets));
+ return(Ioffs_state);
+}
+
+
+/*
+ * add2em() - add to error message
+ */
+
+static char *
+add2em(em, fmt, arg)
+ char *em; /* current error message */
+ char *fmt; /* message format */
+ char *arg; /* format's single string argument */
+{
+ MALLOC_S al, eml, nl;
+ char msg[1024];
+ MALLOC_S msgl = (MALLOC_S)sizeof(msg);
+
+ (void) snpf(msg, msgl, fmt, arg);
+ msg[msgl - 1] = '\0';
+ nl = (MALLOC_S)strlen(msg);
+ if (!em) {
+ al = (MALLOC_S)strlen(EMSGPFX) + nl + 1;
+ em = (char *)malloc((MALLOC_S)al);
+ eml = (MALLOC_S)0;
+ } else {
+ if (!(eml = (MALLOC_S)strlen(em))) {
+ (void) fprintf(stderr, "%s: add2em: previous message empty\n",
+ Pn);
+ Exit(1);
+ }
+ al = eml + nl + 3;
+ em = (char *)realloc((MALLOC_P *)em, al);
+ }
+ if (!em) {
+ (void) fprintf(stderr, "%s: no VxFS error message space\n", Pn);
+ Exit(1);
+ }
+ (void) snpf(em + eml, al - eml, "%s%s%s",
+ eml ? "" : EMSGPFX,
+ eml ? "; " : "",
+ msg);
+ return(em);
+}
+
+
+/*
+ * ckptr() - check pointer and length
+ */
+
+static char *
+ckptr(em, ptr, len, slen, nm)
+ char *em; /* pointer to previous error message */
+ char *ptr; /* pointer to check */
+ int len; /* pointer's value length */
+ int slen; /* value's storage length */
+ char *nm; /* element name */
+{
+
+#if defined(_LP64)
+#define PTR_CAST unsigned long long
+#else /* !defined(_LP64) */
+#define PTR_CAST unsigned long
+#endif /* defined(_LP64) */
+
+ PTR_CAST m;
+ char tbuf[1024];
+
+ if (!ptr)
+ return(add2em(em, "no %s pointer", nm ? nm : "(null)"));
+ if (len > slen) {
+ (void) snpf(tbuf, sizeof(tbuf) - 1,
+ "%s size, %d, > %d",
+ nm ? nm : "(null)",
+ len, slen);
+ tbuf[sizeof(tbuf) - 1] = '\0';
+ return(add2em(em, "%s", tbuf));
+ }
+ if ((m = (PTR_CAST)(len - 1)) < (PTR_CAST)1)
+ return(em);
+ if ((PTR_CAST)ptr & m)
+ return(add2em(em, "%s misaligned", nm ? nm : "(null)"));
+ return(em);
+}
+
+
+/*
+ * getioffs() - get the vx_inode offsets
+ */
+
+static char *
+getioffs(vx, vxl, dev, devl, ino, inol, nl, nll, sz, szl)
+ char **vx; /* pointer to allocated vx_inode space */
+ int *vxl; /* sizeof(*vx) */
+ char **dev; /* pointer to device number element of *vx */
+ int *devl; /* sizeof(*dev) */
+ char **ino; /* pointer to node number element of *vx */
+ int *inol; /* sizeof(*ino) */
+ char **nl; /* pointer to nlink element of *vx */
+ int *nll; /* sizeof(*nl) */
+ char **sz; /* pointer to size element of *vx */
+ int *szl; /* sizeof(*sz) */
+{
+ char *tv;
+ int tvl;
+
+ if (Ioffs_state)
+ return(add2em((char *)NULL, "%s error", "vxfsu_get_ioffsets"));
+ tvl = (int)(Ioffsets.ioff_dev + Ioffsets.ioff_dev_sz);
+ if ((Ioffsets.ioff_nlink + Ioffsets.ioff_nlink_sz) > tvl)
+ tvl = (int)(Ioffsets.ioff_nlink + Ioffsets.ioff_nlink_sz);
+ if ((Ioffsets.ioff_number + Ioffsets.ioff_number_sz) > tvl)
+ tvl = (int)(Ioffsets.ioff_number + Ioffsets.ioff_number_sz);
+ if ((Ioffsets.ioff_size + Ioffsets.ioff_size_sz) > tvl)
+ tvl = (int)(Ioffsets.ioff_size + Ioffsets.ioff_size_sz);
+ if (!tvl)
+ return(add2em((char *)NULL, "zero length %s", "vx_inode"));
+ if (!(tv = (char *)malloc((MALLOC_S)tvl))) {
+ (void) fprintf(stderr, "%s: no vx_inode space\n", Pn);
+ Exit(1);
+ }
+ *vx = tv;
+ *vxl = tvl;
+ *dev = tv + Ioffsets.ioff_dev;
+ *devl = (int)Ioffsets.ioff_dev_sz;
+ *ino = tv + Ioffsets.ioff_number;
+ *inol = (int)Ioffsets.ioff_number_sz;
+ *nl = tv + Ioffsets.ioff_nlink;
+ *nll = (int)Ioffsets.ioff_nlink_sz;
+ *sz = tv + Ioffsets.ioff_size;
+ *szl = (int)Ioffsets.ioff_size_sz;
+ return((char *)NULL);
+}
+
+
+# if defined(HASVXFSRNL)
+
+#define RNLCINIT 64 /* inital RNL cache size */
+#define RNLCINCR 32 /* RNL cache increment */
+
+/*
+ * print_vxfs_rnl_path() -- print VxFS RNL path
+ */
+
+int
+print_vxfs_rnl_path(lf)
+ struct lfile *lf; /* file whose name is to be printed */
+{
+ char **bp = (char **)NULL;
+ int i, j, n, p;
+ typedef struct rmc { /* RNL mount point cache */
+ char *mp; /* mount point */
+ unsigned char s; /* RNL status: 0 = supported
+ * 1 = not supported */
+ } rmc_t;
+ static rmc_t *rm = (rmc_t *)NULL;
+ /* RNL mount point cache */
+ static int rma = 0; /* allocated cache entries */
+ static int rmu = 0; /* used cache entries */
+ size_t sz;
+/*
+ * This must be a VxFS file, it must have an inode and its mount point must
+ * be known.
+ */
+ if (!lf->is_vxfs || (lf->inp_ty != 1) || !lf->fsdir)
+ return(0);
+/*
+ * Locate or create an RNL mount point cache entry.
+ */
+ for (i = 0; i < rmu; i++) {
+ if (rm[i].mp == lf->fsdir)
+ break;
+ }
+ if (i >= rmu) {
+
+ /*
+ * A new entry must be created.
+ */
+ if (i >= rma) {
+
+ /*
+ * RNL mount point cache space must be allocated.
+ */
+ rma += rm ? RNLCINCR : RNLCINIT;
+ sz = (size_t)(rma * sizeof(rmc_t));
+ if (rm)
+ rm = (rmc_t *)realloc((MALLOC_P *)rm, (MALLOC_S)sz);
+ else
+ rm = (rmc_t *)malloc((MALLOC_S)sz);
+ if (!rm) {
+ (void) fprintf(stderr,
+ "%s: no RNL mount point cache space\n", Pn);
+ Exit(1);
+ }
+ }
+ i = rmu;
+ rm[rmu].mp = lf->fsdir;
+ rm[rmu++].s = 0;
+ }
+ if (rm[i].s)
+ return(0);
+/*
+ * Get the RNL path for this mount point and inode.
+ */
+ if (vxfs_inotopath(lf->fsdir, (uint64_t)lf->inode, 0, &bp, &n)) {
+ if (errno == ENOTSUP)
+ rm[i].s = 1;
+ return(0);
+ }
+/*
+ * Print the first RNL path, then free the allocated function reply space.
+ */
+ if (bp) {
+ for (j = 0; j < n; j++) {
+ if (bp[j] && *bp[j]) {
+ safestrprt(bp[j], stdout, 0);
+ p = 1;
+ break;
+ }
+ }
+ for (j = 0; j < n; j++) {
+ if (bp[j])
+ (void) free((FREE_P *)bp[j]);
+ }
+ (void) free((FREE_P *)bp);
+ } else
+ p = 0;
+ return(p);
+}
+# endif /* defined(HASVXFSRNL) */
+# endif /* defined(HASVXFSUTIL) */
+
+
+/*
+ * read_vxnode() - read Veritas file system inode information
+ */
+
+int
+read_vxnode(va, v, vfs, fx, li, vnops)
+ KA_T va; /* containing vnode's address */
+ struct vnode *v; /* containing vnode */
+ struct l_vfs *vfs; /* local vfs structure */
+ int fx; /* file system index (-1 if none) */
+ struct l_ino *li; /* local inode value receiver */
+ KA_T *vnops; /* table of VxFS v_op values */
+{
+ struct vnode cv;
+ char tbuf[32];
+
+# if defined(HASVXFS_VX_INODE)
+ struct vx_inode vx;
+ int vxl = (int)sizeof(vx);
+ dev_t *vxn_dev = (dev_t *)&vx.i_dev;
+ int *vxn_nlink = (int *)&vx.i_nlink;
+ unsigned int *vxn_ino = (unsigned int *)&vx.i_number;
+ SZOFFTYPE *vxn_sz = (SZOFFTYPE *)&vx.i_size;
+ char *vxp = (char *)&vx;
+# else /* !defined(HASVXFS_VX_INODE) */
+# if defined(HASVXFSUTIL)
+ static char *em = (char *)NULL;
+ int devl, nll, szl;
+ static int inol;
+ static char *vxp = (char *)NULL;
+ static int vxl = 0;
+ static dev_t *vxn_dev = (dev_t *)NULL;
+ static int *vxn_nlink = (int *)NULL;
+ static char *vxn_ino = (char *)NULL;
+ static SZOFFTYPE *vxn_sz = (SZOFFTYPE *)NULL;
+# else /* !defined(HASVXFSUTIL) */
+ struct inode vx;
+ int vxl = sizeof(vx);
+ dev_t *vxn_dev = (dev_t *)&vx.i_dev;
+ int *vxn_nlink = (int *)&vx.i_nlink;
+ long *vxn_ino = (long *)&vx.i_number;
+ SZOFFTYPE *vxn_sz = (SZOFFTYPE *)&vx.i_size;
+ char *vxp = (char &)&vx;
+# endif /* defined(HASVXFSUTIL) */
+# endif /* defined(HASVXFS_VX_INODE) */
+
+ li->dev_def = li->ino_def = li->nl_def = li->rdev_def = li->sz_def = 0;
+/*
+ * See if this is vnode is served by fdd_chain_vnops. If it is, its
+ * v_data pointer leads to the "real" vnode.
+ */
+ if (v->v_data && v->v_op && (VXVOP_FDDCH < VXVOP_NUM)
+ && vnops[VXVOP_FDDCH] && ((KA_T)v->v_op == vnops[VXVOP_FDDCH]))
+ {
+ if (kread((KA_T)v->v_data, (char *)&cv, sizeof(cv))) {
+ (void) snpf(Namech, Namechl,
+ "node at %s: can't read real vx vnode: %s",
+ print_kptr(va, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return(1);
+ }
+
+# if defined(HASNCACHE)
+ Lf->na = (KA_T)v->v_data;
+# endif /* defined(HASNCACHE) */
+
+ *v = cv;
+ Ntype = vop2ty(v, fx);
+ }
+
+# if defined(HASVXFSUTIL)
+/*
+ * If libvxfsutil[64].a is in use, establish the vx_inode size and the
+ * locations and sizes of its device, link count, node number, and size
+ * elements.
+ *
+ * If an error was detected while determining the vx_inode values, repeat
+ * the error explanation in the NAME column.
+ */
+ if (!vxp && !em) {
+ em = getioffs(&vxp, &vxl,
+ (char **)&vxn_dev, &devl,
+ &vxn_ino, &inol,
+ (char **)&vxn_nlink, &nll,
+ (char **)&vxn_sz, &szl);
+ if (!em) {
+
+ /*
+ * Check the returned pointers and their sizes.
+ */
+ em = ckptr(em, (char *)vxn_dev, devl, sizeof(dev_t), "dev");
+ em = ckptr(em, (char *)vxn_ino, inol, sizeof(INODETYPE), "ino");
+ em = ckptr(em, (char *)vxn_nlink, nll, sizeof(int), "nlink");
+ em = ckptr(em, (char *)vxn_sz, szl, sizeof(SZOFFTYPE), "sz");
+ }
+ }
+ if (em) {
+ (void) snpf(Namech, Namechl, "%s", em);
+ (void) enter_nm(Namech);
+ return(1);
+ }
+# endif /* !defined(HASVXFSUTIL) */
+
+/*
+ * Read vnode's vx_inode.
+ */
+ if (!v->v_data || kread((KA_T)v->v_data, vxp, vxl)) {
+ (void) snpf(Namech, Namechl, "node at %s: can't read vx_inode: %s",
+ print_kptr(va, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+ (void) enter_nm(Namech);
+ return(1);
+ }
+/*
+ * Return device number, inode number, link count, raw device number, and size.
+ */
+ if (vfs && vfs->fsname) {
+ li->dev = (dev_t)vfs->dev;
+ li->dev_def = 1;
+ } else if (vxn_dev) {
+ li->dev = (dev_t)*vxn_dev;
+ li->dev_def = 1;
+ }
+ if (vxn_ino) {
+
+# if defined(HASVXFSUTIL)
+ switch (inol) {
+ case sizeof(short):
+ li->ino = (INODETYPE)*((short *)vxn_ino);
+ li->ino_def = 1;
+ break;
+ case sizeof(unsigned int):
+ li->ino = (INODETYPE)*((unsigned int *)vxn_ino);
+ li->ino_def = 1;
+ break;
+ case sizeof(unsigned long long):
+ li->ino = (INODETYPE)*((unsigned long long *)vxn_ino);
+ li->ino_def = 1;
+ break;
+ default:
+ break;
+ }
+# else /* !defined(HASVXFSUTIL) */
+ li->ino = (INODETYPE)*vxn_ino;
+ li->ino_def = 1;
+# endif /* defined(HASVXFSUTIL) */
+
+ }
+ if (vxn_nlink) {
+ li->nl = (long)*vxn_nlink;
+ li->nl_def = 1;
+ }
+ li->rdev = v->v_rdev;
+ li->rdev_def = 1;
+ if (vxn_sz) {
+ li->sz = (SZOFFTYPE)*vxn_sz;
+ li->sz_def = 1;
+ }
+ return(0);
+}
+#endif /* defined(HASVXFS) */
diff --git a/dialects/sun/dproc.c b/dialects/sun/dproc.c
new file mode 100644
index 0000000..eecdf1f
--- /dev/null
+++ b/dialects/sun/dproc.c
@@ -0,0 +1,2239 @@
+/*
+ * dproc.c - Solaris lsof functions for accessing process information
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dproc.c,v 1.36 2010/01/18 19:03:54 abe Exp $";
+#endif
+
+#include "lsof.h"
+
+#if solaris<20500
+#include "kernelbase.h"
+#endif /* solaris<20500 */
+
+#if defined(HAS_CRED_IMPL_H)
+# if solaris>=110000
+#define _KERNEL
+# endif /* solaris>=110000 */
+
+#include <sys/cred_impl.h>
+
+# if solaris>=110000
+#undef _KERNEL
+# endif /* solaris>=110000 */
+#endif /* defined(HAS_CRED_IMPL_H) */
+
+
+/*
+ * Local definitions
+ */
+
+#if defined(__sparc) || defined(__sparcv9)
+#define ARCH64B "sparcv9"
+#else /* !defined(__sparc) && !defined(__sparcv9) */
+# if defined(__i386) || defined(__amd64)
+#define ARCH64B "amd64"
+# endif /* defined(__i386) || defined(__amd64) */
+#endif /* defined(__sparc) || defined(__sparcv9) */
+
+#if solaris>=20501
+#define KVMHASHBN 8192 /* KVM hash bucket count -- MUST BE
+ * A POWER OF 2!!! */
+#define HASHKVM(va) ((int)((va * 31415) >> 3) & (KVMHASHBN-1))
+ /* virtual address hash function */
+
+# if solaris<70000
+#define KAERR (u_longlong_t)-1 /* kvm_physaddr() error return */
+#define KBUFT char /* kernel read buffer type */
+#define KPHYS u_longlong_t /* kernel physical address type */
+#define KVIRT u_int /* kernel virtual address type */
+# else /* solaris>=70000 */
+#define KAERR (uint64_t)-1 /* kvm_physaddr() error return */
+#define KBUFT void /* kernel read buffer type */
+#define KPHYS uint64_t /* kernel physical address type */
+#define KVIRT uintptr_t /* kernel virtual address type */
+# endif /* solaris<70000 */
+#endif /* solaris>=20501 */
+
+
+/*
+ * Local structures
+ */
+
+#if solaris>=20501
+typedef struct kvmhash {
+ KVIRT vpa; /* virtual page address */
+ KPHYS pa; /* physical address */
+ struct kvmhash *nxt; /* next virtual address */
+} kvmhash_t;
+#endif /* solaris>=20501 */
+
+
+/*
+ * Local variables
+ */
+
+#if solaris>=20501
+static struct as *Kas = (struct as *)NULL;
+ /* pointer to kernel's address space
+ * map in kernel virtual memory */
+static kvmhash_t **KVMhb = (kvmhash_t **)NULL;
+ /* KVM hash buckets */
+static int PageSz = 0; /* page size */
+static int PSMask = 0; /* page size mask */
+static int PSShft = 0; /* page size shift */
+
+# if solaris<70000
+static struct as Kam; /* kernel's address space map */
+static int Kmd = -1; /* memory device file descriptor */
+# endif /* solaris<70000 */
+#endif /* solaris>=20501 */
+
+#if solaris>=20500
+static KA_T Kb = (KA_T)NULL; /* KERNELBASE for Solaris 2.5 */
+#endif /* solaris>=20500 */
+
+static int Np; /* number of P[], Pgid[] and Pid[]
+ * entries */
+static int Npa = 0; /* number of P[], Pgid[] and Pid[]
+ * entries for which space has been
+ * allocated */
+static struct proc *P = NULL; /* local proc structure table */
+static int *Pgid = NULL; /* process group IDs for P[] entries */
+static int *Pid = NULL; /* PIDs for P[] entries */
+static KA_T PrAct = (KA_T)NULL; /* kernel's *practive address */
+static gid_t Savedgid; /* saved (effective) GID */
+static KA_T Sgvops; /* [_]segvn_ops address */
+static int Switchgid = 0; /* must switch GIDs for kvm_open() */
+
+#if defined(HASZONES)
+static znhash_t **ZoneNm = (znhash_t **)NULL;
+ /* zone names hash buckets */
+#endif /* defined(HASZONES) */
+
+
+/*
+ * Local function prototypes
+ */
+
+_PROTOTYPE(static void get_kernel_access,(void));
+_PROTOTYPE(static void process_text,(KA_T pa));
+_PROTOTYPE(static void read_proc,(void));
+_PROTOTYPE(static void readfsinfo,(void));
+
+#if solaris>=20501
+_PROTOTYPE(static void readkam,(KA_T addr));
+#endif /* solaris>=20501 */
+
+#if solaris>=20501 && solaris<70000
+_PROTOTYPE(extern u_longlong_t kvm_physaddr,(kvm_t *, struct as *, u_int));
+#endif /* solaris>=20501 && solaris<70000 */
+
+#if defined(HASZONES)
+_PROTOTYPE(static int hash_zn,(char *zn));
+#endif /* defined(HASZONES) */
+
+
+
+/*
+ * close_kvm() - close kernel virtual memory access
+ */
+
+void
+close_kvm()
+{
+ if (!Kd)
+ return;
+ if (Kd) {
+ if (kvm_close(Kd) != 0) {
+ (void) fprintf(stderr, "%s: kvm_close failed\n", Pn);
+ Exit(1);
+ }
+ Kd = (kvm_t *)NULL;
+ }
+
+#if solaris>=20501 && solaris<70000
+ if (Kmd >= 0) {
+ (void) close(Kmd);
+ Kmd = -1;
+ }
+#endif /* solaris>=20501 && solaris<70000 */
+
+}
+
+
+/*
+ * 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 */
+ static int ft = 1;
+ int i, j;
+ struct proc *p;
+ int pgid, pid, px;
+ long pofv;
+ short pss, sf;
+ struct user *u;
+ uid_t uid;
+
+#if solaris>=20400
+ int k;
+
+# if !defined(NFPCHUNK)
+#define uf_ofile uf_file
+#define uf_pofile uf_flag
+#define u_flist u_finfo.fi_list
+#define u_nofiles u_finfo.fi_nfiles
+#define NFPREAD 64
+# else /* defined(NFPCHUNK) */
+#define NFPREAD NFPCHUNK
+# endif /* !defined(NFPCHUNK) */
+ uf_entry_t uf[NFPREAD];
+#endif /* solaris>=20400 */
+#if solaris>=20500
+ struct cred pc;
+#endif /* solaris>=20500 */
+
+#if defined(HASZONES)
+ struct zone z;
+ int zh;
+ char zn[ZONENAME_MAX + 1];
+ znhash_t *zp, *zpn;
+#endif /* defined(HASZONES) */
+
+ if (ft) {
+/*
+ * Do first-time only operations.
+ */
+ /*
+ * Get the segment vnodeops address.
+ */
+ if (get_Nl_value("sgvops", Drive_Nl, &Sgvops) < 0)
+ Sgvops = (KA_T)NULL;
+ ft = 0;
+ } else if (!HasALLKMEM) {
+
+ /*
+ * If not the first time and the ALLKMEM device isn't available, it is
+ * necessary to close and reopen the KVM device, so that kvm_open()
+ * will acquire a fresh address for the head of the linked list process
+ * table.
+ */
+ close_kvm();
+ open_kvm();
+
+#if solaris>=20501
+ /*
+ * If not the first time and the ALLKMEM device isn't available,
+ * re-read the kernel's address space map.
+ */
+ readkam((KA_T)NULL);
+#endif /* solaris>=20501 */
+
+ }
+/*
+ * Define socket and regular file conditional processing flags.
+ *
+ * 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;
+ }
+/*
+ * Read the process table.
+ */
+ read_proc();
+/*
+ * Loop through processes.
+ */
+ for (p = P, px = 0; px < Np; p++, px++) {
+
+ /*
+ * Get the process ID.
+ */
+
+ if (Fpgid)
+ pgid = Pgid[px];
+ else
+ pgid = 0;
+ pid = Pid[px];
+
+#if solaris<20500
+ uid = p->p_uid;
+#else /* solaris >=20500 */
+ /*
+ * Read credentials for Solaris 2.5 and above process.
+ */
+ if (kread((KA_T)p->p_cred, (char *)&pc, sizeof(pc)))
+ continue;
+ uid = pc.cr_uid;
+#endif /* solaris<20500 */
+
+ /*
+ * See if the process is excluded.
+ */
+ if (is_proc_excl(pid, pgid, (UID_ARG)uid, &pss, &sf))
+ continue;
+
+#if defined(HASZONES)
+ /*
+ * If the -z (zone) option was specified, get the zone name.
+ */
+ if (Fzone) {
+ zn[0] = zn[sizeof(zn) - 1] = '\0';
+ if (p->p_zone
+ && !kread((KA_T)p->p_zone, (char *)&z, sizeof(z)))
+ {
+ if (!z.zone_name
+ || kread((KA_T)z.zone_name, (char *)&zn, sizeof(zn) - 1))
+ zn[0] = '\0';
+ }
+ }
+#endif /* defined(HASZONES) */
+
+ /*
+ * Get the user area associated with the process.
+ */
+ u = &p->p_user;
+ /*
+ * Allocate a local process structure and start filling it.
+ */
+ if (is_cmd_excl(u->u_comm, &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(pid, pgid, (int)p->p_ppid, (UID_ARG)uid, u->u_comm,
+ (int)pss, (int)sf);
+ Plf = (struct lfile *)NULL;
+
+#if defined(HASZONES)
+ /*
+ * If zone processing is enabled and requested, and if there is a zone
+ * name:
+ *
+ * o Skip processes excluded by zone name.
+ * o Save zone name.
+ */
+ if (Fzone && zn[0]) {
+ zh = hash_zn(zn);
+ if (ZoneArg) {
+
+ /*
+ * See if zone name excludes the process.
+ */
+ for (zp = ZoneArg[zh]; zp; zp = zp->next) {
+ if (!strcmp(zn, zp->zn))
+ break;
+ }
+ if (!zp)
+ continue;
+ zp->f = 1;
+ Lp->pss |= PS_PRI;
+ Lp->sf |= SELZONE;
+ }
+ /*
+ * Make sure the zone name is cached, then save a pointer to it in
+ * the local proc structure.
+ */
+ if (!ZoneNm) {
+ if (!(ZoneNm = (znhash_t **)calloc(HASHZONE,
+ sizeof(znhash_t *))))
+ {
+ (void) fprintf(stderr,
+ "%s: no space for zone name hash\n", Pn);
+ Exit(1);
+ }
+ }
+ for (zp = ZoneNm[zh]; zp; zp = zp->next) {
+ if (!strcmp(zn, zp->zn))
+ break;
+ }
+ if (!zp) {
+
+ /*
+ * The zone name isn't cached, so cache it.
+ */
+ if (!(zp = (znhash_t *)malloc((MALLOC_S)sizeof(znhash_t))))
+ {
+ (void) fprintf(stderr,
+ "%s: no zone name cache space: %s\n", Pn, zn);
+ Exit(1);
+ }
+ if (!(zp->zn = mkstrcpy(zn, (MALLOC_S *)NULL))) {
+ (void) fprintf(stderr,
+ "%s: no zone name space at PID %d: %s\n",
+ Pn, (int)Lp->pid, zn);
+ Exit(1);
+ }
+ zp->next = ZoneNm[zh];
+ ZoneNm[zh] = zp;
+ }
+ Lp->zn = zp->zn;
+ }
+#endif /* defined(HASZONES) */
+
+ /*
+ * Save file count.
+ */
+ Unof = u->u_nofiles;
+ /*
+ * Save current working directory information.
+ */
+ if (!ckscko && u->u_cdir) {
+ alloc_lfile(CWD, -1);
+
+#if defined(FILEPTR)
+ FILEPTR = (struct file *)NULL;
+#endif /* defined(FILEPTR) */
+
+ process_node((KA_T)u->u_cdir);
+ if (Lf->sf)
+ link_lfile();
+ }
+ /*
+ * Save root directory information.
+ */
+ if (!ckscko && u->u_rdir) {
+ alloc_lfile(RTD, -1);
+
+#if defined(FILEPTR)
+ FILEPTR = (struct file *)NULL;
+#endif /* defined(FILEPTR) */
+
+ process_node((KA_T)u->u_rdir);
+ if (Lf->sf)
+ link_lfile();
+ }
+ /*
+ * Save information on text files.
+ */
+ if (!ckscko && p->p_as && Sgvops) {
+
+#if defined(FILEPTR)
+ FILEPTR = (struct file *)NULL;
+#endif /* defined(FILEPTR) */
+
+ process_text((KA_T)p->p_as);
+ }
+ /*
+ * Save information on file descriptors.
+ *
+ * Under Solaris the file pointers are stored in dynamically-linked
+ * ufchunk structures, each containing NFPREAD file pointers. The
+ * first ufchunk structure is in the user area.
+ *
+ * Under Solaris 2.4 the file pointers are in a dynamically allocated,
+ * contiguous memory block.
+ */
+
+#if solaris<20400
+ for (i = 0, j = 0; i < u->u_nofiles; i++) {
+ if (++j > NFPCHUNK) {
+ if (!u->u_flist.uf_next)
+ break;
+ if (kread((KA_T)u->u_flist.uf_next,
+ (char *)&u->u_flist, sizeof(struct ufchunk)))
+ break;
+ j = 1;
+ }
+ if (!u->u_flist.uf_ofile[j-1])
+#else /* solaris>=20400 */
+ for (i = 0, j = NFPREAD; i < u->u_nofiles; i++) {
+ if (++j > NFPREAD) {
+ k = u->u_nofiles - i;
+ if (k > NFPREAD)
+ k = NFPREAD;
+ if (kread((KA_T)((unsigned long)u->u_flist +
+ i * sizeof(uf_entry_t)),
+ (char*)&uf, k * sizeof(uf_entry_t)))
+ {
+ break;
+ }
+ j = 1;
+ }
+ if (!uf[j-1].uf_ofile)
+#endif /* solaris<20400 */
+
+ continue;
+ alloc_lfile((char *)NULL, i);
+
+#if solaris<20400
+ pofv = (long)u->u_flist.uf_pofile[j-1];
+ process_file((KA_T)u->u_flist.uf_ofile[j-1]);
+#else /* solaris>=20400 */
+ pofv = uf[j-1].uf_pofile;
+ process_file((KA_T)uf[j-1].uf_ofile);
+#endif /* solaris <20400 */
+
+ if (Lf->sf) {
+
+#if defined(HASFSTRUCT)
+ if (Fsv & FSV_FG)
+ Lf->pof = pofv;
+#endif /* defined(HASFSTRUCT) */
+
+ link_lfile();
+ }
+ }
+ /*
+ * Examine results.
+ */
+ if (examine_lproc())
+ return;
+ }
+}
+
+
+/*
+ * get_kernel_access() - access the required information in the kernel
+ */
+
+static void
+get_kernel_access()
+{
+ int i;
+ struct stat sb;
+ KA_T v;
+
+#if defined(HAS_AFS)
+ struct nlist *nl = (struct nlist *)NULL;
+#endif /* defined(HAS_AFS) */
+
+/*
+ * Check the Solaris or SunOS version number; check the SunOS architecture.
+ */
+ (void) ckkv("Solaris", LSOF_VSTR, (char *)NULL, (char *)NULL);
+
+#if solaris>=70000
+/*
+ * Compare the Solaris 7 and above lsof compilation bit size with the kernel
+ * bit size.
+ *
+ * Quit on a mismatch.
+ */
+ {
+ char *cp, isa[1024];
+ short kbits = 32;
+
+# if defined(_LP64)
+ short xkbits = 64;
+# else /* !defined(_LP64) */
+ short xkbits = 32;
+# endif /* defined(_LP64) */
+
+ if (sysinfo(SI_ISALIST, isa, (long)sizeof(isa)) < 0) {
+ (void) fprintf(stderr, "%s: can't get ISA list: %s\n",
+ Pn, strerror(errno));
+ Exit(1);
+ }
+ for (cp = isa; *cp;) {
+ if (strncmp(cp, ARCH64B, strlen(ARCH64B)) == 0) {
+ kbits = 64;
+ break;
+ }
+ if (!(cp = strchr(cp, ' ')))
+ break;
+ cp++;
+ }
+ if (kbits != xkbits) {
+ (void) fprintf(stderr,
+ "%s: FATAL: lsof was compiled for a %d bit kernel,\n",
+ Pn, (int)xkbits);
+ (void) fprintf(stderr,
+ " but this machine has booted a %d bit kernel.\n",
+ (int)kbits);
+ Exit(1);
+ }
+ }
+#endif /* solaris>=70000 */
+
+/*
+ * Get kernel symbols.
+ */
+ if (Nmlst && !is_readable(Nmlst, 1))
+ Exit(1);
+ (void) build_Nl(Drive_Nl);
+
+#if defined(HAS_AFS)
+ if (!Nmlst) {
+
+ /*
+ * If AFS is defined and we're getting kernel symbol values from
+ * from N_UNIX, make a copy of Nl[] for possible use with the AFS
+ * modload file.
+ */
+ if (!(nl = (struct nlist *)malloc(Nll))) {
+ (void) fprintf(stderr, "%s: no space (%d) for Nl[] copy\n",
+ Pn, Nll);
+ Exit(1);
+ }
+ (void) memcpy((void *)nl, (void *)Nl, (size_t)Nll);
+ }
+#endif /* defined(HAS_AFS) */
+
+ if (nlist(Nmlst ? Nmlst : N_UNIX, Nl) < 0) {
+ (void) fprintf(stderr, "%s: can't read namelist from %s\n",
+ Pn, Nmlst ? Nmlst : N_UNIX);
+ Exit(1);
+ }
+
+#if defined(HAS_AFS)
+ if (nl) {
+
+ /*
+ * If AFS is defined and we're getting kernel symbol values from
+ * N_UNIX, and if any X_AFS_* symbols isn't there, see if it is in the
+ * the AFS modload file. Make sure that other symbols that appear in
+ * both name list files have the same values.
+ */
+ if ((get_Nl_value("arFID", Drive_Nl, &v) >= 0 && !v)
+ || (get_Nl_value("avops", Drive_Nl, &v) >= 0 && !v)
+ || (get_Nl_value("avol", Drive_Nl, &v) >= 0 && !v))
+ (void) ckAFSsym(nl);
+ (void) free((MALLOC_P *)nl);
+ }
+#endif /* defined(HAS_AFS) */
+
+/*
+ * Determine the availability of the ALLKMEM device. If it is available, the
+ * active processes will be gathered directly from the active process chain.
+ *
+ * If ALLKMEM isn't available, the active processes will be gathered via the
+ * kvm_*proc() functions.
+ */
+ if (statsafely(ALLKMEM, &sb) == 0)
+ HasALLKMEM = 1;
+
+#if defined(HASVXFSUTIL)
+/*
+ * If the VXFS utility library is being used, attempt to get the VXFS inode
+ * offsets before setgid permission is surrendered.
+ */
+ if (access_vxfs_ioffsets() && !Fwarn) {
+
+ /*
+ * Warn that the VxFS offsets are unavailable.
+ */
+ (void) fprintf(stderr,
+ "%s: WARNING: vxfsu_get_ioffsets() returned an error.\n", Pn);
+ (void) fprintf(stderr,
+ "%s: WARNING: Thus, no vx_inode information is available\n",
+ Pn);
+ (void) fprintf(stderr,
+ "%s: WARNING: for display or selection of VxFS files.\n", Pn);
+ }
+#endif /* defined(HASVXFSUTIL) */
+
+#if defined(WILLDROPGID)
+/*
+ * If Solaris kernel memory is coming from KMEM, the process is willing to
+ * surrender GID permission, and the ALLKMEM device is not available, set up
+ * for GID switching after the first call to open_kvm().
+ */
+ if (!Memory && !HasALLKMEM) {
+ Savedgid = getegid();
+ if (Setgid)
+ Switchgid = 1;
+ }
+/*
+ * If kernel memory isn't coming from KMEM, drop setgid permission
+ * before attempting to open the (Memory) file.
+ */
+ if (Memory)
+ (void) dropgid();
+#else /* !defined(WILLDROPGID) */
+/*
+ * See if the non-KMEM memory file is readable.
+ */
+ if (Memory && !is_readable(Memory, 1))
+ Exit(1);
+#endif /* defined(WILLDROPGID) */
+
+/*
+ * Open access to kernel memory.
+ */
+ open_kvm();
+
+#if solaris>=20500
+/*
+ * Get the kernel's KERNELBASE value for Solaris 2.5 and above.
+ */
+ v = (KA_T)0;
+ if (get_Nl_value("kbase", Drive_Nl, &v) < 0 || !v
+ || kread((KA_T)v, (char *)&Kb, sizeof(Kb))) {
+ (void) fprintf(stderr,
+ "%s: can't read kernel base address from %s\n",
+ Pn, print_kptr(v, (char *)NULL, 0));
+ Exit(1);
+ }
+#endif /* solaris>=20500 */
+
+/*
+ * Get the Solaris clone major device number, if possible.
+ */
+ v = (KA_T)0;
+ if ((get_Nl_value("clmaj", Drive_Nl, &v) < 0) || !v) {
+ if (get_Nl_value("clmaj_alt", Drive_Nl, &v) < 0)
+ v = (KA_T)0;
+ }
+ if (v && kread((KA_T)v, (char *)&CloneMaj, sizeof(CloneMaj)) == 0)
+ HaveCloneMaj = 1;
+/*
+ * If the ALLKMEM device is available, check for the address of the kernel's
+ * active process chain. If it's not available, clear the ALLKMEM status.
+ */
+ if (HasALLKMEM) {
+ if ((get_Nl_value("pract", Drive_Nl, &PrAct) < 0) || !PrAct)
+ HasALLKMEM = 0;
+ }
+
+#if solaris>=20501
+/*
+ * If the ALLKMEM device isn't available, get the kernel's virtual to physical
+ * map structure for Solaris 2.5.1 and above.
+ */
+ if (!HasALLKMEM) {
+ if (get_Nl_value("kasp", Drive_Nl, &v) >= 0 && v) {
+ PageSz = getpagesize();
+ PSMask = PageSz - 1;
+ for (i = 1, PSShft = 0; i < PageSz; i <<= 1, PSShft++)
+ ;
+ (void) readkam(v);
+ }
+ }
+#endif /* solaris>=20501 */
+
+#if defined(WILLDROPGID)
+/*
+ * If the ALLKMEM device is available -- i.e., we're not using the kvm_*proc()
+ * functions to read proc structures -- and if we're willing to drop setgid
+ * permission, do so.
+ */
+ if (HasALLKMEM)
+ (void) dropgid();
+#endif /* defined(WILLDROPGID) */
+
+}
+
+
+#if defined(HASZONES)
+/*
+ * enter_zone_arg() - enter zone name argument
+ */
+
+int
+enter_zone_arg(zn)
+ char *zn; /* zone name */
+{
+ int zh;
+ znhash_t *zp, *zpn;
+/*
+ * Allocate zone argument hash space, as required.
+ */
+ if (!ZoneArg) {
+ if (!(ZoneArg = (znhash_t **)calloc(HASHZONE, sizeof(znhash_t *))))
+ {
+ (void) fprintf(stderr, "%s: no space for zone arg hash\n", Pn);
+ Exit(1);
+ }
+ }
+/*
+ * Hash the zone name and search the argument hash.
+ */
+ zh = hash_zn(zn);
+ for (zp = ZoneArg[zh]; zp; zp = zp->next) {
+ if (!strcmp(zp->zn, zn))
+ break;
+ }
+ if (zp) {
+
+ /*
+ * Process a duplicate.
+ */
+ if (!Fwarn)
+ (void) fprintf(stderr, "%s: duplicate zone name: %s\n", Pn, zn);
+ return(1);
+ }
+/*
+ * Create a new hash entry and link it to its bucket.
+ */
+ if (!(zpn = (znhash_t *)malloc((MALLOC_S)sizeof(znhash_t)))) {
+ (void) fprintf(stderr, "%s no hash space for zone: %s\n", Pn, zn);
+ Exit(1);
+ }
+ zpn->f = 0;
+ zpn->zn = zn;
+ zpn->next = ZoneArg[zh];
+ ZoneArg[zh] = zpn;
+ return(0);
+}
+
+
+/*
+ * hash_zn() - hash zone name
+ */
+
+static int
+hash_zn(zn)
+ char *zn; /* zone name */
+{
+ register int i, h;
+ size_t l;
+
+ if (!(l = strlen(zn)))
+ return(0);
+ if (l == 1)
+ return((int)*zn & (HASHZONE - 1));
+ for (i = h = 0; i < (int)(l - 1); i++) {
+ h ^= ((int)zn[i] * (int)zn[i+1]) << ((i*3)%13);
+ }
+ return(h & (HASHZONE - 1));
+}
+#endif /* defined(HASZONES) */
+
+
+/*
+ * initialize() - perform all initialization
+ */
+
+void
+initialize()
+{
+ get_kernel_access();
+/*
+ * Read Solaris file system information and construct the clone table.
+ *
+ * The clone table is needed to identify sockets.
+ */
+ readfsinfo();
+
+#if defined(HASDCACHE)
+ readdev(0);
+#else /* !defined(HASDCACHE) */
+ read_clone();
+#endif /*defined(HASDCACHE) */
+
+}
+
+
+/*
+ * kread() - read from kernel memory
+ */
+
+int
+kread(addr, buf, len)
+ KA_T addr; /* kernel memory address */
+ char *buf; /* buffer to receive data */
+ READLEN_T len; /* length to read */
+{
+ register int br;
+/*
+ * Because lsof reads kernel data and follows pointers found there at a
+ * rate considerably slower than the kernel, lsof sometimes acquires
+ * invalid pointers. If the invalid pointers are fed to kvm_[k]read(),
+ * a segmentation violation may result, so legal kernel addresses are
+ * limited by the value of the KERNELBASE symbol (Kb value from the
+ * kernel's _kernelbase variable for Solaris 2.5 and above).
+ */
+
+#if solaris>=20500
+#define KVMREAD kvm_kread
+ if (addr < Kb)
+#else /* solaris<20500 */
+#define KVMREAD kvm_read
+ if (addr < (KA_T)KERNELBASE)
+#endif /* solaris>=20500 */
+
+ return(1);
+
+#if solaris>=20501
+
+/*
+ * Do extra address checking for Solaris above 2.5 when the ALLKMEM device
+ * isn't available.
+ *
+ * Make sure the virtual address represents real physical memory by testing
+ * it with kvm_physaddr().
+ *
+ * For Solaris below 7 read the kernel data with llseek() and read(). For
+ * Solaris 7 and above use kvm_pread().
+ */
+ if (Kas && !HasALLKMEM) {
+
+# if solaris>20501
+ register int b2r;
+ register char *bp;
+# endif /* solaris>20501 */
+
+ register int h, ip, tb;
+ register kvmhash_t *kp;
+ KPHYS pa;
+ register KVIRT va, vpa;
+
+# if solaris<20600
+ for (tb = 0, va = (KVIRT)addr;
+ tb < len;
+ tb += br, va += (KVIRT)br)
+# else /* solaris>=20600 */
+ for (bp = buf, tb = 0, va = (KVIRT)addr;
+ tb < len;
+ bp += br, tb += br, va += (KVIRT)br)
+# endif /* solaris<20600 */
+
+ {
+ vpa = (va & (KVIRT)~PSMask) >> PSShft;
+ ip = (int)(va & (KVIRT)PSMask);
+ h = HASHKVM(vpa);
+ for (kp = KVMhb[h]; kp; kp = kp->nxt) {
+ if (kp->vpa == vpa) {
+ pa = kp->pa;
+ break;
+ }
+ }
+ if (!kp) {
+ if ((pa = kvm_physaddr(Kd, Kas, va)) == KAERR)
+ return(1);
+ if (!(kp = (kvmhash_t *)malloc(sizeof(kvmhash_t)))) {
+ (void) fprintf(stderr, "%s: no kvmhash_t space\n", Pn);
+ Exit(1);
+ }
+ kp->nxt = KVMhb[h];
+ pa = kp->pa = (pa & ~(KPHYS)PSMask);
+ kp->vpa = vpa;
+ KVMhb[h] = kp;
+ }
+
+# if solaris<20600
+ br = (int)(len - tb);
+ if ((ip + br) > PageSz)
+ br = PageSz - ip;
+# else /* solaris>=20600 */
+ b2r = (int)(len - tb);
+ if ((ip + b2r) > PageSz)
+ b2r = PageSz - ip;
+ pa |= (KPHYS)ip;
+
+# if solaris<70000
+ if (llseek(Kmd, (offset_t)pa, SEEK_SET) == (offset_t)-1)
+ return(1);
+ if ((br = (int)read(Kmd, (void *)bp, (size_t)b2r)) <= 0)
+ return(1);
+# else /* solaris>=70000 */
+ if ((br = kvm_pread(Kd, pa, (void *)bp, (size_t)b2r)) <= 0)
+ return(1);
+# endif /* solaris<70000 */
+# endif /* solaris<20600 */
+
+ }
+
+# if solaris>=20600
+ return(0);
+# endif /* solaris>=20600 */
+
+ }
+#endif /* solaris>=20501 */
+
+/*
+ * Use kvm_read for Solaris < 2.5; use kvm_kread() Solaris >= 2.5.
+ */
+ br = KVMREAD(Kd, (u_long)addr, buf, len);
+ return(((READLEN_T)br == len) ? 0 : 1);
+}
+
+
+/*
+ * open_kvm() - open kernel virtual memory access
+ */
+
+void
+open_kvm()
+{
+ if (Kd)
+ return;
+
+#if defined(WILLDROPGID)
+/*
+ * If this Solaris process began with setgid permission and its been
+ * surrendered, regain it.
+ */
+ (void) restoregid();
+#endif /* defined(WILLDROPGID) */
+
+ if (!(Kd = kvm_open(Nmlst, Memory, NULL, O_RDONLY, Pn))) {
+ (void) fprintf(stderr,
+ "%s: kvm_open(namelist=%s, corefile=%s): %s\n",
+ Pn,
+ Nmlst ? Nmlst : "default",
+ Memory ? Memory : "default",
+ strerror(errno));
+ Exit(1);
+ }
+
+#if solaris>=20501 && solaris<70000
+ if ((Kmd = open((Memory ? Memory : KMEM), O_RDONLY)) < 0) {
+ (void) fprintf(stderr, "%s: open(\"/dev/mem\"): %s\n", Pn,
+ strerror(errno));
+ Exit(1);
+ }
+#endif /* solaris>=20501 && solaris<70000 */
+
+#if defined(WILLDROPGID)
+/*
+ * If this process has setgid permission, and is willing to surrender it,
+ * do so.
+ */
+ (void) dropgid();
+/*
+ * If this Solaris process must switch GIDs, enable switching after the
+ * first call to this function.
+ */
+ if (Switchgid == 1)
+ Switchgid = 2;
+#endif /* define(WILLDROPGID) */
+
+}
+
+
+/*
+ * process_text() - process text access information
+ */
+
+#if solaris>=90000
+#include <sys/avl.h>
+
+/*
+ * Avl trees are implemented as follows: types in AVL trees contain an
+ * avl_node_t. These avl_nodes connect to other avl nodes embedded in
+ * objects of the same type. The avl_tree contains knowledge about the
+ * size of the structure and the offset of the AVL node in the object
+ * so we can convert between AVL nodes and (in this case) struct seg.
+ *
+ * This code was provided by Casper Dik <Casper.Dik@holland.sun.com>.
+ */
+
+#define READ_AVL_NODE(n,o,s) \
+ if (kread((KA_T)AVL_NODE2DATA(n, o), (char*) s, sizeof(*s))) \
+ return -1
+
+static int
+get_first_seg(avl_tree_t *av, struct seg *s)
+{
+ avl_node_t *node = av->avl_root;
+ size_t off = av->avl_offset;
+ int count = 0;
+
+ while (node != NULL && ++count < MAXSEGS * 2) {
+ READ_AVL_NODE(node, off, s);
+ node = s->s_tree.avl_child[0];
+ if (node == NULL)
+ return 0;
+ }
+ return -1;
+}
+
+static int
+get_next_seg(avl_tree_t *av, struct seg *s)
+{
+ avl_node_t *node = &s->s_tree;
+ size_t off = av->avl_offset;
+ int count = 0;
+
+ if (node->avl_child[1]) {
+ /*
+ * Has right child, go all the way to the leftmost child of
+ * the right child.
+ */
+ READ_AVL_NODE(node->avl_child[1], off, s);
+ while (node->avl_child[0] != NULL && ++count < 2 * MAXSEGS)
+ READ_AVL_NODE(node->avl_child[0],off,s);
+ if (count < 2 * MAXSEGS)
+ return 0;
+ } else {
+ /*
+ * No right child, go up until we find a node we're not a right
+ * child of.
+ */
+ for (;count < 2 * MAXSEGS; count++) {
+ int index = AVL_XCHILD(node);
+ avl_node_t *parent = AVL_XPARENT(node);
+
+ if (parent == NULL)
+ return -1;
+
+ READ_AVL_NODE(parent, off, s);
+
+ if (index == 0)
+ return 0;
+ }
+ }
+ return -1;
+}
+
+static void
+process_text(pa)
+ KA_T pa; /* address space description pointer */
+{
+ struct as as;
+ int i, j, k;
+ struct seg s;
+ struct segvn_data vn;
+ avl_tree_t *avtp;
+ KA_T v[MAXSEGS];
+/*
+ * Get address space description.
+ */
+ if (kread((KA_T)pa, (char *)&as, sizeof(as))) {
+ alloc_lfile(" txt", -1);
+ (void) snpf(Namech, Namechl, "can't read text segment list (%s)",
+ print_kptr(pa, (char *)NULL, 0));
+ enter_nm(Namech);
+ if (Lf->sf)
+ link_lfile();
+ return;
+ }
+/*
+ * Loop through the segments. The loop should stop when the segment
+ * pointer returns to its starting point, but just in case, it's stopped
+ * when MAXSEGS unique segments have been recorded or 2*MAXSEGS segments
+ * have been examined.
+ */
+ for (avtp = &as.a_segtree, i = j = 0;
+ (i < MAXSEGS) && (j < 2*MAXSEGS);
+ j++)
+ {
+ if (j ? get_next_seg(avtp, &s) : get_first_seg(avtp, &s))
+ break;
+ if ((KA_T)s.s_ops == Sgvops && s.s_data) {
+ if (kread((KA_T)s.s_data, (char *)&vn, sizeof(vn)))
+ break;
+ if (vn.vp) {
+
+ /*
+ * This is a virtual node segment.
+ *
+ * If its vnode pointer has not been seen already, record the
+ * vnode pointer and process the vnode.
+ */
+ for (k = 0; k < i; k++) {
+ if (v[k] == (KA_T)vn.vp)
+ break;
+ }
+ if (k >= i) {
+ v[i++] = (KA_T)vn.vp;
+ alloc_lfile(" txt", -1);
+
+# if defined(FILEPTR)
+ FILEPTR = (struct file *)NULL;
+# endif /* defined(FILEPTR) */
+
+ process_node((KA_T)vn.vp);
+ if (Lf->sf)
+ link_lfile();
+ }
+ }
+ }
+ }
+}
+
+#else /* solaris<90000 */
+
+# if solaris>=20400
+#define S_NEXT s_next.list
+# else /* solaris<20400 */
+#define S_NEXT s_next
+# endif /* solaris>=20400 */
+
+static void
+process_text(pa)
+ KA_T pa; /* address space description pointer */
+{
+ struct as as;
+ int i, j, k;
+ struct seg s;
+ struct segvn_data vn;
+ KA_T v[MAXSEGS];
+/*
+ * Get address space description.
+ */
+ if (kread((KA_T)pa, (char *)&as, sizeof(as))) {
+ alloc_lfile(" txt", -1);
+ (void) snpf(Namech, Namechl, "can't read text segment list (%s)",
+ print_kptr(pa, (char *)NULL, 0));
+ enter_nm(Namech);
+ if (Lf->sf)
+ link_lfile();
+ return;
+ }
+/*
+ * Loop through the segments. The loop should stop when the segment
+ * pointer returns to its starting point, but just in case, it's stopped
+ * when MAXSEGS unique segments have been recorded or 2*MAXSEGS segments
+ * have been examined.
+ */
+ for (s.s_next = as.a_segs, i = j = 0;
+ i < MAXSEGS && j < 2*MAXSEGS;
+ j++)
+ {
+ if (!s.S_NEXT
+ || kread((KA_T)s.S_NEXT, (char *)&s, sizeof(s)))
+ break;
+ if ((KA_T)s.s_ops == Sgvops && s.s_data) {
+ if (kread((KA_T)s.s_data, (char *)&vn, sizeof(vn)))
+ break;
+ if (vn.vp) {
+
+ /*
+ * This is a virtual node segment.
+ *
+ * If its vnode pointer has not been seen already, record the
+ * vnode pointer and process the vnode.
+ */
+ for (k = 0; k < i; k++) {
+ if (v[k] == (KA_T)vn.vp)
+ break;
+ }
+ if (k >= i) {
+ v[i++] = (KA_T)vn.vp;
+ alloc_lfile(" txt", -1);
+
+# if defined(FILEPTR)
+ FILEPTR = (struct file *)NULL;
+# endif /* defined(FILEPTR) */
+
+ process_node((KA_T)vn.vp);
+ if (Lf->sf)
+ link_lfile();
+ }
+ }
+ }
+ /*
+ * Follow the segment link to the starting point in the address
+ * space description. (The i and j counters place an absolute
+ * limit on the loop.)
+ */
+
+# if solaris<20400
+ if (s.s_next == as.a_segs)
+# else /* solaris>=20400 */
+ if (s.s_next.list == as.a_segs.list)
+# endif /* solaris<20400 */
+
+ break;
+ }
+}
+#endif /* solaris>=90000 */
+
+
+/*
+ * readfsinfo() - read file system information
+ */
+
+static void
+readfsinfo()
+{
+ char buf[FSTYPSZ+1];
+ int i, len;
+
+ if ((Fsinfomax = sysfs(GETNFSTYP)) == -1) {
+ (void) fprintf(stderr, "%s: sysfs(GETNFSTYP) error: %s\n",
+ Pn, strerror(errno));
+ Exit(1);
+ }
+ if (Fsinfomax == 0)
+ return;
+ if (!(Fsinfo = (char **)malloc((MALLOC_S)(Fsinfomax * sizeof(char *)))))
+ {
+ (void) fprintf(stderr, "%s: no space for sysfs info\n", Pn);
+ Exit(1);
+ }
+ for (i = 1; i <= Fsinfomax; i++) {
+ if (sysfs(GETFSTYP, i, buf) == -1) {
+ (void) fprintf(stderr, "%s: sysfs(GETFSTYP) error: %s\n",
+ Pn, strerror(errno));
+ Exit(1);
+ }
+ if (buf[0] == '\0') {
+ Fsinfo[i-1] = "";
+ continue;
+ }
+ buf[FSTYPSZ] = '\0';
+ len = strlen(buf) + 1;
+ if (!(Fsinfo[i-1] = (char *)malloc((MALLOC_S)len))) {
+ (void) fprintf(stderr,
+ "%s: no space for file system entry %s\n", Pn, buf);
+ Exit(1);
+ }
+ (void) snpf(Fsinfo[i-1], len, "%s", buf);
+
+# if defined(HAS_AFS)
+ if (strcasecmp(buf, "afs") == 0)
+ AFSfstype = i;
+# endif /* defined(HAS_AFS) */
+
+ }
+}
+
+
+#if solaris>=20501
+/*
+ * readkam() - read kernel's address map structure
+ */
+
+static void
+readkam(addr)
+ KA_T addr; /* kernel virtual address */
+{
+ register int i;
+ register kvmhash_t *kp, *kpp;
+ static KA_T kas = (KA_T)NULL;
+
+ if (addr)
+ kas = addr;
+ Kas = (struct as *)NULL;
+
+#if solaris<70000
+ if (kas && !kread(kas, (char *)&Kam, sizeof(Kam)))
+ Kas = (KA_T)&Kam;
+#else /* solaris>=70000 */
+ Kas = (struct as *)kas;
+#endif /* solaris<70000 */
+
+ if (Kas) {
+ if (!KVMhb) {
+ if (!(KVMhb = (kvmhash_t **)calloc(KVMHASHBN,
+ sizeof(kvmhash_t *))))
+ {
+ (void) fprintf(stderr,
+ "%s: no space (%d) for KVM hash buckets\n",
+ Pn, (int)(KVMHASHBN * sizeof(kvmhash_t *)));
+ Exit(1);
+ }
+ } else if (!addr) {
+ for (i = 0; i < KVMHASHBN; i++) {
+ if ((kp = KVMhb[i])) {
+ while (kp) {
+ kpp = kp->nxt;
+ (void) free((void *)kp);
+ kp = kpp;
+ }
+ KVMhb[i] = (kvmhash_t *)NULL;
+ }
+ }
+ }
+ }
+}
+#endif /* solaris>=20501 */
+
+
+/*
+ * read_proc() - read proc structures
+ *
+ * As a side-effect, Kd is set by a call to kvm_open().
+ */
+
+static void
+read_proc()
+{
+ int ct, ctl, knp, n, try;
+ MALLOC_S len;
+ struct proc *p;
+ KA_T pa, paf, pan;
+ struct pid pg, pids;
+/*
+ * Try PROCTRYLM times to read a valid proc table.
+ */
+ for (try = 0; try < PROCTRYLM; try++) {
+
+ /*
+ * Get a proc structure count estimate.
+ */
+ if (get_Nl_value("nproc", Drive_Nl, &pa) < 0 || !pa
+ || kread(pa, (char *)&knp, sizeof(knp))
+ || knp < 1)
+ knp = PROCDFLT;
+ /*
+ * Pre-allocate space, as required.
+ */
+ n = knp + PROCDFLT/4;
+ if (n > Npa) {
+
+ /*
+ * Allocate proc structure space.
+ */
+ len = (n * sizeof(struct proc));
+ if (P)
+ P = (struct proc *)realloc((MALLOC_P *)P, len);
+ else
+ P = (struct proc *)malloc(len);
+ if (!P) {
+ (void) fprintf(stderr, "%s: no proc table space\n", Pn);
+ Exit(1);
+ }
+ /*
+ * Pre-allocate PGID and PID number space.
+ */
+ len = (MALLOC_S)(n * sizeof(int));
+ if (Fpgid) {
+ if (Pgid)
+ Pgid = (int *)realloc((MALLOC_P *)Pgid, len);
+ else
+ Pgid = (int *)malloc(len);
+ if (!Pgid) {
+ (void) fprintf(stderr, "%s: no PGID table space\n", Pn);
+ Exit(1);
+ }
+ }
+ if (Pid)
+ Pid = (int *)realloc((MALLOC_P *)Pid, len);
+ else
+ Pid = (int *)malloc(len);
+ if (!Pid) {
+ (void) fprintf(stderr, "%s: no PID table space\n", Pn);
+ Exit(1);
+ }
+ Npa = n;
+ }
+ if (HasALLKMEM) {
+
+ /*
+ * Prepare for a proc table scan via direct reading of the active
+ * chain.
+ */
+ if (!PrAct || kread(PrAct, (char *)&paf, sizeof(pa))) {
+ (void) fprintf(stderr, "%s: can't read practive from %s\n",
+ Pn, print_kptr(PrAct, (char *)NULL, 0));
+ Exit(1);
+ }
+ ct = 1;
+ ctl = knp << 3;
+ pan = paf;
+ pa = (KA_T)NULL;
+ } else {
+
+ /*
+ * Prepare for a proc table scan via the kvm_*proc() functions.
+ */
+ if (kvm_setproc(Kd) != 0) {
+ (void) fprintf(stderr, "%s: kvm_setproc: %s\n", Pn,
+ strerror(errno));
+ Exit(1);
+ }
+ }
+ /*
+ * Accumulate proc structures.
+ */
+ Np = 0;
+ for (;;) {
+ if (Np >= Npa) {
+
+ /*
+ * Expand the local proc table.
+ */
+ Npa += PROCDFLT/2;
+ len = (MALLOC_S)(Npa * sizeof(struct proc));
+ if (!(P = (struct proc *)realloc((MALLOC_P *)P, len))) {
+ (void) fprintf(stderr,
+ "%s: no more (%d) proc space\n", Pn, Npa);
+ Exit(1);
+ }
+ /*
+ * Expand the PGID and PID tables.
+ */
+ len = (MALLOC_S)(Npa * sizeof(int));
+ if (Fpgid) {
+ if (!(Pgid = (int *)realloc((MALLOC_P *)Pgid, len))) {
+ (void) fprintf(stderr,
+ "%s: no more (%d) PGID space\n", Pn, Npa);
+ Exit(1);
+ }
+ }
+ if (!(Pid = (int *)realloc((MALLOC_P *)Pid, len))) {
+ (void) fprintf(stderr,
+ "%s: no more (%d) PID space\n", Pn, Npa);
+ Exit(1);
+ }
+ }
+ /*
+ * Read the next proc structure.
+ */
+ if (HasALLKMEM) {
+
+ /*
+ * If the ALLKMEM device exists, read proc structures directly
+ * from the active chain.
+ */
+ if (!pa)
+ pa = paf;
+ else {
+ pa = pan;
+ if ((pan == paf) || (++ct > ctl))
+ break;
+ }
+ if (!pa)
+ break;
+ p = (struct proc *)&P[Np];
+ if (kread(pa, (char *)p, sizeof(struct proc)))
+ break;
+ pan = (KA_T)p->p_next;
+ } else {
+
+ /*
+ * If the ALLKMEM device doesn't exist, read proc structures
+ * via kbm_getproc().
+ */
+ if (!(p = kvm_nextproc(Kd)))
+ break;
+ }
+ /*
+ * Check process status.
+ */
+ if (p->p_stat == 0 || p->p_stat == SZOMB)
+ continue;
+
+#if solaris >=20500
+ /*
+ * Check Solaris 2.5 and above p_cred pointer.
+ */
+ if (!p->p_cred)
+ continue;
+#endif /* solaris >=20500 */
+
+ /*
+ * Read Solaris PGID and PID numbers.
+ */
+ if (Fpgid) {
+ if (!p->p_pgidp
+ || kread((KA_T)p->p_pgidp, (char *)&pg, sizeof(pg)))
+ continue;
+ }
+ if (!p->p_pidp
+ || kread((KA_T)p->p_pidp, (char *)&pids, sizeof(pids)))
+ continue;
+ /*
+ * Save the PGID and PID numbers in local tables.
+ */
+ if (Fpgid)
+ Pgid[Np] = (int)pg.pid_id;
+ Pid[Np] = (int)pids.pid_id;
+ /*
+ * If the proc structure came from kvm_getproc(), save it in the
+ * local table.
+ */
+ if (!HasALLKMEM)
+ P[Np] = *p;
+ Np++;
+ }
+ /*
+ * If not enough processes were saved in the local table, try again.
+ *
+ * If the ALLKMEM device isn't available, it is necessary to close and
+ * reopen the KVM device, so that kvm_open() will acquire a fresh
+ * address for the head of the linked list process table.
+ */
+ if (Np >= PROCMIN)
+ break;
+ if (!HasALLKMEM) {
+ close_kvm();
+ open_kvm();
+ }
+ }
+/*
+ * Quit if no proc structures were stored in the local table.
+ */
+ if (try >= PROCTRYLM) {
+ (void) fprintf(stderr, "%s: can't read proc table\n", Pn);
+ Exit(1);
+ }
+ if (Np < Npa && !RptTm) {
+
+ /*
+ * Reduce the local proc structure table size to its minimum if
+ * not in repeat mode.
+ */
+ len = (MALLOC_S)(Np * sizeof(struct proc));
+ if (!(P = (struct proc *)realloc((MALLOC_P *)P, len))) {
+ (void) fprintf(stderr, "%s: can't reduce proc table to %d\n",
+ Pn, Np);
+ Exit(1);
+ }
+ /*
+ * Reduce the Solaris PGID and PID tables to their minimum if
+ * not in repeat mode.
+ */
+ len = (MALLOC_S)(Np * sizeof(int));
+ if (Fpgid) {
+ if (!(Pgid = (int *)realloc((MALLOC_P *)Pgid, len))) {
+ (void) fprintf(stderr,
+ "%s: can't reduce PGID table to %d\n", Pn, Np);
+ Exit(1);
+ }
+ }
+ if (!(Pid = (int *)realloc((MALLOC_P *)Pid, len))) {
+ (void) fprintf(stderr,
+ "%s: can't reduce PID table to %d\n", Pn, Np);
+ Exit(1);
+ }
+ Npa = Np;
+ }
+}
+
+
+#if defined(WILLDROPGID)
+/*
+ * restoregid() -- restore setgid permission, as required
+ */
+
+void
+restoregid()
+{
+ if (Switchgid == 2 && !Setgid) {
+ if (setgid(Savedgid) != 0) {
+ (void) fprintf(stderr,
+ "%s: can't set effective GID to %d: %s\n",
+ Pn, (int)Savedgid, strerror(errno));
+ Exit(1);
+ }
+ Setgid = 1;
+ }
+}
+#endif /* defined(WILLDROPGID) */
+
+
+#if defined(HASNCACHE) && solaris>=90000
+
+
+/*
+ * Local static values
+ */
+
+static int Mhl; /* local name cache hash mask */
+static int Nhl = 0; /* size of local name cache hash
+ * pointer table */
+struct l_nch {
+ KA_T vp; /* vnode address */
+ KA_T dp; /* parent vnode address */
+ struct l_nch *pa; /* parent Ncache address */
+ char *nm; /* name */
+ int nl; /* name length */
+};
+
+static struct l_nch *Ncache = (struct l_nch *)NULL;
+ /* the local name cache */
+static struct l_nch **Nchash = (struct l_nch **)NULL;
+ /* Ncache hash pointers */
+static int Ncfirst = 1; /* first-call status */
+static KA_T NegVN = (KA_T)NULL; /* negative vnode address */
+static int Nla = 0; /* entries allocated to Ncache[] */
+static int Nlu = 0; /* entries used in Ncache[] */
+
+_PROTOTYPE(static struct l_nch *ncache_addr,(KA_T v));
+
+#define ncachehash(v) Nchash+((((int)(v)>>2)*31415)&Mhl)
+
+_PROTOTYPE(static int ncache_isroot,(KA_T va, char *cp));
+
+#define LNCHINCRSZ 64 /* local size increment */
+#define XNC 15 /* extra name characters to read beyond those
+ * in name[] of the ncache_t structure -- this
+ * is an efficiency hint and MUST BE AT LEAST
+ * ONE. */
+
+
+/*
+ * ncache_addr() - look up a node's local ncache address
+ */
+
+static struct l_nch *
+
+ncache_addr(v)
+ KA_T v; /* vnode's address */
+{
+ struct l_nch **hp;
+
+ for (hp = ncachehash(v); *hp; hp++) {
+ if ((*hp)->vp == v)
+ return(*hp);
+ }
+ return((struct l_nch *)NULL);
+}
+
+
+/*
+ * ncache_isroot() - is head of name cache path a file system root?
+ */
+
+static int
+ncache_isroot(va, cp)
+ KA_T va; /* kernel vnode address */
+ char *cp; /* partial path */
+{
+ char buf[MAXPATHLEN];
+ int i;
+ MALLOC_S len;
+ struct mounts *mtp;
+ struct stat sb;
+ struct vnode v;
+ static int vca = 0;
+ static int vcn = 0;
+ static KA_T *vc = (KA_T *)NULL;
+
+ if (!va)
+ return(0);
+/*
+ * Search the root vnode cache.
+ */
+ for (i = 0; i < vcn; i++) {
+ if (va == vc[i])
+ return(1);
+ }
+/*
+ * Read the vnode and see if it's a VDIR node with the VROOT flag set. If
+ * it is, then the path is complete.
+ *
+ * If it isn't, and if the file has an inode number, search the mount table
+ * and see if the file system's inode number is known. If it is, form the
+ * possible full path, safely stat() it, and see if it's inode number matches
+ * the one we have for this file. If it does, then the path is complete.
+ */
+ if (kread((KA_T)va, (char *)&v, sizeof(v))
+ || v.v_type != VDIR || !(v.v_flag & VROOT)) {
+
+ /*
+ * The vnode tests failed. Try the inode tests.
+ */
+ if (Lf->inp_ty != 1 || !Lf->inode
+ || !Lf->fsdir || (len = strlen(Lf->fsdir)) < 1)
+ return(0);
+ if ((len + 1 + strlen(cp) + 1) > sizeof(buf))
+ return(0);
+ for (mtp = readmnt(); mtp; mtp = mtp->next) {
+ if (!mtp->dir || !mtp->inode)
+ continue;
+ if (strcmp(Lf->fsdir, mtp->dir) == 0)
+ break;
+ }
+ if (!mtp)
+ return(0);
+ (void) strcpy(buf, Lf->fsdir);
+ if (buf[len - 1] != '/')
+ buf[len++] = '/';
+ (void) strcpy(&buf[len], cp);
+ if (statsafely(buf, &sb) != 0
+ || (INODETYPE)sb.st_ino != Lf->inode)
+ return(0);
+ }
+/*
+ * Add the vnode address to the root vnode cache.
+ */
+ if (vcn >= vca) {
+ vca += 10;
+ len = (MALLOC_S)(vca * sizeof(KA_T));
+ if (!vc)
+ vc = (KA_T *)malloc(len);
+ else
+ vc = (KA_T *)realloc(vc, len);
+ if (!vc) {
+ (void) fprintf(stderr, "%s: no space for root vnode table\n",
+ Pn);
+ Exit(1);
+ }
+ }
+ vc[vcn++] = va;
+ return(1);
+}
+
+
+/*
+ * ncache_load() - load the kernel's name cache
+ */
+
+void
+ncache_load()
+{
+ char *cp;
+ struct l_nch **hp, *lc;
+ int h, i, len, n, xl;
+ static int iNch = 0;
+ nc_hash_t *kh;
+ static KA_T kha = (KA_T)NULL;
+ static nc_hash_t *khl = (nc_hash_t *)NULL;
+ KA_T kn;
+ static ncache_t *nc = (ncache_t *)NULL;
+ static int Nch = 0;
+ static int nmo = 0;
+ KA_T v;
+ static int xn = 0;
+
+ if (!Fncache)
+ return;
+ if (Ncfirst) {
+
+ /*
+ * Do startup (first-time) functions.
+ */
+ Ncfirst = 0;
+ /*
+ * Establish DNLC hash size.
+ */
+ v = (KA_T)0;
+ if (get_Nl_value(X_NCSIZE, (struct drive_Nl *)NULL, &v) < 0
+ || !v
+ || kread((KA_T)v, (char *)&Nch, sizeof(Nch)))
+ {
+ if (!Fwarn)
+ (void) fprintf(stderr,
+ "%s: WARNING: can't read DNLC hash size: %s\n",
+ Pn, print_kptr(v, (char *)NULL, 0));
+ iNch = Nch = 0;
+ return;
+ }
+ if ((iNch = Nch) < 1) {
+ if (!Fwarn)
+ (void) fprintf(stderr,
+ "%s: WARNING: DNLC hash size: %d\n", Pn, Nch);
+ iNch = Nch = 0;
+ return;
+ }
+ /*
+ * Get negative vnode address.
+ */
+ if (get_Nl_value(NCACHE_NEGVN, (struct drive_Nl *)NULL, &NegVN)
+ < 0)
+ NegVN = (KA_T)NULL;
+ /*
+ * Establish DNLC hash address.
+ */
+ v = (KA_T)0;
+ if (get_Nl_value(X_NCACHE,(struct drive_Nl *)NULL,(KA_T *)&v) < 0
+ || !v
+ || kread(v, (char *)&kha, sizeof(kha))
+ || !kha
+ ) {
+ if (!Fwarn)
+ (void) fprintf(stderr,
+ "%s: WARNING: no DNLC hash address\n", Pn);
+ iNch = Nch = 0;
+ return;
+ }
+ /*
+ * Allocate space for a local copy of the kernel's hash table.
+ */
+ len = Nch * sizeof(nc_hash_t);
+ if (!(khl = (nc_hash_t *)malloc((MALLOC_S)len))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate DNLC hash space: %d\n", Pn, len);
+ Exit(1);
+ }
+ /*
+ * Allocate space for a kernel DNLC entry, plus additional name space
+ * for efficiency.
+ */
+ xn = XNC;
+ if (!(nc = (ncache_t *)malloc((MALLOC_S)(sizeof(ncache_t) + XNC))))
+ {
+ (void) fprintf(stderr,
+ "%s: can't allocate DNLC ncache_t space\n", Pn);
+ Exit(1);
+ }
+ nmo = offsetof(struct ncache, name);
+ /*
+ * Allocate estimated space for the local cache, based on the
+ * hash table count and the current average hash length.
+ */
+ v = (KA_T)0;
+ if ((get_Nl_value("hshav", (struct drive_Nl *)NULL, (KA_T *)&v) < 0)
+ || !v
+ || kread(v, (char *)&i, sizeof(i))
+ || (i < 1)
+ ) {
+ i = 16;
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ "%s: can't read DNLC average hash bucket size,", Pn);
+ (void) fprintf(stderr, " using %d\n", i);
+ }
+ }
+ Nla = Nch * i;
+ if (!(Ncache = (struct l_nch *)calloc(Nla, sizeof(struct l_nch)))) {
+
+no_local_space:
+
+ (void) fprintf(stderr,
+ "%s: no space for %d byte local name cache\n", Pn, len);
+ Exit(1);
+ }
+ } else {
+
+ /*
+ * Do setup for repeat calls.
+ */
+ if (!iNch || !Nla || !Ncache)
+ return;
+ if (Nchash) {
+ (void) free((FREE_P *)Nchash);
+ Nchash = (struct l_nch **)NULL;
+ }
+ if (Ncache && Nlu) {
+
+ /*
+ * Free space malloc'd to names in local name cache.
+ */
+ for (i = 0, lc = Ncache; i < Nlu; i++, lc++) {
+ if (lc->nm) {
+ (void) free((FREE_P *)lc->nm);
+ lc->nm = (char *)NULL;
+ }
+ }
+ }
+ Nch = iNch;
+ Nlu = 0;
+ }
+/*
+ * Read the kernel's DNLC hash.
+ */
+ if (kread(kha, (char *)khl, (Nch * sizeof(nc_hash_t)))) {
+ if (!Fwarn)
+ (void) fprintf(stderr,
+ "%s: WARNING: can't read DNLC hash: %s\n",
+ Pn, print_kptr(kha, (char *)NULL, 0));
+ iNch = Nch = 0;
+ return;
+ }
+/*
+ * Build a local copy of the kernel name cache.
+ */
+ for (i = n = 0, kh = khl, lc = Ncache; i < Nch; i++, kh++) {
+
+ /*
+ * Skip empty hash buckets.
+ */
+ if (!kh->hash_next || ((KA_T)kh->hash_next == kha))
+ continue;
+ /*
+ * Process a hash bucket.
+ */
+ for (kn = (KA_T)kh->hash_next, h = 0;
+ kn && (h < Nch) && (!h || (h && kn != (KA_T)kh->hash_next));
+ kn = (KA_T)nc->hash_next, h++)
+ {
+ if (kread(kn, (char *)nc, sizeof(ncache_t) + XNC))
+ break;
+ if (!nc->vp || (len = (int)nc->namlen) < 1)
+ continue;
+ if (NegVN && ((KA_T)nc->vp == NegVN))
+ continue;
+ if ((len < 3) && (nc->name[0] == '.')) {
+ if ((len < 2) || (nc->name[1] == '.'))
+ continue;
+ }
+ /*
+ * If not all the name has been read, read the rest of it,
+ * allocating more space at the end of the ncache structure as
+ * required.
+ */
+ if (len > (XNC + 1)) {
+ if (len > (xn + 1)) {
+ while (len > (xn + 1))
+ xn = xn + xn;
+ xn = ((xn + 7) & ~7) - 1;
+ if (!(nc = (ncache_t *)realloc((MALLOC_P *)nc,
+ (sizeof(ncache_t) + xn)))
+ ) {
+ (void) fprintf(stderr,
+ "%s: can't extend DNLC ncache_t buffer\n", Pn);
+ Exit(1);
+ }
+ }
+ cp = &nc->name[XNC + 1];
+ v = (KA_T)((char *)kn + nmo + XNC + 1);
+ xl = len - XNC - 1;
+ if (kread(v, cp, xl))
+ continue;
+ }
+ /*
+ * Allocate space for the name in the local name cache entry.
+ */
+ if (!(cp = (char *)malloc(len + 1))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d bytes for name cache name\n",
+ Pn, len + 1);
+ Exit(1);
+ }
+ (void) strncpy(cp, nc->name, len);
+ cp[len] = '\0';
+ /*
+ * Make sure there is space for another local name cache entry.
+ * If not, allocate twice as many entries.
+ */
+ if (n >= Nla) {
+ Nla = Nla + Nla;
+ if (!(Ncache = (struct l_nch *)realloc(Ncache,
+ (MALLOC_S)(Nla * sizeof(struct l_nch))))
+ ) {
+ (void) fprintf(stderr,
+ "%s: can't enlarge local name cache\n", Pn);
+ Exit(1);
+ }
+ lc = &Ncache[n];
+ }
+ /*
+ * Complete the local cache entry.
+ */
+ lc->vp = (KA_T)nc->vp;
+ lc->dp = (KA_T)nc->dp;
+ lc->pa = (struct l_nch *)NULL;
+ lc->nm = cp;
+ lc->nl = len;
+ lc++;
+ n++;
+ }
+ }
+/*
+ * Reduce memory usage, as required.
+ */
+ if ((Nlu = n) < 1) {
+
+ /*
+ * No DNLC entries were located, an unexpected result.
+ */
+ if (!RptTm && Ncache) {
+
+ /*
+ * If not in repeat mode, free the space that has been malloc'd
+ * to the local name cache.
+ */
+ (void) free((FREE_P *)Ncache);
+ Ncache = (struct l_nch *)NULL;
+ Nla = Nlu = 0;
+ }
+ /*
+ * Issue a warning and disable furthe DNLC processing.
+ */
+ if (!Fwarn)
+ (void) fprintf(stderr,
+ "%s: WARNING: unusable local name cache size: %d\n", Pn, n);
+ iNch = Nch = 0;
+ return;
+ }
+ if ((Nlu < Nla) && !RptTm) {
+ len = Nlu * sizeof(struct l_nch);
+ if (!(Ncache = (struct l_nch *)realloc(Ncache, len)))
+ goto no_local_space;
+ Nla = Nlu;
+ }
+/*
+ * Build a hash table to locate Ncache entries.
+ */
+ for (Nhl = 1; Nhl < Nlu; Nhl <<= 1)
+ ;
+ Nhl <<= 1;
+ Mhl = Nhl - 1;
+ if (!(Nchash = (struct l_nch **)calloc(Nhl + Nlu,
+ sizeof(struct l_nch *))))
+ {
+ (void) fprintf(stderr,
+ "%s: no space for %d name cache hash pointers\n",
+ Pn, Nhl + Nlu);
+ Exit(1);
+ }
+ for (i = 0, lc = Ncache; i < Nlu; i++, lc++) {
+ for (hp = ncachehash(lc->vp), h = 1; *hp; hp++) {
+ if ((*hp)->vp == lc->vp && strcmp((*hp)->nm, lc->nm) == 0
+ && (*hp)->dp == lc->dp
+ ) {
+ h = 0;
+ break;
+ }
+ }
+ if (h)
+ *hp = lc;
+ }
+/*
+ * Make a final pass through the local cache and convert parent vnode
+ * addresses to local name cache pointers.
+ */
+ for (i = 0, lc = Ncache; i < Nlu; i++, lc++) {
+ if (!lc->dp)
+ continue;
+ if (NegVN && (lc->dp == NegVN)) {
+ lc->pa = (struct l_nch *)NULL;
+ continue;
+ }
+ lc->pa = ncache_addr(lc->dp);
+ }
+}
+
+
+/*
+ * ncache_lookup() - look up a node's name in the kernel's name cache
+ */
+
+char *
+ncache_lookup(buf, blen, fp)
+ char *buf; /* receiving name buffer */
+ int blen; /* receiving buffer length */
+ int *fp; /* full path reply */
+{
+ char *cp = buf;
+ struct l_nch *lc;
+ struct mounts *mtp;
+ int nl, rlen;
+
+ *cp = '\0';
+ *fp = 0;
+
+# if defined(HASFSINO)
+/*
+ * If the entry has an inode number that matches the inode number of the
+ * file system mount point, return an empty path reply. That tells the
+ * caller to print the file system mount point name only.
+ */
+ if (Lf->inp_ty == 1 && Lf->fs_ino && Lf->inode == Lf->fs_ino)
+ return(cp);
+# endif /* defined(HASFSINO) */
+
+/*
+ * Look up the name cache entry for the node address.
+ */
+ if (!Nlu || !(lc = ncache_addr(Lf->na))) {
+
+ /*
+ * If the node has no cache entry, see if it's the mount
+ * point of a known file system.
+ */
+ if (!Lf->fsdir || !Lf->dev_def || Lf->inp_ty != 1)
+ return((char *)NULL);
+ for (mtp = readmnt(); mtp; mtp = mtp->next) {
+ if (!mtp->dir || !mtp->inode)
+ continue;
+ if (Lf->dev == mtp->dev
+ && mtp->inode == Lf->inode
+ && strcmp(mtp->dir, Lf->fsdir) == 0)
+ return(cp);
+ }
+ return((char *)NULL);
+ }
+/*
+ * Begin the path assembly.
+ */
+ if ((nl = lc->nl) > (blen - 1))
+ return((char *)NULL);
+ cp = buf + blen - nl - 1;
+ rlen = blen - nl - 1;
+ (void) strcpy(cp, lc->nm);
+/*
+ * Look up the name cache entries that are parents of the node address.
+ * Quit when:
+ *
+ * there's no parent;
+ * the name is too large to fit in the receiving buffer.
+ */
+ for (;;) {
+ if (!lc->pa) {
+ if (ncache_isroot(lc->dp, cp))
+ *fp = 1;
+ break;
+ }
+ lc = lc->pa;
+ if (((nl = lc->nl) + 1) > rlen)
+ break;
+ *(cp - 1) = '/';
+ cp--;
+ rlen--;
+ (void) strncpy((cp - nl), lc->nm, nl);
+ cp -= nl;
+ rlen -= nl;
+ }
+ return(cp);
+}
+#endif /* defined(HASNCACHE) && solaris>=90000 */
diff --git a/dialects/sun/dproto.h b/dialects/sun/dproto.h
new file mode 100644
index 0000000..fd6cb2c
--- /dev/null
+++ b/dialects/sun/dproto.h
@@ -0,0 +1,109 @@
+/*
+ * dproto.h - Solaris function prototypes for lsof
+ *
+ * The _PROTOTYPE macro is defined in the common proto.h.
+ */
+
+
+/*
+ * Copyright 1994 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.
+ */
+
+
+/*
+ * $Id: dproto.h,v 1.21 2010/01/18 19:03:54 abe Exp $
+ */
+
+
+#if defined(HASVXFSUTIL)
+_PROTOTYPE(extern int access_vxfs_ioffsets,(void));
+#endif /* defined(HASVXFSUTIL) */
+
+_PROTOTYPE(extern void completevfs,(struct l_vfs *vfs, dev_t *dev));
+
+# if defined(HAS_LIBCTF)
+_PROTOTYPE(extern int CTF_getmem,(ctf_file_t *f, const char *mod,
+ const char *ty, CTF_member_t *mem));
+_PROTOTYPE(extern void CTF_init,(int *i, char *t, CTF_request_t *r));
+_PROTOTYPE(extern int CTF_memCB,(const char *name, ctf_id_t id, ulong_t offset,
+ void *arg));
+# endif /* defined(HAS_LIBCTF) */
+
+_PROTOTYPE(extern int is_file_named,(char *p, int nt, enum vtype vt, int ps));
+_PROTOTYPE(extern struct l_vfs *readvfs,(KA_T ka, struct vfs *la, struct vnode *lv));
+_PROTOTYPE(extern int vop2ty,(struct vnode *vp, int fx));
+
+#if defined(HAS_AFS)
+_PROTOTYPE(extern struct vnode *alloc_vcache,(void));
+_PROTOTYPE(extern void ckAFSsym,(struct nlist *nl));
+_PROTOTYPE(extern int hasAFS,(struct vnode *vp));
+_PROTOTYPE(extern int readafsnode,(KA_T va, struct vnode *v, struct afsnode *an));
+#endif /* defined(HAS_AFS) */
+
+#if defined(HASDCACHE)
+_PROTOTYPE(extern int rw_clone_sect,(int m));
+_PROTOTYPE(extern void clr_sect,(void));
+_PROTOTYPE(extern int rw_pseudo_sect,(int m));
+#endif /* defined(HASDCACHE) */
+
+#if defined(HASIPv6)
+_PROTOTYPE(extern struct hostent *gethostbyname2,(const char *nm, int proto));
+#endif /* defined(HASIPv6) */
+
+#if defined(HAS_V_PATH)
+_PROTOTYPE(extern int print_v_path,(struct lfile *lf));
+_PROTOTYPE(extern void read_v_path,(KA_T ka, char *rb, size_t rbl));
+#endif /* defined(HAS_V_PATH) */
+
+#if defined(HASVXFS)
+_PROTOTYPE(extern int read_vxnode,(KA_T va, struct vnode *v, struct l_vfs *vfs,
+ int fx, struct l_ino *li, KA_T *vnops));
+# if defined(HASVXFSRNL)
+_PROTOTYPE(extern int print_vxfs_rnl_path,(struct lfile *lf));
+# endif /* defined(HASVXFSRNL) */
+#endif /* defined(HASVXFS) */
+
+#if defined(HASZONES)
+_PROTOTYPE(extern int enter_zone_arg,(char *zn));
+#endif /* defined(HASZONES) */
+
+_PROTOTYPE(extern void close_kvm,(void));
+_PROTOTYPE(extern void open_kvm,(void));
+_PROTOTYPE(extern void process_socket,(KA_T sa, char *ty));
+
+#if solaris>=110000
+_PROTOTYPE(extern int process_VSOCK,(KA_T va, struct vnode *v,
+ struct sonode *so));
+#endif /* solaris>=11000 */
+
+_PROTOTYPE(extern void read_clone,(void));
+
+#if solaris<20500
+_PROTOTYPE(extern int get_max_fd,(void));
+#endif /* solaris<20500 */
+
+#if defined(WILLDROPGID)
+_PROTOTYPE(extern void restoregid,(void));
+#endif /* defined(WILLDROPGID) */
diff --git a/dialects/sun/dsock.c b/dialects/sun/dsock.c
new file mode 100644
index 0000000..50eae2a
--- /dev/null
+++ b/dialects/sun/dsock.c
@@ -0,0 +1,2089 @@
+/*
+ * dsock.c - Solaris socket processing functions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dsock.c,v 1.31 2011/08/07 22:53:42 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+#if solaris>=110000
+#include <inet/ipclassifier.h>
+#endif /* solaris>=110000 */
+
+
+#if defined(HAS_LIBCTF) && solaris>=110000
+/*
+ * Icmp_t, rts_t and udp_t structure support for Solaris >=11 via libctf
+ *
+ * These structure definitions may look like kernel structures, but they
+ * are not. They have been defined to have member names that duplicate
+ * those used by the kernel that are of interest to lsof. Member valuess
+ * are obtained via the CTF library, libctf.
+ *
+ * Robert Byrnes developed the CTF library access code and contributed it
+ * to lsof.
+ */
+
+/*
+ * Icmp_t internal structure definition
+ */
+
+typedef struct icmp_s {
+ uint_t icmp_state; /* TPI state */
+ KA_T *icmp_connp; /* connection structure pointer */
+ in6_addr_t icmp_bound_v6src; /* Explicitely bound to address */
+ in6_addr_t icmp_v6src; /* Source address of this stream */
+ union {
+ uint_t icmp_dummy;
+ uint_t
+ icmp_Debug : 1, /* SO_DEBUG option */
+ icmp_dontroute : 1, /* SO_DONTROUTE option */
+ icmp_broadcast : 1, /* SO_BROADCAST option */
+ icmp_reuseaddr : 1, /* SO_REUSEADDR option */
+ icmp_useloopback : 1, /* SO_USELOOPBACK option */
+ icmp_hdrincl : 1, /* IP_HDRINCL option, etc. */
+ icmp_dgram_errind : 1, /* SO_DGRAM_ERRIND option */
+ icmp_pad : 25; /* pad to bit 31 */
+ } icmp_debug; /* This name identifies a single bit
+ * variable of the kernel's union, but
+ * CTF won't read individual bit
+ * variables, so for CTF's purposes
+ * it is declared as a uint_t union,
+ * named by the first bit variable of
+ * the kernel union, whose address CTF
+ * groks. */
+} icmp_t;
+
+
+/*
+ * Rts_t internal structure definition
+ */
+
+typedef struct rts_s {
+ uint_t rts_state; /* Provider interface state */
+
+# if defined(HAS_CONN_NEW)
+ KA_T *rts_connp; /* connection structure pointer */
+# endif /* defined(HAS_CONN_NEW) */
+
+ union {
+ uint_t rts_dummy;
+ uint_t
+ rts_Debug : 1, /* SO_DEBUG option */
+ rts_dontroute : 1, /* SO_DONTROUTE option */
+ rts_broadcast : 1, /* SO_BROADCAST option */
+ rts_reuseaddr : 1, /* SO_REUSEADDR option */
+ rts_useloopback : 1, /* SO_USELOOPBACK option */
+ icmp_pad : 27; /* padding to bit 31 */
+ } rts_debug; /* This name identifies a single bit
+ * variable, but CTF won't read
+ * individual bit variables, so for
+ * CTF's purposes it is declared as a
+ * uint_t union, named by its first
+ * bit variable, whose address CTF
+ * groks. */
+} rts_t;
+
+/*
+ * Udp_t internal structure definition
+ */
+
+typedef struct udp { uint_t udp_state; /* TPI state */
+ in_port_t udp_port; /* port bound to this stream */
+ in_port_t udp_dstport; /* connected port */
+ in6_addr_t udp_v6src; /* source address of this stream */
+ in6_addr_t udp_v6dst; /* connected destination */
+ ushort_t udp_ipversion; /* version -- IPV[46]_VERSION */
+ KA_T *udp_connp; /* connection structure pointer */
+ uint_t udp_bits; /* socket option bits */
+} udp_t;
+
+
+/*
+ * CTF definitions for icmp_t, rts_t and udp_t
+ */
+
+static int IRU_ctfs = 0; /* CTF initialization status for
+ * icmp_t, rts_t and udp_t */
+
+# if defined(_LP64)
+#define IRU_MOD_FORMAT "/kernel/%s/genunix"
+#else /* !defined(_LP64) */
+#define IRU_MOD_FORMAT "/kernel/genunix"
+#endif /* defined(_LP64) */
+
+ /* genunix pathname template to which
+ * the kernel's instruction type set
+ * is added for CTF access to icmp_t,
+ * rts_t and udp_t */
+
+
+/*
+ * Icmp_t, rts_t and udp_t access definitions and structures
+ */
+
+#define ICMP_T_TYPE_NAME "icmp_t"
+
+static CTF_member_t icmp_t_members[] = {
+ CTF_MEMBER(icmp_state),
+#define MX_icmp_state 0
+
+# if defined(HAS_CONN_NEW)
+
+ CTF_MEMBER(icmp_connp),
+#define MX_icmp_connp 1
+# else /* !defined(HAS_CONN_NEW) */
+ CTF_MEMBER(icmp_bound_v6src),
+#define MX_icmp_bound_v6src 1
+
+ CTF_MEMBER(icmp_v6src),
+#define MX_icmp_v6src 2
+
+ CTF_MEMBER(icmp_debug),
+#define MX_icmp_debug 3
+# endif /* defined(HAS_CONN_NEW) */
+
+ { NULL, 0 }
+};
+
+
+#define RTS_T_TYPE_NAME "rts_t"
+
+static CTF_member_t rts_t_members[] = {
+ CTF_MEMBER(rts_state),
+#define MX_rts_state 0
+
+# if defined(HAS_CONN_NEW)
+ CTF_MEMBER(rts_connp),
+#define MX_rts_connp 1
+# else /* !defined(HAS_CONN_NEW) */
+
+ CTF_MEMBER(rts_debug),
+#define MX_rts_debug 1
+# endif /* defined(HAS_CONN_NEW) */
+
+ { NULL, 0 }
+};
+
+
+#define UDP_T_TYPE_NAME "udp_t"
+
+static CTF_member_t udp_t_members[] = {
+ CTF_MEMBER(udp_state),
+#define MX_udp_state 0
+
+ CTF_MEMBER(udp_connp),
+#define MX_udp_connp 1
+
+# if !defined(HAS_CONN_NEW)
+ CTF_MEMBER(udp_port),
+#define MX_udp_port 2
+
+ CTF_MEMBER(udp_dstport),
+#define MX_udp_dstport 3
+
+ CTF_MEMBER(udp_v6src),
+#define MX_udp_v6src 4
+
+ CTF_MEMBER(udp_v6dst),
+#define MX_udp_v6dst 5
+
+ CTF_MEMBER(udp_ipversion),
+#define MX_udp_ipversion 6
+
+ CTF_MEMBER(udp_bits),
+#define MX_udp_bits 7
+# endif /* !defined(HAS_CONN_NEW) */
+
+ { NULL, 0 }
+};
+
+
+/*
+ * CTF icmp_t, rts_t and udp_t request table
+ */
+
+static CTF_request_t IRU_requests[] = {
+ { ICMP_T_TYPE_NAME, icmp_t_members },
+ { RTS_T_TYPE_NAME, rts_t_members },
+ { UDP_T_TYPE_NAME, udp_t_members },
+ { NULL, NULL }
+};
+
+
+/*
+ * Icmp_t, rts_t and udp_t function prototypes
+ */
+
+_PROTOTYPE(static int read_icmp_t,(KA_T va, KA_T ph, KA_T ia, icmp_t *ic));
+_PROTOTYPE(static int read_rts_t,(KA_T va, KA_T ph, KA_T ra, rts_t *rt));
+_PROTOTYPE(static int read_udp_t,(KA_T ua, udp_t *uc));
+#endif /* defined(HAS_LIBCTF) && solaris>=110000 */
+
+
+#if solaris<80000 || defined(HAS_IPCLASSIFIER_H)
+/*
+ * Make sure the tcpb structure is always defined.
+ */
+
+typedef struct tcpb {
+ int dummy;
+} tcpb_t;
+#endif /* solaris<80000 || defined(HAS_IPCLASSIFIER_H) */
+
+#if defined(HASIPv6)
+
+/*
+ * IPv6_2_IPv4() -- macro to define the address of an IPv4 address contained
+ * in an IPv6 address
+ */
+
+#define IPv6_2_IPv4(v6) (((uint8_t *)((struct in6_addr *)v6)->s6_addr)+12)
+
+/*
+ * IPv_ADDR_UNSPEC() -- macro to test an IP[46] address for an unspecified
+ * address value
+ */
+
+#define IPv_ADDR_UNSPEC(af, p) \
+ (((af) == AF_INET6) ? (IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *)p)) \
+ : (((struct in_addr *)(p))->s_addr == INADDR_ANY))
+#else /* !defined(HASIPv6) */
+
+/*
+ * IPv_ADDR_UNSPEC() -- IPv4-only form of macro to test for an unspecified
+ * address value
+ */
+
+#define IPv_ADDR_UNSPEC(af, p) (((struct in_addr *)(p))->s_addr == INADDR_ANY)
+
+#endif /* !defined(HASIPv6) */
+
+#if defined(HASTCPOPT)
+# if solaris==20600
+#include <netinet/tcp.h>
+# endif /* solaris==20600 */
+#include <netinet/tcp_timer.h>
+#include <netinet/tcp_var.h>
+
+# if defined(TH_TIMER_NEEDED)
+#define ACK_TIMER TH_TIMER_NEEDED
+# else
+# if defined(TH_ACK_TIMER_NEEDED)
+#define ACK_TIMER TH_ACK_TIMER_NEEDED
+# endif /* defined(TH_ACK_TIMER_NEEDED) */
+# endif /* defined(TH_TIMER_NEEDED */
+#endif /* defined(HASTCPOPT) */
+
+#if defined(HASSOOPT)
+# if solaris<100000
+#define KEEPALIVE_INTERVAL tcp_keepalive_intrvl
+# else /* solaris>=100000 */
+#define KEEPALIVE_INTERVAL tcp_ka_last_intrvl
+# endif /* solaris<100000 */
+#endif /* defined(HASSOOPT) */
+
+
+/*
+ * Local function prototypes
+ */
+
+_PROTOTYPE(static void save_TCP_size,(tcp_t *tc));
+_PROTOTYPE(static void save_TCP_states,(tcp_t *tc, caddr_t *fa, tcpb_t *tb,
+ caddr_t *xp));
+
+
+/*
+ * build_IPstates() -- build the TCP and UDP state tables
+ */
+
+void
+build_IPstates()
+{
+ if (!TcpSt) {
+ (void) enter_IPstate("TCP", "CLOSED", TCPS_CLOSED);
+ (void) enter_IPstate("TCP", "IDLE", TCPS_IDLE);
+ (void) enter_IPstate("TCP", "BOUND", TCPS_BOUND);
+ (void) enter_IPstate("TCP", "LISTEN", TCPS_LISTEN);
+ (void) enter_IPstate("TCP", "SYN_SENT", TCPS_SYN_SENT);
+ (void) enter_IPstate("TCP", "SYN_RCVD", TCPS_SYN_RCVD);
+ (void) enter_IPstate("TCP", "ESTABLISHED", TCPS_ESTABLISHED);
+ (void) enter_IPstate("TCP", "CLOSE_WAIT", TCPS_CLOSE_WAIT);
+ (void) enter_IPstate("TCP", "FIN_WAIT_1", TCPS_FIN_WAIT_1);
+ (void) enter_IPstate("TCP", "CLOSING", TCPS_CLOSING);
+ (void) enter_IPstate("TCP", "LAST_ACK", TCPS_LAST_ACK);
+ (void) enter_IPstate("TCP", "FIN_WAIT_2", TCPS_FIN_WAIT_2);
+ (void) enter_IPstate("TCP", "TIME_WAIT", TCPS_TIME_WAIT);
+ (void) enter_IPstate("TCP", (char *)NULL, 0);
+ }
+ if (!UdpSt) {
+ (void) enter_IPstate("UDP", "Unbound", TS_UNBND);
+ (void) enter_IPstate("UDP", "Wait_BIND_REQ_Ack", TS_WACK_BREQ);
+ (void) enter_IPstate("UDP", "Wait_UNBIND_REQ_Ack", TS_WACK_UREQ);
+ (void) enter_IPstate("UDP", "Idle", TS_IDLE);
+ (void) enter_IPstate("UDP", "Wait_OPT_REQ_Ack", TS_WACK_OPTREQ);
+ (void) enter_IPstate("UDP", "Wait_CONN_REQ_Ack", TS_WACK_CREQ);
+ (void) enter_IPstate("UDP", "Wait_CONN_REQ_Confirm", TS_WCON_CREQ);
+ (void) enter_IPstate("UDP", "Wait_CONN_IND_Response", TS_WRES_CIND);
+ (void) enter_IPstate("UDP", "Wait_CONN_RES_Ack", TS_WACK_CRES);
+ (void) enter_IPstate("UDP", "Wait_Data_Xfr", TS_DATA_XFER);
+ (void) enter_IPstate("UDP", "Wait_Read_Release", TS_WIND_ORDREL);
+ (void) enter_IPstate("UDP", "Wait_Write_Release", TS_WREQ_ORDREL);
+ (void) enter_IPstate("UDP", "Wait_DISCON_REQ_Ack", TS_WACK_DREQ6);
+ (void) enter_IPstate("UDP", "Wait_DISCON_REQ_Ack", TS_WACK_DREQ7);
+ (void) enter_IPstate("UDP", "Wait_DISCON_REQ_Ack", TS_WACK_DREQ9);
+ (void) enter_IPstate("UDP", "Wait_DISCON_REQ_Ack", TS_WACK_DREQ10);
+ (void) enter_IPstate("UDP", "Wait_DISCON_REQ_Ack", TS_WACK_DREQ11);
+ (void) enter_IPstate("UDP", (char *)NULL, 0);
+ }
+}
+
+
+/*
+ * print_tcptpi() - print TCP/TPI info
+ */
+
+void
+print_tcptpi(nl)
+ int nl; /* 1 == '\n' required */
+{
+ char *cp = (char *)NULL;
+ char sbuf[128];
+ int i;
+ int ps = 0;
+ unsigned int u;
+
+ if (Ftcptpi & TCPTPI_STATE) {
+ switch (Lf->lts.type) {
+ case 0: /* TCP */
+ if (!TcpSt)
+ (void) build_IPstates();
+ if ((i = Lf->lts.state.i + TcpStOff) < 0 || i >= TcpNstates) {
+ (void) snpf(sbuf, sizeof(sbuf), "UNKNOWN_TCP_STATE_%d",
+ Lf->lts.state.i);
+ cp = sbuf;
+ } else
+ cp = TcpSt[i];
+ break;
+ case 1: /* TPI */
+ if (!UdpSt)
+ (void) build_IPstates();
+ if ((u = Lf->lts.state.ui + UdpStOff) < 0 || u >= UdpNstates) {
+ (void) snpf(sbuf, sizeof(sbuf), "UNKNOWN_UDP_STATE_%u",
+ Lf->lts.state.ui);
+ cp = sbuf;
+ } else
+ cp = UdpSt[u];
+ }
+ if (cp) {
+ if (Ffield)
+ (void) printf("%cST=%s%c", LSOF_FID_TCPTPI, cp, Terminator);
+ else {
+ putchar('(');
+ (void) fputs(cp, stdout);
+ }
+ ps++;
+ }
+ }
+
+#if defined(HASTCPTPIQ)
+ if (Ftcptpi & TCPTPI_QUEUES) {
+ if (Lf->lts.rqs) {
+ if (Ffield)
+ putchar(LSOF_FID_TCPTPI);
+ else {
+ if (ps)
+ putchar(' ');
+ else
+ putchar('(');
+ }
+ (void) printf("QR=%lu", Lf->lts.rq);
+ if (Ffield)
+ putchar(Terminator);
+ ps++;
+ }
+ if (Lf->lts.sqs) {
+ if (Ffield)
+ putchar(LSOF_FID_TCPTPI);
+ else {
+ if (ps)
+ putchar(' ');
+ else
+ putchar('(');
+ }
+ (void) printf("QS=%lu", Lf->lts.sq);
+ if (Ffield)
+ putchar(Terminator);
+ ps++;
+ }
+ }
+#endif /* defined(HASTCPTPIQ) */
+
+#if defined(HASSOOPT)
+ if (Ftcptpi & TCPTPI_FLAGS) {
+ int opt;
+
+ if ((opt = Lf->lts.opt)
+ || Lf->lts.pqlens || Lf->lts.qlens || Lf->lts.qlims
+ || Lf->lts.rbszs || Lf->lts.sbsz
+ ) {
+ char sep = ' ';
+
+ if (Ffield)
+ sep = LSOF_FID_TCPTPI;
+ else if (!ps)
+ sep = '(';
+ (void) printf("%cSO", sep);
+ ps++;
+ sep = '=';
+
+# if defined(SO_BROADCAST)
+ if (opt & SO_BROADCAST) {
+ (void) printf("%cBROADCAST", sep);
+ opt &= ~SO_BROADCAST;
+ sep = ',';
+ }
+# endif /* defined(SO_BROADCAST) */
+
+# if defined(SO_DEBUG)
+ if (opt & SO_DEBUG) {
+ (void) printf("%cDEBUG", sep);
+ opt &= ~ SO_DEBUG;
+ sep = ',';
+ }
+# endif /* defined(SO_DEBUG) */
+
+# if defined(SO_DGRAM_ERRIND)
+ if (opt & SO_DGRAM_ERRIND) {
+ (void) printf("%cDGRAM_ERRIND", sep);
+ opt &= ~SO_DGRAM_ERRIND;
+ sep = ',';
+ }
+# endif /* defined(SO_DGRAM_ERRIND) */
+
+# if defined(SO_DONTROUTE)
+ if (opt & SO_DONTROUTE) {
+ (void) printf("%cDONTROUTE", sep);
+ opt &= ~SO_DONTROUTE;
+ sep = ',';
+ }
+# endif /* defined(SO_DONTROUTE) */
+
+# if defined(SO_KEEPALIVE)
+ if (opt & SO_KEEPALIVE) {
+ (void) printf("%cKEEPALIVE", sep);
+ if (Lf->lts.kai)
+ (void) printf("=%d", Lf->lts.kai);
+ opt &= ~SO_KEEPALIVE;
+ sep = ',';
+ }
+# endif /* defined(SO_KEEPALIVE) */
+
+# if defined(SO_LINGER)
+ if (opt & SO_LINGER) {
+ (void) printf("%cLINGER", sep);
+ if (Lf->lts.ltm)
+ (void) printf("=%d", Lf->lts.ltm);
+ opt &= ~SO_LINGER;
+ sep = ',';
+ }
+# endif /* defined(SO_LINGER) */
+
+# if defined(SO_OOBINLINE)
+ if (opt & SO_OOBINLINE) {
+ (void) printf("%cOOBINLINE", sep);
+ opt &= ~SO_OOBINLINE;
+ sep = ',';
+ }
+# endif /* defined(SO_OOBINLINE) */
+
+ if (Lf->lts.pqlens) {
+ (void) printf("%cPQLEN=%u", sep, Lf->lts.pqlen);
+ sep = ',';
+ }
+ if (Lf->lts.qlens) {
+ (void) printf("%cQLEN=%u", sep, Lf->lts.qlen);
+ sep = ',';
+ }
+ if (Lf->lts.qlims) {
+ (void) printf("%cQLIM=%u", sep, Lf->lts.qlim);
+ sep = ',';
+ }
+ if (Lf->lts.rbszs) {
+ (void) printf("%cRCVBUF=%lu", sep, Lf->lts.rbsz);
+ sep = ',';
+ }
+
+# if defined(SO_REUSEADDR)
+ if (opt & SO_REUSEADDR) {
+ (void) printf("%cREUSEADDR", sep);
+ opt &= ~SO_REUSEADDR;
+ sep = ',';
+ }
+# endif /* defined(SO_REUSEADDR) */
+
+ if (Lf->lts.sbszs) {
+ (void) printf("%cSNDBUF=%lu", sep, Lf->lts.sbsz);
+ sep = ',';
+ }
+
+# if defined(SO_TIMESTAMP)
+ if (opt & SO_TIMESTAMP) {
+ (void) printf("%cTIMESTAMP", sep);
+ opt &= ~SO_TIMESTAMP;
+ sep = ',';
+ }
+# endif /* defined(SO_TIMESTAMP) */
+
+# if defined(SO_USELOOPBACK)
+ if (opt & SO_USELOOPBACK) {
+ (void) printf("%cUSELOOPBACK", sep);
+ opt &= ~SO_USELOOPBACK;
+ sep = ',';
+ }
+# endif /* defined(SO_USELOOPBACK) */
+
+ if (opt)
+ (void) printf("%cUNKNOWN=%#x", sep, opt);
+ if (Ffield)
+ putchar(Terminator);
+ }
+ }
+#endif /* defined(HASSOOPT) */
+
+#if defined(HASTCPOPT)
+ if (Ftcptpi & TCPTPI_FLAGS) {
+ int topt;
+
+ if ((topt = Lf->lts.topt) || Lf->lts.msss) {
+ char sep = ' ';
+
+ if (Ffield)
+ sep = LSOF_FID_TCPTPI;
+ else if (!ps)
+ sep = '(';
+ (void) printf("%cTF", sep);
+ ps++;
+ sep = '=';
+
+# if defined(TF_ACKNOW)
+ if (topt & TF_ACKNOW) {
+ (void) printf("%cACKNOW", sep);
+ topt &= ~TF_ACKNOW;
+ sep = ',';
+ }
+# endif /* defined(TF_ACKNOW) */
+
+# if defined(TF_DELACK)
+ if (topt & TF_DELACK) {
+ (void) printf("%cDELACK", sep);
+ topt &= ~TF_DELACK;
+ sep = ',';
+ }
+# endif /* defined(TF_DELACK) */
+
+ if (Lf->lts.msss) {
+ (void) printf("%cMSS=%lu", sep, Lf->lts.mss);
+ sep = ',';
+ }
+
+# if defined(TF_NODELAY)
+ if (topt & TF_NODELAY) {
+ (void) printf("%cNODELAY", sep);
+ topt &= ~TF_NODELAY;
+ sep = ',';
+ }
+# endif /* defined(TF_NODELAY) */
+
+# if defined(TF_NOOPT)
+ if (topt & TF_NOOPT) {
+ (void) printf("%cNOOPT", sep);
+ topt &= ~TF_NOOPT;
+ sep = ',';
+ }
+# endif /* defined(TF_NOOPT) */
+
+# if defined(TF_SENTFIN)
+ if (topt & TF_SENTFIN) {
+ (void) printf("%cSENTFIN", sep);
+ topt &= ~TF_SENTFIN;
+ sep = ',';
+ }
+# endif /* defined(TF_SENTFIN) */
+
+ if (topt)
+ (void) printf("%cUNKNOWN=%#x", sep, topt);
+ if (Ffield)
+ putchar(Terminator);
+ }
+ }
+#endif /* defined(HASTCPOPT) */
+
+#if defined(HASTCPTPIW)
+ if (Ftcptpi & TCPTPI_WINDOWS) {
+ if (Lf->lts.rws) {
+ if (Ffield)
+ putchar(LSOF_FID_TCPTPI);
+ else {
+ if (ps)
+ putchar(' ');
+ else
+ putchar('(');
+ }
+ (void) printf("WR=%lu", Lf->lts.rw);
+ if (Ffield)
+ putchar(Terminator);
+ ps++;
+ }
+ if (Lf->lts.wws) {
+ if (Ffield)
+ putchar(LSOF_FID_TCPTPI);
+ else {
+ if (ps)
+ putchar(' ');
+ else
+ putchar('(');
+ }
+ (void) printf("WW=%lu", Lf->lts.ww);
+ if (Ffield)
+ putchar(Terminator);
+ ps++;
+ }
+ }
+#endif /* defined(HASTCPTPIW) */
+
+ if (Ftcptpi && !Ffield && ps)
+ putchar(')');
+ if (nl)
+ putchar('\n');
+}
+
+#if solaris>=110000
+/*
+ * procss_VSOCK() -- process a VSOCK socket
+ */
+
+# if defined(HAS_CONN_NEW)
+/*
+ * Adjust for changes in the conn_s structure, introduced at OpenSolaris
+ * level b134.
+ */
+
+#define conn_ulp conn_proto
+#define conn_rem V4_PART_OF_V6(connua_v6addr.connua_faddr)
+#define conn_src V4_PART_OF_V6(connua_v6addr.connua_laddr)
+# endif /* defined(HAS_CONN_NEW) */
+
+int
+process_VSOCK(va, v, so)
+ KA_T va; /* containing vnode address */
+ struct vnode *v; /* pointer to containing vnode */
+ struct sonode *so; /* pointer to socket's sonode */
+{
+ int af; /* address family */
+ struct conn_s cs; /* connection info */
+ unsigned char *fa = (unsigned char *)NULL;
+ /* foreign address */
+ u_short fp = (u_short)0; /* foreign port */
+ u_short lp; /* local port */
+ icmp_t ic; /* ICMP control structure */
+ KA_T ka; /* temporary kernel address */
+ unsigned char *la = (unsigned char *)NULL;
+ /* local address */
+ KA_T pha; /* protocol handle address */
+ rts_t rt; /* AF_ROUTE control structure */
+ int s; /* state */
+ unsigned char *ta = (unsigned char *)NULL;
+ /* temporary address */
+ char tbuf[32], tbuf1[32]; /* temporary buffers */
+ tcp_t tc; /* TCP control structure */
+ tcph_t th; /* TCP header structure */
+
+# if defined(HAS_CONN_NEW)
+ struct ip_xmit_attr_s xa;
+ caddr_t *xp = (caddr_t *)NULL;
+# else /* !defined(HAS_CONN_NEW) */
+ tcph_t *tha = (tcph_t *)NULL; /* TCP header structure address */
+# endif /* defined(HAS_CONN_NEW) */
+
+ char *ty; /* TCP type */
+ udp_t uc; /* local UDP control structure */
+/*
+ * Read VSOCK's connection information. Enter its address as the protocol
+ * control block device address.
+ */
+ if (!(pha = (KA_T)so->so_proto_handle))
+ return(0);
+ if (kread(pha, (char *)&cs, sizeof(cs))) {
+ (void) snpf(Namech, Namechl,
+ "vnode at %s; snode at %s; can't read proto handle at: %s",
+ print_kptr(va, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)v->v_data, tbuf1, sizeof(tbuf1)),
+ print_kptr(pha, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+ enter_dev_ch(print_kptr(pha, (char *)NULL, 0));
+/*
+ * Process connection info by protocol.
+ */
+ switch ((af = so->so_family)) {
+ case AF_INET:
+ case AF_INET6:
+
+ /*
+ * Set INET type -- IPv4 or IPv6.
+ */
+ if (af == AF_INET)
+ ty = "IPv4";
+ else
+ ty = "IPv6";
+ (void) snpf(Lf->type, sizeof(Lf->type), ty);
+
+ switch (cs.conn_ulp) {
+ case IPPROTO_TCP:
+
+ /*
+ * Process TCP socket; read its control structure.
+ */
+ if (!(ka = (KA_T)cs.conn_proto_priv.cp_tcp)
+ || kread(ka, (char *)&tc, sizeof(tc))
+ ) {
+ (void) snpf(Namech, Namechl - 1,
+ "can't read TCP socket's control structure: %s",
+ print_kptr((KA_T)ka, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+ /*
+ * Set TCP protcol name in Lf->iproto[].
+ */
+ (void) snpf(Lf->iproto, IPROTOL - 1, "%s", "TCP");
+ Lf->iproto[IPROTOL - 1] = '\0';
+ Lf->inp_ty = 2;
+ /*
+ * Check for TCP state inclusion or exclusion.
+ */
+ if (TcpNstates) {
+ if ((s = (int)tc.tcp_state + TcpStOff) < TcpNstates) {
+ if (TcpStXn) {
+ if (TcpStX[s]) {
+ Lf->sf |= SELEXCLF;
+ return(1);
+ }
+ }
+ if (TcpStIn) {
+ if (TcpStI[s]) {
+ TcpStI[s] = 2;
+ Lf->sf |= SELNET;
+ } else {
+ Lf->sf |= SELEXCLF;
+ return(1);
+ }
+ }
+ }
+ }
+ /*
+ * Set network file selection status.
+ */
+ if (Fnet) {
+ if (!FnetTy
+ || ((FnetTy == 4) && (af == AF_INET))
+ || ((FnetTy == 6) && (af == AF_INET6))
+ ) {
+ Lf->sf |= SELNET;
+ }
+ }
+ /*
+ * Save local and remote (foreign) TCP address.
+ */
+ if (af == AF_INET6) {
+ ta = (unsigned char *)&cs.connua_v6addr.connua_faddr;
+ la = (unsigned char *)&cs.connua_v6addr.connua_laddr;
+ } else {
+ ta = (unsigned char *)&cs.conn_rem;
+ la = (unsigned char *)&cs.conn_src;
+ }
+ if (!IPv_ADDR_UNSPEC(af, ta) || (u_short)cs.conn_fport) {
+ fa = ta;
+ fp = (u_short)cs.conn_fport;
+ }
+ if ((af == AF_INET6)
+ && ((la && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)la))
+ || ((fa && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)fa))))
+ ) {
+
+ /*
+ * Convert IPv4 addresses in IPv6 structures to IPv4 addresses
+ * in IPv4 structures. Change the address family to AF_INET.
+ */
+ if (la)
+ la = (unsigned char *)IPv6_2_IPv4(la);
+ if (fa)
+ fa = (unsigned char *)IPv6_2_IPv4(fa);
+ af = AF_INET;
+ }
+ lp = (u_short)cs.conn_lport;
+ (void) ent_inaddr(la, (int)ntohs(lp), fa, (int)ntohs(fp), af);
+ /*
+ * Save TCP state information.
+ */
+
+# if defined(HAS_CONN_NEW)
+ if ((ka = (KA_T)cs.conn_ixa)
+ && !kread(ka, (char *)&xa, sizeof(xa))
+ ) {
+ xp = (caddr_t *)&xa;
+ }
+ (void) save_TCP_states(&tc, (caddr_t *)&cs, (tcpb_t *)NULL, xp);
+# else /* !defined(HAS_CONN_NEW) */
+ if (tc.tcp_tcp_hdr_len
+ && (ka = (KA_T)tc.tcp_tcph)
+ && !kread(ka, (char *)&th, sizeof(th))
+ ) {
+ tha = &th;
+ }
+ (void) save_TCP_states(&tc, (caddr_t *)tha, (tcpb_t *)NULL,
+ (caddr_t *)NULL);
+# endif /* defined(HAS_CONN_NEW) */
+
+ Lf->lts.type = 0;
+ Lf->lts.state.i = (int)tc.tcp_state;
+ /*
+ * Save TCP size information.
+ */
+ (void) save_TCP_size(&tc);
+ break;
+ case IPPROTO_UDP:
+
+ /*
+ * Process UDP socket; read its control structure.
+ */
+ if (!(ka = (KA_T)cs.conn_proto_priv.cp_udp)
+ || kread(ka, (char *)&uc, sizeof(uc))
+ ) {
+ (void) snpf(Namech, Namechl - 1,
+ "can't read UDP socket's control structure: %s",
+ print_kptr((KA_T)ka, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+ /*
+ * Set UDP protcol name in Lf->iproto[].
+ */
+ (void) snpf(Lf->iproto, IPROTOL - 1, "%s", "UDP");
+ Lf->iproto[IPROTOL - 1] = '\0';
+ Lf->inp_ty = 2;
+ /*
+ * Check for UDP state inclusion or exclusion.
+ */
+ if (UdpNstates) {
+ if ((s = (int)uc.udp_state + TcpStOff) < UdpNstates) {
+ if (UdpStXn) {
+ if (UdpStX[s]) {
+ Lf->sf |= SELEXCLF;
+ return(1);
+ }
+ }
+ if (UdpStIn) {
+ if (UdpStI[s]) {
+ UdpStI[s] = 2;
+ Lf->sf |= SELNET;
+ } else {
+ Lf->sf |= SELEXCLF;
+ return(1);
+ }
+ }
+ }
+ }
+ /*
+ * Set network file selection status.
+ */
+ if (Fnet) {
+ if (!FnetTy
+ || ((FnetTy == 4) && (af == AF_INET))
+ || ((FnetTy == 6) && (af == AF_INET6))
+ ) {
+ Lf->sf |= SELNET;
+ }
+ }
+ /*
+ * Save local and remote (foreign) UDP address.
+ */
+ if (af == AF_INET6) {
+ ta = (unsigned char *)&cs.connua_v6addr.connua_faddr;
+ la = (unsigned char *)&cs.connua_v6addr.connua_laddr;
+ } else {
+ ta = (unsigned char *)&cs.conn_rem;
+ la = (unsigned char *)&cs.conn_src;
+ }
+ if (!IPv_ADDR_UNSPEC(af, ta) || (u_short)cs.conn_fport) {
+ fa = ta;
+ fp = (u_short)cs.conn_fport;
+ }
+ lp = (u_short)cs.conn_lport;
+ (void) ent_inaddr(la, (int)ntohs(lp), fa, (int)ntohs(fp), af);
+ /*
+ * Save UDP state and size information.
+ */
+ if (!Fsize)
+ Lf->off_def = 1;
+ Lf->lts.type = 1;
+ Lf->lts.state.ui = (unsigned int)uc.udp_state;
+
+# if defined(HASSOOPT)
+ /*
+ * Save UDP flags.
+ */
+ if (Ftcptpi & TCPTPI_FLAGS) {
+ union {
+ uint_t flags;
+ uint_t
+ udpb_debug : 1, /* SO_DEBUG option */
+ udpb_dontroute : 1, /* SO_DONTROUTE option */
+ udpb_broadcast : 1, /* SO_BROADCAST option */
+ udpb_reuseaddr : 1, /* SO_REUSEADDR option */
+ udpb_useloopback : 1, /* SO_USELOOPBACK option */
+ udpb_dgram_errind : 1, /* SO_DGRAM_ERRIND option */
+ udpb_pad : 26; /* pad to bit 31 */
+ } ucf;
+
+ ucf.flags = uc.udp_bits;
+ if (ucf.udpb_debug)
+ Lf->lts.opt |= SO_DEBUG;
+ if (ucf.udpb_dontroute)
+ Lf->lts.opt |= SO_DONTROUTE;
+ if (ucf.udpb_broadcast)
+ Lf->lts.opt |= SO_BROADCAST;
+ if (ucf.udpb_reuseaddr)
+ Lf->lts.opt |= SO_REUSEADDR;
+ if (ucf.udpb_useloopback)
+ Lf->lts.opt |= SO_USELOOPBACK;
+ if (ucf.udpb_dgram_errind)
+ Lf->lts.opt |= SO_DGRAM_ERRIND;
+ }
+# endif /* defined(HASSOOPT) */
+
+ break;
+ case IPPROTO_ICMP:
+ case IPPROTO_ICMPV6:
+
+ /*
+ * Process ICMP or ICMP6 socket.
+ *
+ * Set protocol name.
+ */
+ if (cs.conn_ulp == IPPROTO_ICMP)
+ ty = "ICMP";
+ else
+ ty = "ICMP6";
+ (void) snpf(Lf->iproto, IPROTOL - 1, "%s", ty);
+ Lf->iproto[IPROTOL - 1] = '\0';
+ Lf->inp_ty = 2;
+ /*
+ * Read the ICMP control structure.
+ */
+ if (read_icmp_t(va, pha, (KA_T)cs.conn_proto_priv.cp_icmp, &ic))
+ return(1);
+ /*
+ * Save ICMP size and state information.
+ */
+ if (!Fsize)
+ Lf->off_def = 1;
+ Lf->lts.type = 1;
+ Lf->lts.state.ui = (unsigned int)ic.icmp_state;
+ /*
+ * Set network file selection status.
+ */
+ if (Fnet) {
+ if (!FnetTy
+ || ((FnetTy == 4) && (af == AF_INET))
+ || ((FnetTy == 6) && (af == AF_INET6))
+ ) {
+ Lf->sf |= SELNET;
+ }
+ }
+ /*
+ * Save addresses.
+ */
+ ta = (af == AF_INET6) ? (unsigned char *)&ic.icmp_bound_v6src
+ : (unsigned char *)&V4_PART_OF_V6(ic.icmp_bound_v6src);
+ if (!IPv_ADDR_UNSPEC(af, ta))
+ la = ta;
+ ta = (af == AF_INET6) ? (unsigned char *)&ic.icmp_v6src
+ : (unsigned char *)&V4_PART_OF_V6(ic.icmp_v6src);
+ if (!IPv_ADDR_UNSPEC(af, ta))
+ fa = ta;
+ if (la || fa)
+ (void)ent_inaddr(la, 0, fa, 0, af);
+
+# if defined(HASSOOPT)
+ /*
+ * Save ICMP flags.
+ */
+ if (Ftcptpi & TCPTPI_FLAGS) {
+ if (ic.icmp_debug.icmp_Debug)
+ Lf->lts.opt |= SO_DEBUG;
+ if (ic.icmp_debug.icmp_dontroute)
+ Lf->lts.opt |= SO_DONTROUTE;
+ if (ic.icmp_debug.icmp_broadcast)
+ Lf->lts.opt |= SO_BROADCAST;
+ if (ic.icmp_debug.icmp_reuseaddr)
+ Lf->lts.opt |= SO_REUSEADDR;
+ if (ic.icmp_debug.icmp_useloopback)
+ Lf->lts.opt |= SO_USELOOPBACK;
+ if (ic.icmp_debug.icmp_dgram_errind)
+ Lf->lts.opt |= SO_DGRAM_ERRIND;
+ }
+# endif /* defined(HASSOOPT) */
+
+ break;
+ default:
+ (void) snpf(Namech, Namechl - 1,
+ "unsupported conn_s AF_INET%s protocol: %u",
+ (af == AF_INET6) ? "6" : "",
+ (unsigned int)cs.conn_ulp);
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+ break;
+ case AF_ROUTE:
+
+ /*
+ * Set INET type -- IPv4 or IPv6.
+ */
+ if (af == AF_INET)
+ ty = "IPv4";
+ else
+ ty = "IPv6";
+ (void) snpf(Lf->type, sizeof(Lf->type), ty);
+ /*
+ * Set protocol name.
+ */
+ (void) strncpy(Lf->iproto, "ROUTE", IPROTOL - 1);
+ Lf->iproto[IPROTOL - 1] = '\0';
+ Lf->inp_ty = 2;
+
+ /*
+ * Read routing control structure.
+ */
+ if (read_rts_t(va, pha, (KA_T)cs.conn_proto_priv.cp_rts, &rt))
+ return(1);
+ /*
+ /*
+ * Save AF_ROUTE size and state information.
+ */
+ if (!Fsize)
+ Lf->off_def = 1;
+ Lf->lts.type = 1;
+ Lf->lts.state.i = (int)rt.rts_state;
+ /*
+ * Set network file selection status.
+ */
+ if (Fnet) {
+ if (!FnetTy
+ || ((FnetTy == 4) && (af == AF_INET))
+ || ((FnetTy == 6) && (af == AF_INET6))
+ ) {
+ Lf->sf |= SELNET;
+ }
+ }
+
+# if defined(HASSOOPT)
+ /*
+ * Save ROUTE flags.
+ */
+ if (Ftcptpi & TCPTPI_FLAGS) {
+ if (rt.rts_debug.rts_Debug)
+ Lf->lts.opt |= SO_DEBUG;
+ if (rt.rts_debug.rts_dontroute)
+ Lf->lts.opt |= SO_DONTROUTE;
+ if (rt.rts_debug.rts_broadcast)
+ Lf->lts.opt |= SO_BROADCAST;
+ if (rt.rts_debug.rts_reuseaddr)
+ Lf->lts.opt |= SO_REUSEADDR;
+ if (rt.rts_debug.rts_useloopback)
+ Lf->lts.opt |= SO_USELOOPBACK;
+ }
+# endif /* defined(HASSOOPT) */
+
+ break;
+ default:
+ (void) printiproto((int)cs.conn_ulp);
+ (void) snpf(Namech, Namechl - 1, "unsupported socket family: %u",
+ so->so_family);
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ Lf->inp_ty = 2;
+ }
+ return(1);
+}
+#endif /* solaris>=110000*/
+
+
+/*
+ * process_socket() - process Solaris socket
+ */
+
+void
+process_socket(sa, ty)
+ KA_T sa; /* stream's data address in kernel */
+ char *ty; /* socket type name */
+{
+ int af;
+ unsigned char *fa = (unsigned char *)NULL;
+ int fp = 0;
+ int i, lp;
+
+#if solaris<110000
+# if solaris>=100000 && defined(HAS_IPCLASSIFIER_H)
+ struct conn_s ic;
+#define ipc_v6laddr conn_srcv6
+#define ipc_v6faddr conn_remv6
+#define ipc_fport conn_fport
+#define ipc_lport conn_lport
+# else /* solaris<100000 || !defined(HAS_IPCLASSIFIER_H) */
+ struct ipc_s ic;
+# endif /* solaris>=100000 && defined(HAS_IPCLASSIFIER_H) */
+#else /* solaris>=110000 */
+ struct conn_s cs;
+#endif /* solaris<110000 */
+
+ int ics = 0;
+ unsigned char *la = (unsigned char *)NULL;
+ struct module_info mi;
+ KA_T ka;
+ u_short p;
+ KA_T pcb = (KA_T)NULL;
+ struct queue q;
+ struct qinit qi;
+ KA_T qp;
+ u_short *s;
+ struct stdata sd;
+ unsigned char *ta;
+ char tbuf[32];
+
+#if solaris<20600
+ struct tcp_s { /* should come from kernel source
+ * file ../uts/common/inet/tcp.c */
+
+# if solaris>=20400
+ struct tcp_s *d1[8];
+# endif /* solaris>=20400 */
+
+# if defined(P101318) && P101318>=32
+ struct tcp_s *d1[6];
+# endif /* defined(P101318) && P101318>=32 */
+
+ int tcp_state;
+ queue_t *d3[2];
+ mblk_t *d4[2];
+ u_long d5;
+ mblk_t *d6;
+ u_long d7;
+ u_long tcp_snxt; /* Senders next seq num */
+ u_long tcp_suna; /* Sender unacknowledged */
+ u_long tcp_swnd; /* Senders window (relative to suna) */
+ u_long d8[5];
+ int tcp_hdr_len; /* combined TCP/IP header length */
+ tcph_t *tcp_tcph; /* pointer to combined header */
+ int d9;
+ unsigned int d10;
+ int d11;
+ mblk_t *d12;
+ long d13;
+ mblk_t *d14;
+ u_long d15;
+
+# if solaris<20400 && (!defined(P101318) || P101318<32)
+ mblk_t *d16;
+# endif /* solaris<20400 && (!defined(P101318) || P101318<32) */
+
+ unsigned int d17;
+ u_long tcp_rnxt; /* Seq we expect to recv next */
+ u_long tcp_rwnd; /* Current receive window */
+ u_long d18;
+ long d19[2];
+ mblk_t *d20[4];
+ u_long d21[5];
+ long d22[3];
+
+# if solaris<20500
+ u_long d23[2];
+ u_long tcp_rack; /* Seq # we have acked */
+# else /* solaris>=20500 */
+ u_long d23[3];
+# endif /* solaris<20500 */
+
+# if solaris<20400
+ u_long d24[28];
+# else /* solaris>=20400 */
+# if solaris<20500
+ u_long d24[67];
+# else /* solaris>=20500 */
+# if solaris<20501
+ u_long d25[6];
+# else /* solaris>=20501 */
+ u_long d25[8];
+# endif /* solaris<20501 */
+ u_long tcp_rack; /* Seq # we have acked */
+# if solaris<20501
+ u_long d26[29];
+# else /* solaris>=20501 */
+ u_long d26[33];
+# endif /* solaris>=20501 */
+# endif /* solaris<20500 */
+# endif /* solaris<20400 */
+
+ iph_t tcp_iph;
+ } tc;
+#else /* solaris>=20600 */
+ struct tcp_s tc;
+#endif /* solaris<20600 */
+
+#if solaris>=80000 && !defined(HAS_IPCLASSIFIER_H)
+ tcpb_t tcb;
+#endif /* solaris>=80000 && !defined(HAS_IPCLASSIFIER_H) */
+
+ tcpb_t *tcbp = (tcpb_t *)NULL;
+ int tcs = 0;
+ tcph_t th;
+ tcph_t *tha = (tcph_t *)NULL;
+
+#if solaris<110000
+ struct ud_s { /* should come from kernel source
+ * file ../uts/common/inet/udp.c */
+ uint udp_state; /* TPI state */
+ unsigned char d1[2];
+ unsigned char udp_port[2]; /* port bound to this stream */
+ unsigned char udp_src[4]; /* source address of this stream */
+ } uc;
+#else /* solaris>=110000 */
+ udp_t uc; /* UDP control structure */
+#endif /* solaris<110000 */
+ int ucs = 0;
+
+#if defined(HASIPv6)
+ if (strrchr(ty, '6')) {
+ (void) snpf(Lf->type, sizeof(Lf->type), "IPv6");
+ af = AF_INET6;
+ } else {
+ (void) snpf(Lf->type, sizeof(Lf->type), "IPv4");
+ af = AF_INET;
+ }
+#else /* !defined(HASIPv6) */
+ (void) snpf(Lf->type, sizeof(Lf->type), "inet");
+ af = AF_INET;
+#endif /* defined(HASIPv6) */
+
+/*
+ * Set network file selection status.
+ */
+ if (Fnet) {
+ if (!FnetTy
+ || ((FnetTy == 4) && (af == AF_INET))
+
+#if defined(HASIPv6)
+ || ((FnetTy == 6) && (af == AF_INET6))
+#endif /* defined(HASIPv6) */
+
+ ) {
+ if (!TcpStIn && !UdpStIn)
+ Lf->sf |= SELNET;
+ }
+ }
+ Lf->inp_ty = 2;
+/*
+ * Convert type to upper case protocol name.
+ */
+ if (ty) {
+ for (i = 0; (ty[i] != '\0') && (i < IPROTOL) && (i < 3); i++) {
+ if (islower((unsigned char)ty[i]))
+ Lf->iproto[i] = toupper((unsigned char)ty[i]);
+ else
+ Lf->iproto[i] = ty[i];
+ }
+ } else
+ i = 0;
+ Lf->iproto[i] = '\0';
+/*
+ * Read stream queue entries to obtain private IP, TCP, and UDP structures.
+ */
+ if (!sa || readstdata(sa, &sd))
+ qp = (KA_T)NULL;
+ else
+ qp = (KA_T)sd.sd_wrq;
+ for (i = 0; qp && i < 20; i++, qp = (KA_T)q.q_next) {
+ if (kread(qp, (char *)&q, sizeof(q)))
+ break;
+ if ((ka = (KA_T)q.q_qinfo) == (KA_T)NULL
+ || kread(ka, (char *)&qi, sizeof(qi)))
+ continue;
+ if ((ka = (KA_T)qi.qi_minfo) == (KA_T)NULL
+ || kread(ka, (char *)&mi, sizeof(mi))
+ || (ka = (KA_T)mi.mi_idname) == (KA_T)NULL)
+ continue;
+ if (kread(ka, (char *)&tbuf, sizeof(tbuf) - 1))
+ continue;
+ if ((pcb = (KA_T)q.q_ptr) == (KA_T)NULL)
+ continue;
+
+#if solaris<110000
+ if (strncasecmp(tbuf, "IP", 2) == 0) {
+ if (kread(pcb, (char *)&ic, sizeof(ic)) == 0)
+ ics = 1;
+ continue;
+ }
+#endif /* solaris<110000 */
+
+ if (strncasecmp(tbuf, "TCP", 3) == 0) {
+
+#if solaris<=90000 || !defined(HAS_IPCLASSIFIER_H)
+ if (!kread((KA_T)pcb, (char *)&tc, sizeof(tc)))
+
+# if solaris>=80000
+ {
+ if (tc.tcp_base
+ && !kread((KA_T)tc.tcp_base, (char *)&tcb, sizeof(tcb))) {
+ tcs = 1;
+ tcbp = &tcb;
+ }
+ tc.tcp_base = &tcb; /* support for macros */
+ tcb.tcpb_tcp = &tc; /* support for macros */
+ }
+# else /* solaris<80000 */
+ tcs = 1;
+# endif /* solaris>=80000 */
+#else /* solaris>90000 && defined(HAS_IPCLASSIFIER_H) */
+# if solaris>=110000
+ if (!kread(pcb, (char *)&cs, sizeof(cs))
+ && (cs.conn_ulp == IPPROTO_TCP)
+ ) {
+ ics = 1;
+ if ((ka = (KA_T)cs.conn_proto_priv.cp_tcp)
+ && !kread(ka, (char *)&tc, sizeof(tc))
+ ) {
+ tcs = 1;
+ }
+ }
+# else /* solaris<110000 */
+ if (!kread((KA_T)pcb, (char *)&ic, sizeof(ic))
+ && ic.conn_tcp
+ && !kread((KA_T)ic.conn_tcp, (char *)&tc, sizeof(tc))
+ ) {
+ ics = tcs = 1;
+ }
+# endif /* solaris>=110000 */
+#endif /* solaris<=90000 || !defined(HAS_IPCLASSIFIER_H) */
+
+ if (tcs && TcpNstates) {
+ int s = (int)tc.tcp_state + TcpStOff;
+ /*
+ * Check for TCP state inclusion or exclusion.
+ */
+
+ if (s < TcpNstates) {
+ if (TcpStXn) {
+ if (TcpStX[s]) {
+ Lf->sf &= ~SELNET;
+ Lf->sf |= SELEXCLF;
+ return;
+ }
+ }
+ if (TcpStIn) {
+ if (TcpStI[s]) {
+ TcpStI[s] = 2;
+ Lf->sf |= SELNET;
+ } else {
+ Lf->sf &= ~SELNET;
+ Lf->sf |= SELEXCLF;
+ return;
+ }
+ }
+ }
+ }
+ if (!(Lf->sf & SELNET) && !TcpStIn && UdpStIn) {
+ if (Fnet) {
+ if (!FnetTy
+ || (FnetTy == 4) && (af == AF_INET)
+
+#if defined(HASIPv6)
+ || (FnetTy == 6) && (af == AF_INET6)
+#endif /* defined(HASIPv6) */
+
+ ) {
+ Lf->sf |= SELNET;
+ }
+ }
+ }
+ continue;
+ }
+ if (strncasecmp(tbuf, "UDP", 3) == 0) {
+
+#if solaris<110000
+ if (kread(pcb, (char *)&uc, sizeof(uc)) == 0)
+ ucs = 1;
+#else /* solaris>=110000 */
+ if (!kread(pcb, (char *)&cs, sizeof(cs))
+ && (cs.conn_ulp == IPPROTO_UDP)
+ ) {
+ ics = 1;
+ if ((ka = (KA_T)cs.conn_proto_priv.cp_udp)
+ && !read_udp_t(ka, &uc)
+ ) {
+ ucs = 1;
+ }
+ }
+#endif /* solaris<110000 */
+
+ if (ucs && UdpNstates) {
+ unsigned int s = (unsigned int)uc.udp_state + UdpStOff;
+ /*
+ * Check for UDP state inclusion or exclusion.
+ */
+
+ if (s < UdpNstates) {
+ if (UdpStXn) {
+ if (UdpStX[s]) {
+ Lf->sf &= ~SELNET;
+ Lf->sf |= SELEXCLF;
+ return;
+ }
+ }
+ if (UdpStIn) {
+ if (UdpStI[s]) {
+ UdpStI[s] = 2;
+ Lf->sf |= SELNET;
+ } else {
+ Lf->sf |= SELEXCLF;
+ return;
+ }
+ }
+ }
+ }
+ if (!(Lf->sf & SELNET) && TcpStIn && !UdpStIn) {
+ if (Fnet) {
+ if (!FnetTy
+ || (FnetTy == 4) && (af == AF_INET)
+
+#if defined(HASIPv6)
+ || (FnetTy == 6) && (af == AF_INET6)
+#endif /* defined(HASIPv6) */
+
+ ) {
+ Lf->sf |= SELNET;
+ }
+ }
+ }
+ continue;
+ }
+ }
+ if (ics) {
+
+ /*
+ * Print stream head's q_ptr address as protocol control block address.
+ */
+ if (pcb)
+ enter_dev_ch(print_kptr(pcb, (char *)NULL, 0));
+ if (strncmp(Lf->iproto, "UDP", 3) == 0) {
+
+ /*
+ * Save UDP address and TPI state.
+ */
+
+#if solaris<20600
+ la = (unsigned char *)&ic.ipc_udp_addr;
+ p = (u_short)ic.ipc_udp_port;
+#else /* solaris>=20600 */
+# if solaris>=110000
+ af = (uc.udp_ipversion == IPV6_VERSION) ? AF_INET6 : AF_INET;
+ la = (af == AF_INET6) ? (unsigned char *)&uc.udp_v6src
+ : (unsigned char *)&V4_PART_OF_V6(uc.udp_v6src);
+ p = (u_short)uc.udp_port;
+# else /* solaris<110000 */
+# if defined(HASIPv6)
+ la = (af == AF_INET6) ? (unsigned char *)&ic.ipc_v6laddr
+ : (unsigned char *)IPv6_2_IPv4(&ic.ipc_v6laddr);
+# else /* !defined(HASIPv6 */
+ la = (unsigned char *)&ic.ipc_laddr;
+# endif /* defined(HASIPv6) */
+
+ p = (u_short)ic.ipc_lport;
+# endif /* solaris>=110000 */
+#endif /* solaris<20600 */
+
+#if solaris<110000
+ if (IPv_ADDR_UNSPEC(af, la) && !p && ucs) {
+
+ /*
+ * If the ipc_s structure has no local address, use
+ * the port in the ud_s structure.
+ */
+ s = (u_short *)&uc.udp_port[0];
+ p = *s;
+ }
+
+# if defined(HASIPv6)
+ if ((af == AF_INET6) && la
+ && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)la)) {
+
+ /*
+ * Convert a local IPv4 address in an IPv6 structure to an IPv4
+ * address in an IPv4 structure. Change the address family to
+ * AF_INET.
+ */
+ la = (unsigned char *)IPv6_2_IPv4(la);
+ af = AF_INET;
+ }
+# endif /* defined(HASIPv6) */
+#endif /* solaris<110000 */
+
+ (void) ent_inaddr(la, (int)ntohs(p), (unsigned char *)NULL,
+ -1, af);
+ if (!Fsize)
+ Lf->off_def = 1;
+ if (ucs) {
+ Lf->lts.type = 1;
+ Lf->lts.state.ui = (unsigned int)uc.udp_state;
+ }
+ } else if (strncmp(Lf->iproto, "TCP", 3) == 0) {
+ if (ics) {
+
+ /*
+ * Save TCP address.
+ */
+
+#if solaris<20400
+ la = (unsigned char *)&ic.ipc_tcp_addr[0];
+ p = (u_short)ic.ipc_tcp_addr[5];
+#else /* solaris>=20400 */
+# if solaris<20600
+ la = (unsigned char *)&ic.ipc_tcp_laddr;
+ p = (u_short)((short *)&ic.ipc_tcp_ports)[1];
+# else /* solaris>=20600 */
+# if solaris>=110000
+ la = (af == AF_INET6)
+ ? (unsigned char *)&cs.connua_v6addr.connua_laddr
+ : (unsigned char *)&cs.conn_src;
+ lp = cs.conn_lport;
+# else /* solaris<110000 */
+# if defined(HASIPv6)
+ la = (af == AF_INET6) ? (unsigned char *)&ic.ipc_v6laddr
+ : (unsigned char *)IPv6_2_IPv4(&ic.ipc_v6laddr);
+# else /* !defined(HASIPv6 */
+ la = (unsigned char *)&ic.ipc_laddr;
+# endif /* defined(HASIPv6) */
+
+ p = (u_short)ic.ipc_lport;
+# endif /* solaris>=110000 */
+# endif /* solaris<20600 */
+#endif /* solaris<20400 */
+
+#if solaris<110000
+ if (IPv_ADDR_UNSPEC(af, la) && !p && tcs) {
+
+ /*
+ * If the ipc_s structure has no local address, use the
+ * local address in the stream's tcp_iph structure (except
+ * for Solaris 2.4), and the port number in the stream's
+ * tcph structure.
+ */
+
+# if solaris!=20400 && solaris<80000
+ la = (unsigned char *)&tc.tcp_iph.iph_src[0];
+# else /* solaris==20400 || solaris<80000 */
+# if solaris>=100000 && defined(HAS_IPCLASSIFIER_H)
+ la = (af == AF_INET6) ? (unsigned char *)&ic.conn_srcv6
+ : (unsigned char *)IPv6_2_IPv4(&ic.conn_srcv6);
+# else /* solaris<100000 || !defined(HAS_IPCLASSIFIER_H) */
+# if solaris>=80000
+# if defined(HASIPv6)
+ la = (af == AF_INET6)
+ ? (unsigned char *)&tcb.tcpb_ip_src_v6
+ : (unsigned char *)IPv6_2_IPv4(&tcb.tcpb_ip_src_v6);
+# else /* !defined(HASIPv6) */
+ la = (unsigned char *)&tcb.tcpb_ip_src;
+# endif /* defined(HASIPv6) */
+# endif /* solaris>=80000 */
+# endif /* solaris>=100000 && defined(HAS_IPCLASSIFIER_H) */
+# endif /* solaris!=20400 && !defined(HASIPv6) */
+
+ if (tc.tcp_hdr_len && tc.tcp_tcph
+ && !kread((KA_T)tc.tcp_tcph, (char *)&th, sizeof(th))
+ ) {
+ tha = &th;
+ s = (u_short *)&th.th_lport[0];
+ p = *s;
+ }
+ }
+#endif /* solaris<110000 */
+
+ lp = (int)ntohs(p);
+
+#if solaris<20400
+ if ((int)ic.ipc_tcp_addr[2] != INADDR_ANY
+ || ic.ipc_tcp_addr[4] != 0)
+ {
+ fa = (unsigned char *)&ic.ipc_tcp_addr[2];
+ fp = (int)ntohs(ic.ipc_tcp_addr[4]);
+ }
+#else /* solaris>=20400 */
+# if solaris<20600
+ if ((int)ic.ipc_tcp_faddr != INADDR_ANY
+ || ((u_short *) &ic.ipc_tcp_ports)[0] != 0)
+ {
+ fa = (unsigned char *)&ic.ipc_tcp_faddr;
+ fp = (int)ntohs(((u_short *)&ic.ipc_tcp_ports)[0]);
+ }
+# else /* solaris>=20600 */
+
+# if solaris>=110000
+ ta = (af == AF_INET6)
+ ? (unsigned char *)&cs.connua_v6addr.connua_faddr
+ : (unsigned char *)&cs.conn_rem;
+ if (!IPv_ADDR_UNSPEC(af, ta) || ((u_short)cs.conn_fport)) {
+ fa = ta;
+ fp = (u_short)cs.conn_fport;
+ }
+# else /* solaris<110000 */
+# if defined(HASIPv6)
+ ta = (af == AF_INET6) ? (unsigned char *)&ic.ipc_v6faddr
+ : (unsigned char *)IPv6_2_IPv4(&ic.ipc_v6faddr);
+# else /* !defined(HASIPv6) */
+ ta = (unsigned char *)&ic.ipc_faddr;
+# endif /* defined(HASIPv6) */
+
+ if (!IPv_ADDR_UNSPEC(af, ta) || ((u_short)ic.ipc_fport)) {
+ fa = ta;
+ fp = (int)ntohs(((u_short)ic.ipc_fport));
+ }
+# endif /* solaris>=110000 */
+# endif /* solaris<20600 */
+#endif /* solaris <20400 */
+
+#if defined(HASIPv6)
+ if ((af == AF_INET6)
+ && ((la && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)la))
+ || ((fa && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)fa))))
+ ) {
+
+ /*
+ * Convert IPv4 addresses in IPv6 structures to IPv4
+ * addresses in IPv4 structures. Change the address
+ * family to AF_INET.
+ */
+ if (la)
+ la = (unsigned char *)IPv6_2_IPv4(la);
+ if (fa)
+ fa = (unsigned char *)IPv6_2_IPv4(fa);
+ af = AF_INET;
+ }
+#endif /* defined(HASIPv6) */
+
+ if (fa || la)
+ (void) ent_inaddr(la, lp, fa, fp, af);
+ }
+ /*
+ * Save TCP state information.
+ */
+ if (tcs) {
+ (void) save_TCP_states(&tc, (caddr_t *)tha, tcbp,
+ (caddr_t *)NULL);
+ Lf->lts.type = 0;
+ Lf->lts.state.i = (int)tc.tcp_state;
+ }
+ /*
+ * Save TCP size information.
+ */
+
+ if (tcs)
+ (void) save_TCP_size(&tc);
+ }
+ } else
+ (void) strcat(Namech, "no TCP/UDP/IP information available");
+/*
+ * Enter name characters if there are some.
+ */
+ if (Namech[0])
+ enter_nm(Namech);
+}
+
+
+#if solaris>=110000
+/*
+ * read_icmp_t() - read connections icmp_t info
+ */
+
+static int
+read_icmp_t(va, ph, ia, ic)
+ KA_T va; /* containing vnode kernel address */
+ KA_T ph; /* containing protocol handle kernel
+ * address */
+ KA_T ia; /* icmp_t structure's kernel address */
+ icmp_t *ic; /* local icmp_t receiver */
+{
+ char tbuf[32], tbuf1[32]; /* print_kptr() temporary buffers */
+
+# if defined(HAS_CONN_NEW)
+ struct conn_s cs; /* connection structure */
+ KA_T ka; /* kernel address */
+
+ zeromem((char *)ic, sizeof(icmp_t));
+# endif /* defined(HAS_CONN_NEW) */
+
+ (void) CTF_init(&IRU_ctfs, IRU_MOD_FORMAT, IRU_requests);
+ if (!ia
+ || CTF_MEMBER_READ(ia, ic, icmp_t_members, icmp_state)
+
+# if defined(HAS_CONN_NEW)
+ || CTF_MEMBER_READ(ia, ic, icmp_t_members, icmp_connp)
+# else /* !defined(HAS_CONN_NEW) */
+ || CTF_MEMBER_READ(ia, ic, icmp_t_members, icmp_bound_v6src)
+ || CTF_MEMBER_READ(ia, ic, icmp_t_members, icmp_v6src)
+ || CTF_MEMBER_READ(ia, ic, icmp_t_members, icmp_debug)
+# endif /* defined(HAS_CONN_NEW) */
+
+ ) {
+ (void) snpf(Namech, Namechl - 1,
+ "vnode at %s; proto handle at %s; can't read icmp_t at %s",
+ print_kptr(va, tbuf, sizeof(tbuf)),
+ print_kptr(ph, tbuf1, sizeof(tbuf1)),
+ print_kptr(ia, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+
+# if defined(HAS_CONN_NEW)
+ if ((ka = (KA_T)ic->icmp_connp)
+ && !kread(ka, (char *)&cs, sizeof(cs)))
+ {
+ struct ip_xmit_attr_s xa;
+
+ /*
+ * Complete the icmp_t structure from the conn_s structure.
+ */
+ ic->icmp_bound_v6src = cs.conn_bound_addr_v6;
+ ic->icmp_v6src = cs.conn_saddr_v6;
+ ic->icmp_debug.icmp_Debug = cs.conn_debug;
+ ic->icmp_debug.icmp_broadcast = cs.conn_broadcast;
+ ic->icmp_debug.icmp_reuseaddr = cs.conn_reuseaddr;
+ ic->icmp_debug.icmp_useloopback = cs.conn_useloopback;
+ ic->icmp_debug.icmp_dgram_errind = cs.conn_dgram_errind;
+ if ((ka = (KA_T)cs.conn_ixa)
+ && !kread(ka, (char *)&xa, sizeof(xa))
+ ) {
+ ic->icmp_debug.icmp_dontroute = (xa.ixa_flags & IXAF_DONTROUTE)
+ ? 1 : 0;
+ }
+
+ }
+# endif /* defined(HAS_CONN_NEW) */
+
+ return(0);
+}
+
+
+/*
+ * read_rts_t() - read connections rts_t info
+ */
+
+static int
+read_rts_t(va, ph, ra, rt)
+ KA_T va; /* containing vnode kernel address */
+ KA_T ph; /* containing protocol handle kernel
+ * address */
+ KA_T ra; /* rts_t structure's kernel address */
+ rts_t *rt; /* local rts_t receiver */
+{
+ char tbuf[32], tbuf1[32]; /* print_kptr() temporary buffers */
+
+# if defined(HAS_CONN_NEW)
+ struct conn_s cs; /* connextion structure */
+ KA_T ka; /* kernal address */
+
+ zeromem((char *)rt, sizeof(rts_t));
+# endif /* defined(HAS_CONN_NEW) */
+
+ (void) CTF_init(&IRU_ctfs, IRU_MOD_FORMAT, IRU_requests);
+ if (!ra
+ || CTF_MEMBER_READ(ra, rt, rts_t_members, rts_state)
+
+# if defined(HAS_CONN_NEW)
+ || CTF_MEMBER_READ(ra, rt, rts_t_members, rts_connp)
+# else /* !defined(HAS_CONN_NEW) */
+ || CTF_MEMBER_READ(ra, rt, rts_t_members, rts_debug)
+# endif /* defined(HAS_CONN_NEW) */
+
+ ) {
+ (void) snpf(Namech, Namechl - 1,
+ "vnode at %s; proto handle at %s; can't read rts_t at %s",
+ print_kptr(va, tbuf, sizeof(tbuf)),
+ print_kptr(ph, tbuf1, sizeof(tbuf1)),
+ print_kptr(ra, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+
+# if defined(HAS_CONN_NEW)
+ if ((ka = (KA_T)rt->rts_connp)
+ && !kread(ka, (char *)&cs, sizeof(struct conn_s))
+ ) {
+ struct ip_xmit_attr_s xa;
+
+ /*
+ * Fill in rts_debug from the connection structure.
+ */
+ rt->rts_debug.rts_Debug = cs.conn_debug;
+ rt->rts_debug.rts_broadcast = cs.conn_broadcast;
+ rt->rts_debug.rts_reuseaddr = cs.conn_reuseaddr;
+ rt->rts_debug.rts_useloopback = cs.conn_useloopback;
+ if ((ka = (KA_T)cs.conn_ixa)
+ && !kread(ka, (char *)&xa, sizeof(xa))
+ ) {
+ rt->rts_debug.rts_dontroute = (xa.ixa_flags & IXAF_DONTROUTE)
+ ? 1 : 0;
+ }
+ }
+
+# endif /* defined(HAS_CONN_NEW) */
+
+ return(0);
+}
+
+
+/*
+ * read_udp_t() - read UDP control structure
+ */
+
+static int
+read_udp_t(ua, uc)
+ KA_T ua; /* ucp_t kernel address */
+ udp_t *uc; /* receiving udp_t structure */
+{
+ (void) CTF_init(&IRU_ctfs, IRU_MOD_FORMAT, IRU_requests);
+ if (!ua
+ || CTF_MEMBER_READ(ua, uc, udp_t_members, udp_state)
+
+# if defined(HAS_CONN_NEW)
+ || CTF_MEMBER_READ(ua, uc, udp_t_members, udp_connp)
+# else /* !defined(HAS_CONN_NEW) */
+ || CTF_MEMBER_READ(ua, uc, udp_t_members, udp_port)
+ || CTF_MEMBER_READ(ua, uc, udp_t_members, udp_dstport)
+ || CTF_MEMBER_READ(ua, uc, udp_t_members, udp_v6src)
+ || CTF_MEMBER_READ(ua, uc, udp_t_members, udp_v6dst)
+ || CTF_MEMBER_READ(ua, uc, udp_t_members, udp_ipversion)
+ || CTF_MEMBER_READ(ua, uc, udp_t_members, udp_bits)
+# endif /* defined(HAS_CONN_NEW) */
+
+ ) {
+ (void) snpf(Namech, Namechl, "can't read udp_t: %s",
+ print_kptr(ua, (char *)NULL, 0));
+ Namech[Namechl - 1] = '\0';
+ enter_nm(Namech);
+ return(1);
+ }
+ return(0);
+}
+#endif /* solaris>=110000 */
+
+
+/*
+ * save_TCP_size() -- save TCP size information
+ */
+
+static void
+
+save_TCP_size(tc)
+ tcp_t *tc; /* pointer to TCP control structure */
+{
+ int rq, sq;
+
+#if defined(HASTCPTPIQ) || defined(HASTCPTPIW)
+# if defined(HASTCPTPIW)
+ Lf->lts.rw = (int)tc->tcp_rwnd;
+ Lf->lts.ww = (int)tc->tcp_swnd;
+ Lf->lts.rws = Lf->lts.wws = 1;
+# endif /* defined(HASTCPTPIW) */
+
+ if ((rq = (int)tc->tcp_rnxt - (int)tc->tcp_rack) < 0)
+ rq = 0;
+ if ((sq = (int)tc->tcp_snxt - (int)tc->tcp_suna - 1) < 0)
+ sq = 0;
+
+# if defined(HASTCPTPIQ)
+ Lf->lts.rq = (unsigned long)rq;
+ Lf->lts.sq = (unsigned long)sq;
+ Lf->lts.rqs = Lf->lts.sqs = 1;
+# endif /* defined(HASTCPTPIQ) */
+
+ if (Fsize) {
+ if (Lf->access == 'r')
+ Lf->sz = (SZOFFTYPE)rq;
+ else if (Lf->access == 'w')
+ Lf->sz = (SZOFFTYPE)sq;
+ else
+ Lf->sz = (SZOFFTYPE)(rq + sq);
+ Lf->sz_def = 1;
+ } else
+ Lf->off_def = 1;
+#else /* !defined(HASTCPTPIQ) && !defined(HASTCPTPIW) */
+ Lf->off_def = 1;
+#endif /* defined(HASTCPTPIQ) || defined(HASTCPTPIW) */
+
+}
+
+
+/*
+ * save_TCP_states() - save TCP states
+ */
+
+static void
+save_TCP_states(tc, fa, tb, xp)
+ tcp_t *tc; /* pointer to TCP control structure */
+ caddr_t *fa; /* flags address (may be NULL):
+ * if HAS_CONN_NEW: conn_s *
+ * if !CONN_HAS_NEW: tcph_t *
+ */
+ tcpb_t *tb; /* pointer to TCP base structure (may
+ * be NULL) */
+ caddr_t *xp; /* pointer to struct ip_xmit_attr_s if
+ * HAS_CONN_NEW (may be NULL) */
+{
+ if (!tc)
+ return;
+
+#if defined(HASSOOPT)
+# if defined(HAS_CONN_NEW)
+ if (Ftcptpi & TCPTPI_FLAGS && fa) {
+ struct conn_s *cs = (struct conn_s *)fa;
+
+ if (cs->conn_broadcast)
+ Lf->lts.opt |= SO_BROADCAST;
+ if (cs->conn_debug)
+ Lf->lts.opt |= SO_DEBUG;
+ if (cs->conn_dgram_errind)
+ Lf->lts.opt |= SO_DGRAM_ERRIND;
+ if (xp && (((ip_xmit_attr_t *)xp)->ixa_flags & IXAF_DONTROUTE))
+ Lf->lts.opt |= SO_DONTROUTE;
+ if (cs->conn_keepalive) {
+ Lf->lts.opt |= SO_KEEPALIVE;
+ Lf->lts.kai = (unsigned int)tc->tcp_ka_interval;
+ }
+ if (cs->conn_linger) {
+ Lf->lts.opt |= SO_LINGER;
+ Lf->lts.ltm = (unsigned int)cs->conn_lingertime;
+ }
+ if (cs->conn_oobinline)
+ Lf->lts.opt |= SO_OOBINLINE;
+ Lf->lts.pqlen = (unsigned int)tc->tcp_conn_req_cnt_q0;
+ Lf->lts.qlen = (unsigned int)tc->tcp_conn_req_cnt_q;
+ Lf->lts.qlim = (unsigned int)tc->tcp_conn_req_max;
+ Lf->lts.pqlens = Lf->lts.qlens = Lf->lts.qlims
+ = (unsigned char)1;
+ if (cs->conn_reuseaddr)
+ Lf->lts.opt |= SO_REUSEADDR;
+ if (cs->conn_useloopback)
+ Lf->lts.opt |= SO_USELOOPBACK;
+# else /* !defined(HAS_CONN_NEW) */
+ if (Ftcptpi & TCPTPI_FLAGS) {
+ if (tc->tcp_broadcast)
+ Lf->lts.opt |= SO_BROADCAST;
+ if (tc->tcp_debug)
+ Lf->lts.opt |= SO_DEBUG;
+ if (tc->tcp_dgram_errind)
+ Lf->lts.opt |= SO_DGRAM_ERRIND;
+ if (tc->tcp_dontroute)
+ Lf->lts.opt |= SO_DONTROUTE;
+ if (tc->KEEPALIVE_INTERVAL) {
+ Lf->lts.opt |= SO_KEEPALIVE;
+ Lf->lts.kai = (unsigned int)tc->KEEPALIVE_INTERVAL;
+ }
+ if (tc->tcp_linger) {
+ Lf->lts.opt |= SO_LINGER;
+ Lf->lts.ltm = (unsigned int)tc->tcp_lingertime;
+ }
+ if (tc->tcp_oobinline)
+ Lf->lts.opt |= SO_OOBINLINE;
+ Lf->lts.pqlen = (unsigned int)tc->tcp_conn_req_cnt_q0;
+ Lf->lts.qlen = (unsigned int)tc->tcp_conn_req_cnt_q;
+ Lf->lts.qlim = (unsigned int)tc->tcp_conn_req_max;
+ Lf->lts.pqlens = Lf->lts.qlens = Lf->lts.qlims
+ = (unsigned char)1;
+
+# if solaris>=80000
+# if defined(HAS_IPCLASSIFIER_H)
+ if (tc->tcp_reuseaddr)
+# else /* !defined(HAS_IPCLASSIFIER_H) */
+ if (tb && tb->tcpb_reuseaddr)
+# endif /* !defined(HAS_IPCLASSIFIER_H) */
+
+ Lf->lts.opt |= SO_REUSEADDR;
+# endif /* solaris>=80000 */
+
+ if (tc->tcp_useloopback)
+ Lf->lts.opt |= SO_USELOOPBACK;
+# endif /* defined(HAS_CONN_NEW) */
+#endif /* defined(HASSOOPT) */
+
+#if defined(HASTCPOPT)
+# if defined(ACK_TIMER)
+# if !defined(HAS_CONN_NEW)
+ if (fa && (((tcph_t *)fa)->th_flags[0] & ACK_TIMER))
+ Lf->lts.topt |= TF_DELACK;
+# endif /* !defined(HAS_CONN_NEW) */
+# endif /* defined(ACK_TIMER) */
+
+# if solaris<80000 || defined(HAS_IPCLASSIFIER_H)
+ Lf->lts.mss = (unsigned long)tc->tcp_mss;
+# else /* solaris>=80000 && !defined(HAS_IPCLASSIFIER_H) */
+ if (tb)
+ Lf->lts.mss = (unsigned long)tb->tcpb_mss;
+# endif /* solaris<80000 || defined(HAS_IPCLASSIFIER_H) */
+
+ Lf->lts.msss = (unsigned char)1;
+ if (tc->tcp_naglim == 1L)
+ Lf->lts.topt |= TF_NODELAY;
+ if (tc->tcp_fin_sent)
+ Lf->lts.topt |= TF_SENTFIN;
+ }
+#endif /* defined(HASTCPOPT) */
+
+}
diff --git a/dialects/sun/dstore.c b/dialects/sun/dstore.c
new file mode 100644
index 0000000..345493a
--- /dev/null
+++ b/dialects/sun/dstore.c
@@ -0,0 +1,234 @@
+/*
+ * dstore.c - Solaris global storage for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dstore.c,v 1.23 2010/01/18 19:03:54 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+/*
+ * Global storage definitions
+ */
+
+#if defined(HAS_AFS)
+
+# if defined(HASAOPT)
+char *AFSApath = (char *)NULL; /* alternate AFS name list path
+ * (from -a) */
+# endif /* defined(HASAOPT) */
+
+dev_t AFSdev; /* AFS file system device number */
+int AFSdevStat = 0; /* AFSdev status: 0 = unknown;
+ * 1 = known */
+int AFSfstype = -1; /* AFS file system type index */
+KA_T AFSVfsp = (KA_T)NULL; /* AFS vfs struct kernel address */
+#endif /* defined(HAS_AFS) */
+
+struct clone *Clone = NULL; /* clone list */
+major_t CloneMaj; /* clone major device number */
+
+
+/*
+ * Drive_Nl -- table to drive the building of Nl[] via build_Nl()
+ * (See lsof.h and misc.c.)
+ */
+
+struct drive_Nl Drive_Nl[] = {
+ { "afsops", "afs_ops" },
+ { "arFid", "afs_rootFid" },
+ { "avops", "afs_vnodeops" },
+ { "Avops", "Afs_vnodeops" },
+ { "avol", "afs_volumes" },
+ { "auvops", "auto_vnodeops" },
+ { "ctfsadir", "ctfs_ops_adir" },
+ { "ctfsbund", "ctfs_ops_bundle" },
+ { "ctfscdir", "ctfs_ops_cdir" },
+ { "ctfsctl", "ctfs_ops_ctl", },
+ { "ctfsevt", "ctfs_ops_event", },
+ { "ctfslate", "ctfs_ops_latest", },
+ { "ctfsroot", "ctfs_ops_root", },
+ { "ctfsstat", "ctfs_ops_stat", },
+ { "ctfssym", "ctfs_ops_sym", },
+ { "ctfstdir", "ctfs_ops_tdir", },
+ { "ctfstmpl", "ctfs_ops_tmpl", },
+ { "cvops", "cachefs_vnodeops" },
+ { "clmaj", "clonemaj" },
+ { "clmaj_alt", "clone_major" },
+ { "fdops", "fdvnodeops" },
+ { "fd_ops", "fd_vnodeops" },
+ { "fvops", "fifo_vnodeops" },
+ { "hvops", "hsfs_vnodeops" },
+ { "lvops", "lo_vnodeops" },
+ { "mntops", "mntvnodeops" },
+ { "mvops", "mvfs_vnodeops" },
+
+#if solaris<90000
+ { X_NCACHE, "ncache" },
+ { X_NCSIZE, "ncsize" },
+#else /* solaris>=90000 */
+ { X_NCACHE, "nc_hash" },
+ { X_NCSIZE, "nc_hashsz" },
+ { "hshav", "nc_hashavelen" },
+#endif /* solaris<90000 */
+
+#if defined(NCACHE_NEGVN)
+ { NCACHE_NEGVN, NCACHE_NEGVN },
+#endif /* defined(NCACHE_NEGVN) */
+
+ { "nvops", "nfs_vnodeops" },
+ { "n3vops", "nfs3_vnodeops" },
+ { "n4vops", "nfs4_vnodeops" },
+ { "nmvops", "nm_vnodeops" },
+ { "nproc", "nproc" },
+ { "pdvops", "pcfs_dvnodeops" },
+ { "pfvops", "pcfs_fvnodeops" },
+ { "portvops", "port_vnodeops" },
+ { "pract", "practive" },
+ { "prvops", "prvnodeops" },
+ { "sam1vops", "samfs_vnodeops" },
+ { "sam2vops", "samfs_client_vnodeops" },
+ { "sam3vops", "samfs_vnodeopsp" },
+ { "sam4vops", "samfs_client_vnodeopsp" },
+ { "sdevops", "sdev_vnodeops" },
+ { "sgvops", "segvn_ops" },
+ { "shvops", "sharefs_ops_data" },
+ { "sckvops", "sock_vnodeops" },
+ { "socketvops", "socket_vnodeops" },
+ { "spvops", "spec_vnodeops" },
+ { "sncavops", "socknca_vnodeops" },
+ { "stpivops", "socktpi_vnodeops" },
+ { "tvops", "tmp_vnodeops" },
+ { "uvops", "ufs_vnodeops" },
+ { "vvfops", "fdd_vnops" },
+ { "vvfcops", "fdd_chain_vnops" },
+ { "vvfclops", "vx_fcl_vnodeops_p" },
+ { "vvops", "vx_vnodeops" },
+ { "vvops_p", "vx_vnodeops_p" },
+
+#if solaris>=20500
+ { "devops", "dv_vnodeops" },
+ { "doorops", "door_vnodeops" },
+ { "kbase", "_kernelbase" },
+#endif /* solaris>=20500 */
+
+#if solaris>=20501
+ { "kasp", "kas" },
+#endif /* solaris>=20501 */
+
+#if solaris>=110000
+ { "devipnetops","devipnet_vnodeops" },
+ { "devnetops", "devnet_vnodeops" },
+ { "devptsops", "devpts_vnodeops" },
+ { "devvtops", "devvt_vnodeops" },
+#endif /* solaris>=110000 */
+
+ { "zfsdops", "zfs_dvnodeops" },
+ { "zfseops", "zfs_evnodeops" },
+ { "zfsfops", "zfs_fvnodeops" },
+ { "zfsshops", "zfs_sharevnodeops" },
+ { "zfssymops", "zfs_symvnodeops" },
+ { "zfsxdops", "zfs_xdvnodeops" },
+ { "", "" },
+ { NULL, NULL }
+};
+
+char **Fsinfo = NULL; /* file system information */
+int Fsinfomax = 0; /* maximum file system type */
+int HasALLKMEM = 0; /* has ALLKMEM device */
+int HaveCloneMaj = 0; /* clone major device number has
+ * been identified and is in
+ * CloneMaj */
+kvm_t *Kd = NULL; /* kvm descriptor */
+struct l_vfs *Lvfs = NULL; /* local vfs structure table */
+struct netclone *Netclone = NULL; /* net clone devices from
+ * /devices/pseudo */
+
+#if defined(HASFSTRUCT)
+/*
+ * Pff_tab[] - table for printing file flags
+ */
+
+struct pff_tab Pff_tab[] = {
+ { (long)FREAD, FF_READ },
+ { (long)FWRITE, FF_WRITE },
+ { (long)FNDELAY, FF_NDELAY },
+ { (long)FAPPEND, FF_APPEND },
+ { (long)FSYNC, FF_SYNC },
+
+# if defined(FREVOKED)
+ { (long)FREVOKED, FF_REVOKED },
+# endif /* defined(FREVOKED) */
+
+ { (long)FDSYNC, FF_DSYNC },
+ { (long)FRSYNC, FF_RSYNC },
+
+# if defined(FOFFMAX)
+ { (long)FOFFMAX, FF_LARGEFILE },
+# endif /* defined(FFOFFMAX) */
+
+ { (long)FNONBLOCK, FF_NBLOCK },
+ { (long)FNOCTTY, FF_NOCTTY },
+ { (long)FASYNC, FF_ASYNC },
+ { (long)FNODSYNC, FF_NODSYNC },
+ { (long)0, NULL }
+};
+
+
+/*
+ * Pof_tab[] - table for print process open file flags
+ */
+
+struct pff_tab Pof_tab[] = {
+
+# if defined(UF_EXCLOSE)
+ { (long)UF_EXCLOSE, POF_CLOEXEC },
+# endif /* defined(UF_EXCLOSE) */
+
+# if defined(FD_CLOEXEC)
+ { (long)FD_CLOEXEC, POF_CLOEXEC },
+# endif /* defined(FD_CLOEXEC) */
+
+# if defined(UF_FDLOCK)
+ { (long)UF_FDLOCK, POF_FDLOCK },
+# endif /* defined(UF_FDLOCK) */
+
+ { (long)0, NULL }
+};
+#endif /* defined(HASFSTRUCT) */
+
+struct pseudo *Pseudo = NULL; /* non-clone devices from
+ * /devices/pseudo */
+int Unof; /* u_nofiles value */
diff --git a/dialects/sun/machine.h b/dialects/sun/machine.h
new file mode 100644
index 0000000..1264a09
--- /dev/null
+++ b/dialects/sun/machine.h
@@ -0,0 +1,749 @@
+/*
+ * machine.h - Solaris definitions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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.
+ */
+
+
+/*
+ * $Id: machine.h,v 1.47 2011/09/07 19:16:00 abe Exp $
+ */
+
+#if !defined(LSOF_MACHINE_H)
+#define LSOF_MACHINE_H 1
+
+# if defined(HAS_LGRP_ROOT_CONFLICT)
+/*
+ * <sys/lgrp.h> must be #include'd early on some older Solaris systems at
+ * version 9 and Solaris 10 before _KMEMUSER or _KERNEL are defined to avoid
+ * a conflict with the use of lgrp_root as an external symbol in <sys/lgrp.h>
+ * and a macro in <sys/lgrp_user.h>.
+ */
+
+#include <sys/lgrp.h>
+# endif /* defined(HAS_LGRP_ROOT_CONFLICT) */
+
+
+# if solaris>=100000
+/*
+ * Define a dummy aio_req structure for Solaris >= 10, because #include'ing
+ * <sys/aio_req.h> with _KERNEL defined creates too many problems.
+ */
+
+typedef struct aio_req { int dummy; } aio_req_t;
+
+/*
+ * Include <sys/utsname.h> so it won't be corrupted for 32 bit compilations
+ * when _KERNEL is defined for some include files in dlsof.h.
+ *
+ * Daniel Trinkle identified this requirement.
+ */
+
+#include <sys/utsname.h>
+# endif /* solaris>=100000 */
+
+
+# if solaris>=20600
+/*
+ * <sys/poll.h> must be #include'd for Solaris >= 2.6 while _KMEMUSER is
+ * defined. Since <netdb.h> also #include's <sys/poll.h> and <netdb.h>
+ * is #include'd from lsof.h, we must perform some early #include magic
+ * here to set things up properly.
+ */
+
+#define _KMEMUSER 1
+#define __BIT_TYPES_DEFINED__ 1 /* work around to keep the BIND
+ * <sys/bitypes.h> from colliding with
+ * the Solaris <sys/int_types.h> */
+
+# if defined(HAS_PAD_MUTEX)
+/*
+ * Some versions of Solaris 11 need to have the pad_mutex_t typedef defined.
+ * However, it is only defined by <sys/mutex.h> when _KERNEL is defined, and
+ * doing that causes other difficulties.
+ *
+ * So <sys/mutex.h> is included here, followed by a copy of its pad_mutex_t
+ * typedef, all outside the _KERNEL definition.
+ *
+ * This brute force work-around was supplied by Carson Gaspar.
+ */
+
+#include <sys/mutex.h>
+typedef struct pad_mutex {
+ kmutex_t pad_mutex;
+# if defined(_LP64)
+ char pad_pad[64 - sizeof (kmutex_t)];
+# endif /* defined(_LP64) */
+} pad_mutex_t;
+# endif /* defined(HAS_PAD_MUTEX) */
+
+#include <sys/poll.h>
+
+# if solaris>=80000
+#include <sys/wait.h>
+#include <sys/types32.h>
+#define _KERNEL 1
+#include <netinet/in.h>
+#undef _KERNEL
+#define ipa_32 s6_ipaddr.ipa_32
+# endif /* solaris>=80000 */
+
+# endif /* solaris>=20600 */
+
+
+/*
+ * CAN_USE_CLNT_CREATE is defined for those dialects where RPC clnt_create()
+ * can be used to obtain a CLIENT handle in lieu of clnttcp_create().
+ */
+
+# if solaris>=20501
+#define CAN_USE_CLNT_CREATE 1
+# endif /* solaris>=20501 */
+
+
+/*
+ * DEVDEV_PATH defines the path to the directory that contains device
+ * nodes.
+ */
+
+# if solaris<100000
+#define DEVDEV_PATH "/dev"
+# else /* solaris>=100000 */
+#define DEVDEV_PATH "/devices"
+# endif /* solaris<100000 */
+
+
+/*
+ * GET_MAX_FD is defined for those dialects that provide a function other than
+ * getdtablesize() to obtain the maximum file descriptor number plus one.
+ */
+
+# if solaris<20500
+#define GET_MAX_FD get_max_fd
+# endif /* solaris<20500 */
+
+
+/*
+ * HASAOPT is defined for those dialects that have AFS support; it specifies
+ * that the default path to an alternate AFS kernel name list file may be
+ * supplied with the -A <path> option.
+ */
+
+#define HASAOPT 1
+
+
+/*
+ * HASBLKDEV is defined for those dialects that want block device information
+ * recorded in BDevtp[].
+ */
+
+#define HASBLKDEV 1
+
+
+/*
+ * HASDCACHE is defined for those dialects that support a device cache
+ * file.
+ *
+ * HASENVDC defined the name of an environment variable that contains the
+ * device cache file path. The HASENVDC environment variable is ignored when
+ * the lsof process is setuid(root) or its real UID is 0.
+ *
+ * HASPERSDC defines the format for the last component of a personal device
+ * cache file path. The first will be the home directory of the real UID that
+ * executes lsof.
+ *
+ * HASPERSDCPATH defines the environment variable whose value is the middle
+ * component of the personal device cache file path. The middle component
+ * follows the home directory and precedes the results of applying HASPERSDC.
+ * The HASPERSDCPATH environment variable is ignored when the lsof process is
+ * setuid(root) or its real UID is 0.
+ *
+ * HASSYSDC defines a public device cache file path. When it's defined, it's
+ * used as the path from which to read the device cache.
+ *
+ * Consult the 00DCACHE and 00FAQ files of the lsof distribution for more
+ * information on device cache file path construction.
+ */
+
+#define HASDCACHE 1
+#define HASENVDC "LSOFDEVCACHE"
+#define HASPERSDC "%h/%p.lsof_%L"
+#define HASPERSDCPATH "LSOFPERSDCPATH"
+/* #define HASSYSDC "/your/choice/of/path" */
+
+
+/*
+ * HASCDRNODE is defined for those dialects that have CD-ROM nodes.
+ */
+
+/* #define HASCDRNODE 1 */
+
+
+/*
+ * HASEOPT is defined for dialects that support the +|-e option.
+ */
+
+/* #define HASEOPT 1 */
+
+
+/*
+ * HASFIFONODE is defined for those dialects that have FIFO nodes.
+ */
+
+#define HASFIFONODE 1
+
+
+/*
+ * HASFSINO is defined for those dialects that have the file system
+ * inode element, fs_ino, in the lfile structure definition in lsof.h.
+ */
+
+#define HASFSINO 1
+
+
+/*
+ * HASFSTRUCT is defined if the dialect has a file structure.
+ *
+ * FSV_DEFAULT defines the default set of file structure values to list.
+ * It defaults to zero (0), but may be made up of a combination of the
+ * FSV_* symbols from lsof.h.
+ *
+ * If any file structure value is unavailable, its use may be suppressed
+ * with any of the following definitions:
+ *
+ * HASNOFSADDR -- has no file structure address
+ * HASNOFSFLAGS -- has no file structure flags
+ * HASNOFSCOUNT -- has no file structure count
+ * HASNOFSNADDR -- has no file structure node address
+ */
+
+#define HASFSTRUCT 1
+/* #define FSV_DEFAULT FSV_? | FSV_? | FSV_? */
+/* #define HASNOFSADDR 1 has no file structure address */
+/* #define HASNOFSFLAGS 1 has no file structure flags */
+/* #define HASNOFSCOUNT 1 has no file structure count */
+/* #define HASNOFSNADDR 1 has no file structure node address */
+
+
+/*
+ * HASGNODE is defined for those dialects that have gnodes.
+ */
+
+/* #define HASGNODE 1 */
+
+
+/*
+ * HASHSNODE is defined for those dialects that have High Sierra nodes.
+ */
+
+#define HASHSNODE 1
+
+
+/*
+ * HASINODE is defined for those dialects that have inodes and wish to
+ * use readinode() from node.c.
+ */
+
+/* #define HASINODE 1 */
+
+
+/*
+ * HASINTSIGNAL is defined for those dialects whose signal function returns
+ * an int.
+ */
+
+/* #define HASINTSIGNAL 1 */
+
+
+/*
+ * HASKERNIDCK is defined for those dialects that support the comparison of
+ * the build to running kernel identity.
+ */
+
+#define HASKERNIDCK 1
+
+
+/*
+ * HASKOPT is defined for those dialects that support the -k option of
+ * reading the kernel's name list from an optional file.
+ */
+
+#define HASKOPT 1
+
+
+/*
+ * HASLFILEADD is defined for those dialects that need additional elements
+ * in struct lfile. The HASLFILEADD definition is a macro that defines them.
+ *
+ * If any additional elements need to be preset in the alloc_lfile() function
+ * of proc.c, the SETLFILEADD macro may be defined to do that.
+ *
+ * If any additional elements need to be cleared in alloc_lfile() or in the
+ * free_proc() function of proc.c, the CLRLFILEADD macro may be defined to
+ * do that. Note that CLRLFILEADD takes one argument, the pointer to the
+ * lfile struct. The CLRLFILEADD macro is expected to expand to statements
+ * that are complete -- i.e., have terminating semi-colons -- so the macro is
+ * called without a terminating semicolon by proc.c.
+ *
+ * The HASXOPT definition may be used to select the conditions under which
+ * private lfile elements are used.
+ */
+
+# if solaris>=10000 && defined(HAS_V_PATH)
+#define HASLFILEADD KA_T V_path;
+#define CLRLFILEADD(lf) (lf)->V_path = (KA_T)NULL;
+#define SETLFILEADD Lf->V_path = (KA_T)NULL;
+# endif /* solaris>=10000 && defined(HAS_V_PATH) */
+
+
+/*
+ * HASMNTSTAT indicates the dialect supports the mount stat(2) result option
+ * in its l_vfs and mounts structures.
+ */
+
+# if solaris>=10000 && defined(HAS_V_PATH)
+#define HASMNTSTAT 1
+# endif /* solaris>=10000 && defined(HAS_V_PATH) */
+
+
+/*
+ * HASMNTSUP is defined for those dialects that support the mount supplement
+ * option.
+ */
+
+/* #define HASMNTSUP 1 */
+
+
+/*
+ * HASMOPT is defined for those dialects that support the reading of
+ * kernel memory from an alternate file.
+ */
+
+#define HASMOPT 1
+
+
+/*
+ * HASNCACHE is defined for those dialects that have a kernel name cache
+ * that lsof can search. A value of 1 directs printname() to prefix the
+ * cache value with the file system directory name; 2, avoid the prefix.
+ *
+ * NCACHELDPFX is a set of C commands to execute before calling ncache_load().
+ *
+ * NCACHELDSFX is a set of C commands to execute after calling ncache_load().
+ */
+
+# if solaris>=10000 && defined(HAS_V_PATH)
+/* #define HASNCACHE 1 */
+#else /* solaris<10 || !defined(HAS_V_PATH) */
+#define HASNCACHE 1
+# endif /* solaris>=10000 && defined(HAS_V_PATH) */
+
+#define NCACHELDPFX open_kvm(); /* do before calling ncache_load() */
+
+/* #define NCACHELDSFX ??? */
+
+
+/*
+ * HASNLIST is defined for those dialects that use nlist() to acccess
+ * kernel symbols.
+ */
+
+#define HASNLIST 1
+
+
+/*
+ * HASPIPEFN is defined for those dialects that have a special function to
+ * process DTYPE_PIPE file structure entries. Its value is the name of the
+ * function.
+ *
+ * NOTE: don't forget to define a prototype for this function in dproto.h.
+ */
+
+/* #define HASPIPEFN process_pipe? */
+
+
+/*
+ * HASPIPENODE is defined for those dialects that have pipe nodes.
+ */
+
+/* #define HASPIPENODE 1 */
+
+
+/*
+ * HASPMAPENABLED is defined when the reporting of portmapper registration
+ * info is enabled by default.
+ */
+
+/* #define HASPMAPENABLED 1 */
+
+
+/*
+ * HASPPID is defined for those dialects that support identification of
+ * the parent process IDentifier (PPID) of a process.
+ */
+
+#define HASPPID 1
+
+
+/*
+ * HASPRINTDEV, HASPRINTINO, HASPRINTNM, HASPRINTOFF, and HASPRINTSZ
+ * define private dialect-specific functions for printing DEVice numbers,
+ * INOde numbers, NaMes, file OFFsets, and file SiZes. The functions are
+ * called from print_file().
+ */
+
+# if solaris<100000
+#define HASPRINTDEV print_dev
+# endif /* solaris<100000 */
+
+/* #define HASPRINTINO print_ino? */
+/* #define HASPRINTNM print_nm? */
+/* #define HASPRINTOFF print_off? */
+/* #define HASPRINTSZ print_sz? */
+
+
+/*
+ * HASPRIVFILETYPE and PRIVFILETYPE are defined for dialects that have a
+ * file structure type that isn't defined by a DTYPE_* symbol. They are
+ * used in lib/prfp.c to select the type's processing.
+ *
+ * PRIVFILETYPE is the definition of the f_type value in the file struct.
+ *
+ * HASPRIVFILETYPE is the name of the processing function.
+ */
+
+/* #define HASPRIVFILETYPE process_shmf? */
+/* #define PRIVFILETYPE ?? */
+
+
+/*
+ * HASPRIVNMCACHE is defined for dialects that have a private method for
+ * printing cached NAME column values for some files. HASPRIVNAMECACHE
+ * is defined to be the name of the function.
+ *
+ * The function takes one argument, a struct lfile pointer to the file, and
+ * returns non-zero if it prints a name to stdout.
+ */
+
+# if solaris>=10000 && defined(HAS_V_PATH)
+#define HASPRIVNMCACHE print_v_path
+# else /* solaris<10 || !defined(HAS_V_PATH) */
+# if defined(HASVXFSRNL)
+#define HASPRIVNMCACHE print_vxfs_rnl_path
+# else /* !defined(HASVXFSRNL) */
+/* #define HASPRIVNMCACHE <function name> */
+# endif /* defined(HASVXFSRNL) */
+# endif /* solaris>=10000 && defined(HAS_V_PATH) */
+
+
+/*
+ * HASPRIVPRIPP is defined for dialects that have a private function for
+ * printing IP protocol names. When HASPRIVPRIPP isn't defined, the
+ * IP protocol name printing function defaults to printiprto().
+ */
+
+/* #define HASPRIVPRIPP 1 */
+
+
+/*
+ * HASPROCFS is defined for those dialects that have a proc file system --
+ * usually /proc and usually in SYSV4 derivatives.
+ *
+ * HASFSTYPE is defined as 1 for those systems that have a file system type
+ * string, st_fstype, in the stat() buffer; 2, for those systems that have a
+ * file system type integer in the stat() buffer, named MOUNTS_STAT_FSTYPE;
+ * 0, for systems whose stat(2) structure has no file system type member. The
+ * additional symbols MOUNTS_FSTYPE, RMNT_FSTYPE, and RMNT_STAT_FSTYPE may be
+ * defined in dlsof.h to direct how the readmnt() function in lib/rmnt.c
+ * preserves these stat(2) and getmntent(3) buffer values in the local mounts
+ * structure.
+ *
+ * The defined value is the string that names the file system type.
+ *
+ * The HASPROCFS definition usually must be accompanied by the HASFSTYPE
+ * definition and the providing of an fstype element in the local mounts
+ * structure (defined in dlsof.h).
+ *
+ * The HASPROCFS definition may be accompanied by the HASPINODEN definition.
+ * HASPINODEN specifies that searching for files in HASPROCFS is to be done
+ * by inode number.
+ */
+
+#define HASPROCFS "proc"
+#define HASFSTYPE 1
+#define HASPINODEN 1
+
+
+/*
+ * HASRNODE is defined for those dialects that have rnodes.
+ */
+
+#define HASRNODE 1
+
+
+/*
+ * Define HASSECURITY to restrict the listing of all open files to the
+ * root user. When HASSECURITY is defined, the non-root user may list
+ * only files whose processes have the same user ID as the real user ID
+ * (the one that its user logged on with) of the lsof process.
+ */
+
+/* #define HASSECURITY 1 */
+
+
+/*
+ * If HASSECURITY is defined, define HASNOSOCKSECURITY to allow users
+ * restricted by HASSECURITY to list any open socket files, provide their
+ * listing is selected by the "-i" option.
+ */
+
+/* #define HASNOSOCKSECURITY 1 */
+
+
+/*
+ * HASSETLOCALE is defined for those dialects that have <locale.h> and
+ * setlocale().
+ *
+ * If the dialect also has wide character support for language locales,
+ * HASWIDECHAR activates lsof's wide character support and WIDECHARINCL
+ * defines the header file (if any) that must be #include'd to use the
+ * mblen() and mbtowc() functions.
+ *
+ * If a special definition is required (e.g., for Solaris) before #include'ing
+ * <ctype.h>, do that here.
+ */
+
+#define HASSETLOCALE 1
+#define HASWIDECHAR 1
+#define WIDECHARINCL <wchar.h>
+#define __XPG4_CHAR_CLASS__
+#include <ctype.h>
+#undef __XPG4_CHAR_CLASS__
+
+
+/*
+ * HASSNODE is defined for those dialects that have snodes.
+ */
+
+#define HASSNODE 1
+
+
+/*
+ * HASTASKS is defined for those dialects that have task reporting support.
+ */
+
+/* #define HASTASKS 1 */
+
+
+/*
+ * HASSOOPT, HASSOSTATE and HASTCPOPT define the availability of information
+ * on socket options (SO_* symbols), socket states (SS_* symbols) and TCP
+ * options.
+ */
+
+# if solaris>=20600
+#define HASSOOPT 1 /* has socket option information */
+/* #define HASSOSTATE 1 has socket state information */
+#define HASTCPOPT 1 /* has TCP options or flags */
+# endif /* solaris>=20600 */
+
+
+/*
+ * Define HASSPECDEVD to be the name of a function that handles the results
+ * of a successful stat(2) of a file name argument.
+ *
+ * For example, HASSPECDEVD() for Darwin makes sure that st_dev is set to
+ * what stat("/dev") returns -- i.e., what's in DevDev.
+ *
+ * The function takes two arguments:
+ *
+ * 1: pointer to the full path name of file
+ * 2: pointer to the stat(2) result
+ *
+ * The function returns void.
+ */
+
+/* #define HASSPECDEVD process_dev_stat */
+
+
+/*
+ * HASSTREAMS is defined for those dialects that support streams.
+ */
+
+#define HASSTREAMS 1
+
+
+/*
+ * HASTCPTPIQ is defined for dialects where it is possible to report the
+ * TCP/TPI Recv-Q and Send-Q values produced by netstat.
+ */
+
+# if solaris==20300 || solaris>=20500
+#define HASTCPTPIQ 1
+# endif /* solaris==20300 || solaris>=20500 */
+
+
+/*
+ * HASTCPTPIW is defined for dialects where it is possible to report the
+ * TCP/TPI send and receive window sizes produced by netstat.
+ */
+
+# if solaris==20300 || solaris>=20500
+#define HASTCPTPIW 1
+# endif /* solaris==20300 || solaris>=20500 */
+
+
+/*
+ * HASTCPUDPSTATE is defined for dialects that have TCP and UDP state
+ * support -- i.e., for the "-stcp|udp:state" option and its associated
+ * speed improvements.
+ */
+
+#define HASTCPUDPSTATE 1
+
+
+/*
+ * HASTMPNODE is defined for those dialects that have tmpnodes.
+ */
+
+#define HASTMPNODE 1
+
+
+/*
+ * HASVNODE is defined for those dialects that use the Sun virtual file system
+ * node, the vnode. BSD derivatives usually do; System V derivatives prior to
+ * R4 usually don't.
+ */
+
+#define HASVNODE 1
+
+
+/*
+ * HASXOPT is defined for those dialects that have an X option. It
+ * defines the text for the usage display. HASXOPT_VALUE defines the
+ * option's default binary value -- 0 or 1.
+ */
+
+# if solaris>=10000 && defined(HAS_V_PATH)
+#define HASXOPT "report deleted paths"
+#define HASXOPT_VALUE 0
+# endif /* solaris>=10000 && defined(HAS_V_PATH) */
+
+
+/*
+ * INODETYPE and INODEPSPEC define the internal node number type and its
+ * printf specification modifier. These need not be defined and lsof.h
+ * can be allowed to define defaults.
+ *
+ * These are defined here, because they must be used in dlsof.h.
+ */
+
+# if solaris>=20501
+#define INODETYPE unsigned long long
+ /* inode number internal storage type */
+#define INODEPSPEC "ll" /* INODETYPE printf specification
+ * modifier */
+# endif /* solaris>=20501 */
+
+
+/*
+ * UID_ARG defines the size of a User ID number when it is passed
+ * as a function argument.
+ */
+
+#define UID_ARG long
+
+
+/*
+ * Each USE_LIB_<function_name> is defined for dialects that use the
+ * <function_name> in the lsof library.
+ *
+ * Note: other definitions and operations may be required to condition the
+ * library function source code. They may be found in the dialect dlsof.h
+ * header files.
+ */
+
+#define USE_LIB_CKKV 1 /* ckkv.c */
+#define USE_LIB_COMPLETEVFS 1 /* cvfs.c */
+#define USE_LIB_FIND_CH_INO 1 /* fino.c */
+/* #define USE_LIB_IS_FILE_NAMED 1 isfn.c */
+#define USE_LIB_LKUPDEV 1 /* lkud.c */
+/* #define USE_LIB_PRINTDEVNAME 1 pdvn.c */
+/* #define USE_LIB_PROCESS_FILE 1 prfp.c */
+/* #define USE_LIB_PRINT_TCPTPI 1 ptti.c */
+/* #define USE_LIB_READDEV 1 rdev.c */
+/* #define USE_LIB_READMNT 1 rmnt.c */
+/* #define USE_LIB_REGEX 1 regex.c */
+/* #define USE_LIB_RNAM 1 rnam.c */
+
+# if solaris<90000
+#define USE_LIB_RNCH 1 /* rnch.c */
+# endif /* solaris<90000 */
+
+/* #define USE_LIB_RNMH 1 rnmh.c */
+
+# if solaris<20600
+#define USE_LIB_SNPF 1 /* snpf.c */
+# else /* solaris>=20600 */
+#define snpf snprintf /* use the system's snprintf() */
+# endif /* solaris<20600 */
+
+
+/*
+ * WARNDEVACCESS is defined for those dialects that should issue a warning
+ * when lsof can't access /dev (or /device) or one of its sub-directories.
+ * The warning can be inhibited by the lsof caller with the -w option.
+ */
+
+#define WARNDEVACCESS 1
+
+
+/*
+ * WARNINGSTATE is defined for those dialects that want to suppress all lsof
+ * warning messages.
+ */
+
+/* #define WARNINGSTATE 1 warnings are enabled by default */
+
+
+/*
+ * WILLDROPGID is defined for those dialects whose lsof executable runs
+ * setgid(not_real_GID) and whose setgid power can be relinquished after
+ * the dialect's initialize() function has been executed.
+ */
+
+#define WILLDROPGID 1
+
+
+/*
+ * zeromem is a macro that uses bzero or memset.
+ */
+
+#define zeromem(a, l) memset((void *)a, 0, l)
+
+#endif /* !defined(LSOF_MACHINE_H) */
diff --git a/dialects/sun/solaris_kaddr_filters b/dialects/sun/solaris_kaddr_filters
new file mode 100644
index 0000000..7fcd692
--- /dev/null
+++ b/dialects/sun/solaris_kaddr_filters
@@ -0,0 +1,239 @@
+ Solaris Kernel Address Filtering in lsof 4.50 and Above
+
+Current Filter
+==============
+
+Lsof revisions 4.49 and below, have exactly one filter: the kernel
+virtual address is checked against the kernel's virtual address
+base -- e.g., what's found in the kernel variable kernelbase. For
+sun4m that's 0xf0000000, for sun4u, 0x10000000.
+
+This filter keeps lsof from handing some bad addresses to the
+kernel, but not all bad addresses. For example, the virtual address
+0x657a682e passes this test on a sun4u machine, but on at least
+one sun4u that virtual address translates to the physical address
+0x1cf08c30000, which is the address of a register of a qfe interface
+on the machine. There is some evidence that a kvm_kread() call for
+the 0x657a682e address may crash that sun4u.
+
+Lsof 4.71 and above use no filter if they detect that /dev/allkmem
+exists. That is done because, when /dev/allkmem exists, /dev/kmem has
+address filtering in its device driver.
+
+
+======================
+!!!IMPORTANT UPDATE!!!
+======================
+
+In late May 2002 I learned that Sun had reports of other kernel
+crashes, caused by adb, lsof, and mdb, related to incorrect addresses
+being supplied to /dev/kmem. (This report was written originally
+on July 18, 2000.)
+
+The problem is described in and fixed or patched:
+
+ Solaris 7: SPARC kernel patch 106541-20
+ Intel kernel patch 106542-20
+
+ Solaris 8: SPARC kernel patch 108528-14
+ Intel kernel patch 108529-14
+
+ Solaris 9: bug 4344513
+
+So, if you want to be comfortable using lsof (or adb or mdb) with
+Solaris, install the appropriate Solaris 7 or 8 patches, or upgrade
+to Solaris 9.
+
+Note that these patches provide the /dev/allkmem device, whose presence
+causes lsof to rely on the address filtering of the /dev/kmem device.
+
+
+New Filters
+===========
+
+Lsof 4.50 adds additional filters to the kernelbase check. The
+filters differ, based on the Solaris version:
+
+ Solaris
+ Version New Filters
+ ======= ===========
+
+ 2.5 and below none
+ 2.5.1 kvm_physaddr() (-lkvm), caching, llseek(),
+ and /dev/mem
+ 2.6 kvm_physaddr() (-lkvm), caching, llseek(),
+ and /dev/mem
+ 7, 8, and 9 kvm_physaddr() (ioctl()), caching, and
+ kvm_pread()
+
+ See !!!IMPORTANT NOTICE!! above for
+ information on a Solaris 9 bug report about,
+ or Solaris 7 and 8 kernel patches to the
+ kernel /dev/kmem driver. Those fixes
+ obviate the need for the kernel address
+ filtering described in this report.
+
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ !!! I STRONGLY RECOMMEND YOU INSTALL !!!
+ !!! THE PATCHES OR UPGRADE TO SOLARIS !!!
+ !!! 9. !!!
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+kvm_physaddr() (-lkvm)
+======================
+
+Solaris has an undocumented function called kvm_physaddr() that
+will convert a kernel virtual address to a kernel physical address.
+(Until Solaris 7 this function doesn't even have a prototype
+definition in <kvm.h>.)
+
+I have been assured repeatedly by Casper Dik of Sun that this
+function, when given a kernel virtual address, will produce addresses
+of physical memory only; it will not produce physical addresses of
+interface registers, such as the one for the qfe interface.
+
+In Solaris 2.5.1 this function runs in application space from within
+the KVM library. Since it needs to know the components of the
+kernel's address space map, it must read those from kernel memory
+each time it is called. That can be time consuming.
+
+I'm not sure about kvm_physaddr() for Solaris 2.6. It may still
+run in application space from within the KVM library, but if so,
+it is much faster than its 2.5.1 ancestor.
+
+kvm_physaddr() (ioctl())
+========================
+
+I'm sure that at Solaris 7 and above kvm_physaddr() has moved inside
+the kernel and is called with an ioctl(). That makes it much faster
+than its ancestors.
+
+kvm_physaddr() Use
+==================
+
+Lsof 4.50 for Solaris will use one or the other version of
+kvm_physaddr() for Solaris 2.5.1, 2.6, 7, and 8.
+
+Using it for Solaris 2.5.1 causes lsof to take four times as much
+real time as it formerly did with only the kernelbase filtering.
+
+Caching
+=======
+
+To recover the performance lost by kvm_physaddr() on Solaris 2.5.1,
+I added virtual-to-physical address caching to lsof's kernel read
+function, kread(). This improves Solaris 2.6, 7, and 8 performance,
+too, but by a smaller amount.
+
+It turns out that a typical lsof run may require reading from 16,000
+or more different kernel virtual addresses. However, it also turns
+out that those addresses are contained within about 600 distinct
+kernel memory pages.
+
+To exploit this condition lsof caches each virtual page address
+that has a corresponding legitimate physical page address for use
+in checking later addresses. This caching regains all but a bit
+of the performance loss on Solaris 2.5.1.
+
+Caching can provide some performance gain on Solaris 2.6, 7, and
+8, but it's not nearly as large as the gain for 2.5.1, and may
+depend on the machine architecture type.
+
+/dev/mem
+========
+
+Once lsof has kernel physical addresses, on Solaris 2.5.1 and 2.6
+it seeks to those addresses with llseek() and reads from them via
+the /dev/mem device. This contrasts with lsof's pre-4.50 behavior
+where it fed kernel virtual addresses to kvm_kread(), letting it
+and the kernel do the virtual to physical translations -- and
+letting that combined process crash that one unlucky sun4u via its
+qfe interface.
+
+Using /dev/mem requires no more permission for lsof, but it does
+require an additional open file descriptor and use of the 64 bit
+llseek() function.
+
+The additional file descriptor is an unfortunate consequence of
+the KVM library's opacity. The library usually has /dev/kmem open
+to a file descriptor, but lsof can't easily get at that descriptor,
+so it opens one of its own.
+
+On Solaris 2.6 for one test system, a 4 CPU E4000 sun4u, doing
+physical kernel address reads from /dev/mem turned out to be faster
+than using kvm_kread(). It was marginally faster on a sun4d, and
+marginally slower on two sun4m's.
+
+kvm_pread()
+===========
+
+Even though it is still undocumented, the kvm_physaddr() function
+is represented by a prototype in the Solaris 7 and 8 <kvm.h>.
+Additionally useful is another undocumented function, kvm_pread()
+(for physical read), that also is represented by a <kvm.h> prototype
+in Solaris 7 and 8.
+
+Lsof 4.50 for Solaris 7 and 8 uses kvm_pread() instead of opening
+a descriptor to /dev/mem, llseek()-ing to physical addresses in
+it, and using read(2) to obtain physical address contents. The
+bonus of kvm_pread() is two-fold: 1) it does positioning as well
+as reading, so there's one less function call; and 2) its combined
+operation appears to be faster than llseek() plus read() -- or even
+kvm_kread().
+
+Combined with the virtual-to-physical address caching, the performance
+boost of kvm_pread() makes lsof faster on Solaris 7 and 8 than
+previous revisions, using only kernelbase filtering and kvm_kread().
+
+Remaining Risks
+===============
+
+There may remain some extremely small likelihood that lsof will
+transmit a bad physical address to the kernel. Here are some
+possible failure scenarios:
+
+ * The physical address filters haven't been tested on
+ the machine whose qfe interface was affected. That's
+ because the machine's memory configuration was changed
+ before the test could be run.
+
+ * The kvm_physaddr() function, especially in Solaris
+ 2.5.1, might fail to map an address correctly. Only
+ Sun can correct this problem.
+
+ * Because lsof must read the kernel address map from
+ kernel virtual memory to pass it to the Solaris 2.5.1
+ and 2.6 kvm_physaddr() functions, lsof must use kvm_kread()
+ to read the map.
+
+ There's also the chance that lsof could pass a stale
+ kernel address map to kvm_physaddr(), because re-reading
+ it for each call to kvm_physaddr() would lead to
+ unacceptable performance. When in repeat mode lsof
+ re-reads the map between each cycle.
+
+ On Solaris 7 and 8, since kvm_physaddr() is inside the
+ kernel, there's no chance of its having a stale address
+ map.
+
+ * There's an extremely small chance that a cached
+ virtual+physical page address could become invalid.
+ This is so small I think it can be ignored, since the
+ kernel memory map rarely changes.
+
+ When in repeat mode, lsof clears its virtual+physical
+ address map between cycles.
+
+ * Lsof still uses Sun's kvm_getproc() (from -lkvm), and
+ I have no idea what kernel address filtering it does,
+ if any.
+
+I wish to acknowledge: Casper Dik of Sun, who provided information
+about kvm_physaddr() and helped test the lsof changes; Jim Mewes
+of Phone.com, who reported the initial problem and helped test the
+lsof changes; and several readers of the lsof-l listserv, who
+volunteered to run test programs.
+
+
+Vic Abell
+March 16, 2004
diff --git a/dialects/uw/Makefile b/dialects/uw/Makefile
new file mode 100644
index 0000000..867362a
--- /dev/null
+++ b/dialects/uw/Makefile
@@ -0,0 +1,159 @@
+
+# SCO OSR6 and UW Makefile
+#
+# $Id: Makefile,v 1.14 2008/04/15 13:30:58 abe Exp $
+
+PROG= lsof
+
+BIN= ${DESTDIR}
+
+DOC= ${DESTDIR}
+
+I=/usr/include
+S=/usr/include/sys
+L=/usr/include/local
+P=
+
+CDEF=
+CDEFS= ${CDEF} ${CFGF}
+INCL= ${DINC}
+CFLAGS= ${CDEFS} ${INCL} ${DEBUG}
+
+HDR= lsof.h lsof_fields.h dlsof.h machine.h proto.h dproto.h
+
+SRC= dfile.c dmnt.c dnode.c dnode1.c dnode2.c dnode3.c dproc.c \
+ dsock.c dstore.c \
+ arg.c main.c misc.c node.c print.c proc.c store.c usage.c util.c
+
+OBJ= dfile.o dmnt.o dnode.o dnode1.o dnode2.o dnode3.o dproc.o \
+ dsock.o dstore.o \
+ arg.o main.o misc.o node.o print.o proc.o store.o usage.o util.o
+
+MAN= lsof.8
+
+OTHER=
+
+SHELL= /bin/sh
+
+SOURCE= Makefile ${OTHER} ${MAN} ${HDR} ${SRC}
+
+all: ${PROG}
+
+${PROG}: ${LIB} ${P} ${OBJ}
+ ${CC} -o $@ ${CFLAGS} ${OBJ} ${CFGL}
+
+clean: FRC
+ rm -f Makefile.bak ${PROG} a.out core errs lint.out tags *.o version.h
+ rm -f machine.h.old new_machine.h
+ (cd lib; ${MAKE} -f Makefile.skel clean)
+
+install: all FRC
+ @echo ''
+ @echo 'Please write your own install rule. Lsof should be installed'
+ @echo 'setgid to the group that can can read /dev/kmem. Normally'
+ @echo 'that is the system group. Your AIX install rule actions might'
+ @echo 'look something like this:'
+ @echo ''
+ @echo ' install -m <modes> -o <owner> -g <group> -f $${BIN} $${PROG}'
+ @echo ' install -m 444 -f $${DOC} $${MAN}'
+ @echo ''
+ @echo 'You will have to fill in the <modes>, <owner> and <group>'
+ @echo 'values and complete the skeletons for the BIN and DOC strings'
+ @echo 'given at the beginning of this Makefile, e.g.,'
+ @echo ''
+ @echo ' BIN= $${DESTDIR}/usr/local/etc'
+ @echo ' DOC= $${DESTDIR}/usr/man/manl'
+ @echo ''
+
+${LIB}: FRC
+ (cd lib; ${MAKE} DEBUG="${DEBUG}" CFGF="${CFGF}")
+
+version.h: FRC
+ @echo Constructing version.h
+ @rm -f version.h
+ @echo '#define LSOF_BLDCMT "${LSOF_BLDCMT}"' > version.h;
+ @echo '#define LSOF_CC "${CC}"' >> version.h
+ @echo '#define LSOF_CCV "${CCV}"' >> version.h
+ @echo '#define LSOF_CCDATE "'`date`'"' >> version.h
+ @echo '#define LSOF_CCFLAGS "'`echo ${CFLAGS} | sed 's/\\\\(/\\(/g' | sed 's/\\\\)/\\)/g' | sed 's/"/\\\\"/g'`'"' >> version.h
+ @echo '#define LSOF_CINFO "${CINFO}"' >> version.h
+ @if [ "X${LSOF_HOST}" = "X" ]; then \
+ echo '#define LSOF_HOST "'`uname -n`'"' >> version.h; \
+ else \
+ if [ "${LSOF_HOST}" = "none" ]; then \
+ echo '#define LSOF_HOST ""' >> version.h; \
+ else \
+ echo '#define LSOF_HOST "${LSOF_HOST}"' >> version.h; \
+ fi \
+ fi
+ @echo '#define LSOF_LDFLAGS "${CFGL}"' >> version.h
+ @if [ "X${LSOF_LOGNAME}" = "X" ]; then \
+ echo '#define LSOF_LOGNAME "${LOGNAME}"' >> version.h; \
+ else \
+ if [ "${LSOF_LOGNAME}" = "none" ]; then \
+ echo '#define LSOF_LOGNAME ""' >> version.h; \
+ else \
+ echo '#define LSOF_LOGNAME "${LSOF_LOGNAME}"' >> version.h; \
+ fi; \
+ fi
+ @if [ "X${LSOF_SYSINFO}" = "X" ]; then \
+ echo '#define LSOF_SYSINFO "'`uname -a`'"' >> version.h; \
+ else \
+ if [ "${LSOF_SYSINFO}" = "none" ]; then \
+ echo '#define LSOF_SYSINFO ""' >> version.h; \
+ else \
+ echo '#define LSOF_SYSINFO "${LSOF_SYSINFO}"' >> version.h; \
+ fi \
+ fi
+ @if [ "X${LSOF_USER}" = "X" ]; then \
+ echo '#define LSOF_USER "${USER}"' >> version.h; \
+ else \
+ if [ "${LSOF_USER}" = "none" ]; then \
+ echo '#define LSOF_USER ""' >> version.h; \
+ else \
+ echo '#define LSOF_USER "${LSOF_USER}"' >> version.h; \
+ fi \
+ fi
+ @sed '/VN/s/.ds VN \(.*\)/#define LSOF_VERSION "\1"/' < version >> version.h
+
+FRC:
+
+# DO NOT DELETE THIS LINE - make depend DEPENDS ON IT
+
+dfile.o: ${HDR} dfile.c
+
+dmnt.o: ${HDR} dmnt.c
+
+dnode.o: ${HDR} dnode.c
+
+dnode1.o: ${HDR} dnode1.c
+
+dnode2.o: ${HDR} dnode2.c
+
+dnode3.o: ${HDR} dnode3.c
+
+dproc.o: ${HDR} dproc.c
+
+dsock.o: ${HDR} dsock.c
+
+dstore.o: ${HDR} dstore.c
+
+arg.o: ${HDR} arg.c
+
+main.o: ${HDR} main.c
+
+misc.o: ${HDR} misc.c
+
+node.o: ${HDR} node.c
+
+print.o: ${HDR} print.c
+
+proc.o: ${HDR} proc.c
+
+store.o: ${HDR} store.c
+
+usage.o: ${HDR} version.h usage.c
+
+util.o: ${HDR} util.c
+
+# *** Do not add anything here - It will go away. ***
diff --git a/dialects/uw/Mksrc b/dialects/uw/Mksrc
new file mode 100755
index 0000000..76a96e4
--- /dev/null
+++ b/dialects/uw/Mksrc
@@ -0,0 +1,23 @@
+#!/bin/sh
+#
+# Mksrc - make SCO UnixWare source files
+#
+# WARNING: This script assumes it is running from the main directory
+# of the lsof, version 4 distribution.
+#
+# One environment variable applies:
+#
+# LSOF_MKC is the method for creating the source files.
+# It defaults to "ln -s". A common alternative is "cp".
+#
+# $Id: Mksrc,v 1.5 99/06/22 09:52:02 abe Exp $
+
+D=dialects/uw
+L="dfile.c dlsof.h dmnt.c dnode.c dnode1.c dnode2.c dnode3.c dproc.c dproto.h dsock.c dstore.c machine.h"
+
+for i in $L
+do
+ rm -f $i
+ $LSOF_MKC $D/$i $i
+ echo "$LSOF_MKC $D/$i $i"
+done
diff --git a/dialects/uw/dfile.c b/dialects/uw/dfile.c
new file mode 100644
index 0000000..4ea24da
--- /dev/null
+++ b/dialects/uw/dfile.c
@@ -0,0 +1,216 @@
+/*
+ * dfile.c - SCO UnixWare file processing functions for lsof
+ */
+
+
+/*
+ * Copyright 1996 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 1996 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dfile.c,v 1.11 2000/08/01 15:26:38 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+/*
+ * get_max_fd() - get maximum file descriptor plus one
+ */
+
+int
+get_max_fd()
+{
+ struct rlimit r;
+
+ if (getrlimit(RLIMIT_NOFILE, &r))
+ return(-1);
+ return(r.rlim_cur);
+}
+
+
+/*
+ * process_file() - process file
+ */
+
+void
+process_file(fp)
+ KA_T fp; /* kernel file structure address */
+{
+ struct file f;
+ int flag;
+
+#if defined(FILEPTR)
+ FILEPTR = &f;
+#endif /* defined(FILEPTR) */
+
+ if (kread(fp, (char *)&f, sizeof(f))) {
+ (void) snpf(Namech, Namechl, "can't read file struct from %s",
+ print_kptr(fp, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ Lf->off = (SZOFFTYPE)f.f_offset;
+
+ if (f.f_count
+
+#if defined(HAS_F_OPEN)
+ || f.f_open
+#endif /* defined(HAS_F_OPEN) */
+
+ ) {
+
+ /*
+ * Construct access code.
+ */
+ if ((flag = (f.f_flag & (FREAD | FWRITE))) == FREAD)
+ Lf->access = 'r';
+ else if (flag == FWRITE)
+ Lf->access = 'w';
+ else if (flag == (FREAD | FWRITE))
+ Lf->access = 'u';
+
+#if defined(HASFSTRUCT)
+ /*
+ * Save file structure values.
+ */
+ if (Fsv & FSV_CT) {
+ Lf->fct = (long)f.f_count;
+ Lf->fsv |= FSV_CT;
+ }
+ if (Fsv & FSV_FA) {
+ Lf->fsa = fp;
+ Lf->fsv |= FSV_FA;
+ }
+ if (Fsv & FSV_FG) {
+ Lf->ffg = (long)f.f_flag;
+ Lf->fsv |= FSV_FG;
+ }
+ if (Fsv & FSV_NI) {
+ Lf->fna = (KA_T)f.f_vnode;
+ Lf->fsv |= FSV_NI;
+ }
+#endif /* defined(HASFSTRUCT) */
+
+ /*
+ * Process structure.
+ */
+ process_node((KA_T)f.f_vnode);
+ return;
+ }
+ enter_nm("no more information");
+}
+
+
+/*
+ * Case independent character mappings -- for strcasecmp() and strncasecmp()
+ */
+
+static short CIMap[] = {
+ '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
+ '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
+ '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
+ '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
+ '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
+ '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
+ '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
+ '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
+ '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+ '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+ '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+ '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
+ '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+ '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+ '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+ '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
+ '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
+ '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
+ '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
+ '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
+ '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
+ '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
+ '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
+ '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
+ '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
+ '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
+ '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
+ '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
+ '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
+ '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
+ '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
+ '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
+};
+
+
+/*
+ * strcasecmp() - case insentitive character compare (from BSD)
+ */
+
+int
+strcasecmp(s1, s2)
+ char *s1, *s2;
+{
+ short *mp = CIMap;
+ unsigned char *cp1 = (unsigned char *)s1;
+ unsigned char *cp2 = (unsigned char *)s2;
+
+ while (mp[*cp1] == mp[*cp2]) {
+ if (*cp1++ == '\0')
+ return(0);
+ cp2++;
+ }
+ return ((int)(mp[*cp1] - mp[*cp2]));
+}
+
+
+/*
+ * strncasecmp() - case insensitive character compare, limited by length
+ * (from BSD)
+ */
+
+int
+strncasecmp(s1, s2, n)
+ char *s1, *s2;
+ int n;
+{
+ short *mp = CIMap;
+ unsigned char *cp1, *cp2;
+
+ if (n) {
+ cp1 = (unsigned char *)s1;
+ cp2 = (unsigned char *)s2;
+ do {
+ if (mp[*cp1] != mp[*cp2])
+ return((int)(mp[*cp1] - mp[*cp2]));
+ if (*cp1++ == '\0')
+ break;
+ cp2++;
+ } while (--n != 0);
+ }
+ return(0);
+}
diff --git a/dialects/uw/dlsof.h b/dialects/uw/dlsof.h
new file mode 100644
index 0000000..72cfff2
--- /dev/null
+++ b/dialects/uw/dlsof.h
@@ -0,0 +1,358 @@
+/*
+ * dlsof.h - SCO UnixWare header file for lsof
+ */
+
+
+/*
+ * Copyright 1996 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.
+ */
+
+
+#if !defined(UW_LSOF_H)
+#define UW_LSOF_H 1
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/conf.h>
+#include <sys/exec.h>
+#include <sys/mkdev.h>
+#include <sys/mnttab.h>
+#include <sys/mntent.h>
+#include <netdb.h>
+#include <string.h>
+#include <nlist.h>
+#include <sys/file.h>
+#include <sys/flock.h>
+#include <sys/immu.h>
+#include <sys/fstyp.h>
+#include <sys/fsid.h>
+
+# if UNIXWAREV>=70103
+#include <sys/poll.h>
+#include <sys/fs/prdata.h>
+#define PR_PIDDIR PR_PIDCAT_DIR
+#define PR_AS PR_PIDCAT_AS
+#define PR_CTL PR_PIDCAT_CTL
+#define PR_STATUS PR_PIDCAT_STATUS
+#define PR_MAP PR_PIDCAT_MAP
+#define PR_CRED PR_PIDCAT_CRED
+#define PR_SIGACT PR_PIDCAT_SIGACT
+#define PR_OBJECTDIR PR_PIDCAT_OBJECTDIR
+#define PR_LWPDIR PR_PIDCAT_LWP_DIR
+#define PR_LWPIDDIR PR_PIDCAT_LWP_IDDIR
+#define PR_LWPCTL PR_PIDCAT_LWP_CTL
+#define PR_LWPSTATUS PR_PIDCAT_LWP_STATUS
+#define PR_LWPSINFO PR_PIDCAT_LWP_SINFO
+# endif /* UNIXWAREV>=70103 */
+
+#include <sys/vfs.h>
+#include <sys/vnode.h>
+#include <sys/fs/memfs_mnode.h>
+#include <sys/fs/namenode.h>
+
+# if UNIXWAREV>=70000
+#undef IREAD
+#undef IWRITE
+#undef IEXEC
+# endif /* UNIXWAREV>=70000 */
+
+#include <sys/fs/snode.h>
+
+# if UNIXWAREV<20102
+#include <fs/proc/prdata.h>
+# else /* UNIXWAREV>=20102 */
+# if UNIXWAREV<70103
+#include <fs/procfs/prdata.h>
+# endif /* UNIXWAREV<70103 */
+# endif /* UNIXWAREV<20102 */
+
+#include <sys/mount.h>
+#include <sys/stream.h>
+#include <sys/strsubr.h>
+#include <sys/sysmacros.h>
+#undef major
+#undef minor
+#define major(d) (((d) >> L_BITSMINOR) & L_MAXMAJ)
+#define minor(d) ((d) & L_MAXMIN)
+#include <sys/time.h>
+#include <sys/fs/s5dir.h>
+#include <signal.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/var.h>
+#include <sys/procfs.h>
+#include <sys/priocntl.h>
+#include <sys/tihdr.h>
+#include <sys/tiuser.h>
+#include <sys/un.h>
+#include <rpc/types.h>
+#include <nfs/nfs.h>
+
+#define _KERNEL
+#include <sys/fs/fifonode.h>
+
+# if UNIXWAREV>=70000
+#include <rpc/xdr.h>
+# endif /* UNIXWAREV>=70000 */
+
+#include <nfs/rnode.h>
+#undef _KERNEL
+
+#include <netinet/in.h>
+
+# if defined(HASIPv6)
+#include <netinet/in6.h>
+# if !defined(IN6_ARE_ADDR_EQUAL)
+#define IN6_ARE_ADDR_EQUAL IN6_ADDR_EQUAL /* required by RFC2292 */
+# endif /* !defined(IN6_ARE_ADDR_EQUAL) */
+# endif /* defined(HASIPv6) */
+
+#include <rpc/rpc.h>
+#include <rpc/clnt_soc.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/rpcent.h>
+#include <sys/socket.h>
+#include <net/route.h>
+
+# if defined(HAS_INKERNEL)
+#define INKERNEL
+# endif /* defined(HAS_INKERNEL) */
+
+#include <netinet/in_pcb.h>
+
+# if defined(HAS_INKERNEL)
+#undef INKERNEL
+# endif /* defined(HAS_INKERNEL) */
+
+# if UNIXWAREV>=70000
+#undef TCP_MAXSEG
+#undef TCP_NODELAY
+# endif /* UNIXWAREV>=70000 */
+
+#include <netinet/tcp.h>
+#include <netinet/tcp_fsm.h>
+
+# if UNIXWAREV<70000
+#include <netinet/tcp_kern.h>
+# else /* UNIXWAREV>=70000 */
+#include <netinet/tcp_timer.h>
+
+# if defined(HAS_INKERNEL)
+#define INKERNEL
+# endif /* defined(HAS_INKERNEL) */
+
+#include <netinet/tcp_var.h>
+
+# if defined(HAS_INKERNEL)
+#undef INKERNEL
+# endif /* defined(HAS_INKERNEL) */
+# endif /* UNIXWAREV<70000 */
+
+#include <sys/protosw.h>
+#include <sys/socketvar.h>
+#include <sys/sockmod.h>
+
+# if UNIXWAREV>=70101
+#undef SS_ISBOUND
+#undef SS_ISCONNECTED
+#undef SS_ISCONNECTING
+#undef SS_CANTRCVMORE
+#undef SS_CANTSENDMORE
+#include <sys/socksys.h>
+# endif /* UNIXWAREV>=70101 */
+
+#include <sys/tiuser.h>
+#include <vm/hat.h>
+#include <vm/as.h>
+#include <vm/seg.h>
+
+# if UNIXWAREV>=70000 && UNIXWAREV<70103
+typedef ulong_t channel_t; /* also in types.h #if _KERNEL */
+# endif /* UNIXWAREV>=70000 && UNIXWAREV<70103 */
+
+#include <vm/seg_dev.h>
+#include <vm/seg_map.h>
+#include <vm/seg_vn.h>
+
+#define COMP_P const void
+#define DEVINCR 1024 /* device table malloc() increment */
+#define DIRTYPE dirent
+#define FSNAMEL 4
+typedef off_t KA_T;
+#define KMEM "/dev/kmem"
+
+# if defined(HAS_UW_NSC)
+#define N_UNIX "/unix"
+# else /* !defined(HAS_UW_NSC) */
+#define N_UNIX "/stand/unix"
+# endif /* defined(HAS_UW_NSC) */
+
+# if UNIXWAREV<70103
+#define MALLOC_P char
+#define MALLOC_S unsigned
+# else /* UNIXWAREV>=70103 */
+#define MALLOC_P void
+#define MALLOC_S size_t
+# endif /* UNIXWAREV<70103 */
+
+#define FREE_P MALLOC_P
+#define MAXSEGS 100 /* maximum text segments */
+#define MAXSYSCMDL (PSCOMSIZ - 1) /* max system command name length */
+#define PROCFS "/proc"
+#define PROCINCR 32 /* local proc table malloc increment */
+#define PROCMIN 3 /* processes that make a "good" scan */
+#define PROCSIZE sizeof(struct proc)
+#define PROCTRYLM 5 /* times to try to read proc table */
+#define QSORT_P char
+
+# if UNIXWAREV<7000
+#define READLEN_T unsigned
+# else /* UNIXWAREV>=7000 */
+#define READLEN_T size_t
+# endif /* UNIXWAREV<7000 */
+
+# if defined(HASPROCFS)
+#define PNSIZ 5 /* size of /HASPROCFS names */
+#define PR_INOBIAS 64L /* /HASPROCFS PID to i_number bias */
+#define PR_ROOTINO 2 /* /HASPROCFS root inode number */
+# endif
+
+#define STRNCPY_L size_t
+#define STRNML 32
+
+# if UNIXWAREV>=70000
+#define SZOFFTYPE unsigned long long
+ /* type for size and offset */
+#define SZOFFPSPEC "ll" /* SZOFFTYPE printf specification
+ * modifier */
+/*
+ * Use the 64 bit stat() functions, so that lsof can get parameters on
+ * large and small files.
+ */
+#define fstat fstat64
+#define lstat lstat64
+#define stat stat64
+# else /* UNIXWAREV<70000 */
+#define SZOFFTYPE unsigned long /* type for size and offset */
+#define SZOFFPSPEC "l" /* SZOFFTYPE printf specification modifier */
+# endif /* UNIXWAREV>=7000 */
+
+#define U_SIZE sizeof(struct user)
+
+
+/*
+ * Global storage definitions (including their structure definitions)
+ */
+
+extern int CloneMaj;
+extern char **Fsinfo;
+extern int Fsinfomax;
+extern int HaveCloneMaj;
+extern int Kd;
+
+struct l_ino {
+ dev_t dev; /* device */
+ long nlink; /* link count */
+ char *nm; /* name */
+ INODETYPE number; /* inode number */
+ dev_t rdev; /* raw device */
+ SZOFFTYPE size; /* file size */
+ unsigned char dev_def; /* dev is defined */
+ unsigned char nlink_def; /* link count is defined */
+ unsigned char number_def; /* number is defined */
+ unsigned char rdev_def; /* rdev is defined */
+ unsigned char size_def; /* size is defined */
+};
+
+struct mounts {
+ char *dir; /* directory (mounted on) */
+ char *fsname; /* file system
+ * (symbolic links unresolved) */
+ char *fsnmres; /* file system
+ * (symbolic links resolved) */
+ dev_t dev; /* directory st_dev */
+ dev_t rdev; /* directory st_rdev */
+ INODETYPE inode; /* directory st_ino */
+ mode_t mode; /* directory st_mode */
+ mode_t fs_mode; /* file system st_mode */
+ struct mounts *next; /* forward link */
+
+# if defined(HASFSTYPE)
+ char *fstype; /* st_fstype */
+# endif
+
+};
+
+extern short Nfstyp;
+
+#define X_NCACHE "ncache"
+#define X_NCSIZE "ncsize"
+#define NL_NAME n_name
+
+struct sfile {
+ char *aname; /* argument file name */
+ char *name; /* file name (after readlink()) */
+ char *devnm; /* device name (optional) */
+ dev_t dev; /* device */
+ dev_t rdev; /* raw device */
+ u_short mode; /* S_IFMT mode bits from stat() */
+ int type; /* file type: 0 = file system
+ * 1 = regular file */
+ INODETYPE i; /* inode number */
+ int f; /* file found flag */
+ struct sfile *next; /* forward link */
+};
+
+#include <setjmp.h>
+
+
+/*
+ * Definition for ckfa.c
+ */
+
+#define CKFA_XDEVTST strcmp(sb.st_fstype,"cdfs")==0
+
+
+/*
+ * Definition for dvch.c, isfn.c, and rdev.c
+ */
+
+#define CLONEMAJ CloneMaj /* clone major variable name */
+#define HAS_STD_CLONE 1 /* has standard clone handling */
+#define HAVECLONEMAJ HaveCloneMaj /* clone major status variable name */
+
+
+/*
+ * Definitions for rnch.c
+ */
+
+#if defined(HASNCACHE)
+#include <sys/dnlc.h>
+#endif /* defined(HASNCACHE) */
+
+#endif /* UW_LSOF_H */
diff --git a/dialects/uw/dmnt.c b/dialects/uw/dmnt.c
new file mode 100644
index 0000000..93690b2
--- /dev/null
+++ b/dialects/uw/dmnt.c
@@ -0,0 +1,227 @@
+/*
+ * dmnt.c - SCO UnixWare mount support functions for lsof
+ */
+
+
+/*
+ * Copyright 1996 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 1996 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dmnt.c,v 1.7 2005/08/13 16:21:41 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+/*
+ * Local static definitions
+ */
+
+static struct mounts *Lmi = (struct mounts *)NULL; /* local mount info */
+static int Lmist = 0; /* Lmi status */
+
+
+/*
+ * readmnt() - read mount table
+ */
+
+struct mounts *
+readmnt()
+{
+ char *dn = (char *)NULL;
+ char *ln;
+ struct mnttab me;
+ FILE *mfp;
+ struct mounts *mtp;
+ char *opt, *opte;
+ struct stat sb;
+
+#if defined(HASPROCFS)
+ int procfs = 0;
+#endif
+
+ if (Lmi || Lmist)
+ return(Lmi);
+/*
+ * Open access to the mount table and read mount table entries.
+ */
+ if (!(mfp = fopen(MNTTAB, "r"))) {
+ (void) fprintf(stderr, "%s: can't access %s\n", Pn, MNTTAB);
+ return(0);
+ }
+ while (!getmntent(mfp, &me)) {
+
+ /*
+ * Skip loop-back mounts, since they are aliases for legitimate file
+ * systems and there is no way to determine that a vnode refers to a
+ * loop-back alias.
+ *
+ * Also skip file systems of type MNTTYPE_IGNORE or with the option
+ * MNTOPT_IGNORE, since they are auto-mounted file systems whose
+ * real entries (if they are mounted) will be separately identified
+ * by getmntent().
+ */
+ if (!strcmp(me.mnt_fstype, MNTTYPE_LO)
+ || !strcmp(me.mnt_fstype, MNTTYPE_IGNORE))
+ continue;
+ /*
+ * Interpolate a possible symbolic directory link.
+ */
+ if (dn)
+ (void) free((FREE_P *)dn);
+ if (!(dn = mkstrcpy(me.mnt_mountp, (MALLOC_S *)NULL))) {
+
+no_space_for_mount:
+
+ (void) fprintf(stderr, "%s: no space for mount at ",Pn);
+ safestrprt(me.mnt_special, stderr, 0);
+ (void) fprintf(stderr, " (");
+ safestrprt(me.mnt_mountp, stderr, 0);
+ (void) fprintf(stderr, ")\n");
+ Exit(1);
+ }
+ if (!(ln = Readlink(dn))) {
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ " Output information may be incomplete.\n");
+ }
+ continue;
+ }
+ if (ln != dn) {
+ (void) free((FREE_P *)dn);
+ dn = ln;
+ }
+ if (*dn != '/')
+ continue;
+ /*
+ * Stat() the directory.
+ */
+ if (statsafely(dn, &sb)) {
+ if (!Fwarn) {
+ (void) fprintf(stderr, "%s: can't stat()", Pn);
+
+#if defined(HASFSTYPE)
+ putc(' ', stderr);
+ safestrprt(me.mnt_fstype, stderr, 0);
+#endif /* defined(HASFSTYPE) */
+
+ (void) fprintf(stderr, " file system ");
+ safestrprt(me.mnt_mountp, stderr, 1);
+ (void) fprintf(stderr,
+ " Output information may be incomplete.\n");
+ }
+ if (!(opt = strstr(me.mnt_mntopts, "dev="))) {
+ (void) memset(&sb, 0, sizeof(sb));
+ if (!(opte = x2dev(opt + 4, &sb.st_dev))) {
+ sb.st_mode = S_IFDIR | 0777;
+
+#if defined(HASFSTYPE)
+ (void) strncpy(sb.st_fstype, me.mnt_fstype,
+ sizeof(sb.st_fstype));
+ sb.st_fstype[sizeof(sb.st_fstype) - 1 ] = '\0';
+#endif /* HASFSTYPE */
+
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ " assuming \"%.*s\" from %s\n",
+ (opte - opt), opt, MNTTAB);
+ }
+ } else
+ opt = (char *)NULL;
+ }
+ if (!opt)
+ continue;
+ }
+ /*
+ * Allocate and fill a local mount structure.
+ */
+ if (!(mtp = (struct mounts *)malloc(sizeof(struct mounts))))
+ goto no_space_for_mount;
+
+#if defined(HASFSTYPE)
+ if (!(mtp->fstype = mkstrcpy(sb.st_fstype, (MALLOC_S *)NULL)))
+ goto no_space_for_mount;
+#endif /* HASFSTYPE */
+
+ mtp->dir = dn;
+ dn = (char *)NULL;
+ mtp->next = Lmi;
+ mtp->dev = sb.st_dev;
+ mtp->rdev = sb.st_rdev;
+ mtp->inode = (INODETYPE)sb.st_ino;
+ mtp->mode = sb.st_mode;
+
+#if defined(HASPROCFS)
+# if defined(HASFSTYPE)
+ if (!strcmp(sb.st_fstype, HASPROCFS))
+# else /* !defined*HASFSTYPE) */
+ if (!strcmp(me.mnt_special, "/proc"))
+# endif /* defined(HASFSTYPE) */
+
+ {
+
+ /*
+ * Save information on exactly one procfs file system.
+ */
+ if (procfs)
+ Mtprocfs = (struct mounts *)NULL;
+ else {
+ procfs = 1;
+ Mtprocfs = mtp;
+ }
+ }
+#endif /* defined(HASPROCFS) */
+
+ /*
+ * Interpolate a possible file system (mounted-on device) name link.
+ */
+ if (!(dn = mkstrcpy(me.mnt_special, (MALLOC_S *)NULL)))
+ goto no_space_for_mount;
+ mtp->fsname = dn;
+ ln = Readlink(dn);
+ dn = (char *)NULL;
+ /*
+ * Stat() the file system (mounted-on) name and add file system
+ * information to the local mounts structure.
+ */
+ if (!ln || statsafely(ln, &sb))
+ sb.st_mode = 0;
+ mtp->fsnmres = ln;
+ mtp->fs_mode = sb.st_mode;
+ Lmi = mtp;
+ }
+ (void) fclose(mfp);
+/*
+ * Clean up and return local mount info table address.
+ */
+ if (dn)
+ (void) free((FREE_P *)dn);
+ Lmist = 1;
+ return(Lmi);
+}
diff --git a/dialects/uw/dnode.c b/dialects/uw/dnode.c
new file mode 100644
index 0000000..bc91e46
--- /dev/null
+++ b/dialects/uw/dnode.c
@@ -0,0 +1,1574 @@
+/*
+ * dnode.c - SCO UnixWare node functions for lsof
+ */
+
+
+/*
+ * Copyright 1996 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 1996 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dnode.c,v 1.28 2006/03/28 21:57:57 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+#include <sys/fs/namenode.h>
+
+#if UNIXWAREV>=70000
+#undef IREAD
+#undef IWRITE
+#undef IEXEC
+#endif /* UNIXWAREV>=70000 */
+
+#if defined(HAS_UW_CFS)
+#include <fs/nsc_cfs/cnode.h>
+#endif /* defined(HAS_UW_CFS) */
+
+#include <sys/fs/ufs_inode.h>
+
+#if defined(HASXNAMNODE)
+#include <sys/fs/xnamnode.h>
+#endif /* defined(HASXNAMNODE) */
+
+
+_PROTOTYPE(static void ent_fa,(KA_T *a1, KA_T *a2, char *d));
+_PROTOTYPE(static int get_vty,(struct vnode *v, KA_T va, struct vfs *kv, int *fx));
+
+#if UNIXWAREV<70103
+_PROTOTYPE(static int examine_stream,(KA_T vs, struct queue *q, char *mn,
+ char *sn, KA_T *sqp));
+#else /* UNIXWAREV>=70103 */
+_PROTOTYPE(static int examine_stream,(KA_T vs, struct queue *q, char **mch,
+ char **mn, char *sn, KA_T *sqp));
+_PROTOTYPE(static struct l_dev * findspdev,(dev_t *dev, dev_t *rdev));
+_PROTOTYPE(static void getspdev,(void));
+_PROTOTYPE(static int get_vty,(struct vnode *v, KA_T va, struct vfs *kv,
+ int *fx));
+_PROTOTYPE(static struct l_dev * ismouse,(struct vnode *va, struct l_ino *i,
+ int fx, struct vfs *kv));
+#endif /* UNIXWAREV<70103 */
+
+_PROTOTYPE(static struct l_dev * findstrdev,(dev_t *dev, dev_t *rdev));
+_PROTOTYPE(static char isvlocked,(struct vnode *va));
+_PROTOTYPE(static int readlino,(int fx, struct vnode *v, struct l_ino *i));
+
+
+/*
+ * Local variables and definitions
+ */
+
+static struct protos {
+ char *module; /* stream module name */
+ char *proto; /* TCP/IP protocol name */
+} Protos[] = {
+ { "tcpu", "TCP" },
+ { "udpu", "UDP" },
+ { "tcpl", "TCP" },
+ { "tcp", "TCP" },
+ { "udpl", "UDP" },
+ { "udp", "UDP" },
+
+#if UNIXWAREV<70103
+ { "icmp", "ICMP" },
+ { "ipu", "IP" },
+ { "ipl", "IP" },
+ { "ip", "IP" },
+#endif /* UNIXWAREV<70103 */
+
+};
+#define NPROTOS (sizeof(Protos)/sizeof(struct protos))
+
+#if UNIXWAREV>=70103
+static struct specdev {
+ char *name;
+ struct l_dev *dp;
+} SpDev[] = {
+ { "/dev/log", (struct l_dev *)NULL },
+ { "/dev/mouse", (struct l_dev *)NULL },
+};
+#define SPDEV_CT (sizeof(SpDev) / sizeof(struct specdev))
+static int SpDevX = -1; /* SpDev[] maximum index */
+#endif /* UNIXWAREV>=70103 */
+
+
+/*
+ * ent_fa() - enter fattach addresses in NAME column addition
+ */
+
+static void
+ent_fa(a1, a2, d)
+ KA_T *a1; /* first fattach address (NULL OK) */
+ KA_T *a2; /* second fattach address */
+ char *d; /* direction ("->" or "<-") */
+{
+ char buf[64], *cp, tbuf[32];
+ MALLOC_S len;
+
+ if (Lf->nma)
+ return;
+ if (!a1)
+ (void) snpf(buf, sizeof(buf), "(FA:%s%s)", d,
+ print_kptr(*a2, (char *)NULL, 0));
+ else
+ (void) snpf(buf, sizeof(buf), " (FA:%s%s%s)",
+ print_kptr(*a1, tbuf, sizeof(tbuf)), d,
+ print_kptr(*a2, (char *)NULL, 0));
+ len = strlen(buf) + 1;
+ if ((cp = (char *)malloc(len)) == NULL) {
+ (void) fprintf(stderr,
+ "%s: no space for fattach addresses at PID %d, FD %s\n",
+ Pn, Lp->pid, Lf->fd);
+ Exit(1);
+ }
+ (void) snpf(cp, len, "%s", buf);
+ Lf->nma = cp;
+}
+
+
+/*
+ * examine_stream() - examine stream
+ */
+
+static int
+
+#if UNIXWAREV<70103
+examine_stream(vs, q, mn, sn, sqp)
+#else /* UNIXWAREV>=70103 */
+examine_stream(vs, q, mch, mn, sn, sqp)
+#endif /* UNIXWAREV<70103 */
+
+ KA_T vs; /* stream head's stdata kernel
+ * address */
+ struct queue *q; /* queue structure buffer */
+
+#if UNIXWAREV>=70103
+ char **mch; /* important stream module name chain,
+ * module names separated by "->" */
+ char **mn; /* pointer to module name receiver */
+#else /* UNIXWAREV<70103 */
+ char *mn; /* module name receiver */
+#endif /* UNIXWAREV>=70103 */
+
+ char *sn; /* special module name */
+ KA_T *sqp; /* special module's q_ptr */
+{
+ struct module_info mi;
+ KA_T qp;
+ struct qinit qi;
+ struct stdata sd;
+ char tbuf[32];
+
+#if UNIXWAREV>=70103
+ static char *ab = (char *)NULL;
+ static MALLOC_S aba = (size_t)0;
+ MALLOC_S al, len, naba, tlen;
+ char *ap;
+ char tmnb[STRNML+1];
+#endif /* UNIXWAREV>=70103 */
+
+/*
+ * Read stream's head.
+ */
+ if (!vs || readstdata(vs, &sd)) {
+ (void) snpf(Namech, Namechl, "can't read stream head from %s",
+ print_kptr(vs, (char *)NULL, 0));
+ enter_nm(Namech);
+ return(1);
+ }
+ if (!sd.sd_wrq) {
+ enter_nm("no stream write queue");
+ return(1);
+ }
+/*
+ * Examine the write queue.
+ */
+
+#if UNIXWAREV<70103
+ for (qp = (KA_T)sd.sd_wrq, *mn = '\0'; qp; qp = (KA_T)q->q_next)
+#else /* UNIXWAREV>=70103 */
+ for (qp = (KA_T)sd.sd_wrq, al = (MALLOC_S)0, ap = ab,
+ *mn = (char *)NULL, tmnb[sizeof(tmnb) - 1] = '\0';
+ qp;
+ qp = (KA_T)q->q_next)
+#endif /* UNIXWAREV<70103 */
+
+ {
+
+ /*
+ * Read stream queue entry.
+ */
+ if (kread(qp, (char *)q, sizeof(struct queue))) {
+ (void) snpf(Namech, Namechl, "can't read stream queue from %s",
+ print_kptr(qp, (char *)NULL, 0));
+ enter_nm(Namech);
+ return(1);
+ }
+ /*
+ * Read queue's information structure.
+ */
+ if (!q->q_qinfo || readstqinit((KA_T)q->q_qinfo, &qi)) {
+ (void) snpf(Namech, Namechl, "can't read qinit for %s from %s",
+ print_kptr(qp, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)q->q_qinfo, (char *)NULL, 0));
+ enter_nm(Namech);
+ return(1);
+ }
+ /*
+ * Read module information structure.
+ */
+ if (!qi.qi_minfo || readstmin((KA_T)qi.qi_minfo, &mi)) {
+ (void) snpf(Namech, Namechl,
+ "can't read module info for %s from %s",
+ print_kptr((KA_T)q->q_qinfo, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)qi.qi_minfo, (char *)NULL, 0));
+ enter_nm(Namech);
+ return(1);
+ }
+ /*
+ * Read module name.
+ */
+
+#if UNIXWAREV<70103
+ if (!mi.mi_idname || kread((KA_T)mi.mi_idname, mn, STRNML-1))
+#else /* UNIXWAREV>=70103 */
+ if (!mi.mi_idname || kread((KA_T)mi.mi_idname, tmnb, STRNML))
+#endif /* UNIXWAREV<70103 */
+
+ {
+ (void) snpf(Namech, Namechl,
+ "can't read module name for %s from %s",
+ print_kptr((KA_T)qi.qi_minfo, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)mi.mi_idname, (char *)NULL, 0));
+ enter_nm(Namech);
+ return(1);
+ }
+
+#if UNIXWAREV<70103
+ *(mn + STRNML - 1) = '\0';
+#endif /* UNIXWAREV<70103 */
+
+ /*
+ * Save the q_ptr of the first special module.
+ */
+
+#if UNIXWAREV<70103
+ if (!sn || *sqp || !q->q_ptr)
+ continue;
+ if (strcmp(mn, sn) == 0)
+ *sqp = (KA_T)q->q_ptr;
+#else /* UNIXWAREV>=70103 */
+ if (sn && !*sqp && q->q_ptr) {
+ if (strcmp(tmnb, sn) == 0)
+ *sqp = (KA_T)q->q_ptr;
+ }
+ /*
+ * Assemble the module name chain. Allocate space as required.
+ * Skip null module names and some "uninteresting" ones.
+ */
+ len = strlen(tmnb);
+ if (len
+ && strcmp(tmnb, "strrhead")
+ && strcmp(tmnb, "strwhead")
+ ) {
+ tlen = len + 1 + (al ? 2 : 0);
+ if ((tlen + al) > aba) {
+ aba = tlen + al + 64; /* allocate some extra */
+ if (!ab) {
+ ab = ap = (char *)malloc(aba);
+ } else {
+ ab = (char *)realloc((MALLOC_P *)ab, aba);
+ if (al)
+ ap = ab + (al - 1);
+ else
+ ap = ab;
+ }
+ if (!ab) {
+ (void) fprintf(stderr,
+ "%s: no space for stream chain", Pn);
+ Exit(1);
+ }
+ }
+ (void) snpf(ap, aba - (al - 1), "%s%s",
+ (ap == ab) ? "" : "->", tmnb);
+ *mn = ap + ((ap == ab) ? 0 : 2);
+ al += tlen;
+ ap += (tlen - 1);
+ }
+#endif /* UNIXWAREV<70103 */
+
+ }
+
+#if UNIXWAREV>=70103
+ *mch = ab;
+ if (!*mn)
+ *mn = "";
+#endif /* UNIXWAREV>=70103 */
+
+ return(0);
+}
+
+
+#if UNIXWAREV>=70103
+/*
+ * findspdev() - find special device by raw major device number
+ */
+
+static struct l_dev *
+findspdev(dev, rdev)
+ dev_t *dev; /* containing device */
+ dev_t *rdev; /* raw device */
+{
+ int i;
+ struct l_dev *dp;
+
+ if (*dev != DevDev)
+ return((struct l_dev *)NULL);
+ if (SpDevX < 0)
+ (void) getspdev();
+ for (i = 0; i < SpDevX; i++) {
+ if (!(dp = SpDev[i].dp))
+ continue;
+ if (GET_MAJ_DEV(*rdev) == GET_MAJ_DEV(dp->rdev))
+ return(dp);
+ }
+ return((struct l_dev *)NULL);
+}
+#endif /* UNIXWAREV>=70103 */
+
+
+/*
+ * findstrdev() - look up stream device by device number
+ */
+
+static struct l_dev *
+findstrdev(dev, rdev)
+ dev_t *dev; /* device */
+ dev_t *rdev; /* raw device */
+{
+ struct clone *c;
+ struct l_dev *dp;
+/*
+ * Search device table for match.
+ */
+
+#if HASDCACHE
+
+findstrdev_again:
+
+#endif /* HASDCACHE */
+
+ if ((dp = lkupdev(dev, rdev, 0, 0)))
+ return(dp);
+/*
+ * Search for clone.
+ */
+ if (Clone) {
+ for (c = Clone; c; c = c->next) {
+ if (GET_MAJ_DEV(*rdev) == GET_MIN_DEV(Devtp[c->dx].rdev)) {
+
+#if HASDCACHE
+ if (DCunsafe && !Devtp[c->dx].v && !vfy_dev(&Devtp[c->dx]))
+ goto findstrdev_again;
+#endif /* HASDCACHE */
+
+ return(&Devtp[c->dx]);
+ }
+ }
+ }
+
+#if UNIXWAREV<70103
+ return((struct l_dev *)NULL);
+#else /* UNIXWAREV>=70103 */
+/*
+ * Search for non-clone clone.
+ */
+ return(findspdev(dev, rdev));
+#endif /* UNIXWAREV<70103 */
+
+}
+
+
+#if UNIXWAREV>=70103
+/*
+ * getspecdev() -- get Devtp[] pointers for "special" devices
+ */
+
+static void
+getspdev()
+{
+ struct l_dev *dp;
+ int i, j, n;
+
+ if (SpDevX >= 0)
+ return;
+/*
+ * Scan Devtp[] for the devices named in SpDev[].
+ */
+ for (i = n = 0; (i < Ndev) && (n < SPDEV_CT); i++) {
+ dp = Sdev[i];
+ for (j = 0; j < SPDEV_CT; j++) {
+ if (SpDev[j].dp)
+ continue;
+ if (strcmp(SpDev[j].name, dp->name) == 0) {
+ SpDev[j].dp = dp;
+ n++;
+ SpDevX = j + 1;
+ break;
+ }
+ }
+ }
+ if (SpDevX < 0)
+ SpDevX = 0;
+}
+#endif /* UNIXWAREV>=70103 */
+
+
+/*
+ * get_vty() - get vnode type
+ *
+ * return: vnode type as an N_* symbol value
+ * N_REGLR if no special file system type applies
+ * -1 if the vnode type is VUNNAMED
+ * -2 if the vfs structure has an illegal type index
+ * -3 if the vfs structure can't be read
+ */
+
+static int
+get_vty(v, va, kv, fx)
+ struct vnode *v; /* vnode to test */
+ KA_T va; /* vnode's kernel address */
+ struct vfs *kv; /* copy of vnode's kernel vfs struct */
+ int *fx; /* file system type index */
+{
+ int fxt;
+ int nty = N_REGLR;
+ char tbuf[32];
+
+ if (v->v_type == VUNNAMED) {
+ *fx = 0;
+ return(-1);
+ }
+ if (!v->v_vfsp) {
+ *fx = 0;
+ if ((v->v_type == VFIFO) || v->v_stream)
+ return(N_STREAM);
+ return(N_REGLR);
+ }
+ if (!kread((KA_T)v->v_vfsp, (char *)kv, sizeof(struct vfs))) {
+
+ /*
+ * Check the file system type.
+ */
+ fxt = kv->vfs_fstype;
+ if (fxt > 0 && fxt <= Fsinfomax) {
+ if (!strcmp(Fsinfo[fxt-1], "fifofs"))
+ nty = N_FIFO;
+ else if (!strcmp(Fsinfo[fxt-1], "nfs"))
+ nty = N_NFS;
+ else if (!strcmp(Fsinfo[fxt-1], "namefs"))
+ nty = N_NM;
+ else if (!strcmp(Fsinfo[fxt-1], "nsc_cfs"))
+ nty = N_CFS;
+
+
+#if defined(HASPROCFS)
+ else if (!strcmp(Fsinfo[fxt-1], "proc"))
+ nty = N_PROC;
+#endif /* defined(HASPROCFS) */
+
+ } else {
+ (void) snpf(Namech, Namechl,
+ "vnode@%s: bad file system index (%d)",
+ print_kptr(va, (char *)NULL, 0), fxt);
+ enter_nm(Namech);
+ return(-2);
+ }
+ } else {
+ (void) snpf(Namech, Namechl, "vnode@%s: bad vfs pointer (%s)",
+ print_kptr(va, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)v->v_vfsp, (char *)NULL, 0));
+ enter_nm(Namech);
+ return(-3);
+ }
+ if (nty == N_REGLR) {
+ if (v->v_type == VFIFO)
+ nty = N_FIFO;
+ else if (v->v_stream)
+ nty = N_STREAM;
+ }
+ *fx = fxt;
+ return(nty);
+}
+
+
+#if UNIXWAREV>=70103
+/*
+ * ismouse() - is vnode attached to /dev/mouse
+ */
+
+static struct l_dev *
+ismouse(va, i, fx, kv)
+ struct vnode *va; /* local vnode address */
+ struct l_ino *i; /* local inode structure */
+ int fx; /* file system index */
+ struct vfs *kv; /* copy of kernel VFS structure */
+{
+ struct l_dev *dp;
+ int j;
+
+ if ((fx < 1) || (fx > Fsinfomax))
+ return((struct l_dev *)NULL);
+ if ((dp = findspdev(&kv->vfs_dev, &va->v_rdev))) {
+ i->dev = kv->vfs_dev;
+ i->dev_def = 1;
+ i->nlink = (long)0;
+ i->nlink_def = 0;
+ i->nm = (char *)NULL;
+ i->number = dp->inode;
+ i->number_def = 1;
+ i->rdev = va->v_rdev;
+ i->rdev_def = 0;
+ i->size = (SZOFFTYPE)0;
+ i->size_def = 0;
+ Ntype = N_REGLR;
+ }
+ return(dp);
+}
+#endif /* UNIXWAREV>=70103 */
+
+
+/*
+ * isvlocked() - is a vnode locked
+ */
+
+static char
+isvlocked(va)
+ struct vnode *va; /* local vnode address */
+{
+ struct filock f;
+ KA_T flf, flp;
+ int i, l;
+
+ if (!(flf = (KA_T)va->v_filocks))
+ return(' ');
+ flp = flf;
+ i = 0;
+ do {
+ if (i++ > 1000)
+ break;
+ if (kread(flp, (char *)&f, sizeof(f)))
+ break;
+ if (f.set.l_sysid || f.set.l_pid != (pid_t)Lp->pid)
+ continue;
+ if (!f.set.l_whence && !f.set.l_start
+
+#if UNIXWAREV>=70101
+# if UNIXWAREV<70103
+ && (f.set.l_len == 0x7fffffffffffffff)
+# else /* UNIXWAREV>=70103 */
+ && (f.set.l_len == 0x7fffffffffffffffLL)
+# endif /* UNIXWAREV<70103 */
+#else /* UNIXWAREV<70101 */
+ && ((f.set.l_len == 0) || (f.set.l_len == 0x7fffffff))
+#endif /* UNIXWAREV>=70101*/
+
+ )
+ l = 1;
+ else
+ l = 0;
+ switch (f.set.l_type & (F_RDLCK | F_WRLCK)) {
+ case F_RDLCK:
+ return((l) ? 'R' : 'r');
+ case F_WRLCK:
+ return((l) ? 'W' : 'w');
+ case (F_RDLCK + F_WRLCK):
+ return('u');
+ default:
+ return(' ');
+ }
+ } while (flp != (KA_T)f.next && (flp = (KA_T)f.next) && flp != flf);
+ return(' ');
+}
+
+
+/*
+ * process_node() - process node
+ */
+
+void
+process_node(na)
+ KA_T na; /* vnode kernel space address */
+{
+ char *cp, *ep;
+ dev_t dev, rdev;
+ unsigned char devs = 0;
+ unsigned char rdevs = 0;
+ unsigned char ni = 0;
+ struct l_dev *dp;
+ struct fifonode f;
+ int fx, rfx;
+ struct l_ino i;
+ int is = 1;
+ int j, k;
+ KA_T ka;
+ struct vfs kv, rkv;
+
+#if UNIXWAREV<70103
+ struct module_info mi;
+ char mn[STRNML];
+#else /* UNIXWAREV>=70103 */
+ char *mch, *mn;
+#endif /* UNIXWAREV<70103 */
+
+ struct mnode mno;
+ MALLOC_S msz;
+ struct namenode nn;
+ int px;
+ struct queue q;
+ struct rnode r;
+ struct vnode rv, v;
+ struct snode s;
+ unsigned char sd = 1;
+ struct so_so so;
+ KA_T sqp = (KA_T)NULL;
+ size_t sz;
+ char tbuf[32], *ty;
+ enum vtype type;
+ struct sockaddr_un ua;
+
+#if defined(HASPROCFS)
+ struct as as;
+ struct proc p;
+ KA_T pa;
+ struct procfsid *pfi;
+ long pid;
+ struct prnode pr;
+# if UNIXWAREV<20102
+ struct pid pids;
+# else /* UNIXWAREV>=20102 */
+ struct prcommon prc;
+# endif /* UNIXWAREV>=20102 */
+#endif /* defined(HASPROCFS) */
+
+/*
+ * Read the vnode.
+ */
+ if (!na) {
+ enter_nm("no vnode address");
+ return;
+ }
+ if (readvnode((KA_T)na, &v)) {
+ enter_nm(Namech);
+ return;
+ }
+
+#if defined(HASNCACHE)
+ Lf->na = na;
+#endif /* defined(HASNCACHE) */
+
+#if defined(HASFSTRUCT)
+ Lf->fna = na;
+ Lf->fsv |= FSV_NI;
+#endif /* defined(HASFSTRUCT) */
+
+/*
+ * Determine the vnode type.
+ */
+ if ((Ntype = get_vty(&v, na, &kv, &fx)) < 0) {
+ if (Ntype == -1)
+ Lf->sf = 0;
+ return;
+ }
+/*
+ * Determine the lock state.
+ */
+
+get_lock_state:
+
+ Lf->lock = isvlocked(&v);
+/*
+ * Read the fifonode, inode, namenode, prnode, rnode, snode, ...
+ */
+ switch (Ntype) {
+ case N_FIFO:
+ if (!v.v_data || readfifonode((KA_T)v.v_data, &f)) {
+ (void) snpf(Namech, Namechl,
+ "vnode@%s: can't read fifonode (%s)",
+ print_kptr(na, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)v.v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ if (f.fn_realvp) {
+ if (readvnode((KA_T)f.fn_realvp, &rv)) {
+ (void) snpf(Namech, Namechl,
+ "fifonode@%s: can't read real vnode (%s)",
+ print_kptr((KA_T)v.v_data, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)f.fn_realvp, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+
+#if defined(HASNCACHE)
+ Lf->na = (KA_T)f.fn_realvp;
+#endif /* defined(HASNCACHE) */
+
+ if (!rv.v_data || (is = readlino(fx, &rv, &i))) {
+ (void) snpf(Namech, Namechl,
+ "fifonode@%s: can't read inode (%s)",
+ print_kptr((KA_T)v.v_data, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)rv.v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ } else
+ ni = 1;
+ break;
+ case N_NFS:
+ if (!v.v_data || readrnode((KA_T)v.v_data, &r)) {
+ (void) snpf(Namech, Namechl, "vnode@%s: can't read rnode (%s)",
+ print_kptr(na, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)v.v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ break;
+ case N_NM:
+ if (!v.v_data || kread((KA_T)v.v_data, (char *)&nn, sizeof(nn))) {
+ (void) snpf(Namech, Namechl, "vnode@%s: no namenode (%s)",
+ print_kptr(na, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)v.v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ i.dev = nn.nm_vattr.va_fsid;
+ i.rdev = nn.nm_vattr.va_rdev;
+ i.number = (INODETYPE)nn.nm_vattr.va_nodeid;
+ i.size = nn.nm_vattr.va_size;
+ if (!nn.nm_mountpt)
+ break;
+ /*
+ * The name node is mounted over/to another vnode. Process that node.
+ */
+ (void) ent_fa(&na, (KA_T *)&nn.nm_mountpt, "->");
+ if (kread((KA_T)nn.nm_mountpt, (char *)&rv, sizeof(rv))) {
+ (void) snpf(Namech, Namechl,
+ "vnode@%s: can't read namenode's mounted vnode (%s)",
+ print_kptr(na, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)nn.nm_mountpt, (char *)NULL, 0));
+ return;
+ }
+ if ((Ntype = get_vty(&rv, (KA_T)nn.nm_mountpt, &rkv, &rfx)) < 0) {
+ if (Ntype == -1)
+ Lf->sf = 0;
+ return;
+ }
+ /*
+ * Unless the mounted-over/to node is another "namefs" node, promote
+ * it to the vnode of interest.
+ */
+ if (Ntype == N_NM)
+ break;
+ fx = rfx;
+ kv = rkv;
+ v = rv;
+ goto get_lock_state;
+
+#if defined(HASPROCFS)
+ case N_PROC:
+ ni = 1;
+ if (!v.v_data || kread((KA_T)v.v_data, (char *)&pr, sizeof(pr))) {
+ (void) snpf(Namech, Namechl, "vnode@%s: can't read prnode (%s)",
+ print_kptr(na, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)v.v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+
+# if UNIXWAREV>=20102
+ i.number = (INODETYPE)pr.pr_ino;
+ sd = 0;
+ if (pr.pr_common
+ && !kread((KA_T)pr.pr_common, (char *)&prc, sizeof(prc))) {
+ pid = (long)prc.prc_pid;
+ switch(pr.pr_type) {
+ case PR_PIDDIR:
+ (void) snpf(Namech, Namechl, "/%s/%ld", HASPROCFS, pid);
+ break;
+ case PR_AS:
+ (void) snpf(Namech, Namechl, "/%s/%ld/as", HASPROCFS, pid);
+ break;
+ case PR_CTL:
+ (void) snpf(Namech, Namechl, "/%s/%ld/ctl", HASPROCFS, pid);
+ break;
+ case PR_STATUS:
+ (void) snpf(Namech, Namechl, "/%s/%ld/status", HASPROCFS,
+ pid);
+ break;
+ case PR_MAP:
+ (void) snpf(Namech, Namechl, "/%s/%ld/map", HASPROCFS, pid);
+ break;
+ case PR_CRED:
+ (void) snpf(Namech, Namechl, "/%s/%ld/cred", HASPROCFS, pid);
+ break;
+ case PR_SIGACT:
+ (void) snpf(Namech, Namechl, "/%s/%ld/sigact", HASPROCFS,
+ pid);
+ break;
+ case PR_OBJECTDIR:
+ (void) snpf(Namech, Namechl, "/%s/%ld/object", HASPROCFS,
+ pid);
+ break;
+ case PR_LWPDIR:
+ (void) snpf(Namech, Namechl, "/%s/%ld/lwp", HASPROCFS, pid);
+ break;
+ case PR_LWPIDDIR:
+ (void) snpf(Namech, Namechl, "/%s/%ld/lwp/%d",
+ HASPROCFS, pid, prc.prc_lwpid);
+ break;
+ case PR_LWPCTL:
+ (void) snpf(Namech, Namechl, "/%s/%ld/lwp/%d/lwpctl",
+ HASPROCFS, pid, prc.prc_lwpid);
+ break;
+ case PR_LWPSTATUS:
+ (void) snpf(Namech, Namechl, "/%s/%ld/lwp/%d/lwpstatus",
+ HASPROCFS, pid, prc.prc_lwpid);
+ break;
+ case PR_LWPSINFO:
+ (void) snpf(Namech, Namechl, "/%s/%ld/lwp/%d/lwpsinfo",
+ HASPROCFS, pid, prc.prc_lwpid);
+ break;
+ }
+ } else
+ pid = 0l;
+ break;
+# else /* UNIXWAREV<20102 */
+ if (!pr.pr_proc) {
+ sd = 0;
+ pid = 0l;
+ if (v.v_type == VDIR)
+ i.number = (INODETYPE)PR_ROOTINO;
+ else
+ i.number = (INODETYPE)0;
+ break;
+ }
+ if (kread((KA_T)pr.pr_proc, (char *)&p, sizeof(p))) {
+ (void) snpf(Namech, Namechl, "prnode@%s: can't read proc (%s)",
+ print_kptr((KA_T)v.v_data, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)pr.pr_proc, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ if (!p.p_pidp || kread((KA_T)p.p_pidp, (char *)&pids, sizeof(pids)))
+ {
+ (void) snpf(Namech, Namechl,
+ "proc struct at %s: can't read pid (%s)",
+ print_kptr((KA_T)pr.pr_proc, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)p.p_pidp, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ pid = (long)pids.pid_id;
+ (void) snpf(Namech, Namechl, "/%s/%ld", HASPROCFS, pid);
+ i.number = (INODETYPE)(pid + PR_INOBIAS);
+ if (!p.p_as || kread((KA_T)p.p_as, (char *)&as, sizeof(as)))
+ sd = 0;
+ else
+ i.size = as.a_size;
+ break;
+# endif /* UNIXWAREV>=20102 */
+#endif /* defined(HASPROCFS) */
+
+ case N_STREAM:
+ if (v.v_stream) {
+ Lf->is_stream = ni = 1;
+
+#if UNIXWAREV>=70101
+ if (process_unix_sockstr(&v, na)) {
+
+ /*
+ * The stream is a UNIX socket stream. No more need be done;
+ * process_unix_stream() has done it all.
+ */
+ return;
+ }
+#endif /* UNIXWAREV>=70101 */
+
+ /*
+ * Get the queue pointer and module name at the end of the stream.
+ * The module name identifies socket streams.
+ */
+ if (examine_stream((KA_T)v.v_stream, &q,
+
+#if UNIXWAREV>=70103
+ &mch, &mn,
+#else /* UNIXWAREV<70103 */
+ mn,
+#endif /* UNIXWAREV>=70103 */
+
+ "sockmod", &sqp))
+ return;
+ for (px = 0; px < NPROTOS; px++) {
+ if (strcmp(mn, Protos[px].module) == 0) {
+ process_socket(Protos[px].proto, &q);
+ return;
+ }
+ }
+ /*
+ * If this stream has a "sockmod" module with a non-NULL q_ptr,
+ * try to use it to read an so_so structure.
+ */
+ if (sqp && kread(sqp, (char *)&so, sizeof(so)) == 0)
+ break;
+ sqp = (KA_T)NULL;
+ (void) snpf(Namech, Namechl, "STR");
+ j = strlen(Namech);
+ if (v.v_type == VCHR) {
+ /*
+ * If this is a VCHR stream, look up the device name and record it.
+ */
+ if ((dp = findstrdev(&DevDev, (dev_t *)&v.v_rdev))) {
+ Lf->inode = dp->inode;
+ Lf->inp_ty = 1;
+ Namech[j++] = ':';
+ k = strlen(dp->name);
+ if ((j + k) <= (Namechl - 1)) {
+ (void) snpf(&Namech[j], Namechl - j, "%s",
+ dp->name);
+ j += k;
+ if ((cp = strrchr(Namech, '/'))
+ && *(cp + 1) == '\0')
+ {
+ *cp = '\0';
+ j--;
+ }
+ }
+ }
+ }
+ /*
+ * Follow the "STR" and possibly the device name with "->" and
+ * the module name or the stream's significant module names.
+ */
+ if ((j + 2) <= (Namechl - 1)) {
+ (void) snpf(&Namech[j], Namechl - j, "->");
+ j += 2;
+ }
+
+#if UNIXWAREV<70103
+ if (mn[0]) {
+ if ((j + strlen(mn)) <= (Namechl - 1))
+ (void) snpf(&Namech[j], Namechl - j, mn);
+#else /* UNIXWAREV>=70103 */
+ if (*mch) {
+ if ((j + strlen(mch)) <= (Namechl - 1))
+ (void) snpf(&Namech[j], Namechl - j, mch);
+#endif /* UNIXWAREV<70103 */
+
+ } else {
+ if ((j + strlen("none")) <= (Namechl - 1))
+ (void) snpf(&Namech[j], Namechl - j, "none");
+ }
+ }
+ break;
+ case N_REGLR:
+ default:
+
+ /*
+ * Follow a VBLK or VCHR vnode to its snode, then to its real vnode,
+ * finally to its inode.
+ */
+ if ((v.v_type == VBLK) || (v.v_type == VCHR)) {
+ if (!v.v_data || readsnode((KA_T)v.v_data, &s)) {
+ (void) snpf(Namech, Namechl,
+ "vnode@%s: can't read snode (%s)",
+ print_kptr(na, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)v.v_data, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ if (s.s_realvp) {
+ if (readvnode((KA_T)s.s_realvp, &rv)) {
+ (void) snpf(Namech, Namechl,
+ "snode@%s: can't read real vnode (%s)",
+ print_kptr((KA_T)v.v_data, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)s.s_realvp, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ if (!rv.v_data || (is = readlino(fx, &rv, &i))) {
+ (void) snpf(Namech, Namechl,
+ "snode@%s: unknown inode@%s; fx=",
+ print_kptr((KA_T)v.v_data, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)rv.v_data, (char *)NULL, 0));
+ ep = endnm(&sz);
+ if (fx < 1 || fx > Fsinfomax)
+ (void) snpf(ep, sz, "%d", fx);
+ else
+ (void) snpf(ep, sz, "%s", Fsinfo[fx - 1]);
+ enter_nm(Namech);
+ return;
+ }
+ }
+ /*
+ * If there's no real vnode, look for a common vnode and a
+ * common snode.
+ */
+ else if ((ka = (KA_T)s.s_commonvp)) {
+ if (readvnode(ka, &rv)) {
+ (void) snpf(Namech, Namechl,
+ "snode@%s: can't read common vnode (%s)",
+ print_kptr((KA_T)v.v_data, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)ka, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+
+#if UNIXWAREV>=70103
+ if (!rv.v_vfsp) {
+ if ((dp = ismouse(&rv, &i, fx, &kv))) {
+ (void) snpf(Namech, Namechl, "STR:%s", dp->name);
+ break;
+ }
+ }
+#endif /* UNIXWAREV>=70103 */
+
+ if (get_vty(&rv, ka, &rkv, &rfx) < 0)
+ Lf->is_com = ni = 1;
+ else {
+ if ((is = readlino(rfx, &rv, &i))) {
+ (void) snpf(Namech, Namechl,
+ "vnode@%s: unknown successor@%s; fx=",
+ print_kptr((KA_T)ka, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)v.v_data, (char *)NULL, 0));
+ ep = endnm(&sz);
+ if (rfx < 1 || rfx > Fsinfomax)
+ (void) snpf(ep, sz, "%d", rfx);
+ else
+ (void) snpf(ep, sz, "%s", Fsinfo[rfx - 1]);
+ enter_nm(Namech);
+ return;
+ }
+ }
+ } else
+ ni = 1;
+ break;
+ }
+
+#if UNIXWAREV>=70103
+ else if (v.v_type == VNON) {
+ ni = 1;
+ break;
+ }
+#endif /* UNIXWAREV>=70103 */
+
+ if (v.v_data == NULL) {
+ (void) snpf(Namech, Namechl, "vnode@%s: no further information",
+ print_kptr(na, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ /*
+ * Read inode information.
+ */
+ if ((is = readlino(fx, &v, &i))) {
+ (void) snpf(Namech, Namechl,
+ "vnode@%s: unknown successor@%s; fx=",
+ print_kptr(na, tbuf, sizeof(tbuf)),
+ print_kptr((KA_T)v.v_data, (char *)NULL, 0));
+ ep = endnm(&sz);
+ if (fx < 1 || fx > Fsinfomax)
+ (void) snpf(ep, sz, "%d", fx);
+ else
+ (void) snpf(ep, sz, "%s", Fsinfo[fx - 1]);
+ enter_nm(Namech);
+ return;
+ }
+ }
+/*
+ * Get device and type for printing.
+ */
+ switch (Ntype) {
+ case N_NFS:
+ dev = r.r_attr.va_fsid;
+ devs = 1;
+ break;
+
+#if defined(HASPROCFS)
+ case N_PROC:
+ dev = kv.vfs_dev;
+ devs = 1;
+ break;
+#endif /* defined(HASPROCFS) */
+
+ case N_STREAM:
+ if (sqp) {
+ if (so.lux_dev.size >= 8) {
+ dev = DevDev;
+ rdev = so.lux_dev.addr.tu_addr.dev;
+ devs = rdevs = 1;
+ } else
+ enter_dev_ch(print_kptr(sqp, (char *)NULL, 0));
+ break;
+ }
+ if (v.v_type == VFIFO) {
+ KA_T ta;
+
+ if ((ta = (KA_T)(v.v_data ? v.v_data : v.v_stream)))
+ enter_dev_ch(print_kptr(ta, (char *)NULL, 0));
+ break;
+ }
+ /* fall through */
+ default:
+ if (!ni) {
+ dev = i.dev;
+ devs = (Ntype == N_CFS) ? i.dev_def : 1;
+ } else if ((Ntype == N_STREAM)
+ && ((v.v_type == VCHR) || (v.v_type == VBLK)))
+ {
+ dev = DevDev;
+ devs = 1;
+ }
+ if ((v.v_type == VCHR) || (v.v_type == VBLK)) {
+ rdev = v.v_rdev;
+ rdevs = (Ntype == N_CFS) ? i.rdev_def : 1;
+ }
+ }
+ type = v.v_type;
+/*
+ * Obtain the inode number.
+ */
+ switch (Ntype) {
+
+ case N_NFS:
+ Lf->inode = (INODETYPE)r.r_attr.va_nodeid;
+ Lf->inp_ty = 1;
+ break;
+
+#if defined(HASPROCFS)
+ case N_PROC:
+ Lf->inode = i.number;
+ Lf->inp_ty = 1;
+ break;
+#endif /* defined(HASPROCFS) */
+
+ case N_FIFO:
+ if (!f.fn_realvp) {
+ enter_dev_ch(print_kptr((KA_T)v.v_data, (char *)NULL, 0));
+ Lf->inode = (INODETYPE)f.fn_ino;
+ Lf->inp_ty = 1;
+ if (f.fn_flag & ISPIPE)
+ (void) snpf(Namech, Namechl, "PIPE");
+ if (f.fn_mate) {
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "->%s",
+ print_kptr((KA_T)f.fn_mate, (char *)NULL, 0));
+ }
+ break;
+ }
+ /* fall through */
+ case N_CFS:
+ case N_REGLR:
+ if (!ni) {
+ Lf->inode = i.number;
+ Lf->inp_ty = (Ntype == N_CFS) ? i.number_def : 1;
+ }
+ break;
+ case N_STREAM:
+ if (sqp && so.lux_dev.size >= 8) {
+ Lf->inode = (INODETYPE)so.lux_dev.addr.tu_addr.ino;
+ Lf->inp_ty = 1;
+ }
+ }
+/*
+ * Obtain the file size.
+ */
+ if (Foffset)
+ Lf->off_def = 1;
+ else {
+ switch (Ntype) {
+
+ case N_FIFO:
+ case N_STREAM:
+ if (!Fsize)
+ Lf->off_def = 1;
+ break;
+ case N_NFS:
+ Lf->sz = (SZOFFTYPE)r.r_attr.va_size;
+ Lf->sz_def = sd;
+ break;
+
+#if defined(HASPROCFS)
+ case N_PROC:
+
+#if UNIXWAREV<70103
+ Lf->sz = (SZOFFTYPE)i.size;
+ Lf->sz_def = sd;
+#else /* UNIXWAREV>=70103 */
+ Lf->sz = (SZOFFTYPE)0;
+ Lf->sz_def = 0;
+#endif /* UNIXWAREV<70103 */
+
+ break;
+#endif /* defined(HASPROCFS) */
+
+ case N_CFS:
+ case N_REGLR:
+ if ((type == VREG) || (type == VDIR)) {
+ if (!ni) {
+ Lf->sz = (SZOFFTYPE)i.size;
+ Lf->sz_def = (Ntype == N_CFS) ? i.size_def : sd;
+ }
+ } else if (((type == VBLK) || (type == VCHR)) && !Fsize)
+ Lf->off_def = 1;
+ break;
+ }
+ }
+/*
+ * Record link count.
+ */
+ if (Fnlink) {
+ switch(Ntype) {
+ case N_FIFO:
+ Lf->nlink = (long)f.fn_open;
+ Lf->nlink_def = 1;
+ break;
+ case N_NFS:
+ Lf->nlink = (long)r.r_attr.va_nlink;
+ Lf->nlink_def = 1;
+ break;
+
+#if defined(HASPROCFS)
+ case N_PROC:
+#endif /* defined(HASPROCFS) */
+
+ case N_CFS:
+ case N_REGLR:
+ if (!ni) {
+ Lf->nlink = (long)i.nlink;
+ Lf->nlink_def = i.nlink_def;
+ }
+ break;
+ }
+ if (Nlink && Lf->nlink_def && (Lf->nlink < Nlink))
+ Lf->sf |= SELNLINK;
+ }
+/*
+ * Record an NFS file selection.
+ */
+ if (Ntype == N_NFS && Fnfs)
+ Lf->sf |= SELNFS;
+/*
+ * Defer file system info lookup until printname().
+ */
+ Lf->lmi_srch = 1;
+/*
+ * Save the device numbers and their states.
+ *
+ * Format the vnode type, and possibly the device name.
+ */
+ if (type != VFIFO) {
+ Lf->dev = dev;
+ Lf->dev_def = devs;
+ Lf->rdev = rdev;
+ Lf->rdev_def = rdevs;
+ }
+ switch (type) {
+ case VNON:
+ ty ="VNON";
+ break;
+ case VREG:
+ ty = "VREG";
+ break;
+ case VDIR:
+ ty = "VDIR";
+ break;
+ case VBLK:
+ ty = "VBLK";
+ Ntype = N_BLK;
+ break;
+ case VCHR:
+ ty = "VCHR";
+ if (Lf->is_stream == 0)
+ Ntype = N_CHR;
+ break;
+ case VLNK:
+ ty = "VLNK";
+ break;
+
+#if defined(VSOCK)
+ case VSOCK:
+ ty = "SOCK";
+ break;
+#endif /* VSOCK */
+
+ case VBAD:
+ ty = "VBAD";
+ break;
+ case VFIFO:
+ if (!Lf->dev_ch || Lf->dev_ch[0] == '\0') {
+ Lf->dev = dev;
+ Lf->dev_def = devs;
+ Lf->rdev = rdev;
+ Lf->rdev_def = rdevs;
+ }
+ ty = "FIFO";
+ break;
+ case VUNNAMED:
+ ty = "UNNM";
+ break;
+ default:
+ (void) snpf(Lf->type, sizeof(Lf->type), "%04o", (type & 0xfff));
+ ty = NULL;
+ }
+ if (ty)
+ (void) snpf(Lf->type, sizeof(Lf->type), "%s", ty);
+ Lf->ntype = Ntype;
+/*
+ * If this is a VBLK file and it's missing an inode number, try to
+ * supply one.
+ */
+ if ((Lf->inp_ty == 0) && (Lf->ntype == N_BLK))
+ find_bl_ino();
+/*
+ * If this is a VCHR file and it's missing an inode number, try to
+ * supply one.
+ */
+ if ((Lf->inp_ty == 0) && (type == VCHR))
+ find_ch_ino();
+/*
+ * If this is a stream with a "sockmod" module whose q_ptr leads to an
+ * so_so structure, assume it's a UNIX domain socket and try to get
+ * the path. Clear the is_stream status.
+ */
+ if (Ntype == N_STREAM && sqp) {
+ if (Funix)
+ Lf->sf |= SELUNX;
+ (void) snpf(Lf->type, sizeof(Lf->type), "unix");
+ if (!Namech[0]
+ && so.laddr.buf && so.laddr.len == sizeof(ua)
+ && !kread((KA_T)so.laddr.buf, (char *)&ua, sizeof(ua))) {
+ ua.sun_path[sizeof(ua.sun_path) - 1] = '\0';
+ (void) snpf(Namech, Namechl, "%s", ua.sun_path);
+ if (Sfile && is_file_named(Namech, 0))
+ Lf->sf = SELNM;
+ if (so.lux_dev.size >= 8) {
+ Lf->inode = (INODETYPE)so.lux_dev.addr.tu_addr.ino;
+ Lf->inp_ty = 1;
+ }
+ }
+ if (so.so_conn) {
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "->%s",
+ print_kptr((KA_T)so.so_conn, (char *)NULL, 0));
+ }
+ Lf->is_stream = 0;
+ }
+/*
+ * Test for specified file.
+ */
+
+#if defined(HASPROCFS)
+ if (Ntype == N_PROC) {
+ if (Procsrch) {
+ Procfind = 1;
+ Lf->sf |= SELNM;
+ } else {
+ for (pfi = Procfsid; pfi; pfi = pfi->next) {
+
+ if ((pfi->pid && pid && pfi->pid == (pid_t)pid)
+
+# if defined(HASPINODEN)
+ || ((Lf->inp_ty == 1) && (Lf->inode == pfi->inode))
+# endif /* defined(HASPINODEN) */
+
+ ) {
+ pfi->f = 1;
+ Lf->sf |= SELNM;
+ if (!Namech[0] && pfi->nm) {
+ (void) strncpy(Namech, pfi->nm, Namechl - 1);
+ Namech[Namechl-1] = '\0';
+ }
+ break;
+ }
+ }
+ }
+ } else
+#endif /* defined(HASPROCFS) */
+
+ {
+ if (Sfile && is_file_named((char *)NULL,
+ ((type == VCHR) || (type == VBLK)) ? 1
+ : 0))
+ Lf->sf |= SELNM;
+ }
+/*
+ * Enter name characters. If there's an l_ino structure with a file name
+ * pointer, and no name column addition exists, make what the l_ino file
+ * name pointer addresses a name column addition.
+ */
+ if (!Lf->nma && !is && i.nm) {
+ if ((msz = (MALLOC_S)strlen(i.nm))) {
+ if (!(cp = (char *)malloc(msz + 1))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d bytes for l_ino name addition\n",
+ msz, Pn);
+ Exit(1);
+ }
+ (void) snpf(cp, msz + 1, "%s", i.nm);
+ Lf->nma = cp;
+ }
+ }
+ if (Namech[0])
+ enter_nm(Namech);
+}
+
+
+/*
+ * readlino() - read local inode information
+ */
+
+static int
+readlino(fx, v, i)
+ int fx; /* file system index */
+ struct vnode *v; /* vnode pointing to inode */
+ struct l_ino *i; /* local inode */
+{
+
+#if defined(HAS_UW_CFS)
+ cnode_t cn;
+#endif /* defined(HAS_UW_CFS) */
+
+ struct vnode fa;
+ struct mnode mn;
+ struct inode sn;
+
+#if defined(HASXNAMNODE)
+ struct xnamnode xn;
+#endif /* defined(HASXNAMNODE) */
+
+ i->nlink_def = 0;
+ if (fx < 1 || fx > Fsinfomax || !v->v_data)
+ return(1);
+ if (!strcmp(Fsinfo[fx-1], "fifofs")
+ || !strcmp(Fsinfo[fx-1], "sfs")
+ || !strcmp(Fsinfo[fx-1], "ufs")) {
+ if (kread((KA_T)v->v_data, (char *)&sn, sizeof(sn)))
+ return(1);
+ i->dev = sn.i_dev;
+ i->dev_def = 1;
+ i->rdev = v->v_rdev;
+ i->rdev_def = 1;
+ i->nlink = (long)sn.i_nlink;
+ i->nlink_def = 1;
+ i->nm = (char *)NULL;
+ i->number = (INODETYPE)sn.i_number;
+ i->size = (SZOFFTYPE)sn.i_size;
+ i->size_def = 1;
+ return(0);
+ }
+
+#if defined(HAS_UW_CFS)
+ else if (!strcmp(Fsinfo[fx-1], "nsc_cfs")) {
+ if (kread((KA_T)v->v_data, (char *)&cn, sizeof(cn)))
+ return(1);
+ if (cn.c_attr.va_mask & AT_FSID) {
+ i->dev = cn.c_attr.va_fsid;
+ i->dev_def = 1;
+ } else
+ i->dev_def = 0;
+ i->rdev = v->v_rdev;
+ i->rdev_def = 1;
+ if (cn.c_attr.va_mask & AT_NLINK) {
+ i->nlink = cn.c_attr.va_nlink;
+ i->nlink_def = 1;
+ } else
+ i->nlink_def = 0;
+ i->nm = (char *)NULL;
+ if (cn.c_attr.va_mask & AT_NODEID) {
+ i->number = (INODETYPE)cn.c_attr.va_nodeid;
+ i->number_def = 1;
+ } else
+ i->number_def = 0;
+ if (cn.c_attr.va_mask & AT_SIZE) {
+ i->size = cn.c_attr.va_size;
+ i->size_def = 1;
+ } else
+ i->size_def = 0;
+ return(0);
+ }
+#endif /* defined(HAS_UW_CFS) */
+
+ else if (!strcmp(Fsinfo[fx-1], "s5"))
+ return(reads5lino(v, i));
+ else if (!strcmp(Fsinfo[fx-1], "vxfs"))
+ return(readvxfslino(v, i));
+ else if (!strcmp(Fsinfo[fx-1], "bfs"))
+ return(readbfslino(v, i));
+
+#if defined(HASXNAMNODE)
+ else if (!strcmp(Fsinfo[fx-1], "xnamfs")
+ || !strcmp(Fsinfo[fx-1], "XENIX"))
+ {
+ if (kread((KA_T)v->v_data, (char *)&xn, sizeof(xn)))
+ return(1);
+ i->dev = xn.x_dev;
+ i->nlink = (long)xn.x_count;
+ i->nlink_def = 1;
+ i->nm = (char *)NULL;
+ i->rdev = xn.x_fsid;
+ i->size = xn.x_size;
+ return(0);
+ }
+#endif /* defined(HASXNAMNODE) */
+
+ else if (!strcmp(Fsinfo[fx-1], "memfs")) {
+ if (kread((KA_T)v->v_data, (char *)&mn, sizeof(mn)))
+ return(1);
+ i->dev = mn.mno_fsid;
+ i->dev_def = 1;
+ i->nlink = (long)mn.mno_nlink;
+ i->nlink_def = 1;
+ i->nm = (char *)NULL;
+ i->number = (INODETYPE)mn.mno_nodeid;
+ i->number_def = 1;
+ i->rdev = mn.mno_rdev;
+ i->rdev = mn.mno_rdev;
+ i->size = (SZOFFTYPE)mn.mno_size;
+ i->size_def = 1;
+ return(0);
+ }
+
+#if UNIXWAREV>=70000
+ else if (!strcmp(Fsinfo[fx-1], "cdfs"))
+ return readcdfslino(v, i);
+ else if (!strcmp(Fsinfo[fx-1], "dosfs"))
+ return readdosfslino(v, i);
+#endif /* UNIXWAREV>=70000 */
+
+ return(1);
+}
diff --git a/dialects/uw/dnode1.c b/dialects/uw/dnode1.c
new file mode 100644
index 0000000..e87597b
--- /dev/null
+++ b/dialects/uw/dnode1.c
@@ -0,0 +1,94 @@
+/*
+ * dnode1.c - SCO UnixWare node functions for lsof
+ *
+ * This module must be separate to keep separate the multiple kernel inode
+ * structure definitions.
+ */
+
+
+/*
+ * Copyright 1996 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 1996 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dnode1.c,v 1.6 2005/08/13 16:21:41 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+#if !defined(DYNAMIC_STACK_TRACE)
+#define DYNAMIC_STACK_TRACE /* suppress C's objection to a zero
+ * length st_buffer[] element in the
+ * stack_trace struct, defined in
+ * <sys/percpu.h> */
+
+#endif /* !defined(DYNAMIC_STACK_TRACE) */
+
+#undef IFMT
+#undef IFIFO
+#undef IFCHR
+#undef IFDIR
+#undef IFNAM
+#undef IFBLK
+#undef IFREG
+#undef IFLNK
+#undef ISUID
+#undef ISGID
+#undef ISVTX
+#undef IREAD
+#undef IWRITE
+#undef IEXEC
+#include <sys/fs/s5inode.h>
+
+
+/*
+ * reads5lino() - read s5 inode's local inode information
+ */
+
+int
+reads5lino(v, i)
+ struct vnode *v; /* containing vnode */
+ struct l_ino *i; /* local inode information */
+{
+ struct inode s5i;
+
+ if (kread((KA_T)v->v_data, (char *)&s5i, sizeof(s5i)))
+ return(1);
+ i->dev = s5i.i_dev;
+ i->dev_def = 1;
+ i->rdev = s5i.i_rdev;
+ i->rdev_def = 1;
+ i->nlink = (long)s5i.i_nlink;
+ i->nlink_def = 1;
+ i->nm = (char *)NULL;
+ i->number = (INODETYPE)s5i.i_number;
+ i->number_def = 1;
+ i->size = s5i.i_size;
+ i->size_def = 1;
+ return(0);
+}
diff --git a/dialects/uw/dnode2.c b/dialects/uw/dnode2.c
new file mode 100644
index 0000000..e7c24f7
--- /dev/null
+++ b/dialects/uw/dnode2.c
@@ -0,0 +1,114 @@
+/*
+ * dnode2.c - SCO UnixWare node functions for lsof
+ *
+ * This module must be separate to keep separate the multiple kernel inode
+ * structure definitions.
+ */
+
+/*
+ * Copyright 1996 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 1996 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dnode2.c,v 1.7 2005/08/13 16:21:41 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+#if defined(HASVXFS)
+
+# if UNIXWAREV<70000
+#undef fs_bsize
+#undef IFMT
+#undef IFIFO
+#undef IFCHR
+#undef IFDIR
+#undef IFNAM
+#undef IFBLK
+#undef IFREG
+#undef IFLNK
+#undef ISUID
+#undef ISGID
+#undef ISVTX
+#undef IREAD
+#undef IWRITE
+#undef IEXEC
+#include <sys/fs/vx_inode.h>
+# else /* UNIXWAREV>=70000 */
+struct vx_inode{
+ unsigned long d1[28];
+ dev_t i_dev;
+ unsigned long i_number;
+ unsigned long d2[76];
+ unsigned long i_nlink;
+ unsigned long d3[2];
+ unsigned long long i_size;
+ unsigned long d4[8];
+ dev_t i_rdev;
+};
+# endif /* UNIXWAREV<70000 */
+#endif /* defined(HASVXFS) */
+
+
+/*
+ * readvxfslino() - read vxfs inode's local inode information
+ */
+
+int
+readvxfslino(v, i)
+ struct vnode *v; /* containing vnode */
+ struct l_ino *i; /* local inode information */
+{
+
+#if defined(HASVXFS)
+ struct vx_inode vx;
+
+ if (kread((KA_T)v->v_data, (char *)&vx, sizeof(vx)))
+ return(1);
+ i->dev = vx.i_dev;
+ i->dev_def = 1;
+ i->nlink = (long)vx.i_nlink;
+ i->nlink_def = 1;
+ i->nm = (char *)NULL;
+ i->number = (INODETYPE)vx.i_number;
+ i->number_def = 1;
+ if (v->v_type == VCHR) {
+ i->rdev = vx.i_rdev;
+ i->rdev_def = 1;
+ } else {
+ i->rdev = (dev_t)0;
+ i->rdev_def = 0;
+ }
+ i->size = (SZOFFTYPE)vx.i_size;
+ i->size_def = 1;
+ return(0);
+#else /* !defined(HASVXFS) */
+ return(1);
+#endif /* defined(HASVXFS) */
+
+}
diff --git a/dialects/uw/dnode3.c b/dialects/uw/dnode3.c
new file mode 100644
index 0000000..8e5d979
--- /dev/null
+++ b/dialects/uw/dnode3.c
@@ -0,0 +1,271 @@
+/*
+ * dnode2.c - SCO UnixWare node functions for lsof
+ *
+ * This module must be separate to keep separate the multiple kernel inode
+ * structure definitions.
+ */
+
+/*
+ * Copyright 1998 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 1996 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dnode3.c,v 1.5 2005/08/13 16:21:41 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+#include <sys/fs/bfs.h>
+
+#if UNIXWAREV>=7000
+# if UNIXWAREV>=70103
+#undef IEXEC
+#undef IREAD
+#undef IWRITE
+# endif /* UNIXWAREV>=70103 */
+#undef ISUID
+#undef ISGID
+#undef ISVTX
+#include <sys/fs/cdfs_fs.h>
+#endif /* UNIXWAREV>=7000 */
+
+
+/*
+ * Local definitions
+ */
+
+#define DOS_NAME_PFX "(DOS name: "
+#define DOS_NAME_SFX ")"
+
+#if UNIXWAREV>=7000 && !defined(TYPELOGSECSHIFT)
+#define TYPELOGSECSHIFT uint_t /* just in case Configure missed it */
+#endif /* UNIXWAREV>=7000 && !defined(TYPELOGSECSHIFT) */
+
+
+/*
+ * Local static variables
+ */
+
+static unsigned char Dos2Unix[] = { /* derived from tounix[] in
+ * /etc/conf/pack.d/ccnv/space.c */
+ '_', '_', '_', '_', '_', '_', '_', '_', /* 0x01-0x08 */
+ '_', '_', '_', '_', '_', '_', '_', '_', /* 0x09-0x10 */
+ '_', '_', '_', '_', '_', '_', '_', '_', /* 0x11-0x18 */
+ '_', '_', '_', '_', '_', '_', '_', ' ', /* 0x19-0x20 */
+ '!', '"', '#', '$', '%', '&', '\'', '(', /* 0x21-0x28 */
+ ')', '*', '+', ',', '-', '.', '/', '0', /* 0x29-0x30 */
+ '1', '2', '3', '4', '5', '6', '7', '8', /* 0x31-0x38 */
+ '9', ':', ';', '<', '=', '>', '?', '@', /* 0x39-0x40 */
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', /* 0x41-0x48 */
+ 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', /* 0x49-0x50 */
+ 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', /* 0x51-0x58 */
+ 'y', 'z', '[', '\\', ']', '^', '_', '`', /* 0x59-0x60 */
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', /* 0x61-0x68 */
+ 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', /* 0x69-0x70 */
+ 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', /* 0x71-0x78 */
+ 'y', 'z', '{', '|', '}', '~', '_', 0347, /* 0x79-0x80 */
+ 0374, 0351, 0342, 0344, 0340, 0345, 0347, 0352, /* 0x81-0x88 */
+ 0353, 0350, 0357, 0356, 0354, 0344, 0345, 0351, /* 0x89-0x90 */
+ 0346, 0346, 0364, 0366, 0362, 0373, 0371, 0377, /* 0X91-0X98 */
+ 0366, 0374, 0370, 0243, 0370, 0367, '_', 0341, /* 0x99-0xa0 */
+ 0355, 0363, 0372, 0361, 0361, 0252, 0272, 0277, /* 0xa1-0xa8 */
+ 0256, 0254, 0275, 0274, 0241, 0253, 0273, '_', /* 0xa9-0xb0 */
+ '_', '_', '_', '_', 0341, 0342, 0340, 0251, /* 0xb1-0xb8 */
+ '_', '_', '_', '_', 0242, 0245, '_', '_', /* 0xb9-0xc0 */
+ '_', '_', '_', '_', '_', 0343, 0343, '_', /* 0xc1-0xc8 */
+ '_', '_', '_', '_', '_', '_', 0244, 0360, /* 0xc9-0xd0 */
+ 0320, 0352, 0353, 0350, '_', 0355, 0356, 0357, /* 0xd1-0xd8 */
+ '_', '_', '_', '_', 0246, 0354, '_', 0363, /* 0xd9-0xe0 */
+ 0337, 0364, 0362, 0365, 0365, 0265, 0376, 0376, /* 0xe1-0xe8 */
+ 0372, 0373, 0371, 0375, 0375, 0257, 0264, 0255, /* 0xe9-0xf0 */
+ 0261, '_', 0276, 0266, 0247, 0327, 0270, 0260, /* 0xf1-0xf8 */
+ 0250, 0267, 0271, 0263, 0262, '_', '_' /* 0xf9-0xff */
+};
+
+
+
+/*
+ * readbfslino() - read bfs inode's local inode information
+ */
+
+int
+readbfslino(v, i)
+ struct vnode *v; /* containing vnode */
+ struct l_ino *i; /* local inode information */
+{
+ struct inode b;
+ struct vfs kv;
+
+ if (kread((KA_T)v->v_data, (char *)&b, sizeof(b)))
+ return(1);
+ if (!v->v_vfsp || kread((KA_T)v->v_vfsp, (char *)&kv, sizeof(kv)))
+ return(1);
+ i->dev = kv.vfs_dev;
+ i->dev_def = 1;
+ i->rdev = (dev_t)0;
+ i->rdev_def = 0;
+ i->nlink = (long)b.i_diskino.d_fattr.va_nlink;
+ i->nlink_def = 1;
+ i->nm = (char *)NULL;
+ i->number = (INODETYPE)b.i_diskino.d_ino;
+ i->number_def = 1;
+ i->size = (SZOFFTYPE)BFS_FILESIZE(&b.i_diskino);
+ i->size_def = 1;
+ return(0);
+}
+
+
+#if UNIXWAREV>=7000
+/*
+ * reacdfslino() - read cdfs inode's local inode information
+ *
+ * Adapted from work by Eric Dumazet <edumazet@cosmosbay.com>.
+ */
+
+int
+readcdfslino(v, i)
+ struct vnode *v; /* containing vnode */
+ struct l_ino *i; /* local inode information */
+{
+ cdfs_inode_t ci;
+ TYPELOGSECSHIFT lss;
+ KA_T ka;
+ struct vfs kv;
+/*
+ * Read the CDFs node. Fill in return values from its contents.
+ */
+ if (!v->v_data || kread((KA_T)v->v_data, (char *)&ci, sizeof(ci)))
+ return(1);
+ if (!v->v_vfsp || kread((KA_T)v->v_vfsp, (char *)&kv, sizeof(kv)))
+ return(1);
+ i->dev = kv.vfs_dev;
+ i->dev_def = 1;
+ i->rdev = ci.i_DevNum;
+ i->rdev_def = 1;
+ i->nlink = (long)ci.i_LinkCnt;
+ i->nlink_def = 1;
+ i->nm = (char *)NULL;
+ i->size = (SZOFFTYPE)ci.i_Size;
+ i->size_def = 1;
+/*
+ * Compute the node number.
+ *
+ * (See the CDFS_INUM() macro in <sys/fs/cdfs_inode.h>.)
+ *
+ * It's too wasteful to read the entire cdfs structure for one element,
+ * cdfs_LogSecShift, so it's read specially. Its type, TYPELOGSECSHIFT,
+ * should be defined by lsof's Configure script, but for safety's sake
+ * has a uint_t default, defined in this source file.
+ */
+ i->number = (INODETYPE)0;
+ if (!(ka = (KA_T)kv.vfs_data))
+ return(0);
+ ka = (KA_T)((char *)ka + offsetof(struct cdfs, cdfs_LogSecShift));
+ if (!kread(ka, (char *)&lss, sizeof(lss))) {
+ i->number = (INODETYPE)((ci.i_Fid.fid_SectNum << lss)
+ + ci.i_Fid.fid_Offset);
+ i->number_def = 1;
+ }
+ return(0);
+}
+
+
+/*
+ * readdosfslino() - read dosfs inode's local inode information
+ *
+ * Adapted from work by Eric Dumazet <edumazet@cosmosbay.com>.
+ */
+
+
+int
+readdosfslino(v, i)
+ struct vnode *v; /* containing vnode */
+ struct l_ino *i; /* local inode information */
+{
+ struct dosfs_inode {
+ int pad1[19];
+ int device;
+ int pad2[21];
+ long offset;
+ long dirnum;
+ int pad3[3];
+ unsigned char name[16];
+ int pad4[3];
+ unsigned long size;
+ } di;
+ static char *nm = (char *)NULL;
+ static MALLOC_S nml = (MALLOC_S)0;
+ int sz;
+/*
+ * Read the DOSFS node. Fill in return values from its contents.
+ */
+ if (!v->v_data || kread((KA_T)v->v_data, (char *)&di, sizeof(di)))
+ return(1);
+ i->dev = (dev_t)di.device;
+ i->dev_def = 1;
+ i->rdev = (dev_t)0;
+ i->rdev_def = 1;
+ i->nlink_def = 0;
+ i->size = (SZOFFTYPE)di.size;
+ i->size_def = 1;
+/*
+ * Allocate space for and save the name, prepared as a name column addition.
+ */
+ i->nm = (char *)NULL;
+ if (di.name[0]) {
+ if (!nm) {
+ nml = (MALLOC_S)(strlen(DOS_NAME_PFX) + sizeof(di.name)
+ + strlen(DOS_NAME_SFX) + 1);
+ if (!(nm = (char *)malloc(nml))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d bytes for DOS name\n", nml, Pn);
+ Exit(1);
+ }
+ }
+ /*
+ * Calculate the DOS name length and convert DOS to UNIX characters.
+ */
+ for (sz = 0; sz < sizeof(di.name); sz++) {
+ if (!di.name[sz])
+ break;
+ di.name[sz] = Dos2Unix[(di.name[sz] & 0xff) - 1];
+ }
+ if (sz) {
+ (void) snpf(nm, nml, "%s%-*.*s%s", DOS_NAME_PFX, sz, sz,
+ di.name, DOS_NAME_SFX);
+ i->nm = nm;
+ }
+ }
+/*
+ * Compute the node number.
+ */
+ i->number = (INODETYPE)((di.dirnum << 16) + di.offset);
+ i->number_def = 1;
+ return(0);
+}
+#endif /* UNIXWAREV>=7000 */
diff --git a/dialects/uw/dproc.c b/dialects/uw/dproc.c
new file mode 100644
index 0000000..0a48d28
--- /dev/null
+++ b/dialects/uw/dproc.c
@@ -0,0 +1,650 @@
+/*
+ * dproc.c - SCO UnixWare process access functions for lsof
+ */
+
+
+/*
+ * Copyright 1996 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 1996 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dproc.c,v 1.14 2002/10/08 20:18:34 abe Exp $";
+#endif
+
+#include "lsof.h"
+
+
+/*
+ * Local static values
+ */
+
+static int Np; /* occupied P[] count */
+static int Npa = 0; /* allocated P[] count */
+static struct proc *P = (struct proc *)NULL;
+ /* proc table */
+static KA_T Pract; /* kernel's practive address */
+static KA_T Sgdnops; /* kernel's segdev_ops address */
+static KA_T Sgvnops; /* kernel's segvn_ops address */
+static struct var Var; /* kernel variables */
+
+
+/*
+ * Local definitions
+ */
+
+#define PROCINCR 32 /* increment for increasing P[] */
+
+
+/*
+ * Local function prototypes.
+ */
+
+_PROTOTYPE(static int get_clonemaj,(void));
+_PROTOTYPE(static void read_proc,(void));
+_PROTOTYPE(static void get_kernel_access,(void));
+_PROTOTYPE(static void readfsinfo,(void));
+_PROTOTYPE(static void process_text,(KA_T pa));
+
+
+/*
+ * gather_proc_info() -- gather process information
+ */
+
+void
+gather_proc_info()
+{
+ struct cred cr;
+ struct execinfo ex;
+ static struct fd_entry *fe;
+ struct fd_entry *f;
+ KA_T fa;
+ int i, nf;
+ MALLOC_S len;
+ static int nfea = 0;
+ struct proc *p;
+ int pgid, pid, px;
+ struct pid pids;
+ short pss, sf;
+ uid_t uid;
+
+#if UNIXWAREV>=70103
+ struct pollx plx;
+#endif /* UNIXWAREV>=70103 */
+
+/*
+ * Examine proc structures and their associated information.
+ */
+ (void) read_proc();
+ for (p = P, px = 0; px < Np; p++, px++) {
+ if ((p->p_flag & P_DESTROY) || (p->p_flag & P_GONE)
+ || !p->p_pidp
+
+#if !defined(HAS_P_PGID)
+ || !p->p_pgidp
+#endif /* !defined(HAS_P_PGID) */
+
+ || !p->p_cred || !p->p_execinfo)
+ continue;
+ /*
+ * Get Process ID, Process group ID, and User ID.
+ */
+ if (!p->p_pidp
+ || kread((KA_T)p->p_pidp, (char *)&pids, sizeof(pids)))
+ continue;
+ pid = (int)pids.pid_id;
+
+#if defined(HAS_P_PGID)
+ pgid = (int)p->p_pgid;
+#else /* !defined(HAS_P_PGID) */
+ if (!p->p_pgidp
+ || kread((KA_T)p->p_pgidp, (char *)&pids, sizeof(pids)))
+ continue;
+ pgid = (int)pids.pid_id;
+#endif /* defined(HAS_P_PGID) */
+
+ if (!p->p_cred
+ || kread((KA_T)p->p_cred, (char *)&cr, sizeof(cr)))
+ continue;
+ uid = cr.cr_uid;
+ if (is_proc_excl(pid, pgid, (UID_ARG)uid, &pss, &sf))
+ continue;
+ /*
+ * Get the execution information -- for the command name.
+ */
+ if (!p->p_execinfo
+ || kread((KA_T)p->p_execinfo, (char *)&ex, sizeof(ex)))
+ continue;
+ /*
+ * Allocate a local process structure.
+ */
+ if (is_cmd_excl(ex.ei_comm, &pss, &sf))
+ continue;
+ alloc_lproc(pid, pgid, (int)p->p_ppid, (UID_ARG)uid, ex.ei_comm,
+ (int)pss, (int)sf);
+ Plf = NULL;
+ /*
+ * Save current working directory information.
+ */
+ if (p->p_cdir) {
+ alloc_lfile(CWD, -1);
+ process_node((KA_T)p->p_cdir);
+ if (Lf->sf)
+ link_lfile();
+ }
+ /*
+ * Save root directory information.
+ */
+ if (p->p_rdir) {
+ alloc_lfile(RTD, -1);
+ process_node((KA_T)p->p_rdir);
+ if (Lf->sf)
+ link_lfile();
+ }
+ /*
+ * Print information on the text file.
+ */
+ if (Sgvnops && p->p_as)
+ process_text((KA_T)p->p_as);
+ /*
+ * Save information on file descriptors.
+ */
+ if (!p->p_fdtab.fdt_entrytab || (nf = p->p_fdtab.fdt_sizeused) < 1)
+ continue;
+ len = (MALLOC_S)(nf * sizeof(struct fd_entry));
+ if (nf > nfea) {
+ if (fe)
+ fe = (struct fd_entry *)realloc((MALLOC_P *)fe, len);
+ else
+ fe = (struct fd_entry *)malloc(len);
+ if (!fe) {
+ (void) fprintf(stderr,
+ "%s: PID %d; no space for %d file descriptors\n",
+ Pn, pid, nf);
+ Exit(1);
+ }
+ nfea = nf;
+ }
+ if (kread((KA_T)p->p_fdtab.fdt_entrytab, (char *)fe, len))
+ continue;
+ for (f = fe, i = 0; i < nf; f++, i++) {
+ if ((fa = (KA_T)f->fd_file) && (f->fd_status & FD_INUSE)) {
+
+#if UNIXWAREV>=70103
+ if (f->fd_flag & FPOLLED) {
+ if (kread(fa, (char *)&plx, sizeof(plx))
+ || !(fa = (KA_T)plx.px_fp))
+ continue;
+ }
+#endif /* UNIXWAREV>=70103 */
+
+ alloc_lfile(NULL, i);
+ process_file(fa);
+ if (Lf->sf) {
+
+#if defined(HASFSTRUCT)
+ if (Fsv & FSV_FG)
+ Lf->pof = (long)f->fd_flag;
+#endif /* defined(HASFSTRUCT) */
+
+ link_lfile();
+ }
+ }
+ }
+ /*
+ * Examine results.
+ */
+ if (examine_lproc())
+ return;
+ }
+}
+
+
+/*
+ * get_clonemaj() - get clone major device number
+ */
+
+static int
+get_clonemaj()
+{
+ KA_T v;
+
+#if UNIXWAREV<70000
+ char buf[32];
+ struct cdevsw *c, *cd;
+ int i, sz;
+ MALLOC_S len;
+ int rv = 0;
+/*
+ * Read the cdevsw[] size and allocate temporary space for it.
+ */
+ if (get_Nl_value("ncdev", Drive_Nl, &v) < 0 || !v
+ || kread((KA_T)v, (char *)&sz, sizeof(sz)) || !sz)
+ return(rv);
+ len = (MALLOC_S)(sz * sizeof(struct cdevsw));
+ if (!(cd = (struct cdevsw *)malloc(len))) {
+ (void) fprintf(stderr, "%s: can't allocate %d bytes for cdevsw\n",
+ Pn);
+ Exit(1);
+ }
+/*
+ * Read the cdevsw[] from kernel memory.
+ */
+ if (get_Nl_value("cdev", Drive_Nl, &v) < 0 || !v
+ || kread((KA_T)v, (char *)cd, (int)len)) {
+ (void) free((MALLOC_P *)cd);
+ return(rv);
+ }
+/*
+ * Scan the cdevsw[], reading it's names, looking for "clone".
+ * Record its cdevsw[] index (i.e., major device number).
+ */
+ len = sizeof(buf) - 1;
+ buf[len] = '\0';
+ for (c = cd, i = 0; i < sz; c++, i++) {
+ if (!c->d_name
+ || kread((KA_T)c->d_name, buf, len)
+ || strcmp(buf, "clone") != 0)
+ continue;
+ CloneMaj = i;
+ HaveCloneMaj = rv = 1;
+ break;
+ }
+ (void) free((MALLOC_P *)cd);
+ return(rv);
+#else /* UNIXWAREV>=70000 */
+/*
+ * At UnixWare 7 the clone major device is found in the kernel's
+ * clonemajor variable.
+ */
+ if (get_Nl_value("cmaj", Drive_Nl, &v) < 0 || !v
+ || kread((KA_T)v, (char *)&CloneMaj, sizeof(CloneMaj)))
+ return(0);
+ return((HaveCloneMaj = 1));
+#endif /* UNIXWAREV<70000 */
+
+}
+
+
+/*
+ * get_kernel_access() - get access to kernel memory
+ */
+
+static void
+get_kernel_access()
+{
+ KA_T v;
+/*
+ * Check kernel version.
+ */
+ (void) ckkv("UW", (char *)NULL, LSOF_VSTR, (char *)NULL);
+
+#if defined(WILLDROPGID)
+/*
+ * If kernel memory isn't coming from KMEM, drop setgid permission
+ * before attempting to open the (Memory) file.
+ */
+ if (Memory)
+ (void) dropgid();
+#else /* !defined(WILLDROPGID) */
+/*
+ * See if the non-KMEM memory file is readable.
+ */
+ if (Memory && !is_readable(Memory, 1))
+ Exit(1);
+#endif /* defined(WILLDROPGID) */
+
+/*
+ * Open kernel memory access.
+ */
+ if ((Kd = open(Memory ? Memory : KMEM, O_RDONLY, 0)) < 0) {
+ (void) fprintf(stderr, "%s: can't open %s: %s\n", Pn,
+ Memory ? Memory : KMEM, strerror(errno));
+ Exit(1);
+ }
+
+#if defined(WILLDROPGID)
+/*
+ * Drop setgid permission, if necessary.
+ */
+ if (!Memory)
+ (void) dropgid();
+#else /* !defined(WILLDROPGID) */
+/*
+ * See if the name list file is readable.
+ */
+ if (Nmlst && !is_readable(Nmlst, 1))
+ Exit(1);
+#endif /* defined(WILLDROPGID) */
+
+/*
+ * Access kernel symbols and values.
+ */
+ (void) build_Nl(Drive_Nl);
+ if (nlist(Nmlst ? Nmlst : N_UNIX, Nl) < 0) {
+ (void) fprintf(stderr, "%s: can't read kernel name list from %s\n",
+ Pn, Nmlst ? Nmlst : N_UNIX);
+ Exit(1);
+ }
+ if (get_Nl_value("var", Drive_Nl, &v) < 0 || !v
+ || kread((KA_T)v, (char *)&Var, sizeof(Var))) {
+ (void) fprintf(stderr,
+ "%s: can't read system configuration info\n", Pn);
+ Exit(1);
+ }
+ if (get_Nl_value("proc", Drive_Nl, &Pract) < 0 || !Pract) {
+ (void) fprintf(stderr,
+ "%s: can't find active process chain pointer\n", Pn);
+ Exit(1);
+ }
+ if (get_Nl_value("sgdnops", Drive_Nl, &Sgdnops) < 0 || !Sgdnops)
+ Sgdnops = (unsigned long)0;
+ if (get_Nl_value("sgvnops", Drive_Nl, &Sgvnops) < 0 || !Sgvnops)
+ Sgvnops = (unsigned long)0;
+/*
+ * Identify the clone major device number.
+ */
+ if (!get_clonemaj()) {
+ if (!Fwarn)
+ (void) fprintf(stderr,
+ "%s: WARNING; can't identify major clone device number\n",
+ Pn);
+ }
+}
+
+
+/*
+ * initialize() - perform all initialization
+ */
+
+void
+initialize()
+{
+ get_kernel_access();
+ readfsinfo();
+}
+
+
+/*
+ * kread() - read from kernel memory
+ */
+
+int
+kread(addr, buf, len)
+ KA_T addr; /* kernel memory address */
+ char *buf; /* buffer to receive data */
+ READLEN_T len; /* length to read */
+{
+ READLEN_T br;
+
+#if UNIXWAREV<7000
+ if (lseek(Kd, (long)addr, L_SET) == (long)-1L)
+ return(-1);
+ br = (READLEN_T) read(Kd, buf, len);
+#else /* UNIXWAREV>=7000 */
+ br = (READLEN_T) pread(Kd, buf, len, (off_t)addr);
+#endif /* UNIXWAREV<7000 */
+
+ return((br == len) ? 0 : 1);
+}
+
+
+/*
+ * process_text() - process text access information
+ */
+
+static void
+process_text(pa)
+ KA_T pa; /* kernel address space description
+ * pointer */
+{
+ struct as as;
+ struct segdev_data dv;
+ char *fd;
+ int i, j, k, l;
+ struct seg s;
+ KA_T v[MAXSEGS];
+ struct segvn_data vn;
+ KA_T vp;
+/*
+ * Get address space description.
+ */
+ if (kread(pa, (char *)&as, sizeof(as)))
+ return;
+/*
+ * Loop through the segments. The loop should stop when the segment
+ * pointer returns to its starting point, but just in case, it's stopped
+ * when MAXSEGS have been recorded or 2*MAXSEGS have been examined.
+ */
+ s.s_next = as.a_segs;
+ for (i = j = k = 0; i < MAXSEGS && j < 2*MAXSEGS; j++) {
+ if (!s.s_next || kread((KA_T)s.s_next, (char *)&s, sizeof(s)))
+ break;
+ fd = (char *)NULL;
+ vp = (KA_T)NULL;
+ if (Sgvnops == (KA_T)s.s_ops && s.s_data) {
+
+ /*
+ * Process a virtual node segment.
+ */
+ if (kread((KA_T)s.s_data, (char *)&vn, sizeof(vn)))
+ break;
+ if ((vp = (KA_T)vn.svd_vp)) {
+ if ((vn.svd_flags & SEGVN_PGPROT)
+ || (vn.svd_prot & PROT_EXEC))
+ fd = " txt";
+ else
+ fd = " mem";
+ }
+ } else if (Sgdnops == (KA_T)s.s_ops && s.s_data) {
+
+ /*
+ * Process a special device segment.
+ */
+ if (kread((KA_T)s.s_data, (char *)&dv, sizeof(dv)))
+ break;
+ if ((vp = (KA_T)dv.vp))
+ fd = "mmap";
+ }
+ if (fd && vp) {
+
+ /*
+ * Process the vnode pointer. First make sure it's unique.
+ */
+ for (l = 0; l < k; l++) {
+ if (v[l] == vp)
+ break;
+ }
+ if (l >= k) {
+ alloc_lfile(fd, -1);
+ process_node(vp);
+ if (Lf->sf) {
+ link_lfile();
+ i++;
+ }
+ }
+ v[k++] = vp;
+ }
+ /*
+ * Follow the segment link to the starting point in the address
+ * space description. (The i and j counters place an absolute
+ * limit on the loop.)
+ */
+ if (s.s_next == as.a_segs)
+ break;
+ }
+}
+
+
+/*
+ * readfsinfo() - read file system information
+ */
+
+static void
+readfsinfo()
+{
+ char buf[FSTYPSZ+1];
+ int i, len;
+
+ if ((Fsinfomax = sysfs(GETNFSTYP)) == -1) {
+ (void) fprintf(stderr, "%s: sysfs(GETNFSTYP) error: %s\n",
+ Pn, strerror(errno));
+ Exit(1);
+ }
+ if (Fsinfomax == 0)
+ return;
+ if (!(Fsinfo = (char **)malloc((MALLOC_S)(Fsinfomax * sizeof(char *)))))
+ {
+ (void) fprintf(stderr, "%s: no space for sysfs info\n", Pn);
+ Exit(1);
+ }
+ for (i = 1; i <= Fsinfomax; i++) {
+ if (sysfs(GETFSTYP, i, buf) == -1) {
+ (void) fprintf(stderr, "%s: sysfs(GETFSTYP) error: %s\n",
+ Pn, strerror(errno));
+ Exit(1);
+ }
+ buf[FSTYPSZ] = '\0';
+ len = strlen(buf) + 1;
+ if (!(Fsinfo[i-1] = (char *)malloc((MALLOC_S)len))) {
+ (void) fprintf(stderr,
+ "%s: no space for file system entry %s\n", Pn, buf);
+ Exit(1);
+ }
+ (void) snpf(Fsinfo[i-1], len, "%s", buf);
+ }
+}
+
+
+/*
+ * read_proc() - read the process table
+ */
+
+static void
+read_proc()
+{
+ MALLOC_S len;
+ struct proc *p;
+ KA_T pa;
+ char tbuf[32];
+ int try;
+
+ if (!P) {
+
+ /*
+ * Allocate initial space for local proc table.
+ */
+ if ((Npa = Var.v_proc) < 1) {
+ (void) fprintf(stderr, "%s: bad proc table size: %d\n",
+ Pn, Var.v_proc);
+ Exit(1);
+ }
+ Npa += PROCINCR;
+ len = (MALLOC_S)(Npa * sizeof(struct proc));
+ if (!(P = (struct proc *)malloc(len))) {
+ (void) fprintf(stderr, "%s: no space for %d proc structures\n",
+ Pn, Npa);
+ Exit(1);
+ }
+ }
+/*
+ * Scan the active process chain.
+ */
+ for (try = 0; try < PROCTRYLM; try++) {
+
+ /*
+ * Read the active process chain head.
+ */
+ pa = (KA_T)NULL;
+ if (!Pract || kread((KA_T)Pract, (char *)&pa, sizeof(pa)) || !pa) {
+ if (!Fwarn)
+ (void) fprintf(stderr,
+ "%s: active proc chain ptr err; addr=%s, val=%s\n",
+ Pn, print_kptr(Pract, tbuf, sizeof(tbuf)),
+ print_kptr(pa, (char *)NULL, 0));
+ continue;
+ }
+ /*
+ * Follow the active process chain, accumulating proc structures.
+ */
+ for (Np = 0, p = P; pa;) {
+ if (Np >= Npa) {
+
+ /*
+ * Allocate more proc table space.
+ */
+ Npa += PROCINCR;
+ len = (MALLOC_S)(Npa * sizeof(struct proc));
+ if (!(P = (struct proc *)realloc((MALLOC_P *)P, len))) {
+ (void) fprintf(stderr,
+ "%s: can't realloc %d proc table entries (%d)\n",
+ Pn, Npa, len);
+ Exit(1);
+ }
+ p = &P[Np];
+ }
+ if (kread(pa, (char *)p, sizeof(struct proc)))
+ break;
+ pa = (KA_T)p->p_next;
+ if ((p->p_flag & P_DESTROY) || (p->p_flag & P_GONE)
+ || !p->p_pidp
+
+#if !defined(HAS_P_PGID)
+ || !p->p_pgidp
+#endif /* !defined(HAS_P_PGID) */
+
+ || !p->p_cred || !p->p_execinfo)
+ continue;
+ Np++;
+ p++;
+ }
+ /*
+ * See if enough processes were accumulated.
+ */
+ if (Np >= PROCMIN)
+ break;
+ }
+/*
+ * Quit if not enough proc structures could be collected.
+ */
+ if (try >= PROCTRYLM) {
+ (void) fprintf(stderr, "%s: can't read proc table\n", Pn);
+ Exit(1);
+ }
+ if (Np < Npa && !RptTm) {
+
+ /*
+ * If not repeating, reduce the local proc table size to a minimum.
+ */
+ len = (MALLOC_S)(Np * sizeof(struct proc));
+ if (!(P = (struct proc *)realloc((MALLOC_P *)P, len))) {
+ (void) fprintf(stderr,
+ "%s: can't reduce proc table to %d entries\n", Pn, Np);
+ Exit(1);
+ }
+ Npa = Np;
+ }
+}
diff --git a/dialects/uw/dproto.h b/dialects/uw/dproto.h
new file mode 100644
index 0000000..491fe60
--- /dev/null
+++ b/dialects/uw/dproto.h
@@ -0,0 +1,49 @@
+/*
+ * dproto.h - SCO UnixWare function prototypes for lsof
+ *
+ * The _PROTOTYPE macro is defined in the common proto.h.
+ */
+
+
+/*
+ * Copyright 1996 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.
+ */
+
+
+
+_PROTOTYPE(extern int get_max_fd,(void));
+_PROTOTYPE(extern int is_file_named,(char *p, int cd));
+_PROTOTYPE(extern void process_socket,(char *pr, struct queue *q));
+_PROTOTYPE(extern int readbfslino,(struct vnode *v, struct l_ino *i));
+_PROTOTYPE(extern int readcdfslino,(struct vnode *v, struct l_ino *i));
+_PROTOTYPE(extern int readdosfslino,(struct vnode *v, struct l_ino *i));
+_PROTOTYPE(extern int reads5lino,(struct vnode *v, struct l_ino *i));
+_PROTOTYPE(extern int readvxfslino,(struct vnode *v, struct l_ino *i));
+_PROTOTYPE(extern int strcasecmp,(char *s1, char *s2));
+_PROTOTYPE(extern int strncasecmp,(char *s1, char *s2, int n));
+
+#if UNIXWAREV>=70101
+_PROTOTYPE(extern int process_unix_sockstr,(struct vnode *v, KA_T na));
+#endif /* UNIXWAREV>=70101 */
diff --git a/dialects/uw/dsock.c b/dialects/uw/dsock.c
new file mode 100644
index 0000000..accdb62
--- /dev/null
+++ b/dialects/uw/dsock.c
@@ -0,0 +1,1197 @@
+/*
+ * dsock.c - SCO UnixWare socket processing functions for lsof
+ */
+
+
+/*
+ * Copyright 1996 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 1996 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dsock.c,v 1.16 2005/08/13 16:21:41 abe Exp $";
+#endif
+
+
+#define TCPSTATES /* activate tcpstates[] */
+#include "lsof.h"
+
+
+/*
+ * Local function prototypes
+ */
+
+#if UNIXWAREV>=70101 && UNIXWAREV<70103
+_PROTOTYPE(static struct sockaddr_un *find_unix_sockaddr_un,(KA_T ka));
+#endif /* UNIXWAREV>=70101 && UNIXWAREV<70103 */
+
+
+/*
+ * print_tcptpi() - print TCP/TPI info
+ */
+
+void
+print_tcptpi(nl)
+ int nl; /* 1 == '\n' required */
+{
+ char buf[128];
+ char *cp = (char *)NULL;
+ int ps = 0;
+ int s;
+
+ if (Ftcptpi & TCPTPI_STATE) {
+ s = Lf->lts.state.i;
+ switch (Lf->lts.type) {
+ case 0:
+ if (s < 0 || s >= TCP_NSTATES) {
+ (void) snpf(buf, sizeof(buf), "UNKNOWN_TCP_STATE_%d", s);
+ cp = buf;
+ } else
+ cp = tcpstates[s];
+ break;
+ case 1:
+ switch (s) {
+ case TS_UNBND:
+ cp = "TS_UNBND";
+ break;
+ case TS_WACK_BREQ:
+ cp = "TS_WACK_BREQ";
+ break;
+ case TS_WACK_UREQ:
+ cp = "TS_WACK_UREQ";
+ break;
+ case TS_IDLE:
+ cp = "TS_IDLE";
+ break;
+ case TS_WACK_OPTREQ:
+ cp = "TS_WACK_OPTREQ";
+ break;
+ case TS_WACK_CREQ:
+ cp = "TS_WACK_CREQ";
+ break;
+ case TS_WCON_CREQ:
+ cp = "TS_WCON_CREQ";
+ break;
+ case TS_WRES_CIND:
+ cp = "TS_WRES_CIND";
+ break;
+ case TS_WACK_CRES:
+ cp = "TS_WACK_CRES";
+ break;
+ case TS_DATA_XFER:
+ cp = "TS_DATA_XFER";
+ break;
+ case TS_WIND_ORDREL:
+ cp = "TS_WIND_ORDREL";
+ break;
+ case TS_WREQ_ORDREL:
+ cp = "TS_WREQ_ORDREL";
+ break;
+ case TS_WACK_DREQ6:
+ cp = "TS_WACK_DREQ6";
+ break;
+ case TS_WACK_DREQ7:
+ cp = "TS_WACK_DREQ7";
+ break;
+ case TS_WACK_DREQ9:
+ cp = "TS_WACK_DREQ9";
+ break;
+ case TS_WACK_DREQ10:
+ cp = "TS_WACK_DREQ10";
+ break;
+ case TS_WACK_DREQ11:
+ cp = "TS_WACK_DREQ11";
+ break;
+ default:
+ (void) snpf(buf, sizeof(buf), "UNKNOWN_TPI_STATE_%d", s);
+ cp = buf;
+ }
+ }
+ if (cp) {
+ if (Ffield)
+ (void) printf("%cST=%s%c", LSOF_FID_TCPTPI, cp, Terminator);
+ else {
+ putchar('(');
+ (void) fputs(cp, stdout);
+ }
+ ps++;
+ }
+ }
+
+# if defined(HASTCPTPIQ)
+ if (Ftcptpi & TCPTPI_QUEUES) {
+ if (Lf->lts.rqs) {
+ if (Ffield)
+ putchar(LSOF_FID_TCPTPI);
+ else {
+ if (ps)
+ putchar(' ');
+ else
+ putchar('(');
+ }
+ (void) printf("QR=%lu", Lf->lts.rq);
+ if (Ffield)
+ putchar(Terminator);
+ ps++;
+ }
+ if (Lf->lts.sqs) {
+ if (Ffield)
+ putchar(LSOF_FID_TCPTPI);
+ else {
+ if (ps)
+ putchar(' ');
+ else
+ putchar('(');
+ }
+ (void) printf("QS=%lu", Lf->lts.sq);
+ if (Ffield)
+ putchar(Terminator);
+ ps++;
+ }
+ }
+# endif /* defined(HASTCPTPIQ) */
+
+#if defined(HASSOOPT)
+ if (Ftcptpi & TCPTPI_FLAGS) {
+ int opt;
+
+ if ((opt = Lf->lts.opt)
+ || Lf->lts.pqlens || Lf->lts.qlens || Lf->lts.qlims
+ || Lf->lts.rbszs || Lf->lts.sbsz
+ ) {
+ char sep = ' ';
+
+ if (Ffield)
+ sep = LSOF_FID_TCPTPI;
+ else if (!ps)
+ sep = '(';
+ (void) printf("%cSO", sep);
+ ps++;
+ sep = '=';
+
+# if defined(SO_ACCEPTCONN)
+ if (opt & SO_ACCEPTCONN) {
+ (void) printf("%cACCEPTCONN", sep);
+ opt &= ~SO_ACCEPTCONN;
+ sep = ',';
+ }
+# endif /* defined(SO_ACCEPTCONN) */
+
+# if defined(SO_BROADCAST)
+ if (opt & SO_BROADCAST) {
+ (void) printf("%cBROADCAST", sep);
+ opt &= ~SO_BROADCAST;
+ sep = ',';
+ }
+# endif /* defined(SO_BROADCAST) */
+
+# if defined(SO_DEBUG)
+ if (opt & SO_DEBUG) {
+ (void) printf("%cDEBUG", sep);
+ opt &= ~ SO_DEBUG;
+ sep = ',';
+ }
+# endif /* defined(SO_DEBUG) */
+
+# if defined(SO_DONTROUTE)
+ if (opt & SO_DONTROUTE) {
+ (void) printf("%cDONTROUTE", sep);
+ opt &= ~SO_DONTROUTE;
+ sep = ',';
+ }
+# endif /* defined(SO_DONTROUTE) */
+
+# if defined(SO_IMASOCKET)
+ if (opt & SO_IMASOCKET) {
+ (void) printf("%cIMASOCKET", sep);
+ opt &= ~SO_IMASOCKET;
+ sep = ',';
+ }
+# endif /* defined(SO_IMASOCKET) */
+
+# if defined(SO_KEEPALIVE)
+ if (opt & SO_KEEPALIVE) {
+ (void) printf("%cKEEPALIVE", sep);
+ opt &= ~SO_KEEPALIVE;
+ sep = ',';
+ }
+# endif /* defined(SO_KEEPALIVE) */
+
+# if defined(SO_LINGER)
+ if (opt & SO_LINGER) {
+ (void) printf("%cLINGER", sep);
+ if (Lf->lts.ltm)
+ (void) printf("=%d", Lf->lts.ltm);
+ opt &= ~SO_LINGER;
+ sep = ',';
+ }
+# endif /* defined(SO_LINGER) */
+
+# if defined(SO_LISTENING)
+ if (opt & SO_LISTENING) {
+ (void) printf("%cLISTENING", sep);
+ opt &= ~SO_LISTENING;
+ sep = ',';
+ }
+# endif /* defined(SO_LISTENING) */
+
+# if defined(SO_MGMT)
+ if (opt & SO_MGMT) {
+ (void) printf("%cMGMT", sep);
+ opt &= ~SO_MGMT;
+ sep = ',';
+ }
+# endif /* defined(SO_MGMT) */
+
+# if defined(SO_OOBINLINE)
+ if (opt & SO_OOBINLINE) {
+ (void) printf("%cOOBINLINE", sep);
+ opt &= ~SO_OOBINLINE;
+ sep = ',';
+ }
+# endif /* defined(SO_OOBINLINE) */
+
+# if defined(SO_ORDREL)
+ if (opt & SO_ORDREL) {
+ (void) printf("%cORDREL", sep);
+ opt &= ~SO_ORDREL;
+ sep = ',';
+ }
+# endif /* defined(SO_ORDREL) */
+
+# if defined(SO_PARALLELSVR)
+ if (opt & SO_PARALLELSVR) {
+ (void) printf("%cPARALLELSVR", sep);
+ opt &= ~SO_PARALLELSVR;
+ sep = ',';
+ }
+# endif /* defined(SO_PARALLELSVR) */
+
+ if (Lf->lts.pqlens) {
+ (void) printf("%cPQLEN=%u", sep, Lf->lts.pqlen);
+ sep = ',';
+ }
+ if (Lf->lts.qlens) {
+ (void) printf("%cQLEN=%u", sep, Lf->lts.qlen);
+ sep = ',';
+ }
+ if (Lf->lts.qlims) {
+ (void) printf("%cQLIM=%u", sep, Lf->lts.qlim);
+ sep = ',';
+ }
+ if (Lf->lts.rbszs) {
+ (void) printf("%cRCVBUF=%lu", sep, Lf->lts.rbsz);
+ sep = ',';
+ }
+
+# if defined(SO_RDWR)
+ if (opt & SO_RDWR) {
+ (void) printf("%cRDWR", sep);
+ opt &= ~SO_RDWR;
+ sep = ',';
+ }
+# endif /* defined(SO_RDWR) */
+
+# if defined(SO_REUSEADDR)
+ if (opt & SO_REUSEADDR) {
+ (void) printf("%cREUSEADDR", sep);
+ opt &= ~SO_REUSEADDR;
+ sep = ',';
+ }
+# endif /* defined(SO_REUSEADDR) */
+
+# if defined(SO_REUSEPORT)
+ if (opt & SO_REUSEPORT) {
+ (void) printf("%cREUSEPORT", sep);
+ opt &= ~SO_REUSEPORT;
+ sep = ',';
+ }
+# endif /* defined(SO_REUSEPORT) */
+
+# if defined(SO_SEMA)
+ if (opt & SO_SEMA) {
+ (void) printf("%cSEMA", sep);
+ opt &= ~SO_SEMA;
+ sep = ',';
+ }
+# endif /* defined(SO_SEMA) */
+
+ if (Lf->lts.sbszs) {
+ (void) printf("%cSNDBUF=%lu", sep, Lf->lts.sbsz);
+ sep = ',';
+ }
+
+# if defined(SO_USELOOPBACK)
+ if (opt & SO_USELOOPBACK) {
+ (void) printf("%cUSELOOPBACK", sep);
+ opt &= ~SO_USELOOPBACK;
+ sep = ',';
+ }
+# endif /* defined(SO_USELOOPBACK) */
+
+ if (opt)
+ (void) printf("%cUNKNOWN=%#x", sep, opt);
+ if (Ffield)
+ putchar(Terminator);
+ }
+ }
+#endif /* defined(HASSOOPT) */
+
+#if defined(HASSOSTATE)
+ if (Ftcptpi & TCPTPI_FLAGS) {
+ int ss;
+
+ if ((ss = Lf->lts.ss)) {
+ char sep = ' ';
+
+ if (Ffield)
+ sep = LSOF_FID_TCPTPI;
+ else if (!ps)
+ sep = '(';
+ (void) printf("%cSS", sep);
+ ps++;
+ sep = '=';
+
+# if defined(SS_ASYNC)
+ if (ss & SS_ASYNC) {
+ (void) printf("%cASYNC", sep);
+ ss &= ~SS_ASYNC;
+ sep = ',';
+ }
+# endif /* defined(SS_ASYNC) */
+
+# if defined(SS_CANTRCVMORE)
+ if (ss & SS_CANTRCVMORE) {
+ (void) printf("%cCANTRCVMORE", sep);
+ ss &= ~SS_CANTRCVMORE;
+ sep = ',';
+ }
+# endif /* defined(SS_CANTRCVMORE) */
+
+# if defined(SS_CANTSENDMORE)
+ if (ss & SS_CANTSENDMORE) {
+ (void) printf("%cCANTSENDMORE", sep);
+ ss &= ~SS_CANTSENDMORE;
+ sep = ',';
+ }
+# endif /* defined(SS_CANTSENDMORE) */
+
+# if defined(SS_IGNERR)
+ if (ss & SS_IGNERR) {
+ (void) printf("%cIGNERR", sep);
+ ss &= ~SS_IGNERR;
+ sep = ',';
+ }
+# endif /* defined(SS_IGNERR) */
+
+# if defined(SS_ISBOUND)
+ if (ss & SS_ISBOUND) {
+ (void) printf("%cISBOUND", sep);
+ ss &= ~SS_ISBOUND;
+ sep = ',';
+ }
+# endif /* defined(SS_ISBOUND) */
+
+# if defined(SS_ISCONNECTED)
+ if (ss & SS_ISCONNECTED) {
+ (void) printf("%cISCONNECTED", sep);
+ ss &= ~SS_ISCONNECTED;
+ sep = ',';
+ }
+# endif /* defined(SS_ISCONNECTED) */
+
+# if defined(SS_ISCONNECTING)
+ if (ss & SS_ISCONNECTING) {
+ (void) printf("%cISCONNECTING", sep);
+ ss &= ~SS_ISCONNECTING;
+ sep = ',';
+ }
+# endif /* defined(SS_ISCONNECTING) */
+
+# if defined(SS_ISDISCONNECTING)
+ if (ss & SS_ISDISCONNECTING) {
+ (void) printf("%cISDISCONNECTING", sep);
+ ss &= ~SS_ISDISCONNECTING;
+ sep = ',';
+ }
+# endif /* defined(SS_ISDISCONNECTING) */
+
+# if defined(SS_NBIO)
+ if (ss & SS_NBIO) {
+ (void) printf("%cNBIO", sep);
+ ss &= ~SS_NBIO;
+ sep = ',';
+ }
+# endif /* defined(SS_NBIO) */
+
+# if defined(SS_NODELETE)
+ if (ss & SS_NODELETE) {
+ (void) printf("%cNODELETE", sep);
+ ss &= ~SS_NODELETE;
+ sep = ',';
+ }
+# endif /* defined(SS_NODELETE) */
+
+# if defined(SS_NOGHOST)
+ if (ss & SS_NOGHOST) {
+ (void) printf("%cNOGHOST", sep);
+ ss &= ~SS_NOGHOST;
+ sep = ',';
+ }
+# endif /* defined(SS_NOGHOST) */
+
+# if defined(SS_NOINPUT)
+ if (ss & SS_NOINPUT) {
+ (void) printf("%cNOINPUT", sep);
+ ss &= ~SS_NOINPUT;
+ sep = ',';
+ }
+# endif /* defined(SS_NOINPUT) */
+
+# if defined(SS_NOFDREF)
+ if (ss & SS_NOFDREF) {
+ (void) printf("%cNOFDREF", sep);
+ ss &= ~SS_NOFDREF;
+ sep = ',';
+ }
+# endif /* defined(SS_NOFDREF) */
+
+# if defined(SS_PRIV)
+ if (ss & SS_PRIV) {
+ (void) printf("%cPRIV", sep);
+ ss &= ~SS_PRIV;
+ sep = ',';
+ }
+# endif /* defined(SS_PRIV) */
+
+# if defined(SS_RCVATMARK)
+ if (ss & SS_RCVATMARK) {
+ (void) printf("%cRCVATMARK", sep);
+ ss &= ~SS_RCVATMARK;
+ sep = ',';
+ }
+# endif /* defined(SS_RCVATMARK) */
+
+# if defined(SS_SETRCV)
+ if (ss & SS_SETRCV) {
+ (void) printf("%cSETRCV", sep);
+ ss &= ~SS_SETRCV;
+ sep = ',';
+ }
+# endif /* defined(SS_SETRCV) */
+
+# if defined(SS_SETSND)
+ if (ss & SS_SETSND) {
+ (void) printf("%cSETSND", sep);
+ ss &= ~SS_SETSND;
+ sep = ',';
+ }
+# endif /* defined(SS_SETSND) */
+
+# if defined(SS_ZOMBIE)
+ if (ss & SS_ZOMBIE) {
+ (void) printf("%cZOMBIE", sep);
+ ss &= ~SS_ZOMBIE;
+ sep = ',';
+ }
+# endif /* defined(SS_ZOMBIE) */
+
+ if (ss)
+ (void) printf("%cUNKNOWN=%#x", sep, ss);
+ if (Ffield)
+ putchar(Terminator);
+ }
+ }
+#endif /* defined(HASSOSTATE) */
+
+#if defined(HASTCPOPT)
+ if (Ftcptpi & TCPTPI_FLAGS) {
+ int topt;
+
+ if ((topt = Lf->lts.topt) || Lf->lts.msss) {
+ char sep = ' ';
+
+ if (Ffield)
+ sep = LSOF_FID_TCPTPI;
+ else if (!ps)
+ sep = '(';
+ (void) printf("%cTF", sep);
+ ps++;
+ sep = '=';
+
+# if defined(TF_ACKNOW)
+ if (topt & TF_ACKNOW) {
+ (void) printf("%cACKNOW", sep);
+ topt &= ~TF_ACKNOW;
+ sep = ',';
+ }
+# endif /* defined(TF_ACKNOW) */
+
+# if defined(TF_DELACK)
+ if (topt & TF_DELACK) {
+ (void) printf("%cDELACK", sep);
+ topt &= ~TF_DELACK;
+ sep = ',';
+ }
+# endif /* defined(TF_DELACK) */
+
+# if defined(TF_HAVEACKED)
+ if (topt & TF_HAVEACKED) {
+ (void) printf("%cHAVEACKED", sep);
+ topt &= ~TF_HAVEACKED;
+ sep = ',';
+ }
+# endif /* defined(TF_HAVEACKED) */
+
+# if defined(TF_HAVECLOSED)
+ if (topt & TF_HAVECLOSED) {
+ (void) printf("%cHAVECLOSED", sep);
+ topt &= ~TF_HAVECLOSED;
+ sep = ',';
+ }
+# endif /* defined(TF_HAVECLOSED) */
+
+# if defined(TF_IOLOCK)
+ if (topt & TF_IOLOCK) {
+ (void) printf("%cIOLOCK", sep);
+ topt &= ~TF_IOLOCK;
+ sep = ',';
+ }
+# endif /* defined(TF_IOLOCK) */
+
+ if (Lf->lts.msss) {
+ (void) printf("%cMSS=%lu", sep, Lf->lts.mss);
+ sep = ',';
+ }
+
+# if defined(TF_MAXSEG_TSTMP)
+ if (topt & TF_MAXSEG_TSTMP) {
+ (void) printf("%cMAXSEG_TSTMP", sep);
+ topt &= ~TF_MAXSEG_TSTMP;
+ sep = ',';
+ }
+# endif /* defined(TF_MAXSEG_TSTMP) */
+
+# if defined(TF_NEEDCLOSE)
+ if (topt & TF_NEEDCLOSE) {
+ (void) printf("%cNEEDCLOSE", sep);
+ topt &= ~TF_NEEDCLOSE;
+ sep = ',';
+ }
+# endif /* defined(TF_NEEDCLOSE) */
+
+# if defined(TF_NEEDIN)
+ if (topt & TF_NEEDIN) {
+ (void) printf("%cNEEDIN", sep);
+ topt &= ~TF_NEEDIN;
+ sep = ',';
+ }
+# endif /* defined(TF_NEEDIN) */
+
+# if defined(TF_NEEDOUT)
+ if (topt & TF_NEEDOUT) {
+ (void) printf("%cNEEDOUT", sep);
+ topt &= ~TF_NEEDOUT;
+ sep = ',';
+ }
+# endif /* defined(TF_NEEDOUT) */
+
+# if defined(TF_NEEDTIMER)
+ if (topt & TF_NEEDTIMER) {
+ (void) printf("%cNEEDTIMER", sep);
+ topt &= ~TF_NEEDTIMER;
+ sep = ',';
+ }
+# endif /* defined(TF_NEEDTIMER) */
+
+# if defined(TF_NODELACK)
+ if (topt & TF_NODELACK) {
+ (void) printf("%cNODELACK", sep);
+ topt &= ~TF_NODELACK;
+ sep = ',';
+ }
+# endif /* defined(TF_NODELACK) */
+
+# if defined(TF_NODELAY)
+ if (topt & TF_NODELAY) {
+ (void) printf("%cNODELAY", sep);
+ topt &= ~TF_NODELAY;
+ sep = ',';
+ }
+# endif /* defined(TF_NODELAY) */
+
+# if defined(TF_NOOPT)
+ if (topt & TF_NOOPT) {
+ (void) printf("%cNOOPT", sep);
+ topt &= ~TF_NOOPT;
+ sep = ',';
+ }
+# endif /* defined(TF_NOOPT) */
+
+# if defined(TF_RCVD_SCALE)
+ if (topt & TF_RCVD_SCALE) {
+ (void) printf("%cRCVD_SCALE", sep);
+ topt &= ~TF_RCVD_SCALE;
+ sep = ',';
+ }
+# endif /* defined(TF_RCVD_SCALE) */
+
+# if defined(TF_RCVD_TSTMP)
+ if (topt & TF_RCVD_TSTMP) {
+ (void) printf("%cRCVD_TSTMP", sep);
+ topt &= ~TF_RCVD_TSTMP;
+ sep = ',';
+ }
+# endif /* defined(TF_RCVD_TSTMP) */
+
+# if defined(TF_REQ_SCALE)
+ if (topt & TF_REQ_SCALE) {
+ (void) printf("%cREQ_SCALE", sep);
+ topt &= ~TF_REQ_SCALE;
+ sep = ',';
+ }
+# endif /* defined(TF_REQ_SCALE) */
+
+# if defined(TF_REQ_TSTMP)
+ if (topt & TF_REQ_TSTMP) {
+ (void) printf("%cREQ_TSTMP", sep);
+ topt &= ~TF_REQ_TSTMP;
+ sep = ',';
+ }
+# endif /* defined(TF_REQ_TSTMP) */
+
+# if defined(TF_SACK_PERMIT)
+ if (topt & TF_SACK_PERMIT) {
+ (void) printf("%cSACK_PERMIT", sep);
+ topt &= ~TF_SACK_PERMIT;
+ sep = ',';
+ }
+# endif /* defined(TF_SACK_PERMIT) */
+
+# if defined(TF_SENTFIN)
+ if (topt & TF_SENTFIN) {
+ (void) printf("%cSENTFIN", sep);
+ topt &= ~TF_SENTFIN;
+ sep = ',';
+ }
+# endif /* defined(TF_SENTFIN) */
+
+# if defined(TF_USERCLOSE)
+ if (topt & TF_USERCLOSE) {
+ (void) printf("%cUSERCLOSE", sep);
+ topt &= ~TF_USERCLOSE;
+ sep = ',';
+ }
+# endif /* defined(TF_USERCLOSE) */
+
+ if (topt)
+ (void) printf("%cUNKNOWN=%#x", sep, topt);
+ if (Ffield)
+ putchar(Terminator);
+ }
+ }
+#endif /* defined(HASTCPOPT) */
+
+# if defined(HASTCPTPIW)
+ if (Ftcptpi & TCPTPI_WINDOWS) {
+ if (Lf->lts.rws) {
+ if (Ffield)
+ putchar(LSOF_FID_TCPTPI);
+ else {
+ if (ps)
+ putchar(' ');
+ else
+ putchar('(');
+ }
+ (void) printf("WR=%lu", Lf->lts.rw);
+ if (Ffield)
+ putchar(Terminator);
+ ps++;
+ }
+ if (Lf->lts.wws) {
+ if (Ffield)
+ putchar(LSOF_FID_TCPTPI);
+ else {
+ if (ps)
+ putchar(' ');
+ else
+ putchar('(');
+ }
+ (void) printf("WW=%lu", Lf->lts.ww);
+ if (Ffield)
+ putchar(Terminator);
+ ps++;
+ }
+ }
+# endif /* defined(HASTCPTPIW) */
+
+ if (!Ffield && ps)
+ putchar(')');
+ if (nl)
+ putchar('\n');
+}
+
+
+/*
+ * process_socket() - process socket
+ */
+
+void
+process_socket(pr, q)
+ char *pr; /* protocol name */
+ struct queue *q; /* queue at end of stream */
+{
+ unsigned char *fa = (unsigned char *)NULL;
+ int fp, ipv, lp;
+ struct inpcb inp;
+ unsigned char *la = (unsigned char *)NULL;
+ struct tcpcb t;
+ int tcp = 0;
+ short ts = 0;
+ int udp = 0;
+
+/*
+ * Process protocol specification.
+ */
+ Lf->inp_ty = 2;
+ (void) snpf(Lf->iproto, sizeof(Lf->iproto), "%s", pr);
+ Lf->is_stream = 0;
+ if (strcasecmp(pr, "TCP") == 0) {
+ ipv = 4;
+ tcp = 1;
+ } else if (strcasecmp(pr, "UDP") == 0) {
+ ipv = 4;
+ udp = 1;
+ }
+
+#if defined(HASIPv6)
+ else if (strcasecmp(pr, "TCP6") == 0) {
+ ipv = 6;
+ tcp = 1;
+ Lf->iproto[3] = '\0';
+ } else if (strcasecmp(pr, "UDP6") == 0) {
+ ipv = 6;
+ udp = 1;
+ Lf->iproto[3] = '\0';
+ }
+#endif /* defined(HASIPv6) */
+
+ if (Fnet && (tcp || udp)) {
+ if (!FnetTy || (FnetTy == ipv))
+ Lf->sf |= SELNET;
+ }
+
+#if defined(HASIPv6)
+ (void) snpf(Lf->type, sizeof(Lf->type), (ipv == 6) ? "IPv6" : "IPv4");
+#else /* !defined(HASIPv6) */
+ (void) snpf(Lf->type, sizeof(Lf->type), "inet");
+#endif /* defined(HASIPv6) */
+
+/*
+ * The PCB address is found in the private data structure at the end
+ * of the queue.
+ */
+ if (q->q_ptr) {
+ enter_dev_ch(print_kptr((KA_T)q->q_ptr, (char *)NULL, 0));
+ if (tcp || udp) {
+ if (kread((KA_T)q->q_ptr, (char *)&inp, sizeof(inp))) {
+ (void) snpf(Namech, Namechl, "can't read inpcb from %s",
+ print_kptr((KA_T)q->q_ptr, (char *)NULL, 0));
+ enter_nm(Namech);
+ return;
+ }
+ la = (unsigned char *)&inp.inp_laddr;
+ lp = (int)ntohs(inp.inp_lport);
+ if (inp.inp_faddr.s_addr != INADDR_ANY || inp.inp_fport != 0) {
+ fa = (unsigned char *)&inp.inp_faddr;
+ fp = (int)ntohs(inp.inp_fport);
+ }
+ if (fa || la)
+ (void) ent_inaddr(la, lp, fa, fp, AF_INET);
+ if (tcp) {
+ if (inp.inp_ppcb
+ && !kread((KA_T)inp.inp_ppcb, (char *)&t, sizeof(t))) {
+ ts = 1;
+ Lf->lts.type = 0;
+ Lf->lts.state.i = (int)t.t_state;
+ }
+ } else {
+ Lf->lts.type = 1;
+ Lf->lts.state.i = (int)inp.inp_tstate;
+ }
+ } else
+ enter_nm("no address for this protocol");
+ } else
+ enter_nm("no address");
+/*
+ * Save size information.
+ */
+ if (ts) {
+ if (Fsize) {
+
+#if UNIXWAREV>=70000
+#define t_outqsize t_qsize
+#endif /* UNIXWAREV>=70000 */
+
+ if (Lf->access == 'r')
+ Lf->sz = (SZOFFTYPE)t.t_iqsize;
+ else if (Lf->access == 'w')
+ Lf->sz = (SZOFFTYPE)t.t_outqsize;
+ else
+ Lf->sz = (SZOFFTYPE)(t.t_iqsize + t.t_outqsize);
+ Lf->sz_def = 1;
+
+ } else
+ Lf->off_def = 1;
+
+#if defined(HASTCPTPIQ)
+ Lf->lts.rq = (unsigned long)t.t_iqsize;
+ Lf->lts.sq = (unsigned long)t.t_outqsize;
+ Lf->lts.rqs = Lf->lts.sqs = 1;
+#endif /* defined(HASTCPTPIQ) */
+
+#if defined(HASSOOPT)
+ Lf->lts.opt = (unsigned int)inp.inp_protoopt;
+ Lf->lts.ltm = (unsigned int)inp.inp_linger;
+ Lf->lts.pqlen = (unsigned int)t.t_q0len;
+ Lf->lts.qlen = (unsigned int)t.t_qlen;
+ Lf->lts.qlim = (unsigned int)t.t_qlimit;
+ Lf->lts.rbsz = (unsigned long)inp.inp_rbufsize;
+ Lf->lts.sbsz = (unsigned long)inp.inp_sbufsize;
+ Lf->lts.pqlens = Lf->lts.qlens = Lf->lts.qlims = Lf->lts.rbszs
+ = Lf->lts.sbszs = (unsigned char)1;
+#endif /* defined(HASSOOPT) */
+
+#if defined(HASSOSTATE)
+ Lf->lts.ss = (unsigned int)inp.inp_state;
+#endif /* defined(HASSOSTATE) */
+
+#if defined(HASTCPOPT)
+ Lf->lts.mss = (unsigned long)t.t_maxseg;
+ Lf->lts.msss = (unsigned char)1;
+ Lf->lts.topt = (unsigned int)t.t_flags;
+#endif /* defined(HASTCPOPT) */
+
+ }
+ else if (Fsize) {
+ Lf->sz = (SZOFFTYPE)q->q_count;
+ Lf->sz_def = 1;
+ } else
+ Lf->off_def = 1;
+ enter_nm(Namech);
+ return;
+}
+
+
+#if UNIXWAREV>=70101
+/*
+ * process_unix_sockstr() - process a UNIX socket stream, if applicable
+ */
+
+int
+process_unix_sockstr(v, na)
+ struct vnode *v; /* the stream's vnode */
+ KA_T na; /* kernel vnode address */
+{
+ int as;
+ char *ep, tbuf[32], tbuf1[32], *ty;
+ KA_T ka, sa, sh;
+ struct stdata sd;
+ struct ss_socket ss;
+ size_t sz;
+
+# if UNIXWAREV<70103
+ struct sockaddr_un *la, *ra;
+# else /* UNIXWAREV>=70103 */
+ struct sockaddr_un la, ra;
+ unsigned char las = 0;
+ unsigned char ras = 0;
+ int up = (int)(sizeof(la.sun_path) - 1);
+/*
+ * It's serious if the sizeof(sun_path) in sockaddr_un isn't greater than zero.
+ */
+ if (up < 0) {
+ (void) snpf(Namech, Namechl, "sizeof(sun_path) < 1 (%d)", up);
+ enter_nm(Namech);
+ return(1);
+ }
+# endif /* UNIXWAREV<70103 */
+
+/*
+ * Read the stream head, if possible.
+ */
+ if (!(sh = (KA_T)v->v_stream))
+ return(0);
+ if (readstdata(sh, &sd)) {
+ (void) snpf(Namech, Namechl,
+ "vnode at %s; can't read stream head at %s",
+ print_kptr(na, (char *)NULL, 0),
+ print_kptr(sh, tbuf, sizeof(tbuf)));
+ enter_nm(Namech);
+ return(1);
+ }
+/*
+ * If the stream head has pointer to a socket, read the socket structure
+ */
+ if (!(sa = (KA_T)sd.sd_socket))
+ return(0);
+ if (kread(sa, (char *)&ss, sizeof(ss))) {
+ (void) snpf(Namech, Namechl,
+ "vnode at %s; stream head at %s; can't read socket at %s",
+ print_kptr(na, (char *)NULL, 0),
+ print_kptr(sh, tbuf, sizeof(tbuf)),
+ print_kptr(sa, tbuf1, sizeof(tbuf1)));
+ enter_nm(Namech);
+ return(1);
+ }
+/*
+ * If the socket is bound to the PF_UNIX protocol family, process it as
+ * a UNIX socket. Otherwise, return and let the vnode be processed as a
+ * stream.
+ */
+ if (ss.family != PF_UNIX)
+ return(0);
+ (void) snpf(Lf->type, sizeof(Lf->type), "unix");
+ if (Funix)
+ Lf->sf |= SELUNX;
+ Lf->is_stream = 0;
+ if (!Fsize)
+ Lf->off_def = 1;
+ enter_dev_ch(print_kptr(sa, (char *)NULL, 0));
+/*
+ * Process the local address.
+ */
+
+# if UNIXWAREV<70103
+ if ((la = find_unix_sockaddr_un((KA_T)sd.sd_socket))) {
+ if (Sfile && is_file_named(la->sun_path, 0))
+ Lf->sf = SELNM;
+ }
+# else /* UNIXWAREV>=70103 */
+ if (((as = (KA_T)ss.local_addrsz) > 0) && (ka = (KA_T)ss.local_addr))
+ {
+ if (as > sizeof(la))
+ as = (int)sizeof(la);
+ if (!kread(ka, (char *)&la, as)) {
+ la.sun_path[up] = '\0';
+ if (la.sun_path[0]) {
+ las = 1;
+ if (Sfile && is_file_named(la.sun_path, 0))
+ Lf->sf = SELNM;
+ }
+ }
+ }
+# endif /* UNIXWAREV<70103 */
+
+/*
+ * Process the remote address.
+ */
+
+# if UNIXWAREV<70103
+ if ((ra = find_unix_sockaddr_un((KA_T)ss.conn_ux))) {
+ if (Sfile && is_file_named(ra->sun_path, 0))
+ Lf->sf = SELNM;
+ }
+# else /* UNIXWAREV>=70103 */
+ if (((as = (KA_T)ss.remote_addrsz) > 0) && (ka = (KA_T)ss.remote_addr))
+ {
+ if (as > sizeof(la))
+ as = (int)sizeof(ra);
+ if (!kread(ka, (char *)&ra, as)) {
+ ra.sun_path[up] = '\0';
+ if (ra.sun_path[0]) {
+ ras = 1;
+ if (Sfile && is_file_named(ra.sun_path, 0))
+ Lf->sf = SELNM;
+ }
+ }
+ }
+# endif /* UNIXWAREV<70103 */
+
+/*
+ * Start Namech[] with the service type, converted to a name, ala netstat.
+ */
+ switch (ss.servtype) {
+ case T_COTS:
+ case T_COTS_ORD:
+ ty = "stream";
+ break;
+ case T_CLTS:
+ ty = "dgram";
+ break;
+ default:
+ ty = (char *)NULL;
+ }
+ if (ty) {
+ (void) snpf(Namech, Namechl, "%s", ty);
+ ty = ":";
+ } else {
+ Namech[0] = '\0';
+ ty = "";
+ }
+/*
+ * Add names to Namech[].
+ */
+
+#if UNIXWAREV<70103
+ if (la && la->sun_path[0]) {
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "%s%s", ty, la->sun_path);
+ }
+#else /* UNIXWAREV>=70103 */
+ if (las) {
+ ep = endnm(&sz);
+ (void) snpf(ep, sz, "%s%s", ty, la.sun_path);
+ }
+#endif /* UNIXWAREV<70103 */
+
+ ep = endnm(&sz);
+
+#if UNIXWAREV<70103
+ if (ra && ra->sun_path[0])
+ (void) snpf(ep, sz, "->%s", ra->sun_path);
+#else /* UNIXWAREV>=70103 */
+ if (ras)
+ (void) snpf(ep, sz, "->%s", ra.sun_path);
+#endif /* UNIXWAREV<70103 */
+
+ else if ((ka = (KA_T)ss.conn_ux))
+ (void) snpf(ep, sz, "->%s", print_kptr(ka, (char *)NULL, 0));
+ if (Namech[0])
+ enter_nm(Namech);
+ return(1);
+}
+
+
+# if UNIXWAREV<70103
+/*
+ * find_unix_sockaddr_un() -- find UNIX socket address structure
+ *
+ */
+
+static struct sockaddr_un *
+find_unix_sockaddr_un(ka)
+ KA_T ka; /* socket's kernel address */
+{
+ static struct soreq *al = (struct soreq *)NULL;
+ static int alct = 0;
+ int i;
+
+ if (!al) {
+ MALLOC_S alen, len;
+ char *ch = (char *)NULL;
+ int ct, pct;
+ struct strioctl ioc;
+ int sock = -1;
+
+ if (alct < 0)
+ return((struct sockaddr_un *)NULL);
+ /*
+ * If there has been no attempt to acquire the address list yet,
+ * do so.
+ *
+ * Get a SOCK_STREAM PF_UNIX socket descriptor and use ioctl() to
+ * send a stream message to acquire the list of PF_UNIX addresses.
+ */
+ if ((sock = socket (PF_UNIX, SOCK_STREAM, 0)) < 0) {
+
+ /*
+ * Some error was detected. Return allocated resources and
+ * indicate that no further attempts need be made.
+ */
+
+find_err_exit:
+
+ alct = -1;
+ if (sock >= 0)
+ close(sock);
+ if (ch)
+ (void) free((FREE_P *)ch);
+ return((struct sockaddr_un *)NULL);
+ }
+ /*
+ * Read the address list. Before starting, get an estimate of its
+ * size and add a small safety margin.
+ */
+ if ((ct = ioctl(sock, SI_UX_COUNT, 0)) < 0)
+ goto find_err_exit;
+ ct += 32;
+ pct = 0;
+ do {
+ if (ct > pct) {
+
+ /*
+ * If the previously allocated space is insufficient,
+ * or if none has been allocated, allocate space.
+ */
+ alen = (MALLOC_S)(ct * sizeof(struct soreq));
+ if (ch)
+ ch = (char *)realloc((MALLOC_P *)ch, alen);
+ else
+ ch = (char *)malloc(alen);
+ if (!ch)
+ goto find_err_exit;
+ pct = ct;
+ }
+ /*
+ * Read the address list into the allocated space.
+ */
+ ioc.ic_cmd = SI_UX_LIST;
+ ioc.ic_dp = ch;
+ ioc.ic_len = (int)alen;
+ ioc.ic_timout = 0;
+ if ((ct = ioctl(sock, I_STR, &ioc)) < 0)
+ goto find_err_exit;
+ } while (ct > pct);
+ /*
+ * The list has been acquired. Free any excess space pre-allocated to
+ * it, then save its address. Close the stream socket.
+ */
+ alct = ct;
+ if ((len = (MALLOC_S)(alct * sizeof(struct soreq))) < alen) {
+ if (!(ch = (char *)realloc((MALLOC_P *)ch, len)))
+ goto find_err_exit;
+ }
+ al = (struct soreq *)ch;
+ close(sock);
+ }
+/*
+ * Search a previously acquired address list, based on the supplied kernel
+ * socket address. If an entry is found, return a pointer to it, making
+ * sure the path it contains is terminated.
+ */
+ for (i = 0; i < alct; i++) {
+ if ((KA_T)al[i].so_addr == ka)
+ break;
+ }
+ if (i >= alct || !al[i].sockaddr.sun_path[0])
+ return((struct sockaddr_un *)NULL);
+ al[i].sockaddr.sun_path[(int)(sizeof(al[i].sockaddr.sun_path) - 1)]
+ = '\0';
+ return(&al[i].sockaddr);
+}
+# endif /* UNIXWAREV<70103 */
+#endif /* UNIXWAREV>=70101 */
diff --git a/dialects/uw/dstore.c b/dialects/uw/dstore.c
new file mode 100644
index 0000000..4501400
--- /dev/null
+++ b/dialects/uw/dstore.c
@@ -0,0 +1,134 @@
+/*
+ * dstore.c - SCO UnixWare global storage for lsof
+ */
+
+
+/*
+ * Copyright 1996 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 1996 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dstore.c,v 1.8 2000/11/03 18:57:07 abe Exp abe $";
+#endif
+
+
+#include "lsof.h"
+
+
+int CloneMaj; /* clone major device number (see
+ * HaveCloneMaj) */
+
+
+/*
+ * Drive_Nl -- table to drive the building of Nl[] via build_Nl()
+ * (See lsof.h and misc.c.)
+ */
+
+struct drive_Nl Drive_Nl[] = {
+ { "cdev", "cdevsw" }, /* UW < 7 */
+ { "cmaj", "clonemajor" }, /* UW >= 7 */
+ { "ncdev", "cdevswsz" }, /* UW < 7 */
+ { X_NCACHE, "ncache" },
+ { X_NCSIZE, "ncsize" },
+ { "proc", "practive" },
+ { "sgvnops", "segvn_ops" },
+ { "sgdnops", "segdev_ops" },
+ { "var", "v" },
+ { "", "" },
+ { NULL, NULL }
+};
+
+char **Fsinfo = NULL; /* file system information */
+int Fsinfomax = 0; /* maximum file system type */
+int HaveCloneMaj = 0; /* CloneMaj status */
+int Kd = -1; /* /dev/kmem file descriptor */
+short Nfstyp = 0; /* number of fstypsw[] entries */
+
+#if defined(HASFSTRUCT)
+/*
+ * Pff_tab[] - table for printing file flags
+ */
+
+struct pff_tab Pff_tab[] = {
+ { (long)FREAD, FF_READ },
+ { (long)FWRITE, FF_WRITE },
+ { (long)FNDELAY, FF_NDELAY },
+
+# if defined(FDIRECT)
+ { (long)FDIRECT, FF_DIRECT },
+# endif /* defined(FDIRECT) */
+
+ { (long)FAPPEND, FF_APPEND },
+
+# if defined(FASYNC)
+ { (long)FASYNC, FF_ASYNC },
+# endif /* defined(FASYNC) */
+
+ { (long)FSYNC, FF_SYNC },
+
+# if defined(FDSYNC)
+ { (long)FDSYNC, FF_DSYNC },
+# endif /* defined(FDSYNC) */
+
+# if defined(FLARGEFILE)
+ { (long)FLARGEFILE, FF_LARGEFILE },
+# endif /* defined(FLARGEFILE) */
+
+# if defined(FCLONE)
+ { (long)FCLONE, FF_CLONE },
+# endif /* defined(FCLONE) */
+
+# if defined(FILE_MBLK)
+ { (long)FILE_MBLK, FF_FILE_MBLK },
+# endif /* defined(FILE_MBLK) */
+
+ { (long)FNONBLOCK, FF_NBLOCK },
+ { (long)FNOCTTY, FF_NOCTTY },
+
+# if defined(FNMFS)
+ { (long)FNMFS, FF_NMFS },
+# endif /* defined(FNMFS) */
+
+ { (long)0, NULL }
+};
+
+
+/*
+ * Pof_tab[] - table for print process open file flags
+ */
+
+struct pff_tab Pof_tab[] = {
+
+ { (long)FCLOSEXEC, POF_CLOEXEC },
+
+# if defined(UF_FDLOCK)
+ { (long)UF_FDLOCK, POF_FDLOCK },
+# endif /* defined(UF_FDLOCK) */
+
+ { (long)0, NULL }
+};
+#endif /* defined(HASFSTRUCT) */
diff --git a/dialects/uw/machine.h b/dialects/uw/machine.h
new file mode 100644
index 0000000..87f8aca
--- /dev/null
+++ b/dialects/uw/machine.h
@@ -0,0 +1,630 @@
+/*
+ * machine.h - SCO UnixWare definitions for lsof
+ */
+
+
+/*
+ * Copyright 1996 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.
+ */
+
+
+/*
+ * $Id: machine.h,v 1.36 2010/07/29 16:03:02 abe Exp $
+ */
+
+
+#if !defined(LSOF_MACHINE_H)
+#define LSOF_MACHINE_H 1
+
+
+#define _KMEMUSER /* to get _KMEMUSER-influenced types */
+
+# if UNIXWAREV>=70103
+#define _KERNEL 1 /* for rnode.h */
+#define _FSKI 2 /* for rnode.h */
+#endif /* UNIXWAREV>=70103 */
+
+#include <sys/types.h>
+
+# if UNIXWAREV>=70103
+#undef _KERNEL
+#undef _FSKI
+#endif /* UNIXWAREV>=70103 */
+
+#include <sys/param.h>
+
+
+/*
+ * CAN_USE_CLNT_CREATE is defined for those dialects where RPC clnt_create()
+ * can be used to obtain a CLIENT handle in lieu of clnttcp_create().
+ */
+
+#if UNIXWAREV>=20103
+#define CAN_USE_CLNT_CREATE 1
+#endif /* UNIXWAREV>=20103 */
+
+
+/*
+ * DEVDEV_PATH defines the path to the directory that contains device
+ * nodes.
+ */
+
+#define DEVDEV_PATH "/dev"
+
+
+/*
+ * GET_MAX_FD is defined for those dialects that provide a function other than
+ * getdtablesize() to obtain the maximum file descriptor number plus one.
+ */
+
+#define GET_MAX_FD get_max_fd
+
+
+/*
+ * HASAOPT is defined for those dialects that have AFS support; it specifies
+ * that the default path to an alternate AFS kernel name list file may be
+ * supplied with the -A <path> option.
+ */
+
+/* #define HASAOPT 1 */
+
+
+/*
+ * HASBLKDEV is defined for those dialects that want block device information
+ * recorded in BDevtp[].
+ */
+
+#define HASBLKDEV 1
+
+
+/*
+ * HASCDRNODE is defined for those dialects that have CD-ROM nodes.
+ */
+
+/* #define HASCDRNODE 1 */
+
+
+/*
+ * HASDCACHE is defined for those dialects that support a device cache
+ * file.
+ *
+ * HASENVDC defined the name of an environment variable that contains the
+ * device cache file path. The HASENVDC environment variable is ignored when
+ * the lsof process is setuid(root) or its real UID is 0.
+ *
+ * HASPERSDC defines the format for the last component of a personal device
+ * cache file path. The first will be the home directory of the real UID that
+ * executes lsof.
+ *
+ * HASPERSDCPATH defines the environment variable whose value is the middle
+ * component of the personal device cache file path. The middle component
+ * follows the home directory and precedes the results of applying HASPERSDC.
+ * The HASPERSDCPATH environment variable is ignored when the lsof process is
+ * setuid(root) or its real UID is 0.
+ *
+ * HASSYSDC defines a public device cache file path. When it's defined, it's
+ * used as the path from which to read the device cache.
+ *
+ * Consult the 00DCACHE and 00FAQ files of the lsof distribution for more
+ * information on device cache file path construction.
+ */
+
+#define HASDCACHE 1
+#define HASENVDC "LSOFDEVCACHE"
+#define HASPERSDC "%h/%p.lsof_%L"
+#define HASPERSDCPATH "LSOFPERSDCPATH"
+/* #define HASSYSDC "/your/choice/of/path" */
+
+
+/*
+ * HASFIFONODE is defined for those dialects that have FIFO nodes.
+ */
+
+#define HASFIFONODE 1
+
+
+/*
+ * HASFSINO is defined for those dialects that have the file system
+ * inode element, fs_ino, in the lfile structure definition in lsof.h.
+ */
+
+#define HASFSINO 1
+
+
+/*
+ * HASFSTRUCT is defined if the dialect has a file structure.
+ *
+ * FSV_DEFAULT defines the default set of file structure values to list.
+ * It defaults to zero (0), but may be made up of a combination of the
+ * FSV_* symbols from lsof.h.
+ *
+ * HASNOFSADDR -- has no file structure address
+ * HASNOFSFLAGS -- has no file structure flags
+ * HASNOFSCOUNT -- has no file structure count
+ * HASNOFSNADDR -- has no file structure node address
+ */
+
+#define HASFSTRUCT 1
+/* #define FSV_DEFAULT FSV_? | FSV_? | FSV_? */
+/* #define HASNOFSADDR 1 has no file structure address */
+/* #define HASNOFSFLAGS 1 has no file structure flags */
+/* #define HASNOFSCOUNT 1 has no file structure count */
+/* #define HASNOFSNADDR 1 has no file structure node address */
+
+
+/*
+ * HASGNODE is defined for those dialects that have gnodes.
+ */
+
+/* #define HASGNODE 1 */
+
+
+/*
+ * HASHSNODE is defined for those dialects that have High Sierra nodes.
+ */
+
+/* #define HASHSNODE 1 */
+
+
+/*
+ * HASINODE is defined for those dialects that have inodes and wish to
+ * use readinode() from node.c.
+ *
+ * UnixWare has multiple inodes, sized differently.
+ */
+
+/* #define HASINODE 1 */
+
+
+/*
+ * HASINTSIGNAL is defined for those dialects whose signal function returns
+ * an int.
+ */
+
+/* #define HASINTSIGNAL 1 */
+
+
+/*
+ * HASKERNIDCK is defined for those dialects that support the comparison of
+ * the build to running kernel identity.
+ */
+
+#define HASKERNIDCK 1
+
+
+/*
+ * HASKOPT is defined for those systems that support the -k option of
+ * reading the kernel's name list from an optional file.
+ */
+
+#define HASKOPT 1
+
+
+/*
+ * HASLFILEADD is defined for those dialects that need additional elements
+ * in struct lfile. The HASLFILEADD definition is a macro that defines
+ * them. If any of the additional elements need to be preset in the
+ * alloc_lfile() function of proc.c, the SETLFILEADD macro may be defined
+ * to do that.
+ *
+ * If any additional elements need to be cleared in alloc_lfile() or in the
+ * free_proc() function of proc.c, the CLRLFILEADD macro may be defined to
+ * do that. Note that CLRLFILEADD takes one argument, the pointer to the
+ * lfile struct. The CLRLFILEADD macro is expected to expand to statements
+ * that are complete -- i.e., have terminating semi-colons -- so the macro is
+ * called without a terminating semicolon by proc.c.
+ *
+ * The HASXOPT definition may be used to select the conditions under which
+ * private lfile elements are used.
+ */
+
+/* #define HASLFILEADD int ... */
+/* #define CLRLFILEADD(lf) (lf)->... = (type)NULL; */
+/* #define SETLFILEADD Lf->... */
+
+
+/*
+ * HASMNTSTAT indicates the dialect supports the mount stat(2) result option
+ * in its l_vfs and mounts structures.
+ */
+
+/* #define HASMNTSTAT 1 */
+
+
+/*
+ * HASMNTSUP is defined for those dialects that support the mount supplement
+ * option.
+ */
+
+/* #define HASMNTSUP 1 */
+
+
+/*
+ * HASMOPT is defined for those dialects that support the reading of
+ * kernel memory from an alternate file.
+ */
+
+#define HASMOPT 1
+
+
+/*
+ * HASNCACHE is defined for those dialects that have a kernel name cache
+ * that lsof can search. A value of 1 directs printname() to prefix the
+ * cache value with the file system directory name; 2, avoid the prefix.
+ *
+ * NCACHELDPFX is a set of C commands to execute before calling ncache_load().
+ *
+ * NCACHELDSFX is a set of C commands to execute after calling ncache_load().
+ */
+
+#define HASNCACHE 1
+/* #define NCACHELDPFX ??? */
+/* #define NCACHELDSFX ??? */
+
+
+/*
+ * HASNLIST is defined for those systems that use nlist() to acccess
+ * kernel symbols.
+ */
+
+#define HASNLIST 1
+
+
+/*
+ * HASPIPEFN is defined for those dialects that have a special function to
+ * process DTYPE_PIPE file structure entries. Its value is the name of the
+ * function.
+ *
+ * NOTE: don't forget to define a prototype for this function in dproto.h.
+ */
+
+/* #define HASPIPEFN process_pipe? */
+
+
+/*
+ * HASPIPENODE is defined for those dialects that have pipe nodes.
+ */
+
+/* #define HASPIPENODE 1 */
+
+
+/*
+ * HASPMAPENABLED is defined when the reporting of portmapper registration
+ * info is enabled by default.
+ */
+
+/* #define HASPMAPENABLED 1 */
+
+
+/*
+ * HASPPID is defined for those dialects that support identification of
+ * the parent process IDentifier (PPID) of a process.
+ */
+
+#define HASPPID 1
+
+
+/*
+ * HASPRINTDEV, HASPRINTINO, HASPRINTNM, HASPRINTOFF, and HASPRINTSZ
+ * define private dialect-specific functions for printing DEVice numbers,
+ * INOde numbers, NaMes, file OFFsets, and file SiZes. The functions are
+ * called from print_file().
+ */
+
+/* #define HASPRINTDEV print_dev? */
+/* #define HASPRINTINO print_ino? */
+/* #define HASPRINTNM print_nm? */
+/* #define HASPRINTOFF print_off? */
+/* #define HASPRINTSZ print_sz? */
+
+
+/*
+ * HASPRIVFILETYPE and PRIVFILETYPE are defined for dialects that have a
+ * file structure type that isn't defined by a DTYPE_* symbol. They are
+ * used in lib/prfp.c to select the type's processing.
+ *
+ * PRIVFILETYPE is the definition of the f_type value in the file struct.
+ *
+ * HASPRIVFILETYPE is the name of the processing function.
+ */
+
+/* #define HASPRIVFILETYPE process_shmf? */
+/* #define PRIVFILETYPE ?? */
+
+
+/*
+ * HASPRIVNMCACHE is defined for dialects that have a private method for
+ * printing cached NAME column values for some files. HASPRIVNAMECACHE
+ * is defined to be the name of the function.
+ *
+ * The function takes one argument, a struct lfile pointer to the file, and
+ * returns non-zero if it prints a name to stdout.
+ */
+
+/* #define HASPRIVNMCACHE <function name> */
+
+
+/*
+ * HASPRIVPRIPP is defined for dialects that have a private function for
+ * printing IP protocol names. When HASPRIVPRIPP isn't defined, the
+ * IP protocol name printing function defaults to printiprto().
+ */
+
+/* #define HASPRIVPRIPP 1 */
+
+
+/*
+ * HASPROCFS is defined for those dialects that have a proc file system --
+ * usually /proc and usually in SYSV4 derivatives.
+ *
+ * HASFSTYPE is defined as 1 for those systems that have a file system type
+ * string, st_fstype, in the stat() buffer; 2, for those systems that have a
+ * file system type integer in the stat() buffer, named MOUNTS_STAT_FSTYPE;
+ * 0, for systems whose stat(2) structure has no file system type member. The
+ * additional symbols MOUNTS_FSTYPE, RMNT_FSTYPE, and RMNT_STAT_FSTYPE may be
+ * defined in dlsof.h to direct how the readmnt() function in lib/rmnt.c
+ * preserves these stat(2) and getmntent(3) buffer values in the local mounts
+ * structure.
+ *
+ * The defined value is the string that names the file system type.
+ *
+ * The HASPROCFS definition usually must be accompanied by the HASFSTYPE
+ * definition and the providing of an fstype element in the local mounts
+ * structure (defined in dlsof.h).
+ *
+ * The HASPROCFS definition may be accompanied by the HASPINODEN definition.
+ * HASPINODEN specifies that searching for files in HASPROCFS is to be done
+ * by inode number.
+ */
+
+#define HASPROCFS "proc"
+#define HASFSTYPE 1
+
+# if UNIXWAREV>=20102
+#define HASPINODEN 1
+# endif /* UNIXWAREV>=20102 */
+
+
+/*
+ * HASRNODE is defined for those dialects that have rnodes.
+ */
+
+#define HASRNODE 1
+
+
+/*
+ * Define HASSECURITY to restrict the listing of all open files to the
+ * root user. When HASSECURITY is defined, the non-root user may list
+ * only files whose processes have the same user ID as the real user ID
+ * (the one that its user logged on with) of the lsof process.
+ */
+
+/* #define HASSECURITY 1 */
+
+
+/*
+ * If HASSECURITY is defined, define HASNOSOCKSECURITY to allow users
+ * restricted by HASSECURITY to list any open socket files, provide their
+ * listing is selected by the "-i" option.
+ */
+
+/* #define HASNOSOCKSECURITY 1 */
+
+
+/*
+ * HASSETLOCALE is defined for those dialects that have <locale.h> and
+ * setlocale().
+ *
+ * If the dialect also has wide character support for language locales,
+ * HASWIDECHAR activates lsof's wide character support and WIDECHARINCL
+ * defines the header file (if any) that must be #include'd to use the
+ * mblen() and mbtowc() functions.
+ */
+
+#define HASSETLOCALE 1
+
+# if UNIXWAREV>=70104
+#define HASWIDECHAR 1
+# endif /* UNIXWAREV>=70104 */
+
+/* #define WIDECHARINCL <wchar.h> */
+
+
+/*
+ * HASSNODE is defined for those dialects that have snodes.
+ */
+
+#define HASSNODE 1
+
+
+/*
+ * HASTASKS is defined for those dialects that have task reporting support.
+ */
+
+/* #define HASTASKS 1 */
+
+
+/*
+ * HASSOOPT, HASSOSTATE and HASTCPOPT define the availability of information
+ * on socket options (SO_* symbols), socket states (SS_* symbols) and TCP
+ * options.
+ */
+
+#define HASSOOPT 1 /* has socket option information */
+#define HASSOSTATE 1 /* has socket state information */
+#define HASTCPOPT 1 /* has TCP options or flags */
+
+
+/*
+ * Define HASSPECDEVD to be the name of a function that handles the results
+ * of a successful stat(2) of a file name argument.
+ *
+ * For example, HASSPECDEVD() for Darwin makes sure that st_dev is set to
+ * what stat("/dev") returns -- i.e., what's in DevDev.
+ *
+ * The function takes two arguments:
+ *
+ * 1: pointer to the full path name of file
+ * 2: pointer to the stat(2) result
+ *
+ * The function returns void.
+ */
+
+/* #define HASSPECDEVD process_dev_stat */
+
+
+/*
+ * HASSTREAMS is defined for those systems that support streams.
+ */
+
+#define HASSTREAMS 1
+
+
+/*
+ * HASTCPTPIQ is defined for dialects where it is possible to report the
+ * TCP/TPI Recv-Q and Send-Q values produced by netstat.
+ */
+
+#define HASTCPTPIQ 1
+
+
+/*
+ * HASTCPTPIW is defined for dialects where it is possible to report the
+ * TCP/TPI send and receive window sizes produced by netstat.
+ */
+
+/* #define HASTCPTPIW 1 */
+
+
+/*
+ * HASTMPNODE is defined for those dialects that have tmpnodes.
+ */
+
+/* #define HASTMPNODE 1 */
+
+
+/*
+ * HASVNODE is defined for those dialects that use the Sun virtual file
+ * system node, the vnode. BSD derivatives usually do; System V derivatives
+ * prior to R4 usually don't.
+ */
+
+#define HASVNODE 1
+
+
+/*
+ * HASXOPT is defined for those dialects that have an X option. It
+ * defines the text for the usage display. HASXOPT_VALUE defines the
+ * option's default binary value -- 0 or 1.
+ */
+
+/* #define HASXOPT "help text for X option" */
+/* #define HASXOPT_VALUE 1 */
+
+
+/*
+ * INODETYPE and INODEPSPEC define the internal node number type and its
+ * printf specification modifier. These need not be defined and lsof.h
+ * can be allowed to define defaults.
+ *
+ * These are defined here, because they must be used in dlsof.h.
+ */
+
+# if UNIXWAREV>=70000
+#define INODETYPE unsigned long long
+ /* inode number internal storage type */
+#define INODEPSPEC "ll" /* INODETYPE printf specification
+ * modifier */
+# endif /* UNIXWAREV>=70000 */
+
+
+/*
+ * UID_ARG defines the size of a User ID number when it is passed
+ * as a function argument.
+ */
+
+#define UID_ARG long
+
+
+/*
+ * Each USE_LIB_<function_name> is defined for dialects that use the
+ * <function_name> in the lsof library.
+ *
+ * Note: other definitions and operations may be required to condition the
+ * library function source code. They may be found in the dialect dlsof.h
+ * header files.
+ */
+
+#define USE_LIB_CKKV 1 /* ckkv.c */
+/* #define USE_LIB_COMPLETEVFS 1 cvfs.c */
+#define USE_LIB_FIND_CH_INO 1 /* fino.c */
+#define USE_LIB_IS_FILE_NAMED 1 /* isfn.c */
+#define USE_LIB_LKUPDEV 1 /* lkud.c */
+#define USE_LIB_PRINTDEVNAME 1 /* pdvn.c */
+/* #define USE_LIB_PROCESS_FILE 1 prfp.c */
+/* #define USE_LIB_PRINT_TCPTPI 1 ptti.c */
+#define USE_LIB_READDEV 1 /* rdev.c */
+/* #define USE_LIB_READMNT 1 rmnt.c */
+/* #define USE_LIB_REGEX 1 regex.c */
+/* #define USE_LIB_RNAM 1 rnam.c */
+#define USE_LIB_RNCH 1 /* rnch.c */
+/* #define USE_LIB_RNMH 1 rnmh.c */
+/* #define USE_LIB_SNPF 1 snpf.c */
+#define snpf snprintf /* use the system's snprintf() */
+
+
+/*
+ * WARNDEVACCESS is defined for those dialects that should issue a warning
+ * when lsof can't access /dev (or /device) or one of its sub-directories.
+ * The warning can be inhibited by the lsof caller with the -w option.
+ */
+
+#define WARNDEVACCESS 1
+
+
+/*
+ * WARNINGSTATE is defined for those dialects that want to suppress all lsof
+ * warning messages.
+ */
+
+/* #define WARNINGSTATE 1 warnings are enabled by default */
+
+
+/*
+ * WILLDROPGID is defined for those dialects whose lsof executable runs
+ * setgid(not_real_GID) and whose setgid power can be relinquished after
+ * the dialect's initialize() function has been executed.
+ */
+
+#define WILLDROPGID 1
+
+
+/*
+ * zeromem is a macro that uses bzero or memset.
+ */
+
+#define zeromem(a, l) memset(a, 0, l)
+
+#endif /* !defined(LSOF_MACHINE_H) */
diff --git a/dialects/uw/uw7/README b/dialects/uw/uw7/README
new file mode 100644
index 0000000..27f8588
--- /dev/null
+++ b/dialects/uw/uw7/README
@@ -0,0 +1,6 @@
+Some header files in this subdirectory tree are Copyright (c) The Santa
+Cruz Operation, Inc. They are reproduced, either in their original or
+corrected forms with permission.
+
+Vic Abell
+March 31, 1998
diff --git a/dialects/uw/uw7/fs/nsc_cfs/cnode.h b/dialects/uw/uw7/fs/nsc_cfs/cnode.h
new file mode 100644
index 0000000..dfdbd89
--- /dev/null
+++ b/dialects/uw/uw7/fs/nsc_cfs/cnode.h
@@ -0,0 +1,78 @@
+/*
+ * cnode.h -- Vic Abell's definition of an nsc_cfs node - with help from
+ * the kind folks at SCO
+ */
+
+
+/*
+ * Copyright 2001 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.
+ */
+
+#if !defined(FS_NSC_CFS_CNODE_H)
+#define FS_NSC_CFS_CNODE_H 1
+
+#include <sys/nsc_synch.h>
+
+
+/*
+ * chandle_t definition from the kernel's <fs/nsc_cfs/cfs.h>
+ */
+
+#define CFS_FHSIZE 44
+
+typedef struct cfhandle {
+ char fh_data[CFS_FHSIZE];
+} cfhandle_t;
+
+
+/*
+ * CFS node structure
+ */
+
+typedef struct cnode {
+ struct cnode *c_freef; /* free list forward pointer */
+ struct cnode *c_freeb; /* free list back pointer */
+ struct cnode *c_hash; /* cnode hash chain */
+ struct vnode c_vnode; /* vnode for remote file */
+ cfhandle_t c_fh; /* file handle */
+ void *c_hp; /* Hash pointer */
+ u_long c_flags; /* flags, see below */
+ union {
+ daddr_t C_nextr; /* next byte read offset (read-ahead) */
+ int C_lastcookie; /* last readdir cookie */
+ } c_c;
+ long c_owner; /* proc index for locker of cnode */
+ long c_count; /* number of cnode locks for c_owner */
+ long c_lwpid; /* lwp id of locker of cnode */
+ CONDITION_T c_cxlock; /* Synch structure */
+ int c_rw_excl; /* RW locked exclusively */
+ /* Credentials here are only for use by cfs-as-nfs-client. */
+ struct cred *c_cred; /* current credentials */
+ struct vattr c_attr; /* cached vnode attributes */
+/*
+ * Lsof needs nothing below c_attr.
+ */
+} cnode_t;
+#endif /* !defined(FS_NSC_CFS_CNODE_H) */
diff --git a/dialects/uw/uw7/fs/procfs/README b/dialects/uw/uw7/fs/procfs/README
new file mode 100644
index 0000000..4b07b74
--- /dev/null
+++ b/dialects/uw/uw7/fs/procfs/README
@@ -0,0 +1,4 @@
+This directory applies to UnixWare 2.1.2 and above.
+
+Vic Abell
+February 16, 1998
diff --git a/dialects/uw/uw7/fs/procfs/prdata.h b/dialects/uw/uw7/fs/procfs/prdata.h
new file mode 100644
index 0000000..e7130b0
--- /dev/null
+++ b/dialects/uw/uw7/fs/procfs/prdata.h
@@ -0,0 +1,228 @@
+#ifndef _FS_PROCFS_PRDATA_H /* wrapper symbol for kernel use */
+#define _FS_PROCFS_PRDATA_H /* subject to change without notice */
+
+#ident "@(#)kern:fs/procfs/prdata.h 1.19.2.1"
+#ident "$Header: $"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#ifdef _KERNEL_HEADERS
+
+#include <fs/vnode.h> /* SVR4.2COMPAT */
+#include <io/uio.h> /* SVR4.0COMPAT */
+#include <mem/seg.h> /* SVR4.0COMPAT */
+#include <proc/proc.h> /* REQUIRED */
+#include <util/ksynch.h> /* REQUIRED */
+#include <util/types.h> /* REQUIRED */
+
+#elif defined(_KERNEL)
+
+#include <sys/vnode.h> /* SVR4.2COMPAT */
+#include <sys/uio.h> /* SVR4.0COMPAT */
+#include <vm/seg.h> /* SVR4.0COMPAT */
+#include <sys/proc.h> /* REQUIRED */
+#include <sys/ksynch.h> /* REQUIRED */
+#include <sys/types.h> /* REQUIRED */
+
+#endif /* _KERNEL_HEADERS */
+
+#if defined(_KERNEL) || defined(_KMEMUSER)
+
+/*
+ * Common file object to which all /proc vnodes for a specific process
+ * or LWP refer.
+ */
+typedef struct prcommon {
+ lock_t prc_mutex; /* Lock for prc_flags and prc_rdwriters */
+ uchar_t prc_flags; /* flags */
+ ulong_t prc_rdwriters; /* # holding or queued for process r/w lock
+
+
+
+*/
+ sv_t prc_rdwrdone; /* sync object to wait for r/w refs done */
+ sv_t prc_stopsv; /* sync object to wait for proc or LWP stop
+
+
+
+*/
+ struct pollhead *prc_pollhead; /* Pointer to list of pollers */
+ pid_t prc_pid; /* process-ID */
+ uint_t prc_opens; /* Number of opens of prnodes */
+ uint_t prc_writers; /* Number of write opens of prnodes */
+ proc_t *prc_proc; /* Associated process */
+ lwp_t *prc_lwp; /* Associated LWP */
+ lwpid_t prc_lwpid; /* LWP id */
+ int prc_slot; /* Associated process slot number */
+} prcommon_t;
+
+/* prc_flags */
+#define PRC_DESTROY 0x01 /* process or LWP is being destroyed */
+#define PRC_LWP 0x02 /* structure refers to an LWP */
+#define PRC_SYS 0x04 /* process is a system process */
+
+/*
+ * prc_mutex: Per prcommon structure lock protecting fields within
+ * a prcommon structure.
+ */
+extern lkinfo_t prc_mutex_lkinfo;
+
+/*
+ * Node types for /proc files (directories and files contained therein).
+ */
+typedef enum prnodetype {
+ PR_PROCDIR, /* 00 /proc */
+ PR_PIDDIR, /* 01 /proc/pid */
+ PR_AS, /* 02 /proc/pid/as */
+ PR_CTL, /* 03 /proc/pid/ctl */
+ PR_STATUS, /* 04 /proc/pid/status */
+ PR_PSINFO, /* 05 /proc/pid/psinfo */
+ PR_MAP, /* 06 /proc/pid/map */
+ PR_CRED, /* 07 /proc/pid/cred */
+ PR_SIGACT, /* 08 /proc/pid/sigact */
+ PR_OBJECTDIR, /* 09 /proc/pid/object */
+ PR_LWPDIR, /* 0A /proc/pid/lwp */
+ PR_LWPIDDIR, /* 0B /proc/pid/lwp/lwpid */
+ PR_LWPCTL, /* 0C /proc/pid/lwp/lwpid/lwpctl */
+ PR_LWPSTATUS, /* 0D /proc/pid/lwp/lwpid/lwpstatus */
+ PR_LWPSINFO /* 0F /proc/pid/lwp/lwpid/lwpsinfo */
+} prnodetype_t;
+
+typedef struct prnode {
+ lock_t pr_mutex; /* Locks pr_flags and child
+pr_files */
+ prnodetype_t pr_type; /* Node type */
+ mode_t pr_mode; /* File mode */
+ ino_t pr_ino; /* Node id (for stat(2)) */
+ ulong_t pr_flags; /* Private flags */
+ prcommon_t *pr_common; /* common data structure */
+ prcommon_t *pr_pcommon; /* process common data structure */
+ struct vnode *pr_parent; /* Parent directory */
+ struct vnode **pr_files; /* Contained files (for directory)
+*/
+ struct vnode *pr_next; /* List in chain of (invalid)
+vnodes */
+ uint_t pr_index; /* Position within parent */
+ struct vnode pr_vnode; /* Embedded vnode */
+} prnode_t;
+
+/*
+ * Values for pr_flags.
+ */
+#define PR_INVAL 0x01 /* Vnode is invalidated */
+
+
+#define VTOP(vp) ((prnode_t *)((vp)->v_data))
+#define PTOV(pnp) (&(pnp)->pr_vnode)
+
+/*
+ * Tables used by prmakenode() in constructing a /proc vnode from
+ * a <directory, name> pair.
+ */
+typedef struct prntable {
+ char *prn_comp; /* Name within directory */
+ prnodetype_t prn_ctype; /* Node type of result vnode */
+ int prn_zvisible; /* Visibility if a zombie */
+ int prn_nasvisible; /* Visibility if no address space
+*/
+ vtype_t prn_ftype; /* File type of result vnode */
+ mode_t prn_mode; /* File mode of result vnode */
+} prntable_t;
+
+
+#endif /* _KERNEL || _KMEMUSER */
+
+
+#ifdef _KERNEL
+
+/*
+ * pr_mutex: Per-structure lock protecting the pr_files field
+ * and the pr_flags field of a child.
+ */
+extern lkinfo_t pr_mutex_lkinfo;
+
+extern prntable_t pdtable[], ldtable[];
+extern int npdent, nldent;
+
+extern struct vnodeops prvnodeops;
+extern struct vfs *procvfs;
+extern dev_t procdev;
+
+struct pstatus;
+struct psinfo;
+struct lwpstatus;
+struct lwpsinfo;
+struct pfamily;
+
+extern ulong_t prsize(prnode_t *);
+extern void prgetsigact(proc_t *, struct sigaction *);
+extern void prgetaction(proc_t *, int, struct sigaction *);
+extern int prusrio(proc_t *, enum uio_rw, struct uio *);
+extern lwp_t *prchoose(proc_t *);
+extern greg_t prgetpc(gregset_t);
+extern int prgetscall(gregset_t);
+extern caddr_t prgetpsaddr(lwp_t *);
+extern void prdebugon(lwp_t *);
+extern void prdebugoff(lwp_t *);
+extern void prgetpfamily(const user_t *up, struct pfamily *fp);
+extern int prwritectl_family(ulong_t, vnode_t *, uio_t *, int, cred_t
+*);
+extern boolean_t pr_p_rdwr(prcommon_t *, boolean_t);
+extern void pr_v_rdwr(prcommon_t *);
+extern boolean_t pr_p_mutex(prcommon_t *);
+#ifdef DEBUG
+extern int prfilesempty(vnode_t **, int);
+#endif
+extern int prvpsegs(proc_t *, vnode_t **);
+extern void prmapname(vnode_t *, char *, ino_t *, cred_t *);
+extern int prcountsegs(struct as *);
+extern int prnsegs(struct as *);
+extern int setisempty(ulong_t *, unsigned int);
+extern int prgetpstatus(proc_t *, struct pstatus *);
+extern void prgetpsinfo(proc_t *, struct psinfo *);
+extern int prgetlwpstatus(lwp_t *, struct lwpstatus *);
+extern void prgetlwpsinfo(lwp_t *, struct lwpsinfo *);
+extern void prchlvl(lid_t);
+
+#define prino(slot, lwpid, type) (((lwpid)<<18) | ((slot)<<5) | type + 2)
+
+/*
+ * Is an LWP stopped on an event of interest to /proc?
+ */
+#define ISTOP(lwp) ((lwp)->l_stat == SSTOP \
+ && ((lwp)->l_whystop == PR_REQUESTED \
+ || (lwp)->l_whystop == PR_SIGNALLED \
+ || (lwp)->l_whystop == PR_SYSENTRY \
+ || (lwp)->l_whystop == PR_SYSEXIT \
+ || (lwp)->l_whystop == PR_FAULTED))
+
+/*
+ * Assign one set to another (possible different sizes).
+ *
+ * Assigning to a smaller set causes members to be lost.
+ * Assigning to a larger set causes extra members to be cleared.
+ */
+#define prassignset(ap, sp) \
+{ \
+ register int _i_ = sizeof(*(ap))/sizeof(ulong_t); \
+ while (--_i_ >= 0) \
+ ((ulong_t*)(ap))[_i_] = \
+ (_i_ >= sizeof(*(sp))/sizeof(ulong_t)) ? \
+ 0L : ((ulong_t*)(sp))[_i_]; \
+}
+
+/*
+ * Determine whether or not a set (of arbitrary size) is empty.
+ */
+#define prisempty(sp) setisempty((ulong_t *)(sp),
+sizeof(*(sp))/sizeof(ulong_t))
+
+#endif /* _KERNEL */
+
+#if defined(__cplusplus)
+ }
+#endif
+
+#endif /* _FS_PROCFS_PRDATA_H */
diff --git a/dialects/uw/uw7/sys/fs/README b/dialects/uw/uw7/sys/fs/README
new file mode 100644
index 0000000..441b270
--- /dev/null
+++ b/dialects/uw/uw7/sys/fs/README
@@ -0,0 +1,6 @@
+The header files in this subdirectory tree are Copyright (c) The Santa
+Cruz Operation, Inc. They are reproduced here, either in their original
+or corrected forms with permission.
+
+Vic Abell
+March 31, 1998
diff --git a/dialects/uw/uw7/sys/fs/fifonode.h b/dialects/uw/uw7/sys/fs/fifonode.h
new file mode 100644
index 0000000..39a6857
--- /dev/null
+++ b/dialects/uw/uw7/sys/fs/fifonode.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 1998 The Santa Cruz Operation, Inc.. All Rights Reserved.
+ *
+ * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF THE
+ * SANTA CRUZ OPERATION INC.
+ *
+ * The copyright notice above does not evidence any actual or intended
+ * publication of such source code.
+ */
+
+#ifndef _FS_FIFOFS_FIFONODE_H /* wrapper symbol for kernel use */
+#define _FS_FIFOFS_FIFONODE_H /* subject to change without notice */
+
+#ident "@(#)kern:fs/fifofs/fifonode.h 1.14"
+#ident "$Header: $"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#ifdef _KERNEL_HEADERS
+
+#include <util/types.h> /* REQUIRED */
+#include <util/ksynch.h> /* REQUIRED */
+#include <fs/vnode.h> /* REQUIRED */
+
+#elif defined(_KERNEL) || defined(_KMEMUSER)
+
+#include <sys/types.h> /* REQUIRED */
+#include <sys/ksynch.h> /* REQUIRED */
+#include <sys/vnode.h> /* REQUIRED */
+
+#endif /* _KERNEL_HEADERS */
+
+#if defined(_KERNEL) || defined(_KMEMUSER)
+
+struct nodelock {
+ lock_t n_lock;
+ int n_count;
+};
+
+/*
+ * Each FIFOFS object is identified by a struct fifonode/vnode pair.
+ */
+struct fifonode {
+ struct vnode fn_vnode; /* represents the fifo/pipe */
+ struct vnode *fn_mate; /* the other end of a pipe */
+ struct vnode *fn_realvp; /* node being shadowed by fifo */
+ sleep_t fn_iolock; /* fifonode iolock */
+ sv_t fn_rwait; /* wait for first reader */
+ sv_t fn_wwait; /* wait for first writer */
+ sv_t fn_fdwait; /* to synchronize fd passing */
+ sv_t fn_openwait; /* to serialize fifo_open */
+ ino_t fn_ino; /* node id for pipes */
+ short fn_wcnt; /* number of writers */
+ short fn_rcnt; /* number of readers */
+ short fn_open; /* open count of node*/
+ ushort fn_flag; /* flags as defined below */
+ struct vnode *fn_unique; /* new vnode created by CONNLD */
+ time_t fn_atime; /* creation times for pipe */
+ time_t fn_mtime;
+ time_t fn_ctime;
+ struct fifonode *fn_nextp; /* next link in the linked list */
+ struct fifonode *fn_backp; /* back link in linked list */
+ struct nodelock *fn_nodelp; /* lock shared by both ends of a pipe */
+};
+
+#endif /* _KERNEL || _KMEMUSER */
+
+#ifdef _KERNEL
+
+/*
+ * Valid flags for fifonodes.
+ */
+#define ISPIPE 01 /* fifonode is that of a pipe */
+#define FIFOWOPEN 02 /* open in progress */
+#define FIFOWCLOSE 04 /* close in progress */
+#define FIFOSEND 010 /* file descriptor at stream head of pipe */
+#define FIFOPASS 020 /* CONNLD passed a new vnode in fn_unique */
+#define FIFOMACPRIV 040 /* bypass MAC checks for privilege process */
+#define CONNLDPUSHED 0100 /* CONNLD is pushed */
+#define FIFOMODTIME 0200 /* access/modification/change time modified */
+
+#define FIFOBSIZE 1024 /* FIFOFS block size */
+
+/* #ifdef MERGE */
+extern int fifo_rdchk(vnode_t *);
+/* #endif MERGE */
+
+/*
+ * Macros to convert a vnode to a fifonode, and vice versa.
+ */
+#define VTOF(vp) ((struct fifonode *)((vp)->v_data))
+#define FTOV(fp) (&(fp)->fn_vnode)
+
+/*
+ * Functions used in multiple places.
+ */
+extern int fifo_rdchk(vnode_t *);
+extern int fifo_mkpipe(vnode_t **, vnode_t **, cred_t *);
+extern void fifo_rmpipe(vnode_t *, vnode_t *, cred_t *);
+
+/*
+ * Macros for manipulating locks and synchronization variables
+ */
+
+/*
+ * Macros called by fifovp() and fifo_inactive()
+ * to avoid a race on the vnode.
+ */
+#define FIFO_LOCK(fp, lockp) \
+ SLEEP_LOCK_RELLOCK(&(fp)->fn_iolock, PRIPIPE, lockp)
+#define FIFO_TRYLOCK(fp) SLEEP_TRYLOCK(&(fp)->fn_iolock)
+#define FIFO_LOCKBLKD(fp) SLEEP_LOCKBLKD(&(fp)->fn_iolock)
+#define FIFO_UNLOCK(fp) SLEEP_UNLOCK(&(fp)->fn_iolock)
+
+/*
+ * Macro to manipulate fn_nodelp->n_lock.
+ */
+#define PIPE_LOCK(fp) LOCK(&(fp)->fn_nodelp->n_lock, PLFIFO)
+#define PIPE_UNLOCK(fp, pl) UNLOCK(&(fp)->fn_nodelp->n_lock, pl)
+
+/*
+ * Macro to manipulate fn_fdwait.
+ * While waiting on fn_fdwait, fn_nodelp->n_lock is dropped.
+ */
+#define FIFO_FDWAIT(fp) \
+ SV_WAIT_SIG(&(fp)->fn_fdwait, PRIPIPE, &(fp)->fn_nodelp->n_lock)
+#define FIFO_FDWAKEUP(fp) SV_SIGNAL(&(fp)->fn_fdwait, 0)
+
+/*
+ * Macro to obtain and release the stream head mutex, sd_mutex
+ */
+#define STREAM_LOCK(stp) LOCK((stp)->sd_mutex, PLSTR);
+#define STREAM_UNLOCK(stp, pl) UNLOCK((stp)->sd_mutex, pl);
+
+#endif /* _KERNEL */
+
+#if defined(__cplusplus)
+ }
+#endif
+
+#endif /* _FS_FIFOFS_FIFONODE_H */
diff --git a/dialects/uw/uw7/sys/fs/namenode.h b/dialects/uw/uw7/sys/fs/namenode.h
new file mode 100644
index 0000000..2c92a0a
--- /dev/null
+++ b/dialects/uw/uw7/sys/fs/namenode.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 1998 The Santa Cruz Operation, Inc.. All Rights Reserved.
+ *
+ * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF THE
+ * SANTA CRUZ OPERATION INC.
+ *
+ * The copyright notice above does not evidence any actual or intended
+ * publication of such source code.
+ */
+
+#ifndef _FS_NAMEFS_NAMENODE_H /* wrapper symbol for kernel use */
+#define _FS_NAMEFS_NAMENODE_H /* subject to change without notice */
+
+#ident "@(#)kern:fs/namefs/namenode.h 1.13.2.1"
+#ident "$Header: $"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#ifdef _KERNEL_HEADERS
+
+#include <util/types.h> /* REQUIRED */
+#include <util/ksynch.h> /* REQUIRED */
+#include <fs/vnode.h> /* REQUIRED */
+#include <acc/dac/acl.h> /* REQUIRED */
+
+#elif defined(_KERNEL) || defined(_KMEMUSER)
+
+#include <sys/types.h> /* REQUIRED */
+#include <sys/ksynch.h> /* REQUIRED */
+#include <sys/vnode.h> /* REQUIRED */
+#include <sys/acl.h> /* REQUIRED */
+
+#endif /* _KERNEL_HEADERS */
+
+/*
+ * This structure is used to pass a file descriptor from user
+ * level to the kernel. It is first used by fattach() and then
+ * be NAMEFS.
+ */
+struct namefd {
+ int fd;
+};
+
+#if defined(_KERNEL) || defined(_KMEMUSER)
+
+/*
+ * Each NAMEFS object is identified by a struct namenode/vnode pair.
+ */
+struct namenode {
+ struct vnode nm_vnode; /* represents mounted file desc.*/
+ ushort nm_flag; /* flags defined below */
+ struct vattr nm_vattr; /* attributes of mounted file desc.*/
+ struct vnode *nm_filevp; /* file desc. prior to mounting */
+ struct file *nm_filep; /* file pointer of nm_filevp */
+ struct vnode *nm_mountpt; /* mount point prior to mounting */
+ struct namenode *nm_nextp; /* next link in the linked list */
+ struct namenode *nm_backp; /* back link in linked list */
+ struct acl *nm_aclp; /* ACL entries */
+ rwsleep_t nm_lock; /* protects namenode */
+};
+
+#endif /* _KERNEL || _KMEMUSER */
+
+#ifdef _KERNEL
+
+/*
+ * Valid flags for namenodes.
+ */
+#define NMUNMOUNT 01 /* the namenode is unmounted */
+#define NMREMOVED 02 /* the namenode is removed from namenode list */
+#define NMREAD 04 /* the mount file has FREAD set */
+#define NMWRITE 010 /* the mount file has FWRITE set */
+
+/*
+ * Constants.
+ */
+#define NMBSIZE 1024 /* NAMEFS block size */
+#define NMFSIZE 1024 /* NAMEFS fundamental block size */
+
+/*
+ * Macros to convert a vnode to a namenode, and vice versa.
+ */
+#define VTONM(vp) ((struct namenode *)((vp)->v_data))
+#define NMTOV(nm) (&(nm)->nm_vnode)
+
+#define STREAM_LOCK(stp) LOCK((stp)->sd_mutex, PLSTR);
+#define STREAM_UNLOCK(stp, pl) UNLOCK((stp)->sd_mutex, pl);
+
+extern int nm_tflush; /* the frequency of flush namefs */
+extern int namefs_fstype; /* index into vfssw returned by vfs_attach */
+
+#endif /* _KERNEL */
+
+#if defined(__cplusplus)
+ }
+#endif
+
+#endif /* _FS_NAMEFS_NAMENODE_H */
diff --git a/lsof.8 b/lsof.8
index a0b7212..cab4a6f 100644
--- a/lsof.8
+++ b/lsof.8
@@ -1,4 +1,4 @@
-.ds VN 4.87
+.ds VN 4.88
.TH LSOF 8 Revision-\*(VN
.if !\n()P .nr )P 1v
.SH NAME
@@ -20,6 +20,8 @@ lsof \- list open files
] [
.BI +|\-e " s"
] [
+.B +|-E
+] [
.B +|\-f [cfgGn]
] [
.BI \-F " [f]"
@@ -67,8 +69,7 @@ opened by processes for the following UNIX dialects:
.PP
.nf
Apple Darwin 9 and Mac OS X 10.[567]
- FreeBSD 4.9 and 6.4 for x86-based systems
- FreeBSD 8.2, 9.0 and 10.0 for AMD64-based systems
+ FreeBSD 8.[234], 9.0, 10.0 and 11.0 for AMD64-based systems
Linux 2.1.72 and above for x86-based systems
Solaris 9, 10 and 11
.fi
@@ -635,6 +636,29 @@ is added in parentheses to the end of the NAME column.
.BI +|\-m " m"
option.)
.TP \w'names'u+4
+.B +|-E
+.B +E
+specifies that Linux files should be displayed with endpoint
+information and the files of the endpoints should also be
+displayed.
+.IP
+Endpoint information is displayed in the NAME column in the
+form ``\fIPID,cmd,FDmode\fP''.
+.I PID
+is the endpoint process ID;
+.I cmd
+is the endpoint process command;
+.I FD
+is the endpoint file's descriptor; and
+.I mode
+is the endpoint file's access mode.
+Multiple occurrences of this information can appear in a file's
+NAME column.
+.IP
+.B -E
+specfies that Linux pipe files should only be displayed with endpoint
+information.
+.TP \w'names'u+4
.B +|\-f [cfgGn]
.B f
by itself clarifies how path name arguments are to be interpreted.
@@ -3146,7 +3170,7 @@ The single character listed first is the field identifier.
C file structure share count
d file's device character code
D file's major/minor device number (0x<hexadecimal>)
- f file descriptor
+ f file descriptor (always selected)
F file structure address (0x<hexadecimal>)
G file flaGs (0x<hexadecimal>; names if \fB+fg\fP follows)
g process group ID
diff --git a/lsof.h b/lsof.h
index afaa56a..b524440 100644
--- a/lsof.h
+++ b/lsof.h
@@ -31,7 +31,7 @@
/*
- * $Id: lsof.h,v 1.66 2013/01/02 17:14:59 abe Exp $
+ * $Id: lsof.h,v 1.67 2014/10/13 22:36:20 abe Exp $
*/
@@ -455,6 +455,12 @@ extern int ZoneColW;
* by PID or UID */
#define PS_SEC 2 /* secondary process selection -- e.g.,
* by directory or file */
+
+# if defined(HASEPTOPTS)
+#define PS_PIPE 1 /* process has a pipe file */
+#define PS_PIPE_END 2 /* process has a pipe end point file */
+# endif /* defined(HASEPTOPTS) */
+
#define SELCMD 0x0001 /* select process by command name */
#define SELCNTX 0x0002 /* select security context (-Z) */
#define SELFD 0x0004 /* select file by descriptor name */
@@ -470,6 +476,8 @@ extern int ZoneColW;
#define SELZONE 0x1000 /* select zone (-z) */
#define SELEXCLF 0x2000 /* file selection excluded */
#define SELTASK 0x4000 /* select tasks (-K) */
+#define SELPINFO 0x8000 /* selected for pipe info (cleared in
+ * link_lfile() */
#define SELALL (SELCMD|SELCNTX|SELFD|SELNA|SELNET|SELNM|SELNFS|SELPID|SELUID|SELUNX|SELZONE|SELTASK)
#define SELPROC (SELCMD|SELCNTX|SELPGID|SELPID|SELUID|SELZONE|SELTASK)
/* process selecters */
@@ -545,6 +553,16 @@ struct pff_tab { /* print file flags table structure */
};
# endif /* defined(HASFSTRUCT) */
+# if defined(HASEPTOPTS)
+typedef struct pinfo { /* hashed pipe inode numbers */
+ INODETYPE ino; /* pipe's inode */
+ struct lfile *lf; /* connected pipe file */
+ int lpx; /* connected process index */
+ struct pinfo *next; /* next entry for hashed inode */
+} pinfo_t;
+# endif /* defined(HASEPTOPTS) */
+
+
struct seluid {
uid_t uid; /* User ID */
char *lnm; /* specified login name (NULL = none) */
@@ -621,6 +639,8 @@ extern int Fnfs;
extern int Fnlink;
extern int Foffset;
extern int Fovhd;
+extern int FpipeE;
+
extern int Fport;
# if !defined(HASNORPC_H)
@@ -703,6 +723,11 @@ struct lfile {
unsigned char nlink_def; /* link count definition status */
unsigned char off_def; /* offset definition status */
+
+# if defined(HASEPTOPTS)
+ unsigned char pipend; /* pipe endpoint file */
+# endif /* defined(HASEPTOPTS) */
+
unsigned char rdev_def; /* rdev definition status */
unsigned char sz_def; /* size definition status */
@@ -838,6 +863,10 @@ struct lproc {
short pss; /* state: 0 = not selected
* 1 = wholly selected
* 2 = partially selected */
+# if defined(HASEPTOPTS)
+ short pipe; /* pipe status -- PS_PIPE* values */
+# endif /* defined(HASEPTOPTS) */
+
int pid; /* process ID */
# if defined(HASTASKS)
@@ -856,6 +885,7 @@ struct lproc {
};
extern struct lproc *Lp, *Lproc;
+extern int MaxFd;
extern char *Memory;
extern int MntSup;
extern char *MntSupP;
diff --git a/lsof.man b/lsof.man
index 158d45e..e109a42 100644
--- a/lsof.man
+++ b/lsof.man
@@ -10,20 +10,19 @@ NAME
SYNOPSIS
lsof [ -?abChKlnNOPRtUvVX ] [ -A A ] [ -c c ] [ +c c ] [
- +|-d d ] [ +|-D D ] [ +|-e s ] [ +|-f [cfgGn] ] [ -F [f] ] [
- -g [s] ] [ -i [i] ] [ -k k ] [ +|-L [l] ] [ +|-m m ] [ +|-M
- ] [ -o [o] ] [ -p s ] [ +|-r [t[m<fmt>]] ] [ -s [p:s] ] [ -S
- [t] ] [ -T [t] ] [ -u s ] [ +|-w ] [ -x [fl] ] [ -z [z] ] [
- -Z [Z] ] [ -- ] [names]
+ +|-d d ] [ +|-D D ] [ +|-e s ] [ +|-E ] [ +|-f [cfgGn] ] [
+ -F [f] ] [ -g [s] ] [ -i [i] ] [ -k k ] [ +|-L [l] ] [ +|-m
+ m ] [ +|-M ] [ -o [o] ] [ -p s ] [ +|-r [t[m<fmt>]] ] [ -s
+ [p:s] ] [ -S [t] ] [ -T [t] ] [ -u s ] [ +|-w ] [ -x [fl] ]
+ [ -z [z] ] [ -Z [Z] ] [ -- ] [names]
DESCRIPTION
- Lsof revision 4.87 lists on its standard output file infor-
+ Lsof revision 4.88 lists on its standard output file infor-
mation about files opened by processes for the following
UNIX dialects:
Apple Darwin 9 and Mac OS X 10.[567]
- FreeBSD 4.9 and 6.4 for x86-based systems
- FreeBSD 8.2, 9.0 and 10.0 for AMD64-based systems
+ FreeBSD 8.[234], 9.0, 10.0 and 11.0 for AMD64-based systems
Linux 2.1.72 and above for x86-based systems
Solaris 9, 10 and 11
@@ -57,10 +56,11 @@ OPTIONS
listed unless -N is also specified; or if a user list is
specified with the -u option, UNIX domain socket files,
belonging to users not in the list, won't be listed unless
+ the -U option is also specified.
-SunOS 5.9 Last change: Revision-4.87 1
+SunOS 5.9 Last change: Revision-4.88 1
@@ -71,8 +71,6 @@ Maintenance Procedures LSOF(8)
- the -U option is also specified.
-
Normally list options that are specifically stated are ORed
- i.e., specifying the -i option without an address and the
-ufoo option produces a listing of all network files OR
@@ -123,10 +121,12 @@ Maintenance Procedures LSOF(8)
-i, +|-L, -o, +|-r, -s, -S, -T, -x and -z. when you have no
values for them be careful that the following character
isn't ambiguous. For example, -Fn might represent the -F
+ and -n options, or it might represent the n field identifier
+ character following the -F option. When ambiguity is
-SunOS 5.9 Last change: Revision-4.87 2
+SunOS 5.9 Last change: Revision-4.88 2
@@ -137,11 +137,10 @@ Maintenance Procedures LSOF(8)
- and -n options, or it might represent the n field identifier
- character following the -F option. When ambiguity is possi-
- ble, start a new option with a `-' character - e.g., ``-F
- -n''. If the next option is a file name, follow the possi-
- bly ambiguous option with ``--'' - e.g., ``-F -- name''.
+ possible, start a new option with a `-' character - e.g.,
+ ``-F -n''. If the next option is a file name, follow the
+ possibly ambiguous option with ``--'' - e.g., ``-F --
+ name''.
Either the `+' or the `-' prefix may be applied to a group
of options. Options that don't take on separate meanings
@@ -192,7 +191,8 @@ Maintenance Procedures LSOF(8)
-SunOS 5.9 Last change: Revision-4.87 3
+
+SunOS 5.9 Last change: Revision-4.88 3
@@ -258,7 +258,7 @@ Maintenance Procedures LSOF(8)
-SunOS 5.9 Last change: Revision-4.87 4
+SunOS 5.9 Last change: Revision-4.88 4
@@ -324,7 +324,7 @@ Maintenance Procedures LSOF(8)
-SunOS 5.9 Last change: Revision-4.87 5
+SunOS 5.9 Last change: Revision-4.88 5
@@ -390,7 +390,7 @@ Maintenance Procedures LSOF(8)
-SunOS 5.9 Last change: Revision-4.87 6
+SunOS 5.9 Last change: Revision-4.88 6
@@ -456,7 +456,7 @@ Maintenance Procedures LSOF(8)
-SunOS 5.9 Last change: Revision-4.87 7
+SunOS 5.9 Last change: Revision-4.88 7
@@ -485,6 +485,21 @@ Maintenance Procedures LSOF(8)
information might be made available via the +|-m m
option.)
+ +|-E +E specifies that Linux files should be displayed
+ with endpoint information and the files of the end-
+ points should also be displayed.
+
+ Endpoint information is displayed in the NAME
+ column in the form ``PID,cmd,FDmode''. PID is the
+ endpoint process ID; cmd is the endpoint process
+ command; FD is the endpoint file's descriptor; and
+ mode is the endpoint file's access mode. Multiple
+ occurrences of this information can appear in a
+ file's NAME column.
+
+ -E specfies that Linux pipe files should only be
+ displayed with endpoint information.
+
+|-f [cfgGn]
f by itself clarifies how path name arguments are
to be interpreted. When followed by c, f, g, G, or
@@ -503,35 +518,35 @@ Maintenance Procedures LSOF(8)
file system name (mounted-on device) isn't a block
device. This happens for some CD-ROM file systems.
- When -f is specified by itself, all path name argu-
- ments will be taken to be simple files. Thus, for
- example, the ``-f -- /'' arguments direct lsof to
- search for open files with a `/' path name, not all
- open files in the `/' (root) file system.
+ When -f is specified by itself, all path name
- Be careful to make sure +f and -f are properly ter-
- minated and aren't followed by a character (e.g.,
- of the file or file system name) that might be
- taken as a parameter. For example, use ``--''
- after +f and -f as in these examples.
- $ lsof +f -- /file/system/name
- $ lsof -f -- /file/name
+SunOS 5.9 Last change: Revision-4.88 8
-SunOS 5.9 Last change: Revision-4.87 8
+Maintenance Procedures LSOF(8)
+ arguments will be taken to be simple files. Thus,
+ for example, the ``-f -- /'' arguments direct lsof
+ to search for open files with a `/' path name, not
+ all open files in the `/' (root) file system.
-Maintenance Procedures LSOF(8)
+ Be careful to make sure +f and -f are properly ter-
+ minated and aren't followed by a character (e.g.,
+ of the file or file system name) that might be
+ taken as a parameter. For example, use ``--''
+ after +f and -f as in these examples.
+ $ lsof +f -- /file/system/name
+ $ lsof -f -- /file/name
The listing of information from kernel file struc-
tures, requested with the +f [cfgGn] option form,
@@ -570,6 +585,20 @@ Maintenance Procedures LSOF(8)
description of the field identification characters
and the field output process.
+
+
+
+SunOS 5.9 Last change: Revision-4.88 9
+
+
+
+
+
+
+Maintenance Procedures LSOF(8)
+
+
+
When the field selection character list is empty,
all standard fields are selected (except the raw
device field, security context and zone field for
@@ -586,19 +615,6 @@ Maintenance Procedures LSOF(8)
cit entries in f, as described in the OUTPUT FOR
OTHER PROGRAMS section.
-
-
-SunOS 5.9 Last change: Revision-4.87 9
-
-
-
-
-
-
-Maintenance Procedures LSOF(8)
-
-
-
When a field selection character identifies an item
lsof does not normally list - e.g., PPID, selected
with -R - specification of the field character -
@@ -635,6 +651,20 @@ Maintenance Procedures LSOF(8)
ing of all Internet and x.25 (HP-UX) network files.
If -i4 or -i6 is specified with no following
+
+
+
+SunOS 5.9 Last change: Revision-4.88 10
+
+
+
+
+
+
+Maintenance Procedures LSOF(8)
+
+
+
address, only files of the indicated IP version,
IPv4 or IPv6, are displayed. (An IPv6 specifica-
tion may be used only if the dialects supports
@@ -651,20 +681,6 @@ Maintenance Procedures LSOF(8)
cipating in AND option selection.
An Internet address is specified in the form (Items
-
-
-
-SunOS 5.9 Last change: Revision-4.87 10
-
-
-
-
-
-
-Maintenance Procedures LSOF(8)
-
-
-
in square brackets are optional.):
[46][protocol][@hostname|hostaddr][:service|port]
@@ -701,6 +717,20 @@ Maintenance Procedures LSOF(8)
IPv4 host names and addresses may not be specified
if network file selection is limited to IPv6 with
-i 6. IPv6 host names and addresses may not be
+
+
+
+SunOS 5.9 Last change: Revision-4.88 11
+
+
+
+
+
+
+Maintenance Procedures LSOF(8)
+
+
+
specified if network file selection is limited to
IPv4 with -i 4. When an open IPv4 network file's
address is mapped in an IPv6 address, the open
@@ -717,20 +747,6 @@ Maintenance Procedures LSOF(8)
the protocol may also need to be specified if the
TCP, UDP and UDPLITE port numbers for the service
name are different. Use any case - lower or upper
-
-
-
-SunOS 5.9 Last change: Revision-4.87 11
-
-
-
-
-
-
-Maintenance Procedures LSOF(8)
-
-
-
- for protocol.
Service names and port numbers may be combined in a
@@ -767,36 +783,36 @@ Maintenance Procedures LSOF(8)
tasks of a main process are selected by other
options, the main process will also be listed as
though it were a task, but without a task ID. (See
- the description of the TID column in the OUTPUT
- section.)
- Where the FreeBSD version supports threads, all
- threads will be listed with their IDs.
- In general threads and tasks inherit the files of
- the caller, but may close some and open others, so
- lsof always reports all the open files of threads
- and tasks.
- -k k specifies a kernel name list file, k, in place of
- /vmunix, /mach, etc. -k is not available under AIX
- on the IBM RISC/System 6000.
+SunOS 5.9 Last change: Revision-4.88 12
- -l inhibits the conversion of user ID numbers to login
-SunOS 5.9 Last change: Revision-4.87 12
+Maintenance Procedures LSOF(8)
+ the description of the TID column in the OUTPUT
+ section.)
-Maintenance Procedures LSOF(8)
+ Where the FreeBSD version supports threads, all
+ threads will be listed with their IDs.
+ In general threads and tasks inherit the files of
+ the caller, but may close some and open others, so
+ lsof always reports all the open files of threads
+ and tasks.
+ -k k specifies a kernel name list file, k, in place of
+ /vmunix, /mach, etc. -k is not available under AIX
+ on the IBM RISC/System 6000.
+ -l inhibits the conversion of user ID numbers to login
names. It is also useful when login name lookup is
working improperly or slowly.
@@ -833,36 +849,36 @@ Maintenance Procedures LSOF(8)
There will be a line in the mount supplement file
for each mounted file system, containing the
- mounted file system directory, followed by a single
- space, followed by the device number in hexadecimal
- "0x" format - e.g.,
- / 0x801
- Lsof can use the mount supplement file to get dev-
- ice numbers for file systems when it can't get them
- via stat(2) or lstat(2).
+SunOS 5.9 Last change: Revision-4.88 13
- The option form +m m identifies m as a mount sup-
- plement file.
- Note: the +m and +m m options are not available for
- all supported dialects. Check the output of lsof's
-SunOS 5.9 Last change: Revision-4.87 13
+Maintenance Procedures LSOF(8)
+ mounted file system directory, followed by a single
+ space, followed by the device number in hexadecimal
+ "0x" format - e.g.,
-Maintenance Procedures LSOF(8)
+ / 0x801
+ Lsof can use the mount supplement file to get dev-
+ ice numbers for file systems when it can't get them
+ via stat(2) or lstat(2).
+ The option form +m m identifies m as a mount sup-
+ plement file.
+ Note: the +m and +m m options are not available for
+ all supported dialects. Check the output of lsof's
-h or -? options to see if the +m and +m m options
are available.
@@ -899,6 +915,20 @@ Maintenance Procedures LSOF(8)
determine if portmapper registration reporting is
slowing or blocking lsof.
+
+
+
+SunOS 5.9 Last change: Revision-4.88 14
+
+
+
+
+
+
+Maintenance Procedures LSOF(8)
+
+
+
For purposes of portmapper registration reporting
lsof considers a TCP, UDP or UDPLITE port local if:
it is found in the local part of its containing
@@ -914,22 +944,8 @@ Maintenance Procedures LSOF(8)
face from the local one.
See the lsof FAQ (The FAQ section gives its loca-
- tion.) for further discussion of portmapper
-
-
-
-SunOS 5.9 Last change: Revision-4.87 14
-
-
-
-
-
-
-Maintenance Procedures LSOF(8)
-
-
-
- registration reporting issues.
+ tion.) for further discussion of portmapper regis-
+ tration reporting issues.
Portmapper registration reporting is supported only
on dialects that have RPC header files. (Some
@@ -966,6 +982,19 @@ Maintenance Procedures LSOF(8)
zero (unlimited) directs lsof to use the ``0t''
form for all offset output.
+
+
+SunOS 5.9 Last change: Revision-4.88 15
+
+
+
+
+
+
+Maintenance Procedures LSOF(8)
+
+
+
This option does NOT direct lsof to display offset
at all times; specify -o (without a trailing
number) to do that. -o o only specifies the number
@@ -981,20 +1010,6 @@ Maintenance Procedures LSOF(8)
The default number of digits allowed after ``0t''
is normally 8, but may have been changed by the
-
-
-
-SunOS 5.9 Last change: Revision-4.87 15
-
-
-
-
-
-
-Maintenance Procedures LSOF(8)
-
-
-
lsof builder. Consult the description of the -o o
option in the output of the -h or -? option to
determine the default that is in effect.
@@ -1032,6 +1047,20 @@ Maintenance Procedures LSOF(8)
ful when port name lookup is not working properly.
+|-r [t[m<fmt>]]
+
+
+
+SunOS 5.9 Last change: Revision-4.88 16
+
+
+
+
+
+
+Maintenance Procedures LSOF(8)
+
+
+
puts lsof in repeat mode. There lsof lists open
files as selected by other options, delays t
seconds (default fifteen), then repeats the list-
@@ -1047,20 +1076,6 @@ Maintenance Procedures LSOF(8)
first cycle no open files are listed - and of
course when lsof is stopped with an interrupt or
quit signal. When repeat mode ends because no
-
-
-
-SunOS 5.9 Last change: Revision-4.87 16
-
-
-
-
-
-
-Maintenance Procedures LSOF(8)
-
-
-
files are listed, the process exit code will be
zero if any open files were ever listed; one, if
none were ever listed.
@@ -1098,35 +1113,35 @@ Maintenance Procedures LSOF(8)
Repeat mode is useful when coupled with field out-
put (see the -F, option description) and a
- supervising awk or Perl script, or a C program.
- -R directs lsof to list the Parent Process IDentifica-
- tion number in the PPID column.
- -s [p:s] s alone directs lsof to display file size at all
- times. It causes the SIZE/OFF output column title
- to be changed to SIZE. If the file does not have a
- size, nothing is displayed.
- The optional -s p:s form is available only for
- selected dialects, and only when the -h or -? help
- output lists it.
+SunOS 5.9 Last change: Revision-4.88 17
- When the optional form is available, the s may be
-SunOS 5.9 Last change: Revision-4.87 17
+Maintenance Procedures LSOF(8)
+ supervising awk or Perl script, or a C program.
-Maintenance Procedures LSOF(8)
+ -R directs lsof to list the Parent Process IDentifica-
+ tion number in the PPID column.
+ -s [p:s] s alone directs lsof to display file size at all
+ times. It causes the SIZE/OFF output column title
+ to be changed to SIZE. If the file does not have a
+ size, nothing is displayed.
+ The optional -s p:s form is available only for
+ selected dialects, and only when the -h or -? help
+ output lists it.
+ When the optional form is available, the s may be
followed by a protocol name (p), either TCP or UDP,
a colon (`:') and a comma-separated protocol state
name list, the option causes open TCP and UDP files
@@ -1164,6 +1179,20 @@ Maintenance Procedures LSOF(8)
-iUDP -sUDP:Idle
State names vary with UNIX dialects, so it's not
+
+
+
+SunOS 5.9 Last change: Revision-4.88 18
+
+
+
+
+
+
+Maintenance Procedures LSOF(8)
+
+
+
possible to provide a complete list. Some common
TCP state names are: CLOSED, IDLE, BOUND, LISTEN,
ESTABLISHED, SYN_SENT, SYN_RCDV, ESTABLISHED,
@@ -1179,20 +1208,6 @@ Maintenance Procedures LSOF(8)
and -s option (without a following protocol and
state name list) are mutually exclusive; they can't
both be specified. When neither is specified, lsof
-
-
-
-SunOS 5.9 Last change: Revision-4.87 18
-
-
-
-
-
-
-Maintenance Procedures LSOF(8)
-
-
-
displays whatever value - size or offset - is
appropriate and available for the type of file.
@@ -1231,34 +1246,33 @@ Maintenance Procedures LSOF(8)
Items values (when available) are reported after
the item name and '='.
- When the field output mode is in effect (See OUTPUT
- FOR OTHER PROGRAMS.) each item appears as a field
- with a `T' leading character.
-
- -T with no following key characters disables
- TCP/TPI information reporting.
- -T with following characters selects the reporting
- of specific TCP/TPI information:
+SunOS 5.9 Last change: Revision-4.88 19
- f selects reporting of socket options,
- states and values, and TCP flags and
- values.
-SunOS 5.9 Last change: Revision-4.87 19
+Maintenance Procedures LSOF(8)
+ When the field output mode is in effect (See OUTPUT
+ FOR OTHER PROGRAMS.) each item appears as a field
+ with a `T' leading character.
-Maintenance Procedures LSOF(8)
+ -T with no following key characters disables
+ TCP/TPI information reporting.
+ -T with following characters selects the reporting
+ of specific TCP/TPI information:
+ f selects reporting of socket options,
+ states and values, and TCP flags and
+ values.
q selects queue length reporting.
s selects connection state reporting.
w selects window size reporting.
@@ -1297,34 +1311,34 @@ Maintenance Procedures LSOF(8)
The following seven values may be reported:
- Name
- Reported Description (Common Symbol)
- KEEPALIVE keep alive time (SO_KEEPALIVE)
- LINGER linger time (SO_LINGER)
- MSS maximum segment size (TCP_MAXSEG)
- PQLEN partial listen queue connections
- QLEN established listen queue connections
- QLIM established listen queue limit
- RCVBUF receive buffer length (SO_RCVBUF)
- SNDBUF send buffer length (SO_SNDBUF)
- Details on what socket options and values, socket
- states, and TCP flags and values may be displayed
+SunOS 5.9 Last change: Revision-4.88 20
-SunOS 5.9 Last change: Revision-4.87 20
+Maintenance Procedures LSOF(8)
-Maintenance Procedures LSOF(8)
+ Name
+ Reported Description (Common Symbol)
+ KEEPALIVE keep alive time (SO_KEEPALIVE)
+ LINGER linger time (SO_LINGER)
+ MSS maximum segment size (TCP_MAXSEG)
+ PQLEN partial listen queue connections
+ QLEN established listen queue connections
+ QLIM established listen queue limit
+ RCVBUF receive buffer length (SO_RCVBUF)
+ SNDBUF send buffer length (SO_SNDBUF)
+ Details on what socket options and values, socket
+ states, and TCP flags and values may be displayed
for particular UNIX dialects may be found in the
answer to the ``Why doesn't lsof report socket
options, socket states, and TCP flags and values
@@ -1363,34 +1377,34 @@ Maintenance Procedures LSOF(8)
-v selects the listing of lsof version information,
including: revision number; when the lsof binary
- was constructed; who constructed the binary and
- where; the name of the compiler used to construct
- the lsof binary; the version number of the compiler
- when readily available; the compiler and loader
- flags used to construct the lsof binary; and system
- information, typically the output of uname's -a
- option.
- -V directs lsof to indicate the items it was asked to
- list and failed to find - command names, file
- names, Internet addresses or files, login names,
- NFS files, PIDs, PGIDs, and UIDs.
- When other options are ANDed to search options, or
+SunOS 5.9 Last change: Revision-4.88 21
-SunOS 5.9 Last change: Revision-4.87 21
+Maintenance Procedures LSOF(8)
-Maintenance Procedures LSOF(8)
+ was constructed; who constructed the binary and
+ where; the name of the compiler used to construct
+ the lsof binary; the version number of the compiler
+ when readily available; the compiler and loader
+ flags used to construct the lsof binary; and system
+ information, typically the output of uname's -a
+ option.
+ -V directs lsof to indicate the items it was asked to
+ list and failed to find - command names, file
+ names, Internet addresses or files, login names,
+ NFS files, PIDs, PGIDs, and UIDs.
+ When other options are ANDed to search options, or
compile-time options restrict the listing of some
files, lsof may not report that it failed to find a
search item when an ANDed option or compile-time
@@ -1429,34 +1443,34 @@ Maintenance Procedures LSOF(8)
the next argument must begin with '-' or '+'.
The optional 'f' parameter enables file system
- mount point cross-over processing; 'l', symbolic
- link cross-over processing.
- The -x option may not be supplied without also sup-
- plying a +d or +D option.
- -X This is a dialect-specific option.
- AIX:
- This IBM AIX RISC/System 6000 option requests the
- reporting of executed text file and shared library
- references.
+SunOS 5.9 Last change: Revision-4.88 22
- WARNING: because this option uses the kernel
-SunOS 5.9 Last change: Revision-4.87 22
+Maintenance Procedures LSOF(8)
+ mount point cross-over processing; 'l', symbolic
+ link cross-over processing.
-Maintenance Procedures LSOF(8)
+ The -x option may not be supplied without also sup-
+ plying a +d or +D option.
+ -X This is a dialect-specific option.
+ AIX:
+ This IBM AIX RISC/System 6000 option requests the
+ reporting of executed text file and shared library
+ references.
+ WARNING: because this option uses the kernel
readx() function, its use on a busy AIX system
might cause an application process to hang so com-
pletely that it can neither be killed nor stopped.
@@ -1494,35 +1508,35 @@ Maintenance Procedures LSOF(8)
forever, thus hanging the application process.
Consult the lsof FAQ (The FAQ section gives its
- location.) and the 00README file of the lsof dis-
- tribution for a more complete description of the
- Stale Segment ID bug, its APAR, and methods for
- defining readx() use when compiling lsof.
+ location.) and the 00README file of the lsof
- Linux:
- This Linux option requests that lsof skip the
- reporting of information on all open TCP, UDP and
- UDPLITE IPv4 and IPv6 files.
- This Linux option is most useful when the system
- has an extremely large number of open TCP, UDP and
- UDPLITE files, the processing of whose information
- in the /proc/net/tcp* and /proc/net/udp* files
- would take lsof a long time, and whose reporting is
+SunOS 5.9 Last change: Revision-4.88 23
-SunOS 5.9 Last change: Revision-4.87 23
+Maintenance Procedures LSOF(8)
-Maintenance Procedures LSOF(8)
+ distribution for a more complete description of the
+ Stale Segment ID bug, its APAR, and methods for
+ defining readx() use when compiling lsof.
+ Linux:
+ This Linux option requests that lsof skip the
+ reporting of information on all open TCP, UDP and
+ UDPLITE IPv4 and IPv6 files.
+ This Linux option is most useful when the system
+ has an extremely large number of open TCP, UDP and
+ UDPLITE files, the processing of whose information
+ in the /proc/net/tcp* and /proc/net/udp* files
+ would take lsof a long time, and whose reporting is
not of interest.
Use this option with care and only when you are
@@ -1561,34 +1575,34 @@ Maintenance Procedures LSOF(8)
ditions specified by other options and arguments.
-Z [Z] specifies how SELinux security contexts are to be
- handled. It and 'Z' field output character support
- are inhibited when SELinux is disabled in the run-
- ning Linux kernel. See OUTPUT FOR OTHER PROGRAMS
- for more information on the 'Z' field output char-
- acter.
- Without a following argument - e.g., NO Z - the
- option specifies that security contexts are to be
- listed in the SECURITY-CONTEXT output column.
- The -Z option may be followed by a wildcard secu-
- rity context name, Z. That causes lsof to list
- only open files for processes in that security con-
- text. Multiple -Z Z option and argument pairs may
+SunOS 5.9 Last change: Revision-4.88 24
-SunOS 5.9 Last change: Revision-4.87 24
+Maintenance Procedures LSOF(8)
-Maintenance Procedures LSOF(8)
+ handled. It and 'Z' field output character support
+ are inhibited when SELinux is disabled in the run-
+ ning Linux kernel. See OUTPUT FOR OTHER PROGRAMS
+ for more information on the 'Z' field output char-
+ acter.
+ Without a following argument - e.g., NO Z - the
+ option specifies that security contexts are to be
+ listed in the SECURITY-CONTEXT output column.
+ The -Z option may be followed by a wildcard secu-
+ rity context name, Z. That causes lsof to list
+ only open files for processes in that security con-
+ text. Multiple -Z Z option and argument pairs may
be specified to form a list of security contexts.
Any open file of any process in any of the security
contexts will be listed, subject to other condi-
@@ -1628,6 +1642,19 @@ Maintenance Procedures LSOF(8)
request that lsof look for open files inside a
directory name, use the +d s and +D D options.
+
+
+SunOS 5.9 Last change: Revision-4.88 25
+
+
+
+
+
+
+Maintenance Procedures LSOF(8)
+
+
+
If a name is the base name of a family of multi-
plexed files - e. g, AIX's /dev/pt[cs] - lsof will
list all the associated multiplexed files on the
@@ -1641,20 +1668,6 @@ Maintenance Procedures LSOF(8)
paragraph for an exception to that rule for Linux.)
Specifying a relative path - e.g., ./file - in
place of the file's absolute path - e.g., /tmp/file
-
-
-
-SunOS 5.9 Last change: Revision-4.87 25
-
-
-
-
-
-
-Maintenance Procedures LSOF(8)
-
-
-
- won't work because lsof must match the characters
you specify with what it finds in the kernel UNIX
domain socket structures.
@@ -1693,24 +1706,11 @@ AFS
Lsof supports the recognition of AFS files for these
dialects (and AFS versions):
- AIX 4.1.4 (AFS 3.4a)
- HP-UX 9.0.5 (AFS 3.4a)
- Linux 1.2.13 (AFS 3.3)
- Solaris 2.[56] (AFS 3.4a)
- It may recognize AFS files on other versions of these
- dialects, but has not been tested there. Depending on how
- AFS is implemented, lsof may recognize AFS files in other
- dialects, or may have difficulties recognizing AFS files in
- the supported dialects.
-
- Lsof may have trouble identifying all aspects of AFS files
- in supported dialects when AFS kernel support is implemented
- via dynamic modules whose addresses do not appear in the
-SunOS 5.9 Last change: Revision-4.87 26
+SunOS 5.9 Last change: Revision-4.88 26
@@ -1721,6 +1721,20 @@ Maintenance Procedures LSOF(8)
+ AIX 4.1.4 (AFS 3.4a)
+ HP-UX 9.0.5 (AFS 3.4a)
+ Linux 1.2.13 (AFS 3.3)
+ Solaris 2.[56] (AFS 3.4a)
+
+ It may recognize AFS files on other versions of these
+ dialects, but has not been tested there. Depending on how
+ AFS is implemented, lsof may recognize AFS files in other
+ dialects, or may have difficulties recognizing AFS files in
+ the supported dialects.
+
+ Lsof may have trouble identifying all aspects of AFS files
+ in supported dialects when AFS kernel support is implemented
+ via dynamic modules whose addresses do not appear in the
kernel's variable name list. In that case, lsof may have to
guess at the identity of AFS files, and might not be able to
obtain volume information from the kernel that is needed for
@@ -1760,33 +1774,32 @@ SECURITY
tion number as the real user ID number of the lsof process
(the one that its user logged on with).
- However, if HASSECURITY and HASNOSOCKSECURITY are both
- defined, anyone may list open socket files, provided they
- are selected with the -i option.
-
- When HASSECURITY is not defined, anyone may list all open
- files.
- Help output, presented in response to the -h or -? option,
- gives the status of the HASSECURITY and HASNOSOCKSECURITY
- definitions.
- See the Security section of the 00README file of the lsof
- distribution for information on building lsof with the
+SunOS 5.9 Last change: Revision-4.88 27
-SunOS 5.9 Last change: Revision-4.87 27
+Maintenance Procedures LSOF(8)
-Maintenance Procedures LSOF(8)
+ However, if HASSECURITY and HASNOSOCKSECURITY are both
+ defined, anyone may list open socket files, provided they
+ are selected with the -i option.
+ When HASSECURITY is not defined, anyone may list all open
+ files.
+ Help output, presented in response to the -h or -? option,
+ gives the status of the HASSECURITY and HASNOSOCKSECURITY
+ definitions.
+ See the Security section of the 00README file of the lsof
+ distribution for information on building lsof with the
HASSECURITY and HASNOSOCKSECURITY options enabled.
Creation and use of a user-readable and user-writable device
@@ -1826,33 +1839,33 @@ Maintenance Procedures LSOF(8)
OUTPUT
This section describes the information lsof lists for each
open file. See the OUTPUT FOR OTHER PROGRAMS section for
- additional information on output that can be processed by
- another program.
- Lsof only outputs printable (declared so by isprint(3)) 8
- bit characters. Non-printable characters are printed in one
- of three forms: the C ``\[bfrnt]'' form; the control char-
- acter `^' form (e.g., ``^@''); or hexadecimal leading ``\x''
- form (e.g., ``\xab''). Space is non-printable in the COM-
- MAND column (``\x20'') and printable elsewhere.
- For some dialects - if HASSETLOCALE is defined in the
- dialect's machine.h header file - lsof will print the
- extended 8 bit characters of a language locale. The lsof
+SunOS 5.9 Last change: Revision-4.88 28
-SunOS 5.9 Last change: Revision-4.87 28
+Maintenance Procedures LSOF(8)
-Maintenance Procedures LSOF(8)
+ additional information on output that can be processed by
+ another program.
+ Lsof only outputs printable (declared so by isprint(3)) 8
+ bit characters. Non-printable characters are printed in one
+ of three forms: the C ``\[bfrnt]'' form; the control char-
+ acter `^' form (e.g., ``^@''); or hexadecimal leading ``\x''
+ form (e.g., ``\xab''). Space is non-printable in the COM-
+ MAND column (``\x20'') and printable elsewhere.
+ For some dialects - if HASSETLOCALE is defined in the
+ dialect's machine.h header file - lsof will print the
+ extended 8 bit characters of a language locale. The lsof
process must be supplied a language locale environment vari-
able (e.g., LANG) whose value represents a known language
locale in which the extended characters are considered
@@ -1892,33 +1905,33 @@ Maintenance Procedures LSOF(8)
ters of the name of the UNIX command associated
with the process up to the limit of characters
supplied to lsof by the UNIX dialect. (See the
- description of the +c w command or the lsof FAQ
- for more information. The FAQ section gives its
- location.)
- If w is less than the length of the column title,
- ``COMMAND'', it will be raised to that length.
- If a zero w value is specified to the +c w
- option, the column contains all the characters of
- the name of the UNIX command associated with the
- process.
- All command name characters maintained by the
+SunOS 5.9 Last change: Revision-4.88 29
-SunOS 5.9 Last change: Revision-4.87 29
+Maintenance Procedures LSOF(8)
-Maintenance Procedures LSOF(8)
+ description of the +c w command or the lsof FAQ
+ for more information. The FAQ section gives its
+ location.)
+ If w is less than the length of the column title,
+ ``COMMAND'', it will be raised to that length.
+ If a zero w value is specified to the +c w
+ option, the column contains all the characters of
+ the name of the UNIX command associated with the
+ process.
+ All command name characters maintained by the
kernel in its structures are displayed in field
output when the command name descriptor (`c') is
specified. See the OUTPUT FOR OTHER COMMANDS
@@ -1958,33 +1971,33 @@ Maintenance Procedures LSOF(8)
USER is the user ID number or login name of the user
to whom the process belongs, usually the same as
reported by ps(1). However, on Linux USER is the
- user ID number or login that owns the directory
- in /proc where lsof finds information about the
- process. Usually that is the same value reported
- by ps(1), but may differ when the process has
- changed its effective user ID. (See the -l
- option description for information on when a user
- ID number or login name is displayed.)
- FD is the File Descriptor number of the file or:
- cwd current working directory;
- Lnn library references (AIX);
+SunOS 5.9 Last change: Revision-4.88 30
-SunOS 5.9 Last change: Revision-4.87 30
+Maintenance Procedures LSOF(8)
-Maintenance Procedures LSOF(8)
+ user ID number or login that owns the directory
+ in /proc where lsof finds information about the
+ process. Usually that is the same value reported
+ by ps(1), but may differ when the process has
+ changed its effective user ID. (See the -l
+ option description for information on when a user
+ ID number or login name is displayed.)
+ FD is the File Descriptor number of the file or:
+ cwd current working directory;
+ Lnn library references (AIX);
err FD information error (see NAME column);
jld jail directory (FreeBSD);
ltx shared library text (code and data);
@@ -2024,32 +2037,32 @@ Maintenance Procedures LSOF(8)
of the file;
X for an SCO OpenServer Xenix lock on the
entire file;
- space if there is no lock.
- See the LOCKS section for more information on the
- lock information character.
- The FD column contents constitutes a single field
- for parsing in post-processing scripts.
- TYPE is the type of the node associated with the file
- - e.g., GDIR, GREG, VDIR, VREG, etc.
+SunOS 5.9 Last change: Revision-4.88 31
- or ``IPv4'' for an IPv4 socket;
-SunOS 5.9 Last change: Revision-4.87 31
+Maintenance Procedures LSOF(8)
+ space if there is no lock.
+ See the LOCKS section for more information on the
+ lock information character.
-Maintenance Procedures LSOF(8)
+ The FD column contents constitutes a single field
+ for parsing in post-processing scripts.
+ TYPE is the type of the node associated with the file
+ - e.g., GDIR, GREG, VDIR, VREG, etc.
+ or ``IPv4'' for an IPv4 socket;
or ``IPv6'' for an open IPv6 network file - even
if its address is IPv4, mapped in an IPv6
@@ -2091,31 +2104,31 @@ Maintenance Procedures LSOF(8)
or ``MPC'' for a multiplexed character file;
- or ``NOFD'' for a Linux /proc/<PID>/fd directory
- that can't be opened -- the directory path
- appears in the NAME column, followed by an error
- message;
- or ``PAS'' for a /proc/as file;
- or ``PAXV'' for a /proc/auxv file;
+SunOS 5.9 Last change: Revision-4.88 32
- or ``PCRE'' for a /proc/cred file;
- or ``PCTL'' for a /proc control file;
-SunOS 5.9 Last change: Revision-4.87 32
+Maintenance Procedures LSOF(8)
+ or ``NOFD'' for a Linux /proc/<PID>/fd directory
+ that can't be opened -- the directory path
+ appears in the NAME column, followed by an error
+ message;
+ or ``PAS'' for a /proc/as file;
-Maintenance Procedures LSOF(8)
+ or ``PAXV'' for a /proc/auxv file;
+ or ``PCRE'' for a /proc/cred file;
+ or ``PCTL'' for a /proc control file;
or ``PCUR'' for the current /proc process;
@@ -2157,31 +2170,30 @@ Maintenance Procedures LSOF(8)
or ``PLWI'' for a /proc/lwpsinfo file;
- or ``PLWS'' for a /proc/lwpstatus file;
-
- or ``PLWU'' for a /proc/lwpusage file;
- or ``PLWX'' for a /proc/xregs file'
- or ``PMAP'' for a /proc map file (map);
+SunOS 5.9 Last change: Revision-4.88 33
- or ``PMEM'' for a /proc memory image file;
- or ``PNTF'' for a /proc process notifier file;
-SunOS 5.9 Last change: Revision-4.87 33
+Maintenance Procedures LSOF(8)
+ or ``PLWS'' for a /proc/lwpstatus file;
+ or ``PLWU'' for a /proc/lwpusage file;
+ or ``PLWX'' for a /proc/xregs file'
-Maintenance Procedures LSOF(8)
+ or ``PMAP'' for a /proc map file (map);
+ or ``PMEM'' for a /proc memory image file;
+ or ``PNTF'' for a /proc process notifier file;
or ``POBJ'' for a /proc/object file;
@@ -2223,31 +2235,32 @@ Maintenance Procedures LSOF(8)
or ``SMT'' for a shared memory transport file;
- or ``STSO'' for a stream socket;
- or ``UNNM'' for an unnamed type file;
- or ``XNAM'' for an OpenServer Xenix special file
- of unknown type;
- or ``XSEM'' for an OpenServer Xenix semaphore
- file;
+SunOS 5.9 Last change: Revision-4.88 34
- or ``XSD'' for an OpenServer Xenix shared data
- file;
-SunOS 5.9 Last change: Revision-4.87 34
+Maintenance Procedures LSOF(8)
+ or ``STSO'' for a stream socket;
-Maintenance Procedures LSOF(8)
+ or ``UNNM'' for an unnamed type file;
+
+ or ``XNAM'' for an OpenServer Xenix special file
+ of unknown type;
+ or ``XSEM'' for an OpenServer Xenix semaphore
+ file;
+ or ``XSD'' for an OpenServer Xenix shared data
+ file;
or the four type number octets if the correspond-
ing name isn't known.
@@ -2288,23 +2301,10 @@ Maintenance Procedures LSOF(8)
DIR direct
DLY delay
DOCL do clone
- DSYN data-only integrity
- DTY must be a directory
- EVO event only
- EX open for exec
- EXCL exclusive open
- FSYN synchronous writes
- GCDF defer during unp_gc() (AIX)
- GCMK mark during unp_gc() (AIX)
- GTTY accessed via /dev/tty
- HUP HUP in progress
- KERN kernel
- KIOC kernel-issued ioctl
- LCK has lock
-SunOS 5.9 Last change: Revision-4.87 35
+SunOS 5.9 Last change: Revision-4.88 35
@@ -2315,6 +2315,19 @@ Maintenance Procedures LSOF(8)
+ DSYN data-only integrity
+ DTY must be a directory
+ EVO event only
+ EX open for exec
+ EXCL exclusive open
+ FSYN synchronous writes
+ GCDF defer during unp_gc() (AIX)
+ GCMK mark during unp_gc() (AIX)
+ GTTY accessed via /dev/tty
+ HUP HUP in progress
+ KERN kernel
+ KIOC kernel-issued ioctl
+ LCK has lock
LG large file
MBLK stream message block
MK mark
@@ -2354,23 +2367,10 @@ Maintenance Procedures LSOF(8)
STPI stop I/O
SWR synchronous read
SYN file integrity while writing
- TCPM avoid TCP collision
- TR truncate
- W write
- WKUP parallel I/O synchronization
- WTG parallel I/O synchronization
- VH vhangup pending
- VTXT virtual text
- XL exclusive lock
-
- this list of names was derived from F* #define's
- in dialect header files <fcntl.h>, <linux</fs.h>,
- <sys/fcntl.c>, <sys/fcntlcom.h>, and
- <sys/file.h>; see the lsof.h header file for a
-SunOS 5.9 Last change: Revision-4.87 36
+SunOS 5.9 Last change: Revision-4.88 36
@@ -2381,6 +2381,19 @@ Maintenance Procedures LSOF(8)
+ TCPM avoid TCP collision
+ TR truncate
+ W write
+ WKUP parallel I/O synchronization
+ WTG parallel I/O synchronization
+ VH vhangup pending
+ VTXT virtual text
+ XL exclusive lock
+
+ this list of names was derived from F* #define's
+ in dialect header files <fcntl.h>, <linux</fs.h>,
+ <sys/fcntl.c>, <sys/fcntlcom.h>, and
+ <sys/file.h>; see the lsof.h header file for a
list showing the correspondence between the above
short-hand names and the header file definitions;
@@ -2420,33 +2433,33 @@ Maintenance Procedures LSOF(8)
or a kernel reference address that identifies the
file (The kernel reference address may be used
- for FIFO's, for example.);
- or the base address or device name of a Linux
- AX.25 socket device.
- Usually only the lower thirty two bits of Tru64
- UNIX kernel addresses are displayed.
- SIZE, SIZE/OFF, or OFFSET
- is the size of the file or the file offset in
- bytes. A value is displayed in this column only
- if it is available. Lsof displays whatever value
- - size or offset - is appropriate for the type of
+SunOS 5.9 Last change: Revision-4.88 37
-SunOS 5.9 Last change: Revision-4.87 37
+Maintenance Procedures LSOF(8)
-Maintenance Procedures LSOF(8)
+ for FIFO's, for example.);
+ or the base address or device name of a Linux
+ AX.25 socket device.
+ Usually only the lower thirty two bits of Tru64
+ UNIX kernel addresses are displayed.
+ SIZE, SIZE/OFF, or OFFSET
+ is the size of the file or the file offset in
+ bytes. A value is displayed in this column only
+ if it is available. Lsof displays whatever value
+ - size or offset - is appropriate for the type of
the file and the version of lsof.
On some UNIX dialects lsof can't obtain accurate
@@ -2486,32 +2499,33 @@ Maintenance Procedures LSOF(8)
If the -s option is specified, lsof always
displays the file size (or nothing if no size is
available) and labels the column SIZE. The -o
- and -s options are mutually exclusive; they can't
- both be specified.
- For files that don't have a fixed size - e.g.,
- don't reside on a disk device - lsof will display
- appropriate information about the current size or
- position of the file if it is available in the
- kernel structures that define the file.
- NLINK contains the file link count when +L has been
- specified;
- NODE is the node number of a local file;
+SunOS 5.9 Last change: Revision-4.88 38
-SunOS 5.9 Last change: Revision-4.87 38
+Maintenance Procedures LSOF(8)
-Maintenance Procedures LSOF(8)
+ and -s options are mutually exclusive; they can't
+ both be specified.
+
+ For files that don't have a fixed size - e.g.,
+ don't reside on a disk device - lsof will display
+ appropriate information about the current size or
+ position of the file if it is available in the
+ kernel structures that define the file.
+ NLINK contains the file link count when +L has been
+ specified;
+ NODE is the node number of a local file;
or the inode number of an NFS file in the server
host;
@@ -2551,6 +2565,20 @@ Maintenance Procedures LSOF(8)
be followed by TCP/TPI information in parentheses
- state (e.g., ``(ESTABLISHED)'', ``(Unbound)''),
queue sizes, and window sizes (not all dialects)
+
+
+
+SunOS 5.9 Last change: Revision-4.88 39
+
+
+
+
+
+
+Maintenance Procedures LSOF(8)
+
+
+
- in a fashion similar to what netstat(1)
reports; see the -T option description or the
description of the TCP/TPI field in OUTPUT FOR
@@ -2566,19 +2594,6 @@ Maintenance Procedures LSOF(8)
or the local and remote mount point names of an
NFS file;
-
-
-SunOS 5.9 Last change: Revision-4.87 39
-
-
-
-
-
-
-Maintenance Procedures LSOF(8)
-
-
-
or ``STR'', followed by the stream name;
or a stream character device name, followed by
@@ -2616,34 +2631,34 @@ Maintenance Procedures LSOF(8)
or ``rd=<offset>'' and ``wr=<offset>'' for the
values of the read and write offsets of a FIFO;
- or ``clone n:/dev/event'' for SCO OpenServer file
- clones of the /dev/event device, where n is the
- minor device number of the file;
- or ``(socketpair: n)'' for a Solaris 2.6, 8, 9
- or 10 UNIX domain socket, created by the
- socketpair(3N) network function;
- or ``no PCB'' for socket files that do not have a
- protocol block associated with them, optionally
- followed by ``, CANTSENDMORE'' if sending on the
- socket has been disabled, or ``, CANTRCVMORE'' if
- receiving on the socket has been disabled (e.g.,
- by the shutdown(2) function);
+SunOS 5.9 Last change: Revision-4.88 40
-SunOS 5.9 Last change: Revision-4.87 40
+Maintenance Procedures LSOF(8)
-Maintenance Procedures LSOF(8)
+ or ``clone n:/dev/event'' for SCO OpenServer file
+ clones of the /dev/event device, where n is the
+ minor device number of the file;
+ or ``(socketpair: n)'' for a Solaris 2.6, 8, 9
+ or 10 UNIX domain socket, created by the
+ socketpair(3N) network function;
+ or ``no PCB'' for socket files that do not have a
+ protocol block associated with them, optionally
+ followed by ``, CANTSENDMORE'' if sending on the
+ socket has been disabled, or ``, CANTRCVMORE'' if
+ receiving on the socket has been disabled (e.g.,
+ by the shutdown(2) function);
or the local and remote addresses of a Linux IPX
socket file in the form <net>:[<node>:]<port>,
@@ -2682,34 +2697,33 @@ Maintenance Procedures LSOF(8)
section gives its location.) for more information on these
NAME column additions.
-LOCKS
- Lsof can't adequately report the wide variety of UNIX
- dialect file locks in a single character. What it reports
- in a single character is a compromise between the informa-
- tion it finds in the kernel and the limitations of the
- reporting format.
-
- Moreover, when a process holds several byte level locks on a
- file, lsof only reports the status of the first lock it
- encounters. If it is a byte level lock, then the lock char-
- acter will be reported in lower case - i.e., `r', `w', or
- `x' - rather than the upper case equivalent reported for a
- full file lock.
+SunOS 5.9 Last change: Revision-4.88 41
-SunOS 5.9 Last change: Revision-4.87 41
+Maintenance Procedures LSOF(8)
-Maintenance Procedures LSOF(8)
+LOCKS
+ Lsof can't adequately report the wide variety of UNIX
+ dialect file locks in a single character. What it reports
+ in a single character is a compromise between the informa-
+ tion it finds in the kernel and the limitations of the
+ reporting format.
+ Moreover, when a process holds several byte level locks on a
+ file, lsof only reports the status of the first lock it
+ encounters. If it is a byte level lock, then the lock char-
+ acter will be reported in lower case - i.e., `r', `w', or
+ `x' - rather than the upper case equivalent reported for a
+ full file lock.
Generally lsof can only report on locks held by local
processes on local files. When a local process sets a lock
@@ -2749,6 +2763,20 @@ OUTPUT FOR OTHER PROGRAMS
file descriptor). It is followed by lines that describe the
file's access mode, lock state, type, device, size, offset,
inode, protocol, name and stream module names. It extends
+
+
+
+SunOS 5.9 Last change: Revision-4.88 42
+
+
+
+
+
+
+Maintenance Procedures LSOF(8)
+
+
+
to the beginning of the next file or process set, whichever
comes first.
@@ -2764,19 +2792,6 @@ OUTPUT FOR OTHER PROGRAMS
of the field character - e.g., ``-FR'' - also selects the
listing of the item.
-
-
-SunOS 5.9 Last change: Revision-4.87 42
-
-
-
-
-
-
-Maintenance Procedures LSOF(8)
-
-
-
It is entirely possible to select a set of fields that can-
not easily be parsed - e.g., if the field descriptor field
is not selected, it may be difficult to identify file sets.
@@ -2795,7 +2810,7 @@ Maintenance Procedures LSOF(8)
C file structure share count
d file's device character code
D file's major/minor device number (0x<hexadecimal>)
- f file descriptor
+ f file descriptor (always selected)
F file structure address (0x<hexadecimal>)
G file flaGs (0x<hexadecimal>; names if +fg follows)
g process group ID
@@ -2814,6 +2829,20 @@ Maintenance Procedures LSOF(8)
R parent process ID
s file's size (decimal)
S file's stream identification
+
+
+
+SunOS 5.9 Last change: Revision-4.88 43
+
+
+
+
+
+
+Maintenance Procedures LSOF(8)
+
+
+
t file's type
T TCP/TPI information, identified by prefixes (the
`=' is part of the prefix):
@@ -2829,20 +2858,6 @@ Maintenance Procedures LSOF(8)
UNIX dialects. The -h or -? help output for the
-T option will show what TCP/TPI reporting can be
requested.)
-
-
-
-SunOS 5.9 Last change: Revision-4.87 43
-
-
-
-
-
-
-Maintenance Procedures LSOF(8)
-
-
-
u process user ID
z Solaris 10 and higher zone name
Z SELinux security context (inhibited when SELinux is disabled)
@@ -2880,6 +2895,20 @@ Maintenance Procedures LSOF(8)
put. When the NUL field terminator is in use, lsof ends
each process and file set with a NL (012).
+
+
+
+SunOS 5.9 Last change: Revision-4.88 44
+
+
+
+
+
+
+Maintenance Procedures LSOF(8)
+
+
+
Three aids to producing programs that can process lsof field
output are included in the lsof distribution. The first is
a C header file, lsof_fields.h, that contains symbols for
@@ -2895,20 +2924,6 @@ Maintenance Procedures LSOF(8)
The test suite is written in C and uses field output to
validate the correct operation of lsof. The library can be
found in the tests/LTlib.c file of the lsof distribution.
-
-
-
-SunOS 5.9 Last change: Revision-4.87 44
-
-
-
-
-
-
-Maintenance Procedures LSOF(8)
-
-
-
The library uses the first aid, the lsof_fields.h header
file.
@@ -2946,6 +2961,20 @@ AVOIDING KERNEL BLOCKS
You can use the -b option to tell lsof to avoid using kernel
functions that would block. Some cautions apply.
+
+
+
+SunOS 5.9 Last change: Revision-4.88 45
+
+
+
+
+
+
+Maintenance Procedures LSOF(8)
+
+
+
First, using this option usually requires that your system
supply alternate device numbers in place of the device
numbers that lsof would normally obtain with the lstat(2)
@@ -2961,20 +2990,6 @@ AVOIDING KERNEL BLOCKS
numbers for the file systems that have alternates, its abil-
ity to locate files on file systems depends completely on
the availability and accuracy of the alternates. If no
-
-
-
-SunOS 5.9 Last change: Revision-4.87 45
-
-
-
-
-
-
-Maintenance Procedures LSOF(8)
-
-
-
alternates are available, or if they're incorrect, lsof
won't be able to locate files on the named file systems.
@@ -3012,35 +3027,35 @@ ALTERNATE DEVICE NUMBERS
You may also be able to supply device numbers using the +m
and +m m options, provided they are supported by your
dialect. Check the output of lsof's -h or -? options to see
- if the +m and +m m options are available.
- The ``xxxx'' portion of the field is the hexadecimal value
- of the file system's device number. (Consult the st_dev
- field of the output of the lstat(2) and stat(2) functions
- for the appropriate values for your file systems.) Here's
- an example from a Sun Solaris 2.6 /etc/mnttab for a file
- system remotely mounted via NFS:
- nfs ignore,noquota,dev=2a40001
- There's an advantage to having ``dev=xxxx'' entries in your
- mount table file, especially for file systems that are
- mounted from remote NFS servers. When a remote server
- crashes and you want to identify its users by running lsof
+SunOS 5.9 Last change: Revision-4.88 46
-SunOS 5.9 Last change: Revision-4.87 46
+Maintenance Procedures LSOF(8)
-Maintenance Procedures LSOF(8)
+ if the +m and +m m options are available.
+ The ``xxxx'' portion of the field is the hexadecimal value
+ of the file system's device number. (Consult the st_dev
+ field of the output of the lstat(2) and stat(2) functions
+ for the appropriate values for your file systems.) Here's
+ an example from a Sun Solaris 2.6 /etc/mnttab for a file
+ system remotely mounted via NFS:
+ nfs ignore,noquota,dev=2a40001
+ There's an advantage to having ``dev=xxxx'' entries in your
+ mount table file, especially for file systems that are
+ mounted from remote NFS servers. When a remote server
+ crashes and you want to identify its users by running lsof
on one of its clients, lsof probably won't be able to get
output from the lstat(2) and stat(2) functions for the file
system. If it can obtain the file system's device number
@@ -3078,6 +3093,20 @@ KERNEL NAME CACHE
If lsof can't report all components in a path, it reports in
the NAME column the file system name, followed by a space,
two `-' characters, another space, and the name components
+
+
+
+SunOS 5.9 Last change: Revision-4.88 47
+
+
+
+
+
+
+Maintenance Procedures LSOF(8)
+
+
+
it has located, separated by the `/' character.
When lsof is run in repeat mode - i.e., with the -r option
@@ -3093,20 +3122,6 @@ KERNEL NAME CACHE
uses device and node number as a key (e.g., SCO OpenServer)
and a key on a rapidly changing file system is reused. If
the UNIX dialect's kernel doesn't purge the name cache entry
-
-
-
-SunOS 5.9 Last change: Revision-4.87 47
-
-
-
-
-
-
-Maintenance Procedures LSOF(8)
-
-
-
for a file when it is unlinked, lsof may find a reference to
the wrong entry in the cache. The lsof FAQ (The FAQ section
gives its location.) has more information on this situa-
@@ -3144,36 +3159,36 @@ DEVICE CACHE FILE
cached /dev (or /devices) information (exception: the
/proc-based Linux lsof where it's not needed.) The local
system administrator who builds lsof can control the way the
- device cache file path is formed, selecting from these
- options:
- Path from the -D option;
- Path from an environment variable;
- System-wide path;
- Personal path (the default);
- Personal path, modified by an environment variable.
- Consult the output of the -h, -D? , or -? help options for
- the current state of device cache support. The help output
- lists the default read-mode device cache file path that is
- in effect for the current invocation of lsof. The -D?
- option output lists the read-only and write device cache
- file paths, the names of any applicable environment
+SunOS 5.9 Last change: Revision-4.88 48
-SunOS 5.9 Last change: Revision-4.87 48
+Maintenance Procedures LSOF(8)
-Maintenance Procedures LSOF(8)
+ device cache file path is formed, selecting from these
+ options:
+ Path from the -D option;
+ Path from an environment variable;
+ System-wide path;
+ Personal path (the default);
+ Personal path, modified by an environment variable.
- variables, and the personal device cache path format.
+ Consult the output of the -h, -D? , or -? help options for
+ the current state of device cache support. The help output
+ lists the default read-mode device cache file path that is
+ in effect for the current invocation of lsof. The -D?
+ option output lists the read-only and write device cache
+ file paths, the names of any applicable environment vari-
+ ables, and the personal device cache path format.
Lsof can detect that the current device cache file has been
accidentally or maliciously modified by integrity checks,
@@ -3210,6 +3225,20 @@ Maintenance Procedures LSOF(8)
LSOF PERMISSIONS THAT AFFECT DEVICE CACHE FILE ACCESS
Two permissions of the lsof executable affect its ability to
access device cache files. The permissions are set by the
+
+
+
+SunOS 5.9 Last change: Revision-4.88 49
+
+
+
+
+
+
+Maintenance Procedures LSOF(8)
+
+
+
local system administrator when lsof is installed.
The first and rarer permission is setuid-root. It comes
@@ -3226,19 +3255,6 @@ LSOF PERMISSIONS THAT AFFECT DEVICE CACHE FILE ACCESS
(GID) of the lsof process is set to one that can access ker-
nel memory devices - e.g., ``kmem'', ``sys'', or ``system''.
-
-
-SunOS 5.9 Last change: Revision-4.87 49
-
-
-
-
-
-
-Maintenance Procedures LSOF(8)
-
-
-
An lsof process that has setgid permission usually
surrenders the permission after it has accessed the kernel
memory devices. When it does that, lsof can allow more
@@ -3275,6 +3291,20 @@ DEVICE CACHE FILE PATH FROM THE -D OPTION
The -D option provides limited means for specifying the dev-
ice cache file path. Its ? function will report the
read-only and write device cache file paths that lsof will
+
+
+
+SunOS 5.9 Last change: Revision-4.88 50
+
+
+
+
+
+
+Maintenance Procedures LSOF(8)
+
+
+
use.
When the -D b, r, and u functions are available, you can use
@@ -3291,20 +3321,6 @@ DEVICE CACHE FILE PATH FROM THE -D OPTION
CACHE FILE ACCESS section for a list of implementations that
normally don't surrender their setgid permission.)
-
-
-
-SunOS 5.9 Last change: Revision-4.87 50
-
-
-
-
-
-
-Maintenance Procedures LSOF(8)
-
-
-
A further -D function, i (for ignore), is always available.
When available, the b function tells lsof to read device
@@ -3341,6 +3357,20 @@ DEVICE CACHE PATH FROM AN ENVIRONMENT VARIABLE
information on implementations that don't surrender their
setgid permission.)
+
+
+
+SunOS 5.9 Last change: Revision-4.88 51
+
+
+
+
+
+
+Maintenance Procedures LSOF(8)
+
+
+
The local system administrator can disable the use of the
LSOFDEVCACHE environment variable or change its name when
building lsof. Consult the output of -D? for the environ-
@@ -3357,20 +3387,6 @@ SYSTEM-WIDE DEVICE CACHE PATH
You can tell that a system-wide device cache file is in
effect for your local installation by examining the lsof
help option output - i.e., the output from the -h or -?
-
-
-
-SunOS 5.9 Last change: Revision-4.87 51
-
-
-
-
-
-
-Maintenance Procedures LSOF(8)
-
-
-
option.
Lsof will never write to the system-wide device cache file
@@ -3407,6 +3423,20 @@ PERSONAL DEVICE CACHE PATH (DEFAULT)
NFS-mounted home directory into which device cache files are
written from several different hosts.
+
+
+
+SunOS 5.9 Last change: Revision-4.88 52
+
+
+
+
+
+
+Maintenance Procedures LSOF(8)
+
+
+
The personal device cache file path formed by this method
represents a device cache file that lsof will attempt to
read, and will attempt to write should it not exist or
@@ -3423,20 +3453,6 @@ PERSONAL DEVICE CACHE PATH (DEFAULT)
MODIFIED PERSONAL DEVICE CACHE PATH
If this option is defined by the local system administrator
when lsof is built, the LSOFPERSDCPATH environment variable
-
-
-
-SunOS 5.9 Last change: Revision-4.87 52
-
-
-
-
-
-
-Maintenance Procedures LSOF(8)
-
-
-
contents may be used to add a component of the personal dev-
ice cache file path.
@@ -3472,6 +3488,21 @@ Maintenance Procedures LSOF(8)
device cache files at the standard personal path and move
them to your subdirectory with shell commands.
+
+
+
+
+SunOS 5.9 Last change: Revision-4.88 53
+
+
+
+
+
+
+Maintenance Procedures LSOF(8)
+
+
+
The local system administrator may: disable this option when
lsof is built; change the name of the environment variable
from LSOFPERSDCPATH to something else; change the HASPERSDC
@@ -3490,19 +3521,6 @@ DIAGNOSTICS
UIDs it was asked to list. If the -V option is specified,
lsof will indicate the search items it failed to list.
-
-
-SunOS 5.9 Last change: Revision-4.87 53
-
-
-
-
-
-
-Maintenance Procedures LSOF(8)
-
-
-
It returns a zero (0) if no errors were detected and if it
was able to list some information about all the specified
search arguments.
@@ -3536,6 +3554,21 @@ EXAMPLES
lsof
+
+
+
+
+SunOS 5.9 Last change: Revision-4.88 54
+
+
+
+
+
+
+Maintenance Procedures LSOF(8)
+
+
+
To list all open Internet, x.25 (HP-UX), and UNIX domain
files, use:
@@ -3556,19 +3589,6 @@ EXAMPLES
lsof -i @wonderland.cc.purdue.edu:513-515
-
-
-SunOS 5.9 Last change: Revision-4.87 54
-
-
-
-
-
-
-Maintenance Procedures LSOF(8)
-
-
-
To list all files using any protocol on any port of
mace.cc.purdue.edu (cc.purdue.edu is the default domain),
use:
@@ -3601,39 +3621,38 @@ Maintenance Procedures LSOF(8)
To find processes with open files on the NFS file system
named /nfs/mount/point whose server is inaccessible, and
presuming your mount table supplies the device number for
- /nfs/mount/point, use:
- lsof -b /nfs/mount/point
- To do the preceding search with warning messages suppressed,
- use:
- lsof -bw /nfs/mount/point
-
- To ignore the device cache file, use:
+SunOS 5.9 Last change: Revision-4.88 55
- lsof -Di
- To obtain PID and command name field output for each pro-
- cess, file descriptor, file device number, and file inode
- number for each file of each process, use:
- lsof -FpcfDi
+Maintenance Procedures LSOF(8)
-SunOS 5.9 Last change: Revision-4.87 55
+ /nfs/mount/point, use:
+ lsof -b /nfs/mount/point
+ To do the preceding search with warning messages suppressed,
+ use:
+ lsof -bw /nfs/mount/point
+ To ignore the device cache file, use:
-Maintenance Procedures LSOF(8)
+ lsof -Di
+ To obtain PID and command name field output for each pro-
+ cess, file descriptor, file device number, and file inode
+ number for each file of each process, use:
+ lsof -FpcfDi
To list the files at descriptors 1 and 3 of every process
running the lsof command for login ID ``abe'' every 10
@@ -3669,6 +3688,19 @@ Maintenance Procedures LSOF(8)
To obtain a repeat mode marker line that contains the
current time, use:
+
+
+SunOS 5.9 Last change: Revision-4.88 56
+
+
+
+
+
+
+Maintenance Procedures LSOF(8)
+
+
+
lsof -rm====%T====
To add spaces to the previous marker line, use:
@@ -3686,21 +3718,6 @@ BUGS
individual record locks that might be described by multiple
lock structures.
-
-
-
-
-SunOS 5.9 Last change: Revision-4.87 56
-
-
-
-
-
-
-Maintenance Procedures LSOF(8)
-
-
-
Lsof can't search for files with restrictive access permis-
sions by name unless it is installed with root set-UID per-
mission. Otherwise it is limited to searching for files to
@@ -3736,6 +3753,20 @@ Maintenance Procedures LSOF(8)
Lsof can't search for Tru64 UNIX named pipes by name,
because their kernel implementation of lstat(2) returns an
+
+
+
+SunOS 5.9 Last change: Revision-4.88 57
+
+
+
+
+
+
+Maintenance Procedures LSOF(8)
+
+
+
improper device number for a named pipe.
Lsof can't report fully or correctly on HP-UX 9.01, 10.20,
@@ -3753,20 +3784,6 @@ Maintenance Procedures LSOF(8)
Linux lsof, because it doesn't read kernel structures from
kernel memory.
-
-
-
-SunOS 5.9 Last change: Revision-4.87 57
-
-
-
-
-
-
-Maintenance Procedures LSOF(8)
-
-
-
ENVIRONMENT
Lsof may access these environment variables.
@@ -3802,6 +3819,20 @@ FILES
/dev/swap system paging device
.lsof_hostname lsof's device cache file (The suffix,
+
+
+
+SunOS 5.9 Last change: Revision-4.88 58
+
+
+
+
+
+
+Maintenance Procedures LSOF(8)
+
+
+
hostname, is the first component of the
host's name returned by gethostname(2).)
@@ -3820,19 +3851,6 @@ DISTRIBUTION
ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof
-
-
-SunOS 5.9 Last change: Revision-4.87 58
-
-
-
-
-
-
-Maintenance Procedures LSOF(8)
-
-
-
Lsof is also mirrored elsewhere. When you access
lsof.itap.purdue.edu and change to its pub/tools/unix/lsof
directory, you'll be given a list of some mirror sites. The
@@ -3870,25 +3888,7 @@ SEE ALSO
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-SunOS 5.9 Last change: Revision-4.87 59
+SunOS 5.9 Last change: Revision-4.88 59
diff --git a/lsof_fields.h b/lsof_fields.h
index bcd3505..9517a58 100644
--- a/lsof_fields.h
+++ b/lsof_fields.h
@@ -32,7 +32,7 @@
/*
- * $Id: lsof_fields.h,v 1.12 2010/07/29 15:59:28 abe Exp $
+ * $Id: lsof_fields.h,v 1.13 2014/10/13 22:36:20 abe Exp $
*/
@@ -79,7 +79,7 @@
#define LSOF_FID_FD 'f'
#define LSOF_FIX_FD 5
-#define LSOF_FNM_FD "file descriptor"
+#define LSOF_FNM_FD "file descriptor (always selected)"
#define LSOF_FID_FA 'F'
#define LSOF_FIX_FA 6
diff --git a/main.c b/main.c
index e2164d3..70b245f 100644
--- a/main.c
+++ b/main.c
@@ -34,7 +34,7 @@
#ifndef lint
static char copyright[] =
"@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n";
-static char *rcsid = "$Id: main.c,v 1.55 2011/09/07 19:13:49 abe Exp $";
+static char *rcsid = "$Id: main.c,v 1.56 2014/10/13 22:36:20 abe Exp $";
#endif
@@ -112,14 +112,17 @@ main(argc, argv)
else
Pn = argv[0];
/*
- * Close all file descriptors above 2.
+ * Close enough file descriptors above 2 that library functions will have
+ * open descriptors.
*
* Make sure stderr, stdout, and stdin are open descriptors. Open /dev/null
* for ones that aren't. Be terse.
*
* Make sure umask allows lsof to define its own file permissions.
*/
- for (i = 3, n = GET_MAX_FD(); i < n; i++)
+ if ((MaxFd = (int) GET_MAX_FD()) < 53)
+ MaxFd = 53;
+ for (i = 3; i < MaxFd; i++)
(void) close(i);
while (((i = open("/dev/null", O_RDWR, 0)) >= 0) && (i < 2))
;
@@ -154,7 +157,7 @@ main(argc, argv)
* Create option mask.
*/
(void) snpf(options, sizeof(options),
- "?a%sbc:%sD:d:%sf:F:g:hi:%s%slL:%s%snNo:Op:Pr:%ss:S:tT:u:UvVwx:%s%s%s",
+ "?a%sbc:%sD:d:%s%sf:F:g:hi:%s%slL:%s%snNo:Op:Pr:%ss:S:tT:u:UvVwx:%s%s%s",
#if defined(HAS_AFS) && defined(HASAOPT)
"A:",
@@ -174,6 +177,12 @@ main(argc, argv)
"",
#endif /* defined(HASEOPT) */
+#if defined(HASEPTOPTS)
+ "E",
+#else /* !defined(HASEPTOPTS) */
+ "",
+#endif /* defined(HASEPTOPTS) */
+
#if defined(HASKOPT)
"k:",
#else /* !defined(HASKOPT) */
@@ -311,15 +320,8 @@ main(argc, argv)
case 'C':
Fncache = (GOp == '-') ? 0 : 1;
break;
-#endif /* defined(HASNCACHE) */
-
-#if defined(HASEOPT)
- case 'e':
- if (enter_efsys(GOv, ((GOp == '+') ? 1 : 0)))
- err = 1;
- break;
-#endif /* defined(HASEOPT) */
+#endif /* defined(HASNCACHE) */
case 'd':
if (GOp == '+') {
if (enter_dir(GOv, 0))
@@ -353,6 +355,20 @@ main(argc, argv)
}
break;
+
+#if defined(HASEOPT)
+ case 'e':
+ if (enter_efsys(GOv, ((GOp == '+') ? 1 : 0)))
+ err = 1;
+ break;
+#endif /* defined(HASEOPT) */
+
+#if defined(HASEPTOPTS)
+ case 'E':
+ FpipeE = (GOp == '+') ? 2 : 1;
+ break;
+#endif /* defined(HASEPTOPTS) */
+
case 'f':
if (!GOv || *GOv == '-' || *GOv == '+') {
Ffilesys = (GOp == '+') ? 2 : 1;
@@ -1275,6 +1291,39 @@ main(argc, argv)
NcacheReload = 1;
#endif /* defined(HASNCACHE) */
+#if defined(HASEPTOPTS)
+ /*
+ * If endpoint info has been requested, make sure it is coded for
+ * printing.
+ *
+ * Lf contents must be preserved, since they may point to a
+ * malloc()'d area, and since Lf is used throughout the print
+ */
+ if (FpipeE) {
+ lf = Lf;
+
+ /*
+ * Check the files that have been selected for printing by
+ * by some selection criterion other than being a pipe.
+ */
+ for (i = 0; i < Nlproc; i++) {
+ Lp = (Nlproc > 1) ? slp[i] : &Lproc[i];
+ if (Lp->pss && (Lp->pipe & PS_PIPE))
+ (void) process_pinfo(0);
+ }
+ /*
+ * In a second pass, process unselected endpoint files,
+ * possibly selecting them for printing.
+ */
+ for (i = 0; i < Nlproc; i++) {
+ Lp = (Nlproc > 1) ? slp[i] : &Lproc[i];
+ if (Lp->pipe & PS_PIPE_END)
+ (void) process_pinfo(1);
+ }
+ Lf = lf;
+ }
+#endif /* defined(HASEPTOPTS) */
+
/*
* Print the selected processes and count them.
*
@@ -1301,6 +1350,11 @@ main(argc, argv)
* If conditional repeat mode is in effect, see if it's time to exit.
*/
if (RptTm) {
+
+#if defined(HASEPTOPTS)
+ (void) clear_pinfo();
+#endif /* defined(HASEPTOPTS) */
+
if (rc) {
if (!n)
break;
diff --git a/misc.c b/misc.c
index 20a6456..8a47ce9 100644
--- a/misc.c
+++ b/misc.c
@@ -32,7 +32,7 @@
#ifndef lint
static char copyright[] =
"@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n";
-static char *rcsid = "$Id: misc.c,v 1.27 2013/01/02 17:14:59 abe Exp $";
+static char *rcsid = "$Id: misc.c,v 1.28 2014/10/13 22:36:20 abe Exp $";
#endif
@@ -73,8 +73,6 @@ _PROTOTYPE(static int handleint,(int sig));
_PROTOTYPE(static void handleint,(int sig));
#endif /* defined(HASINTSIGNAL) */
-_PROTOTYPE(static char *safepup,(unsigned int c, int *cl));
-
/*
* Local variables
@@ -294,14 +292,14 @@ doinchild(fn, fp, rbuf, rbln)
* Begin the child process.
*/
- int fd, nd, r_al, r_rbln;
+ int fd, r_al, r_rbln;
char r_arg[MAXPATHLEN+1], r_rbuf[MAXPATHLEN+1];
int (*r_fn)();
/*
- * Close all open file descriptors except Pipes[0] and
+ * Close sufficient open file descriptors except Pipes[0] and
* Pipes[3].
*/
- for (fd = 0, nd = GET_MAX_FD(); fd < nd; fd++) {
+ for (fd = 0; fd < MaxFd; fd++) {
if (fd == Pipes[0] || fd == Pipes[3])
continue;
(void) close(fd);
@@ -1314,10 +1312,10 @@ readstqinit(addr, buf)
* cl = strlen(printable equivalent)
*/
-static char *
+char *
safepup(c, cl)
unsigned int c; /* unprintable (i.e., !isprint())
- * character */
+ * character and '\\' */
int *cl; /* returned printable strlen -- NULL if
* no return needed */
{
@@ -1350,6 +1348,9 @@ safepup(c, cl)
} else if (c == 0xff) {
rp = "^?";
len = 2;
+ } else if (c == '\\') {
+ rp = "\\\\";
+ len = 2;
} else {
(void) snpf(up, sizeof(up), "\\x%02x", (int)(c & 0xff));
rp = up;
@@ -1382,8 +1383,11 @@ safestrlen(sp, flags)
c = (flags & 2) ? ' ' : '\0';
if (sp) {
for (; *sp; sp++) {
- if (!isprint((unsigned char)*sp) || *sp == c) {
- if (*sp < 0x20 || (unsigned char)*sp == 0xff)
+ if (!isprint((unsigned char)*sp)
+ || (*sp == '\\') || (*sp == c))
+ {
+ if ((*sp < 0x20) || ((unsigned char)*sp == 0xff)
+ || (*sp == '\\'))
len += 2; /* length of \. or ^. form */
else
len += 4; /* length of "\x%02x" printf */
@@ -1457,7 +1461,7 @@ safestrprt(sp, fs, flags)
lnc = 1;
#endif /* defined(HASWIDECHAR) */
- if (isprint((unsigned char)*sp) && *sp != c)
+ if ((*sp != '\\') && isprint((unsigned char)*sp) && *sp != c)
putc((int)(*sp & 0xff), fs);
else {
if ((flags & 8) && (*sp == '\n') && !*(sp + 1))
@@ -1506,7 +1510,7 @@ safestrprtn(sp, len, fs, flags)
if (sp) {
c = (flags & 2) ? ' ' : '\0';
for (i = 0; i < len && *sp; sp++) {
- if (isprint((unsigned char)*sp) && *sp != c) {
+ if ((*sp != '\\') && isprint((unsigned char)*sp) && *sp != c) {
putc((int)(*sp & 0xff), fs);
i++;
} else {
diff --git a/proc.c b/proc.c
index f42d160..a75546a 100644
--- a/proc.c
+++ b/proc.c
@@ -32,7 +32,7 @@
#ifndef lint
static char copyright[] =
"@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n";
-static char *rcsid = "$Id: proc.c,v 1.47 2013/01/02 17:14:59 abe Exp $";
+static char *rcsid = "$Id: proc.c,v 1.48 2014/10/13 22:36:20 abe Exp $";
#endif
@@ -169,6 +169,10 @@ alloc_lfile(nm, num)
Lf->mnt_stat = (unsigned char)0;
#endif /* defined(HASMNTSTAT) */
+#if defined(HASEPTOPTS)
+ Lf->pipend = 0;
+#endif /* defined(HASEPTOPTS) */
+
#if defined(HASSOOPT)
Lf->lts.kai = Lf->lts.ltm = 0;
Lf->lts.opt = Lf->lts.qlen = Lf->lts.qlim = Lf->lts.pqlen
@@ -303,6 +307,10 @@ alloc_lproc(pid, pgid, ppid, uid, cmd, pss, sf)
Lp = &Lproc[Nlproc++];
Lp->pid = pid;
+#if defined(HASEPTOPTS)
+ Lp->pipe = 0;
+#endif /* defined(HASEPTOPTS) */
+
#if defined(HASTASKS)
Lp->tid = 0;
#endif /* defined(HASTASKS) */
@@ -882,6 +890,23 @@ link_lfile()
{
if (Lf->sf & SELEXCLF)
return;
+
+#if defined(HASEPTOPTS)
+/*
+ * If endpoint info has been requested, clear the SELPINFO flag from the local
+ * file structure, since it was set only to insure this file would be linked.
+ * While this might leave no file selection flags set, a later call to the
+ * process_pinfo() function might set some. Also set the PS_PIPE flag for
+ * the process.
+ *
+ * Also set the SELPINFO flag for the process.
+ */
+ if (FpipeE) {
+ Lf->sf &= ~SELPINFO;
+ Lp->pipe |= PS_PIPE;
+ }
+#endif /* defined(HASEPTOPTS) */
+
Lp->pss |= PS_SEC;
if (Plf)
Plf->next = Lf;
@@ -898,6 +923,107 @@ link_lfile()
}
+#if defined(HASEPTOPTS)
+/*
+ * process_pinfo() -- process pipe info, adding it to selected files and
+ * selecting pipe end files (if requested)
+ */
+
+void
+process_pinfo(f)
+ int f; /* function:
+ * 0 == process selected pipe
+ * 1 == process end point
+ */
+{
+ struct lproc *ep; /* pipe endpoint process */
+ struct lfile *ef; /* pipe endpoint file */
+ int i; /* temporary index */
+ char nma[1024]; /* name addition buffer */
+ pinfo_t *pp; /* previous pipe info */
+
+ if (!FpipeE)
+ return;
+ for (Lf = Lp->file; Lf; Lf = Lf->next) {
+ if ((Lf->ntype != N_FIFO) || (Lf->inp_ty != 1))
+ continue;
+ pp = (pinfo_t *)NULL;
+ switch(f) {
+ case 0:
+
+ /*
+ * Process already selected pipe file.
+ */
+ if (is_file_sel(Lp, Lf)) {
+
+ /*
+ * This file has been selected by some criterion other than its
+ * being a pipe. Look up the pipe's endpoints.
+ */
+ do {
+ if ((pp = find_pendinfo(Lf, pp))) {
+
+ /*
+ * This pipe endpoint is linked to the selected pipe
+ * file. Add its PID and FD to the name column
+ * addition.
+ */
+ ep = &Lproc[pp->lpx];
+ ef = pp->lf;
+ for (i = 0; i < (FDLEN - 1); i++) {
+ if (ef->fd[i] != ' ')
+ break;
+ }
+ (void) snpf(nma, sizeof(nma) - 1, "%d,%.*s,%s%c",
+ ep->pid, CmdLim, ep->cmd,&ef->fd[i],
+ ef->access);
+ (void) add_nma(nma, strlen(nma));
+ if (FpipeE == 2) {
+
+ /*
+ * Endpoint files have been selected, so mark this
+ * one for selection later.
+ */
+ ef->pipend = 1;
+ ep->pipe |= PS_PIPE_END;
+ }
+ pp = pp->next;
+ }
+ } while (pp);
+ }
+ break;
+ case 1:
+ if (!is_file_sel(Lp, Lf) && Lf->pipend) {
+
+ /*
+ * This is an unselected end point file. Select it and add
+ * its end point information to its name column addition.
+ */
+ Lf->sf = Selflags;
+ Lp->pss |= PS_SEC;
+ do {
+ if ((pp = find_pendinfo(Lf, pp))) {
+ ep = &Lproc[pp->lpx];
+ ef = pp->lf;
+ for (i = 0; i < (FDLEN - 1); i++) {
+ if (ef->fd[i] != ' ')
+ break;
+ }
+ (void) snpf(nma, sizeof(nma) - 1, "%d,%.*s,%s%c",
+ ep->pid, CmdLim, ep->cmd, &ef->fd[i],
+ ef->access);
+ (void) add_nma(nma, strlen(nma));
+ pp = pp->next;
+ }
+ } while (pp);
+ }
+ break;
+ }
+ }
+}
+#endif /* defined(HASEPTOPTS) */
+
+
#if defined(HASFSTRUCT)
/*
* print_fflags() - print interpreted f_flag[s]
@@ -1056,7 +1182,7 @@ print_proc()
(void) printf("%c%s%c", LSOF_FID_LOGIN, cp, Terminator);
}
if (Terminator == '\0')
- putchar('\n');
+ putchar('\n');
}
/*
* Print files.
@@ -1066,25 +1192,29 @@ print_proc()
continue;
rv = 1;
/*
- * If no field output selected, print dialects-specific formatted
+ * If no field output selected, print dialect-specific formatted
* output.
*/
if (!Ffield) {
print_file();
continue;
}
- /*
- * Print selected fields.
- */
lc = st = 0;
if (FieldSel[LSOF_FIX_FD].st) {
+
+ /*
+ * Skip leading spaces in the file descriptor. Print the field
+ * identifier even if there are no characters after leading
+ * spaces.
+ */
for (cp = Lf->fd; *cp == ' '; cp++)
;
- if (*cp) {
- (void) printf("%c%s%c", LSOF_FID_FD, cp, Terminator);
- lc++;
- }
+ (void) printf("%c%s%c", LSOF_FID_FD, cp, Terminator);
+ lc++;
}
+ /*
+ * Print selected fields.
+ */
if (FieldSel[LSOF_FIX_ACCESS].st) {
(void) printf("%c%c%c",
LSOF_FID_ACCESS, Lf->access, Terminator);
diff --git a/proto.h b/proto.h
index 5b12d00..040d667 100644
--- a/proto.h
+++ b/proto.h
@@ -31,7 +31,7 @@
/*
- * $Id: proto.h,v 1.36 2011/09/07 19:13:49 abe Exp $
+ * $Id: proto.h,v 1.37 2014/10/13 22:36:20 abe Exp $
*/
@@ -109,6 +109,13 @@ _PROTOTYPE(extern void ent_inaddr,(unsigned char *la, int lp, unsigned char *fa,
_PROTOTYPE(extern int examine_lproc,(void));
_PROTOTYPE(extern void Exit,(int xv)) exiting;
_PROTOTYPE(extern void find_ch_ino,(void));
+
+# if defined(HASEPTOPTS)
+_PROTOTYPE(extern void clear_pinfo,(void));
+_PROTOTYPE(extern pinfo_t *find_pendinfo,(struct lfile *lf, pinfo_t *pp));
+_PROTOTYPE(extern void process_pinfo,(int f));
+# endif /* defined(HASEPTOPTS) */
+
_PROTOTYPE(extern void free_lproc,(struct lproc *lp));
_PROTOTYPE(extern void gather_proc_info,(void));
_PROTOTYPE(extern char *gethostnm,(unsigned char *ia, int af));
@@ -162,6 +169,7 @@ _PROTOTYPE(extern char *Readlink,(char *arg));
_PROTOTYPE(extern void readdev,(int skip));
_PROTOTYPE(extern struct mounts *readmnt,(void));
_PROTOTYPE(extern void rereaddev,(void));
+_PROTOTYPE(extern char *safepup,(unsigned int c, int *cl));
_PROTOTYPE(extern int safestrlen,(char *sp, int flags));
_PROTOTYPE(extern void safestrprtn,(char *sp, int len, FILE *fs, int flags));
_PROTOTYPE(extern void safestrprt,(char *sp, FILE *fs, int flags));
diff --git a/store.c b/store.c
index 48948d8..55953bd 100644
--- a/store.c
+++ b/store.c
@@ -32,7 +32,7 @@
#ifndef lint
static char copyright[] =
"@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n";
-static char *rcsid = "$Id: store.c,v 1.41 2013/01/02 17:14:59 abe Exp $";
+static char *rcsid = "$Id: store.c,v 1.42 2014/10/13 22:36:20 abe Exp $";
#endif
@@ -156,6 +156,8 @@ int Fnfs = 0; /* -N option status: 0==none, 1==find all,
int Fnlink = 0; /* -L option status */
int Foffset = 0; /* -o option status */
int Fovhd = 0; /* -O option status */
+int FpipeE = 0; /* -E option status: 0==none, 1==info,
+ * 2==info+files */
int Fport = 1; /* -P option status */
#if !defined(HASNORPC_H)
@@ -207,7 +209,7 @@ struct fieldsel FieldSel[] = {
{ LSOF_FID_CT, 0, LSOF_FNM_CT, &Fsv, FSV_CT }, /* 2 */
{ LSOF_FID_DEVCH, 0, LSOF_FNM_DEVCH, NULL, 0 }, /* 3 */
{ LSOF_FID_DEVN, 0, LSOF_FNM_DEVN, NULL, 0 }, /* 4 */
- { LSOF_FID_FD, 0, LSOF_FNM_FD, NULL, 0 }, /* 5 */
+ { LSOF_FID_FD, 1, LSOF_FNM_FD, NULL, 0 }, /* 5 */
{ LSOF_FID_FA, 0, LSOF_FNM_FA, &Fsv, FSV_FA }, /* 6 */
{ LSOF_FID_FG, 0, LSOF_FNM_FG, &Fsv, FSV_FG }, /* 7 */
{ LSOF_FID_INODE, 0, LSOF_FNM_INODE, NULL, 0 }, /* 8 */
@@ -248,6 +250,7 @@ struct lproc *Lp = (struct lproc *)NULL;
/* current local process table entry */
struct lproc *Lproc = (struct lproc *)NULL;
/* local process table */
+int MaxFd; /* maximum file descriptors to close */
char *Memory = (char *)NULL; /* core file path */
int MntSup = 0; /* mount supplement state: 0 == none
* 1 == create
diff --git a/tests/TestDB b/tests/TestDB
index 1ad618e..e3f669f 100644
--- a/tests/TestDB
+++ b/tests/TestDB
@@ -5,7 +5,7 @@
#
# See Add2TestDB for a script that will build a line for this file.
#
-# $Id: TestDB,v 1.38 2013/01/02 17:03:58 abe Exp $
+# $Id: TestDB,v 1.39 2014/10/13 22:26:55 abe Exp $
LT_AIXA=0 LT_BIGF LT_CC LT_DIAL_aix LT_KMEM LT_VERS=4320
LT_AIXA=0 LT_BIGF LT_CC LT_DIAL_aix LT_KMEM LT_VERS=4330
@@ -59,8 +59,12 @@ LT_BIGF LT_CC LT_DIAL_freebsd LT_KMEM LT_VERS=7040
LT_BIGF LT_CC LT_DIAL_freebsd LT_KMEM LT_VERS=8000
LT_BIGF LT_CC LT_DIAL_freebsd LT_KMEM LT_VERS=8020
LT_BIGF LT_CC LT_DIAL_freebsd LT_KMEM LT_VERS=8030
+LT_BIGF LT_CC LT_DIAL_freebsd LT_KMEM LT_VERS=8040
LT_BIGF LT_CC LT_DIAL_freebsd LT_KMEM LT_VERS=9000
LT_BIGF LT_CC LT_DIAL_freebsd LT_KMEM LT_VERS=10000
+LT_BIGF LT_DIAL_freebsd LT_GCC LT_KMEM LT_VERS=10000
+LT_BIGF LT_CC LT_DIAL_freebsd LT_KMEM LT_VERS=11000
+LT_BIGF LT_DIAL_freebsd LT_GCC LT_KMEM LT_VERS=11000
LT_BIGF LT_CC LT_DIAL_hpux LT_KMEM LT_VERS=1020 _LARGEFILE64_SOURCE
LT_BIGF LT_DIAL_hpux LT_GCC LT_KMEM LT_VERS=1020 _LARGEFILE64_SOURCE
LT_BIGF LT_CC LT_DIAL_hpux LT_KMEM LT_VERS=1100 _LARGEFILE64_SOURCE
@@ -85,6 +89,7 @@ LT_BIGF LT_CC LT_DIAL_linux LT_VERS=26018 _FILE_OFFSET_BITS=64
LT_BIGF LT_CC LT_DIAL_linux LT_VERS=26022 _FILE_OFFSET_BITS=64
LT_BIGF LT_CC LT_DIAL_linux LT_VERS=26032 _FILE_OFFSET_BITS=64
LT_BIGF LT_CC LT_DIAL_linux LT_VERS=26038 _FILE_OFFSET_BITS=64
+LT_BIGF LT_CC LT_DIAL_linux LT_VERS=310004 _FILE_OFFSET_BITS=64
LT_BIGF LT_CC LT_DIAL_linux LT_VERS=31008 _FILE_OFFSET_BITS=64
LT_BIGF LT_CC LT_DIAL_netbsd LT_KMEM LT_VERS=1005000
LT_BIGF LT_CC LT_DIAL_netbsd LT_KMEM LT_VERS=1006000
diff --git a/usage.c b/usage.c
index 7060c21..5c92e46 100644
--- a/usage.c
+++ b/usage.c
@@ -32,7 +32,7 @@
#ifndef lint
static char copyright[] =
"@(#) Copyright 1998 Purdue Research Foundation.\nAll rights reserved.\n";
-static char *rcsid = "$Id: usage.c,v 1.31 2013/01/02 17:14:59 abe Exp $";
+static char *rcsid = "$Id: usage.c,v 1.32 2014/10/13 22:36:20 abe Exp $";
#endif
@@ -386,18 +386,29 @@ usage(xv, fh, version)
(void) fprintf(stderr, " [-A A]");
#endif /* defined(HAS_AFS) && defined(HASAOPT) */
- (void) fprintf(stderr, " [+|-c c] [+|-d s] [+%sD D]",
-
+ (void) fprintf(stderr, " [+|-c c] [+|-d s] [+%sD D]%s",
#if defined(HASDCACHE)
- "|-"
+ "|-",
#else /* !defined(HASDCACHE) */
- ""
+ "",
#endif /* defined(HASDCACHE) */
+#if defined(HASEPTOPTS)
+ " [+|-E]"
+#else /* !defined(HASEPTOPTS) */
+ ""
+#endif /* defined(HASEPTOPTS) */
+
);
(void) fprintf(stderr,
- " [+|-f%s%s%s%s%s%s]%s\n [-F [f]] [-g [s]] [-i [i]]",
+ " %s[+|-f%s%s%s%s%s%s]\n [-F [f]] [-g [s]] [-i [i]]",
+
+#if defined(HASEOPT)
+ "[+|-e s] ",
+#else /* !defined(HASEOPT) */
+ "",
+#endif /* defined(HASEOPT) */
#if defined(HASFSTRUCT)
"[",
@@ -426,17 +437,11 @@ usage(xv, fh, version)
"n",
# endif /* defined(HASNOFSNADDR) */
- "]",
+ "]"
#else /* !defined(HASFSTRUCT) */
- "", "", "", "", "", "",
+ "", "", "", "", "", ""
#endif /* defined(HASFSTRUCT) */
-#if defined(HASEOPT)
- " [+|-e s]"
-#else /* !defined(HASEOPT) */
- ""
-#endif /* defined(HASEOPT) */
-
);
#if defined(HASKOPT)
@@ -464,7 +469,7 @@ usage(xv, fh, version)
#endif /* !defined(HASNORPC_H) */
(void) fprintf(stderr,
- " [-o [o]] [-p s]\n[+|-r [t]]%s [-S [t]] [-T [t]]",
+ " [-o [o]] [-p s]\n [+|-r [t]]%s [-S [t]] [-T [t]]",
#if defined(HASTCPUDPSTATE)
" [-s [p:s]]"
@@ -601,6 +606,14 @@ usage(xv, fh, version)
col = print_in_col(col, "-- end option scan");
if (col != 1)
(void) fprintf(stderr, "\n");
+
+#if defined(HASEPTOPTS)
+ (void) fprintf(stderr, " %-36.36s %s\n",
+ "-E display endpoint info",
+ "+E display endpoint info and files"
+ );
+#endif /* defined(HASEPTOPTS) */
+
(void) fprintf(stderr, " %-36.36s",
"+f|-f +filesystem or -file names");
diff --git a/version b/version
index 95560d3..fdb27c3 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-.ds VN 4.87
+.ds VN 4.88