From 62de77c6731c615c7d95eb942af26373cb758d1f Mon Sep 17 00:00:00 2001
From: Apertis CI <devel@lists.apertis.org>
Date: Wed, 26 Feb 2025 15:43:31 +0000
Subject: [PATCH] Import Upstream version 4.99.4+dfsg

---
 .builds/netbsd.yml                            |   25 +
 .builds/openbsd.yml                           |   29 +
 .circleci/config.yml                          |  173 +
 .cirrus.yml                                   |   23 +
 .ck00MAN                                      |    1 +
 .clang-format                                 |    4 +
 .github/ISSUE_TEMPLATE/bug_report.md          |   32 +
 .github/ISSUE_TEMPLATE/feature_request.md     |   20 +
 .github/workflows/build.yml                   |   27 +
 .gitignore                                    |  169 +
 .readthedocs.yaml                             |   21 +
 .travis.yml                                   |   73 +
 00CREDITS                                     |  576 +-
 00DCACHE                                      |    3 -
 00DIALECTS                                    |   11 +-
 00DIST                                        |  320 +-
 00FAQ                                         |  316 +-
 00MANIFEST                                    |  314 +-
 00PORTING                                     |  129 +-
 00QUICKSTART                                  | 1048 +--
 00README                                      |   67 +-
 00TEST                                        |    8 +-
 00XCONFIG                                     |   42 +-
 AUTHORS                                       |    0
 COPYING                                       |   26 +
 Configure                                     | 1365 ++--
 Customize                                     |    2 +-
 Doxyfile                                      | 2733 +++++++
 HOW_TO_MAINTAIN.rst                           |    2 +
 HOW_TO_RELEASE.rst                            |    1 +
 INSTALL                                       |  368 +
 lsof.8 => Lsof.8                              |  155 +-
 Makefile.am                                   |  224 +
 NEWS                                          |    0
 README                                        |    1 +
 README.md                                     |   68 +-
 arg.c                                         | 2516 -------
 autotools/autotools.h.in                      |  257 +
 autotools/version.h.in                        |   49 +
 check.bash                                    |    8 +-
 configure.ac                                  |  598 ++
 default.nix                                   |   24 +
 dialects/linux/dfile.c                        |  386 -
 dialects/linux/dlsof.h                        |  191 -
 dialects/linux/dmnt.c                         |  710 --
 dialects/linux/dnode.c                        |  986 ---
 dialects/linux/dproc.c                        | 1919 -----
 dialects/linux/dsock.c                        | 5315 --------------
 dialects/linux/dstore.c                       |  127 -
 .../linux/tests/case-20-open-flags-cx.bash    |    4 -
 .../linux/tests/case-20-open-flags-path.bash  |    4 -
 .../linux/tests/case-20-open-flags-tmpf.bash  |    4 -
 dialects/linux/tests/epoll.c                  |   56 -
 dialects/linux/tests/eventfd.c                |   33 -
 dialects/linux/tests/mq_fork.c                |   51 -
 dialects/linux/tests/mq_open.c                |   31 -
 dialects/linux/tests/open_with_flags.c        |   69 -
 dialects/linux/tests/pidfd.c                  |   30 -
 dialects/linux/tests/pipe.c                   |   47 -
 dialects/linux/tests/pty.c                    |   52 -
 dialects/linux/tests/util-open-flags.bash     |   41 -
 dialects/linux/tests/ux.c                     |  154 -
 docs/contributing.md                          |   68 +
 docs/credits.md                               |  603 ++
 docs/faq.md                                   | 3085 ++++++++
 docs/getting-started.md                       |  107 +
 docs/index.md                                 |   59 +
 docs/maintaining.md                           |  243 +
 docs/manpage.md                               | 2919 ++++++++
 docs/manpage.sh                               |    8 +
 docs/options.md                               |  207 +
 docs/requirements.in                          |    1 +
 docs/requirements.txt                         |   40 +
 docs/tutorial.md                              |  699 ++
 include/lsof.h                                |  586 ++
 include/lsof_fields.h                         |  181 +
 lib/Makefile.skel                             |   16 +-
 lib/ckkv.c                                    |   92 +-
 lib/common.h                                  | 1543 ++++
 lib/cvfs.c                                    |  109 +-
 lib/dialects/aix/Makefile                     |  168 +
 lib/dialects/aix/Mksrc                        |   34 +
 lib/dialects/aix/aix5/README                  |    7 +
 lib/dialects/aix/aix5/j2/j2_lock.h            |   19 +
 .../aix/aix5/j2/private_j2_snapshot.h         |   17 +
 lib/dialects/aix/ddev.c                       |  686 ++
 lib/dialects/aix/dfile.c                      |  523 ++
 lib/dialects/aix/dlsof.h                      |  432 ++
 lib/dialects/aix/dmnt.c                       |  289 +
 lib/dialects/aix/dnode.c                      | 1257 ++++
 lib/dialects/aix/dnode1.c                     |  296 +
 lib/dialects/aix/dnode2.c                     |   75 +
 lib/dialects/aix/dproc.c                      | 1424 ++++
 lib/dialects/aix/dproto.h                     |   66 +
 lib/dialects/aix/dsock.c                      |  418 ++
 lib/dialects/aix/dstore.c                     |  398 ++
 lib/dialects/aix/machine.h                    |  631 ++
 lib/dialects/hpux/kmem/Makefile               |  160 +
 lib/dialects/hpux/kmem/Mksrc                  |   24 +
 lib/dialects/hpux/kmem/dfile.c                |  245 +
 lib/dialects/hpux/kmem/dlsof.h                |  439 ++
 lib/dialects/hpux/kmem/dmnt.c                 |  236 +
 lib/dialects/hpux/kmem/dnode.c                | 1052 +++
 lib/dialects/hpux/kmem/dnode1.c               |  145 +
 lib/dialects/hpux/kmem/dnode2.c               |  346 +
 lib/dialects/hpux/kmem/dproc.c                |  804 +++
 lib/dialects/hpux/kmem/dproto.h               |   67 +
 lib/dialects/hpux/kmem/dsock.c                | 1125 +++
 lib/dialects/hpux/kmem/dstore.c               |  226 +
 lib/dialects/hpux/kmem/hpux11/ipc_s.h         |   98 +
 lib/dialects/hpux/kmem/hpux11/kernbits.h      |   22 +
 lib/dialects/hpux/kmem/hpux11/lla.h           |   91 +
 lib/dialects/hpux/kmem/hpux11/nfs_clnt.h      |   76 +
 lib/dialects/hpux/kmem/hpux11/proc.h          |  243 +
 lib/dialects/hpux/kmem/hpux11/rnode.h         |   94 +
 lib/dialects/hpux/kmem/hpux11/sth.h           |   84 +
 lib/dialects/hpux/kmem/hpux11/tcp_s.h         |  208 +
 lib/dialects/hpux/kmem/hpux11/udp_s.h         |   79 +
 lib/dialects/hpux/kmem/hpux11/vnode.h         |  131 +
 lib/dialects/hpux/kmem/machine.h              |  608 ++
 lib/dialects/hpux/pstat/Makefile              |  149 +
 .../linux => lib/dialects/hpux/pstat}/Mksrc   |    9 +-
 lib/dialects/hpux/pstat/dfile.c               |  753 ++
 lib/dialects/hpux/pstat/dlsof.h               |  205 +
 lib/dialects/hpux/pstat/dproc.c               |  845 +++
 lib/dialects/hpux/pstat/dproto.h              |   55 +
 lib/dialects/hpux/pstat/dsock.c               | 1597 +++++
 lib/dialects/hpux/pstat/dstore.c              |   66 +
 lib/dialects/hpux/pstat/machine.h             |  590 ++
 {dialects => lib/dialects}/linux/Makefile     |   38 +-
 lib/dialects/linux/Mksrc                      |   37 +
 lib/dialects/linux/dfile.c                    |  347 +
 lib/dialects/linux/dlsof.h                    |  203 +
 lib/dialects/linux/dmnt.c                     |  696 ++
 lib/dialects/linux/dnode.c                    |  901 +++
 lib/dialects/linux/dproc.c                    | 1934 +++++
 lib/dialects/linux/dproto.h                   |   69 +
 lib/dialects/linux/dsock.c                    | 5013 +++++++++++++
 lib/dialects/linux/dstore.c                   |  117 +
 {dialects => lib/dialects}/linux/machine.h    |  130 +-
 .../dialects}/linux/tests/Makefile            |    1 +
 .../linux/tests/case-00-linux-hello.bash      |    0
 .../dialects}/linux/tests/case-10-mqueue.bash |   18 +-
 .../linux/tests/case-10-ux-socket-state.bash  |   14 +-
 .../dialects}/linux/tests/case-20-epoll.bash  |   13 +-
 .../linux/tests/case-20-eventfd-endpoint.bash |   16 +-
 .../tests/case-20-inet-socket-endpoint.bash   |   10 +-
 .../case-20-inet6-ffffffff-handling.bash      |   15 +-
 .../tests/case-20-inet6-socket-endpoint.bash  |   11 +-
 lib/dialects/linux/tests/case-20-mmap.bash    |   59 +
 .../linux/tests/case-20-mqueue-endpoint.bash  |   18 +-
 .../linux/tests/case-20-open-flags-cx.bash    |    5 +
 .../linux/tests/case-20-open-flags-path.bash  |    5 +
 .../linux/tests/case-20-open-flags-tmpf.bash  |    5 +
 .../linux/tests/case-20-pidfd-pid.bash        |   14 +-
 .../linux/tests/case-20-pipe-endpoint.bash    |   12 +-
 .../tests/case-20-pipe-no-close-endpoint.bash |   12 +-
 .../linux/tests/case-20-pty-endpoint.bash     |   22 +-
 ...case-20-ux-socket-endpoint-unaccepted.bash |   14 +-
 .../tests/case-20-ux-socket-endpoint.bash     |   10 +-
 lib/dialects/linux/tests/epoll.c              |   49 +
 lib/dialects/linux/tests/eventfd.c            |   29 +
 lib/dialects/linux/tests/mmap.c               |   35 +
 lib/dialects/linux/tests/mount-and-mmap.bash  |   20 +
 lib/dialects/linux/tests/mq_fork.c            |   43 +
 lib/dialects/linux/tests/mq_open.c            |   24 +
 lib/dialects/linux/tests/open_with_flags.c    |   63 +
 lib/dialects/linux/tests/pidfd.c              |   26 +
 lib/dialects/linux/tests/pipe.c               |   41 +
 lib/dialects/linux/tests/pty.c                |   48 +
 lib/dialects/linux/tests/util-open-flags.bash |   44 +
 lib/dialects/linux/tests/ux.c                 |  133 +
 lib/dialects/netbsd/Makefile                  |  158 +
 lib/dialects/netbsd/Mksrc                     |   32 +
 lib/dialects/netbsd/dlsof.h                   |  573 ++
 lib/dialects/netbsd/dmnt.c                    |  259 +
 lib/dialects/netbsd/dnode.c                   | 1449 ++++
 lib/dialects/netbsd/dnode1.c                  |   91 +
 lib/dialects/netbsd/dproc.c                   |  576 ++
 .../linux => lib/dialects/netbsd}/dproto.h    |   34 +-
 lib/dialects/netbsd/dsock.c                   |  438 ++
 lib/dialects/netbsd/dstore.c                  |  135 +
 lib/dialects/netbsd/machine.h                 |  575 ++
 lib/dialects/openbsd/Makefile                 |  158 +
 lib/dialects/openbsd/Mksrc                    |   32 +
 lib/dialects/openbsd/dfile.c                  |   75 +
 lib/dialects/openbsd/dlsof.h                  |  158 +
 lib/dialects/openbsd/dmnt.c                   |  160 +
 lib/dialects/openbsd/dnode.c                  |  159 +
 lib/dialects/openbsd/dproc.c                  |  233 +
 lib/dialects/openbsd/dproto.h                 |   43 +
 lib/dialects/openbsd/dsock.c                  |  187 +
 lib/dialects/openbsd/dstore.c                 |   90 +
 lib/dialects/openbsd/machine.h                |  564 ++
 .../openbsd/tests/case-00-openbsd-hello.bash  |    1 +
 lib/dialects/sun/Makefile                     |  159 +
 lib/dialects/sun/Mksrc                        |   27 +
 lib/dialects/sun/ddev.c                       | 1086 +++
 lib/dialects/sun/dfile.c                      |  590 ++
 lib/dialects/sun/distfile.kvm                 |   14 +
 lib/dialects/sun/dlsof.h                      |  697 ++
 lib/dialects/sun/dmnt.c                       |  396 ++
 lib/dialects/sun/dnode.c                      | 5268 ++++++++++++++
 lib/dialects/sun/dnode1.c                     |  414 ++
 lib/dialects/sun/dnode2.c                     |  483 ++
 lib/dialects/sun/dproc.c                      | 2138 ++++++
 lib/dialects/sun/dproto.h                     |  111 +
 lib/dialects/sun/dsock.c                      | 1996 ++++++
 lib/dialects/sun/dstore.c                     |  247 +
 lib/dialects/sun/machine.h                    |  696 ++
 lib/dialects/sun/solaris_kaddr_filters        |  239 +
 lib/dvch.c                                    | 2450 ++++---
 lib/fino.c                                    |  164 +-
 lib/hash.h                                    |   75 +
 lib/isfn.c                                    |  615 +-
 lib/lkud.c                                    |  279 +-
 lib/lsof.c                                    | 1113 +++
 lib/misc.c                                    | 1627 +++++
 lib/node.c                                    |  225 +
 lib/pdvn.c                                    |  228 +-
 lib/prfp.c                                    |  354 +-
 lib/print.c                                   | 1483 ++++
 lib/proc.c                                    | 1402 ++++
 lib/proto.h                                   |  331 +
 lib/ptti.c                                    | 1369 ----
 lib/rdev.c                                    |  774 +-
 lib/regex.c                                   | 6328 -----------------
 lib/rmnt.c                                    |  335 +-
 lib/rnam.c                                    | 1033 ++-
 lib/rnch.c                                    | 1271 ++--
 lib/rnmh.c                                    | 1142 ++-
 lib/rnmt.c                                    |  212 +
 lib/snpf.c                                    |  749 --
 lsof.h                                        | 1108 ---
 lsof.man                                      |    4 -
 lsof_fields.h                                 |  184 -
 m4/.gitignore                                 |    2 +
 m4/header.m4                                  |   82 +
 main.c                                        | 2000 ------
 misc.c                                        | 1707 -----
 mkdocs.yml                                    |   18 +
 node.c                                        |  257 -
 print.c                                       | 2846 --------
 proc.c                                        | 1794 -----
 proto.h                                       |  331 -
 regex.h                                       |  617 --
 scripts/big_brother.pl                        |    2 +-
 scripts/identd.pl                             |    2 +-
 scripts/shared.pl                             |    2 +-
 scripts/sort_res.pl                           |    2 +-
 src/arg.c                                     | 2193 ++++++
 src/cli.h                                     |   37 +
 src/dialects/linux/dprint.c                   |  199 +
 src/main.c                                    | 1956 +++++
 src/print.c                                   | 2137 ++++++
 src/ptti.c                                    | 1355 ++++
 src/store.c                                   |  176 +
 src/usage.c                                   |  997 +++
 util.c => src/util.c                          |   41 +-
 store.c                                       |  401 --
 support/AIXDistrib                            |   14 +
 support/DarwinDistrib                         |   14 +
 support/Distfile.msrc                         |   17 +
 support/FreeBSDDistrib                        |   14 +
 support/GPGDistrib                            |  493 ++
 support/GenericCopy                           |   88 +
 support/GenericDistrib                        |   70 +
 support/GenericDistrib2                       |    1 +
 support/GenericRdist                          |   80 +
 support/GenericSubdir                         |  106 +
 support/GitHub-release/00README               |   10 +
 support/GitHub-release/ITaP                   |   47 +
 support/GitHub-release/Purdue                 |  156 +
 support/HPUXDistrib                           |   14 +
 support/NSDistrib                             |   14 +
 support/NetBSDDistrib                         |   14 +
 support/OSRDistrib                            |   15 +
 support/OpenBSDDistrib                        |   14 +
 support/SpecialRdist                          |   74 +
 support/SunDistrib                            |   14 +
 support/UWDistrib                             |   15 +
 support/argtest                               |  104 +
 support/binaries/README                       |   27 +
 support/contrib.00INDEX                       |   22 +
 support/contrib.README                        |    8 +
 support/install-lsof                          |  143 +
 support/install.log                           |  156 +
 support/look_rlog                             |   21 +
 support/lsof-log.xls                          |    0
 support/lsof.00INDEX                          |  128 +
 support/lsof.README                           |  326 +
 support/makeman                               |   46 +
 support/mentor                                |    5 +
 support/mirrors                               |    9 +
 support/rdist.distrib                         |   10 +
 tests/00README                                |  102 +
 tests/LTbasic.c                               |  635 +-
 tests/LTbasic2.c                              |   99 +
 tests/LTbigf.c                                | 1017 ++-
 tests/LTdnlc.c                                |  562 +-
 tests/LTlib.c                                 | 1412 ++--
 tests/LTlock.c                                |  984 ++-
 tests/LTnfs.c                                 |  796 +--
 tests/LTnlink.c                               |  881 ++-
 tests/LTsock.c                                | 1238 ++--
 tests/LTszoff.c                               |  713 +-
 tests/LTunix.c                                |  471 +-
 tests/LsofTest.h                              |  376 +-
 tests/Makefile                                |    2 +-
 tests/TestDB                                  |    9 +
 tests/case-01-version.bash                    |    6 +-
 tests/case-14-classic-opt.bash                |    2 +-
 tests/case-20-exit-status.bash                |   10 +-
 tests/case-20-fd-only-inclusion.bash          |    5 +-
 tests/case-20-handle-missing-files.bash       |    6 +-
 tests/case-20-offset-field.bash               |    6 +-
 tests/case-20-repeat-count.bash               |   16 +-
 tests/case-21-exit-Q-status.bash              |    7 +-
 tests/case-22-empty-process-name.bash         |   31 +
 tests/common.bash                             |   14 +
 usage.c                                       |  977 ---
 version                                       |    2 +-
 version.in                                    |    1 +
 zipme                                         |   16 +
 324 files changed, 91704 insertions(+), 46261 deletions(-)
 create mode 100644 .builds/netbsd.yml
 create mode 100644 .builds/openbsd.yml
 create mode 100644 .circleci/config.yml
 create mode 100644 .cirrus.yml
 create mode 100644 .ck00MAN
 create mode 100644 .clang-format
 create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md
 create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md
 create mode 100644 .github/workflows/build.yml
 create mode 100644 .gitignore
 create mode 100644 .readthedocs.yaml
 create mode 100644 .travis.yml
 create mode 100644 AUTHORS
 create mode 100644 COPYING
 create mode 100644 Doxyfile
 create mode 100644 HOW_TO_MAINTAIN.rst
 create mode 100644 HOW_TO_RELEASE.rst
 create mode 100644 INSTALL
 rename lsof.8 => Lsof.8 (97%)
 create mode 100644 Makefile.am
 create mode 100644 NEWS
 create mode 120000 README
 delete mode 100644 arg.c
 create mode 100644 autotools/autotools.h.in
 create mode 100644 autotools/version.h.in
 create mode 100644 configure.ac
 create mode 100644 default.nix
 delete mode 100644 dialects/linux/dfile.c
 delete mode 100644 dialects/linux/dlsof.h
 delete mode 100644 dialects/linux/dmnt.c
 delete mode 100644 dialects/linux/dnode.c
 delete mode 100644 dialects/linux/dproc.c
 delete mode 100644 dialects/linux/dsock.c
 delete mode 100644 dialects/linux/dstore.c
 delete mode 100755 dialects/linux/tests/case-20-open-flags-cx.bash
 delete mode 100755 dialects/linux/tests/case-20-open-flags-path.bash
 delete mode 100755 dialects/linux/tests/case-20-open-flags-tmpf.bash
 delete mode 100644 dialects/linux/tests/epoll.c
 delete mode 100644 dialects/linux/tests/eventfd.c
 delete mode 100644 dialects/linux/tests/mq_fork.c
 delete mode 100644 dialects/linux/tests/mq_open.c
 delete mode 100644 dialects/linux/tests/open_with_flags.c
 delete mode 100644 dialects/linux/tests/pidfd.c
 delete mode 100644 dialects/linux/tests/pipe.c
 delete mode 100644 dialects/linux/tests/pty.c
 delete mode 100644 dialects/linux/tests/util-open-flags.bash
 delete mode 100644 dialects/linux/tests/ux.c
 create mode 100644 docs/contributing.md
 create mode 100644 docs/credits.md
 create mode 100644 docs/faq.md
 create mode 100644 docs/getting-started.md
 create mode 100644 docs/index.md
 create mode 100644 docs/maintaining.md
 create mode 100644 docs/manpage.md
 create mode 100755 docs/manpage.sh
 create mode 100644 docs/options.md
 create mode 100644 docs/requirements.in
 create mode 100644 docs/requirements.txt
 create mode 100644 docs/tutorial.md
 create mode 100644 include/lsof.h
 create mode 100644 include/lsof_fields.h
 create mode 100644 lib/common.h
 create mode 100644 lib/dialects/aix/Makefile
 create mode 100755 lib/dialects/aix/Mksrc
 create mode 100644 lib/dialects/aix/aix5/README
 create mode 100644 lib/dialects/aix/aix5/j2/j2_lock.h
 create mode 100644 lib/dialects/aix/aix5/j2/private_j2_snapshot.h
 create mode 100644 lib/dialects/aix/ddev.c
 create mode 100644 lib/dialects/aix/dfile.c
 create mode 100644 lib/dialects/aix/dlsof.h
 create mode 100644 lib/dialects/aix/dmnt.c
 create mode 100644 lib/dialects/aix/dnode.c
 create mode 100644 lib/dialects/aix/dnode1.c
 create mode 100644 lib/dialects/aix/dnode2.c
 create mode 100644 lib/dialects/aix/dproc.c
 create mode 100644 lib/dialects/aix/dproto.h
 create mode 100644 lib/dialects/aix/dsock.c
 create mode 100644 lib/dialects/aix/dstore.c
 create mode 100644 lib/dialects/aix/machine.h
 create mode 100644 lib/dialects/hpux/kmem/Makefile
 create mode 100755 lib/dialects/hpux/kmem/Mksrc
 create mode 100644 lib/dialects/hpux/kmem/dfile.c
 create mode 100644 lib/dialects/hpux/kmem/dlsof.h
 create mode 100644 lib/dialects/hpux/kmem/dmnt.c
 create mode 100644 lib/dialects/hpux/kmem/dnode.c
 create mode 100644 lib/dialects/hpux/kmem/dnode1.c
 create mode 100644 lib/dialects/hpux/kmem/dnode2.c
 create mode 100644 lib/dialects/hpux/kmem/dproc.c
 create mode 100644 lib/dialects/hpux/kmem/dproto.h
 create mode 100644 lib/dialects/hpux/kmem/dsock.c
 create mode 100644 lib/dialects/hpux/kmem/dstore.c
 create mode 100644 lib/dialects/hpux/kmem/hpux11/ipc_s.h
 create mode 100644 lib/dialects/hpux/kmem/hpux11/kernbits.h
 create mode 100644 lib/dialects/hpux/kmem/hpux11/lla.h
 create mode 100644 lib/dialects/hpux/kmem/hpux11/nfs_clnt.h
 create mode 100644 lib/dialects/hpux/kmem/hpux11/proc.h
 create mode 100644 lib/dialects/hpux/kmem/hpux11/rnode.h
 create mode 100644 lib/dialects/hpux/kmem/hpux11/sth.h
 create mode 100644 lib/dialects/hpux/kmem/hpux11/tcp_s.h
 create mode 100644 lib/dialects/hpux/kmem/hpux11/udp_s.h
 create mode 100644 lib/dialects/hpux/kmem/hpux11/vnode.h
 create mode 100644 lib/dialects/hpux/kmem/machine.h
 create mode 100644 lib/dialects/hpux/pstat/Makefile
 rename {dialects/linux => lib/dialects/hpux/pstat}/Mksrc (64%)
 create mode 100644 lib/dialects/hpux/pstat/dfile.c
 create mode 100644 lib/dialects/hpux/pstat/dlsof.h
 create mode 100644 lib/dialects/hpux/pstat/dproc.c
 create mode 100644 lib/dialects/hpux/pstat/dproto.h
 create mode 100644 lib/dialects/hpux/pstat/dsock.c
 create mode 100644 lib/dialects/hpux/pstat/dstore.c
 create mode 100644 lib/dialects/hpux/pstat/machine.h
 rename {dialects => lib/dialects}/linux/Makefile (76%)
 create mode 100755 lib/dialects/linux/Mksrc
 create mode 100644 lib/dialects/linux/dfile.c
 create mode 100644 lib/dialects/linux/dlsof.h
 create mode 100644 lib/dialects/linux/dmnt.c
 create mode 100644 lib/dialects/linux/dnode.c
 create mode 100644 lib/dialects/linux/dproc.c
 create mode 100644 lib/dialects/linux/dproto.h
 create mode 100644 lib/dialects/linux/dsock.c
 create mode 100644 lib/dialects/linux/dstore.c
 rename {dialects => lib/dialects}/linux/machine.h (92%)
 rename {dialects => lib/dialects}/linux/tests/Makefile (98%)
 rename {dialects => lib/dialects}/linux/tests/case-00-linux-hello.bash (100%)
 rename {dialects => lib/dialects}/linux/tests/case-10-mqueue.bash (83%)
 rename {dialects => lib/dialects}/linux/tests/case-10-ux-socket-state.bash (88%)
 rename {dialects => lib/dialects}/linux/tests/case-20-epoll.bash (74%)
 rename {dialects => lib/dialects}/linux/tests/case-20-eventfd-endpoint.bash (93%)
 rename {dialects => lib/dialects}/linux/tests/case-20-inet-socket-endpoint.bash (84%)
 rename {dialects => lib/dialects}/linux/tests/case-20-inet6-ffffffff-handling.bash (77%)
 rename {dialects => lib/dialects}/linux/tests/case-20-inet6-socket-endpoint.bash (86%)
 create mode 100755 lib/dialects/linux/tests/case-20-mmap.bash
 rename {dialects => lib/dialects}/linux/tests/case-20-mqueue-endpoint.bash (91%)
 create mode 100755 lib/dialects/linux/tests/case-20-open-flags-cx.bash
 create mode 100755 lib/dialects/linux/tests/case-20-open-flags-path.bash
 create mode 100755 lib/dialects/linux/tests/case-20-open-flags-tmpf.bash
 rename {dialects => lib/dialects}/linux/tests/case-20-pidfd-pid.bash (57%)
 rename {dialects => lib/dialects}/linux/tests/case-20-pipe-endpoint.bash (90%)
 rename {dialects => lib/dialects}/linux/tests/case-20-pipe-no-close-endpoint.bash (95%)
 rename {dialects => lib/dialects}/linux/tests/case-20-pty-endpoint.bash (93%)
 rename {dialects => lib/dialects}/linux/tests/case-20-ux-socket-endpoint-unaccepted.bash (93%)
 rename {dialects => lib/dialects}/linux/tests/case-20-ux-socket-endpoint.bash (84%)
 create mode 100644 lib/dialects/linux/tests/epoll.c
 create mode 100644 lib/dialects/linux/tests/eventfd.c
 create mode 100644 lib/dialects/linux/tests/mmap.c
 create mode 100755 lib/dialects/linux/tests/mount-and-mmap.bash
 create mode 100644 lib/dialects/linux/tests/mq_fork.c
 create mode 100644 lib/dialects/linux/tests/mq_open.c
 create mode 100644 lib/dialects/linux/tests/open_with_flags.c
 create mode 100644 lib/dialects/linux/tests/pidfd.c
 create mode 100644 lib/dialects/linux/tests/pipe.c
 create mode 100644 lib/dialects/linux/tests/pty.c
 create mode 100644 lib/dialects/linux/tests/util-open-flags.bash
 create mode 100644 lib/dialects/linux/tests/ux.c
 create mode 100644 lib/dialects/netbsd/Makefile
 create mode 100755 lib/dialects/netbsd/Mksrc
 create mode 100644 lib/dialects/netbsd/dlsof.h
 create mode 100644 lib/dialects/netbsd/dmnt.c
 create mode 100644 lib/dialects/netbsd/dnode.c
 create mode 100644 lib/dialects/netbsd/dnode1.c
 create mode 100644 lib/dialects/netbsd/dproc.c
 rename {dialects/linux => lib/dialects/netbsd}/dproto.h (50%)
 create mode 100644 lib/dialects/netbsd/dsock.c
 create mode 100644 lib/dialects/netbsd/dstore.c
 create mode 100644 lib/dialects/netbsd/machine.h
 create mode 100644 lib/dialects/openbsd/Makefile
 create mode 100755 lib/dialects/openbsd/Mksrc
 create mode 100644 lib/dialects/openbsd/dfile.c
 create mode 100644 lib/dialects/openbsd/dlsof.h
 create mode 100644 lib/dialects/openbsd/dmnt.c
 create mode 100644 lib/dialects/openbsd/dnode.c
 create mode 100644 lib/dialects/openbsd/dproc.c
 create mode 100644 lib/dialects/openbsd/dproto.h
 create mode 100644 lib/dialects/openbsd/dsock.c
 create mode 100644 lib/dialects/openbsd/dstore.c
 create mode 100644 lib/dialects/openbsd/machine.h
 create mode 100755 lib/dialects/openbsd/tests/case-00-openbsd-hello.bash
 create mode 100644 lib/dialects/sun/Makefile
 create mode 100755 lib/dialects/sun/Mksrc
 create mode 100644 lib/dialects/sun/ddev.c
 create mode 100644 lib/dialects/sun/dfile.c
 create mode 100644 lib/dialects/sun/distfile.kvm
 create mode 100644 lib/dialects/sun/dlsof.h
 create mode 100644 lib/dialects/sun/dmnt.c
 create mode 100644 lib/dialects/sun/dnode.c
 create mode 100644 lib/dialects/sun/dnode1.c
 create mode 100644 lib/dialects/sun/dnode2.c
 create mode 100644 lib/dialects/sun/dproc.c
 create mode 100644 lib/dialects/sun/dproto.h
 create mode 100644 lib/dialects/sun/dsock.c
 create mode 100644 lib/dialects/sun/dstore.c
 create mode 100644 lib/dialects/sun/machine.h
 create mode 100644 lib/dialects/sun/solaris_kaddr_filters
 create mode 100644 lib/hash.h
 create mode 100644 lib/lsof.c
 create mode 100644 lib/misc.c
 create mode 100644 lib/node.c
 create mode 100644 lib/print.c
 create mode 100644 lib/proc.c
 create mode 100644 lib/proto.h
 delete mode 100644 lib/regex.c
 create mode 100644 lib/rnmt.c
 delete mode 100644 lib/snpf.c
 delete mode 100644 lsof.h
 delete mode 100644 lsof.man
 delete mode 100644 lsof_fields.h
 create mode 100644 m4/.gitignore
 create mode 100644 m4/header.m4
 delete mode 100644 main.c
 delete mode 100644 misc.c
 create mode 100644 mkdocs.yml
 delete mode 100644 node.c
 delete mode 100644 print.c
 delete mode 100644 proc.c
 delete mode 100644 proto.h
 delete mode 100644 regex.h
 create mode 100644 src/arg.c
 create mode 100644 src/cli.h
 create mode 100644 src/dialects/linux/dprint.c
 create mode 100644 src/main.c
 create mode 100644 src/print.c
 create mode 100644 src/ptti.c
 create mode 100644 src/store.c
 create mode 100644 src/usage.c
 rename util.c => src/util.c (71%)
 delete mode 100644 store.c
 create mode 100755 support/AIXDistrib
 create mode 100755 support/DarwinDistrib
 create mode 100644 support/Distfile.msrc
 create mode 100755 support/FreeBSDDistrib
 create mode 100755 support/GPGDistrib
 create mode 100755 support/GenericCopy
 create mode 100755 support/GenericDistrib
 create mode 120000 support/GenericDistrib2
 create mode 100755 support/GenericRdist
 create mode 100755 support/GenericSubdir
 create mode 100644 support/GitHub-release/00README
 create mode 100644 support/GitHub-release/ITaP
 create mode 100644 support/GitHub-release/Purdue
 create mode 100755 support/HPUXDistrib
 create mode 100755 support/NSDistrib
 create mode 100755 support/NetBSDDistrib
 create mode 100755 support/OSRDistrib
 create mode 100755 support/OpenBSDDistrib
 create mode 100755 support/SpecialRdist
 create mode 100755 support/SunDistrib
 create mode 100755 support/UWDistrib
 create mode 100755 support/argtest
 create mode 100644 support/binaries/README
 create mode 100644 support/contrib.00INDEX
 create mode 100644 support/contrib.README
 create mode 100755 support/install-lsof
 create mode 100644 support/install.log
 create mode 100755 support/look_rlog
 create mode 100644 support/lsof-log.xls
 create mode 100644 support/lsof.00INDEX
 create mode 100644 support/lsof.README
 create mode 100755 support/makeman
 create mode 100755 support/mentor
 create mode 100644 support/mirrors
 create mode 100755 support/rdist.distrib
 create mode 100644 tests/00README
 create mode 100644 tests/LTbasic2.c
 create mode 100755 tests/case-22-empty-process-name.bash
 create mode 100644 tests/common.bash
 delete mode 100644 usage.c
 create mode 100644 version.in
 create mode 100755 zipme

diff --git a/.builds/netbsd.yml b/.builds/netbsd.yml
new file mode 100644
index 0000000..f053658
--- /dev/null
+++ b/.builds/netbsd.yml
@@ -0,0 +1,25 @@
+image: netbsd/9.x
+packages:
+  - autoconf
+  - automake
+  - pkg-config
+  - libtool
+  - groff
+tasks:
+  - syssrc: |
+      curl https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.2/source/sets/syssrc.tgz -o syssrc.tgz
+      sudo mkdir -p /usr/src
+      cd / && sudo tar -zxf ~/syssrc.tgz
+  - setup: |
+      cd lsof
+      autoreconf -vif
+      ./configure
+  - build: |
+      cd lsof
+      export PATH=/usr/pkg/gnu/bin:$PATH
+      make
+  - test: |
+      cd lsof
+      export PATH=/usr/pkg/gnu/bin:$PATH
+      sudo make check
+      sudo make distcheck
diff --git a/.builds/openbsd.yml b/.builds/openbsd.yml
new file mode 100644
index 0000000..a74e21f
--- /dev/null
+++ b/.builds/openbsd.yml
@@ -0,0 +1,29 @@
+image: openbsd/7.2
+packages:
+  - autoconf-2.71
+  - automake-1.16.5
+  - pkgconf
+  - libtool
+  - groff
+tasks:
+  - legacy: |
+      cd lsof
+      ./Configure -n openbsd
+      make
+      bash ./check.bash openbsd
+      git clean -fdx .
+  - setup: |
+      cd lsof
+      export AUTOCONF_VERSION=2.71
+      export AUTOMAKE_VERSION=1.16
+      autoreconf -vif
+      ./configure
+  - build: |
+      cd lsof
+      make
+  - test: |
+      cd lsof
+      export AUTOCONF_VERSION=2.71
+      export AUTOMAKE_VERSION=1.16
+      make check
+      make distcheck
diff --git a/.circleci/config.yml b/.circleci/config.yml
new file mode 100644
index 0000000..b7f18d5
--- /dev/null
+++ b/.circleci/config.yml
@@ -0,0 +1,173 @@
+# Use the latest 2.1 version of CircleCI pipeline process engine.
+# See: https://circleci.com/docs/2.0/configuration-reference
+version: 2.1
+
+executors:
+  ubuntu2204:
+    machine:
+      image: ubuntu-2204:2022.10.2 
+  alpine317:
+    docker:
+      - image: docker.io/alpine:3.17
+  opensuse15:
+    docker:
+      - image: docker.io/opensuse/leap:15
+  archlinux:
+    docker:
+      - image: docker.io/archlinux:latest
+  debian11:
+    docker:
+      - image: docker.io/debian:11
+  debian12:
+    docker:
+      - image: docker.io/debian:12
+  fedora37:
+    docker:
+      - image: docker.io/fedora:37
+  fedora38:
+    docker:
+      - image: docker.io/fedora:38
+  centos9:
+    docker:
+      - image: quay.io/centos/centos:stream9
+
+# Define a job to be invoked later in a workflow.
+# See: https://circleci.com/docs/2.0/configuration-reference/#jobs
+jobs:
+  linux:
+    parameters:
+      distro:
+        type: executor
+    executor: << parameters.distro >>
+    steps:
+      - run:
+          name: Install build tools
+          command: |
+            dnf -y install autoconf automake gcc git iproute libtool make nmap-ncat pkg-config procps sudo || true
+            dnf -y install libtirpc-devel || true
+            dnf -y install make || true
+            apt update || true
+            apt install -y autoconf automake gcc git groff iproute2 libtirpc-dev libtool make ncat pkg-config procps sudo || true
+            pacman -Sy --noconfirm autoconf automake gcc git groff iproute2 libtool make pkg-config procps sudo || true
+            zypper install -y autoconf automake gcc git groff gzip iproute2 libtool make pkg-config procps sudo tar make || true
+            apk add sudo autoconf automake bash gcc git groff gzip iproute2 libtool linux-headers make musl-dev nmap-ncat pkgconf strace which || true
+      - when:
+          condition:
+            equal: [ fedora38, << parameters.distro >> ]
+          steps:
+            - run:
+                command: |
+                  dnf -y install lcov gem procps python3-pip
+                  pip3 install --user cpp-coveralls
+      - checkout
+      - run:
+          name: Configure
+          command: |
+            ./Configure -n linux
+      - when:
+          condition:
+            equal: [ fedora38, << parameters.distro >> ]
+          steps:
+            - run:
+                name: Build
+                command: |
+                  CC="cc"
+                  CC_EXTRA="--coverage"
+                  make -j 2 CDEF="${CC_EXTRA}" CC="${CC} ${CC_EXTRA}"
+      - when:
+          condition:
+            not:
+              equal: [ fedora38, << parameters.distro >> ]
+          steps:
+            - run:
+                name: Build
+                command: |
+                  make -j 2
+      - run:
+          name: Test
+          command: |
+            bash ./check.bash linux
+      - when:
+          condition:
+            equal: [ fedora38, << parameters.distro >> ]
+          steps:
+            - run:
+                name: Report coverage
+                command: |
+                  lcov -c -b . -d . -o coverage.info
+                  /root/.local/bin/coveralls --root .
+      - run:
+          name: Build and test using autotools
+          command: |
+            git clean -fdx .
+            autoreconf -vif
+            ./configure
+            make
+            sudo make install
+            make check
+            cat test-suite.log
+            make distcheck
+  nixos:
+    docker:
+      - image: docker.io/nixos/nix:latest
+    steps:
+      - checkout
+      - run:
+          name: Build
+          command: |
+            nix-channel --update
+            nix-build
+  ventura:
+    macos:
+      xcode: 13.4.1
+    steps:
+      - checkout
+      - run:
+          name: Install pkg-config
+          command: |
+            brew install pkg-config libtool autoconf automake
+      - run:
+          name: Configure
+          command: |
+            LSOF_INCLUDE=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include ./Configure -n darwin
+      - run:
+          name: Build
+          command: |
+            make -j 2
+      - run:
+          name: Test
+          command: |
+            bash ./check.bash darwin
+      - run:
+          name: Build using autotools
+          command: |
+            git clean -fdx .
+            autoreconf -vif
+            ./configure
+            make
+            DESTDIR=$PWD/prefix make install
+            make check
+      - run:
+          name: Rebuild and test using distribution tarball
+          command: |
+            make dist
+            mkdir temp
+            cd temp
+            tar xvf ../lsof-*.tar.gz
+            cd lsof-*
+            ./configure
+            make
+            DESTDIR=$PWD/prefix make install
+            make check
+
+# Invoke jobs via workflows
+# See: https://circleci.com/docs/2.0/configuration-reference/#workflows
+workflows:
+  gnulinux-workflow:
+    jobs:
+      - linux:
+          matrix:
+            parameters:
+              distro: [fedora37, fedora38, centos9, debian11, debian12, ubuntu2204, archlinux, opensuse15, alpine317]
+      - nixos
+      - ventura
diff --git a/.cirrus.yml b/.cirrus.yml
new file mode 100644
index 0000000..41751e6
--- /dev/null
+++ b/.cirrus.yml
@@ -0,0 +1,23 @@
+task:
+  freebsd_instance:
+    cpu: 1
+    matrix:
+      - image_family: freebsd-15-0-snap
+      - image_family: freebsd-14-0
+      - image_family: freebsd-13-3
+  install_script: pkg install -y bash git autoconf automake libtool groff pkgconf
+  build_script:
+    - ./Configure -n freebsd
+    - make
+  test_script:
+    - bash ./check.bash freebsd
+  autotools_build_script:
+    - git clean -fdx .
+    - autoreconf -vif
+    - ./configure
+    - make
+    - make install
+  autotools_test_script:
+    - make check
+    - cat test-suite.log
+    - make distcheck
diff --git a/.ck00MAN b/.ck00MAN
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/.ck00MAN
@@ -0,0 +1 @@
+
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..4c5f9db
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,4 @@
+BasedOnStyle: LLVM
+IndentWidth: 4
+SortIncludes: Never
+IndentPPDirectives: AfterHash
\ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 0000000..32c0248
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,32 @@
+---
+name: Bug report
+about: Create a bug report to help us improve
+title: "[BUG]"
+labels: ''
+assignees: ''
+
+---
+
+**Describe the bug**
+A clear and concise description of what the bug is.
+
+**To Reproduce**
+Steps to reproduce the behavior:
+1. Run '...'
+2. See error
+
+**Expected behavior**
+A clear and concise description of what you expected to happen.
+
+**Program output**
+If applicable, paste program output text here to help explain your problem.
+
+**Environment (please complete the following information):**
+
+ - Kernel: [e.g. Linux]
+ - OS: [e.g. Debian]
+ - lsof Version: [e.g. 4.xx.x]
+ - Origin: [e.g. installed by package manager, built from release tarball or git]
+
+**Additional context**
+Add any other context about the problem here.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 0000000..e0c0168
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,20 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+title: "[FEATURE]"
+labels: ''
+assignees: ''
+
+---
+
+**Is your feature request related to a problem? Please describe.**
+A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+
+**Describe the solution you'd like**
+A clear and concise description of what you want to happen.
+
+**Describe alternatives you've considered**
+A clear and concise description of any alternative solutions or features you've considered.
+
+**Additional context**
+Add any other context or screenshots about the feature request here.
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 0000000..dddd2c2
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,27 @@
+name: C/C++ CI
+
+on:
+  push:
+  pull_request:
+    branches: [ "master" ]
+
+jobs:
+  build:
+    strategy:
+      matrix:
+        os: [ubuntu-22.04, ubuntu-20.04]
+    runs-on: ${{ matrix.os }}
+    steps:
+    - uses: actions/checkout@v3
+    - name: install dependencies
+      run: sudo apt install -y pkg-config
+    - name: autoconf
+      run: autoreconf -vif
+    - name: configure
+      run: ./configure
+    - name: make
+      run: make
+    - name: make check
+      run: make check
+    - name: make distcheck
+      run: make distcheck
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..372c43d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,169 @@
+#
+# Glob patterns generated by GitHub
+#
+# Prerequisites
+*.d
+
+# Object files
+*.o
+*.ko
+*.obj
+*.elf
+
+# Linker output
+*.ilk
+*.map
+*.exp
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Libraries
+*.lib
+*.a
+*.la
+*.lo
+
+# Shared objects (inc. Windows DLLs)
+*.dll
+*.so
+*.so.*
+*.dylib
+
+# Executables
+*.exe
+*.out
+*.app
+*.i*86
+*.x86_64
+*.hex
+
+# Debug files
+*.dSYM/
+*.su
+*.idb
+*.pdb
+
+# Kernel Module Compile Results
+*.mod*
+*.cmd
+.tmp_versions/
+modules.order
+Module.symvers
+Mkfile.old
+dkms.conf
+
+#
+# Lsof specific patterns
+#
+
+# Generated files
+*.gcda
+*.gcno
+*~
+/Makefile
+lib/Makefile
+TAGS
+lsof
+lsof-netstat
+tags
+tests/config.*
+version.h
+autotools.h
+lockf_owner.h
+lockf.h
+lsof.man
+/site
+lib/dialects/netbsd/include
+/solaris11
+
+#
+# Symbolic links to lsof cli
+#
+/arg.c
+/dprint.c
+/main.c
+/misc.c
+/node.c
+/print.c
+/ptti.c
+/store.c
+/usage.c
+/util.c
+
+#
+# Symbolic links to a dialect implementation
+#
+/ddev.c
+/dfile.c
+/dlsof.h
+/dmnt.c
+/dnode.c
+/dnode1.c
+/dproc.c
+/dproto.h
+/dsock.c
+/dstore.c
+/machine.h
+
+#
+# Traditional test related files
+#
+LTbasic
+LTbasic2
+LTbigf
+LTdnlc
+LTlock
+LTnfs
+LTnlink
+LTshm2
+LTsock
+LTszoff
+LTszoff2
+LTunix
+LTunix2
+
+#
+# Dialect specific test related files
+#
+lib/dialects/linux/tests/epoll
+lib/dialects/linux/tests/eventfd
+lib/dialects/linux/tests/mq_fork
+lib/dialects/linux/tests/mq_open
+lib/dialects/linux/tests/open_with_flags
+lib/dialects/linux/tests/pidfd
+lib/dialects/linux/tests/pipe
+lib/dialects/linux/tests/pty
+lib/dialects/linux/tests/ux
+lib/dialects/linux/tests/mmap
+
+# automake
+Makefile.in
+.libs/
+.deps/
+.dirstamp
+*.log
+*.trs
+
+# autoconf
+autom4te.cache
+/aclocal.m4
+/compile
+/config.guess
+/config.log
+/config.status
+/config.sub
+/config.h
+/config.h.in
+/configure
+/depcomp
+/install-sh
+/libtool
+/ltmain.sh
+/missing
+/stamp-h1
+/test-driver
+
+# Doxygen
+/output
diff --git a/.readthedocs.yaml b/.readthedocs.yaml
new file mode 100644
index 0000000..2f2f085
--- /dev/null
+++ b/.readthedocs.yaml
@@ -0,0 +1,21 @@
+# .readthedocs.yaml
+# Read the Docs configuration file
+# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
+
+# Required
+version: 2
+
+# Set the version of Python and other tools you might need
+build:
+  os: ubuntu-22.04
+  tools:
+    python: "3.10"
+
+mkdocs:
+  configuration: mkdocs.yml
+
+# Optionally declare the Python requirements required to build your docs
+python:
+   install:
+   - requirements: docs/requirements.txt
+
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..e840122
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,73 @@
+#
+# Derived from
+# https://github.com/steveno/ctags/blob/master/.travis.yml
+#
+
+dist: xenial
+
+language: c
+
+os:
+  - linux
+  - osx
+
+compiler:
+  - gcc
+  - clang
+
+sudo: true
+
+addons:
+  apt:
+    packages:
+      - lcov
+      - procps
+      - netcat
+before_install:
+  - |
+    gem install lcoveralls
+
+script:
+  - |
+    case $TRAVIS_OS_NAME in
+        linux) dialect=linux;;
+        osx)   dialect=darwin;;
+    esac
+    ./Configure -n $dialect
+
+  - |
+    if [ $CC = 'gcc' ]; then
+        CC_EXTRA="--coverage"
+    fi
+    make CDEF="${CC_EXTRA}" CC="${CC} ${CC_EXTRA}"
+
+  - |
+    case $TRAVIS_OS_NAME in
+        linux) dialect=linux;;
+        osx)   dialect=darwin;;
+    esac
+    tdir=dialects/${dialect}/tests
+    if [ -f ${tdir}/Makefile ]; then
+        make -C "${tdir}"
+    fi
+
+  - |
+    case $TRAVIS_OS_NAME in
+        linux) dialect=linux;;
+        osx)   dialect=darwin;;
+    esac
+    sudo -E bash ./check.bash $dialect
+
+after_success:
+  - |
+    if [ $CC = 'gcc' ] && [ $TRAVIS_OS_NAME = 'linux' ]; then
+    (
+            for f in /home/travis/.rvm/gems/ruby-2*/gems/lcoveralls-*/lib/lcoveralls/color_formatter.rb; do
+                    sed -i -e 's/severity.capitalize!/severity = severity.capitalize/' $f
+            done
+            for f in /home/travis/.rvm/gems/ruby-2*/gems/lcoveralls-*/lib/lcoveralls/runner.rb; do
+                    sed -i -e 's/\(.*format.*f\)\(%\)\('"'"'.*$\)/\1%%\3/' $f
+            done
+    ) || :
+    lcov -c -b . -d . -o coverage.info && lcoveralls --root . --retry-count 5 coverage.info
+    fi
diff --git a/00CREDITS b/00CREDITS
index 664bd5c..47fbb22 100644
--- a/00CREDITS
+++ b/00CREDITS
@@ -1,575 +1 @@
-			    Lsof Credits
-
-I owe an enormous debt to the users of lsof who have contributed
-to its steady growth.  The size of the list of people who have
-helped me, while it has grown too large to include in the lsof man
-page any more, is a testimonial to their generosity.
-
-First I acknowledge a debt to the work of Dan Bernstein, Michael
-``Ford'' Ditto, Tom Dunigan, Alexander Dupuy, Vik Lall, Ray Moody,
-C. Spencer, Michael Spitzer and those who wrote Berkeley's fstat
-program, all contributors to lsof's predecessors.
-
-I thank Doug McKenzie for his HP-UX proctor program and Rich Kulawiec
-for pointing it out.
-
-Finally I thank all the following people who have used lsof, pointed
-out its flaws, described its shortcomings, offered suggestions for
-improving it, supplied code for it, gave me technical advice, and
-provided test systems where I was able to do development work.
-
-	Szilveszter Adam
-	David Addison
-	Elias Halldor Agustsson
-	Per Allansson
-	Jim Ankenbrandt
-	Richard Allen
-	Thomas Anders
-	Ric Anderson
-	Stuart Anderson
-        Dimitry Andric
-	Michael Antlitz
-	Cato Auestad
-	Marc Auslander
-	Tigran Aivazian
-	Jos Backus
-	David Bacon
-	Alexis Ballier
-	Scott Ballew
-	Ade Barkah
-	Alon Bar-Lev
-	Brett Bartick
-	Anthony Baxter
-	John Beacom
-	Bruce Beare
-	M. Jay Beck
-	Marek Behun
-	Bill Behr
-	Michael Beirne
-	Marc Bejarano
-	Andrew Bell
-	Steve Bellenot
-	Robert Benites
-	Dmitry Berezin
-	Ulrich Bernhard
-	Peter J. Bertoncini
-	Dave Bianchi
-	Mark Bixby
-	Allan Black
-	Jan Blunck
-	Achim Bohnet
-	Steve Bonds
-	Mark Bonsack
-	Volker Borchert
-	Bill Bormann
-	Ermin Borovac
-	Heddy Boubaker
-	Pieter Bowman
-	Michael Bracewell
-	H. Merijn Brand
-	Danny Braniss
-	Thomas Braunbeck
-	Kieran Broadfoot
-	Dean Brock
-	Hal Brooks
-	Andrew Brown
-	Jim Brown
-	Michael Bryan
-	Matthew Burt
-	Robert Byrnes
-	Pierfrancesco Caci
-	Bill Campbell
-	David Capshaw
-	John Caruso
-	Jon Champlin
-	Kris Chandrasekhar
-	Stephane Chazelas
-	Andrey Chernov
-	Albert Chin-A-Young
-	Bernt Christandl
-	Marc Christensen
-	Hans Petter Christiansen
-	Tom Christiansen
-	Yves Christophe
-	Richard Chycoski
-	A. Channing Clark
-	Jorn Clausen
-	Axel Clauberg
-	John Clear
-	David Clissold
-	Richard Coley
-	John Colgrave
-	David Comay
-	Lionel Cons
-	Bob Cook
-	Patrick Connor
-	Carl Cook
-	Jim Cooper
-	Roger Cornelius
-	Doug Crabill
-	Eric Cronin
-	Kim Culhan
-	Dave Curry
-	Robert Dahlem
-	Guy Dallaire
-	D. Chris Daniels
-	Renata Maria Dart
-	Ian Darwin
-	Carl E. Davidson
-	David Day
-	Will Day
-	Frederic Delanoy
-	Mike Depot
-	Steve Dibbell
-	Hugh Dickins
-	David DiGiacomo
-	Casper Dik
-	John DiMarco
-	Don Draper
-	Bryan Drewery
-	Michel Dubois
-	Eric Dumazet
-	Dick Dunbar
-	Marc Duponcheel
-	Jan Dvorak
-	Calle Dybedahl
-	John Dzubera
-	Jeff Earickson
-	Greg Earle
-	Bernd Eckenfels
-	Niklas Edmundsson
-	Philip Edwards
-	Robert Ehrlich
-	Mark W. Eichin
-	Doug Eldred
-	Scott Ellentuch
-	Tom Endo
-	Grant Erickson
-	Craig Everhart
-	Chris Evert
-	Bob Farmer
-	Sami Farin
-	Mike Feldman
-	Quentin Fennessy
-	Ian Fitchet
-	Toralf Foerster
-	Bob Foertsch
-	Pierre-Yves Fontaniere
-	Ralph Forsythe
-	Jason Fortezzo
-	Mike Fraser
-	Curt Freeland
-	Terry Friedrichsen
-	Mike Frysinger
-	Harvey Garner
-	Carson Gaspar
-	Stuart D. Gathman
-	Brian L. Gentry
-	Dave Gilbert
-	Steve Ginsberg
-	Bjarni Ingi Gislason
-	Edwin Groothuis
-	Jin Guojun
-	Kurt Gollhardt
-	Roman Gollent
-	Steve Gonczi
-	Bill Goodridge
-	Julian Gordon
-	Marcin Gozdalik
-	Henry Grebler
-	Richard Green
-	Chaskiel Grundman
-	Armin Gruner
-	David Gutierrez
-	Mateusz Guzik
-	Robert Hall
-	Garner Halloran
-	Adam Hammer
-	Charles Hannum
-	Vlad Harchev
-	Craig Harmer
-	Michael Haro
-	Peter Harvey
-	Steinar Haug
-	Jia He
-	Sheldon Hearn
-	John Heasley
-	Wolfgang Hecht
-	Janet Hempstead
-	Michael Hennecke
-	Randolph J. Herber
-	Allen Hewes
-	Andrew Hill
-	Kurt Hillig
-	Steven Hinkle
-	Paul Hite
-	Billy Ho
-	Michael Hocke
-	Brett Hogden
-	Gaylord Holder
-	Kjetil Torgrim Homme
-	Pekka Honkanen
-	Jeffrey C. Honig
-	Heidi Hornstein
-	Michael A. Hovan III
-	Barbara Howe
-	J. Nelson Howell
-	Jeff Howie
-	Louis Huemiller
-	John Hughes
-	Gerrit Huizenga
-	Peter Ilieve
-	Mayer Ilovitz
-	Gregory A. Ivanov
-	John Jackson
-	Kurt Jaeger
-	Edward Jajko
-	Marian Jancar
-	Paul Jarc
-	Jakub Jelinek
-	Robert Jelinek
-	Bruce Jerrick
-	Carl Johnson
-	Dion Johnson
-	Jeff Johnson
-	Douglas B. Jones
-	LaMont Jones
-	Peter Jordan
-	Arne H. Juul
-	Pasi Kaara
-	Frank Kaefer
-	Keith Kalet
-	Claus Kalle
-	Henri Karrenbeld
-	Amir Katz
-	Henry Katz
-	Kawaljeet Kaur
-	Doug Kehn
-	Kris Kennaway
-	Terry Kennedy
-	Shane Kenney
-	Andrew Kephart
-	Robert Kiessling
-	Joshua Kinard
-	Don Kirouac
-	Steve Kirsch
-	Philip Kizer
-	Thomas Klausner
-	Roger Klorese
-	Peter Klosky
-	Przemek Klosowski
-	Angelos D. Keromytis
-	Radko Keves
-	Valdis Kletnieks
-	Chris Kordish
-	Alek O. Komarnitsky
-	Joseph Kowalski
-	Christian Krackowizer
-	Paul Kranenburg
-	Troyan Krastev
-	Brad Krebs
-	Alex Kreis
-	Johannes Kroeger
-	Vincent Kujala
-	Ken Laing
-	Shirley Lam
-	Erwin Lansing
-	Victoria H. Lau
-	Markus Lautenbacher
-	Steve Lacey
-	Marc Aurele La France
-	Chad R. Larson
-	Steve Laubscher
-	Andrei V. Lavreniyuk
-	Loc Le
-	Tin Le
-	Diane Lebel
-	Francis Le Bourse
-	Kyungjoon Lee
-	Marty Leisner
-	Maciej Lesniewski
-	Stuart Levy
-	Ben Lewis
-	Michael Lewis
-	Angel Li
-	Ambrose Li
-	Wendy Lin
-	Carl E. Lindberg
-	Onno van der Linden
-	Johan Lindquist
-	James Lingard
-	Jason Lingohr
-	Robert Lipe
-	Gabor Liptak
-	Friedel Loinger
-	Michael Long
-	Pete Lord
-	Steve Logue
-	Bela Lubkin
-	Pav Lucistnik
-	Horst Luehrsen
-	Andreas Luik
-	Timothy J. Luoma
-	Michael Mackenzie
-	Lawrence MacIntyre
-	Jerome Marchand
-	Benson Margulies
-	Claude Marinier
-	Chris Markle
-	Roy Marples
-        Ed Maste
-	Eberhard Mater
-	James Mathiesen
-	Tom Matthews
-	Fletcher Mattox
-	David Mazieres
-	Brian McAllister
-	Scott McClung
-	Dale McCluskey
-	Terry McCoy
-	Sean McDermott
-	Duncan McEwan
-	Dwight McKay
-	William McVey
-	Eric McWhorter
-	Marjo F. Mercado
-	Dan Mercer
-	Bill Melvin
-	Andrew Merril
-	Richard van Meurs
-	Jim Mewes
-	Ivan Melnikov
-	Conrad Meyer
-	Hendrik Meyer
-	Gary Millen
-	Timothy Miller
-	Davin Milun
-	Yuliy Minchev
-	Jim Mintha
-	Mike Miscevic
-	Arkadiusz Miskiewicz
-	Janardhan Molumuri
-	Nasser Momtaheni
-	Laurent Montaron
-	Doug Moore
-	Phillip Moore
-	Dmitry Morozovsky
-	John Paul Morrison
-	John Gardiner Myers
-	Jeffrey Mogul
-	Dave Morrison
-	Pat Myrto
-	Toshiya Nakamura
-	Filippo Natali
-	Allan Nathanson
-	Chance Neale
-	Dan Nelson
-	Vladislav Nespor
-	Bjorn S. Nilsson
-	Anders Nordby
-	Joseph J. Nuspl Jr.
-	David O'Brien
-	Alexandre Oliva
-	Craig B. Olofson
-	Dave Olson
-	Rainer Orth
-	Sergey A. Osokin
-	Keith Parks
-	Will Partain
-	Vasco Pedro
-	Mark Peek
-	Ezra Peisach
-	Bill Pemberton
-	Lee Penn
-	Gildas Perrot
-	Jesse Perry
-	Nathan Peterson
-	Dominique Petitpierre
-	Hung Pham
-	Ray Phillips
-	Francois Pinard
-	Gary Plewa
-	Alex Podlecki
-	Lutz Poetschulat,
-	John Polstra
-	Scott Presnell
-	Mark Price
-	Philippe-Andre Prindeville
-	David Putz
-	Tom Qin
-	Jan Rybar
-	Kurtis Rader
-	Peter Radig
-	Jean-Pierre Radley
-	Tim Ramsey
-	Dewan Rashid
-	Richard J. Rauenzahn
-	Louis Rayman
-	Brian Redman
-	Eric S. Raymond
-	Erwin Reyns
-	Aaron Rhodes
-	Jim Reid
-	Jean-Luc Richier
-	Clint Roberts
-	Ingimar Robertson
-	Sylvain Robitaille
-	Larry Rogers
-	Malgorzata Roos
-	Larry Rosenman
-	Stephan Rossi
-	Kevin Ruderman
-	Wolfgang Rupprecht
-	Pavol Rusnak
-	Eygene Ryabinkin
-	Conrad J. Sabatier
-	Klaus Saggerer
-	Chris Schanzle
-	Igor Schein
-	Horst Scheuermann
-	Peter Schiffer
-	Michael Schmitz
-	Larry Schwimmer
-	Cy Schubert
-	Hendrik G. Seliger
-	Igor V. Semenyuk
-	Jonathan Sergent
-	Frank Sanders
-	Berkley Shands
-	Gregory Neil Shapiro
-	Eyal Shaynis
-	Michael Shields
-	Wesley Shields
-	Philip Shin
-	Anthony Shortland
-	Dave Sill
-	John Silva
-	Chuck Silvers
-	Gerry Singleton
-	Leonard Sitongia
-	Kevin Smallwood
-	Gleb Smirnoff
-	Curt Smith
-	Ben Smithurst
-	Douglas R. Smith
-	Kevin Smith
-	Chang Song
-	Josh Soref
-	John Speno
-	Kenneth Stailey
-	Piet Starreveld
-	David Steiner
-	Charles Stephens
-	Marc Stephenson
-	Chip Stettler
-	Dave Stevens
-	Jeff Stewart
-	Diana Stockdale
-	Andreas Stolcke
-	Jeff Stoner
-	Kristyna Streitova
-	Sushila Subramanian
-	Jan Ole Suhr
-	Mike Sullivan
-	Patrick D. Sullivan
-	Peter Svensson
-	Chris Sylvain
-	Miklos Szeredi
-	Paul Szabo
-	Dale Talcott
-	Jon A. Tankersley
-	Jan Tax
-	Samuel Thibault
-	Andy Thomas
-	Matthew Thurmaier
-	Chris Timmons
-	Andrzej Tobola
-	R. Lindsay Todd
-	Zdenko Tomasic
-	Michael Townsend
-	Linus Torvalds
-	Mike Tracy
-	Jeff Trawick
-	Dan Trinkle
-	Erik Trulsson
-	Lars Tunkrans
-	Lenny Turetsky
-	Kevin Vajk
-	Peter Valchev
-	John R. Vanderpool
-	Peter Van Epp
-	Peter C. Vernam
-	Peter Vines
-	Bob Ward
-	Jules van Weerden
-	Tom Weaver
-	Fernando A.B. Whitaker
-	Tom Whitty
-	Carson Wilson
-	David J. Wilson
-	Frank Winkler
-	Marc Winkler
-	Mark Vasoll
-	Holger VanKoll
-	Robert Vernon
-	Joep Vesseur
-	Larry Virden
-	Jos Vos
-	Jun Biao Wang
-	Christopher J Warweg
-	Bill Watson
-	Florian M. Weps
-	Joel White
-	Paul Wickman
-	Martin Wilke
-	Eric Williams
-	Steve Williams
-	Steve Wilson
-	Erich Wimmer
-	Wally Winzer, Jr.
-	Patrick Wolfe
-	Stephen Woods
-	James Woodward
-	Scott Worley
-	Jan Wortelboer
-	Joshua Wright
-	Sailu Yallapragada
-	Masatake YAMATO
-	Donna Yobs
-	Ron Young
-	Warren Young
-	Blair Zajac
-	Karel Zak
-	Donald Zoch
-	Malcom Zung
-	Waldemar Zurowski
-	@eranik (github account)
-	@jolmg  (github account)
-	yasu@utahime.org (email)
-	jamie@catflap.org (email)
-	@hardikpnsp (github account)
-	Martin D Kealey
-	Henry Peteet
-	@zhrf2020
-	@JustAnotherArchivist
-	@po5857
-	@albert-github
-	Tobias Geerinckx-Rice
-	Andres Salomon
-	Nicholas Bamber
-	Grisha Levit
-	@10ne1 (github account)
-	@a1346054
-	Damjan Jovanovic
-	Fabrice Fontaine and
-	Danny Fowler
-
-If I have omitted a contributor's name, the fault is wholly mine,
-and I apologize for the error.
-
-
-Vic Abell <abe@purdue.edu>
-March 27, 2018
-
-Masatake YAMATO <yamato@redhat.com> (since revision 4.92.1)
-October 4, 2020
+This documentation has been replaced by docs/credits.md. Please refer to the new file or read it online.
\ No newline at end of file
diff --git a/00DCACHE b/00DCACHE
index 57411bc..21984f4 100644
--- a/00DCACHE
+++ b/00DCACHE
@@ -732,13 +732,10 @@ machine.h header files.
     HP-UX 11.00
     NetBSD 1.[456], 2.x and 3.x for Alpha, x86, and SPARC-based
 	systems
-    NEXTSTEP 3.[13]
     OpenBSD 2.[89] and 3.[0-9] for x86-based systems
-    OPENSTEP 4.x
     SCO OpenServer Release 5.0.4 for x86-based systems
     SCO|Caldera UnixWare 7.1.4 for x86-based systems
     Solaris 2.6, 8, 9 and 10
-    Tru64 UNIX 5.1
 
 
 Vic Abell <abe@purdue.edu>
diff --git a/00DIALECTS b/00DIALECTS
index 2c01779..831707d 100644
--- a/00DIALECTS
+++ b/00DIALECTS
@@ -1,4 +1,7 @@
-	Apple Darwin 9 and Mac OS X 10.[567]
-	FreeBSD 8.[234], 9.0 and 1[012].0 for AMD64-based systems
-	Linux 2.1.72 and above for x86-based systems
-	Solaris 9, 10 and 11
+	Apple Darwin 9, Mac OS X 10, macOS 11 and above
+	FreeBSD 8.2 and above
+	Linux 2.1.72 and above
+	NetBSD 1.2 and above
+	OpenBSD 7.2 and above
+	Solaris 9, 10 and 11 and above
+	OpenIndiana 5.11 and above
diff --git a/00DIST b/00DIST
index 0092564..353de42 100644
--- a/00DIST
+++ b/00DIST
@@ -127,6 +127,16 @@
 		4.93.1 May 7, 2019
 		4.93.2 May 8, 2019
 		4.94.0 November 11, 2020
+		4.95.0 April 28, 2022
+		4.96.0 September 16, 2022
+		4.96.1 September 16, 2022
+		4.96.2 September 16, 2022
+		4.96.3 September 16, 2022
+		4.96.4 October 18, 2022
+		4.96.5 December 26, 2022
+		4.97.0 January 17, 2023
+		4.98.0 January 22, 2023
+		4.99.0 November 10, 2023
 
 
 
@@ -146,8 +156,8 @@ been tested on:
 contains information on other ports.)
 
 If your favorite Unix dialect is not in the list, or if your version
-of it is more recent than the ones listed, please contact me at
-<abe@purdue.edu>.
+of it is more recent than the ones listed, please file a new issue at
+https://github.com/lsof-org/lsof.
 
 Version 3 of lsof was tested on:
 
@@ -444,8 +454,7 @@ VENDOR.
 At worst such a bug report will confuse the vendor; at best, the
 vendor will forward the bug report to me.
 
-Please send all bug reports, requests, etc. to me via email at
-<abe@purdue.edu>.
+Please send all bug reports, requests, etc. to https://github.com/lsof-org/lsof.
 
 
 The lsof-l Mailing List
@@ -1894,7 +1903,7 @@ Supplement	Regenerated the 4.04 distribution to correct a non-
 		possible.  PTX 4.4.4 requires clnt_create().
 
 4.41		February 27, 1999
-		Added FreeBSD 3.1 and and 4.0 support with help
+		Added FreeBSD 3.1 and 4.0 support with help
 		from Sheldon Hearn <axl@iafrica.com>, David O'Brien
 		<obrien@NUXI.com>, and John Polstra <jdp@polstra.com>.
 
@@ -4007,7 +4016,7 @@ Supplement	Regenerated the 4.04 distribution to correct a non-
 		a patch to 4.75.
 
 		Added support for Solaris 10 port and CTFS files.  The
-		CTFS support is imcomplete, because I don't know how
+		CTFS support is incomplete, because I don't know how
 		to get inode number, size and link count.  (There's
 		a new 00FAQ entry about that.)
 
@@ -4067,7 +4076,7 @@ Supplement	Regenerated the 4.04 distribution to correct a non-
 		PA-RISC HP-UX 11.23, based on a report from John
 		Orndorff <John.Orndorff@sungard.com>.  Found that
 		neither the HP bundled C compiler nor gcc would build
-		lsof, but the the HP unbundled ANSI C compiler would.
+		lsof, but the HP unbundled ANSI C compiler would.
 		Concluded that HP bundled C compiler can't handle
 		<gssapi/gssapi.h>.  Devised a work-around to gcc's
 		omission of the rpcent structure definition of
@@ -4591,7 +4600,7 @@ Supplement	Regenerated the 4.04 distribution to correct a non-
 		Made FreeBSD 9 adjustment.
 
 		Fixed a Linux bug that prevented the display of paths for
-		abstact UNIX sockets.  Masatake Yamato <yamato@redhat.com>
+		abstract UNIX sockets.  Masatake Yamato <yamato@redhat.com>
 		reported the bug and supplied a patch.
 
 		Added compensation for the removal of RPC header files from
@@ -4743,7 +4752,7 @@ Supplement	Regenerated the 4.04 distribution to correct a non-
 		file names.  Stephane Chazelas <stephane.chazelas@gmail.com>
 		reported the problem.
 
-		Added support for Linux RDMA and CRYPTO protocal names and UNIX
+		Added support for Linux RDMA and CRYPTO protocol names and UNIX
 		socket type with code from Masatake YAMATO <yamato@redhat.com>.
 
 		Fixed field output to insure that the field descriptor field is
@@ -4902,9 +4911,6 @@ Supplement	Regenerated the 4.04 distribution to correct a non-
 		Released lsof to GitHub with Purdue releases documented in
 		support/GitHub-release.
 
-Vic Abell <abe@purdue.edu>
-July 14, 2018
-
 
 4.92.1		May 6, 2019
 
@@ -5283,6 +5289,7 @@ July 14, 2018
 		submitted/expanded by @dilinger (Andres Salomon) in #168.
 
 
+
 		[FreeBSD] update for FreeBSD 13 & 14, and various internal changes
 		submitted by @DmitryAndric & @emaste.
 
@@ -5295,6 +5302,24 @@ July 14, 2018
 		found
 		submitted by @emaste
 
+		[FreeBSD] Use user mode APIs on FreeBSD
+		Extensively changes the FreeBSD dialect to use user mode APIs
+		(sysctls and libutil's kinfo_getfile()), only falling back to kvm
+		access when it's available and required for certain features. lsof can
+		now run as an ordinary user, though not all processes may be visible
+		and some features will be absent without kvm access (file lock state,
+		kqueue info, some pipe details, nullfs details).
+		This also fixes numerous long standing issues: file lock state is now
+		visible on all filesystems, the cwd, root dir, jail dir, text file and
+		controlling TTY are now visible, filenames are shown for all
+		filesystems, procfs is working again and supports file searches even
+		when there are multiple procfs mountpoints, the code is shorter,
+		cleaner and should need much less future maintenance.
+		It builds and works from FreeBSD 9.0 to 14-CURRENT, though older
+		versions have less features (eg. 12 doesn't provide socket buffer
+		usage, 11 also lacks TCP flags and state).
+		Provided by @DamjanJovanovic in #184.
+
 
 		Fix broken LSOF_CFLAGS_OVERRIDE.
 		Provided by Fabrice Fontaine in #172.
@@ -5326,5 +5351,274 @@ July 14, 2018
 		comma.
 		Provided by Danny Fowler in #156.
 
+4.96.0		September 16, 2022
+
+		[linux] fix hash functions used for finding local tcp/udp IPCs
+		There were typos in the code calculating hash values. The typos might
+		break the flatness of hashtables where the endpoint information about
+		locally used tcp/udp was stored. Theoretically, this fix may improve
+		the performance of lsof with [+|-]E option.
+		Inspired by the issue #206 reported by Tomasz Kłoczko (@kloczek).
+
+
+		Show copyright notice in --version output.
+
+
+		[linux] compile with -Wall option
+
+
+		[linux] Avoid some easy collissions for udp/udp6 sockets when hashing
+		
+		
+		[linux] Changing the number of ipcbuckets to 4096
+
+
+		[darwin] fix build with -fno-common (Cfp redefinition)
+		gcc-10 and llvm-11 changed the default from -fcommon to -fno-common:
+		https://gcc.gnu.org/PR85678
+		As a result build fails as:
+
+			duplicate symbol '_Cfp' in: ddev.o dfile.o
+
+		Cfp is already explicitly defined in dstore.c. The change turns
+		header definition into declaration.
+		Provided by Sergei Trofimovich (@trofi) in #221. The same fix is
+		applied to libproc backend by Jiajie Chen (@jiegec) in #226.
+
+
+		[linux] Make build reproducible by checking SOURCE_DATE_EPOCH
+		and considering LSOF_{HOST,LOGNAME,SYSINFO,USER} as "none" when
+		it is set.
+		Provided by Danilo Spinella in #217
+
+
+		[darwin] remove /usr/include prefix from include for Darwin 19+
+		The /usr/include path is missing since macOS Catalina.
+		Fixes issue #234.
+		Provided by Jiajie Chen in #235
+
+
+		[linux] obtain correct information of memory-mapped file.
+		Provided by Teng Hu in #239
+
+
+		[FreeBSD] configure: suggest variable to set if FreeBSD sys not 
+        	found
+        	Submitted by @emaste
+
+
+		Updated 00FAQ with lookup to open files via mountpoint
+		Provided by Jacob Chapman in #240
+
+
+                [FreeBSD] modernize API usage and remove legacy FreeBSD releases
+                Contributor DamjanJovanovic (#184) Ed Maste (#250, #251, #252),
+                Warner Losh (#253)
+
+4.96.1		September 16, 2022
+
+                [FreeBSD] Unconditionally define HASKQUEUE (mjguzik) 
+
+4.96.2		September 16, 2022
+
+                [FreeBSD] fix FreeBSD < 14
+
+4.96.3		September 16, 2022
+
+                [FreeBSD] Fix kqueue compat for releases < 14
+
+4.96.4		October 18, 2022
+
+		[FreeBSD] sys/files.h no longer needs _KERNEL defined to 
+                include it (bsdimp #256)
+
+
+		docs: Describe fd number truncation in output (#261)
+
+4.96.5		December 26, 2022
+
+		[linux] Use correct scanf/printf format for uint64_t (#266)
+
+
+		Avoid C89-only constructs in Configure (#265)
+
+
+		[freebsd] add <sys/callout.h> for recent changes
+
+4.97.0		January 17, 2023
+
+		[decof/du/tru64] Remove support because the os is no longer
+		updated for more than 10 years
+
+
+		[openstep/nextstep] Remove support because the os is no longer
+		updated for more than 20 years
+
+
+		Add experimental build system based on Autotools (#270)
+
+
+		Fixed LTsock testing on darwin (#272)
+
+
+		Remove NEW and OLD folders (#6)
+
+
+		Fix FreeBSD testcases (#271)
+
+
+		Rewrite documentation and publish at https://lsof.readthedocs.io/
+
+4.98.0		January 22, 2023
+
+		Fix two potential null pointer access bug when gethostbyname2()
+		returns an empty address list
+
+
+		Add support for older automake versions (on e.g. CentOS 7)
+
+
+		Migrate testing scripts and programs to autotools
+
+
+		Extend CI to build on more Linux distros
+
+
+		[linux] Fix handling of empty command name, closing #246.
+		Add test from #246, where lsof returns stale command name when the
+		command name is empty. If getting command name failed, return
+		NULL instead of empty string
+
+
+		Add --with/without-libtirpc option to autotools-based build
+		system and automatically detect libtirpc by default
+
+
+		Add -H switch to print human readable size, e.g. 123.4K (#260)
+
+
+		[linux] Fix implicit declaration error when HASPTYEPT is undefined
+
+
+		Add support for musl libc-based Linux distros
+
+
+		Add --enable-security argument to configure to allow only the
+		root user to list all open files
+
+
+		Add --enable-no-sock-security argument to configure to allow
+		anyone to list anyone else's socket files when combined with
+		--enable-security
+
+
+		[linux] Always enable 64 bit off_t in configure.ac
+
+
+		[netbsd] Import patches from pkgsrc and port autotools-based build system to NetBSD
+
+
+		[netbsd] Fix lock status reading
+
+4.99.0		November 10, 2023
+
+		[netbsd] Get device number of tmpfs instead of reporting zero
+
+
+		[openbsd] Rewrite OpenBSD support because OpenBSD disallows
+		kernel memory access and lsof has to switch to user mode API.
+		Currently, most features are working, but file path reporting
+		and lock status are not working for lack of kernel support.
+		As a consequence, OpenBSD dialect is separated in a new folder.
+
+
+		[darwin] Remove /dev/kmem backend because it no longer exists on
+		current macOS releases. Use libproc backend instead.
+
+		
+		[linux] Do not hard-code fd numbers in epoll test, fixing tests
+		on Void Linux
+
+
+		[freebsd] Use kf_file_nlink if provided by kernel instead of
+		stat(). This commit requires kernel with
+		https://reviews.freebsd.org/D38169. It brings back the ability
+		to list deleted files via `lsof +L1`. Closes #264.
+
+
+		[linux] Add --with-selinux configure option.
+
+
+		[solaris] Re-introduce support for recent Solaris & OpenIndiana
+		releases.
+
+
+		[darwin] Display kern ctl info, learned from apple lsof version.
+
+
+		[linux] Improve performance by using closefrom(). Closes #281.
+
+
+		[aix] Fix compilation on AIX 7.2 and add autotools build system
+		support for AIX.
+
+		[aix] Suppress warnings properly on AIX version greater than
+		5.0. Closes #187.
+		
+		Introduce alpha version of liblsof which allows users to use
+		lsof functionality via C functions instead of spawning a
+		subprocess and parsing the output. This version may contain BUGs
+		and memory leaks, and the API may change before it stablizes.
+
+4.99.1		December  16, 2023
+
+		Fix compilation error when HASIPv6 is not defined. (@chenrui333)
+
+		Add configure option --disable-liblsof to disable installation
+		of liblsof. (@subnut, #300)
+
+		[freebsd] fix segfault from fs info (FreeBSD bug 267760)
+
+4.99.2		December  16, 2023
+
+		fix version file
+
+4.99.3		December  16, 2023
+
+		fix 00DIST file <space> -> tabs
+
+4.99.4		November 18, 2024
+
+		fix version parser for clang (lsof-org#305) (#306)
+
+		In lsof manapge: mention /etc/services for -P option (#309)
+
+		[freebsd] don't use kf_sock_inpcb on modern versions. In
+		FreeBSD 14 and after the generic internet protocol control
+		block and protocol specific (TCP) control block are the same
+		pointer.  The latter embeds the former. The kf_sock_inpcb is
+		planned for removal in FreeBSD 15.
+
+		[freebsd] Recognize FreeBSD 15
+
+		Fix typos in docs (#314)
+
+		[linux] Do not embed kernel version in CFLAGS (#314)
+
+		[linux] Linux 6.9 changed the pidfs appearence in procfs. Try
+		to maintain original output in lsof (#317)
+
+		[linux] closefrom_shim: Add optimized fallback for platforms
+		without closefrom or close_range (#316)
+
+		lib/misc.c: fix build against -std=c23 (`void (*)()`) changed
+		the meaning) (#327)
+
+4.9?.?		????????? ??, ????
+
+
+Vic Abell <abe@purdue.edu>
+July 14, 2018
+
 The lsof-org team at GitHub
-April 28, 2022
+December 28, 2022
diff --git a/00FAQ b/00FAQ
index 4c6a636..e8d79c1 100644
--- a/00FAQ
+++ b/00FAQ
@@ -242,19 +242,6 @@ Table of Contents:
 6.0	BSD/OS BSDI Problems
 6.0.5	Statement of deprecation
 
-7.0	DEC OSF/1, Digital UNIX, and Tru64 UNIX Problems
-7.1	Why does lsof complain about non-existent /dev/fd entries?
-7.2	Why does the Digital UNIX V3.2 ld complain about Ots* symbols?
-7.3	Why can't lsof locate named pipes (FIFOs) under V3.2?
-7.4	Why does lsof use the wrong configuration header files?
-	For example, why can't the lsof compilation find cpus.h?
-7.5	Why does lsof indicate incomplete paths with " -- " for Tru64
-	UNIX 5.1 files?
-7.6	Why doesn't lsof report link count, node number, and size
-	for some Tru64 5.x CFS files?
-7.7     Why does lsof say it can't read the kernel name list or
-	proc table on Digital UNIX 4.x or Tru64 UNIX?
-
 8.0	FreeBSD Problems
 8.1	Why doesn't lsof report on open kernfs files?
 8.2	Why doesn't lsof work on my FreeBSD system?
@@ -367,11 +354,6 @@ Table of Contents:
 11.4.2	Why does NetBSD lsof produce incorrect output?
 11.5	Why isn't lsof feature xxx enabled for NetBSD?
 
-12.0	NEXTSTEP and OPENSTEP Problems
-12.1	Why can't lsof report on 3.1 lockf() or fcntl(F_SETLK)
-	locks?
-12.2	Why doesn't lsof compile for NEXTSTEP with AFS?
-
 13.0	OpenBSD Problems
 13.1	Why doesn't lsof support kernfs on my OpenBSD system?
 13.2	Will lsof work on OpenBSD on non-x86-based architectures?
@@ -503,7 +485,7 @@ Table of Contents:
 17.26.1	Why doesn't lsof report size, link count and node number for
 	Solaris 10 contract files?
 17.26.2 Why can't lsof locate a Solaris 10 contract file by path name?
-17.27	Solaris 10 and above ZFS probblems
+17.27	Solaris 10 and above ZFS problems
 17.27.1	Why does Configure warn that ZFS support is not enabled?
 17.28	Problems with Solaris 9 and above
 17.28.1	Why does the compiler complain about lgrp_root on Solaris 9
@@ -513,7 +495,7 @@ Table of Contents:
 18.1	Why doesn't lsof doesn't report on /proc entries on my
 	system?
 18.2	How do I disable the device cache file feature or alter
-	it's behavior?
+	its behavior?
 18.2.1	What's the risk with a perverted device cache file?
 18.2.2	How do I put the full host name in a personal device cache file
 	path?
@@ -549,7 +531,7 @@ ______________________________________________________________________
 
 1.2.1	Are there mirror sites?
 
-	On March 21, 2013 these sites appeared to have the lastest
+	On March 21, 2013 these sites appeared to have the latest
 	lsof revision:
 
 	ftp://ftp.fu-berlin.de/pub/unix/tools/lsof
@@ -676,16 +658,13 @@ ______________________________________________________________________
 
 1.4	How do I report an lsof bug?
 
-	If you believe you have discovered a bug in lsof, you can
-	report it via e-mail to <abe@purdue.edu>.  Do NOT report lsof
-	bugs to the UNIX dialect vendor. Make sure "lsof" appears in
-	the "Subject:" line so my e-mail filter won't classify your
-	letter as Spam.
+	If you believe you have discovered a bug in lsof, you can report it to
+	https://github.com/lsof-org/lsof.  Do NOT report lsof bugs to the UNIX
+	dialect vendor.
 
-	Before you send me a bug report, please read the "Bug Reports"
-	section of the 00README file of the lsof distribution.  It
-	lists the steps you should take before and when reporting a
-	suspected bug.
+	Before you send a bug report, please read the "Bug Reports" section of
+	the 00README file of the lsof distribution.  It lists the steps you
+	should take before and when reporting a suspected bug.
 
 1.5	Where can I get the lsof FAQ?
 
@@ -994,7 +973,7 @@ ______________________________________________________________________
 	The vendor additions are significant to lsof because they
 	affect the internal kernel structures with which lsof does
 	business.  While some vendor derivatives of SVR4 are similar,
-	each one I have encounted so far has been different enough
+	each one I have encountered so far has been different enough
 	from its siblings to require special source code.
 
 	If you're interested in an SVR4 version of lsof, here are
@@ -1161,7 +1140,7 @@ ______________________________________________________________________
 	Errors like the above are most likely not problems in the
 	system's header files, but in the private copies of them
 	that were created when gcc was made or installed.  Note
-	the presense of
+	the presence of
 	".../gcc-3.2.1/lib/gcc-lib/sparcv9-sun-solaris2/3.2.1/include/..."
 	in the paths for user.h and task.h.  It indicates both
 	header files are gcc-specific.
@@ -1215,9 +1194,7 @@ ______________________________________________________________________
 		HP-UX, /dev/kmem and PSTAT based
 		Linux, /dev/kmem-based
 		NetBSD
-		NEXTSTEP
 		OpenBSD
-		OPENSTEP
 		Reliant UNIX
 		SCO OpenServer
 		SCO|Caldera UnixWare
@@ -1427,7 +1404,7 @@ ______________________________________________________________________
 	exclusion and inclusion used?" question.
 
 	Your UNIX dialect may not support "-s p:s" and its associated
-	performance improvments to Internet-only file processing.  You
+	performance improvements to Internet-only file processing.  You
 	can find more information on those topics in the answer to the
 	"Why doesn't my dialect support state name exclusion and
 	inclusion?" question.
@@ -1483,7 +1460,7 @@ ______________________________________________________________________
 	ownerships are changed to that of the real user and group.
 	In addition, lsof checks the file carefully before using
 	it (See the question "How do I disable the device cache
-	file feature or alter it's behavior?" for a description of
+	file feature or alter its behavior?" for a description of
 	the checks.); discards the file if it fails the scrutiny;
 	complains about the condition of the file; then rebuilds
 	the file.
@@ -1697,9 +1674,6 @@ ______________________________________________________________________
 	    Apple Darwin 7.2 and above
 		All socket options and values, socket states, and TCP
 		flags and values described in lsof(8) are reported.
-	    Digital UNIX and Tru64 UNIX 4.0
-		All socket options and values, socket states, and TCP
-		flags and values described in lsof(8) are reported.
 	    FreeBSD 4.9 and above
 		All socket options and values, socket states, and TCP
 		flags and values described in lsof(8) are reported.
@@ -1722,9 +1696,6 @@ ______________________________________________________________________
 	    OpenBSD 3.4 and above
 		All socket options and values, socket states, and TCP
 		flags and values described in lsof(8) are reported.
-	    OPENSTEP 4.2
-		All socket options and values, socket states, and TCP
-		flags and values described in lsof(8) are reported.
 	    OpenUNIX 8
 		All socket options and values, socket states, and TCP
 		flags and values described in lsof(8) are reported.
@@ -1757,10 +1728,6 @@ ______________________________________________________________________
 		Partial listen queue information is available.
 	    Apple Darwin 7.2 and above
 		Partial listen queue information is available.
-	    Digital UNIX 4.0
-		This dialect is no longer supported, so no attempt
-		was made to add partial listen queue length support
-		for it.
 	    FreeBSD 4.9 and above
 		Partial listen queue information is available.
 	    HP-UX 11.00 (/dev/kmem-based lsof)
@@ -1773,8 +1740,6 @@ ______________________________________________________________________
 		Partial listen queue information is available.
 	    OpenBSD 3.4 and above
 		Partial listen queue information is available.
-	    OPENSTEP 4.2
-		Partial listen queue information is available.
 	    OpenUNIX 8
 		This dialect is no longer supported, so no attempt
 		was made to add partial listen queue length support
@@ -2090,7 +2055,7 @@ ______________________________________________________________________
 
 	If the mounted-on device is a block device (the permission
 	field in output of `ls -l <device>` starts with a `b/),
-	you can specify it's name, too -- e.g.,
+	you can specify its name, too -- e.g.,
 
 	    $ lsof /dev/sd0a
 
@@ -2203,8 +2168,15 @@ ______________________________________________________________________
 	current working directory.
 
 	If you want to list instances of open files inside the
-	directory, you need to specify the individual path names
-	of those files, or use the lsof +D and +d options.
+	directory, you need to either specify the individual path names
+	of those files, their common mount point, or use the lsof +D 
+	and +d options.
+	
+	For example, if you wanted to check the files open in your /lsof 
+	folder then the following might be the quickest way to get
+	the answer you are looking for:
+
+	lsof / | grep /lsof | grep -v DIR
 
 	See the answer to the question "Why are the +D and +d
 	options so slow?" before you use +D or +d casually.
@@ -2811,7 +2783,7 @@ ______________________________________________________________________
 	    $ lsof -s/.\// ...
 	    lsof: invalid regexp modifier: /
 
-	Lsof is complaining the the first character it found after
+	Lsof is complaining the first character it found after
 	the second slash isn't an lsof command RE modifier -- 'b',
 	'i', or 'x'.
 
@@ -4095,7 +4067,7 @@ ______________________________________________________________________
 
 	At an upcoming release lsof will use a library called libproc
 	to obtain information about open files.  That version of lsof
-	wil be called libproc-based lsof.
+	will be called libproc-based lsof.
 
 	The /dev/kmem-based lsof sources may be found in the kmem
 	subdirectory of the dialects/darwin branch of the lsof source
@@ -4308,204 +4280,6 @@ ______________________________________________________________________
 	dropped.  The 4.76 distribution of lsof for BSDI BSD/OS may be
 	found on lsof.itap.purdue.edu in pub/tools/unix/lsof/OLD/src.
 
-
-7.0	DEC OSF/1, Digital UNIX, and Tru64 UNIX Problems
-
-7.1	Why does lsof complain about non-existent /dev/fd entries?
-
-	When you run lsof for Digital UNIX 3.2, lsof may complain:
-
-	    lsof: can't lstat /dev/fd/xxx: No such file or directory
-	    lsof: can't lstat /dev/fd/yyy: No such file or directory
-
-	(Or it may warn about other missing /dev/fd paths.)  When
-	you do an ``ls /dev/fd'' none of the missing paths are listed.
-
-	This is caused by a bug in the DEC library function
-	getdirentries().  For some reason, when /dev/fd is a file
-	system mount point, getdirentries() returns an incorrect
-	size for it to readdir().  (Lsof calls readdir() in its
-	ddev.c readdev() function.)  Because of the incorrect size,
-	readdir() goes past the end of the /dev/fd directory buffer,
-	encounters random paths and returns them to lsof.  Lsof
-	then attempts to lstat(2) the random paths, gets error
-	replies from lstat(2), and complains about the paths.
-
-	Duncan McEwan discovered this error and has reported it to
-	DEC.  Duncan also supplied an alternate readdir() function
-	as a work-around.  I've incorporated his readdir() in
-	dialects/osf/ddev.c (as the static ReadDir() function) with
-	some slight modifications, and enabled its use when the
-	USELOCALREADDIR symbol is defined.
-
-	The Configure script defines USELOCALREADDIR for Digital
-	UNIX version and 3.2.  If you don't want to use Duncan's
-	local readdir() function, edit the Makefile and remove
-	-DUSELOCALREADDIR from the CFGF string.  When DEC releases
-	a corrected getdirentries() function, I'll modify the
-	Configure script to stop defining USELOCALREADDIR.
-
-7.2	Why does the Digital UNIX V3.2 ld complain about Ots* symbols?
-
-	When you compile lsof on your Digital UNIX V3.2 system, ld
-	may complain:
-
-	    ld:
-	    Unresolved:
-	    knlist
-	    _OtsRemainder32Unsigned
-	    _OtsDivide64Unsigned
-	    _OtsRemainder64Unsigned
-	    _OtsDivide32Unsigned
-	    _OtsMove
-	    _OtsDivide32
-	    _OtsRemainder32
-	    *** Exit 1
-
-	Chris Eleveld reports this happens on Digital UNIX V3.2
-	systems after the Fortran compiler has been installed.
-
-	The best work-around seems to be to remove -lmld from the
-	CFGL string in the Makefile produced by Configure -- i.e.,
-	change:
-
-	    CFGL=    -lmld
-	to
-	    CFGL=
-
-	According to the V3.2 man page for nlist(3), this shouldn't
-	work, but my testing shows that it does.  Although I haven't
-	been able to test this second work-around, you might try
-	adding -lots to CFGL, rather than removing -lmld -- i.e.,
-	change:
-
-	    CFGL=    -lmld
-	to
-	    CFGL=    -lmld -lots
-
-	WARNING: my testing also shows that the V2.0 nlist(3) man
-	page means what it says when it calls for -lmld -- lsof
-	loaded without -mld under V2.0 can't locate the proc
-	(process) table address.
-
-	    DON'T REMOVE -lmld FROM THE DIGITAL UNIX V2.0 MAKEFILE.
-
-	If you run into this problem, please let me know what
-	problem you encountered and how you solved it.
-
-7.3	Why can't lsof locate named pipes (FIFOs) under V3.2?
-
-	While lsof for V3.2 can report on named pipes (FIFOs), it
-	can't find them by name.  That appears to happen because
-	of the way the V3.2 kernel lstat(2) function reports named
-	pipe device numbers.
-
-	The V3.2 kernel reports the device number as 0xfffffff,
-	while the kernel structures for named pipes that lsof
-	examines contain the device number of the file system on
-	which the named pipe resides.
-
-	Consequently, lsof can't match the device and inode number
-	pair it receives from applying lstat(2) to the named pipe
-	with any device and inode number pair it finds when scanning
-	kernel structures.
-
-	I don't have a work-around.  You can, of course, ask for
-	full lsof output and use a post-processing filer (e.g.,
-	grep) to locate the named pipe of interest.
-
-	This problem doesn't exist under V2.0.
-
-7.4	Why does lsof use the wrong configuration header files?
-	For example, why can't the lsof compilation find cpus.h?
-
-	DEC OSF/1, Digital UNIX, and Tru64 UNIX configuration header
-	files describe the hardware and software environment for
-	which your kernel boot file was constructed.  For example,
-	/sys/<name>/cpus.h defines the number of CPUs in its NCPUS
-	#define.
-
-	Lsof searches for the configuration header file subdirectory
-	in /sys (/usr/sys for Digital UNIX version 4.0 and Tru64
-	UNIX) by converting the first host name component to capital
-	letters -- e.g., TOMIS is derived from tomis.bio.purdue.edu.
-	If that subdirectory exists, lsof uses header files from
-	it.  (Configure reports what subdirectory is being used.)
-
-	If Configure doesn't find a host-name derived subdirectory,
-	it prompts you for the entry of a subdirectory name.  If
-	you can't find one, quit Configure and run the kernel
-	generation process to create a proper configuration sub-
-	directory.  If you don't identify a proper configuration
-	subdirectory and you try to compile lsof, the compiler will
-	complain about missing header files -- e.g., a missing
-	cpus.h.
-
-	Once you have located or generated a proper configuration
-	subdirectory, rerun Configure.  If you have generated a
-	configuration subdirectory whose name is derived from the
-	host name, Configure will find and use it.  If not, you
-	will have to specify its name to Configure.
-
-7.5	Why does lsof indicate incomplete paths with " -- " for Tru64
-	UNIX 5.1 files?
-
-	When lsof can't find a component of a path in the kernel's
-	name cache (aka DNLC), or can't determine that the left-most
-	component has as its parent the file system root, it uses
-	an "incomplete path" notation.  That notation begins with
-	the file system root name, followed by " -- ", followed by
-	the consecutive path name components lsof was able to find
-	in the DNLC -- e.g., "/ -- init".
-
-	Because the DNLC was significantly redesigned in Tru64 UNIX
-	5.1, lsof's handling of the cache had to be completely
-	redone.  As part of the DNLC redesign a name cache entry
-	parameter lsof formerly used to locate the file system root
-	of a path was removed.  With help from Chang Song I've been
-	able to implement an alternate method for detecting the
-	root of these file system types:  AdvFS (MSFS), CDFS, DVDFS,
-	FDFS, NFS, NFS3, and UFS.
-
-	When lsof doesn't know how to identify the root for a file
-	system type, it will resort to the " -- " incomplete path
-	notation.
-
-7.6	Why doesn't lsof report link count, node number, and size
-	for some Tru64 5.x CFS files?
-
-	Lsof reports link count, node number, and size for open
-	CFS files as recorded in their kernel node structure's
-	cached attributes.  Sometimes not all attributes are cached
-	on the system where lsof runs, so lsof cannot report them.
-
-7.7     Why does lsof say it can't read the kernel name list or
-	proc table on Digital UNIX 4.x or Tru64 UNIX?
-
-	By default on Digital UNIX 4 and Tru64 UNIX lsof reads the
-	addresses for kernel symbols with the knlist(3) function.
-	That function can fail, for example, when the kloadsrv
-	daemon isn't running or is malfunctioning.  When that
-	happens, lsof may abort with one of these error messages:
-
-	    lsof: can't read kernel name list from knlist(3): ...
-	  or
-	    lsof: can't read proc table info
-
-	The first message suggests a complete knlist(3) or kloadsrv
-	failure; the second, a partial one.
-
-	If you know the name of the file from which the running
-	system was booted, e.g., /vmunix, you can use lsof's -k
-	option to direct it to read kernel symbol addresses from
-	the name list of that file --
-
-	    $ lsof -k /vmunix ...
-
-	If that works, then knlist(3) is malfunctioning and you
-	need to fix it.
-
-
 8.0	FreeBSD Problems
 
 8.1	Why doesn't lsof report on open kernfs files?
@@ -5737,7 +5511,7 @@ ______________________________________________________________________
 	subdirectory of a process' /proc/<PID> directory, it reports a
 	single file of the type ``NOFD'' (for no file descriptors).
 
-	Lsof reports the the /proc/<PID>/path in the NAME column,
+	Lsof reports the /proc/<PID>/path in the NAME column,
 	followed by "(opendir: xxx)", where ``xxx'' is the error
 	message returned by opendir().
 
@@ -5941,37 +5715,6 @@ ______________________________________________________________________
 	and NETBSD_SYS.
 
 
-12.0	NEXTSTEP and OPENSTEP Problems
-
-12.1	Why can't lsof report on 3.1 lockf() or fcntl(F_SETLK)
-	locks?
-
-	Lsof has code to test for locks defined with lockf() or
-	fcntl(F_SETLK) under NEXTSTEP 3.1, but that code has never
-	been tested.  I couldn't test it, because my NEXTSTEP 3.1
-	lockf() and fcntl(F_SETLK) functions return "Invalid
-	argument" every way I have tried to invoke them.
-
-	If your NEXTSTEP 3.1 system does allow you to use lockf()
-	and fcntl(F_SETLK) and lsof doesn't report locks set with
-	them, then the code in .../dialects/next/dnode.c probably
-	isn't correct.  Please contact me via e-mail at <abe@purdue.edu>
-	and tell me how you got your lockf() and fcntl(F_SETLK) system
-	calls to work.  Make sure "lsof" appears in the "Subject:" line
-	so my e-mail filter won't classify your letter as Spam.
-
-12.2	Why doesn't lsof compile for NEXTSTEP with AFS?
-
-	I no longer have a NEXTSTEP test system that has AFS.
-	Changes to lsof since I once had a test system have caused
-	me to change the AFS code in NEXTSTEP without being able
-	to test the changes.
-
-	If you need AFS support for NEXTSTEP and can't get it to
-	compile, please contact me.  Perhaps we can jointly fix
-	the problems.
-
-
 13.0	OpenBSD Problems
 
 13.1	Why doesn't lsof support kernfs on my OpenBSD system?
@@ -6021,7 +5764,7 @@ ______________________________________________________________________
 	other OpenBSD SPARC versions, but hasn't been tested there.
 
 	If you want to enable the hack for your OpenBSD SPARC
-	version, modify this code in .../dialects/n+obsd/dlsof.h:
+	version, modify this code in .../dialects/openbsd/dlsof.h:
 
 	    # if    defined(OPENBSDV)
 	    #  if   OPENBSDV==2030 && defined(__sparc__)
@@ -7780,7 +7523,7 @@ ______________________________________________________________________
 	applying stat(2) to the contract file path name with what it
 	finds in kernel data.
 
-17.27	Solaris 10 and above ZFS probblems
+17.27	Solaris 10 and above ZFS problems
 
 17.27.1	Why does Configure warn that ZFS support is not enabled?
 
@@ -7835,7 +7578,7 @@ ______________________________________________________________________
 	-- usually called prdata.h.
 
 18.2	How do I disable the device cache file feature or alter
-	it's behavior?
+	its behavior?
 
 	To disable the device cache file feature for a dialect,
 	remove the HASDCACHE definition from the machine.h file of
@@ -7984,7 +7727,6 @@ ______________________________________________________________________
 
 	    AIX 4.1.4 (AFS 3.4a)
 	    Linux 1.2.13 (AFS 3.3)
-	    NEXTSTEP 3.2 (AFS 3.3)
 	    Solaris 2.[56] (AFS 3.4a)
 
 	It may recognize AFS files on other versions of these
diff --git a/00MANIFEST b/00MANIFEST
index 339868c..951b93f 100644
--- a/00MANIFEST
+++ b/00MANIFEST
@@ -1,4 +1,5 @@
 .:
+00.README.FIRST
 00CREDITS
 00DCACHE
 00DIALECTS
@@ -9,31 +10,26 @@
 00PORTING
 00QUICKSTART
 00README
-00.README.FIRST
 00TEST
 00XCONFIG
-0..README.BEFORE.README.FIRST@
 AFSConfig*
-arg.c
 ChangeLog
-check.bash*
 Configure*
 Customize*
-dialects/
 Inventory*
+arg.c
+dialects/
 lib/
 lsof.8
-lsof_fields.h
-lsof.h
+common.h
 lsof.man
+lsof_fields.h
 main.c
 misc.c
 node.c
 print.c
 proc.c
 proto.h
-README.md
-regex.h
 scripts/
 store.c
 tests/
@@ -42,9 +38,140 @@ util.c
 version
 
 ./dialects:
+aix/
+darwin/
+du/
+freebsd/
+hpux/
 linux/
+netbsd/
+n+os/
+openbsd/
+osr/
+sun/
+uw/
+
+./dialects/aix:
+Makefile
+Mksrc*
+aix5/
+ddev.c
+dfile.c
+dlsof.h
+dmnt.c
+dnode.c
+dnode1.c
+dnode2.c
+dproc.c
+dproto.h
+dsock.c
+dstore.c
+machine.h
+
+./dialects/aix/aix5:
+README
+j2/
+
+./dialects/aix/aix5/j2:
+j2_lock.h
+private_j2_snapshot.h
+
+./dialects/darwin:
+Makefile
+Mksrc*
+ddev.c
+dfile.c
+dlsof.h
+dmnt.c
+dproc.c
+dproto.h
+dsock.c
+dstore.c
+machine.h
+
+./dialects/du:
+Makefile
+Mksrc*
+ddev.c
+dfile.c
+dlsof.h
+dmnt.c
+dnode.c
+dproc.c
+dproto.h
+dsock.c
+dstore.c
+machine.h
+
+./dialects/freebsd:
+Makefile
+Makefile.zfs
+Mksrc*
+dlsof.h
+dmnt.c
+dnode.c
+dnode1.c
+dnode2.c
+dproc.c
+dproto.h
+dsock.c
+dstore.c
+dzfs.h
+include/
+machine.h
+
+./dialects/freebsd/include:
+procfs/
+
+./dialects/freebsd/include/procfs:
+pfsnode.h
+
+./dialects/hpux:
+kmem/
+pstat/
+
+./dialects/hpux/kmem:
+Makefile
+Mksrc*
+dfile.c
+dlsof.h
+dmnt.c
+dnode.c
+dnode1.c
+dnode2.c
+dproc.c
+dproto.h
+dsock.c
+dstore.c
+hpux11/
+machine.h
+
+./dialects/hpux/kmem/hpux11:
+ipc_s.h
+kernbits.h
+lla.h
+nfs_clnt.h
+proc.h
+rnode.h
+sth.h
+tcp_s.h
+udp_s.h
+vnode.h
+
+./dialects/hpux/pstat:
+Makefile
+Mksrc*
+dfile.c
+dlsof.h
+dproc.c
+dproto.h
+dsock.c
+dstore.c
+machine.h
 
 ./dialects/linux:
+Makefile
+Mksrc*
 dfile.c
 dlsof.h
 dmnt.c
@@ -54,54 +181,126 @@ dproto.h
 dsock.c
 dstore.c
 machine.h
+
+./dialects/netbsd:
 Makefile
 Mksrc*
-tests/
+dlsof.h
+dmnt.c
+dnode.c
+dnode1.c
+dproc.c
+dproto.h
+dsock.c
+dstore.c
+machine.h
+
+./dialects/n+os:
+Makefile
+Mksrc*
+dlsof.h
+dnode.c
+dnode1.c
+dproc.c
+dproto.h
+dsock.c
+dstore.c
+machine.h
+
+./dialects/osr:
+Makefile
+Mksrc*
+dfile.c
+dlsof.h
+dmnt.c
+dnode.c
+dproc.c
+dproto.h
+dsock.c
+dstore.c
+include/
+machine.h
+
+./dialects/osr/include:
+netdb.h
+sys/
 
-./dialects/linux/tests:
-case-00-linux-hello.bash*
-case-10-mqueue.bash*
-case-10-ux-socket-state.bash*
-case-20-epoll.bash*
-case-20-eventfd-endpoint.bash*
-case-20-inet6-ffffffff-handling.bash*
-case-20-inet6-socket-endpoint.bash*
-case-20-inet-socket-endpoint.bash*
-case-20-mqueue-endpoint.bash*
-case-20-open-flags-cx.bash*
-case-20-open-flags-path.bash*
-case-20-open-flags-tmpf.bash*
-case-20-pidfd-pid.bash*
-case-20-pipe-endpoint.bash*
-case-20-pipe-no-close-endpoint.bash*
-case-20-pty-endpoint.bash*
-case-20-ux-socket-endpoint.bash*
-case-20-ux-socket-endpoint-unaccepted.bash*
-epoll.c
-eventfd.c
+./dialects/osr/include/sys:
+cdefs.h
+
+./dialects/sun:
 Makefile
-mq_fork.c
-mq_open.c
-open_with_flags.c
-pidfd.c
-pipe.c
-pty.c
-util-open-flags.bash
-ux.c
+Mksrc*
+ddev.c
+dfile.c
+dlsof.h
+dmnt.c
+dnode.c
+dnode1.c
+dnode2.c
+dproc.c
+dproto.h
+dsock.c
+dstore.c
+machine.h
+solaris_kaddr_filters
+
+./dialects/uw:
+Makefile
+Mksrc*
+dfile.c
+dlsof.h
+dmnt.c
+dnode.c
+dnode1.c
+dnode2.c
+dnode3.c
+dproc.c
+dproto.h
+dsock.c
+dstore.c
+machine.h
+uw7/
+
+./dialects/uw/uw7:
+README
+fs/
+sys/
+vm/
+
+./dialects/uw/uw7/fs:
+nsc_cfs/
+procfs/
+
+./dialects/uw/uw7/fs/nsc_cfs:
+cnode.h
+
+./dialects/uw/uw7/fs/procfs:
+README
+prdata.h
+
+./dialects/uw/uw7/sys:
+fs/
+
+./dialects/uw/uw7/sys/fs:
+README
+fifonode.h
+namenode.h
+
+./dialects/uw/uw7/vm:
 
 ./lib:
+Makefile.skel
 ckkv.c
 cvfs.c
 dvch.c
 fino.c
 isfn.c
 lkud.c
-Makefile.skel
 pdvn.c
 prfp.c
 ptti.c
 rdev.c
-regex.c
 rmnt.c
 rnam.c
 rnch.c
@@ -111,32 +310,24 @@ snpf.c
 ./scripts:
 00MANIFEST
 00README
-big_brother.pl*
-count_pf.pl*
-identd.pl*
-idrlogin.pl*
+big_brother.perl5*
+count_pf.perl*
+count_pf.perl5*
+identd.perl5*
+idrlogin.perl*
+idrlogin.perl5*
+list_NULf.perl5*
 list_fields.awk
-list_fields.pl*
-list_NULf.pl*
-shared.pl*
-sort_res.pl*
-watch_a_file.pl*
+list_fields.perl*
+shared.perl5*
+sort_res.perl5*
+watch_a_file.perl*
 xusers.awk*
 
 ./tests:
+00README
 Add2TestDB*
-case-00-hello.bash*
-case-01-version.bash*
-case-13-classic.bash*
-case-14-classic-opt.bash*
-case-20-exit-status.bash*
-case-20-fd-only-inclusion.bash*
-case-20-handle-missing-files.bash*
-case-20-offset-field.bash*
-case-20-repeat-count.bash*
-case-21-exit-Q-status.bash*
 CkTestDB*
-LsofTest.h
 LTbasic.c
 LTbigf.c
 LTdnlc.c
@@ -147,5 +338,6 @@ LTnlink.c
 LTsock.c
 LTszoff.c
 LTunix.c
+LsofTest.h
 Makefile
 TestDB
diff --git a/00PORTING b/00PORTING
index 6cf1dcb..8563fcf 100644
--- a/00PORTING
+++ b/00PORTING
@@ -142,6 +142,11 @@ project has so far generated only two kernel modification:
 One final note about the /proc-based Linux lsof: it doesn't need
 any functions from the lsof library in the lib/ subdirectory.
 
+FreeBSD is now also using a similar approach. Sysctls are used
+to retrieve processes, files, socket PCBs etc. Access to kernel
+memory is optional and only used as a last resort when data is
+not provided by the kernel.
+
 
 General Guidelines
 ------------------
@@ -259,11 +264,6 @@ different source files -- e.g., dnode[123].c -- to eliminate node
 header file structure element name conflicts.  The source modules
 in a few subdirectories are organized that way.
 
-Unusual situations occur for NetBSD and OpenBSD, and for NEXTSTEP
-and OPENSTEP.  Each pair of dialects is so close in design that
-the same dialect sources from the n+obsd subdirectory serves NetBSD
-and OpenBSD; from n+os, NEXTSTEP and OPENSTEP.
-
 These are common files in lsof4/:
 
     Configure	the configuration script
@@ -282,7 +282,7 @@ These are the common function source files in lsof4/:
 
     arg.c	common argument processing functions
 
-    lsof.h	common header file that #include's the dialect-specific
+    common.h	common header file that #include's the dialect-specific
 		header files
 
     main.c	common main function for lsof 4
@@ -444,10 +444,6 @@ to be compiled and archived to liblsof.a.
 			NCACHE_VP, X_NCACHE, and X_NCSIZE, customize
 			them.
 
-    snpf.c		Source for the snprintf() family of functions
-
-			USE_LIB_SNPF selects it.
-
 
 The comments and the source code in these library files give more
 information on customization.
@@ -677,7 +673,7 @@ possibilities
 
     FSV_DEFAULT		defines the default file structure values to
 			list.  It may be composed of or'd FSV_*
-			(See lsof.h) values.  The default is none (0).
+			(See common.h) values.  The default is none (0).
 
     GET_MAJ_DEV         is a macro to get major portion from device
 			number instead of via the standard major()
@@ -703,19 +699,9 @@ possibilities
     HAS_AIO_REQ_STRUCT	is defined for Solaris 10 and above systems that
 			have the aio_req structure definition.
 
-    HAS_ATOMIC_T	indicates the Linux version has an
-			<asm/atomic.h> header file and it contains
-			"typedef struct .* atomic_t;"
-
     HASAOPT		indicates the dialect supports the AFS -A
 			option when HAS_AFS is also defined.
 
-    HAS_ASM_TERMIOBITS  indicates for Linux Alpha that the
-			<asm/termiobits.h> header file exists.
-
-    HASAX25CBPTR	indicates that the Linux sock struct has an
-			ax25_db pointer.
-
     HASBLKDEV		indicates the dialect has block device support.
 
     HASBUFQ_H		indicates the *NSD dialect has the <sys/bufq.h>
@@ -724,9 +710,6 @@ possibilities
     HASCACHEFS		enables cache file system support for the
 			dialect.
 
-    HAS_CDFS		enables CDFS file system support for the
-			dialect.
-
     HASCDRNODE		enables/disables readcdrnode() in node.c.
 
     HAS_CLOSEFROM	is defined when the FreeBSD C library contains the
@@ -758,12 +741,6 @@ possibilities
 			distribution for more information on this
 			feature.
 
-    HASDENTRY		indicates the Linux version has a dentry
-			struct defined in <linux/dcache.h>.
-
-    HASDEVKNC           indicates the Linux version has a kernel
-			name cached keyed on device number.
-
     HAS_DINODE_U	indicates the OpenBSD version has a dinode_u
 			union in its inode structure.
 
@@ -798,9 +775,6 @@ possibilities
     HASF_VNODE		indicates the dialect's file structure has an
 			f_vnode member in it.
 
-    HAS_FDESCENTTBL	indicates the FreeBSD system has the fdescenttbl
-			structure.
-
     HAS_FILEDESCENT	indicates the FreeBSD system has the filedescent
 			definition in the <sys/filedesc.h> header file.
 
@@ -814,20 +788,11 @@ possibilities
 
     HASFIFONODE		enables/disables readfifonode() in node.c.
 
-    HAS_FL_FD		indicates the Linux version has an fl_fd
-			element in the lock structure of <linux/fs.h>.
-
-    HAS_FL_FILE		indicates the Linux version has an fl_file
-			element in the lock structure of <linux/fs.h>.
-
-    HAS_FL_WHENCE	indicates the Linux version has an fl_whence
-			element in the lock structure of <linux/fs.h>.
-
     HAS_F_OPEN		indicates the UnixWare 7.x dialect has the
 			f_open member in its file struct.
 
     HASFSINO            enables the inclusion of the fs_ino element
-			in the lfile structure definition in lsof.h.
+			in the lfile structure definition in common.h.
 			This contains the file system's inode number
 			and may be needed when searching the kernel
 			name cache.  See dialects/osr/dproc.c for
@@ -848,18 +813,11 @@ possibilities
 			See also the RMNT_EXPDEV and RMNT_FSTYPE
 			documentation in lib/rmnt.c
 
-    HASFUSEFS		is defined when the FreeBSD system has FUSE file system
-			support.
-
     HASGETBOOTFILE	indicates the NetBSD or OpenBSD dialect has
 			a getbootfile() function.
 
     HASGNODE		enables/disables readgnode() in node.c.
 
-    HASHASHPID		is defined when the Linux version (probably
-			above 2.1.35) has a pidhash_next member in
-			its task structure.
-
     HASHSNODE		enables/disables readhsnode() in node.c.
 
     HASI_E2FS_PTR	indicates the BSD dialect has a pointer in
@@ -878,12 +836,6 @@ possibilities
 
     HASINODE		enables/disables readinode() in node.c.
 
-    HASINOKNC		indicates the Linux version has a kernel
-			name cache keyed on inode address.
-
-    HASINADDRSTR	is defined when the inp_[fl]addr members
-			of the inpcb structure are structures.
-
     HASINRIAIPv6	is defined if the dialect has the INRIA IPv6
 			support.  (HASIPv6 will also be defined.)
 
@@ -912,9 +864,6 @@ possibilities
 
     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>.
-
     HASKERNFS           is defined for BSD dialects for which
 			/kern file system support can be provided.
 
@@ -925,9 +874,6 @@ 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.
 
@@ -938,7 +884,8 @@ possibilities
 			"defined(_KVM_VNODE)" in <sys/vnode.h>.
 
     HASLFILEADD		defines additional, dialect-specific elements
-    SETLFILEADD		in the lfile structure (defined in lsof.h).
+
+    SETLFILEADD		in the lfile structure (defined in common.h).
 			HASLFILEADD is a macro. The accompanying SETFILEADD
 			macro is used in the alloc_lfile() function of
 			proc.c to preset the additional elements.
@@ -988,14 +935,8 @@ possibilities
     HASNCVPID           The *BSD dialect namecache struct has an
 			nc_vpid member.
 
-    HASNETDEVICE_H	indicates the Linux version has a netdevice.h
-			header file.
-
     HAS_NFS		enables NFS support for the dialect.
 
-    HASNFSKNC		indicates the LINUX version has a separate
-			NFS name cache.
-
     HASNFSPROTO         indicates the NetBSD or OpenBSD version
 			has the nfsproto.h header file.
 
@@ -1023,12 +964,6 @@ possibilities
     HAS_NO_6PPCB	is defined if the FreeBSD in_pcb.h has no in6p_ppcb
 			definition.
 
-    HAS_NO_IDEV		indicates the FreeBSD system's inode has no i_dev
-			member.
-
-    HAS_NO_ISO_DEV	indicates the FreeBSD 6 and higher system has
-			no i_dev member in its iso_node structure.
-
     HAS_NO_LONG_LONG	indicates the dialect has no support for the C
 			long long type.  This definition is used by
 			the built-in snprintf() support of lib/snpf.c.
@@ -1036,9 +971,6 @@ possibilities
     HASNORPC_H		indicates the dialect has no /usr/include/rpc/rpc.h
 			header file.
 
-    HAS_NO_SI_UDEV	indicates the FreeBSD 6 and higher system has
-			no si_udev member in its cdev structure.
-
     HASNOSOCKSECURITY   enables the listing of open socket files,
 			even when HASSECURITY restricts listing of
 			open files to the UID of the user who is
@@ -1117,23 +1049,6 @@ possibilities
 
 			void HASPRINTNM(struct lfile *)
 
-    HASPRINTOFF         this value names a private function for
-			printing the dialect's file offset.  Used
-			by print.c/print_file().  Takes two arguments:
-
-			char *HASPRINTOFF(struct lfile *, int ty)
-
-			Where ty == 0 if the offset is to be printed
-			in 0t<decimal> format; 1, 0x<hexadecimal>.
-
-    HASPRINTSZ		this value names a private function for
-			printing the dialect's file size.  Used
-			by print.c/print_file(). Takes one argument:
-
-			char *HASPRINTSZ(struct lfile *)
-
-			void HASPRINTNM(struct lfile *)
-
     HASPRIVFILETYPE     enables processing of the private file
 			type, whose number (from f_type of the file
 			struct) is defined by PRIVFILETYPE.
@@ -1218,15 +1133,8 @@ possibilities
 			that processes the results of a successful
 			stat(2) of a file in that directory.
 
-    HASSPECNODE         indicates the DEC OSF/1, or Digital UNIX,
-			or Tru64 UNIX <sys/specdev.h> has a spec_node
-			structure definition.
-
     HASSNODE		indicates the dialect has snode support.
 
-    HAS_SOCKET_SK	indicates that the Linux socket structure
-			has the ``struct sock *sk'' member.
-
     HASSOOPT            indicates the dialect has socket option
 			information (e.g., SO_* symbols) available.
 
@@ -1268,10 +1176,6 @@ possibilities
     HAS_SYS_SX_H	indicates the FreeBSD 7.0 and higher system has
 			a <sys/sx.h> header file.
 
-    HASTAGTOPATH        indicates the DEC OSF/1, Digital UNIX, or
-			Tru64 UNIX dialect has a libmsfs.so,
-			containing tag_to_path().
-
     HAS_TMPFS		indicates the FreeBSD system has the <fs/tmpfs.h>
 			header file.
 
@@ -1291,7 +1195,7 @@ possibilities
 
     HASTCPUDPSTATE	is defined when the dialect has support for
 			TCP and UDP state, including the "-s p:s"
-			option and associated speed ehancements.
+			option and associated speed enhancements.
 
     HASTFS		indicates that the Pyramid dialect has TFS
 			file system support.
@@ -1302,11 +1206,6 @@ possibilities
     HAS_UM_UFS		indicates the OpenBSD version has UM_UFS[12]
 			definitions.
 
-    HASUNMINSOCK	indicates the Linux version has a user name
-			element in the socket structure; a value of
-			0 says there is no unix_address member; 1,
-			there is.
-
     HASUINT16TYPE	is defined when the dialect has a typedef
 			for u_int16 that may conflict with some other
 			header file's redefinition (e.g., <afs/std.h>).
@@ -1396,6 +1295,10 @@ possibilities
     HASXOPT_VALUE	defines the default binary value for the X option
 			in store.c.
 
+    HAS_XTCPCB_TMAXSEG	indicates that <netinet/tcp_var.h> in this FreeBSD
+			version exists and its struct xtcpcb has a
+			t_magseg field.
+
     HAS_ZFS		indicates the dialect has support for the ZFS file
 			system.
 
@@ -1487,7 +1390,7 @@ possibilities
 
     NOWARNBLKDEV        specifies that no warning is to be issued
 			when no block devices are found.  This
-			definiton is used only when HASBLKDEV is
+			definition is used only when HASBLKDEV is
 			also defined.
 
     OFFDECDIG           specifies how many decimal digits will be
diff --git a/00QUICKSTART b/00QUICKSTART
index a02312d..0df967c 100644
--- a/00QUICKSTART
+++ b/00QUICKSTART
@@ -1,1047 +1 @@
-
-			A Quick Start for Lsof
-
-1.  Introduction
-================
-
-  Agreed, the lsof man page is dense and lsof has a plethora of
-  options.  There are examples, but the manual page format buries
-  them at the end.  How does one get started with lsof?
-
-  This file is an attempt to answer that question.  It plunges
-  immediately into examples of lsof use to solve problems that
-  involve looking at the open files of Unix processes.
-
-
-			    Contents
-
-	    1.  Introduction
-	    2.  Finding Uses of a Specific Open File
-	    3.  Finding Open Files Filling a File System
-		a.  Finding an Unlinked Open File
-	    4.  Finding Processes Blocking Umount
-	    5.  Finding Listening Sockets
-	    6.  Finding a Particular Network Connection
-	    7.  Identifying a Netstat Connection
-	    8.  Finding Files Open to a Named Command
-	    9.  Deciphering the Remote Login Trail
-		a.  The Fundamentals
-		b.  The idrlogin.perl[5] Scripts
-	    10. Watching an Ftp or Rcp Transfer
-	    11. Listing Open NFS Files
-	    12. Listing Files Open by a Specific Login
-		a.  Ignoring a Specific Login
-	    13. Listing Files Open to a Specific Process Group
-	    14. When Lsof Seems to Hang
-		a.  Kernel lstat(), readlink(), and stat() Blockages
-		b.  Problems with /dev or /devices
-		c.  Host and Service Name Lookup Hangs
-		d.  UID to Login Name Conversion Delays
-	    15. Output for Other Programs
-	    16. The Lsof Exit Code and Shell Scripts
-	    17. Strange messages in the NAME column
-
-			Options
-
-	    A.  Selection Options
-	    B.  Output Options
-	    C.  Precautionary Options
-	    D.  Miscellaneous Lsof Options
-
-
-2.  Finding Uses of a Specific Open File
-========================================
-
-  Often you're interested in knowing who is using a specific file.
-  You know the path to it and you want lsof to tell you the processes
-  that have open references to it.
-
-  Simple -- execute lsof and give it the path name of the file of
-  interest -- e.g.,
-
-  $ lsof /etc/passwd
-
-  Caveat: this only works if lsof has permission to get the status
-  (via stat(2)) of the file at the named path.  Unless the lsof
-  process has enough authority  -- e.g., it is being run with a
-  real User ID (UID) of root -- this AIX example won't work:
-
-  Further caveat: this use of lsof will fail if the stat(2) kernel
-  syscall returns different file parameters -- particularly device
-  and inode numbers -- than lsof finds in kernel node structures.
-  This condition is rare and is usually documented in the 00FAQ
-  file of the lsof distribution.
-
-  $ lsof /etc/security/passwd
-  lsof: status error on /etc/security/passwd: Permission denied
-
-
-3.  Finding Open Files Filling a File System
-============================================
-
-  Oh! Oh!  /tmp is filling and ls doesn't show that any large files
-  are being created.  Can lsof help?
-
-  Maybe.  If there's a process that is writing to a file that has
-  been unlinked, lsof may be able to discover the process for you.
-  You ask it to list all open files on the file system where /tmp
-  is located.
-
-  Sometimes /tmp is a file system by itself.  In that case,
-
-  $ lsof /tmp
-
-  is the appropriate command.  If, however, /tmp is part of another
-  file system, typically /, then you may have to ask lsof to list
-  all files open on the containing file system and locate the
-  offending file and its process by inspection -- e.g.,
-
-    $ lsof / | more
-  or
-    $ lsof / | grep ...
-
-  Caveat: there must be a file open to a for the lsof search to
-  succeed.  Sometimes the kernel may cause a file reference to
-  persist, even where there's no file open to a process.  (Can you
-  say kernel bug?  Maybe.)  In any event, lsof won't be able to
-  help in this case.
-
-  a.  Finding an Unlinked Open File
-  =================================
-
-  A pesky variant of a file that is filling a file system is an
-  unlinked file to which some process is still writing.  When a
-  process opens a file and then unlinks it, the file's resources
-  remain in use by the process, but the file's directory entries
-  are removed.  Hence, even when you know the directory where the
-  file once resided, you can't detect it with ls.
-
-  This can be an administrative problem when the unlinked file is
-  large, and the process that holds it open continues to write to
-  it.  Only when the process closes the file will its resources,
-  particularly disk space, be released.
-
-  Lsof can help you find unlinked files on local disks.  It has an
-  option, +L, that will list the link counts of open files.  That
-  helps because an unlinked file on a local disk has a zero link
-  count.  Note: this is NOT true for NFS files, accessed from a
-  remote server.
-
-  You could use the option to list all files and look for a zero
-  link count in the NLINK column -- e.g.,
-
-    $lsof +L
-    COMMAND   PID USER   FD  TYPE DEVICE SIZE/OFF NLINK  NODE NAME
-    ...
-    less    25366  abe  txt  VREG    6,0    40960     1 76319 /usr/...
-    ...
-  > less    25366  abe    3r VREG    6,0    17360     0 98768 / (/dev/sd0a)
-
-  Better yet, you can specify an upper bound to the +L option, and
-  lsof will select only files that have a link count less than the
-  upper bound.  For example:
-
-    $ lsof +L1
-    COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NLINK  NODE NAME
-    less    25366  abe    3r  VREG    6,0    17360     0 98768 / (/dev/sd0a)
-
-  You can use lsof's -a (AND) option to narrow the link count search
-  to a particular file system.  For example, to look for zero link
-  counts on the /home file system, use:
-
-    $ lsof -a +L1 /home
-
-  CAUTION: lsof can't always report link counts for all file types
-  -- e.g., it may not report them for FIFOs, pipes, or sockets.
-  Remember also that link counts for NFS files on an NFS client
-  host don't behave as do link counts for files on local disks.
-
-
-4.  Finding Processes Blocking Umount
-=====================================
-
-  When you need to unmount a file system with the umount command,
-  you may find the operation blocked by a process that has a file
-  open on the file systems.  Lsof may be able to help you find the
-  process.  In response to:
-
-  $ lsof <file_system_name>
-
-  Lsof will display all open files on the named file system.  It
-  will also set its exit code zero when it finds some open files
-  and non-zero when it doesn't, making this type of lsof call
-  useful in shell scripts.  (See section 16.)
-
-  Consult the output of the df command for file system names.
-
-  See the caveat in the preceding section about file references
-  that persist in the kernel without open file traces.  That
-  situation may hamper lsof's ability to help with umount, too.
-
-
-5.  Finding Listening Sockets
-=============================
-
-  Sooner or later you may wonder if someone has installed a network
-  server that you don't know about.  Lsof can list for you all the
-  network socket files open on your machine with:
-
-    $ lsof -i
-
-  The -i option without further qualification lists all open Internet
-  socket files.  You can add network names or addresses, protocol
-  names, and service names or port numbers to the -i option to
-  refine the search.  (See the next section.)
-
-
-6.  Finding a Particular Network Connection
-===========================================
-
-  When you know the source or destination of a network connection
-  whose open files and process you'd like to identify, the -i option
-  may help.
-
-  If, for example, you want to know what process has a connection
-  open to or from the Internet host named aaa.bbb.ccc, you can ask
-  lsof to search for it with:
-
-  $ lsof -i@aaa.bbb.ccc
-
-  If you're interested in a particular protocol -- TCP or UDP --
-  and a specific port number or service name, you can add those
-  discriminators to the -i information:
-
-  $ lsof -iTCP@aaa.bbb.ccc:ftp-data
-
-  If you're interested in a particular IP version -- IPv4 or IPv6
-  -- and your UNIX dialect supports both (It does if "IPv[46]"
-  appears in the lsof -h output.), you can add the '4' or '6'
-  selector immediately after -i:
-
-  $ lsof -i4
-  $ lsof -i6
-
-
-7.  Identifying a Netstat Connection
-====================================
-
-  How do I identify the process that has a network connection
-  described in netstat output?  For example, if netstat says:
-
-  Proto Recv-Q Send-Q  Local Address          Foreign Address        (state)
-  tcp        0      0  vic.1023               ipscgate.login         ESTABLISHED
-
-  What process is connected to service name ``login'' on ipscgate?
-
-  Use lsof's -i option:
-
-  $lsof -iTCP@ipscgate:login
-  COMMAND     PID     USER   FD   TYPE     DEVICE   SIZE/OFF  INODE NAME
-  rlogin    25023      abe    3u  inet 0x10144168      0t184    TCP lsof.itap.purdue.edu:1023->ipscgate.cc.purdue.edu:login
-  ...
-
-  There's another way.  Notice the 0x10144168 in the DEVICE column
-  of the lsof output?  That's the protocol control block (PCB)
-  address.  Many netstat applications will display it when given
-  the -A option:
-
-  $ netstat -A
-  PCB      Proto Recv-Q Send-Q  Local Address      Foreign Address    (state)
-  10144168 tcp        0      0  vic.1023           ipscgate.login     ESTABLISHED
-  ...
-
-  Using the PCB address, lsof, and grep, you can find the process this
-  way, too:
-
-  $ lsof -i | grep 10144168
-  rlogin    25023      abe    3u  inet 0x10144168      0t184    TCP lsof.itap.purdue.edu:1023->ipscgate.cc.purdue.edu:login
-  ...
-
-  If the file is a UNIX socket and netstat reveals and adress for it,
-  like this Solaris 11 example:
-
-  $ netstat -a -f unix
-  Active UNIX domain sockets
-  Address  Type          Vnode     Conn  Local Addr      Remote Addr
-  ffffff0084253b68 stream-ord 0000000 0000000
-
-  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
-
-
-8.  Finding Files Open to a Named Command
-=========================================
-
-  When you want to look at the files open to a particular command,
-  you can look up the PID of the process running the command and
-  use lsof's -p option to specify it.
-
-  $ lsof -p <PID>
-
-  However, there's a quicker way, using lsof's -c option, provided
-  you don't mind seeing output for every process running the named
-  command.
-
-  $ lsof -c <first_characters_of_command_name_that_interest_you>
-
-  The lsof -c option is useful when you want to see how many instances
-  of a given command are executing and what their open files are.
-  One useful example is for the sendmail command.
-
-  $ lsof -c sendmail
-
-
-9.  Deciphering the Remote Login Trail
-======================================
-
-  If the network connection you're interested in tracing has been
-  initiated externally and is connected to an rlogind, sshd, or
-  telnetd process, asking lsof to identify that process might not
-  give a wholly satisfying answer.  The report may be that the
-  connection exists, but to a process owned by root.
-
-  a.  The Fundamentals
-  ====================
-
-    How do you get from there to the login name really using the
-    connection?  You have to know a little about how real and pseudo
-    ttys are paired in your system, and then use several lsof probes
-    to identify the login.
-
-    This example comes from a Solaris 2.4 system, named klaatu.cc.
-    I've logged on to it via rlogin from lsof.itap.  The first lsof
-    probe,
-
-    $ lsof -i@lsof.itap
-
-    yields (among other things):
-
-    COMMAND     PID     USER   FD   TYPE     DEVICE   SIZE/OFF  INODE NAME
-    in.rlogin  7362     root    0u  inet 0xfc0193b0      0t242    TCP klaatu.cc.purdue.edu:login->lsof.itap.purdue.edu:1023
-    ...
-
-    This confirms that a connection exists.  A second lsof probe
-    shows:
-
-    $ lsof -p7362
-    COMMAND     PID     USER   FD   TYPE     DEVICE   SIZE/OFF  INODE NAME
-    ...
-    in.rlogin  7362     root    0u  inet 0xfc0193b0      0t242    TCP klaatu.cc.purdue.edu:login->lsof.itap.purdue.edu:1023
-    ...
-    in.rlogin  7362     root    3u  VCHR    23,   0       0t66  52928 /devices/pseudo/clone@0:ptmx->pckt->ptm
-
-    7362 is the Process ID (PID) of the in.rlogin process, discovered
-    in the first lsof probe.  (I've abbreviated the output to simplify
-    the example.)  Now comes a need to understand Solaris pseudo-ttys.
-    The key indicator is in the DEVICE column for FD 3, the major/minor
-    device number of 23,0.  This translates to /dev/pts/0, so a third
-    lsof probe,
-
-    $ lsof /dev/pts/0
-    COMMAND     PID     USER   FD   TYPE     DEVICE   SIZE/OFF  INODE NAME
-    ksh        7364      abe    0u  VCHR    24,   0     0t2410  53410 /dev/pts/../../devices/pseudo/pts@0:0
-
-    shows in part that login abe has a ksh process on /dev/pts/0.
-    (The NAME that lsof shows is not /dev/pts/0 but the full expansion
-    of the symbolic link that lsof finds at /dev/pts/0.)
-
-    Here's a second example, done on an HP-UX 9.01 host named ghg.ecn.
-    Again, I've logged on to it from lsof.itap, so I start with:
-
-    $ lsof -i@lsof.itap
-    COMMAND     PID     USER   FD   TYPE       DEVICE   SIZE/OFF  INODE NAME
-    rlogind   10214     root    0u  inet   0x041d5f00     0t1536    TCP ghg.ecn.purdue.edu:login->lsof.itap.purdue.edu:1023
-    ...
-
-    Then,
-
-    $ lsof -p10214
-    COMMAND     PID     USER   FD   TYPE       DEVICE   SIZE/OFF  INODE NAME
-    ...
-    rlogind   10214     root    0u  inet   0x041d5f00     0t2005    TCP ghg.ecn.purdue.edu:login->lsof.itap.purdue.edu:1023
-    ...
-    rlogind   10214     root    3u  VCHR  16,0x000030     0t2037  24642 /dev/ptym/ptys0
-
-    Here the key is the NAME /dev/ptym/ptys0.  In HP-UX 9.01 tty and
-    pseudo tty devices are paired with the names like /dev/ptym/ptys0
-    and /dev/pty/ttys0, so the following lsof probe is the final step.
-
-    $ lsof /dev/pty/ttys0
-    COMMAND     PID     USER   FD   TYPE       DEVICE   SIZE/OFF  INODE NAME
-    ksh       10215      abe    0u  VCHR  17,0x000030     0t3399  22607 /dev/pty/ttys0
-    ...
-
-    Here's a third example for an AIX 4.1.4 system.  I've used telnet
-    to connect to it from lsof.itap.purdue.edu.  I start with:
-
-    $ lsof -i@lsof.itap.purdue.edu
-    COMMAND     PID     USER   FD   TYPE     DEVICE   SIZE/OFF      INODE NAME
-    ...
-    telnetd   15616     root    0u  inet 0x05a93400     0t5156        TCP cloud.cc.purdue.edu:telnet->lsof.itap.purdue.edu:3369
-
-    Then I look at the telnetd process:
-
-    $ lsof -p15616
-    COMMAND     PID     USER   FD   TYPE     DEVICE   SIZE/OFF      INODE NAME
-    ...
-    telnetd   15616     root    0u  inet 0x05a93400     0t5641        TCP cloud.cc.purdue.edu:telnet->lsof.itap.purdue.edu:3369
-    ...
-    telnetd   15616     root    3u  VCHR    25,   0     0t5493        103 /dev/ptc/0
-
-    Here the key is /dev/ptc/0.  In AIX it's paired with /dev/pts/0.
-    The last probe for that shows:
-
-    $ lsof /dev/pts/0
-    COMMAND     PID     USER   FD   TYPE     DEVICE   SIZE/OFF      INODE NAME
-    ...
-    ksh       16642      abe    0u  VCHR    26,   0     0t6461        360 /dev/pts/0
-
-  b.  The idrlogin.perl[5] Scripts
-  ================================
-
-    There's another, perhaps easier way, to go about the job of
-    tracing a network connection.  The lsof distribution contains
-    two Perl scripts, idrlogin.perl (Perl 4) and idrlogin.perl5
-    (Perl 5), that use lsof field output to display values for
-    shells that are parented by rlogind, sshd, or telnetd, or
-    connected directly to TCP sockets.  The lsof test suite contains
-    a C library that can be adapted for use with C programs that
-    need to call lsof and process its field output.
-
-    The two Perl scripts use the lsof -R option; it causes the
-    paRent process ID (PPID) to be listed in the lsof output.  The
-    scripts identify all shell processes -- e.g., ones whose command
-    names end in ``sh'' -- and determine if: 1) the ultimate ancestor
-    process before a PID greater than 2 (e.g., init's PID is 1) is
-    rlogind, sshd, or telnetd; or 2) the shell process has open
-    TCP socket files.
-
-    Here's an example of output from idlogin.perl on a Solaris 2.4
-    system:
-
-    centurion: 1 = cd src/lsof4/scripts
-    centurion: 2 = ./idrlogin.perl
-    Login    Shell       PID Via           PID TTY        From
-    oboyle   ksh       12640 in.telnetd  12638 pts/5      opal.cc.purdue.edu
-    icdtest  ksh       15158 in.rlogind  15155 pts/6      localhost
-    sh       csh       18207 in.rlogind  18205 pts/1      babylon5.cc.purdue.edu
-    root     csh       18242 in.rlogind  18205 pts/1      babylon5.cc.purdue.edu
-    trouble  ksh       19208 in.rlogind  18205 pts/1      babylon5.cc.purdue.edu
-    abe      ksh       21334 in.rlogind  21332 pts/2      lsof.itap.purdue.edu
-
-    The scripts assume that its parent directory contains an
-    executable lsof.  If you decide to use one of the scripts, you
-    may want to customize it for your local lsof and perl paths.
-
-    Note that processes executing as remote shells are also
-    identified.
-
-    Here's another example from a UnixWare 7.1.0 system.
-
-    tweeker: 1 = cd src/lsof4/scripts
-    tweeker: 9 = ./idrlogin.perl
-    Login    Shell       PID Via           PID TTY        From
-    abe      ksh        9438 in.telnetd   9436 pts/3      lsof.itap.purdue.edu
-
-
-10. Watching an Ftp or Rcp Transfer
-===================================
-
-  The nature of the Internet being one of unpredictable performance
-  at times, occasionally you want to know if a file transfer, being
-  done by ftp or rcp, is making any progress.
-
-  To use lsof for watching a file transfer, you need to know the
-  PID of the file transfer process.  You can use ps to find that.
-  Then use lsof,
-
-  $ lsof -p<PID>
-
-  to examine the files open to the transfer process.  Usually the
-  ftp files or interest are at file descriptors 9 and 10 or 10 and
-  11; for rcp, 3 and 4.  They describe the network socket file and
-  the local data file.
-
-  If you want to watch only those file descriptors as the file
-  transfer progresses, try these lsof forms (for ftp in the example):
-
-    $ lsof -p<PID> -ad9,10 -r
-  or
-    $ lsof -p<PID> -ad10,11 -r
-
-  Some options need explaining:
-
-    -p<PID>	specifies that lsof is to restrict its attention
-		to the process whose ID is <PID>.  You can specify
-		a set of PIDs by separating them with commas.
-
-		    $ lsof -p 1234,5678,9012
-
-    -a		specifies that lsof is to AND its tests together.
-		The two tests that are specified are tests on the
-		PID and tests on file descriptions (``d9,10'').
-
-    d9,10	specifies that lsof is to test only file descriptors
-		9 and 10.  Note that the `-' is absent, since ``-a''
-		is a unary option and can be followed immediately
-		by another lsof option.
-
-    -r          tells lsof to list the requested open file information,
-		sleep for a default 15 seconds, then list the open
-		file information again.  You can specify a different
-		time (in seconds) after -r and override the default.
-		Lsof issues a short line of equal signs between
-		each set of output to distinguish it.
-
-  For an rcp transfer, the above example becomes:
-
-  $ lsof -p<PID> -ad3,4 -r
-
-
-11. Listing Open NFS Files
-==========================
-
-  Lsof will list all files open on remote file systems, supported
-  by an NFS server.  Just use:
-
-  $ lsof -N
-
-  Note, however, that when run on an NFS server, lsof will not list
-  files open to the server from one of its clients.  That's because
-  lsof can only examine the processes running on the machine where
-  it is called -- i.e., on the NFS server.
-
-  If you run lsof on the NFS client, using the -N option, it will
-  list files open by processes on the client that are on remote
-  NFS file systems.
-
-
-12. Listing Files Open by a Specific Login
-==========================================
-
-  If you're interested in knowing what files the processes owned
-  by a particular login name have open, lsof can help.
-
-    $ lsof -u<login>
-  or
-    $ lsof -u<User ID number>
-
-  You can specify either the login name or the UID associated with
-  it.  You can specify multiple login names and UID numbers, mixed
-  together, by separating them with commas.
-
-  $ lsof -u548,abe
-
-  On the subject of login names and UIDs, it's worth noting that
-  lsof can be told to report either.  By default it reports login
-  names; the -l option switches reporting to UIDs.  You might want
-  to use -l if login name lookup is slow for some reason.
-
-  a.  Ignoring a Specific Login
-  =============================
-
-    The -u option can also be used to direct lsof to ignore a
-    specific login name or UID, or a list of them.  Simply prefix
-    the login names or UIDs with a `^' character, as you might do
-    in a regular expression.  The `^' prefix is useful, for example,
-    when you want to have lsof ignore the files open to system
-    processes, owned by the root (UID 0) login.  Try:
-
-      $ lsof -u ^root
-    or
-      $ lsof -u ^0
-
-
-13. Listing Files Open to a Specific Process Group
-==================================================
-
-  There's a Unix collection of processes called a process group.
-  The name indicates that the processes of the group have a common
-  association and are grouped so that a signal sent to one (e.g.,
-  a keyboard kill stroke) is delivered to all.
-
-  This causes Unix to create a two element process group:
-
-  $ lsof | less
-
-  You can use lsof to look at the open files of all members of a
-  process group, if you know the process group ID number.  Assuming
-  that it is 12717 for the above example, this lsof command:
-
-  $ lsof -g12717 -adcwd
-
-  would produce on a Solaris 8 system:
-
-  $ lsof -g12717 -adcwd
-  COMMAND   PID  PGID USER  FD TYPE DEVICE SIZE/OFF    NODE NAME
-  sshd    11369 12717 root cwd VDIR    0,2      189 1449175 /tmp (swap)
-  sshd    12717 12717 root cwd VDIR  136,0     1024       2 /
-
-  The ``-g12717'' option specifies the process group ID of interest;
-  the ``-adcwd'' option specifies that options are to be ANDed and
-  that lsof should limit file output to information about current
-  working directory (``cwd'') files.
-
-
-14. When Lsof Seems to Hang
-===========================
-
-  On occasion when you run lsof it seems to hang and produce no
-  output.  This may result from system conditions beyond the control
-  of lsof.  Lsof has a number of options that may allow you to
-  bypass the blockage.
-
-  a.  Kernel lstat(), readlink(), and stat() Blockages
-  ====================================================
-
-    Lsof uses the kernel (system) calls lstat(), readlink(), and
-    stat() to locate mounted file system information.  When a file
-    system has been mounted from an NFS server and that server is
-    temporarily unavailable, the calls lsof uses may block in the
-    kernel.
-
-    Lsof will announce that it is being blocked with warning messages
-    (unless they have been suppressed by the lsof builder), but
-    only after a default waiting period of fifteen seconds has
-    expired for each file system whose server is unavailable.  If
-    you have a number of such file systems, the total wait may be
-    unacceptably long.
-
-    You can do two things to shorten your suffering: 1) reduce the
-    wait time with the -S option; or 2) tell lsof to avoid the
-    kernel calls that might block by specifying the -b option.
-
-      $ lsof -S 5
-    or
-      $ lsof -b
-
-    Avoiding the kernel calls that might block may result in the
-    lack of some information that lsof needs to know about mounted
-    file systems.  Thus, when you use -b, lsof warns that it might
-    lack important information.
-
-    The warnings that result from using -b (unless suppressed by
-    the lsof builder) can themselves be annoying.  You can suppress
-    them by adding the -w option.  (Of course, if you do, you won't
-    know what warning messages lsof might have issued.)
-
-    $ lsof -bw
-
-    Note: if the lsof builder suppressed warning message issuance,
-    you don't need to use -w to suppress them.  You can tell what
-    the default state of message warning issuance is by looking at
-    the -h (help) output.  If it says ``-w enable warnings'' then
-    warnings are disabled by default; ``-w disable warnings'', they
-    are enabled by default.
-
-  b.  Problems with /dev or /devices
-  ==================================
-
-    Lsof scans the /dev or /devices branch of your file system to
-    obtain information about your system's devices.  (The scan isn't
-    necessary when a device cache file exists.)
-
-    Sometimes that scan can take a very long time, especially if
-    you have a large number of devices, and if your kernel is
-    relatively slow to process the stat() system call on device
-    nodes.  You can't do anything about the stat() system call
-    speed.
-
-    However, you can make sure that lsof is allowed to use its
-    device cache file feature.  When lsof can use a device cache
-    file, it retains information it gleans via the stat() calls
-    on /dev or /devices in a separate file for later, faster
-    access.
-
-    The device cache file feature is described in the lsof man
-    page.  See the DEVICE CACHE FILE, LSOF PERMISSIONS THAT AFFECT
-    DEVICE CACHE FILE ACCESS, DEVICE CACHE FILE PATH FROM THE -D
-    OPTION, DEVICE CACHE PATH FROM AN ENVIRONMENT VARIABLE,
-    SYSTEM-WIDE DEVICE CACHE PATH, PERSONAL DEVICE CACHE PATH
-    (DEFAULT), and MODIFIED PERSONAL DEVICE CACHE PATH sections.
-
-    There is also a separate file in the lsof distribution, named
-    00DCACHE, that describes the device cache file in detail,
-    including information about possible security problems.
-
-    One final observation: don't overlook the possibility that your
-    /dev or /devices tree might be damaged.  See if
-
-      $ ls -R /dev
-    or
-      $ ls -R /devices
-
-    completes or hangs.  If it hangs, then lsof will probably hang,
-    too, and you should try to discover why ls hangs.
-
-    c.  Host and Service Name Lookup Hangs
-    ======================================
-
-    Lsof can hang up when it tries to convert an Internet dot-form
-    address to a host name, or a port number to a service name.  Both
-    hangs are caused by the lookup functions of your system.
-
-    An independent check for both types of hangs can be made with
-    the netstat program.  Run it without arguments.  If it hangs,
-    then it is probably having lookup difficulties.  When you run
-    it with -n it shouldn't hang and should report network and port
-    numbers instead of names.
-
-    Lsof has two options that serve the same purpose as netstat's
-    -n option.  The lsof -n option tells it to avoid host name
-    lookups; and -P, service name lookups.  Try those options when
-    you suspect lsof may be hanging because of lookup problems.
-
-      $ lsof -n
-    or
-      $ lsof -P
-    or
-      $ lsof -nP
-
-    d.  UID to Login Name Conversion Delays
-    =======================================
-
-    By default lsof converts User IDentification (UID) numbers to
-    login names when it produces output.  That conversion process
-    may sometimes hang because of system problems or interlocks.
-
-    You can tell lsof to skip the lookup with the -l option; it
-    will then report UIDs in the USER column.
-
-    $ lsof -l
-
-
-15. Output for Other Programs
-=============================
-
-  The -F option allows you to specify that lsof should describe
-  open files with a special form of output, called field output,
-  that can be parsed easily by a subsequent program.  The lsof
-  distribution comes with sample AWK, Perl 4, and Perl 5 scripts
-  that post-process field output.  The lsof test suite has a C
-  library that could be adapted for use by C programs that want to
-  process lsof field output from an in-bound pipe.
-
-  The lsof manual page describes field output in detail in its
-  OUTPUT FOR OTHER PROGRAMS section.  A quick look at a sample
-  script in the scripts/ subdirectory of the lsof distribution will
-  also give you an idea how field output works.
-
-  The most important thing about field output is that it is relatively
-  homogeneous across Unix dialects.  Thus, if you write a script
-  to post-process field output for AIX, it probably will work for
-  HP-UX, Solaris, and Ultrix as well.
-
-
-16. The Lsof Exit Code and Shell Scripts
-========================================
-
-  When lsof executes successfully, it returns an exit code based on
-  the result of its search for specified files.  (If no files were
-  specified, then the successful exit code is 0 (zero).)
-
-  If lsof was asked to search for specific files, including any
-  files on specified file systems, it returns an exit code of 0
-  (zero) if it found all the specified files and at least one file
-  on each specified file system.  Otherwise it returns a 1 (one) if
-  any part of the search failed.
-
-  This behavior can be modified by calling lsof with -Q, which will
-  tell it to provide a successful exit code of 0 (zero) even if any
-  part of the file or filesystem search failed.
-
-  If lsof detects a generic (non-search) error during its execution,
-  it returns an exit code of 1 (one).  The -Q option will not
-  affect this behavior.
-
-  You can use the exit code in a shell script to search for files
-  on a file system and take action based on the result -- e.g.,
-
-    #!/bin/sh
-    lsof <file_system_name> > /dev/null 2>&1
-    if test $? -eq 0
-    then
-      echo "<file_system_name> has some users."
-    else
-      echo "<file_system_name> may have no users."
-    fi
-
-  The -Q option can help in certain circumstances.  For example, if
-  you want to log filesystem users without caring if there are no
-  users:
-
-    #!/bin/sh
-    lsof -Q <file_system_name>  > fs_users.log
-    if test $? -ne 0
-    then
-      echo "Error: Something actually went wrong!" 1>&2
-      exit 1
-    fi
-
-
-17. Strange messages in the NAME column
-=======================================
-
-  When lsof encounters problems analyzing a particular file, it may
-  put a message in the file's NAME column.  Many of those messages
-  are explained in the 00FAQ file of the lsof distribution.
-
-  So consult 00FAQ first if you encounter a NAME column message you
-  don't understand.  (00FAQ is a possible source of information
-  about other unfamiliar things in lsof output, too.)
-
-  If you can't find help in 00FAQ, you can use grep to look in the
-  lsof source files for the message -- e.g.,
-
-    $ cd .../lsof_4.76_src
-    $ grep "can't identify protocol" *.[ch]
-
-  The code associated with the message will usually make clear the
-  reason for the message.
-
-  If you have an lsof source tree that has been processed by the
-  lsof Configure script, you need grep only there.  If, however,
-  your source tree hasn't been processed by Configure, you may
-  have to look in the top-level lsof source directory and in the
-  dialects sub-directory for the UNIX dialect you are using - e.g.,
-
-    $ cd .../lsof_4.76_src
-    $ grep "can't identify protocol" *.[ch]
-    $ cd dialects/Linux
-    $ grep "can't identify protocol" *.[ch]
-
-  In rare cases you may have to look in the lsof library, too --
-  e.g.,
-
-    $ cd .../lsof_4.76_src
-    $ grep "can't identify protocol" *.[ch]
-    $ cd dialects/Linux
-    $ grep "can't identify protocol" *.[ch]
-    $ cd ../../lib
-    $ grep "can't identify protocol" *.[ch]
-
-
-Options
-=======
-
-  The following appendices describe the lsof options in detail.
-
-
-A.  Selection Options
-====================
-
-  Lsof has a rich set of options for selecting the files to be
-  displayed.  These include:
-
-	-a	tells lsof to AND the set of selection options that
-		are specified.  Normally lsof ORs them.
-
-		For example, if you specify the -p<PID> and -u<UID>
-		options, lsof will display all files for the
-		specified PID or for the specified UID.
-
-		By adding -a, you specify that the listed files
-		should be limited to PIDs owned by the specified
-		UIDs -- i.e., they match the PIDs *and* the UIDs.
-
-		    $ lsof -p1234 -au 5678
-
-	-c	specifies that lsof should list files belonging
-		to processes having the associated command name.
-
-		Hint: if you want to select files based on more than
-		one command name, use multiple -c<name> specifications.
-
-		    $ lsof -clsof -cksh
-
-	-d      tells lsof to select by the associated file descriptor
-		(FD) set.  An FD set is a comma-separated list of
-		numbers and the names lsof normally displays in
-		its FD column:  cwd, Lnn, ltx, <number>, etc.  See
-		the OUTPUT section of the lsof man page for the
-		complete list of possible file descriptors.  Example:
-
-		    $ lsof -dcwd,0,1,2
-
-	-g      tells lsof to select by the associated process
-		group ID (PGID) set.  The PGID set is a comma-separated
-		list of PGID numbers.  When -g is specified, it also
-		enables the display of PGID numbers.
-
-		Note: when -g isn't followed by a PGID set, it
-		simply selects the listing of PGID for all processes.
-		Examples:
-
-		    $ lsof -g
-		    $ lsof -g1234,5678
-
-	-i	tells lsof to display Internet socket files.  If no
-		protocol/address/port specification follows -i,
-		lsof lists all Internet socket files.
-
-		If a specification follows -i, lsof lists only the
-		socket files whose Internet addresses match the
-		specification.
-
-		Hint: multiple addresses may be specified with
-		multiple -i options.  Examples:
-
-		    $ lsof -iTCP
-		    $ lsof -i@lsof.itap.purdue.edu:sendmail
-
-	-N	selects the listing of files mounted on NFS devices.
-
-	-U	selects the listing of socket files in the Unix
-		domain.
-
-
-B.  Output Options
-==================
-
-  Lsof has these options to control its output format:
-
-	-F	produce output that can be parsed by a subsequent
-		program.
-
-	-g	print process group (PGID) IDs.
-
-	-l	list UID numbers instead of login names.
-
-	-n	list network numbers instead of host names.
-
-	-o	always list file offset.
-
-	-P	list port numbers instead of port service names.
-
-	-s	always list file size.
-
-
-C.  Precautionary Options
-=========================
-
-  Lsof uses system functions that can block or take a long time,
-  depending on the health of the Unix dialect supporting it.  These
-  include:
-
-	-b	directs lsof to avoid system functions -- e.g.,
-		lstat(2), readlink(2), stat(2) -- that might block
-		in the kernel.  See the BLOCKS AND TIMEOUTS
-		section of the lsof man page.
-
-		You might want to use this option when you have
-		a mount from an NFS server that is not responding.
-
-	-C	tells lsof to ignore the kernel's name cache.  As
-		a precaution this option will have little effect on
-		lsof performance, but might be useful if the kernel's
-		name cache is scrambled.  (I've never seen that
-		happen.)
-
-	-D	might be used to direct lsof to ignore an existing
-		device cache file and generate a new one from /dev
-		(and /devices).  This might be useful if you have
-		doubts about the integrity of an existing device
-		cache file.
-
-	-l      tells lsof to list UID numbers instead of login
-		names -- this is useful when UID to login name
-		conversion is slow or inoperative.
-
-	-n	tells lsof to avoid converting Internet addresses
-		to host numbers.  This might be useful when your
-		host name lookup (e.g., DNS) is inoperative.
-
-	-O      tells lsof to avoid its strategy of forking to
-		perform potentially blocking kernel operations.
-		While the forking allows lsof to detect that a
-		block has occurred (and possibly break it), the
-		fork operation is a costly one.  Use the -O option
-		with care, lest your lsof be blocked.
-
-	-P      directs lsof to list port numbers instead of trying
-		to convert them to port service names.  This might
-		be useful if port to service name lookups (e.g.,
-		via NIS) are slow or failing.
-
-	-S      can be used to change the lstat/readlink/stat
-		timeout interval that governs how long lsof waits
-		for response from the kernel.  This might be useful
-		when an NFS server is slow or unresponsive.  When
-		lsof times out of a kernel function, it may have
-		less information to display.  Example:
-
-		    $ lsof -S2
-
-	-w	tells lsof to avoid issuing warning messages, if
-		they are enabled by default, or enable them if they
-		are disabled by default.  Check the -h (help) output
-		to determine their status.  If it says ``-w enable
-		warnings'', then warning messages are disabled by
-		default; ``-w disable warnings'', they are enabled
-		by default.
-
-		This may be a useful option, for example, when you
-		specify -b, if warning messages are enabled, because
-		it will suppress the warning messages lsof issues
-		about avoiding functions that might block in the
-		kernel.
-
-
-D.  Miscellaneous Lsof Options
-==============================
-
-  There are some lsof options that are hard to classify, including:
-
-	-?	these options select help output.
-	-h
-
-	-F      selects field output.  Field output is a mode where
-		lsof produces output that can be parsed easily by
-		subsequent programs -- e.g., AWK or Perl scripts.
-		See ``15. Output for Other Programs'' for more
-		information.
-
-	-k	specifies an alternate kernel symbol file -- i.e.,
-		where nlist() will get its information.  Example:
-
-		    $ lsof -k/usr/crash/vmunix.1
-
-	-m	specifies an alternate kernel memory file from
-		which lsof will read kernel structures in place
-		of /dev/kmem or kvm_read().  Example:
-
-		    $ lsof -m/usr/crash/vmcore.n
-
-	-r	tells lsof to repeat its scan every 15 seconds (the
-		default when no associated value is specified).  A
-		repeat time, different from the default, can follow
-		-r.  Example:
-
-		    $ lsof -r30
-
-	-Q	tells lsof not to consider it an error if it was
-		given search terms and any part of the search came
-		up empty. This will silence any reports of missing
-		files to stderr. Additionally, lsof will exit with
-		a non-error code despite any missing files or
-		filesystems with no open files.
-
-	-v	displays information about the building of the
-		lsof executable.
-
-	--      The double minus sign option may be used to
-		signal the end of options.  It's particularly useful
-		when arguments to the last option are optional and
-		you want to supply a file path that could be confused
-		for arguments to the last option.  Example:
-
-		    $ lsof -g -- 1
-
-		Where `1' is a file path, not PGID ID 1.
-
-
-Vic Abell <abe@purdue.edu>
-October 13, 2014
+This documentation has been replaced by docs/tutorial.md, docs/faq.md and docs/options.md. Please refer to the new files or read them online.
\ No newline at end of file
diff --git a/00README b/00README
index 075c764..2b1e6ea 100644
--- a/00README
+++ b/00README
@@ -37,13 +37,11 @@
 	    Apple Darwin
 	    Auspex LFS (no longer maintained)
 	    BSDI BSD/OS
-	    DEC OSF/1, Digital UNIX, Tru64 UNIX
 	    FreeBSD
 	    HP-UX
 	    IPv6
 	    Linux
 	    NetBSD
-	    NEXTSTEP and OPENSTEP
 	    OpenBSD
 	    Pyramid DC/OSx and Reliant UNIX (no longer available)
 	    Caldera OpenUNIX
@@ -176,9 +174,6 @@ the ``osr'' or the ``sco'' abbreviation:
     aix			IBM AIX 5.[23] and 5.3-ML1 using IBM's C Compiler
     aixgcc		IBM AIX 5.[12] and 5.3-ML1 using gcc
     darwin		Apple Darwin 7.x and 8.x for Power Macintosh systems
-    decosf		DEC OSF/1, Digital UNIX, Tru64 UNIX 4.0 and 5.1
-    digital_unix	Digital UNIX, DEC OSF/1, Tru64 UNIX 4.0 and 5.1
-    du			Digital UNIX, DEC OSF/1, Tru64 UNIX 4.0 and 5.1
     freebsd		FreeBSD 4.x, 4.1x, 5.x and [67].x
     hpux		HP-UX 11.00, 11.11 and 11.23, using HP's C
 			Compiler, both /dev/kmem-based and PSTAT-based
@@ -186,13 +181,7 @@ the ``osr'' or the ``sco'' abbreviation:
 			/dev/kmem-based and PSTAT-based
     linux		Linux 2.1.72 and above for x86-based systems
     netbsd		NetBSD 1.[456], 2.x and 3.x
-    next		NEXTSTEP 3.[13]
-    nextstep		NEXTSTEP 3.[13]
-    ns			NEXTSTEP 3.[13]
-    nxt			NEXTSTEP 3.[13]
     openbsd		OpenBSD 2.[89] and 3.[0-9]
-    openstep		OPENSTEP 4.x
-    os			OPENSTEP 4.x
     osr			SCO OpenServer Release 5.0.6, using the C compiler
 			from the SCO developer's kit
     osrgcc		SCO OpenServer Release 5.0.6, using gcc
@@ -202,7 +191,6 @@ the ``osr'' or the ``sco'' abbreviation:
     scogcc		SCO OpenServer Release 5.0.6, using gcc
     solaris		Solaris 2.x, 7, 8, 9 and 10 using gcc
     solariscc		Solaris 2.x, 7, 8, 9 and 10 using Sun's cc
-    tru64		Tru64 UNIX, DEC OSF/1, Digital UNIX 4.0 and 5.1
     unixware		SCO|Caldera UnixWare 7.1.4
     uw			SCO|Caldera UnixWare 7.1.4
 
@@ -574,7 +562,7 @@ compile-time definitions for the dialect's machine.h header file:
 	HASKERNIDCK		the build-time to run-time kernel
 				identity check
 	HASSECURITY		the security option
-	HASNOSOCKSECURITY	the open socket listing option whe
+	HASNOSOCKSECURITY	the open socket listing option when
 				HASSECURITY is defined
 	WARNDEVACCESS		/dev (or /devices) warning message
 				control
@@ -837,8 +825,8 @@ of tests/, with:
 	$ make opt
     or	$ make optional
 
-It's possible to excute individual tests, too.  See the 00TEST file
-of this distribution for more informaiton on the tests, what they
+It's possible to execute individual tests, too.  See the 00TEST file
+of this distribution for more information on the tests, what they
 do, and how to run and possibly customize each test.
 
 It's possible to run the tests, using an lsof other than the one
@@ -859,7 +847,6 @@ dialect and AFS versions:
 
 	AIX 4.1.4 (AFS 3.4a)
 	Linux 1.2.13 (AFS 3.3)
-	NEXTSTEP 3.2 (AFS 3.3) (untested on recent lsof revisions)
 	Solaris 2.6 (AFS 3.4a)
 	Ultrix 4.2 RISC (AFS 3.2b) (no longer available)
 
@@ -981,31 +968,6 @@ discontinued.  Lsof revision 4.76 with BSDI BSD/OS support may be found
 on lsof.itap.purdue.edu in pub/tools/unix/lsof/src.
 
 
-DEC OSF/1, Digital UNIX, Tru64 UNIX
-===================================
-
-Robert Benites, Dean Brock, Angel Li, Dwight McKay, Berkley Shands,
-Ron Young and Steve Wilson have kindly provided test systems.
-Jeffrey Mogul has provided technical assistance.  Dave Morrison
-and Lawrence MacIntyre did Digital UNIX V3.2 testing.
-
-Lsof supports the ADVFS/MSFS layered file system product.  Lsof
-can locate all the open files of an ADVFS/MSFS file system when
-its path is specified, provided the file system is listed in
-/etc/fstab with an ``advfs'' type.  (This /etc/fstab caveat applies
-only to Digital UNIX 2.0.)  At Digital UNIX 4.0 and Tru64 UNIX,
-using code provided by David Brock, lsof 4.20 and above can locate
-ADVFS file paths.
-
-Testing of lsof on DEC OSF/1 and Digital UNIX 4.0 ended with lsof
-revision 4.74.  Hence, the lsof documentation has dropped the claim
-that it works there.  For a distribution of lsof 4.74 that was tested
-on DEC OSF/1 and Digital UNIX 4.0, check pub/tools/unix/lsof/OLD/src
-on the lsof ftp home, lsof.itap.purdue.edu.
-
-Lsof revisions past 4.74 have only been tested on Tru64 UNIX 5.1.
-
-
 FreeBSD
 =======
 
@@ -1107,21 +1069,7 @@ Paul has provided test systems.  Ray Phillips provided a NetBSA
 Alpha test system.  Andrew Brown also provided a test system.
 
 The NetBSD dialect version of lsof is compiled using the dialect
-sources it shares with OpenBSD in the n+obsd dialect sub-directory.
-
-
-NEXTSTEP and OPENSTEP
-=====================
-
-Virtual memory header files that allow lsof to display text references
-were derived from the contents of /usr/include/vm of NEXTSTEP 2.0.
-NeXT did not ship the virtual memory header files with other NEXTSTEP
-or OPENSTEP versions.
-
-You may use the RC_FLAGS environment variable to declare compiler
-options outside the Makefile.  A common use of this variable is to
-define the architecture types to be included in a "fat" executable.
-See the comments in dialects/next/Makefile for an example.
+sources in the netbsd dialect sub-directory.
 
 
 OpenBSD
@@ -1129,7 +1077,7 @@ OpenBSD
 
 David Mazieres has provided OpenBSD test systems.  The OpenBSD
 dialect version of lsof is compiled using the dialect sources it
-shares with NetBSD in the n+obsd dialect sub-directory.
+shares with NetBSD in the openbsd dialect sub-directory.
 
 Kenneth Stailey has provided OpenBSD testing and advice.
 
@@ -1388,7 +1336,7 @@ to read memory devices such as /dev/kmem, /dev/mem, or /dev/swap,
 or it may be authorization to read entries in the /proc file system.
 
 Memory device access can usually be provided by setting the modes
-of the lsof executable so that it's effective group identifier when
+of the lsof executable so that its effective group identifier when
 it runs is the same as the group that has permission to read the
 memory devices -- i.e., it is setgid-group.  The privileged group
 is usually kmem, sys, or system.
@@ -1455,12 +1403,9 @@ grant read permission to the kernel memory devices.
 
 	AIX 4.1.[45], 4.2[.1], and 4.3[.123]
 	Apple Darwin 7.x for Power Macintosh systems
-	DEC OSF/1, Digital UNIX, Tru64 UNIX 2.0, 3.2, 4.0, and 5.[01]
 	FreeBSD 2.1.6, 2.2[.x], 3.x, 4.x, 5.x, [6789].x and 1[012].x
 	NetBSD 1.[456], 2.x and 3.x
-	NEXTSTEP 3.[13]
 	OpenBSD 2.[89] and 3.[0-9]
-	OPENSTEP 4.x
 	Caldera OpenUNIX 8
 	SCO OpenServer 5.0.[46]
 	SCO UnixWare 7.0 and 7.1.[0134]
diff --git a/00TEST b/00TEST
index c465da8..047145d 100644
--- a/00TEST
+++ b/00TEST
@@ -816,7 +816,7 @@ These files may be created by suite tests.
 
     config.LTnlink*	LTnlink	    for link count tests
 
-    config.LTszoff*     LTszoff     for small file size and and
+    config.LTszoff*     LTszoff     for small file size and
 				    offset reporting
 
     config.LT[01]U*     LTunix      two UNIX domain sockets, used
@@ -913,7 +913,6 @@ base, footprints, and the scripts that support them.
 		 10.0 Amd64, clang
 		 11.0 Amd64, clang
 		 12.0 Amd64, clang
-    DEC OSF/1	  4.0, cc
     HP-UX	  10.20, cc			LTbigf
 		  10.20, gcc (1)		LTbigf
 		  11.00-32, ANSI-C		LTbigf, LTnfs
@@ -957,7 +956,6 @@ base, footprints, and the scripts that support them.
 		  3.10.08
 		  4.14.14
 		  3.10.0-229.1.2.el7
-    NEXTSTEP      3.1, gcc                   	LTnfs
     NetBSD        1.4.1, Alpha, gcc          	LTnfs
 		  1.5x, x86, gcc           	LTnfs
 		  1.6x, Alpha, gcc		LTnfs
@@ -979,7 +977,6 @@ base, footprints, and the scripts that support them.
 		  3.6, gcc
 		  3.7, gcc
 		  3.9, gcc
-    OPENSTEP	  4.2, gcc			LTnfs
     OSR           5.04, cc              	LTnfs
 		  5.06, cc              	LTnfs
     Solaris       2.6, cc			LTnfs
@@ -999,9 +996,6 @@ base, footprints, and the scripts that support them.
 		  10-64, Sparc, cc
 		  10-64, Sparc, gcc
 		  11-64, Amd64, cc
-    Tru64 UNIX    5.0, cc
-    Tru64 UNIX    5.0, cc
-		  5.1, cc
     UnixWare      7.1.1, NSC, cc            	LTnfs
 		  7.1.3, cc
 		  7.1.4, cc
diff --git a/00XCONFIG b/00XCONFIG
index a496a5a..ea1f0b6 100644
--- a/00XCONFIG
+++ b/00XCONFIG
@@ -33,7 +33,7 @@ Marty says:
 
 	LINUX_KERNEL=/some/other/kernel LSOF_VERS=2142 ./Configure linux
 
-     Comments?  Its very convenient when running multiple kernels.
+     Comments?  It's very convenient when running multiple kernels.
      (It would be (have been) very handy when the structures changed
      between 2.0.2* and 2.0.30 , or whatever.)
 
@@ -151,7 +151,7 @@ LSOF_HOST       may be used to specify a value in lsof's -v output
 			 hostname or uname -n
 
 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
+		image of 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
@@ -181,7 +181,7 @@ LSOF_LOGNAME    may be used to specify a value in lsof's -v output
 
 LSOF_MAKE	is the path to the make command.
 
-		deafult: the output of `which make`, if it is not NULL;
+		default: the output of `which make`, if it is not NULL;
 			 otherwise the string "make".
 
 LSOF_MKC        may be used to specify an alternate method of
@@ -302,12 +302,6 @@ Abbreviation*	  Prefix	 Number       LSOF_VERS
 				  6.x		    600
 				  7.x		    700
 				  8.x		    800
-	  du	      DU	  2.0		  20000
-				  3.0		  30000
-				  3.2		  30200
-				  4.0		  40000
-				  5.0		  50000
-				  5.1		  50100
      freebsd	 FREEBSD	  1.x		   1000
 				  2.x		   2000
 				  2.0.5		   2005
@@ -341,7 +335,6 @@ Abbreviation*	  Prefix	 Number       LSOF_VERS
 				  2.0		2000000
 				  2.99.9        2099009
 				  2.99.10       2099010
-	 ns     NEXTSTEP	  3.1		     31
     openbsd	 OPENBSD	  1.2		   1020
 				  2.0		   2000
 				  2.1		   2010
@@ -360,7 +353,6 @@ Abbreviation*	  Prefix	 Number       LSOF_VERS
 				  3.4		   3040
 				  3.5		   3050
 				  3.6		   3060
-         os     OPENSTEP	  4.x		     4x
 	osr	     OSR	  3.2v2.0	     20
 				  3.2v2.1	     21
 				  3.2v4.0	     40
@@ -385,9 +377,6 @@ Abbreviation*	  Prefix	 Number       LSOF_VERS
 	 	       		  7.1.1		  70101
 	 	       		  7.1.3		  70103
 
-* -- The optional Configure abbreviations -- e.g., the ``decosf''
-     and ``digital_unix'' alternatives to ``du'' -- aren't listed
-     here.
 
 
 Dialect-Specific Environment Variables
@@ -442,29 +431,6 @@ DARWIN_XNU_HEADERS	If this environment variable has a value, the value is
 
 			default: none
 
-DU_ADVFSV		specifies the DEC OSF/1, Digital UNIX, or Tru64 UNIX
-			ADVFS file system version -- e.g., 200 for 2.0, 400
-			for 4.0, etc.
-
-			default: determined via /usr/sbin/setld
-
-DU_CDIR			specifies the name of the DEC OSF/1, Digital UNIX, or
-			Tru64 UNIX system configuration directory.
-
-			default: first host name component, converted to upper
-				 case
-
-DU_SHLIB		specifies the DEC OSF/1, Digital UNIX, or Tru64 UNIX
-			shared library directory path.
-
-			default: /usr/shlib
-
-DU_SYSDIR		DEC OSF/1, Digital UNIX, or Tru64 UNIX system
-			directory path.
-
-			2.x and 3.x default: /sys
-			4.x default: /usr/sys
-
 FREEBSD_KERNEL		specifies the path to the FreeBSD kernel for FreeBSD
 			version less than 2.0.
 
@@ -561,7 +527,7 @@ LINUX_CONF_CC		specifies the location of the C compiler to use during
 LINUX_HASSELINUX	If this environment variable has a value of "Y" or "y",
 			Configure unconditionally activates SELinux support.
 			If it has any other value, Configure unconditionally
-			inhibits SELinux suport.
+			inhibits SELinux support.
 
 			Default: assumed to be "Y" if <selinux/selinux.h>
 				 exists
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..e69de29
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..279721a
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,26 @@
+Copyright 2002 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.
diff --git a/Configure b/Configure
index 9abcc2d..ec56d4b 100755
--- a/Configure
+++ b/Configure
@@ -238,20 +238,15 @@ Usage: Configure <options> <target-dialect>
   <target-dialect> (****USE -d TO GET TESTED DIALECT VERSION NUMBERS****):
     aix|aixgcc              : IBM AIX xlc (aix) or gcc (aixgcc)
     darwin                  : Apple Darwin
-    decosf                  : DEC OSF/1
-    digital_unix|du         : Digital UNIX
     freebsd                 : FreeBSD
     hpux|hpuxgcc            : HP-UX cc (hpux) or gcc (hpuxgcc)
     linux                   : Linux
     netbsd                  : NetBSD
-    nextstep|next|ns|nxt    : NEXTSTEP
     openbsd                 : OpenBSD
-    openstep|os             : OPENSTEP
-    osr|sco                 : SCO OpenServer < 6.0.0, SCO devloper's compiler
+    osr|sco                 : SCO OpenServer < 6.0.0, SCO developer's compiler
     osrgcc|scogcc           : SCO OpenServer < 6.0.0, gcc compiler
     osr6                    : SCO OpenServer 6.0.0, SCO compiler
     solaris|solariscc       : Solaris gcc (solaris) or cc (solariscc)
-    tru64		    : Tru64 UNIX
     unixware|uw             : SCO|Caldera UnixWare
 LSOF_HLP
 
@@ -295,16 +290,14 @@ do
       echo "rm -f ${LSOF_HLP_BASE}* cd9660_node.h lockf_owner.h fbsd_minor.h"
       rm -f opt_kdtrace.h opt_random.h
       echo "rm -f opt_kdtrace.h opt_random.h"
-      rm -f dialects/aix/aix5/j2/j2_snapshot.h
-      echo "rm -f dialects/aix/aix5/j2/j2_snapshot.h"
+      rm -f lib/dialects/aix/aix5/j2/j2_snapshot.h
+      echo "rm -f lib/dialects/aix/aix5/j2/j2_snapshot.h"
       rm -f dialects/sun/solaris10	# DEBUG -- for s10_44
       echo "rm -f dialects/sun/solaris10"	# DEBUG -- for s10_44
-      rm -f dialects/du/du5_sys_malloc.h
-      echo "rm -f dialects/du/du5_sys_malloc.h"
       rm -f dialects/hpux/kmem/hpux_mount.h
       echo "rm -f dialects/hpux/kmem/hpux_mount.h"
-      rm -rf dialects/n+obsd/include
-      echo "rm -rf dialects/n+obsd/include"
+      rm -rf lib/dialects/netbsd/include
+      echo "rm -rf lib/dialects/netbsd/include"
       rm -f dialects/uw/uw7/vm/swap.h
       echo "rm -f dialects/uw/uw7/vm/swap.h"
       rm -f ${LSOF_LIB}/${LSOF_LIBMKF}
@@ -586,10 +579,10 @@ case $LSOF_TGT in	# {
       # The AIX > 5.0 system has jfs2 support.  Make the necesssary definitions
       # and adjustments.
 
-	rm -f dialects/aix/aix5/j2/j2_snapshot.h
-	(cd dialects/aix/aix5/j2; ln -s private_j2_snapshot.h j2_snapshot.h)
+	rm -f lib/dialects/aix/aix5/j2/j2_snapshot.h
+	(cd lib/dialects/aix/aix5/j2; ln -s private_j2_snapshot.h j2_snapshot.h)
 	LSOF_CFGF="$LSOF_CFGF -DHAS_JFS2"
-	LSOF_CFGF="$LSOF_CFGF -I`pwd`/dialects/aix/aix5"
+	LSOF_CFGF="$LSOF_CFGF -I`pwd`/lib/dialects/aix/aix5"
 	if test $LSOF_VERS -ge 5200	# {
 	then
 	  if test -r ${LSOF_INCLUDE}/j2/j2_snapshot.h	# {
@@ -598,7 +591,7 @@ case $LSOF_TGT in	# {
 	  # The system has its own j2_snapshot.h, so make sure the
 	  # private lsof copy is discarded.
 
-	    rm -f dialects/aix/aix5/j2/j2_snapshot.h
+	    rm -f lib/dialects/aix/aix5/j2/j2_snapshot.h
 	  fi	# }
 	  echo $LSOF_CC | grep gcc > /dev/null
 	  if test $? -eq 0	# {
@@ -681,7 +674,7 @@ case $LSOF_TGT in	# {
 
 	  rm -f ${LSOF_TMPC}.*
 	  echo "#include <sys/systemcfg.h>" > ${LSOF_TMPC}.c
-	  echo 'main(){ if (__KERNEL_32()) printf("32\\n");' >> ${LSOF_TMPC}.c
+	  echo 'int main(){ if (__KERNEL_32()) printf("32\\n");' >> ${LSOF_TMPC}.c
 	  echo 'else if (__KERNEL_64()) printf("64\\n");' >> ${LSOF_TMPC}.c
 	  echo 'else printf("0\\n");' >> ${LSOF_TMPC}.c
 	  echo "return(0); }" >> ${LSOF_TMPC}.c
@@ -778,7 +771,7 @@ case $LSOF_TGT in	# {
 	  rm -f ${LSOF_TMPC}.*
 	  echo "#include <stddef.h>" > ${LSOF_TMPC}.c
 	  echo "#include <sys/user.h>" >> ${LSOF_TMPC}.c
-	  echo "main(){exit((offsetof(struct user, U_irss) & 0x7) ? 1 : 0);}" >>${LSOF_TMPC}.c
+	  echo "int main(){exit((offsetof(struct user, U_irss) & 0x7) ? 1 : 0);}" >>${LSOF_TMPC}.c
 	  echo "Testing user.h with $LSOF_CC"
 	  $LSOF_CC ${LSOF_TMPC}.c -o ${LSOF_TMPC}.x
 	  if ! ${LSOF_TMPC}.x	# {
@@ -811,7 +804,7 @@ case $LSOF_TGT in	# {
       # Get xlc version number
 
       rm -f ${LSOF_TMPC}.*
-      echo "main(){}" > ${LSOF_TMPC}.c
+      echo "int main(){}" > ${LSOF_TMPC}.c
       echo "Getting version number of ${LSOF_CC}."
       $LSOF_CC -c ${LSOF_TMPC}.c -I${LSOF_INCLUDE} -o ${LSOF_TMPC}.o -qlist > /dev/null 2>&1
       LSOF_CCV=`head -1 ${LSOF_TMPC}.lst | sed 's/\(.*\) ---.*/\1/'`
@@ -892,13 +885,31 @@ case $LSOF_TGT in	# {
       12.*)			# Mac OS X 10.8 (Mountain Lion)
  	LSOF_VERS=1200
  	;;
-      13.*)			# Next Mac OS X
+      13.*)			# Mac OS X 10.9 (Mavericks)
 	LSOF_VERS=1300
 	;;
+      14.*)			# Mac OS X 10.10 (Yosemite)
+	LSOF_VERS=1400
+	;;
+      15.*)			# Mac OS X 10.11 (El Capitan)
+	LSOF_VERS=1500
+	;;
+      16.*)			# macOS 10.12 (Sierra)
+	LSOF_VERS=1600
+	;;
+      17.*)			# macOS 10.13 (High Sierra)
+	LSOF_VERS=1700
+	;;
+      18.*)			# macOS 10.14 (Mojave)
+	LSOF_VERS=1800
+	;;
+      19.*)			# macOS 10.15 (Catalina)
+	LSOF_VERS=1900
+	;;
       *)
 	echo Unknown Darwin release: `uname -r`
-	echo Assuming Darwin 12.0
-	LSOF_VERS=1200
+	echo Assuming Darwin 19.0
+	LSOF_VERS=1900
 	;;
       esac	# }
     fi	# }
@@ -937,9 +948,11 @@ case $LSOF_TGT in	# {
 	LSOF_CFGF="$LSOF_CFGF -DNEEDS_MACH_PORT_T"
       fi	# }
       ;;
-    1300)
+    1300|1400|1500|1600|1700|1800|1900)
       LSOF_CFGF="$LSOF_CFGF -DHASIPv6"
       LSOF_TMP1=""
+      LSOF_UNSUP=""
+      LSOF_TSTBIGF=" "			# enable LTbigf test
       ;;
     *)
       echo "Unsupported Darwin version: $LSOF_VERS"
@@ -953,21 +966,6 @@ case $LSOF_TGT in	# {
     LSOF_CFGF="$LSOF_CFGF -mdynamic-no-pic"
     LSOF_CFGL="$LSOF_CFGL -lcurses"
 
-    if test "X$DARWIN_XNUDIR" != "X"	# {
-    then
-      LSOF_TMP2="${DARWIN_XNUDIR}/bsd"
-      LSOF_TMP3="${DARWIN_XNUDIR}/osfmk"
-      LSOF_TMP4=""
-    else
-      LSOF_TMP2="${DARWIN_XNU_HEADERS}/System/Library/Frameworks/Kernel.framework/Versions/A/PrivateHeaders"
-      LSOF_TMP3="${DARWIN_XNU_HEADERS}/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders"
-      LSOF_TMP4=""
-      if test "X$DARWIN_XNU_HEADERS" != "X"	# {
-      then
-	LSOF_TMP4="${DARWIN_XNU_HEADERS}/usr/include"
-      fi	# }
-    fi	# }
-
     # Test Darwin base.
 
     if test "X$DARWIN_BASE" = "X" -o "X$DARWIN_BASE" = "Xlibproc"	# {
@@ -982,34 +980,44 @@ case $LSOF_TGT in	# {
 	  if test -r ${LSOF_INCLUDE}/../local/include/libproc.h	# {
 	  then
 	    DARWIN_BASE="libproc"
-	    LSOF_TMP5="-I${LSOF_INCLUDE}/../local/include"
+	    LSOF_TMP5="${LSOF_INCLUDE}/../local/include"
 	  else
-	    echo "FATAL: can't find libproc.h"
-	    rm -f $LSOF_HLP
-	    exit 1
+	    if test -r /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/libproc.h	# {
+	    then
+	      DARWIN_BASE="libproc"
+	      LSOF_TMP5="/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/"
+            else
+              echo "FATAL: can't find libproc.h"
+              rm -f $LSOF_HLP
+              exit 1
+            fi
 	  fi	# }
 	fi	# }
       else
 
-      # The default Darwin base is /dev/kmem.
+        # The default Darwin base is libproc
 
-	DARWIN_BASE="/dev/kmem"
+	DARWIN_BASE="libproc"
       fi	# }
     fi	# }
+
     if test "X$DARWIN_BASE" = "Xlibproc"	# {
     then
 
-    # Configure for libproc-based Darwin lsof.
+      # Configure for libproc-based Darwin lsof.
 
       echo "Configuring libproc-based Darwin lsof"
       LSOF_CINFO="libproc-based"
-      LSOF_DIALECT_DIR=darwin/libproc
+      LSOF_DIALECT_DIR=darwin
       if test $LSOF_VERS -lt 1000 	# {
       then
 	LSOF_CFGL="$LSOF_CFGL -lproc"
       fi	# }
       LSOF_TSTKMEM=0
-      LSOF_DINC="$LSOF_DINC $LSOF_TMP5"
+      if test "X$LSOF_TMP5" != "X"  # {
+      then
+	LSOF_DINC="$LSOF_DINC -I$LSOF_TMP5"
+      fi  # }
       if test ! -r ${LSOF_INCLUDE}/sys/proc_info.h	# {
       then
 	if test "X$LSOF_TMP5" = "X" -o ! -r ${LSOF_TMP5}/sys/proc_info.h # {
@@ -1036,373 +1044,16 @@ case $LSOF_TGT in	# {
       then
 	LSOF_CFGF="$LSOF_CFGF -DHASUTMPX"
       fi	# }
-    else
-      if test "X$DARWIN_BASE" != "X/dev/kmem"	# {
-      then
-	echo "Darwin base unrecognized: $DARWIN_BASE"
-	rm -f $LSOF_HLP
-	exit 1
-      fi	# }
-
-    # Configure for /dev/kmem-based Darwin lsof.
-
-      echo "Configuring /dev/kmem-based Darwin lsof"
-      LSOF_CINFO="/dev/kmem-based"
-      LSOF_DIALECT_DIR=darwin/kmem
-
-    # Make sure needed /dev/kmem-base XNU Darwin kernel header files are
-    # present.
-
-      LSOF_TMP5=""
-      for i in $LSOF_TMP1	# {
-      do
-	LSOF_TMP6=0
-	for j in $LSOF_TMP2 $LSOF_TMP3 $LSOF_TMP4 $LSOF_INCLUDE	# {
-	do
-	  if test "X${j}" != "X" -a -r ${j}/${i}  # {
-	  then
-	    LSOF_TMP6=1
-	    break
-	  fi	# }
-	done	# }
-	if test $LSOF_TMP6 -ne 1	# {
-	then
-	  if test "X$LSOF_TMP5" = "X"	# {
-	  then
-	    LSOF_TMP5=$i
-	  else
-	    LSOF_TMP5="$LSOF_TMP5 $i"
-	  fi	# }
-	fi			# }
-      done	# }
-      if test "X$LSOF_TMP5" != "X"	# {
-      then
-
-      # If any Darwin XNU kernel header files are missing, call the
-      # get-hdr-loc.sh script to find the path.
-
-	LSOF_TMP6=`pwd`/dialects/darwin/get-hdr-loc.sh
-	if test ! -x $LSOF_TMP6	# {
-	then
-	  echo "FATAL: can't execute: $LSOF_TMP6"
-	  rm -f $LSOF_HLP
-	  exit 1
-	fi	# }
-	DARWIN_XNUDIR=`$LSOF_TMP6 $LSOF_TMP5`
-	if test $? -ne 0	# {
-	then
-	  echo "FATAL: $LSOF_TMP6 returns: $DARWIN_XNUDIR"
-	  rm -f $LSOF_HLP
-	  exit 1
-	fi	# }
-	LSOF_TMP2="${DARWIN_XNUDIR}/bsd"
-	LSOF_TMP3="${DARWIN_XNUDIR}/osfmk"
-	LSOF_TMP4=""
-      fi	# }
-
-    # Add header file paths for /dev/kmem-based Darwin lsof.
-
-      for i in $LSOF_TMP2 $LSOF_TMP3 $LSOF_TMP4 $LSOF_INCLUDE	# {
-      do
-	if test -d $i -a "X$i" != "X/usr/include"	# {
-	then
-	  LSOF_DINC="$LSOF_DINC -I${i}"
-	fi	# }
-      done	# }
-
-    # Make conditional feature definitions for /dev/kmem-based Darwin lsof.
-
-      for i in $LSOF_TMP2 $LSOF_TMP3 $LSOF_TMP4 $LSOF_INCLUDE      # {
-      do
-	if test "X${i}" != "X" -a -r ${i}/sys/namei.h	# {
-	then
-	  grep -q nc_vpid ${i}/sys/namei.h
-	  if test $? -eq 0	# {
-	  then
-	    LSOF_CFGF="$LSOF_CFGF -DHASNCVPID"
-	  fi	# }
-	  break
-	fi	# }
-      done	# }
-      for i in $LSOF_TMP2 $LSOF_TMP3 $LSOF_TMP4 $LSOF_INCLUDE	# {
-      do
-	if test "X${i}" != "X"	# {
-	then
-	  if test $LSOF_VERS -ge 800	# {
-	  then
-	    if test -r ${i}/sys/file_internal.h	# {
-	    then
-	      grep -q DTYPE_KQUEUE ${i}/sys/file_internal.h
-	      if test $? -eq 0	# {
-	      then
-	        LSOF_CFGF="$LSOF_CFGF -DHASKQUEUE"
-	      fi	# }
-	      break
-	    fi	# }
-	  else
-	    if test $LSOF_VERS -ge 700	# {
-	    then
-	      if test -r ${i}/sys/file.h	# {
-	      then
-	        grep -q DTYPE_KQUEUE ${i}/sys/file.h
-	        if test $? -eq 0	# {
-	        then
-	          LSOF_CFGF="$LSOF_CFGF -DHASKQUEUE"
-	        fi	# }
-	      fi	# }
-	      break
-	    fi	# }
-	  fi	# }
-	fi	# }
-      done	# }
-      LSOF_CFGF="$LSOF_CFGF -DHAS9660FS"
     fi	# }
     LSOF_CFGF="$LSOF_CFGF -DDARWINV=$LSOF_VERS"
     LSOF_CFLAGS_OVERRIDE=1
     ;;
 
-# Configure for DEC OSF/1, Digital UNIX, or Tru64 UNIX.
-
-  digital_unix|du|decosf|tru64)
-    LSOF_TGT="du"
-    LSOF_TSTBIGF=" "
-    LSOF_TSTK64=1
-    if test "X$LSOF_DINC" = "X"	# {
-    then
-      LSOF_DINC="-I/usr/include"
-    fi	# }
-    if test "X$LSOF_VSTR" = "X"	# {
-    then
-      LSOF_VSTR=`uname -r`
-    fi	# }
-    if test "X$LSOF_VERS" = "X"	# {
-    then
-
-      # If the DEC OSF/1, Digital UNIX, or Tru64 UNIX version isn't
-      # predefined, determine it.
-
-      case $LSOF_VSTR in	# {
-      V2.0)
-	LSOF_VERS=20000
-	;;
-      V3.0)
-	LSOF_VERS=30000
-	;;
-      V3.2)
-	LSOF_VERS=30200
-	;;
-      ?4.0)
-	LSOF_TSTXO="../lib/snpf.o"
-	LSOF_VERS=40000
-	;;
-      ?5.0)
-	LSOF_VERS=50000
-	;;
-      ?5.1)
-	LSOF_VERS=50100
-	;;
-      *)
-	echo "WARNING: unknown version; assuming version is 2.0"
-	LSOF_VERS=20000
-	;;
-      esac	# }
-    fi	# }
-
-    # Do DEC OSF/1, Digital UNIX, or Tru64 UNIX version specific stuff.
-
-    case $LSOF_VERS in	# {
-      20000)
-	LSOF_CFGF="$LSOF_CFGF -Olimit 1024"
-	LSOF_TMP1="/sys"
-	;;
-      30000)
-	LSOF_CFGF="$LSOF_CFGF -Olimit 1024"
-	LSOF_TMP1="/sys"
-	LSOF_TMP2=-DUSELOCALREADDIR
-	;;
-      30200)
-	LSOF_CFGF="$LSOF_CFGF -Olimit 1024"
-	LSOF_TMP1="/sys"
-	LSOF_TMP2=-DUSELOCALREADDIR
-	;;
-      40000)
-	LSOF_TMP1="/usr/sys"
-	;;
-      50000|50100)
-	LSOF_CFGF="$LSOF_CFGF -DUSE_STAT"
-	LSOF_TMP1="/usr/sys"
-	;;
-      *)
-	echo "WARNING: unknown version: $LSOF_VERS"
-	rm -f $LSOF_HLP
-	exit 1
-	;;
-    esac	# }
-    if test "X$DU_SYSDIR" = "X"	# {
-    then
-      DU_SYSDIR=$LSOF_TMP1
-    fi	# }
-    LSOF_HOST=`uname -n`
-    if test "X$DU_CDIR" = "X"	# {
-    then
-      LSOF_CDIR=`expr $LSOF_HOST : '\([^\.]*\)\..*$'`
-      if test "X$LSOF_CDIR" = "X"	# {
-      then
-	LSOF_CDIR=$LSOF_HOST
-      fi	# }
-      LSOF_CDIR=`echo $LSOF_CDIR | tr a-z A-Z`
-    else
-      LSOF_CDIR=$DU_CDIR
-    fi	# }
-    LSOF_LOOP=1
-    while test $LSOF_LOOP = 1	# {
-    do
-      if test -d ${DU_SYSDIR}/$LSOF_CDIR	# {
-      then
-	echo "Using header files in ${DU_SYSDIR}/$LSOF_CDIR"
-	LSOF_LOOP=0
-      else
-	cat << .CAT_MARK
-
-Please enter the name of the subdirectory in $DU_SYSDIR that contains the
-configuration files for this host.  Usually its name would be $LSOF_CDIR, but
-that subdirectory doesn't seem to exist.  The lsof compilation needs header
-files specific to this machine's configuration found in that directory.
-
-If you can't specify the appropriate configuration subdirectory, quit this
-Configure step now and generate a proper configuration subdirectory with the
-kernel generation process.
-
-.CAT_MARK
-
-	echo "$DU_SYSDIR contains:"
-	echo ""
-	ls -CF $DU_SYSDIR
-	echo ""
-	echo -n "Configuration subdirectory name? "
-	read LSOF_CDIR LSOF_EXCESS
-	if test "X$LSOF_CDIR" = "X" -o ! -d ${DU_SYSDIR}/$LSOF_CDIR	# {
-	then
-	  echo ""
-	  echo Cannot access directory ${DU_SYSDIR}/$LSOF_CDIR.
-	fi	# }
-      fi	# }
-    done	# }
-
-    # Determine the ADVFS file system version.
-
-    if test "X$DU_ADVFSV" = "X"	# {
-    then
-      echo "Determining the ADVFS version -- this will take a while."
-      LSOF_ADVFSV=`/usr/sbin/setld -i | grep "^OSFADVFSBIN[0-9]" | sed 's/\([^ ]*\).*/\1/' | sort -u | tail -1 | sed 's/OSFADVFSBIN//'`
-    else
-      LSOF_ADVFSV=$DU_ADVFSV
-    fi	# }
-    case $LSOF_ADVFSV in	# {
-    1*)
-      LSOF_ADVFSV=100
-      echo "The ADVFS version is 1."
-      ;;
-    2*)
-      LSOF_ADVFSV=200
-      echo "The ADVFS version is 2."
-      ;;
-    3*)
-      LSOF_ADVFSV=300
-      echo "The ADVFS version is 3."
-      ;;
-    4*)
-      LSOF_ADVFSV=400
-      echo "The ADVFS version is 4."
-      ;;
-    5*)
-      LSOF_ADVFSV=500
-      echo "The ADVFS version is 5."
-      ;;
-    *)
-      echo "The ADVFS version is unknown; it will be assumed to be 1."
-      LSOF_ADVFSV=100
-      ;;
-    esac	# }
-    LSOF_CFGF="$LSOF_CFGF -DDUV=$LSOF_VERS -DADVFSV=$LSOF_ADVFSV $LSOF_TMP2"
-    if test "X$DU_SYSINC" = "X"	# {
-    then
-      DU_SYSINC="/usr/sys/include"
-    fi	# }
-    LSOF_DINC="$LSOF_DINC -I${DU_SYSDIR}/$LSOF_CDIR -I$DU_SYSINC"
-    LSOF_CFGL="$LSOF_CFGL -lmld"
-    if test "X${DU_SHLIB}" = "X"	# {
-    then
-      DU_SHLIB=/usr/shlib
-    fi	# }
-    if test -r ${DU_SHLIB}/libmsfs.so	# {
-    then
-      nm ${DU_SHLIB}/libmsfs.so | grep tag_to_path > /dev/null 2>&1
-      if test $? -eq 0	# {
-      then
-	LSOF_CFGF="$LSOF_CFGF -DHASTAGTOPATH"
-	LSOF_CFGL="$LSOF_CFGL -lmsfs"
-      fi	# }
-    fi	# }
-    grep "^struct spec_node {" ${DU_SYSDIR}/include/sys/specdev.h > /dev/null 2>&1
-    if test $? -eq 0	# {
-    then
-      LSOF_CFGF="$LSOF_CFGF -DHASSPECNODE"
-    fi	# }
-    if test $LSOF_VERS -ge 50000	# {
-    then
-
-    # Make du5_sys_malloc.h for DU 5.0 and above.  Enable strict ANSI checking
-    # on 5.0 and 5.1A, but not 5.1B.  Enable IPv6 handling.
-
-      LSOF_TMP1="-std1"
-      if test $LSOF_VERS -ge 50100	# {
-      then
-	LSOF_TMP1="-std"
-	if test -x /usr/sbin/sizer	# {
-	then
-	  /usr/sbin/sizer -v | grep -q 5.1A
-	  if test $? -eq 0	# {
-	  then
-	    LSOF_TMP1="-std1"
-	  fi	# }
-	fi	# }
-      fi	# }
-      LSOF_CFGF="$LSOF_CFGF $LSOF_TMP1"
-      LSOF_TMP1=${LSOF_INCLUDE}/sys/malloc.h
-      if test -r $LSOF_TMP1	# {
-      then
-	LSOF_TMP2=dialects/du/du5_sys_malloc.h
-	rm -f $LSOF_TMP2
-	echo "#if !defined(MANUFACTURED_DU5_SYS_MALLOC_H)" > $LSOF_TMP2
-	echo "/* By lsof Configure:" `date` " */" >> $LSOF_TMP2
-	echo "#define MANUFACTURED_DU5_SYS_MALLOC_H" >> $LSOF_TMP2
-	grep "^#define[ 	]MALLOC_NUM_BUCKETS" $LSOF_TMP1 >> $LSOF_TMP2
-	echo "struct percpukmembuckets {" >> $LSOF_TMP2
-	sed '1,/^struct percpukmembuckets/d' $LSOF_TMP1 | sed -n '1,/^};/p' >> $LSOF_TMP2
-	echo "#endif" >> $LSOF_TMP2
-	LSOF_CFGF="$LSOF_CFGF -I`pwd`/dialects/du"
-      fi	# }
-
-    # Enable IPv6 for Tru64 UNIX 5.0 and above.
-
-      LSOF_CFGF="$LSOF_CFGF -DHASIPv6"
-    fi	# }
-    if test -r ${LSOF_INCLUDE}/sys/namei.h
-    then
-      grep -q nc_vpid ${LSOF_INCLUDE}/sys/namei.h
-      if test $? -eq 0	# {
-      then
-	LSOF_CFGF="$LSOF_CFGF -DHASNCVPID"
-      fi	# }
-    fi	# }
-    LSOF_DIALECT_DIR=du
-    ;;
-
 # Configure for FreeBSD.
 
   freebsd)
     LSOF_FBSD_ZFS=0
+    LSOF_TSTKMEM=0
     if test "X$LSOF_CC" = "X"	# {
     then
       LSOF_CC=cc
@@ -1418,129 +1069,26 @@ kernel generation process.
     # If the FreeBSD version isn't pre-defined, determine it.
 
       case $LSOF_VSTR in	# {
-      5.0*)
-	LSOF_TSTBIGF=" "
-	LSOF_VERS=5000
-	;;
-      5.1*)
-	LSOF_TSTBIGF=" "
-	LSOF_VERS=5010
-	;;
-      5.2*)
-	LSOF_TSTBIGF=" "
-	LSOF_VERS=5020
-	;;
-      5.3*)
-	LSOF_TSTBIGF=" "
-	LSOF_VERS=5030
-	;;
-      5.4*)
-	LSOF_TSTBIGF=" "
-	LSOF_VERS=5040
-	;;
-      5.5*)
-	LSOF_TSTBIGF=" "
-	LSOF_VERS=5050
-	;;
-      5*)
-	LSOF_VERS=5050
-	echo "!!!WARNING!!!  Unsupported FreeBSD version: $LSOF_VSTR"
-	echo "!!!WARNING!!!  Configuring for FreeBSD 5.5"
-	;;
-      6.0*)
-	LSOF_TSTBIGF=" "
-	LSOF_VERS=6000
-	;;
-      6.1*)
-	LSOF_TSTBIGF=" "
-	LSOF_VERS=6010
-	;;
-      6.2*)
-	LSOF_TSTBIGF=" "
-	LSOF_VERS=6020
-	;;
-      6.3*)
-	LSOF_TSTBIGF=" "
-	LSOF_VERS=6030
-	;;
-      6.4*)
-	LSOF_TSTBIGF=" "
-	LSOF_VERS=6040
-	;;
-      6*)
-	LSOF_VERS=6000
-	echo "!!!WARNING!!!  Unsupported FreeBSD version: $LSOF_VSTR"
-	echo "!!!WARNING!!!  Configuring for FreeBSD 6.0"
-	;;
-      7.0*)
-	LSOF_TSTBIGF=" "
-	LSOF_VERS=7000
-	;;
-      7.1*)
-	LSOF_TSTBIGF=" "
-	LSOF_VERS=7010
-	;;
-      7.2*)
-	LSOF_TSTBIGF=" "
-	LSOF_VERS=7020
-	;;
-      7.3*)
-	LSOF_TSTBIGF=" "
-	LSOF_VERS=7030
-	;;
-      7.4*)
-	LSOF_TSTBIGF=" "
-	LSOF_VERS=7040
-	;;
-      7*)
-	LSOF_VERS=7000
-	echo "!!!WARNING!!!  Unsupported FreeBSD version: $LSOF_VSTR"
-	echo "!!!WARNING!!!  Configuring for FreeBSD 7.0"
-	;;
-      8.0*)
-	LSOF_TSTBIGF=" "
-	LSOF_VERS=8000
-	;;
-      8.1*)
-	LSOF_TSTBIGF=" "
-	LSOF_VERS=8010
-	;;
-      8.2*)
-	LSOF_TSTBIGF=" "
-	LSOF_VERS=8020
-	;;
-      8.3*)
-	LSOF_TSTBIGF=" "
-	LSOF_VERS=8030
-	;;
-      8.4*)
-	LSOF_TSTBIGF=" "
-	LSOF_VERS=8040
-	;;
-      9*)
-	LSOF_TSTBIGF=" "
-	LSOF_VERS=9000
-	;;
-      10*)
-	LSOF_TSTBIGF=" "
-	LSOF_VERS=10000
-	;;
-      11*)
-	LSOF_TSTBIGF=" "
-	LSOF_VERS=11000
-	;;
       12*)
+	LSOF_CFGL="$LSOF_CFGL -lutil"
 	LSOF_TSTBIGF=" "
 	LSOF_VERS=12000
 	;;
       13*)
+	LSOF_CFGL="$LSOF_CFGL -lutil"
 	LSOF_TSTBIGF=" "
 	LSOF_VERS=13000
 	;;
       14*)
+	LSOF_CFGL="$LSOF_CFGL -lutil"
 	LSOF_TSTBIGF=" "
 	LSOF_VERS=14000
 	;;
+      15*)
+	LSOF_CFGL="$LSOF_CFGL -lutil"
+	LSOF_TSTBIGF=" "
+	LSOF_VERS=15000
+	;;
       *)
 	echo Unknown FreeBSD release: `uname -r`
 	rm -f $LSOF_HLP
@@ -1552,7 +1100,7 @@ kernel generation process.
     # Clear LSOF_UNSUP message for supported versions of FreeBSD.
 
     case $LSOF_VERS in  # {
-    4090|8020|8030|8040|9000|10000|11000|12000|13000|14000)
+    12000|13000|14000)
       LSOF_UNSUP=""
       ;;
     esac	# }
@@ -1617,38 +1165,15 @@ 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	# }
-
-    # Check the C library for closefrom and dup2.
-
-      if test -r /usr/lib/libc.a	# {
-      then
-	nm /usr/lib/libc.a | grep -q "W dup2"
-	if test $? -eq 0	# {
-	then
-	  LSOF_CFGF="$LSOF_CFGF -DHAS_DUP2"
-	fi	# }
-	nm /usr/lib/libc.a | grep -q "W closefrom"
-	if test $? -eq 0	# {
-	then
-	  LSOF_CFGF="$LSOF_CFGF -DHAS_CLOSEFROM"
-	fi	# }
-      fi	# }
+    # All supported FreeBSD releases have closefrom and dup2.
+    LSOF_CFGF="$LSOF_CFGF -DHAS_DUP2"
+    LSOF_CFGF="$LSOF_CFGF -DHAS_CLOSEFROM"
 
     # Do FreeBSD version-specific stuff.
 
     case $LSOF_VERS in	# {
     1000)
-      LSOF_CFGF="$LSOF_CFGF -DHASPROCFS"
+      LSOF_CFGF="$LSOF_CFGF"
       LSOF_CFGL="$LSOF_CFGL -lutil"
       LSOF_DINC="$LSOF_DINC -I`pwd`/dialects/freebsd/include"
       if test "X$FREEBSD_KERNEL" = "X"	# {
@@ -1763,7 +1288,7 @@ kernel generation process.
 	  cat > ${LSOF_TMPC}.c << .LSOF_END_HERE_DOC3
 #undef _KERNEL
 #include <sys/types.h>
-main() {
+int main() {
 cpumask_t c;
 }
 .LSOF_END_HERE_DOC3
@@ -1843,11 +1368,6 @@ cpumask_t c;
 	    then
 	      LSOF_CFGF="$LSOF_CFGF -DHAS_UFS1_2"
 	    fi	# }
-	    grep -q i_dev ${LSOF_INCLUDE}/ufs/ufs/inode.h
-	    if test $? -ne 0	# {
-	    then
-	      LSOF_CFGF="$LSOF_CFGF -DHAS_NO_IDEV"
-	    fi	# }
 	  fi	# }
 	  if test -r ${LSOF_INCLUDE}/sys/conf.h	# {
 	  then
@@ -1902,11 +1422,6 @@ FBSD_MINOR3
 		fi	# }
 	      fi	# }
 	    fi	# }
-	    grep -q "si_udev;" ${LSOF_INCLUDE}/sys/conf.h
-	    if test $? -ne 0	# {
-	    then
-	      LSOF_CFGF="$LSOF_CFGF -DHAS_NO_SI_UDEV"
-	    fi	# }
 	    grep -q si_priv ${LSOF_INCLUDE}/sys/conf.h
 	    if test $? -eq 0	# {
 	    then
@@ -1918,12 +1433,6 @@ FBSD_MINOR3
 	    LSOF_CFGF="$LSOF_CFGF -DHAS_SYS_SX_H"
 	  fi	# }
 
-	# Do FUSE file system test,
-
-	  if test -r ${FREEBSD_SYS}/fs/fuse/fuse_node.h	# {
-	  then
-	    LSOF_CFGF="$LSOF_CFGF -DHASFUSEFS"
-	  fi	# }
 	# Do msdosfs test.
 	  if test -r ${FREEBSD_SYS}/fs/msdosfs/denode.h # {
 	  then
@@ -2106,14 +1615,6 @@ LOCKF_OWNER4
 		LSOF_CFGF="$LSOF_CFGF -DHAS_SB_CCC"
 	      fi	# }
 	    fi	# }
-	    if test -r ${LSOF_INCLUDE}/sys/filedesc.h	# {
-	    then
-	      grep -q '^struct fdescenttbl {' ${LSOF_INCLUDE}/sys/filedesc.h
-	      if test $? -eq 0	# {
-	      then
-		LSOF_CFGF="$LSOF_CFGF -DHAS_FDESCENTTBL"
-	      fi	# }
-	    fi	# }
 	  fi	# }
 	fi	# }
       fi	# }
@@ -2195,19 +1696,11 @@ LOCKF_OWNER4
     else
       LSOF_TMP1="miscfs"
     fi	# }
-    if test $LSOF_VERS -lt 5000	# {
-      then
-      if test -d ${FREEBSD_SYS}/${LSOF_TMP1}/procfs	# {
-      then
-	LSOF_CFGF="$LSOF_CFGF -DHASPROCFS"
-	LSOF_DINC_ADD=1
-      fi	# }
-    else
-      if test -d ${FREEBSD_SYS}/${LSOF_TMP1}/pseudofs	# {
-      then
-	LSOF_CFGF="$LSOF_CFGF -DHASPSEUDOFS"
-	LSOF_DINC_ADD=1
-      fi	# }
+    LSOF_CFGF="$LSOF_CFGF -DHASPROCFS"
+    if test -d ${FREEBSD_SYS}/${LSOF_TMP1}/pseudofs	# {
+    then
+      LSOF_CFGF="$LSOF_CFGF -DHASPSEUDOFS"
+      LSOF_DINC_ADD=1
     fi	# }
     if test -r ${LSOF_INCLUDE}/${LSOF_TMP1}/nullfs/null.h	# {
     then
@@ -2242,14 +1735,6 @@ LOCKF_OWNER4
 	echo "" >> cd9660_node.h
       fi	# }
       LSOF_CFGF="$LSOF_CFGF -DHAS9660FS"
-      if test $LSOF_VERS -ge 6000	# {
-      then
-	grep -q "i_dev;" cd9660_node.h
-	if test $? -ne 0	# {
-	then
-	  LSOF_CFGF="$LSOF_CFGF -DHAS_NO_ISO_DEV"
-	fi	# }
-      fi	# }
     fi	# }
     if test -r ${LSOF_INCLUDE}/sys/namei.h
     then
@@ -2285,6 +1770,43 @@ LOCKF_OWNER4
     then
       LSOF_CFGF="$LSOF_CFGF -DHASUTMPX"
     fi	# }
+
+    # Does struct xtcpcb have t_maxseg?
+    rm -f ${LSOF_TMPC}.*
+    cat > ${LSOF_TMPC}.c << .LSOF_END_HERE_DOC4
+#undef _KERNEL
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/socketvar.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/in_pcb.h>
+#include <netinet/tcp_var.h>
+int main() {
+struct xtcpcb pcb; pcb.t_maxseg = 0;
+}
+.LSOF_END_HERE_DOC4
+    $LSOF_CC ${LSOF_TMPC}.c -o ${LSOF_TMPC}.x > /dev/null 2>&1
+    if test $? -eq 0	# {
+    then
+      LSOF_CFGF="$LSOF_CFGF -DHAS_XTCPCB_TMAXSEG"
+    fi	# }
+    rm -f ${LSOF_TMPC}.*
+
+    # Does struct kinfo_file have kf_un.kf_sock.kf_sock_sendq?
+    grep -q kf_sock_sendq ${LSOF_INCLUDE}/sys/user.h
+    if test $? -eq 0	# {
+    then
+      LSOF_CFGF="$LSOF_CFGF -DHAS_KF_SOCK_SENDQ"
+    fi	# }
+
+    # Does struct kinfo_file have kf_un.kf_file.kf_file_nlink?
+    grep -q kf_file_nlink ${LSOF_INCLUDE}/sys/user.h
+    if test $? -eq 0	# {
+    then
+      LSOF_CFGF="$LSOF_CFGF -DHAS_KF_FILE_NLINK"
+    fi	# }
+
     LSOF_DIALECT_DIR=freebsd
     ;;
 
@@ -2380,7 +1902,7 @@ LOCKF_OWNER4
     # Test for "const void" support.
 
     rm -f ${LSOF_TMPC}.*
-    echo "main() { const void *x; return(0); }" >> $LSOF_TMPC.c
+    echo "int main() { const void *x; return(0); }" >> $LSOF_TMPC.c
     $LSOF_CC $LSOF_TMPC.c -o $LSOF_TMPC.x > /dev/null 2>&1
     if test $? -eq 0	# {
     then
@@ -2512,7 +2034,7 @@ LOCKF_OWNER4
 	      echo ""
 	      echo "Testing $LSOF_CC for 64 bit support"
 	      rm -f ${LSOF_TMPC}.*
-	      echo "main(){}" > ${LSOF_TMPC}.c
+	      echo "int main(){}" > ${LSOF_TMPC}.c
 	      LSOF_TMP1=""
 	      $LSOF_CC ${LSOF_TMPC}.c -o ${LSOF_TMPC}.x > /dev/null 2>&1
 	      if test $? -eq 0	# {
@@ -2833,7 +2355,8 @@ LOCKF_OWNER4
       rm -f ${LSOF_TMPC}.*
       cat > $LSOF_TMPC.c << .LSOF_END_HERE_DOC1
 #include <features.h>
-main() {
+#include <stdio.h>
+int main() {
 #if defined(__GLIBC__) && defined(__GLIBC_MINOR__)
 printf("-DGLIBCV=%d\n",__GLIBC__*100+__GLIBC_MINOR__);
 #elif defined(__GLIBC__)
@@ -2953,6 +2476,23 @@ return(0); }
       fi	# }
     fi	# }
 
+  # Test for dup2 and closefrom
+
+    if test -f ${LSOF_INCLUDE}/unistd.h # {
+    then
+      grep -q dup2 ${LSOF_INCLUDE}/unistd.h
+      if test $? -eq 0 # {
+      then
+        LSOF_CFGF="$LSOF_CFGF -DHAS_DUP2"
+      fi	# }
+
+      grep -q closefrom ${LSOF_INCLUDE}/unistd.h
+      if test $? -eq 0 # {
+      then
+        LSOF_CFGF="$LSOF_CFGF -DHAS_CLOSEFROM"
+      fi	# }
+    fi	# }
+
     LSOF_DIALECT_DIR="linux"
     LSOF_CFGF="$LSOF_CFGF -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE"
     ;;
@@ -2992,7 +2532,7 @@ return(0); }
 	LSOF_TSTBIGF=" "
 	LSOF_VERS="1006000"
 	;;
-      1*)
+      1.*)
 	LSOF_VERS="1006000"
 	echo "!!!WARNING!!!  Unsupported NetBSD version: $LSOF_VSTR"
 	echo "!!!WARNING!!!  Configuring for NetBSD 1.6"
@@ -3013,7 +2553,7 @@ return(0); }
 	LSOF_TSTBIGF=" "
 	LSOF_VERS="2099010"
 	;;
-      2*)
+      2.*)
 	LSOF_VERS="2000000"
 	echo "!!!WARNING!!!  Unsupported NetBSD version: $LSOF_VSTR"
 	echo "!!!WARNING!!!  Configuring for NetBSD 2.0"
@@ -3026,37 +2566,122 @@ return(0); }
 	LSOF_TSTBIGF=" "
 	LSOF_VERS="3099000"
 	;;
-      3*)
+      3.*)
 	LSOF_VERS="3000000"
 	echo "!!!WARNING!!!  Unsupported NetBSD version: $LSOF_VSTR"
 	echo "!!!WARNING!!!  Configuring for NetBSD 3.0"
 	;;
+      4.0*)
+	LSOF_TSTBIGF=" "
+	LSOF_VERS="4000000"
+	;;
+      4.99.*)
+	LSOF_TSTBIGF=" "
+	LSOF_VERS="4099000"
+	;;
+      4.*)
+	LSOF_VERS="4000000"
+	echo "!!!WARNING!!!  Unsupported NetBSD version: $LSOF_VSTR"
+	echo "!!!WARNING!!!  Configuring for NetBSD 4.0"
+	;;
+      5.[012]*)
+	LSOF_TSTBIGF=" "
+	LSOF_VERS="5000000"
+	;;
+      5.99.*)
+	LSOF_TSTBIGF=" "
+	LSOF_VERS="5099000"
+	;;
+      5.*)
+	LSOF_VERS="5000000"
+	echo "!!!WARNING!!!  Unsupported NetBSD version: $LSOF_VSTR"
+	echo "!!!WARNING!!!  Configuring for NetBSD 5.0"
+	;;
+      6.[01]*)
+	LSOF_TSTBIGF=" "
+	LSOF_VERS="6000000"
+	;;
+      6.99.*)
+	LSOF_TSTBIGF=" "
+	LSOF_VERS="6099000"
+	;;
+      6.*)
+	LSOF_VERS="6000000"
+	echo "!!!WARNING!!!  Unsupported NetBSD version: $LSOF_VSTR"
+	echo "!!!WARNING!!!  Configuring for NetBSD 6.0"
+	;;
+      7.[01]*)
+	LSOF_TSTBIGF=" "
+	LSOF_VERS="7000000"
+	;;
+      7.99.*)
+	LSOF_TSTBIGF=" "
+	LSOF_VERS="7099000"
+	;;
+      7.*)
+	LSOF_VERS="7000000"
+	echo "!!!WARNING!!!  Unsupported NetBSD version: $LSOF_VSTR"
+	echo "!!!WARNING!!!  Configuring for NetBSD 7.0"
+	;;
+      8.[0123]*)
+	LSOF_TSTBIGF=" "
+	LSOF_VERS="8000000"
+	;;
+      8.99.*)
+	LSOF_TSTBIGF=" "
+	LSOF_VERS="8099000"
+	;;
+      8.*)
+	LSOF_VERS="8000000"
+	echo "!!!WARNING!!!  Unsupported NetBSD version: $LSOF_VSTR"
+	echo "!!!WARNING!!!  Configuring for NetBSD 8.0"
+	;;
+      9.[0123]*)
+	LSOF_TSTBIGF=" "
+	LSOF_VERS="9000000"
+	;;
+      9.99.10[45678])
+	LSOF_TSTBIGF=" "
+	LSOF_VERS="9099104"
+	;;
+      9.99.*)
+	LSOF_TSTBIGF=" "
+	LSOF_VERS="9099000"
+	;;
+      9.*)
+	LSOF_VERS="9000000"
+	echo "!!!WARNING!!!  Unsupported NetBSD version: $LSOF_VSTR"
+	echo "!!!WARNING!!!  Configuring for NetBSD 9.0"
+	;;
+      10.99.*)
+	LSOF_TSTBIGF=" "
+	LSOF_VERS="10099000"
+	;;
+      10.*)
+	LSOF_VERS="10000000"
+	echo "!!!WARNING!!!  Unsupported NetBSD version: $LSOF_VSTR"
+	echo "!!!WARNING!!!  Configuring for NetBSD 10.0"
+	;;
       *)
 	echo "Unknown NetBSD release: $LSOF_VSTR"
-	echo Assuming NetBSD 1.6
-	LSOF_VERS="1006000"
+	echo Assuming NetBSD 10.0
+	LSOF_VERS="10000000"
 	;;
-      esac	# }
-    fi	# }
-
-    # Test for legal NetBSD version.
-
-    case $LSOF_VERS in	# {
-    1002000|1003000|1004000|1005000|1006000)
-      ;;
-    2000000|2099009|2099010)
-      ;;
-    3000000|3099000)
-      ;;
-    *)
-      echo "Unknown NetBSD version: $LSOF_VERS"
-      rm -f $LSOF_HLP
-      exit 1
-      ;;
-    esac	# }
+      esac	# }
+    fi	# }
+
     LSOF_CFGF="$LSOF_CFGF -DNETBSDV=$LSOF_VERS"
+
+    # For paddr_t
+    LSOF_CFGF="$LSOF_CFGF -D_KMEMUSER"
+    # For struct namecache
+    LSOF_CFGF="$LSOF_CFGF -D__NAMECACHE_PRIVATE"
+
     LSOF_TMP1="-DN_UNIXV=/netbsd"
-    if test -r ${LSOF_INCLUDE}/util.h	# {
+    if test -r /dev/ksyms              # {
+    then
+      LSOF_TMP1="-DN_UNIXV=/dev/ksyms"
+    elif test -r ${LSOF_INCLUDE}/util.h        # {
     then
       grep -q getbootfile ${LSOF_INCLUDE}/util.h
       if test $? -eq 0	# {
@@ -3455,6 +3080,7 @@ return(0); }
     fi	# }
     LSOF_TMP2="sys/vnode.h"
     LSOF_NBSD_PTYFS=0
+    LSOF_NBSD_TMPFS=0
     if test -r ${LSOF_INCLUDE}/$LSOF_TMP2	# {
     then
       LSOF_TMP3="${LSOF_INCLUDE}/$LSOF_TMP2"
@@ -3532,16 +3158,29 @@ return(0); }
 	  fi	# }
 	fi	# }
       fi	# }
+      grep -q VT_TMPFS $LSOF_TMP3
+      if test $? -eq 0   # {
+      then
+       LSOF_TMP2="fs/tmpfs/tmpfs.h"
+       if test -r ${LSOF_INCLUDE}/$LSOF_TMP2   # {
+       then
+         LSOF_CFGF="$LSOF_CFGF -DHASTMPFS"
+       else
+         if test -r ${NETBSD_SYS}/$LSOF_TMP2   # {
+         then
+           if test $NETBSD_SYS != $LSOF_INCLUDE        # {
+           then
+             LSOF_CFGF="$LSOF_CFGF -DHASTMPFS"
+             LSOF_NBSD_TMPFS=1
+           fi  # }
+         fi    # }
+       fi      # }
+      fi       # }
       if test "X$NETBSD_UVM" = "X"	# {
       then
-	grep -q UVM $LSOF_TMP3
-	if test $? -ne 0	# {
+	if test -r ${LSOF_INCLUDE}/uvm	# {
 	then
-	  egrep -q "v_uvm;|v_uobj;" $LSOF_TMP3
-	  if test $? -eq 0	# {
-	  then
-	    NETBSD_UVM="Y"
-	  fi	# }
+	  NETBSD_UVM="Y"
 	fi	# }
       fi	# }
     fi	# }
@@ -3697,13 +3336,13 @@ return(0); }
 
   # Build special header files, as required.
 
-    rm -rf dialects/n+obsd/include
+    rm -rf lib/dialects/netbsd/include
     if test "X$NETBSD_UVM" = "XY" -o "X$NETBSD_UVM" = "Xy"	# {
     then
-      mkdir dialects/n+obsd/include
-      touch dialects/n+obsd/include/opt_uvmhist.h
-      touch dialects/n+obsd/include/opt_lockdebug.h
-      LSOF_CFGF="$LSOF_CFGF -DUVM -I`pwd`/dialects/n+obsd/include"
+      mkdir lib/dialects/netbsd/include
+      touch lib/dialects/netbsd/include/opt_uvmhist.h
+      touch lib/dialects/netbsd/include/opt_lockdebug.h
+      LSOF_CFGF="$LSOF_CFGF -DUVM -I`pwd`/lib/dialects/netbsd/include"
       if test -d ${LSOF_INCLUDE}/uvm	# {
       then
 	LSOF_CFGF="$LSOF_CFGF -DHAS_UVM_INCL"
@@ -3730,10 +3369,10 @@ return(0); }
       LSOF_TMP1=${LSOF_TMPC}.edscr
       LSOF_TMP2=${LSOF_TMPC}.netcred
       LSOF_TMP3=${LSOF_TMPC}.netexport
-      LSOF_TMP4=dialects/n+obsd/include/netexport.h
-      if test ! -d dialects/n+obsd/include	# {
+      LSOF_TMP4=lib/dialects/netbsd/include/netexport.h
+      if test ! -d lib/dialects/netbsd/include	# {
       then
-	mkdir dialects/n+obsd/include
+	mkdir lib/dialects/netbsd/include
       fi	# }
       rm -f $LSOF_TMP1 $LSOF_TMP2 $LSOF_TMP3 $LSOF_TMP4
       echo "/^struct netcred" > $LSOF_TMP1
@@ -3769,10 +3408,10 @@ return(0); }
       fi	# }
       echo "#endif	/* !defined(NETEXPORT_H) */" >> $LSOF_TMP4
       rm -f $LSOF_TMP1 $LSOF_TMP2 $LSOF_TMP3
-      echo $LSOF_CFGF | grep /dialects/n+obsd/include > /dev/null 2>&1
+      echo $LSOF_CFGF | grep /lib/dialects/netbsd/include > /dev/null 2>&1
       if test $? -ne 0	# {
       then
-	LSOF_CFGF="$LSOF_CFGF -I`pwd`/dialects/n+obsd/include"
+	LSOF_CFGF="$LSOF_CFGF -I`pwd`/lib/dialects/netbsd/include"
       fi	# }
     fi	# }
     if test $LSOF_NBSD_BUFQH -eq 1	# {
@@ -3780,19 +3419,19 @@ return(0); }
 
     # Make a local copy of $NETBSD_SYS/sys/bufq.h.
 
-      if test ! -d dialects/n+obsd/include	# {
+      if test ! -d lib/dialects/netbsd/include	# {
       then
-	mkdir dialects/n+obsd/include
+	mkdir lib/dialects/netbsd/include
       fi	# }
-      if test ! -d dialects/n+obsd/include/sys	# {
+      if test ! -d lib/dialects/netbsd/include/sys	# {
       then
-	mkdir dialects/n+obsd/include/sys
+	mkdir lib/dialects/netbsd/include/sys
       fi	# }
-      cp $NETBSD_SYS/sys/bufq.h dialects/n+obsd/include/sys
-      echo $LSOF_CFGF | grep /dialects/n+obsd/include > /dev/null 2>&1
+      cp $NETBSD_SYS/sys/bufq.h lib/dialects/netbsd/include/sys
+      echo $LSOF_CFGF | grep lib/dialects/netbsd/include > /dev/null 2>&1
       if test $? -ne 0	# {
       then
-	LSOF_CFGF="$LSOF_CFGF -I`pwd`/dialects/n+obsd/include"
+	LSOF_CFGF="$LSOF_CFGF -I`pwd`lib/dialects/netbsd/include"
       fi	# }
     fi	# }
     if test $LSOF_NBSD_PTYFS -eq 1	# {
@@ -3800,103 +3439,115 @@ return(0); }
 
     # Make a local copy of $NETBSD_SYS/sys/fs/ptyfs/.
 
-      if test ! -d dialects/n+obsd/include	# {
+      if test ! -d lib/dialects/netbsd/include	# {
       then
-	mkdir dialects/n+obsd/include
+	mkdir lib/dialects/netbsd/include
       fi	# }
-      if test ! -d dialects/n+obsd/include/fs	# {
+      if test ! -d lib/dialects/netbsd/include/fs	# {
       then
-	mkdir dialects/n+obsd/include/fs
+	mkdir lib/dialects/netbsd/include/fs
       fi	# }
-      rm -rf dialects/n+obsd/include/fs/ptyfs
-      mkdir dialects/n+obsd/include/fs/ptyfs
-      cp $NETBSD_SYS/fs/ptyfs/*.h dialects/n+obsd/include/fs/ptyfs
-      echo $LSOF_CFGF | grep /dialects/n+obsd/include > /dev/null 2>&1
+      rm -rf lib/dialects/netbsd/include/fs/ptyfs
+      mkdir lib/dialects/netbsd/include/fs/ptyfs
+      cp $NETBSD_SYS/fs/ptyfs/*.h lib/dialects/netbsd/include/fs/ptyfs
+      echo $LSOF_CFGF | grep lib/dialects/netbsd/include > /dev/null 2>&1
       if test $? -ne 0	# {
       then
-	LSOF_CFGF="$LSOF_CFGF -I`pwd`/dialects/n+obsd/include"
+	LSOF_CFGF="$LSOF_CFGF -I`pwd`/lib/dialects/netbsd/include"
       fi	# }
     fi	# }
-    LSOF_CFGL="$LSOF_CFGL -lkvm"
-    LSOF_DIALECT_DIR=n+obsd
-    ;;
-
-# Configure for NeXTSTEP or OPENSTEP.
-
-  nextstep|next|ns|nxt|openstep|os)
-    LSOF_TGT="ns"
-    LSOF_TSTXO="../lib/snpf.o"
-    if test "X$LSOF_AR" = "X"	# {
-    then
-      LSOF_AR="rm -f \${LIB}; ar cr"
-    fi	# }
-    if test "X$LSOF_VSTR" = "X"	# {
-    then
-      LSOF_VSTR=`hostinfo | sed -n 's/.*NeXT Mach \([0-9\.]*\).*/\1/p'`
-    fi	# }
-    if test "X$LSOF_VERS" = "X"	# {
+    if test $LSOF_NBSD_TMPFS -eq 1     # {
     then
 
-      # If the NeXSTEP version isn't predefined, determine it.
+    # Make a local copy of $NETBSD_SYS/sys/fs/tmpfs/tmpfs.h.
 
-      LSOF_VERS=`echo $LSOF_VSTR | sed -n 's/\([0-9]*\)\.\([0-9]*\)/\1\2/p'`
-    fi	# }
-    if test "X$LSOF_CC" = "X"	# {
-    then
-      if test -x /usr/local/bin/gcc	# {
+      if test ! -d lib/dialects/netbsd/include     # {
       then
-	LSOF_CC=/usr/local/bin/gcc
-	LSOF_CCV=`$LSOF_CC -v 2>&1 | sed -n 's/.*version \(.*\)/\1/p'`
-      else
-	LSOF_CC=cc
-	LSOF_CCV=`$LSOF_CC -v 2>&1 | sed -n 's/.*version \(.*\)/\1/p'`
+       mkdir lib/dialects/netbsd/include
+      fi       # }
+      if test ! -d lib/dialects/netbsd/include/fs  # {
+      then
+       mkdir lib/dialects/netbsd/include/fs
+      fi       # }
+      rm -rf lib/dialects/netbsd/include/fs/tmpfs
+      mkdir lib/dialects/netbsd/include/fs/tmpfs
+      cp $NETBSD_SYS/fs/tmpfs/tmpfs.h lib/dialects/netbsd/include/fs/tmpfs
+      echo $LSOF_CFGF | grep lib/dialects/netbsd/include > /dev/null 2>&1
+      if test $? -ne 0 # {
+      then
+       LSOF_CFGF="$LSOF_CFGF -I`pwd`lib/dialects/netbsd/include"
+      fi       # }
+    fi # }
+
+    # Generate lockf.h from kern/vfs_lockf.c
+    rm -f ./lockf.h
+    if test -r ${NETBSD_SYS}/kern/vfs_lockf.c	# {
+    then
+      # Find the line number of TAILQ_HEAD
+      LSOF_TMP1=`grep -n "^TAILQ_HEAD" ${NETBSD_SYS}/kern/vfs_lockf.c | sed 's/\([0-9]*\):.*$/\1/'`
+      if test "X$LSOF_TMP1" != "X"	# {
+      then
+        LSOF_TMP2=0
+        # Find the end of struct lockf
+        for i in `grep -n "};" ${NETBSD_SYS}/kern/vfs_lockf.c | sed 's/\([0-9]*\):.*/\1/'` # {
+        do
+          if test $LSOF_TMP2 -eq 0 -a $i -gt $LSOF_TMP1	# {
+          then
+            LSOF_TMP2=$i
+          fi	# }
+        done	# }
+        if test $LSOF_TMP2 -eq 0	# {
+        then
+          LSOF_TMP1=""
+        else
+          cat > ./lockf.h << LOCKF1
+/*
+* lockf_owner.h -- created by lsof configure script on
+LOCKF1
+          printf " * " >> ./lockf.h
+          date >> ./lockf.h
+          cat >> ./lockf.h << LOCKF2
+*/
+
+#if	!defined(LOCKF_H)
+#define	LOCKF_H
+
+LOCKF2
+          ed -s ${NETBSD_SYS}/kern/vfs_lockf.c >> ./lockf.h << LOCKF3
+${LSOF_TMP1},${LSOF_TMP2}p
+LOCKF3
+          if test $? -ne 0	# {
+          then
+	    LSOF_TMP1=""
+          else
+	    cat >> ./lockf.h << LOCKF4
+
+#endif	/* defined(LOCKF_H) */
+LOCKF4
+	  fi	# }
+        fi	# }
       fi	# }
+    else
+      echo "FATAL ERROR: can't read ${NETBSD_SYS}/kern/vfs_lockf.c"
     fi	# }
-    echo $LSOF_CC | grep gcc > /dev/null
-    if test $? -eq 0	# {
-    then
-      LSOF_CFGL="$LSOF_CFGL -w"
-      LSOF_DEBUG="-pedantic -O"
-    fi	# }
-    LSOF_CFGF="$LSOF_CFGF -DSTEPV=$LSOF_VERS"
-    LSOF_DIALECT_DIR=n+os
-
-    # Test for AFS.
 
-    if test -r ${AFS_VICE}/etc/ThisCell	# {
+    if test "X$LSOF_TMP1" != "X" -a "X$LSOF_TMP2" != "X0" # {
     then
-      if test "X$LSOF_SCRIPT_CALL" = "Xno"	# {
-      then
-	if test -r ./AFSHeaders -a -r ./AFSVersion	# {
-	then
-	  LSOF_AFS="yes"
-	fi	# }
-      else
-	if test ! -x ./AFSConfig	# {
-	then
-	  echo "Can't find or execute the AFSConfig script"
-	  rm -f $LSOF_HLP
-	  exit 1
-	fi	# }
-	./AFSConfig
-	if test $? -eq 0 -a -r ./AFSHeaders -a -r ./AFSVersion	# {
-	then
-	    LSOF_AFS="yes"
-	fi	# }
-      fi	# }
-      if test "X$LSOF_AFS" = "Xyes"	# {
-      then
-	LSOF_AFSV=`cat ./AFSVersion | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1 \2/' | awk '{printf "%d%02d\n",\$1,\$2}'`
-	LSOF_CFGF="$LSOF_CFGF -DHAS_AFS=$LSOF_AFSV"
-	LSOF_DINC="$LSOF_DINC -I`cat ./AFSHeaders`"
-      fi	# }
+      echo "lockf.h creation succeeded."
+      LSOF_CFGF="$LSOF_CFGF -DHAS_LOCKF_H"
+    else
+      echo "lockf.h creation failed (see 00FAQ)"
     fi	# }
+
+    LSOF_CFGL="$LSOF_CFGL -lkvm"
+    LSOF_DIALECT_DIR=netbsd
     ;;
 
 # Configure for OpenBSD.  (OpenBSD uses NetBSD dialect sources and version
 # numbering.
 
   openbsd)
+    LSOF_TSTKMEM=0
     if test "X$LSOF_CC" = "X"	# {
     then
       LSOF_CC=cc
@@ -3987,6 +3638,14 @@ return(0); }
 	echo "!!!WARNING!!!  Unsupported OpenBSD 3.x version: $LSOF_VSTR"
 	echo "!!!WARNING!!!  Configuring for OpenBSD 3.9"
 	;;
+      7.2*)
+	LSOF_TSTBIGF=" "
+	LSOF_VERS=7020
+	;;
+      7.3*)
+	LSOF_TSTBIGF=" "
+	LSOF_VERS=7030
+	;;
       *)
 	echo "Unknown OpenBSD release: $LSOF_VSTR"
 	echo Assuming OpenBSD 3.9
@@ -3998,7 +3657,7 @@ return(0); }
     # Test for legal OpenBSD version.
 
     case $LSOF_VERS in	# {
-    1020|2050|2060|2070|2080|2090|3000|3010|3020|3030|3040|3050|3060|3070|3080|3090)
+    1020|2050|2060|2070|2080|2090|3000|3010|3020|3030|3040|3050|3060|3070|3080|3090|7020|7030)
       ;;
     *)
       echo "Unknown OpenBSD version: $LSOF_VERS"
@@ -4006,241 +3665,30 @@ return(0); }
       exit 1
       ;;
     esac	# }
+
     LSOF_CFGF="$LSOF_CFGF -DOPENBSDV=$LSOF_VERS"
-    if test -r /dev/ksyms	# {
-    then
-      LSOF_CFGF="$LSOF_CFGF -DN_UNIXV=/dev/ksyms"
-    else
-      LSOF_CFGF="$LSOF_CFGF -DN_UNIXV=/bsd"
-    fi
-    if test -r ${LSOF_INCLUDE}/nfs/nfsproto.h	# {
-    then
-      LSOF_CFGF="$LSOF_CFGF -DHASNFSPROTO"
-    fi	# }
+
     if test -r ${LSOF_INCLUDE}/netinet6/in6.h	# {
     then
       LSOF_CFGF="$LSOF_CFGF -DHASIPv6"
     fi	# }
-    LSOF_TMP1=0
+
     if test "X$OPENBSD_SYS" = "X"	# {
     then
       OPENBSD_SYS="/sys"
     fi	# }
-    if test -r ${OPENBSD_SYS}/miscfs/fdesc/fdesc.h	# {
-    then
-      grep -q Fctty ${OPENBSD_SYS}/miscfs/fdesc/fdesc.h
-      if test $? -eq 0	# {
-      then
-	LSOF_CFGF="$LSOF_CFGF -DHASFDESCFS=1"
-      else
-	LSOF_CFGF="$LSOF_CFGF -DHASFDESCFS=2"
-      fi	# }
-      grep -q fd_link ${OPENBSD_SYS}/miscfs/fdesc/fdesc.h
-      if test $? -eq 0	# {
-      then
-	LSOF_CFGF="$LSOF_CFGF -DHASFDLINK"
-      fi	# }
-      LSOF_TMP1=1
-    fi	# }
-    if test -r ${LSOF_INCLUDE}/sys/vnode.h	# {
-    then
-      grep -q VT_LFS ${LSOF_INCLUDE}/sys/vnode.h
-      if test $? -eq 0   # {
-      then
-	LSOF_CFGF="$LSOF_CFGF -DHASLFS"
-      fi	# }
-    fi	# }
-    if test -r ${LSOF_INCLUDE}/miscfs/nullfs/null.h	# {
-    then
-      LSOF_CFGF="$LSOF_CFGF -DHASNULLFS"
-    else
-      if test -r ${OPENBSD_SYS}/miscfs/nullfs/null.h	# {
-      then
-	LSOF_CFGF="$LSOF_CFGF -DHASNULLFS"
-	LSOF_TMP1=1
-      fi	# }
-    fi	# }
+
     if test -d ${OPENBSD_SYS}/miscfs/procfs	# {
     then
       LSOF_CFGF="$LSOF_CFGF -DHASPROCFS"
-      LSOF_TMP1=1
-    fi	# }
-    if test -d ${OPENBSD_SYS}/isofs/cd9660	# {
-    then
-      LSOF_CFGF="$LSOF_CFGF -DHAS9660FS=1"
-      LSOF_TMP1=1
-    else
-      if test -d ${OPENBSD_SYS}/fs/cd9660	# {
-      then
-	LSOF_CFGF="$LSOF_CFGF -DHAS9660FS=2"
-	LSOF_TMP1=1
-      fi	# }
-    fi	# }
-    if test -d ${OPENBSD_SYS}/msdosfs	# {
-    then
-      LSOF_CFGF="$LSOF_CFGF -DHASMSDOSFS=1"
-      LSOF_TMP1=1
-    else
-      if test -d ${OPENBSD_SYS}/fs/msdosfs	# {
-      then
-	LSOF_CFGF="$LSOF_CFGF -DHASMSDOSFS=2"
-	LSOF_TMP1=1
-      fi	# }
-    fi	# }
-    if test -r ${OPENBSD_SYS}/miscfs/kernfs/kernfs.h	# {
-    then
-      grep -q "kt_name;" ${OPENBSD_SYS}/miscfs/kernfs/kernfs.h
-      if test $? -eq 0	# {
-	then
- 	  LSOF_CFGF="$LSOF_CFGF -DHASKERNFS"
-	  LSOF_TMP1=1
-      fi	# }
-    fi	# }
-    if test $LSOF_TMP1 -eq 1 -a "X$LSOF_INCLUDE" != "X$OPENBSD_SYS"	# {
-    then
-      LSOF_DINC="-I$LSOF_INCLUDE -I$OPENBSD_SYS"
-    fi	# }
-    grep -q VT_EXT2FS ${LSOF_INCLUDE}/sys/vnode.h
-    if test $? -eq 0	# {
-    then
-      LSOF_TMP1=1
-      if test -r ${LSOF_INCLUDE}/ufs/ufs/inode.h	# {
-      then
-	grep -q "*e2fs_din" ${LSOF_INCLUDE}/ufs/ufs/inode.h
-	if test $? -eq 0	# {
-	then
-	  LSOF_CFGF="$LSOF_CFGF -DHASI_E2FS_PTR"
-	fi	# }
-	grep -q "^#define[ 	]i_e2din" ${LSOF_INCLUDE}/ufs/ufs/inode.h
-	if test $? -eq 0	# {
-	then
-	  LSOF_TMP1=2
-	fi	# }
-      fi	# }
-      LSOF_CFGF="$LSOF_CFGF -DHASEXT2FS=$LSOF_TMP1"
-    fi	# }
-    if test -r ${LSOF_INCLUDE}/ufs/ufs/inode.h	# {
-    then
-      grep -q i_effnlink ${LSOF_INCLUDE}/ufs/ufs/inode.h
-      if test $? -eq 0	# {
-      then
-	LSOF_CFGF="$LSOF_CFGF -DHASEFFNLINK=i_effnlink"
-      fi	# }
-      grep -q dinode_u ${LSOF_INCLUDE}/ufs/ufs/inode.h
-      if test $? -eq 0	# {
-      then
-	LSOF_CFGF="$LSOF_CFGF -DHAS_DINODE_U"
-      fi	# }
-      grep -q i_ffs1_size ${LSOF_INCLUDE}/ufs/ufs/inode.h
-      if test $? -eq 0	# {
-      then
-	LSOF_CFGF="$LSOF_CFGF -DHASI_FFS1"
-      fi	# }
-      grep -q UM_UFS ${LSOF_INCLUDE}/ufs/ufs/inode.h
-      if test $? -eq 0	# {
-      then
-	LSOF_CFGF="$LSOF_CFGF -DHAS_UM_UFS"
-      fi	# }
-    fi	# }
-    if test -r ${LSOF_INCLUDE}/sys/namei.h
-    then
-      grep -q nc_vpid ${LSOF_INCLUDE}/sys/namei.h
-      if test $? -eq 0	# {
-      then
-	LSOF_CFGF="$LSOF_CFGF -DHASNCVPID"
-      fi	# }
-    fi	# }
-    if test "X$OPENBSD_UVM" = "X"	# {
-    then
-      if test -r ${LSOF_INCLUDE}/sys/vnode.h	# {
-      then
-	grep -q UVM ${LSOF_INCLUDE}/sys/vnode.h
-	if test $? -ne 0	# {
-	then
-	  egrep -q "v_uvm;|v_uobj;" ${LSOF_INCLUDE}/sys/vnode.h
-	  if test $? -eq 0	# {
-	  then
-	    OPENBSD_UVM="Y"
-	  fi	# }
-	fi	# }
-      fi	# }
-    fi	# }
-    if test "X$OPENBSD_UVM" = "XY" -o "X$OPENBSD_UVM" = "Xy"	# {
-    then
-      LSOF_CFGF="$LSOF_CFGF -DUVM"
-      if test -d ${LSOF_INCLUDE}/uvm	# {
-      then
-	LSOF_CFGF="$LSOF_CFGF -DHAS_UVM_INCL"
-      fi	# }
     fi	# }
-    if test -r ${LSOF_INCLUDE}/sys/mount.h -a $LSOF_VERS -lt 3030	# {
-    then
-
-      # Build a local OpenBSD netexport.h header file for possible use by
-      # <msdosfs/msdosfsmount.h>.  Make sure CFGL contains a -I for it.
 
-      LSOF_TMP1=${LSOF_TMPC}.edscr
-      LSOF_TMP2=${LSOF_TMPC}.netcred
-      LSOF_TMP3=${LSOF_TMPC}.netexport
-      LSOF_TMP4=dialects/n+obsd/include/netexport.h
-      if test ! -d dialects/n+obsd/include	# {
-      then
-	mkdir dialects/n+obsd/include
-      fi	# }
-      rm -f $LSOF_TMP1 $LSOF_TMP2 $LSOF_TMP3 $LSOF_TMP4
-      echo "/^struct netcred" > $LSOF_TMP1
-      echo "1,.-1d" >> $LSOF_TMP1
-      echo "/^};" >> $LSOF_TMP1
-      echo "1,.w $LSOF_TMP2" >> $LSOF_TMP1
-      ed ${LSOF_INCLUDE}/sys/mount.h < $LSOF_TMP1 > /dev/null 2>&1
-      rm -f $LSOF_TMP1
-      echo "/^struct netexport" > $LSOF_TMP1
-      echo "1,.-1d" >> $LSOF_TMP1
-      echo "/^};" >> $LSOF_TMP1
-      echo "1,.w $LSOF_TMP3" >> $LSOF_TMP1
-      ed ${LSOF_INCLUDE}/sys/mount.h < $LSOF_TMP1 > /dev/null 2>&1
-      echo "/*" > $LSOF_TMP4
-      echo " * netexport.h" >> $LSOF_TMP4
-      echo -n " * Created by Configure: " >> $LSOF_TMP4
-      echo `date` >> $LSOF_TMP4
-      echo " */" >> $LSOF_TMP4
-      echo "" >> $LSOF_TMP4
-      echo "#if	!defined(NETEXPORT_H)" >> $LSOF_TMP4
-      echo "#define	NETEXPORT_H" >> $LSOF_TMP4
-      echo "" >> $LSOF_TMP4
-      echo "#include <net/radix.h>" >> $LSOF_TMP4
-      echo "" >> $LSOF_TMP4
-      if test -r $LSOF_TMP2	# {
-      then
-	cat $LSOF_TMP2 >> $LSOF_TMP4
-	echo "" >> $LSOF_TMP4
-      fi	# }
-      if test -r $LSOF_TMP3	# {
-      then
-	cat $LSOF_TMP3 >> $LSOF_TMP4
-      fi	# }
-      echo "#endif	/* !defined(NETEXPORT_H) */" >> $LSOF_TMP4
-      rm -f $LSOF_TMP1 $LSOF_TMP2 $LSOF_TMP3
-      echo $LSOF_CFGF | grep /dialects/n+obsd/include > /dev/null 2>&1
-      if test $? -ne 0	# {
-      then
-	LSOF_CFGF="$LSOF_CFGF -I`pwd`/dialects/n+obsd/include"
-      fi	# }
-    fi	# }
-    if test -r ${LSOF_INCLUDE}/sys/lockf.h	# {
-    then
-      grep vop_advlock_args ${LSOF_INCLUDE}/sys/lockf.h > /dev/null
-      if test $? -eq 0	# {
-      then
-	LSOF_CFGF="$LSOF_CFGF -DHAS_ADVLOCK_ARGS"
-      fi	# }
-    fi	# }
     if test -r ${LSOF_INCLUDE}/sys/pipe.h	# {
     then
       LSOF_CFGF="$LSOF_CFGF -DHAS_SYS_PIPEH"
     fi	# }
-    LSOF_CFGL="$LSOF_CFGL -lkvm"
-    LSOF_DIALECT_DIR=n+obsd
+
+    LSOF_DIALECT_DIR=openbsd
     ;;
 
 # Configure for SCO OpenServer.
@@ -4585,7 +4033,7 @@ return(0); }
 	rm -f ${LSOF_TMPC}.*
 	echo "#define _KMEMUSER" > ${LSOF_TMPC}.c
 	echo "#include <sys/proc/prdata.h>" >> ${LSOF_TMPC}.c
-	echo "main(){" >> ${LSOF_TMPC}.c
+	echo "int main(){" >> ${LSOF_TMPC}.c
 	echo "enum prnodetype p=PR_GWINDOWS;}" >> ${LSOF_TMPC}.c
 	echo "Testing prdata.h for PR_GWINDOWS, using $LSOF_CC"
 	echo $LSOF_CC | grep gcc > /dev/null
@@ -4610,7 +4058,7 @@ return(0); }
 	rm -f ${LSOF_TMPC}.*
 	echo "#define _KMEMUSER" > ${LSOF_TMPC}.c
 	echo "#include <sys/proc/prdata.h>" >> ${LSOF_TMPC}.c
-	echo "main(){" >> ${LSOF_TMPC}.c
+	echo "int main(){" >> ${LSOF_TMPC}.c
 	echo "enum prnodetype p=PR_LDT;}" >> ${LSOF_TMPC}.c
 	echo "Testing prdata.h for PR_LDT, using $LSOF_CC"
 	echo $LSOF_CC | grep gcc > /dev/null
@@ -4655,7 +4103,7 @@ return(0); }
 
 	    echo "Testing $LSOF_CC for 64 bit support"
 	    rm -f ${LSOF_TMPC}.*
-	    echo "main(){}" > ${LSOF_TMPC}.c
+	    echo "int main(){}" > ${LSOF_TMPC}.c
 	    LSOF_TMP1=""
 
 	# First try gcc's -m64 option -- it's the most current possibility.
@@ -4675,7 +4123,7 @@ return(0); }
 
 	    # Try using the older -mcpu=v9 option with gcc instead of -m64.
 
-	      echo "main(){}" > ${LSOF_TMPC}.c
+	      echo "int main(){}" > ${LSOF_TMPC}.c
 	      $LSOF_CC ${LSOF_TMPC}.c -mcpu=v9 -o ${LSOF_TMPC}.x > /dev/null 2>&1
 	      if test $? -eq 0	# {
 	      then
@@ -4731,7 +4179,7 @@ return(0); }
 	      echo "Testing $LSOF_CC for 64 bit $LSOF_TMP2 support"
 	      rm -f ${LSOF_TMPC}.*
 	      LSOF_TMP3="-xarch=$LSOF_TMP1"
-	      echo "main(){}" > ${LSOF_TMPC}.c
+	      echo "int main(){}" > ${LSOF_TMPC}.c
 	      LSOF_TMP4=`$LSOF_CC ${LSOF_TMPC}.c $LSOF_TMP3 -o ${LSOF_TMPC}.x 2>&1`
 	      if test $? -eq 0	# {
 	      then
@@ -4970,6 +4418,21 @@ return(0); }
       LSOF_CFGF="$LSOF_CFGF -DHASCACHEFS"
     fi	# }
 
+
+    # Test for <sys/rgm.h>.
+
+    if test -r ${LSOF_INCLUDE}/sys/rgm.h {
+    then
+      LSOF_CFGF="$LSOF_CFGF -DHAS_SYS_RGM_H"
+    fi  # }
+
+    # Test for <rpc/rpc_tags.h>.
+
+    if test -r ${LSOF_INCLUDE}/rpc/rpc_tags.h {
+    then
+      LSOF_CFGF="$LSOF_CFGF -DHAS_RPC_RPC_TAGS_H"
+    fi  # }
+
     # Test for <utmpx.h>
 
     if test -r ${LSOF_INCLUDE}/utmpx.h	# {
@@ -4983,7 +4446,7 @@ return(0); }
     then
       rm -f ${LSOF_TMPC}.*
       echo "#include <sys/vnode.h>" > ${LSOF_TMPC}.c
-      echo "main(){" >> ${LSOF_TMPC}.c
+      echo "int main(){" >> ${LSOF_TMPC}.c
       echo "enum vtype p=VSOCK;}" >> ${LSOF_TMPC}.c
       echo "Testing vnode.h for VSOCK, using $LSOF_CC"
       echo $LSOF_CC | grep gcc > /dev/null
@@ -5388,18 +4851,18 @@ fi	# }
 
 # Make sure target directory exists.
 
-if test ! -d ./dialects/$LSOF_DIALECT_DIR	# {
+if test ! -d ./lib/dialects/$LSOF_DIALECT_DIR	# {
 then
-  echo "Can't configure for $LSOF_TGT -- ./dialects/$LSOF_DIALECT_DIR doesn't exist."
+  echo "Can't configure for $LSOF_TGT -- ./lib/dialects/$LSOF_DIALECT_DIR doesn't exist."
   rm -f $LSOF_HLP
   exit 1
 fi	# }
 
 # Make sure $LSOF_MK exists in the target directory.
 
-if test ! -r ./dialects/$LSOF_DIALECT_DIR/$LSOF_MK	# {
+if test ! -r ./lib/dialects/$LSOF_DIALECT_DIR/$LSOF_MK	# {
 then
-  echo "Can't configure for $LSOF_TGT -- ./dialects/$LSOF_DIALECT_DIR/$LSOF_MK doesn't exist."
+  echo "Can't configure for $LSOF_TGT -- ./lib/dialects/$LSOF_DIALECT_DIR/$LSOF_MK doesn't exist."
   rm -f $LSOF_HLP
   exit 1
 fi	# }
@@ -5419,9 +4882,9 @@ then
 else
   LSOF_REST=$LSOF_TMP1
 fi	# }
-if test ! -r ./dialects/$LSOF_DIALECT_DIR/$LSOF_REST	# {
+if test ! -r ./lib/dialects/$LSOF_DIALECT_DIR/$LSOF_REST	# {
 then
-  echo "Can't configure for $LSOF_TGT -- ./dialects/$LSOF_DIALECT_DIR/$LSOF_REST doesn't exist."
+  echo "Can't configure for $LSOF_TGT -- ./lib/dialects/$LSOF_DIALECT_DIR/$LSOF_REST doesn't exist."
   rm -f $LSOF_HLP
   exit 1
 fi	# }
@@ -5470,7 +4933,7 @@ fi	# }
 rm -f ${LSOF_TMPC}.*
 cat > $LSOF_TMPC.c << .LSOF_END_HERE_DOC2
 #include <time.h>
-main(){
+int main(){
   time_t cl;
   struct tm *ts;
   char bf[32];
@@ -5507,7 +4970,7 @@ if test "X$LSOF_MKC" = "X"	# {
 then
   LSOF_MKC="ln -s"
 fi	# }
-LSOF_MKC=$LSOF_MKC ./dialects/$LSOF_DIALECT_DIR/$LSOF_MK $LSOF_TGT $LSOF_VERS
+LSOF_MKC=$LSOF_MKC ./lib/dialects/$LSOF_DIALECT_DIR/$LSOF_MK $LSOF_TGT $LSOF_VERS || exit 1
 
 # Make $LSOF_MKFC and ${LSOF_LIB}/$LSOF_LIBMKF.
 
@@ -5561,7 +5024,7 @@ fi	# }
 echo "" >> $LSOF_MKFC
 if test "X$LSOF_DEBUG" = "X"	# {
 then
-  LSOF_DEBUG="-O"
+  LSOF_DEBUG=""
 else
   if test "X$LSOF_DEBUG" = "XNo-O"	# {
   then
@@ -5588,12 +5051,14 @@ then
   echo "" >> $LSOF_MKFC
   echo "KVM=	$LSOF_DISTRIBKVM" >> $LSOF_MKFC
 fi	# }
+echo "" >> $LSOF_MKFC
+echo "DIALECT_DIR=	$LSOF_DIALECT_DIR" >> $LSOF_MKFC
 rm -f ${LSOF_LIB}/$LSOF_LIBMKF
 if test "X$LSOF_LIB_NO" = "X"	# {
 then
   cp $LSOF_MKFC ${LSOF_LIB}/$LSOF_LIBMKF
 fi	# }
-cat ./dialects/$LSOF_DIALECT_DIR/$LSOF_REST >> $LSOF_MKFC
+cat ./lib/dialects/$LSOF_DIALECT_DIR/$LSOF_REST >> $LSOF_MKFC
 if test "X$LSOF_CFLAGS_OVERRIDE" != "X"	# {
 then
   sed -i -e 's/^CFLAGS=/override CFLAGS=/' $LSOF_MKFC
@@ -5607,6 +5072,8 @@ then
   #
   # Add the library Makefile skeleton section.
 
+  echo "" >> ${LSOF_LIB}/$LSOF_LIBMKF
+  echo "DIALECT_DIR=	$LSOF_DIALECT_DIR" >> ${LSOF_LIB}/$LSOF_LIBMKF
   echo "" >> ${LSOF_LIB}/$LSOF_LIBMKF
   if test "X$LSOF_AR" = "X"	# {
   then
diff --git a/Customize b/Customize
index 4607002..3a01ea6 100755
--- a/Customize
+++ b/Customize
@@ -641,7 +641,7 @@ users.  Press ENTER to use the current value of HASENVDC:
 HASPERSDC is a format that specifies how the personal device cache
 path is constructed.  Consult the 00DCACHE and 00FAQ files of the
 lsof distribution for information on the conversions supported in
-HASPERSDC.  Press ENTER to use the curent HASPERSDC format:
+HASPERSDC.  Press ENTER to use the current HASPERSDC format:
 
 .CAT_MARK
 
diff --git a/Doxyfile b/Doxyfile
new file mode 100644
index 0000000..8379fa0
--- /dev/null
+++ b/Doxyfile
@@ -0,0 +1,2733 @@
+# Doxyfile 1.9.4
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+#
+# Note:
+#
+# Use doxygen to compare the used configuration file with the template
+# configuration file:
+# doxygen -x [configFile]
+# Use doxygen to compare the used configuration file with the template
+# configuration file without replacing the environment variables:
+# doxygen -x_noenv [configFile]
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the configuration
+# file that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# https://www.gnu.org/software/libiconv/ for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME           = "lsof: LiSt Open Files"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER         =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF          =
+
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
+
+PROJECT_LOGO           =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = output
+
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096
+# sub-directories (in 2 levels) under the output directory of each output format
+# and will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system. Adapt CREATE_SUBDIRS_LEVEL to
+# control the number of sub-directories.
+# The default value is: NO.
+
+CREATE_SUBDIRS         = NO
+
+# Controls the number of sub-directories that will be created when
+# CREATE_SUBDIRS tag is set to YES. Level 0 represents 16 directories, and every
+# level increment doubles the number of directories, resulting in 4096
+# directories at level 8 which is the default and also the maximum value. The
+# sub-directories are organized in 2 levels, the first level always has a fixed
+# number of 16 directories.
+# Minimum value: 0, maximum value: 8, default value: 8.
+# This tag requires that the tag CREATE_SUBDIRS is set to YES.
+
+CREATE_SUBDIRS_LEVEL   = 8
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES    = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Bulgarian,
+# Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, English
+# (United States), Esperanto, Farsi (Persian), Finnish, French, German, Greek,
+# Hindi, Hungarian, Indonesian, Italian, Japanese, Japanese-en (Japanese with
+# English messages), Korean, Korean-en (Korean with English messages), Latvian,
+# Lithuanian, Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese,
+# Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish,
+# Swedish, Turkish, Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF       = "The $name class" \
+                         "The $name widget" \
+                         "The $name file" \
+                         is \
+                         provides \
+                         specifies \
+                         contains \
+                         represents \
+                         a \
+                         an \
+                         the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES        = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH        =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH    =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF      = YES
+
+# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line
+# such as
+# /***************
+# as being the beginning of a Javadoc-style comment "banner". If set to NO, the
+# Javadoc-style will behave just like regular comments and it will not be
+# interpreted by doxygen.
+# The default value is: NO.
+
+JAVADOC_BANNER         = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# By default Python docstrings are displayed as preformatted text and doxygen's
+# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the
+# doxygen's special commands can be used and the contents of the docstring
+# documentation blocks is shown as doxygen documentation.
+# The default value is: YES.
+
+PYTHON_DOCSTRING       = YES
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE               = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:^^"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". Note that you cannot put \n's in the value part of an alias
+# to insert newlines (in the resulting output). You can put ^^ in the value part
+# of an alias to insert a newline as if a physical newline was in the original
+# file. When you need a literal { or } or , in the value part of an alias you
+# have to escape them by means of a backslash (\), this can lead to conflicts
+# with the commands \{ and \} for these it is advised to use the version @{ and
+# @} or use a double escape (\\{ and \\})
+
+ALIASES                =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice
+# sources only. Doxygen will then generate output that is more tailored for that
+# language. For instance, namespaces will be presented as modules, types will be
+# separated into more groups, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_SLICE  = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
+# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice,
+# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
+# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
+# tries to guess whether the code is fixed or free formatted code, this is the
+# default for Fortran type files). For instance to make doxygen treat .inc files
+# as Fortran files (default is PHP), and .f files as C (default is Fortran),
+# use: inc=Fortran f=C.
+#
+# Note: For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen. When specifying no_extension you should add
+# * to the FILE_PATTERNS.
+#
+# Note see also the list of default file extension mappings.
+
+EXTENSION_MAPPING      =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See https://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT       = YES
+
+# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
+# to that level are automatically included in the table of contents, even if
+# they do not have an id attribute.
+# Note: This feature currently applies only to Markdown headings.
+# Minimum value: 0, maximum value: 99, default value: 5.
+# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
+
+TOC_INCLUDE_HEADINGS   = 5
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT       = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# If one adds a struct or class to a group and this option is enabled, then also
+# any nested class or struct is added to the same group. By default this option
+# is disabled and one has to add nested compounds explicitly via \ingroup.
+# The default value is: NO.
+
+GROUP_NESTED_COMPOUNDS = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING            = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS  = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE      = 0
+
+# The NUM_PROC_THREADS specifies the number of threads doxygen is allowed to use
+# during processing. When set to 0 doxygen will based this on the number of
+# cores available in the system. You can set it explicitly to a value larger
+# than 0 to get more control over the balance between CPU load and processing
+# speed. At this moment only the input processing can be done using multiple
+# threads. Since this is still an experimental feature the default is set to 1,
+# which effectively disables parallel processing. Please report any issues you
+# encounter. Generating dot graphs in parallel is controlled by the
+# DOT_NUM_THREADS setting.
+# Minimum value: 0, maximum value: 32, default value: 1.
+
+NUM_PROC_THREADS       = 1
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL            = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual
+# methods of a class will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIV_VIRTUAL   = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO,
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. If set to YES, local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO, only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If this flag is set to YES, the name of an unnamed parameter in a declaration
+# will be determined by the corresponding definition. By default unnamed
+# parameters remain unnamed in the output.
+# The default value is: YES.
+
+RESOLVE_UNNAMED_PARAMS = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO, these classes will be included in the various overviews. This option
+# has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# declarations. If set to NO, these declarations will be included in the
+# documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO, these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS          = NO
+
+# With the correct setting of option CASE_SENSE_NAMES doxygen will better be
+# able to match the capabilities of the underlying filesystem. In case the
+# filesystem is case sensitive (i.e. it supports files in the same directory
+# whose names only differ in casing), the option must be set to YES to properly
+# deal with such files in case they appear in the input. For filesystems that
+# are not case sensitive the option should be set to NO to properly deal with
+# output files written for symbols that only differ in casing, such as for two
+# classes, one named CLASS and the other named Class, and to also support
+# references to files without having to specify the exact matching casing. On
+# Windows (including Cygwin) and MacOS, users should typically set this option
+# to NO, whereas on Linux or other Unix flavors it should typically be set to
+# YES.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES, the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
+# append additional text to a page's title, such as Class Reference. If set to
+# YES the compound reference will be hidden.
+# The default value is: NO.
+
+HIDE_COMPOUND_REFERENCE= NO
+
+# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class
+# will show which file needs to be included to use the class.
+# The default value is: YES.
+
+SHOW_HEADERFILE        = YES
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC  = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES   = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING  = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
+# list. This list is created by putting \todo commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
+# list. This list is created by putting \test commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS       =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES, the
+# list will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES        = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER    =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file. See also section "Changing the
+# layout of pages" for information.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE            =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES         =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS               = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as documenting some parameters in
+# a documented function twice, or documenting parameters that don't exist or
+# using markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR      = YES
+
+# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete
+# function parameter documentation. If set to NO, doxygen will accept that some
+# parameters have no documentation without warning.
+# The default value is: YES.
+
+WARN_IF_INCOMPLETE_DOC = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO, doxygen will only warn about wrong parameter
+# documentation, but not about the absence of documentation. If EXTRACT_ALL is
+# set to YES then this flag will automatically be disabled. See also
+# WARN_IF_INCOMPLETE_DOC
+# The default value is: NO.
+
+WARN_NO_PARAMDOC       = NO
+
+# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
+# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
+# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but
+# at the end of the doxygen process doxygen will return with a non-zero status.
+# Possible values are: NO, YES and FAIL_ON_WARNINGS.
+# The default value is: NO.
+
+WARN_AS_ERROR          = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# See also: WARN_LINE_FORMAT
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# In the $text part of the WARN_FORMAT command it is possible that a reference
+# to a more specific place is given. To make it easier to jump to this place
+# (outside of doxygen) the user can define a custom "cut" / "paste" string.
+# Example:
+# WARN_LINE_FORMAT = "'vi $file +$line'"
+# See also: WARN_FORMAT
+# The default value is: at line $line of file $file.
+
+WARN_LINE_FORMAT       = "at line $line of file $file"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr). In case the file specified cannot be opened for writing the
+# warning and error messages are written to standard error. When as file - is
+# specified the warning and error messages are written to standard output
+# (stdout).
+
+WARN_LOGFILE           =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
+# Note: If this tag is empty the current directory is searched.
+
+INPUT                  = include
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see:
+# https://www.gnu.org/software/libiconv/) for the list of possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# read by doxygen.
+#
+# Note the list of default checked file patterns might differ from the list of
+# default file extension mappings.
+#
+# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
+# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
+# *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, *.php4, *.php5, *.phtml,
+# *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C
+# comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd,
+# *.vhdl, *.ucf, *.qsf and *.ice.
+
+FILE_PATTERNS          = *.c \
+                         *.cc \
+                         *.cxx \
+                         *.cpp \
+                         *.c++ \
+                         *.java \
+                         *.ii \
+                         *.ixx \
+                         *.ipp \
+                         *.i++ \
+                         *.inl \
+                         *.idl \
+                         *.ddl \
+                         *.odl \
+                         *.h \
+                         *.hh \
+                         *.hxx \
+                         *.hpp \
+                         *.h++ \
+                         *.l \
+                         *.cs \
+                         *.d \
+                         *.php \
+                         *.php4 \
+                         *.php5 \
+                         *.phtml \
+                         *.inc \
+                         *.m \
+                         *.markdown \
+                         *.md \
+                         *.mm \
+                         *.dox \
+                         *.py \
+                         *.pyw \
+                         *.f90 \
+                         *.f95 \
+                         *.f03 \
+                         *.f08 \
+                         *.f18 \
+                         *.f \
+                         *.for \
+                         *.vhd \
+                         *.vhdl \
+                         *.ucf \
+                         *.qsf \
+                         *.ice
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE              = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE                =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# ANamespace::AClass, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS        =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH           =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS       = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH             =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+INPUT_FILTER           =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+FILTER_PATTERNS        =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES    = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# entity all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION    = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS        = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see https://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS       = YES
+
+# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
+# clang parser (see:
+# http://clang.llvm.org/) for more accurate parsing at the cost of reduced
+# performance. This can be particularly helpful with template rich C++ code for
+# which doxygen's built-in parser lacks the necessary type information.
+# Note: The availability of this option depends on whether or not doxygen was
+# generated with the -Duse_libclang=ON option for CMake.
+# The default value is: NO.
+
+CLANG_ASSISTED_PARSING = NO
+
+# If the CLANG_ASSISTED_PARSING tag is set to YES and the CLANG_ADD_INC_PATHS
+# tag is set to YES then doxygen will add the directory of each input to the
+# include path.
+# The default value is: YES.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_ADD_INC_PATHS    = YES
+
+# If clang assisted parsing is enabled you can provide the compiler with command
+# line options that you would normally use when invoking the compiler. Note that
+# the include paths will already be set by doxygen for the files and directories
+# specified with INPUT and INCLUDE_PATH.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_OPTIONS          =
+
+# If clang assisted parsing is enabled you can provide the clang parser with the
+# path to the directory containing a file called compile_commands.json. This
+# file is the compilation database (see:
+# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the
+# options used when the source files were built. This is equivalent to
+# specifying the -p option to a clang tool, such as clang-check. These options
+# will then be passed to the parser. Any options specified with CLANG_OPTIONS
+# will be added as well.
+# Note: The availability of this option depends on whether or not doxygen was
+# generated with the -Duse_libclang=ON option for CMake.
+
+CLANG_DATABASE_PATH    =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX     = YES
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX          =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER            =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER            =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET        =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefore more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET  =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES       =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the style sheet and background images according to
+# this color. Hue is specified as an angle on a color-wheel, see
+# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE    = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use gray-scales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT    = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA  = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to YES can help to show when doxygen was last run and thus if the
+# documentation is up to date.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP         = NO
+
+# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
+# documentation will contain a main index with vertical navigation menus that
+# are dynamically created via JavaScript. If disabled, the navigation index will
+# consists of multiple levels of tabs that are statically embedded in every HTML
+# page. Disable this option to support browsers that do not have JavaScript,
+# like the Qt help browser.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_MENUS     = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see:
+# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To
+# create a documentation set, doxygen will generate a Makefile in the HTML
+# output directory. Running make will produce the docset in that directory and
+# running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
+# genXcode/_index.html for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET        = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# This tag determines the URL of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDURL         =
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME  = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# on Windows. In the beginning of 2021 Microsoft took the original page, with
+# a.o. the download links, offline the HTML help workshop was already many years
+# in maintenance mode). You can download the HTML help workshop from the web
+# archives at Installation executable (see:
+# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo
+# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe).
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP      = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE               =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION           =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the main .chm file (NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI           = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING     =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE               =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE          = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME   =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS  =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS  =
+
+# The QHG_LOCATION tag can be used to specify the location (absolute path
+# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to
+# run qhelpgenerator on the generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION           =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP   = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID         = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX          = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine tune the look of the index (see "Fine-tuning the output"). As an
+# example, the default style sheet generated by doxygen has an example that
+# shows how to put an image at the root of the tree instead of the PROJECT_NAME.
+# Since the tree basically has the same information as the tab index, you could
+# consider setting DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW      = NO
+
+# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the
+# FULL_SIDEBAR option determines if the side bar is limited to only the treeview
+# area (value NO) or if it should extend to the full height of the window (value
+# YES). Setting this to YES gives a layout similar to
+# https://docs.readthedocs.io with more room for contents, but less room for the
+# project logo, title, and description. If either GENERATE_TREEVIEW or
+# DISABLE_INDEX is set to NO, this option has no effect.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FULL_SIDEBAR           = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH         = 250
+
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW    = NO
+
+# If the OBFUSCATE_EMAILS tag is set to YES, doxygen will obfuscate email
+# addresses.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+OBFUSCATE_EMAILS       = YES
+
+# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
+# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
+# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
+# the HTML output. These images will generally look nicer at scaled resolutions.
+# Possible values are: png (the default) and svg (looks nicer but requires the
+# pdf2svg or inkscape tool).
+# The default value is: png.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FORMULA_FORMAT    = png
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE       = 10
+
+# Use the FORMULA_TRANSPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT    = YES
+
+# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
+# to create new LaTeX commands to be used in formulas as building blocks. See
+# the section "Including formulas" for details.
+
+FORMULA_MACROFILE      =
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# https://www.mathjax.org) which uses client side JavaScript for the rendering
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX            = NO
+
+# With MATHJAX_VERSION it is possible to specify the MathJax version to be used.
+# Note that the different versions of MathJax have different requirements with
+# regards to the different settings, so it is possible that also other MathJax
+# settings have to be changed when switching between the different MathJax
+# versions.
+# Possible values are: MathJax_2 and MathJax_3.
+# The default value is: MathJax_2.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_VERSION        = MathJax_2
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. For more details about the output format see MathJax
+# version 2 (see:
+# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3
+# (see:
+# http://docs.mathjax.org/en/latest/web/components/output.html).
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility. This is the name for Mathjax version 2, for MathJax version 3
+# this will be translated into chtml), NativeMML (i.e. MathML. Only supported
+# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This
+# is the name for Mathjax version 3, for MathJax version 2 this will be
+# translated into HTML-CSS) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT         = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from https://www.mathjax.org before deployment. The default value is:
+# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2
+# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH        =
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# for MathJax version 2 (see
+# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions):
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# For example for MathJax version 3 (see
+# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html):
+# MATHJAX_EXTENSIONS = ams
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS     =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see:
+# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE       =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE           = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using JavaScript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH    = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see:
+# https://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH        = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see:
+# https://xapian.org/). See the section "External Indexing and Searching" for
+# details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL       =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE        = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID     =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS  =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX         = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when not enabling USE_PDFLATEX the default is latex when enabling
+# USE_PDFLATEX the default is pdflatex and when in the later case latex is
+# chosen this is overwritten by pdflatex. For specific output languages the
+# default can have been set differently, this depends on the implementation of
+# the output language.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME         =
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# Note: This tag is used in the Makefile / make.bat.
+# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file
+# (.tex).
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
+# generate index for LaTeX. In case there is no backslash (\) as first character
+# it will be automatically added in the LaTeX code.
+# Note: This tag is used in the generated output file (.tex).
+# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
+# The default value is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_MAKEINDEX_CMD    = makeindex
+
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE             = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. The package can be specified just
+# by its name or with the correct syntax as to be used with the LaTeX
+# \usepackage command. To get the times font for instance you can specify :
+# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
+# To use the option intlimits with the amsmath package you can specify:
+# EXTRA_PACKAGES=[intlimits]{amsmath}
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES         =
+
+# The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for
+# the generated LaTeX document. The header should contain everything until the
+# first chapter. If it is left blank doxygen will generate a standard header. It
+# is highly recommended to start with a default header using
+# doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty
+# and then modify the file new_header.tex. See also section "Doxygen usage" for
+# information on how to generate the default header that doxygen normally uses.
+#
+# Note: Only use a user-defined header if you know what you are doing!
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. The following
+# commands have a special meaning inside the header (and footer): For a
+# description of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER           =
+
+# The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for
+# the generated LaTeX document. The footer should contain everything after the
+# last chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer. See also section "Doxygen
+# usage" for information on how to generate the default footer that doxygen
+# normally uses. Note: Only use a user-defined footer if you know what you are
+# doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER           =
+
+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# LaTeX style sheets that are included after the standard style sheets created
+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
+# will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_STYLESHEET =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES      =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as
+# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX
+# files. Set this option to YES, to get a higher quality PDF documentation.
+#
+# See also section LATEX_CMD_NAME for selecting the engine.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE        = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES     = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE        = plain
+
+# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_TIMESTAMP        = NO
+
+# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
+# path from which the emoji images will be read. If a relative path is entered,
+# it will be relative to the LATEX_OUTPUT directory. If left blank the
+# LATEX_OUTPUT directory will be used.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EMOJI_DIRECTORY  =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# configuration file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE    =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's configuration file. A template extensions file can be
+# generated using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE    =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION          = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR             =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT             = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING     = YES
+
+# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include
+# namespace members in file scope as well, matching the HTML output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_NS_MEMB_FILE_SCOPE = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK       = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT         = docbook
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures
+# the structure of the code including all documentation. Note that this feature
+# is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO, the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
+# in the source code. If set to NO, only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor. Note that the INCLUDE_PATH is not recursive, so the setting of
+# RECURSIVE has no effect here.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH           =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS  =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED             =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED      =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES               =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE       =
+
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
+# the class index. If set to NO, only the inherited external classes will be
+# listed.
+# The default value is: NO.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS        = YES
+
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES         = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH               =
+
+# If set to YES the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: YES.
+
+HAVE_DOT               = YES
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS        = 0
+
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME           = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH           =
+
+# If the CLASS_GRAPH tag is set to YES (or GRAPH) then doxygen will generate a
+# graph for each documented class showing the direct and indirect inheritance
+# relations. In case HAVE_DOT is set as well dot will be used to draw the graph,
+# otherwise the built-in generator will be used. If the CLASS_GRAPH tag is set
+# to TEXT the direct and indirect inheritance relations will be shown as texts /
+# links.
+# Possible values are: NO, YES, TEXT and GRAPH.
+# The default value is: YES.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies. See also the chapter Grouping
+# in the manual.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK               = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag UML_LOOK is set to YES.
+
+UML_LIMIT_NUM_FIELDS   = 10
+
+# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and
+# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS
+# tag is set to YES, doxygen will add type and arguments for attributes and
+# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen
+# will not generate fields with class member information in the UML graphs. The
+# class diagrams will look similar to the default class diagrams but using UML
+# notation for the relationships.
+# Possible values are: NO, YES and NONE.
+# The default value is: NO.
+# This tag requires that the tag UML_LOOK is set to YES.
+
+DOT_UML_DETAILS        = NO
+
+# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters
+# to display on a single line. If the actual line length exceeds this threshold
+# significantly it will wrapped across multiple lines. Some heuristics are apply
+# to avoid ugly line breaks.
+# Minimum value: 0, maximum value: 1000, default value: 17.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_WRAP_THRESHOLD     = 17
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH          = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command. Disabling a call graph can be
+# accomplished by means of the command \hidecallgraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command. Disabling a caller graph can be
+# accomplished by means of the command \hidecallergraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH           = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH        = YES
+
+# The DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of levels
+# of child directories generated in directory dependency graphs by dot.
+# Minimum value: 1, maximum value: 25, default value: 1.
+# This tag requires that the tag DIRECTORY_GRAPH is set to YES.
+
+DIR_GRAPH_MAX_DEPTH    = 1
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. For an explanation of the image formats see the section
+# output formats in the documentation of the dot tool (Graphviz (see:
+# http://www.graphviz.org/)).
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd,
+# gif, gif:cairo, gif:cairo:gd, gif:gd, gif:gd:gd, svg, png:gd, png:gd:gd,
+# png:cairo, png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
+# png:gdiplus:gdiplus.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT       = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG        = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH               =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS           =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS           =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS           =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file or to the filename of jar file
+# to be used. If left blank, it is assumed PlantUML is not used or called during
+# a preprocessing step. Doxygen will generate a warning when it encounters a
+# \startuml command in this case and will not generate output for the diagram.
+
+PLANTUML_JAR_PATH      =
+
+# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
+# configuration file for plantuml.
+
+PLANTUML_CFG_FILE      =
+
+# When using plantuml, the specified paths are searched for files specified by
+# the !include statement in a plantuml block.
+
+PLANTUML_INCLUDE_PATH  =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# Note: This tag requires that UML_LOOK isn't set, i.e. the doxygen internal
+# graphical representation for inheritance and collaboration diagrams is used.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate
+# files that are used to generate the various graphs.
+#
+# Note: This setting is not only used for dot files but also for msc temporary
+# files.
+# The default value is: YES.
+
+DOT_CLEANUP            = YES
diff --git a/HOW_TO_MAINTAIN.rst b/HOW_TO_MAINTAIN.rst
new file mode 100644
index 0000000..2dae802
--- /dev/null
+++ b/HOW_TO_MAINTAIN.rst
@@ -0,0 +1,2 @@
+
+This documentation has been replaced by docs/maintaining.md. Please refer to the new file or read it online.
\ No newline at end of file
diff --git a/HOW_TO_RELEASE.rst b/HOW_TO_RELEASE.rst
new file mode 100644
index 0000000..c5b7986
--- /dev/null
+++ b/HOW_TO_RELEASE.rst
@@ -0,0 +1 @@
+This documentation has been replaced by docs/maintaining.md. Please refer to the new file or read it online.
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..e82fd21
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,368 @@
+Installation Instructions
+*************************
+
+   Copyright (C) 1994-1996, 1999-2002, 2004-2017, 2020-2021 Free
+Software Foundation, Inc.
+
+   Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved.  This file is offered as-is,
+without warranty of any kind.
+
+Basic Installation
+==================
+
+   Briefly, the shell command './configure && make && make install'
+should configure, build, and install this package.  The following
+more-detailed instructions are generic; see the 'README' file for
+instructions specific to this package.  Some packages provide this
+'INSTALL' file but do not implement all of the features documented
+below.  The lack of an optional feature in a given package is not
+necessarily a bug.  More recommendations for GNU packages can be found
+in *note Makefile Conventions: (standards)Makefile Conventions.
+
+   The 'configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a 'Makefile' in each directory of the package.
+It may also create one or more '.h' files containing system-dependent
+definitions.  Finally, it creates a shell script 'config.status' that
+you can run in the future to recreate the current configuration, and a
+file 'config.log' containing compiler output (useful mainly for
+debugging 'configure').
+
+   It can also use an optional file (typically called 'config.cache' and
+enabled with '--cache-file=config.cache' or simply '-C') that saves the
+results of its tests to speed up reconfiguring.  Caching is disabled by
+default to prevent problems with accidental use of stale cache files.
+
+   If you need to do unusual things to compile the package, please try
+to figure out how 'configure' could check whether to do them, and mail
+diffs or instructions to the address given in the 'README' so they can
+be considered for the next release.  If you are using the cache, and at
+some point 'config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+   The file 'configure.ac' (or 'configure.in') is used to create
+'configure' by a program called 'autoconf'.  You need 'configure.ac' if
+you want to change it or regenerate 'configure' using a newer version of
+'autoconf'.
+
+   The simplest way to compile this package is:
+
+  1. 'cd' to the directory containing the package's source code and type
+     './configure' to configure the package for your system.
+
+     Running 'configure' might take a while.  While running, it prints
+     some messages telling which features it is checking for.
+
+  2. Type 'make' to compile the package.
+
+  3. Optionally, type 'make check' to run any self-tests that come with
+     the package, generally using the just-built uninstalled binaries.
+
+  4. Type 'make install' to install the programs and any data files and
+     documentation.  When installing into a prefix owned by root, it is
+     recommended that the package be configured and built as a regular
+     user, and only the 'make install' phase executed with root
+     privileges.
+
+  5. Optionally, type 'make installcheck' to repeat any self-tests, but
+     this time using the binaries in their final installed location.
+     This target does not install anything.  Running this target as a
+     regular user, particularly if the prior 'make install' required
+     root privileges, verifies that the installation completed
+     correctly.
+
+  6. You can remove the program binaries and object files from the
+     source code directory by typing 'make clean'.  To also remove the
+     files that 'configure' created (so you can compile the package for
+     a different kind of computer), type 'make distclean'.  There is
+     also a 'make maintainer-clean' target, but that is intended mainly
+     for the package's developers.  If you use it, you may have to get
+     all sorts of other programs in order to regenerate files that came
+     with the distribution.
+
+  7. Often, you can also type 'make uninstall' to remove the installed
+     files again.  In practice, not all packages have tested that
+     uninstallation works correctly, even though it is required by the
+     GNU Coding Standards.
+
+  8. Some packages, particularly those that use Automake, provide 'make
+     distcheck', which can by used by developers to test that all other
+     targets like 'make install' and 'make uninstall' work correctly.
+     This target is generally not run by end users.
+
+Compilers and Options
+=====================
+
+   Some systems require unusual options for compilation or linking that
+the 'configure' script does not know about.  Run './configure --help'
+for details on some of the pertinent environment variables.
+
+   You can give 'configure' initial values for configuration parameters
+by setting variables in the command line or in the environment.  Here is
+an example:
+
+     ./configure CC=c99 CFLAGS=-g LIBS=-lposix
+
+   *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+   You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you can use GNU 'make'.  'cd' to the
+directory where you want the object files and executables to go and run
+the 'configure' script.  'configure' automatically checks for the source
+code in the directory that 'configure' is in and in '..'.  This is known
+as a "VPATH" build.
+
+   With a non-GNU 'make', it is safer to compile the package for one
+architecture at a time in the source code directory.  After you have
+installed the package for one architecture, use 'make distclean' before
+reconfiguring for another architecture.
+
+   On MacOS X 10.5 and later systems, you can create libraries and
+executables that work on multiple system types--known as "fat" or
+"universal" binaries--by specifying multiple '-arch' options to the
+compiler but only a single '-arch' option to the preprocessor.  Like
+this:
+
+     ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+                 CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+                 CPP="gcc -E" CXXCPP="g++ -E"
+
+   This is not guaranteed to produce working output in all cases, you
+may have to build one architecture at a time and combine the results
+using the 'lipo' tool if you have problems.
+
+Installation Names
+==================
+
+   By default, 'make install' installs the package's commands under
+'/usr/local/bin', include files under '/usr/local/include', etc.  You
+can specify an installation prefix other than '/usr/local' by giving
+'configure' the option '--prefix=PREFIX', where PREFIX must be an
+absolute file name.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+pass the option '--exec-prefix=PREFIX' to 'configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
+
+   In addition, if you use an unusual directory layout you can give
+options like '--bindir=DIR' to specify different values for particular
+kinds of files.  Run 'configure --help' for a list of the directories
+you can set and what kinds of files go in them.  In general, the default
+for these options is expressed in terms of '${prefix}', so that
+specifying just '--prefix' will affect all of the other directory
+specifications that were not explicitly provided.
+
+   The most portable way to affect installation locations is to pass the
+correct locations to 'configure'; however, many packages provide one or
+both of the following shortcuts of passing variable assignments to the
+'make install' command line to change installation locations without
+having to reconfigure or recompile.
+
+   The first method involves providing an override variable for each
+affected directory.  For example, 'make install
+prefix=/alternate/directory' will choose an alternate location for all
+directory configuration variables that were expressed in terms of
+'${prefix}'.  Any directories that were specified during 'configure',
+but not in terms of '${prefix}', must each be overridden at install time
+for the entire installation to be relocated.  The approach of makefile
+variable overrides for each directory variable is required by the GNU
+Coding Standards, and ideally causes no recompilation.  However, some
+platforms have known limitations with the semantics of shared libraries
+that end up requiring recompilation when using this method, particularly
+noticeable in packages that use GNU Libtool.
+
+   The second method involves providing the 'DESTDIR' variable.  For
+example, 'make install DESTDIR=/alternate/directory' will prepend
+'/alternate/directory' before all installation names.  The approach of
+'DESTDIR' overrides is not required by the GNU Coding Standards, and
+does not work on platforms that have drive letters.  On the other hand,
+it does better at avoiding recompilation issues, and works well even
+when some directory options were not specified in terms of '${prefix}'
+at 'configure' time.
+
+Optional Features
+=================
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving 'configure' the
+option '--program-prefix=PREFIX' or '--program-suffix=SUFFIX'.
+
+   Some packages pay attention to '--enable-FEATURE' options to
+'configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to '--with-PACKAGE' options, where PACKAGE
+is something like 'gnu-as' or 'x' (for the X Window System).  The
+'README' should mention any '--enable-' and '--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, 'configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the 'configure' options '--x-includes=DIR' and
+'--x-libraries=DIR' to specify their locations.
+
+   Some packages offer the ability to configure how verbose the
+execution of 'make' will be.  For these packages, running './configure
+--enable-silent-rules' sets the default to minimal output, which can be
+overridden with 'make V=1'; while running './configure
+--disable-silent-rules' sets the default to verbose, which can be
+overridden with 'make V=0'.
+
+Particular systems
+==================
+
+   On HP-UX, the default C compiler is not ANSI C compatible.  If GNU CC
+is not installed, it is recommended to use the following options in
+order to use an ANSI C compiler:
+
+     ./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
+
+and if that doesn't work, install pre-built binaries of GCC for HP-UX.
+
+   HP-UX 'make' updates targets which have the same timestamps as their
+prerequisites, which makes it generally unusable when shipped generated
+files such as 'configure' are involved.  Use GNU 'make' instead.
+
+   On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
+parse its '<wchar.h>' header file.  The option '-nodtk' can be used as a
+workaround.  If GNU CC is not installed, it is therefore recommended to
+try
+
+     ./configure CC="cc"
+
+and if that doesn't work, try
+
+     ./configure CC="cc -nodtk"
+
+   On Solaris, don't put '/usr/ucb' early in your 'PATH'.  This
+directory contains several dysfunctional programs; working variants of
+these programs are available in '/usr/bin'.  So, if you need '/usr/ucb'
+in your 'PATH', put it _after_ '/usr/bin'.
+
+   On Haiku, software installed for all users goes in '/boot/common',
+not '/usr/local'.  It is recommended to use the following options:
+
+     ./configure --prefix=/boot/common
+
+Specifying the System Type
+==========================
+
+   There may be some features 'configure' cannot figure out
+automatically, but needs to determine by the type of machine the package
+will run on.  Usually, assuming the package is built to be run on the
+_same_ architectures, 'configure' can figure that out, but if it prints
+a message saying it cannot guess the machine type, give it the
+'--build=TYPE' option.  TYPE can either be a short name for the system
+type, such as 'sun4', or a canonical name which has the form:
+
+     CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+     OS
+     KERNEL-OS
+
+   See the file 'config.sub' for the possible values of each field.  If
+'config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+   If you are _building_ compiler tools for cross-compiling, you should
+use the option '--target=TYPE' to select the type of system they will
+produce code for.
+
+   If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with '--host=TYPE'.
+
+Sharing Defaults
+================
+
+   If you want to set default values for 'configure' scripts to share,
+you can create a site shell script called 'config.site' that gives
+default values for variables like 'CC', 'cache_file', and 'prefix'.
+'configure' looks for 'PREFIX/share/config.site' if it exists, then
+'PREFIX/etc/config.site' if it exists.  Or, you can set the
+'CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all 'configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+   Variables not defined in a site shell script can be set in the
+environment passed to 'configure'.  However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost.  In order to avoid this problem, you should set
+them in the 'configure' command line, using 'VAR=value'.  For example:
+
+     ./configure CC=/usr/local2/bin/gcc
+
+causes the specified 'gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+Unfortunately, this technique does not work for 'CONFIG_SHELL' due to an
+Autoconf limitation.  Until the limitation is lifted, you can use this
+workaround:
+
+     CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+'configure' Invocation
+======================
+
+   'configure' recognizes the following options to control how it
+operates.
+
+'--help'
+'-h'
+     Print a summary of all of the options to 'configure', and exit.
+
+'--help=short'
+'--help=recursive'
+     Print a summary of the options unique to this package's
+     'configure', and exit.  The 'short' variant lists options used only
+     in the top level, while the 'recursive' variant lists options also
+     present in any nested packages.
+
+'--version'
+'-V'
+     Print the version of Autoconf used to generate the 'configure'
+     script, and exit.
+
+'--cache-file=FILE'
+     Enable the cache: use and save the results of the tests in FILE,
+     traditionally 'config.cache'.  FILE defaults to '/dev/null' to
+     disable caching.
+
+'--config-cache'
+'-C'
+     Alias for '--cache-file=config.cache'.
+
+'--quiet'
+'--silent'
+'-q'
+     Do not print messages saying which checks are being made.  To
+     suppress all normal output, redirect it to '/dev/null' (any error
+     messages will still be shown).
+
+'--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     'configure' can determine that directory automatically.
+
+'--prefix=DIR'
+     Use DIR as the installation prefix.  *note Installation Names:: for
+     more details, including other options available for fine-tuning the
+     installation locations.
+
+'--no-create'
+'-n'
+     Run the configure checks, but stop before creating any output
+     files.
+
+'configure' also accepts some other, not widely useful, options.  Run
+'configure --help' for more details.
diff --git a/lsof.8 b/Lsof.8
similarity index 97%
rename from lsof.8
rename to Lsof.8
index 5b084c3..995e80c 100644
--- a/lsof.8
+++ b/Lsof.8
@@ -1,10 +1,7 @@
-.lf 1 stdin
-.lf 1 ././version
-.ds VN 4.95.0
-.lf 2 stdin
+.so ./version
 .TH LSOF 8 Revision-\*(VN
-\" Register )P is used neither by this file nor any groff macro.  However,
-\" some versions of nroff require it.
+.\" Register )P is used neither by this file nor any groff macro.  However,
+.\" some versions of nroff require it.
 .if !\n(.g \{\
 .   if !\n()P .nr )P 1v
 .\}
@@ -13,7 +10,7 @@ lsof \- list open files
 .SH SYNOPSIS
 .B lsof
 [
-.B \-?abChlnNOPQRtUvVX
+.B \-?abChHlnNOPQRtUvVX
 ] [
 .BI \-A " A"
 ] [
@@ -77,12 +74,7 @@ revision \*(VN lists on its standard output file information about files
 opened by processes for the following UNIX dialects:
 .PP
 .nf
-.lf 1 ././00DIALECTS
-	Apple Darwin 9 and Mac OS X 10.[567]
-	FreeBSD 8.[234], 9.0 and 1[012].0 for AMD64-based systems
-	Linux 2.1.72 and above for x86-based systems
-	Solaris 9, 10 and 11
-.lf 78 stdin
+.so ./00DIALECTS
 .fi
 .PP
 (See the
@@ -658,10 +650,10 @@ POSIX Message Queueue implementation in Linux, and Linux eventfd
 should be displayed with endpoint information and the files of the endpoints should also be displayed.
 .IP
 Note 1: UNIX socket file endpoint information is only available when the
-compile flags line of
+features enabled line of
 .B \-v
-output contains HASUXSOCKEPT, and psudoterminal endpoint information is only
-available when the compile flags line contains HASPTYEPT.
+output contains uxsockept, and psudoterminal endpoint information is only
+available when the features enabled line contains ptyept.
 .IP
 Note 2: POSIX Message Queue file endpoint information is only available when mqueue
 file system is mounted.
@@ -687,10 +679,10 @@ is a slave device's minor device number; and
 and
 .I mode
 are the same as with pipe endpoint information.
-Note: psudoterminal endpoint information is only available when the compile
-flags line of
-.B \-V
-output contains HASPTYEPT. In addition, this feature works on Linux kernels above 4.13.0.
+Note: psudoterminal endpoint information is only available when the features
+enabled line of
+.B \-v
+output contains ptyept. In addition, this feature works on Linux kernels above 4.13.0.
 .IP
 UNIX socket file endpoint information is displayed in the NAME column
 in the form
@@ -706,14 +698,14 @@ and
 .I mode
 are the same as with pipe endpoint information.
 Note: UNIX socket file endpoint information is available only when the
-compile flags line of
+features enabled line of
 .B \-v
-output contains HASUXSOCKEPT.
+output contains uxsockept.
 .IP
 INET socket file endpoint information is inserted to the value at the
-NAME column in th form
+NAME column in the form
 .br
-...`` \-> \fIPID,cmd,FDmode\fP'' ..., where
+`` \-> \fIPID,cmd,FDmode\fP'', where
 .I "PID, cmd, FD"
 and
 .I mode
@@ -905,6 +897,9 @@ The
 option also enables the output display of PGID numbers.
 When specified without a PGID set that's all it does.
 .TP \w'names'u+4
+.B \-H
+directs lsof to print human readable sizes, e.g. 123.4K 456.7M.
+.TP \w'names'u+4
 .BI \-i " [i]"
 selects the listing of files any of whose Internet address
 matches the address specified in \fIi\fP.
@@ -975,8 +970,8 @@ where:
 .br
 		applies to all IP versions.
 .br
-	\fIprotocol\fP is a protocol name \- \fBTCP\fP, \fBUDP\fP
-.br		or \fBUDPLITE\fP.
+	\fIprotocol\fP is a protocol name \- \fBTCP\fP, \fBUDP\fP or \fBUDPLITE\fP.
+.br
 .br
 	\fIhostname\fP is an Internet host name.  Unless a
 .br
@@ -1406,7 +1401,7 @@ and take effect before other selection criteria are applied.
 .TP \w'names'u+4
 .B \-P
 inhibits the conversion of port numbers to port
-names for network files.
+names for network files (the mapping is commonly learned from /etc/services).
 Inhibiting the conversion may make
 .I lsof
 run a little faster.
@@ -2520,26 +2515,38 @@ is the File Descriptor number of the file or:
 	\fBcwd\fP	current working directory;
 .br
 	\fBL\fInn\fR	library references (AIX);
+.br
+	\fBctty\fR	character tty;
+.br
+	\fBDEL\fR	deleted file;
 .br
 	\fBerr\fR	FD information error (see NAME column);
+.br
+	\fBfp.\fR	Fileport (Darwin);
 .br
 	\fBjld\fR	jail directory (FreeBSD);
 .br
 	\fBltx\fP	shared library text (code and data);
 .br
-	\fBMxx\fP	hex memory\-mapped type number xx.
+	\fBM\fIxx\fR	hex memory\-mapped type number xx.
 .br
 	\fBm86\fP	DOS Merge mapped file;
 .br
 	\fBmem\fP	memory\-mapped file;
 .br
 	\fBmmap\fP	memory\-mapped device;
+.br
+	\fBNOFD\fP	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;
 .br
 	\fBpd\fP	parent directory;
+.br
+	\fBR\fInn\fR	unknown pregion number (HP-UX);
 .br
 	\fBrtd\fP	root directory;
 .br
-	\fBtr\fR	kernel trace file (OpenBSD);
+	\fBtwd\fP	per task current working directory;
 .br
 	\fBtxt\fP	program text (code and data);
 .br
@@ -2580,8 +2587,7 @@ the type of lock applied to the file:
 .br
 	\fBU\fP for a lock of unknown type;
 .br
-	\fBx\fP for an SCO OpenServer Xenix lock on part
-	of the file;
+	\fBx\fP for an SCO OpenServer Xenix lock on part of the file;
 .br
 	\fBX\fP for an SCO OpenServer Xenix lock on the entire file;
 .br
@@ -2592,31 +2598,51 @@ See the
 section for more information on the lock information character.
 .IP
 The FD column contents constitutes a single field for parsing in
-post\-processing scripts.
+post\-processing scripts. FD numbers larger than 9999 are abbreviated
+to a ``*'' followed by the last three digits. E.g., 10001 appears as
+``*001''
 .TP
 TYPE
-is the type of the node associated with the file \- e.g., GDIR, GREG,
-VDIR, VREG, etc.
+is the type of the node associated with the file \- e.g., VDIR, VREG, etc.
 .IP
-or ``IPv4'' for an IPv4 socket;
+or ``ax25'' for a Linux AX.25 socket;
 .IP
-or ``IPv6'' for an open IPv6 network file \- even if its address is
-IPv4, mapped in an IPv6 address;
+or ``a_inode'' for anonymous inode;
 .IP
-or ``ax25'' for a Linux AX.25 socket;
+or ``icmp'' for an ICMP socket;
 .IP
 or ``inet'' for an Internet domain socket;
 .IP
+or ``ipx'' for an IPX socket;
+.IP
+or ``key'' for an internal key management socket;
+.IP
 or ``lla'' for a HP\-UX link level access file;
 .IP
+or ``ndrv'' for a net driver socket;
+.IP
+or ``netlink'' for a netlink socket;
+.IP
+or ``pack'' for a packet socket;
+.IP
+or ``ppp'' for a PPP socket;
+.IP
+or ``raw'' for a raw socket;
+.IP
+or ``raw6'' for a raw IPv6 socket;
+.IP
 or ``rte'' for an AF_ROUTE socket;
 .IP
 or ``sock'' for a socket of unknown domain;
 .IP
+or ``systm'' for a system socket;
+.IP
 or ``unix'' for a UNIX domain socket;
 .IP
 or ``x.25'' for an HP\-UX x.25 socket;
 .IP
+or ``ATALK'' for an AppleTalk socket;
+.IP
 or ``BLK'' for a block special file;
 .IP
 or ``CHR'' for a character special file;
@@ -2627,8 +2653,17 @@ or ``DIR'' for a directory;
 .IP
 or ``DOOR'' for a VDOOR file;
 .IP
+or ``EVENTFD'' for an eventfd;
+.IP
 or ``FIFO'' for a FIFO special file;
 .IP
+or ``FSEVENTS'' for fsevents;
+.IP
+or ``IPv4'' for an IPv4 socket;
+.IP
+or ``IPv6'' for an open IPv6 network file \- even if its address is
+IPv4, mapped in an IPv6 address;
+.IP
 or ``KQUEUE'' for a BSD style kernel event queue file;
 .IP
 or ``LINK'' for a symbolic link file;
@@ -2637,10 +2672,6 @@ or ``MPB'' for a multiplexed block file;
 .IP
 or ``MPC'' for a multiplexed character file;
 .IP
-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;
-.IP
 or ``PAS'' for a
 .I /proc/as
 file;
@@ -2747,6 +2778,10 @@ or ``PMAP'' for a
 .I /proc
 map file (\fImap\fP);
 .IP
+or ``PMPS'' for a
+.I /proc/maps
+file;
+.IP
 or ``PMEM'' for a
 .I /proc
 memory image file;
@@ -2785,6 +2820,8 @@ or ``PRMP'' for a
 .I /proc/rmap
 file;
 .IP
+or ``PROCDSC'' for a processor descriptor;
+.IP
 or ``PRTD'' for a
 .I /proc
 root directory;
@@ -2825,10 +2862,28 @@ file;
 .IP
 or ``REG'' for a regular file;
 .IP
+or ``SHM'' for a shared memory file;
+.IP
 or ``SMT'' for a shared memory transport file;
 .IP
+or ``STR'' for streams;
+.IP
 or ``STSO'' for a stream socket;
 .IP
+or ``UNKN'' for an unknown file;
+.IP
+or ``UNKNcwd'' for unknown current working directory;
+.IP
+or ``UNKNdel'' for unknown deleted file;
+.IP
+or ``UNKNfd'' for unknown file descriptor;
+.IP
+or ``UNKNmem'' for unknown memory-mapped file;
+.IP
+or ``UNKNrtd'' for unknown root directory;
+.IP
+or ``UNKNtxt'' for unknown program text;
+.IP
 or ``UNNM'' for an unnamed type file;
 .IP
 or ``XNAM'' for an OpenServer Xenix special file of unknown type;
@@ -2837,6 +2892,8 @@ or ``XSEM'' for an OpenServer Xenix semaphore file;
 .IP
 or ``XSD'' for an OpenServer Xenix shared data file;
 .IP
+or ``UNSP'' for an unsupported file;
+.IP
 or the four type number octets if the corresponding name isn't known.
 .TP
 FILE\-ADDR
@@ -2952,7 +3009,7 @@ the following table:
 .IP
 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
+see the common.h header file for a list showing the correspondence
 between the above short-hand names and the header file definitions;
 .IP
 the second list (after the semicolon) may contain short-hand names
@@ -3063,6 +3120,12 @@ and
 .B \-s
 options are mutually exclusive; they can't both be specified.
 .IP
+If the
+.B \-H
+option is specified,
+.I lsof
+displays file size in human readable form.
+.IP
 For files that don't have a fixed size \- e.g., don't reside
 on a disk device \-
 .I lsof
@@ -3749,9 +3812,6 @@ can report path name components for these dialects:
 	HP\-UX
 	Linux
 	NetBSD
-	NEXTSTEP
-	OpenBSD
-	OPENSTEP
 	SCO OpenServer
 	SCO|Caldera UnixWare
 	Solaris
@@ -3763,6 +3823,7 @@ can't report path name components for these dialects:
 .PP
 .nf
 	AIX
+	OpenBSD
 .fi
 .PP
 If you want to know why
@@ -3916,9 +3977,7 @@ and be allowed to surrender setgid permission.
 	HP\-UX 11.00
 	NetBSD 1.[456], 2.x and 3.x for Alpha, x86, and SPARC-based
 	    systems
-	NEXTSTEP 3.[13] for NEXTSTEP architectures
 	OpenBSD 2.[89] and 3.[0\-9] for x86-based systems
-	OPENSTEP 4.x
 	SCO OpenServer Release 5.0.6 for x86-based systems
 	SCO|Caldera UnixWare 7.1.4 for x86-based systems
 	Solaris 2.6, 8, 9 and 10
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..fbe28fa
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,224 @@
+# liblsof
+liblsof_la_SOURCES = lib/ckkv.c lib/cvfs.c lib/dvch.c lib/fino.c lib/isfn.c lib/lkud.c lib/lsof.c lib/misc.c lib/node.c lib/pdvn.c lib/prfp.c lib/print.c lib/proc.c lib/ptti.c lib/rdev.c lib/rnmt.c lib/rmnt.c lib/rnam.c lib/rnch.c lib/rnmh.c
+liblsof_la_SOURCES += lib/common.h lib/proto.h lib/hash.h
+
+if INSTALL_LIBLSOF
+lib_LTLIBRARIES = liblsof.la
+include_HEADERS = include/lsof.h include/lsof_fields.h
+else
+noinst_LTLIBRARIES = liblsof.la
+endif
+
+# Hide internal functions
+AM_CFLAGS = -fvisibility=hidden
+
+DIALECT_ROOT = $(top_srcdir)/lib/dialects
+DIALECT_PATH = $(DIALECT_ROOT)/$(LSOF_DIALECT_DIR)
+
+# Dialect specific sources
+if LINUX
+liblsof_la_SOURCES += lib/dialects/linux/dfile.c \
+		lib/dialects/linux/dmnt.c \
+		lib/dialects/linux/dnode.c \
+		lib/dialects/linux/dproc.c \
+		lib/dialects/linux/dsock.c \
+		lib/dialects/linux/dstore.c \
+		lib/dialects/linux/dlsof.h \
+		lib/dialects/linux/dproto.h \
+		lib/dialects/linux/machine.h
+endif
+
+if DARWIN
+liblsof_la_SOURCES += lib/dialects/darwin/ddev.c \
+		lib/dialects/darwin/dfile.c \
+		lib/dialects/darwin/dmnt.c \
+		lib/dialects/darwin/dproc.c \
+		lib/dialects/darwin/dsock.c \
+		lib/dialects/darwin/dstore.c \
+		lib/dialects/darwin/dlsof.h \
+		lib/dialects/darwin/dproto.h \
+		lib/dialects/darwin/machine.h
+endif
+
+if FREEBSD
+liblsof_la_SOURCES += lib/dialects/freebsd/dmnt.c \
+		lib/dialects/freebsd/dnode.c \
+		lib/dialects/freebsd/dproc.c \
+		lib/dialects/freebsd/dsock.c \
+		lib/dialects/freebsd/dstore.c \
+		lib/dialects/freebsd/dlsof.h \
+		lib/dialects/freebsd/dproto.h \
+		lib/dialects/freebsd/machine.h
+endif
+
+if NETBSD
+liblsof_la_SOURCES += lib/dialects/netbsd/dmnt.c \
+		lib/dialects/netbsd/dnode.c \
+		lib/dialects/netbsd/dproc.c \
+		lib/dialects/netbsd/dsock.c \
+		lib/dialects/netbsd/dstore.c \
+		lib/dialects/netbsd/dlsof.h \
+		lib/dialects/netbsd/dproto.h \
+		lib/dialects/netbsd/machine.h
+endif
+
+if OPENBSD
+liblsof_la_SOURCES += lib/dialects/openbsd/dfile.c \
+		lib/dialects/openbsd/dmnt.c \
+		lib/dialects/openbsd/dnode.c \
+		lib/dialects/openbsd/dproc.c \
+		lib/dialects/openbsd/dsock.c \
+		lib/dialects/openbsd/dstore.c \
+		lib/dialects/openbsd/dlsof.h \
+		lib/dialects/openbsd/dproto.h \
+		lib/dialects/openbsd/machine.h
+endif
+
+if SOLARIS
+liblsof_la_SOURCES += lib/dialects/sun/ddev.c \
+		lib/dialects/sun/dfile.c \
+		lib/dialects/sun/dmnt.c \
+		lib/dialects/sun/dnode.c \
+		lib/dialects/sun/dproc.c \
+		lib/dialects/sun/dsock.c \
+		lib/dialects/sun/dstore.c \
+		lib/dialects/sun/dlsof.h \
+		lib/dialects/sun/dproto.h \
+		lib/dialects/sun/machine.h
+endif
+
+if AIX
+liblsof_la_SOURCES += lib/dialects/aix/ddev.c \
+		lib/dialects/aix/dfile.c \
+		lib/dialects/aix/dmnt.c \
+		lib/dialects/aix/dnode.c \
+		lib/dialects/aix/dnode2.c \
+		lib/dialects/aix/dproc.c \
+		lib/dialects/aix/dsock.c \
+		lib/dialects/aix/dstore.c \
+		lib/dialects/aix/dlsof.h \
+		lib/dialects/aix/dproto.h \
+		lib/dialects/aix/machine.h
+endif
+
+# Binary
+bin_PROGRAMS = lsof
+
+lsof_SOURCES = src/arg.c src/main.c src/print.c src/ptti.c src/store.c src/usage.c src/util.c
+lsof_SOURCES += src/cli.h
+
+if LINUX
+lsof_SOURCES += src/dialects/linux/dprint.c
+endif
+if DARWIN
+lsof_SOURCES += src/dialects/darwin/dprint.c
+endif
+# TODO: link to dynamic library instead after internal functions are no longer used
+lsof_SOURCES += $(liblsof_la_SOURCES)
+#lsof_LDADD = liblsof.la
+
+liblsof_la_CPPFLAGS = -I$(DIALECT_PATH) -Iautotools -DAUTOTOOLS -I$(top_srcdir)/lib -I$(top_srcdir)/include
+lsof_CPPFLAGS = -I$(DIALECT_PATH) -Iautotools -DAUTOTOOLS -I$(top_srcdir)/lib -I$(top_srcdir)/include -I$(top_srcdir)/src
+
+# Testing scripts
+AM_TESTS_ENVIRONMENT = export LSOF_DIALECT_DIR=$(LSOF_DIALECT_DIR); export LSOF_DIALECT=$(LSOF_DIALECT);
+EXTRA_DIST =
+# Dialect neutral
+DIALECT_NEUTRAL_TESTS = tests/case-00-hello.bash \
+	tests/case-01-version.bash \
+	tests/case-20-exit-status.bash \
+	tests/case-20-fd-only-inclusion.bash \
+	tests/case-20-handle-missing-files.bash \
+	tests/case-20-offset-field.bash \
+	tests/case-20-repeat-count.bash \
+	tests/case-21-exit-Q-status.bash \
+	tests/case-22-empty-process-name.bash
+TESTS = $(DIALECT_NEUTRAL_TESTS)
+EXTRA_DIST += $(DIALECT_NEUTRAL_TESTS) \
+	tests/case-13-classic.bash \
+	tests/case-14-classic-opt.bash \
+	tests/common.bash
+
+# Dialect specific
+check_PROGRAMS =
+
+# Linux
+LINUX_TESTS = lib/dialects/linux/tests/case-10-mqueue.bash \
+	lib/dialects/linux/tests/case-10-ux-socket-state.bash \
+	lib/dialects/linux/tests/case-20-epoll.bash \
+	lib/dialects/linux/tests/case-20-eventfd-endpoint.bash \
+	lib/dialects/linux/tests/case-20-inet6-ffffffff-handling.bash \
+	lib/dialects/linux/tests/case-20-inet6-socket-endpoint.bash \
+	lib/dialects/linux/tests/case-20-inet-socket-endpoint.bash \
+	lib/dialects/linux/tests/case-20-mmap.bash \
+	lib/dialects/linux/tests/case-20-mqueue-endpoint.bash \
+	lib/dialects/linux/tests/case-20-open-flags-cx.bash \
+	lib/dialects/linux/tests/case-20-open-flags-path.bash \
+	lib/dialects/linux/tests/case-20-open-flags-tmpf.bash \
+	lib/dialects/linux/tests/case-20-pidfd-pid.bash \
+	lib/dialects/linux/tests/case-20-pipe-endpoint.bash \
+	lib/dialects/linux/tests/case-20-pipe-no-close-endpoint.bash \
+	lib/dialects/linux/tests/case-20-pty-endpoint.bash \
+	lib/dialects/linux/tests/case-20-ux-socket-endpoint.bash \
+	lib/dialects/linux/tests/case-20-ux-socket-endpoint-unaccepted.bash
+EXTRA_DIST += $(LINUX_TESTS) lib/dialects/linux/tests/Makefile lib/dialects/linux/tests/case-00-linux-hello.bash
+if LINUX
+check_PROGRAMS += lib/dialects/linux/tests/epoll \
+	lib/dialects/linux/tests/eventfd \
+	lib/dialects/linux/tests/mmap \
+	lib/dialects/linux/tests/mq_fork \
+	lib/dialects/linux/tests/mq_open \
+	lib/dialects/linux/tests/open_with_flags \
+	lib/dialects/linux/tests/pidfd \
+	lib/dialects/linux/tests/pipe \
+	lib/dialects/linux/tests/pty \
+	lib/dialects/linux/tests/ux
+lib_dialects_linux_tests_mq_fork_LDADD = -lrt
+lib_dialects_linux_tests_mq_open_LDADD = -lrt
+
+TESTS += $(LINUX_TESTS)
+endif
+
+# Testing programs
+TESTS += tests/LTbasic tests/LTbigf tests/LTdnlc tests/LTlock tests/LTnfs tests/LTnlink tests/LTsock tests/LTszoff tests/LTunix
+
+check_PROGRAMS += tests/LTbasic tests/LTbigf tests/LTdnlc tests/LTlock tests/LTnfs tests/LTnlink tests/LTsock tests/LTszoff tests/LTunix
+tests_LTbasic_SOURCES = tests/LTbasic.c tests/LTlib.c
+tests_LTbasic_CFLAGS = @LSOF_TEST_CFLAGS@ -I$(top_srcdir)/include
+tests_LTbigf_SOURCES = tests/LTbigf.c tests/LTlib.c
+tests_LTbigf_CFLAGS = @LSOF_TEST_CFLAGS@ -I$(top_srcdir)/include
+tests_LTdnlc_SOURCES = tests/LTdnlc.c tests/LTlib.c
+tests_LTdnlc_CFLAGS = @LSOF_TEST_CFLAGS@ -I$(top_srcdir)/include
+tests_LTlock_SOURCES = tests/LTlock.c tests/LTlib.c
+tests_LTlock_CFLAGS = @LSOF_TEST_CFLAGS@ -I$(top_srcdir)/include
+tests_LTnfs_SOURCES = tests/LTnfs.c tests/LTlib.c
+tests_LTnfs_CFLAGS = @LSOF_TEST_CFLAGS@ -I$(top_srcdir)/include
+tests_LTnlink_SOURCES = tests/LTnlink.c tests/LTlib.c
+tests_LTnlink_CFLAGS = @LSOF_TEST_CFLAGS@ -I$(top_srcdir)/include
+tests_LTsock_SOURCES = tests/LTsock.c tests/LTlib.c
+tests_LTsock_CFLAGS = @LSOF_TEST_CFLAGS@ -I$(top_srcdir)/include
+tests_LTszoff_SOURCES = tests/LTszoff.c tests/LTlib.c
+tests_LTszoff_CFLAGS = @LSOF_TEST_CFLAGS@ -I$(top_srcdir)/include
+tests_LTunix_SOURCES = tests/LTunix.c tests/LTlib.c
+tests_LTunix_CFLAGS = @LSOF_TEST_CFLAGS@ -I$(top_srcdir)/include
+
+TESTS += tests/LTbasic2
+check_PROGRAMS += tests/LTbasic2
+tests_LTbasic2_CFLAGS = -I$(top_srcdir)/include
+tests_LTbasic2_LDADD = liblsof.la
+
+# Documentation
+EXTRA_DIST += 00.README.FIRST 00CREDITS 00DCACHE 00DIALECTS 00DIST 00FAQ 00LSOF-L 00MANIFEST 00PORTING 00QUICKSTART 00README 00TEST 00XCONFIG
+# Testing
+EXTRA_DIST += tests/00README tests/TestDB tests/CkTestDB tests/Makefile tests/LsofTest.h check.bash
+
+# Manpages
+lsof.man: Lsof.8 version 00DIALECTS
+	soelim < Lsof.8 > $@
+man8_MANS = lsof.man
+EXTRA_DIST += Lsof.8
+# Fix distcheck error
+clean-local:
+	rm -rf lsof.man
+distclean-local:
+	rm -rf lockf_owner.h lockf.h
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..e69de29
diff --git a/README b/README
new file mode 120000
index 0000000..42061c0
--- /dev/null
+++ b/README
@@ -0,0 +1 @@
+README.md
\ No newline at end of file
diff --git a/README.md b/README.md
index 54d1955..fc64e91 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,14 @@
-[![Travis CI Linux Build Status](https://travis-ci.org/lsof-org/lsof.svg?branch=master)](https://travis-ci.org/lsof-org/lsof)
-[![Coveralls Linux Coverage Status on Travis CI](https://coveralls.io/repos/github/lsof-org/lsof/badge.svg?branch=master)](https://coveralls.io/github/lsof-org/lsof?branch=master)
+[![Circle CI](https://circleci.com/gh/lsof-org/lsof.svg?style=svg)](https://circleci.com/gh/lsof-org/lsof)
+[![Cirrus CI](https://img.shields.io/cirrus/github/lsof-org/lsof)](https://cirrus-ci.com/github/lsof-org/lsof)
+[![builds.sr.ht status](https://builds.sr.ht/~jiegec/lsof.svg)](https://builds.sr.ht/~jiegec/lsof?)
+[![Read the Docs](https://readthedocs.org/projects/lsof/badge/?version=latest)](https://lsof.readthedocs.io/en/latest/)
 
 # lsof
 
 [lsof](https://en.wikipedia.org/wiki/Lsof) is a command listing open files.
 
-How it works:
+## How it works:
+
 ```
 $ cat > /tmp/LOG &
 cat > /tmp/LOG &
@@ -26,41 +29,48 @@ cat     18083 yamato    1w   REG   0,44         0 54550934 /tmp/LOG
 cat     18083 yamato    2u   CHR  136,3       0t0        6 /dev/pts/3
 ```
 
+Read the documentation at [lsof.readthedocs.io](https://lsof.readthedocs.io/)
+
 # lsof-org at GitHub
 
-The lsof-org team at GitHub takes over the maintainership of lsof
-originally developed and maintained by Vic Abell. This repository is for maintaining
-the final source tree of lsof inherited from Vic. "legacy" branch
-keeps the original source tree. We will not introduce any changes to
-the "legacy" branch. This branch is just for reference.
+The lsof-org team at GitHub takes over the maintainership of lsof originally
+developed and maintained by Vic Abell. This repository is for maintaining the
+final source tree of lsof inherited from Vic. "legacy" branch keeps the original
+source tree. We will not introduce any changes to the "legacy" branch. This
+branch is just for reference.
 
-"master" branch is used for maintenance. Bug fixes and enhancements go
-to "master" branch.
+"master" branch is used for maintenance. Bug fixes and enhancements go to
+"master" branch.
 
-lsof had supported many OSes. A term "dialect" represents code for
-supporting OSes. Because of limited resources, we will maintain the
-part of them. The current status of maintenance is as follows:
+lsof had supported many OSes. A term "dialect" represents code for supporting
+OSes. Because of limited resources, we will maintain the part of them. The
+current status of maintenance is as follows:
 
 <dl>
-<dt>freebsd</dt>
-<dd>partially maintained, but testing on Cirrus CI is temporary disabled</dd>
-<dt>linux</dt>
-<dd>fully maintained, and tested on Travis CI</dd>
-<dt>darwin</dt>
-<dd>not maintained, but partially tested on Travis CI</dd>
+<dt>FreeBSD</dt>
+<dd>fully maintained and tested on Cirrus CI</dd>
+<dt>Linux</dt>
+<dd>fully maintained, and tested on Circle CI</dd>
+<dt>Darwin</dt>
+<dd>fully maintained, and tested on Circle CI</dd>
+<dt>NetBSD</dt>
+<dd>fully maintained, and tested on SourceHut CI</dd>
+<dt>OpenBSD</dt>
+<dd>fully maintained, and tested on SourceHut CI</dd>
+<dt>Solaris/OpenIndiana</dt>
+<dd>fully maintained</dd>
 </dl>
 
-If you are interested in maintaining a dialect, let us know via the
-issue tracker of GitHub (https://github.com/lsof-org/lsof/issues). If
-we cannot find a volunteer for a dialect, we will remove the dialect.
+If you are interested in maintaining a dialect, let us know via the issue
+tracker of GitHub (https://github.com/lsof-org/lsof/issues). If we cannot find a
+volunteer for a dialect, we will remove the dialect.
 
-Many texts in the source tree still refers purdue.edu as the home of
-lsof development. It should be https://github.com/lsof-org/lsof, the
-new home. The updating is in progress.
+Many texts in the source tree still refers purdue.edu as the home of lsof
+development. It should be https://github.com/lsof-org/lsof, the new home. The
+updating is in progress.
 
-We ran another repository, lsof-org/"lsof-linux" derived from
-lsof-4.91 that was also released by Vic. The repository is no more
-used; all the changes made in the repository are now in lsof-org/"lsof"
-repository.
+We ran another repository, lsof-org/"lsof-linux" derived from lsof-4.91 that was
+also released by Vic. The repository is no more used; all the changes made in
+the repository are now in lsof-org/"lsof" repository.
 
 The lsof-org team at GitHub
diff --git a/arg.c b/arg.c
deleted file mode 100644
index ac1b24a..0000000
--- a/arg.c
+++ /dev/null
@@ -1,2516 +0,0 @@
-/*
- * arg.c - common argument processing 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";
-#endif
-
-
-#include "lsof.h"
-
-
-/*
- * Local definitions
- */
-
-#define	CMDRXINCR	32		/* CmdRx[] allocation increment */
-
-
-/*
- * Local static variables
- */
-
-static int NCmdRxA = 0;			/* space allocated to CmdRx[] */
-
-
-/*
- * Local function prototypes
- */
-
-_PROTOTYPE(static int ckfd_range,(char *first, char *dash, char *last, int *lo, int *hi));
-_PROTOTYPE(static int enter_fd_lst,(char *nm, int lo, int hi, int excl));
-_PROTOTYPE(static int enter_nwad,(struct nwad *n, int sp, int ep, char *s, struct hostent *he));
-_PROTOTYPE(static struct hostent *lkup_hostnm,(char *hn, struct nwad *n));
-_PROTOTYPE(static char *isIPv4addr,(char *hn, unsigned char *a, int al));
-
-
-/*
- * ckfd_range() - check fd range
- */
-
-static int
-ckfd_range(first, dash, last, lo, hi)
-	char *first;			/* starting character */
-	char *dash;			/* '-' location */
-	char *last;			/* '\0' location */
-	int *lo;			/* returned low value */
-	int *hi;			/* returned high value */
-{
-	char *cp;
-/*
- * See if the range character pointers make sense.
- */
-	if (first >= dash || dash >= last) {
-	    (void) fprintf(stderr, "%s: illegal FD range for -d: ", Pn);
-	    safestrprt(first, stderr, 1);
-	    return(1);
-	}
-/*
- * Assemble and check the high and low values.
- */
-	for (cp = first, *lo = 0; *cp && cp < dash; cp++) {
-	    if (!isdigit((unsigned char)*cp)) {
-
-FD_range_nondigit:
-
-		(void) fprintf(stderr, "%s: non-digit in -d FD range: ", Pn);
-		safestrprt(first, stderr, 1);
-		return(1);
-	    }
-	    *lo = (*lo * 10) + (int)(*cp - '0');
-	}
-	for (cp = dash+1, *hi = 0; *cp && cp < last; cp++) {
-	    if (!isdigit((unsigned char)*cp))
-		goto FD_range_nondigit;
-	    *hi = (*hi * 10) + (int)(*cp - '0');
-	}
-	if (*lo >= *hi) {
-	    (void) fprintf(stderr, "%s: -d FD range's low >= its high: ", Pn);
-	    safestrprt(first, stderr, 1);
-	    return(1);
-	}
-	return(0);
-}
-
-
-/*
- * ck_file_arg() - check file arguments
- */
-
-int
-ck_file_arg(i, ac, av, fv, rs, sbp, accept_deleted_file)
-	int i;			/* first file argument index */
-	int ac;			/* argument count */
-	char *av[];		/* argument vector */
-	int fv;			/* Ffilesys value (real or temporary) */
-	int rs;			/* Readlink() status if argument count == 1:
-				 *	0 = undone; 1 = done */
-	struct stat *sbp;	/* if non-NULL, pointer to stat(2) buffer
-				 * when argument count == 1 */
-	int accept_deleted_file; /* if non-zero, don't report an error even
-				  * when the file doesn't exist. */
-{
-	char *ap, *fnm, *fsnm, *path;
-	short err = 0;
-	int fsm, ftype, j, k;
-	MALLOC_S l;
-	struct mounts *mp;
-	static struct mounts **mmp = (struct mounts **)NULL;
-	int mx, nm;
-	static int nma = 0;
-	struct stat sb;
-	struct sfile *sfp;
-	short ss = 0;
-
-#if	defined(CKFA_EXPDEV)
-	dev_t dev, rdev;
-#endif	/* defined(CKFA_EXPDEV) */
-
-#if	defined(HASPROCFS)
-	unsigned char ad, an;
-	int pfsnl = -1;
-	pid_t pid;
-	struct procfsid *pfi;
-#endif	/* defined(HASPROCFS) */
-
-/*
- * Loop through arguments.
- */
-	for (; i < ac; i++) {
-	    if (rs && (ac == 1) && (i == 0))
-		path = av[i];
-	    else {
-		if (!(path = Readlink(av[i]))) {
-		    ErrStat = 1;
-		    continue;
-		}
-	    }
-	/*
-	 * Remove terminating `/' characters from paths longer than one.
-	 */
-	    j = k = strlen(path);
-	    while ((k > 1) && (path[k-1] == '/')) {
-		k--;
-	    }
-	    if (k < j) {
-		if (path != av[i])
-		    path[k] = '\0';
-		else {
-		    if (!(ap = (char *)malloc((MALLOC_S)(k + 1)))) {
-			(void) fprintf(stderr, "%s: no space for copy of %s\n",
-			    Pn, path);
-			Error();
-		    }
-		    (void) strncpy(ap, path, k);
-		    ap[k] = '\0';
-		    path = ap;
-		}
-	    }
-	/*
-	 * Check for file system argument.
-	 */
-	    for (ftype = 1, mp = readmnt(), nm = 0;
-		 (fv != 1) && mp;
-		 mp = mp->next)
-	    {
-		fsm = 0;
-		if (strcmp(mp->dir, path) == 0)
-		    fsm++;
-		else if (fv == 2 || (mp->fs_mode & S_IFMT) == S_IFBLK) {
-		    if (mp->fsnmres && strcmp(mp->fsnmres, path) == 0)
-			fsm++;
-		}
-		if (!fsm)
-		    continue;
-		ftype = 0;
-	    /*
-	     * Skip duplicates.
-	     */
-		for (mx = 0; mx < nm; mx++) {
-		    if (strcmp(mp->dir, mmp[mx]->dir) == 0
-		    &&  mp->dev == mmp[mx]->dev
-		    &&  mp->rdev == mmp[mx]->rdev
-		    &&  mp->inode == mmp[mx]->inode)
-			break;
-		}
-		if (mx < nm)
-		    continue;
-	    /*
-	     * Allocate space for and save another mount point match and
-	     * the type of match -- directory name (mounted) or file system
-	     * name (mounted-on).
-	     */
-		if (nm >= nma) {
-		    nma += 5;
-		    l = (MALLOC_S)(nma * sizeof(struct mounts *));
-		    if (mmp)
-			mmp = (struct mounts **)realloc((MALLOC_P *)mmp, l);
-		    else
-			mmp = (struct mounts **)malloc(l);
-		    if (!mmp) {
-			(void) fprintf(stderr,
-			    "%s: no space for mount pointers\n", Pn);
-			Error();
-		    }
-		}
-		mmp[nm++] = mp;
-	    }
-	    if (fv == 2 && nm == 0) {
-		if (!accept_deleted_file) {
-		    (void) fprintf(stderr, "%s: not a file system: ", Pn);
-		    safestrprt(av[i], stderr, 1);
-		}
-		ErrStat = 1;
-		continue;
-	    }
-	/*
-	 * Loop through the file system matches.  If there were none, make one
-	 * pass through the loop, using simply the path name.
-	 */
-	    mx = 0;
-	    do {
-
-	    /*
-	     * Allocate an sfile structure and fill in the type and link.
-	     */
-		if (!(sfp = (struct sfile *)malloc(sizeof(struct sfile)))) {
-		    (void) fprintf(stderr, "%s: no space for files\n", Pn);
-		    Error();
-		}
-		sfp->next = Sfile;
-		Sfile = sfp;
-		sfp->f = 0;
-		if ((sfp->type = ftype)) {
-
-		/*
-		 * For a non-file system path, use the path as the file name
-		 * and set a NULL file system name.
-		 */
-		    fnm = path;
-		    fsnm = (char *)NULL;
-		/*
-		 * Stat the path to obtain its characteristics.
-		 */
-		    if (sbp && (ac == 1))
-			sb = *sbp;
-		    else {
-			if (statsafely(fnm, &sb) != 0) {
-			    int en = errno;
-			    if (!accept_deleted_file) {
-				(void) fprintf(stderr, "%s: status error on ", Pn);
-				safestrprt(fnm, stderr, 0);
-				(void) fprintf(stderr, ": %s\n", strerror(en));
-			    }
-			    Sfile = sfp->next;
-			    (void) free((FREE_P *)sfp);
-			    ErrStat = 1;
-			    continue;
-			}
-
-#if	defined(HASSPECDEVD)
-			(void) HASSPECDEVD(fnm, &sb);
-#endif	/* defined(HASSPECDEVD) */
-
-		    }
-		    sfp->i = (INODETYPE)sb.st_ino;
-		    sfp->mode = sb.st_mode & S_IFMT;
-
-#if	defined(CKFA_EXPDEV)
-		/*
-		 * Expand device numbers before saving, so that they match the
-		 * already-expanded local mount info table device numbers.
-		 * (This is an EP/IX 2.1.1 and above artifact.)
-		 */
-		    sfp->dev = expdev(sb.st_dev);
-		    sfp->rdev = expdev(sb.st_rdev);
-#else	/* !defined(CKFA_EXPDEV) */
-		    sfp->dev = sb.st_dev;
-		    sfp->rdev = sb.st_rdev;
-#endif	/* defined(CKFA_EXPDEV) */
-
-#if	defined(CKFA_MPXCHAN)
-		/*
-		 * Save a (possible) multiplexed channel number.  (This is an
-		 * AIX artifact.)
-		 */
-		    sfp->ch = getchan(path);
-#endif	/* defined(CKFA_MPXCHAN) */
-
-		} else {
-
-#if	defined(SAVE_MP_IN_SFILE)
-		    sfp->mp = mp = mmp[mx++];
-#else	/* !defined(SAVE_MP_IN_SFILE) */
-		    mp = mmp[mx++];
-#endif	/* defined(SAVE_MP_IN_SFILE) */
-
-		    ss++;
-
-#if	defined(HASPROCFS)
-		/*
-		 * If this is a /proc file system, set the search flag and
-		 * abandon the sfile entry.
-		 */
-		    if (mp == Mtprocfs) {
-			Sfile = sfp->next;
-			(void) free((FREE_P *)sfp);
-			Procsrch = 1;
-			continue;
-		    }
-#endif	/* defined(HASPROCFS) */
-
-		/*
-		 * Derive file name and file system name for a mount point.
-		 *
-		 * Save the device numbers, inode number, and modes.
-		 */
-		    fnm = mp->dir;
-		    fsnm = mp->fsname;
-		    sfp->dev = mp->dev;
-		    sfp->rdev = mp->rdev;
-		    sfp->i = mp->inode;
-		    sfp->mode = mp->mode & S_IFMT;
-		}
-		ss = 1;		/* indicate a "safe" stat() */
-	    /*
-	     * Store the file name and file system name pointers in the sfile
-	     * structure, allocating space as necessary.
-	     */
-		if (!fnm || fnm == path) {
-		    sfp->name = fnm;
-
-#if	defined(HASPROCFS)
-		    an = 0;
-#endif	/* defined(HASPROCFS) */
-
-		} else {
-		    if (!(sfp->name = mkstrcpy(fnm, (MALLOC_S *)NULL))) {
-			(void) fprintf(stderr,
-			    "%s: no space for file name: ", Pn);
-			safestrprt(fnm, stderr, 1);
-			Error();
-		    }
-
-#if	defined(HASPROCFS)
-		    an = 1;
-#endif	/* defined(HASPROCFS) */
-
-		}
-		if (!fsnm || fsnm == path) {
-		    sfp->devnm = fsnm;
-
-#if	defined(HASPROCFS)
-		    ad = 0;
-#endif	/* defined(HASPROCFS) */
-
-		} else {
-		    if (!(sfp->devnm = mkstrcpy(fsnm, (MALLOC_S *)NULL))) {
-			(void) fprintf(stderr,
-			    "%s: no space for file system name: ", Pn);
-			safestrprt(fsnm, stderr, 1);
-			Error();
-		    }
-
-#if	defined(HASPROCFS)
-		    ad = 1;
-#endif	/* defined(HASPROCFS) */
-
-		}
-		if (!(sfp->aname = mkstrcpy(av[i], (MALLOC_S *)NULL))) {
-		    (void) fprintf(stderr,
-			"%s: no space for argument file name: ", Pn);
-			safestrprt(av[i], stderr, 1);
-		    Error();
-		}
-
-#if	defined(HASPROCFS)
-	    /*
-	     * See if this is an individual member of a proc file system.
-	     */
-		if (!Mtprocfs || Procsrch)
-		    continue;
-
-# if	defined(HASFSTYPE) && HASFSTYPE==1
-		if (strcmp(sb.st_fstype, HASPROCFS) != 0)
-		    continue;
-# endif	/* defined(HASFSTYPE) && HASFSTYPE==1 */
-
-		if (pfsnl == -1)
-		    pfsnl = strlen(Mtprocfs->dir);
-		if (!pfsnl)
-		    continue;
-		if (strncmp(Mtprocfs->dir, path, pfsnl) != 0)
-		    continue;
-		if (path[pfsnl] != '/')
-
-# if	defined(HASPINODEN)
-		    pid = 0;
-# else	/* !defined(HASPINODEN) */
-		    continue;
-# endif	/* defined(HASPINODEN) */
-
-		else {
-		    for (j = pfsnl+1; path[j]; j++) {
-			if (!isdigit((unsigned char)path[j]))
-			    break;
-		    }
-		    if (path[j] || (j - pfsnl - 1) < 1
-		    ||  (sfp->mode & S_IFMT) != S_IFREG)
-
-# if	defined(HASPINODEN)
-			pid = 0;
-# else	/* !defined(HASPINODEN) */
-			continue;
-# endif	/* defined(HASPINODEN) */
-
-		    else
-			pid = atoi(&path[pfsnl+1]);
-		}
-		if (!(pfi = (struct procfsid *)malloc((MALLOC_S)
-			     sizeof(struct procfsid))))
-		{
-		    (void) fprintf(stderr, "%s: no space for %s ID: ",
-			Pn, Mtprocfs->dir);
-		    safestrprt(path, stderr, 1);
-		    Error();
-		}
-		pfi->pid = pid;
-		pfi->f = 0;
-		pfi->nm = sfp->aname;
-		pfi->next = Procfsid;
-		Procfsid = pfi;
-
-# if	defined(HASPINODEN)
-		pfi->inode = (INODETYPE)sfp->i;
-# endif	/* defined(HASPINODEN) */
-
-	    /*
-	     * Abandon the Sfile entry, lest it be used in is_file_named().
-	     */
-		Sfile = sfp->next;
-		if (ad)
-		    (void) free((FREE_P *)sfp->devnm);
-		if (an)
-		    (void) free((FREE_P *)sfp->name);
-		(void) free((FREE_P *)sfp);
-#endif	/* defined(HASPROCFS) */
-
-	    } while (mx < nm);
-	}
-
-	if (accept_deleted_file) {
-	    if (!ss & ErrStat == 0)
-		err = 1;
-	    if (ErrStat)
-		ErrStat = 0;
-	} else if (!ss) {
-	    err = 1;
-	}
-	return((int)err);
-}
-
-
-#if	defined(HASDCACHE)
-/*
- * ctrl_dcache() - enter device cache control
- */
-
-int
-ctrl_dcache(c)
-	char *c;			/* control string */
-{
-	int rc = 0;
-
-	if (!c) {
-	    (void) fprintf(stderr,
-		"%s: no device cache option control string\n", Pn);
-	    return(1);
-	}
-/*
- * Decode argument function character.
- */
-	switch (*c) {
-	case '?':
-	    if (*(c+1) != '\0') {
-		(void) fprintf(stderr, "%s: nothing should follow -D?\n", Pn);
-		return(1);
-	    }
-	    DChelp = 1;
-	    return(0);
-	case 'b':
-	case 'B':
-	    if (Setuidroot
-
-#if	!defined(WILLDROPGID)
-	    ||  Myuid
-#endif	/* !defined(WILLDROPGID) */
-
-	    )
-		rc = 1;
-	    else
-		DCstate = 1;
-	    break;
-	case 'r':
-	case 'R':
-	    if (Setuidroot && *(c+1))
-		rc = 1;
-	    else
-		DCstate = 2;
-	    break;
-	case 'u':
-	case 'U':
-	    if (Setuidroot
-
-#if	!defined(WILLDROPGID)
-	    ||  Myuid
-#endif	/* !defined(WILLDROPGID) */
-
-	    )
-		rc = 1;
-	    else
-		DCstate = 3;
-	    break;
-	case 'i':
-	case 'I':
-	    if (*(c+1) == '\0') {
-		DCstate = 0;
-		return(0);
-	    }
-	    /* fall through */
-	default:
-	    (void) fprintf(stderr, "%s: unknown -D option: ", Pn);
-	    safestrprt(c, stderr, 1);
-	    return(1);
-	}
-	if (rc) {
-	    (void) fprintf(stderr, "%s: -D option restricted to root: ", Pn);
-	    safestrprt(c, stderr, 1);
-	    return(1);
-	}
-/*
- * Skip to optional path name and save it.
- */
-	for (c++; *c && (*c == ' ' || *c == '\t'); c++)
-	    ;
-	if (strlen(c)) {
-	    if (!(DCpathArg = mkstrcpy(c, (MALLOC_S *)NULL))) {
-		(void) fprintf(stderr, "%s: no space for -D path: ", Pn);
-		safestrprt(c, stderr, 1);
-		Error();
-	    }
-	}
-	return(0);
-}
-#endif	/* defined(HASDCACHE) */
-
-
-/*
- * enter_cmd_rx() - enter command regular expression
- */
-
-int
-enter_cmd_rx(x)
-	char *x;			/* regular expression */
-{
-	int bmod = 0;
-	int bxmod = 0;
-	int i, re;
-	int imod = 0;
-	int xmod = 0;
-	int co = REG_NOSUB|REG_EXTENDED;
-	char reb[256], *xb, *xe, *xm;
-	MALLOC_S xl;
-	char *xp = (char *)NULL;
-/*
- * Make sure the supplied string starts a regular expression.
- */
-	if (!*x || (*x != '/')) {
-	    (void) fprintf(stderr, "%s: regexp doesn't begin with '/': ", Pn);
-	    if (x)
-		safestrprt(x, stderr, 1);
-	    return(1);
-	}
-/*
- * Skip to the end ('/') of the regular expression.
- */
-	xb = x + 1;
-	for (xe = xb; *xe; xe++) {
-	    if (*xe == '/')
-		break;
-	}
-	if (*xe != '/') {
-	    (void) fprintf(stderr, "%s: regexp doesn't end with '/': ", Pn);
-	    safestrprt(x, stderr, 1);
-	    return(1);
-	}
-/*
- * Decode any regular expression modifiers.
- */
-	for (i = 0, xm = xe + 1; *xm; xm++) {
-	    switch(*xm) {
-	    case 'b':			/* This is a basic expression. */
-		if (++bmod > 1) {
-		    if (bmod == 2) {
-			(void) fprintf(stderr,
-			    "%s: b regexp modifier already used: ", Pn);
-			safestrprt(x, stderr, 1);
-		    }
-		    i = 1;
-		} else if (xmod) {
-		    if (++bxmod == 1) {
-			(void) fprintf(stderr,
-			    "%s: b and x regexp modifiers conflict: ", Pn);
-			safestrprt(x, stderr, 1);
-		    }
-		    i = 1;
-		} else
-		    co &= ~REG_EXTENDED;
-		break;
-	    case 'i':			/* Ignore case. */
-		if (++imod > 1) {
-		    if (imod == 2) {
-			(void) fprintf(stderr,
-			    "%s: i regexp modifier already used: ", Pn);
-			safestrprt(x, stderr, 1);
-		    }
-		    i = 1;
-		} else
-		    co |= REG_ICASE;
-		break;
-	    case 'x':			/* This is an extended expression. */
-		if (++xmod > 1) {
-		    if (xmod == 2) {
-			(void) fprintf(stderr,
-			    "%s: x regexp modifier already used: ", Pn);
-			safestrprt(x, stderr, 1);
-		    }
-		    i = 1;
-		} else if (bmod) {
-		    if (++bxmod == 1) {
-			(void) fprintf(stderr,
-			    "%s: b and x regexp modifiers conflict: ", Pn);
-			safestrprt(x, stderr, 1);
-		    }
-		    i = 1;
-		} else
-		    co |= REG_EXTENDED;
-		break;
-	    default:
-		(void) fprintf(stderr, "%s: invalid regexp modifier: %c\n",
-		Pn, (int)*xm);
-		i = 1;
-	    }
-	}
-	if (i)
-	    return(1);
-/*
- * Allocate space to hold expression and copy it there.
- */
-	xl = (MALLOC_S)(xe - xb);
-	if (!(xp = (char *)malloc(xl + 1))) {
-	    (void) fprintf(stderr, "%s: no regexp space for: ", Pn);
-	    safestrprt(x, stderr, 1);
-	    Error();
-	}
-	(void) strncpy(xp, xb, xl);
-	xp[(int)xl] = '\0';
-/*
- * Assign a new CmdRx[] slot for this expression.
- */
-	if (NCmdRxA >= NCmdRxU) {
-
-	/*
-	 * More CmdRx[] space must be assigned.
-	 */
-	    NCmdRxA += CMDRXINCR;
-	    xl = (MALLOC_S)(NCmdRxA * sizeof(lsof_rx_t));
-	    if (CmdRx)
-		CmdRx = (lsof_rx_t *)realloc((MALLOC_P *)CmdRx, xl);
-	    else
-		CmdRx = (lsof_rx_t *)malloc(xl);
-	    if (!CmdRx) {
-		(void) fprintf(stderr, "%s: no space for regexp: ", Pn);
-		safestrprt(x, stderr, 1);
-		Error();
-	    }
-	}
-	i = NCmdRxU;
-	CmdRx[i].exp = xp;
-/*
- * Compile the expression.
- */
-	if ((re = regcomp(&CmdRx[i].cx, xp, co))) {
-	    (void) fprintf(stderr, "%s: regexp error: ", Pn);
-	    safestrprt(x, stderr, 0);
-	    (void) regerror(re, &CmdRx[i].cx, &reb[0], sizeof(reb));
-	    (void) fprintf(stderr, ": %s\n", reb);
-	    if (xp) {
-		(void) free((FREE_P *)xp);
-		xp = (char *)NULL;
-	    }
-	    return(1);
-	}
-/*
- * Complete the CmdRx[] table entry.
- */
-	CmdRx[i].mc = 0;
-	CmdRx[i].exp = xp;
-	NCmdRxU++;
-	return(0);
-}
-
-
-#if	defined(HASEOPT)
-/*
- * enter_efsys() -- enter path of file system whose kernel blocks are to be
- *		    eliminated
- */
-
-int
-enter_efsys(e, rdlnk)
-	char *e;			/* file system path */
-	int rdlnk;			/* avoid readlink(2) if non-zero */
-{
-	char *ec;			/* pointer to copy of path */
-	efsys_list_t *ep;		/* file system path list pointer */
-	int i;				/* temporary index */
-	char *path;			/* Readlink() of file system path */
-
-	if (!e || (*e != '/')) {
-	    if (!Fwarn)
-		(void) fprintf(stderr,
-		    "%s: -e not followed by a file system path: \"%s\"\n",
-		    Pn, e);
-	    return(1);
-	}
-	if (!(ec = mkstrcpy(e, (MALLOC_S *)NULL))) {
-	    (void) fprintf(stderr, "%s: no space for -e string: ", Pn);
-	    safestrprt(e, stderr, 1);
-	    Error();
-	}
-	if (rdlnk)
-	    path = ec;
-	else {
-	    if (!(path = Readlink(ec)))
-		return(1);
-	}
-/*
- * Remove terminating `/' characters from paths longer than one.
- */
-	for (i = (int)strlen(path); (i > 1) && (path[i - 1] == '/'); i--) {
-	    path[i - 1] = '\0';
-	}
-/*
- * Enter file system path on list, avoiding duplicates.
- */
-	for (ep = Efsysl; ep; ep = ep->next) {
-	   if (!strcmp(ep->path, path)) {
-		(void)free((FREE_P *)path);
-		return (0);
-	   }
-	}
-	if (!(ep = (efsys_list_t *)malloc((MALLOC_S)(sizeof(efsys_list_t))))) {
-	   (void) fprintf(stderr, "%s: no space for \"-e %s\" entry\n",
-		Pn, e);
-	   Error();
-	}
-	ep->path = path;
-	ep->pathl = i;
-	ep->rdlnk = rdlnk;
-	ep->mp = (struct mounts *)NULL;
-	ep->next = Efsysl;
-	Efsysl = ep;
-	return(0);
-}
-#endif	/* defined(HASEOPT) */
-
-
-/*
- * enter_fd() - enter file descriptor list for searching
- */
-
-int
-enter_fd(f)
-	char *f;			/* file descriptor list pointer */
-{
-	char c, *cp1, *cp2, *dash;
-	int err, excl, hi, lo;
-	char *fc;
-/*
- *  Check for non-empty list and make a copy.
- */
-	if (!f || (strlen(f) + 1) < 2) {
-	    (void) fprintf(stderr, "%s: no file descriptor specified\n", Pn);
-	    return(1);
-	}
-	if (!(fc = mkstrcpy(f, (MALLOC_S *)NULL))) {
-	    (void) fprintf(stderr, "%s: no space for fd string: ", Pn);
-	    safestrprt(f, stderr, 1);
-	    Error();
-	}
-/*
- * Isolate each file descriptor in the comma-separated list, then enter it
- * in the file descriptor string list.  If a descriptor has the form:
- *
- *	[0-9]+-[0-9]+
- *
- * treat it as an ascending range of file descriptor numbers.
- *
- * Accept a leading '^' as an excusion on match.
- */
-	for (cp1 = fc, err = 0; *cp1;) {
-	    if (*cp1 == '^') {
-		excl = 1;
-		cp1++;
-	    } else
-		excl = 0;
-	    for (cp2 = cp1, dash = (char *)NULL; *cp2 && *cp2 != ','; cp2++) {
-		if (*cp2 == '-')
-		    dash = cp2;
-	    }
-	    if ((c = *cp2) != '\0')
-		*cp2 = '\0';
-	    if (cp2 > cp1) {
-		if (dash) {
-		    if (ckfd_range(cp1, dash, cp2, &lo, &hi))
-			err = 1;
-		    else {
-			if (enter_fd_lst((char *)NULL, lo, hi, excl))
-			    err = 1;
-		    }
-		} else {
-		    if (enter_fd_lst(cp1, 0, 0, excl))
-			err = 1;
-		}
-	    }
-	    if (c == '\0')
-		break;
-	    cp1 = cp2 + 1;
-	}
-	(void) free((FREE_P *)fc);
-	return(err);
-}
-
-
-/*
- * enter_fd_lst() - make an entry in the FD list, Fdl
- */
-
-static int
-enter_fd_lst(nm, lo, hi, excl)
-	char *nm;			/* FD name (none if NULL) */
-	int lo;				/* FD low boundary (if nm NULL) */
-	int hi;				/* FD high boundary (if nm NULL) */
-	int excl;			/* exclusion on match */
-{
-	char buf[256], *cp;
-	int n;
-	struct fd_lst *f, *ft;
-/*
- * Don't allow a mixture of exclusions and inclusions.
- */
-	if (FdlTy >= 0) {
-	    if (FdlTy != excl) {
-		if (!Fwarn) {
-
-		/*
-		 * If warnings are enabled, report a mixture.
-		 */
-		    if (nm) {
-			(void) snpf(buf, sizeof(buf) - 1, "%s%s",
-			    excl ? "^" : "", nm);
-		    } else {
-			if (lo != hi) {
-			    (void) snpf(buf, sizeof(buf) - 1, "%s%d-%d",
-				excl ? "^" : "", lo, hi);
-			} else {
-			    (void) snpf(buf, sizeof(buf) - 1, "%s%d",
-				excl ? "^" : "", lo);
-			}
-		    }
-		    buf[sizeof(buf) - 1] = '\0';
-		    (void) fprintf(stderr,
-		        "%s: %s in an %s -d list: %s\n", Pn,
-			excl ? "exclude" : "include",
-			FdlTy ? "exclude" : "include",
-			buf);
-		}
-		return(1);
-	    }
-	}
-/*
- * Allocate an fd_lst entry.
- */
-	if (!(f = (struct fd_lst *)malloc((MALLOC_S)sizeof(struct fd_lst)))) {
-	   (void) fprintf(stderr, "%s: no space for FD list entry\n", Pn);
-	   Error();
-	}
-	if (nm) {
-
-	/*
-	 * Process an FD name.  First see if it contains only digits; if it
-	 * does, convert them to an integer and set the low and high
-	 * boundaries to the result.
-	 *
-	 * If the name has a non-digit, store it as a string, and set the
-	 * boundaries to impossible values (i.e., low > high).
-	 */
-	    for (cp = nm, n = 0; *cp; cp++) {
-		if (!isdigit((unsigned char)*cp))
-		    break;
-		n = (n * 10) + (int)(*cp - '0');
-	    }
-	    if (*cp) {
-		if (!(f->nm = mkstrcpy(nm, (MALLOC_S *)NULL))) {
-		    (void) fprintf(stderr,
-			"%s: no space for copy of: %s\n", Pn, nm);
-		    Error();
-		}
-		lo = 1;
-		hi = 0;
-	    } else {
-		f->nm = (char *)NULL;
-		lo = hi = n;
-	    }
-	} else
-	    f->nm = (char *)NULL;
-/*
- * Skip duplicates.
- */
-	for (ft = Fdl; ft; ft = ft->next) {
-	    if (f->nm) {
-		if (!ft->nm || strcmp(f->nm, ft->nm))
-		    continue;
-	    } else if ((lo != ft->lo) || (hi != ft->hi))
-		continue;
-	    (void) free((FREE_P *)f);
-	    return(0);
-	}
-/*
- * Complete the fd_lst entry and link it to the head of the chain.
- */
-	f->hi = hi;
-	f->lo = lo;
-	if (f->nm && strcmp(f->nm, "fd") == 0) {
-	    (void) free((FREE_P *)f->nm);
-	    f->nm = NULL;
-	    f->hi = INT_MAX;
-	    f->lo = 0;
-	}
-	f->next = Fdl;
-	Fdl = f;
-	FdlTy = excl;
-	return(0);
-}
-
-
-/*
- * enter_dir() - enter the files of a directory for searching
- */
-
-#define	EDDEFFNL	128		/* default file name length */
-
-int
-enter_dir(d, descend)
-	char *d;			/* directory path name pointer */
-	int descend;			/* subdirectory descend flag:
-					 *	0 = don't descend
-					 *	1 = descend */
-{
-	char *av[2];
-	dev_t ddev;
-	DIR *dfp;
-	char *dn = (char *)NULL;
-	MALLOC_S dnl, dnamlen;
-	struct DIRTYPE *dp;
-	int en, sl;
-	int fct = 0;
-	char *fp = (char *)NULL;
-	MALLOC_S fpl = (MALLOC_S)0;
-	MALLOC_S fpli = (MALLOC_S)0;
-	struct stat sb;
-/*
- * Check the directory path; reduce symbolic links; stat(2) it; make sure it's
- * really a directory.
- */
-	if (!d || !*d || *d == '+' || *d == '-') {
-	    if (!Fwarn)
-		(void) fprintf(stderr,
-		    "%s: +d not followed by a directory path\n", Pn);
-	    return(1);
-	}
-	if (!(dn = Readlink(d)))
-	    return(1);
-	if (statsafely(dn, &sb)) {
-	    if (!Fwarn) {
-		en = errno;
-		(void) fprintf(stderr, "%s: WARNING: can't stat(", Pn);
-		safestrprt(dn, stderr, 0);
-		(void) fprintf(stderr, "): %s\n", strerror(en));
-	    }
-	    if (dn && dn != d) {
-		(void) free((FREE_P *)dn);
-		dn = (char *)NULL;
-	    }
-	    return(1);
-	}
-	if ((sb.st_mode & S_IFMT) != S_IFDIR) {
-	    if (!Fwarn) {
-		(void) fprintf(stderr, "%s: WARNING: not a directory: ", Pn);
-		safestrprt(dn, stderr, 1);
-	    }
-	    if (dn && dn != d) {
-		(void) free((FREE_P *)dn);
-		dn = (char *)NULL;
-	    }
-	    return(1);
-	}
-
-#if	defined(HASSPECDEVD)
-	(void) HASSPECDEVD(dn, &sb);
-#endif	/* defined(HASSPECDEVD) */
-
-	ddev = sb.st_dev;
-/*
- * Stack the directory and record it in Sfile for searching.
- */
-	Dstkn = Dstkx = 0;
-	Dstk = (char **)NULL;
-	(void) stkdir(dn);
-	av[0] = (dn == d) ? mkstrcpy(dn, (MALLOC_S *)NULL) : dn;
-	av[1] = (char *)NULL;
-	dn = (char *)NULL;
-	if (!ck_file_arg(0, 1, av, 1, 1, &sb, 0)) {
-	    av[0] = (char *)NULL;
-	    fct++;
-	}
-/*
- * Unstack the next directory and examine it.
- */
-	while (--Dstkx >= 0) {
-	    if (!(dn = Dstk[Dstkx]))
-		continue;
-	    Dstk[Dstkx] = (char *)NULL;
-	/*
-	 * Open the directory path and prepare its name for use with the
-	 * files in the directory.
-	 */
-	    if (!(dfp = OpenDir(dn))) {
-		if (!Fwarn) {
-		    if ((en = errno) != ENOENT) {
-			(void) fprintf(stderr,
-			    "%s: WARNING: can't opendir(", Pn);
-			safestrprt(dn, stderr, 0);
-			(void) fprintf(stderr, "): %s\n", strerror(en));
-		    }
-	        }
-		(void) free((FREE_P *)dn);
-		dn = (char *)NULL;
-		continue;
-	    }
-	    dnl = strlen(dn);
-	    sl = ((dnl > 0) && (*(dn + dnl - 1) == '/')) ? 0 : 1;
-	/*
-	 * Define space for possible addition to the directory path.
-	 */
-	    fpli = (MALLOC_S)(dnl + sl + EDDEFFNL + 1);
-	    if ((int)fpli > (int)fpl) {
-		fpl = fpli;
-		if (!fp)
-		    fp = (char *)malloc(fpl);
-		else
-		    fp = (char *)realloc(fp, fpl);
-		if (!fp) {
-		    (void) fprintf(stderr,
-			"%s: no space for path to entries in directory: %s\n",
-			Pn, dn);
-		    Error();
-		}
-	    }
-	    (void) snpf(fp, (size_t)fpl, "%s%s", dn, sl ? "/" : "");
-	    (void) free((FREE_P *)dn);
-	    dn = (char *)NULL;
-	/*
-	 * Read the contents of the directory.
-	 */
-	    for (dp = ReadDir(dfp); dp; dp = ReadDir(dfp)) {
-
-	    /*
-	     * Skip: entries with no inode number;
-	     *	     entries with a zero length name;
-	     *	     ".";
-	     *	     and "..".
-	     */
-		if (!dp->d_ino)
-		    continue;
-
-#if     defined(HASDNAMLEN)
-		dnamlen = (MALLOC_S)dp->d_namlen;
-#else   /* !defined(HASDNAMLEN) */
-		dnamlen = (MALLOC_S)strlen(dp->d_name);
-#endif  /* defined(HASDNAMLEN) */
-
-		if (!dnamlen)
-		    continue;
-		if (dnamlen <= 2 && dp->d_name[0] == '.') {
-		    if (dnamlen == 1)
-			continue;
-		    if (dp->d_name[1] == '.')
-			continue;
-		}
-	    /*
-	     * Form the entry's path name.
-	     */
-		fpli = (MALLOC_S)(dnamlen - (fpl - dnl - sl - 1));
-		if ((int)fpli > 0) {
-		    fpl += fpli;
-		    if (!(fp = (char *)realloc(fp, fpl))) {
-			(void) fprintf(stderr, "%s: no space for: ", Pn);
-			safestrprt(dn, stderr, 0);
-			putc('/', stderr);
-			safestrprtn(dp->d_name, dnamlen, stderr, 1);
-			Error();
-		    }
-		}
-		(void) strncpy(fp + dnl + sl, dp->d_name, dnamlen);
-		fp[dnl + sl + dnamlen] = '\0';
-	    /*
-	     * Lstatsafely() the entry; complain if that fails.
-	     *
-	     * Stack entries that represent subdirectories.
-	     */
-		if (lstatsafely(fp, &sb)) {
-		    if ((en = errno) != ENOENT) {
-			if (!Fwarn) {
-			    (void) fprintf(stderr,
-				"%s: WARNING: can't lstat(", Pn);
-			    safestrprt(fp, stderr, 0);
-			    (void) fprintf(stderr, "): %s\n", strerror(en));
-			}
-		    }
-		    continue;
-		}
-
-#if	defined(HASSPECDEVD)
-		(void) HASSPECDEVD(fp, &sb);
-#endif	/* defined(HASSPECDEVD) */
-
-		if (!(Fxover & XO_FILESYS)) {
-
-		/*
-		 * Unless "-x" or "-x f" was specified, don't cross over file
-		 * system mount points.
-		 */
-		    if (sb.st_dev != ddev)
-			continue;
-		}
-		if ((sb.st_mode & S_IFMT) == S_IFLNK) {
-
-		/*
-		 * If this is a symbolic link and "-x_ or "-x l" was specified,
-		 * Statsafely() the entry and process it.
-		 *
-		 * Otherwise skip symbolic links.
-		 */
-		    if (Fxover & XO_SYMLINK) {
-			if (statsafely(fp, &sb)) {
-			    if ((en = errno) != ENOENT) {
-				if (!Fwarn) {
-				    (void) fprintf(stderr,
-					"%s: WARNING: can't stat(", Pn);
-				    safestrprt(fp, stderr, 0);
-				    (void) fprintf(stderr,
-					") symbolc link: %s\n", strerror(en));
-				}
-			    }
-			    continue;
-		        }
-		    } else
-			continue;
-		}
-		if (av[0]) {
-		    (void) free((FREE_P *)av[0]);
-		    av[0] = (char *)NULL;
-		}
-		av[0] = mkstrcpy(fp, (MALLOC_S *)NULL);
-		if ((sb.st_mode & S_IFMT) == S_IFDIR && descend)
-
-		/*
-		 * Stack a subdirectory according to the descend argument.
-		 */
-		    stkdir(av[0]);
-	    /*
-	     * Use ck_file_arg() to record the entry for searching.  Force it
-	     * to consider the entry a file, not a file system.
-	     */
-		if (!ck_file_arg(0, 1, av, 1, 1, &sb, 0)) {
-		    av[0] = (char *)NULL;
-		    fct++;
-		}
-	    }
-	    (void) CloseDir(dfp);
-	    if (dn && dn != d) {
-		(void) free((FREE_P *)dn);
-		dn = (char *)NULL;
-	    }
-	}
-/*
- * Free malloc()'d space.
- */
-	if (dn && dn != d) {
-	    (void) free((FREE_P *)dn);
-	    dn = (char *)NULL;
-	}
-	if (av[0] && av[0] != fp) {
-	    (void) free((FREE_P *)av[0]);
-	    av[0] = (char *)NULL;
-	}
-	if (fp) {
-	    (void) free((FREE_P *)fp);
-	    fp = (char *)NULL;
-	}
-	if (Dstk) {
-	    (void) free((FREE_P *)Dstk);
-	    Dstk = (char **)NULL;
-	}
-	if (!fct) {
-
-	/*
-	 * Warn if no files were recorded for searching.
-	 */
-	    if (!Fwarn) {
-		(void) fprintf(stderr,
-		    "%s: WARNING: no files found in directory: ", Pn);
-		safestrprt(d, stderr, 1);
-	    }
-	    return(1);
-	}
-	return(0);
-}
-
-
-/*
- * enter_id() - enter PGID or PID for searching
- */
-
-int
-enter_id(ty, p)
-	enum IDType ty;			/* type: PGID or PID */
-	char *p;			/* process group ID string pointer */
-{
-	char *cp;
-	int err, i, id, j, mx, n, ni, nx, x;
-	struct int_lst *s;
-
-	if (!p) {
-	    (void) fprintf(stderr, "%s: no process%s ID specified\n",
-		Pn, (ty == PGID) ? " group" : "");
-	    return(1);
-	}
-/*
- * Set up variables for the type of ID.
- */
-	switch (ty) {
-	case PGID:
-	    mx = Mxpgid;
-	    n = Npgid;
-	    ni = Npgidi;
-	    nx = Npgidx;
-	    s = Spgid;
-	    break;
-	case PID:
-	    mx = Mxpid;
-	    n = Npid;
-	    ni = Npidi;
-	    nx = Npidx;
-	    s = Spid;
-	    break;
-	default:
-	    (void) fprintf(stderr, "%s: enter_id \"", Pn);
-	    safestrprt(p, stderr, 0);
-	    (void) fprintf(stderr, "\", invalid type: %d\n", ty);
-	    Error();
-	}
-/*
- * Convert and store the ID.
- */
-	for (cp = p, err = 0; *cp;) {
-
-	/*
-	 * Assemble ID.
-	 */
-	    for (i = id = x = 0; *cp && *cp != ','; cp++) {
-		if (!i) {
-		    i = 1;
-		    if (*cp == '^') {
-			x = 1;
-			continue;
-		    }
-		}
-
-#if	defined(__STDC__)
-		if (!isdigit((unsigned char)*cp))
-#else	/* !defined(__STDC__) */
-		if (!isascii(*cp) || ! isdigit((unsigned char)*cp))
-#endif	/* __STDC__ */
-
-		{
-		    (void) fprintf(stderr, "%s: illegal process%s ID: ",
-			Pn, (ty == PGID) ? " group" : "");
-		    safestrprt(p, stderr, 1);
-		    return(1);
-		}
-		id = (id * 10) + *cp - '0';
-	    }
-	    if (*cp)
-		cp++;
-	/*
-	 * Avoid entering duplicates and conflicts.
-	 */
-	    for (i = j = 0; i < n; i++) {
-		if (id == s[i].i) {
-		    if (x == s[i].x) {
-			j = 1;
-			continue;
-		    }
-		    (void) fprintf(stderr,
-			"%s: P%sID %d has been included and excluded.\n",
-			Pn,
-			(ty == PGID) ? "G" : "",
-			id);
-		    err = j = 1;
-		    break;
-		}
-	    }
-	    if (j)
-		continue;
-	/*
-	 * Allocate table table space.
-	 */
-	    if (n >= mx) {
-		mx += IDINCR;
-		if (!s)
-		    s = (struct int_lst *)malloc(
-			(MALLOC_S)(sizeof(struct int_lst) * mx));
-		else
-		    s = (struct int_lst *)realloc((MALLOC_P *)s,
-			(MALLOC_S)(sizeof(struct int_lst) * mx));
-		if (!s) {
-		    (void) fprintf(stderr, "%s: no space for %d process%s IDs",
-			Pn, mx, (ty == PGID) ? " group" : "");
-		    Error();
-		}
-	    }
-	    s[n].f = 0;
-	    s[n].i = id;
-	    s[n++].x = x;
-	    if (x)
-		nx++;
-	    else
-		ni++;
-	}
-/*
- * Save variables for the type of ID.
- */
-	if (ty == PGID) {
-	    Mxpgid = mx;
-	    Npgid = n;
-	    Npgidi = ni;
-	    Npgidx = nx;
-	    Spgid = s;
-	} else {
-	    Mxpid = mx;
-	    Npid = Npuns = n;
-	    Npidi = ni;
-	    Npidx = nx;
-	    Spid = s;
-	}
-	return(err);
-}
-
-
-/*
- * enter_network_address() - enter Internet address for searching
- */
-
-int
-enter_network_address(na)
-	char *na;			/* Internet address string pointer */
-{
-	int ae, i, pr;
-	int ep = -1;
-	int ft = 0;
-	struct hostent *he = (struct hostent *)NULL;
-	char *hn = (char *)NULL;
-	MALLOC_S l;
-	struct nwad n;
-	char *p, *wa;
-	int pt = 0;
-	int pu = 0;
-	struct servent *se, *se1;
-	char *sn = (char *)NULL;
-	int sp = -1;
-	MALLOC_S snl = 0;
-
-#if	defined(HASIPv6)
-	char *cp;
-#endif	/* defined(HASIPv6) */
-
-	if (!na) {
-	    (void) fprintf(stderr, "%s: no network address specified\n", Pn);
-	    return(1);
-	}
-	zeromem((char *)&n, sizeof(n));
-	wa = na;
-/*
- * Process an IP version type specification, IPv4 or IPv6, optionally followed
- * by a '@' and a host name or Internet address, or a ':' and a service name or
- * port number.
- */
-	if ((*wa == '4') || (*wa == '6')) {
-	    if (*wa == '4')
-		ft = 4;
-	    else if (*wa == '6') {
-
-#if	defined(HASIPv6)
-		ft = 6;
-#else	/* !defined(HASIPv6) */
-		(void) fprintf(stderr, "%s: IPv6 not supported: -i ", Pn);
-		safestrprt(na, stderr, 1);
-		goto nwad_exit;
-#endif	/* defined(HASIPv6) */
-
-	    }
-	    wa++;
-	    if (!*wa) {
-
-	    /*
-	     * If nothing follows 4 or 6, then all network files of the
-	     * specified IP version are selected.  Sequential -i, -i4, and
-	     * -i6 specifications interact logically -- e.g., -i[46] followed
-	     * by -i[64] is the same as -i.
-	     */
-		if (!Fnet) {
-		    Fnet = 1;
-		    FnetTy = ft;
-		} else {
-		    if (FnetTy) {
-			if (FnetTy != ft)
-			    FnetTy = 0;
-		    } else
-			FnetTy = ft;
-		}
-		return(0);
-	    }
-	} else if (Fnet)
-	    ft = FnetTy;
-/*
- * If an IP version has been specified, use it to set the address family.
- */
-	switch (ft) {
-	case 4:
-	    n.af = AF_INET;
-	    break;
-
-#if	defined(HASIPv6)
-	case 6:
-	    n.af = AF_INET6;
-	    break;
-#endif	/* defined(HASIPv6) */
-
-	}
-/*
- * Process protocol name, optionally followed by a '@' and a host name or
- * Internet address, or a ':' and a service name or port number.
- */
-	if (*wa && *wa != '@' && *wa != ':') {
-	    for (p = wa; *wa && *wa != '@' && *wa != ':'; wa++)
-		;
-	    if ((l = wa - p)) {
-		if (!(n.proto = mkstrcat(p, l, (char *)NULL, -1, (char *)NULL,
-			        -1, (MALLOC_S *)NULL)))
-		{
-		    (void) fprintf(stderr,
-			"%s: no space for protocol name from: -i ", Pn);
-		    safestrprt(na, stderr, 1);
-nwad_exit:
-		    if (n.proto)
-			(void) free((FREE_P *)n.proto);
-		    if (hn)
-			(void) free((FREE_P *)hn);
-		    if (sn)
-			(void) free((FREE_P *)sn);
-		    return(1);
-		}
-	    /*
-	     * The protocol name should be "tcp", "udp" or "udplite".
-	     */
-		if ((strcasecmp(n.proto, "tcp") != 0)
-		&&  (strcasecmp(n.proto, "udp") != 0)
-		&&  (strcasecmp(n.proto, "udplite") != 0))
-		{
-		    (void) fprintf(stderr,
-			"%s: unknown protocol name (%s) in: -i ", Pn, n.proto);
-		    safestrprt(na, stderr, 1);
-		    goto nwad_exit;
-		}
-	    /*
-	     * Convert protocol name to lower case.
-	     */
-		for (p = n.proto; *p; p++) {
-		    if (*p >= 'A' && *p <= 'Z')
-			*p = *p - 'A' + 'a';
-		}
-	    }
-	}
-/*
- * Process an IPv4 address (1.2.3.4), IPv6 address ([1:2:3:4:5:6:7:8]),
- * or host name, preceded by a '@' and optionally followed by a colon
- * and a service name or port number.
- */
-	if (*wa == '@') {
-	    wa++;
-	    if (!*wa || *wa == ':') {
-
-#if	defined(HASIPv6)
-unacc_address:
-#endif	/* defined(HASIPv6) */
-
-		(void) fprintf(stderr,
-		    "%s: unacceptable Internet address in: -i ", Pn);
-		safestrprt(na, stderr, 1);
-		goto nwad_exit;
-	    }
-
-	    if ((p = isIPv4addr(wa, n.a, sizeof(n.a)))) {
-
-	    /*
-	     * Process IPv4 address.
-	     */
-		if (ft == 6) {
-		    (void) fprintf(stderr,
-			"%s: IPv4 addresses are prohibited: -i ", Pn);
-		    safestrprt(na, stderr, 1);
-		    goto nwad_exit;
-		}
-		wa = p;
-		n.af = AF_INET;
-	    } else if (*wa == '[') {
-
-#if	defined(HASIPv6)
-	    /*
-	     * Make sure IPv6 addresses are permitted.  If they are, assemble
-	     * one.
-	     */
-		if (ft == 4) {
-		    (void) fprintf(stderr,
-			"%s: IPv6 addresses are prohibited: -i ", Pn);
-		    safestrprt(na, stderr, 1);
-		    goto nwad_exit;
-		}
-		if (!(cp = strrchr(++wa, ']')))
-		    goto unacc_address;
-		*cp = '\0';
-		i = inet_pton(AF_INET6, wa, (void *)&n.a);
-		*cp = ']';
-		if (i != 1)
-		    goto unacc_address;
-		for (ae = i = 0; i < MAX_AF_ADDR; i++) {
-		    if ((ae |= n.a[i]))
-			break;
-		}
-		if (!ae)
-		    goto unacc_address;
-		if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)&n.a[0])) {
-		    if (ft == 6) {
-			(void) fprintf(stderr,
-			    "%s: IPv4 addresses are prohibited: -i ", Pn);
-			safestrprt(na, stderr, 1);
-			goto nwad_exit;
-		    }
-		    for (i = 0; i < 4; i++) {
-			n.a[i] = n.a[i+12];
-		    }
-		    n.af = AF_INET;
-		} else
-		    n.af = AF_INET6;
-		wa = cp + 1;
-#else	/* !defined(HASIPv6) */
-		(void) fprintf(stderr,
-		    "%s: unsupported IPv6 address in: -i ", Pn);
-		safestrprt(na, stderr, 1);
-		goto nwad_exit;
-#endif	/* defined(HASIPv6) */
-
-	    } else {
-
-	    /*
-	     * Assemble host name.
-	     */
-		for (p = wa; *p && *p != ':'; p++)
-		    ;
-		if ((l = p - wa)) {
-		    if (!(hn = mkstrcat(wa, l, (char *)NULL, -1, (char *)NULL,
-			       -1, (MALLOC_S *)NULL)))
-		    {
-			(void) fprintf(stderr,
-			    "%s: no space for host name: -i ", Pn);
-			safestrprt(na, stderr, 1);
-			goto nwad_exit;
-		    }
-
-#if	defined(HASIPv6)
-
-		/*
-		 * If no IP version has been specified, look up an IPv6 host
-		 * name first.  If that fails, look up an IPv4 host name.
-		 *
-		 * If the IPv6 version has been specified, look up the host
-		 * name only under its IP version specification.
-		 */
-		    if (!ft)
-			n.af = AF_INET6;
-		    if (!(he = lkup_hostnm(hn, &n)) && !ft) {
-			n.af = AF_INET;
-			he = lkup_hostnm(hn, &n);
-		    }
-#else	/* !defined(HASIPv6) */
-		    if (!ft)
-			n.af = AF_INET;
-		    he = lkup_hostnm(hn, &n);
-#endif	/* defined(HASIPv6) */
-
-		    if (!he) {
-			fprintf(stderr, "%s: unknown host name (%s) in: -i ",
-			    Pn, hn);
-			safestrprt(na, stderr, 1);
-			goto nwad_exit;
-		    }
-		}
-		wa = p;
-	    }
-	}
-/*
- * If there is no port number, enter the address.
- */
-	if (!*wa)
-	    goto nwad_enter;
-/*
- * Process a service name or port number list, preceded by a colon.
- *
- * Entries of the list are separated with commas; elements of a numeric range
- * are specified with a separating minus sign (`-'); all service names must
- * belong to the same protocol; embedded spaces are not allowed.  An embedded
- * minus sign in a name is taken to be part of the name, the starting entry
- * of a range can't be a service name.
- */
-	if (*wa != ':' || *(wa + 1) == '\0') {
-
-unacc_port:
-	    (void) fprintf(stderr,
-		"%s: unacceptable port specification in: -i ", Pn);
-	    safestrprt(na, stderr, 1);
-	    goto nwad_exit;
-	}
-	for (++wa; wa && *wa; wa++) {
-	    for (ep = pr = sp = 0; *wa; wa++) {
-		if (*wa < '0' || *wa > '9') {
-
-		/*
-		 * Convert service name to port number, using already-specified
-		 * protocol name.  A '-' is taken to be part of the name; hence
-		 * the starting entry of a range can't be a service name.
-		 */
-		    for (p = wa; *wa && *wa != ','; wa++)
-			;
-		    if (!(l = wa - p)) {
-			(void) fprintf(stderr,
-			    "%s: invalid service name: -i ", Pn);
-			safestrprt(na, stderr, 1);
-			goto nwad_exit;
-		    }
-		    if (sn) {
-			if (l > snl) {
-			    sn = (char *)realloc((MALLOC_P *)sn, l + 1);
-			    snl = l;
-			}
-		    } else {
-			sn = (char *)malloc(l + 1);
-			snl = l;
-		    }
-		    if (!sn) {
-			(void) fprintf(stderr,
-			    "%s: no space for service name: -i ", Pn);
-			safestrprt(na, stderr, 1);
-			goto nwad_exit;
-		    }
-		    (void) strncpy(sn, p, l);
-		    *(sn + l) = '\0';
-		    if (n.proto) {
-
-		    /*
-		     * If the protocol has been specified, look up the port
-		     * number for the service name for the specified protocol.
-		     */
-			if (!(se = getservbyname(sn, n.proto))) {
-			    (void) fprintf(stderr,
-				"%s: unknown service %s for %s in: -i ",
-				Pn, sn, n.proto);
-			    safestrprt(na, stderr, 1);
-			    goto nwad_exit;
-			}
-			pt = (int)ntohs(se->s_port);
-		    } else {
-
-		    /*
-		     * If no protocol has been specified, look up the port
-		     * numbers for the service name for both TCP and UDP.
-		     */
-			if ((se = getservbyname(sn, "tcp")))
-			    pt = (int)ntohs(se->s_port);
-			if ((se1 = getservbyname(sn, "udp")))
-			    pu = (int)ntohs(se1->s_port);
-			if (!se && !se1) {
-			    (void) fprintf(stderr,
-				"%s: unknown service %s in: -i ", Pn, sn);
-			    safestrprt(na, stderr, 1);
-			    goto nwad_exit;
-			}
-			if (se && se1 && pt != pu) {
-			    (void) fprintf(stderr,
-				"%s: TCP=%d and UDP=%d %s ports conflict;\n",
-				Pn, pt, pu, sn);
-			    (void) fprintf(stderr,
-				"      specify \"tcp:%s\" or \"udp:%s\": -i ",
-				sn, sn);
-			    safestrprt(na, stderr, 1);
-			    goto nwad_exit;
-			}
-			if (!se && se1)
-			    pt = pu;
-		    }
-		    if (pr)
-			ep = pt;
-		    else {
-			sp = pt;
-			if (*wa == '-')
-			    pr++;
-		    }
-		} else {
-
-		/*
-		 * Assemble port number.
-		 */
-		    for (; *wa && *wa != ','; wa++) {
-			if (*wa == '-') {
-			    if (pr)
-				goto unacc_port;
-			    pr++;
-			    break;
-			}
-			if (*wa < '0' || *wa > '9')
-			    goto unacc_port;
-			if (pr)
-			    ep = (ep * 10) + *wa - '0';
-			else
-			    sp = (sp * 10) + *wa - '0';
-		    }
-		}
-		if (!*wa || *wa == ',')
-		    break;
-		if (pr)
-		    continue;
-		goto unacc_port;
-	    }
-	    if (!pr)
-		ep = sp;
-	    if (ep < sp)
-		goto unacc_port;
-	/*
-	 * Enter completed port or port range specification.
-	 */
-
-nwad_enter:
-
-	    for (i = 1; i;) {
-		if (enter_nwad(&n, sp, ep, na, he))
-		    goto nwad_exit;
-
-#if	defined(HASIPv6)
-	    /*
-	     * If IPv6 is enabled, a host name was specified, and the
-	     * associated * address is for the AF_INET6 address family,
-	     * try to get and address for the AF_INET family, too, unless
-	     * IPv4 is prohibited.
-	     */
-		if (hn && (n.af == AF_INET6) && (ft != 6)) {
-		    n.af = AF_INET;
-		    if ((he = lkup_hostnm(hn, &n)))
-			continue;
-		}
-#endif	/* defined(HASIPv6) */
-
-		i = 0;
-	    }
-	    if (!*wa)
-		break;
-	}
-	if (sn)
-	    (void) free((FREE_P *)sn);
-	return(0);
-}
-
-/*
- * enter_nwad() - enter nwad structure
- */
-
-static int
-enter_nwad(n, sp, ep, s, he)
-	struct nwad *n;			/* pointer to partially completed
-					 * nwad (less port) */
-	int sp;				/* starting port number */
-	int ep;				/* ending port number */
-	char *s;			/* string that states the address */
-	struct hostent *he;		/* pointer to hostent struct from which
-					 * network address came */
-{
-	int ac;
-	unsigned char *ap;
-	static int na = 0;
-	struct nwad nc;
-	struct nwad *np;
-/*
- * Allocate space for the argument specification.
- */
-	if (strlen(s)) {
-	    if (!(n->arg = mkstrcpy(s, (MALLOC_S *)NULL))) {
-		(void) fprintf(stderr,
-		    "%s: no space for Internet argument: -i ", Pn);
-		safestrprt(s, stderr, 1);
-		Error();
-	    }
-	} else
-	    n->arg = (char *)NULL;
-/*
- * Loop through all hostent addresses.
- */
-	for (ac = 1, nc = *n;;) {
-
-	/*
-	 * Test address specification -- it must contain at least one of:
-	 * protocol, Internet address or port.  If correct, link into search
-	 * list.
-	 */
-	    if (!nc.proto
-	    &&  !nc.a[0] && !nc.a[1] && !nc.a[2] && !nc.a[3]
-
-#if	defined(HASIPv6)
-	    &&  (nc.af != AF_INET6
-	    ||   (!nc.a[4]  && !nc.a[5]  && !nc.a[6]  && !nc.a[7]
-	    &&    !nc.a[8]  && !nc.a[9]  && !nc.a[10] && !nc.a[11]
-	    &&    !nc.a[12] && !nc.a[13] && !nc.a[14] && !nc.a[15]))
-#endif	/* defined(HASIPv6) */
-
-	    &&  sp == -1) {
-		(void) fprintf(stderr,
-		    "%s: incomplete Internet address specification: -i ", Pn);
-		safestrprt(s, stderr, 1);
-		return(1);
-	    }
-	/*
-	 * Limit the network address chain length to MAXNWAD for reasons of
-	 * search efficiency.
-	 */
-	    if (na >= MAXNWAD) {
-		(void) fprintf(stderr,
-		    "%s: network address limit (%d) exceeded: -i ",
-		    Pn, MAXNWAD);
-		safestrprt(s, stderr, 1);
-		return(1);
-	    }
-	/*
-	 * Allocate space for the address specification.
-	 */
-	    if ((np = (struct nwad *)malloc(sizeof(struct nwad))) == NULL) {
-		(void) fprintf(stderr,
-		    "%s: no space for network address from: -i ", Pn);
-		safestrprt(s, stderr, 1);
-		return(1);
-	    }
-	/*
-	 * Construct and link the address specification.
-	 */
-	    *np = nc;
-	    np->sport = sp;
-	    np->eport = ep;
-	    np->f = 0;
-	    np->next = Nwad;
-	    Nwad = np;
-	    na++;
-	/*
-	 * If the network address came from gethostbyname(), advance to
-	 * the next address; otherwise quit.
-	 */
-	    if (!he)
-		break;
-	    if (!(ap = (unsigned char *)he->h_addr_list[ac++]))
-		break;
-
-#if	defined(HASIPv6)
-	    {
-		int i;
-
-		for (i = 0;
-		     (i < (he->h_length - 1)) && (i < (MAX_AF_ADDR - 1));
-		     i++)
-		{
-		    nc.a[i] = *ap++;
-		}
-		nc.a[i] = *ap;
-	    }
-#else	/* !defined(HASIPv6) */
-	    nc.a[0] = *ap++;
-	    nc.a[1] = *ap++;
-	    nc.a[2] = *ap++;
-	    nc.a[3] = *ap;
-#endif	/* defined(HASIPv6) */
-
-	}
-	return(0);
-}
-
-
-#if	defined(HASTCPUDPSTATE)
-/*
- * enter_state_spec() -- enter TCP and UDP state specifications
- */
-
-int
-enter_state_spec(ss)
-	char *ss;			/* state specification string */
-{
-	char *cp, *ne, *ns, *pr;
-	int err, d, f, i, tx, x;
-	size_t len;
-	static char *ssc = (char *)NULL;
-	char *ty;
-/*
- * Check the protocol specification.
- */
-	if (!strncasecmp(ss, "tcp:", 4)) {
-	    pr = "TCP";
-	    tx = 0;
-	}
-
-#if	!defined(USE_LIB_PRINT_TCPTPI)
-	else if (!strncasecmp(ss, "UDP:", 4)) {
-	    pr = "UDP";
-	    tx = 1;
-	}
-
-#endif	/* !defined(USE_LIB_PRINT_TCPTPI) */
-
-	else {
-	    (void) fprintf(stderr, "%s: unknown -s protocol: \"%s\"\n",
-		Pn, ss);
-	    return(1);
-	}
-	cp = ss + 4;
-	if (!*cp) {
-	    (void) fprintf(stderr, "%s: no %s state names in: %s\n",
-		Pn, pr, ss);
-	    return(1);
-	}
-	(void) build_IPstates();
-	if (!(tx ? UdpSt : TcpSt)) {
-	    (void) fprintf(stderr, "%s: no %s state names available: %s\n",
-		Pn, pr, ss);
-	    return(1);
-	}
-/*
- * Allocate the inclusion and exclusion tables for the protocol.
- */
-	if (tx) {
-	    if (UdpNstates) {
-		if (!UdpStI) {
-		    if (!(UdpStI = (unsigned char *)calloc((MALLOC_S)UdpNstates,
-				   sizeof(unsigned char))))
-		    {
-			ty = "UDP state inclusion";
-
-no_IorX_space:
-
-			(void) fprintf(stderr, "%s: no %s table space\n",
-			    Pn, ty);
-			Error();
-		    }
-		}
-		if (!UdpStX) {
-		    if (!(UdpStX = (unsigned char *)calloc((MALLOC_S)UdpNstates,
-				   sizeof(unsigned char))))
-		    {
-			ty = "UDP state exclusion";
-			goto no_IorX_space;
-		    }
-		}
-	    }
-	} else {
-	    if (TcpNstates) {
-		if (!TcpStI) {
-		    if (!(TcpStI = (unsigned char *)calloc((MALLOC_S)TcpNstates,
-				   sizeof(unsigned char))))
-		    {
-			ty = "TCP state inclusion";
-			goto no_IorX_space;
-		    }
-		}
-		if (!TcpStX) {
-		    if (!(TcpStX = (unsigned char *)calloc((MALLOC_S)TcpNstates,
-				   sizeof(unsigned char))))
-		    {
-			ty = "TCP state exclusion";
-			goto no_IorX_space;
-		    }
-		}
-	    }
-	}
-/*
- * Convert the state names in the rest of the string to state indexes and
- * record them in the appropriate inclusion or exclusion table.
- */
-	if (ssc)
-	    (void) free((MALLOC_P *)ssc);
-	if (!(ssc = mkstrcpy(cp, (MALLOC_S *)NULL))) {
-	    (void) fprintf(stderr,
-		"%s: no temporary state argument space for: %s\n", Pn, ss);
-	    Error();
-	}
-	cp = ssc;
-	err = 0;
-	while (*cp) {
-
-	/*
-	 * Determine inclusion or exclusion for this state name.
-	 */
-	    if (*cp == '^') {
-		x = 1;
-		cp++;
-	    } else
-		x = 0;
-	/*
-	 * Find the end of the state name.  Make sure it is non-null in length
-	 * and terminated with '\0'.
-	 */
-	    ns = cp;
-	    while (*cp && (*cp != ',')) {
-		cp++;
-	    }
-	    ne = cp;
-	    if (*cp) {
-		*cp = '\0';
-		cp++;
-	    }
-	    if (!(len = (size_t)(ne - ns))) {
-		(void) fprintf(stderr, "%s: NULL %s state name in: %s\n",
-		    Pn, pr, ss);
-		err = 1;
-		continue;
-	    }
-	/*
-	 * Find the state name in the appropriate table.
-	 */
-	    f = 0;
-	    if (tx) {
-		if (UdpSt) {
-		    for (i = 0; i < UdpNstates; i++) {
-			if (!strcasecmp(ns, UdpSt[i])) {
-			    f = 1;
-			    break;
-			}
-		    }
-		}
-	    } else {
-		if (TcpSt) {
-		    for (i = 0; i < TcpNstates; i++) {
-			if (!strcasecmp(ns, TcpSt[i])) {
-			    f = 1;
-			    break;
-			}
-		    }
-		}
-	    }
-	    if (!f) {
-		(void) fprintf(stderr, "%s: unknown %s state name: %s\n",
-		    Pn, pr, ns);
-		err = 1;
-		continue;
-	    }
-	/*
-	 * Set the inclusion or exclusion status in the appropriate table.
-	 */
-	    d = 0;
-	    if (x) {
-		if (tx) {
-		    if (!UdpStX[i]) {
-			UdpStX[i] = 1;
-			UdpStXn++;
-		    } else
-			d = 1;
-		} else {
-		    if (!TcpStX[i]) {
-			TcpStX[i] = 1;
-			TcpStXn++;
-		    } else
-			d = 1;
-		}
-	    } else {
-		if (tx) {
-		    if (!UdpStI[i]) {
-			UdpStI[i] = 1;
-			UdpStIn++;
-		    } else
-			d = 1;
-		} else {
-		    if (!TcpStI[i]) {
-			TcpStI[i] = 1;
-			TcpStIn++;
-		    } else
-			d = 1;
-		}
-	    }
-	    if (d) {
-
-	    /*
-	     * Report a duplicate.
-	     */
-		(void) fprintf(stderr, "%s: duplicate %s %sclusion: %s\n",
-		    Pn, pr,
-		    x ? "ex" : "in",
-		    ns);
-		err = 1;
-	    }
-	}
-/*
- * Release any temporary space and return.
- */
-	if (ssc) {
-	    (void) free((MALLOC_P *)ssc);
-	    ssc = (char *)NULL;
-	}
-	return(err);
-}
-#endif	/* defined(HASTCPUDPSTATE) */
-
-
-/*
- * enter_str_lst() - enter a string on a list
- */
-
-int
-enter_str_lst(opt, s, lp, incl, excl)
-	char *opt;			/* option name */
-	char *s;			/* string to enter */
-	struct str_lst **lp;		/* string's list */
-	int *incl;			/* included count */
-	int *excl;			/* excluded count */
-{
-	char *cp;
-	short i, x;
-	MALLOC_S len;
-	struct str_lst *lpt;
-
-	if (!s || *s == '-' || *s == '+') {
-	    (void) fprintf(stderr, "%s: missing %s option value\n",
-		Pn, opt);
-	    return(1);
-	}
-	if (*s == '^') {
-	    i = 0;
-	    x = 1;
-	    s++;
-	} else {
-	    i = 1;
-	    x = 0;
-	}
-	if (!(cp = mkstrcpy(s, &len))) {
-	    (void) fprintf(stderr, "%s: no string copy space: ", Pn);
-	    safestrprt(s, stderr, 1);
-	    return(1);
-	}
-	if ((lpt = (struct str_lst *)malloc(sizeof(struct str_lst))) == NULL) {
-	    (void) fprintf(stderr, "%s: no list space: ", Pn);
-	    safestrprt(s, stderr, 1);
-	    (void) free((FREE_P *)cp);
-	    return(1);
-	}
-	lpt->f = 0;
-	lpt->str = cp;
-	lpt->len = (int)len;
-	lpt->x = x;
-	if (i)
-	    *incl += 1;
-	if (x)
-	    *excl += 1;
-	lpt->next = *lp;
-	*lp = lpt;
-	return(0);
-}
-
-
-/*
- * enter_uid() - enter User Identifier for searching
- */
-
-int
-enter_uid(us)
-	char *us;			/* User IDentifier string pointer */
-{
-	int err, i, j, lnml, nn;
-	unsigned char excl;
-	MALLOC_S len;
-	char lnm[LOGINML+1], *lp;
-	struct passwd *pw;
-	char *s, *st;
-	uid_t uid;
-
-	if (!us) {
-	    (void) fprintf(stderr, "%s: no UIDs specified\n", Pn);
-	    return(1);
-	}
-	for (err = 0, s = us; *s;) {
-
-	/*
-	 * Assemble next User IDentifier.
-	 */
-	    for (excl = i = j = lnml = nn = uid = 0, st = s;
-		 *s && *s != ',';
-		 i++, s++)
-	    {
-		if (lnml >= LOGINML) {
-		    while (*s && *s != ',') {
-			s++;
-			lnml++;
-		    }
-		    (void) fprintf(stderr,
-			"%s: -u login name > %d characters: ", Pn,
-			    (int)LOGINML);
-		    safestrprtn(st, lnml, stderr, 1);
-		    err = j = 1;
-		    break;
-		}
-		if (i == 0 && *s == '^') {
-		    excl = 1;
-		    continue;
-		}
-		lnm[lnml++] = *s;
-		if (nn)
-		    continue;
-
-#if	defined(__STDC__)
-		if (isdigit((unsigned char)*s))
-#else	/* !defined(__STDC__) */
-		if (isascii(*s) && isdigit((unsigned char)*s))
-#endif	/* defined(__STDC__) */
-
-		    uid = (uid * 10) + *s - '0';
-		else
-		    nn++;
-	    }
-	    if (*s)
-		s++;
-	    if (j)
-		continue;
-	    if (nn) {
-	       lnm[lnml++] = '\0';
-		if ((pw = getpwnam(lnm)) == NULL) {
-		    (void) fprintf(stderr, "%s: can't get UID for ", Pn);
-		    safestrprt(lnm, stderr, 1);
-		    err = 1;
-		    continue;
-		} else
-		    uid = pw->pw_uid;
-	    }
-
-#if	defined(HASSECURITY) && !defined(HASNOSOCKSECURITY)
-	/*
-	 * If the security mode is enabled, only the root user may list files
-	 * belonging to user IDs other than the real user ID of this lsof
-	 * process.  If HASNOSOCKSECURITY is also defined, then anyone may
-	 * list anyone else's socket files.
-	 */
-	    if (Myuid && uid != Myuid) {
-		(void) fprintf(stderr,
-		    "%s: ID %d request rejected because of security mode.\n",
-		    Pn, uid);
-		err = 1;
-		continue;
-	    }
-#endif	/* defined(HASSECURITY)  && !defined(HASNOSOCKSECURITY) */
-
-	/*
-	 * Avoid entering duplicates.
-	 */
-	    for (i = j = 0; i < Nuid; i++) {
-		if (uid != Suid[i].uid)
-		    continue;
-		if (Suid[i].excl == excl) {
-		    j = 1;
-		    continue;
-		}
-		(void) fprintf(stderr,
-		    "%s: UID %d has been included and excluded.\n",
-			Pn, (int)uid);
-		err = j = 1;
-		break;
-	    }
-	    if (j)
-		continue;
-	/*
-	 * Allocate space for User IDentifier.
-	 */
-	    if (Nuid >= Mxuid) {
-		Mxuid += UIDINCR;
-		len = (MALLOC_S)(Mxuid * sizeof(struct seluid));
-		if (!Suid)
-		    Suid = (struct seluid *)malloc(len);
-		else
-		    Suid = (struct seluid *)realloc((MALLOC_P *)Suid, len);
-		if (!Suid) {
-		    (void) fprintf(stderr, "%s: no space for UIDs", Pn);
-		    Error();
-		}
-	    }
-	    if (nn) {
-		if (!(lp = mkstrcpy(lnm, (MALLOC_S *)NULL))) {
-		    (void) fprintf(stderr, "%s: no space for login: ", Pn);
-		    safestrprt(lnm, stderr, 1);
-		    Error();
-		}
-		Suid[Nuid].lnm = lp;
-	    } else
-		Suid[Nuid].lnm = (char *)NULL;
-	    Suid[Nuid].uid = uid;
-	    Suid[Nuid++].excl = excl;
-	    if (excl)
-		Nuidexcl++;
-	    else
-		Nuidincl++;
-	}
-	return(err);
-}
-
-
-/*
- * isIPv4addr() - is host name an IPv4 address
- */
-
-static char *
-isIPv4addr(hn, a, al)
-	char *hn;			/* host name */
-	unsigned char *a;		/* address receptor */
-	int al;				/* address receptor length */
-{
-	int dc = 0;			/* dot count */
-	int i;				/* temorary index */
-	int ov[MIN_AF_ADDR];		/* octet values */
-	int ovx = 0;			/* ov[] index */
-/*
- * The host name must begin with a number and the return octet value
- * arguments must be acceptable.
- */
-	if ((*hn < '0') || (*hn > '9'))
-	    return((char *)NULL);
-	if (!a || (al < MIN_AF_ADDR))
-	    return((char *)NULL);
-/*
- * Start the first octet assembly, then parse tge remainder of the host
- * name for four octets, separated by dots.
- */
-	ov[0] = (int)(*hn++ - '0');
-	while (*hn && (*hn != ':')) {
-	    if (*hn == '.') {
-
-	    /*
-	     * Count a dot.  Make sure a preceding octet value has been
-	     * assembled.  Don't assemble more than MIN_AF_ADDR octets.
-	     */
-		dc++;
-		if ((ov[ovx] < 0) || (ov[ovx] > 255))
-		    return((char *)NULL);
-		if (++ovx > (MIN_AF_ADDR - 1))
-		    return((char *)NULL);
-		ov[ovx] = -1;
-	    } else if ((*hn >= '0') && (*hn <= '9')) {
-
-	    /*
-	     * Assemble an octet.
-	     */
-		if (ov[ovx] < 0)
-		    ov[ovx] = (int)(*hn - '0');
-		else
-		    ov[ovx] = (ov[ovx] * 10) + (int)(*hn - '0');
-	    } else {
-
-	    /*
-	     * A non-address character has been detected.
-	     */
-		return((char *)NULL);
-	    }
-	    hn++;
-	}
-/*
- * Make sure there were three dots and four non-null octets.
- */
-	if ((dc != 3)
-	||  (ovx != (MIN_AF_ADDR - 1))
-	||  (ov[ovx] < 0) || (ov[ovx] > 255))
-	    return((char *)NULL);
-/*
- * Copy the octets as unsigned characters and return the ending host name
- * character position.
- */
-	for (i = 0; i < MIN_AF_ADDR; i++) {
-	     a[i] = (unsigned char)ov[i];
-	}
-	return(hn);
-}
-
-
-/*
- * lkup_hostnm() - look up host name
- */
-
-static struct hostent *
-lkup_hostnm(hn, n)
-	char *hn;			/* host name */
-	struct nwad *n;			/* network address destination */
-{
-	unsigned char *ap;
-	struct hostent *he;
-	int ln;
-/*
- * Get hostname structure pointer.  Return NULL if there is none.
- */
-
-#if	defined(HASIPv6)
-	he = gethostbyname2(hn, n->af);
-#else	/* !defined(HASIPv6) */
-	he = gethostbyname(hn);
-#endif	/* defined(HASIPv6) */
-
-	if (!he)
-	    return(he);
-/*
- * Copy first hostname structure address to destination structure.
- */
-
-#if	defined(HASIPv6)
-	if (n->af != he->h_addrtype)
-	    return((struct hostent *)NULL);
-	if (n->af == AF_INET6) {
-
-	/*
-	 * Copy an AF_INET6 address.
-	 */
-	    if (he->h_length > MAX_AF_ADDR)
-		return((struct hostent *)NULL);
-	    (void) memcpy((void *)&n->a[0], (void *)he->h_addr, he->h_length);
-	    if ((ln = MAX_AF_ADDR - he->h_length) > 0)
-		zeromem((char *)&n->a[he->h_length], ln);
-	    return(he);
-	}
-#endif	/* defined(HASIPv6) */
-
-/*
- * Copy an AF_INET address.
- */
-	if (he->h_length != 4)
-	    return((struct hostent *)NULL);
-	ap = (unsigned char *)he->h_addr;
-	n->a[0] = *ap++;
-	n->a[1] = *ap++;
-	n->a[2] = *ap++;
-	n->a[3] = *ap;
-	if ((ln = MAX_AF_ADDR - 4) > 0)
-	    zeromem((char *)&n->a[4], ln);
-	return(he);
-}
diff --git a/autotools/autotools.h.in b/autotools/autotools.h.in
new file mode 100644
index 0000000..3926081
--- /dev/null
+++ b/autotools/autotools.h.in
@@ -0,0 +1,257 @@
+/*
+ *  autotools.h: header shim for autotools
+ */
+
+/*
+ * 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.
+ */
+
+#if	!defined(LSOF_AUTOTOOLS_H)
+#define	LSOF_AUTOTOOLS_H	1
+
+#ifndef AUTOTOOLS
+#error "This file should only be included when built using autotools"
+#endif
+
+#include "config.h"
+
+#if !HAVE_RPC_RPC_H && !HAVE_LIBTIRPC
+#define HASNORPC_H
+#endif
+
+#if HAVE_DECL___GLIBC__
+#define GLIBCV
+#endif
+
+#if HAVE_DECL_AF_INET6 || HAVE_NETINET6_IN6_H || HAVE_NETINET_IN6_H || HAVE_NETINET_IP6_H
+#define HASIPv6
+#endif
+
+#if HAVE_DECL_TCP_ESTABLISHED
+#define NEEDS_NETINET_TCPH
+#endif
+
+#if HAVE_LINUX_SOCK_DIAG_H && HAVE_LINUX_UNIX_DIAG_H
+#define HASUXSOCKEPT
+#endif
+
+#if HAVE_DECL_TTYAUX_MAJOR
+#define HASPTYEPT
+#endif
+
+#if HAVE_DECL_SS_CONNECTED
+#define HASSOSTATE
+#define HASSOOPT
+#endif
+
+#if HAVE_STRFTIME
+#define HAS_STRFTIME
+#endif
+
+#if HAVE_SELINUX_SELINUX_H
+#define HASSELINUX
+#endif
+
+#if HAVE_UTMPX_H
+#define HASUTMPX
+#endif
+
+#if HAVE_VM_MEMATTR_T
+#define HAS_VM_MEMATTR_T
+#endif
+
+#if HAVE_DECL_DOADUMP
+#define NEEDS_BOOLEAN_T
+#endif
+
+#if HAVE_KVM_VNODE
+#define HAS_KVM_VNODE
+#endif
+
+#if HAVE_DECL_SBS_CANTSENDMORE
+#define HASSBSTATE
+#endif
+
+#if HAVE_STRUCT_KINFO_PROC_KI_NUMTHREADS
+#define HASTASKS
+#endif
+
+#if HAVE_STRUCT_FILE_F_VNODE
+#define HASF_VNODE
+#endif
+
+#if HAVE_STRUCT_FILEDESCENT
+#define HAS_FILEDESCENT
+#endif
+
+/* Do not include wctype.h in AIX to avoid duplicate time error */
+#if HAVE_WCTYPE_H && !defined(AIXV)
+#define HASWCTYPE_H
+#endif
+
+#if HAVE_STRUCT_INODE_I_DIN2
+#define HAS_UFS1_2
+#endif
+
+#if HAVE_STRUCT_VNODE_V_LOCKF
+#define HAS_V_LOCKF
+#endif
+
+/* Check fdescfs v1 on FreeBSD if needed later */
+#if HAVE_FS_FDESCFS_FDESC_H
+#define HASFDESCFS 2
+#endif
+
+/* Check fdescfs v2 on NetBSD if needed later */
+#if HAVE_MISCFS_FDESC_FDESC_H
+#define HASFDESCFS 1
+#endif
+
+#if HAVE_FS_NULLFS_NULL_H || HAVE_MISCFS_NULLFS_NULL_H
+#define HASNULLFS
+#endif
+
+#if HAVE_STRUCT_XTCPCB_T_MAXSEG
+#define HAS_XTCPCB_TMAXSEG
+#endif
+
+#if HAVE_STRUCT_KINFO_FILE_KF_UN_KF_SOCK_KF_SOCK_SENDQ
+#define HAS_KF_SOCK_SENDQ
+#endif
+
+#if HAVE_STRUCT_KINFO_FILE_KF_UN_KF_FILE_KF_FILE_NLINK
+#define HAS_KF_FILE_NLINK
+#endif
+
+#if HAVE_NFS_NFSPROTO_H
+#define HASNFSPROTO
+#endif
+
+#if HAVE_UVM_UVM_H
+#define UVM
+#define HAS_UVM_INCL
+#endif
+
+#if HAVE_STRUCT_STATVFS
+#define HASSTATVFS
+#endif
+
+#if HAVE_STRUCT_INODE_I_FFS1_SIZE
+#define HASI_FFS1
+#endif
+
+#if HAVE_DECL_GETBOOTFILE
+#define HASGETBOOTFILE
+#endif
+
+#if HAVE_DECL_KVM_GETPROC2
+#define HASKVMGETPROC2
+#endif
+
+#if HAVE_FS_PTYFS_PTYFS_H
+#define HASPTYFS
+#endif
+
+#if HAVE_MISCFS_PROCFS_PROCFS_H
+#define HASPROCFS
+#endif
+
+#if HAVE_DECL_PFSROOT
+#define HASPROCFS_PFSROOT
+#endif
+
+#if HAVE_FS_TMPFS_TMPFS_H
+#define HASTMPFS
+#endif
+
+#if HAVE_SYS_PIPE_H
+#define HAS_SYS_PIPEH
+#endif
+
+#if HAVE_STRUCT_FDESCNODE_FD_LINK
+#define HASFDLINK
+#endif
+
+#if HAVE_INET_IPCLASSIFIER_H
+#define HAS_IPCLASSIFIER_H
+#endif
+
+#if HAVE_SYS_ZONE_H
+#define HASZONES
+#endif
+
+#if HAVE_PAD_MUTEX_T
+#define HAS_PAD_MUTEX
+#endif
+
+#if HAVE_LIBCTF_H
+#define HAS_LIBCTF
+#endif
+
+#if HAVE_DECL_PC_DIRENTPERSEC
+#define HAS_PC_DIRENTPERSEC
+#endif
+
+#if HAVE_SYS_FS_ZFS_H
+#define HAS_ZFS
+#endif
+
+#if HAVE_SYS_CRED_IMPL_H
+#define HAS_CRED_IMPL_H
+#endif
+
+#if HAVE_STRUCT_CONN_S_CONN_IXA
+#define HAS_CONN_NEW
+#endif
+
+#if HAVE_STRUCT_VNODE_V_PATH
+#define HAS_V_PATH
+#endif
+
+#if HAVE_DECL_VSOCK
+#define HAS_VSOCK
+#endif
+
+#if HAVE_STRUCT_AIO_REQ
+#define HAS_AIO_REQ_STRUCT
+#endif
+
+#if HAVE_SYS_RGM_H
+#define HAS_SYS_RGM_H
+#endif
+
+#if HAVE_RPC_RPC_TAGS_H
+#define HAS_RPC_RPC_TAGS_H
+#endif
+
+#if HAVE_DECL_DUP2
+#define HAS_DUP2
+#endif
+
+#if HAVE_DECL_CLOSEFROM
+#define HAS_CLOSEFROM
+#endif
+
+#endif
diff --git a/autotools/version.h.in b/autotools/version.h.in
new file mode 100644
index 0000000..aac0b80
--- /dev/null
+++ b/autotools/version.h.in
@@ -0,0 +1,49 @@
+/*
+ *  version.h: generate version info for autotools
+ */
+
+/*
+ * 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.
+ */
+
+#if	!defined(LSOF_VERSION_H)
+#define	LSOF_VERSION_H	1
+
+#ifndef AUTOTOOLS
+#error "This file should only be included when built using autotools"
+#endif
+
+#include "config.h"
+#define LSOF_VERSION PACKAGE_VERSION
+#define LSOF_HOST "@host@"
+#define LSOF_LOGNAME "@logname@"
+#define LSOF_USER "@user@"
+#define LSOF_CC "@cc@"
+#define LSOF_CCV "@ccv@"
+#define LSOF_CCFLAGS "@ccflags@"
+#define LSOF_LDFLAGS "@ldflags@"
+#define LSOF_SYSINFO "@sysinfo@"
+
+#endif
diff --git a/check.bash b/check.bash
index c392c47..17486e7 100755
--- a/check.bash
+++ b/check.bash
@@ -5,7 +5,7 @@ if [ $# = 0 ]; then
     exit 1
 fi
 
-if ! [ -d dialects/$1 ]; then
+if ! [ -d lib/dialects/$1 ]; then
     echo "No such dialect: $1" 1>&2
     exit 1
 fi
@@ -26,7 +26,7 @@ $lsof -v
 
 export CI=1
 
-tdir=dialects/${dialect}/tests
+tdir=lib/dialects/${dialect}/tests
 
 nfailed=0
 nsuccessful=0
@@ -63,7 +63,7 @@ run_one()
         s=ok
         nsuccessful=$((nsuccessful + 1))
         rm -f "$report"
-    elif [ "$s" = 2 ]; then
+    elif [ "$s" = 77 ]; then
         s=skipped
         nskipped=$((nskipped + 1))
         REPORTS_SKIPPED="${REPORTS_SKIPPED} ${report}"
@@ -86,7 +86,7 @@ done
 echo
 echo STARTING TEST '(' $dialect specific ')'
 echo =============================================================================
-for x in  dialects/${dialect}/tests/case-*.bash; do
+for x in lib/dialects/${dialect}/tests/case-*.bash; do
     run_one $x $tdir
 done
 
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..ecbfd28
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,598 @@
+AC_INIT([lsof],[4.99.4])
+AM_INIT_AUTOMAKE([subdir-objects])
+LT_INIT([disable-fast-install]) # avoid lt-lsof naming
+# Locate custom m4 macros
+AC_CONFIG_MACRO_DIR([m4])
+
+# Require C compiler
+AC_PROG_CC
+# For legacy automake on e.g. CentOS 7
+AM_PROG_CC_C_O
+
+# Detect OS
+AC_CANONICAL_HOST
+
+LSOF_VSTR=$(uname -r)
+LSOF_DIALECT=unknown
+LSOF_DIALECT_DIR=unknown
+LSOF_TGT=unknown
+AS_CASE([${host_os}],
+[linux*], [
+	LSOF_DIALECT=linux
+	LSOF_DIALECT_DIR=linux
+	LSOF_TGT=linux
+
+	# Compute version
+	LSOF_VERS=$(echo $LSOF_VSTR | sed 's/\./ /g' | awk '{printf "%d%d%03d",$1,$2,$3}')
+
+	# Always use large file
+	CFLAGS="$CFLAGS -D_FILE_OFFSET_BITS=64"
+
+	# Enable LTbigf test
+	LSOF_TEST_CFLAGS="$LSOF_TEST_CFLAGS -DLT_BIGF -D_FILE_OFFSET_BITS=64"
+], [darwin*], [
+	LSOF_DIALECT=darwin
+	LSOF_DIALECT_DIR=darwin
+	LSOF_TGT=darwin
+
+	AS_CASE([$LSOF_VSTR],
+	[7.*],	[LSOF_VERS=700],		# Mac OS X 10.3 (Panther)
+	[8.*],	[LSOF_VERS=800],		# Mac OS X 10.4 (Tiger)
+	[9.*],	[LSOF_VERS=900],		# Mac OS X 10.5 (Leopard)
+	[10.*],	[LSOF_VERS=1000],		# Mac OS X 10.6 (SnowLeopard)
+	[11.*],	[LSOF_VERS=1100],		# Mac OS X 10.7 (Lion)
+	[12.*],	[LSOF_VERS=1200],		# Mac OS X 10.8 (Mountain Lion)
+	[13.*],	[LSOF_VERS=1300],		# Mac OS X 10.9 (Mavericks)
+	[14.*],	[LSOF_VERS=1400],		# Mac OS X 10.10 (Yosemite)
+	[15.*],	[LSOF_VERS=1500],		# Mac OS X 10.11 (El Capitan)
+	[16.*],	[LSOF_VERS=1600],		# macOS 10.12 (Sierra)
+	[17.*],	[LSOF_VERS=1700],		# macOS 10.13 (High Sierra)
+	[18.*],	[LSOF_VERS=1800],		# macOS 10.14 (Mojave)
+	[19.*],	[LSOF_VERS=1900],		# macOS 10.15 (Catalina)
+	[
+		AC_MSG_NOTICE([Unknown Darwin release: $(uname -r)])
+		AC_MSG_NOTICE([Assuming Darwin 19.0])
+		LSOF_VERS=1900
+	])
+
+	# Add DARWINV to cflags
+	CFLAGS="$CFLAGS -DDARWINV=$LSOF_VERS"
+
+	# Enable LTbigf test
+	LSOF_TEST_CFLAGS="$LSOF_TEST_CFLAGS -DLT_BIGF"
+], [freebsd*], [
+	LSOF_DIALECT=freebsd
+	LSOF_DIALECT_DIR=freebsd
+	LSOF_TGT=freebsd
+
+	AS_CASE([$LSOF_VSTR],
+	[10*],	[LSOF_VERS=10000],
+	[11*],	[LSOF_VERS=11000],
+	[12*],	[LSOF_VERS=12000],
+	[13*],	[LSOF_VERS=13000],
+	[14*],	[LSOF_VERS=14000],
+	[15*],	[LSOF_VERS=15000], [
+		AC_MSG_ERROR([Unknown FreeBSD release: $(uname -r)])
+	])
+
+	# Add FREEBSDV to cflags
+	CFLAGS="$CFLAGS -DFREEBSDV=$LSOF_VERS"
+
+	# Always define HASPROCFS
+	CFLAGS="$CFLAGS -DHASPROCFS"
+
+	# Always link libutil
+	LDFLAGS="$LDFLAGS -lutil"
+
+	# Detect FreeBSD source code
+	AS_IF([test -d /usr/src/sys], [
+		FREEBSD_SYS=/usr/src/sys
+	], [test -d /sys], [
+		FREEBSD_SYS=/sys
+	], [
+		AC_MSG_WARN([No kernel sources in /usr/src/sys or /sys])
+	])
+
+	# Enable LTbigf test
+	LSOF_TEST_CFLAGS="$LSOF_TEST_CFLAGS -DLT_BIGF"
+], [netbsd*],  [
+	LSOF_DIALECT=netbsd
+	LSOF_DIALECT_DIR=netbsd
+	LSOF_TGT=netbsd
+
+	case $LSOF_VSTR in
+		8.[[0123]]*)
+			LSOF_VERS="8000000"
+			;;
+		8.99.*)
+			LSOF_VERS="8099000"
+			;;
+		8.*)
+			LSOF_VERS="8000000"
+			AC_MSG_WARN([Unsupported NetBSD release: $(uname -r)])
+			AC_MSG_WARN([Configuring for NetBSD 8.0])
+			;;
+		9.[[0123]]*)
+			LSOF_VERS="9000000"
+			;;
+		9.99.10[[45678]])
+			LSOF_VERS="9099104"
+			;;
+		9.99.*)
+			LSOF_VERS="9099000"
+			;;
+		9.*)
+			LSOF_VERS="9000000"
+			AC_MSG_WARN([Unsupported NetBSD release: $(uname -r)])
+			AC_MSG_WARN([Configuring for NetBSD 9.0])
+			;;
+		10.99.*)
+			LSOF_VERS="10099000"
+			;;
+		10.*)
+			LSOF_VERS="10000000"
+			AC_MSG_WARN([Unsupported NetBSD release: $(uname -r)])
+			AC_MSG_WARN([Configuring for NetBSD 10.0])
+			;;
+		*)
+			AC_MSG_ERROR([Unknown NetBSD release: $(uname -r)])
+			;;
+	esac
+
+	# Add NETBSDV to cflags
+	CFLAGS="$CFLAGS -DNETBSDV=$LSOF_VERS"
+
+	# Define _KMEMUSER for paddr_t and __NAMECACHE_PRIVATE for struct namecache
+	CFLAGS="$CFLAGS -D_KMEMUSER -D__NAMECACHE_PRIVATE"
+
+	# Define HASNFSVATTRP because the relevant change in kernel src is in 1997
+	# We can safely assume that n_vattr is a pointer
+	CFLAGS="$CFLAGS -DHASNFSVATTRP"
+
+	# Check /dev/kmem
+	LSOF_TEST_CFLAGS="$LSOF_TEST_CFLAGS -DLT_KMEM"
+
+	# Detect NetBSD source code
+	AS_IF([test -d /usr/src/sys], [
+		NETBSD_SYS=/usr/src/sys
+		CFLAGS="$CFLAGS -I$NETBSD_SYS"
+	], [
+		AC_MSG_WARN([No kernel sources in /usr/src/sys])
+	])
+], [openbsd*], [
+	LSOF_DIALECT=openbsd
+	LSOF_DIALECT_DIR=openbsd
+	LSOF_TGT=openbsd
+
+	AS_CASE([$LSOF_VSTR],
+	[7.2],	[LSOF_VERS=7020],
+	[7.3],	[LSOF_VERS=7030],
+	[
+		AC_MSG_NOTICE([Unknown OpenBSD release: $(uname -r)])
+		AC_MSG_NOTICE([Assuming OpenBSD 7.3])
+		LSOF_VERS=7030
+	])
+], [solaris*], [
+	LSOF_DIALECT=solaris
+	LSOF_DIALECT_DIR=sun
+	LSOF_TGT=solaris
+
+	AS_CASE([$LSOF_VSTR],
+	[5.11],	[LSOF_VERS=110000],
+	[
+		AC_MSG_NOTICE([Unknown Solaris release: $(uname -r)])
+		AC_MSG_NOTICE([Assuming Solaris 5.11])
+		LSOF_VERS=110000
+	])
+
+	# Add solaris to cflags
+	CFLAGS="$CFLAGS -Dsolaris=$LSOF_VERS"
+
+	# Link system libraries
+	LIBS="$LIBS -lelf -lsocket -lnsl"
+
+	# Handle missing header
+	mkdir -p ./solaris11/sys
+	touch ./solaris11/sys/extdirent.h
+	CFLAGS="$CFLAGS -Isolaris11"
+], [aix*], [
+	LSOF_DIALECT=aix
+	LSOF_DIALECT_DIR=aix
+	LSOF_TGT=aix
+
+	LSOF_TMP1=/usr/bin/oslevel
+	AS_IF([test -x $LSOF_TMP1], [
+		echo "Determining AIX version with $LSOF_TMP1."
+		echo "This may take a while, depending on your maintenance level."
+		LSOF_VSTR=`$LSOF_TMP1 | sed 's/[^0-9]*\([0-9\.]*\).*/\1/'`
+		echo "$LSOF_TMP1 reports the version is $LSOF_VSTR."
+	], [
+		# If oslevel can't be used, build the version string with
+		# `uname -rv` and issue a warning.
+
+		LSOF_VSTR=`uname -rv | awk '{printf "%d.%d.0.0\n",\$2,\$1}'`
+		echo "WARNING: can't execute $LSOF_TMP1; uname -rv reports"
+		echo "         the version is $LSOF_VSTR;"
+	])
+
+	LSOF_VERS=`echo $LSOF_VSTR | sed 's/\.//g'`
+
+	# Add AIXV to cflags
+	CFLAGS="$CFLAGS -DAIXV=$LSOF_VERS"
+
+	# Assuming recent AIX on PowerPC64
+	CFLAGS="$CFLAGS -maix64 -DAIXA=1 -DAIX_KERNBITS=64 -DHASSTAT64"
+	LSOF_TEST_CFLAGS="$LSOF_TEST_CFLAGS -DLT_AIXA=1"
+
+	# JFS2 support
+	# Add -fms-extensions to handle use of i_dev from the wInode anonymous
+	# structure reference in the JFS2 inode structure of <j2/j2_inode.h>.
+	CFLAGS="$CFLAGS -DHAS_JFS2 -I./lib/dialects/aix/aix5 -fms-extensions"
+], [
+	AC_MSG_ERROR(["Host $host_os not supported"])
+])
+
+# Pass dialect info to Makefile.am
+AM_CONDITIONAL([LINUX], [test x$LSOF_DIALECT_DIR = xlinux])
+AM_CONDITIONAL([DARWIN], [test x$LSOF_DIALECT_DIR = xdarwin])
+AM_CONDITIONAL([FREEBSD], [test x$LSOF_DIALECT_DIR = xfreebsd])
+AM_CONDITIONAL([NETBSD], [test x$LSOF_DIALECT_DIR = xnetbsd])
+AM_CONDITIONAL([OPENBSD], [test x$LSOF_DIALECT_DIR = xopenbsd])
+AM_CONDITIONAL([SOLARIS], [test x$LSOF_DIALECT_DIR = xsun])
+AM_CONDITIONAL([AIX], [test x$LSOF_DIALECT_DIR = xaix])
+
+# Pass OS version
+AS_IF([test x$LSOF_DIALECT_DIR != xlinux], [
+	LSOF_TMP=$(echo $LSOF_VSTR | sed 's/(/\\\\(/g' | sed 's/)/\\\\)/g')
+	CFLAGS="$CFLAGS -DLSOF_VSTR=\\\"$LSOF_TMP\\\""
+])
+
+# Pass LSOF_DIALECT/LSOF_DIALECT_DIR to Makefile.am
+AC_SUBST([LSOF_DIALECT])
+AC_SUBST([LSOF_DIALECT_DIR])
+
+# Export public function with default visibility
+AC_DEFINE([API_EXPORT], [__attribute__ ((visibility ("default")))],
+	[Set visibility to default for exported API functions.])
+
+# --enable-liblsof to install liblsof
+AC_ARG_ENABLE(liblsof, AS_HELP_STRING([--enable-liblsof],
+	[build and install liblsof @<:@default=yes@:>@]), [], [enable_liblsof=yes])
+AM_CONDITIONAL([INSTALL_LIBLSOF], [test "x$enable_liblsof" = xyes])
+
+# --enable-security to define HASSECURITY
+AC_ARG_ENABLE(security, AS_HELP_STRING([--enable-security],
+	[allow only the root user to list all open files @<:@default=no@:>@]), [], [enable_security=no])
+AS_IF([test "x$enable_security" = xyes], [
+	CFLAGS="$CFLAGS -DHASSECURITY"
+])
+
+# --enable-no-sock-security to define HASNOSOCKSECURITY
+AC_ARG_ENABLE(no_sock_security, AS_HELP_STRING([--enable-no-sock-security],
+	[combined with --enable-security, allow anyone to list anyone else's socket files @<:@default=no@:>@]), [], [enable_no_sock_security=no])
+AS_IF([test "x$enable_no_sock_security" = xyes], [
+	AS_IF([test "x$enable_security" = xyes], [
+		CFLAGS="$CFLAGS -DHASNOSOCKSECURITY"
+	], [
+		AC_MSG_ERROR([--enable-no-sock-security must be used with --enable-security])
+	])
+])
+
+# Check rpc/rpc.h or libtirpc
+# with_libtirpc=yes/no/auto
+AC_ARG_WITH(libtirpc, AS_HELP_STRING([--with-libtirpc],
+	[build with libtirpc support @<:@default=auto@:>@]), [], [with_libtirpc=auto])
+AS_IF([test "x$with_libtirpc" != xno], [
+	PKG_CHECK_MODULES([LIBTIRPC], [libtirpc], [
+		CFLAGS="$CFLAGS $LIBTIRPC_CFLAGS"
+		LIBS="$LIBS $LIBTIRPC_LIBS"
+		with_libtirpc=yes
+	], [
+		AS_IF([test "x$with_libtirpc" = xyes], [
+			AC_MSG_ERROR([--with-libtirpc specified, but libtirpc could not be found])
+		])
+		with_libtirpc=no
+	])
+])
+
+AS_IF([test "x$with_libtirpc" = "xyes"],
+        [AC_DEFINE(HAVE_LIBTIRPC, 1, [Enable libtirpc support])])
+
+AC_CHECK_HEADERS([rpc/rpc.h])
+
+# Detect glibc for GLIBCV
+AC_CHECK_DECLS([__GLIBC__])
+
+# Detect ipv6 headers and definitions for HASIPv6
+AC_CHECK_DECLS([AF_INET6], [], [], [[#include <sys/socket.h>]])
+AC_CHECK_HEADERS([netinet6/in6.h netinet/in6.h netinet/ip6.h])
+
+# Detect tcp definitions for NEEDS_NETINET_TCPH
+AC_CHECK_DECLS([TCP_ESTABLISHED], [], [], [[#include <netinet/tcp.h>]])
+
+# Detect unix socket endpoint headers for HASUXSOCKEPT
+AC_CHECK_HEADERS([linux/sock_diag.h linux/unix_diag.h])
+
+# Detect pty endpoint definition for HASPTYEPT
+AC_CHECK_DECLS([TTYAUX_MAJOR], [], [], [[#include <linux/major.h>]])
+
+# Detect socket state definition for HASSOSTATE and HASSOOPT
+AC_CHECK_DECLS([SS_CONNECTED], [], [], [[#include <linux/net.h>]])
+
+# Define _FILE_OFFSET_BITS if necessary
+AC_SYS_LARGEFILE
+
+# Detect strftime function for HAS_STRFTIME
+AC_CHECK_FUNCS([strftime])
+
+# Detect selinux headers for HASSELINUX
+# with_selinux=yes/no/auto
+AC_ARG_WITH(selinux, AS_HELP_STRING([--with-selinux],
+	[build with selinux support @<:@default=auto@:>@]), [], [with_selinux=auto])
+AS_IF([test "x$with_selinux" != xno], [
+	AC_CHECK_HEADERS([selinux/selinux.h], [LIBS="$LIBS -lselinux"], [
+		AS_IF([test "x$with_selinux" = xyes], [
+			AC_MSG_ERROR([--with-selinux specified, but libselinux could not be found])
+		])
+	])
+])
+
+# Detect utmpx headers for HASUTMPX
+AC_CHECK_HEADERS([utmpx.h])
+
+# Detect vm_memattr_t definition for HAS_VM_MEMATTR_T
+AC_CHECK_TYPES([vm_memattr_t], [], [], [[#include <sys/types.h>
+		#include <vm/vm.h>]])
+
+# Detect doadump function for NEEDS_BOOLEAN_T
+AC_CHECK_DECLS([doadump], [], [], [[#define _KERNEL 1
+		#include <sys/types.h>
+		#include <sys/param.h>
+		#include <sys/conf.h>]])
+
+# Detect struct vnode definition for HAS_KVM_VNODE
+# Linking libkvm is not required in AIX
+AS_IF([test x$LSOF_DIALECT_DIR != xaix], [
+	AC_EGREP_CPP([struct vnode], [#define _KVM_VNODE 1
+			#include <sys/vnode.h>], [AC_DEFINE([HAVE_KVM_VNODE], [1], ["Define to 1 if struct vnode exists"])
+			LIBS="$LIBS -lkvm"])
+])
+
+# Detect SBS_CANTSENDMORE definition for HASSBSTATE
+AC_CHECK_DECLS([SBS_CANTSENDMORE], [], [], [[#include <sys/types.h>
+		#include <sys/socketvar.h>]])
+
+# Detect lockf_entry definition for HAS_LOCKF_ENTRY
+AC_CHECK_TYPES([struct lockf_entry], [
+	HEADER_GENERATE([lockf_owner.h], [${FREEBSD_SYS}/kern/kern_lockf.c], ["^struct lock_owner {"], ["^};"], [LOCKF_OWNER_H])
+	AC_MSG_NOTICE([lockf_owner.h creation succeeded.])
+	CFLAGS="$CFLAGS -DHAS_LOCKF_ENTRY"
+], [], [#include <sys/types.h>
+		#include <sys/lockf.h>])
+
+# Detect ki_numthreads definition for HASTASKS
+AC_CHECK_MEMBERS([struct kinfo_proc.ki_numthreads], [], [], [#include <sys/types.h>
+		#include <sys/user.h>])
+
+# Detect i_effnlink/i_ffs_effnlink for HASEFFNLINK
+AC_CHECK_MEMBERS([struct inode.i_effnlink], [CFLAGS="$CFLAGS -DHASEFFNLINK=i_effnlink"], [], [#define __BSD_VISIBLE 1
+		#include <sys/types.h>
+		#include <ufs/ufs/quota.h>
+		#include <ufs/ufs/inode.h>])
+
+# Detect struct file.f_vnode for HASF_VNODE
+AC_CHECK_MEMBERS([struct file.f_vnode], [], [], [#define __BSD_VISIBLE 1
+		#define _KERNEL 1
+		#define GENOFFSET
+		#include <sys/types.h>
+		#include <sys/file.h>])
+
+# Detect struct filedescent for HAS_FILEDESCENT
+AC_CHECK_TYPES([struct filedescent], [], [], [#define __BSD_VISIBLE 1
+		#include <sys/types.h>
+		#include <sys/filedesc.h>])
+
+# Detect fs/tmpfs/tmpfs.h for HAS_TMPFS
+AS_IF([test -r ${FREEBSD_SYS}/fs/tmpfs/tmpfs.h], [
+	AC_DEFINE([HAS_TMPFS], [1], [Define if fs/tmpfs/tmpfs.h is found])
+])
+
+# Detect wctype.h for HASWCTYPE_H
+AC_CHECK_HEADERS([wctype.h])
+
+# Detect struct inode.i_din2 for HAS_UFS1_2
+AC_CHECK_MEMBERS([struct inode.i_din2], [], [], [#define __BSD_VISIBLE 1
+		#include <sys/types.h>
+		#include <ufs/ufs/quota.h>
+		#include <ufs/ufs/inode.h>])
+
+# Detect struct vnode.v_lockf definition for HAS_V_LOCKF
+AC_CHECK_MEMBERS([struct vnode.v_lockf], [], [], [#define _KVM_VNODE 1
+		#define __BSD_VISIBLE 1
+		#include <sys/types.h>
+		#include <sys/vnode.h>])
+
+# Detect fdescfs version for HASFDESCFS
+AC_CHECK_HEADERS([fs/fdescfs/fdesc.h], [], [], [#define _KERNEL 1
+		#define __BSD_VISIBLE 1
+		#include <sys/types.h>
+		#include <sys/mount.h>])
+
+# Detect pseudofs for HASPSEUDOFS
+AS_IF([test -d ${FREEBSD_SYS}/fs/pseudofs], [
+	CFLAGS="$CFLAGS -DHASPSEUDOFS -I$FREEBSD_SYS"
+])
+
+# Detect nullfs for HASNULLFS
+AC_CHECK_HEADERS([fs/nullfs/null.h], [], [], [])
+
+# Detect struct xtcpcb.t_maxseg for HAS_XTCPCB_TMAXSEG
+AC_CHECK_MEMBERS([struct xtcpcb.t_maxseg], [], [], [#include <sys/types.h>
+	#include <sys/queue.h>
+	#include <sys/socketvar.h>
+	#include <sys/socket.h>
+	#include <netinet/in.h>
+	#include <netinet/in_pcb.h>
+	#include <netinet/tcp_var.h>])
+
+# Detect struct kinfo_file.kf_un.kf_sock.kf_sock_sendq for HAS_KF_SOCK_SENDQ
+AC_CHECK_MEMBERS([struct kinfo_file.kf_un.kf_sock.kf_sock_sendq], [], [], [#include <sys/types.h>
+	#include <sys/user.h>])
+
+# Detect struct kinfo_file.kf_un.kf_file.kf_file_nlink for HAS_KF_FILE_NLINK
+AC_CHECK_MEMBERS([struct kinfo_file.kf_un.kf_file.kf_file_nlink], [], [], [#include <sys/types.h>
+	#include <sys/user.h>])
+
+# Detect nfs/nfsproto.h for HASNFSPROTO
+AC_CHECK_HEADERS([nfs/nfsproto.h])
+
+# Detect uvm/uvm.h for HAS_UVM_INCL
+AC_CHECK_HEADERS([uvm/uvm.h])
+
+# Detect struct statvfs for HASSTATVFS
+AC_CHECK_TYPES([struct statvfs], [], [], [#include <sys/statvfs.h>])
+
+# Detect struct inode.i_ffs1_size for HASI_FFS1
+AC_CHECK_MEMBERS([struct inode.i_ffs1_size], [], [], [#include <ufs/ufs/inode.h>])
+
+# Detect getbootfile function for HASGETBOOTFILE
+AC_CHECK_DECLS([getbootfile()], [
+	LDFLAGS="$LDFLAGS -lutil"
+], [], [#include <util.h>])
+
+# Detect kvm_getproc2 function for HASKVMGETPROC2
+AC_CHECK_DECLS([kvm_getproc2], [], [], [#include <kvm.h>])
+
+# Detect fs/ptyfs/ptyfs.h header for HASPTYFS
+AC_CHECK_HEADERS([fs/ptyfs/ptyfs.h])
+
+# Detect fs/ptyfs/ptyfs.h header for HASPROCFS
+AC_CHECK_HEADERS([miscfs/procfs/procfs.h])
+
+# Detect PFSroot enum for HASPROCFS_PFSROOT
+AC_CHECK_DECLS([PFSroot], [], [], [#define _KERNEL
+	#include <sys/types.h>
+	#include <miscfs/procfs/procfs.h>])
+
+# Detect fs/tmpfs/tmpfs.h header for HASTMPFS
+AC_CHECK_HEADERS([fs/tmpfs/tmpfs.h])
+
+# Detect sys/pipe.h header for HAS_SYS_PIPEH
+AC_CHECK_HEADERS([sys/pipe.h])
+
+# Copy struct lockf definition from kernel source code for HAS_LOCKF_H
+AS_IF([test x$LSOF_DIALECT = xnetbsd], [
+	# Generate lockf.h from kern/vfs_lockf.c
+	HEADER_GENERATE([lockf.h], [${NETBSD_SYS}/kern/vfs_lockf.c], ["^TAILQ_HEAD"], ["^};"], [LOCKF_H])
+
+	AC_MSG_NOTICE([lockf.h creation succeeded])
+	CFLAGS="$CFLAGS -DHAS_LOCKF_H"
+])
+
+# Detect fdescfs version for HASFDESCFS
+AC_CHECK_HEADERS([miscfs/fdesc/fdesc.h])
+
+# Detect struct fdescnode.fd_link for HASFDLINK
+AC_CHECK_MEMBERS([struct fdescnode.fd_link], [], [], [#define _KERNEL
+	#include <sys/types.h>
+	#include <miscfs/fdesc/fdesc.h>])
+
+# Detect miscfs/nullfs/null.h header for HASNULLFS
+AC_CHECK_HEADERS([miscfs/nullfs/null.h], [], [], [#include <sys/mount.h>])
+
+# Detect dup2 for HAS_DUP2
+AC_CHECK_DECLS([dup2], [], [], [[#include <unistd.h>]])
+
+# Detect closefrom for HAS_CLOSEFROM
+AC_CHECK_DECLS([closefrom], [], [], [[#include <unistd.h>]])
+
+# Detect sizeof(dev_t) for LT_DEV64
+AC_CHECK_SIZEOF([dev_t])
+AS_IF([test "x$ac_cv_sizeof_dev_t" = x8], [
+	LSOF_TEST_CFLAGS="$LSOF_TEST_CFLAGS -DLT_DEV64"
+])
+
+# Detect inet/ipclassifier.h header for HAS_IPCLASSIFIER_H
+AC_CHECK_HEADERS([inet/ipclassifier.h], [], [], [#define _KERNEL
+	#include <inet/ip.h>])
+
+# Detect struct conn_s.conn_ixa header for HAS_CONN_NEW
+AC_CHECK_MEMBERS([struct conn_s.conn_ixa], [], [], [#define _KERNEL
+	#include <inet/ip.h>
+	#include <inet/ipclassifier.h>])
+
+# Detect sys/zone.h header for HASZONES
+AC_CHECK_HEADERS([sys/zone.h])
+
+# Detect pad_mutex_t for HAS_PAD_MUTEX
+AC_CHECK_TYPES([pad_mutex_t], [], [], [#define _KERNEL
+	#include <sys/mutex.h>])
+
+# Detect libctf.h header for HAS_LIBCTF
+AC_CHECK_HEADERS([libctf.h], [LIBS="$LIBS -lctf"])
+
+# Detect pc_direntpersec macro for HAS_PC_DIRENTPERSEC
+AC_CHECK_DECLS([pc_direntpersec((struct pcfs *)NULL)], [], [], [#include <sys/fs/pc_fs.h>])
+
+# Detect sys/fs/zfs.h header for HAS_ZFS
+AC_CHECK_HEADERS([sys/fs/zfs.h])
+
+# Detect sys/cred_impl.h header for HAS_CRED_IMPL_H
+AC_CHECK_HEADERS([sys/cred_impl.h])
+
+# Detect struct vnode.v_path for HAS_V_PATH
+AC_CHECK_MEMBERS([struct vnode.v_path], [
+	LSOF_TEST_CFLAGS="$LSOF_TEST_CFLAGS -DLT_VPATH"
+], [], [#include <sys/vnode.h>])
+
+# Detect VSOCK for HAS_VSOCK
+AC_CHECK_DECLS([VSOCK], [], [], [#include <sys/vnode.h>])
+
+# Detect struct aio_req for HAS_AIO_REQ_STRUCT
+AC_CHECK_TYPES([struct aio_req], [], [], [#define _KERNEL
+	#include <sys/aio_req.h>])
+
+# Detect sys/rgm.h header for HAS_SYS_RGM_H
+AC_CHECK_HEADERS([sys/rgm.h])
+
+# Detect rpc/rpc_tags.h header for HAS_RPC_RPC_TAGS_H
+AC_CHECK_HEADERS([rpc/rpc_tags.h])
+
+# Generate Makefile from Makefile.in/am
+AC_CONFIG_FILES([Makefile])
+
+# Pass build configurations to version.h.in
+AC_SUBST(cc, $CC)
+AC_SUBST(ccv, $($CC -v 2>&1 | sed -n 's/.*version \(.*\)/\1/p;q'))
+AC_SUBST(ccflags, $CFLAGS)
+AC_SUBST(ldflags, "$LDFLAGS$LIBS")
+# Reproducible build
+AS_IF([test "X$SOURCE_DATE_EPOCH" = "X"], [
+	AC_SUBST(host, $(uname -n))
+	AC_SUBST(logname, $LOGNAME)
+	AC_SUBST(user, $USER)
+	AC_SUBST(sysinfo, $(uname -a))
+])
+
+# Generate version.h/autotools.h
+AC_CONFIG_FILES([autotools/version.h autotools/autotools.h])
+
+# Generate version
+AC_CONFIG_FILES([version])
+
+# Generate config.h
+AC_CONFIG_HEADERS([config.h])
+
+# For VPATH building
+AC_CONFIG_LINKS([tests/common.bash:tests/common.bash
+	lib/dialects/linux/tests/util-open-flags.bash:lib/dialects/linux/tests/util-open-flags.bash
+	Lsof.8:Lsof.8 00DIALECTS:00DIALECTS 00DIST:00DIST])
+
+# Generate cflags for tests
+LSOF_TEST_CFLAGS="$LSOF_TEST_CFLAGS -DLT_DIAL_$LSOF_TGT -DLT_VERS=$LSOF_VERS"
+# Override default lsof path
+LSOF_TEST_CFLAGS="$LSOF_TEST_CFLAGS -DLT_DEF_LSOF_PATH=\\\"$PWD/lsof\\\""
+AC_SUBST([LSOF_TEST_CFLAGS])
+
+# Finish
+AC_OUTPUT
diff --git a/default.nix b/default.nix
new file mode 100644
index 0000000..74469d4
--- /dev/null
+++ b/default.nix
@@ -0,0 +1,24 @@
+with import <nixpkgs> {};
+
+stdenv.mkDerivation {
+  name = "lsof";
+  version = "1.0";
+
+  src = ./.;
+
+  postPatch = ''
+    patchShebangs .
+  '';
+
+  nativeBuildInputs = [
+    autoreconfHook
+    groff
+    pkg-config
+  ];
+
+  doCheck = true;
+  checkInputs = lib.optionals stdenv.isLinux [
+    util-linux
+    procps
+  ];
+}
diff --git a/dialects/linux/dfile.c b/dialects/linux/dfile.c
deleted file mode 100644
index b9a98bf..0000000
--- a/dialects/linux/dfile.c
+++ /dev/null
@@ -1,386 +0,0 @@
-/*
- * dfile.c - Linux file processing functions for /proc-based lsof
- */
-
-
-/*
- * 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 1997 Purdue Research Foundation.\nAll rights reserved.\n";
-#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 (dev,ino) 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	SFDIHASH	4094		/* Sfile hash by (device,inode) number
-					 * pair bucket count (power of 2!) */
-#define	SFFSHASH	1024		/* 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 mod
-					 * (mod must be a 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) */
-#define	SFNMHASH	4096		/* Sfile hash by name bucket count
-					 * (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, 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);
-	    Error();
-	}
-	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);
-	    Error();
-	}
-	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);
-	    Error();
-	}
-	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);
-	    Error();
-	}
-	hs++;
-/*
- * Scan the Sfile chain, building file, file system, raw device, and file
- * name hash bucket chains.
- */
-	for (s = Sfile; s; s = s->next) {
-	    for (i = 0; i < 3; i++) {
-		switch (i) {
-		case 0:			/* hash by name */
-		    if (!s->aname)
-			continue;
-		    sh = &HbyNm[hashbyname(s->aname, SFNMHASH)];
-		    HbyNmCt++;
-		    break;
-		case 1:			/* hash by device and inode, or file
-					 * system device */
-		    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++;
-		    }
-		    break;
-		case 2:			/* hash by file's raw device */
-		    if ((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;
-		}
-	    /*
-	     * Add hash to the bucket's chain, allocating new entries for
-	     * all after the first.
-	     */
-		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);
-			Error();
-		    }
-		    sn->s = s;
-		    sn->next = sh->next;
-		    sh->next = sn;
-		}
-	    }
-	}
-}
-
-
-/*
- * is_file_named() - is this file named?
- */
-
-int
-is_file_named(ty, p, mp, cd)
-	int ty;				/* search type: 0 = only by device
-					 *		    and inode
-					 *		1 = by device and
-					 *		    inode, or by file
-					 *		    system device and
-					 *		    path for NFS file
-					 *		    systems
-					 *		2 = only by path
-					 */
-	char *p;			/* path name (device and inode are
-					 * identified via *Lf) */
-	struct mounts *mp;		/* NFS file system (NULL if not) */
-	int cd;				/* character or block type file --
-					 * VCHR or VBLK vnode, or S_IFCHR
-					 * or S_IFBLK inode */
-{
-	char *ep;
-	int f = 0;
-	struct mounts *smp;
-	struct sfile *s = (struct sfile *)NULL;
-	struct hsfile *sh;
-	size_t sz;
-/*
- * Check for a path name match, as requested.
- */
-	if ((ty == 2) && 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 file by device and inode number.
- */
-	if (!f && (ty < 2) && 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 && (ty == 1) && 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) && (s->dev == Lf->dev)) {
-		    if (Lf->ntype != N_NFS) {
-
-		    /*
-		     * A non-NFS file matches to a non-NFS file system by
-		     * device.
-		     */
-			if (!(smp = s->mp) || (smp->ty != N_NFS)) {
-			    f = 1;
-			    break;
-			}
-		    } else {
-
-		    /*
-		     * An NFS file must also match to a file system by the
-		     * the path name of the file system -- i.e., the first
-		     * part of the file's path.  This terrible, non-UNIX
-		     * hack is forced on lsof by an egregious error in
-		     * Linux NFS that can assign the same device number
-		     * to two different NFS mounts.
-		     */
-			if (p && mp && mp->dirl && mp->dir && s->name
-			&&  !strncmp(mp->dir, s->name, mp->dirl))
-			{
-			    f = 1;
-			    break;
-		 	}
-		    }
-		}
-	    }
-	}
-/*
- * Check for a character or block device match.
- */
-	if (!f && !ty && HbyFrdCt && cd
-	&&  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.
- */
-	switch (f) {
-	case 0:
-	    return(0);
-	case 1:
-	    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 (s->devnm) {
-		    ep = endnm(&sz);
-		    (void) snpf(ep, sz, " (%s)", s->devnm);
-		}
-	    }
-	    break;
-	case 2:
-	    (void) strcpy(Namech, p);
-	    break;
-	}
-	if (s)
-	    s->f = 1;
-	return(1);
-}
-
-
-/*
- * printdevname() - print character device name
- *
- * Note: this function should not be needed in /proc-based lsof, but
- *	 since it is called by printname() in print.c, an ersatz one
- *	 is provided here.
- */
-
-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 buf[128];
-
-	(void) snpf(buf, sizeof(buf), "%s device: %d,%d",
-		    (nty == N_BLK) ? "BLK" : "CHR",
-		    (int)GET_MAJ_DEV(*rdev), (int)GET_MIN_DEV(*rdev));
-	safestrprt(buf, stdout, f);
-	return(1);
-}
diff --git a/dialects/linux/dlsof.h b/dialects/linux/dlsof.h
deleted file mode 100644
index e89d909..0000000
--- a/dialects/linux/dlsof.h
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * dlsof.h - Linux header file for /proc-based lsof
- */
-
-
-/*
- * 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.
- */
-
-
-/*
- * $Id: dlsof.h,v 1.23 2015/07/07 19:46:33 abe Exp $
- */
-
-
-#if	!defined(LINUX_LSOF_H)
-#define	LINUX_LSOF_H	1
-
-#include <dirent.h>
-#define	DIRTYPE	dirent			/* for arg.c's enter_dir() */
-#define	__USE_GNU			/* to get all O_* symbols in fcntl.h */
-#include <fcntl.h>
-#include <malloc.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <string.h>
-#include <setjmp.h>
-#include <unistd.h>
-#include <netinet/in.h>
-
-# if	defined(GLIBCV) || defined(__UCLIBC__) || defined(NEEDS_NETINET_TCPH)
-#include <netinet/tcp.h>
-# else	/* !defined(GLIBCV) && !defined(__UCLIBC__) && !defined(NEEDS_NETINET_TCPH) */
-#include <linux/tcp.h>
-# endif	/* defined(GLIBCV) || defined(__UCLIBC__) || defined(NEEDS_NETINET_TCPH) */
-
-# if	!defined(HASNORPC_H)
-#include <rpc/rpc.h>
-#include <rpc/pmap_prot.h>
-# endif	/* !defined(HASNORPC_H) */
-
-#if	defined(HASSELINUX)
-#include <selinux/selinux.h>
-#endif	/* defined(HASSELINUX) */
-
-#include <sys/sysmacros.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <linux/if_ether.h>
-#include <linux/netlink.h>
-
-#include <sys/syscall.h>
-
-/*
- * This definition is needed for the common function prototype definitions
- * in "proto.h", but isn't used in /proc-based lsof.
- */
-
-typedef	unsigned long	KA_T;
-
-
-/*
- * Local definitions
- */
-
-#define	COMP_P		const void
-#define DEVINCR		1024	/* device table malloc() increment */
-#define	FSNAMEL		4
-#define MALLOC_P	void
-#define FREE_P		MALLOC_P
-#define MALLOC_S	size_t
-#define	MAXSYSCMDL	15	/* max system command name length
-				 *   This value should be obtained from a
-				 * header file #define, but no consistent one
-				 * exists.  Some versions of the Linux kernel
-				 * have a hard-coded "char comm[16]" command
-				 * name member of the task structured
-				 * definition in <linux/sched.h>, while others
-				 * have a "char comm[TASK_COMM_LEN]" member
-				 * with TASK_COMM_LEN #define'd to be 16.
-				 *   Hence, a universal, local definition of
-				 * 16 is #define'd here. */
-#define	PROCFS		"/proc"
-#define QSORT_P		void
-#define	READLEN_T	size_t
-
-/*
- * Definitions that indicate what values are present in a stat(2) or lstat(2)
- * buffer.
- */
-
-#define	SB_DEV		0x01		/* st_dev */
-#define	SB_INO		0x02		/* st_ino */
-#define	SB_MODE		0x04		/* st_mode */
-#define	SB_NLINK	0x08		/* st_nlink */
-#define	SB_RDEV		0x10		/* st_rdev */
-#define	SB_SIZE		0x20		/* st_size */
-#define	SB_ALL		(SB_DEV | SB_INO | SB_MODE | SB_NLINK | SB_RDEV | \
-			 SB_SIZE)	/* all values */
-
-#define STRNCPY_L	size_t
-#define	STRNML		32
-
-# if	defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS==64
-#define	SZOFFTYPE	unsigned long long
-					/* size and offset internal storage
-					 * type */
-#define	SZOFFPSPEC	"ll"		/* SZOFFTYPE print specification
-					 * modifier */
-# endif	/* defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS==64 */
-
-#define	XDR_PMAPLIST	(xdrproc_t)xdr_pmaplist
-#define	XDR_VOID	(xdrproc_t)xdr_void
-
-
-/*
- * Global storage definitions (including their structure definitions)
- */
-
-struct mounts {
-        char *dir;              	/* directory name (mounted on) */
-	char *fsname;           	/* file system
-					 * (symbolic links unresolved) */
-	char *fsnmres;           	/* file system
-					 * (symbolic links resolved) */
-	size_t dirl;			/* length of directory name */
-        dev_t dev;              	/* directory st_dev */
-	dev_t rdev;			/* directory st_rdev */
-	INODETYPE inode;		/* directory st_ino */
-	mode_t mode;			/* directory st_mode */
-	int ds;				/* directory status -- i.e., SB_*
-					 * values */
-	mode_t fs_mode;			/* file system st_mode */
-	int ty;				/* node type -- e.g., N_REGLR, N_NFS */
-        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 */
-	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 mounts *mp;		/* mount structure pointer for file
-					 * system type entries */
-#define	SAVE_MP_IN_SFILE	1	/* for ck_file_arg() im arg.c */
-	struct sfile *next;		/* forward link */
-};
-
-# if	defined(HASEPTOPTS)
-typedef struct pxinfo {			/* hashed pipe, UNIX socket or pseudo-
-					 * terminal inode information */
-	INODETYPE ino;			/* file's inode */
-	struct lfile *lf;		/* connected peer file */
-	int lpx;			/* connected process index */
-	struct pxinfo *next;		/* next entry for hashed inode */
-} pxinfo_t;
-# endif	/* defined(HASEPTOPTS) */
-
-extern int HasNFS;
-extern dev_t MqueueDev;
-extern int OffType;
-
-#endif	/* LINUX_LSOF_H	*/
diff --git a/dialects/linux/dmnt.c b/dialects/linux/dmnt.c
deleted file mode 100644
index 1636a55..0000000
--- a/dialects/linux/dmnt.c
+++ /dev/null
@@ -1,710 +0,0 @@
-/*
- * dmnt.c -- Linux mount support functions for /proc-based lsof
- */
-
-
-/*
- * 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 1997 Purdue Research Foundation.\nAll rights reserved.\n";
-#endif
-
-
-#include "lsof.h"
-
-
-/*
- * Local definitions
- */
-
-#if	defined(HASMNTSUP)
-#define	HASHMNT	128			/* mount supplement hash bucket count
-					 * !!!MUST BE A POWER OF 2!!! */
-#endif	/* defined(HASMNTSUP) */
-
-
-/*
- * Local function prototypes
- */
-
-_PROTOTYPE(static char *cvtoe,(char *os));
-
-#if	defined(HASMNTSUP)
-_PROTOTYPE(static int getmntdev,(char *dn, size_t dnl, struct stat *s, int *ss));
-_PROTOTYPE(static int hash_mnt,(char *dn));
-#endif	/* defined(HASMNTSUP) */
-
-
-/*
- * Local structure definitions.
- */
-
-#if	defined(HASMNTSUP)
-typedef struct mntsup {
-	char *dn;			/* mounted directory name */
-	size_t dnl;			/* strlen(dn) */
-	dev_t dev;			/* device number */
-	int ln;				/* line on which defined */
-	struct mntsup *next;		/* next entry */
-} mntsup_t;
-#endif	/* defined(HASMNTSUP) */
-
-
-/*
- * Local static definitions
- */
-
-static struct mounts *Lmi = (struct mounts *)NULL;	/* local mount info */
-static int Lmist = 0;					/* Lmi status */
-static mntsup_t **MSHash = (mntsup_t **)NULL;		/* mount supplement
-							 * hash buckets */
-
-
-/*
- * cvtoe() -- convert octal-escaped characters in string
- */
-
-static char *
-cvtoe(os)
-	char *os;			/* original string */
-{
-	int c, cl, cx, ol, ox, tx;
-	char *cs;
-	int tc;
-/*
- * Allocate space for a copy of the string in which octal-escaped characters
- * can be replaced by the octal value -- e.g., \040 with ' '.  Leave room for
- * a '\0' terminator.
- */
-	if (!(ol = (int)strlen(os)))
-	   return((char *)NULL);
-	if (!(cs = (char *)malloc(ol + 1))) {
-	    (void) fprintf(stderr,
-		"%s: can't allocate %d bytes for octal-escaping.\n",
-		Pn, ol + 1);
-	    Error();
-	}
-/*
- * Copy the string, replacing octal-escaped characters as they are found.
- */
-	for (cx = ox = 0, cl = ol; ox < ol; ox++) {
-	    if (((c = (int)os[ox]) == (int)'\\') && ((ox + 3) < ol)) {
-
-	    /*
-	     * The beginning of an octal-escaped character has been found.
-	     *
-	     * Convert the octal value to a character value.
-	     */
-		for (tc = 0, tx = 1; os[ox + tx] && (tx < 4); tx++) {
-		    if (((int)os[ox + tx] < (int)'0')
-		    ||  ((int)os[ox + tx] > (int)'7'))
-		    {
-
-		    /*
-		     * The escape isn't followed by octets, so ignore the
-		     * escape and just copy it.
-		     */
-			break;
-		    }
-		    tc <<= 3;
-		    tc += (int)(os[ox + tx] - '0');
-		}
-		if (tx == 4) {
-
-		/*
-		 * If three octets (plus the escape) were assembled, use their
-		 * character-forming result.
-		 *
-		 * Otherwise copy the escape and what follows it until another
-		 * escape is found.
-		 */
-		    ox += 3;
-		    c = (tc & 0xff);
-		}
-	    }
-	    if (cx >= cl) {
-
-	    /*
-	     * Expand the copy string, as required.  Leave room for a '\0'
-	     * terminator.
-	     */
-		cl += 64;		/* (Make an arbitrary increase.) */
-		if (!(cs = (char *)realloc(cs, cl + 1))) {
-		    (void) fprintf(stderr,
-			"%s: can't realloc %d bytes for octal-escaping.\n",
-			Pn, cl + 1);
-		    Error();
-		}
-	    }
-	/*
-	 * Copy the character.
-	 */
-	    cs[cx++] = (char)c;
-	}
-/*
- * Terminate the copy and return its pointer.
- */
-	cs[cx] = '\0';
-	return(cs);
-}
-
-
-#if	defined(HASMNTSUP)
-/*
- * getmntdev() - get mount device from mount supplement
- */
-
-static int
-getmntdev(dn, dnl, s, ss)
-	char *dn;			/* mounted directory name */
-	size_t dnl;			/* strlen(dn) */
-	struct stat *s;			/* stat(2) buffer receptor */
-	int *ss;			/* stat(2) status result -- i.e., SB_*
-					 * values */
-{
-	static int err = 0;
-	int h;
-	mntsup_t *mp, *mpn;
-	static char *vbuf = (char *)NULL;
-	static size_t vsz = (size_t)0;
-
-	if (err)
-	    return(0);
-	if (!MSHash) {
-
-	/*
-	 * No mount supplement hash buckets have been allocated, so read the
-	 * mount supplement file and create hash buckets for its entries.
-	 */
-	    char buf[(MAXPATHLEN*2) + 1], *dp, path[(MAXPATHLEN*2) + 1];
-	    dev_t dev;
-	    FILE *fs;
-	    int ln = 0;
-	    size_t sz;
-
-	    if ((MntSup != 2) || !MntSupP)
-		return(0);
-	    if (!is_readable(MntSupP, 1)) {
-
-	    /*
-	     * The mount supplement file isn't readable.
-	     */
-		err = 1;
-		return(0);
-	    }
-	    if (!(fs = open_proc_stream(MntSupP, "r", &vbuf, &vsz, 0))) {
-
-	    /*
-	     * The mount supplement file can't be opened for reading.
-	     */
-		if (!Fwarn)
-		    (void) fprintf(stderr, "%s: can't open(%s): %s\n",
-			Pn, MntSupP, strerror(errno));
-		err = 1;
-		return(0);
-	    }
-	    buf[sizeof(buf) - 1] = '\0';
-	/*
-	 * Read the mount supplement file.
-	 */
-	    while (fgets(buf, sizeof(buf) - 1, fs)) {
-		ln++;
-		if ((dp = strchr(buf, '\n')))
-		    *dp = '\0';
-		if (buf[0] != '/') {
-
-		/*
-		 * The mount supplement line doesn't begin with the absolute
-		 * path character '/'.
-		 */
-		    if (!Fwarn)
-			(void) fprintf(stderr,
-			    "%s: %s line %d: no path: \"%s\"\n",
-			    Pn, MntSupP, ln, buf);
-		    err = 1;
-		    continue;
-		}
-		if (!(dp = strchr(buf, ' ')) || strncmp(dp + 1, "0x", 2)) {
-
-		/*
-		 * The path on the mount supplement line isn't followed by
-		 * " 0x".
-		 */
-		    if (!Fwarn)
-			(void) fprintf(stderr,
-			    "%s: %s line %d: no device: \"%s\"\n",
-			    Pn, MntSupP, ln, buf);
-		    err = 1;
-		    continue;
-		}
-		sz = (size_t)(dp - buf);
-		(void) strncpy(path, buf, sz);
-		path[sz] = '\0';
-	    /*
-	     * Assemble the hexadecimal device number of the mount supplement
-	     * line.
-	     */
-		for (dev = 0, dp += 3; *dp; dp++) {
-		    if (!isxdigit((int)*dp))
-			break;
-		    if (isdigit((int)*dp))
-			dev = (dev << 4) + (int)*dp - (int)'0';
-		    else
-			dev = (dev << 4) + (int)tolower(*dp) - (int)'a' + 10;
-		}
-		if (*dp) {
-
-		/*
-		 * The device number couldn't be assembled.
-		 */
-		    if (!Fwarn)
-			(void) fprintf(stderr,
-			    "%s: %s line %d: illegal device: \"%s\"\n",
-			    Pn, MntSupP, ln, buf);
-		    err = 1;
-		    continue;
-		}
-	    /*
-	     * Search the mount supplement hash buckets.  (Allocate them as
-	     * required.)
-	     */
-		if (!MSHash) {
-		    if (!(MSHash = (mntsup_t **)calloc(HASHMNT,
-						       sizeof(mntsup_t *)))
-		    ) {
-			(void) fprintf(stderr,
-			    "%s: no space for mount supplement hash buckets\n",
-			    Pn);
-			Error();
-		    }
-		}
-		h = hash_mnt(path);
-		for (mp = MSHash[h]; mp; mp = mp->next) {
-		    if ((mp->dnl == dnl) && !strcmp(mp->dn, path))
-			break;
-		}
-		if (mp) {
-
-		/*
-		 * A path match was located.  If the device number is the
-		 * same, skip this mount supplement line.  Otherwise, issue
-		 * a warning.
-		 */
-		    if (mp->dev != dev) {
-			(void) fprintf(stderr,
-			    "%s: %s line %d path duplicate of %d: \"%s\"\n",
-			    Pn, MntSupP, ln, mp->ln, buf);
-			err = 1;
-		    }
-		    continue;
-		}
-	    /*
-	     * Allocate and fill a new mount supplement hash entry.
-	     */
-		if (!(mpn = (mntsup_t *)malloc(sizeof(mntsup_t)))) {
-		    (void) fprintf(stderr,
-			"%s: no space for mount supplement entry: %d \"%s\"\n",
-			Pn, ln, buf);
-		    Error();
-		}
-		if (!(mpn->dn = (char *)malloc(sz + 1))) {
-		    (void) fprintf(stderr,
-			"%s: no space for mount supplement path: %d \"%s\"\n",
-			Pn, ln, buf);
-		    Error();
-		}
-		(void) strcpy(mpn->dn, path);
-		mpn->dnl = sz;
-		mpn->dev = dev;
-		mpn->ln = ln;
-		mpn->next = MSHash[h];
-		MSHash[h] = mpn;
-	    }
-	    if (ferror(fs)) {
-		if (!Fwarn)
-		    (void) fprintf(stderr, "%s: error reading %s\n",
-			Pn, MntSupP);
-		err = 1;
-	    }
-	    (void) fclose(fs);
-	    if (err) {
-		if (MSHash) {
-		    for (h = 0; h < HASHMNT; h++) {
-			for (mp = MSHash[h]; mp; mp = mpn) {
-			    mpn = mp->next;
-			    if (mp->dn)
-				(void) free((MALLOC_P *)mp->dn);
-			    (void) free((MALLOC_P *)mp);
-			}
-		    }
-		    (void) free((MALLOC_P *)MSHash);
-		    MSHash = (mntsup_t **)NULL;
-		}
-		return(0);
-	    }
-	}
-/*
- * If no errors have been detected reading the mount supplement file, search
- * its hash buckets for the supplied directory path.
- */
-	if (err)
-	    return(0);
-	h = hash_mnt(dn);
-	for (mp = MSHash[h]; mp; mp = mp->next) {
-	    if ((dnl == mp->dnl) && !strcmp(dn, mp->dn)) {
-		zeromem((char *)s, sizeof(struct stat));
-		s->st_dev = mp->dev;
-		*ss |= SB_DEV;
-		return(1);
-	    }
-	}
-	return(0);
-}
-
-
-/*
- * hash_mnt() - hash mount point
- */
-
-static int
-hash_mnt(dn)
-	char *dn;			/* mount point directory name */
-{
-	register int i, h;
-	size_t l;
-
-	if (!(l = strlen(dn)))
-	    return(0);
-	if (l == 1)
-	    return((int)*dn & (HASHMNT - 1));
-	for (i = h = 0; i < (int)(l - 1); i++) {
-	    h ^= ((int)dn[i] * (int)dn[i+1]) << ((i*3)%13);
-	}
-	return(h & (HASHMNT - 1));
-}
-#endif	/* defined(HASMNTSUP) */
-
-
-/*
- * readmnt() - read mount table
- */
-
-struct mounts *
-readmnt()
-{
-	char buf[MAXPATHLEN], *cp, **fp;
-	char *dn = (char *)NULL;
-	size_t dnl;
-	int ds, ne;
-	char *fp0 = (char *)NULL;
-	char *fp1 = (char *)NULL;
-	int fr, ignrdl, ignstat;
-	char *ln;
-	struct mounts *mp;
-	FILE *ms;
-	int nfs;
-	int mqueue;
-	struct stat sb;
-	static char *vbuf = (char *)NULL;
-	static size_t vsz = (size_t)0;
-
-	if (Lmi || Lmist)
-	    return(Lmi);
-/*
- * Open access to /proc/mounts, assigning a page size buffer to its stream.
- */
-	(void) snpf(buf, sizeof(buf), "%s/mounts", PROCFS);
-	ms = open_proc_stream(buf, "r", &vbuf, &vsz, 1);
-/*
- * Read mount table entries.
- */
-	while (fgets(buf, sizeof(buf), ms)) {
-	    if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) < 3
-	    ||  !fp[0] || !fp[1] || !fp[2])
-		continue;
-	/*
-	 * Convert octal-escaped characters in the device name and mounted-on
-	 * path name.
-	 */
-	    if (fp0) {
-		(void) free((FREE_P *)fp0);
-		fp0 = (char *)NULL;
-	    }
-	    if (fp1) {
-		(void) free((FREE_P *)fp1);
-		fp1 = (char *)NULL;
-	    }
-	    if (!(fp0 = cvtoe(fp[0])) || !(fp1 = cvtoe(fp[1])))
-		continue;
-	/*
-	 * Locate any colon (':') in the device name.
-	 *
-	 * If the colon is followed by * "(pid*" -- it's probably an
-	 * automounter entry.
-	 *
-	 * Ignore autofs, pipefs, and sockfs entries.
-	 */
-	    cp = strchr(fp0, ':');
-	    if (cp && !strncasecmp(++cp, "(pid", 4))
-		continue;
-	    if (!strcasecmp(fp[2], "autofs") || !strcasecmp(fp[2], "pipefs")
-	    ||  !strcasecmp(fp[2], "sockfs"))
-		continue;
-	/*
-	 * Interpolate a possible symbolic mounted directory link.
-	 */
-	    if (dn)
-		(void) free((FREE_P *)dn);
-	    dn = fp1;
-	    fp1 = (char *)NULL;
-
-#if	defined(HASEOPT)
-	if (Efsysl) {
-
-	/*
-	 * If there is an -e file system list, check it to decide if a stat()
-	 * and Readlink() on this one should be performed.
-	 */
-	    efsys_list_t *ep;
-
-	    for (ignrdl = ignstat = 0, ep = Efsysl; ep; ep = ep->next) {
-		if (!strcmp(dn, ep->path)) {
-		    ignrdl = ep->rdlnk;
-		    ignstat = 1;
-		    break;
-		}
-	    }
-	} else
-
-#endif	/* defined(HASEOPT */
-
-	    ignrdl = ignstat = 0;
-
-	/*
-	 * Avoid Readlink() when requested.
-	 */
-	    if (!ignrdl) {
-		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;
-	    dnl = strlen(dn);
-
-	/*
-	 * Test Mqueue directory
-	 */
-	    mqueue = strcmp(fp[2], "mqueue");
-
-	/*
-	 * Test for duplicate and NFS directories.
-	 */
-	    for (mp = Lmi; mp; mp = mp->next) {
-		if ((dnl == mp->dirl) && !strcmp(dn, mp->dir))
-		    break;
-	    }
-	    if ((nfs = strcasecmp(fp[2], "nfs"))) {
-		if ((nfs = strcasecmp(fp[2], "nfs3")))
-		    nfs = strcasecmp(fp[2], "nfs4");
-	    }
-	    if (!nfs && !HasNFS)
-		HasNFS = 1;
-	    if (mp) {
-
-	    /*
-	     * If this duplicate directory is not root, ignore it.  If the
-	     * already remembered entry is NFS-mounted, ignore this one.  If
-	     * this one is NFS-mounted, ignore the already remembered entry.
-	     */
-		if (strcmp(dn, "/"))
-		    continue;
-		if (mp->ty == N_NFS)
-		    continue;
-		if (nfs)
-		    continue;
-	    }
-	/*
-	 * Stat() the directory.
-	 */
-	    if (ignstat)
-		fr = 1;
-	    else {
-		if ((fr = statsafely(dn, &sb))) {
-		    if (!Fwarn) {
-			(void) fprintf(stderr, "%s: WARNING: can't stat() ",
-			    Pn);
-			safestrprt(fp[2], stderr, 0);
-			(void) fprintf(stderr, " file system ");
-			safestrprt(dn, stderr, 1);
-			(void) fprintf(stderr,
-			    "      Output information may be incomplete.\n");
-		    }
-		} else
-		    ds = SB_ALL;
-	    }
-
-#if	defined(HASMNTSUP)
-	    if (fr) {
-
-	    /*
-	     * If the stat() failed or wasn't called, check the mount
-	     * supplement table, if possible.
-	     */
-		if ((MntSup == 2) && MntSupP) {
-		    ds = 0;
-		    if (getmntdev(dn, dnl, &sb, &ds) || !(ds & SB_DEV)) {
-			(void) fprintf(stderr,
-			    "%s: assuming dev=%#lx for %s from %s\n",
-			    Pn, (long)sb.st_dev, dn, MntSupP);
-			}
-		} else {
-		    if (!ignstat)
-			continue;
-		   ds = 0;		/* No stat() was allowed. */
-		}
-	    }
-#else	/* !defined(HASMNTSUP) */
-	    if (fr) {
-		if (!ignstat)
-		    continue;
-		ds = 0;			/* No stat() was allowed. */
-	    }
-#endif	/* defined(HASMNTSUP) */
-
-	/*
-	 * Fill a local mount structure or reuse a previous entry when
-	 * indicated.
-	 */
-	    if (mp) {
-		ne = 0;
-		if (mp->dir) {
-		    (void) free((FREE_P *)mp->dir);
-		    mp->dir = (char *)NULL;
-		}
-		if (mp->fsname) {
-		    (void) free((FREE_P *)mp->fsname);
-		    mp->fsname = (char *)NULL;
-		}
-	    } else {
-		ne = 1;
-		if (!(mp = (struct mounts *)malloc(sizeof(struct mounts)))) {
-		    (void) fprintf(stderr,
-			"%s: can't allocate mounts struct for: ", Pn);
-		    safestrprt(dn, stderr, 1);
-		    Error();
-	        }
-	    }
-	    mp->dir = dn;
-	    dn = (char *)NULL;
-	    mp->dirl = dnl;
-	    if (ne)
-		mp->next = Lmi;
-	    mp->dev = ((mp->ds = ds) & SB_DEV) ? sb.st_dev : 0;
-	    mp->rdev = (ds & SB_RDEV) ? sb.st_rdev : 0;
-	    mp->inode = (INODETYPE)((ds & SB_INO) ? sb.st_ino : 0);
-	    mp->mode = (ds & SB_MODE) ? sb.st_mode : 0;
-	    if (!nfs) {
-		mp->ty = N_NFS;
-		if (HasNFS < 2)
-		    HasNFS = 2;
-	    } else if (!mqueue) {
-		mp->ty = N_MQUEUE;
-		MqueueDev = mp->dev;
-	    } else {
-		mp->ty = N_REGLR;
-	    }
-
-#if	defined(HASMNTSUP)
-	/*
-	 * If support for the mount supplement file is defined and if the
-	 * +m option was supplied, print mount supplement information.
-	 */
-	    if (MntSup == 1) {
-		if (mp->dev)
-		    (void) printf("%s %#lx\n", mp->dir, (long)mp->dev);
-		else
-		    (void) printf("%s 0x0\n", mp->dir);
-	    }
-#endif	/* defined(HASMNTSUP) */
-
-	/*
-	 * Save mounted-on device or directory name.
-	 */
-	    dn = fp0;
-	    fp0 = (char *)NULL;
-	    mp->fsname = dn;
-	/*
-	 * Interpolate a possible file system (mounted-on) device name or
-	 * directory name link.
-	 *
-	 * Avoid Readlink() when requested.
-	 */
-	    if (ignrdl || (*dn != '/')) {
-		if (!(ln = mkstrcpy(dn, (MALLOC_S *)NULL))) {
-		    (void) fprintf(stderr,
-			"%s: can't allocate space for: ", Pn);
-		    safestrprt(dn, stderr, 1);
-		    Error();
-		}
-		ignstat = 1;
-	    } else
-		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 (ignstat || !ln || statsafely(ln, &sb))
-		sb.st_mode = 0;
-	    mp->fsnmres = ln;
-	    mp->fs_mode = sb.st_mode;
-	    if (ne)
-		Lmi = mp;
-	}
-/*
- * Clean up and return the local mount info table address.
- */
-	(void) fclose(ms);
-	if (dn)
-	    (void) free((FREE_P *)dn);
-	if (fp0)
-	    (void) free((FREE_P *)fp0);
-	if (fp1)
-	    (void) free((FREE_P *)fp1);
-	Lmist = 1;
-	return(Lmi);
-}
diff --git a/dialects/linux/dnode.c b/dialects/linux/dnode.c
deleted file mode 100644
index 13d99e8..0000000
--- a/dialects/linux/dnode.c
+++ /dev/null
@@ -1,986 +0,0 @@
-/*
- * dnode.c - Linux node functions for /proc-based lsof
- */
-
-
-/*
- * 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 1997 Purdue Research Foundation.\nAll rights reserved.\n";
-#endif
-
-
-#include "lsof.h"
-
-#if	defined(HASEPTOPTS) && defined(HASPTYEPT)
-#include <linux/major.h>
-#endif	/* defined(HASEPTOPTS) && defined(HASPTYEPT) */
-
-
-/*
- * Local definitions
- */
-
-#define	OFFSET_MAX	((off_t)0x7fffffff)	/* this is defined in
-						 * .../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))
-
-
-/*
- * Local structure definitions
- */
-
-struct llock {
-	int pid;
-	dev_t dev;
-	INODETYPE inode;
-	char type;
-	struct llock *next;
-};
-
-
-/*
- * Local definitions
- */
-
-struct llock **LckH = (struct llock **)NULL; /* PID-hashed locks */
-
-
-/*
- * Local function prototypes
- */
-
-_PROTOTYPE(static void check_lock,(void));
-
-#if	defined(HASEPTOPTS)
-_PROTOTYPE(static void enter_pinfo,(void));
-#endif	/* defined(HASEPTOPTS) */
-
-
-/*
- * Local storage
- */
-
-#if	defined(HASEPTOPTS)
-static pxinfo_t **Pinfo = (pxinfo_t **)NULL;	/* pipe endpoint hash buckets */
-# if	defined(HASPTYEPT)
-static pxinfo_t **PtyInfo = (pxinfo_t **)NULL;	/* pseudoterminal endpoint hash
-						 * buckets */
-# endif	/* defined(HASPTYEPT) */
-static pxinfo_t **PSXMQinfo = (pxinfo_t **)NULL;/* posix msg queue endpoint hash buckets */
-static pxinfo_t **EvtFDinfo = (pxinfo_t **)NULL;/* envetfd endpoint hash buckets */
-#endif	/* defined(HASEPTOPTS) */
-
-
-/*
- * check_lock() - check lock for file *Lf, process *Lp
- */
-
-static void
-check_lock()
-{
-	int h;
-	struct llock *lp;
-
-	h = HASHPID(Lp->pid);
-	for (lp = LckH[h]; lp; lp = lp->next) {
-	    if (Lp->pid == lp->pid
-	    &&  Lf->dev == lp->dev
-	    &&  Lf->inode == lp->inode)
-	    {
-		Lf->lock = lp->type;
-		return;
-	    }
-	}
-}
-
-
-#if	defined(HASEPTOPTS)
-static void
-endpoint_pxinfo_hash(pxinfo_t **pinfo_hash, const size_t nbuckets,
-		     void (* free_elt) (void *))
-{
-	int h;				/* hash index */
-	pxinfo_t *pi, *pp;		/* temporary pointers */
-
-	if (!pinfo_hash)
-	    return;
-	for (h = 0; h < nbuckets; h++) {
-	    if ((pi = pinfo_hash[h])) {
-		do {
-		    pp = pi->next;
-		    (void) (* free_elt)
-		    ((FREE_P *)pi);
-		    pi = pp;
-		} while (pi);
-		pinfo_hash[h] = (pxinfo_t *)NULL;
-	    }
-	}
-}
-
-static void
-endpoint_enter(pxinfo_t **pinfo_hash, const char *table_name, int id)
-{
-	int h;
-	struct lfile *lf;		/* local file structure pointer */
-	struct lproc *lp;		/* local proc structure pointer */
-	pxinfo_t *np, *pi, *pe;		/* inode hash pointers */
-
-    /*
-     * Make sure this is a unique entry.
-     */
-	for (h = HASHPINFO(id), pi = pinfo_hash[h], pe = (pxinfo_t *)NULL;
-	     pi;
-	     pe = pi, pi = pi->next
-	    ) {
-	    lf = pi->lf;
-	    lp = &Lproc[pi->lpx];
-	    if (pi->ino == id) {
-		if ((lp->pid == Lp->pid) && !strcmp(lf->fd, Lf->fd))
-		    return;
-	    }
-	}
-   /*
-    * Allocate, fill and link a new pipe info structure used for pty
-    * to the end of the pty device hash chain.
-    */
-	if (!(np = (pxinfo_t *)malloc(sizeof(pxinfo_t)))) {
-	    (void) fprintf(stderr,
-		"%s: no space for pipeinfo for %s, PID %d, FD %s\n",
-		table_name,
-		Pn, Lp->pid, Lf->fd);
-	    Error();
-	}
-	np->ino = id;
-	np->lf = Lf;
-	np->lpx = Lp - Lproc;
-	np->next = (pxinfo_t *)NULL;
-	if (pe)
-	    pe->next = np;
-	else
-	    pinfo_hash[h] = np;
-}
-
-static pxinfo_t *
-endpoint_find(pxinfo_t **pinfo_hash,
-	      int (* is_acceptable) (pxinfo_t *, int, struct lfile *),
-	      int pid, struct lfile *lf, int id, pxinfo_t *pp)
-{
-	int h;				/* hash result */
-	pxinfo_t *pi;			/* pipe info pointer */
-
-	if (pinfo_hash) {
-	    if (pp)
-		pi = pp;
-	    else {
-		h = HASHPINFO(id);
-		pi = pinfo_hash[h];
-	    }
-	    while (pi) {
-		if (pi->ino == id && is_acceptable(pi, pid, lf))
-		    return (pi);
-		pi = pi->next;
-	    }
-	}
-	return ((pxinfo_t *)NULL);
-}
-
-
-/*
- * endpoint_accept_other_than_self() -- a helper function return true if
- * fd associated with pi is not the same as fd associated with lf.
- */
-
-static int
-endpoint_accept_other_than_self(pxinfo_t *pi, int pid, struct lfile *lf)
-{
-	struct lfile *ef = pi->lf;
-	struct lproc *ep = &Lproc[pi->lpx];
-	return (strcmp(lf->fd, ef->fd)) || (pid != ep->pid);
-}
-
-
-/*
- * clear_pinfo() -- clear allocated pipe info
- */
-
-void
-clear_pinfo()
-{
-	endpoint_pxinfo_hash(Pinfo, PINFOBUCKS, free);
-}
-
-
-/*
- * enter_pinfo() -- enter pipe info
- *
- * 	entry	Lf = local file structure pointer
- * 		Lp = local process structure pointer
- */
-
-static void
-enter_pinfo()
-{
-	if (!Pinfo) {
-	/*
-	 * Allocate pipe info hash buckets.
-	 */
-	    if (!(Pinfo = (pxinfo_t **)calloc(PINFOBUCKS, sizeof(pxinfo_t *))))
-	    {
-		(void) fprintf(stderr,
-		    "%s: no space for %d pipe info buckets\n", Pn, PINFOBUCKS);
-		    Error();
-	    }
-	}
-	endpoint_enter(Pinfo, "pipeinfo", Lf->inode);
-}
-
-
-/*
- * find_pepti() -- find pipe end point info
- */
-
-pxinfo_t *
-find_pepti(pid, lf, pp)
-	int pid;			/* pid of the process owning lf */
-	struct lfile *lf;		/* pipe's lfile */
-	pxinfo_t *pp;			/* previous pipe info (NULL == none) */
-{
-	return endpoint_find(Pinfo,
-			     endpoint_accept_other_than_self,
-			     pid, lf, lf->inode, pp);
-}
-
-#if	defined(HASPTYEPT)
-
-
-/*
- * clear_ptyinfo() -- clear allocated pseudoterminal info
- */
-
-void
-clear_ptyinfo()
-{
-	endpoint_pxinfo_hash(PtyInfo, PINFOBUCKS, free);
-}
-
-
-/*
- * enter_ptmxi() -- enter pty info
- *
- * 	entry	Lf = local file structure pointer
- * 		Lp = local process structure pointer
- */
-
-void
-enter_ptmxi(mn)
-	int mn;				/* minor number of device */
-{
-	/*
-	 * Allocate pipe info hash buckets (but used for pty).
-	 */
-	if (!PtyInfo) {
-	    if (!(PtyInfo = (pxinfo_t **)calloc(PINFOBUCKS,
-			    sizeof(pxinfo_t *))))
-	    {
-		(void) fprintf(stderr,
-		    "%s: no space for %d pty info buckets\n", Pn, PINFOBUCKS);
-		    Error();
-	    }
-	}
-	endpoint_enter(PtyInfo, "pty", mn);
-}
-
-/*
- * ptyepti_accept_ptmx() -- a helper function return whether lfile is pty ptmx or not
- */
-
-static int
-ptyepti_accept_ptmx(pxinfo_t *pi, int pid, struct lfile *lf)
-{
-	struct lfile *ef = pi->lf;
-	return is_pty_ptmx(ef->rdev);
-}
-
-/*
- * ptyepti_accept_slave() -- a helper function returns whether lfile is pty slave or not
- */
-
-static int
-ptyepti_accept_slave(pxinfo_t *pi, int pid, struct lfile *lf)
-{
-	struct lfile *ef = pi->lf;
-	return is_pty_slave(GET_MAJ_DEV(ef->rdev));
-}
-
-/*
- * find_ptyepti() -- find pseudoterminal end point info
- */
-
-pxinfo_t *
-find_ptyepti(pid, lf, m, pp)
-	int pid;
-	struct lfile *lf;		/* pseudoterminal's lfile */
-	int m;				/* minor number type:
-					 *     0 == use tty_index
-					 *     1 == use minor device */
-	pxinfo_t *pp;			/* previous pseudoterminal info
-					 * (NULL == none) */
-{
-	return endpoint_find(PtyInfo,
-			     m ? ptyepti_accept_ptmx : ptyepti_accept_slave,
-			     pid, lf, m ? GET_MIN_DEV(lf->rdev) : lf->tty_index, pp);
-}
-
-
-/*
- * is_pty_slave() -- is a pseudoterminal a slave device
- */
-
-int
-is_pty_slave(sm)
-	int sm;				/* slave major device number */
-{
-	/* linux/Documentation/admin-guide/devices.txt
-	   -------------------------------------------
-	   136-143 char	Unix98 PTY slaves
-		  0 = /dev/pts/0	First Unix98 pseudo-TTY
-		  1 = /dev/pts/1	Second Unix98 pseudo-TTY
-		    ...
-
-		These device nodes are automatically generated with
-		the proper permissions and modes by mounting the
-		devpts filesystem onto /dev/pts with the appropriate
-		mount options (distribution dependent, however, on
-		*most* distributions the appropriate options are
-		"mode=0620,gid=<gid of the "tty" group>".) */
-	if ((UNIX98_PTY_SLAVE_MAJOR <= sm)
-	&&  (sm < (UNIX98_PTY_SLAVE_MAJOR + UNIX98_PTY_MAJOR_COUNT))
-	) {
-	    return 1;
-	}
-	return 0;
-}
-
-
-/*
- * is_pty_ptmx() -- is a pseudoterminal a master clone device
- */
-
-int
-is_pty_ptmx(dev)
-	dev_t dev;			/* device number */
-{
-	if ((GET_MAJ_DEV(dev) == TTYAUX_MAJOR) && (GET_MIN_DEV(dev) == 2))
-	    return 1;
-	return 0;
-}
-#endif	/* defined(HASPTYEPT) */
-
-
-/*
- * clear_psxmqinfo -- clear allocate posix mq info
- */
-
-void
-clear_psxmqinfo()
-{
-	endpoint_pxinfo_hash(PSXMQinfo, PINFOBUCKS, free);
-}
-
-
-/*
- * enter_psxmqinfo() -- enter posix mq info
- *
- *	entry	Lf = local file structure pointer
- *		Lp = local process structure pointer
- */
-
-void
-enter_psxmqinfo()
-{
-	if (!PSXMQinfo) {
-	/*
-	 * Allocate posix mq info hash buckets.
-	 */
-	    if (!(PSXMQinfo = (pxinfo_t **)calloc(PINFOBUCKS, sizeof(pxinfo_t *))))
-	    {
-		(void) fprintf(stderr,
-		    "%s: no space for %d posix mq info buckets\n", Pn, PINFOBUCKS);
-		    Error();
-	    }
-	}
-	endpoint_enter(PSXMQinfo, "psxmqinfo", Lf->inode);
-}
-
-
-/*
- * find_psxmqinfo() -- find posix mq end point info
- */
-
-pxinfo_t *
-find_psxmqinfo(pid, lf, pp)
-	int pid;			/* pid of the process owning lf */
-	struct lfile *lf;		/* posix mq's lfile */
-	pxinfo_t *pp;			/* previous posix mq info (NULL == none) */
-{
-	return endpoint_find(PSXMQinfo,
-			     endpoint_accept_other_than_self,
-			     pid, lf, lf->inode, pp);
-}
-
-/*
- * clear_evtfdinfo -- clear allocate eventfd info
- */
-
-void
-clear_evtfdinfo()
-{
-	endpoint_pxinfo_hash(EvtFDinfo, PINFOBUCKS, free);
-}
-
-
-/*
- * enter_evtfdinfo() -- enter eventfd info
- *
- *	entry	Lf = local file structure pointer
- *		Lp = local process structure pointer
- */
-
-void
-enter_evtfdinfo(int id)
-{
-	if (!EvtFDinfo) {
-	/*
-	 * Allocate eventfd info hash buckets.
-	 */
-	    if (!(EvtFDinfo = (pxinfo_t **)calloc(PINFOBUCKS, sizeof(pxinfo_t *))))
-	    {
-		(void) fprintf(stderr,
-		    "%s: no space for %d envet fd info buckets\n", Pn, PINFOBUCKS);
-		    Error();
-	    }
-	}
-	endpoint_enter(EvtFDinfo, "evtfdinfo", id);
-}
-
-
-/*
- * find_evtfdinfo() -- find eventfd end point info
- */
-
-pxinfo_t *
-find_evtfdinfo(pid, lf, pp)
-	int pid;			/* pid of the process owning lf */
-	struct lfile *lf;		/* eventfd's lfile */
-	pxinfo_t *pp;			/* previous eventfd info (NULL == none) */
-{
-	void *r = endpoint_find(EvtFDinfo,
-			     endpoint_accept_other_than_self,
-			     pid, lf, lf->eventfd_id, pp);
-	return r;
-}
-#endif	/* defined(HASEPTOPTS) */
-
-
-/*
- * get_fields() - separate a line into fields
- */
-
-int
-get_fields(ln, sep, fr, eb, en)
-	char *ln;			/* input line */
-	char *sep;			/* separator list */
-	char ***fr;			/* field pointer return address */
-	int *eb;			/* indexes of fields where blank or an
-					 * entry from the separator list may be
-					 * embedded and are not separators
-					 * (may be NULL) */
-	int en;				/* number of entries in eb[] (may be
-					 * zero) */
-{
-	char *bp, *cp, *sp;
-	int i, j, n;
-	MALLOC_S len;
-	static char **fp = (char **)NULL;
-	static int nfpa = 0;
-
-	for (cp = ln, n = 0; cp && *cp;) {
-	    for (bp = cp; *bp && (*bp == ' ' || *bp == '\t'); bp++);
-		;
-	    if (!*bp || *bp == '\n')
-		break;
-	    for (cp = bp; *cp; cp++) {
-		if (*cp == '\n') {
-		    *cp = '\0';
-		    break;
-		}
-		if (*cp == '\t')	/* TAB is always a separator */
-		    break;
-		if (*cp == ' ')  {
-
-		/*
-		 * See if this field may have an embedded space.
-		 */
-		    if (!eb || !en)
-			break;
-		    else {
-			for (i = j = 0; i < en; i++) {
-			    if (eb[i] == n) {
-				j = 1;
-				break;
-			    }
-			}
-			if (!j)
-			    break;
-		    }
-		}
-		if (sep) {
-
-		/*
-		 * See if the character is in the separator list.
-		 */
-		    for (sp = sep; *sp; sp++) {
-			if (*sp == *cp)
-			    break;
-		    }
-		    if (*sp) {
-
-		    /*
-		     * See if this field may have an embedded separator.
-		     */
-			if (!eb || !en)
-			    break;
-			else {
-			    for (i = j = 0; i < en; i++) {
-				if (eb[i] == n) {
-				    j = 1;
-				    break;
-				}
-			    }
-			    if (!j)
-				break;
-			}
-		    }
-		}
-	    }
-	    if (*cp)
-		*cp++ = '\0';
-	    if (n >= nfpa) {
-		nfpa += 32;
-		len = (MALLOC_S)(nfpa * sizeof(char *));
-		if (fp)
-		    fp = (char **)realloc((MALLOC_P *)fp, len);
-		else
-		    fp = (char **)malloc(len);
-		if (!fp) {
-		    (void) fprintf(stderr,
-			"%s: can't allocate %d bytes for field pointers.\n",
-			Pn, (int)len);
-		    Error();
-		}
-	    }
-	    fp[n++] = bp;
-	}
-	*fr = fp;
-	return(n);
-}
-
-
-/*
- * get_locks() - get lock information from /proc/locks
- */
-
-void
-get_locks(p)
-	char *p;				/* /proc lock path */
-{
-	unsigned long bp, ep;
-	char buf[MAXPATHLEN], *ec, **fp;
-	dev_t dev;
-	int ex, i, h, mode, pid;
-	INODETYPE inode;
-	struct llock *lp, *np;
-	FILE *ls;
-	long maj, min;
-	char type;
-	static char *vbuf = (char *)NULL;
-	static size_t vsz = (size_t)0;
-/*
- * Destroy previous lock information.
- */
-	if (LckH) {
-	    for (i = 0; i < PIDBUCKS; i++) {
-		for (lp = LckH[i]; lp; lp = np) {
-		    np = lp->next;
-		    (void) free((FREE_P *)lp);
-		}
-		LckH[i] = (struct llock *)NULL;
-	    }
-	} else {
-
-	/*
-	 * If first time, allocate the lock PID hash buckets.
-	 */
-	    LckH = (struct llock **)calloc((MALLOC_S)PIDBUCKS,
-					   sizeof(struct llock *));
-	    if (!LckH) {
-		(void) fprintf(stderr,
-		    "%s: can't allocate %d lock hash bytes\n",
-		    Pn, (int)(sizeof(struct llock *) * PIDBUCKS));
-		Error();
-	    }
-	}
-/*
- * Open the /proc lock file, assign a page size buffer to its stream,
- * and read it.
- */
-	if (!(ls = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
-	    return;
-	while (fgets(buf, sizeof(buf), ls)) {
-	    if (get_fields(buf, ":", &fp, (int *)NULL, 0) < 10)
-		continue;
-	    if (!fp[1] || strcmp(fp[1], "->") == 0)
-		continue;
-	/*
-	 * Get lock type.
-	 */
-	    if (!fp[3])
-		continue;
-	    if (*fp[3] == 'R')
-		mode = 0;
-	    else if (*fp[3] == 'W')
-		mode = 1;
-	    else
-		continue;
-	/*
-	 * Get PID.
-	 */
-	    if (!fp[4] || !*fp[4])
-		continue;
-	    pid = atoi(fp[4]);
-	/*
-	 * Get device number.
-	 */
-	    ec = (char *)NULL;
-	    if (!fp[5] || !*fp[5]
-	    ||  (maj = strtol(fp[5], &ec, 16)) == LONG_MIN || maj == LONG_MAX
-	    ||  !ec || *ec)
-		continue;
-	    ec = (char *)NULL;
-	    if (!fp[6] || !*fp[6]
-	    ||  (min = strtol(fp[6], &ec, 16)) == LONG_MIN || min == LONG_MAX
-	    ||  !ec || *ec)
-		continue;
-	    dev = (dev_t)makedev((int)maj, (int)min);
-	/*
-	 * Get inode number.
-	 */
-	    ec = (char *)NULL;
-	    if (!fp[7] || !*fp[7]
-	    ||  (inode = strtoull(fp[7], &ec, 0)) == ULONG_MAX
-	    ||  !ec || *ec)
-		continue;
-	/*
-	 * Get lock extent.  Convert it and the lock type to a lock character.
-	 */
-	    if (!fp[8] || !*fp[8] || !fp[9] || !*fp[9])
-		continue;
-	    ec = (char *)NULL;
-	    if ((bp = strtoul(fp[8], &ec, 0)) == ULONG_MAX || !ec || *ec)
-		continue;
-	    if (!strcmp(fp[9], "EOF"))		/* for Linux 2.4.x */
-		ep = OFFSET_MAX;
-	    else {
-		ec = (char *)NULL;
-		if ((ep = strtoul(fp[9], &ec, 0)) == ULONG_MAX || !ec || *ec)
-		    continue;
-	    }
-	    ex = ((off_t)bp == (off_t)0 && (off_t)ep == OFFSET_MAX) ? 1 : 0;
-	    if (mode)
-		type = ex ? 'W' : 'w';
-	    else
-		type = ex ? 'R' : 'r';
-	/*
-	 * Look for this lock via the hash buckets.
-	 */
-	    h = HASHPID(pid);
-	    for (lp = LckH[h]; lp; lp = lp->next) {
-		if (lp->pid == pid
-		&&  lp->dev == dev
-		&&  lp->inode == inode
-		&&  lp->type == type)
-		    break;
-	    }
-	    if (lp)
-		continue;
-	/*
-	 * Allocate a new llock structure and link it to the PID hash bucket.
-	 */
-	    if (!(lp = (struct llock *)malloc(sizeof(struct llock)))) {
-		(void) snpf(buf, sizeof(buf), InodeFmt_d, inode);
-		(void) fprintf(stderr,
-		    "%s: can't allocate llock: PID %d; dev %x; inode %s\n",
-		    Pn, pid, (int)dev, buf);
-		Error();
-	    }
-	    lp->pid = pid;
-	    lp->dev = dev;
-	    lp->inode = inode;
-	    lp->type = type;
-	    lp->next = LckH[h];
-	    LckH[h] = lp;
-	}
-	(void) fclose(ls);
-}
-
-
-/*
- * process_proc_node() - process file node
- */
-
-void
-process_proc_node(p, pbr, s, ss, l, ls)
-	char *p;			/* node's readlink() path */
-	char *pbr;			/* node's path before readlink() */
-	struct stat *s;			/* stat() result for path */
-	int ss;				/* *s status -- i.e., SB_* values */
-	struct stat *l;			/* lstat() result for FD (NULL for
-					 * others) */
-	int ls;				/* *l status -- i.e., SB_* values */
-{
-	mode_t access;
-	mode_t type = 0;
-	char *cp;
-	struct mounts *mp = (struct mounts *)NULL;
-	size_t sz;
-	char *tn;
-/*
- * Set the access mode, if possible.
- */
-	if (l && (ls & SB_MODE) && ((l->st_mode & S_IFMT) == S_IFLNK)) {
-	    if ((access = l->st_mode & (S_IRUSR | S_IWUSR)) == S_IRUSR)
-		Lf->access = 'r';
-	    else if (access == S_IWUSR)
-		Lf->access = 'w';
-	    else
-		Lf->access = 'u';
-	}
-/*
- * Determine node type.
- */
-	if (ss & SB_MODE) {
-	    type = s->st_mode & S_IFMT;
-	    switch (type) {
-	    case S_IFBLK:
-		Lf->ntype = Ntype = N_BLK;
-		break;
-	    case S_IFCHR:
-		Lf->ntype = Ntype = N_CHR;
-		break;
-	    case S_IFIFO:
-		Lf->ntype = Ntype = N_FIFO;
-		break;
-	    case S_IFSOCK:
-		/* Lf->ntype = Ntype = N_REGLR;		by alloc_lfile() */
-		process_proc_sock(p, pbr, s, ss, l, ls);
-		return;
-	    case 0:
-		if (!strcmp(p, "anon_inode"))
-		   Lf->ntype = Ntype = N_ANON_INODE;
-		break;
-	    }
-	}
-	if (Selinet)
-	    return;
-/*
- * Save the device.  If it is an NFS device, change the node type to N_NFS.
- */
-	if (ss & SB_DEV) {
-	    Lf->dev = s->st_dev;
-	    Lf->dev_def = 1;
-	}
-	if ((Ntype == N_CHR || Ntype == N_BLK)) {
-	    if (ss & SB_RDEV) {
-		Lf->rdev = s->st_rdev;
-		Lf->rdev_def = 1;
-
-#if	defined(HASEPTOPTS) && defined(HASPTYEPT)
-		if (FeptE
-		&&  (Ntype == N_CHR)
-		&&  is_pty_slave(GET_MAJ_DEV(Lf->rdev))
-		) {
-		    enter_ptmxi(GET_MIN_DEV(Lf->rdev));
-		    Lf->sf |= SELPTYINFO;
-		}
-#endif	/* defined(HASEPTOPTS) && defined(HASPTYEPT) */
-
-	    }
-	}
-	if (Ntype == N_REGLR && (HasNFS == 2)) {
-	    for (mp = readmnt(); mp; mp = mp->next) {
-		if ((mp->ty == N_NFS)
-		&&  (mp->ds & SB_DEV) && Lf->dev_def && (Lf->dev == mp->dev)
-		&&  (mp->dir && mp->dirl
-		&&   !strncmp(mp->dir, p, mp->dirl))
-		) {
-		    Lf->ntype = Ntype = N_NFS;
-		    break;
-		}
-	    }
-	}
-/*
- * Save the inode number.
- */
-	if (ss & SB_INO) {
-	    Lf->inode = (INODETYPE)s->st_ino;
-	    Lf->inp_ty = 1;
-
-#if	defined(HASEPTOPTS)
-	    if ((Lf->ntype == N_FIFO) && FeptE) {
-	    	(void) enter_pinfo();
-		Lf->sf |= SELPINFO;
-	    } else if ((Lf->dev == MqueueDev) && FeptE) {
-		(void) enter_psxmqinfo();
-		Lf->sf |= SELPSXMQINFO;
-	    }
-#endif	/* defined(HASEPTOPTS) */
-
-	}
-/*
- * Check for a lock.
- */
-	if (Lf->dev_def && (Lf->inp_ty == 1))
-	    (void) check_lock();
-/*
- * Save the file size.
- */
-	switch (Ntype) {
-	case N_BLK:
-	case N_CHR:
-	case N_FIFO:
-	    if (!Fsize && l && (ls & SB_SIZE) && OffType) {
-		Lf->off = (SZOFFTYPE)l->st_size;
-		Lf->off_def = 1;
-	    }
-	    break;
-	default:
-	    if (Foffset) {
-		if (l && (ls & SB_SIZE) && OffType) {
-		    Lf->off = (SZOFFTYPE)l->st_size;
-		    Lf->off_def = 1;
-		}
-	    } else if (!Foffset || Fsize) {
-		if (ss & SB_SIZE) {
-		    Lf->sz = (SZOFFTYPE)s->st_size;
-		    Lf->sz_def = 1;
-		}
-	    }
-	}
-/*
- * Record the link count.
- */
-	if (Fnlink && (ss & SB_NLINK)) {
-	    Lf->nlink = (long)s->st_nlink;
-	    Lf->nlink_def = 1;
-	    if (Nlink && (Lf->nlink < Nlink))
-		Lf->sf |= SELNLINK;
-	}
-/*
- * Format the type name.
- */
-	if (ss & SB_MODE) {
-	    switch (type) {
-	    case S_IFBLK:
-		tn = "BLK";
-		break;
-	    case S_IFCHR:
-		tn = "CHR";
-		break;
-	    case S_IFDIR:
-		tn = "DIR";
-		break;
-	    case S_IFIFO:
-		tn = "FIFO";
-		break;
-	    case S_IFREG:
-		if (Lf->dev == MqueueDev)
-		    tn = "PSXMQ";
-		else
-		    tn = "REG";
-		break;
-	    case S_IFLNK:
-		tn = "LINK";
-		break;
-	    case S_ISVTX:
-		tn = "VTXT";
-		break;
-	    default:
-		if (Ntype == N_ANON_INODE)
-		    tn = "a_inode";
-		else {
-		    (void) snpf(Lf->type, sizeof(Lf->type), "%04o",
-			((type >> 12) & 0xf));
-		    tn = (char *)NULL;
-		}
-	    }
-	} else
-	    tn = "unknown";
-	if (tn)
-	    (void) snpf(Lf->type, sizeof(Lf->type), "%s", tn);
-/*
- * Record an NFS file selection.
- */
-	if (Ntype == N_NFS && Fnfs)
-	    Lf->sf |= SELNFS;
-/*
- * Test for specified file.
- */
-	if (Sfile
-	&& is_file_named(1, p, mp,
-			 ((type == S_IFCHR) || (type == S_IFBLK)) ? 1 : 0))
-	    Lf->sf |= SELNM;
-/*
- * If no NAME information has been stored, store the path.
- *
- * Store the remote host and mount point for an NFS file.
- */
-	if (!Namech[0]) {
-	    (void) snpf(Namech, Namechl, "%s", p);
-	    if ((Ntype == N_NFS) && mp && mp->fsname) {
-		cp = endnm(&sz);
-		(void) snpf(cp, sz, " (%s)", mp->fsname);
-	    }
-	}
-	if (Namech[0])
-	    enter_nm(Namech);
-}
diff --git a/dialects/linux/dproc.c b/dialects/linux/dproc.c
deleted file mode 100644
index 650639f..0000000
--- a/dialects/linux/dproc.c
+++ /dev/null
@@ -1,1919 +0,0 @@
-/*
- * dproc.c - Linux process access functions for /proc-based lsof
- */
-
-
-/*
- * 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 1997 Purdue Research Foundation.\nAll rights reserved.\n";
-#endif
-
-#include "lsof.h"
-
-
-/*
- * Local definitions
- */
-
-#define	FDINFO_FLAGS		0x1	/* fdinfo flags available */
-#define	FDINFO_POS		0x2	/* fdinfo position available */
-
-#if	defined(HASEPTOPTS)
-#define FDINFO_EVENTFD_ID	0x4	/* fdinfo eventfd-id available */
-#if	defined(HASPTYEPT)
-#define FDINFO_TTY_INDEX	0x8	/* fdinfo tty-index available */
-#endif  /* defined(HASPTYEPT) */
-#endif	/* defined(HASEPTOPTS) */
-
-#define FDINFO_PID		0x10	/* pidfd pid available */
-#define FDINFO_TFD		0x20	/* fd monitored by eventpoll fd */
-
-#define FDINFO_BASE		(FDINFO_FLAGS | FDINFO_POS)
-#if	defined(HASEPTOPTS)
-#if     defined(HASPTYEPT)
-#define FDINFO_ALL		(FDINFO_BASE | FDINFO_TTY_INDEX | FDINFO_EVENTFD_ID | FDINFO_PID | FDINFO_TFD)
-#else  /* !defined(HASPTYEPT) */
-#define FDINFO_ALL		(FDINFO_BASE | FDINFO_EVENTFD_ID | FDINFO_PID | FDINFO_TFD)
-#endif  /* defined(HASPTYEPT) */
-#define FDINFO_OPTIONAL		(FDINFO_ALL & ~FDINFO_BASE)
-#else   /* !defined(HASEPTOPTS) */
-#define FDINFO_ALL		(FDINFO_BASE | FDINFO_PID | FDINFO_TFD)
-#endif	/* defined(HASEPTOPTS) */
-
-
-#define	LSTAT_TEST_FILE		"/"
-#define LSTAT_TEST_SEEK		1
-
-#if	!defined(ULLONG_MAX)
-#define	ULLONG_MAX		18446744073709551615ULL
-#endif	/* !defined(ULLONG_MAX) */
-
-
-/*
- * Local structures
- */
-
-struct l_fdinfo {
-	int flags;			/* flags: line value */
-	off_t pos;			/* pos: line value */
-
-#if	defined(HASEPTOPTS)
-	int eventfd_id;
-#if	defined(HASPTYEPT)
-	int tty_index;			/* pty line index */
-#endif  /* defined(HASPTYEPT) */
-#endif	/* defined(HASEPTOPTS) */
-
-	int pid;			/* for pidfd */
-
-#define EPOLL_MAX_TFDS 32
-	int tfds [ EPOLL_MAX_TFDS ];
-	size_t tfd_count;
-};
-
-
-/*
- * Local variables
- */
-
-static short Cckreg;			/* conditional status of regular file
-					 * checking:
-					 *     0 = unconditionally check
-					 *     1 = conditionally check */
-static short Ckscko;			/* socket file only checking status:
-					 *     0 = none
-					 *     1 = check only socket files */
-
-
-/*
- * Local function prototypes
- */
-
-_PROTOTYPE(static MALLOC_S alloc_cbf,(MALLOC_S len, char **cbf, MALLOC_S cbfa));
-_PROTOTYPE(static int get_fdinfo,(char *p, int msk, 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,(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,
-				  char *tcmd));
-_PROTOTYPE(static int statEx,(char *p, struct stat *s, int *ss));
-
-_PROTOTYPE(static void snp_eventpoll, (char *p, int len, int *tfds, int tfd_count));
-
-#if	defined(HASSELINUX)
-_PROTOTYPE(static int cmp_cntx_eq,(char *pcntx, char *ucntx));
-
-
-#include <fnmatch.h>
-
-
-/*
- * cmp_cntx_eq -- compare program and user security contexts
- */
-
-static int
-cmp_cntx_eq(pcntx, ucntx)
-	char *pcntx;			       /* program context */
-	char *ucntx;			       /* user supplied context */
-{
-	return !fnmatch(ucntx, pcntx, 0);
-}
-
-
-/*
- * enter_cntx_arg() - enter name ecurity context argument
- */
-
-int
-enter_cntx_arg(cntx)
-	char *cntx;			       /* context */
-{
-	cntxlist_t *cntxp;
-/*
- * Search the argument list for a duplicate.
- */
-	for (cntxp = CntxArg; cntxp; cntxp = cntxp->next) {
-	    if (!strcmp(cntxp->cntx, cntx)) {
-		if (!Fwarn) {
-		    (void) fprintf(stderr, "%s: duplicate context: %s\n",
-			Pn, cntx);
-		}
-		return(1);
-	    }
-	}
-/*
- * Create and link a new context argument list entry.
- */
-	if (!(cntxp = (cntxlist_t *)malloc((MALLOC_S)sizeof(cntxlist_t)))) {
-	    (void) fprintf(stderr, "%s: no space for context: %s\n", Pn, cntx);
-	    Error();
-	}
-	cntxp->f = 0;
-	cntxp->cntx = cntx;
-	cntxp->next = CntxArg;
-	CntxArg = cntxp;
-	return(0);
-}
-#endif	/* defined(HASSELINUX) */
-
-
-/*
- * 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);
-	     Error();
-	}
-	return(len);
-}
-
-
-/*
- * gather_proc_info() -- gather process information
- */
-
-void
-gather_proc_info()
-{
-	char *cmd, *tcmd;
-	char cmdbuf[MAXPATHLEN];
-	struct dirent *dp;
-	unsigned char ht, pidts;
-	int n, nl, pgid, pid, ppid, prv, rv, tid, tpgid, tppid, tx;
-	static char *path = (char *)NULL;
-	static int pathl = 0;
-	static char *pidpath = (char *)NULL;
-	static MALLOC_S pidpathl = 0;
-	static MALLOC_S pidx = 0;
-	static DIR *ps = (DIR *)NULL;
-	struct stat sb;
-	static char *taskpath = (char *)NULL;
-	static int taskpathl = 0;
-	static char *tidpath = (char *)NULL;
-	static int tidpathl = 0;
-	DIR *ts;
-	UID_ARG uid;
-
-/*
- * Do one-time setup.
- */
-	if (!pidpath) {
-	    pidx = strlen(PROCFS) + 1;
-	    pidpathl = pidx + 64 + 1;	/* 64 is growth room */
-	    if (!(pidpath = (char *)malloc(pidpathl))) {
-		(void) fprintf(stderr,
-		    "%s: can't allocate %d bytes for \"%s/\"<pid>\n",
-		    Pn, (int)pidpathl, PROCFS);
-		Error();
-	    }
-	    (void) snpf(pidpath, pidpathl, "%s/", PROCFS);
-	}
-/*
- * Get lock and net information.
- */
-	(void) make_proc_path(pidpath, pidx, &path, &pathl, "locks");
-	(void) get_locks(path);
-	(void) make_proc_path(pidpath, pidx, &path, &pathl, "net/");
-	(void) set_net_paths(path, strlen(path));
-/*
- * 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 /proc, looking for PID directories.  Open each one and
- * gather its process and file information.
- */
-	if (!ps) {
-	    if (!(ps = opendir(PROCFS))) {
-		(void) fprintf(stderr, "%s: can't open %s\n", Pn, PROCFS);
-		Error();
-	    }
-	} else
-	    (void) rewinddir(ps);
-	while ((dp = readdir(ps))) {
-	    if (nm2id(dp->d_name, &pid, &n))
-		continue;
-	/*
-	 * Build path to PID's directory.
-	 */
-	    if ((pidx + n + 1 + 1) > pidpathl) {
-		pidpathl = pidx + n + 1 + 1 + 64;
-		if (!(pidpath = (char *)realloc((MALLOC_P *)pidpath, pidpathl)))
-		{
-		    (void) fprintf(stderr,
-			"%s: can't allocate %d bytes for \"%s/%s/\"\n",
-			Pn, (int)pidpathl, PROCFS, dp->d_name);
-		    Error();
-		}
-	    }
-	    (void) snpf(pidpath + pidx, pidpathl - pidx, "%s/", dp->d_name);
-	    n += (pidx + 1);
-	/*
-	 * Process the PID's stat info.
-	 */
-	    if (stat(pidpath, &sb))
-		continue;
-	    uid = (UID_ARG)sb.st_uid;
-	    ht = pidts = 0;
-	/*
-	 * Get the PID's command name.
-	 */
-	    (void) make_proc_path(pidpath, n, &path, &pathl, "stat");
-	    if ((prv = read_id_stat(path, pid, &cmd, &ppid, &pgid)) < 0)
-		cmd = "(unknown)";
-
-#if	defined(HASTASKS)
-	/*
-	 * Task reporting has been selected, so save the process' command
-	 * string, so that task processing won't change it in the buffer of
-	 * read_id_stat().
-	 *
-	 * Check the tasks of the process first, so that the "-p<PID> -aK"
-	 * options work properly.
-	 */
-	    else if (!IgnTasks && (Selflags & SELTASK)) {
-		strncpy(cmdbuf, cmd, sizeof(cmdbuf) - 1);
-		cmdbuf[sizeof(cmdbuf) - 1] = '\0';
-		cmd = cmdbuf;
-		(void) make_proc_path(pidpath, n, &taskpath, &taskpathl,
-				      "task");
-		tx = n + 4;
-		if ((ts = opendir(taskpath))) {
-
-		/*
-		 * Process the PID's tasks.  Record the open files of those
-		 * whose TIDs do not match the PID and which are themselves
-		 * not zombies.
-		 */
-		    while ((dp = readdir(ts))) {
-
-		    /*
-		     * Get the task ID.  Skip the task if its ID matches the
-		     * process PID.
-		     */
-			if (nm2id(dp->d_name, &tid, &nl))
-			    continue;
-			if  (tid == pid) {
-			    pidts = 1;
-			    continue;
-			}
-		    /*
-		     * Form the path for the TID.
-		     */
-			if ((tx + 1 + nl + 1 + 4) > tidpathl) {
-			    tidpathl = tx + 1 + n + 1 + 4 + 64;
-			    if (tidpath)
-				tidpath = (char *)realloc((MALLOC_P *)tidpath,
-							  tidpathl);
-			    else
-				tidpath = (char *)malloc((MALLOC_S)tidpathl);
-			    if (!tidpath) {
-				(void) fprintf(stderr,
-				    "%s: can't allocate %d task bytes", Pn,
-				    tidpathl);
-				(void) fprintf(stderr, " for \"%s/%s/stat\"\n",
-				    taskpath, dp->d_name);
-				Error();
-			    }
-			}
-			(void) snpf(tidpath, tidpathl, "%s/%s/stat", taskpath,
-			    dp->d_name);
-		    /*
-		     * Check the task state.
-		     */
-			rv = read_id_stat(tidpath, tid, &tcmd, &tppid,
-					  &tpgid);
-			if ((rv < 0) || (rv == 1))
-			    continue;
-		    /*
-		     * Attempt to record the task.
-		     */
-			if (!process_id(tidpath, (tx + 1 + nl+ 1), cmd, uid,
-					pid, tppid, tpgid, tid, tcmd))
-			{
-			    ht = 1;
-			}
-		    }
-		    (void) closedir(ts);
-		}
-	    }
-#endif	/* defined(HASTASKS) */
-
-	/*
-	 * If the main process is a task and task selection has been specified
-	 * along with option ANDing, enter the main process temporarily as a
-	 * task, so that the "-aK" option set lists the main process along
-	 * with its tasks.
-	 */
-	    if ((prv >= 0) && (prv != 1)) {
-		tid = (Fand && ht && pidts && !IgnTasks && (Selflags & SELTASK))
-		    ? pid : 0;
-		if ((!process_id(pidpath, n, cmd, uid, pid, ppid, pgid, tid,
-				 (char *)NULL))
-		&&  tid)
-		{
-		    Lp->tid = 0;
-		}
-	    }
-	}
-}
-
-
-/*
- * get_fdinfo() - get values from /proc/<PID>fdinfo/FD
- */
-
-static int
-get_fdinfo(p, msk, fi)
-	char *p;			/* path to fdinfo file */
-	int msk;			/* mask for information type: e.g.,
-					 * the FDINFO_* definition */
-	struct l_fdinfo *fi;		/* pointer to local fdinfo values
-					 * return structure */
-{
-	char buf[MAXPATHLEN + 1], *ep, **fp;
-	FILE *fs;
-	int rv = 0;
-	unsigned long ul;
-	unsigned long long ull;
-/*
- * Signal no values returned (0) if no fdinfo pointer was provided or if the
- * fdinfo path can't be opened.
- */
-	if (!fi)
-	    return(0);
-
-#if	defined(HASEPTOPTS)
-	fi->eventfd_id = -1;
-#if	defined(HASPTYEPT)
-	fi->tty_index = -1;
-#endif	/* defined(HASPTYEPT) */
-#endif	/* defined(HASEPTOPTS) */
-	fi->pid = -1;
-	fi->tfd_count = 0;
-
-	if (!p || !*p || !(fs = fopen(p, "r")))
-	    return(0);
-/*
- * Read the fdinfo file.
- */
-	while (fgets(buf, sizeof(buf), fs)) {
-	    int opt_flg = 0;
-	    if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) < 2)
-		continue;
-	    if (!fp[0] || !*fp[0] || !fp[1] || !*fp[1])
-		continue;
-	    if ((msk & FDINFO_FLAGS) && !strcmp(fp[0], "flags:")) {
-
-	    /*
-	     * Process a "flags:" line.
-	     */
-		ep = (char *)NULL;
-		if ((ul = strtoul(fp[1], &ep, 0)) == ULONG_MAX
-		||  !ep || *ep)
-		    continue;
-		fi->flags = (unsigned int)ul;
-		if ((rv |= FDINFO_FLAGS) == msk)
-		    break;
-	    } else if ((msk & FDINFO_POS) && !strcmp(fp[0], "pos:")) {
-
-	    /*
-	     * Process a "pos:" line.
-	     */
-		ep = (char *)NULL;
-		if ((ull = strtoull(fp[1], &ep, 0)) == ULLONG_MAX
-		||  !ep || *ep)
-		    continue;
-		fi->pos = (off_t)ull;
-		if ((rv |= FDINFO_POS) == msk)
-		    break;
-
-	    } else if (
-		       ((msk & FDINFO_PID) && !strcmp(fp[0], "Pid:")
-			&& ((opt_flg = FDINFO_PID)))
-		       || ((msk & FDINFO_TFD) && !strcmp(fp[0], "tfd:")
-			   && ((opt_flg = FDINFO_TFD)))
-#if	defined(HASEPTOPTS)
-		       || ((msk & FDINFO_EVENTFD_ID) && !strcmp(fp[0], "eventfd-id:")
-			   && ((opt_flg = FDINFO_EVENTFD_ID)))
-#if	defined(HASPTYEPT)
-		       || ((msk & FDINFO_TTY_INDEX) && !strcmp(fp[0], "tty-index:")
-			   && ((opt_flg = FDINFO_TTY_INDEX)))
-#endif	/* defined(HASPTYEPT) */
-#endif	/* defined(HASEPTOPTS) */
-		       ) {
-		int val;
-	    /*
-	     * Process a "tty-index:", "eventfd-id:", "Pid:", or "tfid:" line.
-	     */
-		ep = (char *)NULL;
-		if ((ul = strtoul(fp[1], &ep, 0)) == ULONG_MAX
-		||  !ep || *ep)
-		     continue;
-
-		val = (int)ul;
-		if (val < 0) {
-		/*
-		 * Oops! If integer overflow occurred, reset the field.
-		 */
-		     val = -1;
-		}
-
-		rv |= opt_flg;
-		switch (opt_flg) {
-#if	defined(HASEPTOPTS)
-		case FDINFO_EVENTFD_ID:
-		    fi->eventfd_id = val;
-		    break;
-#if	defined(HASPTYEPT)
-		case FDINFO_TTY_INDEX:
-		    fi->tty_index = val;
-		    break;
-#endif	/* defined(HASPTYEPT) */
-#endif	/* defined(HASEPTOPTS) */
-		case FDINFO_PID:
-		    fi->pid = val;
-		    break;
-		case FDINFO_TFD:
-		    if (fi->tfd_count < EPOLL_MAX_TFDS) {
-			fi->tfds [fi->tfd_count] = val;
-			fi->tfd_count++;
-		    }
-		    break;
-		}
-
-		if ((
-			/* There can be more than one tfd: lines.
-			   So even if we found one, we can not exit the loop.
-			   However, we can assume tfd lines are continuous. */
-			opt_flg != FDINFO_TFD
-			&& (rv == msk || (rv & FDINFO_TFD))
-		    )
-		    || (
-			/* Too many tfds. */
-			opt_flg == FDINFO_TFD
-			&& rv == msk && fi->tfd_count == EPOLL_MAX_TFDS
-		    ))
-		  break;
-	    }
-	}
-	fclose(fs);
-/*
- * Signal via the return value what information was obtained. (0 == none)
- */
-	return(rv);
-}
-
-
-/*
- * getlinksrc() - get the source path name for the /proc/<PID>/fd/<FD> link
- */
-
-
-static int
-getlinksrc(ln, src, srcl, rest)
-	char *ln;			/* link path */
-	char *src;			/* link source path return address */
-	int srcl;			/* length of src[] */
-	char **rest;			/* pointer to what follows the ':' in
-					 * the link source path (NULL if no
-					 * return requested) */
-{
-	char *cp;
-	int ll;
-
-	if (rest)
-	    *rest = (char *)NULL;
-	if ((ll = readlink(ln, src, srcl - 1)) < 1
-	||  ll >= srcl)
-	    return(-1);
-	src[ll] = '\0';
-	if (*src == '/')
-	    return(ll);
-	if ((cp = strchr(src, ':'))) {
-	    *cp = '\0';
-	    ll = strlen(src);
-	    if (rest)
-		*rest = cp + 1;
-	}
-	return(ll);
-}
-
-
-/*
- * initialize() - perform all initialization
- */
-
-void
-initialize()
-{
-	int fd;
-	struct l_fdinfo fi;
-	char path[MAXPATHLEN];
-	struct stat sb;
-/*
- * Test for -i and -X option conflict.
- */
-	if (Fxopt && (Fnet || Nwad)) {
-	    (void) fprintf(stderr, "%s: -i is useless when -X is specified.\n",
-		Pn);
-	    usage(1, 0, 0);
-	}
-/*
- * Open LSTAT_TEST_FILE and seek to byte LSTAT_TEST_SEEK, then lstat the
- * /proc/<PID>/fd/<FD> for LSTAT_TEST_FILE to see what position is reported.
- * If the result is LSTAT_TEST_SEEK, enable offset reporting.
- *
- * If the result isn't LSTAT_TEST_SEEK, next check the fdinfo file for the
- * open LSTAT_TEST_FILE file descriptor.  If it exists and contains a "pos:"
- * value, and if the value is LSTAT_TEST_SEEK, enable offset reporting.
- */
-	if ((fd = open(LSTAT_TEST_FILE, O_RDONLY)) >= 0) {
-	    if (lseek(fd, (off_t)LSTAT_TEST_SEEK, SEEK_SET)
-	    == (off_t)LSTAT_TEST_SEEK) {
-		(void) snpf(path, sizeof(path), "%s/%d/fd/%d", PROCFS, Mypid,
-			    fd);
-		if (!lstat(path, &sb)) {
-		    if (sb.st_size == (off_t)LSTAT_TEST_SEEK)
-			OffType = 1;
-		}
-	    }
-	    if (!OffType) {
-		(void) snpf(path, sizeof(path), "%s/%d/fdinfo/%d", PROCFS,
-			    Mypid, fd);
-		if (get_fdinfo(path, FDINFO_POS, &fi) & FDINFO_POS) {
-		    if (fi.pos == (off_t)LSTAT_TEST_SEEK)
-			OffType = 2;
-		}
-	    }
-	    (void) close(fd);
-	}
-	if (!OffType) {
-	    if (Foffset && !Fwarn)
-		(void) fprintf(stderr,
-		    "%s: WARNING: can't report offset; disregarding -o.\n",
-		    Pn);
-	    Foffset = 0;
-	    Fsize = 1;
-	}
-	if (Fsv && (OffType != 2)) {
-	    if (!Fwarn && FsvByf)
-		(void) fprintf(stderr,
-		    "%s: WARNING: can't report file flags; disregarding +f.\n",
-		    Pn);
-	    Fsv = 0;
-	}
-/*
- * Make sure the local mount info table is loaded if doing anything other
- * than just Internet lookups.  (HasNFS is defined during the loading of the
- * local mount table.)
- */
-	if (Selinet == 0)
-	    (void) readmnt();
-}
-
-
-/*
- * make_proc_path() - make a path in a /proc directory
- *
- * entry:
- *	pp = pointer to /proc prefix
- *	lp = length of prefix
- *	np = pointer to malloc'd buffer to receive new file's path
- *	nl = length of new file path buffer
- *	sf = new path's suffix
- *
- * return: length of new path
- *	np = updated with new path
- *	nl = updated with new path length
- */
-
-int
-make_proc_path(pp, pl, np, nl, sf)
-	char *pp;			/* path prefix -- e.g., /proc/<pid>/ */
-	int pl;				/* strlen(pp) */
-	char **np;			/* malloc'd receiving buffer */
-	int *nl;			/* strlen(*np) */
-	char *sf;			/* suffix of new path */
-{
-	char *cp;
-	MALLOC_S rl, sl;
-
-	sl = strlen(sf);
-	if ((rl = pl + sl + 1) > *nl) {
-	    if ((cp = *np))
-		cp = (char *)realloc((MALLOC_P *)cp, rl);
-	    else
-		cp = (char *)malloc(rl);
-	    if (!cp) {
-		(void) fprintf(stderr,
-		    "%s: can't allocate %d bytes for %s%s\n",
-		    Pn, (int)rl, pp, sf);
-		Error();
-	    }
-	    *nl = rl;
-	    *np = cp;
-	}
-	(void) snpf(*np, *nl, "%s", pp);
-	(void) snpf(*np + pl, *nl - pl, "%s", sf);
-	return(rl - 1);
-}
-
-
-/*
- * isefsys() -- is path on a file system exempted with -e
- *
- * Note: alloc_lfile() must have been called in advance.
- */
-
-static int
-isefsys(path, type, l, rep, lfr)
-	char *path;			/* path to file */
-	char *type;			/* unknown file type */
-	int l;				/* link request: 0 = report
-					 *               1 = link */
-	efsys_list_t **rep;		/* returned Efsysl pointer, if not
-					 * NULL */
-	struct lfile **lfr;		/* allocated struct lfile pointer */
-{
-	efsys_list_t *ep;
-	int ds, len;
-	struct mounts *mp;
-	char nmabuf[MAXPATHLEN + 1];
-
-	len = (int) strlen(path);
-	for (ep = Efsysl; ep; ep = ep->next) {
-
-	/*
-	 * Look for a matching exempt file system path at the beginning of
-	 * the file path.
-	 */
-	    if (ep->pathl > len)
-		continue;
-	    if (strncmp(ep->path, path, ep->pathl))
-		continue;
-	/*
-	 * If only reporting, return information as requested.
-	 */
-	    if (!l) {
-		if (rep)
-		    *rep = ep;
-		return(0);
-	    }
-	/*
-	 * Process an exempt file.
-	 */
-	    ds = 0;
-	    if ((mp = ep->mp)) {
-		if (mp->ds & SB_DEV) {
-		    Lf->dev = mp->dev;
-		    ds = Lf->dev_def = 1;
-		}
-		if (mp->ds & SB_RDEV) {
-		    Lf->rdev = mp->rdev;
-		    ds = Lf->rdev_def = 1;
-		}
-	    }
-	    if (!ds)
-		(void) enter_dev_ch("UNKNOWN");
-	    Lf->ntype = N_UNKN;
-	    (void) snpf(Lf->type, sizeof(Lf->type), "%s",
-			(type ? type : "UNKN"));
-	    (void) enter_nm(path);
-	    (void) snpf(nmabuf, sizeof(nmabuf), "(%ce %s)",
-		ep->rdlnk ? '+' : '-', ep->path);
-	    nmabuf[sizeof(nmabuf) - 1] = '\0';
-	    (void) add_nma(nmabuf, strlen(nmabuf));
-	    if (Lf->sf) {
-		if (lfr)
-		    *lfr = Lf;
-		link_lfile();
-	    } else if (lfr)
-		*lfr = (struct lfile *)NULL;
-	    return(0);
-	}
-	return(1);
-}
-
-
-/*
- * nm2id() - convert a name to an integer ID
- */
-
-static int
-nm2id(nm, id, idl)
-	char *nm;			/* pointer to name */
-	int *id;			/* pointer to ID receiver */
-	int *idl;			/* pointer to ID length receiver */
-{
-	register int tid, tidl;
-
-	for (*id = *idl = tid = tidl = 0; *nm; nm++) {
-
-#if	defined(__STDC__)	/* { */
-	    if (!isdigit((unsigned char)*nm))
-#else	/* !defined(__STDC__)	   } { */
-	    if (!isascii(*nm) || !isdigit((unsigned char)*cp))
-#endif	/* defined(__STDC__)	   } */
-
-		{
-		    return(1);
-		}
-		tid = tid * 10 + (int)(*nm - '0');
-		tidl++;
-	}
-	*id = tid;
-	*idl = tidl;
-	return(0);
-}
-
-
-/*
- * open_proc_stream() -- open a /proc stream
- */
-
-FILE *
-open_proc_stream(p, m, buf, sz, act)
-	char *p;			/* pointer to path to open */
-	char *m;			/* pointer to mode -- e.g., "r" */
-	char **buf;			/* pointer tp setvbuf() address
-					 * (NULL if none) */
-	size_t *sz;			/* setvbuf() size (0 if none or if
-					 * getpagesize() desired */
-	int act;			/* fopen() failure action:
-					 *     0 : return (FILE *)NULL
-					 *   <>0 : fprintf() an error message
-					 *         and Error()
-					 */
-{
-	FILE *fs;			/* opened stream */
-	static size_t psz = (size_t)0;	/* page size */
-	size_t tsz;			/* temporary size */
-/*
- * Open the stream.
- */
-	if (!(fs = fopen(p, m))) {
-	    if (!act)
-		return((FILE *)NULL);
-	    (void) fprintf(stderr, "%s: can't fopen(%s, \"%s\"): %s\n",
-		Pn, p, m, strerror(errno));
-	    Error();
-	}
-/*
- * Return the stream if no buffer change is required.
- */
-	if (!buf)
-	    return(fs);
-/*
- * Determine the buffer size required.
- */
-	if (!(tsz = *sz)) {
-	    if (!psz)
-		psz = getpagesize();
-	    tsz = psz;
-	}
-/*
- * Allocate a buffer for the stream, as required.
- */
-	if (!*buf) {
-	    if (!(*buf = (char *)malloc((MALLOC_S)tsz))) {
-		(void) fprintf(stderr,
-		    "%s: can't allocate %d bytes for %s stream buffer\n",
-		    Pn, (int)tsz, p);
-		Error();
-	    }
-	    *sz = tsz;
-	}
-/*
- * Assign the buffer to the stream.
- */
-	if (setvbuf(fs, *buf, _IOFBF, tsz)) {
-	    (void) fprintf(stderr, "%s: setvbuf(%s)=%d failure: %s\n",
-		Pn, p, (int)tsz, strerror(errno));
-	    Error();
-	}
-	return(fs);
-}
-
-
-/*
- * process_id - process ID: PID or LWP
- *
- * return:  0 == ID processed
- *          1 == ID not processed
- */
-
-static int
-process_id(idp, idpl, cmd, uid, pid, ppid, pgid, tid, tcmd)
-	char *idp;			/* pointer to ID's path */
-	int idpl;			/* pointer to ID's path length */
-	char *cmd;			/* pointer to ID's command */
-	UID_ARG uid;			/* ID's UID */
-	int pid;			/* ID's PID */
-	int ppid;			/* parent PID */
-	int pgid;			/* parent GID */
-	int tid;			/* task ID, if non-zero */
-	char *tcmd;			/* task command, if non-NULL) */
-{
-	int av = 0;
-	static char *dpath = (char *)NULL;
-	static int dpathl = 0;
-	short efs, enls, enss, lnk, oty, pn, pss, sf;
-	int fd, i, ls, n, ss, sv;
-	struct l_fdinfo fi;
-	DIR *fdp;
-	struct dirent *fp;
-	static char *ipath = (char *)NULL;
-	static int ipathl = 0;
-	int j = 0;
-	struct lfile *lfr;
-	struct stat lsb, sb;
-	char nmabuf[MAXPATHLEN + 1], pbuf[MAXPATHLEN + 1];
-	static char *path = (char *)NULL;
-	static int pathl = 0;
-	static char *pathi = (char *)NULL;
-	static int pathil = 0;
-	char *rest;
-	int txts = 0;
-
-#if	defined(HASSELINUX)
-	cntxlist_t *cntxp;
-#endif	/* defined(HASSELINUX) */
-
-/*
- * See if process is excluded.
- */
-	if (is_proc_excl(pid, pgid, uid, &pss, &sf, tid)
-	||  is_cmd_excl(cmd, &pss, &sf))
-	{
-
-#if	defined(HASEPTOPTS)
-	    if (!FeptE)
-		return(1);
-#else	/* !defined(HASEPTOPTS) */
-	    return(1);
-#endif	/* defined(HASEPTOPTS) */
-
-	}
-	if (Cckreg && !FeptE) {
-
-	/*
-	 * 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, ppid, uid, cmd, (int)pss, (int)sf);
-	Plf = (struct lfile *)NULL;
-
-#if	defined(HASTASKS)
-/*
- * Enter task information.
- */
-	Lp->tid = tid;
-	if (tid && tcmd) {
-	    if (!(Lp->tcmd = mkstrcpy(tcmd, (MALLOC_S *)NULL))) {
-		(void) fprintf(stderr,
-		    "%s: PID %d, TID %d, no space for task name: ",
-		    Pn, pid, tid);
-		safestrprt(tcmd, stderr, 1);
-		Error();
-	    }
-	}
-#endif	/* defined(HASTASKS) */
-
-/*
- * 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);
-	    if (getlinksrc(path, pbuf, sizeof(pbuf), (char **)NULL) < 1) {
-		if (!Fwarn) {
-		    zeromem((char *)&sb, sizeof(sb));
-		    lnk = ss = 0;
-		    (void) snpf(nmabuf, sizeof(nmabuf), "(readlink: %s)",
-			strerror(errno));
-		    nmabuf[sizeof(nmabuf) - 1] = '\0';
-		    (void) add_nma(nmabuf, strlen(nmabuf));
-		    pn = 1;
-		} else
-		    pn = 0;
-	    } else {
-		lnk = pn = 1;
-		if (Efsysl && !isefsys(pbuf, "UNKNcwd", 1, NULL, &lfr)) {
-		    efs = 1;
-		    pn = 0;
-		} else {
-		    ss = SB_ALL;
-		    if (HasNFS) {
-			if ((sv = statsafely(path, &sb)))
-			sv = statEx(pbuf, &sb, &ss);
-		    } else
-			sv = stat(path, &sb);
-		    if (sv) {
-			ss = 0;
-			if (!Fwarn) {
-			    (void) snpf(nmabuf, sizeof(nmabuf), "(stat: %s)",
-				strerror(errno));
-			    nmabuf[sizeof(nmabuf) - 1] = '\0';
-			    (void) add_nma(nmabuf, strlen(nmabuf));
-			}
-		    }
-		}
-	    }
-	    if (pn) {
-		(void) process_proc_node(lnk ? pbuf : path,
-					 path, &sb, ss,
-					 (struct stat *)NULL, 0);
-		if (Lf->sf)
-		    link_lfile();
-	    }
-	}
-/*
- * 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) {
-		    zeromem((char *)&sb, sizeof(sb));
-		    (void) snpf(nmabuf, sizeof(nmabuf), "(readlink: %s)",
-			strerror(errno));
-		    nmabuf[sizeof(nmabuf) - 1] = '\0';
-		    (void) add_nma(nmabuf, strlen(nmabuf));
-		    pn = 1;
-		} else
-		    pn = 0;
-	    } else {
-		lnk = pn = 1;
-		if (Efsysl && !isefsys(pbuf, "UNKNrtd", 1, NULL, NULL))
-		    pn = 0;
-		else {
-		    ss = SB_ALL;
-		    if (HasNFS) {
-			if ((sv = statsafely(path, &sb)))
-			    sv = statEx(pbuf, &sb, &ss);
-		    } else
-			sv = stat(path, &sb);
-		    if (sv) {
-			ss = 0;
-			if (!Fwarn) {
-			    (void) snpf(nmabuf, sizeof(nmabuf), "(stat: %s)",
-				strerror(errno));
-			    nmabuf[sizeof(nmabuf) - 1] = '\0';
-			    (void) add_nma(nmabuf, strlen(nmabuf));
-			}
-		    }
-		}
-	    }
-	    if (pn) {
-		(void) process_proc_node(lnk ? pbuf : path,
-					 path, &sb, ss,
-					 (struct stat *)NULL, 0);
-		if (Lf->sf)
-		    link_lfile();
-	    }
-	}
-/*
- * Process the ID's execution info.
- */
-	lnk = ss = txts = 0;
-	if (!Ckscko) {
-	    (void) make_proc_path(idp, idpl, &path, &pathl, "exe");
-	    alloc_lfile("txt", -1);
-	    if (getlinksrc(path, pbuf, sizeof(pbuf), (char **)NULL) < 1) {
-		zeromem((void *)&sb, sizeof(sb));
-		if (!Fwarn) {
-		    if ((errno != ENOENT) || uid) {
-			(void) snpf(nmabuf, sizeof(nmabuf), "(readlink: %s)",
-			    strerror(errno));
-			nmabuf[sizeof(nmabuf) - 1] = '\0';
-			(void) add_nma(nmabuf, strlen(nmabuf));
-		    }
-		    pn = 1;
-		} else
-		    pn = 0;
-	    } else {
-		lnk = pn = 1;
-		if (Efsysl && !isefsys(pbuf, "UNKNtxt", 1, NULL, NULL))
-		    pn = 0;
-		else {
-		    ss = SB_ALL;
-		    if (HasNFS) {
-			if ((sv = statsafely(path, &sb))) {
-			    sv = statEx(pbuf, &sb,  &ss);
-			    if (!sv && (ss & SB_DEV) && (ss & SB_INO))
-				txts = 1;
-			}
-		    } else
-			sv = stat(path, &sb);
-		    if (sv) {
-			ss = 0;
-			if (!Fwarn) {
-			    (void) snpf(nmabuf, sizeof(nmabuf), "(stat: %s)",
-				strerror(errno));
-			    nmabuf[sizeof(nmabuf) - 1] = '\0';
-			    (void) add_nma(nmabuf, strlen(nmabuf));
-			}
-		    } else
-			txts = 1;
-		}
-	    }
-	    if (pn) {
-		(void) process_proc_node(lnk ? pbuf : path,
-					 path, &sb, ss,
-					 (struct stat *)NULL, 0);
-		if (Lf->sf)
-		    link_lfile();
-	    }
-	}
-/*
- * Process the ID's memory map info.
- */
-	if (!Ckscko) {
-	    (void) make_proc_path(idp, idpl, &path, &pathl, "maps");
-	    (void) process_proc_map(path, txts ? &sb : (struct stat *)NULL,
-				    txts ? ss : 0);
-	}
-
-#if	defined(HASSELINUX)
-/*
- * Process the PID's SELinux context.
- */
-	if (Fcntx) {
-
-	/*
-	 * If the -Z (cntx) option was specified, match the valid contexts.
-	 */
-	    errno = 0;
-	    if (getpidcon(pid, &Lp->cntx) == -1) {
-		Lp->cntx = (char *)NULL;
-		if (!Fwarn) {
-		    (void) snpf(nmabuf, sizeof(nmabuf),
-			"(getpidcon: %s)", strerror(errno));
-		    if (!(Lp->cntx = strdup(nmabuf))) {
-			(void) fprintf(stderr,
-			    "%s: no context error space: PID %ld",
-			    Pn, (long)Lp->pid);
-			Error();
-		    }
-		}
-	    } else if (CntxArg) {
-
-	    /*
-	     * See if context includes the process.
-	     */
-		for (cntxp = CntxArg; cntxp; cntxp = cntxp->next) {
-		    if (cmp_cntx_eq(Lp->cntx, cntxp->cntx)) {
-			cntxp->f = 1;
-			Lp->pss |= PS_PRI;
-			Lp->sf |= SELCNTX;
-			break;
-		    }
-		}
-	    }
-	}
-#endif	/* defined(HASSELINUX) */
-
-/*
- * Process the ID's file descriptor directory.
- */
-	if ((i = make_proc_path(idp, idpl, &dpath, &dpathl, "fd/")) < 3)
-	    return(0);
-	dpath[i - 1] = '\0';
-	if ((OffType == 2)
-	&&  ((j = make_proc_path(idp, idpl, &ipath, &ipathl, "fdinfo/")) >= 7))
-	    oty = 1;
-	else
-	    oty = 0;
-	if (!(fdp = opendir(dpath))) {
-	    if (!Fwarn) {
-		(void) snpf(nmabuf, sizeof(nmabuf), "%s (opendir: %s)",
-		    dpath, strerror(errno));
-		alloc_lfile("NOFD", -1);
-		nmabuf[sizeof(nmabuf) - 1] = '\0';
-		(void) add_nma(nmabuf, strlen(nmabuf));
-		link_lfile();
-	    }
-	    return(0);
-	}
-	dpath[i - 1] = '/';
-	while ((fp = readdir(fdp))) {
-	    if (nm2id(fp->d_name, &fd, &n))
-		continue;
-	    (void) make_proc_path(dpath, i, &path, &pathl, fp->d_name);
-	    (void) alloc_lfile((char *)NULL, fd);
-	    if (getlinksrc(path, pbuf, sizeof(pbuf), &rest) < 1) {
-		zeromem((char *)&sb, sizeof(sb));
-		lnk = ss = 0;
-		if (!Fwarn) {
-		    ls = 0;
-		    (void) snpf(nmabuf, sizeof(nmabuf), "(readlink: %s)",
-			strerror(errno));
-		    nmabuf[sizeof(nmabuf) - 1] = '\0';
-		    (void) add_nma(nmabuf, strlen(nmabuf));
-		    pn = 1;
-		} else
-		    pn = 0;
-	    } else {
-		lnk = 1;
-		if (Efsysl && !isefsys(pbuf, "UNKNfd", 1, NULL, &lfr)) {
-		    efs = 1;
-		    pn = 0;
-		} else {
-		    if (HasNFS) {
-			if (lstatsafely(path, &lsb)) {
-			    (void) statEx(pbuf, &lsb, &ls);
-			    enls = errno;
-			} else {
-			    enls = 0;
-			    ls = SB_ALL;
-			}
-			if (statsafely(path, &sb)) {
-			    (void) statEx(pbuf, &sb, &ss);
-			    enss = errno;
-			} else {
-			    enss = 0;
-			    ss = SB_ALL;
-			}
-		    } else {
-			ls = lstat(path, &lsb) ? 0 : SB_ALL;
-			enls = errno;
-			ss = stat(path, &sb) ? 0 : SB_ALL;
-			enss = errno;
-		    }
-		    if (!ls && !Fwarn) {
-			(void) snpf(nmabuf, sizeof(nmabuf), "lstat: %s)",
-			    strerror(enls));
-			nmabuf[sizeof(nmabuf) - 1] = '\0';
-			(void) add_nma(nmabuf, strlen(nmabuf));
-		    }
-		    if (!ss && !Fwarn) {
-			(void) snpf(nmabuf, sizeof(nmabuf), "(stat: %s)",
-			    strerror(enss));
-			nmabuf[sizeof(nmabuf) - 1] = '\0';
-			(void) add_nma(nmabuf, strlen(nmabuf));
-		    }
-		    if (Ckscko) {
-			if ((ss & SB_MODE)
-			&&  ((sb.st_mode & S_IFMT) == S_IFSOCK))
-			{
-			    pn = 1;
-			} else
-			    pn = 0;
-		    } else
-			pn = 1;
-		}
-	    }
-	    if (pn || (efs && lfr && oty)) {
-		if (oty) {
-		    int fdinfo_mask = FDINFO_BASE;
-		    (void) make_proc_path(ipath, j, &pathi, &pathil,
-					  fp->d_name);
-
-		    if (rest && rest[0] == '['
-			&& rest[1] == 'e' && rest[2] == 'v' && rest[3] == 'e'
-			&& rest[4] == 'n' && rest[5] == 't') {
-#if	defined(HASEPTOPTS)
-			if (rest[6] == 'f')
-			    fdinfo_mask |= FDINFO_EVENTFD_ID;
-#endif	/* defined(HASEPTOPTS) */
-			else if (rest[6] == 'p')
-			    fdinfo_mask |= FDINFO_TFD;
-		    }
-#if	defined(HASEPTOPTS)
-#if	defined(HASPTYEPT)
-		    fdinfo_mask |= FDINFO_TTY_INDEX;
-#endif  /* defined(HASPTYEPT) */
-#endif	/* defined(HASEPTOPTS) */
-		    if (rest && rest[0] == '[' && rest[1] == 'p')
-			fdinfo_mask |= FDINFO_PID;
-
-		    if ((av = get_fdinfo(pathi,fdinfo_mask,&fi)) & FDINFO_POS) {
-			if (efs) {
-			    if (Foffset) {
-				lfr->off = (SZOFFTYPE)fi.pos;
-				lfr->off_def = 1;
-			    }
-			} else {
-			    ls |= SB_SIZE;
-			    lsb.st_size = fi.pos;
-			}
-		    } else
-			ls &= ~SB_SIZE;
-
-#if	!defined(HASNOFSFLAGS)
-		    if ((av & FDINFO_FLAGS) && (Fsv & FSV_FG)) {
-			if (efs) {
-			    lfr->ffg = (long)fi.flags;
-			    lfr->fsv |= FSV_FG;
-			} else {
-			    Lf->ffg = (long)fi.flags;
-			    Lf->fsv |= FSV_FG;
-			}
-		     }
-# endif	/* !defined(HASNOFSFLAGS) */
-
-		}
-		if (pn) {
-		    process_proc_node(lnk ? pbuf : path, path, &sb, ss, &lsb,
-				      ls);
-		    if (Lf->ntype == N_ANON_INODE) {
-			if (rest && *rest) {
-#if	defined(HASEPTOPTS)
-			    if (fi.eventfd_id != -1
-				&& strcmp(rest, "[eventfd]") == 0) {
-				(void) snpf(rest,
-					    sizeof(pbuf) - (rest - pbuf),
-					    "[eventfd:%d]", fi.eventfd_id);
-			    }
-#endif	/* defined(HASPTYEPT) */
-			    if (fi.pid != -1
-				&& strcmp(rest, "[pidfd]") == 0) {
-				(void) snpf (rest,
-					     sizeof(pbuf) - (rest - pbuf),
-					     "[pidfd:%d]", fi.pid);
-			    }
-			    if (fi.tfd_count > 0
-				&& strcmp(rest, "[eventpoll]") == 0) {
-				snp_eventpoll (rest, sizeof(pbuf) - (rest - pbuf),
-					       fi.tfds, fi.tfd_count);
-			    }
-
-			    enter_nm(rest);
-			}
-#if	defined(HASEPTOPTS)
-			if (FeptE && fi.eventfd_id != -1) {
-			    enter_evtfdinfo(fi.eventfd_id);
-			    Lf->eventfd_id = fi.eventfd_id;
-			    Lf->sf |= SELEVTFDINFO;
-			}
-#endif	/* defined(HASPTYEPT) */
-		    }
-#if	defined(HASEPTOPTS) && defined(HASPTYEPT)
-		    else if (FeptE
-			 &&  Lf->rdev_def
-			 &&  is_pty_ptmx(Lf->rdev)
-			 &&  (av & FDINFO_TTY_INDEX)
-		    ) {
-			    enter_ptmxi(fi.tty_index);
-			    Lf->tty_index = fi.tty_index;
-			    Lf->sf |= SELPTYINFO;
-		    }
-#endif	/* defined(HASEPTOPTS) && defined(HASPTYEPT) */
-
-		    if (Lf->sf)
-			link_lfile();
-		}
-	    }
-	}
-	(void) closedir(fdp);
-	return(0);
-}
-
-
-/*
- * process_proc_map() - process the memory map of a process
- */
-
-static void
-process_proc_map(p, s, ss)
-	char *p;			/* path to process maps file */
-	struct stat *s;			/* executing text file state buffer */
-	int ss;				/* *s status -- i.e., SB_* values */
-{
-	char buf[MAXPATHLEN + 1], *ep, fmtbuf[32], **fp, nmabuf[MAXPATHLEN + 1];
-	dev_t dev;
-	int ds, efs, en, i, mss, nf, sv;
-	int eb = 6;
-	INODETYPE inode;
-	MALLOC_S len;
-	long maj, min;
-	FILE *ms;
-	int ns = 0;
-	struct stat sb;
-	struct saved_map {
-	    dev_t dev;
-	    INODETYPE inode;
-	};
-	static struct saved_map *sm = (struct saved_map *)NULL;
-	efsys_list_t *rep;
-	static int sma = 0;
-	static char *vbuf = (char *)NULL;
-	static size_t vsz = (size_t)0;
-/*
- * Open the /proc/<pid>/maps file, assign a page size buffer to its stream,
- * and read it/
- */
-	if (!(ms = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
-	    return;
-	while (fgets(buf, sizeof(buf), ms)) {
-	    if ((nf = get_fields(buf, ":", &fp, &eb, 1)) < 7)
-		continue;			/* not enough fields */
-	    if (!fp[6] || !*fp[6])
-		continue;			/* no path name */
-	/*
-	 * See if the path ends in " (deleted)".  If it does, strip the
-	 * " (deleted)" characters and remember that they were there.
-	 */
-	    if (((ds = (int)strlen(fp[6])) > 10)
-	    &&  !strcmp(fp[6] + ds - 10, " (deleted)"))
-	    {
-		*(fp[6] + ds - 10) = '\0';
-	    } else
-		ds = 0;
-	/*
-	 * Assemble the major and minor device numbers.
-	 */
-	    ep = (char *)NULL;
-	    if (!fp[3] || !*fp[3]
-	    ||  (maj = strtol(fp[3], &ep, 16)) == LONG_MIN || maj == LONG_MAX
-	    ||  !ep || *ep)
-		continue;
-	    ep = (char *)NULL;
-	    if (!fp[4] || !*fp[4]
-	    ||  (min = strtol(fp[4], &ep, 16)) == LONG_MIN || min == LONG_MAX
-	    ||  !ep || *ep)
-		continue;
-	/*
-	 * Assemble the device and inode numbers.  If they are both zero, skip
-	 * the entry.
-	 */
-	    dev = (dev_t)makedev((int)maj, (int)min);
-	    if (!fp[5] || !*fp[5])
-		continue;
-	    ep = (char *)NULL;
-	    if ((inode = strtoull(fp[5], &ep, 0)) == ULLONG_MAX
-	    ||  !ep || *ep)
-		continue;
-	    if (!dev && !inode)
-		continue;
-	/*
-	 * See if the device + inode pair match that of the executable.
-	 * If they do, skip this map entry.
-	 */
-	    if (s && (ss & SB_DEV) && (ss & SB_INO)
-	    &&  (dev == s->st_dev) && (inode == (INODETYPE)s->st_ino))
-		continue;
-	/*
-	 * See if this device + inode pair has already been processed as
-	 * a map entry.
-	 */
-	    for (i = 0; i < ns; i++) {
-		if (dev == sm[i].dev && inode == sm[i].inode)
-		    break;
-	    }
-	    if (i < ns)
-		continue;
-	/*
-	 * Record the processing of this map entry's device and inode pair.
-	 */
-	    if (ns >= sma) {
-		sma += 10;
-		len = (MALLOC_S)(sma * sizeof(struct saved_map));
-		if (sm)
-		    sm = (struct saved_map *)realloc(sm, len);
-		else
-		    sm = (struct saved_map *)malloc(len);
-		if (!sm) {
-		    (void) fprintf(stderr,
-			"%s: can't allocate %d bytes for saved maps, PID %d\n",
-			Pn, (int)len, Lp->pid);
-		    Error();
-		}
-	    }
-	    sm[ns].dev = dev;
-	    sm[ns++].inode = inode;
-	/*
-	 * Allocate space for the mapped file, then get stat(2) information
-	 * for it.  Skip the stat(2) operation if this is on an exempt file
-	 * system.
-	 */
-	    alloc_lfile("mem", -1);
-	    if (Efsysl && !isefsys(fp[6], (char *)NULL, 0, &rep, NULL))
-		efs = sv = 1;
-	    else
-		efs = 0;
-	    if (!efs) {
-		if (HasNFS)
-		    sv = statsafely(fp[6], &sb);
-		else
-		    sv = stat(fp[6], &sb);
-	    }
-	    if (sv || efs) {
-		en = errno;
-	    /*
-	     * Applying stat(2) to the file was not possible (file is on an
-	     * exempt file system) or stat(2) failed, so manufacture a partial
-	     * stat(2) reply from the process' maps file entry.
-	     *
-	     * If the file has been deleted, reset its type to "DEL";
-	     * otherwise generate a stat() error name addition.
-	     */
-		zeromem((char *)&sb, sizeof(sb));
-		sb.st_dev = dev;
-		sb.st_ino = (ino_t)inode;
-		sb.st_mode = S_IFREG;
-		mss = SB_DEV | SB_INO | SB_MODE;
-		if (ds)
-		    alloc_lfile("DEL", -1);
-		else if (!efs && !Fwarn) {
-		    (void) snpf(nmabuf, sizeof(nmabuf), "(stat: %s)",
-			strerror(en));
-		    nmabuf[sizeof(nmabuf) - 1] = '\0';
-		    (void) add_nma(nmabuf, strlen(nmabuf));
-		}
-	    } else if ((sb.st_dev != dev) || ((INODETYPE)sb.st_ino != inode)) {
-
-	    /*
-	     * The stat(2) device and inode numbers don't match those obtained
-	     * from the process' maps file.
-	     *
-	     * If the file has been deleted, reset its type to "DEL"; otherwise
-	     * generate inconsistency name additions.
-	     *
-	     * Manufacture a partial stat(2) reply from the maps file
-	     * information.
-	     */
-		if (ds)
-		    alloc_lfile("DEL", -1);
-		else if (!Fwarn) {
-		    char *sep;
-
-		    if (sb.st_dev != dev) {
-			(void) snpf(nmabuf, sizeof(nmabuf),
-			    "(path dev=%d,%d%s",
-			    GET_MAJ_DEV(sb.st_dev), GET_MIN_DEV(sb.st_dev),
-			    ((INODETYPE)sb.st_ino == inode) ? ")" : ",");
-			nmabuf[sizeof(nmabuf) - 1] = '\0';
-			(void) add_nma(nmabuf, strlen(nmabuf));
-			sep = "";
-		    } else
-			sep = "(path ";
-		    if ((INODETYPE)sb.st_ino != inode) {
-			(void) snpf(fmtbuf, sizeof(fmtbuf), "%%sinode=%s)",
-			    InodeFmt_d);
-			(void) snpf(nmabuf, sizeof(nmabuf), fmtbuf,
-			    sep, (INODETYPE)sb.st_ino);
-			nmabuf[sizeof(nmabuf) - 1] = '\0';
-			(void) add_nma(nmabuf, strlen(nmabuf));
-		    }
-		}
-		zeromem((char *)&sb, sizeof(sb));
-		sb.st_dev = dev;
-		sb.st_ino = (ino_t)inode;
-		sb.st_mode = S_IFREG;
-		mss = SB_DEV | SB_INO | SB_MODE;
-	    } else
-		mss = SB_ALL;
-	/*
-	 * Record the file's information.
-	 */
-	    if (!efs)
-		process_proc_node(fp[6], fp[6], &sb, mss, (struct stat *)NULL,
-				  0);
-	    else {
-
-	    /*
-	     * If this file is on an exempt file system, complete the lfile
-	     * structure, but change its type and add the exemption note to
-	     * the NAME column.
-	     */
-		Lf->dev = sb.st_dev;
-		Lf->inode = (ino_t)sb.st_ino;
-		Lf->dev_def = Lf->inp_ty = 1;
-		(void) enter_nm(fp[6]);
-		(void) snpf(Lf->type, sizeof(Lf->type), "%s",
-			    (ds ? "UNKNdel" : "UNKNmem"));
-		(void) snpf(nmabuf, sizeof(nmabuf), "(%ce %s)",
-		    rep->rdlnk ? '+' : '-', rep->path);
-		nmabuf[sizeof(nmabuf) - 1] = '\0';
-		(void) add_nma(nmabuf, strlen(nmabuf));
-	    }
-	    if (Lf->sf)
-		link_lfile();
-	}
-	(void) fclose(ms);
-}
-
-
-/*
- * read_id_stat() - read ID (PID or LWP ID) status
- *
- * return: -1 == ID is unavailable
- *          0 == ID OK
- *          1 == ID is a zombie
- *	    2 == ID is a thread
- */
-
-static int
-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 */
-	int *ppid;			/* returned parent PID for PID type */
-	int *pgid;			/* returned process group ID for PID
-					 * type */
-{
-	char buf[MAXPATHLEN], *cp, *cp1, **fp;
-	int ch, cx, es, nf, pc;
-	static char *cbf = (char *)NULL;
-	static MALLOC_S cbfa = 0;
-	FILE *fs;
-	static char *vbuf = (char *)NULL;
-	static size_t vsz = (size_t)0;
-/*
- * Open the stat file path, assign a page size buffer to its stream,
- * and read the file's first line.
- */
-	if (!(fs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
-	    return(-1);
-	if (!(cp = fgets(buf, sizeof(buf), fs))) {
-
-read_id_stat_exit:
-
-	    (void) fclose(fs);
-	    return(-1);
-	}
-/*
- * Skip to the first field, and make sure it is a matching ID.
- */
-	cp1 = cp;
-	while (*cp && (*cp != ' ') && (*cp != '\t'))
-	    cp++;
-	if (*cp)
-	    *cp = '\0';
-	if (atoi(cp1) != id)
-	    goto read_id_stat_exit;
-/*
- * 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.
- *
- */
-	for (++cp; *cp && (*cp == ' '); cp++)
-		;
-	if (!cp || (*cp != '('))
-	    goto read_id_stat_exit;
-	cp++;
-	pc = 1;			/* start the parenthesis balance count at 1 */
-/*
- * 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.  Count embedded '(' characters and balance
- * them with embedded ')' characters.  The opening '(' starts the balance
- * count at one.
- */
-	for (cx = es = 0;;) {
-	    if (!es)
-		ch = *cp++;
-	    else {
-		if ((ch = fgetc(fs)) == EOF)
-		    goto read_id_stat_exit;
-	    }
-	    if (ch == '(')		/* a '(' advances the balance count */
-		pc++;
-	    if (ch == ')') {
-
-	    /*
-	     * Balance parentheses when a closure is encountered.  When
-	     * they are balanced, this is the end of the command.
-	     */
-		pc--;
-		if (!pc)
-		    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. */
-	}
-	*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[1] && *fp[1])
-	    *ppid = atoi(fp[1]);
-	else
-	    return(-1);
-	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[0] && !strcmp(fp[0], "Z"))
-	    return(1);
-	else if (fp[0] && !strcmp(fp[0], "T"))
-	    return(2);
-	return(0);
-}
-
-
-/*
- * statEx() - extended stat() to get device numbers when a "safe" stat has
- *	      failed and the system has an NFS mount
- *
- * Note: this function was suggested by Paul Szabo as a way to get device
- *       numbers for NFS files when an NFS mount point has the root_squash
- *       option set.  In that case, even if lsof is setuid(root), the identity
- *	 of its requests to stat() NFS files lose root permission and may fail.
- *
- *	 This function should be used only when links have been successfully
- *	 resolved in the /proc path by getlinksrc().
- */
-
-static int
-statEx(p, s, ss)
-	char *p;			/* file path */
-	struct stat *s;			/* stat() result -- NULL if none
-					 * wanted */
-	int *ss;			/* stat() status --  SB_* values */
-{
-	static size_t ca = 0;
-	static char *cb = NULL;
-	char *cp;
-	int ensv = ENOENT;
-	struct stat sb;
-	int st = 0;
-	size_t sz;
-/*
- * Make a copy of the path.
- */
-	sz = strlen(p);
-	if ((sz + 1) > ca) {
-	    if (cb)
-		cb = (char *)realloc((MALLOC_P *)cb, sz + 1);
-	    else
-		cb = (char *)malloc(sz + 1);
-	    if (!cb) {
-		(void) fprintf(stderr,
-		    "%s: PID %ld: no statEx path space: %s\n",
-		    Pn, (long)Lp->pid, p);
-		Error();
-	    }
-	    ca = sz + 1;
-	}
-	(void) strcpy(cb, p);
-/*
- * Trim trailing leaves from the end of the path one at a time and do a safe
- * stat() on each trimmed result.  Stop when a safe stat() succeeds or doesn't
- * fail because of EACCES or EPERM.
- */
-	for (cp = strrchr(cb, '/'); cp && (cp != cb);) {
-	    *cp = '\0';
-	    if (!statsafely(cb, &sb)) {
-		st = 1;
-		break;
-	    }
-	    ensv = errno;
-	    if ((ensv != EACCES) && (ensv != EPERM))
-		break;
-	    cp = strrchr(cb, '/');
-	}
-/*
- * If a stat() on a trimmed result succeeded, form partial results containing
- * only the device and raw device numbers.
- */
-	zeromem((char *)s, sizeof(struct stat));
-	if (st) {
-	    errno = 0;
-	    s->st_dev = sb.st_dev;
-	    s->st_rdev = sb.st_rdev;
-	    *ss = SB_DEV | SB_RDEV;
-	    return(0);
-	}
-	errno = ensv;
-	*ss = 0;
-	return(1);
-}
-
-static int
-cal_order (int n)
-{
-	int i = 0;
-	do {
-	    n /= 10;
-	    i++;
-	} while (n);
-	return i;
-}
-
-static int
-snp_eventpoll_fds(char *p, int len, int *tfds, int count)
-{
-	int wl = 0;
-	int i;
-
-	if (len > 0)
-	    p[0] = '\0';
-
-	for (i = 0; i < count; i++) {
-	    int is_last_item = (i == count - 1);
-	    int needs = cal_order (tfds [i]) + (is_last_item? 0: 3);
-
-	    if ((len - wl + (wl? 2: 0)) <= needs) {
-		/* No space to print the tfd. */
-		break;
-	    }
-
-	    if (wl) {
-		/* Rewrite the last "..." to ",". */
-		wl -= 3;
-		p[wl++] = ',';
-	    }
-	    wl += snpf(p + wl, len - wl,
-		       (is_last_item? "%d": "%d..."), tfds[i]);
-	}
-
-	return wl;
-}
-
-static int
-fd_compare(const void *a, const void *b)
-{
-	int ia = *(int *)a, ib = *(int *)b;
-
-	return ia - ib;
-}
-
-static void
-snp_eventpoll(char *p, int len, int *tfds, int tfd_count)
-{
-	/* Reserve the area for prefix: "[eventpoll:" */
-	len -= 11;
-	/* Reserve the area for postfix */
-	len -= ((tfd_count == EPOLL_MAX_TFDS)
-		? 4 /* "...]" */
-		: 1 /* "]" */
-	       ) + 1 /* for the last \0 */
-	;
-
-	if (len > 1) {
-	    qsort (tfds, tfd_count, sizeof (tfds[0]), fd_compare);
-
-	    p[10] = ':'; /* "[eventpoll]" => "[eventpoll:" */
-	    int wl = snp_eventpoll_fds(p + 11, len, tfds, tfd_count);
-
-	    const char *postfix = (
-		/* If the buffer doesn't have enough space, snp_eventpoll_fds puts
-		 * "..." at the end of the buffer. In that case we don't
-		 have to "..." here. */
-		(wl > 3 && p [11 + wl - 1] == '.')
-		? "]"
-		: ((tfd_count == EPOLL_MAX_TFDS)
-		   /* File descriptors more than EPOLL_MAX_TFDS are associated to
-		    * the eventpoll fd. */
-		   ? "...]"
-		   : "]"));
-	    strcpy(p + 11 + wl, postfix);
-	}
-}
diff --git a/dialects/linux/dsock.c b/dialects/linux/dsock.c
deleted file mode 100644
index d586dc4..0000000
--- a/dialects/linux/dsock.c
+++ /dev/null
@@ -1,5315 +0,0 @@
-/*
- * dsock.c - Linux socket processing functions for /proc-based lsof
- */
-
-
-/*
- * 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 1997 Purdue Research Foundation.\nAll rights reserved.\n";
-#endif
-
-
-#include "lsof.h"
-#include <sys/xattr.h>
-
-
-#if	defined(HASEPTOPTS) && defined(HASUXSOCKEPT)
-/*
- * UNIX endpoint definitions
- */
-
-#include <sys/socket.h>			/* for AF_NETLINK */
-#include <linux/rtnetlink.h>		/* for NETLINK_INET_DIAG */
-#include <linux/sock_diag.h>		/* for SOCK_DIAG_BY_FAMILY */
-#include <linux/unix_diag.h>		/* for unix_diag_req */
-#include <string.h>			/* memset */
-#include <stdint.h>			/* for unt8_t */
-#include <unistd.h>			/* for getpagesize */
-#define SOCKET_BUFFER_SIZE (getpagesize() < 8192L ? getpagesize() : 8192L)
-#endif	/* defined(HASEPTOPTS) && defined(HASUXSOCKEPT) */
-
-#if	defined(HASSOSTATE)
-#include <linux/net.h>			/* for SS_* */
-#endif  /* defined(HASSOSTATE) */
-
-/*
- * Local definitions
- */
-
-#define	INOBUCKS	128		/* inode hash bucket count -- must be
-					 * a power of two */
-#define INOHASH(ino)	((int)((ino * 31415) >> 3) & (INOBUCKS - 1))
-#define TCPUDPHASH(ino)	((int)((ino * 31415) >> 3) & (TcpUdp_bucks - 1))
-#define TCPUDP6HASH(ino) ((int)((ino * 31415) >> 3) & (TcpUdp6_bucks - 1))
-
-#define IPCBUCKS 128			/* IPC hash bucket count -- must be
-					 * a power of two */
-
-/* If a socket is used for IPC, we store both end points for the socket
- * to the same hash backet. This makes seaching the counter part of
- * an end point easier. See get_netpeeri(). */
-#define TCPUDP_IPC_HASH(tp) ((int)(((((tp)->faddr			\
-				      + (tp)->laddr,			\
-				      + (tp)->fport			\
-				      + (tp)->lport			\
-				      + (tp)->proto) * 31415) >> 3)	\
-				   & (IPCBUCKS - 1)))
-
-#define TCPUDP6_IPC_ADDR_INT32(a, n) (((a)->s6_addr32[n]))
-#define TCPUDP6_IPC_ADDR_MK_INT(a)		\
-	((int)TCPUDP6_IPC_ADDR_INT32(a, 0x0)    \
-	+(int)TCPUDP6_IPC_ADDR_INT32(a, 0x1)	\
-	+(int)TCPUDP6_IPC_ADDR_INT32(a, 0x2)	\
-	+(int)TCPUDP6_IPC_ADDR_INT32(a, 0x3))
-
-#define TCPUDP6_IPC_HASH(tp) ((int)((((TCPUDP6_IPC_ADDR_MK_INT(&(tp)->faddr) \
-				       + TCPUDP6_IPC_ADDR_MK_INT(&(tp)->laddr), \
-				       + (tp)->fport			\
-				       + (tp)->lport			\
-				       + (tp)->proto) * 31415) >> 3)	\
-				   & (IPCBUCKS - 1)))
-
-/*
- * Local structures
- */
-
-struct ax25sin {			/* AX25 socket information */
-	char *da;			/* destination address */
-	char *dev_ch;			/* device characters */
-	char *sa;			/* source address */
-	INODETYPE inode;
-	unsigned long sq, rq;		/* send and receive queue values */
-	unsigned char sqs, rqs;		/* send and receive queue states */
-	int state;
-	struct ax25sin *next;
-};
-
-struct icmpin {
-	INODETYPE inode;		/* node number */
-	char *la;			/* local address */
-	char *ra;			/* remote address */
-	MALLOC_S lal;			/* strlen(la) */
-	MALLOC_S ral;			/* strlen(ra) */
-	struct icmpin *next;
-};
-
-struct ipxsin {				/* IPX socket information */
-	INODETYPE inode;
-	char *la;			/* local address */
-	char *ra;			/* remote address */
-	int state;
-	unsigned long txq, rxq;		/* transmit and receive queue values */
-	struct ipxsin *next;
-};
-
-struct nlksin {				/* Netlink socket information */
-	INODETYPE inode;		/* node number */
-	unsigned int pr;		/* protocol */
-	struct nlksin *next;
-};
-
-struct packin {				/* packet information */
-	INODETYPE inode;
-	int ty;				/* socket type */
-	int pr;				/* protocol */
-	struct packin *next;
-};
-
-struct rawsin {				/* raw socket information */
-	INODETYPE inode;
-	char *la;			/* local address */
-	char *ra;			/* remote address */
-	char *sp;			/* state characters */
-	MALLOC_S lal;			/* strlen(la) */
-	MALLOC_S ral;			/* strlen(ra) */
-	MALLOC_S spl;			/* strlen(sp) */
-	struct rawsin *next;
-};
-
-struct sctpsin {			/* SCTP socket information */
-	INODETYPE inode;
-	int type;			/* type: 0 = assoc
-					 *	 1 = eps
-					 *	 2  assoc and eps */
-	char *addr;			/* association or endpoint address */
-	char *assocID;			/* association ID */
-	char *lport;			/* local port */
-	char *rport;			/* remote port */
-	char *laddrs;			/* local address */
-	char *raddrs;			/* remote address */
-	struct sctpsin *next;
-};
-
-struct tcp_udp {			/* IPv4 TCP and UDP socket
-					 * information */
-	INODETYPE inode;
-	unsigned long faddr, laddr;	/* foreign & local IPv4 addresses */
-	int fport, lport;		/* foreign & local ports */
-	unsigned long txq, rxq;		/* transmit & receive queue values */
-	int proto;			/* 0 = TCP, 1 = UDP, 2 = UDPLITE */
-	int state;			/* protocol state */
-	struct tcp_udp *next;		/* in TcpUdp inode hash table */
-#if	defined(HASEPTOPTS)
-	pxinfo_t *pxinfo;		/* inode information */
-	struct tcp_udp *ipc_next;	/* in TcpUdp local ipc hash table */
-	struct tcp_udp *ipc_peer;	/* locally connected peer(s) info */
-#endif	/* defined(HASEPTOPTS) */
-};
-
-#if	defined(HASIPv6)
-struct tcp_udp6 {			/* IPv6 TCP and UDP socket
-					 * information */
-	INODETYPE inode;
-	struct in6_addr faddr, laddr;	/* foreign & local IPv6 addresses */
-	int fport, lport;		/* foreign & local ports */
-	unsigned long txq, rxq;		/* transmit & receive queue values */
-	int proto;			/* 0 = TCP, 1 = UDP, 2 = UDPLITE */
-	int state;			/* protocol state */
-	struct tcp_udp6 *next;
-#if	defined(HASEPTOPTS)
-	pxinfo_t *pxinfo;		/* inode information */
-	struct tcp_udp6 *ipc_next;	/* in TcpUdp6 local ipc hash table */
-	struct tcp_udp6 *ipc_peer;	/* locally connected peer(s) info */
-#endif	/* defined(HASEPTOPTS) */
-};
-#endif	/* defined(HASIPv6) */
-
-typedef struct uxsin {			/* UNIX socket information */
-	INODETYPE inode;		/* node number */
-	char *pcb;			/* protocol control block */
-	char *path;			/* file path */
-	unsigned char sb_def;		/* stat(2) buffer definitions */
-	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 */
-	unsigned int opt;		/* socket options */
-	unsigned int ss;		/* socket state */
-
-#  if	defined(HASEPTOPTS) && defined(HASUXSOCKEPT)
-	struct uxsin *icons;		/* incoming socket conections */
-	unsigned int icstat;		/* incoming connection status
-					 * 0 == none */
-	pxinfo_t *pxinfo;		/* inode information */
-	struct uxsin *peer;	        /* connected peer(s) info */
-#  endif	/* defined(HASEPTOPTS) && defined(HASUXSOCKEPT) */
-
-	struct uxsin *next;
-} uxsin_t;
-
-/*
- * Local static values
- */
-
-static char *AX25path = (char *)NULL;	/* path to AX25 /proc information */
-static struct ax25sin **AX25sin = (struct ax25sin **)NULL;
-					/* AX25 socket info, hashed by inode */
-static char *ax25st[] = {
-	"LISTENING",			/* 0 */
-	"SABM SENT",			/* 1 */
-	"DISC SENT",			/* 2 */
-	"ESTABLISHED",			/* 3 */
-	"RECOVERY"			/* 4 */
-};
-#define NAX25ST	(sizeof(ax25st) / sizeof(char *))
-static char *ICMPpath = (char *)NULL;	/* path to ICMP /proc information */
-static struct icmpin **Icmpin = (struct icmpin **)NULL;
-					/* ICMP socket info, hashed by inode */
-static char *Ipxpath = (char *)NULL;	/* path to IPX /proc information */
-static struct ipxsin **Ipxsin = (struct ipxsin **)NULL;
-					/* IPX socket info, hashed by inode */
-static char *Nlkpath = (char *)NULL;	/* path to Netlink /proc information */
-static struct nlksin **Nlksin = (struct nlksin **)NULL;
-					/* Netlink socket info, hashed by
-					 * inode */
-static struct packin **Packin = (struct packin **)NULL;
-					/* packet info, hashed by inode */
-static char *Packpath = (char *)NULL;	/* path to packet /proc information */
-static char *Rawpath = (char *)NULL;	/* path to raw socket /proc
-					 * information */
-static struct rawsin **Rawsin = (struct rawsin **)NULL;
-					/* raw socket info, hashed by inode */
-static char *SCTPPath[] = {		/* paths to /proc/net STCP info */
-	(char *)NULL,			/* 0 = /proc/net/sctp/assocs */
-	(char *)NULL			/* 1 = /proc/net/sctp/eps */
-};
-#define	NSCTPPATHS sizeof(SCTPPath)/sizeof(char *)
-static char *SCTPSfx[] = {		/* /proc/net suffixes */
-	"sctp/assocs",			/* 0 = /proc/net/sctp/assocs */
-	"sctp/eps"			/* 1 = /proc/net/sctp/eps */
-};
-static struct sctpsin **SCTPsin = (struct sctpsin **)NULL;
-					/* SCTP info, hashed by inode */
-static char *SockStatPath = (char *)NULL;
-					/* path to /proc/net socket status */
-static char *TCPpath = (char *)NULL;	/* path to TCP /proc information */
-static struct tcp_udp **TcpUdp = (struct tcp_udp **)NULL;
-					/* IPv4 TCP & UDP info, hashed by
-					 * inode */
-static int TcpUdp_bucks = 0;		/* dynamically sized hash bucket
-					 * count for TCP and UDP -- will
-					 * be a power of two */
-#if	defined(HASEPTOPTS)
-static struct tcp_udp **TcpUdpIPC = (struct tcp_udp **)NULL;
-					/* IPv4 TCP & UDP info for socket used
-					   for IPC, hashed by (addr, port paris
-					   and protocol */
-#endif	/* defined(HASEPTOPTS) */
-
-#if	defined(HASIPv6)
-static char *Raw6path = (char *)NULL;	/* path to raw IPv6 /proc information */
-static struct rawsin **Rawsin6 = (struct rawsin **)NULL;
-					/* IPv6 raw socket info, hashed by
-					 * inode */
-static char *SockStatPath6 = (char *)NULL;
-					/* path to /proc/net IPv6 socket
-					 * status */
-static char *TCP6path = (char *)NULL;	/* path to IPv6 TCP /proc information */
-static struct tcp_udp6 **TcpUdp6 = (struct tcp_udp6 **)NULL;
-					/* IPv6 TCP & UDP info, hashed by
-					 * inode */
-static int TcpUdp6_bucks = 0;		/* dynamically sized hash bucket
-					 * count for IPv6 TCP and UDP -- will
-					 * be a power of two */
-static char *UDP6path = (char *)NULL;	/* path to IPv6 UDP /proc information */
-static char *UDPLITE6path = (char *)NULL;
-					/* path to IPv6 UDPLITE /proc
-					 * information */
-#if	defined(HASEPTOPTS)
-static struct tcp_udp6 **TcpUdp6IPC = (struct tcp_udp6 **)NULL;
-					/* IPv4 TCP & UDP info for socket used
-					   for IPC, hashed by (addr, port paris
-					   and protocol */
-#endif	/* defined(HASEPTOPTS) */
-#endif	/* defined(HASIPv6) */
-
-static char *UDPpath = (char *)NULL;	/* path to UDP /proc information */
-static char *UDPLITEpath = (char *)NULL;
-					/* path to UDPLITE /proc information */
-static char *UNIXpath = (char *)NULL;	/* path to UNIX /proc information */
-static uxsin_t **Uxsin = (uxsin_t **)NULL;
-					/* UNIX socket info, hashed by inode */
-
-
-/*
- * Local function prototypes
- */
-
-_PROTOTYPE(static struct ax25sin *check_ax25,(INODETYPE i));
-
-#if	defined(HASEPTOPTS) && defined(HASUXSOCKEPT)
-_PROTOTYPE(static void enter_uxsinfo,(uxsin_t *up));
-_PROTOTYPE(static void fill_uxicino,(INODETYPE si, INODETYPE sc));
-_PROTOTYPE(static void fill_uxpino,(INODETYPE si, INODETYPE pi));
-_PROTOTYPE(static int get_diagmsg,(int sockfd));
-_PROTOTYPE(static void get_uxpeeri,(void));
-_PROTOTYPE(static void parse_diag,(struct unix_diag_msg *dm, int len));
-_PROTOTYPE(static void prt_uxs,(uxsin_t *p, int mk));
-#endif	/* defined(HASEPTOPTS) && defined(HASUXSOCKEPT) */
-
-#if	defined(HASEPTOPTS)
-_PROTOTYPE(static void enter_netsinfo,(struct tcp_udp *tp));
-_PROTOTYPE(static void get_netpeeri,(void));
-#endif	/* defined(HASEPTOPTS) */
-
-#if	defined(HASIPv6)
-#if	defined(HASEPTOPTS)
-_PROTOTYPE(static void enter_nets6info,(struct tcp_udp6 *tp));
-_PROTOTYPE(static void get_net6peeri,(void));
-#endif	/* defined(HASEPTOPTS) */
-#endif	/* defined(HASIPv6) */
-
-_PROTOTYPE(static struct icmpin *check_icmp,(INODETYPE i));
-_PROTOTYPE(static struct ipxsin *check_ipx,(INODETYPE i));
-_PROTOTYPE(static struct nlksin *check_netlink,(INODETYPE i));
-_PROTOTYPE(static struct packin *check_pack,(INODETYPE i));
-_PROTOTYPE(static struct rawsin *check_raw,(INODETYPE i));
-_PROTOTYPE(static struct sctpsin *check_sctp,(INODETYPE i));
-_PROTOTYPE(static struct tcp_udp *check_tcpudp,(INODETYPE i, char **p));
-_PROTOTYPE(static uxsin_t *check_unix,(INODETYPE i));
-_PROTOTYPE(static void get_ax25,(char *p));
-_PROTOTYPE(static void get_icmp,(char *p));
-_PROTOTYPE(static void get_ipx,(char *p));
-_PROTOTYPE(static void get_netlink,(char *p));
-_PROTOTYPE(static void get_pack,(char *p));
-_PROTOTYPE(static void get_raw,(char *p));
-_PROTOTYPE(static void get_sctp,(void));
-_PROTOTYPE(static char *get_sctpaddrs,(char **fp, int i, int nf, int *x));
-_PROTOTYPE(static void get_tcpudp,(char *p, int pr, int clr));
-_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));
-_PROTOTYPE(static char *nlproto2str,(unsigned int pr));
-#if	defined(HASSOSTATE)
-_PROTOTYPE(static char *sockss2str,(unsigned int ss));
-#endif	/* defined(HASSOSTATE) */
-
-#if	defined(HASIPv6)
-_PROTOTYPE(static struct rawsin *check_raw6,(INODETYPE i));
-_PROTOTYPE(static struct tcp_udp6 *check_tcpudp6,(INODETYPE i, char **p));
-_PROTOTYPE(static void get_raw6,(char *p));
-_PROTOTYPE(static void get_tcpudp6,(char *p, int pr, int clr));
-_PROTOTYPE(static int net6a2in6,(char *as, struct in6_addr *ad));
-#endif	/* defined(HASIPv6) */
-
-
-/*
- * build_IPstates() -- build the TCP and UDP state tables
- */
-
-void
-build_IPstates()
-{
-	if (!TcpSt) {
-	    (void) enter_IPstate("TCP", "ESTABLISHED", TCP_ESTABLISHED);
-	    (void) enter_IPstate("TCP", "SYN_SENT", TCP_SYN_SENT);
-	    (void) enter_IPstate("TCP", "SYN_RECV", TCP_SYN_RECV);
-	    (void) enter_IPstate("TCP", "FIN_WAIT1", TCP_FIN_WAIT1);
-	    (void) enter_IPstate("TCP", "FIN_WAIT2", TCP_FIN_WAIT2);
-	    (void) enter_IPstate("TCP", "TIME_WAIT", TCP_TIME_WAIT);
-	    (void) enter_IPstate("TCP", "CLOSE", TCP_CLOSE);
-	    (void) enter_IPstate("TCP", "CLOSE_WAIT", TCP_CLOSE_WAIT);
-	    (void) enter_IPstate("TCP", "LAST_ACK", TCP_LAST_ACK);
-	    (void) enter_IPstate("TCP", "LISTEN", TCP_LISTEN);
-	    (void) enter_IPstate("TCP", "CLOSING", TCP_CLOSING);
-	    (void) enter_IPstate("TCP", "CLOSED", 0);
-	    (void) enter_IPstate("TCP", (char *)NULL, 0);
-	}
-}
-
-
-/*
- * check_ax25() - check for AX25 socket file
- */
-
-static struct ax25sin *
-check_ax25(i)
-	INODETYPE i;			/* socket file's inode number */
-{
-	struct ax25sin *ap;
-	int h;
-
-	h = INOHASH(i);
-	for (ap = AX25sin[h]; ap; ap = ap->next) {
-	    if (i == ap->inode)
-		return(ap);
-	}
-	return((struct ax25sin *)NULL);
-}
-
-
-
-/*
- * check_icmp() - check for ICMP socket
- */
-
-static struct icmpin *
-check_icmp(i)
-	INODETYPE i;			/* socket file's inode number */
-{
-	int h;
-	struct icmpin *icmpp;
-
-	h = INOHASH(i);
-	for (icmpp = Icmpin[h]; icmpp; icmpp = icmpp->next) {
-	    if (i == icmpp->inode)
-		return(icmpp);
-	}
-	return((struct icmpin *)NULL);
-}
-
-
-/*
- * check_ipx() - check for IPX socket file
- */
-
-static struct ipxsin *
-check_ipx(i)
-	INODETYPE i;			/* socket file's inode number */
-{
-	int h;
-	struct ipxsin *ip;
-
-	h = INOHASH(i);
-	for (ip = Ipxsin[h]; ip; ip = ip->next) {
-	    if (i == ip->inode)
-		return(ip);
-	}
-	return((struct ipxsin *)NULL);
-}
-
-
-/*
- * check_netlink() - check for Netlink socket file
- */
-
-static struct nlksin *
-check_netlink(i)
-	INODETYPE i;			/* socket file's inode number */
-{
-	int h;
-	struct nlksin *lp;
-
-	h = INOHASH(i);
-	for (lp = Nlksin[h]; lp; lp = lp->next) {
-	    if (i == lp->inode)
-		return(lp);
-	}
-	return((struct nlksin *)NULL);
-}
-
-
-/*
- * check_pack() - check for packet file
- */
-
-static struct packin *
-check_pack(i)
-	INODETYPE i;			/* packet file's inode number */
-{
-	int h;
-	struct packin *pp;
-
-	h = INOHASH(i);
-	for (pp = Packin[h]; pp; pp = pp->next) {
-	    if (i == pp->inode)
-		return(pp);
-	}
-	return((struct packin *)NULL);
-}
-
-
-/*
- * check_raw() - check for raw socket file
- */
-
-static struct rawsin *
-check_raw(i)
-	INODETYPE i;			/* socket file's inode number */
-{
-	int h;
-	struct rawsin *rp;
-
-	h = INOHASH(i);
-	for (rp = Rawsin[h]; rp; rp = rp->next) {
-	    if (i == rp->inode)
-		return(rp);
-	}
-	return((struct rawsin *)NULL);
-}
-
-
-/*
- * check_sctp() - check for SCTP socket file
- */
-
-static struct sctpsin *
-check_sctp(i)
-	INODETYPE i;			/* socket file's inode number */
-{
-	int h;
-	struct sctpsin *sp;
-
-	h = INOHASH(i);
-	for (sp = SCTPsin[h]; sp; sp = sp->next) {
-	    if (i == sp->inode)
-		return(sp);
-	}
-	return((struct sctpsin *)NULL);
-}
-
-
-/*
- * check_tcpudp() - check for IPv4 TCP or UDP socket file
- */
-
-static struct tcp_udp *
-check_tcpudp(i, p)
-	INODETYPE i;			/* socket file's inode number */
-	char **p;			/* protocol return */
-{
-	int h;
-	struct tcp_udp *tp;
-
-	h = TCPUDPHASH(i);
-	for (tp = TcpUdp[h]; tp; tp = tp->next) {
-	    if (i == tp->inode) {
-		switch (tp->proto) {
-		case 0:
-		    *p = "TCP";
-		    break;
-		case 1:
-		    *p = "UDP";
-		    break;
-		case 2:
-		    *p = "UDPLITE";
-		    break;
-		default:
-		   *p = "unknown";
-		}
-		return(tp);
-	    }
-	}
-	return((struct tcp_udp *)NULL);
-}
-
-/*
- * check_inet() - check for locally used INET domain socket
- */
-
-static struct tcp_udp *
-check_inet(i)
-	INODETYPE i;			/* socket file's inode number */
-{
-	int h;
-	struct tcp_udp *tp;
-
-	h = TCPUDPHASH(i);
-	for (tp = TcpUdp[h]; tp; tp = tp->next) {
-	    if (i == tp->inode)
-		return(tp);
-	}
-	return((struct tcp_udp *)NULL);
-}
-
-/*
- * clear_netsinfo -- clear allocated INET socket info
- */
-
-void
-clear_netsinfo()
-{
-	int h;				/* hash index */
-	struct tcp_udp *ti, *tp;	/* temporary pointers */
-
-#if	defined(HASEPTOPTS)
-	pxinfo_t *pp, *pnp;
-#endif	/* defined(HASEPTOPTS) */
-
-	if (TcpUdp) {
-	    for (h = 0; h < TcpUdp_bucks; h++) {
-		if ((ti = TcpUdp[h])) {
-		    do {
-			tp = ti->next;
-
-#if	defined(HASEPTOPTS)
-			for (pp = ti->pxinfo; pp; pp = pnp) {
-			    pnp = pp->next;
-			    (void) free((FREE_P *)pp);
-			}
-#endif	/* defined(HASEPTOPTS) */
-
-			(void) free((FREE_P *)ti);
-			ti = tp;
-		    } while (ti);
-		    TcpUdp[h] = (struct tcp_udp *)NULL;
-		}
-	    }
-	}
-	if (TcpUdpIPC) {
-	    for (h = 0; h < IPCBUCKS; h++)
-		TcpUdpIPC[h] = (struct tcp_udp *)NULL;
-	}
-}
-
-#if	defined(HASIPv6)
-/*
- * check_raw6() - check for raw IPv6 socket file
- */
-
-static struct rawsin *
-check_raw6(i)
-	INODETYPE i;			/* socket file's inode number */
-{
-	int h;
-	struct rawsin *rp;
-
-	h = INOHASH(i);
-	for (rp = Rawsin6[h]; rp; rp = rp->next) {
-	    if (i == rp->inode)
-		return(rp);
-	}
-	return((struct rawsin *)NULL);
-}
-
-
-/*
- * check_tcpudp6() - check for IPv6 TCP or UDP socket file
- */
-
-static struct tcp_udp6 *
-check_tcpudp6(i, p)
-	INODETYPE i;			/* socket file's inode number */
-	char **p;			/* protocol return */
-{
-	int h;
-	struct tcp_udp6 *tp6;
-
-	h = TCPUDP6HASH(i);
-	for (tp6 = TcpUdp6[h]; tp6; tp6 = tp6->next) {
-	    if (i == tp6->inode) {
-		switch (tp6->proto) {
-		case 0:
-		    *p = "TCP";
-		    break;
-		case 1:
-		    *p = "UDP";
-		    break;
-		case 2:
-		    *p = "UDPLITE";
-		    break;
-		default:
-		   *p = "unknown";
-		}
-		return(tp6);
-	    }
-	}
-	return((struct tcp_udp6 *)NULL);
-}
-
-/*
- * check_inet6() - check for locally used INET6 domain socket
- */
-
-static struct tcp_udp6 *
-check_inet6(i)
-	INODETYPE i;			/* socket file's inode number */
-{
-	int h;
-	struct tcp_udp6 *tp;
-
-	h = TCPUDP6HASH(i);
-	for (tp = TcpUdp6[h]; tp; tp = tp->next) {
-	    if (i == tp->inode)
-		return(tp);
-	}
-	return((struct tcp_udp6 *)NULL);
-}
-
-/*
- * clear_nets6info -- clear allocated INET6 socket info
- */
-
-void
-clear_nets6info()
-{
-	int h;				/* hash index */
-	struct tcp_udp6 *ti, *tp;	/* temporary pointers */
-
-#if	defined(HASEPTOPTS)
-	pxinfo_t *pp, *pnp;
-#endif	/* defined(HASEPTOPTS) */
-
-	if (TcpUdp6) {
-	    for (h = 0; h < TcpUdp6_bucks; h++) {
-		if ((ti = TcpUdp6[h])) {
-		    do {
-			tp = ti->next;
-
-#if	defined(HASEPTOPTS)
-			for (pp = ti->pxinfo; pp; pp = pnp) {
-			    pnp = pp->next;
-			    (void) free((FREE_P *)pp);
-			}
-#endif	/* defined(HASEPTOPTS) */
-
-			(void) free((FREE_P *)ti);
-			ti = tp;
-		    } while (ti);
-		    TcpUdp6[h] = (struct tcp_udp6 *)NULL;
-		}
-	    }
-	}
-	if (TcpUdp6IPC) {
-	    for (h = 0; h < IPCBUCKS; h++)
-		TcpUdp6IPC[h] = (struct tcp_udp6 *)NULL;
-	}
-}
-
-#endif	/* defined(HASIPv6) */
-
-
-/*
- * check_unix() - check for UNIX domain socket
- */
-
-static uxsin_t *
-check_unix(i)
-	INODETYPE i;			/* socket file's inode number */
-{
-	int h;
-	uxsin_t *up;
-
-	if (!Uxsin)
-	    return NULL;
-
-	h = INOHASH(i);
-	for (up = Uxsin[h]; up; up = up->next) {
-	    if (i == up->inode)
-		return(up);
-	}
-	return((uxsin_t *)NULL);
-}
-
-
-/*
- * clear_uxsinfo -- clear allocated UNIX socket info
- */
-
-void
-clear_uxsinfo()
-{
-	int h;				/* hash index */
-	uxsin_t *ui, *up;		/* remporary pointers */
-
-#if	defined(HASEPTOPTS) && defined(HASUXSOCKEPT)
-	pxinfo_t *pp, *pnp;
-#endif	/* defined(HASEPTOPTS) && defined(HASUXSOCKEPT) */
-
-	if (!Uxsin)
-	    return;
-	for (h = 0; h < INOBUCKS; h++) {
-	    if ((ui = Uxsin[h])) {
-		do {
-		    up = ui->next;
-
-#if	defined(HASEPTOPTS) && defined(HASUXSOCKEPT)
-		    for (pp = ui->pxinfo; pp; pp = pnp) {
-		        pnp = pp->next;
-		        (void) free((FREE_P *)pp);
-		    }
-#endif	/* defined(HASEPTOPTS) && defined(HASUXSOCKEPT) */
-
-		    if (ui->path)
-			(void) free((FREE_P *)ui->path);
-		    if (ui->pcb)
-			(void) free((FREE_P *)ui->pcb);
-		    (void) free((FREE_P *)ui);
-		    ui = up;
-		} while (ui);
-		Uxsin[h] = (uxsin_t *)NULL;
-	    }
-	}
-}
-
-
-/*
- * get_ax25() - get /proc/net/ax25 info
- */
-
-static void
-get_ax25(p)
-	char *p;			/* /proc/net/ipx path */
-{
-	struct ax25sin *ap, *np;
-	FILE *as;
-	char buf[MAXPATHLEN], *da, *dev_ch, *ep, **fp, *sa;
-	int h, nf;
-	INODETYPE inode;
-	unsigned long rq, sq, state;
-	MALLOC_S len;
-	unsigned char rqs, sqs;
-	static char *vbuf = (char *)NULL;
-	static size_t vsz = (size_t)0;
-/*
- * Do second time cleanup or first time setup.
- */
-	if (AX25sin) {
-	    for (h = 0; h < INOBUCKS; h++) {
-		for (ap = AX25sin[h]; ap; ap = np) {
-		    np = ap->next;
-		    if (ap->da)
-			(void) free((FREE_P *)ap->da);
-		    if (ap->dev_ch)
-			(void) free((FREE_P *)ap->dev_ch);
-		    if (ap->sa)
-			(void) free((FREE_P *)ap->sa);
-		    (void) free((FREE_P *)ap);
-		}
-		AX25sin[h] = (struct ax25sin *)NULL;
-	    }
-	} else {
-	    AX25sin = (struct ax25sin **)calloc(INOBUCKS,
-					      sizeof(struct ax25sin *));
-	    if (!AX25sin) {
-		(void) fprintf(stderr,
-		    "%s: can't allocate %d AX25 hash pointer bytes\n",
-		    Pn, (int)(INOBUCKS * sizeof(struct ax25sin *)));
-		Error();
-	    }
-	}
-/*
- * Open the /proc/net/ax25 file, assign a page size buffer to the stream,
- * and read it.  Store AX25 socket info in the AX25sin[] hash buckets.
- */
-	if (!(as = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
-	    return;
-	while (fgets(buf, sizeof(buf) - 1, as)) {
-	    if ((nf = get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0)) < 24)
-		continue;
-	/*
-	 * /proc/net/ax25 has no title line, a very poor deficiency in its
-	 * implementation.
-	 *
-	 * The ax25_get_info() function in kern module .../net/ax25/af_ax25.c
-	 * says the format of the lines in the file is:
-	 *
-	 *     magic dev src_addr dest_addr,digi1,digi2,.. st vs vr va t1 t1 \
-	 *     t2  t2 t3 t3 idle idle n2 n2 rtt window paclen Snd-Q Rcv-Q \
-	 *     inode
-	 *
-	 * The code in this function is forced to assume that format is in
-	 * effect..
-	 */
-
-	/*
-	 * Assemble the inode number and see if it has already been recorded.
-	 * If it has, skip this line.
-	 */
-	    ep = (char *)NULL;
-	    if (!fp[23] || !*fp[23]
-	    ||  (inode = strtoull(fp[23], &ep, 0)) == ULONG_MAX
-	    ||  !ep || *ep)
-		continue;
-	    h = INOHASH((INODETYPE)inode);
-	    for (ap = AX25sin[h]; ap; ap = ap->next) {
-		if (inode == ap->inode)
-		    break;
-	    }
-	    if (ap)
-		continue;
-	/*
-	 * Assemble the send and receive queue values and the state.
-	 */
-	    rq = sq = (unsigned long)0;
-	    rqs = sqs = (unsigned char)0;
-	    ep = (char *)NULL;
-	    if (!fp[21] || !*fp[21]
-	    ||  (sq = strtoul(fp[21], &ep, 0)) == ULONG_MAX || !ep || *ep)
-		continue;
-	    sqs = (unsigned char)1;
-	    ep = (char *)NULL;
-	    if (!fp[22] || !*fp[22]
-	    ||  (rq = strtoul(fp[22], &ep, 0)) == ULONG_MAX || !ep || *ep)
-		continue;
-	    rqs = (unsigned char)1;
-	    ep = (char *)NULL;
-	    if (!fp[4] || !*fp[4]
-	    ||  (state = strtoul(fp[4], &ep, 0)) == ULONG_MAX || !ep || *ep)
-		continue;
-	/*
-	 * Allocate space for the destination address.
-	 */
-	    if (!fp[3] || !*fp[3])
-		da = (char *)NULL;
-	    else if ((len = strlen(fp[3]))) {
-		if (!(da = (char *)malloc(len + 1))) {
-		    (void) fprintf(stderr,
-		      "%s: can't allocate %d destination AX25 addr bytes: %s\n",
-		      Pn, (int)(len + 1), fp[3]);
-		    Error();
-		}
-		(void) snpf(da, len + 1, "%s", fp[3]);
-	    } else
-		da = (char *)NULL;
-	/*
-	 * Allocate space for the source address.
-	 */
-	    if (!fp[2] || !*fp[2])
-		sa = (char *)NULL;
-	    else if ((len = strlen(fp[2]))) {
-		if (!(sa = (char *)malloc(len + 1))) {
-		    (void) fprintf(stderr,
-			"%s: can't allocate %d source AX25 address bytes: %s\n",
-			Pn, (int)(len + 1), fp[2]);
-		    Error();
-		}
-		(void) snpf(sa, len + 1, "%s", fp[2]);
-	    } else
-		sa = (char *)NULL;
-	/*
-	 * Allocate space for the device characters.
-	 */
-	    if (!fp[1] || !*fp[1])
-		dev_ch = (char *)NULL;
-	    else if ((len = strlen(fp[1]))) {
-		if (!(dev_ch = (char *)malloc(len + 1))) {
-		    (void) fprintf(stderr,
-		      "%s: can't allocate %d destination AX25 dev bytes: %s\n",
-		      Pn, (int)(len + 1), fp[1]);
-		    Error();
-		}
-		(void) snpf(dev_ch, len + 1, "%s", fp[1]);
-	    } else
-		dev_ch = (char *)NULL;
-	/*
-	 * Allocate space for an ax25sin entry, fill it, and link it to its
-	 * hash bucket.
-	 */
-	    if (!(ap = (struct ax25sin *)malloc(sizeof(struct ax25sin)))) {
-		(void) fprintf(stderr,
-		    "%s: can't allocate %d byte ax25sin structure\n",
-		    Pn, (int)sizeof(struct ax25sin));
-		Error();
-	    }
-	    ap->da = da;
-	    ap->dev_ch = dev_ch;
-	    ap->inode = inode;
-	    ap->rq = rq;
-	    ap->rqs = rqs;
-	    ap->sa = sa;
-	    ap->sq = sq;
-	    ap->sqs = sqs;
-	    ap->state = (int)state;
-	    ap->next = AX25sin[h];
-	    AX25sin[h] = ap;
-	}
-	(void) fclose(as);
-}
-
-
-#if	defined(HASEPTOPTS) && defined(HASUXSOCKEPT)
-/*
- * enter_uxsinfo() -- enter unix socket info
- * 	entry	Lf = local file structure pointer
- * 		Lp = local process structure pointer
- */
-
-static void
-enter_uxsinfo (up)
-	uxsin_t *up;
-{
-	pxinfo_t *pi;			/* pxinfo_t structure pointer */
-	struct lfile *lf;		/* local file structure pointer */
-	struct lproc *lp;		/* local proc structure pointer */
-	pxinfo_t *np;			/* new pxinfo_t structure pointer */
-
-	for (pi = up->pxinfo; 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;
-	    }
-	}
-	if (!(np = (pxinfo_t *)malloc(sizeof(pxinfo_t)))) {
-	    (void) fprintf(stderr,
-		"%s: no space for pipeinfo in uxsinfo, PID %d\n",
-		Pn, Lp->pid);
-	    Error();
-	}
-	np->ino = Lf->inode;
-	np->lf = Lf;
-	np->lpx = Lp - Lproc;
-	np->next = up->pxinfo;
-	up->pxinfo = np;
-}
-
-
-/*
- * fill_uxicino() -- fill incoming connection inode number
- */
-
-static void
-fill_uxicino (si, ic)
-	INODETYPE si;			/* UNIX socket inode number */
-	INODETYPE ic;			/* incoming UNIX socket connection
-					 * inode number */
-{
-	uxsin_t *psi;			/* pointer to socket's information */
-	uxsin_t *pic;			/* pointer to incoming connection's
-					 * information */
-
-	if ((psi = check_unix(si))) {
-	    if (psi->icstat || psi->icons)
-		return;
-	    if ((pic = check_unix(ic))) {
-		psi->icstat = 1;
-		psi->icons = pic;
-	    }
-	}
-}
-
-
-/*
- * fill_uxpino() -- fill in UNIX socket's peer inode number
- */
-
-static void
-fill_uxpino(si, pi)
-	INODETYPE si;		/* UNIX socket inode number */
-	INODETYPE pi;		/* UNIX socket peer's inode number */
-{
-	uxsin_t *pp, *up;
-
-	if ((up = check_unix(si))) {
-	    if (!up->peer) {
-		if ((pp = check_unix(pi)))
-		    up->peer = pp;
-	    }
-	}
-}
-
-
-/*
- * find_uxepti(lf) -- find UNIX socket endpoint info
- */
-
-uxsin_t *
-find_uxepti(lf)
-	struct lfile *lf;		/* pipe's lfile */
-{
-	uxsin_t *up;
-
-	up = check_unix(lf->inode);
-	return(up ? up->peer: (uxsin_t *)NULL);
-}
-
-
-/*
- * get_diagmsg() -- get UNIX socket's diag message
- */
-
-static int
-get_diagmsg(sockfd)
-	int sockfd;			/* socket's file descriptor */
-{
-	struct msghdr msg;		/* message header */
-	struct nlmsghdr nlh;		/* header length */
-	struct unix_diag_req creq;	/* connection request */
-	struct sockaddr_nl sa;		/* netlink socket address */
-	struct iovec iov[2];		/* I/O vector */
-/*
- * Build and send message to socket's file descriptor, asking for its
- * diagnostic message.
- */
-	zeromem((char *)&msg, sizeof(msg));
-	zeromem((char *)&sa, sizeof(sa));
-	zeromem((char *)&nlh, sizeof(nlh));
-	zeromem((char *)&creq, sizeof(creq));
-	sa.nl_family = AF_NETLINK;
-	creq.sdiag_family = AF_UNIX;
-	creq.sdiag_protocol = 0;
-	memset((void *)&creq.udiag_states, -1, sizeof(creq.udiag_states));
-	creq.udiag_ino = (INODETYPE)0;
-	creq.udiag_show = UDIAG_SHOW_PEER|UDIAG_SHOW_ICONS;
-	nlh.nlmsg_len = NLMSG_LENGTH(sizeof(creq));
-	nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
-	nlh.nlmsg_type = SOCK_DIAG_BY_FAMILY;
-	iov[0].iov_base = (void *)&nlh;
-	iov[0].iov_len = sizeof(nlh);
-	iov[1].iov_base = (void *) &creq;
-	iov[1].iov_len = sizeof(creq);
-	msg.msg_name = (void *) &sa;
-	msg.msg_namelen = sizeof(sa);
-	msg.msg_iov = iov;
-	msg.msg_iovlen = 2;
-	return(sendmsg(sockfd, &msg, 0));
-}
-
-
-/*
- * get_uxpeeri() - get UNIX socket peer inode information
- */
-
-static void
-get_uxpeeri()
-{
-	struct unix_diag_msg *dm;	/* pointer to diag message */
-	struct nlmsghdr *hp;		/* netlink structure header pointer */
-	int nb = 0;			/* number of bytes */
-	int ns = 0;			/* netlink socket */
-	uint8_t rb[SOCKET_BUFFER_SIZE];	/* receive buffer */
-	int rl = 0;			/* route info length */
-/*
- * Get a netlink socket.
- */
-	if ((ns = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_SOCK_DIAG)) == -1) {
-	    (void) fprintf(stderr, "%s: netlink socket error: %s\n",
-		Pn, strerror(errno));
-	    Error();
-	}
-/*
- * Request peer information.
- */
-	if (get_diagmsg(ns) < 0) {
-	    (void) fprintf(stderr, "%s: netlink peer request error: %s\n",
-		Pn, strerror(errno));
-	    goto get_uxpeeri_exit;
-	}
-/*
- * Receive peer information.
- */
-	while (1) {
-	    if ((nb = recv(ns, rb, sizeof(rb), 0)) <= 0)
-		goto get_uxpeeri_exit;
-	    hp = (struct nlmsghdr *)rb;
-	    while (NLMSG_OK(hp, nb)) {
-		if (hp->nlmsg_type == NLMSG_DONE)
-		    goto get_uxpeeri_exit;
-		if (hp->nlmsg_type == NLMSG_ERROR) {
-		    (void) fprintf(stderr,
-			"%s: netlink UNIX socket msg peer info error\n", Pn);
-		    goto get_uxpeeri_exit;
-		}
-		dm = (struct unix_diag_msg *)NLMSG_DATA(hp);
-		rl = hp->nlmsg_len - NLMSG_LENGTH(sizeof(*dm));
-		parse_diag(dm, rl);
-		hp = NLMSG_NEXT(hp, nb);
-	    }
-	}
-
-get_uxpeeri_exit:
-
-	    (void) close(ns);
-}
-
-
-/*
- * parse_diag() -- parse UNIX diag message
- */
-
-static void
-parse_diag(dm, len)
-	struct unix_diag_msg *dm;	/* pointer to diag message */
-	int len;			/* message length */
-{
-	struct rtattr *rp;		/* route info pointer */
-	int i;				/* tmporary index */
-	int icct;			/* incoming connection count */
-	uint32_t *icp;			/* incoming connection pointer */
-	uint32_t inoc, inop;		/* inode numbers */
-
-	if (!dm || (dm->udiag_family != AF_UNIX) || !(inop = dm->udiag_ino)
-	||  (len <= 0)
-	) {
-	    return;
-	}
-	rp = (struct rtattr *)(dm + 1);
-/*
- * Process route information.
- */
-	while (RTA_OK(rp, len)) {
-	    switch (rp->rta_type) {
-	    case UNIX_DIAG_PEER:
-		if (len < 4) {
-		    (void) fprintf(stderr,
-			"%s: unix_diag: msg length (%d) < 4)\n", Pn, len);
-		    return;
-		}
-		if ((inoc = *(uint32_t *)RTA_DATA(rp))) {
-		    fill_uxpino((INODETYPE)inop, (INODETYPE)inoc);
-		    fill_uxpino((INODETYPE)inoc, (INODETYPE)inop);
-		}
-		break;
-	    case UNIX_DIAG_ICONS:
-		icct = RTA_PAYLOAD(rp),
-		icp = (uint32_t *)RTA_DATA(rp);
-
-		for (i = 0; i < icct; i += sizeof(uint32_t), icp++) {
-		    fill_uxicino((INODETYPE)inop, (INODETYPE)*icp);
-		}
-	    }
-	    rp = RTA_NEXT(rp, len);
-	}
-}
-
-
-/*
- * prt_uxs() -- print UNIX socket information
- */
-
-static void
-prt_uxs(p, mk)
-	uxsin_t *p;			/* peer info */
-	int mk;				/* 1 == mark for later processing */
-{
-	struct lproc *ep;		/* socket endpoint process */
-	struct lfile *ef;		/* socket endpoint file */
-	int i;				/* temporary index */
-	int len;			/* string length */
-	char nma[1024];			/* character buffer */
-	pxinfo_t *pp;			/* previous pipe info of socket */
-
-	(void) strcpy(nma, "->INO=");
-	len = (int)strlen(nma);
-	(void) snpf(&nma[len], sizeof(nma) - len - 1, InodeFmt_d, p->inode);
-	(void) add_nma(nma, strlen(nma));
-	for (pp = p->pxinfo; pp; pp = pp->next) {
-
-	/*
-	 * Add a linked socket's PID, command name 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 (mk && FeptE == 2) {
-
-	    /*
-	     * Endpoint files have been selected, so mark this
-	     * one for selection later.
-	     */
-		ef->chend = CHEND_UXS;
-		ep->ept |= EPT_UXS_END;
-	    }
-	}
-}
-
-
-/*
- * process_uxsinfo() -- process UNIX socket information, adding it to selected
- *			UNIX socket files and selecting UNIX socket end point
- *			files (if requested)
- */
-
-void
-process_uxsinfo(f)
-	int f;				/* function:
-					 *     0 == process selected socket
-					 *     1 == process socket end point
-					 */
-{
-	uxsin_t *p;			/* peer UNIX socket info pointer */
-	uxsin_t *tp;			/* temporary UNIX socket info pointer */
-
-	if (!FeptE)
-	    return;
-	for (Lf = Lp->file; Lf; Lf = Lf->next) {
-	    if (strcmp(Lf->type, "unix"))
-		continue;
-	    switch (f) {
-	    case 0:
-
-	    /*
-	     * Process already selected socket.
-	     */
-		if (is_file_sel(Lp, Lf)) {
-
-		/*
-		 * This file has been selected by some criterion other than its
-		 * being a socket.  Look up the socket's endpoints.
-		 */
-		    p = find_uxepti(Lf);
-		    if (p && p->inode)
-			prt_uxs(p, 1);
-		    if ((tp = check_unix(Lf->inode))) {
-			if (tp->icons) {
-			    if (tp->icstat) {
-				p = tp->icons;
-				while (p && p != tp) {
-				    if (p->inode)
-					prt_uxs(p, 1);
-				    p = p->icons;
-				}
-			    } else {
-				for (p = tp->icons; p && !p->icstat; p = p->icons)
-				    ; /* DO NOTHING */
-				if (p && p->inode)
-				    prt_uxs (p, 1);
-			    }
-			}
-		    }
-		}
-		break;
-	    case 1:
-		if (!is_file_sel(Lp, Lf) && (Lf->chend & CHEND_UXS)) {
-
-		/*
-		 * This is an unselected end point UNIX socket file.  Select it
-		 * and add its end point information to peer's name column
-		 * addition.
-		 */
-		    Lf->sf = Selflags;
-		    Lp->pss |= PS_SEC;
-		    p = find_uxepti(Lf);
-		    if (p && p->inode)
-			prt_uxs(p, 0);
-		    else if ((tp = check_unix(Lf->inode))) {
-			if (tp->icons) {
-			    if (tp->icstat) {
-				p = tp->icons;
-				while (p && p != tp) {
-				    if (p->inode)
-					prt_uxs(p, 0);
-				    p = p->icons;
-				}
-			    } else {
-				for (p = tp->icons; p && !p->icstat; p = p->icons)
-				    ; /* DO NOTHING */
-				if (p && p->inode)
-				    prt_uxs(p, 0);
-			    }
-			}
-		    }
-		}
-		break;
-	    }
-	}
-}
-#endif	/* defined(HASEPTOPTS) && defined(HASUXSOCKEPT) */
-
-
-#if	defined(HASEPTOPTS)
-/*
- * enter_netsinfo_common() -- enter inet or inet6 socket info
- * 	tp = tcp/udp on ipv4 or ipv4 socket pointer
- */
-
-static void
-enter_netsinfo_common (void *tp,
-		       pxinfo_t * (* get_pxinfo) (void *),
-		       void (* set_pxinfo) (void *, pxinfo_t *))
-{
-	pxinfo_t *pi;			/* pxinfo_t structure pointer */
-	struct lfile *lf;		/* local file structure pointer */
-	struct lproc *lp;		/* local proc structure pointer */
-	pxinfo_t *np;			/* new pxinfo_t structure pointer */
-
-	for (pi = (* get_pxinfo) (tp); 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;
-	    }
-	}
-	if (!(np = (pxinfo_t *)malloc(sizeof(pxinfo_t)))) {
-	    (void) fprintf(stderr,
-			   "%s: no space for pipeinfo in netsinfo, PID %d\n",
-			   Pn, Lp->pid);
-	    Error();
-	}
-	np->ino = Lf->inode;
-	np->lf = Lf;
-	np->lpx = Lp - Lproc;
-	np->next = (* get_pxinfo)(tp);
-	(* set_pxinfo)(tp, np);
-}
-
-/*
- * prt_nets_common() -- print locally used INET or INET6 socket information
- */
-
-static void
-prt_nets_common(p, mk, get_pxinfo, chend, ept_flag)
-	void *p;			/* peer info */
-	int mk;				/* 1 == mark for later
-					 * processing */
-	pxinfo_t * (* get_pxinfo) (void *);
-	unsigned char chend;
-	short ept_flag;
-{
-	struct lproc *ep;		/* socket endpoint process */
-	struct lfile *ef;		/* socket endpoint file */
-	int i;				/* temporary index */
-	char nma[1024];			/* character buffer */
-	pxinfo_t *pp;			/* previous pipe info of socket */
-
-	for (pp = (* get_pxinfo)(p); pp; pp = pp->next) {
-
-	/*
-	 * Add a linked socket's PID, command name 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 (mk && FeptE == 2) {
-
-	    /*
-	     * Endpoint files have been selected, so mark this
-	     * one for selection later.
-	     */
-		ef->chend = chend;
-		ep->ept |= ept_flag;
-	    }
-	}
-}
-
-/*
- * enter_netsinfo() -- enter inet socket info
- * 	tp = tcp/udp on ipv4 socket pointer
- */
-
-static pxinfo_t *
-tcp_udp_get_pxinfo(void *vp)
-{
-	struct tcp_udp *tp = vp;
-	return tp->pxinfo;
-}
-
-static void
-tcp_udp_set_pxinfo(void *vp, pxinfo_t *np)
-{
-	struct tcp_udp *tp = vp;
-	tp->pxinfo = np;
-}
-
-static void
-enter_netsinfo (tp)
-	struct tcp_udp *tp;
-{
-	enter_netsinfo_common (tp,
-			       tcp_udp_get_pxinfo,
-			       tcp_udp_set_pxinfo);
-}
-
-/*
- * find_netsepti(lf) -- find locally used INET socket endpoint info
- */
-
-static struct tcp_udp *
-find_netsepti(lf)
-	struct lfile *lf;		/* socket's lfile */
-{
-	struct tcp_udp *tp;
-
-	tp = check_inet(lf->inode);
-	return(tp ? tp->ipc_peer: (struct tcp_udp *)NULL);
-}
-
-/*
- * get_netpeeri() - get INET socket peer inode information
- */
-
-static void
-get_netpeeri()
-{
-	int h;
-	struct tcp_udp *np, *tp;
-
-	for (h = 0; h < IPCBUCKS; h++) {
-	    for (tp = TcpUdpIPC[h]; tp; tp = tp->ipc_next) {
-		if (tp->ipc_peer)
-		    continue;
-		for (np = TcpUdpIPC[h]; np; np = np->ipc_next) {
-		    if (np->ipc_peer)
-			continue;
-		    if (tp->faddr == np->laddr &&
-			tp->laddr == np->faddr &&
-			tp->fport == np->lport &&
-			tp->lport == np->fport &&
-			tp->proto == np->proto) {
-			tp->ipc_peer = np;
-			np->ipc_peer = tp;
-			break;
-		    }
-		}
-	    }
-	}
-}
-
-/*
- * prt_nets() -- print locally used INET socket information
- */
-
-static void
-prt_nets(p, mk)
-	struct tcp_udp *p;		/* peer info */
-	int mk;				/* 1 == mark for later processing */
-{
-	prt_nets_common (p, mk, tcp_udp_get_pxinfo, CHEND_NETS, EPT_NETS_END);
-}
-
-/*
- * process_netsinfo() -- process locally used INET socket information, adding
- *			it to selected INET socket files and selecting INET
- *			socket end point files (if requested)
- */
-
-void
-process_netsinfo(f)
-	int f;				/* function:
-					 *     0 == process selected socket
-					 *     1 == process socket end point
-					 */
-{
-	struct tcp_udp *p;		/* peer INET socket info pointer */
-	struct tcp_udp*tp;		/* temporary INET socket info pointer */
-
-	if (!FeptE)
-	    return;
-	for (Lf = Lp->file; Lf; Lf = Lf->next) {
-	    if (strcmp(Lf->type,
-#if	defined(HASIPv6)
-		       "IPv4"
-#else	/* !defined(HASIPv6) */
-		       "inet"
-#endif	/* defined(HASIPv6) */
-		      ))
-		continue;
-	    switch (f) {
-	    case 0:
-
-	    /*
-	     * Process already selected socket.
-	     */
-		if (is_file_sel(Lp, Lf)) {
-
-		/*
-		 * This file has been selected by some criterion other than its
-		 * being a socket.  Look up the socket's endpoints.
-		 */
-		    p = find_netsepti(Lf);
-		    if (p && p->inode)
-			prt_nets(p, 1);
-		}
-		break;
-	    case 1:
-		if (!is_file_sel(Lp, Lf) && (Lf->chend & CHEND_NETS)) {
-
-		/*
-		 * This is an unselected end point INET socket file.  Select it
-		 * and add its end point information to peer's name column
-		 * addition.
-		 */
-		    Lf->sf = Selflags;
-		    Lp->pss |= PS_SEC;
-		    p = find_netsepti(Lf);
-		    if (p && p->inode)
-			prt_nets(p, 0);
-		}
-		break;
-	    }
-	}
-}
-#endif
-    /* defined(HASEPTOPTS) */
-
-#if	defined(HASIPv6)
-#if	defined(HASEPTOPTS)
-/*
- * enter_nets6info() -- enter inet socket info
- * 	tp = tcp/udp on ipv6 socket pointer
- */
-
-static pxinfo_t *
-tcp_udp6_get_pxinfo(void *vp)
-{
-	struct tcp_udp6 *tp = vp;
-	return tp->pxinfo;
-}
-
-static void
-tcp_udp6_set_pxinfo(void *vp, pxinfo_t *np)
-{
-	struct tcp_udp6 *tp = vp;
-	tp->pxinfo = np;
-}
-
-static void
-enter_nets6info (tp)
-	struct tcp_udp6 *tp;
-{
-	enter_netsinfo_common (tp,
-			       tcp_udp6_get_pxinfo,
-			       tcp_udp6_set_pxinfo);
-}
-
-/*
- * find_nets6epti(lf) -- find locally used INET6 socket endpoint info
- */
-
-static struct tcp_udp6 *
-find_nets6epti(lf)
-	struct lfile *lf;		/* socket's lfile */
-{
-	struct tcp_udp6 *tp;
-
-	tp = check_inet6(lf->inode);
-	return(tp ? tp->ipc_peer: (struct tcp_udp6 *)NULL);
-}
-
-/*
- * get_net6peeri() - get INET6 socket peer inode information
- */
-
-static void
-get_net6peeri()
-{
-	int h;
-	struct tcp_udp6 *np, *tp;
-
-	for (h = 0; h < IPCBUCKS; h++) {
-	    for (tp = TcpUdp6IPC[h]; tp; tp = tp->ipc_next) {
-		if (tp->ipc_peer)
-		    continue;
-		for (np = TcpUdp6IPC[h]; np; np = np->ipc_next) {
-		    if (np->ipc_peer)
-			continue;
-		    if (IN6_ARE_ADDR_EQUAL(&tp->faddr, &np->laddr) &&
-			IN6_ARE_ADDR_EQUAL(&tp->laddr, &np->faddr) &&
-			tp->fport == np->lport &&
-			tp->lport == np->fport &&
-			tp->proto == np->proto) {
-			tp->ipc_peer = np;
-			np->ipc_peer = tp;
-			break;
-		    }
-		}
-	    }
-	}
-}
-
-/*
- * prt_nets6() -- print locally used INET6 socket information
- */
-
-static void
-prt_nets6(p, mk)
-	struct tcp_udp6 *p;		/* peer info */
-	int mk;				/* 1 == mark for later processing */
-{
-	prt_nets_common (p, mk, tcp_udp6_get_pxinfo, CHEND_NETS6, EPT_NETS6_END);
-}
-
-/*
- * process_nets6info() -- process locally used INET6 socket information, adding
- *			it to selected INET6 socket files and selecting INET6
- *			socket end point files (if requested)
- */
-
-void
-process_nets6info(f)
-	int f;				/* function:
-					 *     0 == process selected socket
-					 *     1 == process socket end point
-					 */
-{
-	struct tcp_udp6 *p;		/* peer INET6 socket info pointer */
-	struct tcp_udp6*tp;		/* temporary INET6 socket info pointer */
-
-	if (!FeptE)
-	    return;
-	for (Lf = Lp->file; Lf; Lf = Lf->next) {
-	    if (strcmp(Lf->type, "IPv6"))
-		continue;
-	    switch (f) {
-	    case 0:
-
-	    /*
-	     * Process already selected socket.
-	     */
-		if (is_file_sel(Lp, Lf)) {
-		/*
-		 * This file has been selected by some criterion other than its
-		 * being a socket.  Look up the socket's endpoints.
-		 */
-		    p = find_nets6epti(Lf);
-		    if (p && p->inode)
-			prt_nets6(p, 1);
-		}
-		break;
-	    case 1:
-		if (!is_file_sel(Lp, Lf) && (Lf->chend & CHEND_NETS6)) {
-
-		/*
-		 * This is an unselected end point INET6 socket file.  Select it
-		 * and add its end point information to peer's name column
-		 * addition.
-		 */
-		    Lf->sf = Selflags;
-		    Lp->pss |= PS_SEC;
-		    p = find_nets6epti(Lf);
-		    if (p && p->inode)
-			prt_nets6(p, 0);
-		}
-		break;
-	    }
-	}
-}
-#endif	/* defined(HASEPTOPTS) */
-#endif	/* defined(HASIPv6) */
-
-/*
- * get_icmp() - get ICMP net info
- */
-
-static void
-get_icmp(p)
-	char *p;			/* /proc/net/icmp path */
-{
-	char buf[MAXPATHLEN], *ep, **fp, *la, *ra;
-	int fl = 1;
-	int h;
-	INODETYPE inode;
-	struct icmpin *np, *icmpp;
-	MALLOC_S lal, ral;
-	static char *vbuf = (char *)NULL;
-	static size_t vsz = (size_t)0;
-	FILE *xs;
-/*
- * Do second time cleanup or first time setup.
- */
-	if (Icmpin) {
-	    for (h = 0; h < INOBUCKS; h++) {
-		for (icmpp = Icmpin[h]; icmpp; icmpp = np) {
-		    np = icmpp->next;
-		    (void) free((FREE_P *)icmpp);
-		}
-		Icmpin[h] = (struct icmpin *)NULL;
-	    }
-	} else {
-	    Icmpin = (struct icmpin **)calloc(INOBUCKS,
-					      sizeof(struct icmpin *));
-	    if (!Icmpin) {
-		(void) fprintf(stderr,
-		    "%s: can't allocate %d icmp hash pointer bytes\n",
-		    Pn, (int)(INOBUCKS * sizeof(struct icmpin *)));
-		Error();
-	    }
-	}
-/*
- * Open the /proc/net/icmp file, assign a page size buffer to its stream,
- * and read the file.  Store icmp info in the Icmpin[] hash buckets.
- */
-	if (!(xs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
-	    return;
-	while (fgets(buf, sizeof(buf) - 1, xs)) {
-	    if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) < 11)
-		continue;
-	    if (fl) {
-
-	    /*
-	     * Check the column labels in the first line.
-	     *
-	     * NOTE:
-	     *       In column header, "inode" is at the 11th column.
-	     *       However, in data rows, inode appears at the 9th column.
-	     *
-	     *       In column header, "tx_queue" and "rx_queue" are separated
-	     *       by a space.  It is the same for "tr" and "tm->when"; in
-	     *       data rows they are connected with ":".
-	     */
-		if (!fp[1]  || strcmp(fp[1], "local_address")
-		||  !fp[2]  || strcmp(fp[2], "rem_address")
-		||  !fp[11] || strcmp(fp[11], "inode"))
-		{
-		    if (!Fwarn) {
-			(void) fprintf(stderr,
-			    "%s: WARNING: unsupported format: %s\n",
-			    Pn, p);
-		    }
-		    break;
-		}
-		fl = 0;
-		continue;
-	    }
-	/*
-	 * Assemble the inode number and see if the inode is already
-	 * recorded.
-	 */
-	    ep = (char *)NULL;
-	    if (!fp[9] || !*fp[9]
-	    ||  (inode = strtoull(fp[9], &ep, 0)) == ULONG_MAX
-	    ||  !ep || *ep)
-		continue;
-	    h = INOHASH(inode);
-	    for (icmpp = Icmpin[h]; icmpp; icmpp = icmpp->next) {
-		if (inode == icmpp->inode)
-		    break;
-	    }
-	    if (icmpp)
-		continue;
-	/*
-	 * Save the local address, and remote address.
-	 */
-	    if (!fp[1] || !*fp[1] || (lal = strlen(fp[1])) < 1) {
-		la = (char *)NULL;
-		lal = (MALLOC_S)0;
-	    } else {
-		if (!(la = (char *)malloc(lal + 1))) {
-		    (void) fprintf(stderr,
-			"%s: can't allocate %d local icmp address bytes: %s\n",
-			Pn, (int)(lal + 1), fp[1]);
-		    Error();
-		}
-		(void) snpf(la, lal + 1, "%s", fp[1]);
-	    }
-	    if (!fp[2] || !*fp[2] || (ral = strlen(fp[2])) < 1) {
-		ra = (char *)NULL;
-		ral = (MALLOC_S)0;
-	    } else {
-		if (!(ra = (char *)malloc(ral + 1))) {
-		    (void) fprintf(stderr,
-			"%s: can't allocate %d remote icmp address bytes: %s\n",
-			Pn, (int)(ral + 1), fp[2]);
-		    Error();
-		}
-		(void) snpf(ra, ral + 1, "%s", fp[2]);
-	    }
-	/*
-	 * Allocate space for a icmpin entry, fill it, and link it to its
-	 * hash bucket.
-	 */
-	    if (!(icmpp = (struct icmpin *)malloc(sizeof(struct icmpin)))) {
-		(void) fprintf(stderr,
-		    "%s: can't allocate %d byte icmp structure\n",
-		    Pn, (int)sizeof(struct icmpin));
-		Error();
-	    }
-	    icmpp->inode = inode;
-	    icmpp->la = la;
-	    icmpp->lal = lal;
-	    icmpp->ra = ra;
-	    icmpp->ral = ral;
-	    icmpp->next = Icmpin[h];
-	    Icmpin[h] = icmpp;
-	}
-	(void) fclose(xs);
-}
-
-
-
-/*
- * get_ipx() - get /proc/net/ipx info
- */
-
-static void
-get_ipx(p)
-	char *p;			/* /proc/net/ipx path */
-{
-	char buf[MAXPATHLEN], *ep, **fp, *la, *ra;
-	int fl = 1;
-	int h;
-	INODETYPE inode;
-	unsigned long rxq, state, txq;
-	struct ipxsin *ip, *np;
-	MALLOC_S len;
-	static char *vbuf = (char *)NULL;
-	static size_t vsz = (size_t)0;
-	FILE *xs;
-/*
- * Do second time cleanup or first time setup.
- */
-	if (Ipxsin) {
-	    for (h = 0; h < INOBUCKS; h++) {
-		for (ip = Ipxsin[h]; ip; ip = np) {
-		    np = ip->next;
-		    if (ip->la)
-			(void) free((FREE_P *)ip->la);
-		    if (ip->ra)
-			(void) free((FREE_P *)ip->ra);
-		    (void) free((FREE_P *)ip);
-		}
-		Ipxsin[h] = (struct ipxsin *)NULL;
-	    }
-	} else {
-	    Ipxsin = (struct ipxsin **)calloc(INOBUCKS,
-					      sizeof(struct ipxsin *));
-	    if (!Ipxsin) {
-		(void) fprintf(stderr,
-		    "%s: can't allocate %d IPX hash pointer bytes\n",
-		    Pn, (int)(INOBUCKS * sizeof(struct ipxsin *)));
-		Error();
-	    }
-	}
-/*
- * Open the /proc/net/ipx file, assign a page size buffer to the stream,
- * and read it.  Store IPX socket info in the Ipxsin[] hash buckets.
- */
-	if (!(xs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
-	    return;
-	while (fgets(buf, sizeof(buf) - 1, xs)) {
-	    if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) < 7)
-		continue;
-	    if (fl) {
-
-	    /*
-	     * Check the column labels in the first line.
-	     */
-		if (!fp[0] || strcmp(fp[0], "Local_Address")
-		||  !fp[1] || strcmp(fp[1], "Remote_Address")
-		||  !fp[2] || strcmp(fp[2], "Tx_Queue")
-		||  !fp[3] || strcmp(fp[3], "Rx_Queue")
-		||  !fp[4] || strcmp(fp[4], "State")
-		||  !fp[5] || strcmp(fp[5], "Uid")
-		||  !fp[6] || strcmp(fp[6], "Inode"))
-		{
-		    if (!Fwarn) {
-			(void) fprintf(stderr,
-			    "%s: WARNING: unsupported format: %s\n",
-			    Pn, p);
-		    }
-		    break;
-		}
-		fl = 0;
-		continue;
-	    }
-	/*
-	 * Assemble the inode number and see if the inode is already
-	 * recorded.
-	 */
-	    ep = (char *)NULL;
-	    if (!fp[6] || !*fp[6]
-	    ||  (inode = strtoull(fp[6], &ep, 0)) == ULONG_MAX
-	    ||  !ep || *ep)
-		continue;
-	    h = INOHASH(inode);
-	    for (ip = Ipxsin[h]; ip; ip = ip->next) {
-		if (inode == ip->inode)
-		    break;
-	    }
-	    if (ip)
-		continue;
-	/*
-	 * Assemble the transmit and receive queue values and the state.
-	 */
-	    ep = (char *)NULL;
-	    if (!fp[2] || !*fp[2]
-	    ||  (txq = strtoul(fp[2], &ep, 16)) == ULONG_MAX || !ep || *ep)
-		continue;
-	    ep = (char *)NULL;
-	    if (!fp[3] || !*fp[3]
-	    ||  (rxq = strtoul(fp[3], &ep, 16)) == ULONG_MAX || !ep || *ep)
-		continue;
-	    ep = (char *)NULL;
-	    if (!fp[4] || !*fp[4]
-	    ||  (state = strtoul(fp[4], &ep, 16)) == ULONG_MAX || !ep || *ep)
-		continue;
-	/*
-	 * Allocate space for the local address, unless it is "Not_Connected".
-	 */
-	    if (!fp[0] || !*fp[0] || strcmp(fp[0], "Not_Connected") == 0)
-		la = (char *)NULL;
-	    else if ((len = strlen(fp[0]))) {
-		if (!(la = (char *)malloc(len + 1))) {
-		    (void) fprintf(stderr,
-			"%s: can't allocate %d local IPX address bytes: %s\n",
-			Pn, (int)(len + 1), fp[0]);
-		    Error();
-		}
-		(void) snpf(la, len + 1, "%s", fp[0]);
-	    } else
-		la = (char *)NULL;
-	/*
-	 * Allocate space for the remote address, unless it is "Not_Connected".
-	 */
-	    if (!fp[1] || !*fp[1] || strcmp(fp[1], "Not_Connected") == 0)
-		ra = (char *)NULL;
-	    else if ((len = strlen(fp[1]))) {
-		if (!(ra = (char *)malloc(len + 1))) {
-		    (void) fprintf(stderr,
-			"%s: can't allocate %d remote IPX address bytes: %s\n",
-			Pn, (int)(len + 1), fp[1]);
-		    Error();
-		}
-		(void) snpf(ra, len + 1, "%s", fp[1]);
-	    } else
-		ra = (char *)NULL;
-	/*
-	 * Allocate space for an ipxsin entry, fill it, and link it to its
-	 * hash bucket.
-	 */
-	    if (!(ip = (struct ipxsin *)malloc(sizeof(struct ipxsin)))) {
-		(void) fprintf(stderr,
-		    "%s: can't allocate %d byte ipxsin structure\n",
-		    Pn, (int)sizeof(struct ipxsin));
-		Error();
-	    }
-	    ip->inode = inode;
-	    ip->la = la;
-	    ip->ra = ra;
-	    ip->txq = txq;
-	    ip->rxq = rxq;
-	    ip->state = (int)state;
-	    ip->next = Ipxsin[h];
-	    Ipxsin[h] = ip;
-	}
-	(void) fclose(xs);
-}
-
-
-/*
- * get_netlink() - get /proc/net/netlink info
- */
-
-static void
-get_netlink(p)
-	char *p;			/* /proc/net/netlink path */
-{
-	char buf[MAXPATHLEN], *ep, **fp;
-	int fr = 1;
-	int h, pr;
-	INODETYPE inode;
-	struct nlksin *np, *lp;
-	static char *vbuf = (char *)NULL;
-	static size_t vsz = (size_t)0;
-	FILE *xs;
-/*
- * Do second time cleanup or first time setup.
- */
-	if (Nlksin) {
-	    for (h = 0; h < INOBUCKS; h++) {
-		for (lp = Nlksin[h]; lp; lp = np) {
-		    np = lp->next;
-		    (void) free((FREE_P *)lp);
-		}
-		Nlksin[h] = (struct nlksin *)NULL;
-	    }
-	} else {
-	    Nlksin = (struct nlksin **)calloc(INOBUCKS,sizeof(struct nlksin *));
-	    if (!Nlksin) {
-		(void) fprintf(stderr,
-		    "%s: can't allocate %d netlink hash pointer bytes\n",
-		    Pn, (int)(INOBUCKS * sizeof(struct nlksin *)));
-		Error();
-	    }
-	}
-/*
- * Open the /proc/net/netlink file, assign a page size buffer to its stream,
- * and read the file.  Store Netlink info in the Nlksin[] hash buckets.
- */
-	if (!(xs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
-	    return;
-	while (fgets(buf, sizeof(buf) - 1, xs)) {
-	    if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) < 10)
-		continue;
-	    if (fr) {
-
-	    /*
-	     * Check the column labels in the first line.
-	     */
-		if (!fp[1] || strcmp(fp[1], "Eth")
-		||  !fp[9] || strcmp(fp[9], "Inode"))
-		{
-		    if (!Fwarn) {
-			(void) fprintf(stderr,
-			    "%s: WARNING: unsupported format: %s\n",
-			    Pn, p);
-		    }
-		    break;
-		}
-		fr = 0;
-		continue;
-	    }
-	/*
-	 * Assemble the inode number and see if the inode is already
-	 * recorded.
-	 */
-	    ep = (char *)NULL;
-	    if (!fp[9] || !*fp[9]
-	    ||  (inode = strtoull(fp[9], &ep, 0)) == ULONG_MAX
-	    ||  !ep || *ep)
-		continue;
-	    h = INOHASH(inode);
-	    for (lp = Nlksin[h]; lp; lp = lp->next) {
-		if (inode == lp->inode)
-		    break;
-	    }
-	    if (lp)
-		continue;
-	/*
-	 * Save the protocol from the Eth column.
-	 */
-	    if (!fp[1] || !*fp[1] || (strlen(fp[1])) < 1)
-		continue;
-	    pr = atoi(fp[1]);
-	/*
-	 * Allocate space for a nlksin entry, fill it, and link it to its
-	 * hash bucket.
-	 */
-	    if (!(lp = (struct nlksin *)malloc(sizeof(struct nlksin)))) {
-		(void) fprintf(stderr,
-		    "%s: can't allocate %d byte Netlink structure\n",
-		    Pn, (int)sizeof(struct nlksin));
-		Error();
-	    }
-	    lp->inode = inode;
-	    lp->pr = pr;
-	    lp->next = Nlksin[h];
-	    Nlksin[h] = lp;
-	}
-	(void) fclose(xs);
-}
-
-
-/*
- * get_pack() - get /proc/net/packet info
- */
-
-static void
-get_pack(p)
-	char *p;			/* /proc/net/raw path */
-{
-	char buf[MAXPATHLEN], *ep, **fp;
-	int fl = 1;
-	int h, ty;
-	INODETYPE inode;
-	struct packin *np, *pp;
-	unsigned long pr;
-	static char *vbuf = (char *)NULL;
-	static size_t vsz = (size_t)0;
-	FILE *xs;
-/*
- * Do second time cleanup or first time setup.
- */
-	if (Packin) {
-	    for (h = 0; h < INOBUCKS; h++) {
-		for (pp = Packin[h]; pp; pp = np) {
-		    np = pp->next;
-		    (void) free((FREE_P *)pp);
-		}
-		Packin[h] = (struct packin *)NULL;
-	    }
-	} else {
-	    Packin = (struct packin **)calloc(INOBUCKS,
-					      sizeof(struct packin *));
-	    if (!Packin) {
-		(void) fprintf(stderr,
-		    "%s: can't allocate %d packet hash pointer bytes\n",
-		    Pn, (int)(INOBUCKS * sizeof(struct packin *)));
-		Error();
-	    }
-	}
-/*
- * Open the /proc/net/packet file, assign a page size buffer to its stream,
- * and read the file.  Store packet info in the Packin[] hash buckets.
- */
-	if (!(xs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
-	    return;
-	while (fgets(buf, sizeof(buf) - 1, xs)) {
-	    if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) < 9)
-		continue;
-	    if (fl) {
-
-	    /*
-	     * Check the column labels in the first line.
-	     */
-		if (!fp[2]  || strcmp(fp[2], "Type")
-		||  !fp[3]  || strcmp(fp[3], "Proto")
-		||  !fp[8] || strcmp(fp[8], "Inode"))
-		{
-		    if (!Fwarn) {
-			(void) fprintf(stderr,
-			    "%s: WARNING: unsupported format: %s\n",
-			    Pn, p);
-		    }
-		    break;
-		}
-		fl = 0;
-		continue;
-	    }
-	/*
-	 * Assemble the inode number and see if the inode is already
-	 * recorded.
-	 */
-	    ep = (char *)NULL;
-	    if (!fp[8] || !*fp[8]
-	    ||  (inode = strtoull(fp[8], &ep, 0)) == ULONG_MAX
-	    ||  !ep || *ep)
-		continue;
-	    h = INOHASH(inode);
-	    for (pp = Packin[h]; pp; pp = pp->next) {
-		if (inode == pp->inode)
-		    break;
-	    }
-	    if (pp)
-		continue;
-	/*
-	 * Save the socket type and protocol.
-	 */
-	    if (!fp[2] || !*fp[2] || (strlen(fp[2])) < 1)
-		continue;
-	    ty = atoi(fp[2]);
-	    ep = (char *)NULL;
-	    if (!fp[3] || !*fp[3] || (strlen(fp[3]) < 1)
-	    ||  ((pr = strtoul(fp[3], &ep, 16)) == ULONG_MAX) || !ep || *ep)
-		continue;
-	/*
-	 * Allocate space for a packin entry, fill it, and link it to its
-	 * hash bucket.
-	 */
-	    if (!(pp = (struct packin *)malloc(sizeof(struct packin)))) {
-		(void) fprintf(stderr,
-		    "%s: can't allocate %d byte packet structure\n",
-		    Pn, (int)sizeof(struct packin));
-		Error();
-	    }
-	    pp->inode = inode;
-	    pp->pr = (int)pr;
-	    pp->ty = ty;
-	    pp->next = Packin[h];
-	    Packin[h] = pp;
-	}
-	(void) fclose(xs);
-}
-
-
-/*
- * get_raw() - get /proc/net/raw info
- */
-
-static void
-get_raw(p)
-	char *p;			/* /proc/net/raw path */
-{
-	char buf[MAXPATHLEN], *ep, **fp, *la, *ra, *sp;
-	int h;
-	INODETYPE inode;
-	int nf = 12;
-	struct rawsin *np, *rp;
-	MALLOC_S lal, ral, spl;
-	static char *vbuf = (char *)NULL;
-	static size_t vsz = (size_t)0;
-	FILE *xs;
-/*
- * Do second time cleanup or first time setup.
- */
-	if (Rawsin) {
-	    for (h = 0; h < INOBUCKS; h++) {
-		for (rp = Rawsin[h]; rp; rp = np) {
-		    np = rp->next;
-		    if (rp->la)
-			(void) free((FREE_P *)rp->la);
-		    if (rp->ra)
-			(void) free((FREE_P *)rp->ra);
-		    (void) free((FREE_P *)rp);
-		}
-		Rawsin[h] = (struct rawsin *)NULL;
-	    }
-	} else {
-	    Rawsin = (struct rawsin **)calloc(INOBUCKS,
-					      sizeof(struct rawsin *));
-	    if (!Rawsin) {
-		(void) fprintf(stderr,
-		    "%s: can't allocate %d raw hash pointer bytes\n",
-		    Pn, (int)(INOBUCKS * sizeof(struct rawsin *)));
-		Error();
-	    }
-	}
-/*
- * Open the /proc/net/raw file, assign a page size buffer to its stream,
- * and read the file.  Store raw socket info in the Rawsin[] hash buckets.
- */
-	if (!(xs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
-	    return;
-	while (fgets(buf, sizeof(buf) - 1, xs)) {
-	    if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) < nf)
-		continue;
-	    if (nf == 12) {
-
-	    /*
-	     * Check the column labels in the first line.
-	     */
-		if (!fp[1]  || strcmp(fp[1],  "local_address")
-		||  !fp[2]  || strcmp(fp[2],  "rem_address")
-		||  !fp[3]  || strcmp(fp[3],  "st")
-		||  !fp[11] || strcmp(fp[11], "inode"))
-		{
-		    if (!Fwarn) {
-			(void) fprintf(stderr,
-			    "%s: WARNING: unsupported format: %s\n",
-			    Pn, p);
-		    }
-		    break;
-		}
-		nf = 10;
-		continue;
-	    }
-	/*
-	 * Assemble the inode number and see if the inode is already
-	 * recorded.
-	 */
-	    ep = (char *)NULL;
-	    if (!fp[9] || !*fp[9]
-	    ||  (inode = strtoull(fp[9], &ep, 0)) == ULONG_MAX
-	    ||  !ep || *ep)
-		continue;
-	    h = INOHASH(inode);
-	    for (rp = Rawsin[h]; rp; rp = rp->next) {
-		if (inode == rp->inode)
-		    break;
-	    }
-	    if (rp)
-		continue;
-	/*
-	 * Save the local address, remote address, and state.
-	 */
-	    if (!fp[1] || !*fp[1] || (lal = strlen(fp[1])) < 1) {
-		la = (char *)NULL;
-		lal = (MALLOC_S)0;
-	    } else {
-		if (!(la = (char *)malloc(lal + 1))) {
-		    (void) fprintf(stderr,
-			"%s: can't allocate %d local raw address bytes: %s\n",
-			Pn, (int)(lal + 1), fp[1]);
-		    Error();
-		}
-		(void) snpf(la, lal + 1, "%s", fp[1]);
-	    }
-	    if (!fp[2] || !*fp[2] || (ral = strlen(fp[2])) < 1) {
-		ra = (char *)NULL;
-		ral = (MALLOC_S)0;
-	    } else {
-		if (!(ra = (char *)malloc(ral + 1))) {
-		    (void) fprintf(stderr,
-			"%s: can't allocate %d remote raw address bytes: %s\n",
-			Pn, (int)(ral + 1), fp[2]);
-		    Error();
-		}
-		(void) snpf(ra, ral + 1, "%s", fp[2]);
-	    }
-	    if (!fp[3] || !*fp[3] || (spl = strlen(fp[3])) < 1) {
-		sp = (char *)NULL;
-		spl = (MALLOC_S)0;
-	    } else {
-		if (!(sp = (char *)malloc(spl + 1))) {
-		    (void) fprintf(stderr,
-			"%s: can't allocate %d remote raw state bytes: %s\n",
-			Pn, (int)(spl + 1), fp[2]);
-		    Error();
-		}
-		(void) snpf(sp, spl + 1, "%s", fp[3]);
-	    }
-	/*
-	 * Allocate space for an rawsin entry, fill it, and link it to its
-	 * hash bucket.
-	 */
-	    if (!(rp = (struct rawsin *)malloc(sizeof(struct rawsin)))) {
-		(void) fprintf(stderr,
-		    "%s: can't allocate %d byte rawsin structure\n",
-		    Pn, (int)sizeof(struct rawsin));
-		Error();
-	    }
-	    rp->inode = inode;
-	    rp->la = la;
-	    rp->lal = lal;
-	    rp->ra = ra;
-	    rp->ral = ral;
-	    rp->sp = sp;
-	    rp->spl = spl;
-	    rp->next = Rawsin[h];
-	    Rawsin[h] = rp;
-	}
-	(void) fclose(xs);
-}
-
-
-/*
- * get_sctp() - get /proc/net/sctp/assocs info
- */
-
-static void
-get_sctp()
-{
-	char buf[MAXPATHLEN], *a, *ep, **fp, *id, *la, *lp, *ra, *rp, *ta;
-	int d, err, fl, h, i, j, nf, ty, x;
-	INODETYPE inode;
-	MALLOC_S len, plen;
-	struct sctpsin *sp, *np;
-	FILE *ss;
-	static char *vbuf = (char *)NULL;
-	static size_t vsz = (size_t)0;
-/*
- * Do second time cleanup or first time setup.
- */
-	if (SCTPsin) {
-	    for (h = 0; h < INOBUCKS; h++) {
-		for (sp = SCTPsin[h]; sp; sp = np) {
-		    np = sp->next;
-		    if (sp->addr)
-			(void) free((FREE_P *)sp->addr);
-		    if (sp->assocID)
-			(void) free((FREE_P *)sp->assocID);
-		    if (sp->lport)
-			(void) free((FREE_P *)sp->lport);
-		    if (sp->rport)
-			(void) free((FREE_P *)sp->rport);
-		    if (sp->laddrs)
-			(void) free((FREE_P *)sp->laddrs);
-		    if (sp->raddrs)
-			(void) free((FREE_P *)sp->raddrs);
-		    (void) free((FREE_P *)sp);
-		}
-		SCTPsin[h] = (struct sctpsin *)NULL;
-	    }
-	} else {
-	    SCTPsin = (struct sctpsin **)calloc(INOBUCKS,
-					      sizeof(struct sctpsin *));
-	    if (!SCTPsin) {
-		(void) fprintf(stderr,
-		    "%s: can't allocate %d SCTP hash pointer bytes\n",
-		    Pn, (int)(INOBUCKS * sizeof(struct sctpsin *)));
-		Error();
-	    }
-	}
-/*
- * Open the /proc/net/sctp files, assign a page size buffer to the streams,
- * and read them.  Store SCTP socket info in the SCTPsin[] hash buckets.
- */
-	for (i = 0; i < NSCTPPATHS; i++ ) {
-	    if (!(ss = open_proc_stream(SCTPPath[i], "r", &vbuf, &vsz, 0)))
-		continue;
-	    fl = 1;
-	    while (fgets(buf, sizeof(buf) - 1, ss)) {
-		if ((nf = get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0))
-		<   (i ? 9 : 16)
-		) {
-		    continue;
-		}
-		if (fl) {
-
-		/*
-		 * Check the column labels in the first line.
-		 */
-		    err = 0;
-		    switch (i) {
-		    case 0:
-			if (!fp[0]  || strcmp(fp[0],  "ASSOC")
-			||  !fp[6]  || strcmp(fp[6],  "ASSOC-ID")
-			||  !fp[10] || strcmp(fp[10], "INODE")
-			||  !fp[11] || strcmp(fp[11], "LPORT")
-			||  !fp[12] || strcmp(fp[12], "RPORT")
-			||  !fp[13] || strcmp(fp[13], "LADDRS")
-			||  !fp[14] || strcmp(fp[14], "<->")
-			||  !fp[15] || strcmp(fp[15], "RADDRS")
-			) {
-			    err = 1;
-			}
-			break;
-		    case 1:
-			if (!fp[0]  || strcmp(fp[0],  "ENDPT")
-			||  !fp[5]  || strcmp(fp[5],  "LPORT")
-			||  !fp[7]  || strcmp(fp[7],  "INODE")
-			||  !fp[8]  || strcmp(fp[8],  "LADDRS")
-			) {
-			    err = 1;
-			}
-		    }
-		    if (err) {
-			if (!Fwarn)
-			    (void) fprintf(stderr,
-				"%s: WARNING: unsupported format: %s\n",
-				Pn, SCTPPath[i]);
-			break;
-		    }
-		    fl = 0;
-		    continue;
-		}
-	    /*
-	     * Assemble the inode number and see if it has already been
-	     * recorded.
-	     */
-		ep = (char *)NULL;
-		j = i ? 7 : 10;
-		if (!fp[j] || !*fp[j]
-		||  (inode = strtoull(fp[j], &ep, 0)) == ULONG_MAX
-		||  !ep || *ep)
-		    continue;
-		h = INOHASH((INODETYPE)inode);
-		for (sp = SCTPsin[h]; sp; sp = sp->next) {
-		    if (inode == sp->inode)
-			break;
-		}
-	    /*
-	     * Set the entry type.
-	     */
-		if (sp)
-		    ty = (sp->type == i) ? i : 3;
-		else
-		    ty = i;
-	    /*
-	     * Allocate space for this line's sctpsin members.
-	     *
-	     * The association or endpoint address is in the first field.
-	     */
-		a = sp ? sp->addr : (char *)NULL;
-		if (fp[0] && *fp[0] && (len = strlen(fp[0]))) {
-		    if (a) {
-			if (isainb(fp[0], a)) {
-			    plen = strlen(a);
-			    a = (char *)realloc((MALLOC_P *)a, plen + len + 2);
-			    d = 0;
-			} else
-			    d = 1;
-		    } else {
-			plen = (MALLOC_S)0;
-			a = (char *)malloc(len + 1);
-			d = 0;
-		    }
-		    if (!a) {
-			(void) fprintf(stderr,
-			  "%s: can't allocate %d SCTP ASSOC bytes: %s\n",
-			  Pn, (int)(len + 1), fp[0]);
-			Error();
-		    }
-		    if (!d) {
-			if (plen)
-			    (void) snpf((a + plen), len + 2, ",%s", fp[0]);
-			else
-			    (void) snpf(a, len + 1, "%s", fp[0]);
-		    }
-		}
-	    /*
-	     * The association ID is in the seventh field.
-	     */
-		id = sp ? sp->assocID : (char *)NULL;
-		if (!i && fp[6] && *fp[6] && (len = strlen(fp[6]))) {
-		    if (id) {
-			if (isainb(fp[6], id)) {
-			    plen = strlen(id);
-			    id = (char *)realloc((MALLOC_P *)id,plen+len+2);
-			    d = 0;
-			} else
-			    d = 1;
-		    } else {
-			plen = (MALLOC_S)0;
-			id = (char *)malloc(len + 1);
-			d = 0;
-		    }
-		    if (!id) {
-			(void) fprintf(stderr,
-			  "%s: can't allocate %d SCTP ASSOC-ID bytes: %s\n",
-			  Pn, (int)(len + 1), fp[6]);
-			Error();
-		    }
-		    if (!d) {
-			if (plen)
-			    (void) snpf((id + plen), len + 2, ",%s", fp[6]);
-			else
-			    (void) snpf(id, len + 1, "%s", fp[6]);
-		    }
-		}
-	    /*
-	     * The field number for the local port depends on the entry type.
-	     */
-		j = i ? 5 : 11;
-		lp = sp ? sp->lport : (char *)NULL;
-		if (fp[j] && *fp[j] && (len = strlen(fp[j]))) {
-		    if (lp) {
-			if (isainb(fp[j], lp)) {
-			    plen = strlen(lp);
-			    lp = (char *)realloc((MALLOC_P *)lp,plen+len+2);
-			    d = 0;
-			} else
-			    d = 1;
-		    } else {
-			plen = (MALLOC_S)0;
-			lp = (char *)malloc(len + 1);
-			d = 0;
-		    }
-		    if (!lp) {
-			(void) fprintf(stderr,
-			  "%s: can't allocate %d SCTP LPORT bytes: %s\n",
-			  Pn, (int)(len + 1), fp[j]);
-			Error();
-		    }
-		    if (!d) {
-			if (plen)
-			    (void) snpf((lp + plen), len + 2, ",%s", fp[j]);
-			else
-			    (void) snpf(lp, len + 1, "%s", fp[j]);
-		    }
-		}
-	    /*
-	     * The field number for the remote port depends on the entry type.
-	     */
-		rp = sp ? sp->rport : (char *)NULL;
-		if (!i && fp[12] && *fp[12] && (len = strlen(fp[12]))) {
-		    if (rp) {
-			if (isainb(fp[12], rp)) {
-			    plen = strlen(rp);
-			    rp = (char *)realloc((MALLOC_P *)rp,plen+len+2);
-			    d = 0;
-			} else
-			    d = 1;
-		    } else {
-			plen = (MALLOC_S)0;
-			rp = (char *)malloc(len + 1);
-			d = 0;
-		    }
-		    if (!rp) {
-			(void) fprintf(stderr,
-			  "%s: can't allocate %d SCTP RPORT bytes: %s\n",
-			  Pn, (int)(len + 1), fp[12]);
-			Error();
-		    }
-		    if (!d) {
-			if (plen)
-			    (void) snpf((rp + plen), len + 2, ",%s", fp[12]);
-			else
-			    (void) snpf(rp, len + 1, "%s", fp[12]);
-		    }
-		}
-	    /*
-	     * The local addresses begin in a field whose number depends on
-	     * the entry type.
-	     */
-		j = i ? 8 : 13;
-		la = sp ? sp->laddrs : (char *)NULL;
-		if (fp[j] && *fp[j] && (len = strlen(fp[j]))) {
-		    if (!(ta = get_sctpaddrs(fp, j, nf, &x))) {
-			(void) fprintf(stderr,
-			  "%s: can't allocate %d SCTP LADDRS bytes\n",
-			  Pn, (int)len);
-			Error();
-		    }
-		    if (la) {
-			if (isainb(ta, la)) {
-			    len = strlen(ta);
-			    plen = strlen(la);
-			    if (!(la=(char *)realloc((MALLOC_P *)la,plen+len+2))
-			    ) {
-				(void) fprintf(stderr,
-				  "%s: can't reallocate %d SCTP LADDRS bytes\n",
-				  Pn, (int)len);
-				Error();
-			    }
-			    (void) snpf(la + plen, len + 2, ",%s", ta);
-			    (void) free((FREE_P *)ta);
-			}
-		    } else
-			la = ta;
-		}
-	    /*
-	     * The remote addresses begin after the local addresses, but only
-	     * for the ASSOC type.
-	     */
-		ra = sp ? sp->raddrs : (char *)NULL;
-		if (!i && x && fp[x+1] && *fp[x+1] && (len = strlen(fp[x+1]))) {
-		    if (!(ta = get_sctpaddrs(fp, x + 1, nf, &x))) {
-			(void) fprintf(stderr,
-			  "%s: can't allocate %d SCTP RADDRS bytes\n",
-			  Pn, (int)len);
-			Error();
-		    }
-		    if (ra) {
-			if (isainb(ta, ra)) {
-			    len = strlen(ta);
-			    plen = strlen(ra);
-			    if (!(ra=(char *)realloc((MALLOC_P *)ra,plen+len+2))
-			    ) {
-				(void) fprintf(stderr,
-				  "%s: can't reallocate %d SCTP RADDRS bytes\n",
-				  Pn, (int)len);
-				Error();
-			    }
-			    (void) snpf(ra + plen, len + 2, ",%s", ta);
-			    (void) free((FREE_P *)ta);
-			}
-		    } else
-			ra = ta;
-		}
-	    /*
-	     * If no matching sctpsin entry was found for this inode, allocate
-	     * space for a new sctpsin entry, fill it, and link it to its hash
-	     * bucket.  Update a matching entry.
-	     */
-		if (!sp) {
-		    if (!(sp = (struct sctpsin *)malloc(sizeof(struct sctpsin)))		    ) {
-			(void) fprintf(stderr,
-			    "%s: can't allocate %d byte sctpsin structure\n",
-			    Pn, (int)sizeof(struct sctpsin));
-			Error();
-		    }
-		    sp->inode = inode;
-		    sp->next = SCTPsin[h];
-		    SCTPsin[h] = sp;
-		}
-		sp->addr = a;
-		sp->assocID = id;
-		sp->lport = lp;
-		sp->rport = rp;
-		sp->laddrs = la;
-		sp->raddrs = ra;
-		sp->type = ty;
-	    }
-	    (void) fclose(ss);
-	}
-}
-
-
-static char *
-get_sctpaddrs(fp, i, nf, x)
-	char **fp;			/* field pointers */
-	int i;				/* first address field index in fp */
-	int nf;				/* number of fields */
-	int *x;				/* index of first "<->" field entry */
-{
-	MALLOC_S al = (MALLOC_S)0;
-	char *cp = (char *)NULL;
-	MALLOC_S tl;
-
-	*x = 0;
-	do {
-	    if ((i >= nf) || !fp[i] || !*fp[i] || !(tl = strlen(fp[i])))
-		break;
-	    if (!strcmp(fp[i], "<->")) {
-		*x = i;
-		break;
-	    }
-	    if (!strchr(fp[i], (int)'.') && !strchr(fp[i], (int)':'))
-		break;
-	    if (cp)
-		cp = (char *)realloc((MALLOC_P *)cp, al + tl + 1);
-	    else
-		cp = (char *)malloc(al + tl + 1);
-	    if (!cp)
-		break;
-	    if (al)
-		*(cp + al - 1) = ',';
-	    (void) strncpy(al ? (cp + al) : cp, fp[i], tl);
-	    al += (tl + 1);
-	    *(cp + al - 1) = '\0';
-	} while (++i < nf);
-	return(cp);
-}
-
-
-/*
- * get_tcpudp() - get IPv4 TCP, UDP or UDPLITE net info
- */
-
-static void
-get_tcpudp(p, pr, clr)
-	char *p;			/* /proc/net/{tcp,udp} path */
-	int pr;				/* protocol: 0 = TCP, 1 = UDP,
-					 *           2 = UDPLITE */
-	int clr;			/* 1 == clear the table */
-{
-	char buf[MAXPATHLEN], *ep, **fp;
-	unsigned long faddr, fport, laddr, lport, rxq, state, txq;
-	FILE *fs;
-	int h, nf;
-	INODETYPE inode;
-	struct tcp_udp *np, *tp;
-	static char *vbuf = (char *)NULL;
-	static size_t vsz = (size_t)0;
-
-#if	defined(HASEPTOPTS)
-	pxinfo_t *pp, *pnp;
-#endif	/* defined(HASEPTOPTS) */
-
-/*
- * Delete previous table contents.
- */
-	if (TcpUdp) {
-	    if (clr) {
-		for (h = 0; h < TcpUdp_bucks; h++) {
-		    for (tp = TcpUdp[h]; tp; tp = np) {
-			np = tp->next;
-
-#if	defined(HASEPTOPTS)
-			for (pp = tp->pxinfo; pp; pp = pnp) {
-			    pnp = pp->next;
-			    (void) free((FREE_P *)pp);
-			}
-#endif	/* defined(HASEPTOPTS) */
-
-			(void) free((FREE_P *)tp);
-		    }
-		    TcpUdp[h] = (struct tcp_udp *)NULL;
-		}
-#if	defined(HASEPTOPTS)
-		if (FeptE)
-		    for (h = 0; h < IPCBUCKS; h++)
-			TcpUdpIPC[h] = (struct tcp_udp *)NULL;
-#endif	/* defined(HASEPTOPTS) */
-	    }
-/*
- * If no hash buckets have been allocated, do so now.
- */
-	} else {
-
-	/*
-	 * Open the /proc/net/sockstat file and establish the hash bucket
-	 * count from its "sockets: used" line.
-	 */
-	    TcpUdp_bucks = INOBUCKS;
-	    if ((fs = fopen(SockStatPath, "r"))) {
-		while (fgets(buf, sizeof(buf) - 1, fs)) {
-		    if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) != 3)
-			continue;
-		    if (!fp[0] || strcmp(fp[0], "sockets:")
-		    ||  !fp[1] || strcmp(fp[1], "used")
-		    ||  !fp[2] || !*fp[2])
-			continue;
-    		    if ((h = atoi(fp[2])) < 1)
-			h = INOBUCKS;
-		    while (TcpUdp_bucks < h)
-			TcpUdp_bucks *= 2;
-		    break;
-		}
-		(void) fclose(fs);
-	    }
-	    if (!(TcpUdp = (struct tcp_udp **)calloc(TcpUdp_bucks,
-						     sizeof(struct tcp_udp *))))
-	    {
-		(void) fprintf(stderr,
-		    "%s: can't allocate %d bytes for TCP&UDP hash buckets\n",
-		    Pn, (int)(TcpUdp_bucks * sizeof(struct tcp_udp *)));
-		Error();
-	    }
-#if	defined(HASEPTOPTS)
-	    if (FeptE && (!(TcpUdpIPC = (struct tcp_udp **)calloc(IPCBUCKS,
-								  sizeof(struct tcp_udp *))))) {
-		(void) fprintf(stderr,
-			       "%s: can't allocate %d bytes for TCP&UDP local IPC hash buckets\n",
-			       Pn, (int)(IPCBUCKS * sizeof(struct tcp_udp *)));
-		Error();
-	    }
-#endif	/* defined(HASEPTOPTS) */
-	}
-/*
- * Open the /proc/net file, assign a page size buffer to the stream, and
- * read it.
- */
-	if (!(fs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
-	    return;
-	nf = 12;
-	while (fgets(buf, sizeof(buf) - 1, fs)) {
-	    if (get_fields(buf,
-			   (nf == 12) ? (char *)NULL : ":",
-			   &fp, (int *)NULL, 0)
-	    < nf)
-		continue;
-	    if (nf == 12) {
-		if (!fp[1]  || strcmp(fp[1],  "local_address")
-		||  !fp[2]  || strcmp(fp[2],  "rem_address")
-		||  !fp[3]  || strcmp(fp[3],  "st")
-		||  !fp[4]  || strcmp(fp[4],  "tx_queue")
-		||  !fp[5]  || strcmp(fp[5],  "rx_queue")
-		||  !fp[11] || strcmp(fp[11], "inode"))
-		{
-		    if (!Fwarn) {
-			(void) fprintf(stderr,
-			    "%s: WARNING: unsupported format: %s\n",
-			    Pn, p);
-		    }
-		    break;
-		}
-		nf = 14;
-		continue;
-	    }
-	/*
-	 * Get the local and remote addresses.
-	 */
-	    ep = (char *)NULL;
-	    if (!fp[1] || !*fp[1]
-	    ||  (laddr = strtoul(fp[1], &ep, 16)) == ULONG_MAX || !ep || *ep)
-		continue;
-	    ep = (char *)NULL;
-	    if (!fp[2] || !*fp[2]
-	    ||  (lport = strtoul(fp[2], &ep, 16)) == ULONG_MAX || !ep || *ep)
-		continue;
-	    ep = (char *)NULL;
-	    if (!fp[3] || !*fp[3]
-	    ||  (faddr = strtoul(fp[3], &ep, 16)) == ULONG_MAX || !ep || *ep)
-		continue;
-	    ep = (char *)NULL;
-	    if (!fp[4] || !*fp[4]
-	    ||  (fport = strtoul(fp[4], &ep, 16)) == ULONG_MAX || !ep || *ep)
-		continue;
-	/*
-	 * Get the state and queue sizes.
-	 */
-	    ep = (char *)NULL;
-	    if (!fp[5] || !*fp[5]
-	    ||  (state = strtoul(fp[5], &ep, 16)) == ULONG_MAX || !ep || *ep)
-		continue;
-	    ep = (char *)NULL;
-	    if (!fp[6] || !*fp[6]
-	    ||  (txq = strtoul(fp[6], &ep, 16)) == ULONG_MAX || !ep || *ep)
-		continue;
-	    ep = (char *)NULL;
-	    if (!fp[7] || !*fp[7]
-	    ||  (rxq = strtoul(fp[7], &ep, 16)) == ULONG_MAX || !ep || *ep)
-		continue;
-	/*
-	 * Get the inode and use it for hashing and searching.
-	 */
-	    ep = (char *)NULL;
-	    if (!fp[13] || !*fp[13]
-	    ||  (inode = strtoull(fp[13], &ep, 0)) == ULONG_MAX || !ep || *ep)
-		continue;
-	    h = TCPUDPHASH(inode);
-	    for (tp = TcpUdp[h]; tp; tp = tp->next) {
-		if (tp->inode == inode)
-		    break;
-	    }
-	    if (tp)
-		continue;
-	/*
-	 * Create a new entry and link it to its hash bucket.
-	 */
-	    if (!(tp = (struct tcp_udp *)malloc(sizeof(struct tcp_udp)))) {
-		(void) fprintf(stderr,
-		    "%s: can't allocate %d bytes for tcp_udp struct\n",
-		    Pn, (int)sizeof(struct tcp_udp));
-		Error();
-	    }
-	    tp->inode = inode;
-	    tp->faddr = faddr;
-	    tp->fport = (int)(fport & 0xffff);
-	    tp->laddr = laddr;
-	    tp->lport = (int)(lport & 0xffff);
-	    tp->txq = txq;
-	    tp->rxq = rxq;
-	    tp->proto = pr;
-	    tp->state = (int)state;
-	    tp->next = TcpUdp[h];
-	    TcpUdp[h] = tp;
-#if	defined(HASEPTOPTS)
-	    tp->pxinfo = (pxinfo_t *)NULL;
-	    if (FeptE) {
-		tp->ipc_peer = (struct tcp_udp *)NULL;
-		if (tp->state == TCP_ESTABLISHED) {
-		    int i = TCPUDP_IPC_HASH(tp);
-		    tp->ipc_next = TcpUdpIPC[i];
-		    TcpUdpIPC[i] = tp;
-		}
-	    }
-#endif	/* defined(HASEPTOPTS) */
-	}
-
-#if	defined(HASEPTOPTS)
-/*
- * If endpoint info has been requested, link INET socket peer info.
- */
-	if (FeptE)
-	    get_netpeeri();
-#endif	/* defined(HASEPTOPTS) */
-
-	(void) fclose(fs);
-}
-
-
-#if	defined(HASIPv6)
-/*
- * get_raw6() - get /proc/net/raw6 info
- */
-
-static void
-get_raw6(p)
-	char *p;			/* /proc/net/raw path */
-{
-	char buf[MAXPATHLEN], *ep, **fp, *la, *ra, *sp;
-	int h;
-	INODETYPE inode;
-	int nf = 12;
-	struct rawsin *np, *rp;
-	MALLOC_S lal, ral, spl;
-	static char *vbuf = (char *)NULL;
-	static size_t vsz = (size_t)0;
-	FILE *xs;
-/*
- * Do second time cleanup or first time setup.
- */
-	if (Rawsin6) {
-	    for (h = 0; h < INOBUCKS; h++) {
-		for (rp = Rawsin6[h]; rp; rp = np) {
-		    np = rp->next;
-		    if (rp->la)
-			(void) free((FREE_P *)rp->la);
-		    if (rp->ra)
-			(void) free((FREE_P *)rp->ra);
-		    if (rp->sp)
-			(void) free((FREE_P *)rp->sp);
-		    (void) free((FREE_P *)rp);
-		}
-		Rawsin6[h] = (struct rawsin *)NULL;
-	    }
-	} else {
-	    Rawsin6 = (struct rawsin **)calloc(INOBUCKS,
-					       sizeof(struct rawsin *));
-	    if (!Rawsin6) {
-		(void) fprintf(stderr,
-		    "%s: can't allocate %d raw6 hash pointer bytes\n",
-		    Pn, (int)(INOBUCKS * sizeof(struct rawsin *)));
-		Error();
-	    }
-	}
-/*
- * Open the /proc/net/raw6 file, assign a page size buffer to the stream,
- * and read it.  Store raw6 socket info in the Rawsin6[] hash buckets.
- */
-	if (!(xs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
-	    return;
-	while (fgets(buf, sizeof(buf) - 1, xs)) {
-	    if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) < nf)
-		continue;
-	    if (nf == 12) {
-
-	    /*
-	     * Check the column labels in the first line.
-	     */
-		if (!fp[1]  || strcmp(fp[1],  "local_address")
-		||  !fp[2]  || strcmp(fp[2],  "remote_address")
-		||  !fp[3]  || strcmp(fp[3],  "st")
-		||  !fp[11] || strcmp(fp[11], "inode"))
-		{
-		    if (!Fwarn) {
-			(void) fprintf(stderr,
-			    "%s: WARNING: unsupported format: %s\n",
-			    Pn, p);
-		    }
-		    break;
-		}
-		nf = 10;
-		continue;
-	    }
-	/*
-	 * Assemble the inode number and see if the inode is already
-	 * recorded.
-	 */
-	    ep = (char *)NULL;
-	    if (!fp[9] || !*fp[9]
-	    ||  (inode = strtoull(fp[9], &ep, 0)) == ULONG_MAX
-	    ||  !ep || *ep)
-		continue;
-	    h = INOHASH(inode);
-	    for (rp = Rawsin6[h]; rp; rp = rp->next) {
-		if (inode == rp->inode)
-		    break;
-	    }
-	    if (rp)
-		continue;
-	/*
-	 * Save the local address, remote address, and state.
-	 */
-	    if (!fp[1] || !*fp[1] || (lal = strlen(fp[1])) < 1) {
-		la = (char *)NULL;
-		lal = (MALLOC_S)0;
-	    } else {
-		if (!(la = (char *)malloc(lal + 1))) {
-		    (void) fprintf(stderr,
-			"%s: can't allocate %d local raw6 address bytes: %s\n",
-			Pn, (int)(lal + 1), fp[1]);
-		    Error();
-		}
-		(void) snpf(la, lal + 1, "%s", fp[1]);
-	    }
-	    if (!fp[2] || !*fp[2] || (ral = strlen(fp[2])) < 1) {
-		ra = (char *)NULL;
-		ral = (MALLOC_S)0;
-	    } else {
-		if (!(ra = (char *)malloc(ral + 1))) {
-		    (void) fprintf(stderr,
-			"%s: can't allocate %d remote raw6 address bytes: %s\n",
-			Pn, (int)(ral + 1), fp[2]);
-		    Error();
-		}
-		(void) snpf(ra, ral + 1, "%s", fp[2]);
-	    }
-	    if (!fp[3] || !*fp[3] || (spl = strlen(fp[3])) < 1) {
-		sp = (char *)NULL;
-		spl = (MALLOC_S)0;
-	    } else {
-		if (!(sp = (char *)malloc(spl + 1))) {
-		    (void) fprintf(stderr,
-			"%s: can't allocate %d remote raw6 state bytes: %s\n",
-			Pn, (int)(spl + 1), fp[2]);
-		    Error();
-		}
-		(void) snpf(sp, spl + 1, "%s", fp[3]);
-	    }
-	/*
-	 * Allocate space for an rawsin entry, fill it, and link it to its
-	 * hash bucket.
-	 */
-	    if (!(rp = (struct rawsin *)malloc(sizeof(struct rawsin)))) {
-		(void) fprintf(stderr,
-		    "%s: can't allocate %d byte rawsin structure for IPv6\n",
-		    Pn, (int)sizeof(struct rawsin));
-		Error();
-	    }
-	    rp->inode = inode;
-	    rp->la = la;
-	    rp->lal = lal;
-	    rp->ra = ra;
-	    rp->ral = ral;
-	    rp->sp = sp;
-	    rp->spl = spl;
-	    rp->next = Rawsin6[h];
-	    Rawsin6[h] = rp;
-	}
-	(void) fclose(xs);
-}
-
-
-/*
- * get_tcpudp6() - get IPv6 TCP, UDP or UDPLITE net info
- */
-
-static void
-get_tcpudp6(p, pr, clr)
-	char *p;			/* /proc/net/{tcp,udp} path */
-	int pr;				/* protocol: 0 = TCP, 1 = UDP */
-	int clr;			/* 1 == clear the table */
-{
-	char buf[MAXPATHLEN], *ep, **fp;
-	struct in6_addr faddr, laddr;
-	unsigned long fport, lport, rxq, state, txq;
-	FILE *fs;
-	int h, i, nf;
-	INODETYPE inode;
-	struct tcp_udp6 *np6, *tp6;
-	static char *vbuf = (char *)NULL;
-	static size_t vsz = (size_t)0;
-
-#if	defined(HASEPTOPTS)
-	pxinfo_t *pp, *pnp;
-#endif	/* defined(HASEPTOPTS) */
-
-/*
- * Delete previous table contents.  Allocate a table for the first time.
- */
-	if (TcpUdp6) {
-	    if (clr) {
-		for (h = 0; h < TcpUdp6_bucks; h++) {
-		    for (tp6 = TcpUdp6[h]; tp6; tp6 = np6) {
-			np6 = tp6->next;
-
-#if	defined(HASEPTOPTS)
-			for (pp = tp6->pxinfo; pp; pp = pnp) {
-			    pnp = pp->next;
-			    (void) free((FREE_P *)pp);
-			}
-#endif	/* defined(HASEPTOPTS) */
-
-			(void) free((FREE_P *)tp6);
-		    }
-		    TcpUdp6[h] = (struct tcp_udp6 *)NULL;
-		}
-#if	defined(HASEPTOPTS)
-		if (FeptE)
-		    for (h = 0; h < IPCBUCKS; h++)
-			TcpUdp6IPC[h] = (struct tcp_udp6 *)NULL;
-#endif	/* defined(HASEPTOPTS) */
-	    }
-	} else {
-
-	/*
-	 * Open the /proc/net/sockstat6 file and establish the hash bucket
-	 * count from its "TCP6: inuse" and "UDP6: inuse" lines.
-	 */
-	    TcpUdp6_bucks = INOBUCKS;
-	    h = i = nf = 0;
-	    if ((fs = fopen(SockStatPath6, "r"))) {
-		while (fgets(buf, sizeof(buf) - 1, fs)) {
-		    if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) != 3)
-			continue;
-		    if (!fp[0]
-		    ||  !fp[1] || strcmp(fp[1], "inuse")
-		    ||  !fp[2] || !*fp[2])
-			continue;
-		    if (!strcmp(fp[0], "TCP6:")) {
-			nf |= 1;
-    			if ((h = atoi(fp[2])) < 1)
-			    h = INOBUCKS;
-			i += h;
-		    } else if (!strcmp(fp[0], "UDP6:")) {
-			nf |= 2;
-    			if ((h = atoi(fp[2])) < 1)
-			    h = INOBUCKS;
-			i += h;
-		    } else
-			continue;
-		    if (nf == 3) {
-			while (TcpUdp6_bucks < i)
-			    TcpUdp6_bucks *= 2;
-			break;
-		    }
-		}
-		(void) fclose(fs);
-	    }
-	    if (!(TcpUdp6 = (struct tcp_udp6 **)calloc(TcpUdp6_bucks,
-						sizeof(struct tcp_udp6 *))))
-	    {
-		(void) fprintf(stderr,
-		    "%s: can't allocate %d bytes for TCP6&UDP6 hash buckets\n",
-		    Pn, (int)(TcpUdp6_bucks * sizeof(struct tcp_udp6 *)));
-		Error();
-	    }
-#if	defined(HASEPTOPTS)
-	    if (FeptE && (!(TcpUdp6IPC = (struct tcp_udp6 **)calloc(IPCBUCKS,
-								    sizeof(struct tcp_udp6 *))))) {
-		(void) fprintf(stderr,
-			       "%s: can't allocate %d bytes for TCP6&UDP6 local IPC hash buckets\n",
-			       Pn, (int)(IPCBUCKS * sizeof(struct tcp_udp6 *)));
-		Error();
-	    }
-#endif	/* defined(HASEPTOPTS) */
-	}
-/*
- * Open the /proc/net file, assign a page size buffer to the stream,
- * and read it.
- */
-	if (!(fs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
-	    return;
-	nf = 12;
-	while (fgets(buf, sizeof(buf) - 1, fs)) {
-	    if (get_fields(buf,
-			   (nf == 12) ? (char *)NULL : ":",
-			   &fp, (int *)NULL, 0)
-	    < nf)
-		continue;
-	    if (nf == 12) {
-		if (!fp[1]  || strcmp(fp[1],  "local_address")
-		||  !fp[2]  || strcmp(fp[2],  "remote_address")
-		||  !fp[3]  || strcmp(fp[3],  "st")
-		||  !fp[4]  || strcmp(fp[4],  "tx_queue")
-		||  !fp[5]  || strcmp(fp[5],  "rx_queue")
-		||  !fp[11] || strcmp(fp[11], "inode"))
-		{
-		    if (!Fwarn) {
-			(void) fprintf(stderr,
-			    "%s: WARNING: unsupported format: %s\n",
-			    Pn, p);
-		    }
-		    break;
-		}
-		nf = 14;
-		continue;
-	    }
-	/*
-	 * Get the local and remote addresses.
-	 */
-	    if (!fp[1] || !*fp[1] || net6a2in6(fp[1], &laddr))
-		continue;
-	    ep = (char *)NULL;
-	    if (!fp[2] || !*fp[2]
-	    ||  (lport = strtoul(fp[2], &ep, 16)) == ULONG_MAX || !ep || *ep)
-		continue;
-	    if (!fp[3] || !*fp[3] || net6a2in6(fp[3], &faddr))
-		continue;
-	    ep = (char *)NULL;
-	    if (!fp[4] || !*fp[4]
-	    ||  (fport = strtoul(fp[4], &ep, 16)) == ULONG_MAX || !ep || *ep)
-		continue;
-	/*
-	 * Get the state and queue sizes.
-	 */
-	    ep = (char *)NULL;
-	    if (!fp[5] || !*fp[5]
-	    ||  (state = strtoul(fp[5], &ep, 16)) == ULONG_MAX || !ep || *ep)
-		continue;
-	    ep = (char *)NULL;
-	    if (!fp[6] || !*fp[6]
-	    ||  (txq = strtoul(fp[6], &ep, 16)) == ULONG_MAX || !ep || *ep)
-		continue;
-	    ep = (char *)NULL;
-	    if (!fp[7] || !*fp[7]
-	    ||  (rxq = strtoul(fp[7], &ep, 16)) == ULONG_MAX || !ep || *ep)
-		continue;
-	/*
-	 * Get the inode and use it for hashing and searching.
-	 */
-	    ep = (char *)NULL;
-	    if (!fp[13] || !*fp[13]
-	    ||  (inode = strtoull(fp[13], &ep, 0)) == ULONG_MAX || !ep || *ep)
-		continue;
-	    h = TCPUDP6HASH(inode);
-	    for (tp6 = TcpUdp6[h]; tp6; tp6 = tp6->next) {
-		if (tp6->inode == inode)
-		    break;
-	    }
-	    if (tp6)
-		continue;
-	/*
-	 * Create a new entry and link it to its hash bucket.
-	 */
-	    if (!(tp6 = (struct tcp_udp6 *)malloc(sizeof(struct tcp_udp6)))) {
-		(void) fprintf(stderr,
-		    "%s: can't allocate %d bytes for tcp_udp6 struct\n",
-		    Pn, (int)sizeof(struct tcp_udp6));
-		Error();
-	    }
-	    tp6->inode = inode;
-	    tp6->faddr = faddr;
-	    tp6->fport = (int)(fport & 0xffff);
-	    tp6->laddr = laddr;
-	    tp6->lport = (int)(lport & 0xffff);
-	    tp6->txq = txq;
-	    tp6->rxq = rxq;
-	    tp6->proto = pr;
-	    tp6->state = (int)state;
-	    tp6->next = TcpUdp6[h];
-	    TcpUdp6[h] = tp6;
-#if	defined(HASEPTOPTS)
-	    tp6->pxinfo = (pxinfo_t *)NULL;
-	    if (FeptE) {
-		tp6->ipc_peer = (struct tcp_udp6 *)NULL;
-		if (tp6->state == TCP_ESTABLISHED) {
-		    int i = TCPUDP6_IPC_HASH(tp6);
-		    tp6->ipc_next = TcpUdp6IPC[i];
-		    TcpUdp6IPC[i] = tp6;
-		}
-	    }
-#endif	/* defined(HASEPTOPTS) */
-	}
-#if	defined(HASEPTOPTS)
-/*
- * If endpoint info has been requested, link INET6 socket peer info.
- */
-	if (FeptE)
-	    get_net6peeri();
-#endif	/* defined(HASEPTOPTS) */
-
-	(void) fclose(fs);
-}
-#endif	/* defined(HASIPv6) */
-
-
-/*
- * get_unix() - get UNIX net info
- */
-
-static void
-get_unix(p)
-	char *p;			/* /proc/net/unix path */
-{
-	char buf[MAXPATHLEN], *ep, **fp, *path, *pcb;
-	int fl = 1;
-	int h, nf;
-	INODETYPE inode;
-	MALLOC_S len;
-	uxsin_t *np, *up;
-	FILE *us;
-	uint32_t ty;
-	static char *vbuf = (char *)NULL;
-	static size_t vsz = (size_t)0;
-
-#if	defined(HASEPTOPTS) && defined(HASUXSOCKEPT)
-	pxinfo_t *pp, *pnp;
-#endif	/* defined(HASEPTOPTS) && defined(HASUXSOCKEPT) */
-
-/*
- * Do second time cleanup or first time setup.
- */
-	if (Uxsin) {
-	    for (h = 0; h < INOBUCKS; h++) {
-		for (up = Uxsin[h]; up; up = np) {
-		    np = up->next;
-
-#if	defined(HASEPTOPTS) && defined(HASUXSOCKEPT)
-		    for (pp = up->pxinfo; pp; pp = pnp) {
-		        pnp = pp->next;
-		        (void) free((FREE_P *)pp);
-		    }
-#endif	/* defined(HASEPTOPTS) && defined(HASUXSOCKEPT) */
-
-		    if (up->path)
-			(void) free((FREE_P *)up->path);
-		    if (up->pcb)
-			(void) free((FREE_P *)up->pcb);
-		    (void) free((FREE_P *)up);
-		}
-		Uxsin[h] = (uxsin_t *)NULL;
-	    }
-	} else {
-	    Uxsin = (uxsin_t **)calloc(INOBUCKS, sizeof(uxsin_t *));
-	    if (!Uxsin) {
-		(void) fprintf(stderr,
-		    "%s: can't allocate %d bytes for Unix socket info\n",
-		    Pn, (int)(INOBUCKS * sizeof(uxsin_t *)));
-		Error();
-	    }
-	}
-/*
- * Open the /proc/net/unix file, assign a page size buffer to the stream,
- * read the file's contents, and add them to the Uxsin hash buckets.
- */
-	if (!(us = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
-	    return;
-	while (fgets(buf, sizeof(buf) - 1, us)) {
-	    if ((nf = get_fields(buf, ":", &fp, (int *)NULL, 0)) < 7)
-		continue;
-	    if (fl) {
-
-	    /*
-	     * Check the first line for header words.
-	     */
-		if (!fp[0] || strcmp(fp[0], "Num")
-		||  !fp[1] || strcmp(fp[1], "RefCount")
-		||  !fp[2] || strcmp(fp[2], "Protocol")
-		||  !fp[3] || strcmp(fp[3], "Flags")
-		||  !fp[4] || strcmp(fp[4], "Type")
-		||  !fp[5] || strcmp(fp[5], "St")
-		||  !fp[6] || strcmp(fp[6], "Inode")
-		||  nf < 8
-		||  !fp[7] || strcmp(fp[7], "Path"))
-		{
-		    if (!Fwarn) {
-			(void) fprintf(stderr,
-			    "%s: WARNING: unsupported format: %s\n",
-			    Pn, p);
-		    }
-		    break;
-		}
-		fl = 0;
-		continue;
-	    }
-	/*
-	 * Assemble PCB address, inode number, and path name.  If this
-	 * inode is already represented in Uxsin, skip it.
-	 */
-	    ep = (char *)NULL;
-	    if (!fp[6] || !*fp[6]
-	    ||  (inode = strtoull(fp[6], &ep, 0)) == ULONG_MAX || !ep || *ep)
-		continue;
-	    h = INOHASH(inode);
-	    for (up = Uxsin[h]; up; up = up->next) {
-		if (inode == up->inode)
-		    break;
-	    }
-	    if (up)
-		continue;
-	    if (!fp[0] || !*fp[0])
-		pcb = (char *)NULL;
-	    else {
-		len = strlen(fp[0]) + 2;
-		if (!(pcb = (char *)malloc(len + 1))) {
-		    (void) fprintf(stderr,
-			"%s: can't allocate %d bytes for UNIX PCB: %s\n",
-			Pn, (int)(len + 1), fp[0]);
-		    Error();
-		}
-		(void) snpf(pcb, len + 1, "0x%s", fp[0]);
-	    }
-	    if (nf >= 8 && fp[7] && *fp[7] && (len = strlen(fp[7]))) {
-		if (!(path = (char *)malloc(len + 1))) {
-		    (void) fprintf(stderr,
-			"%s: can't allocate %d bytes for UNIX path \"%s\"\n",
-			Pn, (int)(len + 1), fp[7]);
-		    Error();
-		}
-		(void) snpf(path, len + 1, "%s", fp[7]);
-	    } 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;
-	    }
-	/*
-	 * Record socket state.
-	 */
-	    unsigned long proc_flags = 0UL;
-	    ep = (char *)NULL;
-	    if (fp[3] && *fp[3]
-	    &&  (proc_flags = strtoul(fp[3], &ep, 16)) == ULONG_MAX)
-	        proc_flags = 0UL;
-
-	    unsigned long proc_st = 0UL;
-	    ep = (char *)NULL;
-	    if (fp[5] && *fp[5]
-	    &&  ((proc_st = strtoul(fp[5], &ep, 16)) == ULONG_MAX))
-	        proc_st = 0UL;
-
-	/*
-	 * Allocate and fill a Unix socket info structure; link it to its
-	 * hash bucket.
-	 */
-	    if (!(up = (uxsin_t *)malloc(sizeof(uxsin_t)))) {
-		(void) fprintf(stderr,
-		    "%s: can't allocate %d bytes for uxsin struct\n",
-		    Pn, (int)sizeof(uxsin_t));
-		Error();
-	    }
-	    up->inode = inode;
-	    up->next = (uxsin_t *)NULL;
-	    up->pcb = pcb;
-	    up->sb_def = 0;
-	    up->ty = ty;
-	    up->opt = (unsigned int)proc_flags;
-	    up->ss = (unsigned int)proc_st;
-	    if ((up->path = path) && (*path == '/')) {
-
-	    /*
-	     * If an absolute path (i.e., one that begins with a '/') exists
-	     * for the line, attempt to stat(2) it and save the device and
-	     * node numbers reported in the stat buffer.
-	     */
-		struct stat sb;
-		int sr;
-
-		if (HasNFS)
-		    sr = statsafely(path, &sb);
-		else
-		    sr = stat(path, &sb);
-		if (sr && ((sb.st_mode & S_IFMT) == S_IFSOCK)) {
-		    up->sb_def = 1;
-		    up->sb_dev = sb.st_dev;
-		    up->sb_ino = (INODETYPE)sb.st_ino;
-		    up->sb_rdev = sb.st_rdev;
-		}
-	    }
-
-#if	defined(HASEPTOPTS) && defined(HASUXSOCKEPT)
-	/*
-	 * Clean UNIX socket endpoint values.
-	 */
-	    up->icstat = 0;
-	    up->pxinfo = (pxinfo_t *)NULL;
-	    up->peer = up->icons = (uxsin_t *)NULL;
-#endif	/* defined(HASEPTOPTS) && defined(HASUXSOCKEPT) */
-
-	    up->next = Uxsin[h];
-	    Uxsin[h] = up;
-	}
-
-#if	defined(HASEPTOPTS) && defined(HASUXSOCKEPT)
-/*
- * If endpoint info has been requested, get UNIX socket peer info.
- */
-	if (FeptE)
-	    get_uxpeeri();
-#endif	/* defined(HASEPTOPTS) && defined(HASUXSOCKEPT) */
-
-	(void) fclose(us);
-}
-
-
-#if	defined(HASIPv6)
-/*
- * net6a2in6() - convert ASCII IPv6 address in /proc/net/{tcp,udp} form to
- *		 an in6_addr
- */
-
-static int
-net6a2in6(as, ad)
-	char *as;			/* address source */
-	struct in6_addr *ad;		/* address destination */
-{
-	char buf[9], *ep;
-	int i;
-	size_t len;
-/*
- * Assemble four uint32_t's from 4 X 8 hex digits into s6_addr32[].
- */
-	for (i = 0, len = strlen(as);
-	     (i < 4) && (len >= 8);
-	     as += 8, i++, len -= 8)
-	{
-	    (void) strncpy(buf, as, 8);
-	    buf[8] = '\0';
-	    ep = (char *)NULL;
-
-	    errno = 0;
-	    unsigned long ul_addr = strtoul(buf, &ep, 16);
-	    if (!ep || *ep)
-		break;
-	    else if (ul_addr == ULONG_MAX && errno == ERANGE)
-	    {
-		/* Quoted from strtoul(3)
-		   ---------------------------------------------------
-		   The strtoul() function returns either the result of
-		   the conversion or, if there was a leading minus
-		   sign, the negation of the result of the conversion
-		   represented as an unsigned value, unless the
-		   original (nonnegated) value would overflow; in the
-		   latter case, strtoul() returns ULONG_MAX and sets
-		   errno to ERANGE.
-		   ---------------------------------------------------
-		   NOTE: even if the value doesn't overflow, a
-		   negative is not acceptable. */
-		break;
-	    }
-	    else if (ul_addr > (unsigned long)UINT32_MAX)
-	    {
-		/* This will never happen:
-		   The maximum length of BUF is 8 characters.
-		   The possible maximum value represented by BUF is
-		   "FFFFFFFF". This is UINT32_MAX.
-		   If you agree with what I write here, make a pull
-		   request for removing this block. */
-		break;
-	    }
-	    ad->s6_addr32[i] = (uint32_t)ul_addr;
-	}
-	return((*as || (i != 4) || len) ? 1 : 0);
-}
-#endif	/* defined(HASIPv6) */
-
-
-/*
- * isainb(a,b) is string a in string b
- */
-
-static int
-isainb(a, b)
-	char *a;			/*string a */
-	char *b;			/* string b */
-{
-	char *cp, *pp;
-	MALLOC_S la, lb, lt;
-
-	if (!a || !b)
-	    return(1);
-	if (!(la = strlen(a)) || !(lb = strlen(b)))
-	    return(1);
-	if (!(cp = strchr(b, (int)','))) {
-	    if (la != lb)
-		return(1);
-	    return(strcmp(a, b));
-	}
-	for (pp = b; pp && *pp; ) {
-	    lt = (MALLOC_S)(cp - pp);
-	    if ((la == lt) && !strncmp(a, pp, lt))
-		return(0);
-	    if (*cp) {
-		pp = cp + 1;
-		if (!(cp = strchr(pp, (int)',')))
-		    cp = b + lb;
-	    } else
-		pp = cp;
-	}
-	return(1);
-}
-
-
-/*
- * print_ax25info() - print AX25 socket info
- */
-
-static void
-print_ax25info(ap)
-	struct ax25sin *ap;		/* AX25 socket info */
-{
-	char *cp, pbuf[1024];
-	int ds;
-	MALLOC_S pl = (MALLOC_S)0;
-
-	if (Lf->nma)
-	    return;
-	if (ap->sa) {
-	    ds = (ap->da && strcmp(ap->da, "*")) ? 1 : 0;
-	    (void) snpf(&pbuf[pl], sizeof(pbuf) - pl, "%s%s%s ", ap->sa,
-		ds ? "->" : "",
-		ds ? ap->da : "");
-	    pl = strlen(pbuf);
-	}
-	if (ap->sqs) {
-	    (void) snpf(&pbuf[pl], sizeof(pbuf) - pl, "(Sq=%lu ", ap->sq);
-	    pl = strlen(pbuf);
-	    cp = "";
-	} else
-	    cp = "(";
-	if (ap->rqs) {
-	    (void) snpf(&pbuf[pl], sizeof(pbuf) - pl, "%sRq=%lu ", cp, ap->rq);
-	    pl = strlen(pbuf);
-	    cp = "";
-	}
-	(void) snpf(&pbuf[pl], sizeof(pbuf) - pl, "%sState=%d", cp, ap->state);
-	pl = strlen(pbuf);
-	if ((ap->state >= 0) && (ap->state < NAX25ST))
-	    cp = ax25st[ap->state];
-	else
-	    cp = NULL;
-	(void) snpf(&pbuf[pl], sizeof(pbuf) - pl, "%s%s)",
-	    cp ? ", " : "",
-	    cp ? cp : "");
-	pl = strlen(pbuf);
-	if (!(cp = (char *)malloc(pl + 1))) {
-	    (void) fprintf(stderr,
-		"%s: can't allocate %d bytes for AX25 sock state, PID: %d\n",
-		Pn, (int)(pl + 1), Lp->pid);
-	    Error();
-	}
-	(void) snpf(cp, pl + 1, "%s", pbuf);
-	Lf->nma = cp;
-}
-
-
-/*
- * print_ipxinfo() - print IPX socket info
- */
-
-static void
-print_ipxinfo(ip)
-	struct ipxsin *ip;		/* IPX socket info */
-{
-	char *cp, pbuf[256];
-	MALLOC_S pl;
-
-	if (Lf->nma)
-	    return;
-	(void) snpf(pbuf, sizeof(pbuf), "(Tx=%lx Rx=%lx State=%02x)",
-	    ip->txq, ip->rxq, ip->state);
-	pl = strlen(pbuf);
-	if (!(cp = (char *)malloc(pl + 1))) {
-	    (void) fprintf(stderr,
-		"%s: can't allocate %d bytes for IPX sock state, PID: %d\n",
-		Pn, (int)(pl + 1), Lp->pid);
-	    Error();
-	}
-	(void) snpf(cp, pl + 1, "%s", pbuf);
-	Lf->nma = cp;
-}
-
-
-/*
- * print_unix() - print state of UNIX domain socket
- */
-
-static void
-print_unix(int nl)
-{
-	if (Ftcptpi & TCPTPI_STATE) {
-#if	defined(HASSOSTATE) && defined(HASSOOPT)
-	    char *cp = (Lf->lts.opt == __SO_ACCEPTCON)? "LISTEN": sockss2str(Lf->lts.ss);
-
-	    if (Ffield)
-		(void) printf("%cST=%s%c", LSOF_FID_TCPTPI, cp, Terminator);
-	    else {
-		putchar('(');
-		(void) fputs(cp, stdout);
-		putchar(')');
-	    }
-#endif	/* defined(HASSOSTATE) && defined(HASSOOPT) */
-	}
-	if (nl)
-	    putchar('\n');
-}
-
-
-/*
- * print_tcptpi() - print TCP/TPI state
- */
-
-void
-print_tcptpi(nl)
-	int nl;				/* 1 == '\n' required */
-{
-	char buf[128];
-	char *cp = (char *)NULL;
-	int ps = 0;
-	int s;
-
-	if (!strcmp(Lf->type, "unix"))  {
-	    print_unix(nl);
-	    return;
-	}
-	if ((Ftcptpi & TCPTPI_STATE) && Lf->lts.type == 0) {
-	    if (!TcpSt)
-		(void) build_IPstates();
-	    if ((s = Lf->lts.state.i + TcpStOff) < 0 || s >= TcpNstates) {
-		(void) snpf(buf, sizeof(buf), "UNKNOWN_TCP_STATE_%d",
-		    Lf->lts.state.i);
-		cp = buf;
-    	    } else
-		cp = TcpSt[s];
-	    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(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_proc_sock() - process /proc-based socket
- */
-
-void
-process_proc_sock(p, pbr, s, ss, l, lss)
-	char *p;			/* node's readlink() path */
-	char *pbr;			/* node's path before readlink() */
-	struct stat *s;			/* stat() result for path */
-	int ss;				/* *s status -- i.e, SB_* values */
-	struct stat *l;			/* lstat() result for FD (NULL for
-					 * others) */
-	int lss;			/* *l status -- i.e, SB_* values */
-{
-	struct ax25sin *ap;
-	char *cp, *path = (char *)NULL, tbuf[64];
-	unsigned char *fa, *la;
-	struct in_addr fs, ls;
-	struct icmpin *icmpp;
-	struct ipxsin *ip;
-	int i, len, nl, rf;
-	struct nlksin *np;
-	struct packin *pp;
-	char *pr;
-	static char *prp = (char *)NULL;
-	struct rawsin *rp;
-	struct sctpsin *sp;
-	static ssize_t sz;
-	struct tcp_udp *tp;
-	uxsin_t *up;
-
-#if	defined(HASIPv6)
-	int af;
-	struct tcp_udp6 *tp6;
-#endif	/* defined(HASIPv6) */
-
-/*
- * Enter offset, if possible.
- */
-	if (Foffset || !Fsize) {
-	    if (l && (lss & SB_SIZE) && OffType) {
-		Lf->off = (SZOFFTYPE)l->st_size;
-		Lf->off_def = 1;
-	    }
-	}
-/*
- * Check for socket's inode presence in the protocol info caches.
- */
-	if (AX25path) {
-	    (void) get_ax25(AX25path);
-	    (void) free((FREE_P *)AX25path);
-	    AX25path = (char *)NULL;
-	}
-	if ((ss & SB_INO)
-	&&  (ap = check_ax25((INODETYPE)s->st_ino))
-	) {
-
-	/*
-	 * The inode is connected to an AX25 /proc record.
-	 *
-	 * Set the type to "ax25"; save the device name; save the inode number;
-	 * save the destination and source addresses; save the send and receive
-	 * queue sizes; and save the connection state.
-	 */
-	    (void) snpf(Lf->type, sizeof(Lf->type), "ax25");
-	    if (ap->dev_ch)
-		(void) enter_dev_ch(ap->dev_ch);
-	    Lf->inode = ap->inode;
-	    Lf->inp_ty = 1;
-	    print_ax25info(ap);
-	    return;
-	}
-	if (Ipxpath) {
-	    (void) get_ipx(Ipxpath);
-	    (void) free((FREE_P *)Ipxpath);
-	    Ipxpath = (char *)NULL;
-	}
-	if ((ss & SB_INO)
-	&&  (ip = check_ipx((INODETYPE)s->st_ino))
-	) {
-
-	/*
-	 * The inode is connected to an IPX /proc record.
-	 *
-	 * Set the type to "ipx"; enter the inode and device numbers; store
-	 * the addresses, queue sizes, and state in the NAME column.
-	 */
-	    (void) snpf(Lf->type, sizeof(Lf->type), "ipx");
-	    if (ss & SB_INO) {
-		Lf->inode = (INODETYPE)s->st_ino;
-		Lf->inp_ty = 1;
-	    }
-	    if (ss & SB_DEV) {
-		Lf->dev = s->st_dev;
-		Lf->dev_def = 1;
-	    }
-	    cp = Namech;
-	    nl = Namechl;
-	    *cp = '\0';
-	    if (ip->la && nl) {
-
-	    /*
-	     * Store the local IPX address.
-	     */
-		len = strlen(ip->la);
-		if (len > nl)
-		    len = nl;
-		(void) strncpy(cp, ip->la, len);
-		cp += len;
-		*cp = '\0';
-		nl -= len;
-	    }
-	    if (ip->ra && nl) {
-
-	    /*
-	     * Store the remote IPX address, prefixed with "->".
-	     */
-		if (nl > 2) {
-		    (void) snpf(cp, nl, "->");
-		    cp += 2;
-		    nl -= 2;
-		}
-		if (nl) {
-		    (void) snpf(cp, nl, "%s", ip->ra);
-		    cp += len;
-		    nl -= len;
-		}
-	    }
-	    (void) print_ipxinfo(ip);
-	    if (Namech[0])
-		enter_nm(Namech);
-	    return;
-	}
-	if (Rawpath) {
-	    (void) get_raw(Rawpath);
-	    (void) free((FREE_P *)Rawpath);
-	    Rawpath = (char *)NULL;
-	}
-	if ((ss & SB_INO)
-	&&  (rp = check_raw((INODETYPE)s->st_ino))
-	) {
-
-	/*
-	 * The inode is connected to a raw /proc record.
-	 *
-	 * Set the type to "raw"; enter the inode number; store the local
-	 * address, remote address, and state in the NAME column.
-	 */
-	    (void) snpf(Lf->type, sizeof(Lf->type), "raw");
-	    if (ss & SB_INO) {
-		Lf->inode = (INODETYPE)s->st_ino;
-		Lf->inp_ty = 1;
-	    }
-	    cp = Namech;
-	    nl = Namechl - 2;
-	    *cp = '\0';
-	    if (rp->la && rp->lal) {
-
-	    /*
-	     * Store the local raw address.
-	     */
-		if (nl > rp->lal) {
-		    (void) snpf(cp, nl, "%s", rp->la);
-		    cp += rp->lal;
-		    *cp = '\0';
-		    nl -= rp->lal;
-		}
-	    }
-	    if (rp->ra && rp->ral) {
-
-	    /*
-	     * Store the remote raw address, prefixed with "->".
-	     */
-		if (nl > (rp->ral + 2)) {
-		    (void) snpf(cp, nl, "->%s", rp->ra);
-		    cp += (rp->ral + 2);
-		    *cp = '\0';
-		    nl -= (rp->ral + 2);
-		}
-	    }
-	    if (rp->sp && rp->spl) {
-
-	    /*
-	     * Store the state, optionally prefixed by a space, in the
-	     * form "st=x...x".
-	     */
-
-		if (nl > (len = ((cp == Namech) ? 0 : 1) + 3 + rp->spl)) {
-		    (void) snpf(cp, nl, "%sst=%s",
-			(cp == Namech) ? "" : " ", rp->sp);
-		    cp += len;
-		    *cp = '\0';
-		    nl -= len;
-		}
-	    }
-	    if (Namech[0])
-		enter_nm(Namech);
-	    return;
-	}
-	if (Nlkpath) {
-	    (void) get_netlink(Nlkpath);
-	    (void) free((FREE_P *) Nlkpath);
-	    Nlkpath = (char *)NULL;
-	}
-	if ((ss & SB_INO)
-	    &&  (np = check_netlink((INODETYPE)s->st_ino))
-	) {
-	    /*
-	     * The inode is connected to a Netlink /proc record.
-	     *
-	     * Set the type to "netlink" and store the protocol in the NAME
-	     * column.  Save the inode number.
-	     */
-
-	    (void) snpf(Lf->type, sizeof(Lf->type), "netlink");
-	    cp = nlproto2str(np->pr);
-	    if (cp)
-		(void) snpf(Namech, Namechl, "%s", cp);
-	    else
-		(void) snpf(Namech, Namechl, "unknown protocol: %d", np->pr);
-
-	    Lf->inode = (INODETYPE)s->st_ino;
-	    Lf->inp_ty = 1;
-	    if (Namech[0])
-		enter_nm(Namech);
-	    return;
-	}
-	if (Packpath) {
-	    (void) get_pack(Packpath);
-	    (void) free((FREE_P *)Packpath);
-	    Packpath = (char *)NULL;
-	}
-	if ((ss & SB_INO)
-	&&  (pp = check_pack((INODETYPE)s->st_ino))
-	) {
-
-	/*
-	 * The inode is connected to a packet /proc record.
-	 *
-	 * Set the type to "pack" and store the socket type in the NAME
-	 * column.  Put the protocol name in the NODE column and the inode
-	 * number in the DEVICE column.
-	 */
-	    (void) snpf(Lf->type, sizeof(Lf->type), "pack");
-	    cp = sockty2str(pp->ty, &rf);
-	    (void) snpf(Namech, Namechl, "type=%s%s", rf ? "" : "SOCK_", cp);
-	    switch (pp->pr) {
-
-#if	defined(ETH_P_LOOP)
-	    case ETH_P_LOOP:
-		cp = "LOOP";
-		break;
-#endif	/* defined(ETH_P_LOOP) */
-
-#if	defined(ETH_P_PUP)
-	    case ETH_P_PUP:
-		cp = "PUP";
-		break;
-#endif	/* defined(ETH_P_PUP) */
-
-#if	defined(ETH_P_PUPAT)
-	    case ETH_P_PUPAT:
-		cp = "PUPAT";
-		break;
-#endif	/* defined(ETH_P_PUPAT) */
-
-#if	defined(ETH_P_IP)
-	    case ETH_P_IP:
-		cp = "IP";
-		break;
-#endif	/* defined(ETH_P_IP) */
-
-#if	defined(ETH_P_X25)
-	    case ETH_P_X25:
-		cp = "X25";
-		break;
-#endif	/* defined(ETH_P_X25) */
-
-#if	defined(ETH_P_ARP)
-	    case ETH_P_ARP:
-		cp = "ARP";
-		break;
-#endif	/* defined(ETH_P_ARP) */
-
-#if	defined(ETH_P_BPQ)
-	    case ETH_P_BPQ:
-		cp = "BPQ";
-		break;
-#endif	/* defined(ETH_P_BPQ) */
-
-#if	defined(ETH_P_IEEEPUP)
-	    case ETH_P_IEEEPUP:
-		cp = "I3EPUP";
-		break;
-#endif	/* defined(ETH_P_IEEEPUP) */
-
-#if	defined(ETH_P_IEEEPUPAT)
-	    case ETH_P_IEEEPUPAT:
-		cp = "I3EPUPA";
-		break;
-#endif	/* defined(ETH_P_IEEEPUPAT) */
-
-#if	defined(ETH_P_DEC)
-	    case ETH_P_DEC:
-		cp = "DEC";
-		break;
-#endif	/* defined(ETH_P_DEC) */
-
-#if	defined(ETH_P_DNA_DL)
-	    case ETH_P_DNA_DL:
-		cp = "DNA_DL";
-		break;
-#endif	/* defined(ETH_P_DNA_DL) */
-
-#if	defined(ETH_P_DNA_RC)
-	    case ETH_P_DNA_RC:
-		cp = "DNA_RC";
-		break;
-#endif	/* defined(ETH_P_DNA_RC) */
-
-#if	defined(ETH_P_DNA_RT)
-	    case ETH_P_DNA_RT:
-		cp = "DNA_RT";
-		break;
-#endif	/* defined(ETH_P_DNA_RT) */
-
-#if	defined(ETH_P_LAT)
-	    case ETH_P_LAT:
-		cp = "LAT";
-		break;
-#endif	/* defined(ETH_P_LAT) */
-
-#if	defined(ETH_P_DIAG)
-	    case ETH_P_DIAG:
-		cp = "DIAG";
-		break;
-#endif	/* defined(ETH_P_DIAG) */
-
-#if	defined(ETH_P_CUST)
-	    case ETH_P_CUST:
-		cp = "CUST";
-		break;
-#endif	/* defined(ETH_P_CUST) */
-
-#if	defined(ETH_P_SCA)
-	    case ETH_P_SCA:
-		cp = "SCA";
-		break;
-#endif	/* defined(ETH_P_SCA) */
-
-#if	defined(ETH_P_RARP)
-	    case ETH_P_RARP:
-		cp = "RARP";
-		break;
-#endif	/* defined(ETH_P_RARP) */
-
-#if	defined(ETH_P_ATALK)
-	    case ETH_P_ATALK:
-		cp = "ATALK";
-		break;
-#endif	/* defined(ETH_P_ATALK) */
-
-#if	defined(ETH_P_AARP)
-	    case ETH_P_AARP:
-		cp = "AARP";
-		break;
-#endif	/* defined(ETH_P_AARP) */
-
-#if	defined(ETH_P_8021Q)
-	    case ETH_P_8021Q:
-		cp = "8021Q";
-		break;
-#endif	/* defined(ETH_P_8021Q) */
-
-#if	defined(ETH_P_IPX)
-	    case ETH_P_IPX:
-		cp = "IPX";
-		break;
-#endif	/* defined(ETH_P_IPX) */
-
-#if	defined(ETH_P_IPV6)
-	    case ETH_P_IPV6:
-		cp = "IPV6";
-		break;
-#endif	/* defined(ETH_P_IPV6) */
-
-#if	defined(ETH_P_SLOW)
-	    case ETH_P_SLOW:
-		cp = "SLOW";
-		break;
-#endif	/* defined(ETH_P_SLOW) */
-
-#if	defined(ETH_P_WCCP)
-	    case ETH_P_WCCP:
-		cp = "WCCP";
-		break;
-#endif	/* defined(ETH_P_WCCP) */
-
-#if	defined(ETH_P_PPP_DISC)
-	    case ETH_P_PPP_DISC:
-		cp = "PPP_DIS";
-		break;
-#endif	/* defined(ETH_P_PPP_DISC) */
-
-#if	defined(ETH_P_PPP_SES)
-	    case ETH_P_PPP_SES:
-		cp = "PPP_SES";
-		break;
-#endif	/* defined(ETH_P_PPP_SES) */
-
-#if	defined(ETH_P_MPLS_UC)
-	    case ETH_P_MPLS_UC:
-		cp = "MPLS_UC";
-		break;
-#endif	/* defined(ETH_P_MPLS_UC) */
-
-#if	defined(ETH_P_ATMMPOA)
-	    case ETH_P_ATMMPOA:
-		cp = "ATMMPOA";
-		break;
-#endif	/* defined(ETH_P_ATMMPOA) */
-
-#if	defined(ETH_P_MPLS_MC)
-	    case ETH_P_MPLS_MC:
-		cp = "MPLS_MC";
-		break;
-#endif	/* defined(ETH_P_MPLS_MC) */
-
-#if	defined(ETH_P_ATMFATE)
-	    case ETH_P_ATMFATE:
-		cp = "ATMFATE";
-		break;
-#endif	/* defined(ETH_P_ATMFATE) */
-
-#if	defined(ETH_P_AOE)
-	    case ETH_P_AOE:
-		cp = "AOE";
-		break;
-#endif	/* defined(ETH_P_AOE) */
-
-#if	defined(ETH_P_TIPC)
-	    case ETH_P_TIPC:
-		cp = "TIPC";
-		break;
-#endif	/* defined(ETH_P_TIPC) */
-
-#if	defined(ETH_P_802_3)
-	    case ETH_P_802_3:
-		cp = "802.3";
-		break;
-#endif	/* defined(ETH_P_802_3) */
-
-#if	defined(ETH_P_AX25)
-	    case ETH_P_AX25:
-		cp = "AX25";
-		break;
-#endif	/* defined(ETH_P_AX25) */
-
-#if	defined(ETH_P_ALL)
-	    case ETH_P_ALL:
-		cp = "ALL";
-		break;
-#endif	/* defined(ETH_P_ALL) */
-
-#if	defined(ETH_P_802_2)
-	    case ETH_P_802_2:
-		cp = "802.2";
-		break;
-#endif	/* defined(ETH_P_802_2) */
-
-#if	defined(ETH_P_SNAP)
-	    case ETH_P_SNAP:
-		cp = "SNAP";
-		break;
-#endif	/* defined(ETH_P_SNAP) */
-
-#if	defined(ETH_P_DDCMP)
-	    case ETH_P_DDCMP:
-		cp = "DDCMP";
-		break;
-#endif	/* defined(ETH_P_DDCMP) */
-
-#if	defined(ETH_P_WAN_PPP)
-	    case ETH_P_WAN_PPP:
-		cp = "WAN_PPP";
-		break;
-#endif	/* defined(ETH_P_WAN_PPP) */
-
-#if	defined(ETH_P_PPP_MP)
-	    case ETH_P_PPP_MP:
-		cp = "PPP MP";
-		break;
-#endif	/* defined(ETH_P_PPP_MP) */
-
-#if	defined(ETH_P_LOCALTALK)
-	    case ETH_P_LOCALTALK:
-		cp = "LCLTALK";
-		break;
-#endif	/* defined(ETH_P_LOCALTALK) */
-
-#if	defined(ETH_P_PPPTALK)
-	    case ETH_P_PPPTALK:
-		cp = "PPPTALK";
-		break;
-#endif	/* defined(ETH_P_PPPTALK) */
-
-#if	defined(ETH_P_TR_802_2)
-	    case ETH_P_TR_802_2:
-		cp = "802.2";
-		break;
-#endif	/* defined(ETH_P_TR_802_2) */
-
-#if	defined(ETH_P_MOBITEX)
-	    case ETH_P_MOBITEX:
-		cp = "MOBITEX";
-		break;
-#endif	/* defined(ETH_P_MOBITEX) */
-
-#if	defined(ETH_P_CONTROL)
-	    case ETH_P_CONTROL:
-		cp = "CONTROL";
-		break;
-#endif	/* defined(ETH_P_CONTROL) */
-
-#if	defined(ETH_P_IRDA)
-	    case ETH_P_IRDA:
-		cp = "IRDA";
-		break;
-#endif	/* defined(ETH_P_IRDA) */
-
-#if	defined(ETH_P_ECONET)
-	    case ETH_P_ECONET:
-		cp = "ECONET";
-		break;
-#endif	/* defined(ETH_P_ECONET) */
-
-#if	defined(ETH_P_HDLC)
-	    case ETH_P_HDLC:
-		cp = "HDLC";
-		break;
-#endif	/* defined(ETH_P_HDLC) */
-
-#if	defined(ETH_P_ARCNET)
-	    case ETH_P_ARCNET:
-		cp = "ARCNET";
-		break;
-#endif	/* defined(ETH_P_ARCNET) */
-
-	    default:
-		(void) snpf(tbuf, sizeof(tbuf) - 1, "%d", pp->pr);
-		tbuf[sizeof(tbuf) - 1] = '\0';
-		cp = tbuf;
-	    }
-	    (void) snpf(Lf->iproto, sizeof(Lf->iproto), "%.*s", IPROTOL-1, cp);
-	    Lf->inp_ty = 2;
-	    if (ss & SB_INO) {
-		(void) snpf(tbuf, sizeof(tbuf), InodeFmt_d,
-		    (INODETYPE)s->st_ino);
-		tbuf[sizeof(tbuf) - 1] = '\0';
-		enter_dev_ch(tbuf);
-	    }
-	    if (Namech[0])
-		enter_nm(Namech);
-	    return;
-	}
-	if (UNIXpath) {
-	    (void) get_unix(UNIXpath);
-	    (void) free((FREE_P *)UNIXpath);
-	    UNIXpath = (char *)NULL;
-	}
-	if ((ss & SB_INO)
-	&&  (up = check_unix((INODETYPE)s->st_ino))
-	) {
-
-	/*
-	 * The inode is connected to a UNIX /proc record.
-	 *
-	 * Set the type to "unix"; enter the PCB address in the DEVICE column;
-	 * enter the inode number; and save the optional path.
-	 */
-	    if (Funix)
-		Lf->sf |= SELUNX;
-	    (void) snpf(Lf->type, sizeof(Lf->type), "unix");
-	    if (up->pcb)
-		enter_dev_ch(up->pcb);
-	    Lf->inode = (INODETYPE)s->st_ino;
-	    Lf->inp_ty = 1;
-
-	    Lf->lts.type = up->ty;
-#if	defined(HASSOOPT)
-	    Lf->lts.opt = up->opt;
-#endif	/* defined(HASSOOPT) */
-#if	defined(HASSOSTATE)
-	    Lf->lts.ss = up->ss;
-#endif	/* defined(HASSOSTATE) */
-#if	defined(HASEPTOPTS) && defined(HASUXSOCKEPT)
-	    if (FeptE) {
-		(void) enter_uxsinfo(up);
-		Lf->sf |= SELUXSINFO;
-	    }
-#endif	/* defined(HASEPTOPTS) && defined(HASUXSOCKEPT) */
-
-	    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) {
-
-	    /*
-	     * See if this UNIX domain socket was specified as a search
-	     * argument.
-	     *
-	     * Search first by device and node numbers, if that is possible;
-	     * then search by name.
-	     */
-		unsigned char f = 0;		/* file-found flag */
-
-		if (up->sb_def) {
-
-		/*
-		 * If the UNIX socket information includes stat(2) results, do
-		 * a device and node number search.
-		 *
-		 * Note: that requires the saving, temporary modification and
-		 *	 restoration of some *Lf values.
-		 */
-		    unsigned char sv_dev_def;	/* saved dev_def */
-		    unsigned char sv_inp_ty;	/* saved inp_ty */
-		    unsigned char sv_rdev_def;	/* saved rdev_def */
-		    dev_t sv_dev;		/* saved dev */
-		    INODETYPE sv_inode;		/* saved inode */
-		    dev_t sv_rdev;		/* saved rdev */
-
-		    sv_dev_def = Lf->dev_def;
-		    sv_dev = Lf->dev;
-		    sv_inode = Lf->inode;
-		    sv_inp_ty = Lf->inp_ty;
-		    sv_rdev_def = Lf->rdev_def;
-		    sv_rdev = Lf->rdev;
-		    Lf->dev_def = Lf->inp_ty = Lf->rdev_def = 1;
-		    Lf->dev = up->sb_dev;
-		    Lf->inode = up->sb_ino;
-		    Lf->rdev = up->sb_rdev;
-		    if (is_file_named(0, path, (struct mounts *)NULL, 0)) {
-			f = 1;
-			Lf->sf |= SELNM;
-		    }
-		    Lf->dev_def = sv_dev_def;
-		    Lf->dev = sv_dev;
-		    Lf->inode = sv_inode;
-		    Lf->inp_ty = sv_inp_ty;
-		    Lf->rdev_def = sv_rdev_def;
-		    Lf->rdev = sv_rdev;
-		}
-		if (!f && (ss & SB_MODE)) {
-
-		/*
-		 * If the file has not yet been found and the stat buffer has
-		 * st_mode, search for the file by full path.
-		 */
-		    if (is_file_named(2, up->path ? up->path : p,
-			(struct mounts *)NULL,
-			((s->st_mode & S_IFMT) == S_IFCHR)) ? 1 : 0)
-		    {
-			Lf->sf |= SELNM;
-		    }
-		}
-	    }
-	    return;
-	}
-
-#if	defined(HASIPv6)
-	if (Raw6path) {
-	    if (!Fxopt)
-		(void) get_raw6(Raw6path);
-	    (void) free((FREE_P *)Raw6path);
-	    Raw6path = (char *)NULL;
-	}
-	if (!Fxopt && (ss & SB_INO)
-	&&  (rp = check_raw6((INODETYPE)s->st_ino))
-	) {
-
-	/*
-	 * The inode is connected to a raw IPv6 /proc record.
-	 *
-	 * Set the type to "raw6"; enter the inode number; store the local
-	 * address, remote address, and state in the NAME column.
-	 */
-	    (void) snpf(Lf->type, sizeof(Lf->type), "raw6");
-	    if (ss & SB_INO) {
-		Lf->inode = (INODETYPE)s->st_ino;
-		Lf->inp_ty = 1;
-	    }
-	    cp = Namech;
-	    nl = MAXPATHLEN - 2;
-	    if (rp->la && rp->lal) {
-
-	    /*
-	     * Store the local raw IPv6 address.
-	     */
-		if (nl > rp->lal) {
-		    (void) snpf(cp, nl, "%s", rp->la);
-		    cp += rp->lal;
-		    *cp = '\0';
-		    nl -= rp->lal;
-		}
-	    }
-	    if (rp->ra && rp->ral) {
-
-	    /*
-	     * Store the remote raw address, prefixed with "->".
-	     */
-		if (nl > (rp->ral + 2)) {
-		    (void) snpf(cp, nl, "->%s", rp->ra);
-		    cp += (rp->ral + 2);
-		    nl -= (rp->ral + 2);
-		}
-	    }
-	    if (rp->sp && rp->spl) {
-
-	    /*
-	     * Store the state, optionally prefixed by a space, in the
-	     * form "st=x...x".
-	     */
-
-		if (nl > (len = ((cp == Namech) ? 0 : 1) + 3 + rp->spl)) {
-		    (void) snpf(cp, nl, "%sst=%s",
-			(cp == Namech) ? "" : " ", rp->sp);
-		    cp += len;
-		    *cp = '\0';
-		    nl -= len;
-		}
-	    }
-	    if (Namech[0])
-		enter_nm(Namech);
-	    return;
-	}
-	if (TCP6path) {
-	    if (!Fxopt)
-		(void) get_tcpudp6(TCP6path, 0, 1);
-	    (void) free((FREE_P *)TCP6path);
-	    TCP6path = (char *)NULL;
-	}
-	if (UDP6path) {
-	    if (!Fxopt)
-		(void) get_tcpudp6(UDP6path, 1, 0);
-	    (void) free((FREE_P *)UDP6path);
-	    UDP6path = (char *)NULL;
-	}
-	if (UDPLITE6path) {
-	    if (!Fxopt)
-		(void) get_tcpudp6(UDPLITE6path, 2, 0);
-	    (void) free((FREE_P *)UDPLITE6path);
-	    UDPLITE6path = (char *)NULL;
-	}
-	if (!Fxopt && (ss & SB_INO)
-	&&  (tp6 = check_tcpudp6((INODETYPE)s->st_ino, &pr))
-	) {
-
-	/*
-	 * The inode is connected to an IPv6 TCP or UDP /proc record.
-	 *
-	 * Set the type to "IPv6"; enter the protocol; put the inode number
-	 * in the DEVICE column in lieu of the PCB address; save the local
-	 * and foreign IPv6 addresses; save the type and protocol; and
-	 * (optionally) save the queue sizes.
-	 */
-	    i = tp6->state + TcpStOff;
-	    if (TcpStXn) {
-
-	    /*
-	     * Check for state exclusion.
-	     */
-		if (i >= 0 && i < TcpNstates) {
-		    if (TcpStX[i]) {
-			Lf->sf |= SELEXCLF;
-			return;
-		    }
-		}
-	    }
-	    if (TcpStIn) {
-
-	    /*
-	     * Check for state inclusion.
-	     */
-		if (i >= 0 && i < TcpNstates) {
-		    if (TcpStI[i])
-			TcpStI[i] = 2;
-		    else {
-			Lf->sf |= SELEXCLF;
-			return;
-		   }
-		}
-	    }
-	    if (Fnet && (FnetTy != 4))
-		Lf->sf |= SELNET;
-	    (void) snpf(Lf->type, sizeof(Lf->type), "IPv6");
-	    (void) snpf(Lf->iproto, sizeof(Lf->iproto), "%.*s", IPROTOL-1, pr);
-	    Lf->inp_ty = 2;
-	    if (ss & SB_INO) {
-		(void) snpf(tbuf, sizeof(tbuf), InodeFmt_d,
-		    (INODETYPE)s->st_ino);
-		tbuf[sizeof(tbuf) - 1] = '\0';
-		enter_dev_ch(tbuf);
-		Lf->inode = (INODETYPE)s->st_ino;
-	    }
-	    af = AF_INET6;
-	    if (!IN6_IS_ADDR_UNSPECIFIED(&tp6->faddr) || tp6->fport)
-		fa = (unsigned char *)&tp6->faddr;
-	    else
-		fa = (unsigned char *)NULL;
-	    if (!IN6_IS_ADDR_UNSPECIFIED(&tp6->laddr) || tp6->lport)
-		la = (unsigned char *)&tp6->laddr;
-	    else
-		la = (unsigned char *)NULL;
-	    if ((fa && IN6_IS_ADDR_V4MAPPED(&tp6->faddr))
-	    ||  (la && IN6_IS_ADDR_V4MAPPED(&tp6->laddr))) {
-		af = AF_INET;
-		if (fa)
-		    fa += 12;
-		if (la)
-		    la += 12;
-	    }
-	    ent_inaddr(la, tp6->lport, fa, tp6->fport, af);
-	    Lf->lts.type = tp6->proto;
-	    Lf->lts.state.i = tp6->state;
-
-#if     defined(HASTCPTPIQ)
-	    Lf->lts.rq = tp6->rxq;
-	    Lf->lts.sq = tp6->txq;
-	    Lf->lts.rqs = Lf->lts.sqs = 1;
-#endif  /* defined(HASTCPTPIQ) */
-
-#if	defined(HASEPTOPTS)
-	    if (FeptE && tp6->ipc_peer) {
-		(void) enter_nets6info(tp6);
-		Lf->sf |= SELNETS6INFO;
-	    }
-#endif	/* defined(HASEPTOPTS) */
-	    return;
-	}
-#endif	/* defined(HASIPv6) */
-
-	if (TCPpath) {
-	    if (!Fxopt)
-		(void) get_tcpudp(TCPpath, 0, 1);
-	    (void) free((FREE_P *)TCPpath);
-	    TCPpath = (char *)NULL;
-	}
-	if (UDPpath) {
-	    if (!Fxopt)
-		(void) get_tcpudp(UDPpath, 1, 0);
-	    (void) free((FREE_P *)UDPpath);
-	    UDPpath = (char *)NULL;
-	}
-	if (UDPLITEpath) {
-	    if (!Fxopt)
-		(void) get_tcpudp(UDPLITEpath, 2, 0);
-	    (void) free((FREE_P *)UDPLITEpath);
-	    UDPLITEpath = (char *)NULL;
-	}
-	if (!Fxopt && (ss & SB_INO)
-	&&  (tp = check_tcpudp((INODETYPE)s->st_ino, &pr))
-	) {
-
-	/*
-	 * The inode is connected to an IPv4 TCP or UDP /proc record.
-	 *
-	 * Set the type to "inet" or "IPv4"; enter the protocol; put the
-	 * inode number in the DEVICE column in lieu of the PCB address;
-	 * save the local and foreign IPv4 addresses; save the type and
-	 * protocol; and (optionally) save the queue sizes.
-	 */
-	    i = tp->state + TcpStOff;
-	    if (TcpStXn) {
-
-	    /*
-	     * Check for state exclusion.
-	     */
-		if (i >= 0 && i < TcpNstates) {
-		    if (TcpStX[i]) {
-			Lf->sf |= SELEXCLF;
-			return;
-		    }
-		}
-	    }
-	    if (TcpStIn) {
-
-	    /*
-	     * Check for state inclusion.
-	     */
-		if (i >= 0 && i < TcpNstates) {
-		    if (TcpStI[i])
-			TcpStI[i] = 2;
-		    else {
-			Lf->sf |= SELEXCLF;
-			return;
-		    }
-		}
-	    }
-	    if (Fnet && (FnetTy != 6))
-		Lf->sf |= SELNET;
-
-#if	defined(HASIPv6)
-	    (void) snpf(Lf->type, sizeof(Lf->type), "IPv4");
-#else	/* !defined(HASIPv6) */
-	    (void) snpf(Lf->type, sizeof(Lf->type), "inet");
-#endif	/* defined(HASIPv6) */
-
-	    (void) snpf(Lf->iproto, sizeof(Lf->iproto), "%.*s", IPROTOL-1, pr);
-	    Lf->inp_ty = 2;
-	    if (ss & SB_INO) {
-		(void) snpf(tbuf, sizeof(tbuf), InodeFmt_d,
-		    (INODETYPE)s->st_ino);
-		tbuf[sizeof(tbuf) - 1] = '\0';
-		enter_dev_ch(tbuf);
-		Lf->inode = (INODETYPE)s->st_ino;
-	    }
-	    if (tp->faddr || tp->fport) {
-		fs.s_addr = tp->faddr;
-		fa = (unsigned char *)&fs;
-	    } else
-		fa = (unsigned char *)NULL;
-	    if (tp->laddr || tp->lport) {
-		ls.s_addr = tp->laddr;
-		la = (unsigned char *)&ls;
-	    } else
-		la = (unsigned char *)NULL;
-	    ent_inaddr(la, tp->lport, fa, tp->fport, AF_INET);
-	    Lf->lts.type = tp->proto;
-	    Lf->lts.state.i = tp->state;
-
-#if     defined(HASTCPTPIQ)
-	    Lf->lts.rq = tp->rxq;
-	    Lf->lts.sq = tp->txq;
-	    Lf->lts.rqs = Lf->lts.sqs = 1;
-#endif  /* defined(HASTCPTPIQ) */
-
-#if	defined(HASEPTOPTS)
-	    if (FeptE && tp->ipc_peer) {
-		(void) enter_netsinfo(tp);
-		Lf->sf |= SELNETSINFO;
-	    }
-#endif	/* defined(HASEPTOPTS) */
-
-	    return;
-	}
-	if (SCTPPath[0]) {
-	    (void) get_sctp();
-	    for (i = 0; i < NSCTPPATHS; i++) {
-		(void) free((FREE_P *)SCTPPath[i]);
-		SCTPPath[i] = (char *)NULL;
-	    }
-	}
-	if ((ss & SB_INO) && (sp = check_sctp((INODETYPE)s->st_ino))
-	) {
-
-	/*
-	 * The inode is connected to an SCTP /proc record.
-	 *
-	 * Set the type to "sock"; enter the inode number in the DEVICE
-	 * column; set the protocol to SCTP; and fill in the NAME column
-	 * with ASSOC, ASSOC-ID, ENDPT, LADDRS, LPORT, RADDRS and RPORT.
-	 */
-	    (void) snpf(Lf->type, sizeof(Lf->type), "sock");
-	    (void) snpf(Lf->iproto, sizeof(Lf->iproto), "%.*s", IPROTOL-1,
-		"SCTP");
-	    Lf->inp_ty = 2;
-	    (void) snpf(tbuf, sizeof(tbuf), InodeFmt_d, (INODETYPE)s->st_ino);
-	    tbuf[sizeof(tbuf) - 1] = '\0';
-	    enter_dev_ch(tbuf);
-	    Namech[0] = '\0';
-	    if  (sp->type == 1) {
-
-	    /*
-	     * This is an ENDPT SCTP file.
-	     */
-		(void) snpf(Namech, Namechl,
-		    "ENDPT: %s%s%s%s%s%s",
-		    sp->addr ? sp->addr : "",
-		    (sp->laddrs || sp->lport) ? " " : "",
-		    sp->laddrs ? sp->laddrs : "",
-		    sp->lport ? "[" : "",
-		    sp->lport ? sp->lport : "",
-		    sp->lport ? "]" : ""
-		 );
-	    } else {
-
-	    /*
-	     * This is an ASSOC, or ASSOC and ENDPT socket file.
-	     */
-		(void) snpf(Namech, Namechl,
-		    "%s: %s%s%s %s%s%s%s%s%s%s%s%s",
-		    sp->type ? "ASSOC+ENDPT" : "ASSOC",
-		    sp->addr ? sp->addr : "",
-		    (sp->addr && sp->assocID) ? "," : "",
-		    sp->assocID ? sp->assocID : "",
-		    sp->laddrs ? sp->laddrs : "",
-		    sp->lport ? "[" : "",
-		    sp->lport ? sp->lport : "",
-		    sp->lport ? "]" : "",
-		    ((sp->laddrs || sp->lport) && (sp->raddrs || sp->rport))
-			? "<->" : "",
-		    sp->raddrs ? sp->raddrs : "",
-		    sp->rport ? "[" : "",
-		    sp->rport ? sp->rport : "",
-		    sp->rport ? "]" : ""
-		 );
-	    }
-	    if (Namech[0])
-		enter_nm(Namech);
-	    return;
-	}
-	if (ICMPpath) {
-	    (void) get_icmp(ICMPpath);
-	    (void) free((FREE_P *)ICMPpath);
-	    ICMPpath = (char *)NULL;
-	}
-	if ((ss & SB_INO)
-	&&  (icmpp = check_icmp((INODETYPE)s->st_ino))
-	) {
-
-	/*
-	 * The inode is connected to an ICMP /proc record.
-	 *
-	 * Set the type to "icmp" and store the type in the NAME
-	 * column.  Save the inode number.
-	 */
-	    (void) snpf(Lf->type, sizeof(Lf->type), "icmp");
-	    Lf->inode = (INODETYPE)s->st_ino;
-	    Lf->inp_ty = 1;
-	    cp = Namech;
-	    nl = Namechl- 2;
-	    *cp = '\0';
-	    if (icmpp->la && icmpp->lal) {
-
-	    /*
-	     * Store the local raw address.
-	     */
-		if (nl > icmpp->lal) {
-		    (void) snpf(cp, nl, "%s", icmpp->la);
-		    cp += icmpp->lal;
-		    *cp = '\0';
-		    nl -= icmpp->lal;
-		}
-	    }
-	    if (icmpp->ra && icmpp->ral) {
-
-	    /*
-	     * Store the remote raw address, prefixed with "->".
-	     */
-		if (nl > (icmpp->ral + 2)) {
-		    (void) snpf(cp, nl, "->%s", icmpp->ra);
-		    cp += (icmpp->ral + 2);
-		    *cp = '\0';
-		    nl -= (icmpp->ral + 2);
-		}
-	    }
-	    if (Namech[0])
-		enter_nm(Namech);
-	    return;
-	}
-/*
- * The socket's protocol can't be identified.
- */
-	(void) snpf(Lf->type, sizeof(Lf->type), "sock");
-	if (ss & SB_INO) {
-	    Lf->inode = (INODETYPE)s->st_ino;
-	    Lf->inp_ty = 1;
-	}
-	if (ss & SB_DEV) {
-	    Lf->dev = s->st_dev;
-	    Lf->dev_def = 1;
-	}
-	if (Fxopt)
-	    enter_nm("can't identify protocol (-X specified)");
-	else {
-	    (void) snpf(Namech, Namechl, "protocol: ");
-	    if (!prp) {
-		i = (int)strlen(Namech);
-		prp = &Namech[i];
-		sz = (ssize_t)(Namechl - i - 1);
-	    }
-	    if ((getxattr(pbr, "system.sockprotoname", prp, sz)) < 0)
-		enter_nm("can't identify protocol");
-	    else
-		enter_nm(Namech);
-	}
-}
-
-
-/*
- * set_net_paths() - set /proc/net paths
- */
-
-void
-set_net_paths(p, pl)
-	char *p;			/* path to /proc/net/ */
-	int pl;				/* strlen(p) */
-{
-	int i;
-	int pathl;
-
-	pathl = 0;
-	(void) make_proc_path(p, pl, &AX25path, &pathl, "ax25");
-	pathl = 0;
-	(void) make_proc_path(p, pl, &ICMPpath, &pathl, "icmp");
-	pathl = 0;
-	(void) make_proc_path(p, pl, &Ipxpath, &pathl, "ipx");
-	pathl = 0;
-	(void) make_proc_path(p, pl, &Nlkpath, &pathl, "netlink");
-	pathl = 0;
-	(void) make_proc_path(p, pl, &Packpath, &pathl, "packet");
-	pathl = 0;
-	(void) make_proc_path(p, pl, &Rawpath, &pathl, "raw");
-	for (i = 0; i < NSCTPPATHS; i++) {
-	    pathl = 0;
-	    (void) make_proc_path(p, pl, &SCTPPath[i], &pathl, SCTPSfx[i]);
-	}
-	pathl = 0;
-	(void) make_proc_path(p, pl, &SockStatPath, &pathl, "sockstat");
-	pathl = 0;
-	(void) make_proc_path(p, pl, &TCPpath, &pathl, "tcp");
-	pathl = 0;
-	(void) make_proc_path(p, pl, &UDPpath, &pathl, "udp");
-	pathl = 0;
-	(void) make_proc_path(p, pl, &UDPLITEpath, &pathl, "udplite");
-
-#if	defined(HASIPv6)
-	pathl = 0;
-	(void) make_proc_path(p, pl, &Raw6path, &pathl, "raw6");
-	pathl = 0;
-	(void) make_proc_path(p, pl, &SockStatPath6, &pathl, "sockstat6");
-	pathl = 0;
-	(void) make_proc_path(p, pl, &TCP6path, &pathl, "tcp6");
-	pathl = 0;
-	(void) make_proc_path(p, pl, &UDP6path, &pathl, "udp6");
-	pathl = 0;
-	(void) make_proc_path(p, pl, &UDPLITE6path, &pathl, "udplite6");
-#endif	/* defined(HASIPv6) */
-
-	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_DCCP)
-	case SOCK_DCCP:
-	    sr = "DCCP";
-	    break;
-#endif	/* defined(SOCK_DCCP) */
-
-#if	defined(SOCK_PACKET)
-	case SOCK_PACKET:
-	    sr = "PACKET";
-	    break;
-#endif	/* defined(SOCK_PACKET) */
-
-	default:
-	    f = 1;
-	    sr = "unknown";
-	}
-	*rf = f;
-	return(sr);
-}
-
-
-/*
- * Nlproto2str() -- convert netlink protocol number to a string
- *
- * return NULL if the number is unknown.
- */
-
-static char *
-nlproto2str(unsigned int pr)
-{
-	char *cp = NULL;
-	switch (pr) {
-#if	defined(NETLINK_ROUTE)
-	case NETLINK_ROUTE:
-	    cp = "ROUTE";
-	    break;
-#endif	/* defined(NETLINK_ROUTE) */
-
-#if	defined(NETLINK_UNUSED)
-	case NETLINK_UNUSED:
-	    cp = "UNUSED";
-	    break;
-#endif	/* defined(NETLINK_UNUSED) */
-
-#if	defined(NETLINK_USERSOCK)
-	case NETLINK_USERSOCK:
-	    cp = "USERSOCK";
-	    break;
-#endif	/* defined(NETLINK_USERSOCK) */
-
-#if	defined(NETLINK_FIREWALL)
-	case NETLINK_FIREWALL:
-	    cp = "FIREWALL";
-	    break;
-#endif	/* defined(NETLINK_FIREWALL) */
-
-#if	defined(NETLINK_INET_DIAG)
-	case NETLINK_INET_DIAG:
-	    cp = "INET_DIAG";
-	    break;
-#endif	/* defined(NETLINK_INET_DIAG) */
-
-#if	defined(NETLINK_NFLOG)
-	case NETLINK_NFLOG:
-	    cp = "NFLOG";
-	    break;
-#endif	/* defined(NETLINK_NFLOG) */
-
-#if	defined(NETLINK_XFRM)
-	case NETLINK_XFRM:
-	    cp = "XFRM";
-	    break;
-#endif	/* defined(NETLINK_XFRM) */
-
-#if	defined(NETLINK_SELINUX)
-	case NETLINK_SELINUX:
-	    cp = "SELINUX";
-	    break;
-#endif	/* defined(NETLINK_SELINUX) */
-
-#if	defined(NETLINK_ISCSI)
-	case NETLINK_ISCSI:
-	    cp = "ISCSI";
-	    break;
-#endif	/* defined(NETLINK_ISCSI) */
-
-#if	defined(NETLINK_AUDIT)
-	case NETLINK_AUDIT:
-	    cp = "AUDIT";
-	    break;
-#endif	/* defined(NETLINK_AUDIT) */
-
-#if	defined(NETLINK_FIB_LOOKUP)
-	case NETLINK_FIB_LOOKUP:
-	    cp = "FIB_LOOKUP";
-	    break;
-#endif	/* defined(NETLINK_FIB_LOOKUP) */
-
-#if	defined(NETLINK_CONNECTOR)
-	case NETLINK_CONNECTOR:
-	    cp = "CONNECTOR";
-	    break;
-#endif	/* defined(NETLINK_CONNECTOR) */
-
-#if	defined(NETLINK_NETFILTER)
-	case NETLINK_NETFILTER:
-	    cp = "NETFILTER";
-	    break;
-#endif	/* defined(NETLINK_NETFILTER) */
-
-#if	defined(NETLINK_IP6_FW)
-	case NETLINK_IP6_FW:
-	    cp = "IP6_FW";
-	    break;
-#endif	/* defined(NETLINK_IP6_FW) */
-
-#if	defined(NETLINK_DNRTMSG)
-	case NETLINK_DNRTMSG:
-	    cp = "DNRTMSG";
-	    break;
-#endif	/* defined(NETLINK_DNRTMSG) */
-
-#if	defined(NETLINK_KOBJECT_UEVENT)
-	case NETLINK_KOBJECT_UEVENT:
-	    cp = "KOBJECT_UEVENT";
-	    break;
-#endif	/* defined(NETLINK_KOBJECT_UEVENT) */
-
-#if	defined(NETLINK_GENERIC)
-	case NETLINK_GENERIC:
-	    cp = "GENERIC";
-	    break;
-#endif	/* defined(NETLINK_GENERIC) */
-
-#if	defined(NETLINK_SCSITRANSPORT)
-	case NETLINK_SCSITRANSPORT:
-	    cp = "SCSITRANSPORT";
-	    break;
-#endif	/* defined(NETLINK_SCSITRANSPORT) */
-
-#if	defined(NETLINK_ECRYPTFS)
-	case NETLINK_ECRYPTFS:
-	    cp = "ECRYPTFS";
-	    break;
-#endif	/* defined(NETLINK_ECRYPTFS) */
-
-#if	defined(NETLINK_RDMA)
-	case NETLINK_RDMA:
-	    cp = "RDMA";
-	    break;
-#endif	/* defined(NETLINK_RDMA) */
-
-#if	defined(NETLINK_CRYPTO)
-	case NETLINK_CRYPTO:
-	    cp = "CRYPTO";
-	    break;
-#endif	/* defined(NETLINK_CRYPTO) */
-
-#if	defined(NETLINK_SMC)
-	case NETLINK_SMC:
-	    cp = "SMC";
-	    break;
-#endif	/* defined(NETLINK_SMC) */
-	}
-
-	return cp;
-}
-
-/*
- * Sockss2str() -- convert socket state number to a string
- *
- * returns "UNKNOWN" for unknown state.
- */
-#if	defined(HASSOSTATE)
-static char *
-sockss2str(unsigned int ss)
-{
-	char *sr;
-	switch (Lf->lts.ss) {
-	case SS_UNCONNECTED:
-	    sr = "UNCONNECTED";
-	    break;
-	case SS_CONNECTING:
-	    sr = "CONNECTING";
-	    break;
-	case SS_CONNECTED:
-	    sr = "CONNECTED";
-	    break;
-	case SS_DISCONNECTING:
-	    sr = "DISCONNECTING";
-	    break;
-	default:
-	    sr = "UNKNOWN";
-	    break;
-	}
-	return sr;
-}
-#endif	/* defined(HASSOSTATE) */
diff --git a/dialects/linux/dstore.c b/dialects/linux/dstore.c
deleted file mode 100644
index dd32ad3..0000000
--- a/dialects/linux/dstore.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * dstore.c - Linux global storage for /proc-based lsof
- */
-
-
-/*
- * 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 1997 Purdue Research Foundation.\nAll rights reserved.\n";
-#endif
-
-
-#include "lsof.h"
-
-int HasNFS = 0;				/* NFS mount point status:
-					 *     1 == there is an NFS mount point,
-					 *          but its device number is
-					 *          unknown
-					 *     2 == there is an NFS mount point
-					 *          and its device number is
-					 *          known
-					 */
-dev_t MqueueDev = -1;			/* The number for the device behind
-					 * mqueue mount point */
-int OffType = 0;			/* offset type:
-					 *     0 == unknown
-					 *     1 == lstat's st_size
-					 *     2 == from /proc/<PID>/fdinfo */
-
-/*
- * Pff_tab[] - table for printing file flags
- */
-
-struct pff_tab Pff_tab[] = {
-	{ (long)O_WRONLY,	FF_WRITE	},
-	{ (long)O_RDWR,		FF_RDWR		},
-	{ (long)O_CREAT,	FF_CREAT	},
-	{ (long)O_EXCL,		FF_EXCL		},
-	{ (long)O_NOCTTY,	FF_NOCTTY	},
-	{ (long)O_TRUNC,	FF_TRUNC	},
-	{ (long)O_APPEND,	FF_APPEND	},
-	{ (long)O_NDELAY,	FF_NDELAY	},
-	{ (long)O_SYNC,		FF_SYNC		},
-	{ (long)O_ASYNC,	FF_ASYNC	},
-
-#if	defined(O_DIRECT)
-	{ (long)O_DIRECT,	FF_DIRECT	},
-#endif	/* defined(O_DIRECT) */
-
-#if	defined(O_DIRECTORY)
-	{ (long)O_DIRECTORY,	FF_DIRECTORY	},
-#endif	/* defined(O_DIRECTORY) */
-
-#if	defined(O_NOFOLLOW)
-	{ (long)O_NOFOLLOW,	FF_NOFOLNK	},
-#endif	/* defined(O_NOFOLLOW) */
-
-#if	defined(O_NOATIME)
-	{ (long)O_NOATIME,	FF_NOATM	},
-#endif	/* defined(O_NOATIME) */
-
-#if	defined(O_DSYNC)
-	{ (long)O_DSYNC,	FF_DSYNC	},
-#endif	/* defined(O_DSYNC) */
-
-#if	defined(O_RSYNC)
-	{ (long)O_RSYNC,	FF_RSYNC	},
-#endif	/* defined(O_RSYNC) */
-
-#if	defined(O_LARGEFILE)
-# if	O_LARGEFILE==0
-	{ (long)0100000,	FF_LARGEFILE	},
-# else	/* O_LARGEFILE!=0 */
-	{ (long)O_LARGEFILE,	FF_LARGEFILE	},
-# endif	/* O_LARGEFILE==0 */
-#else	/* !defined(O_LARGEFILE) */
-	{ (long)0100000,	FF_LARGEFILE	},
-#endif	/* defined(O_LARGEFILE) */
-
-#if	defined(O_CLOEXEC)
-	{ (long)O_CLOEXEC,	POF_CLOEXEC	},
-#endif	/* defined(O_CLOEXEC) */
-
-#if	defined(O_PATH)
-	{ (long)O_PATH,	FF_PATH	},
-#endif	/* defined(O_PATH) */
-
-#if	defined(O_TMPFILE)
-	{ (long)O_TMPFILE,	FF_TMPFILE	},
-#endif	/* defined(O_TMPFILE) */
-
-	{ (long)0,		NULL		}
-};
-
-
-/*
- * Pof_tab[] - table for print process open file flags
- */
-
-struct pff_tab Pof_tab[] = {
-	{ (long)0,		NULL		}
-};
diff --git a/dialects/linux/tests/case-20-open-flags-cx.bash b/dialects/linux/tests/case-20-open-flags-cx.bash
deleted file mode 100755
index 39650b0..0000000
--- a/dialects/linux/tests/case-20-open-flags-cx.bash
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/bash
-
-pat=".*DIR[ \t]\+.*CX.*[ \t]\+.*/tmp$"
-source $3/util-open-flags.bash "$@" "$pat" /tmp cx
diff --git a/dialects/linux/tests/case-20-open-flags-path.bash b/dialects/linux/tests/case-20-open-flags-path.bash
deleted file mode 100755
index 360c4c7..0000000
--- a/dialects/linux/tests/case-20-open-flags-path.bash
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/sh
-
-pat=".*DIR[ \t]\+.*PATH.*[ \t]\+.*/tmp$"
-source $3/util-open-flags.bash "$@" "$pat" /tmp path
diff --git a/dialects/linux/tests/case-20-open-flags-tmpf.bash b/dialects/linux/tests/case-20-open-flags-tmpf.bash
deleted file mode 100755
index e8f8edd..0000000
--- a/dialects/linux/tests/case-20-open-flags-tmpf.bash
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/bash
-
-pat=".*REG[ \t]\+.*TMPF.*/tmp/.*$"
-source $3/util-open-flags.bash "$@" "$pat" /tmp tmpf rdwr
diff --git a/dialects/linux/tests/epoll.c b/dialects/linux/tests/epoll.c
deleted file mode 100644
index 63a39d8..0000000
--- a/dialects/linux/tests/epoll.c
+++ /dev/null
@@ -1,56 +0,0 @@
-#include <stdio.h>
-#include <sys/epoll.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-int
-main(int argc, char **argv)
-{
-  int epfd = epoll_create (1);
-  if (epfd < 0)
-    {
-      perror ("epoll_create");
-      return 1;
-    }
-
-  struct epoll_event ev;
-  int fd[2];
-  if (pipe(fd) < 0)
-  if (fd < 0)
-    {
-      perror ("pipe");
-      return 1;
-    }
-  if (dup2(fd[0], 5) < 0)
-    {
-      perror ("dup2(fd[0], 5)");
-      return 1;
-    }
-  if (dup2(fd[1], 6) < 0)
-    {
-      perror ("dup2(fd[1], 6)");
-      return 1;
-    }
-
-  ev.events = EPOLLOUT;
-  ev.data.fd = 6;
-  if (epoll_ctl (epfd, EPOLL_CTL_ADD, ev.data.fd, &ev) < 0)
-    {
-      perror ("epoll_ctl<6>");
-      return 1;
-    }
-
-  ev.events = EPOLLIN;
-  ev.data.fd = 5;
-  if (epoll_ctl (epfd, EPOLL_CTL_ADD, ev.data.fd, &ev) < 0)
-    {
-      perror ("epoll_ctl<5>");
-      return 1;
-    }
-
-  printf ("%d %d\n", getpid(), epfd);
-  fflush (stdout);
-  pause ();
-  return 0;
-}
diff --git a/dialects/linux/tests/eventfd.c b/dialects/linux/tests/eventfd.c
deleted file mode 100644
index f22099e..0000000
--- a/dialects/linux/tests/eventfd.c
+++ /dev/null
@@ -1,33 +0,0 @@
-#include <sys/eventfd.h>
-#include <sys/wait.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdio.h>
-
-static int fd = -1;
-
-int
-main(int argc, char **argv)
-{
-	fd = eventfd (0, 0);
-	if (fd < 0)
-	{
-		perror ("eventfd");
-		return -1;
-	}
-
-	pid_t pid = fork();
-	if (pid < 0)
-	{
-		perror ("fork");
-		return -1;
-	} else if (pid == 0) {
-		pause ();
-	} else {
-		printf("%d %d %d\n", getpid (), pid, fd);
-		fflush (stdout);
-		wait (NULL);
-	}
-	return 0;
-}
diff --git a/dialects/linux/tests/mq_fork.c b/dialects/linux/tests/mq_fork.c
deleted file mode 100644
index 0c9a418..0000000
--- a/dialects/linux/tests/mq_fork.c
+++ /dev/null
@@ -1,51 +0,0 @@
-#include <fcntl.h>           /* For O_* constants */
-#include <sys/stat.h>        /* For mode constants */
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <mqueue.h>
-#include <unistd.h>
-#include <stdio.h>
-
-int
-main(int argc, char **argv)
-{
-  int pid;
-  char *fname;
-
-  if (argc != 2)
-    {
-      fprintf(stderr, "wrong number of arguments: %d\n", argc);
-      return 1;
-    }
-  else if (argv[1][0] != '/')
-    {
-      fprintf(stderr, "name must starts with '/': %c\n", argv[1][0]);
-      return 1;
-    }
-
-  fname = argv[1];
-  mqd_t t = mq_open(fname, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR, NULL);;
-
-  if (t == -1)
-    {
-      perror("mq_open");
-      return 1;
-    }
-
-  pid = fork();
-  if (pid == 0)
-    pause();
-  else if (pid > 0)
-    {
-      printf("%d %d %d\n", getpid(), pid, t);
-      fflush(stdout);
-      wait (NULL);
-      mq_unlink(fname);
-    }
-  else
-    {
-      perror("fork");
-      return 1;
-    }
-  return 0;
-}
diff --git a/dialects/linux/tests/mq_open.c b/dialects/linux/tests/mq_open.c
deleted file mode 100644
index 703b220..0000000
--- a/dialects/linux/tests/mq_open.c
+++ /dev/null
@@ -1,31 +0,0 @@
-#include <fcntl.h>           /* For O_* constants */
-#include <sys/stat.h>        /* For mode constants */
-#include <mqueue.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <signal.h>
-
-#define NAME "/xxx"
-
-static void
-do_nothing(int n)
-{
-  signal(SIGCONT, do_nothing);
-}
-
-int
-main(void)
-{
-  mqd_t t = mq_open(NAME, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR, NULL);;
-  if ((mqd_t)t == -1)
-    {
-      perror("open[" NAME "]");
-      return 1;
-    }
-
-  printf("pid: %d / fd: %d\n", getpid(), t);
-  fflush(stdout);
-  signal(SIGCONT, do_nothing);
-  pause();
-  return 0;
-}
diff --git a/dialects/linux/tests/open_with_flags.c b/dialects/linux/tests/open_with_flags.c
deleted file mode 100644
index 2dc90ef..0000000
--- a/dialects/linux/tests/open_with_flags.c
+++ /dev/null
@@ -1,69 +0,0 @@
-#define _GNU_SOURCE
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include <string.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <stdio.h>
-
-struct {
-	const char *name;
-	int flag;
-} table [] = {
-	{ "path", O_PATH },
-	{ "cx",   O_CLOEXEC },
-	{ "tmpf", O_TMPFILE },
-	{ "rdwr", O_RDWR },
-};
-
-#define TABLELEN sizeof(table)/sizeof(table[0])
-
-static int
-encode(const char* const s)
-{
-	for (int i = 0; i < TABLELEN; i++)
-		if (!strcmp (s, table[i].name))
-			return table[i].flag;
-	return 0;
-}
-
-static void
-print_usage(FILE *fp, const char *const prog)
-{
-	fprintf(fp, "Usage:\n");
-	fprintf(fp, "	%s FILENAME FLAG ...\n", prog);
-	fprintf(fp, "Flags:\n");
-	for (int i = 0; i < TABLELEN; i++)
-		fprintf(fp, "	%s\n", table[i].name);
-}
-
-int
-main(int argc, char **argv)
-{
-
-	if (argc < 3) {
-		fprintf(stderr, "Too few argument\n");
-		print_usage (stderr, argv[0]);
-		return 1;
-	}
-
-	char *fname = argv[1];
-	int flags = 0;
-
-	for (int i = 2; i < argc; i++)
-		flags |= encode(argv[i]);
-
-	int fd = open (fname, flags);
-	if (fd < 0) {
-		perror("open");
-		return 1;
-	}
-
-	printf ("%d\n", getpid());
-	fflush (stdout);
-	pause ();
-	return 0;
-}
diff --git a/dialects/linux/tests/pidfd.c b/dialects/linux/tests/pidfd.c
deleted file mode 100644
index 3149b2a..0000000
--- a/dialects/linux/tests/pidfd.c
+++ /dev/null
@@ -1,30 +0,0 @@
-#define _GNU_SOURCE
-#include <sys/types.h>
-#include <sys/syscall.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <errno.h>
-
-#ifndef __NR_pidfd_open
-#define __NR_pidfd_open 434   /* System call # on most architectures */
-#endif
-
-int
-main(void)
-{
-  pid_t self = getpid();
-  int pidfd = syscall(__NR_pidfd_open, self, 0);
-  if (pidfd < 0)
-    {
-      if (errno == ENOSYS)
-	{
-	  printf("%d %d\n", -1, -1);
-	}
-      perror("pidfd_open");
-      return 1;
-    }
-  printf("%d %d\n\n\n", self, pidfd);
-  fclose (stdout);
-  pause();
-  return 0;
-}
diff --git a/dialects/linux/tests/pipe.c b/dialects/linux/tests/pipe.c
deleted file mode 100644
index 175c5b2..0000000
--- a/dialects/linux/tests/pipe.c
+++ /dev/null
@@ -1,47 +0,0 @@
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <string.h>
-
-int
-main(int argc, char **argv)
-{
-  int no_close = 0;
-
-  if (argc > 1 && strcmp (argv[1], "no-close") == 0)
-    no_close = 1;
-
-  int pd[2];
-
-  if (pipe (pd) < 0)
-    {
-      perror("pipe");
-      return 1;
-    }
-
-  pid_t self, child;
-
-  self = getpid();
-  child = fork();
-
-  if (child == 0)
-    {
-      if (!no_close)
-	close (pd[0]);
-      pause ();
-      return 0;
-    }
-  else if (child < 0)
-    {
-      perror("fork");
-      return 1;
-    }
-
-  if (!no_close)
-    close (pd[1]);
-  printf("%d %d %d %d\n", self, child, pd[0], pd[1]);
-  fflush(stdout);
-  wait (NULL);
-  return 0;
-}
diff --git a/dialects/linux/tests/pty.c b/dialects/linux/tests/pty.c
deleted file mode 100644
index 33b836b..0000000
--- a/dialects/linux/tests/pty.c
+++ /dev/null
@@ -1,52 +0,0 @@
-#include <fcntl.h>
-#include <stdio.h>
-#include <error.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-#include <sys/wait.h>
-
-int
-main(void)
-{
-  int tfd[2];
-  int s;
-
-  if ((tfd[0] = open("/dev/ptmx", O_RDONLY)) < 0)
-    error (1, errno, "failed to open ptmx");
-
-  int unlock = 0;
-  if (ioctl(tfd[0], TIOCSPTLCK, &unlock) < 0)
-    error (1, errno, "failed to do ioctl TIOCSPTLCK");
-
-  if (ioctl(tfd[0], TIOCGPTN, &s) < 0)
-    error (1, errno, "failed to do ioctl TIOCGPTN");
-
-  char slave_name [128];
-  snprintf(slave_name, 128, "/dev/pts/%d", s);
-  if ((tfd[1] = open(slave_name, O_RDONLY)) < 0)
-    error (1, errno, "failed to open %s", slave_name);
-
-  pid_t self, child;
-  self = getpid();
-  child = fork();
-
-  if (child == 0)
-    {
-      if (dup2(tfd[1], tfd[0]) < 0)
-	error (1, errno, "failed to dup2(%d, %d)", tfd[1], tfd[0]);
-      close (tfd[1]);
-      pause();
-      return 0;
-    }
-  else if (child < 0)
-    {
-      perror("fork");
-      return 1;
-    }
-
-  printf("%d %d %d %d %d\n", self, child, tfd[0], tfd[1], s);
-  fflush(stdout);
-  wait (NULL);
-  return 0;
-}
diff --git a/dialects/linux/tests/util-open-flags.bash b/dialects/linux/tests/util-open-flags.bash
deleted file mode 100644
index 48109db..0000000
--- a/dialects/linux/tests/util-open-flags.bash
+++ /dev/null
@@ -1,41 +0,0 @@
-lsof=$1
-report=$2
-tdir=$3
-dialect=$4
-pat=$5
-tfile=$6
-
-shift 6
-
-TARGET=$tdir/open_with_flags
-if ! [ -x $TARGET ]; then
-    echo "target executable ( $TARGET ) is not found" >> $report
-    exit 1
-fi
-
-export LC_ALL=C
-
-$TARGET $tfile "$@" 2>> $report | {
-    read pid
-
-    if  [[ -z "$pid" ]]; then
-	if grep -q 'open: Operation not supported' $report; then
-	    echo "a flag passed to open is not supported on this platform" >> $report
-	    exit 2
-	fi
-	echo "unexpected output form target ( $TARGET )" >> $report
-	exit 1
-    fi
-    if ! [ -e "/proc/$pid" ]; then
-	echo "the target process dead unexpectedly" >> $report
-	exit 1
-    fi
-
-    echo "expected: $pat" >> $report
-    echo "lsof output:" >> $report
-    $lsof +fg -p $pid | tee -a $report | grep -q "$pat"
-    result=$?
-
-    kill $pid
-    exit $result
-}
diff --git a/dialects/linux/tests/ux.c b/dialects/linux/tests/ux.c
deleted file mode 100644
index d1fc4c9..0000000
--- a/dialects/linux/tests/ux.c
+++ /dev/null
@@ -1,154 +0,0 @@
-#define _POSIX_SOURCE
-#include <sys/types.h>
-#include <unistd.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <signal.h>
-
-#define TEMPLATE "/tmp/lsof-test-ux-%ld.s"
-
-static void
-do_nothing(int n)
-{
-}
-
-int
-main(void)
-{
-  int rendezvous[2];
-  if (pipe(rendezvous) < 0)
-    {
-      perror("pipe");
-      return 1;
-    }
-
-  pid_t pid = fork();
-  if (pid > 0)
-    {
-      close (rendezvous[0]);
-      /* parent: server */
-      int server = socket(AF_UNIX, SOCK_STREAM, 0);
-      if (server < 0)
-	{
-	  perror("socket (server)");
-	  return 1;
-	}
-      struct sockaddr_un un = {
-			       .sun_family = AF_UNIX,
-      };
-      snprintf (un.sun_path, 108, TEMPLATE, (long int)getpid());
-      unlink (un.sun_path);
-
-      if (bind (server, (void *)&un, sizeof (un)) < 0)
-	{
-	  perror("bind (server)");
-	  return 1;
-	}
-      if (listen(server, 0) < 0)
-	{
-	  perror("listen (server)");
-	  return 1;
-	}
-
-      char b = 1;
-      if (write(rendezvous[1], &b, 1) < 0)
-	{
-	  perror("write rendezvous pipe (server)");
-	  return 1;
-	}
-      b++;
-
-      int client;
-      if ((client = accept(server, NULL, 0)) < 0)
-	{
-	  perror("listen (server)");
-	  return 1;
-	}
-
-      char buf[1024];
-      if (read(client, buf, 1024) < 0)
-	{
-	  perror("read (server)");
-	  return 1;
-	}
-
-      fputs(buf, stdout);
-      printf("ppid %ld\nlisten %d\naccept %d\npath %s\n",
-	     (long int)getpid(), server, client, un.sun_path);
-      fputs("end\n", stdout);
-      fflush(stdout);
-      signal(SIGCONT, do_nothing);
-      pause ();
-
-      unlink (un.sun_path);
-      write(rendezvous[1], &b, 1);
-      b++;
-
-      return 0;
-    }
-  else if (pid == 0)
-    {
-      char b;
-      /* child: client */
-      close(rendezvous[1]);
-      if (read(rendezvous[0], &b, 1) < 0)
-	{
-	  perror("read rendezvous pipe (client)");
-	  /* TODO: kill the parent process. */
-	  return 1;
-	}
-
-      int server = socket(AF_UNIX, SOCK_STREAM, 0);
-      if (server < 0)
-	{
-	  perror("socket (client)");
-	  return 1;
-	}
-
-      struct sockaddr_un un = {
-			       .sun_family = AF_UNIX,
-      };
-      snprintf (un.sun_path, 108, TEMPLATE, (long int)getppid());
-      if (connect(server, (void *)&un, sizeof(un)) < 0)
-	{
-	  perror("connect (client)");
-	  return 1;
-	}
-
-      FILE *serverf = fdopen(server, "w");
-      if (!serverf)
-	{
-	  perror("fdopen (client)");
-	  return 1;
-	}
-
-      int server2 = socket(AF_UNIX, SOCK_STREAM, 0);
-      if (server2 < 0)
-	{
-	  perror("socket (client)");
-	  return 1;
-	}
-      if (connect(server2, (void *)&un, sizeof(un)) < 0)
-	{
-	  perror("connect (client (server2))");
-	  return 1;
-	}
-
-      fprintf(serverf, "pid %ld\nconnect %d\nconnect2 %d\n", (long int)getpid(), server, server2);
-      putc('\0', serverf);
-      fflush(serverf);
-
-      if (read(rendezvous[0], &b, 1) < 0)
-	{
-	  perror("read rendezvous pipe (client)");
-	  return 1;
-	}
-      return 0;
-    }
-
-  perror("fork");
-  return 1;
-}
diff --git a/docs/contributing.md b/docs/contributing.md
new file mode 100644
index 0000000..02d0eda
--- /dev/null
+++ b/docs/contributing.md
@@ -0,0 +1,68 @@
+# Contributing
+
+You can contribute to lsof via pull requests at [GitHub](https://github.com/lsof-org/lsof).
+
+## Commit message
+
+If a change is dialect specific, use `[dialect]` as the prefix of the
+header of the commit log like:
+
+	[linux] compile with -Wall option
+	[linux] delete unused variables
+	[freebsd] cirrus-ci: disabled
+
+If no `[dialect]` prefix is given to a commit, the change may have an impact
+across dialects.
+
+## Code style
+
+C sources should be formatted by `clang-format`, e.g.:
+
+```shell
+clang-format -i lib/dialcets/linux/dsock.c
+# or
+git-clang-format
+```
+
+The formatter may not function properly in some corner cases. You will have to
+rewrite the code to make it happy.
+
+Use as few #if/#else/#endif constructs as possible, even at
+the cost of nearly-duplicate code.
+
+When #if/#else/#endif constructs are necessary:
+
+Use the form
+
+```c
+#if defined(s<symbol>)
+```
+
+in preference to
+
+```c
+#ifdef <symbol>
+```
+
+to allow easier addition of tests to the #if.
+
+- Indent them to signify their level -- e.g.,
+
+```c
+#if		/* level one */
+#  if		/* level two */
+#  endif	/* level two */
+#else		/* level one */
+#endif		/* level one */
+```
+
+Use ANSI standard comments on #else and #endif statements.
+
+## Testing
+
+There are two test mechanism, the original one by Via Abell and a script-based
+one by Masatake YAMATO. About the original test mechanism, see tests/00README.
+About the script-based test mechanism, see tests/case-00-hello.bash and
+check.bash.
+
+Your pull request should pass all CI checks. If necessary, you can modify testcases.
\ No newline at end of file
diff --git a/docs/credits.md b/docs/credits.md
new file mode 100644
index 0000000..e805d51
--- /dev/null
+++ b/docs/credits.md
@@ -0,0 +1,603 @@
+## Credits
+
+I owe an enormous debt to the users of lsof who have contributed
+to its steady growth.  The size of the list of people who have
+helped me, while it has grown too large to include in the lsof man
+page any more, is a testimonial to their generosity.
+
+First I acknowledge a debt to the work of Dan Bernstein, Michael
+`Ford` Ditto, Tom Dunigan, Alexander Dupuy, Vik Lall, Ray Moody,
+C. Spencer, Michael Spitzer and those who wrote Berkeley's fstat
+program, all contributors to lsof's predecessors.
+
+I thank Doug McKenzie for his HP-UX proctor program and Rich Kulawiec
+for pointing it out.
+
+Finally I thank all the following people who have used lsof, pointed
+out its flaws, described its shortcomings, offered suggestions for
+improving it, supplied code for it, gave me technical advice, and
+provided test systems where I was able to do development work.
+
+	Szilveszter Adam
+	David Addison
+	Elias Halldor Agustsson
+	Per Allansson
+	Jim Ankenbrandt
+	Richard Allen
+	Thomas Anders
+	Ric Anderson
+	Stuart Anderson
+	Dimitry Andric
+	Michael Antlitz
+	Cato Auestad
+	Marc Auslander
+	Tigran Aivazian
+	Jos Backus
+	David Bacon
+	Alexis Ballier
+	Scott Ballew
+	Ade Barkah
+	Alon Bar-Lev
+	Brett Bartick
+	Anthony Baxter
+	John Beacom
+	Bruce Beare
+	M. Jay Beck
+	Marek Behun
+	Bill Behr
+	Michael Beirne
+	Marc Bejarano
+	Andrew Bell
+	Steve Bellenot
+	Robert Benites
+	Dmitry Berezin
+	Ulrich Bernhard
+	Peter J. Bertoncini
+	Dave Bianchi
+	Mark Bixby
+	Allan Black
+	Jan Blunck
+	Achim Bohnet
+	Steve Bonds
+	Mark Bonsack
+	Volker Borchert
+	Bill Bormann
+	Ermin Borovac
+	Heddy Boubaker
+	Pieter Bowman
+	Michael Bracewell
+	H. Merijn Brand
+	Danny Braniss
+	Thomas Braunbeck
+	Kieran Broadfoot
+	Dean Brock
+	Hal Brooks
+	Andrew Brown
+	Jim Brown
+	Michael Bryan
+	Matthew Burt
+	Robert Byrnes
+	Pierfrancesco Caci
+	Bill Campbell
+	David Capshaw
+	John Caruso
+	Jon Champlin
+	Kris Chandrasekhar
+	Stephane Chazelas
+	Andrey Chernov
+	Albert Chin-A-Young
+	Bernt Christandl
+	Marc Christensen
+	Hans Petter Christiansen
+	Tom Christiansen
+	Yves Christophe
+	Richard Chycoski
+	A. Channing Clark
+	Jorn Clausen
+	Axel Clauberg
+	John Clear
+	David Clissold
+	Richard Coley
+	John Colgrave
+	David Comay
+	Lionel Cons
+	Bob Cook
+	Patrick Connor
+	Carl Cook
+	Jim Cooper
+	Roger Cornelius
+	Doug Crabill
+	Eric Cronin
+	Kim Culhan
+	Dave Curry
+	Robert Dahlem
+	Guy Dallaire
+	D. Chris Daniels
+	Renata Maria Dart
+	Ian Darwin
+	Carl E. Davidson
+	David Day
+	Will Day
+	Frederic Delanoy
+	Mike Depot
+	Steve Dibbell
+	Hugh Dickins
+	David DiGiacomo
+	Casper Dik
+	John DiMarco
+	Don Draper
+	Bryan Drewery
+	Michel Dubois
+	Eric Dumazet
+	Dick Dunbar
+	Marc Duponcheel
+	Jan Dvorak
+	Calle Dybedahl
+	John Dzubera
+	Jeff Earickson
+	Greg Earle
+	Bernd Eckenfels
+	Niklas Edmundsson
+	Philip Edwards
+	Robert Ehrlich
+	Mark W. Eichin
+	Doug Eldred
+	Scott Ellentuch
+	Tom Endo
+	Grant Erickson
+	Craig Everhart
+	Chris Evert
+	Bob Farmer
+	Sami Farin
+	Mike Feldman
+	Quentin Fennessy
+	Ian Fitchet
+	Toralf Foerster
+	Bob Foertsch
+	Pierre-Yves Fontaniere
+	Ralph Forsythe
+	Jason Fortezzo
+	Mike Fraser
+	Curt Freeland
+	Terry Friedrichsen
+	Mike Frysinger
+	Harvey Garner
+	Carson Gaspar
+	Stuart D. Gathman
+	Brian L. Gentry
+	Dave Gilbert
+	Steve Ginsberg
+	Bjarni Ingi Gislason
+	Edwin Groothuis
+	Jin Guojun
+	Kurt Gollhardt
+	Roman Gollent
+	Steve Gonczi
+	Bill Goodridge
+	Julian Gordon
+	Marcin Gozdalik
+	Henry Grebler
+	Richard Green
+	Chaskiel Grundman
+	Armin Gruner
+	David Gutierrez
+	Mateusz Guzik
+	Robert Hall
+	Garner Halloran
+	Adam Hammer
+	Charles Hannum
+	Vlad Harchev
+	Craig Harmer
+	Michael Haro
+	Peter Harvey
+	Steinar Haug
+	Jia He
+	Sheldon Hearn
+	John Heasley
+	Wolfgang Hecht
+	Janet Hempstead
+	Michael Hennecke
+	Randolph J. Herber
+	Allen Hewes
+	Andrew Hill
+	Kurt Hillig
+	Steven Hinkle
+	Paul Hite
+	Billy Ho
+	Michael Hocke
+	Brett Hogden
+	Gaylord Holder
+	Kjetil Torgrim Homme
+	Pekka Honkanen
+	Jeffrey C. Honig
+	Heidi Hornstein
+	Michael A. Hovan III
+	Barbara Howe
+	J. Nelson Howell
+	Jeff Howie
+	Louis Huemiller
+	John Hughes
+	Gerrit Huizenga
+	Peter Ilieve
+	Mayer Ilovitz
+	Gregory A. Ivanov
+	John Jackson
+	Kurt Jaeger
+	Edward Jajko
+	Marian Jancar
+	Paul Jarc
+	Jakub Jelinek
+	Robert Jelinek
+	Bruce Jerrick
+	Carl Johnson
+	Dion Johnson
+	Jeff Johnson
+	Douglas B. Jones
+	LaMont Jones
+	Peter Jordan
+	Arne H. Juul
+	Pasi Kaara
+	Frank Kaefer
+	Keith Kalet
+	Claus Kalle
+	Henri Karrenbeld
+	Amir Katz
+	Henry Katz
+	Kawaljeet Kaur
+	Doug Kehn
+	Kris Kennaway
+	Terry Kennedy
+	Shane Kenney
+	Andrew Kephart
+	Robert Kiessling
+	Joshua Kinard
+	Don Kirouac
+	Steve Kirsch
+	Philip Kizer
+	Thomas Klausner
+	Ronald Klop
+	Roger Klorese
+	Peter Klosky
+	Przemek Klosowski
+	Angelos D. Keromytis
+	Radko Keves
+	Valdis Kletnieks
+	Chris Kordish
+	Alek O. Komarnitsky
+	Joseph Kowalski
+	Christian Krackowizer
+	Paul Kranenburg
+	Troyan Krastev
+	Brad Krebs
+	Alex Kreis
+	Johannes Kroeger
+	Vincent Kujala
+	Ken Laing
+	Shirley Lam
+	Erwin Lansing
+	Victoria H. Lau
+	Markus Lautenbacher
+	Steve Lacey
+	Marc Aurele La France
+	Chad R. Larson
+	Steve Laubscher
+	Andrei V. Lavreniyuk
+	Loc Le
+	Tin Le
+	Diane Lebel
+	Francis Le Bourse
+	Kyungjoon Lee
+	Marty Leisner
+	Maciej Lesniewski
+	Stuart Levy
+	Ben Lewis
+	Michael Lewis
+	Angel Li
+	Ambrose Li
+	Wendy Lin
+	Carl E. Lindberg
+	Onno van der Linden
+	Johan Lindquist
+	James Lingard
+	Jason Lingohr
+	Robert Lipe
+	Gabor Liptak
+	Friedel Loinger
+	Michael Long
+	Pete Lord
+	Steve Logue
+	Bela Lubkin
+	Pav Lucistnik
+	Horst Luehrsen
+	Andreas Luik
+	Timothy J. Luoma
+	Michael Mackenzie
+	Lawrence MacIntyre
+	Jerome Marchand
+	Benson Margulies
+	Claude Marinier
+	Chris Markle
+	Roy Marples
+        Ed Maste
+	Eberhard Mater
+	James Mathiesen
+	Tom Matthews
+	Fletcher Mattox
+	David Mazieres
+	Brian McAllister
+	Scott McClung
+	Dale McCluskey
+	Terry McCoy
+	Sean McDermott
+	Duncan McEwan
+	Dwight McKay
+	William McVey
+	Eric McWhorter
+	Marjo F. Mercado
+	Dan Mercer
+	Bill Melvin
+	Andrew Merril
+	Richard van Meurs
+	Jim Mewes
+	Ivan Melnikov
+	Conrad Meyer
+	Hendrik Meyer
+	Gary Millen
+	Timothy Miller
+	Davin Milun
+	Yuliy Minchev
+	Jim Mintha
+	Mike Miscevic
+	Arkadiusz Miskiewicz
+	Janardhan Molumuri
+	Nasser Momtaheni
+	Laurent Montaron
+	Doug Moore
+	Phillip Moore
+	Dmitry Morozovsky
+	John Paul Morrison
+	John Gardiner Myers
+	Jeffrey Mogul
+	Dave Morrison
+	Pat Myrto
+	Toshiya Nakamura
+	Filippo Natali
+	Allan Nathanson
+	Chance Neale
+	Dan Nelson
+	Vladislav Nespor
+	Bjorn S. Nilsson
+	Anders Nordby
+	Joseph J. Nuspl Jr.
+	David O'Brien
+	Alexandre Oliva
+	Craig B. Olofson
+	Dave Olson
+	Rainer Orth
+	Sergey A. Osokin
+	Keith Parks
+	Will Partain
+	Vasco Pedro
+	Mark Peek
+	Ezra Peisach
+	Bill Pemberton
+	Lee Penn
+	Gildas Perrot
+	Jesse Perry
+	Nathan Peterson
+	Dominique Petitpierre
+	Hung Pham
+	Ray Phillips
+	Francois Pinard
+	Gary Plewa
+	Alex Podlecki
+	Lutz Poetschulat,
+	John Polstra
+	Scott Presnell
+	Mark Price
+	Philippe-Andre Prindeville
+	Kristof Provost
+	David Putz
+	Tom Qin
+	Jan Rybar
+	Kurtis Rader
+	Peter Radig
+	Jean-Pierre Radley
+	Tim Ramsey
+	Dewan Rashid
+	Richard J. Rauenzahn
+	Louis Rayman
+	Brian Redman
+	Eric S. Raymond
+	Erwin Reyns
+	Aaron Rhodes
+	Jim Reid
+	Jean-Luc Richier
+	Clint Roberts
+	Ingimar Robertson
+	Sylvain Robitaille
+	Larry Rogers
+	Malgorzata Roos
+	Larry Rosenman
+	Stephan Rossi
+	Kevin Ruderman
+	Wolfgang Rupprecht
+	Pavol Rusnak
+	Eygene Ryabinkin
+	Conrad J. Sabatier
+	Klaus Saggerer
+	Chris Schanzle
+	Igor Schein
+	Horst Scheuermann
+	Peter Schiffer
+	Michael Schmitz
+	Larry Schwimmer
+	Cy Schubert
+	Hendrik G. Seliger
+	Igor V. Semenyuk
+	Jonathan Sergent
+	Frank Sanders
+	Berkley Shands
+	Gregory Neil Shapiro
+	Eyal Shaynis
+	Michael Shields
+	Wesley Shields
+	Philip Shin
+	Anthony Shortland
+	Dave Sill
+	John Silva
+	Chuck Silvers
+	Gerry Singleton
+	Leonard Sitongia
+	Kevin Smallwood
+	Gleb Smirnoff
+	Curt Smith
+	Ben Smithurst
+	Douglas R. Smith
+	Kevin Smith
+	Chang Song
+	Josh Soref
+	John Speno
+	Kenneth Stailey
+	Piet Starreveld
+	David Steiner
+	Charles Stephens
+	Marc Stephenson
+	Chip Stettler
+	Dave Stevens
+	Jeff Stewart
+	Diana Stockdale
+	Andreas Stolcke
+	Jeff Stoner
+	Kristyna Streitova
+	Sushila Subramanian
+	Jan Ole Suhr
+	Mike Sullivan
+	Patrick D. Sullivan
+	Peter Svensson
+	Chris Sylvain
+	Miklos Szeredi
+	Paul Szabo
+	Dale Talcott
+	Jon A. Tankersley
+	Jan Tax
+	Samuel Thibault
+	Andy Thomas
+	Matthew Thurmaier
+	Chris Timmons
+	Andrzej Tobola
+	R. Lindsay Todd
+	Zdenko Tomasic
+	Michael Townsend
+	Linus Torvalds
+	Mike Tracy
+	Jeff Trawick
+	Dan Trinkle
+	Erik Trulsson
+	Lars Tunkrans
+	Lenny Turetsky
+	Kevin Vajk
+	Peter Valchev
+	John R. Vanderpool
+	Peter Van Epp
+	Peter C. Vernam
+	Peter Vines
+	Bob Ward
+	Jules van Weerden
+	Tom Weaver
+	Fernando A.B. Whitaker
+	Tom Whitty
+	Carson Wilson
+	David J. Wilson
+	Frank Winkler
+	Marc Winkler
+	Mark Vasoll
+	Holger VanKoll
+	Robert Vernon
+	Joep Vesseur
+	Larry Virden
+	Jos Vos
+	Jun Biao Wang
+	Christopher J Warweg
+	Bill Watson
+	Florian M. Weps
+	Joel White
+	Paul Wickman
+	Martin Wilke
+	Eric Williams
+	Steve Williams
+	Steve Wilson
+	Erich Wimmer
+	Wally Winzer, Jr.
+	Patrick Wolfe
+	Stephen Woods
+	James Woodward
+	Scott Worley
+	Jan Wortelboer
+	Joshua Wright
+	Sailu Yallapragada
+	Masatake YAMATO
+	Donna Yobs
+	Ron Young
+	Warren Young
+	Blair Zajac
+	Karel Zak
+	Donald Zoch
+	Malcom Zung
+	Waldemar Zurowski
+	@eranik (github account)
+	@jolmg  (github account)
+	yasu@utahime.org (email)
+	jamie@catflap.org (email)
+	@hardikpnsp (github account)
+	Martin D Kealey
+	Henry Peteet
+	@zhrf2020
+	@JustAnotherArchivist
+	@po5857
+	@albert-github
+	Tobias Geerinckx-Rice
+	Andres Salomon
+	Nicholas Bamber
+	Grisha Levit
+	@10ne1 (github account)
+	@a1346054
+	Damjan Jovanovic
+	Fabrice Fontaine
+	Danny Fowler
+	Benny "BenBE" Baumann
+	Robert Geislinger (Alienmaster)
+	Subhaditya Nath
+	Sergei Trofimovich (@trofi)
+	Danilo Spinella (@danyspin97)
+	Jiajie Chen (@jiegec)
+	Jacob Chapman (@chapmanjacobd)
+	Teng Hu (@Hunter1016)
+	Li Zeming (@likunyur)
+	Sam James (@thesamesam)
+	Warner Losh (@bsdimp)
+	Andrew Athan (@aathan)
+	Florian Weimer (@fweimer-rh)
+	Andreas Schwab (@andreas-schwab)
+	@oldmanhere
+	@mjoerg
+	Subhaditya Nath (@subnut)
+	Linjie Li (@uniontech-lilinjie)
+	Clement Martin (@clementmartin)
+	Kalin KOZHUHAROV (@thinrope)
+	Rui Chen (@chenrui333)
+	@AngryLoki
+	Peter Marquardt (@wwwutz)
+	Bjorn Helgaas (@bjorn-helgaas)
+	@OstCollector
+	Jiri Slaby and
+	Marc (@MarT512)
+
+If I have omitted a contributor's name, the fault is wholly mine,
+and I apologize for the error.
+
+Vic Abell <abe@purdue.edu>
+March 27, 2018
+
+Masatake YAMATO <yamato@redhat.com> (since revision 4.92.1)
+October 4, 2020
diff --git a/docs/faq.md b/docs/faq.md
new file mode 100644
index 0000000..abc1eb4
--- /dev/null
+++ b/docs/faq.md
@@ -0,0 +1,3085 @@
+# Frequently Asked Questions
+
+Caveat: most of the FAQ comes from the original lsof, which may be outdated.
+
+## When Lsof Seems to Hang
+
+On occasion when you run lsof it seems to hang and produce no
+output.  This may result from system conditions beyond the control
+of lsof.  Lsof has a number of options that may allow you to
+bypass the blockage.
+
+### Kernel lstat(), readlink(), and stat() Blockages
+
+Lsof uses the kernel (system) calls lstat(), readlink(), and
+stat() to locate mounted file system information.  When a file
+system has been mounted from an NFS server and that server is
+temporarily unavailable, the calls lsof uses may block in the
+kernel.
+
+Lsof will announce that it is being blocked with warning messages
+(unless they have been suppressed by the lsof builder), but
+only after a default waiting period of fifteen seconds has
+expired for each file system whose server is unavailable.  If
+you have a number of such file systems, the total wait may be
+unacceptably long.
+
+You can do two things to shorten your suffering: 1) reduce the
+wait time with the -S option; or 2) tell lsof to avoid the
+kernel calls that might block by specifying the -b option.
+
+```shell
+$ lsof -S 5
+# or
+$ lsof -b
+```
+
+Avoiding the kernel calls that might block may result in the
+lack of some information that lsof needs to know about mounted
+file systems.  Thus, when you use -b, lsof warns that it might
+lack important information.
+
+The warnings that result from using -b (unless suppressed by
+the lsof builder) can themselves be annoying.  You can suppress
+them by adding the -w option.  (Of course, if you do, you won't
+know what warning messages lsof might have issued.)
+
+```shell
+$ lsof -bw
+```
+
+Note: if the lsof builder suppressed warning message issuance,
+you don't need to use -w to suppress them.  You can tell what
+the default state of message warning issuance is by looking at
+the -h (help) output.  If it says `-w enable warnings` then
+warnings are disabled by default; `-w disable warnings`, they
+are enabled by default.
+
+### Problems with /dev or /devices
+
+Lsof scans the /dev or /devices branch of your file system to
+obtain information about your system's devices.  (The scan isn't
+necessary when a device cache file exists.)
+
+Sometimes that scan can take a very long time, especially if
+you have a large number of devices, and if your kernel is
+relatively slow to process the stat() system call on device
+nodes.  You can't do anything about the stat() system call
+speed.
+
+However, you can make sure that lsof is allowed to use its
+device cache file feature.  When lsof can use a device cache
+file, it retains information it gleans via the stat() calls
+on /dev or /devices in a separate file for later, faster
+access.
+
+The device cache file feature is described in the lsof man
+page.  See the DEVICE CACHE FILE, LSOF PERMISSIONS THAT AFFECT
+DEVICE CACHE FILE ACCESS, DEVICE CACHE FILE PATH FROM THE -D
+OPTION, DEVICE CACHE PATH FROM AN ENVIRONMENT VARIABLE,
+SYSTEM-WIDE DEVICE CACHE PATH, PERSONAL DEVICE CACHE PATH
+(DEFAULT), and MODIFIED PERSONAL DEVICE CACHE PATH sections.
+
+There is also a separate file in the lsof distribution, named
+00DCACHE, that describes the device cache file in detail,
+including information about possible security problems.
+
+One final observation: don't overlook the possibility that your
+/dev or /devices tree might be damaged.  See if
+
+```shell
+$ ls -R /dev
+# or
+$ ls -R /devices
+```
+
+completes or hangs.  If it hangs, then lsof will probably hang,
+too, and you should try to discover why ls hangs.
+
+### Host and Service Name Lookup Hangs
+
+Lsof can hang up when it tries to convert an Internet dot-form
+address to a host name, or a port number to a service name.  Both
+hangs are caused by the lookup functions of your system.
+
+An independent check for both types of hangs can be made with
+the netstat program.  Run it without arguments.  If it hangs,
+then it is probably having lookup difficulties.  When you run
+it with -n it shouldn't hang and should report network and port
+numbers instead of names.
+
+Lsof has two options that serve the same purpose as netstat's
+-n option.  The lsof -n option tells it to avoid host name
+lookups; and -P, service name lookups.  Try those options when
+you suspect lsof may be hanging because of lookup problems.
+
+```shell
+$ lsof -n
+# or
+$ lsof -P
+# or
+$ lsof -nP
+```
+
+### UID to Login Name Conversion Delays
+
+By default lsof converts User IDentification (UID) numbers to
+login names when it produces output.  That conversion process
+may sometimes hang because of system problems or interlocks.
+
+You can tell lsof to skip the lookup with the -l option; it
+will then report UIDs in the USER column.
+
+```shell
+$ lsof -l
+```
+
+## General Concepts
+
+### Lsof -- what is it?
+
+Lsof is a UNIX-specific tool.  Its name stands for LiSt
+Open Files, and it does just that.  It lists information
+about files that are open by the processes running on a
+UNIX system.
+
+See the lsof [man page](./manpage.md), the 00DIST file, the
+[tutorial](./tutorial.md) and the README.md file of the lsof distribution for
+more information.
+
+### Where do I get lsof?
+
+Lsof is available at [GitHub lsof-org/lsof](https://github.com/lsof-org/lsof).
+
+You can find the latest releases from [GitHub Releases](https://github.com/lsof-org/lsof/releases)
+
+### Are lsof executable available?
+
+You can install lsof from package managers.
+
+If you must use a binary file, please be conscious of the
+security and configuration implications in using an executable.
+
+Three additional cautions apply to executables:
+
+1.  Don't try to use an lsof executable, compiled for one
+	version of a UNIX dialect, on another.  Patches can
+	make the dialect version different.
+
+2.  If you want to use an lsof binary on multiple systems,
+	they must be running the same dialect OS version and
+	have the same patches and feature support.
+
+### Where can I get more lsof documentation?
+
+A significant set of documentation may be found in the lsof distribution (See
+"Where can I get lsof?).  There is a [manual page](./manpage.md), and a copy of
+this FAQ in the file docs/faq.md (perhaps slightly less recent than this file if
+you're reading it via a web browser.)
+
+Two URLs provide some documentation that appears in the
+lsof distribution:
+
+FAQ: [https://lsof.readthedocs.io/en/latest/faq](https://lsof.readthedocs.io/en/latest/faq)
+
+man page: [https://lsof.readthedocs.io/en/latest/manpage](https://lsof.readthedocs.io/en/latest/manpage)
+
+### How do I report an lsof bug?
+
+If you believe you have discovered a bug in lsof, you can report it to
+https://github.com/lsof-org/lsof.  Do NOT report lsof bugs to the UNIX
+dialect vendor.
+
+Before you send a bug report, please read the "Bug Reports" section of
+the 00README file of the lsof distribution.  It lists the steps you
+should take before and when reporting a suspected bug.
+
+### Where can I get the lsof FAQ?
+
+This lsof FAQ is available in the file 00FAQ in the lsof
+distribution and at the URL:
+
+[https://lsof.readthedocs.io/en/latest/faq/](https://lsof.readthedocs.io/en/latest/faq/)
+
+### How timely is the on-line FAQ?
+
+The on-line FAQ is sometimes too timely.  :-)
+
+I update it as soon as new information is available.   That may include
+information about support that won't appear in the lsof source distribution
+until the next revision.  If you encounter something like that, please file a
+new issue at GitHub. 
+
+### Is there a test suite?
+
+Yes, as of lsof revision 4.63 there's an automated lsof
+test suite in the tests/ sub-directory of the lsof top-level
+directory.
+
+More information on using the test suite, what it does,
+how to use it and how to configure it may be found in the
+00TEST file of the lsof distribution.  That file also
+explains where the test suite has been tested.
+
+Frequently asked questions about the test suite will be
+asked and answered here in the FAQ.  (See "Test Suite
+Problems.")
+
+After lsof has been configured with the Configure script,
+lsof can be made and tested with:
+
+	$ make
+	$ cd tests
+	$ make
+
+Under normal conditions -- i.e., unless the lsof tree has
+been cleaned or purged severely -- all tests or individual
+tests may be run by:
+
+	$ cd test
+	$ make
+	# or
+	$ <run a single test>	(See 00TEST.)
+
+### Is lsof vulnerable to the standard I/O descriptor attack?
+
+Lsof revisions 4.63 and above are not vulnerable.
+
+Lsof revisions 4.62 and below are vulnerable, but no damage
+scenarios have so far been demonstrated.
+
+The standard I/O descriptor attack is a local programmed
+assault on setuid and setgid programs that tricks them into
+opening a sensitive file with write access on a standard
+descriptor, usually stderr (2), and writing error messages
+to stderr.  If the attacker can control the content of the
+error message, the attacker may gain elevated privileges.
+
+The attack was first described in Pine Internet Advisory
+PINE-CERT-20020401, available at:
+
+	http://www.pine.nl/advisories/pine-cert-20020401.txt
+
+If you are using an lsof revision below 4.63, you should
+remove any setuid or setgid permissions you might have
+given its executable.  Then you should upgrade to lsof
+revision 4.63.
+
+### Can I alter lsof's make(1) behavior?
+
+Yes.  There are at least two ways to do that.
+
+You can put replacements for lsof Makefile strings in your
+environment.  If you specify the -e make option, make will
+give environment variable values precedence over strings
+from the Makefile.  For example, to change the compiler
+string CC from the environment, you might do this with the
+Bourne shell:
+
+	$ CC=foobar; export CC
+	$ make -e
+
+You can also replace lsof Makefile strings in the make
+command invocation.  Here's the previous example done that
+way:
+
+	$ make CC=foobar
+
+Changing the CFGF, CFGL, and DEBUG strings used in lsof
+Makefiles, either from the environment or from the make
+invocation, can significantly alter lsof make(1) behavior.
+I commonly use DEBUG to change the -O option to -g so I
+can build an lsof executable for debugging -- e.g.,
+
+	$ make DEBUG=-g
+
+(Look for DEBUG in this FAQ for other examples of its use.)
+
+Consult the Makefiles to see what CFGL, CFGL, and other
+lsof Makefile strings contain, and to see what influence
+their alteration might have on lsof make(1) behavior.
+
+### Is there an lsof license?
+
+No.
+
+The only restriction on the use or redistribution of lsof
+is contained in this copyright statement, found in every
+lsof source file.  (The copyright year in or format of the
+notice may vary slightly.)
+
+	/*
+	 * Copyright 2002 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.
+	 */
+
+### Language locale support
+
+#### Does lsof support language locales?  How do I use the support?
+
+Most UNIX dialect versions of lsof support 8 bit language
+locale characters -- e.g., the ability to print 8 bit
+characters that have accents and other marks over them.
+
+See the answer to the "Does lsof support wide characters in
+language locales?" question for information on when lsof's
+language locale support covers characters wider than 8 bits.
+
+To see if lsof supports language locales for your dialect, look
+in the dialect's machine.h header file for the HASSETLOCALE
+definition.  If it is present and not disabled, then lsof has
+language locale support for the dialect.
+
+To enable lsof's language locale support, you must specify in a
+locale environment variable (e.g., LANG) a language locale
+known to your system that supports the printing of marked
+characters -- e.g, en_US.  (On some dialects locale(1) may be
+used to list the known language locales.)
+
+Note that LANG=C and LANG=POSIX are NOT language locales that
+support the printing of marked characters.
+
+If the language locale doesn't support the printing of marked
+characters, lsof's OUTPUT of them follows the rules for
+non-printable characters described in the OUTPUT section of
+lsof(8).
+
+Consult your dialect's setlocale(3) man page for the names of
+environment variables other than LANG  -- e.g., LC_ALL,
+LC_TYPE, etc. -- which may be used to define language locales.
+
+#### Does lsof support wide characters in language locales?
+
+When lsof's language locale support is enabled with the
+HASSETLOCALE definition, for selected dialects lsof will also
+print wide characters (e.g., from UTF-8) when iswprint(3)
+reports them to be printable.
+
+Wide character support is available when HASWIDECHAR is defined
+in a dialect's machine.h header file.  As of this writing on
+July 22, 2004, the following dialect versions have wide character
+support:
+
+	AIX >= 4.3.2
+	Apple Darwin >= 7.3.0
+	FreeBSD >= 5.2
+	HP-UX >= 11.00
+	/proc-based Linux
+	NetBSD >= 1.6
+	SCO OpenServer >= 5.0.6
+	Solaris >= 2.6
+	Tru64 UNIX 5.1
+
+### Are any files in the lsof distribution copyrighted?
+
+Yes.  Most files carry the copyright of the Purdue Research
+Foundation and may be redistributed under the terms that
+accompany the copyright notice.  Those terms may also be found
+in the answer to the question, "Is there an lsof license?")
+
+A few files carry other copyright notices.  Some are BSD
+notices and they explain the terms under which they are
+included in the lsof distribution.
+
+Those that carry vendor copyright notices have been reproduced
+in their original or modified forms with permission from the
+copyright owners.  That permission is indicated in the README
+files that accompany the files.
+
+### Are there other lsof-related resources?
+
+There are other resources available, connected to lsof.  Among
+them are FreeBSD and Linux packages whose products use lsof and
+two particularly interesting resources.
+
+The two interesting resources are a Gnome Tool Kit (GTK) GUI
+for lsof and a Perl wrapper module.
+
+The GTK GUI is called Glsof and was developed by Gnele.  It can
+be found at:
+
+	http://www.sourceforge.net
+
+The Perl wrapper module by Marc Beyer can be found at:
+
+	http://search.cpan.org/dist/Unix-Lsof/
+
+### What does the "WARNING: unsupported dialect or version" mean?
+
+The lsof configure script issues that message for UNIX dialects
+or their versions where I have been unable to test the current
+revision of lsof.  The message doesn't mean that lsof won't
+work, just that I have no direct evidence that it will.
+
+If the Configure script succeeds, except for the warning, try
+compiling) lsof.  If that succeeds, try the lsof test suite.
+
+## Lsof Ports
+
+### What ports exist?
+
+The pub/lsof.README file carries the latest port information:
+
+	AIX 5.[23] and 5.3
+	FreeBSD 4.9 and 6.4 for x86-based systems
+	FreeBSD 8.[234], 9.0, 10.0 and 11.0 for AMD64-based systems
+	Darwin(macOS) for AMD64/ARM64-based systemd
+	Linux 2.1.72 and above for x86-based systems
+	Solaris 9, 10 and 11
+
+In the above list the only UNIX dialects present are ones for
+which I test the current lsof revision.  Lsof may still support
+unlisted dialect versions -- e.g., HP-UX 10.20, Solaris 7, etc.
+-- but I don't have access to systems where I could test lsof
+on them, so I can't claim lsof works on them. If your dialect
+isn't in the list, you should try building lsof on it anyway.
+
+Lsof version 4 predecessors, versions 2 and 3, may support older
+version of some dialects.  Contact me via e-mail at <abe@purdue.edu>
+if you're interested in their distributions.  Make sure "lsof"
+appears in the "Subject:" line so my e-mail filter won't classify
+your letter as Spam.
+
+### What about a new port?
+
+The 00PORTING file in the distribution gives hints on doing
+a port.  I will consider doing a port in exchange for
+permanent access to a test host.  I require permanent access
+so I can test new lsof revisions, because I will not offer
+distributions of dialect ports I cannot upgrade and test.
+
+#### User-contributed Ports
+
+Sometimes I receive contributions of ports of lsof to
+systems where I can't test future revisions of lsof.  Hence,
+I don't incorporate these contributions into my lsof
+distribution.
+
+However, I do make descriptions of these contributions
+available.  You can find them in the 00INDEX and README
+files at:
+
+	ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/contrib
+
+Consult the 00INDEX file in the contrib/ directory for a
+list of the available contributions and consult README
+there for information on how to obtain them.
+
+### Why isn't there an AT&T SVR4 port?
+
+I haven't produced an AT&T SVR4 port because I haven't seen
+a UNIX dialect that is strictly limited to the AT&T System
+V, Release 4 source code.  Every one I have seen is a
+derivative with vendor additions.
+
+The vendor additions are significant to lsof because they
+affect the internal kernel structures with which lsof does
+business.  While some vendor derivatives of SVR4 are similar,
+each one I have encountered so far has been different enough
+from its siblings to require special source code.
+
+If you're interested in an SVR4 version of lsof, here are
+some existing ports you might consider:
+
+	DC/OSx (This obsolete port is only available upon
+		special request.)
+	Reliant UNIX (This obsolete port is only available
+			upon special request.)
+	SCO|Caldera UnixWare (This is the most likely choice.)
+	Solaris
+
+### Why isn't there an SGI IRIX port?
+
+Lsof support for IRIX was terminated at lsof revision 4.36,
+because it had become increasingly difficult for me to
+obtain information on the IRIX kernel structures lsof needs
+to access.
+
+At IRIX 6.5 I decided the obstacles were too large for me
+to overcome, and I stopped supporting lsof on IRIX.  I have
+sources to the last revision of lsof (4.36) for IRIX, but
+that version of lsof does not work on IRIX 6.5 and is
+vulnerable to the standard I/O descriptor attack.  (See
+the "Is lsof vulnerable to the standard I/O descriptor
+attack?" Q&A for more information.) Contact me to discuss
+obtaining those sources.
+
+If you wish to pursue the issue, don't contact me, contact
+SGI.  This case was opened with SGI on the subject:
+
+	Case ID:	0982584
+	Category: Unix
+	Priority: 30-Moderate Impact
+
+	Problem Summary:
+	kernel structure header files needed for continued lsof
+	support
+
+	Problem Description:
+	Email In  07/17/98 19:09:23
+
+### Why does lsof's Configure script report "WARNING: unsupported
+dialect or version"?
+
+Lsof's Configure script issues this message when it encounters
+a dialect or its version that lsof once supported, but no
+longer does.  Usually I drop support for a dialect or version
+when I can no longer test lsof on it.
+
+However, it's worth trying to compile and use lsof.  Be sure to
+run the test suite.  (See the answer to the "Is there a test
+suite?  question for information on the test suite.)
+
+If you have problems with an unsupported dialect or version,
+file a new GitHub issue and I may be able to help.
+
+
+## Lsof Problems
+
+### Configuration Problems
+
+#### Why can't Configure determine the UNIX dialect version?
+
+The lsof Configure script uses UNIX shell commands, often in a
+command pipeline, to determine the UNIX dialect version.
+(Consult the dialect stanza in Configure to determine which
+commands are used.)  If Configure can't determine the dialect
+version, probably one of the commands is not behaving as
+Configure expects.
+
+Symptoms of the failure include Configure warning messages and
+incorrect version definitions in the Makefile CFLAGS.
+
+If you suspect that the lsof Configure script is failing to
+determine the dialect version correctly, try running the
+commands from Configure stanza one at a time.  That will
+usually reveal the source of the problem.  Be particularly
+mindful that the PATH environment variable can cause commands
+to be executed from non-standard directories.
+
+If you can't determine the source of the problem, there is a
+work-around.  You can supply the UNIX dialect version in the
+LSOF_VSTR environment variable.  Use Configure as a guide to
+forming what it expects in LSOF_VSTR.  There is also some
+information on  LSOF_VSTR in the 00XCONFIG documentation file
+of the lsof distribution.
+
+### Compilation Problems
+
+#### Why does the compiler complain about missing header files?
+
+When you use make to build lsof, the compiler may complain
+that it can't find header files -- e.g.,
+
+	$ make
+	(cd lib; make DEBUG="-O" CFGF="-DAIXA=0 -DAIXV=4330 \
+	-DLSOF_VSTR=\"4.3.3.0\"")
+	gcc  -DAIXA=0 -DAIXV=4330 -DLSOF_VSTR="4.3.3.0" -O \
+	-c ckkv.c
+	In file included from ckkv.c:33: ../machine.h:70: \
+	sys/types.h: A file or directory in the path name \
+	does not exist. \
+
+That type of complaint doesn't represent an lsof problem.
+It represents a problem with a missing system header file
+that probably should be found in /usr/include or in the
+system source tree.
+
+As a first step try using find(1) to locate the problem
+header file.  If it's a system header file and can't be
+found, here are some possible causes:
+
+1. The file set, RPM or package containing the header files
+	has not been installed.  Instructions for doing that
+	are specific to the UNIX dialect and beyond the scope
+	of this document.
+
+2. If the compiler is gcc, the private gcc header files:
+
+	* May not have been installed;
+
+	* May have been installed incorrectly;
+
+	* May not have been updated properly after the last
+	compiler or system update;
+
+	* Ones from a previous installation may not have been
+	removed.
+
+	A path leading to the gcc private header files can be
+	found with `gcc -v`.  Consult the gcc documentation for
+	instructions on proper installation of the private gcc
+	header files.
+
+3. On some dialects -- e.g., FreeBSD, NetBSD, OpenBSD --
+	lsof may need to use header files that are located in
+	the system source tree -- /sys or /usr/src/sys, for
+	example.  Make sure the system source tree has been
+	installed.
+
+#### Why does gcc complain about the contents of header files
+distributed by the system's vendor?
+
+When you use make to build lsof and gcc to compile it, gcc
+may complain that it finds errors in system header files
+-- e.g.,
+
+	$ make
+	(cd lib; make DEBUG="-O" CFGF="-Dsolaris=80000 \
+	-DHASPR_GWINDOWS -m64 -DHASIPv6 -DHAS_VSOCK \
+	-DLSOF_VSTR=\"5.8\"")
+	gcc -Dsolaris=80000  -DHASPR_GWINDOWS -m64 -DHASIPv6 \
+	-DHAS_VSOCK -DLSOF_VSTR="5.8"  -O  -c  dvch.c
+	In file included from /usr/include/sys/proc.h:31, \
+	from /homes/abe/gnu/gcc-3.2.1/lib/gcc-lib/sparcv9-sun-solaris2/ \
+	3.2.1/include/sys/user.h:267, from /usr/include/kvm.h:13, \
+	from ../dlsof.h:53, from ../lsof.h:172, from dvch.c:43: \
+	/homes/abe/gnu/gcc-3.2.1/lib/gcc-lib/sparcv9-sun-solaris2/\
+	3.2.1/include/sys/task.h:59: parse error before "uint_t"
+
+Errors like the above are most likely not problems in the
+system's header files, but in the private copies of them
+that were created when gcc was made or installed.  Note
+the presence of
+".../gcc-3.2.1/lib/gcc-lib/sparcv9-sun-solaris2/3.2.1/include/..."
+in the paths for user.h and task.h.  It indicates both
+header files are gcc-specific.
+
+To solve errors like this requires comparing the header
+files in the vendor's /usr/include tree to the gcc-specific
+ones in gcc's private gcc-lib/.../include tree.  It may be
+necessary to regenerate gcc-specific header files, correct
+them or remove them.  See the gcc distribution for the
+appropriate tools.
+
+A possible temporary work-around is to direct gcc to use
+the vendor's header files instead of its temporary ones by
+declaring -I/usr/include in the compilation flags.
+
+#### Other header file problems
+
+Don't overlook any vendor tools that might validate the
+vendor header files installed on the system  -- e.g., the
+Solaris pkgchk tool can be used to check the header files
+that were installed from the SUNWhea package.
+
+For other header file problems contact me at <abe@purdue.edu>.
+Please follow the reporting guidelines in the "How do I
+report an lsof bug?" section of this FAQ.
+
+### Why doesn't lsof report full path names?
+
+Lsof reports the full path name when it is specified as a
+search argument for open files that match the argument.
+However, if the argument is a file system mounted-on
+directory, and lsof finds additional path name components
+from the kernel name cache, it will report them.
+
+Lsof reports path name for file system types that have path
+name lookup features -- e.g., some versions of AdvFS for
+Digital and Tru64 UNIX.  The Linux /proc-based lsof reports
+full path names, because the Linux /proc file system provides
+them.  Lsof on recent builds of Solaris 10 also report full
+path names, because those Solaris kernels record the full path
+name in the vnode structure.
+
+Otherwise, lsof uses the kernel name cache, where it exists
+and can be accessed, and reports some or all path name
+components (e.g., the sys and proc.h components of
+/usr/include/sys/proc.h) for these dialects:
+
+	Apple Darwin
+	DC/OSx
+	FreeBSD
+	HP-UX, /dev/kmem and PSTAT based
+	Linux, /dev/kmem-based
+	NetBSD
+	OpenBSD
+	Reliant UNIX
+	SCO OpenServer
+	SCO|Caldera UnixWare
+	Solaris 2.x, 7, 8 and 9 (except for some VxFS versions;
+					see the "Why doesn't Solaris
+					lsof report VxFS path name
+					components?" section for more
+					information)
+	Solaris 10 (early builds) Tru64 UNIX
+
+As far as I can determine, AFS path lookups don't share in
+kernel name cache operations, so lsof can't identify open AFS
+path name components.  Apparently Solaris VxFS versions 4 and
+above don't share in kernel name cache operations, either, so
+lsof can't display path name components for those open files.
+
+Since the size of the kernel name cache is limited and the
+cache is in constant flux, it does not always contain the names
+of all components in an open file's path; sometimes it contains
+none of them.
+
+Lsof reports the file system directory name and whatever
+components of the file's path it finds in the cache, starting
+with the last component and working backwards through the
+directories that contain it.  If lsof finds no path
+components, lsof reports the file system device name instead.
+
+When lsof does report some path components in the NAME
+column, it prefixes them with the file system directory
+name, followed by " -- ", followed by the components --
+e.g., /usr -- sys/path.h for /usr/include/sys/path.h.  The
+" -- " is omitted when lsof finds all the path name components
+of a file's name.
+
+The PSTAT-based HP-UX lsof relies on kernel name cache
+contents, too, even though its information comes to lsof
+via pstat() function calls.  Consequently, PSTAT-based
+HP-UX lsof won't always report full paths, but may use the
+" -- " partial path name notation, or may occasionally
+report no path name at all but just the file system mounted-on
+directory and device names.
+
+Lsof can't obtain path name components from the kernel name
+caches of the following dialects:
+
+	AIX
+
+Only the Linux kernel records full path names in the
+structures it maintains about open files; instead, most
+kernels convert path names to device and node number doublets
+and use them for subsequent file references once files have
+been opened.
+
+To convert the device and node number doublet into a
+complete path name, lsof would have to start at the root
+node (root directory) of the file system on which the node
+resides, and search every branch for the node, building
+possible path names along the way.  That would be a time
+consuming operation and require access to the raw disk
+device (usually implying setuid-root permission).
+
+If the prospect of all that local disk activity doesn't
+concern you, think about the cost when the device is
+NFS-mounted.
+
+Try using the file system mount point and node number lsof
+reports as parameters to find -- e.g.,
+
+	$ find <mount_point> -inum <node_number> -print
+
+and you may get an appreciation of what a file system
+directory tree search would cost.
+
+#### Why do lsof -r reports show different path names?
+
+When you run lsof with its repeat (`-r`) option, you may
+notice that the extent to which it reports path names for
+the same files may vary from cycle to cycle.  That happens
+because other processes are making kernel calls affecting
+the cache and causing entries to be removed from and added
+to it.
+
+#### Why does lsof report the wrong path names?
+
+Under some circumstances lsof may report an incorrect path
+name component, especially for files in a rapidly changing
+directory like /tmp.
+
+In a rapidly changing directory, like /tmp, if the kernel
+doesn't clear the cache entry when it removes a file, a
+new file may be given the same keys and lead lsof to believe
+that the old cache entry with the same keys belongs to the
+new file.
+
+Lsof tries to avoid this error by purging duplicate entries
+from its copy of the kernel name cache when they have the
+same device and inode number, but different names.
+
+This error is less likely to occur in UNIX dialects where the
+keys to the name cache are node address and possibly a
+capability ID.  The Apple Darwin, Digital UNIX, FreeBSD, HP-UX,
+NEXTSTEP, OPENSTEP, Solaris, Tru64 UNIX, and UnixWare dialects
+use node address.  Apple Darwin, FreeBSD, NetBSD, OpenBSD,
+Tru64 UNIX, and also use a capability ID to further identify
+name cache entries.
+
+#### Why doesn't lsof report path names for unlinked (rm'd) files?
+
+When lsof gets path name components from the kernel's name
+cache, it does not report the path names of a file that has
+been unlinked from its parent directory -- e.g., deleted via
+rm, or the unlink() system call -- even when some process may
+still hold the file open; lsof reports only the file system's
+mounted-on directory and device.  That's because path name
+components are removed from the kernel name cache when the file
+is unlinked.
+
+Unlinked open files are sometimes used by applications for
+temporary, but invisible storage (i.e., ls won't show them,
+and no other process can open them.)  However, they may
+occasionally consume disk space to excess and cause concern
+for a system administrator, who will be unable to locate
+them with find, ls, du, or other tools that rely on finding
+files by examining the directory tree.
+
+By using lsof's +L option you can see the link count of
+open files -- in the NLINK column.  An unlinked file will
+have an NLINK value of zero.  By using the option +L1 you
+can tell lsof to display only files whose link count is
+less than one (i.e., zero).
+
+There are some UNIX dialect-specific exceptions to lsof's
+inability to report unlinked path names.  They are described in
+the answer to the "When will lsof report path names for deleted
+files?" question.
+
+#### Why doesn't lsof report the "correct" hard linked file path
+name?
+
+When lsof reports a rightmost path name component for a
+file with hard links, the component may come from the
+kernel's name cache.  Since the key which connects an open
+file to the kernel name cache may be the same for each
+differently named hard link, lsof may report only one name
+for all open hard-linked files.   Sometimes that will be
+"correct" in the eye of the beholder; sometimes it will
+not.  Remember, the file identification keys significant
+to the kernel are the device and node numbers, and they're
+the same for all the hard linked names.
+
+#### When will lsof report path names for deleted files?
+
+Lsof will report path names for deleted files for two
+dialects:  Linux and later builds of Solaris 10.
+
+Deleted Linux path names are reported by default and have
+"(deleted)" at their ends.
+
+The display of Solaris 10 deleted path names may be selected
+with the -X option.  When selected they are also reported with
+"(deleted)" at their ends.
+
+### Why is lsof so slow?
+
+Lsof may appear to be slow if network address to host name
+resolution is slow.  This can happen, for example, when the
+name server is unreachable, or when a Solaris PPP cache daemon
+is malfunctioning.
+
+To see if name lookup is causing lsof to be slow, turn it off
+with the `-n` option.
+
+Port service name lookup or portmap registration lookup may
+also be causes of slow-down.  To suppress port service name
+lookup, specify the `-P` option.
+
+Lsof doesn't usually make direct portmap calls -- only when +M
+is specified, or when HASPMAPENABLED is defined during lsof
+construction.  (The lsof help panel, produced with `lsof -h`
+will display the default portmap registration reporting
+state.)  The quickest first step in checking if lsof is slow
+because of the portmapper is to use lsof's `-M` option.
+
+Lsof may be slow if UID to login name lookups are slow.
+Suppress them with `-l`.
+
+On dialects where lsof uses the kernel name cache, try
+disabling its use with `-C`.  (You can tell if lsof uses the
+kernel name cache by looking for `-C` in lsof's `-h`
+output.)  Of course, disabling kernel name cache use will mean
+that lsof won't report full or partial path names, just file
+system and character device names.
+
+If you're just interested in the open files of one process, try
+using the `-p <Process-ID>` option to limit lsof to that
+process.  (The `-p` option may also be followed with a list
+of Process-IDs.)
+
+If you're interested in including or excluding certain
+commands, try lsof's "-c[^]cmd" option.
+
+If you're interested in certain Internet TCP and UDP states
+(e.g., ESTABLISHED) or in excluding some (e.g., CLOSE_WAIT),
+try lsof's "-s p:s" option, available where shown on the lsof
+help output, obtained with -h or -?.  More information on it
+may be found in the answer to the "How are protocol state name
+exclusion and inclusion used?" question.
+
+Your UNIX dialect may not support "-s p:s" and its associated
+performance improvements to Internet-only file processing.  You
+can find more information on those topics in the answer to the
+"Why doesn't my dialect support state name exclusion and
+inclusion?" question.
+
+Older AIX lsof may be slow to start because of its oslevel
+identity comparison.  (Newer AIX lsof uses uname(2).)  See the
+"Why does AIX lsof start so slowly?" and "Why does lsof warn
+"compiled for x ... y; this is z.?" sections for more
+information.
+
+### Why doesn't lsof's setgid or setuid permission work?
+
+If you install lsof on an NFS file system that has been
+mounted with the nosuid option, lsof may not be able to
+use the setgid or setuid permission you give it, complaining
+it can't open the kernel memory device -- e.g., /dev/kmem.
+
+The only solution is to install lsof on a file system that
+doesn't inhibit setgid or setuid permission.
+
+### Does lsof have security problems?
+
+I don't think so.  However, lsof does usually start with
+setgid permission, and sometimes with setuid-root permission.
+Any program that has setgid or setuid-root permission,
+should always be regarded with suspicion.
+
+Lsof drops setgid power, holding it only while it opens
+access to kernel memory devices (e.g., /dev/kmem, /dev/mem,
+/dev/swap).  That allows lsof to bypass the weaker security
+of access(2) in favor of the stronger checks the kernel
+makes when it examines the right of the lsof process to
+open files declared with -k and -m.  Lsof also restricts
+some device cache file naming options when it senses the
+process has setuid-root power.
+
+On a few dialects lsof requires setuid-root permission
+during its full execution in order to access files in the
+/proc file system.  These dialects include:
+
+	DC/OSx 1.1 for Pyramid systems
+	Reliant UNIX 5.4[34] for Pyramid systems
+
+When lsof runs with setuid-root permission it severely
+restricts all file accesses it might be asked to make with
+its options.
+
+The device cache file (typically .lsof_hostname in the home
+directory of the real user ID that executes lsof) has 0600
+modes.  (The suffix, hostname, is the first component of
+the host's name returned by gethostname(2).)  However, even
+when lsof runs setuid-root, it makes sure the file's
+ownerships are changed to that of the real user and group.
+In addition, lsof checks the file carefully before using
+it (See the question "How do I disable the device cache
+file feature or alter its behavior?" for a description of
+the checks.); discards the file if it fails the scrutiny;
+complains about the condition of the file; then rebuilds
+the file.
+
+See the 00DCACHE file of the lsof distribution for more
+information about device cache file handling and the risks
+associated with the file.
+
+### Will lsof show remote hosts using files via NFS?
+
+No.  Remember, lsof displays open files for the processes
+of the host on which it runs.  If the host on which lsof
+is running is an NFS server, the remote NFS client processes
+that are accessing files on the server leave no process
+records on the server for lsof to examine.
+
+### Why doesn't lsof report locks held on NFS files?
+
+Generally lock information held by local processes on remote
+NFS files is not recorded by the UNIX dialect kernel.  Hence,
+lsof can't report it.
+
+One exception is some patch levels of Solaris 2.3, and all
+versions of Solaris 2.4 and above.  Lsof for those dialects
+does report on locks held by local processes on remotely
+mounted NFS files.
+
+#### Why does lsof report a one byte lock on byte zero as a full
+file lock?
+
+When a process has a lock of length one, starting at byte
+zero, lsof can't distinguish it from a full file lock.
+That's because most UNIX dialects represent both locks the
+same way in their file lock (flock or eflock) structures.
+
+### Why does lsof report different values for open files on the same file system (the automounter phenomenon)?
+
+On UNIX dialects where file systems may be mounted by an
+automounter with the `direct` type, lsof may sometimes
+report difference DEVICE, SIZE/OFF, INODE and NAME values
+when asked to report files open on the file system.
+
+This happens because some files open on the file system --
+e.g., the current directory of a shell that changed its
+directory to the file system as the file system's first
+reference -- may be characterized in the kernel with
+temporary automounter node information.  The cd doesn't
+cause the file system to be mounted.
+
+A subsequent reference to the file system -- e.g., an ls
+of any place in it -- will cause the file system to be
+mounted.  Processes with files open to the mounted file
+system are characterized in the kernel with data that
+reflects the mounted file system's parameters.
+
+Unfortunately some kernels (e.g., some versions of Solaris
+2.x) don't revisit the process that did only a change-directory
+for the purpose of updating the data associated with the
+open directory file.  The file continues to be characterized
+with temporary automounter information until it does another
+directory change, even a trivial `cd .`.
+
+Lsof will report on both reference types, when supplied
+the file system name as an argument, but the data lsof
+reports will reflect what it finds in the kernel.  For the
+different types lsof will display different data, including
+different major and minor device numbers in the DEVICE
+column, different lengths in the SIZE/OFF column, different
+node numbers in the INODE column, and slightly different
+file system names in the NAME column.
+
+In contrast, fuser, where available, can only report on
+one reference type when supplied the file system name as
+an argument.  Usually it will report on the one that is
+associated with the mounted file system information.  If
+the only reference type is the temporary automounter one,
+fuser will often be silent about it.
+
+### Why don't lsof and netstat output match?
+
+Lsof and netstat output don't match because lsof reports
+the network information it finds in open file system objects
+-- e.g., socket files -- while netstat often gets its
+information from separate kernel tables.
+
+The information available to netstat may describe network
+activities never or no longer associated with open files,
+but necessary for proper network state machine operation.
+
+For example, a TCP connection in the FIN_WAIT_[12] state
+may no longer have an associated open file, because the
+connection has been closed at the application layer and is
+now being closed at the TCP/IP protocol layer.
+
+#### Why can't lsof find accesses to some TCP and UDP ports?
+
+Lsof stands for LiSt Open Files.  If there is no open file
+connected to a TCP or UDP port, lsof won't find it.  That's
+the most common reason why lsof doesn't find a port netstat
+might report open.
+
+One reason I've found on some UNIX dialects is that their
+kernels set aside TCP and UDP ports for communicating with
+support activities, running in application layer servers
+-- the automounter daemons, and the NFS biod and nfsd
+daemons are examples.  Netstat may report the ports are in
+use, but lsof doesn't.
+
+Another reason is that netstat may also be able to report
+a port is open on a particular dialect, because it uses a
+source of data different from what lsof uses -- e.g.,
+netstat might examine kernel tables or use streams messages
+to MIB2, while lsof relies on the information it finds in
+open file structures and their descendants.
+
+Sometimes it's possible to search the data netstat and lsof
+use.  For example, on Linux /proc/tcp and /proc/udp can be
+examined.  There might an entry there for a particular
+protocol and port, but if the line on which the port appears
+doesn't have an inode number that matches an inode number
+of an open file, lsof won't be able to identify the process
+using the port.
+
+This is a tough question to which there is no easy answer.
+
+### Why does lsof update the device cache file?
+
+At the end of the lsof output you may see the message:
+
+	lsof: WARNING: /Homes/abe/.lsof_vic was updated.
+
+In this message /Homes/abe/.lsof_vic is the path to the
+private device cache file for login abe.  (See 00DCACHE.)
+
+Lsof issues this message when it finds it necessary to
+recheck the system device directory (e.g., /dev or /devices)
+and rebuild the device cache file during the open file
+scan.  Lsof may need to do these things it finds that a
+device directory node has changed, or if it cannot find a
+device in the cache.
+
+### Why doesn't lsof report state for UDP socket files?
+
+Lsof reports UDP TPI connection state -- TS_IDLE (Idle),
+TS_BOUND (Bound), etc. -- for some, but not all dialects.
+TPI state is stream-based TCP/IP information that isn't
+available in many dialects.
+
+A fairly weak general rule is if netstat(1) reports UDP
+TPI state, lsof may be able to report it, too.  But don't
+be surprised if lsof fails to report UDP TPI state for your
+dialect.  Other factors influence lsof's ability to report
+UDP TPI state, including the availability of state number
+data in kernel structures, and state number to state name
+conversion data.
+
+### I am editing a file with vi; why doesn't lsof find the file?
+
+Classic implementations of vi usually don't keep open the file
+being edited.  (Newer ones may do so in order to maintain an
+advisory lock.)  Instead classic vi opens the file, makes a
+temporary copy (usually in /tmp or /usr/tmp), and does its work
+in that file.  When you save the file being edited from a
+classic vi implementation, it reopens and rewrites the file.
+
+During a classic vi session, except for the brief periods when
+vi is reading or rewriting the file, lsof won't find an open
+reference to the file from the vi process, because there is
+none.
+
+### Why doesn't lsof report TCP/TPI window and queue sizes for my
+dialect?
+
+Lsof only reports TCP/TPI window sizes for Solaris, because
+only its netstat reports them.  The intent of providing
+TCP/TPI information in lsof NAME column output is to make
+it easier to match netstat output to lsof output.
+
+In general lsof only reports queue sizes for both TCP and
+UDP (TPI) connections on BSD-derived UNIX dialects, where
+both sets of values appear in kernel socket queue structures.
+SYSV-derived UNIX dialects whose TCP/IP implementations
+are based on streams generally provide only TCP queue sizes,
+not UDP (TPI) ones.
+
+While you may find that netstat on some SYSV-derived UNIX
+dialects with streams TCP/IP may report UDP (TPI) queue
+sizes, you will probably also find that the sizes are always
+zero -- netstat supplies a constant zero for UDP (TPI)
+queue sizes to make its headers align the same for TCP and
+UDP (TPI) connections.  Solaris seems to get it right --
+i.e., its netstat does not report UDP (TPI) queue sizes.
+
+When in doubt, I chose to avoid reporting UDP (TPI) queue
+sizes for UNIX dialects whose netstat-reported values I
+knew to be a constant zero or whose origin I couldn't
+determine.  OSR is a dialect in this category.
+
+#### Why doesn't lsof report socket options, socket states, and TCP
+flags and values for my dialect?
+
+The lsof -T argument, 'f', that selects the reporting of socket
+options, socket states and TCP flags was implemented at lsof
+revision 4.71 for the following UNIX dialects, providing the
+indicated information:
+
+	AIX 4.3.2 and 5.1 and above
+	All socket options and values, socket states, and TCP
+	flags and values described in lsof(8) are reported.
+	Apple Darwin 7.2 and above
+	All socket options and values, socket states, and TCP
+	flags and values described in lsof(8) are reported.
+	FreeBSD 4.9 and above
+	All socket options and values, socket states, and TCP
+	flags and values described in lsof(8) are reported.
+	HP-UX 11.00 (/dev/kmem-based lsof)
+	All socket options and values are reported.  No socket
+	states are reported.  Only the TF_NODELAY TCP flag and
+	the TF_MSS value are reported.
+	HP-UX 11.11 and iiiv2 (PSTAT-based lsof)
+	All socket options and values, and socket states are
+	reported.  No TCP flags or values are reported.
+	Linux
+	No socket options and values, socket states, or TCP
+	flags and values are reported.  The support for "-Tf"
+	could not be added to Linux, because socket options,
+	socket states, and TCP flags and values are not
+	available via the /proc file system.
+	NetBSD 1.6G and above
+	All socket options and values, socket states, and TCP
+	flags and values described in lsof(8) are reported.
+	OpenBSD 3.4 and above
+	All socket options and values, socket states, and TCP
+	flags and values described in lsof(8) are reported.
+	OpenUNIX 8
+	All socket options and values, socket states, and TCP
+	flags and values described in lsof(8) are reported.
+	SCO OpenServer Release 5.0.6
+	All socket options and values, socket states, and TCP
+	flags and values described in lsof(8) are reported.
+	Solaris 2.6, 8 and above
+	The socket option display is limited to BROADCAST,
+	DEBUG, DGRAM_ERRIND, DONTROUTE and OOBINLINE.  Socket
+	values are limited to KEEPALIVE and LINGER.  No socket
+	states are reported.  The TCP DELACK, NODELAY and
+	SENTFIN flags are reported.  The TCP MSS value is
+	reported.
+	UnixWare 7.1.[134]
+	All socket options and values, socket states, and TCP
+	flags and values described in lsof(8) are reported.
+
+#### Why doesn't lsof report the partial listen queue connection
+count for my dialect?
+
+The reporting of partial listen queue connections was added to
+-Tf processing at lsof revision 4.76.  Currently it is reported
+for these dialects:
+
+	AIX 4.3.2
+	This dialect is no longer supported, so no attempt
+	was made to add partial listen queue length support
+	for it.
+	AIX 5.1 and above
+	Partial listen queue information is available.
+	Apple Darwin 7.2 and above
+	Partial listen queue information is available.
+	FreeBSD 4.9 and above
+	Partial listen queue information is available.
+	HP-UX 11.00 (/dev/kmem-based lsof)
+	No partial listen queue information is available.
+	HP-UX 11.11 and iiiv2 (PSTAT-based lsof)
+	No partial listen queue information is available.
+	Linux
+	No partial listen queue information is available.
+	NetBSD 1.6G and above
+	Partial listen queue information is available.
+	OpenBSD 3.4 and above
+	Partial listen queue information is available.
+	OpenUNIX 8
+	This dialect is no longer supported, so no attempt
+	was made to add partial listen queue length support
+	for it.
+	SCO OpenServer Release 5.0.6
+	No partial listen queue information is available.
+	Solaris 2.6, 8 and above
+	Partial listen queue information is available.
+	Tru64 UNIX 5.0
+	This dialect is no longer supported, so no attempt
+	was made to add partial listen queue length support
+	for it.
+	Tru64 UNIX 5.1
+	Partial listen queue information is available.
+	UnixWare 7.1.[134]
+	Partial listen queue information is available.
+
+
+### What does "no more information" in the NAME column mean?
+
+When lsof can find no successor structures -- a gnode,
+inode, socket, or vnode -- connected to the file structure
+of an open descriptor of a process, it reports "no more
+information" in the NAME column.  The TYPE, DEVICE, SIZE/OFF,
+and INODE columns will be blank.
+
+Because the file structure is supposed to contain a pointer
+to the next structure of a file's processing support, if
+the pointer is NUL, lsof can go no further.
+
+Some UNIX dialects have file structures for system processes
+-- e.g., the sched process -- that have no successor
+structure pointers.  The "no more information" NAME will
+commonly appear for these processes in lsof output.
+
+It may also be the case that lsof has read the file structure
+while it is being assembled and before a successor structure
+pointer value has been set.  The "no more information" NAME
+will again result.
+
+Unless lsof output is filled with "no more information"
+NAME column messages, the appearance of a few should be no
+cause for alarm.
+
+### Why doesn't lsof find a process that ps finds?
+
+If lsof fails to display open files for a process that ps
+indicates exists, there may be several reasons for the
+difference.
+
+The process may be a "zombie" for which ps displays the
+"(defunct)" state.  In that case, the process has exited
+and has no open file information lsof can display.  It does
+still have a process structure, sufficient for the needs
+of ps.
+
+Another possible explanation is that kernel tables and
+structures may have been changing when lsof looked for the
+process, making lsof unable to find all relevant process
+structures.  Try repeating the lsof request.
+
+### Why doesn't -V report a search failure?
+
+The usual reason that -V won't report a search failure is
+that lsof located the search item, but was prevented from
+listing it by an option that doesn't participate in search
+failure reporting.
+
+For example, this lsof invocation:
+
+	$ lsof -V -i TCP@foobar -a -d 999
+
+won't report it can't find the Internet address TCP@foobar,
+even if there is an open file connected to that address,
+unless the open file also has a file descriptor number of
+999 (the `-a -d 999` options).
+
+Compile-time options can also affect -V results in much the
+same way.  For example, if HASSECURITY and HASNOSOCKSECURITY
+are defined at compile time, this lsof invocation, run by a
+non-root user:
+
+	$ lsof -V -c inetd
+
+won't report that it can't find the inetd command, even if
+there is a process running the inetd command, because the
+HASSECURITY and HASNOSOCKSECURITY options prevent the
+listing of all but the socket files of another user, and
+no socket file selector (e.g., "-i") was specified.
+
+
+### Portmap problems
+
+#### Why isn't a name displayed for the portmap registration?
+
+When portmap registration reporting is enabled, any time
+there is a registration for a local TCP or UDP port, lsof
+displays it in square brackets, following the port number
+or service name -- e.g., `:1234[name]` or `:name[100083]`.
+
+The TCP or UDP port number or service number (what follows
+the `:') is displayed under the control of the lsof -P
+option.  The registration identity is held by the portmapper
+and may be a name or a number, depending on how the
+registration's owner declared it.  Lsof reports what the
+port map holds and cannot derive a registration name from
+a registration number.
+
+Lsof can be compiled with registration reporting enabled
+or disabled by default, under the control of the HASPMAPENABLED
+#define (usually in machine.h).  The lsof help panel (`lsof
+-h`) will show the default.  Lsof is distributed with
+reporting disabled by default.
+
+#### How can I display only portmap registrations?
+
+Lsof doesn't have an option that will display only TCP or
+UDP ports with portmap registrations.  The +M option only
+enables the reporting of registration information when
+Internet socket files are displayed; +M doesn't select
+the displaying of Internet socket files -- the -i option
+does that.
+
+This simple lsof pipe to grep will do the job:
+
+	$ lsof -i +M | grep "\["
+
+This works because -i selects Internet socket files, +M
+enables portmap registration reporting, and only output
+lines with opening square brackets will have registrations.
+
+When portmap registration reporting is enabled by default,
+because the lsof builder constructed it that way, +M is
+not necessary.  (The lsof help panel, produced with `lsof
+-h` will display the default portmapper registration
+reporting state.)  However, specifying +M when reporting
+is already enabled is acceptable, as is specifying -M when
+reporting is already disabled.
+
+Digression: lsof will accept `+' or `-' as a prefix to most
+options.  (That isn't documented in the man page or help
+panel to reduce confusion and complexity.)  The -i option
+is as acceptable as +i, so the above example could be
+written a little more tersely as:
+
+	$ lsof +Mi | grep "\["
+
+But be careful to use the `Mi` ordering, since `iM`
+implies M is an address argument to `i`.
+
+#### Why doesn't lsof report portmap registrations for some ports?
+
+Lsof reports portmap registrations for local TCP and UDP
+ports only.  It identifies local ports this way:
+
+*  The port appears in the local address section of the
+	kernel structure that contains it.
+
+*  The port appears in the foreign address section of a
+	kernel structure whose local and foreign Internet
+	addresses are the same.
+
+*  The port appears in the foreign address section of a
+	kernel address structure whose Internet address is
+	INADDR_LOOPBACK (127.0.0.1).
+
+Following these rules, lsof ignores foreign portmapped
+ports.  That's done for reasons of efficiency and possible
+security prohibitions.  Contacting all remote portmappers
+could take a long time and be blocked by network difficulties
+(i.e., be inefficient).  Many firewalls block portmapper
+access for security reasons.
+
+Lsof may occasionally ignore portmap registration information
+for a legitimate local port by virtue of its local port
+rules.  This can happen when a port appears in the foreign
+part of its kernel structure and the local and foreign
+Internet addresses don't match (perhaps because they're on
+different interfaces), and the foreign Internet address
+isn't INADDR_LOOPBACK (127.0.0.1).
+
+#### Why doesn't lsof report portmap registrations for some Solaris
+versions?
+
+In some versions of Solaris -- 9 and 10 are known to exhibit
+this problem -- lsof is unable to display portmap registrations.
+
+This portmap registration reporting failure occurs when the
+Solaris netconfig field (in /etc or etc/inet) has its first two
+non-comment lines enabling tcp6 and udp6.  When netconfig is
+configured in that fashion, lsof's attempt to read the portmap
+via an RPC function fails.
+
+I don't have an explanation for the failure, but this comment
+in the netconfig(4) man page appears to have some bearing on
+the problem:
+
+	# The following two entries starting with udp6 and tcp6 are
+	# meant to be used for IPv6. If you have Ipv6 enabled on your
+	# machine then you can uncomment these two lines to enable
+	# RPC and NFS to use the Ipv6 stack.
+	...
+	#udp6  tpi_clts      v  inet6  udp  /dev/udp6  -
+	#tcp6  tpi_cots_ord  v  inet6  tcp  /dev/tcp6  - "
+
+My interpretation of that comment is that there is a different
+RPC interface to the portmap when IPv6 is enabled.  However, I
+can't find any documentation on it in the RPC man pages.  If
+anyone has information on it, please send it to me at
+<abe@purdue> and put "lsof Solaris portmap" in the subject
+line.
+
+A work-around may be to move the ucp6 and tcp6 lines after the
+udp and tcxp lines in netconfig.  I don't know if that change
+has any unacceptable consequences, but it works for me on my
+Solaris 9 test system, and I have a report that it also works
+on Solaris 10.
+
+
+### Why is `lsof | wc` bigger than my system's open file limit?
+
+There is a strong temptation to count open files by piping
+lsof output to wc.  If your purpose is to compare the number
+you get to some Unix system parameter that defines the
+number of open files your system can have, resist the
+temptation.
+
+One reason is that lsof reports a number of "files" that
+don't occupy Unix file table space -- current working
+directories, root directories, jail directories, text files,
+library files, memory mapped files are some.  Another reason
+is that lsof can report a file shared by more than one
+process that itself occupies only one file table slot.
+
+If you want to know the number of open files that occupy
+file table slots, use the +ff option and process the lsof
+output's FILE_ADDR column information with standard Unix
+tools like cut, grep, sed, and sort.
+
+You might also consider using use lsof's field output with
++ff, selecting the file struct address with -FF, and
+processing the output with an AWK or Perl script.  See the
+list_fields.awk, list_fields.perl, and shared.perl5 scripts
+in the scripts/ subdirectory of the lsof distribution for
+hints on file struct post-processing filters.
+
+### Why doesn't lsof report file offset (position)?
+
+Lsof won't report a file offset (position) value if the -s
+option (without parameters) has been specified, or if the
+dialect doesn't support the displaying of file offset
+(position).  (Note that on selected dialects the help output,
+obtained with -h or -?, may show that the -s option can also be
+supplied the "p:s" parameters; for more information on that
+addition, see the answer to the "How are protocol state name
+exclusion and inclusion used?" question.)
+
+That lsof is reporting only file size is indicated by the
+fact that the appropriate column header says SIZE instead
+of SIZE/OFF.
+
+If lsof doesn't support the displaying of file offset
+(position) -- e.g., for Linux /proc-based lsof -- the -h
+or -? output panel won't list the -o option.
+
+Sometimes the availability of file offset information
+depends on the dialect's kernel.  This is particularly true
+for socket file offsets.
+
+Maintenance of offsets for pseudo-terminal devices varies
+by UNIX dialect and is related to how the dialect kernel
+implements pseudo-terminal support.  Kernels like AIX, for
+example, that short-circuit the transfer of data between
+socket and pseudo devices to reduce TCP/IP daemon interrupt
+rates won't advance offsets in the TCP/IP daemon socket
+files.  Instead they will advance offsets in the open
+standard I/O files of the shell child precess where the
+pseudo-terminal devices are used.
+
+When in doubt about the behavior of lsof in reporting file
+offset information, do some carefully measured experiments,
+consult the lsof sources, or contact me at <abe@purdue.edu>
+to discuss the matter.  Please follow the reporting guidelines
+in the "How do I report an lsof bug?" section of this FAQ.
+
+#### What does lsof report for size when the file doesn't really have one?
+
+When a file has no true size -- e.g., it's a socket, a
+FIFO, or a pipe -- lsof tries to report the information it
+finds in the kernel that describes the contents of associated
+kernel buffers.
+
+Thus, for example, size for most TCP/IP files is socket
+buffer size.  The size of the socket read buffer is reported
+for read-only files; the size of the write buffer for
+write-only files; and the sum of the buffers sizes for
+read-write files.
+
+### Problems with path name arguments
+
+#### How do I ask lsof to search a file system?
+
+You can ask lsof to search for all open files on a file
+system by specifying its mounted path name as an lsof
+argument -- e.g.,
+
+	$ lsof /
+
+Output of the mount command will show file system mounted
+path names.  It will also show the mounted-on device path
+for the file system.
+
+If the mounted-on device is a block device (the permission
+field in output of `ls -l <device>` starts with a `b/),
+you can specify its name, too -- e.g.,
+
+	$ lsof /dev/sd0a
+
+If the mounted-on device isn't a block device -- for example,
+some UNIX dialects call a CD-ROM device a character device
+(ls output starts with a `c') -- you can force lsof to
+assume that the specified device names a file system with
+the +f option -- e.g.,
+
+	$ lsof +f -- /dev/sd0a
+
+(Note: you must use ``--'' after +f or -f if a file name
+follows immediately, because  +f and -f can be followed by
+characters that specify flag output selections.)
+
+When you use +f and lsof can't match the device to a file
+system, lsof will issue a complaint.
+
+The +f option may be used in some dialects to ask lsof to
+search for an NFS file system by its server name and server
+mount point.  If the mount application reports an NFS file
+system mounted-on value that way, then this sample lsof
+request should work.
+
+	$ lsof +f -- fleet:/home/fleet/u5
+
+Finally, you can use -f if you don't want a mounted file
+system path name to be considered a request to report all
+open files on the file system.  This is useful when you
+want to know if anyone is using the file system's mounted
+path name.  This example directs lsof to report on open
+access to the `/' directory, including when it's being used
+as a current working or root directory.
+
+	$ lsof -f -- /
+
+The lsof -f option performs the same function as -f does
+in some fuser implementations.  However, since the lsof -c
+option was chosen for another purpose before the `f' option
+was added to lsof, +f was selected as the analogue to the
+fuser -c option.  (Sorry for the potential confusion.)
+
+#### Why doesn't lsof find all the open files in a file system?
+
+Lsof may not find all the open files in a file system for
+several reasons.
+
+First, some processes with files open on the file system
+may have been changing status when lsof examined the process
+table, and lsof "missed" them.  Remember, the kernel changes
+much faster than lsof can respond to the changes.
+
+Second, be sure you have specified the file system correctly.
+Perhaps you specified a file instead.  You can use lsof's
+-V option to have lsof report in detail on what it couldn't
+find.  Make sure the report for the file system you specified
+says "file system."  Here's some -V output:
+
+	$ /lsof -V /tmp ./lsof.h ./lsof
+	COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF  INODE NAME
+	lsof    2688  abe  txt   VREG 18,1,7  1428583 226641 ./lsof
+	lsof    2689  abe  txt   VREG 18,1,7  1428583 226641 ./lsof
+	lsof: no file use located: ./lsof.h
+
+You can also use lsof's +f option to force it to consider
+a path name as a file system.  If lsof can't find a file
+system by the specified name, it will issue a complaint --
+e.g.,
+
+	$ lsof +f -- /usr
+	lsof: not a file system: /usr
+
+(/usr is a directory in the / file system.)
+
+#### Why does the lsof exit code report it didn't find open files
+when some files were listed?
+
+Sometimes lsof will list some open files, yet return a
+non-zero exit code, suggesting it hasn't found all the
+specified files.
+
+The first thing you should when you suspect lsof is incorrect
+is to repeat the request, adding the -V option.  In the
+resulting report you may find that your file system
+specification really wasn't a file system specification,
+just a file specification.
+
+Finally, if you specify two files or two file systems twice,
+lsof will credit all matches to the first of the two and
+believe that there were no matches for the second.  It's
+possible to specify a single file system twice with different
+path names by using both its mounted directory path name
+and mounted-one device name.
+
+	$ lsof +f -V spcuna:/sysprog /sysprog
+	COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF  INODE NAME
+	ksh     11092  abe  cwd   VDIR 39,0,1     1536 226562 /sysprog
+	(spcuna:/sysprog)
+	...
+	lsof: no file system use located: spcuna:/sysprog
+
+All matches were credited to /sysprog; none to spcuna:/sysprog.
+
+#### Why won't lsof find all the open files in a directory?
+
+When you give lsof a simple directory path name argument
+(not a file system mounted-on name), you are asking it to
+search for processes that have the directory open as a
+file, or as a process-specific directory -- e.g., root or
+current working directory.
+
+If you want to list instances of open files inside the
+directory, you need to either specify the individual path names
+of those files, their common mount point, or use the lsof +D 
+and +d options.
+
+For example, if you wanted to check the files open in your /lsof 
+folder then the following might be the quickest way to get
+the answer you are looking for:
+
+lsof / | grep /lsof | grep -v DIR
+
+See the answer to the question "Why are the +D and +d
+options so slow?" before you use +D or +d casually.
+
+See the answer to the question "Why do the +D and +d options
+produce warning messages?" for an explanation of some
+process authority limitations of +D and +d.
+
+#### Why are the +D and +d options so slow?
+
+The +D and +d options cause lsof to build a path name search
+list for a specified directory.  +D causes lsof to descend
+the directory to its furthest subdirectory, while +d
+restricts it to the top level.  In both cases, the specified
+directory itself is included in the search list.  In both
+symbolic links are ignored.
+
+Building such a search list can take considerable time,
+especially when the specified directory contains many files
+and subdirectories -- lsof must call the system readlink()
+and stat() functions for each file and directory.  Storing
+the search list can cause lsof to use more than its normal
+amount of dynamic memory -- each file recorded in the search
+list consumes dynamic memory for its path name, characteristics,
+and search linkages.  Using the list means lsof must search
+it for every open file in the system.
+
+Building the search list for a directory specified on some
+file systems can be slow -- e.g., for an NFS directory with
+many files.  Some file systems have special logging features
+that can introduce additional delays to the building of
+the search list -- e.g., NFS logging, or logging on a
+Solaris UFS file system.  The bottom line is that slow
+search list construction may not be so much an lsof problem
+as a file system problem.  (Hint: if you're using Solaris
+UFS logging, consider specifying the "logging,noatime"
+option pair to reduce the number of atime writes to the
+UFS logging queue and disk.)
+
+A somewhat risky way to speed up lsof's building of the
+search list is to use lsof's ``-O'' option.  It forces lsof
+to do all system calls needed to build the search list
+directly, rather than in a child process.  While direct
+system calls are much faster, they can block in the kernel
+-- e.g., when an NFS server stops responding -- stopping
+lsof until the kernel operation unblocks.
+
+As an example of the load +D can impose, consider that an
+`lsof +D /` on a lightly loaded NeXT '040 cube with a 1GB
+root file system disk took 4+ minutes of real time.  It
+also generated several hundred error messages about files
+and directories the lsof process didn't have permission to
+access with stat(2).
+
+The bottom line is that +D and +d should be used cautiously.
++D is more costly than +d for deeply nested directory trees,
+because of the full directory descent it causes.  So use
++d where possible.  And you might need to consider the
+performance of the file system that holds the directory
+you name with +d or +D.
+
+In view of these warnings, when is it appropriate to use
++D or +d?  Probably the most appropriate time is when you
+would specify the directory's contents to lsof with a shell
+globbing construct -- e.g., `lsof *`.  If that's what you
+need to do, `lsof +d .` is probably more efficient than
+having the shell produce a directory list, form it into an
+argument vector, and pass the vector to lsof for it to
+unravel.
+
+See the answer to the question "Why do the +D and +d options
+produce warning messages?" for an explanation of some
+process authority limitations of +D and +d.
+
+#### Why do the +D and +d options produce warning messages?
+
++D and +d option processing is limited by the authority of
+the lsof process -- i.e., lsof can only examine (with
+lstat(2) and stat(2)) files the owner of the process can
+access.
+
+If the ownership, group membership, or permissions of the
+specified directory, file within it, or directory within
+it prevents the owner of the lsof process from using lstat(2)
+or stat(2) on it, lsof will issue a warning message, naming
+the path and giving the system's (lstat(2's or stat(2)'s)
+reason (errno explanation text) for refusing access.
+
+As an example, assume user abc has a subdirectory in /tmp,
+owned by abc and readable, writable and searchable by only
+its owner.  If user def asks lsof to search for all /tmp
+references with +D or +d, lsof will be unable to lstat(2)
+or stat(2) anything in abc's private subdirectory, and will
+issue an appropriate warning.
+
+Lsof warnings can usually be suppressed with the -w option.
+However, using -w with +D or +d means that there will be
+no indication why lsof couldn't find an open reference to
+a restricted directory or something contained in it.
+
+Hint: if you need to use +D or +d and avoid authority
+warnings, and if you have super-user power, su and use lsof
+with +D or +d as root.
+
+### Why can't my C compiler find the rpcent structure definition?
+
+When you try to compile lsof your compiler may complain
+that the rpcent structure is undefined.  The complaints
+may look like this:
+
+	>print.c: In function `fill_portmap':
+	>print.c:213: dereferencing pointer to incomplete type
+	>...
+
+The most likely cause is that someone has allowed a BIND
+installation to update /usr/include/netdb.h (or perhaps
+/usr/include/rpc/netdb.h), removing the rpcent structure
+definition that lsof expects to find there.
+
+Only Solaris has an automatic work-around.  (See dlsof.h
+in dialects/sun.).  The Solaris work-around succeeds because
+there is another header file, <rpc/rpcent.h>, with the rpcent
+structure definition, and there is a Solaris C pre-processor
+test that can tell when the BIND <netdb.h> is in place and
+hence <rpc/rpcent.h> must be included.
+
+Doubtlessly there are similar work-arounds possible in
+other UNIX dialects whose header files have been "touched"
+by BIND, but in general I recommend restoration of the
+vendor's <netdb.h> and any other header files BIND might
+have replaced.  (I think BIND replaces <resolv.h>,
+<sys/bitypes.h>, <sys/cdefs.h> -- and maybe others.)
+
+### Why doesn't lsof report fully on file "foo" on UNIX dialect "bar?"
+
+Lsof sometimes won't report much information on a given
+file, or may even report an error message in its NAME
+column.  That's usually because the file is of a special
+type -- e.g., in a file system specific to the UNIX dialect
+-- and I haven't used a system where the file appeared
+during my testing.
+
+If you encounter such a situation, send me e-mail at
+<abe@purdue.edu> and we may be able to devise an addition to
+lsof that will report on the file in question.  Please follow
+the reporting guidelines in the "How do I report an lsof bug?"
+section of this FAQ.  Make sure "lsof" appears in the
+"Subject:" line so my e-mail filter won't classify your letter
+as Spam.
+
+### Why do I get a complaint when I execute lsof that some library file can't be found?
+
+On systems where the LIBPATH (or the equivalent) environment
+variable is used to record the library search path in
+executable files when they are built, an incorrect value
+may make it impossible for the system to find the shared
+libraries needed to load lsof for execution.
+
+This may be particularly true on systems like AIX >= 4.1.4,
+where the lsof Makefile takes the precautionary step of
+using the -bnolibpath loader flag to insure that the path
+to the private static lsof library is not recorded in the
+lsof binary.  Should LIBPATH be invalid when lsof is built,
+it will be recorded in the lsof binary as the default
+library path search order and lead to an inability to find
+libraries when lsof is executed.
+
+So, if you get missing library complaints when you try to
+execute lsof, check LIBPATH, or whatever environment variable
+is used on your system to define library search order in
+executable files.  Use the tools at your disposal to look
+at the library paths recorded in the lsof binary -- e.g.,
+chatr on HP-UX, dump on AIX, ldd on Solaris.
+
+Make sure, too, that when the correct library search path
+has been recorded in the executable file, the required
+library files exist at one or more of the search paths.
+
+
+### Why does lsof complain it can't open files?
+
+When lsof begins execution, unless it has been asked to
+report only help or version information, typically it will
+attempt to access kernel memory and symbol files -- e.g.,
+/unix, /dev/kmem.  Even though lsof needs only permission
+to open these files for reading, read access to them might
+be restricted by ownerships and permission modes.
+
+So the first step to diagnosing lsof problems with opening
+files is to use ls(1) to examine the ownerships and permission
+modes of the files that lsof wants to open.  You may find
+that lsof needs to be installed with some type of special
+ownership or permission modes to enable it to open the
+necessary files for reading.  See the "Installing Lsof"
+section of 00README for more information.
+
+### Why does lsof warn "compiled for x ... y; this is z."?
+
+Unless warnings are suppressed (with -w) or the kernel
+identity check symbol (HASKERNIDCK) definition has been
+deleted, all but one lsof dialect version (exception:
+/proc-based Linux lsof) compare the identity of the running
+kernel to that of the one for which lsof was constructed.
+If the identities don't match, lsof issues a warning like
+this:
+
+	lsof: WARNING: compiled for Solaris release 5.7; this is 5.6.
+
+Two kernel identity differences can generate this warning
+-- the version number and the release number.
+
+Build and running identity differences are usually significant,
+because they usually indicate kernels whose structures are
+different -- kernel structures commonly change at dialect
+version releases.  Since lsof reads data from the kernel
+in the form of structures, it is sensitive to changes in
+them.  The general rule is that an lsof compiled for one
+UNIX dialect version will not work correctly when run on
+a different version.
+
+There are three work-arounds: 1) use -w to suppress the
+warning -- and risk missing other warnings; 2) permanently
+disable the identity check by deleting the definition of
+HASKERNIDCK in the dialect's machine.h header file -- with
+the same risk; or 3) rebuild lsof on the system where it
+is to be run.  (Deleting HASKERNIDCK can be done with the
+Customize script or by editing machine.h.)
+
+Generally checking kernel identity is a quick operation
+for lsof.  However, it is potentially slow under AIX, where
+lsof must run /usr/bin/oslevel.  To speed up lsof, use -w
+to suppress the /usr/bin/oslevel test.  See "Why does AIX
+lsof start so slowly?" for more information.
+
+### How can I disable the kernel identity check?
+
+The kernel identity check is controlled by the HASKERNIDCK
+definition.  When it is defined, most dialects (exclusion:
+/proc-based Linux lsof) will compare the build-time kernel
+identity with the run-time one.
+
+To disable the kernel identity check, disable the HASKERNIDCK
+definition in the dialect's machine.h header file.  The
+Customize script can be used to do that in its section
+about the kernel identity check.
+
+Caution: while disabling the kernel identity check may
+result in smaller lsof startup overhead, it comes with the
+risk of executing an lsof that may produce warning messages,
+error messages, incorrect output, or no output at all.
+
+### Why don't ps(1) and lsof agree on the owner of a process?
+
+Generally the user ID lsof reports in its USER column is
+the process effective user ID, as found in the process
+structure.  Sometimes that may not agree with what ps(1)
+reports for the same process.
+
+There are sundry reasons for the difference.  Sometimes
+ps(1) uses a different source for process information,
+e.g., the /proc file system or the psinfo structure.
+Sometimes the kernel is lax or confused (e.g., Solaris
+2.5.1) about what ID to report as the effective user ID.
+Sometimes the system carries only one user ID in its process
+structure (some BSD derivatives), leaving lsof no choice.
+
+The differences between lsof and ps(1) user identifications
+should be small and normally it will be apparent that the
+confusion is over a process whose application has changed
+to an effective user ID different from the real one.
+
+### Why doesn't lsof find an open socket file whose connection
+state is past CLOSE_WAIT?
+
+TCP/IP connections in states past CLOSE_WAIT -- e.g.,
+FIN_WAIT_1, CLOSING, LAST_ACK, FIN_WAIT_2, and TIME_WAIT
+-- don't always have open files associated with them.  When
+they don't, lsof can't identify them.  When the connection
+state advances from CLOSE_WAIT, sometimes the open file
+associated with the connection is deleted.
+
+### Why don't machine.h definitions work when the surrounding
+comments are removed?
+
+The machine.h header files in dialect subdirectories have
+some commented-out definitions like:
+
+	/* #define HASSYSDC "/your/choice/of/path */
+
+You can't simply remove the comments and expect the definition
+to work.  That's intended to make you think about what
+value you are assigning to the symbol.  The assigned value
+might have a system-specific convention.  HASSYSDC, for
+example, might be /var/db/lsof.dc for FreeBSD, but it might
+be /var/adm/lsof.dc for Solaris.
+
+Symbols defined in the lsof documentation are described in
+00PORTING, other machine.h comments, and other lsof
+documentation files.  HASSYSDC, for example, is discussed
+in 00DCACHE.  When comments and documentation don't suffice,
+consult the source code for hints on how the symbol is
+used.
+
+### What do "can't read inpcb at 0x...", "no protocol control block", "no PCB, CANTSENDMORE, CANTRCVMORE", etc. mean?
+
+Sometimes lsof will report "can't read inpcb at 0x00000000",
+"no protocol control block", "no PCB, CANTSENDMORE,
+CANTRCVMORE" or a similar message in the NAME column for
+open TCP socket files.  These messages mean the file's socket
+structure lacks a pointer to the INternet Protocol Control
+Block (inpcb) where lsof expects to find connection addresses
+-- local and foreign ports, local and foreign IP addresses.
+The socket file has probably been submitted to the shutdown(2)
+function for processing.
+
+In some implementations lsof issues the "no PCB, CANTSENDMORE,
+CANTRCVMORE" message, which tries to explain the absence
+of a protocol control block by showing the socket state
+settings that have been made by the shutdown(2) function.
+
+If a non-zero address follows the "0x" in the "can't read
+inpcb" message, it means lsof couldn't read inpcb contents
+from the indicated address in kernel memory.
+
+### What do the "unknown file system type" warnings mean?
+
+Lsof may report a message similar to"
+
+	unknown file system type, v_op: 0x10472f10
+
+in the NAME column for some files.
+
+This means that lsof has encountered a vnode for the file
+whose operation switch address (from v_op) references a
+file system type for which there is no support in lsof.
+After lsof identifies the file system type, it uses
+pre-compiled code to locate the file system specific node
+for the file where lsof finds information like file size,
+device number, node number, etc.
+
+To get some idea of what the file system type might be,
+use nm on your kernel symbol file to locate the symbol name
+that corresponds to the v_op address -- e.g., on Solaris
+do:
+
+	$ nm -x /dev/ksyms | grep 0x10472f10
+	0x10472f10 ... |file_system_name_vnodeops
+
+Where "file_system_name" is the clue to the unsupported
+file system.
+
+Lsof doesn't use the v_op address to identify file system
+types on all dialects.  Sometimes it uses an index number
+it finds in the vnode.  It will translate that symbol to
+a short name in the warning message -- e.g., "nfs3" -- if
+possible.
+
+### Installation
+
+#### How do I install lsof?
+
+There is no "standard" way to install lsof.  Too much
+depends on local conditions for me to be able to provide
+working install rules in the lsof make files.  (The skeleton
+install rules you will find just give "hints.")  See the
+"Installing Lsof" section of 00README for a fuller explanation.
+
+To install lsof you will need to consider these questions:
+
+*  Who should be able to use lsof?  (See HASSECURITY and
+	HASNOSOCKSECURITY in the "Security" section of 00README.)
+
+*  Where should lsof be installed?  This is a decision
+	mostly dictated by local conditions.  Somewhere in
+	/usr/local -- etc/ or sbin/ -- is a common choice.
+
+*  What permissions should I give the lsof executable?
+	The answer to this varies by dialect.  The make files
+	have install rules that give hints.  The "Installing
+	Lsof" section of 00README gives information, too.
+
+*  What if I want to install lsof in a shared file system
+	for machines that require different lsof configurations?
+	See the next question and answer, "How do I install a
+	common lsof when I have machines that need differently
+	constructed lsof binaries?"
+
+#### How do I install a common lsof when I have machines that need differently constructed lsof binaries?
+
+A dilemma that faces some system administrators when they
+install lsof in a shared file system -- e.g., NFS -- is
+that they must have different lsof executables for different
+systems.
+
+The answer is to build an lsof wrapper script that is
+executed in place of lsof.  The script can use system
+commands to determine which lsof binary should be executed.
+
+Consider this example.  You have HP-UX machines with 32
+and 64 bit kernels that share the /usr/local/sbin directory
+where you want to install lsof.  Consequently, on each
+system you must use a different lsof executable, built for
+the system's bit size.  (That's because lsof reads kernel
+structures, sized by the kernel's bit size.)
+
+One answer is to install three things in /usr/local/sbin:
+1) a 32 bit lsof as lsof32; 2) a 64 bit lsof as lsof64;
+and 3) an lsof script.  The script might look like this
+one, based on work by Amir J. Katz:
+
+	#!/bin/sh
+	x=`/usr/bin/getconf KERNEL_BITS`  # returns 32 or 64
+	if /usr/bin/test "X$x" = "X32"
+	then
+	lsof32 $*
+	else
+	if /usr/bin/test "X$x" = "X64"
+	then
+	lsof64 $*
+	else
+	echo "Can't determine which lsof executable to use;"
+	echo "getconf KERNEL_BITS says: $x"
+	exit 1
+	fi
+	fi
+
+Solaris users should consult "How do I install lsof for
+Solaris 7, 8 or 9?" for information on a similar trick
+using the Solaris isaexec command.
+
+Users of other dialects might be able to use a command like
+uname(1) that can identify a distinguishing feature of the
+system to be incorporated in pre-installed lsof executable
+names.  For example, use `uname -r` and install binaries
+with suffixes that match `uname -r` output.
+
+### Why do lsof 4.53 and above reject device cache files built by earlier lsof revisions?
+
+When lsof revisions 4.53 run and encounter a device cache
+file built by an earlier revision, it will reject the file
+and build a new one.  The rejection will be advertised with
+these messages:
+
+	lsof: WARNING: no /dev device in <name>: 2 sections
+	...
+	lsof: WARNING: created device cache file: <name>
+
+This happens because the header line of the device cache
+file was changed at revision 4.53 to contain the number of
+the device on which the device directory resides.  The old
+device cache file header line -- the "2 sections" line in
+the above warning message, node reads "2 sections, dev=600".
+
+This is not a serious problem, since lsof automatically
+rebuilds the device cache file with the correct header
+line.
+
+### What do "like block special" and "like character special" mean in the NAME column?
+
+When lsof comes across an open block or character file
+whose device, raw device and inode place it somewhere other
+than /dev (or /devices), lsof doesn't report the /dev (or
+/devices) name in the NAME column.  Instead lsof reports
+the file system name and device or path name in the NAME
+column and parenthetically adds "like block special <path>"
+or "like character special <path>".
+
+The value for <path> will point to a block or character
+device in /dev (or /devices) whose raw device number matches
+that of the open file being reported, but whose device
+number or node number (or both) don't match.
+
+Such an open file is connected to a device node that has
+been created in a directory other than /dev (or /devices.)
+See mknod(8) for information on how such nodes are created.
+(Generally one needs root power to create device nodes with
+mknod.)
+
+### Why does an lsof make fail because of undefined symbols?
+
+When lsof is compiled via the `make` step and the final
+load step fails because of missing symbols, the problem
+may not be lsof.  The problem may be that ld, called by
+the compiler as part of the `make` step, can't find some
+library that lsof needs.
+
+First check the last compiler line of the make operation
+-- e.g., the last line with cc or gcc in it before the
+undefined symbol report -- for loader arguments, i.e.,
+ones beginning with "-l".  Except for "-llsof" the rest
+name system libraries.  ("-L./lib" precedes "-llsof" to
+tell the loader its location.)
+
+Check that all the named system libraries exist.  Look in
+/lib and /usr/lib as a start, but that may not be the only
+place system libraries live.  Consult your dialect's
+documentation, e.g., the compiler and loader man pages,
+for other possible locations.
+
+If some system library doesn't exist, that may mean it was
+never installed or was removed.  You'll have to re-install
+the missing library.
+
+You may find that all the system libraries lsof uses exist.
+Your next step might be to use nm and grep to see if any
+of them contain the undefined symbols.
+
+	$ nm library | grep symbol
+
+If the undefined symbol exists in some library named by
+the lsof make step, then you might have a problem with some
+environment variable that controls the load step.  The most
+common is LD_LIBRARY_PATH.  It may have a setting that
+causes ld to ignore a directory containing a library lsof
+names.  If this is the case, try unsetting LD_LIBRARY_PATH
+in the environment of the ld process -- e.g., do:
+
+	$ unset LD_LIBRARY_PATH
+or
+	% unsetenv LD_LIBRARY_PATH
+
+Consult your ld man page for other environment variables
+that might affect library searching -- e.g., LIBPATH, LPATH,
+SHLIB_PATH, etc.
+
+If the undefined function doesn't exist in any libraries
+lsof names, check other libraries.  See if the function
+has a man page that names its library.  If the latter is
+true, please let me know, because that is an lsof problem
+I need to fix.
+
+If none of these solutions work for you, send me some
+documentation via e-mail at <abe@purdue.edu>.  Include `uname
+-a` output, the output of the lsof `Configure ...` and `make`
+steps, and the contents of the environment in force when the
+`make` step was executed -- e.g., `env` or `printenv` output.
+If you've located the libraries lsof names, send me that
+information, too.  Make sure "lsof" appears in the "Subject:"
+line so my e-mail filter won't classify your letter as Spam.
+
+### Command Regular Expressions (REs)
+
+#### What are basic and extended regular expressions?
+
+Lsof's ``-c'' option allows the specification of regular
+expressions (REs), enclosed in two slash ('/') characters and
+followed by these modifiers:
+
+	b	the RE is a basic RE.
+	i	ignore case.
+	x	the RE is an extended RE (the default).
+
+Note: the characters of the regular expression may need to
+be quoted to prevent their expansion by the shell.
+
+Example: this RE is an extended RE that matches exactly
+four characters, whose third may be an upper ('O') or lower
+case ('o') oh:
+
+	-c /^..o.$/i
+
+For simplicity's sake, an RE that is acceptable to egrep(1)
+is usually called an extended RE.
+
+REs suitable for the old line editor, ed(1), are often
+called basic REs (and sometimes also called obsolete).
+
+These are some ways basic REs usually differ from extended
+REs.  (There are other differences.)
+
+*  `|', `+', `?', '{', and '}' are ordinary characters.
+
+*  `^' is an ordinary character except at the beginning of
+	the RE.
+
+*  `$' is an ordinary character except at the end of the
+	RE.
+
+*  `*' is an ordinary character if it appears at the
+	beginning of the RE.
+
+For more information on REs and the distinction between
+basic and extended REs, consult your dialect's man pages
+for ed(1), egrep(1), sed(1), and possibly regex(5) or
+regex(7).
+
+#### Why can't I put a slash in a command regular expression?
+
+Since a UNIX command name is the last part of a path to
+the command's executable, the lsof command regular expression
+(RE) syntax uses slash ('/') to mark the beginning and end
+of an RE.  Slash may not appear in the RE and the `\'
+back-slash escape is ineffective for "hiding" it.
+
+More likely than not, if you try to put a slash in an lsof
+command RE, you'll get this response:
+
+	$ lsof -s/.\// ...
+	lsof: invalid regexp modifier: /
+
+Lsof is complaining the first character it found after
+the second slash isn't an lsof command RE modifier -- 'b',
+'i', or 'x'.
+
+#### Why does lsof say my command regular expression wasn't found?
+
+When you use both forms of lsof's -c option --
+``-c <command>'' and ``-c /RE/[m]'' -- and ask that lsof
+do a verbose search (``-V''), you may be surprised that
+lsof will say that the regular expression wasn't found.
+
+This can happen if the ``-c <command>'' form matches first,
+because then the ``-c/RE/[m]'' test will never have been
+applied.  For example:
+
+	$ ./lsof -clsof -c/^..o.$/ -V -adcwd
+	COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF  NODE NAME
+	lsof    7850  abe  cwd   VDIR    6,0     2048 96442 / (/dev/sd0a)
+	lsof: no command found for regex: ^..o.$
+
+The ``-clsof'' option matched first, so the ``-c/^..o.$/
+option wasn't tested.
+
+### Why doesn't lsof report on shared memory segments?
+
+Lsof reports on shared memory segments only if they're
+associated with an open file.  That's consistent with lsof's
+mission -- to LiSt Open Files.  Shared memory segments with
+no file associations aren't open files.
+
+That's not to say that a report on shared memory segments
+and their associated processes wouldn't be useful.  But it
+calls for a new tool, not more baggage for lsof.
+
+### Why does lsof report two instances of itself?
+
+When you ask lsof to report all open files and it has
+permission to do so, you may see two lsof processes in the
+output.  The processes are connected via pipes -- e.g.,
+here's an HP-UX 11 example.
+
+	COMMAND     PID USER   FD   TYPE     DEVICE ...
+	...
+	lsof      29450  abe    7w  PIPE 0x48732408 ...
+	lsof      29450  abe    8r  PIPE 0x48970808 ...
+	...
+	lsof      29451  abe    6r  PIPE 0x48732408 ...
+	lsof      29451  abe    9w  PIPE 0x48970808 ...
+
+The first process will usually be the lsof you initiated;
+the second, an lsof child process that is used to isolate
+its parent process from kernel functions that can block --
+e.g., readlink() or stat().
+
+Information to and from the kernel functions is exchanged
+via the two pipes.  When the parent process detects that
+the child process has become blocked, it attempts to kill
+the child.  Depending on the UNIX dialect that may succeed
+or fail, but the parent won't be blocked in any event.
+
+See the "BLOCKS AND TIMEOUTS" and "AVOIDING KERNEL BLOCKS"
+sections of the lsof man page for more information on why
+the child process is used and how you can specify lsof
+options to avoid it.  (Caution: that may be risky.)
+
+### Why does lsof report '\n' in device cache file error messages?
+
+Lsof revisions prior to 4.58 may report '\n' in error
+messages it delivers about problems in the device cache
+file -- e.g.,
+
+	lsof: WARNING: no ...: 4 sections\n
+
+That's deliberately done to show the exact contents of the
+device cache file line about which lsof is complaining,
+including its terminating NL (New Line) '\n' character.
+In the above example the line in the device cache file
+causing the lsof complaint contains "4 sections" and ends
+with a '\n'.
+
+At revision 4.58 and above, device cache error messages
+like the one in the above example have been changed to
+read:
+
+	lsof: WARNING: no ...: line "4 sections"
+
+The terminal '\n' is no longer reported, the line contents
+are enclosed in double quote marks ('"'), and the word
+"line" has been added as a prefix to denote that what
+follows is a line from the device cache file.
+
+### Kernel Symbol and Address Problems
+
+#### What does "lsof: WARNING: name cache hash size length error: 0" mean?
+
+When run on some systems, lsof may issue this warning:
+
+	lsof: WARNING: name cache hash size length error: 0
+
+That is an example from a FreeBSD system where lsof reads
+the kernel's _nchash variable and finds its value is zero.
+
+Similar warnings include:
+
+	WARNING: kernel name cache size:
+	WARNING: can't read kernel's name cache:
+	WARNING: no name cache address
+	WARNING: name cache hash size length error:
+	WARNING: unusable name cache size:
+
+These warnings are issued when lsof is attempting to read
+the kernel's name cache information.  They are usually the
+result of a mis-match between the addresses for kernel
+symbols lsof gets via nlist(2) and the addresses in use by
+the kernel.
+
+Lsof usually gets kernel symbol addresses from what it
+believes to be the kernel boot file.  In FreeBSD, for
+example, that's the path returned by getbootfile(3), usually
+/kernel.  The boot file can have other names in other UNIX
+dialects -- /unix, /vmunix, /bsd, /netbsd, /mach, /stand/vmunix,
+etc.
+
+Lsof will get incorrect (mismatched) addresses from the
+boot file if it has been replaced by a newer one which
+hasn't yet been booted -- e.g., if this is done in FreeBSD:
+
+	# mv /kernel /kernel.OLD
+	# mv /kernel.NEW /kernel
+
+Until the FreeBSD system is rebooted, the booted kernel is
+/kernel.OLD, but getbootfile() says it is /kernel.  If
+symbol addresses important to lsof in /kernel.OLD and
+/kernel don't match, the lsof WARNING messages result.
+
+#### Why does lsof produce "garbage" output?
+
+Kernel name cache warnings may not be the only sign that
+lsof is using incorrect symbol addresses to read kernel
+values.  If there's no reasonable test lsof can make on
+what it reads from the kernel, it may issue other warnings
+or even report nonsensical results.
+
+The warnings may appear on STDERR, such as:
+
+	lsof: can't read proc table info
+
+Or the warnings may appear in the NAME column as messages
+saying lsof can't read or interpret some kernel structure --
+e.g.,
+
+	... NAME
+	... can't read file struct from 0x12345
+
+One possible work-around is to point lsof's kernel symbol
+address gathering at the proper boot file.  That can be
+done with lsof's -k option -- e.g.,
+
+	$ lsof -k /kernel.OLD
+
+The best work-around is to make sure the standard boot file
+is properly sited -- e.g., if you've moved a new /kernel
+in place, boot it.
+
+### Why does lsof report open files when run as super user that it doesn't report when run with lesser privileges?
+
+The most likely cause is that the HASSECURITY option was
+selected when the lsof executable was built.
+
+If HASSECURITY is defined when lsof is built, and lsof is
+run with the privileges of a non-ROOT user, it will only
+list open files belonging to the user.  The same lsof
+executable, when run with root user privileges, will list
+all open files.
+
+However, if HASSECURITY and HASNOSOCKSECURITY are both
+defined when lsof is built, lsof will list open files
+belonging to the user and will also list anyone else's open
+socket files, provided their listing is selected with the
+"-i" option.
+
+So first ask yourself if the process whose open files lsof
+won't list belong to a user other than the one under which
+you're running lsof, and are not open socket files.  If
+either is true, use lsof's help (-h or -?) option and look
+for a line near the bottom of the help panel that says:
+
+	"... can list all files..."
+
+If the leading "..." says "Only root" then HASSECURITY was
+defined when lsof was built.  If the trailing "..." says
+", but anyone can list socket files" then HASNOSOCKSECURITY
+was also defined.
+
+Should you want an lsof not built with HASSECURITY defined,
+rerun the lsof Configure script.  If you let Configure do
+customization, make sure you answer 'n' when it asks if
+you want to enable HASSECURITY and HASNOSOCKSECURITY.  If
+you don't need to do customization, you can rebuild lsof
+with the "-n" option to Configure.  Here's an example of
+such a rebuild sequence:
+
+	$ Configure -clean
+	$ Configure -n <dialect-abbreviation>
+	$ make
+
+More information on the HASSECURITY and HASNOSOCKSECURITY
+options may be found in the "Security" section of the
+00README file of the lsof distribution.
+
+### Test Suite Problems
+
+#### Errors all tests can report:
+
+##### Why do tests complain "ERROR!!!  can't execute ../lsof"?
+
+All tests in the test suite expect an executable lsof file
+to exist in the tests parent directory, ../lsof.
+
+If there's none there, the tests/Makefile has a rule to
+make it, but there are probably circumstances where that
+rule may fail.
+
+The work-around is to re-Configure and re-make lsof, then
+run the test suite.
+
+##### Why do tests complain "ERROR!!! can't find ..." a file?
+
+Many tests create (or use from a supplied environment
+variable path) a test file and use lsof to find it.  When
+lsof can't file the file, the tests report the error with
+messages of the form:
+
+	ERROR!!!  can't find ... : <some file path>
+	or
+	ERROR!!!  lsof couldn't find ...
+
+These type of error messages mean that the lsof field output
+delivered to the test didn't contain a file that the test
+could identify as the one it intended lsof to find.  It
+might also mean that the process information -- command
+name, PID or parent PID -- didn't match what the test
+expected.
+
+This could imply a bug in the test or a bug in lsof.  Try
+using lsof to find a known file that is open.  For example,
+while in the tests sub-directory, do this:
+
+	$ sleep 30 < Makefile
+	$ ../lsof Makefile
+
+If lsof doesn't report that Makefile is open, then the
+fault may be with lsof.  If lsof reports the file is open,
+search further in the test code for the failure cause.
+
+##### Why do some tests fail to compile?
+
+If a test suite program fails to compile, it may be because
+I've never had an opportunity to compile the test on the
+particular UNIX version you are using.
+
+See Appendix B in 00TEST for a list of the UNIX dialects
+where the test suite has been validate.
+
+##### Why do some tests always fail?
+
+There are several tests in the optional group that have
+conflicting or special requirements:
+
+	LTbigf      needs a dialect and file system that support
+		large files.
+
+	LTlock      won't work if the tests/ sub-directory is
+		on an NFS file system.
+
+	LTnfs       won't work if the tests/ sub-directory is
+		not on an NFS file system.
+
+So for two tests in particular, LTlock and LTnfs, one will
+generally fail.
+
+Some failing tests can be run successfully by supplying to
+them a path to the appropriate type of file system with
+the -p option.
+
+##### Why does the test suite say it hasn't been validated on my dialect?
+
+When you use the default rule of the test suite's Makefile,
+it may issue this complaint:
+
+	$ cd tests
+	$ make
+	!!!WARNING!!!
+
+	This dialect or its particular version may not have
+	been validated with the lsof test suite.  Consequently
+	some tests may fail or may not even compile.
+
+	!!!WARNING!!!
+
+You are then given the opportunity to answer 'y' to have
+the test suite operation continue.
+
+This message means that the tests/TestDB file in the tests
+sub-directory doesn't show that the test suite has been
+run with the combination of compiler flags found in
+tests/config.cflags.  The tests might nor run; they may
+encounter compiler failures.
+
+See 00TEST for more information on the UNIX dialects where
+the test suite has been validated and on the workings of
+TestDB and its supporting scripts.
+
+When the tests/Makefile "auto" rule is used, the message
+is more terse and the condition is fatal.
+
+	This suite has not been validated on:
+
+	<dialect_description>
+
+No opportunity to continue is offered.
+
+The tests/Makefile "silent" rule will skip checking for
+the validation footprint.
+
+##### Why do the tests complain they can't stat() or open() /dev/mem or /dev/kmem?
+
+When the tests detect that lsof for the dialect reads its
+information from kernel memory (i.e., the LT_KMEM definition
+is present in tests/config.cflags), and when the lsof
+executable path is ../lsof, the tests make sure they can
+stat() and open() for read access the relevant kernel memory
+devices, /dev/kmem and possibly /dev/mem.
+
+If those stat() or open() operations fail, the tests issue
+an error message and quit.  The message explains why the
+system rejected the operation in terms of system "errno"
+symbols and messages.  More often than not the explanation
+will be that the process lacks permission to access the
+indicated device node.
+
+One work-around is to give the lsof executable being tested
+the necessary permission -- e.g., via chgrp, chmod, etc.
+-- and set its path in the LT_LSOF_PATH environment variable.
+(See 00TEST.)
+
+Another work-around is to make sure the process that runs
+the tests has the necessary permissions -- e.g., run it as
+root, or enable the process login to access the resources.
+For example, I can run the tests on my personal work-station
+because /dev/kmem and /dev/mem are readable by the "kmem"
+group and my login is in that group.
+
+
+#### LTbigf test issues
+
+##### Why does the LTbigf test say that the dialect doesn't support large files?
+
+Large file support is defined dialect by dialect in the
+lsof source files and Configure script.  If large file
+support isn't defined there, it isn't defined in the LTbigf
+test.
+
+If you think that's wrong for a particular dialect, contact me
+via e-mail at <abe@purdue.edu>.  Make sure "lsof" appears in the
+"Subject:" line so my e-mail filter won't classify your letter
+as Spam.
+
+##### Why does LTbigf complain about operations on its config.LTbigf*
+	file?
+
+The LTbigf must be able to write a large file test (size
+> 32 bits) and seek within it and the process file ulimit
+size must permit the operation.  If the default location
+for the test file, tests/, isn't on a file system enabled
+for large file operations or if the process ulimit file
+block size is too small, lsof will get file operation
+errors, particularly when seeking
+
+There may be a work-around.  Specify the path to a file
+LTbigf can write in a file system enabled for large file
+operations a the -poption.  Make sure that the ulimit file
+block size permits writing a large file.  For example,
+presuming /scratch23 is large-file-enabled, and presuming
+you have permission to raise the ulimit file block size,
+this shell commands will allow the LTbigf test to run on
+AIX:
+
+	$ ./LTbigf -p /scratch23/abe/bigfile
+
+(Note: syntax for the ulimit command varies by dialect and
+by shell.  Discovering the proper variant is left to the
+reader.)
+
+More information on this subject can be found in the LTbigf
+description in the 00TEST file.  If course, the LTbigf.c
+source file in tests/ is the ultimate source of information,
+
+##### Why does LTbigf warn that lsof doesn't return file offsets?
+
+On some dialects (e.g., Linux) lsof can't report file
+offsets, because the data access method underlying lsof
+doesn't provide them.  If LTbigf knows that lsof can't
+report file offsets for the dialect, it issues this warning:
+
+	LTbigf ... WARNING!!!  lsof can't return file offsets
+		for this dialect, so offset tests have
+		been disabled.
+
+LTbigf then performs the size test and skips the offset
+tests.
+
+For more information see 00TEST and the "Why doesn't
+/proc-based lsof report file offsets (positions)?" Q&A of
+this file.
+
+#### Why does the LTbasic test complain "ERROR!!! lsof this ..." and "ERROR!!!  lsof that ..."?
+
+The LTbasic test program uses lsof to examine a running
+lsof process.  It looks for the lsof current working
+directory, executable (if possible), and kernel memory file
+(if applicable).
+
+Failures to find those things result in the LTbasic error
+messages.  More information on how LTbasic produces the error
+messages may be found in the LTbasic.c source file.
+
+On HP-UX 11.11 and higher, for example, if the test's current
+working directory is on a loopback (LOFS) file system, LTbasic
+won't be able to find the current working directory of the lsof
+process because of a bug in the HP-UX kernel.
+
+The solution for that HP-UX problem is to install an HP-UX
+patch.  See the answer to the "Why doesn't PSTAT-based lsof
+report a CWD that is on a loopback (LOFS) file system?"
+question for more information on the patch.
+
+#### NFS test issues
+
+##### Why does the LTnfs test complain "couldn't find NFS file ..."?
+
+The LTnfs test must work with an NFS test file.  After it
+opens the file it asks lsof to find it on an NFS file system.
+If the file isn't on an NFS file system, lsof won't find it,
+and the NFS test script complains and fails.
+
+The work-around is to use -p option to supply a path to a
+regular NFS file (not a directory)  that is on an NFS file
+system that LTnfs can read.  Presuming /share/bin/file is
+such a file and can be opened for reading by the LTnfs
+test, this sample shell command could be used to run the
+LTnfs test successfully:
+
+	$ ./LTnfs -p /share/bin/file
+
+(If the NFS file system is enabled for large files, the
+NFS test will produce the error message described in the
+following Q&A.)
+
+#### LTnlink test issues
+
+##### Why does the LTnlink test complain that its test file is on an NFS file system?
+
+The LTnlink test may complain:
+
+	LTnlink ... WARNING!!!  test file <path> is NFS mounted.
+
+and then issue an explanation and a hint about using the
+-p option.
+
+The LTnlist test does this because of the way NFS file
+links are managed when an NFS file is unlinked and the
+unlinking process still has the file open.  Unlike with
+files on a local file system, when an NFS file that is
+still open is unlinked, its link count is not reduced.
+
+The file name is changed to a name of the form .nfsxxxx
+and the link count is left unchanged until the process
+holding the file open closes it.  That's done by NFS so it
+can keep proper track of the file on NFS clients and servers.
+
+Since the link count isn't reduced when the LTnlink test
+program closes the NFS test file it still has open, lsof
+won't find it for LTnlink with a link count of zero.
+Consequently, LTnlink disables that test section and issues
+its warning.
+
+The warning suggests that the unlink test section can be
+run by giving LTnlink a path to a test file with the -p
+option.  That path must name a file LTnlink can write and
+unlink.  Presuming /scratch23/abe/nlinkfile is on a local
+file system and the LTnlink test can write to it and unlink
+it, this sample shell command can be used to run the complete
+LTnlink test successfully:
+
+	$ LTnlink -p /scratch23/abe/nlinkfile
+
+##### Why does LTnlink delay and report "waiting for link count update: ..."?
+
+On some UNIX dialects and file system combinations the
+updating of link count after a file has been unlinked can
+be delayed.  Consequently, lsof won't be able to report
+the updated link count to LTnlink for a while.
+
+When lsof doesn't report the proper link count to LTnlink,
+it sleeps and repeats the lsof call, using the "waiting
+for link count update: ..." message as a signal that it is
+waiting for the expected lsof response.  The wait cycle
+duration is limited to approximately one minute.
+
+##### Why does LTnlink fail because of an unlink error?
+
+LTnlink may fail with an error similar to:
+
+	LTnlink ... ERROR!! unlink(<name>) failed: (Permission denied).
+
+That message will be followed by a short explanation.
+
+The error means that the kernel support for the file system on
+which the file <name> resides does not allow a process to
+unlink a file while it has the file open.  (When LTnlink is run
+without the "-p path" option, it creates a <name> that begins
+with "./config.LTnlink" and ends with the LTnlink process ID
+number.)
+
+An unlink failure of this type runs counter to original UNIX
+file system behavior, but it has been observed on some file
+system types, especially on the ZFS file system.
+
+The work-around is to run LTnlink on a file system that allows
+a process to unlink a file it has open.  Usually /tmp has that
+support.  So, try running LTnlink this way:
+
+	$ ./LTnlink -p /tmp/<name>
+
+where <name> is a unique name in /tmp of your choosing.  To
+be safe, create a subdirectory in /tmp, named by your login:
+
+	$ rm -f /tmp/<login>
+	$ mkdir /tmp/<login>
+	$ ./LTnlink -p /tmp/<login>/<name>
+
+#### LTdnlc test issues
+
+##### Why won't the LTdnlc test run?
+
+Lsof is unable to access the DNLC cache on AIX, because the
+kernel symbols for the DNLC aren't exported.  Contact IBM
+to learn why that decision was made.
+
+The LTdnlc test won't work on Apple Darwin because lsof
+can't obtain reliable DNLC information.
+
+The LTdnlc test may fail on other dialects.  Failure causes
+include: a busy system with a DNLC that is changing rapidly;
+path name components too large for the DNLC; a file system
+-- e.g., NFS, /tmp, loopback -- which doesn't fully
+participate in the DNLC; or DNLC limitations (Many DNLC
+implementations will only store path name components if
+they are 31 characters or less.)
+
+If you suspect the file system doesn't fully participate
+in kernel DNLC processing, as a work-around rebuild and
+test lsof on one that does.
+
+##### What does the LTdnlc test mean by "... <path> found: 100.00%"?
+
+Even when it succeeds the LTdnlc test will report:
+
+	LTdnlc ... /export/home/abe/src/lsof4/tests found: 100.00%
+
+This message means that the LTdnlc test asked lsof to find
+the file at the indicated path five times and lsof found
+the full path name in the indicated percentage of calls.
+The LTdnlc test considers it a failure if the percentage
+falls below 50.0%
+
+##### Why does the DNLC test fail?
+
+The DNLC test may fail when some component of the lsof
+tests/ sub-directory can't be cached by the kernel DNLC.
+Some kernels have a limit on the length of individual
+components (typically) 32.
+
+#### Why hasn't the test suite been qualified for 64 bit HP-UX 11 when lsof is compiled with gcc?
+
+When I attempted to qualify lsof for HP-UX 11, compiled
+with gcc 3.0, the LTsock test failed.  I traced the failure
+to a gcc compilation error.  Because LTsock is an important
+test, I didn't feel that the test suite was qualified if
+it failed.
+
+LTsock compiles and runs correctly on 64 bit HP-UX 11 when
+compiled with HP's ANSI-C.
+
+#### LTszoff test issues
+
+##### Why does LTszoff warn that lsof doesn't return file offsets?
+
+On some dialects (e.g., Linux) lsof can't report file
+offsets, because the data access method underlying lsof
+doesn't provide them.  If LTszoff knows that lsof can't
+report file offsets for the dialect, it issues this warning:
+
+	LTszoff ... WARNING!!!  lsof can't return file offsets
+			for this dialect, so offset tests have
+			been disabled.
+
+LTszoff then performs the size test and skips the offset
+tests.
+
+For more information see 00TEST and the "Why doesn't
+/proc-based lsof report file offsets (positions)?" Q&A of
+this file.
+
+#### LTlock test issues
+
+### File descriptor list (the ``-d'' option) problems
+
+#### Why does lsof reject a ``-d'' FD list?
+
+Lsof rejects ``-d'' FD lists that contain both exclusions
+and inclusions with messages like:
+
+	lsof: exclude in an include list: ^1
+	lsof: include in an exclude list: 2
+
+That's because ``-d'' FD lists are processed as ORed lists,
+so it makes no sense for them to contain both exclusions
+and inclusions.
+
+I.e.,, if a ``-d'' FD list were to contain ``^cwd,1'', the
+``^cwd'' member is useless, because the ``1'' member
+dominates by saying "include only FD 1".  That effectively
+excludes ``cwd'' FD.
+
+Note that lists may have multiple members of the same type,
+exclude or include.  They are processed as an ORed set.
+If an FD isn't excluded by any member of an exclude list,
+it is selected.  If an FD is included by any member of an
+include list, it is selected.
+
+#### Why are file descriptors other than those in my FD list reported?
+
+The FD list that follows ``-d'' excludes or includes file
+descriptors, but unless the ``-a'' (AND) option is specified,
+the FD list selections are ORed to the other selections.
+
+For example, the following lsof command will cause all file
+descriptors to be listed for the lsof command, and all but
+the cwd descriptor for all other commands, probably not
+what was intended.
+
+	$ lsof -clsof -d^cwd
+
+Hint: use ``-a'' -- e.g.,
+
+	$ lsof -clsof -a -d^cwd
+
+### How can I supply device numbers for inaccessible NFS file systems?
+
+When lsof can't get device numbers for inaccessible NFS file
+systems via stat(2) or lstat(2), it attempts to get them from
+the mount table's dev=xxx options.  Successes are reported with
+a warning message that indicates the source of the device
+number and that output might be incomplete as a consequence of
+the warnings.
+
+Some system mount tables -- e.g., Linux /proc/mounts -- don't
+have a dev=xxx option.  In that case, and provided lsof for the
+dialect supports them, you can use the +m option to create a
+mount table supplement file and the "+m m" option to use it.
+
+First check the lsof -h (help) output to see if the +m and
+"+m m" options are supported.  If they are, use +m to create a
+mount table supplement file when all mounted file systems are
+accessible.  Use "+m m" later to make the supplement available
+when some mounted file systems might not be available.
+
+Here's an example that creates a mount supplement file in
+$HOME/mnt-sup and later makes it available to lsof.
+
+	$ rm -f $HOME/mnt-sup
+	$ lsof +m > $HOME/mnt-sup
+	...
+	$ lsof +m $HOME/mnt-sup <other lsof options>
+
+If lsof has to get the device number from the supplement, it
+will issue an informative warning message.  The warning can be
+suppressed with lsof's -w option.
+
+Caution!  Since the mount table supplement file is static, it
+is its supplier's responsibility to update it as file system
+mounts change.
+
+For more information, consult the lsof man page.  The
+"ALTERNATE DEVICE NUMBERS" section has useful information on
+how lsof acquires device numbers when stat(2) or lstat(2)
+fail.
+
+### Why won't lsof find open files on over-mounted file systems?
+
+When a file system, /xyz for example, is mounted on the same
+mount point as another file system, /abc for example, running
+lsof with an argument of the path of the first file system's
+mount point -- the over-mounted one, /abc -- probably will not
+reveal any files open on /abc.
+
+That's because lsof looks for open files on a file system by
+looking for files with the file system's device number.  The
+two file systems usually have different device numbers and lsof
+determines the device number search key from the supplied name
+of the second file system.
+
+A general work-around exists only for Linux.  On that UNIX
+dialect, when you know the over-mounted file system's mount
+point path, you can ask lsof to report on all open files and
+grep that output for the path of the over-mounted file system
+mount point.
+
+### What can be done when lsof reports no more space?
+
+Many lsof methods cache information in memory, using the
+dialects malloc() library function.  When malloc() can't
+allocate the requested amount of memory, lsof exits with
+warning messages similar to this AIX message:
+
+	lsof: no more dev-ch space at pid 2257750: 0x82a8e600
+
+Lsof then exits immediately and produces no more output.
+
+A possible work-around is to increase the memory foot print
+of the shell that runs lsof.  That is often done with the
+ulimit(1) shell command.
+
+### What if the lsof build encounters ar and ld problems?
+
+The lsof main and library Makefiles use the library archiver,
+ar, and the system loader, ld, applications.  Improperly
+located, installed or configured versions of them may cause the
+lsof build to encounter errors with them.
+
+The application producing the error should identify itself in
+its error messages.
+
+The first thing to check the path of the application that is
+being used.  Try `which ar` or `which ld` to see if perhaps the
+PATH used during the build might be causing the wrong archiver
+or loader to be used.
+
+If the problem is with the use of the wrong archiver, and it's
+not possible to correct the PATH to it, try using the LSOF_AR
+environment variable to specify the path to and arguments for
+the correct archiver.  See 00XCONFIG for more information and
+note that LSOF_AR must specify the path to the archive
+application and the arguments for it, less the terminating
+library and module name arguments.
+
+If the problem is with the loader, there is no lsof work-
+around.  That's because lsof calls the loader via the C
+compiler, so the problem must be fixed at the compiler (system)
+level.
+
+### Why does lsof -i report an open socket file for a process, but
+lsof -p on that process' ID report nothing?
+
+The lsof in use was probably built with the HASSECURITY and
+HASNOSOCKSECURITY options and the process in question does not
+belong to the user of lsof.
+
+The HASSECURITY option limits lsof output to processes owned
+by the user invoking lsof and the HASNOSOCKSECURITY option
+weakens that slightly to allow output of open socket file
+information for all processes.
+
+For example, if process PID 12345 is owned by some user other
+than the one invoking lsof, and lsof has been compiled with the
+HASSECURITY and HASNOSOCKSECURITY options, the following lsof
+command will display the open socket files of process 12345:
+
+	$ lsof -p 12345 -a -i
+
+This security restriction is described in the lsof(8) manual
+page.
diff --git a/docs/getting-started.md b/docs/getting-started.md
new file mode 100644
index 0000000..aec99d9
--- /dev/null
+++ b/docs/getting-started.md
@@ -0,0 +1,107 @@
+# Getting started
+
+You can get lsof by building from source or installing from package managers.
+
+Due to the nature that lsof talks to the kernel, it requires many build-time checks to enable support for optional features. If you are installing lsof from package manager, chances are that the build machine has a different configuration from your own ones.
+
+If the prebuilt binary from package manager misses some feature or malfunctions, you should build lsof from source.
+
+## Build from source
+
+You can retrieve lsof sources from [GitHub Releases](https://github.com/lsof-org/lsof/releases) or via git. lsof currently uses two build systems:
+
+- Legacy: supports more OSes
+- Autotools(experimental): supports Linux/Darwin/FreeBSD
+
+### Legacy build system
+
+You should use the legacy build system if you are building lsof on old OSes or do not want to risk. The legacy build system supports the following UNIX dialects:
+
+- aix|aixgcc              : IBM AIX xlc (aix) or gcc (aixgcc)
+- darwin                  : Apple Darwin
+- freebsd                 : FreeBSD
+- hpux|hpuxgcc            : HP-UX cc (hpux) or gcc (hpuxgcc)
+- linux                   : Linux
+- netbsd                  : NetBSD
+- openbsd                 : OpenBSD
+- osr|sco                 : SCO OpenServer < 6.0.0, SCO developer's compiler
+- osrgcc|scogcc           : SCO OpenServer < 6.0.0, gcc compiler
+- osr6                    : SCO OpenServer 6.0.0, SCO compiler
+- solaris|solariscc       : Solaris gcc (solaris) or cc (solariscc)
+- unixware|uw             : SCO|Caldera UnixWare
+
+You can build lsof with the following commands:
+
+```shell
+./Configure <dialect>
+make
+```
+
+Testing:
+
+```shell
+bash check.bash <dialect>
+```
+
+### Autotools-based build system
+
+Since 4.97.0, lsof introduces a new experimental autotools-based build system. It supports the following OSes:
+
+- Linux
+- Darwin
+- FreeBSD
+- NetBSD
+
+Build dependencies:
+
+- c compiler: gcc/clang/etc
+- autotools: autoconf/automake
+- make
+- pkg-config: for package detection
+- groff: to process manpages
+- libtirpc(optional): if your libc does not provide rpc
+- nc/iproute2(optional): for testing
+
+You can build lsof with the following commands:
+
+```shell
+# If you are building from git sources
+# autoreconf -vif
+./configure
+make
+make install
+```
+
+Testing:
+
+```shell
+make check
+```
+
+## Install from package managers
+
+lsof is packaged in many OSes. You can install lsof from package managers:
+
+If you use Debian/Ubuntu/apt-based Linux distros:
+
+```shell
+sudo apt install lsof
+```
+
+If you use RHEL/CentOS/yum-based Linux distros:
+
+```shell
+sudo yum install lsof
+```
+
+If you use Arch/pacman-based Linux distros:
+
+```shell
+sudo pacman -Syu lsof
+```
+
+If you use NixOS/nix-based Linux distros:
+
+```shell
+nix-env -i lsof
+```
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 0000000..d92224d
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,59 @@
+# lsof (LiSt Open Files)
+
+**lsof** is a command for `LiSting Open Files`. You can use lsof for example to:
+
+- Find uses of a specific open file: `lsof /path/to/file`
+- Find an unlinked open file: `lsof +L1`
+- Find processes blocking umount: `lsof /mnt`
+- Find tcp/udp sockets: `lsof -i`
+- Find files open to a process with known PID: `lsof -p 1234`
+- Find files open to a named command: `lsof -c bash`
+- Find files open by a specific user: `lsof -u somebody`
+
+## History
+
+lsof was originally developed and maintained by Vic Abell since 1994. The [lsof-org team at GitHub](https://github.com/lsof-org/lsof) takes over the maintainership of lsof. You can find the latest release at [GitHub Release](https://github.com/lsof-org/lsof/releases).
+
+## OS Support
+
+Actively maintained and supported:
+
+- Linux
+- FreeBSD
+- Darwin(macOS)
+- NetBSD
+- OpenBSD
+- Solaris/OpenIndiana
+
+Not maintained for lack of maintainers but pull requests are welcome:
+
+- IBM AIX
+- HP-UX
+- SCO OpenServer
+- UnixWare
+
+lsof is tested in ci on the following platforms:
+
+- Alpine Linux 3.17
+- Arch Linux
+- CentOS 8/9
+- Debian 11
+- Fedora 36/37
+- FreeBSD 12/13/14
+- macOS Big Sur
+- NixOS
+- openSUSE Leap 15
+- Ubuntu 18.04/20.04/22.04
+- NetBSD 9
+- OpenBSD 7
+
+Additionally, lsof is tested by maintainers manually on the following platforms:
+
+- Solaris 11
+- OpenIndiana 5
+
+lsof is provided by package manager in the following repositories:
+
+<a href="https://repology.org/project/lsof/versions">
+    <img src="https://repology.org/badge/vertical-allrepos/lsof.svg" alt="Packaging status">
+</a>
\ No newline at end of file
diff --git a/docs/maintaining.md b/docs/maintaining.md
new file mode 100644
index 0000000..c027246
--- /dev/null
+++ b/docs/maintaining.md
@@ -0,0 +1,243 @@
+# Maintaining
+
+## The basic rules
+
+a Dialect maintainer can do as one's want as far as what one's will do
+has no impact on the other dialects.
+
+The following three dialects have ACTIVE maintainers:
+
+FreeBSD
+
+	@lrosenman
+	@jiegec
+
+Linux
+	
+	@dilinger
+	@jiegec
+
+NetBSD
+
+	@tnn2
+	@jiegec
+
+Darwin
+
+	@jiegec
+
+OpenBSD
+
+	@jiegec
+
+Solaris/OpenIndiana
+
+	@jiegec
+
+
+If you find a good person who has interested in maintain a dialect
+that none maintains, you can invite the person to the lsof-org
+organization.
+
+See also https://github.com/lsof-org/lsof/issues/157#issuecomment-941591778 .
+
+## Git
+
+A dialect maintainer must know Git.
+
+### Sophisticated commits
+
+You will change the repository. You will write the code or you will merge
+the code submitted by a contributor via pull request.
+
+About your dialect, you can do as you want. However, I recommend you to
+accept only SOPHISTICATED commits only. About a change for the common code
+between dialect, we accept only sophisticated commits. About a change having
+impact on the other dialects, we accept only sophisticated commits.
+
+One sophisticated commit does one thing.
+e.g. a commit including a change for adjusting white-spaces and a change for
+adding an option is not a sophisticated commit.
+
+* https://github.com/lsof-org/lsof/pull/195#discussion_r825328892
+* https://github.com/lsof-org/lsof/pull/208
+
+Sophisticated commits help reviewers.
+Understanding sophisticated commits is easy.
+
+https://github.com/lsof-org/lsof/pull/213
+This is not a sophisticated commit. Improving the way to hash and fixing
+a typo are done in a commit. I didn't have energy to ask the contributor
+to split the commit into two.
+
+"Try-and-error" commits should not be merged. It makes the git log of
+lsof dirty. Such dirtiness make us hard to read and understand git-log
+and to do git-bisect effectively. You can ask the contributor to
+squash the commits into one as far as the commits are for doing one
+thing; squashed commit should be sophisticated.
+
+### Commit logs
+
+If a change is dialect specific, use `[dialect]` as the prefix of the
+header of the commit log like::
+
+   [linux] compile with -Wall option
+   [linux] delete unused variables
+   [freebsd] cirrus-ci: disabled
+
+We should the force this rule to us and contributors. So we can know
+who should review the change/pull request. If no `[dialect]` prefix is
+given to a commit, the change may have an impact across dialects; all
+we must review the commit.
+
+I have seen contributors write much expiation about their change
+at the first comment of their pull request. However, their commit
+log is very short. We should ask them to copy the first comment to
+the commit log.
+
+## Reviewing and merging
+
+A dialect maintainer has a responsibility to review pull requests that
+change the code of one's dialect.
+
+After merging you may have to update two documents:
+
+00DIST
+
+	If a pull request you merged changes user visible aspect of lsof,
+	put the change at the end of 00DIST file. You can ask the contributor
+	making a pull request to put an entry for the one's change instead.
+
+00CREDITS
+
+	If this is the first time for the contributor to contribute to lsof,
+	add one's name to 00CREDITS.
+
+You may have to the contributor to update the lsof.8 man page.
+If a pull request fixes the issue already reported, put
+`Close #issueNumber` to the first comment of the pull request.
+
+e.g. https://github.com/lsof-org/lsof/pull/199#issue-1193523123
+
+## Testing
+
+Having a test case for a change is nice. The original lsof developed
+and maintained by Vic Abell has a test mechanism. However, I started
+developing my own test mechanism (the github test mechanism) written
+in bash.
+
+About the original test mechanism, see tests/00README.
+
+About the github test mechanism, see tests/case-00-hello.bash .
+You can put a test case non-dialect specific, put tests/.
+dialects/linux/tests/ is for testing linux specific code.
+
+## Releasing
+
+A dialect maintainer can release a new version of lsof FOR YOUR
+DIALECT without getting permission from maintainers of the other
+dialects.  So we can work asynchronously.
+
+### Install ksh
+
+The script for making an archive needs ksh.
+
+
+### Implement "make dist" for your favorite dialect
+
+See https://github.com/lsof-org/lsof/pull/131 how @masatake does for
+linux dialect.
+
+Merge the changes.
+
+
+### Update the version and release date in the source tree if you need
+
+You should update the version and release date in the following files:
+
+- 00DIST
+- version
+- configure.ac
+
+And then re-generated `docs/manpapage.md` by running `manpage.sh` in `docs` folder.
+
+The version number has following form MAJOR.MINOR.MICRO.  When making a
+release, update the version number.  If the change from the last release
+is small, increment MICRO. If it is large, increment MINOR.
+
+Merge the changes.
+
+If you just want to make a release for a version already released in
+another dialect, you don't need this step. Release the version number.
+
+e.g.
+
+conditions and situations:
+@masatake already released 4.94.0 for linux.
+No user visible change is committed to our git repo.
+You may want to make the same release but for dialect freebsd.
+
+In this case, you can use 4.94.0 as the version number.  If the
+condition doesn't meet, use 4.94.1 (or 4.95.0).
+
+### Put a tag with Git
+
+NOTE: this step is an optional if the commit for releasing is already
+tagged via another dialect.
+
+The tag you will put should have the same name as the version given in
+the step 2.
+
+Do "git tag" like:
+
+  $ git tag 4.95.0-this-is-an-example
+  $ git push upstream 4.95.0-this-is-an-example
+
+If you took a mistake, you can delete the tag like:
+
+  $ git tag -d 4.95.0-this-is-an-example
+  $ git push upstream :4.95.0-this-is-an-example
+
+### Make the source archive for the release
+
+   $ ./Configure [dialect]
+   $ make dist
+
+The archive is put at support/ directory.
+
+Checking whether you can build a lsof executable from the archive is
+good idea.
+
+e.g.
+
+   $ cp support/lsof_4.94.0.linux.tar.bz2 /tmp
+   $ cd /tmp
+   $ tar jxvf lsof_4.94.0.linux.tar.bz2
+   $ cd lsof_4.94.0.linux
+   $ ./Configure linux
+   $ make
+   $ make check (if your dialect support the target)
+
+### Visit https://github.com/lsof-org/lsof/releases
+
+1. Click [Draft new release]
+2. Choose a tag. Choose with the tag given in the step 3.
+3. Fill "Release title". Use the following form lsof-${theVersionNumber}-${dialect}. e.g. lsof-4.94.0-linux
+4. Fill "Describe this release". Copy and paste the changes described in 00DIST since the last release in your dialect.
+5. Record the release date. Put the date of the release at the end of "Contents" of 00DIST.
+	"Contents" is at the beginning of 00DIST.
+6. Put the source archive generated step in 4. Click "Attach binaries by dropping them here or selecting them. ", then specify the archive file.
+7. Check "This is a pre-release"
+8. Click [Publish release]
+9. Verify the release
+
+After step 8, the browser may show the page for the release. You can
+re-read the description and the source code archives. You can verify
+what you did here.
+
+If you find a fault or something, click the [Edit] in the page. You can
+update the pre-release.
+
+If you convince it is ready, click the [Edit] in the page, remove the
+check at "This is a pre-release", then [Publish release]. The new
+version is available at https://github.com/lsof-org/lsof/releases.
diff --git a/docs/manpage.md b/docs/manpage.md
new file mode 100644
index 0000000..9676882
--- /dev/null
+++ b/docs/manpage.md
@@ -0,0 +1,2919 @@
+# Manpage
+```manpage
+LSOF(8)                     System Manager's Manual                    LSOF(8)
+
+NAME
+       lsof - list open files
+
+SYNOPSIS
+       lsof  [  -?abChHlnNOPQRtUvVX  ] [ -A A ] [ -c c ] [ +c c ] [ +|-d d ] [
+       +|-D D ] [ +|-e s ] [ +|-E ] [ +|-f [cfgGn] ] [ -F [f] ] [ -g [s]  ]  [
+       -i  [i] ] [ -k k ] [ -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.99.0  lists  on  its standard output file information
+       about files opened by processes for the following UNIX dialects:
+
+            Apple Darwin 9, Mac OS X 10, macOS 11 and above
+            FreeBSD 8.2 and above
+            Linux 2.1.72 and above
+            NetBSD 1.2 and above
+            OpenBSD 7.2 and above
+            Solaris 9, 10 and 11 and above
+            OpenIndiana 5.11 and above
+
+       (See the DISTRIBUTION section of this manual page  for  information  on
+       how to obtain the latest lsof revision.)
+
+       An  open file may be a regular file, a directory, a block special file,
+       a character special file, an executing text  reference,  a  library,  a
+       stream  or  a  network  file  (Internet socket, NFS file or UNIX domain
+       socket.)  A specific file or all the files in a file system may be  se‐
+       lected by path.
+
+       Instead  of  a  formatted display, lsof will produce output that can be
+       parsed by other programs.  See the -F, option description, and the OUT‐
+       PUT FOR OTHER PROGRAMS section for more information.
+
+       In  addition to producing a single output list, lsof will run in repeat
+       mode.  In repeat mode it will produce output, delay,  then  repeat  the
+       output  operation  until stopped with an interrupt or quit signal.  See
+       the +|-r [t[m<fmt>]] option description for more information.
+
+OPTIONS
+       In the absence of any options, lsof lists all open files  belonging  to
+       all active processes.
+
+       If  any  list  request option is specified, other list requests must be
+       specifically requested - e.g., if -U is specified for  the  listing  of
+       UNIX  socket  files, NFS files won't be listed unless -N is also speci‐
+       fied; 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 un‐
+       less 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 pro‐
+       duces a listing of all network files OR files  belonging  to  processes
+       owned by user ``foo''.  The exceptions are:
+
+       1) the `^' (negated) login name or user ID (UID), specified with the -u
+          option;
+
+       2) the `^' (negated) process ID (PID), specified with the -p option;
+
+       3) the `^' (negated) process group ID (PGID), specified with the -g op‐
+          tion;
+
+       4) the `^' (negated) command, specified with the -c option;
+
+       5) the  (`^')  negated  TCP or UDP protocol state names, specified with
+          the -s [p:s] option.
+
+       Since they represent exclusions, they are applied without ORing or AND‐
+       ing and take effect before any other selection criteria are applied.
+
+       The -a option may be used to AND the selections.  For example, specify‐
+       ing -a, -U, and -ufoo produces a listing of only UNIX socket files that
+       belong to processes owned by user ``foo''.
+
+       Caution:  the  -a option causes all list selection options to be ANDed;
+       it can't be used to cause ANDing of selected pairs of selection options
+       by  placing it between them, even though its placement there is accept‐
+       able.  Wherever -a is placed, it causes the ANDing of all selection op‐
+       tions.
+
+       Items of the same selection set - command names, file descriptors, net‐
+       work addresses, process identifiers, user identifiers, zone names,  se‐
+       curity  contexts  -  are joined in a single ORed set and applied before
+       the result participates  in  ANDing.   Thus,  for  example,  specifying
+       -i@aaa.bbb,  -i@ccc.ddd,  -a,  and -ufff,ggg will select the listing of
+       files that belong to either login ``fff'' OR ``ggg'' AND  have  network
+       connections to either host aaa.bbb OR ccc.ddd.
+
+       Options  may be grouped together following a single prefix -- e.g., the
+       option set ``-a -b -C'' may be stated as -abC.  However,  since  values
+       are optional following +|-f, -F, -g, -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 fol‐
+       lowing  the  -F option.  When ambiguity is 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 for each prefix - e.g., -i
+       - may be grouped under either prefix.  Thus, for example, ``+M -i'' may
+       be  stated  as ``+Mi'' and the group means the same as the separate op‐
+       tions.  Be careful of prefix grouping when one or more options  in  the
+       group  does  take on separate meanings under different prefixes - e.g.,
+       +|-M; ``-iM'' is not the same request as ``-i +M''.  When in doubt, use
+       separate options with appropriate prefixes.
+
+       -? -h    These  two  equivalent  options  select  a usage (help) output
+                list.  Lsof displays a shortened form of this output  when  it
+                detects  an  error in the options supplied to it, after it has
+                displayed messages explaining each  error.   (Escape  the  `?'
+                character as your shell requires.)
+
+       -a       causes list selection options to be ANDed, as described above.
+
+       -A A     is  available  on  systems configured for AFS whose AFS kernel
+                code is implemented via dynamic modules.  It allows  the  lsof
+                user  to  specify  A  as an alternate name list file where the
+                kernel addresses of the dynamic modules might be  found.   See
+                the  lsof  FAQ (The FAQ section gives its location.)  for more
+                information about dynamic modules, their symbols, and how they
+                affect lsof.
+
+       -b       causes  lsof  to  avoid  kernel  functions  that might block -
+                lstat(2), readlink(2), and stat(2).
+
+                See the BLOCKS AND TIMEOUTS and AVOIDING  KERNEL  BLOCKS  sec‐
+                tions for information on using this option.
+
+       -c c     selects  the listing of files for processes executing the com‐
+                mand that begins with the characters of c.  Multiple  commands
+                may  be specified, using multiple -c options.  They are joined
+                in a single ORed set before participating in AND option selec‐
+                tion.
+
+                If  c begins with a `^', then the following characters specify
+                a command name whose processes are to be ignored (excluded.)
+
+                If c begins and ends with a slash ('/'),  the  characters  be‐
+                tween  the  slashes  are  interpreted as a regular expression.
+                Shell meta-characters in the regular expression must be quoted
+                to  prevent  their  interpretation  by the shell.  The closing
+                slash may be followed by these modifiers:
+
+                     b    the regular expression is a basic one.
+                     i    ignore the case of letters.
+                     x    the regular expression is an extended one
+                          (default).
+
+                See the lsof FAQ (The FAQ section gives  its  location.)   for
+                more information on basic and extended regular expressions.
+
+                The  simple  command  specification  is tested first.  If that
+                test fails, the command regular expression is applied.  If the
+                simple  command  test succeeds, the command regular expression
+                test isn't made.  This may result in ``no  command  found  for
+                regex:'' messages when lsof's -V option is specified.
+
+       +c w     defines  the maximum number of initial characters of the name,
+                supplied by the UNIX dialect, of the UNIX  command  associated
+                with a process to be printed in the COMMAND column.  (The lsof
+                default is nine.)
+
+                Note that many UNIX dialects do not supply  all  command  name
+                characters to lsof in the files and structures from which lsof
+                obtains command name.  Often  dialects  limit  the  number  of
+                characters  supplied  in  those  sources.   For example, Linux
+                2.4.27 and Solaris 9 both limit  command  name  length  to  16
+                characters.
+
+                If w is zero ('0'), all command characters supplied to lsof by
+                the UNIX dialect will be printed.
+
+                If w is less than the length of the column title, ``COMMAND'',
+                it will be raised to that length.
+
+       -C       disables  the  reporting  of any path name components from the
+                kernel's name cache.  See the KERNEL NAME  CACHE  section  for
+                more information.
+
+       +d s     causes  lsof  to  search for all open instances of directory s
+                and the files and directories it contains at  its  top  level.
+                +d does NOT descend the directory tree, rooted at s.  The +D D
+                option may be used to request a  full-descent  directory  tree
+                search, rooted at directory D.
+
+                Processing  of  the  +d  option does not follow symbolic links
+                within s unless the -x or -x  l option is also specified.  Nor
+                does  it  search for open files on file system mount points on
+                subdirectories of s unless the -x or  -x   f  option  is  also
+                specified.
+
+                Note:  the  authority  of the user of this option limits it to
+                searching for files that the user has  permission  to  examine
+                with the system stat(2) function.
+
+       -d s     specifies  a list of file descriptors (FDs) to exclude from or
+                include in the output listing.  The file descriptors are spec‐
+                ified  in  the  comma-separated  set  s  -  e.g., ``cwd,1,3'',
+                ``^6,^2''.  (There should be no spaces in the set.)
+
+                The list is an exclusion list if all entries of the set  begin
+                with  `^'.   It  is  an inclusion list if no entry begins with
+                `^'.  Mixed lists are not permitted.
+
+                A file descriptor number range may be in the set  as  long  as
+                neither  member  is  empty,  both members are numbers, and the
+                ending member is larger than the starting one - e.g.,  ``0-7''
+                or  ``3-10''.   Ranges  may be specified for exclusion if they
+                have the `^' prefix - e.g., ``^0-7''  excludes  all  file  de‐
+                scriptors 0 through 7.
+
+                Multiple  file  descriptor numbers are joined in a single ORed
+                set before participating in AND option selection.
+
+                When there are exclusion and inclusion  members  in  the  set,
+                lsof  reports  them as errors and exits with a non-zero return
+                code.
+
+                See the description of File Descriptor (FD) output  values  in
+                the  OUTPUT  section  for  more information on file descriptor
+                names.
+
+                fd is a pseudo file descriptor name for specifying  the  whole
+                range of possible file descriptor numbers.  fd does not appear
+                in FD column of output.
+
+       +D D     causes lsof to search for all open instances  of  directory  D
+                and  all the files and directories it contains to its complete
+                depth.
+
+                Processing of the +D option does  not  follow  symbolic  links
+                within D unless the -x or -x  l option is also specified.  Nor
+                does it search for open files on file system mount  points  on
+                subdirectories  of  D  unless  the  -x or -x  f option is also
+                specified.
+
+                Note: the authority of the user of this option  limits  it  to
+                searching  for  files  that the user has permission to examine
+                with the system stat(2) function.
+
+                Further note: lsof may process this option slowly and  require
+                a large amount of dynamic memory to do it.  This is because it
+                must descend the entire directory tree, rooted at  D,  calling
+                stat(2)  for  each  file and directory, building a list of all
+                the files it finds, and searching that list for a  match  with
+                every  open  file.  When directory D is large, these steps can
+                take a long time, so use this option prudently.
+
+       -D D     directs lsof's use of the device cache file.  The use of  this
+                option  is  sometimes  restricted.   See the DEVICE CACHE FILE
+                section and the sections that follow it for  more  information
+                on this option.
+
+                -D  must be followed by a function letter; the function letter
+                may optionally be followed by a path  name.   Lsof  recognizes
+                these function letters:
+
+                     ? - report device cache file paths
+                     b - build the device cache file
+                     i - ignore the device cache file
+                     r - read the device cache file
+                     u - read and update the device cache file
+
+                The  b,  r,  and  u functions, accompanied by a path name, are
+                sometimes restricted.  When these  functions  are  restricted,
+                they  will not appear in the description of the -D option that
+                accompanies -h or -?  option output.   See  the  DEVICE  CACHE
+                FILE section and the sections that follow it for more informa‐
+                tion on these functions and when they're restricted.
+
+                The ?  function reports the read-only  and  write  paths  that
+                lsof can use for the device cache file, the names of any envi‐
+                ronment variables whose values lsof will examine when  forming
+                the  device  cache  file path, and the format for the personal
+                device cache file path.  (Escape the  `?'  character  as  your
+                shell requires.)
+
+                When  available,  the b, r, and u functions may be followed by
+                the  device  cache  file's  path.   The  standard  default  is
+                .lsof_hostname  in the home directory of the real user ID that
+                executes lsof, but this could have been changed when lsof  was
+                configured  and  compiled.   (The output of the -h and -?  op‐
+                tions show the current default prefix - e.g., ``.lsof''.)  The
+                suffix,  hostname,  is  the first component of the host's name
+                returned by gethostname(2).
+
+                When available, the b function directs lsof to build a new de‐
+                vice cache file at the default or specified path.
+
+                The i function directs lsof to ignore the default device cache
+                file and obtain its information about devices via direct calls
+                to the kernel.
+
+                The  r  function  directs lsof to read the device cache at the
+                default or specified path, but prevents it from creating a new
+                device  cache file when none exists or the existing one is im‐
+                properly structured.  The r function, when specified without a
+                path  name,  prevents  lsof from updating an incorrect or out‐
+                dated device cache file, or creating a new one in  its  place.
+                The  r function is always available when it is specified with‐
+                out a path name argument; it may be restricted by the  permis‐
+                sions of the lsof process.
+
+                When available, the u function directs lsof to read the device
+                cache file at the default or specified path, if possible,  and
+                to rebuild it, if necessary.  This is the default device cache
+                file function when no -D option has been specified.
+
+       +|-e s   exempts the file system whose path name is s from  being  sub‐
+                jected  to kernel function calls that might block.  The +e op‐
+                tion exempts stat(2), lstat(2)  and  most  readlink(2)  kernel
+                function  calls.   The  -e  option  exempts  only  stat(2) and
+                lstat(2) kernel function calls.  Multiple file systems may  be
+                specified  with separate +|-e specifications and each may have
+                readlink(2) calls exempted or not.
+
+                This option is currently implemented only for Linux.
+
+                CAUTION: this option can easily be mis-applied to  other  than
+                the  file system of interest, because it uses path name rather
+                than the more reliable device and inode numbers.  (Device  and
+                inode  numbers  are  acquired  via  the  potentially  blocking
+                stat(2) kernel call and are thus not available,  but  see  the
+                +|-m  m  option as a possible alternative way to supply device
+                numbers.)  Use this option with great care and  fully  specify
+                the path name of the file system to be exempted.
+
+                When  open files on exempted file systems are reported, it may
+                not be possible to obtain all their  information.   Therefore,
+                some   information  columns  will  be  blank,  the  characters
+                ``UNKN'' preface the values in the TYPE column, and the appli‐
+                cable  exemption  option is added in parentheses to the end of
+                the NAME column.  (Some device  number  information  might  be
+                made available via the +|-m m option.)
+
+       +|-E     +E specifies that Linux pipe, Linux UNIX socket, Linux INET(6)
+                socket closed in a local  host,  Linux  pseudoterminal  files,
+                POSIX  Message  Queueue  implementation  in  Linux,  and Linux
+                eventfd should be displayed with endpoint information and  the
+                files of the endpoints should also be displayed.
+
+                Note  1:  UNIX socket file endpoint information is only avail‐
+                able when the features enabled line of -v output contains  ux‐
+                sockept, and psudoterminal endpoint information is only avail‐
+                able when the features enabled line contains ptyept.
+
+                Note 2: POSIX Message Queue file endpoint information is  only
+                available when mqueue file system is mounted.
+
+                Pipe  endpoint  information is displayed in the NAME column in
+                the form ``PID,cmd,FDmode'', where 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.
+
+                Pseudoterminal  endpoint  information is displayed in the NAME
+                column as  ``->/dev/ptsmin PID,cmd,FDmode''  or  ``PID,cmd,FD‐
+                mode''.   The  first  form is for a master device; the second,
+                for a slave device.  min is a slave device's minor device num‐
+                ber;  and PID, cmd, FD and mode are the same as with pipe end‐
+                point information.  Note: psudoterminal  endpoint  information
+                is  only available when the features enabled line of -v output
+                contains ptyept. In addition, this feature works on Linux ker‐
+                nels above 4.13.0.
+
+                UNIX socket file endpoint information is displayed in the NAME
+                column in the form
+                ``type=TYPE ->INO=INODE PID,cmd,FDmode'', where  TYPE  is  the
+                socket  type;  INODE  is  the  i-node  number of the connected
+                socket; and PID, cmd, FD and mode are the same  as  with  pipe
+                endpoint  information.  Note: UNIX socket file endpoint infor‐
+                mation is available only when the features enabled line of  -v
+                output contains uxsockept.
+
+                INET socket file endpoint information is inserted to the value
+                at the NAME column in the form
+                `` -> PID,cmd,FDmode'', where PID, cmd, FD and  mode  are  the
+                same  as with pipe endpoint information. The endpoint informa‐
+                tion is available only if the socket is used  for  local  IPC;
+                both endpoints bind to the same local IPv4 or IPv6 address.
+
+                POSIX  Message Queue file endpoint information is displayed in
+                the NAME column in the same form as that of pipe.
+
+                eventfd endpoint information is displayed in the  NAME  column
+                in  the same form as that of pipe. This feature works on Linux
+                kernels above 5.2.0.
+
+                Multiple occurrences of  this  information  can  appear  in  a
+                file's NAME column.
+
+                -E specifies that endpoint supported files should be displayed
+                with endpoint information, but not the files of the endpoints.
+
+       +|-f [cfgGn]
+                f by itself clarifies how path name arguments are to be inter‐
+                preted.   When followed by c, f, g, G, or n in any combination
+                it specifies that the listing of kernel file structure  infor‐
+                mation is to be enabled (`+') or inhibited (`-').
+
+                Normally  a  path  name  argument is taken to be a file system
+                name if it matches a mounted-on  directory  name  reported  by
+                mount(8),  or  if  it  represents a block device, named in the
+                mount output and associated with  a  mounted  directory  name.
+                When +f is specified, all path name arguments will be taken to
+                be file system names, and lsof will complain if any  are  not.
+                This  can  be  useful,  for example, when the 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 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.
+
+                Be careful to make sure +f and -f are properly terminated  and
+                aren't followed by a character (e.g., of the file or file sys‐
+                tem 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 structures, re‐
+                quested with the +f [cfgGn] option form,  is  normally  inhib‐
+                ited,  and is not available in whole or part for some dialects
+                - e.g., /proc-based Linux kernels below 2.6.22.  When the pre‐
+                fix  to  f is a plus sign (`+'), these characters request file
+                structure information:
+
+                     c    file structure use count (not Linux)
+                     f    file structure address (not Linux)
+                     g    file flag abbreviations (Linux 2.6.22 and up)
+
+                          Abbrev.   Flag in C code (see open(2))
+
+                          W         O_WRONLY
+                          RW        O_RDWR
+                          CR        O_CREAT
+                          EXCL      O_EXCL
+                          NTTY      O_NOCTTY
+                          TR        O_TRUNC
+                          AP        O_APPEND
+                          ND        O_NDELAY
+                          SYN       O_SYNC
+                          ASYN      O_ASYNC
+                          DIR       O_DIRECT
+                          DTY       O_DIRECTORY
+                          NFLK      O_NOFOLLOW
+                          NATM      O_NOATIME
+                          DSYN      O_DSYNC
+                          RSYN      O_RSYNC
+                          LG        O_LARGEFILE
+                          CX        O_CLOEXEC
+                          TMPF      O_TMPFILE
+
+                     G    file flags in hexadecimal (Linux 2.6.22 and up)
+                     n    file structure node address (not Linux)
+
+                When the prefix is minus (`-') the same characters disable the
+                listing of the indicated values.
+
+                File  structure  addresses,  use  counts,  flags, and node ad‐
+                dresses may be used to detect more readily identical files in‐
+                herited  by child processes and identical files in use by dif‐
+                ferent processes.  Lsof column output can be sorted by  output
+                columns  holding  the  values and listed to identify identical
+                file use, or lsof field output can be parsed by an AWK or Perl
+                post-filter script, or by a C program.
+
+       -F f     specifies  a  character list, f, that selects the fields to be
+                output for processing by another program,  and  the  character
+                that terminates each output field.  Each field to be output is
+                specified with a single character in f.  The field  terminator
+                defaults to NL, but may be changed to NUL (000).  See the OUT‐
+                PUT FOR OTHER PROGRAMS section for a description of the  field
+                identification characters and the field output process.
+
+                When the field selection character list is empty, all standard
+                fields are selected (except the  raw  device  field,  security
+                context  and  zone field for compatibility reasons) and the NL
+                field terminator is used.
+
+                When the field selection character list contains only  a  zero
+                (`0'),  all  fields  are selected (except the raw device field
+                for compatibility reasons) and the NUL terminator character is
+                used.
+
+                Other combinations of fields and their associated field termi‐
+                nator character must be set with explicit entries in f, as de‐
+                scribed in the OUTPUT FOR OTHER PROGRAMS section.
+
+                When  a field selection character identifies an item lsof does
+                not normally list - e.g., PPID, selected with -R -  specifica‐
+                tion of the field character - e.g., ``-FR'' - also selects the
+                listing of the item.
+
+                When the field selection character list  contains  the  single
+                character  `?',  lsof  will  display  a help list of the field
+                identification characters.  (Escape the `?' character as  your
+                shell requires.)
+
+       -g [s]   excludes  or  selects  the  listing of files for the processes
+                whose optional process group IDentification (PGID) numbers are
+                in  the comma-separated set s - e.g., ``123'' or ``123,^456''.
+                (There should be no spaces in the set.)
+
+                PGID numbers that begin with `^' (negation)  represent  exclu‐
+                sions.
+
+                Multiple  PGID  numbers are joined in a single ORed set before
+                participating in AND option selection.  However,  PGID  exclu‐
+                sions  are applied without ORing or ANDing and take effect be‐
+                fore other selection criteria are applied.
+
+                The -g option also enables the output display of PGID numbers.
+                When specified without a PGID set that's all it does.
+
+       -H       directs  lsof  to  print  human  readable  sizes,  e.g. 123.4K
+                456.7M.
+
+       -i [i]   selects the listing of files any  of  whose  Internet  address
+                matches  the  address specified in i.  If no address is speci‐
+                fied, this option selects the listing of all Internet and x.25
+                (HP-UX) network files.
+
+                If  -i4  or  -i6  is specified with no following address, only
+                files of the indicated IP version,  IPv4  or  IPv6,  are  dis‐
+                played.   (An  IPv6  specification may be used only if the di‐
+                alects supports IPv6, as indicated by ``[46]'' and ``IPv[46]''
+                in  lsof's  -h  or  -?  output.)  Sequentially specifying -i4,
+                followed by -i6 is the same as specifying -i, and  vice-versa.
+                Specifying  -i4, or -i6 after -i is the same as specifying -i4
+                or -i6 by itself.
+
+                Multiple addresses (up to a limit of  100)  may  be  specified
+                with  multiple  -i  options.   (A  port number or service name
+                range is counted as one address.)  They are joined in a single
+                ORed set before participating in AND option selection.
+
+                An  Internet address is specified in the form (Items in square
+                brackets are optional.):
+
+                [46][protocol][@hostname|hostaddr][:service|port]
+
+                where:
+                     46 specifies the IP version, IPv4 or IPv6
+                          that applies to the following address.
+                          '6' may be be specified only if the UNIX
+                          dialect supports IPv6.  If neither '4' nor
+                          '6' is specified, the following address
+                          applies to all IP versions.
+                     protocol is a protocol name - TCP, UDP or UDPLITE.
+                     hostname is an Internet host name.  Unless a
+                          specific IP version is specified, open
+                          network files associated with host names
+                          of all versions will be selected.
+                     hostaddr is a numeric Internet IPv4 address in
+                          dot form; or an IPv6 numeric address in
+                          colon form, enclosed in brackets, if the
+                          UNIX dialect supports IPv6.  When an IP
+                          version is selected, only its numeric
+                          addresses may be specified.
+                     service is an /etc/services name - e.g., smtp -
+                          or a list of them.
+                     port is a port number, or a list of them.
+
+                IPv6 options may be used only if  the  UNIX  dialect  supports
+                IPv6.  To see if the dialect supports IPv6, run lsof and spec‐
+                ify the -h or -?  (help) option.  If the displayed description
+                of  the  -i  option contains ``[46]'' and ``IPv[46]'', IPv6 is
+                supported.
+
+                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 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  file's
+                type  will be IPv6, not IPv4, and its display will be selected
+                by '6', not '4'.
+
+                At least one address component -  4,  6,  protocol,  hostname,
+                hostaddr,  or  service - must be supplied.  The `@' character,
+                leading the host specification, is always required; as is  the
+                `:',  leading the port specification.  Specify either hostname
+                or hostaddr.  Specify either service name list or port  number
+                list.   If  a service name list is specified, 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 - for protocol.
+
+                Service names and port numbers may be combined in a list whose
+                entries  are  separated  by commas and whose numeric range en‐
+                tries are separated by minus signs.  There may be no  embedded
+                spaces,  and  all  service  names must belong to the specified
+                protocol.  Since service  names  may  contain  embedded  minus
+                signs,  the starting entry of a range can't be a service name;
+                it can be a port number, however.
+
+                Here are some sample addresses:
+
+                     -i6 - IPv6 only
+                     TCP:25 - TCP and port 25
+                     @1.2.3.4 - Internet IPv4 host address 1.2.3.4
+                     @[3ffe:1ebc::1]:1234 - Internet IPv6 host address
+                          3ffe:1ebc::1, port 1234
+                     UDP:who - UDP who service port
+                     TCP@lsof.itap:513 - TCP, port 513 and host name lsof.itap
+                     tcp@foo:1-10,smtp,99 - TCP, ports 1 through 10,
+                          service name smtp, port 99, host name foo
+                     tcp@bar:1-smtp - TCP, ports 1 through smtp, host bar
+                     :time - either TCP, UDP or UDPLITE time service port
+
+       -K k     selects the listing of tasks (threads) of  processes,  on  di‐
+                alects  where  task (thread) reporting is supported.  (If help
+                output - i.e., the output of the -h or  -?   options  -  shows
+                this  option, then task (thread) reporting is supported by the
+                dialect.)
+
+                If -K is followed by a value,  k,  it  must  be  ``i''.   That
+                causes  lsof  to  ignore  tasks,  particularly in the default,
+                list-everything case when no other options are specified.
+
+                When -K and -a are both specified on Linux, and the 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.
+
+       -l       inhibits the conversion of user ID numbers to login names.  It
+                is also useful when login name lookup is working improperly or
+                slowly.
+
+       +|-L [l] enables  (`+')  or  disables  (`-')  the  listing of file link
+                counts, where they are available - e.g., they aren't available
+                for sockets, or most FIFOs and pipes.
+
+                When  +L  is  specified  without  a following number, all link
+                counts will be listed.  When -L is specified (the default), no
+                link counts will be listed.
+
+                When  +L  is  followed  by  a number, only files having a link
+                count less than that number will be listed.   (No  number  may
+                follow  -L.)   A specification of the form ``+L1'' will select
+                open files that have been unlinked.  A  specification  of  the
+                form ``+aL1 <file_system>'' will select unlinked open files on
+                the specified file system.
+
+                For other link count comparisons, use field output (-F) and  a
+                post-processing script or program.
+
+       +|-m m   specifies  an  alternate kernel memory file or activates mount
+                table supplement processing.
+
+                The option form -m m specifies a kernel  memory  file,  m,  in
+                place of /dev/kmem or /dev/mem - e.g., a crash dump file.
+
+                The  option  form  +m requests that a mount supplement file be
+                written to the standard output file.  All  other  options  are
+                silently ignored.
+
+                There  will  be  a  line in the mount supplement file for each
+                mounted file system, containing the mounted file system direc‐
+                tory,  followed by a single space, followed by the device num‐
+                ber in hexadecimal "0x" format - e.g.,
+
+                     / 0x801
+
+                Lsof can use the mount supplement file to get  device  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 supplement file.
+
+                Note: the +m and +m m options are not available for  all  sup‐
+                ported dialects.  Check the output of lsof's -h or -?  options
+                to see if the +m and +m m options are available.
+
+       +|-M     Enables (+) or disables (-) the reporting of portmapper regis‐
+                trations for local TCP, UDP and UDPLITE ports, where port map‐
+                ping is supported.  (See the last paragraph of this option de‐
+                scription  for information about where portmapper registration
+                reporting is supported.)
+
+                The default reporting mode is set by the lsof builder with the
+                HASPMAPENABLED #define in the dialect's machine.h header file;
+                lsof is distributed with the  HASPMAPENABLED  #define  deacti‐
+                vated, so portmapper reporting is disabled by default and must
+                be requested with +M.  Specifying lsof's -h or -?  option will
+                report  the  default  mode.  Disabling portmapper registration
+                when it is already disabled or enabling it  when  already  en‐
+                abled  is  acceptable.  When portmapper registration reporting
+                is enabled, lsof displays the portmapper registration (if any)
+                for local TCP, UDP or UDPLITE ports in square brackets immedi‐
+                ately following the port numbers  or  service  names  -  e.g.,
+                ``:1234[name]'' or ``:name[100083]''.  The registration infor‐
+                mation may be a name or number, depending on what  the  regis‐
+                tering  program  supplied to the portmapper when it registered
+                the port.
+
+                When portmapper registration reporting is  enabled,  lsof  may
+                run a little more slowly or even become blocked when access to
+                the portmapper becomes congested or stopped.  Reverse the  re‐
+                porting mode to determine if portmapper registration reporting
+                is slowing or blocking lsof.
+
+                For purposes of portmapper registration reporting lsof consid‐
+                ers  a  TCP,  UDP or UDPLITE port local if: it is found in the
+                local part of its containing kernel structure; or if it is lo‐
+                cated  in  the foreign part of its containing kernel structure
+                and the local and foreign Internet addresses are the same;  or
+                if  it is located in the foreign part of its containing kernel
+                structure and the foreign Internet address is  INADDR_LOOPBACK
+                (127.0.0.1).   This  rule  may  make  lsof ignore some foreign
+                ports on machines with multiple interfaces  when  the  foreign
+                Internet  address  is  on a different interface from the local
+                one.
+
+                See the lsof FAQ (The FAQ section gives  its  location.)   for
+                further  discussion  of  portmapper registration reporting is‐
+                sues.
+
+                Portmapper registration reporting is  supported  only  on  di‐
+                alects  that have RPC header files.  (Some Linux distributions
+                with GlibC 2.14 do not have them.)  When portmapper  registra‐
+                tion  reporting  is  supported, the -h or -?  help output will
+                show the +|-M option.
+
+       -n       inhibits the conversion of network numbers to host  names  for
+                network  files.   Inhibiting  conversion  may  make  lsof  run
+                faster.  It is also useful when host name lookup is not  work‐
+                ing properly.
+
+       -N       selects the listing of NFS files.
+
+       -o       directs  lsof  to display file offset at all times.  It causes
+                the SIZE/OFF output column title  to  be  changed  to  OFFSET.
+                Note: on some UNIX dialects lsof can't obtain accurate or con‐
+                sistent file offset information from its kernel data  sources,
+                sometimes  just  for  particular  kinds of files (e.g., socket
+                files.)  Consult the lsof FAQ (The FAQ section gives its loca‐
+                tion.)  for more information.
+
+                The  -o and -s options are mutually exclusive; they can't both
+                be specified.  When neither is specified, lsof displays  what‐
+                ever value - size or offset - is appropriate and available for
+                the type of the file.
+
+       -o o     defines the number of decimal digits (o) to be  printed  after
+                the  ``0t''  for  a file offset before the form is switched to
+                ``0x...''.  An o value of zero (unlimited) directs lsof to use
+                the ``0t'' form for all offset output.
+
+                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 of digits after ``0t'' in either
+                mixed size and offset or offset-only output.  Thus, for  exam‐
+                ple, to direct lsof to display offset at all times with a dec‐
+                imal digit count of 10, use:
+
+                     -o -o 10
+                or
+                     -oo10
+
+                The default number of digits allowed after ``0t'' is  normally
+                8, but may have been changed by the 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.
+
+       -O       directs  lsof  to  bypass  the strategy it uses to avoid being
+                blocked by some kernel operations - i.e., doing them in forked
+                child  processes.   See  the  BLOCKS AND TIMEOUTS and AVOIDING
+                KERNEL BLOCKS sections for more information on  kernel  opera‐
+                tions that may block lsof.
+
+                While use of this option will reduce lsof startup overhead, it
+                may also cause lsof to hang when the kernel doesn't respond to
+                a function.  Use this option cautiously.
+
+       -p s     excludes  or  selects  the  listing of files for the processes
+                whose optional process IDentification (PID) numbers are in the
+                comma-separated set s - e.g., ``123'' or ``123,^456''.  (There
+                should be no spaces in the set.)
+
+                PID numbers that begin with `^'  (negation)  represent  exclu‐
+                sions.
+
+                Multiple  process  ID  numbers are joined in a single ORed set
+                before participating in AND option  selection.   However,  PID
+                exclusions are applied without ORing or ANDing and take effect
+                before other selection criteria are applied.
+
+       -P       inhibits the conversion of port numbers to port names for net‐
+                work  files.   Inhibiting  the  conversion may make lsof run a
+                little faster.  It is also useful when port name lookup is not
+                working properly.
+
+       -Q       ignore  failed  search  terms. When lsof is told to search for
+                users of a file, or for users of a device, or for  a  specific
+                PID,  or  for certain protocols in use by that PID, and so on,
+                lsof will return an error if any of  the  search  results  are
+                empty.  The  -Q  option will change this behavior so that lsof
+                will instead return a successful exit code (0) even if any  of
+                the  search  results  are  empty.  In addition, missing search
+                terms will not be reported to stderr.
+
+       +|-r [t[c<N>][m<fmt>]]
+                puts lsof in repeat mode.  There lsof lists open files as  se‐
+                lected  by  other options, delays t seconds (default fifteen),
+                then repeats the listing, delaying  and  listing  repetitively
+                until  stopped by a condition defined by the prefix to the op‐
+                tion.
+
+                If the prefix is a `-', repeat mode is endless.  Lsof must  be
+                terminated  with  an  interrupt or quit signal.  `c<N>' is for
+                specifying the limits of repeating; if the  number  of  itera‐
+                tions reaches at `<N>', Lsof stops itself.
+
+                If  the prefix is `+', repeat mode will end the first cycle no
+                open files are listed - and of course  when  lsof  is  stopped
+                with  an  interrupt or quit signal.  When repeat mode ends be‐
+                cause no files are listed, the process exit code will be  zero
+                if  any  open  files  were ever listed; one, if none were ever
+                listed.
+
+                Lsof marks the end of each listing:  if  field  output  is  in
+                progress  (the  -F,  option  has  been specified), the default
+                marker is `m'; otherwise the default marker  is  ``========''.
+                The marker is followed by a NL character.
+
+                The  optional  "m<fmt>"  argument  specifies  a format for the
+                marker line.  The <fmt> characters following  `m'  are  inter‐
+                preted  as a format specification to the strftime(3) function,
+                when both it and the localtime(3) function  are  available  in
+                the  dialect's  C library.  Consult the strftime(3) documenta‐
+                tion for what may appear in its  format  specification.   Note
+                that  when field output is requested with the -F option, <fmt>
+                cannot contain the NL format, ``%n''.   Note  also  that  when
+                <fmt>  contains  spaces  or  other  characters that affect the
+                shell's interpretation of arguments, <fmt> must be quoted  ap‐
+                propriately.
+
+                Repeat mode reduces lsof startup overhead, so it is more effi‐
+                cient to use this mode than to call lsof repetitively  from  a
+                shell script, for example.
+
+                To use repeat mode most efficiently, accompany +|-r with spec‐
+                ification of other lsof selection options, so  the  amount  of
+                kernel memory access lsof does will be kept to a minimum.  Op‐
+                tions that filter at the process level - e.g., -c, -g, -p,  -u
+                - are the most efficient selectors.
+
+                Repeat  mode is useful when coupled with field output (see the
+                -F, option description) and a supervising awk or Perl  script,
+                or a C program.
+
+       -R       directs  lsof to list the Parent Process IDentification 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  di‐
+                alects, 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 to be excluded if their  state  name(s)
+                are  in  the  list (s) preceded by a `^'; or included if their
+                name(s) are not preceded by a `^'.
+
+                Dialects that support this option may support only one  proto‐
+                col.   When  an  unsupported  protocol is specified, a message
+                will be displayed indicating state names for the protocol  are
+                unavailable.
+
+                When  an  inclusion  list  is defined, only network files with
+                state names in the list will be present in  the  lsof  output.
+                Thus,  specifying one state name means that only network files
+                with that lone state name will be listed.
+
+                Case is unimportant in the protocol or state names, but  there
+                may  be  no spaces and the colon (`:') separating the protocol
+                name (p) and the state name list (s) is required.
+
+                If only TCP and UDP files are to be listed, as  controlled  by
+                the specified exclusions and inclusions, the -i option must be
+                specified, too.  If only a single protocol's files are  to  be
+                listed, add its name as an argument to the -i option.
+
+                For example, to list only network files with TCP state LISTEN,
+                use:
+
+                     -iTCP -sTCP:LISTEN
+
+                Or, for example, to list network files with all UDP states ex‐
+                cept Idle, use:
+
+                     -iUDP -sUDP:^Idle
+
+                State  names  vary with UNIX dialects, so it's not possible to
+                provide a complete list.  Some common  TCP  state  names  are:
+                CLOSED,  IDLE, BOUND, LISTEN, ESTABLISHED, SYN_SENT, SYN_RCDV,
+                ESTABLISHED,   CLOSE_WAIT,   FIN_WAIT1,   CLOSING,   LAST_ACK,
+                FIN_WAIT_2, and TIME_WAIT.  Two common UDP state names are Un‐
+                bound and Idle.
+
+                See the lsof FAQ (The FAQ section gives  its  location.)   for
+                more  information  on  how to use protocol state exclusion and
+                inclusion, including examples.
+
+                The -o (without a following decimal digit count) and -s option
+                (without  a  following protocol and state name list) are mutu‐
+                ally exclusive; they can't both be specified.  When neither is
+                specified,  lsof displays whatever value - size or offset - is
+                appropriate and available for the type of file.
+
+                Since some types of files don't have true sizes - sockets, FI‐
+                FOs,  pipes,  etc. - lsof displays for their sizes the content
+                amounts in their associated kernel buffers, if possible.
+
+       -S [t]   specifies an optional time-out seconds value for kernel  func‐
+                tions - lstat(2), readlink(2), and stat(2) - that might other‐
+                wise deadlock.  The minimum for t is two;  the  default,  fif‐
+                teen; when no value is specified, the default is used.
+
+                See the BLOCKS AND TIMEOUTS section for more information.
+
+       -T [t]   controls  the  reporting of some TCP/TPI information, also re‐
+                ported by netstat(1), following  the  network  addresses.   In
+                normal  output  the  information  appears in parentheses, each
+                item except TCP or TPI state name  identified  by  a  keyword,
+                followed by `=', separated from others by a single space:
+
+                     <TCP or TPI state name>
+                     QR=<read queue length>
+                     QS=<send queue length>
+                     SO=<socket options and values>
+                     SS=<socket states>
+                     TF=<TCP flags and values>
+                     WR=<window read length>
+                     WW=<window write length>
+
+                Not all values are reported for all UNIX dialects.  Items val‐
+                ues (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  informa‐
+                tion 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.
+
+                Not all selections are enabled for some UNIX dialects.   State
+                may  be  selected for all dialects and is reported by default.
+                The -h or -?  help output for the -T option will show what se‐
+                lections may be used with the UNIX dialect.
+
+                When  -T  is used to select information - i.e., it is followed
+                by one or more selection characters - the displaying of  state
+                is  disabled  by  default,  and it must be explicitly selected
+                again in the characters following -T.  (In effect,  then,  the
+                default  is equivalent to -Ts.)  For example, if queue lengths
+                and state are desired, use -Tqs.
+
+                Socket options, socket states, some socket values,  TCP  flags
+                and  one TCP value may be reported (when available in the UNIX
+                dialect) in the form of the names that commonly  appear  after
+                SO_,  so_,  SS_, TCP_  and TF_ in the dialect's header files -
+                most    often    <sys/socket.h>,     <sys/socketvar.h>     and
+                <netinet/tcp_var.h>.  Consult those header files for the mean‐
+                ing of the flags, options, states and values.
+
+                ``SO='' precedes socket options and  values;  ``SS='',  socket
+                states; and ``TF='', TCP flags and values.
+
+                If  a flag or option has a value, the value will follow an '='
+                and  the  name  --   e.g.,   ``SO=LINGER=5'',   ``SO=QLIM=5'',
+                ``TF=MSS=512''.  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 for particular UNIX  di‐
+                alects  may  be  found in the answer to the ``Why doesn't lsof
+                report socket options, socket states, and TCP flags and values
+                for  my  dialect?''  and ``Why doesn't lsof report the partial
+                listen queue connection count for my dialect?''  questions  in
+                the  lsof  FAQ (The FAQ section gives its location.)  On Linux
+                this option also prints the state of UNIX domain sockets.
+
+       -t       produce  terse  output  comprising  only  process  identifiers
+                (without  a  header),  so  that it is easy to use programmati‐
+                cally. e.g.
+
+                     # reload anything using old SSL
+                     lsof -t /lib/*/libssl.so.* | xargs -r kill -HUP
+
+                     # get list of processes and then iterate over them (Bash only)
+                     mapfile -t pids < <(
+                         lsof -wt /var/log/your.log
+                     )
+                     for pid in "${pids[@]}" ; do
+                         your_command -p "$pid"
+                     done
+
+                The -t option implies the -w option.
+
+       -u s     selects the listing of files for the user whose login names or
+                user  ID  numbers  are  in  the  comma-separated set s - e.g.,
+                ``abe'', or ``548,root''.  (There should be no spaces  in  the
+                set.)
+
+                Multiple login names or user ID numbers are joined in a single
+                ORed set before participating in AND option selection.
+
+                If a login name or user ID is preceded by a `^', it becomes  a
+                negation - i.e., files of processes owned by the login name or
+                user ID will never be listed.  A negated login name or user ID
+                selection  is neither ANDed nor ORed with other selections; it
+                is applied before all other selections and absolutely excludes
+                the  listing of the files of the process.  For example, to di‐
+                rect lsof to exclude the listing of files  belonging  to  root
+                processes, specify ``-u^root'' or ``-u^0''.
+
+       -U       selects the listing of UNIX domain socket files.
+
+       -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 com‐
+                pile-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 option prevents the listing of the open
+                file containing the located search item.
+
+                For example, ``lsof -V -iTCP@foobar -a -d 999'' may not report
+                a failure to locate open files at ``TCP@foobar'' and  may  not
+                list  any,  if  none  have a file descriptor number of 999.  A
+                similar situation arises when HASSECURITY  and  HASNOSOCKSECU‐
+                RITY  are defined at compile time and they prevent the listing
+                of open files.
+
+       +|-w     Enables (+) or disables (-) the suppression  of  warning  mes‐
+                sages.
+
+                The  lsof builder may choose to have warning messages disabled
+                or enabled by default.  The default warning message  state  is
+                indicated  in  the  output of the -h or -?  option.  Disabling
+                warning messages when they are already  disabled  or  enabling
+                them when already enabled is acceptable.
+
+                The -t option implies the -w option.
+
+       -x [fl]  may accompany the +d and +D options to direct their processing
+                to cross over symbolic links and|or file system  mount  points
+                encountered when scanning the directory (+d) or directory tree
+                (+D).
+
+                If -x is specified by itself without  a  following  parameter,
+                cross-over  processing  of both symbolic links and file system
+                mount points is enabled.  Note that when -x is specified with‐
+                out a parameter, the next argument must begin with '-' or '+'.
+
+                The  optional  'f'  parameter  enables file system mount point
+                cross-over processing; 'l', symbolic link cross-over  process‐
+                ing.
+
+                The  -x option may not be supplied without also supplying 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 completely that it can neither be killed
+                nor stopped.  I have never seen this happen or had a report of
+                its  happening,  but  I think there is a remote possibility it
+                could happen.
+
+                By default use of readx() is disabled.  On AIX  5L  and  above
+                lsof  may  need  setuid-root permission to perform the actions
+                this option requests.
+
+                The lsof builder may specify that the -X option be  restricted
+                to  processes  whose real UID is root.  If that has been done,
+                the -X option will not appear in the -h or -?  help output un‐
+                less  the  real  UID of the lsof process is root.  The default
+                lsof distribution allows any UID to specify -X, so by  default
+                it will appear in the help output.
+
+                When  AIX readx() use is disabled, lsof may not be able to re‐
+                port information for all text and loader file references,  but
+                it  may also avoid exacerbating an AIX kernel directory search
+                kernel error, known as the Stale Segment ID bug.
+
+                The readx() function, used by lsof or any other program to ac‐
+                cess  some  sections of kernel virtual memory, can trigger the
+                Stale Segment ID bug.  It can cause the kernel's  dir_search()
+                function to believe erroneously that part of an in-memory copy
+                of a file system directory has been zeroed.  Another  applica‐
+                tion  process, distinct from lsof, asking the kernel to search
+                the  directory  -  e.g.,  by  using  open(2)   -   can   cause
+                dir_search()  to  loop  forever,  thus hanging the application
+                process.
+
+                Consult the lsof FAQ (The FAQ  section  gives  its  location.)
+                and the 00README file of the lsof distribution for a more com‐
+                plete 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 in‐
+                formation on all open TCP,  UDP  and  UDPLITE  IPv4  and  IPv6
+                files.
+
+                This  Linux  option  is most useful when the system has an ex‐
+                tremely 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 sure that the
+                information you want lsof to  display  isn't  associated  with
+                open TCP, UDP or UDPLITE socket files.
+
+           Solaris 10 and above:
+                This  Solaris  10  and  above option requests the reporting of
+                cached paths for files that have been deleted - i.e.,  removed
+                with rm(1) or unlink(2).
+
+                The  cached  path  is followed by the string `` (deleted)'' to
+                indicate that the path by which the file was opened  has  been
+                deleted.
+
+                Because  intervening  changes made to the path - i.e., renames
+                with mv(1) or rename(2) - are not recorded in the cached path,
+                what  lsof  reports  is  only  the  path by which the file was
+                opened, not its possibly different final path.
+
+       -z [z]   specifies how Solaris 10 and higher zone information is to  be
+                handled.
+
+                Without  a following argument - e.g., NO z - the option speci‐
+                fies that zone names are to be listed in the ZONE output  col‐
+                umn.
+
+                The  -z option may be followed by a zone name, z.  That causes
+                lsof to list only open files for processes in that zone.  Mul‐
+                tiple  -z z option and argument pairs may be specified to form
+                a list of named zones.  Any open file of any process in any of
+                the  zones  will be listed, subject to other conditions speci‐
+                fied 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 running Linux kernel.   See  OUTPUT
+                FOR  OTHER PROGRAMS for more information on the 'Z' field out‐
+                put character.
+
+                Without a following argument - e.g., NO Z - the option  speci‐
+                fies  that  security  contexts  are  to be listed in the SECU‐
+                RITY-CONTEXT output column.
+
+                The -Z option may be followed by a wildcard  security  context
+                name,  Z.   That  causes lsof to list only open files for pro‐
+                cesses in that security context.  Multiple -Z Z option and ar‐
+                gument  pairs may be specified to form a list of security con‐
+                texts.  Any open file of any process in any  of  the  security
+                contexts will be listed, subject to other conditions specified
+                by other options and arguments.  Note that Z can be  A:B:C  or
+                *:B:C or A:B:* or *:*:C to match against the A:B:C context.
+
+       --       The  double minus sign option is a marker that signals the end
+                of the keyed options.  It may be used, for example,  when  the
+                first file name begins with a minus sign.  It may also be used
+                when the absence of a value for the last keyed option must  be
+                signified by the presence of a minus sign in the following op‐
+                tion and before the start of the file names.
+
+       names    These are path names of  specific  files  to  list.   Symbolic
+                links  are  resolved  before use.  The first name may be sepa‐
+                rated from the preceding options with the ``--'' option.
+
+                If a name is the mounted-on directory of a file system or  the
+                device  of  the file system, lsof will list all the files open
+                on the file system.  To be considered a file system, the  name
+                must  match a mounted-on directory name in mount(8) output, or
+                match the name of a block device associated with a  mounted-on
+                directory  name.  The +|-f option may be used to force lsof to
+                consider a name a file system identifier (+f) or a simple file
+                (-f).
+
+                If  name  is  a path to a directory that is not the mounted-on
+                directory name of a file system, it is treated just as a regu‐
+                lar  file is treated - i.e., its listing is restricted to pro‐
+                cesses that have it open as a file or  as  a  process-specific
+                directory,  such as the root or current working directory.  To
+                request that lsof look for open files inside a directory name,
+                use the +d s and +D D options.
+
+                If  a name is the base name of a family of multiplexed files -
+                e.g, AIX's /dev/pt[cs] - lsof will  list  all  the  associated
+                multiplexed  files  on  the  device  that  are  open  -  e.g.,
+                /dev/pt[cs]/1, /dev/pt[cs]/2, etc.
+
+                If a name is a UNIX domain  socket  name,  lsof  will  usually
+                search for it by the characters of the name alone - exactly as
+                it is specified and is recorded in the  kernel  socket  struc‐
+                ture.   (See  the next 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 - won't
+                work because lsof must match the characters you  specify  with
+                what it finds in the kernel UNIX domain socket structures.
+
+                If a name is a Linux UNIX domain socket name, in one case lsof
+                is able to search for it by its device and inode  number,  al‐
+                lowing name to be a relative path.  The case requires that the
+                absolute path -- i.e., one beginning with  a  slash  ('/')  be
+                used  by  the  process  that  created the socket, and hence be
+                stored in the /proc/net/unix file; and it requires  that  lsof
+                be  able to obtain the device and node numbers of both the ab‐
+                solute path in /proc/net/unix and name via successful  stat(2)
+                system  calls.   When  those  conditions are met, lsof will be
+                able to search for the UNIX domain socket when some path to it
+                is  is  specified  in name.  Thus, for example, if the path is
+                /dev/log, and an lsof search is initiated when the working di‐
+                rectory is /dev, then name could be ./log.
+
+                If  a name is none of the above, lsof will list any open files
+                whose device and inode match that of the specified path name.
+
+                If you have also specified the -b option, the only  names  you
+                may safely specify are file systems for which your mount table
+                supplies alternate device numbers.  See  the  AVOIDING  KERNEL
+                BLOCKS and ALTERNATE DEVICE NUMBERS sections for more informa‐
+                tion.
+
+                Multiple file names are joined in a  single  ORed  set  before
+                participating in AND option selection.
+
+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  recog‐
+       nizing 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 calculating AFS volume node numbers.  When lsof  can't  com‐
+       pute volume node numbers, it reports blank in the NODE column.
+
+       The  -A  A  option is available in some dialect implementations of lsof
+       for specifying the name list file where dynamic module kernel addresses
+       may  be found.  When this option is available, it will be listed in the
+       lsof help output, presented in response to the -h or -?
+
+       See the lsof FAQ (The FAQ section gives its location.)  for more infor‐
+       mation  about  dynamic modules, their symbols, and how they affect lsof
+       options.
+
+       Because AFS path lookups don't seem to participate in the kernel's name
+       cache  operations,  lsof  can't  identify  path name components for AFS
+       files.
+
+SECURITY
+       Lsof has three features that may cause security concerns.   First,  its
+       default  compilation mode allows anyone to list all open files with it.
+       Second, by default it creates a user-readable and user-writable  device
+       cache  file  in  the  home  directory of the real user ID that executes
+       lsof.  (The list-all-open-files and device cache features may  be  dis‐
+       abled when lsof is compiled.)  Third, its -k and -m options name alter‐
+       nate kernel name list or memory files.
+
+       Restricting the listing of all open files is  controlled  by  the  com‐
+       pile-time  HASSECURITY and HASNOSOCKSECURITY options.  When HASSECURITY
+       is defined, lsof will allow only the root user to list all open  files.
+       The  non-root  user may list only open files of processes with the same
+       user IDentification 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  op‐
+       tion.
+
+       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 HASNOSOCKSE‐
+       CURITY options enabled.
+
+       Creation and use of a user-readable and user-writable device cache file
+       is  controlled  by  the  compile-time HASDCACHE option.  See the DEVICE
+       CACHE FILE section and the sections that follow it for details  on  how
+       its  path  is  formed.   For security considerations it is important to
+       note that in the default lsof distribution, if the real user  ID  under
+       which  lsof  is executed is root, the device cache file will be written
+       in root's home directory - e.g., / or /root.  When HASDCACHE is not de‐
+       fined, lsof does not write or attempt to read a device cache file.
+
+       When  HASDCACHE is defined, the lsof help output, presented in response
+       to the -h, -D?, or -?  options, will provide device cache file handling
+       information.   When HASDCACHE is not defined, the -h or -?  output will
+       have no -D option description.
+
+       Before you decide to disable the device cache file feature  -  enabling
+       it improves the performance of lsof by reducing the startup overhead of
+       examining all the nodes in /dev (or /devices) - read the discussion  of
+       it  in the 00DCACHE file of the lsof distribution and the lsof FAQ (The
+       FAQ section gives its location.)
+
+       WHEN IN DOUBT, YOU CAN TEMPORARILY DISABLE THE USE OF THE DEVICE  CACHE
+       FILE WITH THE -Di OPTION.
+
+       When lsof user declares alternate kernel name list or memory files with
+       the -k and -m options, lsof checks the user's authority  to  read  them
+       with  access(2).   This  is  intended to prevent whatever special power
+       lsof's modes might confer on it from letting it read files not normally
+       accessible via the authority of the real user ID.
+
+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 charac‐
+       ters.  Non-printable characters are printed in one of three forms:  the
+       C  ``\[bfrnt]'' form; the control character `^' form (e.g., ``^@''); or
+       hexadecimal leading ``\x'' form (e.g., ``\xab'').  Space is  non-print‐
+       able in the COMMAND column (``\x20'') and printable elsewhere.
+
+       For  some  dialects  -  if HASSETLOCALE is defined in the dialect's ma‐
+       chine.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 variable (e.g., LANG) whose value represents a  known  lan‐
+       guage  locale in which the extended characters are considered printable
+       by isprint(3).  Otherwise lsof considers the extended  characters  non-
+       printable  and  prints  them  according  to its rules for non-printable
+       characters, stated above.  Consult your dialect's setlocale(3) man page
+       for  the names of other environment variables that may be used in place
+       of LANG - e.g., LC_ALL, LC_CTYPE, etc.
+
+       Lsof's language locale support for a dialect also covers  wide  charac‐
+       ters  -  e.g., UTF-8 - when HASSETLOCALE and HASWIDECHAR are defined in
+       the dialect's machine.h header file, and when a suitable  language  lo‐
+       cale  has  been defined in the appropriate environment variable for the
+       lsof process.  Wide characters are printable under those conditions  if
+       iswprint(3)  reports  them  to  be.  If HASSETLOCALE, HASWIDECHAR and a
+       suitable language locale aren't defined, or if iswprint(3) reports wide
+       characters  that  aren't  printable, lsof considers the wide characters
+       non-printable and prints each of their 8 bits according  to  its  rules
+       for non-printable characters, stated above.
+
+       Consult  the  answers to the "Language locale support" questions in the
+       lsof FAQ (The FAQ section gives its location.) for more information.
+
+       Lsof dynamically sizes the output columns each time it runs, guarantee‐
+       ing  that  each column is a minimum size.  It also guarantees that each
+       column is separated from its predecessor by at least one space.
+
+       COMMAND    contains the first nine characters of the name of  the  UNIX
+                  command  associated with the process.  If a non-zero w value
+                  is specified to the +c w option,  the  column  contains  the
+                  first  w  characters of the name of the UNIX command associ‐
+                  ated 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, ``COM‐
+                  MAND'', it will be raised to that length.
+
+                  If a zero w value is specified to the +c w option, the  col‐
+                  umn contains all the characters of the name of the UNIX com‐
+                  mand 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  section  for information on selecting field
+                  output and the associated command name descriptor.
+
+       PID        is the Process IDentification number of the process.
+
+       TID        is the task (thread) IDentification number, if task (thread)
+                  reporting is supported by the dialect and a task (thread) is
+                  being listed.  (If help output - i.e., the output of the  -h
+                  or  -?   options - shows this option, then task (thread) re‐
+                  porting is supported by the dialect.)
+
+                  A blank TID column in Linux indicates a process  -  i.e.,  a
+                  non-task.
+
+       TASKCMD    is  the  task command name.  Generally this will be the same
+                  as the process named in the COMMAND column,  but  some  task
+                  implementations  (e.g.,  Linux)  permit a task to change its
+                  command name.
+
+                  The TASKCMD column width is subject to the same size limita‐
+                  tion as the COMMAND column.
+
+       ZONE       is the Solaris 10 and higher zone name.  This column must be
+                  selected with the -z option.
+
+       SECURITY-CONTEXT
+                  is the SELinux security context.  This column  must  be  se‐
+                  lected  with  the -Z option.  Note that the -Z option is in‐
+                  hibited when SELinux is disabled in the running  Linux  ker‐
+                  nel.
+
+       PPID       is  the Parent Process IDentification number of the process.
+                  It is only displayed when the -R option has been specified.
+
+       PGID       is the process group IDentification number  associated  with
+                  the  process.   It  is only displayed when the -g option has
+                  been specified.
+
+       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  in‐
+                  formation  on  when  a  user ID number or login name is dis‐
+                  played.)
+
+       FD         is the File Descriptor number of the file or:
+
+                       cwd  current working directory;
+                       Lnn  library references (AIX);
+                       ctty character tty;
+                       DEL  deleted file;
+                       err  FD information error (see NAME column);
+                       fp.  Fileport (Darwin);
+                       jld  jail directory (FreeBSD);
+                       ltx  shared library text (code and data);
+                       Mxx  hex memory-mapped type number xx.
+                       m86  DOS Merge mapped file;
+                       mem  memory-mapped file;
+                       mmap memory-mapped device;
+                       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;
+                       pd   parent directory;
+                       Rnn  unknown pregion number (HP-UX);
+                       rtd  root directory;
+                       twd  per task current working directory;
+                       txt  program text (code and data);
+                       v86  VP/ix mapped file;
+
+                  FD is followed by one of these  characters,  describing  the
+                  mode under which the file is open:
+
+                       r for read access;
+                       w for write access;
+                       u for read and write access;
+                       space if mode unknown and no lock
+                            character follows;
+                       `-' if mode unknown and lock
+                            character follows.
+
+                  The  mode character is followed by one of these lock charac‐
+                  ters, describing the type of lock applied to the file:
+
+                       N for a Solaris NFS lock of unknown type;
+                       r for read lock on part of the file;
+                       R for a read lock on the entire file;
+                       w for a write lock on part of the file;
+                       W for a write lock on the entire file;
+                       u for a read and write lock of any length;
+                       U for a lock of unknown type;
+                       x for an SCO OpenServer Xenix lock on part 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  in‐
+                  formation character.
+
+                  The  FD column contents constitutes a single field for pars‐
+                  ing in post-processing scripts. FD numbers larger than  9999
+                  are  abbreviated  to a ``*'' followed by the last three dig‐
+                  its. E.g., 10001 appears as ``*001''
+
+       TYPE       is the type of the node associated with  the  file  -  e.g.,
+                  VDIR, VREG, etc.
+
+                  or ``ax25'' for a Linux AX.25 socket;
+
+                  or ``a_inode'' for anonymous inode;
+
+                  or ``icmp'' for an ICMP socket;
+
+                  or ``inet'' for an Internet domain socket;
+
+                  or ``ipx'' for an IPX socket;
+
+                  or ``key'' for an internal key management socket;
+
+                  or ``lla'' for a HP-UX link level access file;
+
+                  or ``ndrv'' for a net driver socket;
+
+                  or ``netlink'' for a netlink socket;
+
+                  or ``pack'' for a packet socket;
+
+                  or ``ppp'' for a PPP socket;
+
+                  or ``raw'' for a raw socket;
+
+                  or ``raw6'' for a raw IPv6 socket;
+
+                  or ``rte'' for an AF_ROUTE socket;
+
+                  or ``sock'' for a socket of unknown domain;
+
+                  or ``systm'' for a system socket;
+
+                  or ``unix'' for a UNIX domain socket;
+
+                  or ``x.25'' for an HP-UX x.25 socket;
+
+                  or ``ATALK'' for an AppleTalk socket;
+
+                  or ``BLK'' for a block special file;
+
+                  or ``CHR'' for a character special file;
+
+                  or ``DEL'' for a Linux map file that has been deleted;
+
+                  or ``DIR'' for a directory;
+
+                  or ``DOOR'' for a VDOOR file;
+
+                  or ``EVENTFD'' for an eventfd;
+
+                  or ``FIFO'' for a FIFO special file;
+
+                  or ``FSEVENTS'' for fsevents;
+
+                  or ``IPv4'' for an IPv4 socket;
+
+                  or  ``IPv6'' for an open IPv6 network file - even if its ad‐
+                  dress is IPv4, mapped in an IPv6 address;
+
+                  or ``KQUEUE'' for a BSD style kernel event queue file;
+
+                  or ``LINK'' for a symbolic link file;
+
+                  or ``MPB'' for a multiplexed block file;
+
+                  or ``MPC'' for a multiplexed character file;
+
+                  or ``PAS'' for a /proc/as file;
+
+                  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;
+
+                  or ``PCWD'' for a /proc current working directory;
+
+                  or ``PDIR'' for a /proc directory;
+
+                  or ``PETY'' for a /proc executable type (etype);
+
+                  or ``PFD'' for a /proc file descriptor;
+
+                  or ``PFDR'' for a /proc file descriptor directory;
+
+                  or ``PFIL'' for an executable /proc file;
+
+                  or ``PFPR'' for a /proc FP register set;
+
+                  or ``PGD'' for a /proc/pagedata file;
+
+                  or ``PGID'' for a /proc group notifier file;
+
+                  or ``PIPE'' for pipes;
+
+                  or ``PLC'' for a /proc/lwpctl file;
+
+                  or ``PLDR'' for a /proc/lpw directory;
+
+                  or ``PLDT'' for a /proc/ldt file;
+
+                  or ``PLPI'' for a /proc/lpsinfo file;
+
+                  or ``PLST'' for a /proc/lstatus file;
+
+                  or ``PLU'' for a /proc/lusage file;
+
+                  or ``PLWG'' for a /proc/gwindows file;
+
+                  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);
+
+                  or ``PMPS'' for a /proc/maps file;
+
+                  or ``PMEM'' for a /proc memory image file;
+
+                  or ``PNTF'' for a /proc process notifier file;
+
+                  or ``POBJ'' for a /proc/object file;
+
+                  or ``PODR'' for a /proc/object directory;
+
+                  or ``POLP'' for an old format  /proc  light  weight  process
+                  file;
+
+                  or ``POPF'' for an old format /proc PID file;
+
+                  or ``POPG'' for an old format /proc page data file;
+
+                  or ``PORT'' for a SYSV named pipe;
+
+                  or ``PREG'' for a /proc register file;
+
+                  or ``PRMP'' for a /proc/rmap file;
+
+                  or ``PROCDSC'' for a processor descriptor;
+
+                  or ``PRTD'' for a /proc root directory;
+
+                  or ``PSGA'' for a /proc/sigact file;
+
+                  or ``PSIN'' for a /proc/psinfo file;
+
+                  or ``PSTA'' for a /proc status file;
+
+                  or ``PSXMQ'' for a POSIX message queue file;
+
+                  or ``PSXSEM'' for a POSIX semaphore file;
+
+                  or ``PSXSHM'' for a POSIX shared memory file;
+
+                  or ``PTS'' for a /dev/pts file;
+
+                  or ``PUSG'' for a /proc/usage file;
+
+                  or ``PW'' for a /proc/watch file;
+
+                  or ``PXMP'' for a /proc/xmap file;
+
+                  or ``REG'' for a regular file;
+
+                  or ``SHM'' for a shared memory file;
+
+                  or ``SMT'' for a shared memory transport file;
+
+                  or ``STR'' for streams;
+
+                  or ``STSO'' for a stream socket;
+
+                  or ``UNKN'' for an unknown file;
+
+                  or ``UNKNcwd'' for unknown current working directory;
+
+                  or ``UNKNdel'' for unknown deleted file;
+
+                  or ``UNKNfd'' for unknown file descriptor;
+
+                  or ``UNKNmem'' for unknown memory-mapped file;
+
+                  or ``UNKNrtd'' for unknown root directory;
+
+                  or ``UNKNtxt'' for unknown program text;
+
+                  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 ``UNSP'' for an unsupported file;
+
+                  or the four type number octets  if  the  corresponding  name
+                  isn't known.
+
+       FILE-ADDR  contains  the  kernel file structure address when f has been
+                  specified to +f;
+
+       FCT        contains the file  reference  count  from  the  kernel  file
+                  structure when c has been specified to +f;
+
+       FILE-FLAG  when  g  or  G has been specified to +f, this field contains
+                  the contents of the f_flag[s]  member  of  the  kernel  file
+                  structure  and  the kernel's per-process open file flags (if
+                  available); `G' causes them to be displayed in  hexadecimal;
+                  `g',  as  short-hand  names; two lists may be displayed with
+                  entries separated by commas, the lists separated by a  semi‐
+                  colon (`;'); the first list may contain short-hand names for
+                  f_flag[s] values from the following table:
+
+                       AIO       asynchronous I/O (e.g., FAIO)
+                       AP        append
+                       ASYN      asynchronous I/O (e.g., FASYNC)
+                       BAS       block, test, and set in use
+                       BKIU      block if in use
+                       BL        use block offsets
+                       BSK       block seek
+                       CA        copy avoid
+                       CIO       concurrent I/O
+                       CLON      clone
+                       CLRD      CL read
+                       CR        create
+                       DF        defer
+                       DFI       defer IND
+                       DFLU      data flush
+                       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
+                       LG        large file
+                       MBLK      stream message block
+                       MK        mark
+                       MNT       mount
+                       MSYN      multiplex synchronization
+                       NATM      don't update atime
+                       NB        non-blocking I/O
+                       NBDR      no BDRM check
+                       NBIO      SYSV non-blocking I/O
+                       NBF       n-buffering in effect
+                       NC        no cache
+                       ND        no delay
+                       NDSY      no data synchronization
+                       NET       network
+                       NFLK      don't follow links
+                       NMFS      NM file system
+                       NOTO      disable background stop
+                       NSH       no share
+                       NTTY      no controlling TTY
+                       OLRM      OLR mirror
+                       PAIO      POSIX asynchronous I/O
+                       PATH      path
+                       PP        POSIX pipe
+                       R         read
+                       RC        file and record locking cache
+                       REV       revoked
+                       RSH       shared read
+                       RSYN      read synchronization
+                       RW        read and write access
+                       SL        shared lock
+                       SNAP      cooked snapshot
+                       SOCK      socket
+                       SQSH      Sequent shared set on open
+                       SQSV      Sequent SVM set on open
+                       SQR       Sequent set repair on open
+                       SQS1      Sequent full shared open
+                       SQS2      Sequent partial shared open
+                       STPI      stop I/O
+                       SWR       synchronous read
+                       SYN       file integrity while writing
+                       TCPM      avoid TCP collision
+                       TMPF      temporary file
+                       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 common.h  header
+                  file for a list showing the correspondence between the above
+                  short-hand names and the header file definitions;
+
+                  the second list (after the semicolon) may contain short-hand
+                  names  for  kernel per-process open file flags from this ta‐
+                  ble:
+
+                       ALLC      allocated
+                       BR        the file has been read
+                       BHUP      activity stopped by SIGHUP
+                       BW        the file has been written
+                       CLSG      closing
+                       CX        close-on-exec (see fcntl(F_SETFD))
+                       LCK       lock was applied
+                       MP        memory-mapped
+                       OPIP      open pending - in progress
+                       RSVW      reserved wait
+                       SHMT      UF_FSHMAT set (AIX)
+                       USE       in use (multi-threaded)
+
+       NODE-ID    (or INODE-ADDR for some dialects) contains a unique  identi‐
+                  fier  for  the  file node (usually the kernel vnode or inode
+                  address, but also occasionally a concatenation of device and
+                  node number) when n has been specified to +f;
+
+       DEVICE     contains  the  device  numbers,  separated  by commas, for a
+                  character special, block special, regular, directory or  NFS
+                  file;
+
+                  or  ``memory''  for  a  memory  file system node under Tru64
+                  UNIX;
+
+                  or the address of the private data area of a Solaris  socket
+                  stream;
+
+                  or  a kernel reference address that identifies the file (The
+                  kernel reference address may be used for FIFO's,  for  exam‐
+                  ple.);
+
+                  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 appropri‐
+                  ate for the type of the file and the version of lsof.
+
+                  On some UNIX dialects lsof can't obtain accurate or  consis‐
+                  tent  file  offset information from its kernel data sources,
+                  sometimes just for particular kinds of files  (e.g.,  socket
+                  files.)  In other cases, files don't have true sizes - e.g.,
+                  sockets, FIFOs, pipes - so lsof displays for their sizes the
+                  content  amounts it finds in their kernel buffer descriptors
+                  (e.g., socket buffer size counts or  TCP/IP  window  sizes.)
+                  Consult  the  lsof FAQ (The FAQ section gives its location.)
+                  for more information.
+
+                  The file size is displayed in decimal; the  offset  is  nor‐
+                  mally  displayed in decimal with a leading ``0t'' if it con‐
+                  tains 8 digits or less; in hexadecimal with a leading ``0x''
+                  if it is longer than 8 digits.  (Consult the -o o option de‐
+                  scription for information on when 8 might  default  to  some
+                  other value.)
+
+                  Thus  the  leading ``0t'' and ``0x'' identify an offset when
+                  the column may contain both a size and an offset (i.e.,  its
+                  title is SIZE/OFF).
+
+                  If the -o option is specified, lsof always displays the file
+                  offset (or nothing if no offset is available) and labels the
+                  column  OFFSET.   The  offset  always  begins with ``0t'' or
+                  ``0x'' as described above.
+
+                  The lsof user can control the switch from ``0t''  to  ``0x''
+                  with  the -o o option.  Consult its description for more in‐
+                  formation.
+
+                  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.
+
+                  If  the  -H  option is specified, lsof displays file size in
+                  human readable form.
+
+                  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;
+
+                  or the Internet protocol type - e.g, ``TCP'';
+
+                  or ``STR'' for a stream;
+
+                  or ``CCITT'' for an HP-UX x.25 socket;
+
+                  or the IRQ or inode number of a Linux AX.25 socket device.
+
+       NAME       is  the name of the mount point and file system on which the
+                  file resides;
+
+                  or the name of a file specified in the names  option  (after
+                  any symbolic links have been resolved);
+
+                  or the name of a character special or block special device;
+
+                  or  the  local  and  remote  Internet addresses of a network
+                  file; the local host name or IP  number  is  followed  by  a
+                  colon  (':'),  the port, ``->'', and the two-part remote ad‐
+                  dress; IP addresses may be reported as numbers or names, de‐
+                  pending  on  the  +|-M,  -n, and -P options; colon-separated
+                  IPv6 numbers are  enclosed  in  square  brackets;  IPv4  IN‐
+                  ADDR_ANY  and  IPv6  IN6_IS_ADDR_UNSPECIFIED  addresses, and
+                  zero port numbers are represented by an  asterisk  ('*');  a
+                  UDP  destination  address  may  be followed by the amount of
+                  time elapsed since the last packet was sent to the  destina‐
+                  tion;  TCP, UDP and UDPLITE remote addresses may be followed
+                  by TCP/TPI information in parentheses - state (e.g.,  ``(ES‐
+                  TABLISHED)'',  ``(Unbound)''), queue sizes, and window sizes
+                  (not all dialects) - 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 OTHER PROGRAMS for more  in‐
+                  formation on state, queue size, and window size;
+
+                  or the address or name of a UNIX domain socket, possibly in‐
+                  cluding a stream clone device name, a file  system  object's
+                  path  name,  local and foreign kernel addresses, socket pair
+                  information, and a bound vnode address;
+
+                  or the local and remote mount point names of an NFS file;
+
+                  or ``STR'', followed by the stream name;
+
+                  or a stream character device name, followed  by  ``->''  and
+                  the  stream name or a list of stream module names, separated
+                  by ``->'';
+
+                  or ``STR:'' followed by the SCO OpenServer stream device and
+                  module names, separated by ``->'';
+
+                  or  system  directory name, `` -- '', and as many components
+                  of the path name as lsof can find in the kernel's name cache
+                  for selected dialects (See the KERNEL NAME CACHE section for
+                  more information.);
+
+                  or ``PIPE->'', followed by a Solaris kernel pipe destination
+                  address;
+
+                  or  ``COMMON:'',  followed  by  the vnode device information
+                  structure's device name, for a Solaris common vnode;
+
+                  or the address family, followed by a slash  (`/'),  followed
+                  by  fourteen  comma-separated  bytes  of  a non-Internet raw
+                  socket address;
+
+                  or the HP-UX x.25 local address,  followed  by  the  virtual
+                  connection  number  (if any), followed by the remote address
+                  (if any);
+
+                  or ``(dead)'' for disassociated Tru64 UNIX files - typically
+                  terminal  files  that  have  been flagged with the TIOCNOTTY
+                  ioctl and closed by daemons;
+
+                  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  func‐
+                  tion;
+
+                  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>, followed  in  parentheses
+                  by  the transmit and receive queue sizes, and the connection
+                  state;
+
+                  or ``dgram'' or ``stream'' for the type UnixWare  7.1.1  and
+                  above  in-kernel  UNIX  domain  sockets, followed by a colon
+                  (':') and the local path name when  available,  followed  by
+                  ``->''  and the remote path name or kernel socket address in
+                  hexadecimal when available;
+
+                  or the association value, association index, endpoint value,
+                  local  address,  local  port, remote address and remote port
+                  for Linux SCTP sockets;
+
+                  or ``protocol: '' followed by the  Linux  socket's  protocol
+                  attribute.
+
+       For  dialects  that support a ``namefs'' file system, allowing one file
+       to be attached to another with fattach(3C), lsof  will  add  ``(FA:<ad‐
+       dress1><direction><address2>)''  to  the  NAME  column.  <address1> and
+       <address2> are hexadecimal vnode addresses.  <direction> will be ``<-''
+       if  <address2>  has been fattach'ed to this vnode whose address is <ad‐
+       dress1>; and ``->'' if <address1>, the vnode address of this vnode, has
+       been fattach'ed to <address2>.  <address1> may be omitted if it already
+       appears in the DEVICE column.
+
+       Lsof may add two parenthetical notes to the NAME column  for  open  So‐
+       laris 10 files: ``(?)'' if lsof considers the path name of questionable
+       accuracy; and ``(deleted)'' if the -X option  has  been  specified  and
+       lsof  detects  the open file's path name has been deleted.  Consult the
+       lsof FAQ (The FAQ 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  information 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 character will be reported in lower case
+       -  i.e.,  `r',  `w', or `x' - rather than the upper case equivalent re‐
+       ported for a full file lock.
+
+       Generally lsof can only report on locks held by local processes on  lo‐
+       cal  files.   When  a  local  process sets a lock on a remotely mounted
+       (e.g., NFS) file, the remote  server  host  usually  records  the  lock
+       state.   One exception is Solaris - at some patch levels of 2.3, and in
+       all versions above 2.4, the Solaris kernel records information  on  re‐
+       mote locks in local structures.
+
+       Lsof  has  trouble reporting locks for some UNIX dialects.  Consult the
+       BUGS section of this manual page or the lsof FAQ (The FAQ section gives
+       its location.)  for more information.
+
+OUTPUT FOR OTHER PROGRAMS
+       When  the -F option is specified, lsof produces output that is suitable
+       for processing by another program - e.g, an awk or Perl script, or a  C
+       program.
+
+       Each unit of information is output in a field that is identified with a
+       leading character and terminated by a NL (012) (or a NUL (000) if the 0
+       (zero) field identifier character is specified.)  The data of the field
+       follows immediately after the field identification  character  and  ex‐
+       tends to the field terminator.
+
+       It  is  possible  to think of field output as process and file sets.  A
+       process set begins with a field whose identifier is  `p'  (for  process
+       IDentifier  (PID)).   It extends to the beginning of the next PID field
+       or the beginning of the first file set of the process, whichever  comes
+       first.   Included  in the process set are fields that identify the com‐
+       mand, the process group IDentification (PGID) number, the task (thread)
+       ID (TID), and the user ID (UID) number or login name.
+
+       A  file  set  begins with a field whose identifier is `f' (for file de‐
+       scriptor).  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 to the beginning of the next  file  or
+       process set, whichever comes first.
+
+       When the NUL (000) field terminator has been selected with the 0 (zero)
+       field identifier character, lsof ends each process and file set with  a
+       NL (012) character.
+
+       Lsof  always  produces one field, the PID (`p') field.  In repeat mode,
+       the marker (`m') is also produced.  All other fields  may  be  declared
+       optionally  in  the field identifier character list that follows the -F
+       option.  When a field selection character identifies an item lsof  does
+       not normally list - e.g., PPID, selected with -R - specification of the
+       field character - e.g., ``-FR'' - also selects the listing of the item.
+
+       Lsof version from 4.88 to 4.93.2 always produced one  more  field,  the
+       file descriptor (`f') field. However, lsof in this version doesn't pro‐
+       duce it. This change is for supporting the use case that a  user  needs
+       only the PID field, and doesn't need the file descriptor field. Specify
+       `f' explicitly if you need the field.
+
+       It is entirely possible to select a set of fields that cannot easily be
+       parsed - e.g., if the field descriptor field is not selected, it may be
+       difficult to identify file sets.  To help you  avoid  this  difficulty,
+       lsof  supports  the -F option; it selects the output of all fields with
+       NL terminators (the -F0 option pair selects the output  of  all  fields
+       with  NUL  terminators).   For compatibility reasons neither -F nor -F0
+       select the raw device field.
+
+       These are the fields that lsof  will  produce.   The  single  character
+       listed first is the field identifier.
+
+            a    file access mode
+            c    process command name (all characters from proc or
+                 user structure)
+            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 structure address (0x<hexadecimal>)
+            G    file flaGs (0x<hexadecimal>; names if +fg follows)
+            g    process group ID
+            i    file's inode number
+            K    tasK ID
+            k    link count
+            l    file's lock status
+            L    process login name
+            m    marker between repeated output (always selected in repeat mode)
+            M    the task comMand name
+            n    file name, comment, Internet address
+            N    node identifier (ox<hexadecimal>
+            o    file's offset (0t<decimal> or 0x<hexadecimal>, see -o o)
+            p    process ID (always selected)
+            P    protocol name
+            r    raw device number (0x<hexadecimal>)
+            R    parent process ID
+            s    file's size (decimal)
+            S    file's stream identification
+            t    file's type
+            T    TCP/TPI information, identified by prefixes (the
+                 `=' is part of the prefix):
+                     QR=<read queue size>
+                     QS=<send queue size>
+                     SO=<socket options and values> (not all dialects)
+                     SS=<socket states> (not all dialects)
+                     ST=<connection state>
+                     TF=<TCP flags and values> (not all dialects)
+                     WR=<window read size>  (not all dialects)
+                     WW=<window write size>  (not all dialects)
+                 (TCP/TPI information isn't reported for all supported
+                   UNIX dialects. The -h or -? help output for the
+                   -T option will show what TCP/TPI reporting can be
+                   requested.)
+            u    process user ID
+            z    Solaris 10 and higher zone name
+            Z    SELinux security context (inhibited when SELinux is disabled)
+            0    use NUL field terminator character in place of NL
+            1-9  dialect-specific field identifiers (The output
+                 of -F? identifies the information to be found
+                 in dialect-specific fields.)
+
+       You  can get on-line help information on these characters and their de‐
+       scriptions by specifying the -F?  option pair.  (Escape the `?' charac‐
+       ter  as  your shell requires.)  Additional information on field content
+       can be found in the OUTPUT section.
+
+       As an example, ``-F pcfn'' will select the process  ID  (`p'),  command
+       name (`c'), file descriptor (`f') and file name (`n') fields with an NL
+       field terminator character; ``-F pcfn0'' selects the same output with a
+       NUL (000) field terminator character.
+
+       Lsof  doesn't  produce  all  fields for every process or file set, only
+       those that are available.  Some fields are mutually exclusive: file de‐
+       vice  characters and file major/minor device numbers; file inode number
+       and protocol name; file name and stream identification; file  size  and
+       offset.   One or the other member of these mutually exclusive sets will
+       appear in field output, but not both.
+
+       Normally lsof ends each field with a NL (012) character.  The 0  (zero)
+       field  identifier character may be specified to change the field termi‐
+       nator character to a NUL (000).  A NUL  terminator  may  be  easier  to
+       process  with  xargs  (1),  for example, or with programs whose quoting
+       mechanisms may not easily cope with the  range  of  characters  in  the
+       field  output.  When the NUL field terminator is in use, lsof ends each
+       process and file set with a NL (012).
+
+       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 the field identification char‐
+       acters,  indexes  for  storing them in a table, and explanation strings
+       that may be compiled into programs.  Lsof uses this header file.
+
+       The second aid is a set of sample scripts that  process  field  output,
+       written  in  awk,  Perl  4, and Perl 5.  They're located in the scripts
+       subdirectory of the lsof distribution.
+
+       The third aid is the C library used for the lsof test suite.  The  test
+       suite is written in C and uses field output to validate the correct op‐
+       eration of lsof.  The library can be found in the tests/LTlib.c file of
+       the   lsof   distribution.    The  library  uses  the  first  aid,  the
+       lsof_fields.h header file.
+
+BLOCKS AND TIMEOUTS
+       Lsof can be blocked by some kernel functions that it uses  -  lstat(2),
+       readlink(2),  and  stat(2).  These functions are stalled in the kernel,
+       for example, when the hosts where mounted NFS file systems  reside  be‐
+       come inaccessible.
+
+       Lsof  attempts  to  break these blocks with timers and child processes,
+       but the techniques are not wholly reliable.  When lsof does  manage  to
+       break  a  block,  it  will report the break with an error message.  The
+       messages may be suppressed with the -t and -w options.
+
+       The default timeout value may be displayed with the -h or  -?   option,
+       and it may be changed with the -S [t] option.  The minimum for t is two
+       seconds, but you should avoid small values, since slow  system  respon‐
+       siveness  can  cause  short timeouts to expire unexpectedly and perhaps
+       stop lsof before it can produce any output.
+
+       When lsof has to break a block during its access of mounted file system
+       information,  it  normally  continues,  although  with less information
+       available to display about open files.
+
+       Lsof can also be directed to avoid the protection of timers  and  child
+       processes  when using the kernel functions that might block by specify‐
+       ing the -O option.  While this will allow lsof to start  up  with  less
+       overhead,  it  exposes  lsof  completely  to the kernel situations that
+       might block it.  Use this option cautiously.
+
+AVOIDING KERNEL BLOCKS
+       You can use the -b option to tell lsof to avoid using kernel  functions
+       that would block.  Some cautions apply.
+
+       First,  using  this option usually requires that your system supply al‐
+       ternate device numbers in place of the device numbers that  lsof  would
+       normally  obtain  with  the lstat(2) and stat(2) kernel functions.  See
+       the ALTERNATE DEVICE NUMBERS section for more information on  alternate
+       device numbers.
+
+       Second,  you can't specify names for lsof to locate unless they're file
+       system names.  This is because lsof needs to know the device and  inode
+       numbers  of files listed with names in the lsof options, and the -b op‐
+       tion prevents lsof from obtaining them.  Moreover, since lsof only  has
+       device  numbers  for the file systems that have alternates, its ability
+       to locate files on file systems depends completely on the  availability
+       and  accuracy of the alternates.  If no alternates are available, or if
+       they're incorrect, lsof won't be able to locate files on the named file
+       systems.
+
+       Third,  if  the names of your file system directories that lsof obtains
+       from your system's mount table are symbolic links, lsof won't  be  able
+       to  resolve  the  links.   This is because the -b option causes lsof to
+       avoid the kernel readlink(2)  function  it  uses  to  resolve  symbolic
+       links.
+
+       Finally, using the -b option causes lsof to issue warning messages when
+       it needs to use the kernel functions that the -b option directs  it  to
+       avoid.   You  can  suppress these messages by specifying the -w option,
+       but if you do, you won't see the alternate device numbers  reported  in
+       the warning messages.
+
+ALTERNATE DEVICE NUMBERS
+       On  some  dialects, when lsof has to break a block because it can't get
+       information about a mounted file system via the  lstat(2)  and  stat(2)
+       kernel  functions, or because you specified the -b option, lsof can ob‐
+       tain some of the information it needs - the device number and  possibly
+       the  file system type - from the system mount table.  When that is pos‐
+       sible, lsof will report the device number it obtained.  (You  can  sup‐
+       press the report by specifying the -w option.)
+
+       You  can  assist  this process if your mount table is supported with an
+       /etc/mtab or /etc/mnttab file that contains an options field by  adding
+       a ``dev=xxxx'' field for mount points that do not have one in their op‐
+       tions strings.  Note: you must be able to edit the file  -  i.e.,  some
+       mount  tables like recent Solaris /etc/mnttab or Linux /proc/mounts are
+       read-only and can't be modified.
+
+       You may also be able to supply device numbers using the +m and +m m op‐
+       tions,  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 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  from  the
+       mount  table,  it will be able to display the files open on the crashed
+       NFS server.
+
+       Some dialects that do not use an ASCII /etc/mtab  or  /etc/mnttab  file
+       for  the  mount table may still provide an alternative device number in
+       their internal mount tables.  This includes AIX, Apple Darwin, FreeBSD,
+       NetBSD, OpenBSD, and Tru64 UNIX.  Lsof knows how to obtain the alterna‐
+       tive device number for these dialects and uses it when its  attempt  to
+       lstat(2) or stat(2) the file system is blocked.
+
+       If  you're  not sure your dialect supplies alternate device numbers for
+       file systems from its mount table, use this lsof incantation to see  if
+       it reports any alternate device numbers:
+
+              lsof -b
+
+       Look  for  standard  error  file warning messages that begin ``assuming
+       "dev=xxxx" from ...''.
+
+KERNEL NAME CACHE
+       Lsof is able to examine the kernel's name cache or use other kernel fa‐
+       cilities  (e.g., the ADVFS 4.x tag_to_path() function under Tru64 UNIX)
+       on some dialects for most file system types, excluding AFS, and extract
+       recently  used  path  name  components  from it.  (AFS file system path
+       lookups don't use the kernel's name cache; some Solaris VxFS file  sys‐
+       tem operations apparently don't use it, either.)
+
+       Lsof  reports  the complete paths it finds in the NAME column.  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 it has located,  separated  by  the  `/'
+       character.
+
+       When  lsof is run in repeat mode - i.e., with the -r option specified -
+       the extent to which it can report path name  components  for  the  same
+       file  may  vary from cycle to cycle.  That's because other running pro‐
+       cesses can cause the kernel to remove entries from its name  cache  and
+       replace them with others.
+
+       Lsof's  use of the kernel name cache to identify the paths of files can
+       lead it to report incorrect components under some circumstances.   This
+       can  happen when the 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 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 lo‐
+       cation.)  has more information on this situation.
+
+       Lsof can report path name components for these dialects:
+
+            FreeBSD
+            HP-UX
+            Linux
+            NetBSD
+            SCO OpenServer
+            SCO|Caldera UnixWare
+            Solaris
+            Tru64 UNIX
+
+       Lsof can't report path name components for these dialects:
+
+            AIX
+            OpenBSD
+
+       If you want to know why lsof can't report path name components for some
+       dialects, see the lsof FAQ (The FAQ section gives its location.)
+
+DEVICE CACHE FILE
+       Examining  all members of the /dev (or /devices) node tree with stat(2)
+       functions can be time consuming.  What's  more,  the  information  that
+       lsof needs - device number, inode number, and path - rarely changes.
+
+       Consequently, lsof normally maintains an ASCII text file of 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 in‐
+       vocation 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  acciden‐
+       tally or maliciously modified by integrity checks, including the compu‐
+       tation and verification of a sixteen bit Cyclic Redundancy Check  (CRC)
+       sum  on the file's contents.  When lsof senses something wrong with the
+       file, it issues a warning and attempts to remove the current cache file
+       and  create a new copy, but only to a path that the process can legiti‐
+       mately write.
+
+       The path from which a lsof process may attempt to read a  device  cache
+       file  may  not  be  the  same  as the path to which it can legitimately
+       write.  Thus when lsof senses that it needs to update the device  cache
+       file,  it may choose a different path for writing it from the path from
+       which it read an incorrect or outdated version.
+
+       If available, the -Dr option will inhibit the writing of a  new  device
+       cache  file.  (It's always available when specified without a path name
+       argument.)
+
+       When a new device is added to the system, the  device  cache  file  may
+       need  to  be  recreated.   Since  lsof compares the mtime of the device
+       cache file with the mtime and ctime of the /dev  (or  /devices)  direc‐
+       tory, it usually detects that a new device has been added; in that case
+       lsof issues a warning message and attempts to rebuild the device  cache
+       file.
+
+       Whenever  lsof writes a device cache file, it sets its ownership to the
+       real UID of the executing process, and its permission  modes  to  0600,
+       this restricting its reading and writing to the file's owner.
+
+LSOF PERMISSIONS THAT AFFECT DEVICE CACHE FILE ACCESS
+       Two permissions of the lsof executable affect its ability to access de‐
+       vice cache files.  The permissions are set by the local system adminis‐
+       trator when lsof is installed.
+
+       The  first  and  rarer permission is setuid-root.  It comes into effect
+       when lsof is executed; its effective UID is then root, while  its  real
+       (i.e.,  that  of the logged-on user) UID is not.  The lsof distribution
+       recommends that versions for these dialects run setuid-root.
+
+            HP-UX 11.11 and 11.23
+            Linux
+
+       The second and more common permission is setgid.  It comes into  effect
+       when  the  effective  group  IDentification  number  (GID)  of the lsof
+       process is set to one that can access kernel  memory  devices  -  e.g.,
+       ``kmem'', ``sys'', or ``system''.
+
+       An  lsof process that has setgid permission usually surrenders the per‐
+       mission after it has accessed the kernel memory devices.  When it  does
+       that,  lsof  can  allow more liberal device cache path formations.  The
+       lsof distribution recommends that versions for these dialects run  set‐
+       gid and be allowed to surrender setgid permission.
+
+            AIX 5.[12] and 5.3-ML1
+            Apple Darwin 7.x Power Macintosh systems
+            FreeBSD 4.x, 4.1x, 5.x and [6789].x for x86-based systems
+            FreeBSD 5.x, [6789].x and 1[012].8for Alpha, AMD64 and Sparc64
+                based systems
+            HP-UX 11.00
+            NetBSD 1.[456], 2.x and 3.x for Alpha, x86, and SPARC-based
+                systems
+            OpenBSD 2.[89] and 3.[0-9] for x86-based systems
+            SCO OpenServer Release 5.0.6 for x86-based systems
+            SCO|Caldera UnixWare 7.1.4 for x86-based systems
+            Solaris 2.6, 8, 9 and 10
+            Tru64 UNIX 5.1
+
+       (Note: lsof for AIX 5L and above needs setuid-root permission if its -X
+       option is used.)
+
+       Lsof for these dialects does not support a device cache, so the permis‐
+       sions given to the executable don't apply to the device cache file.
+
+            Linux
+
+DEVICE CACHE FILE PATH FROM THE -D OPTION
+       The  -D  option  provides limited means for specifying the device cache
+       file path.  Its ?  function will report the read-only and write  device
+       cache file paths that lsof will use.
+
+       When  the  -D  b, r, and u functions are available, you can use them to
+       request that the cache file be built in a specific location  (b[path]);
+       read  but not rebuilt (r[path]); or read and rebuilt (u[path]).  The b,
+       r, and u functions are restricted under some conditions.  They are  re‐
+       stricted when the lsof process is setuid-root.  The path specified with
+       the r function is always read-only, even when it is available.
+
+       The b, r, and u functions are also restricted  when  the  lsof  process
+       runs setgid and lsof doesn't surrender the setgid permission.  (See the
+       LSOF PERMISSIONS THAT AFFECT DEVICE CACHE FILE  ACCESS  section  for  a
+       list of implementations that normally don't surrender their setgid per‐
+       mission.)
+
+       A further -D function, i (for ignore), is always available.
+
+       When available, the b function tells lsof to  read  device  information
+       from the kernel with the stat(2) function and build a device cache file
+       at the indicated path.
+
+       When available, the r function tells lsof  to  read  the  device  cache
+       file,  but  not  update  it.   When a path argument accompanies -Dr, it
+       names the device cache file path.  The r function is  always  available
+       when it is specified without a path name argument.  If lsof is not run‐
+       ning setuid-root and surrenders its setgid permission, a path name  ar‐
+       gument may accompany the r function.
+
+       When  available,  the  u function tells lsof to attempt to read and use
+       the device cache file.  If it can't read the file, or if it  finds  the
+       contents  of  the  file incorrect or outdated, it will read information
+       from the kernel, and attempt to write an updated version of the  device
+       cache  file,  but  only  to a path it considers legitimate for the lsof
+       process effective and real UIDs.
+
+DEVICE CACHE PATH FROM AN ENVIRONMENT VARIABLE
+       Lsof's second choice for the device cache file is the contents  of  the
+       LSOFDEVCACHE  environment  variable.  It avoids this choice if the lsof
+       process is setuid-root, or the real UID of the process is root.
+
+       A further restriction applies to a device cache file  path  taken  from
+       the  LSOFDEVCACHE  environment  variable:  lsof will not write a device
+       cache file to the path if the lsof process doesn't surrender its setgid
+       permission.   (See  the  LSOF PERMISSIONS THAT AFFECT DEVICE CACHE FILE
+       ACCESS section for information on implementations that don't  surrender
+       their setgid permission.)
+
+       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 environment variable's name.
+
+SYSTEM-WIDE DEVICE CACHE PATH
+       The  local system administrator may choose to have a system-wide device
+       cache file when building lsof.  That file will generally be constructed
+       by  a special system administration procedure when the system is booted
+       or when the contents of /dev or /devices) changes.  If defined,  it  is
+       lsof's third device cache file path choice.
+
+       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 -?  option.
+
+       Lsof  will never write to the system-wide device cache file path by de‐
+       fault.  It must be explicitly named with a -D function in a  root-owned
+       procedure.   Once  the file has been written, the procedure must change
+       its permission modes to 0644 (owner-read and  owner-write,  group-read,
+       and other-read).
+
+PERSONAL DEVICE CACHE PATH (DEFAULT)
+       The  default  device  cache  file  path of the lsof distribution is one
+       recorded in the home directory of the  real  UID  that  executes  lsof.
+       Added  to  the  home  directory  is a second path component of the form
+       .lsof_hostname.
+
+       This is lsof's fourth device cache file path choice, and is usually the
+       default.  If a system-wide device cache file path was defined when lsof
+       was built, this fourth choice will be applied when lsof can't find  the
+       system-wide  device  cache  file.   This is the only time lsof uses two
+       paths when reading the device cache file.
+
+       The hostname part of the second component is the base name of the  exe‐
+       cuting  host,  as returned by gethostname(2).  The base name is defined
+       to be the characters preceding the first  `.'   in  the  gethostname(2)
+       output, or all the gethostname(2) output if it contains no `.'.
+
+       The  device  cache  file  belongs  to  the  user ID and is readable and
+       writable by the user ID alone - i.e., its modes are  0600.   Each  dis‐
+       tinct  real  user  ID on a given host that executes lsof has a distinct
+       device cache file.  The hostname part of the path distinguishes  device
+       cache  files  in  an NFS-mounted home directory into which device cache
+       files are written from several different hosts.
+
+       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 should its contents be incorrect  or  out‐
+       dated.
+
+       The -Dr option without a path name argument will inhibit the writing of
+       a new device cache file.
+
+       The -D?  option will list the format specification for constructing the
+       personal  device cache file.  The conversions used in the format speci‐
+       fication are described in the 00DCACHE file of the lsof distribution.
+
+MODIFIED PERSONAL DEVICE CACHE PATH
+       If this option is defined by the local system administrator  when  lsof
+       is  built, the LSOFPERSDCPATH environment variable contents may be used
+       to add a component of the personal device cache file path.
+
+       The LSOFPERSDCPATH variable contents are inserted in the  path  at  the
+       place  marked by the local system administrator with the ``%p'' conver‐
+       sion in the HASPERSDC format specification of the  dialect's  machine.h
+       header  file.   (It's  placed right after the home directory in the de‐
+       fault lsof distribution.)
+
+       Thus, for example, if LSOFPERSDCPATH contains ``LSOF'', the home direc‐
+       tory  is ``/Homes/abe'', the host name is ``lsof.itap.purdue.edu'', and
+       the HASPERSDC format is the default (``%h/%p.lsof_%L''),  the  modified
+       personal device cache file path is:
+
+            /Homes/abe/LSOF/.lsof_vic
+
+       The  LSOFPERSDCPATH  environment  variable  is  ignored  when  the lsof
+       process is setuid-root or when the real UID of the process is root.
+
+       Lsof will not write to a modified personal device cache  file  path  if
+       the  lsof  process  doesn't surrender setgid permission.  (See the LSOF
+       PERMISSIONS THAT AFFECT DEVICE CACHE FILE ACCESS section for a list  of
+       implementations that normally don't surrender their setgid permission.)
+
+       If,  for example, you want to create a sub-directory of personal device
+       cache file paths by using the LSOFPERSDCPATH  environment  variable  to
+       name  it,  and  lsof  doesn't surrender its setgid permission, you will
+       have to allow lsof to create device cache files at  the  standard  per‐
+       sonal path and move them to your subdirectory with shell commands.
+
+       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 format to include the personal
+       path component in another place; or exclude the personal path component
+       entirely.   Consult  the  output of the -D?  option for the environment
+       variable's name and the HASPERSDC format specification.
+
+DIAGNOSTICS
+       Errors are identified with messages on the standard error file.
+
+       Lsof returns a one (1) if any error was detected, including the failure
+       to locate command names, file names, Internet addresses or files, login
+       names, NFS files, PIDs, PGIDs, or UIDs it was asked to list.  If the -V
+       option  is  specified, lsof will indicate the search items it failed to
+       list.  If the -Q option is specified, lsof will ignore any search  item
+       failures  and  only return an error if something unusual and unrecover‐
+       able happened.
+
+       It returns a zero (0) if no errors were detected and if either  the  -Q
+       option  was specified or it was able to list some information about all
+       the specified search arguments.
+
+       When lsof cannot open access to /dev (or /devices) or one of its subdi‐
+       rectories, or get information on a file in them with stat(2), it issues
+       a warning message and continues.  That lsof will issue warning messages
+       about inaccessible files in /dev (or /devices) is indicated in its help
+       output - requested with the -h or >B -?  options -  with the message:
+
+            Inaccessible /dev warnings are enabled.
+
+       The warning message may be suppressed with the -w option.  It may  also
+       have been suppressed by the system administrator when lsof was compiled
+       by the setting of the WARNDEVACCESS definition.  In this case, the out‐
+       put from the help options will include the message:
+
+            Inaccessible /dev warnings are disabled.
+
+       Inaccessible  device  warning messages usually disappear after lsof has
+       created a working device cache file.
+
+EXAMPLES
+       For a more extensive set of examples, documented more  fully,  see  the
+       00QUICKSTART file of the lsof distribution.
+
+       To list all open files, use:
+
+              lsof
+
+       To list all open Internet, x.25 (HP-UX), and UNIX domain files, use:
+
+              lsof -i -U
+
+       To  list all open IPv4 network files in use by the process whose PID is
+       1234, use:
+
+              lsof -i 4 -a -p 1234
+
+       If it's okay for PID 1234 to not exist, or for PID 1234 to not have any
+       open IPv4 network files, add -Q :
+
+              lsof -Q -i 4 -a -p 1234
+
+       Presuming  the  UNIX dialect supports IPv6, to list only open IPv6 net‐
+       work files, use:
+
+              lsof -i 6
+
+       To list all files using any protocol on ports 513, 514, or 515 of  host
+       wonderland.cc.purdue.edu, use:
+
+              lsof -i @wonderland.cc.purdue.edu:513-515
+
+       To  list all files using any protocol on any port of mace.cc.purdue.edu
+       (cc.purdue.edu is the default domain), use:
+
+              lsof -i @mace
+
+       To list all open files for login name ``abe'',  or  user  ID  1234,  or
+       process 456, or process 123, or process 789, use:
+
+              lsof -p 456,123,789 -u 1234,abe
+
+       To list all open files on device /dev/hd4, use:
+
+              lsof /dev/hd4
+
+       To  find the process that has /u/abe/foo open without worrying if there
+       are none, use:
+
+              lsof -Q /u/abe/foo
+
+       To take action only if a process has /u/abe/foo open, use:
+
+              lsof /u/abe/foo  echo "still in use"
+
+       To send a SIGHUP to the processes that have /u/abe/bar open, use:
+
+              kill -HUP `lsof -t /u/abe/bar`
+
+       To find any open file, including an open UNIX domain socket file,  with
+       the name /dev/log, use:
+
+              lsof /dev/log
+
+       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:
+
+              lsof -Di
+
+       To  obtain PID and command name field output for each process, file de‐
+       scriptor, 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 seconds, use:
+
+              lsof -c lsof -a -d 1 -d 3 -u abe -r10
+
+       To list the current working directory of processes  running  a  command
+       that is exactly four characters long and has an 'o' or 'O' in character
+       three, use this regular expression form of the -c c option:
+
+              lsof -c /^..o.$/i -a -d cwd
+
+       To find an IP version 4 socket file by its associated numeric  dot-form
+       address, use:
+
+              lsof -i@128.210.15.17
+
+       To  find  an  IP  version 6 socket file (when the UNIX dialect supports
+       IPv6) by its associated numeric colon-form address, use:
+
+              lsof -i@[0:1:2:3:4:5:6:7]
+
+       To find an IP version 6 socket file (when  the  UNIX  dialect  supports
+       IPv6) by an associated numeric colon-form address that has a run of ze‐
+       roes in it - e.g., the loop-back address - use:
+
+              lsof -i@[::1]
+
+       To obtain a repeat mode marker line that  contains  the  current  time,
+       use:
+
+              lsof -rm====%T====
+
+       To add spaces to the previous marker line, use:
+
+              lsof -r "m==== %T ===="
+
+BUGS
+       Since  lsof  reads  kernel  memory  in its search for open files, rapid
+       changes in kernel memory may produce unpredictable results.
+
+       When a file has multiple record locks, the lock status character  (fol‐
+       lowing  the  file  descriptor) is derived from a test of the first lock
+       structure, not from any combination of the individual record locks that
+       might be described by multiple lock structures.
+
+       Lsof can't search for files with restrictive access permissions by name
+       unless it is installed with root set-UID permission.  Otherwise  it  is
+       limited  to  searching for files to which its user or its set-GID group
+       (if any) has access permission.
+
+       The display of the destination address of a raw socket (e.g., for ping)
+       depends on the UNIX operating system.  Some dialects store the destina‐
+       tion address in the raw socket's protocol control block, some do not.
+
+       Lsof can't always represent Solaris device numbers in the same way that
+       ls(1)  does.   For example, the major and minor device numbers that the
+       lstat(2) and stat(2) functions report for the directory on which CD-ROM
+       files  are mounted (typically /cdrom) are not the same as the ones that
+       it reports for the device on which CD-ROM files are mounted  (typically
+       /dev/sr0).  (Lsof reports the directory numbers.)
+
+       The  support for /proc file systems is available only for BSD and Tru64
+       UNIX dialects, Linux, and dialects derived from SYSV R4 -  e.g.,  Free‐
+       BSD, NetBSD, OpenBSD, Solaris, UnixWare.
+
+       Some  /proc  file  items - device number, inode number, and file size -
+       are unavailable in some dialects.  Searching for files in a /proc  file
+       system may require that the full path name be specified.
+
+       No  text (txt) file descriptors are displayed for Linux processes.  All
+       entries for files other than the current working  directory,  the  root
+       directory, and numerical file descriptors are labeled mem descriptors.
+
+       Lsof  can't  search  for  Tru64 UNIX named pipes by name, because their
+       kernel implementation of lstat(2) returns an improper device number for
+       a named pipe.
+
+       Lsof  can't  report  fully or correctly on HP-UX 9.01, 10.20, and 11.00
+       locks because of insufficient access to kernel data or  errors  in  the
+       kernel  data.   See  the lsof FAQ (The FAQ section gives its location.)
+       for details.
+
+       The AIX SMT file type is a fabrication.  It's made up for  file  struc‐
+       tures  whose type (15) isn't defined in the AIX /usr/include/sys/file.h
+       header file.  One way to create  such  file  structures  is  to  run  X
+       clients with the DISPLAY variable set to ``:0.0''.
+
+       The +|-f[cfn] option is not supported under /proc-based Linux lsof, be‐
+       cause it doesn't read kernel structures from kernel memory.
+
+ENVIRONMENT
+       Lsof may access these environment variables.
+
+       LANG              defines a language locale.  See setlocale(3) for  the
+                         names of other variables that can be used in place of
+                         LANG - e.g., LC_ALL, LC_TYPE, etc.
+
+       LSOFDEVCACHE      defines the path to a device cache file.  See the DE‐
+                         VICE  CACHE PATH FROM AN ENVIRONMENT VARIABLE section
+                         for more information.
+
+       LSOFPERSDCPATH    defines the middle component of a  modified  personal
+                         device  cache  file  path.  See the MODIFIED PERSONAL
+                         DEVICE CACHE PATH section for more information.
+
+FAQ
+       Frequently-asked questions and their answers (an FAQ) are available  in
+       the 00FAQ file of the lsof distribution.
+
+       That latest version of the file is found at:
+
+              https://github.com/lsof-org/lsof/blob/master/00FAQ
+
+FILES
+       /dev/kmem         kernel virtual memory device
+
+       /dev/mem          physical memory device
+
+       /dev/swap         system paging device
+
+       .lsof_hostname    lsof's  device  cache  file (The suffix, hostname, is
+                         the first component of the host's  name  returned  by
+                         gethostname(2).)
+
+AUTHORS
+       Lsof  was  written by Victor A.Abell <abe@purdue.edu> of Purdue Univer‐
+       sity.  Since version 4.93.0, the  lsof-org  team  at  GitHub  maintains
+       lsof.   Many  others  have  contributed to lsof.  They're listed in the
+       00CREDITS file of the lsof distribution.
+
+DISTRIBUTION
+       The latest distribution of lsof is available at
+
+              https://github.com/lsof-org/lsof/releases
+
+SEE ALSO
+       Not all the following manual pages may exist in every UNIX  dialect  to
+       which lsof has been ported.
+
+       access(2),  awk(1),  crash(1),  fattach(3C), ff(1), fstat(8), fuser(1),
+       gethostname(2),  isprint(3),  kill(1),  localtime(3),  lstat(2),   mod‐
+       load(8),  mount(8),  netstat(1),  ofiles(8L),  open(2), perl(1), ps(1),
+       readlink(2), setlocale(3), stat(2), strftime(3), time(2), uname(1).
+
+                                Revision-4.99.0                        LSOF(8)
+```
diff --git a/docs/manpage.sh b/docs/manpage.sh
new file mode 100755
index 0000000..d106e96
--- /dev/null
+++ b/docs/manpage.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+echo "# Manpage" > manpage.md
+echo "\`\`\`manpage" >> manpage.md
+# nroff: render manpage
+# col: -b remove backspace, -x use spaces instead of tabs
+# cat: -s remove consecutive blank lines
+nroff -man ../lsof.man | col -bx | cat -s >> manpage.md
+echo "\`\`\`" >> manpage.md
diff --git a/docs/options.md b/docs/options.md
new file mode 100644
index 0000000..010010f
--- /dev/null
+++ b/docs/options.md
@@ -0,0 +1,207 @@
+# Options
+
+The document describes the lsof options in detail.
+
+## Selection Options
+
+Lsof has a rich set of options for selecting the files to be
+displayed.  These include:
+
+- -a	tells lsof to AND the set of selection options that
+	are specified.  Normally lsof ORs them.
+
+	For example, if you specify the -p<PID> and -u<UID>
+	options, lsof will display all files for the
+	specified PID or for the specified UID.
+
+	By adding -a, you specify that the listed files
+	should be limited to PIDs owned by the specified
+	UIDs -- i.e., they match the PIDs *and* the UIDs.
+
+		$ lsof -p1234 -au 5678
+
+- -c	specifies that lsof should list files belonging
+	to processes having the associated command name.
+
+	Hint: if you want to select files based on more than
+	one command name, use multiple -c<name> specifications.
+
+		$ lsof -clsof -cksh
+
+- -d      tells lsof to select by the associated file descriptor
+	(FD) set.  An FD set is a comma-separated list of
+	numbers and the names lsof normally displays in
+	its FD column:  cwd, Lnn, ltx, <number>, etc.  See
+	the OUTPUT section of the lsof man page for the
+	complete list of possible file descriptors.  Example:
+
+		$ lsof -dcwd,0,1,2
+
+- -g      tells lsof to select by the associated process
+	group ID (PGID) set.  The PGID set is a comma-separated
+	list of PGID numbers.  When -g is specified, it also
+	enables the display of PGID numbers.
+
+	Note: when -g isn't followed by a PGID set, it
+	simply selects the listing of PGID for all processes.
+	Examples:
+
+		$ lsof -g
+		$ lsof -g1234,5678
+
+- -i	tells lsof to display Internet socket files.  If no
+	protocol/address/port specification follows -i,
+	lsof lists all Internet socket files.
+
+	If a specification follows -i, lsof lists only the
+	socket files whose Internet addresses match the
+	specification.
+
+	Hint: multiple addresses may be specified with
+	multiple -i options.  Examples:
+
+		$ lsof -iTCP
+		$ lsof -i@lsof.itap.purdue.edu:sendmail
+
+- -N	selects the listing of files mounted on NFS devices.
+
+- -U	selects the listing of socket files in the Unix
+	domain.
+
+
+## Output Options
+
+Lsof has these options to control its output format:
+
+- -F	produce output that can be parsed by a subsequent
+	program.
+
+- -g	print process group (PGID) IDs.
+
+- -l	list UID numbers instead of login names.
+
+- -n	list network numbers instead of host names.
+
+- -o	always list file offset.
+
+- -P	list port numbers instead of port service names.
+
+- -s	always list file size.
+
+## Precautionary Options
+
+Lsof uses system functions that can block or take a long time,
+depending on the health of the Unix dialect supporting it.  These
+include:
+
+- -b	directs lsof to avoid system functions -- e.g.,
+	lstat(2), readlink(2), stat(2) -- that might block
+	in the kernel.  See the BLOCKS AND TIMEOUTS
+	section of the lsof man page.
+
+	You might want to use this option when you have
+	a mount from an NFS server that is not responding.
+
+- -C	tells lsof to ignore the kernel's name cache.  As
+	a precaution this option will have little effect on
+	lsof performance, but might be useful if the kernel's
+	name cache is scrambled.  (I've never seen that
+	happen.)
+
+- -D	might be used to direct lsof to ignore an existing
+	device cache file and generate a new one from /dev
+	(and /devices).  This might be useful if you have
+	doubts about the integrity of an existing device
+	cache file.
+
+- -l      tells lsof to list UID numbers instead of login
+	names -- this is useful when UID to login name
+	conversion is slow or inoperative.
+
+- -n	tells lsof to avoid converting Internet addresses
+	to host numbers.  This might be useful when your
+	host name lookup (e.g., DNS) is inoperative.
+
+- -O      tells lsof to avoid its strategy of forking to
+	perform potentially blocking kernel operations.
+	While the forking allows lsof to detect that a
+	block has occurred (and possibly break it), the
+	fork operation is a costly one.  Use the -O option
+	with care, lest your lsof be blocked.
+
+- -P      directs lsof to list port numbers instead of trying
+	to convert them to port service names.  This might
+	be useful if port to service name lookups (e.g.,
+	via NIS) are slow or failing.
+
+- -S      can be used to change the lstat/readlink/stat
+	timeout interval that governs how long lsof waits
+	for response from the kernel.  This might be useful
+	when an NFS server is slow or unresponsive.  When
+	lsof times out of a kernel function, it may have
+	less information to display.  Example:
+
+		$ lsof -S2
+
+- -w	tells lsof to avoid issuing warning messages, if
+	they are enabled by default, or enable them if they
+	are disabled by default.  Check the -h (help) output
+	to determine their status.  If it says `-w enable warnings`, then warning messages are disabled by
+	default; `-w disable warnings`, they are enabled
+	by default.
+
+	This may be a useful option, for example, when you
+	specify -b, if warning messages are enabled, because
+	it will suppress the warning messages lsof issues
+	about avoiding functions that might block in the
+	kernel.
+
+## Miscellaneous Lsof Options
+
+There are some lsof options that are hard to classify, including:
+
+- -?, -h	these options select help output.
+
+- -F      selects field output.  Field output is a mode where
+	lsof produces output that can be parsed easily by
+	subsequent programs -- e.g., AWK or Perl scripts.
+	See ``15. Output for Other Programs'' for more
+	information.
+
+- -k	specifies an alternate kernel symbol file -- i.e.,
+	where nlist() will get its information.  Example:
+
+		$ lsof -k/usr/crash/vmunix.1
+
+- -m	specifies an alternate kernel memory file from
+	which lsof will read kernel structures in place
+	of /dev/kmem or kvm_read().  Example:
+
+		$ lsof -m/usr/crash/vmcore.n
+
+- -r	tells lsof to repeat its scan every 15 seconds (the
+	default when no associated value is specified).  A
+	repeat time, different from the default, can follow
+	-r.  Example:
+
+		$ lsof -r30
+
+- -Q	tells lsof not to consider it an error if it was
+	given search terms and any part of the search came
+	up empty. This will silence any reports of missing
+	files to stderr. Additionally, lsof will exit with
+	a non-error code despite any missing files or
+	filesystems with no open files.
+
+- -v	displays information about the building of the
+	lsof executable.
+
+- --      The double minus sign option may be used to
+	signal the end of options.  It's particularly useful
+	when arguments to the last option are optional and
+	you want to supply a file path that could be confused
+	for arguments to the last option.  Example:
+
+		$ lsof -g -- 1
+
+	Where `1' is a file path, not PGID ID 1.
diff --git a/docs/requirements.in b/docs/requirements.in
new file mode 100644
index 0000000..b854bca
--- /dev/null
+++ b/docs/requirements.in
@@ -0,0 +1 @@
+mkdocs
\ No newline at end of file
diff --git a/docs/requirements.txt b/docs/requirements.txt
new file mode 100644
index 0000000..bc4d069
--- /dev/null
+++ b/docs/requirements.txt
@@ -0,0 +1,40 @@
+#
+# This file is autogenerated by pip-compile with Python 3.9
+# by the following command:
+#
+#    pip-compile docs/requirements.in
+#
+click==8.1.3
+    # via mkdocs
+ghp-import==2.1.0
+    # via mkdocs
+importlib-metadata==6.0.0
+    # via
+    #   markdown
+    #   mkdocs
+jinja2==3.1.4
+    # via mkdocs
+markdown==3.3.7
+    # via mkdocs
+markupsafe==2.1.1
+    # via jinja2
+mergedeep==1.3.4
+    # via mkdocs
+mkdocs==1.4.2
+    # via -r requirements.in
+packaging==23.0
+    # via mkdocs
+python-dateutil==2.8.2
+    # via ghp-import
+pyyaml==6.0
+    # via
+    #   mkdocs
+    #   pyyaml-env-tag
+pyyaml-env-tag==0.1
+    # via mkdocs
+six==1.16.0
+    # via python-dateutil
+watchdog==2.2.1
+    # via mkdocs
+zipp==3.19.1
+    # via importlib-metadata
diff --git a/docs/tutorial.md b/docs/tutorial.md
new file mode 100644
index 0000000..14b0644
--- /dev/null
+++ b/docs/tutorial.md
@@ -0,0 +1,699 @@
+# Tutorial
+
+## Finding Uses of a Specific Open File
+
+Often you're interested in knowing who is using a specific file.
+You know the path to it and you want lsof to tell you the processes
+that have open references to it.
+
+Simple -- execute lsof and give it the path name of the file of interest --
+e.g.,
+
+```shell
+$ lsof /etc/passwd
+```
+
+Caveat: this only works if lsof has permission to get the status (via stat(2))
+of the file at the named path.  Unless the lsof process has enough authority  --
+e.g., it is being run with a real User ID (UID) of root.
+
+Further caveat: this use of lsof will fail if the stat(2) kernel syscall returns
+different file parameters -- particularly device and inode numbers -- than lsof
+finds in kernel node structures.  This condition is rare and is usually
+documented in the FAQ.
+
+```shell
+$ lsof /etc/security/passwd
+lsof: status error on /etc/security/passwd: Permission denied
+```
+
+## Finding Open Files Filling a File System
+
+Oh! Oh!  /tmp is filling and ls doesn't show that any large files are being
+created.  Can lsof help?
+
+Maybe.  If there's a process that is writing to a file that has been unlinked,
+lsof may be able to discover the process for you.  You ask it to list all open
+files on the file system where /tmp is located.
+
+Sometimes /tmp is a file system by itself.  In that case,
+
+```shell
+$ lsof /tmp
+```
+
+is the appropriate command.  If, however, /tmp is part of another file system,
+typically /, then you may have to ask lsof to list all files open on the
+containing file system and locate the offending file and its process by
+inspection -- e.g.,
+
+```shell
+$ lsof / | more
+# or
+$ lsof / | grep ...
+```
+
+Caveat: there must be a file open to a for the lsof search to succeed.
+Sometimes the kernel may cause a file reference to persist, even where there's
+no file open to a process.  (Can you say kernel bug?  Maybe.)  In any event,
+lsof won't be able to help in this case.
+
+## Finding an Unlinked Open File
+
+A pesky variant of a file that is filling a file system is an unlinked file to
+which some process is still writing.  When a process opens a file and then
+unlinks it, the file's resources remain in use by the process, but the file's
+directory entries are removed.  Hence, even when you know the directory where
+the file once resided, you can't detect it with ls.
+
+This can be an administrative problem when the unlinked file is large, and the
+process that holds it open continues to write to it.  Only when the process
+closes the file will its resources, particularly disk space, be released.
+
+Lsof can help you find unlinked files on local disks.  It has an option, +L,
+that will list the link counts of open files.  That helps because an unlinked
+file on a local disk has a zero link count.  Note: this is NOT true for NFS
+files, accessed from a remote server.
+
+You could use the option to list all files and look for a zero link count in the
+NLINK column -- e.g.,
+
+```shell
+$ lsof +L
+COMMAND   PID USER   FD  TYPE DEVICE SIZE/OFF NLINK  NODE NAME
+...
+less    25366  abe  txt  VREG    6,0    40960     1 76319 /usr/...
+...
+> less    25366  abe    3r VREG    6,0    17360     0 98768 / (/dev/sd0a)
+```
+
+Better yet, you can specify an upper bound to the +L option, and
+lsof will select only files that have a link count less than the
+upper bound.  For example:
+
+```shell
+$ lsof +L1
+COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NLINK  NODE NAME
+less    25366  abe    3r  VREG    6,0    17360     0 98768 / (/dev/sd0a)
+```
+
+You can use lsof's -a (AND) option to narrow the link count search
+to a particular file system.  For example, to look for zero link
+counts on the /home file system, use:
+
+```shell
+$ lsof -a +L1 /home
+```
+
+CAUTION: lsof can't always report link counts for all file types
+-- e.g., it may not report them for FIFOs, pipes, or sockets.
+Remember also that link counts for NFS files on an NFS client
+host don't behave as do link counts for files on local disks.
+
+## Finding Processes Blocking Umount
+
+When you need to unmount a file system with the umount command, you may find the
+operation blocked by a process that has a file open on the file systems.  Lsof
+may be able to help you find the process.  In response to:
+
+```shell
+$ lsof <file_system_name>
+```
+
+Lsof will display all open files on the named file system.  It will also set its
+exit code zero when it finds some open files and non-zero when it doesn't,
+making this type of lsof call useful in shell scripts.  (See section 16.)
+
+Consult the output of the df command for file system names.
+
+See the caveat in the preceding section about file references that persist in
+the kernel without open file traces.  That situation may hamper lsof's ability
+to help with umount, too.
+
+## Finding Listening Sockets
+
+Sooner or later you may wonder if someone has installed a network
+server that you don't know about.  Lsof can list for you all the
+network socket files open on your machine with:
+
+```shell
+$ lsof -i
+```
+
+The -i option without further qualification lists all open Internet socket
+files.  You can add network names or addresses, protocol names, and service
+names or port numbers to the -i option to refine the search.  (See the next
+section.)
+
+## Finding a Particular Network Connection
+
+When you know the source or destination of a network connection whose open files
+and process you'd like to identify, the -i option may help.
+
+If, for example, you want to know what process has a connection open to or from
+the Internet host named aaa.bbb.ccc, you can ask lsof to search for it with:
+
+```shell
+$ lsof -i@aaa.bbb.ccc
+```
+
+If you're interested in a particular protocol -- TCP or UDP --
+and a specific port number or service name, you can add those
+discriminators to the -i information:
+
+```shell
+$ lsof -iTCP@aaa.bbb.ccc:ftp-data
+```
+
+If you're interested in a particular IP version -- IPv4 or IPv6
+-- and your UNIX dialect supports both (It does if "IPv[46]"
+appears in the lsof -h output.), you can add the '4' or '6'
+selector immediately after -i:
+
+```shell
+$ lsof -i4
+$ lsof -i6
+```
+
+## Identifying a Netstat Connection
+
+How do I identify the process that has a network connection
+described in netstat output?  For example, if netstat says:
+
+```
+Proto Recv-Q Send-Q  Local Address          Foreign Address        (state)
+tcp        0      0  vic.1023               ipscgate.login         ESTABLISHED
+```
+
+What process is connected to service name `login` on ipscgate?
+
+Use lsof's -i option:
+
+```
+$ lsof -iTCP@ipscgate:login
+COMMAND     PID     USER   FD   TYPE     DEVICE   SIZE/OFF  INODE NAME
+rlogin    25023      abe    3u  inet 0x10144168      0t184    TCP lsof.itap.purdue.edu:1023->ipscgate.cc.purdue.edu:login
+...
+```
+
+There's another way.  Notice the 0x10144168 in the DEVICE column
+of the lsof output?  That's the protocol control block (PCB)
+address.  Many netstat applications will display it when given
+the -A option:
+
+```shell
+$ netstat -A
+PCB      Proto Recv-Q Send-Q  Local Address      Foreign Address    (state)
+10144168 tcp        0      0  vic.1023           ipscgate.login     ESTABLISHED
+...
+```
+
+Using the PCB address, lsof, and grep, you can find the process this
+way, too:
+
+```shell
+$ lsof -i | grep 10144168
+rlogin    25023      abe    3u  inet 0x10144168      0t184    TCP lsof.itap.purdue.edu:1023->ipscgate.cc.purdue.edu:login
+...
+```
+
+If the file is a UNIX socket and netstat reveals and address for it,
+like this Solaris 11 example:
+
+```shell
+$ netstat -a -f unix
+Active UNIX domain sockets
+Address  Type          Vnode     Conn  Local Addr      Remote Addr
+ffffff0084253b68 stream-ord 0000000 0000000
+```
+
+Using lsof's -U option and its output piped to a grep on the address
+yields:
+
+```shell
+$ lsof -U | grep ffffff0084253b68
+squid 1638 nobody 12u unix 18,98 0t10 9437188 /devices/pseudo/tl@0:ticots->0xffffff0084253b68 stream-ord
+```
+
+## Finding Files Open to a Named Command
+
+When you want to look at the files open to a particular command,
+you can look up the PID of the process running the command and
+use lsof's -p option to specify it.
+
+```shell
+$ lsof -p <PID>
+```
+
+However, there's a quicker way, using lsof's -c option, provided
+you don't mind seeing output for every process running the named
+command.
+
+```shell
+$ lsof -c <first_characters_of_command_name_that_interest_you>
+```
+
+The lsof -c option is useful when you want to see how many instances
+of a given command are executing and what their open files are.
+One useful example is for the sendmail command.
+
+```shell
+$ lsof -c sendmail
+```
+
+## Deciphering the Remote Login Trail
+
+If the network connection you're interested in tracing has been initiated
+externally and is connected to an rlogind, sshd, or telnetd process, asking lsof
+to identify that process might not give a wholly satisfying answer.  The report
+may be that the connection exists, but to a process owned by root.
+
+### The Fundamentals
+
+How do you get from there to the login name really using the connection?  You
+have to know a little about how real and pseudo ttys are paired in your system,
+and then use several lsof probes to identify the login.
+
+This example comes from a Solaris 2.4 system, named klaatu.cc.  I've logged on
+to it via rlogin from lsof.itap.  The first lsof probe,
+
+```shell
+$ lsof -i@lsof.itap
+```
+
+yields (among other things):
+
+```shell
+COMMAND     PID     USER   FD   TYPE     DEVICE   SIZE/OFF  INODE NAME
+in.rlogin  7362     root    0u  inet 0xfc0193b0      0t242    TCP klaatu.cc.purdue.edu:login->lsof.itap.purdue.edu:1023
+...
+```
+
+This confirms that a connection exists.  A second lsof probe
+shows:
+
+```shell
+$ lsof -p7362
+COMMAND     PID     USER   FD   TYPE     DEVICE   SIZE/OFF  INODE NAME
+...
+in.rlogin  7362     root    0u  inet 0xfc0193b0      0t242    TCP klaatu.cc.purdue.edu:login->lsof.itap.purdue.edu:1023
+...
+in.rlogin  7362     root    3u  VCHR    23,   0       0t66  52928 /devices/pseudo/clone@0:ptmx->pckt->ptm
+```
+
+7362 is the Process ID (PID) of the in.rlogin process, discovered
+in the first lsof probe.  (I've abbreviated the output to simplify
+the example.)  Now comes a need to understand Solaris pseudo-ttys.
+The key indicator is in the DEVICE column for FD 3, the major/minor
+device number of 23,0.  This translates to /dev/pts/0, so a third
+lsof probe,
+
+```shell
+$ lsof /dev/pts/0
+COMMAND     PID     USER   FD   TYPE     DEVICE   SIZE/OFF  INODE NAME
+ksh        7364      abe    0u  VCHR    24,   0     0t2410  53410 /dev/pts/../../devices/pseudo/pts@0:0
+```
+
+shows in part that login abe has a ksh process on /dev/pts/0.
+(The NAME that lsof shows is not /dev/pts/0 but the full expansion
+of the symbolic link that lsof finds at /dev/pts/0.)
+
+Here's a second example, done on an HP-UX 9.01 host named ghg.ecn.
+Again, I've logged on to it from lsof.itap, so I start with:
+
+```shell
+$ lsof -i@lsof.itap
+COMMAND     PID     USER   FD   TYPE       DEVICE   SIZE/OFF  INODE NAME
+rlogind   10214     root    0u  inet   0x041d5f00     0t1536    TCP ghg.ecn.purdue.edu:login->lsof.itap.purdue.edu:1023
+...
+```
+
+Then,
+
+```shell
+$ lsof -p10214
+COMMAND     PID     USER   FD   TYPE       DEVICE   SIZE/OFF  INODE NAME
+...
+rlogind   10214     root    0u  inet   0x041d5f00     0t2005    TCP ghg.ecn.purdue.edu:login->lsof.itap.purdue.edu:1023
+...
+rlogind   10214     root    3u  VCHR  16,0x000030     0t2037  24642 /dev/ptym/ptys0
+```
+
+Here the key is the NAME /dev/ptym/ptys0.  In HP-UX 9.01 tty and
+pseudo tty devices are paired with the names like /dev/ptym/ptys0
+and /dev/pty/ttys0, so the following lsof probe is the final step.
+
+```shell
+$ lsof /dev/pty/ttys0
+COMMAND     PID     USER   FD   TYPE       DEVICE   SIZE/OFF  INODE NAME
+ksh       10215      abe    0u  VCHR  17,0x000030     0t3399  22607 /dev/pty/ttys0
+...
+```
+
+Here's a third example for an AIX 4.1.4 system.  I've used telnet
+to connect to it from lsof.itap.purdue.edu.  I start with:
+
+```shell
+$ lsof -i@lsof.itap.purdue.edu
+COMMAND     PID     USER   FD   TYPE     DEVICE   SIZE/OFF      INODE NAME
+...
+telnetd   15616     root    0u  inet 0x05a93400     0t5156        TCP cloud.cc.purdue.edu:telnet->lsof.itap.purdue.edu:3369
+```
+
+Then I look at the telnetd process:
+
+```shell
+$ lsof -p15616
+COMMAND     PID     USER   FD   TYPE     DEVICE   SIZE/OFF      INODE NAME
+...
+telnetd   15616     root    0u  inet 0x05a93400     0t5641        TCP cloud.cc.purdue.edu:telnet->lsof.itap.purdue.edu:3369
+...
+telnetd   15616     root    3u  VCHR    25,   0     0t5493        103 /dev/ptc/0
+```
+
+Here the key is /dev/ptc/0.  In AIX it's paired with /dev/pts/0.
+The last probe for that shows:
+
+```shell
+$ lsof /dev/pts/0
+COMMAND     PID     USER   FD   TYPE     DEVICE   SIZE/OFF      INODE NAME
+...
+ksh       16642      abe    0u  VCHR    26,   0     0t6461        360 /dev/pts/0
+```
+
+### The idrlogin.perl[5] Scripts
+
+There's another, perhaps easier way, to go about the job of
+tracing a network connection.  The lsof distribution contains
+two Perl scripts, idrlogin.perl (Perl 4) and idrlogin.perl5
+(Perl 5), that use lsof field output to display values for
+shells that are parented by rlogind, sshd, or telnetd, or
+connected directly to TCP sockets.  The lsof test suite contains
+a C library that can be adapted for use with C programs that
+need to call lsof and process its field output.
+
+The two Perl scripts use the lsof -R option; it causes the
+paRent process ID (PPID) to be listed in the lsof output.  The
+scripts identify all shell processes -- e.g., ones whose command
+names end in ``sh'' -- and determine if: 1) the ultimate ancestor
+process before a PID greater than 2 (e.g., init's PID is 1) is
+rlogind, sshd, or telnetd; or 2) the shell process has open
+TCP socket files.
+
+Here's an example of output from idlogin.perl on a Solaris 2.4
+system:
+
+```shell
+centurion: 1 = cd src/lsof4/scripts
+centurion: 2 = ./idrlogin.perl
+Login    Shell       PID Via           PID TTY        From
+oboyle   ksh       12640 in.telnetd  12638 pts/5      opal.cc.purdue.edu
+icdtest  ksh       15158 in.rlogind  15155 pts/6      localhost
+sh       csh       18207 in.rlogind  18205 pts/1      babylon5.cc.purdue.edu
+root     csh       18242 in.rlogind  18205 pts/1      babylon5.cc.purdue.edu
+trouble  ksh       19208 in.rlogind  18205 pts/1      babylon5.cc.purdue.edu
+abe      ksh       21334 in.rlogind  21332 pts/2      lsof.itap.purdue.edu
+```
+
+The scripts assume that its parent directory contains an
+executable lsof.  If you decide to use one of the scripts, you
+may want to customize it for your local lsof and perl paths.
+
+Note that processes executing as remote shells are also
+identified.
+
+Here's another example from a UnixWare 7.1.0 system.
+
+```shell
+tweeker: 1 = cd src/lsof4/scripts
+tweeker: 9 = ./idrlogin.perl
+Login    Shell       PID Via           PID TTY        From
+abe      ksh        9438 in.telnetd   9436 pts/3      lsof.itap.purdue.edu
+```
+
+## Watching an Ftp or Rcp Transfer
+
+The nature of the Internet being one of unpredictable performance
+at times, occasionally you want to know if a file transfer, being
+done by ftp or rcp, is making any progress.
+
+To use lsof for watching a file transfer, you need to know the
+PID of the file transfer process.  You can use ps to find that.
+Then use lsof,
+
+```shell
+$ lsof -p<PID>
+```
+
+to examine the files open to the transfer process.  Usually the
+ftp files or interest are at file descriptors 9 and 10 or 10 and
+11; for rcp, 3 and 4.  They describe the network socket file and
+the local data file.
+
+If you want to watch only those file descriptors as the file
+transfer progresses, try these lsof forms (for ftp in the example):
+
+```shell
+$ lsof -p<PID> -ad9,10 -r
+# or
+$ lsof -p<PID> -ad10,11 -r
+```
+
+Some options need explaining:
+
+- -p<PID>	specifies that lsof is to restrict its attention
+	to the process whose ID is <PID>.  You can specify
+	a set of PIDs by separating them with commas.
+
+		$ lsof -p 1234,5678,9012
+
+- -a		specifies that lsof is to AND its tests together.
+	The two tests that are specified are tests on the
+	PID and tests on file descriptions (`d9,10`).
+
+- d9,10	specifies that lsof is to test only file descriptors
+	9 and 10.  Note that the `-` is absent, since `-a`
+	is a unary option and can be followed immediately
+	by another lsof option.
+
+- -r          tells lsof to list the requested open file information,
+	sleep for a default 15 seconds, then list the open
+	file information again.  You can specify a different
+	time (in seconds) after -r and override the default.
+	Lsof issues a short line of equal signs between
+	each set of output to distinguish it.
+
+For an rcp transfer, the above example becomes:
+
+```shell
+$ lsof -p<PID> -ad3,4 -r
+```
+
+## Listing Open NFS Files
+
+Lsof will list all files open on remote file systems, supported
+by an NFS server.  Just use:
+
+```shell
+$ lsof -N
+```
+
+Note, however, that when run on an NFS server, lsof will not list
+files open to the server from one of its clients.  That's because
+lsof can only examine the processes running on the machine where
+it is called -- i.e., on the NFS server.
+
+If you run lsof on the NFS client, using the -N option, it will
+list files open by processes on the client that are on remote
+NFS file systems.
+
+## Listing Files Open by a Specific Login
+
+If you're interested in knowing what files the processes owned
+by a particular login name have open, lsof can help.
+
+```shell
+$ lsof -u<login>
+# or
+$ lsof -u<User ID number>
+```
+
+You can specify either the login name or the UID associated with
+it.  You can specify multiple login names and UID numbers, mixed
+together, by separating them with commas.
+
+```shell
+$ lsof -u548,abe
+```
+
+On the subject of login names and UIDs, it's worth noting that
+lsof can be told to report either.  By default it reports login
+names; the -l option switches reporting to UIDs.  You might want
+to use -l if login name lookup is slow for some reason.
+
+### Ignoring a Specific Login
+
+The -u option can also be used to direct lsof to ignore a
+specific login name or UID, or a list of them.  Simply prefix
+the login names or UIDs with a `^` character, as you might do
+in a regular expression.  The `^` prefix is useful, for example,
+when you want to have lsof ignore the files open to system
+processes, owned by the root (UID 0) login.  Try:
+
+```shell
+$ lsof -u ^root
+# or
+$ lsof -u ^0
+```
+
+## Listing Files Open to a Specific Process Group
+
+There's a Unix collection of processes called a process group.
+The name indicates that the processes of the group have a common
+association and are grouped so that a signal sent to one (e.g.,
+a keyboard kill stroke) is delivered to all.
+
+This causes Unix to create a two element process group:
+
+```shell
+$ lsof | less
+```
+
+You can use lsof to look at the open files of all members of a
+process group, if you know the process group ID number.  Assuming
+that it is 12717 for the above example, this lsof command:
+
+```shell
+$ lsof -g12717 -adcwd
+```
+
+would produce on a Solaris 8 system:
+
+```shell
+$ lsof -g12717 -adcwd
+COMMAND   PID  PGID USER  FD TYPE DEVICE SIZE/OFF    NODE NAME
+sshd    11369 12717 root cwd VDIR    0,2      189 1449175 /tmp (swap)
+sshd    12717 12717 root cwd VDIR  136,0     1024       2 /
+```
+
+The `-g12717'` option specifies the process group ID of interest;
+the `-adcwd` option specifies that options are to be ANDed and
+that lsof should limit file output to information about current
+working directory (`cwd`) files.
+
+
+## Output for Other Programs
+
+The -F option allows you to specify that lsof should describe
+open files with a special form of output, called field output,
+that can be parsed easily by a subsequent program.  The lsof
+distribution comes with sample AWK, Perl 4, and Perl 5 scripts
+that post-process field output.  The lsof test suite has a C
+library that could be adapted for use by C programs that want to
+process lsof field output from an in-bound pipe.
+
+The lsof manual page describes field output in detail in its
+OUTPUT FOR OTHER PROGRAMS section.  A quick look at a sample
+script in the scripts/ subdirectory of the lsof distribution will
+also give you an idea how field output works.
+
+The most important thing about field output is that it is relatively
+homogeneous across Unix dialects.  Thus, if you write a script
+to post-process field output for AIX, it probably will work for
+HP-UX, Solaris, and Ultrix as well.
+
+Support for other formats e.g. JSON is planned.
+
+## The Lsof Exit Code and Shell Scripts
+
+When lsof executes successfully, it returns an exit code based on
+the result of its search for specified files.  (If no files were
+specified, then the successful exit code is 0 (zero).)
+
+If lsof was asked to search for specific files, including any
+files on specified file systems, it returns an exit code of 0
+(zero) if it found all the specified files and at least one file
+on each specified file system.  Otherwise it returns a 1 (one) if
+any part of the search failed.
+
+This behavior can be modified by calling lsof with -Q, which will
+tell it to provide a successful exit code of 0 (zero) even if any
+part of the file or filesystem search failed.
+
+If lsof detects a generic (non-search) error during its execution,
+it returns an exit code of 1 (one).  The -Q option will not
+affect this behavior.
+
+You can use the exit code in a shell script to search for files
+on a file system and take action based on the result -- e.g.,
+
+```shell
+#!/bin/sh
+lsof <file_system_name> > /dev/null 2>&1
+if test $? -eq 0
+then
+echo "<file_system_name> has some users."
+else
+echo "<file_system_name> may have no users."
+fi
+```
+
+The -Q option can help in certain circumstances.  For example, if
+you want to log filesystem users without caring if there are no
+users:
+
+```shell
+#!/bin/sh
+lsof -Q <file_system_name>  > fs_users.log
+if test $? -ne 0
+then
+echo "Error: Something actually went wrong!" 1>&2
+exit 1
+fi
+```
+
+## Strange messages in the NAME column
+
+When lsof encounters problems analyzing a particular file, it may
+put a message in the file's NAME column.  Many of those messages
+are explained in the 00FAQ file of the lsof distribution.
+
+So consult 00FAQ first if you encounter a NAME column message you
+don't understand.  (00FAQ is a possible source of information
+about other unfamiliar things in lsof output, too.)
+
+If you can't find help in 00FAQ, you can use grep to look in the
+lsof source files for the message -- e.g.,
+
+```shell
+$ cd .../lsof_4.76_src
+$ grep "can't identify protocol" *.[ch]
+```
+
+The code associated with the message will usually make clear the
+reason for the message.
+
+If you have an lsof source tree that has been processed by the
+lsof Configure script, you need grep only there.  If, however,
+your source tree hasn't been processed by Configure, you may
+have to look in the top-level lsof source directory and in the
+dialects sub-directory for the UNIX dialect you are using - e.g.,
+
+```shell
+$ cd .../lsof_4.76_src
+$ grep "can't identify protocol" *.[ch]
+$ cd dialects/Linux
+$ grep "can't identify protocol" *.[ch]
+```
+
+In rare cases you may have to look in the lsof library, too --
+e.g.,
+
+```
+$ cd .../lsof_4.76_src
+$ grep "can't identify protocol" *.[ch]
+$ cd dialects/Linux
+$ grep "can't identify protocol" *.[ch]
+$ cd ../../lib
+$ grep "can't identify protocol" *.[ch]
+```
diff --git a/include/lsof.h b/include/lsof.h
new file mode 100644
index 0000000..2dcbd1b
--- /dev/null
+++ b/include/lsof.h
@@ -0,0 +1,586 @@
+/** @file
+ * lsof.h - 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: lsof.h,v 1.70 2018/03/26 21:50:45 abe Exp $
+ */
+
+#if !defined(LSOF_H)
+#    define LSOF_H 1
+
+#    include <stdint.h>
+#    include <stdio.h>
+
+/** lsof error returns */
+enum lsof_error {
+    LSOF_SUCCESS = 0,            /**< Success */
+    LSOF_ERROR_INVALID_ARGUMENT, /**< Invalid argument */
+    LSOF_ERROR_NO_MEMORY,        /**< No memory */
+    LSOF_ERROR_UNSUPPORTED,      /**< Unsupported operation */
+};
+
+/** File access mode */
+enum lsof_file_access_mode {
+    LSOF_FILE_ACCESS_NONE = 0,  /**< None */
+    LSOF_FILE_ACCESS_READ = 1,  /**< Read */
+    LSOF_FILE_ACCESS_WRITE = 2, /**< Write */
+    LSOF_FILE_ACCESS_READ_WRITE =
+        LSOF_FILE_ACCESS_READ | LSOF_FILE_ACCESS_WRITE, /**< Read and write */
+};
+
+/** File lock mode */
+enum lsof_lock_mode {
+    LSOF_LOCK_NONE,          /**< None */
+    LSOF_LOCK_UNKNOWN,       /**< Unknown */
+    LSOF_LOCK_READ_PARTIAL,  /**< Read lock on part of the file */
+    LSOF_LOCK_READ_FULL,     /**< Read lock on the entire file */
+    LSOF_LOCK_WRITE_PARTIAL, /**< Write lock on part of the file */
+    LSOF_LOCK_WRITE_FULL,    /**< Write lock on the entire file */
+    LSOF_LOCK_READ_WRITE,    /**< Read and write lock */
+    LSOF_LOCK_SOLARIS_NFS,   /**< Solaris NFS lock */
+    LSOF_LOCK_SCO_PARTIAL,   /**< SCO OpenServer lock on part of the file */
+    LSOF_LOCK_SCO_FULL,      /**< SCO OpenServer lock on the entire file */
+};
+
+/** File descriptor type */
+enum lsof_fd_type {
+    LSOF_FD_NUMERIC,         /**< Numeric fd opened in process */
+    LSOF_FD_UNKNOWN,         /**< Unknown fd type */
+    LSOF_FD_CWD,             /**< Current working directory */
+    LSOF_FD_ERROR,           /**< Failed to get fd information */
+    LSOF_FD_NOFD,            /**< No file descriptors */
+    LSOF_FD_ROOT_DIR,        /**< Root directory */
+    LSOF_FD_PARENT_DIR,      /**< Parent directory */
+    LSOF_FD_PROGRAM_TEXT,    /**< Program text */
+    LSOF_FD_LIBRARY_TEXT,    /**< Library text */
+    LSOF_FD_MEMORY,          /**< Memory-mapped file */
+    LSOF_FD_DELETED,         /**< Deleted file */
+    LSOF_FD_FILEPORT,        /**< Darwin fileport */
+    LSOF_FD_TASK_CWD,        /**< Per task/thread cwd */
+    LSOF_FD_CTTY,            /**< Character TTY */
+    LSOF_FD_JAIL_DIR,        /**< Jail directory */
+    LSOF_FD_VIRTUAL_8086,    /**< Virtual 8086 */
+    LSOF_FD_MERGE_386,       /**< MERGE386 vm86 region */
+    LSOF_FD_MMAP_DEVICE,     /**< Memory-mapped device */
+    LSOF_FD_LIBRARY_REF,     /**< Library references */
+    LSOF_FD_MMAP_UNKNOWN,    /**< Unknown memory-mapped file */
+    LSOF_FD_PREGION_UNKNOWN, /**< Unknown HP-UX pregion */
+};
+
+/** File type */
+enum lsof_file_type {
+    LSOF_FILE_NONE, /**< No file type */
+
+    /* struct stat S_IFMT modes */
+    LSOF_FILE_FIFO,    /**< FIFO special file */
+    LSOF_FILE_CHAR,    /**< Character special file */
+    LSOF_FILE_DIR,     /**< Directory */
+    LSOF_FILE_BLOCK,   /**< Block special file */
+    LSOF_FILE_REGULAR, /**< Regular file */
+    LSOF_FILE_LINK,    /**< Symolic link */
+    LSOF_FILE_SOCKET,  /**< Socket of unknown domain */
+
+    /* Network */
+    LSOF_FILE_IPV4,              /**< IPv4 socket */
+    LSOF_FILE_IPV6,              /**< IPv6 socket */
+    LSOF_FILE_AX25,              /**< AX.25 socket */
+    LSOF_FILE_INET,              /**< Internet(either IPv4 or IPv6) socket */
+    LSOF_FILE_LINK_LEVEL_ACCESS, /**< HP-UX link level access file */
+    LSOF_FILE_ROUTE,             /**< AF_ROUTE socket */
+    LSOF_FILE_UNIX,              /**< UNIX domain socket */
+    LSOF_FILE_X25,               /**< HP-UX x.25 socket */
+    LSOF_FILE_APPLETALK,         /**< Appletalk socket */
+    LSOF_FILE_NET_DRIVER,        /**< AF_NDRV network driver raw socket */
+    LSOF_FILE_INTERNAL_KEY,      /**< Darwin internal key-management socket */
+    LSOF_FILE_SYSTEM,            /**< AF_SYSTEM kernel event messages socket */
+    LSOF_FILE_PPP,               /**< PPP socket */
+    LSOF_FILE_IPX,               /**< IPX socket */
+    LSOF_FILE_RAW,               /**< raw socket */
+    LSOF_FILE_RAW6,              /**< raw IPv6 socket */
+    LSOF_FILE_NETLINK,           /**< netlink socket */
+    LSOF_FILE_PACKET,            /**< packet socket */
+    LSOF_FILE_ICMP,              /**< icmp socket */
+
+    /* procfs */
+    LSOF_FILE_PROC_AS,             /**< Solaris /proc/<PID>/as file */
+    LSOF_FILE_PROC_AUXV,           /**< /proc/<PID>/auxv file */
+    LSOF_FILE_PROC_CRED,           /**< Solaris /proc/<PID>/cred file */
+    LSOF_FILE_PROC_CTRL,           /**< /proc/<PID>/ctl control file */
+    LSOF_FILE_PROC_CUR_PROC,       /**< NetBSD /proc/curproc file */
+    LSOF_FILE_PROC_CWD,            /**< Solaris /proc/<PID>/cwd folder */
+    LSOF_FILE_PROC_DIR,            /**< /proc directory */
+    LSOF_FILE_PROC_EXEC_TYPE,      /**< FreeBSD /proc executable type (etype) */
+    LSOF_FILE_PROC_FD,             /**< /proc/<PID>/fd/<FD> file */
+    LSOF_FILE_PROC_FD_DIR,         /**< /proc/<PID>/fd directory */
+    LSOF_FILE_PROC_FILE,           /**< /proc/<PID>/file executable file */
+    LSOF_FILE_PROC_FP_REGS,        /**< /proc/<PID>/fpregs fp registers */
+    LSOF_FILE_PROC_PAGE_DATA,      /**< Solaris /proc/<PID>/pagedata file */
+    LSOF_FILE_PROC_GROUP_NOTIFIER, /**< /proc/<PID>/notepg group notifier */
+    LSOF_FILE_PROC_LDT,            /**< Solaris /proc/<PID>/ldt file */
+    LSOF_FILE_PROC_LPS_INFO,       /**< Solaris /proc/<PID>/lpsinfo file */
+    LSOF_FILE_PROC_LSTATUS,        /**< Solaris /proc/<PID>/lstatus file */
+    LSOF_FILE_PROC_LUSAGE,         /**< Solaris /proc/<PID>/lusage file */
+    LSOF_FILE_PROC_LWP_GWINDOWS,   /**< Solaris /proc/<PID>/lwp/<LWPID>/gwindows
+                                    */
+    LSOF_FILE_PROC_LWP_CTL, /**< Solaris /proc/<PID>/lwp/<LWPID>/lwpctl file */
+    LSOF_FILE_PROC_LWP_DIR, /**< Solaris /proc/<PID>/lwp or
+                               /proc/<PID>/lwp/<LWPID> directory */
+    LSOF_FILE_PROC_LWP_SINFO, /**< Solaris /proc/<PID>/lwp/<LWPID>/lwpsinfo file
+                               */
+    LSOF_FILE_PROC_LWP_STATUS, /**< Solaris /proc/<PID>/lwp/<LWPID>/lwpstatus
+                                  file */
+    LSOF_FILE_PROC_LWP_USAGE, /**< Solaris /proc/<PID>/lwp/<LWPID>/lwpusage file
+                               */
+    LSOF_FILE_PROC_LWP_XREGS, /**< Solaris /proc/<PID>/lwp/<LWPID>/xregs file */
+    LSOF_FILE_PROC_MAP,       /**< /proc/<PID>/map memory mapping file */
+    LSOF_FILE_PROC_MAPS,      /**< /proc/<PID>/maps memory mapping file */
+    LSOF_FILE_PROC_MEMORY,    /**< /proc/<PID>/mem memory image file */
+    LSOF_FILE_PROC_PROC_NOTIFIER, /**< /proc/<PID>/note process notifier file */
+    LSOF_FILE_PROC_OBJ,           /**< Solaris /proc/<PID>/object file */
+    LSOF_FILE_PROC_OBJ_DIR,       /**< Solaris /proc/<PID>/object directory */
+    LSOF_FILE_PROC_OLD_LWP,       /**< Solaris old format /proc/<LWPID> file */
+    LSOF_FILE_PROC_OLD_PID,       /**< Solaris old format /proc/<PID> file */
+    LSOF_FILE_PROC_OLD_PAGE,      /**< Solaris old /proc/<PID> page data file */
+    LSOF_FILE_PROC_REGS,          /**< /proc/<PID>/regs register set */
+    LSOF_FILE_PROC_RMAP,          /**< Solaris /proc/<PID>/rmap file */
+    LSOF_FILE_PROC_ROOT,          /**< Solaris /proc/<PID>/root directory */
+    LSOF_FILE_PROC_SIGACT,        /**< Solaris /proc/<PID>/sigact file */
+    LSOF_FILE_PROC_PSINFO,        /**< Solaris /proc/<PID>/psinfo file */
+    LSOF_FILE_PROC_STATUS,        /**< /proc/<PID>/status status file */
+    LSOF_FILE_PROC_USAGE,         /**< Solaris /proc/<PID>/usage file */
+    LSOF_FILE_PROC_WATCH,         /**< Solaris /proc/<PID>/watch file */
+    LSOF_FILE_PROC_XMAP,          /**< Solaris /proc/<PID>/xmap file */
+
+    /* Others */
+    LSOF_FILE_ANON_INODE,        /**< anonymous inode */
+    LSOF_FILE_DEL,               /**< Linux map file that has been deleted */
+    LSOF_FILE_DOOR,              /**< Solaris VDOOR file */
+    LSOF_FILE_KQUEUE,            /**< BSD style kernel event file */
+    LSOF_FILE_FSEVENTS,          /**< fsevents file */
+    LSOF_FILE_EVENTFD,           /**< eventfd file */
+    LSOF_FILE_PROCDESC,          /**< process descriptor file */
+    LSOF_FILE_MULTIPLEXED_BLOCK, /**< SCO OpenServer multiplexed block file */
+    LSOF_FILE_MULTIPLEXED_CHAR,  /**< SCO OpenServer multiplexed char file */
+    LSOF_FILE_UNKNOWN_DELETED,   /**< Linux unknown deleted file */
+    LSOF_FILE_UNKNOWN_MEMORY,    /**< Linux unknown memory file */
+    LSOF_FILE_UNKNOWN_FD,        /**< Linux unknown fd */
+    LSOF_FILE_UNKNOWN_CWD,       /**< Linux unknown cwd */
+    LSOF_FILE_UNKNOWN_ROOT_DIR,  /**< Linux unknown root dir */
+    LSOF_FILE_UNKNOWN_PROGRAM_TEXT, /**< Linux unknown program text */
+    LSOF_FILE_UNKNOWN_STAT,         /**< Linux unknown due to failed stat() */
+    LSOF_FILE_UNKNOWN_RAW, /**< Unknown file type, raw numbers provided in
+                              unknown_file_type_number */
+    LSOF_FILE_UNKNOWN,     /**< Unknown file type without raw number */
+    LSOF_FILE_PIPE,        /**< pipes */
+    LSOF_FILE_PORT,        /**< Solaris SYSV named pipe */
+    LSOF_FILE_POSIX_MQ,    /**< POSIX named message queue file */
+    LSOF_FILE_POSIX_SEMA,  /**< POSIX named semaphore file */
+    LSOF_FILE_POSIX_SHM,   /**< POSIX named shared memory file */
+    LSOF_FILE_SHM,         /**< SystemV shared memory file */
+    LSOF_FILE_PTS,         /**< FreeBSD /dev/pts file */
+    LSOF_FILE_SHARED_MEM_TRANSPORT, /**< AIX Shared memory transport file */
+    LSOF_FILE_STREAM,               /**< HP-UX streams */
+    LSOF_FILE_STREAM_SOCKET,        /**< HP-UX stream socket */
+    LSOF_FILE_SCO_UNKNOWN, /**< SCO OpenServer Xenix special file of unknown
+                              type */
+    LSOF_FILE_SCO_SEMA,    /**< SCO OpenServer Xenix semaphore file */
+    LSOF_FILE_SCO_SHARED,  /**< SCO OpenServer Xenix shared data file */
+    LSOF_FILE_UNSUPPORTED, /**< unsupported file type */
+
+    /* types from struct vnode */
+    LSOF_FILE_VNODE_VNON,  /**< The vnode has no type */
+    LSOF_FILE_VNODE_VREG,  /**< The vnode represents a regular file */
+    LSOF_FILE_VNODE_VDIR,  /**< The vnode represents a directory */
+    LSOF_FILE_VNODE_VBLK,  /**< The vnode represents a block special device */
+    LSOF_FILE_VNODE_VCHR,  /**< The vnode represents a char special device */
+    LSOF_FILE_VNODE_VLNK,  /**< The vnode represents a symbolic link */
+    LSOF_FILE_VNODE_VSOCK, /**< The vnode represents a socket */
+    LSOF_FILE_VNODE_VBAD,  /**< The vnode represents a bad file */
+    LSOF_FILE_VNODE_VMPC,  /**< The vnode represents a multiplexed character
+                              special device */
+    LSOF_FILE_VNODE_VFIFO, /**< The vnode represents a FIFO file */
+    LSOF_FILE_VNODE_VUNNAMED, /**< The vnode represents an unnamed file */
+    LSOF_FILE_VNODE_VDOOR,    /**< The vnode represents a door */
+    LSOF_FILE_VNODE_VPORT,    /**< The vnode represents a port */
+};
+
+/** @struct lsof_context
+ * Hidden struct of lsof context, use `lsof_new()` to get one
+ */
+struct lsof_context;
+
+/** @enum struct lsof_file flags */
+enum lsof_file_flag {
+    LSOF_FILE_FLAG_NONE,
+    /** \ref struct lsof_file.dev field is valid */
+    LSOF_FILE_FLAG_DEV_VALID = 0x00000001,
+    /** \ref struct lsof_file.rdev field is valid */
+    LSOF_FILE_FLAG_RDEV_VALID = 0x00000002,
+    /** \ref struct lsof_file.size field is valid */
+    LSOF_FILE_FLAG_SIZE_VALID = 0x00000004,
+    /** \ref struct lsof_file.offset field is valid */
+    LSOF_FILE_FLAG_OFFSET_VALID = 0x00000008,
+    /** \ref struct lsof_file.num_links field is valid */
+    LSOF_FILE_FLAG_NUM_LINKS_VALID = 0x00000010,
+    /** \ref struct lsof_file.inode field is valid */
+    LSOF_FILE_FLAG_INODE_VALID = 0x00000020,
+};
+
+/** An open file
+ */
+struct lsof_file {
+    /** Flags, see \ref lsof_file_flag */
+    uint64_t flags;
+
+    /* FD column */
+    /** File descriptor type */
+    enum lsof_fd_type fd_type;
+
+    /** File descriptor number, valid if \ref fd_type == \ref LSOF_FD_NUMERIC */
+    uint32_t fd_num;
+
+    /** File access mode */
+    enum lsof_file_access_mode access;
+
+    /** File lock mode */
+    enum lsof_lock_mode lock;
+
+    /* TYPE column */
+    /** File type */
+    enum lsof_file_type file_type;
+    /** Store raw file type number when \ref file_type == \ref LSOF_FILE_UNKNOWN
+     */
+    uint32_t unknown_file_type_number;
+
+    /* DEVICE column */
+    /** Device ID of device containing file, use major() and minor() to extract
+     * components. Valid if \ref flags & \ref LSOF_FILE_FLAG_DEV_VALID */
+    uint64_t dev;
+    /** Device ID of special character/block file, use major() and minor() to
+     * extract components. Valid if \ref flags & \ref
+     * LSOF_FILE_FLAG_RDEV_VALID */
+    uint64_t rdev;
+
+    /* SIZE, SIZE/OFF, OFFSET column */
+    /** File size, valid if \ref flags & \ref LSOF_FILE_FLAG_SIZE_VALID */
+    uint64_t size;
+
+    /** File offset, valid if \ref flags & \ref LSOF_FILE_FLAG_OFFSET_VALID */
+    uint64_t offset;
+
+    /* NLINK column */
+    /** Link count, valid if \ref flags & \ref LSOF_FILE_FLAG_NUM_LINKS_VALID */
+    uint64_t num_links;
+
+    /* NODE column */
+    /** File inode, valid if \ref flags & \ref LSOF_FILE_FLAG_INODE_VALID */
+    uint64_t inode;
+
+    /* NAME column */
+    /** File name or description */
+    char *name;
+};
+
+/** The result of lsof_gather(), grouped by process
+ *
+ * For each process, you can find a linked list of open files at `files`
+ */
+struct lsof_process {
+    /* COMMAND column */
+    char *command; /**< command name */
+    /* PID column */
+    uint32_t pid; /**< process ID */
+
+    /* TID column */
+    uint32_t tid; /**< task ID */
+    /* TASKCMD column */
+    char *task_cmd; /**< task command name */
+
+    /* ZONES column */
+    char *solaris_zone; /**< solaris zone name */
+    /* SECURITY-CONTEXT column */
+    char *selinux_context; /**< seLinux context name */
+
+    /* PGID column */
+    uint32_t pgid; /**< process group ID */
+    /* PPID column */
+    uint32_t ppid; /**< parent process ID */
+    /* USER column */
+    uint32_t uid; /**< user ID */
+
+    uint32_t num_files;      /**< length of files array */
+    struct lsof_file *files; /**< array of open files */
+};
+
+/** selection types */
+enum lsof_selection_type {
+    LSOF_SELECTION_COMMAND,         /**< select by command */
+    LSOF_SELECTION_COMMAND_REGEX,   /**< select by command regex */
+    LSOF_SELECTION_PATH,            /**< select by file path */
+    LSOF_SELECTION_FILE_SYSTEM,     /**< select by file system */
+    LSOF_SELECTION_NETWORK_ADDRESS, /**< select by network address */
+    LSOF_SELECTION_INTERNET,        /**< select by internet protocol */
+    LSOF_SELECTION_PROTOCOL_STATE,  /**< select by tcp/tpi state */
+    LSOF_SELECTION_NFS,             /**< select by nfs */
+    LSOF_SELECTION_PID,             /**< select by pid */
+    LSOF_SELECTION_PGID,            /**< select by pgid */
+    LSOF_SELECTION_UID,             /**< select by uid */
+    LSOF_SELECTION_TASK,            /**< select by tasks */
+    LSOF_SELECTION_SOLARIS_ZONE,    /**< select by Solaris zones */
+    LSOF_SELECTION_SELINUX_CONTEXT, /**< select by SELinux context */
+};
+
+/** Report selection status */
+struct lsof_selection {
+    enum lsof_selection_type type; /**< selection type */
+    int found;                     /**< whether selection matches file */
+    /** string selection argument, valid if type is one of
+     * LSOF_SELECTION_COMMAND, LSOF_SELECTION_COMMAND_REGEX,
+     * LSOF_SELECTION_PATH, LSOF_SELECTION_FILE_SYSTEM,
+     * LSOF_SELECTION_NETWORK_ADDRESS, LSOF_SELECTION_PROTOCOL_STATE,
+     * LSOF_SELECTION_UID, LSOF_SELECTION_SOLARIS_ZONE,
+     * LSOF_SELECTION_SELINUX_CONTEXT
+     */
+    char *string;
+    /** integer selection argument, valid if type is one of
+     * LSOF_SELECTION_PID, LSOF_SELECTION_PGID, LSOF_SELECTION_UID
+     */
+    uint64_t integer;
+};
+
+/** The result of lsof_gather() */
+struct lsof_result {
+    size_t num_processes;           /**< length of processes array */
+    struct lsof_process *processes; /**< array of processes */
+
+    /* Report selection status */
+    size_t num_selections;             /**< length of selections array */
+    struct lsof_selection *selections; /**< array of selections */
+};
+
+/** API version of liblsof
+ * you may use this macro to check the existence of
+ * functions
+ */
+#    define LSOF_API_VERSION 1
+
+/** Get runtime API version of liblsof
+ *
+ * liblsof might not function properly if API version mismatched between compile
+ * time and runtime.
+ *
+ * \since API version 1
+ */
+int lsof_get_api_version();
+
+/** Get library version of liblsof
+ *
+ * \return a string like "4.xx.x". The caller must not free it.
+ *
+ * \since API version 1
+ */
+char *lsof_get_library_version();
+
+/** Create a new lsof context
+ *
+ * The context should be freed via `lsof_destroy()`.
+ *
+ * \since API version 1
+ */
+struct lsof_context *lsof_new();
+
+/** Set output stream for warning and error messages
+ *
+ * lsof may want to print warning and error messages to the user. You can allow
+ * printing by setting the output stream and whether prints warning or not. You
+ * should also supply `program_name` so that the output starts with your program
+ * name.
+ *
+ * By default, the output is suppressed. You can set fp to NULL to suppress
+ * output.
+ *
+ * \since API version 1
+ */
+enum lsof_error lsof_set_output_stream(struct lsof_context *ctx, FILE *fp,
+                                       char *program_name, int warn);
+
+/** Ask lsof to avoid using blocking functions
+ *
+ * lsof may block when calling lstat(), readlink() or stat(). Call this function
+ * with `avoid=1` to let lsof avoid calling these functions.
+ *
+ * \since API version 1
+ */
+enum lsof_error lsof_avoid_blocking(struct lsof_context *ctx, int avoid);
+
+/** Ask lsof to avoid forking
+ *
+ * To avoid being blocked by some kernel operations, liblsof does them in forked
+ * child processes. Call this function to change this behavior.
+ *
+ * \since API version 1
+ */
+enum lsof_error lsof_avoid_forking(struct lsof_context *ctx, int avoid);
+
+/** Ask lsof to AND the selections
+ *
+ * By default, lsof OR the selections, for example, if you call
+ * lsof_select_unix_socket() and lsof_select_login(), it will report unix
+ * sockets OR open files by the user. If lsof_logic_and() is called, it will
+ * report unix sockets open by the specified user.
+ *
+ * \since API version 1
+ */
+enum lsof_error lsof_logic_and(struct lsof_context *ctx);
+
+/** Ask lsof to select process by command
+ *
+ * Select process executing the command that begins with the characters of
+ * `command`. You can specify exclusion by setting `exclude` to 1.
+ *
+ * You can call this function multiple times to add more search conditions.
+ *
+ * \since API version 1
+ */
+enum lsof_error lsof_select_process(struct lsof_context *ctx, char *command,
+                                    int exclude);
+
+/** Ask lsof to select process by matching regex
+ *
+ * Select process executing the command that matches with the
+ * `regex`.
+ *
+ * `regex` must begin and end with a slash ('/'), the characters between the
+ * slashes are interpreted as a regular expression.
+ *
+ * The closing slash may be followed by these modifiers:
+ * - b the regular expression is a basic one.
+ * - i ignore the case of letters.
+ * - x the regular expression is an extended one (default).
+ *
+ * You can call this function multiple times to add more search conditions.
+ *
+ * \since API version 1
+ */
+enum lsof_error lsof_select_process_regex(struct lsof_context *ctx,
+                                          char *regex);
+
+/** Ask lsof to select process by pid (process id)
+ *
+ * Select process by comparing pid. You can specify exclusion by setting
+ * `exclude` to 1.
+ *
+ * You can call this function multiple times to add more search conditions.
+ *
+ * \since API version 1
+ */
+enum lsof_error lsof_select_pid(struct lsof_context *ctx, uint32_t pid,
+                                int exclude);
+
+/** Ask lsof to select process by pgid (process group id)
+ *
+ * Select process by comparing pgid. You can specify exclusion by setting
+ * `exclude` to 1.
+ *
+ * You can call this function multiple times to add more search conditions.
+ *
+ * \since API version 1
+ */
+enum lsof_error lsof_select_pgid(struct lsof_context *ctx, uint32_t pgid,
+                                 int exclude);
+
+/** Ask lsof to select process by uid
+ *
+ * Select process whose user id equals to or not equals to `uid`
+ *
+ * You can call this function multiple times to add more search conditions.
+ *
+ * \since API version 1
+ */
+enum lsof_error lsof_select_uid(struct lsof_context *ctx, uint32_t uid,
+                                int exclude);
+
+/** Ask lsof to select process by user login
+ *
+ * Select process whose user login name equals to or not equals to `login`
+ *
+ * You can call this function multiple times to add more search conditions.
+ *
+ * \since API version 1
+ */
+enum lsof_error lsof_select_login(struct lsof_context *ctx, char *login,
+                                  int exclude);
+
+/** Freeze the lsof context
+ *
+ * You can only call it once per context. After this call, no more options can
+ * be changed.
+ *
+ * The function allows liblsof to do some preprocessing to improve performance.
+ *
+ * \since API version 1
+ */
+enum lsof_error lsof_freeze(struct lsof_context *ctx);
+
+/** List open files, grouped by processes
+ *
+ * The result is a struct lsof_result, saved into `result` parameter.
+ *
+ * You should not alter the content of `result`, nor call `free()` to
+ * pointers within. You should free `result` by calling
+ * `lsof_free_result()`
+ *
+ * If the context is not frozen, lsof_freeze() will be called.
+ *
+ * \return LSOF_INVALID_ARGUMENT if either pointer argument is NULL
+ *
+ * \since API version 1
+ */
+enum lsof_error lsof_gather(struct lsof_context *ctx,
+                            struct lsof_result **result);
+
+/** Destroy a lsof context
+ *
+ * You should call `lsof_free_result` to free all `struct lsof_result`
+ * before destroying the context.
+ *
+ * You must not use the context anymore after this call.
+ *
+ * \since API version 1
+ */
+void lsof_destroy(struct lsof_context *ctx);
+
+/** Free struct lsof_result
+ *
+ * \since API version 1
+ */
+void lsof_free_result(struct lsof_result *result);
+
+#endif
diff --git a/include/lsof_fields.h b/include/lsof_fields.h
new file mode 100644
index 0000000..05d97f5
--- /dev/null
+++ b/include/lsof_fields.h
@@ -0,0 +1,181 @@
+/*
+ * lsof_field.sh - field ID characters for lsof output that can be parsed
+ *		   (selected with -f or -F)
+ */
+
+/*
+ * 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: lsof_fields.h,v 1.14 2018/02/14 14:19:25 abe Exp $
+ */
+
+#if !defined(LSOF_FORMAT_H)
+#    define LSOF_FORMAT_H 1
+
+/*
+ * Codes for output fields:
+ *
+ *	LSOF_FID_*	ID character
+ *	LSOF_FIX_*	ID index
+ *	LSOF_FNM_*	name
+ *
+ * A field is displayed in the form:
+ *		<ID_character><data><field_terminator>
+ *
+ * Output fields are normally terminated with a NL ('\n'), but the field
+ * terminator can be set to NUL with the -0 (zero) option to lsof.
+ *
+ * Field sets -- process-specific information or information specific
+ * to a single file descriptor -- are terminated with NL when the field
+ * terminator is NUL.
+ */
+
+#    define LSOF_FID_ACCESS 'a'
+#    define LSOF_FIX_ACCESS 0
+#    define LSOF_FNM_ACCESS "access: r = read; w = write; u = read/write"
+
+#    define LSOF_FID_CMD 'c'
+#    define LSOF_FIX_CMD 1
+#    define LSOF_FNM_CMD "command name"
+
+#    define LSOF_FID_CT 'C'
+#    define LSOF_FIX_CT 2
+#    define LSOF_FNM_CT "file struct share count"
+
+#    define LSOF_FID_DEVCH 'd'
+#    define LSOF_FIX_DEVCH 3
+#    define LSOF_FNM_DEVCH "device character code"
+
+#    define LSOF_FID_DEVN 'D'
+#    define LSOF_FIX_DEVN 4
+#    define LSOF_FNM_DEVN "major/minor device number as 0x<hex>"
+
+#    define LSOF_FID_FD 'f'
+#    define LSOF_FIX_FD 5
+#    define LSOF_FNM_FD "file descriptor"
+
+#    define LSOF_FID_FA 'F'
+#    define LSOF_FIX_FA 6
+#    define LSOF_FNM_FA "file struct address as 0x<hex>"
+
+#    define LSOF_FID_FG 'G'
+#    define LSOF_FIX_FG 7
+#    define LSOF_FNM_FG "file flaGs"
+
+#    define LSOF_FID_INODE 'i'
+#    define LSOF_FIX_INODE 8
+#    define LSOF_FNM_INODE "inode number"
+
+#    define LSOF_FID_NLINK 'k'
+#    define LSOF_FIX_NLINK 9
+#    define LSOF_FNM_NLINK "link count"
+
+#    define LSOF_FID_TID 'K'
+#    define LSOF_FIX_TID 10
+#    define LSOF_FNM_TID "task ID (TID)"
+
+#    define LSOF_FID_LOCK 'l'
+#    define LSOF_FIX_LOCK 11
+#    define LSOF_FNM_LOCK "lock: r/R = read; w/W = write; u = read/write"
+
+#    define LSOF_FID_LOGIN 'L'
+#    define LSOF_FIX_LOGIN 12
+#    define LSOF_FNM_LOGIN "login name"
+
+#    define LSOF_FID_MARK 'm'
+#    define LSOF_FIX_MARK 13
+#    define LSOF_FNM_MARK "marker between repeated output"
+
+#    define LSOF_FID_TCMD 'M'
+#    define LSOF_FIX_TCMD 14
+#    define LSOF_FNM_TCMD "task comMand name"
+
+#    define LSOF_FID_NAME 'n'
+#    define LSOF_FIX_NAME 15
+#    define LSOF_FNM_NAME "comment, name, Internet addresses"
+
+#    define LSOF_FID_NI 'N'
+#    define LSOF_FIX_NI 16
+#    define LSOF_FNM_NI "file struct node ID as 0x<hex>"
+
+#    define LSOF_FID_OFFSET 'o'
+#    define LSOF_FIX_OFFSET 17
+#    define LSOF_FNM_OFFSET "file offset as 0t<dec> or 0x<hex>"
+
+#    define LSOF_FID_PID 'p'
+#    define LSOF_FIX_PID 18
+#    define LSOF_FNM_PID "process ID (PID)"
+
+#    define LSOF_FID_PGID 'g'
+#    define LSOF_FIX_PGID 19
+#    define LSOF_FNM_PGID "process group ID (PGID)"
+
+#    define LSOF_FID_PROTO 'P'
+#    define LSOF_FIX_PROTO 20
+#    define LSOF_FNM_PROTO "protocol name"
+
+#    define LSOF_FID_RDEV 'r'
+#    define LSOF_FIX_RDEV 21
+#    define LSOF_FNM_RDEV "raw device number as 0x<hex>"
+
+#    define LSOF_FID_PPID 'R'
+#    define LSOF_FIX_PPID 22
+#    define LSOF_FNM_PPID "paRent PID"
+
+#    define LSOF_FID_SIZE 's'
+#    define LSOF_FIX_SIZE 23
+#    define LSOF_FNM_SIZE "file size"
+
+#    define LSOF_FID_STREAM 'S'
+#    define LSOF_FIX_STREAM 24
+#    define LSOF_FNM_STREAM "stream module and device names"
+
+#    define LSOF_FID_TYPE 't'
+#    define LSOF_FIX_TYPE 25
+#    define LSOF_FNM_TYPE "file type"
+
+#    define LSOF_FID_TCPTPI 'T'
+#    define LSOF_FIX_TCPTPI 26
+#    define LSOF_FNM_TCPTPI "TCP/TPI info"
+
+#    define LSOF_FID_UID 'u'
+#    define LSOF_FIX_UID 27
+#    define LSOF_FNM_UID "user ID (UID)"
+
+#    define LSOF_FID_ZONE 'z'
+#    define LSOF_FIX_ZONE 28
+#    define LSOF_FNM_ZONE "zone name"
+
+#    define LSOF_FID_CNTX 'Z'
+#    define LSOF_FIX_CNTX 29
+#    define LSOF_FNM_CNTX "security context"
+
+#    define LSOF_FID_TERM '0'
+#    define LSOF_FIX_TERM 30
+#    define LSOF_FNM_TERM "(zero) use NUL field terminator instead of NL"
+
+#endif /* !defined(LSOF_FORMAT_H) */
diff --git a/lib/Makefile.skel b/lib/Makefile.skel
index 5c2b022..58c0d55 100644
--- a/lib/Makefile.skel
+++ b/lib/Makefile.skel
@@ -8,15 +8,15 @@ LIB=	liblsof.a
 
 CDEF=	${RC_CFLAGS}
 CDEFS=	${CDEF} ${CFGF}
-INCL=	${DINC}
+INCL=	${DINC} -I.. -I../include -Idialects/${DIALECT_DIR}
 
-HDR=	../lsof.h ../proto.h ../dlsof.h ../dproto.h ../machine.h
+HDR=	common.h proto.h proto.h
 
-SRC=	ckkv.c cvfs.c dvch.c fino.c isfn.c lkud.c pdvn.c prfp.c \
-	ptti.c rdev.c regex.c rmnt.c rnam.c rnch.c rnmh.c snpf.c
+SRC=	ckkv.c cvfs.c dvch.c fino.c isfn.c lkud.c lsof.c misc.c node.c pdvn.c prfp.c \
+	print.c proc.c ptti.c rdev.c rmnt.c rnam.c rnch.c rnmh.c rnmt.c
 
-OBJ=	ckkv.o cvfs.o dvch.o fino.o isfn.o lkud.o pdvn.o prfp.o \
-	ptti.o rdev.o regex.o rmnt.o rnam.o rnch.o rnmh.o snpf.o
+OBJ=	ckkv.o cvfs.o dvch.o fino.o isfn.o lkud.o lsof.o misc.o node.o pdvn.o prfp.o \
+	print.o proc.o ptti.o rdev.o rmnt.o rnam.o rnch.o rnmh.o rnmt.o
 
 all:	${LIB}
 
@@ -49,8 +49,6 @@ ptti.o:	${HDR} ptti.c
 
 rdev.o: ${HDR} rdev.c
 
-regex.o: ${HDR} ../regex.h regex.c
-
 rmnt.o: ${HDR} rmnt.c
 
 rnam.o: ${HDR} rnam.c
@@ -59,4 +57,4 @@ rnch.o: ${HDR} rnch.c
 
 rnmh.o: ${HDR} rnmh.c
 
-snpf.o: ${HDR} snpf.c
+rnmt.o: ${HDR} rnmt.c
diff --git a/lib/ckkv.c b/lib/ckkv.c
index 8d49e7b..4526048 100644
--- a/lib/ckkv.c
+++ b/lib/ckkv.c
@@ -2,7 +2,6 @@
  * cvfs.c -- ckkv() function for lsof library
  */
 
-
 /*
  * Copyright 1998 Purdue Research Foundation, West Lafayette, Indiana
  * 47907.  All rights reserved.
@@ -29,64 +28,55 @@
  * 4. This notice may not be removed or altered.
  */
 
+#include "common.h"
+#include "machine.h"
 
-#include "../machine.h"
-
-#if	defined(USE_LIB_CKKV)
-
-# if	!defined(lint)
-static char copyright[] =
-"@(#) Copyright 1998 Purdue Research Foundation.\nAll rights reserved.\n";
-# endif	/* !defined(lint) */
-
-#include "../lsof.h"
-#include <sys/utsname.h>
+#if defined(USE_LIB_CKKV)
 
+#    include <sys/utsname.h>
 
 /*
  * ckkv() - check kernel version
  */
 
-void
-ckkv(d, er, ev, ea)
-	char *d;			/* dialect */
-	char *er;			/* expected revision; NULL, no test */
-	char *ev;			/* expected version; NULL, no test */
-	char *ea;			/* expected architecture; NULL, no
-					 * test */
+void ckkv(struct lsof_context *ctx, /* context */
+          char *d,                  /* dialect */
+          char *er,                 /* expected revision; NULL, no test */
+          char *ev,                 /* expected version; NULL, no test */
+          char *ea)                 /* expected architecture; NULL, no test */
 {
 
-# if	defined(HASKERNIDCK)
-	struct utsname u;
-
-	if (Fwarn)
-	    return;
-/*
- * Read the system information via uname(2).
- */
-	if (uname(&u) < 0) {
-	    (void) fprintf(stderr, "%s: uname error: %s\n",
-		Pn, strerror(errno));
-	    Error();
-	}
-	if (er && strcmp(er, u.release)) {
-	    (void) fprintf(stderr,
-		"%s: WARNING: compiled for %s release %s; this is %s.\n",
-		Pn, d, er, u.release);
-	}
-	if (ev && strcmp(ev, u.version)) {
-	    (void) fprintf(stderr,
-		"%s: WARNING: compiled for %s version %s; this is %s.\n",
-		Pn, d, ev, u.version);
-	}
-	if (ea && strcmp(ea, u.machine)) {
-	    (void) fprintf(stderr,
-		"%s: WARNING: compiled for %s architecture %s; this is %s.\n",
-		Pn, d, ea, u.machine);
-	}
-# endif	/* defined(HASKERNIDCK) */
+#    if defined(HASKERNIDCK)
+    struct utsname u;
 
+    if (Fwarn)
+        return;
+    /*
+     * Read the system information via uname(2).
+     */
+    if (uname(&u) < 0) {
+        (void)fprintf(stderr, "%s: uname error: %s\n", Pn, strerror(errno));
+        Error(ctx);
+    }
+    if (er && strcmp(er, u.release)) {
+        (void)fprintf(stderr,
+                      "%s: WARNING: compiled for %s release %s; this is %s.\n",
+                      Pn, d, er, u.release);
+    }
+    if (ev && strcmp(ev, u.version)) {
+        (void)fprintf(stderr,
+                      "%s: WARNING: compiled for %s version %s; this is %s.\n",
+                      Pn, d, ev, u.version);
+    }
+    if (ea && strcmp(ea, u.machine)) {
+        (void)fprintf(
+            stderr,
+            "%s: WARNING: compiled for %s architecture %s; this is %s.\n", Pn,
+            d, ea, u.machine);
+    }
+#    endif /* defined(HASKERNIDCK) */
 }
-#else	/* !defined(USE_LIB_CKKV) */
-char ckkv_d1[] = "d"; char *ckkv_d2 = ckkv_d1;
-#endif	/* defined(USE_LIB_CKKV) */
+#else  /* !defined(USE_LIB_CKKV) */
+char ckkv_d1[] = "d";
+char *ckkv_d2 = ckkv_d1;
+#endif /* defined(USE_LIB_CKKV) */
diff --git a/lib/common.h b/lib/common.h
new file mode 100644
index 0000000..6014510
--- /dev/null
+++ b/lib/common.h
@@ -0,0 +1,1543 @@
+/*
+ * common.h - common 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: common.h,v 1.70 2018/03/26 21:50:45 abe Exp $
+ */
+
+#if !defined(COMMON_H)
+#    define COMMON_H 1
+
+#    include "lsof.h"
+#    if defined(AUTOTOOLS)
+#        include "autotools.h"
+#    endif
+#    include "machine.h"
+
+#    if !defined(FSV_DEFAULT)
+#        define FSV_DEFAULT 0
+#    endif /* !defined(FSV_DEFAULT) */
+
+#    include "lsof_fields.h"
+
+#    include <ctype.h>
+#    include <errno.h>
+
+#    if defined(HASSETLOCALE)
+#        include <locale.h>
+#    endif /* defined(HASSETLOCALE) */
+
+#    include <netdb.h>
+#    include <pwd.h>
+#    include <stdio.h>
+
+#    include <sys/stat.h>
+#    include <sys/wait.h>
+
+/*
+ * Definitions and structures that may be needed by dlsof.h
+ */
+
+#    if !defined(INODETYPE)
+#        define INODETYPE unsigned long /* node number storage type */
+#        define INODEPSPEC                                                     \
+            "l" /* node number printf specification                            \
+                 * modifier */
+#    endif      /* !defined(INODETYPE) */
+
+struct l_dev {
+    dev_t rdev;      /* device */
+    INODETYPE inode; /* inode number */
+    char *name;      /* name */
+    int v;           /* has been verified
+                      * (when DCUnsafe == 1) */
+};
+
+#    if defined(HASEPTOPTS)
+/*
+ * End point definitions
+ */
+
+#        define CHEND_PIPE 0x01 /* pipe endpoint ID */
+#        define CHEND_PTY 0x02  /* pseudoterminal endpoint ID */
+
+#        if defined(HASUXSOCKEPT)
+#            define CHEND_UXS 0x04 /* UNIX socket endpoint ID */
+#        endif                     /* defined(HASUXSOCKEPT) */
+
+#        define CHEND_NETS 0x08  /* INET socket endpoint ID */
+#        define CHEND_PSXMQ 0x10 /* Posix MQ endpoint ID */
+
+#        if defined(HASIPv6)
+#            define CHEND_NETS6 0x20 /* INET6 socket endpoint ID */
+#        endif                       /* defined(HASIPv6) */
+
+#        define CHEND_EVTFD 0x40 /* eventfd endpoint ID */
+
+#        define EPT_PIPE 0x01     /* process has pipe file */
+#        define EPT_PIPE_END 0x02 /* process has pipe end point file */
+#        define EPT_PTY 0x04      /* process has a pseudoterminal file */
+#        define EPT_PTY_END                                                    \
+            0x08 /* process has a pseudoterminal end                           \
+                  * point file */
+
+#        if defined(HASUXSOCKEPT)
+#            define EPT_UXS 0x10 /* process has a UNIX socket file */
+#            define EPT_UXS_END                                                \
+                0x20 /* process has a UNIX socket end point                    \
+                      * file */
+#        endif       /* defined(HASUXSOCKEPT) */
+
+#        define EPT_NETS 0x40 /* process has a INET socket file */
+#        define EPT_NETS_END                                                   \
+            0x80 /* process has a INET socket end point                        \
+                  * file */
+
+#        define EPT_PSXMQ 0x100 /* process has a POSIX MQ file*/
+#        define EPT_PSXMQ_END                                                  \
+            0x200 /* process has a POSIX MQ end point                          \
+                   * file*/
+
+#        if defined(HASIPv6)
+#            define EPT_NETS6 0x400 /* process has a INET6 socket file */
+#            define EPT_NETS6_END                                              \
+                0x800 /* process has a INET6 socket end point                  \
+                       * file */
+#        endif        /* defined(HASIPv6) */
+
+#        define EPT_EVTFD 0x1000 /* process has a eventfd file*/
+#        define EPT_EVTFD_END                                                  \
+            0x2000 /* process has a eventfd end point                          \
+                    * file*/
+#    endif         /* defined(HASEPTOPTS) */
+
+/*
+ * FILE_FLAG column names
+ */
+
+#    define FF_AIO "AIO"
+#    define FF_APPEND "AP"
+#    define FF_ASYNC "ASYN"
+#    define FF_BLKANDSET "BAS"
+#    define FF_BLKINUSE "BKIU"
+#    define FF_BLKSEEK "BSK"
+#    define FF_CIO "CIO"
+#    define FF_CLONE "CLON"
+#    define FF_CLREAD "CLRD"
+#    define FF_COPYAVOID "CA"
+#    define FF_CREAT "CR"
+#    define FF_DATAFLUSH "DFLU"
+#    define FF_DEFER "DF"
+#    define FF_DEFERIND "DFI"
+#    define FF_DELAY "DLY"
+#    define FF_DIRECT "DIR"
+#    define FF_DIRECTORY "DTY"
+#    define FF_DOCLONE "DOCL"
+#    define FF_DSYNC "DSYN"
+#    define FF_EVTONLY "EVO"
+#    define FF_EXCL "EXCL"
+#    define FF_EXEC "EX"
+#    define FF_EXLOCK "XL"
+#    define FF_FILE_MBLK "MBLK"
+#    define FF_FSYNC "FSYN"
+#    define FF_GCFDEFER "GCDF"
+#    define FF_GCFMARK "GCMK"
+#    define FF_GENTTY "GTTY"
+#    define FF_HASLOCK "LCK"
+#    define FF_HUP "HUP"
+#    define FF_KERNEL "KERN"
+#    define FF_KIOCTL "KIOC"
+#    define FF_LARGEFILE "LG"
+#    define FF_MARK "MK"
+#    define FF_MOUNT "MNT"
+#    define FF_MSYNC "MSYN"
+#    define FF_NBDRM "NBDR"
+#    define FF_NBIO "NBIO"
+#    define FF_NBLOCK "NB"
+#    define FF_NBUF "NBF"
+#    define FF_NMFS "NMFS"
+#    define FF_NDELAY "ND"
+#    define FF_NET "NET"
+#    define FF_NOATM "NATM"
+#    define FF_NOCACHE "NC"
+#    define FF_NOCTTY "NTTY"
+#    define FF_NODSYNC "NDSY"
+#    define FF_NOFOLNK "NFLK"
+#    define FF_NOTOSTOP "NOTO"
+#    define FF_NSHARE "NSH"
+#    define FF_OLRMIRROR "OLRM"
+#    define FF_PATH "PATH"
+#    define FF_POSIX_AIO "PAIO"
+#    define FF_POSIX_PIPE "PP"
+#    define FF_RAIOSIG "RAIO"
+#    define FF_RCACH "RC"
+#    define FF_RDWR "RW"
+#    define FF_READ "R"
+#    define FF_REVOKED "REV"
+#    define FF_RSHARE "RSH"
+#    define FF_RSYNC "RSYN"
+#    define FF_SETBLK "BL"
+#    define FF_SHLOCK "SL"
+#    define FF_SNAP "SNAP"
+#    define FF_SOCKET "SOCK"
+#    define FF_SQTSH1 "SQS1"
+#    define FF_SQTSH2 "SQS2"
+#    define FF_SQTREPAIR "SQR"
+#    define FF_SQTSH "SQSH"
+#    define FF_SQTSVM "SQSV"
+#    define FF_STOPIO "STPI"
+#    define FF_SYNC "SYN"
+#    define FF_SYNCRON "SWR"
+#    define FF_TCP_MDEVONLY "TCPM"
+#    define FF_TERMIO "TIO"
+#    define FF_TMPFILE "TMPF"
+#    define FF_TRUNC "TR"
+#    define FF_VHANGUP "VH"
+#    define FF_VTEXT "VTXT"
+#    define FF_WAKEUP "WKUP"
+#    define FF_WAITING "WTG"
+#    define FF_WRITE "W"
+
+/*
+ * Process open file flag names
+ */
+
+#    define POF_ALLOCATED "ALLC"
+#    define POF_BNRD "BR"
+#    define POF_BNWR "BW"
+#    define POF_BNHUP "BHUP"
+#    define POF_CLOEXEC "CX"
+#    define POF_CLOSING "CLSG"
+#    define POF_FDLOCK "LCK"
+#    define POF_INUSE "USE"
+#    define POF_MAPPED "MP"
+#    define POF_FSHMAT "SHMT"
+#    define POF_RESERVED "OPIP"
+#    define POF_RSVWT "RSVW"
+
+/*
+ * Cross-over (-x) option values
+ */
+
+#    define XO_FILESYS 0x1 /* file system mount points */
+#    define XO_SYMLINK 0x2 /* symbolic links */
+#    define XO_ALL (XO_FILESYS | XO_SYMLINK)
+
+#    include "dlsof.h"
+
+#    include <sys/types.h> /* just in case -- because utmp.h
+                            * may need it */
+#    include <regex.h>
+
+#    if defined(EMPTY)
+#        undef EMPTY
+#    endif /* defined(EMPTY) */
+
+#    if defined(HASUTMPX)
+#        include <utmpx.h>
+#    else /* !defined(HASUTMPX) */
+#        include <utmp.h>
+#    endif /* defined(HASUTMPX) */
+
+extern int errno;
+extern char *optarg;
+extern int optind;
+
+#    define ACCESSERRFMT "%s: WARNING: access %s: %s\n"
+
+#    if defined(HASDCACHE)
+#        define CRC_POLY 0120001 /* CRC-16 polynomial */
+#        define CRC_TBLL 256     /* crc table length for software */
+#        define CRC_BITS 8       /* number of bits contributing */
+#    endif                       /* defined(HASDCACHE) */
+#    define CMDL                                                               \
+        9              /* maximum number of characters from                    \
+                        * command name to print in COMMAND                     \
+                        * column */
+#    define CWD " cwd" /* current working directory fd name */
+#    define FDLEN 8    /* fd printing array length */
+#    define FSV_FA 0x1 /* file struct addr status */
+#    define FSV_CT 0x2 /* file struct count status */
+#    define FSV_FG 0x4 /* file struct flags */
+#    define FSV_NI 0x8 /* file struct node ID status */
+
+#    if !defined(GET_MAJ_DEV)
+#        define GET_MAJ_DEV                                                    \
+            major /* if no dialect specific macro has                          \
+                   * been defined, use standard major()                        \
+                   * macro */
+#    endif        /* !defined(GET_MAJ_DEV) */
+
+#    if !defined(GET_MIN_DEV)
+#        define GET_MIN_DEV                                                    \
+            minor /* if no dialect specific macro has                          \
+                   * been defined, use standard minor()                        \
+                   * macro */
+#    endif        /* !defined(GET_MIN_DEV) */
+
+#    if defined(HASSELINUX)
+#        define HASHCNTX                                                       \
+            128 /* security context hash bucket count                          \
+                 * -- MUST BE A POWER OF 2!!! */
+#    endif      /* defined(HASSELINUX) */
+
+#    if defined(HASZONES)
+#        define HASHZONE                                                       \
+            128 /* zone hash bucket count -- MUST BE                           \
+                 * A POWER OF 2!!! */
+#    endif      /* defined(HASZONES) */
+
+#    define IDINCR 10 /* PID/PGID table malloc() increment */
+
+#    if !defined(INADDR_LOOPBACK)
+#        define INADDR_LOOPBACK (u_long)0x7f000001
+#    endif /* !defined(INADDR_LOOPBACK) */
+
+#    define IPROTOL 8 /* Internet protocol length */
+
+#    if !defined(KA_T_FMT_X)
+#        define KA_T_FMT_X                                                     \
+            "0x%08lx" /* format for printing kernel                            \
+                       * addresses in 0x... format */
+#    endif            /* !defined(KA_T_FMT_X) */
+
+#    if !defined(LOGINML)
+#        if defined(HASUTMPX)
+#            define LOGINML sizeof(((struct utmpx *)0)->ut_user)
+/* login name length */
+#        else /* !defined(HASUTMPX) */
+#            define LOGINML sizeof(((struct utmp *)0)->ut_name)
+/* login name length */
+#        endif /* defined(HASUTMPX) */
+#    endif     /* !defined(LOGINML) */
+
+#    define LPROCINCR 128 /* Lproc[] allocation increment */
+#    define LSOF_GITHUB_URL "https://github.com/lsof-org"
+#    define LSOF_REPO "lsof"
+#    define LSOF_BRANCH "master"
+#    define LSOF_REPO_URL LSOF_GITHUB_URL "/" LSOF_REPO
+#    define LSOF_FAQ_URL LSOF_REPO_URL "/blob/" LSOF_BRANCH "/00FAQ"
+#    define LSOF_MAN_URL LSOF_REPO_URL "/blob/" LSOF_BRANCH "/Lsof.8"
+#    define MIN_AF_ADDR sizeof(struct in_addr)
+/* minimum AF_* address length */
+
+#    if defined(HASIPv6)
+#        define MAX_AF_ADDR sizeof(struct in6_addr)
+/* maximum AF_* address length */
+#    else                               /* !defined(HASIPv6) */
+#        define MAX_AF_ADDR MIN_AF_ADDR /* maximum AF_* address length */
+#    endif                              /* defined(HASIPv6) */
+
+#    define MAXDCPATH 4 /* paths in DCpath[] */
+#    define MAXNWAD 100 /* maximum network addresses */
+
+#    if !defined(MEMMOVE)
+#        define MEMMOVE memmove
+#    endif /* !defined*MEMMOVE) */
+
+#    define N_REGLR 0      /* regular file system node */
+#    define N_AFS 1        /* AFS node */
+#    define N_AFPFS 2      /* Apple Darwin AppleShare */
+#    define N_ANON_INODE 3 /* Linux anon_inodefs node */
+#    define N_AUSX 4       /* Auspex LFS node */
+#    define N_AUTO 5       /* automount node */
+#    define N_BLK 6        /* block device node */
+#    define N_CACHE 7      /* cached file system node */
+#    define N_CDFS 8       /* CD-ROM node */
+#    define N_CFS 9        /* CFS node */
+#    define N_CHR 10       /* character device node */
+#    define N_COM 11       /* streams common device node */
+#    define N_CTFSADIR 12  /* Solaris CTFS adir node */
+#    define N_CTFSBUND 13  /* Solaris CTFS bundle node */
+#    define N_CTFSCDIR 14  /* Solaris CTFS cdir node */
+#    define N_CTFSCTL 15   /* Solaris CTFS ctl node */
+#    define N_CTFSEVT 16   /* Solaris CTFS events node */
+#    define N_CTFSLATE 17  /* Solaris CTFS latest node */
+#    define N_CTFSROOT 18  /* Solaris CTFS root node */
+#    define N_CTFSSTAT 19  /* Solaris CTFS status node */
+#    define N_CTFSSYM 20   /* Solaris CTFS symbolic node */
+#    define N_CTFSTDIR 21  /* Solaris CTFS type node */
+#    define N_CTFSTMPL 22  /* Solaris CTFS template node */
+#    define N_DEV 23       /* DEV FS node */
+#    define N_DOOR 24      /* DOOR node */
+#    define N_FD 25        /* FD node */
+#    define N_FIFO 26      /* FIFO node */
+#    define N_HSFS 27      /* High Sierra node */
+#    define N_KERN 28      /* BSD /kern node */
+#    define N_LOFS 29      /* loopback node */
+#    define N_MNT 30       /* mount file system device node */
+#    define N_MPC 31       /* multiplexed device node */
+#    define N_MVFS 32      /* multi-volume file system node (?) */
+#    define N_NFS 33       /* NFS node */
+#    define N_NFS4 34      /* NFS version 4 node */
+#    define N_NM 35        /* named file system node */
+#    define N_OBJF 36      /* objfs file system node */
+#    define N_PCFS 37      /* PC file system node */
+#    define N_PIPE 38      /* pipe device node */
+#    define N_PORT 39      /* port node */
+#    define N_PROC 40      /* /proc node */
+#    define N_PSEU 41      /* pseudofs node */
+#    define N_SAMFS 42     /* Solaris SAM-FS */
+#    define N_SANFS 43     /* AIX SANFS */
+#    define N_SDEV 44      /* Solaris sdev file system node */
+#    define N_SHARED 45    /* Solaris sharedfs */
+#    define N_SOCK 46      /* sock_vnodeops node */
+#    define N_SPEC 47      /* spec_vnodeops node */
+#    define N_STREAM 48    /* stream node */
+#    define N_TMP 49       /* tmpfs node */
+#    define N_UFS 50       /* UNIX file system node */
+#    define N_UNKN 51      /* unknown node type */
+#    define N_VXFS 52      /* Veritas file system node */
+#    define N_XFS 53       /* XFS node */
+#    define N_ZFS 54       /* ZFS node */
+#    define N_MQUEUE 55    /* Posix mqueue node on Linux */
+
+#    if !defined(OFFDECDIG)
+#        define OFFDECDIG                                                      \
+            8 /* maximum number of digits in the                               \
+               * offset decimal form (0t...) */
+#    endif    /* !defined(OFFDECDIG) */
+
+#    if !defined(USELOCALREADDIR)
+#        define CloseDir closedir /* use standard closedir() */
+#        define OpenDir opendir   /* use standard opendir() */
+#        define ReadDir readdir   /* use standard readdir() */
+#    endif                        /* !defined(USELOCALREADDIR) */
+
+#    define RPTTM 15   /* default repeat seconds */
+#    define RTD " rtd" /* root directory fd name */
+#    define TASKCMDL                                                           \
+        9 /* maximum number of characters from                                 \
+           * command name to print in TASKCMD                                  \
+           * column */
+#    define TCPTPI_FLAGS                                                       \
+        0x0001                    /* report TCP/TPI socket options and         \
+                                   * state, and TCP_NODELAY state */
+#    define TCPTPI_QUEUES 0x0002  /* report TCP/TPI queue lengths */
+#    define TCPTPI_STATE 0x0004   /* report TCP/TPI state */
+#    define TCPTPI_WINDOWS 0x0008 /* report TCP/TPI window sizes */
+#    define TCPTPI_ALL (TCPTPI_QUEUES | TCPTPI_STATE | TCPTPI_WINDOWS)
+/* report all TCP/TPI info */
+#    define TCPUDPALLOC                                                        \
+        32                 /* allocation amount for TCP and UDP                \
+                            * state tables */
+#    define TMLIMIT 15     /* readlink() & stat() timeout sec */
+#    define TMLIMMIN 2     /* minimum timeout */
+#    define TYPEL 8        /* type character length */
+#    define UIDCACHEL 1024 /* UID cache length */
+#    define UIDINCR 10     /* UID table malloc() increment */
+#    define USERPRTL 8     /* UID/login print length limit */
+
+#    if !defined(SZOFFTYPE)
+#        define SZOFFTYPE unsigned long /* type for size and offset */
+#        undef SZOFFPSPEC
+#        define SZOFFPSPEC                                                     \
+            "l" /* SZOFFTYPE printf specification                              \
+                 * modifier */
+#    endif      /* !defined(SZOFFTYPE) */
+
+#    if !defined(TIMEVAL_LSOF)
+#        define TIMEVAL_LSOF timeval
+#    endif /* !defined(TIMEVAL_LSOF) */
+
+#    if !defined(XDR_PMAPLIST)
+#        define XDR_PMAPLIST xdr_pmaplist
+#    endif /* !defined(XDR_PMAPLIST) */
+
+#    if !defined(XDR_VOID)
+#        define XDR_VOID xdr_void
+#    endif /* !defined(XDR_VOID) */
+
+/*
+ * Output title definitions
+ */
+
+#    define CMDTTL "COMMAND"
+extern int CmdColW;
+#    define CNTXTTL "SECURITY-CONTEXT"
+extern int CntxColW;
+#    define DEVTTL "DEVICE"
+extern int DevColW;
+#    define FCTTL "FCT"
+extern int FcColW;
+#    define FDTTL "FD"
+extern int FdColW;
+#    define FGTTL "FILE-FLAG"
+extern int FgColW;
+#    define FSTTL "FILE-ADDR"
+extern int FsColW;
+#    define NITTL "NODE-ID"
+extern int NiColW;
+extern char *NiTtl;
+#    define NLTTL "NLINK"
+extern int NlColW;
+#    define NMTTL "NAME"
+extern int NmColW;
+#    define NODETTL "NODE"
+extern int NodeColW;
+#    define OFFTTL "OFFSET"
+#    define PGIDTTL "PGID"
+extern int PgidColW;
+#    define PIDTTL "PID"
+extern int PidColW;
+#    define PPIDTTL "PPID"
+extern int PpidColW;
+#    define SZTTL "SIZE"
+#    define SZOFFTTL "SIZE/OFF"
+extern int SzOffColW;
+#    define TASKCMDTTL "TASKCMD"
+extern int TaskCmdColW;
+#    define TASKTIDTTL "TID"
+extern int TaskTidColW;
+#    define TYPETTL "TYPE"
+extern int TypeColW;
+#    define USERTTL "USER"
+extern int UserColW;
+#    define ZONETTL "ZONE"
+extern int ZoneColW;
+
+/*
+ * Selection flags
+ */
+
+#    define PS_PRI                                                             \
+        1 /* primary process selection -- e.g.,                                \
+           * by PID or UID */
+#    define PS_SEC                                                             \
+        2                   /* secondary process selection -- e.g.,            \
+                             * by directory or file */
+#    define SELCMD 0x0001   /* select process by command name */
+#    define SELCNTX 0x0002  /* select security context (-Z) */
+#    define SELFD 0x0004    /* select file by descriptor name */
+#    define SELNA 0x0008    /* select socket by address (-i@...) */
+#    define SELNET 0x0010   /* select Internet socket files (-i) */
+#    define SELNFS 0x0020   /* select NFS files (-N) */
+#    define SELNLINK 0x0040 /* select based on link count */
+#    define SELNM 0x0080    /* select by name */
+#    define SELPGID 0x0100  /* select process group IDs (-g) */
+#    define SELPID 0x0200   /* select PIDs (-p) */
+#    define SELUID 0x0400   /* select UIDs (-u) */
+#    define SELUNX 0x0800   /* select UNIX socket (-U) */
+#    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 SELUXSINFO                                                         \
+        0x10000 /* selected for UNIX socket info;                              \
+                 * cleared in link_lfile() */
+#    define SELPTYINFO                                                         \
+        0x20000 /* selected for pseudoterminal info;                           \
+                 * cleared in link_lfile() */
+#    define SELNETSINFO                                                        \
+        0x40000 /* selected for INET socket info;                              \
+                 * cleared in link_lfile() */
+#    define SELPSXMQINFO                                                       \
+        0x80000 /* selected for POSIX MQ socket info;                          \
+    cleared in link_lfile() */
+#    define SELNETS6INFO                                                       \
+        0x100000 /* selected for INET6 socket info;                            \
+                  * cleared in link_lfile() */
+#    define SELEVTFDINFO                                                       \
+        0x200000 /* selected for evetnfd 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 */
+#    define SELFILE (SELFD | SELNFS | SELNLINK | SELNM) /* file selecters */
+#    define SELNW (SELNA | SELNET | SELUNX)             /* network selecters */
+
+/*
+ * Exit Status
+ */
+
+enum ExitStatus {
+    LSOF_EXIT_SUCCESS,
+    LSOF_EXIT_ERROR,
+};
+#    define LSOF_SEARCH_FAILURE                                                \
+        (FsearchErr ? LSOF_EXIT_ERROR : LSOF_EXIT_SUCCESS)
+
+/*
+ * Structure definitions
+ */
+
+#    if defined(HAS_AFS)
+struct afsnode { /* AFS pseudo-node structure */
+    dev_t dev;
+    unsigned char ino_st;   /* 1 if inode has a value */
+    unsigned char nlink_st; /* 1 if nlink has a value */
+    INODETYPE inode;
+    unsigned long size;
+    long nlink;
+};
+#    endif /* defined(HAS_AFS) */
+
+#    if defined(HAS_STD_CLONE)
+struct clone {
+    int dx;             /* index of device entry in Devtp[] */
+    struct clone *next; /* forward link */
+};
+extern struct clone *Clone;
+#    endif /* defined(HAS_STD_CLONE) */
+
+#    if defined(HASNLIST)
+struct drive_Nl { /* data to drive build_Nl() */
+    char *nn;     /* nickname for lookups */
+    char *knm;    /* kernel variable for name list */
+};
+extern struct drive_Nl Drive_Nl[]; /* defined in dstore.c */
+#    endif                         /* defined(HASNLIST) */
+
+/*
+ * Global storage definitions (including their structure definitions)
+ */
+
+typedef struct efsys_list {
+    char *path;              /* path to file system for which kernel
+                              * blocks are to be eliminated */
+    int pathl;               /* path length */
+    int rdlnk;               /* avoid readlink(2) if non-zero */
+    struct mounts *mp;       /* local mount table entry pointer */
+    struct efsys_list *next; /* next efsys_list entry pointer */
+} efsys_list_t;
+
+struct int_lst {
+    int i; /* integer argument */
+    int f; /* find state -- meaningful only if
+            * x == 0 */
+    int x; /* excluded state */
+};
+
+typedef struct lsof_rx { /* regular expression table entry */
+    char *exp;           /* original regular expression */
+    regex_t cx;          /* compiled expression */
+    int mc;              /* match count */
+} lsof_rx_t;
+
+#    if defined(HASFSTRUCT)
+struct pff_tab { /* print file flags table structure */
+    long val;    /* flag value */
+    char *nm;    /* name to print for flag */
+};
+#    endif /* defined(HASFSTRUCT) */
+
+struct seluid {
+    uid_t uid;          /* User ID */
+    char *lnm;          /* specified login name (NULL = none) */
+    unsigned char excl; /* excluded state */
+    unsigned char f;    /* selected User ID find state
+                         * (meaningful only if excl == 0) */
+};
+
+extern int CkPasswd;
+
+struct str_lst {
+    char *str;            /* string */
+    int len;              /* string length */
+    short f;              /* selected string find state */
+    short x;              /* exclusion (if non-zero) */
+    struct str_lst *next; /* next list entry */
+};
+
+typedef struct cntxlist {
+    char *cntx;            /* zone name */
+    int f;                 /* "find" flag (used only in CntxArg) */
+    struct cntxlist *next; /* next zone hash entry */
+} cntxlist_t;
+extern int CntxStatus;
+
+extern int DChelp;
+extern int ErrStat;
+extern uid_t Euid;
+extern int Fcntx;
+extern int Ffield;
+extern int Ffilesys;
+extern int Fhelp;
+extern int Fhost;
+
+#    if defined(HASNCACHE)
+extern int NcacheReload;
+#    endif /* defined(HASNCACHE) */
+
+extern int Fnlink;
+extern int Fport;
+
+#    if !defined(HASNORPC_H)
+extern int FportMap;
+#    endif /* !defined(HASNORPC_H) */
+
+extern int Fpgid;
+extern int Fppid;
+extern int FsearchErr;
+extern int Fhuman;
+extern int Fsv;
+extern int Ftcptpi;
+extern int Fterse;
+extern int Funix;
+extern int Futol;
+extern int Fverbose;
+
+extern int Fxover;
+extern int Fzone;
+
+struct fd_lst {
+    enum lsof_fd_type fd_type; /* file descriptor type;
+                                * range if LSOF_FD_NUMERIC */
+    int lo;                    /* range start (if nm NULL) */
+    int hi;                    /* range end (if nm NULL) */
+    struct fd_lst *next;
+};
+
+struct fieldsel {
+    char id;          /* field ID character */
+    unsigned char st; /* field status */
+    char *nm;         /* field name */
+    int *opt;         /* option variable address */
+    int ov;           /* value to OR with option variable */
+};
+extern struct fieldsel FieldSel[];
+
+extern int Hdr;
+
+enum IDType { PGID, PID };
+extern char *InodeFmt_d;
+extern char *InodeFmt_x;
+extern int LastPid;
+
+struct lfile {
+    enum lsof_file_access_mode access;
+    enum lsof_lock_mode lock;
+    unsigned char dev_def;   /* device number definition status */
+    unsigned char inp_ty;    /* inode/iproto type
+                              * 0: neither inode nor iproto
+                              * 1: print inode in decimal
+                              * 2: iproto contains string
+                              * 3: print inode in hex
+                              */
+    unsigned char is_com;    /* common stream status */
+    unsigned char is_nfs;    /* NFS file status */
+    unsigned char is_stream; /* stream device status */
+
+#    if defined(HASVXFS) && defined(HASVXFSDNLC)
+    unsigned char is_vxfs; /* VxFS file status */
+#    endif                 /* defined(HASVXFS) && defined(HASVXFSDNLC) */
+
+    unsigned char lmi_srch; /* local mount info search status:
+                             * 1 = printname() search required */
+
+#    if defined(HASMNTSTAT)
+    unsigned char mnt_stat; /* mount point stat(2) status */
+#    endif                  /* defined(HASMNTSTAT) */
+
+    unsigned char nlink_def; /* link count definition status */
+    unsigned char off_def;   /* offset definition status */
+
+#    if defined(HASEPTOPTS)
+    unsigned char chend; /* communication channel endpoint
+                          * file */
+    int eventfd_id;      /* evntfd id taken from
+                    /proc/$pid/fdinfo */
+#        if defined(HASPTYEPT)
+    int tty_index; /* pseudoterminal index of slave side
+                    * (if this is the master side) */
+#        endif     /* defined(HASPTYEPT) */
+#    endif         /* defined(HASEPTOPTS) */
+
+    unsigned char rdev_def; /* rdev definition status */
+    unsigned char sz_def;   /* size definition status */
+
+#    if defined(HASFSTRUCT)
+    unsigned char fsv; /* file struct value status */
+#    endif             /* defined(HASFSTRUCT) */
+
+    /* FD column */
+    enum lsof_fd_type fd_type;
+    int fd_num; /* stores fd number when fd_type is LSOF_FD_NUMERIC,
+                   stores raw number when fd_type is one of
+                   {LSOF_FD_LIBRARY_REF, LSOF_FD_MMAP_UNKNOWN,
+                   LSOF_FD_PREGION_UNKNOWN}, otherwise -1 */
+
+    char iproto[IPROTOL];
+    enum lsof_file_type type;
+    uint32_t unknown_file_type_number; /* store file type when type ==
+                                      LSOF_FILE_UNKNOWN_RAW */
+
+    unsigned int sf; /* select flags -- SEL* symbols */
+    int ch;          /* VMPC channel: -1 = none */
+    int ntype;       /* node type -- N_* value */
+    SZOFFTYPE off;
+    SZOFFTYPE sz;
+    dev_t dev;
+    dev_t rdev;
+    INODETYPE inode;
+    long nlink; /* link count */
+    char *dev_ch;
+    char *fsdir; /* file system directory */
+    char *fsdev; /* file system device */
+
+#    if defined(HASFSINO)
+    INODETYPE fs_ino; /* file system inode number */
+#    endif            /* defined HASFSINO) */
+
+    struct linaddr { /* local Internet address information */
+        int af;      /* address family: 0 for none; AF_INET;
+                      * or AF_INET6 */
+        int p;       /* port */
+        union {
+            struct in_addr a4; /* AF_INET Internet address */
+
+#    if defined(HASIPv6)
+            struct in6_addr a6; /* AF_INET6 Internet address */
+#    endif                      /* defined(HASIPv6) */
+
+        } ia;
+    } li[2];         /* li[0]: local
+                      * li[1]: foreign */
+    struct ltstate { /* local TCP/TPI state */
+        int type;    /* state type:
+                      *   -1 == none
+                      *    0 == TCP
+                      *    1 == TPI or socket (SS_*) */
+        union {
+            int i;           /* integer state */
+            unsigned int ui; /* unsigned integer state */
+        } state;
+
+#    if defined(HASSOOPT)
+        unsigned char pqlens; /* pqlen status: 0 = none */
+        unsigned char qlens;  /* qlen status:  0 = none */
+        unsigned char qlims;  /* qlim status:  0 = none */
+        unsigned char rbszs;  /* rbsz status:  0 = none */
+        unsigned char sbszs;  /* sbsz status:  0 = none */
+        int kai;              /* TCP keep-alive interval */
+        int ltm;              /* TCP linger time */
+        unsigned int opt;     /* socket options */
+        unsigned int pqlen;   /* partial connection queue length */
+        unsigned int qlen;    /* connection queue length */
+        unsigned int qlim;    /* connection queue limit */
+        unsigned long rbsz;   /* receive buffer size */
+        unsigned long sbsz;   /* send buffer size */
+#    endif                    /* defined(HASSOOPT) */
+
+#    if defined(HASSOSTATE)
+        unsigned int ss; /* socket state */
+#        if defined(HASSBSTATE)
+        unsigned int sbs_rcv; /* receive socket buffer state */
+        unsigned int sbs_snd; /* send socket buffer state */
+#        endif                /* defined(HASSBSTATE) */
+#    endif                    /* defined(HASSOSTATE) */
+
+#    if defined(HASTCPOPT)
+        unsigned int topt;  /* TCP options */
+        unsigned char msss; /* mss status: 0 = none */
+        unsigned long mss;  /* TCP maximum segment size */
+#    endif                  /* defined(HASTCPOPT) */
+
+#    if defined(HASTCPTPIQ)
+        unsigned long rq;  /* receive queue length */
+        unsigned long sq;  /* send queue length */
+        unsigned char rqs; /* rq status: 0 = none */
+        unsigned char sqs; /* sq status: 0 = none */
+#    endif                 /* defined(HASTCPTPIQ) */
+
+#    if defined(HASTCPTPIW)
+        unsigned char rws; /* rw status: 0 = none */
+        unsigned char wws; /* ww status: 0 = none */
+        unsigned long rw;  /* read window size */
+        unsigned long ww;  /* write window size */
+#    endif                 /* defined(HASTCPTPIW) */
+
+    } lts;
+    char *nm;
+    char *nma; /* NAME column addition */
+
+#    if defined(HASNCACHE) && HASNCACHE < 2
+    KA_T na; /* file structure's node address */
+#    endif   /* defined(HASNCACHE) && HASNCACHE<2 */
+
+#    if defined(HASNCACHE) && defined(HASNCVPID)
+    unsigned long id; /* capability ID */
+#    endif            /* defined(HASNCACHE) && defined(HASNCVPID) */
+
+#    if defined(HASLFILEADD)
+    HASLFILEADD
+#    endif /* defined(HASLFILEADD) */
+
+#    if defined(HASFSTRUCT)
+    KA_T fsa; /* file structure address */
+    long fct; /* file structure's f_count */
+    long ffg; /* file structure's f_flag */
+    long pof; /* process open-file flags */
+    KA_T fna; /* file structure node address */
+#    endif    /* defined(HASFSTRUCT) */
+
+    struct lfile *next;
+};
+
+struct lproc {
+    char *cmd; /* command name */
+
+#    if defined(HASSELINUX)
+    char *cntx; /* security context */
+#    endif      /* defined(HASSELINUX) */
+
+    short sf;  /* select flags -- SEL* symbols */
+    short pss; /* state: 0 = not selected
+                *	  1 = wholly selected
+                *	  2 = partially selected */
+#    if defined(HASEPTOPTS)
+    short ept; /* end point status -- EPT_* values */
+#    endif     /* defined(HASEPTOPTS) */
+
+    int pid; /* process ID */
+
+#    if defined(HASTASKS)
+    int tid;    /* task ID */
+    char *tcmd; /* task command name */
+#    endif      /* HASTASKS */
+
+    int pgid;  /* process group ID */
+    int ppid;  /* parent process ID */
+    uid_t uid; /* user ID */
+
+#    if defined(HASZONES)
+    char *zn; /* zone name */
+#    endif    /* defined(HASZONES) */
+
+    struct lfile *file; /* open files of process */
+};
+
+extern char *Memory;
+
+#    if defined(HASPROCFS)
+extern struct mounts *Mtprocfs;
+#    endif
+
+#    if defined(HASNLIST)
+#        if !defined(NLIST_TYPE)
+#            define NLIST_TYPE nlist
+#        endif /* !defined(NLIST_TYPE) */
+extern struct NLIST_TYPE *Nl;
+extern int Nll;
+#    endif /* defined(HASNLIST) */
+extern char *Nmlst;
+
+struct nwad {
+    char *arg;                    /* argument */
+    char *proto;                  /* protocol */
+    int af;                       /* address family -- e.g.,
+                                   * AF_INET, AF_INET6 */
+    unsigned char a[MAX_AF_ADDR]; /* address */
+    int sport;                    /* starting port */
+    int eport;                    /* ending port */
+    int f;                        /* find state */
+    struct nwad *next;            /* forward link */
+};
+extern struct nwad *Nwad;
+
+extern int OffDecDig;
+
+#    if defined(HASFSTRUCT)
+extern struct pff_tab Pff_tab[]; /* file flags table */
+extern struct pff_tab Pof_tab[]; /* process open file flags table */
+#    endif                       /* defined(HASFSTRUCT) */
+
+#    if defined(HASPROCFS)
+struct procfsid {
+    pid_t pid;       /* search PID */
+    char *nm;        /* search name */
+    unsigned char f; /* match found if == 1 */
+
+#        if defined(HASPINODEN)
+    INODETYPE inode; /* search inode number */
+#        endif       /* defined(HASPINODEN) */
+
+    struct procfsid *next; /* forward link */
+};
+
+extern int Procfind;
+extern struct procfsid *Procfsid;
+extern int Procsrch;
+#    endif /* defined(HASPROCFS) */
+
+extern int PrPass;
+extern int RptMaxCount;
+extern char *SzOffFmt_0t;
+extern char *SzOffFmt_d;
+extern char *SzOffFmt_dv;
+extern char *SzOffFmt_x;
+extern int TaskCmdLim;
+extern int TaskPrtCmd;
+extern int TaskPrtTid;
+extern int TcpStAlloc;
+extern unsigned char *TcpStI;
+extern int TcpStIn;
+extern int TcpStOff;
+extern unsigned char *TcpStX;
+extern int TcpStXn;
+extern int TcpNstates;
+extern char **TcpSt;
+extern char Terminator;
+extern int UdpStAlloc;
+extern unsigned char *UdpStI;
+extern int UdpStIn;
+extern int UdpStOff;
+extern unsigned char *UdpStX;
+extern int UdpStXn;
+extern int UdpNstates;
+extern char **UdpSt;
+
+struct hsfile {
+    struct sfile *s;     /* the Sfile table address */
+    struct hsfile *next; /* the next hash bucket entry */
+};
+
+typedef struct znhash {
+    char *zn;            /* zone name */
+    int f;               /* "find" flag (used only in ZoneArg) */
+    struct znhash *next; /* next zone hash entry */
+} znhash_t;
+
+struct lsof_context {
+    /** Parameters */
+    /** Linked list of files to search */
+    struct sfile *select_files;
+
+    /* file systems for which kernel blocks are
+     * to be eliminated */
+    efsys_list_t *elim_fs_list;
+
+    /* User IDs to include or exclude */
+    struct seluid *sel_uid;
+    /* -u option count */
+    int sel_uid_size;
+    /* capacity of sel_uid */
+    int sel_uid_cap;
+    /* -u option count of UIDs excluded */
+    int num_uid_excluded;
+    /* -u option count of UIDs included */
+    int num_uid_included;
+
+    /* process group IDs to search for */
+    struct int_lst *sel_pgid;
+    int sel_pgid_size;     /* -g option count */
+    int sel_pgid_cap;      /* capacity of sel_pgid */
+    int sel_pgid_incl_num; /* -g option inclusion count */
+    int sel_pgid_excl_num; /* -g option exclusion count */
+
+    /* Process IDs to search for */
+    struct int_lst *sel_pid;
+    int sel_pid_size;  /* -p option count */
+    int num_unsel_pid; /* number of unselected PIDs (starts at sel_pid_size) for
+                          optimization in examine_lproc() */
+    int sel_pid_cap;   /* capacity of sel_pid */
+    int sel_pid_incl_num; /* -p option inclusion count */
+    int sel_pid_excl_num; /* -p option exclusion count */
+
+    /* Whether all processes are selected */
+    int sel_all_proc;
+
+    /* command names selected with -c */
+    struct str_lst *sel_cmds;
+    int sel_cmd_incl; /* number of command name inclusions selected with -c */
+    int sel_cmd_excl; /* number of command name exclusions selected with -c */
+
+    /* command regular expression table for -c option */
+    lsof_rx_t *cmd_regex;
+    int cmd_regex_size; /* number of cmd_regex[] entries */
+    int cmd_regex_cap;  /* capacity of cmd_regex[] */
+
+    /* select by network address */
+    struct nwad *sel_net_addr;
+
+    /* security context arguments supplied with -Z */
+    cntxlist_t *sel_selinux_context;
+
+    /* device cache paths, indexed by DCpathX
+     * when it's >= 0 */
+    char *dev_cache_paths[4];
+    int dev_cache_path_index;    /* device cache path index:
+                                  * -1 = path not defined
+                                  *  0 = defined via -D
+                                  *  1 = defined via HASENVDC
+                                  *  2 = defined via HASSYSDC
+                                  *  3 = defined via HASPERSDC and
+                                  *      HASPERSDCPATH */
+    char *dev_cache_path_arg;    /* device cache path from -D[b|r|u]<path> */
+    unsigned dev_cache_checksum; /* device cache file checksum */
+    int dev_cache_fd;            /* device cache file descriptor */
+    FILE *dev_cache_fp;          /* stream pointer for DCfd */
+    int dev_cache_rebuilt;       /* an unsafe device cache file has been
+                                  * rebuilt */
+    int dev_cache_state;         /* device cache state:
+                                  * 0 = ignore (-Di)
+                                  * 1 = build (-Db[path])
+                                  * 2 = read; don't rebuild (-Dr[path])
+                                  * 3 = update; read and rebuild if
+                                  *     necessary (-Du[path])
+                                  */
+    int dev_cache_unsafe;        /* device cache file is potentially unsafe,
+                                  * (The [cm]time check failed.) */
+
+#    if defined(HASNLIST)
+    /* kernel name list */
+    struct NLIST_TYPE *name_list;
+    int name_list_size;
+#    endif                /* defined(HASNLIST) */
+    char *name_list_path; /* namelist file path */
+    char *core_file_path; /* core file path */
+
+#    if defined(HASPROCFS)
+    /* /proc mount entry */
+    struct mounts *procfs_mount;
+    int procfs_found; /* 1 when searching for an proc file system
+                       * file and one was found */
+    /* proc file system PID search table */
+    struct procfsid *procfs_table;
+    /* 1 if searching for any proc file system
+     * file */
+    int procfs_search;
+#    endif /* defined(HASPROCFS) */
+
+    /* name cache */
+    int name_cache_enable; /* -C option status */
+
+    /* local mount info */
+    struct mounts *local_mount_info;
+    int local_mount_info_valid;
+
+    /** hashSfile() buckets */
+    /* hash by file (dev,ino) buckets */
+    struct hsfile *sfile_hash_file_dev_inode;
+    int sfile_hash_file_dev_inode_count;
+    /* hash by file raw device buckets */
+    struct hsfile *sfile_hash_file_raw_device;
+    int sfile_hash_file_raw_device_count;
+    /* hash by file system buckets */
+    struct hsfile *sfile_hash_file_system;
+    int sfile_hash_file_system_count;
+    /* hash by name buckets */
+    struct hsfile *sfile_hash_name;
+    int sfile_hash_name_count;
+    /* hash by clone buckets */
+    struct hsfile *sfile_hash_clone;
+    int sfile_hash_clone_count;
+
+    /* zone arguments supplied with -z */
+    znhash_t **sel_zone;
+
+    /* command name limit */
+    int cmd_limit;
+
+    /** When frozen, parameters must not be changed */
+    uint8_t frozen;
+
+    /* node type (see N_* symbols) */
+    int node_type;
+
+    /* device table pointer */
+    struct l_dev *dev_table;
+    int dev_table_size; /* number of entries in dev_table[] */
+    /* pointer to dev_table[] pointers, sorted
+     * by device */
+    struct l_dev **dev_table_sorted;
+
+    /* block device table pointer */
+    struct l_dev *block_dev_table;
+    int block_dev_table_size; /* number of entries in block_dev_table[] */
+    /* pointer to BDevtp[] pointers, sorted
+     * by device */
+    struct l_dev **block_dev_table_sorted;
+
+    /* selection flags -- see SEL* macros */
+    int sel_flags;
+    /* SELPROC flags, modified by IgnTasks */
+    int sel_proc;
+    /* SELALL flags, modified by IgnTasks */
+    int sel_all;
+    /* select only Internet socket files */
+    int sel_inet;
+
+    /* -N option status: 0==none, 1==find all,
+     * 2==some found*/
+    int sel_nfs;
+
+    /* -K option value */
+    int sel_task;
+
+    /* -a option status */
+    int logic_and;
+
+    /* -b option status */
+    int avoid_blocking;
+
+    /* -O option status */
+    int avoid_forking;
+
+    /* -X option status */
+    int x_opt;
+
+    /* -E option status:
+     * 0==none,
+     * 1==info,
+     * 2==info+files */
+    int endpoint_status;
+
+    /* ignore tasks when non-zero */
+    int ign_tasks;
+
+    /* maximum file descriptors to close */
+    int max_fd;
+
+    /* file descriptors selected with -d */
+    struct fd_lst *fd_list;
+    /* fd_list[] type:
+     * -1 == none
+     * 0 == include
+     * 1 == exclude */
+    int fd_list_ty;
+
+    /* mount supplement state:
+     * 0 == none
+     * 1 == create
+     * 2 == read */
+    int mnt_sup_state;
+    /* mount supplement path -- if MntSup == 2 */
+    char *mnt_sup_path;
+
+    /* report nlink values below this number
+     * (0 = report all nlink values) */
+    long nlink;
+
+    /* Readlink() and stat() timeout (seconds) */
+    int time_limit;
+
+    int my_pid;      /* lsof's process ID */
+    uid_t my_uid;    /* real UID of this lsof process */
+    gid_t my_gid;    /* real GID of this lsof process */
+    int setgid;      /* setgid state */
+    int setuid_root; /* setuid-root state */
+
+    /* directory stack */
+    char **dir_stack;    /* the directory stack */
+    int dir_stack_index; /* dir_stack[] index */
+    int dir_stack_size;  /* dir_stack[] entries allocated */
+
+    /* allocated (possibly unused) entries in TCP
+     * state tables */
+    int tcp_state_alloc;
+    /* included TCP states */
+    unsigned char *tcp_state_incl;
+    int tcp_state_incl_num; /* number of entries in tcp_state_incl[] */
+    int tcp_state_off;      /* offset for TCP state number to adjust
+                             * negative numbers to an index into tcp_states[],
+                             * tcp_state_incl[] and tcp_state_excl[] */
+    /* excluded TCP states */
+    unsigned char *tcp_state_excl;
+    int tcp_state_excl_num; /* number of entries in tcp_state_excl[] */
+    int tcp_num_states;     /* number of TCP states -- either in
+                             * tcpstates[] or tcp_states[] */
+    char **tcp_states;      /* local TCP state names, indexed by system
+                             * state value */
+
+    /* allocated (possibly unused) entries in UDP
+     * state tables */
+    int udp_state_alloc;
+    /* included UDP states */
+    unsigned char *udp_state_incl;
+    int udp_state_incl_num; /* number of entries in udp_state_incl[] */
+    int udp_state_off;      /* offset for UDP state number to adjust
+                             * negative numbers to an index into udp_states[],
+                             * udp_state_incl[] and udp_state_excl[] */
+    unsigned char *udp_state_excl;
+    /* excluded UDP states */
+    int udp_state_excl_num; /* number of entries in udp_state_excl[] */
+    int udp_num_states;     /* number of UDP states in udp_states[] */
+    char **udp_states;      /* local UDP state names, indexed by system
+                             * state number */
+
+    int unix_socket; /* -U option status */
+
+    dev_t dev_dev; /* device number of /dev or its equivalent */
+
+    int net;      /* -i option status: 0==none
+                   *                   1==find all
+                   *                   2==some found */
+    int net_type; /* Fnet type request: AF_UNSPEC==all
+                   *                    AF_INET==IPv4
+                   *                    AF_INET6==IPv6 */
+
+    /* Fsv was set by +f */
+    int fsv_set_f;
+
+    /* hex format status for FSV_FG */
+    int fsv_hex;
+
+    /* repeat time -- set by -r */
+    int repeat_time;
+
+    /* -o option status */
+    int show_offset;
+
+    /* -s option status */
+    int show_size;
+
+    /** Temporary */
+    /* name characters for printing */
+    char *name_buf;
+    /* sizeof(name_buf) */
+    size_t name_buf_size;
+
+    /** Output */
+    /** Pointer to current process */
+    struct lproc *cur_proc;
+    /** Pointer to all processes */
+    struct lproc *procs;
+    /** Length and capacity of `procs` */
+    size_t procs_size;
+    size_t procs_cap;
+
+    /** Pointer to current file */
+    struct lfile *cur_file;
+    /** Pointer to previous file */
+    struct lfile *prev_file;
+
+    /** Warnings and errors */
+    FILE *err;
+    char *program_name;
+    int warn; /* 1=suppress warnings */
+
+    /** dialect specific fields, see dlsof.h */
+    struct lsof_context_dialect dialect;
+};
+
+/** Convenience macros to access context */
+/* Local process */
+#    define Lp (ctx->cur_proc)
+/* All local processes */
+#    define Lproc (ctx->procs)
+/* Local file */
+#    define Lf (ctx->cur_file)
+/* Previous local file */
+#    define Plf (ctx->prev_file)
+/* Length of local processes */
+#    define Nlproc (ctx->procs_size)
+/* Error output */
+#    define Pn (ctx->program_name)
+/* Suppress warnings */
+#    define Fwarn (ctx->warn)
+/* Name buffer */
+#    define Namech (ctx->name_buf)
+#    define Namechl (ctx->name_buf_size)
+/* Selection flags */
+#    define SelAll (ctx->sel_all)
+#    define Selflags (ctx->sel_flags)
+#    define SelProc (ctx->sel_proc)
+#    define Selinet (ctx->sel_inet)
+/* dev_t of /dev */
+#    define DevDev (ctx->dev_dev)
+/* TCP states */
+#    define TcpNstates (ctx->tcp_num_states)
+#    define TcpSt (ctx->tcp_states)
+#    define TcpStI (ctx->tcp_state_incl)
+#    define TcpStIn (ctx->tcp_state_incl_num)
+#    define TcpStX (ctx->tcp_state_excl)
+#    define TcpStXn (ctx->tcp_state_excl_num)
+#    define TcpStOff (ctx->tcp_state_off)
+#    define TcpStAlloc (ctx->tcp_state_alloc)
+/* UDP states */
+#    define UdpNstates (ctx->udp_num_states)
+#    define UdpSt (ctx->udp_states)
+#    define UdpStI (ctx->udp_state_incl)
+#    define UdpStIn (ctx->udp_state_incl_num)
+#    define UdpStX (ctx->udp_state_excl)
+#    define UdpStXn (ctx->udp_state_excl_num)
+#    define UdpStOff (ctx->udp_state_off)
+#    define UdpStAlloc (ctx->udp_state_alloc)
+/* select unix socket */
+#    define Funix (ctx->unix_socket)
+/* select inet socket */
+#    define Fnet (ctx->net)
+#    define FnetTy (ctx->net_type)
+/* select nfs files */
+#    define Fnfs (ctx->sel_nfs)
+/* -a option */
+#    define Fand (ctx->logic_and)
+/* -x option */
+#    define Fxopt (ctx->x_opt)
+/* avoid blocking */
+#    define Fblock (ctx->avoid_blocking)
+/* avoid forking overhead */
+#    define Fovhd (ctx->avoid_forking)
+/* endpoint status */
+#    define FeptE (ctx->endpoint_status)
+/* select tasks */
+#    define Ftask (ctx->sel_task)
+/* fd list */
+#    define Fdl (ctx->fd_list)
+#    define FdlTy (ctx->fd_list_ty)
+/* ignore tasks */
+#    define IgnTasks (ctx->ign_tasks)
+/* maximum fd number */
+#    define MaxFd (ctx->max_fd)
+/* mount supplement */
+#    define MntSup (ctx->mnt_sup_state)
+#    define MntSupP (ctx->mnt_sup_path)
+/* nlink limit */
+#    define Nlink (ctx->nlink)
+/* Time limit */
+#    define TmLimit (ctx->time_limit)
+/* number of unselected PIDs */
+#    define Npuns (ctx->num_unsel_pid)
+/* pid/uid/gid of current process */
+#    define Mypid (ctx->my_pid)
+#    define Myuid (ctx->my_uid)
+#    define Mygid (ctx->my_gid)
+/* setgid state */
+#    define Setgid (ctx->setgid)
+/* setuid-root state */
+#    define Setuidroot (ctx->setuid_root)
+/* directory stack */
+#    define Dstk (ctx->dir_stack)
+#    define Dstkx (ctx->dir_stack_index)
+#    define Dstkn (ctx->dir_stack_size)
+/* selection files */
+#    define Sfile (ctx->select_files)
+/* fs to eliminate blocking syscalls */
+#    define Efsysl (ctx->elim_fs_list)
+/* select uid */
+#    define Suid (ctx->sel_uid)
+#    define Nuid (ctx->sel_uid_size)
+#    define Nuidincl (ctx->num_uid_included)
+#    define Nuidexcl (ctx->num_uid_excluded)
+#    define Mxuid (ctx->sel_uid_cap)
+/* select pid */
+#    define Spid (ctx->sel_pid)
+#    define Npid (ctx->sel_pid_size)
+#    define Npidi (ctx->sel_pid_incl_num)
+#    define Npidx (ctx->sel_pid_excl_num)
+#    define Mxpid (ctx->sel_pid_cap)
+/* select pgid */
+#    define Spgid (ctx->sel_pgid)
+#    define Npgid (ctx->sel_pgid_size)
+#    define Npgidi (ctx->sel_pgid_incl_num)
+#    define Npgidx (ctx->sel_pgid_excl_num)
+#    define Mxpgid (ctx->sel_pgid_cap)
+/* select all procs */
+#    define AllProc (ctx->sel_all_proc)
+/* select command */
+#    define Cmdl (ctx->sel_cmds)
+#    define Cmdni (ctx->sel_cmd_incl)
+#    define Cmdnx (ctx->sel_cmd_excl)
+#    define CmdRx (ctx->cmd_regex)
+#    define NCmdRxA (ctx->cmd_regex_cap)
+#    define NCmdRxU (ctx->cmd_regex_size)
+/* select by network address */
+#    define Nwad (ctx->sel_net_addr)
+/* device table pointer */
+#    define Devtp (ctx->dev_table)
+#    define Ndev (ctx->dev_table_size)
+#    define Sdev (ctx->dev_table_sorted)
+/* block device table */
+#    define BDevtp (ctx->block_dev_table)
+#    define BNdev (ctx->block_dev_table_size)
+#    define BSdev (ctx->block_dev_table_sorted)
+/* select selinux context */
+#    define CntxArg (ctx->sel_selinux_context)
+/* device cache */
+#    define DCpath (ctx->dev_cache_paths)
+#    define DCpathArg (ctx->dev_cache_path_arg)
+#    define DCpathX (ctx->dev_cache_path_index)
+#    define DCcksum (ctx->dev_cache_checksum)
+#    define DCfd (ctx->dev_cache_fd)
+#    define DCfs (ctx->dev_cache_fp)
+#    define DCrebuilt (ctx->dev_cache_rebuilt)
+#    define DCstate (ctx->dev_cache_state)
+#    define DCunsafe (ctx->dev_cache_unsafe)
+/* name list */
+#    define Nl (ctx->name_list)
+#    define Nll (ctx->name_list_size)
+#    define Nmlst (ctx->name_list_path)
+#    define Memory (ctx->core_file_path)
+/* procfs */
+#    define Mtprocfs (ctx->procfs_mount)
+#    define Procsrch (ctx->procfs_search)
+#    define Procfsid (ctx->procfs_table)
+#    define Procfind (ctx->procfs_found)
+/* name cache */
+#    define Fncache (ctx->name_cache_enable)
+/* local mount info */
+#    define Lmi (ctx->local_mount_info)
+#    define Lmist (ctx->local_mount_info_valid)
+/* hash buckets in hashSfile() */
+#    define HbyFdi (ctx->sfile_hash_file_dev_inode)
+#    define HbyFdiCt (ctx->sfile_hash_file_dev_inode_count)
+#    define HbyFrd (ctx->sfile_hash_file_raw_device)
+#    define HbyFrdCt (ctx->sfile_hash_file_raw_device_count)
+#    define HbyFsd (ctx->sfile_hash_file_system)
+#    define HbyFsdCt (ctx->sfile_hash_file_system_count)
+#    define HbyNm (ctx->sfile_hash_name)
+#    define HbyNmCt (ctx->sfile_hash_name_count)
+#    define HbyCd (ctx->sfile_hash_clone)
+#    define HbyCdCt (ctx->sfile_hash_clone_count)
+/* solaris zone */
+#    define ZoneArg (ctx->sel_zone)
+/* command name limit */
+#    define CmdLim (ctx->cmd_limit)
+/* node type */
+#    define Ntype (ctx->node_type)
+/* Fsv was set by +f */
+#    define FsvByf (ctx->fsv_set_f)
+/* hex format status for FSV_FG */
+#    define FsvFlagX (ctx->fsv_hex)
+/* repeat time */
+#    define RptTm (ctx->repeat_time)
+/* -o option status */
+#    define Foffset (ctx->show_offset)
+/* -s option status */
+#    define Fsize (ctx->show_size)
+
+/* Utility macro to free if non-null and set the pointer to null */
+#    define CLEAN(ptr)                                                         \
+        do {                                                                   \
+            free(ptr);                                                         \
+            ptr = NULL;                                                        \
+        } while (0);
+
+#    include "proto.h"
+#    include "dproto.h"
+
+#endif /* COMMON_H */
diff --git a/lib/cvfs.c b/lib/cvfs.c
index 28e08a5..59d01f5 100644
--- a/lib/cvfs.c
+++ b/lib/cvfs.c
@@ -2,7 +2,6 @@
  * cvfs.c -- completevfs() function for lsof library
  */
 
-
 /*
  * Copyright 1997 Purdue Research Foundation, West Lafayette, Indiana
  * 47907.  All rights reserved.
@@ -29,7 +28,6 @@
  * 4. This notice may not be removed or altered.
  */
 
-
 /*
  * The caller must define CVFS_DEVSAVE to have the device number moved
  * from the mounts entry to the local vfs structure.
@@ -41,69 +39,60 @@
  * mounts entry to the local vfs structure.
  */
 
+#include "common.h"
+#include "machine.h"
 
-#include "../machine.h"
-
-#if	defined(USE_LIB_COMPLETEVFS)
-
-# if	!defined(lint)
-static char copyright[] =
-"@(#) Copyright 1997 Purdue Research Foundation.\nAll rights reserved.\n";
-# endif	/* !defined(lint) */
-
-#include	"../lsof.h"
-
+#if defined(USE_LIB_COMPLETEVFS)
 
 /*
  * completevfs() - complete local vfs structure
  */
 
-void
-completevfs(vfs, dev)
-	struct l_vfs *vfs;		/* local vfs structure pointer */
-	dev_t *dev;			/* device */
+void completevfs(struct lsof_context *ctx, /* context */
+                 struct l_vfs *vfs,        /* local vfs structure pointer */
+                 dev_t *dev)               /* device */
 {
-	struct mounts *mp;
-/*
- * If only Internet socket files are selected, don't bother completing the
- * local vfs structure.
- */
-	if (Selinet)
-	    return;
-/*
- * Search for a match on device number.
- */
-	for (mp = readmnt(); mp; mp = mp->next) {
-	    if (mp->dev == *dev) {
-
-# if	defined(CVFS_DEVSAVE)
-		vfs->dev = mp->dev;
-# endif	/* defined(CVFS_DEVSAVE) */
-
-# if	defined(CVFS_NLKSAVE)
-		vfs->nlink = mp->nlink;
-# endif	/* defined(CVFS_NLKSAVE) */
-
-# if	defined(CVFS_SZSAVE)
-		vfs->size = mp->size;
-# endif	/* defined(CVFS_SZSAVE) */
-
-		vfs->dir = mp->dir;
-		vfs->fsname = mp->fsname;
-
-# if	defined(HASFSINO)
-		vfs->fs_ino = mp->inode;
-# endif	/* defined(HASFSINO) */
-
-# if	defined(HASMNTSTAT)
-		vfs->mnt_stat = mp->stat;
-# endif	/* defined(HASMNTSTAT) */
-
-
-		return;
-	    }
-	}
+    struct mounts *mp;
+    /*
+     * If only Internet socket files are selected, don't bother completing the
+     * local vfs structure.
+     */
+    if (Selinet)
+        return;
+    /*
+     * Search for a match on device number.
+     */
+    for (mp = readmnt(ctx); mp; mp = mp->next) {
+        if (mp->dev == *dev) {
+
+#    if defined(CVFS_DEVSAVE)
+            vfs->dev = mp->dev;
+#    endif /* defined(CVFS_DEVSAVE) */
+
+#    if defined(CVFS_NLKSAVE)
+            vfs->nlink = mp->nlink;
+#    endif /* defined(CVFS_NLKSAVE) */
+
+#    if defined(CVFS_SZSAVE)
+            vfs->size = mp->size;
+#    endif /* defined(CVFS_SZSAVE) */
+
+            vfs->dir = mp->dir;
+            vfs->fsname = mp->fsname;
+
+#    if defined(HASFSINO)
+            vfs->fs_ino = mp->inode;
+#    endif /* defined(HASFSINO) */
+
+#    if defined(HASMNTSTAT)
+            vfs->mnt_stat = mp->stat;
+#    endif /* defined(HASMNTSTAT) */
+
+            return;
+        }
+    }
 }
-#else	/* !defined(USE_LIB_COMPLETEVFS) */
-char cvfs_d1[] = "d"; char *cvfs_d2 = cvfs_d1;
-#endif	/* defined(USE_LIB_COMPLETEVFS) */
+#else  /* !defined(USE_LIB_COMPLETEVFS) */
+char cvfs_d1[] = "d";
+char *cvfs_d2 = cvfs_d1;
+#endif /* defined(USE_LIB_COMPLETEVFS) */
diff --git a/lib/dialects/aix/Makefile b/lib/dialects/aix/Makefile
new file mode 100644
index 0000000..980e78f
--- /dev/null
+++ b/lib/dialects/aix/Makefile
@@ -0,0 +1,168 @@
+
+# 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} -Iinclude -Ilib -Isrc -I.
+CFLAGS=	${CDEFS} ${INCL} ${DEBUG}
+
+GRP=
+
+HDR=    lib/common.h include/lsof_fields.h dlsof.h machine.h lib/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 print.c ptti.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 print.o ptti.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_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/lib/dialects/aix/Mksrc b/lib/dialects/aix/Mksrc
new file mode 100755
index 0000000..edf726c
--- /dev/null
+++ b/lib/dialects/aix/Mksrc
@@ -0,0 +1,34 @@
+#!/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 $
+
+mksrc() {
+  for i in $L
+  do
+    rm -f $i
+    $LSOF_MKC $D/$i $i
+    echo "$LSOF_MKC $D/$i $i"
+  done
+}
+
+
+D=lib/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"
+
+mksrc
+
+D=src
+L="arg.c main.c print.c ptti.c store.c usage.c util.c"
+
+mksrc
+
diff --git a/lib/dialects/aix/aix5/README b/lib/dialects/aix/aix5/README
new file mode 100644
index 0000000..28adc0c
--- /dev/null
+++ b/lib/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/lib/dialects/aix/aix5/j2/j2_lock.h b/lib/dialects/aix/aix5/j2/j2_lock.h
new file mode 100644
index 0000000..b97102b
--- /dev/null
+++ b/lib/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/lib/dialects/aix/aix5/j2/private_j2_snapshot.h b/lib/dialects/aix/aix5/j2/private_j2_snapshot.h
new file mode 100644
index 0000000..f8b3ad9
--- /dev/null
+++ b/lib/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/lib/dialects/aix/ddev.c b/lib/dialects/aix/ddev.c
new file mode 100644
index 0000000..e110d6d
--- /dev/null
+++ b/lib/dialects/aix/ddev.c
@@ -0,0 +1,686 @@
+/*
+ * 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";
+#endif
+
+#include "common.h"
+
+/*
+ * Local definitions
+ */
+
+#define LIKE_BLK_SPEC "like block special"
+#define LIKE_CHR_SPEC "like character special"
+
+/*
+ * Local function prototypes
+ */
+
+static int rmdupdev(struct lsof_context *ctx, 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 lsof_context *ctx) {
+    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(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(struct lsof_context *ctx, /* context */
+                 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(ctx, 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(ctx, &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);
+            Error(ctx);
+        }
+        (void)snpf(cp, len + 1, "(%s %s)", ttl, dp->name);
+        (void)add_nma(ctx, cp, len);
+        (void)free((MALLOC_P *)cp);
+        return (0);
+    }
+    return (0);
+}
+
+/*
+ * readdev() - read device names, modes and types
+ */
+
+void readdev(struct lsof_context *ctx, /* context */
+             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(ctx)) == 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(ctx, "/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);
+            Error(ctx);
+        }
+        (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);
+                Error(ctx);
+            }
+
+#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(ctx, 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);
+                        Error(ctx);
+                    }
+                }
+                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);
+                    Error(ctx);
+                }
+                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);
+                        Error(ctx);
+                    }
+                    if (!(c->cd.name = mkstrcpy(fp, (MALLOC_S)NULL))) {
+                        (void)fprintf(stderr,
+                                      "%s: no space for clone name: ", Pn);
+                        safestrprt(fp, stderr, 1);
+                        Error(ctx);
+                    }
+                    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);
+                        Error(ctx);
+                    }
+                }
+                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);
+            Error(ctx);
+        }
+        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(ctx, &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);
+            Error(ctx);
+        }
+        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(ctx, &Sdev, Ndev, "char");
+    } else {
+        (void)fprintf(stderr, "%s: no character devices found\n", Pn);
+        Error(ctx);
+    }
+
+#if defined(HASDCACHE)
+    /*
+     * Write device cache file, as required.
+     */
+    if (DCstate == 1 || (DCstate == 3 && dcrd))
+        write_dcache(ctx);
+#endif /* defined(HASDCACHE) */
+}
+
+#if defined(HASDCACHE)
+/*
+ * rereaddev() - reread device names, modes and types
+ */
+
+void rereaddev(struct lsof_context *ctx) {
+    (void)clr_devtab(ctx);
+
+#    if defined(DCACHE_CLR)
+    (void)DCACHE_CLR(ctx);
+#    endif /* defined(DCACHE_CLR) */
+
+    readdev(ctx, 1);
+    DCunsafe = 0;
+}
+#endif /* defined(HASDCACHE) */
+
+/*
+ * rmdupdev() - remove duplicate (major/minor/inode) devices
+ */
+
+static int rmdupdev(struct lsof_context *ctx, /* context */
+                    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);
+        Error(ctx);
+    }
+    return (j);
+}
+
+#if defined(HASDCACHE) && AIXV >= 4140
+/*
+ * rw_clone_sect() - read/write the device cache file clone section
+ */
+
+int rw_clone_sect(struct lsof_context *ctx, /* context */
+                  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);
+                Error(ctx);
+            }
+            /*
+             * 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);
+                Error(ctx);
+            }
+            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);
+    Error(ctx);
+}
+#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(struct lsof_context *ctx, /* context */
+            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(ctx);
+        return (0);
+    }
+    dp->v = 1;
+    return (1);
+}
+#endif /* defined(HASDCACHE) */
diff --git a/lib/dialects/aix/dfile.c b/lib/dialects/aix/dfile.c
new file mode 100644
index 0000000..cc70cc9
--- /dev/null
+++ b/lib/dialects/aix/dfile.c
@@ -0,0 +1,523 @@
+/*
+ * 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";
+#endif
+
+#include "common.h"
+
+/*
+ * Local structures
+ */
+
+/*
+ * Local static variables
+ */
+
+static struct hsfile *HbyMPC = /* hash by MPC file buckets */
+    (struct hsfile *)NULL;
+static int HbyMPCCt = 0; /* HbyMPC 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(struct lsof_context *ctx) {
+    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);
+        Error(ctx);
+    }
+    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);
+        Error(ctx);
+    }
+    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);
+        Error(ctx);
+    }
+    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);
+        Error(ctx);
+    }
+    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);
+        Error(ctx);
+    }
+    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);
+                    Error(ctx);
+                }
+                sn->s = s;
+                sn->next = sh->next;
+                sh->next = sn;
+            }
+        }
+    }
+}
+
+/*
+ * is_file_named() - is file named?
+ */
+
+int is_file_named(struct lsof_context *ctx, /* context */
+                  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(ctx, 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(ctx, &sz);
+                (void)snpf(ep, sz, "/%d", ch);
+            }
+            if (s->devnm) {
+                ep = endnm(ctx, &sz);
+                (void)snpf(ep, sz, " (%s)", s->devnm);
+            }
+        }
+        s->f = 1;
+        return (1);
+    }
+    return (0);
+}
+
+/*
+ * print_dev() - print device
+ */
+
+char *print_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(struct lsof_context *ctx, /* context */
+                      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);
+        Error(ctx);
+    }
+    vp->dir = (char *)NULL;
+    vp->fsname = (char *)NULL;
+    /*
+     * Read the vfs structure.
+     */
+    if (kread(ctx, (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(ctx, (KA_T)v.vfs_gfs, (char *)&g, sizeof(g)))
+        goto vfs_exit;
+    if (!v.vfs_mdata ||
+        kread(ctx,
+              (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);
+        Error(ctx);
+    }
+    if (kread(ctx, (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);
+            Error(ctx);
+        }
+    } 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/lib/dialects/aix/dlsof.h b/lib/dialects/aix/dlsof.h
new file mode 100644
index 0000000..b7a5aff
--- /dev/null
+++ b/lib/dialects/aix/dlsof.h
@@ -0,0 +1,432 @@
+/*
+ * 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 architecture.  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 */
+
+struct lsof_context_dialect {};
+
+#endif /* AIX_LSOF_H */
diff --git a/lib/dialects/aix/dmnt.c b/lib/dialects/aix/dmnt.c
new file mode 100644
index 0000000..dc2d2fe
--- /dev/null
+++ b/lib/dialects/aix/dmnt.c
@@ -0,0 +1,289 @@
+/*
+ * 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";
+#endif
+
+#include "common.h"
+
+/*
+ * Local static definitions
+ */
+
+/*
+ * readmnt() - read mount table
+ */
+
+struct mounts *readmnt(struct lsof_context *ctx) {
+    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(ctx, 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);
+            Error(ctx);
+        }
+        if (!(ln = Readlink(ctx, 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(ctx, 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(ctx, 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/lib/dialects/aix/dnode.c b/lib/dialects/aix/dnode.c
new file mode 100644
index 0000000..c220cfc
--- /dev/null
+++ b/lib/dialects/aix/dnode.c
@@ -0,0 +1,1257 @@
+/*
+ * 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";
+#endif
+
+#include "common.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
+ */
+
+enum lsof_lock_mode isglocked(struct lsof_context *ctx, /* context */
+                              struct gnode *ga) /* local gnode address */
+{
+
+    struct filock *cfp, f, *ffp;
+    int l;
+
+    if (!(ffp = ga->gn_filocks))
+        return LSOF_LOCK_NONE;
+    cfp = ffp;
+
+#if AIXV >= 4140
+    do {
+#endif /* AIXV>=4140 */
+
+        if (kread(ctx, (KA_T)cfp, (char *)&f, sizeof(f)))
+            return LSOF_LOCK_NONE;
+
+#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 ? LSOF_LOCK_READ_FULL : LSOF_LOCK_READ_PARTIAL;
+        case F_WRLCK:
+            return (l) ? LSOF_LOCK_WRITE_FULL : LSOF_LOCK_WRITE_PARTIAL;
+        case (F_RDLCK + F_WRLCK):
+            return LSOF_LOCK_READ_WRITE;
+        }
+        return LSOF_LOCK_NONE;
+
+#if AIXV >= 4140
+    } while ((cfp = f.FL_NEXT) && cfp != ffp);
+    return LSOF_LOCK_NONE;
+#endif /* AIXV>=4140 */
+}
+
+/*
+ * process_node() - process vnode
+ */
+
+void process_node(struct lsof_context *ctx, /* context */
+                  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];
+    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(ctx, "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) */
+
+            );
+            Error(ctx);
+        }
+    }
+    /*
+     * Read the vnode.
+     */
+    if (readvnode(ctx, va, v)) {
+        enter_nm(ctx, Namech);
+        return;
+    }
+
+#if defined(HASFSTRUCT)
+    Lf->fsv |= FSV_NI;
+    Lf->fna = va;
+#endif /* defined(HASFSTRUCT) */
+
+    /*
+     * Read the gnode.
+     */
+    if (!v->v_gnode || readgnode(ctx, (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(ctx, 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(ctx, Namech);
+            return;
+        }
+        /*
+         * Read the special node.
+         */
+        if (!g.gn_data ||
+            kread(ctx, (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(ctx, Namech);
+            return;
+        }
+        /*
+         * Read the PFS gnode and its inode and vnode.
+         */
+        if (sn.sn_pfsgnode) {
+            if (Selinet) {
+                Lf->sf = SELEXCLF;
+                return;
+            }
+            if (readgnode(ctx, (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(ctx, Namech);
+                return;
+            }
+            if (!g.gn_data || readlino(ctx, &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(ctx, Namech);
+                return;
+            }
+            ins = 1;
+            if (!g.gn_vnode || readvnode(ctx, (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(ctx, 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(ctx, (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(ctx, &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(ctx, 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(ctx, qp, (char *)&q, sizeof(q)))
+                                break;
+                            if (!(ka = (KA_T)q.q_qinfo) ||
+                                kread(ctx, ka, (char *)&qi, sizeof(qi)))
+                                continue;
+                            if (!(ka = (KA_T)qi.qi_minfo) ||
+                                kread(ctx, ka, (char *)&mi, sizeof(mi)))
+                                continue;
+                            if (!(ka = (KA_T)mi.mi_idname) ||
+                                kread(ctx, ka, mn, sizeof(mn) - 1) ||
+                                !(ml = (int)strlen(mn)) || !strcmp(mn, "sth"))
+                                continue;
+                            if (!strcmp(mn, "xtiso") && (xp = (KA_T)q.q_ptr) &&
+                                !kread(ctx, 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(ctx, (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(ctx, Namech);
+                return;
+            }
+            /*
+             * Otherwise, read the devnode and its gnode.
+             */
+        } else {
+            if (!sn.sn_devnode ||
+                kread(ctx, (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(ctx, 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(ctx, print_kptr(va, (char *)NULL, 0));
+    } else {
+        if (!(vfs = readvfs(ctx, 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(ctx, 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(ctx, &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(ctx, (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(ctx, 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(ctx, (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(ctx, 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(ctx, (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(ctx, 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(ctx, &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(ctx, 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(ctx, 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(ctx, 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(ctx, 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(ctx, 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.
+     */
+    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:
+        break;
+    case N_CHR:
+    case N_MPC:
+        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;
+            }
+        }
+        break;
+    }
+    /*
+     * Record link count.
+     */
+    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:
+        Lf->type = LSOF_FILE_VNODE_VNON;
+        Lf->dev = dev;
+        Lf->dev_def = devs;
+        Lf->rdev = rdev;
+        Lf->rdev_def = rdevs;
+        break;
+    case VREG:
+    case VDIR:
+        Lf->type = (type == VREG) ? LSOF_FILE_VNODE_VREG : LSOF_FILE_VNODE_VDIR;
+        Lf->dev = dev;
+        Lf->dev_def = devs;
+        Lf->rdev = rdev;
+        Lf->rdev_def = rdevs;
+        break;
+    case VBLK:
+        Lf->type = LSOF_FILE_VNODE_VBLK;
+        Lf->dev = dev;
+        Lf->dev_def = devs;
+        Lf->rdev = rdev;
+        Lf->rdev_def = rdevs;
+        Ntype = N_BLK;
+        break;
+    case VCHR:
+        Lf->type = LSOF_FILE_VNODE_VCHR;
+        Lf->dev = dev;
+        Lf->dev_def = devs;
+        Lf->rdev = rdev;
+        Lf->rdev_def = rdevs;
+        Ntype = N_CHR;
+        break;
+    case VLNK:
+        Lf->type = LSOF_FILE_VNODE_VLNK;
+        Lf->dev = dev;
+        Lf->dev_def = devs;
+        Lf->rdev = rdev;
+        Lf->rdev_def = rdevs;
+        break;
+
+#if defined(VSOCK)
+    case VSOCK:
+        Lf->type = LSOF_FILE_VNODE_VSOCK;
+        Lf->dev = dev;
+        Lf->dev_def = devs;
+        Lf->rdev = rdev;
+        Lf->rdev_def = rdevs;
+        break;
+#endif
+
+    case VBAD:
+        Lf->type = LSOF_FILE_VNODE_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;
+        }
+        Lf->type = LSOF_FILE_VNODE_VFIFO;
+        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;
+        Lf->type = LSOF_FILE_VNODE_VMPC;
+        break;
+    default:
+        Lf->dev = dev;
+        Lf->dev_def = devs;
+        Lf->rdev = rdev;
+        Lf->rdev_def = rdevs;
+        Lf->type = LSOF_FILE_UNKNOWN_RAW;
+        Lf->unknown_file_type_number = type;
+    }
+    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(ctx);
+#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(ctx);
+    /*
+     * Test for specified file.
+     */
+    if (Sfile && is_file_named(ctx, NULL, type, g.gn_chan, ic))
+        Lf->sf |= SELNM;
+    /*
+     * Enter name characters.
+     */
+    if (Namech[0])
+        enter_nm(ctx, Namech);
+}
+
+#if defined(HASPRIVFILETYPE)
+/*
+ * process_shmt() -- process shared memory transport file
+ */
+
+void process_shmt(struct lsof_context *ctx, /* context */
+                  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.
+     */
+    Lf->type = LSOF_FILE_SHARED_MEM_TRANSPORT;
+    if (!sa || kread(ctx, (KA_T)sa, (char *)&mn, sizeof(mn))) {
+        (void)snpf(Namech, Namechl, "can't read shmtnode: %s",
+                   print_kptr(sa, (char *)NULL, 0));
+        enter_nm(ctx, Namech);
+        return;
+    }
+    enter_dev_ch(ctx, print_kptr(sa, (char *)NULL, 0));
+    /*
+     * If buffer size is less than free bytes, enable offset display. Otherwise
+     * set the file size as buffer size less free bytes.
+     */
+    if (mn.free <= mn.sz) {
+        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(ctx, (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(ctx, Namech);
+}
+#endif /* AIXV>=4200 */
+
+/*
+ * readlino() -- read local inode
+ */
+
+int readlino(struct lsof_context *ctx, /* context */
+             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(ctx, ga, li));
+#endif /* defined(HAS_JFS2) */
+
+    /*
+     * Read a "standard" inode.
+     */
+    if (readinode(ctx, (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/lib/dialects/aix/dnode1.c b/lib/dialects/aix/dnode1.c
new file mode 100644
index 0000000..11c1a35
--- /dev/null
+++ b/lib/dialects/aix/dnode1.c
@@ -0,0 +1,296 @@
+/*
+ * 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";
+#endif
+
+#if defined(HAS_AFS)
+#    include "common.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
+ */
+
+static struct volume *getvolume(struct lsof_context *ctx, struct VenusFid *f,
+                                int *vols);
+static int is_rootFid(struct lsof_context *ctx, 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(struct lsof_context *ctx, /* context */
+                                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(ctx, kh, (char *)&vp, sizeof(vp)))
+        return ((struct volume *)NULL);
+    while (vp) {
+        if (kread(ctx, (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(struct lsof_context *ctx, /* context */
+           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(ctx, (KA_T)vp->v_vfsp, (char *)&v, sizeof(v)))
+        return (0);
+    if (!v.vfs_mdata || kread(ctx, (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(struct lsof_context *ctx, /* context */
+                      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(ctx, (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(struct lsof_context *ctx, /* context */
+                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(ctx, 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(ctx, &vc->fid, &vols))) {
+            an->inode = (INODETYPE)((vp->mtpoint.Fid.Vnode +
+                                     (vp->mtpoint.Fid.Volume << 16)) &
+                                    0x7fffffff);
+            if (an->inode == (INODETYPE)0) {
+                if (is_rootFid(ctx, 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/lib/dialects/aix/dnode2.c b/lib/dialects/aix/dnode2.c
new file mode 100644
index 0000000..2b080d8
--- /dev/null
+++ b/lib/dialects/aix/dnode2.c
@@ -0,0 +1,75 @@
+/*
+ * 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";
+#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 "common.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(struct lsof_context *ctx, /* context */
+               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(ctx, (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/lib/dialects/aix/dproc.c b/lib/dialects/aix/dproc.c
new file mode 100644
index 0000000..81949ad
--- /dev/null
+++ b/lib/dialects/aix/dproc.c
@@ -0,0 +1,1424 @@
+/*
+ * 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";
+#endif
+
+#include "common.h"
+
+static void get_kernel_access(struct lsof_context *ctx);
+
+#if AIXA < 2
+static struct le *getle(struct lsof_context *ctx, KA_T a, KA_T sid, char **err);
+#endif /* AIXA<2 */
+
+#if AIXV >= 4110
+static void getlenm(struct lsof_context *ctx, struct le *le, KA_T sid);
+#endif /* AIXV>=4110 */
+
+static int kreadx(KA_T addr, char *buf, int len, KA_T sid);
+
+#if AIXA < 2
+static void process_text(struct lsof_context *ctx, KA_T sid);
+#else  /* AIXA>=2 */
+static void getsoinfo(void);
+static void process_text(struct lsof_context *ctx, pid_t pid);
+#endif /* AIXA<2 */
+
+#if defined(SIGDANGER)
+#    if defined(HASINTSIGNAL)
+static int lowpgsp(struct lsof_context *ctx, int sig);
+#    else  /* !defined(HASINTSIGNAL) */
+static void lowpgsp(struct lsof_context *ctx, 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(struct lsof_context *ctx, /* context */
+          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));
+        Error(ctx);
+    }
+    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);
+        Error(ctx);
+    }
+    /*
+     * 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);
+        Error(ctx);
+    }
+    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));
+        Error(ctx);
+    }
+    (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;
+
+    if (Fwarn)
+        return;
+
+    (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(struct lsof_context *ctx) {
+    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);
+            Error(ctx);
+        }
+        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);
+            Error(ctx);
+        }
+    }
+#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);
+            Error(ctx);
+        }
+        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);
+                Error(ctx);
+            }
+            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(ctx, 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(ctx, 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(ctx, 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);
+                Error(ctx);
+            }
+        }
+        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(ctx, 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(ctx, LSOF_FD_CWD, -1);
+            process_node(ctx, cdir);
+            if (Lf->sf)
+                link_lfile(ctx);
+        }
+        /*
+         * Save root directory information.
+         */
+        if (!ckscko && rdir) {
+            alloc_lfile(ctx, LSOF_FD_ROOT_DIR, -1);
+            process_node(ctx, rdir);
+            if (Lf->sf)
+                link_lfile(ctx);
+        }
+
+#if AIXV < 4100
+        /*
+         * Save parent directory information.
+         */
+        if (!ckscko && pdir) {
+            alloc_lfile(ctx, LSOF_FD_PARENT_DIR, -1);
+            process_node(ctx, pdir);
+            if (Lf->sf)
+                link_lfile(ctx);
+        }
+#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(ctx, sid);
+            }
+#    endif /* AIXA<1 */
+#else      /* AIXA>=2 */
+            process_text(ctx, 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(ctx, LSOF_FD_NUMERIC, i);
+                process_file(ctx, fp);
+                if (Lf->sf) {
+
+#if defined(HASFSTRUCT)
+
+#    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(ctx);
+                }
+            }
+        }
+        /*
+         * Examine results.
+         */
+        if (examine_lproc(ctx))
+            return;
+    }
+}
+
+/*
+ * get_kernel_access() - get access to kernel memory
+ */
+
+static void get_kernel_access(struct lsof_context *ctx) {
+    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);
+        Error(ctx);
+    }
+#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(ctx);
+#else  /* !defined(WILLDROPGID) */
+    /*
+     * See if the non-KMEM memory file is readable.
+     */
+    if (Memory && !is_readable(ctx, Memory, 1))
+        Error(ctx);
+#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)
+        Error(ctx);
+
+#if defined(WILLDROPGID)
+    /*
+     * Drop setgid permission, if necessary.
+     */
+    if (!Memory)
+        (void)dropgid(ctx);
+#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);
+        Error(ctx);
+    }
+
+#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(ctx, "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(struct lsof_context *ctx, /* context */
+                        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(ctx, 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(struct lsof_context *ctx, /* context */
+                    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(ctx, (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(ctx, &buf[i + 1]);
+    else if (buf[0])
+        enter_nm(ctx, buf);
+#        else  /* AIXA>=2 */
+    if (!le->nm || kread(ctx, le->nm, buf, sizeof(buf)))
+        return;
+    buf[LIBNMLN - 1] = '\0';
+    if (!strlen(buf))
+        return;
+    enter_nm(ctx, 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);
+        Error(ctx);
+    }
+    /*
+     * 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);
+            Error(ctx);
+        }
+        /*
+         * 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);
+            Error(ctx);
+        }
+        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(struct lsof_context *ctx) {
+    get_kernel_access(ctx);
+
+#if AIXA > 1
+    (void)getsoinfo();
+#endif /* AIXA>1 */
+}
+
+/*
+ * kread() - read from kernel memory
+ */
+
+int kread(struct lsof_context *ctx, /* context */
+          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(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(struct lsof_context *ctx, int sig) {
+    (void)fprintf(stderr, "%s: FATAL: system paging space is low.\n", Pn);
+    Error(ctx);
+}
+#endif /* defined(SIGDANGER) */
+
+#if AIXA < 2
+/*
+ * process_text() - process text file information for non-ia64 AIX
+ */
+
+static void process_text(struct lsof_context *ctx, /* context */
+                         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(ctx, LSOF_FD_PROGRAM_TEXT, -1);
+        if ((le = getle(ctx, ll, sid, &err))) {
+            if ((xf = le->fp)) {
+                process_file(ctx, (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(ctx);
+                }
+            }
+        } else {
+            (void)snpf(Namech, Namechl, "text entry at %s: %s",
+                       print_kptr((KA_T)ll, (char *)NULL, 0), err);
+            enter_nm(ctx, Namech);
+            if (Lf->sf)
+                link_lfile(ctx);
+        }
+    }
+    /*
+     * 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) {
+        alloc_lfile(ctx, LSOF_FD_LIBRARY_REF, i);
+        if (!(le = getle(ctx, ll, sid, &err))) {
+            (void)snpf(Namech, Namechl, "loader entry at %s: %s",
+                       print_kptr((KA_T)ll, (char *)NULL, 0), err);
+            enter_nm(ctx, Namech);
+            if (Lf->sf)
+                link_lfile(ctx);
+            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);
+                Error(ctx);
+            }
+        }
+        f[n++] = le->fp;
+        /*
+         * Save the loader entry.
+         */
+        process_file(ctx, (KA_T)le->fp);
+        if (Lf->sf) {
+
+#    if AIXV >= 4110
+            if (!Lf->nm || !Lf->nm[0])
+                getlenm(ctx, le, sid);
+#    endif /* AIXV>=4110 */
+
+            link_lfile(ctx);
+            i++;
+        }
+    }
+}
+#else /* AIXA>=2 */
+/*
+ * process_text() - process text file information for ia64 AIX >= 5
+ */
+
+static void process_text(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(ctx, (KA_T)la->exec, (char *)&le, sizeof(le)) &&
+        le.fp) {
+        alloc_lfile(ctx, LSOF_FD_PROGRAM_TEXT, -1);
+        process_file(ctx, (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(ctx);
+        }
+    }
+    /*
+     * 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.
+         */
+        alloc_lfile(ctx, LSOF_FD_LIBRARY_REF, i++);
+        Lf->dev_def = Lf->inp_ty = Lf->nlink_def = 1;
+        Lf->dev = sb.st_dev;
+        Lf->inode = (INODETYPE)sb.st_ino;
+        Lf->type = LSOF_FILE_VNODE_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;
+                Lf->sz_def = 1;
+                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;
+            Lf->sz_def = 1;
+        }
+        /*
+         * 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(ctx, nm);
+            link_lfile(ctx);
+        }
+    }
+    (void)closedir(dfp);
+}
+#endif     /* AIXA<2 */
diff --git a/lib/dialects/aix/dproto.h b/lib/dialects/aix/dproto.h
new file mode 100644
index 0000000..70b1568
--- /dev/null
+++ b/lib/dialects/aix/dproto.h
@@ -0,0 +1,66 @@
+/*
+ * 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)
+extern struct vnode *alloc_vcache(void);
+extern int hasAFS(struct lsof_context *ctx, struct vnode *vp);
+extern int readafsnode(struct lsof_context *ctx, KA_T va, struct vnode *v,
+                       struct afsnode *an);
+#    endif /* defined(HAS_AFS) */
+
+#    if defined(HAS_JFS2)
+extern int readj2lino(struct lsof_context *ctx, struct gnode *ga, struct l_ino *li);
+#    endif /* defined(HAS_JFS2) */
+
+extern int getchan(char *p);
+extern int is_file_named(struct lsof_context *ctx, char *p, enum vtype ty, chan_t ch, int ic);
+extern char isglocked(struct lsof_context *ctx, struct gnode *ga);
+extern int readlino(struct lsof_context *ctx, struct gnode *ga, struct l_ino *li);
+extern struct l_vfs *readvfs(struct lsof_context *ctx, struct vnode *vn);
+
+#    if AIXV >= 4200
+extern void process_shmt(struct lsof_context *ctx, KA_T sa);
+#    endif /* AIV>=4200 */
+
+#    if defined(HASDCACHE) && AIXV >= 4140
+extern void clr_sect(struct lsof_context *ctx);
+extern int rw_clone_sect(struct lsof_context *ctx, int m);
+#    endif /* defined(HASDCACHE) && AIXV>=4140 */
+
+#endif /* !defined(DPROTO_H) */
diff --git a/lib/dialects/aix/dsock.c b/lib/dialects/aix/dsock.c
new file mode 100644
index 0000000..1a130ec
--- /dev/null
+++ b/lib/dialects/aix/dsock.c
@@ -0,0 +1,418 @@
+/*
+ * 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";
+#endif
+
+#include "common.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(struct lsof_context *ctx, /* context */
+                    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.
+     */
+    Lf->type = LSOF_FILE_SOCKET;
+    Lf->inp_ty = 2;
+    /*
+     * Read socket and protocol switch structures.
+     */
+    if (!sa) {
+        enter_nm(ctx, "no socket address");
+        return;
+    }
+    if (kread(ctx, sa, (char *)&s, sizeof(s))) {
+        (void)snpf(Namech, Namechl, "can't read socket struct from %s",
+                   print_kptr(sa, (char *)NULL, 0));
+        enter_nm(ctx, Namech);
+        return;
+    }
+    if (!s.so_type) {
+        enter_nm(ctx, "no socket type");
+        return;
+    }
+    if (!s.so_proto || kread(ctx, (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(ctx, Namech);
+        return;
+    }
+    /*
+     * Save size information.
+     */
+    if (Lf->access == LSOF_FILE_ACCESS_READ)
+        Lf->sz = (SZOFFTYPE)s.so_rcv.sb_cc;
+    else if (Lf->access == LSOF_FILE_ACCESS_WRITE)
+        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;
+
+#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(ctx, (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(ctx, 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(ctx, (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(ctx, Namech);
+            return;
+        }
+        if (p.pr_protocol == IPPROTO_TCP) {
+
+            /*
+             * If this is a TCP socket, read its control block.
+             */
+            if (inp.inp_ppcb &&
+                !kread(ctx, (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(ctx, p.pr_protocol);
+
+#if defined(HASIPv6)
+        Lf->type = fam == AF_INET ? LSOF_FILE_IPV4 : LSOF_FILE_IPV6;
+#else  /* !defined(HASIPv6) */
+        Lf->type = LSOF_FILE_INET;
+#endif /* defined(HASIPv6) */
+
+        /*
+         * Save Internet socket information.
+         */
+        enter_dev_ch(ctx,
+                     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(ctx, 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:
+        Lf->type = LSOF_FILE_ROUTE;
+        if (s.so_pcb)
+            enter_dev_ch(ctx, print_kptr((KA_T)(s.so_pcb), (char *)NULL, 0));
+        else
+            (void)snpf(Namech, Namechl, "no protocol control block");
+        break;
+        /*
+         * Process a Unix domain socket.
+         */
+    case AF_UNIX:
+        if (Funix)
+            Lf->sf |= SELUNX;
+        Lf->type = LSOF_FILE_UNIX;
+        /*
+         * Read Unix protocol control block and the Unix address structure.
+         */
+        enter_dev_ch(ctx, print_kptr(sa, (char *)NULL, 0));
+        if (kread(ctx, (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(ctx, (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(ctx, (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(ctx, (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(ctx, (KA_T)unp.unp_vnode, &v)) {
+            if (v.v_gnode && !readgnode(ctx, (KA_T)v.v_gnode, &g)) {
+                Lf->lock = isglocked(ctx, &g);
+                if (g.gn_type == VSOCK && g.gn_data && !readlino(ctx, &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(ctx, 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(ctx, fam, 1);
+    }
+    if (Namech[0])
+        enter_nm(ctx, Namech);
+}
diff --git a/lib/dialects/aix/dstore.c b/lib/dialects/aix/dstore.c
new file mode 100644
index 0000000..11d6ff0
--- /dev/null
+++ b/lib/dialects/aix/dstore.c
@@ -0,0 +1,398 @@
+/*
+ * 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";
+#endif
+
+#include "common.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/lib/dialects/aix/machine.h b/lib/dialects/aix/machine.h
new file mode 100644
index 0000000..75434da
--- /dev/null
+++ b/lib/dialects/aix/machine.h
@@ -0,0 +1,631 @@
+/*
+ * 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 access
+ * 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?	*/
+
+/*
+ * 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_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/lib/dialects/hpux/kmem/Makefile b/lib/dialects/hpux/kmem/Makefile
new file mode 100644
index 0000000..080063d
--- /dev/null
+++ b/lib/dialects/hpux/kmem/Makefile
@@ -0,0 +1,160 @@
+
+# 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_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/lib/dialects/hpux/kmem/Mksrc b/lib/dialects/hpux/kmem/Mksrc
new file mode 100755
index 0000000..f94d164
--- /dev/null
+++ b/lib/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/lib/dialects/hpux/kmem/dfile.c b/lib/dialects/hpux/kmem/dfile.c
new file mode 100644
index 0000000..fd9cf2b
--- /dev/null
+++ b/lib/dialects/hpux/kmem/dfile.c
@@ -0,0 +1,245 @@
+/*
+ * 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";
+#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 "common.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(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(ctx, (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;
+    Lf->off_def = 1;
+
+    if (f.f_count) {
+
+#if defined(HASFSTRUCT)
+        /*
+         * Save file structure values.
+         */
+        Lf->fct = (long)f.f_count;
+        Lf->fsv |= FSV_CT;
+        Lf->fsa = fp;
+        Lf->fsv |= FSV_FA;
+        Lf->ffg = (long)f.f_flag;
+        Lf->fsv |= FSV_FG;
+        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 = LSOF_FILE_ACCESS_READ;
+        else if (flag == FWRITE)
+            Lf->access = LSOF_FILE_ACCESS_WRITE;
+        else if (flag == (FREAD | FWRITE))
+            Lf->access = LSOF_FILE_ACCESS_READ_WRITE;
+        /*
+         * 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(ctx, 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(ctx, qa, (char *)&q, sizeof(q)))
+            break;
+        if (!(ka = (KA_T)q.q_qinfo) || kread(ctx, ka, (char *)&qi, sizeof(qi)))
+            continue;
+        if (!(ka = (KA_T)qi.qi_minfo) ||
+            kread(ctx, ka, (char *)&mi, sizeof(mi)))
+            continue;
+        if (!(ka = (KA_T)mi.mi_idname) || kread(ctx, 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/lib/dialects/hpux/kmem/dlsof.h b/lib/dialects/hpux/kmem/dlsof.h
new file mode 100644
index 0000000..9baed7b
--- /dev/null
+++ b/lib/dialects/hpux/kmem/dlsof.h
@@ -0,0 +1,439 @@
+/*
+ * 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) */
+
+struct lsof_context_dialect {};
+
+#endif /* HPUX_LSOF_H */
diff --git a/lib/dialects/hpux/kmem/dmnt.c b/lib/dialects/hpux/kmem/dmnt.c
new file mode 100644
index 0000000..d24a7cc
--- /dev/null
+++ b/lib/dialects/hpux/kmem/dmnt.c
@@ -0,0 +1,236 @@
+/*
+ * 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";
+#endif
+
+#if defined(HPUXKERNBITS) && HPUXKERNBITS >= 64
+#    define _TIME_T
+typedef int time_t;
+#endif /* defined(HPUXKERNBITS) && HPUXKERNBITS>=64 */
+
+#include "common.h"
+
+/*
+ * Local static definitions
+ */
+
+/*
+ * 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);
+            Error(ctx);
+        }
+        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(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);
+        Error(ctx);
+    }
+    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(ctx, (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(ctx, (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(ctx, (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/lib/dialects/hpux/kmem/dnode.c b/lib/dialects/hpux/kmem/dnode.c
new file mode 100644
index 0000000..458d469
--- /dev/null
+++ b/lib/dialects/hpux/kmem/dnode.c
@@ -0,0 +1,1052 @@
+/*
+ * 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";
+#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 "common.h"
+#include <sys/inode.h>
+
+#if HPUXV >= 900
+static void enter_nma(char *b);
+static enum lsof_lock_mode islocked(KA_T lp);
+#endif /* HPUXV>=900 */
+
+static int getnodety(struct vnode *v);
+static int readinode(KA_T ia, struct inode *i);
+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 enum lsof_lock_mode islocked(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 LSOF_LOCK_NONE;
+    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(ctx, llp, (char *)&ll, sizeof(ll)))
+            return LSOF_LOCK_NONE;
+
+#    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 l ? LSOF_LOCK_WRITE_FULL : LSOF_LOCK_WRITE_PARTIAL;
+        else if (ll.ll_type == F_RDLCK)
+            return l ? LSOF_LOCK_READ_FULL : LSOF_LOCK_READ_PARTIAL;
+        return LSOF_LOCK_NONE;
+    }
+
+#    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 LSOF_LOCK_NONE;
+}
+#endif /* HPUXV>=900 */
+
+/*
+ * getnodety() - get node type
+ */
+
+static int getnodety(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];
+    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) */
+
+            );
+            Error(ctx);
+        }
+    }
+    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 = LSOF_LOCK_READ_WRITE;
+        else if (v->v_shlockc)
+            Lf->lock = LSOF_LOCK_READ_FULL;
+        else
+            Lf->lock = LSOF_LOCK_WRITE_FULL;
+    }
+#else /* HPUXV>900 */
+#    if HPUXV >= 1000
+    Lf->lock = 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(ctx, (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(ctx, (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(ctx, (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 = 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.
+     */
+    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 (Lf->access != LSOF_FILE_ACCESS_READ &&
+            Lf->access != LSOF_FILE_ACCESS_WRITE) {
+            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 == LSOF_FILE_ACCESS_READ) ? rp
+                                                                      : wp);
+            Lf->off_def = 1;
+            (void)snpf(fb, sizeof(fb), "%s=%#x",
+                       (Lf->access == LSOF_FILE_ACCESS_READ) ? "rd" : "wr",
+                       (Lf->access == LSOF_FILE_ACCESS_READ) ? rp : wp);
+            (void)enter_nma(fb);
+        }
+        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) && ins) {
+            Lf->sz = (SZOFFTYPE)i.i_size;
+            Lf->sz_def = 1;
+        }
+        break;
+    }
+    /*
+     * Record link count.
+     */
+    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:
+        Lf->type = LSOF_FILE_VNODE_VNON;
+        break;
+    case VREG:
+    case VDIR:
+        Lf->type = (type == VREG) ? LSOF_FILE_VNODE_VREG : LSOF_FILE_VNODE_VDIR;
+        break;
+    case VBLK:
+        Lf->type = LSOF_FILE_VNODE_VBLK;
+        Ntype = N_BLK;
+        break;
+    case VCHR:
+        Lf->type = LSOF_FILE_VNODE_VCHR;
+        Ntype = N_CHR;
+        break;
+    case VLNK:
+        Lf->type = LSOF_FILE_VNODE_VLNK;
+        break;
+
+#if defined(VSOCK)
+    case VSOCK:
+        Lf->type = LSOF_FILE_VNODE_VSOCK;
+        break;
+#endif /* defined(VSOCK) */
+
+    case VBAD:
+        Lf->type = LSOF_FILE_VNODE_VBAD;
+        break;
+    case VFIFO:
+        switch (Ntype) {
+
+#if HPUXV >= 1000
+        case N_FIFO:
+            Lf->type = LSOF_FILE_VNODE_VFIFO;
+            break;
+        case N_PIPE:
+            Lf->type = LSOF_FILE_PIPE;
+            break;
+#endif /* HPUXV>=1000 */
+
+        default:
+            Lf->type = LSOF_FILE_FIFO;
+        }
+        break;
+    default:
+        Lf->type = LSOF_FILE_UNKNOWN_RAW;
+        Lf->unknown_file_type_number = type;
+    }
+    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(ctx, (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(ctx, (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/lib/dialects/hpux/kmem/dnode1.c b/lib/dialects/hpux/kmem/dnode1.c
new file mode 100644
index 0000000..e187c50
--- /dev/null
+++ b/lib/dialects/hpux/kmem/dnode1.c
@@ -0,0 +1,145 @@
+/*
+ * 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";
+#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(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(ctx, (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 (!(v->v_type == VCHR || v->v_type == VBLK)) {
+        Lf->sz = (SZOFFTYPE)i.i_size;
+        Lf->sz_def = 1;
+    }
+    /*
+     * Record link count.
+     */
+    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/lib/dialects/hpux/kmem/dnode2.c b/lib/dialects/hpux/kmem/dnode2.c
new file mode 100644
index 0000000..240fabe
--- /dev/null
+++ b/lib/dialects/hpux/kmem/dnode2.c
@@ -0,0 +1,346 @@
+/*
+ * 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";
+#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
+ */
+
+static struct volume *getvolume(struct VenusFid *f, int *vols);
+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(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(ctx, kh, (char *)&vp, sizeof(vp)))
+        return ((struct volume *)NULL);
+    while (vp) {
+        if (kread(ctx, (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(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(ctx, (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(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(ctx, (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(ctx, 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/lib/dialects/hpux/kmem/dproc.c b/lib/dialects/hpux/kmem/dproc.c
new file mode 100644
index 0000000..2920151
--- /dev/null
+++ b/lib/dialects/hpux/kmem/dproc.c
@@ -0,0 +1,804 @@
+/*
+ * 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";
+#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 "common.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 */
+
+static void get_kernel_access(void);
+
+#if HPUXV >= 800
+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(ctx, v, (char *)&oftsz, sizeof(oftsz))) {
+                (void)fprintf(stderr, "%s: can't get FD chunk size\n", Pn);
+                Error(ctx);
+            }
+            if (!oftsz) {
+                (void)fprintf(stderr, "%s: bad FD chunk size: %d\n", Pn, oftsz);
+                Error(ctx);
+            }
+        }
+        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);
+            Error(ctx);
+        }
+        if (!(oftp = (char *)malloc((MALLOC_S)oftsz))) {
+            (void)fprintf(stderr, "%s: no space for %d FD bytes\n", Pn, oftsz);
+            Error(ctx);
+        }
+    }
+#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(ctx, 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(ctx, 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(ctx, (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(ctx, LSOF_FD_CWD, -1);
+            process_node((KA_T)CURDIR);
+            if (Lf->sf)
+                link_lfile();
+        }
+        /*
+         * Save root directory information.
+         */
+        if (ROOTDIR) {
+            alloc_lfile(ctx, LSOF_FD_ROOT_DIR, -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(ctx, (KA_T)pfp, (char *)&ofp, sizeof(ofp)) ||
+                    !ofp || kread(ctx, (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(ctx, (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(ctx, LSOF_FD_NUMERIC, i);
+                process_file(fp);
+                if (Lf->sf) {
+
+#if defined(USESPOFILE)
+                    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));
+            Error(ctx);
+        }
+        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);
+            Error(ctx);
+        }
+    }
+#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))
+        Error(ctx);
+#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));
+        Error(ctx);
+    }
+
+#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))
+        Error(ctx);
+#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);
+            Error(ctx);
+        }
+        (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);
+        Error(ctx);
+    }
+    if (get_Nl_value("proc", Drive_Nl, &v) < 0 || !v ||
+        kread(ctx, (KA_T)v, (char *)&Kp, sizeof(Kp)) ||
+        get_Nl_value("nproc", Drive_Nl, &v) < 0 || !v ||
+        kread(ctx, (KA_T)v, (char *)&Np, sizeof(Np)) || !Kp || Np < 1) {
+        (void)fprintf(stderr, "%s: can't read proc table info\n", Pn);
+        Error(ctx);
+    }
+    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);
+        Error(ctx);
+    }
+    if (get_Nl_value("upt", Drive_Nl, (unsigned long *)&usrpt) < 0) {
+        (void)fprintf(stderr, "%s: can't get kernel's usrpt\n", Pn);
+        Error(ctx);
+    }
+#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);
+        Error(ctx);
+    }
+    if (get_Nl_value("npids", Drive_Nl, &v) < 0 || !v ||
+        kread(ctx, (KA_T)v, (char *)&npids, sizeof(npids))) {
+        (void)fprintf(stderr, "%s: can't get kernel's npids\n", Pn);
+        Error(ctx);
+    }
+#endif /* HPUXV<800 && defined(hp9000s800) */
+
+#if HPUXV >= 1030
+    if (get_Nl_value("clmaj", Drive_Nl, &v) < 0 || !v ||
+        kread(ctx, (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(struct lsof_context *ctx, /* context */
+          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(ctx, 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(ctx, prp, (char *)&p, sizeof(p)))
+            return;
+        if (kread(ctx, (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);
+                Error(ctx);
+            }
+        }
+        Vp[i++] = va;
+        /*
+         * Allocate local file structure.
+         */
+        switch (p.p_type) {
+        case PT_DATA:
+        case PT_TEXT:
+            alloc_lfile(ctx, LSOF_FD_PROGRAM_TEXT, -1);
+            break;
+        case PT_MMAP:
+            alloc_lfile(ctx, LSOF_FD_MEMORY, -1);
+            break;
+        default:
+            alloc_lfile(ctx, LSOF_FD_PREGION_UNKNOWN, p.p_type);
+        }
+        /*
+         * Save vnode information.
+         */
+        process_node(va);
+        if (Lf->sf)
+            link_lfile();
+    }
+}
+#endif /* HPUXV>=800 */
diff --git a/lib/dialects/hpux/kmem/dproto.h b/lib/dialects/hpux/kmem/dproto.h
new file mode 100644
index 0000000..5dbff4f
--- /dev/null
+++ b/lib/dialects/hpux/kmem/dproto.h
@@ -0,0 +1,67 @@
+/*
+ * 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
+extern void completevfs(struct l_vfs *vfs, dev_t *dev, struct vfs *v);
+#else
+extern void completevfs(struct l_vfs *vfs, dev_t *dev);
+#endif /* HPUXV>=800 */
+
+extern int is_file_named(char *p, int cd);
+extern int get_max_fd(void);
+
+#if defined(DTYPE_LLA)
+extern void process_lla(KA_T la);
+#endif
+
+extern struct l_vfs *readvfs(struct vnode *lv);
+
+#if HPUXV >= 1030
+extern void process_stream_sock(KA_T ip, KA_T pcb, char *pn, enum vtype vt);
+extern int read_mi(KA_T sh, KA_T *ip, KA_T *pcb, char **pn);
+#endif /* HPUXV>=1030 */
+
+#if defined(HAS_AFS)
+extern struct vnode *alloc_vcache(void);
+extern void ckAFSsym(struct nlist *nl);
+extern int hasAFS(struct vnode *vp);
+extern int readafsnode(KA_T va, struct vnode *v, struct afsnode *an);
+#endif /* defined(HAS_AFS) */
+
+#if defined(HASVXFS)
+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/lib/dialects/hpux/kmem/dsock.c b/lib/dialects/hpux/kmem/dsock.c
new file mode 100644
index 0000000..9f57bd8
--- /dev/null
+++ b/lib/dialects/hpux/kmem/dsock.c
@@ -0,0 +1,1125 @@
+/*
+ * 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";
+#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 "common.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;
+
+    Lf->type = LSOF_FILE_LINK_LEVEL_ACCESS;
+    Lf->inp_ty = 2;
+    enter_dev_ch(print_kptr(la, (char *)NULL, 0));
+    /*
+     * Read link level access control block.
+     */
+    if (!la || kread(ctx, (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 = LSOF_FILE_ACCESS_WRITE;
+    else if ((lcb.lla_flags & LLA_FWRITE | LLA_FREAD) == LLA_FREAD)
+        Lf->access = LSOF_FILE_ACCESS_READ;
+    else if (lcb.lla_flags & LLA_FWRITE | LLA_FREAD)
+        Lf->access = LSOF_FILE_ACCESS_READ_WRITE;
+    /*
+     * 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 */
+
+    Lf->type = LSOF_FILE_SOCKET;
+    Lf->inp_ty = 2;
+    /*
+     * Read socket structure.
+     */
+    if (!sa) {
+        enter_nm("no socket address");
+        return;
+    }
+    if (kread(ctx, (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(ctx, (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(ctx, (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 (Lf->access == LSOF_FILE_ACCESS_READ)
+        Lf->sz = (SZOFFTYPE)s.so_rcv.sb_cc;
+    else if (Lf->access == LSOF_FILE_ACCESS_WRITE)
+        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;
+
+#    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;
+        Lf->type = LSOF_FILE_X25;
+        (void)snpf(Lf->iproto, sizeof(Lf->iproto), "%.*s", IPROTOL, "CCITT");
+        /*
+         * Get the X25 PCB and its extension.
+         */
+        if (!s.so_pcb || kread(ctx, (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(ctx, (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;
+        Lf->type = LSOF_FILE_INET;
+        printiproto(ctx, 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(ctx, (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(ctx, (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(ctx, (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;
+        Lf->type = LSOF_FILE_UNIX;
+
+#if HPUXV >= 1030
+        /*
+         * Save size information for HP-UX 10.30 and above.
+         */
+        if (!s.so_rcv || kread(ctx, (KA_T)s.so_rcv, (char *)&rb, sizeof(rb)))
+            rb.sb_cc = 0;
+        if (!s.so_snd || kread(ctx, (KA_T)s.so_snd, (char *)&sb, sizeof(sb)))
+            sb.sb_cc = 0;
+        if (Lf->access == LSOF_FILE_ACCESS_READ)
+            Lf->sz = (SZOFFTYPE)rb.sb_cc;
+        else if (Lf->access == LSOF_FILE_ACCESS_WRITE)
+            Lf->sz = (SZOFFTYPE)sb.sb_cc;
+        else
+            Lf->sz = (SZOFFTYPE)(rb.sb_cc + sb.sb_cc);
+        Lf->sz_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(ctx, (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(ctx, (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(ctx, (KA_T)unp.unp_addr, (char *)&mb, sizeof(mb)) == 0 &&
+            mb.b_datap &&
+            kread(ctx, (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);
+                        Error(ctx);
+                    }
+                }
+                if (kread(ctx, (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(ctx, (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;
+    Lf->type = LSOF_FILE_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(ctx, 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(ctx, 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(ctx, (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 (Lf->access == LSOF_FILE_ACCESS_READ)
+            Lf->sz = (SZOFFTYPE)rq;
+        else if (Lf->access == LSOF_FILE_ACCESS_WRITE)
+            Lf->sz = (SZOFFTYPE)sq;
+        else
+            Lf->sz = (SZOFFTYPE)(rq + sq);
+        Lf->sz_def = 1;
+
+#    endif /* defined(HASTCPTPIQ) || defined(HASTCPTPIW) */
+
+#    if defined(HASTCPOPT)
+
+        /*
+         * 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)
+
+        /*
+         * 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(ctx, 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);
+        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/lib/dialects/hpux/kmem/dstore.c b/lib/dialects/hpux/kmem/dstore.c
new file mode 100644
index 0000000..74415ee
--- /dev/null
+++ b/lib/dialects/hpux/kmem/dstore.c
@@ -0,0 +1,226 @@
+/*
+ * 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";
+#endif
+
+#include "common.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/lib/dialects/hpux/kmem/hpux11/ipc_s.h b/lib/dialects/hpux/kmem/hpux11/ipc_s.h
new file mode 100644
index 0000000..e5645cf
--- /dev/null
+++ b/lib/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 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/lib/dialects/hpux/kmem/hpux11/kernbits.h b/lib/dialects/hpux/kmem/hpux11/kernbits.h
new file mode 100644
index 0000000..2abea80
--- /dev/null
+++ b/lib/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/lib/dialects/hpux/kmem/hpux11/lla.h b/lib/dialects/hpux/kmem/hpux11/lla.h
new file mode 100644
index 0000000..a6fec9b
--- /dev/null
+++ b/lib/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/lib/dialects/hpux/kmem/hpux11/nfs_clnt.h b/lib/dialects/hpux/kmem/hpux11/nfs_clnt.h
new file mode 100644
index 0000000..5978855
--- /dev/null
+++ b/lib/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/lib/dialects/hpux/kmem/hpux11/proc.h b/lib/dialects/hpux/kmem/hpux11/proc.h
new file mode 100644
index 0000000..a1be13f
--- /dev/null
+++ b/lib/dialects/hpux/kmem/hpux11/proc.h
@@ -0,0 +1,243 @@
+/*
+ * 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/lib/dialects/hpux/kmem/hpux11/rnode.h b/lib/dialects/hpux/kmem/hpux11/rnode.h
new file mode 100644
index 0000000..32820ec
--- /dev/null
+++ b/lib/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
+ * information 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/lib/dialects/hpux/kmem/hpux11/sth.h b/lib/dialects/hpux/kmem/hpux11/sth.h
new file mode 100644
index 0000000..f9de616
--- /dev/null
+++ b/lib/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/lib/dialects/hpux/kmem/hpux11/tcp_s.h b/lib/dialects/hpux/kmem/hpux11/tcp_s.h
new file mode 100644
index 0000000..7932ef1
--- /dev/null
+++ b/lib/dialects/hpux/kmem/hpux11/tcp_s.h
@@ -0,0 +1,208 @@
+/*
+ * 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/lib/dialects/hpux/kmem/hpux11/udp_s.h b/lib/dialects/hpux/kmem/hpux11/udp_s.h
new file mode 100644
index 0000000..21234c4
--- /dev/null
+++ b/lib/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/lib/dialects/hpux/kmem/hpux11/vnode.h b/lib/dialects/hpux/kmem/hpux11/vnode.h
new file mode 100644
index 0000000..5d4de4f
--- /dev/null
+++ b/lib/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/lib/dialects/hpux/kmem/machine.h b/lib/dialects/hpux/kmem/machine.h
new file mode 100644
index 0000000..2fc875c
--- /dev/null
+++ b/lib/dialects/hpux/kmem/machine.h
@@ -0,0 +1,608 @@
+/*
+ * 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?	*/
+
+/*
+ * 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_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/lib/dialects/hpux/pstat/Makefile b/lib/dialects/hpux/pstat/Makefile
new file mode 100644
index 0000000..9eace67
--- /dev/null
+++ b/lib/dialects/hpux/pstat/Makefile
@@ -0,0 +1,149 @@
+
+# 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_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/linux/Mksrc b/lib/dialects/hpux/pstat/Mksrc
similarity index 64%
rename from dialects/linux/Mksrc
rename to lib/dialects/hpux/pstat/Mksrc
index 8a1ffa1..0840e1a 100755
--- a/dialects/linux/Mksrc
+++ b/lib/dialects/hpux/pstat/Mksrc
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# Mksrc - make Linux source files for /proc-based lsof
+# 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.
@@ -10,11 +10,11 @@
 # LSOF_MKC	is the method for creating the source files.
 #		It defaults to "ln -s".  A common alternative is "cp".
 #
-# $Id: Mksrc,v 1.2 2000/12/04 14:31:02 abe Exp $
+# $Id: Mksrc,v 1.1 99/05/25 13:04:50 abe Exp $
 
 
-D=dialects/linux
-L="dfile.c dlsof.h dmnt.c dnode.c dproc.c dproto.h dsock.c dstore.c machine.h"
+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
@@ -22,4 +22,3 @@ do
   $LSOF_MKC $D/$i $i
   echo "$LSOF_MKC $D/$i $i"
 done
-
diff --git a/lib/dialects/hpux/pstat/dfile.c b/lib/dialects/hpux/pstat/dfile.c
new file mode 100644
index 0000000..f1e2d38
--- /dev/null
+++ b/lib/dialects/hpux/pstat/dfile.c
@@ -0,0 +1,753 @@
+/*
+ * 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";
+#endif
+
+#include "common.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
+ */
+
+static struct l_nc *ncache_addr(struct psfileid *ps);
+static void ncache_free(void);
+static int ncache_isroot(struct psfileid *ps);
+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(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(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);
+        Error(ctx);
+    }
+    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);
+        Error(ctx);
+    }
+}
+
+/*
+ * 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(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(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);
+        Error(ctx);
+    }
+    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);
+                Error(ctx);
+            }
+            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);
+                Error(ctx);
+            }
+            /*
+             * 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(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);
+        Error(ctx);
+    }
+    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(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];
+    enum lsof_file_type type;
+    uint32_t unknown_file_type_number = 0;
+    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) {
+        Lf->fna = na;
+        Lf->fsv |= FSV_NI;
+    }
+#endif /* defined(HASFSTRUCT) */
+
+    /*
+     * Construct lock code.
+     */
+    if ((lk = pd->psfd_lckflag) & PS_FPARTRDLCK)
+        Lf->lock = LSOF_LOCK_READ_PARTIAL;
+    else if (lk & PS_FPARTWRLCK)
+        Lf->lock = LSOF_LOCK_WRITE_PARTIAL;
+    else if (lk & PS_FFULLRDLCK)
+        Lf->lock = LSOF_LOCK_READ_FULL;
+    else if (lk & PS_FFULLWRLCK)
+        Lf->lock = LSOF_LOCK_WRITE_FULL;
+    else
+        Lf->lock = LSOF_LOCK_NONE;
+    /*
+     * Derive type from modes.
+     */
+    switch ((int)(pd->psfd_mode & PS_IFMT)) {
+    case PS_IFREG:
+        type = LSOF_FILE_REGULAR;
+        Ntype = N_REGLR;
+        break;
+    case PS_IFBLK:
+        type = LSOF_FILE_BLOCK;
+        Ntype = N_BLK;
+        break;
+    case PS_IFDIR:
+        type = LSOF_FILE_DIR;
+        Ntype = N_REGLR;
+        break;
+    case PS_IFCHR:
+        type = LSOF_FILE_CHAR;
+        Ntype = N_CHR;
+        break;
+    case PS_IFIFO:
+        type = LSOF_FILE_FIFO;
+        Ntype = N_FIFO;
+        break;
+    default:
+        type = LSOF_FILE_UNKNOWN_RAW;
+        unknown_file_type_number = (pd->psfd_mode & PS_IFMT) >> 12;
+        Ntype = N_REGLR;
+    }
+    if (Lf->type == LSOF_FILE_NONE) {
+        Lf->type = type;
+        Lf->unknown_file_type_number = unknown_file_type_number;
+    }
+    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.
+     */
+
+    /*
+     * 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->sz_def) {
+        switch (Ntype) {
+        case N_CHR:
+        case N_FIFO:
+            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/lib/dialects/hpux/pstat/dlsof.h b/lib/dialects/hpux/pstat/dlsof.h
new file mode 100644
index 0000000..2e123fd
--- /dev/null
+++ b/lib/dialects/hpux/pstat/dlsof.h
@@ -0,0 +1,205 @@
+/*
+ * 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 */
+
+struct lsof_context_dialect {};
+
+#endif /* HPUX_LSOF_H */
diff --git a/lib/dialects/hpux/pstat/dproc.c b/lib/dialects/hpux/pstat/dproc.c
new file mode 100644
index 0000000..aca6010
--- /dev/null
+++ b/lib/dialects/hpux/pstat/dproc.c
@@ -0,0 +1,845 @@
+/*
+ * 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";
+#endif
+
+#include "common.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
+ */
+
+static void get_kernel_access(void);
+static void process_text(struct pst_status *p);
+static struct pst_fileinfo2 *read_files(struct pst_status *p, int *n);
+static struct pst_status *read_proc(int *n);
+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(LSOF_FD_CWD, -1) != 2) ? 0 : 1;
+        rtds = (ck_fd_status(LSOF_FD_ROOT_DIR, -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);
+            Error(ctx);
+        }
+        for (fdsa = 0; fdsa < FDS_ALLOC_INIT; fdsa++) {
+            if (Fand && Fdl)
+                fds[fdsa] = (ck_fd_status(LSOF_FD_NUMERIC, 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(ctx, LSOF_FD_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(ctx, LSOF_FD_ROOT_DIR, -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);
+                        Error(ctx);
+                    }
+                    while (fdsa < l) {
+                        fds[fdsa] =
+                            (ck_fd_status(LSOF_FD_NUMERIC, fdsa) == 2) ? 1 : 0;
+                        fdsa++;
+                    }
+                }
+                if (!fds[fd])
+                    continue;
+            }
+            alloc_lfile(ctx, LSOF_FD_NUMERIC, (int)f->psf_fd);
+            /*
+             * Construct access code.
+             */
+            if ((flag = (long)(f->psf_flag & ~PS_FEXCLOS)) == (long)PS_FRDONLY)
+                Lf->access = LSOF_FILE_ACCESS_READ;
+            else if (flag == (long)PS_FWRONLY)
+                Lf->access = LSOF_FILE_ACCESS_WRITE;
+            else
+                Lf->access = LSOF_FILE_ACCESS_READ_WRITE;
+
+#if defined(HASFSTRUCT)
+            /*
+             * Save file structure values.
+             */
+            Lf->fct = (long)f->psf_count;
+            Lf->fsv |= FSV_CT;
+            ka = (((KA_T)(f->psf_hi_fileid & 0xffffffff) << 32) |
+                  (KA_T)(f->psf_lo_fileid & 0xffffffff));
+            if ((Lf->fsa = ka))
+                Lf->fsv |= FSV_FA;
+            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) */
+            Lf->off_def = 1;
+
+            /*
+             * 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:
+                Lf->type = LSOF_FILE_UNKNOWN;
+                (void)enter_nm("no more information");
+                break;
+            case PS_TYPE_UNSP:
+                Lf->type = LSOF_FILE_UNSUPPORTED;
+                (void)enter_nm("no more information");
+                break;
+            case PS_TYPE_LLA:
+                Lf->type = LSOF_FILE_LINK_LEVEL_ACCESS;
+                (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));
+        Error(ctx);
+    }
+    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);
+        Error(ctx);
+    }
+    /*
+     * 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;
+    Error(ctx);
+}
+
+/*
+ * 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 {
+        enum lsof_fd_type 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(LSOF_FD_MEMORY, -1) == 2) ? 1 : 0;
+        else
+            mems = 1;
+    }
+    if (txts < 0) {
+        if (Fand && Fdl)
+            txts = (ck_fd_status(LSOF_FD_PROGRAM_TEXT, -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);
+            Error(ctx);
+        }
+    }
+    /*
+     * 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 = LSOF_FD_PROGRAM_TEXT;
+            tv[0].na = na;
+            tv[0].opfid = p->pst_fid_text;
+            tv[0].psfid = p->pst_text;
+            ntvu = 1;
+        } else {
+            alloc_lfile(ctx, LSOF_FD_PROGRAM_TEXT, -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 = LSOF_FD_MEMORY;
+                tv[ntvu].na = na;
+                tv[ntvu].opfid = rp->pst_fid;
+                tv[ntvu].psfid = rp->pst_id;
+                ntvu++;
+            } else if (!meme) {
+                alloc_lfile(ctx, LSOF_FD_MEMORY, -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(ctx, 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(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(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);
+                Error(ctx);
+            }
+        }
+        /*
+         * 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(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);
+                Error(ctx);
+            }
+        }
+        /*
+         * 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(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);
+                Error(ctx);
+            }
+        }
+        /*
+         * 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/lib/dialects/hpux/pstat/dproto.h b/lib/dialects/hpux/pstat/dproto.h
new file mode 100644
index 0000000..6e17a1f
--- /dev/null
+++ b/lib/dialects/hpux/pstat/dproto.h
@@ -0,0 +1,55 @@
+/*
+ * 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 $
+ */
+
+extern int get_max_fd(void);
+extern int is_file_named(char *p, int cd);
+extern void process_finfo(struct pst_filedetails *pd, struct pst_fid *opfid,
+                          struct psfileid *psfid, KA_T na);
+extern void process_socket(struct pst_fileinfo2 *f, struct pst_socket *s);
+extern void process_stream(struct pst_fileinfo2 *f, int ckscko);
+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);
+extern struct pst_socket *read_sock(struct pst_fileinfo2 *f);
+
+#if defined(HASIPv6)
+extern struct hostent *gethostbyname2(char *nm, int proto);
+#endif /* defined(HASIPv6) */
+
+#if defined(HASVXFS)
+extern int read_vxnode(struct vnode *v, struct l_vfs *vfs, dev_t *dev);
+#endif /* defined(HASVXFS) */
+
+extern void scanmnttab(void);
diff --git a/lib/dialects/hpux/pstat/dsock.c b/lib/dialects/hpux/pstat/dsock.c
new file mode 100644
index 0000000..210683b
--- /dev/null
+++ b/lib/dialects/hpux/pstat/dsock.c
@@ -0,0 +1,1597 @@
+/*
+ * 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";
+#endif
+
+#include "common.h"
+
+/*
+ * Local function prototypes
+ */
+
+#if defined(PS_STR_XPORT_DATA)
+static void make_sock(struct pst_fileinfo2 *f, struct pst_stream *sh,
+                      struct pst_socket *s);
+#endif /* defined(PS_STR_XPORT_DATA) */
+
+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(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;
+    char fd[FDLEN];
+
+#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.
+     */
+    Lf->type = LSOF_FILE_SOCKET;
+    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) {
+        Lf->fna = na;
+        Lf->fsv |= FSV_NI;
+    }
+#endif /* defined(HASFSTRUCT) */
+
+    /*
+     * Save size information, as requested.
+     */
+    if (Lf->access == LSOF_FILE_ACCESS_READ)
+        Lf->sz = (SZOFFTYPE)s->pst_idata;
+    else if (Lf->access == LSOF_FILE_ACCESS_WRITE)
+        Lf->sz = (SZOFFTYPE)s->pst_odata;
+    else
+        Lf->sz = (SZOFFTYPE)(s->pst_idata + s->pst_odata);
+    Lf->sz_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;
+#if defined(HASIPv6)
+        Lf->type = LSOF_FILE_IPV4;
+#else  /* !defined(HASIPv6) */
+        Lf->type = LSOF_FILE_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;
+        Lf->type = LSOF_FILE_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;
+        Lf->type = LSOF_FILE_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))) {
+                        fd_to_string(Lf->fd_type, Lf->fd_num, fd);
+                        (void)fprintf(
+                            stderr, "%s: no unix nma space(1): PID %ld, FD %s",
+                            Pn, (long)Lp->pid, 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))) {
+                            fd_to_string(Lf->fd_type, Lf->fd_num, fd);
+                            (void)fprintf(
+                                stderr,
+                                "%s: no unix nma space(2): PID %ld, FD %s", Pn,
+                                (long)Lp->pid, 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;
+    enum lsof_file_type type;
+    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) {
+        Lf->fna = na;
+        Lf->fsv |= FSV_NI;
+    }
+#endif /* defined(HASFSTRUCT) */
+
+    /*
+     * Enter type.
+     */
+    switch (f->psf_ftype) {
+    case PS_TYPE_STREAMS:
+        Lf->type = LSOF_FILE_STREAM;
+        break;
+    case PS_TYPE_SOCKET:
+        if (f->psf_subtype == PS_SUBTYPE_SOCKSTR) {
+            Lf->type = LSOF_FILE_STREAM_SOCKET;
+            break;
+        }
+        /* fall through */
+    default:
+        Lf->type = LSOF_FILE_UNKNOWN_RAW;
+        Lf->unknown_file_type_number = f->psf_ftype;
+    }
+    /*
+     * 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);
+            Error(ctx);
+        }
+        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 (Lf->access == LSOF_FILE_ACCESS_READ) {
+        Lf->sz = (SZOFFTYPE)s[hx].val.head.pst_rbytes;
+        Lf->sz_def = 1;
+    } else if (Lf->access == LSOF_FILE_ACCESS_WRITE) {
+        Lf->sz = (SZOFFTYPE)s[hx].val.head.pst_wbytes;
+        Lf->sz_def = 1;
+    } else if (Lf->access == LSOF_FILE_ACCESS_READ_WRITE) {
+        Lf->sz = (SZOFFTYPE)s[hx].val.head.pst_rbytes +
+                 (SZOFFTYPE)s[hx].val.head.pst_wbytes;
+        Lf->sz_def = 1;
+    }
+    /*
+     * Get 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;
+    /*
+     * 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(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/lib/dialects/hpux/pstat/dstore.c b/lib/dialects/hpux/pstat/dstore.c
new file mode 100644
index 0000000..0966506
--- /dev/null
+++ b/lib/dialects/hpux/pstat/dstore.c
@@ -0,0 +1,66 @@
+/*
+ * 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";
+#endif
+
+#include "common.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/lib/dialects/hpux/pstat/machine.h b/lib/dialects/hpux/pstat/machine.h
new file mode 100644
index 0000000..d70819a
--- /dev/null
+++ b/lib/dialects/hpux/pstat/machine.h
@@ -0,0 +1,590 @@
+/*
+ * 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 access
+ * 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?	*/
+
+/*
+ * 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_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/Makefile b/lib/dialects/linux/Makefile
similarity index 76%
rename from dialects/linux/Makefile
rename to lib/dialects/linux/Makefile
index 46c83c2..f8adaa6 100644
--- a/dialects/linux/Makefile
+++ b/lib/dialects/linux/Makefile
@@ -17,19 +17,19 @@ P=
 CDEF=
 CDEFS=  ${CDEF} ${CFGF}
 DEP=	${CFGD} ${CFGDN}
-INCL=	${DINC}
-CFLAGS=	${CDEFS} ${INCL} ${DEP} ${DEBUG}
+INCL=	${DINC} -Iinclude -Ilib -Isrc -I.
+CFLAGS=	-Wall ${CDEFS} ${INCL} ${DEP} ${DEBUG}
 
 GRP=
 
-HDR=    lsof.h lsof_fields.h dlsof.h machine.h proto.h dproto.h
+HDR=	lib/common.h include/lsof_fields.h dlsof.h machine.h lib/proto.h dproto.h
 
-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 \
+SRC=    dfile.c dmnt.c dnode.c dprint.c dproc.c dsock.c dstore.c \
+	arg.c main.c print.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 \
+OBJ=	dfile.o dmnt.o dnode.o dprint.o dproc.o dsock.o dstore.o \
+	arg.o main.o print.o store.o usage.o \
 	util.o
 
 MAN=	lsof.8
@@ -56,7 +56,7 @@ clean: FRC
 	rm -f machine.h.old new_machine.h
 	(cd lib; ${MAKE} -f Makefile.skel clean)
 	(cd tests; ${MAKE} clean)
-	(cd dialects/linux/tests; ${MAKE} clean)
+	(cd lib/dialects/linux/tests; ${MAKE} clean)
 
 install: all FRC
 	@echo ''
@@ -89,7 +89,11 @@ version.h:	FRC
 	@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; \
+	  if [ "X${SOURCE_DATE_EPOCH}" = "X" ]; then \
+	    echo '#define	LSOF_HOST	"'`uname -n`'"' >> version.h; \
+	  else \
+	    echo '#define	LSOF_HOST	""' >> version.h; \
+	  fi \
 	else \
 	  if [ "${LSOF_HOST}" = "none" ]; then \
 	    echo '#define	LSOF_HOST	""' >> version.h; \
@@ -99,7 +103,11 @@ version.h:	FRC
 	fi
 	@echo '#define	LSOF_LDFLAGS	"${CFGL}"' >> version.h
 	@if [ "X${LSOF_LOGNAME}" = "X" ]; then \
-	  echo '#define	LSOF_LOGNAME	"${LOGNAME}"' >> version.h; \
+	  if [ "X${SOURCE_DATE_EPOCH}" = "X" ]; then \
+	    echo '#define	LSOF_LOGNAME	"${LOGNAME}"' >> version.h; \
+	  else \
+	    echo '#define	LSOF_LOGNAME	""' >> version.h; \
+	  fi \
 	else \
 	  if [ "${LSOF_LOGNAME}" = "none" ]; then \
 	    echo '#define	LSOF_LOGNAME	""' >> version.h; \
@@ -108,7 +116,11 @@ version.h:	FRC
 	  fi; \
 	fi
 	@if [ "X${LSOF_SYSINFO}" = "X" ]; then \
+	  if [ "X${SOURCE_DATE_EPOCH}" = "X" ]; then \
 	    echo '#define	LSOF_SYSINFO	"'`uname -a`'"' >> version.h; \
+	  else \
+	    echo '#define	LSOF_SYSINFO	""' >> version.h; \
+	  fi \
 	else \
 	  if [ "${LSOF_SYSINFO}" = "none" ]; then \
 	    echo '#define	LSOF_SYSINFO	""' >> version.h; \
@@ -117,7 +129,11 @@ version.h:	FRC
 	  fi \
 	fi
 	@if [ "X${LSOF_USER}" = "X" ]; then \
-	  echo '#define	LSOF_USER	"${USER}"' >> version.h; \
+	  if [ "X${SOURCE_DATE_EPOCH}" = "X" ]; then \
+	    echo '#define	LSOF_USER	"${USER}"' >> version.h; \
+	  else \
+	    echo '#define	LSOF_USER	""' >> version.h; \
+	  fi \
 	else \
 	  if [ "${LSOF_USER}" = "none" ]; then \
 	    echo '#define	LSOF_USER	""' >> version.h; \
diff --git a/lib/dialects/linux/Mksrc b/lib/dialects/linux/Mksrc
new file mode 100755
index 0000000..57a6f89
--- /dev/null
+++ b/lib/dialects/linux/Mksrc
@@ -0,0 +1,37 @@
+#!/bin/bash
+#
+# Mksrc - make Linux source files for /proc-based lsof
+#
+# 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.2 2000/12/04 14:31:02 abe Exp $
+
+mksrc() {
+  for i in $L
+  do
+    rm -f $i
+    $LSOF_MKC $D/$i $i
+    echo "$LSOF_MKC $D/$i $i"
+  done
+}
+
+D=lib/dialects/linux
+L="dfile.c dlsof.h dmnt.c dnode.c dproc.c dproto.h dsock.c dstore.c machine.h"
+
+mksrc
+
+D=src
+L="arg.c main.c print.c ptti.c store.c usage.c util.c"
+
+mksrc
+
+D=src/dialects/linux
+L="dprint.c"
+
+mksrc
diff --git a/lib/dialects/linux/dfile.c b/lib/dialects/linux/dfile.c
new file mode 100644
index 0000000..dbd6c00
--- /dev/null
+++ b/lib/dialects/linux/dfile.c
@@ -0,0 +1,347 @@
+/*
+ * dfile.c - Linux file processing functions for /proc-based lsof
+ */
+
+/*
+ * 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.
+ */
+
+#include "common.h"
+
+/*
+ * Local structures
+ */
+
+/*
+ * Local static variables
+ */
+
+
+/*
+ * Local definitions
+ */
+
+#define SFDIHASH                                                               \
+    4094 /* Sfile hash by (device,inode) number                                \
+          * pair bucket count (power of 2!) */
+#define SFFSHASH                                                               \
+    1024 /* Sfile hash by file system device                                   \
+          * number bucket count (power of 2!) */
+/* hash for Sfile by major device,
+ * minor device, and inode, modulo mod
+ * (mod must be a power of 2) */
+#define SFHASHDEVINO(maj, min, ino, mod)                                       \
+    ((int)(((int)((((int)(maj + 1)) * ((int)((min + 1)))) + ino) * 31415) &    \
+           (mod - 1)))
+#define SFRDHASH                                                               \
+    1024 /* Sfile hash by raw device number                                    \
+          * bucket count (power of 2!) */
+/* 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) */
+#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)))
+#define SFNMHASH                                                               \
+    4096 /* Sfile hash by name bucket count                                    \
+          * (must be a power of 2!) */
+
+/*
+ * hashSfile() - hash Sfile entries for use in is_file_named() searches
+ */
+void hashSfile(struct lsof_context *ctx) {
+    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, 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);
+        Error(ctx);
+    }
+    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);
+        Error(ctx);
+    }
+    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);
+        Error(ctx);
+    }
+    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);
+        Error(ctx);
+    }
+    hs++;
+    /*
+     * Scan the Sfile chain, building file, file system, raw device, and file
+     * name hash bucket chains.
+     */
+    for (s = Sfile; s; s = s->next) {
+        for (i = 0; i < 3; i++) {
+            switch (i) {
+            case 0: /* hash by name */
+                if (!s->aname)
+                    continue;
+                sh = &HbyNm[hashbyname(s->aname, SFNMHASH)];
+                HbyNmCt++;
+                break;
+            case 1: /* hash by device and inode, or file
+                     * system device */
+                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++;
+                }
+                break;
+            case 2: /* hash by file's raw device */
+                if ((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;
+            }
+            /*
+             * Add hash to the bucket's chain, allocating new entries for
+             * all after the first.
+             */
+            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);
+                    Error(ctx);
+                }
+                sn->s = s;
+                sn->next = sh->next;
+                sh->next = sn;
+            }
+        }
+    }
+}
+
+/*
+ * is_file_named() - is this file named?
+ */
+int is_file_named(
+    /* context */
+    struct lsof_context *ctx,
+    /* search type:	0 = only by device
+     *		    and inode
+     *		1 = by device and
+     *		    inode, or by file
+     *		    system device and
+     *		    path for NFS file
+     *		    systems
+     *		2 = only by path
+     */
+    int search_type,
+    /* path name (device and inode are
+     * identified via *Lf) */
+    char *path,
+    /* NFS file system (NULL if not) */
+    struct mounts *nfs_mount,
+    /* character or block type file --
+     * VCHR or VBLK vnode, or S_IFCHR
+     * or S_IFBLK inode */
+    int cd) {
+    char *ep;
+    int f = 0;
+    struct mounts *smp;
+    struct sfile *s = (struct sfile *)NULL;
+    struct hsfile *sh;
+    size_t sz;
+
+    /*
+     * Check for a path name match, as requested.
+     */
+    if ((search_type == 2) && path && HbyNmCt) {
+        for (sh = &HbyNm[hashbyname(path, SFNMHASH)]; sh; sh = sh->next) {
+            if ((s = sh->s) && strcmp(path, s->aname) == 0) {
+                f = 2; /* Found match by path */
+                break;
+            }
+        }
+    }
+
+    /*
+     * Check for a regular file by device and inode number.
+     */
+    if (!f && (search_type < 2) && 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; /* Found match by inode and dev */
+                break;
+            }
+        }
+    }
+
+    /*
+     * Check for a file system match.
+     */
+    if (!f && (search_type == 1) && 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) && (s->dev == Lf->dev)) {
+                if (Lf->ntype != N_NFS) {
+
+                    /*
+                     * A non-NFS file matches to a non-NFS file system by
+                     * device.
+                     */
+                    if (!(smp = s->mp) || (smp->ty != N_NFS)) {
+                        f = 1; /* Found match by fs */
+                        break;
+                    }
+                } else {
+
+                    /*
+                     * An NFS file must also match to a file system by the
+                     * the path name of the file system -- i.e., the first
+                     * part of the file's path.  This terrible, non-UNIX
+                     * hack is forced on lsof by an egregious error in
+                     * Linux NFS that can assign the same device number
+                     * to two different NFS mounts.
+                     */
+                    if (path && nfs_mount && nfs_mount->dirl &&
+                        nfs_mount->dir && s->name &&
+                        !strncmp(nfs_mount->dir, s->name, nfs_mount->dirl)) {
+                        f = 1; /* Found match by fs */
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    /*
+     * Check for a character or block device match.
+     */
+    if (!f && !search_type && HbyFrdCt && cd && 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; /* Found match by inode and dev */
+                break;
+            }
+        }
+    }
+    /*
+     * Convert the name if a match occurred.
+     */
+    switch (f) {
+    case 0: /* Not found */
+        return (0);
+    case 1: /* Found match by inode and dev or fs */
+        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 (s->devnm) {
+                ep = endnm(ctx, &sz);
+                (void)snpf(ep, sz, " (%s)", s->devnm);
+            }
+        }
+        break;
+    case 2: /* Found match by path */
+        (void)strcpy(Namech, path);
+        break;
+    }
+    if (s)
+        s->f = 1;
+    return (1);
+}
+
+/*
+ * printdevname() - print character device name
+ *
+ * Note: this function should not be needed in /proc-based lsof, but
+ *	 since it is called by printname() in print.c, an ersatz one
+ *	 is provided here.
+ */
+int printdevname(struct lsof_context *ctx, /* context */
+                 dev_t *dev,               /* device */
+                 dev_t *rdev,              /* raw device */
+                 int newline,              /* 1 = follow with '\n' */
+                 int node_type)            /* node type: N_BLK or N_chr */
+{
+    char buf[128];
+
+    (void)snpf(buf, sizeof(buf), "%s device: %d,%d",
+               (node_type == N_BLK) ? "BLK" : "CHR", (int)GET_MAJ_DEV(*rdev),
+               (int)GET_MIN_DEV(*rdev));
+    safestrprt(buf, stdout, newline);
+    return (1);
+}
diff --git a/lib/dialects/linux/dlsof.h b/lib/dialects/linux/dlsof.h
new file mode 100644
index 0000000..f4504a6
--- /dev/null
+++ b/lib/dialects/linux/dlsof.h
@@ -0,0 +1,203 @@
+/*
+ * dlsof.h - Linux header file for /proc-based lsof
+ */
+
+/*
+ * 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.
+ */
+
+/*
+ * $Id: dlsof.h,v 1.23 2015/07/07 19:46:33 abe Exp $
+ */
+
+#if !defined(LINUX_LSOF_H)
+#    define LINUX_LSOF_H 1
+
+#    include <dirent.h>
+#    define DIRTYPE dirent /* for arg.c's enter_dir() */
+#    define __USE_GNU      /* to get all O_* symbols in fcntl.h */
+#    include <fcntl.h>
+#    include <malloc.h>
+#    include <signal.h>
+#    include <stdlib.h>
+#    include <string.h>
+#    include <setjmp.h>
+#    include <unistd.h>
+#    include <netinet/in.h>
+
+#    if defined(GLIBCV) || defined(__UCLIBC__) || defined(NEEDS_NETINET_TCPH)
+#        include <netinet/tcp.h>
+#    else /* !defined(GLIBCV) && !defined(__UCLIBC__) &&                       \
+             !defined(NEEDS_NETINET_TCPH) */
+#        include <linux/tcp.h>
+#    endif /* defined(GLIBCV) || defined(__UCLIBC__) ||                        \
+              defined(NEEDS_NETINET_TCPH) */
+
+#    if !defined(HASNORPC_H)
+#        include <rpc/rpc.h>
+#        include <rpc/pmap_prot.h>
+#    endif /* !defined(HASNORPC_H) */
+
+#    if defined(HASSELINUX)
+#        include <selinux/selinux.h>
+#    endif /* defined(HASSELINUX) */
+
+#    include <sys/sysmacros.h>
+#    include <sys/socket.h>
+#    include <arpa/inet.h>
+#    include <linux/if_ether.h>
+#    include <linux/netlink.h>
+
+#    include <sys/syscall.h>
+
+/*
+ * This definition is needed for the common function prototype definitions
+ * in "proto.h", but isn't used in /proc-based lsof.
+ */
+
+typedef unsigned long KA_T;
+
+/*
+ * Local definitions
+ */
+
+#    define COMP_P const void
+#    define DEVINCR 1024 /* device table malloc() increment */
+#    define FSNAMEL 4
+#    define MALLOC_P void
+#    define FREE_P MALLOC_P
+#    define MALLOC_S size_t
+#    define MAXSYSCMDL                                                         \
+        15 /* max system command name length                                   \
+            *   This value should be obtained from a                           \
+            * header file #define, but no consistent one                       \
+            * exists.  Some versions of the Linux kernel                       \
+            * have a hard-coded "char comm[16]" command                        \
+            * name member of the task structured                               \
+            * definition in <linux/sched.h>, while others                      \
+            * have a "char comm[TASK_COMM_LEN]" member                         \
+            * with TASK_COMM_LEN #define'd to be 16.                           \
+            *   Hence, a universal, local definition of                        \
+            * 16 is #define'd here. */
+#    define PROCFS "/proc"
+#    define QSORT_P void
+#    define READLEN_T size_t
+
+/*
+ * Definitions that indicate what values are present in a stat(2) or lstat(2)
+ * buffer.
+ */
+
+#    define SB_DEV 0x01   /* st_dev */
+#    define SB_INO 0x02   /* st_ino */
+#    define SB_MODE 0x04  /* st_mode */
+#    define SB_NLINK 0x08 /* st_nlink */
+#    define SB_RDEV 0x10  /* st_rdev */
+#    define SB_SIZE 0x20  /* st_size */
+#    define SB_ALL                                                             \
+        (SB_DEV | SB_INO | SB_MODE | SB_NLINK | SB_RDEV |                      \
+         SB_SIZE) /* all values                                                \
+                   */
+
+#    define STRNCPY_L size_t
+#    define STRNML 32
+
+#    if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64
+/* size and offset internal storage
+ * type */
+#        define SZOFFTYPE unsigned long long
+#        define SZOFFPSPEC                                                     \
+            "ll" /* SZOFFTYPE print specification                              \
+                  * modifier */
+#    endif       /* defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS==64 */
+
+#    define XDR_PMAPLIST (xdrproc_t) xdr_pmaplist
+#    define XDR_VOID (xdrproc_t) xdr_void
+
+/*
+ * Global storage definitions (including their structure definitions)
+ */
+
+struct mounts {
+    char *dir;           /* directory name (mounted on) */
+    char *fsname;        /* file system
+                          * (symbolic links unresolved) */
+    char *fsnmres;       /* file system
+                          * (symbolic links resolved) */
+    size_t dirl;         /* length of directory name */
+    dev_t dev;           /* directory st_dev */
+    dev_t rdev;          /* directory st_rdev */
+    INODETYPE inode;     /* directory st_ino */
+    mode_t mode;         /* directory st_mode */
+    int ds;              /* directory status -- i.e., SB_*
+                          * values */
+    mode_t fs_mode;      /* file system st_mode */
+    int ty;              /* node type -- e.g., N_REGLR, N_NFS */
+    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 */
+    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 mounts *mp;         /* mount structure pointer for file
+                                * system type entries */
+#    define SAVE_MP_IN_SFILE 1 /* for ck_file_arg() im arg.c */
+    struct sfile *next;        /* forward link */
+};
+
+#    if defined(HASEPTOPTS)
+typedef struct pxinfo {  /* hashed pipe, UNIX socket or pseudo-
+                          * terminal inode information */
+    INODETYPE ino;       /* file's inode */
+    struct lfile *lf;    /* connected peer file */
+    int lpx;             /* connected process index */
+    struct pxinfo *next; /* next entry for hashed inode */
+} pxinfo_t;
+#    endif /* defined(HASEPTOPTS) */
+
+extern int HasNFS;
+extern dev_t MqueueDev;
+
+/* offset type:
+ *     0 == unknown
+ *     1 == lstat's st_size
+ *     2 == from /proc/<PID>/fdinfo
+ */
+#    define OFFSET_UNKNOWN 0
+#    define OFFSET_LSTAT 1
+#    define OFFSET_FDINFO 2
+extern int OffType;
+
+struct lsof_context_dialect {};
+
+#endif /* LINUX_LSOF_H	*/
diff --git a/lib/dialects/linux/dmnt.c b/lib/dialects/linux/dmnt.c
new file mode 100644
index 0000000..9d3fa21
--- /dev/null
+++ b/lib/dialects/linux/dmnt.c
@@ -0,0 +1,696 @@
+/*
+ * dmnt.c -- Linux mount support functions for /proc-based lsof
+ */
+
+/*
+ * 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.
+ */
+
+#include "common.h"
+
+/*
+ * Local definitions
+ */
+
+#if defined(HASMNTSUP)
+#    define HASHMNT                                                            \
+        128 /* mount supplement hash bucket count                              \
+             * !!!MUST BE A POWER OF 2!!! */
+#endif      /* defined(HASMNTSUP) */
+
+/*
+ * Local function prototypes
+ */
+
+static char *convert_octal_escaped(struct lsof_context *ctx, char *orig_str);
+
+#if defined(HASMNTSUP)
+static int getmntdev(struct lsof_context *ctx, char *dir_name,
+                     size_t dir_name_len, struct stat *s, int *ss);
+static int hash_mnt(char *dir_name);
+#endif /* defined(HASMNTSUP) */
+
+/*
+ * Local structure definitions.
+ */
+
+#if defined(HASMNTSUP)
+typedef struct mntsup {
+    char *dir_name;      /* mounted directory name */
+    size_t dir_name_len; /* strlen(dir_name) */
+    dev_t dev;           /* device number */
+    int ln;              /* line on which defined */
+    struct mntsup *next; /* next entry */
+} mntsup_t;
+#endif /* defined(HASMNTSUP) */
+
+/*
+ * Local static definitions
+ */
+
+static mntsup_t **MSHash = (mntsup_t **)NULL;      /* mount supplement
+                                                    * hash buckets */
+
+/*
+ * convert_octal_escaped() -- convert octal-escaped characters in string
+ */
+static char *convert_octal_escaped(struct lsof_context *ctx, /* context */
+                                   char *orig_str /* original string */) {
+    int cur_ch, cvt_len, cvt_idx, orig_len, orig_idx, temp_idx;
+    char *cvt_str;
+    int temp_ch;
+    /*
+     * Allocate space for a copy of the string in which octal-escaped characters
+     * can be replaced by the octal value -- e.g., \040 with ' '.  Leave room
+     * for a '\0' terminator.
+     */
+    if (!(orig_len = (int)strlen(orig_str)))
+        return ((char *)NULL);
+    if (!(cvt_str = (char *)malloc(orig_len + 1))) {
+        (void)fprintf(stderr,
+                      "%s: can't allocate %d bytes for octal-escaping.\n", Pn,
+                      orig_len + 1);
+        Error(ctx);
+    }
+    /*
+     * Copy the string, replacing octal-escaped characters as they are found.
+     */
+    for (cvt_idx = orig_idx = 0, cvt_len = orig_len; orig_idx < orig_len;
+         orig_idx++) {
+        if (((cur_ch = (int)orig_str[orig_idx]) == (int)'\\') &&
+            ((orig_idx + 3) < orig_len)) {
+
+            /*
+             * The beginning of an octal-escaped character has been found.
+             *
+             * Convert the octal value to a character value.
+             */
+            for (temp_ch = 0, temp_idx = 1;
+                 orig_str[orig_idx + temp_idx] && (temp_idx < 4); temp_idx++) {
+                if (((int)orig_str[orig_idx + temp_idx] < (int)'0') ||
+                    ((int)orig_str[orig_idx + temp_idx] > (int)'7')) {
+
+                    /*
+                     * The escape isn't followed by octets, so ignore the
+                     * escape and just copy it.
+                     */
+                    break;
+                }
+                temp_ch <<= 3;
+                temp_ch += (int)(orig_str[orig_idx + temp_idx] - '0');
+            }
+            if (temp_idx == 4) {
+
+                /*
+                 * If three octets (plus the escape) were assembled, use their
+                 * character-forming result.
+                 *
+                 * Otherwise copy the escape and what follows it until another
+                 * escape is found.
+                 */
+                orig_idx += 3;
+                cur_ch = (temp_ch & 0xff);
+            }
+        }
+
+        if (cvt_idx >= cvt_len) {
+            /*
+             * Expand the copy string, as required.  Leave room for a '\0'
+             * terminator.
+             */
+            cvt_len += 64; /* (Make an arbitrary increase.) */
+            if (!(cvt_str = (char *)realloc(cvt_str, cvt_len + 1))) {
+                (void)fprintf(
+                    stderr, "%s: can't realloc %d bytes for octal-escaping.\n",
+                    Pn, cvt_len + 1);
+                Error(ctx);
+            }
+        }
+
+        /*
+         * Copy the character.
+         */
+        cvt_str[cvt_idx++] = (char)cur_ch;
+    }
+
+    /*
+     * Terminate the copy and return its pointer.
+     */
+    cvt_str[cvt_idx] = '\0';
+    return (cvt_str);
+}
+
+#if defined(HASMNTSUP)
+/*
+ * getmntdev() - get mount device from mount supplement
+ */
+static int
+getmntdev(struct lsof_context *ctx, /* context */
+      char *dir_name,               /* mounted directory name */
+      size_t dir_name_len,          /* strlen(dir_name) */
+      struct stat *s,               /* stat(2) buffer receptor */
+      int *ss                       /* stat(2) status result -- i.e., SB_*
+                                     * values */)
+{
+    static int err = 0;
+    int h;
+    mntsup_t *mp, *mpn;
+    static char *vbuf = (char *)NULL;
+    static size_t vsz = (size_t)0;
+
+    if (err)
+        return (0);
+    if (!MSHash) {
+
+        /*
+         * No mount supplement hash buckets have been allocated, so read the
+         * mount supplement file and create hash buckets for its entries.
+         */
+        char buf[(MAXPATHLEN * 2) + 1], *dp, path[(MAXPATHLEN * 2) + 1];
+        dev_t dev;
+        FILE *fs;
+        int ln = 0;
+        size_t sz;
+
+        if ((MntSup != 2) || !MntSupP)
+            return (0);
+        if (!is_readable(ctx, MntSupP, 1)) {
+
+            /*
+             * The mount supplement file isn't readable.
+             */
+            err = 1;
+            return (0);
+        }
+        if (!(fs = open_proc_stream(ctx, MntSupP, "r", &vbuf, &vsz, 0))) {
+
+            /*
+             * The mount supplement file can't be opened for reading.
+             */
+            if (!Fwarn)
+                (void)fprintf(stderr, "%s: can't open(%s): %s\n", Pn, MntSupP,
+                              strerror(errno));
+            err = 1;
+            return (0);
+        }
+        buf[sizeof(buf) - 1] = '\0';
+        /*
+         * Read the mount supplement file.
+         */
+        while (fgets(buf, sizeof(buf) - 1, fs)) {
+            ln++;
+            if ((dp = strchr(buf, '\n')))
+                *dp = '\0';
+            if (buf[0] != '/') {
+
+                /*
+                 * The mount supplement line doesn't begin with the absolute
+                 * path character '/'.
+                 */
+                if (!Fwarn)
+                    (void)fprintf(stderr, "%s: %s line %d: no path: \"%s\"\n",
+                                  Pn, MntSupP, ln, buf);
+                err = 1;
+                continue;
+            }
+            if (!(dp = strchr(buf, ' ')) || strncmp(dp + 1, "0x", 2)) {
+
+                /*
+                 * The path on the mount supplement line isn't followed by
+                 * " 0x".
+                 */
+                if (!Fwarn)
+                    (void)fprintf(stderr, "%s: %s line %d: no device: \"%s\"\n",
+                                  Pn, MntSupP, ln, buf);
+                err = 1;
+                continue;
+            }
+            sz = (size_t)(dp - buf);
+            (void)strncpy(path, buf, sz);
+            path[sz] = '\0';
+            /*
+             * Assemble the hexadecimal device number of the mount supplement
+             * line.
+             */
+            for (dev = 0, dp += 3; *dp; dp++) {
+                if (!isxdigit((int)*dp))
+                    break;
+                if (isdigit((int)*dp))
+                    dev = (dev << 4) + (int)*dp - (int)'0';
+                else
+                    dev = (dev << 4) + (int)tolower(*dp) - (int)'a' + 10;
+            }
+            if (*dp) {
+
+                /*
+                 * The device number couldn't be assembled.
+                 */
+                if (!Fwarn)
+                    (void)fprintf(stderr,
+                                  "%s: %s line %d: illegal device: \"%s\"\n",
+                                  Pn, MntSupP, ln, buf);
+                err = 1;
+                continue;
+            }
+            /*
+             * Search the mount supplement hash buckets.  (Allocate them as
+             * required.)
+             */
+            if (!MSHash) {
+                if (!(MSHash =
+                          (mntsup_t **)calloc(HASHMNT, sizeof(mntsup_t *)))) {
+                    (void)fprintf(
+                        stderr,
+                        "%s: no space for mount supplement hash buckets\n", Pn);
+                    Error(ctx);
+                }
+            }
+            h = hash_mnt(path);
+            for (mp = MSHash[h]; mp; mp = mp->next) {
+                if ((mp->dir_name_len == dir_name_len) &&
+                    !strcmp(mp->dir_name, path))
+                    break;
+            }
+            if (mp) {
+
+                /*
+                 * A path match was located.  If the device number is the
+                 * same, skip this mount supplement line.  Otherwise, issue
+                 * a warning.
+                 */
+                if (mp->dev != dev) {
+                    (void)fprintf(
+                        stderr, "%s: %s line %d path duplicate of %d: \"%s\"\n",
+                        Pn, MntSupP, ln, mp->ln, buf);
+                    err = 1;
+                }
+                continue;
+            }
+            /*
+             * Allocate and fill a new mount supplement hash entry.
+             */
+            if (!(mpn = (mntsup_t *)malloc(sizeof(mntsup_t)))) {
+                (void)fprintf(
+                    stderr,
+                    "%s: no space for mount supplement entry: %d \"%s\"\n", Pn,
+                    ln, buf);
+                Error(ctx);
+            }
+            if (!(mpn->dir_name = (char *)malloc(sz + 1))) {
+                (void)fprintf(
+                    stderr,
+                    "%s: no space for mount supplement path: %d \"%s\"\n", Pn,
+                    ln, buf);
+                Error(ctx);
+            }
+            (void)strcpy(mpn->dir_name, path);
+            mpn->dir_name_len = sz;
+            mpn->dev = dev;
+            mpn->ln = ln;
+            mpn->next = MSHash[h];
+            MSHash[h] = mpn;
+        }
+        if (ferror(fs)) {
+            if (!Fwarn)
+                (void)fprintf(stderr, "%s: error reading %s\n", Pn, MntSupP);
+            err = 1;
+        }
+        (void)fclose(fs);
+        if (err) {
+            if (MSHash) {
+                for (h = 0; h < HASHMNT; h++) {
+                    for (mp = MSHash[h]; mp; mp = mpn) {
+                        mpn = mp->next;
+                        if (mp->dir_name)
+                            (void)free((MALLOC_P *)mp->dir_name);
+                        (void)free((MALLOC_P *)mp);
+                    }
+                }
+                (void)free((MALLOC_P *)MSHash);
+                MSHash = (mntsup_t **)NULL;
+            }
+            return (0);
+        }
+    }
+
+    /*
+     * If no errors have been detected reading the mount supplement file, search
+     * its hash buckets for the supplied directory path.
+     */
+    if (err)
+        return (0);
+    h = hash_mnt(dir_name);
+    for (mp = MSHash[h]; mp; mp = mp->next) {
+        if ((dir_name_len == mp->dir_name_len) &&
+            !strcmp(dir_name, mp->dir_name)) {
+            zeromem((char *)s, sizeof(struct stat));
+            s->st_dev = mp->dev;
+            *ss |= SB_DEV;
+            return (1);
+        }
+    }
+    return (0);
+}
+
+/*
+ * hash_mnt() - hash mount point
+ */
+static int hash_mnt(char *dir_name /* mount point directory name */) {
+    register int i, h;
+    size_t l;
+
+    if (!(l = strlen(dir_name)))
+        return (0);
+    if (l == 1)
+        return ((int)*dir_name & (HASHMNT - 1));
+    for (i = h = 0; i < (int)(l - 1); i++) {
+        h ^= ((int)dir_name[i] * (int)dir_name[i + 1]) << ((i * 3) % 13);
+    }
+    return (h & (HASHMNT - 1));
+}
+#endif /* defined(HASMNTSUP) */
+
+/*
+ * readmnt() - read mount table
+ */
+struct mounts *readmnt(struct lsof_context *ctx) {
+    char buf[MAXPATHLEN], *cp, **fp;
+    char *dn = (char *)NULL;
+    size_t dnl;
+    int ds, ne;
+    char *fp0 = (char *)NULL;
+    char *fp1 = (char *)NULL;
+    int fr, ignrdl, ignstat;
+    char *ln;
+    struct mounts *mp;
+    FILE *ms;
+    int nfs;
+    int mqueue;
+    struct stat sb;
+    static char *vbuf = (char *)NULL;
+    static size_t vsz = (size_t)0;
+
+    if (Lmi || Lmist)
+        return (Lmi);
+    /*
+     * Open access to /proc/mounts, assigning a page size buffer to its stream.
+     */
+    (void)snpf(buf, sizeof(buf), "%s/mounts", PROCFS);
+    ms = open_proc_stream(ctx, buf, "r", &vbuf, &vsz, 1);
+    /*
+     * Read mount table entries.
+     */
+    while (fgets(buf, sizeof(buf), ms)) {
+        if (get_fields(ctx, buf, (char *)NULL, &fp, (int *)NULL, 0) < 3 ||
+            !fp[0] || !fp[1] || !fp[2])
+            continue;
+        /*
+         * Convert octal-escaped characters in the device name and mounted-on
+         * path name.
+         */
+        if (fp0) {
+            (void)free((FREE_P *)fp0);
+            fp0 = (char *)NULL;
+        }
+        if (fp1) {
+            (void)free((FREE_P *)fp1);
+            fp1 = (char *)NULL;
+        }
+        if (!(fp0 = convert_octal_escaped(ctx, fp[0])) ||
+            !(fp1 = convert_octal_escaped(ctx, fp[1])))
+            continue;
+        /*
+         * Locate any colon (':') in the device name.
+         *
+         * If the colon is followed by * "(pid*" -- it's probably an
+         * automounter entry.
+         *
+         * Ignore autofs, pipefs, and sockfs entries.
+         */
+        cp = strchr(fp0, ':');
+        if (cp && !strncasecmp(++cp, "(pid", 4))
+            continue;
+        if (!strcasecmp(fp[2], "autofs") || !strcasecmp(fp[2], "pipefs") ||
+            !strcasecmp(fp[2], "sockfs"))
+            continue;
+
+        /*
+         * Interpolate a possible symbolic mounted directory link.
+         */
+        if (dn)
+            (void)free((FREE_P *)dn);
+        dn = fp1;
+        fp1 = (char *)NULL;
+
+#if defined(HASEOPT)
+        if (Efsysl) {
+
+            /*
+             * If there is an -e file system list, check it to decide if a
+             * stat() and Readlink() on this one should be performed.
+             */
+            efsys_list_t *ep;
+
+            for (ignrdl = ignstat = 0, ep = Efsysl; ep; ep = ep->next) {
+                if (!strcmp(dn, ep->path)) {
+                    ignrdl = ep->rdlnk;
+                    ignstat = 1;
+                    break;
+                }
+            }
+        } else
+
+#endif /* defined(HASEOPT */
+
+            ignrdl = ignstat = 0;
+
+        /*
+         * Avoid Readlink() when requested.
+         */
+        if (!ignrdl) {
+            if (!(ln = Readlink(ctx, 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;
+        dnl = strlen(dn);
+
+        /*
+         * Test Mqueue directory
+         */
+        mqueue = strcmp(fp[2], "mqueue");
+
+        /*
+         * Test for duplicate and NFS directories.
+         */
+        for (mp = Lmi; mp; mp = mp->next) {
+            if ((dnl == mp->dirl) && !strcmp(dn, mp->dir))
+                break;
+        }
+        if ((nfs = strcasecmp(fp[2], "nfs"))) {
+            if ((nfs = strcasecmp(fp[2], "nfs3")))
+                nfs = strcasecmp(fp[2], "nfs4");
+        }
+        if (!nfs && !HasNFS)
+            HasNFS = 1;
+        if (mp) {
+
+            /*
+             * If this duplicate directory is not root, ignore it.  If the
+             * already remembered entry is NFS-mounted, ignore this one.  If
+             * this one is NFS-mounted, ignore the already remembered entry.
+             */
+            if (strcmp(dn, "/"))
+                continue;
+            if (mp->ty == N_NFS)
+                continue;
+            if (nfs)
+                continue;
+        }
+
+        /*
+         * Stat() the directory.
+         */
+        if (ignstat)
+            fr = 1;
+        else {
+            if ((fr = statsafely(ctx, dn, &sb))) {
+                if (!Fwarn) {
+                    (void)fprintf(stderr, "%s: WARNING: can't stat() ", Pn);
+                    safestrprt(fp[2], stderr, 0);
+                    (void)fprintf(stderr, " file system ");
+                    safestrprt(dn, stderr, 1);
+                    (void)fprintf(
+                        stderr,
+                        "      Output information may be incomplete.\n");
+                }
+            } else
+                ds = SB_ALL;
+        }
+
+#if defined(HASMNTSUP)
+        if (fr) {
+
+            /*
+             * If the stat() failed or wasn't called, check the mount
+             * supplement table, if possible.
+             */
+            if ((MntSup == 2) && MntSupP) {
+                ds = 0;
+                if (getmntdev(ctx, dn, dnl, &sb, &ds) || !(ds & SB_DEV)) {
+                    (void)fprintf(stderr,
+                                  "%s: assuming dev=%#lx for %s from %s\n", Pn,
+                                  (long)sb.st_dev, dn, MntSupP);
+                }
+            } else {
+                if (!ignstat)
+                    continue;
+                ds = 0; /* No stat() was allowed. */
+            }
+        }
+#else  /* !defined(HASMNTSUP) */
+        if (fr) {
+            if (!ignstat)
+                continue;
+            ds = 0; /* No stat() was allowed. */
+        }
+#endif /* defined(HASMNTSUP) */
+
+        /*
+         * Fill a local mount structure or reuse a previous entry when
+         * indicated.
+         */
+        if (mp) {
+            ne = 0;
+            if (mp->dir) {
+                (void)free((FREE_P *)mp->dir);
+                mp->dir = (char *)NULL;
+            }
+            if (mp->fsname) {
+                (void)free((FREE_P *)mp->fsname);
+                mp->fsname = (char *)NULL;
+            }
+        } else {
+            ne = 1;
+            if (!(mp = (struct mounts *)malloc(sizeof(struct mounts)))) {
+                (void)fprintf(stderr,
+                              "%s: can't allocate mounts struct for: ", Pn);
+                safestrprt(dn, stderr, 1);
+                Error(ctx);
+            }
+        }
+        mp->dir = dn;
+        dn = (char *)NULL;
+        mp->dirl = dnl;
+        if (ne)
+            mp->next = Lmi;
+        mp->dev = ((mp->ds = ds) & SB_DEV) ? sb.st_dev : 0;
+        mp->rdev = (ds & SB_RDEV) ? sb.st_rdev : 0;
+        mp->inode = (INODETYPE)((ds & SB_INO) ? sb.st_ino : 0);
+        mp->mode = (ds & SB_MODE) ? sb.st_mode : 0;
+        if (!nfs) {
+            mp->ty = N_NFS;
+            if (HasNFS < 2)
+                HasNFS = 2;
+        } else if (!mqueue) {
+            mp->ty = N_MQUEUE;
+            MqueueDev = mp->dev;
+        } else {
+            mp->ty = N_REGLR;
+        }
+
+#if defined(HASMNTSUP)
+        /*
+         * If support for the mount supplement file is defined and if the
+         * +m option was supplied, print mount supplement information.
+         */
+        if (MntSup == 1) {
+            if (mp->dev)
+                (void)printf("%s %#lx\n", mp->dir, (long)mp->dev);
+            else
+                (void)printf("%s 0x0\n", mp->dir);
+        }
+#endif /* defined(HASMNTSUP) */
+
+        /*
+         * Save mounted-on device or directory name.
+         */
+        dn = fp0;
+        fp0 = (char *)NULL;
+        mp->fsname = dn;
+
+        /*
+         * Interpolate a possible file system (mounted-on) device name or
+         * directory name link.
+         *
+         * Avoid Readlink() when requested.
+         */
+        if (ignrdl || (*dn != '/')) {
+            if (!(ln = mkstrcpy(dn, (MALLOC_S *)NULL))) {
+                (void)fprintf(stderr, "%s: can't allocate space for: ", Pn);
+                safestrprt(dn, stderr, 1);
+                Error(ctx);
+            }
+            ignstat = 1;
+        } else
+            ln = Readlink(ctx, dn);
+        dn = (char *)NULL;
+
+        /*
+         * Stat() the file system (mounted-on) name and add file system
+         * information to the local mount table entry.
+         */
+        if (ignstat || !ln || statsafely(ctx, ln, &sb))
+            sb.st_mode = 0;
+        mp->fsnmres = ln;
+        ln = NULL;
+        mp->fs_mode = sb.st_mode;
+        if (ne)
+            Lmi = mp;
+    }
+
+    /*
+     * Clean up and return the local mount info table address.
+     */
+    (void)fclose(ms);
+    if (dn)
+        (void)free((FREE_P *)dn);
+    if (fp0)
+        (void)free((FREE_P *)fp0);
+    if (fp1)
+        (void)free((FREE_P *)fp1);
+    Lmist = 1;
+    return (Lmi);
+}
diff --git a/lib/dialects/linux/dnode.c b/lib/dialects/linux/dnode.c
new file mode 100644
index 0000000..725c52e
--- /dev/null
+++ b/lib/dialects/linux/dnode.c
@@ -0,0 +1,901 @@
+/*
+ * dnode.c - Linux node functions for /proc-based lsof
+ */
+
+/*
+ * 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.
+ */
+
+#include "common.h"
+
+#if defined(HASEPTOPTS) && defined(HASPTYEPT)
+#    include <linux/major.h>
+#endif /* defined(HASEPTOPTS) && defined(HASPTYEPT) */
+
+/*
+ * Local definitions
+ */
+
+#define OFFSET_MAX                                                             \
+    ((off_t)0x7fffffff) /* this is defined in                                  \
+                         * .../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))
+
+/*
+ * Local structure definitions
+ */
+
+struct llock {
+    int pid;
+    dev_t dev;
+    INODETYPE inode;
+    enum lsof_lock_mode type;
+    struct llock *next;
+};
+
+/*
+ * Local definitions
+ */
+
+struct llock **LckH = (struct llock **)NULL; /* PID-hashed locks */
+
+/*
+ * Local function prototypes
+ */
+
+static void check_lock(struct lsof_context *ctx);
+
+#if defined(HASEPTOPTS)
+static void enter_pinfo(struct lsof_context *ctx);
+#endif /* defined(HASEPTOPTS) */
+
+/*
+ * Local storage
+ */
+
+#if defined(HASEPTOPTS)
+static pxinfo_t **Pinfo = (pxinfo_t **)NULL; /* pipe endpoint hash buckets */
+#    if defined(HASPTYEPT)
+static pxinfo_t **PtyInfo = (pxinfo_t **)NULL; /* pseudoterminal endpoint hash
+                                                * buckets */
+#    endif                                     /* defined(HASPTYEPT) */
+static pxinfo_t **PSXMQinfo =
+    (pxinfo_t **)NULL; /* posix msg queue endpoint hash buckets */
+static pxinfo_t **EvtFDinfo =
+    (pxinfo_t **)NULL; /* envetfd endpoint hash buckets */
+#endif                 /* defined(HASEPTOPTS) */
+
+/*
+ * check_lock() - check lock for file *Lf, process *Lp
+ */
+
+static void check_lock(struct lsof_context *ctx) {
+    int h;
+    struct llock *lp;
+
+    h = HASHPID(Lp->pid);
+    for (lp = LckH[h]; lp; lp = lp->next) {
+        if (Lp->pid == lp->pid && Lf->dev == lp->dev &&
+            Lf->inode == lp->inode) {
+            Lf->lock = lp->type;
+            return;
+        }
+    }
+}
+
+#if defined(HASEPTOPTS)
+static void endpoint_pxinfo_hash(pxinfo_t **pinfo_hash, const size_t nbuckets,
+                                 void (*free_elt)(void *)) {
+    int h;             /* hash index */
+    pxinfo_t *pi, *pp; /* temporary pointers */
+
+    if (!pinfo_hash)
+        return;
+    for (h = 0; h < nbuckets; h++) {
+        if ((pi = pinfo_hash[h])) {
+            do {
+                pp = pi->next;
+                (void)(*free_elt)((FREE_P *)pi);
+                pi = pp;
+            } while (pi);
+            pinfo_hash[h] = (pxinfo_t *)NULL;
+        }
+    }
+}
+
+static void endpoint_enter(struct lsof_context *ctx, pxinfo_t **pinfo_hash,
+                           const char *table_name, int id) {
+    int h;
+    struct lfile *lf;       /* local file structure pointer */
+    struct lproc *lp;       /* local proc structure pointer */
+    pxinfo_t *np, *pi, *pe; /* inode hash pointers */
+    char fd[FDLEN];
+
+    /*
+     * Make sure this is a unique entry.
+     */
+    for (h = HASHPINFO(id), pi = pinfo_hash[h], pe = (pxinfo_t *)NULL; pi;
+         pe = pi, pi = pi->next) {
+        lf = pi->lf;
+        lp = &Lproc[pi->lpx];
+        if (pi->ino == id) {
+            if ((lp->pid == Lp->pid) && (lf->fd_type == Lf->fd_type) &&
+                (lf->fd_num == Lf->fd_num))
+                return;
+        }
+    }
+    /*
+     * Allocate, fill and link a new pipe info structure used for pty
+     * to the end of the pty device hash chain.
+     */
+    if (!(np = (pxinfo_t *)malloc(sizeof(pxinfo_t)))) {
+        fd_to_string(Lf->fd_type, Lf->fd_num, fd);
+        (void)fprintf(stderr,
+                      "%s: no space for pipeinfo for %s, PID %d, FD %s\n",
+                      table_name, Pn, Lp->pid, fd);
+        Error(ctx);
+    }
+    np->ino = id;
+    np->lf = Lf;
+    np->lpx = Lp - Lproc;
+    np->next = (pxinfo_t *)NULL;
+    if (pe)
+        pe->next = np;
+    else
+        pinfo_hash[h] = np;
+}
+
+static pxinfo_t *
+endpoint_find(struct lsof_context *ctx, pxinfo_t **pinfo_hash,
+              int (*is_acceptable)(struct lsof_context *, pxinfo_t *, int,
+                                   struct lfile *),
+              int pid, struct lfile *lf, int id, pxinfo_t *pp) {
+    int h;        /* hash result */
+    pxinfo_t *pi; /* pipe info pointer */
+
+    if (pinfo_hash) {
+        if (pp)
+            pi = pp;
+        else {
+            h = HASHPINFO(id);
+            pi = pinfo_hash[h];
+        }
+        while (pi) {
+            if (pi->ino == id && is_acceptable(ctx, pi, pid, lf))
+                return (pi);
+            pi = pi->next;
+        }
+    }
+    return ((pxinfo_t *)NULL);
+}
+
+/*
+ * endpoint_accept_other_than_self() -- a helper function return true if
+ * fd associated with pi is not the same as fd associated with lf.
+ */
+
+static int endpoint_accept_other_than_self(struct lsof_context *ctx,
+                                           pxinfo_t *pi, int pid,
+                                           struct lfile *lf) {
+    struct lfile *ef = pi->lf;
+    struct lproc *ep = &Lproc[pi->lpx];
+    return (lf->fd_type != ef->fd_type) || (lf->fd_num != ef->fd_num) ||
+           (pid != ep->pid);
+}
+
+/*
+ * clear_pinfo() -- clear allocated pipe info
+ */
+
+void clear_pinfo(struct lsof_context *ctx) {
+    endpoint_pxinfo_hash(Pinfo, PINFOBUCKS, free);
+}
+
+/*
+ * enter_pinfo() -- enter pipe info
+ *
+ * 	entry	Lf = local file structure pointer
+ * 		Lp = local process structure pointer
+ */
+
+static void enter_pinfo(struct lsof_context *ctx) {
+    if (!Pinfo) {
+        /*
+         * Allocate pipe info hash buckets.
+         */
+        if (!(Pinfo = (pxinfo_t **)calloc(PINFOBUCKS, sizeof(pxinfo_t *)))) {
+            (void)fprintf(stderr, "%s: no space for %d pipe info buckets\n", Pn,
+                          PINFOBUCKS);
+            Error(ctx);
+        }
+    }
+    endpoint_enter(ctx, Pinfo, "pipeinfo", Lf->inode);
+}
+
+/*
+ * find_pepti() -- find pipe end point info
+ */
+
+pxinfo_t *find_pepti(struct lsof_context *ctx, /* context */
+                     int pid,          /* pid of the process owning lf */
+                     struct lfile *lf, /* pipe's lfile */
+                     pxinfo_t *pp)     /* previous pipe info (NULL == none) */
+{
+    return endpoint_find(ctx, Pinfo, endpoint_accept_other_than_self, pid, lf,
+                         lf->inode, pp);
+}
+
+#    if defined(HASPTYEPT)
+
+/*
+ * clear_ptyinfo() -- clear allocated pseudoterminal info
+ */
+
+void clear_ptyinfo(struct lsof_context *ctx) {
+    endpoint_pxinfo_hash(PtyInfo, PINFOBUCKS, free);
+}
+
+/*
+ * enter_ptmxi() -- enter pty info
+ *
+ * 	entry	Lf = local file structure pointer
+ * 		Lp = local process structure pointer
+ */
+
+void enter_ptmxi(struct lsof_context *ctx, /* context */
+                 int mn)                   /* minor number of device */
+{
+    /*
+     * Allocate pipe info hash buckets (but used for pty).
+     */
+    if (!PtyInfo) {
+        if (!(PtyInfo = (pxinfo_t **)calloc(PINFOBUCKS, sizeof(pxinfo_t *)))) {
+            (void)fprintf(stderr, "%s: no space for %d pty info buckets\n", Pn,
+                          PINFOBUCKS);
+            Error(ctx);
+        }
+    }
+    endpoint_enter(ctx, PtyInfo, "pty", mn);
+}
+
+/*
+ * ptyepti_accept_ptmx() -- a helper function return whether lfile is pty ptmx
+ * or not
+ */
+
+static int ptyepti_accept_ptmx(struct lsof_context *ctx, pxinfo_t *pi, int pid,
+                               struct lfile *lf) {
+    struct lfile *ef = pi->lf;
+    return is_pty_ptmx(ef->rdev);
+}
+
+/*
+ * ptyepti_accept_slave() -- a helper function returns whether lfile is pty
+ * slave or not
+ */
+
+static int ptyepti_accept_slave(struct lsof_context *ctx, pxinfo_t *pi, int pid,
+                                struct lfile *lf) {
+    struct lfile *ef = pi->lf;
+    return is_pty_slave(GET_MAJ_DEV(ef->rdev));
+}
+
+/*
+ * find_ptyepti() -- find pseudoterminal end point info
+ */
+
+pxinfo_t *find_ptyepti(struct lsof_context *ctx, /* context */
+                       int pid,                  /* PID*/
+                       struct lfile *lf,         /* pseudoterminal's lfile */
+                       int m,                    /* minor number type:
+                                                  *     0 == use tty_index
+                                                  *     1 == use minor device */
+                       pxinfo_t *pp)             /* previous pseudoterminal info
+                                                  * (NULL == none) */
+{
+    return endpoint_find(ctx, PtyInfo,
+                         m ? ptyepti_accept_ptmx : ptyepti_accept_slave, pid,
+                         lf, m ? GET_MIN_DEV(lf->rdev) : lf->tty_index, pp);
+}
+
+/*
+ * is_pty_slave() -- is a pseudoterminal a slave device
+ */
+
+int is_pty_slave(int sm) /* slave major device number */
+{
+    /* linux/Documentation/admin-guide/devices.txt
+       -------------------------------------------
+       136-143 char	Unix98 PTY slaves
+       0 = /dev/pts/0	First Unix98 pseudo-TTY
+       1 = /dev/pts/1	Second Unix98 pseudo-TTY
+       ...
+
+       These device nodes are automatically generated with
+       the proper permissions and modes by mounting the
+       devpts filesystem onto /dev/pts with the appropriate
+       mount options (distribution dependent, however, on
+       *most* distributions the appropriate options are
+       "mode=0620,gid=<gid of the "tty" group>".) */
+    if ((UNIX98_PTY_SLAVE_MAJOR <= sm) &&
+        (sm < (UNIX98_PTY_SLAVE_MAJOR + UNIX98_PTY_MAJOR_COUNT))) {
+        return 1;
+    }
+    return 0;
+}
+
+/*
+ * is_pty_ptmx() -- is a pseudoterminal a master clone device
+ */
+
+int is_pty_ptmx(dev_t dev) /* device number */
+{
+    if ((GET_MAJ_DEV(dev) == TTYAUX_MAJOR) && (GET_MIN_DEV(dev) == 2))
+        return 1;
+    return 0;
+}
+#    endif /* defined(HASPTYEPT) */
+
+/*
+ * clear_psxmqinfo -- clear allocate posix mq info
+ */
+
+void clear_psxmqinfo(struct lsof_context *ctx) {
+    endpoint_pxinfo_hash(PSXMQinfo, PINFOBUCKS, free);
+}
+
+/*
+ * enter_psxmqinfo() -- enter posix mq info
+ *
+ *	entry	Lf = local file structure pointer
+ *		Lp = local process structure pointer
+ */
+
+void enter_psxmqinfo(struct lsof_context *ctx) {
+    if (!PSXMQinfo) {
+        /*
+         * Allocate posix mq info hash buckets.
+         */
+        if (!(PSXMQinfo =
+                  (pxinfo_t **)calloc(PINFOBUCKS, sizeof(pxinfo_t *)))) {
+            (void)fprintf(stderr, "%s: no space for %d posix mq info buckets\n",
+                          Pn, PINFOBUCKS);
+            Error(ctx);
+        }
+    }
+    endpoint_enter(ctx, PSXMQinfo, "psxmqinfo", Lf->inode);
+}
+
+/*
+ * find_psxmqinfo() -- find posix mq end point info
+ */
+
+pxinfo_t *
+find_psxmqinfo(struct lsof_context *ctx, /* context */
+               int pid,                  /* pid of the process owning lf */
+               struct lfile *lf,         /* posix mq's lfile */
+               pxinfo_t *pp) /* previous posix mq info (NULL == none) */
+{
+    return endpoint_find(ctx, PSXMQinfo, endpoint_accept_other_than_self, pid,
+                         lf, lf->inode, pp);
+}
+
+/*
+ * clear_evtfdinfo -- clear allocate eventfd info
+ */
+
+void clear_evtfdinfo(struct lsof_context *ctx) {
+    endpoint_pxinfo_hash(EvtFDinfo, PINFOBUCKS, free);
+}
+
+/*
+ * enter_evtfdinfo() -- enter eventfd info
+ *
+ *	entry	Lf = local file structure pointer
+ *		Lp = local process structure pointer
+ */
+
+void enter_evtfdinfo(struct lsof_context *ctx, int id) {
+    if (!EvtFDinfo) {
+        /*
+         * Allocate eventfd info hash buckets.
+         */
+        if (!(EvtFDinfo =
+                  (pxinfo_t **)calloc(PINFOBUCKS, sizeof(pxinfo_t *)))) {
+            (void)fprintf(stderr, "%s: no space for %d envet fd info buckets\n",
+                          Pn, PINFOBUCKS);
+            Error(ctx);
+        }
+    }
+    endpoint_enter(ctx, EvtFDinfo, "evtfdinfo", id);
+}
+
+/*
+ * find_evtfdinfo() -- find eventfd end point info
+ */
+
+pxinfo_t *
+find_evtfdinfo(struct lsof_context *ctx, /* context */
+               int pid,                  /* pid of the process owning lf */
+               struct lfile *lf,         /* eventfd's lfile */
+               pxinfo_t *pp) /* previous eventfd info (NULL == none) */
+{
+    void *r = endpoint_find(ctx, EvtFDinfo, endpoint_accept_other_than_self,
+                            pid, lf, lf->eventfd_id, pp);
+    return r;
+}
+#endif /* defined(HASEPTOPTS) */
+
+/*
+ * get_fields() - separate a line into fields
+ */
+
+int get_fields(struct lsof_context *ctx, /* context */
+               char *ln,                 /* input line */
+               char *sep,                /* separator list */
+               char ***fr,               /* field pointer return address */
+               int *eb,                  /* indexes of fields where blank or an
+                                          * entry from the separator list may be
+                                          * embedded and are not separators
+                                          * (may be NULL) */
+               int en)                   /* number of entries in eb[] (may be
+                                          * zero) */
+{
+    char *bp, *cp, *sp;
+    int i, j, n;
+    MALLOC_S len;
+    static char **fp = (char **)NULL;
+    static int nfpa = 0;
+
+    for (cp = ln, n = 0; cp && *cp;) {
+        for (bp = cp; *bp && (*bp == ' ' || *bp == '\t'); bp++)
+            ;
+        ;
+        if (!*bp || *bp == '\n')
+            break;
+        for (cp = bp; *cp; cp++) {
+            if (*cp == '\n') {
+                *cp = '\0';
+                break;
+            }
+            if (*cp == '\t') /* TAB is always a separator */
+                break;
+            if (*cp == ' ') {
+
+                /*
+                 * See if this field may have an embedded space.
+                 */
+                if (!eb || !en)
+                    break;
+                else {
+                    for (i = j = 0; i < en; i++) {
+                        if (eb[i] == n) {
+                            j = 1;
+                            break;
+                        }
+                    }
+                    if (!j)
+                        break;
+                }
+            }
+            if (sep) {
+
+                /*
+                 * See if the character is in the separator list.
+                 */
+                for (sp = sep; *sp; sp++) {
+                    if (*sp == *cp)
+                        break;
+                }
+                if (*sp) {
+
+                    /*
+                     * See if this field may have an embedded separator.
+                     */
+                    if (!eb || !en)
+                        break;
+                    else {
+                        for (i = j = 0; i < en; i++) {
+                            if (eb[i] == n) {
+                                j = 1;
+                                break;
+                            }
+                        }
+                        if (!j)
+                            break;
+                    }
+                }
+            }
+        }
+        if (*cp)
+            *cp++ = '\0';
+        if (n >= nfpa) {
+            nfpa += 32;
+            len = (MALLOC_S)(nfpa * sizeof(char *));
+            if (fp)
+                fp = (char **)realloc((MALLOC_P *)fp, len);
+            else
+                fp = (char **)malloc(len);
+            if (!fp) {
+                (void)fprintf(
+                    stderr, "%s: can't allocate %d bytes for field pointers.\n",
+                    Pn, (int)len);
+                Error(ctx);
+            }
+        }
+        fp[n++] = bp;
+    }
+    *fr = fp;
+    return (n);
+}
+
+/*
+ * get_locks() - get lock information from /proc/locks
+ */
+
+void get_locks(struct lsof_context *ctx, /* context */
+               char *p)                  /* /proc lock path */
+{
+    unsigned long bp, ep;
+    char buf[MAXPATHLEN], *ec, **fp;
+    dev_t dev;
+    int ex, i, h, mode, pid;
+    INODETYPE inode;
+    struct llock *lp, *np;
+    FILE *ls;
+    long maj, min;
+    enum lsof_lock_mode type;
+    static char *vbuf = (char *)NULL;
+    static size_t vsz = (size_t)0;
+    /*
+     * Destroy previous lock information.
+     */
+    if (LckH) {
+        for (i = 0; i < PIDBUCKS; i++) {
+            for (lp = LckH[i]; lp; lp = np) {
+                np = lp->next;
+                (void)free((FREE_P *)lp);
+            }
+            LckH[i] = (struct llock *)NULL;
+        }
+    } else {
+
+        /*
+         * If first time, allocate the lock PID hash buckets.
+         */
+        LckH =
+            (struct llock **)calloc((MALLOC_S)PIDBUCKS, sizeof(struct llock *));
+        if (!LckH) {
+            (void)fprintf(stderr, "%s: can't allocate %d lock hash bytes\n", Pn,
+                          (int)(sizeof(struct llock *) * PIDBUCKS));
+            Error(ctx);
+        }
+    }
+    /*
+     * Open the /proc lock file, assign a page size buffer to its stream,
+     * and read it.
+     */
+    if (!(ls = open_proc_stream(ctx, p, "r", &vbuf, &vsz, 0)))
+        return;
+    while (fgets(buf, sizeof(buf), ls)) {
+        if (get_fields(ctx, buf, ":", &fp, (int *)NULL, 0) < 10)
+            continue;
+        if (!fp[1] || strcmp(fp[1], "->") == 0)
+            continue;
+        /*
+         * Get lock type.
+         */
+        if (!fp[3])
+            continue;
+        if (*fp[3] == 'R')
+            mode = 0;
+        else if (*fp[3] == 'W')
+            mode = 1;
+        else
+            continue;
+        /*
+         * Get PID.
+         */
+        if (!fp[4] || !*fp[4])
+            continue;
+        pid = atoi(fp[4]);
+        /*
+         * Get device number.
+         */
+        ec = (char *)NULL;
+        if (!fp[5] || !*fp[5] || (maj = strtol(fp[5], &ec, 16)) == LONG_MIN ||
+            maj == LONG_MAX || !ec || *ec)
+            continue;
+        ec = (char *)NULL;
+        if (!fp[6] || !*fp[6] || (min = strtol(fp[6], &ec, 16)) == LONG_MIN ||
+            min == LONG_MAX || !ec || *ec)
+            continue;
+        dev = (dev_t)makedev((int)maj, (int)min);
+        /*
+         * Get inode number.
+         */
+        ec = (char *)NULL;
+        if (!fp[7] || !*fp[7] ||
+            (inode = strtoull(fp[7], &ec, 0)) == ULONG_MAX || !ec || *ec)
+            continue;
+        /*
+         * Get lock extent.  Convert it and the lock type to a lock character.
+         */
+        if (!fp[8] || !*fp[8] || !fp[9] || !*fp[9])
+            continue;
+        ec = (char *)NULL;
+        if ((bp = strtoul(fp[8], &ec, 0)) == ULONG_MAX || !ec || *ec)
+            continue;
+        if (!strcmp(fp[9], "EOF")) /* for Linux 2.4.x */
+            ep = OFFSET_MAX;
+        else {
+            ec = (char *)NULL;
+            if ((ep = strtoul(fp[9], &ec, 0)) == ULONG_MAX || !ec || *ec)
+                continue;
+        }
+        ex = ((off_t)bp == (off_t)0 && (off_t)ep == OFFSET_MAX) ? 1 : 0;
+        if (mode)
+            type = ex ? LSOF_LOCK_WRITE_FULL : LSOF_LOCK_WRITE_PARTIAL;
+        else
+            type = ex ? LSOF_LOCK_READ_FULL : LSOF_LOCK_READ_PARTIAL;
+        /*
+         * Look for this lock via the hash buckets.
+         */
+        h = HASHPID(pid);
+        for (lp = LckH[h]; lp; lp = lp->next) {
+            if (lp->pid == pid && lp->dev == dev && lp->inode == inode &&
+                lp->type == type)
+                break;
+        }
+        if (lp)
+            continue;
+        /*
+         * Allocate a new llock structure and link it to the PID hash bucket.
+         */
+        if (!(lp = (struct llock *)malloc(sizeof(struct llock)))) {
+            (void)snpf(buf, sizeof(buf), "%" INODEPSPEC "u", inode);
+            (void)fprintf(
+                stderr, "%s: can't allocate llock: PID %d; dev %x; inode %s\n",
+                Pn, pid, (int)dev, buf);
+            Error(ctx);
+        }
+        lp->pid = pid;
+        lp->dev = dev;
+        lp->inode = inode;
+        lp->type = type;
+        lp->next = LckH[h];
+        LckH[h] = lp;
+    }
+    (void)fclose(ls);
+}
+
+/*
+ * process_proc_node() - process file node
+ */
+
+void process_proc_node(struct lsof_context *ctx, /* context */
+                       char *p,                  /* node's readlink() path */
+                       char *pbr,      /* node's path before readlink() */
+                       struct stat *s, /* stat() result for path */
+                       int ss,         /* *s status -- i.e., SB_* values */
+                       struct stat *l, /* lstat() result for FD (NULL for
+                                        * others) */
+                       int ls)         /* *l status -- i.e., SB_* values */
+{
+    mode_t access;
+    mode_t type = 0;
+    char *cp;
+    struct mounts *mp = (struct mounts *)NULL;
+    size_t sz;
+    char *tn;
+    /*
+     * Set the access mode, if possible.
+     */
+    if (l && (ls & SB_MODE) && ((l->st_mode & S_IFMT) == S_IFLNK)) {
+        if ((access = l->st_mode & (S_IRUSR | S_IWUSR)) == S_IRUSR)
+            Lf->access = LSOF_FILE_ACCESS_READ;
+        else if (access == S_IWUSR)
+            Lf->access = LSOF_FILE_ACCESS_WRITE;
+        else
+            Lf->access = LSOF_FILE_ACCESS_READ_WRITE;
+    }
+    /*
+     * Determine node type.
+     */
+    if (ss & SB_MODE) {
+        type = s->st_mode & S_IFMT;
+        switch (type) {
+        case S_IFBLK:
+            Lf->ntype = Ntype = N_BLK;
+            break;
+        case S_IFCHR:
+            Lf->ntype = Ntype = N_CHR;
+            break;
+        case S_IFIFO:
+            Lf->ntype = Ntype = N_FIFO;
+            break;
+        case S_IFSOCK:
+            /* Lf->ntype = Ntype = N_REGLR;		by alloc_lfile() */
+            process_proc_sock(ctx, p, pbr, s, ss, l, ls);
+            return;
+        case 0:
+            if (!strcmp(p, "anon_inode"))
+                Lf->ntype = Ntype = N_ANON_INODE;
+            break;
+        }
+    }
+    if (Selinet)
+        return;
+    /*
+     * Save the device.  If it is an NFS device, change the node type to N_NFS.
+     */
+    if (ss & SB_DEV) {
+        Lf->dev = s->st_dev;
+        Lf->dev_def = 1;
+    }
+    if ((Ntype == N_CHR || Ntype == N_BLK)) {
+        if (ss & SB_RDEV) {
+            Lf->rdev = s->st_rdev;
+            Lf->rdev_def = 1;
+
+#if defined(HASEPTOPTS) && defined(HASPTYEPT)
+            if (FeptE && (Ntype == N_CHR) &&
+                is_pty_slave(GET_MAJ_DEV(Lf->rdev))) {
+                enter_ptmxi(ctx, GET_MIN_DEV(Lf->rdev));
+                Lf->sf |= SELPTYINFO;
+            }
+#endif /* defined(HASEPTOPTS) && defined(HASPTYEPT) */
+        }
+    }
+    if (Ntype == N_REGLR && (HasNFS == 2)) {
+        for (mp = readmnt(ctx); mp; mp = mp->next) {
+            if ((mp->ty == N_NFS) && (mp->ds & SB_DEV) && Lf->dev_def &&
+                (Lf->dev == mp->dev) &&
+                (mp->dir && mp->dirl && !strncmp(mp->dir, p, mp->dirl))) {
+                Lf->ntype = Ntype = N_NFS;
+                break;
+            }
+        }
+    }
+    /*
+     * Save the inode number.
+     */
+    if (ss & SB_INO) {
+        Lf->inode = (INODETYPE)s->st_ino;
+        Lf->inp_ty = 1;
+
+#if defined(HASEPTOPTS)
+        if ((Lf->ntype == N_FIFO) && FeptE) {
+            (void)enter_pinfo(ctx);
+            Lf->sf |= SELPINFO;
+        } else if ((Lf->dev == MqueueDev) && FeptE) {
+            (void)enter_psxmqinfo(ctx);
+            Lf->sf |= SELPSXMQINFO;
+        }
+#endif /* defined(HASEPTOPTS) */
+    }
+    /*
+     * Check for a lock.
+     */
+    if (Lf->dev_def && (Lf->inp_ty == 1))
+        (void)check_lock(ctx);
+    /*
+     * Save the file size.
+     */
+    switch (Ntype) {
+    case N_BLK:
+    case N_CHR:
+    case N_FIFO:
+        if (l && (ls & SB_SIZE) && OffType != OFFSET_UNKNOWN) {
+            Lf->off = (SZOFFTYPE)l->st_size;
+            Lf->off_def = 1;
+        }
+        break;
+    default:
+        if (l && (ls & SB_SIZE) && OffType != OFFSET_UNKNOWN) {
+            Lf->off = (SZOFFTYPE)l->st_size;
+            Lf->off_def = 1;
+        }
+        if (ss & SB_SIZE) {
+            Lf->sz = (SZOFFTYPE)s->st_size;
+            Lf->sz_def = 1;
+        }
+    }
+    /*
+     * Record the link count.
+     */
+    if (ss & SB_NLINK) {
+        Lf->nlink = (long)s->st_nlink;
+        Lf->nlink_def = 1;
+        if (Nlink && (Lf->nlink < Nlink))
+            Lf->sf |= SELNLINK;
+    }
+    /*
+     * Format the type name.
+     */
+    if (ss & SB_MODE) {
+        switch (type) {
+        case S_IFBLK:
+            Lf->type = LSOF_FILE_BLOCK;
+            break;
+        case S_IFCHR:
+            Lf->type = LSOF_FILE_CHAR;
+            break;
+        case S_IFDIR:
+            Lf->type = LSOF_FILE_DIR;
+            break;
+        case S_IFIFO:
+            Lf->type = LSOF_FILE_FIFO;
+            break;
+        case S_IFREG:
+            if (Lf->dev == MqueueDev)
+                Lf->type = LSOF_FILE_POSIX_MQ;
+            else
+                Lf->type = LSOF_FILE_REGULAR;
+            break;
+        case S_IFLNK:
+            Lf->type = LSOF_FILE_LINK;
+            break;
+        default:
+            if (Ntype == N_ANON_INODE)
+                Lf->type = LSOF_FILE_ANON_INODE;
+            else {
+                Lf->type = LSOF_FILE_UNKNOWN_RAW;
+                Lf->unknown_file_type_number = (type >> 12) & 0xf;
+            }
+        }
+    } else
+        Lf->type = LSOF_FILE_UNKNOWN_STAT;
+    /*
+     * Record an NFS file selection.
+     */
+    if (Ntype == N_NFS && Fnfs)
+        Lf->sf |= SELNFS;
+    /*
+     * Test for specified file.
+     */
+    if (Sfile &&
+        is_file_named(ctx, 1, p, mp,
+                      ((type == S_IFCHR) || (type == S_IFBLK)) ? 1 : 0))
+        Lf->sf |= SELNM;
+    /*
+     * If no NAME information has been stored, store the path.
+     *
+     * Store the remote host and mount point for an NFS file.
+     */
+    if (!Namech[0]) {
+        (void)snpf(Namech, Namechl, "%s", p);
+        if ((Ntype == N_NFS) && mp && mp->fsname) {
+            cp = endnm(ctx, &sz);
+            (void)snpf(cp, sz, " (%s)", mp->fsname);
+        }
+    }
+    if (Namech[0])
+        enter_nm(ctx, Namech);
+}
diff --git a/lib/dialects/linux/dproc.c b/lib/dialects/linux/dproc.c
new file mode 100644
index 0000000..3a7a120
--- /dev/null
+++ b/lib/dialects/linux/dproc.c
@@ -0,0 +1,1934 @@
+/*
+ * dproc.c - Linux process access functions for /proc-based lsof
+ */
+
+/*
+ * 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.
+ */
+
+#include "common.h"
+
+#include <inttypes.h>
+
+/*
+ * Local definitions
+ */
+
+#define FDINFO_FLAGS 0x1 /* fdinfo flags available */
+#define FDINFO_POS 0x2   /* fdinfo position available */
+
+#if defined(HASEPTOPTS)
+#    define FDINFO_EVENTFD_ID 0x4 /* fdinfo eventfd-id available */
+#    if defined(HASPTYEPT)
+#        define FDINFO_TTY_INDEX 0x8 /* fdinfo tty-index available */
+#    endif                           /* defined(HASPTYEPT) */
+#endif                               /* defined(HASEPTOPTS) */
+
+#define FDINFO_PID 0x10 /* pidfd pid available */
+#define FDINFO_TFD 0x20 /* fd monitored by eventpoll fd */
+
+#define FDINFO_BASE (FDINFO_FLAGS | FDINFO_POS)
+#if defined(HASEPTOPTS)
+#    if defined(HASPTYEPT)
+#        define FDINFO_ALL                                                     \
+            (FDINFO_BASE | FDINFO_TTY_INDEX | FDINFO_EVENTFD_ID | FDINFO_PID | \
+             FDINFO_TFD)
+#    else /* !defined(HASPTYEPT) */
+#        define FDINFO_ALL                                                     \
+            (FDINFO_BASE | FDINFO_EVENTFD_ID | FDINFO_PID | FDINFO_TFD)
+#    endif /* defined(HASPTYEPT) */
+#    define FDINFO_OPTIONAL (FDINFO_ALL & ~FDINFO_BASE)
+#else /* !defined(HASEPTOPTS) */
+#    define FDINFO_ALL (FDINFO_BASE | FDINFO_PID | FDINFO_TFD)
+#endif /* defined(HASEPTOPTS) */
+
+#define LSTAT_TEST_FILE "/"
+#define LSTAT_TEST_SEEK 1
+
+#if !defined(ULLONG_MAX)
+#    define ULLONG_MAX 18446744073709551615ULL
+#endif /* !defined(ULLONG_MAX) */
+
+#define NS_PATH_LENGTH 100  /* namespace path string length */
+#define MAP_PATH_LENGTH 100 /* map_files path length */
+#define ADDR_LENGTH 100     /* addr range of map_files length */
+
+/*
+ * Local structures
+ */
+
+struct l_fdinfo {
+    int flags; /* flags: line value */
+    off_t pos; /* pos: line value */
+
+#if defined(HASEPTOPTS)
+    int eventfd_id;
+#    if defined(HASPTYEPT)
+    int tty_index; /* pty line index */
+#    endif         /* defined(HASPTYEPT) */
+#endif             /* defined(HASEPTOPTS) */
+
+    int pid; /* for pidfd */
+
+#define EPOLL_MAX_TFDS 32
+    int tfds[EPOLL_MAX_TFDS];
+    size_t tfd_count;
+};
+
+/*
+ * Local variables
+ */
+
+static short Cckreg; /* conditional status of regular file
+                      * checking:
+                      *     0 = unconditionally check
+                      *     1 = conditionally check */
+static short Ckscko; /* socket file only checking status:
+                      *     0 = none
+                      *     1 = check only socket files */
+
+/*
+ * Local function prototypes
+ */
+
+static MALLOC_S alloc_cbf(struct lsof_context *ctx, MALLOC_S len, char **cbf,
+                          MALLOC_S cbfa);
+static int get_fdinfo(struct lsof_context *ctx, char *p, int msk,
+                      struct l_fdinfo *fi);
+static int getlinksrc(char *ln, char *src, int srcl, char **rest);
+static int isefsys(struct lsof_context *ctx, char *path,
+                   enum lsof_file_type type, int l, efsys_list_t **rep,
+                   struct lfile **lfr);
+static int nm2id(char *nm, int *id, int *idl);
+static int read_id_stat(struct lsof_context *ctx, char *p, int id, char **cmd,
+                        int *ppid, int *pgid);
+static void process_proc_map(struct lsof_context *ctx, char *p, struct stat *s,
+                             int ss);
+static int process_id(struct lsof_context *ctx, char *idp, int idpl, char *cmd,
+                      UID_ARG uid, int pid, int ppid, int pgid, int tid,
+                      char *tcmd);
+static int statEx(struct lsof_context *ctx, char *p, struct stat *s, int *ss);
+
+static void snp_eventpoll(char *p, int len, int *tfds, int tfd_count);
+
+#if defined(HASSELINUX)
+static int cmp_cntx_eq(char *pcntx, char *ucntx);
+
+#    include <fnmatch.h>
+
+/*
+ * cmp_cntx_eq -- compare program and user security contexts
+ */
+
+static int cmp_cntx_eq(char *pcntx, /* program context */
+                       char *ucntx) /* user supplied context */
+{
+    return !fnmatch(ucntx, pcntx, 0);
+}
+
+/*
+ * enter_cntx_arg() - enter name ecurity context argument
+ */
+
+int enter_cntx_arg(struct lsof_context *ctx, /* context */
+                   char *cntx)               /* context */
+{
+    cntxlist_t *cntxp;
+    /*
+     * Search the argument list for a duplicate.
+     */
+    for (cntxp = CntxArg; cntxp; cntxp = cntxp->next) {
+        if (!strcmp(cntxp->cntx, cntx)) {
+            if (!Fwarn) {
+                (void)fprintf(stderr, "%s: duplicate context: %s\n", Pn, cntx);
+            }
+            return (1);
+        }
+    }
+    /*
+     * Create and link a new context argument list entry.
+     */
+    if (!(cntxp = (cntxlist_t *)malloc((MALLOC_S)sizeof(cntxlist_t)))) {
+        (void)fprintf(stderr, "%s: no space for context: %s\n", Pn, cntx);
+        Error(ctx);
+    }
+    cntxp->f = 0;
+    cntxp->cntx = cntx;
+    cntxp->next = CntxArg;
+    CntxArg = cntxp;
+    return (0);
+}
+#endif /* defined(HASSELINUX) */
+
+/*
+ * alloc_cbf() -- allocate a command buffer
+ */
+
+static MALLOC_S alloc_cbf(struct lsof_context *ctx, /* context */
+                          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);
+        Error(ctx);
+    }
+    return (len);
+}
+
+/*
+ * gather_proc_info() -- gather process information
+ */
+
+void gather_proc_info(struct lsof_context *ctx) {
+    char *cmd, *tcmd;
+    char cmdbuf[MAXPATHLEN];
+    struct dirent *dp;
+    unsigned char ht, pidts;
+    int n, nl, pgid, pid, ppid, prv, rv, tid, tpgid, tppid, tx;
+    static char *path = (char *)NULL;
+    static int pathl = 0;
+    static char *pidpath = (char *)NULL;
+    static MALLOC_S pidpathl = 0;
+    static MALLOC_S pidx = 0;
+    static DIR *ps = (DIR *)NULL;
+    struct stat sb;
+    static char *taskpath = (char *)NULL;
+    static int taskpathl = 0;
+    static char *tidpath = (char *)NULL;
+    static int tidpathl = 0;
+    DIR *ts;
+    UID_ARG uid;
+
+    /*
+     * Do one-time setup.
+     */
+    if (!pidpath) {
+        pidx = strlen(PROCFS) + 1;
+        pidpathl = pidx + 64 + 1; /* 64 is growth room */
+        if (!(pidpath = (char *)malloc(pidpathl))) {
+            (void)fprintf(stderr,
+                          "%s: can't allocate %d bytes for \"%s/\"<pid>\n", Pn,
+                          (int)pidpathl, PROCFS);
+            Error(ctx);
+        }
+        (void)snpf(pidpath, pidpathl, "%s/", PROCFS);
+    }
+    /*
+     * Get lock and net information.
+     */
+    (void)make_proc_path(ctx, pidpath, pidx, &path, &pathl, "locks");
+    (void)get_locks(ctx, path);
+    (void)make_proc_path(ctx, pidpath, pidx, &path, &pathl, "net/");
+    (void)set_net_paths(ctx, path, strlen(path));
+    /*
+     * 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 /proc, looking for PID directories.  Open each one and
+     * gather its process and file information.
+     */
+    if (!ps) {
+        if (!(ps = opendir(PROCFS))) {
+            (void)fprintf(stderr, "%s: can't open %s\n", Pn, PROCFS);
+            Error(ctx);
+        }
+    } else
+        (void)rewinddir(ps);
+    while ((dp = readdir(ps))) {
+        if (nm2id(dp->d_name, &pid, &n))
+            continue;
+        /*
+         * Build path to PID's directory.
+         */
+        if ((pidx + n + 1 + 1) > pidpathl) {
+            pidpathl = pidx + n + 1 + 1 + 64;
+            if (!(pidpath = (char *)realloc((MALLOC_P *)pidpath, pidpathl))) {
+                (void)fprintf(stderr,
+                              "%s: can't allocate %d bytes for \"%s/%s/\"\n",
+                              Pn, (int)pidpathl, PROCFS, dp->d_name);
+                Error(ctx);
+            }
+        }
+        (void)snpf(pidpath + pidx, pidpathl - pidx, "%s/", dp->d_name);
+        n += (pidx + 1);
+        /*
+         * Process the PID's stat info.
+         */
+        if (stat(pidpath, &sb))
+            continue;
+        uid = (UID_ARG)sb.st_uid;
+        ht = pidts = 0;
+        /*
+         * Get the PID's command name.
+         */
+        (void)make_proc_path(ctx, pidpath, n, &path, &pathl, "stat");
+        if ((prv = read_id_stat(ctx, path, pid, &cmd, &ppid, &pgid)) < 0)
+            cmd = NULL; /* NULL means failure to get command name */
+
+#if defined(HASTASKS)
+        /*
+         * Task reporting has been selected, so save the process' command
+         * string, so that task processing won't change it in the buffer of
+         * read_id_stat().
+         *
+         * Check the tasks of the process first, so that the "-p<PID> -aK"
+         * options work properly.
+         */
+        else if (!IgnTasks && (Selflags & SELTASK)) {
+            /*
+             * Copy cmd before next call to read_id_stat due to static
+             * variables
+             */
+            if (cmd) {
+                strncpy(cmdbuf, cmd, sizeof(cmdbuf) - 1);
+                cmdbuf[sizeof(cmdbuf) - 1] = '\0';
+                cmd = cmdbuf;
+            }
+
+            (void)make_proc_path(ctx, pidpath, n, &taskpath, &taskpathl,
+                                 "task");
+            tx = n + 4;
+            if ((ts = opendir(taskpath))) {
+
+                /*
+                 * Process the PID's tasks.  Record the open files of those
+                 * whose TIDs do not match the PID and which are themselves
+                 * not zombies.
+                 */
+                while ((dp = readdir(ts))) {
+
+                    /*
+                     * Get the task ID.  Skip the task if its ID matches the
+                     * process PID.
+                     */
+                    if (nm2id(dp->d_name, &tid, &nl))
+                        continue;
+                    if (tid == pid) {
+                        pidts = 1;
+                        continue;
+                    }
+                    /*
+                     * Form the path for the TID.
+                     */
+                    if ((tx + 1 + nl + 1 + 4) > tidpathl) {
+                        tidpathl = tx + 1 + n + 1 + 4 + 64;
+                        if (tidpath)
+                            tidpath =
+                                (char *)realloc((MALLOC_P *)tidpath, tidpathl);
+                        else
+                            tidpath = (char *)malloc((MALLOC_S)tidpathl);
+                        if (!tidpath) {
+                            (void)fprintf(stderr,
+                                          "%s: can't allocate %d task bytes",
+                                          Pn, tidpathl);
+                            (void)fprintf(stderr, " for \"%s/%s/stat\"\n",
+                                          taskpath, dp->d_name);
+                            Error(ctx);
+                        }
+                    }
+                    (void)snpf(tidpath, tidpathl, "%s/%s/stat", taskpath,
+                               dp->d_name);
+                    /*
+                     * Check the task state.
+                     */
+                    rv = read_id_stat(ctx, tidpath, tid, &tcmd, &tppid, &tpgid);
+                    if ((rv < 0) || (rv == 1))
+                        continue;
+                    /*
+                     * Attempt to record the task.
+                     */
+                    if (!process_id(ctx, tidpath, (tx + 1 + nl + 1), cmd, uid,
+                                    pid, tppid, tpgid, tid, tcmd)) {
+                        ht = 1;
+                    }
+                }
+                (void)closedir(ts);
+            }
+        }
+#endif /* defined(HASTASKS) */
+
+        /*
+         * If the main process is a task and task selection has been specified
+         * along with option ANDing, enter the main process temporarily as a
+         * task, so that the "-aK" option set lists the main process along
+         * with its tasks.
+         */
+        if ((prv >= 0) && (prv != 1)) {
+            tid = (Fand && ht && pidts && !IgnTasks && (Selflags & SELTASK))
+                      ? pid
+                      : 0;
+            if ((!process_id(ctx, pidpath, n, cmd, uid, pid, ppid, pgid, tid,
+                             (char *)NULL)) &&
+                tid) {
+                Lp->tid = 0;
+            }
+        }
+    }
+}
+
+/*
+ * get_fdinfo() - get values from /proc/<PID>fdinfo/FD
+ */
+
+static int get_fdinfo(struct lsof_context *ctx, /* context */
+                      char *p,                  /* path to fdinfo file */
+                      int msk,             /* mask for information type: e.g.,
+                                            * the FDINFO_* definition */
+                      struct l_fdinfo *fi) /* pointer to local fdinfo values
+                                            * return structure */
+{
+    char buf[MAXPATHLEN + 1], *ep, **fp;
+    FILE *fs;
+    int rv = 0;
+    unsigned long ul;
+    unsigned long long ull;
+    /*
+     * Signal no values returned (0) if no fdinfo pointer was provided or if the
+     * fdinfo path can't be opened.
+     */
+    if (!fi)
+        return (0);
+
+#if defined(HASEPTOPTS)
+    fi->eventfd_id = -1;
+#    if defined(HASPTYEPT)
+    fi->tty_index = -1;
+#    endif /* defined(HASPTYEPT) */
+#endif     /* defined(HASEPTOPTS) */
+    fi->pid = -1;
+    fi->tfd_count = 0;
+
+    if (!p || !*p || !(fs = fopen(p, "r")))
+        return (0);
+    /*
+     * Read the fdinfo file.
+     */
+    while (fgets(buf, sizeof(buf), fs)) {
+        int opt_flg = 0;
+        if (get_fields(ctx, buf, (char *)NULL, &fp, (int *)NULL, 0) < 2)
+            continue;
+        if (!fp[0] || !*fp[0] || !fp[1] || !*fp[1])
+            continue;
+        if ((msk & FDINFO_FLAGS) && !strcmp(fp[0], "flags:")) {
+
+            /*
+             * Process a "flags:" line.
+             */
+            ep = (char *)NULL;
+            if ((ul = strtoul(fp[1], &ep, 0)) == ULONG_MAX || !ep || *ep)
+                continue;
+            fi->flags = (unsigned int)ul;
+            if ((rv |= FDINFO_FLAGS) == msk)
+                break;
+        } else if ((msk & FDINFO_POS) && !strcmp(fp[0], "pos:")) {
+
+            /*
+             * Process a "pos:" line.
+             */
+            ep = (char *)NULL;
+            if ((ull = strtoull(fp[1], &ep, 0)) == ULLONG_MAX || !ep || *ep)
+                continue;
+            fi->pos = (off_t)ull;
+            if ((rv |= FDINFO_POS) == msk)
+                break;
+
+        } else if (((msk & FDINFO_PID) && !strcmp(fp[0], "Pid:") &&
+                    ((opt_flg = FDINFO_PID))) ||
+                   ((msk & FDINFO_TFD) && !strcmp(fp[0], "tfd:") &&
+                    ((opt_flg = FDINFO_TFD)))
+#if defined(HASEPTOPTS)
+                   || ((msk & FDINFO_EVENTFD_ID) &&
+                       !strcmp(fp[0], "eventfd-id:") &&
+                       ((opt_flg = FDINFO_EVENTFD_ID)))
+#    if defined(HASPTYEPT)
+                   ||
+                   ((msk & FDINFO_TTY_INDEX) && !strcmp(fp[0], "tty-index:") &&
+                    ((opt_flg = FDINFO_TTY_INDEX)))
+#    endif /* defined(HASPTYEPT) */
+#endif     /* defined(HASEPTOPTS) */
+        ) {
+            int val;
+            /*
+             * Process a "tty-index:", "eventfd-id:", "Pid:", or "tfid:" line.
+             */
+            ep = (char *)NULL;
+            if ((ul = strtoul(fp[1], &ep, 0)) == ULONG_MAX || !ep || *ep)
+                continue;
+
+            val = (int)ul;
+            if (val < 0) {
+                /*
+                 * Oops! If integer overflow occurred, reset the field.
+                 */
+                val = -1;
+            }
+
+            rv |= opt_flg;
+            switch (opt_flg) {
+#if defined(HASEPTOPTS)
+            case FDINFO_EVENTFD_ID:
+                fi->eventfd_id = val;
+                break;
+#    if defined(HASPTYEPT)
+            case FDINFO_TTY_INDEX:
+                fi->tty_index = val;
+                break;
+#    endif /* defined(HASPTYEPT) */
+#endif     /* defined(HASEPTOPTS) */
+            case FDINFO_PID:
+                fi->pid = val;
+                break;
+            case FDINFO_TFD:
+                if (fi->tfd_count < EPOLL_MAX_TFDS) {
+                    fi->tfds[fi->tfd_count] = val;
+                    fi->tfd_count++;
+                }
+                break;
+            }
+
+            if ((
+                    /* There can be more than one tfd: lines.
+                   So even if we found one, we can not exit the loop.
+                   However, we can assume tfd lines are continuous. */
+                    opt_flg != FDINFO_TFD &&
+                    (rv == msk || (rv & FDINFO_TFD))) ||
+                (
+                    /* Too many tfds. */
+                    opt_flg == FDINFO_TFD && rv == msk &&
+                    fi->tfd_count == EPOLL_MAX_TFDS))
+                break;
+        }
+    }
+    fclose(fs);
+    /*
+     * Signal via the return value what information was obtained. (0 == none)
+     */
+    return (rv);
+}
+
+/*
+ * getlinksrc() - get the source path name for the /proc/<PID>/fd/<FD> link
+ */
+
+static int getlinksrc(char *ln,    /* link path */
+                      char *src,   /* link source path return address */
+                      int srcl,    /* length of src[] */
+                      char **rest) /* pointer to what follows the ':' in
+                                    * the link source path (NULL if no
+                                    * return requested) */
+{
+    char *cp;
+    int ll;
+
+    if (rest)
+        *rest = (char *)NULL;
+    if ((ll = readlink(ln, src, srcl - 1)) < 1 || ll >= srcl)
+        return (-1);
+    src[ll] = '\0';
+    if (*src == '/')
+        return (ll);
+    if ((cp = strchr(src, ':'))) {
+        *cp = '\0';
+        ll = strlen(src);
+        if (rest)
+            *rest = cp + 1;
+    }
+    return (ll);
+}
+
+/*
+ * initialize() - perform all initialization
+ */
+
+void initialize(struct lsof_context *ctx) {
+    int fd;
+    struct l_fdinfo fi;
+    char path[MAXPATHLEN];
+    struct stat sb;
+    /*
+     * Test for -i and -X option conflict.
+     */
+    if (Fxopt && (Fnet || Nwad)) {
+        (void)fprintf(stderr, "%s: -i is useless when -X is specified.\n", Pn);
+        usage(ctx, 1, 0, 0);
+    }
+    /*
+     * Open LSTAT_TEST_FILE and seek to byte LSTAT_TEST_SEEK, then lstat the
+     * /proc/<PID>/fd/<FD> for LSTAT_TEST_FILE to see what position is reported.
+     * If the result is LSTAT_TEST_SEEK, enable offset reporting.
+     *
+     * If the result isn't LSTAT_TEST_SEEK, next check the fdinfo file for the
+     * open LSTAT_TEST_FILE file descriptor.  If it exists and contains a "pos:"
+     * value, and if the value is LSTAT_TEST_SEEK, enable offset reporting.
+     */
+    if ((fd = open(LSTAT_TEST_FILE, O_RDONLY)) >= 0) {
+        if (lseek(fd, (off_t)LSTAT_TEST_SEEK, SEEK_SET) ==
+            (off_t)LSTAT_TEST_SEEK) {
+            (void)snpf(path, sizeof(path), "%s/%d/fd/%d", PROCFS, Mypid, fd);
+            if (!lstat(path, &sb)) {
+                if (sb.st_size == (off_t)LSTAT_TEST_SEEK)
+                    OffType = OFFSET_LSTAT;
+            }
+        }
+        if (OffType == OFFSET_UNKNOWN) {
+            (void)snpf(path, sizeof(path), "%s/%d/fdinfo/%d", PROCFS, Mypid,
+                       fd);
+            if (get_fdinfo(ctx, path, FDINFO_POS, &fi) & FDINFO_POS) {
+                if (fi.pos == (off_t)LSTAT_TEST_SEEK)
+                    OffType = OFFSET_FDINFO;
+            }
+        }
+        (void)close(fd);
+    }
+    if (OffType == OFFSET_UNKNOWN) {
+        if (Foffset && !Fwarn)
+            (void)fprintf(
+                stderr, "%s: WARNING: can't report offset; disregarding -o.\n",
+                Pn);
+        Foffset = 0;
+        Fsize = 1;
+    }
+    /*
+     * Make sure the local mount info table is loaded if doing anything other
+     * than just Internet lookups.  (HasNFS is defined during the loading of the
+     * local mount table.)
+     */
+    if (Selinet == 0)
+        (void)readmnt(ctx);
+}
+
+/*
+ * make_proc_path() - make a path in a /proc directory
+ *
+ * entry:
+ *	pp = pointer to /proc prefix
+ *	lp = length of prefix
+ *	np = pointer to malloc'd buffer to receive new file's path
+ *	nl = size of new file path buffer
+ *	sf = new path's suffix
+ *
+ * return: length of new path
+ *	np = updated with new path
+ *	nl = updated with new buffer size
+ */
+int make_proc_path(struct lsof_context *ctx, /* context */
+                   char *pp,  /* path prefix -- e.g., /proc/<pid>/ */
+                   int pl,    /* strlen(pp) */
+                   char **np, /* malloc'd receiving buffer */
+                   int *nl,   /* malloc'd size */
+                   char *sf)  /* suffix of new path */
+{
+    char *cp;
+    MALLOC_S rl, sl;
+
+    sl = strlen(sf);
+    if ((rl = pl + sl + 1) > *nl) {
+        if ((cp = *np))
+            cp = (char *)realloc((MALLOC_P *)cp, rl);
+        else
+            cp = (char *)malloc(rl);
+        if (!cp) {
+            (void)fprintf(stderr, "%s: can't allocate %d bytes for %s%s\n", Pn,
+                          (int)rl, pp, sf);
+            Error(ctx);
+        }
+        *nl = rl;
+        *np = cp;
+    }
+    (void)snpf(*np, *nl, "%s", pp);
+    (void)snpf(*np + pl, *nl - pl, "%s", sf);
+    return (rl - 1);
+}
+
+/*
+ * isefsys() -- is path on a file system exempted with -e
+ *
+ * Note: alloc_lfile() must have been called in advance.
+ */
+
+static int isefsys(struct lsof_context *ctx, /* context */
+                   char *path,               /* path to file */
+                   enum lsof_file_type type, /* unknown file type */
+                   int l,                    /* link request: 0 = report
+                                              *               1 = link */
+                   efsys_list_t **rep,       /* returned Efsysl pointer, if not
+                                              * NULL */
+                   struct lfile **lfr) /* allocated struct lfile pointer */
+{
+    efsys_list_t *ep;
+    int ds, len;
+    struct mounts *mp;
+    char nmabuf[MAXPATHLEN + 1];
+
+    len = (int)strlen(path);
+    for (ep = Efsysl; ep; ep = ep->next) {
+
+        /*
+         * Look for a matching exempt file system path at the beginning of
+         * the file path.
+         */
+        if (ep->pathl > len)
+            continue;
+        if (strncmp(ep->path, path, ep->pathl))
+            continue;
+        /*
+         * If only reporting, return information as requested.
+         */
+        if (!l) {
+            if (rep)
+                *rep = ep;
+            return (0);
+        }
+        /*
+         * Process an exempt file.
+         */
+        ds = 0;
+        if ((mp = ep->mp)) {
+            if (mp->ds & SB_DEV) {
+                Lf->dev = mp->dev;
+                ds = Lf->dev_def = 1;
+            }
+            if (mp->ds & SB_RDEV) {
+                Lf->rdev = mp->rdev;
+                ds = Lf->rdev_def = 1;
+            }
+        }
+        if (!ds)
+            (void)enter_dev_ch(ctx, "UNKNOWN");
+        Lf->ntype = N_UNKN;
+        Lf->type = type != LSOF_FILE_NONE ? type : LSOF_FILE_UNKNOWN;
+        (void)enter_nm(ctx, path);
+        (void)snpf(nmabuf, sizeof(nmabuf), "(%ce %s)", ep->rdlnk ? '+' : '-',
+                   ep->path);
+        nmabuf[sizeof(nmabuf) - 1] = '\0';
+        (void)add_nma(ctx, nmabuf, strlen(nmabuf));
+        if (Lf->sf) {
+            if (lfr)
+                *lfr = Lf;
+            link_lfile(ctx);
+        } else if (lfr)
+            *lfr = (struct lfile *)NULL;
+        return (0);
+    }
+    return (1);
+}
+
+/*
+ * nm2id() - convert a name to an integer ID
+ */
+
+static int nm2id(char *nm, /* pointer to name */
+                 int *id,  /* pointer to ID receiver */
+                 int *idl) /* pointer to ID length receiver */
+{
+    int tid, tidl;
+    int invalid;
+
+    for (*id = *idl = tid = tidl = 0; *nm; nm++) {
+
+#if defined(__STDC__) /* { */
+        invalid = !isdigit((unsigned char)*nm);
+#else  /* !defined(__STDC__)	   } { */
+        invalid = !isascii(*nm) || !isdigit((unsigned char)*cp);
+#endif /* defined(__STDC__)	   } */
+        if (invalid) {
+            return (1);
+        }
+        tid = tid * 10 + (int)(*nm - '0');
+        tidl++;
+    }
+    *id = tid;
+    *idl = tidl;
+    return (0);
+}
+
+/*
+ * open_proc_stream() -- open a /proc stream
+ */
+
+FILE *open_proc_stream(struct lsof_context *ctx, /* context */
+                       char *p,                  /* pointer to path to open */
+                       char *m,    /* pointer to mode -- e.g., "r" */
+                       char **buf, /* pointer tp setvbuf() address
+                                    * (NULL if none) */
+                       size_t *sz, /* setvbuf() size (0 if none or if
+                                    * getpagesize() desired */
+                       int act)    /* fopen() failure action:
+                                    *     0 : return (FILE *)NULL
+                                    *   <>0 : fprintf() an error message
+                                    *         and Error()
+                                    */
+{
+    FILE *fs;                      /* opened stream */
+    static size_t psz = (size_t)0; /* page size */
+    size_t tsz;                    /* temporary size */
+    /*
+     * Open the stream.
+     */
+    if (!(fs = fopen(p, m))) {
+        if (!act)
+            return ((FILE *)NULL);
+        (void)fprintf(stderr, "%s: can't fopen(%s, \"%s\"): %s\n", Pn, p, m,
+                      strerror(errno));
+        Error(ctx);
+    }
+    /*
+     * Return the stream if no buffer change is required.
+     */
+    if (!buf)
+        return (fs);
+    /*
+     * Determine the buffer size required.
+     */
+    if (!(tsz = *sz)) {
+        if (!psz)
+            psz = getpagesize();
+        tsz = psz;
+    }
+    /*
+     * Allocate a buffer for the stream, as required.
+     */
+    if (!*buf) {
+        if (!(*buf = (char *)malloc((MALLOC_S)tsz))) {
+            (void)fprintf(stderr,
+                          "%s: can't allocate %d bytes for %s stream buffer\n",
+                          Pn, (int)tsz, p);
+            Error(ctx);
+        }
+        *sz = tsz;
+    }
+    /*
+     * Assign the buffer to the stream.
+     */
+    if (setvbuf(fs, *buf, _IOFBF, tsz)) {
+        (void)fprintf(stderr, "%s: setvbuf(%s)=%d failure: %s\n", Pn, p,
+                      (int)tsz, strerror(errno));
+        Error(ctx);
+    }
+    return (fs);
+}
+
+/*
+ * process_id - process ID: PID or LWP
+ *
+ * return:  0 == ID processed
+ *          1 == ID not processed
+ */
+
+static int process_id(struct lsof_context *ctx, /* context */
+                      char *idp,                /* pointer to ID's path */
+                      int idpl,    /* pointer to ID's path length */
+                      char *cmd,   /* pointer to ID's command */
+                      UID_ARG uid, /* ID's UID */
+                      int pid,     /* ID's PID */
+                      int ppid,    /* parent PID */
+                      int pgid,    /* parent GID */
+                      int tid,     /* task ID, if non-zero */
+                      char *tcmd)  /* task command, if non-NULL) */
+{
+    int av = 0;
+    static char *dpath = (char *)NULL;
+    static int dpathl = 0;
+    short efs, enls, enss, lnk, oty, pn, pss, sf;
+    int fd, i, ls = 0, n, ss, sv;
+    struct l_fdinfo fi;
+    DIR *fdp;
+    struct dirent *fp;
+    static char *ipath = (char *)NULL;
+    static int ipathl = 0;
+    int j = 0;
+    struct lfile *lfr;
+    struct stat lsb, sb;
+    char nmabuf[MAXPATHLEN + 1], pbuf[MAXPATHLEN + 1];
+    static char *path = (char *)NULL;
+    static int pathl = 0;
+    static char *pathi = (char *)NULL;
+    static int pathil = 0;
+    char *rest;
+    int txts = 0;
+
+#if defined(HASSELINUX)
+    cntxlist_t *cntxp;
+#endif /* defined(HASSELINUX) */
+
+    /*
+     * See if process is excluded.
+     */
+    if (is_proc_excl(ctx, pid, pgid, uid, &pss, &sf, tid) ||
+        is_cmd_excl(ctx, cmd, &pss, &sf)) {
+
+#if defined(HASEPTOPTS)
+        if (!FeptE)
+            return (1);
+#else  /* !defined(HASEPTOPTS) */
+        return (1);
+#endif /* defined(HASEPTOPTS) */
+    }
+    if (Cckreg && !FeptE) {
+
+        /*
+         * 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(ctx, pid, pgid, ppid, uid, cmd, (int)pss, (int)sf);
+    Plf = (struct lfile *)NULL;
+
+#if defined(HASTASKS)
+    /*
+     * Enter task information.
+     */
+    Lp->tid = tid;
+    if (tid && tcmd) {
+        if (!(Lp->tcmd = mkstrcpy(tcmd, (MALLOC_S *)NULL))) {
+            (void)fprintf(stderr,
+                          "%s: PID %d, TID %d, no space for task name: ", Pn,
+                          pid, tid);
+            safestrprt(tcmd, stderr, 1);
+            Error(ctx);
+        }
+    }
+#endif /* defined(HASTASKS) */
+
+    /*
+     * Process the ID's current working directory info.
+     */
+    efs = 0;
+    if (!Ckscko) {
+        (void)make_proc_path(ctx, idp, idpl, &path, &pathl, "cwd");
+        alloc_lfile(ctx, LSOF_FD_CWD, -1);
+        if (getlinksrc(path, pbuf, sizeof(pbuf), (char **)NULL) < 1) {
+            if (!Fwarn) {
+                zeromem((char *)&sb, sizeof(sb));
+                lnk = ss = 0;
+                (void)snpf(nmabuf, sizeof(nmabuf), "(readlink: %s)",
+                           strerror(errno));
+                nmabuf[sizeof(nmabuf) - 1] = '\0';
+                (void)add_nma(ctx, nmabuf, strlen(nmabuf));
+                pn = 1;
+            } else
+                pn = 0;
+        } else {
+            lnk = pn = 1;
+            if (Efsysl &&
+                !isefsys(ctx, pbuf, LSOF_FILE_UNKNOWN_CWD, 1, NULL, &lfr)) {
+                efs = 1;
+                pn = 0;
+            } else {
+                ss = SB_ALL;
+                if (HasNFS) {
+                    if ((sv = statsafely(ctx, path, &sb)))
+                        sv = statEx(ctx, pbuf, &sb, &ss);
+                } else
+                    sv = stat(path, &sb);
+                if (sv) {
+                    ss = 0;
+                    if (!Fwarn) {
+                        (void)snpf(nmabuf, sizeof(nmabuf), "(stat: %s)",
+                                   strerror(errno));
+                        nmabuf[sizeof(nmabuf) - 1] = '\0';
+                        (void)add_nma(ctx, nmabuf, strlen(nmabuf));
+                    }
+                }
+            }
+        }
+        if (pn) {
+            (void)process_proc_node(ctx, lnk ? pbuf : path, path, &sb, ss,
+                                    (struct stat *)NULL, 0);
+            if (Lf->sf)
+                link_lfile(ctx);
+        }
+    }
+    /*
+     * Process the ID's root directory info.
+     */
+    lnk = ss = 0;
+    if (!Ckscko) {
+        (void)make_proc_path(ctx, idp, idpl, &path, &pathl, "root");
+        alloc_lfile(ctx, LSOF_FD_ROOT_DIR, -1);
+        if (getlinksrc(path, pbuf, sizeof(pbuf), (char **)NULL) < 1) {
+            if (!Fwarn) {
+                zeromem((char *)&sb, sizeof(sb));
+                (void)snpf(nmabuf, sizeof(nmabuf), "(readlink: %s)",
+                           strerror(errno));
+                nmabuf[sizeof(nmabuf) - 1] = '\0';
+                (void)add_nma(ctx, nmabuf, strlen(nmabuf));
+                pn = 1;
+            } else
+                pn = 0;
+        } else {
+            lnk = pn = 1;
+            if (Efsysl &&
+                !isefsys(ctx, pbuf, LSOF_FILE_UNKNOWN_ROOT_DIR, 1, NULL, NULL))
+                pn = 0;
+            else {
+                ss = SB_ALL;
+                if (HasNFS) {
+                    if ((sv = statsafely(ctx, path, &sb)))
+                        sv = statEx(ctx, pbuf, &sb, &ss);
+                } else
+                    sv = stat(path, &sb);
+                if (sv) {
+                    ss = 0;
+                    if (!Fwarn) {
+                        (void)snpf(nmabuf, sizeof(nmabuf), "(stat: %s)",
+                                   strerror(errno));
+                        nmabuf[sizeof(nmabuf) - 1] = '\0';
+                        (void)add_nma(ctx, nmabuf, strlen(nmabuf));
+                    }
+                }
+            }
+        }
+        if (pn) {
+            (void)process_proc_node(ctx, lnk ? pbuf : path, path, &sb, ss,
+                                    (struct stat *)NULL, 0);
+            if (Lf->sf)
+                link_lfile(ctx);
+        }
+    }
+    /*
+     * Process the ID's execution info.
+     */
+    lnk = ss = txts = 0;
+    if (!Ckscko) {
+        (void)make_proc_path(ctx, idp, idpl, &path, &pathl, "exe");
+        alloc_lfile(ctx, LSOF_FD_PROGRAM_TEXT, -1);
+        if (getlinksrc(path, pbuf, sizeof(pbuf), (char **)NULL) < 1) {
+            zeromem((void *)&sb, sizeof(sb));
+            if (!Fwarn) {
+                if ((errno != ENOENT) || uid) {
+                    (void)snpf(nmabuf, sizeof(nmabuf), "(readlink: %s)",
+                               strerror(errno));
+                    nmabuf[sizeof(nmabuf) - 1] = '\0';
+                    (void)add_nma(ctx, nmabuf, strlen(nmabuf));
+                }
+                pn = 1;
+            } else
+                pn = 0;
+        } else {
+            lnk = pn = 1;
+            if (Efsysl && !isefsys(ctx, pbuf, LSOF_FILE_UNKNOWN_PROGRAM_TEXT, 1,
+                                   NULL, NULL))
+                pn = 0;
+            else {
+                ss = SB_ALL;
+                if (HasNFS) {
+                    if ((sv = statsafely(ctx, path, &sb))) {
+                        sv = statEx(ctx, pbuf, &sb, &ss);
+                        if (!sv && (ss & SB_DEV) && (ss & SB_INO))
+                            txts = 1;
+                    }
+                } else
+                    sv = stat(path, &sb);
+                if (sv) {
+                    ss = 0;
+                    if (!Fwarn) {
+                        (void)snpf(nmabuf, sizeof(nmabuf), "(stat: %s)",
+                                   strerror(errno));
+                        nmabuf[sizeof(nmabuf) - 1] = '\0';
+                        (void)add_nma(ctx, nmabuf, strlen(nmabuf));
+                    }
+                } else
+                    txts = 1;
+            }
+        }
+        if (pn) {
+            (void)process_proc_node(ctx, lnk ? pbuf : path, path, &sb, ss,
+                                    (struct stat *)NULL, 0);
+            if (Lf->sf)
+                link_lfile(ctx);
+        }
+    }
+    /*
+     * Process the ID's memory map info.
+     */
+    if (!Ckscko) {
+        (void)make_proc_path(ctx, idp, idpl, &path, &pathl, "maps");
+        (void)process_proc_map(ctx, path, txts ? &sb : (struct stat *)NULL,
+                               txts ? ss : 0);
+    }
+
+#if defined(HASSELINUX)
+    /*
+     * Process the PID's SELinux context.
+     */
+    /*
+     * match the valid contexts.
+     */
+    errno = 0;
+    if (getpidcon(pid, &Lp->cntx) == -1) {
+        Lp->cntx = (char *)NULL;
+        if (!Fwarn) {
+            (void)snpf(nmabuf, sizeof(nmabuf), "(getpidcon: %s)",
+                       strerror(errno));
+            if (!(Lp->cntx = strdup(nmabuf))) {
+                (void)fprintf(stderr, "%s: no context error space: PID %ld", Pn,
+                              (long)Lp->pid);
+                Error(ctx);
+            }
+        }
+    } else if (CntxArg) {
+
+        /*
+         * See if context includes the process.
+         */
+        for (cntxp = CntxArg; cntxp; cntxp = cntxp->next) {
+            if (cmp_cntx_eq(Lp->cntx, cntxp->cntx)) {
+                cntxp->f = 1;
+                Lp->pss |= PS_PRI;
+                Lp->sf |= SELCNTX;
+                break;
+            }
+        }
+    }
+#endif /* defined(HASSELINUX) */
+
+    /*
+     * Process the ID's file descriptor directory.
+     */
+    if ((i = make_proc_path(ctx, idp, idpl, &dpath, &dpathl, "fd/")) < 3)
+        return (0);
+    dpath[i - 1] = '\0';
+    if ((OffType == OFFSET_FDINFO) &&
+        ((j = make_proc_path(ctx, idp, idpl, &ipath, &ipathl, "fdinfo/")) >= 7))
+        oty = 1;
+    else
+        oty = 0;
+    if (!(fdp = opendir(dpath))) {
+        if (!Fwarn) {
+            (void)snpf(nmabuf, sizeof(nmabuf), "%s (opendir: %s)", dpath,
+                       strerror(errno));
+            alloc_lfile(ctx, LSOF_FD_NOFD, -1);
+            nmabuf[sizeof(nmabuf) - 1] = '\0';
+            (void)add_nma(ctx, nmabuf, strlen(nmabuf));
+            link_lfile(ctx);
+        }
+        return (0);
+    }
+    dpath[i - 1] = '/';
+    while ((fp = readdir(fdp))) {
+        if (nm2id(fp->d_name, &fd, &n))
+            continue;
+        (void)make_proc_path(ctx, dpath, i, &path, &pathl, fp->d_name);
+        (void)alloc_lfile(ctx, LSOF_FD_NUMERIC, fd);
+        if (getlinksrc(path, pbuf, sizeof(pbuf), &rest) < 1) {
+            zeromem((char *)&sb, sizeof(sb));
+            lnk = ss = 0;
+            if (!Fwarn) {
+                ls = 0;
+                (void)snpf(nmabuf, sizeof(nmabuf), "(readlink: %s)",
+                           strerror(errno));
+                nmabuf[sizeof(nmabuf) - 1] = '\0';
+                (void)add_nma(ctx, nmabuf, strlen(nmabuf));
+                pn = 1;
+            } else
+                pn = 0;
+        } else {
+            lnk = 1;
+            if (Efsysl &&
+                !isefsys(ctx, pbuf, LSOF_FILE_UNKNOWN_FD, 1, NULL, &lfr)) {
+                efs = 1;
+                pn = 0;
+            } else {
+                if (HasNFS) {
+                    if (lstatsafely(ctx, path, &lsb)) {
+                        (void)statEx(ctx, pbuf, &lsb, &ls);
+                        enls = errno;
+                    } else {
+                        enls = 0;
+                        ls = SB_ALL;
+                    }
+                    if (statsafely(ctx, path, &sb)) {
+                        (void)statEx(ctx, pbuf, &sb, &ss);
+                        enss = errno;
+                    } else {
+                        enss = 0;
+                        ss = SB_ALL;
+                    }
+                } else {
+                    ls = lstat(path, &lsb) ? 0 : SB_ALL;
+                    enls = errno;
+                    ss = stat(path, &sb) ? 0 : SB_ALL;
+                    enss = errno;
+                }
+                if (!ls && !Fwarn) {
+                    (void)snpf(nmabuf, sizeof(nmabuf), "lstat: %s)",
+                               strerror(enls));
+                    nmabuf[sizeof(nmabuf) - 1] = '\0';
+                    (void)add_nma(ctx, nmabuf, strlen(nmabuf));
+                }
+                if (!ss && !Fwarn) {
+                    (void)snpf(nmabuf, sizeof(nmabuf), "(stat: %s)",
+                               strerror(enss));
+                    nmabuf[sizeof(nmabuf) - 1] = '\0';
+                    (void)add_nma(ctx, nmabuf, strlen(nmabuf));
+                }
+                if (Ckscko) {
+                    if ((ss & SB_MODE) && ((sb.st_mode & S_IFMT) == S_IFSOCK)) {
+                        pn = 1;
+                    } else
+                        pn = 0;
+                } else
+                    pn = 1;
+            }
+        }
+        if (pn || (efs && lfr && oty)) {
+            /* Clear fi in case oty == 0 */
+            fi.eventfd_id = -1;
+            fi.pid = -1;
+            fi.tfd_count = -1;
+
+            if (oty) {
+                int fdinfo_mask = FDINFO_BASE;
+                (void)make_proc_path(ctx, ipath, j, &pathi, &pathil,
+                                     fp->d_name);
+
+                if (rest && rest[0] == '[' && rest[1] == 'e' &&
+                    rest[2] == 'v' && rest[3] == 'e' && rest[4] == 'n' &&
+                    rest[5] == 't') {
+#if defined(HASEPTOPTS)
+                    if (rest[6] == 'f')
+                        fdinfo_mask |= FDINFO_EVENTFD_ID;
+#endif /* defined(HASEPTOPTS) */
+                    else if (rest[6] == 'p')
+                        fdinfo_mask |= FDINFO_TFD;
+                }
+#if defined(HASEPTOPTS)
+#    if defined(HASPTYEPT)
+                fdinfo_mask |= FDINFO_TTY_INDEX;
+#    endif /* defined(HASPTYEPT) */
+#endif     /* defined(HASEPTOPTS) */
+                if (rest && rest[0] == '[' && rest[1] == 'p')
+                    fdinfo_mask |= FDINFO_PID;
+                else if (Lf->ntype == N_REGLR && rest && *rest && strcmp(pbuf, "pidfd") == 0) {
+                    // https://github.com/lsof-org/lsof/issues/317
+                    fdinfo_mask |= FDINFO_PID;
+                }
+
+                if ((av = get_fdinfo(ctx, pathi, fdinfo_mask, &fi)) &
+                    FDINFO_POS) {
+                    if (efs) {
+                        lfr->off = (SZOFFTYPE)fi.pos;
+                        lfr->off_def = 1;
+                    } else {
+                        ls |= SB_SIZE;
+                        lsb.st_size = fi.pos;
+                    }
+                } else
+                    ls &= ~SB_SIZE;
+
+#if !defined(HASNOFSFLAGS)
+                if (av & FDINFO_FLAGS) {
+                    if (efs) {
+                        lfr->ffg = (long)fi.flags;
+                        lfr->fsv |= FSV_FG;
+                    } else {
+                        Lf->ffg = (long)fi.flags;
+                        Lf->fsv |= FSV_FG;
+                    }
+                }
+#endif /* !defined(HASNOFSFLAGS) */
+            }
+            if (pn) {
+                process_proc_node(ctx, lnk ? pbuf : path, path, &sb, ss, &lsb,
+                                  ls);
+                if (Lf->ntype == N_ANON_INODE) {
+                    if (rest && *rest) {
+#if defined(HASEPTOPTS)
+                        if (fi.eventfd_id != -1 &&
+                            strcmp(rest, "[eventfd]") == 0) {
+                            (void)snpf(rest, sizeof(pbuf) - (rest - pbuf),
+                                       "[eventfd:%d]", fi.eventfd_id);
+                        }
+#endif /* defined(HASPTYEPT) */
+                        if (fi.pid != -1 && strcmp(rest, "[pidfd]") == 0) {
+                            (void)snpf(rest, sizeof(pbuf) - (rest - pbuf),
+                                       "[pidfd:%d]", fi.pid);
+                        }
+                        if (fi.tfd_count > 0 &&
+                            strcmp(rest, "[eventpoll]") == 0) {
+                            snp_eventpoll(rest, sizeof(pbuf) - (rest - pbuf),
+                                          fi.tfds, fi.tfd_count);
+                        }
+
+                        enter_nm(ctx, rest);
+                    }
+#if defined(HASEPTOPTS)
+                    if (FeptE && fi.eventfd_id != -1) {
+                        enter_evtfdinfo(ctx, fi.eventfd_id);
+                        Lf->eventfd_id = fi.eventfd_id;
+                        Lf->sf |= SELEVTFDINFO;
+                    }
+#endif /* defined(HASPTYEPT) */
+                }
+#if defined(HASEPTOPTS) && defined(HASPTYEPT)
+                else if (FeptE && Lf->rdev_def && is_pty_ptmx(Lf->rdev) &&
+                         (av & FDINFO_TTY_INDEX)) {
+                    enter_ptmxi(ctx, fi.tty_index);
+                    Lf->tty_index = fi.tty_index;
+                    Lf->sf |= SELPTYINFO;
+                }
+#endif /* defined(HASEPTOPTS) && defined(HASPTYEPT) */
+                else if (Lf->ntype == N_REGLR && rest && *rest && Lf->nm &&
+                         strcmp(Lf->nm, "pidfd") == 0) {
+                    // https://github.com/lsof-org/lsof/issues/317
+                    // pidfd since Linux 6.9 becomes a regular file:
+                    // /proc/PID/fd/FD -> pidfd:[INODE]
+                    (void)snpf(rest, sizeof(pbuf) - (rest - pbuf),
+                                "[pidfd:%d]", fi.pid);
+                    enter_nm(ctx, rest);
+                }
+
+                if (Lf->sf)
+                    link_lfile(ctx);
+            }
+        }
+    }
+    (void)closedir(fdp);
+    return (0);
+}
+
+/* compare mount namespace of this lsof process and the target process */
+
+static int compare_mntns(int pid) /* pid of the target process */
+{
+    char nspath[NS_PATH_LENGTH];
+    struct stat sb_self, sb_target;
+    int ret;
+
+    if (stat("/proc/self/ns/mnt", &sb_self))
+        return -1;
+
+    ret = snprintf(nspath, sizeof(nspath), "/proc/%d/ns/mnt", pid);
+    if (ret >= sizeof(nspath) || ret <= 0)
+        return -1;
+
+    if (stat(nspath, &sb_target))
+        return -1;
+
+    if (sb_self.st_ino != sb_target.st_ino)
+        return -1;
+
+    return 0;
+}
+
+/*
+ * process_proc_map() - process the memory map of a process
+ */
+
+static void
+process_proc_map(struct lsof_context *ctx, /* context */
+                 char *p,                  /* path to process maps file */
+                 struct stat *s, /* executing text file state buffer */
+                 int ss)         /* *s status -- i.e., SB_* values */
+{
+    char buf[MAXPATHLEN + 1], *ep, fmtbuf[32], **fp, nmabuf[MAXPATHLEN + 1];
+    dev_t dev;
+    int ds, efs, en, i, mss, sv;
+    int eb = 6;
+    INODETYPE inode;
+    MALLOC_S len;
+    long maj, min;
+    FILE *ms;
+    int ns = 0;
+    struct stat sb;
+    struct saved_map {
+        dev_t dev;
+        INODETYPE inode;
+    };
+    static struct saved_map *sm = (struct saved_map *)NULL;
+    efsys_list_t *rep;
+    static int sma = 0;
+    static char *vbuf = (char *)NULL;
+    static size_t vsz = (size_t)0;
+    int diff_mntns = 0;
+    /*
+     * Open the /proc/<pid>/maps file, assign a page size buffer to its stream,
+     * and read it/
+     */
+    if (!(ms = open_proc_stream(ctx, p, "r", &vbuf, &vsz, 0)))
+        return;
+
+    /* target process in a different mount namespace from lsof process. */
+    if (compare_mntns(Lp->pid))
+        diff_mntns = 1;
+
+    while (fgets(buf, sizeof(buf), ms)) {
+        if (get_fields(ctx, buf, ":", &fp, &eb, 1) < 7)
+            continue; /* not enough fields */
+        if (!fp[6] || !*fp[6])
+            continue; /* no path name */
+        /*
+         * See if the path ends in " (deleted)".  If it does, strip the
+         * " (deleted)" characters and remember that they were there.
+         */
+        if (((ds = (int)strlen(fp[6])) > 10) &&
+            !strcmp(fp[6] + ds - 10, " (deleted)")) {
+            *(fp[6] + ds - 10) = '\0';
+        } else
+            ds = 0;
+        /*
+         * Assemble the major and minor device numbers.
+         */
+        ep = (char *)NULL;
+        if (!fp[3] || !*fp[3] || (maj = strtol(fp[3], &ep, 16)) == LONG_MIN ||
+            maj == LONG_MAX || !ep || *ep)
+            continue;
+        ep = (char *)NULL;
+        if (!fp[4] || !*fp[4] || (min = strtol(fp[4], &ep, 16)) == LONG_MIN ||
+            min == LONG_MAX || !ep || *ep)
+            continue;
+        /*
+         * Assemble the device and inode numbers.  If they are both zero, skip
+         * the entry.
+         */
+        dev = (dev_t)makedev((int)maj, (int)min);
+        if (!fp[5] || !*fp[5])
+            continue;
+        ep = (char *)NULL;
+        if ((inode = strtoull(fp[5], &ep, 0)) == ULLONG_MAX || !ep || *ep)
+            continue;
+        if (!dev && !inode)
+            continue;
+        /*
+         * See if the device + inode pair match that of the executable.
+         * If they do, skip this map entry.
+         */
+        if (s && (ss & SB_DEV) && (ss & SB_INO) && (dev == s->st_dev) &&
+            (inode == (INODETYPE)s->st_ino))
+            continue;
+        /*
+         * See if this device + inode pair has already been processed as
+         * a map entry.
+         */
+        for (i = 0; i < ns; i++) {
+            if (dev == sm[i].dev && inode == sm[i].inode)
+                break;
+        }
+        if (i < ns)
+            continue;
+        /*
+         * Record the processing of this map entry's device and inode pair.
+         */
+        if (ns >= sma) {
+            sma += 10;
+            len = (MALLOC_S)(sma * sizeof(struct saved_map));
+            if (sm)
+                sm = (struct saved_map *)realloc(sm, len);
+            else
+                sm = (struct saved_map *)malloc(len);
+            if (!sm) {
+                (void)fprintf(
+                    stderr,
+                    "%s: can't allocate %d bytes for saved maps, PID %d\n", Pn,
+                    (int)len, Lp->pid);
+                Error(ctx);
+            }
+        }
+        sm[ns].dev = dev;
+        sm[ns++].inode = inode;
+        /*
+         * Allocate space for the mapped file, then get stat(2) information
+         * for it.  Skip the stat(2) operation if this is on an exempt file
+         * system.
+         */
+        alloc_lfile(ctx, LSOF_FD_MEMORY, -1);
+        if (Efsysl && !isefsys(ctx, fp[6], LSOF_FILE_NONE, 0, &rep, NULL))
+            efs = sv = 1;
+        else
+            efs = 0;
+
+        /* For processes in different mount namespace from lsof process,
+         * stat corresponding files under /proc/[pid]/map_files would follow
+         * symlinks regardless of namespaces.
+         */
+        if (diff_mntns) {
+            char path[MAP_PATH_LENGTH];
+            char addr[ADDR_LENGTH];
+            uint64_t start, end;
+            int ret;
+
+            if (sscanf(fp[0], "%" SCNx64 "-%" SCNx64, &start, &end) != 2)
+                goto stat_directly;
+
+            ret = snprintf(addr, sizeof(addr), "%" PRIx64 "-%" PRIx64, start,
+                           end);
+            if (ret >= sizeof(addr) || ret <= 0)
+                goto stat_directly;
+
+            ret = snprintf(path, sizeof(path), "/proc/%d/map_files/%s", Lp->pid,
+                           addr);
+            if (ret >= sizeof(path) || ret <= 0)
+                goto stat_directly;
+
+            if (!efs) {
+                if (HasNFS)
+                    sv = statsafely(ctx, path, &sb);
+                else
+                    sv = stat(path, &sb);
+            }
+        } else {
+        stat_directly:
+            if (!efs) {
+                if (HasNFS)
+                    sv = statsafely(ctx, fp[6], &sb);
+                else
+                    sv = stat(fp[6], &sb);
+            }
+        }
+        if (sv || efs) {
+            en = errno;
+            /*
+             * Applying stat(2) to the file was not possible (file is on an
+             * exempt file system) or stat(2) failed, so manufacture a partial
+             * stat(2) reply from the process' maps file entry.
+             *
+             * If the file has been deleted, reset its type to "DEL";
+             * otherwise generate a stat() error name addition.
+             */
+            zeromem((char *)&sb, sizeof(sb));
+            sb.st_dev = dev;
+            sb.st_ino = (ino_t)inode;
+            sb.st_mode = S_IFREG;
+            mss = SB_DEV | SB_INO | SB_MODE;
+            if (ds)
+                alloc_lfile(ctx, LSOF_FD_DELETED, -1);
+            else if (!efs && !Fwarn) {
+                (void)snpf(nmabuf, sizeof(nmabuf), "(stat: %s)", strerror(en));
+                nmabuf[sizeof(nmabuf) - 1] = '\0';
+                (void)add_nma(ctx, nmabuf, strlen(nmabuf));
+            }
+        } else if (diff_mntns) {
+            mss = SB_ALL;
+        } else if ((sb.st_dev != dev) || ((INODETYPE)sb.st_ino != inode)) {
+
+            /*
+             * The stat(2) device and inode numbers don't match those obtained
+             * from the process' maps file.
+             *
+             * If the file has been deleted, reset its type to "DEL"; otherwise
+             * generate inconsistency name additions.
+             *
+             * Manufacture a partial stat(2) reply from the maps file
+             * information.
+             */
+            if (ds)
+                alloc_lfile(ctx, LSOF_FD_DELETED, -1);
+            else if (!Fwarn) {
+                char *sep;
+
+                if (sb.st_dev != dev) {
+                    (void)snpf(nmabuf, sizeof(nmabuf), "(path dev=%d,%d%s",
+                               GET_MAJ_DEV(sb.st_dev), GET_MIN_DEV(sb.st_dev),
+                               ((INODETYPE)sb.st_ino == inode) ? ")" : ",");
+                    nmabuf[sizeof(nmabuf) - 1] = '\0';
+                    (void)add_nma(ctx, nmabuf, strlen(nmabuf));
+                    sep = "";
+                } else
+                    sep = "(path ";
+                if ((INODETYPE)sb.st_ino != inode) {
+                    (void)snpf(fmtbuf, sizeof(fmtbuf),
+                               "%%sinode=%%" INODEPSPEC "u)");
+                    (void)snpf(nmabuf, sizeof(nmabuf), fmtbuf, sep,
+                               (INODETYPE)sb.st_ino);
+                    nmabuf[sizeof(nmabuf) - 1] = '\0';
+                    (void)add_nma(ctx, nmabuf, strlen(nmabuf));
+                }
+            }
+            zeromem((char *)&sb, sizeof(sb));
+            sb.st_dev = dev;
+            sb.st_ino = (ino_t)inode;
+            sb.st_mode = S_IFREG;
+            mss = SB_DEV | SB_INO | SB_MODE;
+        } else
+            mss = SB_ALL;
+        /*
+         * Record the file's information.
+         */
+        if (!efs)
+            process_proc_node(ctx, fp[6], fp[6], &sb, mss, (struct stat *)NULL,
+                              0);
+        else {
+
+            /*
+             * If this file is on an exempt file system, complete the lfile
+             * structure, but change its type and add the exemption note to
+             * the NAME column.
+             */
+            Lf->dev = sb.st_dev;
+            Lf->inode = (ino_t)sb.st_ino;
+            Lf->dev_def = Lf->inp_ty = 1;
+            (void)enter_nm(ctx, fp[6]);
+            Lf->type =
+                ds ? LSOF_FILE_UNKNOWN_DELETED : LSOF_FILE_UNKNOWN_MEMORY;
+            (void)snpf(nmabuf, sizeof(nmabuf), "(%ce %s)",
+                       rep->rdlnk ? '+' : '-', rep->path);
+            nmabuf[sizeof(nmabuf) - 1] = '\0';
+            (void)add_nma(ctx, nmabuf, strlen(nmabuf));
+        }
+        if (Lf->sf)
+            link_lfile(ctx);
+    }
+    (void)fclose(ms);
+}
+
+/*
+ * read_id_stat() - read ID (PID or LWP ID) status
+ *
+ * return: -1 == ID is unavailable
+ *          0 == ID OK
+ *          1 == ID is a zombie
+ *	    2 == ID is a thread
+ */
+static int read_id_stat(struct lsof_context *ctx, /* context */
+                        char *p,                  /* path to status file */
+                        int id,                   /* ID: PID or LWP */
+                        char **cmd,               /* malloc'd command name */
+                        int *ppid, /* returned parent PID for PID type */
+                        int *pgid) /* returned process group ID for PID
+                                    * type */
+{
+    char buf[MAXPATHLEN], *cp, *cp1, **fp;
+    int ch, cx, es, pc;
+    static char *cbf = (char *)NULL;
+    static MALLOC_S cbfa = 0;
+    FILE *fs;
+    static char *vbuf = (char *)NULL;
+    static size_t vsz = (size_t)0;
+    /*
+     * Open the stat file path, assign a page size buffer to its stream,
+     * and read the file's first line.
+     */
+    if (!(fs = open_proc_stream(ctx, p, "r", &vbuf, &vsz, 0)))
+        return (-1);
+    if (!(cp = fgets(buf, sizeof(buf), fs))) {
+
+    read_id_stat_exit:
+
+        (void)fclose(fs);
+        return (-1);
+    }
+    /*
+     * Skip to the first field, and make sure it is a matching ID.
+     */
+    cp1 = cp;
+    while (*cp && (*cp != ' ') && (*cp != '\t'))
+        cp++;
+    if (*cp)
+        *cp = '\0';
+    if (atoi(cp1) != id)
+        goto read_id_stat_exit;
+    /*
+     * 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.
+     *
+     */
+    for (++cp; *cp && (*cp == ' '); cp++)
+        ;
+    if (!cp || (*cp != '('))
+        goto read_id_stat_exit;
+    cp++;
+    pc = 1; /* start the parenthesis balance count at 1 */
+
+    /* empty process name to avoid leaking previous process name,
+     * see issue #246
+     */
+    if (cbf) {
+        cbf[0] = '\0';
+    }
+
+    /*
+     * 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.  Count embedded '(' characters and balance
+     * them with embedded ')' characters.  The opening '(' starts the balance
+     * count at one.
+     */
+    for (cx = es = 0;;) {
+        if (!es)
+            ch = *cp++;
+        else {
+            if ((ch = fgetc(fs)) == EOF)
+                goto read_id_stat_exit;
+        }
+        if (ch == '(') /* a '(' advances the balance count */
+            pc++;
+        if (ch == ')') {
+
+            /*
+             * Balance parentheses when a closure is encountered.  When
+             * they are balanced, this is the end of the command.
+             */
+            pc--;
+            if (!pc)
+                break;
+        }
+        if ((cx + 2) > cbfa)
+            cbfa = alloc_cbf(ctx, (cx + 2), &cbf, cbfa);
+        cbf[cx] = ch;
+        cx++;
+        cbf[cx] = '\0';
+        if (!es && !*cp)
+            es = 1; /* Switch to fgetc() when a '\0' appears. */
+    }
+    *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 (get_fields(ctx, 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[1] && *fp[1])
+        *ppid = atoi(fp[1]);
+    else
+        return (-1);
+    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[0] && !strcmp(fp[0], "Z"))
+        return (1);
+    else if (fp[0] && !strcmp(fp[0], "T"))
+        return (2);
+    return (0);
+}
+
+/*
+ * statEx() - extended stat() to get device numbers when a "safe" stat has
+ *	      failed and the system has an NFS mount
+ *
+ * Note: this function was suggested by Paul Szabo as a way to get device
+ *       numbers for NFS files when an NFS mount point has the root_squash
+ *       option set.  In that case, even if lsof is setuid(root), the identity
+ *	 of its requests to stat() NFS files lose root permission and may fail.
+ *
+ *	 This function should be used only when links have been successfully
+ *	 resolved in the /proc path by getlinksrc().
+ */
+static int statEx(struct lsof_context *ctx, /* context */
+                  char *p,                  /* file path */
+                  struct stat *s,           /* stat() result -- NULL if none
+                                             * wanted */
+                  int *ss)                  /* stat() status --  SB_* values */
+{
+    static size_t ca = 0;
+    static char *cb = NULL;
+    char *cp;
+    int ensv = ENOENT;
+    struct stat sb;
+    int st = 0;
+    size_t sz;
+    /*
+     * Make a copy of the path.
+     */
+    sz = strlen(p);
+    if ((sz + 1) > ca) {
+        if (cb)
+            cb = (char *)realloc((MALLOC_P *)cb, sz + 1);
+        else
+            cb = (char *)malloc(sz + 1);
+        if (!cb) {
+            (void)fprintf(stderr, "%s: PID %ld: no statEx path space: %s\n", Pn,
+                          (long)Lp->pid, p);
+            Error(ctx);
+        }
+        ca = sz + 1;
+    }
+    (void)strcpy(cb, p);
+    /*
+     * Trim trailing leaves from the end of the path one at a time and do a safe
+     * stat() on each trimmed result.  Stop when a safe stat() succeeds or
+     * doesn't fail because of EACCES or EPERM.
+     */
+    for (cp = strrchr(cb, '/'); cp && (cp != cb);) {
+        *cp = '\0';
+        if (!statsafely(ctx, cb, &sb)) {
+            st = 1;
+            break;
+        }
+        ensv = errno;
+        if ((ensv != EACCES) && (ensv != EPERM))
+            break;
+        cp = strrchr(cb, '/');
+    }
+    /*
+     * If a stat() on a trimmed result succeeded, form partial results
+     * containing only the device and raw device numbers.
+     */
+    zeromem((char *)s, sizeof(struct stat));
+    if (st) {
+        errno = 0;
+        s->st_dev = sb.st_dev;
+        s->st_rdev = sb.st_rdev;
+        *ss = SB_DEV | SB_RDEV;
+        return (0);
+    }
+    errno = ensv;
+    *ss = 0;
+    return (1);
+}
+
+static int cal_order(int n) {
+    int i = 0;
+    do {
+        n /= 10;
+        i++;
+    } while (n);
+    return i;
+}
+
+static int snp_eventpoll_fds(char *p, int len, int *tfds, int count) {
+    int wl = 0;
+    int i;
+
+    if (len > 0)
+        p[0] = '\0';
+
+    for (i = 0; i < count; i++) {
+        int is_last_item = (i == count - 1);
+        int needs = cal_order(tfds[i]) + (is_last_item ? 0 : 3);
+
+        if ((len - wl + (wl ? 2 : 0)) <= needs) {
+            /* No space to print the tfd. */
+            break;
+        }
+
+        if (wl) {
+            /* Rewrite the last "..." to ",". */
+            wl -= 3;
+            p[wl++] = ',';
+        }
+        wl += snpf(p + wl, len - wl, (is_last_item ? "%d" : "%d..."), tfds[i]);
+    }
+
+    return wl;
+}
+
+static int fd_compare(const void *a, const void *b) {
+    int ia = *(int *)a, ib = *(int *)b;
+
+    return ia - ib;
+}
+
+static void snp_eventpoll(char *p, int len, int *tfds, int tfd_count) {
+    /* Reserve the area for prefix: "[eventpoll:" */
+    len -= 11;
+    /* Reserve the area for postfix */
+    len -= ((tfd_count == EPOLL_MAX_TFDS) ? 4 /* "...]" */
+                                          : 1 /* "]" */
+            ) +
+           1 /* for the last \0 */
+        ;
+
+    if (len > 1) {
+        qsort(tfds, tfd_count, sizeof(tfds[0]), fd_compare);
+
+        p[10] = ':'; /* "[eventpoll]" => "[eventpoll:" */
+        int wl = snp_eventpoll_fds(p + 11, len, tfds, tfd_count);
+
+        /* If the buffer doesn't have enough space, snp_eventpoll_fds puts
+         * "..." at the end of the buffer. In that case we don't
+         * have to "..." here.
+         */
+        const char *postfix =
+            ((wl > 3 && p[11 + wl - 1] == '.')
+                 ? "]"
+                 : ((tfd_count == EPOLL_MAX_TFDS)
+                        /* File descriptors more than EPOLL_MAX_TFDS are
+                         * associated to the eventpoll fd. */
+                        ? "...]"
+                        : "]"));
+        strcpy(p + 11 + wl, postfix);
+    }
+}
diff --git a/lib/dialects/linux/dproto.h b/lib/dialects/linux/dproto.h
new file mode 100644
index 0000000..defa7b8
--- /dev/null
+++ b/lib/dialects/linux/dproto.h
@@ -0,0 +1,69 @@
+/*
+ * dproto.h - Linux function prototypes for /proc-based lsof
+ *
+ * The _PROTOTYPE macro is defined in the common proto.h.
+ */
+
+/*
+ * 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.
+ */
+
+/*
+ * $Id: dproto.h,v 1.9 2013/01/02 17:02:36 abe Exp $
+ */
+
+#if defined(HASSELINUX)
+extern int enter_cntx_arg(struct lsof_context *ctx, char *cnxt);
+#endif /* defined(HASSELINUX) */
+
+extern int get_fields(struct lsof_context *ctx, char *ln, char *sep, char ***fr,
+                      int *eb, int en);
+extern void get_locks(struct lsof_context *ctx, char *p);
+extern void clean_locks(struct lsof_context *ctx);
+extern void clean_ax25(struct lsof_context *ctx);
+extern void clean_icmp(struct lsof_context *ctx);
+extern void clean_ipx(struct lsof_context *ctx);
+extern void clean_netlink(struct lsof_context *ctx);
+extern void clean_pack(struct lsof_context *ctx);
+extern void clean_raw(struct lsof_context *ctx);
+extern void clean_sctp(struct lsof_context *ctx);
+extern void clean_unix(struct lsof_context *ctx);
+extern void clean_tcpudp(struct lsof_context *ctx, int free_array);
+#if defined(HASIPv6)
+extern void clean_raw6(struct lsof_context *ctx);
+extern void clean_tcpudp6(struct lsof_context *ctx, int free_array);
+#endif
+extern int is_file_named(struct lsof_context *ctx, int ty, char *p,
+                         struct mounts *mp, int cd);
+extern int make_proc_path(struct lsof_context *ctx, char *pp, int lp, char **np,
+                          int *npl, char *sf);
+extern FILE *open_proc_stream(struct lsof_context *ctx, char *p, char *mode,
+                              char **buf, size_t *sz, int act);
+extern void process_proc_node(struct lsof_context *ctx, char *p, char *pbr,
+                              struct stat *s, int ss, struct stat *l, int ls);
+extern void process_proc_sock(struct lsof_context *ctx, char *p, char *pbr,
+                              struct stat *s, int ss, struct stat *l, int ls);
+extern void set_net_paths(struct lsof_context *ctx, char *p, int pl);
+extern void refresh_socket_info(struct lsof_context *ctx);
\ No newline at end of file
diff --git a/lib/dialects/linux/dsock.c b/lib/dialects/linux/dsock.c
new file mode 100644
index 0000000..d049643
--- /dev/null
+++ b/lib/dialects/linux/dsock.c
@@ -0,0 +1,5013 @@
+/*
+ * dsock.c - Linux socket processing functions for /proc-based lsof
+ */
+
+/*
+ * 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.
+ */
+
+#include "common.h"
+#include <sys/xattr.h>
+#include "hash.h"
+
+#if defined(HASEPTOPTS) && defined(HASUXSOCKEPT)
+/*
+ * UNIX endpoint definitions
+ */
+
+#    include <sys/socket.h>      /* for AF_NETLINK */
+#    include <linux/rtnetlink.h> /* for NETLINK_INET_DIAG */
+#    include <linux/sock_diag.h> /* for SOCK_DIAG_BY_FAMILY */
+#    include <linux/unix_diag.h> /* for unix_diag_req */
+#    include <string.h>          /* memset */
+#    include <stdint.h>          /* for unt8_t */
+#    include <unistd.h>          /* for getpagesize */
+#    define SOCKET_BUFFER_SIZE (getpagesize() < 8192L ? getpagesize() : 8192L)
+#endif /* defined(HASEPTOPTS) && defined(HASUXSOCKEPT) */
+
+#if defined(HASSOSTATE)
+#    include <linux/net.h> /* for SS_* */
+#endif                     /* defined(HASSOSTATE) */
+
+/*
+ * Local definitions
+ */
+
+#define INOBUCKS                                                               \
+    128 /* inode hash bucket count -- must be                                  \
+         * a power of two */
+#define INOHASH(ino) ((int)((ino * 31415) >> 3) & (INOBUCKS - 1))
+#define TCPUDPHASH(ino) ((int)((ino * 31415) >> 3) & (TcpUdp_bucks - 1))
+#define TCPUDP6HASH(ino) ((int)((ino * 31415) >> 3) & (TcpUdp6_bucks - 1))
+
+#define IPCBUCKS                                                               \
+    4096 /* IPC hash bucket count -- must be                                   \
+          * a power of two */
+
+/* If a socket is used for IPC, we store both end points for the socket
+ * to the same hash bucket. This makes searching the counter part of
+ * an end point easier. See get_netpeeri(). */
+#define TCPUDP_IPC_HASH(tp)                                                    \
+    ((int)(((((tp)->faddr * 0x109 + (tp)->laddr * 0x109 +                      \
+              (tp)->fport * 0x121 + (tp)->lport * 0x121 +                      \
+              (tp)->proto * 0x181) *                                           \
+             31415) >>                                                         \
+            3) &                                                               \
+           (IPCBUCKS - 1)))
+
+#define TCPUDP6_IPC_ADDR_INT32(a, n) (((a)->s6_addr32[n]))
+#define TCPUDP6_IPC_ADDR_MK_INT(a)                                             \
+    ((int)TCPUDP6_IPC_ADDR_INT32(a, 0x0) * 0x123 +                             \
+     (int)TCPUDP6_IPC_ADDR_INT32(a, 0x1) * 0x111 +                             \
+     (int)TCPUDP6_IPC_ADDR_INT32(a, 0x2) * 0x149 +                             \
+     (int)TCPUDP6_IPC_ADDR_INT32(a, 0x3) * 0x185)
+
+#define TCPUDP6_IPC_HASH(tp)                                                   \
+    ((int)((((TCPUDP6_IPC_ADDR_MK_INT(&(tp)->faddr) +                          \
+              TCPUDP6_IPC_ADDR_MK_INT(&(tp)->laddr) + (tp)->fport * 0x109 +    \
+              (tp)->lport * 0x109 + (tp)->proto * 0x141) *                     \
+             31415) >>                                                         \
+            3) &                                                               \
+           (IPCBUCKS - 1)))
+
+/*
+ * Local structures
+ */
+
+struct ax25sin {  /* AX25 socket information */
+    char *da;     /* destination address */
+    char *dev_ch; /* device characters */
+    char *sa;     /* source address */
+    INODETYPE inode;
+    unsigned long sq, rq;   /* send and receive queue values */
+    unsigned char sqs, rqs; /* send and receive queue states */
+    int state;
+    struct ax25sin *next;
+};
+
+struct icmpin {
+    INODETYPE inode; /* node number */
+    char *la;        /* local address */
+    char *ra;        /* remote address */
+    MALLOC_S lal;    /* strlen(la) */
+    MALLOC_S ral;    /* strlen(ra) */
+    struct icmpin *next;
+};
+
+struct ipxsin { /* IPX socket information */
+    INODETYPE inode;
+    char *la; /* local address */
+    char *ra; /* remote address */
+    int state;
+    unsigned long txq, rxq; /* transmit and receive queue values */
+    struct ipxsin *next;
+};
+
+struct nlksin {      /* Netlink socket information */
+    INODETYPE inode; /* node number */
+    unsigned int pr; /* protocol */
+    struct nlksin *next;
+};
+
+struct packin { /* packet information */
+    INODETYPE inode;
+    int ty; /* socket type */
+    int pr; /* protocol */
+    struct packin *next;
+};
+
+struct rawsin { /* raw socket information */
+    INODETYPE inode;
+    char *la;     /* local address */
+    char *ra;     /* remote address */
+    char *sp;     /* state characters */
+    MALLOC_S lal; /* strlen(la) */
+    MALLOC_S ral; /* strlen(ra) */
+    MALLOC_S spl; /* strlen(sp) */
+    struct rawsin *next;
+};
+
+struct sctpsin { /* SCTP socket information */
+    INODETYPE inode;
+    int type;      /* type: 0 = assoc
+                    *	 1 = eps
+                    *	 2  assoc and eps */
+    char *addr;    /* association or endpoint address */
+    char *assocID; /* association ID */
+    char *lport;   /* local port */
+    char *rport;   /* remote port */
+    char *laddrs;  /* local address */
+    char *raddrs;  /* remote address */
+    struct sctpsin *next;
+};
+
+struct tcp_udp { /* IPv4 TCP and UDP socket
+                  * information */
+    INODETYPE inode;
+    unsigned long faddr, laddr; /* foreign & local IPv4 addresses */
+    int fport, lport;           /* foreign & local ports */
+    unsigned long txq, rxq;     /* transmit & receive queue values */
+    int proto;                  /* 0 = TCP, 1 = UDP, 2 = UDPLITE */
+    int state;                  /* protocol state */
+    struct tcp_udp *next;       /* in TcpUdp inode hash table */
+#if defined(HASEPTOPTS)
+    pxinfo_t *pxinfo;         /* inode information */
+    struct tcp_udp *ipc_next; /* in TcpUdp local ipc hash table */
+    struct tcp_udp *ipc_peer; /* locally connected peer(s) info */
+#endif                        /* defined(HASEPTOPTS) */
+};
+
+#if defined(HASIPv6)
+struct tcp_udp6 { /* IPv6 TCP and UDP socket
+                   * information */
+    INODETYPE inode;
+    struct in6_addr faddr, laddr; /* foreign & local IPv6 addresses */
+    int fport, lport;             /* foreign & local ports */
+    unsigned long txq, rxq;       /* transmit & receive queue values */
+    int proto;                    /* 0 = TCP, 1 = UDP, 2 = UDPLITE */
+    int state;                    /* protocol state */
+    struct tcp_udp6 *next;
+#    if defined(HASEPTOPTS)
+    pxinfo_t *pxinfo;          /* inode information */
+    struct tcp_udp6 *ipc_next; /* in TcpUdp6 local ipc hash table */
+    struct tcp_udp6 *ipc_peer; /* locally connected peer(s) info */
+#    endif                     /* defined(HASEPTOPTS) */
+};
+#endif /* defined(HASIPv6) */
+
+typedef struct uxsin {    /* UNIX socket information */
+    INODETYPE inode;      /* node number */
+    char *pcb;            /* protocol control block */
+    char *path;           /* file path */
+    unsigned char sb_def; /* stat(2) buffer definitions */
+    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 */
+    unsigned int opt;     /* socket options */
+    unsigned int ss;      /* socket state */
+
+#if defined(HASEPTOPTS) && defined(HASUXSOCKEPT)
+    struct uxsin *icons; /* incoming socket connections */
+    unsigned int icstat; /* incoming connection status
+                          * 0 == none */
+    pxinfo_t *pxinfo;    /* inode information */
+    struct uxsin *peer;  /* connected peer(s) info */
+#endif                   /* defined(HASEPTOPTS) && defined(HASUXSOCKEPT) */
+
+    struct uxsin *next;
+} uxsin_t;
+
+/*
+ * Local static values
+ */
+
+static char *AX25path = (char *)NULL; /* path to AX25 /proc information */
+/* AX25 socket info, hashed by inode */
+static struct ax25sin **AX25sin = (struct ax25sin **)NULL;
+static char *ax25st[] = {
+    "LISTENING",   /* 0 */
+    "SABM SENT",   /* 1 */
+    "DISC SENT",   /* 2 */
+    "ESTABLISHED", /* 3 */
+    "RECOVERY"     /* 4 */
+};
+#define NAX25ST (sizeof(ax25st) / sizeof(char *))
+static char *ICMPpath = (char *)NULL; /* path to ICMP /proc information */
+/* ICMP socket info, hashed by inode */
+static struct icmpin **Icmpin = (struct icmpin **)NULL;
+static char *Ipxpath = (char *)NULL; /* path to IPX /proc information */
+/* IPX socket info, hashed by inode */
+static struct ipxsin **Ipxsin = (struct ipxsin **)NULL;
+static char *Nlkpath = (char *)NULL; /* path to Netlink /proc information */
+/* Netlink socket info, hashed by
+ * inode */
+static struct nlksin **Nlksin = (struct nlksin **)NULL;
+/* packet info, hashed by inode */
+static struct packin **Packin = (struct packin **)NULL;
+static char *Packpath = (char *)NULL; /* path to packet /proc information */
+static char *Rawpath = (char *)NULL;  /* path to raw socket /proc
+                                       * information */
+/* raw socket info, hashed by inode */
+static struct rawsin **Rawsin = (struct rawsin **)NULL;
+static char *SCTPPath[] = {
+    /* paths to /proc/net STCP info */
+    (char *)NULL, /* 0 = /proc/net/sctp/assocs */
+    (char *)NULL  /* 1 = /proc/net/sctp/eps */
+};
+#define NSCTPPATHS sizeof(SCTPPath) / sizeof(char *)
+static char *SCTPSfx[] = {
+    /* /proc/net suffixes */
+    "sctp/assocs", /* 0 = /proc/net/sctp/assocs */
+    "sctp/eps"     /* 1 = /proc/net/sctp/eps */
+};
+/* SCTP info, hashed by inode */
+static struct sctpsin **SCTPsin = (struct sctpsin **)NULL;
+/* path to /proc/net socket status */
+static char *SockStatPath = (char *)NULL;
+static char *TCPpath = (char *)NULL; /* path to TCP /proc information */
+/* IPv4 TCP & UDP info, hashed by
+ * inode */
+static struct tcp_udp **TcpUdp = (struct tcp_udp **)NULL;
+static int TcpUdp_bucks = 0; /* dynamically sized hash bucket
+                              * count for TCP and UDP -- will
+                              * be a power of two */
+#if defined(HASEPTOPTS)
+/* IPv4 TCP & UDP info for socket used
+   for IPC, hashed by (addr, port paris
+   and protocol */
+static struct tcp_udp **TcpUdpIPC = (struct tcp_udp **)NULL;
+#endif /* defined(HASEPTOPTS) */
+
+#if defined(HASIPv6)
+static char *Raw6path = (char *)NULL; /* path to raw IPv6 /proc information */
+/* IPv6 raw socket info, hashed by
+ * inode */
+static struct rawsin **Rawsin6 = (struct rawsin **)NULL;
+/* path to /proc/net IPv6 socket
+ * status */
+static char *SockStatPath6 = (char *)NULL;
+static char *TCP6path = (char *)NULL; /* path to IPv6 TCP /proc information */
+/* IPv6 TCP & UDP info, hashed by
+ * inode */
+static struct tcp_udp6 **TcpUdp6 = (struct tcp_udp6 **)NULL;
+static int TcpUdp6_bucks = 0;         /* dynamically sized hash bucket
+                                       * count for IPv6 TCP and UDP -- will
+                                       * be a power of two */
+static char *UDP6path = (char *)NULL; /* path to IPv6 UDP /proc information */
+/* path to IPv6 UDPLITE /proc
+ * information */
+static char *UDPLITE6path = (char *)NULL;
+#    if defined(HASEPTOPTS)
+/* IPv4 TCP & UDP info for socket used
+   for IPC, hashed by (addr, port paris
+   and protocol */
+static struct tcp_udp6 **TcpUdp6IPC = (struct tcp_udp6 **)NULL;
+#    endif /* defined(HASEPTOPTS) */
+#endif     /* defined(HASIPv6) */
+
+static char *UDPpath = (char *)NULL; /* path to UDP /proc information */
+/* path to UDPLITE /proc information */
+static char *UDPLITEpath = (char *)NULL;
+static char *UNIXpath = (char *)NULL; /* path to UNIX /proc information */
+/* UNIX socket info, hashed by inode */
+static uxsin_t **Uxsin = (uxsin_t **)NULL;
+
+/*
+ * Local function prototypes
+ */
+
+static struct ax25sin *check_ax25(struct lsof_context *ctx, INODETYPE i);
+
+#if defined(HASEPTOPTS) && defined(HASUXSOCKEPT)
+static void enter_uxsinfo(struct lsof_context *ctx, uxsin_t *up);
+static void fill_uxicino(struct lsof_context *ctx, INODETYPE si, INODETYPE sc);
+static void fill_uxpino(struct lsof_context *ctx, INODETYPE si, INODETYPE pi);
+static int get_diagmsg(int sockfd);
+static void get_uxpeeri(struct lsof_context *ctx);
+static void parse_diag(struct lsof_context *ctx, struct unix_diag_msg *dm,
+                       int len);
+static void prt_uxs(struct lsof_context *ctx, uxsin_t *p, int mk);
+#endif /* defined(HASEPTOPTS) && defined(HASUXSOCKEPT) */
+
+#if defined(HASEPTOPTS)
+static void enter_netsinfo(struct lsof_context *ctx, struct tcp_udp *tp);
+static void get_netpeeri(struct lsof_context *ctx);
+#endif /* defined(HASEPTOPTS) */
+
+#if defined(HASIPv6)
+#    if defined(HASEPTOPTS)
+static void enter_nets6info(struct lsof_context *ctx, struct tcp_udp6 *tp);
+static void get_net6peeri(struct lsof_context *ctx);
+#    endif /* defined(HASEPTOPTS) */
+#endif     /* defined(HASIPv6) */
+
+static struct icmpin *check_icmp(struct lsof_context *ctx, INODETYPE i);
+static struct ipxsin *check_ipx(struct lsof_context *ctx, INODETYPE i);
+static struct nlksin *check_netlink(struct lsof_context *ctx, INODETYPE i);
+static struct packin *check_pack(struct lsof_context *ctx, INODETYPE i);
+static struct rawsin *check_raw(struct lsof_context *ctx, INODETYPE i);
+static struct sctpsin *check_sctp(struct lsof_context *ctx, INODETYPE i);
+static struct tcp_udp *check_tcpudp(struct lsof_context *ctx, INODETYPE i,
+                                    char **p);
+static uxsin_t *check_unix(struct lsof_context *ctx, INODETYPE i);
+static void get_ax25(struct lsof_context *ctx, char *p);
+static void get_icmp(struct lsof_context *ctx, char *p);
+static void get_ipx(struct lsof_context *ctx, char *p);
+static void get_netlink(struct lsof_context *ctx, char *p);
+static void get_pack(struct lsof_context *ctx, char *p);
+static void get_raw(struct lsof_context *ctx, char *p);
+static void get_sctp(struct lsof_context *ctx);
+static char *get_sctpaddrs(char **fp, int i, int nf, int *x);
+static void get_tcpudp(struct lsof_context *ctx, char *p, int pr, int clr);
+static void get_unix(struct lsof_context *ctx, char *p);
+static int isainb(char *a, char *b);
+static void print_ax25info(struct lsof_context *ctx, struct ax25sin *ap);
+static void print_ipxinfo(struct lsof_context *ctx, struct ipxsin *ip);
+static char *socket_type_to_str(uint32_t ty, int *rf);
+static char *netlink_proto_to_str(unsigned int pr);
+#if defined(HASSOSTATE)
+static char *socket_state_to_str(struct lsof_context *ctx, unsigned int ss);
+#endif /* defined(HASSOSTATE) */
+static char *ethernet_proto_to_str(unsigned int pr);
+
+#if defined(HASIPv6)
+static struct rawsin *check_raw6(struct lsof_context *ctx, INODETYPE i);
+static struct tcp_udp6 *check_tcpudp6(struct lsof_context *ctx, INODETYPE i,
+                                      char **p);
+static void get_raw6(struct lsof_context *ctx, char *p);
+static void get_tcpudp6(struct lsof_context *ctx, char *p, int pr, int clr);
+static int hex_ipv6_to_in6(char *as, struct in6_addr *ad);
+#endif /* defined(HASIPv6) */
+
+/*
+ * build_IPstates() -- build the TCP and UDP state tables
+ */
+void build_IPstates(struct lsof_context *ctx) {
+    if (!TcpSt) {
+        (void)enter_IPstate(ctx, "TCP", "ESTABLISHED", TCP_ESTABLISHED);
+        (void)enter_IPstate(ctx, "TCP", "SYN_SENT", TCP_SYN_SENT);
+        (void)enter_IPstate(ctx, "TCP", "SYN_RECV", TCP_SYN_RECV);
+        (void)enter_IPstate(ctx, "TCP", "FIN_WAIT1", TCP_FIN_WAIT1);
+        (void)enter_IPstate(ctx, "TCP", "FIN_WAIT2", TCP_FIN_WAIT2);
+        (void)enter_IPstate(ctx, "TCP", "TIME_WAIT", TCP_TIME_WAIT);
+        (void)enter_IPstate(ctx, "TCP", "CLOSE", TCP_CLOSE);
+        (void)enter_IPstate(ctx, "TCP", "CLOSE_WAIT", TCP_CLOSE_WAIT);
+        (void)enter_IPstate(ctx, "TCP", "LAST_ACK", TCP_LAST_ACK);
+        (void)enter_IPstate(ctx, "TCP", "LISTEN", TCP_LISTEN);
+        (void)enter_IPstate(ctx, "TCP", "CLOSING", TCP_CLOSING);
+        (void)enter_IPstate(ctx, "TCP", "CLOSED", 0);
+        (void)enter_IPstate(ctx, "TCP", (char *)NULL, 0);
+    }
+}
+
+/*
+ * check_ax25() - check for AX25 socket file
+ */
+static struct ax25sin *check_ax25(struct lsof_context *ctx,
+                                  INODETYPE i) /* socket file's inode number */
+{
+    return HASH_FIND_ELEMENT(AX25sin, INOHASH, struct ax25sin, inode, i);
+}
+
+/*
+ * check_icmp() - check for ICMP socket
+ */
+static struct icmpin *check_icmp(struct lsof_context *ctx,
+                                 INODETYPE i) /* socket file's inode number */
+{
+    return HASH_FIND_ELEMENT(Icmpin, INOHASH, struct icmpin, inode, i);
+}
+
+/*
+ * check_ipx() - check for IPX socket file
+ */
+static struct ipxsin *check_ipx(struct lsof_context *ctx,
+                                INODETYPE i) /* socket file's inode number */
+{
+    return HASH_FIND_ELEMENT(Ipxsin, INOHASH, struct ipxsin, inode, i);
+}
+
+/*
+ * check_netlink() - check for Netlink socket file
+ */
+static struct nlksin *
+check_netlink(struct lsof_context *ctx,
+              INODETYPE i) /* socket file's inode number */
+{
+    return HASH_FIND_ELEMENT(Nlksin, INOHASH, struct nlksin, inode, i);
+}
+
+/*
+ * check_pack() - check for packet file
+ */
+static struct packin *check_pack(struct lsof_context *ctx,
+                                 INODETYPE i) /* packet file's inode number */
+{
+    return HASH_FIND_ELEMENT(Packin, INOHASH, struct packin, inode, i);
+}
+
+/*
+ * check_raw() - check for raw socket file
+ */
+
+static struct rawsin *check_raw(struct lsof_context *ctx,
+                                INODETYPE i) /* socket file's inode number */
+{
+    return HASH_FIND_ELEMENT(Rawsin, INOHASH, struct rawsin, inode, i);
+}
+
+/*
+ * check_sctp() - check for SCTP socket file
+ */
+static struct sctpsin *check_sctp(struct lsof_context *ctx,
+                                  INODETYPE i) /* socket file's inode number */
+{
+    return HASH_FIND_ELEMENT(SCTPsin, INOHASH, struct sctpsin, inode, i);
+}
+
+/*
+ * check_tcpudp() - check for IPv4 TCP or UDP socket file
+ */
+static struct tcp_udp *
+check_tcpudp(struct lsof_context *ctx,
+             INODETYPE i, /* socket file's inode number */
+             char **p)    /* protocol return */
+{
+    struct tcp_udp *tp;
+    tp = HASH_FIND_ELEMENT(TcpUdp, TCPUDPHASH, struct tcp_udp, inode, i);
+
+    if (tp) {
+        switch (tp->proto) {
+        case 0:
+            *p = "TCP";
+            break;
+        case 1:
+            *p = "UDP";
+            break;
+        case 2:
+            *p = "UDPLITE";
+            break;
+        default:
+            *p = "unknown";
+        }
+    }
+    return tp;
+}
+
+/*
+ * check_inet() - check for locally used INET domain socket
+ */
+static struct tcp_udp *check_inet(struct lsof_context *ctx,
+                                  INODETYPE i) /* socket file's inode number */
+{
+    return HASH_FIND_ELEMENT(TcpUdp, TCPUDPHASH, struct tcp_udp, inode, i);
+}
+
+/*
+ * clear_netsinfo -- clear allocated INET socket info
+ */
+void clear_netsinfo(struct lsof_context *ctx) {
+    int h;                   /* hash index */
+    struct tcp_udp *ti, *tp; /* temporary pointers */
+
+#if defined(HASEPTOPTS)
+    pxinfo_t *pp, *pnp;
+#endif /* defined(HASEPTOPTS) */
+
+    if (TcpUdp) {
+        for (h = 0; h < TcpUdp_bucks; h++) {
+            if ((ti = TcpUdp[h])) {
+                do {
+                    tp = ti->next;
+
+#if defined(HASEPTOPTS)
+                    for (pp = ti->pxinfo; pp; pp = pnp) {
+                        pnp = pp->next;
+                        (void)free((FREE_P *)pp);
+                    }
+#endif /* defined(HASEPTOPTS) */
+
+                    (void)free((FREE_P *)ti);
+                    ti = tp;
+                } while (ti);
+                TcpUdp[h] = (struct tcp_udp *)NULL;
+            }
+        }
+    }
+    if (TcpUdpIPC) {
+        for (h = 0; h < IPCBUCKS; h++)
+            TcpUdpIPC[h] = (struct tcp_udp *)NULL;
+    }
+}
+
+#if defined(HASIPv6)
+/*
+ * check_raw6() - check for raw IPv6 socket file
+ */
+static struct rawsin *check_raw6(struct lsof_context *ctx,
+                                 INODETYPE i) /* socket file's inode number */
+{
+    return HASH_FIND_ELEMENT(Rawsin6, INOHASH, struct rawsin, inode, i);
+}
+
+/*
+ * check_tcpudp6() - check for IPv6 TCP or UDP socket file
+ */
+static struct tcp_udp6 *
+check_tcpudp6(struct lsof_context *ctx,
+              INODETYPE i, /* socket file's inode number */
+              char **p)    /* protocol return */
+{
+    struct tcp_udp6 *tp6;
+    tp6 = HASH_FIND_ELEMENT(TcpUdp6, TCPUDP6HASH, struct tcp_udp6, inode, i);
+
+    if (tp6) {
+        switch (tp6->proto) {
+        case 0:
+            *p = "TCP";
+            break;
+        case 1:
+            *p = "UDP";
+            break;
+        case 2:
+            *p = "UDPLITE";
+            break;
+        default:
+            *p = "unknown";
+        }
+    }
+    return tp6;
+}
+
+/*
+ * check_inet6() - check for locally used INET6 domain socket
+ */
+static struct tcp_udp6 *
+check_inet6(struct lsof_context *ctx,
+            INODETYPE i) /* socket file's inode number */
+{
+    return HASH_FIND_ELEMENT(TcpUdp6, TCPUDP6HASH, struct tcp_udp6, inode, i);
+}
+
+/*
+ * clear_nets6info -- clear allocated INET6 socket info
+ */
+void clear_nets6info(struct lsof_context *ctx) {
+    int h;                    /* hash index */
+    struct tcp_udp6 *ti, *tp; /* temporary pointers */
+
+#    if defined(HASEPTOPTS)
+    pxinfo_t *pp, *pnp;
+#    endif /* defined(HASEPTOPTS) */
+
+    if (TcpUdp6) {
+        for (h = 0; h < TcpUdp6_bucks; h++) {
+            if ((ti = TcpUdp6[h])) {
+                do {
+                    tp = ti->next;
+
+#    if defined(HASEPTOPTS)
+                    for (pp = ti->pxinfo; pp; pp = pnp) {
+                        pnp = pp->next;
+                        (void)free((FREE_P *)pp);
+                    }
+#    endif /* defined(HASEPTOPTS) */
+
+                    (void)free((FREE_P *)ti);
+                    ti = tp;
+                } while (ti);
+                TcpUdp6[h] = (struct tcp_udp6 *)NULL;
+            }
+        }
+    }
+    if (TcpUdp6IPC) {
+        for (h = 0; h < IPCBUCKS; h++)
+            TcpUdp6IPC[h] = (struct tcp_udp6 *)NULL;
+    }
+}
+
+#endif /* defined(HASIPv6) */
+
+/*
+ * check_unix() - check for UNIX domain socket
+ */
+static uxsin_t *check_unix(struct lsof_context *ctx,
+                           INODETYPE i) /* socket file's inode number */
+{
+    return HASH_FIND_ELEMENT(Uxsin, INOHASH, uxsin_t, inode, i);
+}
+
+/*
+ * clear_uxsinfo -- clear allocated UNIX socket info
+ */
+void clear_uxsinfo(struct lsof_context *ctx) {
+    int h;            /* hash index */
+    uxsin_t *ui, *up; /* remporary pointers */
+
+#if defined(HASEPTOPTS) && defined(HASUXSOCKEPT)
+    pxinfo_t *pp, *pnp;
+#endif /* defined(HASEPTOPTS) && defined(HASUXSOCKEPT) */
+
+    if (!Uxsin)
+        return;
+    for (h = 0; h < INOBUCKS; h++) {
+        if ((ui = Uxsin[h])) {
+            do {
+                up = ui->next;
+
+#if defined(HASEPTOPTS) && defined(HASUXSOCKEPT)
+                for (pp = ui->pxinfo; pp; pp = pnp) {
+                    pnp = pp->next;
+                    (void)free((FREE_P *)pp);
+                }
+#endif /* defined(HASEPTOPTS) && defined(HASUXSOCKEPT) */
+
+                if (ui->path)
+                    (void)free((FREE_P *)ui->path);
+                if (ui->pcb)
+                    (void)free((FREE_P *)ui->pcb);
+                (void)free((FREE_P *)ui);
+                ui = up;
+            } while (ui);
+            Uxsin[h] = (uxsin_t *)NULL;
+        }
+    }
+}
+
+/*
+ * get_ax25() - get /proc/net/ax25 info
+ */
+static void get_ax25(struct lsof_context *ctx,
+                     char *p) /* /proc/net/ax25 path */
+{
+    struct ax25sin *ap, *np;
+    FILE *as;
+    char buf[MAXPATHLEN], *da, *dev_ch, *ep, **fp, *sa;
+    int h;
+    INODETYPE inode;
+    unsigned long rq, sq, state;
+    MALLOC_S len;
+    unsigned char rqs, sqs;
+    static char *vbuf = (char *)NULL;
+    static size_t vsz = (size_t)0;
+    /*
+     * Do second time cleanup or first time setup.
+     */
+    if (AX25sin) {
+        for (h = 0; h < INOBUCKS; h++) {
+            for (ap = AX25sin[h]; ap; ap = np) {
+                np = ap->next;
+                if (ap->da)
+                    (void)free((FREE_P *)ap->da);
+                if (ap->dev_ch)
+                    (void)free((FREE_P *)ap->dev_ch);
+                if (ap->sa)
+                    (void)free((FREE_P *)ap->sa);
+                (void)free((FREE_P *)ap);
+            }
+            AX25sin[h] = (struct ax25sin *)NULL;
+        }
+    } else {
+        AX25sin = (struct ax25sin **)calloc(INOBUCKS, sizeof(struct ax25sin *));
+        if (!AX25sin) {
+            (void)fprintf(stderr,
+                          "%s: can't allocate %d AX25 hash pointer bytes\n", Pn,
+                          (int)(INOBUCKS * sizeof(struct ax25sin *)));
+            Error(ctx);
+        }
+    }
+    /*
+     * Open the /proc/net/ax25 file, assign a page size buffer to the stream,
+     * and read it.  Store AX25 socket info in the AX25sin[] hash buckets.
+     */
+    if (!(as = open_proc_stream(ctx, p, "r", &vbuf, &vsz, 0)))
+        return;
+    while (fgets(buf, sizeof(buf) - 1, as)) {
+        if (get_fields(ctx, buf, (char *)NULL, &fp, (int *)NULL, 0) < 24)
+            continue;
+        /*
+         * /proc/net/ax25 has no title line, a very poor deficiency in its
+         * implementation.
+         *
+         * The ax25_info_show() function in kern module .../net/ax25/af_ax25.c
+         * says the format of the lines in the file is:
+         *
+         *     magic dev src_addr dest_addr,digi1,digi2,.. st vs vr va t1 t1 \
+         *     t2 t2 t3 t3 idle idle n2 n2 rtt window paclen Snd-Q Rcv-Q \
+         *     inode
+         *
+         * The code in this function is forced to assume that format is in
+         * effect..
+         */
+
+        /*
+         * Assemble the inode number and see if it has already been recorded.
+         * If it has, skip this line.
+         */
+        ep = (char *)NULL;
+        if (!fp[23] || !*fp[23] ||
+            (inode = strtoull(fp[23], &ep, 0)) == ULONG_MAX || !ep || *ep)
+            continue;
+        /* Skip if already exists in hash table */
+        if (HASH_FIND_ELEMENT(AX25sin, INOHASH, struct ax25sin, inode, inode))
+            continue;
+        /*
+         * Assemble the send and receive queue values and the state.
+         */
+        ep = (char *)NULL;
+        if (!fp[21] || !*fp[21] ||
+            (sq = strtoul(fp[21], &ep, 0)) == ULONG_MAX || !ep || *ep)
+            continue;
+        sqs = (unsigned char)1;
+        ep = (char *)NULL;
+        if (!fp[22] || !*fp[22] ||
+            (rq = strtoul(fp[22], &ep, 0)) == ULONG_MAX || !ep || *ep)
+            continue;
+        rqs = (unsigned char)1;
+        ep = (char *)NULL;
+        if (!fp[4] || !*fp[4] ||
+            (state = strtoul(fp[4], &ep, 0)) == ULONG_MAX || !ep || *ep)
+            continue;
+        /*
+         * Allocate space for the destination address.
+         */
+        if (!fp[3] || !*fp[3])
+            da = (char *)NULL;
+        else if ((len = strlen(fp[3]))) {
+            if (!(da = (char *)malloc(len + 1))) {
+                (void)fprintf(
+                    stderr,
+                    "%s: can't allocate %d destination AX25 addr bytes: %s\n",
+                    Pn, (int)(len + 1), fp[3]);
+                Error(ctx);
+            }
+            (void)snpf(da, len + 1, "%s", fp[3]);
+        } else
+            da = (char *)NULL;
+        /*
+         * Allocate space for the source address.
+         */
+        if (!fp[2] || !*fp[2])
+            sa = (char *)NULL;
+        else if ((len = strlen(fp[2]))) {
+            if (!(sa = (char *)malloc(len + 1))) {
+                (void)fprintf(
+                    stderr,
+                    "%s: can't allocate %d source AX25 address bytes: %s\n", Pn,
+                    (int)(len + 1), fp[2]);
+                Error(ctx);
+            }
+            (void)snpf(sa, len + 1, "%s", fp[2]);
+        } else
+            sa = (char *)NULL;
+        /*
+         * Allocate space for the device characters.
+         */
+        if (!fp[1] || !*fp[1])
+            dev_ch = (char *)NULL;
+        else if ((len = strlen(fp[1]))) {
+            if (!(dev_ch = (char *)malloc(len + 1))) {
+                (void)fprintf(
+                    stderr,
+                    "%s: can't allocate %d destination AX25 dev bytes: %s\n",
+                    Pn, (int)(len + 1), fp[1]);
+                Error(ctx);
+            }
+            (void)snpf(dev_ch, len + 1, "%s", fp[1]);
+        } else
+            dev_ch = (char *)NULL;
+        /*
+         * Allocate space for an ax25sin entry, fill it, and link it to its
+         * hash bucket.
+         */
+        if (!(ap = (struct ax25sin *)malloc(sizeof(struct ax25sin)))) {
+            (void)fprintf(stderr,
+                          "%s: can't allocate %d byte ax25sin structure\n", Pn,
+                          (int)sizeof(struct ax25sin));
+            Error(ctx);
+        }
+        ap->da = da;
+        ap->dev_ch = dev_ch;
+        ap->inode = inode;
+        ap->rq = rq;
+        ap->rqs = rqs;
+        ap->sa = sa;
+        ap->sq = sq;
+        ap->sqs = sqs;
+        ap->state = (int)state;
+        HASH_INSERT_ELEMENT(AX25sin, INOHASH, ap, inode);
+    }
+    (void)fclose(as);
+}
+
+#if defined(HASEPTOPTS) && defined(HASUXSOCKEPT)
+/*
+ * enter_uxsinfo() -- enter unix socket info
+ * 	entry	Lf = local file structure pointer
+ * 		Lp = local process structure pointer
+ */
+static void enter_uxsinfo(struct lsof_context *ctx, uxsin_t *up) {
+    pxinfo_t *pi;     /* pxinfo_t structure pointer */
+    struct lfile *lf; /* local file structure pointer */
+    struct lproc *lp; /* local proc structure pointer */
+    pxinfo_t *np;     /* new pxinfo_t structure pointer */
+
+    for (pi = up->pxinfo; pi; pi = pi->next) {
+        lf = pi->lf;
+        lp = &Lproc[pi->lpx];
+        if (pi->ino == Lf->inode) {
+            if ((lp->pid == Lp->pid) && (lf->fd_type == Lf->fd_type) &&
+                (lf->fd_num == Lf->fd_num))
+                return;
+        }
+    }
+    if (!(np = (pxinfo_t *)malloc(sizeof(pxinfo_t)))) {
+        (void)fprintf(stderr, "%s: no space for pipeinfo in uxsinfo, PID %d\n",
+                      Pn, Lp->pid);
+        Error(ctx);
+    }
+    np->ino = Lf->inode;
+    np->lf = Lf;
+    np->lpx = Lp - Lproc;
+    np->next = up->pxinfo;
+    up->pxinfo = np;
+}
+
+/*
+ * fill_uxicino() -- fill incoming connection inode number
+ */
+static void fill_uxicino(struct lsof_context *ctx,
+                         INODETYPE si, /* UNIX socket inode number */
+                         INODETYPE ic) /* incoming UNIX socket connection
+                                        * inode number */
+{
+    uxsin_t *psi; /* pointer to socket's information */
+    uxsin_t *pic; /* pointer to incoming connection's
+                   * information */
+
+    if ((psi = check_unix(ctx, si))) {
+        if (psi->icstat || psi->icons)
+            return;
+        if ((pic = check_unix(ctx, ic))) {
+            psi->icstat = 1;
+            psi->icons = pic;
+        }
+    }
+}
+
+/*
+ * fill_uxpino() -- fill in UNIX socket's peer inode number
+ */
+static void fill_uxpino(struct lsof_context *ctx,
+                        INODETYPE si, /* UNIX socket inode number */
+                        INODETYPE pi) /* UNIX socket peer's inode number */
+{
+    uxsin_t *pp, *up;
+
+    if ((up = check_unix(ctx, si))) {
+        if (!up->peer) {
+            if ((pp = check_unix(ctx, pi)))
+                up->peer = pp;
+        }
+    }
+}
+
+/*
+ * find_uxepti(lf) -- find UNIX socket endpoint info
+ */
+uxsin_t *find_uxepti(struct lsof_context *ctx,
+                     struct lfile *lf) /* pipe's lfile */
+{
+    uxsin_t *up;
+
+    up = check_unix(ctx, lf->inode);
+    return (up ? up->peer : (uxsin_t *)NULL);
+}
+
+/*
+ * get_diagmsg() -- get UNIX socket's diag message
+ */
+
+static int get_diagmsg(int sockfd) /* socket's file descriptor */
+{
+    struct msghdr msg;         /* message header */
+    struct nlmsghdr nlh;       /* header length */
+    struct unix_diag_req creq; /* connection request */
+    struct sockaddr_nl sa;     /* netlink socket address */
+    struct iovec iov[2];       /* I/O vector */
+    /*
+     * Build and send message to socket's file descriptor, asking for its
+     * diagnostic message.
+     */
+    zeromem((char *)&msg, sizeof(msg));
+    zeromem((char *)&sa, sizeof(sa));
+    zeromem((char *)&nlh, sizeof(nlh));
+    zeromem((char *)&creq, sizeof(creq));
+    sa.nl_family = AF_NETLINK;
+    creq.sdiag_family = AF_UNIX;
+    creq.sdiag_protocol = 0;
+    memset((void *)&creq.udiag_states, -1, sizeof(creq.udiag_states));
+    creq.udiag_ino = (INODETYPE)0;
+    creq.udiag_show = UDIAG_SHOW_PEER | UDIAG_SHOW_ICONS;
+    nlh.nlmsg_len = NLMSG_LENGTH(sizeof(creq));
+    nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
+    nlh.nlmsg_type = SOCK_DIAG_BY_FAMILY;
+    iov[0].iov_base = (void *)&nlh;
+    iov[0].iov_len = sizeof(nlh);
+    iov[1].iov_base = (void *)&creq;
+    iov[1].iov_len = sizeof(creq);
+    msg.msg_name = (void *)&sa;
+    msg.msg_namelen = sizeof(sa);
+    msg.msg_iov = iov;
+    msg.msg_iovlen = 2;
+    return (sendmsg(sockfd, &msg, 0));
+}
+
+/*
+ * get_uxpeeri() - get UNIX socket peer inode information
+ */
+static void get_uxpeeri(struct lsof_context *ctx) {
+    struct unix_diag_msg *dm;       /* pointer to diag message */
+    struct nlmsghdr *hp;            /* netlink structure header pointer */
+    int nb = 0;                     /* number of bytes */
+    int ns = 0;                     /* netlink socket */
+    uint8_t rb[SOCKET_BUFFER_SIZE]; /* receive buffer */
+    int rl = 0;                     /* route info length */
+    /*
+     * Get a netlink socket.
+     */
+    if ((ns = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_SOCK_DIAG)) == -1) {
+        (void)fprintf(stderr, "%s: netlink socket error: %s\n", Pn,
+                      strerror(errno));
+        Error(ctx);
+    }
+    /*
+     * Request peer information.
+     */
+    if (get_diagmsg(ns) < 0) {
+        (void)fprintf(stderr, "%s: netlink peer request error: %s\n", Pn,
+                      strerror(errno));
+        goto get_uxpeeri_exit;
+    }
+    /*
+     * Receive peer information.
+     */
+    while (1) {
+        if ((nb = recv(ns, rb, sizeof(rb), 0)) <= 0)
+            goto get_uxpeeri_exit;
+        hp = (struct nlmsghdr *)rb;
+        while (NLMSG_OK(hp, nb)) {
+            if (hp->nlmsg_type == NLMSG_DONE)
+                goto get_uxpeeri_exit;
+            if (hp->nlmsg_type == NLMSG_ERROR) {
+                (void)fprintf(stderr,
+                              "%s: netlink UNIX socket msg peer info error\n",
+                              Pn);
+                goto get_uxpeeri_exit;
+            }
+            dm = (struct unix_diag_msg *)NLMSG_DATA(hp);
+            rl = hp->nlmsg_len - NLMSG_LENGTH(sizeof(*dm));
+            parse_diag(ctx, dm, rl);
+            hp = NLMSG_NEXT(hp, nb);
+        }
+    }
+
+get_uxpeeri_exit:
+
+    (void)close(ns);
+}
+
+/*
+ * parse_diag() -- parse UNIX diag message
+ */
+static void parse_diag(struct lsof_context *ctx,
+                       struct unix_diag_msg *dm, /* pointer to diag message */
+                       int len)                  /* message length */
+{
+    struct rtattr *rp;   /* route info pointer */
+    int i;               /* tmporary index */
+    int icct;            /* incoming connection count */
+    uint32_t *icp;       /* incoming connection pointer */
+    uint32_t inoc, inop; /* inode numbers */
+
+    if (!dm || (dm->udiag_family != AF_UNIX) || !(inop = dm->udiag_ino) ||
+        (len <= 0)) {
+        return;
+    }
+    rp = (struct rtattr *)(dm + 1);
+    /*
+     * Process route information.
+     */
+    while (RTA_OK(rp, len)) {
+        switch (rp->rta_type) {
+        case UNIX_DIAG_PEER:
+            if (len < 4) {
+                (void)fprintf(stderr, "%s: unix_diag: msg length (%d) < 4)\n",
+                              Pn, len);
+                return;
+            }
+            if ((inoc = *(uint32_t *)RTA_DATA(rp))) {
+                fill_uxpino(ctx, (INODETYPE)inop, (INODETYPE)inoc);
+                fill_uxpino(ctx, (INODETYPE)inoc, (INODETYPE)inop);
+            }
+            break;
+        case UNIX_DIAG_ICONS:
+            icct = RTA_PAYLOAD(rp), icp = (uint32_t *)RTA_DATA(rp);
+
+            for (i = 0; i < icct; i += sizeof(uint32_t), icp++) {
+                fill_uxicino(ctx, (INODETYPE)inop, (INODETYPE)*icp);
+            }
+        }
+        rp = RTA_NEXT(rp, len);
+    }
+}
+
+/*
+ * prt_uxs() -- print UNIX socket information
+ */
+static void prt_uxs(struct lsof_context *ctx, uxsin_t *p, /* peer info */
+                    int mk) /* 1 == mark for later processing */
+{
+    struct lproc *ep; /* socket endpoint process */
+    struct lfile *ef; /* socket endpoint file */
+    int i;            /* temporary index */
+    int len;          /* string length */
+    char nma[1024];   /* character buffer */
+    pxinfo_t *pp;     /* previous pipe info of socket */
+    char fd[FDLEN];
+
+    (void)strcpy(nma, "->INO=");
+    len = (int)strlen(nma);
+    (void)snpf(&nma[len], sizeof(nma) - len - 1, "%" INODEPSPEC "u", p->inode);
+    (void)add_nma(ctx, nma, strlen(nma));
+    for (pp = p->pxinfo; pp; pp = pp->next) {
+
+        /*
+         * Add a linked socket's PID, command name and FD to the name column
+         * addition.
+         */
+        ep = &Lproc[pp->lpx];
+        ef = pp->lf;
+        fd_to_string(ef->fd_type, ef->fd_num, fd);
+        (void)snpf(nma, sizeof(nma) - 1, "%d,%.*s,%s%c", ep->pid, CmdLim,
+                   ep->cmd, fd, access_to_char(ef->access));
+        (void)add_nma(ctx, nma, strlen(nma));
+        if (mk && FeptE == 2) {
+
+            /*
+             * Endpoint files have been selected, so mark this
+             * one for selection later.
+             */
+            ef->chend = CHEND_UXS;
+            ep->ept |= EPT_UXS_END;
+        }
+    }
+}
+
+/*
+ * process_uxsinfo() -- process UNIX socket information, adding it to selected
+ *			UNIX socket files and selecting UNIX socket end point
+ *			files (if requested)
+ */
+void process_uxsinfo(struct lsof_context *ctx,
+                     int f) /* function:
+                             *     0 == process selected socket
+                             *     1 == process socket end point
+                             */
+{
+    uxsin_t *p;  /* peer UNIX socket info pointer */
+    uxsin_t *tp; /* temporary UNIX socket info pointer */
+
+    if (!FeptE)
+        return;
+    for (Lf = Lp->file; Lf; Lf = Lf->next) {
+        if (Lf->type != LSOF_FILE_UNIX)
+            continue;
+        switch (f) {
+        case 0:
+
+            /*
+             * Process already selected socket.
+             */
+            if (is_file_sel(ctx, Lp, Lf)) {
+
+                /*
+                 * This file has been selected by some criterion other than its
+                 * being a socket.  Look up the socket's endpoints.
+                 */
+                p = find_uxepti(ctx, Lf);
+                if (p && p->inode)
+                    prt_uxs(ctx, p, 1);
+                if ((tp = check_unix(ctx, Lf->inode))) {
+                    if (tp->icons) {
+                        if (tp->icstat) {
+                            p = tp->icons;
+                            while (p && p != tp) {
+                                if (p->inode)
+                                    prt_uxs(ctx, p, 1);
+                                p = p->icons;
+                            }
+                        } else {
+                            for (p = tp->icons; p && !p->icstat; p = p->icons)
+                                ; /* DO NOTHING */
+                            if (p && p->inode)
+                                prt_uxs(ctx, p, 1);
+                        }
+                    }
+                }
+            }
+            break;
+        case 1:
+            if (!is_file_sel(ctx, Lp, Lf) && (Lf->chend & CHEND_UXS)) {
+
+                /*
+                 * This is an unselected end point UNIX socket file.  Select it
+                 * and add its end point information to peer's name column
+                 * addition.
+                 */
+                Lf->sf = Selflags;
+                Lp->pss |= PS_SEC;
+                p = find_uxepti(ctx, Lf);
+                if (p && p->inode)
+                    prt_uxs(ctx, p, 0);
+                else if ((tp = check_unix(ctx, Lf->inode))) {
+                    if (tp->icons) {
+                        if (tp->icstat) {
+                            p = tp->icons;
+                            while (p && p != tp) {
+                                if (p->inode)
+                                    prt_uxs(ctx, p, 0);
+                                p = p->icons;
+                            }
+                        } else {
+                            for (p = tp->icons; p && !p->icstat; p = p->icons)
+                                ; /* DO NOTHING */
+                            if (p && p->inode)
+                                prt_uxs(ctx, p, 0);
+                        }
+                    }
+                }
+            }
+            break;
+        }
+    }
+}
+#endif /* defined(HASEPTOPTS) && defined(HASUXSOCKEPT) */
+
+#if defined(HASEPTOPTS)
+/*
+ * enter_netsinfo_common() -- enter inet or inet6 socket info
+ * 	tp = tcp/udp on ipv4 or ipv4 socket pointer
+ */
+static void enter_netsinfo_common(struct lsof_context *ctx, void *tp,
+                                  pxinfo_t *(*get_pxinfo)(void *),
+                                  void (*set_pxinfo)(void *, pxinfo_t *)) {
+    pxinfo_t *pi;     /* pxinfo_t structure pointer */
+    struct lfile *lf; /* local file structure pointer */
+    struct lproc *lp; /* local proc structure pointer */
+    pxinfo_t *np;     /* new pxinfo_t structure pointer */
+
+    for (pi = (*get_pxinfo)(tp); pi; pi = pi->next) {
+        lf = pi->lf;
+        lp = &Lproc[pi->lpx];
+        if (pi->ino == Lf->inode) {
+            if ((lp->pid == Lp->pid) && (lf->fd_type == Lf->fd_type) &&
+                (lf->fd_num == Lf->fd_num))
+                return;
+        }
+    }
+    if (!(np = (pxinfo_t *)malloc(sizeof(pxinfo_t)))) {
+        (void)fprintf(stderr, "%s: no space for pipeinfo in netsinfo, PID %d\n",
+                      Pn, Lp->pid);
+        Error(ctx);
+    }
+    np->ino = Lf->inode;
+    np->lf = Lf;
+    np->lpx = Lp - Lproc;
+    np->next = (*get_pxinfo)(tp);
+    (*set_pxinfo)(tp, np);
+}
+
+/*
+ * prt_nets_common() -- print locally used INET or INET6 socket information
+ */
+static void prt_nets_common(struct lsof_context *ctx, void *p, /* peer info */
+                            int mk, /* 1 == mark for later
+                                     * processing */
+                            pxinfo_t *(*get_pxinfo)(void *),
+                            unsigned char chend, short ept_flag) {
+    struct lproc *ep; /* socket endpoint process */
+    struct lfile *ef; /* socket endpoint file */
+    int i;            /* temporary index */
+    char nma[1024];   /* character buffer */
+    pxinfo_t *pp;     /* previous pipe info of socket */
+    char fd[FDLEN];
+
+    for (pp = (*get_pxinfo)(p); pp; pp = pp->next) {
+
+        /*
+         * Add a linked socket's PID, command name and FD to the name column
+         * addition.
+         */
+        ep = &Lproc[pp->lpx];
+        ef = pp->lf;
+        fd_to_string(ef->fd_type, ef->fd_num, fd);
+        (void)snpf(nma, sizeof(nma) - 1, "%d,%.*s,%s%c", ep->pid, CmdLim,
+                   ep->cmd, fd, access_to_char(ef->access));
+        (void)add_nma(ctx, nma, strlen(nma));
+        if (mk && FeptE == 2) {
+
+            /*
+             * Endpoint files have been selected, so mark this
+             * one for selection later.
+             */
+            ef->chend = chend;
+            ep->ept |= ept_flag;
+        }
+    }
+}
+
+/*
+ * enter_netsinfo() -- enter inet socket info
+ * 	tp = tcp/udp on ipv4 socket pointer
+ */
+static pxinfo_t *tcp_udp_get_pxinfo(void *vp) {
+    struct tcp_udp *tp = vp;
+    return tp->pxinfo;
+}
+
+static void tcp_udp_set_pxinfo(void *vp, pxinfo_t *np) {
+    struct tcp_udp *tp = vp;
+    tp->pxinfo = np;
+}
+
+static void enter_netsinfo(struct lsof_context *ctx, struct tcp_udp *tp) {
+    enter_netsinfo_common(ctx, tp, tcp_udp_get_pxinfo, tcp_udp_set_pxinfo);
+}
+
+/*
+ * find_netsepti(lf) -- find locally used INET socket endpoint info
+ */
+static struct tcp_udp *find_netsepti(struct lsof_context *ctx, /* context */
+                                     struct lfile *lf) /* socket's lfile */
+{
+    struct tcp_udp *tp;
+
+    tp = check_inet(ctx, lf->inode);
+    return (tp ? tp->ipc_peer : (struct tcp_udp *)NULL);
+}
+
+/*
+ * get_netpeeri() - get INET socket peer inode information
+ */
+static void get_netpeeri(struct lsof_context *ctx) {
+    int h;
+    struct tcp_udp *np, *tp;
+
+    for (h = 0; h < IPCBUCKS; h++) {
+        for (tp = TcpUdpIPC[h]; tp; tp = tp->ipc_next) {
+            if (tp->ipc_peer)
+                continue;
+            for (np = TcpUdpIPC[h]; np; np = np->ipc_next) {
+                if (np->ipc_peer)
+                    continue;
+                if (tp->faddr == np->laddr && tp->laddr == np->faddr &&
+                    tp->fport == np->lport && tp->lport == np->fport &&
+                    tp->proto == np->proto) {
+                    tp->ipc_peer = np;
+                    np->ipc_peer = tp;
+                    break;
+                }
+            }
+        }
+    }
+}
+
+/*
+ * prt_nets() -- print locally used INET socket information
+ */
+static void prt_nets(struct lsof_context *ctx, /* context */
+                     struct tcp_udp *p,        /* peer info */
+                     int mk) /* 1 == mark for later processing */
+{
+    prt_nets_common(ctx, p, mk, tcp_udp_get_pxinfo, CHEND_NETS, EPT_NETS_END);
+}
+
+/*
+ * process_netsinfo() -- process locally used INET socket information, adding
+ *			it to selected INET socket files and selecting INET
+ *			socket end point files (if requested)
+ */
+void process_netsinfo(struct lsof_context *ctx, /* context */
+                      int f)                    /* function:
+                                                 *     0 == process selected socket
+                                                 *     1 == process socket end point
+                                                 */
+{
+    struct tcp_udp *p; /* peer INET socket info pointer */
+
+    if (!FeptE)
+        return;
+    for (Lf = Lp->file; Lf; Lf = Lf->next) {
+#    if defined(HASIPv6)
+        enum lsof_file_type type = LSOF_FILE_IPV4;
+#    else  /* !defined(HASIPv6) */
+        enum lsof_file_type type = LSOF_FILE_INET;
+#    endif /* defined(HASIPv6) */
+        if (Lf->type != type)
+            continue;
+        switch (f) {
+        case 0:
+
+            /*
+             * Process already selected socket.
+             */
+            if (is_file_sel(ctx, Lp, Lf)) {
+
+                /*
+                 * This file has been selected by some criterion other than its
+                 * being a socket.  Look up the socket's endpoints.
+                 */
+                p = find_netsepti(ctx, Lf);
+                if (p && p->inode)
+                    prt_nets(ctx, p, 1);
+            }
+            break;
+        case 1:
+            if (!is_file_sel(ctx, Lp, Lf) && (Lf->chend & CHEND_NETS)) {
+
+                /*
+                 * This is an unselected end point INET socket file.  Select it
+                 * and add its end point information to peer's name column
+                 * addition.
+                 */
+                Lf->sf = Selflags;
+                Lp->pss |= PS_SEC;
+                p = find_netsepti(ctx, Lf);
+                if (p && p->inode)
+                    prt_nets(ctx, p, 0);
+            }
+            break;
+        }
+    }
+}
+#endif /* defined(HASEPTOPTS) */
+
+#if defined(HASIPv6)
+#    if defined(HASEPTOPTS)
+/*
+ * enter_nets6info() -- enter inet socket info
+ * 	tp = tcp/udp on ipv6 socket pointer
+ */
+static pxinfo_t *tcp_udp6_get_pxinfo(void *vp) {
+    struct tcp_udp6 *tp = vp;
+    return tp->pxinfo;
+}
+
+static void tcp_udp6_set_pxinfo(void *vp, pxinfo_t *np) {
+    struct tcp_udp6 *tp = vp;
+    tp->pxinfo = np;
+}
+
+static void enter_nets6info(struct lsof_context *ctx, struct tcp_udp6 *tp) {
+    enter_netsinfo_common(ctx, tp, tcp_udp6_get_pxinfo, tcp_udp6_set_pxinfo);
+}
+
+/*
+ * find_nets6epti(lf) -- find locally used INET6 socket endpoint info
+ */
+static struct tcp_udp6 *find_nets6epti(struct lsof_context *ctx, /* context */
+                                       struct lfile *lf) /* socket's lfile */
+{
+    struct tcp_udp6 *tp;
+
+    tp = check_inet6(ctx, lf->inode);
+    return (tp ? tp->ipc_peer : (struct tcp_udp6 *)NULL);
+}
+
+/*
+ * get_net6peeri() - get INET6 socket peer inode information
+ */
+static void get_net6peeri(struct lsof_context *ctx) {
+    int h;
+    struct tcp_udp6 *np, *tp;
+
+    for (h = 0; h < IPCBUCKS; h++) {
+        for (tp = TcpUdp6IPC[h]; tp; tp = tp->ipc_next) {
+            if (tp->ipc_peer)
+                continue;
+            for (np = TcpUdp6IPC[h]; np; np = np->ipc_next) {
+                if (np->ipc_peer)
+                    continue;
+                if (IN6_ARE_ADDR_EQUAL(&tp->faddr, &np->laddr) &&
+                    IN6_ARE_ADDR_EQUAL(&tp->laddr, &np->faddr) &&
+                    tp->fport == np->lport && tp->lport == np->fport &&
+                    tp->proto == np->proto) {
+                    tp->ipc_peer = np;
+                    np->ipc_peer = tp;
+                    break;
+                }
+            }
+        }
+    }
+}
+
+/*
+ * prt_nets6() -- print locally used INET6 socket information
+ */
+static void prt_nets6(struct lsof_context *ctx, /* context */
+                      struct tcp_udp6 *p,       /* peer info */
+                      int mk) /* 1 == mark for later processing */
+{
+    prt_nets_common(ctx, p, mk, tcp_udp6_get_pxinfo, CHEND_NETS6,
+                    EPT_NETS6_END);
+}
+
+/*
+ * process_nets6info() -- process locally used INET6 socket information, adding
+ *			it to selected INET6 socket files and selecting INET6
+ *			socket end point files (if requested)
+ */
+void process_nets6info(struct lsof_context *ctx, /* context */
+                       int f)                    /* function:
+                                                  *     0 == process selected socket
+                                                  *     1 == process socket end point
+                                                  */
+{
+    struct tcp_udp6 *p; /* peer INET6 socket info pointer */
+
+    if (!FeptE)
+        return;
+    for (Lf = Lp->file; Lf; Lf = Lf->next) {
+        if (Lf->type != LSOF_FILE_IPV6)
+            continue;
+        switch (f) {
+        case 0:
+
+            /*
+             * Process already selected socket.
+             */
+            if (is_file_sel(ctx, Lp, Lf)) {
+                /*
+                 * This file has been selected by some criterion other than its
+                 * being a socket.  Look up the socket's endpoints.
+                 */
+                p = find_nets6epti(ctx, Lf);
+                if (p && p->inode)
+                    prt_nets6(ctx, p, 1);
+            }
+            break;
+        case 1:
+            if (!is_file_sel(ctx, Lp, Lf) && (Lf->chend & CHEND_NETS6)) {
+
+                /*
+                 * This is an unselected end point INET6 socket file.  Select it
+                 * and add its end point information to peer's name column
+                 * addition.
+                 */
+                Lf->sf = Selflags;
+                Lp->pss |= PS_SEC;
+                p = find_nets6epti(ctx, Lf);
+                if (p && p->inode)
+                    prt_nets6(ctx, p, 0);
+            }
+            break;
+        }
+    }
+}
+#    endif /* defined(HASEPTOPTS) */
+#endif     /* defined(HASIPv6) */
+
+/*
+ * get_icmp() - get ICMP net info
+ */
+static void get_icmp(struct lsof_context *ctx, /* context */
+                     char *p)                  /* /proc/net/icmp path */
+{
+    char buf[MAXPATHLEN], *ep, **fp, *la, *ra;
+    int fl = 1;
+    int h;
+    INODETYPE inode;
+    struct icmpin *np, *icmpp;
+    MALLOC_S lal, ral;
+    static char *vbuf = (char *)NULL;
+    static size_t vsz = (size_t)0;
+    FILE *xs;
+    /*
+     * Do second time cleanup or first time setup.
+     */
+    if (Icmpin) {
+        for (h = 0; h < INOBUCKS; h++) {
+            for (icmpp = Icmpin[h]; icmpp; icmpp = np) {
+                np = icmpp->next;
+                (void)free((FREE_P *)icmpp);
+            }
+            Icmpin[h] = (struct icmpin *)NULL;
+        }
+    } else {
+        Icmpin = (struct icmpin **)calloc(INOBUCKS, sizeof(struct icmpin *));
+        if (!Icmpin) {
+            (void)fprintf(stderr,
+                          "%s: can't allocate %d icmp hash pointer bytes\n", Pn,
+                          (int)(INOBUCKS * sizeof(struct icmpin *)));
+            Error(ctx);
+        }
+    }
+    /*
+     * Open the /proc/net/icmp file, assign a page size buffer to its stream,
+     * and read the file.  Store icmp info in the Icmpin[] hash buckets.
+     */
+    if (!(xs = open_proc_stream(ctx, p, "r", &vbuf, &vsz, 0)))
+        return;
+    while (fgets(buf, sizeof(buf) - 1, xs)) {
+        if (get_fields(ctx, buf, (char *)NULL, &fp, (int *)NULL, 0) < 11)
+            continue;
+        if (fl) {
+
+            /*
+             * Check the column labels in the first line.
+             *
+             * NOTE:
+             *       In column header, "inode" is at the 11th column.
+             *       However, in data rows, inode appears at the 9th column.
+             *
+             *       In column header, "tx_queue" and "rx_queue" are separated
+             *       by a space.  It is the same for "tr" and "tm->when"; in
+             *       data rows they are connected with ":".
+             */
+            if (!fp[1] || strcmp(fp[1], "local_address") || !fp[2] ||
+                strcmp(fp[2], "rem_address") || !fp[11] ||
+                strcmp(fp[11], "inode")) {
+                if (!Fwarn) {
+                    (void)fprintf(
+                        stderr, "%s: WARNING: unsupported format: %s\n", Pn, p);
+                }
+                break;
+            }
+            fl = 0;
+            continue;
+        }
+        /*
+         * Assemble the inode number and see if the inode is already
+         * recorded.
+         */
+        ep = (char *)NULL;
+        if (!fp[9] || !*fp[9] ||
+            (inode = strtoull(fp[9], &ep, 0)) == ULONG_MAX || !ep || *ep)
+            continue;
+        /* Skip if already exists in hash table */
+        if (HASH_FIND_ELEMENT(Icmpin, INOHASH, struct icmpin, inode, inode))
+            continue;
+        /*
+         * Save the local address, and remote address.
+         */
+        if (!fp[1] || !*fp[1] || (lal = strlen(fp[1])) < 1) {
+            la = (char *)NULL;
+            lal = (MALLOC_S)0;
+        } else {
+            if (!(la = (char *)malloc(lal + 1))) {
+                (void)fprintf(
+                    stderr,
+                    "%s: can't allocate %d local icmp address bytes: %s\n", Pn,
+                    (int)(lal + 1), fp[1]);
+                Error(ctx);
+            }
+            (void)snpf(la, lal + 1, "%s", fp[1]);
+        }
+        if (!fp[2] || !*fp[2] || (ral = strlen(fp[2])) < 1) {
+            ra = (char *)NULL;
+            ral = (MALLOC_S)0;
+        } else {
+            if (!(ra = (char *)malloc(ral + 1))) {
+                (void)fprintf(
+                    stderr,
+                    "%s: can't allocate %d remote icmp address bytes: %s\n", Pn,
+                    (int)(ral + 1), fp[2]);
+                Error(ctx);
+            }
+            (void)snpf(ra, ral + 1, "%s", fp[2]);
+        }
+        /*
+         * Allocate space for a icmpin entry, fill it, and link it to its
+         * hash bucket.
+         */
+        if (!(icmpp = (struct icmpin *)malloc(sizeof(struct icmpin)))) {
+            (void)fprintf(stderr, "%s: can't allocate %d byte icmp structure\n",
+                          Pn, (int)sizeof(struct icmpin));
+            Error(ctx);
+        }
+        icmpp->inode = inode;
+        icmpp->la = la;
+        icmpp->lal = lal;
+        icmpp->ra = ra;
+        icmpp->ral = ral;
+        HASH_INSERT_ELEMENT(Icmpin, INOHASH, icmpp, inode);
+    }
+    (void)fclose(xs);
+}
+
+/*
+ * get_ipx() - get /proc/net/ipx info
+ */
+static void get_ipx(struct lsof_context *ctx, /* context */
+                    char *p)                  /* /proc/net/ipx path */
+{
+    char buf[MAXPATHLEN], *ep, **fp, *la, *ra;
+    int fl = 1;
+    int h;
+    INODETYPE inode;
+    unsigned long rxq, state, txq;
+    struct ipxsin *ip, *np;
+    MALLOC_S len;
+    static char *vbuf = (char *)NULL;
+    static size_t vsz = (size_t)0;
+    FILE *xs;
+    /*
+     * Do second time cleanup or first time setup.
+     */
+    if (Ipxsin) {
+        for (h = 0; h < INOBUCKS; h++) {
+            for (ip = Ipxsin[h]; ip; ip = np) {
+                np = ip->next;
+                if (ip->la)
+                    (void)free((FREE_P *)ip->la);
+                if (ip->ra)
+                    (void)free((FREE_P *)ip->ra);
+                (void)free((FREE_P *)ip);
+            }
+            Ipxsin[h] = (struct ipxsin *)NULL;
+        }
+    } else {
+        Ipxsin = (struct ipxsin **)calloc(INOBUCKS, sizeof(struct ipxsin *));
+        if (!Ipxsin) {
+            (void)fprintf(stderr,
+                          "%s: can't allocate %d IPX hash pointer bytes\n", Pn,
+                          (int)(INOBUCKS * sizeof(struct ipxsin *)));
+            Error(ctx);
+        }
+    }
+    /*
+     * Open the /proc/net/ipx file, assign a page size buffer to the stream,
+     * and read it.  Store IPX socket info in the Ipxsin[] hash buckets.
+     */
+    if (!(xs = open_proc_stream(ctx, p, "r", &vbuf, &vsz, 0)))
+        return;
+    while (fgets(buf, sizeof(buf) - 1, xs)) {
+        if (get_fields(ctx, buf, (char *)NULL, &fp, (int *)NULL, 0) < 7)
+            continue;
+        if (fl) {
+
+            /*
+             * Check the column labels in the first line.
+             */
+            if (!fp[0] || strcmp(fp[0], "Local_Address") || !fp[1] ||
+                strcmp(fp[1], "Remote_Address") || !fp[2] ||
+                strcmp(fp[2], "Tx_Queue") || !fp[3] ||
+                strcmp(fp[3], "Rx_Queue") || !fp[4] || strcmp(fp[4], "State") ||
+                !fp[5] || strcmp(fp[5], "Uid") || !fp[6] ||
+                strcmp(fp[6], "Inode")) {
+                if (!Fwarn) {
+                    (void)fprintf(
+                        stderr, "%s: WARNING: unsupported format: %s\n", Pn, p);
+                }
+                break;
+            }
+            fl = 0;
+            continue;
+        }
+        /*
+         * Assemble the inode number and see if the inode is already
+         * recorded.
+         */
+        ep = (char *)NULL;
+        if (!fp[6] || !*fp[6] ||
+            (inode = strtoull(fp[6], &ep, 0)) == ULONG_MAX || !ep || *ep)
+            continue;
+        /* Skip if already exists in hash table */
+        if (HASH_FIND_ELEMENT(Ipxsin, INOHASH, struct ipxsin, inode, inode))
+            continue;
+        /*
+         * Assemble the transmit and receive queue values and the state.
+         */
+        ep = (char *)NULL;
+        if (!fp[2] || !*fp[2] || (txq = strtoul(fp[2], &ep, 16)) == ULONG_MAX ||
+            !ep || *ep)
+            continue;
+        ep = (char *)NULL;
+        if (!fp[3] || !*fp[3] || (rxq = strtoul(fp[3], &ep, 16)) == ULONG_MAX ||
+            !ep || *ep)
+            continue;
+        ep = (char *)NULL;
+        if (!fp[4] || !*fp[4] ||
+            (state = strtoul(fp[4], &ep, 16)) == ULONG_MAX || !ep || *ep)
+            continue;
+        /*
+         * Allocate space for the local address, unless it is "Not_Connected".
+         */
+        if (!fp[0] || !*fp[0] || strcmp(fp[0], "Not_Connected") == 0)
+            la = (char *)NULL;
+        else if ((len = strlen(fp[0]))) {
+            if (!(la = (char *)malloc(len + 1))) {
+                (void)fprintf(
+                    stderr,
+                    "%s: can't allocate %d local IPX address bytes: %s\n", Pn,
+                    (int)(len + 1), fp[0]);
+                Error(ctx);
+            }
+            (void)snpf(la, len + 1, "%s", fp[0]);
+        } else
+            la = (char *)NULL;
+        /*
+         * Allocate space for the remote address, unless it is "Not_Connected".
+         */
+        if (!fp[1] || !*fp[1] || strcmp(fp[1], "Not_Connected") == 0)
+            ra = (char *)NULL;
+        else if ((len = strlen(fp[1]))) {
+            if (!(ra = (char *)malloc(len + 1))) {
+                (void)fprintf(
+                    stderr,
+                    "%s: can't allocate %d remote IPX address bytes: %s\n", Pn,
+                    (int)(len + 1), fp[1]);
+                Error(ctx);
+            }
+            (void)snpf(ra, len + 1, "%s", fp[1]);
+        } else
+            ra = (char *)NULL;
+        /*
+         * Allocate space for an ipxsin entry, fill it, and link it to its
+         * hash bucket.
+         */
+        if (!(ip = (struct ipxsin *)malloc(sizeof(struct ipxsin)))) {
+            (void)fprintf(stderr,
+                          "%s: can't allocate %d byte ipxsin structure\n", Pn,
+                          (int)sizeof(struct ipxsin));
+            Error(ctx);
+        }
+        ip->inode = inode;
+        ip->la = la;
+        ip->ra = ra;
+        ip->txq = txq;
+        ip->rxq = rxq;
+        ip->state = (int)state;
+        HASH_INSERT_ELEMENT(Ipxsin, INOHASH, ip, inode);
+    }
+    (void)fclose(xs);
+}
+
+/*
+ * get_netlink() - get /proc/net/netlink info
+ */
+static void get_netlink(struct lsof_context *ctx, /* context */
+                        char *p)                  /* /proc/net/netlink path */
+{
+    char buf[MAXPATHLEN], *ep, **fp;
+    int fr = 1;
+    int h, pr;
+    INODETYPE inode;
+    struct nlksin *np, *lp;
+    static char *vbuf = (char *)NULL;
+    static size_t vsz = (size_t)0;
+    FILE *xs;
+    /*
+     * Do second time cleanup or first time setup.
+     */
+    if (Nlksin) {
+        for (h = 0; h < INOBUCKS; h++) {
+            for (lp = Nlksin[h]; lp; lp = np) {
+                np = lp->next;
+                (void)free((FREE_P *)lp);
+            }
+            Nlksin[h] = (struct nlksin *)NULL;
+        }
+    } else {
+        Nlksin = (struct nlksin **)calloc(INOBUCKS, sizeof(struct nlksin *));
+        if (!Nlksin) {
+            (void)fprintf(stderr,
+                          "%s: can't allocate %d netlink hash pointer bytes\n",
+                          Pn, (int)(INOBUCKS * sizeof(struct nlksin *)));
+            Error(ctx);
+        }
+    }
+    /*
+     * Open the /proc/net/netlink file, assign a page size buffer to its stream,
+     * and read the file.  Store Netlink info in the Nlksin[] hash buckets.
+     */
+    if (!(xs = open_proc_stream(ctx, p, "r", &vbuf, &vsz, 0)))
+        return;
+    while (fgets(buf, sizeof(buf) - 1, xs)) {
+        if (get_fields(ctx, buf, (char *)NULL, &fp, (int *)NULL, 0) < 10)
+            continue;
+        if (fr) {
+
+            /*
+             * Check the column labels in the first line.
+             */
+            if (!fp[1] || strcmp(fp[1], "Eth") || !fp[9] ||
+                strcmp(fp[9], "Inode")) {
+                if (!Fwarn) {
+                    (void)fprintf(
+                        stderr, "%s: WARNING: unsupported format: %s\n", Pn, p);
+                }
+                break;
+            }
+            fr = 0;
+            continue;
+        }
+        /*
+         * Assemble the inode number and see if the inode is already
+         * recorded.
+         */
+        ep = (char *)NULL;
+        if (!fp[9] || !*fp[9] ||
+            (inode = strtoull(fp[9], &ep, 0)) == ULONG_MAX || !ep || *ep)
+            continue;
+        /* Skip if already exists in hash table */
+        if (HASH_FIND_ELEMENT(Nlksin, INOHASH, struct nlksin, inode, inode))
+            continue;
+        /*
+         * Save the protocol from the Eth column.
+         */
+        if (!fp[1] || !*fp[1] || (strlen(fp[1])) < 1)
+            continue;
+        pr = atoi(fp[1]);
+        /*
+         * Allocate space for a nlksin entry, fill it, and link it to its
+         * hash bucket.
+         */
+        if (!(lp = (struct nlksin *)malloc(sizeof(struct nlksin)))) {
+            (void)fprintf(stderr,
+                          "%s: can't allocate %d byte Netlink structure\n", Pn,
+                          (int)sizeof(struct nlksin));
+            Error(ctx);
+        }
+        lp->inode = inode;
+        lp->pr = pr;
+        HASH_INSERT_ELEMENT(Nlksin, INOHASH, lp, inode);
+    }
+    (void)fclose(xs);
+}
+
+/*
+ * get_pack() - get /proc/net/packet info
+ */
+static void get_pack(struct lsof_context *ctx, /* context */
+                     char *p)                  /* /proc/net/raw path */
+{
+    char buf[MAXPATHLEN], *ep, **fp;
+    int fl = 1;
+    int h, ty;
+    INODETYPE inode;
+    struct packin *np, *pp;
+    unsigned long pr;
+    static char *vbuf = (char *)NULL;
+    static size_t vsz = (size_t)0;
+    FILE *xs;
+    /*
+     * Do second time cleanup or first time setup.
+     */
+    if (Packin) {
+        for (h = 0; h < INOBUCKS; h++) {
+            for (pp = Packin[h]; pp; pp = np) {
+                np = pp->next;
+                (void)free((FREE_P *)pp);
+            }
+            Packin[h] = (struct packin *)NULL;
+        }
+    } else {
+        Packin = (struct packin **)calloc(INOBUCKS, sizeof(struct packin *));
+        if (!Packin) {
+            (void)fprintf(stderr,
+                          "%s: can't allocate %d packet hash pointer bytes\n",
+                          Pn, (int)(INOBUCKS * sizeof(struct packin *)));
+            Error(ctx);
+        }
+    }
+    /*
+     * Open the /proc/net/packet file, assign a page size buffer to its stream,
+     * and read the file.  Store packet info in the Packin[] hash buckets.
+     */
+    if (!(xs = open_proc_stream(ctx, p, "r", &vbuf, &vsz, 0)))
+        return;
+    while (fgets(buf, sizeof(buf) - 1, xs)) {
+        if (get_fields(ctx, buf, (char *)NULL, &fp, (int *)NULL, 0) < 9)
+            continue;
+        if (fl) {
+
+            /*
+             * Check the column labels in the first line.
+             */
+            if (!fp[2] || strcmp(fp[2], "Type") || !fp[3] ||
+                strcmp(fp[3], "Proto") || !fp[8] || strcmp(fp[8], "Inode")) {
+                if (!Fwarn) {
+                    (void)fprintf(
+                        stderr, "%s: WARNING: unsupported format: %s\n", Pn, p);
+                }
+                break;
+            }
+            fl = 0;
+            continue;
+        }
+        /*
+         * Assemble the inode number and see if the inode is already
+         * recorded.
+         */
+        ep = (char *)NULL;
+        if (!fp[8] || !*fp[8] ||
+            (inode = strtoull(fp[8], &ep, 0)) == ULONG_MAX || !ep || *ep)
+            continue;
+        /* Skip if already exists in hash table */
+        if (HASH_FIND_ELEMENT(Packin, INOHASH, struct packin, inode, inode))
+            continue;
+        /*
+         * Save the socket type and protocol.
+         */
+        if (!fp[2] || !*fp[2] || (strlen(fp[2])) < 1)
+            continue;
+        ty = atoi(fp[2]);
+        ep = (char *)NULL;
+        if (!fp[3] || !*fp[3] || (strlen(fp[3]) < 1) ||
+            ((pr = strtoul(fp[3], &ep, 16)) == ULONG_MAX) || !ep || *ep)
+            continue;
+        /*
+         * Allocate space for a packin entry, fill it, and link it to its
+         * hash bucket.
+         */
+        if (!(pp = (struct packin *)malloc(sizeof(struct packin)))) {
+            (void)fprintf(stderr,
+                          "%s: can't allocate %d byte packet structure\n", Pn,
+                          (int)sizeof(struct packin));
+            Error(ctx);
+        }
+        pp->inode = inode;
+        pp->pr = (int)pr;
+        pp->ty = ty;
+        HASH_INSERT_ELEMENT(Packin, INOHASH, pp, inode);
+    }
+    (void)fclose(xs);
+}
+
+/*
+ * get_raw() - get /proc/net/raw info
+ */
+static void get_raw(struct lsof_context *ctx, /* context */
+                    char *p)                  /* /proc/net/raw path */
+{
+    char buf[MAXPATHLEN], *ep, **fp, *la, *ra, *sp;
+    int h;
+    INODETYPE inode;
+    int nf = 12;
+    struct rawsin *np, *rp;
+    MALLOC_S lal, ral, spl;
+    static char *vbuf = (char *)NULL;
+    static size_t vsz = (size_t)0;
+    FILE *xs;
+    /*
+     * Do second time cleanup or first time setup.
+     */
+    if (Rawsin) {
+        for (h = 0; h < INOBUCKS; h++) {
+            for (rp = Rawsin[h]; rp; rp = np) {
+                np = rp->next;
+                if (rp->la)
+                    (void)free((FREE_P *)rp->la);
+                if (rp->ra)
+                    (void)free((FREE_P *)rp->ra);
+                (void)free((FREE_P *)rp);
+            }
+            Rawsin[h] = (struct rawsin *)NULL;
+        }
+    } else {
+        Rawsin = (struct rawsin **)calloc(INOBUCKS, sizeof(struct rawsin *));
+        if (!Rawsin) {
+            (void)fprintf(stderr,
+                          "%s: can't allocate %d raw hash pointer bytes\n", Pn,
+                          (int)(INOBUCKS * sizeof(struct rawsin *)));
+            Error(ctx);
+        }
+    }
+    /*
+     * Open the /proc/net/raw file, assign a page size buffer to its stream,
+     * and read the file.  Store raw socket info in the Rawsin[] hash buckets.
+     */
+    if (!(xs = open_proc_stream(ctx, p, "r", &vbuf, &vsz, 0)))
+        return;
+    while (fgets(buf, sizeof(buf) - 1, xs)) {
+        if (get_fields(ctx, buf, (char *)NULL, &fp, (int *)NULL, 0) < nf)
+            continue;
+        if (nf == 12) {
+
+            /*
+             * Check the column labels in the first line.
+             */
+            if (!fp[1] || strcmp(fp[1], "local_address") || !fp[2] ||
+                strcmp(fp[2], "rem_address") || !fp[3] || strcmp(fp[3], "st") ||
+                !fp[11] || strcmp(fp[11], "inode")) {
+                if (!Fwarn) {
+                    (void)fprintf(
+                        stderr, "%s: WARNING: unsupported format: %s\n", Pn, p);
+                }
+                break;
+            }
+            nf = 10;
+            continue;
+        }
+        /*
+         * Assemble the inode number and see if the inode is already
+         * recorded.
+         */
+        ep = (char *)NULL;
+        if (!fp[9] || !*fp[9] ||
+            (inode = strtoull(fp[9], &ep, 0)) == ULONG_MAX || !ep || *ep)
+            continue;
+        /* Skip if already exists in hash table */
+        if (HASH_FIND_ELEMENT(Rawsin, INOHASH, struct rawsin, inode, inode))
+            continue;
+        /*
+         * Save the local address, remote address, and state.
+         */
+        if (!fp[1] || !*fp[1] || (lal = strlen(fp[1])) < 1) {
+            la = (char *)NULL;
+            lal = (MALLOC_S)0;
+        } else {
+            if (!(la = (char *)malloc(lal + 1))) {
+                (void)fprintf(
+                    stderr,
+                    "%s: can't allocate %d local raw address bytes: %s\n", Pn,
+                    (int)(lal + 1), fp[1]);
+                Error(ctx);
+            }
+            (void)snpf(la, lal + 1, "%s", fp[1]);
+        }
+        if (!fp[2] || !*fp[2] || (ral = strlen(fp[2])) < 1) {
+            ra = (char *)NULL;
+            ral = (MALLOC_S)0;
+        } else {
+            if (!(ra = (char *)malloc(ral + 1))) {
+                (void)fprintf(
+                    stderr,
+                    "%s: can't allocate %d remote raw address bytes: %s\n", Pn,
+                    (int)(ral + 1), fp[2]);
+                Error(ctx);
+            }
+            (void)snpf(ra, ral + 1, "%s", fp[2]);
+        }
+        if (!fp[3] || !*fp[3] || (spl = strlen(fp[3])) < 1) {
+            sp = (char *)NULL;
+            spl = (MALLOC_S)0;
+        } else {
+            if (!(sp = (char *)malloc(spl + 1))) {
+                (void)fprintf(
+                    stderr,
+                    "%s: can't allocate %d remote raw state bytes: %s\n", Pn,
+                    (int)(spl + 1), fp[2]);
+                Error(ctx);
+            }
+            (void)snpf(sp, spl + 1, "%s", fp[3]);
+        }
+        /*
+         * Allocate space for an rawsin entry, fill it, and link it to its
+         * hash bucket.
+         */
+        if (!(rp = (struct rawsin *)malloc(sizeof(struct rawsin)))) {
+            (void)fprintf(stderr,
+                          "%s: can't allocate %d byte rawsin structure\n", Pn,
+                          (int)sizeof(struct rawsin));
+            Error(ctx);
+        }
+        rp->inode = inode;
+        rp->la = la;
+        rp->lal = lal;
+        rp->ra = ra;
+        rp->ral = ral;
+        rp->sp = sp;
+        rp->spl = spl;
+        HASH_INSERT_ELEMENT(Rawsin, INOHASH, rp, inode);
+    }
+    (void)fclose(xs);
+}
+
+/*
+ * get_sctp() - get /proc/net/sctp/assocs info
+ */
+static void get_sctp(struct lsof_context *ctx) {
+    char buf[MAXPATHLEN], *a, *ep, **fp, *id, *la, *lp, *ra, *rp, *ta;
+    int d, err, fl, h, i, j, nf, ty, x;
+    INODETYPE inode;
+    MALLOC_S len, plen;
+    struct sctpsin *sp, *np;
+    FILE *ss;
+    static char *vbuf = (char *)NULL;
+    static size_t vsz = (size_t)0;
+    /*
+     * Do second time cleanup or first time setup.
+     */
+    if (SCTPsin) {
+        for (h = 0; h < INOBUCKS; h++) {
+            for (sp = SCTPsin[h]; sp; sp = np) {
+                np = sp->next;
+                if (sp->addr)
+                    (void)free((FREE_P *)sp->addr);
+                if (sp->assocID)
+                    (void)free((FREE_P *)sp->assocID);
+                if (sp->lport)
+                    (void)free((FREE_P *)sp->lport);
+                if (sp->rport)
+                    (void)free((FREE_P *)sp->rport);
+                if (sp->laddrs)
+                    (void)free((FREE_P *)sp->laddrs);
+                if (sp->raddrs)
+                    (void)free((FREE_P *)sp->raddrs);
+                (void)free((FREE_P *)sp);
+            }
+            SCTPsin[h] = (struct sctpsin *)NULL;
+        }
+    } else {
+        SCTPsin = (struct sctpsin **)calloc(INOBUCKS, sizeof(struct sctpsin *));
+        if (!SCTPsin) {
+            (void)fprintf(stderr,
+                          "%s: can't allocate %d SCTP hash pointer bytes\n", Pn,
+                          (int)(INOBUCKS * sizeof(struct sctpsin *)));
+            Error(ctx);
+        }
+    }
+    /*
+     * Open the /proc/net/sctp files, assign a page size buffer to the streams,
+     * and read them.  Store SCTP socket info in the SCTPsin[] hash buckets.
+     */
+    for (i = 0; i < NSCTPPATHS; i++) {
+        if (!(ss = open_proc_stream(ctx, SCTPPath[i], "r", &vbuf, &vsz, 0)))
+            continue;
+        fl = 1;
+        while (fgets(buf, sizeof(buf) - 1, ss)) {
+            if ((nf = get_fields(ctx, buf, (char *)NULL, &fp, (int *)NULL, 0)) <
+                (i ? 9 : 16)) {
+                continue;
+            }
+            if (fl) {
+
+                /*
+                 * Check the column labels in the first line.
+                 */
+                err = 0;
+                switch (i) {
+                case 0:
+                    if (!fp[0] || strcmp(fp[0], "ASSOC") || !fp[6] ||
+                        strcmp(fp[6], "ASSOC-ID") || !fp[10] ||
+                        strcmp(fp[10], "INODE") || !fp[11] ||
+                        strcmp(fp[11], "LPORT") || !fp[12] ||
+                        strcmp(fp[12], "RPORT") || !fp[13] ||
+                        strcmp(fp[13], "LADDRS") || !fp[14] ||
+                        strcmp(fp[14], "<->") || !fp[15] ||
+                        strcmp(fp[15], "RADDRS")) {
+                        err = 1;
+                    }
+                    break;
+                case 1:
+                    if (!fp[0] || strcmp(fp[0], "ENDPT") || !fp[5] ||
+                        strcmp(fp[5], "LPORT") || !fp[7] ||
+                        strcmp(fp[7], "INODE") || !fp[8] ||
+                        strcmp(fp[8], "LADDRS")) {
+                        err = 1;
+                    }
+                }
+                if (err) {
+                    if (!Fwarn)
+                        (void)fprintf(stderr,
+                                      "%s: WARNING: unsupported format: %s\n",
+                                      Pn, SCTPPath[i]);
+                    break;
+                }
+                fl = 0;
+                continue;
+            }
+            /*
+             * Assemble the inode number and see if it has already been
+             * recorded.
+             */
+            ep = (char *)NULL;
+            j = i ? 7 : 10;
+            if (!fp[j] || !*fp[j] ||
+                (inode = strtoull(fp[j], &ep, 0)) == ULONG_MAX || !ep || *ep)
+                continue;
+            sp = HASH_FIND_ELEMENT(SCTPsin, INOHASH, struct sctpsin, inode,
+                                   inode);
+            /*
+             * Set the entry type.
+             */
+            if (sp)
+                ty = (sp->type == i) ? i : 3;
+            else
+                ty = i;
+            /*
+             * Allocate space for this line's sctpsin members.
+             *
+             * The association or endpoint address is in the first field.
+             */
+            a = sp ? sp->addr : (char *)NULL;
+            if (fp[0] && *fp[0] && (len = strlen(fp[0]))) {
+                if (a) {
+                    if (isainb(fp[0], a)) {
+                        plen = strlen(a);
+                        a = (char *)realloc((MALLOC_P *)a, plen + len + 2);
+                        d = 0;
+                    } else
+                        d = 1;
+                } else {
+                    plen = (MALLOC_S)0;
+                    a = (char *)malloc(len + 1);
+                    d = 0;
+                }
+                if (!a) {
+                    (void)fprintf(
+                        stderr, "%s: can't allocate %d SCTP ASSOC bytes: %s\n",
+                        Pn, (int)(len + 1), fp[0]);
+                    Error(ctx);
+                }
+                if (!d) {
+                    if (plen)
+                        (void)snpf((a + plen), len + 2, ",%s", fp[0]);
+                    else
+                        (void)snpf(a, len + 1, "%s", fp[0]);
+                }
+            }
+            /*
+             * The association ID is in the seventh field.
+             */
+            id = sp ? sp->assocID : (char *)NULL;
+            if (!i && fp[6] && *fp[6] && (len = strlen(fp[6]))) {
+                if (id) {
+                    if (isainb(fp[6], id)) {
+                        plen = strlen(id);
+                        id = (char *)realloc((MALLOC_P *)id, plen + len + 2);
+                        d = 0;
+                    } else
+                        d = 1;
+                } else {
+                    plen = (MALLOC_S)0;
+                    id = (char *)malloc(len + 1);
+                    d = 0;
+                }
+                if (!id) {
+                    (void)fprintf(
+                        stderr,
+                        "%s: can't allocate %d SCTP ASSOC-ID bytes: %s\n", Pn,
+                        (int)(len + 1), fp[6]);
+                    Error(ctx);
+                }
+                if (!d) {
+                    if (plen)
+                        (void)snpf((id + plen), len + 2, ",%s", fp[6]);
+                    else
+                        (void)snpf(id, len + 1, "%s", fp[6]);
+                }
+            }
+            /*
+             * The field number for the local port depends on the entry type.
+             */
+            j = i ? 5 : 11;
+            lp = sp ? sp->lport : (char *)NULL;
+            if (fp[j] && *fp[j] && (len = strlen(fp[j]))) {
+                if (lp) {
+                    if (isainb(fp[j], lp)) {
+                        plen = strlen(lp);
+                        lp = (char *)realloc((MALLOC_P *)lp, plen + len + 2);
+                        d = 0;
+                    } else
+                        d = 1;
+                } else {
+                    plen = (MALLOC_S)0;
+                    lp = (char *)malloc(len + 1);
+                    d = 0;
+                }
+                if (!lp) {
+                    (void)fprintf(
+                        stderr, "%s: can't allocate %d SCTP LPORT bytes: %s\n",
+                        Pn, (int)(len + 1), fp[j]);
+                    Error(ctx);
+                }
+                if (!d) {
+                    if (plen)
+                        (void)snpf((lp + plen), len + 2, ",%s", fp[j]);
+                    else
+                        (void)snpf(lp, len + 1, "%s", fp[j]);
+                }
+            }
+            /*
+             * The field number for the remote port depends on the entry type.
+             */
+            rp = sp ? sp->rport : (char *)NULL;
+            if (!i && fp[12] && *fp[12] && (len = strlen(fp[12]))) {
+                if (rp) {
+                    if (isainb(fp[12], rp)) {
+                        plen = strlen(rp);
+                        rp = (char *)realloc((MALLOC_P *)rp, plen + len + 2);
+                        d = 0;
+                    } else
+                        d = 1;
+                } else {
+                    plen = (MALLOC_S)0;
+                    rp = (char *)malloc(len + 1);
+                    d = 0;
+                }
+                if (!rp) {
+                    (void)fprintf(
+                        stderr, "%s: can't allocate %d SCTP RPORT bytes: %s\n",
+                        Pn, (int)(len + 1), fp[12]);
+                    Error(ctx);
+                }
+                if (!d) {
+                    if (plen)
+                        (void)snpf((rp + plen), len + 2, ",%s", fp[12]);
+                    else
+                        (void)snpf(rp, len + 1, "%s", fp[12]);
+                }
+            }
+            /*
+             * The local addresses begin in a field whose number depends on
+             * the entry type.
+             */
+            j = i ? 8 : 13;
+            la = sp ? sp->laddrs : (char *)NULL;
+            x = 0;
+            if (fp[j] && *fp[j] && (len = strlen(fp[j]))) {
+                if (!(ta = get_sctpaddrs(fp, j, nf, &x))) {
+                    (void)fprintf(stderr,
+                                  "%s: can't allocate %d SCTP LADDRS bytes\n",
+                                  Pn, (int)len);
+                    Error(ctx);
+                }
+                if (la) {
+                    if (isainb(ta, la)) {
+                        len = strlen(ta);
+                        plen = strlen(la);
+                        if (!(la = (char *)realloc((MALLOC_P *)la,
+                                                   plen + len + 2))) {
+                            (void)fprintf(
+                                stderr,
+                                "%s: can't reallocate %d SCTP LADDRS bytes\n",
+                                Pn, (int)len);
+                            Error(ctx);
+                        }
+                        (void)snpf(la + plen, len + 2, ",%s", ta);
+                        (void)free((FREE_P *)ta);
+                    }
+                } else
+                    la = ta;
+            }
+            /*
+             * The remote addresses begin after the local addresses, but only
+             * for the ASSOC type.
+             */
+            ra = sp ? sp->raddrs : (char *)NULL;
+            if (!i && x && fp[x + 1] && *fp[x + 1] &&
+                (len = strlen(fp[x + 1]))) {
+                if (!(ta = get_sctpaddrs(fp, x + 1, nf, &x))) {
+                    (void)fprintf(stderr,
+                                  "%s: can't allocate %d SCTP RADDRS bytes\n",
+                                  Pn, (int)len);
+                    Error(ctx);
+                }
+                if (ra) {
+                    if (isainb(ta, ra)) {
+                        len = strlen(ta);
+                        plen = strlen(ra);
+                        if (!(ra = (char *)realloc((MALLOC_P *)ra,
+                                                   plen + len + 2))) {
+                            (void)fprintf(
+                                stderr,
+                                "%s: can't reallocate %d SCTP RADDRS bytes\n",
+                                Pn, (int)len);
+                            Error(ctx);
+                        }
+                        (void)snpf(ra + plen, len + 2, ",%s", ta);
+                        (void)free((FREE_P *)ta);
+                    }
+                } else
+                    ra = ta;
+            }
+            /*
+             * If no matching sctpsin entry was found for this inode, allocate
+             * space for a new sctpsin entry, fill it, and link it to its hash
+             * bucket.  Update a matching entry.
+             */
+            if (!sp) {
+                if (!(sp = (struct sctpsin *)malloc(sizeof(struct sctpsin)))) {
+                    (void)fprintf(
+                        stderr,
+                        "%s: can't allocate %d byte sctpsin structure\n", Pn,
+                        (int)sizeof(struct sctpsin));
+                    Error(ctx);
+                }
+                sp->inode = inode;
+                HASH_INSERT_ELEMENT(SCTPsin, INOHASH, sp, inode);
+            }
+            sp->addr = a;
+            sp->assocID = id;
+            sp->lport = lp;
+            sp->rport = rp;
+            sp->laddrs = la;
+            sp->raddrs = ra;
+            sp->type = ty;
+        }
+        (void)fclose(ss);
+    }
+}
+
+static char *get_sctpaddrs(char **fp, /* field pointers */
+                           int i,     /* first address field index in fp */
+                           int nf,    /* number of fields */
+                           int *x)    /* index of first "<->" field entry */
+{
+    MALLOC_S al = (MALLOC_S)0;
+    char *cp = (char *)NULL;
+    MALLOC_S tl;
+
+    *x = 0;
+    do {
+        if ((i >= nf) || !fp[i] || !*fp[i] || !(tl = strlen(fp[i])))
+            break;
+        if (!strcmp(fp[i], "<->")) {
+            *x = i;
+            break;
+        }
+        if (!strchr(fp[i], (int)'.') && !strchr(fp[i], (int)':'))
+            break;
+        if (cp)
+            cp = (char *)realloc((MALLOC_P *)cp, al + tl + 1);
+        else
+            cp = (char *)malloc(al + tl + 1);
+        if (!cp)
+            break;
+        if (al)
+            *(cp + al - 1) = ',';
+        (void)strncpy(al ? (cp + al) : cp, fp[i], tl);
+        al += (tl + 1);
+        *(cp + al - 1) = '\0';
+    } while (++i < nf);
+    return (cp);
+}
+
+/*
+ * get_tcpudp() - get IPv4 TCP, UDP or UDPLITE net info
+ */
+static void get_tcpudp(struct lsof_context *ctx, /* context */
+                       char *p,                  /* /proc/net/{tcp,udp} path */
+                       int pr,                   /* protocol: 0 = TCP, 1 = UDP,
+                                                  *           2 = UDPLITE */
+                       int clr)                  /* 1 == clear the table */
+{
+    char buf[MAXPATHLEN], *ep, **fp;
+    unsigned long faddr, fport, laddr, lport, rxq, state, txq;
+    FILE *fs;
+    int h, nf;
+    INODETYPE inode;
+    struct tcp_udp *np, *tp;
+    static char *vbuf = (char *)NULL;
+    static size_t vsz = (size_t)0;
+
+#if defined(HASEPTOPTS)
+    pxinfo_t *pp, *pnp;
+#endif /* defined(HASEPTOPTS) */
+
+    /*
+     * Delete previous table contents.
+     */
+    if (TcpUdp) {
+        if (clr) {
+            for (h = 0; h < TcpUdp_bucks; h++) {
+                for (tp = TcpUdp[h]; tp; tp = np) {
+                    np = tp->next;
+
+#if defined(HASEPTOPTS)
+                    for (pp = tp->pxinfo; pp; pp = pnp) {
+                        pnp = pp->next;
+                        (void)free((FREE_P *)pp);
+                    }
+#endif /* defined(HASEPTOPTS) */
+
+                    (void)free((FREE_P *)tp);
+                }
+                TcpUdp[h] = (struct tcp_udp *)NULL;
+            }
+#if defined(HASEPTOPTS)
+            if (FeptE)
+                for (h = 0; h < IPCBUCKS; h++)
+                    TcpUdpIPC[h] = (struct tcp_udp *)NULL;
+#endif /* defined(HASEPTOPTS) */
+        }
+        /*
+         * If no hash buckets have been allocated, do so now.
+         */
+    } else {
+
+        /*
+         * Open the /proc/net/sockstat file and establish the hash bucket
+         * count from its "sockets: used" line.
+         */
+        TcpUdp_bucks = INOBUCKS;
+        if ((fs = fopen(SockStatPath, "r"))) {
+            while (fgets(buf, sizeof(buf) - 1, fs)) {
+                if (get_fields(ctx, buf, (char *)NULL, &fp, (int *)NULL, 0) !=
+                    3)
+                    continue;
+                if (!fp[0] || strcmp(fp[0], "sockets:") || !fp[1] ||
+                    strcmp(fp[1], "used") || !fp[2] || !*fp[2])
+                    continue;
+                if ((h = atoi(fp[2])) < 1)
+                    h = INOBUCKS;
+                while (TcpUdp_bucks < h)
+                    TcpUdp_bucks *= 2;
+                break;
+            }
+            (void)fclose(fs);
+        }
+        if (!(TcpUdp = (struct tcp_udp **)calloc(TcpUdp_bucks,
+                                                 sizeof(struct tcp_udp *)))) {
+            (void)fprintf(
+                stderr,
+                "%s: can't allocate %d bytes for TCP&UDP hash buckets\n", Pn,
+                (int)(TcpUdp_bucks * sizeof(struct tcp_udp *)));
+            Error(ctx);
+        }
+#if defined(HASEPTOPTS)
+        if (FeptE && (!(TcpUdpIPC = (struct tcp_udp **)calloc(
+                            IPCBUCKS, sizeof(struct tcp_udp *))))) {
+            (void)fprintf(stderr,
+                          "%s: can't allocate %d bytes for TCP&UDP local IPC "
+                          "hash buckets\n",
+                          Pn, (int)(IPCBUCKS * sizeof(struct tcp_udp *)));
+            Error(ctx);
+        }
+#endif /* defined(HASEPTOPTS) */
+    }
+    /*
+     * Open the /proc/net file, assign a page size buffer to the stream, and
+     * read it.
+     */
+    if (!(fs = open_proc_stream(ctx, p, "r", &vbuf, &vsz, 0)))
+        return;
+    nf = 12;
+    while (fgets(buf, sizeof(buf) - 1, fs)) {
+        if (get_fields(ctx, buf, (nf == 12) ? (char *)NULL : ":", &fp,
+                       (int *)NULL, 0) < nf)
+            continue;
+        if (nf == 12) {
+            if (!fp[1] || strcmp(fp[1], "local_address") || !fp[2] ||
+                strcmp(fp[2], "rem_address") || !fp[3] || strcmp(fp[3], "st") ||
+                !fp[4] || strcmp(fp[4], "tx_queue") || !fp[5] ||
+                strcmp(fp[5], "rx_queue") || !fp[11] ||
+                strcmp(fp[11], "inode")) {
+                if (!Fwarn) {
+                    (void)fprintf(
+                        stderr, "%s: WARNING: unsupported format: %s\n", Pn, p);
+                }
+                break;
+            }
+            nf = 14;
+            continue;
+        }
+        /*
+         * Get the local and remote addresses.
+         */
+        ep = (char *)NULL;
+        if (!fp[1] || !*fp[1] ||
+            (laddr = strtoul(fp[1], &ep, 16)) == ULONG_MAX || !ep || *ep)
+            continue;
+        ep = (char *)NULL;
+        if (!fp[2] || !*fp[2] ||
+            (lport = strtoul(fp[2], &ep, 16)) == ULONG_MAX || !ep || *ep)
+            continue;
+        ep = (char *)NULL;
+        if (!fp[3] || !*fp[3] ||
+            (faddr = strtoul(fp[3], &ep, 16)) == ULONG_MAX || !ep || *ep)
+            continue;
+        ep = (char *)NULL;
+        if (!fp[4] || !*fp[4] ||
+            (fport = strtoul(fp[4], &ep, 16)) == ULONG_MAX || !ep || *ep)
+            continue;
+        /*
+         * Get the state and queue sizes.
+         */
+        ep = (char *)NULL;
+        if (!fp[5] || !*fp[5] ||
+            (state = strtoul(fp[5], &ep, 16)) == ULONG_MAX || !ep || *ep)
+            continue;
+        ep = (char *)NULL;
+        if (!fp[6] || !*fp[6] || (txq = strtoul(fp[6], &ep, 16)) == ULONG_MAX ||
+            !ep || *ep)
+            continue;
+        ep = (char *)NULL;
+        if (!fp[7] || !*fp[7] || (rxq = strtoul(fp[7], &ep, 16)) == ULONG_MAX ||
+            !ep || *ep)
+            continue;
+        /*
+         * Get the inode and use it for hashing and searching.
+         */
+        ep = (char *)NULL;
+        if (!fp[13] || !*fp[13] ||
+            (inode = strtoull(fp[13], &ep, 0)) == ULONG_MAX || !ep || *ep)
+            continue;
+        if (HASH_FIND_ELEMENT(TcpUdp, TCPUDPHASH, struct tcp_udp, inode, inode))
+            continue;
+        /*
+         * Create a new entry and link it to its hash bucket.
+         */
+        if (!(tp = (struct tcp_udp *)malloc(sizeof(struct tcp_udp)))) {
+            (void)fprintf(stderr,
+                          "%s: can't allocate %d bytes for tcp_udp struct\n",
+                          Pn, (int)sizeof(struct tcp_udp));
+            Error(ctx);
+        }
+        tp->inode = inode;
+        tp->faddr = faddr;
+        tp->fport = (int)(fport & 0xffff);
+        tp->laddr = laddr;
+        tp->lport = (int)(lport & 0xffff);
+        tp->txq = txq;
+        tp->rxq = rxq;
+        tp->proto = pr;
+        tp->state = (int)state;
+        HASH_INSERT_ELEMENT(TcpUdp, TCPUDPHASH, tp, inode);
+#if defined(HASEPTOPTS)
+        tp->pxinfo = (pxinfo_t *)NULL;
+        if (FeptE) {
+            tp->ipc_peer = (struct tcp_udp *)NULL;
+            if (tp->state == TCP_ESTABLISHED) {
+                int i = TCPUDP_IPC_HASH(tp);
+                tp->ipc_next = TcpUdpIPC[i];
+                TcpUdpIPC[i] = tp;
+            }
+        }
+#endif /* defined(HASEPTOPTS) */
+    }
+
+#if defined(HASEPTOPTS)
+    /*
+     * If endpoint info has been requested, link INET socket peer info.
+     */
+    if (FeptE)
+        get_netpeeri(ctx);
+#endif /* defined(HASEPTOPTS) */
+
+    (void)fclose(fs);
+}
+
+#if defined(HASIPv6)
+/*
+ * get_raw6() - get /proc/net/raw6 info
+ */
+static void get_raw6(struct lsof_context *ctx, /* context */
+                     char *p)                  /* /proc/net/raw path */
+{
+    char buf[MAXPATHLEN], *ep, **fp, *la, *ra, *sp;
+    int h;
+    INODETYPE inode;
+    int nf = 12;
+    struct rawsin *np, *rp;
+    MALLOC_S lal, ral, spl;
+    static char *vbuf = (char *)NULL;
+    static size_t vsz = (size_t)0;
+    FILE *xs;
+    /*
+     * Do second time cleanup or first time setup.
+     */
+    if (Rawsin6) {
+        for (h = 0; h < INOBUCKS; h++) {
+            for (rp = Rawsin6[h]; rp; rp = np) {
+                np = rp->next;
+                if (rp->la)
+                    (void)free((FREE_P *)rp->la);
+                if (rp->ra)
+                    (void)free((FREE_P *)rp->ra);
+                if (rp->sp)
+                    (void)free((FREE_P *)rp->sp);
+                (void)free((FREE_P *)rp);
+            }
+            Rawsin6[h] = (struct rawsin *)NULL;
+        }
+    } else {
+        Rawsin6 = (struct rawsin **)calloc(INOBUCKS, sizeof(struct rawsin *));
+        if (!Rawsin6) {
+            (void)fprintf(stderr,
+                          "%s: can't allocate %d raw6 hash pointer bytes\n", Pn,
+                          (int)(INOBUCKS * sizeof(struct rawsin *)));
+            Error(ctx);
+        }
+    }
+    /*
+     * Open the /proc/net/raw6 file, assign a page size buffer to the stream,
+     * and read it.  Store raw6 socket info in the Rawsin6[] hash buckets.
+     */
+    if (!(xs = open_proc_stream(ctx, p, "r", &vbuf, &vsz, 0)))
+        return;
+    while (fgets(buf, sizeof(buf) - 1, xs)) {
+        if (get_fields(ctx, buf, (char *)NULL, &fp, (int *)NULL, 0) < nf)
+            continue;
+        if (nf == 12) {
+
+            /*
+             * Check the column labels in the first line.
+             */
+            if (!fp[1] || strcmp(fp[1], "local_address") || !fp[2] ||
+                strcmp(fp[2], "remote_address") || !fp[3] ||
+                strcmp(fp[3], "st") || !fp[11] || strcmp(fp[11], "inode")) {
+                if (!Fwarn) {
+                    (void)fprintf(
+                        stderr, "%s: WARNING: unsupported format: %s\n", Pn, p);
+                }
+                break;
+            }
+            nf = 10;
+            continue;
+        }
+        /*
+         * Assemble the inode number and see if the inode is already
+         * recorded.
+         */
+        ep = (char *)NULL;
+        if (!fp[9] || !*fp[9] ||
+            (inode = strtoull(fp[9], &ep, 0)) == ULONG_MAX || !ep || *ep)
+            continue;
+        /* Skip if already exists in hash table */
+        if (HASH_FIND_ELEMENT(Rawsin6, INOHASH, struct rawsin, inode, inode))
+            continue;
+        /*
+         * Save the local address, remote address, and state.
+         */
+        if (!fp[1] || !*fp[1] || (lal = strlen(fp[1])) < 1) {
+            la = (char *)NULL;
+            lal = (MALLOC_S)0;
+        } else {
+            if (!(la = (char *)malloc(lal + 1))) {
+                (void)fprintf(
+                    stderr,
+                    "%s: can't allocate %d local raw6 address bytes: %s\n", Pn,
+                    (int)(lal + 1), fp[1]);
+                Error(ctx);
+            }
+            (void)snpf(la, lal + 1, "%s", fp[1]);
+        }
+        if (!fp[2] || !*fp[2] || (ral = strlen(fp[2])) < 1) {
+            ra = (char *)NULL;
+            ral = (MALLOC_S)0;
+        } else {
+            if (!(ra = (char *)malloc(ral + 1))) {
+                (void)fprintf(
+                    stderr,
+                    "%s: can't allocate %d remote raw6 address bytes: %s\n", Pn,
+                    (int)(ral + 1), fp[2]);
+                Error(ctx);
+            }
+            (void)snpf(ra, ral + 1, "%s", fp[2]);
+        }
+        if (!fp[3] || !*fp[3] || (spl = strlen(fp[3])) < 1) {
+            sp = (char *)NULL;
+            spl = (MALLOC_S)0;
+        } else {
+            if (!(sp = (char *)malloc(spl + 1))) {
+                (void)fprintf(
+                    stderr,
+                    "%s: can't allocate %d remote raw6 state bytes: %s\n", Pn,
+                    (int)(spl + 1), fp[2]);
+                Error(ctx);
+            }
+            (void)snpf(sp, spl + 1, "%s", fp[3]);
+        }
+        /*
+         * Allocate space for an rawsin entry, fill it, and link it to its
+         * hash bucket.
+         */
+        if (!(rp = (struct rawsin *)malloc(sizeof(struct rawsin)))) {
+            (void)fprintf(
+                stderr,
+                "%s: can't allocate %d byte rawsin structure for IPv6\n", Pn,
+                (int)sizeof(struct rawsin));
+            Error(ctx);
+        }
+        rp->inode = inode;
+        rp->la = la;
+        rp->lal = lal;
+        rp->ra = ra;
+        rp->ral = ral;
+        rp->sp = sp;
+        rp->spl = spl;
+        HASH_INSERT_ELEMENT(Rawsin6, INOHASH, rp, inode);
+    }
+    (void)fclose(xs);
+}
+
+/*
+ * get_tcpudp6() - get IPv6 TCP, UDP or UDPLITE net info
+ */
+static void get_tcpudp6(struct lsof_context *ctx, /* context */
+                        char *p,                  /* /proc/net/{tcp,udp} path */
+                        int pr,  /* protocol: 0 = TCP, 1 = UDP */
+                        int clr) /* 1 == clear the table */
+{
+    char buf[MAXPATHLEN], *ep, **fp;
+    struct in6_addr faddr, laddr;
+    unsigned long fport, lport, rxq, state, txq;
+    FILE *fs;
+    int h, i, nf;
+    INODETYPE inode;
+    struct tcp_udp6 *np6, *tp6;
+    static char *vbuf = (char *)NULL;
+    static size_t vsz = (size_t)0;
+
+#    if defined(HASEPTOPTS)
+    pxinfo_t *pp, *pnp;
+#    endif /* defined(HASEPTOPTS) */
+
+    /*
+     * Delete previous table contents.  Allocate a table for the first time.
+     */
+    if (TcpUdp6) {
+        if (clr) {
+            for (h = 0; h < TcpUdp6_bucks; h++) {
+                for (tp6 = TcpUdp6[h]; tp6; tp6 = np6) {
+                    np6 = tp6->next;
+
+#    if defined(HASEPTOPTS)
+                    for (pp = tp6->pxinfo; pp; pp = pnp) {
+                        pnp = pp->next;
+                        (void)free((FREE_P *)pp);
+                    }
+#    endif /* defined(HASEPTOPTS) */
+
+                    (void)free((FREE_P *)tp6);
+                }
+                TcpUdp6[h] = (struct tcp_udp6 *)NULL;
+            }
+#    if defined(HASEPTOPTS)
+            if (FeptE)
+                for (h = 0; h < IPCBUCKS; h++)
+                    TcpUdp6IPC[h] = (struct tcp_udp6 *)NULL;
+#    endif /* defined(HASEPTOPTS) */
+        }
+    } else {
+
+        /*
+         * Open the /proc/net/sockstat6 file and establish the hash bucket
+         * count from its "TCP6: inuse" and "UDP6: inuse" lines.
+         */
+        TcpUdp6_bucks = INOBUCKS;
+        i = nf = 0;
+        if ((fs = fopen(SockStatPath6, "r"))) {
+            while (fgets(buf, sizeof(buf) - 1, fs)) {
+                if (get_fields(ctx, buf, (char *)NULL, &fp, (int *)NULL, 0) !=
+                    3)
+                    continue;
+                if (!fp[0] || !fp[1] || strcmp(fp[1], "inuse") || !fp[2] ||
+                    !*fp[2])
+                    continue;
+                if (!strcmp(fp[0], "TCP6:")) {
+                    nf |= 1;
+                    if ((h = atoi(fp[2])) < 1)
+                        h = INOBUCKS;
+                    i += h;
+                } else if (!strcmp(fp[0], "UDP6:")) {
+                    nf |= 2;
+                    if ((h = atoi(fp[2])) < 1)
+                        h = INOBUCKS;
+                    i += h;
+                } else
+                    continue;
+                if (nf == 3) {
+                    while (TcpUdp6_bucks < i)
+                        TcpUdp6_bucks *= 2;
+                    break;
+                }
+            }
+            (void)fclose(fs);
+        }
+        if (!(TcpUdp6 = (struct tcp_udp6 **)calloc(
+                  TcpUdp6_bucks, sizeof(struct tcp_udp6 *)))) {
+            (void)fprintf(
+                stderr,
+                "%s: can't allocate %d bytes for TCP6&UDP6 hash buckets\n", Pn,
+                (int)(TcpUdp6_bucks * sizeof(struct tcp_udp6 *)));
+            Error(ctx);
+        }
+#    if defined(HASEPTOPTS)
+        if (FeptE && (!(TcpUdp6IPC = (struct tcp_udp6 **)calloc(
+                            IPCBUCKS, sizeof(struct tcp_udp6 *))))) {
+            (void)fprintf(stderr,
+                          "%s: can't allocate %d bytes for TCP6&UDP6 local IPC "
+                          "hash buckets\n",
+                          Pn, (int)(IPCBUCKS * sizeof(struct tcp_udp6 *)));
+            Error(ctx);
+        }
+#    endif /* defined(HASEPTOPTS) */
+    }
+    /*
+     * Open the /proc/net file, assign a page size buffer to the stream,
+     * and read it.
+     */
+    if (!(fs = open_proc_stream(ctx, p, "r", &vbuf, &vsz, 0)))
+        return;
+    nf = 12;
+    while (fgets(buf, sizeof(buf) - 1, fs)) {
+        if (get_fields(ctx, buf, (nf == 12) ? (char *)NULL : ":", &fp,
+                       (int *)NULL, 0) < nf)
+            continue;
+        if (nf == 12) {
+            if (!fp[1] || strcmp(fp[1], "local_address") || !fp[2] ||
+                strcmp(fp[2], "remote_address") || !fp[3] ||
+                strcmp(fp[3], "st") || !fp[4] || strcmp(fp[4], "tx_queue") ||
+                !fp[5] || strcmp(fp[5], "rx_queue") || !fp[11] ||
+                strcmp(fp[11], "inode")) {
+                if (!Fwarn) {
+                    (void)fprintf(
+                        stderr, "%s: WARNING: unsupported format: %s\n", Pn, p);
+                }
+                break;
+            }
+            nf = 14;
+            continue;
+        }
+        /*
+         * Get the local and remote addresses.
+         */
+        if (!fp[1] || !*fp[1] || hex_ipv6_to_in6(fp[1], &laddr))
+            continue;
+        ep = (char *)NULL;
+        if (!fp[2] || !*fp[2] ||
+            (lport = strtoul(fp[2], &ep, 16)) == ULONG_MAX || !ep || *ep)
+            continue;
+        if (!fp[3] || !*fp[3] || hex_ipv6_to_in6(fp[3], &faddr))
+            continue;
+        ep = (char *)NULL;
+        if (!fp[4] || !*fp[4] ||
+            (fport = strtoul(fp[4], &ep, 16)) == ULONG_MAX || !ep || *ep)
+            continue;
+        /*
+         * Get the state and queue sizes.
+         */
+        ep = (char *)NULL;
+        if (!fp[5] || !*fp[5] ||
+            (state = strtoul(fp[5], &ep, 16)) == ULONG_MAX || !ep || *ep)
+            continue;
+        ep = (char *)NULL;
+        if (!fp[6] || !*fp[6] || (txq = strtoul(fp[6], &ep, 16)) == ULONG_MAX ||
+            !ep || *ep)
+            continue;
+        ep = (char *)NULL;
+        if (!fp[7] || !*fp[7] || (rxq = strtoul(fp[7], &ep, 16)) == ULONG_MAX ||
+            !ep || *ep)
+            continue;
+        /*
+         * Get the inode and use it for hashing and searching.
+         */
+        ep = (char *)NULL;
+        if (!fp[13] || !*fp[13] ||
+            (inode = strtoull(fp[13], &ep, 0)) == ULONG_MAX || !ep || *ep)
+            continue;
+        if (HASH_FIND_ELEMENT(TcpUdp6, TCPUDP6HASH, struct tcp_udp6, inode,
+                              inode))
+            continue;
+        /*
+         * Create a new entry and link it to its hash bucket.
+         */
+        if (!(tp6 = (struct tcp_udp6 *)malloc(sizeof(struct tcp_udp6)))) {
+            (void)fprintf(stderr,
+                          "%s: can't allocate %d bytes for tcp_udp6 struct\n",
+                          Pn, (int)sizeof(struct tcp_udp6));
+            Error(ctx);
+        }
+        tp6->inode = inode;
+        tp6->faddr = faddr;
+        tp6->fport = (int)(fport & 0xffff);
+        tp6->laddr = laddr;
+        tp6->lport = (int)(lport & 0xffff);
+        tp6->txq = txq;
+        tp6->rxq = rxq;
+        tp6->proto = pr;
+        tp6->state = (int)state;
+        HASH_INSERT_ELEMENT(TcpUdp6, TCPUDP6HASH, tp6, inode);
+#    if defined(HASEPTOPTS)
+        tp6->pxinfo = (pxinfo_t *)NULL;
+        if (FeptE) {
+            tp6->ipc_peer = (struct tcp_udp6 *)NULL;
+            if (tp6->state == TCP_ESTABLISHED) {
+                int i = TCPUDP6_IPC_HASH(tp6);
+                tp6->ipc_next = TcpUdp6IPC[i];
+                TcpUdp6IPC[i] = tp6;
+            }
+        }
+#    endif /* defined(HASEPTOPTS) */
+    }
+#    if defined(HASEPTOPTS)
+    /*
+     * If endpoint info has been requested, link INET6 socket peer info.
+     */
+    if (FeptE)
+        get_net6peeri(ctx);
+#    endif /* defined(HASEPTOPTS) */
+
+    (void)fclose(fs);
+}
+#endif /* defined(HASIPv6) */
+
+/*
+ * get_unix() - get UNIX net info
+ */
+static void get_unix(struct lsof_context *ctx, /* context */
+                     char *p)                  /* /proc/net/unix path */
+{
+    char buf[MAXPATHLEN], *ep, **fp, *path, *pcb;
+    int fl = 1; /* First line */
+    int h, nf;
+    INODETYPE inode;
+    MALLOC_S len;
+    uxsin_t *np, *up;
+    FILE *us;
+    uint32_t ty;
+    static char *vbuf = (char *)NULL;
+    static size_t vsz = (size_t)0;
+
+#if defined(HASEPTOPTS) && defined(HASUXSOCKEPT)
+    pxinfo_t *pp, *pnp;
+#endif /* defined(HASEPTOPTS) && defined(HASUXSOCKEPT) */
+
+    /*
+     * Do second time cleanup or first time setup.
+     */
+    if (Uxsin) {
+        for (h = 0; h < INOBUCKS; h++) {
+            for (up = Uxsin[h]; up; up = np) {
+                np = up->next;
+
+#if defined(HASEPTOPTS) && defined(HASUXSOCKEPT)
+                for (pp = up->pxinfo; pp; pp = pnp) {
+                    pnp = pp->next;
+                    (void)free((FREE_P *)pp);
+                }
+#endif /* defined(HASEPTOPTS) && defined(HASUXSOCKEPT) */
+
+                if (up->path)
+                    (void)free((FREE_P *)up->path);
+                if (up->pcb)
+                    (void)free((FREE_P *)up->pcb);
+                (void)free((FREE_P *)up);
+            }
+            Uxsin[h] = (uxsin_t *)NULL;
+        }
+    } else {
+        Uxsin = (uxsin_t **)calloc(INOBUCKS, sizeof(uxsin_t *));
+        if (!Uxsin) {
+            (void)fprintf(stderr,
+                          "%s: can't allocate %d bytes for Unix socket info\n",
+                          Pn, (int)(INOBUCKS * sizeof(uxsin_t *)));
+            Error(ctx);
+        }
+    }
+    /*
+     * Open the /proc/net/unix file, assign a page size buffer to the stream,
+     * read the file's contents, and add them to the Uxsin hash buckets.
+     */
+    if (!(us = open_proc_stream(ctx, p, "r", &vbuf, &vsz, 0)))
+        return;
+    while (fgets(buf, sizeof(buf) - 1, us)) {
+        if ((nf = get_fields(ctx, buf, ":", &fp, (int *)NULL, 0)) < 7)
+            continue;
+        if (fl) {
+
+            /*
+             * Check the first line for header words.
+             */
+            if (!fp[0] || strcmp(fp[0], "Num") || !fp[1] ||
+                strcmp(fp[1], "RefCount") || !fp[2] ||
+                strcmp(fp[2], "Protocol") || !fp[3] || strcmp(fp[3], "Flags") ||
+                !fp[4] || strcmp(fp[4], "Type") || !fp[5] ||
+                strcmp(fp[5], "St") || !fp[6] || strcmp(fp[6], "Inode") ||
+                nf < 8 || !fp[7] || strcmp(fp[7], "Path")) {
+                if (!Fwarn) {
+                    (void)fprintf(
+                        stderr, "%s: WARNING: unsupported format: %s\n", Pn, p);
+                }
+                break;
+            }
+            fl = 0;
+            continue;
+        }
+        /*
+         * Assemble PCB address, inode number, and path name.  If this
+         * inode is already represented in Uxsin, skip it.
+         */
+        ep = (char *)NULL;
+        if (!fp[6] || !*fp[6] ||
+            (inode = strtoull(fp[6], &ep, 0)) == ULONG_MAX || !ep || *ep)
+            continue;
+        /* Skip if already exists in hash table */
+        if (HASH_FIND_ELEMENT(Uxsin, INOHASH, uxsin_t, inode, inode))
+            continue;
+        if (!fp[0] || !*fp[0])
+            pcb = (char *)NULL;
+        else {
+            len = strlen(fp[0]) + 2;
+            if (!(pcb = (char *)malloc(len + 1))) {
+                (void)fprintf(stderr,
+                              "%s: can't allocate %d bytes for UNIX PCB: %s\n",
+                              Pn, (int)(len + 1), fp[0]);
+                Error(ctx);
+            }
+            (void)snpf(pcb, len + 1, "0x%s", fp[0]);
+        }
+        if (nf >= 8 && fp[7] && *fp[7] && (len = strlen(fp[7]))) {
+            if (!(path = (char *)malloc(len + 1))) {
+                (void)fprintf(
+                    stderr,
+                    "%s: can't allocate %d bytes for UNIX path \"%s\"\n", Pn,
+                    (int)(len + 1), fp[7]);
+                Error(ctx);
+            }
+            (void)snpf(path, len + 1, "%s", fp[7]);
+        } 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;
+        }
+        /*
+         * Record socket state.
+         */
+        unsigned long proc_flags = 0UL;
+        ep = (char *)NULL;
+        if (fp[3] && *fp[3] &&
+            (proc_flags = strtoul(fp[3], &ep, 16)) == ULONG_MAX)
+            proc_flags = 0UL;
+
+        unsigned long proc_st = 0UL;
+        ep = (char *)NULL;
+        if (fp[5] && *fp[5] &&
+            ((proc_st = strtoul(fp[5], &ep, 16)) == ULONG_MAX))
+            proc_st = 0UL;
+
+        /*
+         * Allocate and fill a Unix socket info structure; link it to its
+         * hash bucket.
+         */
+        if (!(up = (uxsin_t *)malloc(sizeof(uxsin_t)))) {
+            (void)fprintf(stderr,
+                          "%s: can't allocate %d bytes for uxsin struct\n", Pn,
+                          (int)sizeof(uxsin_t));
+            Error(ctx);
+        }
+        up->inode = inode;
+        up->next = (uxsin_t *)NULL;
+        up->pcb = pcb;
+        up->sb_def = 0;
+        up->ty = ty;
+        up->opt = (unsigned int)proc_flags;
+        up->ss = (unsigned int)proc_st;
+        if ((up->path = path) && (*path == '/')) {
+
+            /*
+             * If an absolute path (i.e., one that begins with a '/') exists
+             * for the line, attempt to stat(2) it and save the device and
+             * node numbers reported in the stat buffer.
+             */
+            struct stat sb;
+            int sr;
+
+            if (HasNFS)
+                sr = statsafely(ctx, path, &sb);
+            else
+                sr = stat(path, &sb);
+            if (sr == 0 && ((sb.st_mode & S_IFMT) == S_IFSOCK)) {
+                up->sb_def = 1;
+                up->sb_dev = sb.st_dev;
+                up->sb_ino = (INODETYPE)sb.st_ino;
+                up->sb_rdev = sb.st_rdev;
+            }
+        }
+
+#if defined(HASEPTOPTS) && defined(HASUXSOCKEPT)
+        /*
+         * Clean UNIX socket endpoint values.
+         */
+        up->icstat = 0;
+        up->pxinfo = (pxinfo_t *)NULL;
+        up->peer = up->icons = (uxsin_t *)NULL;
+#endif /* defined(HASEPTOPTS) && defined(HASUXSOCKEPT) */
+
+        HASH_INSERT_ELEMENT(Uxsin, INOHASH, up, inode);
+    }
+
+#if defined(HASEPTOPTS) && defined(HASUXSOCKEPT)
+    /*
+     * If endpoint info has been requested, get UNIX socket peer info.
+     */
+    if (FeptE)
+        get_uxpeeri(ctx);
+#endif /* defined(HASEPTOPTS) && defined(HASUXSOCKEPT) */
+
+    (void)fclose(us);
+}
+
+#if defined(HASIPv6)
+/*
+ * hex_ipv6_to_in6() - convert ASCII IPv6 address in /proc/net/{tcp,udp}6 form
+ *to an in6_addr
+ */
+static int hex_ipv6_to_in6(char *as,            /* address source */
+                           struct in6_addr *ad) /* address destination */
+{
+    char buf[9], *ep;
+    int i;
+    size_t len;
+    /*
+     * Assemble four uint32_t's from 4 X 8 hex digits into s6_addr32[].
+     */
+    for (i = 0, len = strlen(as); (i < 4) && (len >= 8);
+         as += 8, i++, len -= 8) {
+        (void)strncpy(buf, as, 8);
+        buf[8] = '\0';
+        ep = (char *)NULL;
+
+        errno = 0;
+        unsigned long ul_addr = strtoul(buf, &ep, 16);
+        if (!ep || *ep)
+            break;
+        else if (ul_addr == ULONG_MAX && errno == ERANGE) {
+            /* Quoted from strtoul(3)
+               ---------------------------------------------------
+               The strtoul() function returns either the result of
+               the conversion or, if there was a leading minus
+               sign, the negation of the result of the conversion
+               represented as an unsigned value, unless the
+               original (nonnegated) value would overflow; in the
+               latter case, strtoul() returns ULONG_MAX and sets
+               errno to ERANGE.
+               ---------------------------------------------------
+               NOTE: even if the value doesn't overflow, a
+               negative is not acceptable. */
+            break;
+        } else if (ul_addr > (unsigned long)UINT32_MAX) {
+            /* This will never happen:
+               The maximum length of BUF is 8 characters.
+               The possible maximum value represented by BUF is
+               "FFFFFFFF". This is UINT32_MAX.
+               If you agree with what I write here, make a pull
+               request for removing this block. */
+            break;
+        }
+        ad->s6_addr32[i] = (uint32_t)ul_addr;
+    }
+    return ((*as || (i != 4) || len) ? 1 : 0);
+}
+#endif /* defined(HASIPv6) */
+
+/*
+ * isainb(a,b) check if string a is included in b, where b is a comma-separated
+ * string
+ */
+static int isainb(char *a, /*string a */
+                  char *b) /* string b */
+{
+    char *cp, *pp;
+    MALLOC_S la, lb, lt;
+
+    if (!a || !b)
+        return (1);
+    if (!(la = strlen(a)) || !(lb = strlen(b)))
+        return (1);
+    if (!(cp = strchr(b, (int)','))) {
+        if (la != lb)
+            return (1);
+        return (strcmp(a, b));
+    }
+    for (pp = b; pp && *pp;) {
+        lt = (MALLOC_S)(cp - pp);
+        if ((la == lt) && !strncmp(a, pp, lt))
+            return (0);
+        if (*cp) {
+            pp = cp + 1;
+            if (!(cp = strchr(pp, (int)',')))
+                cp = b + lb;
+        } else
+            pp = cp;
+    }
+    return (1);
+}
+
+/*
+ * print_ax25info() - print AX25 socket info
+ */
+static void print_ax25info(struct lsof_context *ctx, /* context */
+                           struct ax25sin *ap)       /* AX25 socket info */
+{
+    char *cp, pbuf[1024];
+    int ds;
+    MALLOC_S pl = (MALLOC_S)0;
+
+    if (Lf->nma)
+        return;
+    if (ap->sa) {
+        ds = (ap->da && strcmp(ap->da, "*")) ? 1 : 0;
+        (void)snpf(&pbuf[pl], sizeof(pbuf) - pl, "%s%s%s ", ap->sa,
+                   ds ? "->" : "", ds ? ap->da : "");
+        pl = strlen(pbuf);
+    }
+    if (ap->sqs) {
+        (void)snpf(&pbuf[pl], sizeof(pbuf) - pl, "(Sq=%lu ", ap->sq);
+        pl = strlen(pbuf);
+        cp = "";
+    } else
+        cp = "(";
+    if (ap->rqs) {
+        (void)snpf(&pbuf[pl], sizeof(pbuf) - pl, "%sRq=%lu ", cp, ap->rq);
+        pl = strlen(pbuf);
+        cp = "";
+    }
+    (void)snpf(&pbuf[pl], sizeof(pbuf) - pl, "%sState=%d", cp, ap->state);
+    pl = strlen(pbuf);
+    if ((ap->state >= 0) && (ap->state < NAX25ST))
+        cp = ax25st[ap->state];
+    else
+        cp = NULL;
+    (void)snpf(&pbuf[pl], sizeof(pbuf) - pl, "%s%s)", cp ? ", " : "",
+               cp ? cp : "");
+    pl = strlen(pbuf);
+    if (!(cp = (char *)malloc(pl + 1))) {
+        (void)fprintf(
+            stderr,
+            "%s: can't allocate %d bytes for AX25 sock state, PID: %d\n", Pn,
+            (int)(pl + 1), Lp->pid);
+        Error(ctx);
+    }
+    (void)snpf(cp, pl + 1, "%s", pbuf);
+    Lf->nma = cp;
+}
+
+/*
+ * print_ipxinfo() - print IPX socket info
+ */
+static void print_ipxinfo(struct lsof_context *ctx, /* context */
+                          struct ipxsin *ip)        /* IPX socket info */
+{
+    char *cp, pbuf[256];
+    MALLOC_S pl;
+
+    if (Lf->nma)
+        return;
+    (void)snpf(pbuf, sizeof(pbuf), "(Tx=%lx Rx=%lx State=%02x)", ip->txq,
+               ip->rxq, ip->state);
+    pl = strlen(pbuf);
+    if (!(cp = (char *)malloc(pl + 1))) {
+        (void)fprintf(
+            stderr, "%s: can't allocate %d bytes for IPX sock state, PID: %d\n",
+            Pn, (int)(pl + 1), Lp->pid);
+        Error(ctx);
+    }
+    (void)snpf(cp, pl + 1, "%s", pbuf);
+    Lf->nma = cp;
+}
+
+/*
+ * process_proc_sock() - process /proc-based socket
+ */
+void process_proc_sock(struct lsof_context *ctx, /* context */
+                       char *p,                  /* node's readlink() path */
+                       char *pbr,      /* node's path before readlink() */
+                       struct stat *s, /* stat() result for path */
+                       int ss,         /* *s status -- i.e, SB_* values */
+                       struct stat *l, /* lstat() result for FD (NULL for
+                                        * others) */
+                       int lss)        /* *l status -- i.e, SB_* values */
+{
+    struct ax25sin *ap;
+    char *cp, *path = (char *)NULL, tbuf[64];
+    unsigned char *fa, *la;
+    struct in_addr fs, ls;
+    struct icmpin *icmpp;
+    struct ipxsin *ip;
+    int i, len, nl, rf;
+    struct nlksin *np;
+    struct packin *pp;
+    char *pr;
+    static char *prp = (char *)NULL;
+    struct rawsin *rp;
+    struct sctpsin *sp;
+    static ssize_t sz;
+    struct tcp_udp *tp;
+    uxsin_t *up;
+
+#if defined(HASIPv6)
+    int af;
+    struct tcp_udp6 *tp6;
+#endif /* defined(HASIPv6) */
+
+    /*
+     * Enter offset, if possible.
+     */
+    if (l && (lss & SB_SIZE) && OffType != OFFSET_UNKNOWN) {
+        Lf->off = (SZOFFTYPE)l->st_size;
+        Lf->off_def = 1;
+    }
+
+    /*
+     * Check for socket's inode presence in the protocol info caches.
+     */
+    if (AX25path) {
+        (void)get_ax25(ctx, AX25path);
+        (void)free((FREE_P *)AX25path);
+        AX25path = (char *)NULL;
+    }
+    if ((ss & SB_INO) && (ap = check_ax25(ctx, (INODETYPE)s->st_ino))) {
+
+        /*
+         * The inode is connected to an AX25 /proc record.
+         *
+         * Set the type to "ax25"; save the device name; save the inode number;
+         * save the destination and source addresses; save the send and receive
+         * queue sizes; and save the connection state.
+         */
+        Lf->type = LSOF_FILE_AX25;
+        if (ap->dev_ch)
+            (void)enter_dev_ch(ctx, ap->dev_ch);
+        Lf->inode = ap->inode;
+        Lf->inp_ty = 1;
+        print_ax25info(ctx, ap);
+        return;
+    }
+
+    if (Ipxpath) {
+        (void)get_ipx(ctx, Ipxpath);
+        (void)free((FREE_P *)Ipxpath);
+        Ipxpath = (char *)NULL;
+    }
+    if ((ss & SB_INO) && (ip = check_ipx(ctx, (INODETYPE)s->st_ino))) {
+        /*
+         * The inode is connected to an IPX /proc record.
+         *
+         * Set the type to "ipx"; enter the inode and device numbers; store
+         * the addresses, queue sizes, and state in the NAME column.
+         */
+        Lf->type = LSOF_FILE_IPX;
+        Lf->inode = (INODETYPE)s->st_ino;
+        Lf->inp_ty = 1;
+
+        if (ss & SB_DEV) {
+            Lf->dev = s->st_dev;
+            Lf->dev_def = 1;
+        }
+
+        cp = Namech;
+        nl = Namechl;
+        *cp = '\0';
+        if (ip->la && nl) {
+            /*
+             * Store the local IPX address.
+             */
+            len = strlen(ip->la);
+            if (len > nl - 1)
+                len = nl - 1;
+            (void)strncpy(cp, ip->la, len);
+            cp += len;
+            *cp = '\0';
+            nl -= len;
+        }
+        if (ip->ra && nl) {
+            /*
+             * Store the remote IPX address, prefixed with "->".
+             */
+            if (nl > 2) {
+                (void)snpf(cp, nl, "->");
+                cp += 2;
+                nl -= 2;
+            }
+            if (nl) {
+                (void)snpf(cp, nl, "%s", ip->ra);
+                len = strlen(ip->ra);
+                cp += len;
+                nl -= len;
+            }
+        }
+        (void)print_ipxinfo(ctx, ip);
+        if (Namech[0])
+            enter_nm(ctx, Namech);
+        return;
+    }
+
+    if (Rawpath) {
+        (void)get_raw(ctx, Rawpath);
+        (void)free((FREE_P *)Rawpath);
+        Rawpath = (char *)NULL;
+    }
+    if ((ss & SB_INO) && (rp = check_raw(ctx, (INODETYPE)s->st_ino))) {
+        /*
+         * The inode is connected to a raw /proc record.
+         *
+         * Set the type to "raw"; enter the inode number; store the local
+         * address, remote address, and state in the NAME column.
+         */
+        Lf->type = LSOF_FILE_RAW;
+        Lf->inode = (INODETYPE)s->st_ino;
+        Lf->inp_ty = 1;
+
+        cp = Namech;
+        nl = Namechl - 2;
+        *cp = '\0';
+        if (rp->la && rp->lal) {
+            /*
+             * Store the local raw address.
+             */
+            if (nl > rp->lal) {
+                (void)snpf(cp, nl, "%s", rp->la);
+                cp += rp->lal;
+                *cp = '\0';
+                nl -= rp->lal;
+            }
+        }
+        if (rp->ra && rp->ral) {
+            /*
+             * Store the remote raw address, prefixed with "->".
+             */
+            if (nl > (rp->ral + 2)) {
+                (void)snpf(cp, nl, "->%s", rp->ra);
+                cp += (rp->ral + 2);
+                *cp = '\0';
+                nl -= (rp->ral + 2);
+            }
+        }
+        if (rp->sp && rp->spl) {
+            /*
+             * Store the state, optionally prefixed by a space, in the
+             * form "st=x...x".
+             */
+
+            if (nl > (len = ((cp == Namech) ? 0 : 1) + 3 + rp->spl)) {
+                (void)snpf(cp, nl, "%sst=%s", (cp == Namech) ? "" : " ",
+                           rp->sp);
+                cp += len;
+                *cp = '\0';
+                nl -= len;
+            }
+        }
+        if (Namech[0])
+            enter_nm(ctx, Namech);
+        return;
+    }
+
+    if (Nlkpath) {
+        (void)get_netlink(ctx, Nlkpath);
+        (void)free((FREE_P *)Nlkpath);
+        Nlkpath = (char *)NULL;
+    }
+    if ((ss & SB_INO) && (np = check_netlink(ctx, (INODETYPE)s->st_ino))) {
+        /*
+         * The inode is connected to a Netlink /proc record.
+         *
+         * Set the type to "netlink" and store the protocol in the NAME
+         * column.  Save the inode number.
+         */
+
+        Lf->type = LSOF_FILE_NETLINK;
+        cp = netlink_proto_to_str(np->pr);
+        if (cp)
+            (void)snpf(Namech, Namechl, "%s", cp);
+        else
+            (void)snpf(Namech, Namechl, "unknown protocol: %d", np->pr);
+
+        Lf->inode = (INODETYPE)s->st_ino;
+        Lf->inp_ty = 1;
+        if (Namech[0])
+            enter_nm(ctx, Namech);
+        return;
+    }
+
+    if (Packpath) {
+        (void)get_pack(ctx, Packpath);
+        (void)free((FREE_P *)Packpath);
+        Packpath = (char *)NULL;
+    }
+    if ((ss & SB_INO) && (pp = check_pack(ctx, (INODETYPE)s->st_ino))) {
+        /*
+         * The inode is connected to a packet /proc record.
+         *
+         * Set the type to "pack" and store the socket type in the NAME
+         * column.  Put the protocol name in the NODE column and the inode
+         * number in the DEVICE column.
+         */
+        Lf->type = LSOF_FILE_PACKET;
+        cp = socket_type_to_str(pp->ty, &rf);
+        (void)snpf(Namech, Namechl, "type=%s%s", rf ? "" : "SOCK_", cp);
+        cp = ethernet_proto_to_str(pp->pr);
+        if (!cp) {
+            /* Unknown ethernet proto */
+            (void)snpf(tbuf, sizeof(tbuf) - 1, "%d", pp->pr);
+            tbuf[sizeof(tbuf) - 1] = '\0';
+            cp = tbuf;
+        }
+        (void)snpf(Lf->iproto, sizeof(Lf->iproto), "%.*s", IPROTOL - 1, cp);
+        Lf->inp_ty = 2;
+        if (ss & SB_INO) {
+            (void)snpf(tbuf, sizeof(tbuf), "%" INODEPSPEC "u",
+                       (INODETYPE)s->st_ino);
+            tbuf[sizeof(tbuf) - 1] = '\0';
+            enter_dev_ch(ctx, tbuf);
+        }
+        if (Namech[0])
+            enter_nm(ctx, Namech);
+        return;
+    }
+
+    if (UNIXpath) {
+        (void)get_unix(ctx, UNIXpath);
+        (void)free((FREE_P *)UNIXpath);
+        UNIXpath = (char *)NULL;
+    }
+    if ((ss & SB_INO) && (up = check_unix(ctx, (INODETYPE)s->st_ino))) {
+
+        /*
+         * The inode is connected to a UNIX /proc record.
+         *
+         * Set the type to "unix"; enter the PCB address in the DEVICE column;
+         * enter the inode number; and save the optional path.
+         */
+        if (Funix)
+            Lf->sf |= SELUNX;
+        Lf->type = LSOF_FILE_UNIX;
+        if (up->pcb)
+            enter_dev_ch(ctx, up->pcb);
+        Lf->inode = (INODETYPE)s->st_ino;
+        Lf->inp_ty = 1;
+
+        Lf->lts.type = up->ty;
+#if defined(HASSOOPT)
+        Lf->lts.opt = up->opt;
+#endif /* defined(HASSOOPT) */
+#if defined(HASSOSTATE)
+        Lf->lts.ss = up->ss;
+#endif /* defined(HASSOSTATE) */
+#if defined(HASEPTOPTS) && defined(HASUXSOCKEPT)
+        if (FeptE) {
+            (void)enter_uxsinfo(ctx, up);
+            Lf->sf |= SELUXSINFO;
+        }
+#endif /* defined(HASEPTOPTS) && defined(HASUXSOCKEPT) */
+
+        cp = socket_type_to_str(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(ctx, Namech);
+        if (Sfile) {
+
+            /*
+             * See if this UNIX domain socket was specified as a search
+             * argument.
+             *
+             * Search first by device and node numbers, if that is possible;
+             * then search by name.
+             */
+            unsigned char f = 0; /* file-found flag */
+
+            if (up->sb_def) {
+
+                /*
+                 * If the UNIX socket information includes stat(2) results, do
+                 * a device and node number search.
+                 *
+                 * Note: that requires the saving, temporary modification and
+                 *	 restoration of some *Lf values.
+                 */
+                unsigned char sv_dev_def;  /* saved dev_def */
+                unsigned char sv_inp_ty;   /* saved inp_ty */
+                unsigned char sv_rdev_def; /* saved rdev_def */
+                dev_t sv_dev;              /* saved dev */
+                INODETYPE sv_inode;        /* saved inode */
+                dev_t sv_rdev;             /* saved rdev */
+
+                sv_dev_def = Lf->dev_def;
+                sv_dev = Lf->dev;
+                sv_inode = Lf->inode;
+                sv_inp_ty = Lf->inp_ty;
+                sv_rdev_def = Lf->rdev_def;
+                sv_rdev = Lf->rdev;
+                Lf->dev_def = Lf->inp_ty = Lf->rdev_def = 1;
+                Lf->dev = up->sb_dev;
+                Lf->inode = up->sb_ino;
+                Lf->rdev = up->sb_rdev;
+                if (is_file_named(ctx, 0, path, (struct mounts *)NULL, 0)) {
+                    f = 1;
+                    Lf->sf |= SELNM;
+                }
+                Lf->dev_def = sv_dev_def;
+                Lf->dev = sv_dev;
+                Lf->inode = sv_inode;
+                Lf->inp_ty = sv_inp_ty;
+                Lf->rdev_def = sv_rdev_def;
+                Lf->rdev = sv_rdev;
+            }
+            if (!f && (ss & SB_MODE)) {
+
+                /*
+                 * If the file has not yet been found and the stat buffer has
+                 * st_mode, search for the file by full path.
+                 */
+                if (is_file_named(ctx, 2, up->path ? up->path : p,
+                                  (struct mounts *)NULL,
+                                  ((s->st_mode & S_IFMT) == S_IFCHR))
+                        ? 1
+                        : 0) {
+                    Lf->sf |= SELNM;
+                }
+            }
+        }
+        return;
+    }
+
+#if defined(HASIPv6)
+    if (Raw6path) {
+        if (!Fxopt)
+            (void)get_raw6(ctx, Raw6path);
+        (void)free((FREE_P *)Raw6path);
+        Raw6path = (char *)NULL;
+    }
+    if (!Fxopt && (ss & SB_INO) &&
+        (rp = check_raw6(ctx, (INODETYPE)s->st_ino))) {
+
+        /*
+         * The inode is connected to a raw IPv6 /proc record.
+         *
+         * Set the type to "raw6"; enter the inode number; store the local
+         * address, remote address, and state in the NAME column.
+         */
+        Lf->type = LSOF_FILE_RAW6;
+        if (ss & SB_INO) {
+            Lf->inode = (INODETYPE)s->st_ino;
+            Lf->inp_ty = 1;
+        }
+        cp = Namech;
+        nl = MAXPATHLEN - 2;
+        if (rp->la && rp->lal) {
+
+            /*
+             * Store the local raw IPv6 address.
+             */
+            if (nl > rp->lal) {
+                (void)snpf(cp, nl, "%s", rp->la);
+                cp += rp->lal;
+                *cp = '\0';
+                nl -= rp->lal;
+            }
+        }
+        if (rp->ra && rp->ral) {
+            /*
+             * Store the remote raw address, prefixed with "->".
+             */
+            if (nl > (rp->ral + 2)) {
+                (void)snpf(cp, nl, "->%s", rp->ra);
+                cp += (rp->ral + 2);
+                nl -= (rp->ral + 2);
+            }
+        }
+        if (rp->sp && rp->spl) {
+
+            /*
+             * Store the state, optionally prefixed by a space, in the
+             * form "st=x...x".
+             */
+
+            if (nl > (len = ((cp == Namech) ? 0 : 1) + 3 + rp->spl)) {
+                (void)snpf(cp, nl, "%sst=%s", (cp == Namech) ? "" : " ",
+                           rp->sp);
+                cp += len;
+                *cp = '\0';
+                nl -= len;
+            }
+        }
+        if (Namech[0])
+            enter_nm(ctx, Namech);
+        return;
+    }
+
+    if (TCP6path) {
+        if (!Fxopt)
+            (void)get_tcpudp6(ctx, TCP6path, 0, 1);
+        (void)free((FREE_P *)TCP6path);
+        TCP6path = (char *)NULL;
+    }
+
+    if (UDP6path) {
+        if (!Fxopt)
+            (void)get_tcpudp6(ctx, UDP6path, 1, 0);
+        (void)free((FREE_P *)UDP6path);
+        UDP6path = (char *)NULL;
+    }
+
+    if (UDPLITE6path) {
+        if (!Fxopt)
+            (void)get_tcpudp6(ctx, UDPLITE6path, 2, 0);
+        (void)free((FREE_P *)UDPLITE6path);
+        UDPLITE6path = (char *)NULL;
+    }
+
+    if (!Fxopt && (ss & SB_INO) &&
+        (tp6 = check_tcpudp6(ctx, (INODETYPE)s->st_ino, &pr))) {
+
+        /*
+         * The inode is connected to an IPv6 TCP or UDP /proc record.
+         *
+         * Set the type to "IPv6"; enter the protocol; put the inode number
+         * in the DEVICE column in lieu of the PCB address; save the local
+         * and foreign IPv6 addresses; save the type and protocol; and
+         * (optionally) save the queue sizes.
+         */
+        i = tp6->state + TcpStOff;
+        if (TcpStXn) {
+
+            /*
+             * Check for state exclusion.
+             */
+            if (i >= 0 && i < TcpNstates) {
+                if (TcpStX[i]) {
+                    Lf->sf |= SELEXCLF;
+                    return;
+                }
+            }
+        }
+        if (TcpStIn) {
+
+            /*
+             * Check for state inclusion.
+             */
+            if (i >= 0 && i < TcpNstates) {
+                if (TcpStI[i])
+                    TcpStI[i] = 2;
+                else {
+                    Lf->sf |= SELEXCLF;
+                    return;
+                }
+            }
+        }
+        if (Fnet && (FnetTy != 4))
+            Lf->sf |= SELNET;
+        Lf->type = LSOF_FILE_IPV6;
+        (void)snpf(Lf->iproto, sizeof(Lf->iproto), "%.*s", IPROTOL - 1, pr);
+        Lf->inp_ty = 2;
+        if (ss & SB_INO) {
+            (void)snpf(tbuf, sizeof(tbuf), "%" INODEPSPEC "u",
+                       (INODETYPE)s->st_ino);
+            tbuf[sizeof(tbuf) - 1] = '\0';
+            enter_dev_ch(ctx, tbuf);
+            Lf->inode = (INODETYPE)s->st_ino;
+        }
+        af = AF_INET6;
+        if (!IN6_IS_ADDR_UNSPECIFIED(&tp6->faddr) || tp6->fport)
+            fa = (unsigned char *)&tp6->faddr;
+        else
+            fa = (unsigned char *)NULL;
+        if (!IN6_IS_ADDR_UNSPECIFIED(&tp6->laddr) || tp6->lport)
+            la = (unsigned char *)&tp6->laddr;
+        else
+            la = (unsigned char *)NULL;
+        if ((fa && IN6_IS_ADDR_V4MAPPED(&tp6->faddr)) ||
+            (la && IN6_IS_ADDR_V4MAPPED(&tp6->laddr))) {
+            af = AF_INET;
+            if (fa)
+                fa += 12;
+            if (la)
+                la += 12;
+        }
+        ent_inaddr(ctx, la, tp6->lport, fa, tp6->fport, af);
+        Lf->lts.type = tp6->proto;
+        Lf->lts.state.i = tp6->state;
+
+#    if defined(HASTCPTPIQ)
+        Lf->lts.rq = tp6->rxq;
+        Lf->lts.sq = tp6->txq;
+        Lf->lts.rqs = Lf->lts.sqs = 1;
+#    endif /* defined(HASTCPTPIQ) */
+
+#    if defined(HASEPTOPTS)
+        if (FeptE && tp6->ipc_peer) {
+            (void)enter_nets6info(ctx, tp6);
+            Lf->sf |= SELNETS6INFO;
+        }
+#    endif /* defined(HASEPTOPTS) */
+        return;
+    }
+#endif /* defined(HASIPv6) */
+
+    if (TCPpath) {
+        if (!Fxopt)
+            (void)get_tcpudp(ctx, TCPpath, 0, 1);
+        (void)free((FREE_P *)TCPpath);
+        TCPpath = (char *)NULL;
+    }
+
+    if (UDPpath) {
+        if (!Fxopt)
+            (void)get_tcpudp(ctx, UDPpath, 1, 0);
+        (void)free((FREE_P *)UDPpath);
+        UDPpath = (char *)NULL;
+    }
+
+    if (UDPLITEpath) {
+        if (!Fxopt)
+            (void)get_tcpudp(ctx, UDPLITEpath, 2, 0);
+        (void)free((FREE_P *)UDPLITEpath);
+        UDPLITEpath = (char *)NULL;
+    }
+
+    if (!Fxopt && (ss & SB_INO) &&
+        (tp = check_tcpudp(ctx, (INODETYPE)s->st_ino, &pr))) {
+
+        /*
+         * The inode is connected to an IPv4 TCP or UDP /proc record.
+         *
+         * Set the type to "inet" or "IPv4"; enter the protocol; put the
+         * inode number in the DEVICE column in lieu of the PCB address;
+         * save the local and foreign IPv4 addresses; save the type and
+         * protocol; and (optionally) save the queue sizes.
+         */
+        i = tp->state + TcpStOff;
+        if (TcpStXn) {
+
+            /*
+             * Check for state exclusion.
+             */
+            if (i >= 0 && i < TcpNstates) {
+                if (TcpStX[i]) {
+                    Lf->sf |= SELEXCLF;
+                    return;
+                }
+            }
+        }
+        if (TcpStIn) {
+
+            /*
+             * Check for state inclusion.
+             */
+            if (i >= 0 && i < TcpNstates) {
+                if (TcpStI[i])
+                    TcpStI[i] = 2;
+                else {
+                    Lf->sf |= SELEXCLF;
+                    return;
+                }
+            }
+        }
+        if (Fnet && (FnetTy != 6))
+            Lf->sf |= SELNET;
+
+#if defined(HASIPv6)
+        Lf->type = LSOF_FILE_IPV4;
+#else  /* !defined(HASIPv6) */
+        Lf->type = LSOF_FILE_INET;
+#endif /* defined(HASIPv6) */
+
+        (void)snpf(Lf->iproto, sizeof(Lf->iproto), "%.*s", IPROTOL - 1, pr);
+        Lf->inp_ty = 2;
+        if (ss & SB_INO) {
+            (void)snpf(tbuf, sizeof(tbuf), "%" INODEPSPEC "u",
+                       (INODETYPE)s->st_ino);
+            tbuf[sizeof(tbuf) - 1] = '\0';
+            enter_dev_ch(ctx, tbuf);
+            Lf->inode = (INODETYPE)s->st_ino;
+        }
+        if (tp->faddr || tp->fport) {
+            fs.s_addr = tp->faddr;
+            fa = (unsigned char *)&fs;
+        } else
+            fa = (unsigned char *)NULL;
+        if (tp->laddr || tp->lport) {
+            ls.s_addr = tp->laddr;
+            la = (unsigned char *)&ls;
+        } else
+            la = (unsigned char *)NULL;
+        ent_inaddr(ctx, la, tp->lport, fa, tp->fport, AF_INET);
+        Lf->lts.type = tp->proto;
+        Lf->lts.state.i = tp->state;
+
+#if defined(HASTCPTPIQ)
+        Lf->lts.rq = tp->rxq;
+        Lf->lts.sq = tp->txq;
+        Lf->lts.rqs = Lf->lts.sqs = 1;
+#endif /* defined(HASTCPTPIQ) */
+
+#if defined(HASEPTOPTS)
+        if (FeptE && tp->ipc_peer) {
+            (void)enter_netsinfo(ctx, tp);
+            Lf->sf |= SELNETSINFO;
+        }
+#endif /* defined(HASEPTOPTS) */
+
+        return;
+    }
+
+    if (SCTPPath[0]) {
+        (void)get_sctp(ctx);
+        for (i = 0; i < NSCTPPATHS; i++) {
+            (void)free((FREE_P *)SCTPPath[i]);
+            SCTPPath[i] = (char *)NULL;
+        }
+    }
+    if ((ss & SB_INO) && (sp = check_sctp(ctx, (INODETYPE)s->st_ino))) {
+
+        /*
+         * The inode is connected to an SCTP /proc record.
+         *
+         * Set the type to "sock"; enter the inode number in the DEVICE
+         * column; set the protocol to SCTP; and fill in the NAME column
+         * with ASSOC, ASSOC-ID, ENDPT, LADDRS, LPORT, RADDRS and RPORT.
+         */
+        Lf->type = LSOF_FILE_SOCKET;
+        (void)snpf(Lf->iproto, sizeof(Lf->iproto), "%.*s", IPROTOL - 1, "SCTP");
+        Lf->inp_ty = 2;
+        (void)snpf(tbuf, sizeof(tbuf), "%" INODEPSPEC "u", (INODETYPE)s->st_ino);
+        tbuf[sizeof(tbuf) - 1] = '\0';
+        enter_dev_ch(ctx, tbuf);
+        Namech[0] = '\0';
+        if (sp->type == 1) {
+
+            /*
+             * This is an ENDPT SCTP file.
+             */
+            (void)snpf(Namech, Namechl, "ENDPT: %s%s%s%s%s%s",
+                       sp->addr ? sp->addr : "",
+                       (sp->laddrs || sp->lport) ? " " : "",
+                       sp->laddrs ? sp->laddrs : "", sp->lport ? "[" : "",
+                       sp->lport ? sp->lport : "", sp->lport ? "]" : "");
+        } else {
+
+            /*
+             * This is an ASSOC, or ASSOC and ENDPT socket file.
+             */
+            (void)snpf(
+                Namech, Namechl, "%s: %s%s%s %s%s%s%s%s%s%s%s%s",
+                sp->type ? "ASSOC+ENDPT" : "ASSOC", sp->addr ? sp->addr : "",
+                (sp->addr && sp->assocID) ? "," : "",
+                sp->assocID ? sp->assocID : "", sp->laddrs ? sp->laddrs : "",
+                sp->lport ? "[" : "", sp->lport ? sp->lport : "",
+                sp->lport ? "]" : "",
+                ((sp->laddrs || sp->lport) && (sp->raddrs || sp->rport)) ? "<->"
+                                                                         : "",
+                sp->raddrs ? sp->raddrs : "", sp->rport ? "[" : "",
+                sp->rport ? sp->rport : "", sp->rport ? "]" : "");
+        }
+        if (Namech[0])
+            enter_nm(ctx, Namech);
+        return;
+    }
+
+    if (ICMPpath) {
+        (void)get_icmp(ctx, ICMPpath);
+        (void)free((FREE_P *)ICMPpath);
+        ICMPpath = (char *)NULL;
+    }
+    if ((ss & SB_INO) && (icmpp = check_icmp(ctx, (INODETYPE)s->st_ino))) {
+
+        /*
+         * The inode is connected to an ICMP /proc record.
+         *
+         * Set the type to "icmp" and store the type in the NAME
+         * column.  Save the inode number.
+         */
+        Lf->type = LSOF_FILE_ICMP;
+        Lf->inode = (INODETYPE)s->st_ino;
+        Lf->inp_ty = 1;
+        cp = Namech;
+        nl = Namechl - 2;
+        *cp = '\0';
+        if (icmpp->la && icmpp->lal) {
+
+            /*
+             * Store the local raw address.
+             */
+            if (nl > icmpp->lal) {
+                (void)snpf(cp, nl, "%s", icmpp->la);
+                cp += icmpp->lal;
+                *cp = '\0';
+                nl -= icmpp->lal;
+            }
+        }
+        if (icmpp->ra && icmpp->ral) {
+
+            /*
+             * Store the remote raw address, prefixed with "->".
+             */
+            if (nl > (icmpp->ral + 2)) {
+                (void)snpf(cp, nl, "->%s", icmpp->ra);
+                cp += (icmpp->ral + 2);
+                *cp = '\0';
+                nl -= (icmpp->ral + 2);
+            }
+        }
+        if (Namech[0])
+            enter_nm(ctx, Namech);
+        return;
+    }
+
+    /*
+     * The socket's protocol can't be identified.
+     */
+    Lf->type = LSOF_FILE_SOCKET;
+    if (ss & SB_INO) {
+        Lf->inode = (INODETYPE)s->st_ino;
+        Lf->inp_ty = 1;
+    }
+    if (ss & SB_DEV) {
+        Lf->dev = s->st_dev;
+        Lf->dev_def = 1;
+    }
+    if (Fxopt)
+        enter_nm(ctx, "can't identify protocol (-X specified)");
+    else {
+        (void)snpf(Namech, Namechl, "protocol: ");
+        if (!prp) {
+            i = (int)strlen(Namech);
+            prp = &Namech[i];
+            sz = (ssize_t)(Namechl - i - 1);
+        }
+        if ((getxattr(pbr, "system.sockprotoname", prp, sz)) < 0)
+            enter_nm(ctx, "can't identify protocol");
+        else
+            enter_nm(ctx, Namech);
+    }
+}
+
+/*
+ * set_net_paths() - set /proc/net paths
+ */
+void set_net_paths(struct lsof_context *ctx, /* context */
+                   char *p,                  /* path to /proc/net/ */
+                   int pl)                   /* strlen(p) */
+{
+    int i;
+    int pathl;
+
+    pathl = 0;
+    (void)make_proc_path(ctx, p, pl, &AX25path, &pathl, "ax25");
+    pathl = 0;
+    (void)make_proc_path(ctx, p, pl, &ICMPpath, &pathl, "icmp");
+    pathl = 0;
+    (void)make_proc_path(ctx, p, pl, &Ipxpath, &pathl, "ipx");
+    pathl = 0;
+    (void)make_proc_path(ctx, p, pl, &Nlkpath, &pathl, "netlink");
+    pathl = 0;
+    (void)make_proc_path(ctx, p, pl, &Packpath, &pathl, "packet");
+    pathl = 0;
+    (void)make_proc_path(ctx, p, pl, &Rawpath, &pathl, "raw");
+    for (i = 0; i < NSCTPPATHS; i++) {
+        pathl = 0;
+        (void)make_proc_path(ctx, p, pl, &SCTPPath[i], &pathl, SCTPSfx[i]);
+    }
+    pathl = 0;
+    (void)make_proc_path(ctx, p, pl, &SockStatPath, &pathl, "sockstat");
+    pathl = 0;
+    (void)make_proc_path(ctx, p, pl, &TCPpath, &pathl, "tcp");
+    pathl = 0;
+    (void)make_proc_path(ctx, p, pl, &UDPpath, &pathl, "udp");
+    pathl = 0;
+    (void)make_proc_path(ctx, p, pl, &UDPLITEpath, &pathl, "udplite");
+
+#if defined(HASIPv6)
+    pathl = 0;
+    (void)make_proc_path(ctx, p, pl, &Raw6path, &pathl, "raw6");
+    pathl = 0;
+    (void)make_proc_path(ctx, p, pl, &SockStatPath6, &pathl, "sockstat6");
+    pathl = 0;
+    (void)make_proc_path(ctx, p, pl, &TCP6path, &pathl, "tcp6");
+    pathl = 0;
+    (void)make_proc_path(ctx, p, pl, &UDP6path, &pathl, "udp6");
+    pathl = 0;
+    (void)make_proc_path(ctx, p, pl, &UDPLITE6path, &pathl, "udplite6");
+#endif /* defined(HASIPv6) */
+
+    pathl = 0;
+    (void)make_proc_path(ctx, p, pl, &UNIXpath, &pathl, "unix");
+}
+
+/*
+ * socket_type_to_str() -- convert socket type number to a string
+ */
+
+static char *socket_type_to_str(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_DCCP)
+    case SOCK_DCCP:
+        sr = "DCCP";
+        break;
+#endif /* defined(SOCK_DCCP) */
+
+#if defined(SOCK_PACKET)
+    case SOCK_PACKET:
+        sr = "PACKET";
+        break;
+#endif /* defined(SOCK_PACKET) */
+
+    default:
+        f = 1;
+        sr = "unknown";
+    }
+    *rf = f;
+    return (sr);
+}
+
+/*
+ * netlink_proto_to_str() -- convert netlink protocol number to a string
+ *
+ * return NULL if the number is unknown.
+ */
+static char *netlink_proto_to_str(unsigned int pr) {
+    char *cp = NULL;
+    switch (pr) {
+#if defined(NETLINK_ROUTE)
+    case NETLINK_ROUTE:
+        cp = "ROUTE";
+        break;
+#endif /* defined(NETLINK_ROUTE) */
+
+#if defined(NETLINK_UNUSED)
+    case NETLINK_UNUSED:
+        cp = "UNUSED";
+        break;
+#endif /* defined(NETLINK_UNUSED) */
+
+#if defined(NETLINK_USERSOCK)
+    case NETLINK_USERSOCK:
+        cp = "USERSOCK";
+        break;
+#endif /* defined(NETLINK_USERSOCK) */
+
+#if defined(NETLINK_FIREWALL)
+    case NETLINK_FIREWALL:
+        cp = "FIREWALL";
+        break;
+#endif /* defined(NETLINK_FIREWALL) */
+
+#if defined(NETLINK_INET_DIAG)
+    case NETLINK_INET_DIAG:
+        cp = "INET_DIAG";
+        break;
+#endif /* defined(NETLINK_INET_DIAG) */
+
+#if defined(NETLINK_NFLOG)
+    case NETLINK_NFLOG:
+        cp = "NFLOG";
+        break;
+#endif /* defined(NETLINK_NFLOG) */
+
+#if defined(NETLINK_XFRM)
+    case NETLINK_XFRM:
+        cp = "XFRM";
+        break;
+#endif /* defined(NETLINK_XFRM) */
+
+#if defined(NETLINK_SELINUX)
+    case NETLINK_SELINUX:
+        cp = "SELINUX";
+        break;
+#endif /* defined(NETLINK_SELINUX) */
+
+#if defined(NETLINK_ISCSI)
+    case NETLINK_ISCSI:
+        cp = "ISCSI";
+        break;
+#endif /* defined(NETLINK_ISCSI) */
+
+#if defined(NETLINK_AUDIT)
+    case NETLINK_AUDIT:
+        cp = "AUDIT";
+        break;
+#endif /* defined(NETLINK_AUDIT) */
+
+#if defined(NETLINK_FIB_LOOKUP)
+    case NETLINK_FIB_LOOKUP:
+        cp = "FIB_LOOKUP";
+        break;
+#endif /* defined(NETLINK_FIB_LOOKUP) */
+
+#if defined(NETLINK_CONNECTOR)
+    case NETLINK_CONNECTOR:
+        cp = "CONNECTOR";
+        break;
+#endif /* defined(NETLINK_CONNECTOR) */
+
+#if defined(NETLINK_NETFILTER)
+    case NETLINK_NETFILTER:
+        cp = "NETFILTER";
+        break;
+#endif /* defined(NETLINK_NETFILTER) */
+
+#if defined(NETLINK_IP6_FW)
+    case NETLINK_IP6_FW:
+        cp = "IP6_FW";
+        break;
+#endif /* defined(NETLINK_IP6_FW) */
+
+#if defined(NETLINK_DNRTMSG)
+    case NETLINK_DNRTMSG:
+        cp = "DNRTMSG";
+        break;
+#endif /* defined(NETLINK_DNRTMSG) */
+
+#if defined(NETLINK_KOBJECT_UEVENT)
+    case NETLINK_KOBJECT_UEVENT:
+        cp = "KOBJECT_UEVENT";
+        break;
+#endif /* defined(NETLINK_KOBJECT_UEVENT) */
+
+#if defined(NETLINK_GENERIC)
+    case NETLINK_GENERIC:
+        cp = "GENERIC";
+        break;
+#endif /* defined(NETLINK_GENERIC) */
+
+#if defined(NETLINK_SCSITRANSPORT)
+    case NETLINK_SCSITRANSPORT:
+        cp = "SCSITRANSPORT";
+        break;
+#endif /* defined(NETLINK_SCSITRANSPORT) */
+
+#if defined(NETLINK_ECRYPTFS)
+    case NETLINK_ECRYPTFS:
+        cp = "ECRYPTFS";
+        break;
+#endif /* defined(NETLINK_ECRYPTFS) */
+
+#if defined(NETLINK_RDMA)
+    case NETLINK_RDMA:
+        cp = "RDMA";
+        break;
+#endif /* defined(NETLINK_RDMA) */
+
+#if defined(NETLINK_CRYPTO)
+    case NETLINK_CRYPTO:
+        cp = "CRYPTO";
+        break;
+#endif /* defined(NETLINK_CRYPTO) */
+
+#if defined(NETLINK_SMC)
+    case NETLINK_SMC:
+        cp = "SMC";
+        break;
+#endif /* defined(NETLINK_SMC) */
+    }
+
+    return cp;
+}
+
+/*
+ * ethernet_proto_to_str() -- convert ethernet protocol number to a string
+ *
+ * The string should not exceed 7 characters.
+ *
+ * return NULL if the number is unknown.
+ */
+static char *ethernet_proto_to_str(unsigned int pr) {
+    char *cp = NULL;
+    switch (pr) {
+#if defined(ETH_P_LOOP)
+    case ETH_P_LOOP:
+        cp = "LOOP";
+        break;
+#endif /* defined(ETH_P_LOOP) */
+
+#if defined(ETH_P_PUP)
+    case ETH_P_PUP:
+        cp = "PUP";
+        break;
+#endif /* defined(ETH_P_PUP) */
+
+#if defined(ETH_P_PUPAT)
+    case ETH_P_PUPAT:
+        cp = "PUPAT";
+        break;
+#endif /* defined(ETH_P_PUPAT) */
+
+#if defined(ETH_P_TSN)
+    case ETH_P_TSN:
+        cp = "TSN";
+        break;
+#endif /* defined(ETH_P_TSN) */
+
+#if defined(ETH_P_ERSPAN2)
+    case ETH_P_ERSPAN2:
+        cp = "ERSPAN2";
+        break;
+#endif /* defined(ETH_P_ERSPAN2) */
+
+#if defined(ETH_P_IP)
+    case ETH_P_IP:
+        cp = "IP";
+        break;
+#endif /* defined(ETH_P_IP) */
+
+#if defined(ETH_P_X25)
+    case ETH_P_X25:
+        cp = "X25";
+        break;
+#endif /* defined(ETH_P_X25) */
+
+#if defined(ETH_P_ARP)
+    case ETH_P_ARP:
+        cp = "ARP";
+        break;
+#endif /* defined(ETH_P_ARP) */
+
+#if defined(ETH_P_BPQ)
+    case ETH_P_BPQ:
+        cp = "BPQ";
+        break;
+#endif /* defined(ETH_P_BPQ) */
+
+#if defined(ETH_P_IEEEPUP)
+    case ETH_P_IEEEPUP:
+        cp = "I3EPUP";
+        break;
+#endif /* defined(ETH_P_IEEEPUP) */
+
+#if defined(ETH_P_IEEEPUPAT)
+    case ETH_P_IEEEPUPAT:
+        cp = "I3EPUPA";
+        break;
+#endif /* defined(ETH_P_IEEEPUPAT) */
+
+#if defined(ETH_P_BATMAN)
+    case ETH_P_BATMAN:
+        cp = "BATMAN";
+        break;
+#endif /* defined(ETH_P_BATMAN) */
+
+#if defined(ETH_P_DEC)
+    case ETH_P_DEC:
+        cp = "DEC";
+        break;
+#endif /* defined(ETH_P_DEC) */
+
+#if defined(ETH_P_DNA_DL)
+    case ETH_P_DNA_DL:
+        cp = "DNA_DL";
+        break;
+#endif /* defined(ETH_P_DNA_DL) */
+
+#if defined(ETH_P_DNA_RC)
+    case ETH_P_DNA_RC:
+        cp = "DNA_RC";
+        break;
+#endif /* defined(ETH_P_DNA_RC) */
+
+#if defined(ETH_P_DNA_RT)
+    case ETH_P_DNA_RT:
+        cp = "DNA_RT";
+        break;
+#endif /* defined(ETH_P_DNA_RT) */
+
+#if defined(ETH_P_LAT)
+    case ETH_P_LAT:
+        cp = "LAT";
+        break;
+#endif /* defined(ETH_P_LAT) */
+
+#if defined(ETH_P_DIAG)
+    case ETH_P_DIAG:
+        cp = "DIAG";
+        break;
+#endif /* defined(ETH_P_DIAG) */
+
+#if defined(ETH_P_CUST)
+    case ETH_P_CUST:
+        cp = "CUST";
+        break;
+#endif /* defined(ETH_P_CUST) */
+
+#if defined(ETH_P_SCA)
+    case ETH_P_SCA:
+        cp = "SCA";
+        break;
+#endif /* defined(ETH_P_SCA) */
+
+#if defined(ETH_P_TEB)
+    case ETH_P_TEB:
+        cp = "TEB";
+        break;
+#endif /* defined(ETH_P_TEB) */
+
+#if defined(ETH_P_RARP)
+    case ETH_P_RARP:
+        cp = "RARP";
+        break;
+#endif /* defined(ETH_P_RARP) */
+
+#if defined(ETH_P_ATALK)
+    case ETH_P_ATALK:
+        cp = "ATALK";
+        break;
+#endif /* defined(ETH_P_ATALK) */
+
+#if defined(ETH_P_AARP)
+    case ETH_P_AARP:
+        cp = "AARP";
+        break;
+#endif /* defined(ETH_P_AARP) */
+
+#if defined(ETH_P_8021Q)
+    case ETH_P_8021Q:
+        cp = "8021Q";
+        break;
+#endif /* defined(ETH_P_8021Q) */
+
+#if defined(ETH_P_ERSPAN)
+    case ETH_P_ERSPAN:
+        cp = "ERSPAN";
+        break;
+#endif /* defined(ETH_P_ERSPAN) */
+
+#if defined(ETH_P_IPX)
+    case ETH_P_IPX:
+        cp = "IPX";
+        break;
+#endif /* defined(ETH_P_IPX) */
+
+#if defined(ETH_P_IPV6)
+    case ETH_P_IPV6:
+        cp = "IPV6";
+        break;
+#endif /* defined(ETH_P_IPV6) */
+
+#if defined(ETH_P_PAUSE)
+    case ETH_P_PAUSE:
+        cp = "PAUSE";
+        break;
+#endif /* defined(ETH_P_PAUSE) */
+
+#if defined(ETH_P_SLOW)
+    case ETH_P_SLOW:
+        cp = "SLOW";
+        break;
+#endif /* defined(ETH_P_SLOW) */
+
+#if defined(ETH_P_WCCP)
+    case ETH_P_WCCP:
+        cp = "WCCP";
+        break;
+#endif /* defined(ETH_P_WCCP) */
+
+#if defined(ETH_P_MPLS_UC)
+    case ETH_P_MPLS_UC:
+        cp = "MPLS_UC";
+        break;
+#endif /* defined(ETH_P_MPLS_UC) */
+
+#if defined(ETH_P_MPLS_MC)
+    case ETH_P_MPLS_MC:
+        cp = "MPLS_MC";
+        break;
+#endif /* defined(ETH_P_MPLS_MC) */
+
+#if defined(ETH_P_ATMMPOA)
+    case ETH_P_ATMMPOA:
+        cp = "ATMMPOA";
+        break;
+#endif /* defined(ETH_P_ATMMPOA) */
+
+#if defined(ETH_P_PPP_DISC)
+    case ETH_P_PPP_DISC:
+        cp = "PPP_DIS";
+        break;
+#endif /* defined(ETH_P_PPP_DISC) */
+
+#if defined(ETH_P_PPP_SES)
+    case ETH_P_PPP_SES:
+        cp = "PPP_SES";
+        break;
+#endif /* defined(ETH_P_PPP_SES) */
+
+#if defined(ETH_P_LINK_CTL)
+    case ETH_P_LINK_CTL:
+        cp = "LINKCTL";
+        break;
+#endif /* defined(ETH_P_LINK_CTL) */
+
+#if defined(ETH_P_ATMFATE)
+    case ETH_P_ATMFATE:
+        cp = "ATMFATE";
+        break;
+#endif /* defined(ETH_P_ATMFATE) */
+
+#if defined(ETH_P_PAE)
+    case ETH_P_PAE:
+        cp = "PAE";
+        break;
+#endif /* defined(ETH_P_PAE) */
+
+#if defined(ETH_P_AOE)
+    case ETH_P_AOE:
+        cp = "AOE";
+        break;
+#endif /* defined(ETH_P_AOE) */
+
+#if defined(ETH_P_8021AD)
+    case ETH_P_8021AD:
+        cp = "8021AD";
+        break;
+#endif /* defined(ETH_P_8021AD) */
+
+#if defined(ETH_P_802_EX1)
+    case ETH_P_802_EX1:
+        cp = "802_EX1";
+        break;
+#endif /* defined(ETH_P_802_EX1) */
+
+#if defined(ETH_P_PREAUTH)
+    case ETH_P_PREAUTH:
+        cp = "PREAUTH";
+        break;
+#endif /* defined(ETH_P_PREAUTH) */
+
+#if defined(ETH_P_TIPC)
+    case ETH_P_TIPC:
+        cp = "TIPC";
+        break;
+#endif /* defined(ETH_P_TIPC) */
+
+#if defined(ETH_P_LLDP)
+    case ETH_P_LLDP:
+        cp = "LLDP";
+        break;
+#endif /* defined(ETH_P_LLDP) */
+
+#if defined(ETH_P_MRP)
+    case ETH_P_MRP:
+        cp = "MRP";
+        break;
+#endif /* defined(ETH_P_MRP) */
+
+#if defined(ETH_P_MACSEC)
+    case ETH_P_MACSEC:
+        cp = "MACSEC";
+        break;
+#endif /* defined(ETH_P_MACSEC) */
+
+#if defined(ETH_P_8021AH)
+    case ETH_P_8021AH:
+        cp = "8021AH";
+        break;
+#endif /* defined(ETH_P_8021AH) */
+
+#if defined(ETH_P_MVRP)
+    case ETH_P_MVRP:
+        cp = "MVRP";
+        break;
+#endif /* defined(ETH_P_MVRP) */
+
+#if defined(ETH_P_1588)
+    case ETH_P_1588:
+        cp = "1588";
+        break;
+#endif /* defined(ETH_P_1588) */
+
+#if defined(ETH_P_NCSI)
+    case ETH_P_NCSI:
+        cp = "NCSI";
+        break;
+#endif /* defined(ETH_P_NCSI) */
+
+#if defined(ETH_P_PRP)
+    case ETH_P_PRP:
+        cp = "PRP";
+        break;
+#endif /* defined(ETH_P_PRP) */
+
+#if defined(ETH_P_FCOE)
+    case ETH_P_FCOE:
+        cp = "FCOE";
+        break;
+#endif /* defined(ETH_P_FCOE) */
+
+#if defined(ETH_P_IBOE)
+    case ETH_P_IBOE:
+        cp = "IBOE";
+        break;
+#endif /* defined(ETH_P_IBOE) */
+
+#if defined(ETH_P_TDLS)
+    case ETH_P_TDLS:
+        cp = "TDLS";
+        break;
+#endif /* defined(ETH_P_TDLS) */
+
+#if defined(ETH_P_FIP)
+    case ETH_P_FIP:
+        cp = "FIP";
+        break;
+#endif /* defined(ETH_P_FIP) */
+
+#if defined(ETH_P_80221)
+    case ETH_P_80221:
+        cp = "802.21";
+        break;
+#endif /* defined(ETH_P_80221) */
+
+#if defined(ETH_P_HSR)
+    case ETH_P_HSR:
+        cp = "HSR";
+        break;
+#endif /* defined(ETH_P_HSR) */
+
+#if defined(ETH_P_NSH)
+    case ETH_P_NSH:
+        cp = "NSH";
+        break;
+#endif /* defined(ETH_P_NSH) */
+
+#if defined(ETH_P_LOOPBACK)
+    case ETH_P_LOOPBACK:
+        cp = "LOOPBACK";
+        break;
+#endif /* defined(ETH_P_LOOPBACK) */
+
+#if defined(ETH_P_QINQ1)
+    case ETH_P_QINQ1:
+        cp = "QINQ1";
+        break;
+#endif /* defined(ETH_P_QINQ1) */
+
+#if defined(ETH_P_QINQ2)
+    case ETH_P_QINQ2:
+        cp = "QINQ2";
+        break;
+#endif /* defined(ETH_P_QINQ2) */
+
+#if defined(ETH_P_QINQ3)
+    case ETH_P_QINQ3:
+        cp = "QINQ3";
+        break;
+#endif /* defined(ETH_P_QINQ3) */
+
+#if defined(ETH_P_EDSA)
+    case ETH_P_EDSA:
+        cp = "EDSA";
+        break;
+#endif /* defined(ETH_P_EDSA) */
+
+#if defined(ETH_P_DSA_8021Q)
+    case ETH_P_DSA_8021Q:
+        cp = "DSAD1Q";
+        break;
+#endif /* defined(ETH_P_DSA_8021Q) */
+
+#if defined(ETH_P_IFE)
+    case ETH_P_IFE:
+        cp = "IFE";
+        break;
+#endif /* defined(ETH_P_IFE) */
+
+#if defined(ETH_P_AF_IUCV)
+    case ETH_P_AF_IUCV:
+        cp = "AF_IUCV";
+        break;
+#endif /* defined(ETH_P_AF_IUCV) */
+
+#if defined(ETH_P_802_3)
+    case ETH_P_802_3:
+        cp = "802.3";
+        break;
+#endif /* defined(ETH_P_802_3) */
+
+#if defined(ETH_P_AX25)
+    case ETH_P_AX25:
+        cp = "AX25";
+        break;
+#endif /* defined(ETH_P_AX25) */
+
+#if defined(ETH_P_ALL)
+    case ETH_P_ALL:
+        cp = "ALL";
+        break;
+#endif /* defined(ETH_P_ALL) */
+
+#if defined(ETH_P_802_2)
+    case ETH_P_802_2:
+        cp = "802.2";
+        break;
+#endif /* defined(ETH_P_802_2) */
+
+#if defined(ETH_P_SNAP)
+    case ETH_P_SNAP:
+        cp = "SNAP";
+        break;
+#endif /* defined(ETH_P_SNAP) */
+
+#if defined(ETH_P_DDCMP)
+    case ETH_P_DDCMP:
+        cp = "DDCMP";
+        break;
+#endif /* defined(ETH_P_DDCMP) */
+
+#if defined(ETH_P_WAN_PPP)
+    case ETH_P_WAN_PPP:
+        cp = "WAN_PPP";
+        break;
+#endif /* defined(ETH_P_WAN_PPP) */
+
+#if defined(ETH_P_PPP_MP)
+    case ETH_P_PPP_MP:
+        cp = "PPP MP";
+        break;
+#endif /* defined(ETH_P_PPP_MP) */
+
+#if defined(ETH_P_LOCALTALK)
+    case ETH_P_LOCALTALK:
+        cp = "LCLTALK";
+        break;
+#endif /* defined(ETH_P_LOCALTALK) */
+
+#if defined(ETH_P_CAN)
+    case ETH_P_CAN:
+        cp = "CAN";
+        break;
+#endif /* defined(ETH_P_CAN) */
+
+#if defined(ETH_P_CANFD)
+    case ETH_P_CANFD:
+        cp = "CANFD";
+        break;
+#endif /* defined(ETH_P_CANFD) */
+
+#if defined(ETH_P_PPPTALK)
+    case ETH_P_PPPTALK:
+        cp = "PPPTALK";
+        break;
+#endif /* defined(ETH_P_PPPTALK) */
+
+#if defined(ETH_P_TR_802_2)
+    case ETH_P_TR_802_2:
+        cp = "802.2";
+        break;
+#endif /* defined(ETH_P_TR_802_2) */
+
+#if defined(ETH_P_MOBITEX)
+    case ETH_P_MOBITEX:
+        cp = "MOBITEX";
+        break;
+#endif /* defined(ETH_P_MOBITEX) */
+
+#if defined(ETH_P_CONTROL)
+    case ETH_P_CONTROL:
+        cp = "CONTROL";
+        break;
+#endif /* defined(ETH_P_CONTROL) */
+
+#if defined(ETH_P_IRDA)
+    case ETH_P_IRDA:
+        cp = "IRDA";
+        break;
+#endif /* defined(ETH_P_IRDA) */
+
+#if defined(ETH_P_ECONET)
+    case ETH_P_ECONET:
+        cp = "ECONET";
+        break;
+#endif /* defined(ETH_P_ECONET) */
+
+#if defined(ETH_P_HDLC)
+    case ETH_P_HDLC:
+        cp = "HDLC";
+        break;
+#endif /* defined(ETH_P_HDLC) */
+
+#if defined(ETH_P_ARCNET)
+    case ETH_P_ARCNET:
+        cp = "ARCNET";
+        break;
+#endif /* defined(ETH_P_ARCNET) */
+
+#if defined(ETH_P_DSA)
+    case ETH_P_DSA:
+        cp = "DSA";
+        break;
+#endif /* defined(ETH_P_DSA) */
+
+#if defined(ETH_P_TRAILER)
+    case ETH_P_TRAILER:
+        cp = "TRAILER";
+        break;
+#endif /* defined(ETH_P_TRAILER) */
+
+#if defined(ETH_P_PHONET)
+    case ETH_P_PHONET:
+        cp = "PHONET";
+        break;
+#endif /* defined(ETH_P_PHONET) */
+
+#if defined(ETH_P_IEEE802154)
+    case ETH_P_IEEE802154:
+        cp = "802154";
+        break;
+#endif /* defined(ETH_P_IEEE802154) */
+
+#if defined(ETH_P_CAIF)
+    case ETH_P_CAIF:
+        cp = "CAIF";
+        break;
+#endif /* defined(ETH_P_CAIF) */
+
+#if defined(ETH_P_XDSA)
+    case ETH_P_XDSA:
+        cp = "XDSA";
+        break;
+#endif /* defined(ETH_P_XDSA) */
+
+#if defined(ETH_P_MAP)
+    case ETH_P_MAP:
+        cp = "MAP";
+        break;
+#endif /* defined(ETH_P_MAP) */
+
+    default:
+        cp = NULL;
+        break;
+    }
+    return cp;
+}
diff --git a/lib/dialects/linux/dstore.c b/lib/dialects/linux/dstore.c
new file mode 100644
index 0000000..9cea7d4
--- /dev/null
+++ b/lib/dialects/linux/dstore.c
@@ -0,0 +1,117 @@
+/*
+ * dstore.c - Linux global storage for /proc-based lsof
+ */
+
+/*
+ * 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.
+ */
+
+#include "common.h"
+
+int HasNFS = 0;       /* NFS mount point status:
+                       *     1 == there is an NFS mount point,
+                       *          but its device number is
+                       *          unknown
+                       *     2 == there is an NFS mount point
+                       *          and its device number is
+                       *          known
+                       */
+dev_t MqueueDev = -1; /* The number for the device behind
+                       * mqueue mount point */
+/* offset type:
+ *     0 == unknown
+ *     1 == lstat's st_size
+ *     2 == from /proc/<PID>/fdinfo
+ */
+int OffType = OFFSET_UNKNOWN;
+
+/*
+ * Pff_tab[] - table for printing file flags
+ */
+
+struct pff_tab Pff_tab[] = {{(long)O_WRONLY, FF_WRITE},
+                            {(long)O_RDWR, FF_RDWR},
+                            {(long)O_CREAT, FF_CREAT},
+                            {(long)O_EXCL, FF_EXCL},
+                            {(long)O_NOCTTY, FF_NOCTTY},
+                            {(long)O_TRUNC, FF_TRUNC},
+                            {(long)O_APPEND, FF_APPEND},
+                            {(long)O_NDELAY, FF_NDELAY},
+                            {(long)O_SYNC, FF_SYNC},
+                            {(long)O_ASYNC, FF_ASYNC},
+
+#if defined(O_DIRECT)
+                            {(long)O_DIRECT, FF_DIRECT},
+#endif /* defined(O_DIRECT) */
+
+#if defined(O_DIRECTORY)
+                            {(long)O_DIRECTORY, FF_DIRECTORY},
+#endif /* defined(O_DIRECTORY) */
+
+#if defined(O_NOFOLLOW)
+                            {(long)O_NOFOLLOW, FF_NOFOLNK},
+#endif /* defined(O_NOFOLLOW) */
+
+#if defined(O_NOATIME)
+                            {(long)O_NOATIME, FF_NOATM},
+#endif /* defined(O_NOATIME) */
+
+#if defined(O_DSYNC)
+                            {(long)O_DSYNC, FF_DSYNC},
+#endif /* defined(O_DSYNC) */
+
+#if defined(O_RSYNC)
+                            {(long)O_RSYNC, FF_RSYNC},
+#endif /* defined(O_RSYNC) */
+
+#if defined(O_LARGEFILE)
+#    if O_LARGEFILE == 0
+                            {(long)0100000, FF_LARGEFILE},
+#    else  /* O_LARGEFILE!=0 */
+                            {(long)O_LARGEFILE, FF_LARGEFILE},
+#    endif /* O_LARGEFILE==0 */
+#else      /* !defined(O_LARGEFILE) */
+                            {(long)0100000, FF_LARGEFILE},
+#endif     /* defined(O_LARGEFILE) */
+
+#if defined(O_CLOEXEC)
+                            {(long)O_CLOEXEC, POF_CLOEXEC},
+#endif /* defined(O_CLOEXEC) */
+
+#if defined(O_PATH)
+                            {(long)O_PATH, FF_PATH},
+#endif /* defined(O_PATH) */
+
+#if defined(O_TMPFILE)
+                            {(long)O_TMPFILE, FF_TMPFILE},
+#endif /* defined(O_TMPFILE) */
+
+                            {(long)0, NULL}};
+
+/*
+ * Pof_tab[] - table for print process open file flags
+ */
+
+struct pff_tab Pof_tab[] = {{(long)0, NULL}};
diff --git a/dialects/linux/machine.h b/lib/dialects/linux/machine.h
similarity index 92%
rename from dialects/linux/machine.h
rename to lib/dialects/linux/machine.h
index f4eab35..469f3d5 100644
--- a/dialects/linux/machine.h
+++ b/lib/dialects/linux/machine.h
@@ -2,7 +2,6 @@
  * machine.h - Linux definitions for /proc-based lsof
  */
 
-
 /*
  * Copyright 1997 Purdue Research Foundation, West Lafayette, Indiana
  * 47907.  All rights reserved.
@@ -29,35 +28,29 @@
  * 4. This notice may not be removed or altered.
  */
 
-
 /*
  * $Id: machine.h,v 1.37 2014/10/13 22:25:58 abe Exp $
  */
 
+#if !defined(LSOF_MACHINE_H)
+#    define LSOF_MACHINE_H 1
 
-#if	!defined(LSOF_MACHINE_H)
-#define	LSOF_MACHINE_H	1
-
-
-#include <sys/types.h>
-#include <sys/param.h>
-
+#    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
-
+#    define CAN_USE_CLNT_CREATE 1
 
 /*
  * DEVDEV_PATH defines the path to the directory that contains device
  * nodes.
  */
 
-#define	DEVDEV_PATH	"/dev"
-
+#    define DEVDEV_PATH "/dev"
 
 /*
  * GET_MAX_FD is defined for those dialects that provide a function other than
@@ -66,7 +59,6 @@
 
 /* #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
@@ -75,7 +67,6 @@
 
 /* #define	HASAOPT		1 */
 
-
 /*
  * HASBLKDEV is defined for those dialects that want block device information
  * recorded in BDevtp[].
@@ -83,7 +74,6 @@
 
 /* #define	HASBLKDEV	1 */
 
-
 /*
  * HASDCACHE is defined for those dialects that support a device cache
  * file.
@@ -125,27 +115,23 @@
 /* #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 */
 
-
 /*
  * HASEOPT is defined for dialects that support the -e option
  */
 
-#define	HASEOPT	1
-
+#    define HASEOPT 1
 
 /*
  * HASFSINO is defined for those dialects that have the file system
@@ -154,7 +140,6 @@
 
 /* #define	HASFSINO	1 */
 
-
 /*
  * HASFSTRUCT is defined if the dialect has a file structure.
  *
@@ -168,13 +153,12 @@
  *   HASNOFSNADDR -- has no file structure node address
  */
 
-#define	HASFSTRUCT	1
+#    define HASFSTRUCT 1
 /* #define	FSV_DEFAULT	FSV_? | FSV_? | FSV_? */
-#define	HASNOFSADDR	1	/* has no file structure address */
+#    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 */
-
+#    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.
@@ -182,14 +166,12 @@
 
 /* #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.
@@ -197,7 +179,6 @@
 
 /* #define	HASINODE	1 */
 
-
 /*
  * HASINTSIGNAL is defined for those dialects whose signal function returns
  * an int.
@@ -205,7 +186,6 @@
 
 /* #define	HASINTSIGNAL	1 */
 
-
 /*
  * HASKERNIDCK is defined for those dialects that support the comparison of
  * the build to running kernel identity.
@@ -213,7 +193,6 @@
 
 /* #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.
@@ -221,7 +200,6 @@
 
 /* #define	HASKOPT	1 */
 
-
 /*
  * HASLFILEADD is defined for those dialects that need additional elements
  * in struct lfile.  The HASLFILEADD definition is a macro that defines
@@ -244,13 +222,11 @@
 /* #define CLRLFILEADD(lf)	(lf)->... = (type)NULL;	*/
 /* #define SETLFILEADD Lf->... */
 
-
 /*
  * HASLWP is defined for dialects that have LWP support inside processes.
  */
 
-#define	HASLWP	1
-
+#    define HASLWP 1
 
 /*
  * HASMNTSTAT indicates the dialect supports the mount stat(2) result option
@@ -259,14 +235,12 @@
 
 /* #define	HASMNTSTAT	1	*/
 
-
 /*
  * HASMNTSUP is defined for those dialects that support the mount supplement
  * option.
  */
 
-#define	HASMNTSUP	1
-
+#    define HASMNTSUP 1
 
 /*
  * HASMOPT is defined for those dialects that support the reading of
@@ -275,7 +249,6 @@
 
 /* #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
@@ -290,15 +263,13 @@
 /* #define	NCACHELDPFX	??? */
 /* #define	NCACHELDSFX	??? */
 
-
 /*
- * HASNLIST is defined for those dialects that use nlist() to acccess
+ * HASNLIST is defined for those dialects that use nlist() to access
  * 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
@@ -309,20 +280,17 @@
 
 /* #define	HASPIPEFN	process_pipe? */
 
-
 /*
  * HASPIPENODE is defined for those dialects that have pipe nodes.
  */
 
 /* #define	HASPIPENODE	1 */
 
-
 /*
  * HASEPTOPTS is defined for dialects that support the +|-E options.
  */
 
-#define		HASEPTOPTS	1
-
+#    define HASEPTOPTS 1
 
 /*
  * HASPMAPENABLED is defined when the reporting of portmapper registration
@@ -331,14 +299,12 @@
 
 /* #define	HASPMAPENABLED	1 */
 
-
 /*
  * HASPPID is defined for those dialects that support identification of
  * the parent process IDentifier (PPID) of a process.
  */
 
-#define	HASPPID		1
-
+#    define HASPPID 1
 
 /*
  * HASPRINTDEV, HASPRINTINO, HASPRINTNM, HASPRINTOFF, and HASPRINTSZ
@@ -350,9 +316,6 @@
 /* #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
@@ -367,7 +330,6 @@
 /* #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
@@ -379,7 +341,6 @@
 
 /* #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
@@ -388,7 +349,6 @@
 
 /* #define	HASPRIVPRIPP	1	*/
 
-
 /*
  * HASPROCFS is defined for those dialects that have a proc file system --
  * usually /proc and usually in SYSV4 derivatives.
@@ -417,14 +377,12 @@
 /* #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
@@ -434,7 +392,6 @@
 
 /* #define	HASSECURITY	1 */
 
-
 /*
  * If HASSECURITY is defined, define HASNOSOCKSECURITY to allow users
  * restricted by HASSECURITY to list any open socket files, provide their
@@ -443,7 +400,6 @@
 
 /* #define	HASNOSOCKSECURITY	1	*/
 
-
 /*
  * HASSETLOCALE is defined for those dialects that have <locale.h> and
  * setlocale().
@@ -454,10 +410,9 @@
  * mblen() and mbtowc() functions.
  */
 
-#define	HASSETLOCALE	1
-#define	HASWIDECHAR	1
-#define	WIDECHARINCL	<wctype.h>
-
+#    define HASSETLOCALE 1
+#    define HASWIDECHAR 1
+#    define WIDECHARINCL <wctype.h>
 
 /*
  * HASSNODE is defined for those dialects that have snodes.
@@ -465,7 +420,6 @@
 
 /* #define	HASSNODE	1 */
 
-
 /*
  * HASSOOPT, HASSOSTATE and HASTCPOPT define the availability of information
  * on socket options (SO_* symbols), socket states (SS_* symbols) and TCP
@@ -476,7 +430,6 @@
 /* #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.
@@ -494,28 +447,24 @@
 
 /* #define	HASSPECDEVD	process_dev_stat */
 
-
 /*
  * HASSTREAMS is defined for those dialects that support streams.
  */
 
 /* #define	HASSTREAMS	1 */
 
-
 /*
  * HASTASKS is defined for those dialects that have task reporting support.
  */
 
-#define	HASTASKS	1
-
+#    define HASTASKS 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
-
+#    define HASTCPTPIQ 1
 
 /*
  * HASTCPTPIW is defined for dialects where it is possible to report the
@@ -524,15 +473,13 @@
 
 /* #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
-
+#    define HASTCPUDPSTATE 1
 
 /*
  * HASTMPNODE is defined for those dialects that have tmpnodes.
@@ -540,7 +487,6 @@
 
 /* #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
@@ -550,16 +496,14 @@
 
 /* #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		"skip TCP&UDP* files"
-#define	HASXOPT_VALUE	0
-
+#    define HASXOPT "skip TCP&UDP* files"
+#    define HASXOPT_VALUE 0
 
 /*
  * INODETYPE and INODEPSPEC define the internal node number type and its
@@ -569,19 +513,18 @@
  * 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 */
-
+#    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	u_int
-
+#    define UID_ARG u_int
 
 /*
  * Each USE_LIB_<function_name> is defined for dialects that use the
@@ -602,20 +545,18 @@
 /* #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() */
-
+#    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.
  *
- * CAUTION!!!  Don't enable the WARNDEVACCESS definiton for /proc-based Linux
+ * CAUTION!!!  Don't enable the WARNDEVACCESS definition for /proc-based Linux
  *	       lsof; it doesn't process /dev at all.
  *
  * The presence of NEVER_WARNDEVACCESS in this comment prevents the Customize
@@ -624,7 +565,6 @@
 
 /* #define	WARNDEVACCESS	1  DON'T ENABLE!!! -- see above comment */
 
-
 /*
  * WARNINGSTATE is defined for those dialects that want to suppress all lsof
  * warning messages.
@@ -632,7 +572,6 @@
 
 /* #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
@@ -641,11 +580,10 @@
 
 /* #define	WILLDROPGID	1 */
 
-
 /*
  * zeromem is a macro that uses bzero or memset.
  */
 
-#define	zeromem(a, l)	memset(a, 0, l)
+#    define zeromem(a, l) memset(a, 0, l)
 
-#endif	/* !defined(LSOF_MACHINE_H) */
+#endif /* !defined(LSOF_MACHINE_H) */
diff --git a/dialects/linux/tests/Makefile b/lib/dialects/linux/tests/Makefile
similarity index 98%
rename from dialects/linux/tests/Makefile
rename to lib/dialects/linux/tests/Makefile
index a744f8f..1532cbe 100644
--- a/dialects/linux/tests/Makefile
+++ b/lib/dialects/linux/tests/Makefile
@@ -7,6 +7,7 @@ HELPERS = \
 	pipe \
 	pty \
 	ux \
+	mmap \
 	\
 	open_with_flags \
 	\
diff --git a/dialects/linux/tests/case-00-linux-hello.bash b/lib/dialects/linux/tests/case-00-linux-hello.bash
similarity index 100%
rename from dialects/linux/tests/case-00-linux-hello.bash
rename to lib/dialects/linux/tests/case-00-linux-hello.bash
diff --git a/dialects/linux/tests/case-10-mqueue.bash b/lib/dialects/linux/tests/case-10-mqueue.bash
similarity index 83%
rename from dialects/linux/tests/case-10-mqueue.bash
rename to lib/dialects/linux/tests/case-10-mqueue.bash
index cd52ca1..b3212b5 100755
--- a/dialects/linux/tests/case-10-mqueue.bash
+++ b/lib/dialects/linux/tests/case-10-mqueue.bash
@@ -1,13 +1,9 @@
-#!/bin/sh
-
-name=$(basename $0 .sh)
-lsof=$1
-report=$2
-tdir=$3
+#!/bin/bash
+source tests/common.bash
 
 MQUEUE_MNTPOINT=/tmp/$$
 
-TARGET=$tdir/mq_open
+TARGET=$tcasedir/mq_open
 if ! [ -x $TARGET ]; then
     echo "target executable ( $TARGET ) is not found" >> $report
     exit 1
@@ -16,13 +12,13 @@ fi
 if grep -q mqueue /proc/mounts; then
     :
 elif ! [ $(id -u) = 0 ]; then
-    echo "root privileged is needed to run $(basename $0. sh)" >> $report
-    exit 2
+    echo "root privileged is needed to run $(basename $0 .sh), skipping" >> $report
+    exit 77
 else
     mkdir -p ${MQUEUE_MNTPOINT}
     if ! mount -t mqueue none ${MQUEUE_MNTPOINT}; then
-	echo "failed to mount mqeueu file system"
-	exit 2
+	echo "failed to mount mqeueu file system, skipping"
+	exit 77
     fi
 fi
 
diff --git a/dialects/linux/tests/case-10-ux-socket-state.bash b/lib/dialects/linux/tests/case-10-ux-socket-state.bash
similarity index 88%
rename from dialects/linux/tests/case-10-ux-socket-state.bash
rename to lib/dialects/linux/tests/case-10-ux-socket-state.bash
index 2c080d6..d47e53a 100755
--- a/dialects/linux/tests/case-10-ux-socket-state.bash
+++ b/lib/dialects/linux/tests/case-10-ux-socket-state.bash
@@ -1,12 +1,14 @@
 #!/bin/bash
+source tests/common.bash
 
-name=$(basename $0 .bash)
-lsof=$1
-report=$2
+if ! [ -r "/proc/self/stack" ]; then
+    echo "this platform doesn't allow to access /proc/\$PID/stack, skipping" >> $report
+    exit 77
+fi
 
-if ! [ -r "/proc/$self/stack" ]; then
-    echo "this platform doesn't allow to access /proc/\$PID/stack" >> $report
-    exit 2
+if [ -z "$(nc -h 2>&1 | grep '\-U')" ]; then
+    echo "nc does not support unix socket, skipping" >> $report
+    exit 77
 fi
 
 ux=/tmp/$name-$$.sock
diff --git a/dialects/linux/tests/case-20-epoll.bash b/lib/dialects/linux/tests/case-20-epoll.bash
similarity index 74%
rename from dialects/linux/tests/case-20-epoll.bash
rename to lib/dialects/linux/tests/case-20-epoll.bash
index 873c71a..770a1d7 100755
--- a/dialects/linux/tests/case-20-epoll.bash
+++ b/lib/dialects/linux/tests/case-20-epoll.bash
@@ -1,18 +1,15 @@
 #!/bin/bash
+source tests/common.bash
 
-lsof=$1
-report=$2
-tdir=$3
-
-TARGET=$tdir/epoll
+TARGET=$tcasedir/epoll
 if ! [ -x $TARGET ]; then
     echo "target executable ( $TARGET ) is not found" >> $report
     exit 1
 fi
 
 $TARGET 2>> $report | {
-    read pid epfd
-    if [[ -z "$pid" || -z "$epfd" ]]; then
+    read pid epfd evfd0 evfd1
+    if [[ -z "$pid" || -z "$epfd" || -z "$evfd0" || -z "$evfd1" ]]; then
 	echo "unexpected output form target ( $TARGET )" >> $report
 	exit 1
     fi
@@ -28,7 +25,7 @@ $TARGET 2>> $report | {
 	echo done
     } >> $report
     if $lsof -p $pid -a -d $epfd |
-	    grep -q "epoll *[0-9]* *.* *${epfd}u *a_inode *[0-9]*,[0-9]* *[0-9]* *[0-9]* *\[eventpoll:5,6\]"; then
+	    grep -q "epoll *[0-9]* *.* *${epfd}u *a_inode *[0-9]*,[0-9]* *[0-9]* *[0-9]* *\[eventpoll:${evfd0},${evfd1}\]"; then
 	kill $pid
 	exit 0
     else
diff --git a/dialects/linux/tests/case-20-eventfd-endpoint.bash b/lib/dialects/linux/tests/case-20-eventfd-endpoint.bash
similarity index 93%
rename from dialects/linux/tests/case-20-eventfd-endpoint.bash
rename to lib/dialects/linux/tests/case-20-eventfd-endpoint.bash
index 44e8a7a..d7d0113 100755
--- a/dialects/linux/tests/case-20-eventfd-endpoint.bash
+++ b/lib/dialects/linux/tests/case-20-eventfd-endpoint.bash
@@ -1,18 +1,16 @@
-name=$(basename $0 .bash)
-lsof=$1
-report=$2
-tdir=$3
+#!/bin/bash
+source tests/common.bash
 
 uname -r >> $report
 uname -r | sed -ne 's/^\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\).*/\1 \2/p' | {
     read major minor
     if [ "$major" -lt 5 ]; then
-	echo "eventfd endpoint features doesn't work on Linux $major"
-	exit 2
+	echo "eventfd endpoint features doesn't work on Linux $major, skipping"
+	exit 77
     fi
     if [ "$major" -eq 5 -a "$minor" -lt 2 ]; then
-	echo "event endpoint features doesn't work on Linux $major.$minor"
-	exit 2
+	echo "event endpoint features doesn't work on Linux $major.$minor, skipping"
+	exit 77
     fi
 } >> $report
 s=$?
@@ -20,7 +18,7 @@ if ! [ $s = 0 ]; then
     exit $s
 fi
 
-TARGET=$tdir/eventfd
+TARGET=$tcasedir/eventfd
 if ! [ -x $TARGET ]; then
     echo "target executable ( $TARGET ) is not found" >> $report
     exit 1
diff --git a/dialects/linux/tests/case-20-inet-socket-endpoint.bash b/lib/dialects/linux/tests/case-20-inet-socket-endpoint.bash
similarity index 84%
rename from dialects/linux/tests/case-20-inet-socket-endpoint.bash
rename to lib/dialects/linux/tests/case-20-inet-socket-endpoint.bash
index 3763ba8..a0a652f 100755
--- a/dialects/linux/tests/case-20-inet-socket-endpoint.bash
+++ b/lib/dialects/linux/tests/case-20-inet-socket-endpoint.bash
@@ -1,8 +1,10 @@
-#!/bin/sh
+#!/bin/bash
+source tests/common.bash
 
-name=$(basename $0 .bash)
-lsof=$1
-report=$2
+if [ -z "$(nc -h 2>&1 | grep '\s\-4')" ]; then
+    echo "nc does not support -4 option, skipping" >> $report
+    exit 77
+fi
 
 nc -l -4 127.0.0.1 10000 > /dev/null < /dev/zero &
 server=$!
diff --git a/dialects/linux/tests/case-20-inet6-ffffffff-handling.bash b/lib/dialects/linux/tests/case-20-inet6-ffffffff-handling.bash
similarity index 77%
rename from dialects/linux/tests/case-20-inet6-ffffffff-handling.bash
rename to lib/dialects/linux/tests/case-20-inet6-ffffffff-handling.bash
index 887e50d..1e3f459 100755
--- a/dialects/linux/tests/case-20-inet6-ffffffff-handling.bash
+++ b/lib/dialects/linux/tests/case-20-inet6-ffffffff-handling.bash
@@ -1,16 +1,13 @@
 #!/bin/bash
-
-name=$(basename $0 .bash)
-lsof=$1
-report=$2
+source tests/common.bash
 
 if [[ $(id -u) != 0 ]]; then
     echo "root privileged is needed to run $(basename $0. sh)" >> "${report}"
-    exit 2
+    exit 77
 fi
 
 #
-# Derrived from the issue #102 opened by @zhrf2020.
+# Derived from the issue #102 opened by @zhrf2020.
 #
 
 v6addr=abcd:ef10:ffff:ffff:ffff:ffff:ffff:ff62
@@ -18,8 +15,8 @@ port=9999
 dev=lo
 
 if ! ip -6 address add "${v6addr}" dev "${dev}" 2>> "${report}"; then
-    echo "failed to add ipv6 address "${v6addr}" to ${dev}" >> "${report}"
-    exit 2
+    echo "failed to add ipv6 address "${v6addr}" to ${dev}, skipping" >> "${report}"
+    exit 77
 fi
 
 ip -6 address show >> "${report}"
@@ -33,7 +30,7 @@ expectation="n[${v6addr}]:$port"
 result=1
 if "${lsof}" -p "${pid}" -a -d fd -P -n -F n \
     | tee -a "${report}" \
-    | fgrep -q "$expectation"; then
+    | grep -Fq "$expectation"; then
     result=0
 fi
 
diff --git a/dialects/linux/tests/case-20-inet6-socket-endpoint.bash b/lib/dialects/linux/tests/case-20-inet6-socket-endpoint.bash
similarity index 86%
rename from dialects/linux/tests/case-20-inet6-socket-endpoint.bash
rename to lib/dialects/linux/tests/case-20-inet6-socket-endpoint.bash
index ec3d350..fbf5cd1 100755
--- a/dialects/linux/tests/case-20-inet6-socket-endpoint.bash
+++ b/lib/dialects/linux/tests/case-20-inet6-socket-endpoint.bash
@@ -1,8 +1,5 @@
-#!/bin/sh
-
-name=$(basename $0 .bash)
-lsof=$1
-report=$2
+#!/bin/bash
+source tests/common.bash
 
 nc -l -6 ::1 10000 > /dev/null < /dev/zero 2>> $report &
 server=$!
@@ -12,8 +9,8 @@ client=$!
 sleep 1
 
 if ! kill -0 $server 2>/dev/null; then
-    echo "Maybe ipv6 stack is not available on this system" >> $report
-    exit 2
+    echo "Maybe ipv6 stack is not available on this system, skipping" >> $report
+    exit 77
 fi
 
 sleep 1
diff --git a/lib/dialects/linux/tests/case-20-mmap.bash b/lib/dialects/linux/tests/case-20-mmap.bash
new file mode 100755
index 0000000..99a7f0c
--- /dev/null
+++ b/lib/dialects/linux/tests/case-20-mmap.bash
@@ -0,0 +1,59 @@
+#!/bin/bash
+source tests/common.bash
+
+cleanup()
+{
+    if [ -n "$(mount | grep "tmp\/ext4.img" | grep -v grep)" ]
+    then
+        umount /tmp/ext4.img
+    fi
+    
+    if [ -f /tmp/ext4.img ]
+    then
+        rm -f /tmp/ext4.img
+    fi
+    
+    if [ -d /tmp/TEST ]
+    then
+        rm -rf /tmp/TEST
+    fi
+    
+    pidlist=`ps aux | grep "TEST\/MMAP" | grep -v grep | awk '{print $2}'`
+    for pid in $pidlist
+    do
+        kill -9 $pid
+    done
+}
+
+# cleanup the environment
+cleanup
+
+# create a new namespace and mmap
+output=$(unshare --mount --propagation private $3/mount-and-mmap.bash $@ 2>&1)
+echo "$output" >> $report
+if echo "$output" | grep -q 'Operation not permitted'; then
+    echo "unshare is not supported on this platform, skipping" >> $report
+    exit 77
+fi
+
+# get pid of the mmap process
+pid=`ps aux | grep "TEST\/MMAP" | grep -v grep | awk '{print $2}'`
+if [ -z "$pid" ]
+then
+    echo "mmap process does not exist" >> $report
+    cleanup
+    exit 1
+fi
+
+# lsof -p pid and obtain the output
+output=`$lsof -p $pid | grep "TEST\/MMAP" | grep "stat: No such file or directory"`
+
+if [ -z "$output" ]
+then
+    cleanup
+    exit 0
+else
+    echo "unexpected output: $output" >> $report
+    cleanup
+    exit 1
+fi
diff --git a/dialects/linux/tests/case-20-mqueue-endpoint.bash b/lib/dialects/linux/tests/case-20-mqueue-endpoint.bash
similarity index 91%
rename from dialects/linux/tests/case-20-mqueue-endpoint.bash
rename to lib/dialects/linux/tests/case-20-mqueue-endpoint.bash
index 1a5a99e..a5613c5 100755
--- a/dialects/linux/tests/case-20-mqueue-endpoint.bash
+++ b/lib/dialects/linux/tests/case-20-mqueue-endpoint.bash
@@ -1,13 +1,9 @@
-#!/bin/sh
-
-name=$(basename $0 .bash)
-lsof=$1
-report=$2
-tdir=$3
+#!/bin/bash
+source tests/common.bash
 
 MQUEUE_MNTPOINT=/tmp/$$
 
-TARGET=$tdir/mq_fork
+TARGET=$tcasedir/mq_fork
 if ! [ -x $TARGET ]; then
     echo "target executable ( $TARGET ) is not found" >> $report
     exit 1
@@ -16,13 +12,13 @@ fi
 if grep -q mqueue /proc/mounts; then
     :
 elif ! [ $(id -u) = 0 ]; then
-    echo "root privileged is needed to run $(basename $0. sh)" >> $report
-    exit 2
+    echo "root privileged is needed to run $(basename $0 .sh), skipping" >> $report
+    exit 77
 else
     mkdir -p ${MQUEUE_MNTPOINT}
     if ! mount -t mqueue none ${MQUEUE_MNTPOINT}; then
-	echo "failed to mount mqeueu file system"
-	exit 2
+	echo "failed to mount mqueue file system, skipping"
+	exit 77
     fi
 fi
 
diff --git a/lib/dialects/linux/tests/case-20-open-flags-cx.bash b/lib/dialects/linux/tests/case-20-open-flags-cx.bash
new file mode 100755
index 0000000..26cf413
--- /dev/null
+++ b/lib/dialects/linux/tests/case-20-open-flags-cx.bash
@@ -0,0 +1,5 @@
+#!/bin/bash
+source tests/common.bash
+
+pat=".*DIR[ \t]\+.*CX.*[ \t]\+.*/tmp$"
+source $tcasedir/util-open-flags.bash "$lsof" "$report" "$tcasedir" "$dialect" "$pat" /tmp cx
diff --git a/lib/dialects/linux/tests/case-20-open-flags-path.bash b/lib/dialects/linux/tests/case-20-open-flags-path.bash
new file mode 100755
index 0000000..4bc6c2d
--- /dev/null
+++ b/lib/dialects/linux/tests/case-20-open-flags-path.bash
@@ -0,0 +1,5 @@
+#!/bin/bash
+source tests/common.bash
+
+pat=".*DIR[ \t]\+.*PATH.*[ \t]\+.*/tmp$"
+source $tcasedir/util-open-flags.bash "$lsof" "$report" "$tcasedir" "$dialect" "$pat" /tmp path
diff --git a/lib/dialects/linux/tests/case-20-open-flags-tmpf.bash b/lib/dialects/linux/tests/case-20-open-flags-tmpf.bash
new file mode 100755
index 0000000..7e17e07
--- /dev/null
+++ b/lib/dialects/linux/tests/case-20-open-flags-tmpf.bash
@@ -0,0 +1,5 @@
+#!/bin/bash
+source tests/common.bash
+
+pat=".*REG[ \t]\+.*TMPF.*/tmp/.*$"
+source $tcasedir/util-open-flags.bash "$lsof" "$report" "$tcasedir" "$dialect" "$pat" /tmp tmpf rdwr
diff --git a/dialects/linux/tests/case-20-pidfd-pid.bash b/lib/dialects/linux/tests/case-20-pidfd-pid.bash
similarity index 57%
rename from dialects/linux/tests/case-20-pidfd-pid.bash
rename to lib/dialects/linux/tests/case-20-pidfd-pid.bash
index 13f00e4..ceeddb4 100755
--- a/dialects/linux/tests/case-20-pidfd-pid.bash
+++ b/lib/dialects/linux/tests/case-20-pidfd-pid.bash
@@ -1,21 +1,17 @@
 #!/bin/bash
+source tests/common.bash
 
-name=$(basename $0 .bash)
-lsof=$1
-report=$2
-tdir=$3
-
-TARGET=$tdir/pidfd
+TARGET=$tcasedir/pidfd
 
 {
 $TARGET | (
     read pid fd
     if [[ $pid = -1 && $fd = -1 ]]; then
-	echo "pidfd is not available on this platform"
-	exit 2
+        echo "pidfd is not available on this platform, skipping"
+        exit 77
     fi
     line=$($lsof -p $pid -a -d $fd -F pfn| tr '\n' ' ')
-    if ! fgrep -q "p${pid} f${fd} n[pidfd:$pid]" <<<"$line"; then
+    if ! grep -Fq "p${pid} f${fd} n[pidfd:$pid]" <<<"$line"; then
 	$lsof -p $pid -a -d $fd -F pfn
 	echo
 	echo $line
diff --git a/dialects/linux/tests/case-20-pipe-endpoint.bash b/lib/dialects/linux/tests/case-20-pipe-endpoint.bash
similarity index 90%
rename from dialects/linux/tests/case-20-pipe-endpoint.bash
rename to lib/dialects/linux/tests/case-20-pipe-endpoint.bash
index 37e2810..77d3ddc 100755
--- a/dialects/linux/tests/case-20-pipe-endpoint.bash
+++ b/lib/dialects/linux/tests/case-20-pipe-endpoint.bash
@@ -1,17 +1,13 @@
-#!/bin/sh
+#!/bin/bash
+source tests/common.bash
 
-name=$(basename $0 .bash)
-lsof=$1
-report=$2
-tdir=$3
-
-TARGET=$tdir/pipe
+TARGET=$tcasedir/pipe
 if ! [ -x $TARGET ]; then
     echo "target executable ( $TARGET ) is not found" >> $report
     exit 1
 fi
 
-{ ./$TARGET & } | {
+{ $TARGET & } | {
     read parent child fdr fdw;
     if [ -z "$parent" ] || [ -z "$child" ] || [ -z "$fdr" ] || [ -z "$fdw" ]; then
 	echo "unexpected output form target ( $TARGET )" >> $report
diff --git a/dialects/linux/tests/case-20-pipe-no-close-endpoint.bash b/lib/dialects/linux/tests/case-20-pipe-no-close-endpoint.bash
similarity index 95%
rename from dialects/linux/tests/case-20-pipe-no-close-endpoint.bash
rename to lib/dialects/linux/tests/case-20-pipe-no-close-endpoint.bash
index fcee368..7529300 100755
--- a/dialects/linux/tests/case-20-pipe-no-close-endpoint.bash
+++ b/lib/dialects/linux/tests/case-20-pipe-no-close-endpoint.bash
@@ -1,17 +1,13 @@
-#!/bin/sh
+#!/bin/bash
+source tests/common.bash
 
-name=$(basename $0 .bash)
-lsof=$1
-report=$2
-tdir=$3
-
-TARGET=$tdir/pipe
+TARGET=$tcasedir/pipe
 if ! [ -x $TARGET ]; then
     echo "target executable ( $TARGET ) is not found" >> $report
     exit 1
 fi
 
-{ ./$TARGET no-close & } | {
+{ $TARGET no-close & } | {
     read parent child fdr fdw;
     if [ -z "$parent" ] || [ -z "$child" ] || [ -z "$fdr" ] || [ -z "$fdw" ]; then
 	echo "unexpected output form target ( $TARGET )" >> $report
diff --git a/dialects/linux/tests/case-20-pty-endpoint.bash b/lib/dialects/linux/tests/case-20-pty-endpoint.bash
similarity index 93%
rename from dialects/linux/tests/case-20-pty-endpoint.bash
rename to lib/dialects/linux/tests/case-20-pty-endpoint.bash
index fb2b864..190eea7 100755
--- a/dialects/linux/tests/case-20-pty-endpoint.bash
+++ b/lib/dialects/linux/tests/case-20-pty-endpoint.bash
@@ -1,20 +1,16 @@
-#!/bin/sh
-
-name=$(basename $0 .bash)
-lsof=$1
-report=$2
-tdir=$3
+#!/bin/bash
+source tests/common.bash
 
 uname -r >> $report
 uname -r | sed -ne 's/^\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\).*/\1 \2/p' | {
     read major minor
     if [ "$major" -lt 4 ]; then
-	echo "pty endpoint features doesn't work on Linux $major"
-	exit 2
+	echo "pty endpoint features doesn't work on Linux $major, skipping"
+	exit 77
     fi
     if [ "$major" -eq 4 -a "$minor" -lt 13 ]; then
-	echo "pty endpoint features doesn't work on Linux $major.$minor"
-	exit 2
+	echo "pty endpoint features doesn't work on Linux $major.$minor, skipping"
+	exit 77
     fi
 } >> $report
 s=$?
@@ -22,13 +18,13 @@ if ! [ $s = 0 ]; then
     exit $s
 fi
 
-TARGET=$tdir/pty
+TARGET=$tcasedir/pty
 if ! [ -x $TARGET ]; then
     echo "target executable ( $TARGET ) is not found" >> $report
     exit 1
 fi
 
-{ ./$TARGET & } | {
+{ $TARGET & } | {
     read parent child fdm fds names;
     if [ -z "$parent" ] || [ -z "$child" ] || [ -z "$fdm" ] || [ -z "$fds" ] || [ -z "$names" ]; then
 	echo "unexpected output form target ( $TARGET )" >> $report
@@ -39,7 +35,7 @@ fi
 	echo child:  $child
 	echo fdm:    $fdm
 	echo fds:    $fds
-	echo nams:   $names
+	echo names:  $names
 	echo cmdline: "$lsof +E -p $parent"
     } >> $report
     $lsof +E -p "$parent" >> $report
diff --git a/dialects/linux/tests/case-20-ux-socket-endpoint-unaccepted.bash b/lib/dialects/linux/tests/case-20-ux-socket-endpoint-unaccepted.bash
similarity index 93%
rename from dialects/linux/tests/case-20-ux-socket-endpoint-unaccepted.bash
rename to lib/dialects/linux/tests/case-20-ux-socket-endpoint-unaccepted.bash
index b4bf916..06ca8cb 100755
--- a/dialects/linux/tests/case-20-ux-socket-endpoint-unaccepted.bash
+++ b/lib/dialects/linux/tests/case-20-ux-socket-endpoint-unaccepted.bash
@@ -1,11 +1,7 @@
-#!/bin/sh
+#!/bin/bash
+source tests/common.bash
 
-name=$(basename $0 .sh)
-lsof=$1
-report=$2
-tdir=$3
-
-TARGET=$tdir/ux
+TARGET=$tcasedir/ux
 
 $TARGET | {
     #
@@ -28,7 +24,7 @@ $TARGET | {
 	eval "$k=$v"
     done
     #
-    # An exapmle of lsof output:
+    # An example of lsof output:
     #
     # COMMAND     PID USER   FD   TYPE             DEVICE SIZE/OFF     NODE NAME
     # ux      1445917  jet    3u  unix 0x000000002d21092b      0t0 75849115 /tmp/lsof-test-ux-1445917.s type=STREAM ->INO=75843930 1445919,ux,5u
@@ -47,7 +43,7 @@ $TARGET | {
     if $lsof +E $path > $out; then
 	kill -CONT $ppid
 	if [[ $(wc -l < $out) != $(( 1 + 4 )) ]]; then
-	    echo "Too many file descriptors are found (the expection is 4 but got $(wc -l < $out)):" >> $report
+	    echo "Too many file descriptors are found (the expectation is 4 but got $(wc -l < $out)):" >> $report
 	    cat $out >> $report
 	    rm $out
 	    exit 1
diff --git a/dialects/linux/tests/case-20-ux-socket-endpoint.bash b/lib/dialects/linux/tests/case-20-ux-socket-endpoint.bash
similarity index 84%
rename from dialects/linux/tests/case-20-ux-socket-endpoint.bash
rename to lib/dialects/linux/tests/case-20-ux-socket-endpoint.bash
index 4f200a3..50acf13 100755
--- a/dialects/linux/tests/case-20-ux-socket-endpoint.bash
+++ b/lib/dialects/linux/tests/case-20-ux-socket-endpoint.bash
@@ -1,6 +1,10 @@
-name=$(basename $0 .bash)
-lsof=$1
-report=$2
+#!/bin/bash
+source tests/common.bash
+
+if [ -z "$(nc -h 2>&1 | grep '\-U')" ]; then
+    echo "nc does not support unix socket, skipping" >> $report
+    exit 77
+fi
 
 ux=/tmp/$name-$$.sock
 nc -l -U $ux > /dev/null < /dev/zero &
diff --git a/lib/dialects/linux/tests/epoll.c b/lib/dialects/linux/tests/epoll.c
new file mode 100644
index 0000000..4f68e73
--- /dev/null
+++ b/lib/dialects/linux/tests/epoll.c
@@ -0,0 +1,49 @@
+#include <stdio.h>
+#include <sys/epoll.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+int main(int argc, char **argv) {
+    int epfd = epoll_create(1);
+    if (epfd < 0) {
+        perror("epoll_create");
+        return 1;
+    }
+
+    int pipefd[2];
+    if (pipe(pipefd) < 0) {
+        perror("pipe");
+        return 1;
+    }
+
+    int evfd[2];
+    if ((evfd[0] = dup(pipefd[0])) < 0) {
+        perror("dup(pipefd[0])");
+        return 1;
+    }
+    if ((evfd[1] = dup(pipefd[1])) < 0) {
+        perror("dup(pipefd[1])");
+        return 1;
+    }
+
+    struct epoll_event ev;
+    ev.events = EPOLLOUT;
+    ev.data.fd = evfd[1];
+    if (epoll_ctl(epfd, EPOLL_CTL_ADD, ev.data.fd, &ev) < 0) {
+        perror("epoll_ctl<evfd[1]>");
+        return 1;
+    }
+
+    ev.events = EPOLLIN;
+    ev.data.fd = evfd[0];
+    if (epoll_ctl(epfd, EPOLL_CTL_ADD, ev.data.fd, &ev) < 0) {
+        perror("epoll_ctl<evfd[0]>");
+        return 1;
+    }
+
+    printf("%d %d %d %d\n", getpid(), epfd, evfd[0], evfd[1]);
+    fflush(stdout);
+    pause();
+    return 0;
+}
diff --git a/lib/dialects/linux/tests/eventfd.c b/lib/dialects/linux/tests/eventfd.c
new file mode 100644
index 0000000..12a5c11
--- /dev/null
+++ b/lib/dialects/linux/tests/eventfd.c
@@ -0,0 +1,29 @@
+#include <sys/eventfd.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+
+static int fd = -1;
+
+int main(int argc, char **argv) {
+    fd = eventfd(0, 0);
+    if (fd < 0) {
+        perror("eventfd");
+        return -1;
+    }
+
+    pid_t pid = fork();
+    if (pid < 0) {
+        perror("fork");
+        return -1;
+    } else if (pid == 0) {
+        pause();
+    } else {
+        printf("%d %d %d\n", getpid(), pid, fd);
+        fflush(stdout);
+        wait(NULL);
+    }
+    return 0;
+}
diff --git a/lib/dialects/linux/tests/mmap.c b/lib/dialects/linux/tests/mmap.c
new file mode 100644
index 0000000..b7e47e5
--- /dev/null
+++ b/lib/dialects/linux/tests/mmap.c
@@ -0,0 +1,35 @@
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#define handle_error(msg)                                                      \
+    do {                                                                       \
+        perror(msg);                                                           \
+        exit(EXIT_FAILURE);                                                    \
+    } while (0)
+
+int main(int argc, char *argv[]) {
+    char *addr;
+    int fd;
+    struct stat sb;
+
+    if (argc != 2)
+        exit(EXIT_FAILURE);
+
+    fd = open(argv[1], O_RDONLY);
+    if (fd == -1)
+        handle_error("open");
+
+    if (fstat(fd, &sb) == -1)
+        handle_error("fstat");
+
+    addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+    if (addr == MAP_FAILED)
+        handle_error("mmap");
+
+    pause();
+    return 0;
+}
diff --git a/lib/dialects/linux/tests/mount-and-mmap.bash b/lib/dialects/linux/tests/mount-and-mmap.bash
new file mode 100755
index 0000000..2eebacc
--- /dev/null
+++ b/lib/dialects/linux/tests/mount-and-mmap.bash
@@ -0,0 +1,20 @@
+#!/bin/sh
+set -e
+
+lsof=$1
+report=$2
+tdir=$3
+
+TARGET=$tdir/mmap
+if ! [ -x $TARGET ]; then
+    echo "target executable ( $TARGET ) is not found" >> $report
+    exit 1
+fi
+
+mkdir /tmp/TEST
+dd if=/dev/zero of=/tmp/ext4.img bs=40MB count=1
+mkfs.ext4 /tmp/ext4.img
+mount --make-private /tmp/ext4.img /tmp/TEST
+
+dd if=/dev/zero of=/tmp/TEST/MMAP bs=2MB count=1
+$TARGET /tmp/TEST/MMAP &
diff --git a/lib/dialects/linux/tests/mq_fork.c b/lib/dialects/linux/tests/mq_fork.c
new file mode 100644
index 0000000..2bcb991
--- /dev/null
+++ b/lib/dialects/linux/tests/mq_fork.c
@@ -0,0 +1,43 @@
+#include <fcntl.h>    /* For O_* constants */
+#include <sys/stat.h> /* For mode constants */
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <mqueue.h>
+#include <unistd.h>
+#include <stdio.h>
+
+int main(int argc, char **argv) {
+    int pid;
+    char *fname;
+
+    if (argc != 2) {
+        fprintf(stderr, "wrong number of arguments: %d\n", argc);
+        return 1;
+    } else if (argv[1][0] != '/') {
+        fprintf(stderr, "name must starts with '/': %c\n", argv[1][0]);
+        return 1;
+    }
+
+    fname = argv[1];
+    mqd_t t = mq_open(fname, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR, NULL);
+    ;
+
+    if (t == -1) {
+        perror("mq_open");
+        return 1;
+    }
+
+    pid = fork();
+    if (pid == 0)
+        pause();
+    else if (pid > 0) {
+        printf("%d %d %d\n", getpid(), pid, t);
+        fflush(stdout);
+        wait(NULL);
+        mq_unlink(fname);
+    } else {
+        perror("fork");
+        return 1;
+    }
+    return 0;
+}
diff --git a/lib/dialects/linux/tests/mq_open.c b/lib/dialects/linux/tests/mq_open.c
new file mode 100644
index 0000000..c818fce
--- /dev/null
+++ b/lib/dialects/linux/tests/mq_open.c
@@ -0,0 +1,24 @@
+#include <fcntl.h>    /* For O_* constants */
+#include <sys/stat.h> /* For mode constants */
+#include <mqueue.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <signal.h>
+
+#define NAME "/xxx"
+
+static void do_nothing(int n) { signal(SIGCONT, do_nothing); }
+
+int main(void) {
+    mqd_t t = mq_open(NAME, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR, NULL);
+    if ((mqd_t)t == -1) {
+        perror("open[" NAME "]");
+        return 1;
+    }
+
+    printf("pid: %d / fd: %d\n", getpid(), t);
+    fflush(stdout);
+    signal(SIGCONT, do_nothing);
+    pause();
+    return 0;
+}
diff --git a/lib/dialects/linux/tests/open_with_flags.c b/lib/dialects/linux/tests/open_with_flags.c
new file mode 100644
index 0000000..01d6316
--- /dev/null
+++ b/lib/dialects/linux/tests/open_with_flags.c
@@ -0,0 +1,63 @@
+#define _GNU_SOURCE
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdio.h>
+
+struct {
+    const char *name;
+    int flag;
+} table[] = {
+    {"path", O_PATH},
+    {"cx", O_CLOEXEC},
+    {"tmpf", O_TMPFILE},
+    {"rdwr", O_RDWR},
+};
+
+#define TABLELEN sizeof(table) / sizeof(table[0])
+
+static int encode(const char *const s) {
+    for (int i = 0; i < TABLELEN; i++)
+        if (!strcmp(s, table[i].name))
+            return table[i].flag;
+    return 0;
+}
+
+static void print_usage(FILE *fp, const char *const prog) {
+    fprintf(fp, "Usage:\n");
+    fprintf(fp, "	%s FILENAME FLAG ...\n", prog);
+    fprintf(fp, "Flags:\n");
+    for (int i = 0; i < TABLELEN; i++)
+        fprintf(fp, "	%s\n", table[i].name);
+}
+
+int main(int argc, char **argv) {
+
+    if (argc < 3) {
+        fprintf(stderr, "Too few argument\n");
+        print_usage(stderr, argv[0]);
+        return 1;
+    }
+
+    char *fname = argv[1];
+    int flags = 0;
+
+    for (int i = 2; i < argc; i++)
+        flags |= encode(argv[i]);
+
+    int fd = open(fname, flags, 0644);
+    if (fd < 0) {
+        perror("open");
+        return 1;
+    }
+
+    printf("%d\n", getpid());
+    fflush(stdout);
+    pause();
+    return 0;
+}
diff --git a/lib/dialects/linux/tests/pidfd.c b/lib/dialects/linux/tests/pidfd.c
new file mode 100644
index 0000000..b5660c3
--- /dev/null
+++ b/lib/dialects/linux/tests/pidfd.c
@@ -0,0 +1,26 @@
+#define _GNU_SOURCE
+#include <sys/types.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+
+#ifndef __NR_pidfd_open
+#    define __NR_pidfd_open 434 /* System call # on most architectures */
+#endif
+
+int main(void) {
+    pid_t self = getpid();
+    int pidfd = syscall(__NR_pidfd_open, self, 0);
+    if (pidfd < 0) {
+        if (errno == ENOSYS) {
+            printf("%d %d\n", -1, -1);
+        }
+        perror("pidfd_open");
+        return 1;
+    }
+    printf("%d %d\n\n\n", self, pidfd);
+    fclose(stdout);
+    pause();
+    return 0;
+}
diff --git a/lib/dialects/linux/tests/pipe.c b/lib/dialects/linux/tests/pipe.c
new file mode 100644
index 0000000..7ec1726
--- /dev/null
+++ b/lib/dialects/linux/tests/pipe.c
@@ -0,0 +1,41 @@
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+
+int main(int argc, char **argv) {
+    int no_close = 0;
+
+    if (argc > 1 && strcmp(argv[1], "no-close") == 0)
+        no_close = 1;
+
+    int pd[2];
+
+    if (pipe(pd) < 0) {
+        perror("pipe");
+        return 1;
+    }
+
+    pid_t self, child;
+
+    self = getpid();
+    child = fork();
+
+    if (child == 0) {
+        if (!no_close)
+            close(pd[0]);
+        pause();
+        return 0;
+    } else if (child < 0) {
+        perror("fork");
+        return 1;
+    }
+
+    if (!no_close)
+        close(pd[1]);
+    printf("%d %d %d %d\n", self, child, pd[0], pd[1]);
+    fflush(stdout);
+    wait(NULL);
+    return 0;
+}
diff --git a/lib/dialects/linux/tests/pty.c b/lib/dialects/linux/tests/pty.c
new file mode 100644
index 0000000..42eb88a
--- /dev/null
+++ b/lib/dialects/linux/tests/pty.c
@@ -0,0 +1,48 @@
+#include <fcntl.h>
+#include <stdio.h>
+#include <err.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+int main(void) {
+    int tfd[2];
+    int s;
+
+    if ((tfd[0] = open("/dev/ptmx", O_RDONLY)) < 0)
+        err(1, "failed to open ptmx");
+
+    int unlock = 0;
+    if (ioctl(tfd[0], TIOCSPTLCK, &unlock) < 0)
+        err(1, "failed to do ioctl TIOCSPTLCK");
+
+    if (ioctl(tfd[0], TIOCGPTN, &s) < 0)
+        err(1, "failed to do ioctl TIOCGPTN");
+
+    char slave_name[128];
+    snprintf(slave_name, 128, "/dev/pts/%d", s);
+    if ((tfd[1] = open(slave_name, O_RDONLY)) < 0)
+        err(1, "failed to open %s", slave_name);
+
+    pid_t self, child;
+    self = getpid();
+    child = fork();
+
+    if (child == 0) {
+        if (dup2(tfd[1], tfd[0]) < 0)
+            err(1, "failed to dup2(%d, %d)", tfd[1], tfd[0]);
+        close(tfd[1]);
+        pause();
+        return 0;
+    } else if (child < 0) {
+        perror("fork");
+        return 1;
+    }
+
+    printf("%d %d %d %d %d\n", self, child, tfd[0], tfd[1], s);
+    fflush(stdout);
+    wait(NULL);
+    return 0;
+}
diff --git a/lib/dialects/linux/tests/util-open-flags.bash b/lib/dialects/linux/tests/util-open-flags.bash
new file mode 100644
index 0000000..5e06399
--- /dev/null
+++ b/lib/dialects/linux/tests/util-open-flags.bash
@@ -0,0 +1,44 @@
+source tests/common.bash
+
+pat=$5
+tfile=$6
+
+shift 6
+
+TARGET=$tcasedir/open_with_flags
+if ! [ -x $TARGET ]; then
+    echo "target executable ( $TARGET ) is not found" >> $report
+    exit 1
+fi
+
+export LC_ALL=C
+
+log=/tmp/$name-$$.log
+$TARGET $tfile "$@" 2>> $log | {
+    read pid
+
+    if  [[ -z "$pid" ]]; then
+        cat $log >> $report
+        # musl prints "Not supported" instead of "Operation not supported"
+        if grep -E -q 'open: (Operation not supported|Not supported)' $log; then
+            echo "a flag passed to open is not supported on this platform, skipping" >> $report
+            exit 77
+        fi
+        echo "unexpected output from target ( $TARGET )" >> $report
+	exit 1
+    fi
+    if ! [ -e "/proc/$pid" ]; then
+        echo "the target process dead unexpectedly" >> $report
+        exit 1
+    fi
+
+    echo "expected: $pat" >> $report
+    echo "lsof output:" >> $report
+    output=$($lsof +fg -p $pid)
+    echo "$output" >> $report
+    echo "$output" | grep -q "$pat"
+    result=$?
+
+    kill $pid
+    exit $result
+}
diff --git a/lib/dialects/linux/tests/ux.c b/lib/dialects/linux/tests/ux.c
new file mode 100644
index 0000000..bab986d
--- /dev/null
+++ b/lib/dialects/linux/tests/ux.c
@@ -0,0 +1,133 @@
+#define _POSIX_SOURCE
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <signal.h>
+
+#define TEMPLATE "/tmp/lsof-test-ux-%ld.s"
+
+static void do_nothing(int n) {}
+
+int main(void) {
+    int rendezvous[2];
+    if (pipe(rendezvous) < 0) {
+        perror("pipe");
+        return 1;
+    }
+
+    pid_t pid = fork();
+    if (pid > 0) {
+        close(rendezvous[0]);
+        /* parent: server */
+        int server = socket(AF_UNIX, SOCK_STREAM, 0);
+        if (server < 0) {
+            perror("socket (server)");
+            return 1;
+        }
+        struct sockaddr_un un = {
+            .sun_family = AF_UNIX,
+        };
+        snprintf(un.sun_path, 108, TEMPLATE, (long int)getpid());
+        unlink(un.sun_path);
+
+        if (bind(server, (void *)&un, sizeof(un)) < 0) {
+            perror("bind (server)");
+            return 1;
+        }
+        if (listen(server, 0) < 0) {
+            perror("listen (server)");
+            return 1;
+        }
+
+        char b = 1;
+        if (write(rendezvous[1], &b, 1) < 0) {
+            perror("write rendezvous pipe (server)");
+            return 1;
+        }
+        b++;
+
+        int client;
+        if ((client = accept(server, NULL, 0)) < 0) {
+            perror("listen (server)");
+            return 1;
+        }
+
+        char buf[1024];
+        if (read(client, buf, 1024) < 0) {
+            perror("read (server)");
+            return 1;
+        }
+
+        fputs(buf, stdout);
+        printf("ppid %ld\nlisten %d\naccept %d\npath %s\n", (long int)getpid(),
+               server, client, un.sun_path);
+        fputs("end\n", stdout);
+        fflush(stdout);
+        signal(SIGCONT, do_nothing);
+        pause();
+
+        unlink(un.sun_path);
+        (void)write(rendezvous[1], &b, 1);
+        b++;
+
+        return 0;
+    } else if (pid == 0) {
+        char b;
+        /* child: client */
+        close(rendezvous[1]);
+        if (read(rendezvous[0], &b, 1) < 0) {
+            perror("read rendezvous pipe (client)");
+            /* TODO: kill the parent process. */
+            return 1;
+        }
+
+        int server = socket(AF_UNIX, SOCK_STREAM, 0);
+        if (server < 0) {
+            perror("socket (client)");
+            return 1;
+        }
+
+        struct sockaddr_un un = {
+            .sun_family = AF_UNIX,
+        };
+        snprintf(un.sun_path, 108, TEMPLATE, (long int)getppid());
+        if (connect(server, (void *)&un, sizeof(un)) < 0) {
+            perror("connect (client)");
+            return 1;
+        }
+
+        FILE *serverf = fdopen(server, "w");
+        if (!serverf) {
+            perror("fdopen (client)");
+            return 1;
+        }
+
+        int server2 = socket(AF_UNIX, SOCK_STREAM, 0);
+        if (server2 < 0) {
+            perror("socket (client)");
+            return 1;
+        }
+        if (connect(server2, (void *)&un, sizeof(un)) < 0) {
+            perror("connect (client (server2))");
+            return 1;
+        }
+
+        fprintf(serverf, "pid %ld\nconnect %d\nconnect2 %d\n",
+                (long int)getpid(), server, server2);
+        putc('\0', serverf);
+        fflush(serverf);
+
+        if (read(rendezvous[0], &b, 1) < 0) {
+            perror("read rendezvous pipe (client)");
+            return 1;
+        }
+        return 0;
+    }
+
+    perror("fork");
+    return 1;
+}
diff --git a/lib/dialects/netbsd/Makefile b/lib/dialects/netbsd/Makefile
new file mode 100644
index 0000000..602673f
--- /dev/null
+++ b/lib/dialects/netbsd/Makefile
@@ -0,0 +1,158 @@
+
+# NetBSD 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} -Iinclude -Ilib -Isrc -I.
+CFLAGS=	${CDEFS} ${INCL} ${DEBUG}
+
+GRP=
+
+HDR=	lib/common.h include/lsof_fields.h dlsof.h machine.h lib/proto.h dproto.h
+
+SRC=    dmnt.c dnode.c dnode1.c dproc.c dsock.c dstore.c \
+	arg.c main.c node.c print.c ptti.c store.c usage.c \
+	util.c
+
+OBJ=	dmnt.o dnode.o dnode1.o dproc.o dsock.o dstore.o \
+	arg.o main.o node.o print.o ptti.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_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/lib/dialects/netbsd/Mksrc b/lib/dialects/netbsd/Mksrc
new file mode 100755
index 0000000..0f86dab
--- /dev/null
+++ b/lib/dialects/netbsd/Mksrc
@@ -0,0 +1,32 @@
+#!/bin/sh
+#
+# Mksrc - make NetBSD 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 $
+
+mksrc() {
+  for i in $L
+  do
+    rm -f $i
+    $LSOF_MKC $D/$i $i
+    echo "$LSOF_MKC $D/$i $i"
+  done
+}
+
+D=lib/dialects/netbsd
+L="dlsof.h dmnt.c dnode.c dnode1.c dproc.c dproto.h dsock.c dstore.c machine.h"
+
+mksrc
+
+D=src
+L="arg.c main.c node.c print.c ptti.c store.c usage.c util.c"
+
+mksrc
diff --git a/lib/dialects/netbsd/dlsof.h b/lib/dialects/netbsd/dlsof.h
new file mode 100644
index 0000000..41dd7f2
--- /dev/null
+++ b/lib/dialects/netbsd/dlsof.h
@@ -0,0 +1,573 @@
+/*
+ * dlsof.h - NetBSD 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(NETBSDV) || __NetBSD_Version__ >= 999001900)
+#        include <sys/ptrace.h> /* pulled in by procfs.h, but needs to be pulled in before _KERNEL is defined */
+#    endif
+
+#    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(NETBSDV) && __NetBSD_Version__ >= 106060000
+
+#        if __NetBSD_Version__ < 399001100
+#            define _KERNEL
+#        endif /* __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(NETBSDV) && __NetBSD_Version__>=106060000 */
+
+#    if defined(NETBSDV) && __NetBSD_Version__ < 399001100
+#        include <sys/buf.h>
+#    endif /* defined(NETBSDV) && __NetBSD_Version__<399001100 */
+
+#    if defined(NETBSDV) && __NetBSD_Version__ >= 106060000 &&                 \
+        __NetBSD_Version__ < 399001100
+#        undef _KERNEL
+#    endif /* defined(NETBSDV) && __NetBSD_Version__>=106060000                \
+          &&  __NetBSD_Version__<399001100 */
+
+#    define NFS
+#    define m_stat mnt_stat
+
+#    if defined(NETBSDV) && __NetBSD_Version__ >= 106060000
+#        define _KERNEL
+#    endif /* defined(NETBSDV) && __NetBSD_Version__>=106060000 */
+
+#    if defined(NETBSDV) && NETBSDV >= 1003000
+#        define sockproto NETBSD_sockproto
+#    endif /* defined(NETBSDV) && NETBSDV>=1003000 */
+
+#    include <sys/mount.h>
+
+#    if defined(NETBSDV) && __NetBSD_Version__ >= 106060000
+#        undef _KERNEL
+#    endif /* defined(NETBSDV) && __NetBSD_Version__>=106060000 */
+
+#    include <rpc/types.h>
+#    include <sys/protosw.h>
+
+#    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(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(NETBSDV) && __NetBSD_Version__<106060000 */
+
+#        define _KERNEL
+#        ifndef VFS_PROTOS
+#            define VFS_PROTOS(x)
+#        endif
+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 <net/route.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 <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>
+
+#    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(HASTMPFS)
+#        include <fs/tmpfs/tmpfs.h>
+#    endif /* defined(HASTMPFS) */
+
+#    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) */
+#        if (defined(NETBSDV) && __NetBSD_Version__ >= 900000000)
+#            include <sys/ptrace.h>
+#        endif
+/*
+ * Needed for definition of curlwp, which isn't used by this code base,
+ * but is exposed in procfs.h in an inline function declaration.
+ */
+#        if (defined(NETBSDV) && __NetBSD_Version__ >= 999009300)
+extern struct lwp *curlwp;
+#        endif
+#        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 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 */
+#                if NETBSDV < 8099000
+#                    define Pctl PFSctl
+#                endif /* NETBSDV<8099000 */
+#            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 */
+#    endif                /* defined(DTYPE_KQUEUE) */
+
+#    include <sys/lockf.h>
+#    undef KERNEL
+#    undef _KERNEL
+
+#    if defined(UVM)
+#        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)
+#        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 */
+#    if defined(NETBSDV) && __NetBSD_Version__ >= 499002500
+    /* MFSNAMELEN was removed from the kernel source after 4.99.24 */
+    char type[sizeof(
+        ((struct statvfs *)NULL)->f_fstypename)]; /* type of file system */
+#    else
+    char type[MFSNAMELEN]; /* type of file system */
+#    endif
+    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(NETBSDV) && NETBSDV >= 1002000
+#            include <stddef.h>
+#        endif /* 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(NETBSDV) && NETBSDV >= 1002000 &&                          \
+            __NetBSD_Version__ < 999005400
+#            define NCACHE_NXT nc_hash.le_next /* link in NCACHE */
+#        else /* 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(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) */
+
+#    if defined(VV_ROOT) /* NetBSD >= 4.99.33 */
+#        define VNODE_VFLAG v_vflag
+#        define NCACHE_VROOT VV_ROOT
+#    else
+#        define VNODE_VFLAG v_flag
+#        define NCACHE_VROOT VROOT
+#    endif /* VV_ROOT */
+
+struct lsof_context_dialect {};
+
+#endif /* NETBSD_LSOF_H */
diff --git a/lib/dialects/netbsd/dmnt.c b/lib/dialects/netbsd/dmnt.c
new file mode 100644
index 0000000..efb6b73
--- /dev/null
+++ b/lib/dialects/netbsd/dmnt.c
@@ -0,0 +1,259 @@
+/*
+ * dmnt.c - NetBSD 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";
+#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) */
+
+#if defined(NETBSDV)
+#    include <sys/param.h>
+
+#    if __NetBSD_Version__ >= 899000100
+#        define __EXPOSE_MOUNT
+#    endif
+#    if __NetBSD_Version__ >= 399002400
+#        include <sys/types.h>
+#        include <sys/mount.h>
+#    endif
+#endif
+
+#include "common.h"
+
+/*
+ * Local static definitions
+ */
+
+/*
+ * readmnt() - read mount table
+ */
+
+struct mounts *readmnt(struct lsof_context *ctx) {
+    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;
+#if defined(NETBSDV) && __NetBSD_Version__ >= 499002500
+        /* MFSNAMELEN was removed from the kernel source after 4.99.24 */
+        mb->f_fstypename[sizeof(mb->f_fstypename) - 1] = '\0';
+#else
+        mb->f_fstypename[MFSNAMELEN - 1] = '\0';
+#endif
+        /*
+         * 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");
+            Error(ctx);
+        }
+        if ((ln = Readlink(ctx, 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(ctx, 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(ctx, 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(ctx, 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(struct lsof_context *ctx, /* context */
+                      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(ctx, 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);
+        Error(ctx);
+    }
+    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);
+        Error(ctx);
+    }
+    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/lib/dialects/netbsd/dnode.c b/lib/dialects/netbsd/dnode.c
new file mode 100644
index 0000000..6a7b941
--- /dev/null
+++ b/lib/dialects/netbsd/dnode.c
@@ -0,0 +1,1449 @@
+/*
+ * dnode.c - NetBSD 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";
+#endif
+
+#include "common.h"
+
+#if defined(HAS_LOCKF_H)
+#    include "lockf.h"
+#endif
+
+#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
+static int lkup_dev_tty(struct lsof_context *ctx, 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)
+static void getmemsz(struct lsof_context *ctx, 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(struct lsof_context *ctx, 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(ctx, (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;
+        }
+    }
+}
+#    undef PGSHIFT
+#endif /* defined(HASPROCFS) */
+
+#if defined(HASFDESCFS) && HASFDESCFS == 1
+/*
+ * lkup_dev_tty() - look up /dev/tty
+ */
+
+static int lkup_dev_tty(struct lsof_context *ctx, /* context */
+                        dev_t *dr,     /* place to return device number */
+                        INODETYPE *ir) /* place to return inode number */
+{
+    int i;
+
+    readdev(ctx, 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(ctx, &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(ctx);
+        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(struct lsof_context *ctx, /* context */
+                    KA_T ka) /* kqueue file structure address */
+{
+    Lf->type = LSOF_FILE_KQUEUE;
+    enter_dev_ch(ctx, print_kptr(ka, (char *)NULL, 0));
+}
+#endif /* defined(HASKQUEUE) */
+
+/*
+ * process_node() - process vnode
+ */
+
+void process_node(struct lsof_context *ctx, /* context */
+                  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;
+#if defined(HAS_LOCKF_H)
+    struct lockf lf, *lff, *lfp;
+#endif
+    struct inode i;
+    struct mfsnode m;
+#if defined(HASTMPFS)
+    struct tmpfs_node tmp;
+#endif /* defined(HASTMPFS) */
+    struct nfsnode n;
+    enum nodetype {
+        NONODE,
+        CDFSNODE,
+        DOSNODE,
+        EXT2NODE,
+        FDESCNODE,
+        INODE,
+        KERNFSNODE,
+        MFSNODE,
+        NFSNODE,
+        PFSNODE,
+        PTYFSNODE,
+        TMPFSNODE
+    } 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;
+#    if __NetBSD_Version__ >= 499006200
+#        define specinfo specnode
+#        define vu_specinfo vu_specnode
+#        define si_rdev sn_rdev
+#    endif
+    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(ctx, 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(ctx, "no vnode address");
+        return;
+    }
+    v = &vb;
+    if (readvnode(ctx, va, v)) {
+        enter_nm(ctx, 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(ctx, (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(ctx, 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(ctx, Namech);
+            return;
+        }
+        iso_stat = 1;
+        nty = CDFSNODE;
+        break;
+#endif /* defined(HAS9660FS) */
+
+#if defined(HASFDESCFS)
+    case VT_FDESC:
+        if (!v->v_data || kread(ctx, (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(ctx, Namech);
+            return;
+        }
+        nty = FDESCNODE;
+        break;
+#endif /* defined(HASFDESCFS) */
+
+#if defined(HASKERNFS)
+    case VT_KERNFS:
+
+        /*
+         * Read the kernfs_node.
+         */
+        if (!v->v_data ||
+            kread(ctx, (KA_T)v->v_data, (char *)&kn, sizeof(kn))) {
+            if (v->v_type != VDIR || !(v->VNODE_VFLAG && NCACHE_VROOT)) {
+                (void)snpf(Namech, Namechl, "can't read kernfs_node at: %s",
+                           print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+                enter_nm(ctx, 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(ctx, (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(ctx, (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->VNODE_VFLAG & NCACHE_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(ctx, (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(ctx, Namech);
+            return;
+        }
+        nty = MFSNODE;
+        break;
+
+#if defined(HASTMPFS)
+    case VT_TMPFS:
+        if (!v->v_data ||
+            kread(ctx, (KA_T)v->v_data, (char *)&tmp, sizeof(tmp))) {
+            (void)snpf(Namech, Namechl, "can't read tmpfs_node at: %s",
+                       print_kptr((KA_T)v->v_data, (char *)NULL, 0));
+            enter_nm(ctx, Namech);
+            return;
+        }
+        nty = TMPFSNODE;
+        break;
+#endif /* defined(HASTMPFS) */
+
+#if defined(HASMSDOSFS)
+    case VT_MSDOSFS:
+        if (!v->v_data || kread(ctx, (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(ctx, Namech);
+            return;
+        }
+        nty = DOSNODE;
+        break;
+#endif /* defined(HASMSDOSFS) */
+
+    case VT_NFS:
+        if (!v->v_data || kread(ctx, (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(ctx, Namech);
+            return;
+        }
+
+#if defined(HASNFSVATTRP)
+        if (!n.n_vattr ||
+            kread(ctx, (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(ctx, 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(ctx, (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(ctx, Namech);
+            return;
+        }
+        if (!nu.null_lowervp) {
+            (void)snpf(Namech, Namechl, "null_node overlays nothing");
+            enter_nm(ctx, 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(ctx, (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(ctx, Namech);
+            return;
+        }
+        nty = PFSNODE;
+        break;
+#endif /* defined(HASPROCFS) */
+
+#if defined(HASPTYFS)
+    case VT_PTYFS:
+        if (!v->v_data ||
+            kread(ctx, (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(ctx, 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(ctx, (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(ctx, 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(ctx, (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(ctx, (KA_T)i.i_ump, (char *)&um, sizeof(um))) {
+                if (um.um_fstype == UFS1) {
+                    ffs = 1;
+                    if (i.DINODE_U.ffs1_din &&
+                        !kread(ctx, (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(ctx, (KA_T)i.DINODE_U.ffs2_din, (char *)&u2,
+                               sizeof(u2))) {
+                        u2s = 1;
+                    }
+                }
+            }
+#endif /* defined(HASI_FFS1) */
+        }
+
+#if defined(HAS_LOCKF_H)
+        if ((lff = i.i_lockf)) {
+
+            /*
+             * Determine the lock state.
+             */
+            lfp = lff;
+            do {
+                if (kread(ctx, (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(ctx, (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 ? LSOF_LOCK_READ_FULL : LSOF_LOCK_READ_PARTIAL;
+                else if (lf.lf_type == F_WRLCK)
+                    Lf->lock =
+                        lt ? LSOF_LOCK_WRITE_FULL : LSOF_LOCK_WRITE_PARTIAL;
+                else if (lf.lf_type == (F_RDLCK | F_WRLCK))
+                    Lf->lock = LSOF_LOCK_READ_WRITE;
+                break;
+            } while ((lfp = lf.lf_next) && lfp != lff);
+        }
+#endif
+        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(ctx, 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(ctx, (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(ctx, &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(ctx, (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) */
+
+#if defined(HASTMPFS)
+    case TMPFSNODE:
+        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(HASTMPFS) */
+    }
+    /*
+     * Obtain the inode number.
+     */
+    switch (nty) {
+
+#if defined(HASMSDOSFS)
+    case DOSNODE:
+        if (d.de_pmp && !kread(ctx, (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) */
+
+#if defined(HASTMPFS)
+    case TMPFSNODE:
+        Lf->inode = (INODETYPE)tmp.tn_id;
+        Lf->inp_ty = 1;
+        break;
+#endif /* defined(HASTMPFS) */
+    }
+
+    /*
+     * Obtain the file size.
+     */
+    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:
+        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(ctx, 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(HASTMPFS)
+            case TMPFSNODE:
+                Lf->sz = (SZOFFTYPE)tmp.tn_size;
+                Lf->sz_def = 1;
+                break;
+#endif /* defined(HASTMPFS) */
+
+#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) */
+            }
+        }
+        break;
+    }
+    /*
+     * Record the link count.
+     */
+    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:
+        Lf->type = LSOF_FILE_VNODE_VNON;
+        break;
+    case VREG:
+        Lf->type = LSOF_FILE_VNODE_VREG;
+        break;
+    case VDIR:
+        Lf->type = LSOF_FILE_VNODE_VDIR;
+        break;
+    case VBLK:
+        Lf->type = LSOF_FILE_VNODE_VBLK;
+        Ntype = N_BLK;
+        break;
+    case VCHR:
+        Lf->type = LSOF_FILE_VNODE_VCHR;
+        Ntype = N_CHR;
+        break;
+    case VLNK:
+        Lf->type = LSOF_FILE_VNODE_VLNK;
+        break;
+
+#if defined(VSOCK)
+    case VSOCK:
+        Lf->type = LSOF_FILE_VNODE_VSOCK;
+        break;
+#endif /* defined(VSOCK) */
+
+    case VBAD:
+        Lf->type = LSOF_FILE_VNODE_VBAD;
+        break;
+    case VFIFO:
+        Lf->type = LSOF_FILE_VNODE_VFIFO;
+        break;
+    default:
+        Lf->type = LSOF_FILE_UNKNOWN_RAW;
+        Lf->unknown_file_type_number = type;
+    }
+    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(ctx, "memory");
+    }
+
+#if defined(HASPROCFS)
+    else if (nty == PFSNODE) {
+        Lf->dev_def = Lf->rdev_def = 0;
+        (void)snpf(Namech, Namechl, "/%s", HASPROCFS);
+        switch (p.pfs_type) {
+        case Proot:
+            Lf->type = LSOF_FILE_PROC_DIR;
+            break;
+        case Pcurproc:
+            ep = endnm(ctx, &sz);
+            (void)snpf(ep, sz, "/curproc");
+            Lf->type = LSOF_FILE_PROC_CUR_PROC;
+            break;
+        case Pproc:
+            ep = endnm(ctx, &sz);
+            (void)snpf(ep, sz, "/%d", p.pfs_pid);
+            Lf->type = LSOF_FILE_PROC_DIR;
+            break;
+        case Pfile:
+            ep = endnm(ctx, &sz);
+            (void)snpf(ep, sz, "/%d/file", p.pfs_pid);
+            Lf->type = LSOF_FILE_PROC_FILE;
+            break;
+        case Pmem:
+            ep = endnm(ctx, &sz);
+            (void)snpf(ep, sz, "/%d/mem", p.pfs_pid);
+            Lf->type = LSOF_FILE_PROC_MEMORY;
+            break;
+        case Pregs:
+            ep = endnm(ctx, &sz);
+            (void)snpf(ep, sz, "/%d/regs", p.pfs_pid);
+            Lf->type = LSOF_FILE_PROC_REGS;
+            break;
+        case Pfpregs:
+            ep = endnm(ctx, &sz);
+            (void)snpf(ep, sz, "/%d/fpregs", p.pfs_pid);
+            Lf->type = LSOF_FILE_PROC_FP_REGS;
+            break;
+
+#    if defined(Pctl)
+        case Pctl:
+            ep = endnm(ctx, &sz);
+            (void)snpf(ep, sz, "/%d/ctl", p.pfs_pid);
+            Lf->type = LSOF_FILE_PROC_CTRL;
+            break;
+#    endif /* defined(Pctl) */
+
+        case Pstatus:
+            ep = endnm(ctx, &sz);
+            (void)snpf(ep, sz, "/%d/status", p.pfs_pid);
+            Lf->type = LSOF_FILE_PROC_STATUS;
+            break;
+        case Pnote:
+            ep = endnm(ctx, &sz);
+            (void)snpf(ep, sz, "/%d/note", p.pfs_pid);
+            Lf->type = LSOF_FILE_PROC_PROC_NOTIFIER;
+            break;
+        case Pnotepg:
+            ep = endnm(ctx, &sz);
+            (void)snpf(ep, sz, "/%d/notepg", p.pfs_pid);
+            Lf->type = LSOF_FILE_PROC_GROUP_NOTIFIER;
+            break;
+
+#    if defined(Pfd)
+        case Pfd:
+            ep = endnm(ctx, &sz);
+            (void)snpf(ep, sz, "/%d/fd", p.pfs_pid);
+            Lf->type = LSOF_FILE_PROC_FD;
+            break;
+#    endif /* defined(Pfd) */
+
+#    if defined(Pmap)
+        case Pmap:
+            ep = endnm(ctx, &sz);
+            (void)snpf(ep, sz, "/%d/map", p.pfs_pid);
+            Lf->type = LSOF_FILE_PROC_MAP;
+            break;
+#    endif /* defined(Pmap) */
+
+#    if defined(Pmaps)
+        case Pmaps:
+            ep = endnm(ctx, &sz);
+            (void)snpf(ep, sz, "/%d/maps", p.pfs_pid);
+            Lf->type = LSOF_FILE_PROC_MAPS;
+            break;
+#    endif /* defined(Pmaps) */
+        }
+    }
+#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(ctx, &sz);
+            (void)snpf(ep, sz, "/%lu", (unsigned long)pt.ptyfs_pty);
+            break;
+        case PTYFSptc:
+            ep = endnm(ctx, &sz);
+            (void)snpf(ep, sz, "/%lu (master)", (unsigned long)pt.ptyfs_pty);
+            break;
+        case PTYFSroot:
+            Lf->sz = 512;
+            Lf->sz_def = 1;
+            break;
+        }
+    }
+#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(ctx);
+#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(ctx);
+        /*
+         * 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(ctx, Namech);
+            ns = 1;
+        } else
+            ns = 0;
+        if (Sfile &&
+            is_file_named(ctx, (char *)NULL,
+                          ((type == VCHR) || (type == VBLK)) ? 1 : 0)) {
+            Lf->sf |= SELNM;
+        }
+        if (ns)
+            Namech[0] = '\0';
+    }
+    /*
+     * Enter name characters.
+     */
+    if (Namech[0])
+        enter_nm(ctx, Namech);
+}
+
+#if defined(HAS_SYS_PIPEH)
+/*
+ * process_pipe() - process a file structure whose type is DTYPE_PIPE
+ */
+
+void process_pipe(struct lsof_context *ctx, /* context */
+                  KA_T pa)                  /* pipe structure kernel address */
+{
+    char *ep;
+    struct pipe p;
+    size_t sz;
+
+    if (!pa || kread(ctx, (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(ctx, Namech);
+        return;
+    }
+    Lf->type = LSOF_FILE_PIPE;
+    enter_dev_ch(ctx, print_kptr(pa, (char *)NULL, 0));
+    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(ctx, &sz);
+        (void)snpf(ep, sz, ", cnt=%d", p.pipe_buffer.cnt);
+    }
+    if (p.pipe_buffer.in) {
+        ep = endnm(ctx, &sz);
+        (void)snpf(ep, sz, ", in=%d", p.pipe_buffer.in);
+    }
+    if (p.pipe_buffer.out) {
+        ep = endnm(ctx, &sz);
+        (void)snpf(ep, sz, ", out=%d", p.pipe_buffer.out);
+    }
+    /*
+     * Enter name characters.
+     */
+    if (Namech[0])
+        enter_nm(ctx, Namech);
+}
+#endif /* defined(HAS_SYS_PIPEH) */
diff --git a/lib/dialects/netbsd/dnode1.c b/lib/dialects/netbsd/dnode1.c
new file mode 100644
index 0000000..7182530
--- /dev/null
+++ b/lib/dialects/netbsd/dnode1.c
@@ -0,0 +1,91 @@
+/*
+ * dnode1.c - NetBSD 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";
+#endif
+
+#include "common.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
+#    undef i_endoff
+#    undef i_diroff
+#    undef i_offset
+
+/*
+ * 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(struct lsof_context *ctx, /* context */
+                  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(ctx, (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/lib/dialects/netbsd/dproc.c b/lib/dialects/netbsd/dproc.c
new file mode 100644
index 0000000..dc9254f
--- /dev/null
+++ b/lib/dialects/netbsd/dproc.c
@@ -0,0 +1,576 @@
+/*
+ * dproc.c - NetBSD 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";
+#endif
+
+#include "common.h"
+
+#if __NetBSD_Version__ >= 499006200
+/*
+ * In NetBSD-4.99.62, struct fdfile was added, struct filedesc::fd_ofiles
+ * changed type from struct file ** to struct fdfile **, and
+ * fd_ofileflags disappeared from struct filedesc, being
+ * replaced by fields in struct fdfile.
+ */
+#    define HAVE_STRUCT_FDFILE 1
+#    define FILESTRUCT struct fdfile
+#else
+#    undef HAVE_STRUCT_FDFILE
+#    define FILESTRUCT struct file
+#endif
+#if __NetBSD_Version__ >= 599001400
+/*
+ * Between NetBSD-5.99.13 and 5.99.14, struct fdtab was added, and
+ * struct filedesc::fd_ofiles and fd_nfiles were replaced by
+ * struct filedesc::fd_dt (a pointer to struct fdtab).
+ */
+#    define HAVE_STRUCT_FDTAB 1
+#    define NFILES(fd, dt) ((dt).dt_nfiles)
+#    define OFILES(fd, dt) ((fd).fd_dt->dt_ff)
+#else
+#    undef HAVE_STRUCT_FDTAB
+#    define NFILES(fd, dt) ((fd).fd_nfiles)
+#    define OFILES(fd, dt) ((fd).fd_ofiles)
+#endif
+
+static void enter_vn_text(struct lsof_context *ctx, KA_T va, int *n);
+static void get_kernel_access(struct lsof_context *ctx);
+static void process_text(struct lsof_context *ctx, 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(struct lsof_context *ctx, /* context */
+          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));
+        Error(ctx);
+    }
+    /*
+     * 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(struct lsof_context *ctx, /* context */
+                          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(ctx, LSOF_FD_PROGRAM_TEXT, -1);
+    Cfp = (struct file *)NULL;
+    process_node(ctx, (KA_T)va);
+    if (Lf->sf)
+        link_lfile(ctx);
+    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);
+            Error(ctx);
+        }
+    }
+    /*
+     * Remember the vnode.
+     */
+    Vp[*n] = va;
+    (*n)++;
+}
+
+/*
+ * gather_proc_info() -- gather process information
+ */
+
+void gather_proc_info(struct lsof_context *ctx) {
+    struct filedesc fd;
+    int i, nf;
+    MALLOC_S nb;
+    static FILESTRUCT **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) */
+
+#if HAVE_STRUCT_FDTAB
+    struct fdtab dt;
+#endif /* HAVE_STRUCT_FDTAB */
+
+    /*
+     * 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));
+        Error(ctx);
+    }
+    /*
+     * 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(ctx, (int)p->P_PID, (int)p->P_PGID, (UID_ARG)uid, &pss,
+                         &sf)) {
+            continue;
+        }
+        if (!p->P_FD || kread(ctx, (KA_T)p->P_FD, (char *)&fd, sizeof(fd)))
+            continue;
+        if (!fd.fd_refcnt)
+            continue;
+#if HAVE_STRUCT_FDTAB
+        if (!fd.fd_dt || kread(ctx, (KA_T)fd.fd_dt, (char *)&dt, sizeof(dt)))
+            continue;
+#endif /* ! HAVE_STRUCT_FDTAB */
+        if (fd.fd_lastfile > NFILES(fd, dt))
+            continue;
+
+#if defined(HASCWDINFO)
+        if (!p->P_CWDI || kread(ctx, (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(ctx, p->P_COMM, &pss, &sf))
+            continue;
+        alloc_lproc(ctx, (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(ctx, LSOF_FD_CWD, -1);
+            Cfp = (struct file *)NULL;
+            process_node(ctx, (KA_T)CDIR);
+            if (Lf->sf)
+                link_lfile(ctx);
+        }
+        /*
+         * Save root directory information.
+         */
+        if (RDIR) {
+            alloc_lfile(ctx, LSOF_FD_ROOT_DIR, -1);
+            Cfp = (struct file *)NULL;
+            process_node(ctx, (KA_T)RDIR);
+            if (Lf->sf)
+                link_lfile(ctx);
+        }
+
+        /*
+         * Save information on the text file.
+         */
+        if (p->P_VMSPACE)
+            process_text(ctx, (KA_T)p->P_VMSPACE);
+        /*
+         * Read open file structure pointers.
+         */
+        if (!OFILES(fd, dt) || (nf = NFILES(fd, dt)) <= 0)
+            continue;
+        nb = (MALLOC_S)(sizeof(FILESTRUCT *) * nf);
+        if (nb > ofbb) {
+            if (!ofb)
+                ofb = (FILESTRUCT **)malloc(nb);
+            else
+                ofb = (FILESTRUCT **)realloc((MALLOC_P *)ofb, nb);
+            if (!ofb) {
+                (void)fprintf(stderr, "%s: PID %d, no file * space\n", Pn,
+                              p->P_PID);
+                Error(ctx);
+            }
+            ofbb = nb;
+        }
+        if (kread(ctx, (KA_T)OFILES(fd, dt), (char *)ofb, nb))
+            continue;
+
+#if defined(HASFSTRUCT)
+        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);
+                Error(ctx);
+            }
+            pofb = nb;
+        }
+#    if !HAVE_STRUCT_FDFILE
+        if (!fd.fd_ofileflags || kread(ctx, (KA_T)fd.fd_ofileflags, pof, nb))
+            zeromem(pof, nb);
+#    endif /* ! HAVE_STRUCT_FDFILE */
+#endif     /* defined(HASFSTRUCT) */
+
+        /*
+         * Save information on file descriptors.
+         */
+        for (i = 0; i < nf; i++) {
+            if (ofb[i]) {
+#if HAVE_STRUCT_FDFILE
+                struct fdfile fdf;
+                if (kread(ctx, (KA_T)ofb[i], (char *)&fdf, sizeof(fdf)))
+                    continue;
+                Cfp = fdf.ff_file;
+                if (Cfp == NULL)
+                    continue;
+                if (pof)
+                    pof[i] = fdf.ff_exclose;
+#else  /* ! HAVE_STRUCT_FDFILE */
+                Cfp = ofb[i];
+#endif /* ! HAVE_STRUCT_FDFILE */
+                alloc_lfile(ctx, LSOF_FD_NUMERIC, i);
+                process_file(ctx, (KA_T)Cfp);
+                if (Lf->sf) {
+
+#if defined(HASFSTRUCT)
+                    Lf->pof = (long)pof[i];
+#endif /* defined(HASFSTRUCT) */
+
+                    link_lfile(ctx);
+                }
+            }
+        }
+        /*
+         * Examine results.
+         */
+        if (examine_lproc(ctx))
+            return;
+    }
+}
+
+/*
+ * get_kernel_access() - get access to kernel memory
+ */
+
+static void get_kernel_access(struct lsof_context *ctx) {
+    KA_T v;
+    /*
+     * Check kernel version.
+     */
+    (void)ckkv(ctx, "NetBSD", 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(ctx, 1))) {
+            (void)fprintf(stderr, "%s: can't get kernel name list path\n", Pn);
+            Error(ctx);
+        }
+    }
+#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(ctx);
+#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)))
+        Error(ctx);
+#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));
+        Error(ctx);
+    }
+    (void)build_Nl(ctx, Drive_Nl);
+    if (kvm_nlist(Kd, Nl) < 0) {
+        (void)fprintf(stderr, "%s: can't read namelist from %s\n", Pn, Nmlst);
+        Error(ctx);
+    }
+
+#if defined(WILLDROPGID)
+    /*
+     * Drop setgid permission, if necessary.
+     */
+    if (!Memory)
+        (void)dropgid(ctx);
+#endif /* defined(WILLDROPGID) */
+
+    /*
+     * Read the kernel's page shift amount, if possible.
+     */
+    if (get_Nl_value(ctx, "pgshift", Drive_Nl, &v) < 0 || !v ||
+        kread(ctx, (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(struct lsof_context *ctx, /* context */
+                     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);
+            Error(ctx);
+        }
+        (void)snpf(bfc, bfl, "%s", bf);
+        return (bfc);
+    }
+    return ((char *)NULL);
+}
+#endif /* !defined(N_UNIX) */
+
+/*
+ * initialize() - perform all initialization
+ */
+
+void initialize(struct lsof_context *ctx) { get_kernel_access(ctx); }
+
+/*
+ * kread() - read from kernel memory
+ */
+
+int kread(struct lsof_context *ctx, /* context */
+          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(struct lsof_context *ctx, /* context */
+                  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(ctx, 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(ctx, 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(ctx, (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(ctx, ka, (char *)&vmo, sizeof(vmo)))
+                break;
+            if (!(ka = (KA_T)vmo.pager) ||
+                kread(ctx, 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/linux/dproto.h b/lib/dialects/netbsd/dproto.h
similarity index 50%
rename from dialects/linux/dproto.h
rename to lib/dialects/netbsd/dproto.h
index 1574bbc..897b155 100644
--- a/dialects/linux/dproto.h
+++ b/lib/dialects/netbsd/dproto.h
@@ -1,12 +1,11 @@
 /*
- * dproto.h - Linux function prototypes for /proc-based lsof
+ * dproto.h - NetBSD function prototypes for lsof
  *
  * The _PROTOTYPE macro is defined in the common proto.h.
  */
 
-
 /*
- * Copyright 1997 Purdue Research Foundation, West Lafayette, Indiana
+ * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana
  * 47907.  All rights reserved.
  *
  * Written by Victor A. Abell
@@ -31,21 +30,24 @@
  * 4. This notice may not be removed or altered.
  */
 
-
 /*
- * $Id: dproto.h,v 1.9 2013/01/02 17:02:36 abe Exp $
+ * $Id: dproto.h,v 1.11 2005/08/08 19:53:24 abe Exp $
  */
 
+#if !defined(N_UNIX)
+extern char *get_nlist_path(struct lsof_context *ctx, int ap);
+#endif /* !defined(N_UNIX) */
+
+extern int is_file_named(struct lsof_context *ctx, char *p, int cd);
+extern struct l_vfs *readvfs(struct lsof_context *ctx, KA_T vm);
+
+#if defined(HAS_SYS_PIPEH)
+extern void process_pipe(struct lsof_context *ctx, KA_T pa);
+#endif /* defined(HAS_SYS_PIPEH) */
 
-#if	defined(HASSELINUX)
-_PROTOTYPE(extern int enter_cntx_arg,(char *cnxt));
-#endif	/* defined(HASSELINUX) */
+#if defined(HAS9660FS)
+extern int read_iso_node(struct lsof_context *ctx, struct vnode *v, dev_t *d,
+                         INODETYPE *ino, long *nl, SZOFFTYPE *sz);
+#endif /* defined(HAS9660FS) */
 
-_PROTOTYPE(extern int get_fields,(char *ln, char *sep, char ***fr, int *eb, int en));
-_PROTOTYPE(extern void get_locks,(char *p));
-_PROTOTYPE(extern int is_file_named,(int ty, char *p, struct mounts *mp, int cd));
-_PROTOTYPE(extern int make_proc_path,(char *pp, int lp, char **np, int *npl, char *sf));
-_PROTOTYPE(extern FILE *open_proc_stream,(char *p, char *mode, char **buf, size_t *sz, int act));
-_PROTOTYPE(extern void process_proc_node,(char *p, char *pbr, struct stat *s, int ss, struct stat *l, int ls));
-_PROTOTYPE(extern void process_proc_sock,(char *p, char *pbr, struct stat *s, int ss, struct stat *l, int ls));
-_PROTOTYPE(extern void set_net_paths,(char *p, int pl));
+extern void process_socket(struct lsof_context *ctx, KA_T sa);
diff --git a/lib/dialects/netbsd/dsock.c b/lib/dialects/netbsd/dsock.c
new file mode 100644
index 0000000..2c1aacb
--- /dev/null
+++ b/lib/dialects/netbsd/dsock.c
@@ -0,0 +1,438 @@
+/*
+ * dsock.c - NetBSD 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";
+#endif
+
+#include "common.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(struct lsof_context *ctx, /* context */
+                    KA_T sa)                  /* socket address in kernel */
+{
+#if NETBSDV >= 9099104
+#    define NETBSD_MERGED_INPCB
+#endif
+    struct domain d;
+    unsigned char *fa = (unsigned char *)NULL;
+    int fam;
+    int fp, lp;
+#ifdef NETBSD_MERGED_INPCB
+    struct in4pcb inp;
+#else
+    struct inpcb inp;
+#endif
+    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)
+#    ifdef NETBSD_MERGED_INPCB
+#        define in6p_ppcb in6p_pcb.inp_ppcb
+#    endif
+    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) */
+
+    Lf->type = LSOF_FILE_SOCKET;
+    Lf->inp_ty = 2;
+    /*
+     * Read the socket, protocol, and domain structures.
+     */
+    if (!sa) {
+        enter_nm(ctx, "no socket address");
+        return;
+    }
+    if (kread(ctx, sa, (char *)&s, sizeof(s))) {
+        (void)snpf(Namech, Namechl, "can't read socket struct from %s",
+                   print_kptr(sa, (char *)NULL, 0));
+        enter_nm(ctx, Namech);
+        return;
+    }
+    if (!s.so_type) {
+        enter_nm(ctx, "no socket type");
+        return;
+    }
+    if (!s.so_proto || kread(ctx, (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(ctx, Namech);
+        return;
+    }
+    if (!p.pr_domain || kread(ctx, (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(ctx, Namech);
+        return;
+    }
+    /*
+     * Save size information.
+     */
+    if (Lf->access == LSOF_FILE_ACCESS_READ)
+        Lf->sz = (SZOFFTYPE)s.so_rcv.sb_cc;
+    else if (Lf->access == LSOF_FILE_ACCESS_WRITE)
+        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;
+
+#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(ctx, p.pr_protocol);
+
+#if defined(HASIPv6)
+        Lf->type = (fam == AF_INET) ? LSOF_FILE_IPV4 : LSOF_FILE_IPV6;
+#else  /* !defined(HASIPv6) */
+        Lf->type = LSOF_FILE_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(ctx, (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(ctx, Namech);
+                return;
+            }
+            /*
+             * Save IPv6 address information.
+             */
+            enter_dev_ch(ctx, 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;
+#    ifdef NETBSD_MERGED_INPCB
+            la = (unsigned char *)&in6p_laddr(&in6p);
+            lp = (int)ntohs(in6p.in6p_pcb.inp_lport);
+            if (!IN6_IS_ADDR_UNSPECIFIED(&in6p_faddr(&in6p)) ||
+                (in6p.in6p_pcb.inp_fport)) {
+                fa = (unsigned char *)&in6p_faddr(&in6p);
+                fp = (int)ntohs(in6p.in6p_pcb.inp_fport);
+            }
+#    else
+            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);
+            }
+#    endif
+        } else
+#endif /* defined(HASIPv6) && defined(NETBSDV) && !defined(HASINRIAIPv6) */
+
+        {
+
+            /*
+             * Read IPv4 or IPv6 (NetBSD) protocol control block.
+             */
+            if (!s.so_pcb ||
+                kread(ctx, (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(ctx, Namech);
+                return;
+            }
+#ifdef NETBSD_MERGED_INPCB
+#    define inp_ppcb in4p_pcb.inp_ppcb
+#    define inp_lport in4p_pcb.inp_lport
+#endif
+            enter_dev_ch(
+                ctx, 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);
+#ifdef NETBSD_MERGED_INPCB
+#    undef inp_ppcb
+#    undef inp_lport
+#endif
+            if (fam == AF_INET) {
+
+                /*
+                 * Save IPv4 address information.
+                 */
+#ifdef NETBSD_MERGED_INPCB
+                la = (unsigned char *)&in4p_laddr(&inp);
+                if (in4p_faddr(&inp).s_addr != INADDR_ANY ||
+                    inp.in4p_pcb.inp_fport) {
+                    fa = (unsigned char *)&in4p_faddr(&inp);
+                    fp = (int)ntohs(inp.in4p_pcb.inp_fport);
+                }
+#else
+                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);
+                }
+#endif
+            }
+
+#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(ctx, 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(ctx, ta, (char *)&t, sizeof(t))) {
+            Lf->lts.type = 0;
+            Lf->lts.state.i = (int)t.t_state;
+
+#if defined(HASTCPOPT)
+            Lf->lts.mss = (unsigned long)t.t_ourmss;
+
+            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:
+        Lf->type = LSOF_FILE_ROUTE;
+        if (s.so_pcb)
+            enter_dev_ch(ctx, print_kptr((KA_T)(s.so_pcb), (char *)NULL, 0));
+        else
+            (void)snpf(Namech, Namechl, "no protocol control block");
+        break;
+        /*
+         * Process a Unix domain socket.
+         */
+    case AF_UNIX:
+        if (Funix)
+            Lf->sf |= SELUNX;
+        Lf->type = LSOF_FILE_UNIX;
+        /*
+         * Read Unix protocol control block and the Unix address structure.
+         */
+
+        enter_dev_ch(ctx, print_kptr(sa, (char *)NULL, 0));
+        if (kread(ctx, (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(ctx, (KA_T)unp.unp_addr, (char *)&mb, sizeof(mb)))
+#else  /* !defined(UNPADDR_IN_MBUF) */
+            if (kread(ctx, (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(ctx, (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(ctx, 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(ctx, fam, 1);
+    }
+    if (Namech[0])
+        enter_nm(ctx, Namech);
+}
diff --git a/lib/dialects/netbsd/dstore.c b/lib/dialects/netbsd/dstore.c
new file mode 100644
index 0000000..1a46015
--- /dev/null
+++ b/lib/dialects/netbsd/dstore.c
@@ -0,0 +1,135 @@
+/*
+ * dstore.c - NetBSD and 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";
+#endif
+
+#include "common.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(NETBSDV) && NETBSDV >= 9099000)
+    {
+        "rootvnode",
+        "rootvnode",
+    },
+#endif
+#if defined(NETBSDV) && NETBSDV >= 1002000
+    {
+        X_NCACHE,
+        "_nchashtbl",
+    },
+    {X_NCSIZE, "_nchash"},
+#else /* 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(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},
+#    else
+    {(long)1, 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/lib/dialects/netbsd/machine.h b/lib/dialects/netbsd/machine.h
new file mode 100644
index 0000000..3a94ef5
--- /dev/null
+++ b/lib/dialects/netbsd/machine.h
@@ -0,0 +1,575 @@
+/*
+ * machine.h - NetBSD 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
+
+#    ifdef AUTOTOOLS
+#        include "autotools.h"
+#    endif
+
+#    include <sys/types.h>
+#    include <sys/param.h>
+#    include <stdbool.h>
+#    if __NetBSD_Version__ >= 499006200
+#        define HASCWDINFO
+#    endif
+
+/*
+ * 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 access
+ * 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?	*/
+
+/*
+ * 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 */
+
+#    if defined(NETBSDV) && NETBSDV >= 9099000
+#        define USE_LIB_RNMT 1 /* rnmt.c */
+#    elif defined(NETBSDV) && NETBSDV >= 1002000
+#        define USE_LIB_RNMH 1 /* rnmh.c */
+#    else                      /* defined(NETBSDV) && NETBSDV<1002000 */
+#        define USE_LIB_RNAM 1 /* rnam.c */
+#    endif                     /* 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/lib/dialects/openbsd/Makefile b/lib/dialects/openbsd/Makefile
new file mode 100644
index 0000000..5b566fc
--- /dev/null
+++ b/lib/dialects/openbsd/Makefile
@@ -0,0 +1,158 @@
+
+# OpenBSD 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} -Iinclude -Ilib -Isrc -I.
+CFLAGS=	${CDEFS} ${INCL} ${DEBUG}
+
+GRP=
+
+HDR=    lib/common.h include/lsof_fields.h dlsof.h machine.h lib/proto.h dproto.h
+
+SRC=    dfile.c dmnt.c dnode.c dproc.c dsock.c dstore.c \
+	arg.c main.c print.c ptti.c store.c usage.c \
+	util.c
+
+OBJ=	dfile.o dmnt.o dnode.o dproc.o dsock.o dstore.o \
+	arg.o main.o print.o ptti.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_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
+
+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/lib/dialects/openbsd/Mksrc b/lib/dialects/openbsd/Mksrc
new file mode 100755
index 0000000..f12e8e8
--- /dev/null
+++ b/lib/dialects/openbsd/Mksrc
@@ -0,0 +1,32 @@
+#!/bin/sh
+#
+# Mksrc - make 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 $
+
+mksrc() {
+  for i in $L
+  do
+    rm -f $i
+    $LSOF_MKC $D/$i $i
+    echo "$LSOF_MKC $D/$i $i"
+  done
+}
+
+D=lib/dialects/openbsd
+L="dfile.c dlsof.h dmnt.c dnode.c dproc.c dproto.h dsock.c dstore.c machine.h"
+
+mksrc
+
+D=src
+L="arg.c main.c node.c print.c ptti.c store.c usage.c util.c"
+
+mksrc
diff --git a/lib/dialects/openbsd/dfile.c b/lib/dialects/openbsd/dfile.c
new file mode 100644
index 0000000..5234b0b
--- /dev/null
+++ b/lib/dialects/openbsd/dfile.c
@@ -0,0 +1,75 @@
+/*
+ * dnode.c - 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";
+#endif
+
+#include "common.h"
+
+/*
+ * process_kqueue() -- process kqueue file
+ */
+void process_kqueue_file(struct lsof_context *ctx, struct kinfo_file *file) {
+    char buf[64];
+    int flag;
+
+    /* Alloc Lf and set fd */
+    alloc_lfile(ctx, LSOF_FD_NUMERIC, file->fd_fd);
+
+    /* Fill type name*/
+    Lf->type = LSOF_FILE_KQUEUE;
+
+    /* Fill dev with f_data if available */
+    if (file->f_data) {
+        (void)snpf(buf, sizeof(buf), "0x%" PRIx64, file->f_data);
+        enter_dev_ch(ctx, buf);
+    }
+
+    /*
+     * Construct access code.
+     */
+    if ((flag = (file->f_flag & (FREAD | FWRITE))) == FREAD)
+        Lf->access = LSOF_FILE_ACCESS_READ;
+    else if (flag == FWRITE)
+        Lf->access = LSOF_FILE_ACCESS_WRITE;
+    else if (flag == (FREAD | FWRITE))
+        Lf->access = LSOF_FILE_ACCESS_READ_WRITE;
+
+    /* Finish */
+    if (Lf->sf)
+        link_lfile(ctx);
+}
+
+/*
+ * process_pipe() - process a file structure whose type is DTYPE_PIPE
+ */
+void process_pipe(struct lsof_context *ctx, struct kinfo_file *file) {}
\ No newline at end of file
diff --git a/lib/dialects/openbsd/dlsof.h b/lib/dialects/openbsd/dlsof.h
new file mode 100644
index 0000000..77346c1
--- /dev/null
+++ b/lib/dialects/openbsd/dlsof.h
@@ -0,0 +1,158 @@
+/*
+ * dlsof.h - 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(OPENBSD_LSOF_H)
+#    define OPENBSD_LSOF_H 1
+
+#    include <stdlib.h>
+#    include <inttypes.h>
+#    include <dirent.h>
+#    include <nlist.h>
+#    include <paths.h>
+#    include <setjmp.h>
+#    include <signal.h>
+#    include <string.h>
+#    include <unistd.h>
+#    include <fcntl.h>
+
+#    include <arpa/inet.h>
+#    include <sys/queue.h>
+#    include <sys/filedesc.h>
+#    include <sys/mbuf.h>
+#    include <sys/mount.h>
+#    include <rpc/types.h>
+#    include <sys/protosw.h>
+#    include <sys/socket.h>
+#    include <sys/socketvar.h>
+#    include <sys/un.h>
+#    include <sys/unpcb.h>
+#    include <net/route.h>
+#    include <netinet/in.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/tcp_fsm.h>
+#    include <netinet/tcp_timer.h>
+#    include <netinet/tcp_var.h>
+
+#    include <sys/ucred.h>
+
+#    include <sys/vnode.h>
+#    include <sys/domain.h>
+
+#    define pmap RPC_pmap
+#    include <rpc/rpc.h>
+#    include <rpc/pmap_prot.h>
+#    undef pmap
+
+#    include <sys/proc.h>
+#    include <kvm.h>
+#    include <sys/sysctl.h>
+
+#    include <sys/file.h>
+#    include <sys/fcntl.h>
+#    include <sys/lockf.h>
+
+#    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) */
+
+#    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)
+ */
+
+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 */
+};
+
+/*
+ * Definitions for rdev.c
+ */
+
+#    define DIRTYPE dirent
+#    define HASDNAMLEN 1 /* struct DIRTYPE has d_namlen element */
+
+struct lsof_context_dialect {};
+
+#endif /* OPENBSD_LSOF_H */
diff --git a/lib/dialects/openbsd/dmnt.c b/lib/dialects/openbsd/dmnt.c
new file mode 100644
index 0000000..2210b60
--- /dev/null
+++ b/lib/dialects/openbsd/dmnt.c
@@ -0,0 +1,160 @@
+/*
+ * dmnt.c - 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";
+#endif
+
+#include "common.h"
+
+/*
+ * Local static definitions
+ */
+
+/*
+ * readmnt() - read mount table
+ */
+struct mounts *readmnt(struct lsof_context *ctx) {
+    char *dn = (char *)NULL;
+    char *ln;
+    struct mounts *mtp;
+    int n;
+    struct stat sb;
+
+    struct statfs *mb = (struct statfs *)NULL;
+
+    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");
+            Error(ctx);
+        }
+        if ((ln = Readlink(ctx, 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(ctx, 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(ctx, 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(ctx, 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);
+}
diff --git a/lib/dialects/openbsd/dnode.c b/lib/dialects/openbsd/dnode.c
new file mode 100644
index 0000000..4b10651
--- /dev/null
+++ b/lib/dialects/openbsd/dnode.c
@@ -0,0 +1,159 @@
+/*
+ * dnode.c - 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";
+#endif
+
+#include "common.h"
+
+/*
+ * process_vnode() - process vnode
+ */
+void process_vnode(struct lsof_context *ctx, struct kinfo_file *file) {
+    enum lsof_fd_type fd_type;
+    int num = -1;
+    uint32_t flag;
+    int mib[3];
+    size_t size;
+    char path[PATH_MAX];
+
+    /* Alloc Lf and set fd */
+    switch (file->fd_fd) {
+    case KERN_FILE_TEXT:
+        fd_type = LSOF_FD_PROGRAM_TEXT;
+        break;
+    case KERN_FILE_CDIR:
+        fd_type = LSOF_FD_CWD;
+        break;
+    case KERN_FILE_RDIR:
+        fd_type = LSOF_FD_ROOT_DIR;
+        break;
+    default:
+        fd_type = LSOF_FD_NUMERIC;
+        num = file->fd_fd;
+        break;
+    }
+    alloc_lfile(ctx, fd_type, num);
+
+    if (file->fd_fd == KERN_FILE_CDIR) {
+        /*
+         * Save current working directory information if available
+         * sysctl(CTL_KERN, KERN_PROC_CWD, pid)
+         */
+        mib[0] = CTL_KERN;
+        mib[1] = KERN_PROC_CWD;
+        mib[2] = file->p_pid;
+        size = sizeof(path);
+        if (sysctl(mib, 3, path, &size, NULL, 0) >= 0) {
+            (void)snpf(Namech, Namechl, "%s", path);
+            enter_nm(ctx, Namech);
+        }
+    }
+
+    /*
+     * Construct access code.
+     */
+    if (file->fd_fd >= 0) {
+        if ((flag = (file->f_flag & (FREAD | FWRITE))) == FREAD)
+            Lf->access = LSOF_FILE_ACCESS_READ;
+        else if (flag == FWRITE)
+            Lf->access = LSOF_FILE_ACCESS_WRITE;
+        else if (flag == (FREAD | FWRITE))
+            Lf->access = LSOF_FILE_ACCESS_READ_WRITE;
+    }
+
+    /* Fill file size/offset */
+    if (file->v_type == VBLK || file->v_type == VCHR) {
+        /* blk/char devices have no size, only offset */
+        if (file->f_offset != (uint64_t)(-1)) {
+            Lf->off = file->f_offset;
+            Lf->off_def = 1;
+        }
+    } else {
+        Lf->off = file->f_offset;
+        Lf->off_def = 1;
+        Lf->sz = file->va_size;
+        Lf->sz_def = 1;
+    }
+
+    /* Fill inode */
+    Lf->inode = file->va_fileid;
+    Lf->inp_ty = 1;
+
+    /* Fill dev && rdef */
+    Lf->dev = file->va_fsid;
+    Lf->dev_def = 1;
+    if (file->v_type == VBLK || file->v_type == VCHR) {
+        Lf->rdev = file->va_rdev;
+        Lf->rdev_def = 1;
+    }
+
+    /* Fill type */
+    switch (file->v_type) {
+    case VREG:
+        Lf->ntype = N_REGLR;
+        Lf->type = LSOF_FILE_VNODE_VREG;
+        break;
+    case VDIR:
+        Lf->type = LSOF_FILE_VNODE_VDIR;
+        break;
+    case VCHR:
+        Lf->ntype = N_CHR;
+        Lf->type = LSOF_FILE_VNODE_VCHR;
+        break;
+    case VFIFO:
+        Lf->ntype = N_FIFO;
+        Lf->type = LSOF_FILE_VNODE_VFIFO;
+        break;
+    }
+
+    /* No way to read file path, request mount info  */
+    Lf->lmi_srch = 1;
+
+    /* Fill number of links */
+    Lf->nlink = file->va_nlink;
+    Lf->nlink_def = 1;
+
+    /* Handle link count filter */
+    if (Nlink && (Lf->nlink < Nlink))
+        Lf->sf |= SELNLINK;
+
+    /* Handle name match, must be done late, because if_file_named checks
+     * Lf->dev etc. */
+    if (is_file_named(ctx, NULL, 0)) {
+        Lf->sf |= SELNM;
+    }
+
+    /* Finish */
+    if (Lf->sf)
+        link_lfile(ctx);
+}
diff --git a/lib/dialects/openbsd/dproc.c b/lib/dialects/openbsd/dproc.c
new file mode 100644
index 0000000..5038f79
--- /dev/null
+++ b/lib/dialects/openbsd/dproc.c
@@ -0,0 +1,233 @@
+/*
+ * dproc.c - 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";
+#endif
+
+#include "common.h"
+
+static void process_kinfo_file(struct lsof_context *ctx,
+                               struct kinfo_file *file);
+
+/*
+ * Local static values
+ */
+
+/*
+ * gather_proc_info() -- gather process information
+ */
+void gather_proc_info(struct lsof_context *ctx) {
+    short pss, sf;
+    uid_t uid;
+    struct stat st;
+    int mib[6];
+    size_t size = 0;
+    int res;
+
+    struct kinfo_proc *procs = NULL;
+    struct kinfo_proc *proc;
+    int num_procs;
+    int px; /* process loop index */
+
+    struct kinfo_file *files = NULL;
+    struct kinfo_file *file;
+    int num_files;
+    int fx; /* file loop index */
+
+    char path[PATH_MAX];
+
+    /*
+     * Read the process table.
+     */
+
+    /* See OpenSBD kernel sys/kern/kern_sysctl.c sysctl_doproc */
+    /* sysctl(CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc),
+     * count) */
+    mib[0] = CTL_KERN;
+    mib[1] = KERN_PROC;
+    mib[2] = KERN_PROC_ALL;             /* op */
+    mib[3] = 0;                         /* arg */
+    mib[4] = sizeof(struct kinfo_proc); /* elem_size */
+
+    /* Loop to probe size, learned from libkvm */
+    while (1) {
+        mib[5] = 0; /* elem_count */
+
+        /* Probe number of entries */
+        if (sysctl(mib, 6, NULL, &size, NULL, 0) < 0) {
+            (void)fprintf(stderr, "%s: can't read process table: %d\n", Pn,
+                          errno);
+            Error(ctx);
+        }
+
+        /* Alloc more to handle new processes in the meantime */
+        size = (size_t)(size / sizeof(struct kinfo_proc) * 1.1) *
+               sizeof(struct kinfo_proc);
+
+        if (!procs) {
+            procs = (struct kinfo_proc *)malloc(size);
+        } else {
+            procs = (struct kinfo_proc *)realloc(procs, size);
+        }
+        if (!procs) {
+            (void)fprintf(stderr, "%s: no kinfo_proc * space\n", Pn);
+            Error(ctx);
+        }
+
+        mib[5] = size / sizeof(struct kinfo_proc); /* elem_count */
+        res = sysctl(mib, 6, procs, &size, NULL, 0);
+        if (res >= 0) {
+            num_procs = size / sizeof(struct kinfo_proc);
+            break;
+        } else if (res < 0 && errno != ENOMEM) {
+            (void)fprintf(stderr, "%s: can't read process table: %d\n", Pn,
+                          errno);
+            Error(ctx);
+        }
+    };
+
+    /*
+     * Examine proc structures and their associated information.
+     */
+
+    for (proc = procs, px = 0; px < num_procs; px++, proc++) {
+        if (proc->p_stat == 0 || proc->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 = proc->p_uid;
+        if (is_proc_excl(ctx, (int)proc->p_pid, (int)proc->p__pgid,
+                         (UID_ARG)uid, &pss, &sf)) {
+            continue;
+        }
+
+        /*
+         * Allocate a local process structure.
+         */
+        if (is_cmd_excl(ctx, proc->p_comm, &pss, &sf))
+            continue;
+        alloc_lproc(ctx, (int)proc->p_pid, (int)proc->p__pgid,
+                    (int)proc->p_ppid, (UID_ARG)uid, proc->p_comm, (int)pss,
+                    (int)sf);
+        Plf = (struct lfile *)NULL; /* Empty list head */
+
+        /*
+         * Read open file structure pointers.
+         * sysctl(CTL_KERN, KERN_FILE, KERN_FILE_BYPID, pid, sizeof(struct
+         * kinfo_file), count)
+         */
+        mib[0] = CTL_KERN;
+        mib[1] = KERN_FILE;
+        mib[2] = KERN_FILE_BYPID;
+        mib[3] = proc->p_pid;
+        mib[4] = sizeof(struct kinfo_file);
+        size = 0;
+
+        /* Loop to probe size, learned from libkvm */
+        while (1) {
+            mib[5] = 0; /* elem_count */
+
+            /* Probe number of entries */
+            if (sysctl(mib, 6, NULL, &size, NULL, 0) < 0) {
+                (void)fprintf(stderr, "%s: can't read file table: %d\n", Pn,
+                              errno);
+                Error(ctx);
+            }
+
+            /* Alloc more to handle new processes in the meantime */
+            size = (size_t)(size / sizeof(struct kinfo_file) * 1.1) *
+                   sizeof(struct kinfo_file);
+
+            if (!files) {
+                files = (struct kinfo_file *)malloc(size);
+            } else {
+                files = (struct kinfo_file *)realloc(files, size);
+            }
+            if (!files) {
+                (void)fprintf(stderr, "%s: no kinfo_file * space\n", Pn);
+                Error(ctx);
+            }
+
+            mib[5] = size / sizeof(struct kinfo_file); /* elem_count */
+            res = sysctl(mib, 6, files, &size, NULL, 0);
+            if (res >= 0) {
+                num_files = size / sizeof(struct kinfo_file);
+                break;
+            } else if (res < 0 && errno != ENOMEM) {
+                (void)fprintf(stderr, "%s: can't read file table: %d\n", Pn,
+                              errno);
+                Error(ctx);
+            }
+        };
+
+        for (file = files, fx = 0; fx < num_files; fx++, file++) {
+            process_kinfo_file(ctx, file);
+        }
+
+        /*
+         * Examine results.
+         */
+        if (examine_lproc(ctx))
+            return;
+    }
+}
+
+/*
+ * initialize() - perform all initialization
+ */
+void initialize(struct lsof_context *ctx) {}
+
+/*
+ * process_kinfo_file() - process kinfo_file
+ */
+void process_kinfo_file(struct lsof_context *ctx, struct kinfo_file *file) {
+    switch (file->f_type) {
+    case DTYPE_VNODE: /* file */
+        process_vnode(ctx, file);
+        break;
+    case DTYPE_SOCKET:
+        process_socket(ctx, file);
+        break;
+    case DTYPE_PIPE:
+        process_pipe(ctx, file);
+        break;
+    case DTYPE_KQUEUE:
+        process_kqueue_file(ctx, file);
+        break;
+    }
+}
\ No newline at end of file
diff --git a/lib/dialects/openbsd/dproto.h b/lib/dialects/openbsd/dproto.h
new file mode 100644
index 0000000..138ca13
--- /dev/null
+++ b/lib/dialects/openbsd/dproto.h
@@ -0,0 +1,43 @@
+/*
+ * dproto.h - 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 $
+ */
+
+extern int is_file_named(struct lsof_context *ctx, char *p, int cd);
+
+extern void process_vnode(struct lsof_context *ctx, struct kinfo_file *file);
+extern void process_socket(struct lsof_context *ctx, struct kinfo_file *file);
+extern void process_pipe(struct lsof_context *ctx, struct kinfo_file *file);
+extern void process_kqueue_file(struct lsof_context *ctx,
+                                struct kinfo_file *file);
diff --git a/lib/dialects/openbsd/dsock.c b/lib/dialects/openbsd/dsock.c
new file mode 100644
index 0000000..c492c12
--- /dev/null
+++ b/lib/dialects/openbsd/dsock.c
@@ -0,0 +1,187 @@
+/*
+ * dsock.c - 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";
+#endif
+
+#include "common.h"
+
+/*
+ * process_socket() - process socket
+ */
+void process_socket(struct lsof_context *ctx, struct kinfo_file *file) {
+    char *proto = NULL;
+    char *type = NULL;
+    char buf[64];
+    int flag;
+    uint32_t lport, fport;
+
+    /* Alloc Lf and set fd */
+    alloc_lfile(ctx, LSOF_FD_NUMERIC, file->fd_fd);
+
+    /* Type name */
+    switch (file->so_family) {
+    case AF_INET:
+        Lf->type = LSOF_FILE_IPV4;
+        break;
+    case AF_INET6:
+        Lf->type = LSOF_FILE_IPV6;
+        break;
+    case AF_UNIX:
+        Lf->type = LSOF_FILE_UNIX;
+        break;
+    case AF_ROUTE:
+        Lf->type = LSOF_FILE_ROUTE;
+        break;
+    }
+
+    /*
+     * Construct access code.
+     */
+    if (file->fd_fd >= 0) {
+        if ((flag = (file->f_flag & (FREAD | FWRITE))) == FREAD)
+            Lf->access = LSOF_FILE_ACCESS_READ;
+        else if (flag == FWRITE)
+            Lf->access = LSOF_FILE_ACCESS_WRITE;
+        else if (flag == (FREAD | FWRITE))
+            Lf->access = LSOF_FILE_ACCESS_READ_WRITE;
+    }
+
+    /* Fill iproto */
+    switch (file->so_type) {
+    case SOCK_STREAM:
+        proto = "TCP";
+        break;
+    case SOCK_DGRAM:
+        proto = "UDP";
+        break;
+    case SOCK_RAW:
+        proto = "RAW";
+        break;
+    }
+    if (proto) {
+        (void)snpf(Lf->iproto, sizeof(Lf->iproto), "%s", proto);
+        Lf->inp_ty = 2;
+    }
+
+    if (file->so_family == AF_INET || file->so_family == AF_INET6) {
+        /* Show this entry if -i */
+        if (Fnet) {
+            /* Handle v4/v6 only */
+            if (FnetTy == 4 && file->so_family == AF_INET) {
+                Lf->sf |= SELNET;
+            } else if (FnetTy == 6 && file->so_family == AF_INET6) {
+                Lf->sf |= SELNET;
+            } else if (FnetTy == 0) {
+                Lf->sf |= SELNET;
+            }
+        }
+
+        /* Fill internet address info */
+        lport = ntohs(file->inp_lport);
+        fport = ntohs(file->inp_fport);
+        if (file->inp_fport) {
+            ent_inaddr(ctx, (unsigned char *)file->inp_laddru, lport,
+                       (unsigned char *)file->inp_faddru, fport,
+                       file->so_family);
+        } else {
+            /* No foreign address on LISTEN sockets */
+            ent_inaddr(ctx, (unsigned char *)file->inp_laddru, lport, NULL, 0,
+                       file->so_family);
+        }
+
+        /* Fill TCP state */
+        if (file->so_type == SOCK_STREAM) {
+            Lf->lts.type = 0;
+            Lf->lts.state.i = file->t_state;
+        }
+
+        /* Fill dev with pcb if available */
+        if (file->inp_ppcb) {
+            (void)snpf(buf, sizeof(buf), "0x%" PRIx64, file->inp_ppcb);
+            enter_dev_ch(ctx, buf);
+        } else if (file->so_pcb && file->so_pcb != (uint64_t)(-1)) {
+            /* when running as non-root, -1 means not NULL */
+            (void)snpf(buf, sizeof(buf), "0x%" PRIx64, file->so_pcb);
+            enter_dev_ch(ctx, buf);
+        }
+    } else if (file->so_family == AF_UNIX) {
+        /* Show this entry if requested */
+        /* Via -U */
+        if (Funix)
+            Lf->sf |= SELUNX;
+        /* Name matches */
+        if (is_file_named(ctx, file->unp_path, 0)) {
+            Lf->sf |= SELNM;
+        }
+
+        /* Fill name */
+        switch (file->so_type) {
+        case SOCK_STREAM:
+            type = "STREAM";
+            break;
+        case SOCK_DGRAM:
+            type = "DGRAM";
+            break;
+        default:
+            type = "UNKNOWN";
+            break;
+        }
+
+        (void)snpf(Namech, Namechl, "%s%stype=%s",
+                   file->unp_path[0] ? file->unp_path : "",
+                   file->unp_path[0] ? " " : "", type);
+        (void)enter_nm(ctx, Namech);
+
+        /* Fill TCP state */
+        if (file->so_type == SOCK_STREAM) {
+            Lf->lts.type = 0;
+            Lf->lts.state.i = file->t_state;
+        }
+
+        /* Fill dev with so_pcb if available */
+        if (file->so_pcb && file->so_pcb != (uint64_t)(-1)) {
+            (void)snpf(buf, sizeof(buf), "0x%" PRIx64, file->so_pcb);
+            enter_dev_ch(ctx, buf);
+        }
+    } else if (file->so_family == AF_ROUTE) {
+        /* Fill dev with f_data if available */
+        if (file->f_data) {
+            (void)snpf(buf, sizeof(buf), "0x%" PRIx64, file->f_data);
+            enter_dev_ch(ctx, buf);
+        }
+    }
+
+    /* Finish */
+    if (Lf->sf)
+        link_lfile(ctx);
+}
diff --git a/lib/dialects/openbsd/dstore.c b/lib/dialects/openbsd/dstore.c
new file mode 100644
index 0000000..d3ecc50
--- /dev/null
+++ b/lib/dialects/openbsd/dstore.c
@@ -0,0 +1,90 @@
+/*
+ * dstore.c - 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";
+#endif
+
+#include "common.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},
+
+#    if defined(FDSYNC)
+    {(long)FDSYNC, FF_DSYNC},
+#    endif /* defined*FDSYNC) */
+
+    {(long)FFSYNC, FF_FSYNC},
+
+#    if defined(FRSYNC)
+    {(long)FRSYNC, FF_RSYNC},
+#    endif /* defined(FRSYNC) */
+
+#    if defined(FMARK)
+    {(long)FMARK, FF_MARK},
+#    endif /* defined(FMARK) */
+
+#    if defined(FDEFER)
+    {(long)FDEFER, FF_DEFER},
+#    endif /* defined(FDEFER) */
+
+#    if defined(FHASLOCK)
+    {(long)FHASLOCK, FF_HASLOCK},
+#    endif /* defined(FHASLOCK) */
+    {(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},
+#    else
+    {(long)1, 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/lib/dialects/openbsd/machine.h b/lib/dialects/openbsd/machine.h
new file mode 100644
index 0000000..8395181
--- /dev/null
+++ b/lib/dialects/openbsd/machine.h
@@ -0,0 +1,564 @@
+/*
+ * machine.h - 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
+
+#    ifdef AUTOTOOLS
+#        include "autotools.h"
+#    endif
+
+#    include <sys/types.h>
+#    include <sys/param.h>
+#    include <stdbool.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	??? */
+/* #define	NCACHELDPFX	??? */
+/* #define	NCACHELDSFX	??? */
+
+/*
+ * HASNLIST is defined for those dialects that use nlist() to access
+ * 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?	*/
+
+/*
+ * 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
+
+/* #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_RNMT			1	   rnmt.c */
+/* #define	USE_LIB_RNMH			1	   rnmh.c */
+/* #define	USE_LIB_RNAM			1	   rnam.c */
+
+/* #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/lib/dialects/openbsd/tests/case-00-openbsd-hello.bash b/lib/dialects/openbsd/tests/case-00-openbsd-hello.bash
new file mode 100755
index 0000000..ca916d0
--- /dev/null
+++ b/lib/dialects/openbsd/tests/case-00-openbsd-hello.bash
@@ -0,0 +1 @@
+exit 0
diff --git a/lib/dialects/sun/Makefile b/lib/dialects/sun/Makefile
new file mode 100644
index 0000000..c3e0cd4
--- /dev/null
+++ b/lib/dialects/sun/Makefile
@@ -0,0 +1,159 @@
+
+# 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_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/lib/dialects/sun/Mksrc b/lib/dialects/sun/Mksrc
new file mode 100755
index 0000000..78ad256
--- /dev/null
+++ b/lib/dialects/sun/Mksrc
@@ -0,0 +1,27 @@
+#!/bin/bash
+#
+# 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 $
+
+mksrc() {
+  for i in $L
+  do
+    rm -f $i
+    $LSOF_MKC $D/$i $i
+    echo "$LSOF_MKC $D/$i $i"
+  done
+}
+
+D=lib/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"
+
+mksrc
diff --git a/lib/dialects/sun/ddev.c b/lib/dialects/sun/ddev.c
new file mode 100644
index 0000000..53265a0
--- /dev/null
+++ b/lib/dialects/sun/ddev.c
@@ -0,0 +1,1086 @@
+/*
+ * 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";
+#endif
+
+#include "common.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
+ */
+
+static void make_devtp(struct lsof_context *ctx, struct stat *s, char *p);
+static int rmdupdev(struct lsof_context *ctx, struct l_dev ***dp, int n,
+                    int ty);
+
+/*
+ * make_devtp() - make Devtp[] entry
+ */
+
+static void make_devtp(struct lsof_context *ctx, /* context */
+                       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);
+            Error(ctx);
+        }
+    }
+    /*
+     * 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);
+        Error(ctx);
+    }
+    Devtp[Devx].rdev = s->st_rdev;
+    Devtp[Devx].v = 0;
+    Devx++;
+}
+
+/*
+ * printdevname() - print block or character device name
+ */
+
+int printdevname(struct lsof_context *ctx, /* context */
+                 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(ctx, 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(ctx, dev, rdev, 1, 0);
+    else
+#endif /* defined(HASBLKDEV) */
+
+        dp = lkupdev(ctx, 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(ctx, &DevDev, rdev, 0, 0);
+    else
+#endif /* defined(HASBLKDEV) */
+
+        dp = lkupdev(ctx, &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);
+            Error(ctx);
+        }
+        (void)snpf(cp, len + 1, "(%s %s)", ttl, dp->name);
+        (void)add_nma(ctx, 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(ctx, &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(ctx, &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(ctx);
+        goto printchdevname_again;
+    }
+#endif /* defined(HASDCACHE) */
+
+    return (0);
+}
+
+/*
+ * read_clone() - read Solaris clone device information
+ */
+
+void read_clone(struct lsof_context *ctx) {
+    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);
+        Error(ctx);
+    }
+    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);
+            Error(ctx);
+        }
+
+#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(ctx, &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);
+                Error(ctx);
+            }
+            /*
+             * 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);
+                Error(ctx);
+            }
+            /*
+             * 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);
+                Error(ctx);
+            }
+            /*
+             * 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(struct lsof_context *ctx, /* context */
+             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(ctx)) == 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);
+        Error(ctx);
+    }
+    read_clone(ctx);
+    Dstk = (char **)NULL;
+    Dstkn = Dstkx = 0;
+    (void)stkdir(ctx, 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);
+            Error(ctx);
+        }
+        (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);
+                Error(ctx);
+            }
+
+#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(ctx, fp);
+                continue;
+            }
+            if ((sb.st_mode & S_IFMT) == S_IFCHR) {
+
+                /*
+                 * Make Devtp[] entry.
+                 */
+                make_devtp(ctx, &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);
+                        Error(ctx);
+                    }
+                }
+                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);
+            Error(ctx);
+        }
+        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(ctx, &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);
+            Error(ctx);
+        }
+        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(ctx, &Sdev, Ndev, 1);
+    } else {
+        (void)fprintf(stderr, "%s: no character devices found\n", Pn);
+        Error(ctx);
+    }
+
+#if defined(HASDCACHE)
+    /*
+     * Write device cache file, as required.
+     */
+    if (DCstate == 1 || (DCstate == 3 && dcrd))
+        write_dcache(ctx);
+#endif /* defined(HASDCACHE) */
+}
+
+/*
+ * clr_sect() - clear cached clone and pseudo sections
+ */
+
+void clr_sect(struct lsof_context *ctx) {
+    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(struct lsof_context *ctx,
+                  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);
+                Error(ctx);
+            }
+            /*
+             * 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);
+                Error(ctx);
+            }
+            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(ctx, 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(ctx, 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);
+    Error(ctx);
+    return (1); /* to make code analyzers happy */
+}
+
+/*
+ * rereaddev() - reread device names, modes and types
+ */
+
+void rereaddev(struct lsof_context *ctx) {
+    (void)clr_devtab(ctx);
+    (void)clr_sect(ctx);
+    Devx = 0;
+
+#    if defined(DCACHE_CLR)
+    (void)DCACHE_CLR(ctx);
+#    endif /* defined(DCACHE_CLR) */
+
+    readdev(ctx, 1);
+    DCunsafe = 0;
+}
+
+/*
+ * rw_pseudo_sect() - read/write the device cache pseudo section
+ */
+
+int rw_pseudo_sect(struct lsof_context *ctx,
+                   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);
+                Error(ctx);
+            }
+            /*
+             * 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);
+                Error(ctx);
+            }
+            *(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(ctx, 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(ctx, 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(struct lsof_context *ctx, /* context */
+            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(ctx);
+        return (0);
+    }
+    dp->v = 1;
+    return (1);
+}
+#endif /* defined(HASDCACHE) */
+
+/*
+ * rmdupdev() - remove duplicate (major/minor/inode) devices
+ */
+
+static int rmdupdev(struct lsof_context *ctx, /* context */
+                    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");
+        Error(ctx);
+    }
+    return (j);
+}
diff --git a/lib/dialects/sun/dfile.c b/lib/dialects/sun/dfile.c
new file mode 100644
index 0000000..c047bb6
--- /dev/null
+++ b/lib/dialects/sun/dfile.c
@@ -0,0 +1,590 @@
+/*
+ * 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";
+#endif
+
+#include "common.h"
+
+/*
+ * Local structures
+ */
+
+/*
+ * Local static variables
+ */
+
+/*
+ * 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(struct lsof_context *ctx) {
+    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);
+            Error(ctx);
+        }
+    }
+    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);
+        Error(ctx);
+    }
+    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);
+        Error(ctx);
+    }
+    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);
+        Error(ctx);
+    }
+    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);
+        Error(ctx);
+    }
+    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);
+                    Error(ctx);
+                }
+                sn->s = s;
+                sn->next = sh->next;
+                sh->next = sn;
+            }
+        }
+    }
+}
+
+/*
+ * is_file_named() - is this file named?
+ */
+
+int is_file_named(struct lsof_context *ctx, /* context */
+                  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(ctx, &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(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(struct lsof_context *ctx,
+                        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(ctx, (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(ctx, 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(struct lsof_context *ctx,
+                        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(ctx, 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(ctx, 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(struct lsof_context *ctx, /* context */
+                  KA_T fp)                  /* kernel file structure address */
+{
+    struct file f;
+    int flag;
+
+#if defined(FILEPTR)
+    FILEPTR = &f;
+#endif /* defined(FILEPTR) */
+
+    if (kread(ctx, fp, (char *)&f, sizeof(f))) {
+        (void)snpf(Namech, Namechl, "can't read file struct from %s",
+                   print_kptr(fp, (char *)NULL, 0));
+        enter_nm(ctx, Namech);
+        return;
+    }
+    Lf->off = (SZOFFTYPE)f.f_offset;
+    Lf->off_def = 1;
+
+    if (f.f_count) {
+
+        /*
+         * Construct access code.
+         */
+        if ((flag = (f.f_flag & (FREAD | FWRITE))) == FREAD)
+            Lf->access = LSOF_FILE_ACCESS_READ;
+        else if (flag == FWRITE)
+            Lf->access = LSOF_FILE_ACCESS_WRITE;
+        else if (flag == (FREAD | FWRITE))
+            Lf->access = LSOF_FILE_ACCESS_READ_WRITE;
+
+#if defined(HASFSTRUCT)
+        /*
+         * Save file structure values.
+         */
+        Lf->fct = (long)f.f_count;
+        Lf->fsv |= FSV_CT;
+        Lf->fsa = fp;
+        Lf->fsv |= FSV_FA;
+        Lf->ffg = (long)f.f_flag;
+        Lf->fsv |= FSV_FG;
+        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(ctx, (KA_T)f.f_vnode);
+        return;
+    }
+    enter_nm(ctx, "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/lib/dialects/sun/distfile.kvm b/lib/dialects/sun/distfile.kvm
new file mode 100644
index 0000000..9559172
--- /dev/null
+++ b/lib/dialects/sun/distfile.kvm
@@ -0,0 +1,14 @@
+# $Id: distfile.kvm,v 1.1 94/05/03 16:04:00 abe Exp $
+#
+# distfile.kvm -- an assist to distributing SunOS objects that use -lkvm
+#
+# This distfile allows Sun4 systems to limit distribution of object files
+# to systems of like architecture, using the source architecture definition
+# in SKVM and the destination architecture definition in KVM.
+#
+# The path of the object to be distributed is defined in OBJPATH.
+
+ifelse(SKVM,KVM,
+`( OBJPATH ) -> ( HOST )
+	install -b ;
+')dnl
diff --git a/lib/dialects/sun/dlsof.h b/lib/dialects/sun/dlsof.h
new file mode 100644
index 0000000..17725a7
--- /dev/null
+++ b/lib/dialects/sun/dlsof.h
@@ -0,0 +1,697 @@
+/*
+ * 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
+#            define fls __kernel_fls
+#            define exit __kernel_exit
+#        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
+#            undef fls
+#            undef exit
+#        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>
+#        if solaris >= 110000
+#            define _KERNEL
+#            if defined(HAS_SYS_RGM_H)
+#                include <sys/rgm.h>
+#            endif /* defined(HAS_SYS_RGM_H) */
+#            if defined(HAS_RPC_RPC_TAGS_H)
+#                include <rpc/rpc_tags.h>
+#            endif /* defined(HAS_RPC_RPC_TAGS_H) */
+#            undef _KERNEL
+#        endif /* solaris>=110000 */
+#        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(ctx, (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) */
+
+struct lsof_context_dialect {};
+
+#endif /* SOLARIS_LSOF_H */
diff --git a/lib/dialects/sun/dmnt.c b/lib/dialects/sun/dmnt.c
new file mode 100644
index 0000000..de1128b
--- /dev/null
+++ b/lib/dialects/sun/dmnt.c
@@ -0,0 +1,396 @@
+/*
+ * 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";
+#endif
+
+#include "common.h"
+
+/*
+ * Local static definitions
+ */
+
+static char *getmntdev(struct lsof_context *ctx, char *o, int l, struct stat *s,
+                       char *f);
+
+/*
+ * getmntdev() - get mount entry's device number
+ */
+
+static char *getmntdev(struct lsof_context *ctx, /* context */
+                       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(struct lsof_context *ctx) {
+    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");
+            Error(ctx);
+        }
+        if (!(ln = Readlink(ctx, 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(ctx, dopt, devl, &sb,
+
+#if defined(HASFSTYPE)
+                                             mp->mnt_fstype
+#else  /* !defined(HASFSTYPE) */
+                                             (char *)NULL
+#endif /* defined(HASFSTYPE) */
+
+                                             )))
+                continue;
+            stat = 1;
+        } else if (statsafely(ctx, dn, &sb)) {
+            if (dopt) {
+                if (!(dopte = getmntdev(ctx, 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(ctx, 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(ctx, 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(struct lsof_context *ctx, /* context */
+                      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);
+        Error(ctx);
+    }
+    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(ctx, (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(ctx);
+        v->vfs_dev = AFSdevStat ? AFSdev : 0;
+    }
+#endif /* defined(HAS_AFS) */
+
+    /*
+     * Complete mount information.
+     */
+
+    (void)completevfs(ctx, vp, (dev_t *)&v->vfs_dev);
+    vp->next = Lvfs;
+    vp->addr = ka;
+    Lvfs = vp;
+    return (vp);
+}
diff --git a/lib/dialects/sun/dnode.c b/lib/dialects/sun/dnode.c
new file mode 100644
index 0000000..2696571
--- /dev/null
+++ b/lib/dialects/sun/dnode.c
@@ -0,0 +1,5268 @@
+/*
+ * 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";
+#endif
+
+#include "common.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/%s/genunix"
+#    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
+ */
+
+static int read_nsti(struct lsof_context *ctx, 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
+ */
+
+static int read_nzn(struct lsof_context *ctx, KA_T na, KA_T nza, znode_t *z);
+static int read_nznp(struct lsof_context *ctx, KA_T nza, KA_T nzpa,
+                     znode_phys_t *zp);
+static int read_nzvfs(struct lsof_context *ctx, KA_T nza, KA_T nzva,
+                      zfsvfs_t *zv);
+#endif /* defined(HAS_ZFS) && defined(HAS_LIBCTF) */
+
+static struct l_dev *finddev(struct lsof_context *ctx, 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
+ */
+
+static void build_Voptab(struct lsof_context *ctx);
+static enum lsof_lock_mode isvlocked(struct lsof_context *ctx,
+                                     struct vnode *va);
+static int readinode(struct lsof_context *ctx, KA_T ia, struct inode *i);
+static void read_mi(struct lsof_context *ctx, 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
+static int read_nan(struct lsof_context *ctx, KA_T na, KA_T aa,
+                    struct fnnode *rn);
+static int read_nson(struct lsof_context *ctx, KA_T na, KA_T sa,
+                     struct sonode *sn);
+static int read_nusa(struct lsof_context *ctx, struct soaddr *so,
+                     struct sockaddr_un *ua);
+#    else  /* solaris<20600 */
+static int read_nan(struct lsof_context *ctx, KA_T na, KA_T aa,
+                    struct autonode *a);
+#    endif /* solaris>=20600 */
+static int idoorkeep(struct lsof_context *ctx, struct door_node *d);
+static int read_ndn(struct lsof_context *ctx, KA_T na, KA_T da,
+                    struct door_node *d);
+#endif /* solaris>=20500 */
+
+#if solaris >= 110000
+static int read_nsdn(struct lsof_context *ctx, KA_T na, KA_T sa,
+                     struct sdev_node *sdn, struct vattr *sdva);
+#endif /* solaris>=110000 */
+
+static int read_nfn(struct lsof_context *ctx, KA_T na, KA_T fa,
+                    struct fifonode *f);
+static int read_nhn(struct lsof_context *ctx, KA_T na, KA_T ha,
+                    struct hsnode *h);
+static int read_nin(struct lsof_context *ctx, KA_T na, KA_T ia,
+                    struct inode *i);
+static int read_nmn(struct lsof_context *ctx, KA_T na, KA_T ia,
+                    struct mvfsnode *m);
+static int read_npn(struct lsof_context *ctx, KA_T na, KA_T pa,
+                    struct pcnode *p);
+static int read_nrn(struct lsof_context *ctx, KA_T na, KA_T ra,
+                    struct rnode *r);
+
+#if solaris >= 100000
+static int read_nctfsn(struct lsof_context *ctx, int ty, KA_T na, KA_T ca,
+                       char *cn);
+static int read_nprtn(struct lsof_context *ctx, KA_T na, KA_T ra, port_t *p);
+static int read_nrn4(struct lsof_context *ctx, KA_T na, KA_T ra,
+                     struct rnode4 *r);
+#endif /* solaris>=100000 */
+
+static int read_nsn(struct lsof_context *ctx, KA_T na, KA_T sa,
+                    struct snode *s);
+static int read_ntn(struct lsof_context *ctx, KA_T na, KA_T ta,
+                    struct tmpnode *t);
+static int read_nvn(struct lsof_context *ctx, KA_T na, KA_T va,
+                    struct vnode *v);
+
+#if defined(HASPROCFS)
+static int read_npi(struct lsof_context *ctx, KA_T na, struct vnode *v,
+                    struct pid *pids);
+#endif /* defined(HASPROCFS) */
+
+static char *ent_fa(KA_T *a1, KA_T *a2, char *d, int *len);
+static int is_socket(struct lsof_context *ctx, struct vnode *v);
+static int read_cni(struct lsof_context *ctx, struct snode *s, struct vnode *rv,
+                    struct vnode *v, struct snode *rs, struct dev_info *di,
+                    char *din, int dinl);
+
+#if defined(HASCACHEFS)
+static int read_ncn(struct lsof_context *ctx, KA_T na, KA_T ca,
+                    struct cnode *cn);
+#endif /* defined(HASCACHEFS) */
+
+static int read_nln(struct lsof_context *ctx, KA_T na, KA_T la,
+                    struct lnode *ln);
+static int read_nnn(struct lsof_context *ctx, KA_T na, KA_T nna,
+                    struct namenode *n);
+
+#if solaris < 100000
+static void savesockmod(struct so_so *so, struct so_so *sop, int *so_st);
+#else  /* solaris>=100000 */
+static int read_ndvn(struct lsof_context *ctx, 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(ctx, name, nl, &ops) < 0)                                  \
+            ops = (KA_T)0;                                                     \
+        else if (kread(ctx, ops, (char *)&ops, sizeof(ops)))                   \
+        ops = (KA_T)0
+#else /* !defined(VOPNAME_OPEN) || solaris<100000 */
+#    define GETVOPS(name, nl, ops)                                             \
+        if (get_Nl_value(ctx, 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(struct lsof_context *ctx) {
+    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);
+        Error(ctx);
+    }
+    if (!(FxToVoptab =
+              (v_optab_t **)calloc((MALLOC_S)Fsinfomax, sizeof(v_optab_t *)))) {
+        (void)fprintf(stderr, "%s: no space for FxToVoptab\n", Pn);
+        Error(ctx);
+    }
+    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);
+            Error(ctx);
+        }
+        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(struct lsof_context *ctx, /* context*/
+               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(struct lsof_context *ctx, /* context */
+              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));
+            Error(ctx);
+        }
+        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(ctx, 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));
+        Error(ctx);
+    }
+    for (err = 0; r->name; r++) {
+        if (CTF_getmem(ctx, f, kmp, r->name, r->mem))
+            err = 1;
+    }
+    (void)ctf_close(f);
+    if (err)
+        Error(ctx);
+    *i = 1;
+}
+
+/*
+ * CTF_memCB() - Callback function for ctf_member_iter()
+ */
+
+int CTF_memCB(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(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(struct lsof_context *ctx, /* context */
+                     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(ctx, (KA_T)v->v_stream, tcpudp[i].proto);
+            return (1);
+        }
+    }
+    return (0);
+}
+
+/*
+ * isvlocked() - is Solaris vnode locked?
+ */
+
+static enum lsof_lock_mode isvlocked(struct lsof_context *ctx, /* context */
+                                     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 LSOF_LOCK_NONE;
+
+#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(ctx, fp, (char *)&f, sizeof(f)))
+                return LSOF_LOCK_NONE;
+            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 ? LSOF_LOCK_READ_FULL : LSOF_LOCK_READ_PARTIAL;
+            case F_WRLCK:
+                return l ? LSOF_LOCK_WRITE_FULL : LSOF_LOCK_WRITE_PARTIAL;
+            case F_RDLCK | F_WRLCK:
+                return LSOF_LOCK_READ_WRITE;
+            default:
+                return LSOF_LOCK_SOLARIS_NFS;
+            }
+        } 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(ctx, lp, (char *)&ld, sizeof(ld)))
+            return LSOF_LOCK_NONE;
+        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 ? LSOF_LOCK_READ_FULL : LSOF_LOCK_READ_PARTIAL;
+        case F_WRLCK:
+            return l ? LSOF_LOCK_WRITE_FULL : LSOF_LOCK_WRITE_PARTIAL;
+        case (F_RDLCK | F_WRLCK):
+            return LSOF_LOCK_READ_WRITE;
+        default:
+            /* It was 'L' since 1997, dunno what is it */
+            return LSOF_LOCK_UNKNOWN;
+        }
+    } while ((lp = (KA_T)LOCK_NEXT) && (lp != lf) && (i < 10000));
+    return LSOF_LOCK_NONE;
+#endif /* solaris>=20300 */
+}
+
+/*
+ * finddev() - look up device by device number
+ */
+
+static struct l_dev *finddev(struct lsof_context *ctx, /* context */
+                             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(ctx, 0);
+        /*
+         * Search device table for match.
+         */
+
+#if defined(HASDCACHE)
+
+finddev_again:
+
+#endif /* defined(HASDCACHE) */
+
+    if (flags & LOOKDEV_TAB) {
+        if ((dp = lkupdev(ctx, 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(ctx, &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(ctx, &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(struct lsof_context *ctx, /* context */
+                     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(ctx, (KA_T)d->door_target, (char *)&dp, sizeof(dp)))
+        return (0);
+    if (!dp.p_pidp || kread(ctx, (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(ctx, buf, (int)strlen(buf));
+    return (1);
+}
+#endif /* solaris>=20500 */
+
+/*
+ * process_node() - process vnode
+ */
+
+void process_node(struct lsof_context *ctx, /* context */
+                  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;
+    char fd[FDLEN];
+
+#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(ctx);
+        ft = 0;
+    }
+    /*
+     * Read the vnode.
+     */
+    if (!va) {
+        enter_nm(ctx, "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) */
+
+            );
+            Error(ctx);
+        }
+    }
+    if (readvnode(ctx, va, v)) {
+        enter_nm(ctx, 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(ctx, v))
+        return;
+    /*
+     * Obtain the Solaris virtual file system structure.
+     */
+    if ((ka = (KA_T)v->v_vfsp)) {
+        if (kread(ctx, 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(ctx, 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(ctx, 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(ctx, 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(ctx, 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(ctx, (KA_T)nn.nm_filevp, (char *)&rv, sizeof(rv))) {
+            rvs = 1;
+            if ((ka = (KA_T)rv.v_vfsp) &&
+                !kread(ctx, 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(ctx, &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(ctx, 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(ctx, 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(ctx, va, (KA_T)v->v_data, &s))
+            return;
+        realvp = (KA_T)s.s_realvp;
+        if (!realvp && s.s_commonvp) {
+            if (read_cni(ctx, &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(ctx, vs, (dev_t *)&s.s_dev, (caddr_t)&soso, &so_st,
+                        so_ad, &sdp);
+#else  /* solaris>=100000 */
+                read_mi(ctx, 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(ctx, va, v, &an))
+            return;
+        break;
+#endif /* defined(HAS_AFS) */
+
+#if solaris >= 20500
+    case N_AUTO:
+
+#    if solaris < 20600
+        if (read_nan(ctx, va, (KA_T)v->v_data, &au))
+#    else  /* solaris>=20600 */
+        if (read_nan(ctx, va, (KA_T)v->v_data, &fnn))
+#    endif /* solaris<20600 */
+
+            return;
+        break;
+
+#    if solaris >= 100000
+    case N_DEV:
+        if (read_ndvn(ctx, va, (KA_T)v->v_data, &dv, &dv_dev, &dv_devs))
+            return;
+        dvs = 1;
+        break;
+#    endif /* solaris>=100000 */
+
+    case N_DOOR:
+        if (read_ndn(ctx, va, (KA_T)v->v_data, &dn))
+            return;
+        dns = 1;
+        break;
+#endif /* solaris>=20500 */
+
+#if defined(HASCACHEFS)
+    case N_CACHE:
+        if (read_ncn(ctx, 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(ctx, 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(ctx, 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(ctx, va, (KA_T)v->v_data, &m))
+            return;
+        break;
+    case N_NFS:
+        if (read_nrn(ctx, va, (KA_T)v->v_data, &r))
+            return;
+        break;
+
+#if solaris >= 100000
+    case N_NFS4:
+        if (read_nrn4(ctx, 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(ctx, 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(ctx, 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(ctx, 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(ctx, tbuf, tbufx);
+            break;
+        }
+        break;
+
+    case N_HSFS:
+        if (read_nhn(ctx, va, (KA_T)v->v_data, &h))
+            return;
+        break;
+    case N_LOFS:
+        llc = 0;
+        do {
+            rvs = 0;
+            if (read_nln(ctx, 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(ctx, Namech);
+                return;
+            }
+            if (read_nvn(ctx, (KA_T)v->v_data, (KA_T)realvp, &rv))
+                return;
+            rvs = 1;
+            llc++;
+            if ((ka = (KA_T)rv.v_vfsp) &&
+                !kread(ctx, ka, (char *)&rkv, sizeof(rkv)) &&
+                ((rfx = rkv.vfs_fstype - 1) >= 0) && (rfx < Fsinfomax)) {
+                rfxs = 1;
+            } else {
+                rfx = fx;
+                rfxs = fxs;
+            }
+            if (((vty_tmp = vop2ty(ctx, &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(ctx, Namech);
+                return;
+            }
+        } while (vty_tmp == N_LOFS);
+        break;
+    case N_PCFS:
+        if (read_npn(ctx, va, (KA_T)v->v_data, &pc))
+            return;
+        break;
+
+#if solaris >= 100000
+    case N_PORT:
+        if (read_nprtn(ctx, va, (KA_T)v->v_data, &pn))
+            return;
+        break;
+#endif /* solaris>=100000 */
+
+#if defined(HASPROCFS)
+    case N_PROC:
+        if (read_npi(ctx, va, v, &pids))
+            return;
+        break;
+#endif /* defined(HASPROCFS) */
+
+#if solaris >= 110000
+    case N_SDEV:
+        if (read_nsdn(ctx, va, (KA_T)v->v_data, &sdn, &sdva))
+            return;
+        sdns = 1;
+        break;
+#endif /* solaris>=110000 */
+
+    case N_SAMFS:
+        (void)add_nma(ctx, 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(ctx, va, (KA_T)v->v_data, &s))
+            return;
+        if (vs) {
+            Lf->is_stream = 1;
+
+#if solaris < 100000
+            read_mi(ctx, vs, (dev_t *)&s.s_dev, (caddr_t)&soso, &so_st, so_ad,
+                    &sdp);
+#else  /* solaris>=100000 */
+            read_mi(ctx, vs, (dev_t *)&s.s_dev, NULL, NULL, NULL, &sdp);
+#endif /* solaris<100000 */
+
+            vs = (KA_T)NULL;
+        }
+        break;
+    case N_TMP:
+        if (read_ntn(ctx, va, (KA_T)v->v_data, &t))
+            return;
+        break;
+
+#if defined(HASVXFS)
+    case N_VXFS:
+        if (read_vxnode(ctx, va, v, vfs, fx, &vx, Vvops))
+            return;
+        break;
+#endif /* defined(HASVXFS) */
+
+#if defined(HAS_ZFS)
+    case N_ZFS:
+        if (read_nzn(ctx, va, (KA_T)v->v_data, &zn))
+            return;
+        zns = 1;
+        break;
+#endif /* defined(HAS_ZFS) */
+
+    case N_REGLR:
+    default:
+        if (read_nin(ctx, 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(ctx, (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(ctx, 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(ctx, vs, (dev_t *)&s.s_dev, (caddr_t)&soso, &so_st, so_ad,
+                    &sdp);
+#else  /* solaris>=100000 */
+            read_mi(ctx, 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(ctx, 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(ctx, v);
+        switch (vty) {
+
+#if defined(HAS_AFS)
+        case N_AFS:
+            if (readafsnode(ctx, va, v, &an))
+                return;
+            break;
+#endif /* defined(HAS_AFS) */
+
+#if solaris >= 20500
+        case N_AUTO:
+
+#    if solaris < 20600
+            if (read_nan(ctx, va, (KA_T)v->v_data, &au))
+#    else  /* solaris>=20600 */
+            if (read_nan(ctx, va, (KA_T)v->v_data, &fnn))
+#    endif /* solaris<20600 */
+
+                return;
+            break;
+
+#    if solaris >= 100000
+        case N_DEV:
+            if (read_ndvn(ctx, 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(ctx, realvp, (KA_T)v->v_data, &dn))
+#    else  /* solaris>=20600 */
+            if (read_ndn(ctx, 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(ctx, 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(ctx, vty, va, (KA_T)v->v_data, (char *)&ctfs))
+                return;
+            break;
+#endif /* solaris>=100000 */
+
+        case N_HSFS:
+            if (read_nhn(ctx, 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(ctx, va, (KA_T)v->v_data, &m))
+                return;
+            break;
+        case N_NFS:
+            if (read_nrn(ctx, va, (KA_T)v->v_data, &r))
+                return;
+            break;
+
+#if solaris >= 100000
+        case N_NFS4:
+            if (read_nrn4(ctx, va, (KA_T)v->v_data, &r4))
+                return;
+            break;
+#endif /* solaris>=100000 */
+
+        case N_NM:
+            if (read_nnn(ctx, va, (KA_T)v->v_data, &nn))
+                return;
+            nns = 1;
+            break;
+
+#if solaris >= 100000
+        case N_PORT:
+            if (read_nprtn(ctx, va, (KA_T)v->v_data, &pn))
+                return;
+            break;
+#endif /* solaris>=100000 */
+
+        case N_PCFS:
+            if (read_npn(ctx, va, (KA_T)v->v_data, &pc))
+                return;
+            break;
+        case N_SAMFS:
+            (void)add_nma(ctx, SAMFS_NMA_MSG, (int)strlen(SAMFS_NMA_MSG));
+
+#if solaris >= 110000
+        case N_SDEV:
+            if (read_nsdn(ctx, 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(ctx, va, sona, &so))
+                return;
+            break;
+#endif /* solaris>=20600 */
+
+        case N_STREAM:
+            if (vs) {
+                Lf->is_stream = 1;
+
+#if solaris < 100000
+                read_mi(ctx, vs, (dev_t *)&s.s_dev, (caddr_t)&soso, &so_st,
+                        so_ad, &sdp);
+#else  /* solaris>=100000 */
+                read_mi(ctx, vs, (dev_t *)&s.s_dev, NULL, NULL, NULL, &sdp);
+#endif /* solaris<100000 */
+
+                vs = (KA_T)NULL;
+            }
+            break;
+        case N_TMP:
+            if (read_ntn(ctx, va, (KA_T)v->v_data, &t))
+                return;
+            break;
+
+#if defined(HASVXFS)
+        case N_VXFS:
+            if (read_vxnode(ctx, va, v, vfs, fx, &vx, Vvops))
+                return;
+            break;
+#endif /* defined(HASVXFS) */
+
+#if defined(HAS_ZFS)
+        case N_ZFS:
+            if (read_nzn(ctx, va, (KA_T)v->v_data, &zn))
+                return;
+            zns = 1;
+            break;
+#endif /* defined(HAS_ZFS) */
+
+        case N_REGLR:
+        default:
+            if (read_nin(ctx, 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(ctx, "    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) {
+            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(ctx, &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(ctx, &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(ctx, &sti.sti_laddr, &ua)) > 0) &&
+                (nmrl > (len + 5))) {
+                if (Sfile && is_file_named(ctx, 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(ctx, &sti.sti_faddr, &ua)) > 0) &&
+                (nmrl > (len + 5))) {
+                if (Sfile && is_file_named(ctx, 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(ctx, (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(ctx, 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(ctx, 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(ctx, (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(ctx, 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(ctx, (KA_T)v->v_data, (KA_T)zn.z_zfsvfs, &zvfs) &&
+                zvfs.z_vfs &&
+                !kread(ctx, (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(ctx, 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(ctx, (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.
+     */
+    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:
+        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:
+        break;
+#endif /* solaris>=100000 */
+
+    case N_DOOR:
+    case N_FIFO:
+        break;
+    case N_MNT:
+
+#if defined(CVFS_SZSAVE)
+        if (vfs) {
+            Lf->sz = (SZOFFTYPE)vfs->size;
+            Lf->sz_def = 1;
+        } else
+#endif /* defined(CVFS_SZSAVE) */
+
+            break;
+    case N_MVFS:
+        /* The location of file size isn't known. */
+        break;
+    case N_NFS:
+        if (!(type == VCHR || type == VBLK)) {
+            Lf->sz = (SZOFFTYPE)r.r_size;
+            Lf->sz_def = 1;
+        }
+        break;
+
+#if solaris >= 100000
+    case N_NFS4:
+        if (!(type == VCHR || type == VBLK)) {
+            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;
+            }
+        }
+        break;
+
+#if solaris >= 110000
+    case N_SDEV:
+        if (sdns) {
+            if (type == VREG || type == VDIR) {
+                Lf->sz = (SZOFFTYPE)sdva.va_size;
+                Lf->sz_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:
+        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;
+        }
+        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;
+            }
+        }
+        break;
+#endif /* defined(HAS_ZFS) */
+    }
+    /*
+     * Record link count.
+     */
+
+    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(ctx, (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(ctx, (KA_T)nn.nm_mountpt, &fv) && fv.v_vfsp) {
+            if ((nvfs = readvfs(ctx, (KA_T)fv.v_vfsp, (struct vfs *)NULL,
+                                nn.nm_filevp)) &&
+                !nvfs->dir) {
+                (void)completevfs(ctx, 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:
+        Lf->type = LSOF_FILE_VNODE_VNON;
+        Lf->dev = dev;
+        Lf->dev_def = devs;
+        Lf->rdev = rdev;
+        Lf->rdev_def = rdevs;
+        break;
+    case VREG:
+    case VDIR:
+        Lf->type = (type == VREG) ? LSOF_FILE_VNODE_VREG : LSOF_FILE_VNODE_VDIR;
+        Lf->dev = dev;
+        Lf->dev_def = devs;
+        Lf->rdev = rdev;
+        Lf->rdev_def = rdevs;
+        break;
+    case VBLK:
+        Lf->type = LSOF_FILE_VNODE_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) {
+            Lf->type = LSOF_FILE_UNIX;
+            break;
+        }
+        Lf->type = LSOF_FILE_VNODE_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;
+        Lf->type = LSOF_FILE_VNODE_VDOOR;
+        if (dns)
+            (void)idoorkeep(ctx, &dn);
+        break;
+#endif /* solaris>=20500 */
+
+    case VLNK:
+        Lf->type = LSOF_FILE_VNODE_VLNK;
+        Lf->dev = dev;
+        Lf->dev_def = devs;
+        Lf->rdev = rdev;
+        Lf->rdev_def = rdevs;
+        break;
+
+#if solaris >= 100000
+    case VPORT:
+        Lf->type = LSOF_FILE_VNODE_VPORT;
+        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;
+        Lf->type = LSOF_FILE_NONE;
+        break;
+#endif /* solaris>=20600 */
+
+#if defined(HAS_VSOCK)
+    case VSOCK:
+
+#    if solaris >= 20600
+        if (so.so_family == AF_UNIX) {
+            Lf->type = LSOF_FILE_UNIX;
+            if (Funix)
+                Lf->sf |= SELUNX;
+        } else {
+            if (so.so_family == AF_INET) {
+
+#        if defined(HASIPv6)
+                Lf->type = LSOF_FILE_IPV4;
+#        else  /* !defined(HASIPv6) */
+                Lf->type = LSOF_FILE_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) {
+                Lf->type = LSOF_FILE_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 {
+                Lf->type = LSOF_FILE_SOCKET;
+                (void)printunkaf(ctx, so.so_family, 0);
+                ep = endnm(ctx, &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:
+        Lf->type = LSOF_FILE_VNODE_VBAD;
+        Lf->dev = dev;
+        Lf->dev_def = devs;
+        Lf->rdev = rdev;
+        Lf->rdev_def = rdevs;
+        break;
+    case VFIFO:
+        Lf->type = LSOF_FILE_VNODE_VFIFO;
+        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;
+        Lf->type = LSOF_FILE_UNKNOWN_RAW;
+        Lf->unknown_file_type_number = type;
+    }
+    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(ctx, 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(ctx);
+#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(ctx);
+        /*
+         * 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(ctx, devs ? &dev : &DevDev,
+                                      rdevs ? &rdev : &Lf->dev, LOOKDEV_CLONE);
+                    else
+                        sdp = finddev(ctx, devs ? &dev : &DevDev,
+                                      rdevs ? &rdev : &Lf->dev, LOOKDEV_PSEUDO);
+                    if (!sdp)
+                        sdp = finddev(ctx, 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))) {
+                        fd_to_string(Lf->fd_type, Lf->fd_num, fd);
+                        (void)fprintf(
+                            stderr,
+                            "%s: no space for (COMMON): PID %d; FD %s\n", Pn,
+                            Lp->pid, fd);
+                        Error(ctx);
+                    }
+                    (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(ctx, NULL, Ntype, type, 1))
+                Lf->sf |= SELNM;
+            if (trdevs) {
+                Lf->rdev = rdev;
+                Lf->rdev_def = tdef;
+            }
+        }
+    }
+    /*
+     * Enter name characters.
+     */
+    if (Namech[0])
+        enter_nm(ctx, Namech);
+}
+
+/*
+ * read_cni() - read common snode information
+ */
+
+static int read_cni(struct lsof_context *ctx, /* context */
+                    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(ctx, (KA_T)v->v_data, (KA_T)s->s_commonvp, rv))
+        return (1);
+    if (read_nsn(ctx, (KA_T)s->s_commonvp, (KA_T)rv->v_data, rs))
+        return (1);
+    *din = '\0';
+    if (rs->s_dip) {
+        if (kread(ctx, (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(ctx, Namech);
+            return (1);
+        }
+        if (di->devi_name &&
+            kread(ctx, (KA_T)di->devi_name, din, dinl - 1) == 0)
+            din[dinl - 1] = '\0';
+    }
+    return (0);
+}
+
+/*
+ * readinode() - read inode
+ */
+
+static int readinode(struct lsof_context *ctx, /* context */
+                     KA_T ia,                  /* inode kernel address */
+                     struct inode *i)          /* inode buffer */
+{
+    if (kread(ctx, (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(ctx, Namech);
+        return (1);
+    }
+    return (0);
+}
+
+#if solaris >= 20500
+/*
+ * read_ndn() - read node's door node
+ */
+
+static int read_ndn(struct lsof_context *ctx, /* context */
+                    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(ctx, (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(ctx, Namech);
+        return (1);
+    }
+    return (0);
+}
+#endif /* solaris>=20500 */
+
+/*
+ * read_mi() - read stream's module information
+ */
+
+static void read_mi(struct lsof_context *ctx, /* context */
+                    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(ctx, (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(ctx, 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(ctx, &DevDev, rdev, LOOKDEV_CLONE)))
+        dp = finddev(ctx, &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(ctx, qp, (char *)&q, sizeof(q)))
+            break;
+        if ((ka = (KA_T)q.q_qinfo) == (KA_T)NULL ||
+            kread(ctx, ka, (char *)&qi, sizeof(qi)))
+            continue;
+        if ((ka = (KA_T)qi.qi_minfo) == (KA_T)NULL ||
+            kread(ctx, ka, (char *)&mi, sizeof(mi)))
+            continue;
+        if ((ka = (KA_T)mi.mi_idname) == (KA_T)NULL || kread(ctx, 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(ctx, (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(struct lsof_context *ctx, /* context */
+                    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(ctx, (KA_T)aa, (char *)rn, sizeof(struct autonode)))
+#    else  /* solaris>=20600 */
+    if (!aa || kread(ctx, (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(ctx, 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(struct lsof_context *ctx, /* context */
+                    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(ctx, (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(ctx, 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(struct lsof_context *ctx, /* context */
+                       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(ctx, Namech);
+        return (1);
+    }
+    if (!ca || kread(ctx, (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(ctx, Namech);
+        return (1);
+    }
+    return (0);
+}
+#endif /* solaris>=100000 */
+
+/*
+ * read_nfn() - read node's fifonode
+ */
+
+static int read_nfn(struct lsof_context *ctx, /* context */
+                    KA_T na,                  /* containing node's address */
+                    KA_T fa,                  /* fifonode address */
+                    struct fifonode *f)       /* fifonode receiver */
+{
+    char tbuf[32];
+
+    if (!fa || readfifonode(ctx, 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(ctx, Namech);
+        return (1);
+    }
+    return (0);
+}
+
+/*
+ * read_nhn() - read node's High Sierra node
+ */
+
+static int read_nhn(struct lsof_context *ctx, /* context */
+                    KA_T na,                  /* containing node's address */
+                    KA_T ha,                  /* hsnode address */
+                    struct hsnode *h)         /* hsnode receiver */
+{
+    char tbuf[32];
+
+    if (!ha || readhsnode(ctx, 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(ctx, Namech);
+        return (1);
+    }
+    return (0);
+}
+
+/*
+ * read_nin() - read node's inode
+ */
+
+static int read_nin(struct lsof_context *ctx, /* context */
+                    KA_T na,                  /* containing node's address */
+                    KA_T ia,                  /* kernel inode address */
+                    struct inode *i)          /* inode receiver */
+{
+    char tbuf[32];
+
+    if (!ia || readinode(ctx, 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(ctx, Namech);
+        return (1);
+    }
+    return (0);
+}
+
+/*
+ * read_nln(na, la, ln) - read node's loopback node
+ */
+
+static int read_nln(struct lsof_context *ctx, /* context */
+                    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(ctx, (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(ctx, Namech);
+        return (1);
+    }
+    return (0);
+}
+
+/*
+ * read_nnn() - read node's namenode
+ */
+
+static int read_nnn(struct lsof_context *ctx, /* context */
+                    KA_T na,                  /* containing node's address */
+                    KA_T nna,                 /* namenode address */
+                    struct namenode *nn)      /* namenode receiver */
+{
+    char tbuf[32];
+
+    if (!nna || kread(ctx, (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(ctx, Namech);
+        return (1);
+    }
+    return (0);
+}
+
+/*
+ * read_nmn() - read node's mvfsnode
+ */
+
+static int read_nmn(struct lsof_context *ctx, /* context */
+                    KA_T na,                  /* containing node's address */
+                    KA_T ma,                  /* kernel mvfsnode address */
+                    struct mvfsnode *m)       /* mvfsnode receiver */
+{
+    char tbuf[32];
+
+    if (!ma || kread(ctx, (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(ctx, Namech);
+        return (1);
+    }
+    return (0);
+}
+
+#if defined(HASPROCFS)
+/*
+ * read_npi() - read node's /proc file system information
+ */
+
+static int read_npi(struct lsof_context *ctx, /* context */
+                    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;
+    kthread_t thread;
+    pid_t prpid;
+    id_t prtid;
+    char *ty = (char *)NULL;
+#    endif /* solaris>=20600 */
+
+    if (!v->v_data || kread(ctx, (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(ctx, 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(ctx, Namech);
+            Lf->inode = (INODETYPE)PR_ROOTINO;
+            Lf->inp_ty = 1;
+        } else {
+            (void)snpf(Namech, Namechl - 1, "/%s/", HASPROCFS);
+            Namech[Namechl - 1] = '\0';
+            enter_nm(ctx, Namech);
+            Lf->inp_ty = 0;
+        }
+        return (0);
+    }
+    if (kread(ctx, (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(ctx, Namech);
+        return (1);
+    }
+    if (p.p_as && !kread(ctx, (KA_T)p.p_as, (char *)&as, sizeof(as))) {
+        Lf->sz = (SZOFFTYPE)as.a_size;
+        Lf->sz_def = 1;
+    }
+    if (!p.p_pidp ||
+        kread(ctx, (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(ctx, 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(ctx, (KA_T)pr.pr_common, (char *)&pc, sizeof(pc)) == 0) {
+        pcs = 1;
+        if (pc.prc_proc &&
+            kread(ctx, (KA_T)pc.prc_proc, (char *)&p, sizeof(p)) == 0)
+            prpcs = 1;
+        else
+            prpcs = 0;
+    } else
+        pcs = prpcs = 0;
+    if (pr.pr_pcommon &&
+        kread(ctx, (KA_T)pr.pr_pcommon, (char *)&ppc, sizeof(ppc)) == 0) {
+        ppcs = 1;
+        if (ppc.prc_proc &&
+            kread(ctx, (KA_T)ppc.prc_proc, (char *)&pp, sizeof(pp)) == 0)
+            prppcs = 1;
+        else
+            prppcs = 0;
+    } else
+        ppcs = prppcs = 0;
+    if (prpcs && p.p_pidp &&
+        kread(ctx, (KA_T)p.p_pidp, (char *)pids, sizeof(struct pid)) == 0)
+        prpid = pids->pid_id;
+    else if (prppcs && pp.p_pidp &&
+             kread(ctx, (KA_T)pp.p_pidp, (char *)pids, sizeof(struct pid)) == 0)
+        prpid = pids->pid_id;
+    else
+        pids->pid_id = prpid = (pid_t)0;
+    if (pcs && pc.prc_thread &&
+        kread(ctx, (KA_T)pc.prc_thread, (char *)&thread, sizeof(kthread_t)) ==
+            0)
+        prtid = thread.t_tid;
+    else if (ppcs && ppc.prc_thread &&
+             kread(ctx, (KA_T)ppc.prc_thread, (char *)&thread,
+                   sizeof(kthread_t)) == 0)
+        prtid = thread.t_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);
+        Lf->type = LSOF_FILE_PROC_DIR;
+        break;
+    case PR_PIDDIR:
+        (void)snpf(Namech, Namechl - 1, "/%s/%d", HASPROCFS, (int)prpid);
+        Lf->type = LSOF_FILE_PROC_DIR;
+        break;
+    case PR_AS:
+        (void)snpf(Namech, Namechl - 1, "/%s/%d/as", HASPROCFS, (int)prpid);
+        Lf->type = LSOF_FILE_PROC_AS;
+        if (prpcs &&
+            kread(ctx, (KA_T)pc.prc_proc, (char *)&p, sizeof(p)) == 0 &&
+            p.p_as && kread(ctx, (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);
+        Lf->type = LSOF_FILE_PROC_CTRL;
+        break;
+    case PR_STATUS:
+        (void)snpf(Namech, Namechl - 1, "/%s/%d/status", HASPROCFS, (int)prpid);
+        Lf->type = LSOF_FILE_PROC_STATUS;
+        break;
+    case PR_LSTATUS:
+        (void)snpf(Namech, Namechl - 1, "/%s/%d/lstatus", HASPROCFS,
+                   (int)prpid);
+        Lf->type = LSOF_FILE_PROC_LSTATUS;
+        break;
+    case PR_PSINFO:
+        (void)snpf(Namech, Namechl - 1, "/%s/%d/psinfo", HASPROCFS, (int)prpid);
+        Lf->type = LSOF_FILE_PROC_PSINFO;
+        break;
+    case PR_LPSINFO:
+        (void)snpf(Namech, Namechl - 1, "/%s/%d/lpsinfo", HASPROCFS,
+                   (int)prpid);
+        Lf->type = LSOF_FILE_PROC_LPS_INFO;
+        break;
+    case PR_MAP:
+        (void)snpf(Namech, Namechl - 1, "/%s/%d/map", HASPROCFS, (int)prpid);
+        Lf->type = LSOF_FILE_PROC_MAP;
+        break;
+    case PR_RMAP:
+        (void)snpf(Namech, Namechl - 1, "/%s/%d/rmap", HASPROCFS, (int)prpid);
+        Lf->type = LSOF_FILE_PROC_RMAP;
+        break;
+    case PR_XMAP:
+        (void)snpf(Namech, Namechl - 1, "/%s/%d/xmap", HASPROCFS, (int)prpid);
+        Lf->type = LSOF_FILE_PROC_XMAP;
+        break;
+    case PR_CRED:
+        (void)snpf(Namech, Namechl - 1, "/%s/%d/cred", HASPROCFS, (int)prpid);
+        Lf->type = LSOF_FILE_PROC_CRED;
+        break;
+    case PR_SIGACT:
+        (void)snpf(Namech, Namechl - 1, "/%s/%d/sigact", HASPROCFS, (int)prpid);
+        Lf->type = LSOF_FILE_PROC_SIGACT;
+        break;
+    case PR_AUXV:
+        (void)snpf(Namech, Namechl - 1, "/%s/%d/auxv", HASPROCFS, (int)prpid);
+        Lf->type = LSOF_FILE_PROC_AUXV;
+        break;
+
+#        if defined(HASPR_LDT)
+    case PR_LDT:
+        (void)snpf(Namech, Namechl - 1, "/%s/%d/ldt", HASPROCFS, (int)prpid);
+        Lf->type = LSOF_FILE_PROC_LDT;
+        break;
+#        endif /* defined(HASPR_LDT) */
+
+    case PR_USAGE:
+        (void)snpf(Namech, Namechl - 1, "/%s/%d/usage", HASPROCFS, (int)prpid);
+        Lf->type = LSOF_FILE_PROC_USAGE;
+        break;
+    case PR_LUSAGE:
+        (void)snpf(Namech, Namechl - 1, "/%s/%d/lusage", HASPROCFS, (int)prpid);
+        Lf->type = LSOF_FILE_PROC_LUSAGE;
+        break;
+    case PR_PAGEDATA:
+        (void)snpf(Namech, Namechl - 1, "/%s/%d/pagedata", HASPROCFS,
+                   (int)prpid);
+        Lf->type = LSOF_FILE_PROC_PAGE_DATA;
+        break;
+    case PR_WATCH:
+        (void)snpf(Namech, Namechl - 1, "/%s/%d/watch", HASPROCFS, (int)prpid);
+        Lf->type = LSOF_FILE_PROC_WATCH;
+        break;
+    case PR_CURDIR:
+        (void)snpf(Namech, Namechl - 1, "/%s/%d/cwd", HASPROCFS, (int)prpid);
+        Lf->type = LSOF_FILE_PROC_CWD;
+        break;
+    case PR_ROOTDIR:
+        (void)snpf(Namech, Namechl - 1, "/%s/%d/root", HASPROCFS, (int)prpid);
+        Lf->type = LSOF_FILE_PROC_ROOT;
+        break;
+    case PR_FDDIR:
+        (void)snpf(Namech, Namechl - 1, "/%s/%d/fd", HASPROCFS, (int)prpid);
+        Lf->type = LSOF_FILE_PROC_FD_DIR;
+        break;
+    case PR_FD:
+        (void)snpf(Namech, Namechl - 1, "/%s/%d/fd/%d", HASPROCFS, (int)prpid,
+                   pr.pr_index);
+        Lf->type = LSOF_FILE_PROC_FD;
+        break;
+    case PR_OBJECTDIR:
+        (void)snpf(Namech, Namechl - 1, "/%s/%d/object", HASPROCFS, (int)prpid);
+        Lf->type = LSOF_FILE_PROC_OBJ_DIR;
+        break;
+    case PR_OBJECT:
+        (void)snpf(Namech, Namechl - 1, "/%s/%d/object/", HASPROCFS,
+                   (int)prpid);
+        Lf->type = LSOF_FILE_PROC_OBJ;
+        break;
+    case PR_LWPDIR:
+        (void)snpf(Namech, Namechl - 1, "/%s/%d/lpw", HASPROCFS, (int)prpid);
+        Lf->type = LSOF_FILE_PROC_LWP_DIR;
+        break;
+    case PR_LWPIDDIR:
+        (void)snpf(Namech, Namechl, "/%s/%d/lwp/%d", HASPROCFS, (int)prpid,
+                   (int)prtid);
+        Lf->type = LSOF_FILE_PROC_LWP_DIR;
+        break;
+    case PR_LWPCTL:
+        (void)snpf(Namech, Namechl - 1, "/%s/%d/lwp/%d/lwpctl", HASPROCFS,
+                   (int)prpid, (int)prtid);
+        Lf->type = LSOF_FILE_PROC_LWP_CTL;
+        break;
+    case PR_LWPSTATUS:
+        (void)snpf(Namech, Namechl - 1, "/%s/%d/lwp/%d/lwpstatus", HASPROCFS,
+                   (int)prpid, (int)prtid);
+        Lf->type = LSOF_FILE_PROC_LWP_STATUS;
+        break;
+    case PR_LWPSINFO:
+        (void)snpf(Namech, Namechl - 1, "/%s/%d/lwp/%d/lwpsinfo", HASPROCFS,
+                   (int)prpid, (int)prtid);
+        Lf->type = LSOF_FILE_PROC_LWP_SINFO;
+        break;
+    case PR_LWPUSAGE:
+        (void)snpf(Namech, Namechl - 1, "/%s/%d/lwp/%d/lwpusage", HASPROCFS,
+                   (int)prpid, (int)prtid);
+        Lf->type = LSOF_FILE_PROC_LWP_USAGE;
+        break;
+    case PR_XREGS:
+        (void)snpf(Namech, Namechl - 1, "/%s/%d/lwp/%d/xregs", HASPROCFS,
+                   (int)prpid, (int)prtid);
+        Lf->type = LSOF_FILE_PROC_LWP_XREGS;
+        break;
+
+#        if defined(HASPR_GWINDOWS)
+    case PR_GWINDOWS:
+        (void)snpf(Namech, Namechl - 1, "/%s/%d/lwp/%d/gwindows", HASPROCFS,
+                   (int)prpid, (int)prtid);
+        Lf->type = LSOF_FILE_PROC_LWP_GWINDOWS;
+        break;
+#        endif /* defined(HASPR_GWINDOWS) */
+
+#        if defined(PR_PIDFILE)
+    case PR_PIDFILE:
+        (void)snpf(Namech, Namechl - 1, "/%s/%d", HASPROCFS, (int)prpid);
+        Lf->type = LSOF_FILE_PROC_OLD_PID;
+        break;
+#        endif /* defined(PR_PIDFILE) */
+
+#        if defined(PR_LWPIDFILE)
+    case PR_LWPIDFILE:
+        (void)snpf(Namech, Namechl - 1, "/%s/%d", HASPROCFS, (int)prpid);
+        Lf->type = LSOF_FILE_PROC_OLD_LWP;
+        break;
+#        endif /* defined(PR_LWPIDFILE) */
+
+    case PR_OPAGEDATA:
+        (void)snpf(Namech, Namechl - 1, "/%s/%d", HASPROCFS, (int)prpid);
+        Lf->type = LSOF_FILE_PROC_OLD_PAGE;
+        break;
+    default:
+        Lf->type = LSOF_FILE_UNKNOWN_RAW;
+        Lf->unknown_file_type_number = pr.pr_type;
+    }
+    /*
+     * 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(ctx, Namech);
+    return (0);
+}
+#endif /* defined(HASPROCFS) */
+
+/*
+ * read_npn() - read node's pcnode
+ */
+
+static int read_npn(struct lsof_context *ctx, /* context */
+                    KA_T na,                  /* containing node's address */
+                    KA_T pa,                  /* pcnode address */
+                    struct pcnode *p)         /* pcnode receiver */
+{
+    char tbuf[32];
+
+    if (!pa || kread(ctx, 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(ctx, Namech);
+        return (1);
+    }
+    return (0);
+}
+
+#if solaris >= 100000
+/*
+ * read_nprtn() - read node's port node
+ */
+
+static int read_nprtn(struct lsof_context *ctx, /* context */
+                      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(ctx, 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(ctx, Namech);
+        return (1);
+    }
+    return (0);
+}
+#endif /* solaris>=100000 */
+
+/*
+ * read_nrn() - read node's rnode
+ */
+
+static int read_nrn(struct lsof_context *ctx, /* context */
+                    KA_T na,                  /* containing node's address */
+                    KA_T ra,                  /* rnode address */
+                    struct rnode *r)          /* rnode receiver */
+{
+    char tbuf[32];
+
+    if (!ra || readrnode(ctx, 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(ctx, Namech);
+        return (1);
+    }
+    return (0);
+}
+
+#if solaris >= 100000
+/*
+ * read_nrn4() - read node's rnode4
+ */
+
+static int read_nrn4(struct lsof_context *ctx, /* context */
+                     KA_T na,                  /* containing node's address */
+                     KA_T ra,                  /* rnode address */
+                     struct rnode4 *r)         /* rnode receiver */
+{
+    char tbuf[32];
+
+    if (!ra || kread(ctx, (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(ctx, Namech);
+        return (1);
+    }
+    return (0);
+}
+#endif /* solaris>=100000 */
+
+#if solaris >= 110000
+/*
+ * read_nsdn() - read node's sdev_node
+ */
+
+static int read_nsdn(struct lsof_context *ctx, /* context */
+                     KA_T na,                  /* containing node's address */
+                     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(ctx, (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(ctx, Namech);
+        return (1);
+    }
+    if (!(va = (KA_T)sdn->sdev_attr) ||
+        kread(ctx, 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(ctx, Namech);
+        return (1);
+    }
+    return (0);
+}
+#endif /* solaris>=110000 */
+
+#if solaris >= 20600
+/*
+ * read_nson() - read node's sonode
+ */
+
+static int read_nson(struct lsof_context *ctx, /* context */
+                     KA_T na,                  /* containing node's address */
+                     KA_T sa,                  /* sonode address */
+                     struct sonode *sn)        /* sonode receiver */
+
+{
+    char tbuf[32];
+
+    if (!sa || kread(ctx, (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(ctx, Namech);
+        return (1);
+    }
+    return (0);
+}
+#endif /* solaris>=20600 */
+
+/*
+ * read_nsn() - read node's snode
+ */
+
+static int read_nsn(struct lsof_context *ctx, /* context */
+                    KA_T na,                  /* containing node's address */
+                    KA_T sa,                  /* snode address */
+                    struct snode *s)          /* snode receiver */
+{
+    char tbuf[32];
+
+    if (!sa || readsnode(ctx, 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(ctx, Namech);
+        return (1);
+    }
+    return (0);
+}
+
+#if solaris >= 110000
+/*
+ * read_nsti() - read socket node's info
+ */
+
+static int read_nsti(struct lsof_context *ctx, /* context */
+                     struct sonode *so,        /* socket's sonode */
+                     sotpi_info_t *stpi)       /* local socket info receiver */
+{
+    char tbuf[32];
+
+    (void)CTF_init(ctx, &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(ctx, Namech);
+        return (1);
+    }
+    return (0);
+}
+#endif /* solaris>=110000 */
+
+/*
+ * read_ntn() - read node's tmpnode
+ */
+
+static int read_ntn(struct lsof_context *ctx, /* context */
+                    KA_T na,                  /* containing node's address */
+                    KA_T ta,                  /* tmpnode address */
+                    struct tmpnode *t)        /* tmpnode receiver */
+{
+    char tbuf[32];
+
+    if (!ta || readtnode(ctx, 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(ctx, Namech);
+        return (1);
+    }
+    return (0);
+}
+
+#if solaris >= 20600
+/*
+ * read_nusa() - read sondode's UNIX socket address
+ */
+
+static int read_nusa(struct lsof_context *ctx, /* context */
+                     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(ctx, 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(struct lsof_context *ctx, /* context */
+                    KA_T na,                  /* node's address */
+                    KA_T va,                  /* vnode address */
+                    struct vnode *v)          /* vnode receiver */
+{
+    char tbuf[32];
+
+    if (readvnode(ctx, 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(ctx, Namech);
+        return (1);
+    }
+    return (0);
+}
+
+#if defined(HAS_ZFS)
+/*
+ * read_nzn() - read node's ZFS node
+ */
+
+static int read_nzn(struct lsof_context *ctx, /* context */
+                    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(ctx, &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(ctx, 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(ctx, 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(ctx, 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(ctx, Namech);
+            err = 1;
+        }
+    }
+    return (err);
+}
+
+/*
+ * read_nznp() - read znode's persistent znode
+ */
+
+static int read_nznp(struct lsof_context *ctx, /* context */
+                     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(ctx, &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(ctx, Namech);
+        return (1);
+    }
+    return (0);
+}
+
+/*
+ * read_nzvfs() - read znode's associated vfs
+ */
+
+static int read_nzvfs(struct lsof_context *ctx, /* context */
+                      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(ctx, &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(ctx, Namech);
+        return (1);
+    }
+    return (0);
+}
+#endif /* defined(HAS_ZFS) */
+
+#if solaris < 100000
+/*
+ * savesockmod() - save addresses from sockmod so_so structure
+ */
+
+static void
+savesockmod(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(struct lsof_context *ctx, /* context */
+           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]);
+                Error(ctx);
+            }
+            *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(struct lsof_context *ctx, /* context */
+                     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(ctx, (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(ctx, Namech);
+        return (1);
+    }
+    /*
+     * Read the snode's real vnode.
+     */
+    if (!s.s_realvp ||
+        kread(ctx, (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(ctx, Namech);
+        return (1);
+    }
+    /*
+     * Read the real vnode's dv_node.
+     */
+    if (!rv.v_data || kread(ctx, (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(ctx, Namech);
+        return (1);
+    }
+    /*
+     * Return the device number of the underlying file system, if possible.
+     */
+    if (rv.v_vfsp && !kread(ctx, (KA_T)rv.v_vfsp, (char *)&v, sizeof(v))) {
+        *dev = v.vfs_dev;
+        *devs = 1;
+    }
+    return (0);
+}
+#endif /* solaris<100000 */
diff --git a/lib/dialects/sun/dnode1.c b/lib/dialects/sun/dnode1.c
new file mode 100644
index 0000000..58785dc
--- /dev/null
+++ b/lib/dialects/sun/dnode1.c
@@ -0,0 +1,414 @@
+/*
+ * 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";
+#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
+ */
+
+static struct volume *getvolume(struct VenusFid *f, int *vols);
+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(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(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(ctx, kh, (char *)&vp, sizeof(vp)))
+        return ((struct volume *)NULL);
+    while (vp) {
+        if (kread(ctx, (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(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(ctx, (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(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(ctx, 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(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(ctx, 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(ctx, 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/lib/dialects/sun/dnode2.c b/lib/dialects/sun/dnode2.c
new file mode 100644
index 0000000..7b6e217
--- /dev/null
+++ b/lib/dialects/sun/dnode2.c
@@ -0,0 +1,483 @@
+/*
+ * 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";
+#endif
+
+#include "common.h"
+
+#if defined(HASVXFS)
+
+#    if defined(HASVXFSUTIL)
+#        include <vxfsutil.h>
+#        define EMSGPFX "vx_inode: "
+
+static char *add2em(char *em, char *fmt, char *arg);
+static char *ckptr(char *em, char *ptr, int len, int slen, char *nm);
+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(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);
+            Error(ctx);
+        }
+        al = eml + nl + 3;
+        em = (char *)realloc((MALLOC_P *)em, al);
+    }
+    if (!em) {
+        (void)fprintf(stderr, "%s: no VxFS error message space\n", Pn);
+        Error(ctx);
+    }
+    (void)snpf(em + eml, al - eml, "%s%s%s", eml ? "" : EMSGPFX,
+               eml ? "; " : "", msg);
+    return (em);
+}
+
+/*
+ * ckptr() - check pointer and length
+ */
+
+static char *ckptr(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(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);
+        Error(ctx);
+    }
+    *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 /* initial RNL cache size */
+#            define RNLCINCR 32 /* RNL cache increment */
+
+/*
+ * print_vxfs_rnl_path() -- print VxFS RNL path
+ */
+
+int print_vxfs_rnl_path(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);
+                Error(ctx);
+            }
+        }
+        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(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(ctx, (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(ctx, 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(ctx, Namech);
+        return (1);
+    }
+#    endif /* !defined(HASVXFSUTIL) */
+
+    /*
+     * Read vnode's vx_inode.
+     */
+    if (!v->v_data || kread(ctx, (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(ctx, 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/lib/dialects/sun/dproc.c b/lib/dialects/sun/dproc.c
new file mode 100644
index 0000000..21f91f8
--- /dev/null
+++ b/lib/dialects/sun/dproc.c
@@ -0,0 +1,2138 @@
+/*
+ * 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";
+#endif
+
+#include "common.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
+ */
+
+static void get_kernel_access(struct lsof_context *ctx);
+static void process_text(struct lsof_context *ctx, KA_T pa);
+static void read_proc(struct lsof_context *ctx);
+static void readfsinfo(struct lsof_context *ctx);
+
+#if solaris >= 20501
+static void readkam(struct lsof_context *ctx, KA_T addr);
+#endif /* solaris>=20501 */
+
+#if solaris >= 20501 && solaris < 70000
+extern u_longlong_t kvm_physaddr(kvm_t *, struct as *, u_int);
+#endif /* solaris>=20501 && solaris<70000 */
+
+#if defined(HASZONES)
+static int hash_zn(char *zn);
+#endif /* defined(HASZONES) */
+
+/*
+ * close_kvm() - close kernel virtual memory access
+ */
+
+void close_kvm(struct lsof_context *ctx) {
+    if (!Kd)
+        return;
+    if (Kd) {
+        if (kvm_close(Kd) != 0) {
+            (void)fprintf(stderr, "%s: kvm_close failed\n", Pn);
+            Error(ctx);
+        }
+        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(struct lsof_context *ctx) {
+    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(ctx, "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(ctx);
+        open_kvm(ctx);
+
+#if solaris >= 20501
+        /*
+         * If not the first time and the ALLKMEM device isn't available,
+         * re-read the kernel's address space map.
+         */
+        readkam(ctx, (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(ctx);
+    /*
+     * 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(ctx, (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(ctx, 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(ctx, (KA_T)p->p_zone, (char *)&z, sizeof(z))) {
+                if (!z.zone_name ||
+                    kread(ctx, (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(ctx, 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(ctx, 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);
+                    Error(ctx);
+                }
+            }
+            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);
+                    Error(ctx);
+                }
+                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);
+                    Error(ctx);
+                }
+                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(ctx, LSOF_FD_CWD, -1);
+
+#if defined(FILEPTR)
+            FILEPTR = (struct file *)NULL;
+#endif /* defined(FILEPTR) */
+
+            process_node(ctx, (KA_T)u->u_cdir);
+            if (Lf->sf)
+                link_lfile(ctx);
+        }
+        /*
+         * Save root directory information.
+         */
+        if (!ckscko && u->u_rdir) {
+            alloc_lfile(ctx, LSOF_FD_ROOT_DIR, -1);
+
+#if defined(FILEPTR)
+            FILEPTR = (struct file *)NULL;
+#endif /* defined(FILEPTR) */
+
+            process_node(ctx, (KA_T)u->u_rdir);
+            if (Lf->sf)
+                link_lfile(ctx);
+        }
+        /*
+         * Save information on text files.
+         */
+        if (!ckscko && p->p_as && Sgvops) {
+
+#if defined(FILEPTR)
+            FILEPTR = (struct file *)NULL;
+#endif /* defined(FILEPTR) */
+
+            process_text(ctx, (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(ctx, (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(ctx,
+                          (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(ctx, LSOF_FD_NUMERIC, i);
+
+#if solaris < 20400
+            pofv = (long)u->u_flist.uf_pofile[j - 1];
+            process_file(ctx, (KA_T)u->u_flist.uf_ofile[j - 1]);
+#else  /* solaris>=20400 */
+            pofv = uf[j - 1].uf_pofile;
+            process_file(ctx, (KA_T)uf[j - 1].uf_ofile);
+#endif /* solaris <20400 */
+
+            if (Lf->sf) {
+
+#if defined(HASFSTRUCT)
+                Lf->pof = pofv;
+#endif /* defined(HASFSTRUCT) */
+
+                link_lfile(ctx);
+            }
+        }
+        /*
+         * Examine results.
+         */
+        if (examine_lproc(ctx))
+            return;
+    }
+}
+
+/*
+ * get_kernel_access() - access the required information in the kernel
+ */
+
+static void get_kernel_access(struct lsof_context *ctx) {
+    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(ctx, "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));
+            Error(ctx);
+        }
+        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);
+            Error(ctx);
+        }
+    }
+#endif /* solaris>=70000 */
+
+    /*
+     * Get kernel symbols.
+     */
+    if (Nmlst && !is_readable(ctx, Nmlst, 1))
+        Error(ctx);
+    (void)build_Nl(ctx, 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);
+            Error(ctx);
+        }
+        (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);
+        Error(ctx);
+    }
+
+#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(ctx, "arFID", Drive_Nl, &v) >= 0 && !v) ||
+            (get_Nl_value(ctx, "avops", Drive_Nl, &v) >= 0 && !v) ||
+            (get_Nl_value(ctx, "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(ctx, 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(ctx);
+#else  /* !defined(WILLDROPGID) */
+    /*
+     * See if the non-KMEM memory file is readable.
+     */
+    if (Memory && !is_readable(ctx, Memory, 1))
+        Error(ctx);
+#endif /* defined(WILLDROPGID) */
+
+    /*
+     * Open access to kernel memory.
+     */
+    open_kvm(ctx);
+
+#if solaris >= 20500
+    /*
+     * Get the kernel's KERNELBASE value for Solaris 2.5 and above.
+     */
+    v = (KA_T)0;
+    if (get_Nl_value(ctx, "kbase", Drive_Nl, &v) < 0 || !v ||
+        kread(ctx, (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));
+        Error(ctx);
+    }
+#endif /* solaris>=20500 */
+
+    /*
+     * Get the Solaris clone major device number, if possible.
+     */
+    v = (KA_T)0;
+    if ((get_Nl_value(ctx, "clmaj", Drive_Nl, &v) < 0) || !v) {
+        if (get_Nl_value(ctx, "clmaj_alt", Drive_Nl, &v) < 0)
+            v = (KA_T)0;
+    }
+    if (v && kread(ctx, (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(ctx, "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(ctx, "kasp", Drive_Nl, &v) >= 0 && v) {
+            PageSz = getpagesize();
+            PSMask = PageSz - 1;
+            for (i = 1, PSShft = 0; i < PageSz; i <<= 1, PSShft++)
+                ;
+            (void)readkam(ctx, 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(ctx);
+#endif /* defined(WILLDROPGID) */
+}
+
+#if defined(HASZONES)
+/*
+ * enter_zone_arg() - enter zone name argument
+ */
+
+int enter_zone_arg(struct lsof_context *ctx, /* context */
+                   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);
+            Error(ctx);
+        }
+    }
+    /*
+     * 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);
+        Error(ctx);
+    }
+    zpn->f = 0;
+    zpn->zn = zn;
+    zpn->next = ZoneArg[zh];
+    ZoneArg[zh] = zpn;
+    return (0);
+}
+
+/*
+ * hash_zn() - hash zone name
+ */
+
+static int hash_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(struct lsof_context *ctx) {
+    get_kernel_access(ctx);
+    /*
+     * Read Solaris file system information and construct the clone table.
+     *
+     * The clone table is needed to identify sockets.
+     */
+    readfsinfo(ctx);
+
+#if defined(HASDCACHE)
+    readdev(ctx, 0);
+#else  /* !defined(HASDCACHE) */
+    read_clone();
+#endif /*defined(HASDCACHE) */
+}
+
+/*
+ * kread() - read from kernel memory
+ */
+
+int kread(struct lsof_context *ctx, /* context */
+          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);
+                    Error(ctx);
+                }
+                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(struct lsof_context *ctx) {
+    if (Kd)
+        return;
+
+#if defined(WILLDROPGID)
+    /*
+     * If this Solaris process began with setgid permission and its been
+     * surrendered, regain it.
+     */
+    (void)restoregid(ctx);
+#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));
+        Error(ctx);
+    }
+
+#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));
+        Error(ctx);
+    }
+#endif /* solaris>=20501 && solaris<70000 */
+
+#if defined(WILLDROPGID)
+    /*
+     * If this process has setgid permission, and is willing to surrender it,
+     * do so.
+     */
+    (void)dropgid(ctx);
+    /*
+     * 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(ctx, (KA_T)AVL_NODE2DATA(n, o), (char *)s, sizeof(*s)))      \
+        return -1
+
+static int get_first_seg(struct lsof_context *ctx, 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(struct lsof_context *ctx, 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(struct lsof_context *ctx, /* context */
+                         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(ctx, (KA_T)pa, (char *)&as, sizeof(as))) {
+        alloc_lfile(ctx, LSOF_FD_PROGRAM_TEXT, -1);
+        (void)snpf(Namech, Namechl, "can't read text segment list (%s)",
+                   print_kptr(pa, (char *)NULL, 0));
+        enter_nm(ctx, Namech);
+        if (Lf->sf)
+            link_lfile(ctx);
+        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(ctx, avtp, &s) : get_first_seg(ctx, avtp, &s))
+            break;
+        if ((KA_T)s.s_ops == Sgvops && s.s_data) {
+            if (kread(ctx, (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(ctx, LSOF_FD_PROGRAM_TEXT, -1);
+
+#    if defined(FILEPTR)
+                    FILEPTR = (struct file *)NULL;
+#    endif /* defined(FILEPTR) */
+
+                    process_node(ctx, (KA_T)vn.vp);
+                    if (Lf->sf)
+                        link_lfile(ctx);
+                }
+            }
+        }
+    }
+}
+
+#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(struct lsof_context *ctx, /* context */
+                         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(ctx, (KA_T)pa, (char *)&as, sizeof(as))) {
+        alloc_lfile(ctx, LSOF_FD_PROGRAM_TEXT, -1);
+        (void)snpf(Namech, Namechl, "can't read text segment list (%s)",
+                   print_kptr(pa, (char *)NULL, 0));
+        enter_nm(ctx, 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(ctx, (KA_T)s.S_NEXT, (char *)&s, sizeof(s)))
+            break;
+        if ((KA_T)s.s_ops == Sgvops && s.s_data) {
+            if (kread(ctx, (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(ctx, LSOF_FD_PROGRAM_TEXT, -1);
+
+#    if defined(FILEPTR)
+                    FILEPTR = (struct file *)NULL;
+#    endif /* defined(FILEPTR) */
+
+                    process_node(ctx, (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(struct lsof_context *ctx) {
+    char buf[FSTYPSZ + 1];
+    int i, len;
+
+    if ((Fsinfomax = sysfs(GETNFSTYP)) == -1) {
+        (void)fprintf(stderr, "%s: sysfs(GETNFSTYP) error: %s\n", Pn,
+                      strerror(errno));
+        Error(ctx);
+    }
+    if (Fsinfomax == 0)
+        return;
+    if (!(Fsinfo = (char **)malloc((MALLOC_S)(Fsinfomax * sizeof(char *))))) {
+        (void)fprintf(stderr, "%s: no space for sysfs info\n", Pn);
+        Error(ctx);
+    }
+    for (i = 1; i <= Fsinfomax; i++) {
+        if (sysfs(GETFSTYP, i, buf) == -1) {
+            (void)fprintf(stderr, "%s: sysfs(GETFSTYP) error: %s\n", Pn,
+                          strerror(errno));
+            Error(ctx);
+        }
+        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);
+            Error(ctx);
+        }
+        (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(struct lsof_context *ctx, /* context */
+                    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(ctx, 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 *)));
+                Error(ctx);
+            }
+        } 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(struct lsof_context *ctx) {
+    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(ctx, "nproc", Drive_Nl, &pa) < 0 || !pa ||
+            kread(ctx, 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);
+                Error(ctx);
+            }
+            /*
+             * 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);
+                    Error(ctx);
+                }
+            }
+            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);
+                Error(ctx);
+            }
+            Npa = n;
+        }
+        if (HasALLKMEM) {
+
+            /*
+             * Prepare for a proc table scan via direct reading of the active
+             * chain.
+             */
+            if (!PrAct || kread(ctx, PrAct, (char *)&paf, sizeof(pa))) {
+                (void)fprintf(stderr, "%s: can't read practive from %s\n", Pn,
+                              print_kptr(PrAct, (char *)NULL, 0));
+                Error(ctx);
+            }
+            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));
+                Error(ctx);
+            }
+        }
+        /*
+         * 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);
+                    Error(ctx);
+                }
+                /*
+                 * 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);
+                        Error(ctx);
+                    }
+                }
+                if (!(Pid = (int *)realloc((MALLOC_P *)Pid, len))) {
+                    (void)fprintf(stderr, "%s: no more (%d) PID space\n", Pn,
+                                  Npa);
+                    Error(ctx);
+                }
+            }
+            /*
+             * 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(ctx, 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(ctx, (KA_T)p->p_pgidp, (char *)&pg, sizeof(pg)))
+                    continue;
+            }
+            if (!p->p_pidp ||
+                kread(ctx, (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(ctx);
+            open_kvm(ctx);
+        }
+    }
+    /*
+     * 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);
+        Error(ctx);
+    }
+    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);
+            Error(ctx);
+        }
+        /*
+         * 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);
+                Error(ctx);
+            }
+        }
+        if (!(Pid = (int *)realloc((MALLOC_P *)Pid, len))) {
+            (void)fprintf(stderr, "%s: can't reduce PID table to %d\n", Pn, Np);
+            Error(ctx);
+        }
+        Npa = Np;
+    }
+}
+
+#if defined(WILLDROPGID)
+/*
+ * restoregid() -- restore setgid permission, as required
+ */
+
+void restoregid(struct lsof_context *ctx) {
+    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));
+            Error(ctx);
+        }
+        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[] */
+
+static struct l_nch *ncache_addr(KA_T v);
+
+#    define ncachehash(v) Nchash + ((((int)(v) >> 2) * 31415) & Mhl)
+
+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(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(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(ctx, (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);
+            Error(ctx);
+        }
+    }
+    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(ctx, X_NCSIZE, (struct drive_Nl *)NULL, &v) < 0 || !v ||
+            kread(ctx, (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(ctx, NCACHE_NEGVN, (struct drive_Nl *)NULL, &NegVN) < 0)
+            NegVN = (KA_T)NULL;
+        /*
+         * Establish DNLC hash address.
+         */
+        v = (KA_T)0;
+        if (get_Nl_value(ctx, X_NCACHE, (struct drive_Nl *)NULL, (KA_T *)&v) < 0 ||
+            !v || kread(ctx, 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);
+            Error(ctx);
+        }
+        /*
+         * 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);
+            Error(ctx);
+        }
+        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(ctx, "hshav", (struct drive_Nl *)NULL, (KA_T *)&v) < 0) ||
+            !v || kread(ctx, 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);
+            Error(ctx);
+        }
+    } 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(ctx, 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(ctx, 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);
+                        Error(ctx);
+                    }
+                }
+                cp = &nc->name[XNC + 1];
+                v = (KA_T)((char *)kn + nmo + XNC + 1);
+                xl = len - XNC - 1;
+                if (kread(ctx, 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);
+                Error(ctx);
+            }
+            (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);
+                    Error(ctx);
+                }
+                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);
+        Error(ctx);
+    }
+    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(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/lib/dialects/sun/dproto.h b/lib/dialects/sun/dproto.h
new file mode 100644
index 0000000..014c28f
--- /dev/null
+++ b/lib/dialects/sun/dproto.h
@@ -0,0 +1,111 @@
+/*
+ * 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)
+extern int access_vxfs_ioffsets(void);
+#endif /* defined(HASVXFSUTIL) */
+
+extern void completevfs(struct lsof_context *ctx, struct l_vfs *vfs,
+                        dev_t *dev);
+
+#if defined(HAS_LIBCTF)
+extern int CTF_getmem(struct lsof_context *ctx, ctf_file_t *f, const char *mod,
+                      const char *ty, CTF_member_t *mem);
+extern void CTF_init(struct lsof_context *ctx, int *i, char *t,
+                     CTF_request_t *r);
+extern int CTF_memCB(const char *name, ctf_id_t id, ulong_t offset, void *arg);
+#endif /* defined(HAS_LIBCTF) */
+
+extern int is_file_named(struct lsof_context *ctx, char *p, int nt,
+                         enum vtype vt, int ps);
+extern struct l_vfs *readvfs(struct lsof_context *ctx, KA_T ka, struct vfs *la,
+                             struct vnode *lv);
+extern int vop2ty(struct lsof_context *ctx, struct vnode *vp, int fx);
+
+#if defined(HAS_AFS)
+extern struct vnode *alloc_vcache(void);
+extern void ckAFSsym(struct nlist *nl);
+extern int hasAFS(struct vnode *vp);
+extern int readafsnode(KA_T va, struct vnode *v, struct afsnode *an);
+#endif /* defined(HAS_AFS) */
+
+#if defined(HASDCACHE)
+extern int rw_clone_sect(struct lsof_context *ctx, int m);
+extern void clr_sect(struct lsof_context *ctx);
+extern int rw_pseudo_sect(struct lsof_context *ctx, int m);
+#endif /* defined(HASDCACHE) */
+
+#if defined(HASIPv6)
+extern struct hostent *gethostbyname2(const char *nm, int proto);
+#endif /* defined(HASIPv6) */
+
+#if defined(HAS_V_PATH)
+extern int print_v_path(struct lsof_context *ctx, struct lfile *lf);
+extern void read_v_path(struct lsof_context *ctx, KA_T ka, char *rb,
+                        size_t rbl);
+#endif /* defined(HAS_V_PATH) */
+
+#if defined(HASVXFS)
+extern int read_vxnode(struct lsof_context *ctx, KA_T va, struct vnode *v,
+                       struct l_vfs *vfs, int fx, struct l_ino *li,
+                       KA_T *vnops);
+#    if defined(HASVXFSRNL)
+extern int print_vxfs_rnl_path(struct lfile *lf);
+#    endif /* defined(HASVXFSRNL) */
+#endif     /* defined(HASVXFS) */
+
+#if defined(HASZONES)
+extern int enter_zone_arg(struct lsof_context *ctx, char *zn);
+#endif /* defined(HASZONES) */
+
+extern void close_kvm(struct lsof_context *ctx);
+extern void open_kvm(struct lsof_context *ctx);
+extern void process_socket(struct lsof_context *ctx, KA_T sa, char *ty);
+
+#if solaris >= 110000
+extern int process_VSOCK(struct lsof_context *ctx, KA_T va, struct vnode *v,
+                         struct sonode *so);
+#endif /* solaris>=11000 */
+
+extern void read_clone(struct lsof_context *ctx);
+
+#if solaris < 20500
+extern int get_max_fd(void);
+#endif /* solaris<20500 */
+
+#if defined(WILLDROPGID)
+extern void restoregid(struct lsof_context *ctx);
+#endif /* defined(WILLDROPGID) */
diff --git a/lib/dialects/sun/dsock.c b/lib/dialects/sun/dsock.c
new file mode 100644
index 0000000..3c2089d
--- /dev/null
+++ b/lib/dialects/sun/dsock.c
@@ -0,0 +1,1996 @@
+/*
+ * 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";
+#endif
+
+#include "common.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 values
+ * 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; /* Explicitly 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
+ */
+
+static int read_icmp_t(struct lsof_context *ctx, KA_T va, KA_T ph, KA_T ia,
+                       icmp_t *ic);
+static int read_rts_t(struct lsof_context *ctx, KA_T va, KA_T ph, KA_T ra,
+                      rts_t *rt);
+static int read_udp_t(struct lsof_context *ctx, 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
+ */
+
+static void save_TCP_size(struct lsof_context *ctx, tcp_t *tc);
+static void save_TCP_states(struct lsof_context *ctx, tcp_t *tc, caddr_t *fa, tcpb_t *tb, caddr_t *xp);
+
+/*
+ * build_IPstates() -- build the TCP and UDP state tables
+ */
+
+void build_IPstates(struct lsof_context *ctx) {
+    if (!TcpSt) {
+        (void)enter_IPstate(ctx, "TCP", "CLOSED", TCPS_CLOSED);
+        (void)enter_IPstate(ctx, "TCP", "IDLE", TCPS_IDLE);
+        (void)enter_IPstate(ctx, "TCP", "BOUND", TCPS_BOUND);
+        (void)enter_IPstate(ctx, "TCP", "LISTEN", TCPS_LISTEN);
+        (void)enter_IPstate(ctx, "TCP", "SYN_SENT", TCPS_SYN_SENT);
+        (void)enter_IPstate(ctx, "TCP", "SYN_RCVD", TCPS_SYN_RCVD);
+        (void)enter_IPstate(ctx, "TCP", "ESTABLISHED", TCPS_ESTABLISHED);
+        (void)enter_IPstate(ctx, "TCP", "CLOSE_WAIT", TCPS_CLOSE_WAIT);
+        (void)enter_IPstate(ctx, "TCP", "FIN_WAIT_1", TCPS_FIN_WAIT_1);
+        (void)enter_IPstate(ctx, "TCP", "CLOSING", TCPS_CLOSING);
+        (void)enter_IPstate(ctx, "TCP", "LAST_ACK", TCPS_LAST_ACK);
+        (void)enter_IPstate(ctx, "TCP", "FIN_WAIT_2", TCPS_FIN_WAIT_2);
+        (void)enter_IPstate(ctx, "TCP", "TIME_WAIT", TCPS_TIME_WAIT);
+        (void)enter_IPstate(ctx, "TCP", (char *)NULL, 0);
+    }
+    if (!UdpSt) {
+        (void)enter_IPstate(ctx, "UDP", "Unbound", TS_UNBND);
+        (void)enter_IPstate(ctx, "UDP", "Wait_BIND_REQ_Ack", TS_WACK_BREQ);
+        (void)enter_IPstate(ctx, "UDP", "Wait_UNBIND_REQ_Ack", TS_WACK_UREQ);
+        (void)enter_IPstate(ctx, "UDP", "Idle", TS_IDLE);
+        (void)enter_IPstate(ctx, "UDP", "Wait_OPT_REQ_Ack", TS_WACK_OPTREQ);
+        (void)enter_IPstate(ctx, "UDP", "Wait_CONN_REQ_Ack", TS_WACK_CREQ);
+        (void)enter_IPstate(ctx, "UDP", "Wait_CONN_REQ_Confirm", TS_WCON_CREQ);
+        (void)enter_IPstate(ctx, "UDP", "Wait_CONN_IND_Response", TS_WRES_CIND);
+        (void)enter_IPstate(ctx, "UDP", "Wait_CONN_RES_Ack", TS_WACK_CRES);
+        (void)enter_IPstate(ctx, "UDP", "Wait_Data_Xfr", TS_DATA_XFER);
+        (void)enter_IPstate(ctx, "UDP", "Wait_Read_Release", TS_WIND_ORDREL);
+        (void)enter_IPstate(ctx, "UDP", "Wait_Write_Release", TS_WREQ_ORDREL);
+        (void)enter_IPstate(ctx, "UDP", "Wait_DISCON_REQ_Ack", TS_WACK_DREQ6);
+        (void)enter_IPstate(ctx, "UDP", "Wait_DISCON_REQ_Ack", TS_WACK_DREQ7);
+        (void)enter_IPstate(ctx, "UDP", "Wait_DISCON_REQ_Ack", TS_WACK_DREQ9);
+        (void)enter_IPstate(ctx, "UDP", "Wait_DISCON_REQ_Ack", TS_WACK_DREQ10);
+        (void)enter_IPstate(ctx, "UDP", "Wait_DISCON_REQ_Ack", TS_WACK_DREQ11);
+        (void)enter_IPstate(ctx, "UDP", (char *)NULL, 0);
+    }
+}
+
+/*
+ * print_tcptpi() - print TCP/TPI info
+ */
+
+void print_tcptpi(struct lsof_context *ctx, /* context */
+                  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(ctx);
+            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(ctx);
+            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(struct lsof_context *ctx, /* context */
+                  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(ctx, 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(ctx, Namech);
+        return (1);
+    }
+    enter_dev_ch(ctx, 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)
+            Lf->type = LSOF_FILE_IPV4;
+        else
+            Lf->type = LSOF_FILE_IPV6;
+
+        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(ctx, 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(ctx, Namech);
+                return (1);
+            }
+            /*
+             * Set TCP protocol 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(ctx, 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(ctx, ka, (char *)&xa, sizeof(xa))) {
+                xp = (caddr_t *)&xa;
+            }
+            (void)save_TCP_states(ctx, &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(ctx, ka, (char *)&th, sizeof(th))) {
+                tha = &th;
+            }
+            (void)save_TCP_states(ctx, &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(ctx, &tc);
+            break;
+        case IPPROTO_UDP:
+
+            /*
+             * Process UDP socket; read its control structure.
+             */
+            if (!(ka = (KA_T)cs.conn_proto_priv.cp_udp) ||
+                kread(ctx, 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(ctx, Namech);
+                return (1);
+            }
+            /*
+             * Set UDP protocol 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(ctx, la, (int)ntohs(lp), fa, (int)ntohs(fp), af);
+            /*
+             * Save UDP state and size information.
+             */
+            Lf->lts.type = 1;
+            Lf->lts.state.ui = (unsigned int)uc.udp_state;
+
+#    if defined(HASSOOPT)
+            /*
+             * Save UDP 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(ctx, va, pha, (KA_T)cs.conn_proto_priv.cp_icmp,
+                            &ic))
+                return (1);
+            /*
+             * Save ICMP size and state information.
+             */
+            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(ctx, la, 0, fa, 0, af);
+
+#    if defined(HASSOOPT)
+            /*
+             * Save ICMP 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(ctx, Namech);
+            return (1);
+        }
+        break;
+    case AF_ROUTE:
+
+        /*
+         * Set INET type -- IPv4 or IPv6.
+         */
+        if (af == AF_INET)
+            Lf->type = LSOF_FILE_IPV4;
+        else
+            Lf->type = LSOF_FILE_IPV6;
+        /*
+         * 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(ctx, va, pha, (KA_T)cs.conn_proto_priv.cp_rts, &rt))
+            return (1);
+        /*
+        /*
+         * Save AF_ROUTE size and state information.
+         */
+        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 (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(ctx, (int)cs.conn_ulp);
+        (void)snpf(Namech, Namechl - 1, "unsupported socket family: %u",
+                   so->so_family);
+        Namech[Namechl - 1] = '\0';
+        enter_nm(ctx, Namech);
+        Lf->inp_ty = 2;
+    }
+    return (1);
+}
+#endif /* solaris>=110000*/
+
+/*
+ * process_socket() - process Solaris socket
+ */
+
+void process_socket(struct lsof_context *ctx, /* context */
+                    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')) {
+        Lf->type = LSOF_FILE_IPV6;
+        af = AF_INET6;
+    } else {
+        Lf->type = LSOF_FILE_IPV4;
+        af = AF_INET;
+    }
+#else  /* !defined(HASIPv6) */
+    Lf->type = LSOF_FILE_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(ctx, 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(ctx, qp, (char *)&q, sizeof(q)))
+            break;
+        if ((ka = (KA_T)q.q_qinfo) == (KA_T)NULL ||
+            kread(ctx, ka, (char *)&qi, sizeof(qi)))
+            continue;
+        if ((ka = (KA_T)qi.qi_minfo) == (KA_T)NULL ||
+            kread(ctx, ka, (char *)&mi, sizeof(mi)) ||
+            (ka = (KA_T)mi.mi_idname) == (KA_T)NULL)
+            continue;
+        if (kread(ctx, 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(ctx, 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(ctx, (KA_T)pcb, (char *)&tc, sizeof(tc)))
+
+#    if solaris >= 80000
+            {
+                if (tc.tcp_base &&
+                    !kread(ctx, (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(ctx, pcb, (char *)&cs, sizeof(cs)) &&
+                (cs.conn_ulp == IPPROTO_TCP)) {
+                ics = 1;
+                if ((ka = (KA_T)cs.conn_proto_priv.cp_tcp) &&
+                    !kread(ctx, ka, (char *)&tc, sizeof(tc))) {
+                    tcs = 1;
+                }
+            }
+#    else  /* solaris<110000 */
+            if (!kread(ctx, (KA_T)pcb, (char *)&ic, sizeof(ic)) &&
+                ic.conn_tcp &&
+                !kread(ctx, (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(ctx, pcb, (char *)&uc, sizeof(uc)) == 0)
+                ucs = 1;
+#else  /* solaris>=110000 */
+            if (!kread(ctx, 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(ctx, 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(ctx, 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(ctx, la, (int)ntohs(p), (unsigned char *)NULL, -1,
+                             af);
+            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(ctx, (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(ctx, la, lp, fa, fp, af);
+            }
+            /*
+             * Save TCP state information.
+             */
+            if (tcs) {
+                (void)save_TCP_states(ctx, &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(ctx, &tc);
+        }
+    } else
+        (void)strcat(Namech, "no TCP/UDP/IP information available");
+    /*
+     * Enter name characters if there are some.
+     */
+    if (Namech[0])
+        enter_nm(ctx, Namech);
+}
+
+#if solaris >= 110000
+/*
+ * read_icmp_t() - read connections icmp_t info
+ */
+
+static int read_icmp_t(struct lsof_context *ctx, /* context */
+                       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(ctx, &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(ctx, Namech);
+        return (1);
+    }
+
+#    if defined(HAS_CONN_NEW)
+    if ((ka = (KA_T)ic->icmp_connp) &&
+        !kread(ctx, 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(ctx, 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(struct lsof_context *ctx, /* context */
+                      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;          /* kernel address */
+
+    zeromem((char *)rt, sizeof(rts_t));
+#    endif /* defined(HAS_CONN_NEW) */
+
+    (void)CTF_init(ctx, &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(ctx, Namech);
+        return (1);
+    }
+
+#    if defined(HAS_CONN_NEW)
+    if ((ka = (KA_T)rt->rts_connp) &&
+        !kread(ctx, 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(ctx, 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(struct lsof_context *ctx, /* context */
+                      KA_T ua,                  /* ucp_t kernel address */
+                      udp_t *uc)                /* receiving udp_t structure */
+{
+    (void)CTF_init(ctx, &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(ctx, Namech);
+        return (1);
+    }
+    return (0);
+}
+#endif /* solaris>=110000 */
+
+/*
+ * save_TCP_size() -- save TCP size information
+ */
+
+static void save_TCP_size(struct lsof_context *ctx, 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 (Lf->access == LSOF_FILE_ACCESS_READ)
+        Lf->sz = (SZOFFTYPE)rq;
+    else if (Lf->access == LSOF_FILE_ACCESS_WRITE)
+        Lf->sz = (SZOFFTYPE)sq;
+    else
+        Lf->sz = (SZOFFTYPE)(rq + sq);
+    Lf->sz_def = 1;
+#endif /* defined(HASTCPTPIQ) || defined(HASTCPTPIW) */
+}
+
+/*
+ * save_TCP_states() - save TCP states
+ */
+
+static void save_TCP_states(struct lsof_context *ctx, /* context */
+                            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 (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 (1) {
+        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/lib/dialects/sun/dstore.c b/lib/dialects/sun/dstore.c
new file mode 100644
index 0000000..9e600ca
--- /dev/null
+++ b/lib/dialects/sun/dstore.c
@@ -0,0 +1,247 @@
+/*
+ * 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";
+#endif
+
+#include "common.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/lib/dialects/sun/machine.h b/lib/dialects/sun/machine.h
new file mode 100644
index 0000000..e330a18
--- /dev/null
+++ b/lib/dialects/sun/machine.h
@@ -0,0 +1,696 @@
+/*
+ * 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.48 2018/02/14 14:24:07 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
+#        if !defined(HAS_AIO_REQ_STRUCT)
+/*
+ * When <sys.aio_req.h> lacks one, define a dummy aio_req structure for
+ * Solaris >= 10 systems.
+ *
+ * If this definition causes compilation errors for <sys/vnode.h>, especially
+ * with Solaris 11, it may be necessary to comment out the following structure
+ * definition.  I don't know a test that will determine the possibility of
+ * compilation errors.
+ */
+
+typedef struct aio_req {
+    int dummy;
+} aio_req_t;
+
+#        endif /* !defined(HAS_AIO_REQ_STRUCT) */
+
+/*
+ * 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 access
+ * 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?	*/
+
+/*
+ * 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_RNAM			1	   rnam.c */
+
+#    if solaris < 90000
+#        define USE_LIB_RNCH 1 /* rnch.c */
+#    endif                     /* solaris<90000 */
+
+/* #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/lib/dialects/sun/solaris_kaddr_filters b/lib/dialects/sun/solaris_kaddr_filters
new file mode 100644
index 0000000..7fcd692
--- /dev/null
+++ b/lib/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/lib/dvch.c b/lib/dvch.c
index b2a5580..46516d7 100644
--- a/lib/dvch.c
+++ b/lib/dvch.c
@@ -2,7 +2,6 @@
  * dvch.c -- device cache functions for lsof library
  */
 
-
 /*
  * Copyright 1997 Purdue Research Foundation, West Lafayette, Indiana
  * 47907.  All rights reserved.
@@ -29,17 +28,10 @@
  * 4. This notice may not be removed or altered.
  */
 
+#include "common.h"
+#include "machine.h"
 
-#include "../machine.h"
-
-#if	defined(HASDCACHE)
-
-# if	!defined(lint)
-static char copyright[] =
-"@(#) Copyright 1997 Purdue Research Foundation.\nAll rights reserved.\n";
-# endif	/* !defined(lint) */
-
-#include "../lsof.h"
+#if defined(HASDCACHE)
 
 /*
  * dvch.c - module that contains common device cache functions
@@ -76,1337 +68,1285 @@ static char copyright[] =
  *	HASBLKDEV	if block device information is stored in BDevtp[].
  */
 
-
 /*
  * Local definitions
  */
 
-# if	!defined(DVCH_DEVPATH)
-#define	DVCH_DEVPATH	"/dev"
-# endif	/* !defined(DVCH_DEVPATH) */
+#    if !defined(DVCH_DEVPATH)
+#        define DVCH_DEVPATH "/dev"
+#    endif /* !defined(DVCH_DEVPATH) */
 
 /*
  * Local storage
  */
 
-static int crctbl[CRC_TBLL];		/* crc partial results table */
-
+static int crctbl[CRC_TBLL]; /* crc partial results table */
 
 /*
  * Local function prototypes
  */
 
-#undef	DCACHE_CLR_LOCAL
-# if	!defined(DCACHE_CLR)
-#  if	defined(HAS_STD_CLONE) && HAS_STD_CLONE==1
-#define	DCACHE_CLR		clr_sect
-#define	DCACHE_CLR_LOCAL	1
-_PROTOTYPE(static void clr_sect,(void));
-#  endif	/* defined(HAS_STD_CLONE) && HAS_STD_CLONE==1 */
-# endif	/* !defined(DCACHE_CLR) */
-
-#undef	DCACHE_CLONE_LOCAL
-# if	!defined(DCACHE_CLONE)
-#  if	defined(HAS_STD_CLONE) && HAS_STD_CLONE==1
-#define	DCACHE_CLONE		rw_clone_sect
-#define	DCACHE_CLONE_LOCAL	1
-_PROTOTYPE(static int rw_clone_sect,(int m));
-#  endif	/* defined(HAS_STD_CLONE) && HAS_STD_CLONE==1 */
-# endif	/*!defined(DCACHE_CLONE) */
-
-
-# if	defined(HASBLKDEV)
+#    undef DCACHE_CLR_LOCAL
+#    if !defined(DCACHE_CLR)
+#        if defined(HAS_STD_CLONE) && HAS_STD_CLONE == 1
+#            define DCACHE_CLR clr_sect
+#            define DCACHE_CLR_LOCAL 1
+static void clr_sect(void);
+#        endif /* defined(HAS_STD_CLONE) && HAS_STD_CLONE==1 */
+#    endif     /* !defined(DCACHE_CLR) */
+
+#    undef DCACHE_CLONE_LOCAL
+#    if !defined(DCACHE_CLONE)
+#        if defined(HAS_STD_CLONE) && HAS_STD_CLONE == 1
+#            define DCACHE_CLONE rw_clone_sect
+#            define DCACHE_CLONE_LOCAL 1
+static int rw_clone_sect(int m);
+#        endif /* defined(HAS_STD_CLONE) && HAS_STD_CLONE==1 */
+#    endif     /*!defined(DCACHE_CLONE) */
+
+#    if defined(HASBLKDEV)
 /*
  * alloc_bdcache() - allocate block device cache
  */
 
-void
-alloc_bdcache()
-{
-	if (!(BDevtp = (struct l_dev *)calloc((MALLOC_S)BNdev,
-				       sizeof(struct l_dev))))
-	{
-	    (void) fprintf(stderr, "%s: no space for block devices\n", Pn);
-	    Error();
-	}
-	if (!(BSdev = (struct l_dev **)malloc((MALLOC_S)(sizeof(struct l_dev *)
-				       * BNdev))))
-	{
-	    (void) fprintf(stderr, "%s: no space for block device pointers\n",
-		Pn);
-	    Error();
-	}
+void alloc_bdcache(struct lsof_context *ctx) {
+    if (!(BDevtp =
+              (struct l_dev *)calloc((MALLOC_S)BNdev, sizeof(struct l_dev)))) {
+        (void)fprintf(stderr, "%s: no space for block devices\n", Pn);
+        Error(ctx);
+    }
+    if (!(BSdev = (struct l_dev **)malloc(
+              (MALLOC_S)(sizeof(struct l_dev *) * BNdev)))) {
+        (void)fprintf(stderr, "%s: no space for block device pointers\n", Pn);
+        Error(ctx);
+    }
 }
-# endif	/* defined(HASBLKDEV) */
-
+#    endif /* defined(HASBLKDEV) */
 
 /*
  * alloc_dcache() - allocate device cache
  */
 
-void
-alloc_dcache()
-{
-	if (!(Devtp = (struct l_dev *)calloc((MALLOC_S)Ndev,
-				      sizeof(struct l_dev))))
-	{
-	    (void) fprintf(stderr, "%s: no space for devices\n", Pn);
-	    Error();
-	}
-	if (!(Sdev = (struct l_dev **)malloc((MALLOC_S)(sizeof(struct l_dev *)
-				      * Ndev))))
-	{
-	    (void) fprintf(stderr, "%s: no space for device pointers\n",
-		Pn);
-	    Error();
-	}
+void alloc_dcache(struct lsof_context *ctx) {
+    if (!(Devtp =
+              (struct l_dev *)calloc((MALLOC_S)Ndev, sizeof(struct l_dev)))) {
+        (void)fprintf(stderr, "%s: no space for devices\n", Pn);
+        Error(ctx);
+    }
+    if (!(Sdev = (struct l_dev **)malloc(
+              (MALLOC_S)(sizeof(struct l_dev *) * Ndev)))) {
+        (void)fprintf(stderr, "%s: no space for device pointers\n", Pn);
+        Error(ctx);
+    }
 }
 
-
 /*
  * clr_devtab() - clear the device tables and free their space
  */
 
-void
-clr_devtab()
-{
-	int i;
-
-	if (Devtp) {
-	    for (i = 0; i < Ndev; i++) {
-		if (Devtp[i].name) {
-		    (void) free((FREE_P *)Devtp[i].name);
-		    Devtp[i].name = (char *)NULL;
-		}
-	    }
-	    (void) free((FREE_P *)Devtp);
-	    Devtp = (struct l_dev *)NULL;
-	}
-	if (Sdev) {
-	    (void) free((FREE_P *)Sdev);
-	    Sdev = (struct l_dev **)NULL;
-	}
-	Ndev = 0;
-
-# if	defined(HASBLKDEV)
-	if (BDevtp) {
-	    for (i = 0; i < BNdev; i++) {
-		if (BDevtp[i].name) {
-		    (void) free((FREE_P *)BDevtp[i].name);
-		    BDevtp[i].name = (char *)NULL;
-		}
-	    }
-	    (void) free((FREE_P *)BDevtp);
-	    BDevtp = (struct l_dev *)NULL;
-	}
-	if (BSdev) {
-	    (void) free((FREE_P *)BSdev);
-	    BSdev = (struct l_dev **)NULL;
-	}
-	BNdev = 0;
-# endif	/* defined(HASBLKDEV) */
-
+void clr_devtab(struct lsof_context *ctx) {
+    int i;
+
+    if (Devtp) {
+        for (i = 0; i < Ndev; i++) {
+            if (Devtp[i].name) {
+                (void)free((FREE_P *)Devtp[i].name);
+                Devtp[i].name = (char *)NULL;
+            }
+        }
+        (void)free((FREE_P *)Devtp);
+        Devtp = (struct l_dev *)NULL;
+    }
+    if (Sdev) {
+        (void)free((FREE_P *)Sdev);
+        Sdev = (struct l_dev **)NULL;
+    }
+    Ndev = 0;
+
+#    if defined(HASBLKDEV)
+    if (BDevtp) {
+        for (i = 0; i < BNdev; i++) {
+            if (BDevtp[i].name) {
+                (void)free((FREE_P *)BDevtp[i].name);
+                BDevtp[i].name = (char *)NULL;
+            }
+        }
+        (void)free((FREE_P *)BDevtp);
+        BDevtp = (struct l_dev *)NULL;
+    }
+    if (BSdev) {
+        (void)free((FREE_P *)BSdev);
+        BSdev = (struct l_dev **)NULL;
+    }
+    BNdev = 0;
+#    endif /* defined(HASBLKDEV) */
 }
 
-
-# if	defined(DCACHE_CLR_LOCAL)
+#    if defined(DCACHE_CLR_LOCAL)
 /*
  * clr_sect() - clear cached standard clone sections
  */
 
-static 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(DCACHE_CLR_LOCAL) */
+static 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(DCACHE_CLR_LOCAL) */
 
 /*
  * crc(b, l, s) - compute a crc for a block of bytes
  */
 
-void
-crc(b, l, s)
-	char *b;			/* block address */
-	int  l;				/* length */
-	unsigned *s;			/* sum */
+void crc(char *b,     /* block address */
+         int l,       /* length */
+         unsigned *s) /* sum */
 {
-	char *cp;			/* character pointer */
-	char *lm;			/* character limit pointer */
-	unsigned sum;			/* check sum */
-
-	cp = b;
-	lm = cp + l;
-	sum = *s;
-	do {
-		sum ^= ((int) *cp++) & 0xff;
-		sum = (sum >> 8) ^ crctbl[sum & 0xff];
-	} while (cp < lm);
-	*s = sum;
+    char *cp;     /* character pointer */
+    char *lm;     /* character limit pointer */
+    unsigned sum; /* check sum */
+
+    cp = b;
+    lm = cp + l;
+    sum = *s;
+    do {
+        sum ^= ((int)*cp++) & 0xff;
+        sum = (sum >> 8) ^ crctbl[sum & 0xff];
+    } while (cp < lm);
+    *s = sum;
 }
 
-
 /*
  * crcbld - build the CRC-16 partial results table
  */
 
-void
-crcbld()
-{
-	int bit;			/* temporary bit value */
-	unsigned entry;			/* entry under construction */
-	int i;				/* polynomial table index */
-	int j;				/* bit shift count */
-
-	for(i = 0; i < CRC_TBLL; i++) {
-		entry = i;
-		for (j = 1; j <= CRC_BITS; j++) {
-			bit = entry & 1;
-			entry >>= 1;
-			if (bit)
-				entry ^= CRC_POLY;
-		}
-		crctbl[i] = entry;
-	}
+void crcbld() {
+    int bit;        /* temporary bit value */
+    unsigned entry; /* entry under construction */
+    int i;          /* polynomial table index */
+    int j;          /* bit shift count */
+
+    for (i = 0; i < CRC_TBLL; i++) {
+        entry = i;
+        for (j = 1; j <= CRC_BITS; j++) {
+            bit = entry & 1;
+            entry >>= 1;
+            if (bit)
+                entry ^= CRC_POLY;
+        }
+        crctbl[i] = entry;
+    }
 }
 
-
 /*
  * dcpath() - define device cache file paths
  */
 
-int
-dcpath(rw, npw)
-	int rw;				/* read (1) or write (2) mode */
-	int npw;			/* inhibit (0) or enable (1) no
-					 * path warning message */
+int dcpath(struct lsof_context *ctx, int rw, /* read (1) or write (2) mode */
+           int npw)                          /* inhibit (0) or enable (1) no
+                                              * path warning message */
 {
-	char buf[MAXPATHLEN+1], *cp1, *cp2, hn[MAXPATHLEN+1];
-	int endf;
-	int i, j;
-	int l = 0;
-	int ierr = 0;			/* intermediate error state */
-	int merr = 0;			/* malloc error state */
-	struct passwd *p = (struct passwd *)NULL;
-	static short wenv = 1;		/* HASENVDC warning state */
-	static short wpp = 1;		/* HASPERSDCPATH warning state */
-/*
- * Release any space reserved by previous path calls to dcpath().
- */
-	if (DCpath[1]) {
-	    (void) free((FREE_P *)DCpath[1]);
-	    DCpath[1] = (char *)NULL;
-	}
-	if (DCpath[3]) {
-	    (void) free((FREE_P *)DCpath[3]);
-	    DCpath[3] = (char *)NULL;
-	}
-/*
- * If a path was specified via -D, it's character address will have been
- * stored in DCpathArg by ctrl_dcache().  Use that address if the real UID
- * of this process is root, or the mode is read, or the process is neither
- * setuid-root nor setgid.
- */
-	if (Myuid == 0 || rw == 1 || (!Setuidroot && !Setgid))
-	    DCpath[0] = DCpathArg;
-	else
-	    DCpath[0] = (char *)NULL;
-
-# if	defined(HASENVDC)
-/*
- * If HASENVDC is defined, get its value from the environment, unless this
- * is a setuid-root process, or the real UID of the process is 0, or the
- * mode is write and the process is setgid.
- */
-	if ((cp1 = getenv(HASENVDC)) && (l = strlen(cp1)) > 0
-	&&  !Setuidroot && Myuid && (rw == 1 || !Setgid)) {
-	    if (!(cp2 = mkstrcpy(cp1, (MALLOC_S *)NULL))) {
-		(void) fprintf(stderr,
-		    "%s: no space for device cache path: %s=", Pn, HASENVDC);
-		safestrprt(cp1, stderr, 1);
-		merr = 1;
-	    } else
-		DCpath[1] = cp2;
-	} else if (cp1 && l > 0) {
-	    if (!Fwarn && wenv) {
-		(void) fprintf(stderr,
-		    "%s: WARNING: ignoring environment: %s=", Pn, HASENVDC);
-		safestrprt(cp1, stderr, 1);
-	    }
-	    wenv = 0;
-	}
-# endif	/* defined(HASENVDC) */
-
-# if	defined(HASSYSDC)
-/*
- * If HASSYSDC is defined, record the path of the system-wide device
- * cache file, unless the mode is write.
- */
-	if (rw != 2)
-	    DCpath[2] = HASSYSDC;
-	else
-	    DCpath[2] = (char *)NULL;
-# endif	/* defined(HASSYSDC) */
-
-# if	defined(HASPERSDC)
-/*
- * If HASPERSDC is defined, form a personal device cache path by
- * interpreting the conversions specified in it.
- *
- * Get (HASPERSDCPATH) from the environment and add it to the home directory
- * path, if possible.
- */
-	for (cp1 = HASPERSDC, endf = i = 0; *cp1 && !endf; cp1++) {
-	    if (*cp1 != '%') {
-
-	    /*
-	     * If the format character isn't a `%', copy it.
-	     */
-		if (i < (int)sizeof(buf)) {
-		    buf[i++] = *cp1;
-		    continue;
-		} else {
-		    ierr = 2;
-		    break;
-		}
-	     }
-	/*
-	 * `%' starts a conversion; the next character specifies
-	 * the conversion type.
-	 */
-	    cp1++;
-	    switch (*cp1) {
-
-	    /*
-	     * Two consecutive `%' characters convert to one `%'
-	     * character in the output.
-	     */
-
-	    case '%':
-		if (i < (int)sizeof(buf))
-			buf[i++] = '%';
-		else
-			ierr = 2;
-		break;
-
-	    /*
-	     * ``%0'' defines a root boundary.  If the effective
-	     * (setuid-root) or real UID of the process is root, any
-	     * path formed to this point is discarded and path formation
-	     * begins with the next character.
-	     *
-	     * If neither the effective nor the real UID is root, path
-	     * formation ends.
-	     *
-	     * This allows HASPERSDC to specify one path for non-root
-	     * UIDs and another for the root (effective or real) UID.
-	     */
-
-	    case '0':
-		if (Setuidroot || !Myuid)
-		    i = 0;
-		else
-		    endf = 1;
-		break;
-
-	    /*
-	     * ``%h'' converts to the home directory.
-	     */
-
-	    case 'h':
-		if (!p && !(p = getpwuid(Myuid))) {
-		    if (!Fwarn)
-			(void) fprintf(stderr,
-			    "%s: WARNING: can't get home dir for UID: %d\n",
-			    Pn, (int)Myuid);
-		    ierr = 1;
-		    break;
-		}
-		if ((i + (l = strlen(p->pw_dir))) >= (int)sizeof(buf)) {
-		    ierr = 2;
-		    break;
-		}
-		(void) strcpy(&buf[i], p->pw_dir);
-		i += l;
-		if (i > 0 && buf[i - 1] == '/' && *(cp1 + 1)) {
-
-		/*
-		 * If the home directory ends in a '/' and the next format
-		 * character is a '/', delete the '/' at the end of the home
-		 * directory.
-		 */
-		    i--;
-		    buf[i] = '\0';
-		}
-		break;
-
-	    /*
-	     * ``%l'' converts to the full host name.
-	     *
-	     * ``%L'' converts to the first component (characters up
-	     * to the first `.') of the host name.
-	     */
-
-	    case 'l':
-	    case 'L':
-		if (gethostname(hn, sizeof(hn) - 1) < 0) {
-		    if (!Fwarn)
-			(void) fprintf(stderr,
-			    "%s: WARNING: no gethostname for %%l or %%L: %s\n",
-			    Pn, strerror(errno));
-		    ierr = 1;
-		    break;
-		}
-		hn[sizeof(hn) - 1] = '\0';
-		if (*cp1 == 'L' && (cp2 = strchr(hn, '.')) && cp2 > hn)
-		    *cp2 = '\0';
-		j = strlen(hn);
-		if ((j + i) < (int)sizeof(buf)) {
-		    (void) strcpy(&buf[i], hn);
-		    i += j;
-		} else
-		    ierr = 2;
-		break;
-
-	    /*
-	     * ``%p'' converts to the contents of LSOFPERSDCPATH, followed
-	     * by a '/'.
-	     *
-	     * It is ignored when:
-	     *
-	     *    The lsof process is setuid-root;
-	     *    The real UID of the lsof process is 0;
-	     *    The mode is write and the process is setgid.
-	     */
-
-	    case 'p':
-
-#  if	defined(HASPERSDCPATH)
-		if ((cp2 = getenv(HASPERSDCPATH))
-		&&  (l = strlen(cp2)) > 0
-		&&  !Setuidroot
-		&&  Myuid
-		&&  (rw == 1 || !Setgid))
-		{
-		    if (i && buf[i - 1] == '/' && *cp2 == '/') {
-			cp2++;
-			l--;
-		    }
-		    if ((i + l) < ((int)sizeof(buf) - 1)) {
-			(void) strcpy(&buf[i], cp2);
-			i += l;
-			if (buf[i - 1] != '/') {
-			    if (i < ((int)sizeof(buf) - 2)) {
-				buf[i++] = '/';
-				buf[i] = '\0';
-			    } else
-				ierr = 2;
-			}
-		    } else
-			ierr = 2;
-		} else {
-		    if (cp2 && l > 0)  {
-			if (!Fwarn && wpp) {
-			    (void) fprintf(stderr,
-				"%s: WARNING: ignoring environment: %s",
-				Pn, HASPERSDCPATH);
-			    safestrprt(cp2, stderr, 1);
-			}
-			wpp = 0;
-		    }
-		}
-#  else	/* !defined(HASPERSDCPATH) */
-		if (!Fwarn && wpp)
-		    (void) fprintf(stderr,
-			"%s: WARNING: HASPERSDCPATH disabled: %s\n",
-			Pn, HASPERSDC);
-		ierr = 1;
-		wpp = 0;
-#  endif	/* defined(HASPERSDCPATH) */
-
-		break;
-
-	    /*
-	     * ``%u'' converts to the login name of the real UID of the
-	     * lsof process.
-	     */
-
-	    case 'u':
-		if (!p && !(p = getpwuid(Myuid))) {
-		    if (!Fwarn)
-			(void) fprintf(stderr,
-			    "%s: WARNING: can't get login name for UID: %d\n",
-			    Pn, (int)Myuid);
-		    ierr = 1;
-		    break;
-		}
-		if ((i + (l = strlen(p->pw_name))) >= (int)sizeof(buf)) {
-		    ierr = 2;
-		    break;
-		}
-		(void) strcpy(&buf[i], p->pw_name);
-		i += l;
-		break;
-
-	    /*
-	     * ``%U'' converts to the real UID of the lsof process.
-	     */
-
-	    case 'U':
-		(void) snpf(hn, sizeof(hn), "%d", (int)Myuid);
-		if ((i + (l = strlen(hn))) >= (int)sizeof(buf))
-		    ierr = 2;
-		else {
-		    (void) strcpy(&buf[i], hn);
-		    i += l;
-		}
-		break;
-	    default:
-		if (!Fwarn)
-		    (void) fprintf(stderr,
-			"%s: WARNING: bad conversion (%%%c): %s\n",
-			Pn, *cp1, HASPERSDC);
-		ierr = 1;
-	    }
-	    if (endf || ierr > 1)
-		break;
-	}
-	if (ierr) {
-
-	/*
-	 * If there was an intermediate error of some type, handle it.
-	 * A type 1 intermediate error has already been noted with a
-	 * warning message.  A type 2 intermediate error requires the
-	 * issuing of a buffer overlow warning message.
-	 */
-	    if (ierr == 2 && !Fwarn)
-		(void) fprintf(stderr,
-	 	    "%s: WARNING: device cache path too large: %s\n",
-		    Pn, HASPERSDC);
-	    i = 0;
-	}
-	buf[i] = '\0';
-/*
- * If there is one, allocate space for the personal device cache path,
- * copy buf[] to it, and store its pointer in DCpath[3].
- */
-	if (i) {
-	    if (!(cp1 = mkstrcpy(buf, (MALLOC_S *)NULL))) {
-		(void) fprintf(stderr,
-		    "%s: no space for device cache path: ", Pn);
-		safestrprt(buf, stderr, 1);
-		merr = 1;
-	    } else
-		DCpath[3] = cp1;
-	}
-# endif	/* defined(HASPERSDC) */
-
-/*
- * Quit if there was a malloc() error.  The appropriate error message
- * will have been issued to stderr.
- */
-	if (merr)
-	    Error();
-/*
- * Return the index of the first defined path.  Since DCpath[] is arranged
- * in priority order, searching it beginning to end follows priority.
- * Return an error indication if the search discloses no path name.
- */
-	for (i = 0; i < MAXDCPATH; i++) {
-	    if (DCpath[i])
-		return(i);
-	}
-	if (!Fwarn && npw)
-	    (void) fprintf(stderr,
-		"%s: WARNING: can't form any device cache path\n", Pn);
-	return(-1);
+    char buf[MAXPATHLEN + 1], *cp1, *cp2, hn[MAXPATHLEN + 1];
+    int endf;
+    int i, j;
+    int l = 0;
+    int ierr = 0; /* intermediate error state */
+    int merr = 0; /* malloc error state */
+    struct passwd *p = (struct passwd *)NULL;
+    static short wenv = 1; /* HASENVDC warning state */
+    static short wpp = 1;  /* HASPERSDCPATH warning state */
+                           /*
+                            * Release any space reserved by previous path calls to dcpath().
+                            */
+    if (DCpath[1]) {
+        (void)free((FREE_P *)DCpath[1]);
+        DCpath[1] = (char *)NULL;
+    }
+    if (DCpath[3]) {
+        (void)free((FREE_P *)DCpath[3]);
+        DCpath[3] = (char *)NULL;
+    }
+    /*
+     * If a path was specified via -D, its character address will have been
+     * stored in DCpathArg by ctrl_dcache().  Use that address if the real UID
+     * of this process is root, or the mode is read, or the process is neither
+     * setuid-root nor setgid.
+     */
+    if (Myuid == 0 || rw == 1 || (!Setuidroot && !Setgid))
+        DCpath[0] = DCpathArg;
+    else
+        DCpath[0] = (char *)NULL;
+
+#    if defined(HASENVDC)
+    /*
+     * If HASENVDC is defined, get its value from the environment, unless this
+     * is a setuid-root process, or the real UID of the process is 0, or the
+     * mode is write and the process is setgid.
+     */
+    if ((cp1 = getenv(HASENVDC)) && (l = strlen(cp1)) > 0 && !Setuidroot &&
+        Myuid && (rw == 1 || !Setgid)) {
+        if (!(cp2 = mkstrcpy(cp1, (MALLOC_S *)NULL))) {
+            (void)fprintf(stderr, "%s: no space for device cache path: %s=", Pn,
+                          HASENVDC);
+            safestrprt(cp1, stderr, 1);
+            merr = 1;
+        } else
+            DCpath[1] = cp2;
+    } else if (cp1 && l > 0) {
+        if (!Fwarn && wenv) {
+            (void)fprintf(stderr, "%s: WARNING: ignoring environment: %s=", Pn,
+                          HASENVDC);
+            safestrprt(cp1, stderr, 1);
+        }
+        wenv = 0;
+    }
+#    endif /* defined(HASENVDC) */
+
+#    if defined(HASSYSDC)
+    /*
+     * If HASSYSDC is defined, record the path of the system-wide device
+     * cache file, unless the mode is write.
+     */
+    if (rw != 2)
+        DCpath[2] = HASSYSDC;
+    else
+        DCpath[2] = (char *)NULL;
+#    endif /* defined(HASSYSDC) */
+
+#    if defined(HASPERSDC)
+    /*
+     * If HASPERSDC is defined, form a personal device cache path by
+     * interpreting the conversions specified in it.
+     *
+     * Get (HASPERSDCPATH) from the environment and add it to the home directory
+     * path, if possible.
+     */
+    for (cp1 = HASPERSDC, endf = i = 0; *cp1 && !endf; cp1++) {
+        if (*cp1 != '%') {
+
+            /*
+             * If the format character isn't a `%', copy it.
+             */
+            if (i < (int)sizeof(buf)) {
+                buf[i++] = *cp1;
+                continue;
+            } else {
+                ierr = 2;
+                break;
+            }
+        }
+        /*
+         * `%' starts a conversion; the next character specifies
+         * the conversion type.
+         */
+        cp1++;
+        switch (*cp1) {
+
+            /*
+             * Two consecutive `%' characters convert to one `%'
+             * character in the output.
+             */
+
+        case '%':
+            if (i < (int)sizeof(buf))
+                buf[i++] = '%';
+            else
+                ierr = 2;
+            break;
+
+            /*
+             * ``%0'' defines a root boundary.  If the effective
+             * (setuid-root) or real UID of the process is root, any
+             * path formed to this point is discarded and path formation
+             * begins with the next character.
+             *
+             * If neither the effective nor the real UID is root, path
+             * formation ends.
+             *
+             * This allows HASPERSDC to specify one path for non-root
+             * UIDs and another for the root (effective or real) UID.
+             */
+
+        case '0':
+            if (Setuidroot || !Myuid)
+                i = 0;
+            else
+                endf = 1;
+            break;
+
+            /*
+             * ``%h'' converts to the home directory.
+             */
+
+        case 'h':
+            if (!p && !(p = getpwuid(Myuid))) {
+                if (!Fwarn)
+                    (void)fprintf(
+                        stderr, "%s: WARNING: can't get home dir for UID: %d\n",
+                        Pn, (int)Myuid);
+                ierr = 1;
+                break;
+            }
+            if ((i + (l = strlen(p->pw_dir))) >= (int)sizeof(buf)) {
+                ierr = 2;
+                break;
+            }
+            (void)strcpy(&buf[i], p->pw_dir);
+            i += l;
+            if (i > 0 && buf[i - 1] == '/' && *(cp1 + 1)) {
+
+                /*
+                 * If the home directory ends in a '/' and the next format
+                 * character is a '/', delete the '/' at the end of the home
+                 * directory.
+                 */
+                i--;
+                buf[i] = '\0';
+            }
+            break;
+
+            /*
+             * ``%l'' converts to the full host name.
+             *
+             * ``%L'' converts to the first component (characters up
+             * to the first `.') of the host name.
+             */
+
+        case 'l':
+        case 'L':
+            if (gethostname(hn, sizeof(hn) - 1) < 0) {
+                if (!Fwarn)
+                    (void)fprintf(
+                        stderr,
+                        "%s: WARNING: no gethostname for %%l or %%L: %s\n", Pn,
+                        strerror(errno));
+                ierr = 1;
+                break;
+            }
+            hn[sizeof(hn) - 1] = '\0';
+            if (*cp1 == 'L' && (cp2 = strchr(hn, '.')) && cp2 > hn)
+                *cp2 = '\0';
+            j = strlen(hn);
+            if ((j + i) < (int)sizeof(buf)) {
+                (void)strcpy(&buf[i], hn);
+                i += j;
+            } else
+                ierr = 2;
+            break;
+
+            /*
+             * ``%p'' converts to the contents of LSOFPERSDCPATH, followed
+             * by a '/'.
+             *
+             * It is ignored when:
+             *
+             *    The lsof process is setuid-root;
+             *    The real UID of the lsof process is 0;
+             *    The mode is write and the process is setgid.
+             */
+
+        case 'p':
+
+#        if defined(HASPERSDCPATH)
+            if ((cp2 = getenv(HASPERSDCPATH)) && (l = strlen(cp2)) > 0 &&
+                !Setuidroot && Myuid && (rw == 1 || !Setgid)) {
+                if (i && buf[i - 1] == '/' && *cp2 == '/') {
+                    cp2++;
+                    l--;
+                }
+                if ((i + l) < ((int)sizeof(buf) - 1)) {
+                    (void)strcpy(&buf[i], cp2);
+                    i += l;
+                    if (buf[i - 1] != '/') {
+                        if (i < ((int)sizeof(buf) - 2)) {
+                            buf[i++] = '/';
+                            buf[i] = '\0';
+                        } else
+                            ierr = 2;
+                    }
+                } else
+                    ierr = 2;
+            } else {
+                if (cp2 && l > 0) {
+                    if (!Fwarn && wpp) {
+                        (void)fprintf(stderr,
+                                      "%s: WARNING: ignoring environment: %s",
+                                      Pn, HASPERSDCPATH);
+                        safestrprt(cp2, stderr, 1);
+                    }
+                    wpp = 0;
+                }
+            }
+#        else  /* !defined(HASPERSDCPATH) */
+            if (!Fwarn && wpp)
+                (void)fprintf(stderr,
+                              "%s: WARNING: HASPERSDCPATH disabled: %s\n", Pn,
+                              HASPERSDC);
+            ierr = 1;
+            wpp = 0;
+#        endif /* defined(HASPERSDCPATH) */
+
+            break;
+
+            /*
+             * ``%u'' converts to the login name of the real UID of the
+             * lsof process.
+             */
+
+        case 'u':
+            if (!p && !(p = getpwuid(Myuid))) {
+                if (!Fwarn)
+                    (void)fprintf(
+                        stderr,
+                        "%s: WARNING: can't get login name for UID: %d\n", Pn,
+                        (int)Myuid);
+                ierr = 1;
+                break;
+            }
+            if ((i + (l = strlen(p->pw_name))) >= (int)sizeof(buf)) {
+                ierr = 2;
+                break;
+            }
+            (void)strcpy(&buf[i], p->pw_name);
+            i += l;
+            break;
+
+            /*
+             * ``%U'' converts to the real UID of the lsof process.
+             */
+
+        case 'U':
+            (void)snpf(hn, sizeof(hn), "%d", (int)Myuid);
+            if ((i + (l = strlen(hn))) >= (int)sizeof(buf))
+                ierr = 2;
+            else {
+                (void)strcpy(&buf[i], hn);
+                i += l;
+            }
+            break;
+        default:
+            if (!Fwarn)
+                (void)fprintf(stderr,
+                              "%s: WARNING: bad conversion (%%%c): %s\n", Pn,
+                              *cp1, HASPERSDC);
+            ierr = 1;
+        }
+        if (endf || ierr > 1)
+            break;
+    }
+    if (ierr) {
+
+        /*
+         * If there was an intermediate error of some type, handle it.
+         * A type 1 intermediate error has already been noted with a
+         * warning message.  A type 2 intermediate error requires the
+         * issuing of a buffer overflow warning message.
+         */
+        if (ierr == 2 && !Fwarn)
+            (void)fprintf(stderr,
+                          "%s: WARNING: device cache path too large: %s\n", Pn,
+                          HASPERSDC);
+        i = 0;
+    }
+    buf[i] = '\0';
+    /*
+     * If there is one, allocate space for the personal device cache path,
+     * copy buf[] to it, and store its pointer in DCpath[3].
+     */
+    if (i) {
+        if (!(cp1 = mkstrcpy(buf, (MALLOC_S *)NULL))) {
+            (void)fprintf(stderr, "%s: no space for device cache path: ", Pn);
+            safestrprt(buf, stderr, 1);
+            merr = 1;
+        } else
+            DCpath[3] = cp1;
+    }
+#    endif /* defined(HASPERSDC) */
+
+    /*
+     * Quit if there was a malloc() error.  The appropriate error message
+     * will have been issued to stderr.
+     */
+    if (merr)
+        Error(ctx);
+    /*
+     * Return the index of the first defined path.  Since DCpath[] is arranged
+     * in priority order, searching it beginning to end follows priority.
+     * Return an error indication if the search discloses no path name.
+     */
+    for (i = 0; i < MAXDCPATH; i++) {
+        if (DCpath[i])
+            return (i);
+    }
+    if (!Fwarn && npw)
+        (void)fprintf(stderr, "%s: WARNING: can't form any device cache path\n",
+                      Pn);
+    return (-1);
 }
 
-
 /*
  * open_dcache() - open device cache file
  */
 
-int
-open_dcache(m, r, s)
-	int m;			/* mode: 1 = read; 2 = write */
-	int r;			/* create DCpath[] if 0, reuse if 1 */
-	struct stat *s;		/* stat() receiver */
+int open_dcache(struct lsof_context *ctx, int m, /* mode: 1 = read; 2 = write */
+                int r,          /* create DCpath[] if 0, reuse if 1 */
+                struct stat *s) /* stat() receiver */
 {
-	char buf[128];
-	char *w = (char *)NULL;
-/*
- * Get the device cache file paths.
- */
-	if (!r) {
-	    if ((DCpathX = dcpath(m, 1)) < 0)
-		return(1);
-	}
-/*
- * Switch to the requested open() action.
- */
-	switch (m) {
-	case 1:
-
-	/*
-	 * Check for access permission.
-	 */
-	    if (!is_readable(DCpath[DCpathX], 0)) {
-		if (DCpathX == 2 && errno == ENOENT)
-		    return(2);
-		if (!Fwarn)
-		    (void) fprintf(stderr, ACCESSERRFMT,
-			Pn, DCpath[DCpathX], strerror(errno));
-		return(1);
-	    }
-	/*
-	 * Open for reading.
-	 */
-	    if ((DCfd = open(DCpath[DCpathX], O_RDONLY, 0)) < 0) {
-		if (DCstate == 3 && errno == ENOENT)
-		    return(1);
-
-cant_open:
-		    (void) fprintf(stderr,
-			"%s: WARNING: can't open %s: %s\n",
-			Pn, DCpath[DCpathX], strerror(errno));
-		return(1);
-	    }
-	    if (stat(DCpath[DCpathX], s) != 0) {
-
-cant_stat:
-		if (!Fwarn)
-		    (void) fprintf(stderr,
-			"%s: WARNING: can't stat(%s): %s\n",
-			Pn, DCpath[DCpathX], strerror(errno));
-close_exit:
-		(void) close(DCfd);
-		DCfd = -1;
-		return(1);
-	    }
-	    if ((int)(s->st_mode & 07777) != ((DCpathX == 2) ? 0644 : 0600)) {
-		(void) snpf(buf, sizeof(buf), "doesn't have %04o modes",
-	    	    (DCpathX == 2) ? 0644 : 0600);
-		w = buf;
-	    } else if ((s->st_mode & S_IFMT) != S_IFREG)
-		w = "isn't a regular file";
-	    else if (!s->st_size)
-		w = "is empty";
-	    if (w) {
-		if (!Fwarn)
-		    (void) fprintf(stderr,
-			"%s: WARNING: %s %s.\n", Pn, DCpath[DCpathX], w);
-		goto close_exit;
-	    }
-	    return(0);
-	case 2:
-
-	/*
-	 * Open for writing: first unlink any previous version; then
-	 * open exclusively, specifying it's an error if the file exists.
-	 */
-	    if (unlink(DCpath[DCpathX]) < 0) {
-		if (errno != ENOENT) {
-		    if (!Fwarn)
-			(void) fprintf(stderr,
-			    "%s: WARNING: can't unlink %s: %s\n",
-			    Pn, DCpath[DCpathX], strerror(errno));
-		    return(1);
-		}
-	    }
-	    if ((DCfd = open(DCpath[DCpathX], O_RDWR|O_CREAT|O_EXCL, 0600)) < 0)
-		goto cant_open;
-	/*
-	 * If the real user is not root, but the process is setuid-root,
-	 * change the ownerships of the file to the real ones.
-	 */
-	    if (Myuid && Setuidroot) {
-
-# if	defined(DVCH_CHOWN)
-	 	if (chown(DCpath[DCpathX], Myuid, getgid()) < 0)
-# else	/* !defined(DVCH_CHOWN) */
-	 	if (fchown(DCfd, Myuid, getgid()) < 0)
-# endif	/* defined(DVCH_CHOWN) */
-
-		{
-		    if (!Fwarn)
-			(void) fprintf(stderr,
-			     "%s: WARNING: can't change ownerships of %s: %s\n",
-			     Pn, DCpath[DCpathX], strerror(errno));
-	 	}
-	    }
-	    if (!Fwarn && DCstate != 1 && !DCunsafe)
-		(void) fprintf(stderr,
-		    "%s: WARNING: created device cache file: %s\n",
-			Pn, DCpath[DCpathX]);
-	    if (stat(DCpath[DCpathX], s) != 0) {
-		(void) unlink(DCpath[DCpathX]);
-		goto cant_stat;
-	    }
-	    return(0);
-	default:
-
-	/*
-	 * Oops!
-	 */
-	    (void) fprintf(stderr, "%s: internal error: open_dcache=%d\n",
-		Pn, m);
-	    Error();
-	}
-	return(1);
+    char buf[128];
+    char *w = (char *)NULL;
+    /*
+     * Get the device cache file paths.
+     */
+    if (!r) {
+        if ((DCpathX = dcpath(ctx, m, 1)) < 0)
+            return (1);
+    }
+    /*
+     * Switch to the requested open() action.
+     */
+    switch (m) {
+    case 1:
+
+        /*
+         * Check for access permission.
+         */
+        if (!is_readable(ctx, DCpath[DCpathX], 0)) {
+            if (DCpathX == 2 && errno == ENOENT)
+                return (2);
+            if (!Fwarn)
+                (void)fprintf(stderr, ACCESSERRFMT, Pn, DCpath[DCpathX],
+                              strerror(errno));
+            return (1);
+        }
+        /*
+         * Open for reading.
+         */
+        if ((DCfd = open(DCpath[DCpathX], O_RDONLY, 0)) < 0) {
+            if (DCstate == 3 && errno == ENOENT)
+                return (1);
+
+        cant_open:
+            (void)fprintf(stderr, "%s: WARNING: can't open %s: %s\n", Pn,
+                          DCpath[DCpathX], strerror(errno));
+            return (1);
+        }
+        if (stat(DCpath[DCpathX], s) != 0) {
+
+        cant_stat:
+            if (!Fwarn)
+                (void)fprintf(stderr, "%s: WARNING: can't stat(%s): %s\n", Pn,
+                              DCpath[DCpathX], strerror(errno));
+        close_exit:
+            (void)close(DCfd);
+            DCfd = -1;
+            return (1);
+        }
+        if ((int)(s->st_mode & 07777) != ((DCpathX == 2) ? 0644 : 0600)) {
+            (void)snpf(buf, sizeof(buf), "doesn't have %04o modes",
+                       (DCpathX == 2) ? 0644 : 0600);
+            w = buf;
+        } else if ((s->st_mode & S_IFMT) != S_IFREG)
+            w = "isn't a regular file";
+        else if (!s->st_size)
+            w = "is empty";
+        if (w) {
+            if (!Fwarn)
+                (void)fprintf(stderr, "%s: WARNING: %s %s.\n", Pn,
+                              DCpath[DCpathX], w);
+            goto close_exit;
+        }
+        return (0);
+    case 2:
+
+        /*
+         * Open for writing: first unlink any previous version; then
+         * open exclusively, specifying it's an error if the file exists.
+         */
+        if (unlink(DCpath[DCpathX]) < 0) {
+            if (errno != ENOENT) {
+                if (!Fwarn)
+                    (void)fprintf(stderr, "%s: WARNING: can't unlink %s: %s\n",
+                                  Pn, DCpath[DCpathX], strerror(errno));
+                return (1);
+            }
+        }
+        if ((DCfd = open(DCpath[DCpathX], O_RDWR | O_CREAT | O_EXCL, 0600)) < 0)
+            goto cant_open;
+        /*
+         * If the real user is not root, but the process is setuid-root,
+         * change the ownerships of the file to the real ones.
+         */
+        if (Myuid && Setuidroot) {
+
+#    if defined(DVCH_CHOWN)
+            if (chown(DCpath[DCpathX], Myuid, getgid()) < 0)
+#    else  /* !defined(DVCH_CHOWN) */
+            if (fchown(DCfd, Myuid, getgid()) < 0)
+#    endif /* defined(DVCH_CHOWN) */
+
+            {
+                if (!Fwarn)
+                    (void)fprintf(
+                        stderr,
+                        "%s: WARNING: can't change ownerships of %s: %s\n", Pn,
+                        DCpath[DCpathX], strerror(errno));
+            }
+        }
+        if (!Fwarn && DCstate != 1 && !DCunsafe)
+            (void)fprintf(stderr,
+                          "%s: WARNING: created device cache file: %s\n", Pn,
+                          DCpath[DCpathX]);
+        if (stat(DCpath[DCpathX], s) != 0) {
+            (void)unlink(DCpath[DCpathX]);
+            goto cant_stat;
+        }
+        return (0);
+    default:
+
+        /*
+         * Oops!
+         */
+        (void)fprintf(stderr, "%s: internal error: open_dcache=%d\n", Pn, m);
+        Error(ctx);
+    }
+    return (1);
 }
 
-
 /*
  * read_dcache() - read device cache file
  */
 
-int
-read_dcache()
-{
-	char buf[MAXPATHLEN*2], cbuf[64], *cp;
-	int i, len, ov;
-	struct stat sb, devsb;
-/*
- * Open the device cache file.
- *
- * If the open at HASSYSDC fails because the file doesn't exist, and
- * the real UID of this process is not zero, try to open a device cache
- * file at HASPERSDC.
- */
-	if ((ov = open_dcache(1, 0, &sb)) != 0) {
-	    if (DCpathX == 2) {
-		if (ov == 2 && DCpath[3]) {
-		    DCpathX = 3;
-		    if (open_dcache(1, 1, &sb) != 0)
-			return(1);
-		} else
-		    return(1);
-	    } else
-		return(1);
-	}
-/*
- * If the open device cache file's last mtime/ctime isn't greater than
- * DVCH_DEVPATH's mtime/ctime, ignore it, unless -Dr was specified.
- */
-	if (stat(DVCH_DEVPATH, &devsb) != 0) {
-	    if (!Fwarn)
-		(void) fprintf(stderr,
-		    "%s: WARNING: can't stat(%s): %s\n",
-		    Pn, DVCH_DEVPATH, strerror(errno));
-	} else {
-	    if (sb.st_mtime <= devsb.st_mtime || sb.st_ctime <= devsb.st_ctime)
-		DCunsafe = 1;
-	}
-	if (!(DCfs = fdopen(DCfd, "r"))) {
-	    if (!Fwarn)
-		(void) fprintf(stderr,
-		    "%s: WARNING: can't fdopen(%s)\n", Pn, DCpath[DCpathX]);
-	    (void) close(DCfd);
-	    DCfd = -1;
-	    return(1);
-	}
-/*
- * Read the section count line; initialize the CRC table;
- * validate the section count line.
- */
-	if (!fgets(buf, sizeof(buf), DCfs)) {
-
-cant_read:
-	    if (!Fwarn)
-		(void) fprintf(stderr,
-		    "%s: WARNING: can't fread %s: %s\n", Pn, DCpath[DCpathX],
-		    strerror(errno));
-read_close:
-		(void) fclose(DCfs);
-		DCfd = -1;
-		DCfs = (FILE *)NULL;
-		(void) clr_devtab();
-
-# if	defined(DCACHE_CLR)
-		(void) DCACHE_CLR();
-# endif	/* defined(DCACHE_CLR) */
-
-		return(1);
-	}
-	(void) crcbld();
-	DCcksum = 0;
-	(void) crc(buf, strlen(buf), &DCcksum);
-	i = 1;
-	cp = "";
-
-# if	defined(HASBLKDEV)
-	i++;
-	cp = "s";
-# endif	/* defined(HASBLKDEV) */
-
-# if	defined(DCACHE_CLONE)
-	i++;
-	cp = "s";
-# endif	/* defined(DCACHE_CLONE) */
-
-# if	defined(DCACHE_PSEUDO)
-	i++;
-	cp = "s";
-# endif	/* defined(DCACHE_PSEUDO) */
-
-	(void) snpf(cbuf, sizeof(cbuf), "%d section%s", i, cp);
-	len = strlen(cbuf);
-	(void) snpf(&cbuf[len], sizeof(cbuf) - len, ", dev=%lx\n",
-		    (long)DevDev);
-	if (!strncmp(buf, cbuf, len) && (buf[len] == '\n')) {
-	    if (!Fwarn) {
-		(void) fprintf(stderr,
-		    "%s: WARNING: no /dev device in %s: line ", Pn,
-		    DCpath[DCpathX]);
-		safestrprt(buf, stderr, 1+4+8);
-	    }
-	    goto read_close;
-	}
-	if (strcmp(buf, cbuf)) {
-	    if (!Fwarn) {
-		(void) fprintf(stderr,
-		    "%s: WARNING: bad section count line in %s: line ",
-		    Pn, DCpath[DCpathX]);
-		safestrprt(buf, stderr, 1+4+8);
-	    }
-	    goto read_close;
-	}
-/*
- * Read device section header and validate it.
- */
-	if (!fgets(buf, sizeof(buf), DCfs))
-	    goto cant_read;
-	(void) crc(buf, strlen(buf), &DCcksum);
-	len = strlen("device section: ");
-	if (strncmp(buf, "device section: ", len) != 0) {
-
-read_dhdr:
-	    if (!Fwarn) {
-		(void) fprintf(stderr,
-		    "%s: WARNING: bad device section header in %s: line ",
-		    Pn, DCpath[DCpathX]);
-		safestrprt(buf, stderr, 1+4+8);
-	    }
-	    goto read_close;
-	}
-/*
- * Compute the device count; allocate Sdev[] and Devtp[] space.
- */
-	if ((Ndev = atoi(&buf[len])) < 1)
-	    goto read_dhdr;
-	alloc_dcache();
-/*
- * Read the device lines and store their information in Devtp[].
- * Construct the Sdev[] pointers to Devtp[].
- */
-	for (i = 0; i < Ndev; i++) {
-	    if (!fgets(buf, sizeof(buf), DCfs)) {
-		if (!Fwarn)
-		    (void) fprintf(stderr,
-			"%s: WARNING: can't read device %d from %s\n",
-			Pn, i + 1, DCpath[DCpathX]);
-		goto read_close;
-	    }
-	    (void) crc(buf, strlen(buf), &DCcksum);
-	/*
-	 * Convert hexadecimal device number.
-	 */
-	    if (!(cp = x2dev(buf, &Devtp[i].rdev)) || *cp != ' ') {
-		if (!Fwarn) {
-		    (void) fprintf(stderr,
-			"%s: device %d: bad device in %s: line ",
-			Pn, i + 1, DCpath[DCpathX]);
-		    safestrprt(buf, stderr, 1+4+8);
-		}
-		goto read_close;
-	    }
-	/*
-	 * Convert inode number.
-	 */
-	    for (cp++, Devtp[i].inode = (INODETYPE)0; *cp != ' '; cp++) {
-		if (*cp < '0' || *cp > '9') {
-		    if (!Fwarn) {
-			(void) fprintf(stderr,
-			    "%s: WARNING: device %d: bad inode # in %s: line ",
-			    Pn, i + 1, DCpath[DCpathX]);
-			safestrprt(buf, stderr, 1+4+8);
-		    }
-		    goto read_close;
-		}
-		Devtp[i].inode = (INODETYPE)((Devtp[i].inode * 10)
-			       + (int)(*cp - '0'));
-	    }
-	/*
-	 * Get path name; allocate space for it; copy it; store the
-	 * pointer in Devtp[]; clear verify status; construct the Sdev[]
-	 * pointer to Devtp[].
-	 */
-	    if ((len = strlen(++cp)) < 2 || *(cp + len - 1) != '\n') {
-		if (!Fwarn) {
-		    (void) fprintf(stderr,
-			"%s: WARNING: device %d: bad path in %s: line ",
-			Pn, i + 1, DCpath[DCpathX]);
-		    safestrprt(buf, stderr, 1+4+8);
-		 }
-		 goto read_close;
-	    }
-	    *(cp + len - 1) = '\0';
-	    if (!(Devtp[i].name = mkstrcpy(cp, (MALLOC_S *)NULL))) {
-		(void) fprintf(stderr,
-		    "%s: device %d: no space for path: line ", Pn, i + 1);
-		safestrprt(buf, stderr, 1+4+8);
-		Error();
-	    }
-	    Devtp[i].v = 0;
-	    Sdev[i] = &Devtp[i];
-	}
-
-# if	defined(HASBLKDEV)
-/*
- * Read block device section header and validate it.
- */
-	if (!fgets(buf, sizeof(buf), DCfs))
-	    goto cant_read;
-	(void) crc(buf, strlen(buf), &DCcksum);
-	len = strlen("block device section: ");
-	if (strncmp(buf, "block device section: ", len) != 0) {
-	    if (!Fwarn) {
-		(void) fprintf(stderr,
-		    "%s: WARNING: bad block device section header in %s: line ",
-		    Pn, DCpath[DCpathX]);
-		safestrprt(buf, stderr, 1+4+8);
-	    }
-	    goto read_close;
-	}
-/*
- * Compute the block device count; allocate BSdev[] and BDevtp[] space.
- */
-	if ((BNdev = atoi(&buf[len])) > 0) {
-	    alloc_bdcache();
-	/*
-	 * Read the block device lines and store their information in BDevtp[].
-	 * Construct the BSdev[] pointers to BDevtp[].
-	 */
-	    for (i = 0; i < BNdev; i++) {
-		if (!fgets(buf, sizeof(buf), DCfs)) {
-		    if (!Fwarn)
-			(void) fprintf(stderr,
-			    "%s: WARNING: can't read block device %d from %s\n",
-			    Pn, i + 1, DCpath[DCpathX]);
-		    goto read_close;
-		}
-		(void) crc(buf, strlen(buf), &DCcksum);
-	    /*
-	     * Convert hexadecimal device number.
-	     */
-		if (!(cp = x2dev(buf, &BDevtp[i].rdev)) || *cp != ' ') {
-		    if (!Fwarn) {
-			(void) fprintf(stderr,
-			    "%s: block dev %d: bad device in %s: line ",
-			    Pn, i + 1, DCpath[DCpathX]);
-			safestrprt(buf, stderr, 1+4+8);
-		    }
-		    goto read_close;
-		}
-	    /*
-	     * Convert inode number.
-	     */
-		for (cp++, BDevtp[i].inode = (INODETYPE)0; *cp != ' '; cp++) {
-		    if (*cp < '0' || *cp > '9') {
-		      if (!Fwarn) {
-			(void) fprintf(stderr,
-			  "%s: WARNING: block dev %d: bad inode # in %s: line ",
-			  Pn, i + 1, DCpath[DCpathX]);
-			safestrprt(buf, stderr, 1+4+8);
-		      }
-		      goto read_close;
-		    }
-		    BDevtp[i].inode = (INODETYPE)((BDevtp[i].inode * 10)
-				    + (int)(*cp - '0'));
-		}
-	    /*
-	     * Get path name; allocate space for it; copy it; store the
-	     * pointer in BDevtp[]; clear verify status; construct the BSdev[]
-	     * pointer to BDevtp[].
-	     */
-		if ((len = strlen(++cp)) < 2 || *(cp + len - 1) != '\n') {
-		    if (!Fwarn) {
-			(void) fprintf(stderr,
-			    "%s: WARNING: block dev %d: bad path in %s: line",
-			    Pn, i + 1, DCpath[DCpathX]);
-			safestrprt(buf, stderr, 1+4+8);
-		    }
-		    goto read_close;
-		}
-	        *(cp + len - 1) = '\0';
-		if (!(BDevtp[i].name = mkstrcpy(cp, (MALLOC_S *)NULL))) {
-		    (void) fprintf(stderr,
-			"%s: block dev %d: no space for path: line", Pn, i + 1);
-		    safestrprt(buf, stderr, 1+4+8);
-		    Error();
-		}
-	        BDevtp[i].v = 0;
-	        BSdev[i] = &BDevtp[i];
-	    }
-	}
-# endif	/* defined(HASBLKDEV) */
-
-# if	defined(DCACHE_CLONE)
-/*
- * Read the clone section.
- */
-	if (DCACHE_CLONE(1))
-	    goto read_close;
-# endif	/* defined(DCACHE_CLONE) */
-
-# if	defined(DCACHE_PSEUDO)
-/*
- * Read the pseudo section.
- */
-	if (DCACHE_PSEUDO(1))
-	    goto read_close;
-# endif	/* defined(DCACHE_PSEUDO) */
-
-/*
- * Read and check the CRC section; it must be the last thing in the file.
- */
-	(void) snpf(cbuf, sizeof(cbuf), "CRC section: %x\n", DCcksum);
-	if (!fgets(buf, sizeof(buf), DCfs) || strcmp(buf, cbuf) != 0) {
-	    if (!Fwarn) {
-		(void) fprintf(stderr,
-		    "%s: WARNING: bad CRC section in %s: line ",
-		    Pn, DCpath[DCpathX]);
-		safestrprt(buf, stderr, 1+4+8);
-	    }
-	    goto read_close;
-	}
-	if (fgets(buf, sizeof(buf), DCfs)) {
-	    if (!Fwarn) {
-		(void) fprintf(stderr,
-		    "%s: WARNING: data follows CRC section in %s: line ",
-		    Pn, DCpath[DCpathX]);
-		safestrprt(buf, stderr, 1+4+8);
-	    }
-	    goto read_close;
-	}
-/*
- * Check one device entry at random -- the randomness based on our
- * PID.
- */
-	i = (int)(Mypid % Ndev);
-	if (stat(Devtp[i].name, &sb) != 0
-
-# if	defined(DVCH_EXPDEV)
-	||  expdev(sb.st_rdev) != Devtp[i].rdev
-# else	/* !defined(DVCH_EXPDEV) */
-	||  sb.st_rdev != Devtp[i].rdev
-# endif	/* defined(DVCH_EXPDEV) */
-
-	|| sb.st_ino != Devtp[i].inode) {
-	    if (!Fwarn)
-		(void) fprintf(stderr,
-			"%s: WARNING: device cache mismatch: %s\n",
-			Pn, Devtp[i].name);
-	    goto read_close;
-	}
-/*
- * Close the device cache file and return OK.
- */
-	(void) fclose(DCfs);
-	DCfd = -1;
-	DCfs = (FILE *)NULL;
-	return(0);
+int read_dcache(struct lsof_context *ctx) {
+    char buf[MAXPATHLEN * 2], cbuf[64], *cp;
+    int i, len, ov;
+    struct stat sb, devsb;
+    /*
+     * Open the device cache file.
+     *
+     * If the open at HASSYSDC fails because the file doesn't exist, and
+     * the real UID of this process is not zero, try to open a device cache
+     * file at HASPERSDC.
+     */
+    if ((ov = open_dcache(ctx, 1, 0, &sb)) != 0) {
+        if (DCpathX == 2) {
+            if (ov == 2 && DCpath[3]) {
+                DCpathX = 3;
+                if (open_dcache(ctx, 1, 1, &sb) != 0)
+                    return (1);
+            } else
+                return (1);
+        } else
+            return (1);
+    }
+    /*
+     * If the open device cache file's last mtime/ctime isn't greater than
+     * DVCH_DEVPATH's mtime/ctime, ignore it, unless -Dr was specified.
+     */
+    if (stat(DVCH_DEVPATH, &devsb) != 0) {
+        if (!Fwarn)
+            (void)fprintf(stderr, "%s: WARNING: can't stat(%s): %s\n", Pn,
+                          DVCH_DEVPATH, strerror(errno));
+    } else {
+        if (sb.st_mtime <= devsb.st_mtime || sb.st_ctime <= devsb.st_ctime)
+            DCunsafe = 1;
+    }
+    if (!(DCfs = fdopen(DCfd, "r"))) {
+        if (!Fwarn)
+            (void)fprintf(stderr, "%s: WARNING: can't fdopen(%s)\n", Pn,
+                          DCpath[DCpathX]);
+        (void)close(DCfd);
+        DCfd = -1;
+        return (1);
+    }
+    /*
+     * Read the section count line; initialize the CRC table;
+     * validate the section count line.
+     */
+    if (!fgets(buf, sizeof(buf), DCfs)) {
+
+    cant_read:
+        if (!Fwarn)
+            (void)fprintf(stderr, "%s: WARNING: can't fread %s: %s\n", Pn,
+                          DCpath[DCpathX], strerror(errno));
+    read_close:
+        (void)fclose(DCfs);
+        DCfd = -1;
+        DCfs = (FILE *)NULL;
+        (void)clr_devtab(ctx);
+
+#    if defined(DCACHE_CLR)
+        (void)DCACHE_CLR(ctx);
+#    endif /* defined(DCACHE_CLR) */
+
+        return (1);
+    }
+    (void)crcbld();
+    DCcksum = 0;
+    (void)crc(buf, strlen(buf), &DCcksum);
+    i = 1;
+    cp = "";
+
+#    if defined(HASBLKDEV)
+    i++;
+    cp = "s";
+#    endif /* defined(HASBLKDEV) */
+
+#    if defined(DCACHE_CLONE)
+    i++;
+    cp = "s";
+#    endif /* defined(DCACHE_CLONE) */
+
+#    if defined(DCACHE_PSEUDO)
+    i++;
+    cp = "s";
+#    endif /* defined(DCACHE_PSEUDO) */
+
+    (void)snpf(cbuf, sizeof(cbuf), "%d section%s", i, cp);
+    len = strlen(cbuf);
+    (void)snpf(&cbuf[len], sizeof(cbuf) - len, ", dev=%lx\n", (long)DevDev);
+    if (!strncmp(buf, cbuf, len) && (buf[len] == '\n')) {
+        if (!Fwarn) {
+            (void)fprintf(stderr, "%s: WARNING: no /dev device in %s: line ",
+                          Pn, DCpath[DCpathX]);
+            safestrprt(buf, stderr, 1 + 4 + 8);
+        }
+        goto read_close;
+    }
+    if (strcmp(buf, cbuf)) {
+        if (!Fwarn) {
+            (void)fprintf(stderr,
+                          "%s: WARNING: bad section count line in %s: line ",
+                          Pn, DCpath[DCpathX]);
+            safestrprt(buf, stderr, 1 + 4 + 8);
+        }
+        goto read_close;
+    }
+    /*
+     * Read device section header and validate it.
+     */
+    if (!fgets(buf, sizeof(buf), DCfs))
+        goto cant_read;
+    (void)crc(buf, strlen(buf), &DCcksum);
+    len = strlen("device section: ");
+    if (strncmp(buf, "device section: ", len) != 0) {
+
+    read_dhdr:
+        if (!Fwarn) {
+            (void)fprintf(stderr,
+                          "%s: WARNING: bad device section header in %s: line ",
+                          Pn, DCpath[DCpathX]);
+            safestrprt(buf, stderr, 1 + 4 + 8);
+        }
+        goto read_close;
+    }
+    /*
+     * Compute the device count; allocate Sdev[] and Devtp[] space.
+     */
+    if ((Ndev = atoi(&buf[len])) < 1)
+        goto read_dhdr;
+    alloc_dcache(ctx);
+    /*
+     * Read the device lines and store their information in Devtp[].
+     * Construct the Sdev[] pointers to Devtp[].
+     */
+    for (i = 0; i < Ndev; i++) {
+        if (!fgets(buf, sizeof(buf), DCfs)) {
+            if (!Fwarn)
+                (void)fprintf(stderr,
+                              "%s: WARNING: can't read device %d from %s\n", Pn,
+                              i + 1, DCpath[DCpathX]);
+            goto read_close;
+        }
+        (void)crc(buf, strlen(buf), &DCcksum);
+        /*
+         * Convert hexadecimal device number.
+         */
+        if (!(cp = x2dev(buf, &Devtp[i].rdev)) || *cp != ' ') {
+            if (!Fwarn) {
+                (void)fprintf(stderr, "%s: device %d: bad device in %s: line ",
+                              Pn, i + 1, DCpath[DCpathX]);
+                safestrprt(buf, stderr, 1 + 4 + 8);
+            }
+            goto read_close;
+        }
+        /*
+         * Convert inode number.
+         */
+        for (cp++, Devtp[i].inode = (INODETYPE)0; *cp != ' '; cp++) {
+            if (*cp < '0' || *cp > '9') {
+                if (!Fwarn) {
+                    (void)fprintf(
+                        stderr,
+                        "%s: WARNING: device %d: bad inode # in %s: line ", Pn,
+                        i + 1, DCpath[DCpathX]);
+                    safestrprt(buf, stderr, 1 + 4 + 8);
+                }
+                goto read_close;
+            }
+            Devtp[i].inode =
+                (INODETYPE)((Devtp[i].inode * 10) + (int)(*cp - '0'));
+        }
+        /*
+         * Get path name; allocate space for it; copy it; store the
+         * pointer in Devtp[]; clear verify status; construct the Sdev[]
+         * pointer to Devtp[].
+         */
+        if ((len = strlen(++cp)) < 2 || *(cp + len - 1) != '\n') {
+            if (!Fwarn) {
+                (void)fprintf(stderr,
+                              "%s: WARNING: device %d: bad path in %s: line ",
+                              Pn, i + 1, DCpath[DCpathX]);
+                safestrprt(buf, stderr, 1 + 4 + 8);
+            }
+            goto read_close;
+        }
+        *(cp + len - 1) = '\0';
+        if (!(Devtp[i].name = mkstrcpy(cp, (MALLOC_S *)NULL))) {
+            (void)fprintf(stderr, "%s: device %d: no space for path: line ", Pn,
+                          i + 1);
+            safestrprt(buf, stderr, 1 + 4 + 8);
+            Error(ctx);
+        }
+        Devtp[i].v = 0;
+        Sdev[i] = &Devtp[i];
+    }
+
+#    if defined(HASBLKDEV)
+    /*
+     * Read block device section header and validate it.
+     */
+    if (!fgets(buf, sizeof(buf), DCfs))
+        goto cant_read;
+    (void)crc(buf, strlen(buf), &DCcksum);
+    len = strlen("block device section: ");
+    if (strncmp(buf, "block device section: ", len) != 0) {
+        if (!Fwarn) {
+            (void)fprintf(
+                stderr,
+                "%s: WARNING: bad block device section header in %s: line ", Pn,
+                DCpath[DCpathX]);
+            safestrprt(buf, stderr, 1 + 4 + 8);
+        }
+        goto read_close;
+    }
+    /*
+     * Compute the block device count; allocate BSdev[] and BDevtp[] space.
+     */
+    if ((BNdev = atoi(&buf[len])) > 0) {
+        alloc_bdcache(ctx);
+        /*
+         * Read the block device lines and store their information in BDevtp[].
+         * Construct the BSdev[] pointers to BDevtp[].
+         */
+        for (i = 0; i < BNdev; i++) {
+            if (!fgets(buf, sizeof(buf), DCfs)) {
+                if (!Fwarn)
+                    (void)fprintf(
+                        stderr,
+                        "%s: WARNING: can't read block device %d from %s\n", Pn,
+                        i + 1, DCpath[DCpathX]);
+                goto read_close;
+            }
+            (void)crc(buf, strlen(buf), &DCcksum);
+            /*
+             * Convert hexadecimal device number.
+             */
+            if (!(cp = x2dev(buf, &BDevtp[i].rdev)) || *cp != ' ') {
+                if (!Fwarn) {
+                    (void)fprintf(stderr,
+                                  "%s: block dev %d: bad device in %s: line ",
+                                  Pn, i + 1, DCpath[DCpathX]);
+                    safestrprt(buf, stderr, 1 + 4 + 8);
+                }
+                goto read_close;
+            }
+            /*
+             * Convert inode number.
+             */
+            for (cp++, BDevtp[i].inode = (INODETYPE)0; *cp != ' '; cp++) {
+                if (*cp < '0' || *cp > '9') {
+                    if (!Fwarn) {
+                        (void)fprintf(stderr,
+                                      "%s: WARNING: block dev %d: bad inode # "
+                                      "in %s: line ",
+                                      Pn, i + 1, DCpath[DCpathX]);
+                        safestrprt(buf, stderr, 1 + 4 + 8);
+                    }
+                    goto read_close;
+                }
+                BDevtp[i].inode =
+                    (INODETYPE)((BDevtp[i].inode * 10) + (int)(*cp - '0'));
+            }
+            /*
+             * Get path name; allocate space for it; copy it; store the
+             * pointer in BDevtp[]; clear verify status; construct the BSdev[]
+             * pointer to BDevtp[].
+             */
+            if ((len = strlen(++cp)) < 2 || *(cp + len - 1) != '\n') {
+                if (!Fwarn) {
+                    (void)fprintf(
+                        stderr,
+                        "%s: WARNING: block dev %d: bad path in %s: line", Pn,
+                        i + 1, DCpath[DCpathX]);
+                    safestrprt(buf, stderr, 1 + 4 + 8);
+                }
+                goto read_close;
+            }
+            *(cp + len - 1) = '\0';
+            if (!(BDevtp[i].name = mkstrcpy(cp, (MALLOC_S *)NULL))) {
+                (void)fprintf(stderr,
+                              "%s: block dev %d: no space for path: line", Pn,
+                              i + 1);
+                safestrprt(buf, stderr, 1 + 4 + 8);
+                Error(ctx);
+            }
+            BDevtp[i].v = 0;
+            BSdev[i] = &BDevtp[i];
+        }
+    }
+#    endif /* defined(HASBLKDEV) */
+
+#    if defined(DCACHE_CLONE)
+    /*
+     * Read the clone section.
+     */
+    if (DCACHE_CLONE(ctx, 1))
+        goto read_close;
+#    endif /* defined(DCACHE_CLONE) */
+
+#    if defined(DCACHE_PSEUDO)
+    /*
+     * Read the pseudo section.
+     */
+    if (DCACHE_PSEUDO(ctx, 1))
+        goto read_close;
+#    endif /* defined(DCACHE_PSEUDO) */
+
+    /*
+     * Read and check the CRC section; it must be the last thing in the file.
+     */
+    (void)snpf(cbuf, sizeof(cbuf), "CRC section: %x\n", DCcksum);
+    if (!fgets(buf, sizeof(buf), DCfs) || strcmp(buf, cbuf) != 0) {
+        if (!Fwarn) {
+            (void)fprintf(stderr, "%s: WARNING: bad CRC section in %s: line ",
+                          Pn, DCpath[DCpathX]);
+            safestrprt(buf, stderr, 1 + 4 + 8);
+        }
+        goto read_close;
+    }
+    if (fgets(buf, sizeof(buf), DCfs)) {
+        if (!Fwarn) {
+            (void)fprintf(stderr,
+                          "%s: WARNING: data follows CRC section in %s: line ",
+                          Pn, DCpath[DCpathX]);
+            safestrprt(buf, stderr, 1 + 4 + 8);
+        }
+        goto read_close;
+    }
+    /*
+     * Check one device entry at random -- the randomness based on our
+     * PID.
+     */
+    i = (int)(Mypid % Ndev);
+    if (stat(Devtp[i].name, &sb) != 0
+
+#    if defined(DVCH_EXPDEV)
+        || expdev(sb.st_rdev) != Devtp[i].rdev
+#    else  /* !defined(DVCH_EXPDEV) */
+        || sb.st_rdev != Devtp[i].rdev
+#    endif /* defined(DVCH_EXPDEV) */
+
+        || sb.st_ino != Devtp[i].inode) {
+        if (!Fwarn)
+            (void)fprintf(stderr, "%s: WARNING: device cache mismatch: %s\n",
+                          Pn, Devtp[i].name);
+        goto read_close;
+    }
+    /*
+     * Close the device cache file and return OK.
+     */
+    (void)fclose(DCfs);
+    DCfd = -1;
+    DCfs = (FILE *)NULL;
+    return (0);
 }
 
-
-# if	defined(DCACHE_CLONE_LOCAL)
+#    if defined(DCACHE_CLONE_LOCAL)
 /*
  * rw_clone_sect() - read/write the device cache file clone section
  */
 
-static int
-rw_clone_sect(m)
-	int m;				/* mode: 1 = read; 2 = write */
+static int rw_clone_sect(struct lsof_context *ctx,
+                         int m) /* mode: 1 = read; 2 = write */
 {
-	char buf[MAXPATHLEN*2], *cp, *cp1;
-	struct clone *c;
-	struct l_dev *dp;
-	int i, j, 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: line ",
-			Pn, DCpath[DCpathX]);
-		    safestrprt(buf, stderr, 1+4+8);
-		}
-		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) == NULL) {
-		    if (!Fwarn) {
-			(void) fprintf(stderr,
-			    "%s: no %d clone line in %s: line ", Pn, i + 1,
-			    DCpath[DCpathX]);
-			safestrprt(buf, stderr, 1+4+8);
-		    }
-		    return(1);
-		}
-		(void) crc(buf, strlen(buf), &DCcksum);
-	    /*
-	     * Assemble Devtp[] index and make sure it's correct.
-	     */
-		for (cp = buf, j = 0; *cp != ' '; cp++) {
-		    if (*cp < '0' || *cp > '9') {
-
-bad_clone_index:
-			if (!Fwarn) {
-			    (void) fprintf(stderr,
-				"%s: clone %d: bad cached device index: line ",
-				Pn, i + 1);
-			    safestrprt(buf, stderr, 1+4+8);
-			}
-			return(1);
-		    }
-		    j = (j * 10) + (int)(*cp - '0');
-		}
-		if (j < 0 || j >= Ndev || (cp1 = strchr(++cp, '\n')) == NULL)
-		    goto bad_clone_index;
-		if (strncmp(cp, Devtp[j].name, (cp1 - cp)) != 0)
-		    goto bad_clone_index;
-	    /*
-	     * Allocate and complete a clone structure.
-	     */
-		if (!(c = (struct clone *)malloc(sizeof(struct clone)))) {
-		    (void) fprintf(stderr,
-			"%s: clone %d: no space for cached clone: line ", Pn,
-			i + 1);
-		    safestrprt(buf, stderr, 1+4+8);
-		    Error();
-		}
-		c->dx = j;
-		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.
-	 */
-	    for (c = Clone; c; c = c->next) {
-		for (dp = &Devtp[c->dx], j = 0; j < Ndev; j++) {
-		    if (dp == Sdev[j])
-			break;
-		}
-		if (j >= Ndev) {
-		    if (!Fwarn) {
-			(void) fprintf(stderr,
-			    "%s: can't make index for clone: ", Pn);
-			safestrprt(dp->name, stderr, 1);
-		    }
-		    (void) unlink(DCpath[DCpathX]);
-		    (void) close(DCfd);
-		    DCfd = -1;
-		    return(1);
-		}
-		(void) snpf(buf, sizeof(buf), "%d %s\n", j, dp->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);
-	Error();
-	return(1);		/* This useless return(1) keeps some
-				 * compilers happy. */
+    char buf[MAXPATHLEN * 2], *cp, *cp1;
+    struct clone *c;
+    struct l_dev *dp;
+    int i, j, 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: line ", Pn,
+                              DCpath[DCpathX]);
+                safestrprt(buf, stderr, 1 + 4 + 8);
+            }
+            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) == NULL) {
+                if (!Fwarn) {
+                    (void)fprintf(stderr, "%s: no %d clone line in %s: line ",
+                                  Pn, i + 1, DCpath[DCpathX]);
+                    safestrprt(buf, stderr, 1 + 4 + 8);
+                }
+                return (1);
+            }
+            (void)crc(buf, strlen(buf), &DCcksum);
+            /*
+             * Assemble Devtp[] index and make sure it's correct.
+             */
+            for (cp = buf, j = 0; *cp != ' '; cp++) {
+                if (*cp < '0' || *cp > '9') {
+
+                bad_clone_index:
+                    if (!Fwarn) {
+                        (void)fprintf(
+                            stderr,
+                            "%s: clone %d: bad cached device index: line ", Pn,
+                            i + 1);
+                        safestrprt(buf, stderr, 1 + 4 + 8);
+                    }
+                    return (1);
+                }
+                j = (j * 10) + (int)(*cp - '0');
+            }
+            if (j < 0 || j >= Ndev || (cp1 = strchr(++cp, '\n')) == NULL)
+                goto bad_clone_index;
+            if (strncmp(cp, Devtp[j].name, (cp1 - cp)) != 0)
+                goto bad_clone_index;
+            /*
+             * Allocate and complete a clone structure.
+             */
+            if (!(c = (struct clone *)malloc(sizeof(struct clone)))) {
+                (void)fprintf(stderr,
+                              "%s: clone %d: no space for cached clone: line ",
+                              Pn, i + 1);
+                safestrprt(buf, stderr, 1 + 4 + 8);
+                Error(ctx);
+            }
+            c->dx = j;
+            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(ctx, buf, &DCcksum))
+            return (1);
+        /*
+         * Write the clone section lines.
+         */
+        for (c = Clone; c; c = c->next) {
+            for (dp = &Devtp[c->dx], j = 0; j < Ndev; j++) {
+                if (dp == Sdev[j])
+                    break;
+            }
+            if (j >= Ndev) {
+                if (!Fwarn) {
+                    (void)fprintf(stderr,
+                                  "%s: can't make index for clone: ", Pn);
+                    safestrprt(dp->name, stderr, 1);
+                }
+                (void)unlink(DCpath[DCpathX]);
+                (void)close(DCfd);
+                DCfd = -1;
+                return (1);
+            }
+            (void)snpf(buf, sizeof(buf), "%d %s\n", j, dp->name);
+            if (wr2DCfd(ctx, 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);
+    Error(ctx);
+    return (1); /* This useless return(1) keeps some
+                 * compilers happy. */
 }
-# endif	/* defined(DCACHE_CLONE_LOCAL) */
-
+#    endif /* defined(DCACHE_CLONE_LOCAL) */
 
 /*
  * write_dcache() - write device cache file
  */
 
-void
-write_dcache()
-{
-	char buf[MAXPATHLEN*2], *cp;
-	struct l_dev *dp;
-	int i;
-	struct stat sb;
-/*
- * Open the cache file; set up the CRC table; write the section count.
- */
-	if (open_dcache(2, 0, &sb))
-    		return;
-	i = 1;
-	cp = "";
-
-# if	defined(HASBLKDEV)
-	i++;
-	cp = "s";
-# endif	/* defined(HASBLKDEV) */
-
-# if	defined(DCACHE_CLONE)
-	i++;
-	cp = "s";
-# endif	/* defined(DCACHE_CLONE) */
-
-# if	defined(DCACHE_PSEUDO)
-	i++;
-	cp = "s";
-# endif	/* defined(DCACHE_PSEUDO) */
-
-	(void) snpf(buf, sizeof(buf), "%d section%s, dev=%lx\n", i, cp,
-	    (long)DevDev);
-	(void) crcbld();
-	DCcksum = 0;
-	if (wr2DCfd(buf, &DCcksum))
-		return;
-/*
- * Write the device section from the contents of Sdev[] and Devtp[].
- */
-	(void) snpf(buf, sizeof(buf), "device section: %d\n", Ndev);
-	if (wr2DCfd(buf, &DCcksum))
-	    return;
-	for (i = 0; i < Ndev; i++) {
-	    dp = Sdev[i];
-	    (void) snpf(buf, sizeof(buf), "%lx %ld %s\n", (long)dp->rdev,
-			(long)dp->inode, dp->name);
-	    if (wr2DCfd(buf, &DCcksum))
-		return;
-	}
-
-# if	defined(HASBLKDEV)
-/*
- * Write the block device section from the contents of BSdev[] and BDevtp[].
- */
-	(void) snpf(buf, sizeof(buf), "block device section: %d\n", BNdev);
-	if (wr2DCfd(buf, &DCcksum))
-	    return;
-	if (BNdev) {
-	    for (i = 0; i < BNdev; i++) {
-		dp = BSdev[i];
-		(void) snpf(buf, sizeof(buf), "%lx %ld %s\n", (long)dp->rdev,
-		    (long)dp->inode, dp->name);
-		if (wr2DCfd(buf, &DCcksum))
-		    return;
-	    }
-	}
-# endif	/* defined(HASBLKDEV) */
-
-# if	defined(DCACHE_CLONE)
-/*
- * Write the clone section.
- */
-	if (DCACHE_CLONE(2))
-	    return;
-# endif	/* defined(DCACHE_CLONE) */
-
-# if	defined(DCACHE_PSEUDO)
-/*
- * Write the pseudo section.
- */
-	if (DCACHE_PSEUDO(2))
-	    return;
-# endif	/* defined(DCACHE_PSEUDO) */
-
-/*
- * Write the CRC section and close the file.
- */
-	(void) snpf(buf, sizeof(buf), "CRC section: %x\n", DCcksum);
-	if (wr2DCfd(buf, (unsigned *)NULL))
-		return;
-	if (close(DCfd) != 0) {
-	    if (!Fwarn)
-		(void) fprintf(stderr,
-		    "%s: WARNING: can't close %s: %s\n",
-		    Pn, DCpath[DCpathX], strerror(errno));
-	    (void) unlink(DCpath[DCpathX]);
-	    DCfd = -1;
-	}
-	DCfd = -1;
-/*
- * If the previous reading of the previous device cache file marked it
- * "unsafe," drop that marking and record that the device cache file was
- * rebuilt.
- */
-	if (DCunsafe) {
-	    DCunsafe = 0;
-	    DCrebuilt = 1;
-	}
+void write_dcache(struct lsof_context *ctx) {
+    char buf[MAXPATHLEN * 2], *cp;
+    struct l_dev *dp;
+    int i;
+    struct stat sb;
+    /*
+     * Open the cache file; set up the CRC table; write the section count.
+     */
+    if (open_dcache(ctx, 2, 0, &sb))
+        return;
+    i = 1;
+    cp = "";
+
+#    if defined(HASBLKDEV)
+    i++;
+    cp = "s";
+#    endif /* defined(HASBLKDEV) */
+
+#    if defined(DCACHE_CLONE)
+    i++;
+    cp = "s";
+#    endif /* defined(DCACHE_CLONE) */
+
+#    if defined(DCACHE_PSEUDO)
+    i++;
+    cp = "s";
+#    endif /* defined(DCACHE_PSEUDO) */
+
+    (void)snpf(buf, sizeof(buf), "%d section%s, dev=%lx\n", i, cp,
+               (long)DevDev);
+    (void)crcbld();
+    DCcksum = 0;
+    if (wr2DCfd(ctx, buf, &DCcksum))
+        return;
+    /*
+     * Write the device section from the contents of Sdev[] and Devtp[].
+     */
+    (void)snpf(buf, sizeof(buf), "device section: %d\n", Ndev);
+    if (wr2DCfd(ctx, buf, &DCcksum))
+        return;
+    for (i = 0; i < Ndev; i++) {
+        dp = Sdev[i];
+        (void)snpf(buf, sizeof(buf), "%lx %ld %s\n", (long)dp->rdev,
+                   (long)dp->inode, dp->name);
+        if (wr2DCfd(ctx, buf, &DCcksum))
+            return;
+    }
+
+#    if defined(HASBLKDEV)
+    /*
+     * Write the block device section from the contents of BSdev[] and BDevtp[].
+     */
+    (void)snpf(buf, sizeof(buf), "block device section: %d\n", BNdev);
+    if (wr2DCfd(ctx, buf, &DCcksum))
+        return;
+    if (BNdev) {
+        for (i = 0; i < BNdev; i++) {
+            dp = BSdev[i];
+            (void)snpf(buf, sizeof(buf), "%lx %ld %s\n", (long)dp->rdev,
+                       (long)dp->inode, dp->name);
+            if (wr2DCfd(ctx, buf, &DCcksum))
+                return;
+        }
+    }
+#    endif /* defined(HASBLKDEV) */
+
+#    if defined(DCACHE_CLONE)
+    /*
+     * Write the clone section.
+     */
+    if (DCACHE_CLONE(ctx, 2))
+        return;
+#    endif /* defined(DCACHE_CLONE) */
+
+#    if defined(DCACHE_PSEUDO)
+    /*
+     * Write the pseudo section.
+     */
+    if (DCACHE_PSEUDO(ctx, 2))
+        return;
+#    endif /* defined(DCACHE_PSEUDO) */
+
+    /*
+     * Write the CRC section and close the file.
+     */
+    (void)snpf(buf, sizeof(buf), "CRC section: %x\n", DCcksum);
+    if (wr2DCfd(ctx, buf, (unsigned *)NULL))
+        return;
+    if (close(DCfd) != 0) {
+        if (!Fwarn)
+            (void)fprintf(stderr, "%s: WARNING: can't close %s: %s\n", Pn,
+                          DCpath[DCpathX], strerror(errno));
+        (void)unlink(DCpath[DCpathX]);
+        DCfd = -1;
+    }
+    DCfd = -1;
+    /*
+     * If the previous reading of the previous device cache file marked it
+     * "unsafe," drop that marking and record that the device cache file was
+     * rebuilt.
+     */
+    if (DCunsafe) {
+        DCunsafe = 0;
+        DCrebuilt = 1;
+    }
 }
 
-
 /*
  * wr2DCfd() - write to the DCfd file descriptor
  */
 
-int
-wr2DCfd(b, c)
-	char *b;			/* buffer */
-	unsigned *c;			/* checksum receiver */
+int wr2DCfd(struct lsof_context *ctx, /* context */
+            char *b,                  /* buffer */
+            unsigned *c)              /* checksum receiver */
 {
-	int bl, bw;
-
-	bl = strlen(b);
-	if (c)
-	    (void) crc(b, bl, c);
-	while (bl > 0) {
-	    if ((bw = write(DCfd, b, bl)) < 0) {
-		if (!Fwarn)
-		    (void) fprintf(stderr,
-			"%s: WARNING: can't write to %s: %s\n",
-			Pn, DCpath[DCpathX], strerror(errno));
-		(void) unlink(DCpath[DCpathX]);
-		(void) close(DCfd);
-		DCfd = -1;
-		return(1);
-	    }
-	    b += bw;
-	    bl -= bw;
-	}
-	return(0);
+    int bl, bw;
+
+    bl = strlen(b);
+    if (c)
+        (void)crc(b, bl, c);
+    while (bl > 0) {
+        if ((bw = write(DCfd, b, bl)) < 0) {
+            if (!Fwarn)
+                (void)fprintf(stderr, "%s: WARNING: can't write to %s: %s\n",
+                              Pn, DCpath[DCpathX], strerror(errno));
+            (void)unlink(DCpath[DCpathX]);
+            (void)close(DCfd);
+            DCfd = -1;
+            return (1);
+        }
+        b += bw;
+        bl -= bw;
+    }
+    return (0);
 }
-#else	/* !defined(HASDCACHE) */
-char dvch_d1[] = "d"; char *dvch_d2 = dvch_d1;
-#endif	/* defined(HASDCACHE) */
+#else  /* !defined(HASDCACHE) */
+char dvch_d1[] = "d";
+char *dvch_d2 = dvch_d1;
+#endif /* defined(HASDCACHE) */
diff --git a/lib/fino.c b/lib/fino.c
index 3502095..693fba3 100644
--- a/lib/fino.c
+++ b/lib/fino.c
@@ -2,7 +2,6 @@
  * fino.c -- find inode functions for lsof library
  */
 
-
 /*
  * Copyright 1997 Purdue Research Foundation, West Lafayette, Indiana
  * 47907.  All rights reserved.
@@ -29,7 +28,6 @@
  * 4. This notice may not be removed or altered.
  */
 
-
 /*
  * fino.c -- find block (optional) and character device file inode numbers
  *
@@ -38,110 +36,98 @@
  *	HASBLKDEV	to activate the block device inode lookup
  */
 
+#include "common.h"
+#include "machine.h"
 
-#include "../machine.h"
-
-#if	defined(HASBLKDEV) || defined(USE_LIB_FIND_CH_INO)
-
-# if	!defined(lint)
-static char copyright[] =
-"@(#) Copyright 1997 Purdue Research Foundation.\nAll rights reserved.\n";
-# endif	/* !defined(lint) */
+#if defined(HASBLKDEV) || defined(USE_LIB_FIND_CH_INO)
 
-#include "../lsof.h"
+#else  /* !defined(HASBLKDEV) && !defined(USE_LIB_FIND_CH_INO) */
+char fino_d1[] = "d";
+char *fino_d2 = fino_d1;
+#endif /* defined(HASBLKDEV) || defined(USE_LIB_FIND_CH_INO) */
 
-#else	/* !defined(HASBLKDEV) && !defined(USE_LIB_FIND_CH_INO) */
-char fino_d1[] = "d"; char *fino_d2 = fino_d1;
-#endif	/* defined(HASBLKDEV) || defined(USE_LIB_FIND_CH_INO) */
-
-
-#if	defined(HASBLKDEV)
+#if defined(HASBLKDEV)
 /*
  * find_bl_ino() - find the inode number for a block device file
  */
 
-void
-find_bl_ino()
-{
-	dev_t ldev, tdev;
-	int low, hi, mid;
+void find_bl_ino(struct lsof_context *ctx) {
+    dev_t ldev, tdev;
+    int low, hi, mid;
 
-	readdev(0);
+    readdev(ctx, 0);
 
-# if	defined(HASDCACHE)
+#    if defined(HASDCACHE)
 find_bl_ino_again:
-# endif	/* defined(HASDCACHE) */
-
-	low = mid = 0;
-	hi = BNdev - 1;
-	if (!Lf->dev_def || (Lf->dev != DevDev) || !Lf->rdev_def)
-	    return;
-	ldev = Lf->rdev;
-	while (low <= hi) {
-	    mid = (low + hi) / 2;
-	    tdev = BSdev[mid]->rdev;
-	    if (ldev < tdev)
-		hi = mid - 1;
-	    else if (ldev > tdev)
-		low = mid + 1;
-	    else {
-
-# if	defined(HASDCACHE)
-		if (DCunsafe && !BSdev[mid]->v && !vfy_dev(BSdev[mid]))
-		    goto find_bl_ino_again;
-# endif	/* defined(HASDCACHE) */
-
-		Lf->inode = BSdev[mid]->inode;
-		if (Lf->inp_ty == 0)
-		    Lf->inp_ty = 1;
-		return;
-	    }
-	}
+#    endif /* defined(HASDCACHE) */
+
+    low = mid = 0;
+    hi = BNdev - 1;
+    if (!Lf->dev_def || (Lf->dev != DevDev) || !Lf->rdev_def)
+        return;
+    ldev = Lf->rdev;
+    while (low <= hi) {
+        mid = (low + hi) / 2;
+        tdev = BSdev[mid]->rdev;
+        if (ldev < tdev)
+            hi = mid - 1;
+        else if (ldev > tdev)
+            low = mid + 1;
+        else {
+
+#    if defined(HASDCACHE)
+            if (DCunsafe && !BSdev[mid]->v && !vfy_dev(ctx, BSdev[mid]))
+                goto find_bl_ino_again;
+#    endif /* defined(HASDCACHE) */
+
+            Lf->inode = BSdev[mid]->inode;
+            if (Lf->inp_ty == 0)
+                Lf->inp_ty = 1;
+            return;
+        }
+    }
 }
-#endif	/* defined(HASBLKDEV) */
-
+#endif /* defined(HASBLKDEV) */
 
-#if	defined(USE_LIB_FIND_CH_INO)
+#if defined(USE_LIB_FIND_CH_INO)
 /*
  * find_ch_ino() - find the inode number for a character device file
  */
 
-void
-find_ch_ino()
-{
-	dev_t ldev, tdev;
-	int low, hi, mid;
+void find_ch_ino(struct lsof_context *ctx) {
+    dev_t ldev, tdev;
+    int low, hi, mid;
 
-	readdev(0);
+    readdev(ctx, 0);
 
-# if	defined(HASDCACHE)
+#    if defined(HASDCACHE)
 find_ch_ino_again:
-# endif	/* defined(HASDCACHE) */
-
-	low = mid = 0;
-	hi = Ndev - 1;
-	if (!Lf->dev_def || (Lf->dev != DevDev) || !Lf->rdev_def)
-	    return;
-	ldev = Lf->rdev;
-	while (low <= hi) {
-	    mid = (low + hi) / 2;
-	    tdev = Sdev[mid]->rdev;
-	    if (ldev < tdev)
-		hi = mid - 1;
-	    else if (ldev > tdev)
-		low = mid + 1;
-	    else {
-
-# if	defined(HASDCACHE)
-		if (DCunsafe && !Sdev[mid]->v && !vfy_dev(Sdev[mid]))
-		    goto find_ch_ino_again;
-# endif	/* defined(HASDCACHE) */
-
-		Lf->inode = Sdev[mid]->inode;
-		if (Lf->inp_ty == 0)
-		    Lf->inp_ty = 1;
-		return;
-	    }
-	}
+#    endif /* defined(HASDCACHE) */
+
+    low = mid = 0;
+    hi = Ndev - 1;
+    if (!Lf->dev_def || (Lf->dev != DevDev) || !Lf->rdev_def)
+        return;
+    ldev = Lf->rdev;
+    while (low <= hi) {
+        mid = (low + hi) / 2;
+        tdev = Sdev[mid]->rdev;
+        if (ldev < tdev)
+            hi = mid - 1;
+        else if (ldev > tdev)
+            low = mid + 1;
+        else {
+
+#    if defined(HASDCACHE)
+            if (DCunsafe && !Sdev[mid]->v && !vfy_dev(ctx, Sdev[mid]))
+                goto find_ch_ino_again;
+#    endif /* defined(HASDCACHE) */
+
+            Lf->inode = Sdev[mid]->inode;
+            if (Lf->inp_ty == 0)
+                Lf->inp_ty = 1;
+            return;
+        }
+    }
 }
-#endif	/* defined(USE_LIB_FIND_CH_INO) */
+#endif /* defined(USE_LIB_FIND_CH_INO) */
diff --git a/lib/hash.h b/lib/hash.h
new file mode 100644
index 0000000..2d3e1ae
--- /dev/null
+++ b/lib/hash.h
@@ -0,0 +1,75 @@
+
+/*
+ * hash.sh - utility functions for hash tables
+ */
+
+/*
+ * 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.
+ */
+
+#if !defined(LSOF_HASH_H)
+#    define LSOF_HASH_H 1
+
+/* Find element in hash table by key, return NULL if not found
+ *
+ * table: hash table
+ * hash: hash function/macro
+ * type: struct type
+ * member: member to match key
+ * key: key
+ *
+ * the struct type should have a member called next
+ **/
+#    define HASH_FIND_ELEMENT(table, hash, type, member, key)                  \
+        ({                                                                     \
+            type *__value = NULL;                                              \
+            int __h = hash(key);                                               \
+            if ((table)) {                                                     \
+                for (__value = (table)[__h]; __value;                          \
+                     __value = __value->next) {                                \
+                    if ((key) == __value->member)                              \
+                        break;                                                 \
+                };                                                             \
+            };                                                                 \
+            __value;                                                           \
+        })
+
+/* Insert element into hash table
+ *
+ * table: hash table
+ * hash: hash function/macro
+ * element: element
+ * member: member name containing key
+ *
+ * the type of element should have a member called next
+ **/
+#    define HASH_INSERT_ELEMENT(table, hash, element, member)                  \
+        ({                                                                     \
+            int __h = hash((element)->member);                                 \
+            (element)->next = (table)[__h];                                    \
+            (table)[__h] = (element);                                          \
+        })
+
+#endif
diff --git a/lib/isfn.c b/lib/isfn.c
index 24cfd03..b73f293 100644
--- a/lib/isfn.c
+++ b/lib/isfn.c
@@ -2,7 +2,6 @@
  * isfn.c -- is_file_named() function for lsof library
  */
 
-
 /*
  * Copyright 1997 Purdue Research Foundation, West Lafayette, Indiana
  * 47907.  All rights reserved.
@@ -29,7 +28,6 @@
  * 4. This notice may not be removed or altered.
  */
 
-
 /*
  * To use this source file:
  *
@@ -53,365 +51,308 @@
  *    d.  Accept clone searching by device number only.
  */
 
+#include "common.h"
+#include "machine.h"
 
-#include "../machine.h"
-
-#if	defined(USE_LIB_IS_FILE_NAMED)
-
-# if	!defined(lint)
-static char copyright[] =
-"@(#) Copyright 1997 Purdue Research Foundation.\nAll rights reserved.\n";
-# endif	/* !defined(lint) */
-
-#include "../lsof.h"
-
+#if defined(USE_LIB_IS_FILE_NAMED)
 
 /*
  * Local structures
  */
 
-struct hsfile {
-	struct sfile *s;		/* the Sfile table address */
-	struct hsfile *next;		/* the next hash bucket entry */
-};
-
 /*
  * Local static variables
  */
 
-# if	defined(HAVECLONEMAJ)
-static struct hsfile *HbyCd =		/* hash by clone buckets */
-	(struct hsfile *)NULL;
-static int HbyCdCt = 0;			/* HbyCd entry count */
-# endif	/* defined(HAVECLONEMAJ) */
-
-static struct hsfile *HbyFdi =		/* hash by file (dev,ino) 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
  */
 
-# if	defined(HAVECLONEMAJ)
-#define	SFCDHASH	1024		/* Sfile hash by clone device (power
-					 * of 2!) */
-# endif	/* defined(HAVECLONEMAJ) */
-
-#define	SFDIHASH	4094		/* Sfile hash by (device,inode) number
-					 * pair bucket count (power of 2!) */
-#define	SFFSHASH	1024		/* 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 mod
-					 * (mod must be a 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) */
-#define	SFNMHASH	4096		/* Sfile hash by name bucket count
-					 * (must be a power of 2!) */
-
-
+#    if defined(HAVECLONEMAJ)
+#        define SFCDHASH                                                       \
+            1024 /* Sfile hash by clone device (power                          \
+                  * of 2!) */
+#    endif       /* defined(HAVECLONEMAJ) */
+
+#    define SFDIHASH                                                           \
+        4094 /* Sfile hash by (device,inode) number                            \
+              * pair bucket count (power of 2!) */
+#    define SFFSHASH                                                           \
+        1024 /* 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 mod
+ * (mod must be a 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) */
+#    define SFNMHASH                                                           \
+        4096 /* Sfile hash by name bucket count                                \
+              * (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;
-	int sfplm = 3;
-	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, and file name.
- */
-
-# if	defined(HAVECLONEMAJ)
-	if (HAVECLONEMAJ) {
-	    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);
-		Error();
-	    }
-	    sfplm++;
-	}
-# endif	/* defined(HAVECLONEMAJ) */
-
-	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);
-	    Error();
-	}
-	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);
-	    Error();
-	}
-	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);
-	    Error();
-	}
-	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);
-	    Error();
-	}
-	hs++;
-/*
- * Scan the Sfile chain, building file, file system, raw device, and file
- * name hash bucket chains.
- */
-	for (s = Sfile; s; s = s->next) {
-	    for (i = 0; i < sfplm; 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->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;
-		}
-
-# if	defined(HAVECLONEMAJ)
-		else {
-		    if (!HAVECLONEMAJ || (GET_MAJ_DEV(s->rdev) != CLONEMAJ))
-			continue;
-		    sh = &HbyCd[SFHASHDEVINO(0, GET_MIN_DEV(s->rdev), 0,
-					     SFCDHASH)];
-		    HbyCdCt++;
-		}
-# else	/* ! defined(HAVECLONEMAJ) */
-		else
-		    continue;
-# endif	/* defined(HAVECLONEMAJ) */
-
-		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);
-			Error();
-		    }
-		    sn->s = s;
-		    sn->next = sh->next;
-		    sh->next = sn;
-		}
-	    }
-	}
+void hashSfile(struct lsof_context *ctx) {
+    static int hs = 0;
+    int i;
+    int sfplm = 3;
+    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, and file
+         * name.
+         */
+
+#    if defined(HAVECLONEMAJ)
+    if (HAVECLONEMAJ) {
+        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);
+            Error(ctx);
+        }
+        sfplm++;
+    }
+#    endif /* defined(HAVECLONEMAJ) */
+
+    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);
+        Error(ctx);
+    }
+    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);
+        Error(ctx);
+    }
+    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);
+        Error(ctx);
+    }
+    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);
+        Error(ctx);
+    }
+    hs++;
+    /*
+     * Scan the Sfile chain, building file, file system, raw device, and file
+     * name hash bucket chains.
+     */
+    for (s = Sfile; s; s = s->next) {
+        for (i = 0; i < sfplm; 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->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;
+            }
+
+#    if defined(HAVECLONEMAJ)
+            else {
+                if (!HAVECLONEMAJ || (GET_MAJ_DEV(s->rdev) != CLONEMAJ))
+                    continue;
+                sh = &HbyCd[SFHASHDEVINO(0, GET_MIN_DEV(s->rdev), 0, SFCDHASH)];
+                HbyCdCt++;
+            }
+#    else  /* ! defined(HAVECLONEMAJ) */
+            else
+                continue;
+#    endif /* defined(HAVECLONEMAJ) */
+
+            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);
+                    Error(ctx);
+                }
+                sn->s = s;
+                sn->next = sh->next;
+                sh->next = sn;
+            }
+        }
+    }
 }
 
-
 /*
  * is_file_named() - is this file named?
  */
 
-int
-is_file_named(p, cd)
-	char *p;			/* path name; NULL = search by device
-					 * and inode (from *Lf) */
-	int cd;				/* character or block type file --
-					 * VCHR or VBLK vnode, or S_IFCHR
-					 * or S_IFBLK inode */
+int is_file_named(struct lsof_context *ctx,
+                  char *p, /* path name; NULL = search by device
+                            * and inode (from *Lf) */
+                  int cd)  /* character or block type file --
+                            * VCHR or VBLK vnode, or S_IFCHR
+                            * or S_IFBLK inode */
 {
-	char *ep;
-	int f = 0;
-	struct sfile *s = (struct sfile *)NULL;
-	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;
-		}
-	    }
-	}
-
-# if	defined(HAVECLONEMAJ)
-/*
- * If this is a stream, check for a clone device match.
- */
-	if (!f && HbyCdCt && Lf->is_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 = 3;
-		    break;
-		}
-	    }
-	}
-# endif	/* defined(HAVECLONEMAJ) */
-
-/*
- * 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) && (s->dev == Lf->dev)) {
-		    f = 1;
-		    break;
-		}
-	    }
-	}
-/*
- * Check for a character or block device match.
- */
-	if (!f && HbyFrdCt && cd
-	&&  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.
- */
-	switch (f) {
-	case 0:
-	    return(0);
-	case 1:
-	    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 (s->devnm) {
-		    ep = endnm(&sz);
-		    (void) snpf(ep, sz, " (%s)", s->devnm);
-		}
-	    }
-	    break;
-	case 2:
-	    (void) strcpy(Namech, p);
-	    break;
-
-# if	defined(HAVECLONEMAJ)
-	/* case 3:		do nothing for stream clone matches */
-# endif	/* defined(HAVECLONEMAJ) */
-
-	}
-	if (s)
-	    s->f = 1;
-	return(1);
+    char *ep;
+    int f = 0;
+    struct sfile *s = (struct sfile *)NULL;
+    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;
+            }
+        }
+    }
+
+#    if defined(HAVECLONEMAJ)
+    /*
+     * If this is a stream, check for a clone device match.
+     */
+    if (!f && HbyCdCt && Lf->is_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 = 3;
+                break;
+            }
+        }
+    }
+#    endif /* defined(HAVECLONEMAJ) */
+
+    /*
+     * 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) && (s->dev == Lf->dev)) {
+                f = 1;
+                break;
+            }
+        }
+    }
+    /*
+     * Check for a character or block device match.
+     */
+    if (!f && HbyFrdCt && cd && 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.
+     */
+    switch (f) {
+    case 0:
+        return (0);
+    case 1:
+        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 (s->devnm) {
+                ep = endnm(ctx, &sz);
+                (void)snpf(ep, sz, " (%s)", s->devnm);
+            }
+        }
+        break;
+    case 2:
+        (void)strcpy(Namech, p);
+        break;
+
+#    if defined(HAVECLONEMAJ)
+        /* case 3:		do nothing for stream clone matches */
+#    endif /* defined(HAVECLONEMAJ) */
+    }
+    if (s)
+        s->f = 1;
+    return (1);
 }
-#else	/* !defined(USE_LIB_IS_FILE_NAMED) */
-char isfn_d1[] = "d"; char *isfn_d2 = isfn_d1;
-#endif	/* defined(USE_LIB_IS_FILE_NAMED) */
+#else  /* !defined(USE_LIB_IS_FILE_NAMED) */
+char isfn_d1[] = "d";
+char *isfn_d2 = isfn_d1;
+#endif /* defined(USE_LIB_IS_FILE_NAMED) */
diff --git a/lib/lkud.c b/lib/lkud.c
index 185a256..221b704 100644
--- a/lib/lkud.c
+++ b/lib/lkud.c
@@ -2,7 +2,6 @@
  * lkud.c -- device lookup functions for lsof library
  */
 
-
 /*
  * Copyright 1997 Purdue Research Foundation, West Lafayette, Indiana
  * 47907.  All rights reserved.
@@ -29,7 +28,6 @@
  * 4. This notice may not be removed or altered.
  */
 
-
 /*
  * lkud.c -- lookup device
  *
@@ -38,169 +36,158 @@
  *	HASBLKDEV	to activate block device lookup
  */
 
+#include "common.h"
+#include "machine.h"
 
-#include "../machine.h"
-
-#if	defined(HASBLKDEV) || defined(USE_LIB_LKUPDEV)
-
-# if	!defined(lint)
-static char copyright[] =
-"@(#) Copyright 1997 Purdue Research Foundation.\nAll rights reserved.\n";
-# endif	/* !defined(lint) */
-
-#include "../lsof.h"
-
-#else	/* !defined(HASBLKDEV) && !defined(USE_LIB_LKUPDEV) */
-char lkud_d1[] = "d"; char *lkud_d2 = lkud_d1;
-#endif	/* defined(HASBLKDEV) || defined(USE_LIB_LKUPDEV) */
-
+#if defined(HASBLKDEV) || defined(USE_LIB_LKUPDEV)
 
+#else  /* !defined(HASBLKDEV) && !defined(USE_LIB_LKUPDEV) */
+char lkud_d1[] = "d";
+char *lkud_d2 = lkud_d1;
+#endif /* defined(HASBLKDEV) || defined(USE_LIB_LKUPDEV) */
 
-#if	defined(HASBLKDEV)
+#if defined(HASBLKDEV)
 /*
  * lkupbdev() - look up a block device
  */
 
-struct l_dev *
-lkupbdev(dev, rdev, i, r)
-	dev_t *dev;			/* pointer to device number */
-	dev_t *rdev;			/* pointer to raw device number */
-	int i;				/* inode match status */
-	int r;				/* if 1, rebuild the device cache with
-					 * rereaddev() when no match is found
-					 * and HASDCACHE is defined and
-					 * DCunsafe is one */
+struct l_dev *lkupbdev(struct lsof_context *ctx,
+                       dev_t *dev,  /* pointer to device number */
+                       dev_t *rdev, /* pointer to raw device number */
+                       int i,       /* inode match status */
+                       int r)       /* if 1, rebuild the device cache with
+                                     * rereaddev() when no match is found
+                                     * and HASDCACHE is defined and
+                                     * DCunsafe is one */
 {
-	INODETYPE inode = (INODETYPE)0;
-	int low, hi, mid;
-	struct l_dev *dp;
-	int ty = 0;
-
-	if (*dev != DevDev)
-	    return((struct l_dev *)NULL);
-	readdev(0);
-	if (i) {
-	    inode = Lf->inode;
-	    ty = Lf->inp_ty;
-	}
-/*
- * Search block device table for match.
- */
-
-# if	defined(HASDCACHE)
+    INODETYPE inode = (INODETYPE)0;
+    int low, hi, mid;
+    struct l_dev *dp;
+    int ty = 0;
+
+    if (*dev != DevDev)
+        return ((struct l_dev *)NULL);
+    readdev(ctx, 0);
+    if (i) {
+        inode = Lf->inode;
+        ty = Lf->inp_ty;
+    }
+    /*
+     * Search block device table for match.
+     */
+
+#    if defined(HASDCACHE)
 
 lkupbdev_again:
 
-# endif	/* defined(HASDCACHE) */
-
-	low = mid = 0;
-	hi = BNdev - 1;
-	while (low <= hi) {
-	    mid = (low + hi) / 2;
-	    dp = BSdev[mid];
-	    if (*rdev < dp->rdev)
-		hi = mid - 1;
-	    else if (*rdev > dp->rdev)
-		low = mid + 1;
-	    else {
-		if ((i == 0) || (ty != 1) || (inode == dp->inode)) {
-
-# if	defined(HASDCACHE)
-		    if (DCunsafe && !dp->v && !vfy_dev(dp))
-			goto lkupbdev_again;
-# endif	/* defined(HASDCACHE) */
-
-		    return(dp);
-		}
-		if (inode < dp->inode)
-		    hi = mid - 1;
-		else
-		    low = mid + 1;
-	    }
-	}
-
-# if	defined(HASDCACHE)
-	if (DCunsafe && r) {
-	    (void) rereaddev();
-	    goto lkupbdev_again;
-	}
-# endif	/* defined(HASDCACHE) */
-
-	return((struct l_dev *)NULL);
+#    endif /* defined(HASDCACHE) */
+
+    low = mid = 0;
+    hi = BNdev - 1;
+    while (low <= hi) {
+        mid = (low + hi) / 2;
+        dp = BSdev[mid];
+        if (*rdev < dp->rdev)
+            hi = mid - 1;
+        else if (*rdev > dp->rdev)
+            low = mid + 1;
+        else {
+            if ((i == 0) || (ty != 1) || (inode == dp->inode)) {
+
+#    if defined(HASDCACHE)
+                if (DCunsafe && !dp->v && !vfy_dev(ctx, dp))
+                    goto lkupbdev_again;
+#    endif /* defined(HASDCACHE) */
+
+                return (dp);
+            }
+            if (inode < dp->inode)
+                hi = mid - 1;
+            else
+                low = mid + 1;
+        }
+    }
+
+#    if defined(HASDCACHE)
+    if (DCunsafe && r) {
+        (void)rereaddev(ctx);
+        goto lkupbdev_again;
+    }
+#    endif /* defined(HASDCACHE) */
+
+    return ((struct l_dev *)NULL);
 }
-#endif	/* defined(HASBLKDEV) */
-
+#endif /* defined(HASBLKDEV) */
 
-#if	defined(USE_LIB_LKUPDEV)
+#if defined(USE_LIB_LKUPDEV)
 /*
  * lkupdev() - look up a character device
  */
 
-struct l_dev *
-lkupdev(dev, rdev, i, r)
-	dev_t *dev;			/* pointer to device number */
-	dev_t *rdev;			/* pointer to raw device number */
-	int i;				/* inode match status */
-	int r;				/* if 1, rebuild the device cache with
-					 * rereaddev() when no match is found
-					 * and HASDCACHE is defined and
-					 * DCunsafe is one */
+struct l_dev *lkupdev(struct lsof_context *ctx,
+                      dev_t *dev,  /* pointer to device number */
+                      dev_t *rdev, /* pointer to raw device number */
+                      int i,       /* inode match status */
+                      int r)       /* if 1, rebuild the device cache with
+                                    * rereaddev() when no match is found
+                                    * and HASDCACHE is defined and
+                                    * DCunsafe is one */
 {
-	INODETYPE inode = (INODETYPE)0;
-	int low, hi, mid;
-	struct l_dev *dp;
-	int ty = 0;
-
-	if (*dev != DevDev)
-	    return((struct l_dev *)NULL);
-	readdev(0);
-	if (i) {
-	    inode = Lf->inode;
-	    ty = Lf->inp_ty;
-	}
-/*
- * Search device table for match.
- */
-
-# if	defined(HASDCACHE)
+    INODETYPE inode = (INODETYPE)0;
+    int low, hi, mid;
+    struct l_dev *dp;
+    int ty = 0;
+
+    if (*dev != DevDev)
+        return ((struct l_dev *)NULL);
+    readdev(ctx, 0);
+    if (i) {
+        inode = Lf->inode;
+        ty = Lf->inp_ty;
+    }
+    /*
+     * Search device table for match.
+     */
+
+#    if defined(HASDCACHE)
 
 lkupdev_again:
 
-# endif	/* defined(HASDCACHE) */
-
-	low = mid = 0;
-	hi = Ndev - 1;
-	while (low <= hi) {
-	    mid = (low + hi) / 2;
-	    dp = Sdev[mid];
-	    if (*rdev < dp->rdev)
-		hi = mid - 1;
-	    else if (*rdev > dp->rdev)
-		low = mid + 1;
-	    else {
-		if ((i == 0) || (ty != 1) || (inode == dp->inode)) {
-
-# if	defined(HASDCACHE)
-		    if (DCunsafe && !dp->v && !vfy_dev(dp))
-			goto lkupdev_again;
-# endif	/* defined(HASDCACHE) */
-
-		    return(dp);
-		}
-		if (inode < dp->inode)
-		    hi = mid - 1;
-		else
-		    low = mid + 1;
-	    }
-	}
-
-# if	defined(HASDCACHE)
-	if (DCunsafe && r) {
-	    (void) rereaddev();
-	    goto lkupdev_again;
-	}
-# endif	/* defined(HASDCACHE) */
-
-	return((struct l_dev *)NULL);
+#    endif /* defined(HASDCACHE) */
+
+    low = mid = 0;
+    hi = Ndev - 1;
+    while (low <= hi) {
+        mid = (low + hi) / 2;
+        dp = Sdev[mid];
+        if (*rdev < dp->rdev)
+            hi = mid - 1;
+        else if (*rdev > dp->rdev)
+            low = mid + 1;
+        else {
+            if ((i == 0) || (ty != 1) || (inode == dp->inode)) {
+
+#    if defined(HASDCACHE)
+                if (DCunsafe && !dp->v && !vfy_dev(ctx, dp))
+                    goto lkupdev_again;
+#    endif /* defined(HASDCACHE) */
+
+                return (dp);
+            }
+            if (inode < dp->inode)
+                hi = mid - 1;
+            else
+                low = mid + 1;
+        }
+    }
+
+#    if defined(HASDCACHE)
+    if (DCunsafe && r) {
+        (void)rereaddev(ctx);
+        goto lkupdev_again;
+    }
+#    endif /* defined(HASDCACHE) */
+
+    return ((struct l_dev *)NULL);
 }
-#endif	/* defined(USE_LIB_LKUPDEV) */
+#endif /* defined(USE_LIB_LKUPDEV) */
diff --git a/lib/lsof.c b/lib/lsof.c
new file mode 100644
index 0000000..0892c4d
--- /dev/null
+++ b/lib/lsof.c
@@ -0,0 +1,1113 @@
+/*
+ * lsof.c -- implement lsof_* functions() for liblsof
+ */
+
+/*
+ * 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.
+ */
+
+#ifdef AUTOTOOLS
+#    include "config.h"
+#endif
+#include "common.h"
+#include "lsof.h"
+#include <unistd.h>
+
+#ifndef API_EXPORT
+#    define API_EXPORT
+#endif
+
+API_EXPORT
+int lsof_get_api_version() { return LSOF_API_VERSION; }
+
+#ifdef AUTOTOOLS
+API_EXPORT
+char *lsof_get_library_version() { return PACKAGE_VERSION; }
+#endif
+
+API_EXPORT
+struct lsof_context *lsof_new() {
+    struct lsof_context *ctx =
+        (struct lsof_context *)malloc(sizeof(struct lsof_context));
+    if (ctx) {
+        /* Initialization */
+        memset(ctx, 0, sizeof(struct lsof_context));
+
+        if (!(Namech = (char *)malloc(MAXPATHLEN + 1))) {
+            free(ctx);
+            return NULL;
+        }
+        Namechl = (size_t)(MAXPATHLEN + 1);
+
+#if defined(WARNINGSTATE)
+        /* suppress warnings */
+        Fwarn = 1;
+#else  /* !defined(WARNINGSTATE) */
+        /* display warnings */
+        Fwarn = 0;
+#endif /* defined(WARNINGSTATE) */
+
+#if defined(HASXOPT_VALUE)
+        /* -X option status */
+        Fxopt = HASXOPT_VALUE;
+#endif /* defined(HASXOPT_VALUE) */
+
+        /* -1 == none */
+        FdlTy = -1;
+
+        /* Readlink() and stat() timeout (seconds) */
+        TmLimit = TMLIMIT;
+
+        /* default */
+        AllProc = 1;
+
+        /* -1 == none */
+        FdlTy = -1;
+
+        /* device cache file descriptor */
+        DCfd = -1;
+
+        /* device cache path index: -1 = path not defined */
+        DCpathX = -1;
+
+        /* device cache state: 3 = update; read and rebuild if necessary */
+        DCstate = 3;
+
+        /* COMMAND column width limit */
+        CmdLim = CMDL;
+    }
+    return ctx;
+}
+
+API_EXPORT
+enum lsof_error lsof_avoid_blocking(struct lsof_context *ctx, int avoid) {
+    if (!ctx || ctx->frozen) {
+        return LSOF_ERROR_INVALID_ARGUMENT;
+    }
+    Fblock = avoid;
+    return LSOF_EXIT_SUCCESS;
+}
+
+API_EXPORT
+enum lsof_error lsof_avoid_forking(struct lsof_context *ctx, int avoid) {
+    if (!ctx || ctx->frozen) {
+        return LSOF_ERROR_INVALID_ARGUMENT;
+    }
+    Fovhd = avoid;
+    return LSOF_SUCCESS;
+}
+
+API_EXPORT
+enum lsof_error lsof_logic_and(struct lsof_context *ctx) {
+    if (!ctx || ctx->frozen) {
+        return LSOF_ERROR_INVALID_ARGUMENT;
+    }
+    Fand = 1;
+    return LSOF_SUCCESS;
+}
+
+API_EXPORT
+enum lsof_error lsof_select_process(struct lsof_context *ctx, char *command,
+                                    int exclude) {
+    char *cp; /* command copy */
+    MALLOC_S len;
+    struct str_lst *lpt, *str;
+    if (!ctx || ctx->frozen) {
+        return LSOF_ERROR_INVALID_ARGUMENT;
+    }
+
+    /*
+     * Check for command inclusion/exclusion conflicts.
+     */
+    for (str = Cmdl; str; str = str->next) {
+        if (str->x != exclude) {
+            if (!strcmp(str->str, command)) {
+                if (ctx->err) {
+                    (void)fprintf(ctx->err, "%s: -c^%s and -c%s conflict.\n",
+                                  Pn, str->str, command);
+                }
+                return LSOF_ERROR_INVALID_ARGUMENT;
+            }
+        }
+    }
+
+    if (!(cp = mkstrcpy(command, &len))) {
+        if (ctx->err) {
+            (void)fprintf(ctx->err, "%s: no string copy space: ", Pn);
+            safestrprt(command, ctx->err, 1);
+        }
+        return LSOF_ERROR_NO_MEMORY;
+    }
+
+#if defined(MAXSYSCMDL)
+    if (len > MAXSYSCMDL) {
+        /* Impossible to match */
+        if (ctx->err) {
+            (void)fprintf(ctx->err, "%s: \"-c ", Pn);
+            (void)safestrprt(command, ctx->err, 2);
+            (void)fprintf(ctx->err, "\" length (%zu) > what system", len);
+            (void)fprintf(ctx->err, " provides (%d)\n", MAXSYSCMDL);
+        }
+        CLEAN(cp);
+        return LSOF_ERROR_INVALID_ARGUMENT;
+    }
+#endif
+
+    if ((lpt = (struct str_lst *)malloc(sizeof(struct str_lst))) == NULL) {
+        if (ctx->err) {
+            safestrprt(command, ctx->err, 1);
+            (void)fprintf(ctx->err, "%s: no list space: ", Pn);
+            safestrprt(command, ctx->err, 1);
+        }
+        CLEAN(cp);
+        return LSOF_ERROR_NO_MEMORY;
+    }
+
+    /* Insert into list */
+    lpt->f = 0;
+    lpt->str = cp;
+    lpt->len = (int)len;
+    lpt->x = exclude;
+    if (exclude) {
+        Cmdnx++;
+    } else {
+        Cmdni++;
+        /* Update selection flag for inclusions */
+        Selflags |= SELCMD;
+    }
+    lpt->next = Cmdl;
+    Cmdl = lpt;
+
+    return LSOF_SUCCESS;
+}
+
+API_EXPORT
+enum lsof_error lsof_set_output_stream(struct lsof_context *ctx, FILE *fp,
+                                       char *program_name, int warn) {
+    if (!ctx) {
+        return LSOF_ERROR_INVALID_ARGUMENT;
+    }
+    ctx->err = fp;
+    ctx->program_name = mkstrcpy(program_name, NULL);
+    ctx->warn = warn;
+    return LSOF_SUCCESS;
+}
+
+API_EXPORT
+enum lsof_error lsof_freeze(struct lsof_context *ctx) {
+    if (ctx->frozen) {
+        return LSOF_ERROR_INVALID_ARGUMENT;
+    }
+
+    if (Selflags == 0) {
+        Selflags = SelAll;
+    } else {
+        if ((Selflags & (SELNA | SELNET)) != 0 &&
+            (Selflags & ~(SELNA | SELNET)) == 0)
+            Selinet = 1;
+        AllProc = 0;
+    }
+
+    initialize(ctx);
+    hashSfile(ctx);
+    ctx->frozen = 1;
+    return LSOF_SUCCESS;
+}
+
+API_EXPORT
+enum lsof_error lsof_gather(struct lsof_context *ctx,
+                            struct lsof_result **result) {
+    enum lsof_error ret = LSOF_SUCCESS;
+    int pi = 0;  /* proc index */
+    int upi = 0; /* user proc index */
+    struct lsof_process *p;
+    struct lproc *lp;
+    int fi = 0; /* file index */
+    size_t num_files;
+    struct lsof_file *f;
+    struct lfile *lf;
+    struct lfile *lf_next;
+    size_t sel_procs = 0;
+    char *cp;
+    char buf[64];
+    int s;
+    struct str_lst *str;
+    struct sfile *sfp;
+    struct nwad *np, *npn;
+#if defined(HASPROCFS)
+    struct procfsid *pfi;
+#endif /* defined(HASPROCFS) */
+#if defined(HASZONES)
+    znhash_t *zp;
+#endif /* defined(HASZONES) */
+#if defined(HASSELINUX)
+    cntxlist_t *cntxp;
+#endif /* defined(HASSELINUX) */
+    int pass;
+    int i;
+    struct lsof_selection *selections;
+    size_t num_selections = 0;
+
+    if (!result) {
+        ret = LSOF_ERROR_INVALID_ARGUMENT;
+        return ret;
+    } else if (!ctx->frozen) {
+        ret = lsof_freeze(ctx);
+        if (ret != LSOF_SUCCESS)
+            return ret;
+    }
+
+    gather_proc_info(ctx);
+
+    /* Cleanup orphaned cur_file, if any*/
+    if (ctx->cur_file) {
+        CLEAN(ctx->cur_file->dev_ch);
+        CLEAN(ctx->cur_file->nm);
+        CLEAN(ctx->cur_file->nma);
+        CLEAN(ctx->cur_file);
+    }
+
+    /* Count selected procs */
+    for (pi = 0; pi < ctx->procs_size; pi++) {
+        lp = &ctx->procs[pi];
+        if (lp->pss) {
+            sel_procs++;
+        }
+    }
+
+    /* Fill result */
+    struct lsof_result *res =
+        (struct lsof_result *)malloc(sizeof(struct lsof_result));
+    struct lsof_process *user_procs =
+        (struct lsof_process *)malloc(sizeof(struct lsof_process) * sel_procs);
+    memset(user_procs, 0, sizeof(struct lsof_process) * sel_procs);
+
+    for (pi = 0, upi = 0; pi < ctx->procs_size; pi++) {
+        /* Copy fields from lproc */
+        lp = &ctx->procs[pi];
+        if (lp->pss) {
+            /* selected process */
+            p = &user_procs[upi++];
+
+            p->command = lp->cmd;
+            lp->cmd = NULL;
+            p->pid = lp->pid;
+
+#if defined(HASTASKS)
+            p->tid = lp->tid;
+            p->task_cmd = lp->tcmd;
+            lp->tcmd = NULL;
+#endif
+#if defined(HASZONES)
+            p->solaris_zone = lp->zn;
+            lp->zn = NULL;
+#endif
+#if defined(HASSELINUX)
+            p->selinux_context = lp->cntx;
+            lp->cntx = NULL;
+#endif
+
+            p->pgid = lp->pgid;
+            p->ppid = lp->ppid;
+            p->uid = lp->uid;
+
+            /* Compute number of files in the linked list */
+            num_files = 0;
+            for (lf = lp->file; lf; lf = lf->next) {
+                if (!is_file_sel(ctx, lp, lf))
+                    continue;
+                num_files++;
+            }
+
+            p->files = (struct lsof_file *)malloc(sizeof(struct lsof_file) *
+                                                  num_files);
+            memset(p->files, 0, sizeof(struct lsof_file) * num_files);
+            p->num_files = num_files;
+            for (fi = 0, lf = lp->file; lf; lf = lf_next) {
+                if (is_file_sel(ctx, lp, lf)) {
+                    /* Copy fields from lfile */
+                    f = &p->files[fi++];
+                    f->flags = 0;
+
+                    /* FD column */
+                    f->fd_type = lf->fd_type;
+                    f->fd_num = lf->fd_num;
+                    f->access = lf->access;
+                    f->lock = lf->lock;
+
+                    /* TYPE column */
+                    f->file_type = lf->type;
+                    f->unknown_file_type_number = lf->unknown_file_type_number;
+
+                    /* DEVICE column */
+                    f->dev = lf->dev;
+                    if (lf->dev_def) {
+                        f->flags |= LSOF_FILE_FLAG_DEV_VALID;
+                    }
+                    f->rdev = lf->rdev;
+                    if (lf->rdev_def) {
+                        f->flags |= LSOF_FILE_FLAG_RDEV_VALID;
+                    }
+
+                    /* SIZE, SIZE/OFF, OFFSET column */
+                    f->size = lf->sz;
+                    if (lf->sz_def) {
+                        f->flags |= LSOF_FILE_FLAG_SIZE_VALID;
+                    }
+                    f->offset = lf->off;
+                    if (lf->off_def) {
+                        f->flags |= LSOF_FILE_FLAG_OFFSET_VALID;
+                    }
+
+                    /* NLINK column */
+                    f->num_links = lf->nlink;
+                    if (lf->nlink_def) {
+                        f->flags |= LSOF_FILE_FLAG_NUM_LINKS_VALID;
+                    }
+
+                    /* NODE column */
+                    f->inode = lf->inode;
+                    if (lf->inp_ty == 1 || lf->inp_ty == 3) {
+                        f->flags |= LSOF_FILE_FLAG_INODE_VALID;
+                    }
+
+                    /* NAME column */
+                    f->name = lf->nm;
+                    lf->nm = NULL;
+                }
+                lf_next = lf->next;
+            }
+        }
+
+        for (lf = lp->file; lf; lf = lf_next) {
+            /* free lf */
+            lf_next = lf->next;
+            CLEAN(lf->nma);
+            CLEAN(lf->dev_ch);
+#if defined(CLRLFILEADD)
+            CLRLFILEADD(lf)
+#endif /* defined(CLRLFILEADD) */
+            CLEAN(lf);
+        }
+        lp->file = NULL;
+
+        /* skip and free */
+        CLEAN(lp->cmd);
+#if defined(HASTASKS)
+        CLEAN(lp->tcmd);
+#endif
+#if defined(HASSELINUX)
+        CLEAN(lp->cntx);
+#endif /* defined(HASSELINUX) */
+        continue;
+    }
+
+    /* Cleanup */
+    CLEAN(ctx->procs);
+    ctx->cur_proc = NULL;
+
+    res->processes = user_procs;
+    res->num_processes = sel_procs;
+
+    ctx->procs_size = ctx->procs_cap = 0;
+    ctx->cur_file = ctx->prev_file = NULL;
+
+    /* Collect selection result */
+    for (pass = 0; pass < 2; pass++) {
+        num_selections = 0;
+
+        /* command */
+        for (str = Cmdl; str; str = str->next) {
+            if (pass) {
+                selections[num_selections].type = LSOF_SELECTION_COMMAND;
+                selections[num_selections].found = str->f;
+                selections[num_selections].string = str->str;
+            }
+            num_selections++;
+        }
+
+        /* command regex */
+        for (i = 0; i < NCmdRxU; i++) {
+            if (pass) {
+                selections[num_selections].type = LSOF_SELECTION_COMMAND_REGEX;
+                selections[num_selections].found = CmdRx[i].mc > 0;
+                selections[num_selections].string = CmdRx[i].exp;
+            }
+            num_selections++;
+        }
+
+        /* select file or file system */
+        for (sfp = Sfile; sfp; sfp = sfp->next) {
+            if (pass) {
+                selections[num_selections].type =
+                    sfp->type ? LSOF_SELECTION_PATH
+                              : LSOF_SELECTION_FILE_SYSTEM;
+                selections[num_selections].found = sfp->f;
+                selections[num_selections].string = sfp->aname;
+            }
+            num_selections++;
+        }
+
+#if defined(HASPROCFS)
+        /* procfs */
+        if (Procsrch) {
+            if (pass) {
+                selections[num_selections].type = LSOF_SELECTION_FILE_SYSTEM;
+                selections[num_selections].found = Procfind;
+                selections[num_selections].string =
+                    Mtprocfs ? Mtprocfs->dir : HASPROCFS;
+            }
+            num_selections++;
+        }
+
+        for (pfi = Procfsid; pfi; pfi = pfi->next) {
+            if (pass) {
+                selections[num_selections].type = LSOF_SELECTION_PATH;
+                selections[num_selections].found = pfi->f;
+                selections[num_selections].string = pfi->nm;
+            }
+            num_selections++;
+        }
+#endif /* defined(HASPROCFS) */
+
+        /* network address */
+        for (np = Nwad; np;) {
+            int found = np->f;
+            if (!(cp = np->arg)) {
+                np = np->next;
+                continue;
+            }
+            for (npn = np->next; npn; npn = npn->next) {
+                if (!npn->arg)
+                    continue;
+                if (!strcmp(cp, npn->arg)) {
+                    /* Found duplicate specification */
+                    found |= npn->f;
+                } else {
+                    break;
+                }
+            }
+
+            if (pass) {
+                selections[num_selections].type =
+                    LSOF_SELECTION_NETWORK_ADDRESS;
+                selections[num_selections].found = found;
+                selections[num_selections].string = np->arg;
+            }
+            num_selections++;
+            np = npn;
+        }
+
+        /* ip protocol */
+        if (Fnet) {
+            if (pass) {
+                selections[num_selections].type = LSOF_SELECTION_INTERNET;
+                selections[num_selections].found = Fnet == 2;
+            }
+            num_selections++;
+        }
+
+#if defined(HASTCPUDPSTATE)
+        /* tcp/tpi protocol state */
+        if (TcpStIn) {
+            for (i = 0; i < TcpNstates; i++) {
+                if (TcpStI[i]) {
+                    if (pass) {
+                        selections[num_selections].type =
+                            LSOF_SELECTION_PROTOCOL_STATE;
+                        selections[num_selections].found = TcpStI[i] == 2;
+                        selections[num_selections].string = TcpSt[i];
+                    }
+                    num_selections++;
+                }
+            }
+        }
+        if (UdpStIn) {
+            for (i = 0; i < UdpNstates; i++) {
+                if (UdpStI[i]) {
+                    if (pass) {
+                        selections[num_selections].type =
+                            LSOF_SELECTION_PROTOCOL_STATE;
+                        selections[num_selections].found = UdpStI[i] == 2;
+                        selections[num_selections].string = UdpSt[i];
+                    }
+                    num_selections++;
+                }
+            }
+        }
+#endif /* defined(HASTCPUDPSTATE) */
+
+        /* nfs */
+        if (Fnfs) {
+            if (pass) {
+                selections[num_selections].type = LSOF_SELECTION_NFS;
+                selections[num_selections].found = Fnfs == 2;
+            }
+            num_selections++;
+        }
+
+        /* pid */
+        for (i = 0; i < Npid; i++) {
+            if (Spid[i].x)
+                continue;
+            if (pass) {
+                selections[num_selections].type = LSOF_SELECTION_PID;
+                selections[num_selections].found = Spid[i].f;
+                selections[num_selections].integer = Spid[i].i;
+            }
+            num_selections++;
+        }
+
+        /* pgid */
+        for (i = 0; i < Npgid; i++) {
+            if (Spgid[i].x)
+                continue;
+            if (pass) {
+                selections[num_selections].type = LSOF_SELECTION_PGID;
+                selections[num_selections].found = Spgid[i].f;
+                selections[num_selections].integer = Spgid[i].i;
+            }
+            num_selections++;
+        }
+
+        /* uid */
+        for (i = 0; i < Nuid; i++) {
+            if (Suid[i].excl)
+                continue;
+            if (pass) {
+                selections[num_selections].type = LSOF_SELECTION_UID;
+                selections[num_selections].found = Suid[i].f;
+                selections[num_selections].string = Suid[i].lnm;
+                selections[num_selections].integer = Suid[i].uid;
+            }
+            num_selections++;
+        }
+
+#if defined(HASTASKS)
+        /* tasks */
+        if (Ftask) {
+            if (pass) {
+                selections[num_selections].type = LSOF_SELECTION_TASK;
+                selections[num_selections].found = Ftask == 2;
+            }
+            num_selections++;
+        }
+#endif /* defined(HASTASKS) */
+
+#if defined(HASZONES)
+        /* solaris zones */
+        if (ZoneArg) {
+            for (i = 0; i < HASHZONE; i++) {
+                for (zp = ZoneArg[i]; zp; zp = zp->next) {
+                    if (pass) {
+                        selections[num_selections].type =
+                            LSOF_SELECTION_SOLARIS_ZONE;
+                        selections[num_selections].found = zp->f;
+                        selections[num_selections].string = zp->zn;
+                    }
+                    num_selections++;
+                }
+            }
+        }
+#endif /* defined(HASZONES) */
+
+#if defined(HASSELINUX)
+        /* SELinux context */
+        if (CntxArg) {
+            for (cntxp = CntxArg; cntxp; cntxp = cntxp->next) {
+                if (pass) {
+                    selections[num_selections].type =
+                        LSOF_SELECTION_SELINUX_CONTEXT;
+                    selections[num_selections].found = cntxp->f;
+                    selections[num_selections].string = cntxp->cntx;
+                }
+                num_selections++;
+            }
+        }
+#endif /* defined(HASSELINUX) */
+
+        /* allocation selections array */
+        if (pass == 0) {
+            selections = (struct lsof_selection *)malloc(
+                sizeof(struct lsof_selection) * num_selections);
+            memset(selections, 0,
+                   sizeof(struct lsof_selection) * num_selections);
+            res->selections = selections;
+            res->num_selections = num_selections;
+        }
+    }
+
+    /* Params */
+    *result = res;
+
+    return ret;
+}
+
+API_EXPORT
+void lsof_destroy(struct lsof_context *ctx) {
+    int i;
+    struct str_lst *str_lst, *str_lst_next;
+    struct int_lst *int_lst, *int_lst_next;
+    struct mounts *mnt, *mnt_next;
+    if (!ctx) {
+        return;
+    }
+    /* Free parameters */
+    for (str_lst = Cmdl; str_lst; str_lst = str_lst_next) {
+        str_lst_next = str_lst->next;
+        CLEAN(str_lst->str);
+        CLEAN(str_lst);
+    }
+    CLEAN(Spid);
+    CLEAN(Spgid);
+    for (i = 0; i < Nuid; i++) {
+        CLEAN(Suid[i].lnm);
+    }
+    CLEAN(Suid);
+    CLEAN(Nmlst);
+
+    /* Free temporary */
+    CLEAN(Namech);
+#if defined(HASNLIST)
+    CLEAN(Nl);
+    Nll = 0;
+#endif /* defined(HASNLIST) */
+
+    /* Free local mount info */
+    if (Lmist) {
+        for (mnt = Lmi; mnt; mnt = mnt_next) {
+            mnt_next = mnt->next;
+            CLEAN(mnt->dir);
+            CLEAN(mnt->fsname);
+            CLEAN(mnt->fsnmres);
+#if defined(HASFSTYPE)
+            CLEAN(mnt->fstype);
+#endif
+            CLEAN(mnt);
+        }
+        Lmi = NULL;
+        Lmist = 0;
+    }
+
+    /* state table */
+#if !defined(USE_LIB_PRINT_TCPTPI)
+    for (i = 0; i < TcpNstates; i++) {
+        CLEAN(TcpSt[i]);
+    }
+    CLEAN(TcpSt);
+#endif /* !defined(USE_LIB_PRINT_TCPTPI) */
+    for (i = 0; i < UdpNstates; i++) {
+        CLEAN(UdpSt[i]);
+    }
+    CLEAN(UdpSt);
+    CLEAN(Pn);
+
+    CLEAN(ctx);
+}
+
+API_EXPORT
+void lsof_free_result(struct lsof_result *result) {
+    int pi, fi;
+    struct lsof_process *p;
+    struct lsof_file *f;
+    for (pi = 0; pi < result->num_processes; pi++) {
+        p = &result->processes[pi];
+        /* Free files */
+        for (fi = 0; fi < p->num_files; fi++) {
+            f = &p->files[fi];
+            CLEAN(f->name);
+        }
+        CLEAN(p->files);
+
+        /* Free process fields */
+        CLEAN(p->command);
+        CLEAN(p->task_cmd);
+        CLEAN(p->solaris_zone);
+        CLEAN(p->selinux_context);
+    }
+    CLEAN(result->processes);
+    CLEAN(result->selections);
+    CLEAN(result);
+}
+
+API_EXPORT
+enum lsof_error lsof_select_process_regex(struct lsof_context *ctx, char *x) {
+    int bmod = 0;
+    int bxmod = 0;
+    int i, re;
+    int imod = 0;
+    int xmod = 0;
+    int co = REG_NOSUB | REG_EXTENDED;
+    char reb[256], *xb, *xe, *xm;
+    MALLOC_S xl;
+    char *xp = (char *)NULL;
+    enum lsof_error ret = LSOF_SUCCESS;
+
+    if (!ctx || ctx->frozen) {
+        return LSOF_ERROR_INVALID_ARGUMENT;
+    }
+
+    /*
+     * Make sure the supplied string starts a regular expression.
+     */
+    if (!*x || (*x != '/')) {
+        if (ctx->err) {
+            (void)fprintf(ctx->err, "%s: regexp doesn't begin with '/': ", Pn);
+            if (x)
+                safestrprt(x, ctx->err, 1);
+        }
+        ret = LSOF_ERROR_INVALID_ARGUMENT;
+        goto cleanup;
+    }
+
+    /*
+     * Skip to the end ('/') of the regular expression.
+     */
+    xb = x + 1;
+    for (xe = xb; *xe; xe++) {
+        if (*xe == '/')
+            break;
+    }
+    if (*xe != '/') {
+        if (ctx->err) {
+            (void)fprintf(ctx->err, "%s: regexp doesn't end with '/': ", Pn);
+            safestrprt(x, ctx->err, 1);
+        }
+        ret = LSOF_ERROR_INVALID_ARGUMENT;
+        goto cleanup;
+    }
+
+    /*
+     * Decode any regular expression modifiers.
+     */
+    for (i = 0, xm = xe + 1; *xm; xm++) {
+        switch (*xm) {
+        case 'b': /* This is a basic expression. */
+            if (++bmod > 1) {
+                if (bmod == 2 && ctx->err) {
+                    (void)fprintf(ctx->err,
+                                  "%s: b regexp modifier already used: ", Pn);
+                    safestrprt(x, ctx->err, 1);
+                }
+                i = 1;
+            } else if (xmod) {
+                if (++bxmod == 1 && ctx->err) {
+                    (void)fprintf(
+                        ctx->err,
+                        "%s: b and x regexp modifiers conflict: ", Pn);
+                    safestrprt(x, ctx->err, 1);
+                }
+                i = 1;
+            } else
+                co &= ~REG_EXTENDED;
+            break;
+        case 'i': /* Ignore case. */
+            if (++imod > 1) {
+                if (imod == 2 && ctx->err) {
+                    (void)fprintf(ctx->err,
+                                  "%s: i regexp modifier already used: ", Pn);
+                    safestrprt(x, ctx->err, 1);
+                }
+                i = 1;
+            } else
+                co |= REG_ICASE;
+            break;
+        case 'x': /* This is an extended expression. */
+            if (++xmod > 1) {
+                if (xmod == 2 && ctx->err) {
+                    (void)fprintf(ctx->err,
+                                  "%s: x regexp modifier already used: ", Pn);
+                    safestrprt(x, ctx->err, 1);
+                }
+                i = 1;
+            } else if (bmod) {
+                if (++bxmod == 1 && ctx->err) {
+                    (void)fprintf(
+                        ctx->err,
+                        "%s: b and x regexp modifiers conflict: ", Pn);
+                    safestrprt(x, ctx->err, 1);
+                }
+                i = 1;
+            } else
+                co |= REG_EXTENDED;
+            break;
+        default:
+            if (ctx->err)
+                (void)fprintf(ctx->err, "%s: invalid regexp modifier: %c\n", Pn,
+                              (int)*xm);
+            i = 1;
+        }
+    }
+    if (i) {
+        ret = LSOF_ERROR_INVALID_ARGUMENT;
+        goto cleanup;
+    }
+
+    /*
+     * Allocate space to hold expression and copy it there.
+     */
+    xl = (MALLOC_S)(xe - xb);
+    if (!(xp = (char *)malloc(xl + 1))) {
+        if (ctx->err) {
+            (void)fprintf(ctx->err, "%s: no regexp space for: ", Pn);
+            safestrprt(x, ctx->err, 1);
+        }
+        Error(ctx);
+        ret = LSOF_ERROR_NO_MEMORY;
+        goto cleanup;
+    }
+    (void)strncpy(xp, xb, xl);
+    xp[(int)xl] = '\0';
+    /*
+     * Assign a new CmdRx[] slot for this expression.
+     */
+    if (NCmdRxA <= NCmdRxU) {
+        /*
+         * More CmdRx[] space must be assigned.
+         */
+        NCmdRxA += 32;
+        xl = (MALLOC_S)(ctx->cmd_regex_cap * sizeof(lsof_rx_t));
+        if (CmdRx)
+            CmdRx = (lsof_rx_t *)realloc((MALLOC_P *)CmdRx, xl);
+        else
+            CmdRx = (lsof_rx_t *)malloc(xl);
+        if (!CmdRx) {
+            if (ctx->err) {
+                (void)fprintf(ctx->err, "%s: no space for regexp: ", Pn);
+                safestrprt(x, ctx->err, 1);
+            }
+            Error(ctx);
+            ret = LSOF_ERROR_NO_MEMORY;
+            goto cleanup;
+        }
+    }
+    i = NCmdRxU;
+    CmdRx[i].exp = xp;
+    /*
+     * Compile the expression.
+     */
+    if ((re = regcomp(&CmdRx[i].cx, xp, co))) {
+        if (ctx->err) {
+            (void)fprintf(ctx->err, "%s: regexp error: ", Pn);
+            safestrprt(x, ctx->err, 0);
+            (void)regerror(re, &CmdRx[i].cx, &reb[0], sizeof(reb));
+            (void)fprintf(ctx->err, ": %s\n", reb);
+        }
+        ret = LSOF_ERROR_INVALID_ARGUMENT;
+        goto cleanup;
+    }
+    /*
+     * Complete the CmdRx[] table entry.
+     */
+    CmdRx[i].mc = 0;
+    CmdRx[i].exp = xp;
+    NCmdRxU++;
+
+    /** Update selection flags for inclusion */
+    if (CmdRx)
+        Selflags |= SELCMD;
+    ret = LSOF_SUCCESS;
+cleanup:
+    CLEAN(xp);
+    return ret;
+}
+
+/* Internal helper for lsof_select_pid/pgid */
+enum lsof_error lsof_select_pid_pgid(struct lsof_context *ctx, int32_t id,
+                                     struct int_lst **sel, int *cap, int *size,
+                                     int *incl_num, int *excl_num, int exclude,
+                                     int is_pid) {
+    int i, j;
+    if (!ctx || ctx->frozen) {
+        return LSOF_ERROR_INVALID_ARGUMENT;
+    }
+
+    /*
+     * Avoid entering duplicates and conflicts.
+     */
+    for (i = 0; i < *size; i++) {
+        if (id == (*sel)[i].i) {
+            if (exclude == (*sel)[i].x) {
+                return LSOF_SUCCESS;
+            }
+            if (ctx->err) {
+                (void)fprintf(ctx->err,
+                              "%s: P%sID %d has been included and excluded.\n",
+                              Pn, is_pid ? "" : "G", id);
+            }
+            return LSOF_ERROR_INVALID_ARGUMENT;
+        }
+    }
+
+    /*
+     * Allocate table table space.
+     */
+    if (*size >= *cap) {
+        *cap += 10;
+        if (!(*sel))
+            *sel = (struct int_lst *)malloc(
+                (MALLOC_S)(sizeof(struct int_lst) * (*cap)));
+        else
+            *sel = (struct int_lst *)realloc(
+                (MALLOC_P *)(*sel),
+                (MALLOC_S)(sizeof(struct int_lst) * (*cap)));
+        if (!(*sel)) {
+            if (ctx->err) {
+                (void)fprintf(ctx->err, "%s: no space for %d process%s IDs", Pn,
+                              *cap, is_pid ? "" : " group");
+            }
+            Error(ctx);
+            return LSOF_ERROR_NO_MEMORY;
+        }
+    }
+
+    /* Insert selection into sel_pid/sel_pgid*/
+    (*sel)[*size].f = 0;
+    (*sel)[*size].i = id;
+    (*sel)[(*size)++].x = exclude;
+    if (exclude)
+        (*excl_num)++;
+    else {
+        (*incl_num)++;
+        /* Update selection flags */
+        Selflags |= is_pid ? SELPID : SELPGID;
+    }
+    return LSOF_SUCCESS;
+}
+
+API_EXPORT
+enum lsof_error lsof_select_pid(struct lsof_context *ctx, uint32_t pid,
+                                int exclude) {
+    enum lsof_error res = lsof_select_pid_pgid(ctx, pid, &Spid, &Mxpid, &Npid,
+                                               &Npidi, &Npidx, exclude, 1);
+    /* Record number of unselected PIDs for optimization */
+    Npuns = Npid;
+    return res;
+}
+
+API_EXPORT
+enum lsof_error lsof_select_pgid(struct lsof_context *ctx, uint32_t pgid,
+                                 int exclude) {
+    return lsof_select_pid_pgid(ctx, pgid, &Spgid, &Mxpgid, &Npgid, &Npgidi,
+                                &Npgidx, exclude, 0);
+}
+
+/* Internal helper for lsof_select_uid/lsof_select_login*/
+enum lsof_error lsof_select_uid_login(struct lsof_context *ctx, uint32_t uid,
+                                      char *login, int exclude) {
+    int i, j;
+    MALLOC_S len;
+    char *lp;
+
+    if (!ctx || ctx->frozen) {
+        return LSOF_ERROR_INVALID_ARGUMENT;
+    }
+
+    /*
+     * Avoid entering duplicates.
+     */
+    for (i = 0; i < Nuid; i++) {
+        if (uid != Suid[i].uid)
+            continue;
+        /* Duplicate */
+        if (Suid[i].excl == exclude) {
+            return LSOF_SUCCESS;
+        }
+
+        /* Conflict */
+        if (ctx->err) {
+            (void)fprintf(ctx->err,
+                          "%s: UID %d has been included and excluded.\n", Pn,
+                          (int)uid);
+        }
+        return LSOF_ERROR_INVALID_ARGUMENT;
+    }
+
+    /*
+     * Allocate space for User IDentifier.
+     */
+    if (Nuid >= Mxuid) {
+        Mxuid += 10;
+        len = (MALLOC_S)(Mxuid * sizeof(struct seluid));
+        if (!Suid)
+            Suid = (struct seluid *)malloc(len);
+        else
+            Suid = (struct seluid *)realloc((MALLOC_P *)Suid, len);
+        if (!Suid) {
+            if (ctx->err) {
+                (void)fprintf(ctx->err, "%s: no space for UIDs", Pn);
+            }
+            Error(ctx);
+            return LSOF_ERROR_NO_MEMORY;
+        }
+    }
+    if (login) {
+        if (!(lp = mkstrcpy(login, (MALLOC_S *)NULL))) {
+            if (ctx->err) {
+                (void)fprintf(ctx->err, "%s: no space for login: ", Pn);
+                safestrprt(login, ctx->err, 1);
+            }
+            Error(ctx);
+            return LSOF_ERROR_NO_MEMORY;
+        }
+        Suid[Nuid].lnm = lp;
+    } else
+        Suid[Nuid].lnm = (char *)NULL;
+    Suid[Nuid].f = 0;
+    Suid[Nuid].uid = uid;
+    Suid[Nuid++].excl = exclude;
+    if (exclude)
+        Nuidexcl++;
+    else {
+        Nuidincl++;
+        Selflags |= SELUID;
+    }
+    return LSOF_SUCCESS;
+}
+
+API_EXPORT
+enum lsof_error lsof_select_uid(struct lsof_context *ctx, uint32_t uid,
+                                int exclude) {
+    return lsof_select_uid_login(ctx, uid, NULL, exclude);
+}
+
+API_EXPORT
+enum lsof_error lsof_select_login(struct lsof_context *ctx, char *login,
+                                  int exclude) {
+    struct passwd *pw;
+    if (!ctx || ctx->frozen) {
+        return LSOF_ERROR_INVALID_ARGUMENT;
+    }
+
+    /* Convert login to uid, then call lsof_select_uid_login */
+    if ((pw = getpwnam(login)) == NULL) {
+        if (ctx->err) {
+            (void)fprintf(ctx->err, "%s: can't get UID for ", Pn);
+            safestrprt(login, ctx->err, 1);
+        }
+        return LSOF_ERROR_INVALID_ARGUMENT;
+    }
+    return lsof_select_uid_login(ctx, pw->pw_uid, login, exclude);
+}
diff --git a/lib/misc.c b/lib/misc.c
new file mode 100644
index 0000000..996cee5
--- /dev/null
+++ b/lib/misc.c
@@ -0,0 +1,1627 @@
+/*
+ * misc.c - common miscellaneous 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.
+ */
+
+#include "common.h"
+#include "dlsof.h"
+
+#if defined(HASWIDECHAR)
+#    if defined(WIDECHARINCL)
+#        include WIDECHARINCL
+#    endif /* defined(WIDECHARINCL) */
+#    if defined(HASWCTYPE_H)
+#        include <wctype.h>
+#    endif /* defined(HASWCTYPE_H) */
+#endif     /* defined(HASWIDECHAR) */
+
+/*
+ * Local definitions
+ */
+
+#if !defined(MAXSYMLINKS)
+#    define MAXSYMLINKS 32
+#endif /* !defined(MAXSYMLINKS) */
+
+/*
+ * Local function prototypes
+ */
+
+static void closePipes(void);
+static int dolstat(char *path, char *buf, int len);
+static int dostat(char *path, char *buf, int len);
+static int doreadlink(char *path, char *buf, int len);
+static int doinchild(struct lsof_context *ctx, int (*fn)(char *path, char *buf, int len), char *fp,
+                     char *rbuf, int rbln);
+
+#if defined(HASINTSIGNAL)
+static int handleint(int sig);
+#else  /* !defined(HASINTSIGNAL) */
+static void handleint(int sig);
+#endif /* defined(HASINTSIGNAL) */
+
+/*
+ * Local variables
+ */
+
+static pid_t Cpid = 0;  /* child PID */
+static jmp_buf Jmp_buf; /* jump buffer */
+static int Pipes[] =    /* pipes for child process */
+    {-1, -1, -1, -1};
+static int CtSigs[] = {0, SIGINT, SIGKILL};
+/* child termination signals (in order
+ * of application) -- the first is a
+ * dummy to allow pipe closure to
+ * cause the child to exit */
+#define NCTSIGS (sizeof(CtSigs) / sizeof(int))
+
+#if defined(HASNLIST)
+/*
+ * build-Nl() - build kernel name list table
+ */
+
+static struct drive_Nl *Build_Nl = (struct drive_Nl *)NULL;
+/* the default Drive_Nl address */
+
+void build_Nl(struct lsof_context *ctx,
+              struct drive_Nl *d) /* data to drive the construction */
+{
+    struct drive_Nl *dp;
+    int i, n;
+
+    for (dp = d, n = 0; dp->nn; dp++, n++)
+        ;
+    if (n < 1) {
+        (void)fprintf(stderr, "%s: can't calculate kernel name list length\n",
+                      Pn);
+        Error(ctx);
+    }
+    if (!(Nl = (struct NLIST_TYPE *)calloc((n + 1),
+                                           sizeof(struct NLIST_TYPE)))) {
+        (void)fprintf(
+            stderr,
+            "%s: can't allocate %d bytes to kernel name list structure\n", Pn,
+            (int)((n + 1) * sizeof(struct NLIST_TYPE)));
+        Error(ctx);
+    }
+    for (dp = d, i = 0; i < n; dp++, i++) {
+        Nl[i].NL_NAME = dp->knm;
+    }
+    Nll = (int)((n + 1) * sizeof(struct NLIST_TYPE));
+    Build_Nl = d;
+}
+#endif /* defined(HASNLIST) */
+
+/*
+ * childx() - make child process exit (if possible)
+ */
+
+void childx(struct lsof_context *ctx) {
+    static int at, sx;
+    pid_t wpid;
+
+    if (Cpid > 1) {
+
+        /*
+         * First close the pipes to and from the child.  That should cause the
+         * child to exit.  Compute alarm time shares.
+         */
+        (void)closePipes();
+        if ((at = TmLimit / NCTSIGS) < TMLIMMIN)
+            at = TMLIMMIN;
+        /*
+         * Loop, waiting for the child to exit.  After the first pass, help
+         * the child exit by sending it signals.
+         */
+        for (sx = 0; sx < NCTSIGS; sx++) {
+            if (setjmp(Jmp_buf)) {
+
+                /*
+                 * An alarm has rung.  Disable further alarms.
+                 *
+                 * If there are more signals to send, continue the signal loop.
+                 *
+                 * If the last signal has been sent, issue a warning (unless
+                 * warninge have been suppressed) and exit the signal loop.
+                 */
+                (void)alarm(0);
+                (void)signal(SIGALRM, SIG_DFL);
+                if (sx < (NCTSIGS - 1))
+                    continue;
+                if (!Fwarn)
+                    (void)fprintf(
+                        stderr,
+                        "%s: WARNING -- child process %d may be hung.\n", Pn,
+                        (int)Cpid);
+                break;
+            }
+            /*
+             * Send the next signal to the child process, after the first pass
+             * through the loop.
+             *
+             * Wrap the wait() with an alarm.
+             */
+            if (sx)
+                (void)kill(Cpid, CtSigs[sx]);
+            (void)signal(SIGALRM, handleint);
+            (void)alarm(at);
+            wpid = (pid_t)wait(NULL);
+            (void)alarm(0);
+            (void)signal(SIGALRM, SIG_DFL);
+            if (wpid == Cpid)
+                break;
+        }
+        Cpid = 0;
+    }
+}
+
+/*
+ * closePipes() - close open pipe file descriptors
+ */
+
+static void closePipes() {
+    int i;
+
+    for (i = 0; i < 4; i++) {
+        if (Pipes[i] >= 0) {
+            (void)close(Pipes[i]);
+            Pipes[i] = -1;
+        }
+    }
+}
+
+/*
+ * compdev() - compare Devtp[] entries
+ */
+
+int compdev(COMP_P *a1, COMP_P *a2) {
+    struct l_dev **p1 = (struct l_dev **)a1;
+    struct l_dev **p2 = (struct l_dev **)a2;
+
+    if ((dev_t)((*p1)->rdev) < (dev_t)((*p2)->rdev))
+        return (-1);
+    if ((dev_t)((*p1)->rdev) > (dev_t)((*p2)->rdev))
+        return (1);
+    if ((INODETYPE)((*p1)->inode) < (INODETYPE)((*p2)->inode))
+        return (-1);
+    if ((INODETYPE)((*p1)->inode) > (INODETYPE)((*p2)->inode))
+        return (1);
+    return (strcmp((*p1)->name, (*p2)->name));
+}
+
+/*
+ * closefrom_shim() -- provide closefrom() when unavailable
+ */
+void closefrom_shim(struct lsof_context *ctx, int low) {
+    int i;
+#if defined(HAS_CLOSEFROM)
+    (void)closefrom(low);
+#else /* !defined(HAS_CLOSEFROM) */
+    /* fallback to SYS_close_range */
+#    if defined(SYS_close_range)
+    if (MaxFd > low && syscall(SYS_close_range, low, MaxFd - 1, 0) == 0)
+        return;
+#    endif
+#    if defined(LINUX_LSOF_H)
+    /* optimized fallback for Linux:
+     * iterate /proc/self/fd and close fd's that are not that directory itself
+     */
+    long fd;
+    char *endp;
+    struct dirent *dent;
+    DIR *dirp;
+
+    dirp = opendir("/proc/self/fd");
+    if (dirp) {
+        while ((dent = readdir(dirp)) != NULL) {
+            fd = strtol(dent->d_name, &endp, 10);
+            if (dent->d_name != endp && *endp == '\0' && fd >= 0 &&
+                fd < INT_MAX && fd >= low && fd != dirfd(dirp))
+                (void)close((int)fd);
+        }
+        (void)closedir(dirp);
+        return;
+    }
+#    endif
+    /* slow brute force fallback */
+    for (i = low; i < MaxFd; i++)
+        (void)close(i);
+#endif /* !defined(HAS_CLOSEFROM) */
+}
+
+/*
+ * doinchild() -- do a function in a child process
+ */
+
+static int doinchild(struct lsof_context *ctx,
+                     int (*fn)(char *path, char *buf, int len), /* function to perform */
+                     char *fp,    /* function parameter */
+                     char *rbuf,  /* response buffer */
+                     int rbln)    /* response buffer length */
+{
+    int en, rv;
+
+    /*
+     * Check reply buffer size.
+     */
+    if (!Fovhd && rbln > MAXPATHLEN) {
+        (void)fprintf(stderr,
+                      "%s: doinchild error; response buffer too large: %d\n",
+                      Pn, rbln);
+        Error(ctx);
+    }
+    /*
+     * Set up to handle an alarm signal; handle an alarm signal; build
+     * pipes for exchanging information with a child process; start the
+     * child process; and perform functions in the child process.
+     */
+    if (!Fovhd) {
+        if (setjmp(Jmp_buf)) {
+
+            /*
+             * Process an alarm that has rung.
+             */
+            (void)alarm(0);
+            (void)signal(SIGALRM, SIG_DFL);
+            (void)childx(ctx);
+            errno = ETIMEDOUT;
+            return (1);
+        } else if (!Cpid) {
+
+            /*
+             * Create pipes to exchange function information with a child
+             * process.
+             */
+            if (pipe(Pipes) < 0 || pipe(&Pipes[2]) < 0) {
+                (void)fprintf(stderr, "%s: can't open pipes: %s\n", Pn,
+                              strerror(errno));
+                Error(ctx);
+            }
+            /*
+             * Fork a child to execute functions.
+             */
+            if ((Cpid = fork()) == 0) {
+
+                /*
+                 * Begin the child process.
+                 */
+
+                int r_al, r_rbln;
+                char r_arg[MAXPATHLEN + 1];
+                union {
+                    char r_rbuf[MAXPATHLEN + 1];
+                    /*
+                     * This field is only for adjusting the alignment of r_rbuf
+                     * that can be used as an argument for stat().
+                     */
+                    struct stat _;
+                } r;
+                int (*r_fn)(char *path, char *buf, int len);
+                /*
+                 * Close sufficient open file descriptors except Pipes[0] and
+                 * Pipes[3].
+                 */
+
+#if defined(HAS_DUP2)
+                int rc;
+
+                rc = dup2(Pipes[0], 0);
+                if (rc < 0) {
+                    (void)fprintf(stderr,
+                                  "%s: can't dup Pipes[0] to fd 0: %s\n", Pn,
+                                  strerror(errno));
+                    Error(ctx);
+                }
+                Pipes[0] = 0;
+                rc = dup2(Pipes[3], 1);
+                if (rc < 0) {
+                    (void)fprintf(stderr,
+                                  "%s: can't dup Pipes.[3] to fd 1: %s\n", Pn,
+                                  strerror(errno));
+                    Error(ctx);
+                }
+                Pipes[3] = 1;
+                (void)closefrom_shim(ctx, 2);
+                Pipes[1] = -1;
+                Pipes[2] = -1;
+
+#else  /* !defined(HAS_DUP2) */
+                int fd;
+
+                for (fd = 0; fd < MaxFd; fd++) {
+                    if (fd == Pipes[0] || fd == Pipes[3])
+                        continue;
+                    (void)close(fd);
+                    if (fd == Pipes[1])
+                        Pipes[1] = -1;
+                    else if (fd == Pipes[2])
+                        Pipes[2] = -1;
+                }
+                if (Pipes[1] >= 0) {
+                    (void)close(Pipes[1]);
+                    Pipes[1] = -1;
+                }
+                if (Pipes[2] >= 0) {
+                    (void)close(Pipes[2]);
+                    Pipes[2] = -1;
+                }
+#endif /* defined(HAS_DUP2) */
+
+                /*
+                 * Read function requests, process them, and return replies.
+                 */
+                for (;;) {
+                    if (read(Pipes[0], (char *)&r_fn, sizeof(r_fn)) !=
+                            (int)sizeof(r_fn) ||
+                        read(Pipes[0], (char *)&r_al, sizeof(int)) !=
+                            (int)sizeof(int) ||
+                        r_al < 1 || r_al > (int)sizeof(r_arg) ||
+                        read(Pipes[0], r_arg, r_al) != r_al ||
+                        read(Pipes[0], (char *)&r_rbln, sizeof(r_rbln)) !=
+                            (int)sizeof(r_rbln) ||
+                        r_rbln < 1 || r_rbln > (int)sizeof(r.r_rbuf))
+                        break;
+                    zeromem(r.r_rbuf, r_rbln);
+                    rv = r_fn(r_arg, r.r_rbuf, r_rbln);
+                    en = errno;
+                    if (write(Pipes[3], (char *)&rv, sizeof(rv)) !=
+                            sizeof(rv) ||
+                        write(Pipes[3], (char *)&en, sizeof(en)) !=
+                            sizeof(en) ||
+                        write(Pipes[3], r.r_rbuf, r_rbln) != r_rbln)
+                        break;
+                }
+                (void)_exit(0);
+            }
+            /*
+             * Continue in the parent process to finish the setup.
+             */
+            if (Cpid < 0) {
+                (void)fprintf(stderr, "%s: can't fork: %s\n", Pn,
+                              strerror(errno));
+                Error(ctx);
+            }
+            (void)close(Pipes[0]);
+            (void)close(Pipes[3]);
+            Pipes[0] = Pipes[3] = -1;
+        }
+    }
+    if (!Fovhd) {
+        int len;
+
+        /*
+         * Send a function to the child and wait for the response.
+         */
+        len = strlen(fp) + 1;
+        (void)signal(SIGALRM, handleint);
+        (void)alarm(TmLimit);
+        if (write(Pipes[1], (char *)&fn, sizeof(fn)) != sizeof(fn) ||
+            write(Pipes[1], (char *)&len, sizeof(len)) != sizeof(len) ||
+            write(Pipes[1], fp, len) != len ||
+            write(Pipes[1], (char *)&rbln, sizeof(rbln)) != sizeof(rbln) ||
+            read(Pipes[2], (char *)&rv, sizeof(rv)) != sizeof(rv) ||
+            read(Pipes[2], (char *)&en, sizeof(en)) != sizeof(en) ||
+            read(Pipes[2], rbuf, rbln) != rbln) {
+            (void)alarm(0);
+            (void)signal(SIGALRM, SIG_DFL);
+            (void)childx(ctx);
+            errno = ECHILD;
+            return (-1);
+        }
+    } else {
+
+        /*
+         * Do the operation directly -- not in a child.
+         */
+        (void)signal(SIGALRM, handleint);
+        (void)alarm(TmLimit);
+        rv = fn(fp, rbuf, rbln);
+        en = errno;
+    }
+    /*
+     * Function completed, response collected -- complete the operation.
+     */
+    (void)alarm(0);
+    (void)signal(SIGALRM, SIG_DFL);
+    errno = en;
+    return (rv);
+}
+
+/*
+ * dolstat() - do an lstat() function
+ */
+
+static int dolstat(char *path, /* path */
+                   char *rbuf, /* response buffer */
+                   int rbln)   /* response buffer length */
+
+/* ARGSUSED */
+
+{
+    return (lstat(path, (struct stat *)rbuf));
+}
+
+/*
+ * doreadlink() -- do a readlink() function
+ */
+
+static int doreadlink(char *path, /* path */
+                      char *rbuf, /* response buffer */
+                      int rbln)   /* response buffer length */
+{
+    return (readlink(path, rbuf, rbln));
+}
+
+/*
+ * dostat() - do a stat() function
+ */
+
+static int dostat(char *path, /* path */
+                  char *rbuf, /* response buffer */
+                  int rbln)   /* response buffer length */
+
+/* ARGSUSED */
+
+{
+    return (stat(path, (struct stat *)rbuf));
+}
+
+#if defined(WILLDROPGID)
+/*
+ * dropgid() - drop setgid permission
+ */
+
+void dropgid(struct lsof_context *ctx) {
+    if (!Setuidroot && Setgid) {
+        if (setgid(Mygid) < 0) {
+            (void)fprintf(stderr, "%s: can't setgid(%d): %s\n", Pn, (int)Mygid,
+                          strerror(errno));
+            Error(ctx);
+        }
+        Setgid = 0;
+    }
+}
+#endif /* defined(WILLDROPGID) */
+
+/*
+ * enter_dev_ch() - enter device characters in file structure
+ */
+
+void enter_dev_ch(struct lsof_context *ctx, char *m) {
+    char *mp;
+
+    if (!m || *m == '\0')
+        return;
+    if (!(mp = mkstrcpy(m, (MALLOC_S *)NULL))) {
+        (void)fprintf(stderr, "%s: no more dev_ch space at PID %d: \n", Pn,
+                      Lp->pid);
+        safestrprt(m, stderr, 1);
+        Error(ctx);
+    }
+    if (Lf->dev_ch)
+        (void)free((FREE_P *)Lf->dev_ch);
+    Lf->dev_ch = mp;
+}
+
+/*
+ * enter_IPstate() -- enter a TCP or UDP state
+ */
+
+void enter_IPstate(struct lsof_context *ctx, char *ty, /* type -- TCP or UDP */
+                   char *nm, /* state name (may be NULL) */
+                   int nr)   /* state number */
+{
+
+#if defined(USE_LIB_PRINT_TCPTPI)
+    TcpNstates = nr;
+#else  /* !defined(USE_LIB_PRINT_TCPTPI) */
+
+    int al, i, j, oc, nn, ns, off, tx;
+    char *cp;
+    MALLOC_S len;
+    /*
+     * Check the type name and set the type index.
+     */
+    if (!ty) {
+        (void)fprintf(stderr, "%s: no type specified to enter_IPstate()\n", Pn);
+        Error(ctx);
+    }
+    if (!strcmp(ty, "TCP"))
+        tx = 0;
+    else if (!strcmp(ty, "UDP"))
+        tx = 1;
+    else {
+        (void)fprintf(stderr, "%s: unknown type for enter_IPstate: %s\n", Pn,
+                      ty);
+        Error(ctx);
+    }
+    /*
+     * If the name argument is NULL, reduce the allocated table to its minimum
+     * size.
+     */
+    if (!nm) {
+        if (tx) {
+            if (UdpSt) {
+                if (!UdpNstates) {
+                    (void)free((MALLOC_P *)UdpSt);
+                    UdpSt = (char **)NULL;
+                }
+                if (UdpNstates < UdpStAlloc) {
+                    len = (MALLOC_S)(UdpNstates * sizeof(char *));
+                    if (!(UdpSt = (char **)realloc((MALLOC_P *)UdpSt, len))) {
+                        (void)fprintf(stderr, "%s: can't reduce UdpSt[]\n", Pn);
+                        Error(ctx);
+                    }
+                }
+                UdpStAlloc = UdpNstates;
+            }
+        } else {
+            if (TcpSt) {
+                if (!TcpNstates) {
+                    (void)free((MALLOC_P *)TcpSt);
+                    TcpSt = (char **)NULL;
+                }
+                if (TcpNstates < TcpStAlloc) {
+                    len = (MALLOC_S)(TcpNstates * sizeof(char *));
+                    if (!(TcpSt = (char **)realloc((MALLOC_P *)TcpSt, len))) {
+                        (void)fprintf(stderr, "%s: can't reduce TcpSt[]\n", Pn);
+                        Error(ctx);
+                    }
+                }
+                TcpStAlloc = TcpNstates;
+            }
+        }
+        return;
+    }
+    /*
+     * Check the name and number.
+     */
+    if (strlen(nm) < 1) {
+        (void)fprintf(stderr, "%s: bad %s name (\"%s\"), number=%d\n", Pn, ty,
+                      nm, nr);
+        Error(ctx);
+    }
+    /*
+     * Make a copy of the name.
+     */
+    if (!(cp = mkstrcpy(nm, (MALLOC_S *)NULL))) {
+        (void)fprintf(stderr, "%s: enter_IPstate(): no %s space for %s\n", Pn,
+                      ty, nm);
+        Error(ctx);
+    }
+    /*
+     * Set the necessary offset for using nr as an index.  If it is
+     * a new offset, adjust previous entries.
+     */
+    if ((nr < 0) && ((off = -nr) > (tx ? UdpStOff : TcpStOff))) {
+        if (tx ? UdpSt : TcpSt) {
+
+            /*
+             * A new, larger offset (smaller negative state number) could mean
+             * a previously allocated state table must be enlarged and its
+             * previous entries moved.
+             */
+            oc = off - (tx ? UdpStOff : TcpStOff);
+            al = tx ? UdpStAlloc : TcpStAlloc;
+            ns = tx ? UdpNstates : TcpNstates;
+            if ((nn = ns + oc) >= al) {
+                while ((nn + 5) > al) {
+                    al += TCPUDPALLOC;
+                }
+                len = (MALLOC_S)(al * sizeof(char *));
+                if (tx) {
+                    if (!(UdpSt = (char **)realloc((MALLOC_P *)UdpSt, len)))
+                        goto no_IP_space;
+                    UdpStAlloc = al;
+                } else {
+                    if (!(TcpSt = (char **)realloc((MALLOC_P *)TcpSt, len)))
+                        goto no_IP_space;
+                    TcpStAlloc = al;
+                }
+                for (i = 0, j = oc; i < oc; i++, j++) {
+                    if (tx) {
+                        if (i < UdpNstates)
+                            UdpSt[j] = UdpSt[i];
+                        UdpSt[i] = (char *)NULL;
+                    } else {
+                        if (i < TcpNstates)
+                            TcpSt[j] = TcpSt[i];
+                        TcpSt[i] = (char *)NULL;
+                    }
+                }
+                if (tx)
+                    UdpNstates += oc;
+                else
+                    TcpNstates += oc;
+            }
+        }
+        if (tx)
+            UdpStOff = off;
+        else
+            TcpStOff = off;
+    }
+    /*
+     * Enter name as {Tc|Ud}pSt[nr + {Tc|Ud}pStOff].
+     *
+     * Allocate space, as required.
+     */
+    al = tx ? UdpStAlloc : TcpStAlloc;
+    off = tx ? UdpStOff : TcpStOff;
+    nn = nr + off + 1;
+    if (nn > al) {
+        i = tx ? UdpNstates : TcpNstates;
+        while ((nn + 5) > al) {
+            al += TCPUDPALLOC;
+        }
+        len = (MALLOC_S)(al * sizeof(char *));
+        if (tx) {
+            if (UdpSt)
+                UdpSt = (char **)realloc((MALLOC_P *)UdpSt, len);
+            else
+                UdpSt = (char **)malloc(len);
+            if (!UdpSt) {
+
+            no_IP_space:
+
+                (void)fprintf(stderr, "%s: no %s state space\n", Pn, ty);
+                Error(ctx);
+            }
+            UdpNstates = nn;
+            UdpStAlloc = al;
+        } else {
+            if (TcpSt)
+                TcpSt = (char **)realloc((MALLOC_P *)TcpSt, len);
+            else
+                TcpSt = (char **)malloc(len);
+            if (!TcpSt)
+                goto no_IP_space;
+            TcpNstates = nn;
+            TcpStAlloc = al;
+        }
+        while (i < al) {
+            if (tx)
+                UdpSt[i] = (char *)NULL;
+            else
+                TcpSt[i] = (char *)NULL;
+            i++;
+        }
+    } else {
+        if (tx) {
+            if (nn > UdpNstates)
+                UdpNstates = nn;
+        } else {
+            if (nn > TcpNstates)
+                TcpNstates = nn;
+        }
+    }
+    if (tx) {
+        if (UdpSt[nr + UdpStOff]) {
+
+        dup_IP_state:
+
+            (void)fprintf(
+                stderr, "%s: duplicate %s state %d (already %s): %s\n", Pn, ty,
+                nr, tx ? UdpSt[nr + UdpStOff] : TcpSt[nr + TcpStOff], nm);
+            Error(ctx);
+        }
+        UdpSt[nr + UdpStOff] = cp;
+    } else {
+        if (TcpSt[nr + TcpStOff])
+            goto dup_IP_state;
+        TcpSt[nr + TcpStOff] = cp;
+    }
+#endif /* defined(USE_LIB_PRINT_TCPTPI) */
+}
+
+/*
+ * enter_nm() - enter name in local file structure
+ */
+
+void enter_nm(struct lsof_context *ctx, char *m) {
+    char *mp;
+
+    if (!m || *m == '\0')
+        return;
+    if (!(mp = mkstrcpy(m, (MALLOC_S *)NULL))) {
+        (void)fprintf(stderr, "%s: no more nm space at PID %d for: ", Pn,
+                      Lp->pid);
+        safestrprt(m, stderr, 1);
+        Error(ctx);
+    }
+    if (Lf->nm)
+        (void)free((FREE_P *)Lf->nm);
+    Lf->nm = mp;
+}
+
+/*
+ * Exit() - do a clean exit()
+ */
+
+void Exit(struct lsof_context *ctx, enum ExitStatus xv) /* exit() value */
+{
+    (void)childx(ctx);
+
+#if defined(HASDCACHE)
+    if (DCrebuilt && !Fwarn)
+        (void)fprintf(stderr, "%s: WARNING: %s was updated.\n", Pn,
+                      DCpath[DCpathX]);
+#endif /* defined(HASDCACHE) */
+
+    exit(xv);
+}
+
+/*
+ * Error() - exit with an error status
+ */
+void Error(struct lsof_context *ctx) { Exit(ctx, LSOF_EXIT_ERROR); }
+
+#if defined(HASNLIST)
+/*
+ * get_Nl_value() - get Nl value for nickname
+ */
+
+int get_Nl_value(struct lsof_context *ctx, /* context */
+                 char *nn,                 /* nickname of requested entry */
+                 struct drive_Nl *d,       /* drive_Nl table that built Nl
+                                            * (if NULL, use Build_Nl) */
+                 KA_T *v)                  /* returned value (if NULL,
+                                            * return nothing) */
+{
+    int i;
+
+    if (!Nl || !Nll)
+        return (-1);
+    if (!d)
+        d = Build_Nl;
+    for (i = 0; d->nn; d++, i++) {
+        if (strcmp(d->nn, nn) == 0) {
+            if (v)
+                *v = (KA_T)Nl[i].n_value;
+            return (i);
+        }
+    }
+    return (-1);
+}
+#endif /* defined(HASNLIST) */
+
+/*
+ * handleint() - handle an interrupt
+ */
+
+#if defined(HASINTSIGNAL)
+static int
+#else
+static void
+#endif
+
+/* ARGSUSED */
+
+handleint(int sig) {
+    longjmp(Jmp_buf, 1);
+}
+
+/*
+ * hashbyname() - hash by name
+ */
+
+int hashbyname(char *nm, /* pointer to NUL-terminated name */
+               int mod)  /* hash modulus */
+{
+    int i, j;
+
+    for (i = j = 0; *nm; nm++) {
+        i ^= (int)*nm << j;
+        if (++j > 7)
+            j = 0;
+    }
+    return (((int)(i * 31415)) & (mod - 1));
+}
+
+/*
+ * is_nw_addr() - is this network address selected?
+ */
+
+int is_nw_addr(struct lsof_context *ctx, /* context */
+               unsigned char *ia,        /* Internet address */
+               int p,                    /* port */
+               int af)                   /* address family -- e.g., AF_INET,
+                                          * AF_INET6 */
+{
+    struct nwad *n;
+
+    if (!(n = Nwad))
+        return (0);
+    for (; n; n = n->next) {
+        if (n->proto) {
+            if (strcasecmp(n->proto, Lf->iproto) != 0)
+                continue;
+        }
+        if (af && n->af && af != n->af)
+            continue;
+
+#if defined(HASIPv6)
+        if (af == AF_INET6) {
+            if (n->a[15] || n->a[14] || n->a[13] || n->a[12] || n->a[11] ||
+                n->a[10] || n->a[9] || n->a[8] || n->a[7] || n->a[6] ||
+                n->a[5] || n->a[4] || n->a[3] || n->a[2] || n->a[1] ||
+                n->a[0]) {
+                if (ia[15] != n->a[15] || ia[14] != n->a[14] ||
+                    ia[13] != n->a[13] || ia[12] != n->a[12] ||
+                    ia[11] != n->a[11] || ia[10] != n->a[10] ||
+                    ia[9] != n->a[9] || ia[8] != n->a[8] || ia[7] != n->a[7] ||
+                    ia[6] != n->a[6] || ia[5] != n->a[5] || ia[4] != n->a[4] ||
+                    ia[3] != n->a[3] || ia[2] != n->a[2] || ia[1] != n->a[1] ||
+                    ia[0] != n->a[0])
+                    continue;
+            }
+        } else if (af == AF_INET)
+#endif /* defined(HASIPv6) */
+
+        {
+            if (n->a[3] || n->a[2] || n->a[1] || n->a[0]) {
+                if (ia[3] != n->a[3] || ia[2] != n->a[2] || ia[1] != n->a[1] ||
+                    ia[0] != n->a[0])
+                    continue;
+            }
+        }
+
+#if defined(HASIPv6)
+        else
+            continue;
+#endif /* defined(HASIPv6) */
+
+        if (n->sport == -1 || (p >= n->sport && p <= n->eport)) {
+            n->f = 1;
+            return (1);
+        }
+    }
+    return (0);
+}
+
+/*
+ * mkstrcpy() - make a string copy in malloc()'d space
+ *
+ * return: copy pointer
+ *	   copy length (optional)
+ */
+
+char *mkstrcpy(char *src,     /* source */
+               MALLOC_S *rlp) /* returned length pointer (optional)
+                               * The returned length is an strlen()
+                               * equivalent */
+{
+    MALLOC_S len;
+    char *ns;
+
+    len = (MALLOC_S)(src ? strlen(src) : 0);
+    ns = (char *)malloc(len + 1);
+    if (ns) {
+        if (src)
+            (void)snpf(ns, len + 1, "%s", src);
+        else
+            *ns = '\0';
+    }
+    if (rlp)
+        *rlp = len;
+    return (ns);
+}
+
+/*
+ * mkstrcat() - make a catenated copy of up to three strings under optional
+ *		string-by-string count control
+ *
+ * return: copy pointer
+ *	   copy string length (optional)
+ */
+
+char *mkstrcat(char *s1,      /* source string 1 */
+               int l1,        /* length of string 1 (-1 if none) */
+               char *s2,      /* source string 2 */
+               int l2,        /* length of string 2 (-1 if none) */
+               char *s3,      /* source string 3 (optional) */
+               int l3,        /* length of string 3 (-1 if none) */
+               MALLOC_S *clp) /* pointer to return of copy length
+                               * (optional) */
+{
+    MALLOC_S cl, len1, len2, len3;
+    char *cp;
+
+    if (s1)
+        len1 = (MALLOC_S)((l1 >= 0) ? l1 : strlen(s1));
+    else
+        len1 = (MALLOC_S)0;
+    if (s2)
+        len2 = (MALLOC_S)((l2 >= 0) ? l2 : strlen(s2));
+    else
+        len2 = (MALLOC_S)0;
+    if (s3)
+        len3 = (MALLOC_S)((l3 >= 0) ? l3 : strlen(s3));
+    else
+        len3 = (MALLOC_S)0;
+    cl = len1 + len2 + len3;
+    if ((cp = (char *)malloc(cl + 1))) {
+        char *tp = cp;
+
+        if (s1 && len1) {
+            (void)strncpy(tp, s1, len1);
+            tp += len1;
+        }
+        if (s2 && len2) {
+            (void)strncpy(tp, s2, len2);
+            tp += len2;
+        }
+        if (s3 && len3) {
+            (void)strncpy(tp, s3, len3);
+            tp += len3;
+        }
+        *tp = '\0';
+    }
+    if (clp)
+        *clp = cl;
+    return (cp);
+}
+
+/*
+ * is_readable() -- is file readable
+ */
+
+int is_readable(struct lsof_context *ctx, /* context */
+                char *path,               /* file path */
+                int msg)                  /* issue warning message if 1 */
+{
+    if (access(path, R_OK) < 0) {
+        if (!Fwarn && msg == 1)
+            (void)fprintf(stderr, ACCESSERRFMT, Pn, path, strerror(errno));
+        return (0);
+    }
+    return (1);
+}
+
+/*
+ * lstatsafely() - lstat path safely (i. e., with timeout)
+ */
+
+int lstatsafely(struct lsof_context *ctx, char *path, /* file path */
+                struct stat *buf)                     /* stat buffer address */
+{
+    if (Fblock) {
+        if (!Fwarn)
+            (void)fprintf(stderr, "%s: avoiding stat(%s): -b was specified.\n",
+                          Pn, path);
+        errno = EWOULDBLOCK;
+        return (1);
+    }
+    return (doinchild(ctx, dolstat, path, (char *)buf, sizeof(struct stat)));
+}
+
+/*
+ * Readlink() - read and interpret file system symbolic links
+ */
+
+char *Readlink(struct lsof_context *ctx,
+               char *arg) /* argument to be interpreted */
+{
+    char abuf[MAXPATHLEN + 1];
+    int alen;
+    char *ap;
+    char *argp1, *argp2;
+    int i, len, llen, slen;
+    char lbuf[MAXPATHLEN + 1];
+    static char *op = (char *)NULL;
+    static int ss = 0;
+    char *s1;
+    static char **stk = (char **)NULL;
+    static int sx = 0;
+    char tbuf[MAXPATHLEN + 1];
+    /*
+     * See if avoiding kernel blocks.
+     */
+    if (Fblock) {
+        if (!Fwarn) {
+            (void)fprintf(stderr, "%s: avoiding readlink(", Pn);
+            safestrprt(arg, stderr, 0);
+            (void)fprintf(stderr, "): -b was specified.\n");
+        }
+        op = (char *)NULL;
+        return mkstrcpy(arg, NULL);
+    }
+    /*
+     * Save the original path.
+     */
+    if (!op)
+        op = arg;
+    /*
+     * Evaluate each component of the argument for a symbolic link.
+     */
+    for (alen = 0, ap = abuf, argp1 = argp2 = arg; *argp2; argp1 = argp2) {
+        for (argp2 = argp1 + 1; *argp2 && *argp2 != '/'; argp2++)
+            ;
+        if ((len = argp2 - arg) >= (int)sizeof(tbuf)) {
+
+        path_too_long:
+            if (!Fwarn) {
+                (void)fprintf(stderr, "%s: readlink() path too long: ", Pn);
+                safestrprt(op ? op : arg, stderr, 1);
+            }
+            op = (char *)NULL;
+            return ((char *)NULL);
+        }
+        (void)strncpy(tbuf, arg, len);
+        tbuf[len] = '\0';
+        /*
+         * Dereference a symbolic link.
+         */
+        if ((llen = doinchild(ctx, doreadlink, tbuf, lbuf, sizeof(lbuf) - 1)) >=
+            0) {
+
+            /*
+             * If the link is a new absolute path, replace
+             * the previous assembly with it.
+             */
+            if (lbuf[0] == '/') {
+                (void)strncpy(abuf, lbuf, llen);
+                ap = &abuf[llen];
+                *ap = '\0';
+                alen = llen;
+                continue;
+            }
+            lbuf[llen] = '\0';
+            s1 = lbuf;
+        } else {
+            llen = argp2 - argp1;
+            s1 = argp1;
+        }
+        /*
+         * Make sure two components are separated by a `/'.
+         *
+         * If the first component is not a link, don't force
+         * a leading '/'.
+         *
+         * If the first component is a link and the source of
+         * the link has a leading '/', force a leading '/'.
+         */
+        if (*s1 == '/')
+            slen = 1;
+        else {
+            if (alen > 0) {
+
+                /*
+                 * This is not the first component.
+                 */
+                if (abuf[alen - 1] == '/')
+                    slen = 1;
+                else
+                    slen = 2;
+            } else {
+
+                /*
+                 * This is the first component.
+                 */
+                if (s1 == lbuf && tbuf[0] == '/')
+                    slen = 2;
+                else
+                    slen = 1;
+            }
+        }
+        /*
+         * Add to the path assembly.
+         */
+        if ((alen + llen + slen) >= (int)sizeof(abuf))
+            goto path_too_long;
+        if (slen == 2)
+            *ap++ = '/';
+        (void)strncpy(ap, s1, llen);
+        ap += llen;
+        *ap = '\0';
+        alen += (llen + slen - 1);
+    }
+    /*
+     * If the assembled path and argument are the same, free all but the
+     * last string in the stack, and return the argument.
+     */
+    if (strcmp(arg, abuf) == 0) {
+        for (i = 0; i < sx; i++) {
+            if (i < (sx - 1))
+                (void)free((FREE_P *)stk[i]);
+            stk[i] = (char *)NULL;
+        }
+        sx = 0;
+        op = (char *)NULL;
+        return mkstrcpy(arg, NULL);
+    }
+    /*
+     * If the assembled path and argument are different, add it to the
+     * string stack, then Readlink() it.
+     */
+    if (!(s1 = mkstrcpy(abuf, (MALLOC_S *)NULL))) {
+
+    no_readlink_space:
+
+        (void)fprintf(stderr, "%s: no Readlink string space for ", Pn);
+        safestrprt(abuf, stderr, 1);
+        Error(ctx);
+    }
+    if (sx >= MAXSYMLINKS) {
+
+        /*
+         * If there are too many symbolic links, report an error, clear
+         * the stack, and return no path.
+         */
+        if (!Fwarn) {
+            (void)fprintf(
+                stderr,
+                "%s: too many (> %d) symbolic links in readlink() path: ", Pn,
+                MAXSYMLINKS);
+            safestrprt(op ? op : arg, stderr, 1);
+        }
+        for (i = 0; i < sx; i++) {
+            (void)free((FREE_P *)stk[i]);
+            stk[i] = (char *)NULL;
+        }
+        (void)free((FREE_P *)stk);
+        (void)free((FREE_P *)s1);
+        stk = (char **)NULL;
+        ss = sx = 0;
+        s1 = (char *)NULL;
+        op = (char *)NULL;
+        return ((char *)NULL);
+    }
+    if (++sx > ss) {
+        if (!stk)
+            stk = (char **)malloc((MALLOC_S)(sizeof(char *) * sx));
+        else
+            stk = (char **)realloc((MALLOC_P *)stk,
+                                   (MALLOC_S)(sizeof(char *) * sx));
+        if (!stk)
+            goto no_readlink_space;
+        ss = sx;
+    }
+    stk[sx - 1] = s1;
+    return (Readlink(ctx, s1));
+}
+
+#if defined(HASSTREAMS)
+/*
+ * readstdata() - read stream's stdata structure
+ */
+
+int readstdata(struct lsof_context *ctx, /* context */
+               KA_T addr,                /* stdata address in kernel*/
+               struct stdata *buf)       /* buffer address */
+{
+    if (!addr || kread(ctx, addr, (char *)buf, sizeof(struct stdata))) {
+        (void)snpf(Namech, Namechl, "no stream data in %s",
+                   print_kptr(addr, (char *)NULL, 0));
+        return (1);
+    }
+    return (0);
+}
+
+/*
+ * readsthead() - read stream head
+ */
+
+int readsthead(struct lsof_context *ctx, /* context */
+               KA_T addr,                /* starting queue pointer in kernel */
+               struct queue *buf)        /* buffer for queue head */
+{
+    KA_T qp;
+
+    if (!addr) {
+        (void)snpf(Namech, Namechl, "no stream queue head");
+        return (1);
+    }
+    for (qp = addr; qp; qp = (KA_T)buf->q_next) {
+        if (kread(ctx, qp, (char *)buf, sizeof(struct queue))) {
+            (void)snpf(Namech, Namechl, "bad stream queue link at %s",
+                       print_kptr(qp, (char *)NULL, 0));
+            return (1);
+        }
+    }
+    return (0);
+}
+
+/*
+ * readstidnm() - read stream module ID name
+ */
+
+int readstidnm(struct lsof_context *ctx, /* context */
+               KA_T addr,                /* module ID name address in kernel */
+               char *buf,                /* receiving buffer address */
+               READLEN_T len)            /* buffer length */
+{
+    if (!addr || kread(ctx, addr, buf, len)) {
+        (void)snpf(Namech, Namechl, "can't read module ID name from %s",
+                   print_kptr(addr, (char *)NULL, 0));
+        return (1);
+    }
+    return (0);
+}
+
+/*
+ * readstmin() - read stream's module info
+ */
+
+int readstmin(struct lsof_context *ctx, /* context */
+              KA_T addr,                /* module info address in kernel */
+              struct module_info *buf)  /* receiving buffer address */
+{
+    if (!addr || kread(ctx, addr, (char *)buf, sizeof(struct module_info))) {
+        (void)snpf(Namech, Namechl, "can't read module info from %s",
+                   print_kptr(addr, (char *)NULL, 0));
+        return (1);
+    }
+    return (0);
+}
+
+/*
+ * readstqinit() - read stream's queue information structure
+ */
+
+int readstqinit(struct lsof_context *ctx, /* context */
+                KA_T addr,                /* queue info address in kernel */
+                struct qinit *buf)        /* receiving buffer address */
+{
+    if (!addr || kread(ctx, addr, (char *)buf, sizeof(struct qinit))) {
+        (void)snpf(Namech, Namechl, "can't read queue info from %s",
+                   print_kptr(addr, (char *)NULL, 0));
+        return (1);
+    }
+    return (0);
+}
+#endif /* HASSTREAMS */
+
+/*
+ * safepup() - safely print an unprintable character -- i.e., print it in a
+ *	       printable form
+ *
+ * return: char * to printable equivalent
+ *	   cl = strlen(printable equivalent)
+ */
+
+char *safepup(unsigned int c, /* unprintable (i.e., !isprint())
+                               * character  and '\\' */
+              int *cl)        /* returned printable strlen -- NULL if
+                               * no return needed */
+{
+    int len;
+    char *rp;
+    static char up[8];
+
+    if (c < 0x20) {
+        switch (c) {
+        case '\b':
+            rp = "\\b";
+            break;
+        case '\f':
+            rp = "\\f";
+            break;
+        case '\n':
+            rp = "\\n";
+            break;
+        case '\r':
+            rp = "\\r";
+            break;
+        case '\t':
+            rp = "\\t";
+            break;
+        default:
+            (void)snpf(up, sizeof(up), "^%c", c + 0x40);
+            rp = up;
+        }
+        len = 2;
+    } 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;
+        len = 4;
+    }
+    if (cl)
+        *cl = len;
+    return (rp);
+}
+
+/*
+ * safestrlen() - calculate a "safe" string length -- i.e., compute space for
+ *		  non-printable characters when printed in a printable form
+ */
+
+int safestrlen(char *sp,  /* string pointer */
+               int flags) /* flags:
+                           *   bit 0: 0 (0) = no NL
+                           *	    1 (1) = add trailing NL
+                           *	 1: 0 (0) = ' ' printable
+                           *	    1 (2) = ' ' not printable
+                           */
+{
+    char c;
+    int len = 0;
+
+    c = (flags & 2) ? ' ' : '\0';
+    if (sp) {
+        for (; *sp; sp++) {
+            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 */
+            } else
+                len++;
+        }
+    }
+    return (len);
+}
+
+/*
+ * safestrprt() - print a string "safely" to the indicated stream -- i.e.,
+ *		  print unprintable characters in a printable form
+ */
+void safestrprt(char *sp,  /* string to print pointer pointer */
+                FILE *fs,  /* destination stream -- e.g., stderr
+                            * or stdout */
+                int flags) /* flags:
+                            *   bit 0: 0 (0) = no NL
+                            *	    1 (1) = add trailing NL
+                            *	 1: 0 (0) = ' ' printable
+                            *	    1 (2) = ' ' not printable
+                            *	 2: 0 (0) = print string as is
+                            *	    1 (4) = surround string
+                            *		    with '"'
+                            *	 4: 0 (0) = print ending '\n'
+                            *	    1 (8) = don't print ending
+                            *		    '\n'
+                            */
+{
+    char c;
+    int lnc, lnt, sl;
+
+#if defined(HASWIDECHAR)
+    wchar_t w;
+    int wcmx = MB_CUR_MAX;
+#else  /* !defined(HASWIDECHAR) */
+    static int wcmx = 1;
+#endif /* defined(HASWIDECHAR) */
+
+    c = (flags & 2) ? ' ' : '\0';
+    if (flags & 4)
+        putc('"', fs);
+    if (sp) {
+        for (sl = strlen(sp); *sp; sl -= lnc, sp += lnc) {
+
+#if defined(HASWIDECHAR)
+            if (wcmx > 1) {
+                lnc = mblen(sp, sl);
+                if (lnc > 1) {
+                    if ((mbtowc(&w, sp, sl) == lnc) && iswprint(w)) {
+                        for (lnt = 0; lnt < lnc; lnt++) {
+                            putc((int)*(sp + lnt), fs);
+                        }
+                    } else {
+                        for (lnt = 0; lnt < lnc; lnt++) {
+                            fputs(
+                                safepup((unsigned int)*(sp + lnt), (int *)NULL),
+                                fs);
+                        }
+                    }
+                    continue;
+                } else
+                    lnc = 1;
+            } else
+                lnc = 1;
+#else  /* !defined(HASWIDECHAR) */
+            lnc = 1;
+#endif /* defined(HASWIDECHAR) */
+
+            if ((*sp != '\\') && isprint((unsigned char)*sp) && *sp != c)
+                putc((int)(*sp & 0xff), fs);
+            else {
+                if ((flags & 8) && (*sp == '\n') && !*(sp + 1))
+                    break;
+                fputs(safepup((unsigned int)*sp, (int *)NULL), fs);
+            }
+        }
+    }
+    if (flags & 4)
+        putc('"', fs);
+    if (flags & 1)
+        putc('\n', fs);
+}
+
+/*
+ * safestrprtn() - print a specified number of characters from a string
+ *		   "safely" to the indicated stream
+ */
+
+void safestrprtn(char *sp,  /* string to print pointer pointer */
+                 int len,   /* safe number of characters to
+                             * print */
+                 FILE *fs,  /* destination stream -- e.g., stderr
+                             * or stdout */
+                 int flags) /* flags:
+                             *   bit 0: 0 (0) = no NL
+                             *	    1 (1) = add trailing NL
+                             *	 1: 0 (0) = ' ' printable
+                             *	    1 (2) = ' ' not printable
+                             *	 2: 0 (0) = print string as is
+                             *	    1 (4) = surround string
+                             *		    with '"'
+                             *	 4: 0 (0) = print ending '\n'
+                             *	    1 (8) = don't print ending
+                             *		    '\n'
+                             */
+{
+    char c, *up;
+    int cl, i;
+
+    if (flags & 4)
+        putc('"', fs);
+    if (sp) {
+        c = (flags & 2) ? ' ' : '\0';
+        for (i = 0; i < len && *sp; sp++) {
+            if ((*sp != '\\') && isprint((unsigned char)*sp) && *sp != c) {
+                putc((int)(*sp & 0xff), fs);
+                i++;
+            } else {
+                if ((flags & 8) && (*sp == '\n') && !*(sp + 1))
+                    break;
+                up = safepup((unsigned int)*sp, &cl);
+                if ((i + cl) > len)
+                    break;
+                fputs(up, fs);
+                i += cl;
+            }
+        }
+    } else
+        i = 0;
+    for (; i < len; i++)
+        putc(' ', fs);
+    if (flags & 4)
+        putc('"', fs);
+    if (flags & 1)
+        putc('\n', fs);
+}
+
+/*
+ * statsafely() - stat path safely (i. e., with timeout)
+ */
+
+int statsafely(struct lsof_context *ctx, char *path, /* file path */
+               struct stat *buf)                     /* stat buffer address */
+{
+    if (Fblock) {
+        if (!Fwarn)
+            (void)fprintf(stderr, "%s: avoiding stat(%s): -b was specified.\n",
+                          Pn, path);
+        errno = EWOULDBLOCK;
+        return (1);
+    }
+    return (doinchild(ctx, dostat, path, (char *)buf, sizeof(struct stat)));
+}
+
+/*
+ * stkdir() - stack directory name
+ */
+
+void stkdir(struct lsof_context *ctx, char *p) /* directory path */
+{
+    MALLOC_S len;
+    /*
+     * Provide adequate space for directory stack pointers.
+     */
+    if (Dstkx >= Dstkn) {
+        Dstkn += 128;
+        len = (MALLOC_S)(Dstkn * sizeof(char *));
+        if (!Dstk)
+            Dstk = (char **)malloc(len);
+        else
+            Dstk = (char **)realloc((MALLOC_P *)Dstk, len);
+        if (!Dstk) {
+            (void)fprintf(stderr, "%s: no space for directory stack at: ", Pn);
+            safestrprt(p, stderr, 1);
+            Error(ctx);
+        }
+    }
+    /*
+     * Allocate space for the name, copy it there and put its pointer on the
+     * stack.
+     */
+    if (!(Dstk[Dstkx] = mkstrcpy(p, (MALLOC_S *)NULL))) {
+        (void)fprintf(stderr, "%s: no space for: ", Pn);
+        safestrprt(p, stderr, 1);
+        Error(ctx);
+    }
+    Dstkx++;
+}
+
+/*
+ * x2dev() - convert hexadecimal ASCII string to device number
+ */
+
+char *x2dev(char *s,  /* ASCII string */
+            dev_t *d) /* device receptacle */
+{
+    char *cp, *cp1;
+    int n;
+    dev_t r;
+
+    /*
+     * Skip an optional leading 0x.  Count the number of hex digits up to the
+     * end of the string, or to a space, or to a comma.  Return an error if an
+     * unknown character is encountered.  If the count is larger than (2 *
+     * sizeof(dev_t))
+     * -- e.g., because of sign extension -- ignore excess leading hex 0xf
+     * digits, but return an error if an excess leading digit isn't 0xf.
+     */
+    if (strncasecmp(s, "0x", 2) == 0)
+        s += 2;
+    for (cp = s, n = 0; *cp; cp++, n++) {
+        if (isdigit((unsigned char)*cp))
+            continue;
+        if ((unsigned char)*cp >= 'a' && (unsigned char)*cp <= 'f')
+            continue;
+        if ((unsigned char)*cp >= 'A' && (unsigned char)*cp <= 'F')
+            continue;
+        if (*cp == ' ' || *cp == ',')
+            break;
+        return ((char *)NULL);
+    }
+    if (!n)
+        return ((char *)NULL);
+    if (n > (2 * (int)sizeof(dev_t))) {
+        cp1 = s;
+        s += (n - (2 * sizeof(dev_t)));
+        while (cp1 < s) {
+            if (*cp1 != 'f' && *cp1 != 'F')
+                return ((char *)NULL);
+            cp1++;
+        }
+    }
+    /*
+     * Assemble the validated hex digits of the device number, starting at a
+     * point in the string relevant to sizeof(dev_t).
+     */
+    for (r = 0; s < cp; s++) {
+        r = r << 4;
+        if (isdigit((unsigned char)*s))
+            r |= (unsigned char)(*s - '0') & 0xf;
+        else {
+            if (isupper((unsigned char)*s))
+                r |= ((unsigned char)(*s - 'A') + 10) & 0xf;
+            else
+                r |= ((unsigned char)(*s - 'a') + 10) & 0xf;
+        }
+    }
+    *d = r;
+    return (s);
+}
diff --git a/lib/node.c b/lib/node.c
new file mode 100644
index 0000000..4da6c67
--- /dev/null
+++ b/lib/node.c
@@ -0,0 +1,225 @@
+/*
+ * node.c - common 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.
+ */
+
+#include "common.h"
+
+/*
+ * print_kptr() - print kernel pointer
+ */
+
+char *print_kptr(KA_T kp,     /* kernel pointer address */
+                 char *buf,   /* optional destination buffer */
+                 size_t bufl) /* size of buf[] */
+{
+    static char dbuf[32];
+
+    (void)snpf(buf ? buf : dbuf, buf ? bufl : sizeof(dbuf), KA_T_FMT_X, kp);
+    return (buf ? buf : dbuf);
+}
+
+#if defined(HASCDRNODE)
+/*
+ * readcdrnode() - read CD-ROM node
+ */
+
+int readcdrnode(struct lsof_context *ctx, /* context */
+                KA_T ca,                  /* cdrnode kernel address */
+                struct cdrnode *c)        /* cdrnode buffer */
+{
+    if (kread(ctx, (KA_T)ca, (char *)c, sizeof(struct cdrnode))) {
+        (void)snpf(Namech, Namechl, "can't read cdrnode at %s",
+                   print_kptr(ca, (char *)NULL, 0));
+        return (1);
+    }
+    return (0);
+}
+#endif /* defined(HASCDRNODE) */
+
+#if defined(HASFIFONODE)
+/*
+ * readfifonode() - read fifonode
+ */
+
+int readfifonode(struct lsof_context *ctx, /* context */
+                 KA_T fa,                  /* fifonode kernel address */
+                 struct fifonode *f)       /* fifonode buffer */
+{
+    if (kread(ctx, (KA_T)fa, (char *)f, sizeof(struct fifonode))) {
+        (void)snpf(Namech, Namechl, "can't read fifonode at %s",
+                   print_kptr(fa, (char *)NULL, 0));
+        return (1);
+    }
+    return (0);
+}
+#endif /* defined(HASFIFONODE) */
+
+#if defined(HASGNODE)
+/*
+ * readgnode() - read gnode
+ */
+
+int readgnode(struct lsof_context *ctx, /* context */
+              KA_T ga,                  /* gnode kernel address */
+              struct gnode *g)          /* gnode buffer */
+{
+    if (kread(ctx, (KA_T)ga, (char *)g, sizeof(struct gnode))) {
+        (void)snpf(Namech, Namechl, "can't read gnode at %s",
+                   print_kptr(ga, (char *)NULL, 0));
+        return (1);
+    }
+    return (0);
+}
+#endif /* defined(HASGNODE) */
+
+#if defined(HASHSNODE)
+/*
+ * readhsnode() - read High Sierra file system node
+ */
+
+int readhsnode(struct lsof_context *ctx, /* context */
+               KA_T ha,                  /* hsnode kernel address */
+               struct hsnode *h)         /* hsnode buffer */
+{
+    if (kread(ctx, (KA_T)ha, (char *)h, sizeof(struct hsnode))) {
+        (void)snpf(Namech, Namechl, "can't read hsnode at %s",
+                   print_kptr(ha, (char *)NULL, 0));
+        return (1);
+    }
+    return (0);
+}
+#endif /* defined(HASHSNODE) */
+
+#if defined(HASINODE)
+/*
+ * readinode() - read inode
+ */
+
+int readinode(struct lsof_context *ctx, /* context */
+              KA_T ia,                  /* inode kernel address */
+              struct inode *i)          /* inode buffer */
+{
+    if (kread(ctx, (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);
+}
+#endif /* defined(HASINODE) */
+
+#if defined(HASPIPENODE)
+/*
+ * readpipenode() - read pipe node
+ */
+
+int readpipenode(struct lsof_context *ctx, /* context */
+                 KA_T pa,                  /* pipe node kernel address */
+                 struct pipenode *p)       /* pipe node buffer */
+{
+    if (kread(ctx, (KA_T)pa, (char *)p, sizeof(struct pipenode))) {
+        (void)snpf(Namech, Namechl, "can't read pipenode at %s",
+                   print_kptr(pa, (char *)NULL, 0));
+        return (1);
+    }
+    return (0);
+}
+#endif /* defined(HASPIPENODE) */
+
+#if defined(HASRNODE)
+/*
+ * readrnode() - read rnode
+ */
+
+int readrnode(struct lsof_context *ctx, /* context */
+              KA_T ra,                  /* rnode kernel space address */
+              struct rnode *r)          /* rnode buffer pointer */
+{
+    if (kread(ctx, (KA_T)ra, (char *)r, sizeof(struct rnode))) {
+        (void)snpf(Namech, Namechl, "can't read rnode at %s",
+                   print_kptr(ra, (char *)NULL, 0));
+        return (1);
+    }
+    return (0);
+}
+#endif /* defined(HASRNODE) */
+
+#if defined(HASSNODE)
+/*
+ * readsnode() - read snode
+ */
+
+int readsnode(struct lsof_context *ctx, /* context */
+              KA_T sa,                  /* snode kernel space address */
+              struct snode *s)          /* snode buffer pointer */
+{
+    if (kread(ctx, (KA_T)sa, (char *)s, sizeof(struct snode))) {
+        (void)snpf(Namech, Namechl, "can't read snode at %s",
+                   print_kptr(sa, (char *)NULL, 0));
+        return (1);
+    }
+    return (0);
+}
+#endif /* defined(HASSNODE) */
+
+#if defined(HASTMPNODE)
+/*
+ * readtnode() - read tmpnode
+ */
+
+int readtnode(struct lsof_context *ctx, /* context */
+              KA_T ta,                  /* tmpnode kernel space address */
+              struct tmpnode *t)        /* tmpnode buffer pointer */
+{
+    if (kread(ctx, (KA_T)ta, (char *)t, sizeof(struct tmpnode))) {
+        (void)snpf(Namech, Namechl, "can't read tmpnode at %s",
+                   print_kptr(ta, (char *)NULL, 0));
+        return (1);
+    }
+    return (0);
+}
+#endif /* defined(HASTMPNODE) */
+
+#if defined(HASVNODE)
+/*
+ * readvnode() - read vnode
+ */
+
+int readvnode(struct lsof_context *ctx, /* context */
+              KA_T va,                  /* vnode kernel space address */
+              struct vnode *v)          /* vnode buffer pointer */
+{
+    if (kread(ctx, (KA_T)va, (char *)v, sizeof(struct vnode))) {
+        (void)snpf(Namech, Namechl, "can't read vnode at %s",
+                   print_kptr(va, (char *)NULL, 0));
+        return (1);
+    }
+    return (0);
+}
+#endif /* defined(HASVNODE) */
diff --git a/lib/pdvn.c b/lib/pdvn.c
index d52fd2e..d553f67 100644
--- a/lib/pdvn.c
+++ b/lib/pdvn.c
@@ -2,7 +2,6 @@
  * pdvn.c -- print device name functions for lsof library
  */
 
-
 /*
  * Copyright 1997 Purdue Research Foundation, West Lafayette, Indiana
  * 47907.  All rights reserved.
@@ -29,22 +28,15 @@
  * 4. This notice may not be removed or altered.
  */
 
+#include "common.h"
+#include "machine.h"
 
-#include "../machine.h"
-
-#if	defined(USE_LIB_PRINTDEVNAME)
-
-# if	!defined(lint)
-static char copyright[] =
-"@(#) Copyright 1997 Purdue Research Foundation.\nAll rights reserved.\n";
-# endif	/* !defined(lint) */
-
-#include "../lsof.h"
-
-#else	/* !defined(USE_LIB_PRINTDEVNAME) */
-char pdvn_d1[] = "d"; char *pdvn_d2 = pdvn_d1;
-#endif	/* defined(USE_LIB_PRINTDEVNAME) */
+#if defined(USE_LIB_PRINTDEVNAME)
 
+#else  /* !defined(USE_LIB_PRINTDEVNAME) */
+char pdvn_d1[] = "d";
+char *pdvn_d2 = pdvn_d1;
+#endif /* defined(USE_LIB_PRINTDEVNAME) */
 
 /*
  * To use this source file:
@@ -57,125 +49,121 @@ char pdvn_d1[] = "d"; char *pdvn_d2 = pdvn_d1;
  * 3. Define HASBLDKDEV to enable block device processing.
  */
 
-
 /*
  * Local definitions
  */
 
-#define	LIKE_BLK_SPEC	"like block special"
-#define	LIKE_CHR_SPEC	"like character special"
+#define LIKE_BLK_SPEC "like block special"
+#define LIKE_CHR_SPEC "like character special"
 
-
-# if	defined(USE_LIB_PRINTDEVNAME)
+#if defined(USE_LIB_PRINTDEVNAME)
 /*
  * 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 */
+int printdevname(struct lsof_context *ctx, dev_t *dev, /* device */
+                 dev_t *rdev,                          /* raw device */
+                 int f,   /* 1 = print trailing '\n' */
+                 int nty) /* node type: N_BLK or N_CHR */
 {
 
-#  if	defined(HAS_STD_CLONE)
-	struct clone *c;
-#  endif	/* defined(HAS_STD_CLONE) */
+#    if defined(HAS_STD_CLONE)
+    struct clone *c;
+#    endif /* defined(HAS_STD_CLONE) */
 
-	struct l_dev *dp;
-	int r = 1;
+    struct l_dev *dp;
+    int r = 1;
 
-#  if	defined(HASDCACHE)
+#    if defined(HASDCACHE)
 
 printdevname_again:
 
-#  endif	/* defined(HASDCACHE) */
-
-# if	defined(HAS_STD_CLONE)
-/*
- * Search for clone if this is a character device on the same device as
- * /dev (or /devices).
- */
-	if ((nty == N_CHR) && Lf->is_stream && Clone && (*dev == DevDev)) {
-	    r = 0;	/* Don't let lkupdev() rebuild the device cache,
-			 * because when it has been rebuilt we want to
-			 * search again for clones. */
-	    readdev(0);
-	    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 printdevname_again;
-#  endif	/* defined(HASDCACHE) */
-
-		    safestrprt(Devtp[c->dx].name, stdout, f);
-		    return(1);
-		}
-	    }
-	}
-# endif	/* defined(HAS_STD_CLONE) */
-
-/*
- * Search appropriate device table for a full match.
- */
-
-# if	defined(HASBLKDEV)
-	if (nty == N_BLK)
-	    dp = lkupbdev(dev, rdev, 1, r);
-	else
-# endif	/* defined(HASBLKDEV) */
-
-	dp = lkupdev(dev, rdev, 1, r);
-	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, r);
-	else
-# endif	/* defined(HASBLKDEV) */
-
-	dp = lkupdev(&DevDev, rdev, 0, r);
-	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);
-		Error();
-	    }
-	    (void) snpf(cp, len + 1, "(%s %s)", ttl, dp->name);
-	    (void) add_nma(cp, len);
-	    (void) free((MALLOC_P *)cp);
-	    return(0);
-	}
-
-# if	defined(HASDCACHE)
-/*
- * We haven't found a match.
- *
- * If rebuilding the device cache was suppressed and the device cache is
- * "unsafe," rebuild it.
- */
-	if (!r && DCunsafe) {
-	    (void) rereaddev();
-	    goto printdevname_again;
-	}
-# endif	/* defined(HASDCACHE) */
-
-	return(0);
+#    endif /* defined(HASDCACHE) */
+
+#    if defined(HAS_STD_CLONE)
+    /*
+     * Search for clone if this is a character device on the same device as
+     * /dev (or /devices).
+     */
+    if ((nty == N_CHR) && Lf->is_stream && Clone && (*dev == DevDev)) {
+        r = 0; /* Don't let lkupdev() rebuild the device cache,
+                * because when it has been rebuilt we want to
+                * search again for clones. */
+        readdev(0);
+        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 printdevname_again;
+#        endif /* defined(HASDCACHE) */
+
+                safestrprt(Devtp[c->dx].name, stdout, f);
+                return (1);
+            }
+        }
+    }
+#    endif /* defined(HAS_STD_CLONE) */
+
+    /*
+     * Search appropriate device table for a full match.
+     */
+
+#    if defined(HASBLKDEV)
+    if (nty == N_BLK)
+        dp = lkupbdev(ctx, dev, rdev, 1, r);
+    else
+#    endif /* defined(HASBLKDEV) */
+
+        dp = lkupdev(ctx, dev, rdev, 1, r);
+    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(ctx, &DevDev, rdev, 0, r);
+    else
+#    endif /* defined(HASBLKDEV) */
+
+        dp = lkupdev(ctx, &DevDev, rdev, 0, r);
+    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);
+            Error(ctx);
+        }
+        (void)snpf(cp, len + 1, "(%s %s)", ttl, dp->name);
+        (void)add_nma(ctx, cp, len);
+        (void)free((MALLOC_P *)cp);
+        return (0);
+    }
+
+#    if defined(HASDCACHE)
+    /*
+     * We haven't found a match.
+     *
+     * If rebuilding the device cache was suppressed and the device cache is
+     * "unsafe," rebuild it.
+     */
+    if (!r && DCunsafe) {
+        (void)rereaddev(ctx);
+        goto printdevname_again;
+    }
+#    endif /* defined(HASDCACHE) */
+
+    return (0);
 }
-#endif	/* defined(USE_LIB_PRINTDEVNAME) */
+#endif /* defined(USE_LIB_PRINTDEVNAME) */
diff --git a/lib/prfp.c b/lib/prfp.c
index 4f8027b..6e57391 100644
--- a/lib/prfp.c
+++ b/lib/prfp.c
@@ -2,7 +2,6 @@
  * prfp.c -- process_file() function for lsof library
  */
 
-
 /*
  * Copyright 1997 Purdue Research Foundation, West Lafayette, Indiana
  * 47907.  All rights reserved.
@@ -29,18 +28,10 @@
  * 4. This notice may not be removed or altered.
  */
 
+#include "common.h"
+#include "machine.h"
 
-#include "../machine.h"
-
-#if	defined(USE_LIB_PROCESS_FILE)
-
-# if	!defined(lint)
-static char copyright[] =
-"@(#) Copyright 1997 Purdue Research Foundation.\nAll rights reserved.\n";
-# endif	/* !defined(lint) */
-
-#include "../lsof.h"
-
+#if defined(USE_LIB_PROCESS_FILE)
 
 /*
  * process_file() - process file
@@ -56,179 +47,170 @@ static char copyright[] =
  *			#define FILEPTR	foobar
  */
 
-void
-process_file(fp)
-	KA_T fp;			/* kernel file structure address */
+void process_file(struct lsof_context *ctx,
+                  KA_T fp) /* kernel file structure address */
 {
-	struct file f;
-	int flag;
-	char tbuf[32];
-
-#if	defined(FILEPTR)
-/*
- * Save file structure address for process_node().
- */
-	FILEPTR = &f;
-#endif	/* defined(FILEPTR) */
-
-/*
- * Read file structure.
- */
-	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) {
-
-	/*
-	 * 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	!defined(HASNOFSCOUNT)
-	    if (Fsv & FSV_CT) {
-		Lf->fct = (long)f.f_count;
-		Lf->fsv |= FSV_CT;
-	    }
-# endif	/* !defined(HASNOFSCOUNT) */
-
-# if	!defined(HASNOFSADDR)
-	    if (Fsv & FSV_FA) {
-		Lf->fsa = fp;
-		Lf->fsv |= FSV_FA;
-	    }
-# endif	/* !defined(HASNOFSADDR) */
-
-# if	!defined(HASNOFSFLAGS)
-	    if (Fsv & FSV_FG) {
-		Lf->ffg = (long)f.f_flag;
-		Lf->fsv |= FSV_FG;
-	    }
-# endif	/* !defined(HASNOFSFLAGS) */
-
-# if	!defined(HASNOFSNADDR)
-	    if (Fsv & FSV_NI) {
-		Lf->fna = (KA_T)f.f_data;
-		Lf->fsv |= FSV_NI;
-	    }
-# endif	/* !defined(HASNOFSNADDR) */
-#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) */
-
-#if	defined(DTYPE_PTS)
-	    case DTYPE_PTS:
-# if	defined(HASPTSFN)
-		HASPTSFN((KA_T)f.f_data);
-# endif	/* defined(HASPTSFN) */
-		return;
-#endif	/* defined(DTYPE_PIPE) */
-
-#if	defined(DTYPE_FIFO)
-	    case DTYPE_FIFO:
-#endif	/* defined(DTYPE_FIFO) */
-
-#if	defined(DTYPE_GNODE)
-	    case DTYPE_GNODE:
-#endif	/* defined(DTYPE_GNODE) */
-
-#if	defined(DTYPE_INODE)
-	    case DTYPE_INODE:
-#endif	/* defined(DTYPE_INODE) */
-
-#if	defined(DTYPE_PORT)
-	    case DTYPE_PORT:
-#endif	/* defined(DTYPE_PORT) */
-
-#if	defined(DTYPE_VNODE)
-	    case DTYPE_VNODE:
-#endif	/* defined(DTYPE_VNODE) */
-
-#if	defined(HASF_VNODE)
-		process_node((KA_T)f.f_vnode);
-#else	/* !defined(HASF_VNODE) */
-		process_node((KA_T)f.f_data);
-#endif	/* defined(HASF_VNODE) */
-
-		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	defined(X_BADFILEOPS)
-		if (X_bfopsa && f.f_ops && (X_bfopsa == (KA_T)f.f_ops)) {
-		    (void) snpf(Namech, Namechl,
-			"no more information; ty=%d file may be closing",
-			(int)f.f_type);
-		    enter_nm(Namech);
-		    return;
-		}
-#endif	/* defined(X_BADFILEOPS) */
-
-		if (f.f_type || f.f_ops) {
-		    (void) snpf(Namech, Namechl,
-			"%s file struct, ty=%d, op=%s",
-			print_kptr(fp, tbuf, sizeof(tbuf)), (int)f.f_type,
-			print_kptr((KA_T)f.f_ops, (char *)NULL, 0));
-		    enter_nm(Namech);
-		    return;
-		}
-	    }
-	}
-	enter_nm("no more information");
+    struct file f;
+    int flag;
+    char tbuf[32];
+
+#    if defined(FILEPTR)
+    /*
+     * Save file structure address for process_node().
+     */
+    FILEPTR = &f;
+#    endif /* defined(FILEPTR) */
+
+    /*
+     * Read file structure.
+     */
+    if (kread(ctx, (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(ctx, Namech);
+        return;
+    }
+    Lf->off = (SZOFFTYPE)f.f_offset;
+    Lf->off_def = 1;
+    if (f.f_count) {
+
+        /*
+         * Construct access code.
+         */
+        if ((flag = (f.f_flag & (FREAD | FWRITE))) == FREAD)
+            Lf->access = LSOF_FILE_ACCESS_READ;
+        else if (flag == FWRITE)
+            Lf->access = LSOF_FILE_ACCESS_WRITE;
+        else if (flag == (FREAD | FWRITE))
+            Lf->access = LSOF_FILE_ACCESS_READ_WRITE;
+
+#    if defined(HASFSTRUCT)
+            /*
+             * Save file structure values.
+             */
+
+#        if !defined(HASNOFSCOUNT)
+        Lf->fct = (long)f.f_count;
+        Lf->fsv |= FSV_CT;
+#        endif /* !defined(HASNOFSCOUNT) */
+
+#        if !defined(HASNOFSADDR)
+        Lf->fsa = fp;
+        Lf->fsv |= FSV_FA;
+#        endif /* !defined(HASNOFSADDR) */
+
+#        if !defined(HASNOFSFLAGS)
+        Lf->ffg = (long)f.f_flag;
+        Lf->fsv |= FSV_FG;
+#        endif /* !defined(HASNOFSFLAGS) */
+
+#        if !defined(HASNOFSNADDR)
+        Lf->fna = (KA_T)f.f_data;
+        Lf->fsv |= FSV_NI;
+#        endif /* !defined(HASNOFSNADDR) */
+#    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(ctx, (KA_T)f.f_data);
+#        endif /* defined(HASPIPEFN) */
+            return;
+#    endif /* defined(DTYPE_PIPE) */
+
+#    if defined(DTYPE_PTS)
+        case DTYPE_PTS:
+#        if defined(HASPTSFN)
+            HASPTSFN(ctx, (KA_T)f.f_data);
+#        endif /* defined(HASPTSFN) */
+            return;
+#    endif /* defined(DTYPE_PIPE) */
+
+#    if defined(DTYPE_FIFO)
+        case DTYPE_FIFO:
+#    endif /* defined(DTYPE_FIFO) */
+
+#    if defined(DTYPE_GNODE)
+        case DTYPE_GNODE:
+#    endif /* defined(DTYPE_GNODE) */
+
+#    if defined(DTYPE_INODE)
+        case DTYPE_INODE:
+#    endif /* defined(DTYPE_INODE) */
+
+#    if defined(DTYPE_PORT)
+        case DTYPE_PORT:
+#    endif /* defined(DTYPE_PORT) */
+
+#    if defined(DTYPE_VNODE)
+        case DTYPE_VNODE:
+#    endif /* defined(DTYPE_VNODE) */
+
+#    if defined(HASF_VNODE)
+            process_node(ctx, (KA_T)f.f_vnode);
+#    else  /* !defined(HASF_VNODE) */
+            process_node(ctx, (KA_T)f.f_data);
+#    endif /* defined(HASF_VNODE) */
+
+            return;
+        case DTYPE_SOCKET:
+            process_socket(ctx, (KA_T)f.f_data);
+            return;
+
+#    if defined(HASKQUEUE)
+        case DTYPE_KQUEUE:
+            process_kqueue(ctx, (KA_T)f.f_data);
+            return;
+#    endif /* defined(HASKQUEUE) */
+
+#    if defined(HASPSXSEM)
+        case DTYPE_PSXSEM:
+            process_psxsem(ctx, (KA_T)f.f_data);
+            return;
+#    endif /* defined(HASPSXSEM) */
+
+#    if defined(HASPSXSHM)
+        case DTYPE_PSXSHM:
+            process_psxshm(ctx, (KA_T)f.f_data);
+            return;
+#    endif /* defined(HASPSXSHM) */
+
+#    if defined(HASPRIVFILETYPE)
+        case PRIVFILETYPE:
+            HASPRIVFILETYPE(ctx, (KA_T)f.f_data);
+            return;
+#    endif /* defined(HASPRIVFILETYPE) */
+
+        default:
+
+#    if defined(X_BADFILEOPS)
+            if (X_bfopsa && f.f_ops && (X_bfopsa == (KA_T)f.f_ops)) {
+                (void)snpf(Namech, Namechl,
+                           "no more information; ty=%d file may be closing",
+                           (int)f.f_type);
+                enter_nm(ctx, Namech);
+                return;
+            }
+#    endif /* defined(X_BADFILEOPS) */
+
+            if (f.f_type || f.f_ops) {
+                (void)snpf(Namech, Namechl, "%s file struct, ty=%d, op=%s",
+                           print_kptr(fp, tbuf, sizeof(tbuf)), (int)f.f_type,
+                           print_kptr((KA_T)f.f_ops, (char *)NULL, 0));
+                enter_nm(ctx, Namech);
+                return;
+            }
+        }
+    }
+    enter_nm(ctx, "no more information");
 }
-#else	/* !defined(USE_LIB_PROCESS_FILE) */
-char prfp_d1[] = "d"; char *prfp_d2 = prfp_d1;
-#endif	/* defined(USE_LIB_PROCESS_FILE) */
+#else  /* !defined(USE_LIB_PROCESS_FILE) */
+char prfp_d1[] = "d";
+char *prfp_d2 = prfp_d1;
+#endif /* defined(USE_LIB_PROCESS_FILE) */
diff --git a/lib/print.c b/lib/print.c
new file mode 100644
index 0000000..f9feef0
--- /dev/null
+++ b/lib/print.c
@@ -0,0 +1,1483 @@
+/*
+ * print.c - common print 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.
+ */
+
+#include "common.h"
+#include "lsof.h"
+
+/*
+ * Local definitions, structures and function prototypes
+ */
+
+/*
+ * access_to_char() - convert enum lsof_file_access_mode to char
+ */
+char access_to_char(enum lsof_file_access_mode access) {
+    switch (access) {
+    default:
+    case LSOF_FILE_ACCESS_NONE:
+        return ' ';
+    case LSOF_FILE_ACCESS_READ:
+        return 'r';
+    case LSOF_FILE_ACCESS_WRITE:
+        return 'w';
+    case LSOF_FILE_ACCESS_READ_WRITE:
+        return 'u';
+    }
+}
+
+/*
+ * lock_to_char() - convert enum lsof_lock_mode to char
+ */
+char lock_to_char(enum lsof_lock_mode lock) {
+    switch (lock) {
+    default:
+    case LSOF_LOCK_NONE:
+        return ' ';
+    case LSOF_LOCK_UNKNOWN:
+        return 'U';
+    case LSOF_LOCK_READ_PARTIAL:
+        return 'r';
+    case LSOF_LOCK_READ_FULL:
+        return 'R';
+    case LSOF_LOCK_WRITE_PARTIAL:
+        return 'w';
+    case LSOF_LOCK_WRITE_FULL:
+        return 'W';
+    case LSOF_LOCK_READ_WRITE:
+        return 'u';
+    case LSOF_LOCK_SOLARIS_NFS:
+        return 'N';
+    case LSOF_LOCK_SCO_PARTIAL:
+        return 'x';
+    case LSOF_LOCK_SCO_FULL:
+        return 'X';
+    }
+}
+
+/*
+ * file_type_to_string() - convert enum lsof_file_type to string
+ */
+void file_type_to_string(enum lsof_file_type type,
+                         uint32_t unknown_file_type_number, char *buf,
+                         size_t buf_len) {
+    switch (type) {
+    default:
+    case LSOF_FILE_UNKNOWN_RAW:
+        (void)snpf(buf, buf_len, "%04o", (unknown_file_type_number & 0xfff));
+        break;
+    case LSOF_FILE_FIFO:
+        (void)snpf(buf, buf_len, "FIFO");
+        break;
+    case LSOF_FILE_CHAR:
+        (void)snpf(buf, buf_len, "CHR");
+        break;
+    case LSOF_FILE_DIR:
+        (void)snpf(buf, buf_len, "DIR");
+        break;
+    case LSOF_FILE_BLOCK:
+        (void)snpf(buf, buf_len, "BLK");
+        break;
+    case LSOF_FILE_REGULAR:
+        (void)snpf(buf, buf_len, "REG");
+        break;
+    case LSOF_FILE_LINK:
+        (void)snpf(buf, buf_len, "LINK");
+        break;
+    /* Use lower case for network-related files except IPv4/IPv6/ATALK for
+     * compatibility */
+    case LSOF_FILE_SOCKET:
+        (void)snpf(buf, buf_len, "sock");
+        break;
+    case LSOF_FILE_IPV4:
+        (void)snpf(buf, buf_len, "IPv4");
+        break;
+    case LSOF_FILE_IPV6:
+        (void)snpf(buf, buf_len, "IPv6");
+        break;
+    case LSOF_FILE_AX25:
+        (void)snpf(buf, buf_len, "ax25");
+        break;
+    case LSOF_FILE_INET:
+        (void)snpf(buf, buf_len, "inet");
+        break;
+    case LSOF_FILE_LINK_LEVEL_ACCESS:
+        (void)snpf(buf, buf_len, "lla");
+        break;
+    case LSOF_FILE_ROUTE:
+        (void)snpf(buf, buf_len, "rte");
+        break;
+    case LSOF_FILE_UNIX:
+        (void)snpf(buf, buf_len, "unix");
+        break;
+    case LSOF_FILE_X25:
+        (void)snpf(buf, buf_len, "x.25");
+        break;
+    case LSOF_FILE_APPLETALK:
+        (void)snpf(buf, buf_len, "ATALK");
+        break;
+    case LSOF_FILE_NET_DRIVER:
+        (void)snpf(buf, buf_len, "ndrv");
+        break;
+    case LSOF_FILE_INTERNAL_KEY:
+        (void)snpf(buf, buf_len, "key");
+        break;
+    case LSOF_FILE_SYSTEM:
+        (void)snpf(buf, buf_len, "systm");
+        break;
+    case LSOF_FILE_PPP:
+        (void)snpf(buf, buf_len, "ppp");
+        break;
+    case LSOF_FILE_IPX:
+        (void)snpf(buf, buf_len, "ipx");
+        break;
+    case LSOF_FILE_RAW:
+        (void)snpf(buf, buf_len, "raw");
+        break;
+    case LSOF_FILE_RAW6:
+        (void)snpf(buf, buf_len, "raw6");
+        break;
+    case LSOF_FILE_NETLINK:
+        (void)snpf(buf, buf_len, "netlink");
+        break;
+    case LSOF_FILE_PACKET:
+        (void)snpf(buf, buf_len, "pack");
+        break;
+    case LSOF_FILE_ICMP:
+        (void)snpf(buf, buf_len, "icmp");
+        break;
+
+    case LSOF_FILE_PROC_AS:
+        (void)snpf(buf, buf_len, "PAS");
+        break;
+    case LSOF_FILE_PROC_AUXV:
+        (void)snpf(buf, buf_len, "PAXV");
+        break;
+    case LSOF_FILE_PROC_CRED:
+        (void)snpf(buf, buf_len, "PCRE");
+        break;
+    case LSOF_FILE_PROC_CTRL:
+        (void)snpf(buf, buf_len, "PCTL");
+        break;
+    case LSOF_FILE_PROC_CUR_PROC:
+        (void)snpf(buf, buf_len, "PCUR");
+        break;
+    case LSOF_FILE_PROC_CWD:
+        (void)snpf(buf, buf_len, "PCWD");
+        break;
+    case LSOF_FILE_PROC_DIR:
+        (void)snpf(buf, buf_len, "PDIR");
+        break;
+    case LSOF_FILE_PROC_EXEC_TYPE:
+        (void)snpf(buf, buf_len, "PETY");
+        break;
+    case LSOF_FILE_PROC_FD:
+        (void)snpf(buf, buf_len, "PFD");
+        break;
+    case LSOF_FILE_PROC_FD_DIR:
+        (void)snpf(buf, buf_len, "PFDR");
+        break;
+    case LSOF_FILE_PROC_FILE:
+        (void)snpf(buf, buf_len, "PFIL");
+        break;
+    case LSOF_FILE_PROC_FP_REGS:
+        (void)snpf(buf, buf_len, "PFPR");
+        break;
+    case LSOF_FILE_PROC_PAGE_DATA:
+        (void)snpf(buf, buf_len, "PGD");
+        break;
+    case LSOF_FILE_PROC_GROUP_NOTIFIER:
+        (void)snpf(buf, buf_len, "PGID");
+        break;
+    case LSOF_FILE_PROC_LWP_CTL:
+        (void)snpf(buf, buf_len, "PLC");
+        break;
+    case LSOF_FILE_PROC_LWP_DIR:
+        (void)snpf(buf, buf_len, "PLDR");
+        break;
+    case LSOF_FILE_PROC_LDT:
+        (void)snpf(buf, buf_len, "PLDT");
+        break;
+    case LSOF_FILE_PROC_LPS_INFO:
+        (void)snpf(buf, buf_len, "PLPI");
+        break;
+    case LSOF_FILE_PROC_LSTATUS:
+        (void)snpf(buf, buf_len, "PLST");
+        break;
+    case LSOF_FILE_PROC_LUSAGE:
+        (void)snpf(buf, buf_len, "PLU");
+        break;
+    case LSOF_FILE_PROC_LWP_GWINDOWS:
+        (void)snpf(buf, buf_len, "PLWG");
+        break;
+    case LSOF_FILE_PROC_LWP_SINFO:
+        (void)snpf(buf, buf_len, "PLWI");
+        break;
+    case LSOF_FILE_PROC_LWP_STATUS:
+        (void)snpf(buf, buf_len, "PLWS");
+        break;
+    case LSOF_FILE_PROC_LWP_USAGE:
+        (void)snpf(buf, buf_len, "PLWU");
+        break;
+    case LSOF_FILE_PROC_LWP_XREGS:
+        (void)snpf(buf, buf_len, "PLWX");
+        break;
+    case LSOF_FILE_PROC_MAP:
+        (void)snpf(buf, buf_len, "PMAP");
+        break;
+    case LSOF_FILE_PROC_MAPS:
+        (void)snpf(buf, buf_len, "PMPS");
+        break;
+    case LSOF_FILE_PROC_MEMORY:
+        (void)snpf(buf, buf_len, "PMEM");
+        break;
+    case LSOF_FILE_PROC_PROC_NOTIFIER:
+        (void)snpf(buf, buf_len, "PNTF");
+        break;
+    case LSOF_FILE_PROC_OBJ:
+        (void)snpf(buf, buf_len, "POBJ");
+        break;
+    case LSOF_FILE_PROC_OBJ_DIR:
+        (void)snpf(buf, buf_len, "PODR");
+        break;
+    case LSOF_FILE_PROC_OLD_LWP:
+        (void)snpf(buf, buf_len, "POLP");
+        break;
+    case LSOF_FILE_PROC_OLD_PID:
+        (void)snpf(buf, buf_len, "POPF");
+        break;
+    case LSOF_FILE_PROC_OLD_PAGE:
+        (void)snpf(buf, buf_len, "POPG");
+        break;
+    case LSOF_FILE_PROC_REGS:
+        (void)snpf(buf, buf_len, "PREG");
+        break;
+    case LSOF_FILE_PROC_RMAP:
+        (void)snpf(buf, buf_len, "PRMP");
+        break;
+    case LSOF_FILE_PROC_ROOT:
+        (void)snpf(buf, buf_len, "PRTD");
+        break;
+    case LSOF_FILE_PROC_SIGACT:
+        (void)snpf(buf, buf_len, "PSGA");
+        break;
+    case LSOF_FILE_PROC_PSINFO:
+        (void)snpf(buf, buf_len, "PSIN");
+        break;
+    case LSOF_FILE_PROC_STATUS:
+        (void)snpf(buf, buf_len, "PSTA");
+        break;
+    case LSOF_FILE_PROC_USAGE:
+        (void)snpf(buf, buf_len, "PUSG");
+        break;
+    case LSOF_FILE_PROC_WATCH:
+        (void)snpf(buf, buf_len, "PW");
+        break;
+    case LSOF_FILE_PROC_XMAP:
+        (void)snpf(buf, buf_len, "PXMP");
+        break;
+
+    /* Others */
+    case LSOF_FILE_ANON_INODE:
+        (void)snpf(buf, buf_len, "a_inode");
+        break;
+    case LSOF_FILE_DEL:
+        (void)snpf(buf, buf_len, "DEL");
+        break;
+    case LSOF_FILE_DOOR:
+        (void)snpf(buf, buf_len, "DOOR");
+        break;
+    case LSOF_FILE_KQUEUE:
+        (void)snpf(buf, buf_len, "KQUEUE");
+        break;
+    case LSOF_FILE_FSEVENTS:
+        (void)snpf(buf, buf_len, "FSEVENTS");
+        break;
+    case LSOF_FILE_EVENTFD:
+        (void)snpf(buf, buf_len, "EVENTFD");
+        break;
+    case LSOF_FILE_PROCDESC:
+        (void)snpf(buf, buf_len, "PROCDSC");
+        break;
+    case LSOF_FILE_MULTIPLEXED_BLOCK:
+        (void)snpf(buf, buf_len, "MPB");
+        break;
+    case LSOF_FILE_MULTIPLEXED_CHAR:
+        (void)snpf(buf, buf_len, "MPC");
+        break;
+    case LSOF_FILE_UNKNOWN_DELETED:
+        (void)snpf(buf, buf_len, "UNKNdel");
+        break;
+    case LSOF_FILE_UNKNOWN_MEMORY:
+        (void)snpf(buf, buf_len, "UNKNmem");
+        break;
+    case LSOF_FILE_UNKNOWN_FD:
+        (void)snpf(buf, buf_len, "UNKNfd");
+        break;
+    case LSOF_FILE_UNKNOWN_CWD:
+        (void)snpf(buf, buf_len, "UNKNcwd");
+        break;
+    case LSOF_FILE_UNKNOWN_ROOT_DIR:
+        (void)snpf(buf, buf_len, "UNKNrtd");
+        break;
+    case LSOF_FILE_UNKNOWN_PROGRAM_TEXT:
+        (void)snpf(buf, buf_len, "UNKNtxt");
+        break;
+    case LSOF_FILE_UNKNOWN:
+        (void)snpf(buf, buf_len, "UNKN");
+        break;
+    case LSOF_FILE_UNKNOWN_STAT:
+        (void)snpf(buf, buf_len, "unknown");
+        break;
+    case LSOF_FILE_PIPE:
+        (void)snpf(buf, buf_len, "PIPE");
+        break;
+    case LSOF_FILE_PORT:
+        (void)snpf(buf, buf_len, "PORT");
+        break;
+    case LSOF_FILE_POSIX_MQ:
+        (void)snpf(buf, buf_len, "PSXMQ");
+        break;
+    case LSOF_FILE_POSIX_SEMA:
+        (void)snpf(buf, buf_len, "PSXSEM");
+        break;
+    case LSOF_FILE_POSIX_SHM:
+        (void)snpf(buf, buf_len, "PSXSHM");
+        break;
+    case LSOF_FILE_SHM:
+        (void)snpf(buf, buf_len, "SHM");
+        break;
+    case LSOF_FILE_PTS:
+        (void)snpf(buf, buf_len, "PTS");
+        break;
+    case LSOF_FILE_SHARED_MEM_TRANSPORT:
+        (void)snpf(buf, buf_len, "SMT");
+        break;
+    case LSOF_FILE_STREAM:
+        (void)snpf(buf, buf_len, "STR");
+        break;
+    case LSOF_FILE_STREAM_SOCKET:
+        (void)snpf(buf, buf_len, "STSO");
+        break;
+    case LSOF_FILE_SCO_UNKNOWN:
+        (void)snpf(buf, buf_len, "XNAM");
+        break;
+    case LSOF_FILE_SCO_SEMA:
+        (void)snpf(buf, buf_len, "XSEM");
+        break;
+    case LSOF_FILE_SCO_SHARED:
+        (void)snpf(buf, buf_len, "XSD");
+        break;
+    case LSOF_FILE_UNSUPPORTED:
+        (void)snpf(buf, buf_len, "UNSP");
+        break;
+
+    /* vnode */
+    case LSOF_FILE_VNODE_VNON:
+        (void)snpf(buf, buf_len, "VNON");
+        break;
+    case LSOF_FILE_VNODE_VREG:
+        (void)snpf(buf, buf_len, "VREG");
+        break;
+    case LSOF_FILE_VNODE_VDIR:
+        (void)snpf(buf, buf_len, "VDIR");
+        break;
+    case LSOF_FILE_VNODE_VBLK:
+        (void)snpf(buf, buf_len, "VBLK");
+        break;
+    case LSOF_FILE_VNODE_VCHR:
+        (void)snpf(buf, buf_len, "VCHR");
+        break;
+    case LSOF_FILE_VNODE_VLNK:
+        (void)snpf(buf, buf_len, "VLNK");
+        break;
+    case LSOF_FILE_VNODE_VSOCK:
+        (void)snpf(buf, buf_len, "SOCK");
+        break;
+    case LSOF_FILE_VNODE_VBAD:
+        (void)snpf(buf, buf_len, "VBAD");
+        break;
+    case LSOF_FILE_VNODE_VMPC:
+        (void)snpf(buf, buf_len, "VMPC");
+        break;
+    case LSOF_FILE_VNODE_VFIFO:
+        (void)snpf(buf, buf_len, "FIFO");
+        break;
+    case LSOF_FILE_VNODE_VDOOR:
+        (void)snpf(buf, buf_len, "DOOR");
+        break;
+    case LSOF_FILE_VNODE_VPORT:
+        (void)snpf(buf, buf_len, "PORT");
+        break;
+    case LSOF_FILE_VNODE_VUNNAMED:
+        (void)snpf(buf, buf_len, "UNNM");
+        break;
+    }
+}
+
+/*
+ * endnm() - locate end of Namech
+ */
+char *endnm(struct lsof_context *ctx, size_t *sz) /* returned remaining size */
+{
+    register char *s;
+    register size_t tsz;
+
+    for (s = Namech, tsz = Namechl; *s; s++, tsz--)
+        ;
+    *sz = tsz;
+    return (s);
+}
+
+void __attribute__((weak))
+usage(struct lsof_context *ctx, /* context */
+      int err,                  /* it is called as part of error handlng? */
+      int fh,                   /* ``-F ?'' status */
+      int version)              /* ``-v'' status */
+{
+    // do nothing in liblsof
+}
+
+#if !defined(HASPRIVPRIPP)
+/*
+ * printiproto() - print Internet protocol name
+ */
+
+void printiproto(struct lsof_context *ctx, /* context */
+                 int p)                    /* protocol number */
+{
+    int i;
+    static int m = -1;
+    char *s;
+
+    switch (p) {
+
+#    if defined(IPPROTO_TCP)
+    case IPPROTO_TCP:
+        s = "TCP";
+        break;
+#    endif /* defined(IPPROTO_TCP) */
+
+#    if defined(IPPROTO_UDP)
+    case IPPROTO_UDP:
+        s = "UDP";
+        break;
+#    endif /* defined(IPPROTO_UDP) */
+
+#    if defined(IPPROTO_IP)
+#        if !defined(IPPROTO_HOPOPTS) || IPPROTO_IP != IPPROTO_HOPOPTS
+    case IPPROTO_IP:
+        s = "IP";
+        break;
+#        endif /* !defined(IPPROTO_HOPOPTS) || IPPROTO_IP!=IPPROTO_HOPOPTS */
+#    endif     /* defined(IPPROTO_IP) */
+
+#    if defined(IPPROTO_ICMP)
+    case IPPROTO_ICMP:
+        s = "ICMP";
+        break;
+#    endif /* defined(IPPROTO_ICMP) */
+
+#    if defined(IPPROTO_ICMPV6)
+    case IPPROTO_ICMPV6:
+        s = "ICMPV6";
+        break;
+#    endif /* defined(IPPROTO_ICMPV6) */
+
+#    if defined(IPPROTO_IGMP)
+    case IPPROTO_IGMP:
+        s = "IGMP";
+        break;
+#    endif /* defined(IPPROTO_IGMP) */
+
+#    if defined(IPPROTO_GGP)
+    case IPPROTO_GGP:
+        s = "GGP";
+        break;
+#    endif /* defined(IPPROTO_GGP) */
+
+#    if defined(IPPROTO_EGP)
+    case IPPROTO_EGP:
+        s = "EGP";
+        break;
+#    endif /* defined(IPPROTO_EGP) */
+
+#    if defined(IPPROTO_PUP)
+    case IPPROTO_PUP:
+        s = "PUP";
+        break;
+#    endif /* defined(IPPROTO_PUP) */
+
+#    if defined(IPPROTO_IDP)
+    case IPPROTO_IDP:
+        s = "IDP";
+        break;
+#    endif /* defined(IPPROTO_IDP) */
+
+#    if defined(IPPROTO_ND)
+    case IPPROTO_ND:
+        s = "ND";
+        break;
+#    endif /* defined(IPPROTO_ND) */
+
+#    if defined(IPPROTO_RAW)
+    case IPPROTO_RAW:
+        s = "RAW";
+        break;
+#    endif /* defined(IPPROTO_RAW) */
+
+#    if defined(IPPROTO_HELLO)
+    case IPPROTO_HELLO:
+        s = "HELLO";
+        break;
+#    endif /* defined(IPPROTO_HELLO) */
+
+#    if defined(IPPROTO_PXP)
+    case IPPROTO_PXP:
+        s = "PXP";
+        break;
+#    endif /* defined(IPPROTO_PXP) */
+
+#    if defined(IPPROTO_RAWIP)
+    case IPPROTO_RAWIP:
+        s = "RAWIP";
+        break;
+#    endif /* defined(IPPROTO_RAWIP) */
+
+#    if defined(IPPROTO_RAWIF)
+    case IPPROTO_RAWIF:
+        s = "RAWIF";
+        break;
+#    endif /* defined(IPPROTO_RAWIF) */
+
+#    if defined(IPPROTO_HOPOPTS)
+    case IPPROTO_HOPOPTS:
+        s = "HOPOPTS";
+        break;
+#    endif /* defined(IPPROTO_HOPOPTS) */
+
+#    if defined(IPPROTO_IPIP)
+    case IPPROTO_IPIP:
+        s = "IPIP";
+        break;
+#    endif /* defined(IPPROTO_IPIP) */
+
+#    if defined(IPPROTO_ST)
+    case IPPROTO_ST:
+        s = "ST";
+        break;
+#    endif /* defined(IPPROTO_ST) */
+
+#    if defined(IPPROTO_PIGP)
+    case IPPROTO_PIGP:
+        s = "PIGP";
+        break;
+#    endif /* defined(IPPROTO_PIGP) */
+
+#    if defined(IPPROTO_RCCMON)
+    case IPPROTO_RCCMON:
+        s = "RCCMON";
+        break;
+#    endif /* defined(IPPROTO_RCCMON) */
+
+#    if defined(IPPROTO_NVPII)
+    case IPPROTO_NVPII:
+        s = "NVPII";
+        break;
+#    endif /* defined(IPPROTO_NVPII) */
+
+#    if defined(IPPROTO_ARGUS)
+    case IPPROTO_ARGUS:
+        s = "ARGUS";
+        break;
+#    endif /* defined(IPPROTO_ARGUS) */
+
+#    if defined(IPPROTO_EMCON)
+    case IPPROTO_EMCON:
+        s = "EMCON";
+        break;
+#    endif /* defined(IPPROTO_EMCON) */
+
+#    if defined(IPPROTO_XNET)
+    case IPPROTO_XNET:
+        s = "XNET";
+        break;
+#    endif /* defined(IPPROTO_XNET) */
+
+#    if defined(IPPROTO_CHAOS)
+    case IPPROTO_CHAOS:
+        s = "CHAOS";
+        break;
+#    endif /* defined(IPPROTO_CHAOS) */
+
+#    if defined(IPPROTO_MUX)
+    case IPPROTO_MUX:
+        s = "MUX";
+        break;
+#    endif /* defined(IPPROTO_MUX) */
+
+#    if defined(IPPROTO_MEAS)
+    case IPPROTO_MEAS:
+        s = "MEAS";
+        break;
+#    endif /* defined(IPPROTO_MEAS) */
+
+#    if defined(IPPROTO_HMP)
+    case IPPROTO_HMP:
+        s = "HMP";
+        break;
+#    endif /* defined(IPPROTO_HMP) */
+
+#    if defined(IPPROTO_PRM)
+    case IPPROTO_PRM:
+        s = "PRM";
+        break;
+#    endif /* defined(IPPROTO_PRM) */
+
+#    if defined(IPPROTO_TRUNK1)
+    case IPPROTO_TRUNK1:
+        s = "TRUNK1";
+        break;
+#    endif /* defined(IPPROTO_TRUNK1) */
+
+#    if defined(IPPROTO_TRUNK2)
+    case IPPROTO_TRUNK2:
+        s = "TRUNK2";
+        break;
+#    endif /* defined(IPPROTO_TRUNK2) */
+
+#    if defined(IPPROTO_LEAF1)
+    case IPPROTO_LEAF1:
+        s = "LEAF1";
+        break;
+#    endif /* defined(IPPROTO_LEAF1) */
+
+#    if defined(IPPROTO_LEAF2)
+    case IPPROTO_LEAF2:
+        s = "LEAF2";
+        break;
+#    endif /* defined(IPPROTO_LEAF2) */
+
+#    if defined(IPPROTO_RDP)
+    case IPPROTO_RDP:
+        s = "RDP";
+        break;
+#    endif /* defined(IPPROTO_RDP) */
+
+#    if defined(IPPROTO_IRTP)
+    case IPPROTO_IRTP:
+        s = "IRTP";
+        break;
+#    endif /* defined(IPPROTO_IRTP) */
+
+#    if defined(IPPROTO_TP)
+    case IPPROTO_TP:
+        s = "TP";
+        break;
+#    endif /* defined(IPPROTO_TP) */
+
+#    if defined(IPPROTO_BLT)
+    case IPPROTO_BLT:
+        s = "BLT";
+        break;
+#    endif /* defined(IPPROTO_BLT) */
+
+#    if defined(IPPROTO_NSP)
+    case IPPROTO_NSP:
+        s = "NSP";
+        break;
+#    endif /* defined(IPPROTO_NSP) */
+
+#    if defined(IPPROTO_INP)
+    case IPPROTO_INP:
+        s = "INP";
+        break;
+#    endif /* defined(IPPROTO_INP) */
+
+#    if defined(IPPROTO_SEP)
+    case IPPROTO_SEP:
+        s = "SEP";
+        break;
+#    endif /* defined(IPPROTO_SEP) */
+
+#    if defined(IPPROTO_3PC)
+    case IPPROTO_3PC:
+        s = "3PC";
+        break;
+#    endif /* defined(IPPROTO_3PC) */
+
+#    if defined(IPPROTO_IDPR)
+    case IPPROTO_IDPR:
+        s = "IDPR";
+        break;
+#    endif /* defined(IPPROTO_IDPR) */
+
+#    if defined(IPPROTO_XTP)
+    case IPPROTO_XTP:
+        s = "XTP";
+        break;
+#    endif /* defined(IPPROTO_XTP) */
+
+#    if defined(IPPROTO_DDP)
+    case IPPROTO_DDP:
+        s = "DDP";
+        break;
+#    endif /* defined(IPPROTO_DDP) */
+
+#    if defined(IPPROTO_CMTP)
+    case IPPROTO_CMTP:
+        s = "CMTP";
+        break;
+#    endif /* defined(IPPROTO_CMTP) */
+
+#    if defined(IPPROTO_TPXX)
+    case IPPROTO_TPXX:
+        s = "TPXX";
+        break;
+#    endif /* defined(IPPROTO_TPXX) */
+
+#    if defined(IPPROTO_IL)
+    case IPPROTO_IL:
+        s = "IL";
+        break;
+#    endif /* defined(IPPROTO_IL) */
+
+#    if defined(IPPROTO_IPV6)
+    case IPPROTO_IPV6:
+        s = "IPV6";
+        break;
+#    endif /* defined(IPPROTO_IPV6) */
+
+#    if defined(IPPROTO_SDRP)
+    case IPPROTO_SDRP:
+        s = "SDRP";
+        break;
+#    endif /* defined(IPPROTO_SDRP) */
+
+#    if defined(IPPROTO_ROUTING)
+    case IPPROTO_ROUTING:
+        s = "ROUTING";
+        break;
+#    endif /* defined(IPPROTO_ROUTING) */
+
+#    if defined(IPPROTO_FRAGMENT)
+    case IPPROTO_FRAGMENT:
+        s = "FRAGMNT";
+        break;
+#    endif /* defined(IPPROTO_FRAGMENT) */
+
+#    if defined(IPPROTO_IDRP)
+    case IPPROTO_IDRP:
+        s = "IDRP";
+        break;
+#    endif /* defined(IPPROTO_IDRP) */
+
+#    if defined(IPPROTO_RSVP)
+    case IPPROTO_RSVP:
+        s = "RSVP";
+        break;
+#    endif /* defined(IPPROTO_RSVP) */
+
+#    if defined(IPPROTO_GRE)
+    case IPPROTO_GRE:
+        s = "GRE";
+        break;
+#    endif /* defined(IPPROTO_GRE) */
+
+#    if defined(IPPROTO_MHRP)
+    case IPPROTO_MHRP:
+        s = "MHRP";
+        break;
+#    endif /* defined(IPPROTO_MHRP) */
+
+#    if defined(IPPROTO_BHA)
+    case IPPROTO_BHA:
+        s = "BHA";
+        break;
+#    endif /* defined(IPPROTO_BHA) */
+
+#    if defined(IPPROTO_ESP)
+    case IPPROTO_ESP:
+        s = "ESP";
+        break;
+#    endif /* defined(IPPROTO_ESP) */
+
+#    if defined(IPPROTO_AH)
+    case IPPROTO_AH:
+        s = "AH";
+        break;
+#    endif /* defined(IPPROTO_AH) */
+
+#    if defined(IPPROTO_INLSP)
+    case IPPROTO_INLSP:
+        s = "INLSP";
+        break;
+#    endif /* defined(IPPROTO_INLSP) */
+
+#    if defined(IPPROTO_SWIPE)
+    case IPPROTO_SWIPE:
+        s = "SWIPE";
+        break;
+#    endif /* defined(IPPROTO_SWIPE) */
+
+#    if defined(IPPROTO_NHRP)
+    case IPPROTO_NHRP:
+        s = "NHRP";
+        break;
+#    endif /* defined(IPPROTO_NHRP) */
+
+#    if defined(IPPROTO_NONE)
+    case IPPROTO_NONE:
+        s = "NONE";
+        break;
+#    endif /* defined(IPPROTO_NONE) */
+
+#    if defined(IPPROTO_DSTOPTS)
+    case IPPROTO_DSTOPTS:
+        s = "DSTOPTS";
+        break;
+#    endif /* defined(IPPROTO_DSTOPTS) */
+
+#    if defined(IPPROTO_AHIP)
+    case IPPROTO_AHIP:
+        s = "AHIP";
+        break;
+#    endif /* defined(IPPROTO_AHIP) */
+
+#    if defined(IPPROTO_CFTP)
+    case IPPROTO_CFTP:
+        s = "CFTP";
+        break;
+#    endif /* defined(IPPROTO_CFTP) */
+
+#    if defined(IPPROTO_SATEXPAK)
+    case IPPROTO_SATEXPAK:
+        s = "SATEXPK";
+        break;
+#    endif /* defined(IPPROTO_SATEXPAK) */
+
+#    if defined(IPPROTO_KRYPTOLAN)
+    case IPPROTO_KRYPTOLAN:
+        s = "KRYPTOL";
+        break;
+#    endif /* defined(IPPROTO_KRYPTOLAN) */
+
+#    if defined(IPPROTO_RVD)
+    case IPPROTO_RVD:
+        s = "RVD";
+        break;
+#    endif /* defined(IPPROTO_RVD) */
+
+#    if defined(IPPROTO_IPPC)
+    case IPPROTO_IPPC:
+        s = "IPPC";
+        break;
+#    endif /* defined(IPPROTO_IPPC) */
+
+#    if defined(IPPROTO_ADFS)
+    case IPPROTO_ADFS:
+        s = "ADFS";
+        break;
+#    endif /* defined(IPPROTO_ADFS) */
+
+#    if defined(IPPROTO_SATMON)
+    case IPPROTO_SATMON:
+        s = "SATMON";
+        break;
+#    endif /* defined(IPPROTO_SATMON) */
+
+#    if defined(IPPROTO_VISA)
+    case IPPROTO_VISA:
+        s = "VISA";
+        break;
+#    endif /* defined(IPPROTO_VISA) */
+
+#    if defined(IPPROTO_IPCV)
+    case IPPROTO_IPCV:
+        s = "IPCV";
+        break;
+#    endif /* defined(IPPROTO_IPCV) */
+
+#    if defined(IPPROTO_CPNX)
+    case IPPROTO_CPNX:
+        s = "CPNX";
+        break;
+#    endif /* defined(IPPROTO_CPNX) */
+
+#    if defined(IPPROTO_CPHB)
+    case IPPROTO_CPHB:
+        s = "CPHB";
+        break;
+#    endif /* defined(IPPROTO_CPHB) */
+
+#    if defined(IPPROTO_WSN)
+    case IPPROTO_WSN:
+        s = "WSN";
+        break;
+#    endif /* defined(IPPROTO_WSN) */
+
+#    if defined(IPPROTO_PVP)
+    case IPPROTO_PVP:
+        s = "PVP";
+        break;
+#    endif /* defined(IPPROTO_PVP) */
+
+#    if defined(IPPROTO_BRSATMON)
+    case IPPROTO_BRSATMON:
+        s = "BRSATMN";
+        break;
+#    endif /* defined(IPPROTO_BRSATMON) */
+
+#    if defined(IPPROTO_WBMON)
+    case IPPROTO_WBMON:
+        s = "WBMON";
+        break;
+#    endif /* defined(IPPROTO_WBMON) */
+
+#    if defined(IPPROTO_WBEXPAK)
+    case IPPROTO_WBEXPAK:
+        s = "WBEXPAK";
+        break;
+#    endif /* defined(IPPROTO_WBEXPAK) */
+
+#    if defined(IPPROTO_EON)
+    case IPPROTO_EON:
+        s = "EON";
+        break;
+#    endif /* defined(IPPROTO_EON) */
+
+#    if defined(IPPROTO_VMTP)
+    case IPPROTO_VMTP:
+        s = "VMTP";
+        break;
+#    endif /* defined(IPPROTO_VMTP) */
+
+#    if defined(IPPROTO_SVMTP)
+    case IPPROTO_SVMTP:
+        s = "SVMTP";
+        break;
+#    endif /* defined(IPPROTO_SVMTP) */
+
+#    if defined(IPPROTO_VINES)
+    case IPPROTO_VINES:
+        s = "VINES";
+        break;
+#    endif /* defined(IPPROTO_VINES) */
+
+#    if defined(IPPROTO_TTP)
+    case IPPROTO_TTP:
+        s = "TTP";
+        break;
+#    endif /* defined(IPPROTO_TTP) */
+
+#    if defined(IPPROTO_IGP)
+    case IPPROTO_IGP:
+        s = "IGP";
+        break;
+#    endif /* defined(IPPROTO_IGP) */
+
+#    if defined(IPPROTO_DGP)
+    case IPPROTO_DGP:
+        s = "DGP";
+        break;
+#    endif /* defined(IPPROTO_DGP) */
+
+#    if defined(IPPROTO_TCF)
+    case IPPROTO_TCF:
+        s = "TCF";
+        break;
+#    endif /* defined(IPPROTO_TCF) */
+
+#    if defined(IPPROTO_IGRP)
+    case IPPROTO_IGRP:
+        s = "IGRP";
+        break;
+#    endif /* defined(IPPROTO_IGRP) */
+
+#    if defined(IPPROTO_OSPFIGP)
+    case IPPROTO_OSPFIGP:
+        s = "OSPFIGP";
+        break;
+#    endif /* defined(IPPROTO_OSPFIGP) */
+
+#    if defined(IPPROTO_SRPC)
+    case IPPROTO_SRPC:
+        s = "SRPC";
+        break;
+#    endif /* defined(IPPROTO_SRPC) */
+
+#    if defined(IPPROTO_LARP)
+    case IPPROTO_LARP:
+        s = "LARP";
+        break;
+#    endif /* defined(IPPROTO_LARP) */
+
+#    if defined(IPPROTO_MTP)
+    case IPPROTO_MTP:
+        s = "MTP";
+        break;
+#    endif /* defined(IPPROTO_MTP) */
+
+#    if defined(IPPROTO_AX25)
+    case IPPROTO_AX25:
+        s = "AX25";
+        break;
+#    endif /* defined(IPPROTO_AX25) */
+
+#    if defined(IPPROTO_IPEIP)
+    case IPPROTO_IPEIP:
+        s = "IPEIP";
+        break;
+#    endif /* defined(IPPROTO_IPEIP) */
+
+#    if defined(IPPROTO_MICP)
+    case IPPROTO_MICP:
+        s = "MICP";
+        break;
+#    endif /* defined(IPPROTO_MICP) */
+
+#    if defined(IPPROTO_SCCSP)
+    case IPPROTO_SCCSP:
+        s = "SCCSP";
+        break;
+#    endif /* defined(IPPROTO_SCCSP) */
+
+#    if defined(IPPROTO_ETHERIP)
+    case IPPROTO_ETHERIP:
+        s = "ETHERIP";
+        break;
+#    endif /* defined(IPPROTO_ETHERIP) */
+
+#    if defined(IPPROTO_ENCAP)
+#        if !defined(IPPROTO_IPIP) || IPPROTO_IPIP != IPPROTO_ENCAP
+    case IPPROTO_ENCAP:
+        s = "ENCAP";
+        break;
+#        endif /* !defined(IPPROTO_IPIP) || IPPROTO_IPIP!=IPPROTO_ENCAP */
+#    endif     /* defined(IPPROTO_ENCAP) */
+
+#    if defined(IPPROTO_APES)
+    case IPPROTO_APES:
+        s = "APES";
+        break;
+#    endif /* defined(IPPROTO_APES) */
+
+#    if defined(IPPROTO_GMTP)
+    case IPPROTO_GMTP:
+        s = "GMTP";
+        break;
+#    endif /* defined(IPPROTO_GMTP) */
+
+#    if defined(IPPROTO_DIVERT)
+    case IPPROTO_DIVERT:
+        s = "DIVERT";
+        break;
+#    endif /* defined(IPPROTO_DIVERT) */
+
+    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));
+    }
+}
+#endif /* !defined(HASPRIVPRIPP) */
+
+/*
+ * printunkaf() - print unknown address family
+ */
+
+void printunkaf(struct lsof_context *ctx, int fam, /* unknown address family */
+                int ty) /* output type: 0 = terse; 1 = full */
+{
+    char *p, *s;
+
+    p = "";
+    switch (fam) {
+
+#if defined(AF_UNSPEC)
+    case AF_UNSPEC:
+        s = "UNSPEC";
+        break;
+#endif /* defined(AF_UNSPEC) */
+
+#if defined(AF_UNIX)
+    case AF_UNIX:
+        s = "UNIX";
+        break;
+#endif /* defined(AF_UNIX) */
+
+#if defined(AF_INET)
+    case AF_INET:
+        s = "INET";
+        break;
+#endif /* defined(AF_INET) */
+
+#if defined(AF_INET6)
+    case AF_INET6:
+        s = "INET6";
+        break;
+#endif /* defined(AF_INET6) */
+
+#if defined(AF_IMPLINK)
+    case AF_IMPLINK:
+        s = "IMPLINK";
+        break;
+#endif /* defined(AF_IMPLINK) */
+
+#if defined(AF_PUP)
+    case AF_PUP:
+        s = "PUP";
+        break;
+#endif /* defined(AF_PUP) */
+
+#if defined(AF_CHAOS)
+    case AF_CHAOS:
+        s = "CHAOS";
+        break;
+#endif /* defined(AF_CHAOS) */
+
+#if defined(AF_NS)
+    case AF_NS:
+        s = "NS";
+        break;
+#endif /* defined(AF_NS) */
+
+#if defined(AF_ISO)
+    case AF_ISO:
+        s = "ISO";
+        break;
+#endif /* defined(AF_ISO) */
+
+#if defined(AF_NBS)
+#    if !defined(AF_ISO) || AF_NBS != AF_ISO
+    case AF_NBS:
+        s = "NBS";
+        break;
+#    endif /* !defined(AF_ISO) || AF_NBS!=AF_ISO */
+#endif     /* defined(AF_NBS) */
+
+#if defined(AF_ECMA)
+    case AF_ECMA:
+        s = "ECMA";
+        break;
+#endif /* defined(AF_ECMA) */
+
+#if defined(AF_DATAKIT)
+    case AF_DATAKIT:
+        s = "DATAKIT";
+        break;
+#endif /* defined(AF_DATAKIT) */
+
+#if defined(AF_CCITT)
+    case AF_CCITT:
+        s = "CCITT";
+        break;
+#endif /* defined(AF_CCITT) */
+
+#if defined(AF_SNA)
+    case AF_SNA:
+        s = "SNA";
+        break;
+#endif /* defined(AF_SNA) */
+
+#if defined(AF_DECnet)
+    case AF_DECnet:
+        s = "DECnet";
+        break;
+#endif /* defined(AF_DECnet) */
+
+#if defined(AF_DLI)
+    case AF_DLI:
+        s = "DLI";
+        break;
+#endif /* defined(AF_DLI) */
+
+#if defined(AF_LAT)
+    case AF_LAT:
+        s = "LAT";
+        break;
+#endif /* defined(AF_LAT) */
+
+#if defined(AF_HYLINK)
+    case AF_HYLINK:
+        s = "HYLINK";
+        break;
+#endif /* defined(AF_HYLINK) */
+
+#if defined(AF_APPLETALK)
+    case AF_APPLETALK:
+        s = "APPLETALK";
+        break;
+#endif /* defined(AF_APPLETALK) */
+
+#if defined(AF_BSC)
+    case AF_BSC:
+        s = "BSC";
+        break;
+#endif /* defined(AF_BSC) */
+
+#if defined(AF_DSS)
+    case AF_DSS:
+        s = "DSS";
+        break;
+#endif /* defined(AF_DSS) */
+
+#if defined(AF_ROUTE)
+    case AF_ROUTE:
+        s = "ROUTE";
+        break;
+#endif /* defined(AF_ROUTE) */
+
+#if defined(AF_RAW)
+    case AF_RAW:
+        s = "RAW";
+        break;
+#endif /* defined(AF_RAW) */
+
+#if defined(AF_LINK)
+    case AF_LINK:
+        s = "LINK";
+        break;
+#endif /* defined(AF_LINK) */
+
+#if defined(pseudo_AF_XTP)
+    case pseudo_AF_XTP:
+        p = "pseudo_";
+        s = "XTP";
+        break;
+#endif /* defined(pseudo_AF_XTP) */
+
+#if defined(AF_RMP)
+    case AF_RMP:
+        s = "RMP";
+        break;
+#endif /* defined(AF_RMP) */
+
+#if defined(AF_COIP)
+    case AF_COIP:
+        s = "COIP";
+        break;
+#endif /* defined(AF_COIP) */
+
+#if defined(AF_CNT)
+    case AF_CNT:
+        s = "CNT";
+        break;
+#endif /* defined(AF_CNT) */
+
+#if defined(pseudo_AF_RTIP)
+    case pseudo_AF_RTIP:
+        p = "pseudo_";
+        s = "RTIP";
+        break;
+#endif /* defined(pseudo_AF_RTIP) */
+
+#if defined(AF_NETMAN)
+    case AF_NETMAN:
+        s = "NETMAN";
+        break;
+#endif /* defined(AF_NETMAN) */
+
+#if defined(AF_INTF)
+    case AF_INTF:
+        s = "INTF";
+        break;
+#endif /* defined(AF_INTF) */
+
+#if defined(AF_NETWARE)
+    case AF_NETWARE:
+        s = "NETWARE";
+        break;
+#endif /* defined(AF_NETWARE) */
+
+#if defined(AF_NDD)
+    case AF_NDD:
+        s = "NDD";
+        break;
+#endif /* defined(AF_NDD) */
+
+#if defined(AF_NIT)
+#    if !defined(AF_ROUTE) || AF_ROUTE != AF_NIT
+    case AF_NIT:
+        s = "NIT";
+        break;
+#    endif /* !defined(AF_ROUTE) || AF_ROUTE!=AF_NIT */
+#endif     /* defined(AF_NIT) */
+
+#if defined(AF_802)
+#    if !defined(AF_RAW) || AF_RAW != AF_802
+    case AF_802:
+        s = "802";
+        break;
+#    endif /* !defined(AF_RAW) || AF_RAW!=AF_802 */
+#endif     /* defined(AF_802) */
+
+#if defined(AF_X25)
+    case AF_X25:
+        s = "X25";
+        break;
+#endif /* defined(AF_X25) */
+
+#if defined(AF_CTF)
+    case AF_CTF:
+        s = "CTF";
+        break;
+#endif /* defined(AF_CTF) */
+
+#if defined(AF_WAN)
+    case AF_WAN:
+        s = "WAN";
+        break;
+#endif /* defined(AF_WAN) */
+
+#if defined(AF_OSINET)
+#    if defined(AF_INET) && AF_INET != AF_OSINET
+    case AF_OSINET:
+        s = "OSINET";
+        break;
+#    endif /* defined(AF_INET) && AF_INET!=AF_OSINET */
+#endif     /* defined(AF_OSINET) */
+
+#if defined(AF_GOSIP)
+    case AF_GOSIP:
+        s = "GOSIP";
+        break;
+#endif /* defined(AF_GOSIP) */
+
+#if defined(AF_SDL)
+    case AF_SDL:
+        s = "SDL";
+        break;
+#endif /* defined(AF_SDL) */
+
+#if defined(AF_IPX)
+    case AF_IPX:
+        s = "IPX";
+        break;
+#endif /* defined(AF_IPX) */
+
+#if defined(AF_SIP)
+    case AF_SIP:
+        s = "SIP";
+        break;
+#endif /* defined(AF_SIP) */
+
+#if defined(psuedo_AF_PIP)
+    case psuedo_AF_PIP:
+        p = "pseudo_";
+        s = "PIP";
+        break;
+#endif /* defined(psuedo_AF_PIP) */
+
+#if defined(AF_OTS)
+    case AF_OTS:
+        s = "OTS";
+        break;
+#endif /* defined(AF_OTS) */
+
+#if defined(pseudo_AF_BLUE)
+    case pseudo_AF_BLUE: /* packets for Blue box */
+        p = "pseudo_";
+        s = "BLUE";
+        break;
+#endif /* defined(pseudo_AF_BLUE) */
+
+#if defined(AF_NDRV) /* network driver raw access */
+    case AF_NDRV:
+        s = "NDRV";
+        break;
+#endif /* defined(AF_NDRV) */
+
+#if defined(AF_SYSTEM) /* kernel event messages */
+    case AF_SYSTEM:
+        s = "SYSTEM";
+        break;
+#endif /* defined(AF_SYSTEM) */
+
+#if defined(AF_USER)
+    case AF_USER:
+        s = "USER";
+        break;
+#endif /* defined(AF_USER) */
+
+#if defined(pseudo_AF_KEY)
+    case pseudo_AF_KEY:
+        p = "pseudo_";
+        s = "KEY";
+        break;
+#endif /* defined(pseudo_AF_KEY) */
+
+#if defined(AF_KEY) /* Security Association DB socket */
+    case AF_KEY:
+        s = "KEY";
+        break;
+#endif /* defined(AF_KEY) */
+
+#if defined(AF_NCA) /* NCA socket */
+    case AF_NCA:
+        s = "NCA";
+        break;
+#endif /* defined(AF_NCA) */
+
+#if defined(AF_POLICY) /* Security Policy DB socket */
+    case AF_POLICY:
+        s = "POLICY";
+        break;
+#endif /* defined(AF_POLICY) */
+
+#if defined(AF_PPP) /* PPP socket */
+    case AF_PPP:
+        s = "PPP";
+        break;
+#endif /* defined(AF_PPP) */
+
+    default:
+        if (!ty)
+            (void)snpf(Namech, Namechl, "%#x", fam);
+        else
+            (void)snpf(Namech, Namechl, "no further information on family %#x",
+                       fam);
+        return;
+    }
+    if (!ty)
+        (void)snpf(Namech, Namechl, "%sAF_%s", p, s);
+    else
+        (void)snpf(Namech, Namechl, "no further information on %sAF_%s", p, s);
+    return;
+}
diff --git a/lib/proc.c b/lib/proc.c
new file mode 100644
index 0000000..aab349c
--- /dev/null
+++ b/lib/proc.c
@@ -0,0 +1,1402 @@
+/*
+ * proc.c - common process and file structure 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.
+ */
+
+#include "common.h"
+#include "dlsof.h"
+#include "lsof.h"
+#include "proto.h"
+
+#if defined(HASEPTOPTS)
+static void prt_pinfo(struct lsof_context *ctx, pxinfo_t *pp, int ps);
+static void prt_psxmqinfo(struct lsof_context *ctx, pxinfo_t *pp, int ps);
+static void prt_evtfdinfo(struct lsof_context *ctx, pxinfo_t *pp, int ps);
+#endif /* defined(HASEPTOPTS) */
+#if defined(HASPTYEPT)
+static void prt_ptyinfo(struct lsof_context *ctx, pxinfo_t *pp, int prt_edev,
+                        int ps);
+#endif /* defined(HASPTYEPT) */
+
+/*
+ * add_nma() - add to NAME column addition
+ */
+
+void add_nma(struct lsof_context *ctx, char *cp, /* string to add */
+             int len)                            /* string length */
+{
+    int nl;
+    char fd[FDLEN];
+
+    if (!cp || !len)
+        return;
+    if (Lf->nma) {
+        nl = (int)strlen(Lf->nma);
+        Lf->nma =
+            (char *)realloc((MALLOC_P *)Lf->nma, (MALLOC_S)(len + nl + 2));
+    } else {
+        nl = 0;
+        Lf->nma = (char *)malloc((MALLOC_S)(len + 1));
+    }
+    if (!Lf->nma) {
+        fd_to_string(Lf->fd_type, Lf->fd_num, fd);
+        (void)fprintf(stderr, "%s: no name addition space: PID %ld, FD %s", Pn,
+                      (long)Lp->pid, fd);
+        Error(ctx);
+    }
+    if (nl) {
+        Lf->nma[nl] = ' ';
+        (void)strncpy(&Lf->nma[nl + 1], cp, len);
+        Lf->nma[nl + 1 + len] = '\0';
+    } else {
+        (void)strncpy(Lf->nma, cp, len);
+        Lf->nma[len] = '\0';
+    }
+}
+
+/*
+ * alloc_lfile() - allocate local file structure space
+ */
+
+void alloc_lfile(struct lsof_context *ctx,
+                 enum lsof_fd_type fd_type, /* file descriptor type */
+                 int num)                   /* file descriptor number -- -1 if
+                                             * none */
+{
+    int fds;
+
+    if (Lf) {
+        /*
+         * If reusing a previously allocated structure, release any allocated
+         * space it was using.
+         */
+        if (Lf->dev_ch)
+            (void)free((FREE_P *)Lf->dev_ch);
+        if (Lf->nm)
+            (void)free((FREE_P *)Lf->nm);
+        if (Lf->nma)
+            (void)free((FREE_P *)Lf->nma);
+
+#if defined(HASLFILEADD) && defined(CLRLFILEADD)
+        CLRLFILEADD(Lf)
+#endif /* defined(HASLFILEADD) && defined(CLRLFILEADD) */
+
+        /*
+         * Othwerise, allocate a new structure.
+         */
+    } else if (!(Lf = (struct lfile *)malloc(sizeof(struct lfile)))) {
+        (void)fprintf(stderr, "%s: no local file space at PID %d\n", Pn,
+                      Lp->pid);
+        Error(ctx);
+    }
+    /*
+     * Initialize the structure.
+     */
+    Lf->access = LSOF_FILE_ACCESS_NONE;
+    Lf->lock = LSOF_LOCK_NONE;
+    Lf->dev_def = Lf->inp_ty = Lf->is_com = Lf->is_nfs = Lf->is_stream =
+        Lf->lmi_srch = Lf->nlink_def = Lf->off_def = Lf->sz_def = Lf->rdev_def =
+            (unsigned char)0;
+    Lf->li[0].af = Lf->li[1].af = 0;
+    Lf->lts.type = -1;
+    Lf->nlink = 0l;
+
+#if defined(HASMNTSTAT)
+    Lf->mnt_stat = (unsigned char)0;
+#endif /* defined(HASMNTSTAT) */
+
+#if defined(HASEPTOPTS)
+    Lf->chend = 0;
+    Lf->eventfd_id = -1;
+#    if defined(HASPTYEPT)
+    Lf->tty_index = -1;
+#    endif /* defined(HASPTYEPT) */
+#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 = (unsigned int)0;
+    Lf->lts.rbsz = Lf->lts.sbsz = (unsigned long)0;
+    Lf->lts.qlens = Lf->lts.qlims = Lf->lts.pqlens = Lf->lts.rbszs =
+        Lf->lts.sbszs = (unsigned char)0;
+#endif /* defined(HASSOOPT) */
+
+#if defined(HASSOSTATE)
+    Lf->lts.ss = 0;
+#endif /* defined(HASSOSTATE) */
+
+#if defined(HASTCPOPT)
+    Lf->lts.mss = (unsigned long)0;
+    Lf->lts.msss = (unsigned char)0;
+    Lf->lts.topt = (unsigned int)0;
+#endif /* defined(HASTCPOPT) */
+
+#if defined(HASTCPTPIQ)
+    Lf->lts.rqs = Lf->lts.sqs = (unsigned char)0;
+#endif /* defined(HASTCPTPIQ) */
+
+#if defined(HASTCPTPIW)
+    Lf->lts.rws = Lf->lts.wws = (unsigned char)0;
+#endif /* defined(HASTCPTPIW) */
+
+#if defined(HASFSINO)
+    Lf->fs_ino = 0;
+#endif /* defined(HASFSINO) */
+
+#if defined(HASVXFS) && defined(HASVXFSDNLC)
+    Lf->is_vxfs = 0;
+#endif /* defined(HASVXFS) && defined(HASVXFSDNLC) */
+
+    Lf->inode = (INODETYPE)0;
+    Lf->off = (SZOFFTYPE)0;
+    if (Lp->pss & PS_PRI)
+        Lf->sf = Lp->sf;
+    else
+        Lf->sf = 0;
+    Lf->iproto[0] = '\0';
+    Lf->type = LSOF_FILE_NONE;
+    Lf->unknown_file_type_number = 0;
+    Lf->fd_type = fd_type;
+    Lf->fd_num = num;
+    Lf->dev_ch = Lf->fsdir = Lf->fsdev = Lf->nm = Lf->nma = (char *)NULL;
+    Lf->ch = -1;
+
+#if defined(HASNCACHE) && HASNCACHE < 2
+    Lf->na = (KA_T)NULL;
+#endif /* defined(HASNCACHE) && HASNCACHE<2 */
+
+    Lf->next = (struct lfile *)NULL;
+    Lf->ntype = Ntype = N_REGLR;
+    Namech[0] = '\0';
+
+#if defined(HASFSTRUCT)
+    Lf->fct = Lf->ffg = Lf->pof = (long)0;
+    Lf->fna = (KA_T)NULL;
+    Lf->fsv = (unsigned char)0;
+#endif /* defined(HASFSTRUCT) */
+
+#if defined(HASLFILEADD) && defined(SETLFILEADD)
+    /*
+     * Do local initializations.
+     */
+    SETLFILEADD
+#endif /* defined(HASLFILEADD) && defined(SETLFILEADD) */
+
+    /*
+     * See if the file descriptor has been selected.
+     */
+    if (!Fdl || (fd_type == LSOF_FD_NUMERIC && num < 0))
+        return;
+    fds = ck_fd_status(ctx, fd_type, num);
+    switch (FdlTy) {
+    case 0: /* inclusion list */
+        if (fds == 2)
+            Lf->sf |= SELFD;
+        break;
+    case 1: /* exclusion list */
+        if (fds != 1)
+            Lf->sf |= SELFD;
+    }
+}
+
+/*
+ * alloc_lproc() - allocate local proc structure space
+ */
+
+void alloc_lproc(struct lsof_context *ctx, int pid, /* Process ID */
+                 int pgid,                          /* process group ID */
+                 int ppid,                          /* parent process ID */
+                 UID_ARG uid,                       /* User ID */
+                 char *cmd,                         /* command */
+                 int pss,                           /* process select state */
+                 int sf)                            /* process select flags */
+{
+    static int sz = 0;
+
+    if (!Lproc) {
+        if (!(Lproc = (struct lproc *)malloc(
+                  (MALLOC_S)(LPROCINCR * sizeof(struct lproc))))) {
+            (void)fprintf(stderr,
+                          "%s: no malloc space for %d local proc structures\n",
+                          Pn, LPROCINCR);
+            Error(ctx);
+        }
+        sz = LPROCINCR;
+    } else if ((Nlproc + 1) > sz) {
+        sz += LPROCINCR;
+        if (!(Lproc = (struct lproc *)realloc(
+                  (MALLOC_P *)Lproc, (MALLOC_S)(sz * sizeof(struct lproc))))) {
+            (void)fprintf(stderr,
+                          "%s: no realloc space for %d local proc structures\n",
+                          Pn, sz);
+            Error(ctx);
+        }
+    }
+    Lp = &Lproc[Nlproc++];
+    Lp->pid = pid;
+
+#if defined(HASEPTOPTS)
+    Lp->ept = 0;
+#endif /* defined(HASEPTOPTS) */
+
+#if defined(HASTASKS)
+    Lp->tid = 0;
+    Lp->tcmd = (char *)NULL;
+#endif /* defined(HASTASKS) */
+
+    Lp->pgid = pgid;
+    Lp->ppid = ppid;
+    Lp->file = (struct lfile *)NULL;
+    Lp->sf = (short)sf;
+    Lp->pss = (short)pss;
+    Lp->uid = (uid_t)uid;
+    /*
+     * Allocate space for the full command name and copy it there.
+     */
+    if (!(Lp->cmd = mkstrcpy(cmd, (MALLOC_S *)NULL))) {
+        (void)fprintf(stderr, "%s: PID %d, no space for command name: ", Pn,
+                      pid);
+        safestrprt(cmd, stderr, 1);
+        Error(ctx);
+    }
+
+#if defined(HASZONES)
+    /*
+     * Clear the zone name pointer.  The dialect's own code will set it.
+     */
+    Lp->zn = (char *)NULL;
+#endif /* defined(HASZONES) */
+
+#if defined(HASSELINUX)
+    /*
+     * Clear the security context pointer.  The dialect's own code will
+     * set it.
+     */
+    Lp->cntx = (char *)NULL;
+#endif /* defined(HASSELINUX) */
+}
+
+/*
+ * ck_fd_status() - check FD status
+ *
+ * return: 0 == FD is neither included nor excluded
+ *	   1 == FD is excluded
+ *	   2 == FD is included
+ */
+
+extern int ck_fd_status(struct lsof_context *ctx,
+                        enum lsof_fd_type fd_type, /* file descriptor type */
+                        int num) /* file descriptor number -- -1 if
+                                  * none */
+{
+    struct fd_lst *fp;
+
+    if (!(fp = Fdl) || (fd_type == LSOF_FD_NUMERIC && num < 0))
+        return (0);
+    /*
+     * Check for an exclusion match.
+     */
+    if (FdlTy == 1) {
+        for (; fp; fp = fp->next) {
+            if (fp->fd_type != fd_type)
+                continue;
+            if (fp->fd_type == LSOF_FD_NUMERIC) {
+                if (num >= fp->lo && num <= fp->hi)
+                    return (1);
+            } else {
+                return (1);
+            }
+        }
+        return (0);
+    }
+    /*
+     * If Fdl isn't an exclusion list, check for an inclusion match.
+     */
+    for (; fp; fp = fp->next) {
+        if (fp->fd_type != fd_type)
+            continue;
+        if (fp->fd_type == LSOF_FD_NUMERIC) {
+            if (num >= fp->lo && num <= fp->hi)
+                return (2);
+        } else {
+            return (2);
+        }
+    }
+    return (0);
+}
+
+/*
+ * comppid() - compare PIDs
+ */
+
+int comppid(COMP_P *a1, COMP_P *a2) {
+    struct lproc **p1 = (struct lproc **)a1;
+    struct lproc **p2 = (struct lproc **)a2;
+
+    if ((*p1)->pid < (*p2)->pid)
+        return (-1);
+    if ((*p1)->pid > (*p2)->pid)
+        return (1);
+
+#if defined(HASTASKS)
+    if ((*p1)->tid < (*p2)->tid)
+        return (-1);
+    if ((*p1)->tid > (*p2)->tid)
+        return (1);
+#endif /* defined(HASTASKS) */
+
+    return (0);
+}
+
+/*
+ * ent_inaddr() - enter Internet addresses
+ */
+
+void ent_inaddr(struct lsof_context *ctx,
+                unsigned char *la, /* local Internet address */
+                int lp,            /* local port */
+                unsigned char *fa, /* foreign Internet address -- may
+                                    * be NULL to indicate no foreign
+                                    * address is known */
+                int fp,            /* foreign port */
+                int af)            /* address family -- e.g, AF_INET,
+                                    * AF_INET */
+{
+    int m;
+
+    if (la) {
+        Lf->li[0].af = af;
+
+#if defined(HASIPv6)
+        if (af == AF_INET6)
+            Lf->li[0].ia.a6 = *(struct in6_addr *)la;
+        else
+#endif /* defined(HASIPv6) */
+
+            Lf->li[0].ia.a4 = *(struct in_addr *)la;
+        Lf->li[0].p = lp;
+    } else
+        Lf->li[0].af = 0;
+    if (fa) {
+        Lf->li[1].af = af;
+
+#if defined(HASIPv6)
+        if (af == AF_INET6)
+            Lf->li[1].ia.a6 = *(struct in6_addr *)fa;
+        else
+#endif /* defined(HASIPv6) */
+
+            Lf->li[1].ia.a4 = *(struct in_addr *)fa;
+        Lf->li[1].p = fp;
+    } else
+        Lf->li[1].af = 0;
+    /*
+     * If network address matching has been selected, check both addresses.
+     */
+    if ((Selflags & SELNA) && Nwad) {
+        m = (fa && is_nw_addr(ctx, fa, fp, af)) ? 1 : 0;
+        m |= (la && is_nw_addr(ctx, la, lp, af)) ? 1 : 0;
+        if (m)
+            Lf->sf |= SELNA;
+    }
+}
+
+/*
+ * examine_lproc() - examine local process
+ *
+ * return: 1 = last process
+ */
+
+int examine_lproc(struct lsof_context *ctx) {
+    int sbp = 0;
+
+    if (RptTm)
+        return (0);
+    /*
+     * List the process if the process is selected and:
+     *
+     *	o  listing is limited to a single PID selection -- this one;
+     *
+     *	o  listing is selected by an ANDed option set (not all options)
+     *	   that includes a single PID selection -- this one.
+     */
+    if ((Lp->sf & SELPID) && !AllProc) {
+        if ((Selflags == SELPID) || (Fand && (Selflags & SELPID))) {
+            sbp = 1;
+            Npuns--;
+        }
+    }
+    /*
+     * Deprecate an unselected (or listed) process.
+     */
+    if (!Lp->pss) {
+        (void)free_lproc(Lp);
+        Nlproc--;
+    }
+    /*
+     * Indicate last-process if listing is limited to PID selections,
+     * and all selected processes have been listed.
+     */
+    return ((sbp && Npuns == 0) ? 1 : 0);
+}
+
+/*
+ * free_lproc() - free lproc entry and its associated malloc'd space
+ */
+
+void free_lproc(struct lproc *lp) {
+    struct lfile *lf, *nf;
+
+    for (lf = lp->file; lf; lf = nf) {
+        if (lf->dev_ch) {
+            (void)free((FREE_P *)lf->dev_ch);
+            lf->dev_ch = (char *)NULL;
+        }
+        if (lf->nm) {
+            (void)free((FREE_P *)lf->nm);
+            lf->nm = (char *)NULL;
+        }
+        if (lf->nma) {
+            (void)free((FREE_P *)lf->nma);
+            lf->nma = (char *)NULL;
+        }
+
+#if defined(HASLFILEADD) && defined(CLRLFILEADD)
+        CLRLFILEADD(lf)
+#endif /* defined(HASLFILEADD) && defined(CLRLFILEADD) */
+
+        nf = lf->next;
+        (void)free((FREE_P *)lf);
+    }
+    lp->file = (struct lfile *)NULL;
+    if (lp->cmd) {
+        (void)free((FREE_P *)lp->cmd);
+        lp->cmd = (char *)NULL;
+    }
+
+#if defined(HASTASKS)
+    if (lp->tcmd) {
+        (void)free((FREE_P *)lp->tcmd);
+        lp->tcmd = (char *)NULL;
+    }
+#endif /* defined(HASTASKS) */
+}
+
+/*
+ * is_cmd_excl() - is command excluded?
+ */
+
+int is_cmd_excl(struct lsof_context *ctx, char *cmd, /* command name */
+                short *pss,                          /* process state */
+                short *sf)                           /* process select flags */
+{
+    int i;
+    struct str_lst *sp;
+    /*
+     * See if the command is excluded by a "-c^<command>" option.
+     */
+    if (Cmdl && Cmdnx) {
+        for (sp = Cmdl; sp; sp = sp->next) {
+            if (sp->x && !strncmp(sp->str, cmd, sp->len))
+                return (1);
+        }
+    }
+    /*
+     * The command is not excluded if no command selection was requested,
+     * or if its name matches any -c <command> specification.
+     *
+     */
+    if ((Selflags & SELCMD) == 0)
+        return (0);
+    for (sp = Cmdl; sp; sp = sp->next) {
+        if (!sp->x && !strncmp(sp->str, cmd, sp->len)) {
+            sp->f = 1;
+            *pss |= PS_PRI;
+            *sf |= SELCMD;
+            return (0);
+        }
+    }
+    /*
+     * The command name doesn't match any -c <command> specification.  See if it
+     * matches a -c /RE/[bix] specification.
+     */
+    for (i = 0; i < NCmdRxU; i++) {
+        if (!regexec(&CmdRx[i].cx, cmd, 0, NULL, 0)) {
+            CmdRx[i].mc = 1;
+            *pss |= PS_PRI;
+            *sf |= SELCMD;
+            return (0);
+        }
+    }
+    /*
+     * The command name matches no -c specification.
+     *
+     * It's excluded if the only selection condition is command name,
+     * or if command name selection is part of an ANDed set.
+     */
+    if (Selflags == SELCMD)
+        return (1);
+    return (Fand ? 1 : 0);
+}
+
+/*
+ * is_file_sel() - is file selected?
+ */
+
+int is_file_sel(struct lsof_context *ctx, /* context */
+                struct lproc *lp,         /* lproc structure pointer */
+                struct lfile *lf)         /* lfile structure pointer */
+{
+    if (!lf || !lf->sf)
+        return (0);
+    if (lf->sf & SELEXCLF)
+        return (0);
+
+#if defined(HASSECURITY) && defined(HASNOSOCKSECURITY)
+    if (Myuid && (Myuid != lp->uid)) {
+        if (!(lf->sf & (SELNA | SELNET)))
+            return (0);
+    }
+#endif /* defined(HASSECURITY) && defined(HASNOSOCKSECURITY) */
+
+    if (AllProc)
+        return (1);
+    if (Fand && ((lf->sf & Selflags) != Selflags))
+        return (0);
+    return (1);
+}
+
+/*
+ * is_proc_excl() - is process excluded?
+ */
+
+int is_proc_excl(struct lsof_context *ctx, int pid, /* Process ID */
+                 int pgid,                          /* process group ID */
+                 UID_ARG uid,                       /* User ID */
+                 short *pss, /* process select state for lproc */
+#if defined(HASTASKS)
+                 short *sf, /* select flags for lproc */
+                 int tid)   /* task ID (not a task if zero) */
+#else
+                 short *sf) /* select flags for lproc */
+#endif /* defined(HASTASKS) */
+
+{
+    int i, j;
+
+    *pss = *sf = 0;
+
+#if defined(HASSECURITY)
+/*
+ * The process is excluded by virtue of the security option if it
+ * isn't owned by the owner of this lsof process, unless the
+ * HASNOSOCKSECURITY option is also specified.  In that case the
+ * selected socket files of any process may be listed.
+ */
+#    if !defined(HASNOSOCKSECURITY)
+    if (Myuid && Myuid != (uid_t)uid)
+        return (1);
+#    endif /* !defined(HASNOSOCKSECURITY) */
+#endif     /* defined(HASSECURITY) */
+
+    /*
+     * If the excluding of process listing by UID has been specified, see if the
+     * owner of this process is excluded.
+     */
+    if (Nuidexcl) {
+        for (i = j = 0; (i < Nuid) && (j < Nuidexcl); i++) {
+            if (!Suid[i].excl)
+                continue;
+            if (Suid[i].uid == (uid_t)uid)
+                return (1);
+            j++;
+        }
+    }
+    /*
+     * If the excluding of process listing by PGID has been specified, see if
+     * this PGID is excluded.
+     */
+    if (Npgidx) {
+        for (i = j = 0; (i < Npgid) && (j < Npgidx); i++) {
+            if (!Spgid[i].x)
+                continue;
+            if (Spgid[i].i == pgid)
+                return (1);
+            j++;
+        }
+    }
+    /*
+     * If the excluding of process listing by PID has been specified, see if
+     * this PID is excluded.
+     */
+    if (Npidx) {
+        for (i = j = 0; (i < Npid) && (j < Npidx); i++) {
+            if (!Spid[i].x)
+                continue;
+            if (Spid[i].i == pid)
+                return (1);
+            j++;
+        }
+    }
+    /*
+     * If the listing of all processes is selected, then this one is not
+     * excluded.
+     *
+     * However, if HASSECURITY and HASNOSOCKSECURITY are both specified, exclude
+     * network selections from the file flags, so that the tests in
+     * is_file_sel() work as expected.
+     */
+    if (AllProc) {
+        *pss = PS_PRI;
+
+#if defined(HASSECURITY) && defined(HASNOSOCKSECURITY)
+        *sf = SelAll & ~(SELNA | SELNET);
+#else  /* !defined(HASSECURITY) || !defined(HASNOSOCKSECURITY) */
+        *sf = SelAll;
+#endif /* defined(HASSECURITY) && defined(HASNOSOCKSECURITY) */
+
+        return (0);
+    }
+    /*
+     * If the listing of processes has been specified by process group ID, see
+     * if this one is included or excluded.
+     */
+    if (Npgidi && (Selflags & SELPGID)) {
+        for (i = j = 0; (i < Npgid) && (j < Npgidi); i++) {
+            if (Spgid[i].x)
+                continue;
+            if (Spgid[i].i == pgid) {
+                Spgid[i].f = 1;
+                *pss = PS_PRI;
+                *sf = SELPGID;
+                if (Selflags == SELPGID)
+                    return (0);
+                break;
+            }
+            j++;
+        }
+        if ((Selflags == SELPGID) && !*sf)
+            return (1);
+    }
+    /*
+     * If the listing of processes has been specified by PID, see if this one is
+     * included or excluded.
+     */
+    if (Npidi && (Selflags & SELPID)) {
+        for (i = j = 0; (i < Npid) && (j < Npidi); i++) {
+            if (Spid[i].x)
+                continue;
+            if (Spid[i].i == pid) {
+                Spid[i].f = 1;
+                *pss = PS_PRI;
+                *sf |= SELPID;
+                if (Selflags == SELPID)
+                    return (0);
+                break;
+            }
+            j++;
+        }
+        if ((Selflags == SELPID) && !*sf)
+            return (1);
+    }
+    /*
+     * If the listing of processes has been specified by UID, see if the owner
+     * of this process has been included.
+     */
+    if (Nuidincl && (Selflags & SELUID)) {
+        for (i = j = 0; (i < Nuid) && (j < Nuidincl); i++) {
+            if (Suid[i].excl)
+                continue;
+            if (Suid[i].uid == (uid_t)uid) {
+                Suid[i].f = 1;
+                *pss = PS_PRI;
+                *sf |= SELUID;
+                if (Selflags == SELUID)
+                    return (0);
+                break;
+            }
+            j++;
+        }
+        if (Selflags == SELUID && (*sf & SELUID) == 0)
+            return (1);
+    }
+
+#if defined(HASTASKS)
+    if ((Selflags & SELTASK) && tid) {
+
+        /*
+         * This is a task and tasks are selected.
+         */
+        *pss = PS_PRI;
+        *sf |= SELTASK;
+        if ((Selflags == SELTASK) || (Fand && ((*sf & Selflags) == Selflags)))
+            return (0);
+    }
+#endif /* defined(HASTASKS) */
+
+    /*
+     * When neither the process group ID, nor the PID, nor the task, nor the UID
+     * is selected:
+     *
+     *	If list option ANDing of process group IDs, PIDs, UIDs or tasks is
+     *	specified, the process is excluded;
+     *
+     *	Otherwise, it's not excluded by the tests of this function.
+     */
+    if (!*sf)
+        return ((Fand && (Selflags & (SELPGID | SELPID | SELUID | SELTASK)))
+                    ? 1
+                    : 0);
+    /*
+     * When the process group ID, PID, task or UID is selected and the process
+     * group ID, PID, task or UID list option has been specified:
+     *
+     *	If list option ANDing has been specified, and the correct
+     *	combination of selections are in place, reply that the process is no
+     *	excluded;
+     * or
+     *	If list option ANDing has not been specified, reply that the
+     *	process is not excluded by the tests of this function.
+     */
+    if (Selflags & (SELPGID | SELPID | SELUID | SELTASK)) {
+        if (Fand)
+            return (((Selflags & (SELPGID | SELPID | SELUID | SELTASK)) != *sf)
+                        ? 1
+                        : 0);
+        return (0);
+    }
+    /*
+     * Finally, when neither the process group ID, nor the PID, nor the UID, nor
+     * the task is selected, and no applicable list option has been specified:
+     *
+     *	If list option ANDing has been specified, this process is
+     *	excluded;
+     *
+     *	Otherwise, it isn't excluded by the tests of this function.
+     */
+    return (Fand ? 1 : 0);
+}
+
+/*
+ * link_lfile() - link local file structures
+ */
+
+void link_lfile(struct lsof_context *ctx) {
+    if (Lf->sf & SELEXCLF)
+        return;
+
+#if defined(HASEPTOPTS)
+    /*
+     * If endpoint info has been requested, clear the SELPINFO flag from the
+     * local pipe 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
+     * EPT_PIPE flag.
+     */
+    if (FeptE) {
+        if (Lf->sf & SELPINFO) {
+            Lp->ept |= EPT_PIPE;
+            Lf->sf &= ~SELPINFO;
+        }
+
+        /*
+         * Process posix mq endpoint files the same way by clearing the
+         * SELPSXMQINFO flag and setting the EPT_PSXMQ flag, letting a later
+         * call to process_psxmqinfo() set selection flags.
+         */
+        if (Lf->sf & SELPSXMQINFO) {
+            Lp->ept |= EPT_PSXMQ;
+            Lf->sf &= ~SELPSXMQINFO;
+        }
+
+#    if defined(HASUXSOCKEPT)
+        /*
+         * Process UNIX socket endpoint files the same way by clearing the
+         * SELUXINFO flag and setting the EPT_UXS flag, letting a later call to
+         * process_uxsinfo() set selection flags.
+         */
+        if (Lf->sf & SELUXSINFO) {
+            Lp->ept |= EPT_UXS;
+            Lf->sf &= ~SELUXSINFO;
+        }
+#    endif /* defined(HASUXSOCKEPT) */
+
+#    if defined(HASPTYEPT)
+        /*
+         * Process pseudoterminal endpoint files the same way by clearing the
+         * SELPTYINFO flag and setting the EPT_PTY flag, letting a later call to
+         * process_ptyinfo() set selection flags.
+         */
+        if (Lf->sf & SELPTYINFO) {
+            Lp->ept |= EPT_PTY;
+            Lf->sf &= ~SELPTYINFO;
+        }
+#    endif /* defined(HASPTYEPT) */
+
+        /*
+         * Process locally used INET socket endpoint files the same way by
+         * clearing the SENETSINFO flag and setting the EPT_NETS flag, letting a
+         * later call to process_netsinfo() set selection flags.
+         */
+        if (Lf->sf & SELNETSINFO) {
+            Lp->ept |= EPT_NETS;
+            Lf->sf &= ~SELNETSINFO;
+        }
+
+#    if defined(HASIPv6)
+        /*
+         * Process locally used INET6 socket endpoint files the same way by
+         * clearing the SENETS6INFO flag and setting the EPT_NETS6 flag, letting
+         * a later call to process_nets6info() set selection flags.
+         */
+        if (Lf->sf & SELNETS6INFO) {
+            Lp->ept |= EPT_NETS6;
+            Lf->sf &= ~SELNETS6INFO;
+        }
+#    endif /* defined(HASIPv6) */
+           /*
+            * Process eventfd endpoint files the same way by clearing the
+            * SELEVTFDINFO    flag and setting the EPT_EVTFD flag, letting a later
+            * call to    process_evtfdinfo()      set selection flags.
+            */
+        if (Lf->sf & SELEVTFDINFO) {
+            Lp->ept |= EPT_EVTFD;
+            Lf->sf &= ~SELEVTFDINFO;
+        }
+    }
+#endif /* defined(HASEPTOPTS) */
+
+    if (Lf->sf)
+        Lp->pss |= PS_SEC;
+    if (Plf)
+        Plf->next = Lf;
+    else
+        Lp->file = Lf;
+    Plf = Lf;
+    if (Fnet && (Lf->sf & SELNET))
+        Fnet = 2;
+    if (Fnfs && (Lf->sf & SELNFS))
+        Fnfs = 2;
+    if (Ftask && (Lf->sf & SELTASK))
+        Ftask = 2;
+    Lf = (struct lfile *)NULL;
+}
+
+#if defined(HASEPTOPTS)
+/*
+ * process_pinfo() -- process pipe info, adding it to selected files and
+ *		      selecting pipe end files (if requested)
+ */
+
+void process_pinfo(struct lsof_context *ctx,
+                   int f) /* function:
+                           *     0 == process selected pipe
+                           *     1 == process end point
+                           */
+{
+    pxinfo_t *pp; /* previous pipe info */
+
+    if (!FeptE)
+        return;
+    for (Lf = Lp->file; Lf; Lf = Lf->next) {
+        if ((Lf->ntype != N_FIFO) || (Lf->inp_ty != 1))
+            continue;
+        pp = (pxinfo_t *)NULL;
+        switch (f) {
+        case 0:
+
+            /*
+             * Process already selected pipe file.
+             */
+            if (is_file_sel(ctx, 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_pepti(ctx, Lp->pid, Lf, pp))) {
+
+                        /*
+                         * This pipe endpoint is linked to the selected pipe
+                         * file.  Add its PID and FD to the name column
+                         * addition.
+                         */
+                        prt_pinfo(ctx, pp, (FeptE == 2));
+                        pp = pp->next;
+                    }
+                } while (pp);
+            }
+            break;
+        case 1:
+            if (!is_file_sel(ctx, Lp, Lf) && (Lf->chend & CHEND_PIPE)) {
+
+                /*
+                 * 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_pepti(ctx, Lp->pid, Lf, pp))) {
+                        prt_pinfo(ctx, pp, 0);
+                        pp = pp->next;
+                    }
+                } while (pp);
+            }
+            break;
+        }
+    }
+}
+
+/*
+ * prt_pinfo() -- print pipe information
+ */
+
+static void prt_pinfo(struct lsof_context *ctx, pxinfo_t *pp, /* peer info */
+                      int ps) /* processing status:
+                               *    0 == process immediately
+                               *    1 == process later */
+{
+    struct lproc *ep; /* pipe endpoint process */
+    struct lfile *ef; /* pipe endpoint file */
+    int i;            /* temporary index */
+    char nma[1024];   /* name addition buffer */
+    char fd[FDLEN];
+
+    ep = &Lproc[pp->lpx];
+    ef = pp->lf;
+    fd_to_string(ef->fd_type, ef->fd_num, fd);
+    (void)snpf(nma, sizeof(nma) - 1, "%d,%.*s,%s%c", ep->pid, CmdLim, ep->cmd,
+               fd, access_to_char(ef->access));
+    (void)add_nma(ctx, nma, strlen(nma));
+    if (ps) {
+
+        /*
+         * Endpoint files have been selected, so mark this
+         * one for selection later. Set the type to PIPE.
+         */
+        ef->chend = CHEND_PIPE;
+        ep->ept |= EPT_PIPE_END;
+    }
+}
+
+/*
+ * process_psxmqinfo() -- posix mq info, adding it to selected files and
+ *		          selecting posix mq end files (if requested)
+ */
+
+void process_psxmqinfo(struct lsof_context *ctx,
+                       int f) /* function:
+                               *     0 == process selected posix mq
+                               *     1 == process end point
+                               */
+{
+    pxinfo_t *pp; /* previous posix mq info */
+
+    if (!FeptE)
+        return;
+    for (Lf = Lp->file; Lf; Lf = Lf->next) {
+        if (Lf->dev != MqueueDev)
+            continue;
+        pp = (pxinfo_t *)NULL;
+        switch (f) {
+        case 0:
+
+            /*
+             * Process already selected posix mq file.
+             */
+            if (is_file_sel(ctx, Lp, Lf)) {
+
+                /*
+                 * This file has been selected by some criterion other than
+                 * its being a posix mq.  Look up the posix mq's endpoints.
+                 */
+                do {
+                    if ((pp = find_psxmqinfo(ctx, Lp->pid, Lf, pp))) {
+
+                        /*
+                         * This posix mq endpoint is linked to the selected
+                         * posix mq file.  Add its PID and FD to the name column
+                         * addition.
+                         */
+                        prt_psxmqinfo(ctx, pp, (FeptE == 2));
+                        pp = pp->next;
+                    }
+                } while (pp);
+            }
+            break;
+        case 1:
+            if (!is_file_sel(ctx, Lp, Lf) && (Lf->chend & CHEND_PSXMQ)) {
+
+                /*
+                 * 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_psxmqinfo(ctx, Lp->pid, Lf, pp))) {
+                        prt_psxmqinfo(ctx, pp, 0);
+                        pp = pp->next;
+                    }
+                } while (pp);
+            }
+            break;
+        }
+    }
+}
+
+/*
+ * prt_psxmqinfo() -- print posix mq information
+ */
+
+static void prt_psxmqinfo(struct lsof_context *ctx,
+                          pxinfo_t *pp, /* peer info */
+                          int ps)       /* processing status:
+                                         *    0 == process immediately
+                                         *    1 == process later */
+{
+    struct lproc *ep; /* posix mq endpoint process */
+    struct lfile *ef; /* posix mq endpoint file */
+    int i;            /* temporary index */
+    char nma[1024];   /* name addition buffer */
+    char fd[FDLEN];
+
+    ep = &Lproc[pp->lpx];
+    ef = pp->lf;
+    fd_to_string(ef->fd_type, ef->fd_num, fd);
+    (void)snpf(nma, sizeof(nma) - 1, "%d,%.*s,%s%c", ep->pid, CmdLim, ep->cmd,
+               fd, access_to_char(ef->access));
+    (void)add_nma(ctx, nma, strlen(nma));
+    if (ps) {
+
+        /*
+         * Endpoint files have been selected, so mark this
+         * one for selection later. Set the type to posix mq.
+         */
+        ef->chend = CHEND_PSXMQ;
+        ep->ept |= EPT_PSXMQ_END;
+    }
+}
+
+/*
+ * process_evtfdinfo() -- process eventfd info, adding it to selected files and
+ *		          selecting envetfd end files (if requested)
+ */
+
+void process_evtfdinfo(struct lsof_context *ctx,
+                       int f) /* function:
+                               *     0 == process selected eventfd
+                               *     1 == process end point
+                               */
+{
+    pxinfo_t *pp; /* previous eventfd info */
+
+    if (!FeptE)
+        return;
+    for (Lf = Lp->file; Lf; Lf = Lf->next) {
+        if ((Lf->ntype != N_ANON_INODE) || (Lf->eventfd_id == -1))
+            continue;
+        pp = (pxinfo_t *)NULL;
+        switch (f) {
+        case 0:
+
+            /*
+             * Process already selected eventfd_id file.
+             */
+            if (is_file_sel(ctx, Lp, Lf)) {
+
+                /*
+                 * This file has been selected by some criterion other than
+                 * its being a eventfd.  Look up the eventfd's endpoints.
+                 */
+                do {
+                    if ((pp = find_evtfdinfo(ctx, Lp->pid, Lf, pp))) {
+
+                        /*
+                         * This eventfd endpoint is linked to the selected
+                         * eventfd file.  Add its PID and FD to the name column
+                         * addition.
+                         */
+                        prt_evtfdinfo(ctx, pp, (FeptE == 2));
+                        pp = pp->next;
+                    }
+                } while (pp);
+            }
+            break;
+        case 1:
+            if (!is_file_sel(ctx, Lp, Lf) && (Lf->chend & CHEND_EVTFD)) {
+
+                /*
+                 * 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_evtfdinfo(ctx, Lp->pid, Lf, pp))) {
+                        prt_evtfdinfo(ctx, pp, 0);
+                        pp = pp->next;
+                    }
+                } while (pp);
+            }
+            break;
+        }
+    }
+}
+
+/*
+ * prt_evtfdinfo() -- print eventfd information
+ */
+
+static void prt_evtfdinfo(struct lsof_context *ctx,
+                          pxinfo_t *pp, /* peer info */
+                          int ps)       /* processing status:
+                                         *    0 == process immediately
+                                         *    1 == process later */
+{
+    struct lproc *ep; /* eventfd endpoint process */
+    struct lfile *ef; /* eventfd endpoint file */
+    int i;            /* temporary index */
+    char nma[1024];   /* name addition buffer */
+    char fd[FDLEN];
+
+    ep = &Lproc[pp->lpx];
+    ef = pp->lf;
+    fd_to_string(ef->fd_type, ef->fd_num, fd);
+    (void)snpf(nma, sizeof(nma) - 1, "%d,%.*s,%s%c", ep->pid, CmdLim, ep->cmd,
+               fd, access_to_char(ef->access));
+    (void)add_nma(ctx, nma, strlen(nma));
+    if (ps) {
+
+        /*
+         * Endpoint files have been selected, so mark this
+         * one for selection later. Set the type to PIPE.
+         */
+        ef->chend = CHEND_EVTFD;
+        ep->ept |= EPT_EVTFD_END;
+    }
+}
+#endif /* defined(HASEPTOPTS) */
+
+#if defined(HASPTYEPT)
+/*
+ * process_ptyinfo() -- process pseudoterminal info, adding it to selected files
+ *and selecting pseudoterminal end files (if requested)
+ */
+
+void process_ptyinfo(struct lsof_context *ctx,
+                     int f) /* function:
+                             *  0 == process selected pseudoterminal
+                             *  1 == process end point */
+{
+    pxinfo_t *pp; /* previous pseudoterminal info */
+    int mos;      /* master or slave indicator
+                   *     0 == slave; 1 == master */
+    int pc;       /* print count */
+
+    if (!FeptE)
+        return;
+    for (Lf = Lp->file; Lf; Lf = Lf->next) {
+        if (Lf->rdev_def && is_pty_ptmx(Lf->rdev))
+            mos = 1;
+        else if (Lf->rdev_def && is_pty_slave(GET_MAJ_DEV(Lf->rdev)))
+            mos = 0;
+        else
+            continue;
+
+        pp = (pxinfo_t *)NULL;
+        switch (f) {
+        case 0:
+
+            /*
+             * Process already selected pseudoterminal file.
+             */
+            if (is_file_sel(ctx, Lp, Lf)) {
+
+                /*
+                 * This file has been selected by some criterion other than
+                 * its being a pseudoterminal.  Look up the pseudoterminal's
+                 * endpoints.
+                 */
+                pc = 1;
+                do {
+                    if ((pp = find_ptyepti(ctx, Lp->pid, Lf, !mos, pp))) {
+
+                        /*
+                         * This pseudoterminal endpoint is linked to the
+                         * selected pseudoterminal file.  Add its PID, FD and
+                         * access mode to the name column addition.
+                         */
+                        prt_ptyinfo(ctx, pp, (mos && pc), (FeptE == 2));
+                        pp = pp->next;
+                        pc = 0;
+                    }
+                } while (pp);
+            }
+            break;
+        case 1:
+            if (!is_file_sel(ctx, Lp, Lf) && (Lf->chend & CHEND_PTY)) {
+
+                /*
+                 * 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;
+                pc = 1;
+                do {
+                    if ((pp = find_ptyepti(ctx, Lp->pid, Lf, !mos, pp))) {
+                        prt_ptyinfo(ctx, pp, (mos && pc), 0);
+                        pp = pp->next;
+                        pc = 0;
+                    }
+                } while (pp);
+            }
+            break;
+        }
+    }
+}
+
+/*
+ * prt_ptyinfo() -- print pseudoterminal information
+ */
+
+static void prt_ptyinfo(struct lsof_context *ctx, pxinfo_t *pp, /* peer info */
+                        int prt_edev, /* print the end point device file */
+                        int ps)       /* processing status:
+                                       *    0 == process immediately
+                                       *    1 == process later */
+{
+    struct lproc *ep; /* pseudoterminal endpoint process */
+    struct lfile *ef; /* pseudoterminal endpoint file */
+    int i;            /* temporary index */
+    char nma[1024];   /* name addition buffer */
+    char fd[FDLEN];
+
+    ep = &Lproc[pp->lpx];
+    ef = pp->lf;
+    fd_to_string(ef->fd_type, ef->fd_num, fd);
+    if (prt_edev) {
+        (void)snpf(nma, sizeof(nma) - 1, "->/dev/pts/%d %d,%.*s,%s%c",
+                   Lf->tty_index, ep->pid, CmdLim, ep->cmd, fd,
+                   access_to_char(ef->access));
+    } else {
+        (void)snpf(nma, sizeof(nma) - 1, "%d,%.*s,%s%c", ep->pid, CmdLim,
+                   ep->cmd, fd, access_to_char(ef->access));
+    }
+    (void)add_nma(ctx, nma, strlen(nma));
+    if (ps) {
+
+        /*
+         * Endpoint files have been selected, so mark this
+         * one for selection later. Set the type to PTY.
+         */
+        ef->chend = CHEND_PTY;
+        ep->ept |= EPT_PTY_END;
+    }
+}
+#endif /* defined(HASPTYEPT) */
+
+/* Convert lsof_fd_type and fd_num to string, sizeof(buf) should >= FDLEN */
+void fd_to_string(enum lsof_fd_type fd_type, int fd_num, char *buf) {
+    switch (fd_type) {
+    case LSOF_FD_NUMERIC:
+        /* strlen("TYPE") == 4, try to match width */
+        if (fd_num < 10000)
+            (void)snpf(buf, FDLEN, "%d", fd_num);
+        else
+            (void)snpf(buf, FDLEN, "*%03d", fd_num % 1000);
+        break;
+    case LSOF_FD_UNKNOWN:
+        (void)snpf(buf, FDLEN, "unk");
+        break;
+    case LSOF_FD_CWD:
+        (void)snpf(buf, FDLEN, "cwd");
+        break;
+    case LSOF_FD_ERROR:
+        (void)snpf(buf, FDLEN, "err");
+        break;
+    case LSOF_FD_NOFD:
+        (void)snpf(buf, FDLEN, "NOFD");
+        break;
+    case LSOF_FD_ROOT_DIR:
+        (void)snpf(buf, FDLEN, "rtd");
+        break;
+    case LSOF_FD_PARENT_DIR:
+        (void)snpf(buf, FDLEN, "pd");
+        break;
+    case LSOF_FD_PROGRAM_TEXT:
+        (void)snpf(buf, FDLEN, "txt");
+        break;
+    case LSOF_FD_LIBRARY_TEXT:
+        (void)snpf(buf, FDLEN, "ltx");
+        break;
+    case LSOF_FD_MEMORY:
+        (void)snpf(buf, FDLEN, "mem");
+        break;
+    case LSOF_FD_DELETED:
+        (void)snpf(buf, FDLEN, "DEL");
+        break;
+    case LSOF_FD_FILEPORT:
+        (void)snpf(buf, FDLEN, "fp.");
+        break;
+    case LSOF_FD_TASK_CWD:
+        (void)snpf(buf, FDLEN, "twd");
+        break;
+    case LSOF_FD_CTTY:
+        (void)snpf(buf, FDLEN, "ctty");
+        break;
+    case LSOF_FD_JAIL_DIR:
+        (void)snpf(buf, FDLEN, "jld");
+        break;
+    case LSOF_FD_VIRTUAL_8086:
+        (void)snpf(buf, FDLEN, "v86");
+        break;
+    case LSOF_FD_MERGE_386:
+        (void)snpf(buf, FDLEN, "m86");
+        break;
+    case LSOF_FD_MMAP_DEVICE:
+        (void)snpf(buf, FDLEN, "mmap");
+        break;
+    case LSOF_FD_LIBRARY_REF:
+        (void)snpf(buf, FDLEN, "L%02d", fd_num);
+        break;
+    case LSOF_FD_MMAP_UNKNOWN:
+        (void)snpf(buf, FDLEN, "M%02x", fd_num);
+        break;
+    case LSOF_FD_PREGION_UNKNOWN:
+        (void)snpf(buf, FDLEN, "R%02d", fd_num);
+        break;
+    default:
+        fprintf(stderr, "Unknown fd type: %d\n", (int)fd_type);
+        buf[0] = '\0';
+        break;
+    }
+}
\ No newline at end of file
diff --git a/lib/proto.h b/lib/proto.h
new file mode 100644
index 0000000..83dfb14
--- /dev/null
+++ b/lib/proto.h
@@ -0,0 +1,331 @@
+/*
+ * proto.h - common function prototypes 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: proto.h,v 1.39 2018/02/14 14:20:14 abe Exp $
+ */
+
+#if !defined(PROTO_H)
+#    define PROTO_H 1
+
+/*
+ * 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 */
+
+extern void add_nma(struct lsof_context *ctx, char *cp, int len);
+extern void alloc_lfile(struct lsof_context *ctx, enum lsof_fd_type fd_type,
+                        int num);
+extern void alloc_lproc(struct lsof_context *ctx, int pid, int pgid, int ppid,
+                        UID_ARG uid, char *cmd, int pss, int sf);
+extern void build_IPstates(struct lsof_context *ctx);
+extern void childx(struct lsof_context *ctx);
+extern void closefrom_shim(struct lsof_context *ctx, int low);
+extern int ck_fd_status(struct lsof_context *ctx, enum lsof_fd_type fd_type,
+                        int num);
+extern int ck_file_arg(struct lsof_context *ctx, int i, int ac, char *av[],
+                       int fv, int rs, struct stat *sbp,
+                       int accept_deleted_file);
+extern void ckkv(struct lsof_context *ctx, char *d, char *er, char *ev,
+                 char *ea);
+extern void clr_devtab(struct lsof_context *ctx);
+extern int compdev(COMP_P *a1, COMP_P *a2);
+extern int comppid(COMP_P *a1, COMP_P *a2);
+
+#    if defined(WILLDROPGID)
+extern void dropgid(struct lsof_context *ctx);
+#    endif /* defined(WILLDROPGID) */
+
+extern char *endnm(struct lsof_context *ctx, size_t *sz);
+extern int enter_cmd_rx(struct lsof_context *ctx, char *x);
+extern void enter_dev_ch(struct lsof_context *ctx, char *m);
+extern int enter_dir(struct lsof_context *ctx, char *d, int descend);
+
+#    if defined(HASEOPT)
+extern int enter_efsys(struct lsof_context *ctx, char *e, int rdlnk);
+#    endif /* defined(HASEOPT) */
+
+extern int enter_fd(struct lsof_context *ctx, char *f);
+extern int enter_network_address(struct lsof_context *ctx, char *na);
+extern int enter_id(struct lsof_context *ctx, enum IDType ty, char *p);
+extern void enter_IPstate(struct lsof_context *ctx, char *ty, char *nm, int nr);
+extern void enter_nm(struct lsof_context *ctx, char *m);
+
+#    if defined(HASTCPUDPSTATE)
+extern int enter_state_spec(struct lsof_context *ctx, char *ss);
+#    endif /* defined(HASTCPUDPSTATE) */
+
+extern int enter_cmd(struct lsof_context *ctx, char *opt, char *s);
+extern int enter_uid(struct lsof_context *ctx, char *us);
+extern void ent_inaddr(struct lsof_context *ctx, unsigned char *la, int lp,
+                       unsigned char *fa, int fp, int af);
+extern int examine_lproc(struct lsof_context *ctx);
+extern void Exit(struct lsof_context *ctx, enum ExitStatus xv) exiting;
+extern void Error(struct lsof_context *ctx) exiting;
+extern void find_ch_ino(struct lsof_context *ctx);
+
+#    if defined(HASEPTOPTS)
+extern void clear_pinfo(struct lsof_context *ctx);
+extern pxinfo_t *find_pepti(struct lsof_context *ctx, int pid, struct lfile *lf,
+                            pxinfo_t *pp);
+extern void process_pinfo(struct lsof_context *ctx, int f);
+extern void clear_psxmqinfo(struct lsof_context *ctx);
+extern pxinfo_t *find_psxmqinfo(struct lsof_context *ctx, int pid,
+                                struct lfile *lf, pxinfo_t *pp);
+extern void process_psxmqinfo(struct lsof_context *ctx, int f);
+#        if defined(HASUXSOCKEPT)
+extern void clear_uxsinfo(struct lsof_context *ctx);
+extern struct uxsin *find_uxsepti(struct lfile *lf);
+extern void process_uxsinfo(struct lsof_context *ctx, int f);
+#        endif /* defined(HASUXSOCKEPT) */
+#        if defined(HASPTYEPT)
+extern void clear_ptyinfo(struct lsof_context *ctx);
+extern void enter_ptmxi(struct lsof_context *ctx, int mn);
+extern pxinfo_t *find_ptyepti(struct lsof_context *ctx, int pid,
+                              struct lfile *lf, int m, pxinfo_t *pp);
+extern int is_pty_slave(int sm);
+extern int is_pty_ptmx(dev_t dev);
+extern void process_ptyinfo(struct lsof_context *ctx, int f);
+#        endif /* defined(HASPTYEPT) */
+extern void clear_evtfdinfo(struct lsof_context *ctx);
+extern void enter_evtfdinfo(struct lsof_context *ctx, int id);
+extern pxinfo_t *find_evtfdinfo(struct lsof_context *ctx, int pid,
+                                struct lfile *lf, pxinfo_t *pp);
+extern void process_evtfdinfo(struct lsof_context *ctx, int f);
+extern void clear_netsinfo(struct lsof_context *ctx);
+extern void process_netsinfo(struct lsof_context *ctx, int f);
+#        if defined(HASIPv6)
+extern void clear_nets6info(struct lsof_context *ctx);
+extern void process_nets6info(struct lsof_context *ctx, int f);
+#        endif /* defined(HASIPv6) */
+#    endif     /* defined(HASEPTOPTS) */
+
+extern void free_lproc(struct lproc *lp);
+extern void gather_proc_info(struct lsof_context *ctx);
+extern char *gethostnm(struct lsof_context *ctx, unsigned char *ia, int af);
+
+#    if !defined(GET_MAX_FD)
+/*
+ * This is not strictly a prototype, but GET_MAX_FD is the name of the
+ * function that, in lieu of getdtablesize(), returns the maximum file
+ * descriptor plus one (or file descriptor count).  GET_MAX_FD may be
+ * defined in the dialect's machine.h.  If it is not, the following
+ * selects getdtablesize().
+ */
+
+#        define GET_MAX_FD getdtablesize
+#    endif /* !defined(GET_MAX_FD) */
+
+extern int hashbyname(char *nm, int mod);
+extern void hashSfile(struct lsof_context *ctx);
+extern void initialize(struct lsof_context *ctx);
+extern int is_cmd_excl(struct lsof_context *ctx, char *cmd, short *pss,
+                       short *sf);
+extern int is_file_sel(struct lsof_context *ctx, struct lproc *lp,
+                       struct lfile *lf);
+extern int is_nw_addr(struct lsof_context *ctx, unsigned char *ia, int p,
+                      int af);
+
+#    if defined(HASTASKS)
+extern int is_proc_excl(struct lsof_context *ctx, int pid, int pgid,
+                        UID_ARG uid, short *pss, short *sf, int tid);
+#    else  /* !defined(HASTASKS) */
+extern int is_proc_excl(struct lsof_context *ctx, int pid, int pgid,
+                        UID_ARG uid, short *pss, short *sf);
+#    endif /* defined(HASTASKS) */
+
+extern int is_readable(struct lsof_context *ctx, char *path, int msg);
+extern int kread(struct lsof_context *ctx, KA_T addr, char *buf, READLEN_T len);
+extern void link_lfile(struct lsof_context *ctx);
+extern struct l_dev *lkupdev(struct lsof_context *ctx, dev_t *dev, dev_t *rdev,
+                             int i, int r);
+extern int main(int argc, char *argv[]);
+extern int lstatsafely(struct lsof_context *ctx, char *path, struct stat *buf);
+extern char *mkstrcpy(char *src, MALLOC_S *rlp);
+extern char *mkstrcat(char *s1, int l1, char *s2, int l2, char *s3, int l3,
+                      MALLOC_S *clp);
+extern int printdevname(struct lsof_context *ctx, dev_t *dev, dev_t *rdev,
+                        int f, int nty);
+extern void print_file(struct lsof_context *ctx);
+extern void print_init(struct lsof_context *ctx);
+extern void printname(struct lsof_context *ctx, int nl);
+extern char *print_kptr(KA_T kp, char *buf, size_t bufl);
+extern int print_proc(struct lsof_context *ctx);
+extern void fd_to_string(enum lsof_fd_type fd_type, int fd_num, char *buf);
+extern void printrawaddr(struct lsof_context *ctx, struct sockaddr *sa);
+extern void print_tcptpi(struct lsof_context *ctx, int nl);
+extern char *printuid(struct lsof_context *ctx, UID_ARG uid, int *ty);
+extern void printunkaf(struct lsof_context *ctx, int fam, int ty);
+extern char access_to_char(enum lsof_file_access_mode access);
+extern char lock_to_char(enum lsof_lock_mode access);
+extern void file_type_to_string(enum lsof_file_type type,
+                                uint32_t unknown_file_type_number, char *buf,
+                                size_t buf_len);
+extern char *printsockty(int ty);
+extern void process_file(struct lsof_context *ctx, KA_T fp);
+extern void process_node(struct lsof_context *ctx, KA_T f);
+extern char *Readlink(struct lsof_context *ctx, char *arg);
+extern void readdev(struct lsof_context *ctx, int skip);
+extern struct mounts *readmnt(struct lsof_context *ctx);
+extern void rereaddev(struct lsof_context *ctx);
+extern char *safepup(unsigned int c, int *cl);
+extern int safestrlen(char *sp, int flags);
+extern void safestrprtn(char *sp, int len, FILE *fs, int flags);
+extern void safestrprt(char *sp, FILE *fs, int flags);
+extern int statsafely(struct lsof_context *ctx, char *path, struct stat *buf);
+extern void stkdir(struct lsof_context *ctx, char *p);
+extern void usage(struct lsof_context *ctx, int err, int fh, int version);
+extern int util_strftime(char *fmtr, int fmtl, char *fmt);
+extern int vfy_dev(struct lsof_context *ctx, struct l_dev *dp);
+extern char *x2dev(char *s, dev_t *d);
+
+#    if defined(HASBLKDEV)
+extern void find_bl_ino(struct lsof_context *ctx);
+extern struct l_dev *lkupbdev(struct lsof_context *ctx, dev_t *dev, dev_t *rdev,
+                              int i, int r);
+extern int printbdevname(dev_t *dev, dev_t *rdev, int f);
+#    endif /* defined(HASBLKDEV) */
+
+#    if defined(HASCDRNODE)
+extern int readcdrnode(struct lsof_context *ctx, KA_T ca, struct cdrnode *c);
+#    endif /* defined(HASCDRNODE) */
+
+#    if defined(HASDCACHE)
+extern void alloc_dcache(struct lsof_context *ctx);
+extern void crc(char *b, int l, unsigned *s);
+extern void crdbld(void);
+extern int ctrl_dcache(struct lsof_context *ctx, char *p);
+extern int dcpath(struct lsof_context *ctx, int rw, int npw);
+extern int open_dcache(struct lsof_context *ctx, int m, int r, struct stat *sb);
+extern int read_dcache(struct lsof_context *ctx);
+extern int wr2DCfd(struct lsof_context *ctx, char *b, unsigned *c);
+extern void write_dcache(struct lsof_context *ctx);
+#    endif /* defined(HASDCACHE) */
+
+#    if defined(HASFIFONODE)
+extern int readfifonode(struct lsof_context *ctx, KA_T fa, struct fifonode *f);
+#    endif /* defined(HASFIFONODE) */
+
+#    if defined(HASFSTRUCT)
+extern char *print_fflags(struct lsof_context *ctx, long ffg, long pof);
+#    endif /* defined(HASFSTRUCT) */
+
+#    if defined(HASGNODE)
+extern int readgnode(struct lsof_context *ctx, KA_T ga, struct gnode *g);
+#    endif /* defined(HASGNODE) */
+
+#    if defined(HASKQUEUE)
+extern void process_kqueue(struct lsof_context *ctx, KA_T ka);
+#    endif /* defined(HASKQUEUE) */
+
+#    if defined(HASHSNODE)
+extern int readhsnode(struct lsof_context *ctx, KA_T ha, struct hsnode *h);
+#    endif /* defined(HASHSNODE) */
+
+#    if defined(HASINODE)
+extern int readinode(struct lsof_context *ctx, KA_T ia, struct inode *i);
+#    endif /* defined(HASINODE) */
+
+#    if defined(HASNCACHE)
+extern void ncache_load(struct lsof_context *ctx);
+extern char *ncache_lookup(struct lsof_context *ctx, char *buf, int blen,
+                           int *fp);
+#    endif /* defined(HASNCACHE) */
+
+#    if defined(HASNLIST)
+extern void build_Nl(struct lsof_context *ctx, struct drive_Nl *d);
+extern int get_Nl_value(struct lsof_context *ctx, char *nn, struct drive_Nl *d,
+                        KA_T *v);
+#    endif /* defined(HASNLIST) */
+
+#    if defined(HASPIPENODE)
+extern int readpipenode(struct lsof_context *ctx, KA_T pa, struct pipenode *p);
+#    endif /* defined(HASPIPENODE) */
+
+#    if defined(HASPRINTDEV)
+extern char *HASPRINTDEV(struct lfile *lf, dev_t *dev);
+#    endif /* defined(HASPRINTDEV) */
+
+#    if defined(HASPRINTINO)
+extern char *HASPRINTINO(struct lfile *lf);
+#    endif /* defined(HASPRINTINO) */
+
+#    if defined(HASPRINTNM)
+extern void HASPRINTNM(struct lsof_context *ctx, struct lfile *lf);
+#    endif /* defined(HASPRINTNM) */
+
+#    if defined(HASPRIVNMCACHE)
+extern int HASPRIVNMCACHE(struct lsof_context *ctx, struct lfile *lf);
+#    endif /* defined(HASPRIVNMCACHE) */
+
+#    if !defined(HASPRIVPRIPP)
+extern void printiproto(struct lsof_context *ctx, int p);
+#    endif /* !defined(HASPRIVPRIPP) */
+
+#    if defined(HASRNODE)
+extern int readrnode(struct lsof_context *ctx, KA_T ra, struct rnode *r);
+#    endif /* defined(HASRNODE) */
+
+#    if defined(HASSPECDEVD)
+extern void HASSPECDEVD(struct lsof_context *ctx, char *p, struct stat *s);
+#    endif /* defined(HASSPECDEVD) */
+
+#    if defined(HASSNODE)
+extern int readsnode(struct lsof_context *ctx, KA_T sa, struct snode *s);
+#    endif /* defined(HASSNODE) */
+
+#    if defined(HASSTREAMS)
+extern int readstdata(struct lsof_context *ctx, KA_T addr, struct stdata *buf);
+extern int readsthead(struct lsof_context *ctx, KA_T addr, struct queue *buf);
+extern int readstidnm(struct lsof_context *ctx, KA_T addr, char *buf,
+                      READLEN_T len);
+extern int readstmin(struct lsof_context *ctx, KA_T addr,
+                     struct module_info *buf);
+extern int readstqinit(struct lsof_context *ctx, KA_T addr, struct qinit *buf);
+#    endif /* defined(HASSTREAMS) */
+
+#    if defined(HASTMPNODE)
+extern int readtnode(struct lsof_context *ctx, KA_T ta, struct tmpnode *t);
+#    endif /* defined(HASTMPNODE) */
+
+#    if defined(HASVNODE)
+extern int readvnode(struct lsof_context *ctx, KA_T va, struct vnode *v);
+#    endif /* defined(HASVNODE) */
+
+#endif /* !defined(PROTO_H) */
diff --git a/lib/ptti.c b/lib/ptti.c
index 4ad13d9..e69de29 100644
--- a/lib/ptti.c
+++ b/lib/ptti.c
@@ -1,1369 +0,0 @@
-/*
- * ptti.c -- BSD style print_tcptpi() function for lsof library
- */
-
-
-/*
- * 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.
- */
-
-
-#include "../machine.h"
-
-#if	defined(USE_LIB_PRINT_TCPTPI)
-
-# if	!defined(lint)
-static char copyright[] =
-"@(#) Copyright 1997 Purdue Research Foundation.\nAll rights reserved.\n";
-# endif	/* !defined(lint) */
-
-#define	TCPSTATES			/* activate tcpstates[] */
-#include "../lsof.h"
-
-
-/*
- * build_IPstates() -- build the TCP and UDP state tables
- *
- * Note: this module does not support a UDP state table.
- */
-
-void
-build_IPstates()
-{
-
-/*
- * Set the TcpNstates global variable.
- */
-	TcpNstates = TCP_NSTATES;
-	TcpSt = (char **)&tcpstates;
-}
-
-
-/*
- * print_tcptpi() - print TCP/TPI info
- */
-
-void
-print_tcptpi(nl)
-	int nl;				/* 1 == '\n' required */
-{
-	int ps = 0;
-	int s;
-
-	if ((Ftcptpi & TCPTPI_STATE) && Lf->lts.type == 0) {
-	    if (Ffield)
-		(void) printf("%cST=", LSOF_FID_TCPTPI);
-	    else
-		putchar('(');
-	    if (!TcpNstates)
-		(void) build_IPstates();
-	    if ((s = Lf->lts.state.i) < 0 || s >= TcpNstates)
-		(void) printf("UNKNOWN_TCP_STATE_%d", s);
-	    else
-		(void) fputs(TcpSt[s], stdout);
-	    ps++;
-	    if (Ffield)
-		putchar(Terminator);
-	}
-
-#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_ACCEPTFILTER)
-		if (opt & SO_ACCEPTFILTER) {
-		    (void) printf("%cACCEPTFILTER", sep);
-		    opt &= ~SO_ACCEPTFILTER;
-		    sep = ',';
-		}
-# endif	/* defined(SO_ACCEPTFILTER) */
-
-# if	defined(SO_AUDIT)
-		if (opt & SO_AUDIT) {
-		    (void) printf("%cAUDIT", sep);
-		    opt &= ~SO_AUDIT;
-		    sep = ',';
-		}
-# endif	/* defined(SO_AUDIT) */
-
-# if	defined(SO_BINDANY)
-		if (opt & SO_BINDANY) {
-		    (void) printf("%cBINDANY", sep);
-		    opt &= ~SO_BINDANY;
-		    sep = ',';
-		}
-# endif	/* defined(SO_BINDANY) */
-
-# if	defined(SO_BINTIME)
-		if (opt & SO_BINTIME) {
-		    (void) printf("%cBINTIME", sep);
-		    opt &= ~SO_BINTIME;
-		    sep = ',';
-		}
-# endif	/* defined(SO_BINTIME) */
-
-# if	defined(SO_BROADCAST)
-		if (opt & SO_BROADCAST) {
-		    (void) printf("%cBROADCAST", sep);
-		    opt &= ~SO_BROADCAST;
-		    sep = ',';
-		}
-# endif	/* defined(SO_BROADCAST) */
-
-# if	defined(SO_CKSUMRECV)
-		if (opt & SO_CKSUMRECV) {
-		    (void) printf("%cCKSUMRECV", sep);
-		    opt &= ~SO_CKSUMRECV;
-		    sep = ',';
-		}
-# endif	/* defined(SO_CKSUMRECV) */
-
-# if	defined(SO_CLUA_IN_NOALIAS)
-		if (opt & SO_CLUA_IN_NOALIAS) {
-		    (void) printf("%cCLUA_IN_NOALIAS", sep);
-		    opt &= ~SO_CLUA_IN_NOALIAS;
-		    sep = ',';
-		}
-# endif	/* defined(SO_CLUA_IN_NOALIAS) */
-
-# if	defined(SO_CLUA_IN_NOLOCAL)
-		if (opt & SO_CLUA_IN_NOLOCAL) {
-		    (void) printf("%cCLUA_IN_NOLOCAL", sep);
-		    opt &= ~SO_CLUA_IN_NOLOCAL;
-		    sep = ',';
-		}
-# endif	/* defined(SO_CLUA_IN_NOLOCAL) */
-
-# 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_DONTTRUNC)
-		if (opt & SO_DONTTRUNC) {
-		    (void) printf("%cDONTTRUNC", sep);
-		    opt &= ~SO_DONTTRUNC;
-		    sep = ',';
-		}
-# endif	/* defined(SO_DONTTRUNC) */
-
-# if	defined(SO_EXPANDED_RIGHTS)
-		if (opt & SO_EXPANDED_RIGHTS) {
-		    (void) printf("%cEXPANDED_RIGHTS", sep);
-		    opt &= ~SO_EXPANDED_RIGHTS;
-		    sep = ',';
-		}
-# endif	/* defined(SO_EXPANDED_RIGHTS) */
-
-# 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_KERNACCEPT)
-		if (opt & SO_KERNACCEPT) {
-		    (void) printf("%cKERNACCEPT", sep);
-		    opt &= ~SO_KERNACCEPT;
-		    sep = ',';
-		}
-# endif	/* defined(SO_KERNACCEPT) */
-
-# if	defined(SO_IMASOCKET)
-		if (opt & SO_IMASOCKET) {
-		    (void) printf("%cIMASOCKET", sep);
-		    opt &= ~SO_IMASOCKET;
-		    sep = ',';
-		}
-# endif	/* defined(SO_IMASOCKET) */
-
-# 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_PAIRABLE)
-		if (opt & SO_PAIRABLE) {
-		    (void) printf("%cPAIRABLE", sep);
-		    opt &= ~SO_PAIRABLE;
-		    sep = ',';
-		}
-# endif	/* defined(SO_PAIRABLE) */
-
-# if	defined(SO_RESVPORT)
-		if (opt & SO_RESVPORT) {
-		    (void) printf("%cRESVPORT", sep);
-		    opt &= ~SO_RESVPORT;
-		    sep = ',';
-		}
-# endif	/* defined(SO_RESVPORT) */
-
-# if	defined(SO_NOREUSEADDR)
-		if (opt & SO_NOREUSEADDR) {
-		    (void) printf("%cNOREUSEADDR", sep);
-		    opt &= ~SO_NOREUSEADDR;
-		    sep = ',';
-		}
-# endif	/* defined(SO_NOREUSEADDR) */
-
-# if	defined(SO_NOSIGPIPE)
-		if (opt & SO_NOSIGPIPE) {
-		    (void) printf("%cNOSIGPIPE", sep);
-		    opt &= ~SO_NOSIGPIPE;
-		    sep = ',';
-		}
-# endif	/* defined(SO_NOSIGPIPE) */
-
-# 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 (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	defined(SO_REUSEALIASPORT)
-		if (opt & SO_REUSEALIASPORT) {
-		    (void) printf("%cREUSEALIASPORT", sep);
-		    opt &= ~SO_REUSEALIASPORT;
-		    sep = ',';
-		}
-# endif	/* defined(SO_REUSEALIASPORT) */
-
-# if	defined(SO_REUSEPORT)
-		if (opt & SO_REUSEPORT) {
-		    (void) printf("%cREUSEPORT", sep);
-		    opt &= ~SO_REUSEPORT;
-		    sep = ',';
-		}
-# endif	/* defined(SO_REUSEPORT) */
-
-# if	defined(SO_REUSERAD)
-		if (opt & SO_REUSERAD) {
-		    (void) printf("%cREUSERAD", sep);
-		    opt &= ~SO_REUSERAD;
-		    sep = ',';
-		}
-# endif	/* defined(SO_REUSERAD) */
-
-# if	defined(SO_SECURITY_REQUEST)
-		if (opt & SO_SECURITY_REQUEST) {
-		    (void) printf("%cSECURITY_REQUEST", sep);
-		    opt &= ~SO_SECURITY_REQUEST;
-		    sep = ',';
-		}
-# endif	/* defined(SO_SECURITY_REQUEST) */
-
-		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_UMC)
-		if (opt & SO_UMC) {
-		    (void) printf("%cUMC", sep);
-		    opt &= ~SO_UMC;
-		    sep = ',';
-		}
-# endif	/* defined(SO_UMC) */
-
-# if	defined(SO_USE_IFBUFS)
-		if (opt & SO_USE_IFBUFS) {
-		    (void) printf("%cUSE_IFBUFS", sep);
-		    opt &= ~SO_USE_IFBUFS;
-		    sep = ',';
-		}
-# endif	/* defined(SO_USE_IFBUFS) */
-
-# if	defined(SO_USELOOPBACK)
-		if (opt & SO_USELOOPBACK) {
-		    (void) printf("%cUSELOOPBACK", sep);
-		    opt &= ~SO_USELOOPBACK;
-		    sep = ',';
-		}
-# endif	/* defined(SO_USELOOPBACK) */
-
-# if	defined(SO_WANTMORE)
-		if (opt & SO_WANTMORE) {
-		    (void) printf("%cWANTMORE", sep);
-		    opt &= ~SO_WANTMORE;
-		    sep = ',';
-		}
-# endif	/* defined(SO_WANTMORE) */
-
-# if	defined(SO_WANTOOBFLAG)
-		if (opt & SO_WANTOOBFLAG) {
-		    (void) printf("%cWANTOOBFLAG", sep);
-		    opt &= ~SO_WANTOOBFLAG;
-		    sep = ',';
-		}
-# endif	/* defined(SO_WANTOOBFLAG) */
-
-		if (opt)
-		    (void) printf("%cUNKNOWN=%#x", sep, opt);
-		if (Ffield)
-		    putchar(Terminator);
-	    }
-	}
-#endif	/* defined(HASSOOPT) */
-
-#if	defined(HASSOSTATE)
-	if (Ftcptpi & TCPTPI_FLAGS) {
-	    unsigned 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_BOUND)
-		if (ss & SS_BOUND) {
-		    (void) printf("%cBOUND", sep);
-		    ss &= ~SS_BOUND;
-		    sep = ',';
-		}
-# endif	/* defined(SS_BOUND) */
-
-# if	defined(HASSBSTATE)
-#  if	defined(SBS_CANTRCVMORE)
-		if (Lf->lts.sbs_rcv & SBS_CANTRCVMORE) {
-		    (void) printf("%cCANTRCVMORE", sep);
-		    Lf->lts.sbs_rcv &= ~SBS_CANTRCVMORE;
-		    sep = ',';
-		}
-#  endif	/* defined(SBS_CANTRCVMORE) */
-
-#  if	defined(SBS_CANTSENDMORE)
-		if (Lf->lts.sbs_snd & SBS_CANTSENDMORE) {
-		    (void) printf("%cCANTSENDMORE", sep);
-		    Lf->lts.sbs_snd &= ~SBS_CANTSENDMORE;
-		    sep = ',';
-		}
-#  endif	/* defined(SS_CANTSENDMORE) */
-# else	/* !defined(HASSBSTATE) */
-
-#  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) */
-# endif	/* defined(HASSBSTATE) */
-
-# if	defined(SS_COMP)
-		if (ss & SS_COMP) {
-		    (void) printf("%cCOMP", sep);
-		    ss &= ~SS_COMP;
-		    sep = ',';
-		}
-# endif	/* defined(SS_COMP) */
-
-# if	defined(SS_CONNECTOUT)
-		if (ss & SS_CONNECTOUT) {
-		    (void) printf("%cCONNECTOUT", sep);
-		    ss &= ~SS_CONNECTOUT;
-		    sep = ',';
-		}
-# endif	/* defined(SS_CONNECTOUT) */
-
-# if	defined(SS_HIPRI)
-		if (ss & SS_HIPRI) {
-		    (void) printf("%cHIPRI", sep);
-		    ss &= ~SS_HIPRI;
-		    sep = ',';
-		}
-# endif	/* defined(SS_HIPRI) */
-
-# if	defined(SS_IGNERR)
-		if (ss & SS_IGNERR) {
-		    (void) printf("%cIGNERR", sep);
-		    ss &= ~SS_IGNERR;
-		    sep = ',';
-		}
-# endif	/* defined(SS_IGNERR) */
-
-# if	defined(SS_INCOMP)
-		if (ss & SS_INCOMP) {
-		    (void) printf("%cINCOMP", sep);
-		    ss &= ~SS_INCOMP;
-		    sep = ',';
-		}
-# endif	/* defined(SS_INCOMP) */
-
-# if	defined(SS_IOCWAIT)
-		if (ss & SS_IOCWAIT) {
-		    (void) printf("%cIOCWAIT", sep);
-		    ss &= ~SS_IOCWAIT;
-		    sep = ',';
-		}
-# endif	/* defined(SS_IOCWAIT) */
-
-# if	defined(SS_ISCONFIRMING)
-		if (ss & SS_ISCONFIRMING) {
-		    (void) printf("%cISCONFIRMING", sep);
-		    ss &= ~SS_ISCONFIRMING;
-		    sep = ',';
-		}
-# endif	/* defined(SS_ISCONFIRMING) */
-
-# 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_MORETOSEND)
-		if (ss & SS_MORETOSEND) {
-		    (void) printf("%cMORETOSEND", sep);
-		    ss &= ~SS_MORETOSEND;
-		    sep = ',';
-		}
-# endif	/* defined(SS_MORETOSEND) */
-
-# if	defined(SS_NBIO)
-		if (ss & SS_NBIO) {
-		    (void) printf("%cNBIO", sep);
-		    ss &= ~SS_NBIO;
-		    sep = ',';
-		}
-# endif	/* defined(SS_NBIO) */
-
-# if	defined(SS_NOCONN)
-		if (ss & SS_NOCONN) {
-		    (void) printf("%cNOCONN", sep);
-		    ss &= ~SS_NOCONN;
-		    sep = ',';
-		}
-# endif	/* defined(SS_NOCONN) */
-
-# if	defined(SS_NODELETE)
-		if (ss & SS_NODELETE) {
-		    (void) printf("%cNODELETE", sep);
-		    ss &= ~SS_NODELETE;
-		    sep = ',';
-		}
-# endif	/* defined(SS_NODELETE) */
-
-# if	defined(SS_NOFDREF)
-		if (ss & SS_NOFDREF) {
-		    (void) printf("%cNOFDREF", sep);
-		    ss &= ~SS_NOFDREF;
-		    sep = ',';
-		}
-# endif	/* defined(SS_NOFDREF) */
-
-# 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_PRIV)
-		if (ss & SS_PRIV) {
-		    (void) printf("%cPRIV", sep);
-		    ss &= ~SS_PRIV;
-		    sep = ',';
-		}
-# endif	/* defined(SS_PRIV) */
-
-# if	defined(SS_QUEUE)
-		if (ss & SS_QUEUE) {
-		    (void) printf("%cQUEUE", sep);
-		    ss &= ~SS_QUEUE;
-		    sep = ',';
-		}
-# endif	/* defined(SS_QUEUE) */
-
-# if	defined(HASSBSTATE)
-#  if	defined(SBS_RCVATMARK)
-		if (Lf->lts.sbs_rcv & SBS_RCVATMARK) {
-		    (void) printf("%cRCVATMARK", sep);
-		    Lf->lts.sbs_rcv &= ~SBS_RCVATMARK;
-		    sep = ',';
-		}
-#  endif	/* defined(SBS_RCVATMARK) */
-
-# else	/* !defined(HASSBSTATE) */
-#  if	defined(SS_RCVATMARK)
-		if (ss & SS_RCVATMARK) {
-		    (void) printf("%cRCVATMARK", sep);
-		    ss &= ~SS_RCVATMARK;
-		    sep = ',';
-		}
-#  endif	/* defined(SS_RCVATMARK) */
-# endif	/* defined(HASSBSTATE) */
-
-# if	defined(SS_READWAIT)
-		if (ss & SS_READWAIT) {
-		    (void) printf("%cREADWAIT", sep);
-		    ss &= ~SS_READWAIT;
-		    sep = ',';
-		}
-# endif	/* defined(SS_READWAIT) */
-
-# 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_SIGREAD)
-		if (ss & SS_SIGREAD) {
-		    (void) printf("%cSIGREAD", sep);
-		    ss &= ~SS_SIGREAD;
-		    sep = ',';
-		}
-# endif	/* defined(SS_SIGREAD) */
-
-# if	defined(SS_SIGWRITE)
-		if (ss & SS_SIGWRITE) {
-		    (void) printf("%cSIGWRITE", sep);
-		    ss &= ~SS_SIGWRITE;
-		    sep = ',';
-		}
-# endif	/* defined(SS_SIGWRITE) */
-
-# if	defined(SS_SPLICED)
-		if (ss & SS_SPLICED) {
-		    (void) printf("%cSPLICED", sep);
-		    ss &= ~SS_SPLICED;
-		    sep = ',';
-		}
-# endif	/* defined(SS_SPLICED) */
-
-# if	defined(SS_WRITEWAIT)
-		if (ss & SS_WRITEWAIT) {
-		    (void) printf("%cWRITEWAIT", sep);
-		    ss &= ~SS_WRITEWAIT;
-		    sep = ',';
-		}
-# endif	/* defined(SS_WRITEWAIT) */
-
-# 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_CANT_TXSACK)
-		if (topt & TF_CANT_TXSACK) {
-		    (void) printf("%cCANT_TXSACK", sep);
-		    topt &= ~TF_CANT_TXSACK;
-		    sep = ',';
-		}
-# endif	/* defined(TF_CANT_TXSACK) */
-
-# if	defined(TF_DEAD)
-		if (topt & TF_DEAD) {
-		    (void) printf("%cDEAD", sep);
-		    topt &= ~TF_DEAD;
-		    sep = ',';
-		}
-# endif	/* defined(TF_DEAD) */
-
-# if	defined(TF_DELACK)
-		if (topt & TF_DELACK) {
-		    (void) printf("%cDELACK", sep);
-		    topt &= ~TF_DELACK;
-		    sep = ',';
-		}
-# endif	/* defined(TF_DELACK) */
-
-# if	defined(TF_DELAY_ACK)
-		if (topt & TF_DELAY_ACK) {
-		    (void) printf("%cDELAY_ACK", sep);
-		    topt &= ~TF_DELAY_ACK;
-		    sep = ',';
-		}
-# endif	/* defined(TF_DELAY_ACK) */
-
-# if	defined(TF_DISABLE_ECN)
-		if (topt & TF_DISABLE_ECN) {
-		    (void) printf("%cDISABLE_ECN", sep);
-		    topt &= ~TF_DISABLE_ECN;
-		    sep = ',';
-		}
-# endif	/* defined(TF_DISABLE_ECN) */
-
-# if	defined(TF_ECN)
-		if (topt & TF_ECN) {
-		    (void) printf("%cECN", sep);
-		    topt &= ~TF_ECN;
-		    sep = ',';
-		}
-# endif	/* defined(TF_ECN) */
-
-# if	defined(TF_ECN_PERMIT)
-		if (topt & TF_ECN_PERMIT) {
-		    (void) printf("%cECN_PERMIT", sep);
-		    topt &= ~TF_ECN_PERMIT;
-		    sep = ',';
-		}
-# endif	/* defined(TF_ECN_PERMIT) */
-
-# if	defined(TF_FASTRECOVERY)
-		if (topt & TF_FASTRECOVERY) {
-		    (void) printf("%cFASTRECOVERY", sep);
-		    topt &= ~TF_FASTRECOVERY;
-		    sep = ',';
-		}
-# endif	/* defined(TF_FASTRECOVERY) */
-
-# if	defined(TF_FASTRXMT_PHASE)
-		if (topt & TF_FASTRXMT_PHASE) {
-		    (void) printf("%cFASTRXMT_PHASE", sep);
-		    topt &= ~TF_FASTRXMT_PHASE;
-		    sep = ',';
-		}
-# endif	/* defined(TF_FASTRXMT_PHASE) */
-
-# 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_IGNR_RXSACK)
-		if (topt & TF_IGNR_RXSACK) {
-		    (void) printf("%cIGNR_RXSACK", sep);
-		    topt &= ~TF_IGNR_RXSACK;
-		    sep = ',';
-		}
-# endif	/* defined(TF_IGNR_RXSACK) */
-
-# if	defined(TF_IOLOCK)
-		if (topt & TF_IOLOCK) {
-		    (void) printf("%cIOLOCK", sep);
-		    topt &= ~TF_IOLOCK;
-		    sep = ',';
-		}
-# endif	/* defined(TF_IOLOCK) */
-
-# if	defined(TF_LARGESEND)
-		if (topt & TF_LARGESEND) {
-		    (void) printf("%cLARGESEND", sep);
-		    topt &= ~TF_LARGESEND;
-		    sep = ',';
-		}
-# endif	/* defined(TF_LARGESEND) */
-
-# if	defined(TF_LASTIDLE)
-		if (topt & TF_LASTIDLE) {
-		    (void) printf("%cLASTIDLE", sep);
-		    topt &= ~TF_LASTIDLE;
-		    sep = ',';
-		}
-# endif	/* defined(TF_LASTIDLE) */
-
-# if	defined(TF_LQ_OVERFLOW)
-		if (topt & TF_LQ_OVERFLOW) {
-		    (void) printf("%cLQ_OVERFLOW", sep);
-		    topt &= ~TF_LQ_OVERFLOW;
-		    sep = ',';
-		}
-# endif	/* defined(TF_LQ_OVERFLOW) */
-
-		if (Lf->lts.msss) {
-		    (void) printf("%cMSS=%lu", sep, Lf->lts.mss);
-		    sep = ',';
-		}
-
-# if	defined(TF_MORETOCOME)
-		if (topt & TF_MORETOCOME) {
-		    (void) printf("%cMORETOCOME", sep);
-		    topt &= ~TF_MORETOCOME;
-		    sep = ',';
-		}
-# endif	/* defined(TF_MORETOCOME) */
-
-# if	defined(TF_NEEDACK)
-		if (topt & TF_NEEDACK) {
-		    (void) printf("%cNEEDACK", sep);
-		    topt &= ~TF_NEEDACK;
-		    sep = ',';
-		}
-# endif	/* defined(TF_NEEDACK) */
-
-# if	defined(TF_NEEDCLOSE)
-		if (topt & TF_NEEDCLOSE) {
-		    (void) printf("%cNEEDCLOSE", sep);
-		    topt &= ~TF_NEEDCLOSE;
-		    sep = ',';
-		}
-# endif	/* defined(TF_NEEDCLOSE) */
-
-# if	defined(TF_NEEDFIN)
-		if (topt & TF_NEEDFIN) {
-		    (void) printf("%cNEEDFIN", sep);
-		    topt &= ~TF_NEEDFIN;
-		    sep = ',';
-		}
-# endif	/* defined(TF_NEEDFIN) */
-
-# 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_NEEDSYN)
-		if (topt & TF_NEEDSYN) {
-		    (void) printf("%cNEEDSYN", sep);
-		    topt &= ~TF_NEEDSYN;
-		    sep = ',';
-		}
-# endif	/* defined(TF_NEEDSYN) */
-
-# if	defined(TF_NEEDTIMER)
-		if (topt & TF_NEEDTIMER) {
-		    (void) printf("%cNEEDTIMER", sep);
-		    topt &= ~TF_NEEDTIMER;
-		    sep = ',';
-		}
-# endif	/* defined(TF_NEEDTIMER) */
-
-# if	defined(TF_NEWRENO_RXMT)
-		if (topt & TF_NEWRENO_RXMT) {
-		    (void) printf("%cNEWRENO_RXMT", sep);
-		    topt &= ~TF_NEWRENO_RXMT;
-		    sep = ',';
-		}
-# endif	/* defined(TF_NEWRENO_RXMT) */
-
-# 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_NOPUSH)
-		if (topt & TF_NOPUSH) {
-		    (void) printf("%cNOPUSH", sep);
-		    topt &= ~TF_NOPUSH;
-		    sep = ',';
-		}
-# endif	/* defined(TF_NOPUSH) */
-
-# if	defined(TF_NO_PMTU)
-		if (topt & TF_NO_PMTU) {
-		    (void) printf("%cNO_PMTU", sep);
-		    topt &= ~TF_NO_PMTU;
-		    sep = ',';
-		}
-# endif	/* defined(TF_NO_PMTU) */
-
-# if	defined(TF_RAW)
-		if (topt & TF_RAW) {
-		    (void) printf("%cRAW", sep);
-		    topt &= ~TF_RAW;
-		    sep = ',';
-		}
-# endif	/* defined(TF_RAW) */
-
-# if	defined(TF_RCVD_CC)
-		if (topt & TF_RCVD_CC) {
-		    (void) printf("%cRCVD_CC", sep);
-		    topt &= ~TF_RCVD_CC;
-		    sep = ',';
-		}
-# endif	/* defined(TF_RCVD_CC) */
-
-# 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_CE)
-		if (topt & TF_RCVD_CE) {
-		    (void) printf("%cRCVD_CE", sep);
-		    topt &= ~TF_RCVD_CE;
-		    sep = ',';
-		}
-# endif	/* defined(TF_RCVD_CE) */
-
-# if	defined(TF_RCVD_TS)
-		if (topt & TF_RCVD_TS) {
-		    (void) printf("%cRCVD_TS", sep);
-		    topt &= ~TF_RCVD_TS;
-		    sep = ',';
-		}
-# endif	/* defined(TF_RCVD_TS) */
-
-# 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_RCVD_WS)
-		if (topt & TF_RCVD_WS) {
-		    (void) printf("%cRCVD_WS", sep);
-		    topt &= ~TF_RCVD_WS;
-		    sep = ',';
-		}
-# endif	/* defined(TF_RCVD_WS) */
-
-# if	defined(TF_REASSEMBLING)
-		if (topt & TF_REASSEMBLING) {
-		    (void) printf("%cREASSEMBLING", sep);
-		    topt &= ~TF_REASSEMBLING;
-		    sep = ',';
-		}
-# endif	/* defined(TF_REASSEMBLING) */
-
-# if	defined(TF_REQ_CC)
-		if (topt & TF_REQ_CC) {
-		    (void) printf("%cREQ_CC", sep);
-		    topt &= ~TF_REQ_CC;
-		    sep = ',';
-		}
-# endif	/* defined(TF_REQ_CC) */
-
-# 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_RFC1323)
-		if (topt & TF_RFC1323) {
-		    (void) printf("%cRFC1323", sep);
-		    topt &= ~TF_RFC1323;
-		    sep = ',';
-		}
-# endif	/* defined(TF_RFC1323) */
-
-# if	defined(TF_RXWIN0SENT)
-		if (topt & TF_RXWIN0SENT) {
-		    (void) printf("%cRXWIN0SENT", sep);
-		    topt &= ~TF_RXWIN0SENT;
-		    sep = ',';
-		}
-# endif	/* defined(TF_RXWIN0SENT) */
-
-# if	defined(TF_SACK_GENERATE)
-		if (topt & TF_SACK_GENERATE) {
-		    (void) printf("%cSACK_GENERATE", sep);
-		    topt &= ~TF_SACK_GENERATE;
-		    sep = ',';
-		}
-# endif	/* defined(TF_SACK_GENERATE) */
-
-# 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_SACK_PROCESS)
-		if (topt & TF_SACK_PROCESS) {
-		    (void) printf("%cSACK_PROCESS", sep);
-		    topt &= ~TF_SACK_PROCESS;
-		    sep = ',';
-		}
-# endif	/* defined(TF_SACK_PROCESS) */
-
-# if	defined(TF_SEND)
-		if (topt & TF_SEND) {
-		    (void) printf("%cSEND", sep);
-		    topt &= ~TF_SEND;
-		    sep = ',';
-		}
-# endif	/* defined(TF_SEND) */
-
-# if	defined(TF_SEND_AND_DISCONNECT)
-		if (topt & TF_SEND_AND_DISCONNECT) {
-		    (void) printf("%cSEND_AND_DISCONNECT", sep);
-		    topt &= ~TF_SEND_AND_DISCONNECT;
-		    sep = ',';
-		}
-# endif	/* defined(TF_SEND_AND_DISCONNECT) */
-
-# if	defined(TF_SENDCCNEW)
-		if (topt & TF_SENDCCNEW) {
-		    (void) printf("%cSENDCCNEW", sep);
-		    topt &= ~TF_SENDCCNEW;
-		    sep = ',';
-		}
-# endif	/* defined(TF_SENDCCNEW) */
-
-# if	defined(TF_SEND_CWR)
-		if (topt & TF_SEND_CWR) {
-		    (void) printf("%cSEND_CWR", sep);
-		    topt &= ~TF_SEND_CWR;
-		    sep = ',';
-		}
-# endif	/* defined(TF_SEND_CWR) */
-
-# if	defined(TF_SEND_ECHO)
-		if (topt & TF_SEND_ECHO) {
-		    (void) printf("%cSEND_ECHO", sep);
-		    topt &= ~TF_SEND_ECHO;
-		    sep = ',';
-		}
-# endif	/* defined(TF_SEND_ECHO) */
-
-# if	defined(TF_SEND_TSTMP)
-		if (topt & TF_SEND_TSTMP) {
-		    (void) printf("%cSEND_TSTMP", sep);
-		    topt &= ~TF_SEND_TSTMP;
-		    sep = ',';
-		}
-# endif	/* defined(TF_SEND_TSTMP) */
-
-# if	defined(TF_SENTFIN)
-		if (topt & TF_SENTFIN) {
-		    (void) printf("%cSENTFIN", sep);
-		    topt &= ~TF_SENTFIN;
-		    sep = ',';
-		}
-# endif	/* defined(TF_SENTFIN) */
-
-# if	defined(TF_SENT_TS)
-		if (topt & TF_SENT_TS) {
-		    (void) printf("%cSENT_TS", sep);
-		    topt &= ~TF_SENT_TS;
-		    sep = ',';
-		}
-# endif	/* defined(TF_SENT_TS) */
-
-# if	defined(TF_SENT_WS)
-		if (topt & TF_SENT_WS) {
-		    (void) printf("%cSENT_WS", sep);
-		    topt &= ~TF_SENT_WS;
-		    sep = ',';
-		}
-# endif	/* defined(TF_SENT_WS) */
-
-# if	defined(TF_SIGNATURE)
-		if (topt & TF_SIGNATURE) {
-		    (void) printf("%cSIGNATURE", sep);
-		    topt &= ~TF_SIGNATURE;
-		    sep = ',';
-		}
-# endif	/* defined(TF_SIGNATURE) */
-
-# if	defined(TF_SLOWLINK)
-		if (topt & TF_SLOWLINK) {
-		    (void) printf("%cSLOWLINK", sep);
-		    topt &= ~TF_SLOWLINK;
-		    sep = ',';
-		}
-# endif	/* defined(TF_SLOWLINK) */
-
-# if	defined(TF_STDURG)
-		if (topt & TF_STDURG) {
-		    (void) printf("%cSTDURG", sep);
-		    topt &= ~TF_STDURG;
-		    sep = ',';
-		}
-# endif	/* defined(TF_STDURG) */
-
-# if	defined(TF_SYN_REXMT)
-		if (topt & TF_SYN_REXMT) {
-		    (void) printf("%cSYN_REXMT", sep);
-		    topt &= ~TF_SYN_REXMT;
-		    sep = ',';
-		}
-# endif	/* defined(TF_SYN_REXMT) */
-
-# if	defined(TF_UIOMOVED)
-		if (topt & TF_UIOMOVED) {
-		    (void) printf("%cUIOMOVED", sep);
-		    topt &= ~TF_UIOMOVED;
-		    sep = ',';
-		}
-# endif	/* defined(TF_UIOMOVED) */
-
-# if	defined(TF_USE_SCALE)
-		if (topt & TF_USE_SCALE) {
-		    (void) printf("%cUSE_SCALE", sep);
-		    topt &= ~TF_USE_SCALE;
-		    sep = ',';
-		}
-# endif	/* defined(TF_USE_SCALE) */
-
-# if	defined(TF_WASIDLE)
-		if (topt & TF_WASIDLE) {
-		    (void) printf("%cWASIDLE", sep);
-		    topt &= ~TF_WASIDLE;
-		    sep = ',';
-		}
-# endif	/* defined(TF_WASIDLE) */
-
-# if	defined(TF_WASFRECOVERY)
-		if (topt & TF_WASFRECOVERY) {
-		    (void) printf("%cWASFRECOVERY", sep);
-		    topt &= ~TF_WASFRECOVERY;
-		    sep = ',';
-		}
-# endif	/* defined(TF_WASFRECOVERY) */
-
-# if	defined(TF_WILL_SACK)
-		if (topt & TF_WILL_SACK) {
-		    (void) printf("%cWILL_SACK", sep);
-		    topt &= ~TF_WILL_SACK;
-		    sep = ',';
-		}
-# endif	/* defined(TF_WILL_SACK) */
-
-		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 (ps && !Ffield)
-	    putchar(')');
-	if (nl)
-	    putchar('\n');
-}
-#else	/* !defined(USE_LIB_PRINT_TCPTPI) */
-char ptti_d1[] = "d"; char *ptti_d2 = ptti_d1;
-#endif	/* defined(USE_LIB_PRINT_TCPTPI) */
diff --git a/lib/rdev.c b/lib/rdev.c
index 5cb842c..96a5297 100644
--- a/lib/rdev.c
+++ b/lib/rdev.c
@@ -2,7 +2,6 @@
  * rdev.c -- readdev() function for lsof library
  */
 
-
 /*
  * Copyright 1997 Purdue Research Foundation, West Lafayette, Indiana
  * 47907.  All rights reserved.
@@ -29,21 +28,13 @@
  * 4. This notice may not be removed or altered.
  */
 
+#include "common.h"
+#include "machine.h"
 
-#include "../machine.h"
-
-#if	defined(USE_LIB_READDEV)
-
-# if	!defined(lint)
-static char copyright[] =
-"@(#) Copyright 1997 Purdue Research Foundation.\nAll rights reserved.\n";
-# endif	/* !defined(lint) */
-
-#include "../lsof.h"
-
-
-_PROTOTYPE(static int rmdupdev,(struct l_dev ***dp, int n, char *nm));
+#if defined(USE_LIB_READDEV)
 
+static int rmdupdev(struct lsof_context *ctx, struct l_dev ***dp, int n,
+                    char *nm);
 
 /*
  * To use this source file:
@@ -98,426 +89,403 @@ _PROTOTYPE(static int rmdupdev,(struct l_dev ***dp, int n, char *nm));
  *    functions.)
  */
 
+#    if !defined(RDEV_EXPDEV)
+#        define RDEV_EXPDEV(n) (n)
+#    endif /* !defined(RDEV_EXPDEV) */
 
-# if	!defined(RDEV_EXPDEV)
-#define	RDEV_EXPDEV(n)		(n)
-# endif	/* !defined(RDEV_EXPDEV) */
-
-# if	!defined(RDEV_STATFN)
-#  if	defined(USE_STAT)
-#define	RDEV_STATFN	stat
-#  else	/* !defined(USE_STAT) */
-#define	RDEV_STATFN	lstat
-#  endif	/* defined(USE_STAT) */
-# endif	/* !defined(RDEV_STATFN) */
-
+#    if !defined(RDEV_STATFN)
+#        if defined(USE_STAT)
+#            define RDEV_STATFN stat
+#        else /* !defined(USE_STAT) */
+#            define RDEV_STATFN lstat
+#        endif /* defined(USE_STAT) */
+#    endif     /* !defined(RDEV_STATFN) */
 
 /*
  * readdev() - read device names, modes and types
  */
 
-void
-readdev(skip)
-	int skip;			/* skip device cache read if 1 */
+void readdev(struct lsof_context *ctx,
+             int skip) /* skip device cache read if 1 */
 {
 
-# if	defined(HAS_STD_CLONE) && HAS_STD_CLONE==1
-	struct clone *c;
-# endif	/* defined(HAS_STD_CLONE) && HAS_STD_CLONE==1 */
-
-# if	defined(HASDCACHE)
-	int dcrd;
-# endif	/* defined(HASDCACHE) */
-
-	DIR *dfp;
-	int dnamlen;
-	struct DIRTYPE *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 (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) */
-
-	Dstkn = Dstkx = 0;
-	Dstk = (char **)NULL;
-	(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);
-		Error();
-	    }
-	    (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	defined(HASDNAMLEN)
-		dnamlen = (int)dp->d_namlen;
-# else	/* !defined(HASDNAMLEN) */
-		dnamlen = (int)strlen(dp->d_name);
-# endif	/* defined(HASDNAMLEN) */
-
-		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);
-		    Error();
-		}
-		if (RDEV_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) {
-		    (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);
-			    Error();
-			}
-		    }
-		    Devtp[i].rdev = RDEV_EXPDEV(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);
-			Error();
-		    }
-		    Devtp[i].v = 0;
-
-# if	defined(HAS_STD_CLONE) && HAS_STD_CLONE==1
-		    if (HAVECLONEMAJ && GET_MAJ_DEV(Devtp[i].rdev) == CLONEMAJ)
-		    {
-
-		    /*
-		     * Record clone device information.
-		     */
-			if (!(c = (struct clone *)malloc(sizeof(struct clone))))
-			{
-			    (void) fprintf(stderr,
-				"%s: no space for clone device: ", Pn);
-			    safestrprt(fp, stderr, 1);
-			    Error();
-			}
-			c->dx = i;
-			c->next = Clone;
-			Clone = c;
-		    }
-# endif	/* defined(HAS_STD_CLONE) && HAS_STD_CLONE==1 */
-
-		    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);
-			    Error();
-			}
-		    }
-		    BDevtp[j].name = fp;
-		    fp = (char *)NULL;
-		    BDevtp[j].inode = (INODETYPE)sb.st_ino;
-		    BDevtp[j].rdev = RDEV_EXPDEV(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;
-	}
-	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);
-		Error();
-	    }
-	    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);
-		Error();
-	    }
-	    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);
-	    Error();
-	}
-
-# if	defined(HASDCACHE)
-/*
- * Write device cache file, as required.
- */
-	if (DCstate == 1 || (DCstate == 3 && dcrd))
-	    write_dcache();
-# endif	/* defined(HASDCACHE) */
-
+#    if defined(HAS_STD_CLONE) && HAS_STD_CLONE == 1
+    struct clone *c;
+#    endif /* defined(HAS_STD_CLONE) && HAS_STD_CLONE==1 */
+
+#    if defined(HASDCACHE)
+    int dcrd;
+#    endif /* defined(HASDCACHE) */
+
+    DIR *dfp;
+    int dnamlen;
+    struct DIRTYPE *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 (Sdev)
+        return;
+
+#    if defined(HASDCACHE)
+    /*
+     * Read device cache, as directed.
+     */
+    if (!skip) {
+        if (DCstate == 2 || DCstate == 3) {
+            if ((dcrd = read_dcache(ctx)) == 0)
+                return;
+        }
+    } else
+        dcrd = 1;
+#    endif /* defined(HASDCACHE) */
+
+    Dstkn = Dstkx = 0;
+    Dstk = (char **)NULL;
+    (void)stkdir(ctx, "/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);
+            Error(ctx);
+        }
+        (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 defined(HASDNAMLEN)
+            dnamlen = (int)dp->d_namlen;
+#    else  /* !defined(HASDNAMLEN) */
+            dnamlen = (int)strlen(dp->d_name);
+#    endif /* defined(HASDNAMLEN) */
+
+            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);
+                Error(ctx);
+            }
+            if (RDEV_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) {
+                (void)stkdir(ctx, 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);
+                        Error(ctx);
+                    }
+                }
+                Devtp[i].rdev = RDEV_EXPDEV(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);
+                    Error(ctx);
+                }
+                Devtp[i].v = 0;
+
+#    if defined(HAS_STD_CLONE) && HAS_STD_CLONE == 1
+                if (HAVECLONEMAJ && GET_MAJ_DEV(Devtp[i].rdev) == CLONEMAJ) {
+
+                    /*
+                     * Record clone device information.
+                     */
+                    if (!(c = (struct clone *)malloc(sizeof(struct clone)))) {
+                        (void)fprintf(stderr,
+                                      "%s: no space for clone device: ", Pn);
+                        safestrprt(fp, stderr, 1);
+                        Error(ctx);
+                    }
+                    c->dx = i;
+                    c->next = Clone;
+                    Clone = c;
+                }
+#    endif /* defined(HAS_STD_CLONE) && HAS_STD_CLONE==1 */
+
+                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);
+                        Error(ctx);
+                    }
+                }
+                BDevtp[j].name = fp;
+                fp = (char *)NULL;
+                BDevtp[j].inode = (INODETYPE)sb.st_ino;
+                BDevtp[j].rdev = RDEV_EXPDEV(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;
+    }
+    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);
+            Error(ctx);
+        }
+        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(ctx, &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);
+            Error(ctx);
+        }
+        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(ctx, &Sdev, Ndev, "char");
+    } else {
+        (void)fprintf(stderr, "%s: no character devices found\n", Pn);
+        Error(ctx);
+    }
+
+#    if defined(HASDCACHE)
+    /*
+     * Write device cache file, as required.
+     */
+    if (DCstate == 1 || (DCstate == 3 && dcrd))
+        write_dcache(ctx);
+#    endif /* defined(HASDCACHE) */
 }
 
-
-# if	defined(HASDCACHE)
+#    if defined(HASDCACHE)
 /*
  * rereaddev() - reread device names, modes and types
  */
 
-void
-rereaddev()
-{
-	(void) clr_devtab();
+void rereaddev(struct lsof_context *ctx) {
+    (void)clr_devtab(ctx);
 
-# if	defined(DCACHE_CLR)
-	(void) DCACHE_CLR();
-# endif	/* defined(DCACHE_CLR) */
+#        if defined(DCACHE_CLR)
+    (void)DCACHE_CLR();
+#        endif /* defined(DCACHE_CLR) */
 
-	readdev(1);
-	DCunsafe = 0;
+    readdev(ctx, 1);
+    DCunsafe = 0;
 }
-#endif	/* defined(HASDCACHE) */
-
+#    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 */
+static int rmdupdev(struct lsof_context *ctx,
+                    struct l_dev ***dp, /* device table pointers address */
+                    int n,              /* number of pointers */
+                    char *nm) /* device table name for error message */
 {
 
-# if	defined(HAS_STD_CLONE) && HAS_STD_CLONE==1
-	struct clone *c, *cp;
-# endif	/* defined(HAS_STD_CLONE) && HAS_STD_CLONE==1 */
-
-	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	defined(HAS_STD_CLONE) && HAS_STD_CLONE==1
-	    /*
-	     * 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;
-		}
-# endif	/* defined(HAS_STD_CLONE) && HAS_STD_CLONE==1 */
-
-	    }
-	    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);
-	    Error();
-	}
-	return(j);
+#    if defined(HAS_STD_CLONE) && HAS_STD_CLONE == 1
+    struct clone *c, *cp;
+#    endif /* defined(HAS_STD_CLONE) && HAS_STD_CLONE==1 */
+
+    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 defined(HAS_STD_CLONE) && HAS_STD_CLONE == 1
+            /*
+             * 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;
+            }
+#    endif /* defined(HAS_STD_CLONE) && HAS_STD_CLONE==1 */
+        }
+        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);
+        Error(ctx);
+    }
+    return (j);
 }
 
-
-# if	defined(HASDCACHE)
+#    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 */
+int vfy_dev(struct lsof_context *ctx,
+            struct l_dev *dp) /* device table pointer */
 {
-	struct stat sb;
-
-	if (!DCunsafe || dp->v)
-	    return(1);
-	if (RDEV_STATFN(dp->name, &sb) != 0
-	||  dp->rdev != RDEV_EXPDEV(sb.st_rdev)
-	||  dp->inode != sb.st_ino) {
-	   (void) rereaddev();
-	   return(0);
-	}
-	dp->v = 1;
-	return(1);
+    struct stat sb;
+
+    if (!DCunsafe || dp->v)
+        return (1);
+    if (RDEV_STATFN(dp->name, &sb) != 0 ||
+        dp->rdev != RDEV_EXPDEV(sb.st_rdev) || dp->inode != sb.st_ino) {
+        (void)rereaddev(ctx);
+        return (0);
+    }
+    dp->v = 1;
+    return (1);
 }
-# endif	/* defined(HASDCACHE) */
-#else	/* !defined(USE_LIB_READDEV) */
-char rdev_d1[] = "d"; char *rdev_d2 = rdev_d1;
-#endif	/* defined(USE_LIB_READDEV) */
+#    endif /* defined(HASDCACHE) */
+#else      /* !defined(USE_LIB_READDEV) */
+char rdev_d1[] = "d";
+char *rdev_d2 = rdev_d1;
+#endif     /* defined(USE_LIB_READDEV) */
diff --git a/lib/regex.c b/lib/regex.c
deleted file mode 100644
index bb83c1c..0000000
--- a/lib/regex.c
+++ /dev/null
@@ -1,6328 +0,0 @@
-/*
- * regex.c -- POSIX-conformant regular expression function set for the lsof
- *	      library
- *
- * This file is used when the UNIX dialect does not have a POSIX-conformant
- * regular expression function set.  In that case USE_LIB_REGEX is defined.
- *
- * V. Abell <abe@purdue.edu>
- * Purdue University Computing Center
- */
-
-
-/*
- * Copyright 2000 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.
- *
- * This software has been adapted from snprintf.c in sendmail 8.9.3.  It
- * is subject to the sendmail copyright statements listed below, and the
- * sendmail licensing terms stated in the sendmail LICENSE file comment
- * section of this file.
- *
- * 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.
- */
-
-
-#include "../machine.h"
-
-#ifdef	USE_LIB_REGEX
-/*
- * This file comes from GLIBC 2.2.  It is used when the UNIX dialect does not
- * have a POSIX-conformant regular expression function set.  In that case
- * USE_LIB_REGEX is defined.
- */
-
-/* Extended regular expression matching and search library,
-   version 0.12.
-   (Implements POSIX draft P1003.2/D11.2, except for some of the
-   internationalization features.)
-   Copyright (C) 1993-1999, 2000 Free Software Foundation, Inc.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Library General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Library General Public License for more details.
-
-   You should have received a copy of the GNU Library General Public
-   License along with the GNU C Library; see the file COPYING.LIB.  If not,
-   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
-
-/* AIX requires this to be the first thing in the file. */
-#if defined _AIX && !defined REGEX_MALLOC
-  #pragma alloca
-#endif
-
-#undef	_GNU_SOURCE
-#define _GNU_SOURCE
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#ifndef PARAMS
-# if defined __GNUC__ || (defined __STDC__ && __STDC__)
-#  define PARAMS(args) args
-# else
-#  define PARAMS(args) ()
-# endif  /* GCC.  */
-#endif  /* Not PARAMS.  */
-
-#if defined STDC_HEADERS && !defined emacs
-# include <stddef.h>
-#else
-/* We need this for `regex.h', and perhaps for the Emacs include files.  */
-# include <sys/types.h>
-#endif
-
-#define WIDE_CHAR_SUPPORT (HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_BTOWC)
-
-/* For platform which support the ISO C amendement 1 functionality we
-   support user defined character classes.  */
-#if defined _LIBC || WIDE_CHAR_SUPPORT
-/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>.  */
-# include <wchar.h>
-# include <wctype.h>
-#endif
-
-#ifdef _LIBC
-/* We have to keep the namespace clean.  */
-# define regfree(preg) __regfree (preg)
-# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef)
-# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags)
-# define regerror(errcode, preg, errbuf, errbuf_size) \
-	__regerror(errcode, preg, errbuf, errbuf_size)
-# define re_set_registers(bu, re, nu, st, en) \
-	__re_set_registers (bu, re, nu, st, en)
-# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \
-	__re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
-# define re_match(bufp, string, size, pos, regs) \
-	__re_match (bufp, string, size, pos, regs)
-# define re_search(bufp, string, size, startpos, range, regs) \
-	__re_search (bufp, string, size, startpos, range, regs)
-# define re_compile_pattern(pattern, length, bufp) \
-	__re_compile_pattern (pattern, length, bufp)
-# define re_set_syntax(syntax) __re_set_syntax (syntax)
-# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \
-	__re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop)
-# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp)
-
-# define btowc __btowc
-
-/* We are also using some library internals.  */
-# include <locale/localeinfo.h>
-# include <locale/elem-hash.h>
-# include <langinfo.h>
-#endif
-
-/* This is for other GNU distributions with internationalized messages.  */
-#if HAVE_LIBINTL_H || defined _LIBC
-# include <libintl.h>
-# ifdef _LIBC
-#  undef gettext
-#  define gettext(msgid) __dcgettext ("libc", msgid, LC_MESSAGES)
-# endif
-#else
-# define gettext(msgid) (msgid)
-#endif
-
-#ifndef gettext_noop
-/* This define is so xgettext can find the internationalizable
-   strings.  */
-# define gettext_noop(String) String
-#endif
-
-/* The `emacs' switch turns on certain matching commands
-   that make sense only in Emacs. */
-#ifdef emacs
-
-# include "lisp.h"
-# include "buffer.h"
-# include "syntax.h"
-
-#else  /* not emacs */
-
-/* If we are not linking with Emacs proper,
-   we can't use the relocating allocator
-   even if config.h says that we can.  */
-# undef REL_ALLOC
-
-# if defined STDC_HEADERS || defined _LIBC
-#  include <stdlib.h>
-# else
-char *malloc ();
-char *realloc ();
-# endif
-
-/* When used in Emacs's lib-src, we need to get bzero and bcopy somehow.
-   If nothing else has been done, use the method below.  */
-# ifdef INHIBIT_STRING_HEADER
-#  if !(defined HAVE_BZERO && defined HAVE_BCOPY)
-#   if !defined bzero && !defined bcopy
-#    undef INHIBIT_STRING_HEADER
-#   endif
-#  endif
-# endif
-
-/* This is the normal way of making sure we have a bcopy and a bzero.
-   This is used in most programs--a few other programs avoid this
-   by defining INHIBIT_STRING_HEADER.  */
-# ifndef INHIBIT_STRING_HEADER
-#  if defined HAVE_STRING_H || defined STDC_HEADERS || defined _LIBC
-#   include <string.h>
-#   ifndef bzero
-#    ifndef _LIBC
-#     define bzero(s, n)	(memset (s, '\0', n), (s))
-#    else
-#     define bzero(s, n)	__bzero (s, n)
-#    endif
-#   endif
-#  else
-#   include <strings.h>
-#   ifndef memcmp
-#    define memcmp(s1, s2, n)	bcmp (s1, s2, n)
-#   endif
-#   ifndef memcpy
-#    define memcpy(d, s, n)	(bcopy (s, d, n), (d))
-#   endif
-#  endif
-# endif
-
-/* Define the syntax stuff for \<, \>, etc.  */
-
-/* This must be nonzero for the wordchar and notwordchar pattern
-   commands in re_match_2.  */
-# ifndef Sword
-#  define Sword 1
-# endif
-
-# ifdef SWITCH_ENUM_BUG
-#  define SWITCH_ENUM_CAST(x) ((int)(x))
-# else
-#  define SWITCH_ENUM_CAST(x) (x)
-# endif
-
-#endif /* not emacs */
-
-#if defined _LIBC || HAVE_LIMITS_H
-# include <limits.h>
-#endif
-
-#ifndef MB_LEN_MAX
-# define MB_LEN_MAX 1
-#endif
-
-/* Get the interface, including the syntax bits.  */
-/* Disabled by V. Abell on January 29, 2001: #include <regex.h> */
-#include "../regex.h"
-
-/* isalpha etc. are used for the character classes.  */
-#include <ctype.h>
-
-/* Jim Meyering writes:
-
-   "... Some ctype macros are valid only for character codes that
-   isascii says are ASCII (SGI's IRIX-4.0.5 is one such system --when
-   using /bin/cc or gcc but without giving an ansi option).  So, all
-   ctype uses should be through macros like ISPRINT...  If
-   STDC_HEADERS is defined, then autoconf has verified that the ctype
-   macros don't need to be guarded with references to isascii. ...
-   Defining isascii to 1 should let any compiler worth its salt
-   eliminate the && through constant folding."
-   Solaris defines some of these symbols so we must undefine them first.  */
-
-#undef ISASCII
-#if defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII)
-# define ISASCII(c) 1
-#else
-# define ISASCII(c) isascii(c)
-#endif
-
-#ifdef isblank
-# define ISBLANK(c) (ISASCII (c) && isblank (c))
-#else
-# define ISBLANK(c) ((c) == ' ' || (c) == '\t')
-#endif
-#ifdef isgraph
-# define ISGRAPH(c) (ISASCII (c) && isgraph (c))
-#else
-# define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
-#endif
-
-#undef ISPRINT
-#define ISPRINT(c) (ISASCII (c) && isprint (c))
-#define ISDIGIT(c) (ISASCII (c) && isdigit (c))
-#define ISALNUM(c) (ISASCII (c) && isalnum (c))
-#define ISALPHA(c) (ISASCII (c) && isalpha (c))
-#define ISCNTRL(c) (ISASCII (c) && iscntrl (c))
-#define ISLOWER(c) (ISASCII (c) && islower (c))
-#define ISPUNCT(c) (ISASCII (c) && ispunct (c))
-#define ISSPACE(c) (ISASCII (c) && isspace (c))
-#define ISUPPER(c) (ISASCII (c) && isupper (c))
-#define ISXDIGIT(c) (ISASCII (c) && isxdigit (c))
-
-#ifdef _tolower
-# define TOLOWER(c) _tolower(c)
-#else
-# define TOLOWER(c) tolower(c)
-#endif
-
-#ifndef NULL
-# define NULL (void *)0
-#endif
-
-/* We remove any previous definition of `SIGN_EXTEND_CHAR',
-   since ours (we hope) works properly with all combinations of
-   machines, compilers, `char' and `unsigned char' argument types.
-   (Per Bothner suggested the basic approach.)  */
-#undef SIGN_EXTEND_CHAR
-#if __STDC__
-# define SIGN_EXTEND_CHAR(c) ((signed char) (c))
-#else  /* not __STDC__ */
-/* As in Harbison and Steele.  */
-# define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128)
-#endif
-
-#ifndef emacs
-/* How many characters in the character set.  */
-# define CHAR_SET_SIZE 256
-
-# ifdef SYNTAX_TABLE
-
-extern char *re_syntax_table;
-
-# else /* not SYNTAX_TABLE */
-
-static char re_syntax_table[CHAR_SET_SIZE];
-
-static void
-init_syntax_once ()
-{
-   register int c;
-   static int done = 0;
-
-   if (done)
-     return;
-   bzero (re_syntax_table, sizeof re_syntax_table);
-
-   for (c = 0; c < CHAR_SET_SIZE; ++c)
-     if (ISALNUM (c))
-	re_syntax_table[c] = Sword;
-
-   re_syntax_table['_'] = Sword;
-
-   done = 1;
-}
-
-# endif /* not SYNTAX_TABLE */
-
-# define SYNTAX(c) re_syntax_table[(unsigned char) (c)]
-
-#endif /* emacs */
-
-/* Should we use malloc or alloca?  If REGEX_MALLOC is not defined, we
-   use `alloca' instead of `malloc'.  This is because using malloc in
-   re_search* or re_match* could cause memory leaks when C-g is used in
-   Emacs; also, malloc is slower and causes storage fragmentation.  On
-   the other hand, malloc is more portable, and easier to debug.
-
-   Because we sometimes use alloca, some routines have to be macros,
-   not functions -- `alloca'-allocated space disappears at the end of the
-   function it is called in.  */
-
-#ifdef REGEX_MALLOC
-
-# define REGEX_ALLOCATE malloc
-# define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize)
-# define REGEX_FREE free
-
-#else /* not REGEX_MALLOC  */
-
-/* Emacs already defines alloca, sometimes.  */
-# ifndef alloca
-
-/* Make alloca work the best possible way.  */
-#  ifdef __GNUC__
-#   define alloca __builtin_alloca
-#  else /* not __GNUC__ */
-#   if HAVE_ALLOCA_H
-#    include <alloca.h>
-#   endif /* HAVE_ALLOCA_H */
-#  endif /* not __GNUC__ */
-
-# endif /* not alloca */
-
-# define REGEX_ALLOCATE alloca
-
-/* Assumes a `char *destination' variable.  */
-# define REGEX_REALLOCATE(source, osize, nsize)				\
-  (destination = (char *) alloca (nsize),				\
-   memcpy (destination, source, osize))
-
-/* No need to do anything to free, after alloca.  */
-# define REGEX_FREE(arg) ((void)0) /* Do nothing!  But inhibit gcc warning.  */
-
-#endif /* not REGEX_MALLOC */
-
-/* Define how to allocate the failure stack.  */
-
-#if defined REL_ALLOC && defined REGEX_MALLOC
-
-# define REGEX_ALLOCATE_STACK(size)				\
-  r_alloc (&failure_stack_ptr, (size))
-# define REGEX_REALLOCATE_STACK(source, osize, nsize)		\
-  r_re_alloc (&failure_stack_ptr, (nsize))
-# define REGEX_FREE_STACK(ptr)					\
-  r_alloc_free (&failure_stack_ptr)
-
-#else /* not using relocating allocator */
-
-# ifdef REGEX_MALLOC
-
-#  define REGEX_ALLOCATE_STACK malloc
-#  define REGEX_REALLOCATE_STACK(source, osize, nsize) realloc (source, nsize)
-#  define REGEX_FREE_STACK free
-
-# else /* not REGEX_MALLOC */
-
-#  define REGEX_ALLOCATE_STACK alloca
-
-#  define REGEX_REALLOCATE_STACK(source, osize, nsize)			\
-   REGEX_REALLOCATE (source, osize, nsize)
-/* No need to explicitly free anything.  */
-#  define REGEX_FREE_STACK(arg)
-
-# endif /* not REGEX_MALLOC */
-#endif /* not using relocating allocator */
-
-
-/* True if `size1' is non-NULL and PTR is pointing anywhere inside
-   `string1' or just past its end.  This works if PTR is NULL, which is
-   a good thing.  */
-#define FIRST_STRING_P(ptr) 					\
-  (size1 && string1 <= (ptr) && (ptr) <= string1 + size1)
-
-/* (Re)Allocate N items of type T using malloc, or fail.  */
-#define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t)))
-#define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t)))
-#define RETALLOC_IF(addr, n, t) \
-  if (addr) RETALLOC((addr), (n), t); else (addr) = TALLOC ((n), t)
-#define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t)))
-
-#define BYTEWIDTH 8 /* In bits.  */
-
-#define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
-
-#undef MAX
-#undef MIN
-#define MAX(a, b) ((a) > (b) ? (a) : (b))
-#define MIN(a, b) ((a) < (b) ? (a) : (b))
-
-typedef char boolean;
-#define false 0
-#define true 1
-
-static int re_match_2_internal PARAMS ((struct re_pattern_buffer *bufp,
-					const char *string1, int size1,
-					const char *string2, int size2,
-					int pos,
-					struct re_registers *regs,
-					int stop));
-
-/* These are the command codes that appear in compiled regular
-   expressions.  Some opcodes are followed by argument bytes.  A
-   command code can specify any interpretation whatsoever for its
-   arguments.  Zero bytes may appear in the compiled regular expression.  */
-
-typedef enum
-{
-  no_op = 0,
-
-  /* Succeed right away--no more backtracking.  */
-  succeed,
-
-        /* Followed by one byte giving n, then by n literal bytes.  */
-  exactn,
-
-        /* Matches any (more or less) character.  */
-  anychar,
-
-        /* Matches any one char belonging to specified set.  First
-           following byte is number of bitmap bytes.  Then come bytes
-           for a bitmap saying which chars are in.  Bits in each byte
-           are ordered low-bit-first.  A character is in the set if its
-           bit is 1.  A character too large to have a bit in the map is
-           automatically not in the set.  */
-  charset,
-
-        /* Same parameters as charset, but match any character that is
-           not one of those specified.  */
-  charset_not,
-
-        /* Start remembering the text that is matched, for storing in a
-           register.  Followed by one byte with the register number, in
-           the range 0 to one less than the pattern buffer's re_nsub
-           field.  Then followed by one byte with the number of groups
-           inner to this one.  (This last has to be part of the
-           start_memory only because we need it in the on_failure_jump
-           of re_match_2.)  */
-  start_memory,
-
-        /* Stop remembering the text that is matched and store it in a
-           memory register.  Followed by one byte with the register
-           number, in the range 0 to one less than `re_nsub' in the
-           pattern buffer, and one byte with the number of inner groups,
-           just like `start_memory'.  (We need the number of inner
-           groups here because we don't have any easy way of finding the
-           corresponding start_memory when we're at a stop_memory.)  */
-  stop_memory,
-
-        /* Match a duplicate of something remembered. Followed by one
-           byte containing the register number.  */
-  duplicate,
-
-        /* Fail unless at beginning of line.  */
-  begline,
-
-        /* Fail unless at end of line.  */
-  endline,
-
-        /* Succeeds if at beginning of buffer (if emacs) or at beginning
-           of string to be matched (if not).  */
-  begbuf,
-
-        /* Analogously, for end of buffer/string.  */
-  endbuf,
-
-        /* Followed by two byte relative address to which to jump.  */
-  jump,
-
-	/* Same as jump, but marks the end of an alternative.  */
-  jump_past_alt,
-
-        /* Followed by two-byte relative address of place to resume at
-           in case of failure.  */
-  on_failure_jump,
-
-        /* Like on_failure_jump, but pushes a placeholder instead of the
-           current string position when executed.  */
-  on_failure_keep_string_jump,
-
-        /* Throw away latest failure point and then jump to following
-           two-byte relative address.  */
-  pop_failure_jump,
-
-        /* Change to pop_failure_jump if know won't have to backtrack to
-           match; otherwise change to jump.  This is used to jump
-           back to the beginning of a repeat.  If what follows this jump
-           clearly won't match what the repeat does, such that we can be
-           sure that there is no use backtracking out of repetitions
-           already matched, then we change it to a pop_failure_jump.
-           Followed by two-byte address.  */
-  maybe_pop_jump,
-
-        /* Jump to following two-byte address, and push a dummy failure
-           point. This failure point will be thrown away if an attempt
-           is made to use it for a failure.  A `+' construct makes this
-           before the first repeat.  Also used as an intermediary kind
-           of jump when compiling an alternative.  */
-  dummy_failure_jump,
-
-	/* Push a dummy failure point and continue.  Used at the end of
-	   alternatives.  */
-  push_dummy_failure,
-
-        /* Followed by two-byte relative address and two-byte number n.
-           After matching N times, jump to the address upon failure.  */
-  succeed_n,
-
-        /* Followed by two-byte relative address, and two-byte number n.
-           Jump to the address N times, then fail.  */
-  jump_n,
-
-        /* Set the following two-byte relative address to the
-           subsequent two-byte number.  The address *includes* the two
-           bytes of number.  */
-  set_number_at,
-
-  wordchar,	/* Matches any word-constituent character.  */
-  notwordchar,	/* Matches any char that is not a word-constituent.  */
-
-  wordbeg,	/* Succeeds if at word beginning.  */
-  wordend,	/* Succeeds if at word end.  */
-
-  wordbound,	/* Succeeds if at a word boundary.  */
-  notwordbound	/* Succeeds if not at a word boundary.  */
-
-#ifdef emacs
-  ,before_dot,	/* Succeeds if before point.  */
-  at_dot,	/* Succeeds if at point.  */
-  after_dot,	/* Succeeds if after point.  */
-
-	/* Matches any character whose syntax is specified.  Followed by
-           a byte which contains a syntax code, e.g., Sword.  */
-  syntaxspec,
-
-	/* Matches any character whose syntax is not that specified.  */
-  notsyntaxspec
-#endif /* emacs */
-} re_opcode_t;
-
-/* Common operations on the compiled pattern.  */
-
-/* Store NUMBER in two contiguous bytes starting at DESTINATION.  */
-
-#define STORE_NUMBER(destination, number)				\
-  do {									\
-    (destination)[0] = (number) & 0377;					\
-    (destination)[1] = (number) >> 8;					\
-  } while (0)
-
-/* Same as STORE_NUMBER, except increment DESTINATION to
-   the byte after where the number is stored.  Therefore, DESTINATION
-   must be an lvalue.  */
-
-#define STORE_NUMBER_AND_INCR(destination, number)			\
-  do {									\
-    STORE_NUMBER (destination, number);					\
-    (destination) += 2;							\
-  } while (0)
-
-/* Put into DESTINATION a number stored in two contiguous bytes starting
-   at SOURCE.  */
-
-#define EXTRACT_NUMBER(destination, source)				\
-  do {									\
-    (destination) = *(source) & 0377;					\
-    (destination) += SIGN_EXTEND_CHAR (*((source) + 1)) << 8;		\
-  } while (0)
-
-#ifdef DEBUG
-static void extract_number _RE_ARGS ((int *dest, unsigned char *source));
-static void
-extract_number (dest, source)
-    int *dest;
-    unsigned char *source;
-{
-  int temp = SIGN_EXTEND_CHAR (*(source + 1));
-  *dest = *source & 0377;
-  *dest += temp << 8;
-}
-
-# ifndef EXTRACT_MACROS /* To debug the macros.  */
-#  undef EXTRACT_NUMBER
-#  define EXTRACT_NUMBER(dest, src) extract_number (&dest, src)
-# endif /* not EXTRACT_MACROS */
-
-#endif /* DEBUG */
-
-/* Same as EXTRACT_NUMBER, except increment SOURCE to after the number.
-   SOURCE must be an lvalue.  */
-
-#define EXTRACT_NUMBER_AND_INCR(destination, source)			\
-  do {									\
-    EXTRACT_NUMBER (destination, source);				\
-    (source) += 2; 							\
-  } while (0)
-
-#ifdef DEBUG
-static void extract_number_and_incr _RE_ARGS ((int *destination,
-					       unsigned char **source));
-static void
-extract_number_and_incr (destination, source)
-    int *destination;
-    unsigned char **source;
-{
-  extract_number (destination, *source);
-  *source += 2;
-}
-
-# ifndef EXTRACT_MACROS
-#  undef EXTRACT_NUMBER_AND_INCR
-#  define EXTRACT_NUMBER_AND_INCR(dest, src) \
-  extract_number_and_incr (&dest, &src)
-# endif /* not EXTRACT_MACROS */
-
-#endif /* DEBUG */
-
-/* If DEBUG is defined, Regex prints many voluminous messages about what
-   it is doing (if the variable `debug' is nonzero).  If linked with the
-   main program in `iregex.c', you can enter patterns and strings
-   interactively.  And if linked with the main program in `main.c' and
-   the other test files, you can run the already-written tests.  */
-
-#ifdef DEBUG
-
-/* We use standard I/O for debugging.  */
-# include <stdio.h>
-
-/* It is useful to test things that ``must'' be true when debugging.  */
-# include <assert.h>
-
-static int debug;
-
-# define DEBUG_STATEMENT(e) e
-# define DEBUG_PRINT1(x) if (debug) printf (x)
-# define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2)
-# define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3)
-# define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4)
-# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) 				\
-  if (debug) print_partial_compiled_pattern (s, e)
-# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2)			\
-  if (debug) print_double_string (w, s1, sz1, s2, sz2)
-
-
-/* Print the fastmap in human-readable form.  */
-
-void
-print_fastmap (fastmap)
-    char *fastmap;
-{
-  unsigned was_a_range = 0;
-  unsigned i = 0;
-
-  while (i < (1 << BYTEWIDTH))
-    {
-      if (fastmap[i++])
-	{
-	  was_a_range = 0;
-          putchar (i - 1);
-          while (i < (1 << BYTEWIDTH)  &&  fastmap[i])
-            {
-              was_a_range = 1;
-              i++;
-            }
-	  if (was_a_range)
-            {
-              printf ("-");
-              putchar (i - 1);
-            }
-        }
-    }
-  putchar ('\n');
-}
-
-
-/* Print a compiled pattern string in human-readable form, starting at
-   the START pointer into it and ending just before the pointer END.  */
-
-void
-print_partial_compiled_pattern (start, end)
-    unsigned char *start;
-    unsigned char *end;
-{
-  int mcnt, mcnt2;
-  unsigned char *p1;
-  unsigned char *p = start;
-  unsigned char *pend = end;
-
-  if (start == NULL)
-    {
-      printf ("(null)\n");
-      return;
-    }
-
-  /* Loop over pattern commands.  */
-  while (p < pend)
-    {
-#ifdef _LIBC
-      printf ("%t:\t", p - start);
-#else
-      printf ("%ld:\t", (long int) (p - start));
-#endif
-
-      switch ((re_opcode_t) *p++)
-	{
-        case no_op:
-          printf ("/no_op");
-          break;
-
-	case exactn:
-	  mcnt = *p++;
-          printf ("/exactn/%d", mcnt);
-          do
-	    {
-              putchar ('/');
-	      putchar (*p++);
-            }
-          while (--mcnt);
-          break;
-
-	case start_memory:
-          mcnt = *p++;
-          printf ("/start_memory/%d/%d", mcnt, *p++);
-          break;
-
-	case stop_memory:
-          mcnt = *p++;
-	  printf ("/stop_memory/%d/%d", mcnt, *p++);
-          break;
-
-	case duplicate:
-	  printf ("/duplicate/%d", *p++);
-	  break;
-
-	case anychar:
-	  printf ("/anychar");
-	  break;
-
-	case charset:
-        case charset_not:
-          {
-            register int c, last = -100;
-	    register int in_range = 0;
-
-	    printf ("/charset [%s",
-	            (re_opcode_t) *(p - 1) == charset_not ? "^" : "");
-
-            assert (p + *p < pend);
-
-            for (c = 0; c < 256; c++)
-	      if (c / 8 < *p
-		  && (p[1 + (c/8)] & (1 << (c % 8))))
-		{
-		  /* Are we starting a range?  */
-		  if (last + 1 == c && ! in_range)
-		    {
-		      putchar ('-');
-		      in_range = 1;
-		    }
-		  /* Have we broken a range?  */
-		  else if (last + 1 != c && in_range)
-              {
-		      putchar (last);
-		      in_range = 0;
-		    }
-
-		  if (! in_range)
-		    putchar (c);
-
-		  last = c;
-              }
-
-	    if (in_range)
-	      putchar (last);
-
-	    putchar (']');
-
-	    p += 1 + *p;
-	  }
-	  break;
-
-	case begline:
-	  printf ("/begline");
-          break;
-
-	case endline:
-          printf ("/endline");
-          break;
-
-	case on_failure_jump:
-          extract_number_and_incr (&mcnt, &p);
-#ifdef _LIBC
-  	  printf ("/on_failure_jump to %t", p + mcnt - start);
-#else
-  	  printf ("/on_failure_jump to %ld", (long int) (p + mcnt - start));
-#endif
-          break;
-
-	case on_failure_keep_string_jump:
-          extract_number_and_incr (&mcnt, &p);
-#ifdef _LIBC
-  	  printf ("/on_failure_keep_string_jump to %t", p + mcnt - start);
-#else
-  	  printf ("/on_failure_keep_string_jump to %ld",
-		  (long int) (p + mcnt - start));
-#endif
-          break;
-
-	case dummy_failure_jump:
-          extract_number_and_incr (&mcnt, &p);
-#ifdef _LIBC
-  	  printf ("/dummy_failure_jump to %t", p + mcnt - start);
-#else
-  	  printf ("/dummy_failure_jump to %ld", (long int) (p + mcnt - start));
-#endif
-          break;
-
-	case push_dummy_failure:
-          printf ("/push_dummy_failure");
-          break;
-
-        case maybe_pop_jump:
-          extract_number_and_incr (&mcnt, &p);
-#ifdef _LIBC
-  	  printf ("/maybe_pop_jump to %t", p + mcnt - start);
-#else
-  	  printf ("/maybe_pop_jump to %ld", (long int) (p + mcnt - start));
-#endif
-	  break;
-
-        case pop_failure_jump:
-	  extract_number_and_incr (&mcnt, &p);
-#ifdef _LIBC
-  	  printf ("/pop_failure_jump to %t", p + mcnt - start);
-#else
-  	  printf ("/pop_failure_jump to %ld", (long int) (p + mcnt - start));
-#endif
-	  break;
-
-        case jump_past_alt:
-	  extract_number_and_incr (&mcnt, &p);
-#ifdef _LIBC
-  	  printf ("/jump_past_alt to %t", p + mcnt - start);
-#else
-  	  printf ("/jump_past_alt to %ld", (long int) (p + mcnt - start));
-#endif
-	  break;
-
-        case jump:
-	  extract_number_and_incr (&mcnt, &p);
-#ifdef _LIBC
-  	  printf ("/jump to %t", p + mcnt - start);
-#else
-  	  printf ("/jump to %ld", (long int) (p + mcnt - start));
-#endif
-	  break;
-
-        case succeed_n:
-          extract_number_and_incr (&mcnt, &p);
-	  p1 = p + mcnt;
-          extract_number_and_incr (&mcnt2, &p);
-#ifdef _LIBC
-	  printf ("/succeed_n to %t, %d times", p1 - start, mcnt2);
-#else
-	  printf ("/succeed_n to %ld, %d times",
-		  (long int) (p1 - start), mcnt2);
-#endif
-          break;
-
-        case jump_n:
-          extract_number_and_incr (&mcnt, &p);
-	  p1 = p + mcnt;
-          extract_number_and_incr (&mcnt2, &p);
-	  printf ("/jump_n to %d, %d times", p1 - start, mcnt2);
-          break;
-
-        case set_number_at:
-          extract_number_and_incr (&mcnt, &p);
-	  p1 = p + mcnt;
-          extract_number_and_incr (&mcnt2, &p);
-#ifdef _LIBC
-	  printf ("/set_number_at location %t to %d", p1 - start, mcnt2);
-#else
-	  printf ("/set_number_at location %ld to %d",
-		  (long int) (p1 - start), mcnt2);
-#endif
-          break;
-
-        case wordbound:
-	  printf ("/wordbound");
-	  break;
-
-	case notwordbound:
-	  printf ("/notwordbound");
-          break;
-
-	case wordbeg:
-	  printf ("/wordbeg");
-	  break;
-
-	case wordend:
-	  printf ("/wordend");
-
-# ifdef emacs
-	case before_dot:
-	  printf ("/before_dot");
-          break;
-
-	case at_dot:
-	  printf ("/at_dot");
-          break;
-
-	case after_dot:
-	  printf ("/after_dot");
-          break;
-
-	case syntaxspec:
-          printf ("/syntaxspec");
-	  mcnt = *p++;
-	  printf ("/%d", mcnt);
-          break;
-
-	case notsyntaxspec:
-          printf ("/notsyntaxspec");
-	  mcnt = *p++;
-	  printf ("/%d", mcnt);
-	  break;
-# endif /* emacs */
-
-	case wordchar:
-	  printf ("/wordchar");
-          break;
-
-	case notwordchar:
-	  printf ("/notwordchar");
-          break;
-
-	case begbuf:
-	  printf ("/begbuf");
-          break;
-
-	case endbuf:
-	  printf ("/endbuf");
-          break;
-
-        default:
-          printf ("?%d", *(p-1));
-	}
-
-      putchar ('\n');
-    }
-
-#ifdef _LIBC
-  printf ("%t:\tend of pattern.\n", p - start);
-#else
-  printf ("%ld:\tend of pattern.\n", (long int) (p - start));
-#endif
-}
-
-
-void
-print_compiled_pattern (bufp)
-    struct re_pattern_buffer *bufp;
-{
-  unsigned char *buffer = bufp->buffer;
-
-  print_partial_compiled_pattern (buffer, buffer + bufp->used);
-  printf ("%ld bytes used/%ld bytes allocated.\n",
-	  bufp->used, bufp->allocated);
-
-  if (bufp->fastmap_accurate && bufp->fastmap)
-    {
-      printf ("fastmap: ");
-      print_fastmap (bufp->fastmap);
-    }
-
-#ifdef _LIBC
-  printf ("re_nsub: %Zd\t", bufp->re_nsub);
-#else
-  printf ("re_nsub: %ld\t", (long int) bufp->re_nsub);
-#endif
-  printf ("regs_alloc: %d\t", bufp->regs_allocated);
-  printf ("can_be_null: %d\t", bufp->can_be_null);
-  printf ("newline_anchor: %d\n", bufp->newline_anchor);
-  printf ("no_sub: %d\t", bufp->no_sub);
-  printf ("not_bol: %d\t", bufp->not_bol);
-  printf ("not_eol: %d\t", bufp->not_eol);
-  printf ("syntax: %lx\n", bufp->syntax);
-  /* Perhaps we should print the translate table?  */
-}
-
-
-void
-print_double_string (where, string1, size1, string2, size2)
-    const char *where;
-    const char *string1;
-    const char *string2;
-    int size1;
-    int size2;
-{
-  int this_char;
-
-  if (where == NULL)
-    printf ("(null)");
-  else
-    {
-      if (FIRST_STRING_P (where))
-        {
-          for (this_char = where - string1; this_char < size1; this_char++)
-            putchar (string1[this_char]);
-
-          where = string2;
-        }
-
-      for (this_char = where - string2; this_char < size2; this_char++)
-        putchar (string2[this_char]);
-    }
-}
-
-void
-printchar (c)
-     int c;
-{
-  putc (c, stderr);
-}
-
-#else /* not DEBUG */
-
-# undef assert
-# define assert(e)
-
-# define DEBUG_STATEMENT(e)
-# define DEBUG_PRINT1(x)
-# define DEBUG_PRINT2(x1, x2)
-# define DEBUG_PRINT3(x1, x2, x3)
-# define DEBUG_PRINT4(x1, x2, x3, x4)
-# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e)
-# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2)
-
-#endif /* not DEBUG */
-
-/* Set by `re_set_syntax' to the current regexp syntax to recognize.  Can
-   also be assigned to arbitrarily: each pattern buffer stores its own
-   syntax, so it can be changed between regex compilations.  */
-/* This has no initializer because initialized variables in Emacs
-   become read-only after dumping.  */
-reg_syntax_t re_syntax_options;
-
-
-/* Specify the precise syntax of regexps for compilation.  This provides
-   for compatibility for various utilities which historically have
-   different, incompatible syntaxes.
-
-   The argument SYNTAX is a bit mask comprised of the various bits
-   defined in regex.h.  We return the old syntax.  */
-
-reg_syntax_t
-re_set_syntax (syntax)
-    reg_syntax_t syntax;
-{
-  reg_syntax_t ret = re_syntax_options;
-
-  re_syntax_options = syntax;
-#ifdef DEBUG
-  if (syntax & RE_DEBUG)
-    debug = 1;
-  else if (debug) /* was on but now is not */
-    debug = 0;
-#endif /* DEBUG */
-  return ret;
-}
-#ifdef _LIBC
-weak_alias (__re_set_syntax, re_set_syntax)
-#endif
-
-/* This table gives an error message for each of the error codes listed
-   in regex.h.  Obviously the order here has to be same as there.
-   POSIX doesn't require that we do anything for REG_NOERROR,
-   but why not be nice?  */
-
-static const char re_error_msgid[] =
-  {
-#define REG_NOERROR_IDX	0
-    gettext_noop ("Success")	/* REG_NOERROR */
-    "\0"
-#define REG_NOMATCH_IDX (REG_NOERROR_IDX + sizeof "Success")
-    gettext_noop ("No match")	/* REG_NOMATCH */
-    "\0"
-#define REG_BADPAT_IDX	(REG_NOMATCH_IDX + sizeof "No match")
-    gettext_noop ("Invalid regular expression") /* REG_BADPAT */
-    "\0"
-#define REG_ECOLLATE_IDX (REG_BADPAT_IDX + sizeof "Invalid regular expression")
-    gettext_noop ("Invalid collation character") /* REG_ECOLLATE */
-    "\0"
-#define REG_ECTYPE_IDX	(REG_ECOLLATE_IDX + sizeof "Invalid collation character")
-    gettext_noop ("Invalid character class name") /* REG_ECTYPE */
-    "\0"
-#define REG_EESCAPE_IDX	(REG_ECTYPE_IDX + sizeof "Invalid character class name")
-    gettext_noop ("Trailing backslash") /* REG_EESCAPE */
-    "\0"
-#define REG_ESUBREG_IDX	(REG_EESCAPE_IDX + sizeof "Trailing backslash")
-    gettext_noop ("Invalid back reference") /* REG_ESUBREG */
-    "\0"
-#define REG_EBRACK_IDX	(REG_ESUBREG_IDX + sizeof "Invalid back reference")
-    gettext_noop ("Unmatched [ or [^")	/* REG_EBRACK */
-    "\0"
-#define REG_EPAREN_IDX	(REG_EBRACK_IDX + sizeof "Unmatched [ or [^")
-    gettext_noop ("Unmatched ( or \\(") /* REG_EPAREN */
-    "\0"
-#define REG_EBRACE_IDX	(REG_EPAREN_IDX + sizeof "Unmatched ( or \\(")
-    gettext_noop ("Unmatched \\{") /* REG_EBRACE */
-    "\0"
-#define REG_BADBR_IDX	(REG_EBRACE_IDX + sizeof "Unmatched \\{")
-    gettext_noop ("Invalid content of \\{\\}") /* REG_BADBR */
-    "\0"
-#define REG_ERANGE_IDX	(REG_BADBR_IDX + sizeof "Invalid content of \\{\\}")
-    gettext_noop ("Invalid range end")	/* REG_ERANGE */
-    "\0"
-#define REG_ESPACE_IDX	(REG_ERANGE_IDX + sizeof "Invalid range end")
-    gettext_noop ("Memory exhausted") /* REG_ESPACE */
-    "\0"
-#define REG_BADRPT_IDX	(REG_ESPACE_IDX + sizeof "Memory exhausted")
-    gettext_noop ("Invalid preceding regular expression") /* REG_BADRPT */
-    "\0"
-#define REG_EEND_IDX	(REG_BADRPT_IDX + sizeof "Invalid preceding regular expression")
-    gettext_noop ("Premature end of regular expression") /* REG_EEND */
-    "\0"
-#define REG_ESIZE_IDX	(REG_EEND_IDX + sizeof "Premature end of regular expression")
-    gettext_noop ("Regular expression too big") /* REG_ESIZE */
-    "\0"
-#define REG_ERPAREN_IDX	(REG_ESIZE_IDX + sizeof "Regular expression too big")
-    gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */
-  };
-
-static const size_t re_error_msgid_idx[] =
-  {
-    REG_NOERROR_IDX,
-    REG_NOMATCH_IDX,
-    REG_BADPAT_IDX,
-    REG_ECOLLATE_IDX,
-    REG_ECTYPE_IDX,
-    REG_EESCAPE_IDX,
-    REG_ESUBREG_IDX,
-    REG_EBRACK_IDX,
-    REG_EPAREN_IDX,
-    REG_EBRACE_IDX,
-    REG_BADBR_IDX,
-    REG_ERANGE_IDX,
-    REG_ESPACE_IDX,
-    REG_BADRPT_IDX,
-    REG_EEND_IDX,
-    REG_ESIZE_IDX,
-    REG_ERPAREN_IDX
-  };
-
-/* Avoiding alloca during matching, to placate r_alloc.  */
-
-/* Define MATCH_MAY_ALLOCATE unless we need to make sure that the
-   searching and matching functions should not call alloca.  On some
-   systems, alloca is implemented in terms of malloc, and if we're
-   using the relocating allocator routines, then malloc could cause a
-   relocation, which might (if the strings being searched are in the
-   ralloc heap) shift the data out from underneath the regexp
-   routines.
-
-   Here's another reason to avoid allocation: Emacs
-   processes input from X in a signal handler; processing X input may
-   call malloc; if input arrives while a matching routine is calling
-   malloc, then we're scrod.  But Emacs can't just block input while
-   calling matching routines; then we don't notice interrupts when
-   they come in.  So, Emacs blocks input around all regexp calls
-   except the matching calls, which it leaves unprotected, in the
-   faith that they will not malloc.  */
-
-/* Normally, this is fine.  */
-#define MATCH_MAY_ALLOCATE
-
-/* When using GNU C, we are not REALLY using the C alloca, no matter
-   what config.h may say.  So don't take precautions for it.  */
-#ifdef __GNUC__
-# undef C_ALLOCA
-#endif
-
-/* The match routines may not allocate if (1) they would do it with malloc
-   and (2) it's not safe for them to use malloc.
-   Note that if REL_ALLOC is defined, matching would not use malloc for the
-   failure stack, but we would still use it for the register vectors;
-   so REL_ALLOC should not affect this.  */
-#if (defined C_ALLOCA || defined REGEX_MALLOC) && defined emacs
-# undef MATCH_MAY_ALLOCATE
-#endif
-
-
-/* Failure stack declarations and macros; both re_compile_fastmap and
-   re_match_2 use a failure stack.  These have to be macros because of
-   REGEX_ALLOCATE_STACK.  */
-
-
-/* Number of failure points for which to initially allocate space
-   when matching.  If this number is exceeded, we allocate more
-   space, so it is not a hard limit.  */
-#ifndef INIT_FAILURE_ALLOC
-# define INIT_FAILURE_ALLOC 5
-#endif
-
-/* Roughly the maximum number of failure points on the stack.  Would be
-   exactly that if always used MAX_FAILURE_ITEMS items each time we failed.
-   This is a variable only so users of regex can assign to it; we never
-   change it ourselves.  */
-
-#ifdef INT_IS_16BIT
-
-# if defined MATCH_MAY_ALLOCATE
-/* 4400 was enough to cause a crash on Alpha OSF/1,
-   whose default stack limit is 2mb.  */
-long int re_max_failures = 4000;
-# else
-long int re_max_failures = 2000;
-# endif
-
-union fail_stack_elt
-{
-  unsigned char *pointer;
-  long int integer;
-};
-
-typedef union fail_stack_elt fail_stack_elt_t;
-
-typedef struct
-{
-  fail_stack_elt_t *stack;
-  unsigned long int size;
-  unsigned long int avail;		/* Offset of next open position.  */
-} fail_stack_type;
-
-#else /* not INT_IS_16BIT */
-
-# if defined MATCH_MAY_ALLOCATE
-/* 4400 was enough to cause a crash on Alpha OSF/1,
-   whose default stack limit is 2mb.  */
-int re_max_failures = 4000;
-# else
-int re_max_failures = 2000;
-# endif
-
-union fail_stack_elt
-{
-  unsigned char *pointer;
-  int integer;
-};
-
-typedef union fail_stack_elt fail_stack_elt_t;
-
-typedef struct
-{
-  fail_stack_elt_t *stack;
-  unsigned size;
-  unsigned avail;			/* Offset of next open position.  */
-} fail_stack_type;
-
-#endif /* INT_IS_16BIT */
-
-#define FAIL_STACK_EMPTY()     (fail_stack.avail == 0)
-#define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0)
-#define FAIL_STACK_FULL()      (fail_stack.avail == fail_stack.size)
-
-
-/* Define macros to initialize and free the failure stack.
-   Do `return -2' if the alloc fails.  */
-
-#ifdef MATCH_MAY_ALLOCATE
-# define INIT_FAIL_STACK()						\
-  do {									\
-    fail_stack.stack = (fail_stack_elt_t *)				\
-      REGEX_ALLOCATE_STACK (INIT_FAILURE_ALLOC * sizeof (fail_stack_elt_t)); \
-									\
-    if (fail_stack.stack == NULL)					\
-      return -2;							\
-									\
-    fail_stack.size = INIT_FAILURE_ALLOC;				\
-    fail_stack.avail = 0;						\
-  } while (0)
-
-# define RESET_FAIL_STACK()  REGEX_FREE_STACK (fail_stack.stack)
-#else
-# define INIT_FAIL_STACK()						\
-  do {									\
-    fail_stack.avail = 0;						\
-  } while (0)
-
-# define RESET_FAIL_STACK()
-#endif
-
-
-/* Double the size of FAIL_STACK, up to approximately `re_max_failures' items.
-
-   Return 1 if succeeds, and 0 if either ran out of memory
-   allocating space for it or it was already too large.
-
-   REGEX_REALLOCATE_STACK requires `destination' be declared.   */
-
-#define DOUBLE_FAIL_STACK(fail_stack)					\
-  ((fail_stack).size > (unsigned) (re_max_failures * MAX_FAILURE_ITEMS)	\
-   ? 0									\
-   : ((fail_stack).stack = (fail_stack_elt_t *)				\
-        REGEX_REALLOCATE_STACK ((fail_stack).stack, 			\
-          (fail_stack).size * sizeof (fail_stack_elt_t),		\
-          ((fail_stack).size << 1) * sizeof (fail_stack_elt_t)),	\
-									\
-      (fail_stack).stack == NULL					\
-      ? 0								\
-      : ((fail_stack).size <<= 1, 					\
-         1)))
-
-
-/* Push pointer POINTER on FAIL_STACK.
-   Return 1 if was able to do so and 0 if ran out of memory allocating
-   space to do so.  */
-#define PUSH_PATTERN_OP(POINTER, FAIL_STACK)				\
-  ((FAIL_STACK_FULL ()							\
-    && !DOUBLE_FAIL_STACK (FAIL_STACK))					\
-   ? 0									\
-   : ((FAIL_STACK).stack[(FAIL_STACK).avail++].pointer = POINTER,	\
-      1))
-
-/* Push a pointer value onto the failure stack.
-   Assumes the variable `fail_stack'.  Probably should only
-   be called from within `PUSH_FAILURE_POINT'.  */
-#define PUSH_FAILURE_POINTER(item)					\
-  fail_stack.stack[fail_stack.avail++].pointer = (unsigned char *) (item)
-
-/* This pushes an integer-valued item onto the failure stack.
-   Assumes the variable `fail_stack'.  Probably should only
-   be called from within `PUSH_FAILURE_POINT'.  */
-#define PUSH_FAILURE_INT(item)					\
-  fail_stack.stack[fail_stack.avail++].integer = (item)
-
-/* Push a fail_stack_elt_t value onto the failure stack.
-   Assumes the variable `fail_stack'.  Probably should only
-   be called from within `PUSH_FAILURE_POINT'.  */
-#define PUSH_FAILURE_ELT(item)					\
-  fail_stack.stack[fail_stack.avail++] =  (item)
-
-/* These three POP... operations complement the three PUSH... operations.
-   All assume that `fail_stack' is nonempty.  */
-#define POP_FAILURE_POINTER() fail_stack.stack[--fail_stack.avail].pointer
-#define POP_FAILURE_INT() fail_stack.stack[--fail_stack.avail].integer
-#define POP_FAILURE_ELT() fail_stack.stack[--fail_stack.avail]
-
-/* Used to omit pushing failure point id's when we're not debugging.  */
-#ifdef DEBUG
-# define DEBUG_PUSH PUSH_FAILURE_INT
-# define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_INT ()
-#else
-# define DEBUG_PUSH(item)
-# define DEBUG_POP(item_addr)
-#endif
-
-
-/* Push the information about the state we will need
-   if we ever fail back to it.
-
-   Requires variables fail_stack, regstart, regend, reg_info, and
-   num_regs_pushed be declared.  DOUBLE_FAIL_STACK requires `destination'
-   be declared.
-
-   Does `return FAILURE_CODE' if runs out of memory.  */
-
-#define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code)	\
-  do {									\
-    char *destination;							\
-    /* Must be int, so when we don't save any registers, the arithmetic	\
-       of 0 + -1 isn't done as unsigned.  */				\
-    /* Can't be int, since there is not a shred of a guarantee that int	\
-       is wide enough to hold a value of something to which pointer can	\
-       be assigned */							\
-    active_reg_t this_reg;						\
-    									\
-    DEBUG_STATEMENT (failure_id++);					\
-    DEBUG_STATEMENT (nfailure_points_pushed++);				\
-    DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id);		\
-    DEBUG_PRINT2 ("  Before push, next avail: %d\n", (fail_stack).avail);\
-    DEBUG_PRINT2 ("                     size: %d\n", (fail_stack).size);\
-									\
-    DEBUG_PRINT2 ("  slots needed: %ld\n", NUM_FAILURE_ITEMS);		\
-    DEBUG_PRINT2 ("     available: %d\n", REMAINING_AVAIL_SLOTS);	\
-									\
-    /* Ensure we have enough space allocated for what we will push.  */	\
-    while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS)			\
-      {									\
-        if (!DOUBLE_FAIL_STACK (fail_stack))				\
-          return failure_code;						\
-									\
-        DEBUG_PRINT2 ("\n  Doubled stack; size now: %d\n",		\
-		       (fail_stack).size);				\
-        DEBUG_PRINT2 ("  slots available: %d\n", REMAINING_AVAIL_SLOTS);\
-      }									\
-									\
-    /* Push the info, starting with the registers.  */			\
-    DEBUG_PRINT1 ("\n");						\
-									\
-    if (1)								\
-      for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \
-	   this_reg++)							\
-	{								\
-	  DEBUG_PRINT2 ("  Pushing reg: %lu\n", this_reg);		\
-	  DEBUG_STATEMENT (num_regs_pushed++);				\
-									\
-	  DEBUG_PRINT2 ("    start: %p\n", regstart[this_reg]);		\
-	  PUSH_FAILURE_POINTER (regstart[this_reg]);			\
-									\
-	  DEBUG_PRINT2 ("    end: %p\n", regend[this_reg]);		\
-	  PUSH_FAILURE_POINTER (regend[this_reg]);			\
-									\
-	  DEBUG_PRINT2 ("    info: %p\n      ",				\
-			reg_info[this_reg].word.pointer);		\
-	  DEBUG_PRINT2 (" match_null=%d",				\
-			REG_MATCH_NULL_STRING_P (reg_info[this_reg]));	\
-	  DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg]));	\
-	  DEBUG_PRINT2 (" matched_something=%d",			\
-			MATCHED_SOMETHING (reg_info[this_reg]));	\
-	  DEBUG_PRINT2 (" ever_matched=%d",				\
-			EVER_MATCHED_SOMETHING (reg_info[this_reg]));	\
-	  DEBUG_PRINT1 ("\n");						\
-	  PUSH_FAILURE_ELT (reg_info[this_reg].word);			\
-	}								\
-									\
-    DEBUG_PRINT2 ("  Pushing  low active reg: %ld\n", lowest_active_reg);\
-    PUSH_FAILURE_INT (lowest_active_reg);				\
-									\
-    DEBUG_PRINT2 ("  Pushing high active reg: %ld\n", highest_active_reg);\
-    PUSH_FAILURE_INT (highest_active_reg);				\
-									\
-    DEBUG_PRINT2 ("  Pushing pattern %p:\n", pattern_place);		\
-    DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend);		\
-    PUSH_FAILURE_POINTER (pattern_place);				\
-									\
-    DEBUG_PRINT2 ("  Pushing string %p: `", string_place);		\
-    DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2,   \
-				 size2);				\
-    DEBUG_PRINT1 ("'\n");						\
-    PUSH_FAILURE_POINTER (string_place);				\
-									\
-    DEBUG_PRINT2 ("  Pushing failure id: %u\n", failure_id);		\
-    DEBUG_PUSH (failure_id);						\
-  } while (0)
-
-/* This is the number of items that are pushed and popped on the stack
-   for each register.  */
-#define NUM_REG_ITEMS  3
-
-/* Individual items aside from the registers.  */
-#ifdef DEBUG
-# define NUM_NONREG_ITEMS 5 /* Includes failure point id.  */
-#else
-# define NUM_NONREG_ITEMS 4
-#endif
-
-/* We push at most this many items on the stack.  */
-/* We used to use (num_regs - 1), which is the number of registers
-   this regexp will save; but that was changed to 5
-   to avoid stack overflow for a regexp with lots of parens.  */
-#define MAX_FAILURE_ITEMS (5 * NUM_REG_ITEMS + NUM_NONREG_ITEMS)
-
-/* We actually push this many items.  */
-#define NUM_FAILURE_ITEMS				\
-  (((0							\
-     ? 0 : highest_active_reg - lowest_active_reg + 1)	\
-    * NUM_REG_ITEMS)					\
-   + NUM_NONREG_ITEMS)
-
-/* How many items can still be added to the stack without overflowing it.  */
-#define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail)
-
-
-/* Pops what PUSH_FAIL_STACK pushes.
-
-   We restore into the parameters, all of which should be lvalues:
-     STR -- the saved data position.
-     PAT -- the saved pattern position.
-     LOW_REG, HIGH_REG -- the highest and lowest active registers.
-     REGSTART, REGEND -- arrays of string positions.
-     REG_INFO -- array of information about each subexpression.
-
-   Also assumes the variables `fail_stack' and (if debugging), `bufp',
-   `pend', `string1', `size1', `string2', and `size2'.  */
-
-#define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\
-{									\
-  DEBUG_STATEMENT (unsigned failure_id;)				\
-  active_reg_t this_reg;						\
-  const unsigned char *string_temp;					\
-									\
-  assert (!FAIL_STACK_EMPTY ());					\
-									\
-  /* Remove failure points and point to how many regs pushed.  */	\
-  DEBUG_PRINT1 ("POP_FAILURE_POINT:\n");				\
-  DEBUG_PRINT2 ("  Before pop, next avail: %d\n", fail_stack.avail);	\
-  DEBUG_PRINT2 ("                    size: %d\n", fail_stack.size);	\
-									\
-  assert (fail_stack.avail >= NUM_NONREG_ITEMS);			\
-									\
-  DEBUG_POP (&failure_id);						\
-  DEBUG_PRINT2 ("  Popping failure id: %u\n", failure_id);		\
-									\
-  /* If the saved string location is NULL, it came from an		\
-     on_failure_keep_string_jump opcode, and we want to throw away the	\
-     saved NULL, thus retaining our current position in the string.  */	\
-  string_temp = POP_FAILURE_POINTER ();					\
-  if (string_temp != NULL)						\
-    str = (const char *) string_temp;					\
-									\
-  DEBUG_PRINT2 ("  Popping string %p: `", str);				\
-  DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2);	\
-  DEBUG_PRINT1 ("'\n");							\
-									\
-  pat = (unsigned char *) POP_FAILURE_POINTER ();			\
-  DEBUG_PRINT2 ("  Popping pattern %p:\n", pat);			\
-  DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend);			\
-									\
-  /* Restore register info.  */						\
-  high_reg = (active_reg_t) POP_FAILURE_INT ();				\
-  DEBUG_PRINT2 ("  Popping high active reg: %ld\n", high_reg);		\
-									\
-  low_reg = (active_reg_t) POP_FAILURE_INT ();				\
-  DEBUG_PRINT2 ("  Popping  low active reg: %ld\n", low_reg);		\
-									\
-  if (1)								\
-    for (this_reg = high_reg; this_reg >= low_reg; this_reg--)		\
-      {									\
-	DEBUG_PRINT2 ("    Popping reg: %ld\n", this_reg);		\
-									\
-	reg_info[this_reg].word = POP_FAILURE_ELT ();			\
-	DEBUG_PRINT2 ("      info: %p\n",				\
-		      reg_info[this_reg].word.pointer);			\
-									\
-	regend[this_reg] = (const char *) POP_FAILURE_POINTER ();	\
-	DEBUG_PRINT2 ("      end: %p\n", regend[this_reg]);		\
-									\
-	regstart[this_reg] = (const char *) POP_FAILURE_POINTER ();	\
-	DEBUG_PRINT2 ("      start: %p\n", regstart[this_reg]);		\
-      }									\
-  else									\
-    {									\
-      for (this_reg = highest_active_reg; this_reg > high_reg; this_reg--) \
-	{								\
-	  reg_info[this_reg].word.integer = 0;				\
-	  regend[this_reg] = 0;						\
-	  regstart[this_reg] = 0;					\
-	}								\
-      highest_active_reg = high_reg;					\
-    }									\
-									\
-  set_regs_matched_done = 0;						\
-  DEBUG_STATEMENT (nfailure_points_popped++);				\
-} /* POP_FAILURE_POINT */
-
-
-
-/* Structure for per-register (a.k.a. per-group) information.
-   Other register information, such as the
-   starting and ending positions (which are addresses), and the list of
-   inner groups (which is a bits list) are maintained in separate
-   variables.
-
-   We are making a (strictly speaking) nonportable assumption here: that
-   the compiler will pack our bit fields into something that fits into
-   the type of `word', i.e., is something that fits into one item on the
-   failure stack.  */
-
-
-/* Declarations and macros for re_match_2.  */
-
-typedef union
-{
-  fail_stack_elt_t word;
-  struct
-  {
-      /* This field is one if this group can match the empty string,
-         zero if not.  If not yet determined,  `MATCH_NULL_UNSET_VALUE'.  */
-#define MATCH_NULL_UNSET_VALUE 3
-    unsigned match_null_string_p : 2;
-    unsigned is_active : 1;
-    unsigned matched_something : 1;
-    unsigned ever_matched_something : 1;
-  } bits;
-} register_info_type;
-
-#define REG_MATCH_NULL_STRING_P(R)  ((R).bits.match_null_string_p)
-#define IS_ACTIVE(R)  ((R).bits.is_active)
-#define MATCHED_SOMETHING(R)  ((R).bits.matched_something)
-#define EVER_MATCHED_SOMETHING(R)  ((R).bits.ever_matched_something)
-
-
-/* Call this when have matched a real character; it sets `matched' flags
-   for the subexpressions which we are currently inside.  Also records
-   that those subexprs have matched.  */
-#define SET_REGS_MATCHED()						\
-  do									\
-    {									\
-      if (!set_regs_matched_done)					\
-	{								\
-	  active_reg_t r;						\
-	  set_regs_matched_done = 1;					\
-	  for (r = lowest_active_reg; r <= highest_active_reg; r++)	\
-	    {								\
-	      MATCHED_SOMETHING (reg_info[r])				\
-		= EVER_MATCHED_SOMETHING (reg_info[r])			\
-		= 1;							\
-	    }								\
-	}								\
-    }									\
-  while (0)
-
-/* Registers are set to a sentinel when they haven't yet matched.  */
-static char reg_unset_dummy;
-#define REG_UNSET_VALUE (&reg_unset_dummy)
-#define REG_UNSET(e) ((e) == REG_UNSET_VALUE)
-
-/* Subroutine declarations and macros for regex_compile.  */
-
-static reg_errcode_t regex_compile _RE_ARGS ((const char *pattern, size_t size,
-					      reg_syntax_t syntax,
-					      struct re_pattern_buffer *bufp));
-static void store_op1 _RE_ARGS ((re_opcode_t op, unsigned char *loc, int arg));
-static void store_op2 _RE_ARGS ((re_opcode_t op, unsigned char *loc,
-				 int arg1, int arg2));
-static void insert_op1 _RE_ARGS ((re_opcode_t op, unsigned char *loc,
-				  int arg, unsigned char *end));
-static void insert_op2 _RE_ARGS ((re_opcode_t op, unsigned char *loc,
-				  int arg1, int arg2, unsigned char *end));
-static boolean at_begline_loc_p _RE_ARGS ((const char *pattern, const char *p,
-					   reg_syntax_t syntax));
-static boolean at_endline_loc_p _RE_ARGS ((const char *p, const char *pend,
-					   reg_syntax_t syntax));
-static reg_errcode_t compile_range _RE_ARGS ((unsigned int range_start,
-					      const char **p_ptr,
-					      const char *pend,
-					      char *translate,
-					      reg_syntax_t syntax,
-					      unsigned char *b));
-
-/* Fetch the next character in the uncompiled pattern---translating it
-   if necessary.  Also cast from a signed character in the constant
-   string passed to us by the user to an unsigned char that we can use
-   as an array index (in, e.g., `translate').  */
-#ifndef PATFETCH
-# define PATFETCH(c)							\
-  do {if (p == pend) return REG_EEND;					\
-    c = (unsigned char) *p++;						\
-    if (translate) c = (unsigned char) translate[c];			\
-  } while (0)
-#endif
-
-/* Fetch the next character in the uncompiled pattern, with no
-   translation.  */
-#define PATFETCH_RAW(c)							\
-  do {if (p == pend) return REG_EEND;					\
-    c = (unsigned char) *p++; 						\
-  } while (0)
-
-/* Go backwards one character in the pattern.  */
-#define PATUNFETCH p--
-
-
-/* If `translate' is non-null, return translate[D], else just D.  We
-   cast the subscript to translate because some data is declared as
-   `char *', to avoid warnings when a string constant is passed.  But
-   when we use a character as a subscript we must make it unsigned.  */
-#ifndef TRANSLATE
-# define TRANSLATE(d) \
-  (translate ? (char) translate[(unsigned char) (d)] : (d))
-#endif
-
-
-/* Macros for outputting the compiled pattern into `buffer'.  */
-
-/* If the buffer isn't allocated when it comes in, use this.  */
-#define INIT_BUF_SIZE  32
-
-/* Make sure we have at least N more bytes of space in buffer.  */
-#define GET_BUFFER_SPACE(n)						\
-    while ((unsigned long) (b - bufp->buffer + (n)) > bufp->allocated)	\
-      EXTEND_BUFFER ()
-
-/* Make sure we have one more byte of buffer space and then add C to it.  */
-#define BUF_PUSH(c)							\
-  do {									\
-    GET_BUFFER_SPACE (1);						\
-    *b++ = (unsigned char) (c);						\
-  } while (0)
-
-
-/* Ensure we have two more bytes of buffer space and then append C1 and C2.  */
-#define BUF_PUSH_2(c1, c2)						\
-  do {									\
-    GET_BUFFER_SPACE (2);						\
-    *b++ = (unsigned char) (c1);					\
-    *b++ = (unsigned char) (c2);					\
-  } while (0)
-
-
-/* As with BUF_PUSH_2, except for three bytes.  */
-#define BUF_PUSH_3(c1, c2, c3)						\
-  do {									\
-    GET_BUFFER_SPACE (3);						\
-    *b++ = (unsigned char) (c1);					\
-    *b++ = (unsigned char) (c2);					\
-    *b++ = (unsigned char) (c3);					\
-  } while (0)
-
-
-/* Store a jump with opcode OP at LOC to location TO.  We store a
-   relative address offset by the three bytes the jump itself occupies.  */
-#define STORE_JUMP(op, loc, to) \
-  store_op1 (op, loc, (int) ((to) - (loc) - 3))
-
-/* Likewise, for a two-argument jump.  */
-#define STORE_JUMP2(op, loc, to, arg) \
-  store_op2 (op, loc, (int) ((to) - (loc) - 3), arg)
-
-/* Like `STORE_JUMP', but for inserting.  Assume `b' is the buffer end.  */
-#define INSERT_JUMP(op, loc, to) \
-  insert_op1 (op, loc, (int) ((to) - (loc) - 3), b)
-
-/* Like `STORE_JUMP2', but for inserting.  Assume `b' is the buffer end.  */
-#define INSERT_JUMP2(op, loc, to, arg) \
-  insert_op2 (op, loc, (int) ((to) - (loc) - 3), arg, b)
-
-
-/* This is not an arbitrary limit: the arguments which represent offsets
-   into the pattern are two bytes long.  So if 2^16 bytes turns out to
-   be too small, many things would have to change.  */
-/* Any other compiler which, like MSC, has allocation limit below 2^16
-   bytes will have to use approach similar to what was done below for
-   MSC and drop MAX_BUF_SIZE a bit.  Otherwise you may end up
-   reallocating to 0 bytes.  Such thing is not going to work too well.
-   You have been warned!!  */
-#if defined _MSC_VER  && !defined WIN32
-/* Microsoft C 16-bit versions limit malloc to approx 65512 bytes.
-   The REALLOC define eliminates a flurry of conversion warnings,
-   but is not required. */
-# define MAX_BUF_SIZE  65500L
-# define REALLOC(p,s) realloc ((p), (size_t) (s))
-#else
-# define MAX_BUF_SIZE (1L << 16)
-# define REALLOC(p,s) realloc ((p), (s))
-#endif
-
-/* Extend the buffer by twice its current size via realloc and
-   reset the pointers that pointed into the old block to point to the
-   correct places in the new one.  If extending the buffer results in it
-   being larger than MAX_BUF_SIZE, then flag memory exhausted.  */
-#if __BOUNDED_POINTERS__
-# define SET_HIGH_BOUND(P) (__ptrhigh (P) = __ptrlow (P) + bufp->allocated)
-# define MOVE_BUFFER_POINTER(P) \
-  (__ptrlow (P) += incr, SET_HIGH_BOUND (P), __ptrvalue (P) += incr)
-# define ELSE_EXTEND_BUFFER_HIGH_BOUND		\
-  else						\
-    {						\
-      SET_HIGH_BOUND (b);			\
-      SET_HIGH_BOUND (begalt);			\
-      if (fixup_alt_jump)			\
-	SET_HIGH_BOUND (fixup_alt_jump);	\
-      if (laststart)				\
-	SET_HIGH_BOUND (laststart);		\
-      if (pending_exact)			\
-	SET_HIGH_BOUND (pending_exact);		\
-    }
-#else
-# define MOVE_BUFFER_POINTER(P) (P) += incr
-# define ELSE_EXTEND_BUFFER_HIGH_BOUND
-#endif
-#define EXTEND_BUFFER()							\
-  do {									\
-    unsigned char *old_buffer = bufp->buffer;				\
-    if (bufp->allocated == MAX_BUF_SIZE)				\
-      return REG_ESIZE;							\
-    bufp->allocated <<= 1;						\
-    if (bufp->allocated > MAX_BUF_SIZE)					\
-      bufp->allocated = MAX_BUF_SIZE;					\
-    bufp->buffer = (unsigned char *) REALLOC (bufp->buffer, bufp->allocated);\
-    if (bufp->buffer == NULL)						\
-      return REG_ESPACE;						\
-    /* If the buffer moved, move all the pointers into it.  */		\
-    if (old_buffer != bufp->buffer)					\
-      {									\
-	int incr = bufp->buffer - old_buffer;				\
-	MOVE_BUFFER_POINTER (b);					\
-	MOVE_BUFFER_POINTER (begalt);					\
-	if (fixup_alt_jump)						\
-	  MOVE_BUFFER_POINTER (fixup_alt_jump);				\
-	if (laststart)							\
-	  MOVE_BUFFER_POINTER (laststart);				\
-	if (pending_exact)						\
-	  MOVE_BUFFER_POINTER (pending_exact);				\
-      }									\
-    ELSE_EXTEND_BUFFER_HIGH_BOUND					\
-  } while (0)
-
-
-/* Since we have one byte reserved for the register number argument to
-   {start,stop}_memory, the maximum number of groups we can report
-   things about is what fits in that byte.  */
-#define MAX_REGNUM 255
-
-/* But patterns can have more than `MAX_REGNUM' registers.  We just
-   ignore the excess.  */
-typedef unsigned regnum_t;
-
-
-/* Macros for the compile stack.  */
-
-/* Since offsets can go either forwards or backwards, this type needs to
-   be able to hold values from -(MAX_BUF_SIZE - 1) to MAX_BUF_SIZE - 1.  */
-/* int may be not enough when sizeof(int) == 2.  */
-typedef long pattern_offset_t;
-
-typedef struct
-{
-  pattern_offset_t begalt_offset;
-  pattern_offset_t fixup_alt_jump;
-  pattern_offset_t inner_group_offset;
-  pattern_offset_t laststart_offset;
-  regnum_t regnum;
-} compile_stack_elt_t;
-
-
-typedef struct
-{
-  compile_stack_elt_t *stack;
-  unsigned size;
-  unsigned avail;			/* Offset of next open position.  */
-} compile_stack_type;
-
-
-#define INIT_COMPILE_STACK_SIZE 32
-
-#define COMPILE_STACK_EMPTY  (compile_stack.avail == 0)
-#define COMPILE_STACK_FULL  (compile_stack.avail == compile_stack.size)
-
-/* The next available element.  */
-#define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail])
-
-
-/* Set the bit for character C in a list.  */
-#define SET_LIST_BIT(c)                               \
-  (b[((unsigned char) (c)) / BYTEWIDTH]               \
-   |= 1 << (((unsigned char) c) % BYTEWIDTH))
-
-
-/* Get the next unsigned number in the uncompiled pattern.  */
-#define GET_UNSIGNED_NUMBER(num) 					\
-  { if (p != pend)							\
-     {									\
-       PATFETCH (c); 							\
-       while ('0' <= c && c <= '9')					\
-         { 								\
-           if (num < 0)							\
-              num = 0;							\
-           num = num * 10 + c - '0'; 					\
-           if (p == pend) 						\
-              break; 							\
-           PATFETCH (c);						\
-         } 								\
-       } 								\
-    }
-
-#if defined _LIBC || WIDE_CHAR_SUPPORT
-/* The GNU C library provides support for user-defined character classes
-   and the functions from ISO C amendement 1.  */
-# ifdef CHARCLASS_NAME_MAX
-#  define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
-# else
-/* This shouldn't happen but some implementation might still have this
-   problem.  Use a reasonable default value.  */
-#  define CHAR_CLASS_MAX_LENGTH 256
-# endif
-
-# ifdef _LIBC
-#  define IS_CHAR_CLASS(string) __wctype (string)
-# else
-#  define IS_CHAR_CLASS(string) wctype (string)
-# endif
-#else
-# define CHAR_CLASS_MAX_LENGTH  6 /* Namely, `xdigit'.  */
-
-# define IS_CHAR_CLASS(string)						\
-   (STREQ (string, "alpha") || STREQ (string, "upper")			\
-    || STREQ (string, "lower") || STREQ (string, "digit")		\
-    || STREQ (string, "alnum") || STREQ (string, "xdigit")		\
-    || STREQ (string, "space") || STREQ (string, "print")		\
-    || STREQ (string, "punct") || STREQ (string, "graph")		\
-    || STREQ (string, "cntrl") || STREQ (string, "blank"))
-#endif
-
-#ifndef MATCH_MAY_ALLOCATE
-
-/* If we cannot allocate large objects within re_match_2_internal,
-   we make the fail stack and register vectors global.
-   The fail stack, we grow to the maximum size when a regexp
-   is compiled.
-   The register vectors, we adjust in size each time we
-   compile a regexp, according to the number of registers it needs.  */
-
-static fail_stack_type fail_stack;
-
-/* Size with which the following vectors are currently allocated.
-   That is so we can make them bigger as needed,
-   but never make them smaller.  */
-static int regs_allocated_size;
-
-static const char **     regstart, **     regend;
-static const char ** old_regstart, ** old_regend;
-static const char **best_regstart, **best_regend;
-static register_info_type *reg_info;
-static const char **reg_dummy;
-static register_info_type *reg_info_dummy;
-
-/* Make the register vectors big enough for NUM_REGS registers,
-   but don't make them smaller.  */
-
-static
-regex_grow_registers (num_regs)
-     int num_regs;
-{
-  if (num_regs > regs_allocated_size)
-    {
-      RETALLOC_IF (regstart,	 num_regs, const char *);
-      RETALLOC_IF (regend,	 num_regs, const char *);
-      RETALLOC_IF (old_regstart, num_regs, const char *);
-      RETALLOC_IF (old_regend,	 num_regs, const char *);
-      RETALLOC_IF (best_regstart, num_regs, const char *);
-      RETALLOC_IF (best_regend,	 num_regs, const char *);
-      RETALLOC_IF (reg_info,	 num_regs, register_info_type);
-      RETALLOC_IF (reg_dummy,	 num_regs, const char *);
-      RETALLOC_IF (reg_info_dummy, num_regs, register_info_type);
-
-      regs_allocated_size = num_regs;
-    }
-}
-
-#endif /* not MATCH_MAY_ALLOCATE */
-
-static boolean group_in_compile_stack _RE_ARGS ((compile_stack_type
-						 compile_stack,
-						 regnum_t regnum));
-
-/* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX.
-   Returns one of error codes defined in `regex.h', or zero for success.
-
-   Assumes the `allocated' (and perhaps `buffer') and `translate'
-   fields are set in BUFP on entry.
-
-   If it succeeds, results are put in BUFP (if it returns an error, the
-   contents of BUFP are undefined):
-     `buffer' is the compiled pattern;
-     `syntax' is set to SYNTAX;
-     `used' is set to the length of the compiled pattern;
-     `fastmap_accurate' is zero;
-     `re_nsub' is the number of subexpressions in PATTERN;
-     `not_bol' and `not_eol' are zero;
-
-   The `fastmap' and `newline_anchor' fields are neither
-   examined nor set.  */
-
-/* Return, freeing storage we allocated.  */
-#define FREE_STACK_RETURN(value)		\
-  return (free (compile_stack.stack), value)
-
-static reg_errcode_t
-regex_compile (pattern, size, syntax, bufp)
-     const char *pattern;
-     size_t size;
-     reg_syntax_t syntax;
-     struct re_pattern_buffer *bufp;
-{
-  /* We fetch characters from PATTERN here.  Even though PATTERN is
-     `char *' (i.e., signed), we declare these variables as unsigned, so
-     they can be reliably used as array indices.  */
-  register unsigned char c, c1;
-
-  /* A random temporary spot in PATTERN.  */
-  const char *p1;
-
-  /* Points to the end of the buffer, where we should append.  */
-  register unsigned char *b;
-
-  /* Keeps track of unclosed groups.  */
-  compile_stack_type compile_stack;
-
-  /* Points to the current (ending) position in the pattern.  */
-  const char *p = pattern;
-  const char *pend = pattern + size;
-
-  /* How to translate the characters in the pattern.  */
-  RE_TRANSLATE_TYPE translate = bufp->translate;
-
-  /* Address of the count-byte of the most recently inserted `exactn'
-     command.  This makes it possible to tell if a new exact-match
-     character can be added to that command or if the character requires
-     a new `exactn' command.  */
-  unsigned char *pending_exact = 0;
-
-  /* Address of start of the most recently finished expression.
-     This tells, e.g., postfix * where to find the start of its
-     operand.  Reset at the beginning of groups and alternatives.  */
-  unsigned char *laststart = 0;
-
-  /* Address of beginning of regexp, or inside of last group.  */
-  unsigned char *begalt;
-
-  /* Place in the uncompiled pattern (i.e., the {) to
-     which to go back if the interval is invalid.  */
-  const char *beg_interval;
-
-  /* Address of the place where a forward jump should go to the end of
-     the containing expression.  Each alternative of an `or' -- except the
-     last -- ends with a forward jump of this sort.  */
-  unsigned char *fixup_alt_jump = 0;
-
-  /* Counts open-groups as they are encountered.  Remembered for the
-     matching close-group on the compile stack, so the same register
-     number is put in the stop_memory as the start_memory.  */
-  regnum_t regnum = 0;
-
-#ifdef DEBUG
-  DEBUG_PRINT1 ("\nCompiling pattern: ");
-  if (debug)
-    {
-      unsigned debug_count;
-
-      for (debug_count = 0; debug_count < size; debug_count++)
-        putchar (pattern[debug_count]);
-      putchar ('\n');
-    }
-#endif /* DEBUG */
-
-  /* Initialize the compile stack.  */
-  compile_stack.stack = TALLOC (INIT_COMPILE_STACK_SIZE, compile_stack_elt_t);
-  if (compile_stack.stack == NULL)
-    return REG_ESPACE;
-
-  compile_stack.size = INIT_COMPILE_STACK_SIZE;
-  compile_stack.avail = 0;
-
-  /* Initialize the pattern buffer.  */
-  bufp->syntax = syntax;
-  bufp->fastmap_accurate = 0;
-  bufp->not_bol = bufp->not_eol = 0;
-
-  /* Set `used' to zero, so that if we return an error, the pattern
-     printer (for debugging) will think there's no pattern.  We reset it
-     at the end.  */
-  bufp->used = 0;
-
-  /* Always count groups, whether or not bufp->no_sub is set.  */
-  bufp->re_nsub = 0;
-
-#if !defined emacs && !defined SYNTAX_TABLE
-  /* Initialize the syntax table.  */
-   init_syntax_once ();
-#endif
-
-  if (bufp->allocated == 0)
-    {
-      if (bufp->buffer)
-	{ /* If zero allocated, but buffer is non-null, try to realloc
-             enough space.  This loses if buffer's address is bogus, but
-             that is the user's responsibility.  */
-          RETALLOC (bufp->buffer, INIT_BUF_SIZE, unsigned char);
-        }
-      else
-        { /* Caller did not allocate a buffer.  Do it for them.  */
-          bufp->buffer = TALLOC (INIT_BUF_SIZE, unsigned char);
-        }
-      if (!bufp->buffer) FREE_STACK_RETURN (REG_ESPACE);
-
-      bufp->allocated = INIT_BUF_SIZE;
-    }
-
-  begalt = b = bufp->buffer;
-
-  /* Loop through the uncompiled pattern until we're at the end.  */
-  while (p != pend)
-    {
-      PATFETCH (c);
-
-      switch (c)
-        {
-        case '^':
-          {
-            if (   /* If at start of pattern, it's an operator.  */
-                   p == pattern + 1
-                   /* If context independent, it's an operator.  */
-                || syntax & RE_CONTEXT_INDEP_ANCHORS
-                   /* Otherwise, depends on what's come before.  */
-                || at_begline_loc_p (pattern, p, syntax))
-              BUF_PUSH (begline);
-            else
-              goto normal_char;
-          }
-          break;
-
-
-        case '$':
-          {
-            if (   /* If at end of pattern, it's an operator.  */
-                   p == pend
-                   /* If context independent, it's an operator.  */
-                || syntax & RE_CONTEXT_INDEP_ANCHORS
-                   /* Otherwise, depends on what's next.  */
-                || at_endline_loc_p (p, pend, syntax))
-               BUF_PUSH (endline);
-             else
-               goto normal_char;
-           }
-           break;
-
-
-	case '+':
-        case '?':
-          if ((syntax & RE_BK_PLUS_QM)
-              || (syntax & RE_LIMITED_OPS))
-            goto normal_char;
-        handle_plus:
-        case '*':
-          /* If there is no previous pattern... */
-          if (!laststart)
-            {
-              if (syntax & RE_CONTEXT_INVALID_OPS)
-                FREE_STACK_RETURN (REG_BADRPT);
-              else if (!(syntax & RE_CONTEXT_INDEP_OPS))
-                goto normal_char;
-            }
-
-          {
-            /* Are we optimizing this jump?  */
-            boolean keep_string_p = false;
-
-            /* 1 means zero (many) matches is allowed.  */
-            char zero_times_ok = 0, many_times_ok = 0;
-
-            /* If there is a sequence of repetition chars, collapse it
-               down to just one (the right one).  We can't combine
-               interval operators with these because of, e.g., `a{2}*',
-               which should only match an even number of `a's.  */
-
-            for (;;)
-              {
-                zero_times_ok |= c != '+';
-                many_times_ok |= c != '?';
-
-                if (p == pend)
-                  break;
-
-                PATFETCH (c);
-
-                if (c == '*'
-                    || (!(syntax & RE_BK_PLUS_QM) && (c == '+' || c == '?')))
-                  ;
-
-                else if (syntax & RE_BK_PLUS_QM  &&  c == '\\')
-                  {
-                    if (p == pend) FREE_STACK_RETURN (REG_EESCAPE);
-
-                    PATFETCH (c1);
-                    if (!(c1 == '+' || c1 == '?'))
-                      {
-                        PATUNFETCH;
-                        PATUNFETCH;
-                        break;
-                      }
-
-                    c = c1;
-                  }
-                else
-                  {
-                    PATUNFETCH;
-                    break;
-                  }
-
-                /* If we get here, we found another repeat character.  */
-               }
-
-            /* Star, etc. applied to an empty pattern is equivalent
-               to an empty pattern.  */
-            if (!laststart)
-              break;
-
-            /* Now we know whether or not zero matches is allowed
-               and also whether or not two or more matches is allowed.  */
-            if (many_times_ok)
-              { /* More than one repetition is allowed, so put in at the
-                   end a backward relative jump from `b' to before the next
-                   jump we're going to put in below (which jumps from
-                   laststart to after this jump).
-
-                   But if we are at the `*' in the exact sequence `.*\n',
-                   insert an unconditional jump backwards to the .,
-                   instead of the beginning of the loop.  This way we only
-                   push a failure point once, instead of every time
-                   through the loop.  */
-                assert (p - 1 > pattern);
-
-                /* Allocate the space for the jump.  */
-                GET_BUFFER_SPACE (3);
-
-                /* We know we are not at the first character of the pattern,
-                   because laststart was nonzero.  And we've already
-                   incremented `p', by the way, to be the character after
-                   the `*'.  Do we have to do something analogous here
-                   for null bytes, because of RE_DOT_NOT_NULL?  */
-                if (TRANSLATE (*(p - 2)) == TRANSLATE ('.')
-		    && zero_times_ok
-                    && p < pend && TRANSLATE (*p) == TRANSLATE ('\n')
-                    && !(syntax & RE_DOT_NEWLINE))
-                  { /* We have .*\n.  */
-                    STORE_JUMP (jump, b, laststart);
-                    keep_string_p = true;
-                  }
-                else
-                  /* Anything else.  */
-                  STORE_JUMP (maybe_pop_jump, b, laststart - 3);
-
-                /* We've added more stuff to the buffer.  */
-                b += 3;
-              }
-
-            /* On failure, jump from laststart to b + 3, which will be the
-               end of the buffer after this jump is inserted.  */
-            GET_BUFFER_SPACE (3);
-            INSERT_JUMP (keep_string_p ? on_failure_keep_string_jump
-                                       : on_failure_jump,
-                         laststart, b + 3);
-            pending_exact = 0;
-            b += 3;
-
-            if (!zero_times_ok)
-              {
-                /* At least one repetition is required, so insert a
-                   `dummy_failure_jump' before the initial
-                   `on_failure_jump' instruction of the loop. This
-                   effects a skip over that instruction the first time
-                   we hit that loop.  */
-                GET_BUFFER_SPACE (3);
-                INSERT_JUMP (dummy_failure_jump, laststart, laststart + 6);
-                b += 3;
-              }
-            }
-	  break;
-
-
-	case '.':
-          laststart = b;
-          BUF_PUSH (anychar);
-          break;
-
-
-        case '[':
-          {
-            boolean had_char_class = false;
-	    unsigned int range_start = 0xffffffff;
-
-            if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
-
-            /* Ensure that we have enough space to push a charset: the
-               opcode, the length count, and the bitset; 34 bytes in all.  */
-	    GET_BUFFER_SPACE (34);
-
-            laststart = b;
-
-            /* We test `*p == '^' twice, instead of using an if
-               statement, so we only need one BUF_PUSH.  */
-            BUF_PUSH (*p == '^' ? charset_not : charset);
-            if (*p == '^')
-              p++;
-
-            /* Remember the first position in the bracket expression.  */
-            p1 = p;
-
-            /* Push the number of bytes in the bitmap.  */
-            BUF_PUSH ((1 << BYTEWIDTH) / BYTEWIDTH);
-
-            /* Clear the whole map.  */
-            bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH);
-
-            /* charset_not matches newline according to a syntax bit.  */
-            if ((re_opcode_t) b[-2] == charset_not
-                && (syntax & RE_HAT_LISTS_NOT_NEWLINE))
-              SET_LIST_BIT ('\n');
-
-            /* Read in characters and ranges, setting map bits.  */
-            for (;;)
-              {
-                if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
-
-                PATFETCH (c);
-
-                /* \ might escape characters inside [...] and [^...].  */
-                if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\')
-                  {
-                    if (p == pend) FREE_STACK_RETURN (REG_EESCAPE);
-
-                    PATFETCH (c1);
-                    SET_LIST_BIT (c1);
-		    range_start = c1;
-                    continue;
-                  }
-
-                /* Could be the end of the bracket expression.  If it's
-                   not (i.e., when the bracket expression is `[]' so
-                   far), the ']' character bit gets set way below.  */
-                if (c == ']' && p != p1 + 1)
-                  break;
-
-                /* Look ahead to see if it's a range when the last thing
-                   was a character class.  */
-                if (had_char_class && c == '-' && *p != ']')
-                  FREE_STACK_RETURN (REG_ERANGE);
-
-                /* Look ahead to see if it's a range when the last thing
-                   was a character: if this is a hyphen not at the
-                   beginning or the end of a list, then it's the range
-                   operator.  */
-                if (c == '-'
-                    && !(p - 2 >= pattern && p[-2] == '[')
-                    && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^')
-                    && *p != ']')
-                  {
-                    reg_errcode_t ret
-                      = compile_range (range_start, &p, pend, translate,
-				       syntax, b);
-                    if (ret != REG_NOERROR) FREE_STACK_RETURN (ret);
-		    range_start = 0xffffffff;
-                  }
-
-                else if (p[0] == '-' && p[1] != ']')
-                  { /* This handles ranges made up of characters only.  */
-                    reg_errcode_t ret;
-
-		    /* Move past the `-'.  */
-                    PATFETCH (c1);
-
-                    ret = compile_range (c, &p, pend, translate, syntax, b);
-                    if (ret != REG_NOERROR) FREE_STACK_RETURN (ret);
-		    range_start = 0xffffffff;
-                  }
-
-                /* See if we're at the beginning of a possible character
-                   class.  */
-
-                else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':')
-                  { /* Leave room for the null.  */
-                    char str[CHAR_CLASS_MAX_LENGTH + 1];
-
-                    PATFETCH (c);
-                    c1 = 0;
-
-                    /* If pattern is `[[:'.  */
-                    if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
-
-                    for (;;)
-                      {
-                        PATFETCH (c);
-                        if ((c == ':' && *p == ']') || p == pend)
-                          break;
-			if (c1 < CHAR_CLASS_MAX_LENGTH)
-			  str[c1++] = c;
-			else
-			  /* This is in any case an invalid class name.  */
-			  str[0] = '\0';
-                      }
-                    str[c1] = '\0';
-
-                    /* If isn't a word bracketed by `[:' and `:]':
-                       undo the ending character, the letters, and leave
-                       the leading `:' and `[' (but set bits for them).  */
-                    if (c == ':' && *p == ']')
-                      {
-#if defined _LIBC || WIDE_CHAR_SUPPORT
-                        boolean is_lower = STREQ (str, "lower");
-                        boolean is_upper = STREQ (str, "upper");
-			wctype_t wt;
-                        int ch;
-
-			wt = IS_CHAR_CLASS (str);
-			if (wt == 0)
-			  FREE_STACK_RETURN (REG_ECTYPE);
-
-                        /* Throw away the ] at the end of the character
-                           class.  */
-                        PATFETCH (c);
-
-                        if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
-
-                        for (ch = 0; ch < 1 << BYTEWIDTH; ++ch)
-			  {
-# ifdef _LIBC
-			    if (__iswctype (__btowc (ch), wt))
-			      SET_LIST_BIT (ch);
-# else
-			    if (iswctype (btowc (ch), wt))
-			      SET_LIST_BIT (ch);
-# endif
-
-			    if (translate && (is_upper || is_lower)
-				&& (ISUPPER (ch) || ISLOWER (ch)))
-			      SET_LIST_BIT (ch);
-			  }
-
-                        had_char_class = true;
-#else
-                        int ch;
-                        boolean is_alnum = STREQ (str, "alnum");
-                        boolean is_alpha = STREQ (str, "alpha");
-                        boolean is_blank = STREQ (str, "blank");
-                        boolean is_cntrl = STREQ (str, "cntrl");
-                        boolean is_digit = STREQ (str, "digit");
-                        boolean is_graph = STREQ (str, "graph");
-                        boolean is_lower = STREQ (str, "lower");
-                        boolean is_print = STREQ (str, "print");
-                        boolean is_punct = STREQ (str, "punct");
-                        boolean is_space = STREQ (str, "space");
-                        boolean is_upper = STREQ (str, "upper");
-                        boolean is_xdigit = STREQ (str, "xdigit");
-
-                        if (!IS_CHAR_CLASS (str))
-			  FREE_STACK_RETURN (REG_ECTYPE);
-
-                        /* Throw away the ] at the end of the character
-                           class.  */
-                        PATFETCH (c);
-
-                        if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
-
-                        for (ch = 0; ch < 1 << BYTEWIDTH; ch++)
-                          {
-			    /* This was split into 3 if's to
-			       avoid an arbitrary limit in some compiler.  */
-                            if (   (is_alnum  && ISALNUM (ch))
-                                || (is_alpha  && ISALPHA (ch))
-                                || (is_blank  && ISBLANK (ch))
-                                || (is_cntrl  && ISCNTRL (ch)))
-			      SET_LIST_BIT (ch);
-			    if (   (is_digit  && ISDIGIT (ch))
-                                || (is_graph  && ISGRAPH (ch))
-                                || (is_lower  && ISLOWER (ch))
-                                || (is_print  && ISPRINT (ch)))
-			      SET_LIST_BIT (ch);
-			    if (   (is_punct  && ISPUNCT (ch))
-                                || (is_space  && ISSPACE (ch))
-                                || (is_upper  && ISUPPER (ch))
-                                || (is_xdigit && ISXDIGIT (ch)))
-			      SET_LIST_BIT (ch);
-			    if (   translate && (is_upper || is_lower)
-				&& (ISUPPER (ch) || ISLOWER (ch)))
-			      SET_LIST_BIT (ch);
-                          }
-                        had_char_class = true;
-#endif	/* libc || wctype.h */
-                      }
-                    else
-                      {
-                        c1++;
-                        while (c1--)
-                          PATUNFETCH;
-                        SET_LIST_BIT ('[');
-                        SET_LIST_BIT (':');
-			range_start = ':';
-                        had_char_class = false;
-                      }
-                  }
-                else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == '=')
-		  {
-		    unsigned char str[MB_LEN_MAX + 1];
-#ifdef _LIBC
-		    uint32_t nrules =
-		      _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
-#endif
-
-		    PATFETCH (c);
-		    c1 = 0;
-
-		    /* If pattern is `[[='.  */
-		    if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
-
-		    for (;;)
-		      {
-			PATFETCH (c);
-			if ((c == '=' && *p == ']') || p == pend)
-			  break;
-			if (c1 < MB_LEN_MAX)
-			  str[c1++] = c;
-			else
-			  /* This is in any case an invalid class name.  */
-			  str[0] = '\0';
-                      }
-		    str[c1] = '\0';
-
-		    if (c == '=' && *p == ']' && str[0] != '\0')
-		      {
-			/* If we have no collation data we use the default
-			   collation in which each character is in a class
-			   by itself.  It also means that ASCII is the
-			   character set and therefore we cannot have character
-			   with more than one byte in the multibyte
-			   representation.  */
-#ifdef _LIBC
-			if (nrules == 0)
-#endif
-			  {
-			    if (c1 != 1)
-			      FREE_STACK_RETURN (REG_ECOLLATE);
-
-			    /* Throw away the ] at the end of the equivalence
-			       class.  */
-			    PATFETCH (c);
-
-			    /* Set the bit for the character.  */
-			    SET_LIST_BIT (str[0]);
-			  }
-#ifdef _LIBC
-			else
-			  {
-			    /* Try to match the byte sequence in `str' against
-			       those known to the collate implementation.
-			       First find out whether the bytes in `str' are
-			       actually from exactly one character.  */
-			    const int32_t *table;
-			    const unsigned char *weights;
-			    const unsigned char *extra;
-			    const int32_t *indirect;
-			    int32_t idx;
-			    const unsigned char *cp = str;
-			    int ch;
-
-			    /* This #include defines a local function!  */
-# include <locale/weight.h>
-
-			    table = (const int32_t *)
-			      _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
-			    weights = (const unsigned char *)
-			      _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB);
-			    extra = (const unsigned char *)
-			      _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
-			    indirect = (const int32_t *)
-			      _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB);
-
-			    idx = findidx (&cp);
-			    if (idx == 0 || cp < str + c1)
-			      /* This is no valid character.  */
-			      FREE_STACK_RETURN (REG_ECOLLATE);
-
-			    /* Throw away the ] at the end of the equivalence
-			       class.  */
-			    PATFETCH (c);
-
-			    /* Now we have to go throught the whole table
-			       and find all characters which have the same
-			       first level weight.
-
-			       XXX Note that this is not entirely correct.
-			       we would have to match multibyte sequences
-			       but this is not possible with the current
-			       implementation.  */
-			    for (ch = 1; ch < 256; ++ch)
-			      /* XXX This test would have to be changed if we
-				 would allow matching multibyte sequences.  */
-			      if (table[ch] > 0)
-				{
-				  int32_t idx2 = table[ch];
-				  size_t len = weights[idx2];
-
-				  /* Test whether the lenghts match.  */
-				  if (weights[idx] == len)
-				    {
-				      /* They do.  New compare the bytes of
-					 the weight.  */
-				      size_t cnt = 0;
-
-				      while (cnt < len
-					     && (weights[idx + 1 + cnt]
-						 == weights[idx2 + 1 + cnt]))
-					++len;
-
-				      if (cnt == len)
-					/* They match.  Mark the character as
-					   acceptable.  */
-					SET_LIST_BIT (ch);
-				    }
-				}
-			  }
-#endif
-			had_char_class = true;
-		      }
-                    else
-                      {
-                        c1++;
-                        while (c1--)
-                          PATUNFETCH;
-                        SET_LIST_BIT ('[');
-                        SET_LIST_BIT ('=');
-			range_start = '=';
-                        had_char_class = false;
-                      }
-		  }
-                else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == '.')
-		  {
-		    unsigned char str[128];	/* Should be large enough.  */
-#ifdef _LIBC
-		    uint32_t nrules =
-		      _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
-#endif
-
-		    PATFETCH (c);
-		    c1 = 0;
-
-		    /* If pattern is `[[='.  */
-		    if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
-
-		    for (;;)
-		      {
-			PATFETCH (c);
-			if ((c == '.' && *p == ']') || p == pend)
-			  break;
-			if (c1 < sizeof (str))
-			  str[c1++] = c;
-			else
-			  /* This is in any case an invalid class name.  */
-			  str[0] = '\0';
-                      }
-		    str[c1] = '\0';
-
-		    if (c == '.' && *p == ']' && str[0] != '\0')
-		      {
-			/* If we have no collation data we use the default
-			   collation in which each character is the name
-			   for its own class which contains only the one
-			   character.  It also means that ASCII is the
-			   character set and therefore we cannot have character
-			   with more than one byte in the multibyte
-			   representation.  */
-#ifdef _LIBC
-			if (nrules == 0)
-#endif
-			  {
-			    if (c1 != 1)
-			      FREE_STACK_RETURN (REG_ECOLLATE);
-
-			    /* Throw away the ] at the end of the equivalence
-			       class.  */
-			    PATFETCH (c);
-
-			    /* Set the bit for the character.  */
-			    SET_LIST_BIT (str[0]);
-			    range_start = ((const unsigned char *) str)[0];
-			  }
-#ifdef _LIBC
-			else
-			  {
-			    /* Try to match the byte sequence in `str' against
-			       those known to the collate implementation.
-			       First find out whether the bytes in `str' are
-			       actually from exactly one character.  */
-			    int32_t table_size;
-			    const int32_t *symb_table;
-			    const unsigned char *extra;
-			    int32_t idx;
-			    int32_t elem;
-			    int32_t second;
-			    int32_t hash;
-
-			    table_size =
-			      _NL_CURRENT_WORD (LC_COLLATE,
-						_NL_COLLATE_SYMB_HASH_SIZEMB);
-			    symb_table = (const int32_t *)
-			      _NL_CURRENT (LC_COLLATE,
-					   _NL_COLLATE_SYMB_TABLEMB);
-			    extra = (const unsigned char *)
-			      _NL_CURRENT (LC_COLLATE,
-					   _NL_COLLATE_SYMB_EXTRAMB);
-
-			    /* Locate the character in the hashing table.  */
-			    hash = elem_hash (str, c1);
-
-			    idx = 0;
-			    elem = hash % table_size;
-			    second = hash % (table_size - 2);
-			    while (symb_table[2 * elem] != 0)
-			      {
-				/* First compare the hashing value.  */
-				if (symb_table[2 * elem] == hash
-				    && c1 == extra[symb_table[2 * elem + 1]]
-				    && memcmp (str,
-					       &extra[symb_table[2 * elem + 1]
-						     + 1],
-					       c1) == 0)
-				  {
-				    /* Yep, this is the entry.  */
-				    idx = symb_table[2 * elem + 1];
-				    idx += 1 + extra[idx];
-				    break;
-				  }
-
-				/* Next entry.  */
-				elem += second;
-			      }
-
-			    if (symb_table[2 * elem] == 0)
-			      /* This is no valid character.  */
-			      FREE_STACK_RETURN (REG_ECOLLATE);
-
-			    /* Throw away the ] at the end of the equivalence
-			       class.  */
-			    PATFETCH (c);
-
-			    /* Now add the multibyte character(s) we found
-			       to the accept list.
-
-			       XXX Note that this is not entirely correct.
-			       we would have to match multibyte sequences
-			       but this is not possible with the current
-			       implementation.  Also, we have to match
-			       collating symbols, which expand to more than
-			       one file, as a whole and not allow the
-			       individual bytes.  */
-			    c1 = extra[idx++];
-			    if (c1 == 1)
-			      range_start = extra[idx];
-			    while (c1-- > 0)
-			      {
-				SET_LIST_BIT (extra[idx]);
-				++idx;
-			      }
-			  }
-#endif
-			had_char_class = false;
-		      }
-                    else
-                      {
-                        c1++;
-                        while (c1--)
-                          PATUNFETCH;
-                        SET_LIST_BIT ('[');
-                        SET_LIST_BIT ('.');
-			range_start = '.';
-                        had_char_class = false;
-                      }
-		  }
-                else
-                  {
-                    had_char_class = false;
-                    SET_LIST_BIT (c);
-		    range_start = c;
-                  }
-              }
-
-            /* Discard any (non)matching list bytes that are all 0 at the
-               end of the map.  Decrease the map-length byte too.  */
-            while ((int) b[-1] > 0 && b[b[-1] - 1] == 0)
-              b[-1]--;
-            b += b[-1];
-          }
-          break;
-
-
-	case '(':
-          if (syntax & RE_NO_BK_PARENS)
-            goto handle_open;
-          else
-            goto normal_char;
-
-
-        case ')':
-          if (syntax & RE_NO_BK_PARENS)
-            goto handle_close;
-          else
-            goto normal_char;
-
-
-        case '\n':
-          if (syntax & RE_NEWLINE_ALT)
-            goto handle_alt;
-          else
-            goto normal_char;
-
-
-	case '|':
-          if (syntax & RE_NO_BK_VBAR)
-            goto handle_alt;
-          else
-            goto normal_char;
-
-
-        case '{':
-           if (syntax & RE_INTERVALS && syntax & RE_NO_BK_BRACES)
-             goto handle_interval;
-           else
-             goto normal_char;
-
-
-        case '\\':
-          if (p == pend) FREE_STACK_RETURN (REG_EESCAPE);
-
-          /* Do not translate the character after the \, so that we can
-             distinguish, e.g., \B from \b, even if we normally would
-             translate, e.g., B to b.  */
-          PATFETCH_RAW (c);
-
-          switch (c)
-            {
-            case '(':
-              if (syntax & RE_NO_BK_PARENS)
-                goto normal_backslash;
-
-            handle_open:
-              bufp->re_nsub++;
-              regnum++;
-
-              if (COMPILE_STACK_FULL)
-                {
-                  RETALLOC (compile_stack.stack, compile_stack.size << 1,
-                            compile_stack_elt_t);
-                  if (compile_stack.stack == NULL) return REG_ESPACE;
-
-                  compile_stack.size <<= 1;
-                }
-
-              /* These are the values to restore when we hit end of this
-                 group.  They are all relative offsets, so that if the
-                 whole pattern moves because of realloc, they will still
-                 be valid.  */
-              COMPILE_STACK_TOP.begalt_offset = begalt - bufp->buffer;
-              COMPILE_STACK_TOP.fixup_alt_jump
-                = fixup_alt_jump ? fixup_alt_jump - bufp->buffer + 1 : 0;
-              COMPILE_STACK_TOP.laststart_offset = b - bufp->buffer;
-              COMPILE_STACK_TOP.regnum = regnum;
-
-              /* We will eventually replace the 0 with the number of
-                 groups inner to this one.  But do not push a
-                 start_memory for groups beyond the last one we can
-                 represent in the compiled pattern.  */
-              if (regnum <= MAX_REGNUM)
-                {
-                  COMPILE_STACK_TOP.inner_group_offset = b - bufp->buffer + 2;
-                  BUF_PUSH_3 (start_memory, regnum, 0);
-                }
-
-              compile_stack.avail++;
-
-              fixup_alt_jump = 0;
-              laststart = 0;
-              begalt = b;
-	      /* If we've reached MAX_REGNUM groups, then this open
-		 won't actually generate any code, so we'll have to
-		 clear pending_exact explicitly.  */
-	      pending_exact = 0;
-              break;
-
-
-            case ')':
-              if (syntax & RE_NO_BK_PARENS) goto normal_backslash;
-
-              if (COMPILE_STACK_EMPTY)
-		{
-		  if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
-		    goto normal_backslash;
-		  else
-		    FREE_STACK_RETURN (REG_ERPAREN);
-		}
-
-            handle_close:
-              if (fixup_alt_jump)
-                { /* Push a dummy failure point at the end of the
-                     alternative for a possible future
-                     `pop_failure_jump' to pop.  See comments at
-                     `push_dummy_failure' in `re_match_2'.  */
-                  BUF_PUSH (push_dummy_failure);
-
-                  /* We allocated space for this jump when we assigned
-                     to `fixup_alt_jump', in the `handle_alt' case below.  */
-                  STORE_JUMP (jump_past_alt, fixup_alt_jump, b - 1);
-                }
-
-              /* See similar code for backslashed left paren above.  */
-              if (COMPILE_STACK_EMPTY)
-		{
-		  if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
-		    goto normal_char;
-		  else
-		    FREE_STACK_RETURN (REG_ERPAREN);
-		}
-
-              /* Since we just checked for an empty stack above, this
-                 ``can't happen''.  */
-              assert (compile_stack.avail != 0);
-              {
-                /* We don't just want to restore into `regnum', because
-                   later groups should continue to be numbered higher,
-                   as in `(ab)c(de)' -- the second group is #2.  */
-                regnum_t this_group_regnum;
-
-                compile_stack.avail--;
-                begalt = bufp->buffer + COMPILE_STACK_TOP.begalt_offset;
-                fixup_alt_jump
-                  = COMPILE_STACK_TOP.fixup_alt_jump
-                    ? bufp->buffer + COMPILE_STACK_TOP.fixup_alt_jump - 1
-                    : 0;
-                laststart = bufp->buffer + COMPILE_STACK_TOP.laststart_offset;
-                this_group_regnum = COMPILE_STACK_TOP.regnum;
-		/* If we've reached MAX_REGNUM groups, then this open
-		   won't actually generate any code, so we'll have to
-		   clear pending_exact explicitly.  */
-		pending_exact = 0;
-
-                /* We're at the end of the group, so now we know how many
-                   groups were inside this one.  */
-                if (this_group_regnum <= MAX_REGNUM)
-                  {
-                    unsigned char *inner_group_loc
-                      = bufp->buffer + COMPILE_STACK_TOP.inner_group_offset;
-
-                    *inner_group_loc = regnum - this_group_regnum;
-                    BUF_PUSH_3 (stop_memory, this_group_regnum,
-                                regnum - this_group_regnum);
-                  }
-              }
-              break;
-
-
-            case '|':					/* `\|'.  */
-              if (syntax & RE_LIMITED_OPS || syntax & RE_NO_BK_VBAR)
-                goto normal_backslash;
-            handle_alt:
-              if (syntax & RE_LIMITED_OPS)
-                goto normal_char;
-
-              /* Insert before the previous alternative a jump which
-                 jumps to this alternative if the former fails.  */
-              GET_BUFFER_SPACE (3);
-              INSERT_JUMP (on_failure_jump, begalt, b + 6);
-              pending_exact = 0;
-              b += 3;
-
-              /* The alternative before this one has a jump after it
-                 which gets executed if it gets matched.  Adjust that
-                 jump so it will jump to this alternative's analogous
-                 jump (put in below, which in turn will jump to the next
-                 (if any) alternative's such jump, etc.).  The last such
-                 jump jumps to the correct final destination.  A picture:
-                          _____ _____
-                          |   | |   |
-                          |   v |   v
-                         a | b   | c
-
-                 If we are at `b', then fixup_alt_jump right now points to a
-                 three-byte space after `a'.  We'll put in the jump, set
-                 fixup_alt_jump to right after `b', and leave behind three
-                 bytes which we'll fill in when we get to after `c'.  */
-
-              if (fixup_alt_jump)
-                STORE_JUMP (jump_past_alt, fixup_alt_jump, b);
-
-              /* Mark and leave space for a jump after this alternative,
-                 to be filled in later either by next alternative or
-                 when know we're at the end of a series of alternatives.  */
-              fixup_alt_jump = b;
-              GET_BUFFER_SPACE (3);
-              b += 3;
-
-              laststart = 0;
-              begalt = b;
-              break;
-
-
-            case '{':
-              /* If \{ is a literal.  */
-              if (!(syntax & RE_INTERVALS)
-                     /* If we're at `\{' and it's not the open-interval
-                        operator.  */
-		  || (syntax & RE_NO_BK_BRACES))
-                goto normal_backslash;
-
-            handle_interval:
-              {
-                /* If got here, then the syntax allows intervals.  */
-
-                /* At least (most) this many matches must be made.  */
-                int lower_bound = -1, upper_bound = -1;
-
-                beg_interval = p - 1;
-
-                if (p == pend)
-                  {
-                    if (!(syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
-                      goto unfetch_interval;
-                    else
-                      FREE_STACK_RETURN (REG_EBRACE);
-                  }
-
-                GET_UNSIGNED_NUMBER (lower_bound);
-
-                if (c == ',')
-                  {
-                    GET_UNSIGNED_NUMBER (upper_bound);
-		    if ((!(syntax & RE_NO_BK_BRACES) && c != '\\')
-			|| ((syntax & RE_NO_BK_BRACES) && c != '}'))
-		      FREE_STACK_RETURN (REG_BADBR);
-
-		    if (upper_bound < 0)
-		      upper_bound = RE_DUP_MAX;
-                  }
-                else
-                  /* Interval such as `{1}' => match exactly once. */
-                  upper_bound = lower_bound;
-
-                if (lower_bound < 0 || upper_bound > RE_DUP_MAX
-                    || lower_bound > upper_bound)
-                  {
-                    if (!(syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
-                      goto unfetch_interval;
-                    else
-                      FREE_STACK_RETURN (REG_BADBR);
-                  }
-
-                if (!(syntax & RE_NO_BK_BRACES))
-                  {
-                    if (c != '\\') FREE_STACK_RETURN (REG_EBRACE);
-
-                    PATFETCH (c);
-                  }
-
-                if (c != '}')
-                  {
-                    if (!(syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
-                      goto unfetch_interval;
-                    else
-                      FREE_STACK_RETURN (REG_BADBR);
-                  }
-
-                /* We just parsed a valid interval.  */
-
-                /* If it's invalid to have no preceding re.  */
-                if (!laststart)
-                  {
-                    if (syntax & RE_CONTEXT_INVALID_OPS)
-                      FREE_STACK_RETURN (REG_BADRPT);
-                    else if (syntax & RE_CONTEXT_INDEP_OPS)
-                      laststart = b;
-                    else
-                      goto unfetch_interval;
-                  }
-
-                /* If the upper bound is zero, don't want to succeed at
-                   all; jump from `laststart' to `b + 3', which will be
-                   the end of the buffer after we insert the jump.  */
-                 if (upper_bound == 0)
-                   {
-                     GET_BUFFER_SPACE (3);
-                     INSERT_JUMP (jump, laststart, b + 3);
-                     b += 3;
-                   }
-
-                 /* Otherwise, we have a nontrivial interval.  When
-                    we're all done, the pattern will look like:
-                      set_number_at <jump count> <upper bound>
-                      set_number_at <succeed_n count> <lower bound>
-                      succeed_n <after jump addr> <succeed_n count>
-                      <body of loop>
-                      jump_n <succeed_n addr> <jump count>
-                    (The upper bound and `jump_n' are omitted if
-                    `upper_bound' is 1, though.)  */
-                 else
-                   { /* If the upper bound is > 1, we need to insert
-                        more at the end of the loop.  */
-                     unsigned nbytes = 10 + (upper_bound > 1) * 10;
-
-                     GET_BUFFER_SPACE (nbytes);
-
-                     /* Initialize lower bound of the `succeed_n', even
-                        though it will be set during matching by its
-                        attendant `set_number_at' (inserted next),
-                        because `re_compile_fastmap' needs to know.
-                        Jump to the `jump_n' we might insert below.  */
-                     INSERT_JUMP2 (succeed_n, laststart,
-                                   b + 5 + (upper_bound > 1) * 5,
-                                   lower_bound);
-                     b += 5;
-
-                     /* Code to initialize the lower bound.  Insert
-                        before the `succeed_n'.  The `5' is the last two
-                        bytes of this `set_number_at', plus 3 bytes of
-                        the following `succeed_n'.  */
-                     insert_op2 (set_number_at, laststart, 5, lower_bound, b);
-                     b += 5;
-
-                     if (upper_bound > 1)
-                       { /* More than one repetition is allowed, so
-                            append a backward jump to the `succeed_n'
-                            that starts this interval.
-
-                            When we've reached this during matching,
-                            we'll have matched the interval once, so
-                            jump back only `upper_bound - 1' times.  */
-                         STORE_JUMP2 (jump_n, b, laststart + 5,
-                                      upper_bound - 1);
-                         b += 5;
-
-                         /* The location we want to set is the second
-                            parameter of the `jump_n'; that is `b-2' as
-                            an absolute address.  `laststart' will be
-                            the `set_number_at' we're about to insert;
-                            `laststart+3' the number to set, the source
-                            for the relative address.  But we are
-                            inserting into the middle of the pattern --
-                            so everything is getting moved up by 5.
-                            Conclusion: (b - 2) - (laststart + 3) + 5,
-                            i.e., b - laststart.
-
-                            We insert this at the beginning of the loop
-                            so that if we fail during matching, we'll
-                            reinitialize the bounds.  */
-                         insert_op2 (set_number_at, laststart, b - laststart,
-                                     upper_bound - 1, b);
-                         b += 5;
-                       }
-                   }
-                pending_exact = 0;
-                beg_interval = NULL;
-              }
-              break;
-
-            unfetch_interval:
-              /* If an invalid interval, match the characters as literals.  */
-               assert (beg_interval);
-               p = beg_interval;
-               beg_interval = NULL;
-
-               /* normal_char and normal_backslash need `c'.  */
-               PATFETCH (c);
-
-               if (!(syntax & RE_NO_BK_BRACES))
-                 {
-                   if (p > pattern  &&  p[-1] == '\\')
-                     goto normal_backslash;
-                 }
-               goto normal_char;
-
-#ifdef emacs
-            /* There is no way to specify the before_dot and after_dot
-               operators.  rms says this is ok.  --karl  */
-            case '=':
-              BUF_PUSH (at_dot);
-              break;
-
-            case 's':
-              laststart = b;
-              PATFETCH (c);
-              BUF_PUSH_2 (syntaxspec, syntax_spec_code[c]);
-              break;
-
-            case 'S':
-              laststart = b;
-              PATFETCH (c);
-              BUF_PUSH_2 (notsyntaxspec, syntax_spec_code[c]);
-              break;
-#endif /* emacs */
-
-
-            case 'w':
-	      if (syntax & RE_NO_GNU_OPS)
-		goto normal_char;
-              laststart = b;
-              BUF_PUSH (wordchar);
-              break;
-
-
-            case 'W':
-	      if (syntax & RE_NO_GNU_OPS)
-		goto normal_char;
-              laststart = b;
-              BUF_PUSH (notwordchar);
-              break;
-
-
-            case '<':
-	      if (syntax & RE_NO_GNU_OPS)
-		goto normal_char;
-              BUF_PUSH (wordbeg);
-              break;
-
-            case '>':
-	      if (syntax & RE_NO_GNU_OPS)
-		goto normal_char;
-              BUF_PUSH (wordend);
-              break;
-
-            case 'b':
-	      if (syntax & RE_NO_GNU_OPS)
-		goto normal_char;
-              BUF_PUSH (wordbound);
-              break;
-
-            case 'B':
-	      if (syntax & RE_NO_GNU_OPS)
-		goto normal_char;
-              BUF_PUSH (notwordbound);
-              break;
-
-            case '`':
-	      if (syntax & RE_NO_GNU_OPS)
-		goto normal_char;
-              BUF_PUSH (begbuf);
-              break;
-
-            case '\'':
-	      if (syntax & RE_NO_GNU_OPS)
-		goto normal_char;
-              BUF_PUSH (endbuf);
-              break;
-
-            case '1': case '2': case '3': case '4': case '5':
-            case '6': case '7': case '8': case '9':
-              if (syntax & RE_NO_BK_REFS)
-                goto normal_char;
-
-              c1 = c - '0';
-
-              if (c1 > regnum)
-                FREE_STACK_RETURN (REG_ESUBREG);
-
-              /* Can't back reference to a subexpression if inside of it.  */
-              if (group_in_compile_stack (compile_stack, (regnum_t) c1))
-                goto normal_char;
-
-              laststart = b;
-              BUF_PUSH_2 (duplicate, c1);
-              break;
-
-
-            case '+':
-            case '?':
-              if (syntax & RE_BK_PLUS_QM)
-                goto handle_plus;
-              else
-                goto normal_backslash;
-
-            default:
-            normal_backslash:
-              /* You might think it would be useful for \ to mean
-                 not to translate; but if we don't translate it
-                 it will never match anything.  */
-              c = TRANSLATE (c);
-              goto normal_char;
-            }
-          break;
-
-
-	default:
-        /* Expects the character in `c'.  */
-	normal_char:
-	      /* If no exactn currently being built.  */
-          if (!pending_exact
-
-              /* If last exactn not at current position.  */
-              || pending_exact + *pending_exact + 1 != b
-
-              /* We have only one byte following the exactn for the count.  */
-	      || *pending_exact == (1 << BYTEWIDTH) - 1
-
-              /* If followed by a repetition operator.  */
-              || *p == '*' || *p == '^'
-	      || ((syntax & RE_BK_PLUS_QM)
-		  ? *p == '\\' && (p[1] == '+' || p[1] == '?')
-		  : (*p == '+' || *p == '?'))
-	      || ((syntax & RE_INTERVALS)
-                  && ((syntax & RE_NO_BK_BRACES)
-		      ? *p == '{'
-                      : (p[0] == '\\' && p[1] == '{'))))
-	    {
-	      /* Start building a new exactn.  */
-
-              laststart = b;
-
-	      BUF_PUSH_2 (exactn, 0);
-	      pending_exact = b - 1;
-            }
-
-	  BUF_PUSH (c);
-          (*pending_exact)++;
-	  break;
-        } /* switch (c) */
-    } /* while p != pend */
-
-
-  /* Through the pattern now.  */
-
-  if (fixup_alt_jump)
-    STORE_JUMP (jump_past_alt, fixup_alt_jump, b);
-
-  if (!COMPILE_STACK_EMPTY)
-    FREE_STACK_RETURN (REG_EPAREN);
-
-  /* If we don't want backtracking, force success
-     the first time we reach the end of the compiled pattern.  */
-  if (syntax & RE_NO_POSIX_BACKTRACKING)
-    BUF_PUSH (succeed);
-
-  free (compile_stack.stack);
-
-  /* We have succeeded; set the length of the buffer.  */
-  bufp->used = b - bufp->buffer;
-
-#ifdef DEBUG
-  if (debug)
-    {
-      DEBUG_PRINT1 ("\nCompiled pattern: \n");
-      print_compiled_pattern (bufp);
-    }
-#endif /* DEBUG */
-
-#ifndef MATCH_MAY_ALLOCATE
-  /* Initialize the failure stack to the largest possible stack.  This
-     isn't necessary unless we're trying to avoid calling alloca in
-     the search and match routines.  */
-  {
-    int num_regs = bufp->re_nsub + 1;
-
-    /* Since DOUBLE_FAIL_STACK refuses to double only if the current size
-       is strictly greater than re_max_failures, the largest possible stack
-       is 2 * re_max_failures failure points.  */
-    if (fail_stack.size < (2 * re_max_failures * MAX_FAILURE_ITEMS))
-      {
-	fail_stack.size = (2 * re_max_failures * MAX_FAILURE_ITEMS);
-
-# ifdef emacs
-	if (! fail_stack.stack)
-	  fail_stack.stack
-	    = (fail_stack_elt_t *) xmalloc (fail_stack.size
-					    * sizeof (fail_stack_elt_t));
-	else
-	  fail_stack.stack
-	    = (fail_stack_elt_t *) xrealloc (fail_stack.stack,
-					     (fail_stack.size
-					      * sizeof (fail_stack_elt_t)));
-# else /* not emacs */
-	if (! fail_stack.stack)
-	  fail_stack.stack
-	    = (fail_stack_elt_t *) malloc (fail_stack.size
-					   * sizeof (fail_stack_elt_t));
-	else
-	  fail_stack.stack
-	    = (fail_stack_elt_t *) realloc (fail_stack.stack,
-					    (fail_stack.size
-					     * sizeof (fail_stack_elt_t)));
-# endif /* not emacs */
-      }
-
-    regex_grow_registers (num_regs);
-  }
-#endif /* not MATCH_MAY_ALLOCATE */
-
-  return REG_NOERROR;
-} /* regex_compile */
-
-/* Subroutines for `regex_compile'.  */
-
-/* Store OP at LOC followed by two-byte integer parameter ARG.  */
-
-static void
-store_op1 (op, loc, arg)
-    re_opcode_t op;
-    unsigned char *loc;
-    int arg;
-{
-  *loc = (unsigned char) op;
-  STORE_NUMBER (loc + 1, arg);
-}
-
-
-/* Like `store_op1', but for two two-byte parameters ARG1 and ARG2.  */
-
-static void
-store_op2 (op, loc, arg1, arg2)
-    re_opcode_t op;
-    unsigned char *loc;
-    int arg1, arg2;
-{
-  *loc = (unsigned char) op;
-  STORE_NUMBER (loc + 1, arg1);
-  STORE_NUMBER (loc + 3, arg2);
-}
-
-
-/* Copy the bytes from LOC to END to open up three bytes of space at LOC
-   for OP followed by two-byte integer parameter ARG.  */
-
-static void
-insert_op1 (op, loc, arg, end)
-    re_opcode_t op;
-    unsigned char *loc;
-    int arg;
-    unsigned char *end;
-{
-  register unsigned char *pfrom = end;
-  register unsigned char *pto = end + 3;
-
-  while (pfrom != loc)
-    *--pto = *--pfrom;
-
-  store_op1 (op, loc, arg);
-}
-
-
-/* Like `insert_op1', but for two two-byte parameters ARG1 and ARG2.  */
-
-static void
-insert_op2 (op, loc, arg1, arg2, end)
-    re_opcode_t op;
-    unsigned char *loc;
-    int arg1, arg2;
-    unsigned char *end;
-{
-  register unsigned char *pfrom = end;
-  register unsigned char *pto = end + 5;
-
-  while (pfrom != loc)
-    *--pto = *--pfrom;
-
-  store_op2 (op, loc, arg1, arg2);
-}
-
-
-/* P points to just after a ^ in PATTERN.  Return true if that ^ comes
-   after an alternative or a begin-subexpression.  We assume there is at
-   least one character before the ^.  */
-
-static boolean
-at_begline_loc_p (pattern, p, syntax)
-    const char *pattern, *p;
-    reg_syntax_t syntax;
-{
-  const char *prev = p - 2;
-  boolean prev_prev_backslash = prev > pattern && prev[-1] == '\\';
-
-  return
-       /* After a subexpression?  */
-       (*prev == '(' && (syntax & RE_NO_BK_PARENS || prev_prev_backslash))
-       /* After an alternative?  */
-    || (*prev == '|' && (syntax & RE_NO_BK_VBAR || prev_prev_backslash));
-}
-
-
-/* The dual of at_begline_loc_p.  This one is for $.  We assume there is
-   at least one character after the $, i.e., `P < PEND'.  */
-
-static boolean
-at_endline_loc_p (p, pend, syntax)
-    const char *p, *pend;
-    reg_syntax_t syntax;
-{
-  const char *next = p;
-  boolean next_backslash = *next == '\\';
-  const char *next_next = p + 1 < pend ? p + 1 : 0;
-
-  return
-       /* Before a subexpression?  */
-       (syntax & RE_NO_BK_PARENS ? *next == ')'
-        : next_backslash && next_next && *next_next == ')')
-       /* Before an alternative?  */
-    || (syntax & RE_NO_BK_VBAR ? *next == '|'
-        : next_backslash && next_next && *next_next == '|');
-}
-
-
-/* Returns true if REGNUM is in one of COMPILE_STACK's elements and
-   false if it's not.  */
-
-static boolean
-group_in_compile_stack (compile_stack, regnum)
-    compile_stack_type compile_stack;
-    regnum_t regnum;
-{
-  int this_element;
-
-  for (this_element = compile_stack.avail - 1;
-       this_element >= 0;
-       this_element--)
-    if (compile_stack.stack[this_element].regnum == regnum)
-      return true;
-
-  return false;
-}
-
-
-/* Read the ending character of a range (in a bracket expression) from the
-   uncompiled pattern *P_PTR (which ends at PEND).  We assume the
-   starting character is in `P[-2]'.  (`P[-1]' is the character `-'.)
-   Then we set the translation of all bits between the starting and
-   ending characters (inclusive) in the compiled pattern B.
-
-   Return an error code.
-
-   We use these short variable names so we can use the same macros as
-   `regex_compile' itself.  */
-
-static reg_errcode_t
-compile_range (range_start_char, p_ptr, pend, translate, syntax, b)
-     unsigned int range_start_char;
-     const char **p_ptr, *pend;
-     RE_TRANSLATE_TYPE translate;
-     reg_syntax_t syntax;
-     unsigned char *b;
-{
-  unsigned this_char;
-  const char *p = *p_ptr;
-  reg_errcode_t ret;
-#if _LIBC
-  const unsigned char *collseq;
-  unsigned int start_colseq;
-  unsigned int end_colseq;
-#else
-  unsigned end_char;
-#endif
-
-  if (p == pend)
-    return REG_ERANGE;
-
-  /* Have to increment the pointer into the pattern string, so the
-     caller isn't still at the ending character.  */
-  (*p_ptr)++;
-
-  /* Report an error if the range is empty and the syntax prohibits this.  */
-  ret = syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR;
-
-#if _LIBC
-  collseq = (const unsigned char *) _NL_CURRENT (LC_COLLATE,
-						 _NL_COLLATE_COLLSEQMB);
-
-  start_colseq = collseq[(unsigned char) TRANSLATE (range_start_char)];
-  end_colseq = collseq[(unsigned char) TRANSLATE (p[0])];
-  for (this_char = 0; this_char <= (unsigned char) -1; ++this_char)
-    {
-      unsigned int this_colseq = collseq[(unsigned char) TRANSLATE (this_char)];
-
-      if (start_colseq <= this_colseq && this_colseq <= end_colseq)
-	{
-	  SET_LIST_BIT (TRANSLATE (this_char));
-	  ret = REG_NOERROR;
-	}
-    }
-#else
-  /* Here we see why `this_char' has to be larger than an `unsigned
-     char' -- we would otherwise go into an infinite loop, since all
-     characters <= 0xff.  */
-  range_start_char = TRANSLATE (range_start_char);
-  end_char = TRANSLATE (p[0]);
-  for (this_char = range_start_char; this_char <= end_char; ++this_char)
-    {
-      SET_LIST_BIT (TRANSLATE (this_char));
-      ret = REG_NOERROR;
-    }
-#endif
-
-  return ret;
-}
-
-/* re_compile_fastmap computes a ``fastmap'' for the compiled pattern in
-   BUFP.  A fastmap records which of the (1 << BYTEWIDTH) possible
-   characters can start a string that matches the pattern.  This fastmap
-   is used by re_search to skip quickly over impossible starting points.
-
-   The caller must supply the address of a (1 << BYTEWIDTH)-byte data
-   area as BUFP->fastmap.
-
-   We set the `fastmap', `fastmap_accurate', and `can_be_null' fields in
-   the pattern buffer.
-
-   Returns 0 if we succeed, -2 if an internal error.   */
-
-int
-re_compile_fastmap (bufp)
-     struct re_pattern_buffer *bufp;
-{
-  int j, k;
-#ifdef MATCH_MAY_ALLOCATE
-  fail_stack_type fail_stack;
-#endif
-#ifndef REGEX_MALLOC
-  char *destination;
-#endif
-
-  register char *fastmap = bufp->fastmap;
-  unsigned char *pattern = bufp->buffer;
-  unsigned char *p = pattern;
-  register unsigned char *pend = pattern + bufp->used;
-
-#ifdef REL_ALLOC
-  /* This holds the pointer to the failure stack, when
-     it is allocated relocatably.  */
-  fail_stack_elt_t *failure_stack_ptr;
-#endif
-
-  /* Assume that each path through the pattern can be null until
-     proven otherwise.  We set this false at the bottom of switch
-     statement, to which we get only if a particular path doesn't
-     match the empty string.  */
-  boolean path_can_be_null = true;
-
-  /* We aren't doing a `succeed_n' to begin with.  */
-  boolean succeed_n_p = false;
-
-  assert (fastmap != NULL && p != NULL);
-
-  INIT_FAIL_STACK ();
-  bzero (fastmap, 1 << BYTEWIDTH);  /* Assume nothing's valid.  */
-  bufp->fastmap_accurate = 1;	    /* It will be when we're done.  */
-  bufp->can_be_null = 0;
-
-  while (1)
-    {
-      if (p == pend || *p == succeed)
-	{
-	  /* We have reached the (effective) end of pattern.  */
-	  if (!FAIL_STACK_EMPTY ())
-	    {
-	      bufp->can_be_null |= path_can_be_null;
-
-	      /* Reset for next path.  */
-	      path_can_be_null = true;
-
-	      p = fail_stack.stack[--fail_stack.avail].pointer;
-
-	      continue;
-	    }
-	  else
-	    break;
-	}
-
-      /* We should never be about to go beyond the end of the pattern.  */
-      assert (p < pend);
-
-      switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++))
-	{
-
-        /* I guess the idea here is to simply not bother with a fastmap
-           if a backreference is used, since it's too hard to figure out
-           the fastmap for the corresponding group.  Setting
-           `can_be_null' stops `re_search_2' from using the fastmap, so
-           that is all we do.  */
-	case duplicate:
-	  bufp->can_be_null = 1;
-          goto done;
-
-
-      /* Following are the cases which match a character.  These end
-         with `break'.  */
-
-	case exactn:
-          fastmap[p[1]] = 1;
-	  break;
-
-
-        case charset:
-          for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
-	    if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))
-              fastmap[j] = 1;
-	  break;
-
-
-	case charset_not:
-	  /* Chars beyond end of map must be allowed.  */
-	  for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++)
-            fastmap[j] = 1;
-
-	  for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
-	    if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))))
-              fastmap[j] = 1;
-          break;
-
-
-	case wordchar:
-	  for (j = 0; j < (1 << BYTEWIDTH); j++)
-	    if (SYNTAX (j) == Sword)
-	      fastmap[j] = 1;
-	  break;
-
-
-	case notwordchar:
-	  for (j = 0; j < (1 << BYTEWIDTH); j++)
-	    if (SYNTAX (j) != Sword)
-	      fastmap[j] = 1;
-	  break;
-
-
-        case anychar:
-	  {
-	    int fastmap_newline = fastmap['\n'];
-
-	    /* `.' matches anything ...  */
-	    for (j = 0; j < (1 << BYTEWIDTH); j++)
-	      fastmap[j] = 1;
-
-	    /* ... except perhaps newline.  */
-	    if (!(bufp->syntax & RE_DOT_NEWLINE))
-	      fastmap['\n'] = fastmap_newline;
-
-	    /* Return if we have already set `can_be_null'; if we have,
-	       then the fastmap is irrelevant.  Something's wrong here.  */
-	    else if (bufp->can_be_null)
-	      goto done;
-
-	    /* Otherwise, have to check alternative paths.  */
-	    break;
-	  }
-
-#ifdef emacs
-        case syntaxspec:
-	  k = *p++;
-	  for (j = 0; j < (1 << BYTEWIDTH); j++)
-	    if (SYNTAX (j) == (enum syntaxcode) k)
-	      fastmap[j] = 1;
-	  break;
-
-
-	case notsyntaxspec:
-	  k = *p++;
-	  for (j = 0; j < (1 << BYTEWIDTH); j++)
-	    if (SYNTAX (j) != (enum syntaxcode) k)
-	      fastmap[j] = 1;
-	  break;
-
-
-      /* All cases after this match the empty string.  These end with
-         `continue'.  */
-
-
-	case before_dot:
-	case at_dot:
-	case after_dot:
-          continue;
-#endif /* emacs */
-
-
-        case no_op:
-        case begline:
-        case endline:
-	case begbuf:
-	case endbuf:
-	case wordbound:
-	case notwordbound:
-	case wordbeg:
-	case wordend:
-        case push_dummy_failure:
-          continue;
-
-
-	case jump_n:
-        case pop_failure_jump:
-	case maybe_pop_jump:
-	case jump:
-        case jump_past_alt:
-	case dummy_failure_jump:
-          EXTRACT_NUMBER_AND_INCR (j, p);
-	  p += j;
-	  if (j > 0)
-	    continue;
-
-          /* Jump backward implies we just went through the body of a
-             loop and matched nothing.  Opcode jumped to should be
-             `on_failure_jump' or `succeed_n'.  Just treat it like an
-             ordinary jump.  For a * loop, it has pushed its failure
-             point already; if so, discard that as redundant.  */
-          if ((re_opcode_t) *p != on_failure_jump
-	      && (re_opcode_t) *p != succeed_n)
-	    continue;
-
-          p++;
-          EXTRACT_NUMBER_AND_INCR (j, p);
-          p += j;
-
-          /* If what's on the stack is where we are now, pop it.  */
-          if (!FAIL_STACK_EMPTY ()
-	      && fail_stack.stack[fail_stack.avail - 1].pointer == p)
-            fail_stack.avail--;
-
-          continue;
-
-
-        case on_failure_jump:
-        case on_failure_keep_string_jump:
-	handle_on_failure_jump:
-          EXTRACT_NUMBER_AND_INCR (j, p);
-
-          /* For some patterns, e.g., `(a?)?', `p+j' here points to the
-             end of the pattern.  We don't want to push such a point,
-             since when we restore it above, entering the switch will
-             increment `p' past the end of the pattern.  We don't need
-             to push such a point since we obviously won't find any more
-             fastmap entries beyond `pend'.  Such a pattern can match
-             the null string, though.  */
-          if (p + j < pend)
-            {
-              if (!PUSH_PATTERN_OP (p + j, fail_stack))
-		{
-		  RESET_FAIL_STACK ();
-		  return -2;
-		}
-            }
-          else
-            bufp->can_be_null = 1;
-
-          if (succeed_n_p)
-            {
-              EXTRACT_NUMBER_AND_INCR (k, p);	/* Skip the n.  */
-              succeed_n_p = false;
-	    }
-
-          continue;
-
-
-	case succeed_n:
-          /* Get to the number of times to succeed.  */
-          p += 2;
-
-          /* Increment p past the n for when k != 0.  */
-          EXTRACT_NUMBER_AND_INCR (k, p);
-          if (k == 0)
-	    {
-              p -= 4;
-  	      succeed_n_p = true;  /* Spaghetti code alert.  */
-              goto handle_on_failure_jump;
-            }
-          continue;
-
-
-	case set_number_at:
-          p += 4;
-          continue;
-
-
-	case start_memory:
-        case stop_memory:
-	  p += 2;
-	  continue;
-
-
-	default:
-          abort (); /* We have listed all the cases.  */
-        } /* switch *p++ */
-
-      /* Getting here means we have found the possible starting
-         characters for one path of the pattern -- and that the empty
-         string does not match.  We need not follow this path further.
-         Instead, look at the next alternative (remembered on the
-         stack), or quit if no more.  The test at the top of the loop
-         does these things.  */
-      path_can_be_null = false;
-      p = pend;
-    } /* while p */
-
-  /* Set `can_be_null' for the last path (also the first path, if the
-     pattern is empty).  */
-  bufp->can_be_null |= path_can_be_null;
-
- done:
-  RESET_FAIL_STACK ();
-  return 0;
-} /* re_compile_fastmap */
-#ifdef _LIBC
-weak_alias (__re_compile_fastmap, re_compile_fastmap)
-#endif
-
-/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
-   ENDS.  Subsequent matches using PATTERN_BUFFER and REGS will use
-   this memory for recording register information.  STARTS and ENDS
-   must be allocated using the malloc library routine, and must each
-   be at least NUM_REGS * sizeof (regoff_t) bytes long.
-
-   If NUM_REGS == 0, then subsequent matches should allocate their own
-   register data.
-
-   Unless this function is called, the first search or match using
-   PATTERN_BUFFER will allocate its own register data, without
-   freeing the old data.  */
-
-void
-re_set_registers (bufp, regs, num_regs, starts, ends)
-    struct re_pattern_buffer *bufp;
-    struct re_registers *regs;
-    unsigned num_regs;
-    regoff_t *starts, *ends;
-{
-  if (num_regs)
-    {
-      bufp->regs_allocated = REGS_REALLOCATE;
-      regs->num_regs = num_regs;
-      regs->start = starts;
-      regs->end = ends;
-    }
-  else
-    {
-      bufp->regs_allocated = REGS_UNALLOCATED;
-      regs->num_regs = 0;
-      regs->start = regs->end = (regoff_t *) 0;
-    }
-}
-#ifdef _LIBC
-weak_alias (__re_set_registers, re_set_registers)
-#endif
-
-/* Searching routines.  */
-
-/* Like re_search_2, below, but only one string is specified, and
-   doesn't let you say where to stop matching. */
-
-int
-re_search (bufp, string, size, startpos, range, regs)
-     struct re_pattern_buffer *bufp;
-     const char *string;
-     int size, startpos, range;
-     struct re_registers *regs;
-{
-  return re_search_2 (bufp, NULL, 0, string, size, startpos, range,
-		      regs, size);
-}
-#ifdef _LIBC
-weak_alias (__re_search, re_search)
-#endif
-
-
-/* Using the compiled pattern in BUFP->buffer, first tries to match the
-   virtual concatenation of STRING1 and STRING2, starting first at index
-   STARTPOS, then at STARTPOS + 1, and so on.
-
-   STRING1 and STRING2 have length SIZE1 and SIZE2, respectively.
-
-   RANGE is how far to scan while trying to match.  RANGE = 0 means try
-   only at STARTPOS; in general, the last start tried is STARTPOS +
-   RANGE.
-
-   In REGS, return the indices of the virtual concatenation of STRING1
-   and STRING2 that matched the entire BUFP->buffer and its contained
-   subexpressions.
-
-   Do not consider matching one past the index STOP in the virtual
-   concatenation of STRING1 and STRING2.
-
-   We return either the position in the strings at which the match was
-   found, -1 if no match, or -2 if error (such as failure
-   stack overflow).  */
-
-int
-re_search_2 (bufp, string1, size1, string2, size2, startpos, range, regs, stop)
-     struct re_pattern_buffer *bufp;
-     const char *string1, *string2;
-     int size1, size2;
-     int startpos;
-     int range;
-     struct re_registers *regs;
-     int stop;
-{
-  int val;
-  register char *fastmap = bufp->fastmap;
-  register RE_TRANSLATE_TYPE translate = bufp->translate;
-  int total_size = size1 + size2;
-  int endpos = startpos + range;
-
-  /* Check for out-of-range STARTPOS.  */
-  if (startpos < 0 || startpos > total_size)
-    return -1;
-
-  /* Fix up RANGE if it might eventually take us outside
-     the virtual concatenation of STRING1 and STRING2.
-     Make sure we won't move STARTPOS below 0 or above TOTAL_SIZE.  */
-  if (endpos < 0)
-    range = 0 - startpos;
-  else if (endpos > total_size)
-    range = total_size - startpos;
-
-  /* If the search isn't to be a backwards one, don't waste time in a
-     search for a pattern that must be anchored.  */
-  if (bufp->used > 0 && range > 0
-      && ((re_opcode_t) bufp->buffer[0] == begbuf
-	  /* `begline' is like `begbuf' if it cannot match at newlines.  */
-	  || ((re_opcode_t) bufp->buffer[0] == begline
-	      && !bufp->newline_anchor)))
-    {
-      if (startpos > 0)
-	return -1;
-      else
-	range = 1;
-    }
-
-#ifdef emacs
-  /* In a forward search for something that starts with \=.
-     don't keep searching past point.  */
-  if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == at_dot && range > 0)
-    {
-      range = PT - startpos;
-      if (range <= 0)
-	return -1;
-    }
-#endif /* emacs */
-
-  /* Update the fastmap now if not correct already.  */
-  if (fastmap && !bufp->fastmap_accurate)
-    if (re_compile_fastmap (bufp) == -2)
-      return -2;
-
-  /* Loop through the string, looking for a place to start matching.  */
-  for (;;)
-    {
-      /* If a fastmap is supplied, skip quickly over characters that
-         cannot be the start of a match.  If the pattern can match the
-         null string, however, we don't need to skip characters; we want
-         the first null string.  */
-      if (fastmap && startpos < total_size && !bufp->can_be_null)
-	{
-	  if (range > 0)	/* Searching forwards.  */
-	    {
-	      register const char *d;
-	      register int lim = 0;
-	      int irange = range;
-
-              if (startpos < size1 && startpos + range >= size1)
-                lim = range - (size1 - startpos);
-
-	      d = (startpos >= size1 ? string2 - size1 : string1) + startpos;
-
-              /* Written out as an if-else to avoid testing `translate'
-                 inside the loop.  */
-	      if (translate)
-                while (range > lim
-                       && !fastmap[(unsigned char)
-				   translate[(unsigned char) *d++]])
-                  range--;
-	      else
-                while (range > lim && !fastmap[(unsigned char) *d++])
-                  range--;
-
-	      startpos += irange - range;
-	    }
-	  else				/* Searching backwards.  */
-	    {
-	      register char c = (size1 == 0 || startpos >= size1
-                                 ? string2[startpos - size1]
-                                 : string1[startpos]);
-
-	      if (!fastmap[(unsigned char) TRANSLATE (c)])
-		goto advance;
-	    }
-	}
-
-      /* If can't match the null string, and that's all we have left, fail.  */
-      if (range >= 0 && startpos == total_size && fastmap
-          && !bufp->can_be_null)
-	return -1;
-
-      val = re_match_2_internal (bufp, string1, size1, string2, size2,
-				 startpos, regs, stop);
-#ifndef REGEX_MALLOC
-# ifdef C_ALLOCA
-      alloca (0);
-# endif
-#endif
-
-      if (val >= 0)
-	return startpos;
-
-      if (val == -2)
-	return -2;
-
-    advance:
-      if (!range)
-        break;
-      else if (range > 0)
-        {
-          range--;
-          startpos++;
-        }
-      else
-        {
-          range++;
-          startpos--;
-        }
-    }
-  return -1;
-} /* re_search_2 */
-#ifdef _LIBC
-weak_alias (__re_search_2, re_search_2)
-#endif
-
-/* This converts PTR, a pointer into one of the search strings `string1'
-   and `string2' into an offset from the beginning of that string.  */
-#define POINTER_TO_OFFSET(ptr)			\
-  (FIRST_STRING_P (ptr)				\
-   ? ((regoff_t) ((ptr) - string1))		\
-   : ((regoff_t) ((ptr) - string2 + size1)))
-
-/* Macros for dealing with the split strings in re_match_2.  */
-
-#define MATCHING_IN_FIRST_STRING  (dend == end_match_1)
-
-/* Call before fetching a character with *d.  This switches over to
-   string2 if necessary.  */
-#define PREFETCH()							\
-  while (d == dend)						    	\
-    {									\
-      /* End of string2 => fail.  */					\
-      if (dend == end_match_2) 						\
-        goto fail;							\
-      /* End of string1 => advance to string2.  */ 			\
-      d = string2;						        \
-      dend = end_match_2;						\
-    }
-
-
-/* Test if at very beginning or at very end of the virtual concatenation
-   of `string1' and `string2'.  If only one string, it's `string2'.  */
-#define AT_STRINGS_BEG(d) ((d) == (size1 ? string1 : string2) || !size2)
-#define AT_STRINGS_END(d) ((d) == end2)
-
-
-/* Test if D points to a character which is word-constituent.  We have
-   two special cases to check for: if past the end of string1, look at
-   the first character in string2; and if before the beginning of
-   string2, look at the last character in string1.  */
-#define WORDCHAR_P(d)							\
-  (SYNTAX ((d) == end1 ? *string2					\
-           : (d) == string2 - 1 ? *(end1 - 1) : *(d))			\
-   == Sword)
-
-/* Disabled due to a compiler bug -- see comment at case wordbound */
-#if 0
-/* Test if the character before D and the one at D differ with respect
-   to being word-constituent.  */
-#define AT_WORD_BOUNDARY(d)						\
-  (AT_STRINGS_BEG (d) || AT_STRINGS_END (d)				\
-   || WORDCHAR_P (d - 1) != WORDCHAR_P (d))
-#endif
-
-/* Free everything we malloc.  */
-#ifdef MATCH_MAY_ALLOCATE
-# define FREE_VAR(var) if (var) REGEX_FREE (var); var = NULL
-# define FREE_VARIABLES()						\
-  do {									\
-    REGEX_FREE_STACK (fail_stack.stack);				\
-    FREE_VAR (regstart);						\
-    FREE_VAR (regend);							\
-    FREE_VAR (old_regstart);						\
-    FREE_VAR (old_regend);						\
-    FREE_VAR (best_regstart);						\
-    FREE_VAR (best_regend);						\
-    FREE_VAR (reg_info);						\
-    FREE_VAR (reg_dummy);						\
-    FREE_VAR (reg_info_dummy);						\
-  } while (0)
-#else
-# define FREE_VARIABLES() ((void)0) /* Do nothing!  But inhibit gcc warning. */
-#endif /* not MATCH_MAY_ALLOCATE */
-
-/* These values must meet several constraints.  They must not be valid
-   register values; since we have a limit of 255 registers (because
-   we use only one byte in the pattern for the register number), we can
-   use numbers larger than 255.  They must differ by 1, because of
-   NUM_FAILURE_ITEMS above.  And the value for the lowest register must
-   be larger than the value for the highest register, so we do not try
-   to actually save any registers when none are active.  */
-#define NO_HIGHEST_ACTIVE_REG (1 << BYTEWIDTH)
-#define NO_LOWEST_ACTIVE_REG (NO_HIGHEST_ACTIVE_REG + 1)
-
-/* Matching routines.  */
-
-#ifndef emacs   /* Emacs never uses this.  */
-/* re_match is like re_match_2 except it takes only a single string.  */
-
-int
-re_match (bufp, string, size, pos, regs)
-     struct re_pattern_buffer *bufp;
-     const char *string;
-     int size, pos;
-     struct re_registers *regs;
-{
-  int result = re_match_2_internal (bufp, NULL, 0, string, size,
-				    pos, regs, size);
-# ifndef REGEX_MALLOC
-#  ifdef C_ALLOCA
-  alloca (0);
-#  endif
-# endif
-  return result;
-}
-# ifdef _LIBC
-weak_alias (__re_match, re_match)
-# endif
-#endif /* not emacs */
-
-static boolean group_match_null_string_p _RE_ARGS ((unsigned char **p,
-						    unsigned char *end,
-						register_info_type *reg_info));
-static boolean alt_match_null_string_p _RE_ARGS ((unsigned char *p,
-						  unsigned char *end,
-						register_info_type *reg_info));
-static boolean common_op_match_null_string_p _RE_ARGS ((unsigned char **p,
-							unsigned char *end,
-						register_info_type *reg_info));
-static int bcmp_translate _RE_ARGS ((const char *s1, const char *s2,
-				     int len, char *translate));
-
-/* re_match_2 matches the compiled pattern in BUFP against the
-   the (virtual) concatenation of STRING1 and STRING2 (of length SIZE1
-   and SIZE2, respectively).  We start matching at POS, and stop
-   matching at STOP.
-
-   If REGS is non-null and the `no_sub' field of BUFP is nonzero, we
-   store offsets for the substring each group matched in REGS.  See the
-   documentation for exactly how many groups we fill.
-
-   We return -1 if no match, -2 if an internal error (such as the
-   failure stack overflowing).  Otherwise, we return the length of the
-   matched substring.  */
-
-int
-re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
-     struct re_pattern_buffer *bufp;
-     const char *string1, *string2;
-     int size1, size2;
-     int pos;
-     struct re_registers *regs;
-     int stop;
-{
-  int result = re_match_2_internal (bufp, string1, size1, string2, size2,
-				    pos, regs, stop);
-#ifndef REGEX_MALLOC
-# ifdef C_ALLOCA
-  alloca (0);
-# endif
-#endif
-  return result;
-}
-#ifdef _LIBC
-weak_alias (__re_match_2, re_match_2)
-#endif
-
-/* This is a separate function so that we can force an alloca cleanup
-   afterwards.  */
-static int
-re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
-     struct re_pattern_buffer *bufp;
-     const char *string1, *string2;
-     int size1, size2;
-     int pos;
-     struct re_registers *regs;
-     int stop;
-{
-  /* General temporaries.  */
-  int mcnt;
-  unsigned char *p1;
-
-  /* Just past the end of the corresponding string.  */
-  const char *end1, *end2;
-
-  /* Pointers into string1 and string2, just past the last characters in
-     each to consider matching.  */
-  const char *end_match_1, *end_match_2;
-
-  /* Where we are in the data, and the end of the current string.  */
-  const char *d, *dend;
-
-  /* Where we are in the pattern, and the end of the pattern.  */
-  unsigned char *p = bufp->buffer;
-  register unsigned char *pend = p + bufp->used;
-
-  /* Mark the opcode just after a start_memory, so we can test for an
-     empty subpattern when we get to the stop_memory.  */
-  unsigned char *just_past_start_mem = 0;
-
-  /* We use this to map every character in the string.  */
-  RE_TRANSLATE_TYPE translate = bufp->translate;
-
-  /* Failure point stack.  Each place that can handle a failure further
-     down the line pushes a failure point on this stack.  It consists of
-     restart, regend, and reg_info for all registers corresponding to
-     the subexpressions we're currently inside, plus the number of such
-     registers, and, finally, two char *'s.  The first char * is where
-     to resume scanning the pattern; the second one is where to resume
-     scanning the strings.  If the latter is zero, the failure point is
-     a ``dummy''; if a failure happens and the failure point is a dummy,
-     it gets discarded and the next next one is tried.  */
-#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global.  */
-  fail_stack_type fail_stack;
-#endif
-#ifdef DEBUG
-  static unsigned failure_id;
-  unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0;
-#endif
-
-#ifdef REL_ALLOC
-  /* This holds the pointer to the failure stack, when
-     it is allocated relocatably.  */
-  fail_stack_elt_t *failure_stack_ptr;
-#endif
-
-  /* We fill all the registers internally, independent of what we
-     return, for use in backreferences.  The number here includes
-     an element for register zero.  */
-  size_t num_regs = bufp->re_nsub + 1;
-
-  /* The currently active registers.  */
-  active_reg_t lowest_active_reg = NO_LOWEST_ACTIVE_REG;
-  active_reg_t highest_active_reg = NO_HIGHEST_ACTIVE_REG;
-
-  /* Information on the contents of registers. These are pointers into
-     the input strings; they record just what was matched (on this
-     attempt) by a subexpression part of the pattern, that is, the
-     regnum-th regstart pointer points to where in the pattern we began
-     matching and the regnum-th regend points to right after where we
-     stopped matching the regnum-th subexpression.  (The zeroth register
-     keeps track of what the whole pattern matches.)  */
-#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global.  */
-  const char **regstart, **regend;
-#endif
-
-  /* If a group that's operated upon by a repetition operator fails to
-     match anything, then the register for its start will need to be
-     restored because it will have been set to wherever in the string we
-     are when we last see its open-group operator.  Similarly for a
-     register's end.  */
-#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global.  */
-  const char **old_regstart, **old_regend;
-#endif
-
-  /* The is_active field of reg_info helps us keep track of which (possibly
-     nested) subexpressions we are currently in. The matched_something
-     field of reg_info[reg_num] helps us tell whether or not we have
-     matched any of the pattern so far this time through the reg_num-th
-     subexpression.  These two fields get reset each time through any
-     loop their register is in.  */
-#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global.  */
-  register_info_type *reg_info;
-#endif
-
-  /* The following record the register info as found in the above
-     variables when we find a match better than any we've seen before.
-     This happens as we backtrack through the failure points, which in
-     turn happens only if we have not yet matched the entire string. */
-  unsigned best_regs_set = false;
-#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global.  */
-  const char **best_regstart, **best_regend;
-#endif
-
-  /* Logically, this is `best_regend[0]'.  But we don't want to have to
-     allocate space for that if we're not allocating space for anything
-     else (see below).  Also, we never need info about register 0 for
-     any of the other register vectors, and it seems rather a kludge to
-     treat `best_regend' differently than the rest.  So we keep track of
-     the end of the best match so far in a separate variable.  We
-     initialize this to NULL so that when we backtrack the first time
-     and need to test it, it's not garbage.  */
-  const char *match_end = NULL;
-
-  /* This helps SET_REGS_MATCHED avoid doing redundant work.  */
-  int set_regs_matched_done = 0;
-
-  /* Used when we pop values we don't care about.  */
-#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global.  */
-  const char **reg_dummy;
-  register_info_type *reg_info_dummy;
-#endif
-
-#ifdef DEBUG
-  /* Counts the total number of registers pushed.  */
-  unsigned num_regs_pushed = 0;
-#endif
-
-  DEBUG_PRINT1 ("\n\nEntering re_match_2.\n");
-
-  INIT_FAIL_STACK ();
-
-#ifdef MATCH_MAY_ALLOCATE
-  /* Do not bother to initialize all the register variables if there are
-     no groups in the pattern, as it takes a fair amount of time.  If
-     there are groups, we include space for register 0 (the whole
-     pattern), even though we never use it, since it simplifies the
-     array indexing.  We should fix this.  */
-  if (bufp->re_nsub)
-    {
-      regstart = REGEX_TALLOC (num_regs, const char *);
-      regend = REGEX_TALLOC (num_regs, const char *);
-      old_regstart = REGEX_TALLOC (num_regs, const char *);
-      old_regend = REGEX_TALLOC (num_regs, const char *);
-      best_regstart = REGEX_TALLOC (num_regs, const char *);
-      best_regend = REGEX_TALLOC (num_regs, const char *);
-      reg_info = REGEX_TALLOC (num_regs, register_info_type);
-      reg_dummy = REGEX_TALLOC (num_regs, const char *);
-      reg_info_dummy = REGEX_TALLOC (num_regs, register_info_type);
-
-      if (!(regstart && regend && old_regstart && old_regend && reg_info
-            && best_regstart && best_regend && reg_dummy && reg_info_dummy))
-        {
-          FREE_VARIABLES ();
-          return -2;
-        }
-    }
-  else
-    {
-      /* We must initialize all our variables to NULL, so that
-         `FREE_VARIABLES' doesn't try to free them.  */
-      regstart = regend = old_regstart = old_regend = best_regstart
-        = best_regend = reg_dummy = NULL;
-      reg_info = reg_info_dummy = (register_info_type *) NULL;
-    }
-#endif /* MATCH_MAY_ALLOCATE */
-
-  /* The starting position is bogus.  */
-  if (pos < 0 || pos > size1 + size2)
-    {
-      FREE_VARIABLES ();
-      return -1;
-    }
-
-  /* Initialize subexpression text positions to -1 to mark ones that no
-     start_memory/stop_memory has been seen for. Also initialize the
-     register information struct.  */
-  for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++)
-    {
-      regstart[mcnt] = regend[mcnt]
-        = old_regstart[mcnt] = old_regend[mcnt] = REG_UNSET_VALUE;
-
-      REG_MATCH_NULL_STRING_P (reg_info[mcnt]) = MATCH_NULL_UNSET_VALUE;
-      IS_ACTIVE (reg_info[mcnt]) = 0;
-      MATCHED_SOMETHING (reg_info[mcnt]) = 0;
-      EVER_MATCHED_SOMETHING (reg_info[mcnt]) = 0;
-    }
-
-  /* We move `string1' into `string2' if the latter's empty -- but not if
-     `string1' is null.  */
-  if (size2 == 0 && string1 != NULL)
-    {
-      string2 = string1;
-      size2 = size1;
-      string1 = 0;
-      size1 = 0;
-    }
-  end1 = string1 + size1;
-  end2 = string2 + size2;
-
-  /* Compute where to stop matching, within the two strings.  */
-  if (stop <= size1)
-    {
-      end_match_1 = string1 + stop;
-      end_match_2 = string2;
-    }
-  else
-    {
-      end_match_1 = end1;
-      end_match_2 = string2 + stop - size1;
-    }
-
-  /* `p' scans through the pattern as `d' scans through the data.
-     `dend' is the end of the input string that `d' points within.  `d'
-     is advanced into the following input string whenever necessary, but
-     this happens before fetching; therefore, at the beginning of the
-     loop, `d' can be pointing at the end of a string, but it cannot
-     equal `string2'.  */
-  if (size1 > 0 && pos <= size1)
-    {
-      d = string1 + pos;
-      dend = end_match_1;
-    }
-  else
-    {
-      d = string2 + pos - size1;
-      dend = end_match_2;
-    }
-
-  DEBUG_PRINT1 ("The compiled pattern is:\n");
-  DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend);
-  DEBUG_PRINT1 ("The string to match is: `");
-  DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2);
-  DEBUG_PRINT1 ("'\n");
-
-  /* This loops over pattern commands.  It exits by returning from the
-     function if the match is complete, or it drops through if the match
-     fails at this starting point in the input data.  */
-  for (;;)
-    {
-#ifdef _LIBC
-      DEBUG_PRINT2 ("\n%p: ", p);
-#else
-      DEBUG_PRINT2 ("\n0x%x: ", p);
-#endif
-
-      if (p == pend)
-	{ /* End of pattern means we might have succeeded.  */
-          DEBUG_PRINT1 ("end of pattern ... ");
-
-	  /* If we haven't matched the entire string, and we want the
-             longest match, try backtracking.  */
-          if (d != end_match_2)
-	    {
-	      /* 1 if this match ends in the same string (string1 or string2)
-		 as the best previous match.  */
-	      boolean same_str_p = (FIRST_STRING_P (match_end)
-				    == MATCHING_IN_FIRST_STRING);
-	      /* 1 if this match is the best seen so far.  */
-	      boolean best_match_p;
-
-	      /* AIX compiler got confused when this was combined
-		 with the previous declaration.  */
-	      if (same_str_p)
-		best_match_p = d > match_end;
-	      else
-		best_match_p = !MATCHING_IN_FIRST_STRING;
-
-              DEBUG_PRINT1 ("backtracking.\n");
-
-              if (!FAIL_STACK_EMPTY ())
-                { /* More failure points to try.  */
-
-                  /* If exceeds best match so far, save it.  */
-                  if (!best_regs_set || best_match_p)
-                    {
-                      best_regs_set = true;
-                      match_end = d;
-
-                      DEBUG_PRINT1 ("\nSAVING match as best so far.\n");
-
-                      for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++)
-                        {
-                          best_regstart[mcnt] = regstart[mcnt];
-                          best_regend[mcnt] = regend[mcnt];
-                        }
-                    }
-                  goto fail;
-                }
-
-              /* If no failure points, don't restore garbage.  And if
-                 last match is real best match, don't restore second
-                 best one. */
-              else if (best_regs_set && !best_match_p)
-                {
-  	        restore_best_regs:
-                  /* Restore best match.  It may happen that `dend ==
-                     end_match_1' while the restored d is in string2.
-                     For example, the pattern `x.*y.*z' against the
-                     strings `x-' and `y-z-', if the two strings are
-                     not consecutive in memory.  */
-                  DEBUG_PRINT1 ("Restoring best registers.\n");
-
-                  d = match_end;
-                  dend = ((d >= string1 && d <= end1)
-		           ? end_match_1 : end_match_2);
-
-		  for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++)
-		    {
-		      regstart[mcnt] = best_regstart[mcnt];
-		      regend[mcnt] = best_regend[mcnt];
-		    }
-                }
-            } /* d != end_match_2 */
-
-	succeed_label:
-          DEBUG_PRINT1 ("Accepting match.\n");
-
-          /* If caller wants register contents data back, do it.  */
-          if (regs && !bufp->no_sub)
-	    {
-              /* Have the register data arrays been allocated?  */
-              if (bufp->regs_allocated == REGS_UNALLOCATED)
-                { /* No.  So allocate them with malloc.  We need one
-                     extra element beyond `num_regs' for the `-1' marker
-                     GNU code uses.  */
-                  regs->num_regs = MAX (RE_NREGS, num_regs + 1);
-                  regs->start = TALLOC (regs->num_regs, regoff_t);
-                  regs->end = TALLOC (regs->num_regs, regoff_t);
-                  if (regs->start == NULL || regs->end == NULL)
-		    {
-		      FREE_VARIABLES ();
-		      return -2;
-		    }
-                  bufp->regs_allocated = REGS_REALLOCATE;
-                }
-              else if (bufp->regs_allocated == REGS_REALLOCATE)
-                { /* Yes.  If we need more elements than were already
-                     allocated, reallocate them.  If we need fewer, just
-                     leave it alone.  */
-                  if (regs->num_regs < num_regs + 1)
-                    {
-                      regs->num_regs = num_regs + 1;
-                      RETALLOC (regs->start, regs->num_regs, regoff_t);
-                      RETALLOC (regs->end, regs->num_regs, regoff_t);
-                      if (regs->start == NULL || regs->end == NULL)
-			{
-			  FREE_VARIABLES ();
-			  return -2;
-			}
-                    }
-                }
-              else
-		{
-		  /* These braces fend off a "empty body in an else-statement"
-		     warning under GCC when assert expands to nothing.  */
-		  assert (bufp->regs_allocated == REGS_FIXED);
-		}
-
-              /* Convert the pointer data in `regstart' and `regend' to
-                 indices.  Register zero has to be set differently,
-                 since we haven't kept track of any info for it.  */
-              if (regs->num_regs > 0)
-                {
-                  regs->start[0] = pos;
-                  regs->end[0] = (MATCHING_IN_FIRST_STRING
-				  ? ((regoff_t) (d - string1))
-			          : ((regoff_t) (d - string2 + size1)));
-                }
-
-              /* Go through the first `min (num_regs, regs->num_regs)'
-                 registers, since that is all we initialized.  */
-	      for (mcnt = 1; (unsigned) mcnt < MIN (num_regs, regs->num_regs);
-		   mcnt++)
-		{
-                  if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt]))
-                    regs->start[mcnt] = regs->end[mcnt] = -1;
-                  else
-                    {
-		      regs->start[mcnt]
-			= (regoff_t) POINTER_TO_OFFSET (regstart[mcnt]);
-                      regs->end[mcnt]
-			= (regoff_t) POINTER_TO_OFFSET (regend[mcnt]);
-                    }
-		}
-
-              /* If the regs structure we return has more elements than
-                 were in the pattern, set the extra elements to -1.  If
-                 we (re)allocated the registers, this is the case,
-                 because we always allocate enough to have at least one
-                 -1 at the end.  */
-              for (mcnt = num_regs; (unsigned) mcnt < regs->num_regs; mcnt++)
-                regs->start[mcnt] = regs->end[mcnt] = -1;
-	    } /* regs && !bufp->no_sub */
-
-          DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n",
-                        nfailure_points_pushed, nfailure_points_popped,
-                        nfailure_points_pushed - nfailure_points_popped);
-          DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed);
-
-          mcnt = d - pos - (MATCHING_IN_FIRST_STRING
-			    ? string1
-			    : string2 - size1);
-
-          DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt);
-
-          FREE_VARIABLES ();
-          return mcnt;
-        }
-
-      /* Otherwise match next pattern command.  */
-      switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++))
-	{
-        /* Ignore these.  Used to ignore the n of succeed_n's which
-           currently have n == 0.  */
-        case no_op:
-          DEBUG_PRINT1 ("EXECUTING no_op.\n");
-          break;
-
-	case succeed:
-          DEBUG_PRINT1 ("EXECUTING succeed.\n");
-	  goto succeed_label;
-
-        /* Match the next n pattern characters exactly.  The following
-           byte in the pattern defines n, and the n bytes after that
-           are the characters to match.  */
-	case exactn:
-	  mcnt = *p++;
-          DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt);
-
-          /* This is written out as an if-else so we don't waste time
-             testing `translate' inside the loop.  */
-          if (translate)
-	    {
-	      do
-		{
-		  PREFETCH ();
-		  if ((unsigned char) translate[(unsigned char) *d++]
-		      != (unsigned char) *p++)
-                    goto fail;
-		}
-	      while (--mcnt);
-	    }
-	  else
-	    {
-	      do
-		{
-		  PREFETCH ();
-		  if (*d++ != (char) *p++) goto fail;
-		}
-	      while (--mcnt);
-	    }
-	  SET_REGS_MATCHED ();
-          break;
-
-
-        /* Match any character except possibly a newline or a null.  */
-	case anychar:
-          DEBUG_PRINT1 ("EXECUTING anychar.\n");
-
-          PREFETCH ();
-
-          if ((!(bufp->syntax & RE_DOT_NEWLINE) && TRANSLATE (*d) == '\n')
-              || (bufp->syntax & RE_DOT_NOT_NULL && TRANSLATE (*d) == '\000'))
-	    goto fail;
-
-          SET_REGS_MATCHED ();
-          DEBUG_PRINT2 ("  Matched `%d'.\n", *d);
-          d++;
-	  break;
-
-
-	case charset:
-	case charset_not:
-	  {
-	    register unsigned char c;
-	    boolean not = (re_opcode_t) *(p - 1) == charset_not;
-
-            DEBUG_PRINT2 ("EXECUTING charset%s.\n", not ? "_not" : "");
-
-	    PREFETCH ();
-	    c = TRANSLATE (*d); /* The character to match.  */
-
-            /* Cast to `unsigned' instead of `unsigned char' in case the
-               bit list is a full 32 bytes long.  */
-	    if (c < (unsigned) (*p * BYTEWIDTH)
-		&& p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
-	      not = !not;
-
-	    p += 1 + *p;
-
-	    if (!not) goto fail;
-
-	    SET_REGS_MATCHED ();
-            d++;
-	    break;
-	  }
-
-
-        /* The beginning of a group is represented by start_memory.
-           The arguments are the register number in the next byte, and the
-           number of groups inner to this one in the next.  The text
-           matched within the group is recorded (in the internal
-           registers data structure) under the register number.  */
-        case start_memory:
-	  DEBUG_PRINT3 ("EXECUTING start_memory %d (%d):\n", *p, p[1]);
-
-          /* Find out if this group can match the empty string.  */
-	  p1 = p;		/* To send to group_match_null_string_p.  */
-
-          if (REG_MATCH_NULL_STRING_P (reg_info[*p]) == MATCH_NULL_UNSET_VALUE)
-            REG_MATCH_NULL_STRING_P (reg_info[*p])
-              = group_match_null_string_p (&p1, pend, reg_info);
-
-          /* Save the position in the string where we were the last time
-             we were at this open-group operator in case the group is
-             operated upon by a repetition operator, e.g., with `(a*)*b'
-             against `ab'; then we want to ignore where we are now in
-             the string in case this attempt to match fails.  */
-          old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p])
-                             ? REG_UNSET (regstart[*p]) ? d : regstart[*p]
-                             : regstart[*p];
-	  DEBUG_PRINT2 ("  old_regstart: %d\n",
-			 POINTER_TO_OFFSET (old_regstart[*p]));
-
-          regstart[*p] = d;
-	  DEBUG_PRINT2 ("  regstart: %d\n", POINTER_TO_OFFSET (regstart[*p]));
-
-          IS_ACTIVE (reg_info[*p]) = 1;
-          MATCHED_SOMETHING (reg_info[*p]) = 0;
-
-	  /* Clear this whenever we change the register activity status.  */
-	  set_regs_matched_done = 0;
-
-          /* This is the new highest active register.  */
-          highest_active_reg = *p;
-
-          /* If nothing was active before, this is the new lowest active
-             register.  */
-          if (lowest_active_reg == NO_LOWEST_ACTIVE_REG)
-            lowest_active_reg = *p;
-
-          /* Move past the register number and inner group count.  */
-          p += 2;
-	  just_past_start_mem = p;
-
-          break;
-
-
-        /* The stop_memory opcode represents the end of a group.  Its
-           arguments are the same as start_memory's: the register
-           number, and the number of inner groups.  */
-	case stop_memory:
-	  DEBUG_PRINT3 ("EXECUTING stop_memory %d (%d):\n", *p, p[1]);
-
-          /* We need to save the string position the last time we were at
-             this close-group operator in case the group is operated
-             upon by a repetition operator, e.g., with `((a*)*(b*)*)*'
-             against `aba'; then we want to ignore where we are now in
-             the string in case this attempt to match fails.  */
-          old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p])
-                           ? REG_UNSET (regend[*p]) ? d : regend[*p]
-			   : regend[*p];
-	  DEBUG_PRINT2 ("      old_regend: %d\n",
-			 POINTER_TO_OFFSET (old_regend[*p]));
-
-          regend[*p] = d;
-	  DEBUG_PRINT2 ("      regend: %d\n", POINTER_TO_OFFSET (regend[*p]));
-
-          /* This register isn't active anymore.  */
-          IS_ACTIVE (reg_info[*p]) = 0;
-
-	  /* Clear this whenever we change the register activity status.  */
-	  set_regs_matched_done = 0;
-
-          /* If this was the only register active, nothing is active
-             anymore.  */
-          if (lowest_active_reg == highest_active_reg)
-            {
-              lowest_active_reg = NO_LOWEST_ACTIVE_REG;
-              highest_active_reg = NO_HIGHEST_ACTIVE_REG;
-            }
-          else
-            { /* We must scan for the new highest active register, since
-                 it isn't necessarily one less than now: consider
-                 (a(b)c(d(e)f)g).  When group 3 ends, after the f), the
-                 new highest active register is 1.  */
-              unsigned char r = *p - 1;
-              while (r > 0 && !IS_ACTIVE (reg_info[r]))
-                r--;
-
-              /* If we end up at register zero, that means that we saved
-                 the registers as the result of an `on_failure_jump', not
-                 a `start_memory', and we jumped to past the innermost
-                 `stop_memory'.  For example, in ((.)*) we save
-                 registers 1 and 2 as a result of the *, but when we pop
-                 back to the second ), we are at the stop_memory 1.
-                 Thus, nothing is active.  */
-	      if (r == 0)
-                {
-                  lowest_active_reg = NO_LOWEST_ACTIVE_REG;
-                  highest_active_reg = NO_HIGHEST_ACTIVE_REG;
-                }
-              else
-                highest_active_reg = r;
-            }
-
-          /* If just failed to match something this time around with a
-             group that's operated on by a repetition operator, try to
-             force exit from the ``loop'', and restore the register
-             information for this group that we had before trying this
-             last match.  */
-          if ((!MATCHED_SOMETHING (reg_info[*p])
-               || just_past_start_mem == p - 1)
-	      && (p + 2) < pend)
-            {
-              boolean is_a_jump_n = false;
-
-              p1 = p + 2;
-              mcnt = 0;
-              switch ((re_opcode_t) *p1++)
-                {
-                  case jump_n:
-		    is_a_jump_n = true;
-                  case pop_failure_jump:
-		  case maybe_pop_jump:
-		  case jump:
-		  case dummy_failure_jump:
-                    EXTRACT_NUMBER_AND_INCR (mcnt, p1);
-		    if (is_a_jump_n)
-		      p1 += 2;
-                    break;
-
-                  default:
-                    /* do nothing */ ;
-                }
-	      p1 += mcnt;
-
-              /* If the next operation is a jump backwards in the pattern
-	         to an on_failure_jump right before the start_memory
-                 corresponding to this stop_memory, exit from the loop
-                 by forcing a failure after pushing on the stack the
-                 on_failure_jump's jump in the pattern, and d.  */
-              if (mcnt < 0 && (re_opcode_t) *p1 == on_failure_jump
-                  && (re_opcode_t) p1[3] == start_memory && p1[4] == *p)
-		{
-                  /* If this group ever matched anything, then restore
-                     what its registers were before trying this last
-                     failed match, e.g., with `(a*)*b' against `ab' for
-                     regstart[1], and, e.g., with `((a*)*(b*)*)*'
-                     against `aba' for regend[3].
-
-                     Also restore the registers for inner groups for,
-                     e.g., `((a*)(b*))*' against `aba' (register 3 would
-                     otherwise get trashed).  */
-
-                  if (EVER_MATCHED_SOMETHING (reg_info[*p]))
-		    {
-		      unsigned r;
-
-                      EVER_MATCHED_SOMETHING (reg_info[*p]) = 0;
-
-		      /* Restore this and inner groups' (if any) registers.  */
-                      for (r = *p; r < (unsigned) *p + (unsigned) *(p + 1);
-			   r++)
-                        {
-                          regstart[r] = old_regstart[r];
-
-                          /* xx why this test?  */
-                          if (old_regend[r] >= regstart[r])
-                            regend[r] = old_regend[r];
-                        }
-                    }
-		  p1++;
-                  EXTRACT_NUMBER_AND_INCR (mcnt, p1);
-                  PUSH_FAILURE_POINT (p1 + mcnt, d, -2);
-
-                  goto fail;
-                }
-            }
-
-          /* Move past the register number and the inner group count.  */
-          p += 2;
-          break;
-
-
-	/* \<digit> has been turned into a `duplicate' command which is
-           followed by the numeric value of <digit> as the register number.  */
-        case duplicate:
-	  {
-	    register const char *d2, *dend2;
-	    int regno = *p++;   /* Get which register to match against.  */
-	    DEBUG_PRINT2 ("EXECUTING duplicate %d.\n", regno);
-
-	    /* Can't back reference a group which we've never matched.  */
-            if (REG_UNSET (regstart[regno]) || REG_UNSET (regend[regno]))
-              goto fail;
-
-            /* Where in input to try to start matching.  */
-            d2 = regstart[regno];
-
-            /* Where to stop matching; if both the place to start and
-               the place to stop matching are in the same string, then
-               set to the place to stop, otherwise, for now have to use
-               the end of the first string.  */
-
-            dend2 = ((FIRST_STRING_P (regstart[regno])
-		      == FIRST_STRING_P (regend[regno]))
-		     ? regend[regno] : end_match_1);
-	    for (;;)
-	      {
-		/* If necessary, advance to next segment in register
-                   contents.  */
-		while (d2 == dend2)
-		  {
-		    if (dend2 == end_match_2) break;
-		    if (dend2 == regend[regno]) break;
-
-                    /* End of string1 => advance to string2. */
-                    d2 = string2;
-                    dend2 = regend[regno];
-		  }
-		/* At end of register contents => success */
-		if (d2 == dend2) break;
-
-		/* If necessary, advance to next segment in data.  */
-		PREFETCH ();
-
-		/* How many characters left in this segment to match.  */
-		mcnt = dend - d;
-
-		/* Want how many consecutive characters we can match in
-                   one shot, so, if necessary, adjust the count.  */
-                if (mcnt > dend2 - d2)
-		  mcnt = dend2 - d2;
-
-		/* Compare that many; failure if mismatch, else move
-                   past them.  */
-		if (translate
-                    ? bcmp_translate (d, d2, mcnt, translate)
-                    : memcmp (d, d2, mcnt))
-		  goto fail;
-		d += mcnt, d2 += mcnt;
-
-		/* Do this because we've match some characters.  */
-		SET_REGS_MATCHED ();
-	      }
-	  }
-	  break;
-
-
-        /* begline matches the empty string at the beginning of the string
-           (unless `not_bol' is set in `bufp'), and, if
-           `newline_anchor' is set, after newlines.  */
-	case begline:
-          DEBUG_PRINT1 ("EXECUTING begline.\n");
-
-          if (AT_STRINGS_BEG (d))
-            {
-              if (!bufp->not_bol) break;
-            }
-          else if (d[-1] == '\n' && bufp->newline_anchor)
-            {
-              break;
-            }
-          /* In all other cases, we fail.  */
-          goto fail;
-
-
-        /* endline is the dual of begline.  */
-	case endline:
-          DEBUG_PRINT1 ("EXECUTING endline.\n");
-
-          if (AT_STRINGS_END (d))
-            {
-              if (!bufp->not_eol) break;
-            }
-
-          /* We have to ``prefetch'' the next character.  */
-          else if ((d == end1 ? *string2 : *d) == '\n'
-                   && bufp->newline_anchor)
-            {
-              break;
-            }
-          goto fail;
-
-
-	/* Match at the very beginning of the data.  */
-        case begbuf:
-          DEBUG_PRINT1 ("EXECUTING begbuf.\n");
-          if (AT_STRINGS_BEG (d))
-            break;
-          goto fail;
-
-
-	/* Match at the very end of the data.  */
-        case endbuf:
-          DEBUG_PRINT1 ("EXECUTING endbuf.\n");
-	  if (AT_STRINGS_END (d))
-	    break;
-          goto fail;
-
-
-        /* on_failure_keep_string_jump is used to optimize `.*\n'.  It
-           pushes NULL as the value for the string on the stack.  Then
-           `pop_failure_point' will keep the current value for the
-           string, instead of restoring it.  To see why, consider
-           matching `foo\nbar' against `.*\n'.  The .* matches the foo;
-           then the . fails against the \n.  But the next thing we want
-           to do is match the \n against the \n; if we restored the
-           string value, we would be back at the foo.
-
-           Because this is used only in specific cases, we don't need to
-           check all the things that `on_failure_jump' does, to make
-           sure the right things get saved on the stack.  Hence we don't
-           share its code.  The only reason to push anything on the
-           stack at all is that otherwise we would have to change
-           `anychar's code to do something besides goto fail in this
-           case; that seems worse than this.  */
-        case on_failure_keep_string_jump:
-          DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump");
-
-          EXTRACT_NUMBER_AND_INCR (mcnt, p);
-#ifdef _LIBC
-          DEBUG_PRINT3 (" %d (to %p):\n", mcnt, p + mcnt);
-#else
-          DEBUG_PRINT3 (" %d (to 0x%x):\n", mcnt, p + mcnt);
-#endif
-
-          PUSH_FAILURE_POINT (p + mcnt, NULL, -2);
-          break;
-
-
-	/* Uses of on_failure_jump:
-
-           Each alternative starts with an on_failure_jump that points
-           to the beginning of the next alternative.  Each alternative
-           except the last ends with a jump that in effect jumps past
-           the rest of the alternatives.  (They really jump to the
-           ending jump of the following alternative, because tensioning
-           these jumps is a hassle.)
-
-           Repeats start with an on_failure_jump that points past both
-           the repetition text and either the following jump or
-           pop_failure_jump back to this on_failure_jump.  */
-	case on_failure_jump:
-        on_failure:
-          DEBUG_PRINT1 ("EXECUTING on_failure_jump");
-
-          EXTRACT_NUMBER_AND_INCR (mcnt, p);
-#ifdef _LIBC
-          DEBUG_PRINT3 (" %d (to %p)", mcnt, p + mcnt);
-#else
-          DEBUG_PRINT3 (" %d (to 0x%x)", mcnt, p + mcnt);
-#endif
-
-          /* If this on_failure_jump comes right before a group (i.e.,
-             the original * applied to a group), save the information
-             for that group and all inner ones, so that if we fail back
-             to this point, the group's information will be correct.
-             For example, in \(a*\)*\1, we need the preceding group,
-             and in \(zz\(a*\)b*\)\2, we need the inner group.  */
-
-          /* We can't use `p' to check ahead because we push
-             a failure point to `p + mcnt' after we do this.  */
-          p1 = p;
-
-          /* We need to skip no_op's before we look for the
-             start_memory in case this on_failure_jump is happening as
-             the result of a completed succeed_n, as in \(a\)\{1,3\}b\1
-             against aba.  */
-          while (p1 < pend && (re_opcode_t) *p1 == no_op)
-            p1++;
-
-          if (p1 < pend && (re_opcode_t) *p1 == start_memory)
-            {
-              /* We have a new highest active register now.  This will
-                 get reset at the start_memory we are about to get to,
-                 but we will have saved all the registers relevant to
-                 this repetition op, as described above.  */
-              highest_active_reg = *(p1 + 1) + *(p1 + 2);
-              if (lowest_active_reg == NO_LOWEST_ACTIVE_REG)
-                lowest_active_reg = *(p1 + 1);
-            }
-
-          DEBUG_PRINT1 (":\n");
-          PUSH_FAILURE_POINT (p + mcnt, d, -2);
-          break;
-
-
-        /* A smart repeat ends with `maybe_pop_jump'.
-	   We change it to either `pop_failure_jump' or `jump'.  */
-        case maybe_pop_jump:
-          EXTRACT_NUMBER_AND_INCR (mcnt, p);
-          DEBUG_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt);
-          {
-	    register unsigned char *p2 = p;
-
-            /* Compare the beginning of the repeat with what in the
-               pattern follows its end. If we can establish that there
-               is nothing that they would both match, i.e., that we
-               would have to backtrack because of (as in, e.g., `a*a')
-               then we can change to pop_failure_jump, because we'll
-               never have to backtrack.
-
-               This is not true in the case of alternatives: in
-               `(a|ab)*' we do need to backtrack to the `ab' alternative
-               (e.g., if the string was `ab').  But instead of trying to
-               detect that here, the alternative has put on a dummy
-               failure point which is what we will end up popping.  */
-
-	    /* Skip over open/close-group commands.
-	       If what follows this loop is a ...+ construct,
-	       look at what begins its body, since we will have to
-	       match at least one of that.  */
-	    while (1)
-	      {
-		if (p2 + 2 < pend
-		    && ((re_opcode_t) *p2 == stop_memory
-			|| (re_opcode_t) *p2 == start_memory))
-		  p2 += 3;
-		else if (p2 + 6 < pend
-			 && (re_opcode_t) *p2 == dummy_failure_jump)
-		  p2 += 6;
-		else
-		  break;
-	      }
-
-	    p1 = p + mcnt;
-	    /* p1[0] ... p1[2] are the `on_failure_jump' corresponding
-	       to the `maybe_finalize_jump' of this case.  Examine what
-	       follows.  */
-
-            /* If we're at the end of the pattern, we can change.  */
-            if (p2 == pend)
-	      {
-		/* Consider what happens when matching ":\(.*\)"
-		   against ":/".  I don't really understand this code
-		   yet.  */
-  	        p[-3] = (unsigned char) pop_failure_jump;
-                DEBUG_PRINT1
-                  ("  End of pattern: change to `pop_failure_jump'.\n");
-              }
-
-            else if ((re_opcode_t) *p2 == exactn
-		     || (bufp->newline_anchor && (re_opcode_t) *p2 == endline))
-	      {
-		register unsigned char c
-                  = *p2 == (unsigned char) endline ? '\n' : p2[2];
-
-                if ((re_opcode_t) p1[3] == exactn && p1[5] != c)
-                  {
-  		    p[-3] = (unsigned char) pop_failure_jump;
-                    DEBUG_PRINT3 ("  %c != %c => pop_failure_jump.\n",
-                                  c, p1[5]);
-                  }
-
-		else if ((re_opcode_t) p1[3] == charset
-			 || (re_opcode_t) p1[3] == charset_not)
-		  {
-		    int not = (re_opcode_t) p1[3] == charset_not;
-
-		    if (c < (unsigned char) (p1[4] * BYTEWIDTH)
-			&& p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
-		      not = !not;
-
-                    /* `not' is equal to 1 if c would match, which means
-                        that we can't change to pop_failure_jump.  */
-		    if (!not)
-                      {
-  		        p[-3] = (unsigned char) pop_failure_jump;
-                        DEBUG_PRINT1 ("  No match => pop_failure_jump.\n");
-                      }
-		  }
-	      }
-            else if ((re_opcode_t) *p2 == charset)
-	      {
-		/* We win if the first character of the loop is not part
-                   of the charset.  */
-                if ((re_opcode_t) p1[3] == exactn
- 		    && ! ((int) p2[1] * BYTEWIDTH > (int) p1[5]
- 			  && (p2[2 + p1[5] / BYTEWIDTH]
- 			      & (1 << (p1[5] % BYTEWIDTH)))))
-		  {
-		    p[-3] = (unsigned char) pop_failure_jump;
-		    DEBUG_PRINT1 ("  No match => pop_failure_jump.\n");
-                  }
-
-		else if ((re_opcode_t) p1[3] == charset_not)
-		  {
-		    int idx;
-		    /* We win if the charset_not inside the loop
-		       lists every character listed in the charset after.  */
-		    for (idx = 0; idx < (int) p2[1]; idx++)
-		      if (! (p2[2 + idx] == 0
-			     || (idx < (int) p1[4]
-				 && ((p2[2 + idx] & ~ p1[5 + idx]) == 0))))
-			break;
-
-		    if (idx == p2[1])
-                      {
-  		        p[-3] = (unsigned char) pop_failure_jump;
-                        DEBUG_PRINT1 ("  No match => pop_failure_jump.\n");
-                      }
-		  }
-		else if ((re_opcode_t) p1[3] == charset)
-		  {
-		    int idx;
-		    /* We win if the charset inside the loop
-		       has no overlap with the one after the loop.  */
-		    for (idx = 0;
-			 idx < (int) p2[1] && idx < (int) p1[4];
-			 idx++)
-		      if ((p2[2 + idx] & p1[5 + idx]) != 0)
-			break;
-
-		    if (idx == p2[1] || idx == p1[4])
-                      {
-  		        p[-3] = (unsigned char) pop_failure_jump;
-                        DEBUG_PRINT1 ("  No match => pop_failure_jump.\n");
-                      }
-		  }
-	      }
-	  }
-	  p -= 2;		/* Point at relative address again.  */
-	  if ((re_opcode_t) p[-1] != pop_failure_jump)
-	    {
-	      p[-1] = (unsigned char) jump;
-              DEBUG_PRINT1 ("  Match => jump.\n");
-	      goto unconditional_jump;
-	    }
-        /* Note fall through.  */
-
-
-	/* The end of a simple repeat has a pop_failure_jump back to
-           its matching on_failure_jump, where the latter will push a
-           failure point.  The pop_failure_jump takes off failure
-           points put on by this pop_failure_jump's matching
-           on_failure_jump; we got through the pattern to here from the
-           matching on_failure_jump, so didn't fail.  */
-        case pop_failure_jump:
-          {
-            /* We need to pass separate storage for the lowest and
-               highest registers, even though we don't care about the
-               actual values.  Otherwise, we will restore only one
-               register from the stack, since lowest will == highest in
-               `pop_failure_point'.  */
-            active_reg_t dummy_low_reg, dummy_high_reg;
-            unsigned char *pdummy;
-            const char *sdummy;
-
-            DEBUG_PRINT1 ("EXECUTING pop_failure_jump.\n");
-            POP_FAILURE_POINT (sdummy, pdummy,
-                               dummy_low_reg, dummy_high_reg,
-                               reg_dummy, reg_dummy, reg_info_dummy);
-          }
-	  /* Note fall through.  */
-
-	unconditional_jump:
-#ifdef _LIBC
-	  DEBUG_PRINT2 ("\n%p: ", p);
-#else
-	  DEBUG_PRINT2 ("\n0x%x: ", p);
-#endif
-          /* Note fall through.  */
-
-        /* Unconditionally jump (without popping any failure points).  */
-        case jump:
-	  EXTRACT_NUMBER_AND_INCR (mcnt, p);	/* Get the amount to jump.  */
-          DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt);
-	  p += mcnt;				/* Do the jump.  */
-#ifdef _LIBC
-          DEBUG_PRINT2 ("(to %p).\n", p);
-#else
-          DEBUG_PRINT2 ("(to 0x%x).\n", p);
-#endif
-	  break;
-
-
-        /* We need this opcode so we can detect where alternatives end
-           in `group_match_null_string_p' et al.  */
-        case jump_past_alt:
-          DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n");
-          goto unconditional_jump;
-
-
-        /* Normally, the on_failure_jump pushes a failure point, which
-           then gets popped at pop_failure_jump.  We will end up at
-           pop_failure_jump, also, and with a pattern of, say, `a+', we
-           are skipping over the on_failure_jump, so we have to push
-           something meaningless for pop_failure_jump to pop.  */
-        case dummy_failure_jump:
-          DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n");
-          /* It doesn't matter what we push for the string here.  What
-             the code at `fail' tests is the value for the pattern.  */
-          PUSH_FAILURE_POINT (NULL, NULL, -2);
-          goto unconditional_jump;
-
-
-        /* At the end of an alternative, we need to push a dummy failure
-           point in case we are followed by a `pop_failure_jump', because
-           we don't want the failure point for the alternative to be
-           popped.  For example, matching `(a|ab)*' against `aab'
-           requires that we match the `ab' alternative.  */
-        case push_dummy_failure:
-          DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n");
-          /* See comments just above at `dummy_failure_jump' about the
-             two zeroes.  */
-          PUSH_FAILURE_POINT (NULL, NULL, -2);
-          break;
-
-        /* Have to succeed matching what follows at least n times.
-           After that, handle like `on_failure_jump'.  */
-        case succeed_n:
-          EXTRACT_NUMBER (mcnt, p + 2);
-          DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt);
-
-          assert (mcnt >= 0);
-          /* Originally, this is how many times we HAVE to succeed.  */
-          if (mcnt > 0)
-            {
-               mcnt--;
-	       p += 2;
-               STORE_NUMBER_AND_INCR (p, mcnt);
-#ifdef _LIBC
-               DEBUG_PRINT3 ("  Setting %p to %d.\n", p - 2, mcnt);
-#else
-               DEBUG_PRINT3 ("  Setting 0x%x to %d.\n", p - 2, mcnt);
-#endif
-            }
-	  else if (mcnt == 0)
-            {
-#ifdef _LIBC
-              DEBUG_PRINT2 ("  Setting two bytes from %p to no_op.\n", p+2);
-#else
-              DEBUG_PRINT2 ("  Setting two bytes from 0x%x to no_op.\n", p+2);
-#endif
-	      p[2] = (unsigned char) no_op;
-              p[3] = (unsigned char) no_op;
-              goto on_failure;
-            }
-          break;
-
-        case jump_n:
-          EXTRACT_NUMBER (mcnt, p + 2);
-          DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt);
-
-          /* Originally, this is how many times we CAN jump.  */
-          if (mcnt)
-            {
-               mcnt--;
-               STORE_NUMBER (p + 2, mcnt);
-#ifdef _LIBC
-               DEBUG_PRINT3 ("  Setting %p to %d.\n", p + 2, mcnt);
-#else
-               DEBUG_PRINT3 ("  Setting 0x%x to %d.\n", p + 2, mcnt);
-#endif
-	       goto unconditional_jump;
-            }
-          /* If don't have to jump any more, skip over the rest of command.  */
-	  else
-	    p += 4;
-          break;
-
-	case set_number_at:
-	  {
-            DEBUG_PRINT1 ("EXECUTING set_number_at.\n");
-
-            EXTRACT_NUMBER_AND_INCR (mcnt, p);
-            p1 = p + mcnt;
-            EXTRACT_NUMBER_AND_INCR (mcnt, p);
-#ifdef _LIBC
-            DEBUG_PRINT3 ("  Setting %p to %d.\n", p1, mcnt);
-#else
-            DEBUG_PRINT3 ("  Setting 0x%x to %d.\n", p1, mcnt);
-#endif
-	    STORE_NUMBER (p1, mcnt);
-            break;
-          }
-
-#if 0
-	/* The DEC Alpha C compiler 3.x generates incorrect code for the
-	   test  WORDCHAR_P (d - 1) != WORDCHAR_P (d)  in the expansion of
-	   AT_WORD_BOUNDARY, so this code is disabled.  Expanding the
-	   macro and introducing temporary variables works around the bug.  */
-
-	case wordbound:
-	  DEBUG_PRINT1 ("EXECUTING wordbound.\n");
-	  if (AT_WORD_BOUNDARY (d))
-	    break;
-	  goto fail;
-
-	case notwordbound:
-	  DEBUG_PRINT1 ("EXECUTING notwordbound.\n");
-	  if (AT_WORD_BOUNDARY (d))
-	    goto fail;
-	  break;
-#else
-	case wordbound:
-	{
-	  boolean prevchar, thischar;
-
-	  DEBUG_PRINT1 ("EXECUTING wordbound.\n");
-	  if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d))
-	    break;
-
-	  prevchar = WORDCHAR_P (d - 1);
-	  thischar = WORDCHAR_P (d);
-	  if (prevchar != thischar)
-	    break;
-	  goto fail;
-	}
-
-      case notwordbound:
-	{
-	  boolean prevchar, thischar;
-
-	  DEBUG_PRINT1 ("EXECUTING notwordbound.\n");
-	  if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d))
-	    goto fail;
-
-	  prevchar = WORDCHAR_P (d - 1);
-	  thischar = WORDCHAR_P (d);
-	  if (prevchar != thischar)
-	    goto fail;
-	  break;
-	}
-#endif
-
-	case wordbeg:
-          DEBUG_PRINT1 ("EXECUTING wordbeg.\n");
-	  if (WORDCHAR_P (d) && (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1)))
-	    break;
-          goto fail;
-
-	case wordend:
-          DEBUG_PRINT1 ("EXECUTING wordend.\n");
-	  if (!AT_STRINGS_BEG (d) && WORDCHAR_P (d - 1)
-              && (!WORDCHAR_P (d) || AT_STRINGS_END (d)))
-	    break;
-          goto fail;
-
-#ifdef emacs
-  	case before_dot:
-          DEBUG_PRINT1 ("EXECUTING before_dot.\n");
- 	  if (PTR_CHAR_POS ((unsigned char *) d) >= point)
-  	    goto fail;
-  	  break;
-
-  	case at_dot:
-          DEBUG_PRINT1 ("EXECUTING at_dot.\n");
- 	  if (PTR_CHAR_POS ((unsigned char *) d) != point)
-  	    goto fail;
-  	  break;
-
-  	case after_dot:
-          DEBUG_PRINT1 ("EXECUTING after_dot.\n");
-          if (PTR_CHAR_POS ((unsigned char *) d) <= point)
-  	    goto fail;
-  	  break;
-
-	case syntaxspec:
-          DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt);
-	  mcnt = *p++;
-	  goto matchsyntax;
-
-        case wordchar:
-          DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n");
-	  mcnt = (int) Sword;
-        matchsyntax:
-	  PREFETCH ();
-	  /* Can't use *d++ here; SYNTAX may be an unsafe macro.  */
-	  d++;
-	  if (SYNTAX (d[-1]) != (enum syntaxcode) mcnt)
-	    goto fail;
-          SET_REGS_MATCHED ();
-	  break;
-
-	case notsyntaxspec:
-          DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt);
-	  mcnt = *p++;
-	  goto matchnotsyntax;
-
-        case notwordchar:
-          DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n");
-	  mcnt = (int) Sword;
-        matchnotsyntax:
-	  PREFETCH ();
-	  /* Can't use *d++ here; SYNTAX may be an unsafe macro.  */
-	  d++;
-	  if (SYNTAX (d[-1]) == (enum syntaxcode) mcnt)
-	    goto fail;
-	  SET_REGS_MATCHED ();
-          break;
-
-#else /* not emacs */
-	case wordchar:
-          DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n");
-	  PREFETCH ();
-          if (!WORDCHAR_P (d))
-            goto fail;
-	  SET_REGS_MATCHED ();
-          d++;
-	  break;
-
-	case notwordchar:
-          DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n");
-	  PREFETCH ();
-	  if (WORDCHAR_P (d))
-            goto fail;
-          SET_REGS_MATCHED ();
-          d++;
-	  break;
-#endif /* not emacs */
-
-        default:
-          abort ();
-	}
-      continue;  /* Successfully executed one pattern command; keep going.  */
-
-
-    /* We goto here if a matching operation fails. */
-    fail:
-      if (!FAIL_STACK_EMPTY ())
-	{ /* A restart point is known.  Restore to that state.  */
-          DEBUG_PRINT1 ("\nFAIL:\n");
-          POP_FAILURE_POINT (d, p,
-                             lowest_active_reg, highest_active_reg,
-                             regstart, regend, reg_info);
-
-          /* If this failure point is a dummy, try the next one.  */
-          if (!p)
-	    goto fail;
-
-          /* If we failed to the end of the pattern, don't examine *p.  */
-	  assert (p <= pend);
-          if (p < pend)
-            {
-              boolean is_a_jump_n = false;
-
-              /* If failed to a backwards jump that's part of a repetition
-                 loop, need to pop this failure point and use the next one.  */
-              switch ((re_opcode_t) *p)
-                {
-                case jump_n:
-                  is_a_jump_n = true;
-                case maybe_pop_jump:
-                case pop_failure_jump:
-                case jump:
-                  p1 = p + 1;
-                  EXTRACT_NUMBER_AND_INCR (mcnt, p1);
-                  p1 += mcnt;
-
-                  if ((is_a_jump_n && (re_opcode_t) *p1 == succeed_n)
-                      || (!is_a_jump_n
-                          && (re_opcode_t) *p1 == on_failure_jump))
-                    goto fail;
-                  break;
-                default:
-                  /* do nothing */ ;
-                }
-            }
-
-          if (d >= string1 && d <= end1)
-	    dend = end_match_1;
-        }
-      else
-        break;   /* Matching at this starting point really fails.  */
-    } /* for (;;) */
-
-  if (best_regs_set)
-    goto restore_best_regs;
-
-  FREE_VARIABLES ();
-
-  return -1;         			/* Failure to match.  */
-} /* re_match_2 */
-
-/* Subroutine definitions for re_match_2.  */
-
-
-/* We are passed P pointing to a register number after a start_memory.
-
-   Return true if the pattern up to the corresponding stop_memory can
-   match the empty string, and false otherwise.
-
-   If we find the matching stop_memory, sets P to point to one past its number.
-   Otherwise, sets P to an undefined byte less than or equal to END.
-
-   We don't handle duplicates properly (yet).  */
-
-static boolean
-group_match_null_string_p (p, end, reg_info)
-    unsigned char **p, *end;
-    register_info_type *reg_info;
-{
-  int mcnt;
-  /* Point to after the args to the start_memory.  */
-  unsigned char *p1 = *p + 2;
-
-  while (p1 < end)
-    {
-      /* Skip over opcodes that can match nothing, and return true or
-	 false, as appropriate, when we get to one that can't, or to the
-         matching stop_memory.  */
-
-      switch ((re_opcode_t) *p1)
-        {
-        /* Could be either a loop or a series of alternatives.  */
-        case on_failure_jump:
-          p1++;
-          EXTRACT_NUMBER_AND_INCR (mcnt, p1);
-
-          /* If the next operation is not a jump backwards in the
-	     pattern.  */
-
-	  if (mcnt >= 0)
-	    {
-              /* Go through the on_failure_jumps of the alternatives,
-                 seeing if any of the alternatives cannot match nothing.
-                 The last alternative starts with only a jump,
-                 whereas the rest start with on_failure_jump and end
-                 with a jump, e.g., here is the pattern for `a|b|c':
-
-                 /on_failure_jump/0/6/exactn/1/a/jump_past_alt/0/6
-                 /on_failure_jump/0/6/exactn/1/b/jump_past_alt/0/3
-                 /exactn/1/c
-
-                 So, we have to first go through the first (n-1)
-                 alternatives and then deal with the last one separately.  */
-
-
-              /* Deal with the first (n-1) alternatives, which start
-                 with an on_failure_jump (see above) that jumps to right
-                 past a jump_past_alt.  */
-
-              while ((re_opcode_t) p1[mcnt-3] == jump_past_alt)
-                {
-                  /* `mcnt' holds how many bytes long the alternative
-                     is, including the ending `jump_past_alt' and
-                     its number.  */
-
-                  if (!alt_match_null_string_p (p1, p1 + mcnt - 3,
-				                      reg_info))
-                    return false;
-
-                  /* Move to right after this alternative, including the
-		     jump_past_alt.  */
-                  p1 += mcnt;
-
-                  /* Break if it's the beginning of an n-th alternative
-                     that doesn't begin with an on_failure_jump.  */
-                  if ((re_opcode_t) *p1 != on_failure_jump)
-                    break;
-
-		  /* Still have to check that it's not an n-th
-		     alternative that starts with an on_failure_jump.  */
-		  p1++;
-                  EXTRACT_NUMBER_AND_INCR (mcnt, p1);
-                  if ((re_opcode_t) p1[mcnt-3] != jump_past_alt)
-                    {
-		      /* Get to the beginning of the n-th alternative.  */
-                      p1 -= 3;
-                      break;
-                    }
-                }
-
-              /* Deal with the last alternative: go back and get number
-                 of the `jump_past_alt' just before it.  `mcnt' contains
-                 the length of the alternative.  */
-              EXTRACT_NUMBER (mcnt, p1 - 2);
-
-              if (!alt_match_null_string_p (p1, p1 + mcnt, reg_info))
-                return false;
-
-              p1 += mcnt;	/* Get past the n-th alternative.  */
-            } /* if mcnt > 0 */
-          break;
-
-
-        case stop_memory:
-	  assert (p1[1] == **p);
-          *p = p1 + 2;
-          return true;
-
-
-        default:
-          if (!common_op_match_null_string_p (&p1, end, reg_info))
-            return false;
-        }
-    } /* while p1 < end */
-
-  return false;
-} /* group_match_null_string_p */
-
-
-/* Similar to group_match_null_string_p, but doesn't deal with alternatives:
-   It expects P to be the first byte of a single alternative and END one
-   byte past the last. The alternative can contain groups.  */
-
-static boolean
-alt_match_null_string_p (p, end, reg_info)
-    unsigned char *p, *end;
-    register_info_type *reg_info;
-{
-  int mcnt;
-  unsigned char *p1 = p;
-
-  while (p1 < end)
-    {
-      /* Skip over opcodes that can match nothing, and break when we get
-         to one that can't.  */
-
-      switch ((re_opcode_t) *p1)
-        {
-	/* It's a loop.  */
-        case on_failure_jump:
-          p1++;
-          EXTRACT_NUMBER_AND_INCR (mcnt, p1);
-          p1 += mcnt;
-          break;
-
-	default:
-          if (!common_op_match_null_string_p (&p1, end, reg_info))
-            return false;
-        }
-    }  /* while p1 < end */
-
-  return true;
-} /* alt_match_null_string_p */
-
-
-/* Deals with the ops common to group_match_null_string_p and
-   alt_match_null_string_p.
-
-   Sets P to one after the op and its arguments, if any.  */
-
-static boolean
-common_op_match_null_string_p (p, end, reg_info)
-    unsigned char **p, *end;
-    register_info_type *reg_info;
-{
-  int mcnt;
-  boolean ret;
-  int reg_no;
-  unsigned char *p1 = *p;
-
-  switch ((re_opcode_t) *p1++)
-    {
-    case no_op:
-    case begline:
-    case endline:
-    case begbuf:
-    case endbuf:
-    case wordbeg:
-    case wordend:
-    case wordbound:
-    case notwordbound:
-#ifdef emacs
-    case before_dot:
-    case at_dot:
-    case after_dot:
-#endif
-      break;
-
-    case start_memory:
-      reg_no = *p1;
-      assert (reg_no > 0 && reg_no <= MAX_REGNUM);
-      ret = group_match_null_string_p (&p1, end, reg_info);
-
-      /* Have to set this here in case we're checking a group which
-         contains a group and a back reference to it.  */
-
-      if (REG_MATCH_NULL_STRING_P (reg_info[reg_no]) == MATCH_NULL_UNSET_VALUE)
-        REG_MATCH_NULL_STRING_P (reg_info[reg_no]) = ret;
-
-      if (!ret)
-        return false;
-      break;
-
-    /* If this is an optimized succeed_n for zero times, make the jump.  */
-    case jump:
-      EXTRACT_NUMBER_AND_INCR (mcnt, p1);
-      if (mcnt >= 0)
-        p1 += mcnt;
-      else
-        return false;
-      break;
-
-    case succeed_n:
-      /* Get to the number of times to succeed.  */
-      p1 += 2;
-      EXTRACT_NUMBER_AND_INCR (mcnt, p1);
-
-      if (mcnt == 0)
-        {
-          p1 -= 4;
-          EXTRACT_NUMBER_AND_INCR (mcnt, p1);
-          p1 += mcnt;
-        }
-      else
-        return false;
-      break;
-
-    case duplicate:
-      if (!REG_MATCH_NULL_STRING_P (reg_info[*p1]))
-        return false;
-      break;
-
-    case set_number_at:
-      p1 += 4;
-
-    default:
-      /* All other opcodes mean we cannot match the empty string.  */
-      return false;
-  }
-
-  *p = p1;
-  return true;
-} /* common_op_match_null_string_p */
-
-
-/* Return zero if TRANSLATE[S1] and TRANSLATE[S2] are identical for LEN
-   bytes; nonzero otherwise.  */
-
-static int
-bcmp_translate (s1, s2, len, translate)
-     const char *s1, *s2;
-     register int len;
-     RE_TRANSLATE_TYPE translate;
-{
-  register const unsigned char *p1 = (const unsigned char *) s1;
-  register const unsigned char *p2 = (const unsigned char *) s2;
-  while (len)
-    {
-      if (translate[*p1++] != translate[*p2++]) return 1;
-      len--;
-    }
-  return 0;
-}
-
-/* Entry points for GNU code.  */
-
-/* re_compile_pattern is the GNU regular expression compiler: it
-   compiles PATTERN (of length SIZE) and puts the result in BUFP.
-   Returns 0 if the pattern was valid, otherwise an error string.
-
-   Assumes the `allocated' (and perhaps `buffer') and `translate' fields
-   are set in BUFP on entry.
-
-   We call regex_compile to do the actual compilation.  */
-
-const char *
-re_compile_pattern (pattern, length, bufp)
-     const char *pattern;
-     size_t length;
-     struct re_pattern_buffer *bufp;
-{
-  reg_errcode_t ret;
-
-  /* GNU code is written to assume at least RE_NREGS registers will be set
-     (and at least one extra will be -1).  */
-  bufp->regs_allocated = REGS_UNALLOCATED;
-
-  /* And GNU code determines whether or not to get register information
-     by passing null for the REGS argument to re_match, etc., not by
-     setting no_sub.  */
-  bufp->no_sub = 0;
-
-  /* Match anchors at newline.  */
-  bufp->newline_anchor = 1;
-
-  ret = regex_compile (pattern, length, re_syntax_options, bufp);
-
-  if (!ret)
-    return NULL;
-  return gettext (re_error_msgid + re_error_msgid_idx[(int) ret]);
-}
-#ifdef _LIBC
-weak_alias (__re_compile_pattern, re_compile_pattern)
-#endif
-
-/* Entry points compatible with 4.2 BSD regex library.  We don't define
-   them unless specifically requested.  */
-
-#if defined _REGEX_RE_COMP || defined _LIBC
-
-/* BSD has one and only one pattern buffer.  */
-static struct re_pattern_buffer re_comp_buf;
-
-char *
-#ifdef _LIBC
-/* Make these definitions weak in libc, so POSIX programs can redefine
-   these names if they don't use our functions, and still use
-   regcomp/regexec below without link errors.  */
-weak_function
-#endif
-re_comp (s)
-    const char *s;
-{
-  reg_errcode_t ret;
-
-  if (!s)
-    {
-      if (!re_comp_buf.buffer)
-	return gettext ("No previous regular expression");
-      return 0;
-    }
-
-  if (!re_comp_buf.buffer)
-    {
-      re_comp_buf.buffer = (unsigned char *) malloc (200);
-      if (re_comp_buf.buffer == NULL)
-        return (char *) gettext (re_error_msgid
-				 + re_error_msgid_idx[(int) REG_ESPACE]);
-      re_comp_buf.allocated = 200;
-
-      re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH);
-      if (re_comp_buf.fastmap == NULL)
-	return (char *) gettext (re_error_msgid
-				 + re_error_msgid_idx[(int) REG_ESPACE]);
-    }
-
-  /* Since `re_exec' always passes NULL for the `regs' argument, we
-     don't need to initialize the pattern buffer fields which affect it.  */
-
-  /* Match anchors at newlines.  */
-  re_comp_buf.newline_anchor = 1;
-
-  ret = regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf);
-
-  if (!ret)
-    return NULL;
-
-  /* Yes, we're discarding `const' here if !HAVE_LIBINTL.  */
-  return (char *) gettext (re_error_msgid + re_error_msgid_idx[(int) ret]);
-}
-
-
-int
-#ifdef _LIBC
-weak_function
-#endif
-re_exec (s)
-    const char *s;
-{
-  const int len = strlen (s);
-  return
-    0 <= re_search (&re_comp_buf, s, len, 0, len, (struct re_registers *) 0);
-}
-
-#endif /* _REGEX_RE_COMP */
-
-/* POSIX.2 functions.  Don't define these for Emacs.  */
-
-#ifndef emacs
-
-/* regcomp takes a regular expression as a string and compiles it.
-
-   PREG is a regex_t *.  We do not expect any fields to be initialized,
-   since POSIX says we shouldn't.  Thus, we set
-
-     `buffer' to the compiled pattern;
-     `used' to the length of the compiled pattern;
-     `syntax' to RE_SYNTAX_POSIX_EXTENDED if the
-       REG_EXTENDED bit in CFLAGS is set; otherwise, to
-       RE_SYNTAX_POSIX_BASIC;
-     `newline_anchor' to REG_NEWLINE being set in CFLAGS;
-     `fastmap' to an allocated space for the fastmap;
-     `fastmap_accurate' to zero;
-     `re_nsub' to the number of subexpressions in PATTERN.
-
-   PATTERN is the address of the pattern string.
-
-   CFLAGS is a series of bits which affect compilation.
-
-     If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we
-     use POSIX basic syntax.
-
-     If REG_NEWLINE is set, then . and [^...] don't match newline.
-     Also, regexec will try a match beginning after every newline.
-
-     If REG_ICASE is set, then we considers upper- and lowercase
-     versions of letters to be equivalent when matching.
-
-     If REG_NOSUB is set, then when PREG is passed to regexec, that
-     routine will report only success or failure, and nothing about the
-     registers.
-
-   It returns 0 if it succeeds, nonzero if it doesn't.  (See regex.h for
-   the return codes and their meanings.)  */
-
-int
-regcomp (preg, pattern, cflags)
-    regex_t *preg;
-    const char *pattern;
-    int cflags;
-{
-  reg_errcode_t ret;
-  reg_syntax_t syntax
-    = (cflags & REG_EXTENDED) ?
-      RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC;
-
-  /* regex_compile will allocate the space for the compiled pattern.  */
-  preg->buffer = 0;
-  preg->allocated = 0;
-  preg->used = 0;
-
-  /* Try to allocate space for the fastmap.  */
-  preg->fastmap = (char *) malloc (1 << BYTEWIDTH);
-
-  if (cflags & REG_ICASE)
-    {
-      unsigned i;
-
-      preg->translate
-	= (RE_TRANSLATE_TYPE) malloc (CHAR_SET_SIZE
-				      * sizeof (*(RE_TRANSLATE_TYPE)0));
-      if (preg->translate == NULL)
-        return (int) REG_ESPACE;
-
-      /* Map uppercase characters to corresponding lowercase ones.  */
-      for (i = 0; i < CHAR_SET_SIZE; i++)
-        preg->translate[i] = ISUPPER (i) ? TOLOWER (i) : i;
-    }
-  else
-    preg->translate = NULL;
-
-  /* If REG_NEWLINE is set, newlines are treated differently.  */
-  if (cflags & REG_NEWLINE)
-    { /* REG_NEWLINE implies neither . nor [^...] match newline.  */
-      syntax &= ~RE_DOT_NEWLINE;
-      syntax |= RE_HAT_LISTS_NOT_NEWLINE;
-      /* It also changes the matching behavior.  */
-      preg->newline_anchor = 1;
-    }
-  else
-    preg->newline_anchor = 0;
-
-  preg->no_sub = !!(cflags & REG_NOSUB);
-
-  /* POSIX says a null character in the pattern terminates it, so we
-     can use strlen here in compiling the pattern.  */
-  ret = regex_compile (pattern, strlen (pattern), syntax, preg);
-
-  /* POSIX doesn't distinguish between an unmatched open-group and an
-     unmatched close-group: both are REG_EPAREN.  */
-  if (ret == REG_ERPAREN) ret = REG_EPAREN;
-
-  if (ret == REG_NOERROR && preg->fastmap)
-    {
-      /* Compute the fastmap now, since regexec cannot modify the pattern
-	 buffer.  */
-      if (re_compile_fastmap (preg) == -2)
-	{
-	  /* Some error occurred while computing the fastmap, just forget
-	     about it.  */
-	  free (preg->fastmap);
-	  preg->fastmap = NULL;
-	}
-    }
-
-  return (int) ret;
-}
-#ifdef _LIBC
-weak_alias (__regcomp, regcomp)
-#endif
-
-
-/* regexec searches for a given pattern, specified by PREG, in the
-   string STRING.
-
-   If NMATCH is zero or REG_NOSUB was set in the cflags argument to
-   `regcomp', we ignore PMATCH.  Otherwise, we assume PMATCH has at
-   least NMATCH elements, and we set them to the offsets of the
-   corresponding matched substrings.
-
-   EFLAGS specifies `execution flags' which affect matching: if
-   REG_NOTBOL is set, then ^ does not match at the beginning of the
-   string; if REG_NOTEOL is set, then $ does not match at the end.
-
-   We return 0 if we find a match and REG_NOMATCH if not.  */
-
-int
-regexec (preg, string, nmatch, pmatch, eflags)
-    const regex_t *preg;
-    const char *string;
-    size_t nmatch;
-    regmatch_t pmatch[];
-    int eflags;
-{
-  int ret;
-  struct re_registers regs;
-  regex_t private_preg;
-  int len = strlen (string);
-  boolean want_reg_info = !preg->no_sub && nmatch > 0;
-
-  private_preg = *preg;
-
-  private_preg.not_bol = !!(eflags & REG_NOTBOL);
-  private_preg.not_eol = !!(eflags & REG_NOTEOL);
-
-  /* The user has told us exactly how many registers to return
-     information about, via `nmatch'.  We have to pass that on to the
-     matching routines.  */
-  private_preg.regs_allocated = REGS_FIXED;
-
-  if (want_reg_info)
-    {
-      regs.num_regs = nmatch;
-      regs.start = TALLOC (nmatch * 2, regoff_t);
-      if (regs.start == NULL)
-        return (int) REG_NOMATCH;
-      regs.end = regs.start + nmatch;
-    }
-
-  /* Perform the searching operation.  */
-  ret = re_search (&private_preg, string, len,
-                   /* start: */ 0, /* range: */ len,
-                   want_reg_info ? &regs : (struct re_registers *) 0);
-
-  /* Copy the register information to the POSIX structure.  */
-  if (want_reg_info)
-    {
-      if (ret >= 0)
-        {
-          unsigned r;
-
-          for (r = 0; r < nmatch; r++)
-            {
-              pmatch[r].rm_so = regs.start[r];
-              pmatch[r].rm_eo = regs.end[r];
-            }
-        }
-
-      /* If we needed the temporary register info, free the space now.  */
-      free (regs.start);
-    }
-
-  /* We want zero return to mean success, unlike `re_search'.  */
-  return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH;
-}
-#ifdef _LIBC
-weak_alias (__regexec, regexec)
-#endif
-
-
-/* Returns a message corresponding to an error code, ERRCODE, returned
-   from either regcomp or regexec.   We don't use PREG here.  */
-
-size_t
-regerror (errcode, preg, errbuf, errbuf_size)
-    int errcode;
-    const regex_t *preg;
-    char *errbuf;
-    size_t errbuf_size;
-{
-  const char *msg;
-  size_t msg_size;
-
-  if (errcode < 0
-      || errcode >= (int) (sizeof (re_error_msgid_idx)
-			   / sizeof (re_error_msgid_idx[0])))
-    /* Only error codes returned by the rest of the code should be passed
-       to this routine.  If we are given anything else, or if other regex
-       code generates an invalid error code, then the program has a bug.
-       Dump core so we can fix it.  */
-    abort ();
-
-  msg = gettext (re_error_msgid + re_error_msgid_idx[errcode]);
-
-  msg_size = strlen (msg) + 1; /* Includes the null.  */
-
-  if (errbuf_size != 0)
-    {
-      if (msg_size > errbuf_size)
-        {
-#if defined HAVE_MEMPCPY || defined _LIBC
-	  *((char *) __mempcpy (errbuf, msg, errbuf_size - 1)) = '\0';
-#else
-          memcpy (errbuf, msg, errbuf_size - 1);
-          errbuf[errbuf_size - 1] = 0;
-#endif
-        }
-      else
-        memcpy (errbuf, msg, msg_size);
-    }
-
-  return msg_size;
-}
-#ifdef _LIBC
-weak_alias (__regerror, regerror)
-#endif
-
-
-/* Free dynamically allocated space used by PREG.  */
-
-void
-regfree (preg)
-    regex_t *preg;
-{
-  if (preg->buffer != NULL)
-    free (preg->buffer);
-  preg->buffer = NULL;
-
-  preg->allocated = 0;
-  preg->used = 0;
-
-  if (preg->fastmap != NULL)
-    free (preg->fastmap);
-  preg->fastmap = NULL;
-  preg->fastmap_accurate = 0;
-
-  if (preg->translate != NULL)
-    free (preg->translate);
-  preg->translate = NULL;
-}
-#ifdef _LIBC
-weak_alias (__regfree, regfree)
-#endif
-
-#endif /* not emacs  */
-#else	/* !defined(USE_LIB_REGEX) */
-char regex_d1[] = "d"; char *regex_d2 = regex_d1;
-#endif	/* defined(USE_LIB_REGEX) */
diff --git a/lib/rmnt.c b/lib/rmnt.c
index 093b6bf..cfc58b2 100644
--- a/lib/rmnt.c
+++ b/lib/rmnt.c
@@ -2,7 +2,6 @@
  * rmnt.c -- readmnt() function for lsof library
  */
 
-
 /*
  * Copyright 1997 Purdue Research Foundation, West Lafayette, Indiana
  * 47907.  All rights reserved.
@@ -29,19 +28,10 @@
  * 4. This notice may not be removed or altered.
  */
 
+#include "common.h"
+#include "machine.h"
 
-#include "../machine.h"
-
-#if	defined(USE_LIB_READMNT)
-
-# if	!defined(lint)
-static char copyright[] =
-"@(#) Copyright 1997 Purdue Research Foundation.\nAll rights reserved.\n";
-# endif	/* !defined(lint) */
-
-#include "../lsof.h"
-
-
+#if defined(USE_LIB_READMNT)
 
 /*
  * The caller may define:
@@ -67,176 +57,169 @@ static char copyright[] =
  *
  */
 
-#if	!defined(RMNT_EXPDEV)
-#define	RMNT_EXPDEV(n)	n
-#endif	/* !defined(RMNT_EXPDEV) */
-
+#    if !defined(RMNT_EXPDEV)
+#        define RMNT_EXPDEV(n) n
+#    endif /* !defined(RMNT_EXPDEV) */
 
 /*
  * 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;
-	FILE *mfp;
-	struct mntent *mp;
-	struct mounts *mtp;
-	char *opt, *opte;
-	struct stat sb;
-
-	if (Lmi || Lmist)
-	    return(Lmi);
-/*
- * Open access to the mount table.
- */
-	if (!(mfp = setmntent(MOUNTED, "r"))) {
-	    (void) fprintf(stderr, "%s: can't access %s\n", Pn, MOUNTED);
-	    Error();
-	}
-/*
- * Read mount table entries.
- */
-	while ((mp = getmntent(mfp))) {
-
-#if	defined(MNTSKIP)
-	/*
-	 * Specfy in the MNTSKIP macro the decisions needed to determine
-	 * that this entry should be skipped.
-	 *
-	 * Typically entries whose mnt_type is MNTTYPE_IGNORE are skipped.
-	 *
-	 * The MNTSKIP macro allows the caller to use other tests.
-	 */
-	    MNTSKIP
-#endif	/* MNTSKIP */
-
-	/*
-	 * Interpolate a possible symbolic directory link.
-	 */
-	    if (dn)
-		(void) free((FREE_P *)dn);
-	    if (!(dn = mkstrcpy(mp->mnt_dir, (MALLOC_S *)NULL)))
-		goto no_space_for_mount;
-	    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(mp->mnt_type, stderr, 0);
-		    (void) fprintf(stderr, " file system ");
-		    safestrprt(mp->mnt_dir, stderr, 1);
-		    (void) fprintf(stderr,
-			"      Output information may be incomplete.\n");
-		}
-		if ((opt = strstr(mp->mnt_opts, "dev="))) {
-		    (void) zeromem(&sb, sizeof(sb));
-		    if ((opte = x2dev(opt + 4, (dev_t *)&sb.st_dev))) {
-			sb.st_mode = S_IFDIR | 0777;
-			if (!Fwarn)
-			    (void) fprintf(stderr,
-				"      assuming \"%.*s\" from %s\n",
-				(int)(opte - opt), opt, MOUNTED);
-		    } else
-			opt = (char *)NULL;
-		}
-		if (!opt)
-		    continue;
-	    }
-	/*
-	 * Allocate and fill a local mounts structure with the directory
-	 * (mounted) information.
-	 */
-	    if (!(mtp = (struct mounts *)malloc(sizeof(struct mounts)))) {
-
-no_space_for_mount:
-
-		(void) fprintf(stderr, "%s: no space for mount at ", Pn);
-		safestrprt(mp->mnt_fsname, stderr, 0);
-		(void) fprintf(stderr, " (");
-		safestrprt(mp->mnt_dir, stderr, 0);
-		(void) fprintf(stderr, ")\n");
-		Error();
-	    }
-	    mtp->dir = dn;
-	    dn = (char *)NULL;
-	    mtp->next = Lmi;
-	    mtp->dev = RMNT_EXPDEV(sb.st_dev);
-	    mtp->rdev = RMNT_EXPDEV(sb.st_rdev);
-	    mtp->inode = (INODETYPE)sb.st_ino;
-	    mtp->mode = sb.st_mode;
-
-# if	defined(RMNT_FSTYPE) && defined(MOUNTS_FSTYPE)
-	/*
-	 * Make a copy of RMNT_FSTYPE in MOUNTS_FSTYPE.
-	 */
-	    if (!(mtp->MOUNTS_FSTYPE = mkstrcpy(mp->RMNT_FSTYPE,
-						(MALLOC_S *)NULL)))
-	    {
-		(void) fprintf(stderr, "%s: no space for fstype (%s): %s\n",
-		    Pn, mtp->dir, mp->RMNT_FSTYPE);
-		Error();
-	    }
-	    (void) strcpy(mtp->MOUNTS_FSTYPE, mp->RMNT_FSTYPE);
-# endif	/* defined(RMNT_FSTYP) && defined(MOUNTS_FSTYP) */
-
-# if	defined(RMNT_STAT_FSTYPE) && defined(MOUNTS_STAT_FSTYPE)
-	/*
-	 * Make a copy of RMNT_STAT_FSTYPE in MOUNTS_STAT_FSTYPE.
-	 */
-	    mtp->MOUNTS_STAT_FSTYPE = (int)sb.RMNT_STAT_FSTYPE;
-# endif	/* defined(RMNT_STAT_FSTYP) && defined(MOUNTS_STAT_FSTYP) */
-
-	/*
-	 * Interpolate a possible file system (mounted-on device) name link.
-	 */
-	    if (!(dn = mkstrcpy(mp->mnt_fsname, (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) endmntent(mfp);
-/*
- * Clean up and return the local nount info table address.
- */
-	if (dn)
-	    (void) free((FREE_P *)dn);
-	Lmist = 1;
-	return(Lmi);
+struct mounts *readmnt(struct lsof_context *ctx) {
+    char *dn = (char *)NULL;
+    char *ln;
+    FILE *mfp;
+    struct mntent *mp;
+    struct mounts *mtp;
+    char *opt, *opte;
+    struct stat sb;
+
+    if (Lmi || Lmist)
+        return (Lmi);
+    /*
+     * Open access to the mount table.
+     */
+    if (!(mfp = setmntent(MOUNTED, "r"))) {
+        (void)fprintf(stderr, "%s: can't access %s\n", Pn, MOUNTED);
+        Error(ctx);
+    }
+    /*
+     * Read mount table entries.
+     */
+    while ((mp = getmntent(mfp))) {
+
+#    if defined(MNTSKIP)
+        /*
+         * Specify in the MNTSKIP macro the decisions needed to determine
+         * that this entry should be skipped.
+         *
+         * Typically entries whose mnt_type is MNTTYPE_IGNORE are skipped.
+         *
+         * The MNTSKIP macro allows the caller to use other tests.
+         */
+        MNTSKIP
+#    endif /* MNTSKIP */
+
+        /*
+         * Interpolate a possible symbolic directory link.
+         */
+        if (dn)
+            (void)free((FREE_P *)dn);
+        if (!(dn = mkstrcpy(mp->mnt_dir, (MALLOC_S *)NULL)))
+            goto no_space_for_mount;
+        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(mp->mnt_type, stderr, 0);
+                (void)fprintf(stderr, " file system ");
+                safestrprt(mp->mnt_dir, stderr, 1);
+                (void)fprintf(stderr,
+                              "      Output information may be incomplete.\n");
+            }
+            if ((opt = strstr(mp->mnt_opts, "dev="))) {
+                (void)zeromem(&sb, sizeof(sb));
+                if ((opte = x2dev(opt + 4, (dev_t *)&sb.st_dev))) {
+                    sb.st_mode = S_IFDIR | 0777;
+                    if (!Fwarn)
+                        (void)fprintf(stderr,
+                                      "      assuming \"%.*s\" from %s\n",
+                                      (int)(opte - opt), opt, MOUNTED);
+                } else
+                    opt = (char *)NULL;
+            }
+            if (!opt)
+                continue;
+        }
+        /*
+         * Allocate and fill a local mounts structure with the directory
+         * (mounted) information.
+         */
+        if (!(mtp = (struct mounts *)malloc(sizeof(struct mounts)))) {
+
+        no_space_for_mount:
+
+            (void)fprintf(stderr, "%s: no space for mount at ", Pn);
+            safestrprt(mp->mnt_fsname, stderr, 0);
+            (void)fprintf(stderr, " (");
+            safestrprt(mp->mnt_dir, stderr, 0);
+            (void)fprintf(stderr, ")\n");
+            Error(ctx);
+        }
+        mtp->dir = dn;
+        dn = (char *)NULL;
+        mtp->next = Lmi;
+        mtp->dev = RMNT_EXPDEV(sb.st_dev);
+        mtp->rdev = RMNT_EXPDEV(sb.st_rdev);
+        mtp->inode = (INODETYPE)sb.st_ino;
+        mtp->mode = sb.st_mode;
+
+#    if defined(RMNT_FSTYPE) && defined(MOUNTS_FSTYPE)
+        /*
+         * Make a copy of RMNT_FSTYPE in MOUNTS_FSTYPE.
+         */
+        if (!(mtp->MOUNTS_FSTYPE =
+                  mkstrcpy(mp->RMNT_FSTYPE, (MALLOC_S *)NULL))) {
+            (void)fprintf(stderr, "%s: no space for fstype (%s): %s\n", Pn,
+                          mtp->dir, mp->RMNT_FSTYPE);
+            Error(ctx);
+        }
+        (void)strcpy(mtp->MOUNTS_FSTYPE, mp->RMNT_FSTYPE);
+#    endif /* defined(RMNT_FSTYP) && defined(MOUNTS_FSTYP) */
+
+#    if defined(RMNT_STAT_FSTYPE) && defined(MOUNTS_STAT_FSTYPE)
+        /*
+         * Make a copy of RMNT_STAT_FSTYPE in MOUNTS_STAT_FSTYPE.
+         */
+        mtp->MOUNTS_STAT_FSTYPE = (int)sb.RMNT_STAT_FSTYPE;
+#    endif /* defined(RMNT_STAT_FSTYP) && defined(MOUNTS_STAT_FSTYP) */
+
+        /*
+         * Interpolate a possible file system (mounted-on device) name link.
+         */
+        if (!(dn = mkstrcpy(mp->mnt_fsname, (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)endmntent(mfp);
+    /*
+     * Clean up and return the local nount info table address.
+     */
+    if (dn)
+        (void)free((FREE_P *)dn);
+    Lmist = 1;
+    return (Lmi);
 }
-#else	/* !defined(USE_LIB_READMNT) */
-char rmnt_d1[] = "d"; char *rmnt_d2 = rmnt_d1;
-#endif	/* defined(USE_LIB_READMNT) */
+#else  /* !defined(USE_LIB_READMNT) */
+char rmnt_d1[] = "d";
+char *rmnt_d2 = rmnt_d1;
+#endif /* defined(USE_LIB_READMNT) */
diff --git a/lib/rnam.c b/lib/rnam.c
index e0cd696..312ef75 100644
--- a/lib/rnam.c
+++ b/lib/rnam.c
@@ -2,7 +2,6 @@
  * rnam.c -- BSD format name cache functions for lsof library
  */
 
-
 /*
  * Copyright 1997 Purdue Research Foundation, West Lafayette, Indiana
  * 47907.  All rights reserved.
@@ -29,18 +28,10 @@
  * 4. This notice may not be removed or altered.
  */
 
+#include "common.h"
+#include "machine.h"
 
-#include "../machine.h"
-
-#if	defined(HASNCACHE) && defined(USE_LIB_RNAM)
-
-# if	!defined(lint)
-static char copyright[] =
-"@(#) Copyright 1997 Purdue Research Foundation.\nAll rights reserved.\n";
-# endif	/* !defined(lint) */
-
-#include "../lsof.h"
-
+#if defined(HASNCACHE) && defined(USE_LIB_RNAM)
 
 /*
  * rnam.c - read BSD format (struct namecache or nch) name cache
@@ -94,58 +85,57 @@ static char copyright[] =
  *		_PROTOTYPE(static void ncache_load,(void));
  */
 
-
 /*
  * Local static values
  */
 
-static int Mch;				/* name cache hash mask */
+static int Mch; /* name cache hash mask */
 
-# if	!defined(NCACHE_NC_CAST)
-#define	NCACHE_SZ_CAST	int
-# endif	/* !defined(NCACHE_NC_CAST) */
+#    if !defined(NCACHE_NC_CAST)
+#        define NCACHE_SZ_CAST int
+#    endif /* !defined(NCACHE_NC_CAST) */
 
-static NCACHE_SZ_CAST Nc = 0;		/* size of name cache */
-static int Nch = 0;			/* size of name cache hash pointer
-					 * table */
+static NCACHE_SZ_CAST Nc = 0; /* size of name cache */
+static int Nch = 0;           /* size of name cache hash pointer
+                               * table */
 struct l_nch {
-	KA_T na;			/* node address */
+    KA_T na; /* node address */
 
-# if	defined(NCACHE_NODEID)
-	unsigned long id;		/* capability ID */
-# endif	/* defined(NCACHE_NODEID) */
+#    if defined(NCACHE_NODEID)
+    unsigned long id; /* capability ID */
+#    endif            /* defined(NCACHE_NODEID) */
 
-# if	defined(NCACHE_PARADDR) && defined(NCACHE_PARID)
-	KA_T pa;			/* parent node address */
-	struct l_nch *pla;		/* parent local node address */
-	unsigned long did;		/* parent capability ID */
-# endif	/* defined(NCACHE_PARADDR) && defined(NCACHE_PARID) */
+#    if defined(NCACHE_PARADDR) && defined(NCACHE_PARID)
+    KA_T pa;           /* parent node address */
+    struct l_nch *pla; /* parent local node address */
+    unsigned long did; /* parent capability ID */
+#    endif             /* defined(NCACHE_PARADDR) && defined(NCACHE_PARID) */
 
-	char nm[NCHNAMLEN+1];		/* name */
-	int nl;				/* name length */
+    char nm[NCHNAMLEN + 1]; /* name */
+    int nl;                 /* name length */
 };
 
-static struct l_nch *Ncache = (struct l_nch*)NULL;
-					/* the local name cache */
+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 */
+/* Ncache hash pointers */
+static int Ncfirst = 1; /* first-call status */
 
-# if	defined(NCACHE_NODEID)
-#define ncachehash(i,n)		Nchash+(((((int)(n)>>2)+((int)(i)))*31415)&Mch)
-_PROTOTYPE(static struct l_nch *ncache_addr,(unsigned long i, KA_T na));
-# else	/* !defined(NCACHE_NODEID) */
-#define ncachehash(n)		Nchash+((((int)(n)>>2)*31415)&Mch)
-_PROTOTYPE(static struct l_nch *ncache_addr,(KA_T na));
-# endif	/* defined(NCACHE_NODEID) */
+#    if defined(NCACHE_NODEID)
+#        define ncachehash(i, n)                                               \
+            Nchash + (((((int)(n) >> 2) + ((int)(i))) * 31415) & Mch)
+static struct l_nch *ncache_addr(unsigned long i, KA_T na);
+#    else /* !defined(NCACHE_NODEID) */
+#        define ncachehash(n) Nchash + ((((int)(n) >> 2) * 31415) & Mch)
+static struct l_nch *ncache_addr(KA_T na);
+#    endif /* defined(NCACHE_NODEID) */
 
-#define DEFNCACHESZ	1024	/* local size if X_NCSIZE kernel value < 1 */
-#define	LNCHINCRSZ	64	/* local size increment */
-
-# if	!defined(NCACHE_NO_ROOT)
-_PROTOTYPE(static int ncache_isroot,(KA_T na, char *cp));
-# endif	/* !defined(NCACHE_NO_ROOT) */
+#    define DEFNCACHESZ 1024 /* local size if X_NCSIZE kernel value < 1 */
+#    define LNCHINCRSZ 64    /* local size increment */
 
+#    if !defined(NCACHE_NO_ROOT)
+static int ncache_isroot(KA_T na, char *cp);
+#    endif /* !defined(NCACHE_NO_ROOT) */
 
 /*
  * ncache_addr() - look up a node's local ncache address
@@ -153,516 +143,501 @@ _PROTOTYPE(static int ncache_isroot,(KA_T na, char *cp));
 
 static struct l_nch *
 
-# if	defined(NCACHE_NODEID)
-ncache_addr(i, na)
-	unsigned long i;		/* node's capability ID */
-# else	/* !defined(NCACHE_NODEID) */
-ncache_addr(na)
-# endif	/* defined(NCACHE_NODEID) */
+#    if defined(NCACHE_NODEID)
+ncache_addr(unsigned long i, /* node's capability ID */
+#    else                    /* !defined(NCACHE_NODEID) */
+ncache_addr(
+#    endif                   /* defined(NCACHE_NODEID) */
 
-	KA_T na;			/* node's address */
+            KA_T na) /* node's address */
 {
-	struct l_nch **hp;
+    struct l_nch **hp;
 
-# if	defined(NCACHE_NODEID)
-	for (hp = ncachehash(i, na); *hp; hp++)
-# else	/* !defined(NCACHE_NODEID) */
-	for (hp = ncachehash(na); *hp; hp++)
-# endif	/* defined(NCACHE_NODEID) */
+#    if defined(NCACHE_NODEID)
+    for (hp = ncachehash(i, na); *hp; hp++)
+#    else  /* !defined(NCACHE_NODEID) */
+    for (hp = ncachehash(na); *hp; hp++)
+#    endif /* defined(NCACHE_NODEID) */
 
-	{
+    {
 
-# if	defined(NCACHE_NODEID)
-	    if ((*hp)->id == i && (*hp)->na == na)
-# else	/* !defined(NCACHE_NODEID) */
-	    if ((*hp)->na == na)
-# endif	/* defined(NCACHE_NODEID) */
+#    if defined(NCACHE_NODEID)
+        if ((*hp)->id == i && (*hp)->na == na)
+#    else  /* !defined(NCACHE_NODEID) */
+        if ((*hp)->na == na)
+#    endif /* defined(NCACHE_NODEID) */
 
-		return(*hp);
-	}
-	return((struct l_nch *)NULL);
+            return (*hp);
+    }
+    return ((struct l_nch *)NULL);
 }
 
-
-# if	!defined(NCACHE_NO_ROOT)
+#    if !defined(NCACHE_NO_ROOT)
 /*
  * ncache_isroot() - is head of name cache path a file system root?
  */
 
-static int
-ncache_isroot(na, cp)
-	KA_T na;				/* kernel node address */
-	char *cp;				/* partial path */
+static int ncache_isroot(struct lsof_context *ctx, /* context */
+                         KA_T na,                  /* kernel node address */
+                         char *cp)                 /* partial path */
 {
-	char buf[MAXPATHLEN];
-	int i;
-	MALLOC_S len;
-	struct mounts *mtp;
-	static int nca = 0;
-	static int ncn = 0;
-	static KA_T *nc = (KA_T *)NULL;
-	struct stat sb;
-	struct vnode v;
-
-	if (!na)
-	    return(0);
-/*
- * Search the root vnode 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
-	    ||  (unsigned long)sb.st_ino != Lf->inode)
-		return(0);
-	}
-/*
- * Add the node address to the root node 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(nc, len);
-	    }
-	    if (!nc) {
-		(void) fprintf(stderr, "%s: no space for root node table\n",
-		    Pn);
-		Error();
-	    }
-	    nca += 10;
-	}
-	nc[ncn++] = na;
-	return(1);
+    char buf[MAXPATHLEN];
+    int i;
+    MALLOC_S len;
+    struct mounts *mtp;
+    static int nca = 0;
+    static int ncn = 0;
+    static KA_T *nc = (KA_T *)NULL;
+    struct stat sb;
+    struct vnode v;
+
+    if (!na)
+        return (0);
+    /*
+     * Search the root vnode 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(ctx, (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 || (unsigned long)sb.st_ino != Lf->inode)
+            return (0);
+    }
+    /*
+     * Add the node address to the root node 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(nc, len);
+        }
+        if (!nc) {
+            (void)fprintf(stderr, "%s: no space for root node table\n", Pn);
+            Error(ctx);
+        }
+        nca += 10;
+    }
+    nc[ncn++] = na;
+    return (1);
 }
-# endif	/* !defined(NCACHE_NO_ROOT) */
-
+#    endif /* !defined(NCACHE_NO_ROOT) */
 
 /*
  * ncache_load() - load the kernel's name cache
  */
 
-void
-ncache_load()
-{
-	struct l_nch **hp, *lc;
-	int i, len, n;
-	static int iNc = 0;
-	struct NCACHE *kc;
-	static KA_T kp = (KA_T)NULL;
-	KA_T v;
-
-# if	defined(NCACHE_NXT)
-	static KA_T kf;
-	struct NCACHE nc;
-# else	/* !defined NCACHE_NXT) */
-	static struct NCACHE *kca = (struct NCACHE *)NULL;
-# endif	/* defined(NCACHE_NXT) */
-
-	if (!Fncache)
-	    return;
-	if (Ncfirst) {
-
-	/*
-	 * Do startup (first-time) functions.
-	 */
-	    Ncfirst = 0;
-	/*
-	 * Establish kernel cache size.
-	 */
-	    v = (KA_T)0;
-	    if (get_Nl_value(X_NCSIZE, (struct drive_Nl *)NULL, &v) < 0
-	    ||  !v
-	    ||  kread((KA_T)v, (char *)&Nc, sizeof(Nc)))
-	    {
-		if (!Fwarn)
-		    (void) fprintf(stderr,
-			"%s: WARNING: can't read name cache size: %s\n",
-			Pn, print_kptr(v, (char *)NULL, 0));
-		iNc = Nc = 0;
-		return;
-	    }
-	    iNc = Nc;
-	    if (Nc < 1) {
-		if (!Fwarn) {
-		    (void) fprintf(stderr,
-			"%s: WARNING: kernel name cache size: %d\n", Pn, Nc);
-		    (void) fprintf(stderr,
-			"      Cache size assumed to be: %d\n", DEFNCACHESZ);
-		}
-		iNc = Nc = DEFNCACHESZ;
-	    }
-	/*
-	 * Establish kernel cache address.
-	 */
-	    v = (KA_T)0;
-	    if (get_Nl_value(X_NCACHE, (struct drive_Nl *)NULL, &v) < 0
-	    ||  !v
-	    ||  kread((KA_T)v, (char *)&kp, sizeof(kp))) {
-		if (!Fwarn)
-		    (void) fprintf(stderr,
-			"%s: WARNING: can't read name cache address: %s\n",
-			Pn, print_kptr(v, (char *)NULL, 0));
-		iNc = Nc = 0;
-		return;
-	    }
-
-# if	defined(NCACHE_NXT)
-	    kf = kp;
-
-# else	/* !defined(NCACHE_NXT) */
-	/*
-	 * Allocate space for a local copy of the kernel's cache.
-	 */
-	    len = Nc * sizeof(struct NCACHE);
-	    if (!(kca = (struct NCACHE *)malloc((MALLOC_S)len))) {
-		if (!Fwarn)
-		    (void) fprintf(stderr,
-			"%s: can't allocate name cache space: %d\n", Pn, len);
-		Error();
-	    }
-# endif	/* defined(NCACHE_NXT) */
-
-	/*
-	 * Allocate space for the local cache.
-	 */
-	    len = Nc * sizeof(struct l_nch);
-	    if (!(Ncache = (struct l_nch *)malloc((MALLOC_S)len))) {
-
-no_local_space:
-
-		if (!Fwarn)
-		    (void) fprintf(stderr,
-			"%s: no space for %d byte local name cache\n", Pn, len);
-		Error();
-	    }
-	} else {
-
-	/*
-	 * Do setup for repeat calls.
-	 */
-	    if ((Nc = iNc) == 0)
-		return;
-	    if (Nchash) {
-		(void) free((FREE_P *)Nchash);
-		Nchash = (struct l_nch **)NULL;
-	    }
-
-# if    defined(NCACHE_NXT)
-	    kp = kf;
-# endif /* defined(NCACHE_NXT) */
-
-	}
-
-# if    !defined(NCACHE_NXT)
+void ncache_load() {
+    struct l_nch **hp, *lc;
+    int i, len, n;
+    static int iNc = 0;
+    struct NCACHE *kc;
+    static KA_T kp = (KA_T)NULL;
+    KA_T v;
+
+#    if defined(NCACHE_NXT)
+    static KA_T kf;
+    struct NCACHE nc;
+#    else  /* !defined NCACHE_NXT) */
+    static struct NCACHE *kca = (struct NCACHE *)NULL;
+#    endif /* defined(NCACHE_NXT) */
+
+    if (!Fncache)
+        return;
+    if (Ncfirst) {
+
+        /*
+         * Do startup (first-time) functions.
+         */
+        Ncfirst = 0;
+        /*
+         * Establish kernel cache size.
+         */
+        v = (KA_T)0;
+        if (get_Nl_value(X_NCSIZE, (struct drive_Nl *)NULL, &v) < 0 || !v ||
+            kread(ctx, (KA_T)v, (char *)&Nc, sizeof(Nc))) {
+            if (!Fwarn)
+                (void)fprintf(stderr,
+                              "%s: WARNING: can't read name cache size: %s\n",
+                              Pn, print_kptr(v, (char *)NULL, 0));
+            iNc = Nc = 0;
+            return;
+        }
+        iNc = Nc;
+        if (Nc < 1) {
+            if (!Fwarn) {
+                (void)fprintf(stderr,
+                              "%s: WARNING: kernel name cache size: %d\n", Pn,
+                              Nc);
+                (void)fprintf(stderr, "      Cache size assumed to be: %d\n",
+                              DEFNCACHESZ);
+            }
+            iNc = Nc = DEFNCACHESZ;
+        }
+        /*
+         * Establish kernel cache address.
+         */
+        v = (KA_T)0;
+        if (get_Nl_value(X_NCACHE, (struct drive_Nl *)NULL, &v) < 0 || !v ||
+            kread(ctx, (KA_T)v, (char *)&kp, sizeof(kp))) {
+            if (!Fwarn)
+                (void)fprintf(
+                    stderr, "%s: WARNING: can't read name cache address: %s\n",
+                    Pn, print_kptr(v, (char *)NULL, 0));
+            iNc = Nc = 0;
+            return;
+        }
 
-/*
- * Read the kernel's name cache.
- */
-	if (kread(kp, (char *)kca, (Nc * sizeof(struct NCACHE)))) {
-	    if (!Fwarn)
-		(void) fprintf(stderr,
-		    "%s: WARNING: can't read kernel's name cache: %s\n",
-		    Pn, print_kptr(kp, (char *)NULL, 0));
-	    Nc = 0;
-	    return;
+#    if defined(NCACHE_NXT)
+        kf = kp;
+
+#    else  /* !defined(NCACHE_NXT) */
+        /*
+         * Allocate space for a local copy of the kernel's cache.
+         */
+        len = Nc * sizeof(struct NCACHE);
+        if (!(kca = (struct NCACHE *)malloc((MALLOC_S)len))) {
+            if (!Fwarn)
+                (void)fprintf(stderr,
+                              "%s: can't allocate name cache space: %d\n", Pn,
+                              len);
+            Error(ctx);
         }
-# endif /* !defined(NCACHE_NXT) */
+#    endif /* defined(NCACHE_NXT) */
 
-/*
- * Build a local copy of the kernel name cache.
- */
+        /*
+         * Allocate space for the local cache.
+         */
+        len = Nc * sizeof(struct l_nch);
+        if (!(Ncache = (struct l_nch *)malloc((MALLOC_S)len))) {
 
-# if	defined(NCACHE_NXT)
-	for (i = iNc * 16, kc = &nc, lc = Ncache, n = 0; kp; )
-# else	/* !defined(NCACHE_NXT) */
-	for (i = n = 0, kc = kca, lc = Ncache; i < Nc; i++, kc++)
-# endif	/* defined(NCACHE_NXT) */
-
-	{
-
-# if	defined(NCACHE_NXT)
-	    if (kread(kp, (char *)kc, sizeof(nc)))
-		break;
-	    if ((kp = (KA_T)kc->NCACHE_NXT) == kf)
-		kp = (KA_T)NULL;
-# endif	/* defined(NCACHE_NXT) */
-
-	    if (!kc->NCACHE_NODEADDR)
-		continue;
-	    if ((len = kc->NCACHE_NMLEN) < 1 || len > NCHNAMLEN)
-		continue;
-	    if (len < 3 && kc->NCACHE_NM[0] == '.') {
-		if (len == 1 || (len == 2 && kc->NCACHE_NM[1] == '.'))
-		    continue;
-	    }
-
-# if	defined(NCACHE_NXT)
-	    if (n >= Nc) {
-		Nc += LNCHINCRSZ;
-		if (!(Ncache = (struct l_nch *)realloc(Ncache,
-		     (MALLOC_S)(Nc * sizeof(struct l_nch)))))
-		{
-		    (void) fprintf(stderr,
-			"%s: no more space for %d entry local name cache\n",
-			Pn, Nc);
-		    Error();
-		}
-		lc = &Ncache[n];
-	    }
-# endif	/* defined(NCACHE_NXT) */
-
-#  if	defined(NCACHE_NODEID)
-	    lc->na = (KA_T)kc->NCACHE_NODEADDR;
-	    lc->id = kc->NCACHE_NODEID;
-#  endif	/* defined(NCACHE_NODEID) */
-
-#  if	defined(NCACHE_PARADDR)
-	    lc->pa = (KA_T)kc->NCACHE_PARADDR;
-	    lc->pla = (struct l_nch *)NULL;
-#  endif	/* defined(NCACHE_PARADDR) */
-
-#  if	defined(NCACHE_PARID)
-	    lc->did = kc->NCACHE_PARID;
-#  endif	/* defined(NCACHE_PARID) */
-
-	    (void) strncpy(lc->nm, kc->NCACHE_NM, len);
-	    lc->nm[len] = '\0';
-	    lc->nl = strlen(lc->nm);
-	    n++;
-	    lc++;
-
-# if	defined(NCACHE_NXT)
-	    if (n >= i) {
-		if (!Fwarn)
-		    (void) fprintf(stderr,
-			"%s: WARNING: name cache truncated at %d entries\n",
-			Pn, n);
-		break;
-	    }
-# endif	/* defined(NCACHE_NXT) */
-
-	}
-/*
- * Reduce memory usage, as required.
- */
+        no_local_space:
 
-# if	!defined(NCACHE_NXT)
-	if (!RptTm)
-	    (void) free((FREE_P *)kca);
-# endif	/* !defined(NCACHE_NXT) */
-
-	if (n < 1) {
-	    Nc = 0;
-	    if (!RptTm) {
-		(void) free((FREE_P *)Ncache);
-		Ncache = (struct l_nch *)NULL;
-	    }
-	    if (!Fwarn)
-		(void) fprintf(stderr,
-		    "%s: WARNING: unusable name cache size: %d\n", Pn, n);
-	    return;
-	}
-	if (n < Nc) {
-	    Nc = n;
-	    if (!RptTm) {
-		len = Nc * sizeof(struct l_nch);
-		if (!(Ncache = (struct l_nch *)realloc(Ncache, len)))
-		    goto no_local_space;
-	    }
-	}
-/*
- * Build a hash table to locate Ncache entries.
- */
-	for (Nch = 1; Nch < Nc; Nch <<= 1)
-	    ;
-	Nch <<= 1;
-	Mch = Nch - 1;
-	if (!(Nchash = (struct l_nch **)calloc(Nch+Nc, sizeof(struct l_nch *))))
-	{
-	    if (!Fwarn)
-		(void) fprintf(stderr,
-		    "%s: no space for %d name cache hash pointers\n",
-		    Pn, Nch + Nc);
-	    Error();
-	}
-	for (i = 0, lc = Ncache; i < Nc; i++, lc++) {
-
-# if	defined(NCACHE_NODEID)
-	    for (hp = ncachehash(lc->id, lc->na), n = 1; *hp; hp++)
-# else	/* defined(NCACHE_NODEID) */
-	    for (hp = ncachehash(lc->na), n = 1; *hp; hp++)
-# endif	/* defined(NCACHE_NODEID) */
-
-	    {
-
-# if	defined(NCACHE_NODEID)
-		if ((*hp)->na == lc->na && (*hp)->id == lc->id
-# else	/* defined(NCACHE_NODEID) */
-		if ((*hp)->na == lc->na
-# endif	/* defined(NCACHE_NODEID) */
-
-		&&  strcmp((*hp)->nm, lc->nm) == 0
-
-# if	defined(NCACHE_PARADDR) && defined(NCACHE_PARID)
-		&&  (*hp)->pa == lc->pa && (*hp)->did == lc->did
-# endif	/* defined(NCACHE_PARADDR) && defined(NCACHE_PARID) */
-
-		) {
-		    n = 0;
-		    break;
-		}
-	    }
-	    if (n)
-		*hp = lc;
-	}
-
-# if	defined(NCACHE_PARADDR) && defined(NCACHE_PARID)
-/*
- * Make a final pass through the local cache and convert parent node
- * addresses to local name cache pointers.
- */
-	for (i = 0, lc = Ncache; i < Nc; i++, lc++) {
-	    if (!lc->pa)
-		continue;
-	    lc->pla = ncache_addr(lc->did, lc->pa);
-	}
-# endif	/* defined(NCACHE_PARADDR) && defined(NCACHE_PARID) */
-}
+            if (!Fwarn)
+                (void)fprintf(stderr,
+                              "%s: no space for %d byte local name cache\n", Pn,
+                              len);
+            Error(ctx);
+        }
+    } else {
+
+        /*
+         * Do setup for repeat calls.
+         */
+        if ((Nc = iNc) == 0)
+            return;
+        if (Nchash) {
+            (void)free((FREE_P *)Nchash);
+            Nchash = (struct l_nch **)NULL;
+        }
 
+#    if defined(NCACHE_NXT)
+        kp = kf;
+#    endif /* defined(NCACHE_NXT) */
+    }
+
+#    if !defined(NCACHE_NXT)
+
+    /*
+     * Read the kernel's name cache.
+     */
+    if (kread(ctx, kp, (char *)kca, (Nc * sizeof(struct NCACHE)))) {
+        if (!Fwarn)
+            (void)fprintf(stderr,
+                          "%s: WARNING: can't read kernel's name cache: %s\n",
+                          Pn, print_kptr(kp, (char *)NULL, 0));
+        Nc = 0;
+        return;
+    }
+#    endif /* !defined(NCACHE_NXT) */
+
+    /*
+     * Build a local copy of the kernel name cache.
+     */
+
+#    if defined(NCACHE_NXT)
+    for (i = iNc * 16, kc = &nc, lc = Ncache, n = 0; kp;)
+#    else  /* !defined(NCACHE_NXT) */
+    for (i = n = 0, kc = kca, lc = Ncache; i < Nc; i++, kc++)
+#    endif /* defined(NCACHE_NXT) */
+
+    {
+
+#    if defined(NCACHE_NXT)
+        if (kread(ctx, kp, (char *)kc, sizeof(nc)))
+            break;
+        if ((kp = (KA_T)kc->NCACHE_NXT) == kf)
+            kp = (KA_T)NULL;
+#    endif /* defined(NCACHE_NXT) */
+
+        if (!kc->NCACHE_NODEADDR)
+            continue;
+        if ((len = kc->NCACHE_NMLEN) < 1 || len > NCHNAMLEN)
+            continue;
+        if (len < 3 && kc->NCACHE_NM[0] == '.') {
+            if (len == 1 || (len == 2 && kc->NCACHE_NM[1] == '.'))
+                continue;
+        }
+
+#    if defined(NCACHE_NXT)
+        if (n >= Nc) {
+            Nc += LNCHINCRSZ;
+            if (!(Ncache = (struct l_nch *)realloc(
+                      Ncache, (MALLOC_S)(Nc * sizeof(struct l_nch))))) {
+                (void)fprintf(
+                    stderr, "%s: no more space for %d entry local name cache\n",
+                    Pn, Nc);
+                Error(ctx);
+            }
+            lc = &Ncache[n];
+        }
+#    endif /* defined(NCACHE_NXT) */
+
+#    if defined(NCACHE_NODEID)
+        lc->na = (KA_T)kc->NCACHE_NODEADDR;
+        lc->id = kc->NCACHE_NODEID;
+#    endif /* defined(NCACHE_NODEID) */
+
+#    if defined(NCACHE_PARADDR)
+        lc->pa = (KA_T)kc->NCACHE_PARADDR;
+        lc->pla = (struct l_nch *)NULL;
+#    endif /* defined(NCACHE_PARADDR) */
+
+#    if defined(NCACHE_PARID)
+        lc->did = kc->NCACHE_PARID;
+#    endif /* defined(NCACHE_PARID) */
+
+        (void)strncpy(lc->nm, kc->NCACHE_NM, len);
+        lc->nm[len] = '\0';
+        lc->nl = strlen(lc->nm);
+        n++;
+        lc++;
+
+#    if defined(NCACHE_NXT)
+        if (n >= i) {
+            if (!Fwarn)
+                (void)fprintf(
+                    stderr, "%s: WARNING: name cache truncated at %d entries\n",
+                    Pn, n);
+            break;
+        }
+#    endif /* defined(NCACHE_NXT) */
+    }
+    /*
+     * Reduce memory usage, as required.
+     */
+
+#    if !defined(NCACHE_NXT)
+    if (!RptTm)
+        (void)free((FREE_P *)kca);
+#    endif /* !defined(NCACHE_NXT) */
+
+    if (n < 1) {
+        Nc = 0;
+        if (!RptTm) {
+            (void)free((FREE_P *)Ncache);
+            Ncache = (struct l_nch *)NULL;
+        }
+        if (!Fwarn)
+            (void)fprintf(stderr, "%s: WARNING: unusable name cache size: %d\n",
+                          Pn, n);
+        return;
+    }
+    if (n < Nc) {
+        Nc = n;
+        if (!RptTm) {
+            len = Nc * sizeof(struct l_nch);
+            if (!(Ncache = (struct l_nch *)realloc(Ncache, len)))
+                goto no_local_space;
+        }
+    }
+    /*
+     * Build a hash table to locate Ncache entries.
+     */
+    for (Nch = 1; Nch < Nc; Nch <<= 1)
+        ;
+    Nch <<= 1;
+    Mch = Nch - 1;
+    if (!(Nchash = (struct l_nch **)calloc(Nch + Nc, sizeof(struct l_nch *)))) {
+        if (!Fwarn)
+            (void)fprintf(stderr,
+                          "%s: no space for %d name cache hash pointers\n", Pn,
+                          Nch + Nc);
+        Error(ctx);
+    }
+    for (i = 0, lc = Ncache; i < Nc; i++, lc++) {
+
+#    if defined(NCACHE_NODEID)
+        for (hp = ncachehash(lc->id, lc->na), n = 1; *hp; hp++)
+#    else  /* defined(NCACHE_NODEID) */
+        for (hp = ncachehash(lc->na), n = 1; *hp; hp++)
+#    endif /* defined(NCACHE_NODEID) */
+
+        {
+
+#    if defined(NCACHE_NODEID)
+            if ((*hp)->na == lc->na && (*hp)->id == lc->id
+#    else  /* defined(NCACHE_NODEID) */
+            if ((*hp)->na == lc->na
+#    endif /* defined(NCACHE_NODEID) */
+
+                && strcmp((*hp)->nm, lc->nm) == 0
+
+#    if defined(NCACHE_PARADDR) && defined(NCACHE_PARID)
+                && (*hp)->pa == lc->pa && (*hp)->did == lc->did
+#    endif /* defined(NCACHE_PARADDR) && defined(NCACHE_PARID) */
+
+            ) {
+                n = 0;
+                break;
+            }
+        }
+        if (n)
+            *hp = lc;
+    }
+
+#    if defined(NCACHE_PARADDR) && defined(NCACHE_PARID)
+    /*
+     * Make a final pass through the local cache and convert parent node
+     * addresses to local name cache pointers.
+     */
+    for (i = 0, lc = Ncache; i < Nc; i++, lc++) {
+        if (!lc->pa)
+            continue;
+        lc->pla = ncache_addr(lc->did, lc->pa);
+    }
+#    endif /* defined(NCACHE_PARADDR) && defined(NCACHE_PARID) */
+}
 
 /*
  * 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 *ncache_lookup(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	defined(NCACHE_NODEID)
-	if (Nc == 0 || !(lc = ncache_addr(Lf->id, Lf->na)))
-# else	/* defined(NCACHE_NODEID) */
-	if (Nc == 0 || !(lc = ncache_addr(Lf->na)))
-# endif	/* defined(NCACHE_NODEID) */
-
-
-	{
-
-	/*
-	 * 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 = lc->nl) > (blen - 1))
-	    return((char *)NULL);
-	cp = buf + blen - nl - 1;
-	rlen = blen - nl - 1;
-	(void) strcpy(cp, lc->nm);
-
-# if	defined(NCACHE_PARADDR) && defined(NCACHE_PARID)
-/*
- * 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 (!lc->pla) {
-
-#  if	!defined(NCACHE_NO_ROOT)
-		if (ncache_isroot(lc->pa, cp))
-		    *fp = 1;
-#  endif	/* !defined(NCACHE_NO_ROOT) */
-
-		break;
-	    }
-	    lc = lc->pla;
-	    if (((nl = lc->nl) + 1) > rlen)
-		break;
-	    *(cp - 1) = '/';
-	    cp--;
-	    rlen--;
-	    (void) strncpy((cp - nl), lc->nm, nl);
-	    cp -= nl;
-	    rlen -= nl;
-	}
-# endif	/* defined(NCACHE_PARADDR) && defined(NCACHE_PARID) */
-	return(cp);
+    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 defined(NCACHE_NODEID)
+    if (Nc == 0 || !(lc = ncache_addr(Lf->id, Lf->na)))
+#    else  /* defined(NCACHE_NODEID) */
+    if (Nc == 0 || !(lc = ncache_addr(Lf->na)))
+#    endif /* defined(NCACHE_NODEID) */
+
+    {
+
+        /*
+         * 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 = lc->nl) > (blen - 1))
+        return ((char *)NULL);
+    cp = buf + blen - nl - 1;
+    rlen = blen - nl - 1;
+    (void)strcpy(cp, lc->nm);
+
+#    if defined(NCACHE_PARADDR) && defined(NCACHE_PARID)
+    /*
+     * 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 (!lc->pla) {
+
+#        if !defined(NCACHE_NO_ROOT)
+            if (ncache_isroot(lc->pa, cp))
+                *fp = 1;
+#        endif /* !defined(NCACHE_NO_ROOT) */
+
+            break;
+        }
+        lc = lc->pla;
+        if (((nl = lc->nl) + 1) > rlen)
+            break;
+        *(cp - 1) = '/';
+        cp--;
+        rlen--;
+        (void)strncpy((cp - nl), lc->nm, nl);
+        cp -= nl;
+        rlen -= nl;
+    }
+#    endif /* defined(NCACHE_PARADDR) && defined(NCACHE_PARID) */
+    return (cp);
 }
-#else	/* !defined(HASNCACHE) || !defined(USE_LIB_RNAM) */
-char rnam_d1[] = "d"; char *rnam_d2 = rnam_d1;
-#endif	/* defined(HASNCACHE) && defined(USE_LIB_RNAM) */
+#else  /* !defined(HASNCACHE) || !defined(USE_LIB_RNAM) */
+char rnam_d1[] = "d";
+char *rnam_d2 = rnam_d1;
+#endif /* defined(HASNCACHE) && defined(USE_LIB_RNAM) */
diff --git a/lib/rnch.c b/lib/rnch.c
index 3c64309..bca84db 100644
--- a/lib/rnch.c
+++ b/lib/rnch.c
@@ -2,7 +2,6 @@
  * rnch.c -- Sun format name cache functions for lsof library
  */
 
-
 /*
  * Copyright 1997 Purdue Research Foundation, West Lafayette, Indiana
  * 47907.  All rights reserved.
@@ -29,18 +28,10 @@
  * 4. This notice may not be removed or altered.
  */
 
+#include "common.h"
+#include "machine.h"
 
-#include "../machine.h"
-
-#if	defined(HASNCACHE) && defined(USE_LIB_RNCH)
-
-# if	!defined(lint)
-static char copyright[] =
-"@(#) Copyright 1997 Purdue Research Foundation.\nAll rights reserved.\n";
-# endif	/* !defined(lint) */
-
-#include "../lsof.h"
-
+#if defined(HASNCACHE) && defined(USE_LIB_RNCH)
 
 /*
  * rnch.c - read Sun format (struct ncache) name cache
@@ -86,7 +77,7 @@ static char copyright[] =
  *				ncache structure that contains the
  *				name length.
  *
- *				Deafult: namlen
+ *				Default: namlen
  *
  *	Define NCACHE_NEGVN	as the name of the name list element
  *				whose value is a vnode address to
@@ -117,694 +108,670 @@ static char copyright[] =
  *		_PROTOTYPE(void ncache_load,(void));
  */
 
-
 /*
  * Local static values
  */
 
-static int Mch;				/* name cache hash mask */
+static int Mch; /* name cache hash mask */
 
-# if	!defined(NCACHE_NC_CAST)
-#define	NCACHE_SZ_CAST	int
-# endif	/* !defined(NCACHE_NC_CAST) */
+#    if !defined(NCACHE_NC_CAST)
+#        define NCACHE_SZ_CAST int
+#    endif /* !defined(NCACHE_NC_CAST) */
 
-static NCACHE_SZ_CAST Nc = 0;		/* size of name cache */
-static int Nch = 0;			/* size of name cache hash pointer
-					 * table */
+static NCACHE_SZ_CAST Nc = 0; /* size of name cache */
+static int Nch = 0;           /* size of 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 */
+    KA_T vp;          /* vnode address */
+    KA_T dp;          /* parent vnode address */
+    struct l_nch *pa; /* parent Ncache address */
 
-# if	defined(NCACHE_NODEID)
-	unsigned long id;		/* node's capability ID */
-	unsigned long did;		/* parent node's capability ID */
-# endif	/* defined(NCACHE_NODEID) */
+#    if defined(NCACHE_NODEID)
+    unsigned long id;  /* node's capability ID */
+    unsigned long did; /* parent node's capability ID */
+#    endif             /* defined(NCACHE_NODEID) */
 
-	char *nm;			/* name */
-	int nl;				/* name length */
+    char *nm; /* name */
+    int nl;   /* name length */
 };
 
 static struct l_nch *Ncache = (struct l_nch *)NULL;
-					/* the local name cache */
+/* the local name cache */
 static struct l_nch **Nchash = (struct l_nch **)NULL;
-					/* Ncache hash pointers */
-static int Ncfirst = 1;			/* first-call status */
+/* Ncache hash pointers */
+static int Ncfirst = 1; /* first-call status */
 
-# if 	defined(NCACHE_NEGVN)
-static KA_T NegVN = (KA_T)NULL;		/* negative vnode address */
-static int NegVNSt = 0;			/* NegVN status: 0 = not loaded */
-# endif	/* defined(NCACHE_NEGVN) */
+#    if defined(NCACHE_NEGVN)
+static KA_T NegVN = (KA_T)NULL; /* negative vnode address */
+static int NegVNSt = 0;         /* NegVN status: 0 = not loaded */
+#    endif                      /* defined(NCACHE_NEGVN) */
 
-# if	defined(NCACHE_NODEID)
-_PROTOTYPE(static struct l_nch *ncache_addr,(unsigned long i, KA_T v));
-#define ncachehash(i,v)		Nchash+(((((int)(v)>>2)+((int)(i)))*31415)&Mch)
-# else	/* !defined(NCACHE_NODEID) */
-_PROTOTYPE(static struct l_nch *ncache_addr,(KA_T v));
-#define ncachehash(v)		Nchash+((((int)(v)>>2)*31415)&Mch)
-# endif	/* defined(NCACHE_NODEID) */
+#    if defined(NCACHE_NODEID)
+static struct l_nch *ncache_addr(unsigned long i, KA_T v);
+#        define ncachehash(i, v)                                               \
+            Nchash + (((((int)(v) >> 2) + ((int)(i))) * 31415) & Mch)
+#    else /* !defined(NCACHE_NODEID) */
+static struct l_nch *ncache_addr(KA_T v);
+#        define ncachehash(v) Nchash + ((((int)(v) >> 2) * 31415) & Mch)
+#    endif /* defined(NCACHE_NODEID) */
 
-_PROTOTYPE(static int ncache_isroot,(KA_T va, char *cp));
+static int ncache_isroot(KA_T va, char *cp);
 
-#define DEFNCACHESZ	1024	/* local size if X_NCSIZE kernel value < 1 */
-#define	LNCHINCRSZ	64	/* local size increment */
+#    define DEFNCACHESZ 1024 /* local size if X_NCSIZE kernel value < 1 */
+#    define LNCHINCRSZ 64    /* local size increment */
 
-# if	!defined(NCACHE_DP)
-#define	NCACHE_DP	dp
-# endif	/* !defined(NCACHE_DP) */
+#    if !defined(NCACHE_DP)
+#        define NCACHE_DP dp
+#    endif /* !defined(NCACHE_DP) */
 
-# if	!defined(NCACHE_NAME)
-#define	NCACHE_NAME	name
-# endif	/* !defined(NCACHE_NAME) */
+#    if !defined(NCACHE_NAME)
+#        define NCACHE_NAME name
+#    endif /* !defined(NCACHE_NAME) */
 
-# if	!defined(NCACHE_NAMLEN)
-#define	NCACHE_NAMLEN	namlen
-# endif	/* !defined(NCACHE_NAMLEN) */
-
-# if	!defined(NCACHE_VP)
-#define	NCACHE_VP	vp
-# endif	/* !defined(NCACHE_VP) */
+#    if !defined(NCACHE_NAMLEN)
+#        define NCACHE_NAMLEN namlen
+#    endif /* !defined(NCACHE_NAMLEN) */
 
+#    if !defined(NCACHE_VP)
+#        define NCACHE_VP vp
+#    endif /* !defined(NCACHE_VP) */
 
 /*
  * ncache_addr() - look up a node's local ncache address
  */
 
-static struct l_nch *
-
-# if	defined(NCACHE_NODEID)
-ncache_addr(i, v)
-# else	/* !defined(NCACHE_NODEID) */
-ncache_addr(v)
-# endif	/* defined(NCACHE_NODEID) */
-
-# if	defined(NCACHE_NODEID)
-	unsigned long i;			/* capability ID */
-# endif	/* defined(NCACHE_NODEID) */
-
-	KA_T v;					/* vnode's address */
+static struct l_nch *ncache_addr(
+#    if defined(NCACHE_NODEID)
+    unsigned long i, /* capability ID */
+#    endif           /* defined(NCACHE_NODEID) */
+    KA_T v)          /* vnode's address */
 {
-	struct l_nch **hp;
+    struct l_nch **hp;
 
-# if	defined(NCACHE_NODEID)
-	for (hp = ncachehash(i, v); *hp; hp++)
-# else	/* !defined(NCACHE_NODEID) */
-	for (hp = ncachehash(v); *hp; hp++)
-# endif	/* defined(NCACHE_NODEID) */
+#    if defined(NCACHE_NODEID)
+    for (hp = ncachehash(i, v); *hp; hp++)
+#    else  /* !defined(NCACHE_NODEID) */
+    for (hp = ncachehash(v); *hp; hp++)
+#    endif /* defined(NCACHE_NODEID) */
 
-	{
+    {
 
-# if	defined(NCACHE_NODEID)
-	    if ((*hp)->vp == v && (*hp)->id == i)
-# else	/* !defined(NCACHE_NODEID) */
-	    if ((*hp)->vp == v)
-# endif	/* defined(NCACHE_NODEID) */
+#    if defined(NCACHE_NODEID)
+        if ((*hp)->vp == v && (*hp)->id == i)
+#    else  /* !defined(NCACHE_NODEID) */
+        if ((*hp)->vp == v)
+#    endif /* defined(NCACHE_NODEID) */
 
-		return(*hp);
-	}
-	return((struct l_nch *)NULL);
+            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 */
+static int ncache_isroot(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
-	    ||  (unsigned long)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);
-		Error();
-	    }
-	}
-	vc[vcn++] = va;
-	return(1);
+    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 its inode number
+     * matches the one we have for this file.  If it does, then the path is
+     * complete.
+     */
+    if (kread(ctx, (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 || (unsigned long)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);
+            Error(ctx);
+        }
+    }
+    vc[vcn++] = va;
+    return (1);
 }
 
-
 /*
  * ncache_load() - load the kernel's name cache
  */
 
-void
-ncache_load()
-{
-	char *cp, *np;
-	struct l_nch **hp, *lc;
-	int i, len, n;
-	static int iNc = 0;
-	struct ncache *kc;
-	static KA_T kp = (KA_T)NULL;
-	KA_T v;
-
-# if	defined(HASDNLCPTR)
-	static int na = 0;
-	static char *nb = (char *)NULL;
-# endif	/* defined(HASDNLCPTR) */
-
-# if	defined(NCACHE_NXT)
-	static KA_T kf;
-	struct ncache nc;
-# else	/* !defined(NCACHE_NXT) */
-	static struct ncache *kca = (struct ncache *)NULL;
-# endif	/* defined(NCACHE_NXT) */
-
-	if (!Fncache)
-	    return;
-	if (Ncfirst) {
-
-	/*
-	 * Do startup (first-time) functions.
-	 */
-	    Ncfirst = 0;
-	/*
-	 * Establish kernel cache size.
-	 */
-
-# if	defined(X_NCSIZE)
-	    v = (KA_T)0;
-	    if (get_Nl_value(X_NCSIZE, (struct drive_Nl *)NULL, &v) < 0
-	    ||  !v
-	    ||  kread((KA_T)v, (char *)&Nc, sizeof(Nc)))
-	    {
-		if (!Fwarn)
-		(void) fprintf(stderr,
-		    "%s: WARNING: can't read name cache size: %s\n",
-			Pn, print_kptr(v, (char *)NULL, 0));
-		iNc = Nc = 0;
-		return;
-	    }
-	    iNc = Nc;
-# else	/* !defined(X_NCSIZE) */
-	    iNc = Nc = FIXED_NCSIZE;
-# endif	/* defined(X_NCSIZE) */
-
-	    if (Nc < 1) {
-		if (!Fwarn) {
-		    (void) fprintf(stderr,
-			"%s: WARNING: kernel name cache size: %d\n", Pn, Nc);
-		    (void) fprintf(stderr,
-			"      Cache size assumed to be: %d\n", DEFNCACHESZ);
-		}
-		iNc = Nc = DEFNCACHESZ;
-	    }
-
-# if	defined(NCACHE_NEGVN)
-	/*
-	 * Get negative vnode address.
-	 */
-	    if (!NegVNSt) {
-		if (get_Nl_value(NCACHE_NEGVN, (struct drive_Nl *)NULL, &NegVN)
-		< 0)
-		    NegVN = (KA_T)NULL;
-		NegVNSt = 1;
-	    }
-# endif	/* defined(NCACHE_NEGVN) */
-
-	/*
-	 * Establish kernel cache address.
-	 */
-
-# if	defined(ADDR_NCACHE)
-	    kp = (KA_T)0;
-	    if (get_Nl_value(X_NCACHE,(struct drive_Nl *)NULL,(KA_T *)&kp) < 0
-	    || !kp) {
-		if (!Fwarn)
-		    (void) fprintf(stderr,
-			"%s: WARNING: no name cache address\n", Pn);
-		iNc = Nc = 0;
-		return;
-	    }
-# else	/* !defined(ADDR_NCACHE) */
-	    v = (KA_T)0;
-	    if (get_Nl_value(X_NCACHE, (struct drive_Nl *)NULL, &v) < 0
-	    || !v
-	    ||  kread((KA_T)v, (char *)&kp, sizeof(kp))) {
-		if (!Fwarn)
-		    (void) fprintf(stderr,
-			"%s: WARNING: can't read name cache ptr: %s\n",
-			Pn, print_kptr(v, (char *)NULL, 0));
-		iNc = Nc = 0;
-		return;
-	    }
-# endif	/* defined(ADDR_NCACHE) */
-
-	/*
-	 * Allocate space for a local copy of the kernel's cache.
-	 */
-
-# if	!defined(NCACHE_NXT)
-	    len = Nc * sizeof(struct ncache);
-	    if (!(kca = (struct ncache *)malloc((MALLOC_S)len))) {
-		if (!Fwarn)
-		    (void) fprintf(stderr,
-			"%s: can't allocate name cache space: %d\n", Pn, len);
-		Error();
-	    }
-# endif	/* !defined(NCACHE_NXT) */
-
-	/*
-	 * Allocate space for the local cache.
-	 */
-	    len = Nc * sizeof(struct l_nch);
-	    if (!(Ncache = (struct l_nch *)calloc(Nc, sizeof(struct l_nch)))) {
-
-no_local_space:
-
-		if (!Fwarn)
-		    (void) fprintf(stderr,
-		      "%s: no space for %d byte local name cache\n", Pn, len);
-		Error();
-	    }
-	} else {
-
-	/*
-	 * Do setup for repeat calls.
-	 */
-	    if (!iNc)
-		return;
-	    if (Nchash) {
-		(void) free((FREE_P *)Nchash);
-		Nchash = (struct l_nch **)NULL;
-	    }
-	    if (Ncache) {
-
-	    /*
-	     * Free space malloc'd to names in local name cache.
-	     */
-	        for (i = 0, lc = Ncache; i < Nc; i++, lc++) {
-		    if (lc->nm) {
-			(void) free((FREE_P *)lc->nm);
-			lc->nm = (char *)NULL;
-		    }
-	        }
-	    }
-	    Nc = iNc;
-
-# if	defined(NCACHE_NXT)
-	    kp = kf;
-# endif	/* defined(NCACHE_NXT) */
-
-	}
-
-# if	!defined(NCACHE_NXT)
-
-/*
- * Read the kernel's name cache.
- */
-	if (kread(kp, (char *)kca, (Nc * sizeof(struct ncache)))) {
-	    if (!Fwarn)
-		(void) fprintf(stderr,
-		    "%s: WARNING: can't read kernel's name cache: %s\n",
-		    Pn, print_kptr(kp, (char *)NULL, 0));
-	    Nc = 0;
-	    return;
-	}
-# endif	/* !defined(NCACHE_NXT) */
-
-/*
- * Build a local copy of the kernel name cache.
- */
-
-# if	defined(NCACHE_NXT)
-	for (i = iNc * 16, kc = &nc, kf = kp, lc = Ncache, n = 0; kp; )
-# else	/* !defined(NCACHE_NXT) */
-	for (i = n = 0, kc = kca, lc = Ncache; i < Nc; i++, kc++)
-# endif	/* defined(NCACHE_NXT) */
-
-	{
-
-# if	defined(NCACHE_NXT)
-	    if (kread(kp, (char *)kc, sizeof(nc)))
-		break;
-	    if ((kp = (KA_T)kc->NCACHE_NXT) == kf)
-		kp = (KA_T)NULL;
-# endif	/* defined(NCACHE_NXT) */
-
-	    if (!kc->NCACHE_VP || (len = kc->NCACHE_NAMLEN) < 1)
-		continue;
-
-# if	defined(NCACHE_NEGVN)
-	    if (NegVN && ((KA_T)kc->NCACHE_VP == NegVN))
-		continue;
-# endif	/* defined(NCACHE_NEGVN) */
-
-# if	defined(HASDNLCPTR)
-	/*
-	 * Read name from kernel to a temporary buffer.
-	 */
-	    if (len > na) {
-		na = len;
-		if (!nb)
-		    nb = (char *)malloc(na);
-		else
-		    nb = (char *)realloc((MALLOC_P *)nb, na);
-		if (!nb) {
-		    (void) fprintf(stderr,
-			"%s: can't allocate %d byte temporary name buffer\n",
-			Pn, na);
-		    Error();
-		}
-	    }
-	    if (!kc->NCACHE_NAME || kread((KA_T)kc->NCACHE_NAME, nb, len))
-		continue;
-	    np = nb;
-# else	/* !defined(HASDNLCPTR) */
-	/*
-	 * Use name that is in the kernel cache entry.
-	 */
-	    if (len > NC_NAMLEN)
-		continue;
-	    np = kc->NCACHE_NAME;
-# endif	/* defined(HASDNLCPTR) */
-
-	    if (len < 3 && *np == '.') {
-		if (len == 1 || (len == 2 && np[1] == '.'))
-		    continue;
-	    }
-	/*
-	 * Allocate space for name in local cache entry.
-	 */
-	    if (!(cp = (char *)malloc(len + 1))) {
-		(void) fprintf(stderr,
-		    "%s: can't allocate %d bytes for name cache name: %s\n",
-		    Pn, len + 1, np);
-		Error();
-	    }
-	    (void) strncpy(cp, np, len);
-	    cp[len] = '\0';
-
-# if	defined(NCACHE_NXT)
-	    if (n >= Nc) {
-
-	    /*
-	     * Allocate more local space to receive the kernel's linked
-	     * entries.
-	     */
-		Nc += LNCHINCRSZ;
-		if (!(Ncache = (struct l_nch *)realloc(Ncache,
-		     (MALLOC_S)(Nc * sizeof(struct l_nch)))))
-		{
-		    (void) fprintf(stderr,
-			"%s: no more space for %d entry local name cache\n",
-			Pn, Nc);
-		    Error();
-		}
-		lc = &Ncache[n];
-		iNc = Nc;
-	    }
-# endif	/* defined(NCACHE_NXT) */
-
-	/*
-	 * Complete the local cache entry.
-	 */
-	    lc->vp = (KA_T)kc->NCACHE_VP;
-	    lc->dp = (KA_T)kc->NCACHE_DP;
-	    lc->pa = (struct l_nch *)NULL;
-	    lc->nm = cp;
-	    lc->nl = len;
-
-# if	defined(NCACHE_NODEID)
-	    lc->id = (unsigned long)kc->NCACHE_NODEID;
-	    lc->did = (unsigned long)kc->NCACHE_PARID;
-# endif	/* defined(NCACHE_NODEID) */
-
-	    n++;
-	    lc++;
-
-# if	defined(NCACHE_NXT)
-	    if (n >= i) {
-		if (!Fwarn)
-		    (void) fprintf(stderr,
-			"%s: WARNING: name cache truncated at %d entries\n",
-			Pn, n);
-		break;
-	    }
-# endif	/* defined(NCACHE_NXT) */
-
-	}
-/*
- * Reduce memory usage, as required.
- */
-
-# if	!defined(NCACHE_NXT)
-	if (!RptTm)
-	    (void) free((FREE_P *)kca);
-# endif	/* !defined(NCACHE_NXT) */
-
-	if (n < 1) {
-	    if (!RptTm && Ncache) {
-
-	    /*
-	     * If not in repeat mode, free the space that has been malloc'd
-	     * to the local name cache.
-	     */
-		for (i = 0, lc = Ncache; i < Nc; i++, lc++) {
-		    if (lc->nm) {
-			(void) free((FREE_P *)lc->nm);
-			lc->nm = (char *)NULL;
-		    }
-		}
-		(void) free((FREE_P *)Ncache);
-	 	Ncache = (struct l_nch *)NULL;
-		Nc = 0;
-	    }
-	    if (!Fwarn)
-		(void) fprintf(stderr,
-		    "%s: WARNING: unusable name cache size: %d\n", Pn, n);
-	    return;
-	}
-	if (n < Nc) {
-	    Nc = n;
-	    if (!RptTm) {
-		len = Nc * sizeof(struct l_nch);
-		if (!(Ncache = (struct l_nch *)realloc(Ncache, len)))
-		    goto no_local_space;
-	    }
-	}
-/*
- * Build a hash table to locate Ncache entries.
- */
-	for (Nch = 1; Nch < Nc; Nch <<= 1)
-	    ;
-	Nch <<= 1;
-	Mch = Nch - 1;
-	if (!(Nchash = (struct l_nch **)calloc(Nch+Nc, sizeof(struct l_nch *))))
-	{
-	    if (!Fwarn)
-		(void) fprintf(stderr,
-		    "%s: no space for %d name cache hash pointers\n",
-		    Pn, Nch + Nc);
-	    Error();
-	}
-	for (i = 0, lc = Ncache; i < Nc; i++, lc++) {
-
-# if	defined(NCACHE_NODEID)
-	    for (hp = ncachehash(lc->id, lc->vp), n = 1; *hp; hp++)
-# else	/* !defined(NCACHE_NODEID) */
-	    for (hp = ncachehash(lc->vp), n = 1; *hp; hp++)
-# endif	/* defined(NCACHE_NODEID) */
-
-	    {
-		if ((*hp)->vp == lc->vp && strcmp((*hp)->nm, lc->nm) == 0
-		&&  (*hp)->dp == lc->dp
-
-# if	defined(NCACHE_NODEID)
-		&&  (*hp)->id == lc->id && (*hp)->did == lc->did
-# endif	/* defined(NCACHE_NODEID) */
-
-		) {
-		    n = 0;
-		    break;
-		}
-	    }
-	    if (n)
-		*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 < Nc; i++, lc++) {
-	    if (!lc->dp)
-		continue;
-
-# if	defined(NCACHE_NEGVN)
-	     if (NegVN && (lc->dp == NegVN)) {
-		lc->pa = (struct l_nch *)NULL;
-		continue;
-	     }
-# endif	/* defined(NCACHE_NEGVN) */
-
-# if	defined(NCACHE_NODEID)
-	    lc->pa = ncache_addr(lc->did, lc->dp);
-# else	/* !defined(NCACHE_NODEID) */
-	    lc->pa = ncache_addr(lc->dp);
-# endif	/* defined(NCACHE_NODEID) */
-
-	}
+void ncache_load(struct lsof_context *ctx) {
+    char *cp, *np;
+    struct l_nch **hp, *lc;
+    int i, len, n;
+    static int iNc = 0;
+    struct ncache *kc;
+    static KA_T kp = (KA_T)NULL;
+    KA_T v;
+
+#    if defined(HASDNLCPTR)
+    static int na = 0;
+    static char *nb = (char *)NULL;
+#    endif /* defined(HASDNLCPTR) */
+
+#    if defined(NCACHE_NXT)
+    static KA_T kf;
+    struct ncache nc;
+#    else  /* !defined(NCACHE_NXT) */
+    static struct ncache *kca = (struct ncache *)NULL;
+#    endif /* defined(NCACHE_NXT) */
+
+    if (!Fncache)
+        return;
+    if (Ncfirst) {
+
+        /*
+         * Do startup (first-time) functions.
+         */
+        Ncfirst = 0;
+        /*
+         * Establish kernel cache size.
+         */
+
+#    if defined(X_NCSIZE)
+        v = (KA_T)0;
+        if (get_Nl_value(X_NCSIZE, (struct drive_Nl *)NULL, &v) < 0 || !v ||
+            kread(ctx, (KA_T)v, (char *)&Nc, sizeof(Nc))) {
+            if (!Fwarn)
+                (void)fprintf(stderr,
+                              "%s: WARNING: can't read name cache size: %s\n",
+                              Pn, print_kptr(v, (char *)NULL, 0));
+            iNc = Nc = 0;
+            return;
+        }
+        iNc = Nc;
+#    else  /* !defined(X_NCSIZE) */
+        iNc = Nc = FIXED_NCSIZE;
+#    endif /* defined(X_NCSIZE) */
+
+        if (Nc < 1) {
+            if (!Fwarn) {
+                (void)fprintf(stderr,
+                              "%s: WARNING: kernel name cache size: %d\n", Pn,
+                              Nc);
+                (void)fprintf(stderr, "      Cache size assumed to be: %d\n",
+                              DEFNCACHESZ);
+            }
+            iNc = Nc = DEFNCACHESZ;
+        }
+
+#    if defined(NCACHE_NEGVN)
+        /*
+         * Get negative vnode address.
+         */
+        if (!NegVNSt) {
+            if (get_Nl_value(NCACHE_NEGVN, (struct drive_Nl *)NULL, &NegVN) < 0)
+                NegVN = (KA_T)NULL;
+            NegVNSt = 1;
+        }
+#    endif /* defined(NCACHE_NEGVN) */
+
+        /*
+         * Establish kernel cache address.
+         */
+
+#    if defined(ADDR_NCACHE)
+        kp = (KA_T)0;
+        if (get_Nl_value(X_NCACHE, (struct drive_Nl *)NULL, (KA_T *)&kp) < 0 ||
+            !kp) {
+            if (!Fwarn)
+                (void)fprintf(stderr, "%s: WARNING: no name cache address\n",
+                              Pn);
+            iNc = Nc = 0;
+            return;
+        }
+#    else  /* !defined(ADDR_NCACHE) */
+        v = (KA_T)0;
+        if (get_Nl_value(X_NCACHE, (struct drive_Nl *)NULL, &v) < 0 || !v ||
+            kread(ctx, (KA_T)v, (char *)&kp, sizeof(kp))) {
+            if (!Fwarn)
+                (void)fprintf(stderr,
+                              "%s: WARNING: can't read name cache ptr: %s\n",
+                              Pn, print_kptr(v, (char *)NULL, 0));
+            iNc = Nc = 0;
+            return;
+        }
+#    endif /* defined(ADDR_NCACHE) */
+
+        /*
+         * Allocate space for a local copy of the kernel's cache.
+         */
+
+#    if !defined(NCACHE_NXT)
+        len = Nc * sizeof(struct ncache);
+        if (!(kca = (struct ncache *)malloc((MALLOC_S)len))) {
+            if (!Fwarn)
+                (void)fprintf(stderr,
+                              "%s: can't allocate name cache space: %d\n", Pn,
+                              len);
+            Error(ctx);
+        }
+#    endif /* !defined(NCACHE_NXT) */
+
+        /*
+         * Allocate space for the local cache.
+         */
+        len = Nc * sizeof(struct l_nch);
+        if (!(Ncache = (struct l_nch *)calloc(Nc, sizeof(struct l_nch)))) {
+
+        no_local_space:
+
+            if (!Fwarn)
+                (void)fprintf(stderr,
+                              "%s: no space for %d byte local name cache\n", Pn,
+                              len);
+            Error(ctx);
+        }
+    } else {
+
+        /*
+         * Do setup for repeat calls.
+         */
+        if (!iNc)
+            return;
+        if (Nchash) {
+            (void)free((FREE_P *)Nchash);
+            Nchash = (struct l_nch **)NULL;
+        }
+        if (Ncache) {
+
+            /*
+             * Free space malloc'd to names in local name cache.
+             */
+            for (i = 0, lc = Ncache; i < Nc; i++, lc++) {
+                if (lc->nm) {
+                    (void)free((FREE_P *)lc->nm);
+                    lc->nm = (char *)NULL;
+                }
+            }
+        }
+        Nc = iNc;
+
+#    if defined(NCACHE_NXT)
+        kp = kf;
+#    endif /* defined(NCACHE_NXT) */
+    }
+
+#    if !defined(NCACHE_NXT)
+
+    /*
+     * Read the kernel's name cache.
+     */
+    if (kread(ctx, kp, (char *)kca, (Nc * sizeof(struct ncache)))) {
+        if (!Fwarn)
+            (void)fprintf(stderr,
+                          "%s: WARNING: can't read kernel's name cache: %s\n",
+                          Pn, print_kptr(kp, (char *)NULL, 0));
+        Nc = 0;
+        return;
+    }
+#    endif /* !defined(NCACHE_NXT) */
+
+    /*
+     * Build a local copy of the kernel name cache.
+     */
+
+#    if defined(NCACHE_NXT)
+    for (i = iNc * 16, kc = &nc, kf = kp, lc = Ncache, n = 0; kp;)
+#    else  /* !defined(NCACHE_NXT) */
+    for (i = n = 0, kc = kca, lc = Ncache; i < Nc; i++, kc++)
+#    endif /* defined(NCACHE_NXT) */
+
+    {
+
+#    if defined(NCACHE_NXT)
+        if (kread(ctx, kp, (char *)kc, sizeof(nc)))
+            break;
+        if ((kp = (KA_T)kc->NCACHE_NXT) == kf)
+            kp = (KA_T)NULL;
+#    endif /* defined(NCACHE_NXT) */
+
+        if (!kc->NCACHE_VP || (len = kc->NCACHE_NAMLEN) < 1)
+            continue;
+
+#    if defined(NCACHE_NEGVN)
+        if (NegVN && ((KA_T)kc->NCACHE_VP == NegVN))
+            continue;
+#    endif /* defined(NCACHE_NEGVN) */
+
+#    if defined(HASDNLCPTR)
+        /*
+         * Read name from kernel to a temporary buffer.
+         */
+        if (len > na) {
+            na = len;
+            if (!nb)
+                nb = (char *)malloc(na);
+            else
+                nb = (char *)realloc((MALLOC_P *)nb, na);
+            if (!nb) {
+                (void)fprintf(
+                    stderr,
+                    "%s: can't allocate %d byte temporary name buffer\n", Pn,
+                    na);
+                Error(ctx);
+            }
+        }
+        if (!kc->NCACHE_NAME || kread(ctx, (KA_T)kc->NCACHE_NAME, nb, len))
+            continue;
+        np = nb;
+#    else  /* !defined(HASDNLCPTR) */
+        /*
+         * Use name that is in the kernel cache entry.
+         */
+        if (len > NC_NAMLEN)
+            continue;
+        np = kc->NCACHE_NAME;
+#    endif /* defined(HASDNLCPTR) */
+
+        if (len < 3 && *np == '.') {
+            if (len == 1 || (len == 2 && np[1] == '.'))
+                continue;
+        }
+        /*
+         * Allocate space for name in local cache entry.
+         */
+        if (!(cp = (char *)malloc(len + 1))) {
+            (void)fprintf(
+                stderr, "%s: can't allocate %d bytes for name cache name: %s\n",
+                Pn, len + 1, np);
+            Error(ctx);
+        }
+        (void)strncpy(cp, np, len);
+        cp[len] = '\0';
+
+#    if defined(NCACHE_NXT)
+        if (n >= Nc) {
+
+            /*
+             * Allocate more local space to receive the kernel's linked
+             * entries.
+             */
+            Nc += LNCHINCRSZ;
+            if (!(Ncache = (struct l_nch *)realloc(
+                      Ncache, (MALLOC_S)(Nc * sizeof(struct l_nch))))) {
+                (void)fprintf(
+                    stderr, "%s: no more space for %d entry local name cache\n",
+                    Pn, Nc);
+                Error(ctx);
+            }
+            lc = &Ncache[n];
+            iNc = Nc;
+        }
+#    endif /* defined(NCACHE_NXT) */
+
+        /*
+         * Complete the local cache entry.
+         */
+        lc->vp = (KA_T)kc->NCACHE_VP;
+        lc->dp = (KA_T)kc->NCACHE_DP;
+        lc->pa = (struct l_nch *)NULL;
+        lc->nm = cp;
+        lc->nl = len;
+
+#    if defined(NCACHE_NODEID)
+        lc->id = (unsigned long)kc->NCACHE_NODEID;
+        lc->did = (unsigned long)kc->NCACHE_PARID;
+#    endif /* defined(NCACHE_NODEID) */
+
+        n++;
+        lc++;
+
+#    if defined(NCACHE_NXT)
+        if (n >= i) {
+            if (!Fwarn)
+                (void)fprintf(
+                    stderr, "%s: WARNING: name cache truncated at %d entries\n",
+                    Pn, n);
+            break;
+        }
+#    endif /* defined(NCACHE_NXT) */
+    }
+    /*
+     * Reduce memory usage, as required.
+     */
+
+#    if !defined(NCACHE_NXT)
+    if (!RptTm)
+        (void)free((FREE_P *)kca);
+#    endif /* !defined(NCACHE_NXT) */
+
+    if (n < 1) {
+        if (!RptTm && Ncache) {
+
+            /*
+             * If not in repeat mode, free the space that has been malloc'd
+             * to the local name cache.
+             */
+            for (i = 0, lc = Ncache; i < Nc; i++, lc++) {
+                if (lc->nm) {
+                    (void)free((FREE_P *)lc->nm);
+                    lc->nm = (char *)NULL;
+                }
+            }
+            (void)free((FREE_P *)Ncache);
+            Ncache = (struct l_nch *)NULL;
+            Nc = 0;
+        }
+        if (!Fwarn)
+            (void)fprintf(stderr, "%s: WARNING: unusable name cache size: %d\n",
+                          Pn, n);
+        return;
+    }
+    if (n < Nc) {
+        Nc = n;
+        if (!RptTm) {
+            len = Nc * sizeof(struct l_nch);
+            if (!(Ncache = (struct l_nch *)realloc(Ncache, len)))
+                goto no_local_space;
+        }
+    }
+    /*
+     * Build a hash table to locate Ncache entries.
+     */
+    for (Nch = 1; Nch < Nc; Nch <<= 1)
+        ;
+    Nch <<= 1;
+    Mch = Nch - 1;
+    if (!(Nchash = (struct l_nch **)calloc(Nch + Nc, sizeof(struct l_nch *)))) {
+        if (!Fwarn)
+            (void)fprintf(stderr,
+                          "%s: no space for %d name cache hash pointers\n", Pn,
+                          Nch + Nc);
+        Error(ctx);
+    }
+    for (i = 0, lc = Ncache; i < Nc; i++, lc++) {
+
+#    if defined(NCACHE_NODEID)
+        for (hp = ncachehash(lc->id, lc->vp), n = 1; *hp; hp++)
+#    else  /* !defined(NCACHE_NODEID) */
+        for (hp = ncachehash(lc->vp), n = 1; *hp; hp++)
+#    endif /* defined(NCACHE_NODEID) */
+
+        {
+            if ((*hp)->vp == lc->vp && strcmp((*hp)->nm, lc->nm) == 0 &&
+                (*hp)->dp == lc->dp
+
+#    if defined(NCACHE_NODEID)
+                && (*hp)->id == lc->id && (*hp)->did == lc->did
+#    endif /* defined(NCACHE_NODEID) */
+
+            ) {
+                n = 0;
+                break;
+            }
+        }
+        if (n)
+            *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 < Nc; i++, lc++) {
+        if (!lc->dp)
+            continue;
+
+#    if defined(NCACHE_NEGVN)
+        if (NegVN && (lc->dp == NegVN)) {
+            lc->pa = (struct l_nch *)NULL;
+            continue;
+        }
+#    endif /* defined(NCACHE_NEGVN) */
+
+#    if defined(NCACHE_NODEID)
+        lc->pa = ncache_addr(lc->did, lc->dp);
+#    else  /* !defined(NCACHE_NODEID) */
+        lc->pa = ncache_addr(lc->dp);
+#    endif /* defined(NCACHE_NODEID) */
+    }
 }
 
-
 /*
  * 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 *ncache_lookup(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 (!Nc
-
-# if	defined(NCACHE_NODEID)
-	||  !(lc = ncache_addr(Lf->id, Lf->na))
-# else	/* !defined(NCACHE_NODEID) */
-	||  !(lc = ncache_addr(Lf->na))
-# endif	/* defined(NCACHE_NODEID) */
-
-	) {
-
-	/*
-	 * 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);
+    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 (!Nc
+
+#    if defined(NCACHE_NODEID)
+        || !(lc = ncache_addr(Lf->id, Lf->na))
+#    else  /* !defined(NCACHE_NODEID) */
+        || !(lc = ncache_addr(Lf->na))
+#    endif /* defined(NCACHE_NODEID) */
+
+    ) {
+
+        /*
+         * 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);
 }
-#else	/* !defined(HASNCACHE) || !defined(USE_LIB_RNCH) */
-char rnch_d1[] = "d"; char *rnch_d2 = rnch_d1;
-#endif	/* defined(HASNCACHE) && defined(USE_LIB_RNCH) */
+#else  /* !defined(HASNCACHE) || !defined(USE_LIB_RNCH) */
+char rnch_d1[] = "d";
+char *rnch_d2 = rnch_d1;
+#endif /* defined(HASNCACHE) && defined(USE_LIB_RNCH) */
diff --git a/lib/rnmh.c b/lib/rnmh.c
index 9a2141f..d5fedda 100644
--- a/lib/rnmh.c
+++ b/lib/rnmh.c
@@ -3,7 +3,6 @@
  *	     kernel hash table
  */
 
-
 /*
  * Copyright 1997 Purdue Research Foundation, West Lafayette, Indiana
  * 47907.  All rights reserved.
@@ -30,18 +29,10 @@
  * 4. This notice may not be removed or altered.
  */
 
+#include "common.h"
+#include "machine.h"
 
-#include "../machine.h"
-
-#if	defined(HASNCACHE) && defined(USE_LIB_RNMH)
-
-# if	!defined(lint)
-static char copyright[] =
-"@(#) Copyright 1997 Purdue Research Foundation.\nAll rights reserved.\n";
-# endif	/* !defined(lint) */
-
-#include "../lsof.h"
-
+#if defined(HASNCACHE) && defined(USE_LIB_RNMH)
 
 /*
  * rnmh.c - read BSD format hashed kernel name cache
@@ -111,76 +102,72 @@ static char copyright[] =
  * a kernel allocated, NUL-terminated, string buffer.
  */
 
-
 /*
  * Casts
  */
 
-# if	!defined(NCACHE_NC_CAST)
-#define	NCACHE_SZ_CAST  unsigned long
-# endif	/* !defined(NCACHE_NC_CAST) */
-
+#    if !defined(NCACHE_NC_CAST)
+#        define NCACHE_SZ_CAST unsigned long
+#    endif /* !defined(NCACHE_NC_CAST) */
 
 /*
  * Flags
  */
 
-# if	!defined(NCACHE_NMLEN)
-#undef	NCHNAMLEN
-# endif	/* !defined(NCACHE_NMLEN) */
+#    if !defined(NCACHE_NMLEN)
+#        undef NCHNAMLEN
+#    endif /* !defined(NCACHE_NMLEN) */
 
-# if	!defined(NCACHE_VROOT)
-#define	NCACHE_VROOT	VROOT		/* vnode is root of its file system */
-# endif	/* !defined(NCACHE_VROOT) */
-
-# if	!defined(VNODE_VFLAG)
-#define	VNODE_VFLAG	v_flag
-# endif	/* !defined(VNODE_VFLAG) */
+#    if !defined(NCACHE_VROOT)
+#        define NCACHE_VROOT VROOT /* vnode is root of its file system */
+#    endif                         /* !defined(NCACHE_VROOT) */
 
+#    if !defined(VNODE_VFLAG)
+#        define VNODE_VFLAG v_flag
+#    endif /* !defined(VNODE_VFLAG) */
 
 /*
  * Local static values
  */
 
-static int Mch;				/* name cache hash mask */
+static int Mch; /* name cache hash mask */
 
 struct l_nch {
-	KA_T na;			/* node address */
-	KA_T pa;			/* parent node address */
-	struct l_nch *pla;		/* parent local node address */
-	int nl;				/* name length */
-	struct l_nch *next;		/* next entry */
-
-# if	defined(NCACHE_NODEID)
-	unsigned long id;		/* capability ID */
-	unsigned long did;		/* parent capability ID */
-# endif	/* defined(NCACHE_NODEID) */
-
-# if	defined(NCHNAMLEN)
-	char nm[NCHNAMLEN + 1];		/* name */
-# else	/* !defined(NCHNAMLEN) */
-	char nm[1];			/* variable length name */
-# endif	/* defined(NCHNAMLEN) */
-
+    KA_T na;            /* node address */
+    KA_T pa;            /* parent node address */
+    struct l_nch *pla;  /* parent local node address */
+    int nl;             /* name length */
+    struct l_nch *next; /* next entry */
+
+#    if defined(NCACHE_NODEID)
+    unsigned long id;  /* capability ID */
+    unsigned long did; /* parent capability ID */
+#    endif             /* defined(NCACHE_NODEID) */
+
+#    if defined(NCHNAMLEN)
+    char nm[NCHNAMLEN + 1]; /* name */
+#    else                   /* !defined(NCHNAMLEN) */
+    char nm[1]; /* variable length name */
+#    endif                  /* defined(NCHNAMLEN) */
 };
 
 static struct l_nch *Ncache = (struct l_nch *)NULL;
-					/* the head of the local name cache */
+/* the head of the local name cache */
 static struct l_nch **Nchash = (struct l_nch **)NULL;
-					/* Ncache hash pointers */
+/* Ncache hash pointers */
 
-# if	defined(NCACHE_NODEID)
-#define ncachehash(i,n)		Nchash+(((((int)(n)>>2)+((int)(i)))*31415)&Mch)
-_PROTOTYPE(static struct l_nch *ncache_addr,(unsigned long i, KA_T na));
-# else	/* !defined(NCACHE_NODEID) */
-#define ncachehash(n)		Nchash+((((int)(n)>>2)*31415)&Mch)
-_PROTOTYPE(static struct l_nch *ncache_addr,(KA_T na));
-# endif	/* defined(NCACHE_NODEID) */
-
-# if	!defined(NCACHE_NO_ROOT)
-_PROTOTYPE(static int ncache_isroot,(KA_T na, char *cp));
-# endif	/* !defined(NCACHE_NO_ROOT) */
+#    if defined(NCACHE_NODEID)
+#        define ncachehash(i, n)                                               \
+            Nchash + (((((int)(n) >> 2) + ((int)(i))) * 31415) & Mch)
+static struct l_nch *ncache_addr(unsigned long i, KA_T na);
+#    else /* !defined(NCACHE_NODEID) */
+#        define ncachehash(n) Nchash + ((((int)(n) >> 2) * 31415) & Mch)
+static struct l_nch *ncache_addr(KA_T na);
+#    endif /* defined(NCACHE_NODEID) */
 
+#    if !defined(NCACHE_NO_ROOT)
+static int ncache_isroot(struct lsof_context *ctx, KA_T na, char *cp);
+#    endif /* !defined(NCACHE_NO_ROOT) */
 
 /*
  * ncache_addr() - look up a node's local ncache address
@@ -188,555 +175,542 @@ _PROTOTYPE(static int ncache_isroot,(KA_T na, char *cp));
 
 static struct l_nch *
 
-# if	defined(NCACHE_NODEID)
-ncache_addr(i, na)
-	unsigned long i;		/* node's capability ID */
-# else	/* !defined(NCACHE_NODEID) */
-ncache_addr(na)
-# endif	/* defined(NCACHE_NODEID) */
-
-	KA_T na;			/* node's address */
+#    if defined(NCACHE_NODEID)
+ncache_addr(unsigned long i, /* node's capability ID */
+#    else                    /* !defined(NCACHE_NODEID) */
+ncache_addr(
+#    endif                   /* defined(NCACHE_NODEID) */
+            KA_T na)         /* node's address */
 {
-	struct l_nch **hp;
+    struct l_nch **hp;
 
-# if	defined(NCACHE_NODEID)
-	for (hp = ncachehash(i, na); *hp; hp++)
-# else	/* !defined(NCACHE_NODEID) */
-	for (hp = ncachehash(na); *hp; hp++)
-# endif	/* defined(NCACHE_NODEID) */
+#    if defined(NCACHE_NODEID)
+    for (hp = ncachehash(i, na); *hp; hp++)
+#    else  /* !defined(NCACHE_NODEID) */
+    for (hp = ncachehash(na); *hp; hp++)
+#    endif /* defined(NCACHE_NODEID) */
 
-	{
+    {
 
-# if	defined(NCACHE_NODEID)
-	    if ((*hp)->id == i && (*hp)->na == na)
-# else	/* !defined(NCACHE_NODEID) */
-	    if ((*hp)->na == na)
-# endif	/* defined(NCACHE_NODEID) */
+#    if defined(NCACHE_NODEID)
+        if ((*hp)->id == i && (*hp)->na == na)
+#    else  /* !defined(NCACHE_NODEID) */
+        if ((*hp)->na == na)
+#    endif /* defined(NCACHE_NODEID) */
 
-		return(*hp);
-	}
-	return((struct l_nch *)NULL);
+            return (*hp);
+    }
+    return ((struct l_nch *)NULL);
 }
 
-
-# if	!defined(NCACHE_NO_ROOT)
+#    if !defined(NCACHE_NO_ROOT)
 /*
  * ncache_isroot() - is head of name cache path a file system root?
  */
 
-static int
-ncache_isroot(na, cp)
-	KA_T na;			/* kernel node address */
-	char *cp;			/* partial path */
+static int ncache_isroot(struct lsof_context *ctx,
+                         KA_T na,  /* kernel node address */
+                         char *cp) /* partial path */
 {
-	char buf[MAXPATHLEN];
-	int i;
-	MALLOC_S len;
-	struct mounts *mtp;
-	static int nca = 0;
-	static int ncn = 0;
-	static KA_T *nc = (KA_T *)NULL;
-	struct stat sb;
-	struct vnode v;
-
-	if (!na)
-	    return(0);
-/*
- * Search the root vnode 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 NCACHE_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.VNODE_VFLAG & NCACHE_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
-	    ||  (unsigned long)sb.st_ino != Lf->inode)
-		return(0);
-	}
-/*
- * Add the node address to the root node 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(nc, len);
-	    }
-	    if (!nc) {
-		(void) fprintf(stderr, "%s: no space for root node table\n",
-		    Pn);
-		Error();
-	    }
-	    nca += 10;
-	}
-	nc[ncn++] = na;
-	return(1);
+    char buf[MAXPATHLEN];
+    int i;
+    MALLOC_S len;
+    struct mounts *mtp;
+    static int nca = 0;
+    static int ncn = 0;
+    static KA_T *nc = (KA_T *)NULL;
+    struct stat sb;
+    struct vnode v;
+
+    if (!na)
+        return (0);
+    /*
+     * Search the root vnode 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 NCACHE_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 its inode number
+     * matches the one we have for this file.  If it does, then the path is
+     * complete.
+     */
+    if (kread(ctx, (KA_T)na, (char *)&v, sizeof(v)) || v.v_type != VDIR ||
+        !(v.VNODE_VFLAG & NCACHE_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(ctx); 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(ctx, buf, &sb) != 0 ||
+            (unsigned long)sb.st_ino != Lf->inode)
+            return (0);
+    }
+    /*
+     * Add the node address to the root node 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(nc, len);
+        }
+        if (!nc) {
+            (void)fprintf(stderr, "%s: no space for root node table\n", Pn);
+            Error(ctx);
+        }
+        nca += 10;
+    }
+    nc[ncn++] = na;
+    return (1);
 }
-# endif	/* !defined(NCACHE_NO_ROOT) */
-
+#    endif /* !defined(NCACHE_NO_ROOT) */
 
 /*
  * ncache_load() - load the kernel's name cache
  */
 
-void
-ncache_load()
-{
-	struct NCACHE c;
-	struct l_nch **hp, *ln;
-	KA_T ka, knx;
-	static struct NCACHE **khp = (struct namecache **)NULL;
-	static int khpl = 0;
-	NCACHE_SZ_CAST khsz;
-	unsigned long kx;
-	static struct l_nch *lc = (struct l_nch *)NULL;
-	static int lcl = 0;
-	int len, lim, n, nch, nchl, nlcl;
-	char tbuf[32];
-	KA_T v;
-
-# if	!defined(NCHNAMLEN)
-	int cin = sizeof(c.NCACHE_NM);
-	KA_T nmo = (KA_T)offsetof(struct NCACHE, NCACHE_NM);
-# endif	/* !defined(NCHNAMLEN) */
-
-# if	!defined(NCACHE_NMLEN)
-	char nbf[MAXPATHLEN + 1];
-	int nbfl = (int)(sizeof(nbf) - 1);
-	KA_T nk;
-	char *np;
-	int rl;
-
-	nbf[nbfl] = '\0';
-# endif	/* !defined(NCACHE_NMLEN) */
-
-	if (!Fncache)
-	    return;
-/*
- * Free previously allocated space.
- */
-	for (lc = Ncache; lc; lc = ln) {
-	    ln = lc->next;
-	    (void) free((FREE_P *)lc);
-	}
-	Ncache = (struct l_nch *)NULL;
-	if (Nchash)
-	    (void) free((FREE_P *)Nchash);
-	Nchash = (struct l_nch **)NULL;
-/*
- * Get kernel cache hash table size
- */
-	v = (KA_T)0;
-	if (get_Nl_value(X_NCSIZE, (struct drive_Nl *)NULL, &v) < 0
-	||  !v
-	||  kread((KA_T)v, (char *)&khsz, sizeof(khsz)))
-	{
-	    if (!Fwarn)
-		(void) fprintf(stderr,
-		    "%s: WARNING: can't read name cache hash size: %s\n",
-		    Pn, print_kptr(v, (char *)NULL, 0));
-	    return;
-	}
-	if (khsz < 1) {
-	    if (!Fwarn)
-		(void) fprintf(stderr,
-		    "%s: WARNING: name cache hash size length error: %#lx\n",
-		    Pn, khsz);
-	    return;
-	}
-/*
- * Get kernel cache hash table address.
- */
-	ka = (KA_T)0;
-	v = (KA_T)0;
-	if (get_Nl_value(X_NCACHE, (struct drive_Nl *)NULL, &v) < 0
-	||  !v
-	||  kread((KA_T)v, (char *)&ka, sizeof(ka))
-	||  !ka)
-	{
-	    if (!Fwarn)
-		(void) fprintf(stderr,
-		    "%s: WARNING: unusable name cache hash pointer: (%s)=%s\n",
-	            Pn, print_kptr(v, tbuf, sizeof(tbuf)),
-		    print_kptr(ka, (char *)NULL, 0));
-	    return;
-	}
-/*
- * Allocate space for the hash table pointers and read them.
- */
-	len = (MALLOC_S)(khsz * sizeof(struct NCACHE *));
-	if (len > khpl) {
-	    if (khp)
-		khp = (struct NCACHE **)realloc((MALLOC_P *)khp, len);
-	    else
-		khp = (struct NCACHE **)malloc(len);
-	    if (!khp) {
-		(void) fprintf(stderr,
-		    "%s: can't allocate %d bytes for name cache hash table\n",
-		    Pn, len);
-		Error();
-	    }
-	    khpl = len;
-	}
-	if (kread((KA_T)ka, (char *)khp, len)) {
-	    (void) fprintf(stderr,
-		"%s: can't read name cache hash pointers from: %s\n",
-		Pn, print_kptr(ka, (char *)NULL, 0));
-	    return;
-	}
-/*
- * Process the kernel's name cache hash table buckets.
- */
-	lim = khsz * 10;
-	for (kx = nch = 0; kx < khsz; kx++) {
-
-	/*
-	 * Loop through the entries for a hash bucket.
-	 */
-	    for (ka = (KA_T)khp[kx], n = 0; ka; ka = knx, n++) {
-		if (n > lim) {
-		    if (!Fwarn)
-			(void) fprintf(stderr,
-			    "%s: WARNING: name cache hash chain too long\n",
-			    Pn);
-		    break;
-		}
-		if (kread(ka, (char *)&c, sizeof(c)))
-		    break;
-		knx = (KA_T)c.NCACHE_NXT;
-		if (!c.NCACHE_NODEADDR)
-		    continue;
-
-# if	defined(NCACHE_NMLEN)
-		if ((len = c.NCACHE_NMLEN) < 1)
-		    continue;
-# else	/* !defined(NCACHE_NMLEN) */
-	    /*
-	     * If it's possible to read the first four characters of the name,
-	     * do so and check for "." and "..".
-	     */
-		if (!c.NCACHE_NM
-		||  kread((KA_T)c.NCACHE_NM, nbf, 4))
-		    continue;
-		if (nbf[0] == '.') {
-		    if (!nbf[1]
-		    ||  ((nbf[1] == '.') && !nbf[2]))
-			continue;
-		}
-	   /*
-	    * Read the rest of the name, 32 characters at a time, until a NUL
-	    * character has been read or nbfl characters have been read.
-	    */
-		nbf[4] = '\0';
-		if ((len = (int)strlen(nbf)) < 4) {
-		    if (!len)
-			continue;
-		} else {
-		    for (np = &nbf[4]; len < nbfl; np += rl) {
-			if ((rl = nbfl - len) > 32) {
-			    rl = 32;
-			    nbf[len + rl] = '\0';
-			}
-			nk = (KA_T)((char *)c.NCACHE_NM + len);
-			if (kread(nk, np, rl)) {
-			    rl = -1;
-			    break;
-			}
-			rl = (int)strlen(np);
-			len += rl;
-			if (rl < 32)
-			    break;
-		    }
-		    if (rl < 0)
-			continue;
-		}
-# endif	/* defined(NCACHE_NMLEN) */
-
-	    /*
-	     * Allocate a cache entry long enough to contain the name and
-	     * move the name to it.
-	     */
-
-# if	defined(NCHNAMLEN)
-		if (len > NCHNAMLEN)
-		    continue;
-		if (len < 3 && c.NCACHE_NM[0] == '.') {
-		    if (len == 1 || (len == 2 && c.NCACHE_NM[1] == '.'))
-			continue;
-		}
-		if ((nlcl = sizeof(struct l_nch)) > lcl)
-# else	/* !defined(NCHNAMLEN) */
-		if ((nlcl = sizeof(struct l_nch) + len) > lcl)
-# endif	/* defined(NCHNAMLEN) */
-
-		{
-		    if (lc)
-			lc = (struct l_nch *)realloc(lc, nlcl);
-		    else
-			lc = (struct l_nch *)malloc(nlcl);
-		    if (!lc) {
-			(void) fprintf(stderr,
-			    "%s: can't allocate %d local name cache bytes\n",
-			    Pn, nlcl);
-			Error();
-		    }
-		    lcl = nlcl;
-		}
-
-# if	defined(NCHNAMLEN)
-		(void) strncpy(lc->nm, c.NCACHE_NM, len);
-# else	/* !defined(NCHNAMLEN) */
-#  if	defined(NCACHE_NMLEN)
-		if ((len < 3) && (cin > 1)) {
-
-		/*
-		 * If this is a one or two character name, and if NCACHE_NM[]
-		 * in c has room for at least two characters, check for "."
-		 * and ".." first, ignoring this entry if the name is either.
-		 */
-		    if (len < 3 && c.NCACHE_NM[0] == '.') {
-			if (len == 1 || (len == 2 && c.NCACHE_NM[1] == '.'))
-			    continue;
-		    }
-		}
-		if (len > cin) {
-
-		/*
-		 * If not all (possibly not any, depending on the value in
-		 * cin) of the name has yet been read to lc->nm[], read it
-		 * or the rest of it.  If it wasn't possible before to check
-		 * for "." or "..", do that. too.
-		 */
-		    if (cin > 0)
-			(void) strncpy(lc->nm, c.NCACHE_NM, cin);
-		    if (kread(ka + (KA_T)(nmo + cin), &lc->nm[cin], len - cin))
-			continue;
-		    if ((cin < 2) && (len < 3) && (lc->nm[0] == '.')) {
-			if (len == 1 || (len == 2 && lc->nm[1] == '.'))
-			    continue;
-		    }
-		} else
-		    (void) strncpy(lc->nm, c.NCACHE_NM, len);
-#  else	/* !defined(NCACHE_NMLEN) */
-		(void) strncpy(lc->nm, nbf, len);
-#  endif	/* defined(NCACHE_NMLEN) */
-
-# endif	/* defined(NCHNAMLEN) */
-		lc->nm[len] = '\0';
-	    /*
-	     * Complete the new local cache entry and link it to the previous
-	     * local cache chain.
-	     */
-		lc->next = Ncache;
-		Ncache = lc;
-		lc->na = (KA_T)c.NCACHE_NODEADDR;
-		lc->nl = len;
-		lc->pa = (KA_T)c.NCACHE_PARADDR;
-		lc->pla = (struct l_nch *)NULL;
-
-# if	defined(NCACHE_NODEID)
-		lc->id = c.NCACHE_NODEID;
-		lc->did = c.NCACHE_PARID;
-# endif	/* defined(NCACHE_NODEID) */
-
-		lcl = 0;
-		lc = (struct l_nch *)NULL;
-		nch++;
-	    }
-	}
-/*
- * Reduce memory usage, as required.
- */
-	if (!RptTm) {
-	    (void) free((FREE_P *)khp);
-	    khp = (struct NCACHE **)NULL;
-	    khpl = 0;
-	}
-	if (nch < 1) {
-	    if (!Fwarn)
-		(void) fprintf(stderr,
-		    "%s: WARNING: unusable name cache size: %d\n", Pn, nch);
-	    return;
-	}
-/*
- * Build a hash table to locate Ncache entries.
- */
-	for (nchl = 1; nchl < nch; nchl <<= 1)
-	    ;
-	nchl <<= 1;
-	Mch = nchl - 1;
-	len = nchl + nch;
-	if (!(Nchash = (struct l_nch **)calloc(len, sizeof(struct l_nch *)))) {
-	    if (!Fwarn)
-		(void) fprintf(stderr,
-		    "%s: no space for %d local name cache hash pointers\n",
-		    Pn, len);
-	    Error();
-	}
-	for (lc = Ncache; lc; lc = lc->next) {
-
-# if	defined(NCACHE_NODEID)
-	    for (hp = ncachehash(lc->id, lc->na),
-# else	/* !defined(NCACHE_NODEID) */
-	    for (hp = ncachehash(lc->na),
-# endif	/* defined(NCACHE_NODEID) */
-
-		    n = 1; *hp; hp++)
-		{
-		if ((*hp)->na == lc->na && strcmp((*hp)->nm, lc->nm) == 0) {
-		    n = 0;
-		    break;
-		}
-	    }
-	    if (n)
-		*hp = lc;
-	    else
-		lc->pa = (KA_T)0;
-	}
-/*
- * Make a final pass through the local cache and convert parent node
- * addresses to local name cache pointers.
- */
-	for (lc = Ncache; lc; lc = lc->next) {
-	    if (!lc->pa)
-		continue;
-
-# if	defined(NCACHE_NODEID)
-	    lc->pla = ncache_addr(lc->did, lc->pa);
-# else	/* !defined(NCACHE_NODEID) */
-	    lc->pla = ncache_addr(lc->pa);
-# endif	/* defined(NCACHE_NODEID) */
-
-	}
+void ncache_load(struct lsof_context *ctx) {
+    struct NCACHE c;
+    struct l_nch **hp, *ln;
+    KA_T ka, knx;
+    static struct NCACHE **khp = (struct namecache **)NULL;
+    static int khpl = 0;
+    NCACHE_SZ_CAST khsz;
+    unsigned long kx;
+    static struct l_nch *lc = (struct l_nch *)NULL;
+    static int lcl = 0;
+    int len, lim, n, nch, nchl, nlcl;
+    char tbuf[32];
+    KA_T v;
+
+#    if !defined(NCHNAMLEN)
+    int cin = sizeof(c.NCACHE_NM);
+    KA_T nmo = (KA_T)offsetof(struct NCACHE, NCACHE_NM);
+#    endif /* !defined(NCHNAMLEN) */
+
+#    if !defined(NCACHE_NMLEN)
+    char nbf[MAXPATHLEN + 1];
+    int nbfl = (int)(sizeof(nbf) - 1);
+    KA_T nk;
+    char *np;
+    int rl;
+
+    nbf[nbfl] = '\0';
+#    endif /* !defined(NCACHE_NMLEN) */
+
+    if (!Fncache)
+        return;
+    /*
+     * Free previously allocated space.
+     */
+    for (lc = Ncache; lc; lc = ln) {
+        ln = lc->next;
+        (void)free((FREE_P *)lc);
+    }
+    Ncache = (struct l_nch *)NULL;
+    if (Nchash)
+        (void)free((FREE_P *)Nchash);
+    Nchash = (struct l_nch **)NULL;
+    /*
+     * Get kernel cache hash table size
+     */
+    v = (KA_T)0;
+    if (get_Nl_value(ctx, X_NCSIZE, (struct drive_Nl *)NULL, &v) < 0 || !v ||
+        kread(ctx, (KA_T)v, (char *)&khsz, sizeof(khsz))) {
+        if (!Fwarn)
+            (void)fprintf(stderr,
+                          "%s: WARNING: can't read name cache hash size: %s\n",
+                          Pn, print_kptr(v, (char *)NULL, 0));
+        return;
+    }
+    if (khsz < 1) {
+        if (!Fwarn)
+            (void)fprintf(
+                stderr,
+                "%s: WARNING: name cache hash size length error: %#lx\n", Pn,
+                khsz);
+        return;
+    }
+    /*
+     * Get kernel cache hash table address.
+     */
+    ka = (KA_T)0;
+    v = (KA_T)0;
+    if (get_Nl_value(ctx, X_NCACHE, (struct drive_Nl *)NULL, &v) < 0 || !v ||
+        kread(ctx, (KA_T)v, (char *)&ka, sizeof(ka)) || !ka) {
+        if (!Fwarn)
+            (void)fprintf(
+                stderr,
+                "%s: WARNING: unusable name cache hash pointer: (%s)=%s\n", Pn,
+                print_kptr(v, tbuf, sizeof(tbuf)),
+                print_kptr(ka, (char *)NULL, 0));
+        return;
+    }
+    /*
+     * Allocate space for the hash table pointers and read them.
+     */
+    len = (MALLOC_S)(khsz * sizeof(struct NCACHE *));
+    if (len > khpl) {
+        if (khp)
+            khp = (struct NCACHE **)realloc((MALLOC_P *)khp, len);
+        else
+            khp = (struct NCACHE **)malloc(len);
+        if (!khp) {
+            (void)fprintf(
+                stderr,
+                "%s: can't allocate %d bytes for name cache hash table\n", Pn,
+                len);
+            Error(ctx);
+        }
+        khpl = len;
+    }
+    if (kread(ctx, (KA_T)ka, (char *)khp, len)) {
+        (void)fprintf(stderr,
+                      "%s: can't read name cache hash pointers from: %s\n", Pn,
+                      print_kptr(ka, (char *)NULL, 0));
+        return;
+    }
+    /*
+     * Process the kernel's name cache hash table buckets.
+     */
+    lim = khsz * 10;
+    for (kx = nch = 0; kx < khsz; kx++) {
+
+        /*
+         * Loop through the entries for a hash bucket.
+         */
+        for (ka = (KA_T)khp[kx], n = 0; ka; ka = knx, n++) {
+            if (n > lim) {
+                if (!Fwarn)
+                    (void)fprintf(
+                        stderr, "%s: WARNING: name cache hash chain too long\n",
+                        Pn);
+                break;
+            }
+            if (kread(ctx, ka, (char *)&c, sizeof(c)))
+                break;
+            knx = (KA_T)c.NCACHE_NXT;
+            if (!c.NCACHE_NODEADDR)
+                continue;
+
+#    if defined(NCACHE_NMLEN)
+            if ((len = c.NCACHE_NMLEN) < 1)
+                continue;
+#    else  /* !defined(NCACHE_NMLEN) */
+            /*
+             * If it's possible to read the first four characters of the name,
+             * do so and check for "." and "..".
+             */
+            if (!c.NCACHE_NM || kread(ctx, (KA_T)c.NCACHE_NM, nbf, 4))
+                continue;
+            if (nbf[0] == '.') {
+                if (!nbf[1] || ((nbf[1] == '.') && !nbf[2]))
+                    continue;
+            }
+            /*
+             * Read the rest of the name, 32 characters at a time, until a NUL
+             * character has been read or nbfl characters have been read.
+             */
+            nbf[4] = '\0';
+            if ((len = (int)strlen(nbf)) < 4) {
+                if (!len)
+                    continue;
+            } else {
+                for (np = &nbf[4]; len < nbfl; np += rl) {
+                    if ((rl = nbfl - len) > 32) {
+                        rl = 32;
+                        nbf[len + rl] = '\0';
+                    }
+                    nk = (KA_T)((char *)c.NCACHE_NM + len);
+                    if (kread(ctx, nk, np, rl)) {
+                        rl = -1;
+                        break;
+                    }
+                    rl = (int)strlen(np);
+                    len += rl;
+                    if (rl < 32)
+                        break;
+                }
+                if (rl < 0)
+                    continue;
+            }
+#    endif /* defined(NCACHE_NMLEN) */
+
+                /*
+                 * Allocate a cache entry long enough to contain the name and
+                 * move the name to it.
+                 */
+
+#    if defined(NCHNAMLEN)
+            if (len > NCHNAMLEN)
+                continue;
+            if (len < 3 && c.NCACHE_NM[0] == '.') {
+                if (len == 1 || (len == 2 && c.NCACHE_NM[1] == '.'))
+                    continue;
+            }
+            if ((nlcl = sizeof(struct l_nch)) > lcl)
+#    else  /* !defined(NCHNAMLEN) */
+            if ((nlcl = sizeof(struct l_nch) + len) > lcl)
+#    endif /* defined(NCHNAMLEN) */
+
+            {
+                if (lc)
+                    lc = (struct l_nch *)realloc(lc, nlcl);
+                else
+                    lc = (struct l_nch *)malloc(nlcl);
+                if (!lc) {
+                    (void)fprintf(
+                        stderr,
+                        "%s: can't allocate %d local name cache bytes\n", Pn,
+                        nlcl);
+                    Error(ctx);
+                }
+                lcl = nlcl;
+            }
+
+#    if defined(NCHNAMLEN)
+            (void)strncpy(lc->nm, c.NCACHE_NM, len);
+#    else /* !defined(NCHNAMLEN) */
+#        if defined(NCACHE_NMLEN)
+            if ((len < 3) && (cin > 1)) {
+
+                /*
+                 * If this is a one or two character name, and if NCACHE_NM[]
+                 * in c has room for at least two characters, check for "."
+                 * and ".." first, ignoring this entry if the name is either.
+                 */
+                if (len < 3 && c.NCACHE_NM[0] == '.') {
+                    if (len == 1 || (len == 2 && c.NCACHE_NM[1] == '.'))
+                        continue;
+                }
+            }
+            if (len > cin) {
+
+                /*
+                 * If not all (possibly not any, depending on the value in
+                 * cin) of the name has yet been read to lc->nm[], read it
+                 * or the rest of it.  If it wasn't possible before to check
+                 * for "." or "..", do that. too.
+                 */
+                if (cin > 0)
+                    (void)strncpy(lc->nm, c.NCACHE_NM, cin);
+                if (kread(ctx, ka + (KA_T)(nmo + cin), &lc->nm[cin], len - cin))
+                    continue;
+                if ((cin < 2) && (len < 3) && (lc->nm[0] == '.')) {
+                    if (len == 1 || (len == 2 && lc->nm[1] == '.'))
+                        continue;
+                }
+            } else
+                (void)strncpy(lc->nm, c.NCACHE_NM, len);
+#        else  /* !defined(NCACHE_NMLEN) */
+            (void)strncpy(lc->nm, nbf, len);
+#        endif /* defined(NCACHE_NMLEN) */
+
+#    endif /* defined(NCHNAMLEN) */
+            lc->nm[len] = '\0';
+            /*
+             * Complete the new local cache entry and link it to the previous
+             * local cache chain.
+             */
+            lc->next = Ncache;
+            Ncache = lc;
+            lc->na = (KA_T)c.NCACHE_NODEADDR;
+            lc->nl = len;
+            lc->pa = (KA_T)c.NCACHE_PARADDR;
+            lc->pla = (struct l_nch *)NULL;
+
+#    if defined(NCACHE_NODEID)
+            lc->id = c.NCACHE_NODEID;
+            lc->did = c.NCACHE_PARID;
+#    endif /* defined(NCACHE_NODEID) */
+
+            lcl = 0;
+            lc = (struct l_nch *)NULL;
+            nch++;
+        }
+    }
+    /*
+     * Reduce memory usage, as required.
+     */
+    if (!RptTm) {
+        (void)free((FREE_P *)khp);
+        khp = (struct NCACHE **)NULL;
+        khpl = 0;
+    }
+    if (nch < 1) {
+        if (!Fwarn)
+            (void)fprintf(stderr, "%s: WARNING: unusable name cache size: %d\n",
+                          Pn, nch);
+        return;
+    }
+    /*
+     * Build a hash table to locate Ncache entries.
+     */
+    for (nchl = 1; nchl < nch; nchl <<= 1)
+        ;
+    nchl <<= 1;
+    Mch = nchl - 1;
+    len = nchl + nch;
+    if (!(Nchash = (struct l_nch **)calloc(len, sizeof(struct l_nch *)))) {
+        if (!Fwarn)
+            (void)fprintf(
+                stderr, "%s: no space for %d local name cache hash pointers\n",
+                Pn, len);
+        Error(ctx);
+    }
+    for (lc = Ncache; lc; lc = lc->next) {
+
+#    if defined(NCACHE_NODEID)
+        for (hp = ncachehash(lc->id, lc->na),
+#    else  /* !defined(NCACHE_NODEID) */
+        for (hp = ncachehash(lc->na),
+#    endif /* defined(NCACHE_NODEID) */
+
+            n = 1;
+             *hp; hp++) {
+            if ((*hp)->na == lc->na && strcmp((*hp)->nm, lc->nm) == 0) {
+                n = 0;
+                break;
+            }
+        }
+        if (n)
+            *hp = lc;
+        else
+            lc->pa = (KA_T)0;
+    }
+    /*
+     * Make a final pass through the local cache and convert parent node
+     * addresses to local name cache pointers.
+     */
+    for (lc = Ncache; lc; lc = lc->next) {
+        if (!lc->pa)
+            continue;
+
+#    if defined(NCACHE_NODEID)
+        lc->pla = ncache_addr(lc->did, lc->pa);
+#    else  /* !defined(NCACHE_NODEID) */
+        lc->pla = ncache_addr(lc->pa);
+#    endif /* defined(NCACHE_NODEID) */
+    }
 }
 
-
 /*
  * 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 *ncache_lookup(struct lsof_context *ctx,
+                    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	defined(NCACHE_NODEID)
-	if (!Nchash || !(lc = ncache_addr(Lf->id, Lf->na)))
-# else	/* !defined(NCACHE_NODEID) */
-	if (!Nchash || !(lc = ncache_addr(Lf->na)))
-# endif	/* defined(NCACHE_NODEID) */
-
-	{
-
-	/*
-	 * 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 = 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 length is too large to fit in the receiving buffer.
- */
-	for (;;) {
-	    if (!lc->pla) {
-
-#  if	!defined(NCACHE_NO_ROOT)
-		if (ncache_isroot(lc->pa, cp))
-		    *fp = 1;
-#  endif	/* !defined(NCACHE_NO_ROOT) */
-
-		break;
-	    }
-	    lc = lc->pla;
-	    if (((nl = lc->nl) + 1) > rlen)
-		break;
-	    *(cp - 1) = '/';
-	    cp--;
-	    rlen--;
-	    (void) strncpy((cp - nl), lc->nm, nl);
-	    cp -= nl;
-	    rlen -= nl;
-	}
-	return(cp);
+    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 defined(NCACHE_NODEID)
+    if (!Nchash || !(lc = ncache_addr(Lf->id, Lf->na)))
+#    else  /* !defined(NCACHE_NODEID) */
+    if (!Nchash || !(lc = ncache_addr(Lf->na)))
+#    endif /* defined(NCACHE_NODEID) */
+
+    {
+
+        /*
+         * 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(ctx); 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 = 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 length is too large to fit in the receiving buffer.
+     */
+    for (;;) {
+        if (!lc->pla) {
+
+#    if !defined(NCACHE_NO_ROOT)
+            if (ncache_isroot(ctx, lc->pa, cp))
+                *fp = 1;
+#    endif /* !defined(NCACHE_NO_ROOT) */
+
+            break;
+        }
+        lc = lc->pla;
+        if (((nl = lc->nl) + 1) > rlen)
+            break;
+        *(cp - 1) = '/';
+        cp--;
+        rlen--;
+        (void)strncpy((cp - nl), lc->nm, nl);
+        cp -= nl;
+        rlen -= nl;
+    }
+    return (cp);
 }
-#else	/* !defined(HASNCACHE) || !defined(USE_LIB_RNMH) */
-char rnmh_d1[] = "d"; char *rnmh_d2 = rnmh_d1;
-#endif	/* defined(HASNCACHE) && defined(USE_LIB_RNMH) */
+#else  /* !defined(HASNCACHE) || !defined(USE_LIB_RNMH) */
+char rnmh_d1[] = "d";
+char *rnmh_d2 = rnmh_d1;
+#endif /* defined(HASNCACHE) && defined(USE_LIB_RNMH) */
diff --git a/lib/rnmt.c b/lib/rnmt.c
new file mode 100644
index 0000000..709aad5
--- /dev/null
+++ b/lib/rnmt.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2022  Tobias Nygren <tnn@NetBSD.org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "common.h"
+#include "machine.h"
+
+#if defined(HASNCACHE) && defined(USE_LIB_RNMT)
+#    include <sys/rbtree.h>
+#    include <sys/vnode_impl.h>
+#    include <err.h>
+
+/*
+ * rnmt.c - read NetBSD=>10-style red-black tree kernel name cache
+ */
+
+static int lnc_compare_nodes(void *, const void *, const void *);
+static int lnc_compare_key(void *, const void *, const void *);
+
+static rb_tree_t lnc_rbtree;
+
+/* local name cache entry */
+struct lnc {
+    struct rb_node lnc_tree;      /* red-black tree */
+    KA_T lnc_vp;                  /* vnode address */
+    const struct lnc *lnc_plnc;   /* parent lnc address */
+    int lnc_nlen;                 /* name length */
+    char lnc_name[NCHNAMLEN + 1]; /* name */
+};
+
+static const rb_tree_ops_t lnc_rbtree_ops = {
+    .rbto_compare_nodes = lnc_compare_nodes,
+    .rbto_compare_key = lnc_compare_key,
+    .rbto_node_offset = offsetof(struct lnc, lnc_tree),
+    .rbto_context = NULL};
+
+static int lnc_compare_nodes(void *context, const void *node1,
+                             const void *node2) {
+    const struct lnc *lnc1 = node1;
+    const struct lnc *lnc2 = node2;
+
+    if (lnc1->lnc_vp < lnc2->lnc_vp) {
+        return -1;
+    }
+    if (lnc1->lnc_vp > lnc2->lnc_vp) {
+        return 1;
+    }
+
+    return 0;
+}
+
+static int lnc_compare_key(void *context, const void *node, const void *key) {
+    const struct lnc *lnc = node;
+    const KA_T vp = (KA_T)key;
+
+    if (lnc->lnc_vp < vp) {
+        return -1;
+    }
+    if (lnc->lnc_vp > vp) {
+        return 1;
+    }
+
+    return 0;
+}
+
+static struct lnc *ncache_enter_local(KA_T vp, const struct lnc *plnc,
+                                      const struct namecache *nc) {
+    struct lnc *lnc;
+
+    lnc = malloc(sizeof(*lnc));
+    if (!lnc) {
+        errx(1, "can't allocate local name cache entry\n");
+    }
+    lnc->lnc_vp = vp;
+    lnc->lnc_plnc = plnc;
+    lnc->lnc_nlen = nc->nc_nlen;
+    memcpy(lnc->lnc_name, nc->nc_name, lnc->lnc_nlen);
+    lnc->lnc_name[lnc->lnc_nlen] = 0;
+
+    rb_tree_insert_node(&lnc_rbtree, lnc);
+
+    return lnc;
+}
+
+static int sanity_check_vnode_impl(const struct vnode_impl *vi) {
+    if (vi->vi_vnode.v_type >= VBAD)
+        return -1;
+
+    return 0;
+}
+
+static int sanity_check_namecache(const struct namecache *nc) {
+    if (nc->nc_vp == NULL)
+        return -1;
+
+    if (nc->nc_nlen > NCHNAMLEN)
+        return -1;
+
+    if (nc->nc_nlen == 1 && nc->nc_name[0] == '.')
+        return -1;
+
+    if (nc->nc_nlen == 2 && nc->nc_name[0] == '.' && nc->nc_name[1] == '.')
+        return -1;
+
+    return 0;
+}
+
+static void ncache_walk(struct lsof_context *ctx, KA_T ncp,
+                        const struct lnc *plnc) {
+    struct l_nch *lc;
+    static struct vnode_impl vi;
+    static struct namecache nc;
+    struct lnc *lnc;
+    KA_T vp;
+    KA_T left, right;
+
+    if (kread(ctx, ncp, (char *)&nc, sizeof(nc))) {
+        return;
+    }
+    vp = (KA_T)nc.nc_vp;
+    if (kread(ctx, vp, (char *)&vi, sizeof(vi))) {
+        vi.vi_vnode.v_type = VBAD;
+    }
+    left = (KA_T)nc.nc_tree.rb_nodes[0];
+    right = (KA_T)nc.nc_tree.rb_nodes[1];
+    if (sanity_check_vnode_impl(&vi) == 0 && sanity_check_namecache(&nc) == 0) {
+        lnc = ncache_enter_local(vp, plnc, &nc);
+        if (vi.vi_vnode.v_type == VDIR && vi.vi_nc_tree.rbt_root != NULL) {
+            ncache_walk((KA_T)vi.vi_nc_tree.rbt_root, lnc);
+        }
+    }
+    if (left)
+        ncache_walk(left, plnc);
+    if (right)
+        ncache_walk(right, plnc);
+}
+
+void ncache_load(struct lsof_context *ctx) {
+    KA_T rootvnode_addr;
+    struct vnode_impl vi;
+
+    rootvnode_addr = (KA_T)0;
+    if (get_Nl_value("rootvnode", (struct drive_Nl *)NULL, &rootvnode_addr) <
+            0 ||
+        !rootvnode_addr ||
+        kread(ctx, (KA_T)rootvnode_addr, (char *)&rootvnode_addr,
+              sizeof(rootvnode_addr)) ||
+        kread(ctx, (KA_T)rootvnode_addr, (char *)&vi, sizeof(vi))) {
+        errx(1, "can't read rootvnode\n");
+    }
+
+    rb_tree_init(&lnc_rbtree, &lnc_rbtree_ops);
+    ncache_walk((KA_T)vi.vi_nc_tree.rbt_root, 0);
+}
+
+static void build_path(char **buf, size_t *remaining, const struct lnc *lnc) {
+    size_t len;
+
+    if (lnc == NULL)
+        return;
+
+    build_path(buf, remaining, lnc->lnc_plnc);
+    if (remaining == 0) {
+        return;
+    }
+    if (lnc->lnc_plnc != NULL) {
+        **buf = '/';
+        (*buf)++;
+        remaining--;
+    }
+    len = lnc->lnc_nlen;
+    if (*remaining < len)
+        len = *remaining;
+    memcpy(*buf, lnc->lnc_name, len);
+    *remaining -= len;
+    *buf += len;
+}
+
+char *ncache_lookup(char *buf, int blen, int *fp) {
+    const struct lnc *lnc;
+    char *p;
+    size_t remaining;
+
+    *fp = 0;
+    lnc = rb_tree_find_node(&lnc_rbtree, (void *)Lf->na);
+    if (lnc != NULL) {
+        p = buf;
+        remaining = blen;
+        build_path(&p, &remaining, lnc);
+        if (remaining == 0) {
+            buf[blen - 1] = 0;
+        } else {
+            *p = 0;
+        }
+        *fp = 1;
+        return buf;
+    }
+
+    return NULL;
+}
+#endif
diff --git a/lib/snpf.c b/lib/snpf.c
deleted file mode 100644
index 2854ed8..0000000
--- a/lib/snpf.c
+++ /dev/null
@@ -1,749 +0,0 @@
-/*
- * snpf.c -- snprintf() empulation functions for lsof library
- *
- * V. Abell
- * Purdue University Computing Center
- */
-
-/*
- * Copyright 2000 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.
- *
- * This software has been adapted from snprintf.c in sendmail 8.9.3.  It
- * is subject to the sendmail copyright statements listed below, and the
- * sendmail licensing terms stated in the sendmail LICENSE file comment
- * section of this file.
- *
- * 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.
- */
-
-#include "../machine.h"
-
-#ifdef	USE_LIB_SNPF
-
-/*
- * Sendmail copyright statements:
- *
- * Copyright (c) 1998 Sendmail, Inc.  All rights reserved.
- * Copyright (c) 1997 Eric P. Allman.  All rights reserved.
- * Copyright (c) 1988, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * By using this file, you agree to the terms and conditions set
- * forth in the LICENSE file which can be found at the top level of
- * the sendmail distribution.
- *
- * The LICENSE file may be found in the following comment section.
- */
-
-
-/*
- * Begin endmail LICENSE file.
-
-			     SENDMAIL LICENSE
-
-The following license terms and conditions apply, unless a different
-license is obtained from Sendmail, Inc., 1401 Park Avenue, Emeryville, CA
-94608, or by electronic mail at license@sendmail.com.
-
-License Terms:
-
-Use, Modification and Redistribution (including distribution of any
-modified or derived work) in source and binary forms is permitted only if
-each of the following conditions is met:
-
-1. Redistributions qualify as "freeware" or "Open Source Software" under
-   one of the following terms:
-
-   (a) Redistributions are made at no charge beyond the reasonable cost of
-       materials and delivery.
-
-   (b) Redistributions are accompanied by a copy of the Source Code or by an
-       irrevocable offer to provide a copy of the Source Code for up to three
-       years at the cost of materials and delivery.  Such redistributions
-       must allow further use, modification, and redistribution of the Source
-       Code under substantially the same terms as this license.  For the
-       purposes of redistribution "Source Code" means the complete source
-       code of sendmail including all modifications.
-
-   Other forms of redistribution are allowed only under a separate royalty-
-   free agreement permitting such redistribution subject to standard
-   commercial terms and conditions.  A copy of such agreement may be
-   obtained from Sendmail, Inc. at the above address.
-
-2. Redistributions of source code must retain the copyright notices as they
-   appear in each source code file, these license terms, and the
-   disclaimer/limitation of liability set forth as paragraph 6 below.
-
-3. Redistributions in binary form must reproduce the Copyright Notice,
-   these license terms, and the disclaimer/limitation of liability set
-   forth as paragraph 6 below, in the documentation and/or other materials
-   provided with the distribution.  For the purposes of binary distribution
-   the "Copyright Notice" refers to the following language:
-   "Copyright (c) 1998 Sendmail, Inc.  All rights reserved."
-
-4. Neither the name of Sendmail, Inc. nor the University of California nor
-   the names of their contributors may be used to endorse or promote
-   products derived from this software without specific prior written
-   permission.  The name "sendmail" is a trademark of Sendmail, Inc.
-
-5. All redistributions must comply with the conditions imposed by the
-   University of California on certain embedded code, whose copyright
-   notice and conditions for redistribution are as follows:
-
-   (a) Copyright (c) 1988, 1993 The Regents of the University of
-       California.  All rights reserved.
-
-   (b) Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions
-       are met:
-
-      (i)   Redistributions of source code must retain the above copyright
-            notice, this list of conditions and the following disclaimer.
-
-      (ii)  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.
-
-      (iii) 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."
-
-      (iv)  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.
-
-6. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY
-   SENDMAIL, INC. 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 SENDMAIL, INC., THE REGENTS OF THE UNIVERSITY OF
-   CALIFORNIA 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 DAMAGES.
-
-(Version 8.6, last updated 6/24/1998)
-
- * End endmail LICENSE file.
- */
-
-
-/*
- * If "ll" format support is not possible -- e.g., the long long type isn't
- * supported -- define HAS_NO_LONG_LONG.
- */
-
-# ifndef lint
-static char copyright[] =
-"@(#) Copyright 2000 Purdue Research Foundation.\nAll rights reserved.\n";
-# endif /* !defined(lint) */
-
-#include <varargs.h>
-
-#if	defined(__STDC__)
-#define	_PROTOTYPE(function, params)	function params
-#else	/* !defined(__STDC__) */
-#define	_PROTOTYPE(function, params)	function()
-#endif /* defined(__STDC__) */
-
-
-/*
-**  SNPRINTF, VSNPRINT -- counted versions of printf
-**
-**	These versions have been grabbed off the net.  They have been
-**	cleaned up to compile properly and support for .precision and
-**	%lx has been added.
-*/
-
-/**************************************************************
- * Original:
- * Patrick Powell Tue Apr 11 09:48:21 PDT 1995
- * A bombproof version of doprnt (dopr) included.
- * Sigh.  This sort of thing is always nasty do deal with.  Note that
- * the version here does not include floating point...
- *
- * snprintf() is used instead of sprintf() as it does limit checks
- * for string length.  This covers a nasty loophole.
- *
- * The other functions are there to prevent NULL pointers from
- * causing nast effects.
- **************************************************************/
-
-/*static char _id[] = "$Id: snpf.c,v 1.5 2008/10/21 16:13:23 abe Exp $";*/
-
-
-/*
- * Local function prototypes
- */
-
-_PROTOTYPE(static void dopr,(char *bp, char *ep, char *fmt, va_list args));
-_PROTOTYPE(static void dopr_outch,(char **bp, char *ep, int c));
-_PROTOTYPE(static void dostr,(char **bp, char *ep, char *str, int));
-
-# if	!defined(HAS_NO_LONG_LONG)
-_PROTOTYPE(static void fmtllnum,(char **bp, char *ep, long long value,
-				 int base, int dosign, int ljust, int len,
-				 int zpad));
-# endif	/* !defined(HAS_NO_LONG_LONG) */
-
-_PROTOTYPE(static void fmtnum,(char **bp, char *ep, long value, int base,
-			       int dosign, int ljust, int len, int zpad));
-_PROTOTYPE(static void fmtstr,(char **bp, char *ep, char *value, int ljust,
-			       int len, int zpad,
-			       int maxwidth));
-
-
-/*
- * Local variables
- */
-
-static int Length;
-
-
-/*
- * snpf() -- count-controlled sprintf()
- */
-
-int
-snpf(va_alist)
-	va_dcl				/* requires at least three arguments:
-					 *   bp =  receiving buffer pointer
-					 *   ct =  length of buffer
-					 *   fmt = format string
-					 */
-{
-	va_list args;
-	char *bp, *fmt;
-	int ct, len;
-
-	va_start(args);
-	bp = va_arg(args, char *);
-	ct = va_arg(args, int);
-	fmt = va_arg(args, char *);
-	len = vsnpf(bp, ct, fmt, args);
-	va_end(args);
-	return(len);
-}
-
-
-/*
- * vsnpf() -- count-controlled vsprintf()
- */
-
-int
-vsnpf(str, count, fmt, args)
-	char *str;			/* result buffer */
-	int count;			/* size of buffer */
-	char *fmt;			/* format */
-	va_list args;			/* variable length argument list */
-{
-	char *ep = str + count - 1;
-
-	*str = '\0';
-	(void) dopr(str, ep, fmt, args);
-	if (count > 0)
-	    *ep = '\0';
-	return(Length);
-}
-
-
-/*
- * dopr() -- poor man's version of doprintf
- */
-
-
-static void
-dopr(bp, ep, fmt, args)
-	char *bp;			/* buffer start */
-	char *ep;			/* buffer end (start + length - 1) */
-	char *fmt;			/* format */
-	va_list args;			/* variable length argument list */
-{
-	int ch;
-	char ebuf[64];
-	int ebufl = (int)(sizeof(ebuf) - 1);
-	long value;
-	int longflag  = 0;
-	int longlongflag  = 0;
-	int pointflag = 0;
-	int maxwidth  = 0;
-	char *strvalue;
-	int ljust;
-	int len;
-	int zpad;
-	int zxflag = 0;
-
-# if	!defined(HAS_NO_LONG_LONG)
-	long long llvalue;
-# endif	/* !defined(HAS_NO_LONG_LONG) */
-
-	Length = 0;
-	while((ch = *fmt++)) {
-	    switch (ch) {
-	    case '%':
-		ljust = len = zpad = zxflag = maxwidth = 0;
-		longflag = longlongflag = pointflag = 0;
-
-nextch:
-
-		ch = *fmt++;
-		switch (ch) {
-		case '\0':
-		    dostr(&bp, ep, "**end of format**" , 0);
-		    return;
-		case '-':
-		    ljust = 1;
-		    goto nextch;
-		case '0': /* set zero padding if len not set */
-		    if ((len == 0) && !pointflag)
-			zpad = '0';
-		case '1':
-		case '2':
-		case '3':
-		case '4':
-		case '5':
-		case '6':
-		case '7':
-		case '8':
-		case '9':
-		    if (pointflag)
-			maxwidth = (maxwidth * 10) + (int)(ch - '0');
-		    else
-			 len = (len * 10) + (int)(ch - '0');
-		    goto nextch;
-		case '*':
-		   if (pointflag)
-			maxwidth = va_arg(args, int);
-		    else
-			len = va_arg(args, int);
-		    goto nextch;
-		case '#':
-		    zxflag = 1;
-		    goto nextch;
-		case '.':
-		    pointflag = 1;
-		    goto nextch;
-		case 'l':
-		    if (longflag) {
-			longflag = 0;
-			longlongflag = 1;
-			goto nextch;
-		    }
-		    longflag = 1;
-		    goto nextch;
-		case 'u':
-		case 'U':
-		    if (longlongflag) {
-
-# if	!defined(HAS_NO_LONG_LONG)
-			llvalue = va_arg(args, long long);
-			(void) fmtllnum(&bp,ep,llvalue,10,0,ljust,len,zpad);
-# else	/* defined(HAS_NO_LONG_LONG) */
-			(void) strncpy(ebuf, "ll is unsupported", ebufl);
-			ebuf[(int)ebufl] = '\0';
-			(void) dostr(&bp, ep, ebuf, 0);
-# endif	/* !defined(HAS_NO_LONG_LONG) */
-
-			break;
-		    }
-		    if (longflag)
-			value = va_arg(args, long);
-		    else
-			value = va_arg(args, int);
-		    (void) fmtnum(&bp, ep, value, 10,0, ljust, len, zpad);
-		    break;
-		case 'o':
-		case 'O':
-		    if (longlongflag) {
-
-# if	!defined(HAS_NO_LONG_LONG)
-			llvalue = va_arg(args, long long);
-			(void) fmtllnum(&bp,ep,llvalue,8,0,ljust,len,zpad);
-# else	/* defined(HAS_NO_LONG_LONG) */
-			(void) strncpy(ebuf, "ll is unsupported", ebufl);
-			ebuf[(int)ebufl] = '\0';
-			(void) dostr(&bp, ep, ebuf, 0);
-# endif	/* !defined(HAS_NO_LONG_LONG) */
-
-			break;
-		    }
-		    if (longflag)
-			value = va_arg(args, long);
-		    else
-			value = va_arg(args, int);
-		    (void) fmtnum(&bp, ep, value, 8,0, ljust, len, zpad);
-		    break;
-		case 'd':
-		case 'D':
-		    if (longlongflag) {
-
-# if	!defined(HAS_NO_LONG_LONG)
-			llvalue = va_arg(args, long long);
-			(void) fmtllnum(&bp,ep,llvalue,10,1,ljust,len,zpad);
-# else	/* defined(HAS_NO_LONG_LONG) */
-			(void) strncpy(ebuf, "ll is unsupported", ebufl);
-			ebuf[(int)ebufl] = '\0';
-			(void) dostr(&bp, ep, ebuf, 0);
-# endif	/* !defined(HAS_NO_LONG_LONG) */
-
-			break;
-		    }
-		    if (longflag)
-			value = va_arg(args, long);
-		    else
-			value = va_arg(args, int);
-		    (void) fmtnum(&bp, ep, value, 10,1, ljust, len, zpad);
-		    break;
-		case 'x':
-		    if (longlongflag) {
-
-# if	!defined(HAS_NO_LONG_LONG)
-			llvalue = va_arg(args, long long);
-			if (zxflag && llvalue) {
-			    (void) dostr(&bp, ep, "0x", 0);
-			    if (len >= 2)
-				len -= 2;
-			}
-			(void) fmtllnum(&bp,ep,llvalue,16,0,ljust,len,zpad);
-# else	/* defined(HAS_NO_LONG_LONG) */
-			(void) strncpy(ebuf, "ll is unsupported", ebufl);
-			ebuf[(int)ebufl] = '\0';
-			(void) dostr(&bp, ep, ebuf, 0);
-# endif	/* !defined(HAS_NO_LONG_LONG) */
-
-			break;
-		    }
-		    if (longflag)
-			value = va_arg(args, long);
-		    else
-			value = va_arg(args, int);
-		    if (zxflag && value) {
-			(void) dostr(&bp, ep, "0x", 0);
-			if (len >= 2)
-			    len -= 2;
-		    }
-		    (void) fmtnum(&bp, ep, value, 16,0, ljust, len, zpad);
-		    break;
-		case 'X':
-		    if (longlongflag) {
-
-# if	!defined(HAS_NO_LONG_LONG)
-			llvalue = va_arg(args, long long);
-			if (zxflag && llvalue) {
-			    (void) dostr(&bp, ep, "0x", 0);
-			    if (len >= 2)
-				len -= 2;
-			}
-			(void) fmtllnum(&bp,ep,llvalue,-16,0,ljust,len,zpad);
-# else	/* defined(HAS_NO_LONG_LONG) */
-			(void) strncpy(ebuf, "ll is unsupported", ebufl);
-			ebuf[(int)ebufl] = '\0';
-			(void) dostr(&bp, ep, ebuf, 0);
-# endif	/* !defined(HAS_NO_LONG_LONG) */
-
-			break;
-		    }
-		    if (longflag)
-			value = va_arg(args, long);
-		    else
-			value = va_arg(args, int);
-		    if (zxflag && value) {
-			(void) dostr(&bp, ep, "0x", 0);
-			if (len >= 2)
-			    len -= 2;
-		    }
-		    (void) fmtnum(&bp, ep, value,-16,0, ljust, len, zpad);
-		    break;
-		case 's':
-		    strvalue = va_arg(args, char *);
-		    if (maxwidth > 0 || !pointflag) {
-			if (pointflag && len > maxwidth)
-			    len = maxwidth; /* Adjust padding */
-			(void) fmtstr(&bp, ep, strvalue, ljust, len, zpad,
-				      maxwidth);
-		    }
-		    break;
-		case 'c':
-		    ch = va_arg(args, int);
-		    dopr_outch(&bp, ep, ch);
-		    break;
-		case '%':
-		    (void) dopr_outch(&bp, ep, ch);
-		    continue;
-		default:
-		    ebuf[0] = ch;
-		    (void) strncpy(&ebuf[1], " is unsupported", ebufl);
-		    ebuf[(int)ebufl] = '\0';
-		    (void) dostr(&bp, ep, ebuf, 0);
-		}
-		break;
-	    default:
-		(void) dopr_outch(&bp, ep, ch);
-		break;
-	    }
-	}
-	*bp = '\0';
-}
-
-
-# if	!defined(HAS_NO_LONG_LONG)
-/*
- * fmtllnum() -- format long long number for output
- */
-
-static void
-fmtllnum(bp, ep, value, base, dosign, ljust, len, zpad)
-	char **bp;			/* current buffer pointer */
-	char *ep;			/* end of buffer (-1) */
-	long long value;		/* number to format */
-	int base;			/* number base */
-	int dosign;			/* sign request */
-	int ljust;			/* left justfication request */
-	int len;			/* length request */
-	int zpad;			/* zero padding request */
-{
-	int signvalue = 0;
-	unsigned long long uvalue;
-	char convert[20];
-	int place = 0;
-	int padlen = 0; /* amount to pad */
-	int caps = 0;
-
-	uvalue = value;
-	if (dosign) {
-	    if (value < 0) {
-		signvalue = '-';
-		uvalue = -value;
-	    }
-	}
-	if (base < 0) {
-	    caps = 1;
-	    base = -base;
-	}
-	do {
-	    convert[place++] =
-		(caps ? "0123456789ABCDEF" : "0123456789abcdef")
-		    [uvalue % (unsigned)base];
-	    uvalue = (uvalue / (unsigned)base);
-	} while (uvalue && (place < (int)(sizeof(convert) - 1)));
-	convert[place] = 0;
-	padlen = len - place;
-	if (padlen < 0)
-	    padlen = 0;
-	if (ljust)
-	    padlen = -padlen;
-	if (zpad && padlen > 0) {
-	    if (signvalue) {
-		(void) dopr_outch(bp, ep, signvalue);
-		--padlen;
-		signvalue = 0;
-	    }
-	    while (padlen > 0) {
-		(void) dopr_outch(bp, ep, zpad);
-		--padlen;
-	    }
-	}
-	while (padlen > 0) {
-	    (void) dopr_outch(bp, ep, ' ');
-	     --padlen;
-	}
-	if (signvalue)
-	    (void) dopr_outch(bp, ep, signvalue);
-	while (place > 0)
-	    (void) dopr_outch(bp, ep, convert[--place]);
-	while (padlen < 0) {
-	    (void) dopr_outch(bp, ep, ' ');
-	    ++padlen;
-	}
-}
-# endif	/* !defined(HAS_NO_LONG_LONG) */
-
-
-/*
- * fmtnum() -- format number for output
- */
-
-static void
-fmtnum(bp, ep, value, base, dosign, ljust, len, zpad)
-	char **bp;			/* current buffer pointer */
-	char *ep;			/* end of buffer (-1) */
-	long value;			/* number to format */
-	int base;			/* number base */
-	int dosign;			/* sign request */
-	int ljust;			/* left justfication request */
-	int len;			/* length request */
-	int zpad;			/* zero padding request */
-{
-	int signvalue = 0;
-	unsigned long uvalue;
-	char convert[20];
-	int place = 0;
-	int padlen = 0; /* amount to pad */
-	int caps = 0;
-
-	uvalue = value;
-	if (dosign) {
-	    if (value < 0) {
-		signvalue = '-';
-		uvalue = -value;
-	    }
-	}
-	if (base < 0) {
-	    caps = 1;
-	    base = -base;
-	}
-	do {
-	    convert[place++] =
-		(caps ? "0123456789ABCDEF" : "0123456789abcdef")
-		    [uvalue % (unsigned)base];
-	    uvalue = (uvalue / (unsigned)base);
-	} while (uvalue && (place < (int)(sizeof(convert) - 1)));
-	convert[place] = 0;
-	padlen = len - place;
-	if (padlen < 0)
-	    padlen = 0;
-	if(ljust)
-	    padlen = -padlen;
-	if (zpad && padlen > 0) {
-	    if (signvalue) {
-		(void) dopr_outch(bp, ep, signvalue);
-		--padlen;
-		signvalue = 0;
-	    }
-	    while (padlen > 0) {
-		(void) dopr_outch(bp, ep, zpad);
-		--padlen;
-	    }
-	}
-	while (padlen > 0) {
-	    (void) dopr_outch(bp, ep, ' ');
-	     --padlen;
-	}
-	if (signvalue)
-	    (void) dopr_outch(bp, ep, signvalue);
-	while (place > 0)
-	    (void) dopr_outch(bp, ep, convert[--place]);
-	while (padlen < 0) {
-	    (void) dopr_outch(bp, ep, ' ');
-	    ++padlen;
-	}
-}
-
-
-/*
- * fmtstr() -- format string for output
- */
-
-static void
-fmtstr(bp, ep, value, ljust, len, zpad, maxwidth)
-	char **bp;			/* current buffer pointer */
-	char *ep;			/* end of buffer (-1) */
-	char *value;			/* string to format */
-	int ljust;			/* left justification request */
-	int len;			/* length request */
-	int zpad;			/* zero padding request */
-	int maxwidth;			/* maximum width request */
-{
-	int padlen, strlen;     /* amount to pad */
-
-	if (value == 0)
-	    value = "<NULL>";
-	for (strlen = 0; value[strlen]; ++ strlen)	/* strlen() */
-	    ;
-	if ((strlen > maxwidth) && maxwidth)
-	    strlen = maxwidth;
-	padlen = len - strlen;
-	if (padlen < 0)
-	    padlen = 0;
-	if (ljust)
-	    padlen = -padlen;
-	while (padlen > 0) {
-	    (void) dopr_outch(bp, ep, ' ');
-	    --padlen;
-	}
-	(void) dostr(bp, ep, value, maxwidth);
-	while (padlen < 0) {
-	    (void) dopr_outch(bp, ep, ' ');
-	    ++padlen;
-	}
-}
-
-
-/*
- * dostr() -- do string output
- */
-
-static void
-dostr(bp, ep, str, cut)
-	char **bp;			/* current buffer pointer */
-	char *ep;			/* end of buffer (-1) */
-	char *str;			/* string to output */
-	int cut;			/* limit on amount of string to output:
-					 *   0 == no limit */
-{
-	int f;
-
-	f = cut ? 1 : 0;
-	while (*str) {
-	    if (f) {
-		if (cut-- > 0)
-		    (void) dopr_outch(bp, ep, *str);
-	    } else
-		(void) dopr_outch(bp, ep, *str);
-	    str++;
-	}
-}
-
-
-/*
- * dopr_outch() -- output a character (or two)
- */
-
-static void
-dopr_outch(bp, ep, c)
-	char **bp;			/* current buffer pointer */
-	char *ep;			/* end of buffer (-1) */
-	int c;				/* character to output */
-{
-	register char *cp = *bp;
-
-	if (iscntrl(c) && c != '\n' && c != '\t') {
-	    c = '@' + (c & 0x1F);
-	    if (cp < ep)
-		*cp++ = '^';
-	    Length++;
-	}
-	if (cp < ep)
-	    *cp++ = c;
-	*bp = cp;
-	Length++;
-}
-
-#else	/* !defined(USE_LIB_SNPF) */
-char snpf_d1[] = "d"; char *snpf_d2 = snpf_d1;
-#endif	/* defined(USE_LIB_SNPF) */
diff --git a/lsof.h b/lsof.h
deleted file mode 100644
index ed8e4bd..0000000
--- a/lsof.h
+++ /dev/null
@@ -1,1108 +0,0 @@
-/*
- * lsof.h - common 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: lsof.h,v 1.70 2018/03/26 21:50:45 abe Exp $
- */
-
-
-#if	!defined(LSOF_H)
-#define	LSOF_H	1
-
-#include "machine.h"
-
-# if	!defined(FSV_DEFAULT)
-#define	FSV_DEFAULT	0
-# endif	/* !defined(FSV_DEFAULT) */
-
-#include "lsof_fields.h"
-
-#include <ctype.h>
-#include <errno.h>
-
-# if	defined(HASSETLOCALE)
-#include <locale.h>
-# endif	/* defined(HASSETLOCALE) */
-
-#include <netdb.h>
-#include <pwd.h>
-#include <stdio.h>
-
-#include <sys/stat.h>
-#include <sys/wait.h>
-
-
-/*
- * Definitions and structures that may be needed by dlsof.h
- */
-
-# if	!defined(INODETYPE)
-#define	INODETYPE	unsigned long	/* node number storage type */
-#define	INODEPSPEC	"l"		/* node number printf specification
-					 * modifier */
-# endif	/* !defined(INODETYPE) */
-
-struct l_dev {
-	dev_t rdev;			/* device */
-	INODETYPE inode;		/* inode number */
-	char *name;			/* name */
-	int v;				/* has been verified
-					 * (when DCUnsafe == 1) */
-};
-
-
-# if	defined(HASEPTOPTS)
-/*
- * End point definitions
- */
-
-#define	CHEND_PIPE	0x01		/* pipe endpoint ID */
-#define	CHEND_PTY	0x02		/* pseudoterminal endpoint ID */
-
-#  if	defined(HASUXSOCKEPT)
-#define	CHEND_UXS	0x04		/* UNIX socket endpoint ID */
-#  endif	/* defined(HASUXSOCKEPT) */
-
-#define	CHEND_NETS	0x08		/* INET socket endpoint ID */
-#define	CHEND_PSXMQ	0x10		/* Posix MQ endpoint ID */
-
-# if	defined(HASIPv6)
-#define	CHEND_NETS6	0x20		/* INET6 socket endpoint ID */
-# endif	/* defined(HASIPv6) */
-
-#define CHEND_EVTFD	0x40		/* eventfd endpoint ID */
-
-#define	EPT_PIPE	0x01		/* process has pipe file */
-#define	EPT_PIPE_END	0x02		/* process has pipe end point file */
-#define	EPT_PTY		0x04		/* process has a pseudoterminal file */
-#define	EPT_PTY_END	0x08		/* process has a pseudoterminal end
-					 * point file */
-
-#  if	defined(HASUXSOCKEPT)
-#define	EPT_UXS		0x10		/* process has a UNIX socket file */
-#define	EPT_UXS_END	0x20		/* process has a UNIX socket end point
-					 * file */
-#  endif	/* defined(HASUXSOCKEPT) */
-
-#define	EPT_NETS	0x40		/* process has a INET socket file */
-#define	EPT_NETS_END	0x80		/* process has a INET socket end point
-					 * file */
-
-#define	EPT_PSXMQ	0x100		/* process has a POSIX MQ file*/
-#define	EPT_PSXMQ_END	0x200		/* process has a POSIX MQ end point
-					 * file*/
-
-# if	defined(HASIPv6)
-#define	EPT_NETS6	0x400		/* process has a INET6 socket file */
-#define	EPT_NETS6_END	0x800		/* process has a INET6 socket end point
-					 * file */
-# endif	/* defined(HASIPv6) */
-
-#define	EPT_EVTFD	0x1000		/* process has a eventfd file*/
-#define	EPT_EVTFD_END	0x2000		/* process has a eventfd end point
-					 * file*/
-# endif	/* defined(HASEPTOPTS) */
-
-
-/*
- * FILE_FLAG column names
- */
-
-#define	FF_AIO		"AIO"
-#define	FF_APPEND	"AP"
-#define	FF_ASYNC	"ASYN"
-#define	FF_BLKANDSET	"BAS"
-#define	FF_BLKINUSE	"BKIU"
-#define	FF_BLKSEEK	"BSK"
-#define	FF_CIO		"CIO"
-#define	FF_CLONE	"CLON"
-#define	FF_CLREAD	"CLRD"
-#define	FF_COPYAVOID	"CA"
-#define	FF_CREAT	"CR"
-#define	FF_DATAFLUSH	"DFLU"
-#define	FF_DEFER	"DF"
-#define	FF_DEFERIND	"DFI"
-#define	FF_DELAY	"DLY"
-#define	FF_DIRECT	"DIR"
-#define	FF_DIRECTORY	"DTY"
-#define	FF_DOCLONE	"DOCL"
-#define	FF_DSYNC	"DSYN"
-#define	FF_EVTONLY	"EVO"
-#define	FF_EXCL		"EXCL"
-#define	FF_EXEC		"EX"
-#define	FF_EXLOCK	"XL"
-#define	FF_FILE_MBLK	"MBLK"
-#define	FF_FSYNC	"FSYN"
-#define	FF_GCFDEFER	"GCDF"
-#define	FF_GCFMARK	"GCMK"
-#define	FF_GENTTY	"GTTY"
-#define	FF_HASLOCK	"LCK"
-#define	FF_HUP		"HUP"
-#define	FF_KERNEL	"KERN"
-#define	FF_KIOCTL	"KIOC"
-#define	FF_LARGEFILE	"LG"
-#define	FF_MARK		"MK"
-#define	FF_MOUNT	"MNT"
-#define	FF_MSYNC	"MSYN"
-#define	FF_NBDRM	"NBDR"
-#define	FF_NBIO		"NBIO"
-#define	FF_NBLOCK	"NB"
-#define	FF_NBUF		"NBF"
-#define	FF_NMFS		"NMFS"
-#define	FF_NDELAY	"ND"
-#define	FF_NET		"NET"
-#define	FF_NOATM	"NATM"
-#define	FF_NOCACHE	"NC"
-#define	FF_NOCTTY	"NTTY"
-#define	FF_NODSYNC	"NDSY"
-#define	FF_NOFOLNK	"NFLK"
-#define	FF_NOTOSTOP	"NOTO"
-#define	FF_NSHARE	"NSH"
-#define	FF_OLRMIRROR	"OLRM"
-#define	FF_PATH		"PATH"
-#define	FF_POSIX_AIO	"PAIO"
-#define	FF_POSIX_PIPE	"PP"
-#define	FF_RAIOSIG	"RAIO"
-#define	FF_RCACH	"RC"
-#define	FF_RDWR		"RW"
-#define	FF_READ		"R"
-#define	FF_REVOKED	"REV"
-#define	FF_RSHARE	"RSH"
-#define	FF_RSYNC	"RSYN"
-#define	FF_SETBLK	"BL"
-#define	FF_SHLOCK	"SL"
-#define	FF_SNAP		"SNAP"
-#define	FF_SOCKET	"SOCK"
-#define	FF_SQTSH1	"SQS1"
-#define	FF_SQTSH2	"SQS2"
-#define	FF_SQTREPAIR	"SQR"
-#define	FF_SQTSH	"SQSH"
-#define	FF_SQTSVM	"SQSV"
-#define	FF_STOPIO	"STPI"
-#define	FF_SYNC		"SYN"
-#define	FF_SYNCRON	"SWR"
-#define	FF_TCP_MDEVONLY	"TCPM"
-#define	FF_TERMIO	"TIO"
-#define	FF_TMPFILE	"TMPF"
-#define	FF_TRUNC	"TR"
-#define	FF_VHANGUP	"VH"
-#define	FF_VTEXT	"VTXT"
-#define	FF_WAKEUP	"WKUP"
-#define	FF_WAITING	"WTG"
-#define	FF_WRITE	"W"
-
-
-/*
- * Process open file flag names
- */
-
-#define	POF_ALLOCATED	"ALLC"
-#define	POF_BNRD	"BR"
-#define	POF_BNWR	"BW"
-#define POF_BNHUP	"BHUP"
-#define	POF_CLOEXEC	"CX"
-#define	POF_CLOSING	"CLSG"
-#define	POF_FDLOCK	"LCK"
-#define	POF_INUSE	"USE"
-#define	POF_MAPPED	"MP"
-#define	POF_FSHMAT	"SHMT"
-#define	POF_RESERVED	"OPIP"
-#define	POF_RSVWT	"RSVW"
-
-
-/*
- * Cross-over (-x) option values
- */
-
-#define	XO_FILESYS	0x1		/* file system mount points */
-#define	XO_SYMLINK	0x2		/* symbolic links */
-#define	XO_ALL		(XO_FILESYS | XO_SYMLINK)
-
-#include "dlsof.h"
-
-#include <sys/types.h>			/* just in case -- because utmp.h
-					 * may need it */
-#include "./regex.h"
-
-# if	defined(EMPTY)
-#undef	EMPTY
-# endif	/* defined(EMPTY) */
-
-# if	defined(HASUTMPX)
-#include <utmpx.h>
-# else	/* !defined(HASUTMPX) */
-#include <utmp.h>
-# endif	/* defined(HASUTMPX) */
-
-extern int errno;
-extern char *optarg;
-extern int optind;
-
-#define	ACCESSERRFMT	"%s: WARNING: access %s: %s\n"
-
-# if	defined(HASDCACHE)
-#define	CRC_POLY	0120001 	/* CRC-16 polynomial */
-#define	CRC_TBLL	256		/* crc table length for software */
-#define	CRC_BITS	8		/* number of bits contributing */
-# endif	/* defined(HASDCACHE) */
-#define	CMDL		9		/* maximum number of characters from
-					 * command name to print in COMMAND
-					 * column */
-#define	CWD		" cwd"		/* current working directory fd name */
-#define	FDLEN		8		/* fd printing array length */
-#define	FSV_FA		0x1		/* file struct addr status */
-#define	FSV_CT		0x2		/* file struct count status */
-#define	FSV_FG		0x4		/* file struct flags */
-#define	FSV_NI		0x8		/* file struct node ID status */
-
-# if	!defined(GET_MAJ_DEV)
-#define	GET_MAJ_DEV	major		/* if no dialect specific macro has
-					 * been defined, use standard major()
-					 * macro */
-# endif	/* !defined(GET_MAJ_DEV) */
-
-# if	!defined(GET_MIN_DEV)
-#define	GET_MIN_DEV	minor		/* if no dialect specific macro has
-					 * been defined, use standard minor()
-					 * macro */
-# endif	/* !defined(GET_MIN_DEV) */
-
-# if	defined(HASSELINUX)
-#define	HASHCNTX	128		/* security context hash bucket count
-					 * -- MUST BE A POWER OF 2!!! */
-# endif	/* defined(HASSELINUX) */
-
-# if	defined(HASZONES)
-#define	HASHZONE	128		/* zone hash bucket count -- MUST BE
-					 * A POWER OF 2!!! */
-# endif	/* defined(HASZONES) */
-
-#define	IDINCR		10		/* PID/PGID table malloc() increment */
-
-# if	!defined(INADDR_LOOPBACK)
-#define	INADDR_LOOPBACK	(u_long)0x7f000001
-# endif	/* !defined(INADDR_LOOPBACK) */
-
-#define	IPROTOL		8		/* Internet protocol length */
-
-# if	!defined(KA_T_FMT_X)
-#define	KA_T_FMT_X	"0x%08lx"	/* format for printing kernel
-					 * addresses in 0x... format */
-# endif	/* !defined(KA_T_FMT_X) */
-
-# if	!defined(LOGINML)
-#  if	defined(HASUTMPX)
-static struct utmpx dummy_utmp;		/* to get login name length */
-#define	LOGINML		sizeof(dummy_utmp.ut_user)
-					/* login name length */
-#  else	/* !defined(HASUTMPX) */
-static struct utmp dummy_utmp;		/* to get login name length */
-#define	LOGINML		sizeof(dummy_utmp.ut_name)
-					/* login name length */
-#  endif	/* defined(HASUTMPX) */
-# endif	/* !defined(LOGINML) */
-
-#define	LPROCINCR	128		/* Lproc[] allocation increment */
-#define	LSOF_GITHUB_URL	"https://github.com/lsof-org"
-#define	LSOF_REPO	"lsof"
-#define	LSOF_BRANCH	"master"
-#define	LSOF_REPO_URL	LSOF_GITHUB_URL "/" LSOF_REPO
-#define	LSOF_FAQ_URL	LSOF_REPO_URL "/blob/" LSOF_BRANCH "/00FAQ"
-#define	LSOF_MAN_URL	LSOF_REPO_URL "/blob/" LSOF_BRANCH "/Lsof.8"
-#define	MIN_AF_ADDR	sizeof(struct in_addr)
-					/* minimum AF_* address length */
-
-# if	defined(HASIPv6)
-#define	MAX_AF_ADDR	sizeof(struct in6_addr)
-					/* maximum AF_* address length */
-# else	/* !defined(HASIPv6) */
-#define	MAX_AF_ADDR	MIN_AF_ADDR	/* maximum AF_* address length */
-# endif	/* defined(HASIPv6) */
-
-#define	MAXDCPATH	4		/* paths in DCpath[] */
-#define	MAXNWAD		100		/* maximum network addresses */
-
-# if	!defined(MEMMOVE)
-#define	MEMMOVE		memmove
-# endif	/* !defined*MEMMOVE) */
-
-#define	N_REGLR		0		/* regular file system node */
-#define	N_AFS		1		/* AFS node */
-#define	N_AFPFS		2		/* Apple Darwin AppleShare */
-#define	N_ANON_INODE	3		/* Linux anon_inodefs node */
-#define	N_AUSX		4		/* Auspex LFS node */
-#define	N_AUTO		5		/* automount node */
-#define	N_BLK		6		/* block device node */
-#define	N_CACHE		7		/* cached file system node */
-#define	N_CDFS		8		/* CD-ROM node */
-#define	N_CFS		9		/* CFS node */
-#define	N_CHR		10		/* character device node */
-#define	N_COM		11		/* streams common device node */
-#define	N_CTFSADIR	12		/* Solaris CTFS adir node */
-#define	N_CTFSBUND	13		/* Solaris CTFS bundle node */
-#define	N_CTFSCDIR	14		/* Solaris CTFS cdir node */
-#define	N_CTFSCTL	15		/* Solaris CTFS ctl node */
-#define	N_CTFSEVT	16		/* Solaris CTFS events node */
-#define	N_CTFSLATE	17		/* Solaris CTFS latest node */
-#define	N_CTFSROOT	18		/* Solaris CTFS root node */
-#define	N_CTFSSTAT	19		/* Solaris CTFS status node */
-#define	N_CTFSSYM	20		/* Solaris CTFS symbolic node */
-#define	N_CTFSTDIR	21		/* Solaris CTFS type node */
-#define	N_CTFSTMPL	22		/* Solaris CTFS template node */
-#define	N_DEV		23		/* DEV FS node */
-#define	N_DOOR		24		/* DOOR node */
-#define	N_FD		25		/* FD node */
-#define	N_FIFO		26		/* FIFO node */
-#define	N_HSFS		27		/* High Sierra node */
-#define	N_KERN		28		/* BSD /kern node */
-#define	N_LOFS		29		/* loopback node */
-#define	N_MNT		30		/* mount file system device node */
-#define	N_MPC		31		/* multiplexed device node */
-#define	N_MVFS		32		/* multi-volume file system node (?) */
-#define	N_NFS		33		/* NFS node */
-#define	N_NFS4		34		/* NFS version 4 node */
-#define	N_NM		35		/* named file system node */
-#define	N_OBJF		36		/* objfs file system node */
-#define	N_PCFS		37		/* PC file system node */
-#define	N_PIPE		38		/* pipe device node */
-#define	N_PORT		39		/* port node */
-#define	N_PROC		40		/* /proc node */
-#define	N_PSEU		41		/* pseudofs node */
-#define	N_SAMFS		42		/* Solaris SAM-FS */
-#define	N_SANFS		43		/* AIX SANFS */
-#define	N_SDEV		44		/* Solaris sdev file system node */
-#define	N_SHARED	45		/* Solaris sharedfs */
-#define	N_SOCK		46		/* sock_vnodeops node */
-#define	N_SPEC		47		/* spec_vnodeops node */
-#define	N_STREAM	48		/* stream node */
-#define	N_TMP		49		/* tmpfs node */
-#define	N_UFS		50		/* UNIX file system node */
-#define	N_UNKN		51		/* unknown node type */
-#define	N_VXFS		52		/* Veritas file system node */
-#define	N_XFS		53		/* XFS node */
-#define	N_ZFS		54		/* ZFS node */
-#define	N_MQUEUE	55		/* Posix mqueue node on Linux */
-
-# if	!defined(OFFDECDIG)
-#define	OFFDECDIG	8		/* maximum number of digits in the
-					 * offset decimal form (0t...) */
-# endif	/* !defined(OFFDECDIG) */
-
-# if	!defined(USELOCALREADDIR)
-#define	CloseDir	closedir	/* use standard closedir() */
-#define	OpenDir		opendir		/* use standard opendir() */
-#define	ReadDir		readdir		/* use standard readdir() */
-# endif	/* !defined(USELOCALREADDIR) */
-
-#define	RPTTM		15		/* default repeat seconds */
-#define	RTD		" rtd"		/* root directory fd name */
-#define	TASKCMDL	9		/* maximum number of characters from
-					 * command name to print in TASKCMD
-					 * column */
-#define TCPTPI_FLAGS	0x0001		/* report TCP/TPI socket options and
-					 * state, and TCP_NODELAY state */
-#define	TCPTPI_QUEUES	0x0002		/* report TCP/TPI queue lengths */
-#define	TCPTPI_STATE	0x0004		/* report TCP/TPI state */
-#define TCPTPI_WINDOWS	0x0008		/* report TCP/TPI window sizes */
-#define	TCPTPI_ALL	(TCPTPI_QUEUES | TCPTPI_STATE | TCPTPI_WINDOWS)
-					/* report all TCP/TPI info */
-#define	TCPUDPALLOC	32		/* allocation amount for TCP and UDP
-					 * state tables */
-#define	TMLIMIT		15		/* readlink() & stat() timeout sec */
-#define	TMLIMMIN	2		/* minimum timeout */
-#define	TYPEL		8		/* type character length */
-#define	UIDCACHEL	1024		/* UID cache length */
-#define	UIDINCR		10		/* UID table malloc() increment */
-#define	USERPRTL	8		/* UID/login print length limit */
-
-# if	!defined(SZOFFTYPE)
-#define	SZOFFTYPE	unsigned long	/* type for size and offset */
-#undef	SZOFFPSPEC
-#define	SZOFFPSPEC	"l"		/* SZOFFTYPE printf specification
-					 * modifier */
-# endif	/* !defined(SZOFFTYPE) */
-
-# if	!defined(TIMEVAL_LSOF)
-#define	TIMEVAL_LSOF	timeval
-# endif	/* !defined(TIMEVAL_LSOF) */
-
-# if	!defined(XDR_PMAPLIST)
-#define	XDR_PMAPLIST	xdr_pmaplist
-# endif	/* !defined(XDR_PMAPLIST) */
-
-# if	!defined(XDR_VOID)
-#define	XDR_VOID	xdr_void
-# endif	/* !defined(XDR_VOID) */
-
-
-/*
- * Output title definitions
- */
-
-#define	CMDTTL		"COMMAND"
-extern int CmdColW;
-#define	CNTXTTL		"SECURITY-CONTEXT"
-extern int CntxColW;
-#define DEVTTL		"DEVICE"
-extern int DevColW;
-#define	FCTTL		"FCT"
-extern int FcColW;
-#define	FDTTL 		"FD"
-extern int FdColW;
-#define	FGTTL		"FILE-FLAG"
-extern int FgColW;
-#define	FSTTL		"FILE-ADDR"
-extern int FsColW;
-#define	NITTL		"NODE-ID"
-extern int NiColW;
-extern char *NiTtl;
-#define	NLTTL		"NLINK"
-extern int NlColW;
-#define	NMTTL		"NAME"
-extern int NmColW;
-#define NODETTL		"NODE"
-extern int NodeColW;
-#define OFFTTL		"OFFSET"
-#define	PGIDTTL		"PGID"
-extern int PgidColW;
-#define	PIDTTL		"PID"
-extern int PidColW;
-#define	PPIDTTL		"PPID"
-extern int PpidColW;
-#define SZTTL		"SIZE"
-#define	SZOFFTTL	"SIZE/OFF"
-extern int SzOffColW;
-#define	TASKCMDTTL	"TASKCMD"
-extern	int TaskCmdColW;
-#define	TASKTIDTTL	"TID"
-extern	int TaskTidColW;
-#define TYPETTL		"TYPE"
-extern int TypeColW;
-#define	USERTTL		"USER"
-extern int UserColW;
-#define ZONETTL		"ZONE"
-extern int ZoneColW;
-
-
-/*
- * Selection flags
- */
-
-#define	PS_PRI		1		/* primary process selection -- e.g.,
-					 * by PID or UID */
-#define	PS_SEC		2		/* secondary process selection -- e.g.,
-					 * by directory or file */
-#define	SELCMD		0x0001		/* select process by command name */
-#define	SELCNTX		0x0002		/* select security context (-Z) */
-#define	SELFD		0x0004		/* select file by descriptor name */
-#define	SELNA		0x0008		/* select socket by address (-i@...) */
-#define	SELNET		0x0010		/* select Internet socket files (-i) */
-#define	SELNFS		0x0020		/* select NFS files (-N) */
-#define	SELNLINK	0x0040		/* select based on link count */
-#define	SELNM		0x0080		/* select by name */
-#define	SELPGID		0x0100		/* select process group IDs (-g) */
-#define	SELPID		0x0200		/* select PIDs (-p) */
-#define	SELUID		0x0400		/* select UIDs (-u) */
-#define	SELUNX		0x0800		/* select UNIX socket (-U) */
-#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	SELUXSINFO	0x10000		/* selected for UNIX socket info;
-					 * cleared in link_lfile() */
-#define	SELPTYINFO	0x20000		/* selected for pseudoterminal info;
-					 * cleared in link_lfile() */
-#define	SELNETSINFO	0x40000		/* selected for INET socket info;
-					 * cleared in link_lfile() */
-#define SELPSXMQINFO	0x80000		/* selected for POSIX MQ socket info;
-					   cleared in link_lfile() */
-#define	SELNETS6INFO	0x100000	/* selected for INET6 socket info;
-					 * cleared in link_lfile() */
-#define	SELEVTFDINFO	0x200000	/* selected for evetnfd 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 */
-#define	SELFILE		(SELFD|SELNFS|SELNLINK|SELNM)	/* file selecters */
-#define	SELNW		(SELNA|SELNET|SELUNX)		/* network selecters */
-
-
-/*
- * Exit Status
- */
-
-enum ExitStatus {
-	LSOF_SUCCESS,
-	LSOF_ERROR,
-};
-#define LSOF_SEARCH_FAILURE (FsearchErr? LSOF_ERROR: LSOF_SUCCESS)
-
-
-/*
- * Structure definitions
- */
-
-# if	defined(HAS_AFS)
-struct afsnode {			/* AFS pseudo-node structure */
-	dev_t dev;
-	unsigned char ino_st;		/* 1 if inode has a value */
-	unsigned char nlink_st;		/* 1 if nlink has a value */
-	INODETYPE inode;
-	unsigned long size;
-	long nlink;
-};
-# endif	/* defined(HAS_AFS) */
-
-extern int AllProc;
-
-# if	defined(HAS_STD_CLONE)
-struct clone {
-	int dx;			/* index of device entry in Devtp[] */
-	struct clone *next;	/* forward link */
-};
-extern struct clone *Clone;
-# endif	/* defined(HAS_STD_CLONE) */
-
-# if	defined(HASNLIST)
-struct drive_Nl {			/* data to drive build_Nl() */
-	char *nn;			/* nickname for lookups */
-	char *knm;			/* kernel variable for name list */
-};
-extern struct drive_Nl Drive_Nl[];	/* defined in dstore.c */
-# endif	/* defined(HASNLIST) */
-
-
-/*
- * Global storage definitions (including their structure definitions)
- */
-
-typedef struct efsys_list {
-	char *path;			/* path to file system for which kernel
-					 * blocks are to be eliminated */
-	int pathl;			/* path length */
-	int rdlnk;			/* avoid readlink(2) if non-zero */
-	struct mounts *mp;		/* local mount table entry pointer */
-	struct efsys_list *next;	/* next efsys_list entry pointer */
-} efsys_list_t;
-extern efsys_list_t *Efsysl;		/* file systems for which kernel blocks
-					 * are to be eliminated */
-
-struct int_lst {
-	int i;				/* integer argument */
-	int f;				/* find state -- meaningful only if
-					 * x == 0 */
-	int x;				/* excluded state */
-};
-
-typedef struct lsof_rx {		/* regular expression table entry */
-	char *exp;			/* original regular expression */
-	regex_t cx;			/* compiled expression */
-	int mc;				/* match count */
-} lsof_rx_t;
-extern lsof_rx_t *CmdRx;
-extern int NCmdRxU;
-
-# if	defined(HASFSTRUCT)
-struct pff_tab {			/* print file flags table structure */
-	long val;			/* flag value */
-	char *nm;			/* name to print for flag */
-};
-# endif	/* defined(HASFSTRUCT) */
-
-
-struct seluid {
-	uid_t uid;			/* User ID */
-	char *lnm;			/* specified login name (NULL = none) */
-	unsigned char excl;		/* excluded state */
-	unsigned char f;		/* selected User ID find state
-					 * (meaningful only if excl == 0) */
-};
-
-# if	defined(HASBLKDEV)
-extern struct l_dev *BDevtp, **BSdev;
-extern int BNdev;
-# endif	/* defined(HASBLKDEV) */
-
-extern int CkPasswd;
-
-struct str_lst {
-	char *str;			/* string */
-	int len;			/* string length */
-	short f;			/* selected string find state */
-	short x;			/* exclusion (if non-zero) */
-	struct str_lst *next;		/* next list entry */
-};
-extern struct str_lst *Cmdl;
-extern int CmdLim;
-extern int Cmdni;
-extern int Cmdnx;
-
-# if	defined(HASSELINUX)
-typedef struct cntxlist {
-	char *cntx;			/* zone name */
-	int f;				/* "find" flag (used only in CntxArg) */
-	struct cntxlist *next;		/* next zone hash entry */
-} cntxlist_t;
-extern cntxlist_t *CntxArg;
-extern int CntxStatus;
-# endif	/* defined(HASSELINUX) */
-
-# if	defined(HASDCACHE)
-extern unsigned DCcksum;
-extern int DCfd;
-extern FILE *DCfs;
-extern char *DCpathArg;
-extern char *DCpath[];
-extern int DCpathX;
-extern int DCrebuilt;
-extern int DCstate;
-extern int DCunsafe;
-# endif	/* defined(HASDCACHE) */
-
-extern int DChelp;
-extern dev_t DevDev;
-extern struct l_dev *Devtp;
-extern char **Dstk;
-extern int Dstkn;
-extern int Dstkx;
-extern int ErrStat;
-extern uid_t Euid;
-extern int Fand;
-extern int Fblock;
-extern int Fcntx;
-extern int Ffield;
-extern int Ffilesys;
-extern int Fhelp;
-extern int Fhost;
-
-# if	defined(HASNCACHE)
-extern int Fncache;
-extern int NcacheReload;
-# endif	/* defined(HASNCACHE) */
-
-extern int Fnet;
-extern int FnetTy;
-extern int Fnfs;
-extern int Fnlink;
-extern int Foffset;
-extern int Fovhd;
-extern int FeptE;
-
-extern int Fport;
-
-# if	!defined(HASNORPC_H)
-extern int FportMap;
-# endif	/* !defined(HASNORPC_H) */
-
-extern int Fpgid;
-extern int Fppid;
-extern int FsearchErr;
-extern int Fsize;
-extern int Fsv;
-extern int FsvByf;
-extern int FsvFlagX;
-extern int Ftask;
-extern int Ftcptpi;
-extern int Fterse;
-extern int Funix;
-extern int Futol;
-extern int Fverbose;
-extern int Fwarn;
-
-# if	defined(HASXOPT_VALUE)
-extern int Fxopt;
-# endif	/* defined(HASXOPT_VALUE) */
-
-extern int Fxover;
-extern int Fzone;
-
-struct fd_lst {
-	char *nm;			/* file descriptor name -- range if
-					 * NULL */
-	int lo;				/* range start (if nm NULL) */
-	int hi;				/* range end (if nm NULL) */
-	struct fd_lst *next;
-};
-extern struct fd_lst *Fdl;
-extern int FdlTy;			/* Fdl[] type: -1 == none
-					 *		0 == include
-					 *		1 == exclude */
-
-struct fieldsel {
-	char id;			/* field ID character */
-	unsigned char st;		/* field status */
-	char *nm;			/* field name */
-	int *opt;			/* option variable address */
-	int ov;				/* value to OR with option variable */
-};
-extern struct fieldsel FieldSel[];
-
-extern int Hdr;
-
-enum IDType {PGID, PID};
-extern int  IgnTasks;
-extern char *InodeFmt_d;
-extern char *InodeFmt_x;
-extern int LastPid;
-
-struct lfile {
-	char access;
-	char lock;
-	unsigned char dev_def;		/* device number definition status */
-	unsigned char inp_ty;		/* inode/iproto type
-					 *	0: neither inode nor iproto
-					 *	1: print inode in decimal
-					 *	2: iproto contains string
-					 *      3: print inode in hex
-					 */
-	unsigned char is_com;		/* common stream status */
-	unsigned char is_nfs;		/* NFS file status */
-	unsigned char is_stream;	/* stream device status */
-
-# if	defined(HASVXFS) && defined(HASVXFSDNLC)
-	unsigned char is_vxfs;		/* VxFS file status */
-# endif	/* defined(HASVXFS) && defined(HASVXFSDNLC) */
-
-	unsigned char lmi_srch;		/* local mount info search status:
-					 * 1 = printname() search required */
-
-# if	defined(HASMNTSTAT)
-	unsigned char mnt_stat;		/* mount point stat(2) status */
-# endif	/* defined(HASMNTSTAT) */
-
-	unsigned char nlink_def;	/* link count definition status */
-	unsigned char off_def;		/* offset definition status */
-
-# if	defined(HASEPTOPTS)
-	unsigned char chend;		/* communication channel endpoint
-					 * file */
-	int eventfd_id;			/* evntfd id taken from
-					   /proc/$pid/fdinfo */
-#  if	defined(HASPTYEPT)
-	int tty_index;			/* pseudoterminal index of slave side
-					 * (if this is the master side) */
-#  endif	/* defined(HASPTYEPT) */
-# endif	/* defined(HASEPTOPTS) */
-
-	unsigned char rdev_def;		/* rdev definition status */
-	unsigned char sz_def;		/* size definition status */
-
-# if	defined(HASFSTRUCT)
-	unsigned char fsv;		/* file struct value status */
-# endif	/* defined(HASFSTRUCT) */
-
-	char fd[FDLEN];
-	char iproto[IPROTOL];
-	char type[TYPEL];
-	unsigned int sf;		/* select flags -- SEL* symbols */
-	int ch;				/* VMPC channel: -1 = none */
-	int ntype;			/* node type -- N_* value */
-	SZOFFTYPE off;
-	SZOFFTYPE sz;
-	dev_t dev;
-	dev_t rdev;
-	INODETYPE inode;
-	long nlink;			/* link count */
-	char *dev_ch;
-	char *fsdir;			/* file system directory */
-	char *fsdev;			/* file system device */
-
-# if	defined(HASFSINO)
-	INODETYPE fs_ino;		/* file system inode number */
-# endif	/* defined HASFSINO) */
-
-	struct linaddr {		/* local Internet address information */
-	    int af;			/* address family: 0 for none; AF_INET;
-					 * or AF_INET6 */
-	    int p;			/* port */
-	    union {
-		struct in_addr a4;	/* AF_INET Internet address */
-
-# if	defined(HASIPv6)
-		struct in6_addr a6;	/* AF_INET6 Internet address */
-# endif	/* defined(HASIPv6) */
-
-	    } ia;
-	} li[2];			/* li[0]: local
-					 * li[1]: foreign */
-	struct ltstate {		/* local TCP/TPI state */
-	    int type;			/* state type:
-					 *   -1 == none
-					 *    0 == TCP
-					 *    1 == TPI or socket (SS_*) */
-	    union {
-		int i;			/* integer state */
-		unsigned int ui;	/* unsigned integer state */
-	    } state;
-
-# if	defined(HASSOOPT)
-	    unsigned char pqlens;	/* pqlen status: 0 = none */
-	    unsigned char qlens;	/* qlen status:  0 = none */
-	    unsigned char qlims;	/* qlim status:  0 = none */
-	    unsigned char rbszs;	/* rbsz status:  0 = none */
-	    unsigned char sbszs;	/* sbsz status:  0 = none */
-	    int kai;			/* TCP keep-alive interval */
-	    int ltm;			/* TCP linger time */
-	    unsigned int opt;		/* socket options */
-	    unsigned int pqlen;		/* partial connection queue length */
-	    unsigned int qlen;		/* connection queue length */
-	    unsigned int qlim;		/* connection queue limit */
-	    unsigned long rbsz;		/* receive buffer size */
-	    unsigned long sbsz;		/* send buffer size */
-# endif	/* defined(HASSOOPT) */
-
-# if	defined(HASSOSTATE)
-	    unsigned int ss;		/* socket state */
-#  if	defined(HASSBSTATE)
-	    unsigned int sbs_rcv;	/* receive socket buffer state */
-	    unsigned int sbs_snd;	/* send socket buffer state */
-#  endif	/* defined(HASSBSTATE) */
-# endif	/* defined(HASSOSTATE) */
-
-# if	defined(HASTCPOPT)
-	    unsigned int topt;		/* TCP options */
-	    unsigned char msss;		/* mss status: 0 = none */
-	    unsigned long mss;		/* TCP maximum segment size */
-# endif	/* defined(HASTCPOPT) */
-
-# if	defined(HASTCPTPIQ)
-	    unsigned long rq;		/* receive queue length */
-	    unsigned long sq;		/* send queue length */
-	    unsigned char rqs;		/* rq status: 0 = none */
-	    unsigned char sqs;		/* sq status: 0 = none */
-# endif	/* defined(HASTCPTPIQ) */
-
-# if	defined(HASTCPTPIW)
-	    unsigned char rws;		/* rw status: 0 = none */
-	    unsigned char wws;		/* ww status: 0 = none */
-	    unsigned long rw;		/* read window size */
-	    unsigned long ww;		/* write window size */
-# endif	/* defined(HASTCPTPIW) */
-
-	} lts;
-	char *nm;
-	char *nma;			/* NAME column addition */
-
-# if	defined(HASNCACHE) && HASNCACHE<2
-	KA_T na;			/* file structure's node address */
-# endif	/* defined(HASNCACHE) && HASNCACHE<2 */
-
-# if	defined(HASNCACHE) && defined(HASNCVPID)
-	unsigned long id;		/* capability ID */
-# endif	/* defined(HASNCACHE) && defined(HASNCVPID) */
-
-# if	defined(HASLFILEADD)
-	HASLFILEADD
-# endif	/* defined(HASLFILEADD) */
-
-# if	defined(HASFSTRUCT)
-	KA_T fsa;			/* file structure address */
-	long fct;			/* file structure's f_count */
-	long ffg;			/* file structure's f_flag */
-	long pof;			/* process open-file flags */
-	KA_T fna;			/* file structure node address */
-# endif	/* defined(HASFSTRUCT) */
-
-	struct lfile *next;
-};
-extern struct lfile *Lf, *Plf;
-
-
-struct lproc {
-	char *cmd;			/* command name */
-
-# if	defined(HASSELINUX)
-	char *cntx;			/* security context */
-# endif	/* defined(HASSELINUX) */
-
-	short sf;			/* select flags -- SEL* symbols */
-	short pss;			/* state: 0 = not selected
-				 	 *	  1 = wholly selected
-				 	 *	  2 = partially selected */
-# if	defined(HASEPTOPTS)
-	short ept;			/* end point status -- EPT_* values */
-# endif	/* defined(HASEPTOPTS) */
-
-	int pid;			/* process ID */
-
-# if	defined(HASTASKS)
-	int tid;			/* task ID */
-	char *tcmd;			/* task command name */
-# endif	/* HASTASKS */
-
-	int pgid;			/* process group ID */
-	int ppid;			/* parent process ID */
-	uid_t uid;			/* user ID */
-
-# if	defined(HASZONES)
-	char *zn;			/* zone name */
-# endif	/* defined(HASZONES) */
-
-	struct lfile *file;		/* open files of process */
-};
-extern struct lproc *Lp, *Lproc;
-
-extern int MaxFd;
-extern char *Memory;
-extern int MntSup;
-extern char *MntSupP;
-
-# if	defined(HASPROCFS)
-extern struct mounts *Mtprocfs;
-# endif
-
-extern int Mxpgid;
-extern int Mxpid;
-extern int Mxuid;
-extern gid_t Mygid;
-extern int Mypid;
-extern uid_t Myuid;
-extern char *Namech;
-extern size_t Namechl;
-extern int Ndev;
-
-# if	defined(HASNLIST)
-#  if	!defined(NLIST_TYPE)
-#define	NLIST_TYPE	nlist
-#  endif	/* !defined(NLIST_TYPE) */
-extern struct NLIST_TYPE *Nl;
-extern int Nll;
-# endif	/* defined(HASNLIST) */
-extern long Nlink;
-extern int Nlproc;
-extern char *Nmlst;
-extern int Npgid;
-extern int Npgidi;
-extern int Npgidx;
-extern int Npid;
-extern int Npidi;
-extern int Npidx;
-extern int Npuns;
-extern int Ntype;
-extern int Nuid;
-extern int Nuidexcl;
-extern int Nuidincl;
-
-struct nwad {
-	char *arg;			/* argument */
-	char *proto;			/* protocol */
-	int af;				/* address family -- e.g.,
-					 * AF_INET, AF_INET6 */
-	unsigned char a[MAX_AF_ADDR];	/* address */
-	int sport;			/* starting port */
-	int eport;			/* ending port */
-	int f;				/* find state */
-	struct nwad *next;		/* forward link */
-};
-extern struct nwad *Nwad;
-
-extern int OffDecDig;
-extern char *Pn;
-
-# if	defined(HASFSTRUCT)
-extern struct pff_tab Pff_tab[];	/* file flags table */
-extern struct pff_tab Pof_tab[];	/* process open file flags table */
-# endif	/* defined(HASFSTRUCT) */
-
-# if	defined(HASPROCFS)
-struct procfsid {
-	pid_t pid;			/* search PID */
-	char *nm;			/* search name */
-	unsigned char f;		/* match found if == 1 */
-
-#  if	defined(HASPINODEN)
-	INODETYPE inode;		/* search inode number */
-#  endif	/* defined(HASPINODEN) */
-
-	struct procfsid *next;		/* forward link */
-};
-
-extern int Procfind;
-extern struct procfsid *Procfsid;
-extern int Procsrch;
-# endif	/* defined(HASPROCFS) */
-
-extern int PrPass;
-extern int RptTm;
-extern int RptMaxCount;
-extern struct l_dev **Sdev;
-extern int SelAll;
-extern int Selflags;
-extern int SelProc;
-extern int Setgid;
-extern int Selinet;
-extern int Setuidroot;
-extern struct sfile *Sfile;
-extern struct int_lst *Spgid;
-extern struct int_lst *Spid;
-extern struct seluid *Suid;
-extern char *SzOffFmt_0t;
-extern char *SzOffFmt_d;
-extern char *SzOffFmt_dv;
-extern char *SzOffFmt_x;
-extern int TaskCmdLim;
-extern int TaskPrtCmd;
-extern int TaskPrtTid;
-extern int TcpStAlloc;
-extern unsigned char *TcpStI;
-extern int TcpStIn;
-extern int TcpStOff;
-extern unsigned char *TcpStX;
-extern int TcpStXn;
-extern int TcpNstates;
-extern char **TcpSt;
-extern char Terminator;
-extern int TmLimit;
-extern int UdpStAlloc;
-extern unsigned char *UdpStI;
-extern int UdpStIn;
-extern int UdpStOff;
-extern unsigned char *UdpStX;
-extern int UdpStXn;
-extern int UdpNstates;
-extern char **UdpSt;
-
-# if	defined(HASZONES)
-typedef struct znhash {
-	char *zn;			/* zone name */
-	int f;				/* "find" flag (used only in ZoneArg) */
-	struct znhash *next;		/* next zone hash entry */
-} znhash_t;
-extern znhash_t **ZoneArg;
-# endif	/* defined(HASZONES) */
-
-#include "proto.h"
-#include "dproto.h"
-
-#endif	/* LSOF_H */
diff --git a/lsof.man b/lsof.man
deleted file mode 100644
index a670e53..0000000
--- a/lsof.man
+++ /dev/null
@@ -1,4 +0,0 @@
-LSOF(8)                     System Manager's Manual                    LSOF(8)
-
-       lsof - list open files
-
diff --git a/lsof_fields.h b/lsof_fields.h
deleted file mode 100644
index 8275f95..0000000
--- a/lsof_fields.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * lsof_field.sh - field ID characters for lsof output that can be parsed
- *		   (selected with -f or -F)
- */
-
-
-/*
- * 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: lsof_fields.h,v 1.14 2018/02/14 14:19:25 abe Exp $
- */
-
-
-#if	!defined(LSOF_FORMAT_H)
-#define	LSOF_FORMAT_H	1
-
-/*
- * Codes for output fields:
- *
- *	LSOF_FID_*	ID character
- *	LSOF_FIX_*	ID index
- *	LSOF_FNM_*	name
- *
- * A field is displayed in the form:
- *		<ID_character><data><field_terminator>
- *
- * Output fields are normally terminated with a NL ('\n'), but the field
- * terminator can be set to NUL with the -0 (zero) option to lsof.
- *
- * Field sets -- process-specific information or information specific
- * to a single file descriptor -- are terminated with NL when the field
- * terminator is NUL.
- */
-
-#define	LSOF_FID_ACCESS		'a'
-#define	LSOF_FIX_ACCESS		0
-#define	LSOF_FNM_ACCESS		"access: r = read; w = write; u = read/write"
-
-#define	LSOF_FID_CMD		'c'
-#define	LSOF_FIX_CMD		1
-#define	LSOF_FNM_CMD		"command name"
-
-#define	LSOF_FID_CT		'C'
-#define	LSOF_FIX_CT		2
-#define	LSOF_FNM_CT		"file struct share count"
-
-#define	LSOF_FID_DEVCH		'd'
-#define	LSOF_FIX_DEVCH		3
-#define	LSOF_FNM_DEVCH		"device character code"
-
-#define	LSOF_FID_DEVN		'D'
-#define	LSOF_FIX_DEVN		4
-#define	LSOF_FNM_DEVN		"major/minor device number as 0x<hex>"
-
-#define	LSOF_FID_FD		'f'
-#define	LSOF_FIX_FD		5
-#define	LSOF_FNM_FD		"file descriptor"
-
-#define	LSOF_FID_FA		'F'
-#define	LSOF_FIX_FA		6
-#define	LSOF_FNM_FA		"file struct address as 0x<hex>"
-
-#define	LSOF_FID_FG		'G'
-#define	LSOF_FIX_FG		7
-#define	LSOF_FNM_FG		"file flaGs"
-
-#define	LSOF_FID_INODE		'i'
-#define	LSOF_FIX_INODE		8
-#define	LSOF_FNM_INODE		"inode number"
-
-#define	LSOF_FID_NLINK		'k'
-#define	LSOF_FIX_NLINK		9
-#define	LSOF_FNM_NLINK		"link count"
-
-#define	LSOF_FID_TID		'K'
-#define	LSOF_FIX_TID		10
-#define	LSOF_FNM_TID		"task ID (TID)"
-
-#define	LSOF_FID_LOCK		'l'
-#define	LSOF_FIX_LOCK		11
-#define	LSOF_FNM_LOCK		"lock: r/R = read; w/W = write; u = read/write"
-
-#define	LSOF_FID_LOGIN		'L'
-#define	LSOF_FIX_LOGIN		12
-#define	LSOF_FNM_LOGIN		"login name"
-
-#define	LSOF_FID_MARK		'm'
-#define	LSOF_FIX_MARK		13
-#define	LSOF_FNM_MARK		"marker between repeated output"
-
-#define	LSOF_FID_TCMD		'M'
-#define	LSOF_FIX_TCMD		14
-#define	LSOF_FNM_TCMD		"task comMand name"
-
-#define	LSOF_FID_NAME		'n'
-#define	LSOF_FIX_NAME		15
-#define	LSOF_FNM_NAME		"comment, name, Internet addresses"
-
-#define	LSOF_FID_NI		'N'
-#define	LSOF_FIX_NI		16
-#define	LSOF_FNM_NI		"file struct node ID as 0x<hex>"
-
-#define	LSOF_FID_OFFSET		'o'
-#define	LSOF_FIX_OFFSET		17
-#define	LSOF_FNM_OFFSET		"file offset as 0t<dec> or 0x<hex>"
-
-#define	LSOF_FID_PID		'p'
-#define	LSOF_FIX_PID		18
-#define	LSOF_FNM_PID		"process ID (PID)"
-
-#define	LSOF_FID_PGID		'g'
-#define	LSOF_FIX_PGID		19
-#define	LSOF_FNM_PGID		"process group ID (PGID)"
-
-#define	LSOF_FID_PROTO		'P'
-#define	LSOF_FIX_PROTO		20
-#define	LSOF_FNM_PROTO		"protocol name"
-
-#define	LSOF_FID_RDEV		'r'
-#define	LSOF_FIX_RDEV		21
-#define	LSOF_FNM_RDEV		"raw device number as 0x<hex>"
-
-#define	LSOF_FID_PPID		'R'
-#define	LSOF_FIX_PPID		22
-#define	LSOF_FNM_PPID		"paRent PID"
-
-#define	LSOF_FID_SIZE		's'
-#define	LSOF_FIX_SIZE		23
-#define	LSOF_FNM_SIZE		"file size"
-
-#define	LSOF_FID_STREAM		'S'
-#define	LSOF_FIX_STREAM		24
-#define	LSOF_FNM_STREAM		"stream module and device names"
-
-#define	LSOF_FID_TYPE		't'
-#define	LSOF_FIX_TYPE		25
-#define	LSOF_FNM_TYPE		"file type"
-
-#define	LSOF_FID_TCPTPI		'T'
-#define	LSOF_FIX_TCPTPI		26
-#define	LSOF_FNM_TCPTPI		"TCP/TPI info"
-
-#define	LSOF_FID_UID		'u'
-#define	LSOF_FIX_UID		27
-#define	LSOF_FNM_UID		"user ID (UID)"
-
-#define	LSOF_FID_ZONE		'z'
-#define	LSOF_FIX_ZONE		28
-#define	LSOF_FNM_ZONE		"zone name"
-
-#define	LSOF_FID_CNTX		'Z'
-#define	LSOF_FIX_CNTX		29
-#define	LSOF_FNM_CNTX		"security context"
-
-#define	LSOF_FID_TERM		'0'
-#define	LSOF_FIX_TERM		30
-#define	LSOF_FNM_TERM		"(zero) use NUL field terminator instead of NL"
-
-#endif	/* !defined(LSOF_FORMAT_H) */
diff --git a/m4/.gitignore b/m4/.gitignore
new file mode 100644
index 0000000..f10a1b5
--- /dev/null
+++ b/m4/.gitignore
@@ -0,0 +1,2 @@
+*.m4
+!header.m4
diff --git a/m4/header.m4 b/m4/header.m4
new file mode 100644
index 0000000..e57661a
--- /dev/null
+++ b/m4/header.m4
@@ -0,0 +1,82 @@
+# header.m4 -- Generate headers from kernel source
+
+# Copyright 2002 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.
+
+# HEADER_GENERATE([HEADER_NAME, KERNEL_SOURCE, PATTERN_BEGIN, PATTERN_END, MACRO])
+# Create HEADER_NAME header from KERNEL_SOURCE,
+# copying the code between lines matching PATTERN_BEGIN and PATTERN_END.
+# The header is guarded from including twice by defining MACRO.
+AC_DEFUN([HEADER_GENERATE], [
+	# Generate HEADER_NAME($1) from KERNEL_SOURCE($2)
+	rm -rf $1
+	AS_IF([test -r $2], [
+		# Find the line number of PATTERN_BEGIN($3)
+		# Note extra quoting [[]] for M4
+		LSOF_TMP1=$(grep -n $3 $2 | sed 's/\([[0-9]]*\):.*$/\1/')
+		AS_IF([test "X$LSOF_TMP1" != "X"], [
+			LSOF_TMP2=0
+			# Find the end of PATTERN_END($4)
+			for i in $(grep -n $4 $2 | sed 's/\([[0-9]]*\):.*/\1/') # {
+			do
+				AS_IF([test $LSOF_TMP2 -eq 0 -a $i -gt $LSOF_TMP1], [
+					LSOF_TMP2=$i
+				])
+			done
+			AS_IF([test $LSOF_TMP2 -eq 0], [
+				LSOF_TMP1=""
+			], [
+				cat > $1 << EOF
+/*
+ * $1 -- created by lsof configure script on
+EOF
+				printf " * " >> $1
+				date >> $1
+				cat >> $1 << EOF
+ */
+
+#if	!defined($5)
+#define	$5
+
+EOF
+				ed -s $2 >> $1 << EOF
+${LSOF_TMP1},${LSOF_TMP2}p
+EOF
+				AS_IF([test $? -ne 0], [
+					AC_MSG_ERROR([can't extract source from $2])
+				], [
+					cat >> $1 << EOF
+
+#endif	/* defined($5) */
+EOF
+				])
+			])
+		])
+	], [
+		AC_MSG_ERROR([can't read $2])
+	])
+]))
diff --git a/main.c b/main.c
deleted file mode 100644
index 628c8d5..0000000
--- a/main.c
+++ /dev/null
@@ -1,2000 +0,0 @@
-/*
- * main.c - common main function for lsof
- *
- * V. Abell, Purdue University
- */
-
-
-/*
- * 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";
-#endif
-
-
-#include "lsof.h"
-
-
-/*
- * Local definitions
- */
-
-static int GObk[] = { 1, 1 };		/* option backspace values */
-static char GOp;			/* option prefix -- '+' or '-' */
-static char *GOv = (char *)NULL;	/* option `:' value pointer */
-static int GOx1 = 1;			/* first opt[][] index */
-static int GOx2 = 0;			/* second opt[][] index */
-
-
-_PROTOTYPE(static int GetOpt,(int ct, char *opt[], char *rules, int *err));
-_PROTOTYPE(static char *sv_fmt_str,(char *f));
-
-
-/*
- * main() - main function for lsof
- */
-
-int
-main(argc, argv)
-	int argc;
-	char *argv[];
-{
-	enum ExitStatus rv;
-	int gopt_rv;
-	int ad, c, i, n, se1, se2, ss;
-	char *cp;
-	int err = 0;
-	enum ExitStatus ev = LSOF_SUCCESS;
-	int fh = 0;
-	char *fmtr = (char *)NULL;
-	long l;
-	MALLOC_S len;
-	struct lfile *lf;
-	struct nwad *np, *npn;
-	char options[128];
-	int rc = 0;
-	struct stat sb;
-	struct sfile *sfp;
-	struct lproc **slp = (struct lproc **)NULL;
-	int sp = 0;
-	struct str_lst *str, *strt;
-	int version = 0;
-	int xover = 0;
-	int pr_count = 0;
-
-#if	defined(HAS_STRFTIME)
-	char *fmt = (char *)NULL;
-	size_t fmtl = (size_t)0;
-#endif	/* defined(HAS_STRFTIME) */
-
-#if	defined(HASZONES)
-	znhash_t *zp;
-#endif	/* defined(HASZONES) */
-
-#if	defined(HASSELINUX)
-/*
- * This stanza must be immediately before the "Save progam name." code, since
- * it contains code itself.
- */
-	cntxlist_t *cntxp;
-
-	CntxStatus = is_selinux_enabled() ? 1 : 0;
-#endif	/* defined(HASSELINUX) */
-
-/*
- * Save program name.
- */
-	if ((Pn = strrchr(argv[0], '/')))
-	    Pn++;
-	else
-	    Pn = argv[0];
-/*
- * 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.
- */
-
-	if ((MaxFd = (int) GET_MAX_FD()) < 53)
-	    MaxFd = 53;
-
-#if	defined(HAS_CLOSEFROM)
-	(void) closefrom(3);
-#else	/* !defined(HAS_CLOSEFROM) */
-#if	defined(SYS_close_range)
-	if (MaxFd > 3 && syscall(SYS_close_range, 3, MaxFd - 1, 0) == 0)
-	    goto closed;
-#endif
-	for (i = 3; i < MaxFd; i++)
-	    (void) close(i);
-#if	defined(SYS_close_range)
-  closed:
-#endif
-#endif	/* !defined(HAS_CLOSEFROM) */
-
-	while (((i = open("/dev/null", O_RDWR, 0)) >= 0) && (i < 2))
-	    ;
-	if (i < 0)
-	    Error();
-	if (i > 2)
-	    (void) close(i);
-	(void) umask(0);
-
-#if	defined(HASSETLOCALE)
-/*
- * Set locale to environment's definition.
- */
-	(void) setlocale(LC_CTYPE, "");
-#endif	/* defined(HASSETLOCALE) */
-
-/*
- * Common initialization.
- */
-	Mypid = getpid();
-	if ((Mygid = (gid_t)getgid()) != getegid())
-	    Setgid = 1;
-	Euid = geteuid();
-	if ((Myuid = (uid_t)getuid()) && !Euid)
-	    Setuidroot = 1;
-	if (!(Namech = (char *)malloc(MAXPATHLEN + 1))) {
-	    (void) fprintf(stderr, "%s: no space for name buffer\n", Pn);
-	    Error();
-	}
-	Namechl = (size_t)(MAXPATHLEN + 1);
-/*
- * Create option mask.
- */
-	(void) snpf(options, sizeof(options),
-	    "?a%sbc:%sD:d:%s%sf:F:g:hi:%s%slL:%s%snNo:Op:QPr:%ss:S:tT:u:UvVwx:%s%s%s",
-
-#if	defined(HAS_AFS) && defined(HASAOPT)
-	    "A:",
-#else	/* !defined(HAS_AFS) || !defined(HASAOPT) */
-	    "",
-#endif	/* defined(HAS_AFS) && defined(HASAOPT) */
-
-#if	defined(HASNCACHE)
-	    "C",
-#else	/* !defined(HASNCACHE) */
-	    "",
-#endif	/* defined(HASNCACHE) */
-
-#if	defined(HASEOPT)
-	    "e:",
-#else	/* !defined(HASEOPT) */
-	    "",
-#endif	/* defined(HASEOPT) */
-
-#if	defined(HASEPTOPTS)
-	    "E",
-#else	/* !defined(HASEPTOPTS) */
-	    "",
-#endif	/* defined(HASEPTOPTS) */
-
-#if	defined(HASKOPT)
-	    "k:",
-#else	/* !defined(HASKOPT) */
-	    "",
-#endif	/* defined(HASKOPT) */
-
-#if	defined(HASTASKS)
-	    "K:",
-#else	/* !defined(HASTASKS) */
-	    "",
-#endif	/* defined(HASTASKS) */
-
-#if	defined(HASMOPT) || defined(HASMNTSUP)
-	    "m:",
-#else	/* !defined(HASMOPT) && !defined(HASMNTSUP) */
-	    "",
-#endif	/* defined(HASMOPT) || defined(HASMNTSUP) */
-
-#if	defined(HASNORPC_H)
-	    "",
-#else	/* !defined(HASNORPC_H) */
-	    "M",
-#endif	/* defined(HASNORPC_H) */
-
-#if	defined(HASPPID)
-	    "R",
-#else	/* !defined(HASPPID) */
-	    "",
-#endif	/* defined(HASPPID) */
-
-#if	defined(HASXOPT)
-# if	defined(HASXOPT_ROOT)
-	    (Myuid == 0) ? "X" : "",
-# else	/* !defined(HASXOPT_ROOT) */
-	    "X",
-# endif	/* defined(HASXOPT_ROOT) */
-#else	/* !defined(HASXOPT) */
-	    "",
-#endif	/* defined(HASXOPT) */
-
-#if	defined(HASZONES)
-	    "z:",
-#else	/* !defined(HASZONES) */
-	    "",
-#endif	/* defined(HASZONES) */
-
-#if	defined(HASSELINUX)
-	    "Z:"
-#else	/* !defined(HASSELINUX) */
-	    ""
-#endif	/* defined(HASSELINUX) */
-
-	    );
-/*
- * Loop through options.
- */
-	while ((c = GetOpt(argc, argv, options, &gopt_rv)) != EOF) {
-	    if (gopt_rv) {
-		err = 1;
-		continue;
-	    }
-	    switch (c) {
-	    case 'a':
-		Fand = 1;
-		break;
-
-#if	defined(HAS_AFS) && defined(HASAOPT)
-	    case 'A':
-		if (!GOv || *GOv == '-' || *GOv == '+') {
-		    (void) fprintf(stderr, "%s: -A not followed by path\n", Pn);
-		    err = 1;
-		    if (GOv) {
-			GOx1 = GObk[0];
-			GOx2 = GObk[1];
-		    }
-		} else
-		    AFSApath = GOv;
-		break;
-#endif	/* defined(HAS_AFS) && defined(HASAOPT) */
-
-	    case 'b':
-		Fblock = 1;
-		break;
-	    case 'c':
-		if (GOp == '+') {
-		    if (!GOv || (*GOv == '-') || (*GOv == '+')
-		    ||  !isdigit((int)*GOv))
-		    {
-			(void) fprintf(stderr,
-			    "%s: +c not followed by width number\n", Pn);
-			err = 1;
-			if (GOv) {
-			    GOx1 = GObk[0];
-			    GOx2 = GObk[1];
-			}
-		    } else {
-			CmdLim = TaskCmdLim = atoi(GOv);
-
-#if	defined(MAXSYSCMDL)
-			if (CmdLim > MAXSYSCMDL) {
-			    (void) fprintf(stderr,
-				"%s: +c %d > what system provides (%d)\n",
-				Pn, CmdLim, MAXSYSCMDL);
-			    err = 1;
-			}
-#endif	/* defined(MAXSYSCMDL) */
-
-		    }
-		    break;
-		}
-		if (GOv && (*GOv == '/')) {
-		    if (enter_cmd_rx(GOv))
-			err = 1;
-		} else {
-		    if (enter_str_lst("-c", GOv, &Cmdl, &Cmdni, &Cmdnx))
-			err = 1;
-
-#if	defined(MAXSYSCMDL)
-		    else if (Cmdl->len > MAXSYSCMDL) {
-			(void) fprintf(stderr, "%s: \"-c ", Pn);
-			(void) safestrprt(Cmdl->str, stderr, 2);
-			(void) fprintf(stderr, "\" length (%d) > what system",
-			    Cmdl->len);
-			(void) fprintf(stderr, " provides (%d)\n",
-			    MAXSYSCMDL);
-			Cmdl->len = 0;	/* (to avoid later error report) */
-			err = 1;
-		    }
-#endif	/* defined(MAXSYSCMDL) */
-
-		}
-		break;
-
-#if	defined(HASNCACHE)
-	    case 'C':
-		Fncache = (GOp == '-') ? 0 : 1;
-		break;
-
-#endif	/* defined(HASNCACHE) */
-	    case 'd':
-		if (GOp == '+') {
-		    if (enter_dir(GOv, 0))
-			err = 1;
-		    else {
-			Selflags |= SELNM;
-			xover = 1;
-		    }
-		} else {
-		    if (enter_fd(GOv))
-			err = 1;
-		}
-		break;
-	    case 'D':
-		if (GOp == '+') {
-		    if (enter_dir(GOv, 1))
-			err = 1;
-		    else {
-			Selflags |= SELNM;
-			xover = 1;
-		    }
-		} else {
-
-#if	defined(HASDCACHE)
-		    if (ctrl_dcache(GOv))
-			err = 1;
-#else	/* !defined(HASDCACHE) */
-		    (void) fprintf(stderr, "%s: unsupported option: -D\n", Pn);
-		    err = 1;
-#endif	/* defined(HASDCACHE) */
-
-		}
-		break;
-
-#if	defined(HASEOPT)
-	    case 'e':
-		if (enter_efsys(GOv, ((GOp == '+') ? 1 : 0)))
-		    err = 1;
-		break;
-#endif	/* defined(HASEOPT) */
-
-#if	defined(HASEPTOPTS)
-	    case 'E':
-		FeptE = (GOp == '+') ? 2 : 1;
-		break;
-#endif	/* defined(HASEPTOPTS) */
-
-	    case 'f':
-		if (!GOv || *GOv == '-' || *GOv == '+') {
-		    Ffilesys = (GOp == '+') ? 2 : 1;
-		    if (GOv) {
-			GOx1 = GObk[0];
-			GOx2 = GObk[1];
-		    }
-		    break;
-		}
-
-#if	defined(HASFSTRUCT)
-		for (; *GOv; GOv++) {
-		    switch (*GOv) {
-
-# if	!defined(HASNOFSCOUNT)
-		    case 'c':
-		    case 'C':
-			if (GOp == '+') {
-			    Fsv |= FSV_CT;
-			    FsvByf = 1;
-			} else
-			    Fsv &= (unsigned char)~FSV_CT;
-			break;
-# endif	/* !defined(HASNOFSCOUNT) */
-
-# if	!defined(HASNOFSADDR)
-		    case 'f':
-		    case 'F':
-			if (GOp == '+') {
-			    Fsv |= FSV_FA;
-			    FsvByf = 1;
-			} else
-			    Fsv &= (unsigned char)~FSV_FA;
-			break;
-# endif	/* !defined(HASNOFSADDR) */
-
-# if	!defined(HASNOFSFLAGS)
-		    case 'g':
-		    case 'G':
-			if (GOp == '+') {
-			    Fsv |= FSV_FG;
-			    FsvByf = 1;
-			} else
-			    Fsv &= (unsigned char)~FSV_FG;
-			FsvFlagX = (*GOv == 'G') ? 1 : 0;
-			break;
-# endif	/* !defined(HASNOFSFLAGS) */
-
-# if	!defined(HASNOFSNADDR)
-		    case 'n':
-		    case 'N':
-			if (GOp == '+') {
-			    Fsv |= FSV_NI;
-			    FsvByf = 1;
-			} else
-			    Fsv &= (unsigned char)~FSV_NI;
-			break;
-# endif	/* !defined(HASNOFSNADDR */
-
-		    default:
-			(void) fprintf(stderr,
-			    "%s: unknown file struct option: %c\n", Pn, *GOv);
-			err++;
-		    }
-		}
-#else	/* !defined(HASFSTRUCT) */
-		(void) fprintf(stderr,
-		    "%s: unknown string for %cf: %s\n", Pn, GOp, GOv);
-		err++;
-#endif	/* defined(HASFSTRUCT) */
-
-		break;
-	    case 'F':
-		if (!GOv || *GOv == '-' || *GOv == '+'
-		||  strcmp(GOv, "0") == 0) {
-		    if (GOv) {
-			if (*GOv == '-' || *GOv == '+') {
-			    GOx1 = GObk[0];
-			    GOx2 = GObk[1];
-			} else if (*GOv == '0')
-			    Terminator = '\0';
-		    }
-		    for (i = 0; FieldSel[i].nm; i++) {
-
-#if	!defined(HASPPID)
-			if (FieldSel[i].id == LSOF_FID_PPID)
-			    continue;
-#endif	/* !defined(HASPPID) */
-
-#if	!defined(HASTASKS)
-			if (FieldSel[i].id == LSOF_FID_TCMD)
-			    continue;
-#endif	/* !defined(HASTASKS) */
-
-#if	!defined(HASFSTRUCT)
-			if (FieldSel[i].id == LSOF_FID_CT
-			||  FieldSel[i].id == LSOF_FID_FA
-			||  FieldSel[i].id == LSOF_FID_FG
-			||  FieldSel[i].id == LSOF_FID_NI)
-			    continue;
-#endif	/* !defined(HASFSTRUCT) */
-
-#if	defined(HASSELINUX)
-			if ((FieldSel[i].id == LSOF_FID_CNTX) && !CntxStatus)
-			    continue;
-#else	/* !defined(HASSELINUX) */
-			if (FieldSel[i].id == LSOF_FID_CNTX)
-			    continue;
-#endif	/* !defined(HASSELINUX) */
-
-			if (FieldSel[i].id == LSOF_FID_RDEV)
-			    continue;	/* for compatibility */
-
-#if	!defined(HASTASKS)
-			if (FieldSel[i].id == LSOF_FID_TID)
-			    continue;
-#endif	/* !defined(HASTASKS) */
-
-#if	!defined(HASZONES)
-			if (FieldSel[i].id == LSOF_FID_ZONE)
-			    continue;
-#endif	/* !defined(HASZONES) */
-
-			FieldSel[i].st = 1;
-			if (FieldSel[i].opt && FieldSel[i].ov)
-			    *(FieldSel[i].opt) |= FieldSel[i].ov;
-		    }
-
-#if	defined(HASFSTRUCT)
-		    Ffield = FsvFlagX = 1;
-#else	/* !defined(HASFSTRUCT) */
-		    Ffield = 1;
-#endif	/* defined(HASFSTRUCT) */
-
-		    break;
-		}
-		if (strcmp(GOv, "?") == 0) {
-		    fh = 1;
-		    break;
-		}
-		for (; *GOv; GOv++) {
-		    for (i = 0; FieldSel[i].nm; i++) {
-
-#if	!defined(HASPPID)
-			if (FieldSel[i].id == LSOF_FID_PPID)
-			    continue;
-#endif	/* !defined(HASPPID) */
-
-#if	!defined(HASTASKS)
-			if (FieldSel[i].id == LSOF_FID_TCMD)
-			    continue;
-#endif	/* !defined(HASTASKS) */
-
-#if	!defined(HASFSTRUCT)
-			if (FieldSel[i].id == LSOF_FID_CT
-			||  FieldSel[i].id == LSOF_FID_FA
-			||  FieldSel[i].id == LSOF_FID_FG
-			||  FieldSel[i].id == LSOF_FID_NI)
-			    continue;
-#endif	/* !defined(HASFSTRUCT) */
-
-#if	!defined(HASTASKS)
-			if (FieldSel[i].id == LSOF_FID_TID)
-			    continue;
-#endif	/* !defined(HASTASKS) */
-
-			if (FieldSel[i].id == *GOv) {
-			    FieldSel[i].st = 1;
-			    if (FieldSel[i].opt && FieldSel[i].ov)
-				*(FieldSel[i].opt) |= FieldSel[i].ov;
-
-#if	defined(HASFSTRUCT)
-			    if (i == LSOF_FIX_FG)
-				FsvFlagX = 1;
-#endif	/* defined(HASFSTRUCT) */
-
-			    if (i == LSOF_FIX_TERM)
-				Terminator = '\0';
-
-			    if (i == LSOF_FIX_OFFSET)
-				Foffset = 1;
-
-			    break;
-			}
-		    }
-		    if ( ! FieldSel[i].nm) {
-			(void) fprintf(stderr,
-			    "%s: unknown field: %c\n", Pn, *GOv);
-			err++;
-		    }
-		}
-		Ffield = 1;
-		break;
-	    case 'g':
-		if (GOv) {
-		    if (*GOv == '-' || *GOv == '+') {
-			GOx1 = GObk[0];
-			GOx2 = GObk[1];
-		    } else if (enter_id(PGID, GOv))
-			err = 1;
-		}
-		Fpgid = 1;
-		break;
-	    case 'h':
-	    case '?':
-		Fhelp = 1;
-		break;
-	    case 'i':
-		if (!GOv || *GOv == '-' || *GOv == '+') {
-		    Fnet = 1;
-		    FnetTy = 0;
-		    if (GOv) {
-			GOx1 = GObk[0];
-			GOx2 = GObk[1];
-		    }
-		    break;
-		}
-		if (enter_network_address(GOv))
-		    err = 1;
-		break;
-
-#if	defined(HASKOPT)
-	    case 'k':
-		if (!GOv || *GOv == '-' || *GOv == '+') {
-		    (void) fprintf(stderr, "%s: -k not followed by path\n", Pn);
-		    err = 1;
-		    if (GOv) {
-			GOx1 = GObk[0];
-			GOx2 = GObk[1];
-		    }
-		} else
-		    Nmlst = GOv;
-		break;
-#endif	/* defined(HASKOPT) */
-
-#if	defined(HASTASKS)
-	    case 'K':
-		if (!GOv || *GOv == '-' || *GOv == '+') {
-		    Ftask = 1;
-		    IgnTasks = 0;
-		    Selflags |= SELTASK;
-		    if (GOv) {
-			GOx1 = GObk[0];
-			GOx2 = GObk[1];
-		    }
-		} else {
-		    if (!strcasecmp(GOv, "i")) {
-			Ftask = 0;
-			IgnTasks = 1;
-			Selflags &= ~SELTASK;
-		   } else {
-			(void) fprintf(stderr,
-			    "%s: -K not followed by i (but by %s)\n", Pn, GOv);
-			err = 1;
-		   }
-		}
-		break;
-#endif	/* defined(HASTASKS) */
-
-	    case 'l':
-		Futol = 0;
-		break;
-	    case 'L':
-		Fnlink = (GOp == '+') ? 1 : 0;
-		if (!GOv || *GOv == '-' || *GOv == '+') {
-		    Nlink = 0l;
-		    if (GOv) {
-			GOx1 = GObk[0];
-			GOx2 = GObk[1];
-		    }
-		    break;
-		}
-		for (cp = GOv, l = 0l, n = 0; *cp; cp++) {
-		    if (!isdigit((unsigned char)*cp))
-			break;
-		    l = (l * 10l) + ((long)*cp - (long)'0');
-		    n++;
-		}
-		if (n) {
-		    if (GOp != '+') {
-			(void) fprintf(stderr,
-			    "%s: no number may follow -L\n", Pn);
-			err = 1;
-		    } else {
-			Nlink = l;
-			Selflags |= SELNLINK;
-		    }
-		} else
-		    Nlink = 0l;
-		if (*cp) {
-		    GOx1 = GObk[0];
-		    GOx2 = GObk[1] + n;
-		}
-		break;
-
-#if	defined(HASMOPT) || defined(HASMNTSUP)
-	    case 'm':
-		if (GOp == '-') {
-
-# if	defined(HASMOPT)
-		    if (!GOv || *GOv == '-' || *GOv == '+') {
-			(void) fprintf(stderr,
-			    "%s: -m not followed by path\n", Pn);
-			err = 1;
-			if (GOv) {
-			    GOx1 = GObk[0];
-			    GOx2 = GObk[1];
-			}
-		    } else
-			Memory = GOv;
-# else	/* !defined(HASMOPT) */
-		    (void) fprintf(stderr, "%s: -m not supported\n", Pn);
-		    err = 1;
-# endif	/* defined(HASMOPT) */
-
-		} else if (GOp == '+') {
-
-# if	defined(HASMNTSUP)
-		    if (!GOv || *GOv == '-' || *GOv == '+') {
-			MntSup = 1;
-			if (GOv) {
-			    GOx1 = GObk[0];
-			    GOx2 = GObk[1];
-			}
-		    } else {
-			MntSup = 2;
-			MntSupP = GOv;
-		    }
-# else	/* !defined(HASMNTSUP) */
-		    (void) fprintf(stderr, "%s: +m not supported\n", Pn);
-		    err = 1;
-# endif	/* defined(HASMNTSUP) */
-
-		} else {
-		    (void) fprintf(stderr, "%s: %cm not supported\n", Pn, GOp);
-		    err = 1;
-		}
-		break;
-#endif	/* defined(HASMOPT) || defined(HASMNTSUP) */
-
-#if	!defined(HASNORPC_H)
-	    case 'M':
-		FportMap = (GOp == '+') ? 1 : 0;
-		break;
-#endif	/* !defined(HASNORPC_H) */
-
-	    case 'n':
-		Fhost = (GOp == '-') ? 0 : 1;
-		break;
-	    case 'N':
-		Fnfs = 1;
-		break;
-	    case 'o':
-		if (!GOv || *GOv == '-' || *GOv == '+') {
-		    Foffset = 1;
-		    if (GOv) {
-			GOx1 = GObk[0];
-			GOx2 = GObk[1];
-		    }
-		    break;
-		}
-		for (cp = GOv, i = n = 0; *cp; cp++) {
-		    if (!isdigit((unsigned char)*cp))
-			break;
-		    i = (i * 10) + ((int)*cp - '0');
-		    n++;
-		}
-		if (n)
-		    OffDecDig = i;
-		else
-		    Foffset = 1;
-		if (*cp) {
-		    GOx1 = GObk[0];
-		    GOx2 = GObk[1] + n;
-		}
-		break;
-	    case 'O':
-		Fovhd = (GOp == '-') ? 1 : 0;
-		break;
-	    case 'p':
-		if (enter_id(PID, GOv))
-		    err = 1;
-		break;
-	    case 'Q':
-		FsearchErr = 0;
-		break;
-	    case 'P':
-		Fport = (GOp == '-') ? 0 : 1;
-		break;
-	    case 'r':
-		if (GOp == '+') {
-		    ev = LSOF_ERROR;
-		    rc = 1;
-		}
-		if (!GOv || *GOv == '-' || *GOv == '+') {
-		    RptTm = RPTTM;
-		    if (GOv) {
-			GOx1 = GObk[0];
-			GOx2 = GObk[1];
-		    }
-		    break;
-		}
-		for (cp = GOv, i = n = 0; *cp; cp++) {
-		    if (!isdigit((unsigned char)*cp))
-			break;
-		    i = (i * 10) + ((int)*cp - '0');
-		    n++;
-		}
-		if (n)
-		    RptTm = i;
-		else
-		    RptTm = RPTTM;
-		if (!*cp)
-		     break;
-		while(*cp && (*cp == ' '))
-		    cp++;
-
-		if (*cp == 'c') {
-		    cp++;
-		    for (i = 0;
-			 *cp && isdigit((unsigned char)*cp);
-			 cp++)
-			i = (i * 10) + ((int)*cp - '0');
-		    RptMaxCount = i;
-		}
-
-		if (*cp != LSOF_FID_MARK) {
-		    GOx1 = GObk[0];
-		    GOx2 = GObk[1] + n;
-		    break;
-		}
-
-#if	defined(HAS_STRFTIME)
-
-	    /*
-	     * Collect the strftime(3) format and test it.
-	     */
-		cp++;
-		if ((fmtl = strlen(cp) + 1) < 1) {
-		    (void) fprintf(stderr, "%s: <fmt> too short: \"%s\"\n",
-			Pn, cp);
-		    err = 1;
-		} else {
-		    fmt = cp;
-		    fmtl = (fmtl * 8) + 1;
-		    if (!(fmtr = (char *)malloc((MALLOC_S)fmtl))) {
-			(void) fprintf(stderr,
-			    "%s: no space (%d) for <fmt> result: \"%s\"\n",
-			    Pn, (int)fmtl, cp);
-			    Error();
-		    }
-		    if (util_strftime(fmtr, fmtl - 1, fmt) < 1) {
-			(void) fprintf(stderr, "%s: illegal <fmt>: \"%s\"\n",
-			    Pn, fmt);
-			err = 1;
-		    }
-		}
-
-#else	/* !defined(HAS_STRFTIME) */
-		(void) fprintf(stderr, "%s: m<fmt> not supported: \"%s\"\n",
-		    Pn, cp);
-		err = 1;
-#endif	/* defined(HAS_STRFTIME) */
-
-		break;
-
-#if	defined(HASPPID)
-	    case 'R':
-		Fppid = 1;
-		break;
-#endif	/* defined(HASPPID) */
-
-	    case 's':
-
-#if	defined(HASTCPUDPSTATE)
-		if (!GOv || *GOv == '-' || *GOv == '+') {
-		    Fsize = 1;
-		    if (GOv) {
-			GOx1 = GObk[0];
-			GOx2 = GObk[1];
-		    }
-		} else {
-		    if (enter_state_spec(GOv))
-			err = 1;
-		}
-#else	/* !defined(HASTCPUDPSTATE) */
-		Fsize = 1;
-#endif	/* defined(HASTCPUDPSTATE) */
-
-		break;
-	    case 'S':
-		if (!GOv || *GOv == '-' || *GOv == '+') {
-		    TmLimit = TMLIMIT;
-		    if (GOv) {
-			GOx1 = GObk[0];
-			GOx2 = GObk[1];
-		    }
-		    break;
-		}
-		for (cp = GOv, i = n = 0; *cp; cp++) {
-		    if (!isdigit((unsigned char)*cp))
-			break;
-		    i = (i * 10) + ((int)*cp - '0');
-		    n++;
-		}
-		if (n)
-		    TmLimit = i;
-		else
-		    TmLimit = TMLIMIT;
-		if (*cp) {
-		    GOx1 = GObk[0];
-		    GOx2 = GObk[1] + n;
-		}
-		if (TmLimit < TMLIMMIN) {
-		    (void) fprintf(stderr,
-			"%s: WARNING: -S time (%d) changed to %d\n",
-			Pn, TmLimit, TMLIMMIN);
-		    TmLimit = TMLIMMIN;
-		}
-		break;
-	    case 't':
-		Fterse = Fwarn = 1;
-		break;
-	    case 'T':
-		if (!GOv || *GOv == '-' || *GOv == '+') {
-		    Ftcptpi = (GOp == '-') ? 0 : TCPTPI_STATE;
-		    if (GOv) {
-			GOx1 = GObk[0];
-			GOx2 = GObk[1];
-		    }
-		    break;
-		}
-		for (Ftcptpi = 0; *GOv; GOv++) {
-		    switch (*GOv) {
-
-#if	defined(HASSOOPT) || defined(HASSOSTATE) || defined(HASTCPOPT)
-		    case 'f':
-			Ftcptpi |= TCPTPI_FLAGS;
-			break;
-#endif	/* defined(HASSOOPT) || defined(HASSOSTATE) || defined(HASTCPOPT) */
-
-#if	defined(HASTCPTPIQ)
-		    case 'q':
-			Ftcptpi |= TCPTPI_QUEUES;
-			break;
-#endif	/* defined(HASTCPTPIQ) */
-
-		    case 's':
-			Ftcptpi |= TCPTPI_STATE;
-			break;
-
-#if	defined(HASTCPTPIW)
-		    case 'w':
-			Ftcptpi |= TCPTPI_WINDOWS;
-			break;
-#endif	/* defined(HASTCPTPIW) */
-
-		    default:
-			(void) fprintf(stderr,
-			"%s: unsupported TCP/TPI info selection: %c\n",
-			    Pn, *GOv);
-			err = 1;
-		    }
-		}
-		break;
-	    case 'u':
-		if (enter_uid(GOv))
-		    err = 1;
-		break;
-	    case 'U':
-		Funix = 1;
-		break;
-	    case 'v':
-		version = 1;
-		break;
-	    case 'V':
-		Fverbose = 1;
-		break;
-	    case 'w':
-		Fwarn = (GOp == '+') ? 0 : 1;
-		break;
-	    case 'x':
-		if (!GOv || *GOv == '-' || *GOv == '+') {
-		    Fxover = XO_ALL;
-		    if (GOv) {
-			GOx1 = GObk[0];
-			GOx2 = GObk[1];
-		    }
-		    break;
-		} else {
-		    for (; *GOv; GOv++) {
-			switch (*GOv) {
-			case 'f':
-			    Fxover |= XO_FILESYS;
-			    break;
-			case 'l':
-			    Fxover |= XO_SYMLINK;
-			    break;
-			default:
-			    (void) fprintf(stderr,
-				"%s: unknown cross-over option: %c\n",
-				Pn, *GOv);
-			    err++;
-			}
-		    }
-		}
-		break;
-
-#if	defined(HASXOPT)
-	    case 'X':
-		Fxopt = Fxopt ? 0 : 1;
-		break;
-#endif	/* defined(HASXOPT) */
-
-#if	defined(HASZONES)
-	    case 'z':
-		Fzone = 1;
-		if (GOv && (*GOv != '-') && (*GOv != '+')) {
-
-		/*
-		 * Add to the zone name argument hash.
-		 */
-		    if (enter_zone_arg(GOv))
-			err = 1;
-		} else if (GOv) {
-		    GOx1 = GObk[0];
-		    GOx2 = GObk[1];
-		}
-		break;
-#endif	/* defined(HASZONES) */
-
-#if	defined(HASSELINUX)
-	    case 'Z':
-		if (!CntxStatus) {
-		   (void) fprintf(stderr, "%s: -Z limited to SELinux\n", Pn);
-		    err = 1;
-		} else {
-		    Fcntx = 1;
-		    if (GOv && (*GOv != '-') && (*GOv != '+')) {
-
-		    /*
-		     * Add to the context name argument hash.
-		     */
-			if (enter_cntx_arg(GOv))
-			    err = 1;
-		    } else if (GOv) {
-			GOx1 = GObk[0];
-			GOx2 = GObk[1];
-		    }
-		}
-		break;
-#endif	/* defined(HASSELINUX) */
-
-	    default:
-		(void) fprintf(stderr, "%s: unknown option (%c)\n", Pn, c);
-		err = 1;
-	    }
-	}
-/*
- * If IgnTasks is set, remove SELTASK from SelAll and SelProc.
- */
-	SelAll = IgnTasks ? (SELALL & ~SELTASK) : SELALL;
-	SelProc = IgnTasks ? (SELPROC & ~SELTASK) : SELPROC;
-/*
- * Check for argument consistency.
- */
-	if (Cmdnx && Cmdni) {
-
-	/*
-	 * Check for command inclusion/exclusion conflicts.
-	 */
-	    for (str = Cmdl; str; str = str->next) {
-		if (str->x) {
-		    for (strt = Cmdl; strt; strt = strt->next) {
-			if (!strt->x) {
-			    if (!strcmp(str->str, strt->str)) {
-				(void) fprintf(stderr,
-				    "%s: -c^%s and -c%s conflict.\n",
-				    Pn, str->str, strt->str);
-				err++;
-			    }
-			}
-		    }
-		}
-	    }
-	}
-
-#if	defined(HASTCPUDPSTATE)
-	if (TcpStXn && TcpStIn) {
-
-	/*
-	 * Check for excluded and included TCP states.
-	 */
-	    for (i = 0; i < TcpNstates; i++) {
-		if (TcpStX[i] && TcpStI[i]) {
-		    (void) fprintf(stderr,
-			"%s: can't include and exclude TCP state: %s\n",
-			Pn, TcpSt[i]);
-		    err = 1;
-		}
-	    }
-	}
-	if (UdpStXn && UdpStIn) {
-
-	/*
-	 * Check for excluded and included UDP states.
-	 */
-	    for (i = 0; i < UdpNstates; i++) {
-		if (UdpStX[i] && UdpStI[i]) {
-		    (void) fprintf(stderr,
-			"%s: can't include and exclude UDP state: %s\n",
-			Pn, UdpSt[i]);
-		    err = 1;
-		}
-	    }
-	}
-#endif	/* defined(HASTCPUDPSTATE) */
-
-	if (Fsize && Foffset) {
-	    (void) fprintf(stderr, "%s: -o and -s are mutually exclusive\n",
-		Pn);
-	    err++;
-	}
-	if (Ffield) {
-	    if (Fterse) {
-		(void) fprintf(stderr,
-		    "%s: -F and -t are mutually exclusive\n", Pn);
-		err++;
-	    }
-	    FieldSel[LSOF_FIX_PID].st = 1;
-
-#if	defined(HAS_STRFTIME)
-	    if (fmtr) {
-
-	    /*
-	     * The field output marker format can't contain "%n" new line
-	     * requests.
-	     */
-		for (cp = strchr(fmt, '%'); cp; cp = strchr(cp, '%')) {
-		    if (*++cp  == 'n') {
-			(void) fprintf(stderr,
-			    "%s: %%n illegal in -r m<fmt> when -F has", Pn);
-			(void) fprintf(stderr,
-			    " been specified: \"%s\"\n", fmt);
-			err++;
-			break;
-		    } else if (*cp == '%')
-			cp++;
-		}
-	    }
-#endif	/* defined(HAS_STRFTIME) */
-
-	}
-	if (Fxover && !xover) {
-	    (void) fprintf(stderr, "%s: -x must accompany +d or +D\n", Pn);
-	    err++;
-	}
-
-#if	defined(HASEOPT)
-	if (Efsysl) {
-
-	/*
-	 * If there are file systems specified by -e options, check them.
-	 */
-	    efsys_list_t *ep;		/* Efsysl pointer */
-	    struct mounts *mp, *mpw;	/* local mount table pointers */
-
-	    if ((mp = readmnt())) {
-		for (ep = Efsysl; ep; ep = ep->next) {
-		    for (mpw = mp; mpw; mpw = mpw->next) {
-			if (!strcmp(mpw->dir, ep->path)) {
-			    ep->mp = mpw;
-			    break;
-			}
-		    }
-		    if (!ep->mp) {
-			(void) fprintf(stderr,
-			    "%s: \"-e %s\" is not a mounted file system.\n",
-			    Pn, ep->path);
-			err++;
-		    }
-		}
-	    }
-	}
-#endif	/* defined(HASEOPT) */
-
-	if (DChelp || err || Fhelp || fh || version)
-	    usage(err ? 1 : 0, fh, version);
-/*
- * Reduce the size of Suid[], if necessary.
- */
-	if (Suid && Nuid && Nuid < Mxuid) {
-	    if (!(Suid = (struct seluid *)realloc((MALLOC_P *)Suid,
-			 (MALLOC_S)(sizeof(struct seluid) * Nuid))))
-	    {
-		(void) fprintf(stderr, "%s: can't realloc UID table\n", Pn);
-		Error();
-	    }
-	    Mxuid = Nuid;
-	}
-/*
- * Compute the selection flags.
- */
-	if ((Cmdl && Cmdni) || CmdRx)
-	    Selflags |= SELCMD;
-
-#if	defined(HASSELINUX)
-	if (CntxArg)
-	    Selflags |= SELCNTX;
-#endif	/* defined(HASSELINUX) */
-
-	if (Fdl)
-	    Selflags |= SELFD;
-	if (Fnet)
-	    Selflags |= SELNET;
-	if (Fnfs)
-	    Selflags |= SELNFS;
-	if (Funix)
-	    Selflags |= SELUNX;
-	if (Npgid && Npgidi)
-	    Selflags |= SELPGID;
-	if (Npid && Npidi)
-	    Selflags |= SELPID;
-	if (Nuid && Nuidincl)
-	    Selflags |= SELUID;
-	if (Nwad)
-	    Selflags |= SELNA;
-
-#if	defined(HASZONES)
-	if (ZoneArg)
-	    Selflags |= SELZONE;
-#endif	/* defined(HASZONES) */
-
-	if (GOx1 < argc)
-	    Selflags |= SELNM;
-	if (Selflags == 0) {
-	    if (Fand) {
-		(void) fprintf(stderr,
-		    "%s: no select options to AND via -a\n", Pn);
-		usage(1, 0, 0);
-	    }
-	    Selflags = SelAll;
-	} else {
-	    if (GOx1 >= argc && (Selflags & (SELNA|SELNET)) != 0
-	    && (Selflags & ~(SELNA|SELNET)) == 0)
-		Selinet = 1;
-	    AllProc = 0;
-	}
-/*
- * Get the device for DEVDEV_PATH.
- */
-	if (stat(DEVDEV_PATH, &sb)) {
-	    se1 = errno;
- 	    if ((ad = strcmp(DEVDEV_PATH, "/dev"))) {
-		if ((ss = stat("/dev", &sb)))
-		    se2 = errno;
-		else
-		    se2 = 0;
-	    } else {
-		se2 = 0;
-		ss = 1;
-	    }
-	    if (ss) {
-		(void) fprintf(stderr, "%s: can't stat(%s): %s\n", Pn,
-		    DEVDEV_PATH, strerror(se1));
-		if (ad) {
-		    (void) fprintf(stderr, "%s: can't stat(/dev): %s\n", Pn,
-		    strerror(se2));
-		}
-		Error();
-	    }
-	}
-	DevDev = sb.st_dev;
-/*
- * Process the file arguments.
- */
-	if (GOx1 < argc) {
-	    if (ck_file_arg(GOx1, argc, argv, Ffilesys, 0, (struct stat *)NULL, FsearchErr == 0))
-		Error();
-	}
-/*
- * Do dialect-specific initialization.
- */
-	initialize();
-	if (Sfile)
-	    (void) hashSfile();
-
-#if	defined(WILLDROPGID)
-/*
- * If this process isn't setuid(root), but it is setgid(not_real_gid),
- * relinquish the setgid power.  (If it hasn't already been done.)
- */
-	(void) dropgid();
-#endif	/* defined(WILLDROPGID) */
-
-
-#if	defined(HASDCACHE)
-/*
- * If there is a device cache, prepare the device table.
- */
-	if (DCstate)
-	    readdev(0);
-#endif	/* defined(HASDCACHE) */
-
-/*
- * Define the size and offset print formats.
- */
-	(void) snpf(options, sizeof(options), "%%%su", INODEPSPEC);
-	InodeFmt_d = sv_fmt_str(options);
-	(void) snpf(options, sizeof(options), "%%#%sx", INODEPSPEC);
-	InodeFmt_x = sv_fmt_str(options);
-	(void) snpf(options, sizeof(options), "0t%%%su", SZOFFPSPEC);
-	SzOffFmt_0t = sv_fmt_str(options);
-	(void) snpf(options, sizeof(options), "%%%su", SZOFFPSPEC);
-	SzOffFmt_d = sv_fmt_str(options);
-	(void) snpf(options, sizeof(options), "%%*%su", SZOFFPSPEC);
-	SzOffFmt_dv = sv_fmt_str(options);
-	(void) snpf(options, sizeof(options), "%%#%sx", SZOFFPSPEC);
-	SzOffFmt_x = sv_fmt_str(options);
-
-#if	defined(HASMNTSUP)
-/*
- * Report mount supplement information, as requested.
- */
-	if (MntSup == 1) {
-	    (void) readmnt();
-	    Exit(LSOF_SUCCESS);
-	}
-#endif	/* defined(HASMNTSUP) */
-
-/*
- * Gather and report process information every RptTm seconds.
- */
-	if (RptTm)
-	    CkPasswd = 1;
-	do {
-
-	/*
-	 * Gather information about processes.
-	 */
-	    gather_proc_info();
-	/*
-	 * If the local process table has more than one entry, sort it by PID.
-	 */
-	    if (Nlproc > 1) {
-		if (Nlproc > sp) {
-		    len = (MALLOC_S)(Nlproc * sizeof(struct lproc *));
-		    sp = Nlproc;
-		    if (!slp)
-			slp = (struct lproc **)malloc(len);
-		    else
-			slp = (struct lproc **)realloc((MALLOC_P *)slp, len);
-		    if (!slp) {
-			(void) fprintf(stderr,
-			    "%s: no space for %d sort pointers\n", Pn, Nlproc);
-			Error();
-		    }
-		}
-		for (i = 0; i < Nlproc; i++) {
-		    slp[i] = &Lproc[i];
-		}
-		(void) qsort((QSORT_P *)slp, (size_t)Nlproc,
-			     (size_t)sizeof(struct lproc *), comppid);
-	    }
-	    if ((n = Nlproc)) {
-
-#if	defined(HASNCACHE)
-	    /*
-	     * If using the kernel name cache, force its reloading.
-	     */
-		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 printing
-	     * of the selected processes.
-	     */
-		if (FeptE) {
-		    lf = Lf;
-		/*
-		 * Scan all selected processes.
-		 */
-		    for (i = 0; i < Nlproc; i++) {
-			Lp = (Nlproc > 1) ? slp[i] : &Lproc[i];
-
-			/*
-			 * For processes that have been selected for printing
-			 * and have files that are the end point(s) of pipe(s),
-			 * process the file endpoints.
-			 */
-			    if (Lp->pss && (Lp->ept & EPT_PIPE))
-				(void) process_pinfo(0);
-			/*
-			 * Process POSIX MQ endpoints.
-			 */
-			    if (Lp->ept & EPT_PSXMQ)
-			      (void) process_psxmqinfo(0);
-
-# if	defined(HASUXSOCKEPT)
-			/*
-			 * For processes that have been selected for printing
-			 * and have files that are the end point(s) of UNIX
-			 * socket(s), process the file endpoints.
-			 */
-			    if (Lp->pss && (Lp->ept & EPT_UXS))
-				(void) process_uxsinfo(0);
-# endif	/* defined(HASUXSOCKEPT) */
-
-# if	defined(HASPTYEPT)
-			/*
-			 * For processes that have been selected for printing
-			 * and have files that are the end point(s) of pseudo-
-			 * terminal files(s), process the file endpoints.
-			 */
-			    if (Lp->pss && (Lp->ept & EPT_PTY))
-				(void) process_ptyinfo(0);
-# endif	/* defined(HASPTYEPT) */
-
-			/*
-			 * Process INET socket endpoints.
-			 */
-			    if (Lp->ept & EPT_NETS)
-				(void) process_netsinfo(0);
-
-# if	defined(HASIPv6)
-			/*
-			 * Process INET6 socket endpoints.
-			 */
-			    if (Lp->ept & EPT_NETS6)
-				(void) process_nets6info(0);
-# endif	/* defined(HASIPv6) */
-			/*
-			 * Process eventfd endpoints.
-			 */
-			    if (Lp->ept & EPT_EVTFD)
-				(void) process_evtfdinfo(0);
-		    }
-		/*
-		 * In a second pass, look for unselected endpoint files,
-		 * possibly selecting them for printing.
-		 */
-		    for (i = 0; i < Nlproc; i++) {
-			Lp = (Nlproc > 1) ? slp[i] : &Lproc[i];
-
-			/*
-			 * Process pipe endpoints.
-			 */
-			    if (Lp->ept & EPT_PIPE_END)
-				(void) process_pinfo(1);
-			/*
-			 * Process POSIX MQ endpoints.
-			 */
-			    if (Lp->ept & EPT_PSXMQ_END)
-			      (void) process_psxmqinfo(1);
-
-# if	defined(HASUXSOCKEPT)
-			/*
-			 * Process UNIX socket endpoints.
-			 */
-			    if (Lp->ept & EPT_UXS_END)
-				(void) process_uxsinfo(1);
-# endif	/* defined(HASUXSOCKEPT) */
-
-# if	defined(HASPTYEPT)
-			/*
-			 * Process pseudo-terminal endpoints.
-			 */
-			    if (Lp->ept & EPT_PTY_END)
-				(void) process_ptyinfo(1);
-# endif	/* defined(HASPTYEPT) */
-
-			/*
-			 * Process INET socket endpoints.
-			 */
-			    if (Lp->ept & EPT_NETS_END)
-				(void) process_netsinfo(1);
-
-#if	defined(HASIPv6)
-			/*
-			 * Process INET6 socket endpoints.
-			 */
-			    if (Lp->ept & EPT_NETS6_END)
-				(void) process_nets6info(1);
-# endif	/* defined(HASIPv6) */
-
-			/*
-			 * Process envetfd endpoints.
-			 */
-			    if (Lp->ept & EPT_EVTFD_END)
-				(void) process_evtfdinfo(1);
-		    }
-		    Lf = lf;
-		}
-#endif	/* defined(HASEPTOPTS) */
-
-	    /*
-	     * Print the selected processes and count them.
-	     *
-	     * Lf contents must be preserved, since they may point to a
-	     * malloc()'d area, and since Lf is used throughout the print
-	     * process.
-	     */
-		for (lf = Lf, print_init(); PrPass < 2; PrPass++) {
-		    for (i = n = 0; i < Nlproc; i++) {
-			Lp = (Nlproc > 1) ? slp[i] : &Lproc[i];
-			if (Lp->pss) {
-			    if (print_proc())
-				n++;
-			}
-			if (RptTm && PrPass)
-			    (void) free_lproc(Lp);
-		    }
-		}
-		Lf = lf;
-	    }
-	/*
-	 * If a repeat time is set, sleep for the specified time.
-	 *
-	 * If conditional repeat mode is in effect, see if it's time to exit.
-	 */
-	    if (RptTm) {
-
-#if	defined(HASEPTOPTS)
-		(void) clear_pinfo();
-
-		(void) clear_psxmqinfo();
-
-# if	defined(HASUXSOCKEPT)
-		(void) clear_uxsinfo();
-# endif	/* defined(HASUXSOCKEPT) */
-
-# if	defined(HASPTYEPT)
-		(void) clear_ptyinfo();
-# endif	/* defined(HASPTYEPT) */
-
-		(void) clear_netsinfo();
-
-# if	defined(HASIPv6)
-		(void) clear_nets6info();
-# endif	/* defined(HASIPv6) */
-
-		(void) clear_evtfdinfo();
-#endif	/* defined(HASEPTOPTS) */
-
-		if (rc) {
-		    if (!n)
-			break;
-		    else
-			ev = LSOF_SUCCESS;
-		}
-
-#if	defined(HAS_STRFTIME)
-		if (fmt && fmtr) {
-
-		/*
-		 * Format the marker line.
-		 */
-		    (void) util_strftime(fmtr, fmtl - 1, fmt);
-		    fmtr[fmtl - 1] = '\0';
-		}
-#endif	/* defined(HAS_STRFTIME) */
-
-		if (Ffield) {
-		    putchar(LSOF_FID_MARK);
-
-#if	defined(HAS_STRFTIME)
-		    if (fmtr)
-	    	        (void) printf("%s", fmtr);
-#endif	/* defined(HAS_STRFTIME) */
-
-		    putchar(Terminator);
-		    if (Terminator != '\n')
-			putchar('\n');
-		} else {
-
-#if	defined(HAS_STRFTIME)
-		    if (fmtr)
-			cp = fmtr;
-		    else
-#endif	/* defined(HAS_STRFTIME) */
-
-			cp = "=======";
-		    puts(cp);
-		}
-		(void) fflush(stdout);
-		(void) childx();
-		(void) sleep(RptTm);
-		Hdr = Nlproc = 0;
-		CkPasswd = 1;
-	    }
-	    if (RptMaxCount && (++pr_count == RptMaxCount))
-		RptTm = 0;
-	} while (RptTm);
-/*
- * See if all requested information was displayed.  Return zero if it
- * was; one, if not.  If -V was specified, report what was not displayed.
- */
-	(void) childx();
-	rv = LSOF_SUCCESS;
-	for (str = Cmdl; str; str = str->next) {
-
-	/*
-	 * Check command specifications.
-	 */
-	    if (str->f)
-		continue;
-	    rv = LSOF_SEARCH_FAILURE;
-	    if (Fverbose) {
-		(void) printf("%s: command not located: ", Pn);
-		safestrprt(str->str, stdout, 1);
-	    }
-	}
-	for (i = 0; i < NCmdRxU; i++) {
-
-	/*
-	 * Check command regular expressions.
-	 */
-	    if (CmdRx[i].mc)
-		continue;
-	    rv = LSOF_SEARCH_FAILURE;
-	    if (Fverbose) {
-		(void) printf("%s: no command found for regex: ", Pn);
-		safestrprt(CmdRx[i].exp, stdout, 1);
-	    }
-	}
-	for (sfp = Sfile; sfp; sfp = sfp->next) {
-
-	/*
-	 * Check file specifications.
-	 */
-	    if (sfp->f)
-		continue;
-	    rv = LSOF_SEARCH_FAILURE;
-	    if (Fverbose) {
-		(void) printf("%s: no file%s use located: ", Pn,
-		    sfp->type ? "" : " system");
-		safestrprt(sfp->aname, stdout, 1);
-	    }
-	}
-
-#if	defined(HASPROCFS)
-	/*
-	 * Report on proc file system search results.
-	 */
-	    if (Procsrch && !Procfind) {
-		rv = LSOF_SEARCH_FAILURE;
-		if (Fverbose) {
-		    (void) printf("%s: no file system use located: ", Pn);
-		    safestrprt(Mtprocfs ? Mtprocfs->dir : HASPROCFS, stdout, 1);
-		}
-	    }
-	    {
-		struct procfsid *pfi;
-
-		for (pfi = Procfsid; pfi; pfi = pfi->next) {
-		    if (!pfi->f) {
-			rv = LSOF_SEARCH_FAILURE;
-			if (Fverbose) {
-			    (void) printf("%s: no file use located: ", Pn);
-			    safestrprt(pfi->nm, stdout, 1);
-			}
-		    }
-		}
-	    }
-#endif	/* defined(HASPROCFS) */
-
-	if ((np = Nwad)) {
-
-	/*
-	 * Check Internet address specifications.
-	 *
-	 * If any Internet address derived from the same argument was found,
-	 * consider all derivations found.  If no derivation from the same
-	 * argument was found, report only the first failure.
-	 *
-	 */
-	    for (; np; np = np->next) {
-		if (!(cp = np->arg))
-		    continue;
-		for (npn = np->next; npn; npn = npn->next) {
-		    if (!npn->arg)
-			continue;
-		    if (!strcmp(cp, npn->arg)) {
-
-		    /*
-		     * If either of the duplicate specifications was found,
-		     * mark them both found.  If neither was found, mark all
-		     * but the first one found.
-		     */
-			if (np->f)
-			    npn->f = np->f;
-			else if (npn->f)
-			    np->f = npn->f;
-			else
-			    npn->f = 1;
-		    }
-		}
-	    }
-	    for (np = Nwad; np; np = np->next) {
-		if (!np->f && (cp = np->arg)) {
-		    rv = LSOF_SEARCH_FAILURE;
-		    if (Fverbose) {
-			(void) printf("%s: Internet address not located: ", Pn);
-			safestrprt(cp ? cp : "(unknown)", stdout, 1);
-		    }
-		}
-	    }
-	}
-	if (Fnet && Fnet < 2) {
-
-	/*
-	 * Report no Internet files located.
-	 */
-	    rv = LSOF_SEARCH_FAILURE;
-	    if (Fverbose)
-		(void) printf("%s: no Internet files located\n", Pn);
-	}
-
-#if	defined(HASTCPUDPSTATE)
-	if (TcpStIn) {
-
-	/*
-	 * Check for included TCP states not located.
-	 */
-	    for (i = 0; i < TcpNstates; i++) {
-		if (TcpStI[i] == 1) {
-		    rv = LSOF_SEARCH_FAILURE;
-		    if (Fverbose)
-			(void) printf("%s: TCP state not located: %s\n",
-			    Pn, TcpSt[i]);
-		}
-	    }
-	}
-	if (UdpStIn) {
-
-	/*
-	 * Check for included UDP states not located.
-	 */
-	    for (i = 0; i < UdpNstates; i++) {
-		if (UdpStI[i] == 1) {
-		    rv = LSOF_SEARCH_FAILURE;
-		    if (Fverbose)
-			(void) printf("%s: UDP state not located: %s\n",
-			    Pn, UdpSt[i]);
-		}
-	    }
-	}
-#endif	/* defined(HASTCPUDPSTATE) */
-
-	if (Fnfs && Fnfs < 2) {
-
-	/*
-	 * Report no NFS files located.
-	 */
-	    rv = LSOF_SEARCH_FAILURE;
-	    if (Fverbose)
-		(void) printf("%s: no NFS files located\n", Pn);
-	}
-	for (i = 0; i < Npid; i++) {
-
-	/*
-	 * Check inclusionary process ID specifications.
-	 */
-	    if (Spid[i].f || Spid[i].x)
-		continue;
-	    rv = LSOF_SEARCH_FAILURE;
-	    if (Fverbose)
-		(void) printf("%s: process ID not located: %d\n",
-		    Pn, Spid[i].i);
-	}
-
-#if	defined(HASTASKS)
-	if (Ftask && Ftask < 2) {
-
-	/*
-	 * Report no tasks located.
-	 */
-	    rv = LSOF_SEARCH_FAILURE;
-	    if (Fverbose)
-		(void) printf("%s: no tasks located\n", Pn);
-	}
-#endif	/* defined(HASTASKS) */
-
-#if	defined(HASZONES)
-	if (ZoneArg) {
-
-	/*
-	 * Check zone argument results.
-	 */
-	    for (i = 0; i < HASHZONE; i++) {
-		for (zp = ZoneArg[i]; zp; zp = zp->next) {
-		    if (!zp->f) {
-			rv = LSOF_SEARCH_FAILURE;
-			if (Fverbose) {
-			    (void) printf("%s: zone not located: ", Pn);
-			    safestrprt(zp->zn, stdout, 1);
-			}
-		    }
-		}
-	    }
-	}
-#endif	/* defined(HASZONES) */
-
-#if	defined(HASSELINUX)
-	if (CntxArg) {
-
-	/*
-	 * Check context argument results.
-	 */
-	    for (cntxp = CntxArg; cntxp; cntxp = cntxp->next) {
-		if (!cntxp->f) {
-		    rv = LSOF_SEARCH_FAILURE;
-		    if (Fverbose) {
-			(void) printf("%s: context not located: ", Pn);
-			safestrprt(cntxp->cntx, stdout, 1);
-		    }
-		}
-	    }
-	}
-#endif	/* defined(HASSELINUX) */
-
-	for (i = 0; i < Npgid; i++) {
-
-	/*
-	 * Check inclusionary process group ID specifications.
-	 */
-	    if (Spgid[i].f || Spgid[i].x)
-		continue;
-	    rv = LSOF_SEARCH_FAILURE;
-	    if (Fverbose)
-		(void) printf("%s: process group ID not located: %d\n",
-		    Pn, Spgid[i].i);
-	}
-	for (i = 0; i < Nuid; i++) {
-
-	/*
-	 * Check inclusionary user ID specifications.
-	 */
-	    if (Suid[i].excl || Suid[i].f)
-		continue;
-	    rv = LSOF_SEARCH_FAILURE;
-	    if (Fverbose) {
-		if (Suid[i].lnm) {
-		    (void) printf("%s: login name (UID %lu) not located: ",
-			Pn, (unsigned long)Suid[i].uid);
-		    safestrprt(Suid[i].lnm, stdout, 1);
-		} else
-		    (void) printf("%s: user ID not located: %lu\n", Pn,
-			(unsigned long)Suid[i].uid);
-	    }
-	}
-	if (!rv && rc)
-	    rv = ev;
-	if (!rv && ErrStat)
-	    rv = LSOF_ERROR;
-	Exit(rv);
-	return(rv);		/* to make code analyzers happy */
-}
-
-
-/*
- * GetOpt() -- Local get option
- *
- * Liberally adapted from the public domain AT&T getopt() source,
- * distributed at the 1985 UNIFORM conference in Dallas
- *
- * The modifications allow `?' to be an option character and allow
- * the caller to decide that an option that may be followed by a
- * value doesn't have one -- e.g., has a default instead.
- */
-
-static int
-GetOpt(ct, opt, rules, err)
-	int ct;				/* option count */
-	char *opt[];			/* options */
-	char *rules;			/* option rules */
-	int *err;			/* error return */
-{
-	register int c;
-	register char *cp = (char *)NULL;
-
-	if (GOx2 == 0) {
-
-	/*
-	 * Move to a new entry of the option array.
-	 *
-	 * EOF if:
-	 *
-	 *	Option list has been exhausted;
-	 *	Next option doesn't start with `-' or `+';
-	 *	Next option has nothing but `-' or `+';
-	 *	Next option is ``--'' or ``++''.
-	 */
-	    if (GOx1 >= ct
-	    ||  (opt[GOx1][0] != '-' && opt[GOx1][0] != '+')
-	    ||  !opt[GOx1][1])
-		 return(EOF);
-	    if (strcmp(opt[GOx1], "--") == 0 || strcmp(opt[GOx1], "++") == 0) {
-		GOx1++;
-		return(EOF);
-	    }
-	    GOp = opt[GOx1][0];
-	    GOx2 = 1;
-	}
-/*
- * Flag `:' option character as an error.
- *
- * Check for a rule on this option character.
- */
-	*err = 0;
-	if ((c = opt[GOx1][GOx2]) == ':') {
-	    (void) fprintf(stderr,
-		"%s: colon is an illegal option character.\n", Pn);
-	    *err = 1;
-	} else if (!(cp = strchr(rules, c))) {
-	    (void) fprintf(stderr, "%s: illegal option character: %c\n", Pn, c);
-	    *err = 2;
-	}
-	if (*err) {
-
-	/*
-	 * An error was detected.
-	 *
-	 * Advance to the next option character.
-	 *
-	 * Return the character causing the error.
-	 */
-	    if (opt[GOx1][++GOx2] == '\0') {
-		GOx1++;
-		GOx2 = 0;
-	    }
-	    return(c);
-	}
-	if (*(cp + 1) == ':') {
-
-	/*
-	 * The option may have a following value.  The caller decides
-	 * if it does.
-	 *
-	 * Save the position of the possible value in case the caller
-	 * decides it does not belong to the option and wants it
-	 * reconsidered as an option character.  The caller does that
-	 * with:
-	 *		GOx1 = GObk[0]; GOx2 = GObk[1];
-	 *
-	 * Don't indicate that an option of ``--'' is a possible value.
-	 *
-	 * Finally, on the assumption that the caller will decide that
-	 * the possible value belongs to the option, position to the
-	 * option following the possible value, so that the next call
-	 * to GetOpt() will find it.
-	 */
-	    if (opt[GOx1][GOx2 + 1] != '\0') {
-		GObk[0] = GOx1;
-		GObk[1] = ++GOx2;
-		GOv = &opt[GOx1++][GOx2];
-	    } else if (++GOx1 >= ct)
-		GOv = (char *)NULL;
-	    else {
-		GObk[0] = GOx1;
-		GObk[1] = 0;
-		GOv = opt[GOx1];
-		if (strcmp(GOv, "--") == 0)
-		    GOv = (char *)NULL;
-		else
-		    GOx1++;
-	    }
-	    GOx2 = 0;
-	} else {
-
-	/*
-	 * The option character stands alone with no following value.
-	 *
-	 * Advance to the next option character.
-	 */
-	    if (opt[GOx1][++GOx2] == '\0') {
-		GOx2 = 0;
-		GOx1++;
-	    }
-	    GOv = (char *)NULL;
-	}
-/*
- * Return the option character.
- */
-	return(c);
-}
-
-
-/*
- * sv_fmt_str() - save format string
- */
-
-static char *
-sv_fmt_str(f)
-	char *f;			/* format string */
-{
-	char *cp;
-	MALLOC_S l;
-
-	l = (MALLOC_S)(strlen(f) + 1);
-	if (!(cp = (char *)malloc(l))) {
-	    (void) fprintf(stderr,
-		"%s: can't allocate %d bytes for format: %s\n", Pn, (int)l, f);
-	    Error();
-	}
-	(void) snpf(cp, l, "%s", f);
-	return(cp);
-}
diff --git a/misc.c b/misc.c
deleted file mode 100644
index dde45be..0000000
--- a/misc.c
+++ /dev/null
@@ -1,1707 +0,0 @@
-/*
- * misc.c - common miscellaneous 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";
-#endif
-
-
-#include "lsof.h"
-
-#if	defined(HASWIDECHAR)
-# if	defined(WIDECHARINCL)
-#include WIDECHARINCL
-# endif	/* defined(WIDECHARINCL) */
-# if	defined(HASWCTYPE_H)
-#include <wctype.h>
-# endif	/* defined(HASWCTYPE_H) */
-#endif	/* defined(HASWIDECHAR) */
-
-
-/*
- * Local definitions
- */
-
-#if	!defined(MAXSYMLINKS)
-#define	MAXSYMLINKS	32
-#endif	/* !defined(MAXSYMLINKS) */
-
-
-/*
- * Local function prototypes
- */
-
-_PROTOTYPE(static void closePipes,(void));
-_PROTOTYPE(static int dolstat,(char *path, char *buf, int len));
-_PROTOTYPE(static int dostat,(char *path, char *buf, int len));
-_PROTOTYPE(static int doreadlink,(char *path, char *buf, int len));
-_PROTOTYPE(static int doinchild,(int (*fn)(), char *fp, char *rbuf, int rbln));
-
-#if	defined(HASINTSIGNAL)
-_PROTOTYPE(static int handleint,(int sig));
-#else	/* !defined(HASINTSIGNAL) */
-_PROTOTYPE(static void handleint,(int sig));
-#endif	/* defined(HASINTSIGNAL) */
-
-
-/*
- * Local variables
- */
-
-static pid_t Cpid = 0;			/* child PID */
-static jmp_buf Jmp_buf;			/* jump buffer */
-static int Pipes[] =			/* pipes for child process */
-	{ -1, -1, -1, -1 };
-static int CtSigs[] = { 0, SIGINT, SIGKILL };
-					/* child termination signals (in order
-					 * of application) -- the first is a
-					 * dummy to allow pipe closure to
-					 * cause the child to exit */
-#define	NCTSIGS	(sizeof(CtSigs) / sizeof(int))
-
-
-#if	defined(HASNLIST)
-/*
- * build-Nl() - build kernel name list table
- */
-
-static struct drive_Nl *Build_Nl = (struct drive_Nl *)NULL;
-					/* the default Drive_Nl address */
-
-void
-build_Nl(d)
-	struct drive_Nl *d;		/* data to drive the construction */
-{
-	struct drive_Nl *dp;
-	int i, n;
-
-	for (dp = d, n = 0; dp->nn; dp++, n++)
-	    ;
-	if (n < 1) {
-	    (void) fprintf(stderr,
-		"%s: can't calculate kernel name list length\n", Pn);
-	    Error();
-	}
-	if (!(Nl = (struct NLIST_TYPE *)calloc((n + 1),
-					       sizeof(struct NLIST_TYPE))))
-	{
-	    (void) fprintf(stderr,
-		"%s: can't allocate %d bytes to kernel name list structure\n",
-		Pn, (int)((n + 1) * sizeof(struct NLIST_TYPE)));
-	    Error();
-	}
-	for (dp = d, i = 0; i < n; dp++, i++) {
-	    Nl[i].NL_NAME = dp->knm;
-	}
-	Nll = (int)((n + 1) * sizeof(struct NLIST_TYPE));
-	Build_Nl = d;
-}
-#endif	/* defined(HASNLIST) */
-
-
-/*
- * childx() - make child process exit (if possible)
- */
-
-void
-childx()
-{
-	static int at, sx;
-	pid_t wpid;
-
-	if (Cpid > 1) {
-
-	/*
-	 * First close the pipes to and from the child.  That should cause the
-	 * child to exit.  Compute alarm time shares.
-	 */
-	    (void) closePipes();
-	    if ((at = TmLimit / NCTSIGS) < TMLIMMIN)
-		at = TMLIMMIN;
-	/*
-	 * Loop, waiting for the child to exit.  After the first pass, help
-	 * the child exit by sending it signals.
-	 */
-	    for (sx = 0; sx < NCTSIGS; sx++) {
-		if (setjmp(Jmp_buf)) {
-
-		/*
-		 * An alarm has rung.  Disable further alarms.
-		 *
-		 * If there are more signals to send, continue the signal loop.
-		 *
-		 * If the last signal has been sent, issue a warning (unless
-		 * warninge have been suppressed) and exit the signal loop.
-		 */
-		    (void) alarm(0);
-		    (void) signal(SIGALRM, SIG_DFL);
-		    if (sx < (NCTSIGS - 1))
-			continue;
-		    if (!Fwarn)
-			(void) fprintf(stderr,
-			    "%s: WARNING -- child process %d may be hung.\n",
-			    Pn, (int)Cpid);
-		    break;
-		}
-	    /*
-	     * Send the next signal to the child process, after the first pass
-	     * through the loop.
-	     *
-	     * Wrap the wait() with an alarm.
-	     */
-		if (sx)
-		    (void) kill(Cpid, CtSigs[sx]);
-		(void) signal(SIGALRM, handleint);
-		(void) alarm(at);
-		wpid = (pid_t) wait(NULL);
-		(void) alarm(0);
-		(void) signal(SIGALRM, SIG_DFL);
-		if (wpid == Cpid)
-		    break;
-	    }
-	    Cpid = 0;
-	}
-}
-
-
-/*
- * closePipes() - close open pipe file descriptors
- */
-
-static void
-closePipes()
-{
-	int i;
-
-	for (i = 0; i < 4; i++) {
-	    if (Pipes[i] >= 0) {
-		(void) close(Pipes[i]);
-		Pipes[i] = -1;
-	    }
-	}
-}
-
-
-/*
- * compdev() - compare Devtp[] entries
- */
-
-int
-compdev(a1, a2)
-	COMP_P *a1, *a2;
-{
-	struct l_dev **p1 = (struct l_dev **)a1;
-	struct l_dev **p2 = (struct l_dev **)a2;
-
-	if ((dev_t)((*p1)->rdev) < (dev_t)((*p2)->rdev))
-	    return(-1);
-	if ((dev_t)((*p1)->rdev) > (dev_t)((*p2)->rdev))
-	    return(1);
-	if ((INODETYPE)((*p1)->inode) < (INODETYPE)((*p2)->inode))
-	    return(-1);
-	if ((INODETYPE)((*p1)->inode) > (INODETYPE)((*p2)->inode))
-	    return(1);
-	return(strcmp((*p1)->name, (*p2)->name));
-}
-
-
-/*
- * doinchild() -- do a function in a child process
- */
-
-static int
-doinchild(fn, fp, rbuf, rbln)
-	int (*fn)();			/* function to perform */
-	char *fp;			/* function parameter */
-	char *rbuf;			/* response buffer */
-	int rbln;			/* response buffer length */
-{
-	int en, rv;
-
-/*
- * Check reply buffer size.
- */
-	if (!Fovhd && rbln > MAXPATHLEN) {
-	    (void) fprintf(stderr,
-		"%s: doinchild error; response buffer too large: %d\n",
-		Pn, rbln);
-	    Error();
-	}
-/*
- * Set up to handle an alarm signal; handle an alarm signal; build
- * pipes for exchanging information with a child process; start the
- * child process; and perform functions in the child process.
- */
-	if (!Fovhd) {
-	    if (setjmp(Jmp_buf)) {
-
-	    /*
-	     * Process an alarm that has rung.
-	     */
-		(void) alarm(0);
-		(void) signal(SIGALRM, SIG_DFL);
-		(void) childx();
-		errno = ETIMEDOUT;
-		return(1);
-	    } else if (!Cpid) {
-
-	    /*
-	     * Create pipes to exchange function information with a child
-	     * process.
-	     */
-		if (pipe(Pipes) < 0 || pipe(&Pipes[2]) < 0) {
-		    (void) fprintf(stderr, "%s: can't open pipes: %s\n",
-			Pn, strerror(errno));
-		    Error();
-		}
-	    /*
-	     * Fork a child to execute functions.
-	     */
-		if ((Cpid = fork()) == 0) {
-
-		/*
-		 * Begin the child process.
-		 */
-
-		    int r_al, r_rbln;
-		    char r_arg[MAXPATHLEN+1];
-		    union {
-			    char r_rbuf[MAXPATHLEN+1];
-			    /*
-			     * This field is only for adjusting the alignment of r_rbuf that
-			     * can be used as an argument for stat().
-			     */
-			    struct stat _;
-		    } r;
-		    int (*r_fn)();
-		/*
-		 * Close sufficient open file descriptors except Pipes[0] and
-		 * Pipes[3].
-		 */
-
-#if	defined(HAS_DUP2) && defined(HAS_CLOSEFROM)
-		    int rc;
-
-		    rc = dup2(Pipes[0], 0);
-		    if (rc < 0) {
-			(void) fprintf(stderr,
-			    "%s: can't dup Pipes[0] to fd 0: %s\n",
-			    Pn, strerror(errno));
-			Error();
-		    }
-		    Pipes[0] = 0;
-		    rc = dup2(Pipes[3], 1);
-		    if (rc < 0) {
-			(void) fprintf(stderr,
-			    "%s: can't dup Pipes.[3] to fd 1: %s\n",
-			    Pn, strerror(errno));
-			Error();
-		    }
-		    Pipes[3] = 1;
-		    (void) closefrom(2);
-		    Pipes[1] = -1;
-		    Pipes[2] = -1;
-
-#else	/* !defined(HAS_DUP2) && !defined(HAS_CLOSEFROM) */
-		    int fd;
-
-		    for (fd = 0; fd < MaxFd; fd++) {
-			if (fd == Pipes[0] || fd == Pipes[3])
-			    continue;
-			(void) close(fd);
-			if (fd == Pipes[1])
-			    Pipes[1] = -1;
-			else if (fd == Pipes[2])
-			    Pipes[2] = -1;
-		    }
-		    if (Pipes[1] >= 0) {
-			(void) close(Pipes[1]);
-			Pipes[1] = -1;
-		    }
-		    if (Pipes[2] >= 0) {
-			(void) close(Pipes[2]);
-			Pipes[2] = -1;
-		    }
-#endif	/* defined(HAS_DUP2) && defined(HAS_CLOSEFROM) */
-
-		/*
-		 * Read function requests, process them, and return replies.
-		 */
-		    for (;;) {
-			if (read(Pipes[0], (char *)&r_fn, sizeof(r_fn))
-			    != (int)sizeof(r_fn)
-			||  read(Pipes[0], (char *)&r_al, sizeof(int))
-			    != (int)sizeof(int)
-			||  r_al < 1
-			||  r_al > (int)sizeof(r_arg)
-			||  read(Pipes[0], r_arg, r_al) != r_al
-			||  read(Pipes[0], (char *)&r_rbln, sizeof(r_rbln))
-			    != (int)sizeof(r_rbln)
-			||  r_rbln < 1 || r_rbln > (int)sizeof(r.r_rbuf))
-			    break;
-			zeromem (r.r_rbuf, r_rbln);
-			rv = r_fn(r_arg, r.r_rbuf, r_rbln);
-			en = errno;
-			if (write(Pipes[3], (char *)&rv, sizeof(rv))
-			    != sizeof(rv)
-			||  write(Pipes[3], (char *)&en, sizeof(en))
-			    != sizeof(en)
-			||  write(Pipes[3], r.r_rbuf, r_rbln) != r_rbln)
-			    break;
-		    }
-		    (void) _exit(0);
-		}
-	    /*
-	     * Continue in the parent process to finish the setup.
-	     */
-		if (Cpid < 0) {
-		    (void) fprintf(stderr, "%s: can't fork: %s\n",
-			Pn, strerror(errno));
-		    Error();
-		}
-		(void) close(Pipes[0]);
-		(void) close(Pipes[3]);
-		Pipes[0] = Pipes[3] = -1;
-	    }
-	}
-	if (!Fovhd) {
-	    int len;
-
-	/*
-	 * Send a function to the child and wait for the response.
-	 */
-	    len  = strlen(fp) + 1;
-	    (void) signal(SIGALRM, handleint);
-	    (void) alarm(TmLimit);
-	    if (write(Pipes[1], (char *)&fn, sizeof(fn)) != sizeof(fn)
-	    ||  write(Pipes[1], (char *)&len, sizeof(len)) != sizeof(len)
-	    ||  write(Pipes[1], fp, len) != len
-	    ||  write(Pipes[1], (char *)&rbln, sizeof(rbln)) != sizeof(rbln)
-	    ||  read(Pipes[2], (char *)&rv, sizeof(rv)) != sizeof(rv)
-	    ||  read(Pipes[2], (char *)&en, sizeof(en)) != sizeof(en)
-	    ||  read(Pipes[2], rbuf, rbln) != rbln) {
-		(void) alarm(0);
-		(void) signal(SIGALRM, SIG_DFL);
-		(void) childx();
-		errno = ECHILD;
-		return(-1);
-	    }
-	} else {
-
-	/*
-	 * Do the operation directly -- not in a child.
-	 */
-	    (void) signal(SIGALRM, handleint);
-	    (void) alarm(TmLimit);
-	    rv = fn(fp, rbuf, rbln);
-	    en = errno;
-	}
-/*
- * Function completed, response collected -- complete the operation.
- */
-	(void) alarm(0);
-	(void) signal(SIGALRM, SIG_DFL);
-	errno = en;
-	return(rv);
-}
-
-
-/*
- * dolstat() - do an lstat() function
- */
-
-static int
-dolstat(path, rbuf, rbln)
-	char *path;			/* path */
-	char *rbuf;			/* response buffer */
-	int rbln;			/* response buffer length */
-
-/* ARGSUSED */
-
-{
-	return(lstat(path, (struct stat *)rbuf));
-}
-
-
-/*
- * doreadlink() -- do a readlink() function
- */
-
-static int
-doreadlink(path, rbuf, rbln)
-	char *path;			/* path */
-	char *rbuf;			/* response buffer */
-	int rbln;			/* response buffer length */
-{
-	return(readlink(path, rbuf, rbln));
-}
-
-
-/*
- * dostat() - do a stat() function
- */
-
-static int
-dostat(path, rbuf, rbln)
-	char *path;			/* path */
-	char *rbuf;			/* response buffer */
-	int rbln;			/* response buffer length */
-
-/* ARGSUSED */
-
-{
-	return(stat(path, (struct stat *)rbuf));
-}
-
-
-#if	defined(WILLDROPGID)
-/*
- * dropgid() - drop setgid permission
- */
-
-void
-dropgid()
-{
-	if (!Setuidroot && Setgid) {
-	    if (setgid(Mygid) < 0) {
-		(void) fprintf(stderr, "%s: can't setgid(%d): %s\n",
-		    Pn, (int)Mygid, strerror(errno));
-		Error();
-	    }
-	    Setgid = 0;
-	}
-}
-#endif	/* defined(WILLDROPGID) */
-
-
-/*
- * enter_dev_ch() - enter device characters in file structure
- */
-
-void
-enter_dev_ch(m)
-	char *m;
-{
-	char *mp;
-
-	if (!m || *m == '\0')
-	    return;
-	if (!(mp = mkstrcpy(m, (MALLOC_S *)NULL))) {
-	    (void) fprintf(stderr, "%s: no more dev_ch space at PID %d: \n",
-		Pn, Lp->pid);
-	    safestrprt(m, stderr, 1);
-	    Error();
-	}
-	if (Lf->dev_ch)
-	   (void) free((FREE_P *)Lf->dev_ch);
-	Lf->dev_ch = mp;
-}
-
-
-/*
- * enter_IPstate() -- enter a TCP or UDP state
- */
-
-void
-enter_IPstate(ty, nm, nr)
-	char *ty;			/* type -- TCP or UDP */
-	char *nm;			/* state name (may be NULL) */
-	int nr;				/* state number */
-{
-
-#if	defined(USE_LIB_PRINT_TCPTPI)
-	TcpNstates = nr;
-#else	/* !defined(USE_LIB_PRINT_TCPTPI) */
-
-	int al, i, j, oc, nn, ns, off, tx;
-	char *cp;
-	MALLOC_S len;
-/*
- * Check the type name and set the type index.
- */
-	if (!ty) {
-	    (void) fprintf(stderr,
-		"%s: no type specified to enter_IPstate()\n", Pn);
-	    Error();
-	}
-	if (!strcmp(ty, "TCP"))
-	    tx = 0;
-	else if (!strcmp(ty, "UDP"))
-	    tx = 1;
-	else {
-	    (void) fprintf(stderr, "%s: unknown type for enter_IPstate: %s\n",
-		Pn, ty);
-	    Error();
-	}
-/*
- * If the name argument is NULL, reduce the allocated table to its minimum
- * size.
- */
-	if (!nm) {
-	    if (tx) {
-		if (UdpSt) {
-		    if (!UdpNstates) {
-			(void) free((MALLOC_P *)UdpSt);
-			UdpSt = (char **)NULL;
-		    }
-		    if (UdpNstates < UdpStAlloc) {
-			len = (MALLOC_S)(UdpNstates * sizeof(char *));
-			if (!(UdpSt = (char **)realloc((MALLOC_P *)UdpSt, len)))
-			{
-			    (void) fprintf(stderr,
-				"%s: can't reduce UdpSt[]\n", Pn);
-			    Error();
-			}
-		    }
-		    UdpStAlloc = UdpNstates;
-		}
-	    } else {
-		if (TcpSt) {
-		    if (!TcpNstates) {
-			(void) free((MALLOC_P *)TcpSt);
-			TcpSt = (char **)NULL;
-		    }
-		    if (TcpNstates < TcpStAlloc) {
-			len = (MALLOC_S)(TcpNstates * sizeof(char *));
-			if (!(TcpSt = (char **)realloc((MALLOC_P *)TcpSt, len)))
-			{
-			    (void) fprintf(stderr,
-				"%s: can't reduce TcpSt[]\n", Pn);
-			    Error();
-			}
-		    }
-		    TcpStAlloc = TcpNstates;
-		}
-	    }
-	    return;
-	}
-/*
- * Check the name and number.
- */
-	if ((len = (size_t)strlen(nm)) < 1) {
-	    (void) fprintf(stderr,
-		"%s: bad %s name (\"%s\"), number=%d\n", Pn, ty, nm, nr);
-	    Error();
-	}
-/*
- * Make a copy of the name.
- */
-	if (!(cp = mkstrcpy(nm, (MALLOC_S *)NULL))) {
-	    (void) fprintf(stderr,
-		"%s: enter_IPstate(): no %s space for %s\n",
-		Pn, ty, nm);
-	    Error();
-	}
-/*
- * Set the necessary offset for using nr as an index.  If it is
- * a new offset, adjust previous entries.
- */
-	if ((nr < 0) && ((off = -nr) > (tx ? UdpStOff : TcpStOff))) {
-	    if (tx ? UdpSt : TcpSt) {
-
-	    /*
-	     * A new, larger offset (smaller negative state number) could mean
-	     * a previously allocated state table must be enlarged and its
-	     * previous entries moved.
-	     */
-		oc = off - (tx ? UdpStOff : TcpStOff);
-		al = tx ? UdpStAlloc : TcpStAlloc;
-		ns = tx ? UdpNstates : TcpNstates;
-		if ((nn = ns + oc) >= al) {
-		    while ((nn + 5) > al) {
-			al += TCPUDPALLOC;
-		    }
-		    len = (MALLOC_S)(al * sizeof(char *));
-		    if (tx) {
-			if (!(UdpSt = (char **)realloc((MALLOC_P *)UdpSt, len)))
-			    goto no_IP_space;
-			UdpStAlloc = al;
-		    } else {
-			if (!(TcpSt = (char **)realloc((MALLOC_P *)TcpSt, len)))
-			    goto no_IP_space;
-			TcpStAlloc = al;
-		    }
-		    for (i = 0, j = oc; i < oc; i++, j++) {
-			if (tx) {
-			    if (i < UdpNstates)
-				UdpSt[j] = UdpSt[i];
-			    UdpSt[i] = (char *)NULL;
-			} else {
-			    if (i < TcpNstates)
-				TcpSt[j] = TcpSt[i];
-			    TcpSt[i] = (char *)NULL;
-			}
-		    }
-		    if (tx)
-			UdpNstates += oc;
-		    else
-			TcpNstates += oc;
-		}
-	    }
-	    if (tx)
-		UdpStOff = off;
-	    else
-		TcpStOff = off;
-	}
-/*
- * Enter name as {Tc|Ud}pSt[nr + {Tc|Ud}pStOff].
- *
- * Allocate space, as required.
- */
-	al = tx ? UdpStAlloc : TcpStAlloc;
-	off = tx ? UdpStOff : TcpStOff;
-	nn = nr + off + 1;
-	if (nn > al) {
-	    i = tx ? UdpNstates : TcpNstates;
-	    while ((nn + 5) > al) {
-		al += TCPUDPALLOC;
-	    }
-	    len = (MALLOC_S)(al * sizeof(char *));
-	    if (tx) {
-		if (UdpSt)
-		    UdpSt = (char **)realloc((MALLOC_P *)UdpSt, len);
-		else
-		    UdpSt = (char **)malloc(len);
-		if (!UdpSt) {
-
-no_IP_space:
-
-		    (void) fprintf(stderr, "%s: no %s state space\n", Pn, ty);
-		    Error();
-		}
-		UdpNstates = nn;
-		UdpStAlloc = al;
-	    } else {
-		if (TcpSt)
-		    TcpSt = (char **)realloc((MALLOC_P *)TcpSt, len);
-		else
-		    TcpSt = (char **)malloc(len);
-		if (!TcpSt)
-		    goto no_IP_space;
-		TcpNstates = nn;
-		TcpStAlloc = al;
-	    }
-	    while (i < al) {
-		if (tx)
-		    UdpSt[i] = (char *)NULL;
-		else
-		    TcpSt[i] = (char *)NULL;
-		i++;
-	    }
-	} else {
-	    if (tx) {
-		if (nn > UdpNstates)
-		    UdpNstates = nn;
-	    } else {
-		if (nn > TcpNstates)
-		    TcpNstates = nn;
-	    }
-	}
-	if (tx) {
-	    if (UdpSt[nr + UdpStOff]) {
-
-dup_IP_state:
-
-		(void) fprintf(stderr,
-		    "%s: duplicate %s state %d (already %s): %s\n",
-		    Pn, ty, nr,
-		    tx ? UdpSt[nr + UdpStOff] : TcpSt[nr + TcpStOff],
-		    nm);
-		Error();
-	    }
-	    UdpSt[nr + UdpStOff] = cp;
-	} else {
-	    if (TcpSt[nr + TcpStOff])
-		goto dup_IP_state;
-	    TcpSt[nr + TcpStOff] = cp;
-	}
-#endif	/* defined(USE_LIB_PRINT_TCPTPI) */
-
-}
-
-
-/*
- * enter_nm() - enter name in local file structure
- */
-
-void
-enter_nm(m)
-	char *m;
-{
-	char *mp;
-
-	if (!m || *m == '\0')
-	    return;
-	if (!(mp = mkstrcpy(m, (MALLOC_S *)NULL))) {
-	    (void) fprintf(stderr, "%s: no more nm space at PID %d for: ",
-		Pn, Lp->pid);
-	    safestrprt(m, stderr, 1);
-	    Error();
-	}
-	if (Lf->nm)
-	    (void) free((FREE_P *)Lf->nm);
-	Lf->nm = mp;
-}
-
-
-/*
- * Exit() - do a clean exit()
- */
-
-void
-Exit(xv)
-	enum ExitStatus xv;				/* exit() value */
-{
-	(void) childx();
-
-#if	defined(HASDCACHE)
-	if (DCrebuilt && !Fwarn)
-	    (void) fprintf(stderr, "%s: WARNING: %s was updated.\n",
-		Pn, DCpath[DCpathX]);
-#endif	/* defined(HASDCACHE) */
-
-	exit(xv);
-}
-
-
-/*
- * Error() - exit with an error status
- */
-void
-Error(void)
-{
-	Exit (LSOF_ERROR);
-}
-
-
-#if	defined(HASNLIST)
-/*
- * get_Nl_value() - get Nl value for nickname
- */
-
-int
-get_Nl_value(nn, d, v)
-	char *nn;			/* nickname of requested entry */
-	struct drive_Nl *d;		/* drive_Nl table that built Nl
-					 * (if NULL, use Build_Nl) */
-	KA_T *v;			/* returned value (if NULL,
-					 * return nothing) */
-{
-	int i;
-
-	if (!Nl || !Nll)
-	    return(-1);
-	if (!d)
-	    d = Build_Nl;
-	for (i = 0; d->nn; d++, i++) {
-	    if (strcmp(d->nn, nn) == 0) {
-		if (v)
-		    *v = (KA_T)Nl[i].n_value;
-		return(i);
-	    }
-	}
-	return(-1);
-}
-#endif	/* defined(HASNLIST) */
-
-
-/*
- * handleint() - handle an interrupt
- */
-
-#if	defined(HASINTSIGNAL)
-static int
-#else
-static void
-#endif
-
-/* ARGSUSED */
-
-handleint(sig)
-	int sig;
-{
-	longjmp(Jmp_buf, 1);
-}
-
-
-/*
- * hashbyname() - hash by name
- */
-
-int
-hashbyname(nm, mod)
-	char *nm;			/* pointer to NUL-terminated name */
-	int mod;			/* hash modulus */
-{
-	int i, j;
-
-	for (i = j = 0; *nm; nm++) {
-	    i ^= (int)*nm << j;
-	    if (++j > 7)
-		j = 0;
-	}
-	return(((int)(i * 31415)) & (mod - 1));
-}
-
-
-/*
- * is_nw_addr() - is this network address selected?
- */
-
-int
-is_nw_addr(ia, p, af)
-	unsigned char *ia;		/* Internet address */
-	int p;				/* port */
-	int af;				/* address family -- e.g., AF_INET,
-					 * AF_INET6 */
-{
-	struct nwad *n;
-
-	if (!(n = Nwad))
-	    return(0);
-	for (; n; n = n->next) {
-	    if (n->proto) {
-		if (strcasecmp(n->proto, Lf->iproto) != 0)
-		    continue;
-	    }
-	    if (af && n->af && af != n->af)
-		continue;
-
-#if	defined(HASIPv6)
-	    if (af == AF_INET6) {
-		if (n->a[15] || n->a[14] || n->a[13] || n->a[12]
-		||  n->a[11] || n->a[10] || n->a[9]  || n->a[8]
-		||  n->a[7]  || n->a[6]  || n->a[5]  || n->a[4]
-		||  n->a[3]  || n->a[2]  || n->a[1]  || n->a[0]) {
-		    if (ia[15] != n->a[15] || ia[14] != n->a[14]
-		    ||  ia[13] != n->a[13] || ia[12] != n->a[12]
-		    ||  ia[11] != n->a[11] || ia[10] != n->a[10]
-		    ||  ia[9]  != n->a[9]  || ia[8]  != n->a[8]
-		    ||  ia[7]  != n->a[7]  || ia[6]  != n->a[6]
-		    ||  ia[5]  != n->a[5]  || ia[4]  != n->a[4]
-		    ||  ia[3]  != n->a[3]  || ia[2]  != n->a[2]
-		    ||  ia[1]  != n->a[1]  || ia[0]  != n->a[0])
-			continue;
-		}
-	    } else if (af == AF_INET)
-#endif	/* defined(HASIPv6) */
-
-	    {
-		if (n->a[3] || n->a[2] || n->a[1] || n->a[0]) {
-		    if (ia[3] != n->a[3] || ia[2] != n->a[2]
-		    ||  ia[1] != n->a[1] || ia[0] != n->a[0])
-			continue;
-		}
-	    }
-
-#if	defined(HASIPv6)
-	    else
-		continue;
-#endif	/* defined(HASIPv6) */
-
-	    if (n->sport == -1 || (p >= n->sport && p <= n->eport)) {
-		n->f = 1;
-		return(1);
-	    }
-	}
-	return(0);
-}
-
-
-/*
- * mkstrcpy() - make a string copy in malloc()'d space
- *
- * return: copy pointer
- *	   copy length (optional)
- */
-
-char *
-mkstrcpy(src, rlp)
-	char *src;			/* source */
-	MALLOC_S *rlp;			/* returned length pointer (optional)
-					 * The returned length is an strlen()
-					 * equivalent */
-{
-	MALLOC_S len;
-	char *ns;
-
-	len = (MALLOC_S)(src ? strlen(src) : 0);
-	ns = (char *)malloc(len + 1);
-	if (ns) {
-	    if (src)
-		(void) snpf(ns, len + 1, "%s", src);
-	    else
-		*ns = '\0';
-	}
-	if (rlp)
-	    *rlp = len;
-	return(ns);
-}
-
-
-/*
- * mkstrcat() - make a catenated copy of up to three strings under optional
- *		string-by-string count control
- *
- * return: copy pointer
- *	   copy string length (optional)
- */
-
-char *
-mkstrcat(s1, l1, s2, l2, s3, l3, clp)
-	char *s1;			/* source string 1 */
-	int l1;				/* length of string 1 (-1 if none) */
-	char *s2;			/* source string 2 */
-	int l2;				/* length of string 2 (-1 if none) */
-	char *s3;			/* source string 3 (optional) */
-	int l3	;			/* length of string 3 (-1 if none) */
-	MALLOC_S *clp;			/* pointer to return of copy length
-					 * (optional) */
-{
-	MALLOC_S cl, len1, len2, len3;
-	char *cp;
-
-	if (s1)
-	    len1 = (MALLOC_S)((l1 >= 0) ? l1 : strlen(s1));
-	else
-	    len1 = (MALLOC_S)0;
-	if (s2)
-	    len2 = (MALLOC_S)((l2 >= 0) ? l2 : strlen(s2));
-	else
-	    len2 = (MALLOC_S)0;
-	if (s3)
-	    len3 = (MALLOC_S)((l3 >= 0) ? l3 : strlen(s3));
-	else
-	    len3 = (MALLOC_S)0;
-	cl = len1 + len2 + len3;
-	if ((cp = (char *)malloc(cl + 1))) {
-	    char *tp = cp;
-
-	    if (s1 && len1) {
-		(void) strncpy(tp, s1, len1);
-		tp += len1;
-	    }
-	    if (s2 && len2) {
-		(void) strncpy(tp, s2, len2);
-		tp += len2;
-	    }
-	    if (s3 && len3) {
-		(void) strncpy(tp, s3, len3);
-		tp += len3;
-	    }
-	    *tp = '\0';
-	}
-	if (clp)
-	    *clp = cl;
-	return(cp);
-}
-
-
-/*
- * is_readable() -- is file readable
- */
-
-int
-is_readable(path, msg)
-	char *path;			/* file path */
-	int msg;			/* issue warning message if 1 */
-{
-	if (access(path, R_OK) < 0) {
-	    if (!Fwarn && msg == 1)
-		(void) fprintf(stderr, ACCESSERRFMT, Pn, path, strerror(errno));
-	    return(0);
-	}
-	return(1);
-}
-
-
-/*
- * lstatsafely() - lstat path safely (i. e., with timeout)
- */
-
-int
-lstatsafely(path, buf)
-	char *path;			/* file path */
-	struct stat *buf;		/* stat buffer address */
-{
-	if (Fblock) {
-	    if (!Fwarn)
-		(void) fprintf(stderr,
-		    "%s: avoiding stat(%s): -b was specified.\n",
-		    Pn, path);
-	    errno = EWOULDBLOCK;
-	    return(1);
-	}
-	return(doinchild(dolstat, path, (char *)buf, sizeof(struct stat)));
-}
-
-
-/*
- * Readlink() - read and interpret file system symbolic links
- */
-
-char *
-Readlink(arg)
-	char *arg;			/* argument to be interpreted */
-{
-	char abuf[MAXPATHLEN+1];
-	int alen;
-	char *ap;
-	char *argp1, *argp2;
-	int i, len, llen, slen;
-	char lbuf[MAXPATHLEN+1];
-	static char *op = (char *)NULL;
-	static int ss = 0;
-	char *s1;
-	static char **stk = (char **)NULL;
-	static int sx = 0;
-	char tbuf[MAXPATHLEN+1];
-/*
- * See if avoiding kernel blocks.
- */
-	if (Fblock) {
-	    if (!Fwarn) {
-		(void) fprintf(stderr, "%s: avoiding readlink(", Pn);
-		safestrprt(arg, stderr, 0);
-		(void) fprintf(stderr, "): -b was specified.\n");
-	    }
-	    op = (char *)NULL;
-	    return(arg);
-	}
-/*
- * Save the original path.
- */
-	if (!op)
-	    op = arg;
-/*
- * Evaluate each component of the argument for a symbolic link.
- */
-	for (alen = 0, ap = abuf, argp1 = argp2 = arg; *argp2; argp1 = argp2 ) {
-	    for (argp2 = argp1 + 1; *argp2 && *argp2 != '/'; argp2++)
-		;
-	    if ((len = argp2 - arg) >= (int)sizeof(tbuf)) {
-
-path_too_long:
-		if (!Fwarn) {
-		    (void) fprintf(stderr,
-			"%s: readlink() path too long: ", Pn);
-		    safestrprt(op ? op : arg, stderr, 1);
-		}
-		op = (char *)NULL;
-		return((char *)NULL);
-	    }
-	    (void) strncpy(tbuf, arg, len);
-	    tbuf[len] = '\0';
-	/*
-	 * Dereference a symbolic link.
-	 */
-	    if ((llen=doinchild(doreadlink,tbuf,lbuf,sizeof(lbuf) - 1)) >= 0) {
-
-	    /*
-	     * If the link is a new absolute path, replace
-	     * the previous assembly with it.
-	     */
-		if (lbuf[0] == '/') {
-		    (void) strncpy(abuf, lbuf, llen);
-		    ap = &abuf[llen];
-		    *ap = '\0';
-		    alen = llen;
-		    continue;
-		}
-		lbuf[llen] = '\0';
-		s1 = lbuf;
-	    } else {
-		llen = argp2 - argp1;
-		s1 = argp1;
-	    }
-	/*
-	 * Make sure two components are separated by a `/'.
-	 *
-	 * If the first component is not a link, don't force
-	 * a leading '/'.
-	 *
-	 * If the first component is a link and the source of
-	 * the link has a leading '/', force a leading '/'.
-	 */
-	    if (*s1 == '/')
-		slen = 1;
-	    else {
-		if (alen > 0) {
-
-		/*
-		 * This is not the first component.
-		 */
-		    if (abuf[alen - 1] == '/')
-			slen = 1;
-		    else
-			slen = 2;
-		} else {
-
-		/*
-		 * This is the first component.
-		 */
-		    if (s1 == lbuf && tbuf[0] == '/')
-			slen = 2;
-		    else
-			slen = 1;
-		}
-	    }
-	/*
-	 * Add to the path assembly.
-	 */
-	    if ((alen + llen + slen) >= (int)sizeof(abuf))
-		goto path_too_long;
-	    if (slen == 2)
-		*ap++ = '/';
-	    (void) strncpy(ap, s1, llen);
-	    ap += llen;
-	    *ap = '\0';
-	    alen += (llen + slen - 1);
-	}
-/*
- * If the assembled path and argument are the same, free all but the
- * last string in the stack, and return the argument.
- */
-	if (strcmp(arg, abuf) == 0) {
-	    for (i = 0; i < sx; i++) {
-		if (i < (sx - 1))
-		    (void) free((FREE_P *)stk[i]);
-		stk[i] = (char *)NULL;
-	    }
-	    sx = 0;
-	    op = (char *)NULL;
-	    return(arg);
-	}
-/*
- * If the assembled path and argument are different, add it to the
- * string stack, then Readlink() it.
- */
-	if (!(s1 = mkstrcpy(abuf, (MALLOC_S *)NULL))) {
-
-no_readlink_space:
-
-	    (void) fprintf(stderr, "%s: no Readlink string space for ", Pn);
-	    safestrprt(abuf, stderr, 1);
-	    Error();
-	}
-	if (sx >= MAXSYMLINKS) {
-
-	/*
-	 * If there are too many symbolic links, report an error, clear
-	 * the stack, and return no path.
-	 */
-	    if (!Fwarn) {
-		(void) fprintf(stderr,
-		    "%s: too many (> %d) symbolic links in readlink() path: ",
-			Pn, MAXSYMLINKS);
-		safestrprt(op ? op : arg, stderr, 1);
-	    }
-	    for (i = 0; i < sx; i++) {
-		(void) free((FREE_P *)stk[i]);
-		stk[i] = (char *)NULL;
-	    }
-	    (void) free((FREE_P *)stk);
-	    (void) free((FREE_P *)s1);
-	    stk = (char **)NULL;
-	    ss = sx = 0;
-	    s1 = (char *)NULL;
-	    op = (char *)NULL;
-	    return((char *)NULL);
-	}
-	if (++sx > ss) {
-	    if (!stk)
-		stk = (char **)malloc((MALLOC_S)(sizeof(char *) * sx));
-	    else
-		stk = (char **)realloc((MALLOC_P *)stk,
-					(MALLOC_S)(sizeof(char *) * sx));
-	    if (!stk)
-		goto no_readlink_space;
-	    ss = sx;
-	}
-	stk[sx - 1] = s1;
-	return(Readlink(s1));
-}
-
-
-#if	defined(HASSTREAMS)
-/*
- * readstdata() - read stream's stdata structure
- */
-
-int
-readstdata(addr, buf)
-	KA_T addr;			/* stdata address in kernel*/
-	struct stdata *buf;		/* buffer addess */
-{
-	if (!addr
-	||  kread(addr, (char *)buf, sizeof(struct stdata))) {
-	    (void) snpf(Namech, Namechl, "no stream data in %s",
-		print_kptr(addr, (char *)NULL, 0));
-	    return(1);
-	}
-	return(0);
-}
-
-
-/*
- * readsthead() - read stream head
- */
-
-int
-readsthead(addr, buf)
-	KA_T addr;			/* starting queue pointer in kernel */
-	struct queue *buf;		/* buffer for queue head */
-{
-	KA_T qp;
-
-	if (!addr) {
-	    (void) snpf(Namech, Namechl, "no stream queue head");
-	    return(1);
-	}
-	for (qp = addr; qp; qp = (KA_T)buf->q_next) {
-	    if (kread(qp, (char *)buf, sizeof(struct queue))) {
-		(void) snpf(Namech, Namechl, "bad stream queue link at %s",
-		    print_kptr(qp, (char *)NULL, 0));
-		return(1);
-	    }
-	}
-	return(0);
-}
-
-
-/*
- * readstidnm() - read stream module ID name
- */
-
-int
-readstidnm(addr, buf, len)
-	KA_T addr;			/* module ID name address in kernel */
-	char *buf;			/* receiving buffer address */
-	READLEN_T len;			/* buffer length */
-{
-	if (!addr || kread(addr, buf, len)) {
-	    (void) snpf(Namech, Namechl, "can't read module ID name from %s",
-		print_kptr(addr, (char *)NULL, 0));
-	    return(1);
-	}
-	return(0);
-}
-
-
-/*
- * readstmin() - read stream's module info
- */
-
-int
-readstmin(addr, buf)
-	KA_T addr;			/* module info address in kernel */
-	struct module_info *buf;	/* receiving buffer address */
-{
-	if (!addr || kread(addr, (char *)buf, sizeof(struct module_info))) {
-	    (void) snpf(Namech, Namechl, "can't read module info from %s",
-		print_kptr(addr, (char *)NULL, 0));
-	    return(1);
-	}
-	return(0);
-}
-
-
-/*
- * readstqinit() - read stream's queue information structure
- */
-
-int
-readstqinit(addr, buf)
-	KA_T addr;			/* queue info address in kernel */
-	struct qinit *buf;		/* receiving buffer address */
-{
-	if (!addr || kread(addr, (char *)buf, sizeof(struct qinit))) {
-	    (void) snpf(Namech, Namechl, "can't read queue info from %s",
-		print_kptr(addr, (char *)NULL, 0));
-	    return(1);
-	}
-	return(0);
-}
-#endif	/* HASSTREAMS */
-
-
-/*
- * safepup() - safely print an unprintable character -- i.e., print it in a
- *	       printable form
- *
- * return: char * to printable equivalent
- *	   cl = strlen(printable equivalent)
- */
-
-char *
-safepup(c, cl)
-	unsigned int c;			/* unprintable (i.e., !isprint())
-					 * character  and '\\' */
-	int *cl;			/* returned printable strlen -- NULL if
-					 * no return needed */
-{
-	int len;
-	char *rp;
-	static char up[8];
-
-	if (c < 0x20) {
-	    switch (c) {
-	    case '\b':
-		rp = "\\b";
-		break;
-	    case '\f':
-		rp = "\\f";
-		break;
-	    case '\n':
-		rp = "\\n";
-		break;
-	    case '\r':
-		rp = "\\r";
-		break;
-	    case '\t':
-		rp = "\\t";
-		break;
-	    default:
-		(void) snpf(up, sizeof(up), "^%c", c + 0x40);
-		rp = up;
-	    }
-	    len = 2;
-	} 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;
-	    len = 4;
-	}
-	if (cl)
-	    *cl = len;
-	return(rp);
-}
-
-
-/*
- * safestrlen() - calculate a "safe" string length -- i.e., compute space for
- *		  non-printable characters when printed in a printable form
- */
-
-int
-safestrlen(sp, flags)
-	char *sp;			/* string pointer */
-	int flags;			/* flags:
-					 *   bit 0: 0 (0) = no NL
-					 *	    1 (1) = add trailing NL
-					 *	 1: 0 (0) = ' ' printable
-					 *	    1 (2) = ' ' not printable
-					 */
-{
-	char c;
-	int len = 0;
-
-	c = (flags & 2) ? ' ' : '\0';
-	if (sp) {
-	    for (; *sp; sp++) {
-		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 */
-		} else
-		    len++;
-	    }
-	}
-	return(len);
-}
-
-
-/*
- * safestrprt() - print a string "safely" to the indicated stream -- i.e.,
- *		  print unprintable characters in a printable form
- */
-
-void
-safestrprt(sp, fs, flags)
-	char *sp;			/* string to print pointer pointer */
-	FILE *fs;			/* destination stream -- e.g., stderr
-					 * or stdout */
-	int flags;			/* flags:
-					 *   bit 0: 0 (0) = no NL
-					 *	    1 (1) = add trailing NL
-					 *	 1: 0 (0) = ' ' printable
-					 *	    1 (2) = ' ' not printable
-					 *	 2: 0 (0) = print string as is
-					 *	    1 (4) = surround string
-					 *		    with '"'
-					 *	 4: 0 (0) = print ending '\n'
-					 *	    1 (8) = don't print ending
-					 *		    '\n'
-					 */
-{
-	char c;
-	int lnc, lnt, sl;
-
-#if	defined(HASWIDECHAR)
-	wchar_t w;
-	int wcmx = MB_CUR_MAX;
-#else	/* !defined(HASWIDECHAR) */
-	static int wcmx = 1;
-#endif	/* defined(HASWIDECHAR) */
-
-	c = (flags & 2) ? ' ' : '\0';
-	if (flags & 4)
-	    putc('"', fs);
-	if (sp) {
-	    for (sl = strlen(sp); *sp; sl -= lnc, sp += lnc) {
-
-#if	defined(HASWIDECHAR)
-		if (wcmx > 1) {
-		    lnc = mblen(sp, sl);
-		    if (lnc > 1) {
-			if ((mbtowc(&w, sp, sl) == lnc) && iswprint(w)) {
-			    for (lnt = 0; lnt < lnc; lnt++) {
-				putc((int)*(sp + lnt), fs);
-			    }
-			} else {
-			    for (lnt = 0; lnt < lnc; lnt++) {
-				fputs(safepup((unsigned int)*(sp + lnt),
-					      (int *)NULL), fs);
-			    }
-			}
-			continue;
-		    } else
-			lnc = 1;
-		} else
-		    lnc = 1;
-#else	/* !defined(HASWIDECHAR) */
-		lnc = 1;
-#endif	/* defined(HASWIDECHAR) */
-
-		if ((*sp != '\\') && isprint((unsigned char)*sp) && *sp != c)
-		    putc((int)(*sp & 0xff), fs);
-		else {
-		    if ((flags & 8) && (*sp == '\n') && !*(sp + 1))
-			break;
-		    fputs(safepup((unsigned int)*sp, (int *)NULL), fs);
-		}
-	    }
-	}
-	if (flags & 4)
-	    putc('"', fs);
-	if (flags & 1)
-	    putc('\n', fs);
-}
-
-
-/*
- * safestrprtn() - print a specified number of characters from a string
- *		   "safely" to the indicated stream
- */
-
-void
-safestrprtn(sp, len, fs, flags)
-	char *sp;			/* string to print pointer pointer */
-	int len;			/* safe number of characters to
-					 * print */
-	FILE *fs;			/* destination stream -- e.g., stderr
-					 * or stdout */
-	int flags;			/* flags:
-					 *   bit 0: 0 (0) = no NL
-					 *	    1 (1) = add trailing NL
-					 *	 1: 0 (0) = ' ' printable
-					 *	    1 (2) = ' ' not printable
-					 *	 2: 0 (0) = print string as is
-					 *	    1 (4) = surround string
-					 *		    with '"'
-					 *	 4: 0 (0) = print ending '\n'
-					 *	    1 (8) = don't print ending
-					 *		    '\n'
-					 */
-{
-	char c, *up;
-	int cl, i;
-
-	if (flags & 4)
-	    putc('"', fs);
-	if (sp) {
-	    c = (flags & 2) ? ' ' : '\0';
-	    for (i = 0; i < len && *sp; sp++) {
-		if ((*sp != '\\') && isprint((unsigned char)*sp) && *sp != c) {
-		    putc((int)(*sp & 0xff), fs);
-		    i++;
-		} else {
-		    if ((flags & 8) && (*sp == '\n') && !*(sp + 1))
-			break;
-		    up = safepup((unsigned int)*sp, &cl);
-		    if ((i + cl) > len)
-			break;
-		    fputs(up, fs);
-		    i += cl;
-		}
-	    }
-	} else
-	    i = 0;
-	for (; i < len; i++)
-	    putc(' ', fs);
-	if (flags & 4)
-	    putc('"', fs);
-	if (flags & 1)
-	    putc('\n', fs);
-}
-
-
-/*
- * statsafely() - stat path safely (i. e., with timeout)
- */
-
-int
-statsafely(path, buf)
-	char *path;			/* file path */
-	struct stat *buf;		/* stat buffer address */
-{
-	if (Fblock) {
-	    if (!Fwarn)
-		(void) fprintf(stderr,
-		    "%s: avoiding stat(%s): -b was specified.\n",
-		    Pn, path);
-	    errno = EWOULDBLOCK;
-	    return(1);
-	}
-	return(doinchild(dostat, path, (char *)buf, sizeof(struct stat)));
-}
-
-
-/*
- * stkdir() - stack directory name
- */
-
-void
-stkdir(p)
-	char *p;		/* directory path */
-{
-	MALLOC_S len;
-/*
- * Provide adequate space for directory stack pointers.
- */
-	if (Dstkx >= Dstkn) {
-	    Dstkn += 128;
-	    len = (MALLOC_S)(Dstkn * sizeof(char *));
-	    if (!Dstk)
-		Dstk = (char **)malloc(len);
-	    else
-		Dstk = (char **)realloc((MALLOC_P *)Dstk, len);
-	    if (!Dstk) {
-		(void) fprintf(stderr,
-		    "%s: no space for directory stack at: ", Pn);
-		safestrprt(p, stderr, 1);
-		Error();
-	    }
-	}
-/*
- * Allocate space for the name, copy it there and put its pointer on the stack.
- */
-	if (!(Dstk[Dstkx] = mkstrcpy(p, (MALLOC_S *)NULL))) {
-	    (void) fprintf(stderr, "%s: no space for: ", Pn);
-	    safestrprt(p, stderr, 1);
-	    Error();
-	}
-	Dstkx++;
-}
-
-
-/*
- * x2dev() - convert hexadecimal ASCII string to device number
- */
-
-char *
-x2dev(s, d)
-	char *s;			/* ASCII string */
-	dev_t *d;			/* device receptacle */
-{
-	char *cp, *cp1;
-	int n;
-	dev_t r;
-
-/*
- * Skip an optional leading 0x.  Count the number of hex digits up to the end
- * of the string, or to a space, or to a comma.  Return an error if an unknown
- * character is encountered.  If the count is larger than (2 * sizeof(dev_t))
- * -- e.g., because of sign extension -- ignore excess leading hex 0xf digits,
- * but return an error if an excess leading digit isn't 0xf.
- */
-	if  (strncasecmp(s, "0x", 2) == 0)
-		s += 2;
-	for (cp = s, n = 0; *cp; cp++, n++) {
-	    if (isdigit((unsigned char)*cp))
-		continue;
-	    if ((unsigned char)*cp >= 'a' && (unsigned char)*cp <= 'f')
-		continue;
-	    if ((unsigned char)*cp >= 'A' && (unsigned char)*cp <= 'F')
-		continue;
-	    if (*cp == ' ' || *cp == ',')
-		break;
-	    return((char *)NULL);
-	}
-	if (!n)
-	    return((char *)NULL);
-	if (n > (2 * (int)sizeof(dev_t))) {
-	    cp1 = s;
-	    s += (n - (2 * sizeof(dev_t)));
-	    while (cp1 < s) {
-		if (*cp1 != 'f' && *cp1 != 'F')
-		    return((char *)NULL);
-		cp1++;
-	    }
-	}
-/*
- * Assemble the validated hex digits of the device number, starting at a point
- * in the string relevant to sizeof(dev_t).
- */
-	for (r = 0; s < cp; s++) {
-	    r = r << 4;
-	    if (isdigit((unsigned char)*s))
-		r |= (unsigned char)(*s - '0') & 0xf;
-	    else {
-		if (isupper((unsigned char)*s))
-		    r |= ((unsigned char)(*s - 'A') + 10) & 0xf;
-		else
-		    r |= ((unsigned char)(*s - 'a') + 10) & 0xf;
-	    }
-	}
-	*d = r;
-	return(s);
-}
diff --git a/mkdocs.yml b/mkdocs.yml
new file mode 100644
index 0000000..3248c32
--- /dev/null
+++ b/mkdocs.yml
@@ -0,0 +1,18 @@
+site_name: lsof
+theme:
+  name: readthedocs
+  highlightjs: true
+nav:
+  - index.md
+  - getting-started.md
+  - tutorial.md
+  - options.md
+  - faq.md
+  - manpage.md
+  - credits.md
+  - contributing.md
+  - maintaining.md
+plugins:
+  - search
+markdown_extensions:
+  - admonition
\ No newline at end of file
diff --git a/node.c b/node.c
deleted file mode 100644
index 0834f21..0000000
--- a/node.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * node.c - common 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";
-#endif
-
-
-#include "lsof.h"
-
-
-/*
- * print_kptr() - print kernel pointer
- */
-
-char *
-print_kptr(kp, buf, bufl)
-	KA_T kp;			/* kernel pointer address */
-	char *buf;			/* optional destination buffer */
-	size_t bufl;			/* size of buf[] */
-{
-	static char dbuf[32];
-
-	(void) snpf(buf ? buf : dbuf,
-		    buf ? bufl : sizeof(dbuf),
-		    KA_T_FMT_X, kp);
-	return(buf ? buf : dbuf);
-}
-
-
-#if	defined(HASCDRNODE)
-/*
- * readcdrnode() - read CD-ROM node
- */
-
-int
-readcdrnode(ca, c)
-	KA_T ca;			/* cdrnode kernel address */
-	struct cdrnode *c;		/* cdrnode buffer */
-{
-	if (kread((KA_T)ca, (char *)c, sizeof(struct cdrnode))) {
-	    (void) snpf(Namech, Namechl, "can't read cdrnode at %s",
-		print_kptr(ca, (char *)NULL, 0));
-	    return(1);
-	}
-	return(0);
-}
-#endif	/* defined(HASCDRNODE) */
-
-
-#if	defined(HASFIFONODE)
-/*
- * readfifonode() - read fifonode
- */
-
-int
-readfifonode(fa, f)
-	KA_T fa;			/* fifonode kernel address */
-	struct fifonode *f;		/* fifonode buffer */
-{
-	if (kread((KA_T)fa, (char *)f, sizeof(struct fifonode))) {
-	    (void) snpf(Namech, Namechl, "can't read fifonode at %s",
-		print_kptr(fa, (char *)NULL, 0));
-	    return(1);
-	}
-	return(0);
-}
-#endif	/* defined(HASFIFONODE) */
-
-
-#if	defined(HASGNODE)
-/*
- * readgnode() - read gnode
- */
-
-int
-readgnode(ga, g)
-	KA_T ga;			/* gnode kernel address */
-	struct gnode *g;		/* gnode buffer */
-{
-	if (kread((KA_T)ga, (char *)g, sizeof(struct gnode))) {
-	    (void) snpf(Namech, Namechl, "can't read gnode at %s",
-		print_kptr(ga, (char *)NULL, 0));
-	    return(1);
-	}
-	return(0);
-}
-#endif	/* defined(HASGNODE) */
-
-
-#if	defined(HASHSNODE)
-/*
- * readhsnode() - read High Sierra file system node
- */
-
-int
-readhsnode(ha, h)
-	KA_T ha;			/* hsnode kernel address */
-	struct hsnode *h;		/* hsnode buffer */
-{
-	if (kread((KA_T)ha, (char *)h, sizeof(struct hsnode))) {
-	    (void) snpf(Namech, Namechl, "can't read hsnode at %s",
-		print_kptr(ha, (char *)NULL, 0));
-	    return(1);
-	}
-	return(0);
-}
-#endif	/* defined(HASHSNODE) */
-
-
-#if	defined(HASINODE)
-/*
- * readinode() - read inode
- */
-
-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);
-}
-#endif	/* defined(HASINODE) */
-
-
-#if	defined(HASPIPENODE)
-/*
- * readpipenode() - read pipe node
- */
-
-int
-readpipenode(pa, p)
-	KA_T pa;			/* pipe node kernel address */
-	struct pipenode *p;		/* pipe node buffer */
-{
-	if (kread((KA_T)pa, (char *)p, sizeof(struct pipenode))) {
-	    (void) snpf(Namech, Namechl, "can't read pipenode at %s",
-		print_kptr(pa, (char *)NULL, 0));
-	    return(1);
-	}
-	return(0);
-}
-#endif	/* defined(HASPIPENODE) */
-
-
-#if	defined(HASRNODE)
-/*
- * readrnode() - read rnode
- */
-
-int
-readrnode(ra, r)
-	KA_T ra;			/* rnode kernel space address */
-	struct rnode *r;		/* rnode buffer pointer */
-{
-	if (kread((KA_T)ra, (char *)r, sizeof(struct rnode))) {
-	    (void) snpf(Namech, Namechl, "can't read rnode at %s",
-		print_kptr(ra, (char *)NULL, 0));
-	    return(1);
-	}
-	return(0);
-}
-#endif	/* defined(HASRNODE) */
-
-
-#if	defined(HASSNODE)
-/*
- * readsnode() - read snode
- */
-
-int
-readsnode(sa, s)
-	KA_T sa;			/* snode kernel space address */
-	struct snode *s;		/* snode buffer pointer */
-{
-	if (kread((KA_T)sa, (char *)s, sizeof(struct snode))) {
-	    (void) snpf(Namech, Namechl, "can't read snode at %s",
-		print_kptr(sa, (char *)NULL, 0));
-	    return(1);
-	}
-	return(0);
-}
-#endif	/* defined(HASSNODE) */
-
-
-#if	defined(HASTMPNODE)
-/*
- * readtnode() - read tmpnode
- */
-
-int
-readtnode(ta, t)
-	KA_T ta;			/* tmpnode kernel space address */
-	struct tmpnode *t;		/* tmpnode buffer pointer */
-{
-	if (kread((KA_T)ta, (char *)t, sizeof(struct tmpnode))) {
-	    (void) snpf(Namech, Namechl, "can't read tmpnode at %s",
-		print_kptr(ta, (char *)NULL, 0));
-	    return(1);
-	}
-	return(0);
-}
-#endif	/* defined(HASTMPNODE) */
-
-
-#if	defined(HASVNODE)
-/*
- * readvnode() - read vnode
- */
-
-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))) {
-	    (void) snpf(Namech, Namechl, "can't read vnode at %s",
-		print_kptr(va, (char *)NULL, 0));
-	    return(1);
-	}
-	return(0);
-}
-#endif	/* defined(HASVNODE) */
diff --git a/print.c b/print.c
deleted file mode 100644
index 9168f2f..0000000
--- a/print.c
+++ /dev/null
@@ -1,2846 +0,0 @@
-/*
- * print.c - common print 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";
-#endif
-
-
-#include "lsof.h"
-
-
-/*
- * Local definitions, structures and function prototypes
- */
-
-#define HCINC		64		/* host cache size increase chunk */
-#define PORTHASHBUCKETS	128		/* port hash bucket count
-					 * !!MUST BE A POWER OF 2!! */
-#define	PORTTABTHRESH	10		/* threshold at which we will switch
-					 * from using getservbyport() to
-					 * getservent() -- see lkup_port()
-					 * and fill_porttab() */
-
-struct hostcache {
-	unsigned char a[MAX_AF_ADDR];	/* numeric address */
-	int af;				/* address family -- e.g., AF_INET
-					 * or AF_INET6 */
-	char *name;			/* name */
-};
-
-struct porttab {
-	int port;
-	MALLOC_S nl;			/* name length (excluding '\0') */
-	int ss;				/* service name status, 0 = lookup not
-					 * yet performed */
-	char *name;
-	struct porttab *next;
-};
-
-
-#if	defined(HASNORPC_H)
-static struct porttab **Pth[2] = { NULL, NULL };
-						/* port hash buckets:
-						 * Pth[0] for TCP service names
-						 * Pth[1] for UDP service names
-						 */
-#else	/* !defined(HASNORPC_H) */
-static struct porttab **Pth[4] = { NULL, NULL, NULL, NULL };
-						/* port hash buckets:
-						 * Pth[0] for TCP service names
-						 * Pth[1] for UDP service names
-						 * Pth[2] for TCP portmap info
-						 * Pth[3] for UDP portmap info
-						 */
-#endif	/* defined(HASNORPC_H) */
-
-#define HASHPORT(p)	(((((int)(p)) * 31415) >> 3) & (PORTHASHBUCKETS - 1))
-
-
-#if	!defined(HASNORPC_H)
-_PROTOTYPE(static void fill_portmap,(void));
-_PROTOTYPE(static void update_portmap,(struct porttab *pt, char *pn));
-#endif	/* !defined(HASNORPC_H) */
-
-_PROTOTYPE(static void fill_porttab,(void));
-_PROTOTYPE(static char *lkup_port,(int p, int pr, int src));
-_PROTOTYPE(static char *lkup_svcnam,(int h, int p, int pr, int ss));
-_PROTOTYPE(static int printinaddr,(void));
-
-
-/*
- * endnm() - locate end of Namech
- */
-
-char *
-endnm(sz)
-	size_t *sz;			/* returned remaining size */
-{
-	register char *s;
-	register size_t tsz;
-
-	for (s = Namech, tsz = Namechl; *s; s++, tsz--)
-		;
-	*sz = tsz;
-	return(s);
-}
-
-
-#if !defined(HASNORPC_H)
-/*
- * fill_portmap() -- fill the RPC portmap program name table via a conversation
- *		     with the portmapper
- *
- * The following copyright notice acknowledges that this function was adapted
- * from getrpcportnam() of the source code of the OpenBSD netstat program.
- */
-
-/*
-* Copyright (c) 1983, 1988, 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.
-*/
-
-static void
-fill_portmap()
-{
-	char buf[128], *cp, *nm;
-	CLIENT *c;
-	int h, port, pr;
-	MALLOC_S nl;
-	struct pmaplist *p = (struct pmaplist *)NULL;
-	struct porttab *pt;
-	struct rpcent *r;
-	struct TIMEVAL_LSOF tm;
-
-#if	!defined(CAN_USE_CLNT_CREATE)
-	struct hostent *he;
-	struct sockaddr_in ia;
-	int s = RPC_ANYSOCK;
-#endif	/* !defined(CAN_USE_CLNT_CREATE) */
-
-/*
- * Construct structures for communicating with the portmapper.
- */
-
-#if	!defined(CAN_USE_CLNT_CREATE)
-	zeromem(&ia, sizeof(ia));
-	ia.sin_family = AF_INET;
-	if ((he = gethostbyname("localhost")))
-	    MEMMOVE((caddr_t)&ia.sin_addr, he->h_addr, he->h_length);
-	ia.sin_port = htons(PMAPPORT);
-#endif	/* !defined(CAN_USE_CLNT_CREATE) */
-
-	tm.tv_sec = 60;
-	tm.tv_usec = 0;
-/*
- * Get an RPC client handle.  Then ask for a dump of the port map.
- */
-
-#if	defined(CAN_USE_CLNT_CREATE)
-	if (!(c = clnt_create("localhost", PMAPPROG, PMAPVERS, "tcp")))
-#else	/* !defined(CAN_USE_CLNT_CREATE) */
-	if (!(c = clnttcp_create(&ia, PMAPPROG, PMAPVERS, &s, 0, 0)))
-#endif	/* defined(CAN_USE_CLNT_CREATE) */
-
-	    return;
-	if (clnt_call(c, PMAPPROC_DUMP, XDR_VOID, NULL, XDR_PMAPLIST,
-		      (caddr_t)&p, tm)
-	!= RPC_SUCCESS) {
-	    clnt_destroy(c);
-	    return;
-	}
-/*
- * Loop through the port map dump, creating portmap table entries from TCP
- * and UDP members.
- */
-	for (; p; p = p->pml_next) {
-
-	/*
-	 * Determine the port map entry's protocol; ignore all but TCP and UDP.
-	 */
-	    if (p->pml_map.pm_prot == IPPROTO_TCP)
-		pr = 2;
-	    else if (p->pml_map.pm_prot == IPPROTO_UDP)
-		pr = 3;
-	    else
-		continue;
-	/*
-	 * See if there's already a portmap entry for this port.  If there is,
-	 * ignore this entry.
-	 */
-	    h = HASHPORT((port = (int)p->pml_map.pm_port));
-	    for (pt = Pth[pr][h]; pt; pt = pt->next) {
-		if (pt->port == port)
-		    break;
-	    }
-	    if (pt)
-		continue;
-	/*
-	 * Save the registration name or number.
-	 */
-	    cp = (char *)NULL;
-	    if ((r = (struct rpcent *)getrpcbynumber(p->pml_map.pm_prog))) {
-		if (r->r_name && strlen(r->r_name))
-		    cp = r->r_name;
-	    }
-	    if (!cp) {
-		(void) snpf(buf, sizeof(buf), "%lu",
-			    (unsigned long)p->pml_map.pm_prog);
-		cp = buf;
-	    }
-	    if (!strlen(cp))
-		continue;
-	/*
-	 * Allocate space for the portmap name entry and copy it there.
-	 */
-	    if (!(nm = mkstrcpy(cp, &nl))) {
-		(void) fprintf(stderr,
-		    "%s: can't allocate space for portmap entry: ", Pn);
-		safestrprt(cp, stderr, 1);
-		Error();
-	    }
-	    if (!nl) {
-		(void) free((FREE_P *)nm);
-		continue;
-	    }
-	/*
-	 * Allocate and fill a porttab struct entry for the portmap table.
-	 * Link it to the head of its hash bucket, and make it the new head.
-	 */
-	    if (!(pt = (struct porttab *)malloc(sizeof(struct porttab)))) {
-		(void) fprintf(stderr,
-		    "%s: can't allocate porttab entry for portmap: ", Pn);
-		safestrprt(nm, stderr, 1);
-		Error();
-	    }
-	    pt->name = nm;
-	    pt->nl = nl;
-	    pt->port = port;
-	    pt->next = Pth[pr][h];
-	    pt->ss = 0;
-	    Pth[pr][h] = pt;
-	}
-	clnt_destroy(c);
-}
-#endif	/* !defined(HASNORPC_H) */
-
-
-/*
- * fill_porttab() -- fill the TCP and UDP service name port table with a
- *		     getservent() scan
- */
-
-static void
-fill_porttab()
-{
-	int h, p, pr;
-	MALLOC_S nl;
-	char *nm;
-	struct porttab *pt;
-	struct servent *se;
-
-	(void) endservent();
-/*
- * Scan the services data base for TCP and UDP entries that have a non-null
- * name associated with them.
- */
-	(void) setservent(1);
-	while ((se = getservent())) {
-	    if (!se->s_name || !se->s_proto)
-		continue;
-	    if (strcasecmp(se->s_proto, "TCP") == 0)
-		pr = 0;
-	    else if (strcasecmp(se->s_proto, "UDP") == 0)
-		pr = 1;
-	    else
-		continue;
-	    if (!se->s_name || !strlen(se->s_name))
-		continue;
-	    p = ntohs(se->s_port);
-	/*
-	 * See if a port->service entry is already cached for this port and
-	 * prototcol.  If it is, leave it alone.
-	 */
-	    h = HASHPORT(p);
-	    for (pt = Pth[pr][h]; pt; pt = pt->next) {
-		if (pt->port == p)
-		    break;
-	    }
-	    if (pt)
-		continue;
-	/*
-	 * Add a new entry to the cache for this port and protocol.
-	 */
-	    if (!(nm = mkstrcpy(se->s_name, &nl))) {
-		(void) fprintf(stderr,
-		    "%s: can't allocate %d bytes for port %d name: %s\n",
-		    Pn, (int)(nl + 1), p, se->s_name);
-		Error();
-	    }
-	    if (!nl) {
-		(void) free((FREE_P *)nm);
-		continue;
-	    }
-	    if (!(pt = (struct porttab *)malloc(sizeof(struct porttab)))) {
-		(void) fprintf(stderr,
-		    "%s: can't allocate porttab entry for port %d: %s\n",
-		    Pn, p, se->s_name);
-		Error();
-	    }
-	    pt->name = nm;
-	    pt->nl = nl - 1;
-	    pt->port = p;
-	    pt->next = Pth[pr][h];
-	    pt->ss = 0;
-	    Pth[pr][h] = pt;
-	}
-	(void) endservent();
-}
-
-
-/*
- * gethostnm() - get host name
- */
-
-char *
-gethostnm(ia, af)
-	unsigned char *ia;		/* Internet address */
-	int af;				/* address family -- e.g., AF_INET
-					 * or AF_INET6 */
-{
-	int al = MIN_AF_ADDR;
-	char hbuf[256];
-	static struct hostcache *hc = (struct hostcache *)NULL;
-	static int hcx = 0;
-	char *hn, *np;
-	struct hostent *he = (struct hostent *)NULL;
-	int i, j;
-	MALLOC_S len;
-	static int nhc = 0;
-/*
- * Search cache.
- */
-
-#if	defined(HASIPv6)
-	if (af == AF_INET6)
-	    al = MAX_AF_ADDR;
-#endif	/* defined(HASIPv6) */
-
-	for (i = 0; i < hcx; i++) {
-	    if (af != hc[i].af)
-		continue;
-	    for (j = 0; j < al; j++) {
-		if (ia[j] != hc[i].a[j])
-		    break;
-	    }
-	    if (j >= al)
-		return(hc[i].name);
-	}
-/*
- * If -n has been specified, construct a numeric address.  Otherwise, look up
- * host name by address.  If that fails, or if there is no name in the returned
- * hostent structure, construct a numeric version of the address.
- */
-	if (Fhost)
-	    he = gethostbyaddr((char *)ia, al, af);
-	if (!he || !he->h_name) {
-
-#if	defined(HASIPv6)
-	    if (af == AF_INET6) {
-
-	    /*
-	     * Since IPv6 numeric addresses use `:' as a separator, enclose
-	     * them in brackets.
-	     */
-		hbuf[0] = '[';
-		if (!inet_ntop(af, ia, hbuf + 1, sizeof(hbuf) - 3)) {
-		    (void) snpf(&hbuf[1], (sizeof(hbuf) - 1),
-			"can't format IPv6 address]");
-		} else {
-		    len = strlen(hbuf);
-		    (void) snpf(&hbuf[len], sizeof(hbuf) - len, "]");
-		}
-	    } else
-#endif	/* defined(HASIPv6) */
-
-	    if (af == AF_INET)
-		(void) snpf(hbuf, sizeof(hbuf), "%u.%u.%u.%u", ia[0], ia[1],
-			    ia[2], ia[3]);
-	    else
-		(void) snpf(hbuf, sizeof(hbuf), "(unknown AF value: %d)", af);
-	    hn = hbuf;
-	} else
-	    hn = (char *)he->h_name;
-/*
- * Allocate space for name and copy name to it.
- */
-	if (!(np = mkstrcpy(hn, (MALLOC_S *)NULL))) {
-	    (void) fprintf(stderr, "%s: no space for host name: ", Pn);
-	    safestrprt(hn, stderr, 1);
-	    Error();
-	}
-/*
- * Add address/name entry to cache.  Allocate cache space in HCINC chunks.
- */
-	if (hcx >= nhc) {
-	    nhc += HCINC;
-	    len = (MALLOC_S)(nhc * sizeof(struct hostcache));
-	    if (!hc)
-		hc = (struct hostcache *)malloc(len);
-	    else
-		hc = (struct hostcache *)realloc((MALLOC_P *)hc, len);
-	    if (!hc) {
-		(void) fprintf(stderr, "%s: no space for host cache\n", Pn);
-		Error();
-	    }
-	}
-	hc[hcx].af = af;
-	for (i = 0; i < al; i++) {
-	    hc[hcx].a[i] = ia[i];
-	}
-	hc[hcx++].name = np;
-	return(np);
-}
-
-
-/*
- * lkup_port() - look up port for protocol
- */
-
-static char *
-lkup_port(p, pr, src)
-	int p;				/* port number */
-	int pr;				/* protocol index: 0 = tcp, 1 = udp */
-	int src;			/* port source: 0 = local
-					 *		1 = foreign */
-{
-	int h, nh;
-	MALLOC_S nl;
-	char *nm, *pn;
-	static char pb[128];
-	static int pm = 0;
-	struct porttab *pt;
-/*
- * If the hash buckets haven't been allocated, do so.
- */
-	if (!Pth[0]) {
-
-#if	defined(HASNORPC_H)
-	    nh = 2;
-#else	/* !defined(HASNORPC_H) */
-	    nh = FportMap ? 4 : 2;
-#endif	/* defined(HASNORPC_H) */
-
-	    for (h = 0; h < nh; h++) {
-		if (!(Pth[h] = (struct porttab **)calloc(PORTHASHBUCKETS,
-				sizeof(struct porttab *))))
-		{
-		    (void) fprintf(stderr,
-		      "%s: can't allocate %d bytes for %s %s hash buckets\n",
-		      Pn,
-		      (int)(2 * (PORTHASHBUCKETS * sizeof(struct porttab *))),
-		      (h & 1) ? "UDP" : "TCP",
-		      (h > 1) ? "portmap" : "port");
-		    Error();
-		}
-	    }
-	}
-
-#if	!defined(HASNORPC_H)
-/*
- * If we're looking up program names for portmapped ports, make sure the
- * portmap table has been loaded.
- */
-	if (FportMap && !pm) {
-	    (void) fill_portmap();
-	    pm++;
-	}
-#endif	/* !defined(HASNORPC_H) */
-
-/*
- * Hash the port and see if its name has been cached.  Look for a local
- * port first in the portmap, if portmap searching is enabled.
- */
-	h = HASHPORT(p);
-
-#if	!defined(HASNORPC_H)
-	if (!src && FportMap) {
-	    for (pt = Pth[pr+2][h]; pt; pt = pt->next) {
-		if (pt->port != p)
-		    continue;
-		if (!pt->ss) {
-		    pn = Fport ? lkup_svcnam(h, p, pr, 0) : (char *)NULL;
-		    if (!pn) {
-			(void) snpf(pb, sizeof(pb), "%d", p);
-			pn = pb;
-		    }
-		    (void) update_portmap(pt, pn);
-		}
-		return(pt->name);
-	    }
-	}
-#endif	/* !defined(HASNORPC_H) */
-
-	for (pt = Pth[pr][h]; pt; pt = pt->next) {
-	    if (pt->port == p)
-		return(pt->name);
-	}
-/*
- * Search for a possible service name, unless the -P option has been specified.
- *
- * If there is no service name, return a %d conversion.
- *
- * Don't cache %d conversions; a zero port number is a %d conversion that
- * is represented by "*".
- */
-	pn = Fport ? lkup_svcnam(h, p, pr, 1) : (char *)NULL;
-	if (!pn || !strlen(pn)) {
-	    if (p) {
-		(void) snpf(pb, sizeof(pb), "%d", p);
-		return(pb);
-	    } else
-		return("*");
-	}
-/*
- * Allocate a new porttab entry for the TCP or UDP service name.
- */
-	if (!(pt = (struct porttab *)malloc(sizeof(struct porttab)))) {
-	    (void) fprintf(stderr,
-		"%s: can't allocate porttab entry for port %d\n", Pn, p);
-	    Error();
-	}
-/*
- * Allocate space for the name; copy it to the porttab entry; and link the
- * porttab entry to its hash bucket.
- *
- * Return a pointer to the name.
- */
-	if (!(nm = mkstrcpy(pn, &nl))) {
-	    (void) fprintf(stderr,
-		"%s: can't allocate space for port name: ", Pn);
-	    safestrprt(pn, stderr, 1);
-	    Error();
-	}
-	pt->name = nm;
-	pt->nl = nl;
-	pt->port = p;
-	pt->next = Pth[pr][h];
-	pt->ss = 0;
-	Pth[pr][h] = pt;
-	return(nm);
-}
-
-
-/*
- * lkup_svcnam() - look up service name for port
- */
-
-static char *
-lkup_svcnam(h, p, pr, ss)
-	int h;				/* porttab hash index */
-	int p;				/* port number */
-	int pr;				/* protocol: 0 = TCP, 1 = UDP */
-	int ss;				/* search status: 1 = Pth[pr][h]
-					 *		  already searched */
-{
-	static int fl[PORTTABTHRESH];
-	static int fln = 0;
-	static int gsbp = 0;
-	int i;
-	struct porttab *pt;
-	static int ptf = 0;
-	struct servent *se;
-/*
- * Do nothing if -P has been specified.
- */
-	if (!Fport)
-	    return((char *)NULL);
-
-	for (;;) {
-
-	/*
-	 * Search service name cache, if it hasn't already been done.
-	 * Return the name of a match.
-	 */
-	    if (!ss) {
-		for (pt = Pth[pr][h]; pt; pt = pt->next) {
-		    if (pt->port == p)
-			return(pt->name);
-		}
-	    }
-/*
- * If fill_porttab() has been called, there is no service name.
- *
- * Do PORTTABTHRES getservbport() calls, remembering the failures, so they
- * won't be repeated.
- *
- * After PORTABTHRESH getservbyport() calls, call fill_porttab() once,
- */
-	    if (ptf)
-		break;
-	    if (gsbp < PORTTABTHRESH) {
-		for (i = 0; i < fln; i++) {
-		    if (fl[i] == p)
-			return((char *)NULL);
-		}
-		gsbp++;
-		if ((se = getservbyport(htons(p), pr ? "udp" : "tcp")))
-		    return(se->s_name);
-		if (fln < PORTTABTHRESH)
-		    fl[fln++] = p;
-		return((char *)NULL);
-	    }
-	    (void) fill_porttab();
-	    ptf++;
-	    ss = 0;
-	}
-	return((char *)NULL);
-}
-
-
-/*
- * print_file() - print file
- */
-
-void
-print_file()
-{
-	char buf[128];
-	char *cp = (char *)NULL;
-	dev_t dev;
-	int devs, len;
-
-	if (PrPass && !Hdr) {
-
-	/*
-	 * Print the header line if this is the second pass and the
-	 * header hasn't already been printed.
-	 */
-	    (void) printf("%-*.*s %*s", CmdColW, CmdColW, CMDTTL, PidColW,
-		PIDTTL);
-
-#if	defined(HASTASKS)
-	    if (TaskPrtTid)
-		(void) printf(" %*s", TaskTidColW, TASKTIDTTL);
-	    if (TaskPrtCmd)
-		(void) printf(" %-*.*s", TaskCmdColW, TaskCmdColW, TASKCMDTTL);
-#endif	/* defined(HASTASKS) */
-
-#if	defined(HASZONES)
-	    if (Fzone)
-		(void) printf(" %-*s", ZoneColW, ZONETTL);
-#endif	/* defined(HASZONES) */
-
-#if	defined(HASSELINUX)
-	    if (Fcntx)
-		(void) printf(" %-*s", CntxColW, CNTXTTL);
-#endif /* defined(HASSELINUX) */
-
-#if	defined(HASPPID)
-	    if (Fppid)
-	 	(void) printf(" %*s", PpidColW, PPIDTTL);
-#endif	/* defined(HASPPID) */
-
-	    if (Fpgid)
-		(void) printf(" %*s", PgidColW, PGIDTTL);
-	    (void) printf(" %*s %*s   %*s",
-		UserColW, USERTTL,
-		FdColW - 2, FDTTL,
-		TypeColW, TYPETTL);
-
-#if	defined(HASFSTRUCT)
-	    if (Fsv) {
-
-# if	!defined(HASNOFSADDR)
-		if (Fsv & FSV_FA)
-		    (void) printf(" %*s", FsColW, FSTTL);
-# endif	/* !defined(HASNOFSADDR) */
-
-# if	!defined(HASNOFSCOUNT)
-		if (Fsv & FSV_CT)
-		    (void) printf(" %*s", FcColW, FCTTL);
-# endif	/* !defined(HASNOFSCOUNT) */
-
-# if	!defined(HASNOFSFLAGS)
-		if (Fsv & FSV_FG)
-		    (void) printf(" %*s", FgColW, FGTTL);
-# endif	/* !defined(HASNOFSFLAGS) */
-
-# if	!defined(HASNOFSNADDR)
-		if (Fsv & FSV_NI)
-		    (void) printf(" %*s", NiColW, NiTtl);
-# endif	/* !defined(HASNOFSNADDR) */
-
-	    }
-#endif	/* defined(HASFSTRUCT) */
-
-	    (void) printf(" %*s", DevColW, DEVTTL);
-	    if (Foffset)
-		(void) printf(" %*s", SzOffColW, OFFTTL);
-	    else if (Fsize)
-		(void) printf(" %*s", SzOffColW, SZTTL);
-	    else
-		(void) printf(" %*s", SzOffColW, SZOFFTTL);
-	    if (Fnlink)
-		(void) printf(" %*s", NlColW, NLTTL);
-	    (void) printf(" %*s %s\n", NodeColW, NODETTL, NMTTL);
-	    Hdr++;
-	}
-/*
- * Size or print the command.
- */
-	cp = (Lp->cmd && *Lp->cmd != '\0') ? Lp->cmd : "(unknown)";
-	if (!PrPass) {
-	    len = safestrlen(cp, 2);
-	    if (CmdLim && (len > CmdLim))
-		len = CmdLim;
-	    if (len > CmdColW)
-		CmdColW = len;
-	} else
-	    safestrprtn(cp, CmdColW, stdout, 2);
-/*
- * Size or print the process ID.
- */
-	if (!PrPass) {
-	    (void) snpf(buf, sizeof(buf), "%d", Lp->pid);
-	    if ((len = strlen(buf)) > PidColW)
-		PidColW = len;
-	} else
-	    (void) printf(" %*d", PidColW, Lp->pid);
-
-#if	defined(HASTASKS)
-/*
- * Size or print task ID and command name.
- */
-	if (!PrPass) {
-	    if ((cp = Lp->tcmd)) {
-		len = safestrlen(cp, 2);
-		if (TaskCmdLim && (len > TaskCmdLim))
-		    len = TaskCmdLim;
-		if (len > TaskCmdColW)
-		    TaskCmdColW = len;
-		TaskPrtCmd = 1;
-	    }
-	    if (Lp->tid) {
-		(void) snpf(buf, sizeof(buf), "%d", Lp->tid);
-		if ((len = strlen(buf)) >TaskTidColW)
-		    TaskTidColW = len;
-		TaskPrtTid = 1;
-	    }
-	} else {
-	    if (TaskPrtTid) {
-		if (Lp->tid)
-		    (void) printf(" %*d", TaskTidColW, Lp->tid);
-		else
-		    (void) printf(" %*s", TaskTidColW, "");
-	    }
-	    if (TaskPrtCmd) {
-		cp = Lp->tcmd ? Lp->tcmd : "";
-		printf(" ");
-		safestrprtn(cp, TaskCmdColW, stdout, 2);
-	    }
-	}
-#endif	/* defined(HASTASKS) */
-
-#if	defined(HASZONES)
-/*
- * Size or print the zone.
- */
-	if (Fzone) {
-	    if (!PrPass) {
-		if (Lp->zn) {
-		    if ((len = strlen(Lp->zn)) > ZoneColW)
-			ZoneColW = len;
-		}
-	    } else
-		(void) printf(" %-*s", ZoneColW, Lp->zn ? Lp->zn : "");
-	}
-#endif	/* defined(HASZONES) */
-
-#if	defined(HASSELINUX)
-/*
- * Size or print the context.
- */
-	if (Fcntx) {
-	    if (!PrPass) {
-		if (Lp->cntx) {
-		    if ((len = strlen(Lp->cntx)) > CntxColW)
-			CntxColW = len;
-		}
-	    } else
-		(void) printf(" %-*s", CntxColW, Lp->cntx ? Lp->cntx : "");
-	}
-#endif	/* defined(HASSELINUX) */
-
-#if	defined(HASPPID)
-	if (Fppid) {
-
-	/*
-	 * Size or print the parent process ID.
-	 */
-	    if (!PrPass) {
-		(void) snpf(buf, sizeof(buf), "%d", Lp->ppid);
-		if ((len = strlen(buf)) > PpidColW)
-		    PpidColW = len;
-	    } else
-		(void) printf(" %*d", PpidColW, Lp->ppid);
-	}
-#endif	/* defined(HASPPID) */
-
-	if (Fpgid) {
-
-	/*
-	 * Size or print the process group ID.
-	 */
-	    if (!PrPass) {
-		(void) snpf(buf, sizeof(buf), "%d", Lp->pgid);
-		if ((len = strlen(buf)) > PgidColW)
-		    PgidColW = len;
-	    } else
-		(void) printf(" %*d", PgidColW, Lp->pgid);
-	}
-/*
- * Size or print the user ID or login name.
- */
-	if (!PrPass) {
-	    if ((len = strlen(printuid((UID_ARG)Lp->uid, NULL))) > UserColW)
-		UserColW = len;
-	} else
-	    (void) printf(" %*.*s", UserColW, UserColW,
-		printuid((UID_ARG)Lp->uid, NULL));
-/*
- * Size or print the file descriptor, access mode and lock status.
- */
-	if (!PrPass) {
-	    (void) snpf(buf, sizeof(buf), "%s%c%c",
-		Lf->fd,
-		(Lf->lock == ' ') ? Lf->access
-				  : (Lf->access == ' ') ? '-'
-							: Lf->access,
-		Lf->lock);
-	    if ((len = strlen(buf)) > FdColW)
-		FdColW = len;
-	} else
-	    (void) printf(" %*.*s%c%c", FdColW - 2, FdColW - 2, Lf->fd,
-		(Lf->lock == ' ') ? Lf->access
-				  : (Lf->access == ' ') ? '-'
-							: Lf->access,
-		Lf->lock);
-/*
- * Size or print the type.
- */
-	if (!PrPass) {
-	    if ((len = strlen(Lf->type)) > TypeColW)
-		TypeColW = len;
-	} else
-	    (void) printf(" %*.*s", TypeColW, TypeColW, Lf->type);
-
-#if	defined(HASFSTRUCT)
-/*
- * Size or print the file structure address, file usage count, and node
- * ID (address).
- */
-
-	if (Fsv) {
-
-# if	!defined(HASNOFSADDR)
-	    if (Fsv & FSV_FA) {
-		cp =  (Lf->fsv & FSV_FA) ? print_kptr(Lf->fsa, buf, sizeof(buf))
-					 : "";
-		if (!PrPass) {
-		    if ((len = strlen(cp)) > FsColW)
-			FsColW = len;
-		} else
-		    (void) printf(" %*.*s", FsColW, FsColW, cp);
-
-	    }
-# endif	/* !defined(HASNOFSADDR) */
-
-# if	!defined(HASNOFSCOUNT)
-	    if (Fsv & FSV_CT) {
-		if (Lf->fsv & FSV_CT) {
-		    (void) snpf(buf, sizeof(buf), "%ld", Lf->fct);
-		    cp = buf;
-		} else
-		    cp = "";
-		if (!PrPass) {
-		    if ((len = strlen(cp)) > FcColW)
-			FcColW = len;
-		} else
-		    (void) printf(" %*.*s", FcColW, FcColW, cp);
-	    }
-# endif	/* !defined(HASNOFSCOUNT) */
-
-# if	!defined(HASNOFSFLAGS)
-	    if (Fsv & FSV_FG) {
-		if ((Lf->fsv & FSV_FG) && (FsvFlagX || Lf->ffg || Lf->pof))
-		    cp = print_fflags(Lf->ffg, Lf->pof);
-		else
-		    cp = "";
-		if (!PrPass) {
-		    if ((len = strlen(cp)) > FgColW)
-			FgColW = len;
-		} else
-		    (void) printf(" %*.*s", FgColW, FgColW, cp);
-	    }
-# endif	/* !defined(HASNOFSFLAGS) */
-
-# if	!defined(HASNOFSNADDR)
-	    if (Fsv & FSV_NI) {
-		cp = (Lf->fsv & FSV_NI) ? print_kptr(Lf->fna, buf, sizeof(buf))
-					: "";
-		if (!PrPass) {
-		    if ((len = strlen(cp)) > NiColW)
-			NiColW = len;
-		} else
-		    (void) printf(" %*.*s", NiColW, NiColW, cp);
-	    }
-# endif	/* !defined(HASNOFSNADDR) */
-
-	}
-#endif	/* defined(HASFSTRUCT) */
-
-/*
- * Size or print the device information.
- */
-
-	if (Lf->rdev_def) {
-	    dev = Lf->rdev;
-	    devs = 1;
-	} else if (Lf->dev_def) {
-	    dev = Lf->dev;
-	    devs = 1;
-	} else
-	    devs = 0;
-	if (devs) {
-
-#if	defined(HASPRINTDEV)
-	    cp = HASPRINTDEV(Lf, &dev);
-#else	/* !defined(HASPRINTDEV) */
-	    (void) snpf(buf, sizeof(buf), "%u,%u", GET_MAJ_DEV(dev),
-		GET_MIN_DEV(dev));
-	    cp = buf;
-#endif	/* defined(HASPRINTDEV) */
-
-	}
-
-	if (!PrPass) {
-	    if (devs)
-		len = strlen(cp);
-	    else if (Lf->dev_ch)
-		len = strlen(Lf->dev_ch);
-	    else
-		len = 0;
-	    if (len > DevColW)
-		DevColW = len;
-	} else {
-	    if (devs)
-		(void) printf(" %*.*s", DevColW, DevColW, cp);
-	    else {
-		if (Lf->dev_ch)
-		    (void) printf(" %*.*s", DevColW, DevColW, Lf->dev_ch);
-		else
-		    (void) printf(" %*.*s", DevColW, DevColW, "");
-	    }
-	}
-/*
- * Size or print the size or offset.
- */
-	if (!PrPass) {
-	    if (Lf->sz_def) {
-
-#if	defined(HASPRINTSZ)
-		cp = HASPRINTSZ(Lf);
-#else	/* !defined(HASPRINTSZ) */
-		(void) snpf(buf, sizeof(buf), SzOffFmt_d, Lf->sz);
-		cp = buf;
-#endif	/* defined(HASPRINTSZ) */
-
-		len = strlen(cp);
-	    } else if (Lf->off_def) {
-
-#if	defined(HASPRINTOFF)
-		cp = HASPRINTOFF(Lf, 0);
-#else	/* !defined(HASPRINTOFF) */
-		(void) snpf(buf, sizeof(buf), SzOffFmt_0t, Lf->off);
-		cp = buf;
-#endif	/* defined(HASPRINTOFF) */
-
-		len = strlen(cp);
-		if (OffDecDig && len > (OffDecDig + 2)) {
-
-#if	defined(HASPRINTOFF)
-		    cp = HASPRINTOFF(Lf, 1);
-#else	/* !defined(HASPRINTOFF) */
-		    (void) snpf(buf, sizeof(buf), SzOffFmt_x, Lf->off);
-		    cp = buf;
-#endif	/* defined(HASPRINTOFF) */
-
-		    len = strlen(cp);
-		}
-	    } else
-		len = 0;
-	    if (len > SzOffColW)
-		SzOffColW = len;
-	} else {
-	    putchar(' ');
-	    if (Lf->sz_def)
-
-#if	defined(HASPRINTSZ)
-		(void) printf("%*.*s", SzOffColW, SzOffColW, HASPRINTSZ(Lf));
-#else	/* !defined(HASPRINTSZ) */
-		(void) printf(SzOffFmt_dv, SzOffColW, Lf->sz);
-#endif	/* defined(HASPRINTSZ) */
-
-	    else if (Lf->off_def) {
-
-#if	defined(HASPRINTOFF)
-		cp = HASPRINTOFF(Lf, 0);
-#else	/* !defined(HASPRINTOFF) */
-		(void) snpf(buf, sizeof(buf), SzOffFmt_0t, Lf->off);
-		cp = buf;
-#endif	/* defined(HASPRINTOFF) */
-
-		if (OffDecDig && (int)strlen(cp) > (OffDecDig + 2)) {
-
-#if	defined(HASPRINTOFF)
-		    cp = HASPRINTOFF(Lf, 1);
-#else	/* !defined(HASPRINTOFF) */
-		    (void) snpf(buf, sizeof(buf), SzOffFmt_x, Lf->off);
-		    cp = buf;
-#endif	/* defined(HASPRINTOFF) */
-
-		}
-		(void) printf("%*.*s", SzOffColW, SzOffColW, cp);
-	    } else
-		(void) printf("%*.*s", SzOffColW, SzOffColW, "");
-	}
-/*
- * Size or print the link count.
- */
-	if (Fnlink) {
-	    if (Lf->nlink_def) {
-		(void) snpf(buf, sizeof(buf), " %ld", Lf->nlink);
-		cp = buf;
-	   } else
-		cp = "";
-	    if (!PrPass) {
-		if ((len = strlen(cp)) > NlColW)
-		    NlColW = len;
-	    } else
-		(void) printf(" %*s", NlColW, cp);
-	}
-/*
- * Size or print the inode information.
- */
-	switch (Lf->inp_ty) {
-	case 1:
-
-#if	defined(HASPRINTINO)
-	    cp = HASPRINTINO(Lf);
-#else	/* !defined(HASPRINTINO) */
-	    (void) snpf(buf, sizeof(buf), InodeFmt_d, Lf->inode);
-	    cp = buf;
-#endif	/* defined(HASPRINTINO) */
-
-	    break;
-	case 2:
-	    if (Lf->iproto[0])
-		cp = Lf->iproto;
-	    else
-		cp = "";
-	    break;
-	case 3:
-	    (void) snpf(buf, sizeof(buf), InodeFmt_x, Lf->inode);
-	    cp = buf;
-	    break;
-	default:
-	    cp = "";
-	}
-	if (!PrPass) {
-	    if ((len = strlen(cp)) > NodeColW)
-		NodeColW = len;
-	} else {
-	    (void) printf(" %*.*s", NodeColW, NodeColW, cp);
-	}
-/*
- * If this is the second pass, print the name column.  (It doesn't need
- * to be sized.)
- */
-	if (PrPass) {
-	    putchar(' ');
-
-#if	defined(HASPRINTNM)
-	    HASPRINTNM(Lf);
-#else	/* !defined(HASPRINTNM) */
-	    printname(1);
-#endif	/* defined(HASPRINTNM) */
-
-	}
-}
-
-
-/*
- * printinaddr() - print Internet addresses
- */
-
-static int
-printinaddr()
-{
-	int i, len, src;
-	char *host, *port;
-	int nl = Namechl - 1;
-	char *np = Namech;
-	char pbuf[32];
-/*
- * Process local network address first.  If there's a foreign address,
- * separate it from the local address with "->".
- */
-	for (i = 0, *np = '\0'; i < 2; i++) {
-	    if (!Lf->li[i].af)
-		continue;
-	    host = port = (char *)NULL;
-	    if (i) {
-
-	    /*
-	     * If this is the foreign address, insert the separator.
-	     */
-		if (nl < 2)
-
-addr_too_long:
-
-		    {
-			(void) snpf(Namech, Namechl,
-			    "network addresses too long");
-			return(1);
-		    }
-		(void) snpf(np, nl, "->");
-		np += 2;
-		nl -= 2;
-	    }
-	/*
-	 * Convert the address to a host name.
-	 */
-
-#if	defined(HASIPv6)
-	    if ((Lf->li[i].af == AF_INET6
-	    &&   IN6_IS_ADDR_UNSPECIFIED(&Lf->li[i].ia.a6))
-	    ||  (Lf->li[i].af == AF_INET
-	    &&    Lf->li[i].ia.a4.s_addr == INADDR_ANY))
-		host ="*";
-	    else
-		host = gethostnm((unsigned char *)&Lf->li[i].ia, Lf->li[i].af);
-#else /* !defined(HASIPv6) */
-	    if (Lf->li[i].ia.a4.s_addr == INADDR_ANY)
-		host ="*";
-	    else
-		host = gethostnm((unsigned char *)&Lf->li[i].ia, Lf->li[i].af);
-#endif	/* defined(HASIPv6) */
-
-	/*
-	 * Process the port number.
-	 */
-	    if (Lf->li[i].p > 0) {
-
-		if (Fport
-
-#if	!defined(HASNORPC_H)
-		||  FportMap
-#endif	/* defined(HASNORPC_H) */
-
-		) {
-
-		/*
-		 * If converting port numbers to service names, or looking
-		 * up portmap program names and numbers, do so by protocol.
-		 *
-		 * Identify the port source as local if: 1) it comes from the
-		 * local entry (0) of the file's Internet address array; or
-		 * 2) it comes from  the foreign entry (1), and the foreign
-		 * Internet address matches the local one; or 3) it is the
-		 * loopback address 127.0.0.1.  (Test 2 may not always work
-		 * -- e.g., on hosts with multiple interfaces.)
-		 */
-#if	!defined(HASNORPC_H)
-		    if ((src = i) && FportMap) {
-
-# if	defined(HASIPv6)
-			if (Lf->li[0].af == AF_INET6) {
-			    if (IN6_IS_ADDR_LOOPBACK(&Lf->li[i].ia.a6)
-			    ||  IN6_ARE_ADDR_EQUAL(&Lf->li[0].ia.a6,
-						   &Lf->li[1].ia.a6)
-			    )
-				src = 0;
-			} else
-# endif	/* defined(HASIPv6) */
-
-			if (Lf->li[0].af == AF_INET) {
-			    if (Lf->li[i].ia.a4.s_addr == htonl(INADDR_LOOPBACK)
-			    ||  Lf->li[0].ia.a4.s_addr == Lf->li[1].ia.a4.s_addr
-			    )
-				src = 0;
-			}
-		    }
-#endif	/* !defined(HASNORPC_H) */
-
-		    if (strcasecmp(Lf->iproto, "TCP") == 0)
-			port = lkup_port(Lf->li[i].p, 0, src);
-		    else if (strcasecmp(Lf->iproto, "UDP") == 0)
-			port = lkup_port(Lf->li[i].p, 1, src);
-		}
-		if (!port) {
-		    (void) snpf(pbuf, sizeof(pbuf), "%d", Lf->li[i].p);
-		    port = pbuf;
-		}
-	    } else if (Lf->li[i].p == 0)
-		port = "*";
-	/*
-	 * Enter the host name.
-	 */
-	    if (host) {
-		if ((len = strlen(host)) > nl)
-		    goto addr_too_long;
-		if (len) {
-		    (void) snpf(np, nl, "%s", host);
-		    np += len;
-		    nl -= len;
-		}
-	    }
-	/*
-	 * Enter the port number, preceded by a colon.
-	 */
-	    if (port) {
-		if (((len = strlen(port)) + 1) >= nl)
-		    goto addr_too_long;
-		(void) snpf(np, nl, ":%s", port);
-		np += len + 1;
-		nl -= len - 1;
-	    }
-	}
-	if (Namech[0]) {
-	    safestrprt(Namech, stdout, 0);
-	    return(1);
-	}
-	return(0);
-}
-
-
-/*
- * print_init() - initialize for printing
- */
-
-void
-print_init()
-{
-
-/*
- * Preset standard values.
- */
-	PrPass = (Ffield || Fterse) ? 1 : 0;
-	LastPid = -1;
-	TaskPrtCmd = TaskPrtTid = 0;
-/*
- * Size columns by their titles.
- */
-	CmdColW = strlen(CMDTTL);
-	DevColW = strlen(DEVTTL);
-	FdColW = strlen(FDTTL);
-	if (Fnlink)
-	    NlColW = strlen(NLTTL);
-	NmColW = strlen(NMTTL);
-	NodeColW = strlen(NODETTL);
-	PgidColW = strlen(PGIDTTL);
-	PidColW = strlen(PIDTTL);
-	PpidColW = strlen(PPIDTTL);
-	if (Fsize)
-	    SzOffColW = strlen(SZTTL);
-	else if (Foffset)
-	    SzOffColW = strlen(OFFTTL);
-	else
-	    SzOffColW = strlen(SZOFFTTL);
-
-#if	defined(HASTASKS)
-	TaskCmdColW = strlen(TASKCMDTTL);
-	TaskTidColW = strlen(TASKTIDTTL);
-#endif	/* defined(HASTASKS) */
-
-	TypeColW = strlen(TYPETTL);
-	UserColW = strlen(USERTTL);
-
-#if	defined(HASFSTRUCT)
-
-# if	!defined(HASNOFSADDR)
-	FsColW = strlen(FSTTL);
-# endif	/* !defined(HASNOFSADDR) */
-
-# if	!defined(HASNOFSCOUNT)
-	FcColW = strlen(FCTTL);
-# endif	/* !defined(HASNOFSCOUNT) */
-
-# if	!defined(HASNOFSFLAGS)
-	FgColW = strlen(FGTTL);
-# endif	/* !defined(HASNOFSFLAGS) */
-
-# if	!defined(HASNOFSNADDR)
-	NiColW = strlen(NiTtl);
-# endif	/* !defined(HASNOFSNADDR) */
-#endif	/* defined(HASFSTRUCT) */
-
-#if	defined(HASSELINUX)
-	if (Fcntx)
-	    CntxColW = strlen(CNTXTTL);
-#endif	/* defined(HASSELINUX) */
-
-#if	defined(HASZONES)
-	if (Fzone)
-	    ZoneColW = strlen(ZONETTL);
-#endif	/* defined(HASZONES) */
-
-}
-
-
-#if	!defined(HASPRIVPRIPP)
-/*
- * printiproto() - print Internet protocol name
- */
-
-void
-printiproto(p)
-	int p;				/* protocol number */
-{
-	int i;
-	static int m = -1;
-	char *s;
-
-	switch (p) {
-
-#if	defined(IPPROTO_TCP)
-	case IPPROTO_TCP:
-	    s = "TCP";
-	    break;
-#endif	/* defined(IPPROTO_TCP) */
-
-#if	defined(IPPROTO_UDP)
-	case IPPROTO_UDP:
-	    s = "UDP";
-	    break;
-#endif	/* defined(IPPROTO_UDP) */
-
-#if	defined(IPPROTO_IP)
-# if	!defined(IPPROTO_HOPOPTS) || IPPROTO_IP!=IPPROTO_HOPOPTS
-	case IPPROTO_IP:
-	    s = "IP";
-	    break;
-# endif	/* !defined(IPPROTO_HOPOPTS) || IPPROTO_IP!=IPPROTO_HOPOPTS */
-#endif	/* defined(IPPROTO_IP) */
-
-#if	defined(IPPROTO_ICMP)
-	case IPPROTO_ICMP:
-	    s = "ICMP";
-	    break;
-#endif	/* defined(IPPROTO_ICMP) */
-
-#if	defined(IPPROTO_ICMPV6)
-	case IPPROTO_ICMPV6:
-	    s = "ICMPV6";
-	    break;
-#endif	/* defined(IPPROTO_ICMPV6) */
-
-#if	defined(IPPROTO_IGMP)
-	case IPPROTO_IGMP:
-	    s = "IGMP";
-	    break;
-#endif	/* defined(IPPROTO_IGMP) */
-
-#if	defined(IPPROTO_GGP)
-	case IPPROTO_GGP:
-	    s = "GGP";
-	    break;
-#endif	/* defined(IPPROTO_GGP) */
-
-#if	defined(IPPROTO_EGP)
-	case IPPROTO_EGP:
-	    s = "EGP";
-	    break;
-#endif	/* defined(IPPROTO_EGP) */
-
-#if	defined(IPPROTO_PUP)
-	case IPPROTO_PUP:
-	    s = "PUP";
-	    break;
-#endif	/* defined(IPPROTO_PUP) */
-
-#if	defined(IPPROTO_IDP)
-	case IPPROTO_IDP:
-	    s = "IDP";
-	    break;
-#endif	/* defined(IPPROTO_IDP) */
-
-#if	defined(IPPROTO_ND)
-	case IPPROTO_ND:
-	    s = "ND";
-	    break;
-#endif	/* defined(IPPROTO_ND) */
-
-#if	defined(IPPROTO_RAW)
-	case IPPROTO_RAW:
-	    s = "RAW";
-	    break;
-#endif	/* defined(IPPROTO_RAW) */
-
-#if	defined(IPPROTO_HELLO)
-	case IPPROTO_HELLO:
-	    s = "HELLO";
-	    break;
-#endif	/* defined(IPPROTO_HELLO) */
-
-#if	defined(IPPROTO_PXP)
-	case IPPROTO_PXP:
-	    s = "PXP";
-	    break;
-#endif	/* defined(IPPROTO_PXP) */
-
-#if	defined(IPPROTO_RAWIP)
-	case IPPROTO_RAWIP:
-	    s = "RAWIP";
-	    break;
-#endif	/* defined(IPPROTO_RAWIP) */
-
-#if	defined(IPPROTO_RAWIF)
-	case IPPROTO_RAWIF:
-	    s = "RAWIF";
-	    break;
-#endif	/* defined(IPPROTO_RAWIF) */
-
-#if	defined(IPPROTO_HOPOPTS)
-	case IPPROTO_HOPOPTS:
-	    s = "HOPOPTS";
-	    break;
-#endif	/* defined(IPPROTO_HOPOPTS) */
-
-#if	defined(IPPROTO_IPIP)
-	case IPPROTO_IPIP:
-	    s = "IPIP";
-	    break;
-#endif	/* defined(IPPROTO_IPIP) */
-
-#if	defined(IPPROTO_ST)
-	case IPPROTO_ST:
-	    s = "ST";
-	    break;
-#endif	/* defined(IPPROTO_ST) */
-
-#if	defined(IPPROTO_PIGP)
-	case IPPROTO_PIGP:
-	    s = "PIGP";
-	    break;
-#endif	/* defined(IPPROTO_PIGP) */
-
-#if	defined(IPPROTO_RCCMON)
-	case IPPROTO_RCCMON:
-	    s = "RCCMON";
-	    break;
-#endif	/* defined(IPPROTO_RCCMON) */
-
-#if	defined(IPPROTO_NVPII)
-	case IPPROTO_NVPII:
-	    s = "NVPII";
-	    break;
-#endif	/* defined(IPPROTO_NVPII) */
-
-#if	defined(IPPROTO_ARGUS)
-	case IPPROTO_ARGUS:
-	    s = "ARGUS";
-	    break;
-#endif	/* defined(IPPROTO_ARGUS) */
-
-#if	defined(IPPROTO_EMCON)
-	case IPPROTO_EMCON:
-	    s = "EMCON";
-	    break;
-#endif	/* defined(IPPROTO_EMCON) */
-
-#if	defined(IPPROTO_XNET)
-	case IPPROTO_XNET:
-	    s = "XNET";
-	    break;
-#endif	/* defined(IPPROTO_XNET) */
-
-#if	defined(IPPROTO_CHAOS)
-	case IPPROTO_CHAOS:
-	    s = "CHAOS";
-	    break;
-#endif	/* defined(IPPROTO_CHAOS) */
-
-#if	defined(IPPROTO_MUX)
-	case IPPROTO_MUX:
-	    s = "MUX";
-	    break;
-#endif	/* defined(IPPROTO_MUX) */
-
-#if	defined(IPPROTO_MEAS)
-	case IPPROTO_MEAS:
-	    s = "MEAS";
-	    break;
-#endif	/* defined(IPPROTO_MEAS) */
-
-#if	defined(IPPROTO_HMP)
-	case IPPROTO_HMP:
-	    s = "HMP";
-	    break;
-#endif	/* defined(IPPROTO_HMP) */
-
-#if	defined(IPPROTO_PRM)
-	case IPPROTO_PRM:
-	    s = "PRM";
-	    break;
-#endif	/* defined(IPPROTO_PRM) */
-
-#if	defined(IPPROTO_TRUNK1)
-	case IPPROTO_TRUNK1:
-	    s = "TRUNK1";
-	    break;
-#endif	/* defined(IPPROTO_TRUNK1) */
-
-#if	defined(IPPROTO_TRUNK2)
-	case IPPROTO_TRUNK2:
-	    s = "TRUNK2";
-	    break;
-#endif	/* defined(IPPROTO_TRUNK2) */
-
-#if	defined(IPPROTO_LEAF1)
-	case IPPROTO_LEAF1:
-	    s = "LEAF1";
-	    break;
-#endif	/* defined(IPPROTO_LEAF1) */
-
-#if	defined(IPPROTO_LEAF2)
-	case IPPROTO_LEAF2:
-	    s = "LEAF2";
-	    break;
-#endif	/* defined(IPPROTO_LEAF2) */
-
-#if	defined(IPPROTO_RDP)
-	case IPPROTO_RDP:
-	    s = "RDP";
-	    break;
-#endif	/* defined(IPPROTO_RDP) */
-
-#if	defined(IPPROTO_IRTP)
-	case IPPROTO_IRTP:
-	    s = "IRTP";
-	    break;
-#endif	/* defined(IPPROTO_IRTP) */
-
-#if	defined(IPPROTO_TP)
-	case IPPROTO_TP:
-	    s = "TP";
-	    break;
-#endif	/* defined(IPPROTO_TP) */
-
-#if	defined(IPPROTO_BLT)
-	case IPPROTO_BLT:
-	    s = "BLT";
-	    break;
-#endif	/* defined(IPPROTO_BLT) */
-
-#if	defined(IPPROTO_NSP)
-	case IPPROTO_NSP:
-	    s = "NSP";
-	    break;
-#endif	/* defined(IPPROTO_NSP) */
-
-#if	defined(IPPROTO_INP)
-	case IPPROTO_INP:
-	    s = "INP";
-	    break;
-#endif	/* defined(IPPROTO_INP) */
-
-#if	defined(IPPROTO_SEP)
-	case IPPROTO_SEP:
-	    s = "SEP";
-	    break;
-#endif	/* defined(IPPROTO_SEP) */
-
-#if	defined(IPPROTO_3PC)
-	case IPPROTO_3PC:
-	    s = "3PC";
-	    break;
-#endif	/* defined(IPPROTO_3PC) */
-
-#if	defined(IPPROTO_IDPR)
-	case IPPROTO_IDPR:
-	    s = "IDPR";
-	    break;
-#endif	/* defined(IPPROTO_IDPR) */
-
-#if	defined(IPPROTO_XTP)
-	case IPPROTO_XTP:
-	    s = "XTP";
-	    break;
-#endif	/* defined(IPPROTO_XTP) */
-
-#if	defined(IPPROTO_DDP)
-	case IPPROTO_DDP:
-	    s = "DDP";
-	    break;
-#endif	/* defined(IPPROTO_DDP) */
-
-#if	defined(IPPROTO_CMTP)
-	case IPPROTO_CMTP:
-	    s = "CMTP";
-	    break;
-#endif	/* defined(IPPROTO_CMTP) */
-
-#if	defined(IPPROTO_TPXX)
-	case IPPROTO_TPXX:
-	    s = "TPXX";
-	    break;
-#endif	/* defined(IPPROTO_TPXX) */
-
-#if	defined(IPPROTO_IL)
-	case IPPROTO_IL:
-	    s = "IL";
-	    break;
-#endif	/* defined(IPPROTO_IL) */
-
-#if	defined(IPPROTO_IPV6)
-	case IPPROTO_IPV6:
-	    s = "IPV6";
-	    break;
-#endif	/* defined(IPPROTO_IPV6) */
-
-#if	defined(IPPROTO_SDRP)
-	case IPPROTO_SDRP:
-	    s = "SDRP";
-	    break;
-#endif	/* defined(IPPROTO_SDRP) */
-
-#if	defined(IPPROTO_ROUTING)
-	case IPPROTO_ROUTING:
-	    s = "ROUTING";
-	    break;
-#endif	/* defined(IPPROTO_ROUTING) */
-
-#if	defined(IPPROTO_FRAGMENT)
-	case IPPROTO_FRAGMENT:
-	    s = "FRAGMNT";
-	    break;
-#endif	/* defined(IPPROTO_FRAGMENT) */
-
-#if	defined(IPPROTO_IDRP)
-	case IPPROTO_IDRP:
-	    s = "IDRP";
-	    break;
-#endif	/* defined(IPPROTO_IDRP) */
-
-#if	defined(IPPROTO_RSVP)
-	case IPPROTO_RSVP:
-	    s = "RSVP";
-	    break;
-#endif	/* defined(IPPROTO_RSVP) */
-
-#if	defined(IPPROTO_GRE)
-	case IPPROTO_GRE:
-	    s = "GRE";
-	    break;
-#endif	/* defined(IPPROTO_GRE) */
-
-#if	defined(IPPROTO_MHRP)
-	case IPPROTO_MHRP:
-	    s = "MHRP";
-	    break;
-#endif	/* defined(IPPROTO_MHRP) */
-
-#if	defined(IPPROTO_BHA)
-	case IPPROTO_BHA:
-	    s = "BHA";
-	    break;
-#endif	/* defined(IPPROTO_BHA) */
-
-#if	defined(IPPROTO_ESP)
-	case IPPROTO_ESP:
-	    s = "ESP";
-	    break;
-#endif	/* defined(IPPROTO_ESP) */
-
-#if	defined(IPPROTO_AH)
-	case IPPROTO_AH:
-	    s = "AH";
-	    break;
-#endif	/* defined(IPPROTO_AH) */
-
-#if	defined(IPPROTO_INLSP)
-	case IPPROTO_INLSP:
-	    s = "INLSP";
-	    break;
-#endif	/* defined(IPPROTO_INLSP) */
-
-#if	defined(IPPROTO_SWIPE)
-	case IPPROTO_SWIPE:
-	    s = "SWIPE";
-	    break;
-#endif	/* defined(IPPROTO_SWIPE) */
-
-#if	defined(IPPROTO_NHRP)
-	case IPPROTO_NHRP:
-	    s = "NHRP";
-	    break;
-#endif	/* defined(IPPROTO_NHRP) */
-
-#if	defined(IPPROTO_NONE)
-	case IPPROTO_NONE:
-	    s = "NONE";
-	    break;
-#endif	/* defined(IPPROTO_NONE) */
-
-#if	defined(IPPROTO_DSTOPTS)
-	case IPPROTO_DSTOPTS:
-	    s = "DSTOPTS";
-	    break;
-#endif	/* defined(IPPROTO_DSTOPTS) */
-
-#if	defined(IPPROTO_AHIP)
-	case IPPROTO_AHIP:
-	    s = "AHIP";
-	    break;
-#endif	/* defined(IPPROTO_AHIP) */
-
-#if	defined(IPPROTO_CFTP)
-	case IPPROTO_CFTP:
-	    s = "CFTP";
-	    break;
-#endif	/* defined(IPPROTO_CFTP) */
-
-#if	defined(IPPROTO_SATEXPAK)
-	case IPPROTO_SATEXPAK:
-	    s = "SATEXPK";
-	    break;
-#endif	/* defined(IPPROTO_SATEXPAK) */
-
-#if	defined(IPPROTO_KRYPTOLAN)
-	case IPPROTO_KRYPTOLAN:
-	    s = "KRYPTOL";
-	    break;
-#endif	/* defined(IPPROTO_KRYPTOLAN) */
-
-#if	defined(IPPROTO_RVD)
-	case IPPROTO_RVD:
-	    s = "RVD";
-	    break;
-#endif	/* defined(IPPROTO_RVD) */
-
-#if	defined(IPPROTO_IPPC)
-	case IPPROTO_IPPC:
-	    s = "IPPC";
-	    break;
-#endif	/* defined(IPPROTO_IPPC) */
-
-#if	defined(IPPROTO_ADFS)
-	case IPPROTO_ADFS:
-	    s = "ADFS";
-	    break;
-#endif	/* defined(IPPROTO_ADFS) */
-
-#if	defined(IPPROTO_SATMON)
-	case IPPROTO_SATMON:
-	    s = "SATMON";
-	    break;
-#endif	/* defined(IPPROTO_SATMON) */
-
-#if	defined(IPPROTO_VISA)
-	case IPPROTO_VISA:
-	    s = "VISA";
-	    break;
-#endif	/* defined(IPPROTO_VISA) */
-
-#if	defined(IPPROTO_IPCV)
-	case IPPROTO_IPCV:
-	    s = "IPCV";
-	    break;
-#endif	/* defined(IPPROTO_IPCV) */
-
-#if	defined(IPPROTO_CPNX)
-	case IPPROTO_CPNX:
-	    s = "CPNX";
-	    break;
-#endif	/* defined(IPPROTO_CPNX) */
-
-#if	defined(IPPROTO_CPHB)
-	case IPPROTO_CPHB:
-	    s = "CPHB";
-	    break;
-#endif	/* defined(IPPROTO_CPHB) */
-
-#if	defined(IPPROTO_WSN)
-	case IPPROTO_WSN:
-	    s = "WSN";
-	    break;
-#endif	/* defined(IPPROTO_WSN) */
-
-#if	defined(IPPROTO_PVP)
-	case IPPROTO_PVP:
-	    s = "PVP";
-	    break;
-#endif	/* defined(IPPROTO_PVP) */
-
-#if	defined(IPPROTO_BRSATMON)
-	case IPPROTO_BRSATMON:
-	    s = "BRSATMN";
-	    break;
-#endif	/* defined(IPPROTO_BRSATMON) */
-
-#if	defined(IPPROTO_WBMON)
-	case IPPROTO_WBMON:
-	    s = "WBMON";
-	    break;
-#endif	/* defined(IPPROTO_WBMON) */
-
-#if	defined(IPPROTO_WBEXPAK)
-	case IPPROTO_WBEXPAK:
-	    s = "WBEXPAK";
-	    break;
-#endif	/* defined(IPPROTO_WBEXPAK) */
-
-#if	defined(IPPROTO_EON)
-	case IPPROTO_EON:
-	    s = "EON";
-	    break;
-#endif	/* defined(IPPROTO_EON) */
-
-#if	defined(IPPROTO_VMTP)
-	case IPPROTO_VMTP:
-	    s = "VMTP";
-	    break;
-#endif	/* defined(IPPROTO_VMTP) */
-
-#if	defined(IPPROTO_SVMTP)
-	case IPPROTO_SVMTP:
-	    s = "SVMTP";
-	    break;
-#endif	/* defined(IPPROTO_SVMTP) */
-
-#if	defined(IPPROTO_VINES)
-	case IPPROTO_VINES:
-	    s = "VINES";
-	    break;
-#endif	/* defined(IPPROTO_VINES) */
-
-#if	defined(IPPROTO_TTP)
-	case IPPROTO_TTP:
-	    s = "TTP";
-	    break;
-#endif	/* defined(IPPROTO_TTP) */
-
-#if	defined(IPPROTO_IGP)
-	case IPPROTO_IGP:
-	    s = "IGP";
-	    break;
-#endif	/* defined(IPPROTO_IGP) */
-
-#if	defined(IPPROTO_DGP)
-	case IPPROTO_DGP:
-	    s = "DGP";
-	    break;
-#endif	/* defined(IPPROTO_DGP) */
-
-#if	defined(IPPROTO_TCF)
-	case IPPROTO_TCF:
-	    s = "TCF";
-	    break;
-#endif	/* defined(IPPROTO_TCF) */
-
-#if	defined(IPPROTO_IGRP)
-	case IPPROTO_IGRP:
-	    s = "IGRP";
-	    break;
-#endif	/* defined(IPPROTO_IGRP) */
-
-#if	defined(IPPROTO_OSPFIGP)
-	case IPPROTO_OSPFIGP:
-	    s = "OSPFIGP";
-	    break;
-#endif	/* defined(IPPROTO_OSPFIGP) */
-
-#if	defined(IPPROTO_SRPC)
-	case IPPROTO_SRPC:
-	    s = "SRPC";
-	    break;
-#endif	/* defined(IPPROTO_SRPC) */
-
-#if	defined(IPPROTO_LARP)
-	case IPPROTO_LARP:
-	    s = "LARP";
-	    break;
-#endif	/* defined(IPPROTO_LARP) */
-
-#if	defined(IPPROTO_MTP)
-	case IPPROTO_MTP:
-	    s = "MTP";
-	    break;
-#endif	/* defined(IPPROTO_MTP) */
-
-#if	defined(IPPROTO_AX25)
-	case IPPROTO_AX25:
-	    s = "AX25";
-	    break;
-#endif	/* defined(IPPROTO_AX25) */
-
-#if	defined(IPPROTO_IPEIP)
-	case IPPROTO_IPEIP:
-	    s = "IPEIP";
-	    break;
-#endif	/* defined(IPPROTO_IPEIP) */
-
-#if	defined(IPPROTO_MICP)
-	case IPPROTO_MICP:
-	    s = "MICP";
-	    break;
-#endif	/* defined(IPPROTO_MICP) */
-
-#if	defined(IPPROTO_SCCSP)
-	case IPPROTO_SCCSP:
-	    s = "SCCSP";
-	    break;
-#endif	/* defined(IPPROTO_SCCSP) */
-
-#if	defined(IPPROTO_ETHERIP)
-	case IPPROTO_ETHERIP:
-	    s = "ETHERIP";
-	    break;
-#endif	/* defined(IPPROTO_ETHERIP) */
-
-#if	defined(IPPROTO_ENCAP)
-# if	!defined(IPPROTO_IPIP) || IPPROTO_IPIP!=IPPROTO_ENCAP
-	case IPPROTO_ENCAP:
-	    s = "ENCAP";
-	    break;
-# endif	/* !defined(IPPROTO_IPIP) || IPPROTO_IPIP!=IPPROTO_ENCAP */
-#endif	/* defined(IPPROTO_ENCAP) */
-
-#if	defined(IPPROTO_APES)
-	case IPPROTO_APES:
-	    s = "APES";
-	    break;
-#endif	/* defined(IPPROTO_APES) */
-
-#if	defined(IPPROTO_GMTP)
-	case IPPROTO_GMTP:
-	    s = "GMTP";
-	    break;
-#endif	/* defined(IPPROTO_GMTP) */
-
-#if	defined(IPPROTO_DIVERT)
-	case IPPROTO_DIVERT:
-	    s = "DIVERT";
-	    break;
-#endif	/* defined(IPPROTO_DIVERT) */
-
-	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));
-	}
-}
-#endif	/* !defined(HASPRIVPRIPP) */
-
-
-/*
- * printname() - print output name field
- */
-
-void
-printname(nl)
-	int nl;				/* NL status */
-{
-
-#if	defined(HASNCACHE)
-	char buf[MAXPATHLEN];
-	char *cp;
-	int fp;
-#endif	/* defined(HASNCACHE) */
-
-	int ps = 0;
-
-	if (Lf->nm && Lf->nm[0]) {
-
-	/*
-	 * Print the name characters, if there are some.
-	 */
-	    safestrprt(Lf->nm, stdout, 0);
-	    ps++;
-	    if (!Lf->li[0].af && !Lf->li[1].af)
-		goto print_nma;
-	}
-	if (Lf->li[0].af || Lf->li[1].af) {
-	    if (ps)
-		putchar(' ');
-	/*
-	 * If the file has Internet addresses, print them.
-	 */
-	    if (printinaddr())
-		ps++;
-	    goto print_nma;
-	}
-	if (((Lf->ntype == N_BLK) || (Lf->ntype == N_CHR))
-	&&  Lf->dev_def && Lf->rdev_def
-	&&  printdevname(&Lf->dev, &Lf->rdev, 0, Lf->ntype))
-	{
-
-	/*
-	 * If this is a block or character device and it has a name, print it.
-	 */
-	    ps++;
-	    goto print_nma;
-	}
-	if (Lf->is_com) {
-
-	/*
-	 * If this is a common node, print that fact.
-	 */
-	    (void) fputs("COMMON: ", stdout);
-	    ps++;
-	    goto print_nma;
-	}
-
-#if	defined(HASPRIVNMCACHE)
-	if (HASPRIVNMCACHE(Lf)) {
-	    ps++;
-	    goto print_nma;
-	}
-#endif	/* defined(HASPRIVNMCACHE) */
-
-	if (Lf->lmi_srch) {
-	    struct mounts *mp;
-	/*
-	 * Do a deferred local mount info table search for the file system
-	 * (mounted) directory name and inode number, and mounted device name.
-	 */
-	    for (mp = readmnt(); mp; mp = mp->next) {
-		if (Lf->dev == mp->dev) {
-		    Lf->fsdir = mp->dir;
-		    Lf->fsdev = mp->fsname;
-
-#if	defined(HASFSINO)
-		    Lf->fs_ino = mp->inode;
-#endif	/* defined(HASFSINO) */
-
-		    break;
-		}
-	    }
-	    Lf->lmi_srch = 0;
-	}
-	if (Lf->fsdir || Lf->fsdev) {
-
-	/*
-	 * Print the file system directory name, device name, and
-	 * possible path name components.
-	 */
-
-#if	!defined(HASNCACHE) || HASNCACHE<2
-	    if (Lf->fsdir) {
-		safestrprt(Lf->fsdir, stdout, 0);
-		ps++;
-	    }
-#endif	/* !defined(HASNCACHE) || HASNCACHE<2 */
-
-#if	defined(HASNCACHE)
-
-# if	HASNCACHE<2
-	    if (Lf->na) {
-		if (NcacheReload) {
-
-#  if	defined(NCACHELDPFX)
-		    NCACHELDPFX
-#  endif	/* defined(NCACHELDPFX) */
-
-		    (void) ncache_load();
-
-#  if	defined(NCACHELDSFX)
-		    NCACHELDSFX
-#  endif	/* defined(NCACHELDSFX) */
-
-		    NcacheReload = 0;
-		}
-		if ((cp = ncache_lookup(buf, sizeof(buf), &fp))) {
-		    char *cp1;
-
-		    if (*cp == '\0')
-			goto print_nma;
-		    if (fp && Lf->fsdir) {
-			if (*cp != '/') {
-			    cp1 = strrchr(Lf->fsdir, '/');
-			    if (cp1 == (char *)NULL ||  *(cp1 + 1) != '\0')
-				putchar('/');
-			    }
-		    } else
-			(void) fputs(" -- ", stdout);
-		    safestrprt(cp, stdout, 0);
-		    ps++;
-		    goto print_nma;
-		}
-	    }
-# else	/* HASNCACHE>1 */
-	    if (NcacheReload) {
-
-#  if	defined(NCACHELDPFX)
-		    NCACHELDPFX
-#  endif	/* defined(NCACHELDPFX) */
-
-		(void) ncache_load();
-
-#  if	defined(NCACHELDSFX)
-		    NCACHELDSFX
-#  endif	/* defined(NCACHELDSFX) */
-
-		NcacheReload = 0;
-	    }
-	    if ((cp = ncache_lookup(buf, sizeof(buf), &fp))) {
-		if (fp) {
-		    safestrprt(cp, stdout, 0);
-		    ps++;
-		} else {
-		    if (Lf->fsdir) {
-			safestrprt(Lf->fsdir, stdout, 0);
-			ps++;
-		    }
-		    if (*cp) {
-			(void) fputs(" -- ", stdout);
-			safestrprt(cp, stdout, 0);
-			ps++;
-		    }
-		}
-		goto print_nma;
-	    }
-	    if (Lf->fsdir) {
-		safestrprt(Lf->fsdir, stdout, 0);
-		ps++;
-	    }
-# endif	/* HASNCACHE<2 */
-#endif	/* defined(HASNCACHE) */
-
-	    if (Lf->fsdev) {
-		if (Lf->fsdir)
-		    (void) fputs(" (", stdout);
-		else
-		    (void) putchar('(');
-		safestrprt(Lf->fsdev, stdout, 0);
-		(void) putchar(')');
-		ps++;
-	    }
-	}
-/*
- * Print the NAME column addition, if there is one.  If there isn't
- * make sure a NL is printed, as requested.
- */
-
-print_nma:
-
-	if (Lf->nma) {
-	    if (ps)
-		putchar(' ');
-	    safestrprt(Lf->nma, stdout, 0);
-	    ps++;
-	}
-/*
- * If this file has TCP/IP state information, print it.
- */
-	if (!Ffield && Ftcptpi
-	&&  (Lf->lts.type >= 0
-
-#if	defined(HASTCPTPIQ)
-	||   ((Ftcptpi & TCPTPI_QUEUES) && (Lf->lts.rqs || Lf->lts.sqs))
-#endif	/* defined(HASTCPTPIQ) */
-
-#if	defined(HASTCPTPIW)
-	||   ((Ftcptpi & TCPTPI_WINDOWS) && (Lf->lts.rws || Lf->lts.wws))
-#endif	/* defined(HASTCPTPIW) */
-
-	)) {
-	    if (ps)
-		putchar(' ');
-	    (void) print_tcptpi(0);
-	}
-	if (nl)
-	    putchar('\n');
-}
-
-
-/*
- * printrawaddr() - print raw socket address
- */
-
-void
-printrawaddr(sa)
-	struct sockaddr *sa;		/* socket address */
-{
-	char *ep;
-	size_t sz;
-
-	ep = endnm(&sz);
-	(void) snpf(ep, sz, "%u/%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u",
-	    sa->sa_family,
-	    (unsigned char)sa->sa_data[0],
-	    (unsigned char)sa->sa_data[1],
-	    (unsigned char)sa->sa_data[2],
-	    (unsigned char)sa->sa_data[3],
-	    (unsigned char)sa->sa_data[4],
-	    (unsigned char)sa->sa_data[5],
-	    (unsigned char)sa->sa_data[6],
-	    (unsigned char)sa->sa_data[7],
-	    (unsigned char)sa->sa_data[8],
-	    (unsigned char)sa->sa_data[9],
-	    (unsigned char)sa->sa_data[10],
-	    (unsigned char)sa->sa_data[11],
-	    (unsigned char)sa->sa_data[12],
-	    (unsigned char)sa->sa_data[13]);
-}
-
-
-/*
- * printsockty() - print socket type
- */
-
-char *
-printsockty(ty)
-	int ty;				/* socket type -- e.g., from so_type */
-{
-	static char buf[64];
-	char *cp;
-
-	switch (ty) {
-
-#if	defined(SOCK_STREAM)
-	case SOCK_STREAM:
-	    cp = "STREAM";
-	    break;
-#endif	/* defined(SOCK_STREAM) */
-
-#if	defined(SOCK_STREAM)
-	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) */
-
-	default:
-	    (void) snpf(buf, sizeof(buf), "SOCK_%#x", ty);
-	    return(buf);
-	}
-	(void) snpf(buf, sizeof(buf), "SOCK_%s", cp);
-	return(buf);
-}
-
-
-/*
- * printuid() - print User ID or login name
- */
-
-char *
-printuid(uid, ty)
-	UID_ARG uid;			/* User IDentification number */
-	int *ty;			/* returned UID type pointer (NULL
-					 * (if none wanted).  If non-NULL
-					 * then: *ty = 0 = login name
-					 *	     = 1 = UID number */
-{
-	int i;
-	struct passwd *pw;
-	struct stat sb;
-	static struct stat sbs;
-	static struct uidcache {
-	    uid_t uid;
-	    char nm[LOGINML+1];
-	    struct uidcache *next;
-	} **uc = (struct uidcache **)NULL;
-	struct uidcache *up, *upn;
-	static char user[USERPRTL+1];
-
-	if (Futol) {
-	    if (CkPasswd) {
-
-	    /*
-	     * Get the mtime and ctime of /etc/passwd, as required.
-	     */
-		if (stat("/etc/passwd", &sb) != 0) {
-		    (void) fprintf(stderr, "%s: can't stat(/etc/passwd): %s\n",
-			Pn, strerror(errno));
-		    Error();
-		}
-	    }
-	/*
-	 * Define the UID cache, if necessary.
-	 */
-	    if (!uc) {
-		if (!(uc = (struct uidcache **)calloc(UIDCACHEL,
-						sizeof(struct uidcache *))))
-		{
-		    (void) fprintf(stderr,
-			"%s: no space for %d byte UID cache hash buckets\n",
-			Pn, (int)(UIDCACHEL * (sizeof(struct uidcache *))));
-		    Error();
-		}
-		if (CkPasswd) {
-		    sbs = sb;
-		    CkPasswd = 0;
-		}
-	    }
-	/*
-	 * If it's time to check /etc/passwd and if its the mtime/ctime has
-	 * changed, destroy the existing UID cache.
-	 */
-	    if (CkPasswd) {
-		if (sbs.st_mtime != sb.st_mtime || sbs.st_ctime != sb.st_ctime)
-		{
-		    for (i = 0; i < UIDCACHEL; i++) {
-			if ((up = uc[i])) {
-			    do {
-				upn = up->next;
-				(void) free((FREE_P *)up);
-			    } while ((up = upn) != (struct uidcache *)NULL);
-			    uc[i] = (struct uidcache *)NULL;
-			}
-		    }
-		    sbs = sb;
-		}
-		CkPasswd = 0;
-	    }
-	/*
-	 * Search the UID cache.
-	 */
-	    i = (int)((((unsigned long)uid * 31415L) >> 7) & (UIDCACHEL - 1));
-	    for (up = uc[i]; up; up = up->next) {
-		if (up->uid == (uid_t)uid) {
-		    if (ty)
-			*ty = 0;
-		    return(up->nm);
-		}
-	    }
-	/*
-	 * The UID is not in the cache.
-	 *
-	 * Look up the login name from the UID for a new cache entry.
-	 */
-	    if (!(pw = getpwuid((uid_t)uid))) {
-		if (!Fwarn) {
-		    (void) fprintf(stderr, "%s: no pwd entry for UID %lu\n",
-			Pn, (unsigned long)uid);
-		}
-	    } else {
-
-	    /*
-	     * Allocate and fill a new cache entry.  Link it to its hash bucket.
-	     */
-		if (!(upn = (struct uidcache *)malloc(sizeof(struct uidcache))))
-		{
-		    (void) fprintf(stderr,
-			"%s: no space for UID cache entry for: %lu, %s)\n",
-			Pn, (unsigned long)uid, pw->pw_name);
-		    Error();
-		}
-		(void) strncpy(upn->nm, pw->pw_name, LOGINML);
-		upn->nm[LOGINML] = '\0';
-		upn->uid = (uid_t)uid;
-		upn->next = uc[i];
-		uc[i] = upn;
-		if (ty)
-		    *ty = 0;
-		return(upn->nm);
-	    }
-	}
-/*
- * Produce a numeric conversion of the UID.
- */
-	(void) snpf(user, sizeof(user), "%*lu", USERPRTL, (unsigned long)uid);
-	if (ty)
-	    *ty = 1;
-	return(user);
-}
-
-
-/*
- * printunkaf() - print unknown address family
- */
-
-void
-printunkaf(fam, ty)
-	int fam;			/* unknown address family */
-	int ty;				/* output type: 0 = terse; 1 = full */
-{
-	char *p, *s;
-
-	p = "";
-	switch (fam) {
-
-#if	defined(AF_UNSPEC)
-	case AF_UNSPEC:
-	    s = "UNSPEC";
-	    break;
-#endif	/* defined(AF_UNSPEC) */
-
-#if	defined(AF_UNIX)
-	case AF_UNIX:
-	    s = "UNIX";
-	    break;
-#endif	/* defined(AF_UNIX) */
-
-#if	defined(AF_INET)
-	case AF_INET:
-	    s = "INET";
-	    break;
-#endif	/* defined(AF_INET) */
-
-#if	defined(AF_INET6)
-	case AF_INET6:
-	    s = "INET6";
-	    break;
-#endif	/* defined(AF_INET6) */
-
-#if	defined(AF_IMPLINK)
-	case AF_IMPLINK:
-	    s = "IMPLINK";
-	    break;
-#endif	/* defined(AF_IMPLINK) */
-
-#if	defined(AF_PUP)
-	case AF_PUP:
-	    s = "PUP";
-	    break;
-#endif	/* defined(AF_PUP) */
-
-#if	defined(AF_CHAOS)
-	case AF_CHAOS:
-	    s = "CHAOS";
-	    break;
-#endif	/* defined(AF_CHAOS) */
-
-#if	defined(AF_NS)
-	case AF_NS:
-	    s = "NS";
-	    break;
-#endif	/* defined(AF_NS) */
-
-#if	defined(AF_ISO)
-	case AF_ISO:
-	    s = "ISO";
-	    break;
-#endif	/* defined(AF_ISO) */
-
-#if	defined(AF_NBS)
-# if	!defined(AF_ISO) || AF_NBS!=AF_ISO
-	case AF_NBS:
-	    s = "NBS";
-	    break;
-# endif	/* !defined(AF_ISO) || AF_NBS!=AF_ISO */
-#endif	/* defined(AF_NBS) */
-
-#if	defined(AF_ECMA)
-	case AF_ECMA:
-	    s = "ECMA";
-	    break;
-#endif	/* defined(AF_ECMA) */
-
-#if	defined(AF_DATAKIT)
-	case AF_DATAKIT:
-	    s = "DATAKIT";
-	    break;
-#endif	/* defined(AF_DATAKIT) */
-
-#if	defined(AF_CCITT)
-	case AF_CCITT:
-	    s = "CCITT";
-	    break;
-#endif	/* defined(AF_CCITT) */
-
-#if	defined(AF_SNA)
-	case AF_SNA:
-	    s = "SNA";
-	    break;
-#endif	/* defined(AF_SNA) */
-
-#if	defined(AF_DECnet)
-	case AF_DECnet:
-	    s = "DECnet";
-	    break;
-#endif	/* defined(AF_DECnet) */
-
-#if	defined(AF_DLI)
-	case AF_DLI:
-	    s = "DLI";
-	    break;
-#endif	/* defined(AF_DLI) */
-
-#if	defined(AF_LAT)
-	case AF_LAT:
-	    s = "LAT";
-	    break;
-#endif	/* defined(AF_LAT) */
-
-#if	defined(AF_HYLINK)
-	case AF_HYLINK:
-	    s = "HYLINK";
-	    break;
-#endif	/* defined(AF_HYLINK) */
-
-#if	defined(AF_APPLETALK)
-	case AF_APPLETALK:
-	    s = "APPLETALK";
-	    break;
-#endif	/* defined(AF_APPLETALK) */
-
-#if	defined(AF_BSC)
-	case AF_BSC:
-	    s = "BSC";
-	    break;
-#endif	/* defined(AF_BSC) */
-
-#if	defined(AF_DSS)
-	case AF_DSS:
-	    s = "DSS";
-	    break;
-#endif	/* defined(AF_DSS) */
-
-#if	defined(AF_ROUTE)
-	case AF_ROUTE:
-	    s = "ROUTE";
-	    break;
-#endif	/* defined(AF_ROUTE) */
-
-#if	defined(AF_RAW)
-	case AF_RAW:
-	    s = "RAW";
-	    break;
-#endif	/* defined(AF_RAW) */
-
-#if	defined(AF_LINK)
-	case AF_LINK:
-	    s = "LINK";
-	    break;
-#endif	/* defined(AF_LINK) */
-
-#if	defined(pseudo_AF_XTP)
-	case pseudo_AF_XTP:
-	    p = "pseudo_";
-	    s = "XTP";
-	    break;
-#endif	/* defined(pseudo_AF_XTP) */
-
-#if	defined(AF_RMP)
-	case AF_RMP:
-	    s = "RMP";
-	    break;
-#endif	/* defined(AF_RMP) */
-
-#if	defined(AF_COIP)
-	case AF_COIP:
-	    s = "COIP";
-	    break;
-#endif	/* defined(AF_COIP) */
-
-#if	defined(AF_CNT)
-	case AF_CNT:
-	    s = "CNT";
-	    break;
-#endif	/* defined(AF_CNT) */
-
-#if	defined(pseudo_AF_RTIP)
-	case pseudo_AF_RTIP:
-	    p = "pseudo_";
-	    s = "RTIP";
-	    break;
-#endif	/* defined(pseudo_AF_RTIP) */
-
-#if	defined(AF_NETMAN)
-	case AF_NETMAN:
-	    s = "NETMAN";
-	    break;
-#endif	/* defined(AF_NETMAN) */
-
-#if	defined(AF_INTF)
-	case AF_INTF:
-	    s = "INTF";
-	    break;
-#endif	/* defined(AF_INTF) */
-
-#if	defined(AF_NETWARE)
-	case AF_NETWARE:
-	    s = "NETWARE";
-	    break;
-#endif	/* defined(AF_NETWARE) */
-
-#if	defined(AF_NDD)
-	case AF_NDD:
-	    s = "NDD";
-	    break;
-#endif	/* defined(AF_NDD) */
-
-#if	defined(AF_NIT)
-# if	!defined(AF_ROUTE) || AF_ROUTE!=AF_NIT
-	case AF_NIT:
-	    s = "NIT";
-	    break;
-# endif	/* !defined(AF_ROUTE) || AF_ROUTE!=AF_NIT */
-#endif	/* defined(AF_NIT) */
-
-#if	defined(AF_802)
-# if	!defined(AF_RAW) || AF_RAW!=AF_802
-	case AF_802:
-	    s = "802";
-	    break;
-# endif	/* !defined(AF_RAW) || AF_RAW!=AF_802 */
-#endif	/* defined(AF_802) */
-
-#if	defined(AF_X25)
-	case AF_X25:
-	    s = "X25";
-	    break;
-#endif	/* defined(AF_X25) */
-
-#if	defined(AF_CTF)
-	case AF_CTF:
-	    s = "CTF";
-	    break;
-#endif	/* defined(AF_CTF) */
-
-#if	defined(AF_WAN)
-	case AF_WAN:
-	    s = "WAN";
-	    break;
-#endif	/* defined(AF_WAN) */
-
-#if	defined(AF_OSINET)
-# if	defined(AF_INET) && AF_INET!=AF_OSINET
-	case AF_OSINET:
-	    s = "OSINET";
-	    break;
-# endif	/* defined(AF_INET) && AF_INET!=AF_OSINET */
-#endif	/* defined(AF_OSINET) */
-
-#if	defined(AF_GOSIP)
-	case AF_GOSIP:
-	    s = "GOSIP";
-	    break;
-#endif	/* defined(AF_GOSIP) */
-
-#if	defined(AF_SDL)
-	case AF_SDL:
-	    s = "SDL";
-	    break;
-#endif	/* defined(AF_SDL) */
-
-#if	defined(AF_IPX)
-	case AF_IPX:
-	    s = "IPX";
-	    break;
-#endif	/* defined(AF_IPX) */
-
-#if	defined(AF_SIP)
-	case AF_SIP:
-	    s = "SIP";
-	    break;
-#endif	/* defined(AF_SIP) */
-
-#if	defined(psuedo_AF_PIP)
-	case psuedo_AF_PIP:
-	    p = "pseudo_";
-	    s = "PIP";
-	    break;
-#endif	/* defined(psuedo_AF_PIP) */
-
-#if	defined(AF_OTS)
-	case AF_OTS:
-	    s = "OTS";
-	    break;
-#endif	/* defined(AF_OTS) */
-
-#if	defined(pseudo_AF_BLUE)
-	case pseudo_AF_BLUE:	/* packets for Blue box */
-	    p = "pseudo_";
-	    s = "BLUE";
-	    break;
-#endif	/* defined(pseudo_AF_BLUE) */
-
-#if	defined(AF_NDRV)	/* network driver raw access */
-	case AF_NDRV:
-	    s = "NDRV";
-	    break;
-#endif	/* defined(AF_NDRV) */
-
-#if	defined(AF_SYSTEM)	/* kernel event messages */
-	case AF_SYSTEM:
-	    s = "SYSTEM";
-	    break;
-#endif	/* defined(AF_SYSTEM) */
-
-#if	defined(AF_USER)
-	case AF_USER:
-	    s = "USER";
-	    break;
-#endif	/* defined(AF_USER) */
-
-#if	defined(pseudo_AF_KEY)
-	case pseudo_AF_KEY:
-	    p = "pseudo_";
-	    s = "KEY";
-	    break;
-#endif	/* defined(pseudo_AF_KEY) */
-
-#if	defined(AF_KEY)		/* Security Association DB socket */
-	case AF_KEY:
-	    s = "KEY";
-	    break;
-#endif	/* defined(AF_KEY) */
-
-#if	defined(AF_NCA)		/* NCA socket */
-	case AF_NCA:
-	    s = "NCA";
-	    break;
-#endif	/* defined(AF_NCA) */
-
-#if	defined(AF_POLICY)		/* Security Policy DB socket */
-	case AF_POLICY:
-	    s = "POLICY";
-	    break;
-#endif	/* defined(AF_POLICY) */
-
-#if	defined(AF_PPP)		/* PPP socket */
-	case AF_PPP:
-	    s = "PPP";
-	    break;
-#endif	/* defined(AF_PPP) */
-
-	default:
-	    if (!ty)
-		(void) snpf(Namech, Namechl, "%#x", fam);
-	    else
-		(void) snpf(Namech, Namechl,
-		    "no further information on family %#x", fam);
-	    return;
-	}
-	if (!ty)
-	    (void) snpf(Namech, Namechl, "%sAF_%s", p, s);
-	else
-	    (void) snpf(Namech, Namechl, "no further information on %sAF_%s",
-		p, s);
-	return;
-}
-
-
-#if	!defined(HASNORPC_H)
-/*
- * update_portmap() - update a portmap entry with its port number or service
- *		      name
- */
-
-static void
-update_portmap(pt, pn)
-	struct porttab *pt;		/* porttab entry */
-	char *pn;			/* port name */
-{
-	MALLOC_S al, nl;
-	char *cp;
-
-	if (pt->ss)
-	    return;
-	if (!(al = strlen(pn))) {
-	    pt->ss = 1;
-	    return;
-	}
-	nl = al + pt->nl + 2;
-	if (!(cp = (char *)malloc(nl + 1))) {
-	    (void) fprintf(stderr,
-		"%s: can't allocate %d bytes for portmap name: %s[%s]\n",
-		Pn, (int)(nl + 1), pn, pt->name);
-	    Error();
-	}
-	(void) snpf(cp, nl + 1, "%s[%s]", pn, pt->name);
-	(void) free((FREE_P *)pt->name);
-	pt->name = cp;
-	pt->nl = nl;
-	pt->ss = 1;
-}
-#endif	/* !defined(HASNORPC_H) */
diff --git a/proc.c b/proc.c
deleted file mode 100644
index a085cc6..0000000
--- a/proc.c
+++ /dev/null
@@ -1,1794 +0,0 @@
-/*
- * proc.c - common process and file structure 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";
-#endif
-
-
-#include "lsof.h"
-
-#if	defined(HASEPTOPTS)
-_PROTOTYPE(static void prt_pinfo,(pxinfo_t *pp, int ps));
-_PROTOTYPE(static void prt_psxmqinfo,(pxinfo_t *pp, int ps));
-_PROTOTYPE(static void prt_evtfdinfo,(pxinfo_t *pp, int ps));
-#endif  /* defined(HASEPTOPTS) */
-#if	defined(HASPTYEPT)
-_PROTOTYPE(static void prt_ptyinfo,(pxinfo_t *pp, int prt_edev, int ps));
-#endif	/* defined(HASPTYEPT) */
-
-
-/*
- * add_nma() - add to NAME column addition
- */
-
-void
-add_nma(cp, len)
-	char *cp;			/* string to add */
-	int len;			/* string length */
-{
-	int nl;
-
-	if (!cp || !len)
-	    return;
-	if (Lf->nma) {
-	    nl = (int) strlen(Lf->nma);
-	    Lf->nma = (char *) realloc((MALLOC_P *)Lf->nma,
-				       (MALLOC_S)(len + nl + 2));
-	} else {
-	    nl = 0;
-	    Lf->nma = (char *) malloc((MALLOC_S)(len + 1));
-	}
-	if (!Lf->nma) {
-	    (void) fprintf(stderr, "%s: no name addition space: PID %ld, FD %s",
-		Pn, (long)Lp->pid, Lf->fd);
-	    Error();
-	}
-	if (nl) {
-	    Lf->nma[nl] = ' ';
-	    (void) strncpy(&Lf->nma[nl + 1], cp, len);
-	    Lf->nma[nl + 1 + len] = '\0';
-	} else {
-	    (void) strncpy(Lf->nma, cp, len);
-	    Lf->nma[len] = '\0';
-	}
-}
-
-
-#if	defined(HASFSTRUCT)
-_PROTOTYPE(static char *alloc_fflbuf,(char **bp, int *al, int lr));
-
-
-/*
- * alloc_fflbuf() - allocate file flags print buffer
- */
-
-static char *
-alloc_fflbuf(bp, al, lr)
-	char **bp;			/* current buffer pointer */
-	int *al;			/* current allocated length */
-	int lr;				/* length required */
-{
-	int sz;
-
-	sz = (int)(lr + 1);		/* allocate '\0' space */
-	if (*bp && (sz <= *al))
-	    return(*bp);
-	if (*bp)
-	    *bp = (char *)realloc((MALLOC_P *)*bp, (MALLOC_S)sz);
-	else
-	    *bp = (char *)malloc((MALLOC_S)sz);
-	if (!*bp) {
-	    (void) fprintf(stderr, "%s: no space (%d) for print flags\n",
-		Pn, sz);
-	    Error();
-	}
-	*al = sz;
-	return(*bp);
-}
-#endif	/* defined(HASFSTRUCT) */
-
-
-/*
- * alloc_lfile() - allocate local file structure space
- */
-
-void
-alloc_lfile(nm, num)
-	char *nm;			/* file descriptor name (may be NULL) */
-	int num;			/* file descriptor number -- -1 if
-					 * none */
-{
-	int fds;
-
-	if (Lf) {
-/*
- * If reusing a previously allocated structure, release any allocated
- * space it was using.
- */
-	    if (Lf->dev_ch)
-		(void) free((FREE_P *)Lf->dev_ch);
-	    if (Lf->nm)
-		(void) free((FREE_P *)Lf->nm);
-	    if (Lf->nma)
-		(void) free((FREE_P *)Lf->nma);
-
-#if	defined(HASLFILEADD) && defined(CLRLFILEADD)
-	    CLRLFILEADD(Lf)
-#endif	/* defined(HASLFILEADD) && defined(CLRLFILEADD) */
-
-/*
- * Othwerise, allocate a new structure.
- */
-	} else if (!(Lf = (struct lfile *)malloc(sizeof(struct lfile)))) {
-	    (void) fprintf(stderr, "%s: no local file space at PID %d\n",
-		Pn, Lp->pid);
-	    Error();
-	}
-/*
- * Initialize the structure.
- */
-	Lf->access = Lf->lock = ' ';
-	Lf->dev_def = Lf->inp_ty = Lf->is_com = Lf->is_nfs = Lf->is_stream
-		    = Lf->lmi_srch = Lf->nlink_def = Lf->off_def = Lf->sz_def
-		    = Lf->rdev_def
-		    = (unsigned char)0;
-	Lf->li[0].af = Lf->li[1].af = 0;
-	Lf->lts.type = -1;
-	Lf->nlink = 0l;
-
-#if	defined(HASMNTSTAT)
-	Lf->mnt_stat = (unsigned char)0;
-#endif	/* defined(HASMNTSTAT) */
-
-#if	defined(HASEPTOPTS)
-	Lf->chend = 0;
-	Lf->eventfd_id = -1;
-#if	defined(HASPTYEPT)
-	Lf->tty_index  = -1;
-#endif	/* defined(HASPTYEPT) */
-#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
-		    = (unsigned int)0;
-	Lf->lts.rbsz = Lf->lts.sbsz = (unsigned long)0;
-	Lf->lts.qlens = Lf->lts.qlims = Lf->lts.pqlens = Lf->lts.rbszs
-		      = Lf->lts.sbszs = (unsigned char)0;
-#endif	/* defined(HASSOOPT) */
-
-#if	defined(HASSOSTATE)
-	Lf->lts.ss = 0;
-#endif	/* defined(HASSOSTATE) */
-
-#if	defined(HASTCPOPT)
-	Lf->lts.mss = (unsigned long)0;
-	Lf->lts.msss = (unsigned char)0;
-	Lf->lts.topt = (unsigned int)0;
-#endif	/* defined(HASTCPOPT) */
-
-#if	defined(HASTCPTPIQ)
-	Lf->lts.rqs = Lf->lts.sqs = (unsigned char)0;
-#endif	/* defined(HASTCPTPIQ) */
-
-#if	defined(HASTCPTPIW)
-	Lf->lts.rws = Lf->lts.wws = (unsigned char)0;
-#endif	/* defined(HASTCPTPIW) */
-
-#if	defined(HASFSINO)
-	Lf->fs_ino = 0;
-#endif	/* defined(HASFSINO) */
-
-#if	defined(HASVXFS) && defined(HASVXFSDNLC)
-	Lf->is_vxfs = 0;
-#endif	/* defined(HASVXFS) && defined(HASVXFSDNLC) */
-
-	Lf->inode = (INODETYPE)0;
-	Lf->off = (SZOFFTYPE)0;
-	if (Lp->pss & PS_PRI)
-	    Lf->sf = Lp->sf;
-	else
-	    Lf->sf = 0;
-	Lf->iproto[0] = Lf->type[0] = '\0';
-	if (nm) {
-	    (void) strncpy(Lf->fd, nm, FDLEN - 1);
-	    Lf->fd[FDLEN - 1] = '\0';
-	} else if (num >= 0) {
-	    if (num < 10000)
-		(void) snpf(Lf->fd, sizeof(Lf->fd), "%4d", num);
-	    else
-		(void) snpf(Lf->fd, sizeof(Lf->fd), "*%03d", num % 1000);
-	} else
-	    Lf->fd[0] = '\0';
-	Lf->dev_ch = Lf->fsdir = Lf->fsdev = Lf->nm = Lf->nma = (char *)NULL;
-	Lf->ch = -1;
-
-#if	defined(HASNCACHE) && HASNCACHE<2
-	Lf->na = (KA_T)NULL;
-#endif	/* defined(HASNCACHE) && HASNCACHE<2 */
-
-	Lf->next = (struct lfile *)NULL;
-	Lf->ntype = Ntype = N_REGLR;
-	Namech[0] = '\0';
-
-#if	defined(HASFSTRUCT)
-	Lf->fct = Lf->ffg = Lf->pof = (long)0;
-	Lf->fna = (KA_T)NULL;
-	Lf->fsv = (unsigned char)0;
-#endif	/* defined(HASFSTRUCT) */
-
-#if	defined(HASLFILEADD) && defined(SETLFILEADD)
-/*
- * Do local initializations.
- */
-	SETLFILEADD
-#endif	/* defined(HASLFILEADD) && defined(SETLFILEADD) */
-
-/*
- * See if the file descriptor has been selected.
- */
-	if (!Fdl || (!nm && num < 0))
-	    return;
-	fds = ck_fd_status(nm, num);
-	switch (FdlTy) {
-	case 0:			/* inclusion list */
-	    if (fds == 2)
-		Lf->sf |= SELFD;
-	    break;
-	case 1:			/* exclusion list */
-	    if (fds != 1)
-		Lf->sf |= SELFD;
-	}
-}
-
-
-/*
- * alloc_lproc() - allocate local proc structure space
- */
-
-void
-alloc_lproc(pid, pgid, ppid, uid, cmd, pss, sf)
-	int pid;			/* Process ID */
-	int pgid;			/* process group ID */
-	int ppid;			/* parent process ID */
-	UID_ARG uid;			/* User ID */
-	char *cmd;			/* command */
-	int pss;			/* process select state */
-	int sf;				/* process select flags */
-{
-	static int sz = 0;
-
-	if (!Lproc) {
-	    if (!(Lproc = (struct lproc *)malloc(
-			  (MALLOC_S)(LPROCINCR * sizeof(struct lproc)))))
-	    {
-		(void) fprintf(stderr,
-		    "%s: no malloc space for %d local proc structures\n",
-		    Pn, LPROCINCR);
-		Error();
-	    }
-	    sz = LPROCINCR;
-	} else if ((Nlproc + 1) > sz) {
-	    sz += LPROCINCR;
-	    if (!(Lproc = (struct lproc *)realloc((MALLOC_P *)Lproc,
-			  (MALLOC_S)(sz * sizeof(struct lproc)))))
-	    {
-		(void) fprintf(stderr,
-		    "%s: no realloc space for %d local proc structures\n",
-		    Pn, sz);
-		Error();
-	    }
-	}
-	Lp = &Lproc[Nlproc++];
-	Lp->pid = pid;
-
-#if	defined(HASEPTOPTS)
-	Lp->ept = 0;
-#endif	/* defined(HASEPTOPTS) */
-
-#if	defined(HASTASKS)
-	Lp->tid = 0;
-	Lp->tcmd = (char *)NULL;
-#endif	/* defined(HASTASKS) */
-
-	Lp->pgid = pgid;
-	Lp->ppid = ppid;
-	Lp->file = (struct lfile *)NULL;
-	Lp->sf = (short)sf;
-	Lp->pss = (short)pss;
-	Lp->uid = (uid_t)uid;
-/*
- * Allocate space for the full command name and copy it there.
- */
-	if (!(Lp->cmd = mkstrcpy(cmd, (MALLOC_S *)NULL))) {
-	    (void) fprintf(stderr, "%s: PID %d, no space for command name: ",
-		Pn, pid);
-	    safestrprt(cmd, stderr, 1);
-	    Error();
-	}
-
-#if	defined(HASZONES)
-/*
- * Clear the zone name pointer.  The dialect's own code will set it.
- */
-	Lp->zn = (char *)NULL;
-#endif	/* defined(HASZONES) */
-
-#if	defined(HASSELINUX)
-/*
- * Clear the security context pointer.  The dialect's own code will
- * set it.
- */
-	Lp->cntx = (char *)NULL;
-#endif	/* defined(HASSELINUX) */
-
-}
-
-
-/*
- * ck_fd_status() - check FD status
- *
- * return: 0 == FD is neither included nor excluded
- *	   1 == FD is excluded
- *	   2 == FD is included
- */
-
-extern int
-ck_fd_status(nm, num)
-	char *nm;			/* file descriptor name (may be NULL) */
-	int num;			/* file descriptor number -- -1 if
-					 * none */
-{
-	char *cp;
-	struct fd_lst *fp;
-
-	if (!(fp = Fdl) || (!nm && num < 0))
-	    return(0);
-	if ((cp = nm)) {
-	    while (*cp && *cp == ' ')
-		cp++;
-	}
-/*
- * Check for an exclusion match.
- */
-	if (FdlTy == 1) {
-	    for (; fp; fp = fp->next) {
-		if (cp) {
-		    if (fp->nm && strcmp(fp->nm, cp) == 0)
-			return(1);
-		    continue;
-		}
-		if (num >= fp->lo && num <= fp->hi)
-		    return(1);
-	    }
-	    return(0);
-	}
-/*
- * If Fdl isn't an exclusion list, check for an inclusion match.
- */
-	for (; fp; fp = fp->next) {
-	    if (cp) {
-		if (fp->nm && strcmp(fp->nm, cp) == 0)
-		    return(2);
-		continue;
-	    }
-	    if (num >= fp->lo && num <= fp->hi)
-		return(2);
-	}
-	return(0);
-}
-
-
-/*
- * comppid() - compare PIDs
- */
-
-int
-comppid(a1, a2)
-	COMP_P *a1, *a2;
-{
-	struct lproc **p1 = (struct lproc **)a1;
-	struct lproc **p2 = (struct lproc **)a2;
-
-	if ((*p1)->pid < (*p2)->pid)
-	    return(-1);
-	if ((*p1)->pid > (*p2)->pid)
-	    return(1);
-
-#if	defined(HASTASKS)
-	if ((*p1)->tid < (*p2)->tid)
-	    return(-1);
-	if ((*p1)->tid > (*p2)->tid)
-	    return(1);
-#endif	/* defined(HASTASKS) */
-
-	return(0);
-}
-
-
-/*
- * ent_inaddr() - enter Internet addresses
- */
-
-void
-ent_inaddr(la, lp, fa, fp, af)
-	unsigned char *la;		/* local Internet address */
-	int lp;				/* local port */
-	unsigned char *fa;		/* foreign Internet address -- may
-					 * be NULL to indicate no foreign
-					 * address is known */
-	int fp;				/* foreign port */
-	int af;				/* address family -- e.g, AF_INET,
-					 * AF_INET */
-{
-	int m;
-
-	if (la) {
-	    Lf->li[0].af = af;
-
-#if	defined(HASIPv6)
-	    if (af == AF_INET6)
-		Lf->li[0].ia.a6 = *(struct in6_addr *)la;
-	    else
-#endif	/* defined(HASIPv6) */
-
-		Lf->li[0].ia.a4 = *(struct in_addr *)la;
-	    Lf->li[0].p = lp;
-	} else
-	    Lf->li[0].af = 0;
-	if (fa) {
-	    Lf->li[1].af = af;
-
-#if	defined(HASIPv6)
-	    if (af == AF_INET6)
-		Lf->li[1].ia.a6 = *(struct in6_addr *)fa;
-	    else
-#endif	/* defined(HASIPv6) */
-
-		Lf->li[1].ia.a4 = *(struct in_addr *)fa;
-	    Lf->li[1].p = fp;
-	} else
-	    Lf->li[1].af = 0;
-/*
- * If network address matching has been selected, check both addresses.
- */
-	if ((Selflags & SELNA) && Nwad) {
-	    m = (fa && is_nw_addr(fa, fp, af)) ? 1 : 0;
-	    m |= (la && is_nw_addr(la, lp, af)) ? 1 : 0;
-	    if (m)
-		Lf->sf |= SELNA;
-	}
-}
-
-
-/*
- * examine_lproc() - examine local process
- *
- * return: 1 = last process
- */
-
-int
-examine_lproc()
-{
-	int sbp = 0;
-
-	if (RptTm)
-	    return(0);
-/*
- * List the process if the process is selected and:
- *
- *	o  listing is limited to a single PID selection -- this one;
- *
- *	o  listing is selected by an ANDed option set (not all options)
- *	   that includes a single PID selection -- this one.
- */
-	if ((Lp->sf & SELPID) && !AllProc) {
-	    if ((Selflags == SELPID)
-	    ||  (Fand && (Selflags & SELPID))) {
-		sbp = 1;
-		Npuns--;
-	    }
-	}
-	if (Lp->pss && Npid == 1 && sbp) {
-	    print_init();
-	    (void) print_proc();
-	    PrPass++;
-	    if (PrPass < 2)
-		(void) print_proc();
-	    Lp->pss = 0;
-	}
-/*
- * Deprecate an unselected (or listed) process.
- */
-	if ( ! Lp->pss) {
-	    (void) free_lproc(Lp);
-	    Nlproc--;
-	}
-/*
- * Indicate last-process if listing is limited to PID selections,
- * and all selected processes have been listed.
- */
-	return((sbp && Npuns == 0) ? 1 : 0);
-}
-
-
-/*
- * free_lproc() - free lproc entry and its associated malloc'd space
- */
-
-void
-free_lproc(lp)
-	struct lproc *lp;
-{
-	struct lfile *lf, *nf;
-
-	for (lf = lp->file; lf; lf = nf) {
-	    if (lf->dev_ch) {
-		(void) free((FREE_P *)lf->dev_ch);
-		lf->dev_ch = (char *)NULL;
-	    }
-	    if (lf->nm) {
-		(void) free((FREE_P *)lf->nm);
-		lf->nm = (char *)NULL;
-	    }
-	    if (lf->nma) {
-		(void) free((FREE_P *)lf->nma);
-		lf->nma = (char *)NULL;
-	    }
-
-#if	defined(HASLFILEADD) && defined(CLRLFILEADD)
-	    CLRLFILEADD(lf)
-#endif	/* defined(HASLFILEADD) && defined(CLRLFILEADD) */
-
-	    nf = lf->next;
-	    (void) free((FREE_P *)lf);
-	}
-	lp->file = (struct lfile *)NULL;
-	if (lp->cmd) {
-	    (void) free((FREE_P *)lp->cmd);
-	    lp->cmd = (char *)NULL;
-	}
-
-#if	defined(HASTASKS)
-	if (lp->tcmd) {
-	    (void) free((FREE_P *)lp->tcmd);
-	    lp->tcmd = (char *)NULL;
-	}
-#endif	/* defined(HASTASKS) */
-
-}
-
-
-/*
- * is_cmd_excl() - is command excluded?
- */
-
-int
-is_cmd_excl(cmd, pss, sf)
-	char *cmd;			/* command name */
-	short *pss;			/* process state */
-	short *sf;			/* process select flags */
-{
-	int i;
-	struct str_lst *sp;
-/*
- * See if the command is excluded by a "-c^<command>" option.
- */
-	if (Cmdl && Cmdnx) {
-	    for (sp = Cmdl; sp; sp = sp->next) {
-		if (sp->x && !strncmp(sp->str, cmd, sp->len))
-		    return(1);
-	    }
-	}
-/*
- * The command is not excluded if no command selection was requested,
- * or if its name matches any -c <command> specification.
- *
- */
-	if ((Selflags & SELCMD) == 0)
-	    return(0);
-	for (sp = Cmdl; sp; sp = sp->next) {
-	    if (!sp->x && !strncmp(sp->str, cmd, sp->len)) {
-		sp->f = 1;
-		*pss |= PS_PRI;
-		*sf |= SELCMD;
-		return(0);
-	    }
-	}
-/*
- * The command name doesn't match any -c <command> specification.  See if it
- * matches a -c /RE/[bix] specification.
- */
-	for (i = 0; i < NCmdRxU; i++) {
-	    if (!regexec(&CmdRx[i].cx, cmd, 0, NULL, 0)) {
-		CmdRx[i].mc = 1;
-		*pss |= PS_PRI;
-		*sf |= SELCMD;
-		return(0);
-	    }
-	}
-/*
- * The command name matches no -c specification.
- *
- * It's excluded if the only selection condition is command name,
- * or if command name selection is part of an ANDed set.
- */
-	if (Selflags == SELCMD)
-	    return(1);
-	return (Fand ? 1 : 0);
-}
-
-
-/*
- * is_file_sel() - is file selected?
- */
-
-int
-is_file_sel(lp, lf)
-	struct lproc *lp;		/* lproc structure pointer */
-	struct lfile *lf;		/* lfile structure pointer */
-{
-	if (!lf || !lf->sf)
-	    return(0);
-	if (Lf->sf & SELEXCLF)
-	    return(0);
-
-#if	defined(HASSECURITY) && defined(HASNOSOCKSECURITY)
-	if (Myuid && (Myuid != lp->uid)) {
-	    if (!(lf->sf & (SELNA | SELNET)))
-		return(0);
-	}
-#endif	/* defined(HASSECURITY) && defined(HASNOSOCKSECURITY) */
-
-	if (AllProc)
-	    return(1);
-	if (Fand && ((lf->sf & Selflags) != Selflags))
-	    return(0);
-	return(1);
-}
-
-
-/*
- * is_proc_excl() - is process excluded?
- */
-
-int
-
-#if	defined(HASTASKS)
-is_proc_excl(pid, pgid, uid, pss, sf, tid)
-#else	/* !defined(HASTASKS) */
-is_proc_excl(pid, pgid, uid, pss, sf)
-#endif	/* defined(HASTASKS) */
-
-	int pid;			/* Process ID */
-	int pgid;			/* process group ID */
-	UID_ARG uid;			/* User ID */
-	short *pss;			/* process select state for lproc */
-	short *sf;			/* select flags for lproc */
-
-#if	defined(HASTASKS)
-	int tid;			/* task ID (not a task if zero) */
-#endif	/* defined(HASTASKS) */
-
-{
-	int i, j;
-
-	*pss = *sf = 0;
-
-#if	defined(HASSECURITY)
-/*
- * The process is excluded by virtue of the security option if it
- * isn't owned by the owner of this lsof process, unless the
- * HASNOSOCKSECURITY option is also specified.  In that case the
- * selected socket files of any process may be listed.
- */
-# if	!defined(HASNOSOCKSECURITY)
-	if (Myuid && Myuid != (uid_t)uid)
-	    return(1);
-# endif	/* !defined(HASNOSOCKSECURITY) */
-#endif	/* defined(HASSECURITY) */
-
-/*
- * If the excluding of process listing by UID has been specified, see if the
- * owner of this process is excluded.
- */
-	if (Nuidexcl) {
-	    for (i = j = 0; (i < Nuid) && (j < Nuidexcl); i++) {
-		if (!Suid[i].excl)
-		    continue;
-		if (Suid[i].uid == (uid_t)uid)
-		    return(1);
-		j++;
-	    }
-	}
-/*
- * If the excluding of process listing by PGID has been specified, see if this
- * PGID is excluded.
- */
-	if (Npgidx) {
-	    for (i = j = 0; (i < Npgid) && (j < Npgidx); i++) {
-		if (!Spgid[i].x)
-		    continue;
-		if (Spgid[i].i == pgid)
-		    return(1);
-		j++;
-	    }
-	}
-/*
- * If the excluding of process listing by PID has been specified, see if this
- * PID is excluded.
- */
-	if (Npidx) {
-	    for (i = j = 0; (i < Npid) && (j < Npidx); i++) {
-		if (!Spid[i].x)
-		    continue;
-		if (Spid[i].i == pid)
-		    return(1);
-		j++;
-	    }
-	}
-/*
- * If the listing of all processes is selected, then this one is not excluded.
- *
- * However, if HASSECURITY and HASNOSOCKSECURITY are both specified, exclude
- * network selections from the file flags, so that the tests in is_file_sel()
- * work as expected.
- */
-	if (AllProc) {
-	    *pss = PS_PRI;
-
-#if	defined(HASSECURITY) && defined(HASNOSOCKSECURITY)
-	    *sf = SelAll & ~(SELNA | SELNET);
-#else	/* !defined(HASSECURITY) || !defined(HASNOSOCKSECURITY) */
-	    *sf = SelAll;
-#endif	/* defined(HASSECURITY) && defined(HASNOSOCKSECURITY) */
-
-	    return(0);
-	}
-/*
- * If the listing of processes has been specified by process group ID, see
- * if this one is included or excluded.
- */
-	if (Npgidi && (Selflags & SELPGID)) {
-	    for (i = j = 0; (i < Npgid) && (j < Npgidi); i++) {
-		if (Spgid[i].x)
-		    continue;
-		if (Spgid[i].i == pgid) {
-		    Spgid[i].f = 1;
-		    *pss = PS_PRI;
-		    *sf = SELPGID;
-		    if (Selflags == SELPGID)
-			return(0);
-		    break;
-		}
-		j++;
-	    }
-	    if ((Selflags == SELPGID) && !*sf)
-		return(1);
-	}
-/*
- * If the listing of processes has been specified by PID, see if this one is
- * included or excluded.
- */
-	if (Npidi && (Selflags & SELPID)) {
-	    for (i = j = 0; (i < Npid) && (j < Npidi); i++) {
-		if (Spid[i].x)
-		    continue;
-		if (Spid[i].i == pid) {
-		    Spid[i].f = 1;
-		    *pss = PS_PRI;
-		    *sf |= SELPID;
-		    if (Selflags == SELPID)
-			return(0);
-		    break;
-		}
-		j++;
-	    }
-	    if ((Selflags == SELPID) && !*sf)
-		return(1);
-	}
-/*
- * If the listing of processes has been specified by UID, see if the owner of
- * this process has been included.
- */
-	if (Nuidincl && (Selflags & SELUID)) {
-	    for (i = j = 0; (i < Nuid) && (j < Nuidincl); i++) {
-		if (Suid[i].excl)
-		    continue;
-		if (Suid[i].uid == (uid_t)uid) {
-		    Suid[i].f = 1;
-		    *pss = PS_PRI;
-		    *sf |= SELUID;
-		    if (Selflags == SELUID)
-			return(0);
-		    break;
-		}
-		j++;
-	    }
-	    if (Selflags == SELUID && (*sf & SELUID) == 0)
-		return(1);
-	}
-
-#if	defined(HASTASKS)
-	if ((Selflags & SELTASK) && tid) {
-
-	/*
-	 * This is a task and tasks are selected.
-	 */
-	    *pss = PS_PRI;
-	    *sf |= SELTASK;
-	    if ((Selflags == SELTASK)
-	    ||  (Fand && ((*sf & Selflags) == Selflags)))
-		return(0);
-	}
-#endif	/* defined(HASTASKS) */
-
-/*
- * When neither the process group ID, nor the PID, nor the task, nor the UID
- * is selected:
- *
- *	If list option ANDing of process group IDs, PIDs, UIDs or tasks is
- *	specified, the process is excluded;
- *
- *	Otherwise, it's not excluded by the tests of this function.
- */
-	if ( ! *sf)
-	    return((Fand && (Selflags & (SELPGID|SELPID|SELUID|SELTASK)))
-		   ? 1 : 0);
-/*
- * When the process group ID, PID, task or UID is selected and the process
- * group ID, PID, task or UID list option has been specified:
- *
- *	If list option ANDing has been specified, and the correct
- *	combination of selections are in place, reply that the process is no
- *	excluded;
- * or
- *	If list option ANDing has not been specified, reply that the
- *	process is not excluded by the tests of this function.
- */
-	if (Selflags & (SELPGID|SELPID|SELUID|SELTASK)) {
-	    if (Fand)
-		return(((Selflags & (SELPGID|SELPID|SELUID|SELTASK)) != *sf)
-			? 1 : 0);
-	    return(0);
-	}
-/*
- * Finally, when neither the process group ID, nor the PID, nor the UID, nor
- * the task is selected, and no applicable list option has been specified:
- *
- *	If list option ANDing has been specified, this process is
- *	excluded;
- *
- *	Otherwise, it isn't excluded by the tests of this function.
- */
-	return(Fand ? 1 : 0);
-}
-
-
-/*
- * link_lfile() - link local file structures
- */
-
-void
-link_lfile()
-{
-	if (Lf->sf & SELEXCLF)
-	    return;
-
-#if	defined(HASEPTOPTS)
-/*
- * If endpoint info has been requested, clear the SELPINFO flag from the local
- * pipe 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 EPT_PIPE flag.
- */
-	if (FeptE) {
-	    if (Lf->sf & SELPINFO) {
-		Lp->ept |= EPT_PIPE;
-		Lf->sf &= ~SELPINFO;
-	    }
-
-/*
- * Process posix mq endpoint files the same way by clearing the
- * SELPSXMQINFO flag and setting the EPT_PSXMQ flag, letting a later call to
- * process_psxmqinfo() set selection flags.
- */
-	    if (Lf->sf & SELPSXMQINFO) {
-		Lp->ept |= EPT_PSXMQ;
-		Lf->sf &= ~SELPSXMQINFO;
-	    }
-
-# if	defined(HASUXSOCKEPT)
-/*
- * Process UNIX socket endpoint files the same way by clearing the SELUXINFO
- * flag and setting the EPT_UXS flag, letting a later call to process_uxsinfo()
- * set selection flags.
- */
-	    if (Lf->sf & SELUXSINFO) {
-		Lp->ept |= EPT_UXS;
-		Lf->sf &= ~SELUXSINFO;
-	    }
-# endif	/* defined(HASUXSOCKEPT) */
-
-# if	defined(HASPTYEPT)
-/*
- * Process pseudoterminal endpoint files the same way by clearing the SELPTYINFO
- * flag and setting the EPT_PTY flag, letting a later call to process_ptyinfo()
- * set selection flags.
- */
-	    if (Lf->sf & SELPTYINFO) {
-		Lp->ept |= EPT_PTY;
-		Lf->sf &= ~SELPTYINFO;
-	    }
-# endif	/* defined(HASPTYEPT) */
-
-/*
- * Process locally used INET socket endpoint files the same way by clearing the
- * SENETSINFO flag and setting the EPT_NETS flag, letting a later call to
- * process_netsinfo() set selection flags.
- */
-	    if (Lf->sf & SELNETSINFO) {
-		Lp->ept |= EPT_NETS;
-		Lf->sf &= ~SELNETSINFO;
-	    }
-
-#if	defined(HASIPv6)
-/*
- * Process locally used INET6 socket endpoint files the same way by clearing the
- * SENETS6INFO flag and setting the EPT_NETS6 flag, letting a later call to
- * process_nets6info() set selection flags.
- */
-	    if (Lf->sf & SELNETS6INFO) {
-		Lp->ept |= EPT_NETS6;
-		Lf->sf &= ~SELNETS6INFO;
-	    }
-# endif	/* defined(HASIPv6) */
-/*
- * Process eventfd endpoint files the same way by clearing the SELEVTFDINFO
- * flag and setting the EPT_EVTFD flag, letting a later call to process_evtfdinfo()
- * set selection flags.
- */
-	    if (Lf->sf & SELEVTFDINFO) {
-		Lp->ept |= EPT_EVTFD;
-		Lf->sf &= ~SELEVTFDINFO;
-	    }
-	}
-#endif	/* defined(HASEPTOPTS) */
-
-	if (Lf->sf)
-	    Lp->pss |= PS_SEC;
-	if (Plf)
-	    Plf->next = Lf;
-	else
-	    Lp->file = Lf;
-	Plf = Lf;
-	if (Fnet && (Lf->sf & SELNET))
-	    Fnet = 2;
-	if (Fnfs && (Lf->sf & SELNFS))
-	    Fnfs = 2;
-	if (Ftask && (Lf->sf & SELTASK))
-	    Ftask = 2;
-	Lf = (struct lfile *)NULL;
-}
-
-
-#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
-					 */
-{
-	pxinfo_t *pp;			/* previous pipe info */
-
-	if (!FeptE)
-	    return;
-	for (Lf = Lp->file; Lf; Lf = Lf->next) {
-	    if ((Lf->ntype != N_FIFO) || (Lf->inp_ty != 1))
-		continue;
-	    pp = (pxinfo_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_pepti(Lp->pid, Lf, pp))) {
-
-			/*
-			 * This pipe endpoint is linked to the selected pipe
-			 * file.  Add its PID and FD to the name column
-			 * addition.
-			 */
-			    prt_pinfo(pp, (FeptE == 2));
-			    pp = pp->next;
-			}
-		    } while (pp);
-		}
-		break;
-	    case 1:
-		if (!is_file_sel(Lp, Lf) && (Lf->chend & CHEND_PIPE)) {
-
-		/*
-		 * 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_pepti(Lp->pid, Lf, pp))) {
-			    prt_pinfo(pp, 0);
-			    pp = pp->next;
-			}
-		    } while (pp);
-		}
-		break;
-	    }
-	}
-}
-
-/*
- * prt_pinfo() -- print pipe information
- */
-
-static void
-prt_pinfo(pp, ps)
-	pxinfo_t *pp;			/* peer info */
-	int ps;				/* processing status:
-					 *    0 == process immediately
-					 *    1 == process later */
-{
-	struct lproc *ep;		/* pipe endpoint process */
-	struct lfile *ef;		/* pipe endpoint file */
-	int i;				/* temporary index */
-	char nma[1024];			/* name addition buffer */
-
-	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 (ps) {
-
-	/*
-	* Endpoint files have been selected, so mark this
-	* one for selection later. Set the type to PIPE.
-	*/
-	    ef->chend = CHEND_PIPE;
-	    ep->ept |= EPT_PIPE_END;
-	}
-}
-
-
-/*
- * process_psxmqinfo() -- posix mq info, adding it to selected files and
- *		          selecting posix mq end files (if requested)
- */
-
-void
-process_psxmqinfo(f)
-	int f;				/* function:
-					 *     0 == process selected posix mq
-					 *     1 == process end point
-					 */
-{
-	pxinfo_t *pp;			/* previous posix mq info */
-
-	if (!FeptE)
-	    return;
-	for (Lf = Lp->file; Lf; Lf = Lf->next) {
-	    if (Lf->dev != MqueueDev)
-		continue;
-	    pp = (pxinfo_t *)NULL;
-	    switch(f) {
-	    case 0:
-
-	    /*
-	     * Process already selected posix mq file.
-	     */
-		if (is_file_sel(Lp, Lf)) {
-
-		/*
-		 * This file has been selected by some criterion other than
-		 * its being a posix mq.  Look up the posix mq's endpoints.
-		 */
-		    do {
-			if ((pp = find_psxmqinfo(Lp->pid, Lf, pp))) {
-
-			/*
-			 * This posix mq endpoint is linked to the selected posix mq
-			 * file.  Add its PID and FD to the name column
-			 * addition.
-			 */
-			    prt_psxmqinfo(pp, (FeptE == 2));
-			    pp = pp->next;
-			}
-		    } while (pp);
-		}
-		break;
-	    case 1:
-		if (!is_file_sel(Lp, Lf) && (Lf->chend & CHEND_PSXMQ)) {
-
-		/*
-		 * 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_psxmqinfo(Lp->pid, Lf, pp))) {
-			    prt_psxmqinfo(pp, 0);
-			    pp = pp->next;
-			}
-		    } while (pp);
-		}
-		break;
-	    }
-	}
-}
-
-
-/*
- * prt_psxmqinfo() -- print posix mq information
- */
-
-static void
-prt_psxmqinfo(pp, ps)
-	pxinfo_t *pp;			/* peer info */
-	int ps;				/* processing status:
-					 *    0 == process immediately
-					 *    1 == process later */
-{
-	struct lproc *ep;		/* posix mq endpoint process */
-	struct lfile *ef;		/* posix mq endpoint file */
-	int i;				/* temporary index */
-	char nma[1024];			/* name addition buffer */
-
-	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 (ps) {
-
-	/*
-	* Endpoint files have been selected, so mark this
-	* one for selection later. Set the type to posix mq.
-	*/
-	    ef->chend = CHEND_PSXMQ;
-	    ep->ept |= EPT_PSXMQ_END;
-	}
-}
-
-
-/*
- * process_evtfdinfo() -- process eventfd info, adding it to selected files and
- *		          selecting envetfd end files (if requested)
- */
-
-void
-process_evtfdinfo(f)
-	int f;				/* function:
-					 *     0 == process selected eventfd
-					 *     1 == process end point
-					 */
-{
-	pxinfo_t *pp;			/* previous eventfd info */
-
-	if (!FeptE)
-	    return;
-	for (Lf = Lp->file; Lf; Lf = Lf->next) {
-	    if ((Lf->ntype != N_ANON_INODE) || (Lf->eventfd_id == -1))
-		continue;
-	    pp = (pxinfo_t *)NULL;
-	    switch(f) {
-	    case 0:
-
-	    /*
-	     * Process already selected eventfd_id file.
-	     */
-		if (is_file_sel(Lp, Lf)) {
-
-		/*
-		 * This file has been selected by some criterion other than
-		 * its being a eventfd.  Look up the eventfd's endpoints.
-		 */
-		    do {
-			if ((pp = find_evtfdinfo(Lp->pid, Lf, pp))) {
-
-			/*
-			 * This eventfd endpoint is linked to the selected eventfd
-			 * file.  Add its PID and FD to the name column
-			 * addition.
-			 */
-			    prt_evtfdinfo(pp, (FeptE == 2));
-			    pp = pp->next;
-			}
-		    } while (pp);
-		}
-		break;
-	    case 1:
-		if (!is_file_sel(Lp, Lf) && (Lf->chend & CHEND_EVTFD)) {
-
-		/*
-		 * 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_evtfdinfo(Lp->pid, Lf, pp))) {
-			    prt_evtfdinfo(pp, 0);
-			    pp = pp->next;
-			}
-		    } while (pp);
-		}
-		break;
-	    }
-	}
-}
-
-
-/*
- * prt_evtfdinfo() -- print eventfd information
- */
-
-static void
-prt_evtfdinfo(pp, ps)
-	pxinfo_t *pp;			/* peer info */
-	int ps;				/* processing status:
-					 *    0 == process immediately
-					 *    1 == process later */
-{
-	struct lproc *ep;		/* eventfd endpoint process */
-	struct lfile *ef;		/* eventfd endpoint file */
-	int i;				/* temporary index */
-	char nma[1024];			/* name addition buffer */
-
-	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 (ps) {
-
-	/*
-	* Endpoint files have been selected, so mark this
-	* one for selection later. Set the type to PIPE.
-	*/
-	    ef->chend = CHEND_EVTFD;
-	    ep->ept |= EPT_EVTFD_END;
-	}
-}
-#endif	/* defined(HASEPTOPTS) */
-
-
-#if	defined(HASFSTRUCT)
-/*
- * print_fflags() - print interpreted f_flag[s]
- */
-
-char *
-print_fflags(ffg, pof)
-	long ffg;		/* file structure's flags value */
-	long pof;		/* process open files flags value */
-{
-	int al, ct, fx;
-	static int bl = 0;
-	static char *bp = (char *)NULL;
-	char *sep;
-	int sepl;
-	struct pff_tab *tp;
-	long wf;
-	char xbuf[64];
-/*
- * Reduce the supplied flags according to the definitions in Pff_tab[] and
- * Pof_tab[].
- */
-	for (ct = fx = 0; fx < 2; fx++) {
-	    if (fx == 0) {
-		sep = "";
-		sepl = 0;
-		tp = Pff_tab;
-		wf = ffg;
-	    } else {
-		sep = ";";
-		sepl = 1;
-		tp = Pof_tab;
-		wf = pof;
-	    }
-	    for (; wf && !FsvFlagX; ct += al ) {
-		while (tp->nm) {
-		    if (wf & tp->val)
-			break;
-		    tp++;
-		}
-		if (!tp->nm)
-		    break;
-		al = (int)strlen(tp->nm) + sepl;
-		bp = alloc_fflbuf(&bp, &bl, al + ct);
-		(void) snpf(bp + ct, al + 1, "%s%s", sep, tp->nm);
-		sep = ",";
-		sepl = 1;
-		wf &= ~(tp->val);
-	    }
-	/*
-	 * If flag bits remain, print them in hex.  If hex output was
-	 * specified with +fG, print all flag values, including zero,
-	 * in hex.
-	 */
-	    if (wf || FsvFlagX) {
-		(void) snpf(xbuf, sizeof(xbuf), "0x%lx", wf);
-		al = (int)strlen(xbuf) + sepl;
-		bp = alloc_fflbuf(&bp, &bl, al + ct);
-		(void) snpf(bp + ct, al + 1, "%s%s", sep, xbuf);
-		ct += al;
-	    }
-	}
-/*
- * Make sure there is at least a NUL terminated reply.
- */
-	if (!bp) {
-	    bp = alloc_fflbuf(&bp, &bl, 0);
-	    *bp = '\0';
-	}
-	return(bp);
-}
-#endif	/* defined(HASFSTRUCT) */
-
-
-/*
- * print_proc() - print process
- */
-
-int
-print_proc()
-{
-	char buf[128], *cp;
-	int lc, len, st, ty;
-	int rv = 0;
-	unsigned long ul;
-/*
- * If nothing in the process has been selected, skip it.
- */
-	if (!Lp->pss)
-	    return(0);
-	if (Fterse) {
-	    if (Lp->pid == LastPid)		/* eliminate duplicates */
-		return(0);
-	    LastPid = Lp->pid;
-	/*
-	 * The mode is terse and something in the process appears to have
-	 * been selected.  Make sure of that by looking for a selected file,
-	 * so that the HASSECURITY and HASNOSOCKSECURITY option combination
-	 * won't produce a false positive result.
-	 */
-	    for (Lf = Lp->file; Lf; Lf = Lf->next) {
-		if (is_file_sel(Lp, Lf)) {
-		    (void) printf("%d\n", Lp->pid);
-		    return(1);
-		}
-	    }
-	    return(0);
-	}
-/*
- * If fields have been selected, output the process-only ones, provided
- * that some file has also been selected.
- */
-	if (Ffield) {
-	    for (Lf = Lp->file; Lf; Lf = Lf->next) {
-		if (is_file_sel(Lp, Lf))
-		    break;
-	    }
-	    if (!Lf)
-		return(rv);
-	    rv = 1;
-	    (void) printf("%c%d%c", LSOF_FID_PID, Lp->pid, Terminator);
-
-#if	defined(HASTASKS)
-	    if (FieldSel[LSOF_FIX_TID].st && Lp->tid)
-		(void) printf("%c%d%c", LSOF_FID_TID, Lp->tid, Terminator);
-	    if (FieldSel[LSOF_FIX_TCMD].st && Lp->tcmd)
-		(void) printf("%c%s%c", LSOF_FID_TCMD, Lp->tcmd, Terminator);
-#endif	/* defined(HASTASKS) */
-
-#if	defined(HASZONES)
-	    if (FieldSel[LSOF_FIX_ZONE].st && Fzone && Lp->zn)
-		(void) printf("%c%s%c", LSOF_FID_ZONE, Lp->zn, Terminator);
-#endif	/* defined(HASZONES) */
-
-#if	defined(HASSELINUX)
-	    if (FieldSel[LSOF_FIX_CNTX].st && Fcntx && Lp->cntx && CntxStatus)
-		(void) printf("%c%s%c", LSOF_FID_CNTX, Lp->cntx, Terminator);
-#endif	/* defined(HASSELINUX) */
-
-	    if (FieldSel[LSOF_FIX_PGID].st && Fpgid)
-		(void) printf("%c%d%c", LSOF_FID_PGID, Lp->pgid, Terminator);
-
-#if	defined(HASPPID)
-	    if (FieldSel[LSOF_FIX_PPID].st && Fppid)
-		(void) printf("%c%d%c", LSOF_FID_PPID, Lp->ppid, Terminator);
-#endif	/* defined(HASPPID) */
-
-	    if (FieldSel[LSOF_FIX_CMD].st) {
-		putchar(LSOF_FID_CMD);
-		safestrprt(Lp->cmd ? Lp->cmd : "(unknown)", stdout, 0);
-		putchar(Terminator);
-	    }
-	    if (FieldSel[LSOF_FIX_UID].st)
-		(void) printf("%c%d%c", LSOF_FID_UID, (int)Lp->uid, Terminator);
-	    if (FieldSel[LSOF_FIX_LOGIN].st) {
-		cp = printuid((UID_ARG)Lp->uid, &ty);
-		if (ty == 0)
-		    (void) printf("%c%s%c", LSOF_FID_LOGIN, cp, Terminator);
-	    }
-	    if (Terminator == '\0')
-		putchar('\n');
-	}
-/*
- * Print files.
- */
-	for (Lf = Lp->file; Lf; Lf = Lf->next) {
-	    if (!is_file_sel(Lp, Lf))
-		continue;
-	    rv = 1;
-	/*
-	 * If no field output selected, print dialect-specific formatted
-	 * output.
-	 */
-	    if (!Ffield) {
-		print_file();
-		continue;
-	    }
-	    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++)
-		    ;
-		(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);
-		lc++;
-	    }
-	    if (FieldSel[LSOF_FIX_LOCK].st) {
-		(void) printf("%c%c%c", LSOF_FID_LOCK, Lf->lock, Terminator);
-		lc++;
-	    }
-	    if (FieldSel[LSOF_FIX_TYPE].st) {
-		for (cp = Lf->type; *cp == ' '; cp++)
-		    ;
-		if (*cp) {
-		    (void) printf("%c%s%c", LSOF_FID_TYPE, cp, Terminator);
-		    lc++;
-		}
-	    }
-
-#if	defined(HASFSTRUCT)
-	    if (FieldSel[LSOF_FIX_FA].st && (Fsv & FSV_FA)
-	    &&  (Lf->fsv & FSV_FA)) {
-		(void) printf("%c%s%c", LSOF_FID_FA,
-		    print_kptr(Lf->fsa, (char *)NULL, 0), Terminator);
-		lc++;
-	    }
-	    if (FieldSel[LSOF_FIX_CT].st && (Fsv & FSV_CT)
-	    &&  (Lf->fsv & FSV_CT)) {
-		(void) printf("%c%ld%c", LSOF_FID_CT, Lf->fct, Terminator);
-		lc++;
-	    }
-	    if (FieldSel[LSOF_FIX_FG].st && (Fsv & FSV_FG)
-	    &&  (Lf->fsv & FSV_FG) && (FsvFlagX || Lf->ffg || Lf->pof)) {
-		(void) printf("%c%s%c", LSOF_FID_FG,
-		    print_fflags(Lf->ffg, Lf->pof), Terminator);
-		lc++;
-	    }
-	    if (FieldSel[LSOF_FIX_NI].st && (Fsv & FSV_NI)
-	    &&  (Lf->fsv & FSV_NI)) {
-		(void) printf("%c%s%c", LSOF_FID_NI,
-		    print_kptr(Lf->fna, (char *)NULL, 0), Terminator);
-		lc++;
-	    }
-#endif	/* defined(HASFSTRUCT) */
-
-	    if (FieldSel[LSOF_FIX_DEVCH].st && Lf->dev_ch && Lf->dev_ch[0]) {
-		for (cp = Lf->dev_ch; *cp == ' '; cp++)
-		    ;
-		if (*cp) {
-		    (void) printf("%c%s%c", LSOF_FID_DEVCH, cp, Terminator);
-		    lc++;
-		}
-	    }
-	    if (FieldSel[LSOF_FIX_DEVN].st && Lf->dev_def) {
-		if (sizeof(unsigned long) > sizeof(dev_t))
-		    ul = (unsigned long)((unsigned int)Lf->dev);
-		else
-		    ul = (unsigned long)Lf->dev;
-		(void) printf("%c0x%lx%c", LSOF_FID_DEVN, ul, Terminator);
-		lc++;
-	    }
-	    if (FieldSel[LSOF_FIX_RDEV].st && Lf->rdev_def) {
-		if (sizeof(unsigned long) > sizeof(dev_t))
-		    ul = (unsigned long)((unsigned int)Lf->rdev);
-		else
-		    ul = (unsigned long)Lf->rdev;
-		(void) printf("%c0x%lx%c", LSOF_FID_RDEV, ul, Terminator);
-		lc++;
-	    }
-	    if (FieldSel[LSOF_FIX_SIZE].st && Lf->sz_def) {
-		putchar(LSOF_FID_SIZE);
-
-#if	defined(HASPRINTSZ)
-		cp = HASPRINTSZ(Lf);
-#else	/* !defined(HASPRINTSZ) */
-		(void) snpf(buf, sizeof(buf), SzOffFmt_d, Lf->sz);
-		cp = buf;
-#endif	/* defined(HASPRINTSZ) */
-
-		(void) printf("%s", cp);
-		putchar(Terminator);
-		lc++;
-	    }
-	    if (FieldSel[LSOF_FIX_OFFSET].st && Lf->off_def) {
-		putchar(LSOF_FID_OFFSET);
-
-#if	defined(HASPRINTOFF)
-		cp = HASPRINTOFF(Lf, 0);
-#else	/* !defined(HASPRINTOFF) */
-		(void) snpf(buf, sizeof(buf), SzOffFmt_0t, Lf->off);
-		cp = buf;
-#endif	/* defined(HASPRINTOFF) */
-
-		len = strlen(cp);
-		if (OffDecDig && len > (OffDecDig + 2)) {
-
-#if	defined(HASPRINTOFF)
-		    cp = HASPRINTOFF(Lf, 1);
-#else	/* !defined(HASPRINTOFF) */
-		    (void) snpf(buf, sizeof(buf), SzOffFmt_x, Lf->off);
-		    cp = buf;
-#endif	/* defined(HASPRINTOFF) */
-
-		}
-		(void) printf("%s", cp);
-		putchar(Terminator);
-		lc++;
-	    }
-	    if (FieldSel[LSOF_FIX_INODE].st && Lf->inp_ty == 1) {
-		putchar(LSOF_FID_INODE);
-		(void) printf(InodeFmt_d, Lf->inode);
-		putchar(Terminator);
-		lc++;
-	    }
-	    if (FieldSel[LSOF_FIX_NLINK].st && Lf->nlink_def) {
-		(void) printf("%c%ld%c", LSOF_FID_NLINK, Lf->nlink, Terminator);
-		lc++;
-	    }
-	    if (FieldSel[LSOF_FIX_PROTO].st && Lf->inp_ty == 2) {
-		for (cp = Lf->iproto; *cp == ' '; cp++)
-		    ;
-		if (*cp) {
-		    (void) printf("%c%s%c", LSOF_FID_PROTO, cp, Terminator);
-		    lc++;
-		}
-	    }
-	    if (FieldSel[LSOF_FIX_STREAM].st && Lf->nm && Lf->is_stream) {
-		if (strncmp(Lf->nm, "STR:", 4) == 0
-		||  strcmp(Lf->iproto, "STR") == 0) {
-		    putchar(LSOF_FID_STREAM);
-		    printname(0);
-		    putchar(Terminator);
-		    lc++;
-		    st++;
-		}
-	    }
-	    if (st == 0 && FieldSel[LSOF_FIX_NAME].st) {
-		putchar(LSOF_FID_NAME);
-		printname(0);
-		putchar(Terminator);
-		lc++;
-	    }
-	    if (Lf->lts.type >= 0 && FieldSel[LSOF_FIX_TCPTPI].st) {
-		print_tcptpi(0);
-		lc++;
-	    }
-	    if (Terminator == '\0' && lc)
-		putchar('\n');
-	}
-	return(rv);
-}
-
-
-#if	defined(HASPTYEPT)
-/*
- * process_ptyinfo() -- process pseudoterminal info, adding it to selected files and
- *		      selecting pseudoterminal end files (if requested)
- */
-
-void
-process_ptyinfo(f)
-	int f;				/* function:
-					 *  0 == process selected pseudoterminal
-					 *  1 == process end point */
-{
-	pxinfo_t *pp;			/* previous pseudoterminal info */
-	int mos;			/* master or slave indicator
-					 *     0 == slave; 1 == master */
-	int pc;				/* print count */
-
-	if (!FeptE)
-	    return;
-	for (Lf = Lp->file; Lf; Lf = Lf->next) {
-	    if (Lf->rdev_def && is_pty_ptmx(Lf->rdev))
-		mos = 1;
-	    else if (Lf->rdev_def && is_pty_slave(GET_MAJ_DEV(Lf->rdev)))
-		mos = 0;
-	    else
-		continue;
-
-	    pp = (pxinfo_t *)NULL;
-	    switch(f) {
-	    case 0:
-
-	    /*
-	     * Process already selected pseudoterminal file.
-	     */
-		if (is_file_sel(Lp, Lf)) {
-
-		/*
-		 * This file has been selected by some criterion other than
-		 * its being a pseudoterminal.  Look up the pseudoterminal's
-		 * endpoints.
-		 */
-		    pc = 1;
-		    do {
-			if ((pp = find_ptyepti(Lp->pid, Lf, !mos, pp))) {
-
-			/*
-			 * This pseudoterminal endpoint is linked to the
-			 * selected pseudoterminal file.  Add its PID, FD and
-			 * access mode to the name column addition.
-			 */
-			    prt_ptyinfo(pp, (mos && pc), (FeptE == 2));
-			    pp = pp->next;
-			    pc = 0;
-			}
-		    } while (pp);
-		}
-		break;
-	    case 1:
-		if (!is_file_sel(Lp, Lf) && (Lf->chend & CHEND_PTY)) {
-
-		/*
-		 * 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;
-		    pc = 1;
-		    do {
-			if ((pp = find_ptyepti(Lp->pid, Lf, !mos, pp))) {
-			    prt_ptyinfo(pp, (mos && pc), 0);
-			    pp = pp->next;
-			    pc = 0;
-			}
-		    } while (pp);
-		}
-		break;
-	    }
-	}
-}
-
-
-/*
- * prt_ptyinfo() -- print pseudoterminal information
- */
-
-static void
-prt_ptyinfo(pp, prt_edev, ps)
-	pxinfo_t *pp;			/* peer info */
-	int prt_edev;			/* print the end point device file */
-	int ps;				/* processing status:
-					 *    0 == process immediately
-					 *    1 == process later */
-{
-	struct lproc *ep;		/* pseudoterminal endpoint process */
-	struct lfile *ef;		/* pseudoterminal endpoint file */
-	int i;				/* temporary index */
-	char nma[1024];			/* name addition buffer */
-
-	ep = &Lproc[pp->lpx];
-	ef = pp->lf;
-	for (i = 0; i < (FDLEN - 1); i++) {
-	    if (ef->fd[i] != ' ')
-		break;
-	}
-	if (prt_edev) {
-	    (void) snpf(nma, sizeof(nma) - 1, "->/dev/pts/%d %d,%.*s,%s%c",
-			Lf->tty_index,
-			ep->pid, CmdLim, ep->cmd, &ef->fd[i],
-			ef->access);
-	} else {
-	    (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 (ps) {
-
-	/*
-	 * Endpoint files have been selected, so mark this
-	 * one for selection later. Set the type to PTY.
-	 */
-	    ef->chend = CHEND_PTY;
-	    ep->ept |= EPT_PTY_END;
-	}
-}
-#endif	/* defined(HASPTYEPT) */
diff --git a/proto.h b/proto.h
deleted file mode 100644
index 5d85236..0000000
--- a/proto.h
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- * proto.h - common function prototypes 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: proto.h,v 1.39 2018/02/14 14:20:14 abe Exp $
- */
-
-
-#if	!defined(PROTO_H)
-#define	PROTO_H	1
-
-
-/*
- * 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 */
-
-
-_PROTOTYPE(extern void add_nma,(char *cp, int len));
-_PROTOTYPE(extern void alloc_lfile,(char *nm, int num));
-_PROTOTYPE(extern void alloc_lproc,(int pid, int pgid, int ppid, UID_ARG uid, char *cmd, int pss, int sf));
-_PROTOTYPE(extern void build_IPstates,(void));
-_PROTOTYPE(extern void childx,(void));
-_PROTOTYPE(extern int ck_fd_status,(char *nm, int num));
-_PROTOTYPE(extern int ck_file_arg,(int i, int ac, char *av[], int fv, int rs, struct stat *sbp, int accept_deleted_file));
-_PROTOTYPE(extern void ckkv,(char *d, char *er, char *ev, char *ea));
-_PROTOTYPE(extern void clr_devtab,(void));
-_PROTOTYPE(extern int compdev,(COMP_P *a1, COMP_P *a2));
-_PROTOTYPE(extern int comppid,(COMP_P *a1, COMP_P *a2));
-
-# if	defined(WILLDROPGID)
-_PROTOTYPE(extern void dropgid,(void));
-# endif	/* defined(WILLDROPGID) */
-
-_PROTOTYPE(extern char *endnm,(size_t *sz));
-_PROTOTYPE(extern int enter_cmd_rx,(char *x));
-_PROTOTYPE(extern void enter_dev_ch,(char *m));
-_PROTOTYPE(extern int enter_dir,(char *d, int descend));
-
-# if	defined(HASEOPT)
-_PROTOTYPE(extern int enter_efsys,(char *e, int rdlnk));
-# endif	/* defined(HASEOPT) */
-
-_PROTOTYPE(extern int enter_fd,(char *f));
-_PROTOTYPE(extern int enter_network_address,(char *na));
-_PROTOTYPE(extern int enter_id,(enum IDType ty, char *p));
-_PROTOTYPE(extern void enter_IPstate,(char *ty, char *nm, int nr));
-_PROTOTYPE(extern void enter_nm,(char *m));
-
-# if	defined(HASTCPUDPSTATE)
-_PROTOTYPE(extern int enter_state_spec,(char *ss));
-# endif	/* defined(HASTCPUDPSTATE) */
-
-_PROTOTYPE(extern int enter_str_lst,(char *opt, char *s, struct str_lst **lp,
-				     int *incl, int *excl));
-_PROTOTYPE(extern int enter_uid,(char *us));
-_PROTOTYPE(extern void ent_inaddr,(unsigned char *la, int lp, unsigned char *fa, int fp, int af));
-_PROTOTYPE(extern int examine_lproc,(void));
-_PROTOTYPE(extern void Exit,(enum ExitStatus xv)) exiting;
-_PROTOTYPE(extern void Error,()) exiting;
-_PROTOTYPE(extern void find_ch_ino,(void));
-
-# if	defined(HASEPTOPTS)
-_PROTOTYPE(extern void clear_pinfo,(void));
-_PROTOTYPE(extern pxinfo_t *find_pepti,(int pid, struct lfile *lf, pxinfo_t *pp));
-_PROTOTYPE(extern void process_pinfo,(int f));
-_PROTOTYPE(extern void clear_psxmqinfo,(void));
-_PROTOTYPE(extern pxinfo_t *find_psxmqinfo,(int pid, struct lfile *lf, pxinfo_t *pp));
-_PROTOTYPE(extern void process_psxmqinfo,(int f));
-#  if	defined(HASUXSOCKEPT)
-_PROTOTYPE(extern void clear_uxsinfo,(void));
-_PROTOTYPE(extern struct uxsin *find_uxsepti,(struct lfile *lf));
-_PROTOTYPE(extern void process_uxsinfo,(int f));
-#  endif	/* defined(HASUXSOCKEPT) */
-#  if	defined(HASPTYEPT)
-_PROTOTYPE(extern void clear_ptyinfo,(void));
-_PROTOTYPE(extern void enter_ptmxi,(int mn));
-_PROTOTYPE(extern pxinfo_t *find_ptyepti,(int pid, struct lfile *lf,int m,pxinfo_t *pp));
-_PROTOTYPE(extern int is_pty_slave,(int sm));
-_PROTOTYPE(extern int is_pty_ptmx,(dev_t dev));
-_PROTOTYPE(extern void process_ptyinfo,(int f));
-_PROTOTYPE(extern void clear_evtfdinfo,(void));
-_PROTOTYPE(extern void enter_evtfdinfo,(int id));
-_PROTOTYPE(extern pxinfo_t *find_evtfdinfo,(int pid, struct lfile *lf,pxinfo_t *pp));
-_PROTOTYPE(extern void process_evtfdinfo,(int f));
-#  endif	/* defined(HASPTYEPT) */
-_PROTOTYPE(extern void clear_netsinfo,(void));
-_PROTOTYPE(extern void process_netsinfo,(int f));
-#if	defined(HASIPv6)
-_PROTOTYPE(extern void clear_nets6info,(void));
-_PROTOTYPE(extern void process_nets6info,(int f));
-# endif	/* defined(HASIPv6) */
-# 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));
-
-# if	!defined(GET_MAX_FD)
-/*
- * This is not strictly a prototype, but GET_MAX_FD is the name of the
- * function that, in lieu of getdtablesize(), returns the maximum file
- * descriptor plus one (or file descriptor count).  GET_MAX_FD may be
- * defined in the dialect's machine.h.  If it is not, the following
- * selects getdtablesize().
- */
-
-#define	GET_MAX_FD	getdtablesize
-# endif	/* !defined(GET_MAX_FD) */
-
-_PROTOTYPE(extern int hashbyname,(char *nm, int mod));
-_PROTOTYPE(extern void hashSfile,(void));
-_PROTOTYPE(extern void initialize,(void));
-_PROTOTYPE(extern int is_cmd_excl,(char *cmd, short *pss, short *sf));
-_PROTOTYPE(extern int is_file_sel,(struct lproc *lp, struct lfile *lf));
-_PROTOTYPE(extern int is_nw_addr,(unsigned char *ia, int p, int af));
-
-#if	defined(HASTASKS)
-_PROTOTYPE(extern int is_proc_excl,(int pid, int pgid, UID_ARG uid, short *pss, short *sf, int tid));
-#else	/* !defined(HASTASKS) */
-_PROTOTYPE(extern int is_proc_excl,(int pid, int pgid, UID_ARG uid, short *pss, short *sf));
-#endif	/* defined(HASTASKS) */
-
-_PROTOTYPE(extern int is_readable,(char *path, int msg));
-_PROTOTYPE(extern int kread,(KA_T addr, char *buf, READLEN_T len));
-_PROTOTYPE(extern void link_lfile,(void));
-_PROTOTYPE(extern struct l_dev *lkupdev,(dev_t *dev,dev_t *rdev,int i,int r));
-_PROTOTYPE(extern int main,(int argc, char *argv[]));
-_PROTOTYPE(extern int lstatsafely,(char *path, struct stat *buf));
-_PROTOTYPE(extern char *mkstrcpy,(char *src, MALLOC_S *rlp));
-_PROTOTYPE(extern char *mkstrcat,(char *s1, int l1, char *s2, int l2, char *s3, int l3, MALLOC_S *clp));
-_PROTOTYPE(extern int printdevname,(dev_t *dev, dev_t *rdev, int f, int nty));
-_PROTOTYPE(extern void print_file,(void));
-_PROTOTYPE(extern void print_init,(void));
-_PROTOTYPE(extern void printname,(int nl));
-_PROTOTYPE(extern char *print_kptr,(KA_T kp, char *buf, size_t bufl));
-_PROTOTYPE(extern int print_proc,(void));
-_PROTOTYPE(extern void printrawaddr,(struct sockaddr *sa));
-_PROTOTYPE(extern void print_tcptpi,(int nl));
-_PROTOTYPE(extern char *printuid,(UID_ARG uid, int *ty));
-_PROTOTYPE(extern void printunkaf,(int fam, int ty));
-_PROTOTYPE(extern char *printsockty,(int ty));
-_PROTOTYPE(extern void process_file,(KA_T fp));
-_PROTOTYPE(extern void process_node,(KA_T f));
-_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));
-_PROTOTYPE(extern int statsafely,(char *path, struct stat *buf));
-_PROTOTYPE(extern void stkdir,(char *p));
-_PROTOTYPE(extern void usage,(int err, int fh, int version));
-_PROTOTYPE(extern int util_strftime,(char *fmtr, int fmtl, char *fmt));
-_PROTOTYPE(extern int vfy_dev,(struct l_dev *dp));
-_PROTOTYPE(extern char *x2dev,(char *s, dev_t *d));
-
-# if	defined(HASBLKDEV)
-_PROTOTYPE(extern void find_bl_ino,(void));
-_PROTOTYPE(extern struct l_dev *lkupbdev,(dev_t *dev,dev_t *rdev,int i,int r));
-_PROTOTYPE(extern int printbdevname,(dev_t *dev, dev_t *rdev, int f));
-# endif	/* defined(HASBLKDEV) */
-
-# if	defined(HASCDRNODE)
-_PROTOTYPE(extern int readcdrnode,(KA_T ca, struct cdrnode *c));
-# endif	/* defined(HASCDRNODE) */
-
-# if	defined(HASDCACHE)
-_PROTOTYPE(extern void alloc_dcache,(void));
-_PROTOTYPE(extern void crc,(char *b, int l, unsigned *s));
-_PROTOTYPE(extern void crdbld,(void));
-_PROTOTYPE(extern int ctrl_dcache,(char *p));
-_PROTOTYPE(extern int dcpath,(int rw, int npw));
-_PROTOTYPE(extern int open_dcache,(int m, int r, struct stat *sb));
-_PROTOTYPE(extern int read_dcache,(void));
-_PROTOTYPE(extern int wr2DCfd,(char *b, unsigned *c));
-_PROTOTYPE(extern void write_dcache,(void));
-# endif	/* defined(HASDCACHE) */
-
-# if	defined(HASFIFONODE)
-_PROTOTYPE(extern int readfifonode,(KA_T fa, struct fifonode *f));
-# endif	/* defined(HASFIFONODE) */
-
-# if	defined(HASFSTRUCT)
-_PROTOTYPE(extern char *print_fflags,(long ffg, long pof));
-# endif	/* defined(HASFSTRUCT) */
-
-# if	defined(HASGNODE)
-_PROTOTYPE(extern int readgnode,(KA_T ga, struct gnode *g));
-# endif	/* defined(HASGNODE) */
-
-# if	defined(HASKQUEUE)
-_PROTOTYPE(extern void process_kqueue,(KA_T ka));
-# endif	/* defined(HASKQUEUE) */
-
-# if	defined(HASHSNODE)
-_PROTOTYPE(extern int readhsnode,(KA_T ha, struct hsnode *h));
-# endif	/* defined(HASHSNODE) */
-
-# if	defined(HASINODE)
-_PROTOTYPE(extern int readinode,(KA_T ia, struct inode *i));
-# endif	/* defined(HASINODE) */
-
-# if	defined(HASNCACHE)
-_PROTOTYPE(extern void ncache_load,(void));
-_PROTOTYPE(extern char *ncache_lookup,(char *buf, int blen, int *fp));
-# endif	/* defined(HASNCACHE) */
-
-# if	defined(HASNLIST)
-_PROTOTYPE(extern void build_Nl,(struct drive_Nl *d));
-_PROTOTYPE(extern int get_Nl_value,(char *nn, struct drive_Nl *d, KA_T *v));
-# endif	/* defined(HASNLIST) */
-
-# if	defined(HASPIPENODE)
-_PROTOTYPE(extern int readpipenode,(KA_T pa, struct pipenode *p));
-# endif	/* defined(HASPIPENODE) */
-
-# if	defined(HASPRINTDEV)
-_PROTOTYPE(extern char *HASPRINTDEV,(struct lfile *lf, dev_t *dev));
-# endif	/* defined(HASPRINTDEV) */
-
-# if	defined(HASPRINTINO)
-_PROTOTYPE(extern char *HASPRINTINO,(struct lfile *lf));
-# endif	/* defined(HASPRINTINO) */
-
-# if	defined(HASPRINTNM)
-_PROTOTYPE(extern void HASPRINTNM,(struct lfile *lf));
-# endif	/* defined(HASPRINTNM) */
-
-# if	defined(HASPRINTOFF)
-_PROTOTYPE(extern char *HASPRINTOFF,(struct lfile *lf, int ty));
-# endif	/* defined(HASPRINTOFF) */
-
-# if	defined(HASPRINTSZ)
-_PROTOTYPE(extern char *HASPRINTSZ,(struct lfile *lf));
-# endif	/* defined(HASPRINTSZ) */
-
-# if	defined(HASPRIVNMCACHE)
-_PROTOTYPE(extern int HASPRIVNMCACHE,(struct lfile *lf));
-# endif	/* defined(HASPRIVNMCACHE) */
-
-# if	!defined(HASPRIVPRIPP)
-_PROTOTYPE(extern void printiproto,(int p));
-# endif	/* !defined(HASPRIVPRIPP) */
-
-# if	defined(HASRNODE)
-_PROTOTYPE(extern int readrnode,(KA_T ra, struct rnode *r));
-# endif	/* defined(HASRNODE) */
-
-# if	defined(HASSPECDEVD)
-_PROTOTYPE(extern void HASSPECDEVD,(char *p, struct stat *s));
-# endif	/* defined(HASSPECDEVD) */
-
-# if	defined(HASSNODE)
-_PROTOTYPE(extern int readsnode,(KA_T sa, struct snode *s));
-# endif	/* defined(HASSNODE) */
-
-# if	defined(HASSTREAMS)
-_PROTOTYPE(extern int readstdata,(KA_T addr, struct stdata *buf));
-_PROTOTYPE(extern int readsthead,(KA_T addr, struct queue *buf));
-_PROTOTYPE(extern int readstidnm,(KA_T addr, char *buf, READLEN_T len));
-_PROTOTYPE(extern int readstmin,(KA_T addr, struct module_info *buf));
-_PROTOTYPE(extern int readstqinit,(KA_T addr, struct qinit *buf));
-# endif	/* defined(HASSTREAMS) */
-
-# if	defined(HASTMPNODE)
-_PROTOTYPE(extern int readtnode,(KA_T ta, struct tmpnode *t));
-# endif	/* defined(HASTMPNODE) */
-
-# if	defined(HASVNODE)
-_PROTOTYPE(extern int readvnode,(KA_T va, struct vnode *v));
-# endif	/* defined(HASVNODE) */
-
-# if	defined(USE_LIB_SNPF)
-_PROTOTYPE(extern int snpf,(char *str, int len, char *fmt, ...));
-# endif	/* defined(USE_LIB_SNPF) */
-
-# endif	/* !defined(PROTO_H) */
diff --git a/regex.h b/regex.h
deleted file mode 100644
index 27bb8e5..0000000
--- a/regex.h
+++ /dev/null
@@ -1,617 +0,0 @@
-/*
- * regex.h -- regular expression definitions for lsof
- *
- * This header file is used only when the dialect has no POSIX-conformant
- * regular expression function set.  When that is the case, the dialect's
- * machine.h will define USE_LIB_REGEX.
- *
- * When the dialect has a POSIX-conformant regular expression function set,
- * USE_LIB_REGEX is not defined and this header file #include's <regex.h>.
- *
- * V. Abell <abe@purdue.edu>
- * Purdue University
- */
-
-
-/*
- * Copyright 2000 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.
- *
- * This software has been adapted from snprintf.c in sendmail 8.9.3.  It
- * is subject to the sendmail copyright statements listed below, and the
- * sendmail licensing terms stated in the sendmail LICENSE file comment
- * section of this file.
- *
- * 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.
- */
-
-
-#ifdef	USE_LIB_REGEX
-/*
- * This section comes from GLIBC 2.2.  It is used only when the dialect
- * has no POSIX-conformant regular expression function set.  When that is
- * the case, the dialect's machine.h will define USE_LIB_REGEX.
- */
-
-/* Definitions for data structures and routines for the regular
-   expression library, version 0.12.
-   Copyright (C) 1985,1989-1993,1995-1998, 2000 Free Software Foundation, Inc.
-
-   This file is part of the GNU C Library.  Its master source is NOT part of
-   the C library, however.  The master source lives in /gd/gnu/lib.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Library General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Library General Public License for more details.
-
-   You should have received a copy of the GNU Library General Public
-   License along with the GNU C Library; see the file COPYING.LIB.  If not,
-   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
-
-#ifndef _REGEX_H
-#define _REGEX_H 1
-
-/* Allow the use in C++ code.  */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* POSIX says that <sys/types.h> must be included (by the caller) before
-   <regex.h>.  */
-
-#if !defined _POSIX_C_SOURCE && !defined _POSIX_SOURCE && defined VMS
-/* VMS doesn't have `size_t' in <sys/types.h>, even though POSIX says it
-   should be there.  */
-# include <stddef.h>
-#endif
-
-/* The following two types have to be signed and unsigned integer type
-   wide enough to hold a value of a pointer.  For most ANSI compilers
-   ptrdiff_t and size_t should be likely OK.  Still size of these two
-   types is 2 for Microsoft C.  Ugh... */
-typedef long int s_reg_t;
-typedef unsigned long int active_reg_t;
-
-/* The following bits are used to determine the regexp syntax we
-   recognize.  The set/not-set meanings are chosen so that Emacs syntax
-   remains the value 0.  The bits are given in alphabetical order, and
-   the definitions shifted by one from the previous bit; thus, when we
-   add or remove a bit, only one other definition need change.  */
-typedef unsigned long int reg_syntax_t;
-
-/* If this bit is not set, then \ inside a bracket expression is literal.
-   If set, then such a \ quotes the following character.  */
-#define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1)
-
-/* If this bit is not set, then + and ? are operators, and \+ and \? are
-     literals.
-   If set, then \+ and \? are operators and + and ? are literals.  */
-#define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1)
-
-/* If this bit is set, then character classes are supported.  They are:
-     [:alpha:], [:upper:], [:lower:],  [:digit:], [:alnum:], [:xdigit:],
-     [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:].
-   If not set, then character classes are not supported.  */
-#define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1)
-
-/* If this bit is set, then ^ and $ are always anchors (outside bracket
-     expressions, of course).
-   If this bit is not set, then it depends:
-        ^  is an anchor if it is at the beginning of a regular
-           expression or after an open-group or an alternation operator;
-        $  is an anchor if it is at the end of a regular expression, or
-           before a close-group or an alternation operator.
-
-   This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because
-   POSIX draft 11.2 says that * etc. in leading positions is undefined.
-   We already implemented a previous draft which made those constructs
-   invalid, though, so we haven't changed the code back.  */
-#define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1)
-
-/* If this bit is set, then special characters are always special
-     regardless of where they are in the pattern.
-   If this bit is not set, then special characters are special only in
-     some contexts; otherwise they are ordinary.  Specifically,
-     * + ? and intervals are only special when not after the beginning,
-     open-group, or alternation operator.  */
-#define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1)
-
-/* If this bit is set, then *, +, ?, and { cannot be first in an re or
-     immediately after an alternation or begin-group operator.  */
-#define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1)
-
-/* If this bit is set, then . matches newline.
-   If not set, then it doesn't.  */
-#define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1)
-
-/* If this bit is set, then . doesn't match NUL.
-   If not set, then it does.  */
-#define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1)
-
-/* If this bit is set, nonmatching lists [^...] do not match newline.
-   If not set, they do.  */
-#define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1)
-
-/* If this bit is set, either \{...\} or {...} defines an
-     interval, depending on RE_NO_BK_BRACES.
-   If not set, \{, \}, {, and } are literals.  */
-#define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1)
-
-/* If this bit is set, +, ? and | aren't recognized as operators.
-   If not set, they are.  */
-#define RE_LIMITED_OPS (RE_INTERVALS << 1)
-
-/* If this bit is set, newline is an alternation operator.
-   If not set, newline is literal.  */
-#define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1)
-
-/* If this bit is set, then `{...}' defines an interval, and \{ and \}
-     are literals.
-  If not set, then `\{...\}' defines an interval.  */
-#define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1)
-
-/* If this bit is set, (...) defines a group, and \( and \) are literals.
-   If not set, \(...\) defines a group, and ( and ) are literals.  */
-#define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1)
-
-/* If this bit is set, then \<digit> matches <digit>.
-   If not set, then \<digit> is a back-reference.  */
-#define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1)
-
-/* If this bit is set, then | is an alternation operator, and \| is literal.
-   If not set, then \| is an alternation operator, and | is literal.  */
-#define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1)
-
-/* If this bit is set, then an ending range point collating higher
-     than the starting range point, as in [z-a], is invalid.
-   If not set, then when ending range point collates higher than the
-     starting range point, the range is ignored.  */
-#define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1)
-
-/* If this bit is set, then an unmatched ) is ordinary.
-   If not set, then an unmatched ) is invalid.  */
-#define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1)
-
-/* If this bit is set, succeed as soon as we match the whole pattern,
-   without further backtracking.  */
-#define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1)
-
-/* If this bit is set, do not process the GNU regex operators.
-   If not set, then the GNU regex operators are recognized. */
-#define RE_NO_GNU_OPS (RE_NO_POSIX_BACKTRACKING << 1)
-
-/* If this bit is set, turn on internal regex debugging.
-   If not set, and debugging was on, turn it off.
-   This only works if regex.c is compiled -DDEBUG.
-   We define this bit always, so that all that's needed to turn on
-   debugging is to recompile regex.c; the calling code can always have
-   this bit set, and it won't affect anything in the normal case. */
-#define RE_DEBUG (RE_NO_GNU_OPS << 1)
-
-/* This global variable defines the particular regexp syntax to use (for
-   some interfaces).  When a regexp is compiled, the syntax used is
-   stored in the pattern buffer, so changing this does not affect
-   already-compiled regexps.  */
-extern reg_syntax_t re_syntax_options;
-
-/* Define combinations of the above bits for the standard possibilities.
-   (The [[[ comments delimit what gets put into the Texinfo file, so
-   don't delete them!)  */
-/* [[[begin syntaxes]]] */
-#define RE_SYNTAX_EMACS 0
-
-#define RE_SYNTAX_AWK							\
-  (RE_BACKSLASH_ESCAPE_IN_LISTS   | RE_DOT_NOT_NULL			\
-   | RE_NO_BK_PARENS              | RE_NO_BK_REFS			\
-   | RE_NO_BK_VBAR                | RE_NO_EMPTY_RANGES			\
-   | RE_DOT_NEWLINE		  | RE_CONTEXT_INDEP_ANCHORS		\
-   | RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS)
-
-#define RE_SYNTAX_GNU_AWK						\
-  ((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DEBUG)	\
-   & ~(RE_DOT_NOT_NULL | RE_INTERVALS | RE_CONTEXT_INDEP_OPS))
-
-#define RE_SYNTAX_POSIX_AWK 						\
-  (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS		\
-   | RE_INTERVALS	    | RE_NO_GNU_OPS)
-
-#define RE_SYNTAX_GREP							\
-  (RE_BK_PLUS_QM              | RE_CHAR_CLASSES				\
-   | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS				\
-   | RE_NEWLINE_ALT)
-
-#define RE_SYNTAX_EGREP							\
-  (RE_CHAR_CLASSES        | RE_CONTEXT_INDEP_ANCHORS			\
-   | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE			\
-   | RE_NEWLINE_ALT       | RE_NO_BK_PARENS				\
-   | RE_NO_BK_VBAR)
-
-#define RE_SYNTAX_POSIX_EGREP						\
-  (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES)
-
-/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff.  */
-#define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC
-
-#define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC
-
-/* Syntax bits common to both basic and extended POSIX regex syntax.  */
-#define _RE_SYNTAX_POSIX_COMMON						\
-  (RE_CHAR_CLASSES | RE_DOT_NEWLINE      | RE_DOT_NOT_NULL		\
-   | RE_INTERVALS  | RE_NO_EMPTY_RANGES)
-
-#define RE_SYNTAX_POSIX_BASIC						\
-  (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM)
-
-/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes
-   RE_LIMITED_OPS, i.e., \? \+ \| are not recognized.  Actually, this
-   isn't minimal, since other operators, such as \`, aren't disabled.  */
-#define RE_SYNTAX_POSIX_MINIMAL_BASIC					\
-  (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS)
-
-#define RE_SYNTAX_POSIX_EXTENDED					\
-  (_RE_SYNTAX_POSIX_COMMON  | RE_CONTEXT_INDEP_ANCHORS			\
-   | RE_CONTEXT_INDEP_OPS   | RE_NO_BK_BRACES				\
-   | RE_NO_BK_PARENS        | RE_NO_BK_VBAR				\
-   | RE_CONTEXT_INVALID_OPS | RE_UNMATCHED_RIGHT_PAREN_ORD)
-
-/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INDEP_OPS is
-   removed and RE_NO_BK_REFS is added.  */
-#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED				\
-  (_RE_SYNTAX_POSIX_COMMON  | RE_CONTEXT_INDEP_ANCHORS			\
-   | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES				\
-   | RE_NO_BK_PARENS        | RE_NO_BK_REFS				\
-   | RE_NO_BK_VBAR	    | RE_UNMATCHED_RIGHT_PAREN_ORD)
-/* [[[end syntaxes]]] */
-
-/* Maximum number of duplicates an interval can allow.  Some systems
-   (erroneously) define this in other header files, but we want our
-   value, so remove any previous define.  */
-#ifdef RE_DUP_MAX
-# undef RE_DUP_MAX
-#endif
-/* If sizeof(int) == 2, then ((1 << 15) - 1) overflows.  */
-#define RE_DUP_MAX (0x7fff)
-
-
-/* POSIX `cflags' bits (i.e., information for `regcomp').  */
-
-/* If this bit is set, then use extended regular expression syntax.
-   If not set, then use basic regular expression syntax.  */
-#define REG_EXTENDED 1
-
-/* If this bit is set, then ignore case when matching.
-   If not set, then case is significant.  */
-#define REG_ICASE (REG_EXTENDED << 1)
-
-/* If this bit is set, then anchors do not match at newline
-     characters in the string.
-   If not set, then anchors do match at newlines.  */
-#define REG_NEWLINE (REG_ICASE << 1)
-
-/* If this bit is set, then report only success or fail in regexec.
-   If not set, then returns differ between not matching and errors.  */
-#define REG_NOSUB (REG_NEWLINE << 1)
-
-
-/* POSIX `eflags' bits (i.e., information for regexec).  */
-
-/* If this bit is set, then the beginning-of-line operator doesn't match
-     the beginning of the string (presumably because it's not the
-     beginning of a line).
-   If not set, then the beginning-of-line operator does match the
-     beginning of the string.  */
-#define REG_NOTBOL 1
-
-/* Like REG_NOTBOL, except for the end-of-line.  */
-#define REG_NOTEOL (1 << 1)
-
-
-/* If any error codes are removed, changed, or added, update the
-   `re_error_msg' table in regex.c.  */
-typedef enum
-{
-#ifdef _XOPEN_SOURCE
-  REG_ENOSYS = -1,	/* This will never happen for this implementation.  */
-#endif
-
-  REG_NOERROR = 0,	/* Success.  */
-  REG_NOMATCH,		/* Didn't find a match (for regexec).  */
-
-  /* POSIX regcomp return error codes.  (In the order listed in the
-     standard.)  */
-  REG_BADPAT,		/* Invalid pattern.  */
-  REG_ECOLLATE,		/* Not implemented.  */
-  REG_ECTYPE,		/* Invalid character class name.  */
-  REG_EESCAPE,		/* Trailing backslash.  */
-  REG_ESUBREG,		/* Invalid back reference.  */
-  REG_EBRACK,		/* Unmatched left bracket.  */
-  REG_EPAREN,		/* Parenthesis imbalance.  */
-  REG_EBRACE,		/* Unmatched \{.  */
-  REG_BADBR,		/* Invalid contents of \{\}.  */
-  REG_ERANGE,		/* Invalid range end.  */
-  REG_ESPACE,		/* Ran out of memory.  */
-  REG_BADRPT,		/* No preceding re for repetition op.  */
-
-  /* Error codes we've added.  */
-  REG_EEND,		/* Premature end.  */
-  REG_ESIZE,		/* Compiled pattern bigger than 2^16 bytes.  */
-  REG_ERPAREN		/* Unmatched ) or \); not returned from regcomp. */
-} reg_errcode_t;
-
-/* This data structure represents a compiled pattern.  Before calling
-   the pattern compiler, the fields `buffer', `allocated', `fastmap',
-   `translate', and `no_sub' can be set.  After the pattern has been
-   compiled, the `re_nsub' field is available.  All other fields are
-   private to the regex routines.  */
-
-#ifndef RE_TRANSLATE_TYPE
-# define RE_TRANSLATE_TYPE char *
-#endif
-
-struct re_pattern_buffer
-{
-/* [[[begin pattern_buffer]]] */
-	/* Space that holds the compiled pattern.  It is declared as
-          `unsigned char *' because its elements are
-           sometimes used as array indexes.  */
-  unsigned char *buffer;
-
-	/* Number of bytes to which `buffer' points.  */
-  unsigned long int allocated;
-
-	/* Number of bytes actually used in `buffer'.  */
-  unsigned long int used;
-
-        /* Syntax setting with which the pattern was compiled.  */
-  reg_syntax_t syntax;
-
-        /* Pointer to a fastmap, if any, otherwise zero.  re_search uses
-           the fastmap, if there is one, to skip over impossible
-           starting points for matches.  */
-  char *fastmap;
-
-        /* Either a translate table to apply to all characters before
-           comparing them, or zero for no translation.  The translation
-           is applied to a pattern when it is compiled and to a string
-           when it is matched.  */
-  RE_TRANSLATE_TYPE translate;
-
-	/* Number of subexpressions found by the compiler.  */
-  size_t re_nsub;
-
-        /* Zero if this pattern cannot match the empty string, one else.
-           Well, in truth it's used only in `re_search_2', to see
-           whether or not we should use the fastmap, so we don't set
-           this absolutely perfectly; see `re_compile_fastmap' (the
-           `duplicate' case).  */
-  unsigned can_be_null : 1;
-
-        /* If REGS_UNALLOCATED, allocate space in the `regs' structure
-             for `max (RE_NREGS, re_nsub + 1)' groups.
-           If REGS_REALLOCATE, reallocate space if necessary.
-           If REGS_FIXED, use what's there.  */
-#define REGS_UNALLOCATED 0
-#define REGS_REALLOCATE 1
-#define REGS_FIXED 2
-  unsigned regs_allocated : 2;
-
-        /* Set to zero when `regex_compile' compiles a pattern; set to one
-           by `re_compile_fastmap' if it updates the fastmap.  */
-  unsigned fastmap_accurate : 1;
-
-        /* If set, `re_match_2' does not return information about
-           subexpressions.  */
-  unsigned no_sub : 1;
-
-        /* If set, a beginning-of-line anchor doesn't match at the
-           beginning of the string.  */
-  unsigned not_bol : 1;
-
-        /* Similarly for an end-of-line anchor.  */
-  unsigned not_eol : 1;
-
-        /* If true, an anchor at a newline matches.  */
-  unsigned newline_anchor : 1;
-
-/* [[[end pattern_buffer]]] */
-};
-
-typedef struct re_pattern_buffer regex_t;
-
-/* Type for byte offsets within the string.  POSIX mandates this.  */
-typedef int regoff_t;
-
-
-/* This is the structure we store register match data in.  See
-   regex.texinfo for a full description of what registers match.  */
-struct re_registers
-{
-  unsigned num_regs;
-  regoff_t *start;
-  regoff_t *end;
-};
-
-
-/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer,
-   `re_match_2' returns information about at least this many registers
-   the first time a `regs' structure is passed.  */
-#ifndef RE_NREGS
-# define RE_NREGS 30
-#endif
-
-
-/* POSIX specification for registers.  Aside from the different names than
-   `re_registers', POSIX uses an array of structures, instead of a
-   structure of arrays.  */
-typedef struct
-{
-  regoff_t rm_so;  /* Byte offset from string's start to substring's start.  */
-  regoff_t rm_eo;  /* Byte offset from string's start to substring's end.  */
-} regmatch_t;
-
-/* Declarations for routines.  */
-
-/* To avoid duplicating every routine declaration -- once with a
-   prototype (if we are ANSI), and once without (if we aren't) -- we
-   use the following macro to declare argument types.  This
-   unfortunately clutters up the declarations a bit, but I think it's
-   worth it.  */
-
-#if __STDC__
-
-# define _RE_ARGS(args) args
-
-#else /* not __STDC__ */
-
-# define _RE_ARGS(args) ()
-
-#endif /* not __STDC__ */
-
-/* Sets the current default syntax to SYNTAX, and return the old syntax.
-   You can also simply assign to the `re_syntax_options' variable.  */
-extern reg_syntax_t re_set_syntax _RE_ARGS ((reg_syntax_t syntax));
-
-/* Compile the regular expression PATTERN, with length LENGTH
-   and syntax given by the global `re_syntax_options', into the buffer
-   BUFFER.  Return NULL if successful, and an error string if not.  */
-extern const char *re_compile_pattern
-  _RE_ARGS ((const char *pattern, size_t length,
-             struct re_pattern_buffer *buffer));
-
-
-/* Compile a fastmap for the compiled pattern in BUFFER; used to
-   accelerate searches.  Return 0 if successful and -2 if was an
-   internal error.  */
-extern int re_compile_fastmap _RE_ARGS ((struct re_pattern_buffer *buffer));
-
-
-/* Search in the string STRING (with length LENGTH) for the pattern
-   compiled into BUFFER.  Start searching at position START, for RANGE
-   characters.  Return the starting position of the match, -1 for no
-   match, or -2 for an internal error.  Also return register
-   information in REGS (if REGS and BUFFER->no_sub are nonzero).  */
-extern int re_search
-  _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
-            int length, int start, int range, struct re_registers *regs));
-
-
-/* Like `re_search', but search in the concatenation of STRING1 and
-   STRING2.  Also, stop searching at index START + STOP.  */
-extern int re_search_2
-  _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
-             int length1, const char *string2, int length2,
-             int start, int range, struct re_registers *regs, int stop));
-
-
-/* Like `re_search', but return how many characters in STRING the regexp
-   in BUFFER matched, starting at position START.  */
-extern int re_match
-  _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
-             int length, int start, struct re_registers *regs));
-
-
-/* Relates to `re_match' as `re_search_2' relates to `re_search'.  */
-extern int re_match_2
-  _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
-             int length1, const char *string2, int length2,
-             int start, struct re_registers *regs, int stop));
-
-
-/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
-   ENDS.  Subsequent matches using BUFFER and REGS will use this memory
-   for recording register information.  STARTS and ENDS must be
-   allocated with malloc, and must each be at least `NUM_REGS * sizeof
-   (regoff_t)' bytes long.
-
-   If NUM_REGS == 0, then subsequent matches should allocate their own
-   register data.
-
-   Unless this function is called, the first search or match using
-   PATTERN_BUFFER will allocate its own register data, without
-   freeing the old data.  */
-extern void re_set_registers
-  _RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs,
-             unsigned num_regs, regoff_t *starts, regoff_t *ends));
-
-#if defined _REGEX_RE_COMP || defined _LIBC
-# ifndef _CRAY
-/* 4.2 bsd compatibility.  */
-extern char *re_comp _RE_ARGS ((const char *));
-extern int re_exec _RE_ARGS ((const char *));
-# endif
-#endif
-
-/* GCC 2.95 and later have "__restrict"; C99 compilers have
-   "restrict", and "configure" may have defined "restrict".  */
-#ifndef __restrict
-# if ! (2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__))
-#  if defined restrict || 199901L <= __STDC_VERSION__
-#   define __restrict restrict
-#  else
-#   define __restrict
-#  endif
-# endif
-#endif
-/* For now unconditionally define __restrict_arr to expand to nothing.
-   Ideally we would have a test for the compiler which allows defining
-   it to restrict.  */
-#define __restrict_arr
-
-/* POSIX compatibility.  */
-extern int regcomp _RE_ARGS ((regex_t *__restrict __preg,
-			      const char *__restrict __pattern,
-			      int __cflags));
-
-extern int regexec _RE_ARGS ((const regex_t *__restrict __preg,
-			      const char *__restrict __string, size_t __nmatch,
-			      regmatch_t __pmatch[__restrict_arr],
-			      int __eflags));
-
-extern size_t regerror _RE_ARGS ((int __errcode, const regex_t *__preg,
-				  char *__errbuf, size_t __errbuf_size));
-
-extern void regfree _RE_ARGS ((regex_t *__preg));
-
-#ifdef __cplusplus
-}
-#endif	/* C++ */
-
-#endif /* regex.h */
-
-/*
-Local variables:
-make-backup-files: t
-version-control: t
-trim-versions-without-asking: nil
-End:
-*/
-
-#else	/* !defined(USE_LIB_REGEX) */
-#include <regex.h>
-#endif	/* defined(USE_LIB_REGEX) */
diff --git a/scripts/big_brother.pl b/scripts/big_brother.pl
index 8a19757..8ed8a67 100755
--- a/scripts/big_brother.pl
+++ b/scripts/big_brother.pl
@@ -11,7 +11,7 @@
 
 # @(#)big_brother	1.12 08/14/96 Written by Lionel.Cons@cern.ch
 
-# no waranty! use this at your own risks!
+# no warranty! use this at your own risks!
 
 #
 # init & setup
diff --git a/scripts/identd.pl b/scripts/identd.pl
index 20661fb..e7a8108 100755
--- a/scripts/identd.pl
+++ b/scripts/identd.pl
@@ -9,7 +9,7 @@
 #   ident   stream  tcp     nowait  root    /usr/local/bin/identd.pl -t200
 #
 # - Multiple instances of the server are not a performance penalty
-#   since they shall use lsof's cacheing mechanism. (compare with
+#   since they shall use lsof's caching mechanism. (compare with
 #   Peter Eriksson's pidentd)
 # - Command line arguments :
 #   -t TIMEOUT Number of seconds to wait for a query before aborting.
diff --git a/scripts/shared.pl b/scripts/shared.pl
index 25840f0..425b734 100755
--- a/scripts/shared.pl
+++ b/scripts/shared.pl
@@ -338,7 +338,7 @@ sub Print_block {
 	    if ($tW > $InoW) { $InoW = $tW; }
 	} else { printf " %${InoW}.${InoW}s", $t; }
 
-    # Print name and line terminater, if this is a print pass.
+    # Print name and line terminator, if this is a print pass.
 
 	if ($pass) {
 	    if (defined($Name{$key})) { print " $Name{$key}\n"; }
diff --git a/scripts/sort_res.pl b/scripts/sort_res.pl
index 374dcda..c5efb21 100755
--- a/scripts/sort_res.pl
+++ b/scripts/sort_res.pl
@@ -30,7 +30,7 @@
 #	-size reset in loop (script was broken in 4.76)
 #	-isexec looking in .. (like other scripts)
 #	-display for one or all processes
-#	-removing unuseful line number arg.
+#	-removing useless line number arg.
 #	-display global size
 
 my @args = @_;
diff --git a/src/arg.c b/src/arg.c
new file mode 100644
index 0000000..03c9dd1
--- /dev/null
+++ b/src/arg.c
@@ -0,0 +1,2193 @@
+/*
+ * arg.c - common argument processing 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.
+ */
+
+#include "common.h"
+#include "cli.h"
+#include "lsof.h"
+#include <limits.h>
+
+/*
+ * Local definitions
+ */
+
+#define CMDRXINCR 32 /* CmdRx[] allocation increment */
+
+/*
+ * Local static variables
+ */
+
+/*
+ * Local function prototypes
+ */
+
+static int ckfd_range(struct lsof_context *ctx, char *first, char *dash,
+                      char *last, int *lo, int *hi);
+static int enter_fd_lst(struct lsof_context *ctx, char *nm, int lo, int hi,
+                        int excl);
+static int enter_nwad(struct lsof_context *ctx, struct nwad *n, int sp, int ep,
+                      char *s, struct hostent *he);
+static struct hostent *lkup_hostnm(char *hn, struct nwad *n);
+static char *isIPv4addr(char *hn, unsigned char *a, int al);
+
+/*
+ * ckfd_range() - check fd range
+ */
+
+static int ckfd_range(struct lsof_context *ctx, /* context */
+                      char *first,              /* starting character */
+                      char *dash,               /* '-' location */
+                      char *last,               /* '\0' location */
+                      int *lo,                  /* returned low value */
+                      int *hi)                  /* returned high value */
+{
+    char *cp;
+    /*
+     * See if the range character pointers make sense.
+     */
+    if (first >= dash || dash >= last) {
+        (void)fprintf(stderr, "%s: illegal FD range for -d: ", Pn);
+        safestrprt(first, stderr, 1);
+        return (1);
+    }
+    /*
+     * Assemble and check the high and low values.
+     */
+    for (cp = first, *lo = 0; *cp && cp < dash; cp++) {
+        if (!isdigit((unsigned char)*cp)) {
+
+        FD_range_nondigit:
+
+            (void)fprintf(stderr, "%s: non-digit in -d FD range: ", Pn);
+            safestrprt(first, stderr, 1);
+            return (1);
+        }
+        *lo = (*lo * 10) + (int)(*cp - '0');
+    }
+    for (cp = dash + 1, *hi = 0; *cp && cp < last; cp++) {
+        if (!isdigit((unsigned char)*cp))
+            goto FD_range_nondigit;
+        *hi = (*hi * 10) + (int)(*cp - '0');
+    }
+    if (*lo >= *hi) {
+        (void)fprintf(stderr, "%s: -d FD range's low >= its high: ", Pn);
+        safestrprt(first, stderr, 1);
+        return (1);
+    }
+    return (0);
+}
+
+/*
+ * ck_file_arg() - check file arguments
+ */
+
+int ck_file_arg(struct lsof_context *ctx, int i, /* first file argument index */
+                int ac,                          /* argument count */
+                char *av[],                      /* argument vector */
+                int fv,           /* Ffilesys value (real or temporary) */
+                int rs,           /* Readlink() status if argument count == 1:
+                                   *	0 = undone; 1 = done */
+                struct stat *sbp, /* if non-NULL, pointer to stat(2) buffer
+                                   * when argument count == 1 */
+                int accept_deleted_file) /* if non-zero, don't report an error
+                                          * even when the file doesn't exist. */
+{
+    char *ap, *fnm, *fsnm, *path;
+    short err = 0;
+    int fsm, ftype, j, k;
+    MALLOC_S l;
+    struct mounts *mp;
+    static struct mounts **mmp = (struct mounts **)NULL;
+    int mx, nm;
+    static int nma = 0;
+    struct stat sb;
+    struct sfile *sfp;
+    short ss = 0;
+
+#if defined(CKFA_EXPDEV)
+    dev_t dev, rdev;
+#endif /* defined(CKFA_EXPDEV) */
+
+#if defined(HASPROCFS)
+    unsigned char ad, an;
+    int pfsnl = -1;
+    pid_t pid;
+    struct procfsid *pfi;
+#endif /* defined(HASPROCFS) */
+
+    /*
+     * Loop through arguments.
+     */
+    for (; i < ac; i++) {
+        if (rs && (ac == 1) && (i == 0))
+            path = av[i];
+        else {
+            if (!(path = Readlink(ctx, av[i]))) {
+                ErrStat = 1;
+                continue;
+            }
+        }
+        /*
+         * Remove terminating `/' characters from paths longer than one.
+         */
+        j = k = strlen(path);
+        while ((k > 1) && (path[k - 1] == '/')) {
+            k--;
+        }
+        if (k < j) {
+            if (path != av[i])
+                path[k] = '\0';
+            else {
+                if (!(ap = (char *)malloc((MALLOC_S)(k + 1)))) {
+                    (void)fprintf(stderr, "%s: no space for copy of %s\n", Pn,
+                                  path);
+                    Error(ctx);
+                }
+                (void)strncpy(ap, path, k);
+                ap[k] = '\0';
+                path = ap;
+            }
+        }
+        /*
+         * Check for file system argument.
+         */
+        for (ftype = 1, mp = readmnt(ctx), nm = 0; (fv != 1) && mp;
+             mp = mp->next) {
+            fsm = 0;
+            if (strcmp(mp->dir, path) == 0)
+                fsm++;
+            else if (fv == 2 || (mp->fs_mode & S_IFMT) == S_IFBLK) {
+                if (mp->fsnmres && strcmp(mp->fsnmres, path) == 0)
+                    fsm++;
+            }
+            if (!fsm)
+                continue;
+            ftype = 0;
+            /*
+             * Skip duplicates.
+             */
+            for (mx = 0; mx < nm; mx++) {
+                if (strcmp(mp->dir, mmp[mx]->dir) == 0 &&
+                    mp->dev == mmp[mx]->dev && mp->rdev == mmp[mx]->rdev &&
+                    mp->inode == mmp[mx]->inode)
+                    break;
+            }
+            if (mx < nm)
+                continue;
+            /*
+             * Allocate space for and save another mount point match and
+             * the type of match -- directory name (mounted) or file system
+             * name (mounted-on).
+             */
+            if (nm >= nma) {
+                nma += 5;
+                l = (MALLOC_S)(nma * sizeof(struct mounts *));
+                if (mmp)
+                    mmp = (struct mounts **)realloc((MALLOC_P *)mmp, l);
+                else
+                    mmp = (struct mounts **)malloc(l);
+                if (!mmp) {
+                    (void)fprintf(stderr, "%s: no space for mount pointers\n",
+                                  Pn);
+                    Error(ctx);
+                }
+            }
+            mmp[nm++] = mp;
+        }
+        if (fv == 2 && nm == 0) {
+            if (!accept_deleted_file) {
+                (void)fprintf(stderr, "%s: not a file system: ", Pn);
+                safestrprt(av[i], stderr, 1);
+            }
+            ErrStat = 1;
+            continue;
+        }
+        /*
+         * Loop through the file system matches.  If there were none, make one
+         * pass through the loop, using simply the path name.
+         */
+        mx = 0;
+        do {
+
+            /*
+             * Allocate an sfile structure and fill in the type and link.
+             */
+            if (!(sfp = (struct sfile *)malloc(sizeof(struct sfile)))) {
+                (void)fprintf(stderr, "%s: no space for files\n", Pn);
+                Error(ctx);
+            }
+            sfp->next = Sfile;
+            Sfile = sfp;
+            sfp->f = 0;
+            if ((sfp->type = ftype)) {
+
+                /*
+                 * For a non-file system path, use the path as the file name
+                 * and set a NULL file system name.
+                 */
+                fnm = path;
+                fsnm = (char *)NULL;
+                /*
+                 * Stat the path to obtain its characteristics.
+                 */
+                if (sbp && (ac == 1))
+                    sb = *sbp;
+                else {
+                    if (statsafely(ctx, fnm, &sb) != 0) {
+                        int en = errno;
+                        if (!accept_deleted_file) {
+                            (void)fprintf(stderr, "%s: status error on ", Pn);
+                            safestrprt(fnm, stderr, 0);
+                            (void)fprintf(stderr, ": %s\n", strerror(en));
+                        }
+                        Sfile = sfp->next;
+                        (void)free((FREE_P *)sfp);
+                        ErrStat = 1;
+                        continue;
+                    }
+
+#if defined(HASSPECDEVD)
+                    (void)HASSPECDEVD(ctx, fnm, &sb);
+#endif /* defined(HASSPECDEVD) */
+                }
+                sfp->i = (INODETYPE)sb.st_ino;
+                sfp->mode = sb.st_mode & S_IFMT;
+
+#if defined(CKFA_EXPDEV)
+                /*
+                 * Expand device numbers before saving, so that they match the
+                 * already-expanded local mount info table device numbers.
+                 * (This is an EP/IX 2.1.1 and above artifact.)
+                 */
+                sfp->dev = expdev(sb.st_dev);
+                sfp->rdev = expdev(sb.st_rdev);
+#else  /* !defined(CKFA_EXPDEV) */
+                sfp->dev = sb.st_dev;
+                sfp->rdev = sb.st_rdev;
+#endif /* defined(CKFA_EXPDEV) */
+
+#if defined(CKFA_MPXCHAN)
+                /*
+                 * Save a (possible) multiplexed channel number.  (This is an
+                 * AIX artifact.)
+                 */
+                sfp->ch = getchan(path);
+#endif /* defined(CKFA_MPXCHAN) */
+
+            } else {
+
+#if defined(SAVE_MP_IN_SFILE)
+                sfp->mp = mp = mmp[mx++];
+#else  /* !defined(SAVE_MP_IN_SFILE) */
+                mp = mmp[mx++];
+#endif /* defined(SAVE_MP_IN_SFILE) */
+
+                ss++;
+
+#if defined(HASPROCFS)
+                /*
+                 * If this is a /proc file system, set the search flag and
+                 * abandon the sfile entry.
+                 */
+                if (mp == Mtprocfs) {
+                    Sfile = sfp->next;
+                    (void)free((FREE_P *)sfp);
+                    Procsrch = 1;
+                    continue;
+                }
+#endif /* defined(HASPROCFS) */
+
+                /*
+                 * Derive file name and file system name for a mount point.
+                 *
+                 * Save the device numbers, inode number, and modes.
+                 */
+                fnm = mp->dir;
+                fsnm = mp->fsname;
+                sfp->dev = mp->dev;
+                sfp->rdev = mp->rdev;
+                sfp->i = mp->inode;
+                sfp->mode = mp->mode & S_IFMT;
+            }
+            ss = 1; /* indicate a "safe" stat() */
+                    /*
+                     * Store the file name and file system name pointers in the sfile
+                     * structure, allocating space as necessary.
+                     */
+            if (!fnm || fnm == path) {
+                sfp->name = fnm;
+
+#if defined(HASPROCFS)
+                an = 0;
+#endif /* defined(HASPROCFS) */
+
+            } else {
+                if (!(sfp->name = mkstrcpy(fnm, (MALLOC_S *)NULL))) {
+                    (void)fprintf(stderr, "%s: no space for file name: ", Pn);
+                    safestrprt(fnm, stderr, 1);
+                    Error(ctx);
+                }
+
+#if defined(HASPROCFS)
+                an = 1;
+#endif /* defined(HASPROCFS) */
+            }
+            if (!fsnm || fsnm == path) {
+                sfp->devnm = fsnm;
+
+#if defined(HASPROCFS)
+                ad = 0;
+#endif /* defined(HASPROCFS) */
+
+            } else {
+                if (!(sfp->devnm = mkstrcpy(fsnm, (MALLOC_S *)NULL))) {
+                    (void)fprintf(stderr,
+                                  "%s: no space for file system name: ", Pn);
+                    safestrprt(fsnm, stderr, 1);
+                    Error(ctx);
+                }
+
+#if defined(HASPROCFS)
+                ad = 1;
+#endif /* defined(HASPROCFS) */
+            }
+            if (!(sfp->aname = mkstrcpy(av[i], (MALLOC_S *)NULL))) {
+                (void)fprintf(stderr,
+                              "%s: no space for argument file name: ", Pn);
+                safestrprt(av[i], stderr, 1);
+                Error(ctx);
+            }
+
+#if defined(HASPROCFS)
+            /*
+             * See if this is an individual member of a proc file system.
+             */
+            if (!Mtprocfs || Procsrch)
+                continue;
+
+#    if defined(HASFSTYPE) && HASFSTYPE == 1
+            if (strcmp(sb.st_fstype, HASPROCFS) != 0)
+                continue;
+#    endif /* defined(HASFSTYPE) && HASFSTYPE==1 */
+
+            if (pfsnl == -1)
+                pfsnl = strlen(Mtprocfs->dir);
+            if (!pfsnl)
+                continue;
+            if (strncmp(Mtprocfs->dir, path, pfsnl) != 0)
+                continue;
+            if (path[pfsnl] != '/')
+
+#    if defined(HASPINODEN)
+                pid = 0;
+#    else  /* !defined(HASPINODEN) */
+                continue;
+#    endif /* defined(HASPINODEN) */
+
+            else {
+                for (j = pfsnl + 1; path[j]; j++) {
+                    if (!isdigit((unsigned char)path[j]))
+                        break;
+                }
+                if (path[j] || (j - pfsnl - 1) < 1 ||
+                    (sfp->mode & S_IFMT) != S_IFREG)
+
+#    if defined(HASPINODEN)
+                    pid = 0;
+#    else  /* !defined(HASPINODEN) */
+                    continue;
+#    endif /* defined(HASPINODEN) */
+
+                else
+                    pid = atoi(&path[pfsnl + 1]);
+            }
+            if (!(pfi = (struct procfsid *)malloc(
+                      (MALLOC_S)sizeof(struct procfsid)))) {
+                (void)fprintf(stderr, "%s: no space for %s ID: ", Pn,
+                              Mtprocfs->dir);
+                safestrprt(path, stderr, 1);
+                Error(ctx);
+            }
+            pfi->pid = pid;
+            pfi->f = 0;
+            pfi->nm = sfp->aname;
+            pfi->next = Procfsid;
+            Procfsid = pfi;
+
+#    if defined(HASPINODEN)
+            pfi->inode = (INODETYPE)sfp->i;
+#    endif /* defined(HASPINODEN) */
+
+            /*
+             * Abandon the Sfile entry, lest it be used in is_file_named().
+             */
+            Sfile = sfp->next;
+            if (ad)
+                (void)free((FREE_P *)sfp->devnm);
+            if (an)
+                (void)free((FREE_P *)sfp->name);
+            (void)free((FREE_P *)sfp);
+#endif /* defined(HASPROCFS) */
+
+        } while (mx < nm);
+    }
+
+    if (accept_deleted_file) {
+        if (!ss && ErrStat == 0)
+            err = 1;
+        if (ErrStat)
+            ErrStat = 0;
+    } else if (!ss) {
+        err = 1;
+    }
+    return ((int)err);
+}
+
+#if defined(HASDCACHE)
+/*
+ * ctrl_dcache() - enter device cache control
+ */
+
+int ctrl_dcache(struct lsof_context *ctx, /* context */
+                char *c)                  /* control string */
+{
+    int rc = 0;
+
+    if (!c) {
+        (void)fprintf(stderr, "%s: no device cache option control string\n",
+                      Pn);
+        return (1);
+    }
+    /*
+     * Decode argument function character.
+     */
+    switch (*c) {
+    case '?':
+        if (*(c + 1) != '\0') {
+            (void)fprintf(stderr, "%s: nothing should follow -D?\n", Pn);
+            return (1);
+        }
+        DChelp = 1;
+        return (0);
+    case 'b':
+    case 'B':
+        if (Setuidroot
+
+#    if !defined(WILLDROPGID)
+            || Myuid
+#    endif /* !defined(WILLDROPGID) */
+
+        )
+            rc = 1;
+        else
+            DCstate = 1;
+        break;
+    case 'r':
+    case 'R':
+        if (Setuidroot && *(c + 1))
+            rc = 1;
+        else
+            DCstate = 2;
+        break;
+    case 'u':
+    case 'U':
+        if (Setuidroot
+
+#    if !defined(WILLDROPGID)
+            || Myuid
+#    endif /* !defined(WILLDROPGID) */
+
+        )
+            rc = 1;
+        else
+            DCstate = 3;
+        break;
+    case 'i':
+    case 'I':
+        if (*(c + 1) == '\0') {
+            DCstate = 0;
+            return (0);
+        }
+        /* fall through */
+    default:
+        (void)fprintf(stderr, "%s: unknown -D option: ", Pn);
+        safestrprt(c, stderr, 1);
+        return (1);
+    }
+    if (rc) {
+        (void)fprintf(stderr, "%s: -D option restricted to root: ", Pn);
+        safestrprt(c, stderr, 1);
+        return (1);
+    }
+    /*
+     * Skip to optional path name and save it.
+     */
+    for (c++; *c && (*c == ' ' || *c == '\t'); c++)
+        ;
+    if (strlen(c)) {
+        if (!(DCpathArg = mkstrcpy(c, (MALLOC_S *)NULL))) {
+            (void)fprintf(stderr, "%s: no space for -D path: ", Pn);
+            safestrprt(c, stderr, 1);
+            Error(ctx);
+        }
+    }
+    return (0);
+}
+#endif /* defined(HASDCACHE) */
+
+
+#if defined(HASEOPT)
+/*
+ * enter_efsys() -- enter path of file system whose kernel blocks are to be
+ *		    eliminated
+ */
+
+int enter_efsys(struct lsof_context *ctx, /* context */
+                char *e,                  /* file system path */
+                int rdlnk)                /* avoid readlink(2) if non-zero */
+{
+    char *ec;         /* pointer to copy of path */
+    efsys_list_t *ep; /* file system path list pointer */
+    int i;            /* temporary index */
+    char *path;       /* Readlink() of file system path */
+
+    if (!e || (*e != '/')) {
+        if (!Fwarn)
+            (void)fprintf(stderr,
+                          "%s: -e not followed by a file system path: \"%s\"\n",
+                          Pn, e);
+        return (1);
+    }
+    if (!(ec = mkstrcpy(e, (MALLOC_S *)NULL))) {
+        (void)fprintf(stderr, "%s: no space for -e string: ", Pn);
+        safestrprt(e, stderr, 1);
+        Error(ctx);
+    }
+    if (rdlnk)
+        path = ec;
+    else {
+        if (!(path = Readlink(ctx, ec)))
+            return (1);
+    }
+    /*
+     * Remove terminating `/' characters from paths longer than one.
+     */
+    for (i = (int)strlen(path); (i > 1) && (path[i - 1] == '/'); i--) {
+        path[i - 1] = '\0';
+    }
+    /*
+     * Enter file system path on list, avoiding duplicates.
+     */
+    for (ep = Efsysl; ep; ep = ep->next) {
+        if (!strcmp(ep->path, path)) {
+            (void)free((FREE_P *)path);
+            return (0);
+        }
+    }
+    if (!(ep = (efsys_list_t *)malloc((MALLOC_S)(sizeof(efsys_list_t))))) {
+        (void)fprintf(stderr, "%s: no space for \"-e %s\" entry\n", Pn, e);
+        Error(ctx);
+    }
+    ep->path = path;
+    ep->pathl = i;
+    ep->rdlnk = rdlnk;
+    ep->mp = (struct mounts *)NULL;
+    ep->next = Efsysl;
+    Efsysl = ep;
+    return (0);
+}
+#endif /* defined(HASEOPT) */
+
+/*
+ * enter_fd() - enter file descriptor list for searching
+ */
+
+int enter_fd(struct lsof_context *ctx, /* context */
+             char *f)                  /* file descriptor list pointer */
+{
+    char c, *cp1, *cp2, *dash;
+    int err, excl, hi, lo;
+    char *fc;
+    /*
+     *  Check for non-empty list and make a copy.
+     */
+    if (!f || (strlen(f) + 1) < 2) {
+        (void)fprintf(stderr, "%s: no file descriptor specified\n", Pn);
+        return (1);
+    }
+    if (!(fc = mkstrcpy(f, (MALLOC_S *)NULL))) {
+        (void)fprintf(stderr, "%s: no space for fd string: ", Pn);
+        safestrprt(f, stderr, 1);
+        Error(ctx);
+    }
+    /*
+     * Isolate each file descriptor in the comma-separated list, then enter it
+     * in the file descriptor string list.  If a descriptor has the form:
+     *
+     *	[0-9]+-[0-9]+
+     *
+     * treat it as an ascending range of file descriptor numbers.
+     *
+     * Accept a leading '^' as an excusion on match.
+     */
+    for (cp1 = fc, err = 0; *cp1;) {
+        if (*cp1 == '^') {
+            excl = 1;
+            cp1++;
+        } else
+            excl = 0;
+        for (cp2 = cp1, dash = (char *)NULL; *cp2 && *cp2 != ','; cp2++) {
+            if (*cp2 == '-')
+                dash = cp2;
+        }
+        if ((c = *cp2) != '\0')
+            *cp2 = '\0';
+        if (cp2 > cp1) {
+            if (dash) {
+                if (ckfd_range(ctx, cp1, dash, cp2, &lo, &hi))
+                    err = 1;
+                else {
+                    if (enter_fd_lst(ctx, (char *)NULL, lo, hi, excl))
+                        err = 1;
+                }
+            } else {
+                if (enter_fd_lst(ctx, cp1, 0, 0, excl))
+                    err = 1;
+            }
+        }
+        if (c == '\0')
+            break;
+        cp1 = cp2 + 1;
+    }
+    (void)free((FREE_P *)fc);
+    return (err);
+}
+
+/*
+ * enter_fd_lst() - make an entry in the FD list, Fdl
+ */
+
+static int enter_fd_lst(struct lsof_context *ctx, /* context */
+                        char *nm,                 /* FD name (none if NULL) */
+                        int lo,   /* FD low boundary (if nm NULL) */
+                        int hi,   /* FD high boundary (if nm NULL) */
+                        int excl) /* exclusion on match */
+{
+    char buf[256], *cp;
+    int n;
+    struct fd_lst *f, *ft;
+    /*
+     * Don't allow a mixture of exclusions and inclusions.
+     */
+    if (FdlTy >= 0) {
+        if (FdlTy != excl) {
+            if (!Fwarn) {
+
+                /*
+                 * If warnings are enabled, report a mixture.
+                 */
+                if (nm) {
+                    (void)snpf(buf, sizeof(buf) - 1, "%s%s", excl ? "^" : "",
+                               nm);
+                } else {
+                    if (lo != hi) {
+                        (void)snpf(buf, sizeof(buf) - 1, "%s%d-%d",
+                                   excl ? "^" : "", lo, hi);
+                    } else {
+                        (void)snpf(buf, sizeof(buf) - 1, "%s%d",
+                                   excl ? "^" : "", lo);
+                    }
+                }
+                buf[sizeof(buf) - 1] = '\0';
+                (void)fprintf(stderr, "%s: %s in an %s -d list: %s\n", Pn,
+                              excl ? "exclude" : "include",
+                              FdlTy ? "exclude" : "include", buf);
+            }
+            return (1);
+        }
+    }
+    /*
+     * Allocate an fd_lst entry.
+     */
+    if (!(f = (struct fd_lst *)malloc((MALLOC_S)sizeof(struct fd_lst)))) {
+        (void)fprintf(stderr, "%s: no space for FD list entry\n", Pn);
+        Error(ctx);
+    }
+    if (nm) {
+
+        /*
+         * Process an FD name.  First see if it contains only digits; if it
+         * does, convert them to an integer and set the low and high
+         * boundaries to the result.
+         *
+         * If the name has a non-digit, store it as a string, and set the
+         * boundaries to impossible values (i.e., low > high).
+         */
+        for (cp = nm, n = 0; *cp; cp++) {
+            if (!isdigit((unsigned char)*cp))
+                break;
+            n = (n * 10) + (int)(*cp - '0');
+        }
+        if (*cp) {
+            lo = 1;
+            hi = 0;
+            if (strcmp(nm, "unk") == 0) {
+                f->fd_type = LSOF_FD_UNKNOWN;
+            } else if (strcmp(nm, "cwd") == 0) {
+                f->fd_type = LSOF_FD_CWD;
+            } else if (strcmp(nm, "err") == 0) {
+                f->fd_type = LSOF_FD_ERROR;
+            } else if (strcmp(nm, "NOFD") == 0) {
+                f->fd_type = LSOF_FD_NOFD;
+            } else if (strcmp(nm, "rtd") == 0) {
+                f->fd_type = LSOF_FD_ROOT_DIR;
+            } else if (strcmp(nm, "pd") == 0) {
+                f->fd_type = LSOF_FD_PARENT_DIR;
+            } else if (strcmp(nm, "txt") == 0) {
+                f->fd_type = LSOF_FD_PROGRAM_TEXT;
+            } else if (strcmp(nm, "ltx") == 0) {
+                f->fd_type = LSOF_FD_LIBRARY_TEXT;
+            } else if (strcmp(nm, "mem") == 0) {
+                f->fd_type = LSOF_FD_MEMORY;
+            } else if (strcmp(nm, "DEL") == 0) {
+                f->fd_type = LSOF_FD_DELETED;
+            } else if (strcmp(nm, "fp") == 0) {
+                f->fd_type = LSOF_FD_FILEPORT;
+            } else if (strcmp(nm, "twd") == 0) {
+                f->fd_type = LSOF_FD_TASK_CWD;
+            } else if (strcmp(nm, "ctty") == 0) {
+                f->fd_type = LSOF_FD_CTTY;
+            } else if (strcmp(nm, "jd.") == 0) {
+                f->fd_type = LSOF_FD_JAIL_DIR;
+            } else if (strcmp(nm, "v86") == 0) {
+                f->fd_type = LSOF_FD_VIRTUAL_8086;
+            } else if (strcmp(nm, "m86") == 0) {
+                f->fd_type = LSOF_FD_MERGE_386;
+            } else if (strcmp(nm, "mmap") == 0) {
+                f->fd_type = LSOF_FD_MMAP_DEVICE;
+            } else if (strcmp(nm, "fd") == 0) {
+                /* pseudo fd type meaning whole range of fd */
+                f->fd_type = LSOF_FD_NUMERIC;
+                hi = INT_MAX;
+                lo = 0;
+            } else {
+                (void)fprintf(stderr,
+                              "%s: invalid fd type given in -d option\n", Pn);
+                Error(ctx);
+                return (1);
+            }
+        } else {
+            f->fd_type = LSOF_FD_NUMERIC;
+            lo = hi = n;
+        }
+    } else
+        f->fd_type = LSOF_FD_NUMERIC;
+    /*
+     * Skip duplicates.
+     */
+    for (ft = Fdl; ft; ft = ft->next) {
+        if (ft->fd_type != f->fd_type)
+            continue;
+        if (ft->fd_type == LSOF_FD_NUMERIC) {
+            if ((lo != ft->lo) || (hi != ft->hi))
+                continue;
+        }
+        (void)free((FREE_P *)f);
+        return (0);
+    }
+    /*
+     * Complete the fd_lst entry and link it to the head of the chain.
+     */
+    f->hi = hi;
+    f->lo = lo;
+    f->next = Fdl;
+    Fdl = f;
+    FdlTy = excl;
+    return (0);
+}
+
+/*
+ * enter_dir() - enter the files of a directory for searching
+ */
+
+#define EDDEFFNL 128 /* default file name length */
+
+int enter_dir(struct lsof_context *ctx, /* context */
+              char *d,                  /* directory path name pointer */
+              int descend)              /* subdirectory descend flag:
+                                         *	0 = don't descend
+                                         *	1 = descend */
+{
+    char *av[2];
+    dev_t ddev;
+    DIR *dfp;
+    char *dn = (char *)NULL;
+    MALLOC_S dnl, dnamlen;
+    struct DIRTYPE *dp;
+    int en, sl;
+    int fct = 0;
+    char *fp = (char *)NULL;
+    MALLOC_S fpl = (MALLOC_S)0;
+    MALLOC_S fpli = (MALLOC_S)0;
+    struct stat sb;
+    /*
+     * Check the directory path; reduce symbolic links; stat(2) it; make sure
+     * it's really a directory.
+     */
+    if (!d || !*d || *d == '+' || *d == '-') {
+        if (!Fwarn)
+            (void)fprintf(stderr, "%s: +d not followed by a directory path\n",
+                          Pn);
+        return (1);
+    }
+    if (!(dn = Readlink(ctx, d)))
+        return (1);
+    if (statsafely(ctx, dn, &sb)) {
+        if (!Fwarn) {
+            en = errno;
+            (void)fprintf(stderr, "%s: WARNING: can't stat(", Pn);
+            safestrprt(dn, stderr, 0);
+            (void)fprintf(stderr, "): %s\n", strerror(en));
+        }
+        if (dn && dn != d) {
+            (void)free((FREE_P *)dn);
+            dn = (char *)NULL;
+        }
+        return (1);
+    }
+    if ((sb.st_mode & S_IFMT) != S_IFDIR) {
+        if (!Fwarn) {
+            (void)fprintf(stderr, "%s: WARNING: not a directory: ", Pn);
+            safestrprt(dn, stderr, 1);
+        }
+        if (dn && dn != d) {
+            (void)free((FREE_P *)dn);
+            dn = (char *)NULL;
+        }
+        return (1);
+    }
+
+#if defined(HASSPECDEVD)
+    (void)HASSPECDEVD(ctx, dn, &sb);
+#endif /* defined(HASSPECDEVD) */
+
+    ddev = sb.st_dev;
+    /*
+     * Stack the directory and record it in Sfile for searching.
+     */
+    Dstkn = Dstkx = 0;
+    Dstk = (char **)NULL;
+    (void)stkdir(ctx, dn);
+    av[0] = (dn == d) ? mkstrcpy(dn, (MALLOC_S *)NULL) : dn;
+    av[1] = (char *)NULL;
+    dn = (char *)NULL;
+    if (!ck_file_arg(ctx, 0, 1, av, 1, 1, &sb, 0)) {
+        av[0] = (char *)NULL;
+        fct++;
+    }
+    /*
+     * Unstack the next directory and examine it.
+     */
+    while (--Dstkx >= 0) {
+        if (!(dn = Dstk[Dstkx]))
+            continue;
+        Dstk[Dstkx] = (char *)NULL;
+        /*
+         * Open the directory path and prepare its name for use with the
+         * files in the directory.
+         */
+        if (!(dfp = OpenDir(dn))) {
+            if (!Fwarn) {
+                if ((en = errno) != ENOENT) {
+                    (void)fprintf(stderr, "%s: WARNING: can't opendir(", Pn);
+                    safestrprt(dn, stderr, 0);
+                    (void)fprintf(stderr, "): %s\n", strerror(en));
+                }
+            }
+            (void)free((FREE_P *)dn);
+            dn = (char *)NULL;
+            continue;
+        }
+        dnl = strlen(dn);
+        sl = ((dnl > 0) && (*(dn + dnl - 1) == '/')) ? 0 : 1;
+        /*
+         * Define space for possible addition to the directory path.
+         */
+        fpli = (MALLOC_S)(dnl + sl + EDDEFFNL + 1);
+        if ((int)fpli > (int)fpl) {
+            fpl = fpli;
+            if (!fp)
+                fp = (char *)malloc(fpl);
+            else
+                fp = (char *)realloc(fp, fpl);
+            if (!fp) {
+                (void)fprintf(
+                    stderr,
+                    "%s: no space for path to entries in directory: %s\n", Pn,
+                    dn);
+                Error(ctx);
+            }
+        }
+        (void)snpf(fp, (size_t)fpl, "%s%s", dn, sl ? "/" : "");
+        (void)free((FREE_P *)dn);
+        dn = (char *)NULL;
+        /*
+         * Read the contents of the directory.
+         */
+        for (dp = ReadDir(dfp); dp; dp = ReadDir(dfp)) {
+
+            /*
+             * Skip: entries with no inode number;
+             *	     entries with a zero length name;
+             *	     ".";
+             *	     and "..".
+             */
+            if (!dp->d_ino)
+                continue;
+
+#if defined(HASDNAMLEN)
+            dnamlen = (MALLOC_S)dp->d_namlen;
+#else  /* !defined(HASDNAMLEN) */
+            dnamlen = (MALLOC_S)strlen(dp->d_name);
+#endif /* defined(HASDNAMLEN) */
+
+            if (!dnamlen)
+                continue;
+            if (dnamlen <= 2 && dp->d_name[0] == '.') {
+                if (dnamlen == 1)
+                    continue;
+                if (dp->d_name[1] == '.')
+                    continue;
+            }
+            /*
+             * Form the entry's path name.
+             */
+            fpli = (MALLOC_S)(dnamlen - (fpl - dnl - sl - 1));
+            if ((int)fpli > 0) {
+                fpl += fpli;
+                if (!(fp = (char *)realloc(fp, fpl))) {
+                    (void)fprintf(stderr, "%s: no space for: ", Pn);
+                    safestrprt(dn, stderr, 0);
+                    putc('/', stderr);
+                    safestrprtn(dp->d_name, dnamlen, stderr, 1);
+                    Error(ctx);
+                }
+            }
+            (void)strncpy(fp + dnl + sl, dp->d_name, dnamlen);
+            fp[dnl + sl + dnamlen] = '\0';
+            /*
+             * Lstatsafely() the entry; complain if that fails.
+             *
+             * Stack entries that represent subdirectories.
+             */
+            if (lstatsafely(ctx, fp, &sb)) {
+                if ((en = errno) != ENOENT) {
+                    if (!Fwarn) {
+                        (void)fprintf(stderr, "%s: WARNING: can't lstat(", Pn);
+                        safestrprt(fp, stderr, 0);
+                        (void)fprintf(stderr, "): %s\n", strerror(en));
+                    }
+                }
+                continue;
+            }
+
+#if defined(HASSPECDEVD)
+            (void)HASSPECDEVD(ctx, fp, &sb);
+#endif /* defined(HASSPECDEVD) */
+
+            if (!(Fxover & XO_FILESYS)) {
+
+                /*
+                 * Unless "-x" or "-x f" was specified, don't cross over file
+                 * system mount points.
+                 */
+                if (sb.st_dev != ddev)
+                    continue;
+            }
+            if ((sb.st_mode & S_IFMT) == S_IFLNK) {
+
+                /*
+                 * If this is a symbolic link and "-x_ or "-x l" was specified,
+                 * Statsafely() the entry and process it.
+                 *
+                 * Otherwise skip symbolic links.
+                 */
+                if (Fxover & XO_SYMLINK) {
+                    if (statsafely(ctx, fp, &sb)) {
+                        if ((en = errno) != ENOENT) {
+                            if (!Fwarn) {
+                                (void)fprintf(stderr,
+                                              "%s: WARNING: can't stat(", Pn);
+                                safestrprt(fp, stderr, 0);
+                                (void)fprintf(stderr, ") symbolc link: %s\n",
+                                              strerror(en));
+                            }
+                        }
+                        continue;
+                    }
+                } else
+                    continue;
+            }
+            if (av[0]) {
+                (void)free((FREE_P *)av[0]);
+                av[0] = (char *)NULL;
+            }
+            av[0] = mkstrcpy(fp, (MALLOC_S *)NULL);
+            if ((sb.st_mode & S_IFMT) == S_IFDIR && descend)
+
+                /*
+                 * Stack a subdirectory according to the descend argument.
+                 */
+                stkdir(ctx, av[0]);
+            /*
+             * Use ck_file_arg() to record the entry for searching.  Force it
+             * to consider the entry a file, not a file system.
+             */
+            if (!ck_file_arg(ctx, 0, 1, av, 1, 1, &sb, 0)) {
+                av[0] = (char *)NULL;
+                fct++;
+            }
+        }
+        (void)CloseDir(dfp);
+        if (dn && dn != d) {
+            (void)free((FREE_P *)dn);
+            dn = (char *)NULL;
+        }
+    }
+    /*
+     * Free malloc()'d space.
+     */
+    if (dn && dn != d) {
+        (void)free((FREE_P *)dn);
+        dn = (char *)NULL;
+    }
+    if (av[0] && av[0] != fp) {
+        (void)free((FREE_P *)av[0]);
+        av[0] = (char *)NULL;
+    }
+    if (fp) {
+        (void)free((FREE_P *)fp);
+        fp = (char *)NULL;
+    }
+    if (Dstk) {
+        (void)free((FREE_P *)Dstk);
+        Dstk = (char **)NULL;
+    }
+    if (!fct) {
+
+        /*
+         * Warn if no files were recorded for searching.
+         */
+        if (!Fwarn) {
+            (void)fprintf(stderr,
+                          "%s: WARNING: no files found in directory: ", Pn);
+            safestrprt(d, stderr, 1);
+        }
+        return (1);
+    }
+    return (0);
+}
+
+/*
+ * enter_id() - enter PGID or PID for searching
+ */
+
+int enter_id(struct lsof_context *ctx, /* context */
+             enum IDType ty,           /* type: PGID or PID */
+             char *p)                  /* process group ID string pointer */
+{
+    char *cp;
+    int err, i, id, j, mx, n, ni, nx, x;
+    struct int_lst *s;
+
+    if (!p) {
+        (void)fprintf(stderr, "%s: no process%s ID specified\n", Pn,
+                      (ty == PGID) ? " group" : "");
+        return (1);
+    }
+    /*
+     * Convert and store the ID.
+     */
+    for (cp = p, err = 0; *cp;) {
+
+        /*
+         * Assemble ID.
+         */
+        for (i = id = x = 0; *cp && *cp != ','; cp++) {
+            if (!i) {
+                i = 1;
+                if (*cp == '^') {
+                    x = 1;
+                    continue;
+                }
+            }
+
+#if defined(__STDC__)
+            if (!isdigit((unsigned char)*cp))
+#else  /* !defined(__STDC__) */
+            if (!isascii(*cp) || !isdigit((unsigned char)*cp))
+#endif /* __STDC__ */
+
+            {
+                (void)fprintf(stderr, "%s: illegal process%s ID: ", Pn,
+                              (ty == PGID) ? " group" : "");
+                safestrprt(p, stderr, 1);
+                return (1);
+            }
+            id = (id * 10) + *cp - '0';
+        }
+        if (*cp)
+            cp++;
+        if (ty == PGID) {
+            if (lsof_select_pgid(ctx, id, x)) {
+                err = 1;
+            }
+        } else {
+            if (lsof_select_pid(ctx, id, x)) {
+                err = 1;
+            }
+        }
+    }
+    return (err);
+}
+
+/*
+ * enter_network_address() - enter Internet address for searching
+ */
+
+int enter_network_address(struct lsof_context *ctx, /* context */
+                          char *na) /* Internet address string pointer */
+{
+    int ae, i, pr;
+    int ep = -1;
+    int ft = 0;
+    struct hostent *he = (struct hostent *)NULL;
+    char *hn = (char *)NULL;
+    MALLOC_S l;
+    struct nwad n;
+    char *p, *wa;
+    int pt = 0;
+    int pu = 0;
+    struct servent *se, *se1;
+    char *sn = (char *)NULL;
+    int sp = -1;
+    MALLOC_S snl = 0;
+
+#if defined(HASIPv6)
+    char *cp;
+#endif /* defined(HASIPv6) */
+
+    if (!na) {
+        (void)fprintf(stderr, "%s: no network address specified\n", Pn);
+        return (1);
+    }
+    zeromem((char *)&n, sizeof(n));
+    wa = na;
+    /*
+     * Process an IP version type specification, IPv4 or IPv6, optionally
+     * followed by a '@' and a host name or Internet address, or a ':' and a
+     * service name or port number.
+     */
+    if ((*wa == '4') || (*wa == '6')) {
+        if (*wa == '4')
+            ft = 4;
+        else if (*wa == '6') {
+
+#if defined(HASIPv6)
+            ft = 6;
+#else  /* !defined(HASIPv6) */
+            (void)fprintf(stderr, "%s: IPv6 not supported: -i ", Pn);
+            safestrprt(na, stderr, 1);
+            goto nwad_exit;
+#endif /* defined(HASIPv6) */
+        }
+        wa++;
+        if (!*wa) {
+
+            /*
+             * If nothing follows 4 or 6, then all network files of the
+             * specified IP version are selected.  Sequential -i, -i4, and
+             * -i6 specifications interact logically -- e.g., -i[46] followed
+             * by -i[64] is the same as -i.
+             */
+            if (!Fnet) {
+                Fnet = 1;
+                FnetTy = ft;
+            } else {
+                if (FnetTy) {
+                    if (FnetTy != ft)
+                        FnetTy = 0;
+                } else
+                    FnetTy = ft;
+            }
+            return (0);
+        }
+    } else if (Fnet)
+        ft = FnetTy;
+    /*
+     * If an IP version has been specified, use it to set the address family.
+     */
+    switch (ft) {
+    case 4:
+        n.af = AF_INET;
+        break;
+
+#if defined(HASIPv6)
+    case 6:
+        n.af = AF_INET6;
+        break;
+#endif /* defined(HASIPv6) */
+    }
+    /*
+     * Process protocol name, optionally followed by a '@' and a host name or
+     * Internet address, or a ':' and a service name or port number.
+     */
+    if (*wa && *wa != '@' && *wa != ':') {
+        for (p = wa; *wa && *wa != '@' && *wa != ':'; wa++)
+            ;
+        if ((l = wa - p)) {
+            if (!(n.proto = mkstrcat(p, l, (char *)NULL, -1, (char *)NULL, -1,
+                                     (MALLOC_S *)NULL))) {
+                (void)fprintf(stderr,
+                              "%s: no space for protocol name from: -i ", Pn);
+                safestrprt(na, stderr, 1);
+            nwad_exit:
+                if (n.proto)
+                    (void)free((FREE_P *)n.proto);
+                if (hn)
+                    (void)free((FREE_P *)hn);
+                if (sn)
+                    (void)free((FREE_P *)sn);
+                return (1);
+            }
+            /*
+             * The protocol name should be "tcp", "udp" or "udplite".
+             */
+            if ((strcasecmp(n.proto, "tcp") != 0) &&
+                (strcasecmp(n.proto, "udp") != 0) &&
+                (strcasecmp(n.proto, "udplite") != 0)) {
+                (void)fprintf(stderr, "%s: unknown protocol name (%s) in: -i ",
+                              Pn, n.proto);
+                safestrprt(na, stderr, 1);
+                goto nwad_exit;
+            }
+            /*
+             * Convert protocol name to lower case.
+             */
+            for (p = n.proto; *p; p++) {
+                if (*p >= 'A' && *p <= 'Z')
+                    *p = *p - 'A' + 'a';
+            }
+        }
+    }
+    /*
+     * Process an IPv4 address (1.2.3.4), IPv6 address ([1:2:3:4:5:6:7:8]),
+     * or host name, preceded by a '@' and optionally followed by a colon
+     * and a service name or port number.
+     */
+    if (*wa == '@') {
+        wa++;
+        if (!*wa || *wa == ':') {
+
+#if defined(HASIPv6)
+        unacc_address:
+#endif /* defined(HASIPv6) */
+
+            (void)fprintf(stderr, "%s: unacceptable Internet address in: -i ",
+                          Pn);
+            safestrprt(na, stderr, 1);
+            goto nwad_exit;
+        }
+
+        if ((p = isIPv4addr(wa, n.a, sizeof(n.a)))) {
+
+            /*
+             * Process IPv4 address.
+             */
+            if (ft == 6) {
+                (void)fprintf(stderr, "%s: IPv4 addresses are prohibited: -i ",
+                              Pn);
+                safestrprt(na, stderr, 1);
+                goto nwad_exit;
+            }
+            wa = p;
+            n.af = AF_INET;
+        } else if (*wa == '[') {
+
+#if defined(HASIPv6)
+            /*
+             * Make sure IPv6 addresses are permitted.  If they are, assemble
+             * one.
+             */
+            if (ft == 4) {
+                (void)fprintf(stderr, "%s: IPv6 addresses are prohibited: -i ",
+                              Pn);
+                safestrprt(na, stderr, 1);
+                goto nwad_exit;
+            }
+            if (!(cp = strrchr(++wa, ']')))
+                goto unacc_address;
+            *cp = '\0';
+            i = inet_pton(AF_INET6, wa, (void *)&n.a);
+            *cp = ']';
+            if (i != 1)
+                goto unacc_address;
+            for (ae = i = 0; i < MAX_AF_ADDR; i++) {
+                if ((ae |= n.a[i]))
+                    break;
+            }
+            if (!ae)
+                goto unacc_address;
+            if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)&n.a[0])) {
+                if (ft == 6) {
+                    (void)fprintf(stderr,
+                                  "%s: IPv4 addresses are prohibited: -i ", Pn);
+                    safestrprt(na, stderr, 1);
+                    goto nwad_exit;
+                }
+                for (i = 0; i < 4; i++) {
+                    n.a[i] = n.a[i + 12];
+                }
+                n.af = AF_INET;
+            } else
+                n.af = AF_INET6;
+            wa = cp + 1;
+#else  /* !defined(HASIPv6) */
+            (void)fprintf(stderr, "%s: unsupported IPv6 address in: -i ", Pn);
+            safestrprt(na, stderr, 1);
+            goto nwad_exit;
+#endif /* defined(HASIPv6) */
+
+        } else {
+
+            /*
+             * Assemble host name.
+             */
+            for (p = wa; *p && *p != ':'; p++)
+                ;
+            if ((l = p - wa)) {
+                if (!(hn = mkstrcat(wa, l, (char *)NULL, -1, (char *)NULL, -1,
+                                    (MALLOC_S *)NULL))) {
+                    (void)fprintf(stderr, "%s: no space for host name: -i ",
+                                  Pn);
+                    safestrprt(na, stderr, 1);
+                    goto nwad_exit;
+                }
+
+#if defined(HASIPv6)
+
+                /*
+                 * If no IP version has been specified, look up an IPv6 host
+                 * name first.  If that fails, look up an IPv4 host name.
+                 *
+                 * If the IPv6 version has been specified, look up the host
+                 * name only under its IP version specification.
+                 */
+                if (!ft)
+                    n.af = AF_INET6;
+                if (!(he = lkup_hostnm(hn, &n)) && !ft) {
+                    n.af = AF_INET;
+                    he = lkup_hostnm(hn, &n);
+                }
+#else  /* !defined(HASIPv6) */
+                if (!ft)
+                    n.af = AF_INET;
+                he = lkup_hostnm(hn, &n);
+#endif /* defined(HASIPv6) */
+
+                if (!he) {
+                    fprintf(stderr, "%s: unknown host name (%s) in: -i ", Pn,
+                            hn);
+                    safestrprt(na, stderr, 1);
+                    goto nwad_exit;
+                }
+            }
+            wa = p;
+        }
+    }
+    /*
+     * If there is no port number, enter the address.
+     */
+    if (!*wa)
+        goto nwad_enter;
+    /*
+     * Process a service name or port number list, preceded by a colon.
+     *
+     * Entries of the list are separated with commas; elements of a numeric
+     * range are specified with a separating minus sign (`-'); all service names
+     * must belong to the same protocol; embedded spaces are not allowed.  An
+     * embedded minus sign in a name is taken to be part of the name, the
+     * starting entry of a range can't be a service name.
+     */
+    if (*wa != ':' || *(wa + 1) == '\0') {
+
+    unacc_port:
+        (void)fprintf(stderr, "%s: unacceptable port specification in: -i ",
+                      Pn);
+        safestrprt(na, stderr, 1);
+        goto nwad_exit;
+    }
+    for (++wa; wa && *wa; wa++) {
+        for (ep = pr = sp = 0; *wa; wa++) {
+            if (*wa < '0' || *wa > '9') {
+
+                /*
+                 * Convert service name to port number, using already-specified
+                 * protocol name.  A '-' is taken to be part of the name; hence
+                 * the starting entry of a range can't be a service name.
+                 */
+                for (p = wa; *wa && *wa != ','; wa++)
+                    ;
+                if (!(l = wa - p)) {
+                    (void)fprintf(stderr, "%s: invalid service name: -i ", Pn);
+                    safestrprt(na, stderr, 1);
+                    goto nwad_exit;
+                }
+                if (sn) {
+                    if (l > snl) {
+                        sn = (char *)realloc((MALLOC_P *)sn, l + 1);
+                        snl = l;
+                    }
+                } else {
+                    sn = (char *)malloc(l + 1);
+                    snl = l;
+                }
+                if (!sn) {
+                    (void)fprintf(stderr, "%s: no space for service name: -i ",
+                                  Pn);
+                    safestrprt(na, stderr, 1);
+                    goto nwad_exit;
+                }
+                (void)strncpy(sn, p, l);
+                *(sn + l) = '\0';
+                if (n.proto) {
+
+                    /*
+                     * If the protocol has been specified, look up the port
+                     * number for the service name for the specified protocol.
+                     */
+                    if (!(se = getservbyname(sn, n.proto))) {
+                        (void)fprintf(stderr,
+                                      "%s: unknown service %s for %s in: -i ",
+                                      Pn, sn, n.proto);
+                        safestrprt(na, stderr, 1);
+                        goto nwad_exit;
+                    }
+                    pt = (int)ntohs(se->s_port);
+                } else {
+
+                    /*
+                     * If no protocol has been specified, look up the port
+                     * numbers for the service name for both TCP and UDP.
+                     */
+                    if ((se = getservbyname(sn, "tcp")))
+                        pt = (int)ntohs(se->s_port);
+                    if ((se1 = getservbyname(sn, "udp")))
+                        pu = (int)ntohs(se1->s_port);
+                    if (!se && !se1) {
+                        (void)fprintf(stderr, "%s: unknown service %s in: -i ",
+                                      Pn, sn);
+                        safestrprt(na, stderr, 1);
+                        goto nwad_exit;
+                    }
+                    if (se && se1 && pt != pu) {
+                        (void)fprintf(
+                            stderr,
+                            "%s: TCP=%d and UDP=%d %s ports conflict;\n", Pn,
+                            pt, pu, sn);
+                        (void)fprintf(
+                            stderr,
+                            "      specify \"tcp:%s\" or \"udp:%s\": -i ", sn,
+                            sn);
+                        safestrprt(na, stderr, 1);
+                        goto nwad_exit;
+                    }
+                    if (!se && se1)
+                        pt = pu;
+                }
+                if (pr)
+                    ep = pt;
+                else {
+                    sp = pt;
+                    if (*wa == '-')
+                        pr++;
+                }
+            } else {
+
+                /*
+                 * Assemble port number.
+                 */
+                for (; *wa && *wa != ','; wa++) {
+                    if (*wa == '-') {
+                        if (pr)
+                            goto unacc_port;
+                        pr++;
+                        break;
+                    }
+                    if (*wa < '0' || *wa > '9')
+                        goto unacc_port;
+                    if (pr)
+                        ep = (ep * 10) + *wa - '0';
+                    else
+                        sp = (sp * 10) + *wa - '0';
+                }
+            }
+            if (!*wa || *wa == ',')
+                break;
+            if (pr)
+                continue;
+            goto unacc_port;
+        }
+        if (!pr)
+            ep = sp;
+        if (ep < sp)
+            goto unacc_port;
+        /*
+         * Enter completed port or port range specification.
+         */
+
+    nwad_enter:
+
+        for (i = 1; i;) {
+            if (enter_nwad(ctx, &n, sp, ep, na, he))
+                goto nwad_exit;
+
+#if defined(HASIPv6)
+            /*
+             * If IPv6 is enabled, a host name was specified, and the
+             * associated * address is for the AF_INET6 address family,
+             * try to get and address for the AF_INET family, too, unless
+             * IPv4 is prohibited.
+             */
+            if (hn && (n.af == AF_INET6) && (ft != 6)) {
+                n.af = AF_INET;
+                if ((he = lkup_hostnm(hn, &n)))
+                    continue;
+            }
+#endif /* defined(HASIPv6) */
+
+            i = 0;
+        }
+        if (!*wa)
+            break;
+    }
+    if (sn)
+        (void)free((FREE_P *)sn);
+    return (0);
+}
+
+/*
+ * enter_nwad() - enter nwad structure
+ */
+
+static int enter_nwad(struct lsof_context *ctx, /* context */
+                      struct nwad *n,     /* pointer to partially completed
+                                           * nwad (less port) */
+                      int sp,             /* starting port number */
+                      int ep,             /* ending port number */
+                      char *s,            /* string that states the address */
+                      struct hostent *he) /* pointer to hostent struct from
+                                           * which network address came */
+{
+    int ac;
+    unsigned char *ap;
+    static int na = 0;
+    struct nwad nc;
+    struct nwad *np;
+    /*
+     * Allocate space for the argument specification.
+     */
+    if (strlen(s)) {
+        if (!(n->arg = mkstrcpy(s, (MALLOC_S *)NULL))) {
+            (void)fprintf(stderr, "%s: no space for Internet argument: -i ",
+                          Pn);
+            safestrprt(s, stderr, 1);
+            Error(ctx);
+        }
+    } else
+        n->arg = (char *)NULL;
+    /*
+     * Loop through all hostent addresses.
+     */
+    for (ac = 1, nc = *n;;) {
+
+        /*
+         * Test address specification -- it must contain at least one of:
+         * protocol, Internet address or port.  If correct, link into search
+         * list.
+         */
+        if (!nc.proto && !nc.a[0] && !nc.a[1] && !nc.a[2] && !nc.a[3]
+
+#if defined(HASIPv6)
+            && (nc.af != AF_INET6 ||
+                (!nc.a[4] && !nc.a[5] && !nc.a[6] && !nc.a[7] && !nc.a[8] &&
+                 !nc.a[9] && !nc.a[10] && !nc.a[11] && !nc.a[12] && !nc.a[13] &&
+                 !nc.a[14] && !nc.a[15]))
+#endif /* defined(HASIPv6) */
+
+            && sp == -1) {
+            (void)fprintf(stderr,
+                          "%s: incomplete Internet address specification: -i ",
+                          Pn);
+            safestrprt(s, stderr, 1);
+            return (1);
+        }
+        /*
+         * Limit the network address chain length to MAXNWAD for reasons of
+         * search efficiency.
+         */
+        if (na >= MAXNWAD) {
+            (void)fprintf(stderr,
+                          "%s: network address limit (%d) exceeded: -i ", Pn,
+                          MAXNWAD);
+            safestrprt(s, stderr, 1);
+            return (1);
+        }
+        /*
+         * Allocate space for the address specification.
+         */
+        if ((np = (struct nwad *)malloc(sizeof(struct nwad))) == NULL) {
+            (void)fprintf(stderr, "%s: no space for network address from: -i ",
+                          Pn);
+            safestrprt(s, stderr, 1);
+            return (1);
+        }
+        /*
+         * Construct and link the address specification.
+         */
+        *np = nc;
+        np->sport = sp;
+        np->eport = ep;
+        np->f = 0;
+        np->next = Nwad;
+        Nwad = np;
+        na++;
+        /*
+         * If the network address came from gethostbyname(), advance to
+         * the next address; otherwise quit.
+         */
+        if (!he)
+            break;
+        if (!he->h_addr_list[ac -
+                             1]) /* Check if address list ended prematurely */
+            break;
+        if (!(ap = (unsigned char *)he->h_addr_list[ac++]))
+            break;
+
+#if defined(HASIPv6)
+        {
+            int i;
+
+            for (i = 0; (i < (he->h_length - 1)) && (i < (MAX_AF_ADDR - 1));
+                 i++) {
+                nc.a[i] = *ap++;
+            }
+            nc.a[i] = *ap;
+        }
+#else  /* !defined(HASIPv6) */
+        nc.a[0] = *ap++;
+        nc.a[1] = *ap++;
+        nc.a[2] = *ap++;
+        nc.a[3] = *ap;
+#endif /* defined(HASIPv6) */
+    }
+    return (0);
+}
+
+#if defined(HASTCPUDPSTATE)
+/*
+ * enter_state_spec() -- enter TCP and UDP state specifications
+ */
+
+int enter_state_spec(struct lsof_context *ctx,
+                     char *ss) /* state specification string */
+{
+    char *cp, *ne, *ns, *pr;
+    int err, d, f, i, tx, x;
+    static char *ssc = (char *)NULL;
+    char *ty;
+    /*
+     * Check the protocol specification.
+     */
+    if (!strncasecmp(ss, "tcp:", 4)) {
+        pr = "TCP";
+        tx = 0;
+    }
+
+#    if !defined(USE_LIB_PRINT_TCPTPI)
+    else if (!strncasecmp(ss, "UDP:", 4)) {
+        pr = "UDP";
+        tx = 1;
+    }
+
+#    endif /* !defined(USE_LIB_PRINT_TCPTPI) */
+
+    else {
+        (void)fprintf(stderr, "%s: unknown -s protocol: \"%s\"\n", Pn, ss);
+        return (1);
+    }
+    cp = ss + 4;
+    if (!*cp) {
+        (void)fprintf(stderr, "%s: no %s state names in: %s\n", Pn, pr, ss);
+        return (1);
+    }
+    (void)build_IPstates(ctx);
+    if (!(tx ? UdpSt : TcpSt)) {
+        (void)fprintf(stderr, "%s: no %s state names available: %s\n", Pn, pr,
+                      ss);
+        return (1);
+    }
+    /*
+     * Allocate the inclusion and exclusion tables for the protocol.
+     */
+    if (tx) {
+        if (UdpNstates) {
+            if (!UdpStI) {
+                if (!(UdpStI = (unsigned char *)calloc(
+                          (MALLOC_S)UdpNstates, sizeof(unsigned char)))) {
+                    ty = "UDP state inclusion";
+
+                no_IorX_space:
+
+                    (void)fprintf(stderr, "%s: no %s table space\n", Pn, ty);
+                    Error(ctx);
+                }
+            }
+            if (!UdpStX) {
+                if (!(UdpStX = (unsigned char *)calloc(
+                          (MALLOC_S)UdpNstates, sizeof(unsigned char)))) {
+                    ty = "UDP state exclusion";
+                    goto no_IorX_space;
+                }
+            }
+        }
+    } else {
+        if (TcpNstates) {
+            if (!TcpStI) {
+                if (!(TcpStI = (unsigned char *)calloc(
+                          (MALLOC_S)TcpNstates, sizeof(unsigned char)))) {
+                    ty = "TCP state inclusion";
+                    goto no_IorX_space;
+                }
+            }
+            if (!TcpStX) {
+                if (!(TcpStX = (unsigned char *)calloc(
+                          (MALLOC_S)TcpNstates, sizeof(unsigned char)))) {
+                    ty = "TCP state exclusion";
+                    goto no_IorX_space;
+                }
+            }
+        }
+    }
+    /*
+     * Convert the state names in the rest of the string to state indexes and
+     * record them in the appropriate inclusion or exclusion table.
+     */
+    if (ssc)
+        (void)free((MALLOC_P *)ssc);
+    if (!(ssc = mkstrcpy(cp, (MALLOC_S *)NULL))) {
+        (void)fprintf(stderr, "%s: no temporary state argument space for: %s\n",
+                      Pn, ss);
+        Error(ctx);
+    }
+    cp = ssc;
+    err = 0;
+    while (*cp) {
+
+        /*
+         * Determine inclusion or exclusion for this state name.
+         */
+        if (*cp == '^') {
+            x = 1;
+            cp++;
+        } else
+            x = 0;
+        /*
+         * Find the end of the state name.  Make sure it is non-null in length
+         * and terminated with '\0'.
+         */
+        ns = cp;
+        while (*cp && (*cp != ',')) {
+            cp++;
+        }
+        ne = cp;
+        if (*cp) {
+            *cp = '\0';
+            cp++;
+        }
+        if (!(size_t)(ne - ns)) {
+            (void)fprintf(stderr, "%s: NULL %s state name in: %s\n", Pn, pr,
+                          ss);
+            err = 1;
+            continue;
+        }
+        /*
+         * Find the state name in the appropriate table.
+         */
+        f = 0;
+        if (tx) {
+            if (UdpSt) {
+                for (i = 0; i < UdpNstates; i++) {
+                    if (!strcasecmp(ns, UdpSt[i])) {
+                        f = 1;
+                        break;
+                    }
+                }
+            }
+        } else {
+            if (TcpSt) {
+                for (i = 0; i < TcpNstates; i++) {
+                    if (!strcasecmp(ns, TcpSt[i])) {
+                        f = 1;
+                        break;
+                    }
+                }
+            }
+        }
+        if (!f) {
+            (void)fprintf(stderr, "%s: unknown %s state name: %s\n", Pn, pr,
+                          ns);
+            err = 1;
+            continue;
+        }
+        /*
+         * Set the inclusion or exclusion status in the appropriate table.
+         */
+        d = 0;
+        if (x) {
+            if (tx) {
+                if (!UdpStX[i]) {
+                    UdpStX[i] = 1;
+                    UdpStXn++;
+                } else
+                    d = 1;
+            } else {
+                if (!TcpStX[i]) {
+                    TcpStX[i] = 1;
+                    TcpStXn++;
+                } else
+                    d = 1;
+            }
+        } else {
+            if (tx) {
+                if (!UdpStI[i]) {
+                    UdpStI[i] = 1;
+                    UdpStIn++;
+                } else
+                    d = 1;
+            } else {
+                if (!TcpStI[i]) {
+                    TcpStI[i] = 1;
+                    TcpStIn++;
+                } else
+                    d = 1;
+            }
+        }
+        if (d) {
+
+            /*
+             * Report a duplicate.
+             */
+            (void)fprintf(stderr, "%s: duplicate %s %sclusion: %s\n", Pn, pr,
+                          x ? "ex" : "in", ns);
+            err = 1;
+        }
+    }
+    /*
+     * Release any temporary space and return.
+     */
+    if (ssc) {
+        (void)free((MALLOC_P *)ssc);
+        ssc = (char *)NULL;
+    }
+    return (err);
+}
+#endif /* defined(HASTCPUDPSTATE) */
+
+/*
+ * enter_cmd() - enter -c option
+ */
+
+int enter_cmd(struct lsof_context *ctx, /* context */
+              char *opt,                /* option name */
+              char *s)                  /* string to enter */
+{
+    char *cp;
+    short x;
+    MALLOC_S len;
+    struct str_lst *lpt;
+
+    if (!s || *s == '-' || *s == '+') {
+        (void)fprintf(stderr, "%s: missing %s option value\n", Pn, opt);
+        return (1);
+    }
+    if (*s == '^') {
+        x = 1;
+        s++;
+    } else {
+        x = 0;
+    }
+    if (lsof_select_process(ctx, s, x) != LSOF_SUCCESS) {
+        return 1;
+    }
+    return 0;
+}
+
+/*
+ * enter_uid() - enter User Identifier for searching
+ */
+
+int enter_uid(struct lsof_context *ctx, /* context */
+              char *us)                 /* User IDentifier string pointer */
+{
+    int err, i, j, lnml, nn;
+    unsigned char excl;
+    MALLOC_S len;
+    char lnm[LOGINML + 1], *lp;
+    struct passwd *pw;
+    char *s, *st;
+    uid_t uid;
+
+    if (!us) {
+        (void)fprintf(stderr, "%s: no UIDs specified\n", Pn);
+        return (1);
+    }
+    for (err = 0, s = us; *s;) {
+
+        /*
+         * Assemble next User IDentifier.
+         */
+        for (excl = i = j = lnml = nn = uid = 0, st = s; *s && *s != ',';
+             i++, s++) {
+            if (lnml >= LOGINML) {
+                while (*s && *s != ',') {
+                    s++;
+                    lnml++;
+                }
+                (void)fprintf(stderr, "%s: -u login name > %d characters: ", Pn,
+                              (int)LOGINML);
+                safestrprtn(st, lnml, stderr, 1);
+                err = j = 1;
+                break;
+            }
+            if (i == 0 && *s == '^') {
+                excl = 1;
+                continue;
+            }
+            lnm[lnml++] = *s;
+            if (nn)
+                continue;
+
+#if defined(__STDC__)
+            if (isdigit((unsigned char)*s))
+#else  /* !defined(__STDC__) */
+            if (isascii(*s) && isdigit((unsigned char)*s))
+#endif /* defined(__STDC__) */
+
+                uid = (uid * 10) + *s - '0';
+            else
+                nn++;
+        }
+        if (*s)
+            s++;
+        if (j)
+            continue;
+        if (nn) {
+            lnm[lnml++] = '\0';
+            if ((pw = getpwnam(lnm)) == NULL) {
+                (void)fprintf(stderr, "%s: can't get UID for ", Pn);
+                safestrprt(lnm, stderr, 1);
+                err = 1;
+                continue;
+            } else
+                uid = pw->pw_uid;
+        }
+
+#if defined(HASSECURITY) && !defined(HASNOSOCKSECURITY)
+        /*
+         * If the security mode is enabled, only the root user may list files
+         * belonging to user IDs other than the real user ID of this lsof
+         * process.  If HASNOSOCKSECURITY is also defined, then anyone may
+         * list anyone else's socket files.
+         */
+        if (Myuid && uid != Myuid) {
+            (void)fprintf(
+                stderr,
+                "%s: ID %d request rejected because of security mode.\n", Pn,
+                uid);
+            err = 1;
+            continue;
+        }
+#endif /* defined(HASSECURITY)  && !defined(HASNOSOCKSECURITY) */
+
+        if (nn) {
+            if (lsof_select_login(ctx, lnm, excl)) {
+                Error(ctx);
+                return (1);
+            }
+        } else {
+            if (lsof_select_uid(ctx, uid, excl)) {
+                Error(ctx);
+                return (1);
+            }
+        }
+    }
+    return (err);
+}
+
+/*
+ * isIPv4addr() - is host name an IPv4 address
+ */
+
+static char *isIPv4addr(char *hn,         /* host name */
+                        unsigned char *a, /* address receptor */
+                        int al)           /* address receptor length */
+{
+    int dc = 0;          /* dot count */
+    int i;               /* temporary index */
+    int ov[MIN_AF_ADDR]; /* octet values */
+    int ovx = 0;         /* ov[] index */
+                         /*
+                          * The host name must begin with a number and the return octet value
+                          * arguments must be acceptable.
+                          */
+    if ((*hn < '0') || (*hn > '9'))
+        return ((char *)NULL);
+    if (!a || (al < MIN_AF_ADDR))
+        return ((char *)NULL);
+    /*
+     * Start the first octet assembly, then parse tge remainder of the host
+     * name for four octets, separated by dots.
+     */
+    ov[0] = (int)(*hn++ - '0');
+    while (*hn && (*hn != ':')) {
+        if (*hn == '.') {
+
+            /*
+             * Count a dot.  Make sure a preceding octet value has been
+             * assembled.  Don't assemble more than MIN_AF_ADDR octets.
+             */
+            dc++;
+            if ((ov[ovx] < 0) || (ov[ovx] > 255))
+                return ((char *)NULL);
+            if (++ovx > (MIN_AF_ADDR - 1))
+                return ((char *)NULL);
+            ov[ovx] = -1;
+        } else if ((*hn >= '0') && (*hn <= '9')) {
+
+            /*
+             * Assemble an octet.
+             */
+            if (ov[ovx] < 0)
+                ov[ovx] = (int)(*hn - '0');
+            else
+                ov[ovx] = (ov[ovx] * 10) + (int)(*hn - '0');
+        } else {
+
+            /*
+             * A non-address character has been detected.
+             */
+            return ((char *)NULL);
+        }
+        hn++;
+    }
+    /*
+     * Make sure there were three dots and four non-null octets.
+     */
+    if ((dc != 3) || (ovx != (MIN_AF_ADDR - 1)) || (ov[ovx] < 0) ||
+        (ov[ovx] > 255))
+        return ((char *)NULL);
+    /*
+     * Copy the octets as unsigned characters and return the ending host name
+     * character position.
+     */
+    for (i = 0; i < MIN_AF_ADDR; i++) {
+        a[i] = (unsigned char)ov[i];
+    }
+    return (hn);
+}
+
+/*
+ * lkup_hostnm() - look up host name
+ */
+
+static struct hostent *
+lkup_hostnm(char *hn,       /* host name */
+            struct nwad *n) /* network address destination */
+{
+    unsigned char *ap;
+    struct hostent *he;
+    int ln;
+    /*
+     * Get hostname structure pointer.  Return NULL if there is none.
+     */
+
+#if defined(HASIPv6)
+    he = gethostbyname2(hn, n->af);
+#else  /* !defined(HASIPv6) */
+    he = gethostbyname(hn);
+#endif /* defined(HASIPv6) */
+
+    if (!he || !he->h_addr)
+        return (he);
+        /*
+         * Copy first hostname structure address to destination structure.
+         */
+
+#if defined(HASIPv6)
+    if (n->af != he->h_addrtype)
+        return ((struct hostent *)NULL);
+    if (n->af == AF_INET6) {
+
+        /*
+         * Copy an AF_INET6 address.
+         */
+        if (he->h_length > MAX_AF_ADDR)
+            return ((struct hostent *)NULL);
+        (void)memcpy((void *)&n->a[0], (void *)he->h_addr, he->h_length);
+        if ((ln = MAX_AF_ADDR - he->h_length) > 0)
+            zeromem((char *)&n->a[he->h_length], ln);
+        return (he);
+    }
+#endif /* defined(HASIPv6) */
+
+    /*
+     * Copy an AF_INET address.
+     */
+    if (he->h_length != 4)
+        return ((struct hostent *)NULL);
+    ap = (unsigned char *)he->h_addr;
+    n->a[0] = *ap++;
+    n->a[1] = *ap++;
+    n->a[2] = *ap++;
+    n->a[3] = *ap;
+    if ((ln = MAX_AF_ADDR - 4) > 0)
+        zeromem((char *)&n->a[4], ln);
+    return (he);
+}
diff --git a/src/cli.h b/src/cli.h
new file mode 100644
index 0000000..8c9dfdd
--- /dev/null
+++ b/src/cli.h
@@ -0,0 +1,37 @@
+/*
+ * cli.h - header file for lsof cli
+ */
+
+/*
+ * 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.
+ */
+
+#if !defined(CLI_H)
+#    define CLI_H
+
+#    include "lsof.h"
+#    include "proto.h"
+
+#endif
\ No newline at end of file
diff --git a/src/dialects/linux/dprint.c b/src/dialects/linux/dprint.c
new file mode 100644
index 0000000..f8d8422
--- /dev/null
+++ b/src/dialects/linux/dprint.c
@@ -0,0 +1,199 @@
+/*
+ * dprint.c - Linux printing functions for /proc-based lsof
+ */
+
+/*
+ * 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.
+ */
+
+#include "common.h"
+#include "cli.h"
+
+#if defined(HASSOSTATE)
+#    include <linux/net.h> /* for SS_* */
+#endif                     /* defined(HASSOSTATE) */
+
+#if defined(HASSOSTATE)
+static char *socket_state_to_str(struct lsof_context *ctx, unsigned int ss);
+#endif /* defined(HASSOSTATE) */
+
+/*
+ * print_unix() - print state of UNIX domain socket e.g. UNCONNECTED
+ */
+static void print_unix(struct lsof_context *ctx, int nl) {
+    if (Ftcptpi & TCPTPI_STATE) {
+#if defined(HASSOSTATE) && defined(HASSOOPT)
+        char *cp = (Lf->lts.opt == __SO_ACCEPTCON)
+                       ? "LISTEN"
+                       : socket_state_to_str(ctx, Lf->lts.ss);
+
+        if (Ffield)
+            (void)printf("%cST=%s%c", LSOF_FID_TCPTPI, cp, Terminator);
+        else {
+            putchar('(');
+            (void)fputs(cp, stdout);
+            putchar(')');
+        }
+#endif /* defined(HASSOSTATE) && defined(HASSOOPT) */
+    }
+    if (nl)
+        putchar('\n');
+}
+
+/*
+ * print_tcptpi() - print TCP/TPI state e.g. ESTBALISHED
+ */
+void print_tcptpi(struct lsof_context *ctx, /* context */
+                  int nl)                   /* 1 == '\n' required */
+{
+    char buf[128];
+    char *cp = (char *)NULL;
+    int ps = 0;
+    int s;
+
+    if (Lf->type == LSOF_FILE_UNIX) {
+        print_unix(ctx, nl);
+        return;
+    }
+    if ((Ftcptpi & TCPTPI_STATE) && Lf->lts.type == 0) {
+        if (!TcpSt)
+            (void)build_IPstates(ctx);
+        if ((s = Lf->lts.state.i + TcpStOff) < 0 || s >= TcpNstates) {
+            (void)snpf(buf, sizeof(buf), "UNKNOWN_TCP_STATE_%d",
+                       Lf->lts.state.i);
+            cp = buf;
+        } else
+            cp = TcpSt[s];
+        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(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');
+}
+
+#if defined(HASSOSTATE)
+/*
+ * socket_state_to_str() -- convert socket state number to a string
+ *
+ * returns "UNKNOWN" for unknown state.
+ */
+static char *socket_state_to_str(struct lsof_context *ctx, unsigned int ss) {
+    char *sr;
+    switch (Lf->lts.ss) {
+    case SS_UNCONNECTED:
+        sr = "UNCONNECTED";
+        break;
+    case SS_CONNECTING:
+        sr = "CONNECTING";
+        break;
+    case SS_CONNECTED:
+        sr = "CONNECTED";
+        break;
+    case SS_DISCONNECTING:
+        sr = "DISCONNECTING";
+        break;
+    default:
+        sr = "UNKNOWN";
+        break;
+    }
+    return sr;
+}
+#endif /* defined(HASSOSTATE) */
\ No newline at end of file
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..5d91a6e
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,1956 @@
+/*
+ * main.c - common main function for lsof
+ *
+ * V. Abell, Purdue University
+ */
+
+/*
+ * 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.
+ */
+
+#include "common.h"
+#include "cli.h"
+
+/*
+ * Local definitions
+ */
+
+static int GObk[] = {1, 1};      /* option backspace values */
+static char GOp;                 /* option prefix -- '+' or '-' */
+static char *GOv = (char *)NULL; /* option `:' value pointer */
+static int GOx1 = 1;             /* first opt[][] index */
+static int GOx2 = 0;             /* second opt[][] index */
+
+static int GetOpt(struct lsof_context *ctx, int ct, char *opt[], char *rules,
+                  int *err);
+static char *sv_fmt_str(struct lsof_context *ctx, char *f);
+
+/*
+ * main() - main function for lsof
+ */
+
+int main(int argc, char *argv[]) {
+    enum ExitStatus rv;
+    int gopt_rv;
+    int ad, c, i, n, se1, se2, ss;
+    char *cp;
+    int err = 0;
+    enum ExitStatus ev = LSOF_EXIT_SUCCESS;
+    int fh = 0;
+    char *fmtr = (char *)NULL;
+    long l;
+    MALLOC_S len;
+    struct lfile *lf;
+    struct nwad *np, *npn;
+    char options[128];
+    int rc = 0;
+    struct stat sb;
+    struct sfile *sfp;
+    struct lproc **slp = (struct lproc **)NULL;
+    int sp = 0;
+    struct str_lst *str, *strt;
+    int version = 0;
+    int xover = 0;
+    int pr_count = 0;
+    /** liblsof context */
+    struct lsof_context *ctx = NULL;
+
+#if defined(HAS_STRFTIME)
+    char *fmt = (char *)NULL;
+    size_t fmtl = (size_t)0;
+#endif /* defined(HAS_STRFTIME) */
+
+#if defined(HASZONES)
+    znhash_t *zp;
+#endif /* defined(HASZONES) */
+
+#if defined(HASSELINUX)
+    /*
+     * This stanza must be immediately before the "Save program name." code,
+     * since it contains code itself.
+     */
+    cntxlist_t *cntxp;
+
+    CntxStatus = is_selinux_enabled() ? 1 : 0;
+#endif /* defined(HASSELINUX) */
+
+    /* Initialize lsof context */
+    ctx = lsof_new();
+
+    /*
+     * Save program name.
+     */
+    if ((Pn = strrchr(argv[0], '/')))
+        Pn++;
+    else
+        Pn = argv[0];
+    lsof_set_output_stream(ctx, stderr, Pn, 0);
+
+    /*
+     * 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.
+     */
+
+    if ((MaxFd = (int)GET_MAX_FD()) < 53)
+        MaxFd = 53;
+
+    closefrom_shim(ctx, 3);
+
+    while (((i = open("/dev/null", O_RDWR, 0)) >= 0) && (i < 2))
+        ;
+    if (i < 0)
+        Error(ctx);
+    if (i > 2)
+        (void)close(i);
+    (void)umask(0);
+
+#if defined(HASSETLOCALE)
+    /*
+     * Set locale to environment's definition.
+     */
+    (void)setlocale(LC_CTYPE, "");
+#endif /* defined(HASSETLOCALE) */
+
+    /*
+     * Common initialization.
+     */
+    Mypid = getpid();
+    if ((Mygid = (gid_t)getgid()) != getegid())
+        Setgid = 1;
+    Euid = geteuid();
+    if ((Myuid = (uid_t)getuid()) && !Euid)
+        Setuidroot = 1;
+    /*
+     * Create option mask.
+     */
+    (void)snpf(options, sizeof(options),
+               "?a%sbc:%sD:d:%s%sf:F:g:hHi:%s%slL:%s%snNo:Op:QPr:%ss:S:tT:u:"
+               "UvVwx:%s%s%s",
+
+#if defined(HAS_AFS) && defined(HASAOPT)
+               "A:",
+#else  /* !defined(HAS_AFS) || !defined(HASAOPT) */
+               "",
+#endif /* defined(HAS_AFS) && defined(HASAOPT) */
+
+#if defined(HASNCACHE)
+               "C",
+#else  /* !defined(HASNCACHE) */
+               "",
+#endif /* defined(HASNCACHE) */
+
+#if defined(HASEOPT)
+               "e:",
+#else  /* !defined(HASEOPT) */
+               "",
+#endif /* defined(HASEOPT) */
+
+#if defined(HASEPTOPTS)
+               "E",
+#else  /* !defined(HASEPTOPTS) */
+               "",
+#endif /* defined(HASEPTOPTS) */
+
+#if defined(HASKOPT)
+               "k:",
+#else  /* !defined(HASKOPT) */
+               "",
+#endif /* defined(HASKOPT) */
+
+#if defined(HASTASKS)
+               "K:",
+#else  /* !defined(HASTASKS) */
+               "",
+#endif /* defined(HASTASKS) */
+
+#if defined(HASMOPT) || defined(HASMNTSUP)
+               "m:",
+#else  /* !defined(HASMOPT) && !defined(HASMNTSUP) */
+               "",
+#endif /* defined(HASMOPT) || defined(HASMNTSUP) */
+
+#if defined(HASNORPC_H)
+               "",
+#else  /* !defined(HASNORPC_H) */
+               "M",
+#endif /* defined(HASNORPC_H) */
+
+#if defined(HASPPID)
+               "R",
+#else  /* !defined(HASPPID) */
+               "",
+#endif /* defined(HASPPID) */
+
+#if defined(HASXOPT)
+#    if defined(HASXOPT_ROOT)
+               (Myuid == 0) ? "X" : "",
+#    else  /* !defined(HASXOPT_ROOT) */
+               "X",
+#    endif /* defined(HASXOPT_ROOT) */
+#else      /* !defined(HASXOPT) */
+               "",
+#endif     /* defined(HASXOPT) */
+
+#if defined(HASZONES)
+               "z:",
+#else  /* !defined(HASZONES) */
+               "",
+#endif /* defined(HASZONES) */
+
+#if defined(HASSELINUX)
+               "Z:"
+#else  /* !defined(HASSELINUX) */
+               ""
+#endif /* defined(HASSELINUX) */
+
+    );
+    /*
+     * Loop through options.
+     */
+    while ((c = GetOpt(ctx, argc, argv, options, &gopt_rv)) != EOF) {
+        if (gopt_rv) {
+            err = 1;
+            continue;
+        }
+        switch (c) {
+        case 'a':
+            Fand = 1;
+            break;
+
+#if defined(HAS_AFS) && defined(HASAOPT)
+        case 'A':
+            if (!GOv || *GOv == '-' || *GOv == '+') {
+                (void)fprintf(stderr, "%s: -A not followed by path\n", Pn);
+                err = 1;
+                if (GOv) {
+                    GOx1 = GObk[0];
+                    GOx2 = GObk[1];
+                }
+            } else
+                AFSApath = GOv;
+            break;
+#endif /* defined(HAS_AFS) && defined(HASAOPT) */
+
+        case 'b':
+            lsof_avoid_blocking(ctx, 1);
+            break;
+        case 'c':
+            if (GOp == '+') {
+                if (!GOv || (*GOv == '-') || (*GOv == '+') ||
+                    !isdigit((int)*GOv)) {
+                    (void)fprintf(stderr,
+                                  "%s: +c not followed by width number\n", Pn);
+                    err = 1;
+                    if (GOv) {
+                        GOx1 = GObk[0];
+                        GOx2 = GObk[1];
+                    }
+                } else {
+                    CmdLim = TaskCmdLim = atoi(GOv);
+
+#if defined(MAXSYSCMDL)
+                    if (CmdLim > MAXSYSCMDL) {
+                        (void)fprintf(stderr,
+                                      "%s: +c %d > what system provides (%d)\n",
+                                      Pn, CmdLim, MAXSYSCMDL);
+                        err = 1;
+                    }
+#endif /* defined(MAXSYSCMDL) */
+                }
+                break;
+            }
+            if (GOv && (*GOv == '/')) {
+                if (lsof_select_process_regex(ctx, GOv))
+                    err = 1;
+            } else {
+                if (enter_cmd(ctx, "-c", GOv))
+                    err = 1;
+            }
+            break;
+
+#if defined(HASNCACHE)
+        case 'C':
+            Fncache = (GOp == '-') ? 0 : 1;
+            break;
+
+#endif /* defined(HASNCACHE) */
+        case 'd':
+            if (GOp == '+') {
+                if (enter_dir(ctx, GOv, 0))
+                    err = 1;
+                else {
+                    Selflags |= SELNM;
+                    xover = 1;
+                }
+            } else {
+                if (enter_fd(ctx, GOv))
+                    err = 1;
+            }
+            break;
+        case 'D':
+            if (GOp == '+') {
+                if (enter_dir(ctx, GOv, 1))
+                    err = 1;
+                else {
+                    Selflags |= SELNM;
+                    xover = 1;
+                }
+            } else {
+
+#if defined(HASDCACHE)
+                if (ctrl_dcache(ctx, GOv))
+                    err = 1;
+#else  /* !defined(HASDCACHE) */
+                (void)fprintf(stderr, "%s: unsupported option: -D\n", Pn);
+                err = 1;
+#endif /* defined(HASDCACHE) */
+            }
+            break;
+
+#if defined(HASEOPT)
+        case 'e':
+            if (enter_efsys(ctx, GOv, ((GOp == '+') ? 1 : 0)))
+                err = 1;
+            break;
+#endif /* defined(HASEOPT) */
+
+#if defined(HASEPTOPTS)
+        case 'E':
+            FeptE = (GOp == '+') ? 2 : 1;
+            break;
+#endif /* defined(HASEPTOPTS) */
+
+        case 'f':
+            if (!GOv || *GOv == '-' || *GOv == '+') {
+                Ffilesys = (GOp == '+') ? 2 : 1;
+                if (GOv) {
+                    GOx1 = GObk[0];
+                    GOx2 = GObk[1];
+                }
+                break;
+            }
+
+#if defined(HASFSTRUCT)
+            for (; *GOv; GOv++) {
+                switch (*GOv) {
+
+#    if !defined(HASNOFSCOUNT)
+                case 'c':
+                case 'C':
+                    if (GOp == '+') {
+                        Fsv |= FSV_CT;
+                        FsvByf = 1;
+                    } else
+                        Fsv &= (unsigned char)~FSV_CT;
+                    break;
+#    endif /* !defined(HASNOFSCOUNT) */
+
+#    if !defined(HASNOFSADDR)
+                case 'f':
+                case 'F':
+                    if (GOp == '+') {
+                        Fsv |= FSV_FA;
+                        FsvByf = 1;
+                    } else
+                        Fsv &= (unsigned char)~FSV_FA;
+                    break;
+#    endif /* !defined(HASNOFSADDR) */
+
+#    if !defined(HASNOFSFLAGS)
+                case 'g':
+                case 'G':
+                    if (GOp == '+') {
+                        Fsv |= FSV_FG;
+                        FsvByf = 1;
+                    } else
+                        Fsv &= (unsigned char)~FSV_FG;
+                    FsvFlagX = (*GOv == 'G') ? 1 : 0;
+                    break;
+#    endif /* !defined(HASNOFSFLAGS) */
+
+#    if !defined(HASNOFSNADDR)
+                case 'n':
+                case 'N':
+                    if (GOp == '+') {
+                        Fsv |= FSV_NI;
+                        FsvByf = 1;
+                    } else
+                        Fsv &= (unsigned char)~FSV_NI;
+                    break;
+#    endif /* !defined(HASNOFSNADDR */
+
+                default:
+                    (void)fprintf(stderr,
+                                  "%s: unknown file struct option: %c\n", Pn,
+                                  *GOv);
+                    err++;
+                }
+            }
+#else  /* !defined(HASFSTRUCT) */
+            (void)fprintf(stderr, "%s: unknown string for %cf: %s\n", Pn, GOp,
+                          GOv);
+            err++;
+#endif /* defined(HASFSTRUCT) */
+
+            break;
+        case 'F':
+            if (!GOv || *GOv == '-' || *GOv == '+' || strcmp(GOv, "0") == 0) {
+                if (GOv) {
+                    if (*GOv == '-' || *GOv == '+') {
+                        GOx1 = GObk[0];
+                        GOx2 = GObk[1];
+                    } else if (*GOv == '0')
+                        Terminator = '\0';
+                }
+                for (i = 0; FieldSel[i].nm; i++) {
+
+#if !defined(HASPPID)
+                    if (FieldSel[i].id == LSOF_FID_PPID)
+                        continue;
+#endif /* !defined(HASPPID) */
+
+#if !defined(HASTASKS)
+                    if (FieldSel[i].id == LSOF_FID_TCMD)
+                        continue;
+#endif /* !defined(HASTASKS) */
+
+#if !defined(HASFSTRUCT)
+                    if (FieldSel[i].id == LSOF_FID_CT ||
+                        FieldSel[i].id == LSOF_FID_FA ||
+                        FieldSel[i].id == LSOF_FID_FG ||
+                        FieldSel[i].id == LSOF_FID_NI)
+                        continue;
+#endif /* !defined(HASFSTRUCT) */
+
+#if defined(HASSELINUX)
+                    if ((FieldSel[i].id == LSOF_FID_CNTX) && !CntxStatus)
+                        continue;
+#else  /* !defined(HASSELINUX) */
+                    if (FieldSel[i].id == LSOF_FID_CNTX)
+                        continue;
+#endif /* !defined(HASSELINUX) */
+
+                    if (FieldSel[i].id == LSOF_FID_RDEV)
+                        continue; /* for compatibility */
+
+#if !defined(HASTASKS)
+                    if (FieldSel[i].id == LSOF_FID_TID)
+                        continue;
+#endif /* !defined(HASTASKS) */
+
+#if !defined(HASZONES)
+                    if (FieldSel[i].id == LSOF_FID_ZONE)
+                        continue;
+#endif /* !defined(HASZONES) */
+
+                    FieldSel[i].st = 1;
+                    if (FieldSel[i].opt && FieldSel[i].ov)
+                        *(FieldSel[i].opt) |= FieldSel[i].ov;
+                }
+
+#if defined(HASFSTRUCT)
+                Ffield = FsvFlagX = 1;
+#else  /* !defined(HASFSTRUCT) */
+                Ffield = 1;
+#endif /* defined(HASFSTRUCT) */
+
+                break;
+            }
+            if (strcmp(GOv, "?") == 0) {
+                fh = 1;
+                break;
+            }
+            for (; *GOv; GOv++) {
+                for (i = 0; FieldSel[i].nm; i++) {
+
+#if !defined(HASPPID)
+                    if (FieldSel[i].id == LSOF_FID_PPID)
+                        continue;
+#endif /* !defined(HASPPID) */
+
+#if !defined(HASTASKS)
+                    if (FieldSel[i].id == LSOF_FID_TCMD)
+                        continue;
+#endif /* !defined(HASTASKS) */
+
+#if !defined(HASFSTRUCT)
+                    if (FieldSel[i].id == LSOF_FID_CT ||
+                        FieldSel[i].id == LSOF_FID_FA ||
+                        FieldSel[i].id == LSOF_FID_FG ||
+                        FieldSel[i].id == LSOF_FID_NI)
+                        continue;
+#endif /* !defined(HASFSTRUCT) */
+
+#if !defined(HASTASKS)
+                    if (FieldSel[i].id == LSOF_FID_TID)
+                        continue;
+#endif /* !defined(HASTASKS) */
+
+                    if (FieldSel[i].id == *GOv) {
+                        FieldSel[i].st = 1;
+                        if (FieldSel[i].opt && FieldSel[i].ov)
+                            *(FieldSel[i].opt) |= FieldSel[i].ov;
+
+#if defined(HASFSTRUCT)
+                        if (i == LSOF_FIX_FG)
+                            FsvFlagX = 1;
+#endif /* defined(HASFSTRUCT) */
+
+                        if (i == LSOF_FIX_TERM)
+                            Terminator = '\0';
+
+                        if (i == LSOF_FIX_OFFSET)
+                            Foffset = 1;
+
+                        break;
+                    }
+                }
+                if (!FieldSel[i].nm) {
+                    (void)fprintf(stderr, "%s: unknown field: %c\n", Pn, *GOv);
+                    err++;
+                }
+            }
+            Ffield = 1;
+            break;
+        case 'g':
+            if (GOv) {
+                if (*GOv == '-' || *GOv == '+') {
+                    GOx1 = GObk[0];
+                    GOx2 = GObk[1];
+                } else if (enter_id(ctx, PGID, GOv))
+                    err = 1;
+            }
+            Fpgid = 1;
+            break;
+        case 'H':
+            Fhuman = 1;
+            break;
+        case 'h':
+        case '?':
+            Fhelp = 1;
+            break;
+        case 'i':
+            if (!GOv || *GOv == '-' || *GOv == '+') {
+                Fnet = 1;
+                FnetTy = 0;
+                if (GOv) {
+                    GOx1 = GObk[0];
+                    GOx2 = GObk[1];
+                }
+                break;
+            }
+            if (enter_network_address(ctx, GOv))
+                err = 1;
+            break;
+
+#if defined(HASKOPT)
+        case 'k':
+            if (!GOv || *GOv == '-' || *GOv == '+') {
+                (void)fprintf(stderr, "%s: -k not followed by path\n", Pn);
+                err = 1;
+                if (GOv) {
+                    GOx1 = GObk[0];
+                    GOx2 = GObk[1];
+                }
+            } else
+                Nmlst = GOv;
+            break;
+#endif /* defined(HASKOPT) */
+
+#if defined(HASTASKS)
+        case 'K':
+            if (!GOv || *GOv == '-' || *GOv == '+') {
+                Ftask = 1;
+                IgnTasks = 0;
+                Selflags |= SELTASK;
+                if (GOv) {
+                    GOx1 = GObk[0];
+                    GOx2 = GObk[1];
+                }
+            } else {
+                if (!strcasecmp(GOv, "i")) {
+                    Ftask = 0;
+                    IgnTasks = 1;
+                    Selflags &= ~SELTASK;
+                } else {
+                    (void)fprintf(stderr,
+                                  "%s: -K not followed by i (but by %s)\n", Pn,
+                                  GOv);
+                    err = 1;
+                }
+            }
+            break;
+#endif /* defined(HASTASKS) */
+
+        case 'l':
+            Futol = 0;
+            break;
+        case 'L':
+            Fnlink = (GOp == '+') ? 1 : 0;
+            if (!GOv || *GOv == '-' || *GOv == '+') {
+                Nlink = 0l;
+                if (GOv) {
+                    GOx1 = GObk[0];
+                    GOx2 = GObk[1];
+                }
+                break;
+            }
+            for (cp = GOv, l = 0l, n = 0; *cp; cp++) {
+                if (!isdigit((unsigned char)*cp))
+                    break;
+                l = (l * 10l) + ((long)*cp - (long)'0');
+                n++;
+            }
+            if (n) {
+                if (GOp != '+') {
+                    (void)fprintf(stderr, "%s: no number may follow -L\n", Pn);
+                    err = 1;
+                } else {
+                    Nlink = l;
+                    Selflags |= SELNLINK;
+                }
+            } else
+                Nlink = 0l;
+            if (*cp) {
+                GOx1 = GObk[0];
+                GOx2 = GObk[1] + n;
+            }
+            break;
+
+#if defined(HASMOPT) || defined(HASMNTSUP)
+        case 'm':
+            if (GOp == '-') {
+
+#    if defined(HASMOPT)
+                if (!GOv || *GOv == '-' || *GOv == '+') {
+                    (void)fprintf(stderr, "%s: -m not followed by path\n", Pn);
+                    err = 1;
+                    if (GOv) {
+                        GOx1 = GObk[0];
+                        GOx2 = GObk[1];
+                    }
+                } else
+                    Memory = GOv;
+#    else  /* !defined(HASMOPT) */
+                (void)fprintf(stderr, "%s: -m not supported\n", Pn);
+                err = 1;
+#    endif /* defined(HASMOPT) */
+
+            } else if (GOp == '+') {
+
+#    if defined(HASMNTSUP)
+                if (!GOv || *GOv == '-' || *GOv == '+') {
+                    MntSup = 1;
+                    if (GOv) {
+                        GOx1 = GObk[0];
+                        GOx2 = GObk[1];
+                    }
+                } else {
+                    MntSup = 2;
+                    MntSupP = GOv;
+                }
+#    else  /* !defined(HASMNTSUP) */
+                (void)fprintf(stderr, "%s: +m not supported\n", Pn);
+                err = 1;
+#    endif /* defined(HASMNTSUP) */
+
+            } else {
+                (void)fprintf(stderr, "%s: %cm not supported\n", Pn, GOp);
+                err = 1;
+            }
+            break;
+#endif /* defined(HASMOPT) || defined(HASMNTSUP) */
+
+#if !defined(HASNORPC_H)
+        case 'M':
+            FportMap = (GOp == '+') ? 1 : 0;
+            break;
+#endif /* !defined(HASNORPC_H) */
+
+        case 'n':
+            Fhost = (GOp == '-') ? 0 : 1;
+            break;
+        case 'N':
+            Fnfs = 1;
+            break;
+        case 'o':
+            if (!GOv || *GOv == '-' || *GOv == '+') {
+                Foffset = 1;
+                if (GOv) {
+                    GOx1 = GObk[0];
+                    GOx2 = GObk[1];
+                }
+                break;
+            }
+            for (cp = GOv, i = n = 0; *cp; cp++) {
+                if (!isdigit((unsigned char)*cp))
+                    break;
+                i = (i * 10) + ((int)*cp - '0');
+                n++;
+            }
+            if (n)
+                OffDecDig = i;
+            else
+                Foffset = 1;
+            if (*cp) {
+                GOx1 = GObk[0];
+                GOx2 = GObk[1] + n;
+            }
+            break;
+        case 'O':
+            lsof_avoid_forking(ctx, (GOp == '-') ? 1 : 0);
+            break;
+        case 'p':
+            if (enter_id(ctx, PID, GOv))
+                err = 1;
+            break;
+        case 'Q':
+            FsearchErr = 0;
+            break;
+        case 'P':
+            Fport = (GOp == '-') ? 0 : 1;
+            break;
+        case 'r':
+            if (GOp == '+') {
+                ev = LSOF_EXIT_ERROR;
+                rc = 1;
+            }
+            if (!GOv || *GOv == '-' || *GOv == '+') {
+                RptTm = RPTTM;
+                if (GOv) {
+                    GOx1 = GObk[0];
+                    GOx2 = GObk[1];
+                }
+                break;
+            }
+            for (cp = GOv, i = n = 0; *cp; cp++) {
+                if (!isdigit((unsigned char)*cp))
+                    break;
+                i = (i * 10) + ((int)*cp - '0');
+                n++;
+            }
+            if (n)
+                RptTm = i;
+            else
+                RptTm = RPTTM;
+            if (!*cp)
+                break;
+            while (*cp && (*cp == ' '))
+                cp++;
+
+            if (*cp == 'c') {
+                cp++;
+                for (i = 0; *cp && isdigit((unsigned char)*cp); cp++)
+                    i = (i * 10) + ((int)*cp - '0');
+                RptMaxCount = i;
+            }
+
+            if (*cp != LSOF_FID_MARK) {
+                GOx1 = GObk[0];
+                GOx2 = GObk[1] + n;
+                break;
+            }
+
+#if defined(HAS_STRFTIME)
+
+            /*
+             * Collect the strftime(3) format and test it.
+             */
+            cp++;
+            if ((fmtl = strlen(cp) + 1) < 1) {
+                (void)fprintf(stderr, "%s: <fmt> too short: \"%s\"\n", Pn, cp);
+                err = 1;
+            } else {
+                fmt = cp;
+                fmtl = (fmtl * 8) + 1;
+                if (!(fmtr = (char *)malloc((MALLOC_S)fmtl))) {
+                    (void)fprintf(
+                        stderr, "%s: no space (%d) for <fmt> result: \"%s\"\n",
+                        Pn, (int)fmtl, cp);
+                    Error(ctx);
+                }
+                if (util_strftime(fmtr, fmtl - 1, fmt) < 1) {
+                    (void)fprintf(stderr, "%s: illegal <fmt>: \"%s\"\n", Pn,
+                                  fmt);
+                    err = 1;
+                }
+            }
+
+#else  /* !defined(HAS_STRFTIME) */
+            (void)fprintf(stderr, "%s: m<fmt> not supported: \"%s\"\n", Pn, cp);
+            err = 1;
+#endif /* defined(HAS_STRFTIME) */
+
+            break;
+
+#if defined(HASPPID)
+        case 'R':
+            Fppid = 1;
+            break;
+#endif /* defined(HASPPID) */
+
+        case 's':
+
+#if defined(HASTCPUDPSTATE)
+            if (!GOv || *GOv == '-' || *GOv == '+') {
+                Fsize = 1;
+                if (GOv) {
+                    GOx1 = GObk[0];
+                    GOx2 = GObk[1];
+                }
+            } else {
+                if (enter_state_spec(ctx, GOv))
+                    err = 1;
+            }
+#else  /* !defined(HASTCPUDPSTATE) */
+            Fsize = 1;
+#endif /* defined(HASTCPUDPSTATE) */
+
+            break;
+        case 'S':
+            if (!GOv || *GOv == '-' || *GOv == '+') {
+                TmLimit = TMLIMIT;
+                if (GOv) {
+                    GOx1 = GObk[0];
+                    GOx2 = GObk[1];
+                }
+                break;
+            }
+            for (cp = GOv, i = n = 0; *cp; cp++) {
+                if (!isdigit((unsigned char)*cp))
+                    break;
+                i = (i * 10) + ((int)*cp - '0');
+                n++;
+            }
+            if (n)
+                TmLimit = i;
+            else
+                TmLimit = TMLIMIT;
+            if (*cp) {
+                GOx1 = GObk[0];
+                GOx2 = GObk[1] + n;
+            }
+            if (TmLimit < TMLIMMIN) {
+                (void)fprintf(stderr,
+                              "%s: WARNING: -S time (%d) changed to %d\n", Pn,
+                              TmLimit, TMLIMMIN);
+                TmLimit = TMLIMMIN;
+            }
+            break;
+        case 't':
+            Fterse = Fwarn = 1;
+            break;
+        case 'T':
+            if (!GOv || *GOv == '-' || *GOv == '+') {
+                Ftcptpi = (GOp == '-') ? 0 : TCPTPI_STATE;
+                if (GOv) {
+                    GOx1 = GObk[0];
+                    GOx2 = GObk[1];
+                }
+                break;
+            }
+            for (Ftcptpi = 0; *GOv; GOv++) {
+                switch (*GOv) {
+
+#if defined(HASSOOPT) || defined(HASSOSTATE) || defined(HASTCPOPT)
+                case 'f':
+                    Ftcptpi |= TCPTPI_FLAGS;
+                    break;
+#endif /* defined(HASSOOPT) || defined(HASSOSTATE) || defined(HASTCPOPT) */
+
+#if defined(HASTCPTPIQ)
+                case 'q':
+                    Ftcptpi |= TCPTPI_QUEUES;
+                    break;
+#endif /* defined(HASTCPTPIQ) */
+
+                case 's':
+                    Ftcptpi |= TCPTPI_STATE;
+                    break;
+
+#if defined(HASTCPTPIW)
+                case 'w':
+                    Ftcptpi |= TCPTPI_WINDOWS;
+                    break;
+#endif /* defined(HASTCPTPIW) */
+
+                default:
+                    (void)fprintf(
+                        stderr, "%s: unsupported TCP/TPI info selection: %c\n",
+                        Pn, *GOv);
+                    err = 1;
+                }
+            }
+            break;
+        case 'u':
+            if (enter_uid(ctx, GOv))
+                err = 1;
+            break;
+        case 'U':
+            Funix = 1;
+            break;
+        case 'v':
+            version = 1;
+            break;
+        case 'V':
+            Fverbose = 1;
+            break;
+        case 'w':
+            Fwarn = (GOp == '+') ? 0 : 1;
+            break;
+        case 'x':
+            if (!GOv || *GOv == '-' || *GOv == '+') {
+                Fxover = XO_ALL;
+                if (GOv) {
+                    GOx1 = GObk[0];
+                    GOx2 = GObk[1];
+                }
+                break;
+            } else {
+                for (; *GOv; GOv++) {
+                    switch (*GOv) {
+                    case 'f':
+                        Fxover |= XO_FILESYS;
+                        break;
+                    case 'l':
+                        Fxover |= XO_SYMLINK;
+                        break;
+                    default:
+                        (void)fprintf(stderr,
+                                      "%s: unknown cross-over option: %c\n", Pn,
+                                      *GOv);
+                        err++;
+                    }
+                }
+            }
+            break;
+
+#if defined(HASXOPT)
+        case 'X':
+            Fxopt = Fxopt ? 0 : 1;
+            break;
+#endif /* defined(HASXOPT) */
+
+#if defined(HASZONES)
+        case 'z':
+            Fzone = 1;
+            if (GOv && (*GOv != '-') && (*GOv != '+')) {
+
+                /*
+                 * Add to the zone name argument hash.
+                 */
+                if (enter_zone_arg(ctx, GOv))
+                    err = 1;
+            } else if (GOv) {
+                GOx1 = GObk[0];
+                GOx2 = GObk[1];
+            }
+            break;
+#endif /* defined(HASZONES) */
+
+#if defined(HASSELINUX)
+        case 'Z':
+            if (!CntxStatus) {
+                (void)fprintf(stderr, "%s: -Z limited to SELinux\n", Pn);
+                err = 1;
+            } else {
+                Fcntx = 1;
+                if (GOv && (*GOv != '-') && (*GOv != '+')) {
+
+                    /*
+                     * Add to the context name argument hash.
+                     */
+                    if (enter_cntx_arg(ctx, GOv))
+                        err = 1;
+                } else if (GOv) {
+                    GOx1 = GObk[0];
+                    GOx2 = GObk[1];
+                }
+            }
+            break;
+#endif /* defined(HASSELINUX) */
+
+        default:
+            (void)fprintf(stderr, "%s: unknown option (%c)\n", Pn, c);
+            err = 1;
+        }
+    }
+    /*
+     * If IgnTasks is set, remove SELTASK from SelAll and SelProc.
+     */
+    SelAll = IgnTasks ? (SELALL & ~SELTASK) : SELALL;
+    SelProc = IgnTasks ? (SELPROC & ~SELTASK) : SELPROC;
+    /*
+     * Check for argument consistency.
+     */
+    if (Cmdnx && Cmdni) {
+
+        /*
+         * Check for command inclusion/exclusion conflicts.
+         */
+        for (str = Cmdl; str; str = str->next) {
+            if (str->x) {
+                for (strt = Cmdl; strt; strt = strt->next) {
+                    if (!strt->x) {
+                        if (!strcmp(str->str, strt->str)) {
+                            (void)fprintf(stderr,
+                                          "%s: -c^%s and -c%s conflict.\n", Pn,
+                                          str->str, strt->str);
+                            err++;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+#if defined(HASTCPUDPSTATE)
+    if (TcpStXn && TcpStIn) {
+
+        /*
+         * Check for excluded and included TCP states.
+         */
+        for (i = 0; i < TcpNstates; i++) {
+            if (TcpStX[i] && TcpStI[i]) {
+                (void)fprintf(stderr,
+                              "%s: can't include and exclude TCP state: %s\n",
+                              Pn, TcpSt[i]);
+                err = 1;
+            }
+        }
+    }
+    if (UdpStXn && UdpStIn) {
+
+        /*
+         * Check for excluded and included UDP states.
+         */
+        for (i = 0; i < UdpNstates; i++) {
+            if (UdpStX[i] && UdpStI[i]) {
+                (void)fprintf(stderr,
+                              "%s: can't include and exclude UDP state: %s\n",
+                              Pn, UdpSt[i]);
+                err = 1;
+            }
+        }
+    }
+#endif /* defined(HASTCPUDPSTATE) */
+
+    if (Fsize && Foffset) {
+        (void)fprintf(stderr, "%s: -o and -s are mutually exclusive\n", Pn);
+        err++;
+    }
+    if (Ffield) {
+        if (Fterse) {
+            (void)fprintf(stderr, "%s: -F and -t are mutually exclusive\n", Pn);
+            err++;
+        }
+        FieldSel[LSOF_FIX_PID].st = 1;
+
+#if defined(HAS_STRFTIME)
+        if (fmtr) {
+
+            /*
+             * The field output marker format can't contain "%n" new line
+             * requests.
+             */
+            for (cp = strchr(fmt, '%'); cp; cp = strchr(cp, '%')) {
+                if (*++cp == 'n') {
+                    (void)fprintf(
+                        stderr, "%s: %%n illegal in -r m<fmt> when -F has", Pn);
+                    (void)fprintf(stderr, " been specified: \"%s\"\n", fmt);
+                    err++;
+                    break;
+                } else if (*cp == '%')
+                    cp++;
+            }
+        }
+#endif /* defined(HAS_STRFTIME) */
+    }
+    if (Fxover && !xover) {
+        (void)fprintf(stderr, "%s: -x must accompany +d or +D\n", Pn);
+        err++;
+    }
+
+#if defined(HASEOPT)
+    if (Efsysl) {
+
+        /*
+         * If there are file systems specified by -e options, check them.
+         */
+        efsys_list_t *ep;        /* Efsysl pointer */
+        struct mounts *mp, *mpw; /* local mount table pointers */
+
+        if ((mp = readmnt(ctx))) {
+            for (ep = Efsysl; ep; ep = ep->next) {
+                for (mpw = mp; mpw; mpw = mpw->next) {
+                    if (!strcmp(mpw->dir, ep->path)) {
+                        ep->mp = mpw;
+                        break;
+                    }
+                }
+                if (!ep->mp) {
+                    (void)fprintf(
+                        stderr, "%s: \"-e %s\" is not a mounted file system.\n",
+                        Pn, ep->path);
+                    err++;
+                }
+            }
+        }
+    }
+#endif /* defined(HASEOPT) */
+
+    if (DChelp || err || Fhelp || fh || version)
+        usage(ctx, err ? 1 : 0, fh, version);
+    /*
+     * Reduce the size of Suid[], if necessary.
+     */
+    if (Suid && Nuid && Nuid < Mxuid) {
+        if (!(Suid = (struct seluid *)realloc(
+                  (MALLOC_P *)Suid,
+                  (MALLOC_S)(sizeof(struct seluid) * Nuid)))) {
+            (void)fprintf(stderr, "%s: can't realloc UID table\n", Pn);
+            Error(ctx);
+        }
+        Mxuid = Nuid;
+    }
+    /*
+     * Compute the selection flags.
+     */
+    if ((Cmdl && Cmdni) || CmdRx)
+        Selflags |= SELCMD;
+
+#if defined(HASSELINUX)
+    if (CntxArg)
+        Selflags |= SELCNTX;
+#endif /* defined(HASSELINUX) */
+
+    if (Fdl)
+        Selflags |= SELFD;
+    if (Fnet)
+        Selflags |= SELNET;
+    if (Fnfs)
+        Selflags |= SELNFS;
+    if (Funix)
+        Selflags |= SELUNX;
+    if (Npgid && Npgidi)
+        Selflags |= SELPGID;
+    if (Npid && Npidi)
+        Selflags |= SELPID;
+    if (Nuid && Nuidincl)
+        Selflags |= SELUID;
+    if (Nwad)
+        Selflags |= SELNA;
+
+#if defined(HASZONES)
+    if (ZoneArg)
+        Selflags |= SELZONE;
+#endif /* defined(HASZONES) */
+
+    if (GOx1 < argc)
+        Selflags |= SELNM;
+    if (Selflags == 0) {
+        if (Fand) {
+            (void)fprintf(stderr, "%s: no select options to AND via -a\n", Pn);
+            usage(ctx, 1, 0, 0);
+        }
+        Selflags = SelAll;
+    } else {
+        if (GOx1 >= argc && (Selflags & (SELNA | SELNET)) != 0 &&
+            (Selflags & ~(SELNA | SELNET)) == 0)
+            Selinet = 1;
+        AllProc = 0;
+    }
+    /*
+     * Get the device for DEVDEV_PATH.
+     */
+    if (stat(DEVDEV_PATH, &sb)) {
+        se1 = errno;
+        if ((ad = strcmp(DEVDEV_PATH, "/dev"))) {
+            if ((ss = stat("/dev", &sb)))
+                se2 = errno;
+            else
+                se2 = 0;
+        } else {
+            se2 = 0;
+            ss = 1;
+        }
+        if (ss) {
+            (void)fprintf(stderr, "%s: can't stat(%s): %s\n", Pn, DEVDEV_PATH,
+                          strerror(se1));
+            if (ad) {
+                (void)fprintf(stderr, "%s: can't stat(/dev): %s\n", Pn,
+                              strerror(se2));
+            }
+            Error(ctx);
+        }
+    }
+    DevDev = sb.st_dev;
+    /*
+     * Process the file arguments.
+     */
+    if (GOx1 < argc) {
+        if (ck_file_arg(ctx, GOx1, argc, argv, Ffilesys, 0, (struct stat *)NULL,
+                        FsearchErr == 0))
+            Error(ctx);
+    }
+    /*
+     * Do dialect-specific initialization.
+     */
+    initialize(ctx);
+#if defined(LINUX_LSOF_H)
+    if (Fsv && (OffType != OFFSET_FDINFO)) {
+        if (!Fwarn && FsvByf)
+            (void)fprintf(
+                stderr,
+                "%s: WARNING: can't report file flags; disregarding +f.\n", Pn);
+        Fsv = 0;
+    }
+#endif
+    if (Sfile)
+        (void)hashSfile(ctx);
+
+#if defined(WILLDROPGID)
+    /*
+     * If this process isn't setuid(root), but it is setgid(not_real_gid),
+     * relinquish the setgid power.  (If it hasn't already been done.)
+     */
+    (void)dropgid(ctx);
+#endif /* defined(WILLDROPGID) */
+
+#if defined(HASDCACHE)
+    /*
+     * If there is a device cache, prepare the device table.
+     */
+    if (DCstate)
+        readdev(ctx, 0);
+#endif /* defined(HASDCACHE) */
+
+    /*
+     * Define the size and offset print formats.
+     */
+    (void)snpf(options, sizeof(options), "%%%su", INODEPSPEC);
+    InodeFmt_d = sv_fmt_str(ctx, options);
+    (void)snpf(options, sizeof(options), "%%#%sx", INODEPSPEC);
+    InodeFmt_x = sv_fmt_str(ctx, options);
+    (void)snpf(options, sizeof(options), "0t%%%su", SZOFFPSPEC);
+    SzOffFmt_0t = sv_fmt_str(ctx, options);
+    (void)snpf(options, sizeof(options), "%%%su", SZOFFPSPEC);
+    SzOffFmt_d = sv_fmt_str(ctx, options);
+    (void)snpf(options, sizeof(options), "%%*%su", SZOFFPSPEC);
+    SzOffFmt_dv = sv_fmt_str(ctx, options);
+    (void)snpf(options, sizeof(options), "%%#%sx", SZOFFPSPEC);
+    SzOffFmt_x = sv_fmt_str(ctx, options);
+
+#if defined(HASMNTSUP)
+    /*
+     * Report mount supplement information, as requested.
+     */
+    if (MntSup == 1) {
+        (void)readmnt(ctx);
+        Exit(ctx, LSOF_EXIT_SUCCESS);
+    }
+#endif /* defined(HASMNTSUP) */
+
+    /*
+     * Gather and report process information every RptTm seconds.
+     */
+    if (RptTm)
+        CkPasswd = 1;
+    do {
+
+        /*
+         * Gather information about processes.
+         */
+        gather_proc_info(ctx);
+        /*
+         * If the local process table has more than one entry, sort it by PID.
+         */
+        if (Nlproc > 1) {
+            if (Nlproc > sp) {
+                len = (MALLOC_S)(Nlproc * sizeof(struct lproc *));
+                sp = Nlproc;
+                if (!slp)
+                    slp = (struct lproc **)malloc(len);
+                else
+                    slp = (struct lproc **)realloc((MALLOC_P *)slp, len);
+                if (!slp) {
+                    (void)fprintf(stderr, "%s: no space for %d sort pointers\n",
+                                  Pn, Nlproc);
+                    Error(ctx);
+                }
+            }
+            for (i = 0; i < Nlproc; i++) {
+                slp[i] = &Lproc[i];
+            }
+            (void)qsort((QSORT_P *)slp, (size_t)Nlproc,
+                        (size_t)sizeof(struct lproc *), comppid);
+        }
+        if ((n = Nlproc)) {
+
+#if defined(HASNCACHE)
+            /*
+             * If using the kernel name cache, force its reloading.
+             */
+            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 printing
+             * of the selected processes.
+             */
+            if (FeptE) {
+                lf = Lf;
+                /*
+                 * Scan all selected processes.
+                 */
+                for (i = 0; i < Nlproc; i++) {
+                    Lp = (Nlproc > 1) ? slp[i] : &Lproc[i];
+
+                    /*
+                     * For processes that have been selected for printing
+                     * and have files that are the end point(s) of pipe(s),
+                     * process the file endpoints.
+                     */
+                    if (Lp->pss && (Lp->ept & EPT_PIPE))
+                        (void)process_pinfo(ctx, 0);
+                    /*
+                     * Process POSIX MQ endpoints.
+                     */
+                    if (Lp->ept & EPT_PSXMQ)
+                        (void)process_psxmqinfo(ctx, 0);
+
+#    if defined(HASUXSOCKEPT)
+                    /*
+                     * For processes that have been selected for printing
+                     * and have files that are the end point(s) of UNIX
+                     * socket(s), process the file endpoints.
+                     */
+                    if (Lp->pss && (Lp->ept & EPT_UXS))
+                        (void)process_uxsinfo(ctx, 0);
+#    endif /* defined(HASUXSOCKEPT) */
+
+#    if defined(HASPTYEPT)
+                    /*
+                     * For processes that have been selected for printing
+                     * and have files that are the end point(s) of pseudo-
+                     * terminal files(s), process the file endpoints.
+                     */
+                    if (Lp->pss && (Lp->ept & EPT_PTY))
+                        (void)process_ptyinfo(ctx, 0);
+#    endif /* defined(HASPTYEPT) */
+
+                    /*
+                     * Process INET socket endpoints.
+                     */
+                    if (Lp->ept & EPT_NETS)
+                        (void)process_netsinfo(ctx, 0);
+
+#    if defined(HASIPv6)
+                    /*
+                     * Process INET6 socket endpoints.
+                     */
+                    if (Lp->ept & EPT_NETS6)
+                        (void)process_nets6info(ctx, 0);
+#    endif /* defined(HASIPv6) */
+                    /*
+                     * Process eventfd endpoints.
+                     */
+                    if (Lp->ept & EPT_EVTFD)
+                        (void)process_evtfdinfo(ctx, 0);
+                }
+                /*
+                 * In a second pass, look for unselected endpoint files,
+                 * possibly selecting them for printing.
+                 */
+                for (i = 0; i < Nlproc; i++) {
+                    Lp = (Nlproc > 1) ? slp[i] : &Lproc[i];
+
+                    /*
+                     * Process pipe endpoints.
+                     */
+                    if (Lp->ept & EPT_PIPE_END)
+                        (void)process_pinfo(ctx, 1);
+                    /*
+                     * Process POSIX MQ endpoints.
+                     */
+                    if (Lp->ept & EPT_PSXMQ_END)
+                        (void)process_psxmqinfo(ctx, 1);
+
+#    if defined(HASUXSOCKEPT)
+                    /*
+                     * Process UNIX socket endpoints.
+                     */
+                    if (Lp->ept & EPT_UXS_END)
+                        (void)process_uxsinfo(ctx, 1);
+#    endif /* defined(HASUXSOCKEPT) */
+
+#    if defined(HASPTYEPT)
+                    /*
+                     * Process pseudo-terminal endpoints.
+                     */
+                    if (Lp->ept & EPT_PTY_END)
+                        (void)process_ptyinfo(ctx, 1);
+#    endif /* defined(HASPTYEPT) */
+
+                    /*
+                     * Process INET socket endpoints.
+                     */
+                    if (Lp->ept & EPT_NETS_END)
+                        (void)process_netsinfo(ctx, 1);
+
+#    if defined(HASIPv6)
+                    /*
+                     * Process INET6 socket endpoints.
+                     */
+                    if (Lp->ept & EPT_NETS6_END)
+                        (void)process_nets6info(ctx, 1);
+#    endif /* defined(HASIPv6) */
+
+                    /*
+                     * Process envetfd endpoints.
+                     */
+                    if (Lp->ept & EPT_EVTFD_END)
+                        (void)process_evtfdinfo(ctx, 1);
+                }
+                Lf = lf;
+            }
+#endif /* defined(HASEPTOPTS) */
+
+            /*
+             * Print the selected processes and count them.
+             *
+             * Lf contents must be preserved, since they may point to a
+             * malloc()'d area, and since Lf is used throughout the print
+             * process.
+             */
+            for (lf = Lf, print_init(ctx); PrPass < 2; PrPass++) {
+                for (i = n = 0; i < Nlproc; i++) {
+                    Lp = (Nlproc > 1) ? slp[i] : &Lproc[i];
+                    if (Lp->pss) {
+                        if (print_proc(ctx))
+                            n++;
+                    }
+                    if (RptTm && PrPass)
+                        (void)free_lproc(Lp);
+                }
+            }
+            Lf = lf;
+        }
+        /*
+         * If a repeat time is set, sleep for the specified time.
+         *
+         * If conditional repeat mode is in effect, see if it's time to exit.
+         */
+        if (RptTm) {
+
+#if defined(HASEPTOPTS)
+            (void)clear_pinfo(ctx);
+
+            (void)clear_psxmqinfo(ctx);
+
+#    if defined(HASUXSOCKEPT)
+            (void)clear_uxsinfo(ctx);
+#    endif /* defined(HASUXSOCKEPT) */
+
+#    if defined(HASPTYEPT)
+            (void)clear_ptyinfo(ctx);
+#    endif /* defined(HASPTYEPT) */
+
+            (void)clear_netsinfo(ctx);
+
+#    if defined(HASIPv6)
+            (void)clear_nets6info(ctx);
+#    endif /* defined(HASIPv6) */
+
+            (void)clear_evtfdinfo(ctx);
+#endif /* defined(HASEPTOPTS) */
+
+            if (rc) {
+                if (!n)
+                    break;
+                else
+                    ev = LSOF_EXIT_SUCCESS;
+            }
+
+#if defined(HAS_STRFTIME)
+            if (fmt && fmtr) {
+
+                /*
+                 * Format the marker line.
+                 */
+                (void)util_strftime(fmtr, fmtl - 1, fmt);
+                fmtr[fmtl - 1] = '\0';
+            }
+#endif /* defined(HAS_STRFTIME) */
+
+            if (Ffield) {
+                putchar(LSOF_FID_MARK);
+
+#if defined(HAS_STRFTIME)
+                if (fmtr)
+                    (void)printf("%s", fmtr);
+#endif /* defined(HAS_STRFTIME) */
+
+                putchar(Terminator);
+                if (Terminator != '\n')
+                    putchar('\n');
+            } else {
+
+#if defined(HAS_STRFTIME)
+                if (fmtr)
+                    cp = fmtr;
+                else
+#endif /* defined(HAS_STRFTIME) */
+
+                    cp = "=======";
+                puts(cp);
+            }
+            (void)fflush(stdout);
+            (void)childx(ctx);
+            (void)sleep(RptTm);
+            Hdr = Nlproc = 0;
+            CkPasswd = 1;
+        }
+        if (RptMaxCount && (++pr_count == RptMaxCount))
+            RptTm = 0;
+    } while (RptTm);
+    /*
+     * See if all requested information was displayed.  Return zero if it
+     * was; one, if not.  If -V was specified, report what was not displayed.
+     */
+    (void)childx(ctx);
+    rv = LSOF_EXIT_SUCCESS;
+    for (str = Cmdl; str; str = str->next) {
+
+        /*
+         * Check command specifications.
+         */
+        if (str->f)
+            continue;
+        rv = LSOF_SEARCH_FAILURE;
+        if (Fverbose) {
+            (void)printf("%s: command not located: ", Pn);
+            safestrprt(str->str, stdout, 1);
+        }
+    }
+    for (i = 0; i < NCmdRxU; i++) {
+
+        /*
+         * Check command regular expressions.
+         */
+        if (CmdRx[i].mc)
+            continue;
+        rv = LSOF_SEARCH_FAILURE;
+        if (Fverbose) {
+            (void)printf("%s: no command found for regex: ", Pn);
+            safestrprt(CmdRx[i].exp, stdout, 1);
+        }
+    }
+    for (sfp = Sfile; sfp; sfp = sfp->next) {
+
+        /*
+         * Check file specifications.
+         */
+        if (sfp->f)
+            continue;
+        rv = LSOF_SEARCH_FAILURE;
+        if (Fverbose) {
+            (void)printf("%s: no file%s use located: ", Pn,
+                         sfp->type ? "" : " system");
+            safestrprt(sfp->aname, stdout, 1);
+        }
+    }
+
+#if defined(HASPROCFS)
+    /*
+     * Report on proc file system search results.
+     */
+    if (Procsrch && !Procfind) {
+        rv = LSOF_SEARCH_FAILURE;
+        if (Fverbose) {
+            (void)printf("%s: no file system use located: ", Pn);
+            safestrprt(Mtprocfs ? Mtprocfs->dir : HASPROCFS, stdout, 1);
+        }
+    }
+    {
+        struct procfsid *pfi;
+
+        for (pfi = Procfsid; pfi; pfi = pfi->next) {
+            if (!pfi->f) {
+                rv = LSOF_SEARCH_FAILURE;
+                if (Fverbose) {
+                    (void)printf("%s: no file use located: ", Pn);
+                    safestrprt(pfi->nm, stdout, 1);
+                }
+            }
+        }
+    }
+#endif /* defined(HASPROCFS) */
+
+    if ((np = Nwad)) {
+
+        /*
+         * Check Internet address specifications.
+         *
+         * If any Internet address derived from the same argument was found,
+         * consider all derivations found.  If no derivation from the same
+         * argument was found, report only the first failure.
+         *
+         */
+        for (; np; np = np->next) {
+            if (!(cp = np->arg))
+                continue;
+            for (npn = np->next; npn; npn = npn->next) {
+                if (!npn->arg)
+                    continue;
+                if (!strcmp(cp, npn->arg)) {
+
+                    /*
+                     * If either of the duplicate specifications was found,
+                     * mark them both found.  If neither was found, mark all
+                     * but the first one found.
+                     */
+                    if (np->f)
+                        npn->f = np->f;
+                    else if (npn->f)
+                        np->f = npn->f;
+                    else
+                        npn->f = 1;
+                }
+            }
+        }
+        for (np = Nwad; np; np = np->next) {
+            if (!np->f && (cp = np->arg)) {
+                rv = LSOF_SEARCH_FAILURE;
+                if (Fverbose) {
+                    (void)printf("%s: Internet address not located: ", Pn);
+                    safestrprt(cp ? cp : "(unknown)", stdout, 1);
+                }
+            }
+        }
+    }
+    if (Fnet && Fnet < 2) {
+
+        /*
+         * Report no Internet files located.
+         */
+        rv = LSOF_SEARCH_FAILURE;
+        if (Fverbose)
+            (void)printf("%s: no Internet files located\n", Pn);
+    }
+
+#if defined(HASTCPUDPSTATE)
+    if (TcpStIn) {
+
+        /*
+         * Check for included TCP states not located.
+         */
+        for (i = 0; i < TcpNstates; i++) {
+            if (TcpStI[i] == 1) {
+                rv = LSOF_SEARCH_FAILURE;
+                if (Fverbose)
+                    (void)printf("%s: TCP state not located: %s\n", Pn,
+                                 TcpSt[i]);
+            }
+        }
+    }
+    if (UdpStIn) {
+
+        /*
+         * Check for included UDP states not located.
+         */
+        for (i = 0; i < UdpNstates; i++) {
+            if (UdpStI[i] == 1) {
+                rv = LSOF_SEARCH_FAILURE;
+                if (Fverbose)
+                    (void)printf("%s: UDP state not located: %s\n", Pn,
+                                 UdpSt[i]);
+            }
+        }
+    }
+#endif /* defined(HASTCPUDPSTATE) */
+
+    if (Fnfs && Fnfs < 2) {
+
+        /*
+         * Report no NFS files located.
+         */
+        rv = LSOF_SEARCH_FAILURE;
+        if (Fverbose)
+            (void)printf("%s: no NFS files located\n", Pn);
+    }
+    for (i = 0; i < Npid; i++) {
+
+        /*
+         * Check inclusionary process ID specifications.
+         */
+        if (Spid[i].f || Spid[i].x)
+            continue;
+        rv = LSOF_SEARCH_FAILURE;
+        if (Fverbose)
+            (void)printf("%s: process ID not located: %d\n", Pn, Spid[i].i);
+    }
+
+#if defined(HASTASKS)
+    if (Ftask && Ftask < 2) {
+
+        /*
+         * Report no tasks located.
+         */
+        rv = LSOF_SEARCH_FAILURE;
+        if (Fverbose)
+            (void)printf("%s: no tasks located\n", Pn);
+    }
+#endif /* defined(HASTASKS) */
+
+#if defined(HASZONES)
+    if (ZoneArg) {
+
+        /*
+         * Check zone argument results.
+         */
+        for (i = 0; i < HASHZONE; i++) {
+            for (zp = ZoneArg[i]; zp; zp = zp->next) {
+                if (!zp->f) {
+                    rv = LSOF_SEARCH_FAILURE;
+                    if (Fverbose) {
+                        (void)printf("%s: zone not located: ", Pn);
+                        safestrprt(zp->zn, stdout, 1);
+                    }
+                }
+            }
+        }
+    }
+#endif /* defined(HASZONES) */
+
+#if defined(HASSELINUX)
+    if (CntxArg) {
+
+        /*
+         * Check context argument results.
+         */
+        for (cntxp = CntxArg; cntxp; cntxp = cntxp->next) {
+            if (!cntxp->f) {
+                rv = LSOF_SEARCH_FAILURE;
+                if (Fverbose) {
+                    (void)printf("%s: context not located: ", Pn);
+                    safestrprt(cntxp->cntx, stdout, 1);
+                }
+            }
+        }
+    }
+#endif /* defined(HASSELINUX) */
+
+    for (i = 0; i < Npgid; i++) {
+
+        /*
+         * Check inclusionary process group ID specifications.
+         */
+        if (Spgid[i].f || Spgid[i].x)
+            continue;
+        rv = LSOF_SEARCH_FAILURE;
+        if (Fverbose)
+            (void)printf("%s: process group ID not located: %d\n", Pn,
+                         Spgid[i].i);
+    }
+    for (i = 0; i < Nuid; i++) {
+
+        /*
+         * Check inclusionary user ID specifications.
+         */
+        if (Suid[i].excl || Suid[i].f)
+            continue;
+        rv = LSOF_SEARCH_FAILURE;
+        if (Fverbose) {
+            if (Suid[i].lnm) {
+                (void)printf("%s: login name (UID %lu) not located: ", Pn,
+                             (unsigned long)Suid[i].uid);
+                safestrprt(Suid[i].lnm, stdout, 1);
+            } else
+                (void)printf("%s: user ID not located: %lu\n", Pn,
+                             (unsigned long)Suid[i].uid);
+        }
+    }
+    if (!rv && rc)
+        rv = ev;
+    if (!rv && ErrStat)
+        rv = LSOF_EXIT_ERROR;
+    Exit(ctx, rv);
+    return (rv); /* to make code analyzers happy */
+}
+
+/*
+ * GetOpt() -- Local get option
+ *
+ * Liberally adapted from the public domain AT&T getopt() source,
+ * distributed at the 1985 UNIFORM conference in Dallas
+ *
+ * The modifications allow `?' to be an option character and allow
+ * the caller to decide that an option that may be followed by a
+ * value doesn't have one -- e.g., has a default instead.
+ */
+
+static int GetOpt(struct lsof_context *ctx, /* context */
+                  int ct,                   /* option count */
+                  char *opt[],              /* options */
+                  char *rules,              /* option rules */
+                  int *err)                 /* error return */
+{
+    register int c;
+    register char *cp = (char *)NULL;
+
+    if (GOx2 == 0) {
+
+        /*
+         * Move to a new entry of the option array.
+         *
+         * EOF if:
+         *
+         *	Option list has been exhausted;
+         *	Next option doesn't start with `-' or `+';
+         *	Next option has nothing but `-' or `+';
+         *	Next option is ``--'' or ``++''.
+         */
+        if (GOx1 >= ct || (opt[GOx1][0] != '-' && opt[GOx1][0] != '+') ||
+            !opt[GOx1][1])
+            return (EOF);
+        if (strcmp(opt[GOx1], "--") == 0 || strcmp(opt[GOx1], "++") == 0) {
+            GOx1++;
+            return (EOF);
+        }
+        GOp = opt[GOx1][0];
+        GOx2 = 1;
+    }
+    /*
+     * Flag `:' option character as an error.
+     *
+     * Check for a rule on this option character.
+     */
+    *err = 0;
+    if ((c = opt[GOx1][GOx2]) == ':') {
+        (void)fprintf(stderr, "%s: colon is an illegal option character.\n",
+                      Pn);
+        *err = 1;
+    } else if (!(cp = strchr(rules, c))) {
+        (void)fprintf(stderr, "%s: illegal option character: %c\n", Pn, c);
+        *err = 2;
+    }
+    if (*err) {
+
+        /*
+         * An error was detected.
+         *
+         * Advance to the next option character.
+         *
+         * Return the character causing the error.
+         */
+        if (opt[GOx1][++GOx2] == '\0') {
+            GOx1++;
+            GOx2 = 0;
+        }
+        return (c);
+    }
+    if (*(cp + 1) == ':') {
+
+        /*
+         * The option may have a following value.  The caller decides
+         * if it does.
+         *
+         * Save the position of the possible value in case the caller
+         * decides it does not belong to the option and wants it
+         * reconsidered as an option character.  The caller does that
+         * with:
+         *		GOx1 = GObk[0]; GOx2 = GObk[1];
+         *
+         * Don't indicate that an option of ``--'' is a possible value.
+         *
+         * Finally, on the assumption that the caller will decide that
+         * the possible value belongs to the option, position to the
+         * option following the possible value, so that the next call
+         * to GetOpt() will find it.
+         */
+        if (opt[GOx1][GOx2 + 1] != '\0') {
+            GObk[0] = GOx1;
+            GObk[1] = ++GOx2;
+            GOv = &opt[GOx1++][GOx2];
+        } else if (++GOx1 >= ct)
+            GOv = (char *)NULL;
+        else {
+            GObk[0] = GOx1;
+            GObk[1] = 0;
+            GOv = opt[GOx1];
+            if (strcmp(GOv, "--") == 0)
+                GOv = (char *)NULL;
+            else
+                GOx1++;
+        }
+        GOx2 = 0;
+    } else {
+
+        /*
+         * The option character stands alone with no following value.
+         *
+         * Advance to the next option character.
+         */
+        if (opt[GOx1][++GOx2] == '\0') {
+            GOx2 = 0;
+            GOx1++;
+        }
+        GOv = (char *)NULL;
+    }
+    /*
+     * Return the option character.
+     */
+    return (c);
+}
+
+/*
+ * sv_fmt_str() - save format string
+ */
+
+static char *sv_fmt_str(struct lsof_context *ctx, char *f) /* format string */
+{
+    char *cp;
+    MALLOC_S l;
+
+    l = (MALLOC_S)(strlen(f) + 1);
+    if (!(cp = (char *)malloc(l))) {
+        (void)fprintf(stderr, "%s: can't allocate %d bytes for format: %s\n",
+                      Pn, (int)l, f);
+        Error(ctx);
+    }
+    (void)snpf(cp, l, "%s", f);
+    return (cp);
+}
diff --git a/src/print.c b/src/print.c
new file mode 100644
index 0000000..494f9eb
--- /dev/null
+++ b/src/print.c
@@ -0,0 +1,2137 @@
+/*
+ * print.c - common print 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.
+ */
+
+#include "common.h"
+#include "cli.h"
+#include "proto.h"
+
+/*
+ * Local definitions, structures and function prototypes
+ */
+
+#define HCINC 64 /* host cache size increase chunk */
+#define PORTHASHBUCKETS                                                        \
+    128 /* port hash bucket count                                              \
+         * !!MUST BE A POWER OF 2!! */
+#define PORTTABTHRESH                                                          \
+    10 /* threshold at which we will switch                                    \
+        * from using getservbyport() to                                        \
+        * getservent() -- see lkup_port()                                      \
+        * and fill_porttab() */
+
+struct hostcache {
+    unsigned char a[MAX_AF_ADDR]; /* numeric address */
+    int af;                       /* address family -- e.g., AF_INET
+                                   * or AF_INET6 */
+    char *name;                   /* name */
+};
+
+struct porttab {
+    int port;
+    MALLOC_S nl; /* name length (excluding '\0') */
+    int ss;      /* service name status, 0 = lookup not
+                  * yet performed */
+    char *name;
+    struct porttab *next;
+};
+
+#if defined(HASNORPC_H)
+static struct porttab **Pth[2] = {NULL, NULL};
+/* port hash buckets:
+ * Pth[0] for TCP service names
+ * Pth[1] for UDP service names
+ */
+#else  /* !defined(HASNORPC_H) */
+static struct porttab **Pth[4] = {NULL, NULL, NULL, NULL};
+/* port hash buckets:
+ * Pth[0] for TCP service names
+ * Pth[1] for UDP service names
+ * Pth[2] for TCP portmap info
+ * Pth[3] for UDP portmap info
+ */
+#endif /* defined(HASNORPC_H) */
+
+#define HASHPORT(p) (((((int)(p)) * 31415) >> 3) & (PORTHASHBUCKETS - 1))
+
+#if !defined(HASNORPC_H)
+static void fill_portmap(struct lsof_context *ctx);
+static void update_portmap(struct lsof_context *ctx, struct porttab *pt,
+                           char *pn);
+#endif /* !defined(HASNORPC_H) */
+
+static void fill_porttab(struct lsof_context *ctx);
+static char *lkup_port(struct lsof_context *ctx, int p, int pr, int src);
+static char *lkup_svcnam(struct lsof_context *ctx, int h, int p, int pr,
+                         int ss);
+static int printinaddr(struct lsof_context *ctx);
+static int human_readable_size(SZOFFTYPE sz, int print, int col);
+
+#if !defined(HASNORPC_H)
+/*
+ * fill_portmap() -- fill the RPC portmap program name table via a conversation
+ *		     with the portmapper
+ *
+ * The following copyright notice acknowledges that this function was adapted
+ * from getrpcportnam() of the source code of the OpenBSD netstat program.
+ */
+
+/*
+ * Copyright (c) 1983, 1988, 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.
+ */
+
+static void fill_portmap(struct lsof_context *ctx) {
+    static int already_run = 0;
+    char buf[128], *cp, *nm;
+    CLIENT *c;
+    int h, port, pr;
+    MALLOC_S nl;
+    struct pmaplist *p = (struct pmaplist *)NULL;
+    struct porttab *pt;
+    struct rpcent *r;
+    struct TIMEVAL_LSOF tm;
+
+#    if !defined(CAN_USE_CLNT_CREATE)
+    struct hostent *he;
+    struct sockaddr_in ia;
+    int s = RPC_ANYSOCK;
+#    endif /* !defined(CAN_USE_CLNT_CREATE) */
+
+    /*
+     * Make sure this is only run once.
+     */
+    if (already_run)
+        return;
+    already_run = 1;
+
+    /*
+     * Construct structures for communicating with the portmapper.
+     */
+
+#    if !defined(CAN_USE_CLNT_CREATE)
+    zeromem(&ia, sizeof(ia));
+    ia.sin_family = AF_INET;
+    if ((he = gethostbyname("localhost")))
+        MEMMOVE((caddr_t)&ia.sin_addr, he->h_addr, he->h_length);
+    ia.sin_port = htons(PMAPPORT);
+#    endif /* !defined(CAN_USE_CLNT_CREATE) */
+
+    tm.tv_sec = 60;
+    tm.tv_usec = 0;
+    /*
+     * Get an RPC client handle.  Then ask for a dump of the port map.
+     */
+
+#    if defined(CAN_USE_CLNT_CREATE)
+    if (!(c = clnt_create("localhost", PMAPPROG, PMAPVERS, "tcp")))
+#    else  /* !defined(CAN_USE_CLNT_CREATE) */
+    if (!(c = clnttcp_create(&ia, PMAPPROG, PMAPVERS, &s, 0, 0)))
+#    endif /* defined(CAN_USE_CLNT_CREATE) */
+
+        return;
+    if (clnt_call(c, PMAPPROC_DUMP, XDR_VOID, NULL, XDR_PMAPLIST, (caddr_t)&p,
+                  tm) != RPC_SUCCESS) {
+        clnt_destroy(c);
+        return;
+    }
+    /*
+     * Loop through the port map dump, creating portmap table entries from TCP
+     * and UDP members.
+     */
+    for (; p; p = p->pml_next) {
+
+        /*
+         * Determine the port map entry's protocol; ignore all but TCP and UDP.
+         */
+        if (p->pml_map.pm_prot == IPPROTO_TCP)
+            pr = 2;
+        else if (p->pml_map.pm_prot == IPPROTO_UDP)
+            pr = 3;
+        else
+            continue;
+        /*
+         * See if there's already a portmap entry for this port.  If there is,
+         * ignore this entry.
+         */
+        h = HASHPORT((port = (int)p->pml_map.pm_port));
+        for (pt = Pth[pr][h]; pt; pt = pt->next) {
+            if (pt->port == port)
+                break;
+        }
+        if (pt)
+            continue;
+        /*
+         * Save the registration name or number.
+         */
+        cp = (char *)NULL;
+        if ((r = (struct rpcent *)getrpcbynumber(p->pml_map.pm_prog))) {
+            if (r->r_name && strlen(r->r_name))
+                cp = r->r_name;
+        }
+        if (!cp) {
+            (void)snpf(buf, sizeof(buf), "%lu",
+                       (unsigned long)p->pml_map.pm_prog);
+            cp = buf;
+        }
+        if (!strlen(cp))
+            continue;
+        /*
+         * Allocate space for the portmap name entry and copy it there.
+         */
+        if (!(nm = mkstrcpy(cp, &nl))) {
+            (void)fprintf(stderr,
+                          "%s: can't allocate space for portmap entry: ", Pn);
+            safestrprt(cp, stderr, 1);
+            Error(ctx);
+        }
+        if (!nl) {
+            (void)free((FREE_P *)nm);
+            continue;
+        }
+        /*
+         * Allocate and fill a porttab struct entry for the portmap table.
+         * Link it to the head of its hash bucket, and make it the new head.
+         */
+        if (!(pt = (struct porttab *)malloc(sizeof(struct porttab)))) {
+            (void)fprintf(stderr,
+                          "%s: can't allocate porttab entry for portmap: ", Pn);
+            safestrprt(nm, stderr, 1);
+            Error(ctx);
+        }
+        pt->name = nm;
+        pt->nl = nl;
+        pt->port = port;
+        pt->next = Pth[pr][h];
+        pt->ss = 0;
+        Pth[pr][h] = pt;
+    }
+    clnt_destroy(c);
+}
+#endif /* !defined(HASNORPC_H) */
+
+/*
+ * fill_porttab() -- fill the TCP and UDP service name port table with a
+ *		     getservent() scan
+ */
+
+static void fill_porttab(struct lsof_context *ctx) {
+    int h, p, pr;
+    MALLOC_S nl;
+    char *nm;
+    struct porttab *pt;
+    struct servent *se;
+
+    (void)endservent();
+    /*
+     * Scan the services data base for TCP and UDP entries that have a non-null
+     * name associated with them.
+     */
+    (void)setservent(1);
+    while ((se = getservent())) {
+        if (!se->s_name || !se->s_proto)
+            continue;
+        if (strcasecmp(se->s_proto, "TCP") == 0)
+            pr = 0;
+        else if (strcasecmp(se->s_proto, "UDP") == 0)
+            pr = 1;
+        else
+            continue;
+        if (!se->s_name || !strlen(se->s_name))
+            continue;
+        p = ntohs(se->s_port);
+        /*
+         * See if a port->service entry is already cached for this port and
+         * prototcol.  If it is, leave it alone.
+         */
+        h = HASHPORT(p);
+        for (pt = Pth[pr][h]; pt; pt = pt->next) {
+            if (pt->port == p)
+                break;
+        }
+        if (pt)
+            continue;
+        /*
+         * Add a new entry to the cache for this port and protocol.
+         */
+        if (!(nm = mkstrcpy(se->s_name, &nl))) {
+            (void)fprintf(stderr,
+                          "%s: can't allocate %d bytes for port %d name: %s\n",
+                          Pn, (int)(nl + 1), p, se->s_name);
+            Error(ctx);
+        }
+        if (!nl) {
+            (void)free((FREE_P *)nm);
+            continue;
+        }
+        if (!(pt = (struct porttab *)malloc(sizeof(struct porttab)))) {
+            (void)fprintf(stderr,
+                          "%s: can't allocate porttab entry for port %d: %s\n",
+                          Pn, p, se->s_name);
+            Error(ctx);
+        }
+        pt->name = nm;
+        pt->nl = nl - 1;
+        pt->port = p;
+        pt->next = Pth[pr][h];
+        pt->ss = 0;
+        Pth[pr][h] = pt;
+    }
+    (void)endservent();
+}
+
+/*
+ * gethostnm() - get host name
+ */
+
+char *gethostnm(struct lsof_context *ctx, /* context */
+                unsigned char *ia,        /* Internet address */
+                int af)                   /* address family -- e.g., AF_INET
+                                           * or AF_INET6 */
+{
+    int al = MIN_AF_ADDR;
+    char hbuf[256];
+    static struct hostcache *hc = (struct hostcache *)NULL;
+    static int hcx = 0;
+    char *hn, *np;
+    struct hostent *he = (struct hostent *)NULL;
+    int i, j;
+    MALLOC_S len;
+    static int nhc = 0;
+    /*
+     * Search cache.
+     */
+
+#if defined(HASIPv6)
+    if (af == AF_INET6)
+        al = MAX_AF_ADDR;
+#endif /* defined(HASIPv6) */
+
+    for (i = 0; i < hcx; i++) {
+        if (af != hc[i].af)
+            continue;
+        for (j = 0; j < al; j++) {
+            if (ia[j] != hc[i].a[j])
+                break;
+        }
+        if (j >= al)
+            return (hc[i].name);
+    }
+    /*
+     * If -n has been specified, construct a numeric address.  Otherwise, look
+     * up host name by address.  If that fails, or if there is no name in the
+     * returned hostent structure, construct a numeric version of the address.
+     */
+    if (Fhost)
+        he = gethostbyaddr((char *)ia, al, af);
+    if (!he || !he->h_name) {
+
+#if defined(HASIPv6)
+        if (af == AF_INET6) {
+
+            /*
+             * Since IPv6 numeric addresses use `:' as a separator, enclose
+             * them in brackets.
+             */
+            hbuf[0] = '[';
+            if (!inet_ntop(af, ia, hbuf + 1, sizeof(hbuf) - 3)) {
+                (void)snpf(&hbuf[1], (sizeof(hbuf) - 1),
+                           "can't format IPv6 address]");
+            } else {
+                len = strlen(hbuf);
+                (void)snpf(&hbuf[len], sizeof(hbuf) - len, "]");
+            }
+        } else
+#endif /* defined(HASIPv6) */
+
+            if (af == AF_INET)
+                (void)snpf(hbuf, sizeof(hbuf), "%u.%u.%u.%u", ia[0], ia[1],
+                           ia[2], ia[3]);
+            else
+                (void)snpf(hbuf, sizeof(hbuf), "(unknown AF value: %d)", af);
+        hn = hbuf;
+    } else
+        hn = (char *)he->h_name;
+    /*
+     * Allocate space for name and copy name to it.
+     */
+    if (!(np = mkstrcpy(hn, (MALLOC_S *)NULL))) {
+        (void)fprintf(stderr, "%s: no space for host name: ", Pn);
+        safestrprt(hn, stderr, 1);
+        Error(ctx);
+    }
+    /*
+     * Add address/name entry to cache.  Allocate cache space in HCINC chunks.
+     */
+    if (hcx >= nhc) {
+        nhc += HCINC;
+        len = (MALLOC_S)(nhc * sizeof(struct hostcache));
+        if (!hc)
+            hc = (struct hostcache *)malloc(len);
+        else
+            hc = (struct hostcache *)realloc((MALLOC_P *)hc, len);
+        if (!hc) {
+            (void)fprintf(stderr, "%s: no space for host cache\n", Pn);
+            Error(ctx);
+        }
+    }
+    hc[hcx].af = af;
+    for (i = 0; i < al; i++) {
+        hc[hcx].a[i] = ia[i];
+    }
+    hc[hcx++].name = np;
+    return (np);
+}
+
+/*
+ * lkup_port() - look up port for protocol
+ */
+
+static char *lkup_port(struct lsof_context *ctx, /* context */
+                       int p,                    /* port number */
+                       int pr,  /* protocol index: 0 = tcp, 1 = udp */
+                       int src) /* port source: 0 = local
+                                 *		1 = foreign */
+{
+    int h, nh;
+    MALLOC_S nl;
+    char *nm, *pn;
+    static char pb[128];
+    struct porttab *pt;
+    /*
+     * If the hash buckets haven't been allocated, do so.
+     */
+    if (!Pth[0]) {
+
+#if defined(HASNORPC_H)
+        nh = 2;
+#else  /* !defined(HASNORPC_H) */
+        nh = FportMap ? 4 : 2;
+#endif /* defined(HASNORPC_H) */
+
+        for (h = 0; h < nh; h++) {
+            if (!(Pth[h] = (struct porttab **)calloc(
+                      PORTHASHBUCKETS, sizeof(struct porttab *)))) {
+                (void)fprintf(
+                    stderr,
+                    "%s: can't allocate %d bytes for %s %s hash buckets\n", Pn,
+                    (int)(2 * (PORTHASHBUCKETS * sizeof(struct porttab *))),
+                    (h & 1) ? "UDP" : "TCP", (h > 1) ? "portmap" : "port");
+                Error(ctx);
+            }
+        }
+    }
+
+#if !defined(HASNORPC_H)
+    /*
+     * If we're looking up program names for portmapped ports, make sure the
+     * portmap table has been loaded.
+     */
+    if (FportMap)
+        (void)fill_portmap(ctx);
+#endif /* !defined(HASNORPC_H) */
+
+    /*
+     * Hash the port and see if its name has been cached.  Look for a local
+     * port first in the portmap, if portmap searching is enabled.
+     */
+    h = HASHPORT(p);
+
+#if !defined(HASNORPC_H)
+    if (!src && FportMap) {
+        for (pt = Pth[pr + 2][h]; pt; pt = pt->next) {
+            if (pt->port != p)
+                continue;
+            if (!pt->ss) {
+                pn = Fport ? lkup_svcnam(ctx, h, p, pr, 0) : (char *)NULL;
+                if (!pn) {
+                    (void)snpf(pb, sizeof(pb), "%d", p);
+                    pn = pb;
+                }
+                (void)update_portmap(ctx, pt, pn);
+            }
+            return (pt->name);
+        }
+    }
+#endif /* !defined(HASNORPC_H) */
+
+    for (pt = Pth[pr][h]; pt; pt = pt->next) {
+        if (pt->port == p)
+            return (pt->name);
+    }
+    /*
+     * Search for a possible service name, unless the -P option has been
+     * specified.
+     *
+     * If there is no service name, return a %d conversion.
+     *
+     * Don't cache %d conversions; a zero port number is a %d conversion that
+     * is represented by "*".
+     */
+    pn = Fport ? lkup_svcnam(ctx, h, p, pr, 1) : (char *)NULL;
+    if (!pn || !strlen(pn)) {
+        if (p) {
+            (void)snpf(pb, sizeof(pb), "%d", p);
+            return (pb);
+        } else
+            return ("*");
+    }
+    /*
+     * Allocate a new porttab entry for the TCP or UDP service name.
+     */
+    if (!(pt = (struct porttab *)malloc(sizeof(struct porttab)))) {
+        (void)fprintf(stderr, "%s: can't allocate porttab entry for port %d\n",
+                      Pn, p);
+        Error(ctx);
+    }
+    /*
+     * Allocate space for the name; copy it to the porttab entry; and link the
+     * porttab entry to its hash bucket.
+     *
+     * Return a pointer to the name.
+     */
+    if (!(nm = mkstrcpy(pn, &nl))) {
+        (void)fprintf(stderr, "%s: can't allocate space for port name: ", Pn);
+        safestrprt(pn, stderr, 1);
+        Error(ctx);
+    }
+    pt->name = nm;
+    pt->nl = nl;
+    pt->port = p;
+    pt->next = Pth[pr][h];
+    pt->ss = 0;
+    Pth[pr][h] = pt;
+    return (nm);
+}
+
+/*
+ * lkup_svcnam() - look up service name for port
+ */
+
+static char *lkup_svcnam(struct lsof_context *ctx, /* context */
+                         int h,                    /* porttab hash index */
+                         int p,                    /* port number */
+                         int pr, /* protocol: 0 = TCP, 1 = UDP */
+                         int ss) /* search status: 1 = Pth[pr][h]
+                                  *		  already searched */
+{
+    static int fl[PORTTABTHRESH];
+    static int fln = 0;
+    static int gsbp = 0;
+    int i;
+    struct porttab *pt;
+    static int ptf = 0;
+    struct servent *se;
+    /*
+     * Do nothing if -P has been specified.
+     */
+    if (!Fport)
+        return ((char *)NULL);
+
+    for (;;) {
+
+        /*
+         * Search service name cache, if it hasn't already been done.
+         * Return the name of a match.
+         */
+        if (!ss) {
+            for (pt = Pth[pr][h]; pt; pt = pt->next) {
+                if (pt->port == p)
+                    return (pt->name);
+            }
+        }
+        /*
+         * If fill_porttab() has been called, there is no service name.
+         *
+         * Do PORTTABTHRES getservbport() calls, remembering the failures, so
+         * they won't be repeated.
+         *
+         * After PORTABTHRESH getservbyport() calls, call fill_porttab() once,
+         */
+        if (ptf)
+            break;
+        if (gsbp < PORTTABTHRESH) {
+            for (i = 0; i < fln; i++) {
+                if (fl[i] == p)
+                    return ((char *)NULL);
+            }
+            gsbp++;
+            if ((se = getservbyport(htons(p), pr ? "udp" : "tcp")))
+                return (se->s_name);
+            if (fln < PORTTABTHRESH)
+                fl[fln++] = p;
+            return ((char *)NULL);
+        }
+        (void)fill_porttab(ctx);
+        ptf++;
+        ss = 0;
+    }
+    return ((char *)NULL);
+}
+
+/*
+ * print_file() - print file
+ */
+
+void print_file(struct lsof_context *ctx) {
+    char buf[128];
+    char *cp = (char *)NULL;
+    dev_t dev;
+    int devs, len;
+    char access;
+    char lock;
+    char fd[FDLEN];
+    char type[TYPEL];
+
+    if (PrPass && !Hdr) {
+
+        /*
+         * Print the header line if this is the second pass and the
+         * header hasn't already been printed.
+         */
+        (void)printf("%-*.*s %*s", CmdColW, CmdColW, CMDTTL, PidColW, PIDTTL);
+
+#if defined(HASTASKS)
+        if (TaskPrtTid)
+            (void)printf(" %*s", TaskTidColW, TASKTIDTTL);
+        if (TaskPrtCmd)
+            (void)printf(" %-*.*s", TaskCmdColW, TaskCmdColW, TASKCMDTTL);
+#endif /* defined(HASTASKS) */
+
+#if defined(HASZONES)
+        if (Fzone)
+            (void)printf(" %-*s", ZoneColW, ZONETTL);
+#endif /* defined(HASZONES) */
+
+#if defined(HASSELINUX)
+        if (Fcntx)
+            (void)printf(" %-*s", CntxColW, CNTXTTL);
+#endif /* defined(HASSELINUX) */
+
+#if defined(HASPPID)
+        if (Fppid)
+            (void)printf(" %*s", PpidColW, PPIDTTL);
+#endif /* defined(HASPPID) */
+
+        if (Fpgid)
+            (void)printf(" %*s", PgidColW, PGIDTTL);
+        (void)printf(" %*s %*s   %*s", UserColW, USERTTL, FdColW - 2, FDTTL,
+                     TypeColW, TYPETTL);
+
+#if defined(HASFSTRUCT)
+        if (Fsv) {
+
+#    if !defined(HASNOFSADDR)
+            if (Fsv & FSV_FA)
+                (void)printf(" %*s", FsColW, FSTTL);
+#    endif /* !defined(HASNOFSADDR) */
+
+#    if !defined(HASNOFSCOUNT)
+            if (Fsv & FSV_CT)
+                (void)printf(" %*s", FcColW, FCTTL);
+#    endif /* !defined(HASNOFSCOUNT) */
+
+#    if !defined(HASNOFSFLAGS)
+            if (Fsv & FSV_FG)
+                (void)printf(" %*s", FgColW, FGTTL);
+#    endif /* !defined(HASNOFSFLAGS) */
+
+#    if !defined(HASNOFSNADDR)
+            if (Fsv & FSV_NI)
+                (void)printf(" %*s", NiColW, NiTtl);
+#    endif /* !defined(HASNOFSNADDR) */
+        }
+#endif /* defined(HASFSTRUCT) */
+
+        (void)printf(" %*s", DevColW, DEVTTL);
+        if (Foffset)
+            (void)printf(" %*s", SzOffColW, OFFTTL);
+        else if (Fsize)
+            (void)printf(" %*s", SzOffColW, SZTTL);
+        else
+            (void)printf(" %*s", SzOffColW, SZOFFTTL);
+        if (Fnlink)
+            (void)printf(" %*s", NlColW, NLTTL);
+        (void)printf(" %*s %s\n", NodeColW, NODETTL, NMTTL);
+        Hdr++;
+    }
+    /*
+     * Size or print the command.
+     *
+     * CAUTION: command can be empty, see issue #246,
+     * use NULL to represent failure instead of empty string
+     */
+    cp = Lp->cmd ? Lp->cmd : "(unknown)";
+    if (!PrPass) {
+        len = safestrlen(cp, 2);
+        if (CmdLim && (len > CmdLim))
+            len = CmdLim;
+        if (len > CmdColW)
+            CmdColW = len;
+    } else
+        safestrprtn(cp, CmdColW, stdout, 2);
+    /*
+     * Size or print the process ID.
+     */
+    if (!PrPass) {
+        (void)snpf(buf, sizeof(buf), "%d", Lp->pid);
+        if ((len = strlen(buf)) > PidColW)
+            PidColW = len;
+    } else
+        (void)printf(" %*d", PidColW, Lp->pid);
+
+#if defined(HASTASKS)
+    /*
+     * Size or print task ID and command name.
+     */
+    if (!PrPass) {
+        if ((cp = Lp->tcmd)) {
+            len = safestrlen(cp, 2);
+            if (TaskCmdLim && (len > TaskCmdLim))
+                len = TaskCmdLim;
+            if (len > TaskCmdColW)
+                TaskCmdColW = len;
+            TaskPrtCmd = 1;
+        }
+        if (Lp->tid) {
+            (void)snpf(buf, sizeof(buf), "%d", Lp->tid);
+            if ((len = strlen(buf)) > TaskTidColW)
+                TaskTidColW = len;
+            TaskPrtTid = 1;
+        }
+    } else {
+        if (TaskPrtTid) {
+            if (Lp->tid)
+                (void)printf(" %*d", TaskTidColW, Lp->tid);
+            else
+                (void)printf(" %*s", TaskTidColW, "");
+        }
+        if (TaskPrtCmd) {
+            cp = Lp->tcmd ? Lp->tcmd : "";
+            printf(" ");
+            safestrprtn(cp, TaskCmdColW, stdout, 2);
+        }
+    }
+#endif /* defined(HASTASKS) */
+
+#if defined(HASZONES)
+    /*
+     * Size or print the zone.
+     */
+    if (Fzone) {
+        if (!PrPass) {
+            if (Lp->zn) {
+                if ((len = strlen(Lp->zn)) > ZoneColW)
+                    ZoneColW = len;
+            }
+        } else
+            (void)printf(" %-*s", ZoneColW, Lp->zn ? Lp->zn : "");
+    }
+#endif /* defined(HASZONES) */
+
+#if defined(HASSELINUX)
+    /*
+     * Size or print the context.
+     */
+    if (Fcntx) {
+        if (!PrPass) {
+            if (Lp->cntx) {
+                if ((len = strlen(Lp->cntx)) > CntxColW)
+                    CntxColW = len;
+            }
+        } else
+            (void)printf(" %-*s", CntxColW, Lp->cntx ? Lp->cntx : "");
+    }
+#endif /* defined(HASSELINUX) */
+
+#if defined(HASPPID)
+    if (Fppid) {
+
+        /*
+         * Size or print the parent process ID.
+         */
+        if (!PrPass) {
+            (void)snpf(buf, sizeof(buf), "%d", Lp->ppid);
+            if ((len = strlen(buf)) > PpidColW)
+                PpidColW = len;
+        } else
+            (void)printf(" %*d", PpidColW, Lp->ppid);
+    }
+#endif /* defined(HASPPID) */
+
+    if (Fpgid) {
+
+        /*
+         * Size or print the process group ID.
+         */
+        if (!PrPass) {
+            (void)snpf(buf, sizeof(buf), "%d", Lp->pgid);
+            if ((len = strlen(buf)) > PgidColW)
+                PgidColW = len;
+        } else
+            (void)printf(" %*d", PgidColW, Lp->pgid);
+    }
+    /*
+     * Size or print the user ID or login name.
+     */
+    if (!PrPass) {
+        if ((len = strlen(printuid(ctx, (UID_ARG)Lp->uid, NULL))) > UserColW)
+            UserColW = len;
+    } else
+        (void)printf(" %*.*s", UserColW, UserColW,
+                     printuid(ctx, (UID_ARG)Lp->uid, NULL));
+    /*
+     * Size or print the file descriptor, access mode and lock status.
+     */
+    fd_to_string(Lf->fd_type, Lf->fd_num, fd);
+    access = access_to_char(Lf->access);
+    lock = lock_to_char(Lf->lock);
+    if (!PrPass) {
+        (void)snpf(buf, sizeof(buf), "%s%c%c", fd,
+                   (lock == ' ')     ? access
+                   : (access == ' ') ? '-'
+                                     : access,
+                   lock);
+        if ((len = strlen(buf)) > FdColW)
+            FdColW = len;
+    } else
+        (void)printf(" %*.*s%c%c", FdColW - 2, FdColW - 2, fd,
+                     (lock == ' ')     ? access
+                     : (access == ' ') ? '-'
+                                       : access,
+                     lock);
+    /*
+     * Size or print the type.
+     */
+    file_type_to_string(Lf->type, Lf->unknown_file_type_number, type,
+                        sizeof(type));
+    if (!PrPass) {
+        if ((len = strlen(type)) > TypeColW)
+            TypeColW = len;
+    } else
+        (void)printf(" %*.*s", TypeColW, TypeColW, type);
+
+#if defined(HASFSTRUCT)
+    /*
+     * Size or print the file structure address, file usage count, and node
+     * ID (address).
+     */
+
+    if (Fsv) {
+
+#    if !defined(HASNOFSADDR)
+        if (Fsv & FSV_FA) {
+            cp =
+                (Lf->fsv & FSV_FA) ? print_kptr(Lf->fsa, buf, sizeof(buf)) : "";
+            if (!PrPass) {
+                if ((len = strlen(cp)) > FsColW)
+                    FsColW = len;
+            } else
+                (void)printf(" %*.*s", FsColW, FsColW, cp);
+        }
+#    endif /* !defined(HASNOFSADDR) */
+
+#    if !defined(HASNOFSCOUNT)
+        if (Fsv & FSV_CT) {
+            if (Lf->fsv & FSV_CT) {
+                (void)snpf(buf, sizeof(buf), "%ld", Lf->fct);
+                cp = buf;
+            } else
+                cp = "";
+            if (!PrPass) {
+                if ((len = strlen(cp)) > FcColW)
+                    FcColW = len;
+            } else
+                (void)printf(" %*.*s", FcColW, FcColW, cp);
+        }
+#    endif /* !defined(HASNOFSCOUNT) */
+
+#    if !defined(HASNOFSFLAGS)
+        if (Fsv & FSV_FG) {
+            if ((Lf->fsv & FSV_FG) && (FsvFlagX || Lf->ffg || Lf->pof))
+                cp = print_fflags(ctx, Lf->ffg, Lf->pof);
+            else
+                cp = "";
+            if (!PrPass) {
+                if ((len = strlen(cp)) > FgColW)
+                    FgColW = len;
+            } else
+                (void)printf(" %*.*s", FgColW, FgColW, cp);
+        }
+#    endif /* !defined(HASNOFSFLAGS) */
+
+#    if !defined(HASNOFSNADDR)
+        if (Fsv & FSV_NI) {
+            cp =
+                (Lf->fsv & FSV_NI) ? print_kptr(Lf->fna, buf, sizeof(buf)) : "";
+            if (!PrPass) {
+                if ((len = strlen(cp)) > NiColW)
+                    NiColW = len;
+            } else
+                (void)printf(" %*.*s", NiColW, NiColW, cp);
+        }
+#    endif /* !defined(HASNOFSNADDR) */
+    }
+#endif /* defined(HASFSTRUCT) */
+
+    /*
+     * Size or print the device information.
+     */
+
+    if (Lf->rdev_def) {
+        dev = Lf->rdev;
+        devs = 1;
+    } else if (Lf->dev_def) {
+        dev = Lf->dev;
+        devs = 1;
+    } else
+        devs = 0;
+    if (devs) {
+
+#if defined(HASPRINTDEV)
+        cp = HASPRINTDEV(Lf, &dev);
+#else  /* !defined(HASPRINTDEV) */
+        (void)snpf(buf, sizeof(buf), "%u,%u", GET_MAJ_DEV(dev),
+                   GET_MIN_DEV(dev));
+        cp = buf;
+#endif /* defined(HASPRINTDEV) */
+    }
+
+    if (!PrPass) {
+        if (devs)
+            len = strlen(cp);
+        else if (Lf->dev_ch)
+            len = strlen(Lf->dev_ch);
+        else
+            len = 0;
+        if (len > DevColW)
+            DevColW = len;
+    } else {
+        if (devs)
+            (void)printf(" %*.*s", DevColW, DevColW, cp);
+        else {
+            if (Lf->dev_ch)
+                (void)printf(" %*.*s", DevColW, DevColW, Lf->dev_ch);
+            else
+                (void)printf(" %*.*s", DevColW, DevColW, "");
+        }
+    }
+    /*
+     * Size or print the size or offset.
+     */
+    if (!PrPass) {
+        if (!Foffset && Lf->sz_def) {
+            if (Fhuman) {
+                len = human_readable_size(Lf->sz, 0, 0);
+            } else {
+                (void)snpf(buf, sizeof(buf), SzOffFmt_d, Lf->sz);
+                len = strlen(buf);
+            }
+        } else if (!Fsize && Lf->off_def) {
+
+            (void)snpf(buf, sizeof(buf), SzOffFmt_0t, Lf->off);
+            cp = buf;
+
+            len = strlen(cp);
+            if (OffDecDig && len > (OffDecDig + 2)) {
+
+                (void)snpf(buf, sizeof(buf), SzOffFmt_x, Lf->off);
+                cp = buf;
+
+                len = strlen(cp);
+            }
+        } else
+            len = 0;
+        if (len > SzOffColW)
+            SzOffColW = len;
+    } else {
+        putchar(' ');
+        if (!Foffset && Lf->sz_def) {
+            if (Fhuman) {
+                human_readable_size(Lf->sz, 1, SzOffColW);
+            } else {
+                (void)snpf(buf, sizeof(buf), SzOffFmt_d, Lf->sz);
+                len = strlen(buf);
+                (void)printf(SzOffFmt_dv, SzOffColW, Lf->sz);
+            }
+        } else if (!Fsize && Lf->off_def) {
+
+            (void)snpf(buf, sizeof(buf), SzOffFmt_0t, Lf->off);
+            cp = buf;
+
+            if (OffDecDig && (int)strlen(cp) > (OffDecDig + 2)) {
+
+                (void)snpf(buf, sizeof(buf), SzOffFmt_x, Lf->off);
+                cp = buf;
+            }
+            (void)printf("%*.*s", SzOffColW, SzOffColW, cp);
+        } else
+            (void)printf("%*.*s", SzOffColW, SzOffColW, "");
+    }
+    /*
+     * Size or print the link count.
+     */
+    if (Fnlink) {
+        if (Lf->nlink_def) {
+            (void)snpf(buf, sizeof(buf), " %ld", Lf->nlink);
+            cp = buf;
+        } else
+            cp = "";
+        if (!PrPass) {
+            if ((len = strlen(cp)) > NlColW)
+                NlColW = len;
+        } else
+            (void)printf(" %*s", NlColW, cp);
+    }
+    /*
+     * Size or print the inode information.
+     */
+    switch (Lf->inp_ty) {
+    case 1:
+
+#if defined(HASPRINTINO)
+        cp = HASPRINTINO(Lf);
+#else  /* !defined(HASPRINTINO) */
+        (void)snpf(buf, sizeof(buf), InodeFmt_d, Lf->inode);
+        cp = buf;
+#endif /* defined(HASPRINTINO) */
+
+        break;
+    case 2:
+        if (Lf->iproto[0])
+            cp = Lf->iproto;
+        else
+            cp = "";
+        break;
+    case 3:
+        (void)snpf(buf, sizeof(buf), InodeFmt_x, Lf->inode);
+        cp = buf;
+        break;
+    default:
+        cp = "";
+    }
+    if (!PrPass) {
+        if ((len = strlen(cp)) > NodeColW)
+            NodeColW = len;
+    } else {
+        (void)printf(" %*.*s", NodeColW, NodeColW, cp);
+    }
+    /*
+     * If this is the second pass, print the name column.  (It doesn't need
+     * to be sized.)
+     */
+    if (PrPass) {
+        putchar(' ');
+
+#if defined(HASPRINTNM)
+        HASPRINTNM(ctx, Lf);
+#else  /* !defined(HASPRINTNM) */
+        printname(ctx, 1);
+#endif /* defined(HASPRINTNM) */
+    }
+}
+
+/*
+ * printinaddr() - print Internet addresses
+ */
+
+static int printinaddr(struct lsof_context *ctx) {
+    int i, len, src;
+    char *host, *port;
+    int nl = Namechl - 1;
+    char *np = Namech;
+    char pbuf[32];
+    /*
+     * Process local network address first.  If there's a foreign address,
+     * separate it from the local address with "->".
+     */
+    for (i = 0, *np = '\0'; i < 2; i++) {
+        if (!Lf->li[i].af)
+            continue;
+        host = port = (char *)NULL;
+        if (i) {
+
+            /*
+             * If this is the foreign address, insert the separator.
+             */
+            if (nl < 2)
+
+            addr_too_long :
+
+            {
+                (void)snpf(Namech, Namechl, "network addresses too long");
+                return (1);
+            }
+                (void)snpf(np, nl, "->");
+            np += 2;
+            nl -= 2;
+        }
+        /*
+         * Convert the address to a host name.
+         */
+
+#if defined(HASIPv6)
+        if ((Lf->li[i].af == AF_INET6 &&
+             IN6_IS_ADDR_UNSPECIFIED(&Lf->li[i].ia.a6)) ||
+            (Lf->li[i].af == AF_INET && Lf->li[i].ia.a4.s_addr == INADDR_ANY))
+            host = "*";
+        else
+            host = gethostnm(ctx, (unsigned char *)&Lf->li[i].ia, Lf->li[i].af);
+#else  /* !defined(HASIPv6) */
+        if (Lf->li[i].ia.a4.s_addr == INADDR_ANY)
+            host = "*";
+        else
+            host = gethostnm(ctx, (unsigned char *)&Lf->li[i].ia, Lf->li[i].af);
+#endif /* defined(HASIPv6) */
+
+        /*
+         * Process the port number.
+         */
+        if (Lf->li[i].p > 0) {
+
+            if (Fport
+
+#if !defined(HASNORPC_H)
+                || FportMap
+#endif /* defined(HASNORPC_H) */
+
+            ) {
+
+                /*
+                 * If converting port numbers to service names, or looking
+                 * up portmap program names and numbers, do so by protocol.
+                 *
+                 * Identify the port source as local if: 1) it comes from the
+                 * local entry (0) of the file's Internet address array; or
+                 * 2) it comes from  the foreign entry (1), and the foreign
+                 * Internet address matches the local one; or 3) it is the
+                 * loopback address 127.0.0.1.  (Test 2 may not always work
+                 * -- e.g., on hosts with multiple interfaces.)
+                 */
+#if !defined(HASNORPC_H)
+                if ((src = i) && FportMap) {
+
+#    if defined(HASIPv6)
+                    if (Lf->li[0].af == AF_INET6) {
+                        if (IN6_IS_ADDR_LOOPBACK(&Lf->li[i].ia.a6) ||
+                            IN6_ARE_ADDR_EQUAL(&Lf->li[0].ia.a6,
+                                               &Lf->li[1].ia.a6))
+                            src = 0;
+                    } else
+#    endif /* defined(HASIPv6) */
+
+                        if (Lf->li[0].af == AF_INET) {
+                            if (Lf->li[i].ia.a4.s_addr ==
+                                    htonl(INADDR_LOOPBACK) ||
+                                Lf->li[0].ia.a4.s_addr ==
+                                    Lf->li[1].ia.a4.s_addr)
+                                src = 0;
+                        }
+                }
+#else
+                /*
+                 * Just for suppressing warnings reported from compiler.
+                 *
+                 * src is referenced in lkup_port() only if
+                 * "!defined(HASNORPC_H)" is true. The condition here is
+                 * !defined(HASNORPC_H) is false. Therefore the value of src has
+                 * no impact.
+                 */
+                src = 1;
+#endif /* !defined(HASNORPC_H) */
+
+                if (strcasecmp(Lf->iproto, "TCP") == 0)
+                    port = lkup_port(ctx, Lf->li[i].p, 0, src);
+                else if (strcasecmp(Lf->iproto, "UDP") == 0)
+                    port = lkup_port(ctx, Lf->li[i].p, 1, src);
+            }
+            if (!port) {
+                (void)snpf(pbuf, sizeof(pbuf), "%d", Lf->li[i].p);
+                port = pbuf;
+            }
+        } else if (Lf->li[i].p == 0)
+            port = "*";
+        /*
+         * Enter the host name.
+         */
+        if (host) {
+            if ((len = strlen(host)) > nl)
+                goto addr_too_long;
+            if (len) {
+                (void)snpf(np, nl, "%s", host);
+                np += len;
+                nl -= len;
+            }
+        }
+        /*
+         * Enter the port number, preceded by a colon.
+         */
+        if (port) {
+            if (((len = strlen(port)) + 1) >= nl)
+                goto addr_too_long;
+            (void)snpf(np, nl, ":%s", port);
+            np += len + 1;
+            nl -= len - 1;
+        }
+    }
+    if (Namech[0]) {
+        safestrprt(Namech, stdout, 0);
+        return (1);
+    }
+    return (0);
+}
+
+/*
+ * print_init() - initialize for printing
+ */
+
+void print_init(struct lsof_context *ctx) {
+
+    /*
+     * Preset standard values.
+     */
+    PrPass = (Ffield || Fterse) ? 1 : 0;
+    LastPid = -1;
+    TaskPrtCmd = TaskPrtTid = 0;
+    /*
+     * Size columns by their titles.
+     */
+    CmdColW = strlen(CMDTTL);
+    DevColW = strlen(DEVTTL);
+    FdColW = strlen(FDTTL);
+    if (Fnlink)
+        NlColW = strlen(NLTTL);
+    NmColW = strlen(NMTTL);
+    NodeColW = strlen(NODETTL);
+    PgidColW = strlen(PGIDTTL);
+    PidColW = strlen(PIDTTL);
+    PpidColW = strlen(PPIDTTL);
+    if (Fsize)
+        SzOffColW = strlen(SZTTL);
+    else if (Foffset)
+        SzOffColW = strlen(OFFTTL);
+    else
+        SzOffColW = strlen(SZOFFTTL);
+
+#if defined(HASTASKS)
+    TaskCmdColW = strlen(TASKCMDTTL);
+    TaskTidColW = strlen(TASKTIDTTL);
+#endif /* defined(HASTASKS) */
+
+    TypeColW = strlen(TYPETTL);
+    UserColW = strlen(USERTTL);
+
+#if defined(HASFSTRUCT)
+
+#    if !defined(HASNOFSADDR)
+    FsColW = strlen(FSTTL);
+#    endif /* !defined(HASNOFSADDR) */
+
+#    if !defined(HASNOFSCOUNT)
+    FcColW = strlen(FCTTL);
+#    endif /* !defined(HASNOFSCOUNT) */
+
+#    if !defined(HASNOFSFLAGS)
+    FgColW = strlen(FGTTL);
+#    endif /* !defined(HASNOFSFLAGS) */
+
+#    if !defined(HASNOFSNADDR)
+    NiColW = strlen(NiTtl);
+#    endif /* !defined(HASNOFSNADDR) */
+#endif     /* defined(HASFSTRUCT) */
+
+#if defined(HASSELINUX)
+    if (Fcntx)
+        CntxColW = strlen(CNTXTTL);
+#endif /* defined(HASSELINUX) */
+
+#if defined(HASZONES)
+    if (Fzone)
+        ZoneColW = strlen(ZONETTL);
+#endif /* defined(HASZONES) */
+}
+
+/*
+ * printname() - print output name field
+ */
+
+void printname(struct lsof_context *ctx, int nl) /* NL status */
+{
+
+#if defined(HASNCACHE)
+    char buf[MAXPATHLEN];
+    char *cp;
+    int fp;
+#endif /* defined(HASNCACHE) */
+
+    int ps = 0;
+
+    if (Lf->nm && Lf->nm[0]) {
+
+        /*
+         * Print the name characters, if there are some.
+         */
+        safestrprt(Lf->nm, stdout, 0);
+        ps++;
+        if (!Lf->li[0].af && !Lf->li[1].af)
+            goto print_nma;
+    }
+    if (Lf->li[0].af || Lf->li[1].af) {
+        if (ps)
+            putchar(' ');
+        /*
+         * If the file has Internet addresses, print them.
+         */
+        if (printinaddr(ctx))
+            ps++;
+        goto print_nma;
+    }
+    if (((Lf->ntype == N_BLK) || (Lf->ntype == N_CHR)) && Lf->dev_def &&
+        Lf->rdev_def && printdevname(ctx, &Lf->dev, &Lf->rdev, 0, Lf->ntype)) {
+
+        /*
+         * If this is a block or character device and it has a name, print it.
+         */
+        ps++;
+        goto print_nma;
+    }
+    if (Lf->is_com) {
+
+        /*
+         * If this is a common node, print that fact.
+         */
+        (void)fputs("COMMON: ", stdout);
+        ps++;
+        goto print_nma;
+    }
+
+#if defined(HASPRIVNMCACHE)
+    if (HASPRIVNMCACHE(ctx, Lf)) {
+        ps++;
+        goto print_nma;
+    }
+#endif /* defined(HASPRIVNMCACHE) */
+
+    if (Lf->lmi_srch) {
+        struct mounts *mp;
+        /*
+         * Do a deferred local mount info table search for the file system
+         * (mounted) directory name and inode number, and mounted device name.
+         */
+        for (mp = readmnt(ctx); mp; mp = mp->next) {
+            if (Lf->dev == mp->dev) {
+                Lf->fsdir = mp->dir;
+                Lf->fsdev = mp->fsname;
+
+#if defined(HASFSINO)
+                Lf->fs_ino = mp->inode;
+#endif /* defined(HASFSINO) */
+
+                break;
+            }
+        }
+        Lf->lmi_srch = 0;
+    }
+    if (Lf->fsdir || Lf->fsdev) {
+
+        /*
+         * Print the file system directory name, device name, and
+         * possible path name components.
+         */
+
+#if !defined(HASNCACHE) || HASNCACHE < 2
+        if (Lf->fsdir) {
+            safestrprt(Lf->fsdir, stdout, 0);
+            ps++;
+        }
+#endif /* !defined(HASNCACHE) || HASNCACHE<2 */
+
+#if defined(HASNCACHE)
+
+#    if HASNCACHE < 2
+        if (Lf->na) {
+            if (NcacheReload) {
+
+#        if defined(NCACHELDPFX)
+                NCACHELDPFX
+#        endif /* defined(NCACHELDPFX) */
+
+                    (void)
+                ncache_load(ctx);
+
+#        if defined(NCACHELDSFX)
+                NCACHELDSFX
+#        endif /* defined(NCACHELDSFX) */
+
+                NcacheReload = 0;
+            }
+            if ((cp = ncache_lookup(ctx, buf, sizeof(buf), &fp))) {
+                char *cp1;
+
+                if (*cp == '\0')
+                    goto print_nma;
+                if (fp && Lf->fsdir) {
+                    if (*cp != '/') {
+                        cp1 = strrchr(Lf->fsdir, '/');
+                        if (cp1 == (char *)NULL || *(cp1 + 1) != '\0')
+                            putchar('/');
+                    }
+                } else
+                    (void)fputs(" -- ", stdout);
+                safestrprt(cp, stdout, 0);
+                ps++;
+                goto print_nma;
+            }
+        }
+#    else /* HASNCACHE>1 */
+        if (NcacheReload) {
+
+#        if defined(NCACHELDPFX)
+            NCACHELDPFX
+#        endif /* defined(NCACHELDPFX) */
+
+                (void)
+            ncache_load();
+
+#        if defined(NCACHELDSFX)
+            NCACHELDSFX
+#        endif /* defined(NCACHELDSFX) */
+
+            NcacheReload = 0;
+        }
+        if ((cp = ncache_lookup(buf, sizeof(buf), &fp))) {
+            if (fp) {
+                safestrprt(cp, stdout, 0);
+                ps++;
+            } else {
+                if (Lf->fsdir) {
+                    safestrprt(Lf->fsdir, stdout, 0);
+                    ps++;
+                }
+                if (*cp) {
+                    (void)fputs(" -- ", stdout);
+                    safestrprt(cp, stdout, 0);
+                    ps++;
+                }
+            }
+            goto print_nma;
+        }
+        if (Lf->fsdir) {
+            safestrprt(Lf->fsdir, stdout, 0);
+            ps++;
+        }
+#    endif     /* HASNCACHE<2 */
+#endif         /* defined(HASNCACHE) */
+
+        if (Lf->fsdev) {
+            if (Lf->fsdir)
+                (void)fputs(" (", stdout);
+            else
+                (void)putchar('(');
+            safestrprt(Lf->fsdev, stdout, 0);
+            (void)putchar(')');
+            ps++;
+        }
+    }
+    /*
+     * Print the NAME column addition, if there is one.  If there isn't
+     * make sure a NL is printed, as requested.
+     */
+
+print_nma:
+
+    if (Lf->nma) {
+        if (ps)
+            putchar(' ');
+        safestrprt(Lf->nma, stdout, 0);
+        ps++;
+    }
+    /*
+     * If this file has TCP/IP state information, print it.
+     */
+    if (!Ffield && Ftcptpi &&
+        (Lf->lts.type >= 0
+
+#if defined(HASTCPTPIQ)
+         || ((Ftcptpi & TCPTPI_QUEUES) && (Lf->lts.rqs || Lf->lts.sqs))
+#endif /* defined(HASTCPTPIQ) */
+
+#if defined(HASTCPTPIW)
+         || ((Ftcptpi & TCPTPI_WINDOWS) && (Lf->lts.rws || Lf->lts.wws))
+#endif /* defined(HASTCPTPIW) */
+
+             )) {
+        if (ps)
+            putchar(' ');
+        (void)print_tcptpi(ctx, 0);
+    }
+    if (nl)
+        putchar('\n');
+}
+
+/*
+ * printrawaddr() - print raw socket address
+ */
+
+void printrawaddr(struct lsof_context *ctx,
+                  struct sockaddr *sa) /* socket address */
+{
+    char *ep;
+    size_t sz;
+
+    ep = endnm(ctx, &sz);
+    (void)snpf(ep, sz, "%u/%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u",
+               sa->sa_family, (unsigned char)sa->sa_data[0],
+               (unsigned char)sa->sa_data[1], (unsigned char)sa->sa_data[2],
+               (unsigned char)sa->sa_data[3], (unsigned char)sa->sa_data[4],
+               (unsigned char)sa->sa_data[5], (unsigned char)sa->sa_data[6],
+               (unsigned char)sa->sa_data[7], (unsigned char)sa->sa_data[8],
+               (unsigned char)sa->sa_data[9], (unsigned char)sa->sa_data[10],
+               (unsigned char)sa->sa_data[11], (unsigned char)sa->sa_data[12],
+               (unsigned char)sa->sa_data[13]);
+}
+
+/*
+ * printsockty() - print socket type
+ */
+
+char *printsockty(int ty) /* socket type -- e.g., from so_type */
+{
+    static char buf[64];
+    char *cp;
+
+    switch (ty) {
+
+#if defined(SOCK_STREAM)
+    case SOCK_STREAM:
+        cp = "STREAM";
+        break;
+#endif /* defined(SOCK_STREAM) */
+
+#if defined(SOCK_STREAM)
+    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) */
+
+    default:
+        (void)snpf(buf, sizeof(buf), "SOCK_%#x", ty);
+        return (buf);
+    }
+    (void)snpf(buf, sizeof(buf), "SOCK_%s", cp);
+    return (buf);
+}
+
+/*
+ * printuid() - print User ID or login name
+ */
+
+char *printuid(struct lsof_context *ctx, /* context */
+               UID_ARG uid,              /* User IDentification number */
+               int *ty)                  /* returned UID type pointer (NULL
+                                          * (if none wanted).  If non-NULL
+                                          * then: *ty = 0 = login name
+                                          *	     = 1 = UID number */
+{
+    int i;
+    struct passwd *pw;
+    struct stat sb;
+    static struct stat sbs;
+    static struct uidcache {
+        uid_t uid;
+        char nm[LOGINML + 1];
+        struct uidcache *next;
+    } **uc = (struct uidcache **)NULL;
+    struct uidcache *up, *upn;
+    static char user[USERPRTL + 1];
+
+    if (Futol) {
+        if (CkPasswd) {
+
+            /*
+             * Get the mtime and ctime of /etc/passwd, as required.
+             */
+            if (stat("/etc/passwd", &sb) != 0) {
+                (void)fprintf(stderr, "%s: can't stat(/etc/passwd): %s\n", Pn,
+                              strerror(errno));
+                Error(ctx);
+            }
+        }
+        /*
+         * Define the UID cache, if necessary.
+         */
+        if (!uc) {
+            if (!(uc = (struct uidcache **)calloc(UIDCACHEL,
+                                                  sizeof(struct uidcache *)))) {
+                (void)fprintf(
+                    stderr, "%s: no space for %d byte UID cache hash buckets\n",
+                    Pn, (int)(UIDCACHEL * (sizeof(struct uidcache *))));
+                Error(ctx);
+            }
+            if (CkPasswd) {
+                sbs = sb;
+                CkPasswd = 0;
+            }
+        }
+        /*
+         * If it's time to check /etc/passwd and if its the mtime/ctime has
+         * changed, destroy the existing UID cache.
+         */
+        if (CkPasswd) {
+            if (sbs.st_mtime != sb.st_mtime || sbs.st_ctime != sb.st_ctime) {
+                for (i = 0; i < UIDCACHEL; i++) {
+                    if ((up = uc[i])) {
+                        do {
+                            upn = up->next;
+                            (void)free((FREE_P *)up);
+                        } while ((up = upn) != (struct uidcache *)NULL);
+                        uc[i] = (struct uidcache *)NULL;
+                    }
+                }
+                sbs = sb;
+            }
+            CkPasswd = 0;
+        }
+        /*
+         * Search the UID cache.
+         */
+        i = (int)((((unsigned long)uid * 31415L) >> 7) & (UIDCACHEL - 1));
+        for (up = uc[i]; up; up = up->next) {
+            if (up->uid == (uid_t)uid) {
+                if (ty)
+                    *ty = 0;
+                return (up->nm);
+            }
+        }
+        /*
+         * The UID is not in the cache.
+         *
+         * Look up the login name from the UID for a new cache entry.
+         */
+        if (!(pw = getpwuid((uid_t)uid))) {
+            if (!Fwarn) {
+                (void)fprintf(stderr, "%s: no pwd entry for UID %lu\n", Pn,
+                              (unsigned long)uid);
+            }
+        } else {
+
+            /*
+             * Allocate and fill a new cache entry.  Link it to its hash bucket.
+             */
+            if (!(upn = (struct uidcache *)malloc(sizeof(struct uidcache)))) {
+                (void)fprintf(
+                    stderr, "%s: no space for UID cache entry for: %lu, %s)\n",
+                    Pn, (unsigned long)uid, pw->pw_name);
+                Error(ctx);
+            }
+            (void)strncpy(upn->nm, pw->pw_name, LOGINML);
+            upn->nm[LOGINML] = '\0';
+            upn->uid = (uid_t)uid;
+            upn->next = uc[i];
+            uc[i] = upn;
+            if (ty)
+                *ty = 0;
+            return (upn->nm);
+        }
+    }
+    /*
+     * Produce a numeric conversion of the UID.
+     */
+    (void)snpf(user, sizeof(user), "%*lu", USERPRTL, (unsigned long)uid);
+    if (ty)
+        *ty = 1;
+    return (user);
+}
+
+#if !defined(HASNORPC_H)
+/*
+ * update_portmap() - update a portmap entry with its port number or service
+ *		      name
+ */
+
+static void update_portmap(struct lsof_context *ctx, /* context */
+                           struct porttab *pt,       /* porttab entry */
+                           char *pn)                 /* port name */
+{
+    MALLOC_S al, nl;
+    char *cp;
+
+    if (pt->ss)
+        return;
+    if (!(al = strlen(pn))) {
+        pt->ss = 1;
+        return;
+    }
+    nl = al + pt->nl + 2;
+    if (!(cp = (char *)malloc(nl + 1))) {
+        (void)fprintf(stderr,
+                      "%s: can't allocate %d bytes for portmap name: %s[%s]\n",
+                      Pn, (int)(nl + 1), pn, pt->name);
+        Error(ctx);
+    }
+    (void)snpf(cp, nl + 1, "%s[%s]", pn, pt->name);
+    (void)free((FREE_P *)pt->name);
+    pt->name = cp;
+    pt->nl = nl;
+    pt->ss = 1;
+}
+#endif /* !defined(HASNORPC_H) */
+
+/*
+ * Convert sz to human readable format, print to stdout if print=1
+ *
+ * Return the length of output
+ */
+int human_readable_size(SZOFFTYPE sz, int print, int col) {
+    char buf[128];
+    SZOFFTYPE base = 1024;
+    SZOFFTYPE unit = base;
+    SZOFFTYPE upper = base * base;
+    int suffix_count = 6;
+    char *suffix[6] = {"K", "M", "G", "T", "P", "E"};
+    int i;
+    int len;
+    double val;
+
+    if (sz < base) {
+        /* <1KB */
+        (void)snpf(buf, sizeof(buf), "%" SZOFFPSPEC "uB", sz);
+    } else {
+        for (i = 0; i < suffix_count - 1; i++) {
+            if (sz < upper) {
+                break;
+            }
+            unit = upper;
+            upper = upper * base;
+        }
+
+        /* Avoid floating point overflow */
+        val = (double)(sz / (unit / base)) / base;
+        (void)snpf(buf, sizeof(buf), "%.1lf%s", val, suffix[i]);
+    }
+    if (print) {
+        printf("%*s", col, buf);
+    }
+    return strlen(buf);
+}
+
+/*
+ * print_proc() - print process
+ */
+int print_proc(struct lsof_context *ctx) {
+    char buf[128], *cp;
+    int lc, len, st, ty;
+    int rv = 0;
+    unsigned long ul;
+    char fd[FDLEN];
+    char type[TYPEL];
+    /*
+     * If nothing in the process has been selected, skip it.
+     */
+    if (!Lp->pss)
+        return (0);
+    if (Fterse) {
+        if (Lp->pid == LastPid) /* eliminate duplicates */
+            return (0);
+        LastPid = Lp->pid;
+        /*
+         * The mode is terse and something in the process appears to have
+         * been selected.  Make sure of that by looking for a selected file,
+         * so that the HASSECURITY and HASNOSOCKSECURITY option combination
+         * won't produce a false positive result.
+         */
+        for (Lf = Lp->file; Lf; Lf = Lf->next) {
+            if (is_file_sel(ctx, Lp, Lf)) {
+                (void)printf("%d\n", Lp->pid);
+                return (1);
+            }
+        }
+        return (0);
+    }
+    /*
+     * If fields have been selected, output the process-only ones, provided
+     * that some file has also been selected.
+     */
+    if (Ffield) {
+        for (Lf = Lp->file; Lf; Lf = Lf->next) {
+            if (is_file_sel(ctx, Lp, Lf))
+                break;
+        }
+        if (!Lf)
+            return (rv);
+        rv = 1;
+        (void)printf("%c%d%c", LSOF_FID_PID, Lp->pid, Terminator);
+
+#if defined(HASTASKS)
+        if (FieldSel[LSOF_FIX_TID].st && Lp->tid)
+            (void)printf("%c%d%c", LSOF_FID_TID, Lp->tid, Terminator);
+        if (FieldSel[LSOF_FIX_TCMD].st && Lp->tcmd)
+            (void)printf("%c%s%c", LSOF_FID_TCMD, Lp->tcmd, Terminator);
+#endif /* defined(HASTASKS) */
+
+#if defined(HASZONES)
+        if (FieldSel[LSOF_FIX_ZONE].st && Fzone && Lp->zn)
+            (void)printf("%c%s%c", LSOF_FID_ZONE, Lp->zn, Terminator);
+#endif /* defined(HASZONES) */
+
+#if defined(HASSELINUX)
+        if (FieldSel[LSOF_FIX_CNTX].st && Fcntx && Lp->cntx && CntxStatus)
+            (void)printf("%c%s%c", LSOF_FID_CNTX, Lp->cntx, Terminator);
+#endif /* defined(HASSELINUX) */
+
+        if (FieldSel[LSOF_FIX_PGID].st && Fpgid)
+            (void)printf("%c%d%c", LSOF_FID_PGID, Lp->pgid, Terminator);
+
+#if defined(HASPPID)
+        if (FieldSel[LSOF_FIX_PPID].st && Fppid)
+            (void)printf("%c%d%c", LSOF_FID_PPID, Lp->ppid, Terminator);
+#endif /* defined(HASPPID) */
+
+        if (FieldSel[LSOF_FIX_CMD].st) {
+            putchar(LSOF_FID_CMD);
+            safestrprt(Lp->cmd ? Lp->cmd : "(unknown)", stdout, 0);
+            putchar(Terminator);
+        }
+        if (FieldSel[LSOF_FIX_UID].st)
+            (void)printf("%c%d%c", LSOF_FID_UID, (int)Lp->uid, Terminator);
+        if (FieldSel[LSOF_FIX_LOGIN].st) {
+            cp = printuid(ctx, (UID_ARG)Lp->uid, &ty);
+            if (ty == 0)
+                (void)printf("%c%s%c", LSOF_FID_LOGIN, cp, Terminator);
+        }
+        if (Terminator == '\0')
+            putchar('\n');
+    }
+    /*
+     * Print files.
+     */
+    for (Lf = Lp->file; Lf; Lf = Lf->next) {
+        if (!is_file_sel(ctx, Lp, Lf))
+            continue;
+        rv = 1;
+        /*
+         * If no field output selected, print dialect-specific formatted
+         * output.
+         */
+        if (!Ffield) {
+            print_file(ctx);
+            continue;
+        }
+        lc = st = 0;
+        if (FieldSel[LSOF_FIX_FD].st) {
+
+            fd_to_string(Lf->fd_type, Lf->fd_num, fd);
+            (void)printf("%c%s%c", LSOF_FID_FD, fd, Terminator);
+            lc++;
+        }
+        /*
+         * Print selected fields.
+         */
+        if (FieldSel[LSOF_FIX_ACCESS].st) {
+            (void)printf("%c%c%c", LSOF_FID_ACCESS, access_to_char(Lf->access),
+                         Terminator);
+            lc++;
+        }
+        if (FieldSel[LSOF_FIX_LOCK].st) {
+            (void)printf("%c%c%c", LSOF_FID_LOCK, lock_to_char(Lf->lock),
+                         Terminator);
+            lc++;
+        }
+        if (FieldSel[LSOF_FIX_TYPE].st) {
+            if (Lf->type != LSOF_FILE_NONE) {
+                file_type_to_string(Lf->type, Lf->unknown_file_type_number,
+                                    type, TYPEL);
+                (void)printf("%c%s%c", LSOF_FID_TYPE, type, Terminator);
+                lc++;
+            }
+        }
+
+#if defined(HASFSTRUCT)
+        if (FieldSel[LSOF_FIX_FA].st && (Fsv & FSV_FA) && (Lf->fsv & FSV_FA)) {
+            (void)printf("%c%s%c", LSOF_FID_FA,
+                         print_kptr(Lf->fsa, (char *)NULL, 0), Terminator);
+            lc++;
+        }
+        if (FieldSel[LSOF_FIX_CT].st && (Fsv & FSV_CT) && (Lf->fsv & FSV_CT)) {
+            (void)printf("%c%ld%c", LSOF_FID_CT, Lf->fct, Terminator);
+            lc++;
+        }
+        if (FieldSel[LSOF_FIX_FG].st && (Fsv & FSV_FG) && (Lf->fsv & FSV_FG) &&
+            (FsvFlagX || Lf->ffg || Lf->pof)) {
+            (void)printf("%c%s%c", LSOF_FID_FG,
+                         print_fflags(ctx, Lf->ffg, Lf->pof), Terminator);
+            lc++;
+        }
+        if (FieldSel[LSOF_FIX_NI].st && (Fsv & FSV_NI) && (Lf->fsv & FSV_NI)) {
+            (void)printf("%c%s%c", LSOF_FID_NI,
+                         print_kptr(Lf->fna, (char *)NULL, 0), Terminator);
+            lc++;
+        }
+#endif /* defined(HASFSTRUCT) */
+
+        if (FieldSel[LSOF_FIX_DEVCH].st && Lf->dev_ch && Lf->dev_ch[0]) {
+            for (cp = Lf->dev_ch; *cp == ' '; cp++)
+                ;
+            if (*cp) {
+                (void)printf("%c%s%c", LSOF_FID_DEVCH, cp, Terminator);
+                lc++;
+            }
+        }
+        if (FieldSel[LSOF_FIX_DEVN].st && Lf->dev_def) {
+            if (sizeof(unsigned long) > sizeof(dev_t))
+                ul = (unsigned long)((unsigned int)Lf->dev);
+            else
+                ul = (unsigned long)Lf->dev;
+            (void)printf("%c0x%lx%c", LSOF_FID_DEVN, ul, Terminator);
+            lc++;
+        }
+        if (FieldSel[LSOF_FIX_RDEV].st && Lf->rdev_def) {
+            if (sizeof(unsigned long) > sizeof(dev_t))
+                ul = (unsigned long)((unsigned int)Lf->rdev);
+            else
+                ul = (unsigned long)Lf->rdev;
+            (void)printf("%c0x%lx%c", LSOF_FID_RDEV, ul, Terminator);
+            lc++;
+        }
+        if (FieldSel[LSOF_FIX_SIZE].st && Lf->sz_def) {
+            putchar(LSOF_FID_SIZE);
+
+            (void)snpf(buf, sizeof(buf), SzOffFmt_d, Lf->sz);
+            cp = buf;
+
+            (void)printf("%s", cp);
+            putchar(Terminator);
+            lc++;
+        }
+        if (FieldSel[LSOF_FIX_OFFSET].st && Lf->off_def) {
+            putchar(LSOF_FID_OFFSET);
+
+            (void)snpf(buf, sizeof(buf), SzOffFmt_0t, Lf->off);
+            cp = buf;
+
+            len = strlen(cp);
+            if (OffDecDig && len > (OffDecDig + 2)) {
+
+                (void)snpf(buf, sizeof(buf), SzOffFmt_x, Lf->off);
+                cp = buf;
+            }
+            (void)printf("%s", cp);
+            putchar(Terminator);
+            lc++;
+        }
+        if (FieldSel[LSOF_FIX_INODE].st && Lf->inp_ty == 1) {
+            putchar(LSOF_FID_INODE);
+            (void)printf(InodeFmt_d, Lf->inode);
+            putchar(Terminator);
+            lc++;
+        }
+        if (FieldSel[LSOF_FIX_NLINK].st && Lf->nlink_def) {
+            (void)printf("%c%ld%c", LSOF_FID_NLINK, Lf->nlink, Terminator);
+            lc++;
+        }
+        if (FieldSel[LSOF_FIX_PROTO].st && Lf->inp_ty == 2) {
+            for (cp = Lf->iproto; *cp == ' '; cp++)
+                ;
+            if (*cp) {
+                (void)printf("%c%s%c", LSOF_FID_PROTO, cp, Terminator);
+                lc++;
+            }
+        }
+        if (FieldSel[LSOF_FIX_STREAM].st && Lf->nm && Lf->is_stream) {
+            if (strncmp(Lf->nm, "STR:", 4) == 0 ||
+                strcmp(Lf->iproto, "STR") == 0) {
+                putchar(LSOF_FID_STREAM);
+                printname(ctx, 0);
+                putchar(Terminator);
+                lc++;
+                st++;
+            }
+        }
+        if (st == 0 && FieldSel[LSOF_FIX_NAME].st) {
+            putchar(LSOF_FID_NAME);
+            printname(ctx, 0);
+            putchar(Terminator);
+            lc++;
+        }
+        if (Lf->lts.type >= 0 && FieldSel[LSOF_FIX_TCPTPI].st) {
+            print_tcptpi(ctx, 0);
+            lc++;
+        }
+        if (Terminator == '\0' && lc)
+            putchar('\n');
+    }
+    return (rv);
+}
+
+#if defined(HASFSTRUCT)
+static char *alloc_fflbuf(struct lsof_context *ctx, char **bp, int *al, int lr);
+
+/*
+ * alloc_fflbuf() - allocate file flags print buffer
+ */
+
+static char *alloc_fflbuf(struct lsof_context *ctx,
+                          char **bp, /* current buffer pointer */
+                          int *al,   /* current allocated length */
+                          int lr)    /* length required */
+{
+    int sz;
+
+    sz = (int)(lr + 1); /* allocate '\0' space */
+    if (*bp && (sz <= *al))
+        return (*bp);
+    if (*bp)
+        *bp = (char *)realloc((MALLOC_P *)*bp, (MALLOC_S)sz);
+    else
+        *bp = (char *)malloc((MALLOC_S)sz);
+    if (!*bp) {
+        (void)fprintf(stderr, "%s: no space (%d) for print flags\n", Pn, sz);
+        Error(ctx);
+    }
+    *al = sz;
+    return (*bp);
+}
+#endif /* defined(HASFSTRUCT) */
+
+#if defined(HASFSTRUCT)
+/*
+ * print_fflags() - print interpreted f_flag[s]
+ */
+char *print_fflags(struct lsof_context *ctx,
+                   long ffg, /* file structure's flags value */
+                   long pof) /* process open files flags value */
+{
+    int al, ct, fx;
+    static int bl = 0;
+    static char *bp = (char *)NULL;
+    char *sep;
+    int sepl;
+    struct pff_tab *tp;
+    long wf;
+    char xbuf[64];
+    /*
+     * Reduce the supplied flags according to the definitions in Pff_tab[] and
+     * Pof_tab[].
+     */
+    for (ct = fx = 0; fx < 2; fx++) {
+        if (fx == 0) {
+            sep = "";
+            sepl = 0;
+            tp = Pff_tab;
+            wf = ffg;
+        } else {
+            sep = ";";
+            sepl = 1;
+            tp = Pof_tab;
+            wf = pof;
+        }
+        for (; wf && !FsvFlagX; ct += al) {
+            while (tp->nm) {
+                if (wf & tp->val)
+                    break;
+                tp++;
+            }
+            if (!tp->nm)
+                break;
+            al = (int)strlen(tp->nm) + sepl;
+            bp = alloc_fflbuf(ctx, &bp, &bl, al + ct);
+            (void)snpf(bp + ct, al + 1, "%s%s", sep, tp->nm);
+            sep = ",";
+            sepl = 1;
+            wf &= ~(tp->val);
+        }
+        /*
+         * If flag bits remain, print them in hex.  If hex output was
+         * specified with +fG, print all flag values, including zero,
+         * in hex.
+         */
+        if (wf || FsvFlagX) {
+            (void)snpf(xbuf, sizeof(xbuf), "0x%lx", wf);
+            al = (int)strlen(xbuf) + sepl;
+            bp = alloc_fflbuf(ctx, &bp, &bl, al + ct);
+            (void)snpf(bp + ct, al + 1, "%s%s", sep, xbuf);
+            ct += al;
+        }
+    }
+    /*
+     * Make sure there is at least a NUL terminated reply.
+     */
+    if (!bp) {
+        bp = alloc_fflbuf(ctx, &bp, &bl, 0);
+        *bp = '\0';
+    }
+    return (bp);
+}
+#endif /* defined(HASFSTRUCT) */
diff --git a/src/ptti.c b/src/ptti.c
new file mode 100644
index 0000000..ae3e005
--- /dev/null
+++ b/src/ptti.c
@@ -0,0 +1,1355 @@
+/*
+ * ptti.c -- BSD style print_tcptpi() function for lsof library
+ */
+
+/*
+ * 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.
+ */
+
+#define TCPSTATES /* activate tcpstates[] */
+
+#include "common.h"
+#include "machine.h"
+
+#if defined(USE_LIB_PRINT_TCPTPI)
+
+/*
+ * build_IPstates() -- build the TCP and UDP state tables
+ *
+ * Note: this module does not support a UDP state table.
+ */
+
+void build_IPstates(struct lsof_context *ctx) {
+
+    /*
+     * Set the TcpNstates global variable.
+     */
+    TcpNstates = TCP_NSTATES;
+    TcpSt = (char **)&tcpstates;
+}
+
+/*
+ * print_tcptpi() - print TCP/TPI info
+ */
+
+void print_tcptpi(struct lsof_context *ctx, int nl) /* 1 == '\n' required */
+{
+    int ps = 0;
+    int s;
+
+    if ((Ftcptpi & TCPTPI_STATE) && Lf->lts.type == 0) {
+        if (Ffield)
+            (void)printf("%cST=", LSOF_FID_TCPTPI);
+        else
+            putchar('(');
+        if (!TcpNstates)
+            (void)build_IPstates(ctx);
+        if ((s = Lf->lts.state.i) < 0 || s >= TcpNstates)
+            (void)printf("UNKNOWN_TCP_STATE_%d", s);
+        else
+            (void)fputs(TcpSt[s], stdout);
+        ps++;
+        if (Ffield)
+            putchar(Terminator);
+    }
+
+#    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_ACCEPTFILTER)
+            if (opt & SO_ACCEPTFILTER) {
+                (void)printf("%cACCEPTFILTER", sep);
+                opt &= ~SO_ACCEPTFILTER;
+                sep = ',';
+            }
+#        endif /* defined(SO_ACCEPTFILTER) */
+
+#        if defined(SO_AUDIT)
+            if (opt & SO_AUDIT) {
+                (void)printf("%cAUDIT", sep);
+                opt &= ~SO_AUDIT;
+                sep = ',';
+            }
+#        endif /* defined(SO_AUDIT) */
+
+#        if defined(SO_BINDANY)
+            if (opt & SO_BINDANY) {
+                (void)printf("%cBINDANY", sep);
+                opt &= ~SO_BINDANY;
+                sep = ',';
+            }
+#        endif /* defined(SO_BINDANY) */
+
+#        if defined(SO_BINTIME)
+            if (opt & SO_BINTIME) {
+                (void)printf("%cBINTIME", sep);
+                opt &= ~SO_BINTIME;
+                sep = ',';
+            }
+#        endif /* defined(SO_BINTIME) */
+
+#        if defined(SO_BROADCAST)
+            if (opt & SO_BROADCAST) {
+                (void)printf("%cBROADCAST", sep);
+                opt &= ~SO_BROADCAST;
+                sep = ',';
+            }
+#        endif /* defined(SO_BROADCAST) */
+
+#        if defined(SO_CKSUMRECV)
+            if (opt & SO_CKSUMRECV) {
+                (void)printf("%cCKSUMRECV", sep);
+                opt &= ~SO_CKSUMRECV;
+                sep = ',';
+            }
+#        endif /* defined(SO_CKSUMRECV) */
+
+#        if defined(SO_CLUA_IN_NOALIAS)
+            if (opt & SO_CLUA_IN_NOALIAS) {
+                (void)printf("%cCLUA_IN_NOALIAS", sep);
+                opt &= ~SO_CLUA_IN_NOALIAS;
+                sep = ',';
+            }
+#        endif /* defined(SO_CLUA_IN_NOALIAS) */
+
+#        if defined(SO_CLUA_IN_NOLOCAL)
+            if (opt & SO_CLUA_IN_NOLOCAL) {
+                (void)printf("%cCLUA_IN_NOLOCAL", sep);
+                opt &= ~SO_CLUA_IN_NOLOCAL;
+                sep = ',';
+            }
+#        endif /* defined(SO_CLUA_IN_NOLOCAL) */
+
+#        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_DONTTRUNC)
+            if (opt & SO_DONTTRUNC) {
+                (void)printf("%cDONTTRUNC", sep);
+                opt &= ~SO_DONTTRUNC;
+                sep = ',';
+            }
+#        endif /* defined(SO_DONTTRUNC) */
+
+#        if defined(SO_EXPANDED_RIGHTS)
+            if (opt & SO_EXPANDED_RIGHTS) {
+                (void)printf("%cEXPANDED_RIGHTS", sep);
+                opt &= ~SO_EXPANDED_RIGHTS;
+                sep = ',';
+            }
+#        endif /* defined(SO_EXPANDED_RIGHTS) */
+
+#        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_KERNACCEPT)
+            if (opt & SO_KERNACCEPT) {
+                (void)printf("%cKERNACCEPT", sep);
+                opt &= ~SO_KERNACCEPT;
+                sep = ',';
+            }
+#        endif /* defined(SO_KERNACCEPT) */
+
+#        if defined(SO_IMASOCKET)
+            if (opt & SO_IMASOCKET) {
+                (void)printf("%cIMASOCKET", sep);
+                opt &= ~SO_IMASOCKET;
+                sep = ',';
+            }
+#        endif /* defined(SO_IMASOCKET) */
+
+#        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_PAIRABLE)
+            if (opt & SO_PAIRABLE) {
+                (void)printf("%cPAIRABLE", sep);
+                opt &= ~SO_PAIRABLE;
+                sep = ',';
+            }
+#        endif /* defined(SO_PAIRABLE) */
+
+#        if defined(SO_RESVPORT)
+            if (opt & SO_RESVPORT) {
+                (void)printf("%cRESVPORT", sep);
+                opt &= ~SO_RESVPORT;
+                sep = ',';
+            }
+#        endif /* defined(SO_RESVPORT) */
+
+#        if defined(SO_NOREUSEADDR)
+            if (opt & SO_NOREUSEADDR) {
+                (void)printf("%cNOREUSEADDR", sep);
+                opt &= ~SO_NOREUSEADDR;
+                sep = ',';
+            }
+#        endif /* defined(SO_NOREUSEADDR) */
+
+#        if defined(SO_NOSIGPIPE)
+            if (opt & SO_NOSIGPIPE) {
+                (void)printf("%cNOSIGPIPE", sep);
+                opt &= ~SO_NOSIGPIPE;
+                sep = ',';
+            }
+#        endif /* defined(SO_NOSIGPIPE) */
+
+#        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 (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 defined(SO_REUSEALIASPORT)
+            if (opt & SO_REUSEALIASPORT) {
+                (void)printf("%cREUSEALIASPORT", sep);
+                opt &= ~SO_REUSEALIASPORT;
+                sep = ',';
+            }
+#        endif /* defined(SO_REUSEALIASPORT) */
+
+#        if defined(SO_REUSEPORT)
+            if (opt & SO_REUSEPORT) {
+                (void)printf("%cREUSEPORT", sep);
+                opt &= ~SO_REUSEPORT;
+                sep = ',';
+            }
+#        endif /* defined(SO_REUSEPORT) */
+
+#        if defined(SO_REUSERAD)
+            if (opt & SO_REUSERAD) {
+                (void)printf("%cREUSERAD", sep);
+                opt &= ~SO_REUSERAD;
+                sep = ',';
+            }
+#        endif /* defined(SO_REUSERAD) */
+
+#        if defined(SO_SECURITY_REQUEST)
+            if (opt & SO_SECURITY_REQUEST) {
+                (void)printf("%cSECURITY_REQUEST", sep);
+                opt &= ~SO_SECURITY_REQUEST;
+                sep = ',';
+            }
+#        endif /* defined(SO_SECURITY_REQUEST) */
+
+            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_UMC)
+            if (opt & SO_UMC) {
+                (void)printf("%cUMC", sep);
+                opt &= ~SO_UMC;
+                sep = ',';
+            }
+#        endif /* defined(SO_UMC) */
+
+#        if defined(SO_USE_IFBUFS)
+            if (opt & SO_USE_IFBUFS) {
+                (void)printf("%cUSE_IFBUFS", sep);
+                opt &= ~SO_USE_IFBUFS;
+                sep = ',';
+            }
+#        endif /* defined(SO_USE_IFBUFS) */
+
+#        if defined(SO_USELOOPBACK)
+            if (opt & SO_USELOOPBACK) {
+                (void)printf("%cUSELOOPBACK", sep);
+                opt &= ~SO_USELOOPBACK;
+                sep = ',';
+            }
+#        endif /* defined(SO_USELOOPBACK) */
+
+#        if defined(SO_WANTMORE)
+            if (opt & SO_WANTMORE) {
+                (void)printf("%cWANTMORE", sep);
+                opt &= ~SO_WANTMORE;
+                sep = ',';
+            }
+#        endif /* defined(SO_WANTMORE) */
+
+#        if defined(SO_WANTOOBFLAG)
+            if (opt & SO_WANTOOBFLAG) {
+                (void)printf("%cWANTOOBFLAG", sep);
+                opt &= ~SO_WANTOOBFLAG;
+                sep = ',';
+            }
+#        endif /* defined(SO_WANTOOBFLAG) */
+
+            if (opt)
+                (void)printf("%cUNKNOWN=%#x", sep, opt);
+            if (Ffield)
+                putchar(Terminator);
+        }
+    }
+#    endif /* defined(HASSOOPT) */
+
+#    if defined(HASSOSTATE)
+    if (Ftcptpi & TCPTPI_FLAGS) {
+        unsigned 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_BOUND)
+            if (ss & SS_BOUND) {
+                (void)printf("%cBOUND", sep);
+                ss &= ~SS_BOUND;
+                sep = ',';
+            }
+#        endif /* defined(SS_BOUND) */
+
+#        if defined(HASSBSTATE)
+#            if defined(SBS_CANTRCVMORE)
+            if (Lf->lts.sbs_rcv & SBS_CANTRCVMORE) {
+                (void)printf("%cCANTRCVMORE", sep);
+                Lf->lts.sbs_rcv &= ~SBS_CANTRCVMORE;
+                sep = ',';
+            }
+#            endif /* defined(SBS_CANTRCVMORE) */
+
+#            if defined(SBS_CANTSENDMORE)
+            if (Lf->lts.sbs_snd & SBS_CANTSENDMORE) {
+                (void)printf("%cCANTSENDMORE", sep);
+                Lf->lts.sbs_snd &= ~SBS_CANTSENDMORE;
+                sep = ',';
+            }
+#            endif /* defined(SS_CANTSENDMORE) */
+#        else      /* !defined(HASSBSTATE) */
+
+#            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) */
+#        endif     /* defined(HASSBSTATE) */
+
+#        if defined(SS_COMP)
+            if (ss & SS_COMP) {
+                (void)printf("%cCOMP", sep);
+                ss &= ~SS_COMP;
+                sep = ',';
+            }
+#        endif /* defined(SS_COMP) */
+
+#        if defined(SS_CONNECTOUT)
+            if (ss & SS_CONNECTOUT) {
+                (void)printf("%cCONNECTOUT", sep);
+                ss &= ~SS_CONNECTOUT;
+                sep = ',';
+            }
+#        endif /* defined(SS_CONNECTOUT) */
+
+#        if defined(SS_HIPRI)
+            if (ss & SS_HIPRI) {
+                (void)printf("%cHIPRI", sep);
+                ss &= ~SS_HIPRI;
+                sep = ',';
+            }
+#        endif /* defined(SS_HIPRI) */
+
+#        if defined(SS_IGNERR)
+            if (ss & SS_IGNERR) {
+                (void)printf("%cIGNERR", sep);
+                ss &= ~SS_IGNERR;
+                sep = ',';
+            }
+#        endif /* defined(SS_IGNERR) */
+
+#        if defined(SS_INCOMP)
+            if (ss & SS_INCOMP) {
+                (void)printf("%cINCOMP", sep);
+                ss &= ~SS_INCOMP;
+                sep = ',';
+            }
+#        endif /* defined(SS_INCOMP) */
+
+#        if defined(SS_IOCWAIT)
+            if (ss & SS_IOCWAIT) {
+                (void)printf("%cIOCWAIT", sep);
+                ss &= ~SS_IOCWAIT;
+                sep = ',';
+            }
+#        endif /* defined(SS_IOCWAIT) */
+
+#        if defined(SS_ISCONFIRMING)
+            if (ss & SS_ISCONFIRMING) {
+                (void)printf("%cISCONFIRMING", sep);
+                ss &= ~SS_ISCONFIRMING;
+                sep = ',';
+            }
+#        endif /* defined(SS_ISCONFIRMING) */
+
+#        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_MORETOSEND)
+            if (ss & SS_MORETOSEND) {
+                (void)printf("%cMORETOSEND", sep);
+                ss &= ~SS_MORETOSEND;
+                sep = ',';
+            }
+#        endif /* defined(SS_MORETOSEND) */
+
+#        if defined(SS_NBIO)
+            if (ss & SS_NBIO) {
+                (void)printf("%cNBIO", sep);
+                ss &= ~SS_NBIO;
+                sep = ',';
+            }
+#        endif /* defined(SS_NBIO) */
+
+#        if defined(SS_NOCONN)
+            if (ss & SS_NOCONN) {
+                (void)printf("%cNOCONN", sep);
+                ss &= ~SS_NOCONN;
+                sep = ',';
+            }
+#        endif /* defined(SS_NOCONN) */
+
+#        if defined(SS_NODELETE)
+            if (ss & SS_NODELETE) {
+                (void)printf("%cNODELETE", sep);
+                ss &= ~SS_NODELETE;
+                sep = ',';
+            }
+#        endif /* defined(SS_NODELETE) */
+
+#        if defined(SS_NOFDREF)
+            if (ss & SS_NOFDREF) {
+                (void)printf("%cNOFDREF", sep);
+                ss &= ~SS_NOFDREF;
+                sep = ',';
+            }
+#        endif /* defined(SS_NOFDREF) */
+
+#        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_PRIV)
+            if (ss & SS_PRIV) {
+                (void)printf("%cPRIV", sep);
+                ss &= ~SS_PRIV;
+                sep = ',';
+            }
+#        endif /* defined(SS_PRIV) */
+
+#        if defined(SS_QUEUE)
+            if (ss & SS_QUEUE) {
+                (void)printf("%cQUEUE", sep);
+                ss &= ~SS_QUEUE;
+                sep = ',';
+            }
+#        endif /* defined(SS_QUEUE) */
+
+#        if defined(HASSBSTATE)
+#            if defined(SBS_RCVATMARK)
+            if (Lf->lts.sbs_rcv & SBS_RCVATMARK) {
+                (void)printf("%cRCVATMARK", sep);
+                Lf->lts.sbs_rcv &= ~SBS_RCVATMARK;
+                sep = ',';
+            }
+#            endif /* defined(SBS_RCVATMARK) */
+
+#        else /* !defined(HASSBSTATE) */
+#            if defined(SS_RCVATMARK)
+            if (ss & SS_RCVATMARK) {
+                (void)printf("%cRCVATMARK", sep);
+                ss &= ~SS_RCVATMARK;
+                sep = ',';
+            }
+#            endif /* defined(SS_RCVATMARK) */
+#        endif     /* defined(HASSBSTATE) */
+
+#        if defined(SS_READWAIT)
+            if (ss & SS_READWAIT) {
+                (void)printf("%cREADWAIT", sep);
+                ss &= ~SS_READWAIT;
+                sep = ',';
+            }
+#        endif /* defined(SS_READWAIT) */
+
+#        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_SIGREAD)
+            if (ss & SS_SIGREAD) {
+                (void)printf("%cSIGREAD", sep);
+                ss &= ~SS_SIGREAD;
+                sep = ',';
+            }
+#        endif /* defined(SS_SIGREAD) */
+
+#        if defined(SS_SIGWRITE)
+            if (ss & SS_SIGWRITE) {
+                (void)printf("%cSIGWRITE", sep);
+                ss &= ~SS_SIGWRITE;
+                sep = ',';
+            }
+#        endif /* defined(SS_SIGWRITE) */
+
+#        if defined(SS_SPLICED)
+            if (ss & SS_SPLICED) {
+                (void)printf("%cSPLICED", sep);
+                ss &= ~SS_SPLICED;
+                sep = ',';
+            }
+#        endif /* defined(SS_SPLICED) */
+
+#        if defined(SS_WRITEWAIT)
+            if (ss & SS_WRITEWAIT) {
+                (void)printf("%cWRITEWAIT", sep);
+                ss &= ~SS_WRITEWAIT;
+                sep = ',';
+            }
+#        endif /* defined(SS_WRITEWAIT) */
+
+#        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_CANT_TXSACK)
+            if (topt & TF_CANT_TXSACK) {
+                (void)printf("%cCANT_TXSACK", sep);
+                topt &= ~TF_CANT_TXSACK;
+                sep = ',';
+            }
+#        endif /* defined(TF_CANT_TXSACK) */
+
+#        if defined(TF_DEAD)
+            if (topt & TF_DEAD) {
+                (void)printf("%cDEAD", sep);
+                topt &= ~TF_DEAD;
+                sep = ',';
+            }
+#        endif /* defined(TF_DEAD) */
+
+#        if defined(TF_DELACK)
+            if (topt & TF_DELACK) {
+                (void)printf("%cDELACK", sep);
+                topt &= ~TF_DELACK;
+                sep = ',';
+            }
+#        endif /* defined(TF_DELACK) */
+
+#        if defined(TF_DELAY_ACK)
+            if (topt & TF_DELAY_ACK) {
+                (void)printf("%cDELAY_ACK", sep);
+                topt &= ~TF_DELAY_ACK;
+                sep = ',';
+            }
+#        endif /* defined(TF_DELAY_ACK) */
+
+#        if defined(TF_DISABLE_ECN)
+            if (topt & TF_DISABLE_ECN) {
+                (void)printf("%cDISABLE_ECN", sep);
+                topt &= ~TF_DISABLE_ECN;
+                sep = ',';
+            }
+#        endif /* defined(TF_DISABLE_ECN) */
+
+#        if defined(TF_ECN)
+            if (topt & TF_ECN) {
+                (void)printf("%cECN", sep);
+                topt &= ~TF_ECN;
+                sep = ',';
+            }
+#        endif /* defined(TF_ECN) */
+
+#        if defined(TF_ECN_PERMIT)
+            if (topt & TF_ECN_PERMIT) {
+                (void)printf("%cECN_PERMIT", sep);
+                topt &= ~TF_ECN_PERMIT;
+                sep = ',';
+            }
+#        endif /* defined(TF_ECN_PERMIT) */
+
+#        if defined(TF_FASTRECOVERY)
+            if (topt & TF_FASTRECOVERY) {
+                (void)printf("%cFASTRECOVERY", sep);
+                topt &= ~TF_FASTRECOVERY;
+                sep = ',';
+            }
+#        endif /* defined(TF_FASTRECOVERY) */
+
+#        if defined(TF_FASTRXMT_PHASE)
+            if (topt & TF_FASTRXMT_PHASE) {
+                (void)printf("%cFASTRXMT_PHASE", sep);
+                topt &= ~TF_FASTRXMT_PHASE;
+                sep = ',';
+            }
+#        endif /* defined(TF_FASTRXMT_PHASE) */
+
+#        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_IGNR_RXSACK)
+            if (topt & TF_IGNR_RXSACK) {
+                (void)printf("%cIGNR_RXSACK", sep);
+                topt &= ~TF_IGNR_RXSACK;
+                sep = ',';
+            }
+#        endif /* defined(TF_IGNR_RXSACK) */
+
+#        if defined(TF_IOLOCK)
+            if (topt & TF_IOLOCK) {
+                (void)printf("%cIOLOCK", sep);
+                topt &= ~TF_IOLOCK;
+                sep = ',';
+            }
+#        endif /* defined(TF_IOLOCK) */
+
+#        if defined(TF_LARGESEND)
+            if (topt & TF_LARGESEND) {
+                (void)printf("%cLARGESEND", sep);
+                topt &= ~TF_LARGESEND;
+                sep = ',';
+            }
+#        endif /* defined(TF_LARGESEND) */
+
+#        if defined(TF_LASTIDLE)
+            if (topt & TF_LASTIDLE) {
+                (void)printf("%cLASTIDLE", sep);
+                topt &= ~TF_LASTIDLE;
+                sep = ',';
+            }
+#        endif /* defined(TF_LASTIDLE) */
+
+#        if defined(TF_LQ_OVERFLOW)
+            if (topt & TF_LQ_OVERFLOW) {
+                (void)printf("%cLQ_OVERFLOW", sep);
+                topt &= ~TF_LQ_OVERFLOW;
+                sep = ',';
+            }
+#        endif /* defined(TF_LQ_OVERFLOW) */
+
+            if (Lf->lts.msss) {
+                (void)printf("%cMSS=%lu", sep, Lf->lts.mss);
+                sep = ',';
+            }
+
+#        if defined(TF_MORETOCOME)
+            if (topt & TF_MORETOCOME) {
+                (void)printf("%cMORETOCOME", sep);
+                topt &= ~TF_MORETOCOME;
+                sep = ',';
+            }
+#        endif /* defined(TF_MORETOCOME) */
+
+#        if defined(TF_NEEDACK)
+            if (topt & TF_NEEDACK) {
+                (void)printf("%cNEEDACK", sep);
+                topt &= ~TF_NEEDACK;
+                sep = ',';
+            }
+#        endif /* defined(TF_NEEDACK) */
+
+#        if defined(TF_NEEDCLOSE)
+            if (topt & TF_NEEDCLOSE) {
+                (void)printf("%cNEEDCLOSE", sep);
+                topt &= ~TF_NEEDCLOSE;
+                sep = ',';
+            }
+#        endif /* defined(TF_NEEDCLOSE) */
+
+#        if defined(TF_NEEDFIN)
+            if (topt & TF_NEEDFIN) {
+                (void)printf("%cNEEDFIN", sep);
+                topt &= ~TF_NEEDFIN;
+                sep = ',';
+            }
+#        endif /* defined(TF_NEEDFIN) */
+
+#        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_NEEDSYN)
+            if (topt & TF_NEEDSYN) {
+                (void)printf("%cNEEDSYN", sep);
+                topt &= ~TF_NEEDSYN;
+                sep = ',';
+            }
+#        endif /* defined(TF_NEEDSYN) */
+
+#        if defined(TF_NEEDTIMER)
+            if (topt & TF_NEEDTIMER) {
+                (void)printf("%cNEEDTIMER", sep);
+                topt &= ~TF_NEEDTIMER;
+                sep = ',';
+            }
+#        endif /* defined(TF_NEEDTIMER) */
+
+#        if defined(TF_NEWRENO_RXMT)
+            if (topt & TF_NEWRENO_RXMT) {
+                (void)printf("%cNEWRENO_RXMT", sep);
+                topt &= ~TF_NEWRENO_RXMT;
+                sep = ',';
+            }
+#        endif /* defined(TF_NEWRENO_RXMT) */
+
+#        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_NOPUSH)
+            if (topt & TF_NOPUSH) {
+                (void)printf("%cNOPUSH", sep);
+                topt &= ~TF_NOPUSH;
+                sep = ',';
+            }
+#        endif /* defined(TF_NOPUSH) */
+
+#        if defined(TF_NO_PMTU)
+            if (topt & TF_NO_PMTU) {
+                (void)printf("%cNO_PMTU", sep);
+                topt &= ~TF_NO_PMTU;
+                sep = ',';
+            }
+#        endif /* defined(TF_NO_PMTU) */
+
+#        if defined(TF_RAW)
+            if (topt & TF_RAW) {
+                (void)printf("%cRAW", sep);
+                topt &= ~TF_RAW;
+                sep = ',';
+            }
+#        endif /* defined(TF_RAW) */
+
+#        if defined(TF_RCVD_CC)
+            if (topt & TF_RCVD_CC) {
+                (void)printf("%cRCVD_CC", sep);
+                topt &= ~TF_RCVD_CC;
+                sep = ',';
+            }
+#        endif /* defined(TF_RCVD_CC) */
+
+#        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_CE)
+            if (topt & TF_RCVD_CE) {
+                (void)printf("%cRCVD_CE", sep);
+                topt &= ~TF_RCVD_CE;
+                sep = ',';
+            }
+#        endif /* defined(TF_RCVD_CE) */
+
+#        if defined(TF_RCVD_TS)
+            if (topt & TF_RCVD_TS) {
+                (void)printf("%cRCVD_TS", sep);
+                topt &= ~TF_RCVD_TS;
+                sep = ',';
+            }
+#        endif /* defined(TF_RCVD_TS) */
+
+#        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_RCVD_WS)
+            if (topt & TF_RCVD_WS) {
+                (void)printf("%cRCVD_WS", sep);
+                topt &= ~TF_RCVD_WS;
+                sep = ',';
+            }
+#        endif /* defined(TF_RCVD_WS) */
+
+#        if defined(TF_REASSEMBLING)
+            if (topt & TF_REASSEMBLING) {
+                (void)printf("%cREASSEMBLING", sep);
+                topt &= ~TF_REASSEMBLING;
+                sep = ',';
+            }
+#        endif /* defined(TF_REASSEMBLING) */
+
+#        if defined(TF_REQ_CC)
+            if (topt & TF_REQ_CC) {
+                (void)printf("%cREQ_CC", sep);
+                topt &= ~TF_REQ_CC;
+                sep = ',';
+            }
+#        endif /* defined(TF_REQ_CC) */
+
+#        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_RFC1323)
+            if (topt & TF_RFC1323) {
+                (void)printf("%cRFC1323", sep);
+                topt &= ~TF_RFC1323;
+                sep = ',';
+            }
+#        endif /* defined(TF_RFC1323) */
+
+#        if defined(TF_RXWIN0SENT)
+            if (topt & TF_RXWIN0SENT) {
+                (void)printf("%cRXWIN0SENT", sep);
+                topt &= ~TF_RXWIN0SENT;
+                sep = ',';
+            }
+#        endif /* defined(TF_RXWIN0SENT) */
+
+#        if defined(TF_SACK_GENERATE)
+            if (topt & TF_SACK_GENERATE) {
+                (void)printf("%cSACK_GENERATE", sep);
+                topt &= ~TF_SACK_GENERATE;
+                sep = ',';
+            }
+#        endif /* defined(TF_SACK_GENERATE) */
+
+#        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_SACK_PROCESS)
+            if (topt & TF_SACK_PROCESS) {
+                (void)printf("%cSACK_PROCESS", sep);
+                topt &= ~TF_SACK_PROCESS;
+                sep = ',';
+            }
+#        endif /* defined(TF_SACK_PROCESS) */
+
+#        if defined(TF_SEND)
+            if (topt & TF_SEND) {
+                (void)printf("%cSEND", sep);
+                topt &= ~TF_SEND;
+                sep = ',';
+            }
+#        endif /* defined(TF_SEND) */
+
+#        if defined(TF_SEND_AND_DISCONNECT)
+            if (topt & TF_SEND_AND_DISCONNECT) {
+                (void)printf("%cSEND_AND_DISCONNECT", sep);
+                topt &= ~TF_SEND_AND_DISCONNECT;
+                sep = ',';
+            }
+#        endif /* defined(TF_SEND_AND_DISCONNECT) */
+
+#        if defined(TF_SENDCCNEW)
+            if (topt & TF_SENDCCNEW) {
+                (void)printf("%cSENDCCNEW", sep);
+                topt &= ~TF_SENDCCNEW;
+                sep = ',';
+            }
+#        endif /* defined(TF_SENDCCNEW) */
+
+#        if defined(TF_SEND_CWR)
+            if (topt & TF_SEND_CWR) {
+                (void)printf("%cSEND_CWR", sep);
+                topt &= ~TF_SEND_CWR;
+                sep = ',';
+            }
+#        endif /* defined(TF_SEND_CWR) */
+
+#        if defined(TF_SEND_ECHO)
+            if (topt & TF_SEND_ECHO) {
+                (void)printf("%cSEND_ECHO", sep);
+                topt &= ~TF_SEND_ECHO;
+                sep = ',';
+            }
+#        endif /* defined(TF_SEND_ECHO) */
+
+#        if defined(TF_SEND_TSTMP)
+            if (topt & TF_SEND_TSTMP) {
+                (void)printf("%cSEND_TSTMP", sep);
+                topt &= ~TF_SEND_TSTMP;
+                sep = ',';
+            }
+#        endif /* defined(TF_SEND_TSTMP) */
+
+#        if defined(TF_SENTFIN)
+            if (topt & TF_SENTFIN) {
+                (void)printf("%cSENTFIN", sep);
+                topt &= ~TF_SENTFIN;
+                sep = ',';
+            }
+#        endif /* defined(TF_SENTFIN) */
+
+#        if defined(TF_SENT_TS)
+            if (topt & TF_SENT_TS) {
+                (void)printf("%cSENT_TS", sep);
+                topt &= ~TF_SENT_TS;
+                sep = ',';
+            }
+#        endif /* defined(TF_SENT_TS) */
+
+#        if defined(TF_SENT_WS)
+            if (topt & TF_SENT_WS) {
+                (void)printf("%cSENT_WS", sep);
+                topt &= ~TF_SENT_WS;
+                sep = ',';
+            }
+#        endif /* defined(TF_SENT_WS) */
+
+#        if defined(TF_SIGNATURE)
+            if (topt & TF_SIGNATURE) {
+                (void)printf("%cSIGNATURE", sep);
+                topt &= ~TF_SIGNATURE;
+                sep = ',';
+            }
+#        endif /* defined(TF_SIGNATURE) */
+
+#        if defined(TF_SLOWLINK)
+            if (topt & TF_SLOWLINK) {
+                (void)printf("%cSLOWLINK", sep);
+                topt &= ~TF_SLOWLINK;
+                sep = ',';
+            }
+#        endif /* defined(TF_SLOWLINK) */
+
+#        if defined(TF_STDURG)
+            if (topt & TF_STDURG) {
+                (void)printf("%cSTDURG", sep);
+                topt &= ~TF_STDURG;
+                sep = ',';
+            }
+#        endif /* defined(TF_STDURG) */
+
+#        if defined(TF_SYN_REXMT)
+            if (topt & TF_SYN_REXMT) {
+                (void)printf("%cSYN_REXMT", sep);
+                topt &= ~TF_SYN_REXMT;
+                sep = ',';
+            }
+#        endif /* defined(TF_SYN_REXMT) */
+
+#        if defined(TF_UIOMOVED)
+            if (topt & TF_UIOMOVED) {
+                (void)printf("%cUIOMOVED", sep);
+                topt &= ~TF_UIOMOVED;
+                sep = ',';
+            }
+#        endif /* defined(TF_UIOMOVED) */
+
+#        if defined(TF_USE_SCALE)
+            if (topt & TF_USE_SCALE) {
+                (void)printf("%cUSE_SCALE", sep);
+                topt &= ~TF_USE_SCALE;
+                sep = ',';
+            }
+#        endif /* defined(TF_USE_SCALE) */
+
+#        if defined(TF_WASIDLE)
+            if (topt & TF_WASIDLE) {
+                (void)printf("%cWASIDLE", sep);
+                topt &= ~TF_WASIDLE;
+                sep = ',';
+            }
+#        endif /* defined(TF_WASIDLE) */
+
+#        if defined(TF_WASFRECOVERY)
+            if (topt & TF_WASFRECOVERY) {
+                (void)printf("%cWASFRECOVERY", sep);
+                topt &= ~TF_WASFRECOVERY;
+                sep = ',';
+            }
+#        endif /* defined(TF_WASFRECOVERY) */
+
+#        if defined(TF_WILL_SACK)
+            if (topt & TF_WILL_SACK) {
+                (void)printf("%cWILL_SACK", sep);
+                topt &= ~TF_WILL_SACK;
+                sep = ',';
+            }
+#        endif /* defined(TF_WILL_SACK) */
+
+            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 (ps && !Ffield)
+        putchar(')');
+    if (nl)
+        putchar('\n');
+}
+#else  /* !defined(USE_LIB_PRINT_TCPTPI) */
+char ptti_d1[] = "d";
+char *ptti_d2 = ptti_d1;
+#endif /* defined(USE_LIB_PRINT_TCPTPI) */
diff --git a/src/store.c b/src/store.c
new file mode 100644
index 0000000..8e7dfd2
--- /dev/null
+++ b/src/store.c
@@ -0,0 +1,176 @@
+/*
+ * store.c - common 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.
+ */
+
+#include "common.h"
+
+/*
+ * Global storage definitions
+ */
+
+int CkPasswd = 0; /* time to check /etc/passwd for change */
+
+#if defined(HAS_STD_CLONE)
+struct clone *Clone = (struct clone *)NULL;
+/* clone device list */
+#endif /* defined(HAS_STD_CLONE) */
+
+int CmdColW;       /* COMMAND column width */
+
+#if defined(HASSELINUX)
+int CntxColW;       /* security context column width */
+int CntxStatus = 0; /* security context status: 0 == disabled,
+                     * 1 == enabled */
+#endif              /* defined(HASSELINUX) */
+
+int DChelp = 0; /* -D? status */
+
+int DevColW; /* DEVICE column width */
+
+/*
+ * Externals for a stkdir(), dumbed-down for older AIX compilers.
+ */
+
+int ErrStat = 0;  /* path stat() error count */
+uid_t Euid;       /* effective UID of this lsof process */
+int FcColW;       /* FCT column width */
+int Fcntx = 0;    /* -Z option status */
+int FdColW;       /* FD column width */
+int Ffilesys = 0; /* -f option status:
+                   *    0 = paths may be file systems
+                   *    1 = paths are just files
+                   *    2 = paths must be file systems */
+
+#if defined(HASNCACHE)
+int NcacheReload = 1; /* 1 == call ncache_load() */
+#endif                /* defined(HASNCACHE) */
+
+int Ffield = 0;  /* -f and -F status */
+int FgColW;      /* FILE-FLAG column width */
+int Fhelp = 0;   /* -h option status */
+int Fhost = 1;   /* -H option status */
+int Fnlink = 0;  /* -L option status */
+int Fport = 1;   /* -P option status */
+
+#if !defined(HASNORPC_H)
+#    if defined(HASPMAPENABLED)
+int FportMap = 1; /* +|-M option status */
+#    else         /* !defined(HASPMAPENABLED) */
+int FportMap = 0; /* +|-M option status */
+#    endif        /* defined(HASPMAPENABLED) */
+#endif            /* !defined(HASNORPC_H) */
+
+int Fpgid = 0;              /* -g option status */
+int Fppid = 0;              /* -R option status */
+int Fhuman = 0;             /* -H option status */
+int FsColW;                 /* FSTR-ADDR column width */
+int Fsv = FSV_DEFAULT;      /* file struct value selections */
+int NiColW;                 /* NODE-ID column width */
+char *NiTtl = NITTL;        /* NODE-ID column title */
+int FsearchErr = 1;         /* -Q option status */
+int Ftcptpi = TCPTPI_STATE; /* -T option status */
+int Fterse = 0;             /* -t option status */
+int Futol = 1;              /* -l option status */
+int Fverbose = 0;           /* -V option status */
+
+int Fxover = 0; /* -x option value */
+int Fzone = 0;  /* -z option status */
+
+struct fieldsel FieldSel[] = {
+    {LSOF_FID_ACCESS, 0, LSOF_FNM_ACCESS, NULL, 0},              /*  0 */
+    {LSOF_FID_CMD, 0, LSOF_FNM_CMD, NULL, 0},                    /*  1 */
+    {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_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 */
+    {LSOF_FID_NLINK, 0, LSOF_FNM_NLINK, &Fnlink, 1},             /*  9 */
+    {LSOF_FID_TID, 0, LSOF_FNM_TID, NULL, 0},                    /* 11 */
+    {LSOF_FID_LOCK, 0, LSOF_FNM_LOCK, NULL, 0},                  /* 11 */
+    {LSOF_FID_LOGIN, 0, LSOF_FNM_LOGIN, NULL, 0},                /* 12 */
+    {LSOF_FID_MARK, 1, LSOF_FNM_MARK, NULL, 0},                  /* 13 */
+    {LSOF_FID_TCMD, 0, LSOF_FNM_TCMD, NULL, 0},                  /* 14 */
+    {LSOF_FID_NAME, 0, LSOF_FNM_NAME, NULL, 0},                  /* 15 */
+    {LSOF_FID_NI, 0, LSOF_FNM_NI, &Fsv, FSV_NI},                 /* 16 */
+    {LSOF_FID_OFFSET, 0, LSOF_FNM_OFFSET, NULL, 0},              /* 17 */
+    {LSOF_FID_PID, 1, LSOF_FNM_PID, NULL, 0},                    /* 18 */
+    {LSOF_FID_PGID, 0, LSOF_FNM_PGID, &Fpgid, 1},                /* 19 */
+    {LSOF_FID_PROTO, 0, LSOF_FNM_PROTO, NULL, 0},                /* 20 */
+    {LSOF_FID_RDEV, 0, LSOF_FNM_RDEV, NULL, 0},                  /* 21 */
+    {LSOF_FID_PPID, 0, LSOF_FNM_PPID, &Fppid, 1},                /* 22 */
+    {LSOF_FID_SIZE, 0, LSOF_FNM_SIZE, NULL, 0},                  /* 23 */
+    {LSOF_FID_STREAM, 0, LSOF_FNM_STREAM, NULL, 0},              /* 24 */
+    {LSOF_FID_TYPE, 0, LSOF_FNM_TYPE, NULL, 0},                  /* 25 */
+    {LSOF_FID_TCPTPI, 0, LSOF_FNM_TCPTPI, &Ftcptpi, TCPTPI_ALL}, /* 26 */
+    {LSOF_FID_UID, 0, LSOF_FNM_UID, NULL, 0},                    /* 27 */
+    {LSOF_FID_ZONE, 0, LSOF_FNM_ZONE, &Fzone, 1},                /* 28 */
+    {LSOF_FID_CNTX, 0, LSOF_FNM_CNTX, &Fcntx, 1},                /* 29 */
+    {LSOF_FID_TERM, 0, LSOF_FNM_TERM, NULL, 0},                  /* 30 */
+    {' ', 0, NULL, NULL, 0}};
+
+int Hdr = 0; /* header print status */
+char *InodeFmt_d = (char *)NULL;
+/* INODETYPE decimal printf specification */
+char *InodeFmt_x = (char *)NULL;
+/* INODETYPE hexadecimal printf specification */
+int LastPid = -1; /* last PID listed (for eliminating duplicates
+                   * in terse output) */
+
+int NlColW;                /* NLINK column width */
+int NmColW;                /* NAME column width */
+int NodeColW;              /* NODE column width */
+int OffDecDig = OFFDECDIG; /* offset decimal form (0t...) digit limit */
+int OffColW;               /* OFFSET column width */
+int PgidColW;              /* PGID column width */
+int PidColW;               /* PID column width */
+int PpidColW;              /* PPID column width */
+
+int PrPass = 0;                   /* print pass: 0 = compute column widths
+                                   *	       1 = print */
+int RptMaxCount = 0;              /* count of repeasts: 0 = no limit
+                                   * -- set by -r */
+int SzColW;                       /* SIZE column width */
+int SzOffColW;                    /* SIZE/OFF column width */
+char *SzOffFmt_0t = (char *)NULL; /* SZOFFTYPE 0t%u printf specification */
+char *SzOffFmt_d = (char *)NULL;  /* SZOFFTYPE %d printf specification */
+char *SzOffFmt_dv = (char *)NULL; /* SZOFFTYPE %*d printf specification */
+char *SzOffFmt_x = (char *)NULL;  /* SZOFFTYPE %#x printf specification */
+int TaskCmdColW = 0;              /* task command column width */
+int TaskCmdLim = TASKCMDL;        /* TASKCMD column width limit (same as
+                                   * CmdLim) */
+int TaskPrtCmd = 0;               /* task print task command flag */
+int TaskPrtTid = 0;               /* task print TID flag */
+char Terminator = '\n';           /* output field terminator */
+int TaskTidColW = 0;              /* task TID column width */
+int TypeColW;                     /* TYPE column width */
+int UserColW;                     /* USER column width */
+
+int ZoneColW; /* ZONE column width */
diff --git a/src/usage.c b/src/usage.c
new file mode 100644
index 0000000..546b3ae
--- /dev/null
+++ b/src/usage.c
@@ -0,0 +1,997 @@
+/*
+ * usage.c - usage functions for lsof
+ */
+
+/*
+ * 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.
+ */
+
+static char copyright[] =
+    "Copyright 1998 Purdue Research Foundation. All rights reserved.";
+
+#include "common.h"
+#include "cli.h"
+#include "version.h"
+
+/*
+ * Local function prototypes
+ */
+
+static char *isnullstr(char *s);
+static int print_in_col(int col, char *cp);
+static void report_HASDCACHE(struct lsof_context *ctx, int type, char *ttl,
+                             char *det);
+static void report_HASKERNIDCK(char *pfx, char *verb);
+static void report_SECURITY(char *pfx, char *punct);
+static void report_WARNDEVACCESS(char *pfx, char *verb, char *punct);
+
+/*
+ * isnullstr() - is it a null string?
+ */
+
+static char *isnullstr(char *s) /* string pointer */
+{
+    if (!s)
+        return ((char *)NULL);
+    while (*s) {
+        if (*s != ' ')
+            return (s);
+        s++;
+    }
+    return ((char *)NULL);
+}
+
+/*
+ * print_in_col() -- print character string in help column
+ */
+
+static int print_in_col(int col,  /* column number */
+                        char *cp) /* what to print */
+{
+    if (cp && *cp) {
+        switch (col) {
+        case 1:
+            (void)fprintf(stderr, "  %-23.23s", cp);
+            break;
+        case 2:
+            (void)fprintf(stderr, "  %-25.25s", cp);
+            break;
+        default:
+            (void)fprintf(stderr, "  %s\n", cp);
+            col = 0;
+        }
+        col++;
+    }
+    return (col);
+}
+
+/*
+ * report_HASDCACHE() -- report device cache file state
+ */
+
+static void report_HASDCACHE(struct lsof_context *ctx, /* context */
+                             int type,  /* type: 0 == read path report
+                                         *       1 == full report */
+                             char *ttl, /* title lines prefix
+                                         * (NULL if none) */
+                             char *det) /* detail lines prefix
+                                         * (NULL if none) */
+{
+
+#if defined(HASDCACHE)
+    char *cp;
+    int dx;
+
+#    if defined(WILLDROPGID)
+    int saved_Setgid = Setgid;
+
+    Setgid = 0;
+#    endif /* defined(WILLDROPGID) */
+
+    if (type) {
+
+        /*
+         * Report full device cache information.
+         */
+        (void)fprintf(stderr, "%sDevice cache file read-only paths:\n",
+                      ttl ? ttl : "");
+        if ((dx = dcpath(ctx, 1, 0)) < 0)
+            (void)fprintf(stderr, "%snone\n", det ? det : "");
+        else {
+            (void)fprintf(stderr, "%sNamed via -D: %s\n", det ? det : "",
+                          DCpath[0] ? DCpath[0] : "none");
+
+#    if defined(HASENVDC)
+            (void)fprintf(stderr, "%sNamed in environment variable %s: %s\n",
+                          det ? det : "", HASENVDC,
+                          DCpath[1] ? DCpath[1] : "none");
+#    endif /* defined(HASENVDC) */
+
+#    if defined(HASSYSDC)
+            if (DCpath[2])
+                (void)fprintf(stderr, "%sSystem-wide device cache: %s\n",
+                              det ? det : "", DCpath[2]);
+#    endif /* defined(HASSYSDC) */
+
+#    if defined(HASPERSDC)
+            (void)fprintf(stderr,
+                          "%sPersonal path format (HASPERSDC): \"%s\"\n",
+                          det ? det : "", HASPERSDC);
+#        if defined(HASPERSDCPATH)
+            (void)fprintf(stderr,
+                          "%sModified personal path environment variable: %s\n",
+                          det ? det : "", HASPERSDCPATH);
+            cp = getenv(HASPERSDCPATH);
+            (void)fprintf(stderr, "%s%s value: %s\n", det ? det : "",
+                          HASPERSDCPATH, cp ? cp : "none");
+#        endif /* defined(HASPERSDCPATH) */
+            (void)fprintf(stderr, "%sPersonal path: %s\n", det ? det : "",
+                          DCpath[3] ? DCpath[3] : "none");
+#    endif /* defined(HASPERSDC) */
+        }
+        (void)fprintf(stderr, "%sDevice cache file write paths:\n",
+                      ttl ? ttl : "");
+        if ((dx = dcpath(ctx, 2, 0)) < 0)
+            (void)fprintf(stderr, "%snone\n", det ? det : "");
+        else {
+            (void)fprintf(stderr, "%sNamed via -D: %s\n", det ? det : "",
+                          DCstate == 2 ? "none"
+                          : DCpath[0]  ? DCpath[0]
+                                       : "none");
+
+#    if defined(HASENVDC)
+            (void)fprintf(stderr, "%sNamed in environment variable %s: %s\n",
+                          det ? det : "", HASENVDC,
+                          DCpath[1] ? DCpath[1] : "none");
+#    endif /* defined(HASENVDC) */
+
+#    if defined(HASPERSDC)
+            (void)fprintf(stderr,
+                          "%sPersonal path format (HASPERSDC): \"%s\"\n",
+                          det ? det : "", HASPERSDC);
+#        if defined(HASPERSDCPATH)
+            (void)fprintf(stderr,
+                          "%sModified personal path environment variable: %s\n",
+                          det ? det : "", HASPERSDCPATH);
+            cp = getenv(HASPERSDCPATH);
+            (void)fprintf(stderr, "%s%s value: %s\n", det ? det : "",
+                          HASPERSDCPATH, cp ? cp : "none");
+#        endif /* defined(HASPERSDCPATH) */
+            (void)fprintf(stderr, "%sPersonal path: %s\n", det ? det : "",
+                          DCpath[3] ? DCpath[3] : "none");
+#    endif /* defined(HASPERSDC) */
+        }
+    } else {
+
+        /*
+         * Report device cache read file path.
+         */
+
+#    if defined(HASENVDC) || defined(HASPERSDC) || defined(HASSYSDC)
+        cp = NULL;
+#        if defined(HASENVDC)
+        if ((dx = dcpath(ctx, 1, 0)) >= 0)
+            cp = DCpath[1];
+#        endif /* defined(HASENVDC) */
+#        if defined(HASSYSDC)
+        if (!cp)
+            cp = HASSYSDC;
+#        endif /* defined(HASSYSDC) */
+#        if defined(HASPERSDC)
+        if (!cp && dx != -1 && (dx = dcpath(ctx, 1, 0)) >= 0)
+            cp = DCpath[3];
+#        endif /* defined(HASPERSDC) */
+        if (cp)
+            (void)fprintf(stderr,
+                          "%s%s is the default device cache file read path.\n",
+                          ttl ? ttl : "", cp);
+#    endif /* defined(HASENVDC) || defined(HASPERSDC) || defined(HASSYSDC) */
+    }
+
+#    if defined(WILLDROPGID)
+    Setgid = saved_Setgid;
+#    endif /* defined(WILLDROPGID) */
+
+#endif /* defined(HASDCACHE) */
+}
+
+/*
+ * report_HASKERNIDCK() -- report HASKERNIDCK state
+ */
+
+static void report_HASKERNIDCK(pfx, verb) char *pfx; /* prefix (NULL if none) */
+char *verb;                                          /* verb (NULL if none) */
+{
+    (void)fprintf(stderr, "%sernel ID check %s%s%s.\n", pfx ? pfx : "",
+                  verb ? verb : "", verb ? " " : "",
+
+#if defined(HASKERNIDCK)
+                  "enabled"
+#else  /* !defined(HASKERNIDCK) */
+                  "disabled"
+#endif /* defined(HASKERNIDCK) */
+
+    );
+}
+
+/*
+ * report_SECURITY() -- report *SECURITY states
+ */
+
+static void report_SECURITY(pfx, punct) char *pfx; /* prefix (NULL if none) */
+char *punct;                                       /* short foem punctuation
+                                                    * (NULL if none) */
+{
+    fprintf(stderr, "%s%s can list all files%s", pfx ? pfx : "",
+
+#if defined(HASSECURITY)
+            "Only root",
+#    if defined(HASNOSOCKSECURITY)
+            ", but anyone can list socket files.\n"
+#    else  /* !defined(HASNOSOCKSECURITY) */
+            punct ? punct : ""
+#    endif /* defined(HASNOSOCKSECURITY) */
+#else      /* !defined(HASSECURITY) */
+            "Anyone", punct ? punct : ""
+#endif     /* defined(HASSECURITY) */
+
+    );
+}
+
+/*
+ * report_WARNDEVACCESS() -- report WEARNDEVACCESS state
+ */
+
+static void report_WARNDEVACCESS(pfx, verb,
+                                 punct) char *pfx; /* prefix (NULL if none) */
+char *verb;                                        /* verb (NULL if none) */
+char *punct;                                       /* punctuation */
+{
+    (void)fprintf(stderr, "%s/dev warnings %s%s%s%s", pfx ? pfx : "",
+                  verb ? verb : "", verb ? " " : "",
+
+#if defined(WARNDEVACCESS)
+                  "enabled",
+#else  /* !defined(WARNDEVACCESS) */
+                  "disabled",
+#endif /* defined(WARNDEVACCESS) */
+
+                  punct);
+}
+
+/*
+ * usage() - display usage and exit
+ */
+
+void usage(struct lsof_context *ctx, /* context */
+           int err,     /* it is called as part of error handlng? */
+           int fh,      /* ``-F ?'' status */
+           int version) /* ``-v'' status */
+{
+    char buf[MAXPATHLEN + 1], *cp, *cp1, *cp2;
+    int col, i;
+
+    if (Fhelp || err) {
+        (void)fprintf(stderr, "%s %s\n latest revision: %s\n", Pn, LSOF_VERSION,
+                      LSOF_REPO_URL);
+        (void)fprintf(stderr, " latest FAQ: %s\n", LSOF_FAQ_URL);
+        (void)fprintf(stderr, " latest (non-formatted) man page: %s\n",
+                      LSOF_MAN_URL);
+        (void)fprintf(stderr, " usage: [-?ab%shH%slnNoOP%s%stUvV%s]",
+
+#if defined(HASNCACHE)
+                      "C",
+#else  /* !defined(HASNCACHE) */
+                      "",
+#endif /* defined(HASNCACHE) */
+
+#if defined(HASTASKS)
+                      "K",
+#else  /* !defined(HASTASKS) */
+                      "",
+#endif /* defined(HASTASKS) */
+
+#if defined(HASPPID)
+                      "R",
+#else  /* !defined(HASPPID) */
+                      "",
+#endif /* defined(HASPPID) */
+
+#if defined(HASTCPUDPSTATE)
+                      "",
+#else  /* !defined(HASTCPUDPSTATE) */
+                      "s",
+#endif /* defined(HASTCPUDPSTATE) */
+
+#if defined(HASXOPT)
+#    if defined(HASXOPT_ROOT)
+                      (Myuid == 0) ? "X" : ""
+#    else  /* !defined(HASXOPT_ROOT) */
+                      "X"
+#    endif /* defined(HASXOPT_ROOT) */
+#else      /* !defined(HASXOPT) */
+                      ""
+#endif     /* defined(HASXOPT) */
+
+        );
+
+#if defined(HAS_AFS) && defined(HASAOPT)
+        (void)fprintf(stderr, " [-A A]");
+#endif /* defined(HAS_AFS) && defined(HASAOPT) */
+
+        (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,
+                      " %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)
+                      "[",
+
+#    if defined(HASNOFSCOUNT)
+                      "",
+#    else  /* !defined(HASNOFSCOUNT) */
+                      "c",
+#    endif /* defined(HASNOFSCOUNT) */
+
+#    if defined(HASNOFSADDR)
+                      "",
+#    else  /* !defined(HASNOFSADDR) */
+                      "f",
+#    endif /* defined(HASNOFSADDR) */
+
+#    if defined(HASNOFSFLAGS)
+                      "",
+#    else  /* !defined(HASNOFSFLAGS) */
+                      "gG",
+#    endif /* defined(HASNOFSFLAGS) */
+
+#    if defined(HASNOFSNADDR)
+                      "",
+#    else  /* !defined(HASNOFSNADDR) */
+                      "n",
+#    endif /* defined(HASNOFSNADDR) */
+
+                      "]"
+#else  /* !defined(HASFSTRUCT) */
+                      "", "", "", "", "", ""
+#endif /* defined(HASFSTRUCT) */
+
+        );
+
+#if defined(HASKOPT)
+        (void)fprintf(stderr, " [-k k]");
+#endif /* defined(HASKOPT) */
+
+        (void)fprintf(stderr, " [+|-L [l]]");
+
+#if defined(HASMOPT) || defined(HASMNTSUP)
+        (void)fprintf(stderr,
+#    if defined(HASMOPT)
+#        if defined(HASMNTSUP)
+                      " [+|-m [m]]"
+#        else  /* !defined(HASMNTSUP) */
+                      " [-m m]"
+#        endif /* defined(HASMNTSUP) */
+#    else      /* !defined(HASMOPT) */
+                      " [+m [m]]"
+#    endif     /* defined(HASMOPT) */
+        );
+#endif /* defined(HASMOPT) || defined(HASMNTSUP) */
+
+#if !defined(HASNORPC_H)
+        (void)fprintf(stderr, " [+|-M]");
+#endif /* !defined(HASNORPC_H) */
+
+        (void)fprintf(stderr,
+                      " [-o [o]] [-p s]\n [+|-r [t]]%s [-S [t]] [-T [t]]",
+
+#if defined(HASTCPUDPSTATE)
+                      " [-s [p:s]]"
+#else  /* !defined(HASTCPUDPSTATE) */
+                      ""
+#endif /* defined(HASTCPUDPSTATE) */
+
+        );
+        (void)fprintf(stderr, " [-u s] [+|-w] [-x [fl]]");
+
+#if defined(HASZONES)
+        (void)fprintf(stderr, " [-z [z]]");
+#else /* !defined(HASZONES) */
+#    if defined(HASSELINUX)
+        if (CntxStatus)
+            (void)fprintf(stderr, " [-Z [Z]]");
+#    endif /* defined(HASSELINUX) */
+#endif     /* defined(HASZONES) */
+
+        (void)fprintf(stderr, " [--] [names]\n");
+    }
+    if (err && !Fhelp) {
+        (void)fprintf(stderr,
+                      "Use the ``-h'' option to get more help information.\n");
+        if (!fh)
+            Exit(ctx, err ? LSOF_EXIT_ERROR : LSOF_EXIT_SUCCESS);
+    }
+    if (Fhelp) {
+        (void)fprintf(
+            stderr, "Defaults in parentheses; comma-separated set (s) items;");
+        (void)fprintf(stderr, " dash-separated ranges.\n");
+        col = print_in_col(1, "-?|-h list help");
+        col = print_in_col(col, "-a AND selections (OR)");
+        col = print_in_col(col, "-b avoid kernel blocks");
+        col = print_in_col(col, "-c c  cmd c ^c /c/[bix]");
+        (void)snpf(buf, sizeof(buf), "+c w  COMMAND width (%d)", CMDL);
+        col = print_in_col(col, buf);
+
+#if defined(HASNCACHE)
+        col = print_in_col(col, "-C no kernel name cache");
+#endif /* defined(HASNCACHE) */
+
+        col = print_in_col(col, "+d s  dir s files");
+        col = print_in_col(col, "-d s  select by FD set");
+        col = print_in_col(col, "+D D  dir D tree *SLOW?*");
+
+#if defined(HASDCACHE)
+        if (Setuidroot)
+            cp = "?|i|r";
+
+#    if !defined(WILLDROPGID)
+        else if (Myuid)
+            cp = "?|i|r<path>";
+#    endif /* !defined(WILLDROPGID) */
+
+        else
+            cp = "?|i|b|r|u[path]";
+        (void)snpf(buf, sizeof(buf), "-D D  %s", cp);
+#else  /* !defined(HASDCACHE) */
+        buf[0] = '\0';
+#endif /* defined(HASDCACHE) */
+
+        col = print_in_col(col, buf);
+
+#if defined(HASEOPT)
+        col = print_in_col(col, "+|-e s  exempt s *RISKY*");
+#endif /* defined(HASEOPT) */
+
+        (void)snpf(buf, sizeof(buf), "-i select IPv%s files",
+
+#if defined(HASIPv6)
+                   "[46]"
+#else  /* !defined(HASIPv6) */
+                   "4"
+#endif /* defined(HASIPv6) */
+
+        );
+        col = print_in_col(col, buf);
+
+#if defined(HASTASKS)
+        /* DEBUG	    col = print_in_col(col, "-K list tasKs (threads)");
+         */
+        col = print_in_col(col, "-K [i] list|(i)gn tasKs");
+#endif /* defined(HASTASKS) */
+
+        col = print_in_col(col, "-l list UID numbers");
+        col = print_in_col(col, "-n no host names");
+        col = print_in_col(col, "-N select NFS files");
+        col = print_in_col(col, "-o list file offset");
+        col = print_in_col(col, "-O no overhead *RISKY*");
+        col = print_in_col(col, "-P no port names");
+        col = print_in_col(col, "-Q allow failed search");
+
+#if defined(HASPPID)
+        col = print_in_col(col, "-R list paRent PID");
+#endif /* defined(HASPPID) */
+
+        col = print_in_col(col, "-s list file size");
+        col = print_in_col(col, "-t terse listing");
+        col = print_in_col(col, "-T disable TCP/TPI info");
+        col = print_in_col(col, "-U select Unix socket");
+        col = print_in_col(col, "-v list version info");
+        col = print_in_col(col, "-V verbose search");
+        (void)snpf(buf, sizeof(buf), "+|-w  Warnings (%s)",
+
+#if defined(WARNINGSTATE)
+                   "-"
+#else  /* !defined(WARNINGSTATE) */
+                   "+"
+#endif /* defined(WARNINGSTATE) */
+        );
+
+        col = print_in_col(col, buf);
+
+#if defined(HASXOPT)
+#    if defined(HASXOPT_ROOT)
+        if (Myuid == 0)
+            (void)snpf(buf, sizeof(buf), "-X %s", HASXOPT);
+        else
+            buf[0] = '\0';
+#    else  /* !defined(HASXOPT_ROOT) */
+        (void)snpf(buf, sizeof(buf), "-X %s", HASXOPT);
+#    endif /* defined(HASXOPT_ROOT) */
+#else      /* !defined(HASXOPT) */
+        buf[0] = '\0';
+#endif     /* defined(HASXOPT) */
+
+        col = print_in_col(col, buf);
+
+#if defined(HASZONES)
+        col = print_in_col(col, "-z z  zone [z]");
+#endif /* defined(HASZONES) */
+
+#if defined(HASSELINUX)
+        col = print_in_col(col, "-Z Z  context [Z]");
+#endif /* defined(HASSELINUX) */
+
+        col = print_in_col(col, "-H human readable size");
+
+        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");
+
+#if defined(HASFSTRUCT)
+        (void)fprintf(stderr, "  +|-f[%s%s%s%s]%s%s%s%s %s%s%s%s%s%s%s\n",
+
+#    if defined(HASNOFSCOUNT)
+                      "",
+#    else  /* !defined(HASNOFSCOUNT) */
+                      "c",
+#    endif /* defined(HASNOFSCOUNT) */
+
+#    if defined(HASNOFSADDR)
+                      "",
+#    else  /* !defined(HASNOFSADDR) */
+                      "f",
+#    endif /* defined(HASNOFSADDR) */
+
+#    if defined(HASNOFSFLAGS)
+                      "",
+#    else  /* !defined(HASNOFSFLAGS) */
+                      "gG",
+#    endif /* defined(HASNOFSFLAGS) */
+
+#    if defined(HASNOFSNADDR)
+                      "",
+#    else  /* !defined(HASNOFSNADDR) */
+                      "n",
+#    endif /* defined(HASNOFSNADDR) */
+
+#    if defined(HASNOFSCOUNT)
+                      "",
+#    else  /* !defined(HASNOFSCOUNT) */
+                      " Ct",
+#    endif /* defined(HASNOFSCOUNT) */
+
+#    if defined(HASNOFSADDR)
+                      "",
+#    else  /* !defined(HASNOFSADDR) */
+                      " Fstr",
+#    endif /* defined(HASNOFSADDR) */
+
+#    if defined(HASNOFSFLAGS)
+                      "",
+#    else  /* !defined(HASNOFSFLAGS) */
+                      " flaGs",
+#    endif /* defined(HASNOFSFLAGS) */
+
+#    if defined(HASNOFSNADDR)
+                      "",
+#    else  /* !defined(HASNOFSNADDR) */
+                      " Node",
+#    endif /* defined(HASNOFSNADDR) */
+
+                      Fsv ? "(" : "", (Fsv & FSV_CT) ? "C" : "",
+                      (Fsv & FSV_FA) ? "F" : "",
+                      ((Fsv & FSV_FG) && FsvFlagX) ? "g" : "",
+                      ((Fsv & FSV_FG) && !FsvFlagX) ? "G" : "",
+                      (Fsv & FSV_NI) ? "N" : "", Fsv ? ")" : "");
+#else  /* !defined(HASFSTRUCT) */
+        putc('\n', stderr);
+#endif /* defined(HASFSTRUCT) */
+
+        (void)fprintf(stderr, "  %-36.36s",
+                      "-F [f] select fields; -F? for help");
+
+#if defined(HASKOPT)
+        (void)fprintf(stderr, "  -k k   kernel symbols (%s)\n",
+                      Nmlst ? Nmlst
+#    if defined(N_UNIX)
+                            : N_UNIX
+#    else  /* !defined(N_UNIX) */
+                      : (Nmlst = get_nlist_path(ctx, 1)) ? Nmlst
+                                                         : "none found"
+#    endif /* defined(N_UNIX) */
+
+        );
+#else  /* !defined(HASKOPT) */
+        putc('\n', stderr);
+#endif /* defined(HASKOPT) */
+
+        (void)fprintf(stderr,
+                      "  +|-L [l] list (+) suppress (-) link counts < l (0 "
+                      "= all; default = 0)\n");
+
+#if defined(HASMOPT) || defined(HASMNTSUP)
+#    if defined(HASMOPT)
+        (void)snpf(buf, sizeof(buf), "-m m   kernel memory (%s)", KMEM);
+#    else  /* !defined(HASMOPT) */
+        buf[0] = '\0';
+#    endif /* defined(HASMOPT) */
+
+        (void)fprintf(stderr, "  %-36.36s", buf);
+
+#    if defined(HASMNTSUP)
+        (void)fprintf(stderr, "  +m [m] use|create mount supplement\n");
+#    else  /* !defined(HASMNTSUP) */
+        (void)fprintf(stderr, "\n");
+#    endif /* defined(HASMNTSUP) */
+#endif     /* defined(HASMOPT) || defined(HASMNTSUP) */
+
+#if !defined(HASNORPC_H)
+        (void)snpf(buf, sizeof(buf), "+|-M   portMap registration (%s)",
+
+#    if defined(HASPMAPENABLED)
+                   "+"
+#    else  /* !defined(HASPMAPENABLED) */
+                   "-"
+#    endif /* defined(HASPMAPENABLED) */
+
+        );
+#else  /* defined(HASNORPC_H) */
+        buf[0] = '\0';
+#endif /* !defined(HASNORPC_H) */
+
+        (void)fprintf(stderr, "  %-36.36s", buf);
+        (void)snpf(buf, sizeof(buf), "-o o   o 0t offset digits (%d)",
+                   OFFDECDIG);
+        (void)fprintf(stderr, "  %s\n", buf);
+        (void)fprintf(stderr, "  %-36.36s", "-p s   exclude(^)|select PIDs");
+        (void)fprintf(stderr, "  -S [t] t second stat timeout (%d)\n", TMLIMIT);
+        (void)snpf(buf, sizeof(buf), "-T %s%ss%s TCP/TPI %s%sSt%s (s) info",
+
+#if defined(HASSOOPT) || defined(HASSOSTATE) || defined(HASTCPOPT)
+                   "f",
+#else  /* !defined(HASSOOPT) && !defined(HASSOSTATE) && !defined(HASTCPOPT)*/
+                   "",
+#endif /* defined(HASSOOPT) || defined(HASSOSTATE) || defined(HASTCPOPT)*/
+
+#if defined(HASTCPTPIQ)
+                   "q",
+#else  /* !defined(HASTCPTPIQ) */
+                   " ",
+#endif /* defined(HASTCPTPIQ) */
+
+#if defined(HASTCPTPIW)
+                   "w",
+#else  /* !defined(HASTCPTPIW) */
+                   "",
+#endif /* defined(HASTCPTPIW) */
+
+#if defined(HASSOOPT) || defined(HASSOSTATE) || defined(HASTCPOPT)
+                   "Fl,",
+#else  /* !defined(HASSOOPT) && !defined(HASSOSTATE) && !defined(HASTCPOPT)*/
+                   "",
+#endif /* defined(HASSOOPT) || defined(HASSOSTATE) || defined(HASTCPOPT)*/
+
+#if defined(HASTCPTPIQ)
+                   "Q,",
+#else  /* !defined(HASTCPTPIQ) */
+                   "",
+#endif /* defined(HASTCPTPIQ) */
+
+#if defined(HASTCPTPIW)
+                   ",Win"
+#else  /* !defined(HASTCPTPIW) */
+                   ""
+#endif /* defined(HASTCPTPIW) */
+
+        );
+        (void)fprintf(stderr, "  %s\n", buf);
+
+#if defined(HAS_AFS) && defined(HASAOPT)
+        (void)fprintf(stderr, "  -A A   AFS name list file (%s)\n",
+                      AFSAPATHDEF);
+#endif /* defined(HAS_AFS) && defined(HASAOPT) */
+
+        (void)fprintf(
+            stderr, "  -g [s] exclude(^)|select and print process group IDs\n");
+        (void)fprintf(stderr, "  -i i   select by IPv%s address:",
+
+#if defined(HASIPv6)
+                      "[46]"
+#else  /* !defined(HASIPv6) */
+                      "4"
+#endif /* defined(HASIPv6) */
+
+        );
+        (void)fprintf(stderr, " [%s][proto][@host|addr][:svc_list|port_list]\n",
+
+#if defined(HASIPv6)
+                      "46"
+#else  /* !defined(HASIPv6) */
+                      "4"
+#endif /* defined(HASIPv6) */
+
+        );
+
+        (void)fprintf(stderr, "  +|-r [%s] repeat every t seconds (%d); %s",
+
+#if defined(HAS_STRFTIME)
+                      "t[m<fmt>]",
+#else  /* !defined(has_STRFTIME) */
+                      "t",
+#endif /* defined(HAS_STRFTIME) */
+
+                      RPTTM, " + until no files, - forever.\n");
+
+#if defined(HAS_STRFTIME)
+        (void)fprintf(
+            stderr,
+            "       An optional suffix to t is m<fmt>; m must separate %s",
+            "t from <fmt> and\n");
+        (void)fprintf(stderr, "      <fmt> is an strftime(3) format %s",
+                      "for the marker line.\n");
+#endif /* defined(HAS_STRFTIME) */
+
+#if defined(HASTCPUDPSTATE)
+        (void)fprintf(
+            stderr,
+            "  -s p:s  exclude(^)|select protocol (p = TCP|UDP) states");
+        (void)fprintf(stderr, " by name(s).\n");
+#endif /* defined(HASTCPUDPSTATE) */
+
+        (void)fprintf(stderr, "  -u s   exclude(^)|select login|UID set s\n");
+        (void)fprintf(
+            stderr,
+            "  -x [fl] cross over +d|+D File systems or symbolic Links\n");
+        (void)fprintf(
+            stderr,
+            "  names  select named files or files on named file systems\n");
+        (void)report_SECURITY(NULL, "; ");
+        (void)report_WARNDEVACCESS(NULL, NULL, ";");
+        (void)report_HASKERNIDCK(" k", NULL);
+        (void)report_HASDCACHE(ctx, 0, NULL, NULL);
+
+#if defined(DIALECT_WARNING)
+        (void)fprintf(stderr, "WARNING: %s\n", DIALECT_WARNING);
+#endif /* defined(DIALECT_WARNING) */
+    }
+    if (fh) {
+        (void)fprintf(stderr, "%s:\tID    field description\n", Pn);
+        for (i = 0; FieldSel[i].nm; i++) {
+
+#if !defined(HASPPID)
+            if (FieldSel[i].id == LSOF_FID_PPID)
+                continue;
+#endif /* !defined(HASPPID) */
+
+#if !defined(HASFSTRUCT)
+            if (FieldSel[i].id == LSOF_FID_FA ||
+                FieldSel[i].id == LSOF_FID_CT ||
+                FieldSel[i].id == LSOF_FID_FG || FieldSel[i].id == LSOF_FID_NI)
+                continue;
+#else /* defined(HASFSTRUCT) */
+#    if defined(HASNOFSADDR)
+            if (FieldSel[i].id == LSOF_FID_FA)
+                continue;
+#    endif /* defined(HASNOFSADDR) */
+
+#    if defined(HASNOFSCOUNT)
+            if (FieldSel[i].id == LSOF_FID_CT)
+                continue;
+#    endif /* !defined(HASNOFSCOUNT) */
+
+#    if defined(HASNOFSFLAGS)
+            if (FieldSel[i].id == LSOF_FID_FG)
+                continue;
+#    endif /* defined(HASNOFSFLAGS) */
+
+#    if defined(HASNOFSNADDR)
+            if (FieldSel[i].id == LSOF_FID_NI)
+                continue;
+#    endif /* defined(HASNOFSNADDR) */
+#endif     /* !defined(HASFSTRUCT) */
+
+#if !defined(HASZONES)
+            if (FieldSel[i].id == LSOF_FID_ZONE)
+                continue;
+#endif /* !defined(HASZONES) */
+
+#if defined(HASSELINUX)
+            if ((FieldSel[i].id == LSOF_FID_CNTX) && !CntxStatus)
+                continue;
+#else  /* !defined(HASSELINUX) */
+            if (FieldSel[i].id == LSOF_FID_CNTX)
+                continue;
+#endif /* !defined(HASSELINUX) */
+
+            (void)fprintf(stderr, "\t %c    %s\n", FieldSel[i].id,
+                          FieldSel[i].nm);
+        }
+    }
+
+#if defined(HASDCACHE)
+    if (DChelp)
+        report_HASDCACHE(ctx, 1, NULL, "    ");
+#endif /* defined(HASDCACHE) */
+
+    if (version) {
+
+        /*
+         * Display version information in response to ``-v''.
+         */
+        (void)fprintf(stderr, "%s version information:\n", Pn);
+        (void)fprintf(stderr, "    revision: %s\n", LSOF_VERSION);
+        (void)fprintf(stderr, "    copyright notice: %s\n", copyright);
+        (void)fprintf(stderr, "    latest revision: %s\n", LSOF_REPO_URL);
+        (void)fprintf(stderr, "    latest FAQ: %s\n", LSOF_FAQ_URL);
+        (void)fprintf(stderr, "    latest (non-formatted) man page: %s\n",
+                      LSOF_MAN_URL);
+
+#if defined(LSOF_CINFO)
+        if ((cp = isnullstr(LSOF_CINFO)))
+            (void)fprintf(stderr, "    configuration info: %s\n", cp);
+#endif /* defined(LSOF_CINFO) */
+
+        cp = isnullstr(LSOF_HOST);
+        if (!(cp1 = isnullstr(LSOF_LOGNAME)))
+            cp1 = isnullstr(LSOF_USER);
+        if (cp || cp1) {
+            if (cp && cp1)
+                cp2 = "by and on";
+            else if (cp)
+                cp2 = "on";
+            else
+                cp2 = "by";
+            (void)fprintf(stderr, "    constructed %s: %s%s%s\n", cp2,
+                          cp1 ? cp1 : "", (cp && cp1) ? "@" : "", cp ? cp : "");
+        }
+
+#if defined(LSOF_BLDCMT)
+        if ((cp = isnullstr(LSOF_BLDCMT)))
+            (void)fprintf(stderr, "    builder's comment: %s\n", cp);
+#endif /* defined(LSOF_BLDCMT) */
+
+        if ((cp = isnullstr(LSOF_CC)))
+            (void)fprintf(stderr, "    compiler: %s\n", cp);
+        if ((cp = isnullstr(LSOF_CCV)))
+            (void)fprintf(stderr, "    compiler version: %s\n", cp);
+        if ((cp = isnullstr(LSOF_CCFLAGS)))
+            (void)fprintf(stderr, "    compiler flags: %s\n", cp);
+        if ((cp = isnullstr(LSOF_LDFLAGS)))
+            (void)fprintf(stderr, "    loader flags: %s\n", cp);
+        if ((cp = isnullstr(LSOF_SYSINFO)))
+            (void)fprintf(stderr, "    system info: %s\n", cp);
+        // display configurations that might affect output
+        char *features[] = {
+#if defined(HASEFFNLINK)
+            "effnlink",
+#endif
+#if defined(HASFDESCFS)
+            "fdescfs",
+#endif
+#if defined(HASF_VNODE)
+            "f_vnode",
+#endif
+#if defined(HASIPv6)
+            "ipv6",
+#endif
+#if defined(HAS_KF_SOCK_SENDQ)
+            "kf_sock_sendq",
+#endif
+#if defined(HAS_KF_FILE_NLINK)
+            "kf_file_nlink",
+#endif
+#if defined(HASNULLFS)
+            "nullfs",
+#endif
+#if defined(HAS_SYS_PIPEH)
+            "pipe",
+#endif
+#if defined(HASPROCFS)
+            "procfs",
+#endif
+#if defined(HASPSEUDOFS)
+            "pseudofs",
+#endif
+#if defined(HASPTYEPT)
+            "ptyept",
+#endif
+#if defined(HASPTYFS)
+            "ptyfs",
+#endif
+#if !defined(HASNORPC_H)
+            "rpc",
+#endif
+#if defined(HASSBSTATE)
+            "sbstate",
+#endif
+#if defined(HASSELINUX)
+            "selinux",
+#endif
+#if defined(HASSOOPT)
+            "soopt",
+#endif
+#if defined(HASSOSTATE)
+            "sostate",
+#endif
+#if defined(HASTASKS)
+            "tasks",
+#endif
+#if defined(HAS_TMPFS) || defined(HASTMPFS)
+            "tmpfs",
+#endif
+#if defined(HAS_XTCPCB_TMAXSEG)
+            "xtcpcb_tmaxseg",
+#endif
+#if defined(HASUXSOCKEPT)
+            "uxsockept",
+#endif
+#if defined(HAS_V_LOCKF)
+            "v_lockf",
+#endif
+        };
+        (void)fprintf(stderr, "    features enabled:");
+        for (i = 0; i < sizeof(features) / sizeof(features[0]); i++) {
+            (void)fprintf(stderr, " %s", features[i]);
+        }
+        (void)fprintf(stderr, "\n");
+        (void)report_SECURITY("    ", ".\n");
+        (void)report_WARNDEVACCESS("    ", "are", ".\n");
+        (void)report_HASKERNIDCK("    K", "is");
+
+#if defined(DIALECT_WARNING)
+        (void)fprintf(stderr, "    WARNING: %s\n", DIALECT_WARNING);
+#endif /* defined(DIALECT_WARNING) */
+
+        (void)report_HASDCACHE(ctx, 1, "    ", "\t");
+    }
+    Exit(ctx, err ? LSOF_EXIT_ERROR : LSOF_EXIT_SUCCESS);
+}
diff --git a/util.c b/src/util.c
similarity index 71%
rename from util.c
rename to src/util.c
index e625e2b..bc6e231 100644
--- a/util.c
+++ b/src/util.c
@@ -8,7 +8,6 @@
  * Purdue University
  */
 
-
 /*
  * Copyright 2008 Purdue Research Foundation, West Lafayette, Indiana
  * 47907.  All rights reserved.
@@ -35,38 +34,30 @@
  * 4. This notice may not be removed or altered.
  */
 
+#include "common.h"
 
-#ifndef lint
-static char copyright[] =
-"@(#) Copyright 2008 Purdue Research Foundation.\nAll rights reserved.\n";
-#endif
-
-#if	defined(HAS_STRFTIME)
-#include <time.h>
-#endif	/* defined(HAS_STRFTIME) */
-
+#if defined(HAS_STRFTIME)
+#    include <time.h>
+#endif /* defined(HAS_STRFTIME) */
 
 /*
  * util_strftime() -- utility function to call strftime(3) without header
  *		      file distractions
  */
 
-int
-util_strftime(fmtr, fmtl, fmt)
-	char *fmtr;			/* format output receiver */
-	int fmtl;			/* sizeof(*fmtr) */
-	char *fmt;			/* format */
+int util_strftime(char *fmtr, /* format output receiver */
+                  int fmtl,   /* sizeof(*fmtr) */
+                  char *fmt)  /* format */
 {
 
-#if	defined(HAS_STRFTIME)
-	struct tm *lt;
-	time_t tm;
-
-	tm = time((time_t *)NULL);
-	lt = localtime(&tm);
-	return(strftime(fmtr, fmtl, fmt, lt));
-#else	/* !defined(HAS_STRFTIME) */
-	return(0);
-#endif	/* defined(HAS_STRFTIME) */
+#if defined(HAS_STRFTIME)
+    struct tm *lt;
+    time_t tm;
 
+    tm = time((time_t *)NULL);
+    lt = localtime(&tm);
+    return (strftime(fmtr, fmtl, fmt, lt));
+#else  /* !defined(HAS_STRFTIME) */
+    return (0);
+#endif /* defined(HAS_STRFTIME) */
 }
diff --git a/store.c b/store.c
deleted file mode 100644
index 2f30843..0000000
--- a/store.c
+++ /dev/null
@@ -1,401 +0,0 @@
-/*
- * store.c - common 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";
-#endif
-
-
-#include "lsof.h"
-
-
-/*
- * Global storage definitions
- */
-
-int AllProc = 1;		/* all processes are selected (default) */
-
-#if	defined(HASBLKDEV)
-struct l_dev *BDevtp = (struct l_dev *)NULL;
-				/* block device table pointer */
-int BNdev = 0;			/* number of entries in BDevtp[] */
-struct l_dev **BSdev = (struct l_dev **)NULL;
-				/* pointer to BDevtp[] pointers, sorted
-				 * by device */
-#endif	/* defined(HASBLKDEV) */
-
-int CkPasswd = 0;		/* time to check /etc/passwd for change */
-
-#if	defined(HAS_STD_CLONE)
-struct clone *Clone = (struct clone *)NULL;
-				/* clone device list */
-#endif	/* defined(HAS_STD_CLONE) */
-
-int CmdColW;			/* COMMAND column width */
-struct str_lst *Cmdl = (struct str_lst *)NULL;
-				/* command names selected with -c */
-int CmdLim = CMDL;		/* COMMAND column width limit */
-int Cmdni = 0;			/* command name inclusions selected with -c */
-int Cmdnx = 0;			/* command name exclusions selected with -c */
-lsof_rx_t *CmdRx = (lsof_rx_t *)NULL;
-				/* command regular expression table */
-
-#if	defined(HASSELINUX)
-cntxlist_t *CntxArg = (cntxlist_t *)NULL;
-				/* security context arguments supplied with
-				 * -Z */
-int CntxColW;			/* security context column width */
-int CntxStatus = 0;		/* security context status: 0 == disabled,
-				 * 1 == enabled */
-#endif	/* defined(HASSELINUX) */
-
-#if	defined(HASDCACHE)
-unsigned DCcksum;		/* device cache file checksum */
-int DCfd = -1;			/* device cache file descriptor */
-FILE *DCfs = (FILE *)NULL;	/* stream pointer for DCfd */
-char *DCpathArg = (char *)NULL;	/* device cache path from -D[b|r|u]<path> */
-char *DCpath[] = {		/* device cache paths, indexed by DCpathX
-				 *when it's >= 0 */
-	(char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL
-};
-int DCpathX = -1;		/* device cache path index:
-				 *	-1 = path not defined
-				 *	 0 = defined via -D
-				 *	 1 = defined via HASENVDC
-				 *	 2 = defined via HASSYSDC
-				 *	 3 = defined via HASPERSDC and
-				 *	     HASPERSDCPATH */
-int DCrebuilt = 0;		/* an unsafe device cache file has been
-				 * rebuilt */
-int DCstate = 3;		/* device cache state:
-				 *	0 = ignore (-Di)
-				 *	1 = build (-Db[path])
-				 *	2 = read; don't rebuild (-Dr[path])
-				 *	3 = update; read and rebuild if
-				 *	    necessary (-Du[path])
-				 */
-int DCunsafe = 0;		/* device cache file is potentially unsafe,
-				 * (The [cm]time check failed.) */
-#endif	/* defined(HASDCACHE) */
-
-int DChelp = 0;			/* -D? status */
-
-int DevColW;			/* DEVICE column width */
-dev_t DevDev;			/* device number of /dev or its equivalent */
-struct l_dev *Devtp = (struct l_dev *)NULL;
-				/* device table pointer */
-
-
-/*
- * Externals for a stkdir(), dumbed-down for older AIX compilers.
- */
-
-char **Dstk = (char **)NULL;	/* the directory stack */
-int Dstkx = 0;			/* Dstk[] index */
-int Dstkn = 0;			/* Dstk[] entries allocated */
-efsys_list_t *Efsysl = (efsys_list_t *)NULL;
-				/* file systems for which kernel blocks are
-				 * to be eliminated */
-int ErrStat = 0;		/* path stat() error count */
-uid_t Euid;			/* effective UID of this lsof process */
-int Fand = 0;			/* -a option status */
-int Fblock = 0;			/* -b option status */
-int FcColW;			/* FCT column width */
-int Fcntx = 0;			/* -Z option status */
-int FdColW;			/* FD column width */
-int FeptE = 0;			/* -E option status: 0==none, 1==info,
-				 * 2==info+files */
-int Ffilesys = 0;		/* -f option status:
-				 *    0 = paths may be file systems
-				 *    1 = paths are just files
-				 *    2 = paths must be file systems */
-
-#if	defined(HASNCACHE)
-int Fncache = 1;		/* -C option status */
-int NcacheReload = 1;		/* 1 == call ncache_load() */
-#endif	/* defined(HASNCACHE) */
-
-int Ffield = 0;			/* -f and -F status */
-int FgColW;			/* FILE-FLAG column width */
-int Fhelp = 0;			/* -h option status */
-int Fhost = 1;			/* -H option status */
-int Fnet = 0;			/* -i option status: 0==none
-				 *		     1==find all
-				 *		     2==some found*/
-int FnetTy = 0;			/* Fnet type request: 0==all
-				 *		      4==IPv4
-				 *		      6==IPv6 */
-int Fnfs = 0;			/* -N option status: 0==none, 1==find all,
-				 * 2==some found*/
-int Fnlink = 0;			/* -L option status */
-int Foffset = 0;		/* -o option status */
-int Fovhd = 0;			/* -O option status */
-int Fport = 1;			/* -P option status */
-
-#if	!defined(HASNORPC_H)
-# if	defined(HASPMAPENABLED)
-int FportMap = 1;		/* +|-M option status */
-# else	/* !defined(HASPMAPENABLED) */
-int FportMap = 0;		/* +|-M option status */
-# endif	/* defined(HASPMAPENABLED) */
-#endif	/* !defined(HASNORPC_H) */
-
-int Fpgid = 0;			/* -g option status */
-int Fppid = 0;			/* -R option status */
-int Fsize = 0;			/* -s option status */
-int FsColW;			/* FSTR-ADDR column width */
-int Fsv = FSV_DEFAULT;		/* file struct value selections */
-int FsvByf = 0;			/* Fsv was set by +f */
-int FsvFlagX = 0;		/* hex format status for FSV_FG */
-int Ftask = 0;			/* -K option value */
-int NiColW;			/* NODE-ID column width */
-char *NiTtl = NITTL;		/* NODE-ID column title */
-int FsearchErr = 1;		/* -Q option status */
-int Ftcptpi = TCPTPI_STATE;	/* -T option status */
-int Fterse = 0;			/* -t option status */
-int Funix = 0;			/* -U option status */
-int Futol = 1;			/* -l option status */
-int Fverbose = 0;		/* -V option status */
-
-#if	defined(WARNINGSTATE)
-int Fwarn = 1;			/* +|-w option status */
-#else	/* !defined(WARNINGSTATE) */
-int Fwarn = 0;			/* +|-w option status */
-#endif	/* defined(WARNINGSTATE) */
-
-#if	defined(HASXOPT_VALUE)
-int Fxopt = HASXOPT_VALUE;	/* -X option status */
-#endif	/* defined(HASXOPT_VALUE) */
-
-int Fxover = 0;			/* -x option value */
-int Fzone = 0;			/* -z option status */
-
-struct fd_lst *Fdl = (struct fd_lst *)NULL;
-				/* file descriptors selected with -d */
-int FdlTy = -1;			/* Fdl[] type: -1 == none
-				 *		0 == include
-				 *		1 == exclude */
-
-struct fieldsel FieldSel[] = {
-    { LSOF_FID_ACCESS, 0,  LSOF_FNM_ACCESS, NULL,     0		 }, /*  0 */
-    { LSOF_FID_CMD,    0,  LSOF_FNM_CMD,    NULL,     0		 }, /*  1 */
-    { 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_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 */
-    { LSOF_FID_NLINK,  0,  LSOF_FNM_NLINK,  &Fnlink,  1		 }, /*  9 */
-    { LSOF_FID_TID,    0,  LSOF_FNM_TID,    NULL,     0		 }, /* 11 */
-    { LSOF_FID_LOCK,   0,  LSOF_FNM_LOCK,   NULL,     0		 }, /* 11 */
-    { LSOF_FID_LOGIN,  0,  LSOF_FNM_LOGIN,  NULL,     0		 }, /* 12 */
-    { LSOF_FID_MARK,   1,  LSOF_FNM_MARK,   NULL,     0		 }, /* 13 */
-    { LSOF_FID_TCMD,   0,  LSOF_FNM_TCMD,   NULL,     0		 }, /* 14 */
-    { LSOF_FID_NAME,   0,  LSOF_FNM_NAME,   NULL,     0		 }, /* 15 */
-    { LSOF_FID_NI,     0,  LSOF_FNM_NI,     &Fsv,     FSV_NI	 }, /* 16 */
-    { LSOF_FID_OFFSET, 0,  LSOF_FNM_OFFSET, NULL,     0		 }, /* 17 */
-    { LSOF_FID_PID,    1,  LSOF_FNM_PID,    NULL,     0		 }, /* 18 */
-    { LSOF_FID_PGID,   0,  LSOF_FNM_PGID,   &Fpgid,   1		 }, /* 19 */
-    { LSOF_FID_PROTO,  0,  LSOF_FNM_PROTO,  NULL,     0		 }, /* 20 */
-    { LSOF_FID_RDEV,   0,  LSOF_FNM_RDEV,   NULL,     0		 }, /* 21 */
-    { LSOF_FID_PPID,   0,  LSOF_FNM_PPID,   &Fppid,   1		 }, /* 22 */
-    { LSOF_FID_SIZE,   0,  LSOF_FNM_SIZE,   NULL,     0		 }, /* 23 */
-    { LSOF_FID_STREAM, 0,  LSOF_FNM_STREAM, NULL,     0		 }, /* 24 */
-    { LSOF_FID_TYPE,   0,  LSOF_FNM_TYPE,   NULL,     0		 }, /* 25 */
-    { LSOF_FID_TCPTPI, 0,  LSOF_FNM_TCPTPI, &Ftcptpi, TCPTPI_ALL }, /* 26 */
-    { LSOF_FID_UID,    0,  LSOF_FNM_UID,    NULL,     0		 }, /* 27 */
-    { LSOF_FID_ZONE,   0,  LSOF_FNM_ZONE,   &Fzone,   1		 }, /* 28 */
-    { LSOF_FID_CNTX,   0,  LSOF_FNM_CNTX,   &Fcntx,   1		 }, /* 29 */
-    { LSOF_FID_TERM,   0,  LSOF_FNM_TERM,   NULL,     0		 }, /* 30 */
-    { ' ',	       0,  NULL,	    NULL,     0		 }
-};
-
-int Hdr = 0;			/* header print status */
-int IgnTasks = 0;		/* ignore tasks when non-zero */
-char *InodeFmt_d = (char *) NULL;
-				/* INODETYPE decimal printf specification */
-char *InodeFmt_x = (char *) NULL;
-				/* INODETYPE hexadecimal printf specification */
-int LastPid = -1;		/* last PID listed (for eliminating duplicates
-				 * in terse output) */
-struct lfile *Lf = (struct lfile *)NULL;
-				/* current local file structure */
-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
-				 *			   2 == read */
-char *MntSupP = (char *)NULL;	/* mount supplement path -- if MntSup == 2 */
-
-#if	defined(HASPROCFS)
-struct mounts *Mtprocfs = (struct mounts *)NULL;
-				/* /proc mount entry */
-#endif	/* defined(HASPROCFS) */
-
-int Mxpgid = 0;			/* maximum process group ID table entries */
-int Mxpid = 0;			/* maximum PID table entries */
-int Mxuid = 0;			/* maximum UID table entries */
-gid_t Mygid;			/* real GID of this lsof process */
-int Mypid;			/* lsof's process ID */
-uid_t Myuid;			/* real UID of this lsof process */
-char *Namech = (char *)NULL;	/* name characters for printing */
-size_t Namechl = (size_t)0;	/* sizeof(Namech) */
-int NCmdRxU = 0;		/* number of CmdRx[] entries */
-int Ndev = 0;			/* number of entries in Devtp[] */
-
-#if	defined(HASNLIST)
-struct NLIST_TYPE *Nl = (struct NLIST_TYPE *)NULL;
-				/* kernel name list */
-int Nll = 0;			/* Nl calloc'd length */
-#endif	/* defined(HASNLIST) */
-
-long Nlink = 0l;		/* report nlink values below this number
-				 * (0 = report all nlink values) */
-int Nlproc = 0;			/* number of entries in Lproc[] */
-int NlColW;			/* NLINK column width */
-int NmColW;			/* NAME column width */
-char *Nmlst = (char *)NULL;	/* namelist file path */
-int NodeColW;			/* NODE column width */
-int Npgid = 0;			/* -g option count */
-int Npgidi = 0;			/* -g option inclusion count */
-int Npgidx = 0;			/* -g option exclusion count */
-int Npid = 0;			/* -p option count */
-int Npidi = 0;			/* -p option inclusion count */
-int Npidx = 0;			/* -p option exclusion count */
-int Npuns;			/* number of unselected PIDs (starts at Npid) */
-int Ntype;			/* node type (see N_* symbols) */
-int Nuid = 0;			/* -u option count */
-int Nuidexcl = 0;		/* -u option count of UIDs excluded */
-int Nuidincl = 0;		/* -u option count of UIDs included */
-struct nwad *Nwad = (struct nwad *)NULL;
-				/* list of network addresses */
-int OffDecDig = OFFDECDIG;	/* offset decimal form (0t...) digit limit */
-int OffColW;			/* OFFSET column width */
-int PgidColW;			/* PGID column width */
-int PidColW;			/* PID column width */
-struct lfile *Plf = (struct lfile *)NULL;
-				/* previous local file structure */
-char *Pn;			/* program name */
-int PpidColW;			/* PPID column width */
-
-#if	defined(HASPROCFS)
-int Procfind = 0;		/* 1 when searching for an proc file system
-				 * file and one was found */
-struct procfsid *Procfsid = (struct procfsid *)NULL;
-				/* proc file system PID search table */
-int Procsrch = 0;		/* 1 if searching for any proc file system
-				 * file */
-#endif	/* defined(HASPROCFS) */
-
-int PrPass = 0;			/* print pass: 0 = compute column widths
-				 *	       1 = print */
-int RptTm = 0;			/* repeat time -- set by -r */
-int RptMaxCount = 0;		/* count of repeasts: 0 = no limit
-				 * -- set by -r */
-struct l_dev **Sdev = (struct l_dev **)NULL;
-				/* pointer to Devtp[] pointers, sorted
-				 * by device */
-int SelAll = 0;			/* SELALL flags, modified by IgnTasks */
-int Selflags = 0;		/* selection flags -- see SEL* in lsof.h */
-int SelProc = 0;		/* SELPROC flags, modified by IgnTasks */
-int Setgid = 0;			/* setgid state */
-int Selinet = 0;		/* select only Internet socket files */
-int Setuidroot = 0;		/* setuid-root state */
-struct sfile *Sfile = (struct sfile *)NULL;
-				/* chain of files to search for */
-struct int_lst *Spgid = (struct int_lst *)NULL;
-				/* process group IDs to search for */
-struct int_lst *Spid = (struct int_lst *)NULL;
-				/* Process IDs to search for */
-struct seluid *Suid = (struct seluid *)NULL;
-				/* User IDs to include or exclude */
-int SzColW;			/* SIZE column width */
-int SzOffColW;			/* SIZE/OFF column width */
-char *SzOffFmt_0t = (char *)NULL;
-				/* SZOFFTYPE 0t%u printf specification */
-char *SzOffFmt_d = (char *)NULL;
-				/* SZOFFTYPE %d printf  specification */
-char *SzOffFmt_dv = (char *)NULL;
-				/* SZOFFTYPE %*d printf  specification */
-char *SzOffFmt_x = (char *)NULL;
-				/* SZOFFTYPE %#x printf  specification */
-int TaskCmdColW = 0;		/* task command column width */
-int TaskCmdLim = TASKCMDL;	/* TASKCMD column width limit (same as
-				 * CmdLim) */
-int TaskPrtCmd = 0;		/* task print task command flag */
-int TaskPrtTid = 0;		/* task print TID flag */
-int TcpStAlloc = 0;		/* allocated (possibly unused) entries in TCP
-				 * state tables */
-unsigned char *TcpStI = (unsigned char *)NULL;
-				/* included TCP states */
-int TcpStIn = 0;		/* number of entries in TcpStI[] */
-int TcpStOff = 0;		/* offset for TCP state number to adjust
-				 * negative numbers to an index into TcpSt[],
-				 * TcpStI[] and TcpStX[] */
-unsigned char *TcpStX = (unsigned char *)NULL;
-				/* excluded TCP states */
-int TcpStXn = 0;		/* number of entries in TcpStX[] */
-int TcpNstates = 0;		/* number of TCP states -- either in
-				 * tcpstates[] or TcpSt[] */
-char **TcpSt = (char **)NULL;	/* local TCP state names, indexed by system
-				 * state value */
-char Terminator = '\n';		/* output field terminator */
-int TaskTidColW = 0;		/* task TID column width */
-int TmLimit = TMLIMIT;		/* Readlink() and stat() timeout (seconds) */
-int TypeColW;			/* TYPE column width */
-int UdpStAlloc = 0;		/* allocated (possibly unused) entries in UDP
-				 * state tables */
-unsigned char *UdpStI = (unsigned char *)NULL;
-				/* included UDP states */
-int UdpStIn = 0;		/* number of entries in UdpStI[] */
-int UdpStOff = 0;		/* offset for UDP state number to adjust
-				 * negative numbers to an index into UdpSt[],
-				 * UdpStI[] and UdpStX[] */
-unsigned char *UdpStX = (unsigned char *)NULL;
-				/* excluded UDP states */
-int UdpStXn = 0;		/* number of entries in UdpStX[] */
-int UdpNstates = 0;		/* number of UDP states  in UdpSt[] */
-char **UdpSt = (char **)NULL;	/* local UDP state names, indexed by system
-				 * state number */
-int UserColW;			/* USER column width */
-
-#if	defined(HASZONES)
-znhash_t **ZoneArg = (znhash_t **)NULL;
-				/* zone arguments supplied with -z */
-#endif	/* defined(HASZONES) */
-
-int ZoneColW;			/* ZONE column width */
diff --git a/support/AIXDistrib b/support/AIXDistrib
new file mode 100755
index 0000000..1d13db6
--- /dev/null
+++ b/support/AIXDistrib
@@ -0,0 +1,14 @@
+#!/bin/ksh
+#
+# AIXDistrib -- make AIX distribution of lsof 4.x
+#
+# Usage: AIXDistrib [<suffix>]
+#
+#	 <suffix>	optional suffix for identification
+
+if test $# -gt 1
+then
+  echo "Usage: [<suffix>]"
+  exit 1
+fi
+$HOME/src/lsof4/support/GenericDistrib aix $1
diff --git a/support/DarwinDistrib b/support/DarwinDistrib
new file mode 100755
index 0000000..9ade012
--- /dev/null
+++ b/support/DarwinDistrib
@@ -0,0 +1,14 @@
+#!/bin/ksh
+#
+# DarwinDistrib -- make Apple Darwin distribution of lsof 4.x
+#
+# Usage: DarwindDistrib [<suffix>]
+#
+#	 <suffix>	optional suffix for identification
+
+if test $# -gt 1
+then
+  echo "Usage: [<suffix>]"
+  exit 1
+fi
+$HOME/src/lsof4/support/GenericDistrib2 darwin $1
diff --git a/support/Distfile.msrc b/support/Distfile.msrc
new file mode 100644
index 0000000..2c175c3
--- /dev/null
+++ b/support/Distfile.msrc
@@ -0,0 +1,17 @@
+# $Id: Distfile.msrc,v 1.3 97/03/04 09:32:13 abe Exp $
+
+( . ) -> ( HOST )
+	except_pat ( /RCS /Makefile\$ /Distfile /Make\.host /dialects /Lsof.8 );
+	install ${INTO};
+
+( @Make.host@ ) -> ( HOST )
+	install -b ${INTO}/makefile;
+
+ifelse(
+HOSTTYPE,`IBMR2',`( ./dialects/aix ) -> ( HOST )
+	except_pat ( /RCS );
+	install ${INTO}/dialects/aix;',
+HOSTTYPE,`SUN5',`( ./dialects/sun ) -> ( HOST )
+	except_pat ( /RCS );
+	install ${INTO}/dialects/sun;',
+)dnl
diff --git a/support/FreeBSDDistrib b/support/FreeBSDDistrib
new file mode 100755
index 0000000..b58a4a9
--- /dev/null
+++ b/support/FreeBSDDistrib
@@ -0,0 +1,14 @@
+#!/bin/ksh
+#
+# FreeBSDDistrib -- make FreeBSD distribution of lsof 4.x
+#
+# Usage: FreeBSDDistrib [<suffix>]
+#
+#	 <suffix>	optional suffix for identification
+
+if test $# -gt 1
+then
+  echo "Usage: [<suffix>]"
+  exit 1
+fi
+$HOME/src/lsof4/support/GenericDistrib2 freebsd $1
diff --git a/support/GPGDistrib b/support/GPGDistrib
new file mode 100755
index 0000000..06b9675
--- /dev/null
+++ b/support/GPGDistrib
@@ -0,0 +1,493 @@
+#!/bin/ksh
+#
+# GPGDistrib -- make lsof 4.x GPG distribution files
+
+# Define DEBUG to 1 in the environment to skip to the README file construction.
+#
+# Usage: GPGDistrib [edition]
+#
+#	edition		optional edition suffix to add to version number
+#set -x	# DEBUG
+
+if test "X$DEBUG" = "X"
+then
+  DEBUG=0
+fi
+
+# Check for GPG pass phrase.
+
+if test $DEBUG -eq 0
+then
+  if test "X$PGPPASS" = "X"
+  then
+    echo "No GPG pass phrase is defined in the environment."
+    exit 1
+  fi
+fi
+
+# Change working directory.
+
+HD=$HOME/src/lsof4
+echo Changing to $HD
+cd $HD
+
+# Get version number.
+
+V=`sed '/VN/s/.ds VN \(.*\)/\1/' version`
+if test $? -ne 0
+then
+  echo $V
+  exit 1
+fi
+
+# Handle optional edition suffix.
+
+if test $# -gt 0
+then
+  if test $# -gt 1
+  then
+    echo "Usage: GPGDistrib [edition]"
+    exit 1
+  fi
+  V=${V}$1
+fi
+
+# Define directory and archive file names.
+
+CK=CHECKSUMS_${V}
+DN=lsof_${V}
+DT=${DN}.tar
+M=00MANIFEST
+MC=${DN}/manifest_check.${V}
+R=README.lsof_${V}
+RM=00.README.FIRST_${V}
+SF=support/lsof.README
+DSF=RELEASE.SUMMARY_${V}
+SN=${DN}_src
+SD=${DN}/$SN
+ST=${SN}.tar
+echo "Creating lsof ${V} GPG distribution ..."
+
+# Define source files to copy.
+
+F="00.README.FIRST 00CREDITS 00DCACHE 00DIALECTS 00DIST 00FAQ 00LSOF-L 00MANIFEST 00PORTING 00QUICKSTART 00README 00TEST 00XCONFIG AFSConfig ChangeLog Configure Customize Inventory dialects arg.c lib common.h lsof_fields.h main.c misc.c node.c print.c proc.c proto.h regex.h scripts store.c tests usage.c util.c version"
+MS=Lsof.8
+MD=${DN}/${SN}/lsof.8
+MF=${DN}/${SN}/lsof.man
+
+# Set exit cleanup trap.
+
+trap 'rm -rf support/$CK $DN; exit' 1 2 3 15
+
+# Create source directory.
+
+if test $DEBUG -eq 0
+then
+  echo Creating $DN and ${DN}/${SN}
+  rm -rf $DN
+  mkdir $DN
+  (cd $DN; mkdir $SN)
+  echo "Copying to ${SD}:\c"
+  for i in $F
+  do
+    echo " $i\c"
+    cp -rp $i $SD
+  done
+  echo " ... done"
+  echo "Removing extraneous stuff from lib ...\c"
+  find $SD/lib -name OLD -exec rm -rf {} \; > /dev/null 2>&1
+  find $SD/lib -name RCS -exec rm -rf {} \; > /dev/null 2>&1
+  find $SD/lib -name NEW -exec rm -rf {} \; > /dev/null 2>&1
+  rm -rf $SD/lib/Makefile
+  rm -rf $SD/lib/*.[oa]
+  echo " done"
+  echo "Removing extraneous stuff from dialects ...\c"
+  find $SD/dialects -name OLD -exec rm -rf {} \; > /dev/null 2>&1
+  find $SD/dialects -name RCS -exec rm -rf {} \; > /dev/null 2>&1
+  find $SD/dialects -name NEW -exec rm -rf {} \; > /dev/null 2>&1
+  find $SD/dialects -name Makefile.local -exec rm -f {} \; > /dev/null 2>&1
+  find $SD/dialects -name distfile.kvm -exec rm -f {} \; > /dev/null 2>&1
+  find $SD/dialects -name support -exec rm -rf {} \; > /dev/null 2>&1
+  echo " done"
+  echo "Removing extraneous stuff from scripts ...\c"
+  find $SD/scripts -name OLD -exec rm -rf {} \; > /dev/null 2>&1
+  find $SD/scripts -name RCS -exec rm -rf {} \; > /dev/null 2>&1
+  find $SD/scripts -name NEW -exec rm -rf {} \; > /dev/null 2>&1
+  echo " done"
+  echo "Removing extraneous stuff from tests ...\c"
+  find $SD/tests -name OLD -exec rm -rf {} \; > /dev/null 2>&1
+  find $SD/tests -name RCS -exec rm -rf {} \; > /dev/null 2>&1
+  find $SD/tests -name NEW -exec rm -rf {} \; > /dev/null 2>&1
+  rm -rf $SD/tests/config.* $SD/tests/*.o
+  rm -rf $SD/tests/LTbasic $SD/tests/LTbigf $SD/tests/LTdnlc
+  rm -rf $SD/tests/LTlock $SD/tests/LTnfs $SD/tests/LTnlink
+  rm -rf $SD/tests/LTsock $SD/tests/LTszoff $SD/tests/LTunix
+  echo " done"
+fi
+
+# Create manual page files.
+
+if test $DEBUG -eq 0
+then
+  echo Producing $MD
+  soelim < $MS > $MD
+  echo Producing $MF
+  nroff -man $MD | colcrt - | cat -s > $MF
+fi
+
+# Check distribution directory for completeness.
+
+if test $DEBUG -eq 0
+then
+  echo "Checking $SD for completeness"
+  rm -f $MC
+  (cd $SD; ls -FR) > $MC
+  diff $M $MC > /dev/null
+  if test $? -ne 0
+  then
+    (echo Some files may be missing.; echo diff $M $MC; diff $M $MC) | less
+    exit 1
+  fi
+fi
+
+# Create source distribution tar file.
+
+if test $DEBUG -eq 0
+then
+  echo Creating $ST in $DN
+  (cd $DN; tar cf $ST $SN; ls -l $ST)
+  echo Removing $SD
+  rm -rf $SD
+fi
+
+# Create source distribution README.lsof_<version> file.
+
+if test $DEBUG -eq 0
+then
+  echo Creating $R for $DT
+  rm -f ${DN}/$R
+  EO=${DN}/$R
+else
+  echo "==== The $R file ====="
+  EO=""
+fi
+cat > $EO << END_README_1
+
+                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_${V}.  If either is the case, please skip to
+the Inventory section.  If you haven't read RELEASE.SUMMARY_${V},
+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 ${DT}.bz2,
+${DT}.gz or ${DT}.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, ${V}, is the lsof revision number.  When you bunzip2'd,
+gunzip'd or uncompressed ${DT}.* and used tar to unpack
+${DT}, you got: ${RM}, describing the contents
+of ${DN}; ${R}; ${ST}; and
+${ST}.sig.  All are identified with the revision number.
+You're reading ${R}.  ${ST}.sig is a GPG
+certificate that authenticates the lsof source archive,
+${ST}.
+
+After you read the Inventory and Security sections, and hopefully
+after you check the GPG certificate, unpack the ${ST}
+source archive and you will get a sub-directory, named ${SN},
+that contains the lsof ${V} source distribution.
+
+
+Inventory
+=========
+
+Once you have unpacked ${ST}.tar, you can check
+${SN} for completeness by changing to that sub-directory
+and running the Inventory script.  The ${SN}/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 ${SN} sub-directory you just created.
+
+
+Security
+========
+
+The md5 checksum for $ST is:
+
+END_README_1
+echo "  \c" >> $EO
+if test $DEBUG -eq 1
+then
+  echo "MD5 checksum of $ST would go here." >> $EO
+else
+  (cd $DN; md5 $ST) >> $EO
+fi
+cat >> $EO << END_README_2
+
+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 $SN
+
+The old-style sum(1) checksum for $ST (Please read
+the next paragraph if you don't get this value.) is:
+
+END_README_2
+echo "  \c" >> $EO
+if test $DEBUG -eq 1
+then
+  echo "Sum checksum of $ST would go here." >> $EO
+else
+  sum -r ${DN}/$ST >> $EO
+fi
+cat >> $EO << END_README_3
+
+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.
+
+${ST}.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 $ST:
+
+    gpg --verify ${ST}.sig $ST
+
+If the certificate check isn't good, $ST 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
+$ST to the value listed in this file.  However, that
+is a less reliable authentication method, since it can't detect
+changes to both $ST 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>
+END_README_3
+
+date >> $EO
+
+# Create GPG certificate.
+
+if test $DEBUG -eq 0
+then
+  echo Creating ${ST}.sig in $DN
+  (cd $DN; rm -f ${ST}.sig; \
+   echo $PGPPASS | gpg -o ${ST}.sig --passphrase-fd 0 -b $ST; \
+   chmod 644 ${ST}.sig)
+fi
+
+# Construct distribution's 00.README_FIRST_<version> file.
+
+if test $DEBUG -eq 0
+then
+  echo Creating $RM for $DT
+  rm -f ${DN}/$RM
+  EO=${DN}/$RM
+else
+  echo ""
+  echo "==== The $RM file ====="
+  echo ""
+  EO=""
+fi
+echo "A tour of the lsof_${V} distribution:" > $EO
+echo "" >> $EO
+echo "  $RM is this file." >> $EO
+echo "" >> $EO
+echo "  $R contains distribution and security information." >> $EO
+echo "" >> $EO
+echo "  ${DSF} contains a summary of the lsof ${V}" >> $EO
+echo "  distribution." >> $EO
+echo "" >> $EO
+echo "  $ST is the lsof ${V} source tar archive." >> $EO
+echo "" >> $EO
+echo "  ${ST}.sig is a detached GPG certificate for" >> $EO
+echo "  ${ST}." >> $EO
+echo "" >> $EO
+echo "I suggest you follow these steps:" >> $EO
+echo "" >> $EO
+echo "1.  Read ${RM}." >> $EO
+echo "" >> $EO
+echo "2.  Read ${R} and follow its instructions to verify" >> $EO
+echo "    the authenticity of ${ST}." >> $EO
+echo "" >> $EO
+echo "3.  Unpack ${ST} -- use \`tar xf ${ST}\`." >> $EO
+echo "    That will produce an ${SN} sub-directory." >> $EO
+echo "" >> $EO
+echo "4.  Change to the ${SN} sub-directory and read its" >> $EO
+echo "    00.README.FIRST file." >> $EO
+echo "" >> $EO
+echo "Vic Abell <abe@purdue.edu>" >> $EO
+echo `date` >> $EO
+
+# Create distribution summary file.
+
+if test $DEBUG -eq 0
+then
+  echo Creating ${DN}/$DSF
+  rm -f ${DN}/$DSF
+  cp $SF ${DN}/$DSF
+else
+  echo Distribution summary file would be ${DN}/$DSF, copied from $SF.
+fi
+
+# Create distribution tar file, then bzip2, compress and gzip it.
+
+if test $DEBUG -eq 0
+then
+  rm -f $MC
+  echo Creating $DT
+  rm -f $DT ${DT}.bz2 ${DT}.gz ${DT}.Z
+  tar cf $DT $DN
+  ls -l $DT
+  echo Bzip2ing $DT
+  bzip2 -c $DT > support/${DT}.bz2
+  ls -l support/${DT}.bz2
+  echo Gzipping $DT
+  gzip -c $DT > support/${DT}.gz
+  ls -l support/${DT}.gz
+  echo Compressing $DT
+  compress < $DT > support/${DT}.Z
+  ls -l support/${DT}.Z
+  echo Removing $DN and $DT
+  rm -rf $DN $DT
+
+  # Create checksum files.
+
+  for i in bz2 gz Z
+  do
+    echo Creating ${DT}.${i}.sig
+    SIG=support/${DT}.${i}.sig
+    SRC=support/${DT}.${i}
+    rm -f $SIG
+    echo $PGPPASS | gpg -o $SIG --passphrase-fd 0 -b $SRC
+  done
+  echo Creating $CK
+  rm -f support/$CK
+  cat >> support/$CK << END_CKSUM_1
+
+                        Checksums for lsof_${V}
+
+This file was created when the official lsof ${V} distribution files
+were created.  It contains MD5 checksums and GPG certificate
+information for the lsof ${V} bzip2, gzip and compressed distribution
+files.
+
+There are additional opportunities to validate the lsof distribution
+with information found inside it.  Consult the file ${R}
+inside the distribution.
+
+MD5 Checksums
+=============
+
+The MD5 checksums are:
+
+END_CKSUM_1
+
+  for i in bz2 gz Z
+  do
+    echo "  \c" >> support/$CK
+    (cd support; md5 ${DT}.$i >> $CK)
+  done
+
+cat >> support/$CK << END_CKSUM_2
+
+GPG Certificates
+================
+
+The following files, found with the lsof distribution files, contain
+GPG certificates:
+
+  lsof.tar.bz2.sig or ${DT}.bz2.sig
+  lsof.tar.gz.sig  or ${DT}.gz.sig
+  lsof.tar.Z.sig   or ${DT}.Z.sig
+
+Validating a GPG certificate is the best way to make sure no one has
+tampered with a distribution file.
+
+Use the GPG certificate files with the GPG public key for:
+
+  Victor A. Abell <abe@purdue.edu>
+
+You may be able to find the key on some public key servers.  It is also
+available at:
+
+  ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/Victor_A_Abell.gpg
+
+Get the key and install it in your public key ring.  Once the key is
+installed, use one of these command forms to check the certificate of a
+distribution file:
+
+  gpg --verify ${DT}.<type>.sig ${DT}.<type>
+
+or
+
+  gpg --verify lsof.tar.<type>.sig lsof.tar.<type>
+
+Where <type> is bz2, gz or Z.
+
+Problems
+========
+
+If an MD5 or GPG check reveals a problem, please report it via e-mail
+to <abe@purdue.edu>.
+
+
+Vic Abell
+END_CKSUM_2
+date >> support/$CK
+(cd support; ls -l $CK)
+fi
+echo "all done"
diff --git a/support/GenericCopy b/support/GenericCopy
new file mode 100755
index 0000000..93abf9b
--- /dev/null
+++ b/support/GenericCopy
@@ -0,0 +1,88 @@
+#!/bin/ksh
+#
+# GenericCopy -- generically copy lsof 4.x sources to a specified destination
+#
+# Usage: GenericCopy <destination> <login> <dialect> [<directory>]
+#
+#	 <destination>	destination host
+#
+#	 <login>	login name at destination host
+#
+#	 <dialect>	dialect subdirectory name
+#
+#	 [<directory>]	directory if other than src/lsof4
+
+if test $# -lt 1 -o $? -gt 4
+then
+  echo "Usage: <destination> <login> <dialect> [<directory>]"
+  exit
+fi
+D=$1
+L=$2
+DSDIR=$3
+if test $# -eq 4
+then
+  DDIR=$4
+else
+  DDIR=src/lsof4
+fi
+
+# Set useful definitions.
+
+SDIR=src/lsof4
+F="00DIALECTS AFSConfig Configure Customize Inventory arg.c lsof_fields.h common.h main.c misc.c node.c print.c proc.c proto.h regex.h store.c usage.c util.c version"
+
+cd $HOME/$SDIR
+
+# Make sure the destination directories exist.
+
+rsh $D -l $L -n mkdir $DDIR $DDIR/dialects $DDIR/lib $DDIR/dialects/$DSDIR
+
+# Copy new base directory files to destination.
+
+rsh $D -l $L -n "(cd $DDIR; rm -f $F)"
+for i in $F
+do
+  rcp $i ${L}@${D}:${DDIR}
+  echo "$i \c"
+done
+echo ""
+
+# Remove old files in lib/ and dialects/<dialect>/.
+
+rsh $D -l $L -n "rm -rf $DDIR/lib/* $DDIR/dialects/$DSDIR/*"
+
+# Copy lib/*.
+
+cd lib
+echo "lib: \c"
+for i in *.c Makefile.skel
+do
+  if test ! -d $i
+  then
+    rcp $i ${L}@${D}:${DDIR}/lib
+    echo "$i \c"
+  fi
+done
+echo ""
+
+# Copy dialects/<dialect>/*.
+
+cd ../dialects/$DSDIR
+echo "dialects/$DSDIR: \c"
+for i in *
+do
+  if test -d $i
+  then
+    if test $i != OLD -a $i != NEW -a $i != RCS
+    then
+      rcp -r $i ${L}@${D}:${DDIR}/dialects/$DSDIR
+      echo "$i \c"
+    fi
+  else
+    rcp $i ${L}@${D}:${DDIR}/dialects/$DSDIR
+    echo "$i \c"
+  fi
+done
+echo ""
+echo "done"
diff --git a/support/GenericDistrib b/support/GenericDistrib
new file mode 100755
index 0000000..ebe25fe
--- /dev/null
+++ b/support/GenericDistrib
@@ -0,0 +1,70 @@
+#!/bin/ksh
+#
+# GenericDistrib -- generic lsof 4.x distribution gzip'd archive builder
+# GenericDistrib2 -- generic lsof 4.x distribution bzip2'd archive builder
+#
+# Usage: GenericDistrib <dialect> [<suffix>]
+#
+#	<dialect>	dialect's subdirectory name
+#
+#	[<suffix>]	optional suffix for version number
+
+cd $(dirname $0)/..
+
+# Get version number.
+
+V=`sed '/VN/s/.ds VN \(.*\)/\1/' version`
+if test $? -ne 0
+then
+  echo $V
+  exit 1
+fi
+
+# Handle arguments.
+
+if test $# -lt 1 -o $# -gt 2
+then
+  echo "Usage: <dialect> [<suffix>]"
+  exit 1
+fi
+DIALECT=$1
+if test $# -eq 2
+then
+  V=${V}$2
+fi
+
+# Set variable names.
+
+DIR=lsof_${V}.${DIALECT}
+TAR=${DIR}.tar
+echo $0 | grep 2 > /dev/null
+if test $? -eq 0
+then
+  TARC=${TAR}.bz2
+  COMP=bzip2
+else
+  TARC=${TAR}.gz
+  COMP=gzip
+fi
+
+# Prepare for premature exit.
+
+trap 'rm -rf $DIR $TAR $TARC; exit' 1 2 3 15
+
+# Make a temporary directory with the relevant files in it and
+# create a gzip'd tar archive of it.
+
+rm -rf $TAR $TARC
+./support/GenericSubdir $1 $2
+echo "Making $TAR ...\c"
+tar cf $TAR $DIR
+echo " done"
+ls -l $TAR
+echo "Removing $DIR ...\c"
+rm -rf $DIR
+echo " done"
+echo "$COMP $TAR ...\c"
+$COMP -c $TAR > support/$TARC
+echo " done"
+ls -l support/$TARC
+rm -f $TAR
diff --git a/support/GenericDistrib2 b/support/GenericDistrib2
new file mode 120000
index 0000000..e2306c6
--- /dev/null
+++ b/support/GenericDistrib2
@@ -0,0 +1 @@
+GenericDistrib
\ No newline at end of file
diff --git a/support/GenericRdist b/support/GenericRdist
new file mode 100755
index 0000000..f2b75cf
--- /dev/null
+++ b/support/GenericRdist
@@ -0,0 +1,80 @@
+#!/bin/ksh
+#
+# GenericRdist -- generically rdist lsof 4.x sources to a specified destination
+#
+# Usage: GenericRdist <destination> <dialect> <shell>
+#
+#	 <destination>	destination host
+#
+#	 <dialect>	dialect subdirectory name
+#
+#	 <shell>	remote shell -- rsh or ssh
+
+# Process arguments.
+
+if test $# -ne 3
+then
+  echo "Usage: <destination> <dialect> <shell>"
+  exit
+fi
+H=$1
+D=$2
+S=$3
+
+# Test the shell and define its full path, as required.
+
+if test "X$S" = "Xrsh"
+then
+  SHP=""
+else
+  if test "X$S" = "Xssh"
+  then
+    SHP="-P /opt/openssh/bin/ssh"
+  else
+    echo "$S is not an acceptable shell; specify rsh or ssh."
+    exit
+  fi
+fi
+
+# Define the distfile and make sure it's removed on premature exit.
+
+R=/tmp/distfile.$$
+trap 'rm $R; exit 1' 1 2 3 15
+
+rm -f $R
+cat > $R << .DISTFILE
+. -> $H
+	except ( ./00.README.FIRST ./00DCACHE ./00DIST ./00FAQ );
+	except ( ./00PORTING ./00README ./00CREDITS ./00QUICKSTART );
+	except ( ./00LSOF-L ./00MANIFEST ./00XCONFIG ./.ck00MAN );
+	except ( ./00TEST ./.neverCust ./.neverInv );
+	except ( ./ChangeLog ./Makefile );
+	except ( ./lsof ./lsof32 ./lsof64 ./lsof_old /lsof_32.old );
+	except ( ./lsof_64.old ./Lsof.8 );
+	except ( ./ddev.c ./dfile.c ./dlsof.h ./dmnt.c ./dnode.c ./dnode1.c );
+	except ( ./dnode2.c ./dproc.c ./dproto.h ./dsock.c ./dstore.c );
+	except ( ./kernelbase.h ./machine.h ./version.h ./zipme );
+	except ( ./NEW ./OLD ./RCS ./dialects ./support ) ;
+	except ( ./make.out ./new ./old ./out ./X ./xxx ./errs ) ;
+	except ( ./lib/Makefile ./lib/RCS ./lib/OLD ./lib/NEW );
+	except ( ./scripts/OLD ./scripts/NEW ./scripts/RCS );
+	except ( ./scripts/00MANIFEST ./scripts/00README ) ;
+	except ( ./tests/OLD ./tests/NEW ./tests/RCS );
+	except ( ./tests/00README );
+	except ( ./tests/LTbasic ./tests/LTbigf ./tests/LTdnlc );
+	except ( ./tests/LTlock ./tests/LTnfs ./tests/LTnlink );
+	except ( ./tests/LTsock ./tests/LTszoff ./tests/LTunix );
+	except_pat ( \\.o\\$ \\.a\\$ ./tests/config\\. );
+	install src/lsof4;
+
+./dialects/$D -> $H
+	except ( ./dialects/$D/NEW );
+	except ( ./dialects/$D/OLD ./dialects/$D/RCS );
+	install src/lsof4/dialects/$D ;
+.DISTFILE
+
+# Do the actual distribution.
+
+(cd $HOME/src/lsof4; /usr/local/bin/rdist $SHP -f $R)
+rm $R
+echo done
diff --git a/support/GenericSubdir b/support/GenericSubdir
new file mode 100755
index 0000000..5921414
--- /dev/null
+++ b/support/GenericSubdir
@@ -0,0 +1,106 @@
+#!/bin/ksh
+#
+# GenericSubdir -- create generic lsof 4.x distribution subdirectory
+#
+# Usage: GenericSubdir <dialect> [<suffix>]
+#
+#	<dialect>	dialect's subdirectory name
+#
+#	[<suffix>]	optional suffix for version number
+
+cd $(dirname $0)/..
+
+# Get version number.
+
+V=`sed '/VN/s/.ds VN \(.*\)/\1/' version`
+if test $? -ne 0
+then
+  echo $V
+  exit 1
+fi
+
+# Handle arguments.
+
+if test $# -lt 1 -o $# -gt 2
+then
+  echo "Usage: <dialect> [<suffix>]"
+  exit 1
+fi
+DIALECT=$1
+if test $# -eq 2
+then
+  V=${V}$2
+fi
+
+# Set variable names.
+
+DIR=lsof_${V}.${DIALECT}
+F=
+F="$F 0..README.BEFORE.README.FIRST README.md check.bash"
+F="$F 00.README.FIRST 00CREDITS 00DCACHE 00DIALECTS 00DIST 00FAQ 00LSOF-L 00PORTING 00QUICKSTART 00README 00TEST 00XCONFIG"
+F="$F AFSConfig ChangeLog Configure Customize Inventory"
+F="$F arg.c lsof_fields.h common.h main.c misc.c node.c print.c proc.c proto.h regex.h store.c usage.c util.c"
+F="$F version"
+MS=Lsof.8
+MD=lsof.8
+MF=lsof.man
+
+# Prepare for premature exit.
+
+trap 'rm -rf $DIR; exit' 1 2 3 15
+
+# Make a temporary directory and copy the relevant files to it.
+
+rm -rf $DIR
+mkdir $DIR
+echo "Copying:\c"
+for i in $F
+do
+  echo " $i\c"
+  cp -r $i $DIR
+done
+echo " ... done"
+echo "Copying lib ...\c"
+cp -r lib $DIR/lib
+echo " done"
+echo "Removing extraneous stuff from lib ...\c"
+rm -rf $DIR/lib/RCS $DIR/lib/OLD $DIR/lib/NEW
+rm -rf $DIR/lib/Makefile $DIR/lib/*.[oa]
+echo " done"
+mkdir $DIR/dialects
+echo "Copying dialects/${DIALECT} ...\c"
+cp -r dialects/${DIALECT} $DIR/dialects
+echo " done"
+echo "Removing extraneous stuff from dialects/${DIALECT} ...\c"
+rm -rf $DIR/dialects/${DIALECT}/distfile.kvm
+rm -rf $DIR/dialects/${DIALECT}/Makefile.LOCAL
+rm -rf $DIR/dialects/${DIALECT}/version.h
+find ${DIR}/dialects -name OLD -exec rm -rf {} \; > /dev/null 2>&1
+find ${DIR}/dialects -name NEW -exec rm -rf {} \; > /dev/null 2>&1
+find ${DIR}/dialects -name support -exec rm -rf {} \; > /dev/null 2>&1
+find ${DIR}/dialects -name RCS -exec rm -rf {} \; > /dev/null 2>&1
+echo " done"
+echo "Copying scripts ...\c"
+cp -r scripts $DIR
+echo " done"
+echo "Removing extraneous stuff from scripts ...\c"
+rm -rf $DIR/scripts/NEW $DIR/scripts/OLD $DIR/scripts/RCS
+echo " done"
+echo "Copying tests ...\c"
+cp -r tests $DIR
+echo " done"
+echo "Removing extraneous stuff from tests ...\c"
+rm -rf $DIR/tests/NEW $DIR/tests/OLD $DIR/tests/RCS $DIR/tests/*.o
+rm -rf $DIR/tests/00README
+rm -rf $DIR/tests/config.* $DIR/tests/LTbasic $DIR/tests/LTbigf
+rm -rf $DIR/tests/LTdnlc $DIR/tests/LTlock $DIR/tests/LTnfs
+rm -rf $DIR/tests/LTnlink $DIR/tests/LTsock $DIR/tests/LTszoff
+rm -rf $DIR/tests/LTunix
+echo " done"
+echo "Producing $MD and $MF ...\c"
+soelim < $MS > $DIR/$MD
+nroff -man $MS | colcrt - | cat -s > $DIR/$MF
+echo " done"
+echo "Producing 00MANIFEST ...\c"
+(cd $DIR; ls -FR > 00MANIFEST)
+echo " done"
diff --git a/support/GitHub-release/00README b/support/GitHub-release/00README
new file mode 100644
index 0000000..fd69bbe
--- /dev/null
+++ b/support/GitHub-release/00README
@@ -0,0 +1,10 @@
+There are two files in this directory that document the release
+of lsof to GitHub by Purdue officials.
+
+ITaP	contains a release from Purdue's Vice President for
+	Information technology, Gerry McCartney.
+
+Purdue	contains a release from Purdue's Senior Intellectual
+	Property Officer, Ken L. Sandel.
+
+14 July 2018
diff --git a/support/GitHub-release/ITaP b/support/GitHub-release/ITaP
new file mode 100644
index 0000000..0a115b4
--- /dev/null
+++ b/support/GitHub-release/ITaP
@@ -0,0 +1,47 @@
+From:	McCartney, William G <mccart@purdue.edu>
+Sent:	Wednesday, June 27, 2018 16:35
+To:	Victor Abell
+Cc:	Vic Abell
+Subject:	RE: retiring lsof
+
+No objection at all Vic,  and thank you for so many years of valuable service to the community.
+
+From one my senior people: “Lsof is one of the most amazing UNIX tools that retired PUCC
+wizard Vic wrote and still supports. Github is a much better answer than running a server in
+ITaP for it.”
+
+Best wishes,   Gerry-
+
+From: Victor Abell <vabell@lsof.comcastbiz.net>
+Sent: Wednesday, June 27, 2018 5:06 AM
+To: McCartney, William G <mccart@purdue.edu>
+Cc: Vic Abell <abe@purdue.edu>
+Subject: retiring lsof
+
+Gerry,
+
+Since I retired from ITaP in 2003, I have received support from ITaP
+to continue distributing lsof, the open source UNIX tool that I developed
+at PUCC and released in 1994.  That support extends to a Visiting
+Scholar appointment and a Sun Solaris system, lsof.itap.purdue.edu
+from which lsof is distributed.
+
+I am nearing 80 in age and it is time for me to end my support before
+circumstances do it for me.  I announced that intention to the lsof –l
+mailing list (lsof-l@lists.purdue.edu) and several readers replied that
+they would like to continue support by moving lsof to the GitHub
+open source development platform (https://github.com/).
+
+Because the lsof source code contains a Purdue Research Foundation
+copyright, I have been discussing the release with Joseph R. Kasper
+(JRKasper@prf.org) in Purdue’s Office of Technology Commercialization.
+Joe is supportive of the move, but asks if I have discussed it with anyone
+in ITaP.  Only Greg Veldman (gv@purdue.edu) , who has provided
+support for lsof.itap, has been aware of the GitHub request.
+I have been remiss in not contacting you about this.  Please excuse my
+omission and let me know if you have any objection to the release of
+lsof to GitHub.
+
+Regards,
+
+Vic Abell
diff --git a/support/GitHub-release/Purdue b/support/GitHub-release/Purdue
new file mode 100644
index 0000000..d7fd360
--- /dev/null
+++ b/support/GitHub-release/Purdue
@@ -0,0 +1,156 @@
+From:	Sandel, Ken L. <sandel@purdue.edu>
+Sent:	Tuesday, July 10, 2018 14:28
+To:	Victor Abell
+Subject:	RE: One more question regarding GitHub release
+
+Vic,
+
+For clarity – I approved the release.
+
+Ken
+
+Ken L. Sandel
+Senior Director, Sponsored Program Services
+Senior Intellectual Property Officer
+Purdue University
+610 Purdue Mall
+Hovde Hall Room 328
+West Lafayette, IN 47907
+sandel@purdue.edu
+(765) 494-1063 (office)
+(765) 426-2530 (cell)
+
+From: Kasper, Joseph R. <JRKasper@prf.org>
+Sent: Tuesday, July 10, 2018 11:23 AM
+To: Victor Abell <vabell@lsof.comcastbiz.net>
+Cc: Sandel, Ken L. <sandel@purdue.edu>
+Subject: RE: One more question regarding GitHub release
+
+Hi Vic,
+
+My apologies for not following up. Mr. Sandel approves the release on GitHub under the copyright
+notice text currently in use.
+
+Best,
+Joe
+
+Joseph R. Kasper, Ph.D.
+Senior Business Development Manager & Director of Marketing
+Office of Technology Commercialization
+765-588-3486
+jrkasper@prf.org
+Purdue Technology Center Aerospace
+1801 Newman Road
+West Lafayette, IN 47906
+www.innovation-entrepreneurship-purdue.com
+www.prf.org/otc/
+
+
+CONFIDENTIALITY NOTICE:  This email and any attachments are for the exclusive and confidential use of the intended recipient.  If you are not
+the intended recipient, please do not read, distribute or take action in reliance upon this message.  If you have received this in error, please
+notify us immediately by return email and promptly delete this message and its attachments from your computer system.
+
+
+
+
+From: Victor Abell <vabell@lsof.comcastbiz.net>
+Sent: Monday, July 9, 2018 8:26 PM
+To: Kasper, Joseph R. <JRKasper@prf.org>
+Subject: RE: One more question regarding GitHub release
+
+Joe,
+
+Has there been any word from Ken about the release
+of lsof to GitHub?
+
+Vic
+
+From: Kasper, Joseph R. [mailto:JRKasper@prf.org]
+Sent: Thursday, June 28, 2018 1:15 PM
+To: Victor Abell
+Subject: RE: One more question regarding GitHub release
+
+Hi Vic,
+
+One more request. Ken would like a copy of the email from Gerry. If for any reason you aren’t
+comfortable sending it to me, please contact Ken directly (765-494-1063, sandel@purdue.edu).
+
+If this last piece of information is satisfactory to Ken, I expect to get his approval.
+
+Thanks for your cooperation throughout this process.
+
+Best,
+Joe
+
+From: Victor Abell <vabell@lsof.comcastbiz.net>
+Sent: Thursday, June 28, 2018 7:43 AM
+To: Kasper, Joseph R. <JRKasper@prf.org>
+Subject: RE: One more question regarding GitHub release
+
+Joe,
+
+I sent e-mail to Gerry McCartney and in his answer he
+says he has no objection.
+
+Vic
+
+From: Kasper, Joseph R. [mailto:JRKasper@prf.org]
+Sent: Tuesday, June 26, 2018 4:03 PM
+To: Victor Abell
+Subject: RE: One more question regarding GitHub release
+
+Hi Vic,
+
+Thanks for the extra detail. I think it would put Ken’s mind at ease if you have Gerry’s blessing. Let me
+know if you’ll reach out to him.
+
+Best,
+Joe
+
+From: Victor Abell <vabell@lsof.comcastbiz.net>
+Sent: Tuesday, June 26, 2018 3:57 PM
+To: Kasper, Joseph R. <JRKasper@prf.org>
+Subject: RE: One more question regarding GitHub release
+
+Joe,
+
+I have had no communication with ITaP about the move to GitHub.
+The extent of their involvement with lsof has been minimal – the
+Visiting Scholar appointment and the maintenance of a distribution
+system.
+
+I know Gerry McCartney well.  Would it be helpful if I contacted
+him about the GitHub move?
+
+Vic
+
+From: Kasper, Joseph R. [mailto:JRKasper@prf.org]
+Sent: Tuesday, June 26, 2018 3:44 PM
+To: Vic Abell; Victor Abell
+Subject: One more question regarding GitHub release
+
+Hi Vic,
+
+Ken Sandel, Senior IP Officer, just got back to me. He wants to know if the leadership of ITaP supports
+the contribution to Github. Please let me know. If you have any communication to this effect that you
+can forward to me, it would be helpful.
+
+Best,
+Joe
+
+Joseph R. Kasper, Ph.D.
+Business Development Manager
+Purdue Research Foundation
+Office of Technology Commercialization
+765-588-3486
+jrkasper@prf.org
+Purdue Technology Center Aerospace
+1801 Newman Road
+West Lafayette, IN 47906
+www.innovation-entrepreneurship-purdue.com
+www.prf.org/otc/
+
+
+CONFIDENTIALITY NOTICE:  This email and any attachments are for the exclusive and confidential use of the intended recipient.  If you are not
+the intended recipient, please do not read, distribute or take action in reliance upon this message.  If you have received this in error, please
+notify us immediately by return email and promptly delete this message and its attachments from your computer system.
diff --git a/support/HPUXDistrib b/support/HPUXDistrib
new file mode 100755
index 0000000..082e253
--- /dev/null
+++ b/support/HPUXDistrib
@@ -0,0 +1,14 @@
+#!/bin/ksh
+#
+# HPUXDistrib -- make HP-UX distribution of lsof 4.x
+#
+# Usage: HPUXDistrib [<suffix>]
+#
+#	 <suffix>	optional suffix for identification
+
+if test $# -gt 1
+then
+  echo "Usage: [<suffix>]"
+  exit 1
+fi
+$HOME/src/lsof4/support/GenericDistrib hpux $1
diff --git a/support/NSDistrib b/support/NSDistrib
new file mode 100755
index 0000000..ed72809
--- /dev/null
+++ b/support/NSDistrib
@@ -0,0 +1,14 @@
+#!/bin/ksh
+#
+# NSDistrib -- make NeXTSTEP distribution of lsof 4.x
+#
+# Usage: NSDistrib [<suffix>]
+#
+#	 <suffix>	optional suffix for identification
+
+if test $# -gt 1
+then
+  echo "Usage: [<suffix>]"
+  exit 1
+fi
+$HOME/src/lsof4/support/GenericDistrib ns $1
diff --git a/support/NetBSDDistrib b/support/NetBSDDistrib
new file mode 100755
index 0000000..c23abb1
--- /dev/null
+++ b/support/NetBSDDistrib
@@ -0,0 +1,14 @@
+#!/bin/ksh
+#
+# NetBSDDistrib -- make NetBSD distribution of lsof 4.x
+#
+# Usage: NetBSDDistrib [<suffix>]
+#
+#	 <suffix>	optional suffix for identification
+
+if test $# -gt 1
+then
+  echo "Usage: [<suffix>]"
+  exit 1
+fi
+$HOME/src/lsof4/support/GenericDistrib2 netbsd $1
diff --git a/support/OSRDistrib b/support/OSRDistrib
new file mode 100755
index 0000000..16c860c
--- /dev/null
+++ b/support/OSRDistrib
@@ -0,0 +1,15 @@
+#!/bin/ksh
+#
+# OSRDistrib -- make SCO OpenServer distribution of lsof 4.x
+#
+# Usage: OSRDistrib [<suffix>]
+#
+#	 <suffix>	optional suffix for identification
+
+if test $# -gt 1
+then
+  echo "Usage: [<suffix>]"
+  exit 1
+fi
+cd $HOME/src/lsof4/support
+./GenericDistrib osr $1
diff --git a/support/OpenBSDDistrib b/support/OpenBSDDistrib
new file mode 100755
index 0000000..3f124e8
--- /dev/null
+++ b/support/OpenBSDDistrib
@@ -0,0 +1,14 @@
+#!/bin/ksh
+#
+# OpenBSDDistrib -- make OpenBSD distribution of lsof 4.x
+#
+# Usage: OpenBSDDistrib [<suffix>]
+#
+#	 <suffix>	optional suffix for identification
+
+if test $# -gt 1
+then
+  echo "Usage: [<suffix>]"
+  exit 1
+fi
+$HOME/src/lsof4/support/GenericDistrib2 openbsd $1
diff --git a/support/SpecialRdist b/support/SpecialRdist
new file mode 100755
index 0000000..53aa990
--- /dev/null
+++ b/support/SpecialRdist
@@ -0,0 +1,74 @@
+#!/bin/ksh
+#
+# SpecialRdist -- specially rdist lsof 4.x sources to a specified destination
+#
+# Usage: GenericRdist <destination> <dialect> <shell>
+#
+#	 <destination>	destination host
+#
+#	 <dialect>	dialect subdirectory name
+#
+#	 <shell>	remote shell -- rsh or ssh
+
+# Process arguments.
+
+if test $# -ne 3
+then
+  echo "Usage: <destination> <dialect> <shell>"
+  exit
+fi
+H=$1
+D=$2
+S=$3
+
+# Test the shell and define its full path, as required.
+
+if test "X$S" = "Xrsh"
+then
+  SHP=""
+else
+  if test "X$S" = "Xssh"
+  then
+    SHP="-P /opt/openssh/bin/ssh"
+  else
+    echo "$S is not an acceptable shell; specify rsh or ssh."
+    exit
+  fi
+fi
+
+# Define the distfile and make sure it's removed on premature exit.
+
+R=/tmp/distfile.$$
+trap 'rm $R; exit 1' 1 2 3 15
+
+rm -f $R
+echo ". -> $H" > $R
+echo "	except ( ./.ck00MAN );" >> $R
+echo "	except ( ./.neverCust ./.neverInv );" >> $R
+echo "	except ( ./Makefile ./ddev.c ./dfile.c ./dlsof.h ./dmnt.c );" >> $R
+echo "	except ( ./dnode.c ./dnode1.c ./dproc.c ./dproto.h ./dsock.c );" >> $R
+echo "	except ( ./dstore.c ./lib/Makefile ./lib/RCS ./lib/OLD ./lib/NEW );" >> $R
+echo "	except ( ./lsof ./machine.h ./version.h ./zipme );" >> $R
+echo "	except ( ./NEW ./OLD ./RCS ./dialects ./support ) ;" >> $R
+echo "	except ( ./new ./old ./X ./xxx ./errs ) ;" >> $R
+echo "	except ( ./scripts/OLD ./scripts/NEW ./scripts/RCS ) ;" >> $R
+echo "	except ( ./scripts/00MANIFEST ./scripts/00README ) ;" >> $R
+echo "	except ( ./tests/OLD ./tests/NEW ./tests/RCS ) ;" >> $R
+echo "	except ( ./tests/00README ) ;" >> $R
+echo "	except ( ./tests/LTbasic ./tests/LTbigf ./tests/LTdnlc ) ;" >> $R
+echo "	except ( ./tests/LTlock ./tests/LTnfs ./tests/LTnlink ) ;" >> $R
+echo "	except ( ./tests/LTsock ./tests/LTszoff ./tests/LTunix ) ;" >> $R
+echo "	except_pat ( \\\\./tests/config\\\\. );" >> $R
+echo "	except_pat ( \\\\.gz \\\\.o \\\\.a );" >> $R
+echo "	install src/lsof4 ;" >> $R
+echo "" >> $R
+echo "./dialects/$D -> $H" >> $R
+echo "	except ( ./dialects/$D/NEW );" >> $R
+echo "	except ( ./dialects/$D/OLD ./dialects/$D/RCS );" >> $R
+echo "	install src/lsof4/dialects/$D ;" >> $R
+
+# Do the actual distribution.
+
+(cd $HOME/src/lsof4; rdist $SHP -f $R)
+rm $R
+echo done
diff --git a/support/SunDistrib b/support/SunDistrib
new file mode 100755
index 0000000..d569d59
--- /dev/null
+++ b/support/SunDistrib
@@ -0,0 +1,14 @@
+#!/bin/ksh
+#
+# SunDistrib -- make Solaris and SunOS distribution of lsof 4.x
+#
+# Usage: SunDistrib [<suffix>]
+#
+#	 <suffix>	optional suffix for identification
+
+if test $# -gt 1
+then
+  echo "Usage: [<suffix>]"
+  exit 1
+fi
+$HOME/src/lsof4/support/GenericDistrib2 sun $1
diff --git a/support/UWDistrib b/support/UWDistrib
new file mode 100755
index 0000000..3710b7e
--- /dev/null
+++ b/support/UWDistrib
@@ -0,0 +1,15 @@
+#!/bin/ksh
+#
+# UWDistrib -- make SCO UnixWare distribution of lsof 4.x
+#
+# Usage: UWDistrib [<suffix>]
+#
+#	 <suffix>	optional suffix for identification
+
+if test $# -gt 1
+then
+  echo "Usage: [<suffix>]"
+  exit 1
+fi
+cd $HOME/src/lsof4/support
+./GenericDistrib2 uw $1
diff --git a/support/argtest b/support/argtest
new file mode 100755
index 0000000..b84ffff
--- /dev/null
+++ b/support/argtest
@@ -0,0 +1,104 @@
+#!/bin/sh
+#
+# argtest -- test lsof arguments for stack overflows
+#
+# usage: argtest [path_to_lsof]
+#
+#   where:
+#	    path_to_lsof	optional *absolute* path to lsof (default
+#				${HOME}/src/lsof4/lsof)
+
+ARG_A=`pwd`/argtest_a.$$
+ARG_N=`pwd`/argtest_n.$$
+ERR=0
+SH=`pwd`/lsoftest.$$
+SH1=`pwd`/lsoftestc.$$
+T=`pwd`/argtest_tmp.$$
+T1=`pwd`/argtest_tmp1.$$
+trap 'rm -f $ARG_A $ARG_N $SH $SH1 $T $T1; exit 1' 1 2 3 15
+
+# Decide how to use echo.
+
+ECHO=`echo -n ""`
+if test "X$ECHO" = "X-n "
+then
+  EC="\c"
+  EO=""
+else
+  EC=""
+  EO="-n"
+fi
+
+# Establish the lsof path.
+
+if test $# -gt 0
+then
+  LSOF=$1
+else
+  LSOF=${HOME}/src/lsof4/lsof
+fi
+
+# Create temporary files that can be used as very large alphabetic
+# and numeric arguments.
+
+rm -f $ARG_A $T $T1
+echo $EO "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678901$EC" > $T
+cp $T $T1
+for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+do
+  cat $T >> $T1
+done
+cp $T1 $ARG_A
+for i in 1 2 3 4 5 6 7
+do
+  cat $T1 >> $ARG_A
+done
+rm -f $T $T1
+ls -l $ARG_A
+rm -f $ARG_N $T $T1
+echo $EO "0123456789012345678901234567890123456789012345678901234567890123$EC" > $T
+cp $T $T1
+for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+do
+  cat $T >> $T1
+done
+cp $T1 $ARG_N
+for i in 1 2 3 4 5 6 7
+do
+  cat $T1 >> $ARG_N
+done
+rm -f $T $T1
+ls -l $ARG_N
+
+# Create a temporary shell script to execute lsof with options that require
+# arguments, and use the contents of $ARG_A and $ARG_N as the arguments.
+
+rm -f $SH $SH1
+echo "#!/bin/sh" > $SH
+echo "#!/bin/sh" > $SH1
+echo "$LSOF \$1 \`cat $ARG_A\`" >> $SH
+echo "$LSOF -c/\`cat $ARG_A\`/" >> $SH1
+echo "$LSOF \$1 \`cat $ARG_N\`" >> $SH
+echo "$LSOF -c/\`cat $ARG_N\`/" >> $SH1
+chmod +x $SH $SH1
+ls -l $SH $SH1
+
+for a in -A -c -c/ +c +d +D -e +e -f +f -F -g -i -i4 -i6 -i@ -i: -k +L -m +m -p -s -stcp: -sudp: -T -u -x -z -Z
+do
+  echo $EO "Testing: $a ... $EC"
+  if test "X$a" = "X-c/"
+  then
+    $SH1 2>&1 | egrep "Memory fault|Segmentation fault|Bus Error" > /dev/null 2>&1
+  else
+    $SH $a 2>&1 | egrep "Memory fault|Segmentation fault|Bus Error" > /dev/null 2>&1
+  fi
+  if test $? -eq 0
+  then
+    echo "!!!!FAILED!!!!"
+    ERR=1
+  else
+   echo "OK"
+  fi
+done
+rm -f $ARG_A $ARG_N $SH $SH1 core
+exit $ERR
diff --git a/support/binaries/README b/support/binaries/README
new file mode 100644
index 0000000..37015e7
--- /dev/null
+++ b/support/binaries/README
@@ -0,0 +1,27 @@
+
+			    Lsof Binaries
+
+I do not recommend that you use a pre-compiled lsof binary and I no
+longer provide any.
+
+It is important that you compile lsof for yourself from the distributed
+sources to allow its Configure script to tailor the binary to your
+system.
+
+    *************************************************************
+    * DON'T TRY TO USE AN LSOF BINARY, COMPILED FOR ONE UNIX OS *
+    * VERSION, ON ANOTHER.                                      *
+    *************************************************************
+
+On some UNIX dialects lsof versions may be even more restricted by
+architecture types.
+
+    *************************************************************
+    * AVOID USING BINARIES FOR LSOF REVISIONS BELOW 4.63.  THEY *
+    * ARE VULNERABLE TO THE STANDARD I/O DESCRIPTOR ATTACK.     *
+    * (See 00FAQ for more information.)                         *
+    *************************************************************
+
+
+Vic Abell
+April 15, 2008
diff --git a/support/contrib.00INDEX b/support/contrib.00INDEX
new file mode 100644
index 0000000..89ab9e7
--- /dev/null
+++ b/support/contrib.00INDEX
@@ -0,0 +1,22 @@
+
+	Index of Files in pub/tools/unix/lsof/contrib
+
+
+00INDEX			is this file.
+
+BSDI-1.1                contains information on a BSDI BSD/386 1.1
+			port to lsof 3.25 from Bob Thrush
+			<rd@tarpit.oau.org>.
+
+NCR                     a directory containing a complete distribution
+			of lsof 3.88 for NCR System Vr4 (3.0) releases
+			2.2.1 and 3.0.0, done by Boyd Roberts
+			<boyd@france3.fr>
+
+RT_PC.BSD4.3            contains information on a RT/PC BSD 4.3
+			port to lsof 3.24 from R. Bernstein
+			<rocky@panix.com>.
+
+
+Vic Abell
+February 20, 1997
diff --git a/support/contrib.README b/support/contrib.README
new file mode 100644
index 0000000..3c6f84e
--- /dev/null
+++ b/support/contrib.README
@@ -0,0 +1,8 @@
+
+		    pub/tools/unix/lsof/contrib
+
+This subdirectory contains user-contributed patches, sources, and
+subdirectories for porting lsof to other Unix dialects.
+
+Vic Abell
+February 20, 1997
diff --git a/support/install-lsof b/support/install-lsof
new file mode 100755
index 0000000..c518f32
--- /dev/null
+++ b/support/install-lsof
@@ -0,0 +1,143 @@
+#!/bin/sh
+#
+# install-lsof <revision> -- install lsof <revision>
+
+DD=/var/ftpd/pub/tools/unix/lsof
+# DEBUG DD=/tmp/lsof	# DEBUG
+SD=$HOME/src/lsof4/support
+
+# Check for version specification.
+
+if test $# -ne 1
+then
+  echo "Usage: install-lsof <version>"
+  exit 1
+fi
+R=$1
+echo $R | grep '^4\.[0-9]*$' > /dev/null 2>&1
+if test $? -ne 0
+then
+  echo "<revision> must be 4.nn"
+  exit 1
+fi
+SR=`echo $R | sed 's/^4\.\([0-9]*\)$/\1/'`
+if test $SR -lt 73
+then
+  echo "Sub-revision must be 73 or greater."
+  exit 1
+fi
+PR=4.`expr $SR - 1`
+PPR=4.`expr $SR - 2`
+
+# Check for the presence of files for the new revision.
+
+err=0
+if test ! -f ${SD}/lsof_${R}.man
+then
+  echo "Creating lsof_${R}.man"
+  (cd $SD; ./makeman) > /dev/null
+fi
+for i in CHECKSUMS_$R ../00FAQ ../00DIST lsof_${R}.man lsof.00INDEX \
+	 lsof.README \
+	 lsof_${R}.tar.bz2 lsof_${R}.tar.bz2.sig \
+	 lsof_${R}.tar.gz lsof_${R}.tar.gz.sig \
+	 lsof_${R}.tar.Z  lsof_${R}.tar.Z.sig 
+do
+  if test ! -f ${SD}/$i
+  then
+    echo "${SD}/$i not found"
+    err=1
+  fi
+done
+
+# Check for the presence of files for the previous revision.
+
+for i in lsof_${PR}.man \
+	 lsof_${PR}.tar.bz2 \
+	 lsof_${PR}.tar.bz2.sig \
+	 lsof_${PR}.tar.gz \
+	 lsof_${PR}.tar.gz.sig \
+	 lsof_${PR}.tar.Z \
+	 lsof_${PR}.tar.Z.sig 
+do
+  if test ! -f ${DD}/$i
+  then
+    echo "${DD}/$i not found"
+    err=1
+  fi
+done
+
+# Quit if there are missing files.
+
+if test $err -ne 0
+then
+  echo "Quitting because of missing files"
+  exit 1
+fi
+
+# Archive previous revision files.
+
+for i in CHECKSUMS_$PR lsof_${PR}.man \
+	 lsof_${PR}.tar.bz2 lsof_${PR}.tar.bz2.sig \
+	 lsof_${PR}.tar.gz  lsof_${PR}.tar.gz.sig  \
+	 lsof_${PR}.tar.Z   lsof_${PR}.tar.Z.sig 
+do
+  if test -f ${DD}/$i
+  then
+    mv ${DD}/$i ${DD}/OLD
+  else
+    echo "No ${DD}/$i to archive"
+  fi
+done
+
+# Remove some previously archived files.  Save the gz archive and signature.
+
+for i in CHECKSUMS_$PPR lsof_${PPR}.man \
+	 lsof_${PPR}.tar.bz2  lsof_${PPR}.tar.bz2.sig  \
+	 lsof_${PPR}.tar.Z   lsof_${PPR}.tar.Z.sig 
+do
+  if test -f ${DD}/OLD/$i
+  then
+    echo "Removing ${DD}/OLD/$i"
+    rm -f ${DD}/OLD/$i
+  fi
+done
+
+# Install new files.
+
+for i in lsof.00INDEX lsof.README 
+do
+  echo "Installing $i"
+  rm -f $DD/$i
+  cp ${SD}/$i $DD
+  chmod 444 $DD/$i
+done
+rm -f ${DD}/00INDEX; mv ${DD}/lsof.00INDEX ${DD}/00INDEX
+rm -f ${DD}/README; mv ${DD}/lsof.README ${DD}/README
+for i in CHECKSUMS_$R lsof_${R}.man \
+	 lsof_${R}.tar.bz2 lsof_${R}.tar.bz2.sig \
+	 lsof_${R}.tar.gz lsof_${R}.tar.gz.sig \
+	 lsof_${R}.tar.Z  lsof_${R}.tar.Z.sig 
+do
+  echo "Installing $i"
+  rm -f $DD/$i
+  mv ${SD}/$i $DD
+  chmod 444 $DD/$i
+done
+(cd $DD; rm -f CHECKSUMS; ln -s CHECKSUMS_$R CHECKSUMS; ls -lL CHECKSUMS)
+(cd $DD; rm -f lsof_man; ln -s lsof_${R}.man lsof_man; ls -lL lsof_man)
+echo "Installing FAQ"
+rm -f ${DD}/FAQ; cp ${SD}/../00FAQ ${DD}/FAQ; chmod 644 ${DD}/FAQ
+rm -f ${DD}/ChangeLog; cp ${SD}/../00DIST ${DD}/ChangeLog; chmod 644 ${DD}/ChangeLog
+for i in bz2 gz Z
+do
+  rm -f ${DD}/lsof.tar.$i ${DD}/lsof.tar.${i}.sig
+  (cd $DD; ln -s lsof_${R}.tar.$i lsof.tar.$i)
+  (cd $DD; ln -s lsof_${R}.tar.${i}.sig lsof.tar.${i}.sig)
+  (cd $DD; ls -lL lsof.tar.$i lsof.tar.${i}.sig)
+done
+
+# Install binaries. (Disabled April 15, 2008.)
+
+#(cd $SD; rdist -f distfile.binaries)
+exit 0
diff --git a/support/install.log b/support/install.log
new file mode 100644
index 0000000..bd6a15e
--- /dev/null
+++ b/support/install.log
@@ -0,0 +1,156 @@
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/CHECKSUMS_4.84
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/lsof_4.84.man
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/lsof_4.84.tar.bz2
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/lsof_4.84.tar.bz2.sig
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/lsof_4.84.tar.Z
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/lsof_4.84.tar.Z.sig
+Installing lsof.00INDEX
+Installing lsof.README
+Installing CHECKSUMS_4.86
+Installing lsof_4.86.man
+Installing lsof_4.86.tar.bz2
+Installing lsof_4.86.tar.bz2.sig
+Installing lsof_4.86.tar.gz
+Installing lsof_4.86.tar.gz.sig
+Installing lsof_4.86.tar.Z
+Installing lsof_4.86.tar.Z.sig
+-r--r--r--   1 abe      pucc        1726 Apr 10 13:06 CHECKSUMS
+-r--r--r--   1 abe      pucc           0 Apr 10 13:01 lsof_man
+Installing FAQ
+-r--r--r--   1 abe      pucc      769231 Apr 10 13:06 lsof.tar.bz2
+-r--r--r--   1 abe      pucc         152 Apr 10 13:06 lsof.tar.bz2.sig
+-r--r--r--   1 abe      pucc     1079288 Apr 10 13:06 lsof.tar.gz
+-r--r--r--   1 abe      pucc         152 Apr 10 13:06 lsof.tar.gz.sig
+-r--r--r--   1 abe      pucc     1630733 Apr 10 13:06 lsof.tar.Z
+-r--r--r--   1 abe      pucc         152 Apr 10 13:06 lsof.tar.Z.sig
+Creating lsof_4.87.man
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/CHECKSUMS_4.85
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/lsof_4.85.man
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/lsof_4.85.tar.bz2
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/lsof_4.85.tar.bz2.sig
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/lsof_4.85.tar.Z
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/lsof_4.85.tar.Z.sig
+Installing lsof.00INDEX
+Installing lsof.README
+Installing CHECKSUMS_4.87
+Installing lsof_4.87.man
+Installing lsof_4.87.tar.bz2
+Installing lsof_4.87.tar.bz2.sig
+Installing lsof_4.87.tar.gz
+Installing lsof_4.87.tar.gz.sig
+Installing lsof_4.87.tar.Z
+Installing lsof_4.87.tar.Z.sig
+-r--r--r--   1 abe      pucc        1726 Jan  2 12:52 CHECKSUMS
+-r--r--r--   1 abe      pucc      151915 Jan  2 12:56 lsof_man
+Installing FAQ
+-r--r--r--   1 abe      pucc      773664 Jan  2 12:52 lsof.tar.bz2
+-r--r--r--   1 abe      pucc         152 Jan  2 12:52 lsof.tar.bz2.sig
+-r--r--r--   1 abe      pucc     1084323 Jan  2 12:52 lsof.tar.gz
+-r--r--r--   1 abe      pucc         152 Jan  2 12:52 lsof.tar.gz.sig
+-r--r--r--   1 abe      pucc     1632799 Jan  2 12:52 lsof.tar.Z
+-r--r--r--   1 abe      pucc         152 Jan  2 12:52 lsof.tar.Z.sig
+Creating lsof_4.88.man
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/CHECKSUMS_4.86
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/lsof_4.86.man
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/lsof_4.86.tar.bz2
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/lsof_4.86.tar.bz2.sig
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/lsof_4.86.tar.Z
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/lsof_4.86.tar.Z.sig
+Installing lsof.00INDEX
+Installing lsof.README
+Installing CHECKSUMS_4.88
+Installing lsof_4.88.man
+Installing lsof_4.88.tar.bz2
+Installing lsof_4.88.tar.bz2.sig
+Installing lsof_4.88.tar.gz
+Installing lsof_4.88.tar.gz.sig
+Installing lsof_4.88.tar.Z
+Installing lsof_4.88.tar.Z.sig
+-r--r--r--   1 abe      pucc        1726 Oct 14 12:04 CHECKSUMS
+-r--r--r--   1 abe      pucc      152630 Oct 14 12:12 lsof_man
+Installing FAQ
+-r--r--r--   1 abe      pucc      778563 Oct 14 12:04 lsof.tar.bz2
+-r--r--r--   1 abe      pucc         152 Oct 14 12:04 lsof.tar.bz2.sig
+-r--r--r--   1 abe      pucc     1090289 Oct 14 12:04 lsof.tar.gz
+-r--r--r--   1 abe      pucc         152 Oct 14 12:04 lsof.tar.gz.sig
+-r--r--r--   1 abe      pucc     1643851 Oct 14 12:04 lsof.tar.Z
+-r--r--r--   1 abe      pucc         152 Oct 14 12:04 lsof.tar.Z.sig
+Creating lsof_4.89.man
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/CHECKSUMS_4.87
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/lsof_4.87.man
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/lsof_4.87.tar.bz2
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/lsof_4.87.tar.bz2.sig
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/lsof_4.87.tar.Z
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/lsof_4.87.tar.Z.sig
+Installing lsof.00INDEX
+Installing lsof.README
+Installing CHECKSUMS_4.89
+Installing lsof_4.89.man
+Installing lsof_4.89.tar.bz2
+Installing lsof_4.89.tar.bz2.sig
+Installing lsof_4.89.tar.gz
+Installing lsof_4.89.tar.gz.sig
+Installing lsof_4.89.tar.Z
+Installing lsof_4.89.tar.Z.sig
+-r--r--r--   1 abe      pucc        1726 Jul 13 10:04 CHECKSUMS
+-r--r--r--   1 abe      pucc      153636 Jul 13 10:05 lsof_man
+Installing FAQ
+-r--r--r--   1 abe      pucc      784560 Jul 13 10:04 lsof.tar.bz2
+-r--r--r--   1 abe      pucc         152 Jul 13 10:04 lsof.tar.bz2.sig
+-r--r--r--   1 abe      pucc     1096819 Jul 13 10:04 lsof.tar.gz
+-r--r--r--   1 abe      pucc         152 Jul 13 10:04 lsof.tar.gz.sig
+-r--r--r--   1 abe      pucc     1649885 Jul 13 10:04 lsof.tar.Z
+-r--r--r--   1 abe      pucc         152 Jul 13 10:04 lsof.tar.Z.sig
+Creating lsof_4.90.man
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/CHECKSUMS_4.88
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/lsof_4.88.man
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/lsof_4.88.tar.bz2
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/lsof_4.88.tar.bz2.sig
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/lsof_4.88.tar.Z
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/lsof_4.88.tar.Z.sig
+Installing lsof.00INDEX
+Installing lsof.README
+Installing CHECKSUMS_4.90
+Installing lsof_4.90.man
+Installing lsof_4.90.tar.bz2
+Installing lsof_4.90.tar.bz2.sig
+Installing lsof_4.90.tar.gz
+Installing lsof_4.90.tar.gz.sig
+Installing lsof_4.90.tar.Z
+Installing lsof_4.90.tar.Z.sig
+-r--r--r--   1 abe      pucc        1726 Feb 14 15:33 CHECKSUMS
+-r--r--r--   1 abe      pucc      155331 Feb 15 13:12 lsof_man
+Installing FAQ
+-r--r--r--   1 abe      pucc      791758 Feb 14 15:32 lsof.tar.bz2
+-r--r--r--   1 abe      pucc         152 Feb 14 15:33 lsof.tar.bz2.sig
+-r--r--r--   1 abe      pucc     1104570 Feb 14 15:32 lsof.tar.gz
+-r--r--r--   1 abe      pucc         152 Feb 14 15:33 lsof.tar.gz.sig
+-r--r--r--   1 abe      pucc     1663473 Feb 14 15:33 lsof.tar.Z
+-r--r--r--   1 abe      pucc         152 Feb 14 15:33 lsof.tar.Z.sig
+sof: 44 = install-lsof 4.91
+Creating lsof_4.91.man
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/CHECKSUMS_4.89
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/lsof_4.89.man
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/lsof_4.89.tar.bz2
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/lsof_4.89.tar.bz2.sig
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/lsof_4.89.tar.Z
+Removing /var/ftpd/pub/tools/unix/lsof/OLD/lsof_4.89.tar.Z.sig
+Installing lsof.00INDEX
+Installing lsof.README
+Installing CHECKSUMS_4.91
+Installing lsof_4.91.man
+Installing lsof_4.91.tar.bz2
+Installing lsof_4.91.tar.bz2.sig
+Installing lsof_4.91.tar.gz
+Installing lsof_4.91.tar.gz.sig
+Installing lsof_4.91.tar.Z
+Installing lsof_4.91.tar.Z.sig
+-r--r--r--   1 abe      pucc        1726 Mar 26 17:56 CHECKSUMS
+-r--r--r--   1 abe      pucc      155331 Mar 26 18:00 lsof_man
+Installing FAQ
+-r--r--r--   1 abe      pucc      791734 Mar 26 17:56 lsof.tar.bz2
+-r--r--r--   1 abe      pucc         152 Mar 26 17:56 lsof.tar.bz2.sig
+-r--r--r--   1 abe      pucc     1104767 Mar 26 17:56 lsof.tar.gz
+-r--r--r--   1 abe      pucc         152 Mar 26 17:56 lsof.tar.gz.sig
+-r--r--r--   1 abe      pucc     1658305 Mar 26 17:56 lsof.tar.Z
+-r--r--r--   1 abe      pucc         152 Mar 26 17:56 lsof.tar.Z.sig
diff --git a/support/look_rlog b/support/look_rlog
new file mode 100755
index 0000000..d1f8653
--- /dev/null
+++ b/support/look_rlog
@@ -0,0 +1,21 @@
+#!/bin/ksh
+#
+# look_rlog
+#set -v			# for DEBUGging
+
+if test $# -ne 2
+then
+  echo "$0 usage: file highest-revision"
+  exit 1
+fi
+if test ! -r RCS/${1},v
+then
+  echo "$0: no RCS/${1},v"
+  exit 1
+fi
+r=$2
+while test $r -gt 0
+do
+  (echo 1.$r; co -p1.$r $1) | less
+  r=`expr $r - 1`
+done
diff --git a/support/lsof-log.xls b/support/lsof-log.xls
new file mode 100644
index 0000000..e69de29
diff --git a/support/lsof.00INDEX b/support/lsof.00INDEX
new file mode 100644
index 0000000..7d1fe7e
--- /dev/null
+++ b/support/lsof.00INDEX
@@ -0,0 +1,128 @@
+
+	Index of Files and Directories in pub/tools/unix/lsof
+
+
+00INDEX			is this file.
+
+00LSOF-L		contains information on the lsof-l LISTSERV
+			mailing list for lsof.
+
+ChangeLog		contains information about changes to lsof, also
+			found in the 00DIST distribution notes file of
+			the lsof distribution.
+
+CHECKSUMS		contains information on external checksums for
+			the current lsof distribution files.
+
+FAQ			is the lsof FAQ, also found in the file 00FAQ
+			of the lsof distribution.
+
+			NOTE: this file is as current as possible.
+			Therefore it may contain information that
+			applies to an upcoming revision.  When in
+			doubt, send email to <abe@purdue.edu>.
+
+NEW/			is a directory that may sometimes contain
+			new information -- usually bzip2'd or gzip'd
+			tar files for ports to specific dialects that
+			are under development.  Please don't get
+			anything from this directory without contacting
+			me first.
+
+OLD/			is a directory that contains OLD lsof
+			distribution files.
+
+README			contains information on the lsof distribution.
+			This file is included in the lsof distribution
+			tar files, lsof.tar.bz2, lsof.tar.gz and
+			lsof.tar.Z.
+
+Victor_A_Abell.gpg      contains the GnuPG 5.0 public key for Victor
+			A. Abell (abe@purdue.edu).
+
+			MAY BE USED TO AUTHENTICATE THE LSOF
+			DISTRIBUTION AND BINARY FILES.
+
+Victor_A_Abell.pgp      contains the PGP 2.62 public key for Victor A.
+			Abell (abe@purdue.edu).
+
+			MAY BE USED TO AUTHENTICATE THE LSOF
+			DISTRIBUTION AND BINARY FILES.
+
+binaries/		is a directory tree that contains selected
+			lsof executables, not always for the latest
+			source distribution.  I strongly recommend
+			you avoid using one of these binaries and
+			build your own instead.
+
+contrib/		is a directory of user-contributed information
+			on porting lsof to other Unix dialects.
+
+lsof_man		is a symbolic link to the man page for the
+			current lsof revision.  This file is included
+			in the lsof distribution tar files,
+			lsof.tar.bz2, lsof.tar.gz and lsof.tar.Z.
+
+lsof.tar.bz2		is a symbolic link to the bzip2'd lsof
+			distribution tar archive for the latest
+			revision of lsof.  Consult the README file
+			in this directory for information on its
+			contents.
+
+lsof.tar.bz2.sig	is a symbolic link to the GPG authentication
+			certificate for lsof.tar.bz2.
+
+lsof.tar.gz		is a symbolic link to the gzip'd lsof
+			distribution tar archive for the latest
+			revision of lsof.  Consult the README file
+			in this directory for information on its
+			contents.
+
+lsof.tar.gz.sig		is a symbolic link to the GPG authentication
+			certificate for lsof.tar.gz.
+
+lsof.tar.Z		is a symbolic link to the compressed lsof
+			distribution tar archive for the latest
+			revision of lsof.  Consult the README file
+			in this directory for information on its
+			contents.
+
+lsof.tar.Z.sig		is a symbolic link to the GPG authentication
+			certificate for lsof.tar.Z.
+
+lsof_4.92.man		is the man page for the current lsof
+			distribution.
+
+lsof_4.92.tar.bz2	is the current bzip2'd lsof distribution.
+			Consult the README file in this directory for
+			information on its contents.
+
+lsof_4.92.tar.bz2.sig	is the GPG authentication certificate for
+			lsof_4.92.tar.bz2.
+
+lsof_4.92.tar.gz	is the current gzip'd lsof distribution.
+			Consult the README file in this directory for
+			information on its contents.
+
+lsof_4.92.tar.gz.sig	is the GPG authentication certificate for
+			lsof_4.92.tar.gz.
+
+lsof_4.92.tar.Z		is the current compressed lsof distribution.
+			Consult the README file in this directory for
+			information on its contents.
+
+lsof_4.92.tar.Z.sig	is the GPG authentication certificate for
+			lsof_4.92.tar.Z.
+
+mirrors			is a list of ftp sites where lsof is mirrored.
+
+patches/		contains lsof patches.
+
+solaris_kaddr_filters   contains a discussion of the Solaris kernel
+			address filters installed in lsof 4.50 and
+			above.  This file may also be found in
+			lsof_4.92/dialects/sun.
+
+
+Vic Abell <abe@purdue.edu>
+July 14, 2018
diff --git a/support/lsof.README b/support/lsof.README
new file mode 100644
index 0000000..411a372
--- /dev/null
+++ b/support/lsof.README
@@ -0,0 +1,326 @@
+		    lsof (LiSt Open Files) version 4
+			    (revision 4.92)
+
+
+    ********************************************************************
+    | The latest release of lsof is always available via anonymous ftp |
+    | from lsof.itap.purdue.edu.  Look in pub/tools/unix/lsof.         |
+    ********************************************************************
+
+******************************************************************************
+| CHECK THE PATCHES/ SUBDIRECTORY FOR FIXES TO THE LATEST LSOF DISTRIBUTION. |
+******************************************************************************
+
+ **************************************************************************
+ | AVOID USING PRE-BUILT LSOF BINARIES: SEE THE "PRE-BUILT LSOF BINARIES" |
+ |                 SECTION IN 00README FOR AN EXPLANATION.                |
+ **************************************************************************
+
+   **********************************************************************
+   | READ 00LSOF-L FOR INFORMATION ON THE LSOF-L LISTSERV MAILING LIST. |
+   **********************************************************************
+
+    *********************************************************************
+    |      CHECK 00FAQ BEFORE REPORTING BUGS TO <abe@purdue.edu>.       |
+    | 00FAQ ALSO AT: ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/FAQ |
+    *********************************************************************
+
+    ********************************************************************
+    | IMPORTANT!  This README file explains how the lsof tar archive   |
+    | is assembled -- it's a "wrapper" tar archive.  Please read the   |
+    | explanation of its naming and construction, immediately          |
+    | following the initial list of supported dialects.                |
+    ********************************************************************
+
+
+Lsof version 4 lists open files for running UNIX processes.  It is a
+descendent of ofiles, fstat, and lsof versions 1, 2, and 3.  It has
+been tested recently on these UNIX dialects.
+
+	Apple Darwin 9 and Mac OS X 10.[567]
+	FreeBSD 8.[234], 9.0 and 1[012].0 for AMD64-based systems
+	Linux 2.1.72 and above for x86-based systems
+	Solaris 9, 10 and 11
+
+Lsof 4 may work on other versions of these dialects, but hasn't been
+tested there recently.  Lsof versions 2 and 3 are still available and
+may provide older dialect version support.  See the notes on them in
+this file.
+
+The pub/tools/unix/lsof/contrib directory on lsof.itap.purdue.edu also
+contains information on other ports.
+
+Version 4 of lsof is distributed as bzip2'd, gzip'd and compressed tar
+archives in the files:
+
+    ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/lsof.tar.bz2
+  and
+    ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/lsof.tar.gz
+  and
+    ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/lsof.tar.Z
+
+These files are links to the current distribution, whose name includes
+the revision number:
+
+    ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof_<rev>.tar.bz2
+  and
+    ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof_<rev>.tar.gz
+  and
+    ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof_<rev>.tar.Z
+
+<rev> is the revision number -- e.g., 4.92.  These archives are called
+wrappers, because the lsof source tar archive, its GPG certificate
+(lsof_<rev>_src.tar.sig), and some documentation files are wrapped
+together inside them.  (The GPG certificate authenticates the source
+tar archive.)  A tar archive with: a ``.bz2'' suffix has been
+compressed with bzip2; ``.gz'', with gzip; and ``.Z'', with compress.
+
+When the wrapper tar is gunzip'd or uncompressed, and its tar archive
+contents are extracted, an lsof_4.92 subdirectory is created in the
+directory where the extraction was performed.  The lsof_4.92
+subdirectory contains these files:
+
+	00.README.FIRST		contains introductory distribution
+				information.
+
+	README.lsof_4.92	contains instructions for the
+				security-conscious on how to be
+				sure that no one has tampered with
+				the distribution.
+
+	RELEASE_SUMMARY_4.92	is this file.
+
+	lsof_4.92_src.tar       is a tar archive, containing the
+				lsof sources.  When extracted with
+				tar it creates a subdirectory named
+				lsof_4.92_src in the directory
+				where the extraction was performed.
+				The lsof source files will be found
+				in lsof_4.92_src.
+
+	lsof_4.92_src.tar.sig   is a GPG certificate, authenticating
+				the lsof_4.92_src.tar archive.  See the
+				README.lsof_4.92 file for more
+				information on GPG authentication of
+				lsof_4.92_src.tar.
+
+If you've obtained this file and an lsof distribution from a mirror
+site, please be aware that THE LATEST VERSION OF LSOF IS AVAILABLE VIA
+ANONYMOUS FTP FROM LSOF.ITAP.PURDUE.EDU IN THE PUB/TOOLS/UNIX/LSOF
+DIRECTORY.
+
+Patches to lsof distributions may be found in the patches/ sub-
+directory where you found lsof.tar.bz2, lsof.tar.gz or lsof.tar.Z.
+If there are any patches to the current distribution, they will be
+found in the patches/4.92/ branch.
+
+(If you need a copy of gunzip, look for it at prep.ai.mit.edu in
+pub/gnu/gzip*.)
+
+The March 26, 2018 revision (4.91): corrects a bug in the processing of Linux
+  PTY endpoint information.
+
+The June 6, 2018 revision (4.92:) is a FreeBSD-only revision; it corrects a bug
+  in the Configure script section that creates a local lockf_owner.h header
+  file; removes a <string,h> kernel header conflicts.
+
+Read the 00.README.FIRST in the lsof distribution first.
+
+Read the 00DIST distribution file for more details on feature additions
+and bug fixes.
+
+The 00README distribution file has build instructions, dialect
+descriptions, special feature discussions, and installation hints.
+
+The 00FAQ file contains a list of frequently asked questions and their
+answers.
+
+The 00DCACHE file explains device cache file path formation.
+
+The 00PORTING file contains information on porting lsof to other UNIX
+dialects.
+
+The 00QUICKSTART file gives a quick introduction to using lsof.
+
+The distribution files lsof.8 (nroff source) and lsof.man (nroff
+formatted output) contain the manual page for lsof; it is the only
+other documentation besides the source code (it's included).
+
+
+Version 4 Binaries
+==================
+
+Version 4 binaries for some revisions, dialects, and platforms may be
+found in pub/tools/unix/lsof/binaries.  Check the README files for
+exact descriptions.  Check the dialect-specific Makefiles for
+installation instructions.  CHECKSUMS and GPG certificates are provided
+for authentication.
+
+Please think very carefully before you decide to use a pre-built binary
+instead of making your own from the sources.  Here are some points to
+consider:
+
+1. Lsof must run setgid or setuid.  Are you willing to trust that
+   power to a binary you didn't construct yourself?
+
+2. Lsof binaries may be generated on a system whose configuration
+   header files differ from yours.  Under Digital UNIX (DEC OSF/1), for
+   example, lsof includes header files from the machine's configuration
+   directory, /sys/<name>.  Are you willing to gamble that your
+   configuration directory's header files match the ones used to
+   compile lsof?
+
+3. Lsof is often configured with specific options that are determined
+   from the configuration of the system on which it is configured --
+   e.g., Solaris patch level, dynamic loader libraries, etc.  Are you
+   sure that the lsof binary you retrieve will have been configured for
+   your system? If you get a binary that is misconfigured for you, it
+   may not work at all.
+
+If you haven't already guessed, I believe firmly that you should
+retrieve sources and build your own binary.  If you still want to use
+the distribution binaries, please authenticate what you retrieved with
+the GPG certificates; please compare checksums, too.
+
+
+Version 4 Checksums
+===================
+
+Security checksums -- both MD5 and sum(1) -- for revisions of lsof
+version 4 are contained in the README.lsof_<rev> files in the wrapper
+tar archives of pub/tools/unix/lsof.
+
+The CHECKSUMS file, found with the distribution archives, contains
+information on validating the archives with external MD5 checksums and
+external GPG certificates.
+
+
+GPG Certificates
+================
+
+The lsof wrapper tar archive includes a GPG certificate file in its
+contained lsof_4.71_src.tar.sig file.
+
+Binary files have detached GPG certificates that may be found in their
+directories with ".sig" extensions.
+
+The certificates are signed with my GPG public key, which may be found
+in the file:
+
+    ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/Victor_A_Abell.gpg
+
+My key may also be available at some public key servers,
+
+There is also authentication information in the CHECKSUMS file (a link
+to CHECKSUMS_<rev>), found with the lsof distribution files.  CHECKSUMS
+contains external MD5 checksums for the distribution files and
+information on using the external GPG certificates, found with the lsof
+distribution files.
+
+
+Old Dialect Support
+===================
+
+Remnants of source code and binaries for dialects for which lsof once
+provided support may be obtained by request.  Send the request to
+abe@purdue.edu.
+
+Dialects no longer supported include:
+
+	CDC EP/IX
+	MIPS RISC/os
+	Motorola V/88
+	Pyramid DC/OSx
+	Pyramid Reliant UNIX
+	Sequent DYNIX
+	SGI IRIX
+	SunOS 4.1.x
+	Ultrix
+
+Generally I drop support for a dialect when I no longer have access to
+a test system.
+
+
+Lsof Version 2
+==============
+
+The version 3 predecessor, revision 36 of version 2, is also available
+upon request.  Send the request to abe@purdue.edu.
+
+I recommend you avoid lsof version 2.  It's out of date and I no
+longer provide support for it.  (Versions 3 and 4 support more
+dialects, and have many enhancements, bug fixes, and improvements.)
+Version 2 was tested on the following UNIX dialects:
+
+	AIX 3.2.[1234] for the IBM RISC/System 6000
+	DEC OSF/1 1.[23] and 2.0 for the DEC Alpha
+	EP/IX 1.4.3 and 2.1.1 for the CDC 4680
+	ETAV 1.17 for the ETA-10P*
+	FreeBSD 1.0e for x86-based systems
+	HP-UX [789].x for HP systems
+	IRIX 4.0.5 and 5.1.1 for SGI systems
+	NEXTSTEP 2.1, 3.0, 3.1 for NeXT systems
+	Sequent Dynix 3.0.12 for Sequent Symmetry systems
+	SunOS 4.1.[123] for Sun 3 and 4 systems
+	SunOS 5.[13] (Solaris 2.[13]) for Sun 4 systems
+	Ultrix 2.2 and 4.2 for DEC systems
+
+(If you need a copy of gunzip, look for it at prep.ai.mit.edu in
+pub/gnu.)
+
+
+Version 2 Checksums
+===================
+
+MD5:
+	(OLD/lsof236tar.gz) = f8a1ab3971ea2f6a3ea16752f84409e8
+
+sum(1):
+	39996   106 OLD/lsof236tar.gz
+
+The file OLD/lsof236tar.gz.asc is a detached PGP certificate that may
+be used to authenticate OLD/lsof236tar.gz with my PGP public key.  You
+may find my PGP public key at:
+
+  ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/OLD/Victor_A_Abell.pgp
+    
+
+Lsof Version 3
+==============
+
+The last revision of lsof version 3, 3.88, may obtained by request.
+Send the request to abe@purdue.edu.
+
+I recommend version 4 over version 3.  It is the version I actively
+support.
+
+Lsof version 3 was tested on these UNIX dialects:
+
+	AIX 3.2.5, 4.1[.[1234]], and 4.2
+	BSDI BSD/OS 2.0, 2.0.1, and 2.1 for x86-based systems
+	DC/OSx 1.1 for Pyramid systems
+	Digital UNIX (DEC OSF/1) 2.0, 3.0, 3.2, and 4.0
+	EP/IX 2.1.1 for the CDC 4680
+	FreeBSD 1.1.5.1, 2.0, 2.0.5, 2.1, 2.1.5 for x86-based
+	    systems
+	HP-UX 8.x, 9.x, 10.01, 10.10, and 10.20
+	IRIX 5.2, 5.3, 6.0, 6.0.1, and 6.[124]
+	Linux 2.0.3[01] and 2.1.57 for x86-based systems
+	NetBSD 1.0, 1.1, and 1.2 for x86 and SPARC-based
+	    systems
+	NEXTSTEP 2.1 and 3.[0123] for NEXTSTEP architectures
+	OpenBSD 1.2 and 2.0 for x86-based systems
+	Reliant UNIX 5.43 for Pyramid systems
+	RISC/os 4.52 for MIPS R2000-based systems
+	SCO OpenServer 1.1, 3.0, and 5.0.[024] for x86-based 
+	    systems
+	SCO UnixWare 2.1 and 2.1.1 for x86-based systems
+	Sequent PTX 2.1.[1569], 4.0.[23], 4.1.[024], 4.2[.1],
+	    and 4.3
+	Solaris 2.[12345], 2.5.1, and 2.6-Beta
+	SunOS 4.1.x
+	Ultrix 4.2, 4.3, 4.4, and 4.5
+
+
+Vic Abell <abe@purdue.edu>
+July 14, 2018
diff --git a/support/makeman b/support/makeman
new file mode 100755
index 0000000..d330abb
--- /dev/null
+++ b/support/makeman
@@ -0,0 +1,46 @@
+#!/bin/ksh
+#
+# makman -- make lsof 4.x man page for ftp tree
+
+SD=${HOME}/src/lsof4
+cd $SD
+
+# Get version number.
+
+V=`sed '/VN/s/.ds VN \(.*\)/\1/' version`
+if test $? -ne 0
+then
+  echo $V
+  exit 1
+fi
+
+# Handle optional edition suffix.
+
+if test $# -gt 0
+then
+  if test $# -gt 1
+  then
+    echo "Usage: makeman [edition]"
+    exit 1
+  fi
+  V=${V}$1
+fi
+
+# Define man file names.
+
+MS=Lsof.8
+MD=${SD}/support/lsof.8
+MF=${SD}/support/lsof_${V}.man
+
+# Set exit cleanup trap.
+
+trap 'rm -rf $MD $MF; exit' 1 2 3 15
+
+# Create manual page files.
+
+echo Producing $MD
+soelim < $MS > $MD
+echo Producing $MF
+nroff -man $MD | colcrt - | cat -s > $MF
+rm -f $MD
+ls -l $MF
diff --git a/support/mentor b/support/mentor
new file mode 100755
index 0000000..3c8b155
--- /dev/null
+++ b/support/mentor
@@ -0,0 +1,5 @@
+#!/bin/ksh
+#
+# mentor - rdist Sun sources to mentor.cc
+
+$HOME/src/lsof4/support/GenericRdist mentor sun ssh
diff --git a/support/mirrors b/support/mirrors
new file mode 100644
index 0000000..4821f6f
--- /dev/null
+++ b/support/mirrors
@@ -0,0 +1,9 @@
+Lsof is available via anonymous ftp from these mirror hosts.
+
+ 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/
+
+
+WANT YOUR LSOF MIRROR LISTED HERE?  SEND E-MAIL TO <abe@purdue.edu>.
diff --git a/support/rdist.distrib b/support/rdist.distrib
new file mode 100755
index 0000000..5afd538
--- /dev/null
+++ b/support/rdist.distrib
@@ -0,0 +1,10 @@
+#!/bin/sh
+#
+# rdist.distrib - distribute lsof via rdist
+
+cd $HOME/src/lsof4
+for i in cloud mentor
+do
+        echo "::::: " $i " :::::"
+	support/$i
+done
diff --git a/tests/00README b/tests/00README
new file mode 100644
index 0000000..eee8e4d
--- /dev/null
+++ b/tests/00README
@@ -0,0 +1,102 @@
+
+		.../lsof_<version>/tests
+
+This sub-directory contains support for lsof's test suite.  Find
+more information about the test suite in the 00TESTS file of the
+lsof distribution, which should be in in the parent of this
+subdirectory.
+
+These tests can be activated from .. with:
+
+    $ make test
+
+They can be activated from this directory with:
+
+    $ make
+    $ make test
+    $ make all
+
+These tests are all written in C, so individual tests may be
+activated by executing them directly -- e.g.,
+
+    $ ./LTlock
+
+It may sometimes be necessary to use execution-time options
+alter test behavior.  (Some tests will suggest that when they
+encounter certain kinds of errors.)  See the 00FAQ and 00TEST files
+in .. for more information.
+
+These tests check lsof field output, not lsof text output.  There
+are no tests for lsof text output.
+
+Here is a brief description of the files in this subdirectory:
+
+    00README		this file
+
+    Add2TestDB          a script to add the identity of the current
+			test to TestDB
+
+    CkTestDB		a script to check the identity of this
+			dialect against the TestDB file
+
+    config.cc           a file prepared by ../Configure that contains
+			the name (and possibly the path) to the C
+			compiler for the programs of this sub-directory
+
+    config.cflags       a file prepared by ../Configure that contains
+			C compiler flags for the programs of this
+			sub-directory
+
+    config.libs		a file prepared by ../Configure that contains
+			library load specifications -- i.e, make(1)
+			LDFLAGS
+
+    config.xobj         a file prepared by ../Configure that contains
+			paths to any extra object files (*.o) needed
+			by the C programs in this directory
+
+    LsofTest.h		lsof test definitions for C programs
+
+    LTbasic.c		C source to basic lsof tests
+
+    LTbigf.c		C source to a program that tests large file
+			sizes and offsets on dialects that support
+			file sizes > 32 bits
+
+    LTdnlc.c            C source to a program that tests the
+			effectiveness of assembling path names from
+			the kernel's Dynamic Name Lookup Cache
+			(DNLC)
+
+    LTlib.c		a support library in C
+
+    LTlock.c		C source to a program that tests lock reporting
+
+    LTnfs		C source to a program that tests for open NFS
+			files
+
+    LTnlink.c           C source to a program that tests lsof's
+			reporting of open file link counts
+
+    LTsock.c            C source to program that tests the finding
+			of IPv4 sockets
+
+    LTszoff.c           C source to a program that tests file sizes
+			and offsets  -- see LTbigf.c for a large
+			file (size > 32 bits) test
+
+    LTunix.c		C source to a program that tests the finding
+			of UNIX domain sockets
+
+    Makefile		the make(1) control file
+
+			The Makefile clean rule will not remove
+			config.* files, but the spotless rule will.
+			One the spotless rule has been used,
+			../Configure must be re-run.
+
+    TestDB              a data base of dialects where the test
+			suite has been validated
+
+Vic Abell
+April 11, 2002
diff --git a/tests/LTbasic.c b/tests/LTbasic.c
index 5dbdc7d..3db186b 100644
--- a/tests/LTbasic.c
+++ b/tests/LTbasic.c
@@ -8,7 +8,6 @@
  * Purdue University
  */
 
-
 /*
  * Copyright 2002 Purdue Research Foundation, West Lafayette, Indiana
  * 47907.  All rights reserved.
@@ -35,411 +34,383 @@
  * 4. This notice may not be removed or altered.
  */
 
-#ifndef lint
-static char copyright[] =
-"@(#) Copyright 2002 Purdue Research Foundation.\nAll rights reserved.\n";
-#endif
-
 #include "LsofTest.h"
 #include "lsof_fields.h"
 
-
 /*
  * Local definitions
  */
 
-
 /*
  * Globals
  */
 
-char *Pn = (char *)NULL;	/* program name */
-
+char *Pn = (char *)NULL; /* program name */
 
 /*
  * Local function prototypes
  */
 
-_PROTOTYPE(static void cleanup,(void));
-_PROTOTYPE(static char *tstlsof,(char **texec, char **tkmem, char **tproc));
-
+static void cleanup(void);
+static char *tstlsof(char **texec, char **tkmem, char **tproc);
 
 /*
  * Main program for dialects that support locking tests.
  */
 
-int
-main(argc, argv)
-    int argc;				/* argument count */
-    char *argv[];			/* arguments */
+int main(int argc,     /* argument count */
+         char *argv[]) /* arguments */
 {
-    char buf[2048];			/* temporary buffer */
-    char *em;				/* error message pointer */
-    char *texec = (char *)NULL;		/* lsof executable test result */
-    char *tkmem = (char *)NULL;		/* /dev/kmem test result */
-    char *tproc = (char *)NULL;		/* lsof process test result */
-    int xv = 0;				/* exit value */
-/*
- * Get program name and PID, issue start message, and build space prefix.
- */
+    char buf[2048];             /* temporary buffer */
+    char *em;                   /* error message pointer */
+    char *texec = (char *)NULL; /* lsof executable test result */
+    char *tkmem = (char *)NULL; /* /dev/kmem test result */
+    char *tproc = (char *)NULL; /* lsof process test result */
+    int xv = 0;                 /* exit value */
+                                /*
+                                 * Get program name and PID, issue start message, and build space prefix.
+                                 */
     if ((Pn = strrchr(argv[0], '/')))
-	Pn++;
+        Pn++;
     else
-	Pn = argv[0];
-    (void) printf("%s ... ", Pn);
-    (void) fflush(stdout);
+        Pn = argv[0];
+    (void)printf("%s ... ", Pn);
+    (void)fflush(stdout);
     PrtMsg((char *)NULL, Pn);
-/*
- * Process arguments.
- */
+    /*
+     * Process arguments.
+     */
     if (ScanArg(argc, argv, "h", Pn))
-	xv = 1;
+        xv = 1;
     if (xv || LTopt_h) {
-	(void) PrtMsg("usage: [-h]", Pn);
-	PrtMsgX      ("       -h       print help (this panel)", Pn, cleanup,
-		      xv);
+        (void)PrtMsg("usage: [-h]", Pn);
+        PrtMsgX("       -h       print help (this panel)", Pn, cleanup, xv);
     }
-/*
- * See if lsof can be executed and can access kernel memory.
- */
+    /*
+     * See if lsof can be executed and can access kernel memory.
+     */
     if ((em = IsLsofExec()))
-	(void) PrtMsgX(em, Pn, cleanup, 1);
+        (void)PrtMsgX(em, Pn, cleanup, 1);
     if ((em = CanRdKmem()))
-	(void) PrtMsgX(em, Pn, cleanup, 1);
-/*
- * Test lsof.
- */
+        (void)PrtMsgX(em, Pn, cleanup, 1);
+    /*
+     * Test lsof.
+     */
     if ((em = tstlsof(&texec, &tkmem, &tproc)))
-	PrtMsg(em, Pn);
+        PrtMsg(em, Pn);
     if (texec)
-	PrtMsg(texec, Pn);
+        PrtMsg(texec, Pn);
     if (tkmem)
-	PrtMsg(tkmem, Pn);
+        PrtMsg(tkmem, Pn);
     if (tproc)
-	PrtMsg(tproc, Pn);
-/*
- * Compute exit value and exit.
- */
+        PrtMsg(tproc, Pn);
+    /*
+     * Compute exit value and exit.
+     */
     if (em || texec || tkmem || tproc) {
-	if (strcmp(LT_DEF_LSOF_PATH, LsofPath)) {
-	    PrtMsg (" ", Pn);
-	    PrtMsg ("Hint: you used the LT_LSOF_PATH environment variable to",
-		Pn);
-	    PrtMsg ("  specify this path to the lsof executable:\n", Pn);
-	    (void) snprintf(buf, sizeof(buf) - 1, "      %s\n", LsofPath);
-	    buf[sizeof(buf) - 1] = '\0';
-	    PrtMsg (buf, Pn);
-	    PrtMsgX("  Make sure its revision is 4.63 or higher.",
-		Pn, cleanup, 1);
-	} else
-	    PrtMsgX("", Pn, cleanup, 1);
+        if (strcmp(LT_DEF_LSOF_PATH, LsofPath)) {
+            PrtMsg(" ", Pn);
+            PrtMsg("Hint: you used the LT_LSOF_PATH environment variable to",
+                   Pn);
+            PrtMsg("  specify this path to the lsof executable:\n", Pn);
+            (void)snprintf(buf, sizeof(buf) - 1, "      %s\n", LsofPath);
+            buf[sizeof(buf) - 1] = '\0';
+            PrtMsg(buf, Pn);
+            PrtMsgX("  Make sure its revision is 4.63 or higher.", Pn, cleanup,
+                    1);
+        } else
+            PrtMsgX("", Pn, cleanup, 1);
     }
-    (void) PrtMsgX("OK", Pn, cleanup, 0);
-    return(0);
+    (void)PrtMsgX("OK", Pn, cleanup, 0);
+    return (0);
 }
 
-
 /*
  * cleanup() -- release resources
  */
 
-static void
-cleanup()
-{
-}
-
+static void cleanup() {}
 
 /*
  * tstlsof() -- test for the lsof process
  */
 
-static char *
-tstlsof(texec, tkmem, tproc)
-    char **texec;			/* result of the executable test */
-    char **tkmem;			/* result of the /dev/kmem test */
-    char **tproc;			/* result of the lsof process test */
+static char *tstlsof(char **texec, /* result of the executable test */
+                     char **tkmem, /* result of the /dev/kmem test */
+                     char **tproc) /* result of the lsof process test */
 {
-    char buf[2048];			/* temporary buffer */
-    char *cem;				/* current error message pointer */
-    LTfldo_t *cmdp;			/* command pointer */
-    LTdev_t cwddc;			/* CWD device components */
-    struct stat cwdsb;			/* CWD stat(2) buffer */
-    LTfldo_t *devp;			/* device pointer */
-    int execs = 0;			/* executable status */
-    int fdn;				/* FD is a number */
-    LTfldo_t *fdp;			/* file descriptor pointer */
-    LTfldo_t *fop;			/* field output pointer */
-    char ibuf[64];			/* inode string buffer */
-    LTfldo_t *inop;			/* inode number pointer */
-    LTdev_t kmemdc;			/* /dev/kmem device components */
-    int kmems = 0;			/* kmem status */
-    struct stat kmemsb;			/* /dev/kmem stat(2) buffer */
-    LTdev_t lsofdc;			/* lsof device components */
-    struct stat lsofsb;			/* lsof stat(2) buffer */
-    int nf;				/* number of fields */
-    char *opv[4];			/* option vector for ExecLsof() */
-    char *pem = (char *)NULL;		/* previous error message */
-    pid_t pid;				/* PID */
-    int pids = 0;			/* PID found status */
-    int procs = 0;			/* process status */
-    LTfldo_t *rdevp;			/* raw device pointer */
-    char *tcp;				/* temporary character pointer */
-    int ti;				/* temporary integer */
-    LTdev_t tmpdc;			/* temporary device components */
-    LTfldo_t *typ;			/* file type pointer */
-    int xwhile;				/* exit while() flag */
-
-/*
- * Get lsof executable's stat(2) information.
- */
-    if (stat(LsofPath, &lsofsb)) {
-	(void) snprintf(buf, sizeof(buf) - 1, "ERROR!!!  stat(%s): %s",
-	    LsofPath, strerror(errno));
-	buf[sizeof(buf) - 1] = '\0';
-	cem = MkStrCpy(buf, &ti);
-	if (pem)
-	    (void) PrtMsg(pem, Pn);
-	pem = cem;
-	execs = 1;
+    char buf[2048];           /* temporary buffer */
+    char buf2[2048] = {};     /* temporary buffer */
+    char *cem;                /* current error message pointer */
+    LTfldo_t *cmdp;           /* command pointer */
+    LTdev_t cwddc;            /* CWD device components */
+    struct stat cwdsb;        /* CWD stat(2) buffer */
+    LTfldo_t *devp;           /* device pointer */
+    int execs = 0;            /* executable status */
+    int fdn;                  /* FD is a number */
+    LTfldo_t *fdp;            /* file descriptor pointer */
+    LTfldo_t *fop;            /* field output pointer */
+    char ibuf[64];            /* inode string buffer */
+    LTfldo_t *inop;           /* inode number pointer */
+    LTdev_t kmemdc;           /* /dev/kmem device components */
+    int kmems = 0;            /* kmem status */
+    struct stat kmemsb;       /* /dev/kmem stat(2) buffer */
+    LTdev_t lsofdc;           /* lsof device components */
+    struct stat lsofsb;       /* lsof stat(2) buffer */
+    int nf;                   /* number of fields */
+    char *opv[4];             /* option vector for ExecLsof() */
+    char *pem = (char *)NULL; /* previous error message */
+    pid_t pid;                /* PID */
+    int pids = 0;             /* PID found status */
+    int procs = 0;            /* process status */
+    LTfldo_t *rdevp;          /* raw device pointer */
+    char *tcp;                /* temporary character pointer */
+    int ti;                   /* temporary integer */
+    LTdev_t tmpdc;            /* temporary device components */
+    LTfldo_t *typ;            /* file type pointer */
+    int xwhile;               /* exit while() flag */
+
+    /*
+     * Get lsof executable's stat(2) information.
+     */
+    /* lsof could be a wrapper script when building with libtool, try
+     * ./.libs/lsof first */
+    (void)snprintf(buf, sizeof(buf) - 1, "%s", LsofPath);
+    if (strlen(buf) >= 4) {
+        /* strip lsof suffix */
+        buf[strlen(buf) - 4] = '\0';
+        (void)snprintf(buf2, sizeof(buf2) - 1, "%s.libs/lsof", buf);
+    }
+    if ((buf2[0] && stat(buf2, &lsofsb)) && stat(LsofPath, &lsofsb)) {
+        (void)snprintf(buf, sizeof(buf) - 1, "ERROR!!!  stat(%s): %s", LsofPath,
+                       strerror(errno));
+        buf[sizeof(buf) - 1] = '\0';
+        cem = MkStrCpy(buf, &ti);
+        if (pem)
+            (void)PrtMsg(pem, Pn);
+        pem = cem;
+        execs = 1;
     } else if ((cem = ConvStatDev(&lsofsb.st_dev, &lsofdc))) {
-	if (pem)
-	    (void) PrtMsg(pem, Pn);
-	pem = cem;
-	execs = 1;
+        if (pem)
+            (void)PrtMsg(pem, Pn);
+        pem = cem;
+        execs = 1;
     }
 
-#if	defined(LT_KMEM)
-/*
- * Get /dev/kmem's stat(2) information.
- */
+#if defined(LT_KMEM)
+    /*
+     * Get /dev/kmem's stat(2) information.
+     */
     if (stat("/dev/kmem", &kmemsb)) {
-	(void) snprintf(buf, sizeof(buf) - 1,
-	    "ERROR!!!  can't stat(2) /dev/kmem: %s", strerror(errno));
-	buf[sizeof(buf) - 1] = '\0';
-	cem = MkStrCpy(buf, &ti);
-	if (pem)
-	    (void) PrtMsg(pem, Pn);
-	pem = cem;
-	kmems = 1;
+        (void)snprintf(buf, sizeof(buf) - 1,
+                       "ERROR!!!  can't stat(2) /dev/kmem: %s",
+                       strerror(errno));
+        buf[sizeof(buf) - 1] = '\0';
+        cem = MkStrCpy(buf, &ti);
+        if (pem)
+            (void)PrtMsg(pem, Pn);
+        pem = cem;
+        kmems = 1;
     } else if ((cem = ConvStatDev(&kmemsb.st_rdev, &kmemdc))) {
-	if (pem)
-	    (void) PrtMsg(pem, Pn);
-	pem = cem;
-	kmems = 1;
+        if (pem)
+            (void)PrtMsg(pem, Pn);
+        pem = cem;
+        kmems = 1;
     }
-#else	/* !defined(LT_KMEM) */
+#else  /* !defined(LT_KMEM) */
     kmems = 1;
-#endif	/* defined(LT_KMEM) */
+#endif /* defined(LT_KMEM) */
 
-/*
- * Get CWD's stat(2) information.
- */
+    /*
+     * Get CWD's stat(2) information.
+     */
     if (stat(".", &cwdsb)) {
-	(void) snprintf(buf, sizeof(buf) - 1, "ERROR!!!  stat(.): %s",
-	    strerror(errno));
-	buf[sizeof(buf) - 1] = '\0';
-	cem = MkStrCpy(buf, &ti);
-	if (pem)
-	    (void) PrtMsg(pem, Pn);
-	pem = cem;
-	procs = 1;
+        (void)snprintf(buf, sizeof(buf) - 1, "ERROR!!!  stat(.): %s",
+                       strerror(errno));
+        buf[sizeof(buf) - 1] = '\0';
+        cem = MkStrCpy(buf, &ti);
+        if (pem)
+            (void)PrtMsg(pem, Pn);
+        pem = cem;
+        procs = 1;
     } else if ((cem = ConvStatDev(&cwdsb.st_dev, &cwddc))) {
-	if (pem)
-	    (void) PrtMsg(pem, Pn);
-	pem = cem;
-	procs = 1;
+        if (pem)
+            (void)PrtMsg(pem, Pn);
+        pem = cem;
+        procs = 1;
     }
 
-/*
- * Complete the option vector and start lsof execution.
- */
+    /*
+     * Complete the option vector and start lsof execution.
+     */
     ti = 0;
 
-#if	defined(USE_LSOF_C_OPT)
+#if defined(USE_LSOF_C_OPT)
     opv[ti++] = "-C";
-#endif	/* defined(USE_LSOF_C_OPT) */
+#endif /* defined(USE_LSOF_C_OPT) */
 
-#if	defined(USE_LSOF_X_OPT)
+#if defined(USE_LSOF_X_OPT)
     opv[ti++] = "-X";
-#endif	/* defined(USE_LSOF_X_OPT) */
+#endif /* defined(USE_LSOF_X_OPT) */
 
     opv[ti++] = "-clsof";
     opv[ti] = (char *)NULL;
     if ((cem = ExecLsof(opv))) {
-	if (pem)
-	    (void) PrtMsg(pem, Pn);
-	return(cem);
+        if (pem)
+            (void)PrtMsg(pem, Pn);
+        return (cem);
     }
-/*
- * Read lsof output.
- */
+    /*
+     * Read lsof output.
+     */
     xwhile = execs + kmems + procs;
     while ((xwhile < 3) && (fop = RdFrLsof(&nf, &cem))) {
-	if (pem)
-	    (void) PrtMsg(pem, Pn);
-	pem = cem;
-	switch (fop->ft) {
-	case LSOF_FID_PID:
-
-	/*
-	 * This is a process information line.
-	 */
-	    pid = (pid_t)atoi(fop->v);
-	    pids = 1;
-	    cmdp = (LTfldo_t *)NULL;
-	    for (fop++, ti = 1; ti < nf; fop++, ti++) {
-		switch (fop->ft) {
-		case LSOF_FID_CMD:
-		    cmdp = fop;
-		    break;
-		}
-	    }
-	    if (!cmdp || (pid != LsofPid))
-		pids = 0;
-	    break;
-	case LSOF_FID_FD:
-
-	/*
-	 * This is a file descriptor line.  Scan its fields.
-	 */
-	    if (!pids)
-		break;
-	    devp = inop = rdevp = typ = (LTfldo_t *)NULL;
-	    fdp = fop;
-	    for (fop++, ti = 1; ti < nf; fop++, ti++) {
-		switch(fop->ft) {
-		case LSOF_FID_DEVN:
-		    devp = fop;
-		    break;
-		case LSOF_FID_INODE:
-		    inop = fop;
-		    break;
-		case LSOF_FID_RDEV:
-		    rdevp = fop;
-		    break;
-		case LSOF_FID_TYPE:
-		    typ = fop;
-		    break;
-		}
-	    }
-	/*
-	 * A file descriptor line has been processes.
-	 *
-	 * Set the descriptor's numeric status.
-	 *
-	 * Check descriptor by FD type.
-	 */
-
-	    for (fdn = 0, tcp = fdp->v; *tcp; tcp++) {
-		if (!isdigit((unsigned char)*tcp)) {
-		    fdn = -1;
-		    break;
-		}
-		fdn = (fdn * 10) + (int)(*tcp - '0');
-	    }
-	    if (!procs
-	    &&  (fdn == -1)
-	    &&  !strcasecmp(fdp->v, "cwd")
-	    &&  typ
-	    &&  (!strcasecmp(typ->v, "DIR") || !strcasecmp(typ->v, "VDIR"))
-	    ) {
-
-	    /*
-	     * This is the CWD for the process.  Make sure its information
-	     * matches what stat(2) said about the CWD.
-	     */
-		if (!devp || !inop)
-		    break;
-		if ((cem = ConvLsofDev(devp->v, &tmpdc))) {
-		    if (pem)
-			(void) PrtMsg(pem, Pn);
-		    pem = cem;
-		    break;
-		}
-		(void) snprintf(ibuf, sizeof(ibuf) - 1, "%" PRIu64,
-		    (uint64_t)cwdsb.st_ino);
-		ibuf[sizeof(ibuf) - 1] = '\0';
-		if ((tmpdc.maj == cwddc.maj)
-		&&  (tmpdc.min == cwddc.min)
-		&&  (tmpdc.unit == cwddc.unit)
-		&&  !strcmp(inop->v, ibuf)
-		) {
-		    procs = 1;
-		    xwhile++;
-		}
-		break;
-	    }
-	    if (!kmems
-	    &&  (fdn >= 0)
-	    &&  typ
-	    &&  (!strcasecmp(typ->v, "CHR") || !strcasecmp(typ->v, "VCHR"))
-	    ) {
-
-	    /*
-	     * /dev/kmem hasn't been found and this is an open character device
-	     * file with a numeric descriptor.
-	     *
-	     * See if it is /dev/kmem.
-	     */
-		if (!inop || !rdevp)
-		    break;
-		if ((cem = ConvLsofDev(rdevp->v, &tmpdc))) {
-		    if (pem)
-			(void) PrtMsg(pem, Pn);
-		    pem = cem;
-		    break;
-		}
-		(void) snprintf(ibuf, sizeof(ibuf) - 1, "%" PRIu64,
-		    (uint64_t)kmemsb.st_ino);
-		ibuf[sizeof(ibuf) - 1] = '\0';
-		if ((tmpdc.maj == kmemdc.maj)
-		&&  (tmpdc.min == kmemdc.min)
-		&&  (tmpdc.unit == kmemdc.unit)
-		&&  !strcmp(inop->v, ibuf)
-		) {
-		    kmems = 1;
-		    xwhile++;
-		}
-		break;
-	    }
-	    if (!execs
-	    &&  (fdn == -1)
-	    &&  typ
-	    &&  (!strcasecmp(typ->v, "REG") || !strcasecmp(typ->v, "VREG"))
-	    ) {
-
-	    /*
-	     * If this is a regular file with a non-numeric FD, it may be the
-	     * executable.
-	     */
-		if (!devp || !inop)
-		    break;
-	        if ((cem = ConvLsofDev(devp->v, &lsofdc))) {
-		    if (pem)
-			(void) PrtMsg(pem, Pn);
-		    pem = cem;
-		    break;
-		}
-		(void) snprintf(ibuf, sizeof(ibuf) - 1, "%" PRIu64,
-		    (uint64_t)lsofsb.st_ino);
-		ibuf[sizeof(ibuf) - 1] = '\0';
-		if ((tmpdc.maj == lsofdc.maj)
-		&&  (tmpdc.min == lsofdc.min)
-		&&  (tmpdc.unit == lsofdc.unit)
-		&&  !strcmp(inop->v, ibuf)
-		) {
-		    execs = 1;
-		    xwhile++;
-		}
-	    }
-	}
+        if (pem)
+            (void)PrtMsg(pem, Pn);
+        pem = cem;
+        switch (fop->ft) {
+        case LSOF_FID_PID:
+
+            /*
+             * This is a process information line.
+             */
+            pid = (pid_t)atoi(fop->v);
+            pids = 1;
+            cmdp = (LTfldo_t *)NULL;
+            for (fop++, ti = 1; ti < nf; fop++, ti++) {
+                switch (fop->ft) {
+                case LSOF_FID_CMD:
+                    cmdp = fop;
+                    break;
+                }
+            }
+            if (!cmdp || (pid != LsofPid))
+                pids = 0;
+            break;
+        case LSOF_FID_FD:
+
+            /*
+             * This is a file descriptor line.  Scan its fields.
+             */
+            if (!pids)
+                break;
+            devp = inop = rdevp = typ = (LTfldo_t *)NULL;
+            fdp = fop;
+            for (fop++, ti = 1; ti < nf; fop++, ti++) {
+                switch (fop->ft) {
+                case LSOF_FID_DEVN:
+                    devp = fop;
+                    break;
+                case LSOF_FID_INODE:
+                    inop = fop;
+                    break;
+                case LSOF_FID_RDEV:
+                    rdevp = fop;
+                    break;
+                case LSOF_FID_TYPE:
+                    typ = fop;
+                    break;
+                }
+            }
+            /*
+             * A file descriptor line has been processes.
+             *
+             * Set the descriptor's numeric status.
+             *
+             * Check descriptor by FD type.
+             */
+
+            for (fdn = 0, tcp = fdp->v; *tcp; tcp++) {
+                if (!isdigit((unsigned char)*tcp)) {
+                    fdn = -1;
+                    break;
+                }
+                fdn = (fdn * 10) + (int)(*tcp - '0');
+            }
+            if (!procs && (fdn == -1) && !strcasecmp(fdp->v, "cwd") && typ &&
+                (!strcasecmp(typ->v, "DIR") || !strcasecmp(typ->v, "VDIR"))) {
+
+                /*
+                 * This is the CWD for the process.  Make sure its information
+                 * matches what stat(2) said about the CWD.
+                 */
+                if (!devp || !inop)
+                    break;
+                if ((cem = ConvLsofDev(devp->v, &tmpdc))) {
+                    if (pem)
+                        (void)PrtMsg(pem, Pn);
+                    pem = cem;
+                    break;
+                }
+                (void)snprintf(ibuf, sizeof(ibuf) - 1, "%" PRIu64,
+                               (uint64_t)cwdsb.st_ino);
+                ibuf[sizeof(ibuf) - 1] = '\0';
+                if ((tmpdc.maj == cwddc.maj) && (tmpdc.min == cwddc.min) &&
+                    (tmpdc.unit == cwddc.unit) && !strcmp(inop->v, ibuf)) {
+                    procs = 1;
+                    xwhile++;
+                }
+                break;
+            }
+            if (!kmems && (fdn >= 0) && typ &&
+                (!strcasecmp(typ->v, "CHR") || !strcasecmp(typ->v, "VCHR"))) {
+
+                /*
+                 * /dev/kmem hasn't been found and this is an open character
+                 * device file with a numeric descriptor.
+                 *
+                 * See if it is /dev/kmem.
+                 */
+                if (!inop || !rdevp)
+                    break;
+                if ((cem = ConvLsofDev(rdevp->v, &tmpdc))) {
+                    if (pem)
+                        (void)PrtMsg(pem, Pn);
+                    pem = cem;
+                    break;
+                }
+                (void)snprintf(ibuf, sizeof(ibuf) - 1, "%" PRIu64,
+                               (uint64_t)kmemsb.st_ino);
+                ibuf[sizeof(ibuf) - 1] = '\0';
+                if ((tmpdc.maj == kmemdc.maj) && (tmpdc.min == kmemdc.min) &&
+                    (tmpdc.unit == kmemdc.unit) && !strcmp(inop->v, ibuf)) {
+                    kmems = 1;
+                    xwhile++;
+                }
+                break;
+            }
+            if (!execs && (fdn == -1) && typ &&
+                (!strcasecmp(typ->v, "REG") || !strcasecmp(typ->v, "VREG"))) {
+
+                /*
+                 * If this is a regular file with a non-numeric FD, it may be
+                 * the executable.
+                 */
+                if (!devp || !inop)
+                    break;
+                if ((cem = ConvLsofDev(devp->v, &tmpdc))) {
+                    if (pem)
+                        (void)PrtMsg(pem, Pn);
+                    pem = cem;
+                    break;
+                }
+                (void)snprintf(ibuf, sizeof(ibuf) - 1, "%" PRIu64,
+                               (uint64_t)lsofsb.st_ino);
+                ibuf[sizeof(ibuf) - 1] = '\0';
+                if ((tmpdc.maj == lsofdc.maj) && (tmpdc.min == lsofdc.min) &&
+                    (tmpdc.unit == lsofdc.unit) && !strcmp(inop->v, ibuf)) {
+                    execs = 1;
+                    xwhile++;
+                }
+            }
+        }
     }
-    (void) StopLsof();
+    (void)StopLsof();
     if (!execs)
-	*texec = "ERROR!!!  open lsof executable wasn't found.";
+        *texec = "ERROR!!!  open lsof executable wasn't found.";
     if (!kmems)
-	*tkmem = "ERROR!!!  open lsof /dev/kmem usage wasn't found.";
+        *tkmem = "ERROR!!!  open lsof /dev/kmem usage wasn't found.";
     if (!procs)
-	*tproc = "ERROR!!!  lsof process wasn't found.";
-    return(pem);
+        *tproc = "ERROR!!!  lsof process wasn't found.";
+    return (pem);
 }
diff --git a/tests/LTbasic2.c b/tests/LTbasic2.c
new file mode 100644
index 0000000..4ad9024
--- /dev/null
+++ b/tests/LTbasic2.c
@@ -0,0 +1,99 @@
+/*
+ * LTbasic2.c -- Lsof Test basic tests 2
+ *
+ * The basic tests measure the finding by liblsof of its own open CWD, open
+ * executable (when possible).
+ *
+ * V. Abell
+ * Purdue University
+ */
+
+/*
+ * Copyright 2002 Purdue Research Foundation, West Lafayette, Indiana
+ * 47907.  All rights reserved.
+ *
+ * Written by V. 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.
+ */
+
+#include "lsof.h"
+#include <stdio.h>
+#include <sys/stat.h>
+
+int main(int argc, char **argv) {
+    struct lsof_result *result;
+    struct lsof_context *ctx;
+    struct lsof_process *p;
+    struct lsof_file *f;
+    int pi, fi;
+    char buffer[128];
+    int exec_found = 0; /* executable found in result */
+    int cwd_found = 0;  /* cwd found in result */
+    struct stat exec_stat;
+    struct stat cwd_stat;
+    if (stat(argv[0], &exec_stat)) {
+        fprintf(stderr, "Cannot stat %s, skipping executable check\n", argv[0]);
+        exec_found = 1;
+    }
+    if (stat(".", &cwd_stat)) {
+        fprintf(stderr, "Cannot stat '.', skipping cwd check\n");
+        cwd_found = 1;
+    }
+
+    ctx = lsof_new();
+    lsof_select_process(ctx, "LTbasic2", 0);
+    lsof_freeze(ctx);
+    lsof_gather(ctx, &result);
+
+    for (pi = 0; pi < result->num_processes; pi++) {
+        p = &result->processes[pi];
+        for (fi = 0; fi < p->num_files; fi++) {
+            f = &p->files[fi];
+            if (f->fd_type == LSOF_FD_PROGRAM_TEXT) {
+                /* check if device and inode matches */
+                if ((f->flags &
+                     (LSOF_FILE_FLAG_DEV_VALID | LSOF_FILE_FLAG_INODE_VALID)) &&
+                    f->dev == exec_stat.st_dev &&
+                    f->inode == exec_stat.st_ino) {
+                    exec_found = 1;
+                }
+            } else if (f->fd_type == LSOF_FD_CWD) {
+                /* check if device and inode matches */
+                if ((f->flags &
+                     (LSOF_FILE_FLAG_DEV_VALID | LSOF_FILE_FLAG_INODE_VALID)) &&
+                    f->dev == cwd_stat.st_dev && f->inode == cwd_stat.st_ino) {
+                    cwd_found = 1;
+                }
+            }
+        }
+    }
+
+    lsof_free_result(result);
+    lsof_destroy(ctx);
+
+    if (!exec_found) {
+        fprintf(stderr, "ERROR!!!  open LTbasic2 executable wasn't found.\n");
+    }
+    if (!cwd_found) {
+        fprintf(stderr, "ERROR!!!  current working directory wasn't found.\n");
+    }
+    return !(exec_found && cwd_found);
+}
\ No newline at end of file
diff --git a/tests/LTbigf.c b/tests/LTbigf.c
index d1aa9ef..823d6cd 100644
--- a/tests/LTbigf.c
+++ b/tests/LTbigf.c
@@ -5,7 +5,6 @@
  * Purdue University
  */
 
-
 /*
  * Copyright 2002 Purdue Research Foundation, West Lafayette, Indiana
  * 47907.  All rights reserved.
@@ -32,736 +31,698 @@
  * 4. This notice may not be removed or altered.
  */
 
-#ifndef lint
-static char copyright[] =
-"@(#) Copyright 2002 Purdue Research Foundation.\nAll rights reserved.\n";
-#endif
-
 #include "LsofTest.h"
 
-#if	!defined(LT_BIGF)
+#if !defined(LT_BIGF)
 
 /*
  * Here begins the version of this program for dialects that don't support
  * large files.
  */
 
-
 /*
  * Main program for dialects that don't support large files
  */
 
-int
-main(argc, argv)
-	int argc;			/* argument count */
-	char *argv[];			/* arguments */
+int main(int argc,     /* argument count */
+         char *argv[]) /* arguments */
 {
-    char *pn;			/* program name */
-/*
- * Get program name and issue start and exit message.
- */
+    char *pn; /* program name */
+              /*
+               * Get program name and issue start and exit message.
+               */
     if ((pn = (char *)strrchr(argv[0], '/')))
-	    pn++;
+        pn++;
     else
-	    pn = argv[0];
+        pn = argv[0];
 
-    (void) printf("%s ... %s\n", pn, LT_DONT_DO_TEST);
-    return(0);
+    (void)printf("%s ... %s\n", pn, LT_DONT_DO_TEST);
+    return (0);
 }
-#else	/* defined(LT_BIGF) */
+#else /* defined(LT_BIGF) */
 
 /*
  * Here begins the version of this program for dialects that support
  * large files.
  */
 
-#include "lsof_fields.h"
-
+#    include "lsof_fields.h"
 
 /*
  * Pre-definitions that may be changed by specific dialects
  */
 
-#define	OFFTST_STAT	1		/* offset tests status */
+#    define OFFTST_STAT 1 /* offset tests status */
 
-
-#if	defined(LT_DIAL_aix)
+#    if defined(LT_DIAL_aix)
 /*
  * AIX-specific definitions
  */
 
-#define	OFFSET_T	off64_t		/* define offset type */
-#endif	/* defined(LT_DIAL_aix) */
-
+#        define OFFSET_T off64_t /* define offset type */
+#    endif                       /* defined(LT_DIAL_aix) */
 
-#if	defined(LT_DIAL_bsdi)
+#    if defined(LT_DIAL_bsdi)
 /*
  * BSDI-specific definitions
  */
 
-#define	OFFSET_T	off_t		/* define offset type */
-#define	OPENF		open		/* define open function */
-#define	SEEKF		lseek		/* define seek function */
-#define	STATF		stat		/* define stat function */
-#define	STATS		struct stat	/* define stat structure */
-#endif	/* defined(LT_DIAL_bsdi) */
+#        define OFFSET_T off_t    /* define offset type */
+#        define OPENF open        /* define open function */
+#        define SEEKF lseek       /* define seek function */
+#        define STATF stat        /* define stat function */
+#        define STATS struct stat /* define stat structure */
+#    endif                        /* defined(LT_DIAL_bsdi) */
 
-
-#if	defined(LT_DIAL_darwin)
+#    if defined(LT_DIAL_darwin)
 /*
  * Darwin-specific definitions
  */
 
-# if	LT_VERS>=900
-#define	OFFSET_T	off_t		/* define offset type */
-#define	OPENF		open		/* define open function */
-#define	SEEKF		lseek		/* define seek function */
-#define	STATF		stat		/* define stat function */
-#define	STATS		struct stat	/* define stat structure */
-# endif	/* LT_VERS>=900 */
-#endif	/* defined(LT_DIAL_darwin) */
-
+#        if LT_VERS >= 900
+#            define OFFSET_T off_t    /* define offset type */
+#            define OPENF open        /* define open function */
+#            define SEEKF lseek       /* define seek function */
+#            define STATF stat        /* define stat function */
+#            define STATS struct stat /* define stat structure */
+#        endif                        /* LT_VERS>=900 */
+#    endif                            /* defined(LT_DIAL_darwin) */
 
-#if	defined(LT_DIAL_du)
+#    if defined(LT_DIAL_du)
 /*
  * DEC_OSF/1|Digital_UNIX|Tru64_UNIX-specific items
  */
 
-#define	OFFSET_T	off_t		/* define offset type */
-#define	OPENF		open		/* define open function */
-#define	SEEKF		lseek		/* define seek function */
-#define	STATF		stat		/* define stat function */
-#define	STATS		struct stat	/* define stat structure */
-#endif	/* defined(LT_DIAL_du) */
+#        define OFFSET_T off_t    /* define offset type */
+#        define OPENF open        /* define open function */
+#        define SEEKF lseek       /* define seek function */
+#        define STATF stat        /* define stat function */
+#        define STATS struct stat /* define stat structure */
+#    endif                        /* defined(LT_DIAL_du) */
 
-
-#if	defined(LT_DIAL_freebsd)
+#    if defined(LT_DIAL_freebsd)
 /*
  * FreeBSD-specific definitions
  */
 
-#define	OFFSET_T	off_t		/* define offset type */
-#define	OPENF		open		/* define open function */
-#define	SEEKF		lseek		/* define seek function */
-#define	STATF		stat		/* define stat function */
-#define	STATS		struct stat	/* define stat structure */
-#endif	/* defined(LT_DIAL_freebsd) */
-
+#        define OFFSET_T off_t    /* define offset type */
+#        define OPENF open        /* define open function */
+#        define SEEKF lseek       /* define seek function */
+#        define STATF stat        /* define stat function */
+#        define STATS struct stat /* define stat structure */
+#    endif                        /* defined(LT_DIAL_freebsd) */
 
-#if	defined(LT_DIAL_linux)
+#    if defined(LT_DIAL_linux)
 /*
  * Linux-specific definitions
  */
 
-#undef	OFFTST_STAT
-#define	OFFTST_STAT	0		/* Linux lsof may not be able to report
-					 * offsets -- see the function
-					 * ck_Linux_offset_support() */
-#define	OFFSET_T	off_t		/* define offset type */
-#define	OPENF		open		/* define open function */
-#define	SEEKF		lseek		/* define seek function */
-#define	STATF		stat		/* define stat function */
-#define	STATS		struct stat	/* define stat structure */
+#        undef OFFTST_STAT
+#        define OFFTST_STAT                                                    \
+            0                     /* Linux lsof may not be able to report      \
+                                   * offsets -- see the function               \
+                                   * ck_Linux_offset_support() */
+#        define OFFSET_T off_t    /* define offset type */
+#        define OPENF open        /* define open function */
+#        define SEEKF lseek       /* define seek function */
+#        define STATF stat        /* define stat function */
+#        define STATS struct stat /* define stat structure */
 
-_PROTOTYPE(static int ck_Linux_offset_support,(void));
-#endif	/* defined(LT_DIAL_linux) */
+static int ck_Linux_offset_support(void);
+#    endif                        /* defined(LT_DIAL_linux) */
 
-
-#if	defined(LT_DIAL_hpux)
+#    if defined(LT_DIAL_hpux)
 /*
  * HP-UX-specific definitions
  */
 
-#define	OFFSET_T	off64_t		/* define offset type */
-#endif	/* defined(LT_DIAL_hpux) */
-
+#        define OFFSET_T off64_t /* define offset type */
+#    endif                       /* defined(LT_DIAL_hpux) */
 
-#if	defined(LT_DIAL_netbsd)
+#    if defined(LT_DIAL_netbsd)
 /*
  * NetBSD-specific definitions
  */
 
-#define	OFFSET_T	off_t		/* define offset type */
-#define	OPENF		open		/* define open function */
-#define	SEEKF		lseek		/* define seek function */
-#define	STATF		stat		/* define stat function */
-#define	STATS		struct stat	/* define stat structure */
-#endif	/* defined(LT_DIAL_netbsd) */
-
+#        define OFFSET_T off_t    /* define offset type */
+#        define OPENF open        /* define open function */
+#        define SEEKF lseek       /* define seek function */
+#        define STATF stat        /* define stat function */
+#        define STATS struct stat /* define stat structure */
+#    endif                        /* defined(LT_DIAL_netbsd) */
 
-#if	defined(LT_DIAL_openbsd)
+#    if defined(LT_DIAL_openbsd)
 /*
  * OpenBSD-specific definitions
  */
 
-#define	OFFSET_T	off_t		/* define offset type */
-#define	OPENF		open		/* define open function */
-#define	SEEKF		lseek		/* define seek function */
-#define	STATF		stat		/* define stat function */
-#define	STATS		struct stat	/* define stat structure */
-#endif	/* defined(LT_DIAL_openbsd) */
+#        define OFFSET_T off_t    /* define offset type */
+#        define OPENF open        /* define open function */
+#        define SEEKF lseek       /* define seek function */
+#        define STATF stat        /* define stat function */
+#        define STATS struct stat /* define stat structure */
+#    endif                        /* defined(LT_DIAL_openbsd) */
 
-
-#if	defined(LT_DIAL_ou)
+#    if defined(LT_DIAL_ou)
 /*
  * OpenUNIX-specific items
  */
 
-#include <signal.h>
-
-#define	IGNORE_SIGXFSZ
-#define	OFFSET_T	off64_t		/* define offset type */
-#endif	/* defined(LT_DIAL_ou) */
+#        include <signal.h>
 
+#        define IGNORE_SIGXFSZ
+#        define OFFSET_T off64_t /* define offset type */
+#    endif                       /* defined(LT_DIAL_ou) */
 
-#if	defined(LT_DIAL_solaris)
+#    if defined(LT_DIAL_solaris)
 /*
  * Solaris-specific definitions
  */
 
-#define	OFFSET_T	off64_t		/* define offset type */
-#endif	/* defined(LT_DIAL_solaris) */
+#        define OFFSET_T off64_t /* define offset type */
+#    endif                       /* defined(LT_DIAL_solaris) */
 
-
-#if	defined(LT_DIAL_uw)
+#    if defined(LT_DIAL_uw)
 /*
  * UnixWare-specific items
  */
 
-#include <signal.h>
-
-#define	IGNORE_SIGXFSZ
-#define	OFFSET_T	off64_t		/* define offset type */
-#endif	/* defined(LT_DIAL_uw) */
+#        include <signal.h>
 
+#        define IGNORE_SIGXFSZ
+#        define OFFSET_T off64_t /* define offset type */
+#    endif                       /* defined(LT_DIAL_uw) */
 
 /*
  * Local definitions
  */
 
-#if	!defined(OPENF)
-#define	OPENF		open64		/* open() function */
-#endif	/* !defined(OPENF) */
+#    if !defined(OPENF)
+#        define OPENF open64 /* open() function */
+#    endif                   /* !defined(OPENF) */
 
-#if	!defined(OFFSET_T)
-#define	OFFSET_T unsigned long long	/* offset type */
-#endif	/* !defined(OFFSET_T) */
+#    if !defined(OFFSET_T)
+#        define OFFSET_T unsigned long long /* offset type */
+#    endif                                  /* !defined(OFFSET_T) */
 
-#if	!defined(SEEKF)
-#define	SEEKF		lseek64		/* seek() function */
-# endif	/* !defined(SEEKF) */
+#    if !defined(SEEKF)
+#        define SEEKF lseek64 /* seek() function */
+#    endif                    /* !defined(SEEKF) */
 
-#if	!defined(STATF)
-#define	STATF		stat64		/* stat(2) structure */
-#endif	/* !defined(STATF) */
+#    if !defined(STATF)
+#        define STATF stat64 /* stat(2) structure */
+#    endif                   /* !defined(STATF) */
 
-#if	!defined(STATS)
-#define	STATS		struct stat64	/* stat(2) structure */
-#endif	/* !defined(STATS) */
-
-#define	TST_OFFT	0		/* test offset in 0t decimal*/
-#define	TST_OFFX	1		/* test offset in hex */
-#define	TST_SZ		2		/* test size */
+#    if !defined(STATS)
+#        define STATS struct stat64 /* stat(2) structure */
+#    endif                          /* !defined(STATS) */
 
+#    define TST_OFFT 0 /* test offset in 0t decimal*/
+#    define TST_OFFX 1 /* test offset in hex */
+#    define TST_SZ 2   /* test size */
 
 /*
  * Globals
  */
 
-int Fd = -1;			/* test file descriptor; open if >= 0 */
-pid_t MyPid = (pid_t)0;		/* PID of this process */
-char *Path = (char *)NULL;	/* test file path; none if NULL */
-char *Pn = (char *)NULL;	/* program name */
-
+int Fd = -1;               /* test file descriptor; open if >= 0 */
+pid_t MyPid = (pid_t)0;    /* PID of this process */
+char *Path = (char *)NULL; /* test file path; none if NULL */
+char *Pn = (char *)NULL;   /* program name */
 
 /*
  * Local function prototypes
  */
 
-_PROTOTYPE(static void cleanup,(void));
-_PROTOTYPE(static int tstwlsof,(int tt, char *opt, OFFSET_T sz));
-
+static void cleanup(void);
+static int tstwlsof(int tt, char *opt, OFFSET_T sz);
 
 /*
  * Main program for dialects that support large files
  */
 
-int
-main(argc, argv)
-    int argc;				/* argument count */
-    char *argv[];			/* arguments */
+int main(int argc,     /* argument count */
+         char *argv[]) /* arguments */
 {
-    char buf[2048];			/* temporary buffer */
-    int do_offt = OFFTST_STAT;		/* do offset tests if == 1 */
-    char *em;				/* error message pointer */
-    int i;				/* temporary integer */
-    int len;				/* string length */
-    OFFSET_T sz = 0x140000000ll;	/* test file size */
-    char szbuf[64];			/* size buffer */
-    char *tcp;				/* temporary character pointer */
-    int tofft = 0;			/* 0t offset test result */
-    int toffx = 0;			/* 0x offset test result */
-    int tsz = 0;			/* size test result */
-    int xv = 0;				/* exit value */
-/*
- * Get program name and PID, issue start message, and build space prefix.
- */
+    char buf[2048];              /* temporary buffer */
+    int do_offt = OFFTST_STAT;   /* do offset tests if == 1 */
+    char *em;                    /* error message pointer */
+    int i;                       /* temporary integer */
+    int len;                     /* string length */
+    OFFSET_T sz = 0x140000000ll; /* test file size */
+    char szbuf[64];              /* size buffer */
+    char *tcp;                   /* temporary character pointer */
+    int tofft = 0;               /* 0t offset test result */
+    int toffx = 0;               /* 0x offset test result */
+    int tsz = 0;                 /* size test result */
+    int xv = 0;                  /* exit value */
+                                 /*
+                                  * Get program name and PID, issue start message, and build space prefix.
+                                  */
     if ((Pn = strrchr(argv[0], '/')))
-	Pn++;
+        Pn++;
     else
-	Pn = argv[0];
+        Pn = argv[0];
     MyPid = getpid();
-    (void) printf("%s ... ", Pn);
-    (void) fflush(stdout);
+    (void)printf("%s ... ", Pn);
+    (void)fflush(stdout);
     PrtMsg((char *)NULL, Pn);
-/*
- * Process arguments.
- */
+    /*
+     * Process arguments.
+     */
     if (ScanArg(argc, argv, "hp:", Pn))
-	xv = 1;
+        xv = 1;
     if (xv || LTopt_h) {
-	(void) PrtMsg("usage: [-h] [-p path]", Pn);
-	PrtMsg       ("       -h       print help (this panel)", Pn);
-	PrtMsgX      ("       -p path  define test file path", Pn, cleanup, xv);
+        (void)PrtMsg("usage: [-h] [-p path]", Pn);
+        PrtMsg("       -h       print help (this panel)", Pn);
+        PrtMsgX("       -p path  define test file path", Pn, cleanup, xv);
     }
 
-#if	defined(LT_DIAL_linux)
-/*
- * If this is Linux, see if lsof can report file offsets.
- */
-	do_offt = ck_Linux_offset_support();
-#endif	/* defined(LT_DIAL_linux) */
+#    if defined(LT_DIAL_linux)
+    /*
+     * If this is Linux, see if lsof can report file offsets.
+     */
+    do_offt = ck_Linux_offset_support();
+#    endif /* defined(LT_DIAL_linux) */
 
-/*
- * See if lsof can be executed and can access kernel memory.
- */
+    /*
+     * See if lsof can be executed and can access kernel memory.
+     */
     if ((em = IsLsofExec()))
-	(void) PrtMsgX(em, Pn, cleanup, 1);
+        (void)PrtMsgX(em, Pn, cleanup, 1);
     if ((em = CanRdKmem()))
-	(void) PrtMsgX(em, Pn, cleanup, 1);
-/*
- * Construct the path.  If LT_BIGSZOFF_PATH is defined in the environment,
- * use it. otherwise construct a path in the CWD.
- */
+        (void)PrtMsgX(em, Pn, cleanup, 1);
+    /*
+     * Construct the path.  If LT_BIGSZOFF_PATH is defined in the environment,
+     * use it. otherwise construct a path in the CWD.
+     */
     if (!(Path = LTopt_p)) {
-	(void) snprintf(buf, sizeof(buf), "./config.LTbigf%ld",
-	(long)MyPid);
-	buf[sizeof(buf) - 1] = '\0';
-	Path = MkStrCpy(buf, &len);
+        (void)snprintf(buf, sizeof(buf), "./config.LTbigf%ld", (long)MyPid);
+        buf[sizeof(buf) - 1] = '\0';
+        Path = MkStrCpy(buf, &len);
     }
-/*
- * Fill buffer for writing to the test file.
- */
+    /*
+     * Fill buffer for writing to the test file.
+     */
     for (i = 0; i < sizeof(buf); i++) {
-	buf[i] = (char)(i & 0xff);
+        buf[i] = (char)(i & 0xff);
     }
 
-#if	defined(IGNORE_SIGXFSZ)
-/*
- * Ignore SIGXFSZ, if directed by a dialect-specific option.
- */
-	(void) signal(SIGXFSZ, SIG_IGN);
-#endif	/* defined(IGNORE_SIGXFSZ) */
-
-/*
- * Open a new test file at the specified path.
- */
-    (void) unlink(Path);
-    if ((Fd = OPENF(Path, O_RDWR|O_CREAT, 0600)) < 0) {
-	(void) fprintf(stderr, "ERROR!!!  can't open %s\n", Path);
-
-print_hint:
-
+#    if defined(IGNORE_SIGXFSZ)
     /*
-     * Print a hint about the LT_BIGSZOFF_PATH environment variable.
+     * Ignore SIGXFSZ, if directed by a dialect-specific option.
      */
+    (void)signal(SIGXFSZ, SIG_IGN);
+#    endif /* defined(IGNORE_SIGXFSZ) */
 
-	MsgStat = 1;
-	(void) snprintf(buf, sizeof(buf) - 1, "      Errno %d: %s",
-	    errno, strerror(errno));
-	buf[sizeof(buf) - 1] = '\0';
-	(void) PrtMsg(buf, Pn);
-	(void) PrtMsg("Hint: try using \"-p path\" to supply a path in a", Pn);
-	(void) PrtMsg("file system that has large file support enabled.\n", Pn);
-	(void) PrtMsg("Hint: try raising the process ulimit file block", Pn);
-	(void) PrtMsg("size to a value that will permit this test to", Pn);
-	(void) snprintf(szbuf, sizeof(szbuf) - 1, "%lld", (long long)sz);
-	szbuf[sizeof(szbuf) - 1] = '\0';
-	(void) snprintf(buf, sizeof(buf) - 1,
-	    "write a file whose size appears to be %s", szbuf);
-	buf[sizeof(buf) - 1] = '\0';
-	(void) PrtMsg(buf, Pn);
-	(void) PrtMsg("bytes.  (The file really isn't that big -- it", Pn);
-	(void) PrtMsg("just has a large \"hole\" in its mid-section.)\n", Pn);
-	(void) PrtMsgX("See 00FAQ and 00TEST for more information.", Pn,
-		       cleanup, 1);
+    /*
+     * Open a new test file at the specified path.
+     */
+    (void)unlink(Path);
+    if ((Fd = OPENF(Path, O_RDWR | O_CREAT, 0600)) < 0) {
+        (void)fprintf(stderr, "ERROR!!!  can't open %s\n", Path);
+
+    print_hint:
+
+        /*
+         * Print a hint about the LT_BIGSZOFF_PATH environment variable.
+         */
+
+        MsgStat = 1;
+        (void)snprintf(buf, sizeof(buf) - 1, "      Errno %d: %s", errno,
+                       strerror(errno));
+        buf[sizeof(buf) - 1] = '\0';
+        (void)PrtMsg(buf, Pn);
+        (void)PrtMsg("Hint: try using \"-p path\" to supply a path in a", Pn);
+        (void)PrtMsg("file system that has large file support enabled.\n", Pn);
+        (void)PrtMsg("Hint: try raising the process ulimit file block", Pn);
+        (void)PrtMsg("size to a value that will permit this test to", Pn);
+        (void)snprintf(szbuf, sizeof(szbuf) - 1, "%lld", (long long)sz);
+        szbuf[sizeof(szbuf) - 1] = '\0';
+        (void)snprintf(buf, sizeof(buf) - 1,
+                       "write a file whose size appears to be %s", szbuf);
+        buf[sizeof(buf) - 1] = '\0';
+        (void)PrtMsg(buf, Pn);
+        (void)PrtMsg("bytes.  (The file really isn't that big -- it", Pn);
+        (void)PrtMsg("just has a large \"hole\" in its mid-section.)\n", Pn);
+        (void)PrtMsgX("See 00FAQ and 00TEST for more information.", Pn, cleanup,
+                      1);
     }
-/*
- * Write a buffer load at the beginning of the file.
- */
+    /*
+     * Write a buffer load at the beginning of the file.
+     */
     if (SEEKF(Fd, (OFFSET_T)0, SEEK_SET) < 0) {
-	(void) fprintf(stderr,
-	    "ERROR!!!  can't seek to the beginning of %s\n", Path);
-	goto print_hint;
+        (void)fprintf(stderr, "ERROR!!!  can't seek to the beginning of %s\n",
+                      Path);
+        goto print_hint;
     }
     if (write(Fd, buf, sizeof(buf)) != sizeof(buf)) {
-	(void) fprintf(stderr,
-	    "ERROR!!!  can't write %d bytes to the beginning of %s\n",
-	    (int)sizeof(buf), Path);
-	goto print_hint;
+        (void)fprintf(stderr,
+                      "ERROR!!!  can't write %d bytes to the beginning of %s\n",
+                      (int)sizeof(buf), Path);
+        goto print_hint;
     }
-/*
- * Write a buffer load near the end of the file to bring it to the
- * specified length.  Leave the file open so lsof can find it.
- */
+    /*
+     * Write a buffer load near the end of the file to bring it to the
+     * specified length.  Leave the file open so lsof can find it.
+     */
     if (SEEKF(Fd, (OFFSET_T)(sz - sizeof(buf)), SEEK_SET) < 0) {
-	(void) snprintf(szbuf, sizeof(szbuf) - 1, "%lld",
-	    (unsigned long long)(sz - sizeof(buf)));
-	(void) fprintf(stderr, "ERROR!!!  can't seek to %s in %s\n", szbuf,
-	    Path);
-	goto print_hint;
+        (void)snprintf(szbuf, sizeof(szbuf) - 1, "%lld",
+                       (unsigned long long)(sz - sizeof(buf)));
+        (void)fprintf(stderr, "ERROR!!!  can't seek to %s in %s\n", szbuf,
+                      Path);
+        goto print_hint;
     }
     if (write(Fd, buf, sizeof(buf)) != sizeof(buf)) {
-	(void) fprintf(stderr,
-	    "ERROR!!!  can't write %d bytes near the end of %s\n",
-	    (int)sizeof(buf), Path);
-	goto print_hint;
+        (void)fprintf(stderr,
+                      "ERROR!!!  can't write %d bytes near the end of %s\n",
+                      (int)sizeof(buf), Path);
+        goto print_hint;
     }
-/*
- * Fsync() the file.
- */
+    /*
+     * Fsync() the file.
+     */
     if (fsync(Fd)) {
-	(void) fprintf(stderr, "ERROR!!!  can't fsync %s\n", Path);
-	goto print_hint;
+        (void)fprintf(stderr, "ERROR!!!  can't fsync %s\n", Path);
+        goto print_hint;
     }
 
-/*
- * If this dialect can't report offsets, disable the offset tests.
- */
+    /*
+     * If this dialect can't report offsets, disable the offset tests.
+     */
     if (!do_offt) {
-	tofft = toffx = 1;
-	PrtMsg("WARNING!!!  lsof can't return file offsets for this dialect,",
-	    Pn);
-	PrtMsg("  so offset tests have been disabled.", Pn);
+        tofft = toffx = 1;
+        PrtMsg("WARNING!!!  lsof can't return file offsets for this dialect,",
+               Pn);
+        PrtMsg("  so offset tests have been disabled.", Pn);
     }
-/*
- * Do file size test.
- */
+    /*
+     * Do file size test.
+     */
     tsz = tstwlsof(TST_SZ, "-s", sz);
-/*
- * If enabled, do offset tests.
- */
+    /*
+     * If enabled, do offset tests.
+     */
     if (!tofft)
-	tofft = tstwlsof(TST_OFFT, "-oo20", sz);
+        tofft = tstwlsof(TST_OFFT, "-oo20", sz);
     if (!toffx)
-	toffx = tstwlsof(TST_OFFX, "-oo2", sz);
-/*
- * Compute exit value and exit.
- */
+        toffx = tstwlsof(TST_OFFX, "-oo2", sz);
+    /*
+     * Compute exit value and exit.
+     */
     if ((tsz != 1) || (tofft != 1) || (toffx != 1)) {
-	tcp = (char *)NULL;
-	xv = 1;
+        tcp = (char *)NULL;
+        xv = 1;
     } else {
-	tcp = "OK";
-	xv = 0;
+        tcp = "OK";
+        xv = 0;
     }
-    (void) PrtMsgX(tcp, Pn, cleanup, xv);
-    return(0);
+    (void)PrtMsgX(tcp, Pn, cleanup, xv);
+    return (0);
 }
 
-
-#if	defined(LT_DIAL_linux)
+#    if defined(LT_DIAL_linux)
 /*
  * ck_Linux_offset_support() -- see if lsof can report offsets for this
  *				Linux implementation
  */
 
-static int
-ck_Linux_offset_support()
-{
-	char buf[1024];			/* lsof output line buffer */
-	int bufl = sizeof(buf);		/* size of buf[] */
-	char *opv[5];			/* option vector for lsof */
-	int rv = 1;			/* return value:
-					 *     0 == no lsof offset support
-					 *     1 == lsof offset support */
-/*
- * Ask lsof to report the test's FD zero offset.
- */
-	if (IsLsofExec())
-	    return(0);
-	opv[0] = "-o";
-	snprintf(buf, bufl - 1, "-p%d", (int)getpid());
-	opv[1] = buf;
-	opv[2] = "-ad0";
-	opv[3] = "+w";
-	opv[4] = (char *)NULL;
-	if (ExecLsof(opv))
-	    return(0);
-/*
- * Read the lsof output.  Look for a line with "WARNING: can't report offset"
- * in it.  If it is found, then this Linux lsof can't report offsets.
- */
-	while(fgets(buf, bufl - 1, LsofFs)) {
-	    if (strstr(buf, "WARNING: can't report offset")) {
-		rv = 0;
-		break;
-	    }
-	}
-	(void) StopLsof();
-	return(rv);
+static int ck_Linux_offset_support() {
+    char buf[1024];         /* lsof output line buffer */
+    int bufl = sizeof(buf); /* size of buf[] */
+    char *opv[5];           /* option vector for lsof */
+    int rv = 1;             /* return value:
+                             *     0 == no lsof offset support
+                             *     1 == lsof offset support */
+                            /*
+                             * Ask lsof to report the test's FD zero offset.
+                             */
+    if (IsLsofExec())
+        return (0);
+    opv[0] = "-o";
+    snprintf(buf, bufl - 1, "-p%d", (int)getpid());
+    opv[1] = buf;
+    opv[2] = "-ad0";
+    opv[3] = "+w";
+    opv[4] = (char *)NULL;
+    if (ExecLsof(opv))
+        return (0);
+    /*
+     * Read the lsof output.  Look for a line with "WARNING: can't report
+     * offset" in it.  If it is found, then this Linux lsof can't report
+     * offsets.
+     */
+    while (fgets(buf, bufl - 1, LsofFs)) {
+        if (strstr(buf, "WARNING: can't report offset")) {
+            rv = 0;
+            break;
+        }
+    }
+    (void)StopLsof();
+    return (rv);
 }
-#endif	/* defined(LT_DIAL_linux) */
-
+#    endif /* defined(LT_DIAL_linux) */
 
 /*
  * cleanup() -- release resources
  */
 
-static void
-cleanup()
-{
+static void cleanup() {
     if (Fd >= 0) {
-/*
- * Close the test file.
- *
- * But first unlink it to discourage some kernel file system implementations
- * (e.g., HFS on Apple Darwin, aka Mac OS X) from trying to fill the file's
- * large holes.  (Filling can take a long time.)
- */
-	if (Path) {
-	    (void) unlink(Path);
-	    Path = (char *)NULL;
-	}
-	(void) close(Fd);
-	Fd = -1;
+        /*
+         * Close the test file.
+         *
+         * But first unlink it to discourage some kernel file system
+         * implementations (e.g., HFS on Apple Darwin, aka Mac OS X) from trying
+         * to fill the file's large holes.  (Filling can take a long time.)
+         */
+        if (Path) {
+            (void)unlink(Path);
+            Path = (char *)NULL;
+        }
+        (void)close(Fd);
+        Fd = -1;
     }
 }
 
-
 /*
  * tstwlsof() -- test the open file with lsof
  */
 
-static int
-tstwlsof(tt, opt, sz)
-    int tt;				/* test type -- i.e., TST_* */
-    char *opt;				/* additional lsof options */
-    OFFSET_T sz;			/* expected size (and offset) */
+static int tstwlsof(int tt,      /* test type -- i.e., TST_* */
+                    char *opt,   /* additional lsof options */
+                    OFFSET_T sz) /* expected size (and offset) */
 {
-    char buf[2048], buf1[2048];		/* temporary buffers */
-    LTfldo_t *cmdp;			/* command pointer */
-    LTfldo_t *devp;			/* device pointer */
-    char *em;				/* error message pointer */
-    int ff = 0;				/* file found status */
-    LTfldo_t *fop;			/* field output pointer */
-    LTfldo_t *inop;			/* inode number pointer */
-    LTdev_t lsofdc;			/* lsof device components */
-    int nf;				/* number of fields */
-    LTfldo_t *nmp;			/* file name pointer */
-    LTfldo_t *offp;			/* file offset pointer */
-    char *opv[4];			/* option vector for ExecLsof() */
-    pid_t pid;				/* PID */
-    int pids = 0;			/* PID found status */
-    STATS sb;				/* stat(2) buffer */
-    LTdev_t stdc;			/* stat(2) device components */
-    LTfldo_t *szp;			/* file size pointer */
-    LTfldo_t *tfop;			/* temporary field output pointer */
-    int ti;				/* temporary index */
-    LTfldo_t *typ;			/* file type pointer */
-    int xv = 0;				/* exit value */
-/*
- * Check the test type.
- */
+    char buf[2048], buf1[2048]; /* temporary buffers */
+    LTfldo_t *cmdp;             /* command pointer */
+    LTfldo_t *devp;             /* device pointer */
+    char *em;                   /* error message pointer */
+    int ff = 0;                 /* file found status */
+    LTfldo_t *fop;              /* field output pointer */
+    LTfldo_t *inop;             /* inode number pointer */
+    LTdev_t lsofdc;             /* lsof device components */
+    int nf;                     /* number of fields */
+    LTfldo_t *nmp;              /* file name pointer */
+    LTfldo_t *offp;             /* file offset pointer */
+    char *opv[4];               /* option vector for ExecLsof() */
+    pid_t pid;                  /* PID */
+    int pids = 0;               /* PID found status */
+    STATS sb;                   /* stat(2) buffer */
+    LTdev_t stdc;               /* stat(2) device components */
+    LTfldo_t *szp;              /* file size pointer */
+    LTfldo_t *tfop;             /* temporary field output pointer */
+    int ti;                     /* temporary index */
+    LTfldo_t *typ;              /* file type pointer */
+    int xv = 0;                 /* exit value */
+                                /*
+                                 * Check the test type.
+                                 */
     switch (tt) {
     case TST_OFFT:
     case TST_OFFX:
     case TST_SZ:
-	break;
+        break;
     default:
-	(void) snprintf(buf, sizeof(buf) - 1,
-	    "ERROR!!! unknown test type: %d", tt);
-	buf[sizeof(buf) - 1] = '\0';
-	(void) PrtMsgX(buf, Pn, cleanup, 1);
+        (void)snprintf(buf, sizeof(buf) - 1, "ERROR!!! unknown test type: %d",
+                       tt);
+        buf[sizeof(buf) - 1] = '\0';
+        (void)PrtMsgX(buf, Pn, cleanup, 1);
     }
-/*
- * Get test file's information.
- */
+    /*
+     * Get test file's information.
+     */
     if (STATF(Path, &sb)) {
-	(void) snprintf(buf, sizeof(buf) - 1,
-	    "ERROR!!! can't stat(2) %s: %s", Path, strerror(errno));
-	buf[sizeof(buf) - 1] = '\0';
-	(void) PrtMsgX(buf, Pn, cleanup, 1);
+        (void)snprintf(buf, sizeof(buf) - 1, "ERROR!!! can't stat(2) %s: %s",
+                       Path, strerror(errno));
+        buf[sizeof(buf) - 1] = '\0';
+        (void)PrtMsgX(buf, Pn, cleanup, 1);
     }
-/*
- * Extract components from test file's device number.
- */
+    /*
+     * Extract components from test file's device number.
+     */
     if ((em = ConvStatDev(&sb.st_dev, &stdc))) {
-	(void) PrtMsg(em, Pn);
-	return(0);
+        (void)PrtMsg(em, Pn);
+        return (0);
     }
-/*
- * Complete the option vector and start lsof execution.
- */
+    /*
+     * Complete the option vector and start lsof execution.
+     */
     ti = 0;
     if (opt && *opt)
-	opv[ti++] = opt;
+        opv[ti++] = opt;
 
-#if	defined(USE_LSOF_C_OPT)
+#    if defined(USE_LSOF_C_OPT)
     opv[ti++] = "-C";
-#else	/* !defined(USE_LSOF_C_OPT) */
+#    else  /* !defined(USE_LSOF_C_OPT) */
     opv[ti++] = "--";
-#endif	/* defined(USE_LSOF_C_OPT) */
+#    endif /* defined(USE_LSOF_C_OPT) */
 
     opv[ti++] = Path;
     opv[ti] = (char *)NULL;
     if ((em = ExecLsof(opv))) {
-	(void) PrtMsg(em, Pn);
-	return(0);
+        (void)PrtMsg(em, Pn);
+        return (0);
     }
-/*
- * Read lsof output.
- */
+    /*
+     * Read lsof output.
+     */
     while (!ff && (fop = RdFrLsof(&nf, &em))) {
-	switch (fop->ft) {
-	case LSOF_FID_PID:
-
-	/*
-	 * This is a process information line.
-	 */
-	    pid = (pid_t)atoi(fop->v);
-	    pids = 1;
-	    cmdp = (LTfldo_t *)NULL;
-	    for (fop++, ti = 1; ti < nf; fop++, ti++) {
-		switch (fop->ft) {
-		case LSOF_FID_CMD:
-		    cmdp = fop;
-		    break;
-		}
-	    }
-	    if (!cmdp || (pid != MyPid))
-		pids = 0;
-	    break;
-	case LSOF_FID_FD:
-
-	/*
-	 * This is a file descriptor line.
-	 *
-	 * Scan for device number, inode number, name, offset, size, and type
-	 * fields.
-	 */
-	    if (!pids)
-		break;
-	    devp = inop = nmp = offp = szp = typ = (LTfldo_t *)NULL;
-	    for (fop++, ti = 1; ti < nf; fop++, ti++) {
-		switch(fop->ft) {
-		case LSOF_FID_DEVN:
-		    devp = fop;
-		    break;
-		case LSOF_FID_INODE:
-		    inop = fop;
-		    break;
-		case LSOF_FID_NAME:
-		    nmp = fop;
-		    break;
-		case LSOF_FID_OFFSET:
-		    offp = fop;
-		    break;
-		case LSOF_FID_SIZE:
-		    szp = fop;
-		    break;
-		case LSOF_FID_TYPE:
-		    typ = fop;
-		    break;
-		}
-	    }
-	/*
-	 * Check the results of the file descriptor field scan.
-	 *
-	 * (Don't compare path names because of symbolic link interference.)
-	 */
-	    if (!devp || !inop || !nmp || !typ)
-		break;
-	    if (strcasecmp(typ->v, "reg") && strcasecmp(typ->v, "vreg"))
-		break;
-	    if (ConvLsofDev(devp->v, &lsofdc))
-		break;
-	    if ((stdc.maj != lsofdc.maj)
-	    ||  (stdc.min != lsofdc.min)
-	    ||  (stdc.unit != lsofdc.unit))
-		break;
-	    (void) snprintf(buf, sizeof(buf) - 1, "%llu",
-		(unsigned long long)sb.st_ino);
-	    buf[sizeof(buf) - 1] = '\0';
-	    if (strcmp(inop->v, buf))
-		break;
-	/*
-	 * The specifed file has been located.  Check its size or offset,
-	 * according to the tt argument.
-	 */
-	    ff = 1;
-	    switch (tt) {
-	    case TST_OFFT:
-	    case TST_SZ:
-
-	    /*
-	     * Test the size as an offset in decimal with a leading "0t", or
-	     * test the size as a size in decimal.
-	     */
-		(void) snprintf(buf, sizeof(buf) - 1,
-		    (tt == TST_SZ) ? "%llu" : "0t%llu",
-		    (unsigned long long)sz);
-		buf[sizeof(buf) - 1] = '\0';
-		tfop = (tt == TST_SZ) ? szp : offp;
-		if (!tfop || strcmp(tfop->v, buf)) {
-		    (void) snprintf(buf1, sizeof(buf1) - 1,
-			"%s mismatch: expected %s, got %s",
-			(tt == TST_SZ) ? "size" : "0t offset",
-			buf,
-			tfop ? tfop->v : "nothing");
-		    buf1[sizeof(buf1) - 1] = '\0';
-		    (void) PrtMsg(buf1, Pn);
-		    xv = 0;
-		} else
-		    xv = 1;
-		break;
-	    case TST_OFFX:
-
-	    /*
-	     * Test the size as an offset in hex.
-	     */
-		(void) snprintf(buf, sizeof(buf) - 1, "0x%llx",
-		    (unsigned long long)sz);
-		buf[sizeof(buf) - 1] = '\0';
-		if (!offp || strcmp(offp->v, buf)) {
-		    (void) snprintf(buf1, sizeof(buf1) - 1,
-			"0x offset mismatch: expected %s, got %s",
-			buf,
-			offp ? offp->v : "nothing");
-		    buf1[sizeof(buf1) - 1] = '\0';
-		    (void) PrtMsg(buf1, Pn);
-		    xv = 0;
-		} else
-		    xv = 1;
-	    }
-	    break;
-	}
+        switch (fop->ft) {
+        case LSOF_FID_PID:
+
+            /*
+             * This is a process information line.
+             */
+            pid = (pid_t)atoi(fop->v);
+            pids = 1;
+            cmdp = (LTfldo_t *)NULL;
+            for (fop++, ti = 1; ti < nf; fop++, ti++) {
+                switch (fop->ft) {
+                case LSOF_FID_CMD:
+                    cmdp = fop;
+                    break;
+                }
+            }
+            if (!cmdp || (pid != MyPid))
+                pids = 0;
+            break;
+        case LSOF_FID_FD:
+
+            /*
+             * This is a file descriptor line.
+             *
+             * Scan for device number, inode number, name, offset, size, and
+             * type fields.
+             */
+            if (!pids)
+                break;
+            devp = inop = nmp = offp = szp = typ = (LTfldo_t *)NULL;
+            for (fop++, ti = 1; ti < nf; fop++, ti++) {
+                switch (fop->ft) {
+                case LSOF_FID_DEVN:
+                    devp = fop;
+                    break;
+                case LSOF_FID_INODE:
+                    inop = fop;
+                    break;
+                case LSOF_FID_NAME:
+                    nmp = fop;
+                    break;
+                case LSOF_FID_OFFSET:
+                    offp = fop;
+                    break;
+                case LSOF_FID_SIZE:
+                    szp = fop;
+                    break;
+                case LSOF_FID_TYPE:
+                    typ = fop;
+                    break;
+                }
+            }
+            /*
+             * Check the results of the file descriptor field scan.
+             *
+             * (Don't compare path names because of symbolic link interference.)
+             */
+            if (!devp || !inop || !nmp || !typ)
+                break;
+            if (strcasecmp(typ->v, "reg") && strcasecmp(typ->v, "vreg"))
+                break;
+            if (ConvLsofDev(devp->v, &lsofdc))
+                break;
+            if ((stdc.maj != lsofdc.maj) || (stdc.min != lsofdc.min) ||
+                (stdc.unit != lsofdc.unit))
+                break;
+            (void)snprintf(buf, sizeof(buf) - 1, "%llu",
+                           (unsigned long long)sb.st_ino);
+            buf[sizeof(buf) - 1] = '\0';
+            if (strcmp(inop->v, buf))
+                break;
+            /*
+             * The specified file has been located.  Check its size or offset,
+             * according to the tt argument.
+             */
+            ff = 1;
+            switch (tt) {
+            case TST_OFFT:
+            case TST_SZ:
+
+                /*
+                 * Test the size as an offset in decimal with a leading "0t", or
+                 * test the size as a size in decimal.
+                 */
+                (void)snprintf(buf, sizeof(buf) - 1,
+                               (tt == TST_SZ) ? "%llu" : "0t%llu",
+                               (unsigned long long)sz);
+                buf[sizeof(buf) - 1] = '\0';
+                tfop = (tt == TST_SZ) ? szp : offp;
+                if (!tfop || strcmp(tfop->v, buf)) {
+                    (void)snprintf(buf1, sizeof(buf1) - 1,
+                                   "%s mismatch: expected %s, got %s",
+                                   (tt == TST_SZ) ? "size" : "0t offset", buf,
+                                   tfop ? tfop->v : "nothing");
+                    buf1[sizeof(buf1) - 1] = '\0';
+                    (void)PrtMsg(buf1, Pn);
+                    xv = 0;
+                } else
+                    xv = 1;
+                break;
+            case TST_OFFX:
+
+                /*
+                 * Test the size as an offset in hex.
+                 */
+                (void)snprintf(buf, sizeof(buf) - 1, "0x%llx",
+                               (unsigned long long)sz);
+                buf[sizeof(buf) - 1] = '\0';
+                if (!offp || strcmp(offp->v, buf)) {
+                    (void)snprintf(buf1, sizeof(buf1) - 1,
+                                   "0x offset mismatch: expected %s, got %s",
+                                   buf, offp ? offp->v : "nothing");
+                    buf1[sizeof(buf1) - 1] = '\0';
+                    (void)PrtMsg(buf1, Pn);
+                    xv = 0;
+                } else
+                    xv = 1;
+            }
+            break;
+        }
     }
-    (void) StopLsof();
+    (void)StopLsof();
     if (em) {
 
-    /*
-     * RdFrLsof() encountered an error.
-     */
-	(void) PrtMsg(em, Pn);
-	xv = 0;
+        /*
+         * RdFrLsof() encountered an error.
+         */
+        (void)PrtMsg(em, Pn);
+        xv = 0;
     }
     if (!ff) {
-	(void) snprintf(buf, sizeof(buf) - 1, "%s not found by lsof", Path);
-	buf[sizeof(buf) - 1] = '\0';
-	PrtMsg(buf, Pn);
-	xv = 0;
+        (void)snprintf(buf, sizeof(buf) - 1, "%s not found by lsof", Path);
+        buf[sizeof(buf) - 1] = '\0';
+        PrtMsg(buf, Pn);
+        xv = 0;
     }
-    return(xv);
+    return (xv);
 }
-#endif	/* defined(LT_BIG) */
+#endif     /* defined(LT_BIG) */
diff --git a/tests/LTdnlc.c b/tests/LTdnlc.c
index e66f63f..3f1b377 100644
--- a/tests/LTdnlc.c
+++ b/tests/LTdnlc.c
@@ -5,7 +5,6 @@
  * Purdue University
  */
 
-
 /*
  * Copyright 2002 Purdue Research Foundation, West Lafayette, Indiana
  * 47907.  All rights reserved.
@@ -32,395 +31,368 @@
  * 4. This notice may not be removed or altered.
  */
 
-#ifndef lint
-static char copyright[] =
-"@(#) Copyright 2002 Purdue Research Foundation.\nAll rights reserved.\n";
-#endif
-
 #include "LsofTest.h"
 #include "lsof_fields.h"
 
-
 /*
  * Pre-definitions that may be revoked by specific dialects
  */
 
-#define	DO_TEST				/* do the test */
-
+#define DO_TEST /* do the test */
 
 /*
  * Dialect-specific items
  */
 
-
-#if	defined(LT_DIAL_aix)
+#if defined(LT_DIAL_aix)
 /*
  * AIX-specific items
  */
 
-#undef	DO_TEST
-#endif	/* defined(LT_DIAL_aix) */
+#    undef DO_TEST
+#endif /* defined(LT_DIAL_aix) */
 
-
-#if   defined(LT_DIAL_darwin)
+#if defined(LT_DIAL_darwin)
 /*
  * Darwin-specific items
  */
 
-# if	LT_VERS<800
-#undef        DO_TEST
-# endif	/* LT_VERS<800 */
-#endif        /* defined(LT_DIAL_darwin) */
-
+#    if LT_VERS < 800
+#        undef DO_TEST
+#    endif /* LT_VERS<800 */
+#endif     /* defined(LT_DIAL_darwin) */
 
 /*
  * Local definitions
  */
 
-#define	ATTEMPT_CT	5		/* number of lsof CWD lookup attempts */
-#define	LSPATH		"/bin/ls"	/* path to ls(1) */
-#define	SUCCESS_THRESH	50.0		/* success threshold */
-
+#define ATTEMPT_CT 5        /* number of lsof CWD lookup attempts */
+#define LSPATH "/bin/ls"    /* path to ls(1) */
+#define SUCCESS_THRESH 50.0 /* success threshold */
 
 /*
  * Globals
  */
 
-pid_t MyPid = (pid_t)0;		/* PID of this process */
-char *Pn = (char *)NULL;	/* program name */
-
+pid_t MyPid = (pid_t)0;  /* PID of this process */
+char *Pn = (char *)NULL; /* program name */
 
 /*
  * Local function prototypes
  */
 
-_PROTOTYPE(static void cleanup,(void));
-_PROTOTYPE(static char *FindLsofCwd,(int *ff, LTdev_t *cwddc, char *ibuf));
-
+static void cleanup(void);
+static char *FindLsofCwd(int *ff, LTdev_t *cwddc, char *ibuf);
 
 /*
  * Main program
  */
 
-int
-main(argc, argv)
-    int argc;				/* argument count */
-    char *argv[];			/* arguments */
+int main(int argc,     /* argument count */
+         char *argv[]) /* arguments */
 {
-    char buf[2048];			/* temporary buffer */
-    char cwd[MAXPATHLEN + 1];		/* CWD */
-    LTdev_t cwddc;			/* CWD device components */
-    char *em;				/* error message pointer */
-    int ff;				/* FindFile() file-found flag */
-    int fpathct;			/* full path found count */
-    char ibuf[32];			/* inode buffer */
-    char lsbuf[2048 + MAXPATHLEN + 1];	/* ls(1) system() command */
-    double pct;				/* performance percentage */
-    struct stat sb;			/* CWD stat(2) results */
-    int ti;				/* temporary index */
-    int xv = 0;				/* exit value */
-/*
- * Get program name and PID, issue start message, and build space prefix.
- */
+    char buf[2048];                    /* temporary buffer */
+    char cwd[MAXPATHLEN + 1];          /* CWD */
+    LTdev_t cwddc;                     /* CWD device components */
+    char *em;                          /* error message pointer */
+    int ff;                            /* FindFile() file-found flag */
+    int fpathct;                       /* full path found count */
+    char ibuf[32];                     /* inode buffer */
+    char lsbuf[2048 + MAXPATHLEN + 1]; /* ls(1) system() command */
+    double pct;                        /* performance percentage */
+    struct stat sb;                    /* CWD stat(2) results */
+    int ti;                            /* temporary index */
+    int xv = 0;                        /* exit value */
+                                       /*
+                                        * Get program name and PID, issue start message, and build space prefix.
+                                        */
     if ((Pn = strrchr(argv[0], '/')))
-	Pn++;
+        Pn++;
     else
-	Pn = argv[0];
+        Pn = argv[0];
     MyPid = getpid();
-    (void) printf("%s ... ", Pn);
-    (void) fflush(stdout);
+    (void)printf("%s ... ", Pn);
+    (void)fflush(stdout);
     PrtMsg((char *)NULL, Pn);
-/*
- * Process arguments.
- */
+    /*
+     * Process arguments.
+     */
     if (ScanArg(argc, argv, "h", Pn))
-	xv = 1;
+        xv = 1;
     if (xv || LTopt_h) {
-	(void) PrtMsg("usage: [-h] [-p path]", Pn);
-	PrtMsgX("       -h       print help (this panel)", Pn, cleanup, xv);
+        (void)PrtMsg("usage: [-h] [-p path]", Pn);
+        PrtMsgX("       -h       print help (this panel)", Pn, cleanup, xv);
     }
 
-#if	!defined(DO_TEST)
-/*
- * If the dialect has disabled the test, echo that result and exit with
- * a successful return code.
- */
-    (void) PrtMsgX(LT_DONT_DO_TEST, Pn, cleanup, 0);
-#endif	/* !defined(DO_TEST) */
+#if !defined(DO_TEST)
+    /*
+     * If the dialect has disabled the test, echo that result and exit with
+     * a successful return code.
+     */
+    (void)PrtMsgX(LT_DONT_DO_TEST, Pn, cleanup, 0);
+#endif /* !defined(DO_TEST) */
 
-/*
- * See if lsof can be executed and can access kernel memory.
- */
+    /*
+     * See if lsof can be executed and can access kernel memory.
+     */
     if ((em = IsLsofExec()))
-	(void) PrtMsgX(em, Pn, cleanup, 1);
+        (void)PrtMsgX(em, Pn, cleanup, 1);
     if ((em = CanRdKmem()))
-	(void) PrtMsgX(em, Pn, cleanup, 1);
-/*
- * Get the CWD and form the ls(1) system() command.
- */
+        (void)PrtMsgX(em, Pn, cleanup, 1);
+        /*
+         * Get the CWD and form the ls(1) system() command.
+         */
 
-#if	defined(USE_GETCWD)
+#if defined(USE_GETCWD)
     em = "getcwd";
     if (!getcwd(cwd, sizeof(cwd)))
-#else	/* ! defined(USE_GETCWD) */
+#else  /* ! defined(USE_GETCWD) */
     em = "getwd";
     if (!getwd(cwd))
-#endif	/* defined(USE_GETCWD) */
+#endif /* defined(USE_GETCWD) */
 
     {
-	(void) snprintf(buf, sizeof(buf) - 1,
-	    "ERROR!!!  %s() error: %s", em, strerror(errno));
-	buf[sizeof(buf) - 1] = '\0';
-	(void) PrtMsgX(buf, Pn, cleanup, 1);
+        (void)snprintf(buf, sizeof(buf) - 1, "ERROR!!!  %s() error: %s", em,
+                       strerror(errno));
+        buf[sizeof(buf) - 1] = '\0';
+        (void)PrtMsgX(buf, Pn, cleanup, 1);
     }
-    (void) snprintf(lsbuf, sizeof(lsbuf) - 1, "%s %s > /dev/null 2>&1",
-	LSPATH, cwd);
-/*
- * Get the CWD stat(2) results.
- */
+    (void)snprintf(lsbuf, sizeof(lsbuf) - 1, "%s %s > /dev/null 2>&1", LSPATH,
+                   cwd);
+    /*
+     * Get the CWD stat(2) results.
+     */
     if (stat(cwd, &sb)) {
-	(void) snprintf(buf, sizeof(buf) - 1,
-	    "ERROR!!!  stat(%s) error: %s", cwd, strerror(errno));
-	buf[sizeof(buf) - 1] = '\0';
-	(void) PrtMsgX(buf, Pn, cleanup, 1);
+        (void)snprintf(buf, sizeof(buf) - 1, "ERROR!!!  stat(%s) error: %s",
+                       cwd, strerror(errno));
+        buf[sizeof(buf) - 1] = '\0';
+        (void)PrtMsgX(buf, Pn, cleanup, 1);
     }
     if ((em = ConvStatDev(&sb.st_dev, &cwddc)))
-	PrtMsgX(em, Pn, cleanup, 1);
-    (void) snprintf(ibuf, sizeof(ibuf) - 1, "%" PRIu64, (uint64_t)sb.st_ino);
+        PrtMsgX(em, Pn, cleanup, 1);
+    (void)snprintf(ibuf, sizeof(ibuf) - 1, "%" PRIu64, (uint64_t)sb.st_ino);
     ibuf[sizeof(ibuf) - 1] = '\0';
-/*
- * Loop ATTEMPT_CT times.
- */
-    for (fpathct = ti = 0; ti < ATTEMPT_CT; ti++) {
-
     /*
-     * Call ls(1) to list the CWD to /dev/null.
+     * Loop ATTEMPT_CT times.
      */
-	(void) system(lsbuf);
-    /*
-     * Call lsof to look up its own CWD -- i.e., this one.
-     */
-	if ((em = FindLsofCwd(&ff, &cwddc, ibuf))) {
-
-	/*
-	 * FindLsofCwd() returned a message.  Decode it via ff.
-	 */
-	    if (ff == -1)
-		PrtMsgX(em, Pn, cleanup, 1);
-	    else if (ff == 1) {
+    for (fpathct = ti = 0; ti < ATTEMPT_CT; ti++) {
 
-	    /*
-	     * This shouldn't happen.  If FindLsof() found lsof's CWD, it
-	     * should set ff to one and return NULL.
-	     */
-		PrtMsgX("ERROR!!!  inconsistent FindLsofCwd() return", Pn,
-		    cleanup, 1);
-	    }
-	} else if (ff == 1) {
-	    fpathct++;
-	}
+        /*
+         * Call ls(1) to list the CWD to /dev/null.
+         */
+        (void)system(lsbuf);
+        /*
+         * Call lsof to look up its own CWD -- i.e., this one.
+         */
+        if ((em = FindLsofCwd(&ff, &cwddc, ibuf))) {
+
+            /*
+             * FindLsofCwd() returned a message.  Decode it via ff.
+             */
+            if (ff == -1)
+                PrtMsgX(em, Pn, cleanup, 1);
+            else if (ff == 1) {
+
+                /*
+                 * This shouldn't happen.  If FindLsof() found lsof's CWD, it
+                 * should set ff to one and return NULL.
+                 */
+                PrtMsgX("ERROR!!!  inconsistent FindLsofCwd() return", Pn,
+                        cleanup, 1);
+            }
+        } else if (ff == 1) {
+            fpathct++;
+        }
     }
-/*
- * Compute, display, and measure the success percentage.
- */
+    /*
+     * Compute, display, and measure the success percentage.
+     */
     pct = ((double)fpathct * (double)100.0) / (double)ATTEMPT_CT;
     PrtMsg((char *)NULL, Pn);
-    (void) printf("%s found: %.2f%%\n", cwd, pct);	/* NeXT snpf.c has no
-							 * %f support */
+    (void)printf("%s found: %.2f%%\n", cwd, pct); /* NeXT snpf.c has no
+                                                   * %f support */
     MsgStat = 1;
     if (pct < (double)SUCCESS_THRESH) {
-	PrtMsg("ERROR!!!  the find rate was too low.", Pn);
-	if (!fpathct) {
-	    (void) PrtMsg(
-		"Hint: since the find rate is zero, it may be that this file",
-		Pn);
-	    (void) PrtMsg(
-		"system does not fully participate in kernel DNLC processing",
-		Pn);
-	    (void) PrtMsg(
-		"-- e.g., NFS file systems often do not, /tmp file systems",
-		Pn);
-	    (void) PrtMsg(
-		"sometimes do not, Solaris loopback file systems do not.\n",
-		Pn);
-	    (void) PrtMsg(
-		"As a work-around rebuild and test lsof on a file system that",
-		Pn);
-	    (void) PrtMsg(
-		"fully participates in kernel DNLC processing.\n",
-		Pn);
-	    (void) PrtMsg("See 00FAQ and 00TEST for more information.", Pn);
-	}
-	exit(1);
+        PrtMsg("ERROR!!!  the find rate was too low.", Pn);
+        if (!fpathct) {
+            (void)PrtMsg(
+                "Hint: since the find rate is zero, it may be that this file",
+                Pn);
+            (void)PrtMsg(
+                "system does not fully participate in kernel DNLC processing",
+                Pn);
+            (void)PrtMsg(
+                "-- e.g., NFS file systems often do not, /tmp file systems",
+                Pn);
+            (void)PrtMsg(
+                "sometimes do not, Solaris loopback file systems do not.\n",
+                Pn);
+            (void)PrtMsg(
+                "As a work-around rebuild and test lsof on a file system that",
+                Pn);
+            (void)PrtMsg("fully participates in kernel DNLC processing.\n", Pn);
+            (void)PrtMsg("See 00FAQ and 00TEST for more information.", Pn);
+        }
+        exit(1);
     }
-/*
- * Exit successfully.
- */
-    (void) PrtMsgX("OK", Pn, cleanup, 0);
-    return(0);
+    /*
+     * Exit successfully.
+     */
+    (void)PrtMsgX("OK", Pn, cleanup, 0);
+    return (0);
 }
 
-
 /*
  * cleanup() -- release resources
  */
 
-static void
-cleanup()
-{
-}
-
+static void cleanup() {}
 
 /*
  * FindLsofCwd() -- find the lsof CWD
  */
 
-static char *
-FindLsofCwd(ff, cwddc, ibuf)
-    int *ff;				/* file-found response receptor */
-    LTdev_t *cwddc;			/* CWD device components */
-    char *ibuf;				/* CWD inode number in ASCII */
+static char *FindLsofCwd(int *ff,        /* file-found response receptor */
+                         LTdev_t *cwddc, /* CWD device components */
+                         char *ibuf)     /* CWD inode number in ASCII */
 {
-    char *cp;				/* temporary character pointer */
-    char *cem;				/* current error message pointer */
-    LTfldo_t *cmdp;			/* command pointer */
-    LTdev_t devdc;			/* devp->v device components */
-    LTfldo_t *devp;			/* device pointer */
-    LTfldo_t *fop;			/* field output pointer */
-    LTfldo_t *inop;			/* inode number pointer */
-    int nf;				/* number of fields */
-    LTfldo_t *nmp;			/* name pointer */
-    char *opv[3];			/* option vector for ExecLsof() */
-    char *pem = (char *)NULL;		/* previous error message pointer */
-    pid_t pid;				/* PID */
-    int pids = 0;			/* PID found status */
-    int ti;				/* temporary integer */
-    LTfldo_t *typ;			/* file type pointer */
-/*
- * Check the argument pointers.
- *
- * Set the file-found response false.
- */
+    char *cp;                 /* temporary character pointer */
+    char *cem;                /* current error message pointer */
+    LTfldo_t *cmdp;           /* command pointer */
+    LTdev_t devdc;            /* devp->v device components */
+    LTfldo_t *devp;           /* device pointer */
+    LTfldo_t *fop;            /* field output pointer */
+    LTfldo_t *inop;           /* inode number pointer */
+    int nf;                   /* number of fields */
+    LTfldo_t *nmp;            /* name pointer */
+    char *opv[3];             /* option vector for ExecLsof() */
+    char *pem = (char *)NULL; /* previous error message pointer */
+    pid_t pid;                /* PID */
+    int pids = 0;             /* PID found status */
+    int ti;                   /* temporary integer */
+    LTfldo_t *typ;            /* file type pointer */
+                              /*
+                               * Check the argument pointers.
+                               *
+                               * Set the file-found response false.
+                               */
     if (!ff || !cwddc || !ibuf)
-	(void) PrtMsgX("ERROR!!!  missing argument to FindFile()",
-		       Pn, cleanup, 1);
+        (void)PrtMsgX("ERROR!!!  missing argument to FindFile()", Pn, cleanup,
+                      1);
     *ff = 0;
-/*
- * Complete the option vector and start lsof execution.
- */
+    /*
+     * Complete the option vector and start lsof execution.
+     */
     opv[0] = "-clsof";
     opv[1] = "-adcwd";
     opv[2] = (char *)NULL;
     if ((cem = ExecLsof(opv))) {
-	*ff = -1;
-	return(cem);
+        *ff = -1;
+        return (cem);
     }
-/*
- * Read lsof output.
- */
+    /*
+     * Read lsof output.
+     */
     while (!*ff && (fop = RdFrLsof(&nf, &cem))) {
-	if (cem) {
-	    if (pem)
-		(void) PrtMsg(pem, Pn);
-	    *ff = -1;
-	    return(cem);
-	}
-	switch (fop->ft) {
-	case LSOF_FID_PID:
-
-	/*
-	 * This is a process information line.
-	 */
-	    pid = (pid_t)atoi(fop->v);
-	    pids = 1;
-	    cmdp = (LTfldo_t *)NULL;
-	    for (fop++, ti = 1; ti < nf; fop++, ti++) {
-		switch (fop->ft) {
-		case LSOF_FID_CMD:
-		    cmdp = fop;
-		    break;
-		}
-	    }
-	    if (!cmdp || (pid != LsofPid))
-		pids = 0;
-	    break;
-	case LSOF_FID_FD:
-
-	/*
-	 * This is a file descriptor line.  Make sure it's for the expected
-	 * PID and its type is "cwd".
-	 */
-	    if (!pids)
-		break;
-	    if (strcasecmp(fop->v, "cwd"))
-		break;
-	/*
-	 * Scan for device, inode, name, and type fields.
-	 */
-	    devp = inop = nmp = typ = (LTfldo_t *)NULL;
-	    for (fop++, ti = 1; ti < nf; fop++, ti++) {
-		switch (fop->ft) {
-		case LSOF_FID_DEVN:
-		    devp = fop;
-		    break;
-		case LSOF_FID_INODE:
-		    inop = fop;
-		    break;
-		case LSOF_FID_NAME:
-		    nmp = fop;
-		    break;
-		case LSOF_FID_TYPE:
-		    typ = fop;
-		    break;
-		}
-	    }
-	/*
-	 * Check the device, inode, and type of the file.
-	 */
-	    if (!devp || !inop || !nmp || !typ)
-		break;
-	    if (strcasecmp(typ->v, "dir") && strcasecmp(typ->v, "vdir"))
-		break;
-	    if ((cem = ConvLsofDev(devp->v, &devdc))) {
-		if (pem)
-		    (void) PrtMsg(pem, Pn);
-		pem = cem;
-		break;
-	    }
-	    if ((cwddc->maj != devdc.maj)
-	    ||  (cwddc->min != devdc.min)
-	    ||  (cwddc->unit != devdc.unit)
-	    ||  strcmp(inop->v, ibuf)
-	    ) {
-		break;
-	    }
-	/*
-	 * Check the name for spaces.  If it has none, set a file-found
-	 * response.
-	 */
-	    if (!(cp = strchr(nmp->v, ' ')))
-		*ff = 1;
-	    else {
-
-	    /*
-	     * If a parenthesized file system name follows the space in the
-	     * file's name, it probably is an NFS file system name and can
-	     * be ignored.  Accordingly set a file-found response.
-	     */
-		if ((*(cp + 1) == '(') && *(cp + 2) && !strchr(cp + 2, ' ')) {
-		    if ((cp = strchr(cp + 2, ')')) && !*(cp + 1))
-			*ff = 1;
-		}
-	    }
-	}
+        if (cem) {
+            if (pem)
+                (void)PrtMsg(pem, Pn);
+            *ff = -1;
+            return (cem);
+        }
+        switch (fop->ft) {
+        case LSOF_FID_PID:
+
+            /*
+             * This is a process information line.
+             */
+            pid = (pid_t)atoi(fop->v);
+            pids = 1;
+            cmdp = (LTfldo_t *)NULL;
+            for (fop++, ti = 1; ti < nf; fop++, ti++) {
+                switch (fop->ft) {
+                case LSOF_FID_CMD:
+                    cmdp = fop;
+                    break;
+                }
+            }
+            if (!cmdp || (pid != LsofPid))
+                pids = 0;
+            break;
+        case LSOF_FID_FD:
+
+            /*
+             * This is a file descriptor line.  Make sure it's for the expected
+             * PID and its type is "cwd".
+             */
+            if (!pids)
+                break;
+            if (strcasecmp(fop->v, "cwd"))
+                break;
+            /*
+             * Scan for device, inode, name, and type fields.
+             */
+            devp = inop = nmp = typ = (LTfldo_t *)NULL;
+            for (fop++, ti = 1; ti < nf; fop++, ti++) {
+                switch (fop->ft) {
+                case LSOF_FID_DEVN:
+                    devp = fop;
+                    break;
+                case LSOF_FID_INODE:
+                    inop = fop;
+                    break;
+                case LSOF_FID_NAME:
+                    nmp = fop;
+                    break;
+                case LSOF_FID_TYPE:
+                    typ = fop;
+                    break;
+                }
+            }
+            /*
+             * Check the device, inode, and type of the file.
+             */
+            if (!devp || !inop || !nmp || !typ)
+                break;
+            if (strcasecmp(typ->v, "dir") && strcasecmp(typ->v, "vdir"))
+                break;
+            if ((cem = ConvLsofDev(devp->v, &devdc))) {
+                if (pem)
+                    (void)PrtMsg(pem, Pn);
+                pem = cem;
+                break;
+            }
+            if ((cwddc->maj != devdc.maj) || (cwddc->min != devdc.min) ||
+                (cwddc->unit != devdc.unit) || strcmp(inop->v, ibuf)) {
+                break;
+            }
+            /*
+             * Check the name for spaces.  If it has none, set a file-found
+             * response.
+             */
+            if (!(cp = strchr(nmp->v, ' ')))
+                *ff = 1;
+            else {
+
+                /*
+                 * If a parenthesized file system name follows the space in the
+                 * file's name, it probably is an NFS file system name and can
+                 * be ignored.  Accordingly set a file-found response.
+                 */
+                if ((*(cp + 1) == '(') && *(cp + 2) && !strchr(cp + 2, ' ')) {
+                    if ((cp = strchr(cp + 2, ')')) && !*(cp + 1))
+                        *ff = 1;
+                }
+            }
+        }
     }
-/*
- * Clean up and return.
- */
-    (void) StopLsof();
+    /*
+     * Clean up and return.
+     */
+    (void)StopLsof();
     if (pem) {
-	*ff = -1;
-	return(pem);
+        *ff = -1;
+        return (pem);
     }
-    return((char *)NULL);
+    return ((char *)NULL);
 }
diff --git a/tests/LTlib.c b/tests/LTlib.c
index e04a5ef..24ef241 100644
--- a/tests/LTlib.c
+++ b/tests/LTlib.c
@@ -5,7 +5,6 @@
  * Purdue University
  */
 
-
 /*
  * Copyright 2002 Purdue Research Foundation, West Lafayette, Indiana
  * 47907.  All rights reserved.
@@ -32,563 +31,518 @@
  * 4. This notice may not be removed or altered.
  */
 
-#ifndef lint
-static char copyright[] =
-"@(#) Copyright 2002 Purdue Research Foundation.\nAll rights reserved.\n";
-#endif
-
 #include "LsofTest.h"
 
-
 /*
  * Pre-defintions that may be changed by a specific dialect
  */
 
-#define	X2DEV_T		unsigned int	/* cast for result of x2dev() */
-#define	XDINDEV		8		/* number of hex digits in an lsof
-					 * device field -- should be
-					 * 2 X sizeof(X2DEV_T) */
+#define X2DEV_T unsigned int /* cast for result of x2dev() */
+#define XDINDEV                                                                \
+    8 /* number of hex digits in an lsof                                       \
+       * device field -- should be                                             \
+       * 2 X sizeof(X2DEV_T) */
 
-
-#if	defined(LT_DIAL_aix)
+#if defined(LT_DIAL_aix)
 /*
  * AIX-specific items
  */
 
-#include <sys/sysmacros.h>
+#    include <sys/sysmacros.h>
 
-# if	defined(LT_AIXA) && LT_AIXA>=1
+#    if defined(LT_AIXA) && LT_AIXA >= 1
 
 /*
  * Note: the DEVNO64 and ISDEVNO54 #define's come from <sys/sysmacros.h>, but
  * only when _KERNEL is #define'd.
  */
 
-#undef	DEVNO64
-#define	DEVNO64		0x8000000000000000LL
-#undef	ISDEVNO64
-#define	ISDEVNO64(d)	(((ulong)(d) & DEVNO64) ? 1 : 0)
+#        undef DEVNO64
+#        define DEVNO64 0x8000000000000000LL
+#        undef ISDEVNO64
+#        define ISDEVNO64(d) (((ulong)(d)&DEVNO64) ? 1 : 0)
 
 /*
  * Define major and minor extraction macros that work on 64 bit AIX
  * architectures.
  */
 
-#define	major_S(d)	(ISDEVNO64(d) ? major64(d) : minor(d & ~SDEV_REMOTE))
-#define	minor_S(d)	(ISDEVNO64(d) ? (minor64(d) & ~SDEV_REMOTE) : minor(d))
-#undef	X2DEV_T
-#define	X2DEV_T		unsigned long long
-#undef	XDINDEV
-#define	XDINDEV		16
-#define	major_X(dp, em)	major_S(x2dev(dp, em))
-#define	minor_X(dp, em)	minor_S(x2dev(dp, em))
-# endif	/* defined(LT_AIXA) && LT_AIXA>=1 */
-
-#endif	/* defined(LT_DIAL_aix) */
+#        define major_S(d) (ISDEVNO64(d) ? major64(d) : minor(d & ~SDEV_REMOTE))
+#        define minor_S(d)                                                     \
+            (ISDEVNO64(d) ? (minor64(d) & ~SDEV_REMOTE) : minor(d))
+#        undef X2DEV_T
+#        define X2DEV_T unsigned long long
+#        undef XDINDEV
+#        define XDINDEV 16
+#        define major_X(dp, em) major_S(x2dev(dp, em))
+#        define minor_X(dp, em) minor_S(x2dev(dp, em))
+#    endif /* defined(LT_AIXA) && LT_AIXA>=1 */
 
+#endif /* defined(LT_DIAL_aix) */
 
-#if	defined(LT_DIAL_bsdi)
+#if defined(LT_DIAL_bsdi)
 /*
  * BSDI-specific items
  */
 
-#define	minor_S(dev)	dv_subunit(dev)
-#define	unit_S(dev)	dv_unit(dev)
-#define	minor_X(dp, em)	dv_subunit(x2dev(dp, em))
-#define	unit_X(dp, em)	dv_unit(x2dev(dp, em))
-#endif	/* defined(LT_DIAL_bsdi) */
-
+#    define minor_S(dev) dv_subunit(dev)
+#    define unit_S(dev) dv_unit(dev)
+#    define minor_X(dp, em) dv_subunit(x2dev(dp, em))
+#    define unit_X(dp, em) dv_unit(x2dev(dp, em))
+#endif /* defined(LT_DIAL_bsdi) */
 
-#if	defined(LT_DIAL_freebsd)
+#if defined(LT_DIAL_freebsd)
 /*
  *FreeBSD-specific items
-*/
-
-#undef	XDINDEV
-#define	XDINDEV		16
-# if	defined(LT_DEV64)
-#undef	X2DEV_T
-#define	X2DEV_T		unsigned long long
-#define	major_X(dp, em)	((int)((x2dev(dp, em) >> 32) & 0xffffffff))
-# endif	/* defined(LT_DEV64) */
-#endif	/* defined(LT_DIAL_freebsd) */
+ */
 
+#    undef XDINDEV
+#    define XDINDEV 16
+#    if defined(LT_DEV64)
+#        undef X2DEV_T
+#        define X2DEV_T unsigned long long
+#    endif /* defined(LT_DEV64) */
+#endif     /* defined(LT_DIAL_freebsd) */
 
-#if	defined(LT_DIAL_osr)
+#if defined(LT_DIAL_osr)
 /*
  * OpenUNIX-specific items
  */
 
-#include <sys/sysmacros.h>
-#endif	/* defined(LT_DIAL_osr) */
-
+#    include <sys/sysmacros.h>
+#endif /* defined(LT_DIAL_osr) */
 
-#if	defined(LT_DIAL_ou)
+#if defined(LT_DIAL_ou)
 /*
  * OpenUNIX-specific items
  */
 
-#include <sys/mkdev.h>
-#endif	/* defined(LT_DIAL_ou) */
+#    include <sys/mkdev.h>
+#endif /* defined(LT_DIAL_ou) */
 
-
-#if	defined(LT_DIAL_solaris)
+#if defined(LT_DIAL_solaris)
 /*
  * Solaris-specific items
  */
 
-#include <sys/sysmacros.h>
-
+#    include <sys/sysmacros.h>
 
 /*
  * Define maximum major device number in a stat(2) dev_t
  */
 
-# if	LT_VERS>=20501
-#define LT_MJX	L_MAXMAJ	/* Get maximum major device number from
-				 * <sys/sysmacros.h>. */
-# else	/* LT_VERS<20501 */
-#define	LT_MJX	0x3fff		/* Avoid <sys/sysmacros.h> when
-				 * Solaris < 2.5.1. */
-# endif /* LT_VERS>=20501 */
+#    if LT_VERS >= 20501
+#        define LT_MJX                                                         \
+            L_MAXMAJ /* Get maximum major device number from                   \
+                      * <sys/sysmacros.h>. */
+#    else            /* LT_VERS<20501 */
+#        define LT_MJX                                                         \
+            0x3fff /* Avoid <sys/sysmacros.h> when                             \
+                    * Solaris < 2.5.1. */
+#    endif         /* LT_VERS>=20501 */
 
-#define	major_S(dev)	((int)((dev >> L_BITSMINOR) & LT_MJX))
-#define	minor_S(dev)	((int)(dev & L_MAXMIN))
+#    define major_S(dev) ((int)((dev >> L_BITSMINOR) & LT_MJX))
+#    define minor_S(dev) ((int)(dev & L_MAXMIN))
 
-# if	defined(LT_K64)
+#    if defined(LT_DEV64)
 
-/*
- * Solaris 64 bit kernel
- */
+#        undef X2DEV_T
+#        define X2DEV_T unsigned long long
+#        undef XDINDEV
+#        define XDINDEV 16
+#    endif /* !defined(LT_DEV64) */
 
-#undef	X2DEV_T
-#define	X2DEV_T		unsigned long long
-#undef	XDINDEV
-#define	XDINDEV		16
+#    define major_X(dp, em) (major_S(x2dev(dp, em)))
+#    define minor_X(dp, em) (minor_S(x2dev(dp, em)))
 
-#define	major_X(dp, em)	((int)((x2dev(dp, em) >> 32) & 0xffffffff))
-#define	minor_X(dp, em) ((int)(x2dev(dp, em) & 0xffffffff))
-# else	/* !defined(LT_K64) */
+#endif /* defined(LT_DIAL_solaris) */
 
-/*
- * Solaris 32 bit kernel
- */
-
-#define	major_X(dp, em)	((int)((x2dev(dp, em) >> L_BITSMINOR) & LT_MJX))
-#define	minor_X(dp, em)	((int)(x2dev(dp, em) & L_MAXMIN))
-# endif	/* LT_K64 */
-#endif	/* defined(LT_DIAL_solaris) */
-
-
-#if	defined(LT_DIAL_uw)
+#if defined(LT_DIAL_uw)
 /*
  * UnixWare-specific items
  */
 
-#include <sys/mkdev.h>
-#endif	/* defined(LT_DIAL_uw) */
+#    include <sys/mkdev.h>
+#endif /* defined(LT_DIAL_uw) */
 
-#if	defined(LT_DIAL_linux)
+#if defined(LT_DIAL_linux)
 /*
  * Linux-specific items
  */
 
-#include <sys/sysmacros.h>
-#endif	/* defined(LT_DIAL_linux) */
-
+#    include <sys/sysmacros.h>
+#endif /* defined(LT_DIAL_linux) */
 
 /*
  * Global variables
  */
 
-int LsofFd = -1;			/* lsof pipe FD */
-FILE *LsofFs = (FILE *)NULL;		/* stream for lsof pipe FD */
-char *LsofPath = (char *)NULL;		/* path to lsof executable */
-pid_t LsofPid = (pid_t)0;		/* PID of lsof child process */
-int LTopt_h = 0;			/* "-h" option's switch value */
-char *LTopt_p = (char *)NULL;		/* "-p path" option's path value */
-int MsgStat = 0;			/* message status: 1 means prefix needs
-					 * to be issued */
-
+int LsofFd = -1;               /* lsof pipe FD */
+FILE *LsofFs = (FILE *)NULL;   /* stream for lsof pipe FD */
+char *LsofPath = (char *)NULL; /* path to lsof executable */
+pid_t LsofPid = (pid_t)0;      /* PID of lsof child process */
+int LTopt_h = 0;               /* "-h" option's switch value */
+char *LTopt_p = (char *)NULL;  /* "-p path" option's path value */
+int MsgStat = 0;               /* message status: 1 means prefix needs
+                                * to be issued */
 
 /*
  * Local static variables
  */
 
-static int Afo = 0;			/* Fo[] structures allocated */
-static char *GOv = (char *)NULL;	/* option `:' value pointer */
-static int GOx1 = 1;			/* first opt[][] index */
-static int GOx2 = 0;			/* second opt[][] index */
-static LTfldo_t *Fo = (LTfldo_t *)NULL;	/* allocated LTfldo_t structures */
-static int Ufo = 0;			/* Fo[] structures used */
-
+static int Afo = 0;                     /* Fo[] structures allocated */
+static char *GOv = (char *)NULL;        /* option `:' value pointer */
+static int GOx1 = 1;                    /* first opt[][] index */
+static int GOx2 = 0;                    /* second opt[][] index */
+static LTfldo_t *Fo = (LTfldo_t *)NULL; /* allocated LTfldo_t structures */
+static int Ufo = 0;                     /* Fo[] structures used */
 
 /*
  * Local function prototypes
  */
 
-_PROTOTYPE(static void closepipe,(void));
-_PROTOTYPE(static void getlsofpath,(void));
-_PROTOTYPE(static int GetOpt,(int ct, char *opt[], char *rules, char **em,
-			 char *pn));
-_PROTOTYPE(static X2DEV_T x2dev,(char *x, char **em));
-
+static void closepipe(void);
+static void getlsofpath(void);
+static int GetOpt(int ct, char *opt[], char *rules, char **em, char *pn);
+static X2DEV_T x2dev(char *x, char **em);
 
 /*
  * Default major, minor, and unit macros.
  */
 
-#if	!defined(major_S)
-#define	major_S		major
-#endif	/* defined(major_S) */
+#if !defined(major_S)
+#    define major_S major
+#endif /* defined(major_S) */
 
-#if	!defined(minor_S)
-#define	minor_S		minor
-#endif	/* defined(minor_S) */
+#if !defined(minor_S)
+#    define minor_S minor
+#endif /* defined(minor_S) */
 
-#if	!defined(unit_S)
-#define	unit_S(x)	0
-#endif	/* defined(unit_S) */
+#if !defined(unit_S)
+#    define unit_S(x) 0
+#endif /* defined(unit_S) */
 
-#if	!defined(major_X)
-#define	major_X(dp, em)	major(x2dev(dp, em))
-#endif	/* defined(major_X) */
+#if !defined(major_X)
+#    define major_X(dp, em) major(x2dev(dp, em))
+#endif /* defined(major_X) */
 
-#if	!defined(minor_X)
-#define	minor_X(dp, em)	minor(x2dev(dp, em))
-#endif	/* defined(minor_X) */
-
-#if	!defined(unit_X)
-#define	unit_X(dp, em)	0
-#endif	/* defined(unit_X) */
+#if !defined(minor_X)
+#    define minor_X(dp, em) minor(x2dev(dp, em))
+#endif /* defined(minor_X) */
 
+#if !defined(unit_X)
+#    define unit_X(dp, em) 0
+#endif /* defined(unit_X) */
 
 /*
  * CanRdKmem() -- can lsof read kernel memory devices?
  */
 
-char *
-CanRdKmem()
-{
-
-#if	defined(LT_KMEM)
-    char buf[2048];			/* temporary buffer */
-    char *dn;				/* memory device name */
-    char *em;				/* error message pointer */
-    int fd;				/* temporary file descriptor */
-    struct stat sb;			/* memory device stat(2) buffer */
-    int ti;				/* temporary integer */
-/*
- * Get the lsof path.  If it is not the default, check no further.
- */
-    (void) getlsofpath();
+char *CanRdKmem() {
+
+#if defined(LT_KMEM)
+    char buf[2048]; /* temporary buffer */
+    char *dn;       /* memory device name */
+    char *em;       /* error message pointer */
+    int fd;         /* temporary file descriptor */
+    struct stat sb; /* memory device stat(2) buffer */
+    int ti;         /* temporary integer */
+                    /*
+                     * Get the lsof path.  If it is not the default, check no further.
+                     */
+    (void)getlsofpath();
     if (!strcmp(LsofPath, LT_DEF_LSOF_PATH))
-	return((char *)NULL);
-/*
- * Check /dev/kmem access.
- */
+        return ((char *)NULL);
+    /*
+     * Check /dev/kmem access.
+     */
     dn = "/dev/kmem";
     if (stat(dn, &sb)) {
-	em = "stat";
+        em = "stat";
 
-kmem_error:
+    kmem_error:
 
-	(void) snprintf(buf, sizeof(buf) - 1,
-	    "ERROR!!!  can't %s(%s): %s\n", em, dn, strerror(errno));
-	buf[sizeof(buf) - 1] = '\0';
-	return(MkStrCpy(buf, &ti));
+        (void)snprintf(buf, sizeof(buf) - 1, "ERROR!!!  can't %s(%s): %s\n", em,
+                       dn, strerror(errno));
+        buf[sizeof(buf) - 1] = '\0';
+        return (MkStrCpy(buf, &ti));
     }
     if ((fd = open(dn, O_RDONLY, 0)) < 0) {
-	em = "open";
-	goto kmem_error;
+        em = "open";
+        goto kmem_error;
     }
-    (void) close(fd);
-/*
- * Check /dev/mem access.
- */
+    (void)close(fd);
+    /*
+     * Check /dev/mem access.
+     */
     dn = "/dev/mem";
     if (stat(dn, &sb)) {
 
-    /*
-     * If /dev/mem can't be found, ignore the error.
-     */
-	return((char *)NULL);
+        /*
+         * If /dev/mem can't be found, ignore the error.
+         */
+        return ((char *)NULL);
     }
     if ((fd = open(dn, O_RDONLY, 0)) < 0) {
-	em = "open";
-	goto kmem_error;
+        em = "open";
+        goto kmem_error;
     }
-    (void) close(fd);
-#endif	/* defined(LT_KMEM) */
+    (void)close(fd);
+#endif /* defined(LT_KMEM) */
 
-    return((char *)NULL);
+    return ((char *)NULL);
 }
 
-
 /*
  * closepipe() -- close pipe from lsof
  */
 
-static void
-closepipe()
-{
+static void closepipe() {
     if (LsofFd >= 0) {
 
-    /*
-     * A pipe from lsof is open.  Close it and the associated stream.
-     */
-	if (LsofFs) {
-	    (void) fclose(LsofFs);
-	    LsofFs = (FILE *)NULL;
-	}
-	(void) close(LsofFd);
-	LsofFd = -1;
+        /*
+         * A pipe from lsof is open.  Close it and the associated stream.
+         */
+        if (LsofFs) {
+            (void)fclose(LsofFs);
+            LsofFs = (FILE *)NULL;
+        }
+        (void)close(LsofFd);
+        LsofFd = -1;
     }
 }
 
-
 /*
  * ConvLsofDev() -- convert lsof device string
  *
  * Note: this function is dialect-specific.
  */
 
-char *
-ConvLsofDev(dev, ldev)
-    char *dev;			/* lsof device string -- the value to the
-				 * LSOF_FID_DEVN field of a LSOF_FID_FD block
-				 * (see lsof_fields.h) */
-    LTdev_t *ldev;		/* results are returned to this structure */
+char *ConvLsofDev(char *dev,     /* lsof device string -- the value to the
+                                  * LSOF_FID_DEVN field of a LSOF_FID_FD block
+                                  * (see lsof_fields.h) */
+                  LTdev_t *ldev) /* results are returned to this structure */
 {
-    char *dp;			/* device pointer */
-    char *em;			/* error message pointer */
-    int tlen;			/* temporary length */
-/*
- * Check function arguments.
- *
- * Establish values for decoding the device string.
- */
+    char *dp; /* device pointer */
+    char *em; /* error message pointer */
+    int tlen; /* temporary length */
+              /*
+               * Check function arguments.
+               *
+               * Establish values for decoding the device string.
+               */
     if (!dev)
-	return("ERROR!!!  no ConvLsofDev() device");
+        return ("ERROR!!!  no ConvLsofDev() device");
     if (!ldev)
-	return("ERROR!!!  no ConvLsofDev() result pointer");
+        return ("ERROR!!!  no ConvLsofDev() result pointer");
     if (strncmp(dev, "0x", 2))
-	return("ERROR!!!  no leading 0x in ConvLsofDev() device");
+        return ("ERROR!!!  no leading 0x in ConvLsofDev() device");
     dp = dev + 2;
     if (((tlen = (int)strlen(dp)) < 1) || (tlen > XDINDEV))
-	return("ERROR!!!  bad ConvLsofDev() device length");
-/*
- * Use the pre-defined *_X() macros to do the decomposition.
- */
+        return ("ERROR!!!  bad ConvLsofDev() device length");
+    /*
+     * Use the pre-defined *_X() macros to do the decomposition.
+     */
     ldev->maj = (unsigned int)major_X(dp, &em);
     if (em)
-	return(em);
+        return (em);
     ldev->min = (unsigned int)minor_X(dp, &em);
     if (em)
-	return(em);
+        return (em);
     ldev->unit = (unsigned int)unit_X(dp, &em);
-    return(em);
+    return (em);
 }
 
-
 /*
  * ConvStatDev() -- convert stat(2) device number
  *
  * Note: this function is dialect-specific.
  */
 
-char *
-ConvStatDev(dev, ldev)
-    dev_t *dev;			/* device number to be converted */
-    LTdev_t *ldev;		/* results are returned to this structure */
+char *ConvStatDev(dev_t *dev,    /* device number to be converted */
+                  LTdev_t *ldev) /* results are returned to this structure */
 {
 
-/*
- * Check function arguments.
- */
+    /*
+     * Check function arguments.
+     */
     if (!dev)
-	return("ERROR!!!  no ConvStatDev() device");
+        return ("ERROR!!!  no ConvStatDev() device");
     if (!ldev)
-	return("ERROR!!!  no ConvStatDev() result pointer");
-/*
- * Use the pre-defined *_S() macros to do the decomposition.
- */
+        return ("ERROR!!!  no ConvStatDev() result pointer");
+    /*
+     * Use the pre-defined *_S() macros to do the decomposition.
+     */
     ldev->maj = (unsigned int)major_S(*dev);
     ldev->min = (unsigned int)minor_S(*dev);
     ldev->unit = (unsigned int)unit_S(*dev);
-    return((char *)NULL);
+    return ((char *)NULL);
 }
 
-
 /*
  * ExecLsof() -- execute lsof with full field output and a NUL field terminator
  *		 in a child process
  */
 
-char *
-ExecLsof(opt)
-    char **opt;				/* lsof options -- a pointer to an
-					 * array of character pointers,
-					 * terminated by a NULL pointer */
+char *ExecLsof(char **opt) /* lsof options -- a pointer to an
+                            * array of character pointers,
+                            * terminated by a NULL pointer */
 {
-    static char **av = (char **)NULL;	/* lsof argument vector, dynamically
-					 * allocated */
-    static int ava = 0;			/* **av entries allocated */
-    char buf[2048];			/* temporary buffer */
-    char *em;				/* error message pointer */
-    int fd;				/* temporary file descriptor */
-    int optc;				/* option count */
-    int nf;				/* number of files */
-    int p[2];				/* pipe FDs */
-    char **tcpp;			/* temporary character pointer
-					 * pointer */
-    int ti;				/* temporary integer */
-    int tlen;				/* temporary length */
-    pid_t tpid;				/* temporary PID holder */
-/*
- * It's an error if lsof is already in execution or if no lsof options
- * were supplied.
- */
-    (void) getlsofpath();
+    static char **av = (char **)NULL; /* lsof argument vector, dynamically
+                                       * allocated */
+    static int ava = 0;               /* **av entries allocated */
+    char buf[2048];                   /* temporary buffer */
+    char *em;                         /* error message pointer */
+    int fd;                           /* temporary file descriptor */
+    int optc;                         /* option count */
+    int nf;                           /* number of files */
+    int p[2];                         /* pipe FDs */
+    char **tcpp;                      /* temporary character pointer
+                                       * pointer */
+    int ti;                           /* temporary integer */
+    int tlen;                         /* temporary length */
+    pid_t tpid;                       /* temporary PID holder */
+                                      /*
+                                       * It's an error if lsof is already in execution or if no lsof options
+                                       * were supplied.
+                                       */
+    (void)getlsofpath();
     if (LsofPid)
-	return("ERROR!!!  ExecLsof() says lsof is already in execution");
+        return ("ERROR!!!  ExecLsof() says lsof is already in execution");
     if (!opt)
-	return("ERROR!!!  no ExecLsof() option list");
+        return ("ERROR!!!  no ExecLsof() option list");
     for (optc = 0, tcpp = opt; *tcpp; optc++, tcpp++)
-	;
-/*
- * Make sure lsof is executable.
- */
+        ;
+    /*
+     * Make sure lsof is executable.
+     */
     if ((em = IsLsofExec()))
-	return(em);
-/*
- * Open a pipe through which lsof can return output.
- */
+        return (em);
+    /*
+     * Open a pipe through which lsof can return output.
+     */
     if (pipe(p)) {
-	(void) snprintf(buf, sizeof(buf) - 1,
-	    "ERROR!!!  can't open pipe: %s", strerror(errno));
-	return(MkStrCpy(buf, &ti));
+        (void)snprintf(buf, sizeof(buf) - 1, "ERROR!!!  can't open pipe: %s",
+                       strerror(errno));
+        return (MkStrCpy(buf, &ti));
     }
-/*
- * Allocate and build an argument vector.  The first entry will be set
- * to "lsof", the second to "-wFr", and the third to "-F0".  Additional
- * entries will be set as supplied by the caller.
- */
+    /*
+     * Allocate and build an argument vector.  The first entry will be set
+     * to "lsof", the second to "-wFr", and the third to "-F0".  Additional
+     * entries will be set as supplied by the caller.
+     */
     if ((optc + 4) > ava) {
-	tlen = (int)(sizeof(char *) * (optc + 4));
-	if (!av)
-	    av = (char **)malloc(tlen);
-	else
-	    av = (char **)realloc((void *)av, tlen);
-	if (!av) {
-	    (void) snprintf(buf, sizeof(buf) - 1,
-		"LTlib: ExecLsof() can't allocat pointers for %d arguments",
-		optc + 4);
-	    return(MkStrCpy(buf, &ti));
-	}
-	ava = optc + 4;
+        tlen = (int)(sizeof(char *) * (optc + 4));
+        if (!av)
+            av = (char **)malloc(tlen);
+        else
+            av = (char **)realloc((void *)av, tlen);
+        if (!av) {
+            (void)snprintf(
+                buf, sizeof(buf) - 1,
+                "LTlib: ExecLsof() can't allocate pointers for %d arguments",
+                optc + 4);
+            return (MkStrCpy(buf, &ti));
+        }
+        ava = optc + 4;
     }
     for (ti = 0, tcpp = opt; ti < (optc + 3); ti++) {
-	switch(ti) {
-	case 0:
-	    av[ti] = "lsof";
-	    break;
-	case 1:
-	    av[ti] = "-wFr";
-	    break;
-	case 2:
-	    av[ti] = "-F0";
-	    break;
-	default:
-	    av[ti] = *tcpp;
-	    tcpp++;
-	}
+        switch (ti) {
+        case 0:
+            av[ti] = "lsof";
+            break;
+        case 1:
+            av[ti] = "-wFr";
+            break;
+        case 2:
+            av[ti] = "-F0";
+            break;
+        default:
+            av[ti] = *tcpp;
+            tcpp++;
+        }
     }
     av[ti] = (char *)NULL;
-/*
- * Fork a child process to run lsof.
- */
-    switch((tpid = fork())) {
-    case (pid_t)0:
-
     /*
-     * This is the child process.
-     *
-     * First close all file descriptors except the output side of the pipe.
-     *
-     * Make the output side of the pipe STDOUT and STDERR.
+     * Fork a child process to run lsof.
      */
-	for (fd = 0, nf = getdtablesize(); fd < nf; fd++) {
-	    if (fd == p[1])
-		continue;
-	    (void) close(fd);
-	}
-	if (p[1] != 1)
-	    (void) dup2(p[1], 1);
-	if (p[1] != 2)
-	    (void) dup2(p[1], 2);
-	if ((p[1] != 1) && (p[1] != 2))
-	    (void) close(p[1]);
-    /*
-     * Execute lsof.
-     */
-	(void) execv(LsofPath, av);
-	_exit(0);				/* (Shouldn't get here.) */
+    switch ((tpid = fork())) {
+    case (pid_t)0:
+
+        /*
+         * This is the child process.
+         *
+         * First close all file descriptors except the output side of the pipe.
+         *
+         * Make the output side of the pipe STDOUT and STDERR.
+         */
+        for (fd = 0, nf = getdtablesize(); fd < nf; fd++) {
+            if (fd == p[1])
+                continue;
+            (void)close(fd);
+        }
+        if (p[1] != 1)
+            (void)dup2(p[1], 1);
+        if (p[1] != 2)
+            (void)dup2(p[1], 2);
+        if ((p[1] != 1) && (p[1] != 2))
+            (void)close(p[1]);
+        /*
+         * Execute lsof.
+         */
+        (void)execv(LsofPath, av);
+        _exit(0); /* (Shouldn't get here.) */
     case (pid_t)-1:
 
-    /*
-     * A fork error occurred.  Form and return a message.
-     */
-	(void) snprintf(buf, sizeof(buf) - 1,
-	    "ERROR!!!  ExecLsof() can't fork: %s", strerror(errno));
-	buf[sizeof(buf) - 1] = '\0';
-	return(MkStrCpy(buf, &ti));
+        /*
+         * A fork error occurred.  Form and return a message.
+         */
+        (void)snprintf(buf, sizeof(buf) - 1,
+                       "ERROR!!!  ExecLsof() can't fork: %s", strerror(errno));
+        buf[sizeof(buf) - 1] = '\0';
+        return (MkStrCpy(buf, &ti));
     default:
 
+        /*
+         * This is the parent.
+         *
+         * Save the lsof child PID.
+         *
+         * Close the output side of the pipe.
+         *
+         * Save the input side of the pipe as LsofFd; open a stream for it.
+         */
+        LsofPid = tpid;
+        (void)close(p[1]);
+        LsofFd = p[0];
+        if (!(LsofFs = fdopen(LsofFd, "r")))
+            return ("ERROR!!!  ExecLsof() can't open stream to lsof output FD");
+    }
     /*
-     * This is the parent.
-     *
-     * Save the lsof child PID.
-     *
-     * Close the output side of the pipe.
-     *
-     * Save the input side of the pipe as LsofFd; open a stream for it.
+     * Wait a bit for lsof to start and put something in its pipe, then return
+     * an "All is well." response.
      */
-	LsofPid = tpid;
-	(void) close(p[1]);
-	LsofFd = p[0];
-	if (!(LsofFs = fdopen(LsofFd, "r")))
-	    return("ERROR!!!  ExecLsof() can't open stream to lsof output FD");
-    }
-/*
- * Wait a bit for lsof to start and put something in its pipe, then return
- * an "All is well." response.
- */
     sleep(1);
-    return((char *)NULL);
+    return ((char *)NULL);
 }
 
-
 /*
  * getlsofpath() -- get lsof path, either from LT_LSOF_PATH in the environment
  *		    or from LT_DEF_LSOF_PATH
  */
 
-static void
-getlsofpath()
-{
-    char *tcp;				/* temporary character pointer */
-    int ti;				/* temporary integer */
+static void getlsofpath() {
+    char *tcp; /* temporary character pointer */
+    int ti;    /* temporary integer */
 
     if (LsofPath)
-	return;
+        return;
     if ((tcp = getenv("LT_LSOF_PATH")))
-	LsofPath = MkStrCpy(tcp, &ti);
+        LsofPath = MkStrCpy(tcp, &ti);
     else
-	LsofPath = LT_DEF_LSOF_PATH;
+        LsofPath = LT_DEF_LSOF_PATH;
 }
 
-
 /*
  * GetOpt() -- Local get option
  *
@@ -602,526 +556,498 @@ getlsofpath()
  * value doesn't have one -- e.g., has a default instead.
  */
 
-static int
-GetOpt(ct, opt, rules, em, pn)
-    int ct;				/* option count */
-    char *opt[];			/* options */
-    char *rules;			/* option rules */
-    char **em;				/* error message return */
-    char *pn;
-{
-    register int c;			/* character value */
-    register char *cp = (char *)NULL;	/* character pointer */
-    char embf[2048];			/* error message buffer */
-    int tlen;				/* temporary message length from
-					 * MkStrCpy() */
+static int GetOpt(int ct,      /* option count */
+                  char *opt[], /* options */
+                  char *rules, /* option rules */
+                  char **em,   /* error message return */
+                  char *pn) {
+    register int c;                   /* character value */
+    register char *cp = (char *)NULL; /* character pointer */
+    char embf[2048];                  /* error message buffer */
+    int tlen;                         /* temporary message length from
+                                       * MkStrCpy() */
 
     *em = (char *)NULL;
     if (GOx2 == 0) {
 
+        /*
+         * Move to a new entry of the option array.
+         *
+         * EOF if:
+         *
+         *	Option list has been exhausted;
+         *	Next option doesn't start with `-' or `+';
+         *	Next option has nothing but `-' or `+';
+         *	Next option is ``--'' or ``++''.
+         */
+        if (GOx1 >= ct || (opt[GOx1][0] != '-' && opt[GOx1][0] != '+') ||
+            !opt[GOx1][1])
+            return (EOF);
+        if (strcmp(opt[GOx1], "--") == 0 || strcmp(opt[GOx1], "++") == 0) {
+            GOx1++;
+            return (EOF);
+        }
+        GOx2 = 1;
+    }
     /*
-     * Move to a new entry of the option array.
-     *
-     * EOF if:
+     * Flag `:' option character as an error.
      *
-     *	Option list has been exhausted;
-     *	Next option doesn't start with `-' or `+';
-     *	Next option has nothing but `-' or `+';
-     *	Next option is ``--'' or ``++''.
+     * Check for a rule on this option character.
      */
-	if (GOx1 >= ct
-	||  (opt[GOx1][0] != '-' && opt[GOx1][0] != '+')
-	||  !opt[GOx1][1])
-	    return(EOF);
-	if (strcmp(opt[GOx1], "--") == 0 || strcmp(opt[GOx1], "++") == 0) {
-	    GOx1++;
-	    return(EOF);
-	}
-	GOx2 = 1;
-    }
-/*
- * Flag `:' option character as an error.
- *
- * Check for a rule on this option character.
- */
     if ((c = opt[GOx1][GOx2]) == ':') {
-	(void) snprintf(embf, sizeof(embf) - 1,
-	    "ERROR!!!  colon is an illegal option character.");
-	embf[sizeof(embf) - 1] = '\0';
-	*em = MkStrCpy(embf, &tlen);
+        (void)snprintf(embf, sizeof(embf) - 1,
+                       "ERROR!!!  colon is an illegal option character.");
+        embf[sizeof(embf) - 1] = '\0';
+        *em = MkStrCpy(embf, &tlen);
     } else if (!(cp = strchr(rules, c))) {
-	(void) snprintf(embf, sizeof(embf) - 1,
-	    "ERROR!!!  illegal option character: %c", c);
-	embf[sizeof(embf) - 1] = '\0';
-	*em = MkStrCpy(embf, &tlen);
+        (void)snprintf(embf, sizeof(embf) - 1,
+                       "ERROR!!!  illegal option character: %c", c);
+        embf[sizeof(embf) - 1] = '\0';
+        *em = MkStrCpy(embf, &tlen);
     }
     if (*em) {
 
-    /*
-     * An error was detected.
-     *
-     * Advance to the next option character.
-     *
-     * Return the character causing the error.
-     */
-	if (opt[GOx1][++GOx2] == '\0') {
-	    GOx1++;
-	    GOx2 = 0;
-	}
-	return(c);
+        /*
+         * An error was detected.
+         *
+         * Advance to the next option character.
+         *
+         * Return the character causing the error.
+         */
+        if (opt[GOx1][++GOx2] == '\0') {
+            GOx1++;
+            GOx2 = 0;
+        }
+        return (c);
     }
     if (*(cp + 1) == ':') {
 
+        /*
+         * The option may have a following value.  The caller decides if it
+         * does.
+         *
+         * Don't indicate that an option of ``--'' is a possible value.
+         *
+         * Finally, on the assumption that the caller will decide that the
+         * possible value belongs to the option, position to the option
+         * following the possible value, so that the next call to GetOpt() will
+         * find it.
+         */
+        if (opt[GOx1][GOx2 + 1] != '\0') {
+            GOv = &opt[GOx1++][GOx2];
+        } else if (++GOx1 >= ct)
+            GOv = (char *)NULL;
+        else {
+            GOv = opt[GOx1];
+            if (strcmp(GOv, "--") == 0)
+                GOv = (char *)NULL;
+            else
+                GOx1++;
+        }
+        GOx2 = 0;
+    } else {
+
+        /*
+         * The option character stands alone with no following value.
+         *
+         * Advance to the next option character.
+         */
+        if (opt[GOx1][++GOx2] == '\0') {
+            GOx2 = 0;
+            GOx1++;
+        }
+        GOv = (char *)NULL;
+    }
     /*
-     * The option may have a following value.  The caller decides if it does.
-     *
-     * Don't indicate that an option of ``--'' is a possible value.
-     *
-     * Finally, on the assumption that the caller will decide that the possible
-     * value belongs to the option, position to the option following the
-     * possible value, so that the next call to GetOpt() will find it.
-     */
-	if (opt[GOx1][GOx2 + 1] != '\0') {
-	    GOv = &opt[GOx1++][GOx2];
-	} else if (++GOx1 >= ct)
-	    GOv = (char *)NULL;
-	else {
-	    GOv = opt[GOx1];
-	    if (strcmp(GOv, "--") == 0)
-		GOv = (char *)NULL;
-	    else
-		GOx1++;
-	}
-	GOx2 = 0;
-     } else {
-
-    /*
-     * The option character stands alone with no following value.
-     *
-     * Advance to the next option character.
+     * Return the option character.
      */
-	if (opt[GOx1][++GOx2] == '\0') {
-	    GOx2 = 0;
-	    GOx1++;
-	}
-	GOv = (char *)NULL;
-    }
-/*
- * Return the option character.
- */
-    return(c);
+    return (c);
 }
 
-
 /*
  * IsLsofExec() -- see if lsof is executable
  */
 
-char *
-IsLsofExec()
-{
-    char buf[2048];			/* temporary buffer */
-    int len;				/* temporary length */
+char *IsLsofExec() {
+    char buf[2048]; /* temporary buffer */
+    int len;        /* temporary length */
 
-    (void) getlsofpath();
+    (void)getlsofpath();
     if (access(LsofPath, X_OK) < 0) {
-	(void) snprintf(buf, sizeof(buf) - 1,
-	    "ERROR!!!  can't execute %s: %s", LsofPath, strerror(errno));
-        return(MkStrCpy(buf, &len));
+        (void)snprintf(buf, sizeof(buf) - 1, "ERROR!!!  can't execute %s: %s",
+                       LsofPath, strerror(errno));
+        return (MkStrCpy(buf, &len));
     }
-    return((char *)NULL);
+    return ((char *)NULL);
 }
 
-
 /*
  * LTlibClean() -- clean up LTlib resource accesses
  */
 
-void
-LTlibClean()
-{
-    (void) StopLsof();
-}
-
+void LTlibClean() { (void)StopLsof(); }
 
 /*
  * MkStrCpy() -- make string copy
  */
 
-char *
-MkStrCpy(src, len)
-    char *src;			/* string source to copy */
-    int *len;			/* returned length allocation */
+char *MkStrCpy(char *src, /* string source to copy */
+               int *len)  /* returned length allocation */
 {
-    char *rp;			/* return pointer */
-    int srclen;			/* source string length */
+    char *rp;   /* return pointer */
+    int srclen; /* source string length */
 
     if (!src) {
-	(void) fprintf(stderr, "ERROR!!!  no string supplied to MkStrCpy()\n");
-	exit(1);
+        (void)fprintf(stderr, "ERROR!!!  no string supplied to MkStrCpy()\n");
+        exit(1);
     }
     srclen = (int)strlen(src);
     *len = srclen++;
     if (!(rp = (char *)malloc(srclen))) {
-	(void) fprintf(stderr, "ERROR!!!  MkStrCpy() -- no malloc() space");
-	exit(1);
+        (void)fprintf(stderr, "ERROR!!!  MkStrCpy() -- no malloc() space");
+        exit(1);
     }
-    (void) strcpy(rp, src);
-    return(rp);
+    (void)strcpy(rp, src);
+    return (rp);
 }
 
-
 /*
  * PrtMsg() -- print message
  */
 
-void
-PrtMsg(mp, pn)
-    char *mp;				/* message pointer -- may be NULL to
-					 * trigger space prefix initialization
-					 */
-    char *pn;				/* program name */
+void PrtMsg(mp, pn) char *mp; /* message pointer -- may be NULL to
+                               * trigger space prefix initialization
+                               */
+char *pn;                     /* program name */
 {
-    static int pfxlen = -1;		/* prefix length, based on program */
-					/* name -- computed on first call
-					 * when pfxlen == -1 */
-    static char *pfx = (char *)NULL;	/* prefix (spaces) */
-    int ti;				/* temporary index */
+    static int pfxlen = -1;          /* prefix length, based on program */
+                                     /* name -- computed on first call
+                                      * when pfxlen == -1 */
+    static char *pfx = (char *)NULL; /* prefix (spaces) */
+    int ti;                          /* temporary index */
 
     if (pfxlen == -1) {
 
+        /*
+         * This is the first call.  Compute the prefix length and build the
+         * prefix.
+         */
+        if (!pn)
+            pfxlen = 0;
+        else
+            pfxlen = (int)(strlen(pn));
+        pfxlen += (int)strlen(" ... ");
+        if (!(pfx = (char *)malloc(pfxlen + 1))) {
+            (void)printf("ERROR!!!  not enough space for %d space prefix\n",
+                         pfxlen);
+            exit(1);
+        }
+        for (ti = 0; ti < pfxlen; ti++) {
+            pfx[ti] = ' ';
+        }
+        pfx[pfxlen] = '\0';
+        MsgStat = 0;
+    }
     /*
-     * This is the first call.  Compute the prefix length and build the
-     * prefix.
+     * Process the message.
      */
-	if (!pn)
-	    pfxlen = 0;
-	else
-	    pfxlen = (int)(strlen(pn));
-	pfxlen += (int)strlen(" ... ");
-	if (!(pfx = (char *)malloc(pfxlen + 1))) {
-	    (void) printf( "ERROR!!!  not enough space for %d space prefix\n",
-		pfxlen);
-	    exit(1);
-	}
-	for (ti = 0; ti < pfxlen; ti++) {
-	    pfx[ti] = ' ';
-	}
-	pfx[pfxlen] = '\0';
-	MsgStat = 0;
-    }
-/*
- * Process the message.
- */
     if (MsgStat)
-	(void) printf("%s", pfx);
+        (void)printf("%s", pfx);
     if (mp && *mp) {
-	(void) printf("%s\n", mp);
-	MsgStat = 1;
+        (void)printf("%s\n", mp);
+        MsgStat = 1;
     }
 }
 
-
 /*
  * PrtMsgX() -- print message and exit
  */
 
-void
-PrtMsgX(mp, pn, f, xv)
-    char *mp;				/* message pointer */
-    char *pn;				/* program name */
-    void (*f)();			/* clean-up function pointer */
-    int xv;				/* exit value */
+void PrtMsgX(mp, pn, f, xv) char *mp; /* message pointer */
+char *pn;                             /* program name */
+void (*f)();                          /* clean-up function pointer */
+int xv;                               /* exit value */
 {
     if (mp)
-	PrtMsg(mp, pn);
+        PrtMsg(mp, pn);
     if (f)
-	(void) (*f)();
-    (void) LTlibClean();
+        (void)(*f)();
+    (void)LTlibClean();
     exit(xv);
 }
 
-
 /*
  * RdFrLsof() -- read from lsof
  */
 
-LTfldo_t *
-RdFrLsof(nf, em)
-    int *nf;				/* number of fields receiver */
-    char **em;				/* error message pointer receiver */
+LTfldo_t *RdFrLsof(int *nf,   /* number of fields receiver */
+                   char **em) /* error message pointer receiver */
 {
-    char buf[2048];			/* temporary buffer */
-    int bufl = (int)sizeof(buf);	/* size of buf[] */
-    char *blim = &buf[bufl - 1];	/* buf[] limit (last character
-					 * address) */
-    char *fsp;				/* field start pointer */
-    char *tcp;				/* temporary character pointer */
-    LTfldo_t *tfop;			/* temporary field output pointer */
-    int ti;				/* temporary index */
-    int tlen;				/* remporary length */
-    char *vp;				/* value character pointer */
-/*
- * Check for errors.
- */
+    char buf[2048];              /* temporary buffer */
+    int bufl = (int)sizeof(buf); /* size of buf[] */
+    char *blim = &buf[bufl - 1]; /* buf[] limit (last character
+                                  * address) */
+    char *fsp;                   /* field start pointer */
+    char *tcp;                   /* temporary character pointer */
+    LTfldo_t *tfop;              /* temporary field output pointer */
+    int ti;                      /* temporary index */
+    int tlen;                    /* remporary length */
+    char *vp;                    /* value character pointer */
+                                 /*
+                                  * Check for errors.
+                                  */
     if (!em)
-	return((LTfldo_t *)NULL);
+        return ((LTfldo_t *)NULL);
     if (!nf) {
-	*em = "ERROR!!!  RdFrLsof() not given a count return pointer";
-	return((LTfldo_t *)NULL);
+        *em = "ERROR!!!  RdFrLsof() not given a count return pointer";
+        return ((LTfldo_t *)NULL);
     }
     *em = (char *)NULL;
     *nf = 0;
-/*
- * If fields are in use, release their resources.
- */
+    /*
+     * If fields are in use, release their resources.
+     */
     for (ti = 0, tfop = Fo; (ti < Ufo); ti++, tfop++) {
-	if (tfop->v)
-	    (void) free((void *)tfop->v);
+        if (tfop->v)
+            (void)free((void *)tfop->v);
     }
     Ufo = 0;
-/*
- * Read a line from lsof.
- */
-    if (!fgets(buf, bufl - 2, LsofFs)) {
-
     /*
-     * An lsof pipe EOF has been reached.  Indicate that with a NULL
-     * pointer return, coupled with a NULL error message return pointer
-     * (set above), and a field count of zero (set above).
+     * Read a line from lsof.
      */
-	return((LTfldo_t *)NULL);
-    }
-/*
- * Parse the lsof line, allocating field output structures as appropriate.
- *
- * It is expected that fields will end in a NUL ('\0') or a NL ('\0') and
- * that a NL ends all fields in the lsof line.
- */
-    for (tcp = buf, Ufo = 0; (*tcp != '\n') && (tcp < blim); tcp++) {
+    if (!fgets(buf, bufl - 2, LsofFs)) {
 
+        /*
+         * An lsof pipe EOF has been reached.  Indicate that with a NULL
+         * pointer return, coupled with a NULL error message return pointer
+         * (set above), and a field count of zero (set above).
+         */
+        return ((LTfldo_t *)NULL);
+    }
     /*
-     * Start a new field.  The first character is the LSOF_FID_*.
+     * Parse the lsof line, allocating field output structures as appropriate.
      *
-     * First allocate an LTfldo_t structure.
+     * It is expected that fields will end in a NUL ('\0') or a NL ('\0') and
+     * that a NL ends all fields in the lsof line.
      */
-	if (Ufo >= Afo) {
-
-	/*
-	 * More LTfldo_t space is required.
-	 */
-	     Afo += LT_FLDO_ALLOC;
-	     tlen = (int)(Afo * sizeof(LTfldo_t));
-	     if (Fo)
-		Fo = (LTfldo_t *)realloc(Fo, tlen);
-	     else
-		Fo = (LTfldo_t *)malloc(tlen);
-	    if (!Fo) {
-
-	    /*
-	     * A serious error has occurred; no LTfldo_t space is available.
-	     */
-		(void) snprintf(buf, bufl,
-		    "ERROR!!!  RdFrLsof() can't allocate %d pointer bytes",
-		    tlen);
-		*em = MkStrCpy(buf, &ti);
-		*nf = -1;
-		return((LTfldo_t *)NULL);
-	    }
-	}
-	tfop = Fo + Ufo;
-	tfop->v = (char *)NULL;
-	Ufo++;
+    for (tcp = buf, Ufo = 0; (*tcp != '\n') && (tcp < blim); tcp++) {
+
+        /*
+         * Start a new field.  The first character is the LSOF_FID_*.
+         *
+         * First allocate an LTfldo_t structure.
+         */
+        if (Ufo >= Afo) {
+
+            /*
+             * More LTfldo_t space is required.
+             */
+            Afo += LT_FLDO_ALLOC;
+            tlen = (int)(Afo * sizeof(LTfldo_t));
+            if (Fo)
+                Fo = (LTfldo_t *)realloc(Fo, tlen);
+            else
+                Fo = (LTfldo_t *)malloc(tlen);
+            if (!Fo) {
+
+                /*
+                 * A serious error has occurred; no LTfldo_t space is available.
+                 */
+                (void)snprintf(
+                    buf, bufl,
+                    "ERROR!!!  RdFrLsof() can't allocate %d pointer bytes",
+                    tlen);
+                *em = MkStrCpy(buf, &ti);
+                *nf = -1;
+                return ((LTfldo_t *)NULL);
+            }
+        }
+        tfop = Fo + Ufo;
+        tfop->v = (char *)NULL;
+        Ufo++;
+        /*
+         * Save the LSOF_FID_* character.  Then compute the field value length,
+         * and make a copy of it.
+         */
+        tfop->ft = *tcp++;
+        fsp = tcp;
+        tlen = 0;
+        while (*tcp && (*tcp != '\n') && (tcp < blim)) {
+            tcp++;
+            tlen++;
+        }
+        if (!(vp = (char *)malloc(tlen + 1))) {
+
+            /*
+             * A serious error has occurred; there's no space for the field
+             * value.
+             */
+            (void)snprintf(buf, bufl,
+                           "ERROR!!!  RdFrLsof() can't allocate %d field bytes",
+                           tlen + 1);
+            *em = MkStrCpy(buf, &ti);
+            *nf = -1;
+            return ((LTfldo_t *)NULL);
+        }
+        (void)memcpy((void *)vp, (void *)fsp, tlen);
+        vp[tlen] = '\0';
+        tfop->v = vp;
+        if (*tcp == '\n')
+            break;
+        if (tcp >= blim) {
+
+            /*
+             * The lsof line has no NL terminator; that's an error.
+             */
+            *em = "ERROR!!! RdFrLsof() didn't find a NL";
+            *nf = -1;
+            return ((LTfldo_t *)NULL);
+        }
+    }
     /*
-     * Save the LSOF_FID_* character.  Then compute the field value length,
-     * and make a copy of it.
+     * The end of the lsof line has been reached.  If no fields were assembled,
+     * return an error indicate.  Otherwise return the fields and their count.
      */
-	tfop->ft = *tcp++;
-	fsp = tcp;
-	tlen = 0;
-	while (*tcp && (*tcp != '\n') && (tcp < blim)) {
-	     tcp++;
-	     tlen++;
-	}
-	if (!(vp = (char *)malloc(tlen + 1))) {
-
-	/*
-	 * A serious error has occurred; there's no space for the field value.
-	 */
-	    (void) snprintf(buf, bufl,
-		"ERROR!!!  RdFrLsof() can't allocate %d field bytes", tlen + 1);
-	    *em = MkStrCpy(buf, &ti);
-	    *nf = -1;
-	    return((LTfldo_t *)NULL);
-	}
-	(void) memcpy((void *)vp, (void *)fsp, tlen);
-	vp[tlen] = '\0';
-	tfop->v = vp;
-	if (*tcp == '\n')
-	    break;
-	if (tcp >= blim) {
-
-	/*
-	 * The lsof line has no NL terminator; that's an error.
-	 */
-	    *em = "ERROR!!! RdFrLsof() didn't find a NL";
-	    *nf = -1;
-	    return((LTfldo_t *)NULL);
-	}
-    }
-/*
- * The end of the lsof line has been reached.  If no fields were assembled,
- * return an error indicate.  Otherwise return the fields and their count.
- */
     if (!Ufo) {
-	*em = "ERROR!!! RdFrLsof() read an empty lsof line";
-	*nf = -1;
-	return((LTfldo_t *)NULL);
+        *em = "ERROR!!! RdFrLsof() read an empty lsof line";
+        *nf = -1;
+        return ((LTfldo_t *)NULL);
     }
     *nf = Ufo;
     *em = (char *)NULL;
-    return(Fo);
+    return (Fo);
 }
 
-
 /*
  * ScanArg() -- scan arguments
  */
 
-int
-ScanArg(ac, av, opt, pn)
-    int ac;				/* argument count */
-    char *av[];				/* argument pointers */
-    char *opt;				/* option string */
-    char *pn;				/* program name */
+int ScanArg(int ac,     /* argument count */
+            char *av[], /* argument pointers */
+            char *opt,  /* option string */
+            char *pn)   /* program name */
 {
-    char *em;				/* pointer to error message returned by
-					 * GetOpt() */
-    char embf[2048];			/* error message buffer */
-    int rv = 0;				/* return value */
-    int tc;				/* temporary character value */
-/*
- * Preset possible argument values.
- */
+    char *em;        /* pointer to error message returned by
+                      * GetOpt() */
+    char embf[2048]; /* error message buffer */
+    int rv = 0;      /* return value */
+    int tc;          /* temporary character value */
+                     /*
+                      * Preset possible argument values.
+                      */
     LTopt_h = 0;
     if (LTopt_p) {
-	(void) free((void *)LTopt_p);
-	LTopt_p = (char *)NULL;
+        (void)free((void *)LTopt_p);
+        LTopt_p = (char *)NULL;
     }
-/*
- * Process the options according to the supplied option string.
- */
+    /*
+     * Process the options according to the supplied option string.
+     */
     while ((tc = GetOpt(ac, av, opt, &em, pn)) != EOF) {
-	if (em) {
-	    rv = 1;
-	    PrtMsg(em, pn);
-	    continue;
-	}
-	switch (tc) {
-	case 'h':
-	    LTopt_h = 1;
-	    break;
-	case 'p':
-	    if (!GOv || *GOv == '-' || *GOv == '+') {
-		rv = 1;
-		(void) PrtMsg("ERROR!!!  -p not followed by a path", pn);
-	    } else
-		LTopt_p = GOv;
-	    break;
-	default:
-	    rv = 1;
-	    (void) snprintf(embf, sizeof(embf) - 1,
-		"ERROR!!!  unknown option: %c", tc);
-	    PrtMsg(embf, pn);
-	}
+        if (em) {
+            rv = 1;
+            PrtMsg(em, pn);
+            continue;
+        }
+        switch (tc) {
+        case 'h':
+            LTopt_h = 1;
+            break;
+        case 'p':
+            if (!GOv || *GOv == '-' || *GOv == '+') {
+                rv = 1;
+                (void)PrtMsg("ERROR!!!  -p not followed by a path", pn);
+            } else
+                LTopt_p = GOv;
+            break;
+        default:
+            rv = 1;
+            (void)snprintf(embf, sizeof(embf) - 1,
+                           "ERROR!!!  unknown option: %c", tc);
+            PrtMsg(embf, pn);
+        }
     }
     for (; GOx1 < ac; GOx1++) {
 
-    /*
-     * Report extraneous arguments.
-     */
-	rv = 1;
-	(void) snprintf(embf, sizeof(embf) - 1,
-	    "ERROR!!!  extraneous option: \"%s\"", av[GOx1]);
-	PrtMsg(embf, pn);
+        /*
+         * Report extraneous arguments.
+         */
+        rv = 1;
+        (void)snprintf(embf, sizeof(embf) - 1,
+                       "ERROR!!!  extraneous option: \"%s\"", av[GOx1]);
+        PrtMsg(embf, pn);
     }
-    return(rv);
+    return (rv);
 }
 
-
 /*
  * StopLsof() -- stop a running lsof process and close the pipe from it
  */
 
-void
-StopLsof()
-{
+void StopLsof() {
     pid_t pid;
 
     if (LsofPid) {
 
-    /*
-     * An lsof child process may be active.  Wait for (or kill) it.
-     */
-	pid = wait3(NULL, WNOHANG, NULL);
-	if (pid != LsofPid) {
-	    (void) kill(LsofPid, SIGKILL);
-	    sleep(2);
-	    pid = wait3(NULL, WNOHANG, NULL);
-	}
-	LsofPid = (pid_t)0;
+        /*
+         * An lsof child process may be active.  Wait for (or kill) it.
+         */
+        pid = wait3(NULL, WNOHANG, NULL);
+        if (pid != LsofPid) {
+            (void)kill(LsofPid, SIGKILL);
+            sleep(2);
+            pid = wait3(NULL, WNOHANG, NULL);
+        }
+        LsofPid = (pid_t)0;
     }
-    (void) closepipe();
+    (void)closepipe();
 }
 
-
 /*
  * x2dev() -- convert hex string to device number
  */
 
-static X2DEV_T
-x2dev(x, em)
-    char *x;				/* hex string */
-    char **em;				/* error message receiver */
+static X2DEV_T x2dev(char *x,   /* hex string */
+                     char **em) /* error message receiver */
 {
-    char buf[2048];			/* temporary message buffer */
-    int c;				/* character holder */
-    X2DEV_T dev;			/* device number result */
-    char *wx;				/* working hex string pointer */
-    int xl;				/* hex string length */
+    char buf[2048]; /* temporary message buffer */
+    int c;          /* character holder */
+    X2DEV_T dev;    /* device number result */
+    char *wx;       /* working hex string pointer */
+    int xl;         /* hex string length */
 
     if (!x || !*x) {
-	*em = "ERROR!!!  no hex string supplied to x2dev()";
-	return(0);
+        *em = "ERROR!!!  no hex string supplied to x2dev()";
+        return (0);
     }
     wx = strncasecmp(x, "0x", 2) ? x : (x + 2);
     if (((xl = (int)strlen(wx)) < 1) || (xl > XDINDEV)) {
-	(void) snprintf(buf, sizeof(buf) - 1,
-	    "ERROR!!!  x2dev(\"%s\") bad length: %d", x, xl + 2);
-	buf[sizeof(buf) - 1] = '\0';
-	*em = MkStrCpy(buf, &c);
-	return(0);
+        (void)snprintf(buf, sizeof(buf) - 1,
+                       "ERROR!!!  x2dev(\"%s\") bad length: %d", x, xl + 2);
+        buf[sizeof(buf) - 1] = '\0';
+        *em = MkStrCpy(buf, &c);
+        return (0);
     }
-/*
- * Assemble the device number result from the hex string.
- */
+    /*
+     * Assemble the device number result from the hex string.
+     */
     for (dev = (X2DEV_T)0; *wx; wx++) {
-	if (isdigit((unsigned char)*wx)) {
-	    dev = (dev << 4) | (unsigned int)(((int)*wx - (int)'0') & 0xf);
-	    continue;
-	}
-	c = (int) tolower((unsigned char)*wx);
-	if ((c >= (int)'a') && (c <= (int)'f')) {
-	    dev = (dev << 4) | (unsigned int)((c - 'a' + 10) & 0xf);
-	    continue;
-	}
-	(void) snprintf(buf, sizeof(buf) - 1,
-	    "ERROR!!!  x2dev(\"%s\") non-hex character: %c", x, c);
-	*em = MkStrCpy(buf, &c);
+        if (isdigit((unsigned char)*wx)) {
+            dev = (dev << 4) | (unsigned int)(((int)*wx - (int)'0') & 0xf);
+            continue;
+        }
+        c = (int)tolower((unsigned char)*wx);
+        if ((c >= (int)'a') && (c <= (int)'f')) {
+            dev = (dev << 4) | (unsigned int)((c - 'a' + 10) & 0xf);
+            continue;
+        }
+        (void)snprintf(buf, sizeof(buf) - 1,
+                       "ERROR!!!  x2dev(\"%s\") non-hex character: %c", x, c);
+        *em = MkStrCpy(buf, &c);
     }
-/*
- * Return result and no error indication.
- */
+    /*
+     * Return result and no error indication.
+     */
     *em = (char *)NULL;
-    return(dev);
+    return (dev);
 }
diff --git a/tests/LTlock.c b/tests/LTlock.c
index b030630..60aa0f3 100644
--- a/tests/LTlock.c
+++ b/tests/LTlock.c
@@ -5,7 +5,6 @@
  * Purdue University
  */
 
-
 /*
  * Copyright 2002 Purdue Research Foundation, West Lafayette, Indiana
  * 47907.  All rights reserved.
@@ -32,34 +31,26 @@
  * 4. This notice may not be removed or altered.
  */
 
-#ifndef lint
-static char copyright[] =
-"@(#) Copyright 2002 Purdue Research Foundation.\nAll rights reserved.\n";
-#endif
-
 #include "LsofTest.h"
 #include "lsof_fields.h"
 
-
-#if	defined(LT_DIAL_aix)
+#if defined(LT_DIAL_aix)
 /*
  * AIX-specific items
  */
 
-#define	USE_FCNTL
-#endif	/* defined(LT_DIAL_aix) */
+#    define USE_FCNTL
+#endif /* defined(LT_DIAL_aix) */
 
-
-#if	defined(LT_DIAL_bsdi)
+#if defined(LT_DIAL_bsdi)
 /*
  * BSDI-specific items
  */
 
-#define	USE_FCNTL
-#endif	/* defined(LT_DIAL_bsdi) */
-
+#    define USE_FCNTL
+#endif /* defined(LT_DIAL_bsdi) */
 
-#if	defined(LT_DIAL_darwin)
+#if defined(LT_DIAL_darwin)
 /*
  * Darwin-specific items
  */
@@ -68,702 +59,681 @@ static char copyright[] =
  * There is no Darwin USE_* definition, because lock support in lsof for
  * Darwin is inadequate for this test.
  */
-#endif	/* defined(LT_DIAL_darwin) */
-
+#endif /* defined(LT_DIAL_darwin) */
 
-#if	defined(LT_DIAL_du)
+#if defined(LT_DIAL_du)
 /*
  * DEC_OSF/1|Digital_UNIX|Tru64_UNIX-specific items
  */
 
-#define	USE_FCNTL
-#endif	/* defined(LT_DIAL_du) */
+#    define USE_FCNTL
+#endif /* defined(LT_DIAL_du) */
 
-
-#if	defined(LT_DIAL_freebsd)
+#if defined(LT_DIAL_freebsd)
 /*
  * FreeBSD-specific items
  */
 
-#define	USE_FCNTL
-#endif	/* defined(LT_DIAL_freebsd) */
-
+#    define USE_FCNTL
+#endif /* defined(LT_DIAL_freebsd) */
 
-#if	defined(LT_DIAL_linux)
+#if defined(LT_DIAL_linux)
 /*
  * Linux-specific items
  */
 
-#define	USE_FCNTL
-#endif	/* defined(LT_DIAL_linux) */
-
+#    define USE_FCNTL
+#endif /* defined(LT_DIAL_linux) */
 
-#if	defined(LT_DIAL_netbsd)
+#if defined(LT_DIAL_netbsd)
 /*
  * NetBSD-specific items
  */
 
-#define	USE_FCNTL
-#endif	/* defined(LT_DIAL_netbsd) */
+#    define USE_FCNTL
+#endif /* defined(LT_DIAL_netbsd) */
 
-
-#if	defined(LT_DIAL_openbsd)
+#if defined(LT_DIAL_openbsd)
 /*
  * OpenBSD-specific items
  */
 
-#define	USE_FCNTL
-#endif	/* defined(LT_DIAL_openbsd) */
-
+#    define USE_FCNTL
+#endif /* defined(LT_DIAL_openbsd) */
 
-#if	defined(LT_DIAL_hpux)
+#if defined(LT_DIAL_hpux)
 /*
  * HP-UX-specific items
  */
 
-#define	USE_FCNTL
-#endif	/* defined(LT_DIAL_hpux) */
-
+#    define USE_FCNTL
+#endif /* defined(LT_DIAL_hpux) */
 
-#if	defined(LT_DIAL_ns)
+#if defined(LT_DIAL_ns)
 /*
  * NEXTSTEP-specific items
  */
 
-#define	USE_FLOCK
-#endif	/* defined(LT_DIAL_ns) */
+#    define USE_FLOCK
+#endif /* defined(LT_DIAL_ns) */
 
-
-#if	defined(LT_DIAL_osr)
+#if defined(LT_DIAL_osr)
 /*
  * OSR-specific items
  */
 
-#define	USE_FCNTL
-#endif	/* defined(LT_DIAL_osr) */
-
+#    define USE_FCNTL
+#endif /* defined(LT_DIAL_osr) */
 
-#if	defined(LT_DIAL_ou)
+#if defined(LT_DIAL_ou)
 /*
  * OpenUNIX-specific items
  */
 
-#define	USE_FCNTL
-#endif	/* defined(LT_DIAL_ou) */
-
+#    define USE_FCNTL
+#endif /* defined(LT_DIAL_ou) */
 
-#if	defined(LT_DIAL_openbsd)
+#if defined(LT_DIAL_openbsd)
 /*
  * OpenBSD-specific items
  */
 
-#define	USE_FCNTL
-#endif	/* defined(LT_DIAL_openbsd) */
+#    define USE_FCNTL
+#endif /* defined(LT_DIAL_openbsd) */
 
-
-#if	defined(LT_DIAL_solaris)
+#if defined(LT_DIAL_solaris)
 /*
  * Solaris-specific items
  */
 
-#define	USE_FCNTL
-#endif	/* defined(solaris) */
-
+#    define USE_FCNTL
+#endif /* defined(solaris) */
 
-#if	defined(LT_DIAL_uw)
+#if defined(LT_DIAL_uw)
 /*
  * UnixWare-specific items
  */
 
-#define	USE_FCNTL
-#endif	/* defined(LT_DIAL_uw) */
-
+#    define USE_FCNTL
+#endif /* defined(LT_DIAL_uw) */
 
-#if	!defined(USE_FLOCK) && !defined(USE_FCNTL)
+#if !defined(USE_FLOCK) && !defined(USE_FCNTL)
 /*
  * Here begins the version of this program for dialects that don't support
  * flock() or fcntl() locking.
  */
 
-
 /*
  * Main program for dialects that don't support flock() of fcntl() locking.
  */
 
-int
-main(argc, argv)
-	int argc;			/* argument count */
-	char *argv[];			/* arguments */
+int main(int argc,     /* argument count */
+         char *argv[]) /* arguments */
 {
-    char *pn;			/* program name */
-/*
- * Get program name and issue error message.
- */
+    char *pn; /* program name */
+              /*
+               * Get program name and issue error message.
+               */
     if ((pn = (char *)strrchr(argv[0], '/')))
-	pn++;
+        pn++;
     else
-	pn = argv[0];
-    (void) printf("%s ... %s\n", pn, LT_DONT_DO_TEST);
-    return(0);
+        pn = argv[0];
+    (void)printf("%s ... %s\n", pn, LT_DONT_DO_TEST);
+    return (0);
 }
-#else	/* defined(USE_FLOCK) || defined(USE_FCNTL) */
-
+#else /* defined(USE_FLOCK) || defined(USE_FCNTL) */
 
 /*
  * Local definitions
  */
 
-#define	FULL_EX_LOCK	0	/* get a full file exclusive lock */
-#define	FULL_SH_LOCK	1	/* get a full file shared lock */
-#define	PART_EX_LOCK	2	/* get a partial file exclusive lock */
-#define	PART_SH_LOCK	3	/* get a partial file shared lock */
-
+#    define FULL_EX_LOCK 0 /* get a full file exclusive lock */
+#    define FULL_SH_LOCK 1 /* get a full file shared lock */
+#    define PART_EX_LOCK 2 /* get a partial file exclusive lock */
+#    define PART_SH_LOCK 3 /* get a partial file shared lock */
 
 /*
  * Globals
  */
 
-int Fd = -1;			/* test file descriptor; open if >= 0 */
-pid_t MyPid = (pid_t)0;		/* PID of this process */
-char *Path = (char *)NULL;	/* test file path; none if NULL */
-char *Pn = (char *)NULL;	/* program name */
-
+int Fd = -1;               /* test file descriptor; open if >= 0 */
+pid_t MyPid = (pid_t)0;    /* PID of this process */
+char *Path = (char *)NULL; /* test file path; none if NULL */
+char *Pn = (char *)NULL;   /* program name */
 
 /*
  * Local function prototypes
  */
 
-_PROTOTYPE(static void cleanup,(void));
-_PROTOTYPE(static char *lkfile,(int ty));
-_PROTOTYPE(static char *tstwlsof,(char *opt, char *xlk));
-_PROTOTYPE(static char *unlkfile,(int ty));
-
+static void cleanup(void);
+static char *lkfile(int ty);
+static char *tstwlsof(char *opt, char *xlk);
+static char *unlkfile(int ty);
 
 /*
  * Main program for dialects that support locking tests.
  */
 
-int
-main(argc, argv)
-    int argc;				/* argument count */
-    char *argv[];			/* arguments */
+int main(int argc,     /* argument count */
+         char *argv[]) /* arguments */
 {
-    char buf[2048];			/* temporary buffer */
-    char *em;				/* error message pointer */
-    int ti;				/* temporary index */
-    char *tcp;				/* temporary character pointer */
-    int tlen;				/* temporary length -- e.g., as
-					 * returned by MkStrCpy() */
-    char *tstR = (char *)NULL;		/* "R" lock test result */
-    char *tstr = (char *)NULL;		/* "r" lock test result */
-    char *tstW = (char *)NULL;		/* "W" lock test result */
-    char *tstw = (char *)NULL;		/* "w" lock test result */
-    int xv = 0;				/* exit value */
-/*
- * Get program name and PID, issue start message, and build space prefix.
- */
+    char buf[2048];            /* temporary buffer */
+    char *em;                  /* error message pointer */
+    int ti;                    /* temporary index */
+    char *tcp;                 /* temporary character pointer */
+    int tlen;                  /* temporary length -- e.g., as
+                                * returned by MkStrCpy() */
+    char *tstR = (char *)NULL; /* "R" lock test result */
+    char *tstr = (char *)NULL; /* "r" lock test result */
+    char *tstW = (char *)NULL; /* "W" lock test result */
+    char *tstw = (char *)NULL; /* "w" lock test result */
+    int xv = 0;                /* exit value */
+                               /*
+                                * Get program name and PID, issue start message, and build space prefix.
+                                */
     if ((Pn = strrchr(argv[0], '/')))
-	Pn++;
+        Pn++;
     else
-	Pn = argv[0];
+        Pn = argv[0];
     MyPid = getpid();
-    (void) printf("%s ... ", Pn);
-    (void) fflush(stdout);
-    (void) PrtMsg((char *)NULL, Pn);
-/*
- * Process arguments.
- */
+    (void)printf("%s ... ", Pn);
+    (void)fflush(stdout);
+    (void)PrtMsg((char *)NULL, Pn);
+    /*
+     * Process arguments.
+     */
     if (ScanArg(argc, argv, "hp:", Pn))
-	xv = 1;
+        xv = 1;
     if (xv || LTopt_h) {
-	(void) PrtMsg ("usage: [-h] [-p path]", Pn);
-	(void) PrtMsg ("       -h       print help (this panel)", Pn);
-	(void) PrtMsgX("       -p path  define test file path", Pn, cleanup,
-		       xv);
+        (void)PrtMsg("usage: [-h] [-p path]", Pn);
+        (void)PrtMsg("       -h       print help (this panel)", Pn);
+        (void)PrtMsgX("       -p path  define test file path", Pn, cleanup, xv);
     }
-/*
- * See if lsof can be executed and can access kernel memory.
- */
+    /*
+     * See if lsof can be executed and can access kernel memory.
+     */
     if ((em = IsLsofExec()))
-	(void) PrtMsgX(em, Pn, cleanup, 1);
+        (void)PrtMsgX(em, Pn, cleanup, 1);
     if ((em = CanRdKmem()))
-	(void) PrtMsgX(em, Pn, cleanup, 1);
-/*
- * If a path was supplied in an "-p path" option, use it.  Otherwise construct
- * a path in the CWD.
- */
+        (void)PrtMsgX(em, Pn, cleanup, 1);
+    /*
+     * If a path was supplied in an "-p path" option, use it.  Otherwise
+     * construct a path in the CWD.
+     */
     if (!(Path = LTopt_p)) {
-	(void) snprintf(buf, sizeof(buf), "./config.LTlock%ld",
-	(long)MyPid);
-	buf[sizeof(buf) - 1] = '\0';
-	Path = MkStrCpy(buf, &tlen);
+        (void)snprintf(buf, sizeof(buf), "./config.LTlock%ld", (long)MyPid);
+        buf[sizeof(buf) - 1] = '\0';
+        Path = MkStrCpy(buf, &tlen);
     }
-/*
- * Fill buffer for writing to the test file.
- */
+    /*
+     * Fill buffer for writing to the test file.
+     */
     for (ti = 0; ti < sizeof(buf); ti++) {
-	buf[ti] = (char)(ti & 0xff);
+        buf[ti] = (char)(ti & 0xff);
     }
-/*
- * Open a new test file at the specified path.
- */
-    (void) unlink(Path);
-    if ((Fd = open(Path, O_RDWR|O_CREAT, 0600)) < 0) {
-	(void) fprintf(stderr, "ERROR!!!  can't open %s\n", Path);
-
-print_file_error:
-
-	MsgStat = 1;
-	(void) snprintf(buf, sizeof(buf) - 1, "      Errno %d: %s",
-	    errno, strerror(errno));
-	buf[sizeof(buf) - 1] = '\0';
-	(void) PrtMsgX(buf, Pn, cleanup, 1);
+    /*
+     * Open a new test file at the specified path.
+     */
+    (void)unlink(Path);
+    if ((Fd = open(Path, O_RDWR | O_CREAT, 0600)) < 0) {
+        (void)fprintf(stderr, "ERROR!!!  can't open %s\n", Path);
+
+    print_file_error:
+
+        MsgStat = 1;
+        (void)snprintf(buf, sizeof(buf) - 1, "      Errno %d: %s", errno,
+                       strerror(errno));
+        buf[sizeof(buf) - 1] = '\0';
+        (void)PrtMsgX(buf, Pn, cleanup, 1);
     }
-/*
- * Write a buffer load at the beginning of the file.
- */
+    /*
+     * Write a buffer load at the beginning of the file.
+     */
     if (write(Fd, buf, sizeof(buf)) != sizeof(buf)) {
-	(void) fprintf(stderr,
-	    "ERROR!!!  can't write %d bytes to the beginning of %s\n",
-	    (int)sizeof(buf), Path);
-	goto print_file_error;
+        (void)fprintf(stderr,
+                      "ERROR!!!  can't write %d bytes to the beginning of %s\n",
+                      (int)sizeof(buf), Path);
+        goto print_file_error;
     }
-/*
- * Fsync() the file.
- */
+    /*
+     * Fsync() the file.
+     */
     if (fsync(Fd)) {
-	(void) fprintf(stderr, "ERROR!!!  can't fsync %s\n", Path);
-	goto print_file_error;
+        (void)fprintf(stderr, "ERROR!!!  can't fsync %s\n", Path);
+        goto print_file_error;
     }
-/*
- * Quit (with a hint) if the test file is on an NFS file system.
- */
+    /*
+     * Quit (with a hint) if the test file is on an NFS file system.
+     */
     if (!tstwlsof("-wNa", " ")) {
-	(void) printf("ERROR!!!  %s is NFS-mounted.\n", Path);
-	MsgStat = 1;
-	(void) PrtMsg ("Lsof can't report lock information on files that", Pn);
-	(void) PrtMsg ("are located on file systems mounted from a remote", Pn);
-	(void) PrtMsg ("NFS server.\n", Pn);
-        (void) PrtMsg ("Hint: try using \"-p path\" to supply a path in a", Pn);
-        (void) PrtMsg ("non-NFS file system.\n", Pn);
-	(void) PrtMsgX("See 00FAQ and 00TEST for more information.", Pn,
-		       cleanup, 1);
+        (void)printf("ERROR!!!  %s is NFS-mounted.\n", Path);
+        MsgStat = 1;
+        (void)PrtMsg("Lsof can't report lock information on files that", Pn);
+        (void)PrtMsg("are located on file systems mounted from a remote", Pn);
+        (void)PrtMsg("NFS server.\n", Pn);
+        (void)PrtMsg("Hint: try using \"-p path\" to supply a path in a", Pn);
+        (void)PrtMsg("non-NFS file system.\n", Pn);
+        (void)PrtMsgX("See 00FAQ and 00TEST for more information.", Pn, cleanup,
+                      1);
     }
-/*
- * Get an exclusive lock on the entire file and test it with lsof.
- */
+    /*
+     * Get an exclusive lock on the entire file and test it with lsof.
+     */
     if ((em = lkfile(FULL_EX_LOCK)))
-	(void) PrtMsgX(em, Pn, cleanup, 1);
+        (void)PrtMsgX(em, Pn, cleanup, 1);
     if ((tstW = tstwlsof("-w", "W")))
-	(void) PrtMsg(tstW, Pn);
-/*
- * Get a shared lock on the entire file and test it with lsof.
- */
+        (void)PrtMsg(tstW, Pn);
+    /*
+     * Get a shared lock on the entire file and test it with lsof.
+     */
     if ((em = unlkfile(FULL_EX_LOCK)))
-	(void) PrtMsgX(em, Pn, cleanup, 1);
+        (void)PrtMsgX(em, Pn, cleanup, 1);
     if ((em = lkfile(FULL_SH_LOCK)))
-	(void) PrtMsgX(em, Pn, cleanup, 1);
+        (void)PrtMsgX(em, Pn, cleanup, 1);
     if ((tstR = tstwlsof("-w", "R")))
-	(void) PrtMsg(tstR, Pn);
+        (void)PrtMsg(tstR, Pn);
 
-# if	defined(USE_FLOCK)
-/*
- * If using flock(), skip the byte lock tests.
- */
+#    if defined(USE_FLOCK)
+    /*
+     * If using flock(), skip the byte lock tests.
+     */
     tstr = tstw = (char *)NULL;
-# endif	/* defined(USE_FLOCK) */
+#    endif /* defined(USE_FLOCK) */
 
-# if	defined(USE_FCNTL)
-/*
- * If using fcntl(), do exclusive and shared byte lock tests,
- */
+#    if defined(USE_FCNTL)
+    /*
+     * If using fcntl(), do exclusive and shared byte lock tests,
+     */
     if ((em = unlkfile(FULL_SH_LOCK)))
-	(void) PrtMsgX(em, Pn, cleanup, 1);
+        (void)PrtMsgX(em, Pn, cleanup, 1);
     if ((em = lkfile(PART_EX_LOCK)))
-	(void) PrtMsgX(em, Pn, cleanup, 1);
+        (void)PrtMsgX(em, Pn, cleanup, 1);
     if ((tstw = tstwlsof("-w", "w")))
-	(void) PrtMsg(tstw, Pn);
+        (void)PrtMsg(tstw, Pn);
     if ((em = unlkfile(PART_EX_LOCK)))
-	(void) PrtMsgX(em, Pn, cleanup, 1);
+        (void)PrtMsgX(em, Pn, cleanup, 1);
     if ((em = lkfile(PART_SH_LOCK)))
-	(void) PrtMsgX(em, Pn, cleanup, 1);
+        (void)PrtMsgX(em, Pn, cleanup, 1);
     if ((tstr = tstwlsof("-w", "r")))
-	(void) PrtMsg(tstr, Pn);
-# endif	/* defined(USE_FCNTL) */
+        (void)PrtMsg(tstr, Pn);
+#    endif /* defined(USE_FCNTL) */
 
-/*
- * Compute exit value and exit.
- */
+    /*
+     * Compute exit value and exit.
+     */
     if (tstr || tstR || tstw || tstW) {
-	tcp = (char *)NULL;
-	xv = 1;
+        tcp = (char *)NULL;
+#    if defined(LT_DIAL_freebsd)
+        /*
+         * Note: in future FreeBSD releases with
+         * https://reviews.freebsd.org/D34756, this will work as non-root user
+         */
+        (void)PrtMsg("Hint: lsof is unable to get the lock status when running "
+                     "as non-root",
+                     Pn);
+        (void)PrtMsg("in certain FreeBSD releases (e.g. FreeBSD 13.1), thus "
+                     "skipping the test",
+                     Pn);
+        xv = 77;
+#    elif defined(LT_DIAL_openbsd)
+        (void)PrtMsg("Hint: lsof is unable to get the lock status in OpenBSD",
+                     Pn);
+        (void)PrtMsg(
+            "since OpenBSD kernel forbids kvm_read, thus skipping the test",
+            Pn);
+        xv = 77;
+#    else
+        xv = 1;
+#    endif
     } else {
-	tcp = "OK";
-	xv = 0;
+        tcp = "OK";
+        xv = 0;
     }
-    (void) PrtMsgX(tcp, Pn, cleanup, xv);
-    return(0);
+    (void)PrtMsgX(tcp, Pn, cleanup, xv);
+    return (0);
 }
 
-
 /*
  * cleanup() -- release resources
  */
 
-static void
-cleanup()
-{
+static void cleanup() {
     if (Fd >= 0) {
-	(void) close(Fd);
-	Fd = -1;
-	if (Path) {
-	    (void) unlink(Path);
-	    Path = (char *)NULL;
-	}
+        (void)close(Fd);
+        Fd = -1;
+        if (Path) {
+            (void)unlink(Path);
+            Path = (char *)NULL;
+        }
     }
 }
 
-
 /*
  * lkfile() -- lock the test file
  */
 
-static char *
-lkfile(ty)
-    int ty;				/* a *_*_LOCK requested */
+static char *lkfile(int ty) /* a *_*_LOCK requested */
 {
-    char buf[2048];			/* temporary buffer */
-    int ti;				/* temporary integer */
-
-# if	defined(USE_FLOCK)
-    int flf;				/* flock() function */
-# endif	/* defined(USE_FLOCK) */
-
-# if	defined(USE_FCNTL)
-    struct flock fl;			/* flock control structure */
-/*
- * Check fcntl() lock request.
- */
-    (void) memset((void *)&fl, 0, sizeof(fl));
-    switch(ty) {
+    char buf[2048];  /* temporary buffer */
+    int ti;          /* temporary integer */
+
+#    if defined(USE_FLOCK)
+    int flf;         /* flock() function */
+#    endif /* defined(USE_FLOCK) */
+
+#    if defined(USE_FCNTL)
+    struct flock fl; /* flock control structure */
+                     /*
+                      * Check fcntl() lock request.
+                      */
+    (void)memset((void *)&fl, 0, sizeof(fl));
+    switch (ty) {
     case FULL_EX_LOCK:
-	fl.l_type = F_WRLCK;
-	break;
+        fl.l_type = F_WRLCK;
+        break;
     case FULL_SH_LOCK:
-	fl.l_type = F_RDLCK;
-	break;
+        fl.l_type = F_RDLCK;
+        break;
     case PART_EX_LOCK:
-	fl.l_type = F_WRLCK;
-	fl.l_len = (off_t)1;
-	break;
+        fl.l_type = F_WRLCK;
+        fl.l_len = (off_t)1;
+        break;
     case PART_SH_LOCK:
-	fl.l_type = F_RDLCK;
-	fl.l_len = (off_t)1;
-	break;
+        fl.l_type = F_RDLCK;
+        fl.l_len = (off_t)1;
+        break;
     default:
-	(void) snprintf(buf, sizeof(buf) - 1,
-	    "ERROR!!!  unknown lock type: %d", ty);
-	buf[sizeof(buf) - 1] = '\0';
-	return(MkStrCpy(buf, &ti));
+        (void)snprintf(buf, sizeof(buf) - 1, "ERROR!!!  unknown lock type: %d",
+                       ty);
+        buf[sizeof(buf) - 1] = '\0';
+        return (MkStrCpy(buf, &ti));
     }
-/*
- * Lock test file with fcntl().
- */
+    /*
+     * Lock test file with fcntl().
+     */
     if (fcntl(Fd, F_SETLK, &fl) != -1)
-	return((char *)NULL);
-    (void) snprintf(buf, sizeof(buf) - 1, "ERROR!!!  fcntl() lock error: %s",
-	strerror(errno));
+        return ((char *)NULL);
+    (void)snprintf(buf, sizeof(buf) - 1, "ERROR!!!  fcntl() lock error: %s",
+                   strerror(errno));
     buf[sizeof(buf) - 1] = '\0';
-    return(MkStrCpy(buf, &ti));
-# endif	/* defined(USE_FCNTL) */
-
-# if	defined(USE_FLOCK)
-/*
- * Check flock() lock request.
- */
-    switch(ty) {
+    return (MkStrCpy(buf, &ti));
+#    endif /* defined(USE_FCNTL) */
+
+#    if defined(USE_FLOCK)
+    /*
+     * Check flock() lock request.
+     */
+    switch (ty) {
     case FULL_EX_LOCK:
-	flf = LOCK_EX;
-	break;
+        flf = LOCK_EX;
+        break;
     case FULL_SH_LOCK:
-	flf = LOCK_SH;
-	break;
+        flf = LOCK_SH;
+        break;
     case PART_EX_LOCK:
     case PART_SH_LOCK:
-	return("ERROR!!!  flock() doesn't support partial locks");
-	break;
+        return ("ERROR!!!  flock() doesn't support partial locks");
+        break;
     default:
-	(void) snprintf(buf, sizeof(buf) - 1,
-	    "ERROR!!!  unknown flock() type: %d", ty);
-	buf[sizeof(buf) - 1] = '\0';
-	return(MkStrCpy(buf, &ti));
+        (void)snprintf(buf, sizeof(buf) - 1,
+                       "ERROR!!!  unknown flock() type: %d", ty);
+        buf[sizeof(buf) - 1] = '\0';
+        return (MkStrCpy(buf, &ti));
     }
-/*
- * Acquire lock.
- */
+    /*
+     * Acquire lock.
+     */
     if (!flock(Fd, flf))
-	return((char *)NULL);
-    (void) snprintf(buf, sizeof(buf) - 1,
-	"ERROR!!!  flock() %s lock failed: %s",
-	(flf == LOCK_EX) ? "exclusive" : "shared",
-	strerror(errno));
+        return ((char *)NULL);
+    (void)snprintf(buf, sizeof(buf) - 1, "ERROR!!!  flock() %s lock failed: %s",
+                   (flf == LOCK_EX) ? "exclusive" : "shared", strerror(errno));
     buf[sizeof(buf) - 1] = '\0';
-    return(MkStrCpy(buf, &ti));
-# endif	/* defined(USE_FLOCK) */
-
+    return (MkStrCpy(buf, &ti));
+#    endif /* defined(USE_FLOCK) */
 }
 
-
 /*
  * tstwlsof() -- test the open file with lsof
  */
 
-static char *
-tstwlsof(opt, xlk)
-    char *opt;				/* extra lsof options */
-    char *xlk;				/* expected lock value */
+static char *tstwlsof(char *opt, /* extra lsof options */
+                      char *xlk) /* expected lock value */
 {
-    char buf[2048];			/* temporary buffer */
-    LTfldo_t *cmdp;			/* command pointer */
-    LTfldo_t *devp;			/* device pointer */
-    char *cem;				/* current error message pointer */
-    int ff = 0;				/* file found status */
-    LTfldo_t *fop;			/* field output pointer */
-    LTfldo_t *inop;			/* inode number pointer */
-    LTfldo_t *lkp;			/* lock pointer */
-    LTdev_t lsofdc;			/* lsof device components */
-    int nf;				/* number of fields */
-    LTfldo_t *nmp;			/* file name pointer */
-    char *opv[4];			/* option vector for ExecLsof() */
-    char *pem = (char *)NULL;		/* previous error message pointer */
-    pid_t pid;				/* PID */
-    int pids = 0;			/* PID found status */
-    struct stat sb;			/* stat(2) buffer */
-    LTdev_t stdc;			/* stat(2) device components */
-    char *tcp;				/* temporary character pointer */
-    int ti;				/* temporary integer */
-    LTfldo_t *typ;			/* file type pointer */
-/*
- * Make sure there is an expected lock value.
- */
+    char buf[2048];           /* temporary buffer */
+    LTfldo_t *cmdp;           /* command pointer */
+    LTfldo_t *devp;           /* device pointer */
+    char *cem;                /* current error message pointer */
+    int ff = 0;               /* file found status */
+    LTfldo_t *fop;            /* field output pointer */
+    LTfldo_t *inop;           /* inode number pointer */
+    LTfldo_t *lkp;            /* lock pointer */
+    LTdev_t lsofdc;           /* lsof device components */
+    int nf;                   /* number of fields */
+    LTfldo_t *nmp;            /* file name pointer */
+    char *opv[4];             /* option vector for ExecLsof() */
+    char *pem = (char *)NULL; /* previous error message pointer */
+    pid_t pid;                /* PID */
+    int pids = 0;             /* PID found status */
+    struct stat sb;           /* stat(2) buffer */
+    LTdev_t stdc;             /* stat(2) device components */
+    char *tcp;                /* temporary character pointer */
+    int ti;                   /* temporary integer */
+    LTfldo_t *typ;            /* file type pointer */
+                              /*
+                               * Make sure there is an expected lock value.
+                               */
     if (!xlk || !*xlk)
-	(void) PrtMsgX("ERROR!!!  no expected lock value", Pn, cleanup, 1);
-/*
- * Get test file's information.
- */
+        (void)PrtMsgX("ERROR!!!  no expected lock value", Pn, cleanup, 1);
+    /*
+     * Get test file's information.
+     */
     if (stat(Path, &sb)) {
-	(void) snprintf(buf, sizeof(buf) - 1,
-	    "ERROR!!!  can't stat(2) %s: %s", Path, strerror(errno));
-	buf[sizeof(buf) - 1] = '\0';
-	(void) PrtMsgX(buf, Pn, cleanup, 1);
+        (void)snprintf(buf, sizeof(buf) - 1, "ERROR!!!  can't stat(2) %s: %s",
+                       Path, strerror(errno));
+        buf[sizeof(buf) - 1] = '\0';
+        (void)PrtMsgX(buf, Pn, cleanup, 1);
     }
-/*
- * Extract components from test file's device number.
- */
+    /*
+     * Extract components from test file's device number.
+     */
     if ((cem = ConvStatDev(&sb.st_dev, &stdc)))
-	(void) PrtMsgX(cem, Pn, cleanup, 1);
-/*
- * Complete the option vector and start lsof execution.
- */
+        (void)PrtMsgX(cem, Pn, cleanup, 1);
+    /*
+     * Complete the option vector and start lsof execution.
+     */
     ti = 0;
     if (opt && *opt)
-	opv[ti++] = opt;
+        opv[ti++] = opt;
 
-#if	defined(USE_LSOF_C_OPT)
+#    if defined(USE_LSOF_C_OPT)
     opv[ti++] = "-C";
-#endif	/* defined(USE_LSOF_C_OPT) */
+#    endif /* defined(USE_LSOF_C_OPT) */
 
     opv[ti++] = Path;
     opv[ti] = (char *)NULL;
     if ((cem = ExecLsof(opv)))
-	return(cem);
-/*
- * Read lsof output.
- */
+        return (cem);
+    /*
+     * Read lsof output.
+     */
     while (!ff && (fop = RdFrLsof(&nf, &cem))) {
-	if (cem) {
-	    if (pem)
-		(void) PrtMsg(pem, Pn);
-	    return(cem);
-	}
-	switch (fop->ft) {
-	case LSOF_FID_PID:
-
-	/*
-	 * This is a process information line.
-	 */
-	    pid = (pid_t)atoi(fop->v);
-	    pids = 1;
-	    cmdp = (LTfldo_t *)NULL;
-	    for (fop++, ti = 1; ti < nf; fop++, ti++) {
-		switch (fop->ft) {
-		case LSOF_FID_CMD:
-		    cmdp = fop;
-		    break;
-		}
-	    }
-	    if (!cmdp || (pid != MyPid))
-		pids = 0;
-	    break;
-	case LSOF_FID_FD:
-
-	/*
-	 * This is a file descriptor line.  Make sure its number matches the
-	 * test file's descriptor number.
-	 *
-	 * Scan for lock and name fields.
-	 */
-	    if (!pids)
-		break;
-	    for (ti = 0, tcp = fop->v; *tcp; tcp++) {
-
-	    /*
-	     * Convert file descriptor to a number.
-	     */
-		if (*tcp == ' ')
-		    continue;
-		if (((int)*tcp < (int)'0') || ((int)*tcp > (int)'9')) {
-		    ti = -1;
-		    break;
-		}
-		ti = (ti * 10) + (int)*tcp - (int)'0';
-	    }
-	    if (Fd != ti)
-		break;
-	    devp = inop = lkp = nmp = (LTfldo_t *)NULL;
-	    for (fop++, ti = 1; ti < nf; fop++, ti++) {
-		switch(fop->ft) {
-		case LSOF_FID_DEVN:
-		    devp = fop;
-		    break;
-		case LSOF_FID_INODE:
-		    inop = fop;
-		    break;
-		case LSOF_FID_LOCK:
-		    lkp = fop;
-		    break;
-		case LSOF_FID_NAME:
-		    nmp = fop;
-		    break;
-		case LSOF_FID_TYPE:
-		    typ = fop;
-		    break;
-		}
-	    }
-	/*
-	 * Check the results of the file descriptor field scan.
-	 *
-	 * (Don't compare path names because of symbolic link interference.)
-	 */
-	    if (!devp || !inop || !nmp || !typ)
-		break;
-	    if (strcasecmp(typ->v, "reg") && strcasecmp(typ->v, "vreg"))
-		break;
-	    if (ConvLsofDev(devp->v, &lsofdc))
-		break;
-	    if ((stdc.maj != lsofdc.maj)
-	    ||  (stdc.min != lsofdc.min)
-	    ||  (stdc.unit != lsofdc.unit))
-		break;
-	    (void) snprintf(buf, sizeof(buf) - 1, "%u",
-		(unsigned int)sb.st_ino);
-	    buf[sizeof(buf) - 1] = '\0';
-	    if (strcmp(inop->v, buf))
-		break;
-	/*
-	 * The specified file has been located.  Check its lock status.
-	 */
-	    ff = 1;
-	    if (!lkp || strcmp(lkp->v, xlk)) {
-		if (pem)
-		    (void) PrtMsg(pem, Pn);
-		(void) snprintf(buf, sizeof(buf) - 1,
-		    "lock mismatch: expected %s, got \"%s\"", xlk,
-		    lkp ? lkp->v : "(none)");
-		pem = MkStrCpy(buf, &ti);
-	    }
-	    break;
-	}
+        if (cem) {
+            if (pem)
+                (void)PrtMsg(pem, Pn);
+            return (cem);
+        }
+        switch (fop->ft) {
+        case LSOF_FID_PID:
+
+            /*
+             * This is a process information line.
+             */
+            pid = (pid_t)atoi(fop->v);
+            pids = 1;
+            cmdp = (LTfldo_t *)NULL;
+            for (fop++, ti = 1; ti < nf; fop++, ti++) {
+                switch (fop->ft) {
+                case LSOF_FID_CMD:
+                    cmdp = fop;
+                    break;
+                }
+            }
+            if (!cmdp || (pid != MyPid))
+                pids = 0;
+            break;
+        case LSOF_FID_FD:
+
+            /*
+             * This is a file descriptor line.  Make sure its number matches the
+             * test file's descriptor number.
+             *
+             * Scan for lock and name fields.
+             */
+            if (!pids)
+                break;
+            for (ti = 0, tcp = fop->v; *tcp; tcp++) {
+
+                /*
+                 * Convert file descriptor to a number.
+                 */
+                if (*tcp == ' ')
+                    continue;
+                if (((int)*tcp < (int)'0') || ((int)*tcp > (int)'9')) {
+                    ti = -1;
+                    break;
+                }
+                ti = (ti * 10) + (int)*tcp - (int)'0';
+            }
+            if (Fd != ti)
+                break;
+            devp = inop = lkp = nmp = (LTfldo_t *)NULL;
+            for (fop++, ti = 1; ti < nf; fop++, ti++) {
+                switch (fop->ft) {
+                case LSOF_FID_DEVN:
+                    devp = fop;
+                    break;
+                case LSOF_FID_INODE:
+                    inop = fop;
+                    break;
+                case LSOF_FID_LOCK:
+                    lkp = fop;
+                    break;
+                case LSOF_FID_NAME:
+                    nmp = fop;
+                    break;
+                case LSOF_FID_TYPE:
+                    typ = fop;
+                    break;
+                }
+            }
+            /*
+             * Check the results of the file descriptor field scan.
+             *
+             * (Don't compare path names because of symbolic link interference.)
+             */
+            if (!devp || !inop || !nmp || !typ)
+                break;
+            if (strcasecmp(typ->v, "reg") && strcasecmp(typ->v, "vreg"))
+                break;
+            if (ConvLsofDev(devp->v, &lsofdc))
+                break;
+            if ((stdc.maj != lsofdc.maj) || (stdc.min != lsofdc.min) ||
+                (stdc.unit != lsofdc.unit))
+                break;
+            (void)snprintf(buf, sizeof(buf) - 1, "%u", (unsigned int)sb.st_ino);
+            buf[sizeof(buf) - 1] = '\0';
+            if (strcmp(inop->v, buf))
+                break;
+            /*
+             * The specified file has been located.  Check its lock status.
+             */
+            ff = 1;
+            if (!lkp || strcmp(lkp->v, xlk)) {
+                if (pem)
+                    (void)PrtMsg(pem, Pn);
+                (void)snprintf(buf, sizeof(buf) - 1,
+                               "lock mismatch: expected %s, got \"%s\"", xlk,
+                               lkp ? lkp->v : "(none)");
+                pem = MkStrCpy(buf, &ti);
+            }
+            break;
+        }
     }
-    (void) StopLsof();
+    (void)StopLsof();
     if (!ff) {
-	if (pem)
-	   (void) PrtMsg(pem, Pn);
-	(void) snprintf(buf, sizeof(buf) - 1,
-	    "lock test file %s not found by lsof", Path);
-	buf[sizeof(buf) - 1] = '\0';
-	return(MkStrCpy(buf, &ti));
+        if (pem)
+            (void)PrtMsg(pem, Pn);
+        (void)snprintf(buf, sizeof(buf) - 1,
+                       "lock test file %s not found by lsof", Path);
+        buf[sizeof(buf) - 1] = '\0';
+        return (MkStrCpy(buf, &ti));
     }
-    return(pem);
+    return (pem);
 }
 
-
 /*
  * unlkfile() -- unlock the test file
  */
 
-static char *
-unlkfile(ty)
-    int ty;				/* current *_*_LOCK lock typ */
+static char *unlkfile(int ty) /* current *_*_LOCK lock typ */
 {
-    char buf[2048];			/* temporary buffer */
-    int ti;				/* temporary integer */
-
-# if	defined(USE_FCNTL)
-    struct flock fl;			/* flock control structure */
-/*
- * Check current fcntl() lock type.
- */
-    (void) memset((void *)&fl, 0, sizeof(fl));
-    switch(ty) {
+    char buf[2048];  /* temporary buffer */
+    int ti;          /* temporary integer */
+
+#    if defined(USE_FCNTL)
+    struct flock fl; /* flock control structure */
+                     /*
+                      * Check current fcntl() lock type.
+                      */
+    (void)memset((void *)&fl, 0, sizeof(fl));
+    switch (ty) {
     case FULL_EX_LOCK:
     case FULL_SH_LOCK:
-	break;
+        break;
     case PART_EX_LOCK:
     case PART_SH_LOCK:
-	fl.l_len = (off_t)1;
-	break;
+        fl.l_len = (off_t)1;
+        break;
     default:
-	(void) snprintf(buf, sizeof(buf) - 1,
-	    "ERROR!!!  unknown unlock type: %d", ty);
-	buf[sizeof(buf) - 1] = '\0';
-	return(MkStrCpy(buf, &ti));
+        (void)snprintf(buf, sizeof(buf) - 1,
+                       "ERROR!!!  unknown unlock type: %d", ty);
+        buf[sizeof(buf) - 1] = '\0';
+        return (MkStrCpy(buf, &ti));
     }
-/*
- * Unlock test file with fcntl().
- */
+    /*
+     * Unlock test file with fcntl().
+     */
     fl.l_type = F_UNLCK;
     if (fcntl(Fd, F_SETLK, &fl) != -1)
-	return((char *)NULL);
-    (void) snprintf(buf, sizeof(buf) - 1, "ERROR!!!  fcntl() unlock error: %s",
-	strerror(errno));
+        return ((char *)NULL);
+    (void)snprintf(buf, sizeof(buf) - 1, "ERROR!!!  fcntl() unlock error: %s",
+                   strerror(errno));
     buf[sizeof(buf) - 1] = '\0';
-    return(MkStrCpy(buf, &ti));
-# endif	/* defined(USE_FCNTL) */
-
-# if	defined(USE_FLOCK)
-/*
- * Check current flock() lock type.
- */
-    switch(ty) {
+    return (MkStrCpy(buf, &ti));
+#    endif /* defined(USE_FCNTL) */
+
+#    if defined(USE_FLOCK)
+    /*
+     * Check current flock() lock type.
+     */
+    switch (ty) {
     case FULL_EX_LOCK:
     case FULL_SH_LOCK:
-	break;
+        break;
     default:
-	(void) snprintf(buf, sizeof(buf) - 1,
-	    "ERROR!!!   unknown unlock type: %s", ty);
-	buf[sizeof(buf) - 1] = '\0';
-	return(MkStrCpy(buf, &ti));
+        (void)snprintf(buf, sizeof(buf) - 1,
+                       "ERROR!!!   unknown unlock type: %s", ty);
+        buf[sizeof(buf) - 1] = '\0';
+        return (MkStrCpy(buf, &ti));
     }
-/*
- * Unlock file with flock().
- */
+    /*
+     * Unlock file with flock().
+     */
     if (!flock(Fd, LOCK_UN))
-	return((char *)NULL);
-    (void) snprintf(buf, sizeof(buf) - 1, "ERROR!!!  flock() unlock error: %s",
-	strerror(errno));
-    return(MkStrCpy(buf, &ti));
-# endif	/* defined(USE_FLOCK) */
-
+        return ((char *)NULL);
+    (void)snprintf(buf, sizeof(buf) - 1, "ERROR!!!  flock() unlock error: %s",
+                   strerror(errno));
+    return (MkStrCpy(buf, &ti));
+#    endif /* defined(USE_FLOCK) */
 }
-#endif	/* !defined(USE_FLOCK) && !defined(USE_FCNTL) */
+#endif     /* !defined(USE_FLOCK) && !defined(USE_FCNTL) */
diff --git a/tests/LTnfs.c b/tests/LTnfs.c
index d5019a3..df28412 100644
--- a/tests/LTnfs.c
+++ b/tests/LTnfs.c
@@ -5,7 +5,6 @@
  * Purdue University
  */
 
-
 /*
  * Copyright 2002 Purdue Research Foundation, West Lafayette, Indiana
  * 47907.  All rights reserved.
@@ -32,500 +31,471 @@
  * 4. This notice may not be removed or altered.
  */
 
-#ifndef lint
-static char copyright[] =
-"@(#) Copyright 2002 Purdue Research Foundation.\nAll rights reserved.\n";
-#endif
-
 #include "LsofTest.h"
 #include "lsof_fields.h"
 
-
 /*
  * Pre-definitions that may be revoked by specific dialects
  */
 
-#define	DO_TEST				/* do the test */
+#define DO_TEST /* do the test */
 
-
-#if	defined(LT_DIAL_darwin)
+#if defined(LT_DIAL_darwin)
 /*
  * Darwin-specific items
  */
 
-# if LT_VERS<800
-#undef	DO_TEST
-# endif	/* LT_VERS<800 */
-#endif	/* defined(LT_DIAL_darwin) */
-
+#    if LT_VERS < 800
+#        undef DO_TEST
+#    endif /* LT_VERS<800 */
+#endif     /* defined(LT_DIAL_darwin) */
 
 /*
  * Globals
  */
 
-int Fd = -1;			/* test file descriptor; open if >= 0 */
-pid_t MyPid = (pid_t)0;		/* PID of this process */
-int NFstat = 0;			/* NFS file status: 0 == closed
-				 *		    1 == not created by this
-				 *			 these and must not be
-				 *			 unlinked
-				 *		    2 == created by this test
-				 *			 and must be unlinked
-				 */
-char *Path = (char *)NULL;	/* test file path; none if NULL */
-char *Pn = (char *)NULL;	/* program name */
-
+int Fd = -1;               /* test file descriptor; open if >= 0 */
+pid_t MyPid = (pid_t)0;    /* PID of this process */
+int NFstat = 0;            /* NFS file status: 0 == closed
+                            *		    1 == not created by this
+                            *			 these and must not be
+                            *			 unlinked
+                            *		    2 == created by this test
+                            *			 and must be unlinked
+                            */
+char *Path = (char *)NULL; /* test file path; none if NULL */
+char *Pn = (char *)NULL;   /* program name */
 
 /*
  * Local function prototypes
  */
 
-_PROTOTYPE(static void cleanup,(void));
-_PROTOTYPE(static char *FindNFSfile,(int *ff, char *szbuf));
-
+static void cleanup(void);
+static char *FindNFSfile(int *ff, char *szbuf);
 
 /*
  * Main program
  */
 
-int
-main(argc, argv)
-    int argc;				/* argument count */
-    char *argv[];			/* arguments */
+int main(int argc,     /* argument count */
+         char *argv[]) /* arguments */
 {
-    char buf[2048];			/* temporary buffer */
-    char *em;				/* error message pointer */
-    int ff;				/* FindNFSfile() file-found flag */
-    int sz;				/* file size (if created) */
-    char szbuf[32];			/* created test file size in ASCII */
-    int ti;				/* temporary index */
-    int xv = 0;				/* exit value */
-/*
- * Get program name and PID, issue start message, and build space prefix.
- */
+    char buf[2048]; /* temporary buffer */
+    char *em;       /* error message pointer */
+    int ff;         /* FindNFSfile() file-found flag */
+    int sz;         /* file size (if created) */
+    char szbuf[32]; /* created test file size in ASCII */
+    int ti;         /* temporary index */
+    int xv = 0;     /* exit value */
+                    /*
+                     * Get program name and PID, issue start message, and build space prefix.
+                     */
     if ((Pn = strrchr(argv[0], '/')))
-	Pn++;
+        Pn++;
     else
-	Pn = argv[0];
+        Pn = argv[0];
     MyPid = getpid();
-    (void) printf("%s ... ", Pn);
-    (void) fflush(stdout);
+    (void)printf("%s ... ", Pn);
+    (void)fflush(stdout);
     PrtMsg((char *)NULL, Pn);
 
-#if	!defined(DO_TEST)
-/*
- * If the dialect has disabled the test, echo that result and exit with
- * a successful return code.
- */
-    (void) PrtMsgX(LT_DONT_DO_TEST, Pn, cleanup, 0);
-#endif	/* !defined(DO_TEST) */
-
-/*
- * Process arguments.
- */
-    if (ScanArg(argc, argv, "hp:", Pn))
-	xv = 1;
-    if (xv || LTopt_h) {
-	(void) PrtMsg("usage: [-h] [-p path]", Pn);
-	PrtMsg       ("       -h       print help (this panel)", Pn);
-	PrtMsgX      ("       -p path  define test file path", Pn, cleanup, xv);
-    }
-/*
- * See if lsof can be executed and can access kernel memory.
- */
-    if ((em = IsLsofExec()))
-	(void) PrtMsgX(em, Pn, cleanup, 1);
-    if ((em = CanRdKmem()))
-	(void) PrtMsgX(em, Pn, cleanup, 1);
-/*
- * Process the file path and open it.
- */
-    if ((Path = LTopt_p)) {
-
+#if !defined(DO_TEST)
     /*
-     * The file path was supplied.  Open the file read-only.
+     * If the dialect has disabled the test, echo that result and exit with
+     * a successful return code.
      */
-	if ((Fd = open(Path, O_RDONLY, 0400)) < 0) {
-	    (void) fprintf(stderr, "ERROR!!!  can't read-only open %s\n",
-		Path);
-	    goto print_file_error;
-	}
+    (void)PrtMsgX(LT_DONT_DO_TEST, Pn, cleanup, 0);
+#endif /* !defined(DO_TEST) */
+
     /*
-     * Record that an existing file is being used.  Clear its ASCII size.
+     * Process arguments.
      */
-	NFstat = 1;
-	szbuf[0] = '\0';
-    } else {
-
+    if (ScanArg(argc, argv, "hp:", Pn))
+        xv = 1;
+    if (xv || LTopt_h) {
+        (void)PrtMsg("usage: [-h] [-p path]", Pn);
+        PrtMsg("       -h       print help (this panel)", Pn);
+        PrtMsgX("       -p path  define test file path", Pn, cleanup, xv);
+    }
     /*
-     * The file path wasn't supplied with -p, so generate one.
+     * See if lsof can be executed and can access kernel memory.
      */
-	(void) snprintf(buf, sizeof(buf) - 1, "./config.LTnfs%ld",
-	    (long)MyPid);
-	buf[sizeof(buf) - 1] = '\0';
-	Path = MkStrCpy(buf, &ti);
+    if ((em = IsLsofExec()))
+        (void)PrtMsgX(em, Pn, cleanup, 1);
+    if ((em = CanRdKmem()))
+        (void)PrtMsgX(em, Pn, cleanup, 1);
     /*
-     * Open a new test file at the specified path.
+     * Process the file path and open it.
      */
-	(void) unlink(Path);
-	if ((Fd = open(Path, O_RDWR|O_CREAT, 0600)) < 0) {
-	    (void) fprintf(stderr, "ERROR!!!  can't create %s\n", Path);
+    if ((Path = LTopt_p)) {
 
-print_file_error:
+        /*
+         * The file path was supplied.  Open the file read-only.
+         */
+        if ((Fd = open(Path, O_RDONLY, 0400)) < 0) {
+            (void)fprintf(stderr, "ERROR!!!  can't read-only open %s\n", Path);
+            goto print_file_error;
+        }
+        /*
+         * Record that an existing file is being used.  Clear its ASCII size.
+         */
+        NFstat = 1;
+        szbuf[0] = '\0';
+    } else {
 
-	    MsgStat = 1;
-	    (void) snprintf(buf, sizeof(buf) - 1, "      Errno %d: %s",
-		errno, strerror(errno));
-	    buf[sizeof(buf) - 1] = '\0';
-	    (void) PrtMsgX(buf, Pn, cleanup, 1);
-	}
-	NFstat = 2;
-    /*
-     * Write the test file to its expected size.
-     */
-	sz = sizeof(buf);
-	for (ti = 0; ti < sz; ti++) {
-	    buf[ti] = (char)(ti & 0xff);
-	}
-	if (write(Fd, buf, sz) != sz) {
-	    (void) fprintf(stderr, "ERROR!!!  can't write %d bytes to %s\n",
-		sz, Path);
-	    goto print_file_error;
-	}
+        /*
+         * The file path wasn't supplied with -p, so generate one.
+         */
+        (void)snprintf(buf, sizeof(buf) - 1, "./config.LTnfs%ld", (long)MyPid);
+        buf[sizeof(buf) - 1] = '\0';
+        Path = MkStrCpy(buf, &ti);
+        /*
+         * Open a new test file at the specified path.
+         */
+        (void)unlink(Path);
+        if ((Fd = open(Path, O_RDWR | O_CREAT, 0600)) < 0) {
+            (void)fprintf(stderr, "ERROR!!!  can't create %s\n", Path);
+
+        print_file_error:
+
+            MsgStat = 1;
+            (void)snprintf(buf, sizeof(buf) - 1, "      Errno %d: %s", errno,
+                           strerror(errno));
+            buf[sizeof(buf) - 1] = '\0';
+            (void)PrtMsgX(buf, Pn, cleanup, 1);
+        }
+        NFstat = 2;
+        /*
+         * Write the test file to its expected size.
+         */
+        sz = sizeof(buf);
+        for (ti = 0; ti < sz; ti++) {
+            buf[ti] = (char)(ti & 0xff);
+        }
+        if (write(Fd, buf, sz) != sz) {
+            (void)fprintf(stderr, "ERROR!!!  can't write %d bytes to %s\n", sz,
+                          Path);
+            goto print_file_error;
+        }
+        /*
+         * Fsync() the file.
+         */
+        if (fsync(Fd)) {
+            (void)fprintf(stderr, "ERROR!!!  can't fsync %s\n", Path);
+            goto print_file_error;
+        }
+        /*
+         * Convert the file size to ASCII.
+         */
+        (void)snprintf(szbuf, sizeof(szbuf) - 1, "%d", sz);
+        szbuf[sizeof(szbuf) - 1] = '\0';
+    }
     /*
-     * Fsync() the file.
+     * Make sure the test file can be found on an NFS file system.
      */
-	if (fsync(Fd)) {
-	    (void) fprintf(stderr, "ERROR!!!  can't fsync %s\n", Path);
-	    goto print_file_error;
-	}
-   /*
-    * Convert the file size to ASCII.
-    */
-	(void) snprintf(szbuf, sizeof(szbuf) - 1, "%d", sz);
-	szbuf[sizeof(szbuf) - 1] = '\0';
-    }
-/*
- * Make sure the test file can be found on an NFS file system.
- */
     if ((em = FindNFSfile(&ff, szbuf))) {
 
+        /*
+         * Print the error message returned by FindNFSfile().
+         */
+        (void)PrtMsg(em, Pn);
+        if (!ff) {
+
+            /*
+             * If the file couldn't be found, print hints.
+             */
+            if (NFstat == 1) {
+                (void)PrtMsg(
+                    "Hint: this test must be able to open for read access", Pn);
+                (void)PrtMsg(
+                    "the file at the path supplied with the -p option and", Pn);
+                (void)PrtMsg(
+                    "that file must be a regular file (not a directory) on",
+                    Pn);
+                (void)PrtMsg("an NFS file system.\n", Pn);
+                (void)PrtMsgX("See 00FAQ and 00TEST for more information.", Pn,
+                              cleanup, 77);
+            } else if (NFstat == 2) {
+                (void)PrtMsg(
+                    "Hint: the temporary path generated by this test might",
+                    Pn);
+                (void)PrtMsg(
+                    "not be on an NFS file system, or this test might be", Pn);
+                (void)PrtMsg(
+                    "unable to create a file on the NFS file system.\n", Pn);
+                (void)PrtMsg(
+                    "As a work-around use the -p option to specify a path to",
+                    Pn);
+                (void)PrtMsg(
+                    "a regular file (not a directory) on an NFS file system",
+                    Pn);
+                (void)PrtMsg("to which this test will have read access.\n", Pn);
+                (void)PrtMsgX("See 00FAQ and 00TEST for more information.", Pn,
+                              cleanup, 77);
+            }
+        }
+    }
     /*
-     * Print the error message returned by FindNFSfile().
+     * Exit successfully.
      */
-	(void) PrtMsg(em, Pn);
-	if (!ff) {
-
-	/*
-	 * If the file couldn't be found, print hints.
-	 */
-	    if (NFstat == 1) {
-		(void) PrtMsg(
-		    "Hint: this test must be able to open for read access",
-		    Pn);
-		(void) PrtMsg(
-		    "the file at the path supplied with the -p option and",
-		    Pn);
-		(void) PrtMsg(
-		    "that file must be a regular file (not a directory) on",
-		    Pn);
-		(void) PrtMsg(
-		    "an NFS file system.\n",
-		    Pn);
-		(void) PrtMsgX(
-		    "See 00FAQ and 00TEST for more information.",
-		    Pn, cleanup, 1);
-	    } else if (NFstat == 2) {
-		(void) PrtMsg(
-		    "Hint: the temporary path generated by this test might",
-		    Pn);
-		(void) PrtMsg(
-		    "not be on an NFS file system, or this test might be",
-		    Pn);
-		(void) PrtMsg(
-		    "unable to create a file on the NFS file system.\n",
-		    Pn);
-		(void) PrtMsg(
-		    "As a work-around use the -p option to specify a path to",
-		    Pn);
-		(void) PrtMsg(
-		    "a regular file (not a directory) on an NFS file system",
-		    Pn);
-		(void) PrtMsg(
-		    "to which this test will have read access.\n",
-		    Pn);
-		(void) PrtMsgX(
-		    "See 00FAQ and 00TEST for more information.",
-		    Pn, cleanup, 1);
-	    }
-	}
-    }
-/*
- * Exit successfully.
- */
-    (void) PrtMsgX("OK", Pn, cleanup, 0);
-    return(0);
+    (void)PrtMsgX("OK", Pn, cleanup, 0);
+    return (0);
 }
 
-
 /*
  * cleanup() -- release resources
  */
 
-static void
-cleanup()
-{
+static void cleanup() {
     if (Fd >= 0) {
-	(void) close(Fd);
-	Fd = -1;
-	if (Path) {
-	    if (NFstat == 2)
-		(void) unlink(Path);
-	    Path = (char *)NULL;
-	}
+        (void)close(Fd);
+        Fd = -1;
+        if (Path) {
+            if (NFstat == 2)
+                (void)unlink(Path);
+            Path = (char *)NULL;
+        }
     }
 }
 
-
 /*
  * FindNFSfile() -- find the NFS file with lsof
  */
 
-static char *
-FindNFSfile(ff, szbuf)
-    int *ff;				/* file-found response receptor */
-    char *szbuf;			/* expected file size in ASCII (if
-					 * the file was created by this test */
+static char *FindNFSfile(int *ff,     /* file-found response receptor */
+                         char *szbuf) /* expected file size in ASCII (if
+                                       * the file was created by this test */
 {
-    char buf[2048];			/* temporary buffer */
-    char *cem;				/* current error message pointer */
-    LTfldo_t *cmdp;			/* command pointer */
-    LTfldo_t *devp;			/* device pointer */
-    LTfldo_t *fop;			/* field output pointer */
-    char ibuf[64];			/* inode number buffer */
-    LTfldo_t *inop;			/* inode number pointer */
-    LTdev_t lsofdc;			/* lsof device components */
-    int nf;				/* number of fields */
-    char nlkbuf[32];			/* link count buffer */
-    LTfldo_t *nlkp;			/* nlink pointer */
-    char *opv[5];			/* option vector for ExecLsof() */
-    char *pem = (char *)NULL;		/* previous error message pointer */
-    pid_t pid;				/* PID */
-    int pids = 0;			/* PID found status */
-    struct stat sb;			/* stat(2) buffer */
-    LTdev_t stdc;			/* stat(2) device components */
-    LTfldo_t *szp;			/* size pointer */
-    char *tcp;				/* temporary character pointer */
-    int ti;				/* temporary integer */
-    LTfldo_t *typ;			/* file type pointer */
-/*
- * Check the argument pointers.
- *
- * Set the file-found response false.
- */
+    char buf[2048];           /* temporary buffer */
+    char *cem;                /* current error message pointer */
+    LTfldo_t *cmdp;           /* command pointer */
+    LTfldo_t *devp;           /* device pointer */
+    LTfldo_t *fop;            /* field output pointer */
+    char ibuf[64];            /* inode number buffer */
+    LTfldo_t *inop;           /* inode number pointer */
+    LTdev_t lsofdc;           /* lsof device components */
+    int nf;                   /* number of fields */
+    char nlkbuf[32];          /* link count buffer */
+    LTfldo_t *nlkp;           /* nlink pointer */
+    char *opv[5];             /* option vector for ExecLsof() */
+    char *pem = (char *)NULL; /* previous error message pointer */
+    pid_t pid;                /* PID */
+    int pids = 0;             /* PID found status */
+    struct stat sb;           /* stat(2) buffer */
+    LTdev_t stdc;             /* stat(2) device components */
+    LTfldo_t *szp;            /* size pointer */
+    char *tcp;                /* temporary character pointer */
+    int ti;                   /* temporary integer */
+    LTfldo_t *typ;            /* file type pointer */
+                              /*
+                               * Check the argument pointers.
+                               *
+                               * Set the file-found response false.
+                               */
     if (!ff || !szbuf)
-	(void) PrtMsgX("ERROR!!!  missing argument to FindNFSfile()",
-		       Pn, cleanup, 1);
+        (void)PrtMsgX("ERROR!!!  missing argument to FindNFSfile()", Pn,
+                      cleanup, 1);
     *ff = 0;
-/*
- * Get test file's information.
- */
+    /*
+     * Get test file's information.
+     */
     if (stat(Path, &sb)) {
-	(void) snprintf(buf, sizeof(buf) - 1,
-	    "ERROR!!!  can't stat(2) %s: %s", Path, strerror(errno));
-	buf[sizeof(buf) - 1] = '\0';
-	PrtMsgX(buf, Pn, cleanup, 1);
+        (void)snprintf(buf, sizeof(buf) - 1, "ERROR!!!  can't stat(2) %s: %s",
+                       Path, strerror(errno));
+        buf[sizeof(buf) - 1] = '\0';
+        PrtMsgX(buf, Pn, cleanup, 1);
     }
-/*
- * Extract components from test file's stat buffer.
- */
+    /*
+     * Extract components from test file's stat buffer.
+     */
     if ((cem = ConvStatDev(&sb.st_dev, &stdc)))
-	PrtMsgX(cem, Pn, cleanup, 1);
-    (void) snprintf(ibuf, sizeof(ibuf) - 1, "%u", (unsigned int)sb.st_ino);
+        PrtMsgX(cem, Pn, cleanup, 1);
+    (void)snprintf(ibuf, sizeof(ibuf) - 1, "%u", (unsigned int)sb.st_ino);
     ibuf[sizeof(ibuf) - 1] = '\0';
-    (void) snprintf(nlkbuf, sizeof(nlkbuf) - 1, "%d", (int)sb.st_nlink);
+    (void)snprintf(nlkbuf, sizeof(nlkbuf) - 1, "%d", (int)sb.st_nlink);
     nlkbuf[sizeof(nlkbuf) - 1] = '\0';
-/*
- * Complete the option vector and start lsof execution.
- */
+    /*
+     * Complete the option vector and start lsof execution.
+     */
     ti = 0;
     opv[ti++] = "-s";
     opv[ti++] = "-Na";
 
-#if	defined(USE_LSOF_C_OPT)
+#if defined(USE_LSOF_C_OPT)
     opv[ti++] = "-C";
-#endif	/* defined(USE_LSOF_C_OPT) */
+#endif /* defined(USE_LSOF_C_OPT) */
 
     opv[ti++] = Path;
     opv[ti] = (char *)NULL;
     if ((cem = ExecLsof(opv)))
-	return(cem);
-/*
- * Read lsof output.
- */
+        return (cem);
+    /*
+     * Read lsof output.
+     */
     while (!*ff && (fop = RdFrLsof(&nf, &cem))) {
-	if (cem) {
-	    if (pem)
-		(void) PrtMsg(pem, Pn);
-	    return(cem);
-	}
-	switch (fop->ft) {
-	case LSOF_FID_PID:
-
-	/*
-	 * This is a process information line.
-	 */
-	    pid = (pid_t)atoi(fop->v);
-	    pids = 1;
-	    cmdp = (LTfldo_t *)NULL;
-	    for (fop++, ti = 1; ti < nf; fop++, ti++) {
-		switch (fop->ft) {
-		case LSOF_FID_CMD:
-		    cmdp = fop;
-		    break;
-		}
-	    }
-	    if (!cmdp || (pid != MyPid))
-		pids = 0;
-	    break;
-	case LSOF_FID_FD:
-
-	/*
-	 * This is a file descriptor line.  Make sure its number matches the
-	 * test file's descriptor number.
-	 */
-	    if (!pids)
-		break;
-	    for (ti = 0, tcp = fop->v; *tcp; tcp++) {
-
-	    /*
-	     * Convert file descriptor to a number.
-	     */
-		if (*tcp == ' ')
-		    continue;
-		if (((int)*tcp < (int)'0') || ((int)*tcp > (int)'9')) {
-		    ti = -1;
-		    break;
-		}
-		ti = (ti * 10) + (int)*tcp - (int)'0';
-	    }
-	    if (Fd != ti)
-		break;
-	/*
-	 * Scan for device, inode, nlink, offset, size and type fields.
-	 */
-	    devp = inop = nlkp, szp = typ = (LTfldo_t *)NULL;
-	    for (fop++, ti = 1; ti < nf; fop++, ti++) {
-		switch (fop->ft) {
-		case LSOF_FID_DEVN:
-		    devp = fop;
-		    break;
-		case LSOF_FID_INODE:
-		    inop = fop;
-		    break;
-		case LSOF_FID_NLINK:
-		    nlkp = fop;
-		    break;
-		case LSOF_FID_OFFSET:
-		    break;
-		case LSOF_FID_SIZE:
-		    szp = fop;
-		    break;
-		case LSOF_FID_TYPE:
-		    typ = fop;
-		    break;
-		}
-	    }
-	/*
-	 * Check the device, inode, and type of the file.
-	 */
-	    if (!devp || !inop || !typ)
-		break;
-	    if (strcasecmp(typ->v, "reg") && strcasecmp(typ->v, "vreg"))
-		break;
-	    if ((cem = ConvLsofDev(devp->v, &lsofdc))) {
-		if (pem)
-		    (void) PrtMsg(pem, Pn);
-		pem = cem;
-		break;
-	    }
-	    if ((stdc.maj != lsofdc.maj)
-	    ||  (stdc.min != lsofdc.min)
-	    ||  (stdc.unit != lsofdc.unit)
-	    ||  strcmp(inop->v, ibuf)
-	    ) {
-		break;
-	    }
-	/*
-	 * Indicate the file was found.
-	 */
-	    *ff = 1;
-	/*
-	 * Check the link count.
-	 */
-	    if (!nlkp) {
-		(void) snprintf(buf, sizeof(buf) - 1,
-		    "ERROR!!!  lsof didn't report a link count for %s", Path);
-		buf[sizeof(buf) - 1] = '\0';
-		cem = MkStrCpy(buf, &ti);
-		if (pem)
-		    (void) PrtMsg(pem, Pn);
-		pem = cem;
-		break;
-	    }
-	    if (strcmp(nlkp->v, nlkbuf)) {
-		(void) snprintf(buf, sizeof(buf) - 1,
-		    "ERROR!!!  wrong link count: expected %s, got %s",
-		    nlkbuf, nlkp->v);
-		buf[sizeof(buf) - 1] = '\0';
-		cem = MkStrCpy(buf, &ti);
-		if (pem)
-		    (void) PrtMsg(pem, Pn);
-		pem = cem;
-		break;
-	    }
-	/*
-	 * If the file was created by this test, check its size.
-	 */
-	    if (NFstat == 2) {
-		if (!szp) {
-		    (void) snprintf(buf, sizeof(buf) - 1,
-			"ERROR!!!  lsof didn't report a size for %s", Path);
-		    buf[sizeof(buf) - 1] = '\0';
-		    cem = MkStrCpy(buf, &ti);
-		    if (pem)
-			(void) PrtMsg(pem, Pn);
-		    pem = cem;
-		    break;
-		}
-		if (strcmp(szp->v, szbuf)) {
-		    (void) snprintf(buf, sizeof(buf) - 1,
-			"ERROR!!!  wrong file size: expected %s, got %s",
-			szbuf, szp->v);
-		    buf[sizeof(buf) - 1] = '\0';
-		    cem = MkStrCpy(buf, &ti);
-		    if (pem)
-			(void) PrtMsg(pem, Pn);
-		    pem = cem;
-		    break;
-		}
-	    }
-	/*
-	 * The requested file was located.  Return the previous error message
-	 * pointer.  (It will be NULL if no error was detected.)
-	 */
-	    (void) StopLsof();
-	    return(pem);
-	}
+        if (cem) {
+            if (pem)
+                (void)PrtMsg(pem, Pn);
+            return (cem);
+        }
+        switch (fop->ft) {
+        case LSOF_FID_PID:
+
+            /*
+             * This is a process information line.
+             */
+            pid = (pid_t)atoi(fop->v);
+            pids = 1;
+            cmdp = (LTfldo_t *)NULL;
+            for (fop++, ti = 1; ti < nf; fop++, ti++) {
+                switch (fop->ft) {
+                case LSOF_FID_CMD:
+                    cmdp = fop;
+                    break;
+                }
+            }
+            if (!cmdp || (pid != MyPid))
+                pids = 0;
+            break;
+        case LSOF_FID_FD:
+
+            /*
+             * This is a file descriptor line.  Make sure its number matches the
+             * test file's descriptor number.
+             */
+            if (!pids)
+                break;
+            for (ti = 0, tcp = fop->v; *tcp; tcp++) {
+
+                /*
+                 * Convert file descriptor to a number.
+                 */
+                if (*tcp == ' ')
+                    continue;
+                if (((int)*tcp < (int)'0') || ((int)*tcp > (int)'9')) {
+                    ti = -1;
+                    break;
+                }
+                ti = (ti * 10) + (int)*tcp - (int)'0';
+            }
+            if (Fd != ti)
+                break;
+            /*
+             * Scan for device, inode, nlink, offset, size and type fields.
+             */
+            devp = inop = nlkp, szp = typ = (LTfldo_t *)NULL;
+            for (fop++, ti = 1; ti < nf; fop++, ti++) {
+                switch (fop->ft) {
+                case LSOF_FID_DEVN:
+                    devp = fop;
+                    break;
+                case LSOF_FID_INODE:
+                    inop = fop;
+                    break;
+                case LSOF_FID_NLINK:
+                    nlkp = fop;
+                    break;
+                case LSOF_FID_OFFSET:
+                    break;
+                case LSOF_FID_SIZE:
+                    szp = fop;
+                    break;
+                case LSOF_FID_TYPE:
+                    typ = fop;
+                    break;
+                }
+            }
+            /*
+             * Check the device, inode, and type of the file.
+             */
+            if (!devp || !inop || !typ)
+                break;
+            if (strcasecmp(typ->v, "reg") && strcasecmp(typ->v, "vreg"))
+                break;
+            if ((cem = ConvLsofDev(devp->v, &lsofdc))) {
+                if (pem)
+                    (void)PrtMsg(pem, Pn);
+                pem = cem;
+                break;
+            }
+            if ((stdc.maj != lsofdc.maj) || (stdc.min != lsofdc.min) ||
+                (stdc.unit != lsofdc.unit) || strcmp(inop->v, ibuf)) {
+                break;
+            }
+            /*
+             * Indicate the file was found.
+             */
+            *ff = 1;
+            /*
+             * Check the link count.
+             */
+            if (!nlkp) {
+                (void)snprintf(
+                    buf, sizeof(buf) - 1,
+                    "ERROR!!!  lsof didn't report a link count for %s", Path);
+                buf[sizeof(buf) - 1] = '\0';
+                cem = MkStrCpy(buf, &ti);
+                if (pem)
+                    (void)PrtMsg(pem, Pn);
+                pem = cem;
+                break;
+            }
+            if (strcmp(nlkp->v, nlkbuf)) {
+                (void)snprintf(
+                    buf, sizeof(buf) - 1,
+                    "ERROR!!!  wrong link count: expected %s, got %s", nlkbuf,
+                    nlkp->v);
+                buf[sizeof(buf) - 1] = '\0';
+                cem = MkStrCpy(buf, &ti);
+                if (pem)
+                    (void)PrtMsg(pem, Pn);
+                pem = cem;
+                break;
+            }
+            /*
+             * If the file was created by this test, check its size.
+             */
+            if (NFstat == 2) {
+                if (!szp) {
+                    (void)snprintf(buf, sizeof(buf) - 1,
+                                   "ERROR!!!  lsof didn't report a size for %s",
+                                   Path);
+                    buf[sizeof(buf) - 1] = '\0';
+                    cem = MkStrCpy(buf, &ti);
+                    if (pem)
+                        (void)PrtMsg(pem, Pn);
+                    pem = cem;
+                    break;
+                }
+                if (strcmp(szp->v, szbuf)) {
+                    (void)snprintf(
+                        buf, sizeof(buf) - 1,
+                        "ERROR!!!  wrong file size: expected %s, got %s", szbuf,
+                        szp->v);
+                    buf[sizeof(buf) - 1] = '\0';
+                    cem = MkStrCpy(buf, &ti);
+                    if (pem)
+                        (void)PrtMsg(pem, Pn);
+                    pem = cem;
+                    break;
+                }
+            }
+            /*
+             * The requested file was located.  Return the previous error
+             * message pointer.  (It will be NULL if no error was detected.)
+             */
+            (void)StopLsof();
+            return (pem);
+        }
     }
-/*
- * The test file wasn't found.
- */
-    (void) StopLsof();
+    /*
+     * The test file wasn't found.
+     */
+    (void)StopLsof();
     if (pem)
-	(void) PrtMsg(pem, Pn);
-    (void) snprintf(buf, sizeof(buf) - 1,
-	"ERROR!!!  test file %s not found by lsof", Path);
+        (void)PrtMsg(pem, Pn);
+    (void)snprintf(buf, sizeof(buf) - 1,
+                   "ERROR!!!  test file %s not found by lsof", Path);
     buf[sizeof(buf) - 1] = '\0';
-    return(MkStrCpy(buf, &ti));
+    return (MkStrCpy(buf, &ti));
 }
diff --git a/tests/LTnlink.c b/tests/LTnlink.c
index be51373..45cdbab 100644
--- a/tests/LTnlink.c
+++ b/tests/LTnlink.c
@@ -5,7 +5,6 @@
  * Purdue University
  */
 
-
 /*
  * Copyright 2002 Purdue Research Foundation, West Lafayette, Indiana
  * 47907.  All rights reserved.
@@ -32,555 +31,539 @@
  * 4. This notice may not be removed or altered.
  */
 
-#ifndef lint
-static char copyright[] =
-"@(#) Copyright 2002 Purdue Research Foundation.\nAll rights reserved.\n";
-#endif
-
 #include "LsofTest.h"
 #include "lsof_fields.h"
 
-
 /*
  * Pre-definitions that may be changed by specific dialects
  */
 
-#define	DO_TEST			/* do the test */
-
+#define DO_TEST /* do the test */
 
 /*
  * Dialect-specific items
  */
 
-
-#if	defined(LT_DIAL_darwin)
+#if defined(LT_DIAL_darwin)
 /*
  * Darwin-specific items
  */
 
-# if	defined(LT_KMEM)
-#undef	DO_TEST
-# endif	/* defined(LT_KMEM) */
+#    if defined(LT_KMEM)
+#        undef DO_TEST
+#    endif /* defined(LT_KMEM) */
 
-#endif	/* defined(LT_DIAL_darwin) */
+#endif /* defined(LT_DIAL_darwin) */
 
 /*
  * Globals
  */
 
-int Fd = -1;			/* test file descriptor; open if >= 0 */
-pid_t MyPid = (pid_t)0;		/* PID of this process */
-char *Path = (char *)NULL;	/* test file path; none if NULL */
-char *Pn = (char *)NULL;	/* program name */
-
+int Fd = -1;               /* test file descriptor; open if >= 0 */
+pid_t MyPid = (pid_t)0;    /* PID of this process */
+char *Path = (char *)NULL; /* test file path; none if NULL */
+char *Pn = (char *)NULL;   /* program name */
 
 /*
  * Local function prototypes
  */
 
-_PROTOTYPE(static void cleanup,(void));
-_PROTOTYPE(static char *FindFile,(char *opt, int *ff, int ie, LTdev_t *tfdc,
-				  char *ibuf, char *xlnk, char *szbuf));
-
+static void cleanup(void);
+static char *FindFile(char *opt, int *ff, int ie, LTdev_t *tfdc, char *ibuf,
+                      char *xlnk, char *szbuf);
 
 /*
  * Main program
  */
 
-int
-main(argc, argv)
-    int argc;				/* argument count */
-    char *argv[];			/* arguments */
+int main(int argc,     /* argument count */
+         char *argv[]) /* arguments */
 {
-    char buf[2048];			/* temporary buffer */
-    int do_unlink = 1;			/* do the unlink test section */
-    char *em;				/* error message pointer */
-    int ff;				/* FindFile() file-found flag */
-    char ibuf[32];			/* inode number in ASCII */
-    char *opt;				/* lsof option */
-    int sz;				/* file size */
-    char szbuf[32];			/* file size in ASCII */
-    LTdev_t tfdc;			/* device components */
-    struct stat tfsb;			/* test file stat(2) buffer */
-    int ti, tj;				/* temporary indexes */
-    char xlnk[32];			/* expected link count in ASCII */
-    int xv = 0;				/* exit value */
-/*
- * Get program name and PID, issue start message, and build space prefix.
- */
+    char buf[2048];    /* temporary buffer */
+    int do_unlink = 1; /* do the unlink test section */
+    char *em;          /* error message pointer */
+    int ff;            /* FindFile() file-found flag */
+    char ibuf[32];     /* inode number in ASCII */
+    char *opt;         /* lsof option */
+    int sz;            /* file size */
+    char szbuf[32];    /* file size in ASCII */
+    LTdev_t tfdc;      /* device components */
+    struct stat tfsb;  /* test file stat(2) buffer */
+    int ti, tj;        /* temporary indexes */
+    char xlnk[32];     /* expected link count in ASCII */
+    int xv = 0;        /* exit value */
+                       /*
+                        * Get program name and PID, issue start message, and build space prefix.
+                        */
     if ((Pn = strrchr(argv[0], '/')))
-	Pn++;
+        Pn++;
     else
-	Pn = argv[0];
+        Pn = argv[0];
     MyPid = getpid();
-    (void) printf("%s ... ", Pn);
-    (void) fflush(stdout);
+    (void)printf("%s ... ", Pn);
+    (void)fflush(stdout);
     PrtMsg((char *)NULL, Pn);
 
-#if	!defined(DO_TEST)
-/*
- * Quit if lsof for this dialect doesn't support adequate nlink reporting.
- */
-    (void) PrtMsgX(LT_DONT_DO_TEST, Pn, cleanup, 0);
-#endif	/* !defined(DO_TEST) */
+#if !defined(DO_TEST)
+    /*
+     * Quit if lsof for this dialect doesn't support adequate nlink reporting.
+     */
+    (void)PrtMsgX(LT_DONT_DO_TEST, Pn, cleanup, 0);
+#endif /* !defined(DO_TEST) */
 
-/*
- * Process arguments.
- */
+    /*
+     * Process arguments.
+     */
     if (ScanArg(argc, argv, "hp:", Pn))
-	xv = 1;
+        xv = 1;
     if (xv || LTopt_h) {
-	(void) PrtMsg("usage: [-h] [-p path]", Pn);
-	PrtMsg       ("       -h       print help (this panel)", Pn);
-	PrtMsgX      ("       -p path  define test file path", Pn, cleanup, xv);
+        (void)PrtMsg("usage: [-h] [-p path]", Pn);
+        PrtMsg("       -h       print help (this panel)", Pn);
+        PrtMsgX("       -p path  define test file path", Pn, cleanup, xv);
     }
-/*
- * See if lsof can be executed and can access kernel memory.
- */
+    /*
+     * See if lsof can be executed and can access kernel memory.
+     */
     if ((em = IsLsofExec()))
-	(void) PrtMsgX(em, Pn, cleanup, 1);
+        (void)PrtMsgX(em, Pn, cleanup, 1);
     if ((em = CanRdKmem()))
-	(void) PrtMsgX(em, Pn, cleanup, 1);
-/*
- * Process the file path.
- */
+        (void)PrtMsgX(em, Pn, cleanup, 1);
+    /*
+     * Process the file path.
+     */
     if (!(Path = LTopt_p)) {
 
+        /*
+         * The file path was not supplied, so make one.
+         */
+        (void)snprintf(buf, sizeof(buf) - 1, "./config.LTnlink%ld",
+                       (long)MyPid);
+        buf[sizeof(buf) - 1] = '\0';
+        Path = MkStrCpy(buf, &ti);
+    }
     /*
-     * The file path was not supplied, so make one.
+     * Create the test file.
      */
-	(void) snprintf(buf, sizeof(buf) - 1, "./config.LTnlink%ld",
-	    (long)MyPid);
-	buf[sizeof(buf) - 1] = '\0';
-	Path = MkStrCpy(buf, &ti);
-    }
-/*
- * Create the test file.
- */
-    (void) unlink(Path);
-    if ((Fd = open(Path, O_RDWR|O_CREAT, 0600)) < 0) {
-	(void) fprintf(stderr, "ERROR!!!  can't create %s\n", Path);
+    (void)unlink(Path);
+    if ((Fd = open(Path, O_RDWR | O_CREAT, 0600)) < 0) {
+        (void)fprintf(stderr, "ERROR!!!  can't create %s\n", Path);
 
-print_file_error:
+    print_file_error:
 
-	MsgStat = 1;
-	(void) snprintf(buf, sizeof(buf) - 1, "      Errno %d: %s",
-	    errno, strerror(errno));
-	buf[sizeof(buf) - 1] = '\0';
-	(void) PrtMsgX(buf, Pn, cleanup, 1);
+        MsgStat = 1;
+        (void)snprintf(buf, sizeof(buf) - 1, "      Errno %d: %s", errno,
+                       strerror(errno));
+        buf[sizeof(buf) - 1] = '\0';
+        (void)PrtMsgX(buf, Pn, cleanup, 1);
     }
-/*
- * Write the test file to its expected size.
- */
+    /*
+     * Write the test file to its expected size.
+     */
     sz = sizeof(buf);
     for (ti = 0; ti < sz; ti++) {
-	buf[ti] = (char)(ti & 0xff);
+        buf[ti] = (char)(ti & 0xff);
     }
     if (write(Fd, buf, sz) != sz) {
-	(void) fprintf(stderr, "ERROR!!!  can't write %d bytes to %s\n",
-	    sz, Path);
-	goto print_file_error;
+        (void)fprintf(stderr, "ERROR!!!  can't write %d bytes to %s\n", sz,
+                      Path);
+        goto print_file_error;
     }
-/*
- * Fsync() the file.
- */
+    /*
+     * Fsync() the file.
+     */
     if (fsync(Fd)) {
-	(void) fprintf(stderr, "ERROR!!!  can't fsync %s\n", Path);
-	goto print_file_error;
+        (void)fprintf(stderr, "ERROR!!!  can't fsync %s\n", Path);
+        goto print_file_error;
     }
-/*
- * Stat(2) the test file.
- */
+    /*
+     * Stat(2) the test file.
+     */
     if (stat(Path, &tfsb)) {
-	(void) snprintf(buf, sizeof(buf) - 1,
-	    "ERROR!!!  can't stat(2) %s: %s", Path, strerror(errno));
-	buf[sizeof(buf) - 1] = '\0';
-	PrtMsgX(buf, Pn, cleanup, 1);
+        (void)snprintf(buf, sizeof(buf) - 1, "ERROR!!!  can't stat(2) %s: %s",
+                       Path, strerror(errno));
+        buf[sizeof(buf) - 1] = '\0';
+        PrtMsgX(buf, Pn, cleanup, 1);
     }
-/*
- * Set the test file status to open and linked.
- *
- * Get the test file's parameters:
- *
- *    * device paramters in LTdev_t form;
- *    * inode number in ASCII;
- *    * link count in ASCII;
- *    * file size in ASCII.
- */
+    /*
+     * Set the test file status to open and linked.
+     *
+     * Get the test file's parameters:
+     *
+     *    * device parameters in LTdev_t form;
+     *    * inode number in ASCII;
+     *    * link count in ASCII;
+     *    * file size in ASCII.
+     */
     if ((em = ConvStatDev(&tfsb.st_dev, &tfdc)))
-	PrtMsgX(em, Pn, cleanup, 1);
-    (void) snprintf(ibuf, sizeof(ibuf) - 1, "%" PRIu64, (uint64_t)tfsb.st_ino);
+        PrtMsgX(em, Pn, cleanup, 1);
+    (void)snprintf(ibuf, sizeof(ibuf) - 1, "%" PRIu64, (uint64_t)tfsb.st_ino);
     ibuf[sizeof(szbuf) - 1] = '\0';
-    (void) snprintf(xlnk, sizeof(xlnk) - 1, "%d", (int)tfsb.st_nlink);
+    (void)snprintf(xlnk, sizeof(xlnk) - 1, "%d", (int)tfsb.st_nlink);
     ibuf[sizeof(szbuf) - 1] = '\0';
-    (void) snprintf(szbuf, sizeof(szbuf) - 1, "%d", sz);
+    (void)snprintf(szbuf, sizeof(szbuf) - 1, "%d", sz);
     szbuf[sizeof(szbuf) - 1] = '\0';
-/*
- * See if the file is on an NFS file system.
- */
-    (void) FindFile("-Na", &ff, 1, &tfdc, ibuf, xlnk, szbuf);
+    /*
+     * See if the file is on an NFS file system.
+     */
+    (void)FindFile("-Na", &ff, 1, &tfdc, ibuf, xlnk, szbuf);
     if (ff) {
 
+        /*
+         * The file was found on an NFS file system.
+         */
+        (void)snprintf(buf, sizeof(buf) - 1,
+                       "WARNING!!!  Test file %s is NFS mounted.", Path);
+        (void)PrtMsg(buf, Pn);
+        (void)PrtMsg(
+            "  As a result this test probably won't be able to unlink it and",
+            Pn);
+        (void)PrtMsg(
+            "  find its open and unlinked instance with lsof's +L option.", Pn);
+        (void)PrtMsg(
+            "  Therefore, that section of this test has been disabled.\n", Pn);
+        (void)PrtMsg(
+            "  Hint: supply a path with the -p option to a file in a non-NFS",
+            Pn);
+        (void)PrtMsg("  file system that this test can write and unlink.\n",
+                     Pn);
+        (void)PrtMsg("  See 00FAQ and 00TEST for more information.", Pn);
+        do_unlink = 0;
+    }
+#if defined(LT_DIAL_freebsd)
+    // See https://github.com/lsof-org/lsof/issues/264, unlinked files are not
+    // found by lsof
+    do_unlink = 0;
+#endif
     /*
-     * The file was found on an NFS file system.
+     * Find the test file.
      */
-	(void) snprintf(buf, sizeof(buf) - 1,
-	    "WARNING!!!  Test file %s is NFS mounted.", Path);
-	(void) PrtMsg(buf, Pn);
-	(void) PrtMsg(
-	    "  As a result this test probably won't be able to unlink it and",
-	    Pn);
-	(void) PrtMsg(
-	    "  find its open and unlinked instance with lsof's +L option.",
-	    Pn);
-	(void) PrtMsg(
-	    "  Therefore, that section of this test has been disabled.\n",
-	    Pn);
-	(void) PrtMsg(
-	    "  Hint: supply a path with the -p option to a file in a non-NFS",
-	    Pn);
-	(void) PrtMsg(
-	    "  file system that this test can write and unlink.\n",
-	    Pn);
-	(void) PrtMsg(
-	    "  See 00FAQ and 00TEST for more information.",
-	    Pn);
-	do_unlink = 0;
-    }
-/*
- * Find the test file.
- */
     if ((em = FindFile("+L", &ff, 0, &tfdc, ibuf, xlnk, szbuf)))
-	(void) PrtMsgX(em, Pn, cleanup, 1);
-/*
- * If the unlink test is enabled, do it.
- */
+        (void)PrtMsgX(em, Pn, cleanup, 1);
+    /*
+     * If the unlink test is enabled, do it.
+     */
     if (do_unlink) {
-	if (unlink(Path)) {
-	    (void) snprintf(buf, sizeof(buf) - 1,
-		"ERROR!!!  unlink(%s) failed: (%s).", Path, strerror(errno));
-	    buf[sizeof(buf) - 1] = '\0';
-	    (void) PrtMsg(buf, Pn);
-	    (void) snprintf(buf, sizeof(buf) - 1,
-		"  %s may be on a ZFS file system, where it", Path);
-	    buf[sizeof(buf) - 1] = '\0';
-	    (void) PrtMsg(buf, Pn);
-	    (void) snprintf(buf, sizeof(buf) - 1,
-	      "  is not possible for %s to unlink the file it has open.", Pn);
-	    buf[sizeof(buf) - 1] = '\0';
-	    (void) PrtMsg(buf, Pn);
-	    (void) snprintf(buf, sizeof(buf) - 1,
-	      "  To run the %s test, use the \"-p path\" option to specify",
-	      Pn);
-	    buf[sizeof(buf) - 1] = '\0';
-	    (void) PrtMsg(buf, Pn);
-	    (void) PrtMsg(
-	      "  a file on a file system -- e.g., UFS -- that supports unlink",
-	      Pn);
-	    (void) PrtMsg(
-	      "  while the file is open.  Usually /tmp can do that -- e.g.,",
-	      Pn);
-	    (void) snprintf(buf, sizeof(buf) - 1,
-	      "  run the test as \"./%s -p /tmp/<name>\".\n", Pn);
-	    buf[sizeof(buf) - 1] = '\0';
-	    (void) PrtMsg(buf, Pn);
-	    (void) PrtMsgX( "  See 00FAQ and 00TEST for more information.",
-	      Pn, cleanup, 1);
-	}
-	for (opt = "+L1", ti = 0, tj = 30; ti < tj; ti++) {
-
-	/*
-	 * Wait a while for the link count to be updated before concluding
-	 * lsof can't find the unlinked file.  Use "+L1" for only the first
-	 * third of the tries, then switch to "+L".
-	 */
-	    if ((ti + ti + ti) >= tj)
-		opt = "+L";
-	    if (!(em = FindFile(opt, &ff, 0, &tfdc, ibuf, "0", szbuf)))
-		break;
-	    if (ti)
-		(void) printf(".");
-	    else
-		(void) printf("waiting for link count update: .");
-	    (void) fflush(stdout);
-	    (void) sleep(2);
-	}
-	if (ti) {
-
-	/*
-	 * End the delay message.
-	 */
-	    printf("\n");
-	    (void) fflush(stdout);
-	    MsgStat = 1;
-	}
-	if (em)
-	    (void) PrtMsgX(em, Pn, cleanup, 1);
+        if (unlink(Path)) {
+            (void)snprintf(buf, sizeof(buf) - 1,
+                           "ERROR!!!  unlink(%s) failed: (%s).", Path,
+                           strerror(errno));
+            buf[sizeof(buf) - 1] = '\0';
+            (void)PrtMsg(buf, Pn);
+            (void)snprintf(buf, sizeof(buf) - 1,
+                           "  %s may be on a ZFS file system, where it", Path);
+            buf[sizeof(buf) - 1] = '\0';
+            (void)PrtMsg(buf, Pn);
+            (void)snprintf(
+                buf, sizeof(buf) - 1,
+                "  is not possible for %s to unlink the file it has open.", Pn);
+            buf[sizeof(buf) - 1] = '\0';
+            (void)PrtMsg(buf, Pn);
+            (void)snprintf(
+                buf, sizeof(buf) - 1,
+                "  To run the %s test, use the \"-p path\" option to specify",
+                Pn);
+            buf[sizeof(buf) - 1] = '\0';
+            (void)PrtMsg(buf, Pn);
+            (void)PrtMsg("  a file on a file system -- e.g., UFS -- that "
+                         "supports unlink",
+                         Pn);
+            (void)PrtMsg(
+                "  while the file is open.  Usually /tmp can do that -- e.g.,",
+                Pn);
+            (void)snprintf(buf, sizeof(buf) - 1,
+                           "  run the test as \"./%s -p /tmp/<name>\".\n", Pn);
+            buf[sizeof(buf) - 1] = '\0';
+            (void)PrtMsg(buf, Pn);
+            (void)PrtMsgX("  See 00FAQ and 00TEST for more information.", Pn,
+                          cleanup, 1);
+        }
+        for (opt = "+L1", ti = 0, tj = 30; ti < tj; ti++) {
+
+            /*
+             * Wait a while for the link count to be updated before concluding
+             * lsof can't find the unlinked file.  Use "+L1" for only the first
+             * third of the tries, then switch to "+L".
+             */
+            if ((ti + ti + ti) >= tj)
+                opt = "+L";
+            if (!(em = FindFile(opt, &ff, 0, &tfdc, ibuf, "0", szbuf)))
+                break;
+            if (ti)
+                (void)printf(".");
+            else
+                (void)printf("waiting for link count update: .");
+            (void)fflush(stdout);
+            (void)sleep(2);
+        }
+        if (ti) {
+
+            /*
+             * End the delay message.
+             */
+            printf("\n");
+            (void)fflush(stdout);
+            MsgStat = 1;
+        }
+        if (em)
+            (void)PrtMsgX(em, Pn, cleanup, 1);
     }
-/*
- * Exit successfully.
- */
-    (void) PrtMsgX("OK", Pn, cleanup, 0);
-    return(0);
+    /*
+     * Exit successfully.
+     */
+    (void)PrtMsgX("OK", Pn, cleanup, 0);
+    return (0);
 }
 
-
 /*
  * cleanup() -- release resources
  */
 
-static void
-cleanup()
-{
+static void cleanup() {
     if (Fd >= 0) {
-	(void) close(Fd);
-	Fd = -1;
+        (void)close(Fd);
+        Fd = -1;
     }
     if (Path)
-	(void) unlink(Path);
+        (void)unlink(Path);
 }
 
-
 /*
  * FindFile() -- find a file with lsof
  */
 
-static char *
-FindFile(opt, ff, ie, tfdc, ibuf, xlnk, szbuf)
-    char *opt;				/* additional lsof options */
-    int *ff;				/* file-found response receptor */
-    int ie;				/* ignore errors if == 1 */
-    LTdev_t *tfdc;			/* test file device components */
-    char *ibuf;				/* inode number in ASCII */
-    char *xlnk;				/* expected link count */
-    char *szbuf;			/* file size in ASCII */
+static char *FindFile(char *opt,     /* additional lsof options */
+                      int *ff,       /* file-found response receptor */
+                      int ie,        /* ignore errors if == 1 */
+                      LTdev_t *tfdc, /* test file device components */
+                      char *ibuf,    /* inode number in ASCII */
+                      char *xlnk,    /* expected link count */
+                      char *szbuf)   /* file size in ASCII */
 {
-    char buf[2048];			/* temporary buffer */
-    char *cem;				/* current error message pointer */
-    LTfldo_t *cmdp;			/* command pointer */
-    LTfldo_t *devp;			/* device pointer */
-    LTfldo_t *fop;			/* field output pointer */
-    LTfldo_t *inop;			/* inode number pointer */
-    LTdev_t lsofdc;			/* lsof device components */
-    int nf;				/* number of fields */
-    LTfldo_t *nlkp;			/* nlink pointer */
-    char *opv[4];			/* option vector for ExecLsof() */
-    char *pem = (char *)NULL;		/* previous error message pointer */
-    pid_t pid;				/* PID */
-    int pids = 0;			/* PID found status */
-    LTfldo_t *szp;			/* size pointer */
-    char *tcp;				/* temporary character pointer */
-    int ti;				/* temporary integer */
-    LTfldo_t *typ;			/* file type pointer */
-/*
- * Check the argument pointers.
- *
- * Set the file-found response false.
- */
+    char buf[2048];           /* temporary buffer */
+    char *cem;                /* current error message pointer */
+    LTfldo_t *cmdp;           /* command pointer */
+    LTfldo_t *devp;           /* device pointer */
+    LTfldo_t *fop;            /* field output pointer */
+    LTfldo_t *inop;           /* inode number pointer */
+    LTdev_t lsofdc;           /* lsof device components */
+    int nf;                   /* number of fields */
+    LTfldo_t *nlkp;           /* nlink pointer */
+    char *opv[4];             /* option vector for ExecLsof() */
+    char *pem = (char *)NULL; /* previous error message pointer */
+    pid_t pid;                /* PID */
+    int pids = 0;             /* PID found status */
+    LTfldo_t *szp;            /* size pointer */
+    char *tcp;                /* temporary character pointer */
+    int ti;                   /* temporary integer */
+    LTfldo_t *typ;            /* file type pointer */
+                              /*
+                               * Check the argument pointers.
+                               *
+                               * Set the file-found response false.
+                               */
     if (!ff || !ibuf || !szbuf || !tfdc || !xlnk)
-	(void) PrtMsgX("ERROR!!!  missing argument to FindFile()",
-		       Pn, cleanup, 1);
+        (void)PrtMsgX("ERROR!!!  missing argument to FindFile()", Pn, cleanup,
+                      1);
     *ff = 0;
-/*
- * Complete the option vector and start lsof execution.
- */
+    /*
+     * Complete the option vector and start lsof execution.
+     */
     ti = 0;
     if (opt && *opt)
-	opv[ti++] = opt;
+        opv[ti++] = opt;
 
-#if	defined(USE_LSOF_C_OPT)
+#if defined(USE_LSOF_C_OPT)
     opv[ti++] = "-C";
-#endif	/* defined(USE_LSOF_C_OPT) */
+#endif /* defined(USE_LSOF_C_OPT) */
 
     if (strcmp(xlnk, "0"))
-	opv[ti++] = Path;
+        opv[ti++] = Path;
     opv[ti] = (char *)NULL;
     if ((cem = ExecLsof(opv))) {
- 	if (ie)
-	    return((char *)NULL);
-	return(cem);
+        if (ie)
+            return ((char *)NULL);
+        return (cem);
     }
-/*
- * Read lsof output.
- */
+    /*
+     * Read lsof output.
+     */
     while (!*ff && (fop = RdFrLsof(&nf, &cem))) {
-	if (cem) {
- 	    if (ie)
-		return((char *)NULL);
-	    if (pem)
-		(void) PrtMsg(pem, Pn);
-	    return(cem);
-	}
-	switch (fop->ft) {
-	case LSOF_FID_PID:
-
-	/*
-	 * This is a process information line.
-	 */
-	    pid = (pid_t)atoi(fop->v);
-	    pids = 1;
-	    cmdp = (LTfldo_t *)NULL;
-	    for (fop++, ti = 1; ti < nf; fop++, ti++) {
-		switch (fop->ft) {
-		case LSOF_FID_CMD:
-		    cmdp = fop;
-		    break;
-		}
-	    }
-	    if (!cmdp || (pid != MyPid))
-		pids = 0;
-	    break;
-	case LSOF_FID_FD:
-
-	/*
-	 * This is a file descriptor line.  Make sure its number matches the
-	 * test file's descriptor number.
-	 */
-	    if (!pids)
-		break;
-	    for (ti = 0, tcp = fop->v; *tcp; tcp++) {
-
-	    /*
-	     * Convert file descriptor to a number.
-	     */
-		if (*tcp == ' ')
-		    continue;
-		if (((int)*tcp < (int)'0') || ((int)*tcp > (int)'9')) {
-		    ti = -1;
-		    break;
-		}
-		ti = (ti * 10) + (int)*tcp - (int)'0';
-	    }
-	    if (Fd != ti)
-		break;
-	/*
-	 * Scan for device, inode, nlink, size and type fields.
-	 */
-	    devp = inop = nlkp = szp = typ = (LTfldo_t *)NULL;
-	    for (fop++, ti = 1; ti < nf; fop++, ti++) {
-		switch (fop->ft) {
-		case LSOF_FID_DEVN:
-		    devp = fop;
-		    break;
-		case LSOF_FID_INODE:
-		    inop = fop;
-		    break;
-		case LSOF_FID_NLINK:
-		    nlkp = fop;
-		    break;
-		case LSOF_FID_SIZE:
-		    szp = fop;
-		    break;
-		case LSOF_FID_TYPE:
-		    typ = fop;
-		    break;
-		}
-	    }
-	/*
-	 * Check the device, inode, and type of the file.
-	 */
-	    if (!devp || !inop || !szp || !typ)
-		break;
-	    if (strcasecmp(typ->v, "reg") && strcasecmp(typ->v, "vreg"))
-		break;
-	    if ((cem = ConvLsofDev(devp->v, &lsofdc))) {
-		if (pem)
-		    (void) PrtMsg(pem, Pn);
-		pem = cem;
-		break;
-	    }
-	    if ((tfdc->maj != lsofdc.maj)
-	    ||  (tfdc->min != lsofdc.min)
-	    ||  (tfdc->unit != lsofdc.unit)
-	    ||  strcmp(inop->v, ibuf)
-	    ) {
-		break;
-	    }
-	/*
-	 * Indicate the file was found.
-	 */
-	    *ff = 1;
-	/*
-	 * Check the size and link count.
-	 */
-	    if (!szp) {
-		(void) snprintf(buf, sizeof(buf) - 1,
-		    "ERROR!!!  lsof didn't report a file size for %s", Path);
-		buf[sizeof(buf) - 1] = '\0';
-		cem = MkStrCpy(buf, &ti);
-		if (pem)
-		    (void) PrtMsg(pem, Pn);
-		pem = cem;
-		break;
-	    }
-	    if (strcmp(szp->v, szbuf)) {
-		(void) snprintf(buf, sizeof(buf) - 1,
-		    "ERROR!!!  wrong file size: expected %s, got %s",
-		    szbuf, szp->v);
-		buf[sizeof(buf) - 1] = '\0';
-		cem = MkStrCpy(buf, &ti);
-		if (pem)
-		    (void) PrtMsg(pem, Pn);
-		pem = cem;
-		break;
-	    }
-	    if (!nlkp) {
-		if (strcmp(xlnk, "0")) {
-
-		/*
-		 * If lsof returned no link count and the expected return is
-		 * not "0", it's an error.  Otherwise, interpret no link count
-		 * as equivalent to a "0" link count.
-		 */
-		    (void) snprintf(buf, sizeof(buf) - 1,
-			"ERROR!!!  lsof didn't report a link count for %s",
-			Path);
-		    buf[sizeof(buf) - 1] = '\0';
-		    cem = MkStrCpy(buf, &ti);
-		    if (pem)
-			(void) PrtMsg(pem, Pn);
-		    pem = cem;
-		    break;
-		}
-	    } else {
-		if (strcmp(nlkp->v, xlnk)) {
-		    (void) snprintf(buf, sizeof(buf) - 1,
-			"ERROR!!!  wrong link count: expected %s, got %s",
-			xlnk, nlkp->v);
-		    buf[sizeof(buf) - 1] = '\0';
-		    cem = MkStrCpy(buf, &ti);
-		    if (pem)
-			(void) PrtMsg(pem, Pn);
-		    pem = cem;
-		    break;
-		}
-	    }
-	/*
-	 * The requested file was located.  Return the previous error message
-	 * pointer unless errors are being ignored.  (The previous error
-	 * message pointer  will be NULL if no error was detected.)
-	 */
-	    (void) StopLsof();
- 	    if (ie)
-		return((char *)NULL);
-	    return(pem);
-	}
+        if (cem) {
+            if (ie)
+                return ((char *)NULL);
+            if (pem)
+                (void)PrtMsg(pem, Pn);
+            return (cem);
+        }
+        switch (fop->ft) {
+        case LSOF_FID_PID:
+
+            /*
+             * This is a process information line.
+             */
+            pid = (pid_t)atoi(fop->v);
+            pids = 1;
+            cmdp = (LTfldo_t *)NULL;
+            for (fop++, ti = 1; ti < nf; fop++, ti++) {
+                switch (fop->ft) {
+                case LSOF_FID_CMD:
+                    cmdp = fop;
+                    break;
+                }
+            }
+            if (!cmdp || (pid != MyPid))
+                pids = 0;
+            break;
+        case LSOF_FID_FD:
+
+            /*
+             * This is a file descriptor line.  Make sure its number matches the
+             * test file's descriptor number.
+             */
+            if (!pids)
+                break;
+            for (ti = 0, tcp = fop->v; *tcp; tcp++) {
+
+                /*
+                 * Convert file descriptor to a number.
+                 */
+                if (*tcp == ' ')
+                    continue;
+                if (((int)*tcp < (int)'0') || ((int)*tcp > (int)'9')) {
+                    ti = -1;
+                    break;
+                }
+                ti = (ti * 10) + (int)*tcp - (int)'0';
+            }
+            if (Fd != ti)
+                break;
+            /*
+             * Scan for device, inode, nlink, size and type fields.
+             */
+            devp = inop = nlkp = szp = typ = (LTfldo_t *)NULL;
+            for (fop++, ti = 1; ti < nf; fop++, ti++) {
+                switch (fop->ft) {
+                case LSOF_FID_DEVN:
+                    devp = fop;
+                    break;
+                case LSOF_FID_INODE:
+                    inop = fop;
+                    break;
+                case LSOF_FID_NLINK:
+                    nlkp = fop;
+                    break;
+                case LSOF_FID_SIZE:
+                    szp = fop;
+                    break;
+                case LSOF_FID_TYPE:
+                    typ = fop;
+                    break;
+                }
+            }
+            /*
+             * Check the device, inode, and type of the file.
+             */
+            if (!devp || !inop || !szp || !typ)
+                break;
+            if (strcasecmp(typ->v, "reg") && strcasecmp(typ->v, "vreg"))
+                break;
+            if ((cem = ConvLsofDev(devp->v, &lsofdc))) {
+                if (pem)
+                    (void)PrtMsg(pem, Pn);
+                pem = cem;
+                break;
+            }
+            if ((tfdc->maj != lsofdc.maj) || (tfdc->min != lsofdc.min) ||
+                (tfdc->unit != lsofdc.unit) || strcmp(inop->v, ibuf)) {
+                break;
+            }
+            /*
+             * Indicate the file was found.
+             */
+            *ff = 1;
+            /*
+             * Check the size and link count.
+             */
+            if (!szp) {
+                (void)snprintf(
+                    buf, sizeof(buf) - 1,
+                    "ERROR!!!  lsof didn't report a file size for %s", Path);
+                buf[sizeof(buf) - 1] = '\0';
+                cem = MkStrCpy(buf, &ti);
+                if (pem)
+                    (void)PrtMsg(pem, Pn);
+                pem = cem;
+                break;
+            }
+            if (strcmp(szp->v, szbuf)) {
+                (void)snprintf(buf, sizeof(buf) - 1,
+                               "ERROR!!!  wrong file size: expected %s, got %s",
+                               szbuf, szp->v);
+                buf[sizeof(buf) - 1] = '\0';
+                cem = MkStrCpy(buf, &ti);
+                if (pem)
+                    (void)PrtMsg(pem, Pn);
+                pem = cem;
+                break;
+            }
+            if (!nlkp) {
+                if (strcmp(xlnk, "0")) {
+
+                    /*
+                     * If lsof returned no link count and the expected return is
+                     * not "0", it's an error.  Otherwise, interpret no link
+                     * count as equivalent to a "0" link count.
+                     */
+                    (void)snprintf(
+                        buf, sizeof(buf) - 1,
+                        "ERROR!!!  lsof didn't report a link count for %s",
+                        Path);
+                    buf[sizeof(buf) - 1] = '\0';
+                    cem = MkStrCpy(buf, &ti);
+                    if (pem)
+                        (void)PrtMsg(pem, Pn);
+                    pem = cem;
+                    break;
+                }
+            } else {
+                if (strcmp(nlkp->v, xlnk)) {
+                    (void)snprintf(
+                        buf, sizeof(buf) - 1,
+                        "ERROR!!!  wrong link count: expected %s, got %s", xlnk,
+                        nlkp->v);
+                    buf[sizeof(buf) - 1] = '\0';
+                    cem = MkStrCpy(buf, &ti);
+                    if (pem)
+                        (void)PrtMsg(pem, Pn);
+                    pem = cem;
+                    break;
+                }
+            }
+            /*
+             * The requested file was located.  Return the previous error
+             * message pointer unless errors are being ignored.  (The previous
+             * error message pointer  will be NULL if no error was detected.)
+             */
+            (void)StopLsof();
+            if (ie)
+                return ((char *)NULL);
+            return (pem);
+        }
     }
-/*
- * Clean up and return.
- */
-    (void) StopLsof();
+    /*
+     * Clean up and return.
+     */
+    (void)StopLsof();
     if (!*ff && !ie) {
-	if (pem)
-	    (void) PrtMsg(pem, Pn);
-	(void) snprintf(buf, sizeof(buf) - 1,
-	    "ERROR!!!  %s test file %s not found by lsof",
-	    strcmp(xlnk, "0") ? "linked" : "unlinked",
-	    Path);
-	buf[sizeof(buf) - 1] = '\0';
-	pem = MkStrCpy(buf, &ti);
+        if (pem)
+            (void)PrtMsg(pem, Pn);
+        (void)snprintf(buf, sizeof(buf) - 1,
+                       "ERROR!!!  %s test file %s not found by lsof",
+                       strcmp(xlnk, "0") ? "linked" : "unlinked", Path);
+        buf[sizeof(buf) - 1] = '\0';
+        pem = MkStrCpy(buf, &ti);
     }
     if (ie)
-	return((char *)NULL);
-    return(pem);
+        return ((char *)NULL);
+    return (pem);
 }
diff --git a/tests/LTsock.c b/tests/LTsock.c
index bc0750f..9206581 100644
--- a/tests/LTsock.c
+++ b/tests/LTsock.c
@@ -5,7 +5,6 @@
  * Purdue University
  */
 
-
 /*
  * Copyright 2002 Purdue Research Foundation, West Lafayette, Indiana
  * 47907.  All rights reserved.
@@ -32,11 +31,6 @@
  * 4. This notice may not be removed or altered.
  */
 
-#ifndef lint
-static char copyright[] =
-"@(#) Copyright 2002 Purdue Research Foundation.\nAll rights reserved.\n";
-#endif
-
 #include "LsofTest.h"
 #include "lsof_fields.h"
 
@@ -46,841 +40,803 @@ static char copyright[] =
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
-
 /*
  * Pre-definitions that make be changed or revoked by dialects
  */
 
-#define SIGHANDLER_T	void		/* signal handler function type */
-#define	LT_SOCKLEN_T	int		/* socket length type */
-
+#define SIGHANDLER_T void /* signal handler function type */
+#define LT_SOCKLEN_T int  /* socket length type */
 
-#if	defined(LT_DIAL_aix)
+#if defined(LT_DIAL_aix)
 /*
  * AIX-specific items
  */
 
-#undef	LT_SOCKLEN_T
-#define	LT_SOCKLEN_T	size_t
-#endif	/* defined(LT_DIAL_aix) */
+#    undef LT_SOCKLEN_T
+#    define LT_SOCKLEN_T size_t
+#endif /* defined(LT_DIAL_aix) */
 
-
-#if	defined(LT_DIAL_darwin)
+#if defined(LT_DIAL_darwin)
 /*
  * Darwin-specific items
  */
 
-# if	LT_VERS>=800
-#undef	LT_SOCKLEN_T
-#define	LT_SOCKLEN_T	socklen_t
-# endif	/* LT_VERS>=800 */
-#endif	/* defined(LT_DIAL_darwin) */
-
+#    if LT_VERS >= 800
+#        undef LT_SOCKLEN_T
+#        define LT_SOCKLEN_T socklen_t
+#    endif /* LT_VERS>=800 */
+#endif     /* defined(LT_DIAL_darwin) */
 
-#if	defined(LT_DIAL_freebsd)
+#if defined(LT_DIAL_freebsd)
 /*
  * FreeBSD-specific items
  */
-#undef	LT_SOCKLEN_T
-#define	LT_SOCKLEN_T	socklen_t
-#endif	/* defined(LT_DIAL_freebsd) */
+#    undef LT_SOCKLEN_T
+#    define LT_SOCKLEN_T socklen_t
+#endif /* defined(LT_DIAL_freebsd) */
 
-
-#if	defined(LT_DIAL_hpux)
+#if defined(LT_DIAL_hpux)
 /*
  * HP-UX-specific items
  */
 
-# if	LT_VERS>=1123 && defined(__GNUC__)
-#undef	LT_SOCKLEN_T
-#define	LT_SOCKLEN_T	size_t
-# endif	/* LT_VERS>=1123 && defined(__GNUC__) */
-#endif	/* defined(LT_DIAL_hpux) */
+#    if LT_VERS >= 1123 && defined(__GNUC__)
+#        undef LT_SOCKLEN_T
+#        define LT_SOCKLEN_T size_t
+#    endif /* LT_VERS>=1123 && defined(__GNUC__) */
+#endif     /* defined(LT_DIAL_hpux) */
 
+#if defined(LT_DIAL_linux)
+/*
+ * Linux-specific items
+ */
+
+#    undef LT_SOCKLEN_T
+#    define LT_SOCKLEN_T socklen_t
+#endif /* defined(LT_DIAL_linux) */
 
-#if	defined(LT_DIAL_ou)
+#if defined(LT_DIAL_ou)
 /*
  * OpenUNIX-specific items
  */
 
-#undef	LT_SOCKLEN_T
-#define	LT_SOCKLEN_T	size_t
-#endif	/* defined(LT_DIAL_ou) */
+#    undef LT_SOCKLEN_T
+#    define LT_SOCKLEN_T size_t
+#endif /* defined(LT_DIAL_ou) */
 
-
-#if	defined(LT_DIAL_uw)
+#if defined(LT_DIAL_uw)
 /*
  * UnixWare-specific items
  */
 
-#undef	LT_SOCKLEN_T
-#define	LT_SOCKLEN_T	size_t
-#endif	/* defined(LT_DIAL_uw) */
-
+#    undef LT_SOCKLEN_T
+#    define LT_SOCKLEN_T size_t
+#endif /* defined(LT_DIAL_uw) */
 
 /*
  * Local definitions
  */
 
-#define	ALARMTM		30		/* alarm timer */
+#define ALARMTM 30 /* alarm timer */
 
-#define	LT_CLNT		0		/* child process index */
-#define	LT_SRVR		1		/* parent process index */
+#define LT_CLNT 0 /* child process index */
+#define LT_SRVR 1 /* parent process index */
 
-#define	LT_FNF		0		/* file not found */
-#define LT_FBYIP	1		/* file found by IP address */
-#define	LT_FBYHN	2		/* file found by host name */
-#define	LT_FBYPORT	4		/* file found by port */
+#define LT_FNF 0     /* file not found */
+#define LT_FBYIP 1   /* file found by IP address */
+#define LT_FBYHN 2   /* file found by host name */
+#define LT_FBYPORT 4 /* file found by port */
 
-#if	!defined(MAXHOSTNAMELEN)
-#define	MAXHOSTNAMELEN	256		/* maximum host name length */
-#endif	/* !defined(MAXHOSTNAMELEN) */
-
-#if	!defined(MAXPATHLEN)
-#define	MAXPATHLEN	1024		/* maximum path length */
-#endif	/* !defined(MAXPATHLEN) */
+#if !defined(MAXHOSTNAMELEN)
+#    define MAXHOSTNAMELEN 256 /* maximum host name length */
+#endif                         /* !defined(MAXHOSTNAMELEN) */
 
+#if !defined(MAXPATHLEN)
+#    define MAXPATHLEN 1024 /* maximum path length */
+#endif                      /* !defined(MAXPATHLEN) */
 
 /*
  * Local structure definitions.
  */
 
-
-typedef struct fdpara {		/* file descriptor parameters */
-    int fd;			/* FD */
-    char *fds;			/* FD in ASCII */
-    int ff;			/* file found flags (see LT_F*) */
-    char *host;			/* host name */
-    int hlen;			/* strlen(host) */
-    char *ipaddr;		/* dotted IP address */
-    int ilen;			/* strlen(ipaddr) */
-    pid_t pid;			/* PID of process */
-    char *port;			/* port in ASCII */
-    int plen;			/* strlen(port) */
-    struct sockaddr_in sa;	/* socket's address */
+typedef struct fdpara {    /* file descriptor parameters */
+    int fd;                /* FD */
+    char *fds;             /* FD in ASCII */
+    int ff;                /* file found flags (see LT_F*) */
+    char *host;            /* host name */
+    int hlen;              /* strlen(host) */
+    char *ipaddr;          /* dotted IP address */
+    int ilen;              /* strlen(ipaddr) */
+    pid_t pid;             /* PID of process */
+    char *port;            /* port in ASCII */
+    int plen;              /* strlen(port) */
+    struct sockaddr_in sa; /* socket's address */
 } fdpara_t;
 
-
 /*
  * Globals
  */
 
-pid_t CPid = (pid_t)0;		/* client PID */
-fdpara_t FdPara[2];		/* file descriptor parameters */
-#define	NFDPARA	(sizeof(FdPara) /sizeof(fdpara_t))
-struct sockaddr_in Myad;	/* my (server) socket address */
-pid_t MyPid = (pid_t)0;		/* PID of this process */
-char *Pn = (char *)NULL;	/* program name */
-char *PtNm[] = { "client", "server" };
-				/* program type name */
-int Ssock = -1;			/* server socket */
-
+pid_t CPid = (pid_t)0; /* client PID */
+fdpara_t FdPara[2];    /* file descriptor parameters */
+#define NFDPARA (sizeof(FdPara) / sizeof(fdpara_t))
+struct sockaddr_in Myad; /* my (server) socket address */
+pid_t MyPid = (pid_t)0;  /* PID of this process */
+char *Pn = (char *)NULL; /* program name */
+char *PtNm[] = {"client", "server"};
+/* program type name */
+int Ssock = -1; /* server socket */
 
 /*
  * Local function prototypes
  */
 
-_PROTOTYPE(static void CleanupClnt,(void));
-_PROTOTYPE(static void CleanupSrvr,(void));
-_PROTOTYPE(static SIGHANDLER_T HandleClntAlarm,(int sig));
-_PROTOTYPE(static SIGHANDLER_T HandleSrvrAlarm,(int sig));
-_PROTOTYPE(static char *FindSock,(int fn));
-_PROTOTYPE(static void StartClnt,(struct sockaddr_in *cad));
-
+static void CleanupClnt(void);
+static void CleanupSrvr(void);
+static SIGHANDLER_T HandleClntAlarm(int sig);
+static SIGHANDLER_T HandleSrvrAlarm(int sig);
+static char *FindSock(int fn);
+static void StartClnt(struct sockaddr_in *cad);
 
 /*
  * Main program
  */
 
-int
-main(argc, argv)
-    int argc;				/* argument count */
-    char *argv[];			/* arguments */
+int main(int argc,     /* argument count */
+         char *argv[]) /* arguments */
 {
-    struct sockaddr_in aa;		/* accept address */
-    struct sockaddr_in ba;		/* bind address */
-    char buf[2048];			/* temporary buffer */
-    int bufl = sizeof(buf);		/* size of buf[] */
-    struct sockaddr_in ca;		/* connect address */
-    char *cem;				/* current error message pointer */
-    char *ep;				/* error message parameter */
-    char hnm[MAXHOSTNAMELEN + 1];	/* this host's name */
-    char *host;				/* host name */
-    struct hostent *hp;			/* this host's hostent structure */
-    char *ipaddr;			/* IP address */
-    char *pem = (char *)NULL;		/* previous error message */
-    char *port;				/* port */
-    LT_SOCKLEN_T sal;			/* socket address length */
-    char *tcp;				/* temporary character size */
-    int ti, tj, tk;			/* temporary indexes */
-    int tsfd;				/* temporary socket FD */
-    int xv = 0;				/* exit value */
-/*
- * Get program name and PID, issue start message, and build space prefix.
- */
+    struct sockaddr_in aa;        /* accept address */
+    struct sockaddr_in ba;        /* bind address */
+    char buf[2048];               /* temporary buffer */
+    int bufl = sizeof(buf);       /* size of buf[] */
+    struct sockaddr_in ca;        /* connect address */
+    char *cem;                    /* current error message pointer */
+    char *ep;                     /* error message parameter */
+    char hnm[MAXHOSTNAMELEN + 1]; /* this host's name */
+    char *host;                   /* host name */
+    struct hostent *hp;           /* this host's hostent structure */
+    char *ipaddr;                 /* IP address */
+    char *pem = (char *)NULL;     /* previous error message */
+    char *port;                   /* port */
+    LT_SOCKLEN_T sal;             /* socket address length */
+    char *tcp;                    /* temporary character size */
+    int ti, tj, tk;               /* temporary indexes */
+    int tsfd;                     /* temporary socket FD */
+    int xv = 0;                   /* exit value */
+                                  /*
+                                   * Get program name and PID, issue start message, and build space prefix.
+                                   */
     if ((Pn = strrchr(argv[0], '/')))
-	Pn++;
+        Pn++;
     else
-	Pn = argv[0];
+        Pn = argv[0];
     MyPid = getpid();
-    (void) printf("%s ... ", Pn);
-    (void) fflush(stdout);
+    (void)printf("%s ... ", Pn);
+    (void)fflush(stdout);
     PrtMsg((char *)NULL, Pn);
-/*
- * Initalize the FdPara[] array before any CleanupClnt() call.
- */
+    /*
+     * Initialize the FdPara[] array before any CleanupClnt() call.
+     */
     for (ti = 0; ti < NFDPARA; ti++) {
-	(void) memset((void *)&FdPara[ti], 0, sizeof(fdpara_t));
-	FdPara[ti].fd = -1;
-	FdPara[ti].ff = LT_FNF;
+        (void)memset((void *)&FdPara[ti], 0, sizeof(fdpara_t));
+        FdPara[ti].fd = -1;
+        FdPara[ti].ff = LT_FNF;
     }
-/*
- * Process arguments.
- */
+    /*
+     * Process arguments.
+     */
     if (ScanArg(argc, argv, "h", Pn))
-	xv = 1;
+        xv = 1;
     if (xv || LTopt_h) {
-	(void) PrtMsg("usage: [-h]", Pn);
-	PrtMsgX("       -h       print help (this panel)", Pn, CleanupSrvr,
-		xv);
+        (void)PrtMsg("usage: [-h]", Pn);
+        PrtMsgX("       -h       print help (this panel)", Pn, CleanupSrvr, xv);
     }
-/*
- * See if lsof can be executed and can access kernel memory.
- */
+    /*
+     * See if lsof can be executed and can access kernel memory.
+     */
     if ((cem = IsLsofExec()))
-	(void) PrtMsgX(cem, Pn, CleanupSrvr, 1);
+        (void)PrtMsgX(cem, Pn, CleanupSrvr, 1);
     if ((cem = CanRdKmem()))
-	(void) PrtMsgX(cem, Pn, CleanupSrvr, 1);
-/*
- * Get the host name and its IP address.  Convert the IP address to dotted
- * ASCII form.
- */
+        (void)PrtMsgX(cem, Pn, CleanupSrvr, 1);
+    /*
+     * Get the host name and its IP address.  Convert the IP address to dotted
+     * ASCII form.
+     */
     if (gethostname(hnm, sizeof(hnm) - 1)) {
-	cem = "ERROR!!!  can't get this host's name";
-	goto print_errno;
+        cem = "ERROR!!!  can't get this host's name";
+        goto print_errno;
     }
     hnm[sizeof(hnm) - 1] = '\0';
     if (!(hp = gethostbyname(hnm))) {
-	(void) snprintf(buf, bufl - 1, "ERROR!!!  can't get IP address for %s",
-	    hnm);
-	buf[bufl - 1] = '\0';
-	cem = buf;
-	goto print_errno;
+        // fallback to localhost if hostname cannot be resolved
+        strcpy(hnm, "localhost");
+        if (!(hp = gethostbyname(hnm))) {
+            (void)snprintf(buf, bufl - 1,
+                           "ERROR!!!  can't get IP address for %s", hnm);
+            buf[bufl - 1] = '\0';
+            cem = buf;
+            goto print_errno;
+        }
     }
-    (void) memset((void *)&Myad, 0, sizeof(Myad));
+    (void)memset((void *)&Myad, 0, sizeof(Myad));
     if ((ti = hp->h_length) > sizeof(Myad.sin_addr))
-	ti = sizeof(Myad.sin_addr);
-    (void) memcpy((void *)&Myad.sin_addr, (void *)hp->h_addr, ti);
+        ti = sizeof(Myad.sin_addr);
+    (void)memcpy((void *)&Myad.sin_addr, (void *)hp->h_addr, ti);
     Myad.sin_family = hp->h_addrtype;
-/*
- * Get INET domain socket FDs.
- */
+    /*
+     * Get INET domain socket FDs.
+     */
     for (ti = 0; ti < NFDPARA; ti++) {
-	if ((tsfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
-	    ep = "socket";
-
-print_errno_by_ti:
-
-	/*
-	 * Report socket function error.
-	 *
-	 * Entry: ep   = function name
-	 *	  hnm  = this host's name
-	 *	  Myad = this host's IP address
-	 *	  ti   =  FdPara[] index
-	 */
-	    (void) snprintf(buf, bufl - 1, "ERROR!!!  %s %s() failure",
-		PtNm[ti], ep);
-	    buf[bufl - 1] = '\0';
-	    PrtMsg(buf, Pn);
-	    (void) snprintf(buf, bufl - 1, "    host: %s",
-		FdPara[ti].host ? FdPara[ti].host : hnm);
-	    buf[bufl - 1] = '\0';
-	    PrtMsg(buf, Pn);
-	    (void) snprintf(buf, bufl - 1, "    IP: %s",
-		FdPara[ti].ipaddr ? FdPara[ti].ipaddr
-				  : inet_ntoa(Myad.sin_addr));
-	    buf[bufl - 1] = '\0';
-	    cem = buf;
-
-print_errno:
-
-	/*
-	 * Report errno.
-	 *
-	 * Entry: errno = error number
-	 */
-	    PrtMsg(cem, Pn);
-	    (void) snprintf(buf, bufl - 1, "    Errno %d: %s", errno,
-		strerror(errno));
-	    buf[bufl - 1] = '\0';
-	    PrtMsgX(buf, Pn, CleanupSrvr, 1);
-	}
+        if ((tsfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+            ep = "socket";
+
+        print_errno_by_ti:
+
+            /*
+             * Report socket function error.
+             *
+             * Entry: ep   = function name
+             *	  hnm  = this host's name
+             *	  Myad = this host's IP address
+             *	  ti   =  FdPara[] index
+             */
+            (void)snprintf(buf, bufl - 1, "ERROR!!!  %s %s() failure", PtNm[ti],
+                           ep);
+            buf[bufl - 1] = '\0';
+            PrtMsg(buf, Pn);
+            (void)snprintf(buf, bufl - 1, "    host: %s",
+                           FdPara[ti].host ? FdPara[ti].host : hnm);
+            buf[bufl - 1] = '\0';
+            PrtMsg(buf, Pn);
+            (void)snprintf(buf, bufl - 1, "    IP: %s",
+                           FdPara[ti].ipaddr ? FdPara[ti].ipaddr
+                                             : inet_ntoa(Myad.sin_addr));
+            buf[bufl - 1] = '\0';
+            cem = buf;
+
+        print_errno:
+
+            /*
+             * Report errno.
+             *
+             * Entry: errno = error number
+             */
+            PrtMsg(cem, Pn);
+            (void)snprintf(buf, bufl - 1, "    Errno %d: %s", errno,
+                           strerror(errno));
+            buf[bufl - 1] = '\0';
+            PrtMsgX(buf, Pn, CleanupSrvr, 1);
+        }
+        /*
+         * Put the FD just acquired in FdPara[ti].fd.
+         *
+         * Set the file-not-found to LT_FNF.
+         *
+         * Save the server socket if this FdPara[] is for it.
+         */
+        FdPara[ti].fd = tsfd;
+        (void)snprintf(buf, bufl - 1, "%d", tsfd);
+        buf[bufl - 1] = '\0';
+        FdPara[ti].fds = MkStrCpy(buf, &tj);
+        if (ti == LT_SRVR)
+            Ssock = tsfd;
+    }
     /*
-     * Put the FD just acquired in FdPara[ti].fd.
+     * Bind the host name to the server socket.
      *
-     * Set the file-not-found to LT_FNF.
+     * Get and save the server's socket address.
      *
-     * Save the server socket if this FdPara[] is for it.
+     * Initiate a listen with an address list of one.
      */
-	FdPara[ti].fd = tsfd;
-	(void) snprintf(buf, bufl - 1, "%d", tsfd);
-	buf[bufl - 1] = '\0';
-	FdPara[ti].fds = MkStrCpy(buf, &tj);
-	if (ti == LT_SRVR)
-	    Ssock = tsfd;
-    }
-/*
- * Bind the host name to the server socket.
- *
- * Get and save the server's socket address.
- *
- * Initiate a listen with an address list of one.
- */
-    (void) memcpy((void *)&ba, (void *)&Myad, sizeof(ba));
+    (void)memcpy((void *)&ba, (void *)&Myad, sizeof(ba));
     ti = LT_SRVR;
     FdPara[ti].pid = MyPid;
     if (bind(Ssock, (struct sockaddr *)&ba, sizeof(ba)) < 0) {
-	ep = "bind";
-	goto print_errno_by_ti;
+        ep = "bind";
+        goto print_errno_by_ti;
     }
     sal = (LT_SOCKLEN_T)sizeof(ca);
     if (getsockname(Ssock, (struct sockaddr *)&ca, &sal)) {
-	ep = "getsockname";
-	goto print_errno_by_ti;
+        ep = "getsockname";
+        goto print_errno_by_ti;
     }
-    (void) memcpy((void *)&FdPara[ti].sa, (void *)&ca, sizeof(FdPara[ti].sa));
+    (void)memcpy((void *)&FdPara[ti].sa, (void *)&ca, sizeof(FdPara[ti].sa));
     if (listen(Ssock, 1) < 0) {
-	ep = "listen";
-	goto print_errno_by_ti;
+        ep = "listen";
+        goto print_errno_by_ti;
     }
-/*
- * Fork a child process to run as the client.
- */
+    /*
+     * Fork a child process to run as the client.
+     */
     switch ((CPid = (pid_t)fork())) {
     case (pid_t)0:
 
-    /*
-     * This is the child.  Start the client.
-     */
-	StartClnt(&ca);
-	(void) PrtMsgX("ERROR!!!  unexpected client return", Pn, CleanupSrvr,
-		       1);
+        /*
+         * This is the child.  Start the client.
+         */
+        StartClnt(&ca);
+        (void)PrtMsgX("ERROR!!!  unexpected client return", Pn, CleanupSrvr, 1);
     case (pid_t)-1:
 
-    /*
-     * This is a fork error.
-     */
-	cem = "ERROR!!! fork() error";
-	goto print_errno;
+        /*
+         * This is a fork error.
+         */
+        cem = "ERROR!!! fork() error";
+        goto print_errno;
     default:
 
+        /*
+         * This is the parent.
+         *
+         * Save the client's PID.
+         *
+         * Close the client's socket.
+         */
+        FdPara[LT_CLNT].pid = CPid;
+        if (FdPara[LT_CLNT].fd >= 0) {
+            (void)close(FdPara[LT_CLNT].fd);
+            FdPara[LT_CLNT].fd = -1;
+        }
+    }
     /*
-     * This is the parent.
+     * Set a SIGALRM, then accept() the connection from the client.
      *
-     * Save the client's PID.
+     * Save the client's socket address.
      *
-     * Close the client's socket.
+     * Replace the server's FD with the accepted one and close the original.
      */
-	FdPara[LT_CLNT].pid = CPid;
-	if (FdPara[LT_CLNT].fd >= 0) {
-	    (void) close(FdPara[LT_CLNT].fd);
-	    FdPara[LT_CLNT].fd = -1;
-	}
-    }
-/*
- * Set a SIGALRM, then accept() the connection from the client.
- *
- * Save the client's socket address.
- *
- * Replace the server's FD with the accepted one and close the original.
- */
     sal = (LT_SOCKLEN_T)sizeof(aa);
-    (void) alarm(0);
-    (void) signal(SIGALRM, HandleSrvrAlarm);
-    (void) alarm(ALARMTM);
+    (void)alarm(0);
+    (void)signal(SIGALRM, HandleSrvrAlarm);
+    (void)alarm(ALARMTM);
     tsfd = FdPara[LT_SRVR].fd = accept(Ssock, (struct sockaddr *)&aa, &sal);
-    (void) alarm(0);
-    (void) signal(SIGALRM, SIG_DFL);
+    (void)alarm(0);
+    (void)signal(SIGALRM, SIG_DFL);
     if (tsfd < 0) {
-	ep = "accept";
-	goto print_errno_by_ti;
+        ep = "accept";
+        goto print_errno_by_ti;
     }
-    (void) snprintf(buf, bufl - 1, "%d", tsfd);
+    (void)snprintf(buf, bufl - 1, "%d", tsfd);
     buf[bufl - 1] = '\0';
     if (FdPara[LT_SRVR].fds)
-	(void) free((void *)FdPara[LT_SRVR].fds);
+        (void)free((void *)FdPara[LT_SRVR].fds);
     FdPara[LT_SRVR].fds = MkStrCpy(buf, &tj);
     ti = LT_CLNT;
-    (void) memcpy((void *)&FdPara[ti].sa, (void *)&aa, sizeof(FdPara[ti].sa));
-    (void) close(Ssock);
+    (void)memcpy((void *)&FdPara[ti].sa, (void *)&aa, sizeof(FdPara[ti].sa));
+    (void)close(Ssock);
     Ssock = -1;
-/*
- * Convert the client and server IP address to ASCII form.
- *
- * Look up the client and server host names for their IP addresses.
- *
- * Convert the port from the socket address to host form.
- */
+    /*
+     * Convert the client and server IP address to ASCII form.
+     *
+     * Look up the client and server host names for their IP addresses.
+     *
+     * Convert the port from the socket address to host form.
+     */
     for (ti = 0; ti < NFDPARA; ti++) {
-	tcp = inet_ntoa(FdPara[ti].sa.sin_addr);
-	FdPara[ti].ipaddr = MkStrCpy(tcp, &FdPara[ti].ilen);
-	(void) snprintf(buf, bufl - 1, "%d",
-	    (int)ntohs(FdPara[ti].sa.sin_port));
-	buf[bufl - 1] = '\0';
-	FdPara[ti].port = MkStrCpy(buf, &FdPara[ti].plen);
-	if (!(hp = gethostbyaddr((char *)&FdPara[ti].sa.sin_addr,
-				 sizeof(FdPara[ti].sa.sin_addr),
-				 FdPara[ti].sa.sin_family))
-	) {
-	    ep = "gethostbyaddr";
-	    goto print_errno_by_ti;
-	}
-	if (hp->h_name)
-	    FdPara[ti].host = MkStrCpy(hp->h_name, &FdPara[ti].hlen);
-	else {
-
-	/*
-	 * The connected client's socket address can't be mapped to a host
-	 * name.
-	 */
-
-	    (void) snprintf(buf, bufl - 1,
-		"ERROR!!!  can't map %s (client) to a host name",
-		FdPara[ti].ipaddr);
-	    buf[bufl - 1] = '\0';
-	    PrtMsgX(buf, Pn, CleanupSrvr, 1);
-	}
+        tcp = inet_ntoa(FdPara[ti].sa.sin_addr);
+        FdPara[ti].ipaddr = MkStrCpy(tcp, &FdPara[ti].ilen);
+        (void)snprintf(buf, bufl - 1, "%d", (int)ntohs(FdPara[ti].sa.sin_port));
+        buf[bufl - 1] = '\0';
+        FdPara[ti].port = MkStrCpy(buf, &FdPara[ti].plen);
+        if (!(hp = gethostbyaddr((char *)&FdPara[ti].sa.sin_addr,
+                                 sizeof(FdPara[ti].sa.sin_addr),
+                                 FdPara[ti].sa.sin_family))) {
+            ep = "gethostbyaddr";
+            goto print_errno_by_ti;
+        }
+        if (hp->h_name)
+            FdPara[ti].host = MkStrCpy(hp->h_name, &FdPara[ti].hlen);
+        else {
+
+            /*
+             * The connected client's socket address can't be mapped to a host
+             * name.
+             */
+
+            (void)snprintf(buf, bufl - 1,
+                           "ERROR!!!  can't map %s (client) to a host name",
+                           FdPara[ti].ipaddr);
+            buf[bufl - 1] = '\0';
+            PrtMsgX(buf, Pn, CleanupSrvr, 1);
+        }
     }
-/*
- * Call lsof three times to find the two sockets: 1) by host name and port;
- * 2) by IP address and port; and 3) by port.
- */
+    /*
+     * Call lsof three times to find the two sockets: 1) by host name and port;
+     * 2) by IP address and port; and 3) by port.
+     */
     if ((cem = FindSock(LT_FBYHN)))
-	PrtMsgX(cem, Pn, CleanupSrvr, 1);
+        PrtMsgX(cem, Pn, CleanupSrvr, 1);
     if ((cem = FindSock(LT_FBYIP)))
-	PrtMsgX(cem, Pn, CleanupSrvr, 1);
+        PrtMsgX(cem, Pn, CleanupSrvr, 1);
     if ((cem = FindSock(LT_FBYPORT)))
-	PrtMsgX(cem, Pn, CleanupSrvr, 1);
-/*
- * Check the FindSock() results.
- */
+        PrtMsgX(cem, Pn, CleanupSrvr, 1);
+    /*
+     * Check the FindSock() results.
+     */
     for (pem = (char *)NULL, ti = 0; ti < NFDPARA; ti++) {
-	if ((tj = FdPara[ti].ff) != (LT_FBYHN | LT_FBYIP | LT_FBYPORT)) {
-	    host = FdPara[ti].host;
-	    ipaddr = FdPara[ti].ipaddr;
-	    port = FdPara[ti].port;
-
-	/*
-	 * This FD wasn't found by some search method.
-	 */
-	    if (!(tj & LT_FBYHN)) {
-
-	    /*
-	     * The search by host name and port failed.
-	     */
-		(void) snprintf(buf, bufl - 1,
-		    "ERROR!!!  no %s socket by host and port: %s@%s",
-		    PtNm[ti], host, port);
-		buf[bufl - 1] = '\0';
-		if (pem)
-		    (void) PrtMsg(pem, Pn);
-		pem = MkStrCpy(buf, &tk);
-	    }
-	    if (!(tj & LT_FBYIP)) {
-
-	    /*
-	     * The search by IP address and port failed.
-	     */
-		(void) snprintf(buf, bufl - 1,
-		    "ERROR!!!  no %s socket by IP and port: %s@%s",
-		    PtNm[ti], ipaddr, port);
-		buf[bufl - 1] = '\0';
-		if (pem)
-		    (void) PrtMsg(pem, Pn);
-		pem = MkStrCpy(buf, &tk);
-	    }
-	    if (!(tj & LT_FBYPORT)) {
-
-	    /*
-	     * The search by port number failed.
-	     */
-		(void) snprintf(buf, bufl - 1,
-		    "ERROR!!!  no %s socket by port: %s",
-		    PtNm[ti], port);
-		buf[bufl - 1] = '\0';
-		if (pem)
-		    (void) PrtMsg(pem, Pn);
-		pem = MkStrCpy(buf, &tk);
-	    }
-	}
+        if ((tj = FdPara[ti].ff) != (LT_FBYHN | LT_FBYIP | LT_FBYPORT)) {
+            host = FdPara[ti].host;
+            ipaddr = FdPara[ti].ipaddr;
+            port = FdPara[ti].port;
+
+            /*
+             * This FD wasn't found by some search method.
+             */
+            if (!(tj & LT_FBYHN)) {
+
+                /*
+                 * The search by host name and port failed.
+                 */
+                (void)snprintf(buf, bufl - 1,
+                               "ERROR!!!  no %s socket by host and port: %s@%s",
+                               PtNm[ti], host, port);
+                buf[bufl - 1] = '\0';
+                if (pem)
+                    (void)PrtMsg(pem, Pn);
+                pem = MkStrCpy(buf, &tk);
+            }
+            if (!(tj & LT_FBYIP)) {
+
+                /*
+                 * The search by IP address and port failed.
+                 */
+                (void)snprintf(buf, bufl - 1,
+                               "ERROR!!!  no %s socket by IP and port: %s@%s",
+                               PtNm[ti], ipaddr, port);
+                buf[bufl - 1] = '\0';
+                if (pem)
+                    (void)PrtMsg(pem, Pn);
+                pem = MkStrCpy(buf, &tk);
+            }
+            if (!(tj & LT_FBYPORT)) {
+
+                /*
+                 * The search by port number failed.
+                 */
+                (void)snprintf(buf, bufl - 1,
+                               "ERROR!!!  no %s socket by port: %s", PtNm[ti],
+                               port);
+                buf[bufl - 1] = '\0';
+                if (pem)
+                    (void)PrtMsg(pem, Pn);
+                pem = MkStrCpy(buf, &tk);
+            }
+        }
     }
     if (pem)
-	(void) PrtMsgX(pem, Pn, CleanupSrvr, 1);
-/*
- * Exit successfully.
- */
-    (void) PrtMsgX("OK", Pn, CleanupSrvr, 0);
-    return(0);
+        (void)PrtMsgX(pem, Pn, CleanupSrvr, 1);
+    /*
+     * Exit successfully.
+     */
+    (void)PrtMsgX("OK", Pn, CleanupSrvr, 0);
+    return (0);
 }
 
-
 /*
  * ClntCleanup() -- release client resources
  */
 
-static void
-CleanupClnt()
-{
-    int tfd;				/* temporary file descriptor */
+static void CleanupClnt() {
+    int tfd; /* temporary file descriptor */
 
     if ((tfd = FdPara[LT_CLNT].fd) >= 0) {
-	(void) shutdown(tfd, 2);
-	(void) close(tfd);
-	FdPara[LT_CLNT].fd = -1;
+        (void)shutdown(tfd, 2);
+        (void)close(tfd);
+        FdPara[LT_CLNT].fd = -1;
     }
 }
 
-
 /*
  * CleanupSrvr() -- release server resources
  */
 
-static void
-CleanupSrvr()
-{
-    int tfd;				/* temporary file descriptor */
-    int ti;				/* temporary index */
-    pid_t wpid;				/* wait() PID */
+static void CleanupSrvr() {
+    int tfd;    /* temporary file descriptor */
+    int ti;     /* temporary index */
+    pid_t wpid; /* wait() PID */
 
     if ((Ssock >= 0) && (Ssock != FdPara[LT_SRVR].fd)) {
-	(void) shutdown(Ssock, 2);
-	(void) close(Ssock);
-	Ssock = -1;
+        (void)shutdown(Ssock, 2);
+        (void)close(Ssock);
+        Ssock = -1;
     }
     for (ti = 0; ti < NFDPARA; ti++) {
-	if ((tfd = FdPara[ti].fd) >= 0) {
-	    (void) shutdown(tfd, 2);
-	    (void) close(tfd);
-	    FdPara[ti].fd = -1;
-	}
+        if ((tfd = FdPara[ti].fd) >= 0) {
+            (void)shutdown(tfd, 2);
+            (void)close(tfd);
+            FdPara[ti].fd = -1;
+        }
     }
     if (CPid > 0) {
-	wpid = wait3(NULL, WNOHANG, NULL);
-	if (wpid != CPid) {
-	    kill(CPid, SIGKILL);
-	    (void) wait3(NULL, WNOHANG, NULL);
-	}
-	CPid = (pid_t)0;
+        wpid = wait3(NULL, WNOHANG, NULL);
+        if (wpid != CPid) {
+            kill(CPid, SIGKILL);
+            (void)wait3(NULL, WNOHANG, NULL);
+        }
+        CPid = (pid_t)0;
     }
 }
 
-
 /*
  * FindSock() -- find sockets with lsof
  */
 
-static char *
-FindSock(fn)
-    int fn;				/* function -- an LT_FBY* value */
+static char *FindSock(int fn) /* function -- an LT_FBY* value */
 {
-    char buf[2048];			/* temporary buffer */
-    int bufl = sizeof(buf);		/* size of buf[] */
-    char *cem;				/* current error message pointer */
-    LTfldo_t *cmdp;			/* command pointer */
-    LTfldo_t *fop;			/* field output pointer */
-    int nf;				/* number of fields */
-    int nl;				/* name length */
-    LTfldo_t *nmp;			/* name pointer */
-    char *opv[5];			/* option vector for ExecLsof() */
-    char *pem = (char *)NULL;		/* previous error message pointer */
-    pid_t pid;				/* PID */
-    int pids = 0;			/* PID found status */
-    int pl;				/* port length */
-    int px;				/* process index -- LT_CLNT or
-					 * LT_SRVR */
-    char *tcp, *tcp1;			/* temporary character pointers */
-    int ti, tj;				/* temporary integers */
-    LTfldo_t *typ;			/* file type pointer */
-/*
- * Check the function and determine the first lsof option from it.
- */
+    char buf[2048];           /* temporary buffer */
+    int bufl = sizeof(buf);   /* size of buf[] */
+    char *cem;                /* current error message pointer */
+    LTfldo_t *cmdp;           /* command pointer */
+    LTfldo_t *fop;            /* field output pointer */
+    int nf;                   /* number of fields */
+    int nl;                   /* name length */
+    LTfldo_t *nmp;            /* name pointer */
+    char *opv[5];             /* option vector for ExecLsof() */
+    char *pem = (char *)NULL; /* previous error message pointer */
+    pid_t pid;                /* PID */
+    int pids = 0;             /* PID found status */
+    int pl;                   /* port length */
+    int px;                   /* process index -- LT_CLNT or
+                               * LT_SRVR */
+    char *tcp, *tcp1;         /* temporary character pointers */
+    int ti, tj;               /* temporary integers */
+    LTfldo_t *typ;            /* file type pointer */
+                              /*
+                               * Check the function and determine the first lsof option from it.
+                               */
     ti = 0;
     switch (fn) {
     case LT_FBYHN:
-	opv[ti++] = "-P";
-	for (tj = 0; tj < NFDPARA; tj++) {
-	    (void) snprintf(buf, bufl - 1, "-i@%s:%s", FdPara[tj].host,
-		FdPara[tj].port);
-	    buf[bufl - 1] = '\0';
-	    opv[ti++] = MkStrCpy(buf, &pl);
-	}
-	break;
+        opv[ti++] = "-P";
+        for (tj = 0; tj < NFDPARA; tj++) {
+            (void)snprintf(buf, bufl - 1, "-i@%s:%s", FdPara[tj].host,
+                           FdPara[tj].port);
+            buf[bufl - 1] = '\0';
+            opv[ti++] = MkStrCpy(buf, &pl);
+        }
+        break;
     case LT_FBYIP:
-	opv[ti++] = "-Pn";
-	for (tj = 0; tj < NFDPARA; tj++) {
-	    (void) snprintf(buf, bufl - 1, "-i@%s:%s", FdPara[tj].ipaddr,
-		FdPara[tj].port);
-	    buf[bufl - 1] = '\0';
-	    opv[ti++] = MkStrCpy(buf, &pl);
-	}
-	break;
+        opv[ti++] = "-Pn";
+        for (tj = 0; tj < NFDPARA; tj++) {
+            (void)snprintf(buf, bufl - 1, "-i@%s:%s", FdPara[tj].ipaddr,
+                           FdPara[tj].port);
+            buf[bufl - 1] = '\0';
+            opv[ti++] = MkStrCpy(buf, &pl);
+        }
+        break;
     case LT_FBYPORT:
-	opv[ti++] = "-P";
-	for (tj = 0; tj < NFDPARA; tj++) {
-	    (void) snprintf(buf, bufl - 1, "-i:%s", FdPara[tj].port);
-	    buf[bufl - 1] = '\0';
-	    opv[ti++] = MkStrCpy(buf, &pl);
-	}
-	break;
+        opv[ti++] = "-P";
+        for (tj = 0; tj < NFDPARA; tj++) {
+            (void)snprintf(buf, bufl - 1, "-i:%s", FdPara[tj].port);
+            buf[bufl - 1] = '\0';
+            opv[ti++] = MkStrCpy(buf, &pl);
+        }
+        break;
     default:
-	(void) snprintf(buf, bufl - 1,
-	    "ERROR!!!  illegal FindSock() function: %d", fn);
-	buf[bufl - 1] = '\0';
-	return(MkStrCpy(buf, &ti));
+        (void)snprintf(buf, bufl - 1,
+                       "ERROR!!!  illegal FindSock() function: %d", fn);
+        buf[bufl - 1] = '\0';
+        return (MkStrCpy(buf, &ti));
     }
-/*
- * Complete the option vector and start lsof execution.
- */
+    /*
+     * Complete the option vector and start lsof execution.
+     */
 
-#if	defined(USE_LSOF_C_OPT)
+#if defined(USE_LSOF_C_OPT)
     opv[ti++] = "-C";
-#endif	/* defined(USE_LSOF_C_OPT) */
+#endif /* defined(USE_LSOF_C_OPT) */
 
     opv[ti] = (char *)NULL;
     if ((cem = ExecLsof(opv)))
-	return(cem);
-/*
- * Read lsof output.
- */
-    while ((((FdPara[LT_CLNT].ff & fn) == 0)
-    ||	    ((FdPara[LT_SRVR].ff & fn) == 0))
-    &&	   (fop = RdFrLsof(&nf, &cem))
-    ) {
-	if (cem) {
-	    if (pem)
-		(void) PrtMsg(pem, Pn);
-	    return(cem);
-	}
-	switch (fop->ft) {
-	case LSOF_FID_PID:
-
-	/*
-	 * This is a process information line.
-	 */
-	    pid = (pid_t)atoi(fop->v);
-	    pids = 1;
-	    cmdp = (LTfldo_t *)NULL;
-	    for (fop++, ti = 1; ti < nf; fop++, ti++) {
-		switch (fop->ft) {
-		case LSOF_FID_CMD:
-		    cmdp = fop;
-		    break;
-		}
-	    }
-	    if (!cmdp || ((pid != CPid) && (pid != MyPid)))
-		pids = 0;
-	    break;
-	case LSOF_FID_FD:
-
-	/*
-	 * This is a file descriptor line.
-	 *
-	 * Identify the process -- client or server.
-	 */
-	    if (!pids)
-		break;
-	    if (pid == CPid)
-		px = LT_CLNT;
-	    else if (pid == MyPid)
-		px = LT_SRVR;
-	    else
-		break;
-	/*
-	 * Make sure the FD matches the identified process.
-	 */
-	    if (strcmp(fop->v, FdPara[px].fds))
-		break;
-	/*
-	 * Scan for name and type.
-	 */
-	    nmp = typ  = (LTfldo_t *)NULL;
-	    for (fop++, ti = 1; ti < nf; fop++, ti++) {
-		switch (fop->ft) {
-		case LSOF_FID_NAME:
-		    nmp = fop;
-		    break;
-		case LSOF_FID_TYPE:
-		    typ = fop;
-		    break;
-		}
-	    }
-	/*
-	 * Check the type of the file.
-	 */
-	    if (!typ
-	    ||  (strcasecmp(typ->v, "inet") && strcasecmp(typ->v, "ipv4"))
-	    ) {
-		break;
-	    }
-	/*
-	 * Check the addess in the name, based on the calling function.
-	 */
-	    if (!nmp)
-		break;
-	    tcp = nmp->v;
-	    switch (fn) {
-	    case LT_FBYHN:
-		if (((nl = FdPara[px].hlen) <= 0)
-		||  !(tcp1 = FdPara[px].host)
-		||  strncasecmp(tcp, tcp1, nl)
-		) {
-		    break;
-		}
-		tcp += nl;
-		if ((*tcp++ != ':')
-		||  !(tcp1 = FdPara[px].port)
-		||  ((pl = FdPara[px].plen) <= 0)
-		||  strncmp(tcp, tcp1, pl)
-		) {
-		    break;
-		}
-		tcp += pl;
-		if ((*tcp == '-') || (*tcp == ' ') || !*tcp) {
-		    FdPara[px].ff |= LT_FBYHN;
-		}
-		break;
-	    case LT_FBYIP:
-		if (((nl = FdPara[px].ilen) <= 0)
-		||  !(tcp1 = FdPara[px].ipaddr)
-		||  strncasecmp(tcp, tcp1, nl)
-		) {
-		    break;
-		}
-		tcp += nl;
-		if ((*tcp++ != ':')
-		||  !(tcp1 = FdPara[px].port)
-		||  ((pl = FdPara[px].plen) <= 0)
-		||  strncmp(tcp, tcp1, pl)
-		) {
-		    break;
-		}
-		tcp += pl;
-		if ((*tcp == '-') || (*tcp == ' ') || !*tcp) {
-		    FdPara[px].ff |= LT_FBYIP;
-		}
-		break;
-	    case LT_FBYPORT:
-		if (!(tcp = strchr(tcp, ':')))
-		    break;
-		tcp++;
-		if (!(tcp1 = FdPara[px].port)
-		||  ((pl = FdPara[px].plen) <= 0)
-		||  strncmp(tcp, tcp1, pl)
-		) {
-		    break;
-		}
-		tcp += pl;
-		if ((*tcp == '-') || (*tcp == ' ') || !*tcp) {
-		    FdPara[px].ff |= LT_FBYPORT;
-		}
-		break;
-	    }
-	}
+        return (cem);
+    /*
+     * Read lsof output.
+     */
+    while ((((FdPara[LT_CLNT].ff & fn) == 0) ||
+            ((FdPara[LT_SRVR].ff & fn) == 0)) &&
+           (fop = RdFrLsof(&nf, &cem))) {
+        if (cem) {
+            if (pem)
+                (void)PrtMsg(pem, Pn);
+            return (cem);
+        }
+        switch (fop->ft) {
+        case LSOF_FID_PID:
+
+            /*
+             * This is a process information line.
+             */
+            pid = (pid_t)atoi(fop->v);
+            pids = 1;
+            cmdp = (LTfldo_t *)NULL;
+            for (fop++, ti = 1; ti < nf; fop++, ti++) {
+                switch (fop->ft) {
+                case LSOF_FID_CMD:
+                    cmdp = fop;
+                    break;
+                }
+            }
+            if (!cmdp || ((pid != CPid) && (pid != MyPid)))
+                pids = 0;
+            break;
+        case LSOF_FID_FD:
+
+            /*
+             * This is a file descriptor line.
+             *
+             * Identify the process -- client or server.
+             */
+            if (!pids)
+                break;
+            if (pid == CPid)
+                px = LT_CLNT;
+            else if (pid == MyPid)
+                px = LT_SRVR;
+            else
+                break;
+            /*
+             * Make sure the FD matches the identified process.
+             */
+            if (strcmp(fop->v, FdPara[px].fds))
+                break;
+            /*
+             * Scan for name and type.
+             */
+            nmp = typ = (LTfldo_t *)NULL;
+            for (fop++, ti = 1; ti < nf; fop++, ti++) {
+                switch (fop->ft) {
+                case LSOF_FID_NAME:
+                    nmp = fop;
+                    break;
+                case LSOF_FID_TYPE:
+                    typ = fop;
+                    break;
+                }
+            }
+            /*
+             * Check the type of the file.
+             */
+            if (!typ ||
+                (strcasecmp(typ->v, "inet") && strcasecmp(typ->v, "ipv4"))) {
+                break;
+            }
+            /*
+             * Check the address in the name, based on the calling function.
+             */
+            if (!nmp)
+                break;
+            tcp = nmp->v;
+            switch (fn) {
+            case LT_FBYHN:
+                if (((nl = FdPara[px].hlen) <= 0) ||
+                    !(tcp1 = FdPara[px].host) || strncasecmp(tcp, tcp1, nl)) {
+                    break;
+                }
+                tcp += nl;
+                if ((*tcp++ != ':') || !(tcp1 = FdPara[px].port) ||
+                    ((pl = FdPara[px].plen) <= 0) || strncmp(tcp, tcp1, pl)) {
+                    break;
+                }
+                tcp += pl;
+                if ((*tcp == '-') || (*tcp == ' ') || !*tcp) {
+                    FdPara[px].ff |= LT_FBYHN;
+                }
+                break;
+            case LT_FBYIP:
+                if (((nl = FdPara[px].ilen) <= 0) ||
+                    !(tcp1 = FdPara[px].ipaddr) || strncasecmp(tcp, tcp1, nl)) {
+                    break;
+                }
+                tcp += nl;
+                if ((*tcp++ != ':') || !(tcp1 = FdPara[px].port) ||
+                    ((pl = FdPara[px].plen) <= 0) || strncmp(tcp, tcp1, pl)) {
+                    break;
+                }
+                tcp += pl;
+                if ((*tcp == '-') || (*tcp == ' ') || !*tcp) {
+                    FdPara[px].ff |= LT_FBYIP;
+                }
+                break;
+            case LT_FBYPORT:
+                if (!(tcp = strchr(tcp, ':')))
+                    break;
+                tcp++;
+                if (!(tcp1 = FdPara[px].port) ||
+                    ((pl = FdPara[px].plen) <= 0) || strncmp(tcp, tcp1, pl)) {
+                    break;
+                }
+                tcp += pl;
+                if ((*tcp == '-') || (*tcp == ' ') || !*tcp) {
+                    FdPara[px].ff |= LT_FBYPORT;
+                }
+                break;
+            }
+        }
     }
-/*
- * Clean up and return.
- */
-    (void) StopLsof();
-    return(pem);
+    /*
+     * Clean up and return.
+     */
+    (void)StopLsof();
+    return (pem);
 }
 
-
 /*
  * HandleClntAlarm() -- handle client alarm
  */
 
-static SIGHANDLER_T
-HandleClntAlarm(sig)
-    int sig;				/* the signal (SIGALRM) */
+static SIGHANDLER_T HandleClntAlarm(int sig) /* the signal (SIGALRM) */
 {
-    (void) PrtMsgX("ERROR!!!  client caught an alarm signal", Pn,
-	CleanupClnt, 1);
+    (void)PrtMsgX("ERROR!!!  client caught an alarm signal", Pn, CleanupClnt,
+                  1);
 }
 
-
 /*
  * Handle SrvrAlarm() -- handle server alarm
  */
 
-static SIGHANDLER_T
-HandleSrvrAlarm(sig)
-    int sig;				/* the signal (SIGALRM) */
+static SIGHANDLER_T HandleSrvrAlarm(int sig) /* the signal (SIGALRM) */
 {
-    (void) PrtMsgX("ERROR!!!  server caught an alarm signal.", Pn,
-	CleanupSrvr, 1);
+    (void)PrtMsgX("ERROR!!!  server caught an alarm signal.", Pn, CleanupSrvr,
+                  1);
 }
 
-
 /*
  * StartClnt() -- start network client
  */
 
-static void
-StartClnt(cad)
-    struct sockaddr_in *cad;		/* connection address */
+static void StartClnt(cad) struct sockaddr_in *cad; /* connection address */
 {
-    struct sockaddr_in ba;		/* bind address */
-    int br;				/* bytes read */
-    char buf[2048];			/* temporary buffer */
-    int bufl = sizeof(buf);		/* size of buf[] */
-    int cr;				/* connect() reply */
-    char *em;				/* error message pointer */
-    int fd = FdPara[LT_CLNT].fd;	/* client's socket FD */
-/*
- * Close the server's sockets.
- */
+    struct sockaddr_in ba;       /* bind address */
+    int br;                      /* bytes read */
+    char buf[2048];              /* temporary buffer */
+    int bufl = sizeof(buf);      /* size of buf[] */
+    int cr;                      /* connect() reply */
+    char *em;                    /* error message pointer */
+    int fd = FdPara[LT_CLNT].fd; /* client's socket FD */
+                                 /*
+                                  * Close the server's sockets.
+                                  */
     if ((Ssock >= 0) && (Ssock != FdPara[LT_SRVR].fd)) {
-	(void) close(Ssock);
-	Ssock = -1;
+        (void)close(Ssock);
+        Ssock = -1;
     }
     if (FdPara[LT_SRVR].fd >= 0) {
-	(void) close(FdPara[LT_SRVR].fd);
-	FdPara[LT_SRVR].fd = -1;
+        (void)close(FdPara[LT_SRVR].fd);
+        FdPara[LT_SRVR].fd = -1;
     }
-/*
- * Bind to the local address.
- */
-    (void) memcpy((void *)&ba, (void *)&Myad, sizeof(ba));
+    /*
+     * Bind to the local address.
+     */
+    (void)memcpy((void *)&ba, (void *)&Myad, sizeof(ba));
     if (bind(fd, (struct sockaddr *)&ba, sizeof(ba)) < 0) {
-	em = "bind";
+        em = "bind";
 
-client_errno:
+    client_errno:
 
-	(void) snprintf(buf, bufl - 1,
-	    "ERROR!!!  client %s error: %s", em, strerror(errno));
-	buf[bufl - 1] = '\0';
-	(void) PrtMsgX(em, Pn, CleanupClnt, 1);
+        (void)snprintf(buf, bufl - 1, "ERROR!!!  client %s error: %s", em,
+                       strerror(errno));
+        buf[bufl - 1] = '\0';
+        (void)PrtMsgX(em, Pn, CleanupClnt, 1);
     }
-/*
- * Set an alarm timeout and connect to the server.
- */
-    (void) signal(SIGALRM, HandleClntAlarm);
-    (void) alarm(ALARMTM);
+    /*
+     * Set an alarm timeout and connect to the server.
+     */
+    (void)signal(SIGALRM, HandleClntAlarm);
+    (void)alarm(ALARMTM);
     cr = connect(fd, (struct sockaddr *)cad, sizeof(struct sockaddr_in));
-    (void) alarm(0);
-    (void) signal(SIGALRM, SIG_DFL);
+    (void)alarm(0);
+    (void)signal(SIGALRM, SIG_DFL);
     if (cr) {
-	em = "connect";
-	goto client_errno;
+        em = "connect";
+        goto client_errno;
     }
-/*
- * Sleep until the socket closes or the parent kills the process.
- */
+    /*
+     * Sleep until the socket closes or the parent kills the process.
+     */
     for (br = 0; br >= 0;) {
-	sleep(1);
-	br = read(fd, buf, bufl);
+        sleep(1);
+        br = read(fd, buf, bufl);
     }
-    (void) CleanupClnt();
+    (void)CleanupClnt();
     exit(0);
 }
diff --git a/tests/LTszoff.c b/tests/LTszoff.c
index 9de433d..148a891 100644
--- a/tests/LTszoff.c
+++ b/tests/LTszoff.c
@@ -5,7 +5,6 @@
  * Purdue University
  */
 
-
 /*
  * Copyright 2002 Purdue Research Foundation, West Lafayette, Indiana
  * 47907.  All rights reserved.
@@ -32,478 +31,456 @@
  * 4. This notice may not be removed or altered.
  */
 
-#ifndef lint
-static char copyright[] =
-"@(#) Copyright 2002 Purdue Research Foundation.\nAll rights reserved.\n";
-#endif
-
 #include "LsofTest.h"
 #include "lsof_fields.h"
 
-
 /*
  * Pre-definitions that might be undefined by dialects
  */
 
-#define	OFFTST_STAT	1		/* offset tests status */
-
+#define OFFTST_STAT 1 /* offset tests status */
 
-#if	defined(LT_DIAL_linux)
+#if defined(LT_DIAL_linux)
 /*
  * Linux-specific items
  */
 
-#undef	OFFTST_STAT
-#define	OFFTST_STAT	0		/* Linux lsof may not be able to report
-					 * offsets -- see the function
-					 * ck_Linux_offset_support() */
-
-_PROTOTYPE(static int ck_Linux_offset_support,(void));
-#endif	/* defined(LT_DIAL_linux) */
+#    undef OFFTST_STAT
+#    define OFFTST_STAT                                                        \
+        0 /* Linux lsof may not be able to report                              \
+           * offsets -- see the function                                       \
+           * ck_Linux_offset_support() */
 
+static int ck_Linux_offset_support(void);
+#endif /* defined(LT_DIAL_linux) */
 
 /*
  * Local definitions
  */
 
-#define	TYTST_SZ	0	/* size test type */
-#define	TYTST_0to	1	/* 0t offset test type */
-#define	TYTST_0xo	2	/* 0x offset test type */
-#define TSTFSZ		32768	/* test file size */
-
+#define TYTST_SZ 0   /* size test type */
+#define TYTST_0to 1  /* 0t offset test type */
+#define TYTST_0xo 2  /* 0x offset test type */
+#define TSTFSZ 32768 /* test file size */
 
 /*
  * Globals
  */
 
-int Fd = -1;			/* test file descriptor; open if >= 0 */
-pid_t MyPid = (pid_t)0;		/* PID of this process */
-char *Path = (char *)NULL;	/* test file path; none if NULL */
-char *Pn = (char *)NULL;	/* program name */
-
+int Fd = -1;               /* test file descriptor; open if >= 0 */
+pid_t MyPid = (pid_t)0;    /* PID of this process */
+char *Path = (char *)NULL; /* test file path; none if NULL */
+char *Pn = (char *)NULL;   /* program name */
 
 /*
  * Local function prototypes
  */
 
-_PROTOTYPE(static void cleanup,(void));
-_PROTOTYPE(static char *testlsof,(int tt, char *opt, char *xval));
-
+static void cleanup(void);
+static char *testlsof(int tt, char *opt, char *xval);
 
 /*
  * Main program
  */
 
-int
-main(argc, argv)
-    int argc;				/* argument count */
-    char *argv[];			/* arguments */
+int main(int argc,     /* argument count */
+         char *argv[]) /* arguments */
 {
-    char buf[2048];			/* temporary buffer */
-    int do_offt = OFFTST_STAT;		/* do offset tests if == 1 */
-    char *em;				/* error message pointer */
-    int ti;				/* temporary index */
-    char *tcp;				/* temporary character pointer */
-    char *tstsz = (char *)NULL;		/* size test status */
-    char *tst0to = (char *)NULL;	/* offset 0t form test */
-    char *tst0xo = (char *)NULL;	/* offset 0x form test */
-    int xv = 0;				/* exit value */
-    char xbuf[64];			/* expected value buffer */
-/*
- * Get program name and PID, issue start message, and build space prefix.
- */
+    char buf[2048];              /* temporary buffer */
+    int do_offt = OFFTST_STAT;   /* do offset tests if == 1 */
+    char *em;                    /* error message pointer */
+    int ti;                      /* temporary index */
+    char *tcp;                   /* temporary character pointer */
+    char *tstsz = (char *)NULL;  /* size test status */
+    char *tst0to = (char *)NULL; /* offset 0t form test */
+    char *tst0xo = (char *)NULL; /* offset 0x form test */
+    int xv = 0;                  /* exit value */
+    char xbuf[64];               /* expected value buffer */
+                                 /*
+                                  * Get program name and PID, issue start message, and build space prefix.
+                                  */
     if ((Pn = strrchr(argv[0], '/')))
-	Pn++;
+        Pn++;
     else
-	Pn = argv[0];
+        Pn = argv[0];
     MyPid = getpid();
-    (void) printf("%s ... ", Pn);
-    (void) fflush(stdout);
+    (void)printf("%s ... ", Pn);
+    (void)fflush(stdout);
     PrtMsg((char *)NULL, Pn);
-/*
- * Process arguments.
- */
+    /*
+     * Process arguments.
+     */
     if (ScanArg(argc, argv, "hp:", Pn))
-	xv = 1;
+        xv = 1;
     if (xv || LTopt_h) {
-	(void) PrtMsg("usage: [-h] [-p path]", Pn);
-	PrtMsg       ("       -h       print help (this panel)", Pn);
-	PrtMsgX      ("       -p path  define test file path", Pn, cleanup, xv);
+        (void)PrtMsg("usage: [-h] [-p path]", Pn);
+        PrtMsg("       -h       print help (this panel)", Pn);
+        PrtMsgX("       -p path  define test file path", Pn, cleanup, xv);
     }
 
-#if	defined(LT_DIAL_linux)
-/*
- * If this is Linux, see if lsof can report file offsets.
- */
-	do_offt = ck_Linux_offset_support();
-#endif	/* defined(LT_DIAL_linux) */
+#if defined(LT_DIAL_linux)
+    /*
+     * If this is Linux, see if lsof can report file offsets.
+     */
+    do_offt = ck_Linux_offset_support();
+#endif /* defined(LT_DIAL_linux) */
 
-/*
- * See if lsof can be executed and can access kernel memory.
- */
+    /*
+     * See if lsof can be executed and can access kernel memory.
+     */
     if ((em = IsLsofExec()))
-	(void) PrtMsgX(em, Pn, cleanup, 1);
+        (void)PrtMsgX(em, Pn, cleanup, 1);
     if ((em = CanRdKmem()))
-	(void) PrtMsgX(em, Pn, cleanup, 1);
-/*
- * If a path was supplied in an "-p path" option, use it.  Otherwise construct
- * a path in the CWD.
- */
+        (void)PrtMsgX(em, Pn, cleanup, 1);
+    /*
+     * If a path was supplied in an "-p path" option, use it.  Otherwise
+     * construct a path in the CWD.
+     */
     if (!(Path = LTopt_p)) {
-	(void) snprintf(buf, sizeof(buf) - 1, "./config.LTszoff%ld",
-	(long)MyPid);
-	buf[sizeof(buf) - 1] = '\0';
-	Path = MkStrCpy(buf, &ti);
+        (void)snprintf(buf, sizeof(buf) - 1, "./config.LTszoff%ld",
+                       (long)MyPid);
+        buf[sizeof(buf) - 1] = '\0';
+        Path = MkStrCpy(buf, &ti);
     }
-/*
- * Open a new test file at the specified path.
- */
-    (void) unlink(Path);
-    if ((Fd = open(Path, O_RDWR|O_CREAT, 0600)) < 0) {
-	(void) fprintf(stderr, "ERROR!!!  can't open %s\n", Path);
-
-print_file_error:
-
-	MsgStat = 1;
-	(void) snprintf(buf, sizeof(buf) - 1, "      Errno %d: %s",
-	    errno, strerror(errno));
-	buf[sizeof(buf) - 1] = '\0';
-	(void) PrtMsgX(buf, Pn, cleanup, 1);
+    /*
+     * Open a new test file at the specified path.
+     */
+    (void)unlink(Path);
+    if ((Fd = open(Path, O_RDWR | O_CREAT, 0600)) < 0) {
+        (void)fprintf(stderr, "ERROR!!!  can't open %s\n", Path);
+
+    print_file_error:
+
+        MsgStat = 1;
+        (void)snprintf(buf, sizeof(buf) - 1, "      Errno %d: %s", errno,
+                       strerror(errno));
+        buf[sizeof(buf) - 1] = '\0';
+        (void)PrtMsgX(buf, Pn, cleanup, 1);
     }
-/*
- * Write the test file to its expected size.
- */
+    /*
+     * Write the test file to its expected size.
+     */
     for (ti = 0; ti < sizeof(buf); ti++) {
-	buf[ti] = (char)(ti & 0xff);
+        buf[ti] = (char)(ti & 0xff);
     }
     for (ti = 0; ti < TSTFSZ; ti += sizeof(buf)) {
-	if (write(Fd, buf, sizeof(buf)) != sizeof(buf)) {
-	    (void) fprintf(stderr, "ERROR!!!  can't write %d bytes to %s\n",
-		(int)sizeof(buf), Path);
-	     goto print_file_error;
-	}
+        if (write(Fd, buf, sizeof(buf)) != sizeof(buf)) {
+            (void)fprintf(stderr, "ERROR!!!  can't write %d bytes to %s\n",
+                          (int)sizeof(buf), Path);
+            goto print_file_error;
+        }
     }
-/*
- * Fsync() the file.
- */
+    /*
+     * Fsync() the file.
+     */
     if (fsync(Fd)) {
-	(void) fprintf(stderr, "ERROR!!!  can't fsync %s\n", Path);
-	goto print_file_error;
+        (void)fprintf(stderr, "ERROR!!!  can't fsync %s\n", Path);
+        goto print_file_error;
     }
-/*
- * Do the tests.  Skip offset tests as indicated.
- */
-    (void) snprintf(xbuf, sizeof(xbuf) - 1, "%d", TSTFSZ);
+    /*
+     * Do the tests.  Skip offset tests as indicated.
+     */
+    (void)snprintf(xbuf, sizeof(xbuf) - 1, "%d", TSTFSZ);
     xbuf[sizeof(xbuf) - 1] = '\0';
     if ((tstsz = testlsof(TYTST_SZ, "-s", xbuf)))
-	(void) PrtMsg(tstsz, Pn);
+        (void)PrtMsg(tstsz, Pn);
     if (do_offt) {
-	(void) snprintf(xbuf, sizeof(xbuf) - 1, "0t%d", TSTFSZ);
-	xbuf[sizeof(xbuf) - 1] = '\0';
-	if ((tst0to = testlsof(TYTST_0to, "-o", xbuf)))
-	    (void) PrtMsg(tst0to, Pn);
-	(void) snprintf(xbuf, sizeof(xbuf) - 1, "0x%x", TSTFSZ);
-	xbuf[sizeof(xbuf) - 1] = '\0';
-	if ((tst0xo = testlsof(TYTST_0xo, "-oo2", xbuf)))
-	    (void) PrtMsg(tst0to, Pn);
+        (void)snprintf(xbuf, sizeof(xbuf) - 1, "0t%d", TSTFSZ);
+        xbuf[sizeof(xbuf) - 1] = '\0';
+        if ((tst0to = testlsof(TYTST_0to, "-o", xbuf)))
+            (void)PrtMsg(tst0to, Pn);
+        (void)snprintf(xbuf, sizeof(xbuf) - 1, "0x%x", TSTFSZ);
+        xbuf[sizeof(xbuf) - 1] = '\0';
+        if ((tst0xo = testlsof(TYTST_0xo, "-oo2", xbuf)))
+            (void)PrtMsg(tst0to, Pn);
     } else {
-	PrtMsg("WARNING!!!  lsof can't return file offsets for this dialect,",
-	   Pn);
-	PrtMsg("  so offset tests have been disabled.", Pn);
+        PrtMsg("WARNING!!!  lsof can't return file offsets for this dialect,",
+               Pn);
+        PrtMsg("  so offset tests have been disabled.", Pn);
     }
-/*
- * Compute exit value and exit.
- */
+    /*
+     * Compute exit value and exit.
+     */
     if (tstsz || tst0to || tst0xo) {
-	tcp = (char *)NULL;
-	xv = 1;
+        tcp = (char *)NULL;
+        xv = 1;
     } else {
-	tcp = "OK";
-	xv = 0;
+        tcp = "OK";
+        xv = 0;
     }
-    (void) PrtMsgX(tcp, Pn, cleanup, xv);
-    return(0);
+    (void)PrtMsgX(tcp, Pn, cleanup, xv);
+    return (0);
 }
 
-
-#if	defined(LT_DIAL_linux)
+#if defined(LT_DIAL_linux)
 /*
  * ck_Linux_offset_support() -- see if lsof can report offsets for this
  *				Linux implementation
  */
 
-static int
-ck_Linux_offset_support()
-{
-	char buf[1024];			/* lsof output line buffer */
-	int bufl = sizeof(buf);		/* size of buf[] */
-	char *opv[5];			/* option vector for lsof */
-	int rv = 1;			/* return value:
-					 *     0 == no lsof offset support
-					 *     1 == lsof offset support */
-/*
- * Ask lsof to report the test's FD zero offset.
- */
-	if (IsLsofExec())
-	    return(0);
-	opv[0] = "-o";
-	snprintf(buf, bufl - 1, "-p%d", (int)getpid());
-	opv[1] = buf;
-	opv[2] = "-ad0";
-	opv[3] = "+w";
-	opv[4] = (char *)NULL;
-	if (ExecLsof(opv))
-	    return(0);
-/*
- * Read the lsof output.  Look for a line with "WARNING: can't report offset"
- * in it.  If it is found, then this Linux lsof can't report offsets.
- */
-	while(fgets(buf, bufl - 1, LsofFs)) {
-	    if (strstr(buf, "WARNING: can't report offset")) {
-		rv = 0;
-		break;
-	    }
-	}
-	(void) StopLsof();
-	return(rv);
+static int ck_Linux_offset_support() {
+    char buf[1024];         /* lsof output line buffer */
+    int bufl = sizeof(buf); /* size of buf[] */
+    char *opv[5];           /* option vector for lsof */
+    int rv = 1;             /* return value:
+                             *     0 == no lsof offset support
+                             *     1 == lsof offset support */
+                            /*
+                             * Ask lsof to report the test's FD zero offset.
+                             */
+    if (IsLsofExec())
+        return (0);
+    opv[0] = "-o";
+    snprintf(buf, bufl - 1, "-p%d", (int)getpid());
+    opv[1] = buf;
+    opv[2] = "-ad0";
+    opv[3] = "+w";
+    opv[4] = (char *)NULL;
+    if (ExecLsof(opv))
+        return (0);
+    /*
+     * Read the lsof output.  Look for a line with "WARNING: can't report
+     * offset" in it.  If it is found, then this Linux lsof can't report
+     * offsets.
+     */
+    while (fgets(buf, bufl - 1, LsofFs)) {
+        if (strstr(buf, "WARNING: can't report offset")) {
+            rv = 0;
+            break;
+        }
+    }
+    (void)StopLsof();
+    return (rv);
 }
-#endif	/* defined(LT_DIAL_linux) */
-
+#endif /* defined(LT_DIAL_linux) */
 
 /*
  * cleanup() -- release resources
  */
 
-static void
-cleanup()
-{
+static void cleanup() {
     if (Fd >= 0) {
-	(void) close(Fd);
-	Fd = -1;
-	if (Path) {
-	    (void) unlink(Path);
-	    Path = (char *)NULL;
-	}
+        (void)close(Fd);
+        Fd = -1;
+        if (Path) {
+            (void)unlink(Path);
+            Path = (char *)NULL;
+        }
     }
 }
 
-
 /*
  * testlsof() -- test the open file with lsof
  */
 
-static char *
-testlsof(tt, opt, xval)
-    int tt;				/* test type -- TYTST_* symbol */
-    char *opt;				/* extra lsof options */
-    char *xval;				/* expected value */
+static char *testlsof(int tt,     /* test type -- TYTST_* symbol */
+                      char *opt,  /* extra lsof options */
+                      char *xval) /* expected value */
 {
-    char buf[2048];			/* temporary buffer */
-    char *cem;				/* current error message pointer */
-    LTfldo_t *cmdp;			/* command pointer */
-    LTfldo_t *devp;			/* device pointer */
-    int ff = 0;				/* file found status */
-    LTfldo_t *fop;			/* field output pointer */
-    char ibuf[64];			/* inode number buffer */
-    LTfldo_t *inop;			/* inode number pointer */
-    LTdev_t lsofdc;			/* lsof device components */
-    int nf;				/* number of fields */
-    LTfldo_t *offp;			/* offset pointer */
-    char *opv[4];			/* option vector for ExecLsof() */
-    char *pem = (char *)NULL;		/* previous error message pointer */
-    pid_t pid;				/* PID */
-    int pids = 0;			/* PID found status */
-    struct stat sb;			/* stat(2) buffer */
-    LTdev_t stdc;			/* stat(2) device components */
-    LTfldo_t *szp;			/* size pointer */
-    char *tcp;				/* temporary character pointer */
-    int ti;				/* temporary integer */
-    char *tnm1, *tnm2;			/* test names */
-    int ts = 0;				/* test status flag */
-    LTfldo_t *typ;			/* file type pointer */
-/*
- * Check the test type.
- */
+    char buf[2048];           /* temporary buffer */
+    char *cem;                /* current error message pointer */
+    LTfldo_t *cmdp;           /* command pointer */
+    LTfldo_t *devp;           /* device pointer */
+    int ff = 0;               /* file found status */
+    LTfldo_t *fop;            /* field output pointer */
+    char ibuf[64];            /* inode number buffer */
+    LTfldo_t *inop;           /* inode number pointer */
+    LTdev_t lsofdc;           /* lsof device components */
+    int nf;                   /* number of fields */
+    LTfldo_t *offp;           /* offset pointer */
+    char *opv[4];             /* option vector for ExecLsof() */
+    char *pem = (char *)NULL; /* previous error message pointer */
+    pid_t pid;                /* PID */
+    int pids = 0;             /* PID found status */
+    struct stat sb;           /* stat(2) buffer */
+    LTdev_t stdc;             /* stat(2) device components */
+    LTfldo_t *szp;            /* size pointer */
+    char *tcp;                /* temporary character pointer */
+    int ti;                   /* temporary integer */
+    char *tnm1, *tnm2;        /* test names */
+    int ts = 0;               /* test status flag */
+    LTfldo_t *typ;            /* file type pointer */
+                              /*
+                               * Check the test type.
+                               */
     switch (tt) {
     case TYTST_SZ:
-	tnm1 = "";
-	tnm2 = " size";
-	break;
+        tnm1 = "";
+        tnm2 = " size";
+        break;
     case TYTST_0to:
-	tnm1 = " 0t";
-	tnm2 = " offset";
-	break;
+        tnm1 = " 0t";
+        tnm2 = " offset";
+        break;
     case TYTST_0xo:
-	tnm1 = " 0x";
-	tnm2 = " offset";
-	break;
+        tnm1 = " 0x";
+        tnm2 = " offset";
+        break;
     default:
-	(void) snprintf(buf, sizeof(buf) - 1,
-	    "ERROR!!!  illegal test type: %d", tt);
-	buf[sizeof(buf) - 1] = '\0';
-	(void) PrtMsgX(buf, Pn, cleanup, 1);
+        (void)snprintf(buf, sizeof(buf) - 1, "ERROR!!!  illegal test type: %d",
+                       tt);
+        buf[sizeof(buf) - 1] = '\0';
+        (void)PrtMsgX(buf, Pn, cleanup, 1);
     }
-/*
- * Get test file's information.
- */
+    /*
+     * Get test file's information.
+     */
     if (stat(Path, &sb)) {
-	(void) snprintf(buf, sizeof(buf) - 1,
-	    "ERROR!!!  can't stat(2) %s: %s", Path, strerror(errno));
-	buf[sizeof(buf) - 1] = '\0';
-	PrtMsgX(buf, Pn, cleanup, 1);
+        (void)snprintf(buf, sizeof(buf) - 1, "ERROR!!!  can't stat(2) %s: %s",
+                       Path, strerror(errno));
+        buf[sizeof(buf) - 1] = '\0';
+        PrtMsgX(buf, Pn, cleanup, 1);
     }
-/*
- * Extract components from test file's stat buffer.
- */
+    /*
+     * Extract components from test file's stat buffer.
+     */
     if ((cem = ConvStatDev(&sb.st_dev, &stdc)))
-	PrtMsgX(buf, Pn, cleanup, 1);
-    (void) snprintf(ibuf, sizeof(ibuf) - 1, "%" PRIu64, (uint64_t)sb.st_ino);
+        PrtMsgX(buf, Pn, cleanup, 1);
+    (void)snprintf(ibuf, sizeof(ibuf) - 1, "%" PRIu64, (uint64_t)sb.st_ino);
     ibuf[sizeof(ibuf) - 1] = '\0';
-/*
- * Complete the option vector and start lsof execution.
- */
+    /*
+     * Complete the option vector and start lsof execution.
+     */
     ti = 0;
     if (opt && *opt)
-	opv[ti++] = opt;
+        opv[ti++] = opt;
 
-#if	defined(USE_LSOF_C_OPT)
+#if defined(USE_LSOF_C_OPT)
     opv[ti++] = "-C";
-#else	/* !defined(USE_LSOF_C_OPT) */
+#else  /* !defined(USE_LSOF_C_OPT) */
     opv[ti++] = "--";
-#endif	/* defined(USE_LSOF_C_OPT) */
+#endif /* defined(USE_LSOF_C_OPT) */
 
     opv[ti++] = Path;
     opv[ti] = (char *)NULL;
     if ((cem = ExecLsof(opv)))
-	return(cem);
-/*
- * Read lsof output.
- */
+        return (cem);
+    /*
+     * Read lsof output.
+     */
     while (!ff && !cem && (fop = RdFrLsof(&nf, &cem))) {
-	if (cem) {
-	    if (pem)
-		(void) PrtMsg(pem, Pn);
-	    return(cem);
-	}
-	switch (fop->ft) {
-	case LSOF_FID_PID:
-
-	/*
-	 * This is a process information line.
-	 */
-	    pid = (pid_t)atoi(fop->v);
-	    pids = 1;
-	    cmdp = (LTfldo_t *)NULL;
-	    for (fop++, ti = 1; ti < nf; fop++, ti++) {
-		switch (fop->ft) {
-		case LSOF_FID_CMD:
-		    cmdp = fop;
-		    break;
-		}
-	    }
-	    if (!cmdp || (pid != MyPid))
-		pids = 0;
-	    break;
-	case LSOF_FID_FD:
-
-	/*
-	 * This is a file descriptor line.  Make sure its number matches the
-	 * test file's descriptor number.
-	 */
-	    if (!pids)
-		break;
-	    for (ti = 0, tcp = fop->v; *tcp; tcp++) {
-
-	    /*
-	     * Convert file descriptor to a number.
-	     */
-		if (*tcp == ' ')
-		    continue;
-		if (((int)*tcp < (int)'0') || ((int)*tcp > (int)'9')) {
-		    ti = -1;
-		    break;
-		}
-		ti = (ti * 10) + (int)*tcp - (int)'0';
-	    }
-	    if (Fd != ti)
-		break;
-	/*
-	 * Scan for device, inode, offset, size and type fields.
-	 */
-	    devp = inop = offp = szp = typ = (LTfldo_t *)NULL;
-	    for (fop++, ti = 1; ti < nf; fop++, ti++) {
-		switch (fop->ft) {
-		case LSOF_FID_DEVN:
-		    devp = fop;
-		    break;
-		case LSOF_FID_INODE:
-		    inop = fop;
-		    break;
-		case LSOF_FID_OFFSET:
-		    offp = fop;
-		    break;
-		case LSOF_FID_SIZE:
-		    szp = fop;
-		    break;
-		case LSOF_FID_TYPE:
-		    typ = fop;
-		    break;
-		}
-	    }
-	/*
-	 * Check the results of the file descriptor field scan.
-	 */
-	    if (!devp || !inop || !typ)
-		break;
-	    if (strcasecmp(typ->v, "reg") && strcasecmp(typ->v, "vreg"))
-		break;
-	    if ((cem = ConvLsofDev(devp->v, &lsofdc))) {
-		if (pem)
-		    (void) PrtMsg(pem, Pn);
-		pem = cem;
-		break;
-	    }
-	    if ((stdc.maj != lsofdc.maj)
-	    ||  (stdc.min != lsofdc.min)
-	    ||  (stdc.unit != lsofdc.unit)
-	    ||  strcmp(inop->v, ibuf)
-	    ) {
-		break;
-	    }
-	/*
-	 * The specified file has been located.  Do the specified test.
-	 */
-	    ff = 1;
-	    fop = (tt == TYTST_SZ) ? szp : offp;
-	    if (!fop) {
-		(void) snprintf(buf, sizeof(buf) - 1,
-		    "ERROR!!! %s%s test, but no lsof%s", tnm1, tnm2, tnm2);
-		ts = 1;
-	    } else if (strcmp(fop->v, xval)) {
-		(void) snprintf(buf, sizeof(buf) - 1,
-		    "ERROR!!! %s%s mismatch: expected %s, got %s",
-		    tnm1, tnm2, xval, fop->v);
-		ts = 1;
-	    }
-	    if (ts) {
-		buf[sizeof(buf) - 1] = '\0';
-		cem = MkStrCpy(buf, &ti);
-		if (pem)
-		    (void) PrtMsg(pem, Pn);
-		pem = cem;
-	    }
-	    break;
-	}
+        if (cem) {
+            if (pem)
+                (void)PrtMsg(pem, Pn);
+            return (cem);
+        }
+        switch (fop->ft) {
+        case LSOF_FID_PID:
+
+            /*
+             * This is a process information line.
+             */
+            pid = (pid_t)atoi(fop->v);
+            pids = 1;
+            cmdp = (LTfldo_t *)NULL;
+            for (fop++, ti = 1; ti < nf; fop++, ti++) {
+                switch (fop->ft) {
+                case LSOF_FID_CMD:
+                    cmdp = fop;
+                    break;
+                }
+            }
+            if (!cmdp || (pid != MyPid))
+                pids = 0;
+            break;
+        case LSOF_FID_FD:
+
+            /*
+             * This is a file descriptor line.  Make sure its number matches the
+             * test file's descriptor number.
+             */
+            if (!pids)
+                break;
+            for (ti = 0, tcp = fop->v; *tcp; tcp++) {
+
+                /*
+                 * Convert file descriptor to a number.
+                 */
+                if (*tcp == ' ')
+                    continue;
+                if (((int)*tcp < (int)'0') || ((int)*tcp > (int)'9')) {
+                    ti = -1;
+                    break;
+                }
+                ti = (ti * 10) + (int)*tcp - (int)'0';
+            }
+            if (Fd != ti)
+                break;
+            /*
+             * Scan for device, inode, offset, size and type fields.
+             */
+            devp = inop = offp = szp = typ = (LTfldo_t *)NULL;
+            for (fop++, ti = 1; ti < nf; fop++, ti++) {
+                switch (fop->ft) {
+                case LSOF_FID_DEVN:
+                    devp = fop;
+                    break;
+                case LSOF_FID_INODE:
+                    inop = fop;
+                    break;
+                case LSOF_FID_OFFSET:
+                    offp = fop;
+                    break;
+                case LSOF_FID_SIZE:
+                    szp = fop;
+                    break;
+                case LSOF_FID_TYPE:
+                    typ = fop;
+                    break;
+                }
+            }
+            /*
+             * Check the results of the file descriptor field scan.
+             */
+            if (!devp || !inop || !typ)
+                break;
+            if (strcasecmp(typ->v, "reg") && strcasecmp(typ->v, "vreg"))
+                break;
+            if ((cem = ConvLsofDev(devp->v, &lsofdc))) {
+                if (pem)
+                    (void)PrtMsg(pem, Pn);
+                pem = cem;
+                break;
+            }
+            if ((stdc.maj != lsofdc.maj) || (stdc.min != lsofdc.min) ||
+                (stdc.unit != lsofdc.unit) || strcmp(inop->v, ibuf)) {
+                break;
+            }
+            /*
+             * The specified file has been located.  Do the specified test.
+             */
+            ff = 1;
+            fop = (tt == TYTST_SZ) ? szp : offp;
+            if (!fop) {
+                (void)snprintf(buf, sizeof(buf) - 1,
+                               "ERROR!!! %s%s test, but no lsof%s", tnm1, tnm2,
+                               tnm2);
+                ts = 1;
+            } else if (strcmp(fop->v, xval)) {
+                (void)snprintf(buf, sizeof(buf) - 1,
+                               "ERROR!!! %s%s mismatch: expected %s, got %s",
+                               tnm1, tnm2, xval, fop->v);
+                ts = 1;
+            }
+            if (ts) {
+                buf[sizeof(buf) - 1] = '\0';
+                cem = MkStrCpy(buf, &ti);
+                if (pem)
+                    (void)PrtMsg(pem, Pn);
+                pem = cem;
+            }
+            break;
+        }
     }
-    (void) StopLsof();
+    (void)StopLsof();
     if (!ff) {
-	(void) snprintf(buf, sizeof(buf) - 1,
-	    "ERROR!!!  test file %s not found by lsof", Path);
-	buf[sizeof(buf) - 1] = '\0';
-	cem = MkStrCpy(buf, &ti);
-	if (pem)
-	    (void) PrtMsg(pem, Pn);
-	return(cem);
+        (void)snprintf(buf, sizeof(buf) - 1,
+                       "ERROR!!!  test file %s not found by lsof", Path);
+        buf[sizeof(buf) - 1] = '\0';
+        cem = MkStrCpy(buf, &ti);
+        if (pem)
+            (void)PrtMsg(pem, Pn);
+        return (cem);
     }
-    return(pem);
+    return (pem);
 }
diff --git a/tests/LTunix.c b/tests/LTunix.c
index 2c95f4d..46c544b 100644
--- a/tests/LTunix.c
+++ b/tests/LTunix.c
@@ -5,7 +5,6 @@
  * Purdue University
  */
 
-
 /*
  * Copyright 2002 Purdue Research Foundation, West Lafayette, Indiana
  * 47907.  All rights reserved.
@@ -32,333 +31,315 @@
  * 4. This notice may not be removed or altered.
  */
 
-#ifndef lint
-static char copyright[] =
-"@(#) Copyright 2002 Purdue Research Foundation.\nAll rights reserved.\n";
-#endif
-
 #include "LsofTest.h"
 #include "lsof_fields.h"
 
 #include <sys/socket.h>
 #include <sys/un.h>
 
-
 /*
  * Local definitions
  */
 
-#if	!defined(MAXPATHLEN)
-#define	MAXPATHLEN	1024		/* maximum path length */
-#endif	/* !defined(MAXPATHLEN) */
-
+#if !defined(MAXPATHLEN)
+#    define MAXPATHLEN 1024 /* maximum path length */
+#endif                      /* !defined(MAXPATHLEN) */
 
 /*
  * Globals
  */
 
-pid_t MyPid = (pid_t)0;		/* PID of this process */
-char *Pn = (char *)NULL;	/* program name */
-int SpFd[2] = {-1,-1};		/* socket pair FDs */
+pid_t MyPid = (pid_t)0;  /* PID of this process */
+char *Pn = (char *)NULL; /* program name */
+int SpFd[2] = {-1, -1};  /* socket pair FDs */
 char *Path[2] = {(char *)NULL, (char *)NULL};
-				/* socket pair paths */
-
+/* socket pair paths */
 
 /*
  * Local function prototypes
  */
 
-_PROTOTYPE(static void cleanup,(void));
-_PROTOTYPE(static char *FindUsocks,(void));
-
+static void cleanup(void);
+static char *FindUsocks(void);
 
 /*
  * Main program
  */
 
-int
-main(argc, argv)
-    int argc;				/* argument count */
-    char *argv[];			/* arguments */
+int main(int argc,     /* argument count */
+         char *argv[]) /* arguments */
 {
-    char buf[2048];			/* temporary buffer */
-    char cwd[MAXPATHLEN + 1];		/* CWD buffer */
-    char *em;				/* error message pointer */
-    int ti, tj;				/* temporary indexes */
-    struct sockaddr_un ua;		/* UNIX socket address */
-    int xv = 0;				/* exit value */
-/*
- * Get program name and PID, issue start message, and build space prefix.
- */
+    char buf[2048];           /* temporary buffer */
+    char cwd[MAXPATHLEN + 1]; /* CWD buffer */
+    char *em;                 /* error message pointer */
+    int ti, tj;               /* temporary indexes */
+    struct sockaddr_un ua;    /* UNIX socket address */
+    int xv = 0;               /* exit value */
+                              /*
+                               * Get program name and PID, issue start message, and build space prefix.
+                               */
     if ((Pn = strrchr(argv[0], '/')))
-	Pn++;
+        Pn++;
     else
-	Pn = argv[0];
+        Pn = argv[0];
     MyPid = getpid();
-    (void) printf("%s ... ", Pn);
-    (void) fflush(stdout);
+    (void)printf("%s ... ", Pn);
+    (void)fflush(stdout);
     PrtMsg((char *)NULL, Pn);
-/*
- * Process arguments.
- */
+    /*
+     * Process arguments.
+     */
     if (ScanArg(argc, argv, "h", Pn))
-	xv = 1;
+        xv = 1;
     if (xv || LTopt_h) {
-	(void) PrtMsg("usage: [-h]", Pn);
-	PrtMsgX("       -h       print help (this panel)", Pn, cleanup, xv);
+        (void)PrtMsg("usage: [-h]", Pn);
+        PrtMsgX("       -h       print help (this panel)", Pn, cleanup, xv);
     }
-/*
- * See if lsof can be executed and can access kernel memory.
- */
+    /*
+     * See if lsof can be executed and can access kernel memory.
+     */
     if ((em = IsLsofExec()))
-	(void) PrtMsgX(em, Pn, cleanup, 1);
+        (void)PrtMsgX(em, Pn, cleanup, 1);
     if ((em = CanRdKmem()))
-	(void) PrtMsgX(em, Pn, cleanup, 1);
-/*
- * Construct the socket paths.
- */
+        (void)PrtMsgX(em, Pn, cleanup, 1);
+        /*
+         * Construct the socket paths.
+         */
 
-#if	defined(USE_GETCWD)
+#if defined(USE_GETCWD)
     if (!getcwd(cwd, sizeof(cwd)))
-#else	/* ! defined(USE_GETCWD) */
+#else  /* ! defined(USE_GETCWD) */
     if (!getwd(cwd))
-#endif	/* defined(USE_GETCWD) */
+#endif /* defined(USE_GETCWD) */
 
     {
-	em = "ERROR!!!  can't get CWD";
-	goto print_errno;
+        em = "ERROR!!!  can't get CWD";
+        goto print_errno;
     }
     cwd[sizeof(cwd) - 1] = '\0';
-    if ((strlen(cwd) + strlen("/config.LT#U9223372036854775807") + 1)
-    > sizeof(ua.sun_path))
-    {
-	strncpy(cwd, "/tmp", sizeof(cwd) - 1);
+    if ((strlen(cwd) + strlen("/config.LT#U9223372036854775807") + 1) >
+        sizeof(ua.sun_path)) {
+        strncpy(cwd, "/tmp", sizeof(cwd) - 1);
     }
     for (ti = 0; ti < 2; ti++) {
-	(void) snprintf(buf, sizeof(buf) - 1, "%s/config.LT%dU%ld", cwd, ti,
-	    (long)MyPid);
-	buf[sizeof(buf) - 1] = '\0';
-	Path[ti] = MkStrCpy(buf, &tj);
-	(void) unlink(Path[ti]);
+        (void)snprintf(buf, sizeof(buf) - 1, "%s/config.LT%dU%ld", cwd, ti,
+                       (long)MyPid);
+        buf[sizeof(buf) - 1] = '\0';
+        Path[ti] = MkStrCpy(buf, &tj);
+        (void)unlink(Path[ti]);
     }
-/*
- * Get two UNIX domain socket FDs.
- */
+    /*
+     * Get two UNIX domain socket FDs.
+     */
     for (ti = 0; ti < 2; ti++) {
-	if ((SpFd[ti] = socket(AF_UNIX, SOCK_STREAM, PF_UNSPEC)) < 0) {
-	    em = "socket";
+        if ((SpFd[ti] = socket(AF_UNIX, SOCK_STREAM, PF_UNSPEC)) < 0) {
+            em = "socket";
 
-print_errno_by_ti:
+        print_errno_by_ti:
 
-	    (void) snprintf(buf, sizeof(buf) - 1, "ERROR!!!  %s(%s) failure",
-		em, Path[ti]);
-	    buf[sizeof(buf) - 1] = '\0';
-	    em = buf;
+            (void)snprintf(buf, sizeof(buf) - 1, "ERROR!!!  %s(%s) failure", em,
+                           Path[ti]);
+            buf[sizeof(buf) - 1] = '\0';
+            em = buf;
 
-print_errno:
+        print_errno:
 
-	    PrtMsg(em, Pn);
-	    (void) snprintf(buf, sizeof(buf) - 1, "    Errno %d: %s", errno,
-		strerror(errno));
-	    buf[sizeof(buf) - 1] = '\0';
-	    PrtMsgX(buf, Pn, cleanup, 1);
-	}
+            PrtMsg(em, Pn);
+            (void)snprintf(buf, sizeof(buf) - 1, "    Errno %d: %s", errno,
+                           strerror(errno));
+            buf[sizeof(buf) - 1] = '\0';
+            PrtMsgX(buf, Pn, cleanup, 1);
+        }
     }
-/*
- * Bind file system names to the sockets.
- */
+    /*
+     * Bind file system names to the sockets.
+     */
     for (ti = 0; ti < 2; ti++) {
-	(void) memset((void *)&ua, 0, sizeof(ua));
-	ua.sun_family = AF_UNIX;
-	(void) strncpy(ua.sun_path, Path[ti], sizeof(ua.sun_path));
-	ua.sun_path[sizeof(ua.sun_path) - 1] = '\0';
-	if (bind(SpFd[ti], (struct sockaddr *)&ua, sizeof(ua)) < 0) {
-	    em = "bind";
-	    goto print_errno_by_ti;
-	}
+        (void)memset((void *)&ua, 0, sizeof(ua));
+        ua.sun_family = AF_UNIX;
+        (void)strncpy(ua.sun_path, Path[ti], sizeof(ua.sun_path));
+        ua.sun_path[sizeof(ua.sun_path) - 1] = '\0';
+        if (bind(SpFd[ti], (struct sockaddr *)&ua, sizeof(ua)) < 0) {
+            em = "bind";
+            goto print_errno_by_ti;
+        }
     }
-/*
- * Look for the open UNIX domain socket files with lsof.
- */
+    /*
+     * Look for the open UNIX domain socket files with lsof.
+     */
     if ((em = FindUsocks()))
-	(void) PrtMsgX(em, Pn, cleanup, 1);
-/*
- * Exit successfully.
- */
-    (void) PrtMsgX("OK", Pn, cleanup, 0);
-    return(0);
+        (void)PrtMsgX(em, Pn, cleanup, 1);
+    /*
+     * Exit successfully.
+     */
+    (void)PrtMsgX("OK", Pn, cleanup, 0);
+    return (0);
 }
 
-
 /*
  * cleanup() -- release resources
  */
 
-static void
-cleanup()
-{
+static void cleanup() {
     int ti;
 
     for (ti = 0; ti < 2; ti++) {
-	if (SpFd[ti] >= 0) {
-	    (void) close(SpFd[ti]);
-	    SpFd[ti] = -1;
-	}
-	if (Path[ti]) {
-	    (void) unlink(Path[ti]);
-	    (void) free((void *)Path[ti]);
-	    Path[ti] = (char *)NULL;
-	}
+        if (SpFd[ti] >= 0) {
+            (void)close(SpFd[ti]);
+            SpFd[ti] = -1;
+        }
+        if (Path[ti]) {
+            (void)unlink(Path[ti]);
+            (void)free((void *)Path[ti]);
+            Path[ti] = (char *)NULL;
+        }
     }
 }
 
-
 /*
  * FindUsocks() -- find UNIX sockets with lsof
  */
 
-static char *
-FindUsocks()
-{
-    char buf[2048];			/* temporary buffer */
-    char *cem;				/* current error message pointer */
-    LTfldo_t *cmdp;			/* command pointer */
-    int ff[2];				/* file-found flags */
-    LTfldo_t *fop;			/* field output pointer */
-    int nf;				/* number of fields */
-    int nl;				/* name length */
-    LTfldo_t *nmp;			/* name pointer */
-    char *opv[5];			/* option vector for ExecLsof() */
-    char *pem = (char *)NULL;		/* previous error message pointer */
-    pid_t pid;				/* PID */
-    int pids = 0;			/* PID found status */
-    char *tcp;				/* temporary character pointer */
-    int ti, tj;				/* temporary integers */
-    LTfldo_t *typ;			/* file type pointer */
-/*
- * Build the option vector and start lsof execution.
- */
+static char *FindUsocks() {
+    char buf[2048];           /* temporary buffer */
+    char *cem;                /* current error message pointer */
+    LTfldo_t *cmdp;           /* command pointer */
+    int ff[2];                /* file-found flags */
+    LTfldo_t *fop;            /* field output pointer */
+    int nf;                   /* number of fields */
+    int nl;                   /* name length */
+    LTfldo_t *nmp;            /* name pointer */
+    char *opv[5];             /* option vector for ExecLsof() */
+    char *pem = (char *)NULL; /* previous error message pointer */
+    pid_t pid;                /* PID */
+    int pids = 0;             /* PID found status */
+    char *tcp;                /* temporary character pointer */
+    int ti, tj;               /* temporary integers */
+    LTfldo_t *typ;            /* file type pointer */
+                              /*
+                               * Build the option vector and start lsof execution.
+                               */
     ff[0] = ff[1] = ti = 0;
     opv[ti++] = "-aU";
     opv[ti++] = "-p";
-    (void) snprintf(buf, sizeof(buf) - 1, "%ld", (long)MyPid);
+    (void)snprintf(buf, sizeof(buf) - 1, "%ld", (long)MyPid);
     buf[sizeof(buf) - 1] = '\0';
     opv[ti++] = MkStrCpy(buf, &tj);
 
-#if	defined(USE_LSOF_C_OPT)
+#if defined(USE_LSOF_C_OPT)
     opv[ti++] = "-C";
-#endif	/* defined(USE_LSOF_C_OPT) */
+#endif /* defined(USE_LSOF_C_OPT) */
 
     opv[ti] = (char *)NULL;
     if ((cem = ExecLsof(opv)))
-	return(cem);
-/*
- * Read lsof output.
- */
+        return (cem);
+    /*
+     * Read lsof output.
+     */
     while (((ff[0] + ff[1]) < 2) && (fop = RdFrLsof(&nf, &cem))) {
-	if (cem) {
-	    if (pem)
-		(void) PrtMsg(pem, Pn);
-	    return(cem);
-	}
-	switch (fop->ft) {
-	case LSOF_FID_PID:
-
-	/*
-	 * This is a process information line.
-	 */
-	    pid = (pid_t)atoi(fop->v);
-	    pids = 1;
-	    cmdp = (LTfldo_t *)NULL;
-	    for (fop++, ti = 1; ti < nf; fop++, ti++) {
-		switch (fop->ft) {
-		case LSOF_FID_CMD:
-		    cmdp = fop;
-		    break;
-		}
-	    }
-	    if (!cmdp || (pid != MyPid))
-		pids = 0;
-	    break;
-	case LSOF_FID_FD:
-
-	/*
-	 * This is a file descriptor line.  Make sure its number matches a
-	 * test file descriptor number.
-	 */
-	    if (!pids)
-		break;
-	    for (ti = 0, tcp = fop->v; *tcp; tcp++) {
-
-	    /*
-	     * Convert file descriptor to a number.
-	     */
-		if (*tcp == ' ')
-		    continue;
-		if (((int)*tcp < (int)'0') || ((int)*tcp > (int)'9')) {
-		    ti = -1;
-		    break;
-		}
-		ti = (ti * 10) + (int)*tcp - (int)'0';
-	    }
-	    for (tj = 0; tj < 2; tj++) {
-		if (ff[tj])
-		    continue;
-		if (SpFd[tj] == ti)
-		    break;
-	    }
-	    if (tj >= 2)
-		break;
-	/*
-	 * Scan for name and type.
-	 */
-	    nmp = typ  = (LTfldo_t *)NULL;
-	    for (fop++, ti = 1; ti < nf; fop++, ti++) {
-		switch (fop->ft) {
-		case LSOF_FID_NAME:
-		    nmp = fop;
-		    break;
-		case LSOF_FID_TYPE:
-		    typ = fop;
-		    break;
-		}
-	    }
-	/*
-	 * Check the type of the file.
-	 */
-	    if (!typ || strcasecmp(typ->v, "unix"))
-		break;
-	/*
-	 * Look for the name.
-	 */
-	    if (!nmp)
-		break;
-	    nl = strlen(Path[tj]);
-	    for (tcp = nmp->v; tcp; tcp = strchr(tcp + 1, '/')) {
-		if (!strncmp(tcp, Path[tj], nl)) {
-
-		/*
-		 * Mark a file as found.
-		 */
-		    ff[tj] = 1;
-		    break;
-		}
-	    }
-	}
+        if (cem) {
+            if (pem)
+                (void)PrtMsg(pem, Pn);
+            return (cem);
+        }
+        switch (fop->ft) {
+        case LSOF_FID_PID:
+
+            /*
+             * This is a process information line.
+             */
+            pid = (pid_t)atoi(fop->v);
+            pids = 1;
+            cmdp = (LTfldo_t *)NULL;
+            for (fop++, ti = 1; ti < nf; fop++, ti++) {
+                switch (fop->ft) {
+                case LSOF_FID_CMD:
+                    cmdp = fop;
+                    break;
+                }
+            }
+            if (!cmdp || (pid != MyPid))
+                pids = 0;
+            break;
+        case LSOF_FID_FD:
+
+            /*
+             * This is a file descriptor line.  Make sure its number matches a
+             * test file descriptor number.
+             */
+            if (!pids)
+                break;
+            for (ti = 0, tcp = fop->v; *tcp; tcp++) {
+
+                /*
+                 * Convert file descriptor to a number.
+                 */
+                if (*tcp == ' ')
+                    continue;
+                if (((int)*tcp < (int)'0') || ((int)*tcp > (int)'9')) {
+                    ti = -1;
+                    break;
+                }
+                ti = (ti * 10) + (int)*tcp - (int)'0';
+            }
+            for (tj = 0; tj < 2; tj++) {
+                if (ff[tj])
+                    continue;
+                if (SpFd[tj] == ti)
+                    break;
+            }
+            if (tj >= 2)
+                break;
+            /*
+             * Scan for name and type.
+             */
+            nmp = typ = (LTfldo_t *)NULL;
+            for (fop++, ti = 1; ti < nf; fop++, ti++) {
+                switch (fop->ft) {
+                case LSOF_FID_NAME:
+                    nmp = fop;
+                    break;
+                case LSOF_FID_TYPE:
+                    typ = fop;
+                    break;
+                }
+            }
+            /*
+             * Check the type of the file.
+             */
+            if (!typ || strcasecmp(typ->v, "unix"))
+                break;
+            /*
+             * Look for the name.
+             */
+            if (!nmp)
+                break;
+            nl = strlen(Path[tj]);
+            for (tcp = nmp->v; tcp; tcp = strchr(tcp + 1, '/')) {
+                if (!strncmp(tcp, Path[tj], nl)) {
+
+                    /*
+                     * Mark a file as found.
+                     */
+                    ff[tj] = 1;
+                    break;
+                }
+            }
+        }
     }
-/*
- * Clean up and return.
- */
-    (void) StopLsof();
+    /*
+     * Clean up and return.
+     */
+    (void)StopLsof();
     for (ti = 0; ti < 2; ti++) {
-	if (ff[tj])
-	    continue;
-	(void) snprintf(buf, sizeof(buf) - 1, "ERROR!!!  not found: %s",
-	    Path[ti]);
-	buf[sizeof(buf) - 1] = '\0';
-	if (pem)
-	    (void) PrtMsg(pem, Pn);
-	pem = MkStrCpy(buf, &tj);
+        if (ff[tj])
+            continue;
+        (void)snprintf(buf, sizeof(buf) - 1, "ERROR!!!  not found: %s",
+                       Path[ti]);
+        buf[sizeof(buf) - 1] = '\0';
+        if (pem)
+            (void)PrtMsg(pem, Pn);
+        pem = MkStrCpy(buf, &tj);
     }
-    return(pem);
+    return (pem);
 }
diff --git a/tests/LsofTest.h b/tests/LsofTest.h
index def29f2..c4eff23 100644
--- a/tests/LsofTest.h
+++ b/tests/LsofTest.h
@@ -2,7 +2,6 @@
  * LsofTest.h -- header file for lsof tests
  */
 
-
 /*
  * Copyright 2002 Purdue Research Foundation, West Lafayette, Indiana
  * 47907.  All rights reserved.
@@ -29,29 +28,12 @@
  * 4. This notice may not be removed or altered.
  */
 
-
 /*
  * $Id: LsofTest.h,v 1.13 2018/02/14 14:21:44 abe Exp $
  */
 
-
-#if	!defined(LSOF_TEST_H)
-#define	LSOF_TEST_H	1
-
-
-/*
- * 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__) */
-
+#if !defined(LSOF_TEST_H)
+#    define LSOF_TEST_H 1
 
 /*
  * The following define keeps gcc>=2.7 from complaining about the failure
@@ -60,268 +42,254 @@
  * Paul Eggert <eggert@twinsun.com> 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(__GNUC__) &&                                                   \
+        !(__GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7))
+#        define exiting __attribute__((__noreturn__))
+#    else /* !gcc || gcc<2.7 */
+#        define exiting
+#    endif /* gcc && gcc>=2.7 */
 
 /*
  * Necessary header files.
  */
 
-#include <stdio.h>
-#include <ctype.h>
-#include <errno.h>
-#include <signal.h>
-#include <inttypes.h>
-
-#include <sys/types.h>
+#    include <stdio.h>
+#    include <ctype.h>
+#    include <errno.h>
+#    include <signal.h>
+#    include <inttypes.h>
 
-#if	defined(LT_DIAL_linux) && LT_VERS>=414014
-#undef	major
-#include <sys/sysmacros.h>
-#endif	/* defined(LT_DIAL_linux) && LT_VERS>=414014 */
+#    include <sys/types.h>
 
-#include <sys/param.h>
-#include <sys/stat.h>
+#    if defined(LT_DIAL_linux) && LT_VERS >= 414014
+#        undef major
+#        include <sys/sysmacros.h>
+#    endif /* defined(LT_DIAL_linux) && LT_VERS>=414014 */
 
+#    include <sys/param.h>
+#    include <sys/stat.h>
 
 /*
  * Definitions that may be revoked by a particular dialect.
  */
 
-#define	USE_GETCWD			/* use the POSIX getcwd() function in
-					 * place of getwd() */
-#define	USE_LSOF_C_OPT			/* use lsof's -C option */
-#undef	USE_LSOF_X_OPT			/* don't use lsof's -X option */
+#    define USE_GETCWD     /* use the POSIX getcwd() function in               \
+                            * place of getwd() */
+#    define USE_LSOF_C_OPT /* use lsof's -C option */
+#    undef USE_LSOF_X_OPT  /* don't use lsof's -X option */
 
-
-# if	defined(LT_DIAL_aix)
+#    if defined(LT_DIAL_aix)
 /*
  * AIX-specific items
  */
 
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/access.h>
-#undef	USE_LSOF_C_OPT
-#define	USE_LSOF_X_OPT
-# endif	/* defined(LT_DIAL_aix) */
-
+#        include <fcntl.h>
+#        include <stdlib.h>
+#        include <string.h>
+#        include <unistd.h>
+#        include <sys/access.h>
+#        undef USE_LSOF_C_OPT
+#        define USE_LSOF_X_OPT
+#    endif /* defined(LT_DIAL_aix) */
 
-# if	defined(LT_DIAL_bsdi)
+#    if defined(LT_DIAL_bsdi)
 /*
- * OpenBSD-specific items
+ * BSDI-specific items
  */
 
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/wait.h>
-# endif	/* defined(LT_DIAL_bsdi) */
-
+#        include <fcntl.h>
+#        include <stdlib.h>
+#        include <string.h>
+#        include <unistd.h>
+#        include <sys/wait.h>
+#    endif /* defined(LT_DIAL_bsdi) */
 
-# if	defined(LT_DIAL_darwin)
+#    if defined(LT_DIAL_darwin)
 /*
  * Darwin-specific items
  */
 
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/wait.h>
-#undef	USE_LSOF_C_OPT
-# endif	/* defined(LT_DIAL_darwin) */
+#        include <fcntl.h>
+#        include <stdlib.h>
+#        include <string.h>
+#        include <unistd.h>
+#        include <sys/wait.h>
+#        undef USE_LSOF_C_OPT
+#    endif /* defined(LT_DIAL_darwin) */
 
-
-# if	defined(LT_DIAL_du)
+#    if defined(LT_DIAL_du)
 /*
  * DEC_OSF/1|Digital_UNIX|Tru64_UNIX-specific items
  */
 
-#include <fcntl.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/wait.h>
-
-# if	LT_VERS<50000
-#define	snprintf	snpf		/* use lsof's snpf() */
-# endif	/* LT_VERS<50000 */
-# endif	/* defined(LT_DIAL_du) */
+#        include <fcntl.h>
+#        include <string.h>
+#        include <unistd.h>
+#        include <sys/wait.h>
 
+#        if LT_VERS < 50000
+#            define snprintf snpf /* use lsof's snpf() */
+#        endif                    /* LT_VERS<50000 */
+#    endif                        /* defined(LT_DIAL_du) */
 
-# if	defined(LT_DIAL_freebsd)
+#    if defined(LT_DIAL_freebsd)
 /*
  * FreeBSD-specific items
  */
 
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/wait.h>
-# endif	/* defined(LT_DIAL_freebsd) */
+#        include <fcntl.h>
+#        include <stdlib.h>
+#        include <string.h>
+#        include <unistd.h>
+#        include <sys/wait.h>
+#        undef USE_LSOF_C_OPT
+#    endif /* defined(LT_DIAL_freebsd) */
 
-
-# if	defined(LT_DIAL_linux)
+#    if defined(LT_DIAL_linux)
 /*
  * Linux-specific items
  */
 
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/wait.h>
-#undef	USE_LSOF_C_OPT
-# endif	/* defined(LT_DIAL_linux) */
-
+#        include <fcntl.h>
+#        include <stdlib.h>
+#        include <string.h>
+#        include <unistd.h>
+#        include <sys/wait.h>
+#        undef USE_LSOF_C_OPT
+#    endif /* defined(LT_DIAL_linux) */
 
-# if	defined(LT_DIAL_hpux)
+#    if defined(LT_DIAL_hpux)
 /*
  * HP-UX-specific items
  */
 
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <unistd.h>
-# endif	/* defined(LT_DIAL_hpux) */
+#        include <fcntl.h>
+#        include <stdlib.h>
+#        include <string.h>
+#        include <strings.h>
+#        include <unistd.h>
+#    endif /* defined(LT_DIAL_hpux) */
 
-
-# if	defined(LT_DIAL_netbsd)
+#    if defined(LT_DIAL_netbsd)
 /*
  * NetBSD-specific items
  */
 
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/wait.h>
-# endif	/* defined(LT_DIAL_netbsd) */
-
+#        include <fcntl.h>
+#        include <stdlib.h>
+#        include <string.h>
+#        include <unistd.h>
+#        include <sys/wait.h>
+#    endif /* defined(LT_DIAL_netbsd) */
 
-# if	defined(LT_DIAL_openbsd)
+#    if defined(LT_DIAL_openbsd)
 /*
  * OpenBSD-specific items
  */
 
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/wait.h>
-# endif	/* defined(LT_DIAL_openbsd) */
+#        include <fcntl.h>
+#        include <stdlib.h>
+#        include <string.h>
+#        include <unistd.h>
+#        include <sys/wait.h>
+#        undef USE_LSOF_C_OPT
+#    endif /* defined(LT_DIAL_openbsd) */
 
-
-# if	defined(LT_DIAL_ou)
+#    if defined(LT_DIAL_ou)
 /*
  * OpenUNIX-specific items
  */
 
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-# endif	/* defined(LT_DIAL_ou) */
-
+#        include <fcntl.h>
+#        include <stdlib.h>
+#        include <string.h>
+#        include <unistd.h>
+#    endif /* defined(LT_DIAL_ou) */
 
-# if	defined(LT_DIAL_osr)
+#    if defined(LT_DIAL_osr)
 /*
  * OSR-specific items
  */
 
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-# endif	/* defined(LT_DIAL_osr) */
+#        include <fcntl.h>
+#        include <stdlib.h>
+#        include <string.h>
+#        include <unistd.h>
+#    endif /* defined(LT_DIAL_osr) */
 
-
-# if	defined(LT_DIAL_ns)
+#    if defined(LT_DIAL_ns)
 /*
  * NEXTSTEP-specific items
  */
 
-#include <stdlib.h>
-#include <string.h>
-#include <sys/file.h>
-#include <sys/wait.h>
-
-typedef int		pid_t;
-#define	snprintf	snpf
+#        include <stdlib.h>
+#        include <string.h>
+#        include <sys/file.h>
+#        include <sys/wait.h>
 
-#undef	USE_GETCWD
-# endif	/* defined(LT_DIAL_ns) */
+typedef int pid_t;
+#        define snprintf snpf
 
+#        undef USE_GETCWD
+#    endif /* defined(LT_DIAL_ns) */
 
-# if	defined(LT_DIAL_solaris)
+#    if defined(LT_DIAL_solaris)
 /*
  * Solaris-specific items
  */
 
-#include <fcntl.h>
-#include <stdlib.h>
-#include <strings.h>
-#include <unistd.h>
-#include <sys/wait.h>
+#        include <fcntl.h>
+#        include <stdlib.h>
+#        include <strings.h>
+#        include <unistd.h>
+#        include <sys/wait.h>
 
-# if	defined(LT_VPATH)
-#undef	USE_LSOF_C_OPT
-#endif	/* defined(LT_VPATH) */
-# endif	/* defined(LT_DIAL_solaris) */
+#        if defined(LT_VPATH)
+#            undef USE_LSOF_C_OPT
+#        endif /* defined(LT_VPATH) */
+#    endif     /* defined(LT_DIAL_solaris) */
 
-
-# if	defined(LT_DIAL_uw)
+#    if defined(LT_DIAL_uw)
 /*
  * UnixWare-specific items
  */
 
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-# endif	/* defined(LT_DIAL_uw) */
-
+#        include <fcntl.h>
+#        include <stdlib.h>
+#        include <string.h>
+#        include <unistd.h>
+#    endif /* defined(LT_DIAL_uw) */
 
 /*
  * Local definitions, including ones may have been left undefined by
  * dialect-specific header files
  */
 
-#define	LT_DONT_DO_TEST		"this test does not run on this dialect."
-#define	LT_DEF_LSOF_PATH	"../lsof"
-
-# if	!defined(MAXPATHLEN)
-#define	MAXPATHLEN	1024
-# endif	/* !defined(MAXPATHLEN) */
+#    define LT_DONT_DO_TEST "this test does not run on this dialect."
+#    if !defined(LT_DEF_LSOF_PATH)
+#        define LT_DEF_LSOF_PATH "../lsof"
+#    endif /* !defined(LT_DEF_LSOF_PATH) */
 
+#    if !defined(MAXPATHLEN)
+#        define MAXPATHLEN 1024
+#    endif /* !defined(MAXPATHLEN) */
 
 /*
  * Local structure definitions
  */
 
-typedef struct LTdev {			/* local device parameters */
-    unsigned int maj;			/* major device number */
-    unsigned int min;			/* minor device number */
-    unsigned int unit;			/* unit number (where applicable) */
+typedef struct LTdev { /* local device parameters */
+    unsigned int maj;  /* major device number */
+    unsigned int min;  /* minor device number */
+    unsigned int unit; /* unit number (where applicable) */
 } LTdev_t;
 
-typedef struct LTfldo {			/* lsof field output information */
-    char ft;				/* field identifier (see the LSOF_FID_*
-					 * definitions in ../lsof_fields.h) */
-    char *v;				/* field value character string */
+typedef struct LTfldo { /* lsof field output information */
+    char ft;            /* field identifier (see the LSOF_FID_*
+                         * definitions in ../lsof_fields.h) */
+    char *v;            /* field value character string */
 } LTfldo_t;
-#define	LT_FLDO_ALLOC		16	/* LTfldo_t allocation increment */
-
+#    define LT_FLDO_ALLOC 16 /* LTfldo_t allocation increment */
 
 /*
  * Lsof test library global variable external declarations:
@@ -329,21 +297,19 @@ typedef struct LTfldo {			/* lsof field output information */
  *	these global variables may be found in LTlib.c.
  */
 
-extern int LsofFd;			/* lsof pipe FD */
-extern FILE *LsofFs;			/* stream for lsof pipe FD */
-extern char *LsofPath;			/* path to lsof executable */
-extern pid_t LsofPid;			/* PID of lsof child process */
-extern int LTopt_h;			/* "-h" option's switch value */
-extern char *LTopt_p;			/* "-p path" option's path value */
-extern int MsgStat;			/* message status */
-
+extern int LsofFd;     /* lsof pipe FD */
+extern FILE *LsofFs;   /* stream for lsof pipe FD */
+extern char *LsofPath; /* path to lsof executable */
+extern pid_t LsofPid;  /* PID of lsof child process */
+extern int LTopt_h;    /* "-h" option's switch value */
+extern char *LTopt_p;  /* "-p path" option's path value */
+extern int MsgStat;    /* message status */
 
 /*
  * External declarations
  */
 
-extern int errno;			/* error number */
-
+extern int errno; /* error number */
 
 /*
  * Lsof test library function prototypes:
@@ -351,17 +317,17 @@ extern int errno;			/* error number */
  *	these functions may be found in LTlib.c.
  */
 
-_PROTOTYPE(extern char *CanRdKmem,(void));
-_PROTOTYPE(extern char *ConvStatDev,(dev_t *dev, LTdev_t *ldev));
-_PROTOTYPE(extern char *ConvLsofDev,(char *dev, LTdev_t *ldev));
-_PROTOTYPE(extern char *ExecLsof,(char **opt));
-_PROTOTYPE(extern char *IsLsofExec,(void));
-_PROTOTYPE(extern void LTlibClean,(void));
-_PROTOTYPE(extern char *MkStrCpy,(char *src, int *len));
-_PROTOTYPE(extern LTfldo_t *RdFrLsof,(int *nf, char **em));
-_PROTOTYPE(extern void PrtMsg,(char *mp, char *pn));
-_PROTOTYPE(extern void PrtMsgX,(char *mp, char *pn, void (*f)(), int xv));
-_PROTOTYPE(extern int ScanArg,(int ac, char *av[], char *opt, char *pn));
-_PROTOTYPE(extern void StopLsof,(void));
-
-#endif	/* LSOF_TEST_H */
+extern char *CanRdKmem(void);
+extern char *ConvStatDev(dev_t *dev, LTdev_t *ldev);
+extern char *ConvLsofDev(char *dev, LTdev_t *ldev);
+extern char *ExecLsof(char **opt);
+extern char *IsLsofExec(void);
+extern void LTlibClean(void);
+extern char *MkStrCpy(char *src, int *len);
+extern LTfldo_t *RdFrLsof(int *nf, char **em);
+extern void PrtMsg(char *mp, char *pn);
+extern void PrtMsgX(char *mp, char *pn, void (*f)(), int xv);
+extern int ScanArg(int ac, char *av[], char *opt, char *pn);
+extern void StopLsof(void);
+
+#endif /* LSOF_TEST_H */
diff --git a/tests/Makefile b/tests/Makefile
index 64efe18..0b82654 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -6,7 +6,7 @@
 # $Id: Makefile,v 1.17 2005/05/17 00:40:53 abe Exp abe $
 
 DEBUG=
-CFLAGS=	${DEBUG} -I. -I..
+CFLAGS=	${DEBUG} -I. -I.. -I../include
 
 HDR=	LsofTest.h
 
diff --git a/tests/TestDB b/tests/TestDB
index 93ffa08..e6ec430 100644
--- a/tests/TestDB
+++ b/tests/TestDB
@@ -142,4 +142,13 @@ LT_BIGF LT_CC LT_DIAL_uw LT_KMEM LT_VERS=70101
 LT_BIGF LT_CC LT_DIAL_uw LT_KMEM LT_VERS=70103
 LT_BIGF LT_CC LT_DIAL_uw LT_KMEM LT_VERS=70104
 LT_BIGF LT_CC LT_DEV64 LT_DIAL_freebsd LT_KMEM LT_VERS=13000
+LT_BIGF LT_CC LT_DEV64 LT_DIAL_freebsd LT_VERS=12000
+LT_BIGF LT_CC LT_DEV64 LT_DIAL_freebsd LT_VERS=13000
+LT_BIGF LT_CC LT_DEV64 LT_DIAL_freebsd LT_VERS=14000
 LT_BIGF LT_CC LT_DIAL_linux LT_VERS=50009 _FILE_OFFSET_BITS=64
+LT_BIGF LT_CC LT_DIAL_linux LT_VERS=60005 _FILE_OFFSET_BITS=64
+LT_CC LT_DIAL_darwin LT_VERS=1900
+LT_BIGF LT_CC LT_DIAL_darwin LT_VERS=1900
+LT_BIGF LT_CC LT_DIAL_openbsd LT_VERS=7020
+LT_BIGF LT_CC LT_DIAL_openbsd LT_VERS=7030
+LT_BIGF LT_CC LT_DEV64 LT_DIAL_freebsd LT_VERS=15000
diff --git a/tests/case-01-version.bash b/tests/case-01-version.bash
index ae32e09..b1a18bf 100755
--- a/tests/case-01-version.bash
+++ b/tests/case-01-version.bash
@@ -1,11 +1,11 @@
+#!/usr/bin/env bash
 #
 # check that the version numbers are updated
 #
-lsof=$1
-report=$2
+source tests/common.bash
 
 expected_version=$(sed '/VN/s/.ds VN \([0-9.a-z]*\)/\1/' ./version)
-actual_version=$(./lsof -v 2>&1 | sed -ne 's/^ *revision: *\([0-9.a-z]*\)/\1/p')
+actual_version=$($lsof -v 2>&1 | sed -ne 's/^ *revision: *\([0-9.a-z]*\)/\1/p')
 dist_version=$(sed -ne 's/^\([0-9][0-9.a-z]*\)		.*$/\1/p' 00DIST | tail -1)
 
 if [ "${expected_version}" != "${actual_version}" ]; then
diff --git a/tests/case-14-classic-opt.bash b/tests/case-14-classic-opt.bash
index a151d54..61133e9 100755
--- a/tests/case-14-classic-opt.bash
+++ b/tests/case-14-classic-opt.bash
@@ -23,7 +23,7 @@ base=$(pwd)
 	s=1
     fi
 
-    if [ -n "$CI" ] && [ "$dialect" = "darwin" ]; then
+    if [ -n "$CI" ] && { [ "$dialect" = "darwin" ] || [ "$dialect" = "openbsd" ]; }; then
 	:			# TODO: temporary skip this
     elif ! grep -q "LTlock \.\.\. OK" $f; then
 	echo '"LTlock ... OK" is not found in the output' >> $report
diff --git a/tests/case-20-exit-status.bash b/tests/case-20-exit-status.bash
index ac3dbef..ee6b46e 100755
--- a/tests/case-20-exit-status.bash
+++ b/tests/case-20-exit-status.bash
@@ -1,10 +1,10 @@
-name=$(basename $0 .bash)
-lsof=$1
-report=$2
+#!/usr/bin/env bash
+source tests/common.bash
 
 f=/tmp/lsof-${name}-$$
 
 {
+    # should fail if not exists
     $lsof $f > /dev/null
     s=$?
     case $s in
@@ -18,12 +18,13 @@ f=/tmp/lsof-${name}-$$
 	    ;;
     esac
 
+    # should fail if no one opens the file
     touch $f
     $lsof $f > /dev/null
     s=$?
     case $s in
 	1)
-	    echo "ok: touch $f; $lsof $f => 0"
+	    echo "ok: touch $f; $lsof $f => 1"
 	    rm $f
 	    ;;
 	*)
@@ -34,6 +35,7 @@ f=/tmp/lsof-${name}-$$
 	    ;;
     esac
 
+    # should succeed if some one opens the file
     g=/dev/null
     cat < /dev/zero > $g &
     pid=$!
diff --git a/tests/case-20-fd-only-inclusion.bash b/tests/case-20-fd-only-inclusion.bash
index 40b915c..bae89c4 100755
--- a/tests/case-20-fd-only-inclusion.bash
+++ b/tests/case-20-fd-only-inclusion.bash
@@ -1,6 +1,5 @@
-name=$(basename $0 .bash)
-lsof=$1
-report=$2
+#!/usr/bin/env bash
+source tests/common.bash
 
 echo "inclusion test" >> $report
 while read line; do
diff --git a/tests/case-20-handle-missing-files.bash b/tests/case-20-handle-missing-files.bash
index 6baa5ed..00e0063 100755
--- a/tests/case-20-handle-missing-files.bash
+++ b/tests/case-20-handle-missing-files.bash
@@ -1,7 +1,7 @@
+#!/usr/bin/env bash
 # See https://github.com/lsof-org/lsof/issues/90
-name=$(basename $0 .bash)
-lsof=$1
-report=$2
+source tests/common.bash
+
 msg=$(${lsof} /NO-SUCH-FILE 2>&1)
 
 if [[ "${msg}" == \
diff --git a/tests/case-20-offset-field.bash b/tests/case-20-offset-field.bash
index 21bc332..6924661 100755
--- a/tests/case-20-offset-field.bash
+++ b/tests/case-20-offset-field.bash
@@ -1,6 +1,6 @@
-name=$(basename $0 .bash)
-lsof=$1
-report=$2
+#!/usr/bin/env bash
+source tests/common.bash
+
 base=$(pwd)
 
 t=/tmp/lsof-test-reg-file-$$
diff --git a/tests/case-20-repeat-count.bash b/tests/case-20-repeat-count.bash
index f32ff86..6962bc6 100755
--- a/tests/case-20-repeat-count.bash
+++ b/tests/case-20-repeat-count.bash
@@ -1,14 +1,18 @@
-name=$(basename $0 .bash)
-lsof=$1
-report=$2
+#!/usr/bin/env bash
+source tests/common.bash
+# need gnu grep for -e in solaris
+export PATH=/usr/gnu/bin:$PATH
 base=$(pwd)
 
-
-if [ $(${lsof} -r 1c1 -p $$ | tee -a $report | grep -e '=======' | wc -l) != 1 ]; then
+output=$(${lsof} -r 1c1 -p $$)
+echo "$output" >> $report
+if [ $(echo "$output" | grep -e '=======' | wc -l) != 1 ]; then
     exit 1
 fi
 
-if [ $(${lsof} -r 1c5 -p $$ | tee -a $report | grep -e '=======' | wc -l) != 5 ]; then
+output=$(${lsof} -r 1c5 -p $$)
+echo "$output" >> $report
+if [ $(echo "$output" | grep -e '=======' | wc -l) != 5 ]; then
     exit 1
 fi
 
diff --git a/tests/case-21-exit-Q-status.bash b/tests/case-21-exit-Q-status.bash
index 4cc8264..e6be3a0 100755
--- a/tests/case-21-exit-Q-status.bash
+++ b/tests/case-21-exit-Q-status.bash
@@ -1,8 +1,9 @@
+#!/usr/bin/env bash
 # See https://github.com/lsof-org/lsof/issues/128
-name=$(basename $0 .bash)
-lsof0="$1"
+source tests/common.bash
+
+lsof0="$lsof"
 lsof=
-report=$2
 
 f=/tmp/lsof-${name}-$$
 r=0
diff --git a/tests/case-22-empty-process-name.bash b/tests/case-22-empty-process-name.bash
new file mode 100755
index 0000000..ff1d75e
--- /dev/null
+++ b/tests/case-22-empty-process-name.bash
@@ -0,0 +1,31 @@
+#!/usr/bin/env bash
+# See https://github.com/lsof-org/lsof/issues/246
+source tests/common.bash
+
+{
+    perl -e '$0 = ""; sleep 999' &
+    pid=$!
+    sleep 1
+
+    output=$($lsof -w -ad cwd -F c -p "$pid")
+    echo "lsof output:" >> $report
+    echo "$output" >> $report
+    kill $pid
+    for entry in $output
+    do
+	if [[ $entry =~ ^p[0-9]+$ ]]; then
+	    if [[ $entry != p$pid ]]; then
+	        echo "Incorrect pid, expect p$pid, got $entry" >> $report
+		exit 1
+	    fi
+	elif [[ $entry =~ c* ]]; then
+	    if [[ $entry =~ cperl* ]]; then
+	        echo "The platform does not report changed command name, that's okay" >> $report
+	    elif [[ $entry != c ]]; then
+	        echo "Process name should be empty, expect c, got $entry" >> $report
+		exit 1
+	    fi
+	fi
+    done
+    exit 0
+} > $report 2>&1
diff --git a/tests/common.bash b/tests/common.bash
new file mode 100644
index 0000000..b621787
--- /dev/null
+++ b/tests/common.bash
@@ -0,0 +1,14 @@
+name=$(basename $0 .bash)
+if [ "$#" -ne 0 ]; then
+	# Legacy
+	lsof=$1
+	report=$2
+	tcasedir=$3
+	dialect=$4
+else
+	# Autotools
+	lsof=$PWD/lsof
+	report=/dev/stdout
+	tcasedir=lib/dialects/${LSOF_DIALECT_DIR}/tests
+	dialect=${LSOF_DIALECT}
+fi
\ No newline at end of file
diff --git a/usage.c b/usage.c
deleted file mode 100644
index 282e84f..0000000
--- a/usage.c
+++ /dev/null
@@ -1,977 +0,0 @@
-/*
- * usage.c - usage functions for lsof
- */
-
-
-/*
- * 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 1998 Purdue Research Foundation.\nAll rights reserved.\n";
-#endif
-
-
-#include "lsof.h"
-#include "version.h"
-
-
-/*
- * Local function prototypes
- */
-
-_PROTOTYPE(static char *isnullstr,(char *s));
-_PROTOTYPE(static int print_in_col,(int col, char *cp));
-_PROTOTYPE(static void report_HASDCACHE,(int type, char *ttl, char *det));
-_PROTOTYPE(static void report_HASKERNIDCK,(char *pfx, char *verb));
-_PROTOTYPE(static void report_SECURITY,(char *pfx, char *punct));
-_PROTOTYPE(static void report_WARNDEVACCESS,(char *pfx, char *verb,
-					     char *punct));
-
-
-/*
- * isnullstr() - is it a null string?
- */
-
-static char *
-isnullstr(s)
-	char *s;			/* string pointer */
-{
-	if (!s)
-		return((char *)NULL);
-	while (*s) {
-		if (*s != ' ')
-			return(s);
-		s++;
-	}
-	return((char *)NULL);
-}
-
-
-/*
- * print_in_col() -- print character string in help column
- */
-
-static int
-print_in_col(col, cp)
-	int col;				/* column number */
-	char *cp;				/* what to print */
-{
-	if (cp && *cp) {
-	    switch (col) {
-	    case 1:
-		(void) fprintf(stderr, "  %-23.23s", cp);
-		break;
-	    case 2:
-		(void) fprintf(stderr, "  %-25.25s", cp);
-		break;
-	    default:
-		(void) fprintf(stderr, "  %s\n", cp);
-		col = 0;
-	    }
-	    col++;
-	}
-	return(col);
-}
-
-
-/*
- * report_HASDCACHE() -- report device cache file state
- */
-
-static void
-report_HASDCACHE(type, ttl, det)
-	int type;				/* type: 0 == read path report
-						 *       1 == full report */
-	char *ttl;				/* title lines prefix
-						 * (NULL if none) */
-	char *det;				/* detail lines prefix
-						 * (NULL if none) */
-{
-
-#if	defined(HASDCACHE)
-	char *cp;
-	int dx;
-
-# if	defined(WILLDROPGID)
-	int saved_Setgid = Setgid;
-
-	Setgid = 0;
-# endif	/* defined(WILLDROPGID) */
-
-	if (type) {
-
-	/*
-	 * Report full device cache information.
-	 */
-	    (void) fprintf(stderr, "%sDevice cache file read-only paths:\n",
-		ttl ? ttl : "");
-	    if ((dx = dcpath(1, 0)) < 0)
-		(void) fprintf(stderr, "%snone\n", det ? det : "");
-	    else {
-		(void) fprintf(stderr, "%sNamed via -D: %s\n",
-		    det ? det : "",
-		    DCpath[0] ? DCpath[0] : "none");
-
-# if	defined(HASENVDC)
-		(void) fprintf(stderr,
-		    "%sNamed in environment variable %s: %s\n",
-		    det ? det : "",
-		    HASENVDC, DCpath[1] ? DCpath[1] : "none");
-# endif	/* defined(HASENVDC) */
-
-# if	defined(HASSYSDC)
-		if (DCpath[2])
-		    (void) fprintf(stderr,
-			"%sSystem-wide device cache: %s\n",
-			det ? det : "",
-			DCpath[2]);
-# endif	/* defined(HASSYSDC) */
-
-# if	defined(HASPERSDC)
-		(void) fprintf(stderr,
-		    "%sPersonal path format (HASPERSDC): \"%s\"\n",
-		    det ? det : "",
-		    HASPERSDC);
-#  if	defined(HASPERSDCPATH)
-		(void) fprintf(stderr,
-		    "%sModified personal path environment variable: %s\n",
-		    det ? det : "",
-		    HASPERSDCPATH);
-		cp = getenv(HASPERSDCPATH);
-		(void) fprintf(stderr, "%s%s value: %s\n",
-		    det ? det : "",
-		    HASPERSDCPATH, cp ? cp : "none");
-#  endif	/* defined(HASPERSDCPATH) */
-		(void) fprintf(stderr, "%sPersonal path: %s\n",
-		    det ? det : "",
-		    DCpath[3] ? DCpath[3] : "none");
-# endif	/* defined(HASPERSDC) */
-	    }
-	    (void) fprintf(stderr, "%sDevice cache file write paths:\n",
-		ttl ? ttl : "");
-	    if ((dx = dcpath(2, 0)) < 0)
-		(void) fprintf(stderr, "%snone\n", det ? det : "");
-	    else {
-		(void) fprintf(stderr, "%sNamed via -D: %s\n",
-		    det ? det : "",
-		    DCstate == 2 ? "none"
-				 : DCpath[0] ? DCpath[0] : "none");
-
-# if	defined(HASENVDC)
-		(void) fprintf(stderr,
-		    "%sNamed in environment variable %s: %s\n",
-		    det ? det : "",
-		    HASENVDC, DCpath[1] ? DCpath[1] : "none");
-# endif	/* defined(HASENVDC) */
-
-# if	defined(HASPERSDC)
-		(void) fprintf(stderr,
-		    "%sPersonal path format (HASPERSDC): \"%s\"\n",
-		    det ? det : "",
-		    HASPERSDC);
-#  if	defined(HASPERSDCPATH)
-		(void) fprintf(stderr,
-		    "%sModified personal path environment variable: %s\n",
-		    det ? det : "",
-		    HASPERSDCPATH);
-		cp = getenv(HASPERSDCPATH);
-		(void) fprintf(stderr, "%s%s value: %s\n",
-		    det ? det : "",
-		    HASPERSDCPATH, cp ? cp : "none");
-#  endif	/* defined(HASPERSDCPATH) */
-		 (void) fprintf(stderr, "%sPersonal path: %s\n",
-		    det ? det : "",
-		    DCpath[3] ? DCpath[3] : "none");
-# endif	/* defined(HASPERSDC) */
-	    }
-	} else {
-
-	/*
-	 * Report device cache read file path.
-	 */
-
-# if	defined(HASENVDC) || defined(HASPERSDC) || defined(HASSYSDC)
-	    cp = NULL;
-#  if	defined(HASENVDC)
-	    if ((dx = dcpath(1, 0)) >= 0)
-		cp = DCpath[1];
-#  endif	/* defined(HASENVDC) */
-#  if	defined(HASSYSDC)
-	    if (!cp)
-		cp = HASSYSDC;
-#  endif	/* defined(HASSYSDC) */
-#  if	defined(HASPERSDC)
-	    if (!cp && dx != -1 && (dx = dcpath(1, 0)) >= 0)
-		cp = DCpath[3];
-#  endif	/* defined(HASPERSDC) */
-	    if (cp)
-		(void) fprintf(stderr,
-		    "%s%s is the default device cache file read path.\n",
-		    ttl ? ttl : "",
-		    cp
-		);
-# endif    /* defined(HASENVDC) || defined(HASPERSDC) || defined(HASSYSDC) */
-	}
-
-# if	defined(WILLDROPGID)
-	Setgid = saved_Setgid;
-# endif	/* defined(WILLDROPGID) */
-
-#endif	/* defined(HASDCACHE) */
-
-}
-
-
-/*
- * report_HASKERNIDCK() -- report HASKERNIDCK state
- */
-
-static void
-report_HASKERNIDCK(pfx, verb)
-	char *pfx;				/* prefix (NULL if none) */
-	char *verb;				/* verb (NULL if none) */
-{
-	(void) fprintf(stderr, "%sernel ID check %s%s%s.\n",
-	    pfx ? pfx : "",
-	    verb ? verb : "",
-	    verb ? " " : "",
-
-#if	defined(HASKERNIDCK)
-		"enabled"
-#else	/* !defined(HASKERNIDCK) */
-		"disabled"
-#endif	/* defined(HASKERNIDCK) */
-
-	    );
-}
-
-
-/*
- * report_SECURITY() -- report *SECURITY states
- */
-
-static void
-report_SECURITY(pfx, punct)
-	char *pfx;				/* prefix (NULL if none) */
-	char *punct;				/* short foem punctuation
-						 * (NULL if none) */
-{
-	fprintf(stderr, "%s%s can list all files%s",
-	    pfx ? pfx : "",
-
-#if	defined(HASSECURITY)
-	    "Only root",
-# if	defined(HASNOSOCKSECURITY)
-	    ", but anyone can list socket files.\n"
-# else	/* !defined(HASNOSOCKSECURITY) */
-	    punct ? punct : ""
-# endif	/* defined(HASNOSOCKSECURITY) */
-#else	/* !defined(HASSECURITY) */
-	    "Anyone",
-	    punct ? punct : ""
-#endif	/* defined(HASSECURITY) */
-
-	);
-}
-
-
-/*
- * report_WARNDEVACCESS() -- report WEARNDEVACCESS state
- */
-
-static void
-report_WARNDEVACCESS(pfx, verb, punct)
-	char *pfx;				/* prefix (NULL if none) */
-	char *verb;				/* verb (NULL if none) */
-	char *punct;				/* punctuation */
-{
-	(void) fprintf(stderr, "%s/dev warnings %s%s%s%s",
-	    pfx ? pfx : "",
-	    verb ? verb : "",
-	    verb ? " " : "",
-
-#if	defined(WARNDEVACCESS)
-	    "enabled",
-#else	/* !defined(WARNDEVACCESS) */
-	    "disabled",
-#endif	/* defined(WARNDEVACCESS) */
-
-	    punct);
-}
-
-
-/*
- * usage() - display usage and exit
- */
-
-void
-usage(err, fh, version)
-	int err;			/* it is called as part of error handlng? */
-	int fh;				/* ``-F ?'' status */
-	int version;			/* ``-v'' status */
-{
-	char buf[MAXPATHLEN+1], *cp, *cp1, *cp2;
-	int col, i;
-
-	if (Fhelp || err) {
-	    (void) fprintf(stderr, "%s %s\n latest revision: %s\n",
-		Pn, LSOF_VERSION, LSOF_REPO_URL);
-	    (void) fprintf(stderr, " latest FAQ: %s\n", LSOF_FAQ_URL);
-	    (void) fprintf(stderr, " latest (non-formatted) man page: %s\n", LSOF_MAN_URL);
-	    (void) fprintf(stderr,
-		" usage: [-?ab%sh%slnNoOP%s%stUvV%s]",
-
-#if	defined(HASNCACHE)
-		"C",
-#else	/* !defined(HASNCACHE) */
-		"",
-#endif	/* defined(HASNCACHE) */
-
-#if	defined(HASTASKS)
-		"K",
-#else	/* !defined(HASTASKS) */
-		"",
-#endif	/* defined(HASTASKS) */
-
-#if	defined(HASPPID)
-		"R",
-#else	/* !defined(HASPPID) */
-		"",
-#endif	/* defined(HASPPID) */
-
-#if	defined(HASTCPUDPSTATE)
-		"",
-#else	/* !defined(HASTCPUDPSTATE) */
-		"s",
-#endif	/* defined(HASTCPUDPSTATE) */
-
-#if	defined(HASXOPT)
-# if	defined(HASXOPT_ROOT)
-		(Myuid == 0) ? "X" : ""
-# else	/* !defined(HASXOPT_ROOT) */
-		"X"
-# endif	/* defined(HASXOPT_ROOT) */
-#else	/* !defined(HASXOPT) */
-		""
-#endif	/* defined(HASXOPT) */
-
-	    );
-
-#if	defined(HAS_AFS) && defined(HASAOPT)
-	    (void) fprintf(stderr, " [-A A]");
-#endif	/* defined(HAS_AFS) && defined(HASAOPT) */
-
-	    (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,
-		" %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)
-		"[",
-
-# if	defined(HASNOFSCOUNT)
-		"",
-# else	/* !defined(HASNOFSCOUNT) */
-		"c",
-# endif	/* defined(HASNOFSCOUNT) */
-
-# if	defined(HASNOFSADDR)
-		"",
-# else	/* !defined(HASNOFSADDR) */
-		"f",
-# endif	/* defined(HASNOFSADDR) */
-
-# if	defined(HASNOFSFLAGS)
-		"",
-# else	/* !defined(HASNOFSFLAGS) */
-		"gG",
-# endif	/* defined(HASNOFSFLAGS) */
-
-# if	defined(HASNOFSNADDR)
-		"",
-# else	/* !defined(HASNOFSNADDR) */
-		"n",
-# endif	/* defined(HASNOFSNADDR) */
-
-		"]"
-#else	/* !defined(HASFSTRUCT) */
-		"", "", "", "", "", ""
-#endif	/* defined(HASFSTRUCT) */
-
-		);
-
-#if	defined(HASKOPT)
-	    (void) fprintf(stderr, " [-k k]");
-#endif	/* defined(HASKOPT) */
-
-	    (void) fprintf(stderr, " [+|-L [l]]");
-
-#if	defined(HASMOPT) || defined(HASMNTSUP)
-	    (void) fprintf(stderr,
-# if	defined(HASMOPT)
-#  if	defined(HASMNTSUP)
-		" [+|-m [m]]"
-#  else	/* !defined(HASMNTSUP) */
-		" [-m m]"
-#  endif	/* defined(HASMNTSUP) */
-# else	/* !defined(HASMOPT) */
-		" [+m [m]]"
-# endif	/* defined(HASMOPT) */
-		);
-#endif	/* defined(HASMOPT) || defined(HASMNTSUP) */
-
-#if	!defined(HASNORPC_H)
-	    (void) fprintf(stderr, " [+|-M]");
-#endif	/* !defined(HASNORPC_H) */
-
-	    (void) fprintf(stderr,
-		" [-o [o]] [-p s]\n [+|-r [t]]%s [-S [t]] [-T [t]]",
-
-#if	defined(HASTCPUDPSTATE)
-		" [-s [p:s]]"
-#else	/* !defined(HASTCPUDPSTATE) */
-		""
-#endif	/* defined(HASTCPUDPSTATE) */
-
-		);
-	    (void) fprintf(stderr, " [-u s] [+|-w] [-x [fl]]");
-
-#if	defined(HASZONES)
-	    (void) fprintf(stderr, " [-z [z]]");
-#else	/* !defined(HASZONES) */
-# if	defined(HASSELINUX)
-	    if (CntxStatus)
-		(void) fprintf(stderr, " [-Z [Z]]");
-# endif	/* defined(HASSELINUX) */
-#endif	/* defined(HASZONES) */
-
-	    (void) fprintf(stderr, " [--] [names]\n");
-	}
-	if (err && !Fhelp) {
-	    (void) fprintf(stderr,
-		"Use the ``-h'' option to get more help information.\n");
-	    if (!fh)
-		Exit(err? LSOF_ERROR: LSOF_SUCCESS);
-	}
-	if (Fhelp) {
-	    (void) fprintf(stderr,
-		"Defaults in parentheses; comma-separated set (s) items;");
-	    (void) fprintf(stderr, " dash-separated ranges.\n");
-	    col = print_in_col(1, "-?|-h list help");
-	    col = print_in_col(col, "-a AND selections (OR)");
-	    col = print_in_col(col, "-b avoid kernel blocks");
-	    col = print_in_col(col,  "-c c  cmd c ^c /c/[bix]");
-	    (void) snpf(buf, sizeof(buf), "+c w  COMMAND width (%d)", CMDL);
-	    col = print_in_col(col, buf);
-
-#if	defined(HASNCACHE)
-	   col = print_in_col(col, "-C no kernel name cache");
-#endif	/* defined(HASNCACHE) */
-
-	    col = print_in_col(col, "+d s  dir s files");
-	    col = print_in_col(col,  "-d s  select by FD set");
-	    col = print_in_col(col,  "+D D  dir D tree *SLOW?*");
-
-#if	defined(HASDCACHE)
-	    if (Setuidroot)
-		cp = "?|i|r";
-
-# if	!defined(WILLDROPGID)
-	    else if (Myuid)
-		cp = "?|i|r<path>";
-# endif	/* !defined(WILLDROPGID) */
-
-	    else
-		cp = "?|i|b|r|u[path]";
-	    (void) snpf(buf, sizeof(buf), "-D D  %s", cp);
-#else	/* !defined(HASDCACHE) */
-	    buf[0] = '\0';
-#endif	/* defined(HASDCACHE) */
-
-	    col = print_in_col(col, buf);
-
-#if	defined(HASEOPT)
-	    col = print_in_col(col, "+|-e s  exempt s *RISKY*");
-#endif	/* defined(HASEOPT) */
-
-	    (void) snpf(buf, sizeof(buf), "-i select IPv%s files",
-
-#if	defined(HASIPv6)
-			  "[46]"
-#else	/* !defined(HASIPv6) */
-			  "4"
-#endif	/* defined(HASIPv6) */
-
-			  );
-	    col = print_in_col(col, buf);
-
-#if	defined(HASTASKS)
-/* DEBUG	    col = print_in_col(col, "-K list tasKs (threads)");	*/
-	    col = print_in_col(col, "-K [i] list|(i)gn tasKs");
-#endif	/* defined(HASTASKS) */
-
-	    col = print_in_col(col, "-l list UID numbers");
-	    col = print_in_col(col, "-n no host names");
-	    col = print_in_col(col, "-N select NFS files");
-	    col = print_in_col(col, "-o list file offset");
-	    col = print_in_col(col, "-O no overhead *RISKY*");
-	    col = print_in_col(col, "-P no port names");
-	    col = print_in_col(col, "-Q allow failed search");
-
-#if	defined(HASPPID)
-	     col = print_in_col(col, "-R list paRent PID");
-#endif	/* defined(HASPPID) */
-
-	    col = print_in_col(col,  "-s list file size");
-	    col = print_in_col(col,  "-t terse listing");
-	    col = print_in_col(col,  "-T disable TCP/TPI info");
-	    col = print_in_col(col,  "-U select Unix socket");
-	    col = print_in_col(col,  "-v list version info");
-	    col = print_in_col(col,  "-V verbose search");
-	    (void) snpf(buf, sizeof(buf), "+|-w  Warnings (%s)",
-
-#if	defined(WARNINGSTATE)
-		"-");
-#else	/* !defined(WARNINGSTATE) */
-		"+");
-#endif	/* defined(WARNINGSTATE) */
-
-	    col = print_in_col(col, buf);
-
-#if	defined(HASXOPT)
-# if	defined(HASXOPT_ROOT)
-	    if (Myuid == 0)
-		(void) snpf(buf, sizeof(buf), "-X %s", HASXOPT);
-	    else
-		buf[0] = '\0';
-# else	/* !defined(HASXOPT_ROOT) */
-	    (void) snpf(buf, sizeof(buf), "-X %s", HASXOPT);
-# endif	/* defined(HASXOPT_ROOT) */
-# else	/* !defined(HASXOPT) */
-	    buf[0] = '\0';
-#endif	/* defined(HASXOPT) */
-
-	    col = print_in_col(col, buf);
-
-#if	defined(HASZONES)
-	    col = print_in_col(col, "-z z  zone [z]");
-#endif	/* defined(HASZONES) */
-
-#if	defined(HASSELINUX)
-	    col = print_in_col(col, "-Z Z  context [Z]");
-#endif	/* defined(HASSELINUX) */
-
-	    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");
-
-#if	defined(HASFSTRUCT)
-	    (void) fprintf(stderr,
-		"  +|-f[%s%s%s%s]%s%s%s%s %s%s%s%s%s%s%s\n",
-
-# if	defined(HASNOFSCOUNT)
-		"",
-# else	/* !defined(HASNOFSCOUNT) */
-		"c",
-# endif	/* defined(HASNOFSCOUNT) */
-
-# if	defined(HASNOFSADDR)
-		"",
-# else	/* !defined(HASNOFSADDR) */
-		"f",
-# endif	/* defined(HASNOFSADDR) */
-
-# if	defined(HASNOFSFLAGS)
-		"",
-# else	/* !defined(HASNOFSFLAGS) */
-		"gG",
-# endif	/* defined(HASNOFSFLAGS) */
-
-# if	defined(HASNOFSNADDR)
-		"",
-# else	/* !defined(HASNOFSNADDR) */
-		"n",
-# endif	/* defined(HASNOFSNADDR) */
-
-# if	defined(HASNOFSCOUNT)
-		"",
-# else	/* !defined(HASNOFSCOUNT) */
-		" Ct",
-# endif	/* defined(HASNOFSCOUNT) */
-
-# if	defined(HASNOFSADDR)
-		"",
-# else	/* !defined(HASNOFSADDR) */
-		" Fstr",
-# endif	/* defined(HASNOFSADDR) */
-
-# if	defined(HASNOFSFLAGS)
-		"",
-# else	/* !defined(HASNOFSFLAGS) */
-		" flaGs",
-# endif	/* defined(HASNOFSFLAGS) */
-
-# if	defined(HASNOFSNADDR)
-		"",
-# else	/* !defined(HASNOFSNADDR) */
-		" Node",
-# endif	/* defined(HASNOFSNADDR) */
-
-		Fsv ? "(" : "",
-		(Fsv & FSV_CT) ? "C" : "",
-		(Fsv & FSV_FA) ? "F" : "",
-		((Fsv & FSV_FG) && FsvFlagX)  ? "g" : "",
-		((Fsv & FSV_FG) && !FsvFlagX) ? "G" : "",
-		(Fsv & FSV_NI) ? "N" : "",
-		Fsv ? ")" : "");
-#else	/* !defined(HASFSTRUCT) */
-	    putc('\n', stderr);
-#endif	/* defined(HASFSTRUCT) */
-
-	    (void) fprintf(stderr, "  %-36.36s",
-		"-F [f] select fields; -F? for help");
-
-#if	defined(HASKOPT)
-	    (void) fprintf(stderr,
-		"  -k k   kernel symbols (%s)\n",
-		Nmlst ? Nmlst
-# if	defined(N_UNIX)
-		      : N_UNIX
-# else	/* !defined(N_UNIX) */
-		      : (Nmlst = get_nlist_path(1)) ? Nmlst
-						    : "none found"
-# endif	/* defined(N_UNIX) */
-
-	    );
-#else	/* !defined(HASKOPT) */
-	    putc('\n', stderr);
-#endif	/* defined(HASKOPT) */
-
-	    (void) fprintf(stderr,
-		"  +|-L [l] list (+) suppress (-) link counts < l (0 = all; default = 0)\n");
-
-#if	defined(HASMOPT) || defined(HASMNTSUP)
-# if	defined(HASMOPT)
-	    (void) snpf(buf, sizeof(buf), "-m m   kernel memory (%s)", KMEM);
-# else	/* !defined(HASMOPT) */
-	    buf[0] = '\0';
-# endif	/* defined(HASMOPT) */
-
-	    (void) fprintf(stderr, "  %-36.36s", buf);
-
-# if	defined(HASMNTSUP)
-	    (void) fprintf(stderr, "  +m [m] use|create mount supplement\n");
-# else	/* !defined(HASMNTSUP) */
-	    (void) fprintf(stderr, "\n");
-# endif	/* defined(HASMNTSUP) */
-#endif	/* defined(HASMOPT) || defined(HASMNTSUP) */
-
-#if	!defined(HASNORPC_H)
-	    (void) snpf(buf, sizeof(buf), "+|-M   portMap registration (%s)",
-
-# if	defined(HASPMAPENABLED)
-		"+"
-# else	/* !defined(HASPMAPENABLED) */
-		"-"
-# endif	/* defined(HASPMAPENABLED) */
-
-	    );
-#else	/* defined(HASNORPC_H) */
-	    buf[0] = '\0';
-#endif	/* !defined(HASNORPC_H) */
-
-	    (void) fprintf(stderr, "  %-36.36s", buf);
-	    (void) snpf(buf, sizeof(buf), "-o o   o 0t offset digits (%d)",
-		OFFDECDIG);
-	    (void) fprintf(stderr, "  %s\n", buf);
-	    (void) fprintf(stderr, "  %-36.36s",
-		"-p s   exclude(^)|select PIDs");
-	    (void) fprintf(stderr, "  -S [t] t second stat timeout (%d)\n",
-		TMLIMIT);
-	    (void) snpf(buf, sizeof(buf),
-		"-T %s%ss%s TCP/TPI %s%sSt%s (s) info",
-
-#if	defined(HASSOOPT) || defined(HASSOSTATE) || defined(HASTCPOPT)
-		"f",
-#else	/* !defined(HASSOOPT) && !defined(HASSOSTATE) && !defined(HASTCPOPT)*/
-		"",
-#endif	/* defined(HASSOOPT) || defined(HASSOSTATE) || defined(HASTCPOPT)*/
-
-#if	defined(HASTCPTPIQ)
-		"q",
-#else	/* !defined(HASTCPTPIQ) */
-		" ",
-#endif	/* defined(HASTCPTPIQ) */
-
-#if	defined(HASTCPTPIW)
-		"w",
-#else	/* !defined(HASTCPTPIW) */
-		"",
-#endif	/* defined(HASTCPTPIW) */
-
-#if	defined(HASSOOPT) || defined(HASSOSTATE) || defined(HASTCPOPT)
-		"Fl,",
-#else	/* !defined(HASSOOPT) && !defined(HASSOSTATE) && !defined(HASTCPOPT)*/
-		"",
-#endif	/* defined(HASSOOPT) || defined(HASSOSTATE) || defined(HASTCPOPT)*/
-
-#if	defined(HASTCPTPIQ)
-		"Q,",
-#else	/* !defined(HASTCPTPIQ) */
-		"",
-#endif	/* defined(HASTCPTPIQ) */
-
-#if	defined(HASTCPTPIW)
-		",Win"
-#else	/* !defined(HASTCPTPIW) */
-		""
-#endif	/* defined(HASTCPTPIW) */
-
-	    );
-	    (void) fprintf(stderr, "  %s\n", buf);
-
-#if	defined(HAS_AFS) && defined(HASAOPT)
-	    (void) fprintf(stderr,
-		"  -A A   AFS name list file (%s)\n", AFSAPATHDEF);
-#endif	/* defined(HAS_AFS) && defined(HASAOPT) */
-
-	    (void) fprintf(stderr,
-		"  -g [s] exclude(^)|select and print process group IDs\n");
-	    (void) fprintf(stderr, "  -i i   select by IPv%s address:",
-
-#if	defined(HASIPv6)
-			  "[46]"
-#else	/* !defined(HASIPv6) */
-			  "4"
-#endif	/* defined(HASIPv6) */
-
-			  );
-	    (void) fprintf(stderr,
-		" [%s][proto][@host|addr][:svc_list|port_list]\n",
-
-#if	defined(HASIPv6)
-		"46"
-#else	/* !defined(HASIPv6) */
-		"4"
-#endif	/* defined(HASIPv6) */
-
-		);
-
-	    (void) fprintf(stderr,
-		"  +|-r [%s] repeat every t seconds (%d); %s",
-
-#if	defined(HAS_STRFTIME)
-		"t[m<fmt>]",
-#else	/* !defined(has_STRFTIME) */
-		"t",
-#endif	/* defined(HAS_STRFTIME) */
-
-		RPTTM,
-		" + until no files, - forever.\n");
-
-#if	defined(HAS_STRFTIME)
-	    (void) fprintf(stderr,
-		"       An optional suffix to t is m<fmt>; m must separate %s",
-		"t from <fmt> and\n");
-	    (void) fprintf(stderr, "      <fmt> is an strftime(3) format %s",
-		"for the marker line.\n");
-#endif	/* defined(HAS_STRFTIME) */
-
-#if	defined(HASTCPUDPSTATE)
-	    (void) fprintf(stderr,
-		"  -s p:s  exclude(^)|select protocol (p = TCP|UDP) states");
-	    (void) fprintf(stderr, " by name(s).\n");
-#endif	/* defined(HASTCPUDPSTATE) */
-
-	    (void) fprintf(stderr,
-		"  -u s   exclude(^)|select login|UID set s\n");
-	    (void) fprintf(stderr,
-		"  -x [fl] cross over +d|+D File systems or symbolic Links\n");
-	    (void) fprintf(stderr,
-		"  names  select named files or files on named file systems\n");
-	    (void) report_SECURITY(NULL, "; ");
-	    (void) report_WARNDEVACCESS(NULL, NULL, ";");
-	    (void) report_HASKERNIDCK(" k", NULL);
-	    (void) report_HASDCACHE(0, NULL, NULL);
-
-#if	defined(DIALECT_WARNING)
-	    (void) fprintf(stderr, "WARNING: %s\n", DIALECT_WARNING);
-#endif	/* defined(DIALECT_WARNING) */
-
-	}
-	if (fh) {
-	    (void) fprintf(stderr, "%s:\tID    field description\n", Pn);
-	    for (i = 0; FieldSel[i].nm; i++) {
-
-#if	!defined(HASPPID)
-		if (FieldSel[i].id == LSOF_FID_PPID)
-		    continue;
-#endif	/* !defined(HASPPID) */
-
-#if	!defined(HASFSTRUCT)
-		if (FieldSel[i].id == LSOF_FID_FA
-		||  FieldSel[i].id == LSOF_FID_CT
-		||  FieldSel[i].id == LSOF_FID_FG
-		||  FieldSel[i].id == LSOF_FID_NI)
-		    continue;
-#else	/* defined(HASFSTRUCT) */
-# if	defined(HASNOFSADDR)
-		if (FieldSel[i].id == LSOF_FID_FA)
-		    continue;
-# endif	/* defined(HASNOFSADDR) */
-
-# if	defined(HASNOFSCOUNT)
-		if (FieldSel[i].id == LSOF_FID_CT)
-		    continue;
-# endif	/* !defined(HASNOFSCOUNT) */
-
-# if	defined(HASNOFSFLAGS)
-		if (FieldSel[i].id == LSOF_FID_FG)
-		    continue;
-# endif	/* defined(HASNOFSFLAGS) */
-
-# if	defined(HASNOFSNADDR)
-		if (FieldSel[i].id == LSOF_FID_NI)
-		    continue;
-# endif	/* defined(HASNOFSNADDR) */
-#endif	/* !defined(HASFSTRUCT) */
-
-#if	!defined(HASZONES)
-		if (FieldSel[i].id == LSOF_FID_ZONE)
-		    continue;
-#endif	/* !defined(HASZONES) */
-
-#if	defined(HASSELINUX)
-		if ((FieldSel[i].id == LSOF_FID_CNTX) && !CntxStatus)
-		    continue;
-#else	/* !defined(HASSELINUX) */
-		if (FieldSel[i].id == LSOF_FID_CNTX)
-		    continue;
-#endif	/* !defined(HASSELINUX) */
-
-		(void) fprintf(stderr, "\t %c    %s\n",
-		    FieldSel[i].id, FieldSel[i].nm);
-	    }
-	}
-
-#if	defined(HASDCACHE)
-	if (DChelp)
-	    report_HASDCACHE(1, NULL, "    ");
-#endif	/* defined(HASDCACHE) */
-
-	if (version) {
-
-	/*
-	 * Display version information in reponse to ``-v''.
-	 */
-	    (void) fprintf(stderr, "%s version information:\n", Pn);
-	    (void) fprintf(stderr, "    revision: %s\n", LSOF_VERSION);
-	    (void) fprintf(stderr, "    latest revision: %s\n", LSOF_REPO_URL);
-	    (void) fprintf(stderr, "    latest FAQ: %s\n",
-		LSOF_FAQ_URL);
-	    (void) fprintf(stderr, "    latest (non-formatted) man page: %s\n",
-		LSOF_MAN_URL);
-
-#if	defined(LSOF_CINFO)
-	    if ((cp = isnullstr(LSOF_CINFO)))
-		(void) fprintf(stderr, "    configuration info: %s\n", cp);
-#endif	/* defined(LSOF_CINFO) */
-
-	    cp = isnullstr(LSOF_HOST);
-	    if (!(cp1 = isnullstr(LSOF_LOGNAME)))
-		cp1 = isnullstr(LSOF_USER);
-	    if (cp || cp1) {
-		if (cp && cp1)
-		    cp2 = "by and on";
-		else if (cp)
-		    cp2 = "on";
-		else
-		    cp2 = "by";
-		(void) fprintf(stderr, "    constructed %s: %s%s%s\n",
-		    cp2,
-		    cp1 ? cp1 : "",
-		    (cp && cp1) ? "@" : "",
-		    cp  ? cp  : ""
-		);
-	    }
-
-#if	defined(LSOF_BLDCMT)
-	    if ((cp = isnullstr(LSOF_BLDCMT)))
-		(void) fprintf(stderr, "    builder's comment: %s\n", cp);
-#endif	/* defined(LSOF_BLDCMT) */
-
-	    if ((cp = isnullstr(LSOF_CC)))
-		(void) fprintf(stderr, "    compiler: %s\n", cp);
-	    if ((cp = isnullstr(LSOF_CCV)))
-		(void) fprintf(stderr, "    compiler version: %s\n", cp);
-	    if ((cp = isnullstr(LSOF_CCFLAGS)))
-		(void) fprintf(stderr, "    compiler flags: %s\n", cp);
-	    if ((cp = isnullstr(LSOF_LDFLAGS)))
-		(void) fprintf(stderr, "    loader flags: %s\n", cp);
-	    if ((cp = isnullstr(LSOF_SYSINFO)))
-		(void) fprintf(stderr, "    system info: %s\n", cp);
-	    (void) report_SECURITY("    ", ".\n");
-	    (void) report_WARNDEVACCESS("    ", "are", ".\n");
-	    (void) report_HASKERNIDCK("    K", "is");
-
-#if	defined(DIALECT_WARNING)
-	    (void) fprintf(stderr, "    WARNING: %s\n", DIALECT_WARNING);
-#endif	/* defined(DIALECT_WARNING) */
-
-	    (void) report_HASDCACHE(1, "    ", "\t");
-	}
-	Exit(err? LSOF_ERROR: LSOF_SUCCESS);
-}
diff --git a/version b/version
index e9094cb..9ad13ff 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-.ds VN 4.95.0
+.ds VN 4.99.4
diff --git a/version.in b/version.in
new file mode 100644
index 0000000..5aaf5d6
--- /dev/null
+++ b/version.in
@@ -0,0 +1 @@
+.ds VN @PACKAGE_VERSION@
\ No newline at end of file
diff --git a/zipme b/zipme
new file mode 100755
index 0000000..22fac32
--- /dev/null
+++ b/zipme
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+# zipme -- make a bzip2'd tar archive of ~/src/lsof4
+
+cd $HOME/src/lsof4
+V=$(sed '/VN/s/.ds VN \(.*\)/\1/' $HOME/src/lsof4/version)
+if test $? -ne 0
+then
+  echo $V
+  exit 1
+fi
+cd ..
+T=lsof${V}.tar.bz2
+rm -f $T
+tar cf - lsof4 | bzip2 -c > $T
+ls -l $T
-- 
GitLab